The Simple Sockets Library Version 2.09 Charles E. Campbell, Jr., Ph.D. Terry McRoberts April 18, 2001 Abstract The Simple Sockets Library (SSL) allows C programmers to use interprocess com- munications via Berkeley sockets simply and quickly. The programmer is able to move information easily between processes on the same or different machines connected via Ethernet (tm) and using the TCP/IP protocol. Most of the SSL's functions resemble C's file i/o functions, so C programmers will find the SSL easy to learn. The SSL currently runs under various UNIX (tm) machines: IRIX (tm) (Silicon Graphics), SunOS (tm) (Sun), Domain O/S (tm) (Apollo), Ultrix (tm) (Dec), AIX (tm) (IBM), SCO (tm) , OSF (tm) , and VMS 5.x (tm) , and MS-DOS (tm) (using Borland C++ 5.0). Keywords Socket Interprocess CommunicationsIntermachine Communications Berkeley Sockets Ethernet TCP/IP Robotics Machine Control Contents 1 Introduction 1 2 The Library 3 2.1 User Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.2 Reference Manual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.3 Hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3 The PortMaster 16 3.1 Users Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.2 Sharing PortMasters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 3.3 Theory of Operation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 3.3.1 The PortMaster Firewall . . . . . . . . . . . . . . . . . . . . . . . . . 21 4 The Utilities 22 4.1 The sktdbg Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 5 Installation Instructions 27 5.1 Unix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 5.2 Vms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 5.3 Windows 95 ( or more recent) . . . . . . . . . . . . . . . . . . . . . . . . . . 28 5.4 Older Ms-Dos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 6 Appendix: Miscellaneous Functions 31 1 Introduction The Simple Sockets Library (henceforth to be abbreviated as the SSL) allows C programmers to develop systems of cooperating programs using Berkeley streaming Sockets running under the TCP/IP protocol over Ethernet. The SSL provides simple ways to move information between programs running on the same or different machines and does so with little overhead. During experiments with the Sreadbytes and Swrite functions, for example, between two machines, a 44; 000 bytes/second transfer rate was achieved with 4 bytes per packet and over 1; 000; 000 bytes/second was achieved with 128 bytes per packet. Of course, heavily loaded networks will affect the rate individual users achieve. The SSL provides two-way communications. The SSL was designed to resemble the FILE i/o system provided by the standard C li- braries (ie. fopen, fclose, fputs, etc. map to SSL analogs Sopen, Sclose, Sputs, etc.). Thus, C pro- grammers typically find the SSL easy to learn. A good analogy for the SSL refers to the phone system. There are three types of Sockets supported by the SSL that concern the user: a server, a client, and an accept socket. A server is analogous to someone waiting by several phones for a call, a client is analogous to someone making a call, and an accept is analogous to a (server) person accepting the call by picking up one of the phones. Thus, one must have a server for a client to make a successful connection. The server must in turn accept the connection. Unlike our overworked server person, however, the computer using the SSL is perfectly happy handling multiple \accept" Sockets concurrently. The SSL itself is provided in three main parts (see Table 1). The Library is composed of C functions and the PortMaster and the Utilities are self-contained programs. Table 1: The Three Parts of the SSL Library The functions that the users will link to are in the library. PortMaster The PortMaster is a daemon program which runs in the background. It allows clients to connect to servers using any available ports. UtilitiesThere are several utility programs provided with the SSL: sktdbg, srmsrvr, and spmtable. The SSL has been in use at NASA's Goddard Space Flight Center's Intelligent Robotics Laboratory (IRL) since May, 1991. The software appears to be stable at the current writing and reasonably robust. For example, the PortMaster, a background process provided in the SSL distribution, is resistant to hanging (and thereby being unresponsive). It uses Stimeoutwaits (see the Reference Manual) to return to its normal quiescent mode when communications with one of its clients ceases unexpectedly. The IRL uses the SSL to control its three robots; its use of the Ethernet is consequently somewhat heavy. Those of you who wish to control machinery or otherwise present a heavy 1 load may wish to purchase a \bridge" to isolate your machines from your local network. This isolation will benefit both the you and the network, as the heavy user will not be afflicted with slowdowns due to the network and the network will not be bothered with lots of packets which slows all its users down. Please contact COSMIC if you have serious difficulties (ie. bugs) with the SSL. 2 2 The Library ||| |||| The user of the SSL accesses|it|by|linking|his|or|her program to a library. A software library is typically a single file|which|consists|of|some|linkage|information along with pre-compiled object code; unfortunately,|methods|for|producing|a|library|and linking to it vary from system to system and compiler to|compiler.|Directions|for|several|systems|appear in the Section on Implementation. |||| || Practically speaking, a|library|is|composed|of a number of pre-compiled C functions to be utilized by the programmer.|The|calls|made|available|in|the SSL are reminiscent of those used by the various file functions|in|the|C|language|(see Table 2). ||||| ||||| ||||| ||||| |||||| Table 2: Simple|Sockets|and|Related|File|I/O|Functions||| |||| ___|___|File|FunctionS___ocket|Function ___ ___ ___|___|fopen||Sopen ___ ___ ___ ___|___|fclose|Sclose|___ ___ ___ ___|___|fread| Sread ___ ___ ___ | ___|___|fwrite|Swrite ___ ___ ___ | ___|___|fgets| Sgets ___ ___ ___ ___|___|fputs||Sputs ___ ___ ___ ___|___|fprintfSprintf___| ___ ___ || ___|___|fscanf Sscanf ___ ___ ___ The Sockets library depends upon the PortMaster running on your host machine. Only one copy of the PortMaster need be running at any time on a given machine, and may be started up by anyone by running the Spm program in the background. On Unix, the Spm program will put itself into the background. One may determine if your system has a Port- Master running by typing spmtable first { it will inform you of any existing servers if the PortMaster is up or tell you that the PortMaster is not up otherwise. A new feature of the SSL allows servers to share another machine's PortMaster. Thus, the SSL supports both distributed and centralized socket name to port mapping. If the machine on which a server is to run doesn't have a PortMaster, such as older MSDOS machines, then it can \borrow" another machine's PortMaster. A program may open a server Socket, a client Socket, or an accept Socket. Following the phone system analogy, assume that a server Socket is opened first. Then, a different program may open a client Socket which attempts to connect to the server { it succeeds when the server program \notices" that there is a connection waiting on the server Socket and then generates an accept Socket. The client Socket can open, however, before the server accepts the client; there just won't be any two-way communication until the server does accept the client. 3 2.1 User Guide Software using C must #include "sockets.h" and must link to the SSL. Directions for doing so will vary from system to system and also depend upon where the installer placed the libraries. Please refer to your compiler documentation and the SSL installer to know how to set up library linkage paths and for the include path to the sockets.h file. The software below illustrates some typical Socket code fragments to get a connected socket, assuming that the sockets.h file is on your compiler's include search path. If the sockets.h file has been placed in a standard system directory (not wise - updates to the compiler may wipe it off!) then you may have to substitute #include for #include "sockets.h" in the following examples. Example 2.1 A server with one accept #include "sockets.h" Socket *server; Socket *skt; server= Sopen("servername","s"); skt = Saccept(server); ... Sclose(skt); Sclose(server); Note in Example 2.1 that the servername is completely up to the programmer to select. Please note that all servers share the same namespace on any given machine, however. Example 2.2 A server with multiple accepts #include "sockets.h" Socket *server=NULL; Socket *skt=NULL; server= Sopen("servername","s"); do { skt = Saccept(server); ... Sclose(skt); } while(whatever); Sclose(server); Again, the programmer may select any servername. Note that the accept Socket (\skt") is re-used in Example 2.2. Example 2.3 A client #include "sockets.h" Socket *client; client= Sopen("serverName","c"); ... Sclose(client); 4 In Example 2.3, the serverName may be in the optional form serverName@machineName. Without the machine name specification, the PortMaster on the machine that the client is running on will be searched for the server. The smsrvr.c and smclient.c example programs provided in the SSL distribution give complete illustrations of Examples 2.1 and 2.3. Example 2.4 Using Sopenv #include "sockets.h" Socket *client; while(1) { client= Sopenv("serverName","c","SKTPATH"); if(client) break; sleep(1); } ... Sclose(client); The SSL allows the programmer to set up a group of machines for making client con- nections. In Example 2.4, the SSL tries to open a client to a server named serverName on any machine on the SKTPATH. The \SKTPATH" is an environment variable typically of the form machine1:machine2:machine3, ie. a list of machine names separated by colons. This example also shows a typical client connection attempt and sleep polling loop. A somewhat larger example is included in the distribution: multiskt.c. This example program concurrently accepts multiple clients on a single server, reads any messages sent its way from any of its clients, and sends a modified version back to the sending client. It uses the Smaskwait functions to block the multiskt process for friendly multi-tasking. It is a useful program to study in conjunction with the Manual below. Connected sockets are a pre-requisite for any of the I/O Socket functions described in the next section. Note that the server should have a unique name on any given machine. Servers may have the same name on different machines, although this may be confusing. It is suggested that one use the name of the process (at least as a prefix) for that purpose. Note that the only things that one can do with a server Socket are: open one, close one, generate an accept Socket with one, and test/block on one (for clients requesting connection). The SSL supports up to 10 clients concurrently awaiting acceptance on a server Socket, although many machines will limit that to 5 (silently). The SSL supports two way communication of data between a client and an accept Socket. Since the processes are not likely to be synchronized, often one process must somehow wait until the other process has sent it something. There are two methods to support this under the SSL: polling and interrupt-driven. The polling method uses a lot of CPU time, but lets the program do other tasks in the meantime. The interrupt-driven approach hangs the process (aka blocks and suspends) until something shows up on the Socket. The SmaskXXX group of functions allows one to hang the process until something shows up on any number of Sockets { sort of a big OR gate! The SmaskXXX alternative to polling also allows the programmer to insert non-socket file descriptors into the mask via Smaskfdset (and to remove them via Smaskunfdset) such as serial ports (ex. open with DEVICE), graphics queues (ex. SGIs with qgetfd), etc. 5 || || || || ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| |||||| ||| ||| ||| ||| ||| 2.2 ||Reference|Manual| ||||| This section|contains|a|description|of the functions available in the Socket Library. The SSL returns|three|types|of|Sockets:|a server, client, and an accept Socket. A Socket itself ||| is a data|structure|type|set up by the sockets.h header file. The Socket is deliberately used in a fashion|reminiscent|of|the|use|of|FILE pointers so that the C user who knows how to read and|write|a|file|will|immediately|feel comfortable with reading and writing Sockets. ||| ||| | ___|___ Return ___Function Ar___gument ___ ___ | ___|___ Type ___Name ___List ___ ___ ___ ___ Socket * ___Saccept (S___ocket *skt) ___ ___ ___ ___ void ___Sclose (S___ocket *skt) ___ ___ ___|___|char| * ___Sgets (c___har *buf, int maxbuf, Socket *skt) ___ ___ | ___|___|int| ___Smaskfdisset(i___nt fd) ___ ___ | ___|___|void| ___Smaskfdset (___int fd) ___ ___ ___|___|fd|set|| ___Smaskget (___) ___ ___ ___|___|int| ___Smaskisset (S___ocket *skt) ___ ___ || ___|___|void ___Smaskpop ___() ___ ___ ___|___|void|| ___Smaskpush (___) ___ ___ ___|___|void|| ___Smaskset (___Socket *skt) ___ ___ ___|___|int|| ___Smasktest (___) ___ ___ ___|___|void|| ___Smasktime (___long seconds,long useconds) ___ ___ ___|___|void|| ___Smaskunset (___Socket *skt) ___ ___ ___|___|void|| ___Smaskunfdset(___int fd) ___ ___ ___|___|void|| ___Smaskuse (___fd|set usermask) ___ ___ ___|___|int| ___Smaskwait (___) ___ ___ | ___|___|Socket| * ___Sopen (___char *skthost, char *mode) ___ ___ ___|___|Socket||* ___Sopenv (___char *srvrname,char *ctrl,char *envvar) ___ ___ ___|___|int| ___Speek (___Socket *skt, char *buf, int buflen) ___ ___ || ___|___|unsigned long_Speeraddr (S___ocket *skt) ___ ___ || ___|___|char * ___Speername (___Socket *skt) ___ ___ ___|___|void|| ___Sprintf (S___ocket *skt, char *fmt,...) ___ ___ ___|___|char|| * ___Sprtskt (S___ocket *skt) ___ ___ ___|___|void|| ___Sputs (___char *buf, Socket *skt) ___ ___ ___|___|int|| ___Sread (___Socket *skt, char *buf, int buflen) ___ ___ ___|___|int|| ___Sreadbytes (S___ocket *skt, char *buf, int buflen) ___ ___ ___|___|int|| ___Srmsrvr (___char *skthost) ___ ___ ___|___|int| ___Sscanf (S___ocket *skt, char *fmt, ...) ___ ___ | ___|___|int| ___Stest (S___ocket *skt) ___ ___ | ___|___|int| ___Stimeoutwait(S___ocket *skt,long seconds,long useconds) ___ ___ ___|___|int|| ___Svprintf (S___ocket *skt, char *fmt, void *args) ___ ___ ___|___|int| ___Swait (___Socket *skt) ___ ___ || ___|___|int ___Swrite (S___ocket *skt, char *buf, int buflen) ___ ___ 6 Socket *Saccept(Socket *skt) This function takes a server Socket and produces a Socket which has accepted a con- nection. This function may be used as often as wanted on the same server Socket! Note that one must have successfully opened a server prior to using Saccept to accept connections (see Examples 2.1 and 2.2). If this operation is unsuccessful, then Saccept will return a null Socket pointer. void Sclose(Socket *skt) This function closes a Socket of any type (server, client, accept). The Sclose function communicates with the local PortMaster whenever a server is closed. char *Sgets(char *buf, int maxbuf, Socket *skt) This is an I/O function which assumes that one has already opened a connected Socket (skt). It will attempt to get a null-terminated string from the Socket (up to maxbuf characters). This call will block (aka hang, sleep) until a string shows up, but otherwise acts much as a fgets() function does. If Sgets has a socket error, then a null pointer is returned. Otherwise, it returns the \buf" pointer. int Smaskfdisset(int fd) The Smaskfdisset() function works in conjunction with the Smaskwait() function. After the Smaskwait() function returns, one can use Smaskfdisset(skt) to test if a particular file descriptor is read-ready. void Smaskfdset(int fd) The SmaskXXX functions use a mask of type fd|set internally. Other operations, such as use of a serial port under Unix or the GL queue for SGI's Irises (see their qgetfd() function) use file descriptors. This function allows one to set up the SmaskXXX mask with one or more of those file descriptors. Smask Smaskget() The SmaskXXX functions use a mask of type fd|set internally. Other operations, such as use of a serial port under Unix, can also be used to set masks. This function provides access to the mask set up by Smaskset. The mate to this function is Smaskuse(). int Smaskisset(Socket *skt) The Smaskisset() function works in conjunction with the Smaskwait() function. After the Smaskwait() function returns, one can use Smaskisset(skt) to test if a particular Socket is read-ready. It is simpler then and thereby faster than Smasktest(). void Smaskpop() The Smaskpop() function, along with the Smaskpush() function, allows the program- mer to manipulate an internal stack of masks. The \top" mask is the current mask. 7 void Smaskpush() The Smaskpush() function, along with the Smaskpop() function, allows the program- mer to manipulate an internal stack of masks. The \top" mask is the current mask. void Smaskset(Socket *skt) This function is part of the SmaskXXX group. Sockets may be set up for Smaskwait'ing one at a time. Note that all Sockets are effectively OR'ed together for blocking; to clear the mask, pass a NULL Socket pointer to Smaskset: Smaskset((Socket *) NULL);. int Smasktest() This function is part of the SmaskXXX group. The Smasktest function supports polling { one may determine if anything is on any of the Smaskset Sockets and immediately receive a positive integer if there is, a 0 if there isn't, and a negative number if there's an error. void Smasktime(long seconds,long useconds) This function is part of the SmaskXXX group. Normally Smaskwait will block \forever" (well, at least as long as the machine stays up!). However, one can specify a time limit { then Smaskwait will return with a value of 0 if the time limit is exceeded. One may specify the time limit in seconds and micro-seconds. To clear the time limit (ie. restore Smaskwait to waiting forever), pass a negative time in either or both arguments to Smasktime. Waiting forever is also set up when both arguments to Smasktime are zero. void Smaskunfdset(int fd) This function is part of the SmaskXXX group. File descriptors may be entered into the mask via the Smaskfdset() function, and this function can remove it from the mask. This function is similar to the Smaskunset() function. void Smaskunset(Socket *skt) This function is part of the SmaskXXX group. Sockets may be removed from the Smaskwait's mask one at a time via this function. Like Smaskset, a Smaskunset((Socket *) NULL); will clear the entire mask. void Smaskuse(Smask usermask) This function is part of the SmaskXXX group. The internal mask in SmaskXXX can be set up by the user via this function. Often, Smaskset will be used to set up an internal mask, Smaskget will be used to obtain the resulting mask, and Smaskuse will be used to apply that mask. int Smaskwait() This function is part of the SmaskXXX group. The Smaskwait function will block (aka hang) the process until any Socket set via Smaskset has something waiting on it to be read. Note that Sockets set by Smaskset are retained; ie. they must be explicitly cleared by passing a NULL Socket pointer to Smaskset. 8 | | || || || || || || || || || || || || ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| |||| ||||| ||| ||| ||| ||| |||| Smaskwait|returns|a|positive|number|if something is waiting on a Socket, zero if a time- out occurs,|and|a|negative number on an error. ||| |||| Socket *Sopen(char|*skthost,|char|*mode)|| This function|is|the|workhorse|for|opening|Sockets. Basically, it can make either a server or a client|depending|on|the|mode.|| ||| ||| || ___|Mode|| Effect ___ ___|| s open a server ___ ___|| S open a server but, on failure, retry after using Srmsrvr ___ ___|| c open a client ___ ___||s###open a server with the specified port number ___ ___|S###like S above, but with the specified port ___ | ___| c###open a client to a server with the specified port ___ The skthost is the name of the server. If one is making a client Socket, then one may optionally use the form \servername@hostname" for the skthost. The \@hostname" form is not necessary for clients to servers that are on the same host as the client, as the default host is the local host. The \servername@hostname" form makes no sense for servers, and so, for opening servers, Sopen will ignore any \@hostname" portion of skthost. The \S" mode for opening servers, like the \s" mode, will cause Sopen to attempt to open a server, but if unsuccessful, Sopen will then use Srmsrvr using the provided skthost and then retry opening the server. In the case of s### or S###, the servers are set up with the TCP/IP option SO|REUSEADDR. This option alleviates some of the difficulties associated with re-starting servers with fixed ports. If the skthost is null or an empty string (""), the PortMaster is bypassed. One must specify a port number to use in that case. A warning is issued (as well as a null Socket*) because that is typically a programming error, not a user error. The PortMaster is also always bypassed for clients which specify port number (c###). In the latter case, a client connection is immediately attempted to the user-specified port number. If the function is not successful, a null Socket pointer is returned. If the user-specified server port mode is used with a skthost, the server will be registered with its PortMaster; clients need not use specified-port mode to connect (ie. they may set mode to "c") so long as they specify the correct name of the server. PortMaster sharing (by setting the environment variable PMSHARE) causes servers to work with the PMSHARE-specified machine's PortMaster. Clients should use the name of the machine that the PortMaster is on; the eventual connection will be made with the appropriate server program, even though it is running on a different machine than the PortMaster it uses. See Example 3.1 for an illustration of how PortMaster sharing works. 9 Socket *Sopenv(char *srvrname,char *ctrl,char *envvar) The Sopenv function is used to open client Sockets, but is formulated to resemble the Sopen function with one additional argument. Assuming your computer system supports the concept of environment variables, the Sopenv function can use an en- vironment variable of your choice to help it open a client. Typically, a SKTPATH environment variable gets set up by the user with a colon-separated list of machine names (ex. setenv SKTPATH \gryphon:dragon:xorn"). The Sopenv function attempts to open a client to a server of the given name on the current machine first, and then attempts to do so on each machine in the given sequence. If env_var is NULL or a null string, then SKTPATH will be used instead. If successful, a Socket pointer is returned, otherwise a NULL Socket pointer is returned. Please see Saccept on how to use servers. int Speek(Socket *skt, char *buf, int buflen) The Speek function behaves like Sread | up to buflen bytes, the buffer will be filled by whatever is currently on the Socket. This function does not remove those bytes from the Socket, however, and those bytes will be returned again on subsequent Speek, Sread, etc. calls. This function does not||block (aka hang, sleep). It will return EOF on select error, some negative number on recv error, zero if no data is present on the Socket, and a positive count of the available bytes otherwise. In the latter case, buf will have a copy of the bytes available. MS-DOS: Speek will only return a 1 when data is available on the Socket, not the number of bytes available. Furthermore, the buffer buf will be a zero-length string with just a null byte. unsigned long Speeraddr(Socket *skt) The Speeraddr function returns the internet address of the peer Socket. char *Speername(Socket *skt) The Speername function returns the name of the peer Socket. Internally, it has three buffers; thus it can be used up to three times in the same printf statement. void Sprintf(Socket *skt, char *fmt,...) The Sprintf function acts in an analogous fashion to fprintf, sprintf, etc, by putting formatted strings, appropriately null byte terminated, through the Socket. Thus, one may use either Sgets or an appropriate Sscanf to receive the information. char *Sprtskt(Socket *skt) The Sprtskt function returns a string describing the Socket. void Sputs(char *buf, Socket *skt) The Sputs function puts a null byte terminated string on the Socket in a fashion analogous to fputs. 10 int Sread(Socket *skt, char *buf, int buflen) The Sread function is similar to the read function in Unix. This function can block (aka hang, sleep) if nothing is on the Socket. Otherwise, it will return up to buflen bytes in the buffer \buf". This function will return whatever is on the Socket, and doesn't try to insure that buflen bytes are read. It returns the number of bytes read from the Socket. On error, an EOF is returned. int Sreadbytes(Socket *skt, char *buf, int buflen) The Sreadbytes function behaves much like Sread, and it too can block (aka hang, sleep) if nothing is on the Socket. However, it will not return until buflen bytes are read from the Socket and placed in \buf". On error, an EOF is returned. int Srmsrvr(char *skthost) The Srmsrvr function is made available to take care of those situations when skt = Sopen(\servername",\s") fails because the servername has been inadvertently left in the PortMaster's PortTable. This untoward event can happen, for example, when a process is aborted/exited without calling Sclose on its server(s). The Srmsrvr function will remove a server (or server@host) from the PortMaster's PortTable. Note: it will not|| close the associated Socket, nor free up any Socket memory, and is not||a substitute for Sclose. The Srmsrvr function will return either PM|OK (if successful) or PM|SORRY (other- wise). int Sscanf(Socket *skt, char *fmt, ...) The Sscanf function acts much the same as sscanf and fscanf, taking format strings and additional arguments in a like manner. The arguments Sscanf takes, of course, must all be appropriate pointers. This function will block if insufficient data is available on the socket according to the fmt. The Sscanf function returns the number of arguments for which it read data, which may be zero or incomplete if a socket error occurred. Normally, the returned count should equal the number of arguments with which Sscanf was provided. int Stest(Socket *skt) The Stest function allows one to determine if anything is available on the specified Socket, without blocking. It will return EOF on select error, some negative number on recv error, zero if no data is present on the Socket, and a positive count of the available bytes otherwise. MS-DOS: Stest will only return a 1 when data is available on the Socket, not the number of bytes available. 11 int Stimeoutwait(Socket *skt,long seconds,long useconds) The Stimeoutwait function blocks on the given Socket, but for no longer than the number of seconds plus the number of microseconds specified. The function returns the number of bytes available on the Socket (which may be zero), -1 if there was an error, and -2 on timeout. int Svprintf(Socket *skt, char *fmt, void *args) The Svprintf function reads bytes using a printf family format string from the Socket. As each format code is processed, the associated argument is changed in the args vector. It returns the number of format items processed. int Swait(Socket *skt) The Swait function will block (aka hang, sleep) until the specified Socket has data available. It will return EOF on select error, some negative number on recv error, zero if no data is present on the Socket, and a positive count of the available bytes otherwise. int Swrite(Socket *skt, char *buf, int buflen) The Swrite function will write buflen bytes from the buf buffer onto the specified Socket. The function will return a count of the number of bytes transmitted through the Socket, which should be equal to buflen. If the output is less than buflen, then an error occurred while writing to the Socket. 2.3 Hints The Hints below have been found useful at the Intelligent Robotics Laboratory at the God- dard Space Flight Center. They are based on almost a year's experience with the SSL. 1.The \Sscanf" function is dangerous. It will block until all of the format codes in its fmt string have been used. If somehow a programmer sends an improper string and Sscanf is used to receive it, then the receiving program will probably hang for quite a while. Dr. Campbell has found that it is somewhat safer to use Sgets to get an entire string from the Socket and then use sscanf and stpnxt to parse it. 2.Polling is unfriendly to other processes { it wastes a tremendous amount of CPU time merely querying the Socket(s) to see if anything is awaiting action. The various blocking functions are much better: Swait, Stimeoutwait, SmaskXXX, etc. 3.Unless your processes will always run on the same kind of machine, portability con- siderations argue against using Sread and Swrite to move non-character string data around { ie. floats, doubles, and even ints. Even if the programmer tests out the ma- chines and verifies that (s)he can safely move, say, a double around, or even a vector of doubles, data structures (struct XXX { ... }) may have \holes" in them placed there for word or byte alignment reasons. These \holes" may not be there (or may be placed differently) by other machines and compilers. 12 4.The Srmsrvr function is a rather rude function { there is no ownership check of a server. Please use your process name (or your id) as part of your server name so that servers do not clash. Remember: your server's name is in only one \name space" shared by all users on your machine. 5.For those of you who wish to use other services (ex. serial ports) which can use the select function provided by TCP/IP , check out Smaskfdset and its mate, Smaskunfdset. 6.The IRL has been using a leading two character command convention: tp~L~x~y~z rx ry rz will tell the \left" T3 robot to move to \x y z" (inches) in space with an orientation of \rx ry rz" degrees (roll, pitch, yaw). Longer words provide more readability but take up more bandwidth. Experimentally, Dr. Campbell has found that TCP/IP can transfer about 10,000 packets per second with up to 128 bytes in a packet. Loaded systems will, of course, achieve less throughput. 7.It is a good idea for clients to inform servers that they are quitting. The IRL has used the following convention: tq tells the server that the messaging client is quitting. Also, a tQ tells the server to shut itself down. The server then emits a tq to all of its clients to inform them that the server is shutting down (except for the one client who issued the shutdown command), and then closes itself down with Sclose. 8.The server-client relationship is intimately involved with object-oriented messaging { refer to the literature on object-oriented concepts. 9.The SSL can be used to support a no startup sequencing paradigm. Typically, clients who attempt to Sopen and fail should go into a poll - sleep loop: Example 2.5 Client Socket Polling skt= Sopen("servername","c"); while(!skt) { sleep(1); skt= Sopen("servername","c"); } The multiskt.c program illustrates how servers should be able to accept multiple clients using blocking judiciously. This non-sequencing approach allows one to bring up programs which have servers and/or clients without worrying about what comes first. For two programs, this isn't terribly serious, but at the IRL numerous programs providing numerous services are available and sequencing would be a nightmare. 10.As alluded to earlier, clients should tell servers and servers should tell clients when they are going down. The program that is not quitting should return to an \awaiting another client (or server)" mode (ie. see the preceding item). Thus, a troublesome program can be brought down, the programs to which it is communicating will gracefully terminate 13 their connections, and the programmer can then (hopefully) fix the problem. When the program is restarted, the non-sequencing approach will allow the program to seamlessly re-enter into communications with the other software. 11.When a machine is down, and an attempt to connect a client Socket using either Sopen directly or Sopenv to a server either normally or possibly on that machine, the Sopen will fail but will take an inordinately long time doing so (connection timeout). 12.When a program dies abruptly, connected Sockets appear to select() to have something on them (select is used by Stest, Smasktest, Swait, Smaskwait, Speek, Stimeoutwait). Hence, functions which normally block (Smaskwait, Swait) no longer block. On com- puters which can MSG|PEEK (Unix, Vms), the Stest, Speek, Sgets, and Sscanf func- tions will detect this situation and will return an error indication (EOF, NULL pointer, incomplete argument processed count) to indicate that the Socket has a problem (one should then Sclose the affected Socket). Furthermore, attempts to write to such dead Sockets may generate SIGPIPEs on Unix boxes. Unix programmers should write and install signal handlers for SIGPIPEs. 13.For multiple concurrent Sockets, one should generate routines for both closing and opening them. Example 2.6 Client Opening Function #include "sockets.h" typedef struct clientlist_str ClientList; struct clientlist_str { Socket *skt; ClientList *nxt,*prv; } ClientList *clhd=NULL; ClientList *cltl=NULL; ... ClientList *openClient(char *srvrname) { Socket *skt; ClientList *clist; while(1) { skt= Sopen(srvrname,"c"); if(!skt) sleep(1); } clist= (ClientList *) malloc(sizeof(ClientList)); if(cltl) cltl->nxt= clist; else clhd = clist; clist->prv= cltl; clist->nxt= NULL; 14 cltl = clist; Smaskset(skt); clist->skt= skt; return clist; } The openClient() function polls once a second in attempting to open a client Socket. Once it succeeds, a ClientList data structure is allocated, double-linked, and a pointer to it returned. In addition, the new client Socket is added to the Smask. Example 2.7 Client Closing Function void closeClient(ClientList *clist) { if(clist) { Smaskunset(clist->skt); Sclose(clist->skt); clist->skt= NULL; } } The closeClient() function removes the client Socket from the Smask system, closes the Socket, and then sets the skt pointer to NULL to guarantee that the now dead socket won't be inadvertently re-used somehow. 14.It is usually advisable to use some sort of handshaking protocol between server and client, especially when large data blocks are being moved. The TCP/IP buffers can easily get filled and data get lost otherwise. To facilitate this, the SSL sets sockets up with the TCP|NODELAY option so that small packets are moved out across and not collected (collection of small packets normally improves network efficiency since there's less overhead per byte of data). 15 3 The PortMaster Servers have names provided by the program which opens them. When a server is to be opened, the Sopen function temporarily opens a Socket to the PortMaster running on the same machine. The Sopen function then tells the PortMaster the server's name and the (ran- dom) port assigned to the new server, and then closes down the connection. The PortMaster retains a list of all active servers and ports running on its machine. A client is opened using the Sopen function, too. In that case, a connection is made to the PortMaster on the machine where the requested server is running. The PortMaster then tells the Sopen function the port number associated with the requested server, and then closes down the temporary connection. The Sopen function then attempts to connect to the server using the given port. The server program can use its server Socket to test if any clients are waiting to be connected to it (via the Stest function). If a client is waiting, then the server's program can accept the connection, generating an accept Socket (via Saccept). Once the connection is accepted, the program attempting to open the client Socket will finally receive a Socket pointer. 3.1 Users Guide The PortMaster is probably the simplest program to run: under UNIX, type Spm & and under VMS type run/detach Spm. The PortMaster will only allow one copy of itself to run on any given computer. It uses a fixed port address (1750, now registered with IANA) and implements a table of server names mapping to random ports. Although knowledgeable users could change the PortMaster's fixed port, this is discouraged: hopefully, PortMasters will proliferate across the world and, if they all use the same port on their machines, will be able to communicate with one another. In other words, the SSL will be unable to communicate with other SSL systems which use a different port for its PortMaster. Since MS-DOS is not a multi-tasking operating system, unlike UNIX, VMS, or Amiga-DOS, one cannot have a PortMaster running in the background | there is no background. Hence, MS-DOS programs are currently restricted to using client Sockets only, unless they can share another machine's PortMaster (see below). The PortMaster now supports a firewall: one can instruct the PortMaster to restrict access to a group of machines by their host addresses. See the section on The PortMaster Firewall below. 3.2 Sharing PortMasters PortMasters can now be shared. This feature was installed mainly to support MSDOS { since it doesn't have a background process capability, it cannot run PortMasters. Hence, it is normally restricted to running clients only, because servers normally announce their presence to their host's PortMaster. If the environment variable PMSHARE is set to some other machine, that other machine's PortMaster will be used by the host's processes attempting 16 | | | | || || || || || || || || || || || || || || || || || || || || || || || || || || || || || || |||| || || || ||| ||| to|open|servers.|From the client's viewpoint, the server appears to be on the machine with || the|PortMaster|{|the|client doesn't need to know about where the server actually is. ||| |||| Example|3.1|||PortMaster|Sharing || ___|| Machine ___Machine ___ Machine ___ || ___||| A ___ B ___ C ___ ___|| ___ ___ ___ ___|PMSHARE=machineb|___ ___ ___ ___|| ___ ___ ___ ___|opens server ASrvr ___ ___ ___ | ___| ___ ___ ___ | ___| B'___s PortMaster ___ ___ ___|| no___w has ASrvr ___ ___ ___|| on___its list ___ ___ ___|| ___ ___ ___ ___|| ___ ___pgm opens client ___ ___|| ___ ___to ASrvr@machineb ___ ___|| ___ ___ ___ ___|| B'___s PortMaster ___ ___ ___|| sa___tisfies ___ ___ ___|| cl___ient's request ___ ___ ___|| ___ ___ ___ ___| ___ ___pgm has client to ___ | ___| ___ ___ASrvr on A ___ In Example 3.1, three machines are in use. However, machines B and C could have been the same machine. In essence, when A shares B's PortMaster, the servers on A appear to be on B insofar as Sopen'ing a client is concerned. Internally, of course, B's PortMaster knows where the ASrvr is, and clients end up being connected to the server on machine A. 3.3 Theory of Operation Normally, users of the SSL will not need to read this section. However, for those who are curious... There are two main benefits to using the SSL: the functions are similar to those that the C programmer already knows how to use and hence the SSL has a rapid learning curve, and second, servers are assigned to currently available ports. The PortMaster is integral to providing the second benefit. Berkeley sockets are assigned ports, which are basically just integers. The port is used internally to assign the flow of data to the correct places. One must assign a specific port to a server or, alternatively, allow the system to assign any available port to it. Clients must use that same port number to connect to the desired server. Hence, the problem with using the \any available port" is how to get the client process to know what the currently assigned port is! Programmers using Berkeley sockets have typically just assigned a fixed port to 17 their server and hard-coded the clients with that port. If some other process just happens to use that same port, then things get messy { re-compile, wait until the other process goes away, etc. On a machine where there are many users, co-operation between the users may be impractical. The PortMaster solves the problem of associating a server name with a randomly assigned (and available) port, and making that association available to clients. The PortMaster itself uses a fixed port, and so servers and clients always know \where" it is. Whenever a server opens (using the Sopen("XXX","s") call), the Sopen function makes a Socket data structure, creates a Berkeley socket, initializes and binds the socket with any available port, and then connects to the PortMaster, using its fixed port. It then sends a \message" (PM|SERVER, which is simply an integer) to the PortMaster, telling it the type of Socket it is. Subsequently, the PortMaster gets the new server's name and the port it is assigned to. When a client opens, it makes a Socket, initializes a Berkeley socket as a client (using the AF|INET format), gets a \host" entity pointer (the server's machine is known as a host), and then connects to the PortMaster on the host machine. It then sends a \PM|CLIENT" to that PortMaster and the desired server's name; that PortMaster will respond with the associated port number (if there is one). The client then closes down the connection to the target host's PortMaster, and initializes a Berkeley socket with the port number it just received and returns a client Socket pointer to the user. Thus, the SSL's PortMaster system is a distributed database. There are advantages and disadvantages to this scheme. No PortMaster knows anything about servers residing on other machines; if a machine goes down, other machines which have no need to communicate with the downed machine are not affected. On the other hand, a single machine with a single PortMaster would obviate the need for clients to know what machines they wish to connect to, and could force servers on all machines to have unique names (as it is, servers can have the same name so long as they run on different machines). As a palliative, the Sopenv function supports the concept of a machine path via the use of environment variables. Using the Sopenv function, clients can \hunt" down a given server by attempting to open a client one at a time on each machine until a server of that name is found. Thus, the user can designate a local group of machines via an environment variable (typically, the \SKTPATH" environment variable is used for this purpose). The PortMaster talks to its temporary clients using a relatively simple protocol based on \messages" (integers) defined in the sockets.h header file. Table 3 illustrates the protocol. If the PortMaster is using its firewall capability, it immediately checks all of its temporary clients for approved machine status; a PM|SORRY is issued immediately prior to the protocol in Table 3 upon failure to be approved. The connection is then summarily severed. As indicated in Table 3, the PortMaster handles more events than just the PM|SERVER and PM|CLIENT events mentioned earlier. When a client opens to the PortMaster, it iden- tifies the type of service it wishes by sending that PortMaster a \message": PM|SERVER, PM|CLIENT, PM|CLOSE, PM|TABLE, or PM|QUIT. These messages are discussed below. Whenever the PortMaster does not understand the initial message (due to garbling or what- ever), the PortMaster will immediately issue a PM|RESEND message and then wait for 18 || || ||| |||| |||| |||| |||| |||| |||| |||| |||| |||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| |||||| |||||| |||||| |||||| |||||| |||||| ||||||| ||||||| |||||||||| ||||||||||| ||||||| ||||||| |||||||| |||||||| |||||||| |||||||| ||||||||||| ||||||||Table|3:|The|PortMaster|Protocol| |||||||| ||||||||| ||||||| ___|___||||EventClie___nt|SendsPo___rtMaster Sends ___ ___ |||||| ___|___|PM|CLIENT||___||| ___ ___ ___ || ___|___|||||||||||| ___ ___PM|OK / PM|RESEND ___ ___ ___|___||||||||"sktn___ame"||||___ ___ ___ | ___|___||||||| ___ ___PM|OK / PM|SORRY ___ ___ ||||||| ___|___|||||||| ___ ___port ___ ___ ||| ___|___|PM|CLOSE||___||||| ___ ___ ___ ||| ___|___|||||||| ___ ___PM|OK / PM|RESEND ___ ___ || ___|___|||||| port ___ ___ ___ ___ |||||| ___|___||||||| ___ ___PM|OK / PM|SORRY ___ ___ ___|___|PM|QUIT||||___|||| ___ ___ ___ ___|___|||||| ___ ___PM|OK / PM|RESEND ___ ___ ||||| ___|___|||||| "Port___Master" ___ ___ ___ ___|___|PM|SERVER|___||||| ___PM|OK / PM|RESEND ___ ___ ___|___||||||| "sktn___ame" ___ ___ ___ ___|___||| port ___ ___ ___ ___ |||| ___|___|||||| ___ ___PM|OK / PM|SORRY ___ ___ ___|___|PM|TABLE||___|| ___ ___ ___ ___|___|||| ___ ___PM|OK / PM|RESEND ___ ___ | ___|___|||| ___ ___count of servers ___ ___ ___|___||| ___ ___"server : port" ___ ___ ||| ___|___|| ___ ___... ___ ___ || ___|___|PM|FWINIT ___ ___ ___ ___ || ___|___| ___ ___PM|OK / PM|RESEND ___ ___ data. It will continue doing so for up to PM|MAXTRY times (in the sockets.h file as sent, PM|MAXTRY is defined as 20). If the limit of re-tries is reached, the PortMaster will peremptorily close down the connection and go back to its usual quiescent state waiting for a new connection. The PortMaster will wait no more than TIMEOUT seconds for data, which is set to 20 seconds in Spm.c as delivered. If that amount of time elapses, the PortMaster will summarily close down the temporary client and continue for more business. PM|CLIENT tells the PortMaster that a client is attempting to open. The PortMaster normally responds with a PM|OK and the program attempting to open a client responds with a null-byte terminated string (the requested server name). If the PortMaster finds the requested server in its list, then it responds with a PM|OK and then the port number, otherwise it sends a PM|SORRY. 19 If the PortMaster is using a firewall, it may respond immediately with a PM|SORRY if the client is originating from an unapproved machine. PM|CLOSE tells the PortMaster that a server is closing down. The PortMaster will normally respond with a PM|OK; the program closing down the server (via Sclose) will then send the port number. The PortMaster will then remove the associated server from its internal list of servers and respond with a PM|OK if the designated server was in its list and a PM|SORRY otherwise. PM|FWINIT tells the PortMaster to re-read its firewall datafile. The PortMaster will then respond with a PM|OK if it worked or PM|RESEND if something got garbled. PM|QUIT tells the PortMaster that a shutdown command is to be sent. The PortMaster responds with a PM|OK, and the program shutting down the PortMaster issues a null- byte terminated string, \PortMaster" (just to guarantee that a shutdown is really wanted). The PortMaster will then shutdown. This operation requires some knowledge of the protocol as no SSL function is provided to make shutting down the PortMaster easy. However, the sktdbg program does provide an easy way to shut down the Port- Master. Concerned system administrators may wish to remove the \shut" command from sktdbg. Shutting down the PortMaster does not affect currently connected Sock- ets; however, new connections between servers and clients cannot be made. On the other hand, starting up a new PortMaster is easy and anyone may do so { the Spm program itself will refuse to allow two PortMasters to run concurrently (and will say so). PM|SERVER tells the PortMaster that a server has been opened. The PortMaster will nor- mally respond with a PM|OK and then the program opening a server will send a string giving the new server's name and then will send its port. The PortMaster will then respond with a PM|OK upon success or a PM|SORRY if a server by that name already exists. If the PortMaster is using a firewall, it may respond immediately with a PM|SORRY if the server is originating from an unapproved machine. When PortMaster sharing is not operating, this event should never occur, as servers can then only be legally generated on the same machine that the PortMaster resides upon. The PortMaster enters its own host onto its internal firewall table whenever use of a firewall is enabled. PM|TABLE tells the PortMaster to give out a list of the servers it currently knows about. Normally the PortMaster will respond with a PM|OK, a count of servers (in network standard 2-byte format, see the Berkeley \ntohs" function for details), and a sequence of strings giving the server name and associated port number. The spmtable program and sktdbg's \table" function use this facility. 20 3.3.1 The PortMaster Firewall The PortMaster supports a firewall to keep out socket requests from unapproved machines. The firewall consists of a list of machines' internet addresses in a file. One specifies the file by one of two methods: 1.Startup with Spm -ffull-path-to-filename 2.Initialization of an environment variable, SPMFIREWALL, to the full-path-to-filename. The full-path-to-filename file contains records of the form: * * number number number number where the four numbers are the internet addresses of the machines permitted to talk to the PortMaster. The * indicates accept any number in that field. The firewall function examines incoming internet addresses by use of the getpeername function. The firewall file, often called spmfirewall.dat, may contain blank lines. The # is assumed to begin a comment and is stripped off. 21 4 The Utilities There are several utilities provided with the SSL, and they are explained below. These are all complete programs in themselves, and can serve as lessons on how to use the SSL. sktdbg server-name {s|c} sktdbg is the SSL's testing program. One may open server Sockets, accept Sockets, and client Sockets, test out how other program's Sockets are communicating, etc. See the subsection on sktdbg below. The \server-name" may take two forms: servername or servername@machine-name. The latter form may be used when attempting to open clients to servers residing on machines other than the one the user is currently running sktdbg on. spmchk [machine] This program tests the current machine by default, the named machine otherwise, for the presence of a PortMaster. It will return a 0 if the PortMaster is present, or a 1 otherwise, and is useful in scripts: spmchk || (nohup Spm > /dev/null &) Translated for non-csh/ksh users: if spmchk finds no PortMaster on the current ma- chine, start one up in the background in \no hangup on user exit" mode, with output headed to the bit bucket. (thanks go to Marty Olevitch for this program). For VMS users: spmchk:= [fullpath]spmchk.exe set noon spmchk if '$SEVERITY' .ne. 1 then run/detach [fullpath]Spm.exe set on spmtable [machine [machine [machine ...]]] This program lists the servers and port numbers on the requested machines. If no machine is listed, then the current machine will be used. srmsrvr [server-name [server-name [server-name ...]]] Sometimes the all-knowledgeable and omnipotent programmer finds a need to hit the control-c key or otherwise kill a running program with a server Socket. In such cases, the PortMaster does not get informed that the server has gone down. This utility will tell the PortMaster to forcibly remove the named server(s) from its list. Except when using sktdbg to open a server with sktdbg, the server names above can also have the form srvr@machine-name. This name specifies a server on a specific ma- chine. Note that the machine-name is its normal abbreviation (ie. gryphon) or its full name (ie. gryphon.gsfc.nasa.gov). 22 4.1 The sktdbg Program The sktdbg program was originally a testing facility to debug the SSL itself, but has proven exceptionally useful in debugging programs which use the SSL. Consequently, it is provided as part of the package. To start up sktdbg, one must choose between starting up a server or attempting to open a client Socket. Example 4.1 Starting up a sktdbg Server sktdbg servername s Example 4.2 Starting up a sktdbg Client sktdbg servername c One may also ask sktdbg to explain itself. Example 4.3 sktdbg Explanation sktdbg "?" When the sktdbg program is started, the first thing it does is attempt to create the requested type of Socket. Typically, attempts to make a server will succeed; if it doesn't, it will report a warning, apply Srmsrvr(), and try a second time to open the server again. If it fails twice, then usually the PortMaster is not running on your machine. Attempts to open a client to a non-existent server also yields an error message: \unable to Sopen(srvrname,c)". If the server is up and running, then a client Socket will be set up. The sktdbg program then prints out a little menu of actions that the user can take with it. The \Enter" prompt now also shows the number of bytes waiting on the queue for reading. This number is updated only when the prompt is generated; ie. it is not a dynamic value, but is often useful. In Table 4, there are 20 commands available, and are described below. accept Used by a server Socket to accept clients. Note that one may first do test to determine if a client is waiting. close Used by a server Socket to close down an accept Socket. fput This function takes a filename, fput filename, which sktdbg then opens. Every line in it, minus trailing white space, is sent via Sputs across the Socket. Sktdbg then closes the file. 23 Table 4: sktdbg Help Menu Socket Test Commands accept close fwinit fput get menu peek printf put q quit read rmsrvr scanf shutdown table test wait write ? ( 0 bytes) Enter: fwinit This call issues a PM|FWINIT to the local machine's PortMaster. The PortMaster will then re-read the firewall data file that it was optionally started up with (if it had none, then this command will have no effect). The fwinit command is useful for the owner of the firewall data file to change it and have the PortMaster update itself without bringing down the PortMaster and restarting it. get Uses Sgets to get a null-terminated string from the client. This call will block until something arrives for up to 60 seconds. isset Uses Smaskwait() with negligible timeout (1 microsecond!) and then uses Smaskisset() to determine if the socket is read-ready. This function was included mostly for testing Smaskisset(). menu 24 Repeats the Socket Test Commands menu (just like \?" below). peek Uses Speek to peek at what the client has sent. This call will not block, even if nothing is there yet. printf printf your-word Uses Sprintf to send "your-word 7 8. itworked!" through the Socket. put put your various sundry strings across Uses Sputs to send your strings on the same line through the Socket. q This function \quits" { uses Sclose to close down all Sockets that sktdbg is using and exits. Just like \quit". quit This function \quits" { uses Sclose to close down all Sockets that sktdbg is using and exits. Just like \q". read This function uses Sread to read whatever is on the Socket, and prints it out assuming that it received a string. rmsrvr rmsrvr server-name This function uses Srmsrvr to remove a server. scanf This function accepts a subset of format code: %c, %d, %f, and %s. It will call Sscanf once for each format code given to it. shutdown This function is dangerous! It will shut down the PortMaster on your current machine and perform a quit. Use of this function is strongly discouraged unless it is necessary to pull down a PortMaster. table The table function communicates with the PortMaster and prints out a table of all current servers and their ports (rather like spmtable). test The test function prints out the number of bytes awaiting perusal by a get or read operation. It does not block, even if nothing is waiting { it will return 0 in such a case. wait This function will block the process until something shows up on the accept or client Socket. 25 write write your sundry thoughts and words This function will Swrite your words, appropriately null-byte terminated, through the Socket. It can be read by the read function. ? Repeats the Socket Test Commands menu (just like \menu" above). This program is really quite simple to learn and run, and is useful to help the installer verify that the SSL is installed correctly. 26 5 Installation Instructions Installation varies, of course, from operating system to operating system. 5.1 Unix 1.Make a SKTS subdirectory somewhere, and extract the contents of the tape into that subdirectory (typically, tar -xvop, but systems will vary and you may need to spec- ify a tape drive). 2.If your machine is not ANSI C compliant, but supports prototyping anyway, edit the sockets.h file to #define ||PROTOTYPE||for your machine. 3.Type make all. These instructions should result in the SSL being compiled, the utilities being compiled, and the PortMaster being compiled. A simpleskts.a library results. Although the PortMaster gets started by the make instructions, you may occasionally need to re-start it (for example, after the computer goes down). System administrators should know how to modify their operating system to automatically bring up the PortMaster during a re-boot. Users may wish to place setenv SKTPATH machine:machine:machine... csh users export SKTPATH=machine:machine:machine... ksh users SKTPATH:==machine:machine:machine... vms users set SKTPATH=machine:machine:machine... msdos users in their .login, .profile, login.com, and autoexec.bat respectively. To link to the SSL, one must include \sockets.h". For example, under UNIX, a user should have a .HDR subdirectory with all his/her favorite header files and use \cc ... -I~/.HDR ... simpleskts.a". 5.2 Vms 1.Make a SKTS subdirectory somewhere, and extract the contents of the tape into that subdirectory. The original tape was a quarter-inch cartridge in Unix tar format, but you may well receive a different format. 2.Type @makeskts The \makeskts" command script will create several subdirectories, compile the SSL, and set up a \simpleskts.olb" library. It will not attempt to start up the PortMaster. Change to the \EXE" subdirectory under the SKTS subdirectory. The PortMaster should be started via run/detach Spm; you may or may not have sufficient privileges to do so. One may spawn the PortMaster, but as soon as you log off the PortMaster will rudely terminate. Due to the potential problem with privileges, the command script will not start up the PortMaster itself. 27 In order to make use of command-line arguments for sktdbg, etc, VMS requires that you first make \logical symbols." In your , place the following lines (with appropriately modified YOURDIR): $ spmchk :== $[YOURDIR.SKTS.EXE]spmchk.exe $ spmtable :== $[YOURDIR.SKTS.EXE]spmtable.exe $ spm :== $[YOURDIR.SKTS.EXE]spm.exe $ srmsrvr :== $[YOURDIR.SKTS.EXE]srmsrvr.exe 5.3 Windows 95 ( or more recent) Version 2.08 (currently the latest) of the SSL now runs under Windows 95. One may have a PortMaster running in the background on those machines, too! Since the present author only has Borland C++, only that compiler has been tested. Other compilers may need to modify the file to include any TCP/IP initialization they may require. 1.Set up your system with an appropriate C compiler, Ethernet card, and TCP/IP . 2.Copy the contents of onto your computer. 3.Use gunzip and untar to get the uncompressed files 4.Open a MSDOS console, change directory to ...\COSMIC 5.mkwin95 The smplskts.lib and various *.exe files should be generated in the COSMIC subdirectory. You may well want to have the Simple Sockets Library's PortMaster (Spm) always running in background. To accomplish this: 1.On your workbench, click the right mouse button 2.Select New 3.Select Shortcut 4.Put the fully specified path to Spm.exe in the Command Line dialog box. 5.Put Spm as the shortcut's name 6.Right-mouse click on the Spm shortcut 7.Select Properties 8.Select the Shortcut tab 9.In the Run dialog, left mouse click on the down arrow and select minimized. 10.Bring up Explorer 28 11.Click on the + in the left hand window near Windows 12.Click on the + in the left hand window near Start Menu 13.Click on the + in the left hand window near Programs 14.Double click on StartUp 15.Put the mouse cursor on the Spm shortcut; press the right mouse button and drag it over the right hand Explorer window. 16.Select Copy Here. You will now need to re-boot your machine for this operation to take effect. 5.4 Older Ms-Dos The SSL was compiled and tested using the Wollongong TCP/IP package with MicroSoft C (v6.0). Other compilers and TCP/IP packages may require adjustment to the SSL code. You must have a TCP/IP package for your machine, however { that is what provides Berkeley sockets over which the SSL provides a convenient overlay. Also, you must have an Ethernet card for your machine { that provides the hardware over which the information flows. Neither the TCP/IP package, the C compiler, nor the Ethernet hardware come with the SSL. 1.The SSL makes several assumptions, unfortunately, about where include files are (ex. see Speek.c). The installer will undoubtedly need to customize these include lines. These areas will always be in #ifdef MSDOS ... #endif zones. 2.Acquire a TCP/IP package for your computer (ie. Wollongong). 3.Acquire a C compiler for your computer (ie. Microsoft C, v6.0). 4.Acquire an Ethernet card and TCP/IP address for your computer. 5.Copy the contents of the provided diskette into your subdirectory. 6.For those of you with the software mentioned in Table 5: (a) Make a directory: c:\c600\socket (b) Make a directory: c:\c600\socket\exe (c) Copy wintcp.lib to c:\c600\socket (d) Copy socket.lib to c:\c600\socket (e) Copy slibce.lib to c:\c600\socket (f) Disable the MSDOS linker { possibly by renaming it to doslink. Use the Mi- croSoft C linker instead. (g) Return to the directory where you placed the SSL software. 29 (h) Type makeskt (which will use the Makeskt.bat command script). This script will use Makelib., compile, create the smplskts.lib library, and generate sktdbg.exe, spmtable.exe, and srmsrvr.exe. (i)You should be done installing the software at this point. 7.If your compiler is not ANSI C compliant, but supports prototyping, edit the sockets.h file to define ||PROTOTYPE||for your machine. 8.Follow your compiler's directions to compile to object file format all the C files in SKTS and SKTS\EXE. 9.Follow your compiler's directions to set up a \library" (a .LIB file) with all the .OBJ files in the SKTS subdirectory. 10.Change to the SKTS\EXE subdirectory and follow your compiler's instructions to link each of the object files, one at a time, to the \smplskts.lib" library, the TCP/IP library, and whatever libraries your compiler normally needs. The installation should yield a smplskts.lib (or something similar) library and three exe- cutable files (sktdbg.exe, spmtable.exe, and spmtable.exe). Note that the \SPM.EXE" file should not be generated; you could generate and execute it, but your clone could not use it as it does not allow the PortMaster to run in the back- ground. No attempt has been made to insure that the PortMaster is actually compilable under MicroSoft C, either. Someday a kludge to allow MS-DOS programs to be their own PortMaster may be developed, but that day is not yet. Using Wollongong TCP/IP , one will be restricted to three (or five if its \kernel" is rebuilt) clients. The software in Table 5 was used by the IRL and is known to work properly with the SSL. Other software may work but has not been tested. Table 5: Ms-Dos Software known to work with the SSL Software Product Company MicroSoft C, v6.0 MicroSoft Win/API for DOS, v4.1 The Wollongong Group, Inc. PO Box 51860 Palo Alto, CA 94303-4374 (415)-962-7100 Wollongong Win/TCP, v4.1.1 The Wollongong Group, Inc. 30 6 Appendix: Miscellaneous Functions The SSL uses nine functions from Dr. Campbell's xtdio library; these have been gathered together and made part of the simpleskts.a library. Several of the functions use a special data file, rdcolor.dat. Note: the error and outofmem functions claim they will \terminate" under certain con- ditions. Actually, they will call the function (*error|exit)(int rtn), which by default is the exit function. Programmers may easily prevent or otherwise control termination by simply setting error|exit to point to some other function. void error(int severity,char *fmt,...) The error function prints out an error, warning, or note type of message to stdout. This function takes four kinds of \severity": SEVERE, ERROR, WARNING, and NOTE. Both the SEVERE and ERROR levels will terminate the program. The other two, WARNING and NOTE, will not do so. The termination action tends to enforce a standard for what errors versus warnings mean! If your terminal type is supported by the rdcolor.dat file (see rdcolor below), SEVERE and ERROR messages are printed with a red leader, WARNINGs with a yellow leader, and NOTEs with a cyan leader. FILE *fopenv(char *filename,char *ctrl,char *env|var) The fopenv provides a file opening service akin to that provided by the Sopenv function for the SSL. The fopen() function will be used with the given filename and ctrl strings, and upon failure, the environment variable in env|var will be used like a PATH variable in attempts to open the file in one directory after another (until success). If none of the fopens succeed, then the fopenv function will return a NULL pointer. void outofmem(void *ptr,char *fmt,...) The outofmem function checks if ptr is NULL; if it is not, the function immediately returns. However, if the ptr pointer is in fact NULL, then the fmt and any subsequent arguments will be used like a regular printf to give a message to the user. The program will then terminate. void rdcolor(void) This function reads the rdcolor.dat file, which essentially is an extended \termcap" file. It uses the \RDCOLOR" environment variable with fopenv to search for the rdcolor.dat file. The function uses that file to set up various string variables (RED, CLEAR, { see below). void rdcputs(char *s,FILE *fp) This function puts a string out to the FILE pointer fp, except that those strings (XRED, XUWHITE, etc.) are interpreted using the rdcolor-provided string instead. char *sprt(char *s) This function returns a pointer to a static buffer (there are four of them). The string 31 s has all of its characters made into \visible" forms: control characters become ^A through ^Z and characters with ANSI values greater than or equal to 128 are made into ~### sequences. Characters which are normally visible are left unchanged. void srmtrblk(char *s) This function removes any trailing \blanks" (white space) from the end of a string. char *stpblk(char *p) This function returns a pointer to the first non-white space character in the string p (ie. steps past blanks). char *stpnxt(char *s,char *fmt) This function returns a pointer to the first character in s which would not have been read by a sscanf(s,fmt,...) function. Useful for quick and dirty parsing. char *strnxtfmt(char *fmt) The strnxtfmt function returns a pointer to the beginning of the (next) format code substring. If fmt is NULL, then the previous format string is used (ie. a pointer to the last fmt code is retained and the a pointer to the next format code pointer will be returned). This function bears some similarity to strtok except that it jumps from format code to format code (used by Sscanf). The rdcolor.dat file describes terminal escape sequences to use to control color and a few other actions. Each line which does not begin with a white space character is assumed to be a terminal line: terminal types are separated by vertical bars and the line is terminated by a colon. There are a number of strings defined (see Table 6). Escape sequences may include the sequence \e for the ESCAPE character and \b for a blank. Please see the rdcolor.dat file for examples. 32 || || ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| |||||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| ||| |||||| Table 6: rdcolor.dat strings | ___|___ String NameFun___ction ___ ___ ___ ___ BLACK subs___equent chars are black ___ ___ ___ ___ RED subse___quent chars are red ___ ___ ___ ___ GREEN subs___equent chars are green ___ ___ ___ ___ YELLOW sub___sequent chars are yellow ___ ___ || ___|___|BLUE subs___equent chars are blue ___ ___ ___|___|MAGENTA|sub___sequent|chars are magenta ___ ___ ___|___|CYAN|| subs___equent chars are cyan ___ ___ ___|___|WHITE|| subs___equent chars are white ___ ___ ___|___||| ___ ___ ___ ___|___|UBLACK||subs___equent chars are underlined and black ___ ___ ___|___|URED|| subs___equent chars are underlined and red ___ ___ ___|___|UGREEN||sub___sequent chars are underlined and green ___ ___ ___|___|UYELLOW|sub___sequent chars are underlined and yellow ___ ___ | ___|___|UBLUE| subs___equent chars are underlined and blue ___ ___ ___|___|UMAGENTAsu___bsequent|chars|are underlined and magenta ___ ___ ___|___|UCYAN| subs___equent chars are underlined and cyan ___ ___ || ___|___|UWHITE subs___equent chars are underlined and white ___ ___ || ___|___| ___ ___ ___ ___|___|RVBLACK|sub___sequent|chars are reverse-video and black ___ ___ ___|___|RVRED|| subs___equent chars are reverse-video and red ___ ___ ___|___|RVGREEN|sub___sequent|chars are reverse-video and green ___ ___ ___|___|RVYELLOWsub___sequent|chars|are reverse-video and yellow ___ ___ ___|___|RVBLUE||subs___equent chars are reverse-video and blue ___ ___ ___|___|RVMAGENTAs___ubsequent|chars|are reverse-video and magenta ___ ___ ___|___|RVCYAN| subs___equent chars are reverse-video and cyan ___ ___ | ___|___|RVWHITE|sub___sequent chars are reverse-video and white ___ ___ | ___|___|| ___ ___ ___ ___|___|NRML|| subs___equent chars are \normal" ___ ___ ___|___|BOLD| subs___equent chars are \bold" ___ ___ || ___|___|CLEAR the ___screen is cleared ___ ___ 33