#include "server.h" #include "network/tcp-chat-protocol/v1.h" void ClientConnection_close(ClientConnection* conn){ if(conn == NULL) return; EncryptedSocketTCP_destroy(&conn->sock); free(conn->session_key.data); free(conn); } Result(ClientConnection*) ClientConnection_accept(ServerCredentials* server_credentials, Socket sock_tcp, EndpointIPv4 client_end, u64 session_id) { Deferral(32); ClientConnection* conn = (ClientConnection*)malloc(sizeof(ClientConnection)); memset(conn, 0, sizeof(*conn)); bool success = false; Defer( if(!success) ClientConnection_close(conn); ); conn->client_end = client_end; conn->session_id = session_id; conn->session_key = Array_alloc_size(AES_SESSION_KEY_SIZE); // correct session key will be received from client later Array_memset(conn->session_key, 0); EncryptedSocketTCP_construct(&conn->sock, sock_tcp, NETWORK_BUFFER_SIZE, conn->session_key); try_void(socket_TCP_enableAliveChecks_default(sock_tcp)); // decrypt the rsa messages using server private key RSADecryptor rsa_dec; RSADecryptor_construct(&rsa_dec, &server_credentials->rsa_sk); // receive PacketHeader PacketHeader packet_header = {0}; try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &packet_header)); try_void(PacketHeader_validateMagic(&packet_header)); try_void(PacketHeader_validateType(&packet_header, PacketType_ClientHandshake)); try_void(PacketHeader_validateContentSize(&packet_header, sizeof(ClientHandshake))); // receive ClientHandshake ClientHandshake client_handshake = {0}; try_void(EncryptedSocketTCP_recvStructRSA(&conn->sock, &rsa_dec, &client_handshake)); // use received session key memcpy(conn->session_key.data, client_handshake.session_key, conn->session_key.size); EncryptedSocketTCP_changeKey(&conn->sock, conn->session_key); // send PacketHeader and ServerHandshake over encrypted TCP socket ServerHandshake server_handshake = {0}; ServerHandshake_construct(&server_handshake, &packet_header, session_id); try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &packet_header)); try_void(EncryptedSocketTCP_sendStruct(&conn->sock, &server_handshake)); success = true; Return RESULT_VALUE(p, conn); }