common.odin 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. // +build windows, linux, darwin
  2. package net
  3. /*
  4. Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures.
  5. For other protocols and their features, see subdirectories of this package.
  6. This file collects structs, enums and settings applicable to the entire package in one handy place.
  7. Platform-specific ones can be found in their respective `*_windows.odin` and similar files.
  8. */
  9. /*
  10. Copyright 2022 Tetralux <[email protected]>
  11. Copyright 2022 Colin Davidson <[email protected]>
  12. Copyright 2022 Jeroen van Rijn <[email protected]>.
  13. Made available under Odin's BSD-3 license.
  14. List of contributors:
  15. Tetralux: Initial implementation
  16. Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
  17. Jeroen van Rijn: Cross platform unification, code style, documentation
  18. */
  19. import "base:runtime"
  20. /*
  21. TUNEABLES - See also top of `dns.odin` for DNS configuration.
  22. Determines the default value for whether dial_tcp() and accept_tcp() will set TCP_NODELAY on the new
  23. socket, and the client socket, respectively.
  24. This can also be set on a per-socket basis using the 'options' optional parameter to those procedures.
  25. When TCP_NODELAY is set, data will be sent out to the peer as quickly as possible, rather than being
  26. coalesced into fewer network packets.
  27. This makes the networking layer more eagerly send data when you ask it to,
  28. which can reduce latency by up to 200ms.
  29. This does mean that a lot of small writes will negatively effect throughput however,
  30. since the Nagle algorithm will be disabled, and each write becomes one
  31. IP packet. This will increase traffic by a factor of 40, with IP and TCP
  32. headers for each payload.
  33. However, you can avoid this by buffering things up yourself if you wish to send a lot of
  34. short data chunks, when TCP_NODELAY is enabled on that socket.
  35. */
  36. ODIN_NET_TCP_NODELAY_DEFAULT :: #config(ODIN_NET_TCP_NODELAY_DEFAULT, true)
  37. // COMMON DEFINITIONS
  38. Maybe :: runtime.Maybe
  39. Network_Error :: union #shared_nil {
  40. General_Error,
  41. Platform_Error,
  42. Create_Socket_Error,
  43. Dial_Error,
  44. Listen_Error,
  45. Accept_Error,
  46. Bind_Error,
  47. TCP_Send_Error,
  48. UDP_Send_Error,
  49. TCP_Recv_Error,
  50. UDP_Recv_Error,
  51. Shutdown_Error,
  52. Socket_Option_Error,
  53. Set_Blocking_Error,
  54. Parse_Endpoint_Error,
  55. Resolve_Error,
  56. DNS_Error,
  57. }
  58. General_Error :: enum u32 {
  59. None = 0,
  60. Unable_To_Enumerate_Network_Interfaces = 1,
  61. }
  62. // `Platform_Error` is used to wrap errors returned by the different platforms that don't fit a common error.
  63. Platform_Error :: enum u32 {}
  64. Parse_Endpoint_Error :: enum {
  65. None = 0,
  66. Bad_Port = 1,
  67. Bad_Address,
  68. Bad_Hostname,
  69. }
  70. Resolve_Error :: enum u32 {
  71. None = 0,
  72. Unable_To_Resolve = 1,
  73. }
  74. DNS_Error :: enum u32 {
  75. Invalid_Hostname_Error = 1,
  76. Invalid_Hosts_Config_Error,
  77. Invalid_Resolv_Config_Error,
  78. Connection_Error,
  79. Server_Error,
  80. System_Error,
  81. }
  82. // SOCKET OPTIONS & DEFINITIONS
  83. TCP_Options :: struct {
  84. no_delay: bool,
  85. }
  86. default_tcp_options := TCP_Options {
  87. no_delay = ODIN_NET_TCP_NODELAY_DEFAULT,
  88. }
  89. /*
  90. To allow freely using `Socket` in your own data structures in a cross-platform manner,
  91. we treat it as a handle large enough to accomodate OS-specific notions of socket handles.
  92. The platform code will perform the cast so you don't have to.
  93. */
  94. Socket :: distinct i64
  95. TCP_Socket :: distinct Socket
  96. UDP_Socket :: distinct Socket
  97. Socket_Protocol :: enum {
  98. TCP,
  99. UDP,
  100. }
  101. Any_Socket :: union {
  102. TCP_Socket,
  103. UDP_Socket,
  104. }
  105. /*
  106. ADDRESS DEFINITIONS
  107. */
  108. IP4_Address :: distinct [4]u8
  109. IP6_Address :: distinct [8]u16be
  110. Address :: union {IP4_Address, IP6_Address}
  111. IP4_Loopback := IP4_Address{127, 0, 0, 1}
  112. IP6_Loopback := IP6_Address{0, 0, 0, 0, 0, 0, 0, 1}
  113. IP4_Any := IP4_Address{}
  114. IP6_Any := IP6_Address{}
  115. Endpoint :: struct {
  116. address: Address,
  117. port: int,
  118. }
  119. Address_Family :: enum {
  120. IP4,
  121. IP6,
  122. }
  123. Netmask :: distinct Address
  124. /*
  125. INTERFACE / LINK STATE
  126. */
  127. Network_Interface :: struct {
  128. adapter_name: string, // On Windows this is a GUID that we could parse back into its u128 for more compact storage.
  129. friendly_name: string,
  130. description: string,
  131. dns_suffix: string,
  132. physical_address: string, // MAC address, etc.
  133. mtu: u32,
  134. unicast: [dynamic]Lease,
  135. multicast: [dynamic]Address,
  136. anycast: [dynamic]Address,
  137. gateways: [dynamic]Address,
  138. dhcp_v4: Address,
  139. dhcp_v6: Address,
  140. tunnel_type: Tunnel_Type,
  141. link: struct {
  142. state: Link_State,
  143. transmit_speed: u64,
  144. receive_speed: u64,
  145. },
  146. }
  147. // Empty bit set is unknown state.
  148. Link_States :: enum u32 {
  149. Up = 1,
  150. Down = 2,
  151. Testing = 3,
  152. Dormant = 4,
  153. Not_Present = 5,
  154. Lower_Layer_Down = 6,
  155. Loopback = 7,
  156. }
  157. Link_State :: bit_set[Link_States; u32]
  158. Lease :: struct {
  159. address: Address,
  160. netmask: Netmask,
  161. lifetime: struct {
  162. valid: u32,
  163. preferred: u32,
  164. lease: u32,
  165. },
  166. origin: struct {
  167. prefix: Prefix_Origin,
  168. suffix: Suffix_Origin,
  169. },
  170. address_duplication: Address_Duplication,
  171. }
  172. Tunnel_Type :: enum i32 {
  173. None = 0,
  174. Other = 1,
  175. Direct = 2,
  176. IPv4_To_IPv6 = 11,
  177. ISA_TAP = 13,
  178. Teredo = 14,
  179. IP_HTTPS = 15,
  180. }
  181. Prefix_Origin :: enum i32 {
  182. Other = 0,
  183. Manual = 1,
  184. Well_Known = 2,
  185. DHCP = 3,
  186. Router_Advertisement = 4,
  187. Unchanged = 16,
  188. }
  189. Suffix_Origin :: enum i32 {
  190. Other = 0,
  191. Manual = 1,
  192. Well_Known = 2,
  193. DHCP = 3,
  194. Link_Layer_Address = 4,
  195. Random = 5,
  196. Unchanged = 16,
  197. }
  198. Address_Duplication :: enum i32 {
  199. Invalid = 0,
  200. Tentative = 1,
  201. Duplicate = 2,
  202. Deprecated = 3,
  203. Preferred = 4,
  204. }
  205. // DNS DEFINITIONS
  206. DNS_Configuration :: struct {
  207. // Configuration files.
  208. resolv_conf: string,
  209. hosts_file: string,
  210. // TODO: Allow loading these up with `reload_configuration()` call or the like,
  211. // so we don't have to do it each call.
  212. name_servers: []Endpoint,
  213. hosts_file_entries: []DNS_Record,
  214. }
  215. DNS_Record_Type :: enum u16 {
  216. DNS_TYPE_A = 0x1, // IP4 address.
  217. DNS_TYPE_NS = 0x2, // IP6 address.
  218. DNS_TYPE_CNAME = 0x5, // Another host name.
  219. DNS_TYPE_MX = 0xf, // Arbitrary binary data or text.
  220. DNS_TYPE_AAAA = 0x1c, // Address of a name (DNS) server.
  221. DNS_TYPE_TEXT = 0x10, // Address and preference priority of a mail exchange server.
  222. DNS_TYPE_SRV = 0x21, // Address, port, priority, and weight of a host that provides a particular service.
  223. IP4 = DNS_TYPE_A,
  224. IP6 = DNS_TYPE_AAAA,
  225. CNAME = DNS_TYPE_CNAME,
  226. TXT = DNS_TYPE_TEXT,
  227. NS = DNS_TYPE_NS,
  228. MX = DNS_TYPE_MX,
  229. SRV = DNS_TYPE_SRV,
  230. }
  231. // Base DNS Record. All DNS responses will carry a hostname and TTL (time to live) field.
  232. DNS_Record_Base :: struct {
  233. record_name: string,
  234. ttl_seconds: u32, // The time in seconds that this service will take to update, after the record is updated.
  235. }
  236. // An IP4 address that the domain name maps to. There can be any number of these.
  237. DNS_Record_IP4 :: struct {
  238. using base: DNS_Record_Base,
  239. address: IP4_Address,
  240. }
  241. // An IPv6 address that the domain name maps to. There can be any number of these.
  242. DNS_Record_IP6 :: struct {
  243. using base: DNS_Record_Base,
  244. address: IP6_Address,
  245. }
  246. /*
  247. Another domain name that the domain name maps to.
  248. Domains can be pointed to another domain instead of directly to an IP address.
  249. `get_dns_records` will recursively follow these if you request this type of record.
  250. */
  251. DNS_Record_CNAME :: struct {
  252. using base: DNS_Record_Base,
  253. host_name: string,
  254. }
  255. /*
  256. Arbitrary string data that is associated with the domain name.
  257. Commonly of the form `key=value` to be parsed, though there is no specific format for them.
  258. These can be used for any purpose.
  259. */
  260. DNS_Record_TXT :: struct {
  261. using base: DNS_Record_Base,
  262. value: string,
  263. }
  264. /*
  265. Domain names of other DNS servers that are associated with the domain name.
  266. TODO(tetra): Expand on what these records are used for, and when you should use pay attention to these.
  267. */
  268. DNS_Record_NS :: struct {
  269. using base: DNS_Record_Base,
  270. host_name: string,
  271. }
  272. // Domain names for email servers that are associated with the domain name.
  273. // These records also have values which ranks them in the order they should be preferred. Lower is more-preferred.
  274. DNS_Record_MX :: struct {
  275. using base: DNS_Record_Base,
  276. host_name: string,
  277. preference: int,
  278. }
  279. /*
  280. An endpoint for a service that is available through the domain name.
  281. This is the way to discover the services that a domain name provides.
  282. Clients MUST attempt to contact the host with the lowest priority that they can reach.
  283. If two hosts have the same priority, they should be contacted in the order according to their weight.
  284. Hosts with larger weights should have a proportionally higher chance of being contacted by clients.
  285. A weight of zero indicates a very low weight, or, when there is no choice (to reduce visual noise).
  286. The host may be "." to indicate that it is "decidedly not available" on this domain.
  287. */
  288. DNS_Record_SRV :: struct {
  289. // base contains the full name of this record.
  290. // e.g: _sip._tls.example.com
  291. using base: DNS_Record_Base,
  292. // The hostname or address where this service can be found.
  293. target: string,
  294. // The port on which this service can be found.
  295. port: int,
  296. service_name: string, // NOTE(tetra): These are substrings of 'record_name'
  297. protocol_name: string, // NOTE(tetra): These are substrings of 'record_name'
  298. // Lower is higher priority
  299. priority: int,
  300. // Relative weight of this host compared to other of same priority; the chance of using this host should be proporitional to this weight.
  301. // The number of seconds that it will take to update the record.
  302. weight: int,
  303. }
  304. DNS_Record :: union {
  305. DNS_Record_IP4,
  306. DNS_Record_IP6,
  307. DNS_Record_CNAME,
  308. DNS_Record_TXT,
  309. DNS_Record_NS,
  310. DNS_Record_MX,
  311. DNS_Record_SRV,
  312. }
  313. DNS_Response_Code :: enum u16be {
  314. No_Error,
  315. Format_Error,
  316. Server_Failure,
  317. Name_Error,
  318. Not_Implemented,
  319. Refused,
  320. }
  321. DNS_Query :: enum u16be {
  322. Host_Address = 1,
  323. Authoritative_Name_Server = 2,
  324. Mail_Destination = 3,
  325. Mail_Forwarder = 4,
  326. CNAME = 5,
  327. All = 255,
  328. }
  329. DNS_Header :: struct {
  330. id: u16be,
  331. is_response: bool,
  332. opcode: u16be,
  333. is_authoritative: bool,
  334. is_truncated: bool,
  335. is_recursion_desired: bool,
  336. is_recursion_available: bool,
  337. response_code: DNS_Response_Code,
  338. }
  339. DNS_Record_Header :: struct #packed {
  340. type: u16be,
  341. class: u16be,
  342. ttl: u32be,
  343. length: u16be,
  344. }
  345. DNS_Host_Entry :: struct {
  346. name: string,
  347. addr: Address,
  348. }