| 1 | module net |
| 2 | |
| 3 | // validate_port checks whether a port is valid and returns the port or an error. |
| 4 | // The valid ports numbers are between 0 and 0xFFFF. |
| 5 | // For TCP, port number 0 is reserved and cannot be used, while for UDP, the source port |
| 6 | // is optional and a value of zero means no port. |
| 7 | // See also https://en.wikipedia.org/wiki/Port_%28computer_networking%29 . |
| 8 | pub fn validate_port(port int) !u16 { |
| 9 | if port >= 0 && port <= 0xFFFF { |
| 10 | return u16(port) |
| 11 | } else { |
| 12 | return err_port_out_of_range |
| 13 | } |
| 14 | } |
| 15 | |
| 16 | // split_address splits an address into its host name and its port |
| 17 | pub fn split_address(addr string) !(string, u16) { |
| 18 | if _ := addr.index(']') { |
| 19 | // ipv6 brackets |
| 20 | address := addr.all_after('[').all_before_last(']') |
| 21 | port := addr.all_after_last(']:').int() |
| 22 | p := validate_port(port)! |
| 23 | return address, p |
| 24 | } else if _ := addr.index('::') { |
| 25 | if addr.count(':') == 2 && addr.all_before_last('::') == '' { |
| 26 | // ipv6 host only `::1` |
| 27 | return addr, 0 |
| 28 | } else { |
| 29 | // addr:port, or `::addr:port` |
| 30 | address := addr.all_before_last(':') |
| 31 | port := addr.all_after_last(':').int() |
| 32 | p := validate_port(port)! |
| 33 | return address, p |
| 34 | } |
| 35 | } else if _ := addr.index(':') { |
| 36 | // addr:port |
| 37 | address := addr.all_before_last(':') |
| 38 | p := validate_port(addr.all_after_last(':').int())! |
| 39 | return address, p |
| 40 | } else { |
| 41 | // addr only |
| 42 | return addr, 0 |
| 43 | } |
| 44 | } |
| 45 | |