core/net

net

Types

62

Accept_Error

Accept_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. Insufficient_Resources = 2, // Invalid socket, or options. Invalid_Argument = 3, // The given socket does not support accepting connections. Unsupported_Socket = 4, // accept called on a socket which is not listening. Not_Listening = 5, // A connection arrived but was closed while in the listen queue. Aborted = 6, // Timed out before being able to accept a connection. Timeout = 7, // Non-blocking socket that would need to block waiting for a connection. Would_Block = 8, // Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows. Interrupted = 9, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 10, }Source

Bind_Error

Bind_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. Insufficient_Resources = 2, // Invalid socket or endpoint, or invalid combination of the two. Invalid_Argument = 3, // The socket is already bound to an address. Already_Bound = 4, // The address is protected and the current user has insufficient permissions to access it. Insufficient_Permissions_For_Address = 5, // The address is already in use. Address_In_Use = 6, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 7, }Source

Create_Socket_Error

Create_Socket_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. Insufficient_Resources = 2, // Invalid/unsupported family or protocol. Invalid_Argument = 3, // The user has no permission to create a socket of this type and/or protocol. Insufficient_Permissions = 4, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 5, }Source

DNS_Error

DNS_Error :: enum u32 { None = 0, Invalid_Hostname_Error = 1, Invalid_Hosts_Config_Error = 2, Invalid_Resolv_Config_Error = 3, Connection_Error = 4, Server_Error = 5, System_Error = 6, }Source

DNS_Query

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

DNS_Record_CNAME

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

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_MX

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

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 { base: DNS_Record_Base, host_name: string, }Source

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 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, 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, }Source

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_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 = DNS_TYPE_A, IP6 = DNS_TYPE_AAAA, CNAME = DNS_TYPE_CNAME, TXT = DNS_TYPE_TEXT, NS = DNS_TYPE_NS, MX = DNS_TYPE_MX, SRV = DNS_TYPE_SRV, }Source

Dial_Error

Dial_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. Insufficient_Resources = 2, // Invalid endpoint and/or options. Invalid_Argument = 3, // An attempt was made to connect to a broadcast socket on a socket that doesn't support it. Broadcast_Not_Supported = 4, // The socket is already connected. Already_Connected = 5, // The socket is already in the progress of making a connection. Already_Connecting = 6, // The address is already in use. Address_In_Use = 7, // Could not reach the remote host. Host_Unreachable = 8, // The remote host refused the connection or isn't listening. Refused = 9, // The connection was reset by the remote host. Reset = 10, // Timed out before making a connection. Timeout = 11, // Non-blocking socket that would need to block waiting to connect. Would_Block = 12, // Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows. Interrupted = 13, // Endpoint given without a port, which is required. Port_Required = 14, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 15, }Source

Listen_Error

Listen_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. Insufficient_Resources = 2, // The socket or backlog is invalid. Invalid_Argument = 3, // The socket is valid, but does not support listening. Unsupported_Socket = 4, // The socket is already connected. Already_Connected = 5, // The address is already in use. Address_In_Use = 6, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 7, }Source

Set_Blocking_Error

Set_Blocking_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Socket is invalid. Invalid_Argument = 2, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 3, }Source

Shutdown_Error

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

Socket

Socket :: i64Source

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.

Socket_Info_Error

Socket_Info_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. Insufficient_Resources = 2, // Socket is invalid or not connected, or the manner given is invalid. Invalid_Argument = 3, // The socket is valid, but unsupported by this opperation. Unsupported_Socket = 4, // Connection was closed/aborted/shutdown. Connection_Closed = 5, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 6, }Source

Socket_Option

