Connection: adt { dfd: ref FD; # data file cfd: ref FD; # control file dir: string; # pathname of line directory }; announce: fn(addr: string): (int, Connection); dial: fn(addr, local: string): (int, Connection); listen: fn(c: Connection): (int, Connection); export: fn(fd: ref FD, flag: int): int;
dial: fn(addr, local: string): (int, Connection);
## returns tuple of (int, Connection). The int member is 0 for success, -1 for failure.The dial function establishes a connection to destination addr.
network!destination!serviceport
For more information about the structure of this address, see Request format in Chapter 6
If the connection server daemon is not running, the dial function silently skips the translation stage and attempts to open a network connection with addr as received.
The cs daemon is accessed by an interface file also called cs. The dial function looks for this file in the following directories in the OR'ed listed:
At the completion of dial, local can be read from the local file of the network interface.
On failure, the dial function returns -1 in the integer portion of the tuple.
On success, the members of the returned Connection adt have been initialized to the following values:
See the appropriate Network device pages (for example, ip - TCP, UDP network protocols over IP in Chapter 2) for further details of using this interface.
announce: fn(addr: string): (int, Connection);
## returns tuple of (int, Connection). The int member is 0 for success, -1 for failure.The announce function and the listen function described in this section are the complements of the dial function. Their actions allow completion of connection requests from clients using the dial function.
The localname component is translated (if possible) by the connection server. The result is stored in the local file of the network interface. That file can be used for display purposes. The localname value is not used by the underlying network. The setting of local file is skipped if localname is'
*'
.
The cs daemon is accessed by an interface file also called cs. The announce function looks for that file in two directories in the following order:
listen: fn(c: Connection): (int, Connection);
## returns tuple of (int, Connection). The int member is 0 for success, -1 for failure.The listen function allows the completion of a connection to a process calling the dial function.
When a call is received, listen returns a value that includes a Connection adt that leads to a network interface file. The ctl file descriptor of the returned Connection adt is open, but the data file descriptor needs to be explicitly opened. The data file of that interface is cross connected (read-to-write and write-to-read) to the data file associated with the Connection adt returned by the dial function to the client process.
export: fn(fd: ref FD, flag: int): int;
## returns 0 on success, -1 on failure.The export function responds to client requests for file operations on the server's file namespace. This is the server end of a client's mount call.
Note: Requests for pathname resolution occur relative to the current root directory of the process calling export. That process can control the set of files available for mount requests by clients by defining the root directory of its namespace using the operations described on the bind page.
The export function can take two mutually exclusive flags
EXPWAIT | The export function blocks until all client requests are complete. |
EXPASYNC | Client requests are handled by a background thread, while export returns immediately |
callkremvax( ): (int, Connection) { return sys->dial("tcp!kremvax!mpeg", nil); }Call the local authentication server:
dialauth(service: string): (int, Connection) { return sys->dial("net!$SIGNER!inflogin", nil); }Announce address and get a connection ADT:
addr := "net!*!" + hd tl argv; (ok, conn) := sys->announce(addr);Listen for a client on an announced connection:
(ok, conn) = sys->listen(conn); if (ok == -1) { print("cannot listen %s: %r\n", addr); return; } print("listening on %s\n", addr);Export a file descriptor fd.
if(sys->export(fd, sys->EXPASYNC) < 0) sys->fprint(stderr, "Error: styxd: file export %r\n");
implement Client; # a barebones TCP/IP client # typical usage: client machine 13 # date server include "sys.m"; sys: Sys; print, fprint: import sys; stdout, stderr: ref Sys->FD; include "draw.m"; # program name pname: string; Client: module { init: fn(ctxt: ref Draw->Context, argv: list of string); }; init(ctxt: ref Draw->Context, argv: list of string) { sys = load Sys Sys->PATH; stdout = sys->fildes(1); stderr = sys->fildes(2); pname = hd argv; argv = tl argv; # rudimentary argument checking if (len argv != 2) usage(); # dial server dialto := "net!" + hd argv + "!" + hd tl argv; (ok, conn) := sys->dial(dialto, nil); if (ok < 0) { fprint(stderr, "Cannot dial to %s: %r\n", dialto); return; } # read server message from conn.dfd answer := readbytes(conn.dfd); # write message to client console print("%s\n", answer); } readbytes(fd: ref Sys->FD): string { buf := array[8192] of byte; n := sys->read(fd, buf, len buf); if (n < 0) return ""; # return the bytes read from server return string buf[:n]; } usage() { print("Usage: %s server_name port_number\n", pname); exit; }