Apply #shared_nil to Network_Error

This commit is contained in:
Jeroen van Rijn
2023-03-04 10:39:20 +01:00
parent 38ea140b3f
commit e254581a1b
4 changed files with 41 additions and 33 deletions

View File

@@ -404,16 +404,10 @@ Host_Or_Endpoint :: union {
Host,
Endpoint,
}
Parse_Endpoint_Error :: enum {
None = 0,
Bad_Port = 1,
Bad_Address,
Bad_Hostname,
}
// Takes a string consisting of a hostname or IP address, and an optional port,
// and return the component parts in a useful form.
parse_hostname_or_endpoint :: proc(endpoint_str: string) -> (target: Host_Or_Endpoint, err: Network_Error) {
parse_hostname_or_endpoint :: proc(endpoint_str: string) -> (target: Host_Or_Endpoint, err: Parse_Endpoint_Error) {
host, port, port_ok := split_port(endpoint_str)
if !port_ok {
return nil, .Bad_Port

View File

@@ -50,23 +50,7 @@ ODIN_NET_TCP_NODELAY_DEFAULT :: #config(ODIN_NET_TCP_NODELAY_DEFAULT, true)
// COMMON DEFINITIONS
Maybe :: runtime.Maybe
General_Error :: enum {
Unable_To_Enumerate_Network_Interfaces = 1,
}
// `Platform_Error` is used to wrap errors returned by the different platforms that don't fit a common error.
Platform_Error :: enum u32 {}
/*
NOTE(tetra): Enums in Network_Error should not have a named zero value.
If you have a proc that returns an enum with an Ok=0 value, using or_return from the callsite, when the caller returns a union, works as expected.
However, if that proc returns the union directly, returning the Ok value will NOT work with the caller's or_return, as it will treat Error{.Ok} as != nil, and early-return with it.
The approach currently taken to avoid this is:
- Remove the named zero values for the enums
- Use the union everywhere
*/
Network_Error :: union {
Network_Error :: union #shared_nil {
General_Error,
Platform_Error,
Create_Socket_Error,
@@ -85,11 +69,27 @@ Network_Error :: union {
DNS_Error,
}
Resolve_Error :: enum {
General_Error :: enum u32 {
None = 0,
Unable_To_Enumerate_Network_Interfaces = 1,
}
// `Platform_Error` is used to wrap errors returned by the different platforms that don't fit a common error.
Platform_Error :: enum u32 {}
Parse_Endpoint_Error :: enum {
None = 0,
Bad_Port = 1,
Bad_Address,
Bad_Hostname,
}
Resolve_Error :: enum u32 {
None = 0,
Unable_To_Resolve = 1,
}
DNS_Error :: enum {
DNS_Error :: enum u32 {
Invalid_Hostname_Error = 1,
Invalid_Hosts_Config_Error,
Invalid_Resolv_Config_Error,

View File

@@ -22,6 +22,7 @@ import "core:c"
import win "core:sys/windows"
Create_Socket_Error :: enum c.int {
None = 0,
Network_Subsystem_Failure = win.WSAENETDOWN,
Family_Not_Supported_For_This_Socket = win.WSAEAFNOSUPPORT,
No_Socket_Descriptors_Available = win.WSAEMFILE,
@@ -32,6 +33,7 @@ Create_Socket_Error :: enum c.int {
}
Dial_Error :: enum c.int {
None = 0,
Port_Required = -1,
Address_In_Use = win.WSAEADDRINUSE,
In_Progress = win.WSAEALREADY,
@@ -49,6 +51,7 @@ Dial_Error :: enum c.int {
}
Bind_Error :: enum c.int {
None = 0,
Address_In_Use = win.WSAEADDRINUSE, // Another application is currently bound to this endpoint.
Given_Nonlocal_Address = win.WSAEADDRNOTAVAIL, // The address is not a local address on this machine.
Broadcast_Disabled = win.WSAEACCES, // To bind a UDP socket to the broadcast address, the appropriate socket option must be set.
@@ -58,6 +61,7 @@ Bind_Error :: enum c.int {
}
Listen_Error :: enum c.int {
None = 0,
Address_In_Use = win.WSAEADDRINUSE,
Already_Connected = win.WSAEISCONN,
No_Socket_Descriptors_Available = win.WSAEMFILE,
@@ -68,6 +72,7 @@ Listen_Error :: enum c.int {
}
Accept_Error :: enum c.int {
None = 0,
Not_Listening = win.WSAEINVAL,
No_Socket_Descriptors_Available_For_Client_Socket = win.WSAEMFILE,
No_Buffer_Space_Available = win.WSAENOBUFS,
@@ -79,6 +84,7 @@ Accept_Error :: enum c.int {
}
TCP_Recv_Error :: enum c.int {
None = 0,
Network_Subsystem_Failure = win.WSAENETDOWN,
Not_Connected = win.WSAENOTCONN,
Bad_Buffer = win.WSAEFAULT,
@@ -99,6 +105,7 @@ TCP_Recv_Error :: enum c.int {
}
UDP_Recv_Error :: enum c.int {
None = 0,
Network_Subsystem_Failure = win.WSAENETDOWN,
// TODO: not functionally different from Reset; merge?
@@ -124,6 +131,7 @@ UDP_Recv_Error :: enum c.int {
// TODO: consider merging some errors to make handling them easier
// TODO: verify once more what errors to actually expose
TCP_Send_Error :: enum c.int {
None = 0,
// TODO: not functionally different from Reset; merge?
Aborted = win.WSAECONNABORTED,
@@ -148,6 +156,7 @@ TCP_Send_Error :: enum c.int {
}
UDP_Send_Error :: enum c.int {
None = 0,
Network_Subsystem_Failure = win.WSAENETDOWN,
// TODO: not functionally different from Reset; merge?
@@ -181,6 +190,7 @@ Shutdown_Manner :: enum c.int {
}
Shutdown_Error :: enum c.int {
None = 0,
Aborted = win.WSAECONNABORTED,
Reset = win.WSAECONNRESET,
Offline = win.WSAENETDOWN,
@@ -237,6 +247,7 @@ Socket_Option :: enum c.int {
}
Socket_Option_Error :: enum c.int {
None = 0,
Linger_Only_Supports_Whole_Seconds = 1,
// The given value is too big or small to be given to the OS.

View File

@@ -374,17 +374,19 @@ tcp_tests :: proc(t: ^testing.T) {
}
tcp_client :: proc(retval: rawptr) {
r := transmute(^Thread_Data)retval
send :: proc(content: []u8) -> (err: net.Network_Error) {
skt := net.dial_tcp(ENDPOINT) or_return
defer net.close(skt)
if r.skt, r.err = net.dial_tcp(ENDPOINT); r.err != nil {
net.set_option(skt, .Send_Timeout, SEND_TIMEOUT)
net.set_option(skt, .Receive_Timeout, RECV_TIMEOUT)
_, err = net.send(skt, content)
return
}
defer net.close(r.skt)
net.set_option(r.skt, .Send_Timeout, SEND_TIMEOUT)
net.set_option(r.skt, .Receive_Timeout, RECV_TIMEOUT)
_, r.err = net.send(r.skt.(net.TCP_Socket), transmute([]u8)CONTENT)
r := transmute(^Thread_Data)retval
r.err = send(transmute([]u8)CONTENT)
return
}
@@ -407,6 +409,7 @@ tcp_server :: proc(retval: rawptr) {
}
defer net.close(client)
r.length, r.err = net.recv_tcp(client, r.data[:])
return
}