]> jxnshi.xyz Git - mesange.git/commitdiff
Update
authorjxnshi <jxnshi@proton.me>
Fri, 31 Jan 2025 14:02:52 +0000 (15:02 +0100)
committerjxnshi <jxnshi@proton.me>
Fri, 31 Jan 2025 14:02:52 +0000 (15:02 +0100)
client-cli/client-cli
client-cli/command.odin
client-cli/host.odin [new file with mode: 0644]
client-cli/main.odin
client-cli/state.odin
common/request.odin
server/client.odin [new file with mode: 0644]
server/main.odin
server/server

index 324f2293480c95f3eb9247c7ddc9e5b9e6fca3e4..4a7a161a94f53ad56dc49905380b2e3a9ca49b61 100755 (executable)
Binary files a/client-cli/client-cli and b/client-cli/client-cli differ
index a8b467333b6c2ab050089002d56e4ebdb126860a..9382e8de12b64ae2fd0b8c9c9de885736186c050 100644 (file)
@@ -3,6 +3,7 @@ package main
 import "core:encoding/base64"
 import "core:log"
 import "core:math/rand"
+import "core:net"
 import "core:os"
 import "core:slice"
 import "core:strings"
@@ -107,7 +108,7 @@ handle_command :: proc(app: ^App, command: string) -> Maybe(Handle_Command_Error
                 room_id = room_get_id(&room),
             }
 
