hare

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

commit 0b68a9ec9421a9319e3adc57b1f35858d172156a
parent bc5ba82fe0e58d44cf89ffff81b3bf1b8795bb4a
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 19 Jun 2021 10:37:20 -0400

net: reorganize modules

This moves each protocol's connect/listen functions into their
respective modules, e.g. net::tcp and net::unix. This allows us to add
new protocols without updating net.

Future work will include:

- SOCK_DGRAM abstraction for net
- SOCK_DGRAM providers for net::udp and net::ip
- Out of tree implementations of net::bluetooth et al

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Anet/+linux.ha | 125+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dnet/+linux/socket.ha | 148-------------------------------------------------------------------------------
Dnet/+linux/util.ha | 78------------------------------------------------------------------------------
Anet/listener.ha | 26++++++++++++++++++++++++++
Anet/options.ha | 30++++++++++++++++++++++++++++++
Dnet/socket.ha | 92-------------------------------------------------------------------------------
Anet/tcp/+linux.ha | 50++++++++++++++++++++++++++++++++++++++++++++++++++
Mnet/unix/+linux.ha | 42++++++++++++++++++++++++++++++++++++++++++
Mscripts/gen-stdlib | 18+++++++++++++-----
Mstdlib.mk | 50++++++++++++++++++++++++++++++++++++++++----------
10 files changed, 326 insertions(+), 333 deletions(-)

