123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- #+build linux
- package net
- /*
- Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures.
- For other protocols and their features, see subdirectories of this package.
- */
- /*
- Copyright 2022 Tetralux <[email protected]>
- Copyright 2022 Colin Davidson <[email protected]>
- Copyright 2022 Jeroen van Rijn <[email protected]>.
- Copyright 2024 Feoramund <[email protected]>.
- Made available under Odin's BSD-3 license.
- List of contributors:
- Tetralux: Initial implementation
- Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
- Jeroen van Rijn: Cross platform unification, code style, documentation
- flysand: Move dependency from core:linux.Errno to core:sys/linux
- Feoramund: FreeBSD platform code
- */
- import "core:reflect"
- import "core:sys/linux"
- @(private="file", thread_local)
- _last_error: linux.Errno
- _last_platform_error :: proc() -> i32 {
- return i32(_last_error)
- }
- _last_platform_error_string :: proc() -> string {
- description, _ := reflect.enum_name_from_value(_last_error)
- return description
- }
- _set_last_platform_error :: proc(err: i32) {
- _last_error = linux.Errno(err)
- }
- _create_socket_error :: proc(errno: linux.Errno) -> Create_Socket_Error {
- assert(errno != nil)
- _last_error = errno
- #partial switch errno {
- case .EMFILE, .ENFILE, .ENOBUFS, .EPROTONOSUPPORT:
- return .Insufficient_Resources
- case .EAFNOSUPPORT, .EPROTOTYPE:
- return .Invalid_Argument
- case .EACCES, .EPERM:
- return .Insufficient_Permissions
- case:
- return .Unknown
- }
- }
- _dial_error :: proc(errno: linux.Errno) -> Dial_Error {
- assert(errno != nil)
- _last_error = errno
- #partial switch errno {
- case .EAGAIN:
- return .Insufficient_Resources
- case .EBADF, .EINVAL, .ENOTSOCK, .EADDRNOTAVAIL, .EAFNOSUPPORT, .EFAULT:
- return .Invalid_Argument
- case .EISCONN:
- return .Already_Connected
- case .EALREADY:
- return .Already_Connecting
- case .EADDRINUSE:
- return .Address_In_Use
- case .ENETUNREACH:
- return .Network_Unreachable
- case .EHOSTUNREACH:
- return .Host_Unreachable
- case .ECONNREFUSED:
- return .Refused
- case .ECONNRESET:
- return .Reset
- case .ETIMEDOUT:
- return .Timeout
- case .EINPROGRESS:
- return .Would_Block
- case .EINTR:
- return .Interrupted
- case .EACCES:
- return .Broadcast_Not_Supported
- case:
- return .Unknown
- }
- }
- _bind_error :: proc(errno: linux.Errno) -> Bind_Error {
- assert(errno != nil)
- _last_error = errno
- #partial switch errno {
- case .EAGAIN, .ENOTSOCK, .EADDRNOTAVAIL, .EAFNOSUPPORT, .EFAULT:
- return .Insufficient_Resources
- case .EINVAL:
- return .Already_Bound
- case .EBADF:
- return .Invalid_Argument
- case .EACCES:
- return .Insufficient_Permissions_For_Address
- case .EADDRINUSE:
- return .Address_In_Use
- case:
- return .Unknown
- }
- }
- _listen_error :: proc(errno: linux.Errno) -> Listen_Error {
- assert(errno != nil)
- _last_error = errno
- #partial switch errno {
- case .EBADF, .ENOTSOCK:
- return .Invalid_Argument
- case .EDESTADDRREQ, .EOPNOTSUPP:
- return .Unsupported_Socket
- case .EINVAL:
- return .Already_Connected
- case:
- return .Unknown
- }
- }
- _accept_error :: proc(errno: linux.Errno) -> Accept_Error {
- assert(errno != nil)
- _last_error = errno
- #partial switch errno {
- case .EMFILE, .ENFILE, .ENOBUFS, .ENOMEM:
- return .Insufficient_Resources
- case .EBADF, .ENOTSOCK, .EFAULT:
- return .Invalid_Argument
- case .EINVAL:
- return .Not_Listening
- case .ECONNABORTED:
- return .Aborted
- case .EWOULDBLOCK:
- return .Would_Block
- case .EINTR:
- return .Interrupted
- case:
- return .Unknown
- }
- }
- _tcp_recv_error :: proc(errno: linux.Errno) -> TCP_Recv_Error {
- assert(errno != nil)
- _last_error = errno
- #partial switch errno {
- case .EBADF, .ENOTSOCK, .EFAULT:
- return .Invalid_Argument
- case .ENOTCONN:
- return .Not_Connected
- case .ECONNREFUSED, .ECONNRESET:
- return .Connection_Closed
- case .ETIMEDOUT:
- return .Timeout
- case .EAGAIN:
- return .Would_Block
- case .EINTR:
- return .Interrupted
- case:
- return .Unknown
- }
- }
- _udp_recv_error :: proc(errno: linux.Errno) -> UDP_Recv_Error {
- assert(errno != nil)
- _last_error = errno
- #partial switch errno {
- case .EBADF, .ENOTSOCK, .EFAULT:
- return .Invalid_Argument
- case .ECONNREFUSED, .ENOTCONN, .ECONNRESET:
- return .Connection_Refused
- case .ETIMEDOUT:
- return .Timeout
- case .EAGAIN:
- return .Would_Block
- case .EINTR:
- return .Interrupted
- case:
- return .Unknown
- }
- }
- _tcp_send_error :: proc(errno: linux.Errno) -> TCP_Send_Error {
- assert(errno != nil)
- _last_error = errno
- #partial switch errno {
- case .EBADF, .EACCES, .ENOTSOCK, .EFAULT, .EMSGSIZE, .EDESTADDRREQ, .EINVAL, .EISCONN, .EOPNOTSUPP:
- return .Invalid_Argument
- case .ENOBUFS, .ENOMEM:
- return .Insufficient_Resources
- case .ECONNRESET, .EPIPE:
- return .Connection_Closed
- case .ENOTCONN:
- return .Not_Connected
- case .EHOSTUNREACH:
- return .Host_Unreachable
- case .EHOSTDOWN:
- return .Host_Unreachable
- case .ENETDOWN:
- return .Network_Unreachable
- case .EAGAIN:
- return .Would_Block
- case .EINTR:
- return .Interrupted
- case:
- return .Unknown
- }
- }
- _udp_send_error :: proc(errno: linux.Errno) -> UDP_Send_Error {
- assert(errno != nil)
- _last_error = errno
- #partial switch errno {
- case .EBADF, .EACCES, .ENOTSOCK, .EFAULT, .EMSGSIZE, .EDESTADDRREQ, .EINVAL, .EISCONN, .EOPNOTSUPP:
- return .Invalid_Argument
- case .ENOBUFS, .ENOMEM:
- return .Insufficient_Resources
- case .ECONNRESET, .EPIPE:
- return .Connection_Refused
- case .EHOSTUNREACH:
- return .Host_Unreachable
- case .EHOSTDOWN:
- return .Host_Unreachable
- case .ENETDOWN:
- return .Network_Unreachable
- case .EAGAIN:
- return .Would_Block
- case .EINTR:
- return .Interrupted
- case:
- return .Unknown
- }
- }
- _shutdown_error :: proc(errno: linux.Errno) -> Shutdown_Error {
- assert(errno != nil)
- _last_error = errno
- #partial switch errno {
- case .EBADF, .EINVAL, .ENOTSOCK, .ENOTCONN:
- return .Invalid_Argument
- case:
- return .Unknown
- }
- }
- _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
- #partial switch errno {
- case .ENOMEM, .ENOBUFS:
- return .Insufficient_Resources
- case .EBADF, .ENOTSOCK:
- return .Invalid_Socket
- case .ENOPROTOOPT, .EINVAL:
- return .Invalid_Option
- case .EFAULT, .EDOM:
- return .Invalid_Value
- case:
- return .Unknown
- }
- }
- _set_blocking_error :: proc(errno: linux.Errno) -> Set_Blocking_Error {
- assert(errno != nil)
- _last_error = errno
- #partial switch errno {
- case .EBADF:
- return .Invalid_Argument
- case:
- return .Unknown
- }
- }
|