use_enum_names = true,
}
+Message :: struct {
+ timestamp: i64,
+ content: [common.MESSAGE_SIZE]u8,
+}
+
App :: struct {
ui_mutex: sync.Mutex,
data_mutex: sync.Mutex,
requests_callbacks: map[u32]Request_Callback,
selected_room: int,
+
+ messages: map[common.Room_ID][dynamic]Message,
}
app_init :: proc(storage_path: string) -> App {
info_bar = info_bar,
input_window = input_window,
- requests_callbacks= make(map[u32]Request_Callback),
+ requests_callbacks = make(map[u32]Request_Callback),
+
+ messages = make(map[common.Room_ID][dynamic]Message),
}
app_update_info_bar(&app)
sync.mutex_lock(&app.data_mutex)
defer sync.mutex_unlock(&app.data_mutex)
+ for messages in app.messages {
+ delete(messages)
+ }
+
+ delete(app.messages)
+
delete(app.requests_callbacks)
if host, ok := app.host.?; ok {
continue
}
- #partial switch message in server_message {
+ switch message in server_message {
+ case common.Server_Request:
+ request := message
+
+ #partial switch r in request {
+ case Push_Request:
+ user_message := Message{
+ timestamp = message.timestamp,
+ content = request.message,
+ }
+
+ {
+ sync.mutex_lock(&app.data_mutex)
+ defer sync.mutex_unlock(&app.data_mutex)
+
+ if app.messages[request.room_id] == nil {
+ app.messages[request.room_id] = make([dynamic]Message)
+ }
+
+ append(&app.messages[request.room_id], user_message)
+ }
+ }
+
case common.Server_Response:
response := message
defer common.server_response_deinit(response)
import "../common"
-Room_Name :: small_array.Small_Array(common.ROOM_NAME_SIZE, u8)
-
-Room :: struct {
- name: Room_Name,
- key: [common.ROOM_KEY_SIZE]u8,
-}
-
-room_init :: proc(name: string, key: [common.ROOM_KEY_SIZE]u8) -> (Room, bool) {
- _, name_len, _ := utf8.grapheme_count(name)
-
- if name_len > common.ROOM_NAME_LEN {
- return {}, false
- }
-
- name_bytes := transmute([]u8)name
-
- room_name: Room_Name
- small_array.append_elems(&room_name, ..name_bytes)
-
- return {
- name = room_name,
- key = key,
- },
- true
-}
-
-room_init_with_key_string :: proc(name: string, key_string: string) -> (Room, bool) {
- if len(key_string) != 44 {
- return {}, false
- }
-
- 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)
-
- err := base64.decode_into(key_bytes_stream, key_string)
-
- if err != nil {
- return {}, false
- }
-
- return room_init(name, key_bytes)
-}
-
-room_get_name :: proc(room: ^Room) -> string {
- bytes := small_array.slice(&room.name)
- return string(bytes)
-}
-
-room_get_id :: proc(room: ^Room) -> [sha3.DIGEST_SIZE_256]u8 {
- sha3_context: sha3.Context
- sha3.init_256(&sha3_context)
- sha3.update(&sha3_context, room.key[:])
-
- id: [sha3.DIGEST_SIZE_256]u8
- sha3.final(&sha3_context, id[:])
-
- return id
-}
-
Profile :: struct {
private_key: ed25519.Private_Key,
hosts: string,
--- /dev/null
+package main
+
+Room_Name :: small_array.Small_Array(common.ROOM_NAME_SIZE, u8)
+
+Room :: struct {
+ name: Room_Name,
+ key: [common.ROOM_KEY_SIZE]u8,
+}
+
+room_init :: proc(name: string, key: [common.ROOM_KEY_SIZE]u8) -> (Room, bool) {
+ _, name_len, _ := utf8.grapheme_count(name)
+
+ if name_len > common.ROOM_NAME_LEN {
+ return {}, false
+ }
+
+ name_bytes := transmute([]u8)name
+
+ room_name: Room_Name
+ small_array.append_elems(&room_name, ..name_bytes)
+
+ return {
+ name = room_name,
+ key = key,
+ },
+ true
+}
+
+room_init_with_key_string :: proc(name: string, key_string: string) -> (Room, bool) {
+ if len(key_string) != 44 {
+ return {}, false
+ }
+
+ 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)
+
+ err := base64.decode_into(key_bytes_stream, key_string)
+
+ if err != nil {
+ return {}, false
+ }
+
+ return room_init(name, key_bytes)
+}
+
+room_get_name :: proc(room: ^Room) -> string {
+ bytes := small_array.slice(&room.name)
+ return string(bytes)
+}
+
+room_get_id :: proc(room: ^Room) -> common.Room_ID {
+ sha3_context: sha3.Context
+ sha3.init_256(&sha3_context)
+ sha3.update(&sha3_context, room.key[:])
+
+ id: [sha3.DIGEST_SIZE_256]u8
+ sha3.final(&sha3_context, id[:])
+
+ return id
+}
Push_Request :: struct {
room_id: Room_ID,
+ timestamp: i64,
message: [MESSAGE_SIZE]u8,
}
room_id: Room_ID
_ = io.read(stream, room_id[:]) or_return
+ timestamp_bytes: [size_of(i64)]u8
+ _ = io.read(stream, timestamp_bytes[:]) or_return
+
+ timestamp, _ := endian.get_i64(timestamp_bytes[:], .Little)
+
encrypted_message: [MESSAGE_SIZE]u8
_ = io.read(stream, encrypted_message[:]) or_return
return {
room_id = room_id,
+ timestamp = timestamp,
message = encrypted_message,
},
nil
request := request
_ = io.write(stream, request.room_id[:]) or_return
+
+ timestamp_bytes: [size_of(i64)]u8
+ _ = endian.put_i64(timestamp_bytes[:], .Little, request.timestamp)
+ _ = io.write(stream, timestamp_bytes[:]) or_return
+
_ = io.write(stream, request.message[:]) or_return
return nil
Client_Info :: struct {
endpoint: net.Endpoint,
- socket: net.TCP_Socket,
public_key: ed25519.Public_Key,
+ socket: net.TCP_Socket,
}
App :: struct {
return nil
}
-app_get_client_info_by_public_key :: proc(app: ^App, public_key: ed25519.Public_Key) -> ^Client_Info {
+app_get_clients_info_by_public_key :: proc(app: ^App, buffer: []^Client_Info, public_key: ed25519.Public_Key) -> []^Client_Info {
public_key := public_key
+ i := 0
for &client_info in app.clients_info {
if ed25519.public_key_equal(&client_info.public_key, &public_key) {
- return &client_info
+ buffer[i] = &client_info
+ i += 1
}
}
- return nil
+ return buffer[:i]
}
app_delete_client_info :: proc(app: ^App, endpoint: net.Endpoint) {
}
}
- defer {
- log.infof("Response: %v", response)
- send_response(client_socket, request_id, response)
- }
+ defer send_response(client_socket, request_id, response)
if err1 != nil {
response := "Invalid request"
continue
}
- log.infof("Received request: %v", request)
-
#partial switch &inner in request.inner {
case common.Sync_Request:
sync.mutex_lock(&app.data_mutex)
defer sync.mutex_unlock(&app.data_mutex)
client_info := app_get_client_info_by_endpoint(app, client_endpoint)
-
- if client_info != nil {
- client_info.public_key = request.public_key
- }
+ client_info.public_key = request.public_key
case common.Push_Request:
sync.mutex_lock(&app.data_mutex)
defer sync.mutex_unlock(&app.data_mutex)
for &subscription in app.subscriptions {
- if slice.equal(subscription.room_id[:], inner.room_id[:]) {
- client_info := app_get_client_info_by_public_key(app, subscription.public_key)
- if client_info == nil do continue
+ if !slice.equal(subscription.room_id[:], inner.room_id[:]) {
+ continue
+ }
+
+ clients_info_buffer: [100]^Client_Info
+
+ clients_info := app_get_clients_info_by_public_key(app, clients_info_buffer[:], subscription.public_key)
- request := common.Push_Request{
- room_id = inner.room_id,
- message = inner.message,
- }
+ if len(clients_info) == 0 {
+ continue
+ }
+
+ request := common.Push_Request{
+ room_id = inner.room_id,
+ timestamp = request.timestamp,
+ message = inner.message,
+ }
+ for client_info in clients_info {
send_request(client_info.socket, request)
}
}