Update comments

This commit is contained in:
Jeroen van Rijn
2023-03-02 13:45:12 +01:00
parent 13c6352b8e
commit c02ff3af27
8 changed files with 100 additions and 211 deletions

View File

@@ -31,10 +31,10 @@ import "core:fmt"
The port, if present, is required to be a base 10 number in the range 0-65535, inclusive.
If `non_decimal_address` is true, `aton` is told each component must be decimal and max 255.
If `allow_non_decimal` is true, `aton` is told each component must be decimal and max 255.
*/
parse_ip4_address :: proc(address_and_maybe_port: string, non_decimal_address := false) -> (addr: IP4_Address, ok: bool) {
res, res_ok := aton(address_and_maybe_port, .IP4, !non_decimal_address)
parse_ip4_address :: proc(address_and_maybe_port: string, allow_non_decimal := false) -> (addr: IP4_Address, ok: bool) {
res, res_ok := aton(address_and_maybe_port, .IP4, !allow_non_decimal)
if ip4, ip4_ok := res.(IP4_Address); ip4_ok {
return ip4, res_ok
}
@@ -58,12 +58,10 @@ parse_ip4_address :: proc(address_and_maybe_port: string, non_decimal_address :=
The port, if present, is required to be a base 10 number in the range 0-65535, inclusive.
*/
aton :: proc(address_and_maybe_port: string, family: Address_Family, is_decimal_only := false) -> (addr: Address, ok: bool) {
aton :: proc(address_and_maybe_port: string, family: Address_Family, allow_decimal_only := false) -> (addr: Address, ok: bool) {
switch family {
case .IP4:
/*
There is no valid address shorter than `0.0.0.0`.
*/
// There is no valid address shorter than `0.0.0.0`.
if len(address_and_maybe_port) < 7 {
return {}, false
}
@@ -76,7 +74,7 @@ aton :: proc(address_and_maybe_port: string, family: Address_Family, is_decimal_
max_value := u64(max(u32))
bases := DEFAULT_DIGIT_BASES
if is_decimal_only {
if allow_decimal_only {
max_value = 255
bases = {.Dec}
}
@@ -86,10 +84,8 @@ aton :: proc(address_and_maybe_port: string, family: Address_Family, is_decimal_
return {}, false
}
/*
Decimal-only addresses may not have a leading zero.
*/
if is_decimal_only && len(address) > 1 && address[0] == '0' && address[1] != '.' {
// Decimal-only addresses may not have a leading zero.
if allow_decimal_only && len(address) > 1 && address[0] == '0' && address[1] != '.' {
return
}
@@ -108,9 +104,7 @@ aton :: proc(address_and_maybe_port: string, family: Address_Family, is_decimal_
i += 1
}
/*
Distribute parts.
*/
// Distribute parts.
switch i {
case 1:
buf[1] = buf[0] & 0xffffff
@@ -155,14 +149,10 @@ IPv6_MIN_COLONS :: 2
IPv6_PIECE_COUNT :: 8
parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address, ok: bool) {
/*
If we have an IPv6 address of the form [IP]:Port, first get us just the IP.
*/
// If we have an IPv6 address of the form [IP]:Port, first get us just the IP.
address, _ := split_port(address_and_maybe_port) or_return
/*
Early bailouts based on length and number of pieces.
*/
// Early bailouts based on length and number of pieces.
if len(address) < IPv6_MIN_STRING_LENGTH || len(address) > IPv6_MAX_STRING_LENGTH { return }
/*
@@ -186,10 +176,7 @@ parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address,
piece_end += 1
case ':':
/*
If we see a `:` after a `.`, it means an IPv4 part was sandwiched between IPv6,
instead of it being the tail: invalid.
*/
// If we see a `:` after a `.`, it means an IPv4 part was sandwiched between IPv6, instead of it being the tail: invalid.
if dot_count > 0 { return }
pieces_temp[colon_count] = address[piece_start:piece_end]
@@ -197,19 +184,14 @@ parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address,
colon_count += 1
if colon_count > IPv6_PIECE_COUNT { return }
/*
If there's anything left, put it in the next piece.
*/
// If there's anything left, put it in the next piece.
piece_start = i + 1
piece_end = piece_start
case '.':
/*
IPv4 address is treated as one piece. No need to update `piece_*`.
*/
// IPv4 address is treated as one piece. No need to update `piece_*`.
dot_count += 1
case: // Invalid character, return early
return
}
@@ -217,19 +199,13 @@ parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address,
if colon_count < IPv6_MIN_COLONS { return }
/*
Assign the last piece string.
*/
// Assign the last piece string.
pieces_temp[colon_count] = address[piece_start:]
/*
`pieces` now holds the same output as it would if had used `strings.split`.
*/
// `pieces` now holds the same output as it would if had used `strings.split`.
pieces := pieces_temp[:colon_count + 1]
/*
Check if we have what looks like an embedded IPv4 address.
*/
// Check if we have what looks like an embedded IPv4 address.
ipv4: IP4_Address
have_ipv4: bool
@@ -252,19 +228,12 @@ parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address,
if !have_ipv4 { return }
}
/*
Check for `::` being used more than once, and save the skip.
*/
// Check for `::` being used more than once, and save the skip.
zero_skip := -1
for i in 1..<len(pieces) - 1 {
for i in 1..<colon_count {
if pieces[i] == "" {
/*
Return if skip has already been set.
*/
if zero_skip != -1 {
return
}
// Return if skip has already been set.
if zero_skip != -1 { return }
zero_skip = i
}
}
@@ -279,28 +248,22 @@ parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address,
if zero_skip != -1 {
before_skip = zero_skip
after_skip = len(pieces) - zero_skip - 1
after_skip = colon_count - zero_skip
/*
An IPv4 "piece" accounts for 2 IPv6 pieces we haven't added to the pieces slice, so add 1.
*/
// An IPv4 "piece" accounts for 2 IPv6 pieces we haven't added to the pieces slice, so add 1.
if have_ipv4 {
after_skip += 1
}
/*
Adjust for leading `::`.
*/
// Adjust for leading `::`.
if pieces[0] == "" {
before_skip -= 1
// Leading `:` can only be part of `::`.
if before_skip > 0 { return }
}
/*
Adjust for trailing `::`.
*/
if pieces[len(pieces) - 1] == "" {
// Adjust for trailing `::`.
if pieces[colon_count] == "" {
after_skip -= 1
// Trailing `:` can only be part of `::`.
if after_skip > 0 { return }
@@ -318,20 +281,16 @@ parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address,
No zero skip means everything is part of "before the skip".
An IPv4 "piece" accounts for 2 IPv6 pieces we haven't added to the pieces slice, so add 1.
*/
piece_count := len(pieces)
piece_count := colon_count + 1
if have_ipv4 {
piece_count += 1
}
/*
Do we have the complete set?
*/
// Do we have the complete set?
if piece_count != IPv6_PIECE_COUNT { return }
/*
Validate leading and trailing empty parts, as they can only be part of a `::`.
*/
if pieces[0] == "" || pieces[len(pieces) - 1] == "" { return }
// Validate leading and trailing empty parts, as they can only be part of a `::`.
if pieces[0] == "" || pieces[colon_count] == "" { return }
before_skip = piece_count
@@ -339,9 +298,7 @@ parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address,
num_skipped = 0
}
/*
Now try to parse the pieces into a 8 16-bit pieces.
*/
// Now try to parse the pieces into a 8 16-bit pieces.
piece_values: [IPv6_PIECE_COUNT]u16be
idx := 0
@@ -358,9 +315,7 @@ parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address,
piece := pieces[idx]
/*
An IPv6 piece can at most contain 4 hex digits.
*/
// An IPv6 piece can at most contain 4 hex digits.
if len(piece) > 4 { return }
if piece != "" {
@@ -393,9 +348,7 @@ parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address,
piece := pieces[idx]
/*
An IPv6 piece can at most contain 4 hex digits.
*/
// An IPv6 piece can contain at most 4 hex digits.
if len(piece) > 4 { return }
if piece != "" {
@@ -408,20 +361,16 @@ parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address,
}
}
/*
Distribute IPv4 address into last two pieces, if applicable.
*/
// Distribute IPv4 address into last two pieces, if applicable.
if have_ipv4 {
val := u16(ipv4[0]) << 8
val |= u16(ipv4[1])
piece_values[6] = u16be(val)
val = u16(ipv4[2]) << 8
val |= u16(ipv4[3])
piece_values[7] = u16be(val)
}
return transmute(IP6_Address)piece_values, true
}
@@ -430,22 +379,21 @@ parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address,
If it's determined not to be, try as an IPv4 address, optionally in non-decimal format.
*/
parse_address :: proc(address_and_maybe_port: string, non_decimal_address := false) -> Address {
addr6, ok6 := parse_ip6_address(address_and_maybe_port)
if ok6 do return addr6
addr4, ok4 := parse_ip4_address(address_and_maybe_port, non_decimal_address)
if ok4 do return addr4
if addr6, ok6 := parse_ip6_address(address_and_maybe_port); ok6 {
return addr6
}
if addr4, ok4 := parse_ip4_address(address_and_maybe_port, non_decimal_address); ok4 {
return addr4
}
return nil
}
parse_endpoint :: proc(endpoint_str: string) -> (ep: Endpoint, ok: bool) {
addr_str, port, split_ok := split_port(endpoint_str)
if !split_ok do return
addr := parse_address(addr_str)
if addr == nil do return
ep = Endpoint { address = addr, port = port }
ok = true
if addr_str, port, split_ok := split_port(endpoint_str); split_ok {
if addr := parse_address(addr_str); addr != nil {
return Endpoint { address = addr, port = port }, true
}
}
return
}
@@ -565,9 +513,7 @@ address_to_string :: proc(addr: Address, allocator := context.temp_allocator) ->
case IP4_Address:
fmt.sbprintf(&b, "%v.%v.%v.%v", v[0], v[1], v[2], v[3])
case IP6_Address:
/*
First find the longest run of zeroes.
*/
// First find the longest run of zeroes.
Zero_Run :: struct {
start: int,
end: int,
@@ -609,9 +555,7 @@ address_to_string :: proc(addr: Address, allocator := context.temp_allocator) ->
}
}
/*
If we were in a run, this is where we reset it.
*/
// If we were in a run, this is where we reset it.
if val != 0 {
run = {-1, -1}
}
@@ -621,9 +565,7 @@ address_to_string :: proc(addr: Address, allocator := context.temp_allocator) ->
for val, i in addr {
if best.start == i || best.end == i {
/*
For the left and right side of the best zero run, print a `:`.
*/
// For the left and right side of the best zero run, print a `:`.
fmt.sbprint(&b, ":")
} else if i < best.start {
/*
@@ -710,9 +652,7 @@ DEFAULT_DIGIT_BASES :: Digit_Parse_Bases{.Dec, .Oct, .Hex}
Numbers will otherwise be considered to be in base 10.
*/
parse_ip_component :: proc(input: string, max_value := u64(max(u32)), bases := DEFAULT_DIGIT_BASES) -> (value: u64, bytes_consumed: int, ok: bool) {
/*
Default to base 10
*/
// Default to base 10
base := u64(10)
input := input
@@ -732,9 +672,7 @@ parse_ip_component :: proc(input: string, max_value := u64(max(u32)), bases := D
if bases != {.IPv6} { return } // Must be used on its own.
base = 16
} else {
/*
Scan for and consume prefix, if applicable.
*/
// Scan for and consume prefix, if applicable.
if len(input) >= 2 && input[0] == '0' {
if .Hex in bases && (input[1] == 'x' || input[1] == 'X') {
base = 16
@@ -759,9 +697,7 @@ parse_ip_component :: proc(input: string, max_value := u64(max(u32)), bases := D
digit_bytes += 1
if base == 8 {
/*
Out of range for octal numbers.
*/
// Out of range for octal numbers.
return value, digit_bytes + prefix_bytes, false
}
value = value * base + u64(ch - '0')
@@ -770,9 +706,7 @@ parse_ip_component :: proc(input: string, max_value := u64(max(u32)), bases := D
digit_bytes += 1
if base == 8 || base == 10 {
/*
Out of range for octal and decimal numbers.
*/
// Out of range for octal and decimal numbers.
return value, digit_bytes + prefix_bytes, false
}
value = value * base + (u64(ch - 'a') + 10)
@@ -781,9 +715,7 @@ parse_ip_component :: proc(input: string, max_value := u64(max(u32)), bases := D
digit_bytes += 1
if base == 8 || base == 10 {
/*
Out of range for octal and decimal numbers.
*/
// Out of range for octal and decimal numbers.
return value, digit_bytes + prefix_bytes, false
}
value = value * base + (u64(ch - 'A') + 10)
@@ -797,22 +729,16 @@ parse_ip_component :: proc(input: string, max_value := u64(max(u32)), bases := D
break parse_loop
case:
/*
Invalid character encountered.
*/
// Invalid character encountered.
return value, digit_bytes + prefix_bytes, false
}
if value > max_value {
/*
Out-of-range number.
*/
// Out-of-range number.
return value, digit_bytes + prefix_bytes, false
}
}
/*
If we consumed at least 1 digit byte, `value` *should* continue a valid number in an appropriate base in the allowable range.
*/
// If we consumed at least 1 digit byte, `value` *should* continue a valid number in an appropriate base in the allowable range.
return value, digit_bytes + prefix_bytes, digit_bytes >= 1
}
}

View File

@@ -84,8 +84,7 @@ sockaddr_basic_to_endpoint :: proc(native_addr: ^os.SOCKADDR) -> (ep: Endpoint)
port = port,
}
case:
//panic("native_addr is neither IP4 or IP6 address")
return {}
panic("native_addr is neither IP4 or IP6 address")
}
return
}

View File

@@ -22,10 +22,8 @@ package net
import "core:runtime"
/*
TUNEABLES
*/
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.
@@ -44,25 +42,17 @@ import "core:runtime"
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.
*/
ODIN_NET_TCP_NODELAY_DEFAULT :: #config(ODIN_NET_TCP_NODELAY_DEFAULT, true)
/*
See also top of `dns.odin` for DNS configuration.
*/
/*
COMMON DEFINITIONS
*/
// COMMON DEFINITIONS
Maybe :: runtime.Maybe
General_Error :: enum {
Unable_To_Enumerate_Network_Interfaces = 1,
}
/*
`Platform_Error` is used to wrap errors returned by the different platforms that defy translation into a common error.
*/
// `Platform_Error` is used to wrap errors returned by the different platforms that don't fit a common error.
Platform_Error :: enum u32 {}
/*
@@ -93,7 +83,6 @@ Network_Error :: union {
DNS_Error,
}
Resolve_Error :: enum {
Unable_To_Resolve = 1,
}
@@ -107,10 +96,7 @@ DNS_Error :: enum {
System_Error,
}
/*
SOCKET OPTIONS & DEFINITIONS
*/
// SOCKET OPTIONS & DEFINITIONS
TCP_Options :: struct {
no_delay: bool,
}
@@ -195,9 +181,7 @@ Network_Interface :: struct {
},
}
/*
Empty bit set is unknown state.
*/
// Empty bit set is unknown state.
Link_States :: enum u32 {
Up = 1,
Down = 2,
@@ -261,18 +245,14 @@ Address_Duplication :: enum i32 {
Preferred = 4,
}
/*
DNS DEFINITIONS
*/
// DNS DEFINITIONS
DNS_Configuration :: struct {
/*
Configuration files.
*/
// 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.
// 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,
}
@@ -295,25 +275,19 @@ DNS_Record_Type :: enum u16 {
SRV = DNS_TYPE_SRV,
}
/*
Base DNS Record. All DNS responses will carry a hostname and TTL (time to live) field.
*/
// Base DNS Record. All DNS responses will carry a hostname and TTL (time to live) field.
DNS_Record_Base :: struct {
record_name: string,
ttl_seconds: u32, // The time in seconds that this service will take to update, after the record is updated.
ttl_seconds: u32, // The time in seconds that this service will take to update, after the record is updated.
}
/*
An IP4 address that the domain name maps to. There can be any number of these.
*/
// An IP4 address that the domain name maps to. There can be any number of these.
DNS_Record_IP4 :: struct {
using base: DNS_Record_Base,
address: IP4_Address,
}
/*
An IPv6 address that the domain name maps to. There can be any number of these.
*/
// An IPv6 address that the domain name maps to. There can be any number of these.
DNS_Record_IP6 :: struct {
using base: DNS_Record_Base,
address: IP6_Address,
@@ -356,15 +330,17 @@ DNS_Record_MX :: struct {
preference: 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.
/*
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_SRV :: struct {
// base contains the full name of this record.
// e.g: _sip._tls.example.com

View File

@@ -54,13 +54,9 @@ destroy_dns_configuration :: proc() {
dns_configuration := DEFAULT_DNS_CONFIGURATION
/*
Always allocates for consistency.
*/
// Always allocates for consistency.
replace_environment_path :: proc(path: string, allocator := context.allocator) -> (res: string, ok: bool) {
/*
Nothing to replace. Return a clone of the original.
*/
// Nothing to replace. Return a clone of the original.
if strings.count(path, "%") != 2 {
return strings.clone(path), true
}
@@ -76,7 +72,6 @@ replace_environment_path :: proc(path: string, allocator := context.allocator) -
defer delete(env_val)
res, _ = strings.replace(path, path[left - 1: right + 1], env_val, 1)
return res, true
}
@@ -171,9 +166,7 @@ resolve_ip6 :: proc(hostname_and_maybe_port: string) -> (ep6: Endpoint, err: Net
unreachable()
}
/*
`get_dns_records` uses OS-specific methods to query DNS records.
*/
// `get_dns_records` uses OS-specific methods to query DNS records.
when ODIN_OS == .Windows {
get_dns_records_from_os :: get_dns_records_windows
} else when ODIN_OS == .Linux || ODIN_OS == .Darwin || ODIN_OS == .OpenBSD {
@@ -434,9 +427,7 @@ load_hosts :: proc(hosts_file_path: string, allocator := context.allocator) -> (
return _hosts[:], true
}
/*
www.google.com -> 3www6google3com0
*/
// www.google.com -> 3www6google3com0
encode_hostname :: proc(b: ^strings.Builder, hostname: string, allocator := context.allocator) -> (ok: bool) {
_hostname := hostname
for section in strings.split_iterator(&_hostname, ".") {
@@ -861,4 +852,4 @@ parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator
}
return _records[:], true
}
}

View File

@@ -80,4 +80,4 @@ get_dns_records_unix :: proc(hostname: string, type: DNS_Record_Type, allocator
}
return get_dns_records_from_nameservers(hostname, type, name_servers, host_overrides[:])
}
}

View File

@@ -22,14 +22,16 @@ import "core:mem"
import win "core:sys/windows"
// 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.
//
// WARNING: This procedure allocates memory for each record returned; deleting just the returned slice is not enough!
// See `destroy_records`.
/*
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.
WARNING: This procedure allocates memory for each record returned; deleting just the returned slice is not enough!
See `destroy_records`.
*/
get_dns_records_windows :: proc(hostname: string, type: DNS_Record_Type, allocator := context.allocator) -> (records: []DNS_Record, err: DNS_Error) {
context.allocator = allocator
@@ -55,7 +57,6 @@ get_dns_records_windows :: proc(hostname: string, type: DNS_Record_Type, allocat
count += 1
}
recs := make([dynamic]DNS_Record, 0, count)
if recs == nil do return nil, .System_Error // return no results if OOM.
@@ -163,4 +164,4 @@ get_dns_records_windows :: proc(hostname: string, type: DNS_Record_Type, allocat
records = recs[:]
return
}
}

View File

@@ -42,6 +42,5 @@
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.
*/
package net

View File

@@ -16,10 +16,7 @@
*/
package net
//
// TODO(tetra): Bluetooth, Raw
//
any_socket_to_socket :: proc(any_socket: Any_Socket) -> Socket {
switch s in any_socket {
case TCP_Socket: return Socket(s)