Socket_Option :: enum i32 { Broadcast = i32(_SOCKET_OPTION_BROADCAST), Reuse_Address = i32(_SOCKET_OPTION_REUSE_ADDRESS), Keep_Alive = i32(_SOCKET_OPTION_KEEP_ALIVE), Out_Of_Bounds_Data_Inline = i32(_SOCKET_OPTION_OUT_OF_BOUNDS_DATA_INLINE), Linger = i32(_SOCKET_OPTION_LINGER), Receive_Buffer_Size = i32(_SOCKET_OPTION_RECEIVE_BUFFER_SIZE), Send_Buffer_Size = i32(_SOCKET_OPTION_SEND_BUFFER_SIZE), Receive_Timeout = i32(_SOCKET_OPTION_RECEIVE_TIMEOUT), Send_Timeout = i32(_SOCKET_OPTION_SEND_TIMEOUT), TCP_Nodelay = i32(_SOCKET_OPTION_TCP_NODELAY), Use_Loopback = i32(_SOCKET_OPTION_USE_LOOPBACK), Reuse_Port = i32(_SOCKET_OPTION_REUSE_PORT), No_SIGPIPE_From_EPIPE = i32(_SOCKET_OPTION_NO_SIGPIPE_FROM_EPIPE), Reuse_Port_Load_Balancing = i32(_SOCKET_OPTION_REUSE_PORT_LOAD_BALANCING), Exclusive_Addr_Use = i32(_SOCKET_OPTION_EXCLUSIVE_ADDR_USE), Conditional_Accept = i32(_SOCKET_OPTION_CONDITIONAL_ACCEPT), Dont_Linger = i32(_SOCKET_OPTION_DONT_LINGER), }Source

Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures.

For other protocols and their features, see subdirectories of this package.
Copyright 2022-2023 Tetralux        <tetraluxonpc@gmail.com>
	Copyright 2022-2023 Colin Davidson  <colrdavidson@gmail.com>
	Copyright 2022-2023 Jeroen van Rijn <nom@duclavier.com>.
	Copyright 2024 Feoramund       <rune@swevencraft.org>.
	Made available under Odin's license.

	List of contributors:
		Tetralux:        Initial implementation
		Colin Davidson:  Linux platform code, OSX platform code, Odin-native DNS resolver
		Jeroen van Rijn: Cross platform unification, code style, documentation
		Feoramund:       FreeBSD platform code

Socket_Option_Error

Socket_Option_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. Insufficient_Resources = 2, // Socket is invalid, not connected, or the connection has been closed/reset/shutdown. Invalid_Socket = 3, // Unknown or unsupported option for the socket. Invalid_Option = 4, // Invalid level or value. Invalid_Value = 5, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 6, }Source

TCP_Recv_Error

TCP_Recv_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. Insufficient_Resources = 2, // Invalid socket or buffer given. Invalid_Argument = 3, // The socket is not connected. Not_Connected = 4, // Connection was closed due to an error or shutdown. // NOTE: a graceful close is indicated by a `0, nil` (0 bytes received and no error) return. Connection_Closed = 5, // Timed out before being able to receive any data. Timeout = 6, // Non-blocking socket that would need to block waiting on data. Would_Block = 7, // Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows. Interrupted = 8, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 9, }Source

TCP_Send_Error

TCP_Send_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. Insufficient_Resources = 2, // Invalid socket or buffer given. Invalid_Argument = 3, // Connection was closed/broken/shutdown while sending data. Connection_Closed = 4, // The socket is not connected. Not_Connected = 5, // Could not reach the remote host. Host_Unreachable = 6, // Timed out before being able to send any data. Timeout = 7, // Non-blocking socket that would need to block waiting on the remote to be able to receive the data. Would_Block = 8, // Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows. Interrupted = 9, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 10, }Source

UDP_Recv_Error

UDP_Recv_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. Insufficient_Resources = 2, // Invalid socket or buffer given. Invalid_Argument = 3, // "Connection" was refused, or closed due to an error. // NOTE: a graceful close is indicated by a `0, nil` (0 bytes received and no error) return. Connection_Refused = 4, // Timed out before being able to receive any data. Timeout = 5, // Non-blocking socket that would need to block waiting on data. Would_Block = 6, // Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows. Interrupted = 7, // Linux and UDP only: indicates the buffer was too small to receive all data, and the excess is truncated and discarded. Excess_Truncated = 8, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 9, }Source

UDP_Send_Error

UDP_Send_Error :: enum i32 { None = 0, // No network connection, or the network stack is not initialized. Network_Unreachable = 1, // Not enough space in internal tables/buffers to create a new socket, or an unsupported protocol is given. Insufficient_Resources = 2, // Invalid socket or buffer given. Invalid_Argument = 3, // Could not reach the remote host. Host_Unreachable = 4, // "Connection" was refused by remote, or closed/broken/shutdown while sending data. Connection_Refused = 5, // Timed out before being able to send any data. Timeout = 6, // Non-blocking socket that would need to block waiting on the remote to be able to receive the data. Would_Block = 7, // Interrupted by a signal or other method of cancellation like WSACancelBlockingCall on Windows. Interrupted = 8, // An error unable to be categorized in above categories, `last_platform_error` may have more info. Unknown = 9, }Source

Constants

39

IPv6_MIN_STRING_LENGTH

IPv6_MIN_STRING_LENGTH :: 2Source

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)