diff --git a/net/+linux.ha b/net/+linux.ha @@ -0,0 +1,125 @@ +use errors; +use fmt; +use io; +use net::ip; +use os; +use rt; +use strings; + +export fn connect_fd( + addr: rt::sockaddr, + options: connect_option... +) (int | io::error) = { + const sockfd = mksockfd(addr)?; + for (let i = 0z; i < len(options); i += 1) { + // The only option is keepalive right now + setsockopt(sockfd, rt::SO_KEEPALIVE, true)?; + }; + wrap(rt::connect(sockfd, &addr, sockasz(addr)))?; + return sockfd; +}; + +export type stream_listener = struct { + l: listener, + fd: int, +}; + +// Gets the fd of the listener's socket. This function is not portable. +export fn listenerfd(l: *listener) (int | void) = { + if (l.accept == &stream_accept) { + return (l: *stream_listener).fd; + }; +}; + +export fn listen_fd( + addr: rt::sockaddr, + options: listen_option... +) (int | io::error) = { + const sockfd = mksockfd(addr)?; + + let bk: u32 = 10; + let portout: nullable *u16 = null; + + for (let i = 0z; i < len(options); i += 1) { + match (options[i]) { + reuseaddr => setsockopt(sockfd, rt::SO_REUSEADDR, true)?, + reuseport => setsockopt(sockfd, rt::SO_REUSEPORT, true)?, + keepalive => setsockopt(sockfd, rt::SO_KEEPALIVE, true)?, + b: backlog => bk = b, + p: portassignment => portout = p, + }; + }; + setfcntl(sockfd, rt::O_CLOEXEC)!; + + wrap(rt::bind(sockfd, &addr, sockasz(addr)))?; + wrap(rt::listen(sockfd, bk))?; + + match (portout) { + p: *u16 => { + if (addr.in.sin_family != rt::AF_INET && + addr.in.sin_family != rt::AF_INET6) { + return errors::unsupported; + }; + let sn = rt::sockaddr {...}; + let al = sockasz(addr); + wrap(rt::getsockname(sockfd, &sn, &al))?; + const addr = ip::from_native(sn); + *p = addr.1; + }, + null => void, + }; + + return sockfd; +}; + +export fn stream_accept(l: *listener) (*io::stream | io::error) = { + assert(l.accept == &stream_accept); + let l = l: *stream_listener; + let sn = rt::sockaddr {...}; + const sz = size(rt::sockaddr): u32; + const fd = wrap(rt::accept(l.fd, &sn, &sz))?; + + static let namebuf: [32]u8 = [0...]; + return os::fdopen(fd, fmt::bsprintf(namebuf, "<net connection {}>", fd), + io::mode::READ | io::mode::WRITE); +}; + +export fn stream_shutdown(l: *listener) void = { + assert(l.shutdown == &stream_shutdown); + let l = l: *stream_listener; + rt::close(l.fd)!; + free(l); +}; + +fn setsockopt(sockfd: int, option: int, value: bool) (void | rt::errno) = { + let val: int = if (value) 1 else 0; + rt::setsockopt(sockfd, rt::SOL_SOCKET, option, + &val: *void, size(int): u32)?; + return; +}; + +fn setfcntl(sockfd: int, flag: int) (void | rt::errno) = { + let flags = rt::fcntl(sockfd, rt::F_GETFL, 0)?; + rt::fcntl(sockfd, rt::F_SETFL, flags | flag)!; + return; +}; + +fn wrap(ie: (int | rt::errno)) (int | io::error) = { + match (ie) { + i: int => i, + err: rt::errno => errors::errno(err), + }; +}; + +fn sockasz(addr: rt::sockaddr) u32 = { + return switch (addr.in.sin_family) { + rt::AF_INET => size(rt::sockaddr_in): u32, + rt::AF_INET6 => size(rt::sockaddr_in6): u32, + rt::AF_UNIX => size(rt::sockaddr_un): u32, + * => size(rt::sockaddr): u32, + }; +}; + +export fn mksockfd(addr: rt::sockaddr) (int | io::error) = { + return wrap(rt::socket(addr.in.sin_family: int, rt::SOCK_STREAM, 0))?; +}; diff --git a/net/+linux/socket.ha b/net/+linux/socket.ha @@ -1,148 +0,0 @@ -use errors; -use io; -use net::ip; -use net::unix; -use os; -use rt; -use strings; - -fn connect_fd( - addr: rt::sockaddr, - options: connect_option... -) (int | io::error) = { - const sockfd = mksockfd(addr)?; - for (let i = 0z; i < len(options); i += 1) { - // The only option is keepalive right now - setsockopt(sockfd, rt::SO_KEEPALIVE, true)?; - }; - wrap(rt::connect(sockfd, &addr, sockasz(addr)))?; - return sockfd; -}; - -// Opens a TCP connection to the given host and port. Blocks until the -// connection is established. -export fn connect( - addr: ip::addr, - port: u16, - options: connect_option... -) (*io::stream | io::error) = { - const sockaddr = ip::to_native(addr, port); - const sockfd = connect_fd(sockaddr, options...)?; - return os::fdopen(sockfd, string(addr), - io::mode::READ | io::mode::WRITE); -}; - -// Opens a UNIX socket connection to the path. Blocks until the -// connection is established. -export fn connect_unix( - addr: unix::addr, - options: connect_option... -) (*io::stream | io::error) = { - let sockaddr = match (unix::to_native(addr)) { - a: rt::sockaddr => a, - unix::invalid => return errors::unsupported, // path too long - }; - const sockfd = connect_fd(sockaddr, options...)?; - return os::fdopen(sockfd, string(addr), - io::mode::READ | io::mode::WRITE); -}; - -type stream_listener = struct { - l: listener, - fd: int, -}; - -fn listen_fd( - addr: rt::sockaddr, - options: listen_option... -) (int | io::error) = { - const sockfd = mksockfd(addr)?; - - let bk: u32 = 10; - let portout: nullable *u16 = null; - - for (let i = 0z; i < len(options); i += 1) { - match (options[i]) { - reuseaddr => setsockopt(sockfd, rt::SO_REUSEADDR, true)?, - reuseport => setsockopt(sockfd, rt::SO_REUSEPORT, true)?, - keepalive => setsockopt(sockfd, rt::SO_KEEPALIVE, true)?, - b: backlog => bk = b, - p: portassignment => portout = p, - }; - }; - setfcntl(sockfd, rt::O_CLOEXEC)!; - - wrap(rt::bind(sockfd, &addr, sockasz(addr)))?; - wrap(rt::listen(sockfd, bk))?; - - match (portout) { - p: *u16 => { - if (addr.in.sin_family != rt::AF_INET && - addr.in.sin_family != rt::AF_INET6) { - return errors::unsupported; - }; - let sn = rt::sockaddr {...}; - let al = sockasz(addr); - wrap(rt::getsockname(sockfd, &sn, &al))?; - const addr = ip::from_native(sn); - *p = addr.1; - }, - null => void, - }; - - return sockfd; -}; - -// Binds a TCP listener to the given address. -export fn listen( - addr: ip::addr, - port: u16, - options: listen_option... -) (*listener | io::error) = { - let sockaddr = ip::to_native(addr, port); - let sockfd = listen_fd(sockaddr, options...)?; - return alloc(stream_listener { - l = listener { - accept = &stream_accept, - shutdown = &stream_shutdown, - }, - fd = sockfd, - }): *listener; -}; - -fn stream_accept(l: *listener) (*io::stream | io::error) = { - assert(l.accept == &stream_accept); - let l = l: *stream_listener; - let sn = rt::sockaddr {...}; - const sz = size(rt::sockaddr): u32; - const fd = wrap(rt::accept(l.fd, &sn, &sz))?; - const addr = from_native(sn); - return os::fdopen(fd, string(addr), - io::mode::READ | io::mode::WRITE); -}; - -fn stream_shutdown(l: *listener) void = { - assert(l.shutdown == &stream_shutdown); - let l = l: *stream_listener; - rt::close(l.fd)!; - free(l); -}; - -// Binds a UNIX socket listener at the given path. -export fn listen_unix( - addr: unix::addr, - options: listen_option... -) (*listener | io::error) = { - let sockaddr = match (unix::to_native(addr)) { - a: rt::sockaddr => a, - unix::invalid => return errors::unsupported, // path too long - }; - let sockfd = listen_fd(sockaddr, options...)?; - return alloc(stream_listener { - l = listener { - accept = &stream_accept, - shutdown = &stream_shutdown, - }, - fd = sockfd, - }): *listener; -}; diff --git a/net/+linux/util.ha b/net/+linux/util.ha @@ -1,78 +0,0 @@ -use errors; -use io; -use fmt; -use net::ip; -use net::unix; -use os; -use rt; - -fn setsockopt(sockfd: int, option: int, value: bool) (void | rt::errno) = { - let val: int = if (value) 1 else 0; - rt::setsockopt(sockfd, rt::SOL_SOCKET, option, - &val: *void, size(int): u32)?; - return; -}; - -fn setfcntl(sockfd: int, flag: int) (void | rt::errno) = { - let flags = rt::fcntl(sockfd, rt::F_GETFL, 0)?; - rt::fcntl(sockfd, rt::F_SETFL, flags | flag)!; - return; -}; - -fn wrap(ie: (int | rt::errno)) (int | io::error) = { - match (ie) { - i: int => i, - err: rt::errno => errors::errno(err), - }; -}; - -fn mksockfd(addr: rt::sockaddr) (int | io::error) = { - return wrap(rt::socket(addr.in.sin_family: int, rt::SOCK_STREAM, 0))?; -}; - -fn sockasz(addr: rt::sockaddr) u32 = { - return switch (addr.in.sin_family) { - rt::AF_INET => size(rt::sockaddr_in): u32, - rt::AF_INET6 => size(rt::sockaddr_in6): u32, - rt::AF_UNIX => size(rt::sockaddr_un): u32, - * => size(rt::sockaddr): u32, - }; -}; - -fn string(addr: (ip::addr | unix::addr)) str = { - return match (addr) { - ip: ip::addr => ip::string(ip), - un: unix::addr => un, - }; -}; - -fn from_native(addr: rt::sockaddr) (ip::addr | unix::addr) = { - return switch (addr.in.sin_family) { - rt::AF_INET => ip::from_native(addr).0, - rt::AF_INET6 => ip::from_native(addr).0, - rt::AF_UNIX => unix::from_native(addr), - * => abort("Wrong address family"), - }; -}; - -// Returns the remote address for a given connection, or void if none is -// available. -export fn peeraddr(stream: *io::stream) ((ip::addr, u16) | void) = { - let fd = match (os::streamfd(stream, true)) { - fd: int => fd, - void => return, - }; - let sn = rt::sockaddr {...}; - let sz = size(rt::sockaddr): u32; - if (rt::getpeername(fd, &sn, &sz) is rt::errno) { - return; - }; - return ip::from_native(sn); -}; - -// Gets the fd of the listener's socket. -export fn listenerfd(l: *listener) (int | void) = { - if (l.accept == &stream_accept) { - return (l: *stream_listener).fd; - }; -}; diff --git a/net/listener.ha b/net/listener.ha @@ -0,0 +1,26 @@ +use errors; +use io; + +// A listener binds a socket and listens for incoming traffic for some +// unspecified protocol. +export type listener = struct { + accept: nullable *fn(l: *listener) (*io::stream | io::error), + shutdown: nullable *fn(l: *listener) void, +}; + +// Accepts the next connection from a listener. Blocks until a new connection is +// available. +export fn accept(l: *listener) (*io::stream | io::error) = { + return match (l.accept) { + f: *fn(l: *listener) (*io::stream | io::error) => f(l), + null => errors::unsupported, + }; +}; + +// Shuts down a [[listener]] and frees resources associated with it. +export fn shutdown(l: *listener) void = { + match (l.shutdown) { + f: *fn(l: *listener) void => f(l), + null => void, + }; +}; diff --git a/net/options.ha b/net/options.ha @@ -0,0 +1,30 @@ +// Enables keep-alive for a socket. +export type keepalive = void; + +// Configures the backlog size for a listener. If not specified, a sensible +// default (10) is used. +export type backlog = u32; + +// Enables port re-use for a TCP listener. +export type reuseport = void; + +// Enables address re-use for a TCP listener. +export type reuseaddr = void; + +// To have the system select an arbitrary unused port for [[listen]], set port to +// zero. To retrieve the assigned port, provide this as one of the options and +// the addressed u16 will be filled in with the port. +export type portassignment = *u16; + +// Options for [[connect]]. Not all options are supported by all socket types or +// platforms. +export type connect_option = keepalive; + +// Options for [[listen]]. Not all options are supported by all socket types or +// platforms. +export type listen_option = ( + keepalive | + reuseport | + reuseaddr | + backlog | + portassignment); diff --git a/net/socket.ha b/net/socket.ha @@ -1,92 +0,0 @@ -use errors; -use io; -use net::ip; - -// Enables keep-alive for a socket. -export type keepalive = void; - -// Enables port re-use for a TCP listener. -export type reuseport = void; - -// Enables address re-use for a TCP listener. -export type reuseaddr = void; - -// Configures the backlog size for a listener. If not specified, a sensible -// default (10) is used. -export type backlog = u32; - -// To have the system select an arbitrary unused port for [[listen]], set port to -// zero. To retrieve the assigned port, provide this as one of the options and -// the addressed u16 will be filled in with the port. -export type portassignment = *u16; - -// Options for the [[listen]] family of functions. -export type listen_option = ( - keepalive | - reuseport | - reuseaddr | - backlog | - portassignment); - -// Options for the [[connect]] family of functions. -export type connect_option = keepalive; - -// Indicates that a send or recv operation should include out-of-band data. -export type oob = []u8; - -// Options for [[send]] and [[recv]]. -export type dgram_option = oob; - -// A listener binds a socket and listens for incoming traffic for some -// unspecified protocol. -export type listener = struct { - accept: nullable *fn(l: *listener) (*io::stream | io::error), - send: nullable *fn(l: *listener, to: ip::addr, port: u16, - buf: []u8, options: dgram_option...) (size | io::error), - recv: nullable *fn(l: *listener, - from: nullable *ip::addr, port: nullable *u16, - buf: []u8, options: dgram_option...) (size | io::error), - shutdown: nullable *fn(l: *listener) void, -}; - -// Accepts the next connection from a listener. Blocks until a new connection is -// available. -export fn accept(l: *listener) (*io::stream | io::error) = { - return match (l.accept) { - f: *fn(l: *listener) (*io::stream | io::error) => f(l), - null => errors::unsupported, - }; -}; - -// Shuts down a [[listener]] and frees resources associated with it. -export fn shutdown(l: *listener) void = { - match (l.shutdown) { - f: *fn(l: *listener) void => f(l), - null => void, - }; -}; - -// Sends a datagram to the given destination, returning the number of bytes sent -// (or an error). -export fn send( - l: *listener, - to: ip::addr, - port: u16, - buf: []u8, - options: dgram_option... -) (size | io::error) = { - abort(); // TODO -}; - -// Blocks until a datagram is received from a listener, writing it to the -// provided buffer and returning the number of bytes received. Populates the -// sender address and port in 'from' and 'port' if non-null. -export fn recv( - l: *listener, - from: nullable *ip::addr, - port: nullable *u16, - buf: []u8, - options: dgram_option... -) (size | io::error) = { - abort(); // TODO -}; diff --git a/net/tcp/+linux.ha b/net/tcp/+linux.ha @@ -0,0 +1,50 @@ +use io; +use net::ip; +use net; +use os; +use rt; + +// Opens a TCP connection to the given host and port. Blocks until the +// connection is established. +export fn connect( + addr: ip::addr, + port: u16, + options: net::connect_option... +) (*io::stream | io::error) = { + const sockaddr = ip::to_native(addr, port); + const sockfd = net::connect_fd(sockaddr, options...)?; + return os::fdopen(sockfd, ip::string(addr), + io::mode::READ | io::mode::WRITE); +}; + +// Binds a TCP listener to the given address. +export fn listen( + addr: ip::addr, + port: u16, + options: net::listen_option... +) (*net::listener | io::error) = { + let sockaddr = ip::to_native(addr, port); + let sockfd = net::listen_fd(sockaddr, options...)?; + return alloc(net::stream_listener { + l = net::listener { + accept = &net::stream_accept, + shutdown = &net::stream_shutdown, + }, + fd = sockfd, + }): *net::listener; +}; + +// Returns the remote address for a given connection, or void if none is +// available. +export fn peeraddr(stream: *io::stream) ((ip::addr, u16) | void) = { + let fd = match (os::streamfd(stream, true)) { + fd: int => fd, + void => return, + }; + let sn = rt::sockaddr {...}; + let sz = size(rt::sockaddr): u32; + if (rt::getpeername(fd, &sn, &sz) is rt::errno) { + return; + }; + return ip::from_native(sn); +}; diff --git a/net/unix/+linux.ha b/net/unix/+linux.ha @@ -1,5 +1,11 @@ +use errors; +use fmt; +use io; +use net; +use os; use rt; use strings; +use types; // Converts a UNIX socket address to a native sockaddr. export fn to_native(addr: addr) (rt::sockaddr | invalid) = { @@ -29,3 +35,39 @@ export fn from_native(a: rt::sockaddr) addr = { * => abort("Wrong address family!"), }; }; + +// Opens a UNIX socket connection to the path. Blocks until the +// connection is established. +export fn connect( + addr: addr, + options: net::connect_option... +) (*io::stream | io::error) = { + let sockaddr = match (to_native(addr)) { + a: rt::sockaddr => a, + invalid => return errors::unsupported, // path too long + }; + const sockfd = net::connect_fd(sockaddr, options...)?; + static let buf: [rt::UNIX_PATH_MAX + 32]u8 = [0...]; + return os::fdopen(sockfd, + fmt::bsprintf(buf, "<unix connection {}>", addr), + io::mode::READ | io::mode::WRITE); +}; + +// Binds a UNIX socket listener at the given path. +export fn listen( + addr: addr, + options: net::listen_option... +) (*net::listener | io::error) = { + let sockaddr = match (to_native(addr)) { + a: rt::sockaddr => a, + invalid => return errors::unsupported, // path too long + }; + let sockfd = net::listen_fd(sockaddr, options...)?; + return alloc(net::stream_listener { + l = net::listener { + accept = &net::stream_accept, + shutdown = &net::stream_shutdown, + }, + fd = sockfd, + }): *net::listener; +}; diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -544,10 +544,10 @@ linux_vdso() { net() { printf '# net\n' gen_srcs net \ - '$(PLATFORM)/socket.ha' \ - '$(PLATFORM)/util.ha' \ - socket.ha - gen_ssa net io os strings net::ip net::unix errors + '$(PLATFORM).ha' \ + options.ha \ + listener.ha + gen_ssa net io os strings net::ip errors rt fmt } gensrcs_net_ip() { @@ -568,12 +568,19 @@ net_ip() { gen_ssa net::ip bytes io strconv strings strio fmt } +net_tcp() { + printf '# net::tcp\n' + gen_srcs net::tcp \ + '$(PLATFORM).ha' + gen_ssa net::tcp io net net::ip os rt +} + net_unix() { printf '# net::unix\n' gen_srcs net::unix \ addr.ha \ '$(PLATFORM).ha' - gen_ssa net::unix strings + gen_ssa net::unix net errors os io strings types fmt } math_random() { @@ -793,6 +800,7 @@ linux::io_uring linux::vdso net net::ip +net::tcp net::unix math::random os diff --git a/stdlib.mk b/stdlib.mk @@ -249,6 +249,10 @@ hare_stdlib_deps+=$(stdlib_net) stdlib_net_ip=$(HARECACHE)/net/ip/net_ip.o hare_stdlib_deps+=$(stdlib_net_ip) +# gen_lib net::tcp +stdlib_net_tcp=$(HARECACHE)/net/tcp/net_tcp.o +hare_stdlib_deps+=$(stdlib_net_tcp) + # gen_lib net::unix stdlib_net_unix=$(HARECACHE)/net/unix/net_unix.o hare_stdlib_deps+=$(stdlib_net_unix) @@ -798,11 +802,11 @@ $(HARECACHE)/linux/vdso/linux_vdso.ssa: $(stdlib_linux_vdso_srcs) $(stdlib_rt) $ # net # net stdlib_net_srcs= \ - $(STDLIB)/net/$(PLATFORM)/socket.ha \ - $(STDLIB)/net/$(PLATFORM)/util.ha \ - $(STDLIB)/net/socket.ha + $(STDLIB)/net/$(PLATFORM).ha \ + $(STDLIB)/net/options.ha \ + $(STDLIB)/net/listener.ha -$(HARECACHE)/net/net.ssa: $(stdlib_net_srcs) $(stdlib_rt) $(stdlib_io) $(stdlib_os) $(stdlib_strings) $(stdlib_net_ip) $(stdlib_net_unix) $(stdlib_errors) +$(HARECACHE)/net/net.ssa: $(stdlib_net_srcs) $(stdlib_rt) $(stdlib_io) $(stdlib_os) $(stdlib_strings) $(stdlib_net_ip) $(stdlib_errors) $(stdlib_rt) $(stdlib_fmt) @printf 'HAREC \t$@\n' @mkdir -p $(HARECACHE)/net @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nnet \ @@ -819,13 +823,24 @@ $(HARECACHE)/net/ip/net_ip.ssa: $(stdlib_net_ip_srcs) $(stdlib_rt) $(stdlib_byte @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nnet::ip \ -t$(HARECACHE)/net/ip/net_ip.td $(stdlib_net_ip_srcs) +# net::tcp +# net::tcp +stdlib_net_tcp_srcs= \ + $(STDLIB)/net/tcp/$(PLATFORM).ha + +$(HARECACHE)/net/tcp/net_tcp.ssa: $(stdlib_net_tcp_srcs) $(stdlib_rt) $(stdlib_io) $(stdlib_net) $(stdlib_net_ip) $(stdlib_os) $(stdlib_rt) + @printf 'HAREC \t$@\n' + @mkdir -p $(HARECACHE)/net/tcp + @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nnet::tcp \ + -t$(HARECACHE)/net/tcp/net_tcp.td $(stdlib_net_tcp_srcs) + # net::unix # net::unix stdlib_net_unix_srcs= \ $(STDLIB)/net/unix/addr.ha \ $(STDLIB)/net/unix/$(PLATFORM).ha -$(HARECACHE)/net/unix/net_unix.ssa: $(stdlib_net_unix_srcs) $(stdlib_rt) $(stdlib_strings) +$(HARECACHE)/net/unix/net_unix.ssa: $(stdlib_net_unix_srcs) $(stdlib_rt) $(stdlib_net) $(stdlib_errors) $(stdlib_os) $(stdlib_io) $(stdlib_strings) $(stdlib_types) $(stdlib_fmt) @printf 'HAREC \t$@\n' @mkdir -p $(HARECACHE)/net/unix @HARECACHE=$(HARECACHE) $(HAREC) $(HAREFLAGS) -o $@ -Nnet::unix \ @@ -1299,6 +1314,10 @@ hare_testlib_deps+=$(testlib_net) testlib_net_ip=$(TESTCACHE)/net/ip/net_ip.o hare_testlib_deps+=$(testlib_net_ip) +# gen_lib net::tcp +testlib_net_tcp=$(TESTCACHE)/net/tcp/net_tcp.o +hare_testlib_deps+=$(testlib_net_tcp) + # gen_lib net::unix testlib_net_unix=$(TESTCACHE)/net/unix/net_unix.o hare_testlib_deps+=$(testlib_net_unix) @@ -1868,11 +1887,11 @@ $(TESTCACHE)/linux/vdso/linux_vdso.ssa: $(testlib_linux_vdso_srcs) $(testlib_rt) # net # net testlib_net_srcs= \ - $(STDLIB)/net/$(PLATFORM)/socket.ha \ - $(STDLIB)/net/$(PLATFORM)/util.ha \ - $(STDLIB)/net/socket.ha + $(STDLIB)/net/$(PLATFORM).ha \ + $(STDLIB)/net/options.ha \ + $(STDLIB)/net/listener.ha -$(TESTCACHE)/net/net.ssa: $(testlib_net_srcs) $(testlib_rt) $(testlib_io) $(testlib_os) $(testlib_strings) $(testlib_net_ip) $(testlib_net_unix) $(testlib_errors) +$(TESTCACHE)/net/net.ssa: $(testlib_net_srcs) $(testlib_rt) $(testlib_io) $(testlib_os) $(testlib_strings) $(testlib_net_ip) $(testlib_errors) $(testlib_rt) $(testlib_fmt) @printf 'HAREC \t$@\n' @mkdir -p $(TESTCACHE)/net @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nnet \ @@ -1890,13 +1909,24 @@ $(TESTCACHE)/net/ip/net_ip.ssa: $(testlib_net_ip_srcs) $(testlib_rt) $(testlib_b @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nnet::ip \ -t$(TESTCACHE)/net/ip/net_ip.td $(testlib_net_ip_srcs) +# net::tcp +# net::tcp +testlib_net_tcp_srcs= \ + $(STDLIB)/net/tcp/$(PLATFORM).ha + +$(TESTCACHE)/net/tcp/net_tcp.ssa: $(testlib_net_tcp_srcs) $(testlib_rt) $(testlib_io) $(testlib_net) $(testlib_net_ip) $(testlib_os) $(testlib_rt) + @printf 'HAREC \t$@\n' + @mkdir -p $(TESTCACHE)/net/tcp + @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nnet::tcp \ + -t$(TESTCACHE)/net/tcp/net_tcp.td $(testlib_net_tcp_srcs) + # net::unix # net::unix testlib_net_unix_srcs= \ $(STDLIB)/net/unix/addr.ha \ $(STDLIB)/net/unix/$(PLATFORM).ha -$(TESTCACHE)/net/unix/net_unix.ssa: $(testlib_net_unix_srcs) $(testlib_rt) $(testlib_strings) +$(TESTCACHE)/net/unix/net_unix.ssa: $(testlib_net_unix_srcs) $(testlib_rt) $(testlib_net) $(testlib_errors) $(testlib_os) $(testlib_io) $(testlib_strings) $(testlib_types) $(testlib_fmt) @printf 'HAREC \t$@\n' @mkdir -p $(TESTCACHE)/net/unix @HARECACHE=$(TESTCACHE) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nnet::unix \