mirror of https://github.com/thearcanum/WIFSS
286 lines
6.6 KiB
C
Executable File
286 lines
6.6 KiB
C
Executable File
#include "commands.h"
|
|
|
|
|
|
void* command_handler(void *foo)
|
|
{
|
|
/* To get rid of '-Wextra' "Unused variable" warning */
|
|
(void)foo;
|
|
|
|
char buffer[BUFFER];
|
|
char *args[BUFFER];
|
|
int16_t nbArgs = -1;
|
|
|
|
while(true)
|
|
{
|
|
command_cursor();
|
|
prompt_keyboard(buffer);
|
|
free_args(args, &nbArgs);
|
|
parse_command(buffer, args, &nbArgs);
|
|
|
|
// In order to avoid a segmentation fault if 'args' is empty...
|
|
if(nbArgs == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if(command_validation((const char* const*)args, nbArgs, EXIT, 1))
|
|
{
|
|
broadcast(SID, "[Server] is going to shutdown !");
|
|
pthread_exit(NULL);
|
|
}
|
|
|
|
else if(str_beginwith(buffer, SEND) && nbArgs >= 3)
|
|
{
|
|
char cpy[BUFFER] = "";
|
|
char buffTemp[BUFFER] = "";
|
|
strncat(cpy, get_second_args_group(buffer), BUFFER);
|
|
snprintf(buffTemp, BUFFER, "[Server] says: \"%s\".", cpy);
|
|
broadcast(SID, buffTemp);
|
|
}
|
|
|
|
else if(str_beginwith(buffer, WHISPER) && nbArgs >= 3)
|
|
{
|
|
char cpy[BUFFER] = "";
|
|
char buffTemp[BUFFER] = "";
|
|
|
|
int16_t idTemp = get_second_args_group_as_integer(buffer);
|
|
strncpy(cpy, get_third_arg_group(buffer), BUFFER);
|
|
|
|
if(idTemp >= 0 && core_variables.clients[idTemp].status == TAKEN && idTemp < MAX_CLIENTS)
|
|
{
|
|
snprintf(buffTemp, BUFFER, "[Server] whispers to you: \"%s\".", cpy);
|
|
SSL_write(core_variables.clients[idTemp].ssl, buffTemp, BUFFER);
|
|
}
|
|
|
|
else
|
|
{
|
|
printf("\n\033[35m[WIFSS] This client identifier is invalid.\033[0m\n\n");
|
|
}
|
|
}
|
|
|
|
else if(command_validation((const char* const*)args, nbArgs, DISCONNECT, 2))
|
|
{
|
|
disconnect(buffer);
|
|
}
|
|
|
|
else if(command_validation((const char* const*)args, nbArgs, CLEAR, 1))
|
|
{
|
|
clear_console();
|
|
}
|
|
|
|
else if(command_validation((const char* const*)args, nbArgs, WHO, 1))
|
|
{
|
|
who(SID);
|
|
}
|
|
|
|
else if(command_validation((const char* const*)args, nbArgs, HELP, 1))
|
|
{
|
|
static const char *helpMenu[32] =
|
|
{
|
|
"help",
|
|
"who",
|
|
"send <message>",
|
|
"whisper <idClient> <message>",
|
|
"disconnect <idClient> ['-1' for all]",
|
|
"exit",
|
|
"clear",
|
|
""
|
|
};
|
|
|
|
for(uint8_t j = 0; helpMenu[j] != NULL; j++)
|
|
{
|
|
printf("\t%s\n", helpMenu[j]);
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
printf("\n\033[35mUnknown command. Try \"help\" for further information.\033[0m\n\n");
|
|
}
|
|
}
|
|
|
|
close_server();
|
|
}
|
|
|
|
|
|
void process_command(const char *command, const uint8_t sender_id)
|
|
{
|
|
if(str_beginwith(command, WHO))
|
|
{
|
|
who(sender_id);
|
|
}
|
|
|
|
else if(str_beginwith(command, SEND))
|
|
{
|
|
message(command, sender_id);
|
|
}
|
|
|
|
else if(str_beginwith(command, WHISPER))
|
|
{
|
|
whisper(command, sender_id);
|
|
}
|
|
|
|
else
|
|
{
|
|
printf("\n\n\033[35m[WIFSS] Unknown command from [Client %d]: \"%s\".\033[0m\n\n", sender_id, command);
|
|
}
|
|
|
|
command_cursor();
|
|
}
|
|
|
|
|
|
void* connections_handler(void *foo)
|
|
{
|
|
/* In order to deal with '-Wextra' "Unused variable" warning */
|
|
(void)foo;
|
|
|
|
struct sockaddr_in6 client;
|
|
uint32_t asize = sizeof(client);
|
|
|
|
int8_t sock;
|
|
uint8_t count = 0;
|
|
while(true)
|
|
{
|
|
sock = accept(core_variables.server_sock, (struct sockaddr*)&client, &asize);
|
|
if(sock == -1)
|
|
{
|
|
printf("\033[31m[WIFSS] Error during a connection acceptation: %s.\033[0m\n\n", strerror(errno));
|
|
continue;
|
|
}
|
|
|
|
char host[1024] = "";
|
|
char service[32] = "";
|
|
|
|
if(getnameinfo((struct sockaddr*)&client, sizeof(client), host, sizeof(host), service, sizeof(service), 0) != 0)
|
|
{
|
|
printf("\033[31m[WIFSS] An error occurred while retrieving some information about : %s.\033[0m\n\n", strerror(errno));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
if(count >= MAX_CLIENTS)
|
|
{
|
|
printf("\n\n\033[35m[WIFSS] Maximum capacity reached, can\'t accept a new client yet... (%s [%s])\033[0m\n\n", host, service);
|
|
|
|
const char *const local = "\n\033[35m[Server] Maximum capacity reached, please try again later !\033[0m\n";
|
|
send(sock, local, strlen(local), false);
|
|
|
|
close(sock);
|
|
command_cursor();
|
|
continue;
|
|
}
|
|
|
|
else
|
|
{
|
|
// Whereas the connection has been accepted, just send a packet in order to synchronize the `select` call...
|
|
send(sock, CLIENT_SERVER_SYNC, strlen(CLIENT_SERVER_SYNC), false);
|
|
}
|
|
|
|
// Enables SSL !
|
|
SSL *ssl = SSL_new(core_variables.ctx);
|
|
SSL_set_fd(ssl, sock);
|
|
|
|
if(SSL_accept(ssl) <= 0)
|
|
{
|
|
ERR_print_errors_fp(stderr);
|
|
printf("\n\n\033[35m[WIFSS] Can\'t accept the SSL connection with the client \'%s [%s]\'\033[0m\n\n", host, service);
|
|
close(sock);
|
|
command_cursor();
|
|
continue;
|
|
}
|
|
|
|
uint8_t current_id = -1;
|
|
for(uint8_t i = 0; i < MAX_CLIENTS; i++)
|
|
{
|
|
if(core_variables.clients[i].status == FREE)
|
|
{
|
|
current_id = i;
|
|
core_variables.clients[i].status = TAKEN;
|
|
break;
|
|
}
|
|
}
|
|
|
|
printf("\n\n\033[35m[WIFSS] Connection received \'%s [%s]\' -> ID given: %d.\033[0m\n", host, service, current_id);
|
|
|
|
Client new_client;
|
|
new_client.id = current_id;
|
|
new_client.addr = client;
|
|
new_client.sock = sock;
|
|
new_client.status = TAKEN;
|
|
new_client.ssl = ssl;
|
|
|
|
core_variables.clients[current_id] = new_client;
|
|
|
|
int16_t res = pthread_create(&core_variables.threads[current_id], NULL, &on_connection, (void*)&new_client);
|
|
if(res != 0)
|
|
{
|
|
printf("\033[31m[WIFSS] Error during thread creation %d: Error (%d).\033[0m\n\n", current_id, res);
|
|
broadcast(SID, "Server fatal error, stopping now.\n");
|
|
close_all_connections();
|
|
pthread_exit(NULL);
|
|
}
|
|
|
|
/* Let's count the number of clients online */
|
|
count = 0;
|
|
for(uint8_t i = 0; i < MAX_CLIENTS; i++)
|
|
{
|
|
if(core_variables.clients[i].status == TAKEN)
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
|
|
printf("\033[35m[WIFSS] There is %d client%s connected.\033[0m\n\n", count, (count > 1 ? "s" : ""));
|
|
|
|
command_cursor();
|
|
}
|
|
}
|
|
|
|
|
|
void* on_connection(void *data)
|
|
{
|
|
Client client = *((Client*)data);
|
|
|
|
char buffer[BUFFER] = "";
|
|
|
|
snprintf(buffer, BUFFER, "[Client %d] is connected.", client.id);
|
|
broadcast(client.id, buffer);
|
|
|
|
strncpy(buffer, "", BUFFER);
|
|
snprintf(buffer, BUFFER, "id: %d", client.id);
|
|
SSL_write(client.ssl, buffer, BUFFER);
|
|
|
|
do
|
|
{
|
|
strncpy(buffer, "", BUFFER);
|
|
|
|
if(SSL_read(client.ssl, buffer, BUFFER) <= 0)
|
|
{
|
|
fprintf(stderr, "\n\n\033[35m[WIFSS] [Client %d]\'s socket has been closed. He\'ll be disconnected from now.\033[0m\n\n", client.id);
|
|
break; /* Client is offline */
|
|
}
|
|
|
|
process_command(buffer, client.id);
|
|
|
|
} while(true);
|
|
|
|
strncpy(buffer, "", BUFFER);
|
|
snprintf(buffer, BUFFER, "[Client %d] is disconnected.", client.id);
|
|
broadcast(client.id, buffer);
|
|
|
|
SSL_free(client.ssl);
|
|
|
|
if(close(client.sock) == -1)
|
|
{
|
|
printf("\033[35m[WIFSS] Warning: couldn\'t close the [Client %d]\'s socket (already closed ?): %s.\033[0m\n\n", client.id, strerror(errno));
|
|
}
|
|
|
|
command_cursor();
|
|
|
|
core_variables.clients[client.id].status = FREE;
|
|
core_variables.clients[client.id].id = -1;
|
|
core_variables.clients[client.id].sock = -1;
|
|
core_variables.clients[client.id].ssl = NULL;
|
|
|
|
return NULL;
|
|
}
|