aboutsummaryrefslogtreecommitdiff
path: root/src/server/c2s_handler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/c2s_handler.c')
-rw-r--r--src/server/c2s_handler.c159
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;
+}
+