hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 3cffe29adb1fab6e4887a095fd2b48a086bb4d16
parent d11b0f794ec768acf0468440dba1f74f3311c486
Author: Mykyta Holubakha <hilobakho@gmail.com>
Date:   Sun, 28 Mar 2021 19:42:56 +0300

net::ip: add conversion to rt::sockaddr

Diffstat:
Anet/ip/+linux.ha | 17+++++++++++++++++
Mnet/ip/+test.ha | 2+-
Mnet/ip/ip.ha | 63+++++++++++++++++++++++++++------------------------------------
Mscripts/gen-stdlib | 1+
Mstdlib.mk | 4+++-
5 files changed, 49 insertions(+), 38 deletions(-)

diff --git a/net/ip/+linux.ha b/net/ip/+linux.ha @@ -0,0 +1,17 @@ +use rt; +use endian; + +export fn to_native(a: addr, port: u16) rt::sockaddr = { + return match (a) { + v4: addr4 => rt::sockaddr { in = rt::sockaddr_in { + sin_family = rt::AF_INET, + sin_port = endian::htonu16(port), + sin_addr = rt::in_addr { s_addr = *(&v4[0]: *void: *u32) }, + } }, + v6: addr6 => rt::sockaddr { in6 = rt::sockaddr_in6 { + sin6_family = rt::AF_INET6, + sin6_port = endian::htonu16(port), + sin6_addr = rt::in6_addr { s6_addr = v6 }, + } }, + }; +}; diff --git a/net/ip/+test.ha b/net/ip/+test.ha @@ -61,7 +61,7 @@ fn subnet_test_simple(s: str) void = { a: subnet => a, * => return, }; - let fmted = stringsubnet(net); + let fmted = string(net); assert(fmted == s); let netrp = parsecidr(fmted); assert(netrp is subnet); diff --git a/net/ip/ip.ha b/net/ip/ip.ha @@ -44,7 +44,7 @@ export fn equal(l: addr, r: addr) bool = { }; }; -export fn parsev4(st: str) (addr4 | invalid) = { +fn parsev4(st: str) (addr4 | invalid) = { let ret: addr4 = [0...]; let tok = strings::tokenize(st, "."); let i = 0z; @@ -108,8 +108,9 @@ fn parsev6(st: str) (addr6 | invalid) = { return invalid; }; if (ells >= 0) { - if (i >= 15) + if (i >= 15) { return invalid; + }; rt::memcpy( &ret[16 - (i - ells)], &ret[ells], (i - ells): size); @@ -134,7 +135,7 @@ export fn parse(s: str) (addr | invalid) = { return invalid; }; -fn fmtv4(a: addr4, s: *io::stream) (io::error | size) = { +fn fmtv4(s: *io::stream, a: addr4) (io::error | size) = { let ret = 0z; for (let i = 0; i < 4; i += 1) { if (i > 0) { @@ -145,7 +146,7 @@ fn fmtv4(a: addr4, s: *io::stream) (io::error | size) = { return ret; }; -fn fmtv6(a: addr6, s: *io::stream) (io::error | size) = { +fn fmtv6(s: *io::stream, a: addr6) (io::error | size) = { let ret = 0z; let zstart: int = -1; let zend: int = -1; @@ -182,25 +183,6 @@ fn fmtv6(a: addr6, s: *io::stream) (io::error | size) = { return ret; }; -// Formats an IP address -export fn fmt(addr: addr, s: *io::stream) (io::error | size) = { - return match (addr) { - v4: addr4 => fmtv4(v4, s)?, - v6: addr6 => fmtv6(v6, s)?, - }; -}; - -// Formats an [addr] as a string. The return value is statically -// allocated and will be overwritten on subsequent calls; see -// [strings::dup] to extend its lifetime. -export fn string(addr: addr) str = { - // Maximum length of an IPv6 address is 45 chars - static let buf: [46]u8 = [0...]; - let stream = strio::fixed(buf); - fmt(addr, stream) as size; - return strio::string(stream); -}; - // Fills a netmask according to the CIDR value // e.g. 23 -> [0xFF, 0xFF, 0xFD, 0x00] fn fillmask(mask: []u8, val: u8) void = { @@ -281,7 +263,7 @@ fn masklen(addr: []u8) (void | size) = { return n; }; -fn fmtmask(mask: addr, s: *io::stream) (io::error | size) = { +fn fmtmask(s: *io::stream, mask: addr) (io::error | size) = { let ret = 0z; let slice = match (mask) { v4: addr4 => v4[..], @@ -301,23 +283,32 @@ fn fmtmask(mask: addr, s: *io::stream) (io::error | size) = { return ret; }; -// Format an IP subnet -export fn fmtsubnet(subnet: subnet, s: *io::stream) (io::error | size) = { +fn fmtsubnet(s: *io::stream, subnet: subnet) (io::error | size) = { let ret = 0z; - ret += fmt(subnet.addr, s)?; + ret += fmt(s, subnet.addr)?; ret += fmt::fprintf(s, "/")?; - ret += fmtmask(subnet.mask, s)?; + ret += fmtmask(s, subnet.mask)?; return ret; }; -// Formats a [subnet] as a string. The return value is statically -// allocated and will be overwritten on subsequent calls; see -// [strings::dup] to extend its lifetime. -export fn stringsubnet(subnet: subnet) str = { - static let buf: [66]u8 = [0...]; - let stream = strio::fixed(buf); - fmtsubnet(subnet, stream) as size; - return strio::string(stream); +// Formats an [addr] or [subnet] and prints it to a stream. +export fn fmt(s: *io::stream, item: (...addr | subnet)) (io::error | size) = { + return match (item) { + v4: addr4 => fmtv4(s, v4)?, + v6: addr6 => fmtv6(s, v6)?, + sub: subnet => fmtsubnet(s, sub), + }; +}; + +// Formats an [addr] or [subnet] as a string. The return value is statically +// allocated and will be overwritten on subsequent calls; see [strings::dup] to +// extend its lifetime. +export fn string(item: (...addr | subnet)) str = { + // Maximum length of an IPv6 address is 45 chars + static let buf: [46]u8 = [0...]; + let stream = strio::fixed(buf); + fmt(stream, item) as size; + return strio::string(stream); }; fn wanttoken(tok: *strings::tokenizer) (str | invalid) = { diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -397,6 +397,7 @@ linux_vdso() { gensrcs_net_ip() { gen_srcs net::ip \ ip.ha \ + '$(PLATFORM).ha' \ $* } diff --git a/stdlib.mk b/stdlib.mk @@ -504,7 +504,8 @@ $(HARECACHE)/linux/vdso/linux_vdso.ssa: $(stdlib_linux_vdso_srcs) $(stdlib_rt) $ # net::ip stdlib_net_ip_srcs= \ - $(STDLIB)/net/ip/ip.ha + $(STDLIB)/net/ip/ip.ha \ + $(STDLIB)/net/ip/$(PLATFORM).ha $(HARECACHE)/net/ip/net_ip.ssa: $(stdlib_net_ip_srcs) $(stdlib_rt) $(stdlib_bytes) $(stdlib_io) $(stdlib_strconv) $(stdlib_strings) $(stdlib_strio) @printf 'HAREC \t$@\n' @@ -1216,6 +1217,7 @@ $(TESTCACHE)/linux/vdso/linux_vdso.ssa: $(testlib_linux_vdso_srcs) $(testlib_rt) # net::ip testlib_net_ip_srcs= \ $(STDLIB)/net/ip/ip.ha \ + $(STDLIB)/net/ip/$(PLATFORM).ha \ $(STDLIB)/net/ip/+test.ha $(TESTCACHE)/net/ip/net_ip.ssa: $(testlib_net_ip_srcs) $(testlib_rt) $(testlib_bytes) $(testlib_io) $(testlib_strconv) $(testlib_strings) $(testlib_strio)