]> jxnshi.xyz Git - mesange.git/commitdiff
First commit
authorjxnshi <jxnshi@cock.li>
Tue, 24 Dec 2024 18:06:18 +0000 (19:06 +0100)
committerjxnshi <jxnshi@cock.li>
Tue, 24 Dec 2024 18:06:18 +0000 (19:06 +0100)
common/request.odin [new file with mode: 0644]
mesange-cli/main.odin [new file with mode: 0644]
mesange-cli/mesange-cli [new file with mode: 0755]
mesange-server/.gitignore [new file with mode: 0644]
mesange-server/main.odin [new file with mode: 0644]
mesange-server/mesange-server [new file with mode: 0755]

diff --git a/common/request.odin b/common/request.odin
new file mode 100644 (file)
index 0000000..b83d97f
--- /dev/null
@@ -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 (file)
index 0000000..6a9538f
--- /dev/null
@@ -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 (executable)
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 (file)
index 0000000..3389c86
--- /dev/null
@@ -0,0 +1,2 @@
+.zig-cache/
+zig-out/
diff --git a/mesange-server/main.odin b/mesange-server/main.odin
new file mode 100644 (file)
index 0000000..167392b
--- /dev/null
@@ -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 (executable)
index 0000000..05f61f9
Binary files /dev/null and b/mesange-server/mesange-server differ