package core:net

⌘K
Ctrl+K
or
/

    Overview

    Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures. For other protocols and their features, see subdirectories of this package.

    Features: Supports Windows, Linux and OSX. Opening and closing of TCP and UDP sockets. Sending to and receiving from these sockets. DNS name lookup, using either the OS or our own resolver.

    Planned: Nonblocking IO Connection struct; A "fat socket" struct that remembers how you opened it, etc, instead of just being a handle. IP Range structs, CIDR/class ranges, netmask calculator and associated helper procedures. Use context.temp_allocator instead of stack-based arenas?
    And check it's the default temp allocator or can give us 4 MiB worth of memory without punting to the main allocator by comparing their addresses in an @(init) procedure. Panic if this assumption is not met. Document assumptions about libc usage (or avoidance thereof) for each platform.

    Assumptions: For performance reasons this package relies on the context.temp_allocator in some places.

    You can replace the default context.temp_allocator with your own as long as it meets this requirement: A minimum of 4 MiB of scratch space that's expected not to be freed.

    If this expectation is not met, the package's @(init) procedure will attempt to detect this and panic to avoid temp allocations prematurely overwriting data and garbling results, or worse. This means that should you replace the temp allocator with an insufficient one, we'll do our best to loudly complain the first time you try it.

    Index

    Types (60)
    Procedures (68)
    Procedure Groups (4)

    Types

    Accept_Error ¶

    Accept_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, 
    	// Invalid socket, or options.
    	Invalid_Argument, 
    	// The given socket does not support accepting connections.
    	Unsupported_Socket, 
    	// accept called on a socket which is not listening.
    	Not_Listening, 
    	// A connection arrived but was closed while in the listen queue.
    	Aborted, 
    	// Timed out before being able to accept a connection.
    	Timeout, 
    	// Non-blocking socket that would need to block waiting for a connection.
    	Would_Block, 
    	// Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows.
    	Interrupted, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }
    Related Procedures With Returns

    Address ¶

    Address :: union {
    	IP4_Address, 
    	IP6_Address, 
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Address_Duplication ¶

    Address_Duplication :: enum i32 {
    	Invalid    = 0, 
    	Tentative  = 1, 
    	Duplicate  = 2, 
    	Deprecated = 3, 
    	Preferred  = 4, 
    }

    Address_Family ¶

    Address_Family :: enum int {
    	IP4, 
    	IP6, 
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Any_Socket ¶

    Any_Socket :: union {
    	TCP_Socket, 
    	UDP_Socket, 
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Bind_Error ¶

    Bind_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, 
    	// Invalid socket or endpoint, or invalid combination of the two.
    	Invalid_Argument, 
    	// The socket is already bound to an address.
    	Already_Bound, 
    	// The address is protected and the current user has insufficient permissions to access it.
    	Insufficient_Permissions_For_Address, 
    	// The address is already in use.
    	Address_In_Use, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }
    Related Procedures With Returns

    Create_Socket_Error ¶

    Create_Socket_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, 
    	// Invalid/unsupported family or protocol.
    	Invalid_Argument, 
    	// The user has no permission to create a socket of this type and/or protocol.
    	Insufficient_Permissions, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }
    Related Procedures With Returns

    DNS_Configuration ¶

    DNS_Configuration :: struct {
    	// Configuration files.
    	resolv_conf:        string,
    	hosts_file:         string,
    	// TODO: Allow loading these up with `reload_configuration()` call or the like,
    	// so we don't have to do it each call.
    	name_servers:       []Endpoint,
    	hosts_file_entries: []DNS_Record,
    }
     

    DNS DEFINITIONS

    Related Constants

    DNS_Error ¶

    DNS_Error :: enum u32 {
    	None                        = 0, 
    	Invalid_Hostname_Error      = 1, 
    	Invalid_Hosts_Config_Error, 
    	Invalid_Resolv_Config_Error, 
    	Connection_Error, 
    	Server_Error, 
    	System_Error, 
    }
    Related Procedures With Returns

    DNS_Header ¶

    DNS_Header :: struct {
    	id:                     u16be,
    	is_response:            bool,
    	opcode:                 u16be,
    	is_authoritative:       bool,
    	is_truncated:           bool,
    	is_recursion_desired:   bool,
    	is_recursion_available: bool,
    	response_code:          DNS_Response_Code,
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    DNS_Host_Entry ¶

    DNS_Host_Entry :: struct {
    	name: string,
    	addr: Address,
    }

    DNS_Query ¶

    DNS_Query :: enum u16be {
    	Host_Address              = 1, 
    	Authoritative_Name_Server = 2, 
    	Mail_Destination          = 3, 
    	Mail_Forwarder            = 4, 
    	CNAME                     = 5, 
    	All                       = 255, 
    }

    DNS_Record_Base ¶

    DNS_Record_Base :: struct {
    	record_name: string,
    	ttl_seconds: u32,
    }
     

    Base DNS Record. All DNS responses will carry a hostname and TTL (time to live) field.

    DNS_Record_CNAME ¶

    DNS_Record_CNAME :: struct {
    	using base: DNS_Record_Base,
    	host_name: string,
    }
     

    Another domain name that the domain name maps to. Domains can be pointed to another domain instead of directly to an IP address. get_dns_records will recursively follow these if you request this type of record.

    DNS_Record_Header ¶

    DNS_Record_Header :: struct #packed {
    	type:   u16be,
    	class:  u16be,
    	ttl:    u32be,
    	length: u16be,
    }

    DNS_Record_IP4 ¶

    DNS_Record_IP4 :: struct {
    	using base: DNS_Record_Base,
    	address: IP4_Address,
    }
     

    An IP4 address that the domain name maps to. There can be any number of these.

    DNS_Record_IP6 ¶

    DNS_Record_IP6 :: struct {
    	using base: DNS_Record_Base,
    	address: IP6_Address,
    }
     

    An IPv6 address that the domain name maps to. There can be any number of these.

    DNS_Record_MX ¶

    DNS_Record_MX :: struct {
    	using base: DNS_Record_Base,
    	host_name:  string,
    	preference: int,
    }
     

    Domain names for email servers that are associated with the domain name. These records also have values which ranks them in the order they should be preferred. Lower is more-preferred.

    DNS_Record_NS ¶

    DNS_Record_NS :: struct {
    	using base: DNS_Record_Base,
    	host_name: string,
    }
     

    Domain names of other DNS servers that are associated with the domain name. TODO(tetra): Expand on what these records are used for, and when you should use pay attention to these.

    DNS_Record_SRV ¶

    DNS_Record_SRV :: struct {
    	// base contains the full name of this record.
    	// e.g: _sip._tls.example.com
    	using base:    DNS_Record_Base,
    	// The hostname or address where this service can be found.
    	target:        string,
    	// The port on which this service can be found.
    	port:          int,
    	service_name:  string,
    	// NOTE(tetra): These are substrings of 'record_name'
    	protocol_name: string,
    	// Lower is higher priority
    	priority:      int,
    	// Relative weight of this host compared to other of same priority; the chance of using this host should be proporitional to this weight.
    	// The number of seconds that it will take to update the record.
    	weight:        int,
    }
     

    An endpoint for a service that is available through the domain name. This is the way to discover the services that a domain name provides.

    Clients MUST attempt to contact the host with the lowest priority that they can reach. If two hosts have the same priority, they should be contacted in the order according to their weight. Hosts with larger weights should have a proportionally higher chance of being contacted by clients. A weight of zero indicates a very low weight, or, when there is no choice (to reduce visual noise).

    The host may be "." to indicate that it is "decidedly not available" on this domain.

    DNS_Record_TXT ¶

    DNS_Record_TXT :: struct {
    	using base: DNS_Record_Base,
    	value: string,
    }
     

    Arbitrary string data that is associated with the domain name. Commonly of the form key=value to be parsed, though there is no specific format for them. These can be used for any purpose.

    DNS_Record_Type ¶

    DNS_Record_Type :: enum u16 {
    	DNS_TYPE_A     = 1,  // IP4 address.
    	DNS_TYPE_NS    = 2,  // IP6 address.
    	DNS_TYPE_CNAME = 5,  // Another host name.
    	DNS_TYPE_MX    = 15, // Arbitrary binary data or text.
    	DNS_TYPE_AAAA  = 28, // Address of a name (DNS) server.
    	DNS_TYPE_TEXT  = 16, // Address and preference priority of a mail exchange server.
    	DNS_TYPE_SRV   = 33, // Address, port, priority, and weight of a host that provides a particular service.
    	IP4            = 1, 
    	IP6            = 28, 
    	CNAME          = 5, 
    	TXT            = 16, 
    	NS             = 2, 
    	MX             = 15, 
    	SRV            = 33, 
    }
    Related Procedures With Parameters

    DNS_Response_Code ¶

    DNS_Response_Code :: enum u16be {
    	No_Error, 
    	Format_Error, 
    	Server_Failure, 
    	Name_Error, 
    	Not_Implemented, 
    	Refused, 
    }

    Dial_Error ¶

    Dial_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, 
    	// Invalid endpoint and/or options.	
    	Invalid_Argument, 
    	// An attempt was made to connect to a broadcast socket on a socket that doesn't support it.
    	Broadcast_Not_Supported, 
    	// The socket is already connected.
    	Already_Connected, 
    	// The socket is already in the progress of making a connection.
    	Already_Connecting, 
    	// The address is already in use.
    	Address_In_Use, 
    	// Could not reach the remote host.
    	Host_Unreachable, 
    	// The remote host refused the connection or isn't listening.
    	Refused, 
    	// The connection was reset by the remote host.
    	Reset, 
    	// Timed out before making a connection.
    	Timeout, 
    	// Non-blocking socket that would need to block waiting to connect.
    	Would_Block, 
    	// Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows.
    	Interrupted, 
    	// Endpoint given without a port, which is required.
    	Port_Required, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }

    Digit_Parse_Base ¶

    Digit_Parse_Base :: enum u8 {
    	Dec  = 0, // No prefix
    	Oct  = 1, // Leading zero
    	Hex  = 2, // 0x prefix
    	IPv6 = 3, // Unprefixed IPv6 piece hex. Can't be used with other bases.
    }

    Digit_Parse_Bases ¶

    Digit_Parse_Bases :: bit_set[Digit_Parse_Base; u8]
    Related Constants

    Endpoint ¶

    Endpoint :: struct {
    	address: Address,
    	port:    int,
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Host ¶

    Host :: struct {
    	hostname: string,
    	port:     int,
    }
    Related Procedures With Parameters

    Host_Or_Endpoint ¶

    Host_Or_Endpoint :: union {
    	Host, 
    	Endpoint, 
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    IP4_Address ¶

    IP4_Address :: distinct [4]u8
    Related Procedures With Returns
    Related Constants

    IP6_Address ¶

    IP6_Address :: distinct [8]u16be
    Related Procedures With Returns
    Related Constants

    Interfaces_Error ¶

    Interfaces_Error :: enum u32 {
    	None, 
    	Unable_To_Enumerate_Network_Interfaces, 
    	Allocation_Failure, 
    	Unknown, 
    }
    Related Procedures With Returns

    Lease ¶

    Lease :: struct {
    	address:             Address,
    	netmask:             Netmask,
    	lifetime:            struct {
    		valid:     u32,
    		preferred: u32,
    		lease:     u32,
    	},
    	origin:              struct {
    		prefix: Prefix_Origin,
    		suffix: Suffix_Origin,
    	},
    	address_duplication: Address_Duplication,
    }
    Link_State :: bit_set[Link_States; u32]
    Link_States :: enum u32 {
    	Up               = 1, 
    	Down             = 2, 
    	Testing          = 3, 
    	Dormant          = 4, 
    	Not_Present      = 5, 
    	Lower_Layer_Down = 6, 
    	Loopback         = 7, 
    }
     

    Empty bit set is unknown state.

    Listen_Error ¶

    Listen_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, 
    	// The socket or backlog is invalid.
    	Invalid_Argument, 
    	// The socket is valid, but does not support listening.
    	Unsupported_Socket, 
    	// The socket is already connected.
    	Already_Connected, 
    	// The address is already in use.
    	Address_In_Use, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }
    Related Procedures With Returns

    Maybe ¶

    Maybe :: runtime.Maybe
     

    COMMON DEFINITIONS

    Related Procedures With Parameters
    Related Procedures With Returns

    Netmask ¶

    Netmask :: union {
    	IP4_Address, 
    	IP6_Address, 
    }

    Network_Interface ¶

    Network_Interface :: struct {
    	adapter_name:     string,
    	// On Windows this is a GUID that we could parse back into its u128 for more compact storage.
    	friendly_name:    string,
    	description:      string,
    	dns_suffix:       string,
    	physical_address: string,
    	// MAC address, etc.
    	mtu:              u32,
    	unicast:          [dynamic]Lease,
    	multicast:        [dynamic]Address,
    	anycast:          [dynamic]Address,
    	gateways:         [dynamic]Address,
    	dhcp_v4:          Address,
    	dhcp_v6:          Address,
    	tunnel_type:      Tunnel_Type,
    	link:             struct {
    		state:          bit_set[Link_States; u32],
    		transmit_speed: u64,
    		receive_speed:  u64,
    	},
    }
     

    INTERFACE / LINK STATE

    Parse_Endpoint_Error ¶

    Parse_Endpoint_Error :: enum u32 {
    	None         = 0, 
    	Bad_Port     = 1, 
    	Bad_Address, 
    	Bad_Hostname, 
    }
    Related Procedures With Returns

    Prefix_Origin ¶

    Prefix_Origin :: enum i32 {
    	Other                = 0, 
    	Manual               = 1, 
    	Well_Known           = 2, 
    	DHCP                 = 3, 
    	Router_Advertisement = 4, 
    	Unchanged            = 16, 
    }

    Resolve_Error ¶

    Resolve_Error :: enum u32 {
    	None              = 0, 
    	Unable_To_Resolve = 1, 
    }

    Set_Blocking_Error ¶

    Set_Blocking_Error :: enum i32 {
    	None, 
    	// No network connection, or the network stack is not initialized.
    	Network_Unreachable, 
    	// Socket is invalid.
    	Invalid_Argument, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }
    Related Procedures With Returns

    Shutdown_Error ¶

    Shutdown_Error :: enum i32 {
    	None, 
    	// No network connection, or the network stack is not initialized.
    	Network_Unreachable, 
    	// Socket is invalid or not connected, or the manner given is invalid.
    	Invalid_Argument, 
    	// Connection was closed/aborted/shutdown.
    	Connection_Closed, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }
    Related Procedures With Returns

    Shutdown_Manner ¶

    Shutdown_Manner :: enum i32 {
    	Receive = 0, 
    	Send    = 1, 
    	Both    = 2, 
    }
    Related Procedures With Parameters

    Socket ¶

    Socket :: distinct i64
     

    To allow freely using Socket in your own data structures in a cross-platform manner, we treat it as a handle large enough to accomodate OS-specific notions of socket handles.

    The platform code will perform the cast so you don't have to.

    Related Procedures With Returns

    Socket_Option ¶

    Socket_Option :: enum i32 {
    	// bool: Whether the address that this socket is bound to can be reused by other sockets.
    	//       This allows you to bypass the cooldown period if a program dies while the socket is bound.
    	Reuse_Address             = 4, 
    	// bool: Whether other programs will be inhibited from binding the same endpoint as this socket.
    	Exclusive_Addr_Use        = -5, 
    	// bool: When true, keepalive packets will be automatically be sent for this connection. TODO: verify this understanding
    	Keep_Alive                = 8, 
    	// bool: When true, client connections will immediately be sent a TCP/IP RST response, rather than being accepted.
    	Conditional_Accept        = 12290, 
    	// bool: If true, when the socket is closed, but data is still waiting to be sent, discard that data.
    	Dont_Linger               = -129, 
    	// bool: When true, 'out-of-band' data sent over the socket will be read by a normal net.recv() call, the same as normal 'in-band' data.
    	Out_Of_Bounds_Data_Inline = 256, 
    	// bool: When true, disables send-coalescing, therefore reducing latency.
    	TCP_Nodelay               = 1, 
    	// win.LINGER: Customizes how long (if at all) the socket will remain open when there
    	// is some remaining data waiting to be sent, and net.close() is called.
    	Linger                    = 128, 
    	// win.DWORD: The size, in bytes, of the OS-managed receive-buffer for this socket.
    	Receive_Buffer_Size       = 4098, 
    	// win.DWORD: The size, in bytes, of the OS-managed send-buffer for this socket.
    	Send_Buffer_Size          = 4097, 
    	// win.DWORD: For blocking sockets, the time in milliseconds to wait for incoming data to be received, before giving up and returning .Timeout.
    	//            For non-blocking sockets, ignored.
    	//            Use a value of zero to potentially wait forever.
    	Receive_Timeout           = 4102, 
    	// win.DWORD: For blocking sockets, the time in milliseconds to wait for outgoing data to be sent, before giving up and returning .Timeout.
    	//            For non-blocking sockets, ignored.
    	//            Use a value of zero to potentially wait forever.
    	Send_Timeout              = 4101, 
    	// bool: Allow sending to, receiving from, and binding to, a broadcast address.
    	Broadcast                 = 32, 
    }
    Related Procedures With Parameters

    Socket_Option_Error ¶

    Socket_Option_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, not connected, or the connection has been closed/reset/shutdown.
    	Invalid_Socket, 
    	// Unknown or unsupported option for the socket.
    	Invalid_Option, 
    	// Invalid level or value.
    	Invalid_Value, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }
    Related Procedures With Returns

    Socket_Protocol ¶

    Socket_Protocol :: enum int {
    	TCP, 
    	UDP, 
    }
    Related Procedures With Parameters

    Suffix_Origin ¶

    Suffix_Origin :: enum i32 {
    	Other              = 0, 
    	Manual             = 1, 
    	Well_Known         = 2, 
    	DHCP               = 3, 
    	Link_Layer_Address = 4, 
    	Random             = 5, 
    	Unchanged          = 16, 
    }

    TCP_Recv_Error ¶

    TCP_Recv_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, 
    	// Invalid socket or buffer given.
    	Invalid_Argument, 
    	// The socket is not connected.
    	Not_Connected, 
    	// Connection was closed/broken/shutdown while receiving data.
    	Connection_Closed, 
    	// Timed out before being able to receive any data.
    	Timeout, 
    	// Non-blocking socket that would need to block waiting on data.
    	Would_Block, 
    	// Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows.
    	Interrupted, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }
    Related Procedures With Returns

    TCP_Send_Error ¶

    TCP_Send_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, 
    	// Invalid socket or buffer given.
    	Invalid_Argument, 
    	// Connection was closed/broken/shutdown while receiving data.
    	Connection_Closed, 
    	// The socket is not connected.
    	Not_Connected, 
    	// Could not reach the remote host.
    	Host_Unreachable, 
    	// Timed out before being able to send any data.
    	Timeout, 
    	// Non-blocking socket that would need to block waiting on the remote to be able to receive the data.
    	Would_Block, 
    	// Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows.
    	Interrupted, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }
    Related Procedures With Returns

    Tunnel_Type ¶

    Tunnel_Type :: enum i32 {
    	None         = 0, 
    	Other        = 1, 
    	Direct       = 2, 
    	IPv4_To_IPv6 = 11, 
    	ISA_TAP      = 13, 
    	Teredo       = 14, 
    	IP_HTTPS     = 15, 
    }

    UDP_Recv_Error ¶

    UDP_Recv_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, 
    	// Invalid socket or buffer given.
    	Invalid_Argument, 
    	// "Connection" was refused by remote, or closed/broken/shutdown while receiving data.
    	Connection_Refused, 
    	// Timed out before being able to receive any data.
    	Timeout, 
    	// Non-blocking socket that would need to block waiting on data.
    	Would_Block, 
    	// Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows.
    	Interrupted, 
    	// Linux and UDP only: indicates the buffer was too small to receive all data, and the excess is truncated and discarded.
    	Excess_Truncated, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }
    Related Procedures With Returns

    UDP_Send_Error ¶

    UDP_Send_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, 
    	// Invalid socket or buffer given.
    	Invalid_Argument, 
    	// Could not reach the remote host.
    	Host_Unreachable, 
    	// "Connection" was refused by remote, or closed/broken/shutdown while sending data.
    	Connection_Refused, 
    	// Timed out before being able to send any data.
    	Timeout, 
    	// Non-blocking socket that would need to block waiting on the remote to be able to receive the data.
    	Would_Block, 
    	// Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows.
    	Interrupted, 
    	// An error unable to be categorized in above categories, `last_platform_error` may have more info.
    	Unknown, 
    }
    Related Procedures With Returns

    UDP_Socket ¶

    UDP_Socket :: distinct i64
    Related Procedures With Parameters
    Related Procedures With Returns

    Constants

    DEFAULT_DIGIT_BASES ¶

    DEFAULT_DIGIT_BASES: bit_set[Digit_Parse_Base; u8] : Digit_Parse_Bases{.Dec, .Oct, .Hex}

    DEFAULT_DNS_CONFIGURATION ¶

    DEFAULT_DNS_CONFIGURATION :: DNS_Configuration{resolv_conf = "", hosts_file = "%WINDIR%\\system32\\drivers\\etc\\hosts"}

    IP4_Loopback ¶

    IP4_Loopback :: IP4_Address{127, 0, 0, 1}

    IP6_Loopback ¶

    IP6_Loopback :: IP6_Address{0, 0, 0, 0, 0, 0, 0, 1}

    IPv6_MAX_STRING_LENGTH ¶

    IPv6_MAX_STRING_LENGTH: int : 45

    IPv6_MIN_COLONS ¶

    IPv6_MIN_COLONS: int : 2

    IPv6_MIN_STRING_LENGTH ¶

    IPv6_MIN_STRING_LENGTH: int : 2
     

    The minimum length of a valid IPv6 address string is 2, e.g. ::

    The maximum length of a valid IPv6 address string is 45, when it embeds an IPv4, e.g. 0000:0000:0000:0000:0000:ffff:255.255.255.255

    An IPv6 address must contain at least 3 pieces, e.g. ::, and at most 9 (using :: for a trailing or leading 0)

    IPv6_PIECE_COUNT ¶

    IPv6_PIECE_COUNT: int : 8

    LABEL_MAX ¶

    LABEL_MAX: int : 63

    MAX_INTERFACE_ENUMERATION_TRIES ¶

    MAX_INTERFACE_ENUMERATION_TRIES: int : 3

    NAME_MAX ¶

    NAME_MAX: int : 255

    ODIN_NET_TCP_NODELAY_DEFAULT ¶

    ODIN_NET_TCP_NODELAY_DEFAULT: bool : #config(ODIN_NET_TCP_NODELAY_DEFAULT, true)

    Variables

    IP4_mDNS_Broadcast ¶

    IP4_mDNS_Broadcast: Endpoint = …

    IP6_mDNS_Broadcast ¶

    IP6_mDNS_Broadcast: Endpoint = …

    default_tcp_options ¶

    default_tcp_options: TCP_Options = …

    Procedures

    accept_tcp ¶

    accept_tcp :: proc(socket: TCP_Socket, options: TCP_Options = default_tcp_options) -> (client: TCP_Socket, source: Endpoint, err: Accept_Error) {…}

    address_to_string ¶

    address_to_string :: proc(addr: Address, allocator := context.temp_allocator) -> string {…}
     

    Returns a temporarily-allocated string representation of the address.

    See RFC 5952 section 4 for IPv6 representation recommendations.

    any_socket_to_socket ¶

    any_socket_to_socket :: proc "contextless" (socket: Any_Socket) -> Socket {…}

    aton ¶

    aton :: proc(address_and_maybe_port: string, family: Address_Family, allow_decimal_only: bool = false) -> (addr: Address, ok: bool) {…}
     

    Parses an IP address in "non-decimal" inet_aton form.

    e.g."00377.0x0ff.65534" = 255.255.255.254

    00377 = 255 in octal
    0x0ff = 255 in hexadecimal
    This leaves 16 bits worth of address
    .65534 then accounts for the last two digits
    
    

    For the address part the allowed forms are:

    a.b.c.d - where each part represents a byte
    a.b.c   - where `a` & `b` represent a byte and `c` a u16
    a.b     - where `a` represents a byte and `b` supplies the trailing 24 bits
    a       - where `a` gives the entire 32-bit value
    
    

    The port, if present, is required to be a base 10 number in the range 0-65535, inclusive.

    bind ¶

    bind :: proc(socket: Any_Socket, ep: Endpoint) -> (err: Bind_Error) {…}

    bound_endpoint ¶

    bound_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: Listen_Error) {…}
     

    Returns the endpoint that the given socket is listening / bound on.

    close ¶

    close :: proc(socket: Any_Socket) {…}

    create_socket ¶

    create_socket :: proc(family: Address_Family, protocol: Socket_Protocol) -> (socket: Any_Socket, err: Create_Socket_Error) {…}

    decode_hostname ¶

    decode_hostname :: proc(packet: []u8, start_idx: int, allocator := context.allocator) -> (hostname: string, encode_size: int, ok: bool) {…}

    destroy_dns_records ¶

    destroy_dns_records :: proc(records: []DNS_Record, allocator := context.allocator) {…}
     

    records slice is also destroyed.

    destroy_interfaces ¶

    destroy_interfaces :: proc(interfaces: []Network_Interface, allocator := context.allocator) {…}
     

    destroy_interfaces cleans up a list of network interfaces retrieved by e.g. enumerate_interfaces.

    dial_tcp_from_address_and_port ¶

    dial_tcp_from_address_and_port :: proc(address: Address, port: int, options: TCP_Options = default_tcp_options) -> (socket: TCP_Socket, err: Network_Error) {…}
     

    Dial from an Address.

    Errors that can be returned: Create_Socket_Error, or Dial_Error

    dial_tcp_from_endpoint ¶

    dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options: TCP_Options = default_tcp_options) -> (socket: TCP_Socket, err: Network_Error) {…}
     

    Dial from an Endpoint.

    Errors that can be returned: Create_Socket_Error, or Dial_Error

    dial_tcp_from_host ¶

    dial_tcp_from_host :: proc(host: Host, options: TCP_Options = default_tcp_options) -> (socket: TCP_Socket, err: Network_Error) {…}
     

    Expects the host as Host.

    Errors that can be returned: `Resolve_Error`, `DNS_Error`, `Create_Socket_Error`, or `Dial_Error`
    

    dial_tcp_from_host_or_endpoint ¶

    dial_tcp_from_host_or_endpoint :: proc(target: Host_Or_Endpoint, options: TCP_Options = default_tcp_options) -> (socket: TCP_Socket, err: Network_Error) {…}
     

    Expects the target as a Host_OrEndpoint. Unwraps the underlying type and calls dial_tcp_from_host or dial_tcp_from_endpoint.

    Errors that can be returned: `Parse_Endpoint_Error`, `Resolve_Error`, `DNS_Error`, `Create_Socket_Error`, or `Dial_Error`
    

    dial_tcp_from_hostname_and_port_string ¶

    dial_tcp_from_hostname_and_port_string :: proc(hostname_and_port: string, options: TCP_Options = default_tcp_options) -> (socket: TCP_Socket, err: Network_Error) {…}
     

    Expects both hostname and port to be present in the hostname_and_port parameter, either as: a.host.name:9999, or as 1.2.3.4:9999, or IP6 equivalent.

    Calls parse_hostname_or_endpoint and dial_tcp_from_host_or_endpoint.

    Errors that can be returned: `Parse_Endpoint_Error`, `Resolve_Error`, `DNS_Error`, `Create_Socket_Error`, or `Dial_Error`
    

    dial_tcp_from_hostname_with_port_override ¶

    dial_tcp_from_hostname_with_port_override :: proc(hostname: string, port: int, options: TCP_Options = default_tcp_options) -> (socket: TCP_Socket, err: Network_Error) {…}
     

    Expects the hostname as a string and port as a int. parse_hostname_or_endpoint is called and the hostname will be resolved into an IP.

    If a hostname of form a.host.name:9999 is given, the port will be ignored in favor of the explicit port param.

    Errors that can be returned: `Parse_Endpoint_Error`, `Resolve_Error`, `DNS_Error`, `Create_Socket_Error`, or `Dial_Error`
    

    encode_hostname ¶

    encode_hostname :: proc(b: ^strings.Builder, hostname: string) -> (ok: bool) {…}
     

    www.google.com -> 3www6google3com0

    endpoint_to_string ¶

    endpoint_to_string :: proc(ep: Endpoint, allocator := context.temp_allocator) -> string {…}
     

    Returns a temporarily-allocated string representation of the endpoint. If there's a port, uses the ip4address:port or [ip6address]:port format, respectively.

    enumerate_interfaces ¶

    enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Interfaces_Error) {…}
     

    enumerate_interfaces retrieves a list of network interfaces with their associated properties.

    family_from_address ¶

    family_from_address :: proc(addr: Address) -> Address_Family {…}

    family_from_endpoint ¶

    family_from_endpoint :: proc(ep: Endpoint) -> Address_Family {…}

    get_dns_records_from_nameservers ¶

    get_dns_records_from_nameservers :: proc(hostname: string, type: DNS_Record_Type, name_servers: []Endpoint, host_overrides: []DNS_Record, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) {…}
     

    A generic DNS client usable on any platform. Performs a recursive DNS query for records of a particular type for the hostname.

    NOTE: This procedure instructs the DNS resolver to recursively perform CNAME requests on our behalf, meaning that DNS queries for a hostname will resolve through CNAME records until an IP address is reached.

    IMPORTANT: This procedure allocates memory for each record returned; deleting just the returned slice is not enough! See destroy_records.

    get_dns_records_from_os ¶

    get_dns_records_from_os :: proc(hostname: string, type: DNS_Record_Type, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) {…}
     

    Performs a recursive DNS query for records of a particular type for the hostname using the OS.

    NOTE: This procedure instructs the DNS resolver to recursively perform CNAME requests on our behalf, meaning that DNS queries for a hostname will resolve through CNAME records until an IP address is reached.

    IMPORTANT: This procedure allocates memory for each record returned; deleting just the returned slice is not enough! See destroy_records.

    get_network_interfaces ¶

    get_network_interfaces :: proc() -> []Address {…}
     

    Returns an address for each interface that can be bound to.

    init_dns_configuration ¶

    init_dns_configuration :: proc() {…}

    join_port ¶

    join_port :: proc(address_or_host: string, port: int, allocator := context.allocator) -> string {…}
     

    Joins an address or hostname with a port.

    join_url ¶

    join_url :: proc(
    	scheme, host, path: string, 
    	queries:            map[string]string, 
    	fragment:           string, 
    	allocator := context.allocator, 
    ) -> string {…}

    last_platform_error ¶

    last_platform_error :: proc() -> i32 {…}
     

    Retrieve a platform specific error code, for when the categorized cross-platform errors are not enough.

    Platforms specific returns: Darwin: posix.Errno (core:sys/posix) Linux: linux.Errno (core:sys/linux) FreeBSD: freebsd.Errno (core:sys/freebsd) Windows: windows.System_Error (core:sys/windows)

    last_platform_error_string ¶

    last_platform_error_string :: proc() -> string {…}
     

    Retrieve a stringified version of the last platform error.

    listen_tcp ¶

    listen_tcp :: proc(interface_endpoint: Endpoint, backlog: int = 1000) -> (socket: TCP_Socket, err: Network_Error) {…}
     

    Creates a TCP socket and starts listening on the given endpoint.

    Errors that can be returned: Create_Socket_Error, Bind_Error, or Listen_Error

    load_hosts ¶

    load_hosts :: proc(hosts_file_path: string, allocator := context.allocator) -> (hosts: []DNS_Host_Entry, ok: bool) {…}

    load_resolv_conf ¶

    load_resolv_conf :: proc(resolv_conf_path: string, allocator := context.allocator) -> (name_servers: []Endpoint, ok: bool) {…}

    make_bound_udp_socket ¶

    make_bound_udp_socket :: proc(bound_address: Address, port: int) -> (socket: UDP_Socket, err: Network_Error) {…}
     

    This type of socket is bound immediately, which enables it to receive data on the port. Since it's UDP, it's also able to send data without receiving any first.

    This is like a listening TCP socket, except that data packets can be sent and received without needing to establish a connection first. The bound_address is the address of the network interface that you want to use, or a loopback address if you don't care which to use.

    Errors that can be returned: Parse_Endpoint_Error, Create_Socket_Error, or Bind_Error

    make_unbound_udp_socket ¶

    make_unbound_udp_socket :: proc(family: Address_Family) -> (socket: UDP_Socket, err: Create_Socket_Error) {…}
     

    This type of socket becomes bound when you try to send data. It is likely what you want if you want to send data unsolicited.

    This is like a client TCP socket, except that it can send data to any remote endpoint without needing to establish a connection first.

    map_to_ip6 ¶

    map_to_ip6 :: proc(addr: Address) -> Address {…}
     

    TODO(tetra): Do we need this?

    pack_dns_header ¶

    pack_dns_header :: proc(hdr: DNS_Header) -> (id: u16be, bits: u16be) {…}

    parse_address ¶

    parse_address :: proc(address_and_maybe_port: string, non_decimal_address: bool = false) -> Address {…}
     

    Try parsing as an IPv6 address. If it's determined not to be, try as an IPv4 address, optionally in non-decimal format.

    parse_endpoint ¶

    parse_endpoint :: proc(endpoint_str: string) -> (ep: Endpoint, ok: bool) {…}

    parse_hostname_or_endpoint ¶

    parse_hostname_or_endpoint :: proc(endpoint_str: string) -> (target: Host_Or_Endpoint, err: Parse_Endpoint_Error) {…}
     

    Takes a string consisting of a hostname or IP address, and an optional port, and return the component parts in a useful form.

    parse_ip4_address ¶

    parse_ip4_address :: proc(address_and_maybe_port: string, allow_non_decimal: bool = false) -> (addr: IP4_Address, ok: bool) {…}
     

    Expects an IPv4 address with no leading or trailing whitespace: a.b.c.d a.b.c.d:port [a.b.c.d]:port

    If the IP address is bracketed, the port must be present and valid (though it will be ignored): [a.b.c.d] will be treated as a parsing failure.

    The port, if present, is required to be a base 10 number in the range 0-65535, inclusive.

    If allow_non_decimal is false, aton is told each component must be decimal and max 255.

    parse_ip6_address ¶

    parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address, ok: bool) {…}

    parse_ip_component ¶

    parse_ip_component :: proc(input: string, max_value: u64 = u64(max(u32)), bases: bit_set[Digit_Parse_Base; u8] = DEFAULT_DIGIT_BASES) -> (value: u64, bytes_consumed: int, ok: bool) {…}
     

    Parses a single unsigned number in requested bases from input. max_value represents the maximum allowed value for this number.

    Returns the value, the bytes_consumed so far, and ok to signal success or failure.

    An out-of-range or invalid number will return the accumulated value so far (which can be out of range), the number of bytes consumed leading up the error, and ok = false.

    When . or : are encountered, they'll be considered valid separators and will stop parsing, returning the valid number leading up to it.

    Other non-digit characters are treated as an error.

    Octal numbers are expected to have a leading zero, with no 'o' format specifier. Hexadecimal numbers are expected to be preceded by '0x' or '0X'. Numbers will otherwise be considered to be in base 10.

    parse_record ¶

    parse_record :: proc(packet: []u8, cur_off: ^int, filter: DNS_Record_Type = nil) -> (record: DNS_Record, ok: bool) {…}

    parse_response ¶

    parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator := context.allocator) -> (records: []DNS_Record, xid: u16be, ok: bool) {…}

    parse_socket_address ¶

    parse_socket_address :: proc(addr_in: sys_windows.SOCKET_ADDRESS) -> (addr: Endpoint) {…}
     

    Interpret SOCKET_ADDRESS as an Address

    percent_decode ¶

    percent_decode :: proc(encoded_string: string, allocator := context.allocator) -> (decoded_string: string, ok: bool) {…}

    percent_encode ¶

    percent_encode :: proc(s: string, allocator := context.allocator) -> string {…}

    physical_address_to_string ¶

    physical_address_to_string :: proc(phy_addr: []u8, allocator := context.allocator) -> (phy_string: string) {…}
     

    Turns a slice of bytes (from e.g. get_adapters_addresses) into a "XX:XX:XX:..." string.

    recv_any ¶

    recv_any :: proc(socket: Any_Socket, buf: []u8) -> (bytes_read: int, remote_endpoint: runtime.Maybe($T=Endpoint), err: Network_Error) {…}
     

    Receive data from into a buffer from any socket.

    Note: remote_endpoint parameter is non-nil only if the socket type is UDP. On TCP sockets it will always return nil.

    Errors that can be returned: TCP_Recv_Error, or UDP_Recv_Error

    recv_tcp ¶

    recv_tcp :: proc(socket: TCP_Socket, buf: []u8) -> (bytes_read: int, err: TCP_Recv_Error) {…}

    recv_udp ¶

    recv_udp :: proc(socket: UDP_Socket, buf: []u8) -> (bytes_read: int, remote_endpoint: Endpoint, err: UDP_Recv_Error) {…}

    replace_environment_path ¶

    replace_environment_path :: proc(path: string, allocator := context.allocator) -> (res: string, ok: bool) {…}
     

    Always allocates for consistency.

    resolve ¶

    resolve :: proc(hostname_and_maybe_port: string) -> (ep4, ep6: Endpoint, err: Network_Error) {…}
     

    Resolves a hostname to exactly one IP4 and IP6 endpoint. It's then up to you which one you use. Note that which address you use to open a socket, determines the type of the socket you get.

    Returns ok=false if the host name could not be resolved to any endpoints.

    Returned endpoints have the same port as provided in the string, or 0 if absent. If you want to use a specific port, just modify the field after the call to this procedure.

    If the hostname part of the endpoint is actually a string representation of an IP address, DNS resolution will be skipped. This allows you to pass both strings like "example.com:9000" and "1.2.3.4:9000" to this function end reliably get back an endpoint in both cases.

    resolve_ip4 ¶

    resolve_ip4 :: proc(hostname_and_maybe_port: string) -> (ep4: Endpoint, err: Network_Error) {…}

    resolve_ip6 ¶

    resolve_ip6 :: proc(hostname_and_maybe_port: string) -> (ep6: Endpoint, err: Network_Error) {…}

    send_any ¶

    send_any :: proc(socket: Any_Socket, buf: []u8, to: runtime.Maybe($T=Endpoint) = nil) -> (bytes_written: int, err: Network_Error) {…}
     

    Sends data over the socket.

    Errors that can be returned: TCP_Send_Error, or UDP_Send_Error

    send_tcp ¶

    send_tcp :: proc(socket: TCP_Socket, buf: []u8) -> (bytes_written: int, err: TCP_Send_Error) {…}
     

    Repeatedly sends data until the entire buffer is sent. If a send fails before all data is sent, returns the amount sent up to that point.

    send_udp ¶

    send_udp :: proc(socket: UDP_Socket, buf: []u8, to: Endpoint) -> (bytes_written: int, err: UDP_Send_Error) {…}
     

    Sends a single UDP datagram packet.

    Datagrams are limited in size; attempting to send more than this limit at once will result in a Message_Too_Long error. UDP packets are not guarenteed to be received in order.

    set_blocking ¶

    set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Set_Blocking_Error) {…}

    set_last_platform_error ¶

    set_last_platform_error :: proc(err: i32) {…}

    set_option ¶

    set_option :: proc(socket: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Socket_Option_Error {…}

    shutdown ¶

    shutdown :: proc(socket: Any_Socket, manner: Shutdown_Manner) -> (err: Shutdown_Error) {…}

    skip_hostname ¶

    skip_hostname :: proc(packet: []u8, start_idx: int) -> (encode_size: int, ok: bool) {…}

    split_port ¶

    split_port :: proc(endpoint_str: string) -> (addr_or_host: string, port: int, ok: bool) {…}
     

    Takes an endpoint string and returns its parts. Returns ok=false if port is not a number.

    split_url ¶

    split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, path: string, queries: map[string]string, fragment: string) {…}

    unpack_dns_header ¶

    unpack_dns_header :: proc(id: u16be, bits: u16be) -> (hdr: DNS_Header) {…}

    validate_hostname ¶

    validate_hostname :: proc(hostname: string) -> (ok: bool) {…}
     

    Uses RFC 952 & RFC 1123

    Procedure Groups

    Source Files

    Generation Information

    Generated with odin version dev-2025-04 (vendor "odin") Windows_amd64 @ 2025-04-15 11:45:54.807983900 +0000 UTC