import "core:encoding/base64"
import "core:log"
import "core:math/rand"
+import "core:net"
import "core:os"
import "core:slice"
import "core:strings"
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.")
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.")
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.")
--- /dev/null
+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 {
+
+}
import nc "../ncurses"
+import "../common"
+
COLOR_FIRST :: 16
COLOR_SECOND :: 17
COLOR_THIRD :: 18
seed_phrase_checksum: u8,
host: Maybe(net.TCP_Socket),
+ waiting_respones: [dynamic]common.Server_Response,
selected_room: int,
}
info_bar = info_bar,
input_window = input_window,
+
+ waiting_responses = make([dynamic]common.Server_Response),
}
app_update_info_bar(&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)
}
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)
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 {
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
}
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
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
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
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
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
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
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) }
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
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
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)
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())
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)
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")
-}
--- /dev/null
+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
+}
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,
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
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