SEALINK File Transfer Protocol August 24, 1987 Copyright 1986,87 by System Enhancement Associates, Inc. This document describes briefly the SEAlink file transfer protocol developers' package. SEAlink is a sliding window protocol that is fully backwards compatible with XMODEM in all tested implementations. The intent of SEAlink is to provide a file transfer protocol that does not suffer from propagation delays, such as are introduced by satellite relays or packet switched networks, while retaining full compatibility with XMODEM. Unlike other high-speed protocols, SEAlink does not "side step" to avoid using XMODEM, but instead works with an XMODEM driver to establish the fastest possible link, thus reducing startup delays in both SEAlink and XMODEM transfers. Actual tests of the enclosed routines has shown that SEAlink is capable of virtually eliminating propagation delays and turnaround delays. File transfers between New Jersey and Hawaii, which normally suffer a degradation of 50% or more due to satellite relays, proceed as fast as local transfers. Even transfers within the local exchange are speeded up by up to 20% at 2400 baud by the elimination of turnaround delays. Large volume tests show that SEAlink is capable of coming to within 2% of the theoretical minimum time for data transfer. The developers' package contains the following files: SEALINK.DOC This document. SEALINK.C A set of C routines for implementing SEAlink. CLINK.EXE A sample TTY program that implements SEAlink. You are granted a license to use this code in your programs, and to adapt it to your particular situation and needs, subject only to the following conditions: 1) You must refer to it as the SEAlink protocol, and you must give credit to System Enhancement Associates. 2) If you modify it in such a way that your version cannot converse with the original code as supplied by us, then you should refer to it as "SEAlink derived", or as a "variation of SEAlink", or words to that effect. In short, we're not asking for any money, but we'd like to get some credit for our work. This document is not meant to be a rigorous definition of the protocol. The code provided should serve to document the details and fine points of implementing SEAlink. We will, however, present a brief synopsis of how SEAlink adds sliding windows to XMODEM, and why XMODEM doesn't mind. First of all, SEAlink adds a block number to the ACK and NAK used in XMODEM.(1) We thus create "ACK/NAK packets", with the following structure: Byte 0: ACK, NAK, or C Byte 1: Block number Byte 2: One's compliment of block number This is identical in form to the first three bytes of a data packet, except that the SOH has been replaced with an ACK or NAK.(2) From the receiver's point of view, it does not matter if the trans- mitter is using sliding window or not. The receiver simply sends ACK and NAK packets as appropriate. Any XMODEM driver tested to date will simply ignore this excess data behind the ACK or NAK. From the transmitter's point of view, it just barely matters if the receiver can handle sliding window. The transmitter always acts as if it is sending sliding window, but varies the window size. If it is seeing valid block numbers and check values behind the received ACKs and NAKs, it sets the window size to six blocks. Otherwise, it sets the window size to one block. The result is that it only "sends ahead" if the receiver can handle it. It should be a fairly simple matter to apply the underlying SEAlink logic to almost any variant of XMODEM. The SEAlink routines provided in this package are also capable of passing system dependent information, such as true file size and time of last modification. This data is passed in a special header block. The header block looks exactly like any other block, except that it is block number zero. This is still backwards compatible with XMODEM, as a SEAlink receiver does not mind if block zero is missing, and any XMODEM receiver yet tested will regard block zero as a duplicate block and ACK it. (1) XMODEM/CRC uses a "C" in place of a NAK to indicate CRC error detection. SEAlink follows this convention, and supports either checksum or CRC. For brevity, this document will use the term NAK to mean either a true NAK (hex 15) or a C (hex 43). (2) See previous footnote. The data portion of block zero contains the following fields: Offset Size Contents ====== ==== ======== 0 4 Original file length. 4 4 Date and time file was last mofified, in seconds since 1979. 8 17 Original file name, as a null terminated string. 25 15 Name of transmitting program, as a null terminated string. 40 1 Overdrive flag. 41 87 Null filler and expansion area. Any field which the transmitter cannot support should be set to all zeros. Conversly, the receiver should ignore any null fields. The receiver may ignore any field which he cannot support. Of special interest is the byte flag at offset 40 in block zero. This is the "Overdrive flag", and is used to trigger streaming mode for high-speed, half duplex modems. In Overdrive mode the receiver stops sending ACKs for the bulk of the file transfer, thus facilitating transfers over a half-duplex connection. Overdrive is never required over a full duplex connection. Overdrive requires that the basic link be effectively error free. Overdrive is disengaged in either of the following conditions: o The transmitter will disengaged overdrive if it detects that the receiver has dropped out of overdrive, or does not support overdrive. o The receiver will disengage overdrive if it finds itself receiving an excessive number of bad blocks, as Overdrive requires an error-free link. The routines enclosed in this package should be reasonably easy to implement in your application. We have attempted to exclude compiler dependent and system dependent logic from these routines. You will need to alter our references to our communications driver to conform to your own driver. The communications related routines we use are: com_putc(c) Output character c to comm port. int com_getc(t) Get character from comm port within t tenths of a second. Return EOF if time limit expires. com_dump() Discard any pending output without sending it. In addition, we use the following routines for controlling timed loops: long timerset(t) Set a timer. Returns a timer value which will expire in t tenths of a second. int timeup(z) Check a timer. Returns true if timer z has expired yet, or false otherwise. These routines also make reference to the following functions for system dependent information, which is optional: filestat(name,&fs) Read directory entry for a file and return system dependent information. setstamp(f,dtg) Set a file's date/time of last modification. The SEAlink implementation provided in this package is used by invoking the two primary routines: int xmtfile(name) /* transmit a file */ char *name; /* name of file to transmit */ This routine is used to send a file. One file is sent at a time. If the name is blank (name is null or *name points to a null), then an end of transmission marker is sent. This routine returns a one if the file is successfully transmitted, or a zero if a fatal error occurs. char *rcvfile(name) /* receive a file */ char *name; /* name of file (optional) */ This routine is used to receive a file. One file is received. If a name is specified for the file, then that name WILL be used, and any name sent by the transmitter will be ignored. If the name is blank (name is null or *name points to a null), then the transmitter must provide a name for the file. This routine returns a pointer to the name of the file that was received. If the file transfer is not successful, then a null pointer is returned. The pointer returned by rcvfile() points to a static data buffer. This does not have to be freed (and should not be), but it will be overwritten the next time rcvfile() is called. The rcvfile() function works on a temporary file whose name is the same as the final file, but with a dash ("-") added at the beginning. If a file transfer is aborted, then this temporary file will be retained. An aborted file transfer will not harm a pre-existing file of the same name. In addition, this set of routines includes two global variables that may be set to affect the SEAlink driver. These are: int ackless; This is used to control the overdrive. It should be set to a non-zero value before calling the SEAlink transmitter if overdrive is desired. We recommend using overdrive at link rates greater than 2400 bps, and not otherwise. char *progname; This is used to set the "name of transmitting program" field in block zero. It should be set to point to a string constant. The SEAlink routines can be used for either single or multiple file transfers. To send multiple files, send each file one by one until either a transmit fails or all files are sent. If all files are sent, then signal the end by calling xmtfile() with a null pointer. To receive multiple files, call rcvfile() repeatedly until it returns a null pointer. This package includes a demonstration program named CLINK (pronounced "clink"), which is a simple TTY program for doing SEAlink file transfers. CLINK does not perform any sort of terminal emulation whatsoever. However, she will make use of the ANSI.SYS screen driver if you have it installed. CLINK may be used in either of two ways: interactive mode or command mode. To use CLINK in the interactive mode, give the command "CLINK" with no arguments. Press the "ESCape" key to give a command to CLINK. The command "?" (question mark) instructs CLINK to tell you what commands she understands. To use CLINK in the command mode, give the command "CLINK" with an argument. There are three arguments you can give CLINK in the command mode. These are: 1) Receive files; Do this with a command of the form: CLINK R CLINK will attempt to receive one or more files from COM1, and will terminate as soon as all files are received, or when the transfer aborts. 2) Transmit files; Do this with a command of the form: CLINK T ... CLINK will attempt to transmit the listed files over COM1, and will terminate as soon as all files are sent, or the transfer is aborted. may be one or more file names with or without drive and path specifiers. Wildcards may be used. 3) Give help; If you type: CLINK ? or any invalid command, CLINK will display a brief reminder of what arguments she understands in command mode. When CLINK is invoked in the command mode it normally uses COM1, does not alter the baud rate, and does not transmit in Overdrive mode. This can be altered by using any or all of the following command line switches: /P1 to use COM1: (default) /P2 to use COM2: /B to set baud rate /O for Overdrive CLINK comes with her own serial driver built in for the IBM PC family and true compatibles, but she is capable of using any standard FOSSIL driver.