2023-02-21 07:59:09 +01:00
/*
This is part of WHY2
Copyright ( C ) 2022 Václav Š mejkal
This program is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < https : //www.gnu.org/licenses/>.
*/
2023-02-21 07:58:12 +01:00
# include <why2/chat/misc.h>
2023-03-12 14:59:07 +01:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2024-01-27 18:40:12 +01:00
# include <ctype.h>
2023-03-12 14:59:07 +01:00
# include <sys/socket.h>
2023-02-21 10:53:09 +01:00
# include <unistd.h>
2023-02-21 07:58:12 +01:00
2023-03-12 14:59:07 +01:00
# include <pthread.h>
2023-02-21 19:34:40 +01:00
2023-03-24 19:43:48 +01:00
# include <json-c/json.h>
2023-05-02 18:55:21 +02:00
# include <why2/chat/config.h>
2023-03-12 15:02:06 +01:00
# include <why2/chat/flags.h>
2023-08-27 12:19:30 +02:00
2023-04-18 21:10:42 +02:00
# include <why2/llist.h>
2023-02-21 07:58:12 +01:00
# include <why2/memory.h>
2023-04-01 13:36:08 +02:00
# include <why2/misc.h>
2023-02-21 07:58:12 +01:00
2024-01-20 15:48:22 +01:00
pthread_t getline_thread ;
2023-04-19 14:33:39 +02:00
//LINKED LIST STUFF
typedef struct _connection_node
2023-02-21 12:29:45 +01:00
{
int connection ;
2023-02-22 10:09:58 +01:00
pthread_t thread ;
2024-01-27 18:07:48 +01:00
char * username ;
2023-04-19 14:33:39 +02:00
} connection_node_t ; //SINGLE LINKED LIST
2023-02-21 12:29:45 +01:00
2023-04-19 14:33:39 +02:00
why2_list_t connection_list = WHY2_LIST_EMPTY ;
2023-04-18 21:10:42 +02:00
why2_list_t waiting_list = WHY2_LIST_EMPTY ;
2023-02-21 12:29:45 +01:00
2023-03-25 17:39:52 +01:00
char * get_string_from_json ( struct json_object * json , char * string )
{
struct json_object * object ;
json_object_object_get_ex ( json , string , & object ) ;
return ( char * ) json_object_get_string ( object ) ;
}
char * get_string_from_json_string ( char * json , char * string )
{
struct json_object * json_obj = json_tokener_parse ( json ) ;
char * returning = get_string_from_json ( json_obj , string ) ;
//DEALLOCATION
json_object_put ( json_obj ) ;
//GET STRINGS
return returning ;
}
void * send_to_all ( void * json )
2023-02-22 12:07:26 +01:00
{
2023-04-20 09:28:39 +02:00
why2_node_t _first_node = ( why2_node_t ) { NULL , connection_list . head } ;
why2_node_t * node_buffer = & _first_node ;
2023-04-19 14:33:39 +02:00
connection_node_t connection_buffer ;
2023-02-22 12:07:26 +01:00
2023-03-25 17:39:52 +01:00
//PARSE
struct json_object * json_obj = json_tokener_parse ( ( char * ) json ) ;
2023-04-20 09:49:16 +02:00
char * message = get_string_from_json ( json_obj , " message " ) ;
char * username = get_string_from_json ( json_obj , " username " ) ;
2023-03-25 17:39:52 +01:00
2023-03-31 18:12:56 +02:00
if ( json_obj = = NULL ) return NULL ; //EXIT IF INVALID SYNTAX WAS SENT
2023-03-31 17:50:40 +02:00
2023-04-19 14:33:39 +02:00
while ( node_buffer - > next ! = NULL ) //SEND TO ALL CONNECTIONS
2023-02-22 12:07:26 +01:00
{
2023-04-20 09:28:39 +02:00
node_buffer = node_buffer - > next ;
2023-04-19 14:33:39 +02:00
connection_buffer = * ( connection_node_t * ) node_buffer - > value ;
2023-04-20 09:49:16 +02:00
why2_send_socket ( message , username , connection_buffer . connection ) ; //SEND TO CLIENT
2023-04-19 14:33:39 +02:00
}
2023-02-22 12:07:26 +01:00
2023-03-25 17:39:52 +01:00
//DEALLOCATION
json_object_put ( json_obj ) ;
2023-02-22 12:07:26 +01:00
return NULL ;
}
2023-03-24 19:43:48 +01:00
void append ( char * * destination , char * key , char * value )
{
char * output = why2_calloc ( strlen ( * destination ) + strlen ( key ) + strlen ( value ) + 7 , sizeof ( char ) ) ;
sprintf ( output , " %s%s \" %s \" : \" %s \" " , * destination , strcmp ( * destination , " " ) = = 0 ? " " : " , " , key , value ) ;
why2_deallocate ( * destination ) ;
* destination = output ;
}
void add_brackets ( char * * json )
{
char * output = why2_calloc ( strlen ( * json ) + 3 , sizeof ( char ) ) ;
2024-01-27 22:10:32 +01:00
sprintf ( output , " {%s}%c " , * json , ' \0 ' ) ;
2023-03-24 19:43:48 +01:00
why2_deallocate ( * json ) ;
* json = output ;
}
2023-03-25 16:35:44 +01:00
char * read_socket_raw ( int socket )
{
if ( socket = = - 1 )
{
fprintf ( stderr , " Reading socket failed. \n " ) ;
return NULL ;
}
unsigned short content_size = 0 ;
char * content_buffer = why2_calloc ( 3 , sizeof ( char ) ) ;
//GET LENGTH
if ( recv ( socket , content_buffer , 2 , 0 ) ! = 2 )
{
fprintf ( stderr , " Getting message length failed! \n " ) ;
return NULL ;
}
content_size = ( unsigned short ) ( ( ( unsigned ) content_buffer [ 1 ] < < 8 ) | content_buffer [ 0 ] ) ;
why2_deallocate ( content_buffer ) ;
//ALLOCATE
content_buffer = why2_calloc ( content_size + 1 , sizeof ( char ) ) ;
//READ JSON MESSAGE
if ( recv ( socket , content_buffer , content_size , 0 ) ! = content_size - 2 ) fprintf ( stderr , " Socket probably read wrongly! \n " ) ;
content_buffer [ content_size - 2 ] = ' \0 ' ; //TODO: Possible problems
return content_buffer ;
}
2023-04-05 10:16:53 +02:00
void * read_socket_raw_thread ( void * socket )
{
return read_socket_raw ( * ( int * ) socket ) ;
}
2023-03-25 16:35:44 +01:00
char * read_socket_from_raw ( char * raw )
{
char * final_message ;
struct json_object * json_obj = json_tokener_parse ( raw ) ;
2023-03-31 18:09:35 +02:00
if ( json_obj = = NULL ) return " ERR " ; //RETURN IF INVALID SYNTAX WAS SENT BY SOME FUCKING SCRIPT KIDDIE
2023-03-25 16:35:44 +01:00
//GET STRINGS
2023-05-02 19:11:08 +02:00
char * message = get_string_from_json ( json_obj , " message " ) ;
2023-03-25 16:35:44 +01:00
char * username = get_string_from_json ( json_obj , " username " ) ;
//ALLOCATE final_message
final_message = why2_calloc ( strlen ( message ) + strlen ( username ) + 3 , sizeof ( char ) ) ;
//BUILD final_message
sprintf ( final_message , " %s: %s " , username , message ) ;
//DEALLOCATION
json_object_put ( json_obj ) ;
return final_message ;
2023-03-24 20:45:16 +01:00
}
2023-03-31 17:47:05 +02:00
void remove_json_syntax_characters ( char * text )
{
for ( size_t i = 0 ; i < strlen ( text ) ; i + + ) //TODO: DO SOMETHING MORE
{
if ( text [ i ] = = ' \" ' )
{
text [ i ] = ' \' ' ;
}
}
}
2024-01-27 18:40:12 +01:00
void lowercase ( char * string )
{
for ( unsigned long i = 0 ; i < strlen ( string ) ; i + + )
{
string [ i ] = tolower ( string [ i ] ) ;
}
}
why2_bool username_equal ( char * u1 , char * u2 )
{
char * one = why2_strdup ( u1 ) ;
char * two = why2_strdup ( u2 ) ;
//LOWERCASE
lowercase ( one ) ;
lowercase ( two ) ;
return strcmp ( one , two ) = = 0 ;
}
2024-01-27 17:44:39 +01:00
why2_bool check_username ( char * username )
{
2024-01-27 18:40:12 +01:00
if ( username_equal ( username , WHY2_CHAT_SERVER_USERNAME ) ) return 0 ; //DISABLE 'server' USERNAME
if ( username_equal ( username , WHY2_DEFAULT_USERNAME ) ) return 0 ; //DISABLE 'anon' USERNAME DUE TO ONE USERNAME PER SERVER
2024-01-27 17:44:39 +01:00
for ( unsigned long i = 0 ; i < strlen ( username ) ; i + + )
{
if ( ! ( ( username [ i ] > = 48 & & username [ i ] < = 57 ) | |
( username [ i ] > = 65 & & username [ i ] < = 90 ) | | //CHECK ONLY FOR a-Z & 0-9
( username [ i ] > = 97 & & username [ i ] < = 122 ) ) )
{
return 0 ;
}
}
return 1 ;
}
2023-04-12 08:02:11 +02:00
void * stop_oldest_thread ( void * id )
2023-04-05 10:16:53 +02:00
{
2023-04-12 08:02:11 +02:00
sleep ( WHY2_COMMUNICATION_TIME ) ; //yk wait
2023-04-18 21:10:42 +02:00
if ( waiting_list . head = = NULL ) return NULL ;
2023-04-19 11:09:26 +02:00
if ( * * ( pthread_t * * ) waiting_list . head - > value = = * ( pthread_t * ) id ) //THREAD IS STILL ALIVE, I HOPE
2023-04-12 08:02:11 +02:00
{
//KILL THE THREAD
2023-04-18 21:10:42 +02:00
pthread_cancel ( * ( pthread_t * ) id ) ;
why2_list_remove ( & waiting_list , why2_list_find ( & waiting_list , id ) ) ;
2023-04-12 08:02:11 +02:00
}
return NULL ;
2023-04-05 10:16:53 +02:00
}
2023-04-18 21:08:18 +02:00
why2_node_t * find_request ( void * thread ) / / COPIED FROM why2_list_find ; using double pointers
{
why2_node_t * head = waiting_list . head ;
if ( head = = NULL ) return NULL ; //EMPTY LIST
why2_node_t * buffer = head ;
while ( buffer - > next ! = NULL )
{
if ( * ( void * * ) buffer - > value = = thread ) return buffer ;
buffer = buffer - > next ;
}
if ( thread ! = * ( void * * ) buffer - > value ) buffer = NULL ; //PREVENT FROM RETURNING INVALID NODE
return buffer ;
}
2023-04-19 14:33:39 +02:00
why2_node_t * find_connection ( int connection )
{
why2_node_t * head = connection_list . head ;
if ( head = = NULL ) return NULL ; //EMPTY LIST
why2_node_t * buffer = head ;
while ( buffer - > next ! = NULL )
{
if ( ( * ( connection_node_t * ) buffer - > value ) . connection = = connection ) return buffer ;
buffer = buffer - > next ;
}
if ( connection ! = ( * ( connection_node_t * ) buffer - > value ) . connection ) buffer = NULL ; //PREVENT FROM RETURNING INVALID NODE
return buffer ;
}
2024-01-27 14:57:19 +01:00
char * read_user ( int connection , void * * raw_ptr )
{
//VARIABLES
void * buffer ;
pthread_t thread_buffer ;
pthread_t thread_deletion_buffer ;
//RESET VARIABLES
* raw_ptr = NULL ;
buffer = & thread_buffer ;
//READ
pthread_create ( & thread_buffer , NULL , read_socket_raw_thread , & connection ) ;
why2_list_push ( & waiting_list , & buffer , sizeof ( buffer ) ) ;
//RUN DELETION THREAD
pthread_create ( & thread_deletion_buffer , NULL , stop_oldest_thread , & thread_buffer ) ;
//WAIT FOR MESSAGE
pthread_join ( thread_buffer , raw_ptr ) ;
why2_list_remove ( & waiting_list , find_request ( & thread_buffer ) ) ;
pthread_cancel ( thread_deletion_buffer ) ;
if ( * raw_ptr = = WHY2_INVALID_POINTER | | * raw_ptr = = NULL ) return NULL ; //QUIT COMMUNICATION IF INVALID PACKET WAS RECEIVED
return ( char * ) * raw_ptr ;
}
2024-01-28 13:17:04 +01:00
char * get_username ( int connection )
{
why2_node_t * node = find_connection ( connection ) ;
connection_node_t c_node = * ( connection_node_t * ) node - > value ;
return c_node . username ;
}
2023-02-21 12:29:45 +01:00
//GLOBAL
2023-03-25 17:39:52 +01:00
void why2_send_socket ( char * text , char * username , int socket )
2023-02-21 07:58:12 +01:00
{
2023-03-24 19:43:48 +01:00
char * output = why2_strdup ( " " ) ;
size_t length_buffer = strlen ( text ) ;
2023-04-20 21:42:53 +02:00
char * text_copy = why2_calloc ( length_buffer + 2 , sizeof ( char ) ) ;
2023-03-24 19:43:48 +01:00
struct json_object * json = json_tokener_parse ( " {} " ) ;
2023-03-25 17:50:19 +01:00
//COPY text INTO text_copy (WITHOUT LAST CHARACTER WHEN NEWLINE IS AT THE END)
2023-03-31 17:47:05 +02:00
if ( text [ length_buffer - 1 ] = = ' \n ' ) length_buffer - - ;
2023-03-25 17:50:19 +01:00
strncpy ( text_copy , text , length_buffer ) ;
2023-03-24 19:43:48 +01:00
2023-03-31 17:47:05 +02:00
//UNFUCK QUOTES FROM text_copy
remove_json_syntax_characters ( text_copy ) ;
2023-03-24 19:43:48 +01:00
//ADD OBJECTS
json_object_object_add ( json , " message " , json_object_new_string ( text_copy ) ) ;
2024-01-28 13:17:04 +01:00
if ( username ! = NULL ) json_object_object_add ( json , " username " , json_object_new_string ( username ) ) ; //WAS SENT FROM SERVER
2023-03-24 19:43:48 +01:00
//GENERATE JSON STRING
json_object_object_foreach ( json , key , value )
{
append ( & output , key , ( char * ) json_object_get_string ( value ) ) ;
}
add_brackets ( & output ) ;
why2_deallocate ( text_copy ) ;
json_object_put ( json ) ;
unsigned short text_length = ( unsigned short ) strlen ( output ) + 2 ;
2023-02-21 19:19:47 +01:00
char * final = why2_calloc ( text_length , sizeof ( char ) ) ;
2023-02-21 07:58:12 +01:00
//SPLIT LENGTH INTO TWO CHARS
final [ 0 ] = ( unsigned ) text_length & 0xff ;
final [ 1 ] = ( unsigned ) text_length > > 8 ;
2023-02-21 19:19:47 +01:00
for ( int i = 2 ; i < text_length ; i + + ) //APPEND
2023-02-21 07:58:12 +01:00
{
2023-03-24 19:43:48 +01:00
final [ i ] = output [ i - 2 ] ;
2023-02-21 07:58:12 +01:00
}
//SEND
2023-02-21 19:48:28 +01:00
send ( socket , final , text_length , 0 ) ;
2023-02-21 07:58:12 +01:00
2023-03-24 19:43:48 +01:00
//DEALLOCATION
2023-02-21 07:58:12 +01:00
why2_deallocate ( final ) ;
2023-03-24 19:43:48 +01:00
why2_deallocate ( output ) ;
2023-02-21 10:53:09 +01:00
}
2023-02-21 12:33:33 +01:00
void * why2_communicate_thread ( void * arg )
2023-02-21 10:53:09 +01:00
{
2023-04-01 12:43:49 +02:00
int connection = * ( int * ) arg ;
2023-02-22 10:09:58 +01:00
2023-04-20 09:45:39 +02:00
printf ( " User connected. \t \t %d \n " , connection ) ;
2023-02-21 18:59:44 +01:00
2023-08-27 12:19:30 +02:00
//GET USERNAME
char * string_buffer = why2_replace ( WHY2_CHAT_CONFIG_DIR " / " WHY2_CHAT_CONFIG_SERVER , " {USER} " , getenv ( " USER " ) ) ;
2024-01-24 12:17:45 +01:00
char * config_username = why2_toml_read ( string_buffer , " user_pick_username " ) ;
2023-08-27 12:19:30 +02:00
2024-01-27 17:47:05 +01:00
char * raw ;
void * raw_ptr = NULL ;
why2_bool force_exiting = 0 ;
2024-01-27 22:13:02 +01:00
why2_bool invalid_username = 1 ;
2024-01-27 17:47:05 +01:00
why2_bool exiting = 0 ;
char * decoded_buffer = NULL ;
2024-01-28 13:17:04 +01:00
char * username = why2_strdup ( WHY2_DEFAULT_USERNAME ) ;
2024-01-27 22:13:02 +01:00
int usernames_n = 0 ;
2024-01-28 13:17:04 +01:00
struct json_object * json = json_tokener_parse ( " {} " ) ;
2024-01-27 17:47:05 +01:00
why2_deallocate ( string_buffer ) ;
2023-08-27 12:19:30 +02:00
if ( config_username = = NULL | | strcmp ( config_username , " true " ) = = 0 )
{
2024-01-27 22:22:36 +01:00
if ( usernames_n + + = = WHY2_MAX_USERNAME_TRIES ) //ASKED CLIENT WAY TOO FUCKING MANY TIMES FOR USERNAME, KICK HIM
{
exiting = 1 ;
goto deallocation ;
}
2023-08-27 12:19:30 +02:00
if ( config_username = = NULL ) fprintf ( stderr , " Your config doesn't contain 'user_pick_username'. Please update your configuration. \n " ) ;
2024-01-27 22:13:02 +01:00
while ( invalid_username )
{
why2_send_socket ( WHY2_CHAT_CODE_PICK_USERNAME , WHY2_CHAT_SERVER_USERNAME , connection ) ; //ASK USER FOR USERNAME
2024-01-27 17:47:05 +01:00
2024-01-27 22:13:02 +01:00
if ( ( raw = read_user ( connection , & raw_ptr ) ) = = NULL ) //READ
{
force_exiting = 1 ; //FAILURE
goto deallocation ;
}
2024-01-27 17:47:05 +01:00
2024-01-27 22:13:02 +01:00
decoded_buffer = get_string_from_json_string ( raw , " message " ) ; //DECODE
2024-01-27 17:47:05 +01:00
2024-01-27 22:19:38 +01:00
invalid_username = ( strlen ( decoded_buffer ) > WHY2_MAX_USERNAME_LENGTH ) | | ( strlen ( decoded_buffer ) < WHY2_MIN_USERNAME_LENGTH ) | | ( ! check_username ( decoded_buffer ) ) ; //CHECK FOR USERNAMES LONGER THAN 20 CHARACTERS
2024-01-27 17:47:05 +01:00
2024-01-27 22:13:02 +01:00
why2_deallocate ( username ) ;
username = decoded_buffer ;
2024-01-27 17:47:05 +01:00
2024-01-27 22:13:02 +01:00
//DEALLOCATE STUFF HERE
why2_deallocate ( raw ) ;
why2_deallocate ( raw_ptr ) ;
2024-01-27 17:47:05 +01:00
2024-01-27 22:13:02 +01:00
if ( invalid_username )
{
why2_send_socket ( WHY2_CHAT_CODE_INVALID_USERNAME , WHY2_CHAT_SERVER_USERNAME , connection ) ; //TELL THE USER HE IS DUMB AS FUCK
}
2024-01-28 13:39:03 +01:00
printf ( " User set username. \t %d \t %s \n " , connection , decoded_buffer ) ;
2024-01-27 17:47:05 +01:00
}
2023-08-27 12:19:30 +02:00
}
2024-01-24 12:17:45 +01:00
why2_toml_read_free ( config_username ) ;
2023-05-02 18:55:21 +02:00
2024-01-28 13:17:04 +01:00
connection_node_t node = ( connection_node_t )
{
connection ,
pthread_self ( ) ,
strdup ( username )
} ;
why2_list_push ( & connection_list , & node , sizeof ( node ) ) ; //ADD TO LIST
2024-01-27 17:47:05 +01:00
raw = why2_strdup ( " " ) ;
2024-01-28 13:17:04 +01:00
char * raw_output ;
2023-02-22 12:07:26 +01:00
pthread_t thread_buffer ;
2024-01-27 17:47:05 +01:00
char * connection_message = why2_malloc ( strlen ( username ) + 11 ) ;
//BUILD connection_message
sprintf ( connection_message , " %s connected " , username ) ;
2023-04-20 09:28:39 +02:00
//SEND CONNECTION MESSAGE
2024-01-27 17:47:05 +01:00
json_object_object_add ( json , " message " , json_object_new_string ( connection_message ) ) ;
json_object_object_add ( json , " username " , json_object_new_string ( WHY2_CHAT_SERVER_USERNAME ) ) ;
2023-04-20 09:28:39 +02:00
json_object_object_foreach ( json , key , value ) //GENERATE JSON STRING
{
append ( & raw , key , ( char * ) json_object_get_string ( value ) ) ;
}
add_brackets ( & raw ) ;
2024-01-28 13:17:04 +01:00
json_object_put ( json ) ;
2023-04-20 09:28:39 +02:00
pthread_create ( & thread_buffer , NULL , send_to_all , raw ) ; //SEND
pthread_join ( thread_buffer , NULL ) ;
why2_deallocate ( raw ) ;
2024-01-27 17:47:05 +01:00
why2_deallocate ( connection_message ) ;
2024-01-28 13:17:04 +01:00
why2_deallocate ( username ) ;
2023-02-21 10:53:09 +01:00
2024-01-27 17:47:05 +01:00
while ( ! ( exiting | | force_exiting ) ) //KEEP COMMUNICATION ALIVE FOR 5 MINUTES [RESET TIMER AT MESSAGE SENT]
2023-02-21 10:53:09 +01:00
{
2024-01-27 14:57:19 +01:00
if ( ( raw = read_user ( connection , & raw_ptr ) ) = = NULL ) break ; //READ
2024-01-28 13:17:04 +01:00
json = json_tokener_parse ( " {} " ) ;
raw_output = why2_strdup ( " " ) ;
2023-03-31 18:36:09 +02:00
2023-03-31 18:21:06 +02:00
//REMOVE CONTROL CHARACTERS FROM raw
for ( size_t i = 0 ; i < strlen ( raw ) ; i + + )
{
if ( raw [ i ] = = ' \\ ' ) raw [ i ] = ' / ' ;
}
2023-03-25 16:37:58 +01:00
decoded_buffer = get_string_from_json_string ( raw , " message " ) ; //DECODE
if ( decoded_buffer [ 0 ] = = ' ! ' ) //COMMANDS
2023-02-23 09:05:16 +01:00
{
2024-01-27 15:36:09 +01:00
if ( strcmp ( decoded_buffer , " !exit " ) = = 0 ) //USER REQUESTED EXIT
{
exiting = 1 ;
} else
{
why2_send_socket ( WHY2_CHAT_CODE_INVALID_COMMAND , WHY2_CHAT_SERVER_USERNAME , connection ) ;
}
2023-02-23 09:05:16 +01:00
2023-04-01 13:36:08 +02:00
goto deallocation ; //IGNORE MESSAGES BEGINNING WITH '!'
2023-02-23 09:05:16 +01:00
}
2023-02-21 10:53:09 +01:00
2024-01-28 13:17:04 +01:00
//REBUILD MESSAGE WITH USERNAME
json_object_object_add ( json , " message " , json_object_new_string ( decoded_buffer ) ) ;
json_object_object_add ( json , " username " , json_object_new_string ( get_username ( connection ) ) ) ;
json_object_object_foreach ( json , key , value ) //GENERATE JSON STRING
{
append ( & raw_output , key , ( char * ) json_object_get_string ( value ) ) ;
}
add_brackets ( & raw_output ) ;
pthread_create ( & thread_buffer , NULL , send_to_all , raw_output ) ;
2023-02-22 14:37:18 +01:00
pthread_join ( thread_buffer , NULL ) ;
2023-02-22 12:07:26 +01:00
2023-04-01 13:36:08 +02:00
deallocation :
2023-03-25 16:37:58 +01:00
why2_deallocate ( raw ) ;
2023-04-05 10:16:53 +02:00
why2_deallocate ( raw_ptr ) ;
2024-01-28 13:17:04 +01:00
why2_deallocate ( raw_output ) ;
2023-03-25 16:37:58 +01:00
why2_deallocate ( decoded_buffer ) ;
2024-01-28 13:17:04 +01:00
json_object_put ( json ) ;
2023-02-21 10:53:09 +01:00
}
2024-01-24 18:29:02 +01:00
if ( exiting ) why2_send_socket ( WHY2_CHAT_CODE_SSQC , WHY2_CHAT_SERVER_USERNAME , connection ) ;
2024-01-20 15:48:22 +01:00
2023-04-20 09:45:39 +02:00
printf ( " User disconnected. \t %d \n " , connection ) ;
2023-02-21 10:53:09 +01:00
//DEALLOCATION
2023-04-01 12:43:49 +02:00
close ( connection ) ;
2024-01-27 18:07:48 +01:00
why2_deallocate ( node . username ) ;
2023-04-19 14:33:39 +02:00
why2_list_remove ( & connection_list , find_connection ( connection ) ) ;
2023-02-21 10:53:09 +01:00
2024-01-20 15:48:22 +01:00
return NULL ;
2023-02-21 10:53:09 +01:00
}
2023-02-21 12:33:33 +01:00
char * why2_read_socket ( int socket )
2023-02-21 10:53:09 +01:00
{
2023-03-25 16:37:42 +01:00
char * raw_socket = read_socket_raw ( socket ) ;
2023-03-24 20:01:15 +01:00
char * final_message ;
2023-03-25 16:37:42 +01:00
struct json_object * json_obj = json_tokener_parse ( raw_socket ) ;
2023-03-24 20:01:15 +01:00
//GET STRINGS
2023-05-02 19:11:08 +02:00
char * message = get_string_from_json ( json_obj , " message " ) ;
2023-03-24 20:45:16 +01:00
char * username = get_string_from_json ( json_obj , " username " ) ;
2023-03-24 20:01:15 +01:00
2023-03-25 16:37:42 +01:00
//ALLOCATE final_message
2023-03-24 20:01:15 +01:00
final_message = why2_calloc ( strlen ( message ) + strlen ( username ) + 3 , sizeof ( char ) ) ;
//BUILD final_message
sprintf ( final_message , " %s: %s " , username , message ) ;
//DEALLOCATION
2023-03-25 16:37:42 +01:00
why2_deallocate ( raw_socket ) ;
2023-03-24 20:01:15 +01:00
json_object_put ( json_obj ) ;
return final_message ;
2023-02-21 10:53:09 +01:00
}
2023-02-21 12:31:27 +01:00
2023-02-21 19:34:40 +01:00
void * why2_accept_thread ( void * socket )
{
int accepted ;
pthread_t thread ;
//LOOP ACCEPT
for ( ; ; )
{
2023-04-05 14:24:40 +02:00
accepted = accept ( * ( ( int * ) socket ) , ( WHY2_SA * ) NULL , NULL ) ; //ACCEPT NEW SOCKET
2023-02-21 19:34:40 +01:00
if ( accepted = = - 1 ) continue ;
2023-04-01 12:43:49 +02:00
pthread_create ( & thread , NULL , why2_communicate_thread , & accepted ) ;
2023-02-21 19:34:40 +01:00
}
2023-04-20 09:42:20 +02:00
return NULL ;
2023-02-22 10:16:01 +01:00
}
2024-01-21 13:44:31 +01:00
void why2_clean_connections ( void )
2023-02-22 10:16:01 +01:00
{
2024-01-21 13:44:31 +01:00
why2_node_t * head = connection_list . head ;
if ( head = = NULL ) return ; //EMPTY LIST
2023-04-19 14:33:39 +02:00
2024-01-21 13:44:31 +01:00
why2_node_t * node_buffer = head ;
why2_node_t * node_buffer_2 ;
2023-04-19 14:33:39 +02:00
connection_node_t connection_buffer ;
2023-02-22 10:16:01 +01:00
2024-01-20 20:13:58 +01:00
do //GO TROUGH LIST
2023-02-22 10:16:01 +01:00
{
2024-01-21 13:44:31 +01:00
node_buffer_2 = node_buffer ;
node_buffer = node_buffer - > next ;
2023-02-22 10:16:01 +01:00
2024-01-24 13:28:09 +01:00
connection_buffer = * ( connection_node_t * ) node_buffer_2 - > value ;
2024-01-20 20:13:58 +01:00
why2_send_socket ( WHY2_CHAT_CODE_SSQC , WHY2_CHAT_SERVER_USERNAME , connection_buffer . connection ) ;
2023-04-19 14:33:39 +02:00
close ( connection_buffer . connection ) ;
2024-01-21 13:44:31 +01:00
why2_list_remove ( & connection_list , node_buffer_2 ) ; //REMOVE
} while ( node_buffer ! = NULL ) ;
}
void why2_clean_threads ( void )
{
why2_node_t * head = waiting_list . head ;
if ( head = = NULL ) return ; //EMPTY LIST
why2_node_t * node_buffer = head ;
why2_node_t * node_buffer_2 ;
do //GO TROUGH LIST
{
node_buffer_2 = node_buffer ;
node_buffer = node_buffer - > next ;
2023-02-22 10:19:36 +01:00
2024-01-21 13:44:31 +01:00
pthread_cancel ( * * ( pthread_t * * ) ( node_buffer_2 - > value ) ) ;
why2_list_remove ( & waiting_list , node_buffer_2 ) ; //REMOVE
} while ( node_buffer ! = NULL ) ;
2023-02-22 12:12:04 +01:00
}
void * why2_listen_server ( void * socket )
{
2023-02-24 16:31:20 +01:00
char * read = NULL ;
2024-01-20 15:48:22 +01:00
why2_bool exiting = 0 ;
2023-02-24 16:31:20 +01:00
2023-04-05 10:21:47 +02:00
printf ( " >>> " ) ;
2023-02-24 16:31:20 +01:00
fflush ( stdout ) ;
2024-01-27 17:43:59 +01:00
while ( ! exiting )
2023-02-22 12:12:04 +01:00
{
2023-04-05 10:21:47 +02:00
read = why2_read_socket ( * ( ( int * ) socket ) ) ;
2023-05-02 19:08:43 +02:00
2023-08-27 11:56:23 +02:00
if ( strncmp ( read , WHY2_CHAT_SERVER_USERNAME " : code " , 12 ) = = 0 ) //CODE WAS SENT
2023-05-02 19:08:43 +02:00
{
2024-01-20 15:48:22 +01:00
if ( strcmp ( read + 8 , WHY2_CHAT_CODE_SSQC ) = = 0 )
{
printf ( " %s \n Server closed the connection. \n " , WHY2_CLEAR_AND_GO_UP ) ;
fflush ( stdout ) ;
pthread_cancel ( getline_thread ) ; //CANCEL CLIENT getline
exiting = 1 ; //EXIT THIS THREAD
} else if ( strcmp ( read + 8 , WHY2_CHAT_CODE_PICK_USERNAME ) = = 0 ) //PICK USERNAME
2023-05-02 19:08:43 +02:00
{
2024-01-27 22:19:38 +01:00
printf ( " %sEnter username (a-Z, 0-9; %d-%d characters): \n " , WHY2_CLEAR_AND_GO_UP , WHY2_MAX_USERNAME_LENGTH , WHY2_MAX_USERNAME_LENGTH ) ;
2024-01-27 17:46:45 +01:00
fflush ( stdout ) ;
goto continue_input ;
2024-01-27 15:36:09 +01:00
} else if ( strcmp ( read + 8 , WHY2_CHAT_CODE_INVALID_COMMAND ) = = 0 ) //PICK USERNAME
{
printf ( " \n Invalid command! \n \n " ) ;
fflush ( stdout ) ;
2024-01-27 17:46:45 +01:00
goto continue_input ;
} else if ( strcmp ( read + 8 , WHY2_CHAT_CODE_INVALID_USERNAME ) = = 0 ) //PICK USERNAME
{
printf ( " \n Invalid username! \n \n \n " ) ;
fflush ( stdout ) ;
2024-01-27 15:36:09 +01:00
goto continue_input ;
2023-05-02 19:08:43 +02:00
}
} else
{
2024-01-27 18:21:50 +01:00
printf ( WHY2_CLEAR_AND_GO_UP WHY2_CLEAR_AND_GO_UP ) ; //do not fucking ask me how the fucking formatting fucking works, i dont fucking know
printf ( " \n \n %s%s \n \n " , WHY2_CLEAR_AND_GO_UP , read ) ;
2024-01-27 15:36:09 +01:00
continue_input :
printf ( " >>> " ) ;
2023-05-02 19:08:43 +02:00
fflush ( stdout ) ;
}
2023-02-24 16:31:20 +01:00
why2_deallocate ( read ) ;
2023-02-22 12:12:04 +01:00
}
2023-05-02 19:08:43 +02:00
return NULL ;
2024-01-20 15:48:22 +01:00
}
void * why2_getline_thread ( WHY2_UNUSED void * arg )
{
getline_thread = pthread_self ( ) ;
char * line = NULL ;
size_t line_length = 0 ;
if ( getline ( & line , & line_length , stdin ) = = - 1 ) why2_die ( " Reading input failed. " ) ;
return line ;
2023-05-02 19:11:08 +02:00
}