home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-06 | 78.4 KB | 1,609 lines |
-
-
- OOBPLUS - CompuServe B protocol objects
- Copyright (c) Steve Sneed 1991
- All rights reserved
-
-
- This document and the included source code ("the material") are the
- copyrighted work of their author. The material is provided to TurboPower
- Software, and a license is hereby granted to TurboPower Software, for
- distribution with their product(s). Purchasers of TurboPower Software
- product(s) that include the material may use the material under the same
- purchase agreement rights and restrictions as the TurboPower product(s).
-
- Portions of the material are copyright (c) by CompuServe, Inc. and
- are used by permission. "GIF" and "Graphics Interchange Format" are
- Service Marks (sm) of CompuServe, Inc., an H&R Block Company.
-
-
- ---- Other Documentation --------------------------------------------------
-
- The information and code provided here is based on the BPlus spec
- document, and the GIF 87a and 89a spec documents. For anything more than
- a direct "plug-n-play" implementation based on these objects you will
- definitely need those documents, and both are available for download from
- CompuServe. The BPlus document is available in the IBMCOM Forum's LIBrary
- 10 (Protocols) as PBDOC.ARC. The GIF 89a specification, which includes
- all of the 87a spec, is available in the PICS Forum's LIBrary 14 (Misc.
- Utilities & Code) as GIF89A.DOC. (Other word processor formats, such as
- WordPerfect and MSWord, are available for the GIF 89a spec; BROwse the
- library with a KEYword of "89A" or "SPEC" to find them.)
-
- The book "Programmer's Guide to PC & PS/2 Video Systems" (Richard
- Wilton, Microsoft Press 1988, ISBN 1-55615-103-9) is generally considered
- the "bible" of PC video programming. Highly recommended if you intend to
- work with GIF decoding. I have also found "C Programmer's Guide to Serial
- Communications" (Joe Campbell, Howard W. Sams & Company 1987, ISBN
- 0-672-22584-0) to be extremely helpful in general comm programming and
- protocols.
-
-
- ---- Overview -------------------------------------------------------------
-
- The CompuServe Information Service (CIS) is the largest and most popular
- system of its type in the world, with over 1,000,000 members in the US and
- abroad. CIS provides several "special" capabilities, such as the ability
- to display graphics in real time and the ability to encapsulate the entire
- online session within a protocol for improved data integrity and management.
- Many of these special capabilities are based on CompuServe's own transport
- protocol, the "B" protocol. Because of the size and number of users of CIS
- today, any communications program should provide support for at least the
- basic File Transfer Protocol (FTP) portions of the B protocol. OOBPLUS
- makes providing that support simple.
-
- The OOBPLUS unit provides a set of objects for B protocol. Derived from
- Async Professional's AbstractProtocol object, OOBPLUS provides a "plug-in"
- interface for both the B series protocol's FTP services, and the special
- version for use with CompuServe's GIF graphics image display services.
-
- There are three distinct species of B protocol in use today:
-
- "Classic" B: The original B protocol. This version defines a protocol
- similar in some ways to the XMODEM protocol but with special consider-
- ation for the packet-switcher network CIS uses to connect users to their
- hosts. It uses a 512-byte block at all bps rates, a one-byte arithmetic
- checksum, and simple "send block/wait for ACK" flow of control. It does
- allow for flexible block length of less than 512 bytes, and uses a fixed
- quoting set (see below). Classic B provides a much more robust protocol
- environment than XMODEM for CIS, but its thruput is only slightly
- better than XMODEM. Classic B was designed in the days of 300baud
- modems and early protocol technology.
-
- "Quick" B: Quick B (QB) is a major enhancement over Classic B. While
- maintaining backwards compatibility with Classic B it adds "send-ahead"
- technology (the ability to send more than one packet before receiving an
- acknowledgement), a larger 1K packet size for better thruput with higher
- speed modems, and 16-bit CRC blockchecking. QB is designed so the host
- can "handshake" with the remote and determine whether Classic B or QB
- will be used. QB was such a marked improvement over Classic B that many
- comm programs rushed to support it, and some unfortunately did not
- implement the handshake properly; as a result CIS had to add a new
- option to all of its protocols menus just for QB.
-
- "BPlus": BPlus (B+) is a superset of QB, or more correctly, QB is a
- subset of B+. QB was more a preliminary version of B+ than a
- self-standing version, and only the rapid implementation of QB by
- several major comm programs kept it in use. B+ defines several
- extensions and enhancements over QB, such as the "TI" file information
- packet type. B+ also introduced the use of flexible maximum packet
- size, to allow achievement of optimum packet size based on baud rate and
- other factors. Most importantly for users, B+ defines a method to
- resume an aborted download from the point of abort in the transferred
- file rather than forcing the download to restart from the beginning.
- CompuServe would like to see QB disappear completely and is encouraging
- developers to provide complete B+ support; many major comm programs
- (such a ProComm Plus 2.0 and CrossTalk XVI and Mk 4) have done so, but a
- large base of comm programs are still in use that only provide QB
- support (such as BitCom, which many modem vendors distribute free with
- their modems).
-
- B+ is not a file transfer protocol in the typical sense. It is a
- "Transport Level" protocol, and as such can be used to provide protocol
- error trapping and data management to an entire online session which may
- include file transfer sub-sessions. The full B+ specification defines
- multiple "layers" of protocol support, the lowest being the "Transport
- Layer". The transport layer provides the basic data packetization, flow
- control and error handling. On top of the Transport Layer may be
- "Application-Specific" layer(s) which performs preprocessing (such as
- decompression of compressed data) or prioritizing/directing of data to
- various parts of the overall program. In order to use B+ as a full
- transport protocol, the CIS host and the local program must handshake
- immediately after the remote logs into the service, both for protocol
- support and then for application support. This requires the remote
- software to have intimate knowledge of the host and vice versa, so this
- level of B+ is currently only used by software developed by CIS itself. B
- was originally developed for the Vidtex terminals back in the late 70's and
- early 80's, but currently the only software in the PC arena that uses
- full-session protocol encapsulation is the Host-Micro Interface protocol in
- the Compuserve Information Manager products for PCs and Macs.
-
- HMI NOTE: This new version of OOBPLUS now specifically includes the
- modifications nessessary to support the special HMI version of B+. However,
- because no documentation has been made publicly available by CompuServe on
- the exact format or usage of HMI, what's here has been arrived at by
- experimentation and may require modification as more information on HMI
- becomes available.
-
- The B+ protocol was designed with more than PCs in mind. Many types of
- computers access the CIS hosts, from Apple ]['s and RadioShack Model III's
- to Cray supercomputers. Also, CIS ties to several different telephone
- networks both in the US and abroad, and many of these networks are
- decidedly different from the network CIS itself owns and operates
- (especially the overseas PADs and networks). Because many of these
- networks use some control characters for their own internal purposes, and
- many of the mini and mainframe computers have their own interpretation of
- certain characters, B+ "quotes" some characters in a manner similar to
- Kermit. This gives the protocol greater flexibility, but has the negative
- effect of increasing packet overhead and slowing overall data thruput.
- Classic B defined a fixed quoting set of the first 32 ASCII characters, but
- this proved to be excessive for most microcomputers. B+ allows the quoting
- set to be negotiated during protocol session startup, so that the smallest
- nessessary set is used to maximize thruput.
-
- One of the most common questions I've heard about B over the years is,
- "How do I add it to my PC-based BBS?" I cannot recommend using B+ anywhere
- but on CIS for typical FTP uses. B+ is optimized for CIS' packet-switched
- networks and is the best protocol to use by far in that environment, but on
- direct PC-to-PC links the high per-packet overhead of B+ causes thruput
- to suffer dramatically. Also, a B+ "host-side" program can be difficult
- to interface to current BBS technology for forking protocol modules,
- because the filename prompting and startup process is different from the
- common protocols like XMODEM. For BBS use, you are much better off to use
- ZModem. B+ would, however, make a good base protocol for a transaction
- processing system or similar project that used serial links to other
- machines (I have used a modified version of it for such a system between a
- main VME-based processor and AT workstations.) Earlier beta versions of
- this library provided a host-side object derived from the BPProtoFTP
- object, but recent changes in CIS policy would require each person
- receiving this library to obtain a (no-cost) license directly from CIS
- before receiving the source or working TPU so it has been eliminated.
- (I've tried to remove all references to the BPProtoHost object throughout
- this document; if I've missed some please forgive me.)
-
-
- ---- Specifics ---------------------------------------------------------------
-
- OOBPLUS implements the B protocols in a layered fashion, just as the CIS
- hosts. An abstract parent object handles the basic flow management and
- packetization chores, while child objects implement the specific FTP and
- GIF receive services. A hierarchial diagram:
-
- AbstractProtocol
- ├── (...other derived APRO protocols...)
- └── BPProtocol {abstract BPlus parent}
- ├── BPProtoFTP {File Transfer services}
- └── BPProtoGIF {GIF receive/decode services}
-
- The BPProtocol abstract parent is derived from Async Professional's
- AbstractProtocol object to take advantage of some of its variables and
- methods. Like other protocols derived from AbstractProtocol, BPProtoGIF
- can be instantiated "on the fly", as it is needed. However, the
- BPProtoFTP object needs to be instantiated whenever the main program is
- receiving and processing characters from the commport.
-
- Because B is a transport level protocol, the host may send non-protocol
- data between protocol packets, or between the protocol support handshake
- and the first actual protocol packet. The term "protocol session" is used
- to denote some period of host-remote activity that begins with the
- handshake and ends with with a termination packet. A FTP or GIF-receive
- session may be a complete protocol session, or there may be other data
- and/or commands issued via protocol packets. Some of the variables used in
- the BPProtocol object and its children are "session dependent" and are
- initialized whenever the handshake is performed, while others are
- re-initialized each time a FTP or GIF-receive subsession is started.
-
- B+ requires an 8-bit data path. The CIS hosts default to E71 port
- parameters when you connect to the host, so your terminal handler must be
- able to switch to N81 "on the fly" for a protocol session, and back to E71
- when the session is complete. Such a flying switch, with data streaming
- into the port, is tricky to do without dropping characters. The SetLine
- method in Async Professional's AbstractPort object can be used to make the
- switch.
-
-
- Considerations for protocol handshake and initialization
- --------------------------------------------------------
-
- Most conventional protocols, such as XMODEM, are considered "receiver
- driven" because whichever end of the protocol link is receiving the primary
- data flow manages the protocol. B+ on the other hand is considered "host
- driven", because one end of the link is the "master" or host while the
- other is the "slave" or remote, irrespective of the direction of primary
- data flow. On CIS, the host is always the CIS computer, with the local
- PC system being the remote.
-
- Starting XMODEM is typically a two-step process: you start XMODEM on the
- other end of the link, and then you start it on the local end. B+ doesn't
- work this way; the host always starts the actual protocol processing
- session via command to the remote, without user intervention.
-
- B+ handles this as a two-step process. First the host issues an <ENQ>
- char to the remote. When the remote "sees" an <ENQ> in the incomming
- data, it calls the BPProtocol.HandleENQ method. This method responds with
- a specific sequence of characters as a "support/sync handshake":
-
- for Classic B: <DLE><'0'>
- for QB: <DLE><'+'><DLE><'0'>
- for B+: <DLE><'+'><'+'><DLE><'0'> (we use this)
-
- This tells the host what level of B is supported by the remote and that
- the remote's initial packet sequence number will be 0. It also initializes
- several internal variables that are protocol-session dependent. Once the
- remote has responded to the <ENQ>, the host may at any time (but not
- nessessarily immediately or as the next char) send the remote the
- two-character sequence <DLE><'B'>, the first two characters of a protocol
- packet. The remote software's terminal handler must look for any <DLE>
- received and call the protocol handler function bpDLESeen; the bpDLESeen
- method verifies the <'B'> char and continues protocol processing or exits
- as is appropriate.
-
- This means that the protocol handler object needs to be instantiated
- when you start your terminal handler loop (or before), so that the <ENQ>
- handshake properly initializes the nessessary vars in the object for later
- when the <DLE><'B'> sequence is received. For FTP and GIF uses, the
- <DLE><'B'> will almost always immediately follow the <ENQ> response, but
- for non-FTP purposes this may not be the case so we have to handle it that
- way. Also, you can set your user options at the CIS host end so that an
- <ENQ> is sent immediately after login (as a handshake) without starting
- a protocol session, so the <ENQ> must be handled throughout the online
- session.
-
-
- Packet definition and layout
- ----------------------------
-
- B Protocol "packets" are like XMODEM "blocks", but the term packet is
- used because the actual data within may be self-standing and have no
- connection to data in previous or subsequent packets. Each packet provides
- the information nessessary for the packet handler to determine what to do
- with the data, and even within a FTP or GIF session there may be packets
- that do not contain file data. For example, in the CompuServe Information
- Manager, when performing a FTP some packets are not file data but instead
- is data used to update the "tracking" status line at the bottom of the
- screen. During a protocol session, all commands and data in both
- directions, other than packet ACKs/NAKs, are sent via packets.
-
- The layout of a B packet:
-
- <DLE><'B'><SeqNum><...quoted data...><ETX><quoted checkvalue>
-
- The <DLE><'B'> identifies this as a B protocol block. The <SeqNum> field
- is an ASCII digit 0 thru 9 (ASCII $30 to $39) incremented each packet and
- wrapping back to 0 from 9. <...quoted data...> is the data block for this
- packet, and contains any command info needed by the packet handler as well
- as any "raw data" that might be needed in this packet. The data is quoted
- as nessessary to protect volatile characters. <ETX> is the "end-of-packet"
- flag character, and is sent unquoted. <Quoted checkvalue> may be either a
- one-byte arithmetic checksum or two-byte CRC depending on negotiated
- settings (see below), and is quoted as nessessary. Any given packet can be
- a maximum of 1024 data bytes in size and can be less (as few as one byte).
- The maximum size to expect is defined per handshake, and typically is
- chosen based on current baud rate to provide a good balance between thruput
- on good packets against turn-around time on flawed packets. CIS has shown
- the best average has proven to be a maximum packet size that gives a packet
- transmission time of 4 to 5 seconds at the current bps rate; at 300baud the
- packet size should be 128 bytes, at 1200bps it should be 512 bytes, and at
- 2400bps and above it should be 1K bytes.
-
- Quoting is performed by sending a <DLE> followed by the quoted data
- byte. If the byte to be quoted in in the range $00..$1F, it is OR-ed with
- $20 before sending, and if in the range $80..$9F it is OR-ed with $60.
- When the receiving side sees a <DLE> in the packet other than in the
- header, it assumes the next byte is quoted and reverses the sender's
- quoting after discarding the <DLE>. The checksum/CRC calc is performed on
- the byte's "natural" value, i.e. the CRC or checksum calc is performed on
- the byte before quoting on the sending side and after the byte is un-quoted
- on the receiving side. The <DLE> is discarded without inclusion in the
- checksum/CRC calculation.
-
- Classic B used a fixed quoting set, all chars in the range $00..$1F.
- This proved to be excessive on most systems, increasing overhead
- unnessessarily. In PC-based applications on most networks, only six
- characters actually need to be quoted: <DLE>, <ENQ>, <ETX>, <XON>, <XOFF>
- and <NAK>. The first three and <NAK> are used by the protocol itself and
- must be protected to prevent the protocol from becomming confused, and the
- flow control chars must be quoted to prevent unintended XOFF deadlocks.
- Other platforms require different quoting sets, so B+ defines several
- "standard" sets, but we only use 2: DQDefault (the minimum 6-char set) and
- DQFull (the full set, equal to the Classic B set). For B+, DQFull is only
- used during handshake, since at that point we have not negotiated the
- quoting set and protocol level, and must assume the worst.
-
- Each packet from either end must be acknowledged by the receiving end,
- although such acknowledgements may be delayed so that multiple packets are
- outstanding. Positive acknowledgements (ACKs) are sent as <DLE><SeqNum>
- where <SeqNum> is the sequence number of the packet being ACKed. Negative
- acknowledgements (NAKs) are sent as a single <NAK> character. Since the
- NAK does not specifiy to which packet it applies, the packet handler must
- keep track of how many packets are outstanding and assume the NAK refers to
- the oldest. This also means that when a NAK is received, *all* outstanding
- packets are discarded in order to keep the sequencing straight. Obviously,
- the higher the number of outstanding packets, the greater the amount of
- data that is resent - and the longer the "turn-around" time on a protocol
- error. B+ is currently defined as having a maximum of 2 outstanding
- packets. Tests by CIS have proved that more than two do not noticably
- improve thruput while seriously degrading performance on error turn-around.
-
-
- Packet types
- ------------
-
- Although all packets follow the above format, packets have different
- types. The first data byte of the packet (sometimes the first 2 bytes)
- defines the packet's type and is not part of other data in the packet. For
- FTP and GIF uses, the only types we are concerned with are "T", "N", "F"
- and "+" packets.
-
- "T" packets are transfer management packets. There are several subtypes
- of this packet type, used for specific transfer management jobs. "N"
- packets are "Next Data" packets, meaning they contain data that is a
- continuation of the previous packet(s). "F" packets are Failure packets
- and mean the protocol session is aborting for some reason. Again, there
- are several possible "F" packet types depending on the reason for the
- failure. The "+" packet is the special BPlus Parameters Handshake packet
- used during protocol initialization.
-
- "T" packets fall into the following categories:
-
- "T" - Transfer Init. This packet contains the file type (Binary or
- ASCII), the transfer direction relative to the remote (Upload
- or Download), and the file's name for the remote's storage.
- Sometimes called the "TD" packet.
-
- "TI" - Transfer Information. This packet can contain several
- different pieces of information (see the full B+ spec for a
- detailed description of the fields in this packet). We
- currently only use the FileSize field.
-
- "TC" - Transfer Complete. Signals the end of the current file.
- This packet will never contain file data; the last previous
- "N" packet contained the end of the file or GIF data.
-
- "Tr" - Resume Request. Special-case packet, sent by remote to
- request the host attempt a resume. The "Tr" packet will
- contain the size of the file (in bytes) that resides on the
- remote's disk, and a CRC of the file calculated in the same
- manner as a packet's CRC checkvalue. Note that CIS does not
- currently support Upload Resume (where the CIS host resumes
- a failed transfer of a file sent by the remote.)
-
- "Tf" - Transfer Resume Failed. Special-case packet, sent when a
- resume attempt request made by the remote failed. When the
- remote requests a resume attempt it sends the length and CRC
- of the "piece" of the file it has; the host verifies it's
- local file is at least as long and has an equal CRC over the
- matching length, and if either test fails the host sends this
- packet.
-
- The "N" packet is pretty much self-explanatory; it is a "Next Data
- Block" packet and contains only actual file contents data. Since B packets
- can be any length from one byte up to the maximum specified length, only
- the exact file length is transmitted without padding.
-
- "F" packets are typically sent for one of three reasons: the remote's
- user requested the protocol be aborted via keystroke or other manual
- method, the protocol has detected a hard failure such as too many
- sequential error packets, or the remote experienced a file I/O error.
- The host can issue Failure packets as well, and although they are rare we
- must be prepared for them.
-
- Typical Failure packet types:
-
- "FA" - Failure/Aborted. Sent when the user requested an abort.
-
- "FN" - Failure/Not known. Sent when an unsupported service was
- requested by the host. CIS supports several file types
- besides Binary and ASCII (for use on non-PC systems), but we
- can't handle them so we send a FN if the file type is not
- Binary or ASCII. Also, transfer direction flags other than
- Upload and Download may be used on non-PC systems, so if we
- see a direction flag other than "U" or "D" we send a FN
- packet.
-
- "FE" - Failure/Error. Usually sent when a hardware error occurs,
- such as file I/O error.
-
- Only the first two characters in a Failure packet have meaning to the
- CIS hosts, the "F" and the failure-type flag. Traditionally a text string
- is also sent in the packet as descriptive info on the failure, but this is
- only for use by the remote if it chooses to display the reason string.
- OOBPLUS follows this tradition.
-
- The "+" packet type is a special case. It provides a method for the
- host and remote to negotiate what level of B+ capabilities is to be
- supported during this session and the quoting set to be used. The "+"
- packet is typically sent between the <ENQ> handshake and the "T" packet.
- The host sends its "+" packet first with its capabilities, and the remote
- compares this information to its own capabilities and sends back a "+"
- packet with what it can support. The usual "+" packet handshake will set
- the number of outstanding packets that can be supported both on send and
- receive, the type of checkvalue used (CRC or arithmetic checksum), the
- maximum size of a packet in this session, whether the host will support
- download and/or upload resume and whether the remote can support it, and
- the quoting set to be used. See the interface section of OOBPLUS and the
- ProcessTransportParams method of the BPProtocol object for more detail.
-
-
- Flow of control
- ---------------
-
- The overall flow of control of a B protocol session is basically the
- same whether the transfer direction is Upload (from remote to host) or
- Download (from host to remote). A diagram of a typical download is the
- easiest way of visualizing the flow. An upload would be the same except
- for the direction of the "N" packets and the possible resume request (no
- resume on uploads). Notice that the host always starts the ball rolling.
- (The following information is specific to FTP and GIF uses of the BPlus
- protocol. Exact ordering may be different in non-FTP or GIF uses such as
- HMI.)
-
-
- HOST REMOTE
- ---- ------
- <ENQ> sent -----------> Init vars,
-
- Receive ENQ resp. <----------- Send ENQ Response
- Set vars to match
-
- ... (possible non-protocol data flow between sides) ...
-
- (NOTE 1)
-
- Send "+" packet -----------> Compare host's options with ours,
- set our options to "best-fit"
- the host's settings
-
- Configure to match <----------- Send "+" packet with our options
- remote's capabilities
-
- ... (possible non-protocol data flow between sides) ...
-
- (NOTE 2)
-
- Send "T" packet -----------> Process "T" packet info, enter
- protocol FTP mode, open file
-
- {!! IF FILE DOES NOT EXIST, SKIP TO "JUMP HERE" !!}
-
- (NOTE 3)
- File exists: calc CRC on file,
- build "Tr" packet with file's
- size and CRC,
- Gets "Tr" packet, <----------- send "Tr" packet
- check size & CRC:
-
- IF AND ONLY IF the
- file size and/or CRC
- checks fail, send
- empty "Tf" packet -----------> "Tf" recd, rewind on file (either
- overwrite from beginning, abort or
- question the user what to do)
-
- ELSE send first
- "N" data packet,
- contents of which
- are assumed to
- be appended to
- the existing file -----------> append data to file, ACK packet
-
-
- {JUMP HERE}
- Send "N" packets -----------> write data to file, ACK packet
- ...(as many times as needed)...
-
- Send "TC" packet -----------> Close file, flush pending ACKs,
- exit FTP mode
-
- ...(back to normal terminal operations)...
-
-
- Notes:
-
- 1) If the host is to send a GIF stream for decode/display, it will send the
- "Start GIF Decode" sequence immediately before the "+" packet. It will
- also send an <ENQ> after the start-decode sequence, so we must handle it.
-
- 2) If in GIF decode mode, there will be no "T" packet as it is unnessessary
- (there is no filename, and the direction and data type are fixed at
- Download and Binary). The first packet after the "+" packet will be the
- first "N" packet of the GIF stream's data.
-
- 3) No resume is possible on a GIF stream; it always starts from the
- beginning.
-
-
- Performance, thruput and packet size
- ------------------------------------
-
- When send-ahead is enabled (QB or B+ mode), multiple packets can be
- outstanding (meaning no ACK or NAK has been processed for that packet).
- The design of B+ is such that it always tracks the number of packets that
- are outstanding rather than a specific offset within the file (ala ZModem)
- or other criteria. This simplifies the tracking process, but it has the
- negative effect of requiring all outstanding packets to be discarded and
- resent when a packet is NAKed for some reason.
-
- Ultimate thruput for any protocol is a function of several factors: the
- port speed, percentage of overhead, turnaround delays on packet ACKs, and
- turnaround delays caused by defective packets that must be resent. B+
- essentially eliminates ACK turnaround delays, so raw thruput will closely
- approach the raw port speed. On binary transfers, B+'s quoting overhead
- will typically reduce data thruput to 92% - 96% of the raw thruput, while
- ASCII transfers will seldom be less than 98% of raw thruput. However, if
- one or more packets are defective and must be resent, the turnaround delay
- for the defective packet will be several seconds because multiple packets
- must be discarded and resent. Obviously this seriously degrades overall
- thruput, although the degredation percentage is a function of the number of
- packets in the transfer, the size of a packet and the number of "hits" that
- cause turnaround. A substantial amount of testing has been performed by CIS
- personnel on this subject, and it has been determined that a send-ahead
- window of 2 packets gives the best thruput with minimal turnaround delay,
- when used with a packet size that gives a per-packet transmission time of 4
- to 5 seconds at the current port bps rate. Smaller packets improve
- turnaround delay substantially, but hurt thruput on "clean" packets;
- packets larger than 1024 bytes do not markedly improve clean thruput but
- seriously hurt turnaround times. I have implemented packet size as a
- function of port bps rate in the same manner and using the same criteria as
- CIS software, but my own experimentation has shown that, at 2400bps, a
- 512-byte packet size reduces average data thruput by only 2% - 5% while
- reducing turnaround delays 50%. A like reduction of default packet size at
- 1200bps produces similar results. For most users the "factory settings"
- will be fine, but you may wish to make max packet size settable via
- external configuration to provide greater flexability - for example,
- providing a config option for "normal lines" or "noisy lines", and reduce
- the max packet size setting if the "noisy lines" option is selected.
- NOTE: current B+ implementations on CIS do not support re-negotiation of
- transport parameters during FTP or GIF sessions once a given protocol
- session has started, although it will "drop out" of send-ahead mode and
- revert to "send and wait ACK" mode if it sees a high percentage of
- defective blocks. The special version of B+ used by CIS hosts for HMI
- does support such re-negotiation. Adding re-negotiation capability for
- standard FTP and GIF sessions would be wonderful, but would break existing
- implementations.
-
-
- Other things
- ------------
-
- Most developers will implement watching for <ENQ>, <DLE> and GIF Decode
- Start signals from the host within some sort of terminal emulation code,
- possibly based on Async Professional's OOEMU unit's ANSI emulator. CIS
- supports ANSI/VT100, so this is convenient and works well. However, be
- aware of one point: CIS hosts actually use VT100 terminal command
- sequences. VT100 and DOS ANSI (ANSI.SYS and emulators built to mimmic it)
- are both unequal and improper subsets of the full ANSI X3.64 terminal
- control standard. Specifically, DOS ANSI handles defaults on the "J" and
- "K" commands differently than VT100, and an emulator that exactly mimmics
- DOS ANSI will find itself clearing the whole screen at the wrong times.
- Be sure your emulator setup processes the "J" and "K" commands in the
- VT100 manner when on CIS.
-
- CIS also can support a subset of the VT52 sequences. The <ESC><'I'>
- interrogation is a VT52 sequence, for example. You may wish to implement
- VT52 processing as well as VT100 to eliminate potential misunderstood
- commands. A child of Async Professional's AnsiEmulator can easily be
- derived that handles both command sets within one emulator, and is
- recommended.
-
- When you log on to CIS, the node you call defaults to Even parity/7
- data bits parameters. As mentioned above, a proper full B+ implementation
- needs to know when to switch to N81 parameters for the actual protocol and
- back once the protocol session is complete, but port and/or modem hardware
- can cause problems with the switch. You are usually better off to force
- N81 parameters for the entire online session. To do so you need to ignore
- both parity and framing errors from the port handler, and to mask all
- incomming non-protocol chars to 7 bits. CIS has a user configuration
- option to select N81 parameters, but this won't become active until you
- have logged in to CIS, so be prepared to cope. The TERMBP example program
- demonstrates one method of handling this.
-
- CIS supports other networks besides its own. Such "suplimental
- carriers" often behave differently than CIS' own network. Tymnet in
- particular seems to have occasional problems, though these are usually
- specific to the node you call. Specifically, Tymnet uses a PAD (Packet
- Assembler/Disassembler) system that uses the <DLE> char as a signal
- itself. In order for CIS to use the <DLE> char for its own purposes, it
- must tell the Tymnet network to consider that char "transparent". CIS
- issues the nessessary command automatically, but some Tymnet nodes are
- slow to update themselves. In this case the <DLE> is seen as a PAD
- command and is "swallowed" by the Tymnet node. Tymnet then sees the <'B'>
- as an unknown command and issues a "pad command error" string to the
- remote. Meanwhile CIS thinks it has switched things and has sent the "+"
- packet, and is waiting for a response. A long timeout ensues. This
- doesn't seem to crop up too often on normal FTP transfers, but is not
- uncommon on GIF sends. Thankfully this problem only seems to occur on a
- few nodes.
-
-
- ---- GIF Information --------------------------------------------------------
-
- First off, if you intend to implement GIF decoders, either off- or on-
- line, you absolutely need the GIF 89a spec document. It can be obtained on
- CompuServe (see the top of this file for info.) OOBPLUS is primarily a B
- protocols unit, with GIF decoding technology provided as demonstration
- only; trying to go into detail on GIF itself and the internals of a GIF
- decoder is really outside the bounds of this document. However, the GIF
- spec documents provide very little information on actual online decoder
- implementation details other than some general rules. I'll try to fill
- those gaps here.
-
- GIF (Graphics Interchange Format (sm)) is a definition for transmission
- and display of raster-based graphics image data - in other words,
- "bit-mapped" graphics. GIF supports images of up to 2048 by 2048 pixels
- and up to 256 colors. Extensions allow support for "full-color" images
- such as 24-bit Targa. GIF provides services for anamation and text display
- as well. GIF was developed by CompuServe as a medium for online graphics,
- with an eye towards future development in online graphics environments (ala
- Prodigy.) GIF in combination with "Transport Layer" B+ protocol provides a
- rich platform for this type of environment. GIF rapidly gained acceptance
- in the file-based imaging world as well, because of its space efficiency,
- ease of processing and device independence - so rapidly, in fact, that
- online GIF development has been practically non-existant. CIS early on
- set up a "Developer's Group" of graphics specialists and programmers to
- help steer the directions of GIF, but only myself and one other member of
- that group worked primarily with the online development aspects of the
- spec (and that other member has pretty much ceased online development.)
- Not surprizingly, only myself and one or two other members of that group
- develop primarily in Turbo Pascal; C and assembler are the norm.
-
- My primary purpose in providing both the GIF children to the B+ objects
- and the example decoders is to spark interest in GIF development,
- especially online. The horizons opened up by realtime online graphics are
- huge; the surface has only been barely scratched. I am deluged with calls
- from other developers and even more from companies and individuals with
- some idea for online graphics usage, wanting me to write this or that
- program (even whole BBS systems with built-in GIF databases!); I've taken a
- couple of these contracts but there's many, many more where they came from.
- (Tip: the real estate industry especially seems to be hurting for a good
- BBS-type system for Boards Of Realtors or Brokers to run for their agents,
- that provides a database of listings with images made from pictures of the
- properties. I get more requests in this area than any other. I'm not sure
- why but Medical Imaging is another popular area, although GIF's standard
- color resolution is generally considered insufficent for many medical
- imaging needs.)
-
-
- GIF general info
- ----------------
-
- GIF is a stream format. Besides making it simple to implement online
- display, this means GIF image data may formally be included in other data
- or that multiple GIF streams may easily be made into a "graphics database".
- CIS has steadfastly refused to formally define a "file format" for GIF, but
- a format for file storage has evolved over the years and is adhered to by
- all known decoders whose primary purpose is display of GIF files. As long
- as the first 6 bytes of the file's contents are the GIF signature
- ("GIF87a" or "GIF89a"), the image data is contiguous and a valid
- terminator exists, it can be handled by most any offline decoder.
-
- CIS maintains a "storage class" flag for each file in its forum
- libraries. If you BROwse a library's directory, you will see a "/bin" or
- "/gif" or "/rle" next to the filename on many entries. When uploading a
- file to CIS, you are prompted for, among other things, the file's type.
- Most users assume that "binary" and "ASCII" are all there is, but GIF image
- files should be uploaded with a file type of "GIF". Even if a file
- contains a GIF image and has filename extension of ".GIF", CIS will not
- allow online display of the file's contents unless the file's storage class
- is GIF as well.
-
- GIF image data, with the exception of the header blocks, is binary
- raster-based sequential pixel color data, compressed using a modified form
- of the LZW compression method. The image raster data is uncompressed on
- the fly as it is being displayed. It is somewhat difficult for the LZW
- decompressor to itself determine when a invalid byte is received - usually
- it is not detected until it has corrupted the codes table in the decom-
- pressor, often leading to a lockup. Most decompressors do no or only
- minimal error-checking; they assume the data handed to them is valid.
- For this reason the GIF spec notes that the image data stream must be
- guaranteed error-free. For disk-based streams this is assumed, but for
- online decode the stream must be protected by protocol. The GIF spec does
- not define one particular protocol that is recommended for image streams.
- This is important for the bigger world of Bulletin Board Systems; it means
- that it is perfectly acceptable to implement an online GIF decoder that
- uses ZModem or some other protocol, so that users of BBS' without CIS B+
- support can still easily view GIF images in an online environment. Since
- the main thrust of this unit is the B+ protocol I am only detailing
- decoding GIF streams from B+ encapsulation, but careful study of the
- example code in OLGIF.PAS should make it fairly obvious how to implement a
- GIF decoder using the other protocols Async Professional provides.
-
- The GIF spec does define the two protocols CIS computers will use for
- transmission of online GIF display streams: raw stream data (assumed to be
- protected by a link-level protocol such as MNP or V.42, and not to be used
- without such link-level protection) and B+ protocol. It also defines a
- "handshake" system to be used to determine both that GIF is supported for
- online display, and what level of protocol and hardware support is
- available on the particular remote. While only CIS uses this handshake
- system, it behooves developers to support it for online decoders based on
- other protocols as well, as a standard needs to evolve on this particular
- point.
-
- The handshake consists of 3 different "private" ANSI command sequences
- ("private" because only CIS defines them). These use the standard ANSI
- X3.64 introducer sequence (<ESC><'['>) followed by a right pointer bracket,
- a numeric code specifier and the command type tailer character. The
- sequences are:
-
- <ESC>[>0g - sent by host to interrogate remote for GIF/protocol/hardware
- support. If the remote supports GIF display, it returns a
- string consisting of codes that tell the host to use raw
- stream or B+ transmission, what screen resolutions (X by Y,
- and number and depth of colors), whether hardcopy output is
- supported, and which version of the spec the decoder supports
- (87a or 89a). See the spec document for the various details
- of this code scheme.
-
- <ESC>[>1g - begin online decoding to the local screen. This will be sent
- by the host immediately before the <ENQ> to handshake B+
- support. Once this is received, you can safely assume that
- the next <ENQ> will be to handshake the start of a B+ session
- to transmit the GIF stream. Non-B+ sessions will see the
- next char after the command be the first char of the GIF
- signature starting the image data.
-
- <ESC>[>2g - begin decoding to the local hardcopy device. Lots of systems
- still in use simply do not have the video capabilities to
- adequately display GIFs, especially the higher-resolution/
- high number of colors images available from many sources.
- Also, some areas of the service provide graphics that are of
- more use as hardcopy than on the screen (such as the weather
- maps, or the stock performance graphs in the TRENDS area).
- I don't support hardcopy decode in this set of examples, but
- it is fairly easy to implement and a handy capability. The
- handhake sequence above can be used to tell the host we want
- hardcopy decode, and for color printers can tell the host
- to use provide normal color information.
-
- One important note concerning the "0" code above: it is *not* sent every
- time an online GIF decode is requested. In the forum areas of CIS, it is
- usually sent the first time you request a online decode and not sent again
- until you leave that forum, either to another area of CIS or back to the
- same forum. Most of the non-forum areas of CIS that support GIF at all
- make GIF support their primary purpose, such as the weather maps areas and
- TREND; these areas will send the "0" inquiry when you first enter the area
- before they display any menu text or prompts. Your program must be able to
- handle the "0" inquiry at any time, just as it must be able to process a B+
- <ENQ> or <DLE> at any time.
-
- Until recently there were a few areas of CIS that provided GIF support
- but did not support B+ encapsulation (the TREND area was the most commonly
- accessed.) These areas defaulted to raw stream even if the remote reported
- its ability to handle B+, so a decoder had to be able to determine if B+
- was initializing or not and process incomming data accordingly. As you can
- imagine, this lead to a lot of headaches, and problems for users when the
- unprotected stream took a line hit and locked up the system. To the best
- of my knowledge there are no such areas left on CIS; all areas that provide
- any support for online GIF decoding support B+ encapsulation, and all areas
- support B+ by default unless specifically told otherwise by the "0" code
- response string described above.
-
- The flow of control for B+ when processing a GIF stream for display is
- very little different from a "normal" FTP session, with a couple of notable
- exceptions:
-
- 1) As mentioned in the B+ infomation above, there is no "T" packet sent
- during a GIF display. Since many of CIS' GIF streams are built and sent
- "on the fly" in real time they have no filename, and obviously the
- transfer's direction and data type are fixed at "Download" and "Binary".
- This only complicates matters a little bit, and only if you are writing the
- image data to a file as well as displaying it (something every online
- decoder should do, but that CompuServe's own software products do not.)
- If you do write the image to a file, it's your responsibility to determine
- a name for the file and manage getting the stream data into the file; see
- OLGIF.PAS and TERMBP.PAS for an example. Such processing really should be
- part of the BPProtoGIF object, but I have not included it that way because
- the spec does not define the capability; you may wish to derive a child of
- BPProtoGIF that does.
-
- 2) The data in each "N" packet is yours to do with as you wish. The
- BPProtoGIF object provides a method (bpGetGIFDataBlock) that gets the next
- pending "N" packet and hands you the data within it; what you do with it
- from there is your business. This provides an example of possibilities for
- non-FTP uses of B+, but it also points out that protocol management is to a
- large extent outside the bounds of the BPProtoGIF object - if you don't
- call bpGetGIFDataBlock, or fail to call it in a timely fashion, the
- protocol will time out and abort. Also, to give the GIF decoder enough
- power to properly manage the protocol flow, packets must be ACK-ed by the
- GIF decoder itself (defective packets are handled automatically within the
- GetPacket method of the BPProtocol parent of BPProtoGIF). The same goes
- for sending "F" packets in case the user wants to abort the decode or the
- decoder itself has a problem. With power comes responsibility; study the
- OLGIF.PAS file for an example of how to manage the flow control properly.
-
-
- OOBPLUS and GIF
- ---------------
-
- GIF data may come from a single file, the serial port, as a piece of a
- file from database-type storage, etc., and may be sent to the screen, a
- printer, or some other output device, so it makes sense to isolate the
- process of getting the stream's raw data and outputting the processed image
- data from the decoder's inner workings. Doing so also makes implementing a
- GIF decoder thru a protocol much easier. The demo decoders' kernel
- (DEGIF.PAS) names two procedure pointers, one to a function which returns
- the next byte of raw data and one that does something with a processed
- raster line of display data, and refers only to these proc pointers for
- source and destination. Various "shells" can then be wrapped around the
- decoder to implement the routines for a particular decoder's needs.
-
- This allows any protocol that gathers data in packets or blocks to hand
- a block of data to the decoder shell and go on about its business; the
- shell will dole out the bytes to the decoder. The downside (at least for
- single-thread operating systems like DOS) is that actual decode/display
- only takes place between packets, which gives the decode the appearence of
- occuring in spurts. It also makes basing a GIF decoder on true streaming
- protocols like ZModem a bit trickier, as the decoder has to get some time
- to do its job.
-
- The BPProtoGIF object provides two methods for the decoder. The first,
- the bpDLESeen virtual method, handles the "+" packet reception and
- processing. It is a function, returning True if it is successful and False
- otherwise; the decoder should abort if the function returns False. The
- second is the bpGetGIFDataBlock function, which returns True and a packet's
- worth of raw GIF stream data if successful, False if the packet reception
- failed for some reason. bpGetGIFDataBlock also returns a Boolean var
- parameter showing whether the "TC" packet has been received, to make it
- easier to see the end of the protocol session.
-
- When the main program sees the GIF decode startup ANSI sequence, it
- should initialize itself and start looking for an <ENQ> from the port to
- handshake the B+ protocol session. Immediately after the <ENQ> should be
- the <DLE> starting the host's "+" packet; the decoder calls bpDLESeen at
- this point. From here until we receive the "TC" terminating packet, all
- port data will be B+ encapsulated GIF image data, to be processed by the
- decoder. We simply loop calling bpGetGIFDataPaket and handing the received
- bytes to the decoder until done. Review OLGIF for examples.
-
-
- Video support considerations
- ----------------------------
-
- There is a multitude of video hardware types available for PCs. How do
- we support 'em all? Which should we support?
-
- In today's hardware market, SVGA cards are the most common video cards
- sold. SVGA support is a "must" in a GIF decoder. But... Any graphics
- programmer will tell you: programming for SVGA can be a royal nightmare.
- At least a dozen "common" main SVGA chipsets (more all the time) and, once
- past the "IBM-standard" EGA/VGA modes, each having different mode
- resolutions, different mode select numbers for those resolutions that are
- the same, and different coding requirements to manage video memory
- bankswitching and plotting.
-
- The TP BGI's provide a high level of device independence, and can be a
- reasonable starting point for a GIF decoder. But GIF's device-independent
- nature doesn't keep device dependence from cropping up. Because GIF
- encoders and decoders are implemented on a wide variety of platforms, many
- of which have video resolutions different from the common PC video modes, a
- sizable percentage of GIF images are not "sized" to fit well on a PC screen
- unless special handling is performed. Also, since GIF is a high-resolution
- format, it is commonly used with video hardware for which there is no BGI
- support (including Targa, TIGA, IBM's new HGA and others). Only a few
- SVGA BGI drivers are available, and do not cover all common SVGA chipsets.
- While decoder speed is not much of an issue in online environments until
- the port bps rate reaches 9600 and above, a production offline decoder
- that paints an image on the screen at BGI speeds will be considered
- totally unacceptable. Finally, the BGI's are pretty topheavy considering
- that GIF support only requires 2 video routines to do its job - a method
- of setting the video card to the needed graphics mode and back to text
- mode when done (a simple video BIOS call), and a routine to plot pixels or
- raster lines on the screen. An intelligently written set of routines done
- in assembler that will detect and support all common video types from Herc
- mono to SVGA, complete with SVGA chipset autodetect code and bankswitching
- code, will take less code and data space than a single BGI driver linked
- into the program. Turbo Pascal 6.0's BASM makes an ideal environment for
- the nessessary assembler, though I have stuck with straight TP in the demo
- code for the sake of compatibility with earlier versions of TP and to be
- more informative. Although it can be done, it is no trivial job to write
- straight TP code that directly manipulated SVGA hardware since most
- chipsets require substantial diddling of ports; VGA and lower video types
- can be dealt with in straight TP code quite acceptably, but assembler is
- still preferred on these cards for best speed.
-
- The easy way out is to use the BIOS services for pixel plotting. This
- is only marginally faster than the BGI's, but easier to deal with and with
- substantially less code overhead. It is a dangerous way to go, though,
- especially on CGA and earlier EGA and VGA cards - these older cards'
- BIOS routines for plotting typically disable interrupts while plotting the
- pixel, which in an online environment leads to dropped characters at the
- port and a high percentage of resent data. And on Hercules monochrome cards
- it is unavailable. I have mixed the best of both worlds in the demo
- decoders (see GIFVIDEO.PAS), but a production program should use direct
- hardware manipulation as far as possible for best speed and minimum
- potential interference with the serial port.
-
- That said, there's a cure on the horizon: VESA. VESA is a set of
- standards for SVGA detection, mode selection and video manipulation that
- provides a consistent set of mode resolutions, commands and data access to
- eliminate most all the confusion between SVGA chipsets. VESA is still new
- but gaining support by leaps and bounds; all the major video manufacturers
- support the VESA standards at least via a TSR. Some are now bringing to
- market cards that support VESA standards "hardwired" on the card,
- although this is currently quite difficult due to the severely limited
- room in most SVGA video BIOS ROM chips. There are no VESA-compliant SVGA
- BGIs available that I know of, but at least one is currently under
- development and looks very good. In this most recent version I have added
- the nessessary VESA support to work with this code; it is in no way a
- complete VESA interface, but it does work on all cards/drivers I have
- been able to test with.
-
- On the subject of CGA and Hercules mono support: I have included
- support for these hardware types, but really only for their instructive
- capability. CGA and Herc mono simply do not have the size and/or color
- resolution to do justice to the vast majority of GIF images today unless
- all sorts of sneaky tricks are used. With CGA and Herc mono rapidly
- becomming a thing of the past (a low-end VGA card and mono analog monitor
- costs about the same as a Herc card and mono TTL monitor and a *lot*
- less than CGA), there's even less reason to expend effort and code space
- on their support. However, if you need such support, you will need to
- implement some sort of dithering method to do color reduction. In GIF
- context, "dithering" an image means to perform colors reduction so that
- the colors in the original image are mapped to best fit the available
- palette on the local system. There are a number of common color-reduction
- dithers in use. Most all work on the principle of error distribution;
- spreading out the color error over surrounding pixels. Just about all of
- them require the decoder to have access to pixel data "in front of" the
- current pixel - data that is unavailable to a decoder getting its data
- from the serial port unless relatively complex buffer management is used.
- Implementing such dithers is left to your skills and imagination, with the
- following tip: there is a large base of dither technology available in
- LIBrary 14 of the PICS forum on CIS, although practically none of it is in
- Turbo Pascal. If you can wade thru C and assembler code, you'll find lots
- of good information with which to get started. A good dither method to
- reduce 256-color maps to 16 colors is important for EGA support as well.
-
- The switch from text mode to graphics mode is a sticky spot for online
- GIF. The header blocks must first be received so the decoder can
- determine which mode to use before making the switch, so data will be
- typically be streaming into the port when it is time to make the switch.
- Most every video BIOS in captivity disables interrupts while it switches
- modes, so at least a few bytes will be dropped by the port - causing a
- defective packet and a resend. This doesn't cause the protocol any grief
- it can't handle, but it does slow things down unnessessarily. The cure is
- relatively simple: send the host an XOFF and wait for the port to become
- "quiet" for some arbitrary length of time before making the mode switch.
- Async Professional does not provide a method for waiting for a port to
- quiese, so the demo adds a method for doing it; the method employs a sneaky
- trick and goes against good OOP programming, so you may want to implement
- such a method within the port handler object. Don't forget to send an XON
- after the mode switch is complete!
-
-
- ---- Beyond what's here: where to get help ----------------------------------
-
- The demo decoders are fully compliant with the 87a version of the GIF
- spec. They will also decode GIF streams built to the 89a version of the
- spec, but will ignore all 89a extensions. The DEGIF.OBJ module is
- copyright (c)1989 Cyborg Software Systems, Inc., 3119 Cossell Drive,
- Indianapolis, IN 46224 USA., and used by permission of its author.
-
- As mentioned before, dealing with the vagaries of SVGA hardware can be
- a daunting task. John Bridges, author of GRASP and PCPaint, is a past
- master at it. John periodically uploads a file to LIBrary 14 of the PICS
- forum called VGAKIT.ZIP, that contains SVGA chipset autodetect and
- bankswitch code, example plotting code, code to set and use special "not
- supported by BIOS" modes on the VGA, and other juicy tidbits. Be prepared
- for MASM code written primarily to interface to MSC, but the conversion to
- TASM and TP is fairly straightforward; John and I spent some time last
- year working the kinks out so his MASM code requires minimal changes to
- port to TP/TASM.
-
- The best allaround source for GIF help is the Developer's Den section
- (17) of the PICS forum. The place is haunted by some of the best and
- brightest graphics minds in the world, all ready and willing to share their
- expertise. You'll find specialists in ray-tracing, format conversion,
- fractals, high-end video, scanning, etc.
-
- I can be contacted via CIS at User ID# 70007,3574. I frequent several
- forums at least once a day, especially IBMCOM, PCVENB (TurboPower's section
- 6), BPROGA and PICS. The TurboPower folks will be happy to help you as
- well, but to help keep their support headaches in check I hope you'll
- contact me first; they may need to forward questions to me anyway.
- US Mail will reach me at:
-
- Ozarks West Software
- 14150 Gleneagle Dr.
- Colorado Springs, CO 80921
-
-
- {==== Reference Section ======================================================}
-
- The interface section of the OOBPLUS unit is provided below.
-
- {-----------------------------------------------------------------------------}
-
- {The following define is used to specify status updates at more frequent
- intervals than normal. This makes the status display more informative and
- causes the "Time to go" field to just about tick like a clock on downloads,
- but it can have a negative effect on thruput at higher bps rates and can
- cause the CPS field to "jitter" somewhat, especially on uploads.}
-
- {$DEFINE ShowRates}
-
-
- {The following define enables support of online GIF decoding. If you are not
- going to use GIF support, un-defining this can both save about 400 bytes of
- code space and allow you to use the unit even if you don't have TurboPower's
- Object Professional or Turbo Professional libraries. The provided example
- program TERMBP.PAS does require Object Professional to compile.}
-
- {$DEFINE SupportGIF}
-
-
- {$IFNDEF UseOpro}
- {$IFDEF SupportGIF}
- !!! The options selected are incompatible with this unit !!!
- {$ENDIF}
- {$ENDIF}
-
- interface
-
- uses
- DOS,
- {$IFDEF UseOpro}
- OpCrt,
- {$ELSE}
- {$IFDEF UseTpro}
- TpCrt,
- {$ELSE}
- Crt,
- {$ENDIF}
- {$ENDIF}
- ApMisc,
- ApTimer,
- ApPort,
- ApUart,
- OOCom,
- OOAbsPcl;
-
- const
- UnitVers = '1.2f';
- UnitDate = '24-Apr-91';
-
- {consts needed here for status, continued from ApMisc}
- ecResync = 9980;
- ecWaitACK = 9981;
- ecDropout = 9982;
- ecHostCan = 9983;
- ecFileIO = 9984;
- ecTryResume = 9985;
- ecHostResume= 9986;
- ecResumeOK = 9987;
- ecResumeBad = 9988;
- ecOverwrite = 9989;
- ecUnPacket = 9990;
-
- BP_Timeout_Max = 30; {max allowed timeout per-char}
- BP_Error_Max = 10; {max sequential errors}
- BP_Buffer_Max = 1032; {largest data block available}
- BP_Abort_Max = 3; {number of abort requests req'd to trigger Override}
- BP_SendAhead_Max = 2; {max number of packets we can send ahead}
-
- {minimum <ESC><'I'> (and GIF support interrogation) response strings}
- {$IFDEF SupportGIF}
-
- ESCI_Response : String[80] = '#IB1,SSxx,GF,PB,DT';
-
- {see the GIF87a or 89a spec for explanation of these codes}
- GIFReplyEGA = '#87a;1;0,320,200,4,0;0,640,200,2,2;0,640,350,4,2';
- GIFReplyCGA = '#87a;1;0,320,200,2,0;0,640,200,1,0';
- GIFReplyHGC = '#87a;1;0,720,350,1,0';
- GIFReply : String[60] = GIFReplyEGA;
-
- {$ELSE}
-
- ESCI_Response : String[80] = '#IB1,SSxx,PB,DT';
-
- {$ENDIF}
-
-
- type
- {used by GetResumeProc for resume request handling}
- ResumeResultType = (xfrResume, xfrOverwrite, xfrRename, xfrAbort);
-
- BufferType = Array[0..BP_Buffer_Max] of Byte; {a buffer of data}
- SABuffType = {windowing buffer:}
- record
- Seq : Integer; {this sequence number}
- Num : Integer; {this packet's data size}
- Buf : BufferType; {this packet's data}
- end;
- SPackets = Array[0..BP_SendAhead_Max] of SABuffType;
-
- QuoteArray = Array[0..7] of Byte; {for quoting params sets}
-
- const
- DQFull : {all chars in ranges $00..$1F and $80..$9F}
- QuoteArray = ($FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF);
- DQDefault : {ETX ENQ DLE XON XOFF NAK}
- QuoteArray = ($14, $00, $D4, $00, $00, $00, $00, $00);
- DQExtend : {same as DQDefault plus XON & XOFF w/ high bit set}
- QuoteArray = ($14, $00, $D4, $00, $00, $00, $50, $00);
- DQClassic : {Classic B set, all chars in range $00..$1F}
- QuoteArray = ($FF, $FF, $FF, $FF, $00, $00, $00, $00);
-
- type
- ParamsRecord = {xfer params record:}
- record
- WinSend, {send window size}
- WinRecv, {recv window size}
- BlkSize, {block size (* 128)}
- ChkType : Byte; {check type, chksum or CRC}
- QuoteSet : QuoteArray; {chars to quote}
- DROpt, {DL Recovery option}
- UROpt, {UL Recovery option}
- FIOpt : Byte; {File Info option}
- end;
-
- {protocol direction options}
- DirectionType = (Upload, Download);
-
- BPProtocolPtr = ^BPProtocol;
- GetResumeProc = function(BPP : BPProtocolPtr) : ResumeResultType;
- ChkAbortProc = function : Boolean;
-
- BPProtocol = {abstract BPlus object:}
- object(AbstractProtocol)
- Ch : Integer; {curr char sent/recd}
- Quoted : Boolean; {true if last ch recd was quoted}
- QuoteTable: Array[0..255] of Byte; {our active quoting table}
- Checksum : Word; {may hold CRC}
- Direction : DirectionType; {upload or download}
- DefResume : ResumeResultType; {default resume handling}
- GetResume : GetResumeProc; {determine how to handle resume}
- ChkAbort : ChkAbortProc; {see if user wants an abort}
-
- HisParams : ParamsRecord; {host's parameters}
- OurParams : ParamsRecord; {our parameters}
-
- AbortCount: Integer; {# of abort requests so far}
- ResumeFlag: Boolean; {true if resuming an aborted dl}
- ResumeOK : Boolean; {true if resume was successful}
- Aborting : Boolean; {true if processing abort}
- FatalAbort: Boolean; {true if OverrideAbort}
- ShowStatus: Boolean; {False only for GIF}
- PacketRecd: Boolean; {true if packet recd in SendPacket}
- BPlus : Boolean; {true if in full B+ mode}
- ClassicB : Boolean; {true for "original" B proto}
- UseSQuote : Boolean; {true if using special quote set}
- SQuoteSet : QuoteArray; {user's specified quote set}
-
- RSize : Integer; {size of last recd buffer}
- BuffeRSize: Integer; {current allowed recv size}
- RBuffer : BufferType; {receive buffer}
- SBuffer : SPackets; {sending buffers}
- SeqNum : Integer; {current sequence number}
- Next2ACK : Integer; {packet pending ACK}
- Next2Fill : Integer; {packet to load for send}
- SAMax : Integer; {highest current sendahead cnt}
- SAWaiting : Integer; {# of packets outstanding ACKs}
- SAErrors : Integer; {keep track of SendAhead errors}
-
- R_Raw : LongInt; {vars for status display}
- R_Packets : LongInt;
- S_Raw : LongInt;
- S_Packets : LongInt;
- {$IFDEF ShowRates}
- R_Counter : LongInt;
- S_Counter : LongInt;
- {$ENDIF}
-
- constructor Init(AP : AbstractPortPtr);
- destructor Done; virtual;
-
- {...public methods called by terminal handlers}
- procedure bpHandleENQ;
- {-handle an <ENQ> from host}
- procedure bpHandleESCI;
- {-handle <ESC><'I'> (VT52 terminal capabilities inquiry) from host}
- function bpDLESeen : Boolean; virtual;
- {-called when <DLE> seen from host, starts protocol}
-
- {...other publics}
- procedure bpSetResumeProc(RP : GetResumeProc);
- {-set our ResumeProc for this instance}
- procedure bpSetChkAbortProc(CAP : ChkAbortProc);
- {-set our ChkAbortProc for this instance}
- procedure bpSendACK;
- {-acknowledge receipt of a complete packet}
-
- {...private methods}
- procedure UpdateStatus(W : Word);
- procedure UpdateQuoteTable(QS : QuoteArray);
- procedure QuoteThis(Value : Integer);
- procedure apResetProtocol; virtual;
- procedure apUpdateBlockCheck(CurByte : Byte); virtual;
- function CheckAbort : Boolean;
- procedure SendByte(C : Char);
- procedure SendQuotedByte(I : Integer);
- procedure SendNAK;
- procedure SendENQ;
- function IncSequence(Value : Integer) : Integer;
- function ReadByte : Boolean;
- function ReadQuotedByte : Boolean;
- procedure SendFailure(Reason : String);
- function ReadPacket(LeadInSeen, FromSend : Boolean) : Boolean;
- procedure SendData(BNum : Integer);
- function IncSA(Value : Integer) : Integer;
- function ReSync : Integer;
- function GetACK : Boolean;
- function SAFlush : Boolean;
- function SendPacket(Size : Integer) : Boolean;
- function SendTransport : Boolean;
- procedure ProcessTransportParams(SendXPortInfo : Boolean);
- procedure bpInitVars;
- end;
-
- BPProtoFTPPtr = ^BPProtoFTP;
- BPProtoFTP =
- object(BPProtocol)
- constructor Init(AP : AbstractPortPtr;
- DefaultResume : ResumeResultType);
- destructor Done; virtual;
-
- {...public methods}
- function bpDLESeen : Boolean; virtual;
-
- {...virtual methods}
- procedure apPrepareReading; virtual;
- procedure apFinishReading; virtual;
- procedure apFinishWriting; virtual;
- procedure apPrepareWriting; virtual;
-
- {...private methods}
- procedure SendFile;
- procedure RecvFile;
- end;
-
- {$IFDEF SupportGIF}
- BPProtoGIFPtr = ^BPProtoGIF;
- BPProtoGIF =
- object(BPProtocol)
- constructor Init(AP : AbstractPortPtr);
- destructor Done; virtual;
-
- {...Public methods}
- function bpDLESeen : Boolean; virtual;
- function bpGetGIFDataBlock(var P;
- var PSize : Word;
- var IsLast : Boolean) : Boolean;
- end;
- {$ENDIF}
-
- function bpStatusStr(Code : Word) : String;
- procedure NoUserStatus(AP : AbstractProtocolPtr; First, Last : Boolean);
-
-
-
- {===== Procedure/Function/Method Reference ===================================}
-
- This section provides details on the public and virtual methods of the
- various BPlus protocol objects.
-
- {----- BPProtocol object -----------------------------------------------------}
-
- constructor Init(AP : AbstractPortPtr);
- Purpose:
- Initialize BPlus protocol instance, including all shared vars from
- AbstractProtocol and those BPProtocol vars that are instance-dependent.
- Like other protocol objects derived from AbstractProtocol, if the constructor
- fails the reason code is returned in the AsyncStatus global.
-
- Example:
- {...}
- Var
- OurBPlus : BPProtocol;
- {...}
- if NOT OurBPlus.Init(OurPortPtr) then
- WriteLn('Error ',AsyncStatus,' initializing BPlus protocol object!');
- {...}
-
-
-
-
- destructor Done; virtual;
- Purpose:
- Dispose of BPProtocol instance when processing is complete.
-
-
-
-
- procedure bpHandleENQ;
- Purpose:
- Perform protocol-dependent processing when a <ENQ> char (ASCII $05) is
- received at the serial port. This method initializes some internal vars
- and sends the proper response back to the CIS host.
-
- Example:
- {...}
- case RecdChar of
- #5:
- OurBPlus.bpHandleENQ;
- else
- Write(RecdChar);
- {...}
-
- See also:
- bpHandleESCI, bpDLESeen
-
-
-
-
- procedure bpHandleESCI;
- Purpose:
- Handle responding to <ESC><'I'> inquiry from CIS host. See the detailed
- description in the protocol spec document for more information on the
- codes that are used to build the response string.
-
- Example:
- {...}
- if (LastRecdChar = #27) and (RecdChar = 'I') then
- OurBPlus.bpHandleESCI;
- {...}
-
- See also:
- bpHandleENQ, bpDLESeen
-
-
-
-
- function bpDLESeen : Boolean; virtual;
- Purpose:
- Called when a <DLE> char (ASCII $10) is received from the CIS host. This
- function calls the main protocol processing loop. It returns True if
- protocol processing completed successfully, or False if a error occurs
- during protocol handshaking or if the protocol session is aborted for any
- reason. Note that in the BBProtocol object this is only an abstract method.
-
- Example:
- {...}
- if (RecdChar = cDLE) then
- if OurBPlus.bpDLESeen then ;
- {...}
- WRONG! In the BPProtocol base object, bpDLESeen is an ABSTRACT method that
- will generate a runtime error (211) if called directly.
-
- See also:
- bpHandleENQ, bpHandleESCI
-
-
-
-
-
- procedure bpSetResumeProc(RP : GetResumeProc);
- Purpose:
- Assign a function to the BPProtocol object's GetResume proc pointer to tell
- the protocol which type of handling should be used for resuming an aborted
- download. When a download is started and the protocol determines that a
- file of the same name as the file being downloaded already exists, it can
- proceed in one of several ways: it can abort in order not to risk
- overwriting the existing file, it can overwrite the existing file
- regardless, it can rename the new file being downloaded so as not to
- conflict, or it can attempt a resume of a previous download. No one choice
- is appropriate for all occasions, so this hook is provided for an outside
- function to tell the protocol how to proceed. The function must be
- compiled using the FAR model and cannot be nested within another procedure
- or function. It takes the following form:
-
- function GetResumeFunc(BPP : BPProtocolPtr) : ResumeResultType;
-
- Typically this function prompts the user what to do and returns his/her
- choice. See the definition of the ResumeResultType above.
-
- Example:
- {...}
- OurBPlus.Init(OurPortPtr);
- OurBPlus.bpSetResumeProc(GetResumeFunc);
- {...}
-
- See also:
- bpSetChkAbortProc, and the type declaration of ResumeResultType above.
-
-
-
-
-
- procedure bpSetChkAbortProc(CAP : ChkAbortProc);
- Purpose:
- Assign a function to determine if the user wishes to abort the protocol
- session. Typically this will be set to point to a function that returns
- True of the user has requested an abort (by pressing a key, clicking the
- mouse on a hotspot, etc.) or False otherwise. Like bpSetResumeProc, the
- function passed to this procedure must be compiled under the FAR model and
- not be nested within any other procedure or function. The function takes
- the form:
-
- function ChkAbortFunc : Boolean;
-
- Example:
- {...}
- OurBPlus.Init(OurPortPtr);
- OurBPlus.bpSetChkAbortProc(ChkAbortFunc);
- {...}
-
- See also:
- bpSetResumeProc
-
-
-
- {----- BPProtoFTP object -----------------------------------------------------}
-
- constructor Init(AP : AbstractPortPtr; DefaultResume : ResumeResultType);
- Purpose:
- Initialize BPProtoFTP object. The DefaultResume parameter provides the
- default handling type for resume attempts in case no GetResumeProc has
- been assigned, so totally automated systems such as "CIS navigators" can
- continue processing without user intervention.
-
- Example:
- {...}
- var OurBPFTP : BPProtoFTP;
- {...}
- OurBPFTP.Init(OurPortPtr,xfrOverWrite);
- {...}
-
- See also:
- AbstractProtocol.InitCustom, BPProtocol.Init
-
-
-
-
- destructor Done; virtual;
- Purpose:
- Dispose of BPProtoFTP instance when processing is complete.
-
-
-
-
- procedure apPrepareReading; virtual;
- Purpose:
- Prepare for transmitting data via the protocol (usually opens the file to
- be uploaded).
-
- See also:
- The other AbstractProtocol child objects' apPrepareReading methods.
-
-
-
-
- procedure apFinishReading; virtual;
- Purpose:
- Perform any nessessary cleanup after the upload is finished (usually closes
- the file uploaded).
-
- See also:
- The other AbstractProtocol child objects' apFinishReading methods.
-
-
-
-
-
- procedure apPrepareWriting; virtual;
- Purpose:
- Prepare for receiving data via the protocol (usually opens the file to
- be downloaded). In this instance the method also checks if a resume
- attempt is needed.
-
- See also:
- The other AbstractProtocol child objects' apPrepareWriting methods.
-
-
-
-
-
- procedure apFinishWriting; virtual;
- Purpose:
- Perform any nessessary cleanup after the download is finished (usually
- closes the received file).
-
- See also:
- The other AbstractProtocol child objects' apFinishWriting methods.
-
-
-
-
-
- function bpDLESeen : Boolean; virtual;
- Purpose:
- Called when a <DLE> char (ASCII $10) is received from the CIS host. This
- function calls the main protocol processing loop. It returns True if
- protocol processing completed successfully, or False if a error occurs
- during protocol handshaking or if the protocol session is aborted for any
- reason. In this BPProtoFTP instance, bpDLESeen either receives the "+"
- packet and initializes the nessessary internal variables, or receives the
- initial "TD" packet, verifies that all provided parameters are correct, and
- sends or receives the file named in the "TD" packet.
-
- Example:
- {...}
- if (RecdChar = cDLE) then
- if OurBPFTP.bpDLESeen then ;
- {...}
-
- See also:
- BPProtocol.bpDLESeen
-
-
- {----- BPProtoGIF object -----------------------------------------------------}
-
- constructor Init(AP : AbstractPortPtr);
- Purpose:
- Initialize BPProtoGIF object.
-
- Example:
- {...}
- var OurBPGIF : BPProtoGIF;
- {...}
- OurBPGIF.Init(OurPortPtr);
- {...}
-
- See also:
- AbstractProtocol.InitCustom, BPProtocol.Init
-
-
-
-
- destructor Done; virtual;
- Purpose:
- Dispose of BPProtoGIF instance when processing is complete.
-
-
-
-
- function bpDLESeen : Boolean; virtual;
- Purpose:
- Called when a <DLE> char (ASCII $10) is received from the CIS host. This
- function calls the main protocol processing loop. It returns True if
- protocol processing completed successfully, or False if a error occurs
- during protocol handshaking or if the protocol session is aborted for any
- reason. In this BPProtoGIF instance, bpDLESeen receives the "+" packet and
- initializes the nessessary internal variables; all other protocol
- processing is handled by the bpGetGIFDataBlock and bpSendACK methods.
-
- Example:
- {...}
- if (RecdChar = cDLE) then
- if OurBPFTP.bpDLESeen then ;
- {...}
-
- See also:
- BPProtocol.bpDLESeen, BPProtoFTP.bpDLESeen
-
-
-
-
- function bpGetGIFDataBlock(var P;
- var PSize : Word;
- var IsLast : Boolean) : Boolean;
- Purpose:
- Return a block data from the protocol handler for decoding. P is a var
- parameter denoting a buffer at least large enough to hold one full packet's
- worth of data. On exit, PSize holds the number of bytes placed in P, and
- the IsLast parameter is set True if the packet received was a "TC"
- termination packet or False otherwise.
-
- The function returns False if the protocol terminates (a Failure packet is
- received or too many consecutive protocol errors occur), otherwise it
- returns True. Defective packets are automatically NAKed within the
- protocol, but _your_ code is responsible for sending the ACK for a good
- packet (see bpSendACK above).
-
- Example:
- {...}
- var DecodeBuffer : Array[1..1024] of Byte;
- DecodeSize : Word;
- IsLastPacket : Boolean;
- {...}
- if NOT bpGetGIFDataBlock(DecodeBuffer,DecodeSize,IsLastPacket) then
- {handle error}
- else
- {decode/display image data now in DecodeBuffer}
-
- See also:
- The example code in the OFLGIF.PAS file included in the package.
-
-
- (* EOF *)
-