socket address no longer query for information
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 27 Mar 2022 03:41:32 +0000 (22:41 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 27 Mar 2022 03:41:32 +0000 (22:41 -0500)
core/conv.onyx
core/net/net.onyx
src/onyx_runtime.c

index f904224390eed04de1e03cbf643d14ac6c870787..6b83af1082dd2b6b496d2e3a768788e225f999c5 100644 (file)
@@ -489,29 +489,23 @@ format_any :: (output: ^Format_Output, formatting: ^Format, v: any) {
             }
         }
 
-        case i16, u16 {
-            value := *(cast(^i16) v.data);
-
-            ibuf : [128] u8;
-            istr := i64_to_str(~~value, formatting.base, ~~ibuf, min_length=formatting.minimum_width);
-            output->write(istr);
-        }
-
-        case i32, u32 {
-            value := *(cast(^i32) v.data);
+        int_case :: macro (T: type_expr) {
+            case T {
+                value := *(cast(^T) v.data);
 
-            ibuf : [128] u8;
-            istr := i64_to_str(~~value, formatting.base, ~~ibuf, min_length=formatting.minimum_width);
-            output->write(istr);
+                ibuf : [128] u8;
+                istr := i64_to_str(~~value, formatting.base, ~~ibuf, min_length=formatting.minimum_width);
+                output->write(istr);
+            }
         }
 
-        case i64, u64 {
-            value := *(cast(^i64) v.data);
-
-            ibuf : [128] u8;
-            istr := i64_to_str(~~value, formatting.base, ~~ibuf);
-            output->write(istr);
-        }
+        int_case(i8);
+        int_case(i16);
+        int_case(u16);
+        int_case(i32);
+        int_case(u32);
+        int_case(i64);
+        int_case(u64);
 
         case f32 {
             value := *(cast(^f32) v.data);
index 82bf9b045c1ac083eb1b670311ac0f1c7e5f7253..bec979887b76fc9641f5272842be6ebc77524837 100644 (file)
@@ -16,9 +16,11 @@ Socket :: struct {
     accept    :: socket_accept
     connect   :: socket_connect
     send      :: socket_send
+    sendto    :: socket_sendto
     sendall   :: socket_sendall
     recv      :: socket_recv
     recv_into :: socket_recv_into
+    recvfrom  :: socket_recvfrom
 }
 
 SocketError :: enum {
@@ -43,20 +45,21 @@ SocketSetting :: enum {
     NonBlocking :: 0x01;
 }
 
-Socket_Address :: struct {
-    Handle :: #distinct u64
-    addr: Handle;
+// This structure is twenty bytes in size to accommodate IPV6 addresses.
+Socket_Address :: struct #size 20 {
+    family: u16;
+    port: u16;
+    addr: u32;
 
-    get_address :: (s: ^Socket_Address, allocator := context.allocator) -> [] u8 {
-        buf: [256] u8;
-        addr_len := __net_address_get_address(s.addr, buf);
-        
-        ret := memory.copy_slice(buf[0 .. addr_len], allocator=allocator);
-        return ret;
-    }
+    addr_as_str :: (use this: ^Socket_Address, allocator := context.allocator) -> str {
+        out: [64] u8; 
+        str_addr := conv.format(out, "{}.{}.{}.{}",
+            (addr >> 24) & 0xff,
+            (addr >> 16) & 0xff,
+            (addr >>  8) & 0xff,
+            (addr >>  0) & 0xff);
 
-    get_port :: (s: ^Socket_Address) -> u32 {
-        return __net_address_get_port(s.addr);
+        return string.alloc_copy(str_addr, allocator=allocator);
     }
 }
 
@@ -99,7 +102,7 @@ socket_listen :: (s: ^Socket, backlog := 32) {
 socket_accept :: (s: ^Socket) -> (Socket, Socket_Address) {
     new_socket: Socket;
     new_addr: Socket_Address;
-    new_socket.handle = __net_accept(s.handle, ^new_addr.addr);
+    new_socket.handle = __net_accept(s.handle, ^new_addr);
 
     if new_socket.handle >= 0 {
         new_socket.vtable = ^__net_socket_vtable;
@@ -132,6 +135,12 @@ socket_send :: (s: ^Socket, data: [] u8) -> i32 {
     return sent;
 }
 
+socket_sendto :: (s: ^Socket, data: [] u8, addr: ^Socket_Address) -> i32 {
+    sent := __net_sendto(s.handle, data, addr);
+    if sent < 0 { s.vtable = null; }
+    return sent;
+}
+
 socket_sendall :: (s: ^Socket, data: [] u8) {
     to_send := data;
 
@@ -166,6 +175,17 @@ socket_recv_into :: (s: ^Socket, buffer: [] u8) -> i32 {
     return received;
 }
 
+socket_recvfrom :: (s: ^Socket, buffer: [] u8) -> (Socket_Address, i32) {
+    would_block: bool;
+    sa: Socket_Address;
+
+    received := __net_recvfrom(s.handle, buffer, ^sa, ^would_block);
+    if received < 0 && !would_block do s.vtable = null;
+    if would_block do return sa, 0;
+
+    return sa, received;
+}
+
 #local __net_socket_vtable := io.Stream_Vtable.{
     read = (use s: ^Socket, buffer: [] u8) -> (io.Error, u32) {
         if handle == 0 do return .BadFile, 0;
@@ -199,14 +219,13 @@ socket_recv_into :: (s: ^Socket, buffer: [] u8) -> i32 {
     #package __net_setting       :: (handle: Socket.Handle, setting: SocketSetting, value: i32) -> void ---
     #package __net_bind          :: (handle: Socket.Handle, port: u16)    -> bool ---
     #package __net_listen        :: (handle: Socket.Handle, backlog: i32) -> void ---
-    #package __net_accept        :: (handle: Socket.Handle, out_address: ^Socket_Address.Handle) -> Socket.Handle ---
+    #package __net_accept        :: (handle: Socket.Handle, out_address: ^Socket_Address) -> Socket.Handle ---
     #package __net_connect       :: (handle: Socket.Handle, host: str, port: u16) -> SocketError ---
     #package __net_send          :: (handle: Socket.Handle, data: [] u8)  -> i32 ---
-    #package __net_recv          :: (handle: Socket.Handle, data: [] u8, async_would_block: ^bool)  -> i32 ---
+    #package __net_sendto        :: (handle: Socket.Handle, data: [] u8, addr: ^Socket_Address)  -> i32 ---
+    #package __net_recv          :: (handle: Socket.Handle, data: [] u8, async_would_block: ^bool) -> i32 ---
+    #package __net_recvfrom      :: (handle: Socket.Handle, data: [] u8, out_recv_addr: ^Socket_Address, async_would_block: ^bool) -> i32 ---
     #package __net_poll_recv     :: (handle: [] Socket.Handle, timeout: i32, out_recv_indicies: ^i32) -> i32 ---
-
-    #package __net_address_get_address :: (address: Socket_Address.Handle, out_buffer: [] u8) -> i32 ---
-    #package __net_address_get_port    :: (address: Socket_Address.Handle) -> i32 ---
 }
 
 #operator >= macro (a, b: Socket.Handle) => cast(u32) a >= cast(u32) b;
index 41577ee96a3d9cdd9ed16369c52c7bffc4e21538..d78f8b441aa12fa2d2c96e6a818606ed62aef26b 100644 (file)
@@ -797,6 +797,12 @@ ONYX_DEF(__time, (), (WASM_I64)) {
 //
 // Networking
 //
+struct onyx_socket_addr {
+    unsigned short family;
+    unsigned short port;
+    unsigned int   addr;
+};
+
 ONYX_DEF(__net_create_socket, (WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
 
     #ifdef _BH_LINUX
@@ -895,13 +901,17 @@ ONYX_DEF(__net_listen, (WASM_I32, WASM_I32), ()) {
 
 ONYX_DEF(__net_accept, (WASM_I32, WASM_I32), (WASM_I32)) {
     #ifdef _BH_LINUX
-    struct sockaddr_in *client_addr = malloc(sizeof(*client_addr));
-    int client_len = sizeof(*client_addr);
-    memset(client_addr, 0, client_len);
+    struct sockaddr_in client_addr;
+    int client_len = sizeof(client_addr);
+    memset(&client_addr, 0, client_len);
 
-    int client_socket = accept(params->data[0].of.i32, client_addr, &client_len);
+    int client_socket = accept(params->data[0].of.i32, &client_addr, &client_len);
+
+    struct onyx_socket_addr* out_addr = (struct onyx_socket_addr *) ONYX_PTR(params->data[1].of.i32); 
+    out_addr->family = client_addr.sin_family;
+    out_addr->port   = ntohs(client_addr.sin_port);
+    out_addr->addr   = ntohl(client_addr.sin_addr.s_addr);
 
-    *(i64 *) ONYX_PTR(params->data[1].of.i32) = (i64) client_addr;
     results->data[0] = WASM_I32_VAL(client_socket);
     #endif
 
@@ -950,6 +960,25 @@ ONYX_DEF(__net_send, (WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
     return NULL;
 }
 
+ONYX_DEF(__net_sendto, (WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
+    #ifdef _BH_LINUX
+    struct sockaddr_in dest_addr;
+    int dest_addr_len = sizeof(dest_addr);
+    memset(&dest_addr, 0, dest_addr_len);
+
+    struct onyx_socket_addr *o_addr = (struct onyx_socket_addr *) ONYX_PTR(params->data[3].of.i32);
+    dest_addr.sin_family = AF_INET; // TODO: See other comments related to AF_NET above.
+    dest_addr.sin_port = htons(o_addr->port);
+    dest_addr.sin_addr.s_addr = htonl(o_addr->addr);
+
+    // TODO: The flags at the end should be controllable.
+    int sent = sendto(params->data[0].of.i32, ONYX_PTR(params->data[1].of.i32), params->data[2].of.i32, MSG_NOSIGNAL, &dest_addr, dest_addr_len);
+    results->data[0] = WASM_I32_VAL(sent);
+    #endif
+    
+    return NULL;
+}
+
 ONYX_DEF(__net_recv, (WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
     *(i32 *) ONYX_PTR(params->data[3].of.i32) = 0;
 
@@ -968,6 +997,33 @@ ONYX_DEF(__net_recv, (WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
     return NULL;
 }
 
+ONYX_DEF(__net_recvfrom, (WASM_I32, WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
+    *(i32 *) ONYX_PTR(params->data[4].of.i32) = 0;
+
+    #ifdef _BH_LINUX
+    struct onyx_socket_addr *out_addr = (struct onyx_socket_addr *) ONYX_PTR(params->data[3].of.i32);
+
+    struct sockaddr_in client_addr;
+    int socket_len = sizeof(client_addr);
+    memset(&client_addr, 0, socket_len);
+
+    int received = recvfrom(params->data[0].of.i32, ONYX_PTR(params->data[1].of.i32), params->data[2].of.i32, 0, &client_addr, &socket_len);
+    out_addr->family = client_addr.sin_family;
+    out_addr->port   = ntohs(client_addr.sin_port);
+    out_addr->addr   = ntohl(client_addr.sin_addr.s_addr);
+
+    results->data[0] = WASM_I32_VAL(received);
+
+    if (received < 0) {
+        if (errno == EAGAIN || errno == EWOULDBLOCK) {
+            *(i32 *) ONYX_PTR(params->data[3].of.i32) = 1;
+        }
+    }
+    #endif
+
+    return NULL;
+}
+
 ONYX_DEF(__net_poll_recv, (WASM_I32, WASM_I32, WASM_I32, WASM_I32), (WASM_I32)) {
     #ifdef _BH_LINUX
     int i, res, cursor;
@@ -1106,10 +1162,10 @@ ONYX_LIBRARY {
     ONYX_FUNC(__net_accept)
     ONYX_FUNC(__net_connect)
     ONYX_FUNC(__net_send)
+    ONYX_FUNC(__net_sendto)
     ONYX_FUNC(__net_recv)
+    ONYX_FUNC(__net_recvfrom)
     ONYX_FUNC(__net_poll_recv)
-    ONYX_FUNC(__net_address_get_address)
-    ONYX_FUNC(__net_address_get_port)
 
     ONYX_FUNC(__cptr_make)
     ONYX_FUNC(__cptr_read)