aboutsummaryrefslogtreecommitdiff
path: root/core/net/errors_darwin.odin
blob: c80d2cf560d743b387b377ce4ced25ee1a9679a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package net
// +build darwin

/*
	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        <tetraluxonpc@gmail.com>
	Copyright 2022 Colin Davidson  <colrdavidson@gmail.com>
	Copyright 2022 Jeroen van Rijn <nom@duclavier.com>.
	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
*/

import "core:c"
import "core:os"

Create_Socket_Error :: enum c.int {
	None                                 = 0,
	Family_Not_Supported_For_This_Socket = c.int(os.EAFNOSUPPORT),
	No_Socket_Descriptors_Available      = c.int(os.EMFILE),
	No_Buffer_Space_Available            = c.int(os.ENOBUFS),
	No_Memory_Available_Available        = c.int(os.ENOMEM),
	Protocol_Unsupported_By_System       = c.int(os.EPROTONOSUPPORT),
	Wrong_Protocol_For_Socket            = c.int(os.EPROTONOSUPPORT),
	Family_And_Socket_Type_Mismatch      = c.int(os.EPROTONOSUPPORT),
}

Dial_Error :: enum c.int {
	None                      = 0,
	Port_Required             = -1,

	Address_In_Use            = c.int(os.EADDRINUSE),
	In_Progress               = c.int(os.EINPROGRESS),
	Cannot_Use_Any_Address    = c.int(os.EADDRNOTAVAIL),
	Wrong_Family_For_Socket   = c.int(os.EAFNOSUPPORT),
	Refused                   = c.int(os.ECONNREFUSED),
	Is_Listening_Socket       = c.int(os.EACCES),
	Already_Connected         = c.int(os.EISCONN),
	Network_Unreachable       = c.int(os.ENETUNREACH),  // Device is offline
	Host_Unreachable          = c.int(os.EHOSTUNREACH), // Remote host cannot be reached
	No_Buffer_Space_Available = c.int(os.ENOBUFS),
	Not_Socket                = c.int(os.ENOTSOCK),
	Timeout                   = c.int(os.ETIMEDOUT),

	// TODO: we may need special handling for this; maybe make a socket a struct with metadata?
	Would_Block               = c.int(os.EWOULDBLOCK), 
}

Bind_Error :: enum c.int {
	None                    = 0,
	Address_In_Use          = c.int(os.EADDRINUSE),    // Another application is currently bound to this endpoint.
	Given_Nonlocal_Address  = c.int(os.EADDRNOTAVAIL), // The address is not a local address on this machine.
	Broadcast_Disabled      = c.int(os.EACCES),        // To bind a UDP socket to the broadcast address, the appropriate socket option must be set.
	Address_Family_Mismatch = c.int(os.EFAULT),        // The address family of the address does not match that of the socket.
	Already_Bound           = c.int(os.EINVAL),        // The socket is already bound to an address.
	No_Ports_Available      = c.int(os.ENOBUFS),       // There are not enough ephemeral ports available.
}

Listen_Error :: enum c.int {
	None                                    = 0,
	Address_In_Use                          = c.int(os.EADDRINUSE),
	Already_Connected                       = c.int(os.EISCONN),
	No_Socket_Descriptors_Available         = c.int(os.EMFILE),
	No_Buffer_Space_Available               = c.int(os.ENOBUFS),
	Nonlocal_Address                        = c.int(os.EADDRNOTAVAIL),
	Not_Socket                              = c.int(os.ENOTSOCK),
	Listening_Not_Supported_For_This_Socket = c.int(os.EOPNOTSUPP),
}

Accept_Error :: enum c.int {
	None                                              = 0,
	// TODO(tetra): Is this error actually possible here? Or is like Linux, in which case we can remove it.
	Reset                                             = c.int(os.ECONNRESET), 
	Not_Listening                                     = c.int(os.EINVAL),
	No_Socket_Descriptors_Available_For_Client_Socket = c.int(os.EMFILE),
	No_Buffer_Space_Available                         = c.int(os.ENOBUFS),
	Not_Socket                                        = c.int(os.ENOTSOCK),
	Not_Connection_Oriented_Socket                    = c.int(os.EOPNOTSUPP),

	// TODO: we may need special handling for this; maybe make a socket a struct with metadata?
	Would_Block                                       = c.int(os.EWOULDBLOCK), 
}

TCP_Recv_Error :: enum c.int {
	None              = 0,
	Shutdown          = c.int(os.ESHUTDOWN),
	Not_Connected     = c.int(os.ENOTCONN),

	// TODO(tetra): Is this error actually possible here?
	Connection_Broken = c.int(os.ENETRESET),
	Not_Socket        = c.int(os.ENOTSOCK),
	Aborted           = c.int(os.ECONNABORTED),

	// TODO(tetra): Determine when this is different from the syscall returning n=0 and maybe normalize them?
	Connection_Closed = c.int(os.ECONNRESET),
	Offline           = c.int(os.ENETDOWN),
	Host_Unreachable  = c.int(os.EHOSTUNREACH),
	Interrupted       = c.int(os.EINTR),

	// NOTE: No, really. Presumably this means something different for nonblocking sockets...
	Timeout           = c.int(os.EWOULDBLOCK),
}

