From: jxnshi Date: Tue, 24 Dec 2024 18:06:18 +0000 (+0100) Subject: First commit X-Git-Url: https://jxnshi.xyz/repos?a=commitdiff_plain;h=224a2d362156c449be012cbf08125b5cf900ba24;p=mesange.git First commit --- 224a2d362156c449be012cbf08125b5cf900ba24 diff --git a/common/request.odin b/common/request.odin new file mode 100644 index 0000000..b83d97f --- /dev/null +++ b/common/request.odin @@ -0,0 +1,78 @@ +package common + +import "core:crypto/ed25519" + +Public_Key_Bytes :: [32]u8 + +Create_Room :: struct { + room_id: string, + public: bool, +} + +Create_Group :: struct { + group_name: string, + members_public_keys: []Public_Key_Bytes, +} + +Public_Message :: struct { + room_id: string, + content: string, +} + +Private_Message :: struct { + room_id: string, + content: string, +} + +Direct_Message :: struct { + receiver_public_key: ed25519.Public_Key, + encrypted_content: []u8, +} + +Group_Message :: struct { + group_id: u32, + encrypted_contents: map[Public_Key_Bytes][]u8, +} + +Block_User :: struct { + user_public_key: ed25519.Public_Key, +} + +Client_Request_Content :: union { + // Client only. + Block_User, + Create_Room, + Create_Group, + + // Common. + Public_Message, + Private_Message, + Direct_Message, + Group_Message, +} + +Client_Request :: struct { + public_key: ed25519.Public_Key, + content: Client_Request_Content, + timestamp: u32, + signature: [32]u8, +} + +client_request_parse :: proc(source: []u8) -> (Client_Request, bool) { + panic("TODO") +} + +client_request_verify :: proc(request: Client_Request, expiration: Maybe(u32)) -> bool { + panic("TODO") +} + +Server_Request :: union { + Public_Message, + Private_Message, + Direct_Message, + Group_Message, +} + +send_server_request :: proc(request: Server_Request) { + panic("TODO") +} diff --git a/mesange-cli/main.odin b/mesange-cli/main.odin new file mode 100644 index 0000000..6a9538f --- /dev/null +++ b/mesange-cli/main.odin @@ -0,0 +1,31 @@ +package main + +import "core:log" +import "core:net" + +import "../common" + +main :: proc() { + context.logger = log.create_console_logger() + defer log.destroy_console_logger(context.logger) + + server_endpoint := net.Endpoint{ + address = net.IP4_Address { 127, 0, 0, 1 }, + port = 3000, + } + + socket, err1 := net.dial_tcp(server_endpoint) + + if err1 != nil { + log.errorf("Failed to connect to server with error %v.", err1) + return + } + + defer net.close(socket) + + log.info("Connected to server.") + + for { + + } +} diff --git a/mesange-cli/mesange-cli b/mesange-cli/mesange-cli new file mode 100755 index 0000000..8d9fb48 Binary files /dev/null and b/mesange-cli/mesange-cli differ diff --git a/mesange-server/.gitignore b/mesange-server/.gitignore new file mode 100644 index 0000000..3389c86 --- /dev/null +++ b/mesange-server/.gitignore @@ -0,0 +1,2 @@ +.zig-cache/ +zig-out/ diff --git a/mesange-server/main.odin b/mesange-server/main.odin new file mode 100644 index 0000000..167392b --- /dev/null +++ b/mesange-server/main.odin @@ -0,0 +1,144 @@ +package main + +import "base:runtime" + +import "core:fmt" +import "core:log" +import "core:net" +import "core:sync" +import "core:thread" + +import "../common" + +Handle_Client_Data :: struct { + clients_sockets: ^map[net.Endpoint]net.TCP_Socket, + clients_sockets_mutex: ^sync.Mutex, + + client_socket: net.TCP_Socket, + client_endpoint: net.Endpoint, +} + +handle_client :: proc(data: Handle_Client_Data) { + using data + + client_endpoint_string := net.to_string(client_endpoint) + + defer { + log.infof("Client %v disconnected.", client_endpoint_string) + + sync.mutex_lock(clients_sockets_mutex) + defer sync.mutex_unlock(clients_sockets_mutex) + + delete_key(clients_sockets, client_endpoint) + } + + recv_buffer: [4_096]u8 + send_buffer: [4_096]u8 + + response: []u8 + + for { + bytes_read, err := net.recv(client_socket, recv_buffer[:]) + + if err != nil { + log.errorf("Failed to receive message with error %v.", err) + return + } + + if bytes_read == 0 { + break + } + + bytes := recv_buffer[:bytes_read] + + defer net.send(response) + + request, ok := common.client_request_parse(bytes) + + if !ok { + response = "Invalid request" + continue + } + + if !common.client_request_verify(request, 1 * 60 * 60 * 1_000_000_000) { + response = "Invalid authentication" + continue + } + + switch content in request.content { + + } + + fmt.printf("<%v> %v\n", client_endpoint_string, message) + } +} + +main :: proc() { + context.logger = log.create_console_logger() + defer log.destroy_console_logger(context.logger) + + server_endpoint := net.Endpoint{ + address = net.IP4_Address{ 127, 0, 0, 1 }, + port = 3000, + } + + server_socket, err1 := net.listen_tcp(server_endpoint) + + if err1 != nil { + log.errorf("Failed to open server with error %v.", err1) + return + } + + defer net.close(server_socket) + + log.infof("Server open on port %v.", server_endpoint.port) + + clients_sockets := make(map[net.Endpoint]net.TCP_Socket) + + defer { + for _, socket in clients_sockets { + net.close(socket) + } + + delete(clients_sockets) + } + + clients_sockets_mutex: sync.Mutex + + for { + client_socket, client_endpoint, err2 := net.accept_tcp(server_socket) + + if err2 != nil { + log.errorf("Failed to accept client with error %v.", err2) + continue + } + + client_endpoint_string := net.to_string(client_endpoint) + + log.infof("Accepted client from %v.", client_endpoint_string) + + { + sync.mutex_lock(&clients_sockets_mutex) + defer sync.mutex_unlock(&clients_sockets_mutex) + + clients_sockets[client_endpoint] = client_socket + } + + client_handle_data := Handle_Client_Data{ + clients_sockets = &clients_sockets, + clients_sockets_mutex = &clients_sockets_mutex, + + client_socket = client_socket, + client_endpoint = client_endpoint, + } + + client_thread := thread.create_and_start_with_poly_data( + client_handle_data, + handle_client, + runtime.Context{ + allocator = context.allocator, + logger = context.logger, + }, + ) + } +} diff --git a/mesange-server/mesange-server b/mesange-server/mesange-server new file mode 100755 index 0000000..05f61f9 Binary files /dev/null and b/mesange-server/mesange-server differ