addr.odin 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. // +build windows, linux, darwin
  2. package net
  3. /*
  4. Package net implements cross-platform Berkeley Sockets, DNS resolution and associated procedures.
  5. For other protocols and their features, see subdirectories of this package.
  6. */
  7. /*
  8. Copyright 2022 Tetralux <[email protected]>
  9. Copyright 2022 Colin Davidson <[email protected]>
  10. Copyright 2022 Jeroen van Rijn <[email protected]>.
  11. Made available under Odin's BSD-3 license.
  12. List of contributors:
  13. Tetralux: Initial implementation
  14. Colin Davidson: Linux platform code, OSX platform code, Odin-native DNS resolver
  15. Jeroen van Rijn: Cross platform unification, code style, documentation
  16. */
  17. import "core:strconv"
  18. import "core:strings"
  19. import "core:fmt"
  20. /*
  21. Expects an IPv4 address with no leading or trailing whitespace:
  22. - a.b.c.d
  23. - a.b.c.d:port
  24. - [a.b.c.d]:port
  25. If the IP address is bracketed, the port must be present and valid (though it will be ignored):
  26. - [a.b.c.d] will be treated as a parsing failure.
  27. The port, if present, is required to be a base 10 number in the range 0-65535, inclusive.
  28. If `allow_non_decimal` is false, `aton` is told each component must be decimal and max 255.
  29. */
  30. parse_ip4_address :: proc(address_and_maybe_port: string, allow_non_decimal := false) -> (addr: IP4_Address, ok: bool) {
  31. res := aton(address_and_maybe_port, .IP4, !allow_non_decimal) or_return
  32. return res.?
  33. }
  34. /*
  35. Parses an IP address in "non-decimal" `inet_aton` form.
  36. e.g."00377.0x0ff.65534" = 255.255.255.254
  37. 00377 = 255 in octal
  38. 0x0ff = 255 in hexadecimal
  39. This leaves 16 bits worth of address
  40. .65534 then accounts for the last two digits
  41. For the address part the allowed forms are:
  42. a.b.c.d - where each part represents a byte
  43. a.b.c - where `a` & `b` represent a byte and `c` a u16
  44. a.b - where `a` represents a byte and `b` supplies the trailing 24 bits
  45. a - where `a` gives the entire 32-bit value
  46. The port, if present, is required to be a base 10 number in the range 0-65535, inclusive.
  47. */
  48. aton :: proc(address_and_maybe_port: string, family: Address_Family, allow_decimal_only := false) -> (addr: Address, ok: bool) {
  49. switch family {
  50. case .IP4:
  51. // There is no valid address shorter than `0.0.0.0`.
  52. if len(address_and_maybe_port) < 7 {
  53. return {}, false
  54. }
  55. address, _ := split_port(address_and_maybe_port) or_return // This call doesn't allocate
  56. buf: [4]u64 = {}
  57. i := 0
  58. max_value := u64(max(u32))
  59. bases := DEFAULT_DIGIT_BASES
  60. if allow_decimal_only {
  61. max_value = 255
  62. bases = {.Dec}
  63. }
  64. for len(address) > 0 {
  65. if i == 4 {
  66. return {}, false
  67. }
  68. // Decimal-only addresses may not have a leading zero.
  69. if allow_decimal_only && len(address) > 1 && address[0] == '0' && address[1] != '.' {
  70. return
  71. }
  72. number, consumed, number_ok := parse_ip_component(address, max_value, bases)
  73. if !number_ok || consumed == 0 {
  74. return {}, false
  75. }
  76. buf[i] = number
  77. address = address[consumed:]
  78. if len(address) > 0 && address[0] == '.' {
  79. address = address[1:]
  80. }
  81. i += 1
  82. }
  83. // Distribute parts.
  84. switch i {
  85. case 1:
  86. buf[1] = buf[0] & 0xffffff
  87. buf[0] >>= 24
  88. fallthrough
  89. case 2:
  90. buf[2] = buf[1] & 0xffff
  91. buf[1] >>= 16
  92. fallthrough
  93. case 3:
  94. buf[3] = buf[2] & 0xff
  95. buf[2] >>= 8
  96. }
  97. a: [4]u8 = ---
  98. for v, j in buf {
  99. if v > 255 { return {}, false }
  100. a[j] = u8(v)
  101. }
  102. return IP4_Address(a), true
  103. case .IP6:
  104. return parse_ip6_address(address_and_maybe_port)
  105. case:
  106. return nil, false
  107. }
  108. }
  109. /*
  110. The minimum length of a valid IPv6 address string is 2, e.g. `::`
  111. The maximum length of a valid IPv6 address string is 45, when it embeds an IPv4,
  112. e.g. `0000:0000:0000:0000:0000:ffff:255.255.255.255`
  113. An IPv6 address must contain at least 3 pieces, e.g. `::`,
  114. and at most 9 (using `::` for a trailing or leading 0)
  115. */
  116. IPv6_MIN_STRING_LENGTH :: 2
  117. IPv6_MAX_STRING_LENGTH :: 45
  118. IPv6_MIN_COLONS :: 2
  119. IPv6_PIECE_COUNT :: 8
  120. parse_ip6_address :: proc(address_and_maybe_port: string) -> (addr: IP6_Address, ok: bool) {
  121. // If we have an IPv6 address of the form [IP]:Port, first get us just the IP.
  122. address, _ := split_port(address_and_maybe_port) or_return
  123. // Early bailouts based on length and number of pieces.
  124. if len(address) < IPv6_MIN_STRING_LENGTH || len(address) > IPv6_MAX_STRING_LENGTH { return }
  125. /*
  126. Do a pre-pass on the string that checks how many `:` and `.` we have,
  127. if they're in the right order, and if the things between them are digits as expected.
  128. It's not strictly necessary considering we could use `strings.split`,
  129. but this way we can avoid using an allocator and return earlier on bogus input. Win-win.
  130. */
  131. colon_count := 0
  132. dot_count := 0
  133. pieces_temp: [IPv6_PIECE_COUNT + 1]string
  134. piece_start := 0
  135. piece_end := 0
  136. for ch, i in address {
  137. switch ch {
  138. case '0'..='9', 'a'..='f', 'A'..='F':
  139. piece_end += 1
  140. case ':':
  141. // If we see a `:` after a `.`, it means an IPv4 part was sandwiched between IPv6, instead of it being the tail: invalid.
  142. if dot_count > 0 { return }
  143. pieces_temp[colon_count] = address[piece_start:piece_end]
  144. colon_count += 1
  145. if colon_count > IPv6_PIECE_COUNT { return }
  146. // If there's anything left, put it in the next piece.
  147. piece_start = i + 1
  148. piece_end = piece_start
  149. case '.':
  150. // IPv4 address is treated as one piece. No need to update `piece_*`.
  151. dot_count += 1
  152. case: // Invalid character, return early
  153. return
  154. }
  155. }
  156. if colon_count < IPv6_MIN_COLONS { return }
  157. // Assign the last piece string.
  158. pieces_temp[colon_count] = address[piece_start:]
  159. // `pieces` now holds the same output as it would if had used `strings.split`.
  160. pieces := pieces_temp[:colon_count + 1]
  161. // Check if we have what looks like an embedded IPv4 address.
  162. ipv4: IP4_Address
  163. have_ipv4: bool
  164. if dot_count > 0 {
  165. /*
  166. If we have an IPv4 address accounting for the last 32 bits,
  167. this means we can have at most 6 IPv6 pieces, like so: `x:x:X:x:x:x:d.d.d.d`
  168. Or, put differently: 6 pieces IPv6 (5 colons), a colon, 1 piece IPv4 (3 dots),
  169. for a total of 6 colons and 3 dots.
  170. */
  171. if dot_count != 3 || colon_count > 6 { return }
  172. /*
  173. Try to parse IPv4 address.
  174. If successful, we have our least significant 32 bits.
  175. If not, it invalidates the whole address and we can bail.
  176. */
  177. ipv4, have_ipv4 = parse_ip4_address(pieces_temp[colon_count])
  178. if !have_ipv4 { return }
  179. }
  180. // Check for `::` being used more than once, and save the skip.
  181. zero_skip := -1
  182. for i in 1..<colon_count {
  183. if pieces[i] == "" {
  184. // Return if skip has already been set.
  185. if zero_skip != -1 { return }
  186. zero_skip = i
  187. }
  188. }
  189. /*
  190. Now check if we have the necessary number pieces, accounting for any `::`,
  191. and how many were skipped by it if applicable.
  192. */
  193. before_skip := 0
  194. after_skip := 0
  195. num_skipped := 0
  196. if zero_skip != -1 {
  197. before_skip = zero_skip
  198. after_skip = colon_count - zero_skip
  199. // An IPv4 "piece" accounts for 2 IPv6 pieces we haven't added to the pieces slice, so add 1.
  200. if have_ipv4 {
  201. after_skip += 1
  202. }
  203. // Adjust for leading `::`.
  204. if pieces[0] == "" {
  205. before_skip -= 1
  206. // Leading `:` can only be part of `::`.
  207. if before_skip > 0 { return }
  208. }
  209. // Adjust for trailing `::`.
  210. if pieces[colon_count] == "" {
  211. after_skip -= 1
  212. // Trailing `:` can only be part of `::`.
  213. if after_skip > 0 { return }
  214. }
  215. /*
  216. Calculate how many zero pieces we skipped.
  217. It should be at least one, considering we encountered a `::`.
  218. */
  219. num_skipped = IPv6_PIECE_COUNT - before_skip - after_skip
  220. if num_skipped < 1 { return }
  221. } else {
  222. /*
  223. No zero skip means everything is part of "before the skip".
  224. An IPv4 "piece" accounts for 2 IPv6 pieces we haven't added to the pieces slice, so add 1.
  225. */
  226. piece_count := colon_count + 1
  227. if have_ipv4 {
  228. piece_count += 1
  229. }
  230. // Do we have the complete set?
  231. if piece_count != IPv6_PIECE_COUNT { return }
  232. // Validate leading and trailing empty parts, as they can only be part of a `::`.
  233. if pieces[0] == "" || pieces[colon_count] == "" { return }
  234. before_skip = piece_count
  235. after_skip = 0
  236. num_skipped = 0
  237. }
  238. // Now try to parse the pieces into a 8 16-bit pieces.
  239. piece_values: [IPv6_PIECE_COUNT]u16be
  240. idx := 0
  241. val_idx := 0
  242. for _ in 0..<before_skip {
  243. /*
  244. An empty piece is the default zero. Otherwise, try to parse as an IPv6 hex piece.
  245. If we have an IPv4 address, stop on the penultimate index.
  246. */
  247. if have_ipv4 && val_idx == 6 {
  248. break
  249. }
  250. piece := pieces[idx]
  251. // An IPv6 piece can at most contain 4 hex digits.
  252. if len(piece) > 4 { return }
  253. if piece != "" {
  254. val, _ := parse_ip_component(piece, 65535, {.IPv6}) or_return
  255. piece_values[val_idx] = u16be(val)
  256. }
  257. idx += 1
  258. val_idx += 1
  259. }
  260. if before_skip == 0 {
  261. idx += 1
  262. }
  263. if num_skipped > 0 {
  264. idx += 1
  265. val_idx += num_skipped
  266. }
  267. if after_skip > 0 {
  268. for _ in 0..<after_skip {
  269. /*
  270. An empty piece is the default zero. Otherwise, try to parse as an IPv6 hex piece.
  271. If we have an IPv4 address, stop on the penultimate index.
  272. */
  273. if have_ipv4 && val_idx == 6 {
  274. break
  275. }
  276. piece := pieces[idx]
  277. // An IPv6 piece can contain at most 4 hex digits.
  278. if len(piece) > 4 { return }
  279. if piece != "" {
  280. val, _ := parse_ip_component(piece, 65535, {.IPv6}) or_return
  281. piece_values[val_idx] = u16be(val)
  282. }
  283. idx += 1
  284. val_idx += 1
  285. }
  286. }
  287. // Distribute IPv4 address into last two pieces, if applicable.
  288. if have_ipv4 {
  289. val := u16(ipv4[0]) << 8
  290. val |= u16(ipv4[1])
  291. piece_values[6] = u16be(val)
  292. val = u16(ipv4[2]) << 8
  293. val |= u16(ipv4[3])
  294. piece_values[7] = u16be(val)
  295. }
  296. return transmute(IP6_Address)piece_values, true
  297. }
  298. /*
  299. Try parsing as an IPv6 address.
  300. If it's determined not to be, try as an IPv4 address, optionally in non-decimal format.
  301. */
  302. parse_address :: proc(address_and_maybe_port: string, non_decimal_address := false) -> Address {
  303. if addr6, ok6 := parse_ip6_address(address_and_maybe_port); ok6 {
  304. return addr6
  305. }
  306. if addr4, ok4 := parse_ip4_address(address_and_maybe_port, non_decimal_address); ok4 {
  307. return addr4
  308. }
  309. return nil
  310. }
  311. parse_endpoint :: proc(endpoint_str: string) -> (ep: Endpoint, ok: bool) {
  312. if addr_str, port, split_ok := split_port(endpoint_str); split_ok {
  313. if addr := parse_address(addr_str); addr != nil {
  314. return Endpoint { address = addr, port = port }, true
  315. }
  316. }
  317. return
  318. }
  319. Host :: struct {
  320. hostname: string,
  321. port: int,
  322. }
  323. Host_Or_Endpoint :: union {
  324. Host,
  325. Endpoint,
  326. }
  327. // Takes a string consisting of a hostname or IP address, and an optional port,
  328. // and return the component parts in a useful form.
  329. parse_hostname_or_endpoint :: proc(endpoint_str: string) -> (target: Host_Or_Endpoint, err: Parse_Endpoint_Error) {
  330. host, port, port_ok := split_port(endpoint_str)
  331. if !port_ok {
  332. return nil, .Bad_Port
  333. }
  334. if addr := parse_address(host); addr != nil {
  335. return Endpoint{addr, port}, .None
  336. }
  337. if !validate_hostname(host) {
  338. return nil, .Bad_Hostname
  339. }
  340. return Host{host, port}, .None
  341. }
  342. // Takes an endpoint string and returns its parts.
  343. // Returns ok=false if port is not a number.
  344. split_port :: proc(endpoint_str: string) -> (addr_or_host: string, port: int, ok: bool) {
  345. // IP6 [addr_or_host]:port
  346. if i := strings.last_index(endpoint_str, "]:"); i >= 0 {
  347. addr_or_host = endpoint_str[1:i]
  348. port, ok = strconv.parse_int(endpoint_str[i+2:], 10)
  349. if port > 65535 {
  350. ok = false
  351. }
  352. return
  353. }
  354. if n := strings.count(endpoint_str, ":"); n == 1 {
  355. // IP4 addr_or_host:port
  356. i := strings.last_index(endpoint_str, ":")
  357. assert(i != -1)
  358. addr_or_host = endpoint_str[:i]
  359. port, ok = strconv.parse_int(endpoint_str[i+1:], 10)
  360. if port > 65535 {
  361. ok = false
  362. }
  363. return
  364. } else if n > 1 {
  365. // IP6 address without port
  366. }
  367. // No port
  368. addr_or_host = endpoint_str
  369. port = 0
  370. ok = true
  371. return
  372. }
  373. // Joins an address or hostname with a port.
  374. join_port :: proc(address_or_host: string, port: int, allocator := context.allocator) -> string {
  375. addr_or_host, _, ok := split_port(address_or_host)
  376. if !ok {
  377. return addr_or_host
  378. }
  379. b := strings.builder_make(allocator)
  380. addr := parse_address(addr_or_host)
  381. if addr == nil {
  382. // hostname
  383. fmt.sbprintf(&b, "%v:%v", addr_or_host, port)
  384. } else {
  385. switch _ in addr {
  386. case IP4_Address:
  387. fmt.sbprintf(&b, "%v:%v", address_to_string(addr), port)
  388. case IP6_Address:
  389. fmt.sbprintf(&b, "[%v]:%v", address_to_string(addr), port)
  390. }
  391. }
  392. return strings.to_string(b)
  393. }
  394. // TODO(tetra): Do we need this?
  395. map_to_ip6 :: proc(addr: Address) -> Address {
  396. if addr6, ok := addr.(IP6_Address); ok {
  397. return addr6
  398. }
  399. addr4 := addr.(IP4_Address)
  400. addr4_u16 := transmute([2]u16be) addr4
  401. addr6: IP6_Address
  402. addr6[4] = 0xffff
  403. copy(addr6[5:], addr4_u16[:])
  404. return addr6
  405. }
  406. /*
  407. Returns a temporarily-allocated string representation of the address.
  408. See RFC 5952 section 4 for IPv6 representation recommendations.
  409. */
  410. address_to_string :: proc(addr: Address, allocator := context.temp_allocator) -> string {
  411. b := strings.builder_make(allocator)
  412. switch v in addr {
  413. case IP4_Address:
  414. fmt.sbprintf(&b, "%v.%v.%v.%v", v[0], v[1], v[2], v[3])
  415. case IP6_Address:
  416. // First find the longest run of zeroes.
  417. Zero_Run :: struct {
  418. start: int,
  419. end: int,
  420. }
  421. /*
  422. We're dealing with 0-based indices, appropriately enough for runs of zeroes.
  423. Still, it means we need to initialize runs with some value outside of the possible range.
  424. */
  425. run := Zero_Run{-1, -1}
  426. best := Zero_Run{-1, -1}
  427. addr := transmute([8]u16be)v
  428. last := u16be(1)
  429. for val, i in addr {
  430. /*
  431. If we encounter adjacent zeroes, then start a new run if not already in one.
  432. Also remember the rightmost index regardless, because it'll be the new
  433. frontier of both new and existing runs.
  434. */
  435. if last == 0 && val == 0 {
  436. run.end = i
  437. if run.start == -1 {
  438. run.start = i - 1
  439. }
  440. }
  441. /*
  442. If we're in a run check if its length is better than the best recorded so far.
  443. If so, update the best run's start and end.
  444. */
  445. if run.start != -1 {
  446. length_to_beat := best.end - best.start
  447. length := run.end - run.start
  448. if length > length_to_beat {
  449. best = run
  450. }
  451. }
  452. // If we were in a run, this is where we reset it.
  453. if val != 0 {
  454. run = {-1, -1}
  455. }
  456. last = val
  457. }
  458. for val, i in addr {
  459. if best.start == i || best.end == i {
  460. // For the left and right side of the best zero run, print a `:`.
  461. fmt.sbprint(&b, ":")
  462. } else if i < best.start {
  463. /*
  464. If we haven't made it to the best run yet, print the digit.
  465. Make sure we only print a `:` after the digit if it's not
  466. immediately followed by the run's own leftmost `:`.
  467. */
  468. fmt.sbprintf(&b, "%x", val)
  469. if i < best.start - 1 {
  470. fmt.sbprintf(&b, ":")
  471. }
  472. } else if i > best.end {
  473. /*
  474. If there are any digits after the zero run, print them.
  475. But don't print the `:` at the end of the IP number.
  476. */
  477. fmt.sbprintf(&b, "%x", val)
  478. if i != 7 {
  479. fmt.sbprintf(&b, ":")
  480. }
  481. }
  482. }
  483. }
  484. return strings.to_string(b)
  485. }
  486. // Returns a temporarily-allocated string representation of the endpoint.
  487. // If there's a port, uses the `ip4address:port` or `[ip6address]:port` format, respectively.
  488. endpoint_to_string :: proc(ep: Endpoint, allocator := context.temp_allocator) -> string {
  489. if ep.port == 0 {
  490. return address_to_string(ep.address, allocator)
  491. } else {
  492. s := address_to_string(ep.address, context.temp_allocator)
  493. b := strings.builder_make(allocator)
  494. switch a in ep.address {
  495. case IP4_Address: fmt.sbprintf(&b, "%v:%v", s, ep.port)
  496. case IP6_Address: fmt.sbprintf(&b, "[%v]:%v", s, ep.port)
  497. }
  498. return strings.to_string(b)
  499. }
  500. }
  501. to_string :: proc{address_to_string, endpoint_to_string}
  502. family_from_address :: proc(addr: Address) -> Address_Family {
  503. switch _ in addr {
  504. case IP4_Address: return .IP4
  505. case IP6_Address: return .IP6
  506. case:
  507. unreachable()
  508. }
  509. }
  510. family_from_endpoint :: proc(ep: Endpoint) -> Address_Family {
  511. return family_from_address(ep.address)
  512. }
  513. Digit_Parse_Base :: enum u8 {
  514. Dec = 0, // No prefix
  515. Oct = 1, // Leading zero
  516. Hex = 2, // 0x prefix
  517. IPv6 = 3, // Unprefixed IPv6 piece hex. Can't be used with other bases.
  518. }
  519. Digit_Parse_Bases :: bit_set[Digit_Parse_Base; u8]
  520. DEFAULT_DIGIT_BASES :: Digit_Parse_Bases{.Dec, .Oct, .Hex}
  521. /*
  522. Parses a single unsigned number in requested `bases` from `input`.
  523. `max_value` represents the maximum allowed value for this number.
  524. Returns the `value`, the `bytes_consumed` so far, and `ok` to signal success or failure.
  525. An out-of-range or invalid number will return the accumulated value so far (which can be out of range),
  526. the number of bytes consumed leading up the error, and `ok = false`.
  527. When `.` or `:` are encountered, they'll be considered valid separators and will stop parsing,
  528. returning the valid number leading up to it.
  529. Other non-digit characters are treated as an error.
  530. Octal numbers are expected to have a leading zero, with no 'o' format specifier.
  531. Hexadecimal numbers are expected to be preceded by '0x' or '0X'.
  532. Numbers will otherwise be considered to be in base 10.
  533. */
  534. parse_ip_component :: proc(input: string, max_value := u64(max(u32)), bases := DEFAULT_DIGIT_BASES) -> (value: u64, bytes_consumed: int, ok: bool) {
  535. // Default to base 10
  536. base := u64(10)
  537. input := input
  538. /*
  539. We keep track of the number of prefix bytes and digit bytes separately.
  540. This way if a prefix is consumed and we encounter a separator or the end of the string,
  541. the number is only considered valid if at least 1 digit byte has been consumed and the value is within range.
  542. */
  543. prefix_bytes := 0
  544. digit_bytes := 0
  545. /*
  546. IPv6 hex bytes are unprefixed and can't be disambiguated from octal or hex unless the digit is out of range.
  547. If we got the `.IPv6` option, skip prefix scanning and other flags aren't also used.
  548. */
  549. if .IPv6 in bases {
  550. if bases != {.IPv6} { return } // Must be used on its own.
  551. base = 16
  552. } else {
  553. // Scan for and consume prefix, if applicable.
  554. if len(input) >= 2 && input[0] == '0' {
  555. if .Hex in bases && (input[1] == 'x' || input[1] == 'X') {
  556. base = 16
  557. input = input[2:]
  558. prefix_bytes = 2
  559. }
  560. if prefix_bytes == 0 && .Oct in bases {
  561. base = 8
  562. input = input[1:]
  563. prefix_bytes = 1
  564. }
  565. }
  566. }
  567. parse_loop: for ch in input {
  568. switch ch {
  569. case '0'..='7':
  570. digit_bytes += 1
  571. value = value * base + u64(ch - '0')
  572. case '8'..='9':
  573. digit_bytes += 1
  574. if base == 8 {
  575. // Out of range for octal numbers.
  576. return value, digit_bytes + prefix_bytes, false
  577. }
  578. value = value * base + u64(ch - '0')
  579. case 'a'..='f':
  580. digit_bytes += 1
  581. if base == 8 || base == 10 {
  582. // Out of range for octal and decimal numbers.
  583. return value, digit_bytes + prefix_bytes, false
  584. }
  585. value = value * base + (u64(ch - 'a') + 10)
  586. case 'A'..='F':
  587. digit_bytes += 1
  588. if base == 8 || base == 10 {
  589. // Out of range for octal and decimal numbers.
  590. return value, digit_bytes + prefix_bytes, false
  591. }
  592. value = value * base + (u64(ch - 'A') + 10)
  593. case '.', ':':
  594. /*
  595. Number separator. Return early.
  596. We don't need to check if the number is in range.
  597. We do that each time through the loop.
  598. */
  599. break parse_loop
  600. case:
  601. // Invalid character encountered.
  602. return value, digit_bytes + prefix_bytes, false
  603. }
  604. if value > max_value {
  605. // Out-of-range number.
  606. return value, digit_bytes + prefix_bytes, false
  607. }
  608. }
  609. // If we consumed at least 1 digit byte, `value` *should* continue a valid number in an appropriate base in the allowable range.
  610. return value, digit_bytes + prefix_bytes, digit_bytes >= 1
  611. }
  612. // Returns an address for each interface that can be bound to.
  613. get_network_interfaces :: proc() -> []Address {
  614. // TODO: Implement using `enumerate_interfaces` and returning only the addresses of active interfaces.
  615. return nil
  616. }