From c402ac86060e66a5b127352d9f515c568242562d Mon Sep 17 00:00:00 2001 From: PePerRoNii Date: Wed, 11 Jun 2025 12:44:17 +0700 Subject: [PATCH 1/9] Add entry point in core:net as peer_endpoint --- core/net/socket.odin | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/net/socket.odin b/core/net/socket.odin index 801693962..ada7247e3 100644 --- a/core/net/socket.odin +++ b/core/net/socket.odin @@ -178,6 +178,13 @@ bound_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: Listen_E return _bound_endpoint(socket) } +/* + Returns the endpoint that the given socket is connected to. (Peer's endpoint) +*/ +peer_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: TCP_Recv_Error) { + return _peer_endpoint(socket) +} + accept_tcp :: proc(socket: TCP_Socket, options := DEFAULT_TCP_OPTIONS) -> (client: TCP_Socket, source: Endpoint, err: Accept_Error) { return _accept_tcp(socket, options) } From 5e11af96767f112f610526b702d7962f1e04978a Mon Sep 17 00:00:00 2001 From: PePerRoNii Date: Wed, 11 Jun 2025 12:50:20 +0700 Subject: [PATCH 2/9] added darwin implementation --- core/net/socket_darwin.odin | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/net/socket_darwin.odin b/core/net/socket_darwin.odin index e63f1844a..bb6480f76 100644 --- a/core/net/socket_darwin.odin +++ b/core/net/socket_darwin.odin @@ -149,6 +149,19 @@ _bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { return } +@(private) +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: TCP_Recv_Error) { + addr: posix.sockaddr_storage + addr_len := posix.socklen_t(size_of(addr)) + if posix.getpeername(posix.FD(any_socket_to_socket(sock)), (^posix.sockaddr)(&addr), &addr_len) != .OK { + err = _tcp_recv_error() + return + } + + ep = _sockaddr_to_endpoint(&addr) + return +} + @(private) _accept_tcp :: proc(sock: TCP_Socket, options := DEFAULT_TCP_OPTIONS) -> (client: TCP_Socket, source: Endpoint, err: Accept_Error) { addr: posix.sockaddr_storage From 7ba4427d52d201b6dd913395d6fb2eb94506ecf6 Mon Sep 17 00:00:00 2001 From: PePerRoNii Date: Wed, 11 Jun 2025 12:57:22 +0700 Subject: [PATCH 3/9] added windows implementation --- core/net/socket_windows.odin | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/net/socket_windows.odin b/core/net/socket_windows.odin index 4576149de..948ccfc5f 100644 --- a/core/net/socket_windows.odin +++ b/core/net/socket_windows.odin @@ -189,6 +189,20 @@ _bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { return } +@(private) +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: TCP_Recv_Error) { + sockaddr: win.SOCKADDR_STORAGE_LH + sockaddrlen := c.int(size_of(sockaddr)) + res := win.getpeername(win.SOCKET(any_socket_to_socket(sock)), &sockaddr, &sockaddrlen) + if res < 0 { + err = _tcp_recv_error() + return + } + + ep = _sockaddr_to_endpoint(&sockaddr) + return +} + @(private) _accept_tcp :: proc(sock: TCP_Socket, options := DEFAULT_TCP_OPTIONS) -> (client: TCP_Socket, source: Endpoint, err: Accept_Error) { for { From 297fdd4075c18c8102ef7a453bc10675cccef3a5 Mon Sep 17 00:00:00 2001 From: PePerRoNii Date: Wed, 11 Jun 2025 13:05:16 +0700 Subject: [PATCH 4/9] added freebsd implementation NOTE: bsd's tcp_recv_error does not cover all cases --- core/net/socket_freebsd.odin | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/net/socket_freebsd.odin b/core/net/socket_freebsd.odin index b510346ba..681d0e038 100644 --- a/core/net/socket_freebsd.odin +++ b/core/net/socket_freebsd.odin @@ -153,6 +153,20 @@ _bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { return } +@(private) +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: TCP_Recv_Error) { + sockaddr: freebsd.Socket_Address_Storage + + errno := freebsd.getpeername(cast(Fd)any_socket_to_socket(sock), &sockaddr) + if errno != nil { + err = _tcp_recv_error(errno) + return + } + + ep = _sockaddr_to_endpoint(&sockaddr) + return +} + @(private) _accept_tcp :: proc(sock: TCP_Socket, options := DEFAULT_TCP_OPTIONS) -> (client: TCP_Socket, source: Endpoint, err: Accept_Error) { sockaddr: freebsd.Socket_Address_Storage From a32ee6af97459ef9cf1f52df4f522a30abadec04 Mon Sep 17 00:00:00 2001 From: PePerRoNii Date: Wed, 11 Jun 2025 13:10:37 +0700 Subject: [PATCH 5/9] added linux implementation NOTE: tcp_recv_error doesn't cover all cases --- core/net/socket_linux.odin | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin index 3ec3521f0..b176fb848 100644 --- a/core/net/socket_linux.odin +++ b/core/net/socket_linux.odin @@ -230,6 +230,19 @@ _bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { return } +@(private) +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: TCP_Recv_Error) { + addr: linux.Sock_Addr_Any + errno := linux.getpeername(_unwrap_os_socket(sock), &addr) + if errno != .NONE { + err = _tcp_recv_error(errno) + return + } + + ep = _wrap_os_addr(addr) + return +} + @(private) _accept_tcp :: proc(sock: TCP_Socket, options := DEFAULT_TCP_OPTIONS) -> (tcp_client: TCP_Socket, endpoint: Endpoint, err: Accept_Error) { addr: linux.Sock_Addr_Any From f49bf1abd262a708886d7babf13100e7f1152de0 Mon Sep 17 00:00:00 2001 From: PePerRoNii Date: Sun, 15 Jun 2025 10:26:06 +0700 Subject: [PATCH 6/9] added Socket_Info_Errors Enum --- core/net/errors.odin | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/core/net/errors.odin b/core/net/errors.odin index 53c936a66..4853327b0 100644 --- a/core/net/errors.odin +++ b/core/net/errors.odin @@ -246,6 +246,23 @@ Shutdown_Error :: enum i32 { Unknown, } +Socket_Info_Error :: enum i32 { + None, + // No network connection, or the network stack is not initialized. + Network_Unreachable, + // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. + Insufficient_Resources, + // Socket is invalid or not connected, or the manner given is invalid. + Invalid_Argument, + // The socket is valid, but unsupported by this opperation. + Unsupported_Socket, + // Connection was closed/aborted/shutdown. + Connection_Closed, + + // An error unable to be categorized in above categories, `last_platform_error` may have more info. + Unknown, +} + Socket_Option_Error :: enum i32 { None, // No network connection, or the network stack is not initialized. From 42aa8ac383e5b5020ba12fab44193eca8a244ad8 Mon Sep 17 00:00:00 2001 From: PePerRoNii Date: Sun, 15 Jun 2025 11:17:49 +0700 Subject: [PATCH 7/9] Implemented _socket_info_error on peer_endpoint and bound_endpoint --- core/net/errors_darwin.odin | 17 +++++++++++++++++ core/net/errors_freebsd.odin | 18 ++++++++++++++++++ core/net/errors_linux.odin | 16 ++++++++++++++++ core/net/errors_windows.odin | 11 +++++++++++ core/net/socket.odin | 2 +- core/net/socket_darwin.odin | 8 ++++---- core/net/socket_freebsd.odin | 8 ++++---- core/net/socket_linux.odin | 8 ++++---- core/net/socket_windows.odin | 8 ++++---- 9 files changed, 79 insertions(+), 17 deletions(-) diff --git a/core/net/errors_darwin.odin b/core/net/errors_darwin.odin index 7aaa220e9..255bd351f 100644 --- a/core/net/errors_darwin.odin +++ b/core/net/errors_darwin.odin @@ -226,6 +226,23 @@ _shutdown_error :: proc() -> Shutdown_Error { } } +_socket_info_error :: proc() -> Socket_Info_Error { + #partial switch posix.errno() { + case .EBADF, .ENOTSOCK: + return .Invalid_Argument + case .ENOTCONN: + return .Network_Unreachable + case .EOPNOTSUPP: + return .Unsupported_Socket + case .EINVAL: + return .Connection_Closed + case .ENOBUFS: + return .Insufficient_Resources + case: + return .Unknown + } +} + _socket_option_error :: proc() -> Socket_Option_Error { #partial switch posix.errno() { case .ENOBUFS: diff --git a/core/net/errors_freebsd.odin b/core/net/errors_freebsd.odin index 707ffd0dd..05de41746 100644 --- a/core/net/errors_freebsd.odin +++ b/core/net/errors_freebsd.odin @@ -255,6 +255,24 @@ _shutdown_error :: proc(errno: freebsd.Errno) -> Shutdown_Error { } } +_socket_info_error :: proc(errno: freebsd.Errno) -> Socket_Info_Error { + assert(errno != nil) + _last_error = errno + + #partial switch errno { + case .EBADF, .ENOTSOCK, .EINVAL, .EFAULT: + return .Invalid_Argument + case .ENOTCONN: + return .Network_Unreachable + case .ECONNRESET: + return .Connection_Closed + case .ENOBUFS: + return .Insufficient_Resources + case: + return .Unknown + } +} + _socket_option_error :: proc(errno: freebsd.Errno) -> Socket_Option_Error { assert(errno != nil) _last_error = errno diff --git a/core/net/errors_linux.odin b/core/net/errors_linux.odin index 237579f28..258560595 100644 --- a/core/net/errors_linux.odin +++ b/core/net/errors_linux.odin @@ -258,6 +258,22 @@ _shutdown_error :: proc(errno: linux.Errno) -> Shutdown_Error { } } +_socket_info_error :: proc(errno: linux.Errno) -> Socket_Info_Error { + assert(errno != nil) + _last_error = errno + + #partial switch errno { + case .EBADF, .ENOTSOCK, .EFAULT, .EINVAL: + return .Invalid_Argument + case .ENOTCONN: + return .Network_Unreachable + case .ENOBUFS: + return .Insufficient_Resources + case: + return .Unknown + } +} + _socket_option_error :: proc(errno: linux.Errno) -> Socket_Option_Error { assert(errno != nil) _last_error = errno diff --git a/core/net/errors_windows.odin b/core/net/errors_windows.odin index b30046a17..8e0e4cda3 100644 --- a/core/net/errors_windows.odin +++ b/core/net/errors_windows.odin @@ -234,6 +234,17 @@ _shutdown_error :: proc() -> Shutdown_Error { } } +_socket_info_error :: proc() -> Socket_Info_Error { + #partial switch win.System_Error(win.WSAGetLastError()) { + case .WSAEFAULT, .WSAEINPROGRESS, .WSAENOTSOCK, .WSAEINVAL: + return .Invalid_Argument + case .WSANOTINITIALISED, .WSAENETDOWN, .WSAENOTCONN: + return .Network_Unreachable + case: + return .Unknown + } +} + _socket_option_error :: proc() -> Socket_Option_Error { #partial switch win.System_Error(win.WSAGetLastError()) { case .WSAENETDOWN, .WSANOTINITIALISED: diff --git a/core/net/socket.odin b/core/net/socket.odin index ada7247e3..988d47c86 100644 --- a/core/net/socket.odin +++ b/core/net/socket.odin @@ -174,7 +174,7 @@ listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (socket: TC /* Returns the endpoint that the given socket is listening / bound on. */ -bound_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: Listen_Error) { +bound_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: Socket_Info_Error) { return _bound_endpoint(socket) } diff --git a/core/net/socket_darwin.odin b/core/net/socket_darwin.odin index bb6480f76..fe4b4c3b5 100644 --- a/core/net/socket_darwin.odin +++ b/core/net/socket_darwin.odin @@ -137,11 +137,11 @@ _listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (skt: TCP_ } @(private) -_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { +_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { addr: posix.sockaddr_storage addr_len := posix.socklen_t(size_of(addr)) if posix.getsockname(posix.FD(any_socket_to_socket(sock)), (^posix.sockaddr)(&addr), &addr_len) != .OK { - err = _listen_error() + err = _socket_info_error() return } @@ -150,11 +150,11 @@ _bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { } @(private) -_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: TCP_Recv_Error) { +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { addr: posix.sockaddr_storage addr_len := posix.socklen_t(size_of(addr)) if posix.getpeername(posix.FD(any_socket_to_socket(sock)), (^posix.sockaddr)(&addr), &addr_len) != .OK { - err = _tcp_recv_error() + err = _socket_info_error() return } diff --git a/core/net/socket_freebsd.odin b/core/net/socket_freebsd.odin index 681d0e038..78bd1cdae 100644 --- a/core/net/socket_freebsd.odin +++ b/core/net/socket_freebsd.odin @@ -140,12 +140,12 @@ _listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (socket: T } @(private) -_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { +_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { sockaddr: freebsd.Socket_Address_Storage errno := freebsd.getsockname(cast(Fd)any_socket_to_socket(sock), &sockaddr) if errno != nil { - err = _listen_error(errno) + err = _socket_info_error(errno) return } @@ -154,12 +154,12 @@ _bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { } @(private) -_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: TCP_Recv_Error) { +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { sockaddr: freebsd.Socket_Address_Storage errno := freebsd.getpeername(cast(Fd)any_socket_to_socket(sock), &sockaddr) if errno != nil { - err = _tcp_recv_error(errno) + err = _socket_info_error(errno) return } diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin index b176fb848..bdb48fce8 100644 --- a/core/net/socket_linux.odin +++ b/core/net/socket_linux.odin @@ -218,11 +218,11 @@ _listen_tcp :: proc(endpoint: Endpoint, backlog := 1000) -> (socket: TCP_Socket, } @(private) -_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { +_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { addr: linux.Sock_Addr_Any errno := linux.getsockname(_unwrap_os_socket(sock), &addr) if errno != .NONE { - err = _listen_error(errno) + err = _socket_info_error(errno) return } @@ -231,11 +231,11 @@ _bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { } @(private) -_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: TCP_Recv_Error) { +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { addr: linux.Sock_Addr_Any errno := linux.getpeername(_unwrap_os_socket(sock), &addr) if errno != .NONE { - err = _tcp_recv_error(errno) + err = _socket_info_error(errno) return } diff --git a/core/net/socket_windows.odin b/core/net/socket_windows.odin index 948ccfc5f..cab820ed5 100644 --- a/core/net/socket_windows.odin +++ b/core/net/socket_windows.odin @@ -177,11 +177,11 @@ _listen_tcp :: proc(interface_endpoint: Endpoint, backlog := 1000) -> (socket: T } @(private) -_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { +_bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { sockaddr: win.SOCKADDR_STORAGE_LH sockaddrlen := c.int(size_of(sockaddr)) if win.getsockname(win.SOCKET(any_socket_to_socket(sock)), &sockaddr, &sockaddrlen) == win.SOCKET_ERROR { - err = _listen_error() + err = _socket_info_error() return } @@ -190,12 +190,12 @@ _bound_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Listen_Error) { } @(private) -_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: TCP_Recv_Error) { +_peer_endpoint :: proc(sock: Any_Socket) -> (ep: Endpoint, err: Socket_Info_Error) { sockaddr: win.SOCKADDR_STORAGE_LH sockaddrlen := c.int(size_of(sockaddr)) res := win.getpeername(win.SOCKET(any_socket_to_socket(sock)), &sockaddr, &sockaddrlen) if res < 0 { - err = _tcp_recv_error() + err = _socket_info_error() return } From c08d9c50c83f3b6c1aa1ea99667564448a911f23 Mon Sep 17 00:00:00 2001 From: PePerRoNii Date: Sun, 15 Jun 2025 12:14:59 +0700 Subject: [PATCH 8/9] Changed TCP_Recv_Err to Socket_Info_Err and tested on darwin_arm64 --- core/net/socket.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/net/socket.odin b/core/net/socket.odin index 988d47c86..f68508169 100644 --- a/core/net/socket.odin +++ b/core/net/socket.odin @@ -181,7 +181,7 @@ bound_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: Socket_I /* Returns the endpoint that the given socket is connected to. (Peer's endpoint) */ -peer_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: TCP_Recv_Error) { +peer_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: Socket_Info_Error) { return _peer_endpoint(socket) } From acdab793d920388541afec713bce0a7ec1120575 Mon Sep 17 00:00:00 2001 From: PePerRoNii Date: Mon, 16 Jun 2025 16:17:48 +0700 Subject: [PATCH 9/9] Added Socket_Info_Error to Network_Error union --- core/net/common.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/core/net/common.odin b/core/net/common.odin index fb6b17511..6d64a65d7 100644 --- a/core/net/common.odin +++ b/core/net/common.odin @@ -64,6 +64,7 @@ Network_Error :: union #shared_nil { UDP_Recv_Error, Shutdown_Error, Interfaces_Error, + Socket_Info_Error, Socket_Option_Error, Set_Blocking_Error, Parse_Endpoint_Error,