UDP_Recv_Error :: enum c.int {
	None             = 0,
	Buffer_Too_Small = c.int(os.EMSGSIZE), // The buffer is too small to fit the entire message, and the message was truncated. When this happens, the rest of message is lost.
	Not_Socket       = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
	Not_Descriptor   = c.int(os.EBADF),    // The so-called socket is, in fact, not even a valid descriptor.
	Bad_Buffer       = c.int(os.EFAULT),   // The buffer did not point to a valid location in memory.
	Interrupted      = c.int(os.EINTR),    // A signal occurred before any data was transmitted. See signal(7).

	// The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
	// NOTE: No, really. Presumably this means something different for nonblocking sockets...
	Timeout          = c.int(os.EWOULDBLOCK), 
	Socket_Not_Bound = c.int(os.EINVAL), // The socket must be bound for this operation, but isn't.
}

TCP_Send_Error :: enum c.int {
	None                      = 0,

	Aborted                   = c.int(os.ECONNABORTED), 
	Connection_Closed         = c.int(os.ECONNRESET),
	Not_Connected             = c.int(os.ENOTCONN),
	Shutdown                  = c.int(os.ESHUTDOWN),

	// The send queue was full.
	// This is usually a transient issue.
	//
	// This also shouldn't normally happen on Linux, as data is dropped if it
	// doesn't fit in the send queue.
	No_Buffer_Space_Available = c.int(os.ENOBUFS),
	Offline                   = c.int(os.ENETDOWN),
	Host_Unreachable          = c.int(os.EHOSTUNREACH),
	Interrupted               = c.int(os.EINTR), // A signal occurred before any data was transmitted. See signal(7).

	// NOTE: No, really. Presumably this means something different for nonblocking sockets...
	// The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
	Timeout                   = c.int(os.EWOULDBLOCK), 
	Not_Socket                = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
}

// TODO
UDP_Send_Error :: enum c.int {
	None                        = 0,
	Message_Too_Long            = c.int(os.EMSGSIZE), // The message is larger than the maximum UDP packet size. No data was sent.

	// TODO: not sure what the exact circumstances for this is yet
	Network_Unreachable         = c.int(os.ENETUNREACH),
	No_Outbound_Ports_Available = c.int(os.EAGAIN),   // There are no more emphemeral outbound ports available to bind the socket to, in order to send.

	// The send timeout duration passed before all data was sent. See Socket_Option.Send_Timeout.
	// NOTE: No, really. Presumably this means something different for nonblocking sockets...
	Timeout                     = c.int(os.EWOULDBLOCK), 
	Not_Socket                  = c.int(os.ENOTSOCK), // The so-called socket is not an open socket.
	Not_Descriptor              = c.int(os.EBADF),    // The so-called socket is, in fact, not even a valid descriptor.
	Bad_Buffer                  = c.int(os.EFAULT),   // The buffer did not point to a valid location in memory.
	Interrupted                 = c.int(os.EINTR),    // A signal occurred before any data was transmitted. See signal(7).

	// The send queue was full.
	// This is usually a transient issue.
	//
	// This also shouldn't normally happen on Linux, as data is dropped if it
	// doesn't fit in the send queue.
	No_Buffer_Space_Available   = c.int(os.ENOBUFS),
	No_Memory_Available         = c.int(os.ENOMEM),   // No memory was available to properly manage the send queue.
}

Shutdown_Manner :: enum c.int {
	Receive = c.int(os.SHUT_RD),
	Send    = c.int(os.SHUT_WR),
	Both    = c.int(os.SHUT_RDWR),
}

Shutdown_Error :: enum c.int {
	None           = 0,
	Aborted        = c.int(os.ECONNABORTED),
	Reset          = c.int(os.ECONNRESET),
	Offline        = c.int(os.ENETDOWN),
	Not_Connected  = c.int(os.ENOTCONN),
	Not_Socket     = c.int(os.ENOTSOCK),
	Invalid_Manner = c.int(os.EINVAL),
}

Socket_Option_Error :: enum c.int {
	None                       = 0,
	Offline                    = c.int(os.ENETDOWN),
	Timeout_When_Keepalive_Set = c.int(os.ENETRESET),
	Invalid_Option_For_Socket  = c.int(os.ENOPROTOOPT),
	Reset_When_Keepalive_Set   = c.int(os.ENOTCONN),
	Not_Socket                 = c.int(os.ENOTSOCK),
}

Set_Blocking_Error :: enum c.int {
	None = 0,

	// TODO: Add errors for `set_blocking`
}