diff options
Diffstat (limited to 'src/server/c2s_handler.c')
-rw-r--r-- | src/server/c2s_handler.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/server/c2s_handler.c b/src/server/c2s_handler.c new file mode 100644 index 0000000..4406aa7 --- /dev/null +++ b/src/server/c2s_handler.c @@ -0,0 +1,159 @@ +#include <basic/basic.h> +#include <messages/messages.h> +#include <server/client_connections.h> +#include <server/c2s_handler.h> +#include <server/s2c_sender.h> + + +internal_fn void +handle_c2s_chat_message(ClientConnections *conns, ClientConnection *conn) +{ + // Todo: verify package size + C2S_ChatMessage *chat_message = (C2S_ChatMessage*)conn->recv_buff; + chat_message->content = (void*)chat_message + (size_t)chat_message->content; + + Time now = os_time_get_now(); + + // Todo: make proper groups + for (size_t i = 0; i < conns->max_connection_count; i++) { + ClientConnection *connection = conns->connections + i; + if (connection->username->len > 0) { + send_s2c_chat_message(connection, conn->username, chat_message->content, now); + } + } +} + + +internal_fn void +handle_c2s_login(ClientConnections *conns, ClientConnection *conn) +{ + // init package + C2S_Login *login = (C2S_Login*)conn->recv_buff; + login->username = (void*)login + (size_t)login->username; + login->password = (void*)login + (size_t)login->password; + + + // verify package + if (login->username->len <= 0) { + printf("handle_c2s_login error: username len %d is invalid\n", login->username->len); + } + if (login->username->len > MESSAGES_MAX_USERNAME_LEN) { + printf("handle_c2s_login error: username len %d/%d\n", login->username->len, MESSAGES_MAX_USERNAME_LEN); + return; // Todo: rm connection + } + if (login->username->len > MESSAGES_MAX_PASSWORD_LEN) { + printf("handle_c2s_login error: password len %d/%d\n", login->password->len, MESSAGES_MAX_PASSWORD_LEN); + return; // Todo: rm connection + } + size_t message_size = sizeof(C2S_Login) + 2*sizeof(String32) + sizeof(u32) * (login->username->len + login->password->len); + if (message_size != conn->recv_buff_size_used) { + printf("handle_c2s_login error: message size is %zu/%d\n", message_size, conn->recv_buff_size_used); + return; // Todo: rm connection + } + + + // temporary check if username already connected (use a hashmap for this) + b32 login_success = true; + for (size_t i = 0; i < conns->max_connection_count; i++) { + ClientConnection *connection = conns->connections + i; + if (string32_equal(connection->username, login->username)) { + login_success = false; + break; + } + } + + + // login + for (size_t i = 0; i < login->username->len; i++) { + conn->username->codepoints[i] = login->username->codepoints[i]; + } + conn->username->len = login->username->len; + + + if (!login_success) { + send_s2c_login(conn, S2C_LOGIN_ERROR); + } + + + send_s2c_login(conn, S2C_LOGIN_SUCCESS); + + // send everyone else's user update to conn + // Todo: make proper groups + for (size_t i = 0; i < conns->max_connection_count; i++) { + ClientConnection *connection = conns->connections + i; + if (string32_equal(connection->username, conn->username)) { + continue; + } + if (connection->username->len > 0) { + send_s2c_user_update(conn, connection->username, S2C_USER_UPDATE_ONLINE); + } + } + + // send conn's user update to everyone else + // Todo: make proper groups + for (size_t i = 0; i < conns->max_connection_count; i++) { + ClientConnection *connection = conns->connections + i; + if (connection->username->len > 0) { + send_s2c_user_update(connection, conn->username, S2C_USER_UPDATE_ONLINE); + } + } + + // Todo: make function string32_printf + printf("<"); + string32_print(conn->username);; + printf("> connected to the server\n"); +} + + +b32 +handle_c2s(ClientConnections *conns, ClientConnection *conn) +{ + // recv header + if (conn->recv_buff_size_used < sizeof(MessageHeader)) { + size_t size_to_recv = sizeof(MessageHeader) - conn->recv_buff_size_used; + i64 size_recvd = os_net_secure_stream_recv(conn->secure_stream_id, conn->recv_buff + conn->recv_buff_size_used, size_to_recv); + if (size_recvd < 0) { + return false; + } + else if (size_recvd == 0) { + return false; + } + + conn->recv_buff_size_used += size_recvd; + if (conn->recv_buff_size_used < sizeof(MessageHeader)) { + return true; + } + } + + + // recv body + MessageHeader *header = (MessageHeader*)conn->recv_buff; + if (conn->recv_buff_size_used < header->size) { + size_t size_to_recv = header->size - conn->recv_buff_size_used; + i64 size_recvd = os_net_secure_stream_recv(conn->secure_stream_id, conn->recv_buff + conn->recv_buff_size_used, size_to_recv); + if (size_recvd < 0) { + return false; + } + else if (size_recvd == 0) { + return false; + } + + conn->recv_buff_size_used += size_recvd; + if (conn->recv_buff_size_used < header->size) { + return true; + } + } + + + // dispatch + switch (header->type) { + case C2S_LOGIN: handle_c2s_login(conns, conn); break; + case C2S_CHAT_MESSAGE: handle_c2s_chat_message(conns, conn); break; + } + + + // cleanup + conn->recv_buff_size_used = 0; + return true; +} + |