NAME_MAX

NAME_MAX :: 255Source

TODO(cloin): Does the DNS Resolver need to recursively hop through CNAMEs to get the IP

or is that what recursion desired does? Do we need to handle recursion unavailable?
	How do we deal with is_authoritative / is_truncated?

ODIN_NET_TCP_NODELAY_DEFAULT

ODIN_NET_TCP_NODELAY_DEFAULT :: _ = #config(ODIN_NET_TCP_NODELAY_DEFAULT, true)Source

TUNEABLES - See also top of dns.odin for DNS configuration.

Determines the default value for whether dial_tcp() and accept_tcp() will set TCP_NODELAY on the new
	socket, and the client socket, respectively.
	This can also be set on a per-socket basis using the 'options' optional parameter to those procedures.

	When TCP_NODELAY is set, data will be sent out to the peer as quickly as possible, rather than being
	coalesced into fewer network packets.

	This makes the networking layer more eagerly send data when you ask it to,
	which can reduce latency by up to 200ms.

	This does mean that a lot of small writes will negatively effect throughput however,
	since the Nagle algorithm will be disabled, and each write becomes one
	IP packet. This will increase traffic by a factor of 40, with IP and TCP
	headers for each payload.

	However, you can avoid this by buffering things up yourself if you wish to send a lot of
	short data chunks, when TCP_NODELAY is enabled on that socket.

Variables

1

Procedures

90

aton

aton :: proc(address_and_maybe_port: string, family: Address_Family, allow_decimal_only: untyped boolean = false) -> (addr: Address, ok: bool)Source

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.

dial_tcp_from_hostname_and_port_string

dial_tcp_from_hostname_and_port_string :: proc(hostname_and_port: string, options = DEFAULT_TCP_OPTIONS) -> (socket: TCP_Socket, err: Network_Error)Source

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 = DEFAULT_TCP_OPTIONS) -> (socket: TCP_Socket, err: Network_Error)Source

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`

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: mem.Allocator = context.allocator) -> (records: []DNS_Record, err: DNS_Error)Source

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: mem.Allocator = context.allocator) -> (records: []DNS_Record, err: DNS_Error)Source

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`.

last_platform_error

last_platform_error :: proc() -> (i32)Source

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)

listen_tcp

listen_tcp :: proc(interface_endpoint: Endpoint, backlog: untyped integer = 1000) -> (socket: TCP_Socket, err: Network_Error)Source

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

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

make_bound_udp_socket

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

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`

parse_address

parse_address :: proc(address_and_maybe_port: string, non_decimal_address: untyped boolean = false) -> (Address)Source

Try parsing as an IPv6 address.

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

parse_ip4_address

parse_ip4_address :: proc(address_and_maybe_port: string, allow_non_decimal: untyped boolean = false) -> (addr: IP4_Address, ok: bool)Source

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_ip_component

parse_ip_component :: proc(input: string, max_value: u64 = u64(max(u32)), bases = DEFAULT_DIGIT_BASES) -> (value: u64, bytes_consumed: int, ok: bool)Source

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.

recv_any

recv_any :: proc(socket: Any_Socket, buf: []u8) -> (bytes_read: int, remote_endpoint: Maybe(Endpoint), err: Network_Error)Source

Receive data 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`.

	If no error occurs, `recv_any` returns the number of bytes received and `buf` will contain this data received.
	If the connection has been gracefully closed, the return value is `0, nil, nil` (0 bytes read and no error).

recv_tcp

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

Receive data into a buffer from a TCP socket.

If no error occurs, `recv_tcp` returns the number of bytes received and `buf` will contain this data received.
	If the connection has been gracefully closed, the return value is `0, nil` (0 bytes read and no error).

recv_udp

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

Receive data into a buffer from a UDP socket.

If no error occurs, `recv_udp` returns the number of bytes received and `buf` will contain this data received.
	If the "connection" has been gracefully closed, the return value is `0, nil` (0 bytes read and no error).

resolve

resolve :: proc(hostname_and_maybe_port: string) -> (ep4: Endpoint, ep6: Endpoint, err: Network_Error)Source

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.

send_udp

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

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.

Procedure Groups

7

Reference search

Find anything

Documentation preferences

Settings

System theme variants

Used only while Theme is set to System.