From: jxnshi Date: Fri, 31 Jan 2025 14:02:52 +0000 (+0100) Subject: Update X-Git-Url: https://jxnshi.xyz/repos?a=commitdiff_plain;h=16e313b38294c9e43478bad6f9df2b2f64d71d0b;p=mesange.git Update --- diff --git a/client-cli/client-cli b/client-cli/client-cli index 324f229..4a7a161 100755 Binary files a/client-cli/client-cli and b/client-cli/client-cli differ diff --git a/client-cli/command.odin b/client-cli/command.odin index a8b4673..9382e8d 100644 --- a/client-cli/command.odin +++ b/client-cli/command.odin @@ -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 index 0000000..5a745fd --- /dev/null +++ b/client-cli/host.odin @@ -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 { + +} diff --git a/client-cli/main.odin b/client-cli/main.odin index 8846d4b..839e2fd 100644 --- a/client-cli/main.odin +++ b/client-cli/main.odin @@ -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) } diff --git a/client-cli/state.odin b/client-cli/state.odin index 39cf6a6..a351d12 100644 --- a/client-cli/state.odin +++ b/client-cli/state.odin @@ -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) diff --git a/common/request.odin b/common/request.odin index d89b806..844fef1 100644 --- a/common/request.odin +++ b/common/request.odin @@ -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 index 0000000..d3c52e3 --- /dev/null +++ b/server/client.odin @@ -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.. 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 +} diff --git a/server/main.odin b/server/main.odin index fdba95e..b4755dc 100644 --- a/server/main.odin +++ b/server/main.odin @@ -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..