ref: d0ffb958c7247028223c7e53253249d52a47a324
dir: /doc/api/libstd/networking.txt/
{ title: Networking description: libstd: Networking } Networking ---------- pkg std = type netaddr = union `Ipv4 byte[4] `Ipv6 byte[16] ;; /* network connections */ const dial : (dialstr : byte[:] -> result(fd, byte[:])) const announce : (ds : byte[:] -> result(fd, byte[:])) const listen : (sock : fd -> result(fd, byte[:])) const accept : (lfd : fd -> result(fd, byte[:])) /* ip parsing */ const ipparse : (ip : byte[:] -> option(netaddr)) const ip4parse : (ip : byte[:] -> option(netaddr)) const ip6parse : (ip : byte[:] -> option(netaddr)) generic hosttonet : (v : @a -> @a) generic nettohost : (v : @a -> @a) ;; Summary ------- This group of functions contains the basic, portable networking functionality provided by libstd. There are other packages shipped which provide access to the underlying functionality used to implement this code, and which may provide more control. The bulk of the functionality is fairly low level. Most of the client side networking should be done using nothing more than `dial` and `announce` Dial describes the endpoint to connect to in the form `proto!host!service`. `proto` can be any supported protocol. The host specified can be an IP address, hostname, or path to a local socket. The service ismay be either a named service, or a protocol specific port. If the port is not a component of the address (eg, Unix domain sockets) then it should be ommitted. On plan 9, the full dial(2) dial string syntax is suported. Data Types ---------- This contains the infomation that we extract by resolving a host. type ipaddr = union `Ipv4 byte[4] `Ipv6 byte[16] ;; This contains an IP address. Either V4 or V6 is supported. Connections ---------- const dial : (dialstr : byte[:] -> result(fd, byte[:])) Dial connects to a dial string as described in the summary, returning either a file descriptor on success, or an error description on failure. The FD returned is a connection to the server. const announce : (ds : byte[:] -> result(fd, byte[:])) Announce sets up a file descriptor which is ready to listen for connections, and binds it to an address. Wildcards can be specified with '*' within the dial string. const listen : (sock : fd -> result(fd, byte[:])) Listen specifies that the socket created with `announce` is willing to accept connections. const accept : (lfd : fd -> result(fd, byte[:])) Accept takes the returned file descriptor from listen, and returns a file descriptor that is prepared for reading and writing. IP Parsing ---------- const ipparse : (ip : byte[:] -> option(netaddr)) Ipparse will parse an IP address. This will recognize either V4 or V6 addresses, and `\`Some \`Ipv4 bits or `\`Some \`Ipv6 bits` as appropriate, or `\`None` if the address can't be parsed. const ip4parse : (ip : byte[:] -> option(netaddr)) Parses an Ipv4 address from the string `ip`. The syntax expected is dotted quad notation. Returns `\` Some \`Ipv4 bits` if the address parses successfully, or `\`None` if parsing fails. const ip6parse : (ip : byte[:] -> option(netaddr)) Parses an Ipv6 address from the string `ip`. Returns `\` Some \`Ipv4 bits` if the address parses successfully, or `\`None` if parsing fails. Zones are currently not supported. This is a bug. Endian flipping -------------- generic hosttonet : (v : @a -> @a) generic nettohost : (v : @a -> @a) Flips the bits in an integer to match the expected. These functions should be avoided in favor of explicit packing functions. Examples -------- Some simple examples of how to use the Myrddin networking API #### Echo Server use std const Dialstr = "tcp!*!1234" const main = { var lfd, afd var buf : byte[1024] match std.announce(Dialstr) | `std.Ok f: lfd = f | `std.Fail e: std.fatal("unable to announce on {}: {}\n", Dialstr, e) ;; match std.listen(lfd) | `std.Ok f: afd = f | `std.Fail e: std.fatal("unable to listen on {}: {}\n", Dialstr, e) ;; while true match std.accept(afd) | `std.Ok fd: match std.read(fd, buf[:]) | `std.Ok n: std.writeall(fd, buf[:n]) | `std.Fail e: std.put("lost conection while reading: {}\n", e) ;; std.close(fd) | `std.Fail e: std.fatal("unable to accept connection on {}: {}\n", Dialstr, e) ;; ;; } #### Echo Client use std const Dialstr = "tcp!localhost!1234" const main = {args : byte[:][:] var req, resp match std.dial(Dialstr) | `std.Ok fd: req = std.strjoin(args[1:], " ") std.writeall(fd, req) resp = std.try(std.fslurp(fd)) std.put("{}\n", resp) | `std.Fail e: std.fatal("unable to dial {}: {}\n", Dialstr, e) ;; } Bugs ---- The errors returned are strings, when they should be unions with default formatting functions.