package main
import "core:encoding/base64"
-import "core:log"
import "core:math/rand"
+import "core:mem"
import "core:net"
import "core:os"
import "core:slice"
}
}
+ room_name := room_get_name(&room)
+
+ room_name_bytes: [common.ROOM_NAME_SIZE]u8
+ mem.copy_non_overlapping(raw_data(room_name_bytes[:]), raw_data(room_name), len(room_name))
+
request := common.Subscribe_Request{
room_id = room_get_id(&room),
+ room_name = room_name_bytes,
}
err := request_host(app, request, &app.profile.private_key, nil)
room_name := args[0]
- key: [ROOM_KEY_SIZE]u8
+ key: [common.ROOM_KEY_SIZE]u8
_ = rand.read(key[:])
room, ok := room_init(room_name, key)
return .Invalid_Arguments
}
+ room_name_bytes: [common.ROOM_NAME_SIZE]u8
+ mem.copy_non_overlapping(raw_data(room_name_bytes[:]), raw_data(room_name), len(room_name))
+
request := common.Subscribe_Request{
room_id = room_get_id(&room),
+ room_name = room_name_bytes,
}
callback :: proc(app: ^App, response: common.Server_Response) {
receive_host :: proc(app: ^App) -> (id: u32, message: common.Server_Message, err: common.Error) {
buffer: [1_000]u8
packet := common.receive_packet(app.host.?, buffer[:]) or_return
- packet_buffer := common.buffer_from_slice(buffer[:])
+ packet_buffer := common.buffer_from_slice(packet[:])
packet_stream := bytes.buffer_to_stream(&packet_buffer)
return common.server_message_from_bytes(app.host.?, packet_stream)
nc.wclear(room_list_window)
- c_room_name_buffer: [ROOM_NAME_MAX_SIZE + 1]u8
+ c_room_name_buffer: [common.ROOM_NAME_SIZE + 1]u8
for &room, i in app.profile.rooms {
room_color := nc.COLOR_PAIR(3)
app.seed_phrase_checksum = entropy_hash[0] & 0b1111
}
-app_room_key_exists :: proc(app: ^App, key: [ROOM_KEY_SIZE]u8) -> bool {
+app_room_key_exists :: proc(app: ^App, key: [common.ROOM_KEY_SIZE]u8) -> bool {
key := key
for &room in app.profile.rooms {
import chacha "core:crypto/chacha20poly1305"
import fpath "core:path/filepath"
-ROOM_NAME_LEN :: 30
-ROOM_NAME_SIZE :: ROOM_NAME_LEN * 4
+import "../common"
-ROOM_KEY_SIZE :: 32
-
-Room_Name :: small_array.Small_Array(ROOM_NAME_SIZE, u8)
+Room_Name :: small_array.Small_Array(common.ROOM_NAME_SIZE, u8)
Room :: struct {
name: Room_Name,
- key: [ROOM_KEY_SIZE]u8,
+ key: [common.ROOM_KEY_SIZE]u8,
}
-room_init :: proc(name: string, key: [ROOM_KEY_SIZE]u8) -> (Room, bool) {
+room_init :: proc(name: string, key: [common.ROOM_KEY_SIZE]u8) -> (Room, bool) {
_, name_len, _ := utf8.grapheme_count(name)
- if name_len > ROOM_NAME_MAX_LEN {
+ if name_len > common.ROOM_NAME_LEN {
return {}, false
}
return {}, false
}
- key_bytes: [ROOM_KEY_SIZE]u8
+ key_bytes: [common.ROOM_KEY_SIZE]u8
key_bytes_buffer := bytes.Buffer{ buf = mem.buffer_from_slice(key_bytes[:]) }
key_bytes_stream := bytes.buffer_to_stream(&key_bytes_buffer)
request := common.Push_Request {
room_id = room_get_id(selected_room),
- encrypted_message = encrypted_message,
+ message = encrypted_message,
}
err := request_host(app, request, &app.profile.private_key, nil)
return nil
}
+ROOM_NAME_LEN :: 30
+ROOM_NAME_SIZE :: ROOM_NAME_LEN * 4
+
Subscribe_Request :: struct {
room_id: Room_ID,
room_name: [ROOM_NAME_SIZE]u8,
server_response_from_bytes :: proc(stream: io.Stream) -> (response: Server_Response, err: Error) {
buffer: [1_000]u8
- _, _ = io.read(stream, buffer[:])
+ bytes_read, _ := io.read(stream, buffer[:])
- response, _ = strings.clone_from_bytes(buffer[:])
+ response, _ = strings.clone_from_bytes(buffer[:bytes_read])
return response, nil
}
server_message_from_bytes :: proc(server: net.TCP_Socket, stream: io.Stream) -> (id: u32, message: Server_Message, err: Error) {
// Message type.
- message_type, _ := io.read_byte(stream)
+ message_type := io.read_byte(stream) or_return
// Message ID.
id_bytes: [size_of(u32)]u8
- _, _ = io.read(stream, id_bytes[:])
+ _ = io.read(stream, id_bytes[:]) or_return
id, _ = endian.get_u32(id_bytes[:], .Little)
// Response.
case 1:
- message, err = server_response_from_bytes(stream)
+ message = server_response_from_bytes(stream) or_return
case:
return 0, nil, Receive_Message_Error.Invalid_Type
}
- return id, message, err
+ return id, message, nil
}
receive_packet :: proc(socket: net.TCP_Socket, buffer: []u8) -> (packet: []u8, err: Error) {
import "core:bytes"
import "core:encoding/endian"
import "core:io"
-import "core:log"
import "core:mem"
import "core:net"
import "core:slice"
package main
-
import "base:runtime"
import "core:crypto/ed25519"
import "../common"
-Subscribtion :: struct {
+Subscription :: struct {
public_key: ed25519.Public_Key,
- room_id: Room_ID,
+ room_id: common.Room_ID,
room_name: [common.ROOM_NAME_SIZE]u8,
}
-Handle_Client_Data :: struct {
- data_mutex: ^sync.Mutex,
- db_mutex: ^sync.Mutex,
+App :: struct {
+ data_mutex: sync.Mutex,
+ db_mutex: sync.Mutex,
+
+ clients_sockets: map[net.Endpoint]net.TCP_Socket,
+
+ subscriptions: [dynamic]Subscription,
+}
+
+app_init :: proc() -> App {
+ return {
+ clients_sockets = make(map[net.Endpoint]net.TCP_Socket),
- clients_sockets: ^map[net.Endpoint]net.TCP_Socket,
+ subscriptions = make([dynamic]Subscription),
+ }
+}
+
+app_deinit :: proc(app: ^App) {
+ delete(app.subscriptions)
+
+ for _, socket in app.clients_sockets {
+ net.close(socket)
+ }
+
+ delete(app.clients_sockets)
+}
+
+Handle_Client_Data :: struct {
+ app: ^App,
client_socket: net.TCP_Socket,
client_endpoint: net.Endpoint,
-
- subscribtions: [dynamic]Subscription,
}
handle_client :: proc(data: Handle_Client_Data) {
defer {
log.infof("Client %v disconnected.", client_endpoint_string)
- sync.mutex_lock(data_mutex)
- defer sync.mutex_unlock(data_mutex)
+ sync.mutex_lock(&app.data_mutex)
+ defer sync.mutex_unlock(&app.data_mutex)
- delete_key(clients_sockets, client_endpoint)
+ delete_key(&app.clients_sockets, client_endpoint)
}
recv_buffer: [10_000]u8
log.infof("Received request: %v", request)
- #partial switch inner in request.inner {
+ #partial switch &inner in request.inner {
case common.Subscribe_Request:
subscription := Subscription{
public_key = request.public_key,
}
{
- sync.mutex_lock(&data_mutex)
- defer sync.mutex_unlock(&data_mutex)
+ sync.mutex_lock(&app.data_mutex)
+ defer sync.mutex_unlock(&app.data_mutex)
- append(&subscriptions, subscription)
+ append(&app.subscriptions, subscription)
}
case common.Unsubscribe_Request:
- sync.mutex_lock(&data_mutex)
- defer sync.mutex_unlock(&data_mutex)
+ sync.mutex_lock(&app.data_mutex)
+ defer sync.mutex_unlock(&app.data_mutex)
- for subscription, i in subscriptions {
+ for &subscription, i in app.subscriptions {
if ed25519.public_key_equal(&subscription.public_key, &request.public_key) &&
- subscription.room_id == inner.room_id
+ slice.equal(subscription.room_id[:], inner.room_id[:])
{
- unordered_remove(&subscriptions, i)
+ unordered_remove(&app.subscriptions, i)
break
}
}
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)
- }
-
- data_mutex: sync.Mutex
- db_mutex: sync.Mutex
+ app := app_init()
+ defer app_deinit(&app)
handle_client_thread_context := runtime.default_context()
handle_client_thread_context.logger = context.logger
log.infof("Accepted client from %v.", client_endpoint_string)
{
- sync.mutex_lock(&data_mutex)
- defer sync.mutex_unlock(&data_mutex)
+ sync.mutex_lock(&app.data_mutex)
+ defer sync.mutex_unlock(&app.data_mutex)
- clients_sockets[client_endpoint] = client_socket
+ app.clients_sockets[client_endpoint] = client_socket
}
client_handle_data := Handle_Client_Data{
- data_mutex = &data_mutex,
- db_mutex = &db_mutex,
-
- clients_sockets = &clients_sockets,
+ app = &app,
client_socket = client_socket,
client_endpoint = client_endpoint,