}
)
- host_endpoint, err1 := net.resolve_ip4(app.profile.host)
+ host_endpoint: net.Endpoint
+ host_endpoint.port = DEFAULT_PORT
- if err1 != nil {
- log.errorf("Failed to resolve host with error: %v", err1)
- app_set_state(app, .Invalid_Host)
- return
- }
+ blk: { // Resolve host endpoint.
+ ok: bool
+ host_endpoint, ok = net.parse_endpoint(app.profile.host)
- host_endpoint.port = DEFAULT_PORT
+ if ok {
+ break blk
+ }
+
+ err: net.Network_Error
+ host_endpoint, err = net.resolve_ip4(app.profile.host)
- host, err2 := net.dial_tcp_from_endpoint(host_endpoint)
+ if err != nil {
+ log.errorf("Failed to resolve host with error: %v", err)
+ app_set_state(app, .Invalid_Host)
+ return
+ }
+ }
- if err2 != nil {
- log.errorf("Failed to connect to host with error: %v", err2)
+ host, err := net.dial_tcp_from_endpoint(host_endpoint)
+
+ if err != nil {
+ log.errorf("Failed to connect to host with error: %v", err)
app_set_state(app, .Invalid_Host)
return
}
app,
{
"Failed to connect to host.",
- "Either enter a new host,",
+ "Enter either a new host,",
"or :retry."
}
)
public: bool,
}
-Create_Group :: struct {
- group_name: string,
- members_public_keys: []Public_Key_Bytes,
-}
-
-Block_User :: struct {
+Kick_User :: struct {
user_public_key: ed25519.Public_Key,
}
-Set_Whitelist_State :: struct {
- state: bool,
-}
-
-Add_To_Whitelist :: struct {
+Ban_User :: struct {
user_public_key: ed25519.Public_Key,
}
-Remove_From_Whitelist :: struct {
- user_public_key: ed25519.Public_Key,
-}
-
-Public_Message :: struct {
+Message :: struct {
room_id: string,
content: string,
}
-Private_Message :: struct {
- room_id: string,
- content: string,
-}
-
-Direct_Message :: struct {
- receiver_public_key: ed25519.Public_Key,
- encrypted_content: []u8,
-}
-
-Group_Message :: struct {
- group_id: u32,
- encrypted_contents: map[Public_Key_Bytes][]u8,
-}
-
Client_Request_Content :: union {
- // Client only.
Create_Room,
- Create_Group,
-
- Block_User,
-
- Set_Whitelist_State,
- Add_To_Whitelist,
- Remove_From_Whitelist,
+ Kick_User,
+ Ban_User,
- // Common.
- Public_Message,
- Private_Message,
- Direct_Message,
- Group_Message,
+ Message,
}
Client_Request :: struct {
}
Server_Request :: union {
- Public_Message,
- Private_Message,
- Direct_Message,
- Group_Message,
+ Message,
}
send_server_request :: proc(request: Server_Request) {
Handle_Client_Data :: struct {
clients_sockets: ^map[net.Endpoint]net.TCP_Socket,
- clients_sockets_mutex: ^sync.Mutex,
+ mutex: ^sync.Mutex,
client_socket: net.TCP_Socket,
client_endpoint: net.Endpoint,
continue
}
- switch content in request.content {
+ #partial switch content in request.content {
case:
response_string := "Unhandled request type"
response = transmute([]u8)response_string
defer log.destroy_console_logger(context.logger)
when ODIN_DEBUG {
- track: mem.Tracking_Allocator
- mem.tracking_allocator_init(&track, context.allocator)
-
- context.allocator = mem.tracking_allocator(&track)
-
- defer {
- if len(track.allocation_map) > 0 {
- fmt.eprintf("=== %v allocations not freed: ===\n", len(track.allocation_map))
-
- for _, entry in track.allocation_map {
- fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
- }
- }
-
- if len(track.bad_free_array) > 0 {
- fmt.eprintf("=== %v incorrect frees: ===\n", len(track.bad_free_array))
-
- for entry in track.bad_free_array {
- fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
- }
- }
-
- mem.tracking_allocator_destroy(&track)
- }
- }
+ track: mem.Tracking_Allocator
+ mem.tracking_allocator_init(&track, context.allocator)
+
+ context.allocator = mem.tracking_allocator(&track)
+
+ defer {
+ if len(track.allocation_map) > 0 {
+ log.errorf("%v allocation not freed.", len(track.allocation_map))
+
+ for _, entry in track.allocation_map {
+ log.errorf("- %v bytes at %v", entry.size, entry.location)
+ }
+ }
+
+ if len(track.bad_free_array) > 0 {
+ log.errorf("%v incorrect frees.", len(track.bad_free_array))
+
+ for entry in track.bad_free_array {
+ log.errorf("- %p at %v", entry.memory, entry.location)
+ }
+ }
+
+ mem.tracking_allocator_destroy(&track)
+ }
+ }
server_endpoint := net.Endpoint{
address = net.IP4_Address{ 127, 0, 0, 1 },
delete(clients_sockets)
}
- clients_sockets_mutex: sync.Mutex
+ mutex: sync.Mutex
+
+ handle_client_thread_context := runtime.default_context()
+ handle_client_thread_context.logger = context.logger
+ handle_client_thread_context.random_generator = context.random_generator
+
+ clients_threads := make(map[net.Endpoint]^thread.Thread)
+
+ defer {
+ for _, handle_client_thread in clients_threads {
+ thread.terminate(handle_client_thread, 0)
+ thread.destroy(handle_client_thread)
+ }
+
+ delete(clients_threads)
+ }
for {
client_socket, client_endpoint, err2 := net.accept_tcp(server_socket)
log.infof("Accepted client from %v.", client_endpoint_string)
{
- sync.mutex_lock(&clients_sockets_mutex)
- defer sync.mutex_unlock(&clients_sockets_mutex)
+ sync.mutex_lock(&mutex)
+ defer sync.mutex_unlock(&mutex)
clients_sockets[client_endpoint] = client_socket
}
client_endpoint = client_endpoint,
}
- client_thread := thread.create_and_start_with_poly_data(
- client_handle_data,
- handle_client,
- runtime.Context{
- allocator = context.allocator,
- logger = context.logger,
- },
- )
+ client_thread := thread.create_and_start_with_poly_data(client_handle_data, handle_client, handle_client_thread_context)
+
+ {
+ sync.mutex_lock(&mutex)
+ defer sync.mutex_unlock(&mutex)
+
+ clients_threads[client_endpoint] = client_thread
+ }
}
}