package core:net
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 (61)
- Accept_Error
- Address
- Address_Duplication
- Address_Family
- Any_Socket
- Bind_Error
- Create_Socket_Error
- DNS_Configuration
- DNS_Error
- DNS_Header
- DNS_Host_Entry
- DNS_Query
- DNS_Record
- DNS_Record_Base
- DNS_Record_CNAME
- DNS_Record_Header
- DNS_Record_IP4
- DNS_Record_IP6
- DNS_Record_MX
- DNS_Record_NS
- DNS_Record_SRV
- DNS_Record_TXT
- DNS_Record_Type
- DNS_Response_Code
- Dial_Error
- Digit_Parse_Base
- Digit_Parse_Bases
- Endpoint
- General_Error
- Host
- Host_Or_Endpoint
- IP4_Address
- IP6_Address
- Lease
- Link_State
- Link_States
- Listen_Error
- Maybe
- Netmask
- Network_Error
- Network_Interface
- Parse_Endpoint_Error
- Platform_Error
- Prefix_Origin
- Resolve_Error
- Set_Blocking_Error
- Shutdown_Error
- Shutdown_Manner
- Socket
- Socket_Option
- Socket_Option_Error
- Socket_Protocol
- Suffix_Origin
- TCP_Options
- TCP_Recv_Error
- TCP_Send_Error
- TCP_Socket
- Tunnel_Type
- UDP_Recv_Error
- UDP_Send_Error
- UDP_Socket
Variables (4)
Procedures (64)
- accept_tcp
- address_to_string
- any_socket_to_socket
- aton
- bind
- bound_endpoint
- close
- create_socket
- decode_hostname
- destroy_dns_configuration
- destroy_dns_records
- destroy_interfaces
- dial_tcp_from_address_and_port
- dial_tcp_from_endpoint
- dial_tcp_from_hostname_and_port_string
- dial_tcp_from_hostname_with_port_override
- encode_hostname
- endpoint_to_string
- enumerate_interfaces
- family_from_address
- family_from_endpoint
- get_dns_records_from_nameservers
- get_dns_records_from_os
- get_network_interfaces
- init_dns_configuration
- join_port
- join_url
- listen_tcp
- load_hosts
- load_resolv_conf
- make_bound_udp_socket
- make_unbound_udp_socket
- map_to_ip6
- pack_dns_header
- parse_address
- parse_endpoint
- parse_hostname_or_endpoint
- parse_ip4_address
- parse_ip6_address
- parse_ip_component
- parse_record
- parse_response
- parse_socket_address
- percent_decode
- percent_encode
- physical_address_to_string
- recv_any
- recv_tcp
- recv_udp
- replace_environment_path
- resolve
- resolve_ip4
- resolve_ip6
- send_any
- send_tcp
- send_udp
- set_blocking
- set_option
- shutdown
- skip_hostname
- split_port
- split_url
- unpack_dns_header
- validate_hostname
Types
Accept_Error ¶
Accept_Error :: enum i32 { None = 0, Not_Listening = 10022, No_Socket_Descriptors_Available_For_Client_Socket = 10024, No_Buffer_Space_Available = 10055, Not_Socket = 10038, Not_Connection_Oriented_Socket = 10045, // TODO: we may need special handling for this; maybe make a socket a struct with metadata? Would_Block = 10035, }
Address ¶
Address :: union { IP4_Address, IP6_Address, }
Related Procedures With Parameters
- address_to_string
- dial_tcp_from_address_and_port
- family_from_address
- make_bound_udp_socket
- map_to_ip6
- dial_tcp (procedure groups)
- to_string (procedure groups)
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
- any_socket_to_socket
- bind
- bound_endpoint
- close
- recv_any
- send_any
- set_blocking
- set_option
- shutdown
- recv (procedure groups)
- send (procedure groups)
Related Procedures With Returns
Bind_Error ¶
Bind_Error :: enum i32 { None = 0, Address_In_Use = 10048, // Another application is currently bound to this endpoint. Given_Nonlocal_Address = 10049, // The address is not a local address on this machine. Broadcast_Disabled = 10013, // To bind a UDP socket to the broadcast address, the appropriate socket option must be set. Address_Family_Mismatch = 10014, // The address family of the address does not match that of the socket. Already_Bound = 10022, // The socket is already bound to an address. No_Ports_Available = 10055, // There are not enough ephemeral ports available. }
Create_Socket_Error ¶
Create_Socket_Error :: enum i32 { None = 0, Network_Subsystem_Failure = 10050, Family_Not_Supported_For_This_Socket = 10047, No_Socket_Descriptors_Available = 10024, No_Buffer_Space_Available = 10055, Protocol_Unsupported_By_System = 10043, Wrong_Protocol_For_Socket = 10041, Family_And_Socket_Type_Mismatch = 10044, }
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 { 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_Query ¶
DNS_Query :: enum u16be { Host_Address = 1, Authoritative_Name_Server = 2, Mail_Destination = 3, Mail_Forwarder = 4, CNAME = 5, All = 255, }
DNS_Record ¶
DNS_Record :: union { DNS_Record_IP4, DNS_Record_IP6, DNS_Record_CNAME, DNS_Record_TXT, DNS_Record_NS, DNS_Record_MX, DNS_Record_SRV, }
Related Procedures With Returns
DNS_Record_Base ¶
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_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 = 0, Port_Required = -1, Address_In_Use = 10048, In_Progress = 10037, Cannot_Use_Any_Address = 10049, Wrong_Family_For_Socket = 10047, Refused = 10061, Is_Listening_Socket = 10022, Already_Connected = 10056, Network_Unreachable = 10051, // Device is offline Host_Unreachable = 10065, // Remote host cannot be reached No_Buffer_Space_Available = 10055, Not_Socket = 10038, Timeout = 10060, Would_Block = 10035, // TODO: we may need special handling for this; maybe make a socket a struct with metadata? }
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. }
Endpoint ¶
Related Procedures With Parameters
- bind
- dial_tcp_from_endpoint
- endpoint_to_string
- family_from_endpoint
- listen_tcp
- send_udp
- dial_tcp (procedure groups)
- send (procedure groups)
- to_string (procedure groups)
Related Procedures With Returns
- accept_tcp
- bound_endpoint
- parse_endpoint
- parse_socket_address
- recv_udp
- resolve
- resolve_ip4
- resolve_ip6
- recv (procedure groups)
General_Error ¶
General_Error :: enum u32 { None = 0, Unable_To_Enumerate_Network_Interfaces = 1, }
Host_Or_Endpoint ¶
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 ¶
Link_State :: bit_set[Link_States; u32]
Link_States ¶
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 = 0, Address_In_Use = 10048, Already_Connected = 10056, No_Socket_Descriptors_Available = 10024, No_Buffer_Space_Available = 10055, Nonlocal_Address = 10049, Not_Socket = 10038, Listening_Not_Supported_For_This_Socket = 10045, }
Maybe ¶
Maybe :: runtime.Maybe
COMMON DEFINITIONS
Related Procedures With Parameters
Related Procedures With Returns
Netmask ¶
Netmask :: union { IP4_Address, IP6_Address, }
Network_Error ¶
Network_Error :: union { General_Error, Platform_Error, Create_Socket_Error, Dial_Error, Listen_Error, Accept_Error, Bind_Error, TCP_Send_Error, UDP_Send_Error, TCP_Recv_Error, UDP_Recv_Error, Shutdown_Error, Socket_Option_Error, Set_Blocking_Error, Parse_Endpoint_Error, Resolve_Error, DNS_Error, }
Related Procedures With Returns
- accept_tcp
- bind
- bound_endpoint
- create_socket
- dial_tcp_from_address_and_port
- dial_tcp_from_endpoint
- dial_tcp_from_hostname_and_port_string
- dial_tcp_from_hostname_with_port_override
- enumerate_interfaces
- listen_tcp
- make_bound_udp_socket
- make_unbound_udp_socket
- recv_any
- recv_tcp
- recv_udp
- resolve
- resolve_ip4
- resolve_ip6
- send_any
- send_tcp
- send_udp
- set_blocking
- set_option
- shutdown
- dial_tcp (procedure groups)
- recv (procedure groups)
- send (procedure groups)
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
Platform_Error ¶
Platform_Error :: enum u32 { }
Platform_Error
is used to wrap errors returned by the different platforms that don't fit a common error.
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 = 0, Network_Subsystem_Failure = 10050, Blocking_Call_In_Progress = 10036, Not_Socket = 10038, // TODO: are those errors possible? Network_Subsystem_Not_Initialized = 10093, Invalid_Argument_Pointer = 10014, }
Shutdown_Error ¶
Shutdown_Error :: enum i32 { None = 0, Aborted = 10053, Reset = 10054, Offline = 10050, Not_Connected = 10057, Not_Socket = 10038, Invalid_Manner = 10022, }
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 = 0, Linger_Only_Supports_Whole_Seconds = 1, // The given value is too big or small to be given to the OS. Value_Out_Of_Range, Network_Subsystem_Failure = 10050, Timeout_When_Keepalive_Set = 10052, Invalid_Option_For_Socket = 10042, Reset_When_Keepalive_Set = 10057, Not_Socket = 10038, }
Suffix_Origin ¶
Suffix_Origin :: enum i32 { Other = 0, Manual = 1, Well_Known = 2, DHCP = 3, Link_Layer_Address = 4, Random = 5, Unchanged = 16, }
TCP_Options ¶
TCP_Options :: struct { no_delay: bool, }
SOCKET OPTIONS & DEFINITIONS
Related Procedures With Parameters
TCP_Recv_Error ¶
TCP_Recv_Error :: enum i32 { None = 0, Network_Subsystem_Failure = 10050, Not_Connected = 10057, Bad_Buffer = 10014, Keepalive_Failure = 10052, Not_Socket = 10038, Shutdown = 10058, Would_Block = 10035, Aborted = 10053, Timeout = 10060, // TODO(tetra): Determine when this is different from the syscall returning n=0 and maybe normalize them? Connection_Closed = 10054, // TODO: verify can actually happen Host_Unreachable = 10065, }
TCP_Send_Error ¶
TCP_Send_Error :: enum i32 { None = 0, Aborted = 10053, Not_Connected = 10057, Shutdown = 10058, Connection_Closed = 10054, No_Buffer_Space_Available = 10055, Network_Subsystem_Failure = 10050, Host_Unreachable = 10065, Would_Block = 10035, // TODO: verify possible, as not mentioned in docs Offline = 10051, Timeout = 10060, // A broadcast address was specified, but the .Broadcast socket option isn't set. Broadcast_Disabled = 10013, Bad_Buffer = 10014, // Connection is broken due to keepalive activity detecting a failure during the operation. Keepalive_Failure = 10052, // TODO: not functionally different from Reset; merge? Not_Socket = 10038, // The so-called socket is not an open socket. }
TODO: consider merging some errors to make handling them easier TODO: verify once more what errors to actually expose
TCP_Socket ¶
TCP_Socket :: distinct i64
Related Procedures With Parameters
- accept_tcp
- recv_tcp
- send_tcp
- recv (procedure groups)
- send (procedure groups)
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 = 0, Network_Subsystem_Failure = 10050, Aborted = 10053, Buffer_Too_Small = 10040, // The buffer is too small to fit the entire message, and the message was truncated. When this happens, the rest of message is lost. Remote_Not_Listening = 10054, // The machine at the remote endpoint doesn't have the given port open to receiving UDP data. Shutdown = 10058, Broadcast_Disabled = 10013, // A broadcast address was specified, but the .Broadcast socket option isn't set. Bad_Buffer = 10014, No_Buffer_Space_Available = 10055, Not_Socket = 10038, // The socket is not valid socket handle. Would_Block = 10035, Host_Unreachable = 10065, // The remote host cannot be reached from this host at this time. Offline = 10051, // The network cannot be reached from this host at this time. Timeout = 10060, // TODO: can this actually happen? The socket isn't bound; an unknown flag specified; or MSG_OOB specified with SO_OOBINLINE enabled. Incorrectly_Configured = 10022, TTL_Expired = 10052, // The message took more hops than was allowed (the Time To Live) to reach the remote endpoint. }
UDP_Send_Error ¶
UDP_Send_Error :: enum i32 { None = 0, Network_Subsystem_Failure = 10050, Aborted = 10053, Message_Too_Long = 10040, // The message is larger than the maximum UDP packet size. Remote_Not_Listening = 10054, // The machine at the remote endpoint doesn't have the given port open to receiving UDP data. Shutdown = 10058, // A broadcast address was specified, but the .Broadcast socket option isn't set. Broadcast_Disabled = 10013, Bad_Buffer = 10014, // Connection is broken due to keepalive activity detecting a failure during the operation. // TODO: not functionally different from Reset; merge? Keepalive_Failure = 10052, No_Buffer_Space_Available = 10055, Not_Socket = 10038, // The socket is not valid socket handle. // This socket is unidirectional and cannot be used to send any data. // TODO: verify possible; decide whether to keep if not Receive_Only = 10045, Would_Block = 10035, Host_Unreachable = 10065, // The remote host cannot be reached from this host at this time. Cannot_Use_Any_Address = 10049, // Attempt to send to the Any address. Family_Not_Supported_For_This_Socket = 10047, // The address is of an incorrect address family for this socket. Offline = 10051, // The network cannot be reached from this host at this time. Timeout = 10060, }
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 :: 45
IPv6_MIN_COLONS ¶
IPv6_MIN_COLONS :: 2
IPv6_MIN_STRING_LENGTH ¶
IPv6_MIN_STRING_LENGTH :: 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 :: 8
LABEL_MAX ¶
LABEL_MAX :: 63
MAX_INTERFACE_ENUMERATION_TRIES ¶
MAX_INTERFACE_ENUMERATION_TRIES :: 3
NAME_MAX ¶
NAME_MAX :: 255
ODIN_NET_TCP_NODELAY_DEFAULT ¶
ODIN_NET_TCP_NODELAY_DEFAULT :: #config(ODIN_NET_TCP_NODELAY_DEFAULT, true)
Variables
IP4_Any ¶
IP4_Any: IP4_Address = …
IP6_Any ¶
IP6_Any: IP6_Address = …
default_tcp_options ¶
default_tcp_options: TCP_Options = …
dns_configuration ¶
dns_configuration: DNS_Configuration = …
Procedures
accept_tcp ¶
accept_tcp :: proc(socket: TCP_Socket, options: TCP_Options = default_tcp_options) -> (client: TCP_Socket, source: Endpoint, err: Network_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: Network_Error) {…}
bound_endpoint ¶
bound_endpoint :: proc(socket: Any_Socket) -> (endpoint: Endpoint, err: Network_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: Network_Error) {…}
destroy_dns_configuration ¶
destroy_dns_configuration :: proc() {…}
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
dial_tcp_from_endpoint ¶
dial_tcp_from_endpoint :: proc(endpoint: Endpoint, options: TCP_Options = default_tcp_options) -> (socket: TCP_Socket, err: Network_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 resolve
, then dial_tcp_from_endpoint
.
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.
encode_hostname ¶
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: Network_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.
listen_tcp ¶
listen_tcp :: proc(interface_endpoint: Endpoint, backlog: int = 1000) -> (socket: TCP_Socket, err: Network_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.
make_unbound_udp_socket ¶
make_unbound_udp_socket :: proc(family: Address_Family) -> (socket: UDP_Socket, err: Network_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.
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_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, 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
.
recv_tcp ¶
recv_tcp :: proc(socket: TCP_Socket, buf: []u8) -> (bytes_read: int, err: Network_Error) {…}
recv_udp ¶
recv_udp :: proc(socket: UDP_Socket, buf: []u8) -> (bytes_read: int, remote_endpoint: Endpoint, err: Network_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) {…}
send_tcp ¶
send_tcp :: proc(socket: TCP_Socket, buf: []u8) -> (bytes_written: int, err: Network_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: Network_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: Network_Error) {…}
set_option ¶
set_option :: proc(socket: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Network_Error {…}
shutdown ¶
shutdown :: proc(socket: Any_Socket, manner: Shutdown_Manner) -> (err: Network_Error) {…}
split_port ¶
Takes an endpoint string and returns its parts. Returns ok=false if port is not a number.
unpack_dns_header ¶
unpack_dns_header :: proc(id: u16be, bits: u16be) -> (hdr: DNS_Header) {…}
validate_hostname ¶
Uses RFC 952 & RFC 1123
Procedure Groups
to_string ¶
to_string :: proc{ address_to_string, endpoint_to_string, }
Source Files
- addr.odin
- common.odin
- dns.odin
- doc.odin
- interface.odin
- socket.odin
- url.odin
- (hidden platform specific files)
Generation Information
Generated with odin version dev-2024-12 (vendor "odin") Windows_amd64 @ 2024-12-17 21:11:01.189017200 +0000 UTC