-            err := common.request_server(app.host.?, request, &app.profile.private_key)
+            err := request_host(app.host.?, request, &app.profile.private_key)
 
             if err != nil {
                 app_set_info_bar(app, "Could not subscribe to room.")
@@ -141,13 +142,19 @@ handle_command :: proc(app: ^App, command: string) -> Maybe(Handle_Command_Error
                 room_id = room_get_id(&room),
             }
 
-            err := common.request_server(app.host.?, request, &app.profile.private_key)
+            err := request_host(app.host.?, request, &app.profile.private_key)
 
             if err != nil {
                 app_set_info_bar(app, "Could not subscribe to room.")
                 return .Command_Failed
             }
 
+            buffer: [1_000]u8
+            bytes_read, _ := net.recv_tcp(app.host.?, buffer[:])
+            response := transmute(string)buffer[:bytes_read]
+
+            log.infof("Response %v", response)
+
             app_add_room(app, room)
             app_set_info_bar(app, "Room generated.")
 
@@ -189,13 +196,19 @@ handle_command :: proc(app: ^App, command: string) -> Maybe(Handle_Command_Error
                 room_id = room_get_id(room),
             }
 
-            err := common.request_server(app.host.?, request, &app.profile.private_key)
+            err := request_host(app.host.?, request, &app.profile.private_key)
 
             if err != nil {
                 app_set_info_bar(app, "Could not subscribe to room.")
                 return .Command_Failed
             }
 
+            buffer: [1_000]u8
+            bytes_read, _ := net.recv_tcp(app.host.?, buffer[:])
+            response := transmute(string)buffer[:bytes_read]
+
+            log.infof("Response %v", response)
+
             app_remove_room(app, app.selected_room)
             app_set_info_bar(app, "Room removed.")
 
diff --git a/client-cli/host.odin b/client-cli/host.odin
new file mode 100644 (file)
index 0000000..5a745fd
--- /dev/null
@@ -0,0 +1,53 @@
+package main
+
+import "core:bytes"
+import "core:crypto/ed25519"
+import "core:encoding/endian"
+import "core:io"
+import "core:net"
+import "core:slice"
+import "core:time"
+
+import "../common"
+
+request_host :: proc(host: net.TCP_Socket, inner: common.Client_Request_Inner, private_key: ^ed25519.Private_Key) -> (id: u32, err: Error) {
+    client_request: Client_Request
+    ed25519.public_key_set_priv(&client_request.public_key, private_key)
+    client_request.inner = inner
+    client_request.timestamp = time.time_to_unix_nano(time.now())
+    client_request.signature = client_request_signature(client_request, private_key)
+
+    bytes_buf: [10_000]u8
+    bytes_buffer: bytes.Buffer
+    bytes_buffer.buf = slice.into_dynamic(bytes_buf[:])
+    request_stream := bytes.buffer_to_stream(&bytes_buffer)
+
+    // Request ID.
+    id_bytes: [size_of(u32)]u8
+    _ = rand.read(id_bytes[:])
+
+    id, _ = endian.get_u32(id_bytes[:], .Little)
+
+    _, _ = io.write(request_stream, id_bytes[:])
+
+    // Request.
+    _ = client_request_to_bytes(request_stream, request)
+
+    // Length.
+    buffer_length := bytes.buffer_length(&bytes_buffer)
+
+    len_bytes: [size_of(32)]u8
+    endian.put_u32(len_bytes[:], .Little, u32(buffer_length))
+
+    _, _ = io.write_at(request_stream, len_bytes[:], 0)
+
+    request_bytes := bytes.buffer_to_bytes(&bytes_buffer)
+
+    _ = net.send_tcp(server, request_bytes) or_return
+
+    return id, nil
+}
+
+receive_host :: proc(host: net.TCP_Socket) -> Message {
+       
+}
index 8846d4b253d1043ed727564de04024c86127f7ce..839e2fd12fa516ae6a69b8cbd7abf8cb2895d200 100644 (file)
@@ -21,6 +21,8 @@ import fpath "core:path/filepath"
 
 import nc "../ncurses"
 
+import "../common"
+
 COLOR_FIRST :: 16
 COLOR_SECOND :: 17
 COLOR_THIRD :: 18
@@ -60,6 +62,7 @@ App :: struct {
     seed_phrase_checksum: u8,
 
     host: Maybe(net.TCP_Socket),
+    waiting_respones: [dynamic]common.Server_Response,
 
     selected_room: int,
 }
@@ -109,6 +112,8 @@ app_init :: proc(storage_path: string) -> App {
 
         info_bar = info_bar,
         input_window = input_window,
+
+        waiting_responses = make([dynamic]common.Server_Response),
     }
 
     app_update_info_bar(&app)
@@ -122,6 +127,8 @@ app_deinit :: proc(app: ^App) {
     sync.mutex_lock(&app.mutex)
     defer sync.mutex_unlock(&app.mutex)
 
+    delete(app.waiting_responses)
+
     if host, ok := app.host.?; ok {
         net.close(host)
     }
index 39cf6a6e9074acef23340fc6ac33c2fb2f004fd5..a351d1232e03a329821434ab2466dad2323103a4 100644 (file)
@@ -538,15 +538,18 @@ state_room :: proc(app: ^App) {
         iv: [chacha.IV_SIZE]u8
         _ = rand.read(iv[:])
 
+        message: [common.MESSAGE_SIZE]u8
+        mem.copy_non_overlapping(raw_data(message[:]), raw_data(input), common.MESSAGE_SIZE)
+
         chacha_context: chacha.Context
         chacha.init(&chacha_context, selected_room.key[:], iv[:])
 
-        message: [common.MESSAGE_SIZE]u8
-        chacha.xor_bytes(&chacha_context, message[:], transmute([]u8)input)
+        encrypted_message: [common.MESSAGE_SIZE]u8
+        chacha.xor_bytes(&chacha_context, encrypted_message[:], message[:])
 
         request := common.Write_Request {
             room_id = room_get_id(selected_room),
-            message = message
+            encrypted_message = encrypted_message,
         }
 
         err := common.request_server(app.host.?, request, &app.profile.private_key)
index d89b806292aa8daf032bf1abc1b6982e755eaa78..844fef1f6d180d9b2150a7993b233e2db6f74a1d 100644 (file)
@@ -7,20 +7,25 @@ import "core:encoding/endian"
 import "core:io"
 import "core:log"
 import "core:net"
+import "core:math/rand"
 import "core:mem"
+import "core:slice"
 import "core:time"
 
 ROOM_KEY_SIZE :: 32
 MESSAGE_SIZE :: 1_000 * 4
 
-Request_Validity_Error :: enum {
-    Invalid_Inner_Kind,
-    Invalid_Public_Key,
+Receive_Packet_Error :: enum {
+    Packet_Too_Large,
 }
 
-From_Bytes_Error :: union {
-    Request_Validity_Error,
-    io.Error,
+Receive_Request_Error :: enum {
+    Invalid_Request,
+}
+
+Client_Request_From_Bytes_Error :: enum {
+    Invalid_Inner_Kind,
+    Invalid_Public_Key,
 }
 
 Request_Verify_Error :: enum {
@@ -28,30 +33,42 @@ Request_Verify_Error :: enum {
     Invalid_Signature,
 }
 
+Error :: union {
+    Receive_Packet_Error,
+    Receive_Request_Error,
+
+    Client_Request_From_Bytes_Error,
+
+    Request_Verify_Error,
+
+    io.Error,
+    net.Network_Error,
+}
+
 Write_Request :: struct {
     room_id: [sha3.DIGEST_SIZE_256]u8,
-    message: [MESSAGE_SIZE]u8,
+    encrypted_message: [MESSAGE_SIZE]u8,
 }
 
-write_request_from_bytes :: proc(stream: io.Stream) -> (request: Write_Request, err: From_Bytes_Error) {
+write_request_from_bytes :: proc(stream: io.Stream) -> (request: Write_Request, err: Error) {
     room_id: [sha3.DIGEST_SIZE_256]u8
     _ = io.read(stream, room_id[:]) or_return
 
-    message: [MESSAGE_SIZE]u8
-    _ = io.read(stream, message[:]) or_return
+    encrypted_message: [MESSAGE_SIZE]u8
+    _ = io.read(stream, encrypted_message[:]) or_return
 
     return {
         room_id = room_id,
-        message = message,
+        encrypted_message = encrypted_message,
     },
         nil
 }
 
-write_request_to_bytes :: proc(stream: io.Stream, request: Write_Request) -> io.Error {
+write_request_to_bytes :: proc(stream: io.Stream, request: Write_Request) -> Error {
     request := request
 
     _ = io.write(stream, request.room_id[:]) or_return
-    _ = io.write(stream, request.message[:]) or_return
+    _ = io.write(stream, request.encrypted_message[:]) or_return
 
     return nil
 }
@@ -60,7 +77,7 @@ Subscribe_Request :: struct {
     room_id: [sha3.DIGEST_SIZE_256]u8,
 }
 
-subscribe_request_from_bytes :: proc(stream: io.Stream) -> (request: Subscribe_Request, err: From_Bytes_Error) {
+subscribe_request_from_bytes :: proc(stream: io.Stream) -> (request: Subscribe_Request, err: Error) {
     room_id: [sha3.DIGEST_SIZE_256]u8
     _ = io.read(stream, room_id[:]) or_return
 
@@ -70,7 +87,7 @@ subscribe_request_from_bytes :: proc(stream: io.Stream) -> (request: Subscribe_R
         nil
 }
 
-subscribe_request_to_bytes :: proc(stream: io.Stream, request: Subscribe_Request) -> io.Error {
+subscribe_request_to_bytes :: proc(stream: io.Stream, request: Subscribe_Request) -> Error {
     request := request
     _ = io.write(stream, request.room_id[:]) or_return
 
@@ -81,7 +98,7 @@ Unsubscribe_Request :: struct {
     room_id: [sha3.DIGEST_SIZE_256]u8,
 }
 
-unsubscribe_request_from_bytes :: proc(stream: io.Stream) -> (request: Unsubscribe_Request, err: From_Bytes_Error) {
+unsubscribe_request_from_bytes :: proc(stream: io.Stream) -> (request: Unsubscribe_Request, err: Error) {
     room_id: [sha3.DIGEST_SIZE_256]u8
     _ = io.write(stream, request.room_id[:]) or_return
 
@@ -91,7 +108,7 @@ unsubscribe_request_from_bytes :: proc(stream: io.Stream) -> (request: Unsubscri
         nil
 }
 
-unsubscribe_request_to_bytes :: proc(stream: io.Stream, request: Unsubscribe_Request) -> io.Error {
+unsubscribe_request_to_bytes :: proc(stream: io.Stream, request: Unsubscribe_Request) -> Error {
     request := request
     _ = io.write(stream, request.room_id[:]) or_return
 
@@ -105,7 +122,7 @@ Client_Request_Inner :: union {
     Unsubscribe_Request,
 }
 
-client_request_inner_from_bytes :: proc(stream: io.Stream) -> (request: Client_Request_Inner, err: From_Bytes_Error) {
+client_request_inner_from_bytes :: proc(stream: io.Stream) -> (request: Client_Request_Inner, err: Error) {
     kind, err1 := io.read_byte(stream)
     if err1 != nil do return {}, err1
 
@@ -115,13 +132,13 @@ client_request_inner_from_bytes :: proc(stream: io.Stream) -> (request: Client_R
     case 0: inner = write_request_from_bytes(stream) or_return
     case 1: inner = subscribe_request_from_bytes(stream) or_return
     case 2: inner = unsubscribe_request_from_bytes(stream) or_return
-    case: return {}, Request_Validity_Error.Invalid_Inner_Kind
+    case: return {}, Client_Request_From_Bytes_Error.Invalid_Inner_Kind
     }
 
     return inner, nil
 }
 
-client_request_inner_to_bytes :: proc(stream: io.Stream, inner: Client_Request_Inner) -> io.Error {
+client_request_inner_to_bytes :: proc(stream: io.Stream, inner: Client_Request_Inner) -> Error {
     switch i in inner {
     case Write_Request:
         io.write_byte(stream, 2) or_return
@@ -146,7 +163,7 @@ Client_Request :: struct {
     signature: [ed25519.SIGNATURE_SIZE]u8,
 }
 
-client_request_from_bytes :: proc(input: []u8) -> (request: Client_Request, err: From_Bytes_Error) {
+client_request_from_bytes :: proc(input: []u8) -> (request: Client_Request, err: Error) {
     input := input
 
     bytes_buffer := bytes.Buffer{ buf = mem.buffer_from_slice(input) }
@@ -179,7 +196,7 @@ client_request_from_bytes :: proc(input: []u8) -> (request: Client_Request, err:
         nil
 }
 
-client_request_to_bytes_signatureless :: proc(stream: io.Stream, request: Client_Request) -> io.Error {
+client_request_to_bytes_signatureless :: proc(stream: io.Stream, request: Client_Request) -> Error {
     request := request
 
     public_key_bytes: [ed25519.PUBLIC_KEY_SIZE]u8
@@ -195,7 +212,7 @@ client_request_to_bytes_signatureless :: proc(stream: io.Stream, request: Client
     return nil
 }
 
-client_request_to_bytes :: proc(stream: io.Stream, request: Client_Request) -> io.Error {
+client_request_to_bytes :: proc(stream: io.Stream, request: Client_Request) -> Error {
     request := request
 
     client_request_to_bytes_signatureless(stream, request) or_return
@@ -207,7 +224,7 @@ client_request_to_bytes :: proc(stream: io.Stream, request: Client_Request) -> i
 client_request_signature :: proc(request: Client_Request, private_key: ^ed25519.Private_Key) -> [ed25519.SIGNATURE_SIZE]u8 {
     bytes_buf: [10_000]u8
     bytes_buffer: bytes.Buffer
-    bytes.buffer_init(&bytes_buffer, bytes_buf[:])
+    bytes_buffer.buf = slice.into_dynamic(bytes_buf[:])
     request_stream := bytes.buffer_to_stream(&bytes_buffer)
 
     _ = client_request_to_bytes_signatureless(request_stream, request)
@@ -220,7 +237,7 @@ client_request_signature :: proc(request: Client_Request, private_key: ^ed25519.
     return signature
 }
 
-client_request_verify :: proc(request: Client_Request, expiration: Maybe(i64)) -> Maybe(Request_Verify_Error) {
+client_request_verify :: proc(request: Client_Request, expiration: Maybe(i64)) -> Error {
     request := request
 
     now := time.time_to_unix_nano(time.now())
@@ -233,7 +250,7 @@ client_request_verify :: proc(request: Client_Request, expiration: Maybe(i64)) -
 
     bytes_buf: [10_000]u8
     bytes_buffer: bytes.Buffer
-    bytes.buffer_init(&bytes_buffer, bytes_buf[:])
+    bytes_buffer.buf = slice.into_dynamic(bytes_buf[:])
     request_stream := bytes.buffer_to_stream(&bytes_buffer)
 
     _ = client_request_to_bytes_signatureless(request_stream, request)
@@ -241,54 +258,10 @@ client_request_verify :: proc(request: Client_Request, expiration: Maybe(i64)) -
     request_bytes := bytes.buffer_to_bytes(&bytes_buffer)
 
     if !ed25519.verify(&request.public_key, request_bytes, request.signature[:]) {
-        return .Invalid_Signature
+        return Request_Verify_Error.Invalid_Signature
     }
 
     return nil
 }
 
-send_client_request :: proc(server: net.TCP_Socket, request: Client_Request, private_key: ^ed25519.Private_Key) -> net.Network_Error {
-    bytes_buf: [10_000]u8
-    bytes_buffer: bytes.Buffer
-    bytes.buffer_init(&bytes_buffer, bytes_buf[:])
-    request_stream := bytes.buffer_to_stream(&bytes_buffer)
-
-    _ = client_request_to_bytes(request_stream, request)
-
-    buffer_length := bytes.buffer_length(&bytes_buffer)
-
-    len_bytes: [size_of(32)]u8
-    endian.put_u32(len_bytes[:], .Little, u32(buffer_length))
-
-    request_bytes := bytes.buffer_to_bytes(&bytes_buffer)
-
-    log.infof("Preview %v", request_bytes[:1_000])
-
-    _, _ = io.write_at(request_stream, len_bytes[:], 0)
-
-    request_bytes = bytes.buffer_to_bytes(&bytes_buffer)
-
-    log.infof("Preview %v", request_bytes[:1_000])
-
-    _ = net.send_tcp(server, request_bytes) or_return
-
-    return nil
-}
-
-request_server :: proc(server: net.TCP_Socket, inner: Client_Request_Inner, private_key: ^ed25519.Private_Key) -> net.Network_Error {
-    client_request: Client_Request
-    ed25519.public_key_set_priv(&client_request.public_key, private_key)
-    client_request.inner = inner
-    client_request.timestamp = time.time_to_unix_nano(time.now())
-    client_request.signature = client_request_signature(client_request, private_key)
-
-    send_client_request(server, client_request, private_key) or_return
-
-    return nil
-}
-
 Server_Request :: union {}
-
-send_server_request :: proc(request: Server_Request) {
-    panic("TODO")
-}
diff --git a/server/client.odin b/server/client.odin
new file mode 100644 (file)
index 0000000..d3c52e3
--- /dev/null
@@ -0,0 +1,77 @@
+package main
+
+import "core:bytes"
+import "core:encoding/endian"
+import "core:io"
+import "core:net"
+import "core:slice"
+
+import "../common"
+
+receive_request :: proc(client: net.TCP_Socket) -> (id: u32, request: common.Client_Request, err: common.Error) {
+    length_bytes: [size_of(u32)]u8
+    _ = net.recv_tcp(client, length_bytes[:]) or_return
+
+    length, _ := endian.get_u32(length_bytes[:], .Little)
+
+    if length == 0 {
+        return 0, {}, nil
+    }
+
+    buffer: [10_000]u8
+
+    if int(length) > len(buffer) {
+        // Empty the socket buffer.
+        for _ in 0..<length {
+            _ = net.recv_tcp(client, buffer[:]) or_return
+        }
+
+        return 0, {}, common.Receive_Packet_Error.Packet_Too_Large
+    }
+
+    _ = net.recv_tcp(client, buffer[:length]) or_return
+
+    id_bytes := buffer[:size_of(u32)]
+    id, _ = endian.get_u32(id_bytes[:], .Little)
+
+    request_bytes := buffer[size_of(u32):]
+
+    request, err = common.client_request_from_bytes(request_bytes)
+
+    return id, request, err
+}
+
+send_request :: proc(client: net.TCP_Socket, request: common.Server_Request) -> common.Error {
+    panic("TODO")    
+}
+
+send_response :: proc(client: net.TCP_Socket, id: u32, content: string) -> common.Error {
+    bytes_buf: [1_000]u8
+    bytes_buffer: bytes.Buffer
+    bytes_buffer.buf = slice.into_dynamic(bytes_buf[:])
+    response_stream := bytes.buffer_to_stream(&bytes_buffer)
+
+    // Message type.
+    _ = io.write_byte(response_stream, 0)
+
+    // Reponse ID.
+    id_bytes: [size_of(u32)]u8
+    endian.put_u32(id_bytes[:], .Little, id)
+
+    _, _ = io.write(response_stream, id_bytes[:])
+
+    // Content.
+    _, _ = io.write(response_stream, transmute([]u8)content)
+
+    // Length.
+    buffer_length := bytes.buffer_length(&bytes_buffer)
+
+    len_bytes: [size_of(32)]u8
+    endian.put_u32(len_bytes[:], .Little, u32(buffer_length))
+
+    _, _ = io.write_at(response_stream, len_bytes[:], 0)
+
+    response_bytes := bytes.buffer_to_bytes(&bytes_buffer)
+
+    return nil
+}
index fdba95ec0b9985d9c1353a74d24ea8d2e429948c..b4755dc5cb9241549d1443f2c3baa64239d9de2c 100644 (file)
@@ -8,21 +8,12 @@ import "core:io"
 import "core:log"
 import "core:mem"
 import "core:net"
+import "core:slice"
 import "core:sync"
 import "core:thread"
 
 import "../common"
 
-Packet_Error :: enum {
-    Packet_Too_Large,
-}
-
-Recv_Packet_Error :: union {
-    Packet_Error,
-    io.Error,
-    net.Network_Error,
-}
-
 Handle_Client_Data :: struct {
     clients_sockets: ^map[net.Endpoint]net.TCP_Socket,
     mutex: ^sync.Mutex,
@@ -31,25 +22,6 @@ Handle_Client_Data :: struct {
     client_endpoint: net.Endpoint,
 }
 
-receive_packet :: proc(socket: net.TCP_Socket, buffer: []u8) -> (packet: []u8, err: Recv_Packet_Error) {
-    length_bytes: [size_of(u32)]u8
-    _ = net.recv_tcp(socket, length_bytes[:]) or_return
-
-    length, _ := endian.get_u32(length_bytes[:], .Little)
-
-    if int(length) > len(buffer) {
-        for _ in 0..<length {
-            _ = net.recv_tcp(socket, buffer[:]) or_return
-        }
-
-        return nil, .Packet_Too_Large
-    }
-
-    _ = net.recv_tcp(socket, buffer[:length]) or_return
-
-    return buffer[:length], nil
-}
-
 handle_client :: proc(data: Handle_Client_Data) {
     using data
 
@@ -70,47 +42,18 @@ handle_client :: proc(data: Handle_Client_Data) {
     response: []u8
 
     for {
-        packet, err1 := receive_packet(client_socket, recv_buffer[:])
+        defer net.send_tcp(client_socket, response)
 
-        if err1 != nil {
-            #partial switch e in err1 {
-            case Packet_Error:
-                log.errorf("Failed to receive packet with error: %v", e)
-
-            case net.Network_Error:
-                #partial switch e_ in e {
-                case net.TCP_Recv_Error:
-                    #partial switch e_ {
-                    case .Connection_Closed:
-                        return
-
-                    case:
-                        log.errorf("Failed to receive packet with error: %v", e_)
-                    }
-
-                case:
-                    log.errorf("Failed to receive packet with error: %v", e_)
-                }
-
-            case:
-                return
-            }
-
-            continue
-        }
-
-        defer net.send(client_socket, response)
+        request_id, request, err1 := receive_request(client_socket)
 
-        request, err2 := common.client_request_from_bytes(packet)
-
-        if err2 != nil {
+        if err1 != nil {
             response_string := "Invalid request"
             response = transmute([]u8)response_string
 
             continue
         }
 
-        if err3 := common.client_request_verify(request, 1 * 60 * 60 * 1_000_000_000); err3 != nil {
+        if err2 := common.client_request_verify(request, 1 * 60 * 60 * 1_000_000_000); err2 != nil {
             response_string := "Invalid authentication"
             response = transmute([]u8)response_string
 
index f3419970c152368fc0ccf6a06494fd02dbf25523..92462e07ccaf694719f765a4231976261c24fb9a 100755 (executable)
Binary files a/server/server and b/server/server differ