Annotation of 43BSDReno/contrib/isode-beta/doc/manual/tsap.tex, revision 1.1

1.1     ! root        1: % run this through LaTeX with the appropriate wrapper
        !             2: 
        !             3: \chapter      {Transport Services}\label{libtsap}
        !             4: At the heart of this distribution is the \man libtsap(3n) library.
        !             5: This library contains a set of routines which implement the
        !             6: transport services access point (TSAP).
        !             7: 
        !             8: As with most models of OSI services,
        !             9: the underlying assumption is one of a symmetric, asynchronous environment.
        !            10: That is,
        !            11: although peers exist at a given layer, one does not necessarily view a peer as
        !            12: either a client or a server.
        !            13: Further,
        !            14: the service provider may generate events for the service user without the
        !            15: latter entity triggering the actions which led to the event.
        !            16: For example,
        !            17: in a synchronous environment,
        !            18: an indication that data has arrived usually occurs only when the service user
        !            19: asks the service provider to read data;
        !            20: in an asynchronous environment,
        !            21: the service provider may interrupt the service user at any time to announce
        !            22: the arrival of data.
        !            23: 
        !            24: The \verb"tsap" module in this release initially uses a client/server
        !            25: paradigm to start communications.
        !            26: Once the connection is established,
        !            27: a symmetric view is taken.
        !            28: In addition,
        !            29: initially the interface is synchronous;
        !            30: however once the connection is established,
        !            31: an asynchronous interface may be selected.
        !            32: 
        !            33: All of the routines in the \man libtsap(3n) library are integer-valued.
        !            34: They return the manifest constant \verb"OK" on success,
        !            35: or \verb"NOTOK" otherwise.
        !            36: 
        !            37: \section      {Addresses}\label{tsap:addresses}
        !            38: Addresses at the transport service access point are represented by the
        !            39: \verb"TSAPaddr" structure.
        !            40: \begin{quote}\index{TSAPaddr}\small\begin{verbatim}
        !            41: struct TSAPaddr {
        !            42: #define NTADDR  4
        !            43:     struct NSAPaddr ta_addrs[NTADDR];
        !            44:     int    ta_naddr;
        !            45: 
        !            46: #define TSSIZE  64
        !            47:     int    ta_selectlen;
        !            48:     char   ta_selector[TSSIZE];
        !            49: };
        !            50: #define NULLTA  ((struct TSAPaddr *) 0)
        !            51: \end{verbatim}\end{quote}
        !            52: This structure contains two elements:
        !            53: \begin{describe}
        !            54: \item[\verb"ta\_addrs"/\verb"ta\_nadr":] a list of network addresses,
        !            55: as described in the Section~\ref{nsap:addresses} on
        !            56: page~\pageref{nsap:addresses};
        !            57: 
        !            58: \item[\verb"ta\_selector"/\verb"ta\_selectlen":] the transport selector,
        !            59: as described in the \man isoservices(5) database in Chapter~\ref{isoservices},
        !            60: for the service provider \verb"tsap".
        !            61: \end{describe}
        !            62: 
        !            63: In Figure~\ref{getSSprovider},
        !            64: an example of how one constructs the TSAP address for the session provider on
        !            65: host \verb"RemoteHost" is presented.
        !            66: The routine \verb"is2taddr" takes a host and service,
        !            67: and then consults the \man isoentities(5) file described in
        !            68: Chapter~\ref{isoentities} of \volone/ to construct a transport
        !            69: address.
        !            70: \begin{quote}\index{is2taddr}\small\begin{verbatim}
        !            71: struct TSAPaddr *is2taddr (host, service, is)
        !            72: char   *host,
        !            73:        *service;
        !            74: struct isoservent *is;
        !            75: \end{verbatim}\end{quote}
        !            76: \tagrind[tp]{grind6-1}{Constructing the TSAP address for the Session provider}%
        !            77:        {getSSprovider}
        !            78: 
        !            79: \subsection    {Calling Address}
        !            80: Certain users of the transport service
        !            81: might need to know the name of the local host when they initiate a connection.
        !            82: The routine \verb"TLocalHostName" has been provided for this reason.
        !            83: \begin{quote}\index{TLocalHostName}\small\begin{verbatim}
        !            84: char   *TLocalHostName ()
        !            85: \end{verbatim}\end{quote}
        !            86: 
        !            87: \subsection    {Address Encodings}
        !            88: It may be useful to encode a transport address for viewing.
        !            89: Although a consensus for a standard way of doing this has not yet been
        !            90: reached,
        !            91: the routines \verb"taddr2str" and \verb"str2taddr" may be used in the interim.
        !            92: \begin{quote}\index{taddr2str}\small\begin{verbatim}
        !            93: char   *taddr2str (ta)
        !            94: struct TSAPaddr *ta;
        !            95: \end{verbatim}\end{quote}
        !            96: The parameter to this procedure is:
        !            97: \begin{describe}
        !            98: \item[\verb"ta":] the transport address.
        !            99: \end{describe}
        !           100: If \verb"taddr2str" fails,
        !           101: it returns the manifest constant \verb"NULLCP".
        !           102: 
        !           103: The routine \verb"str2taddr" takes an ascii string encoding and
        !           104: returns a
        !           105: transport address.
        !           106: \begin{quote}\index{str2taddr}\small\begin{verbatim}
        !           107: struct TSAPaddr *str2taddr (str)
        !           108: char   *str;
        !           109: \end{verbatim}\end{quote}
        !           110: The parameter to this procedure is:
        !           111: \begin{describe}
        !           112: \item[\verb"str":] the ascii string.
        !           113: \end{describe}
        !           114: If \verb"str2taddr" fails,
        !           115: it returns the manifest constant \verb"NULLTA".
        !           116: 
        !           117: Once a connection has been established,
        !           118: the routine \verb"TGetAddresses" may be called to retrieve to the associated
        !           119: addresses.
        !           120: (Normally this information is presented to the application during connection
        !           121: establishment.)
        !           122: \begin{quote}\index{TGetAddresses}\small\begin{verbatim}
        !           123: struct TSAPaddr *TGetAddresses (sd, initiating,
        !           124:         responding, td)
        !           125: int     sd;
        !           126: struct TSAPaddr *initiating,
        !           127:                 *responding;
        !           128: struct TSAPdisconnect *td;
        !           129: \end{verbatim}\end{quote}
        !           130: The parameters to this procedure are:
        !           131: \begin{describe}
        !           132: \item[\verb"sd":] the transport-descriptor;
        !           133: 
        !           134: \item[\verb"initiating":] the TSAP address of the initiator (to be filled-in);
        !           135: 
        !           136: \item[\verb"responding":] the TSAP address of the responder (to be filled-in);
        !           137: and,
        !           138: 
        !           139: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           140: updated only if the call fails.
        !           141: \end{describe}
        !           142: If the call is successful,
        !           143: the \verb"initiating" and \verb"responding" parameters will be updated
        !           144: accordingly.
        !           145: Otherwise,
        !           146: the parameter \verb"td" contains the reason for the failure.
        !           147: 
        !           148: \section      {Connection Establishment}
        !           149: Until the connection has been fully established,
        !           150: the implementation distinguishes between clients and servers,
        !           151: which are more properly referred to as {\em initiators\/} and
        !           152: {\em responders}, to use the OSI terminology.
        !           153: 
        !           154: \subsection    {Connection Negotiation}
        !           155: From the user's perspective,
        !           156: there are two parameters which are negotiated by the transport providers
        !           157: during connection establishment:
        !           158: {\em expedited data transfer},
        !           159: and the {\em maximum size\/} of transport service data units.
        !           160: 
        !           161: \subsubsection {Expedited Data}
        !           162: If the transfer of expedited data is negotiated,
        !           163: then small amounts of data may be sent out-of-band once the connection has
        !           164: been established.
        !           165: The size of the largest discrete unit to be sent is \verb"TX_SIZE"
        !           166: (which is non-negotiable).
        !           167: This parameter is negotiated downward;
        !           168: that is, both the initiator and responder must agree to the use of expedited
        !           169: data.
        !           170: 
        !           171: \subsubsection {Maximum TSDU Size}
        !           172: The transport provider will accept arbitrarily large transport service data
        !           173: units (TSDUs) and transparently fragment and re-assemble them during transit.
        !           174: Hence, the actual TSDU is of unlimited size.
        !           175: However, for efficiency reasons,
        !           176: it may be desirable for the user to send TSDUs which are no larger than a
        !           177: certain threshold.
        !           178: When a connection has been established,
        !           179: the service providers inform the initiator and responder as to what this
        !           180: threshold is.
        !           181: 
        !           182: \[\fbox{\begin{tabular}{lp{0.8\textwidth}}\label{TSDU:atomic}
        !           183: \bf NOTE:&     In the current implementation,
        !           184:                TSDUs which are no larger than the maximum atomic TSDU size
        !           185:                are handled very efficiently.
        !           186:                For optimal performance,
        !           187:                users of the transport service should strive to avoid sending
        !           188:                TSDUs which are larger than this threshold.
        !           189: \end{tabular}}\]
        !           190: 
        !           191: \subsection    {Server Initialization}
        !           192: The \man tsapd(8c) daemon,
        !           193: upon accepting a connection from an initiating host,
        !           194: consults the ISO services database to determine which program
        !           195: on the system implements the desired TSAP entity.
        !           196: For efficiency reasons,
        !           197: the \pgm{tsapd} program contains the bootstrap for several providers 
        !           198: (e.g., session).
        !           199: 
        !           200: Once the program has been ascertained,
        !           201: the daemon runs the program with any arguments listed in the database.
        !           202: In addition, it appends some {\em magic arguments\/} to the argument vector.
        !           203: Hence, the very first action performed by the responder is to re-capture the
        !           204: TSAP state contained in these magic arguments.
        !           205: This is done by calling the routine \verb"TInit",
        !           206: which on a successful return,
        !           207: is equivalent to a {\sf T-CONNECT.INDICATION\/} event from the transport
        !           208: service provider.
        !           209: \begin{quote}\index{TInit}\small\begin{verbatim}
        !           210: int     TInit (vecp, vec, ts, td)
        !           211: int     vecp;
        !           212: char  **vec;
        !           213: struct TSAPstart *ts;
        !           214: struct TSAPdisconnect *td;
        !           215: \end{verbatim}\end{quote}
        !           216: The parameters to this procedure are:
        !           217: \begin{describe}
        !           218: \item[\verb"vecp":] the length of the argument vector;
        !           219: 
        !           220: \item[\verb"vec":] the argument vector;
        !           221: 
        !           222: \item[\verb"ts":] a pointer to a \verb"TSAPstart" structure, which is updated
        !           223: only if the call succeeds;
        !           224: and,
        !           225: 
        !           226: \item[\verb"td":] a pointer to a  \verb"TSAPdisconnect" structure, which is
        !           227: updated only if the call fails.
        !           228: \end{describe}
        !           229: If \verb"TInit" is successful,
        !           230: it returns information in the \verb"ts" parameter,
        !           231: which is a pointer to a \verb"TSAPstart" structure.
        !           232: \begin{quote}\index{TSAPstart}\small\begin{verbatim}
        !           233: struct TSAPstart {
        !           234:     int     ts_sd;
        !           235: 
        !           236:     struct TSAPaddr ts_calling;
        !           237:     struct TSAPaddr ts_called;
        !           238: 
        !           239:     int     ts_expedited;
        !           240: 
        !           241:     int     ts_tsdusize;
        !           242: 
        !           243:     struct QOStype ts_qos;
        !           244: 
        !           245: #define TS_SIZE         32
        !           246:     int     ts_cc;
        !           247:     char    ts_data[TS_SIZE];
        !           248: };
        !           249: \end{verbatim}\end{quote}
        !           250: The elements of this structure are:
        !           251: \begin{describe}\label{TSAPstart}
        !           252: \item[\verb"ts\_sd":] the transport-descriptor to be used to reference this
        !           253: connection;
        !           254: 
        !           255: \item[\verb"ts\_calling":] the address of peer initiating the connection;
        !           256: 
        !           257: \item[\verb"ts\_called":] the address of the peer being asked to respond;
        !           258: 
        !           259: \item[\verb"ts\_expedited":]   whether initiator requests the use of expedited
        !           260:        data;
        !           261: 
        !           262: \item[\verb"ts\_tsdusize":]    the largest atomic TSDU size that can be used
        !           263: on the connection (see the note on page~\pageref{TSDU:atomic});
        !           264: 
        !           265: \item[\verb"ts\_qos":] the quality of service on the connection
        !           266: (see Section~\ref{tsap:qos});
        !           267: and,
        !           268: 
        !           269: \item[\verb"ts\_data"/\verb"ts\_cc":] any initial data
        !           270: (and the length of that data).
        !           271: \end{describe}
        !           272: 
        !           273: If the call to \verb"TInit" is not successful,
        !           274: then the user is informed that a {\sf T-DISCONNECT.INDICATION\/} event has
        !           275: occurred,
        !           276: and the relevant information is returned in a \verb"TSAPdisconnect" structure.
        !           277: \begin{quote}\index{TSAPdisconnect}\small\begin{verbatim}
        !           278: struct TSAPdisconnect {
        !           279:     int     td_reason;
        !           280: 
        !           281: #define TD_SIZE         64
        !           282:     int     td_cc;
        !           283:     char    td_data[TD_SIZE];
        !           284: };
        !           285: \end{verbatim}\end{quote}
        !           286: The elements of this structure are:\label{TSAPdisconnect}
        !           287: \begin{describe}
        !           288: \item[\verb"td\_reason":] reason for disconnect
        !           289: (codes are listed in Table~\ref{TSAPreasons});
        !           290: and,
        !           291: 
        !           292: \item[\verb"td\_data"/\verb"td\_cc":] any disconnect data
        !           293: (and the length of that data) from the peer.
        !           294: \end{describe}
        !           295: \tagtable[tp]{6-1}{TSAP Failure Codes}{TSAPreasons}
        !           296: 
        !           297: After examining the information returned by \verb"TInit" on a successful call
        !           298: (and possibly after examining the argument vector),
        !           299: the responder should either accept or reject the connection.
        !           300: If accepting, the \verb"TConnResponse" routine is called
        !           301: (which corresponds to the {\sf T-CONNECT.RESPONSE\/} action).
        !           302: \begin{quote}\index{TConnResponse}\small\begin{verbatim}
        !           303: int     TConnResponse (sd, responding, expedited, data, cc,
        !           304:                        qos, td)
        !           305: int     sd;
        !           306: struct TSAPaddr *responding;
        !           307: int     expedited,
        !           308:         cc;
        !           309: char   *data;
        !           310: struct QOStype *qos;
        !           311: struct TSAPdisconnect *td;
        !           312: \end{verbatim}\end{quote}
        !           313: The parameters to this procedure are:
        !           314: \begin{describe}
        !           315: \item[\verb"sd":] the transport-descriptor;
        !           316: 
        !           317: \item[\verb"responding":] the TSAP address of the responder
        !           318: (defaulting to the called address, if not present);
        !           319: 
        !           320: \item[\verb"expedited":] whether expedited data is to be permitted
        !           321: (this value must be \verb"0" unless the {\sf T-CONNECT.INDICATION\/} event
        !           322: indicated a willingness on the part of the initiator to support expedited
        !           323: data transfer);
        !           324: 
        !           325: \item[\verb"data"/\verb"cc":] any initial data
        !           326: (and the length of that data,
        !           327: which may not exceed \verb"TC_SIZE" octets);
        !           328: 
        !           329: \item[\verb"qos":] the quality of service on the connection
        !           330: (see Section~\ref{tsap:qos});
        !           331: and,
        !           332: 
        !           333: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           334: updated only if the call fails.
        !           335: \end{describe}
        !           336: If the call to \verb"TConnResponse" is successful,
        !           337: then connection establishment has completed
        !           338: and the users of the transport service now operate as symmetric peers.
        !           339: Otherwise, if the call fails and the reason is not an interface error
        !           340: (see Table~\ref{TSAPreasons} on page~\pageref{TSAPreasons}),
        !           341: then the connection is closed.
        !           342: 
        !           343: If instead, the responder wishes to reject the connection,
        !           344: it should fire the {\sf T-DISCONNECT.REQUEST\/} action by calling the
        !           345: \verb"TDiscRequest" routine.
        !           346: \begin{quote}\index{TDiscRequest}\small\begin{verbatim}
        !           347: int     TDiscRequest (sd, data, cc, td)
        !           348: int     sd;
        !           349: char   *data;
        !           350: int     cc;
        !           351: struct TSAPdisconnect  *td;
        !           352: \end{verbatim}\end{quote}
        !           353: The parameters to this procedure are:
        !           354: \begin{describe}\label{TDiscRequest}
        !           355: \item[\verb"sd":] the transport-descriptor;
        !           356: 
        !           357: \item[\verb"data"/\verb"cc":] any disconnect data
        !           358: (and the length of that data, which may not exceed \verb"TD_SIZE" octets);
        !           359: and,
        !           360: 
        !           361: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           362: updated only if the call fails.
        !           363: \end{describe}
        !           364: After a return from this call, the responder may exit.
        !           365: 
        !           366: \subsection    {Client Initialization}
        !           367: A program wishing to connect to another user of transport services calls the
        !           368: \verb"TConnRequest" routine,
        !           369: which corresponds to the {\sf T-CONNECT.REQUEST\/} action.
        !           370: \begin{quote}\index{TConnRequest}\small\begin{verbatim}
        !           371: int     TConnRequest (calling, called, expedited, data, cc,
        !           372:                 qos, tc, td)
        !           373: struct TSAPaddr *calling,
        !           374:                 *called;
        !           375: int     expedited,
        !           376:         cc;
        !           377: char   *data;
        !           378: struct QOStype *qos;
        !           379: struct TSAPconnect *tc;
        !           380: struct TSAPdisconnect  *td;
        !           381: \end{verbatim}\end{quote}
        !           382: The parameters to this procedure are:
        !           383: \begin{describe}
        !           384: \item[\verb"calling":] the TSAP address of the initiator;
        !           385: (need not be present);
        !           386: 
        !           387: \item[\verb"called":] the TSAP address of the responder;
        !           388: 
        !           389: \item[\verb"expedited":] whether expedited data is to be permitted;
        !           390: 
        !           391: \item[\verb"data"/\verb"cc":] any initial data
        !           392: (and the length of that data, which may not exceed \verb"TS_SIZE" octets);
        !           393: 
        !           394: \item[\verb"qos":] the quality of service on the connection
        !           395: (see Section~\ref{tsap:qos});
        !           396: 
        !           397: \item[\verb"tc":] a pointer to a \verb"TSAPconnect" structure, which is
        !           398: updated only if the call succeeds;
        !           399: and,
        !           400: 
        !           401: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           402: updated only if the call fails.
        !           403: \end{describe}
        !           404: If the call to \verb"TConnRequest" is successful
        !           405: (a successful return corresponds to a {\sf T-CONNECT.CONFIRMATION} event),
        !           406: then information is returned in the \verb"tc" parameter,
        !           407: which is a pointer to a \verb"TSAPconnect" structure.
        !           408: \begin{quote}\index{TSAPconnect}\small\begin{verbatim}
        !           409: struct TSAPconnect {
        !           410:     int     tc_sd;
        !           411: 
        !           412:     struct TSAPaddr tc_responding;
        !           413: 
        !           414:     int     tc_expedited;
        !           415: 
        !           416:     int     tc_tsdusize;
        !           417: 
        !           418:     struct QOStype tc_qos;
        !           419: 
        !           420: #define TC_SIZE         32
        !           421:     int     tc_cc;
        !           422:     char    tc_data[TC_SIZE];
        !           423: };
        !           424: \end{verbatim}\end{quote}
        !           425: The elements of this structure are:
        !           426: \begin{describe}
        !           427: \item[\verb"tc\_sd":] the transport-descriptor to be used to reference this
        !           428: connection;
        !           429: 
        !           430: \item[\verb"tc\_responding":]  the responding peer's address
        !           431: (which is the same as the \verb"called" address given as a parameter to
        !           432: \verb"TConnRequest");
        !           433: 
        !           434: \item[\verb"tc\_expedited":]   whether expedited data will be supported;
        !           435: 
        !           436: \item[\verb"tc\_tsdusize":]    the largest atomic TSDU size that can be used
        !           437: on the connection (see the note on page~\pageref{TSDU:atomic});
        !           438: 
        !           439: \item[\verb"tc\_qos":] the quality of service on the connection
        !           440: (see Section~\ref{tsap:qos});
        !           441: and,
        !           442: 
        !           443: \item[\verb"tc\_data"/\verb"tc\_cc":] any initial data
        !           444: (and the length of that data).
        !           445: \end{describe}
        !           446: If the call to \verb"TConnRequest" is successful,
        !           447: then connection establishment has completed
        !           448: and the users of the transport service now operate as symmetric peers.
        !           449: Otherwise, if the call fails then the connection is not established,
        !           450: and the \verb"TSAPdisconnect" structure has been updated.
        !           451: 
        !           452: \subsubsection {Asynchronous Connections}\label{tsap:async}
        !           453: Normally \verb"TConnRequest" returns only after a connection has succeeded or
        !           454: failed.
        !           455: This is termed a {\em synchronous\/} connection initiation.
        !           456: If the user desires, an {\em asynchronous\/} connection may be initiated.
        !           457: The routine \verb"TConnRequest" is really a macro which calls the routine
        !           458: \verb"TAsynConnRequest" with an argument indicating that a connection should
        !           459: be attempted synchronously.
        !           460: \begin{quote}\index{TAsynConnRequest}\small\begin{verbatim}
        !           461: int     TAsynConnRequest (calling, called, expedited,
        !           462:                 data, cc, qos, tc, td, async)
        !           463: struct TSAPaddr *calling,
        !           464:                 *called;
        !           465: int     expedited,
        !           466:         cc,
        !           467:         async;
        !           468: char   *data;
        !           469: struct QOStype *qos;
        !           470: struct TSAPconnect *tc;
        !           471: struct TSAPdisconnect  *td;
        !           472: \end{verbatim}\end{quote}
        !           473: The additional parameter to this procedure is:
        !           474: \begin{describe}
        !           475: \item[\verb"async":] whether the connection should be initiated asynchronously.
        !           476: \end{describe}
        !           477: If the \verb"async" parameter is non-zero,
        !           478: then \verb"TAsynConnRequest" returns one of four values:
        !           479: \verb"NOTOK", which indicates that the connection request failed;
        !           480: \verb"DONE", which indicates that the connection request succeeded;
        !           481: or, either of \verb"CONNECTING_1" or \verb"CONNECTING_2", which indicates that
        !           482: the connection request is still in
        !           483: progress.
        !           484: In the first two cases,
        !           485: the usual procedures for handling return values from \verb"TConnRequest" are
        !           486: employed
        !           487: (i.e., a \verb"NOTOK" return from \verb"TAsynConnRequest" is equivalent to a
        !           488: \verb"NOTOK" return from \verb"TConnRequest", and,
        !           489: a \verb"DONE" return from \verb"TAsynConnRequest" is equivalent to a
        !           490: \verb"OK" return from \verb"TConnRequest").
        !           491: In the final case, when either \verb"CONNECTING_1" or
        !           492: \verb"CONNECTING_2" is returned,
        !           493: only the \verb"tc_sd" element of the \verb"tc" parameter has been updated;
        !           494: it reflects the transport-descriptor to be used to reference this connection.
        !           495: Note that the \verb"data" parameter is still being referenced by
        !           496: \man libtsap(3n) and should not be tampered with until the connection attempt
        !           497: has been completed.
        !           498: 
        !           499: To determine when the connection attempt has been completed,
        !           500: the routine \verb"xselect" (consult Section~\ref{acs:select} of \volone/)
        !           501: should be used after calling \verb"TSelectMask".
        !           502: In order to determine if the connection attempt was successful,
        !           503: the routine \verb"TAsynRetryRequest" is called:
        !           504: \begin{quote}\index{TAsynRetryRequest}\small\begin{verbatim}
        !           505: int     TAsynRetryRequest (sd, tc, td)
        !           506: int     sd;
        !           507: struct TSAPconnect *tc;
        !           508: struct TSAPdisconnect  *td;
        !           509: \end{verbatim}\end{quote}
        !           510: The parameters to this procedure are:
        !           511: \begin{describe}
        !           512: \item[\verb"sd":] the transport-descriptor;
        !           513: 
        !           514: \item[\verb"tc":] a pointer to a \verb"TSAPconnect" structure, which is
        !           515: updated only if the call succeeds;
        !           516: and,
        !           517: 
        !           518: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           519: updated only if the call fails.
        !           520: \end{describe}
        !           521: Again, one of four values are returned:
        !           522: \verb"NOTOK", which indicates that the connection request failed;
        !           523: \verb"DONE", which indicates that the connection request succeeded;
        !           524: or, either of \verb"CONNECTING_1" or \verb"CONNECTING_2" which indicates that
        !           525: the connection request is still in progress.
        !           526: 
        !           527: In order to make efficient use of the asychronous connection facility,
        !           528: it is necessary to understand a bit of its underlying mechanisms.
        !           529: From a temporal perspective,
        !           530: connection establishment consists of two parts:
        !           531: \begin{enumerate}
        !           532: \item  establishing a reliable end-to-end connection;
        !           533:        and,
        !           534: 
        !           535: \item  exchanging connection establishment information.
        !           536: \end{enumerate}
        !           537: In some cases,
        !           538: the underlying transport mechanisms accomplish both simultaneously
        !           539: (when the end-to-end connection is built,
        !           540: connection establishment information is also exchanged).
        !           541: 
        !           542: Thus, in order to to perform asynchronous connections effectively,
        !           543: use of \verb"TAsynConnRequest" and \verb"TAsynRetry" should reflect this
        !           544: two-step process:
        !           545: \begin{enumerate}
        !           546: \item  Call \verb"TAsynConnRequest" with the \verb"async" parameter taking the
        !           547:        value~1.
        !           548:        If the return value was either \verb"NOTOK"
        !           549:        (the connection was not established),
        !           550:        or \verb"DONE" (the connection was established),
        !           551:        then terminate this algorithm.
        !           552: 
        !           553:        Otherwise, a return value of \verb"CONNECTING_1" or
        !           554:        \verb"CONNECTING_2" indicates that connection
        !           555:        establishment process has begun. Remember this value.
        !           556: 
        !           557: \item  At some point in the future,
        !           558:        call \verb"TSelectMask" to get an argument for \verb"xselect".
        !           559:        Then call \verb"xselect" checking to see if writing is
        !           560:        permitted.  Then call \verb"xselect" checking for writing if
        !           561:        the remembered value was \verb"CONNECTING_1" and for reading
        !           562:        if it was \verb"CONNECTING_2".  If either call returns
        !           563:        \verb"NOTOK", then a catastrophic error has occurred.
        !           564: 
        !           565:        Repeat this step as often as necessary until \verb"xselect" says that
        !           566:        reading or writing as required is permitted.
        !           567: 
        !           568: \item  Call \verb"TAsynRetry".
        !           569:        If the return value was either \verb"NOTOK" (the connection
        !           570:        was not established), or \verb"DONE" (the connection was
        !           571:        established), then terminate this algorithm.
        !           572: 
        !           573:        Otherwise, a return value of \verb"CONNECTING_1" or
        !           574:        \verb"CONNECTING_2" indicates that connection establishment is
        !           575:        {\em still\/} in progress. Remember this value and go back to
        !           576:        the previous step.
        !           577: 
        !           578: \end{enumerate}
        !           579: Although this seems complicated,
        !           580: implementation of these rules is actually straight-forward.
        !           581: In most cases,
        !           582: your code will do some work unrelated to the connection
        !           583: 
        !           584: Note that this procedure is equally applicable to the higher-layers
        !           585: (session, presentation, and association control) which also provide
        !           586: asynchronous connection facilities.
        !           587: For example,
        !           588: at the application layer,
        !           589: the routines \verb"AcAsynAssocRequest" and \verb"AcAsynRetryRequest" would be
        !           590: used.
        !           591: 
        !           592: \section      {Data Transfer}
        !           593: Once the connection has been established,
        !           594: a transport-descriptor is used to reference the connection.
        !           595: This is usually the first parameter given to any of the remaining routines in
        !           596: the \man libtsap(3n) library.
        !           597: Further,
        !           598: the last parameter is usually a pointer to a \verb"TSAPdisconnect" structure
        !           599: (as described on page~\pageref{TSAPdisconnect}).
        !           600: If a call to one of these routines fails,
        !           601: then the structure is updated.
        !           602: Otherwise, if the value of the \verb"td_reason" element is associated with a
        !           603: fatal error, then the connection is closed.
        !           604: That is, a {\sf T-DISCONNECT.INDICATION\/} event has occurred.
        !           605: The \verb"DR_FATAL" macro can be used to determine this.
        !           606: \begin{quote}\index{DR\_FATAL}\small\begin{verbatim}
        !           607: int     DR_FATAL (r)
        !           608: int     r;
        !           609: \end{verbatim}\end{quote}
        !           610: For protocol purists,
        !           611: the \verb"DR_OFFICIAL" macro can be used to determine if the error is an
        !           612: ``official'' error as defined by the specification,
        !           613: or an ``unofficial'' error used by the implementation.
        !           614: \begin{quote}\index{DR\_OFFICIAL}\small\begin{verbatim}
        !           615: int     DR_OFFICIAL (r)
        !           616: int     r;
        !           617: \end{verbatim}\end{quote}
        !           618: 
        !           619: \subsection    {Sending Data}
        !           620: There are three routines that may be used to send data.
        !           621: A call to the \verb"TDataRequest" routine is equivalent to a
        !           622: {\sf T-DATA.REQUEST\/} action on the part of the user.
        !           623: \begin{quote}\index{TDataRequest}\small\begin{verbatim}
        !           624: int     TDataRequest (sd, data, cc, td)
        !           625: int     sd;
        !           626: char   *data;
        !           627: int     cc;
        !           628: struct TSAPdisconnect  *td;
        !           629: \end{verbatim}\end{quote}
        !           630: The parameters to this procedure are:
        !           631: \begin{describe}
        !           632: \item[\verb"sd":] the transport-descriptor;
        !           633: 
        !           634: \item[\verb"data"/\verb"cc":] the data to be written
        !           635: (and the length of that data);
        !           636: and,
        !           637: 
        !           638: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           639: updated only if the call fails.
        !           640: \end{describe}
        !           641: If the call to \verb"TDataRequest" is successful,
        !           642: then the data has been queued for sending.
        !           643: Otherwise,
        !           644: the \verb"td" parameter indicates the reason for failure.
        !           645: 
        !           646: The \verb"TWriteRequest" routine is similar in nature to the
        !           647: \verb"TDataRequest" routine,
        !           648: but uses a different set of parameters.
        !           649: The invocation is:
        !           650: \begin{quote}\index{TWriteRequest}\small\begin{verbatim}
        !           651: int     TWriteRequest (sd, uv, td)
        !           652: int     sd;
        !           653: struct udvec *uv;
        !           654: struct TSAPdisconnect  *td;
        !           655: \end{verbatim}\end{quote}
        !           656: While the parameters are:
        !           657: \begin{describe}
        !           658: \item[\verb"sd":] the transport-descriptor;
        !           659: 
        !           660: \item[\verb"uv":] the data to be written,
        !           661: described in a null-terminated array of scatter/gather elements:
        !           662: \begin{quote}\index{udvec}\small\begin{verbatim}
        !           663: struct udvec {
        !           664:     caddr_t uv_base;
        !           665:     int     uv_len;
        !           666: };
        !           667: \end{verbatim}\end{quote}
        !           668:     The elements of the structure are:
        !           669:     \begin{describe}
        !           670:     \item[\verb"uv\_base":] the base of an element; and,
        !           671:     \item[\verb"uv\_cc":] the length of an element.
        !           672:     \end{describe}
        !           673: and,
        !           674: 
        !           675: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           676: updated only if the call fails.
        !           677: \end{describe}
        !           678: If the call to \verb"TWriteRequest" is successful,
        !           679: then the data has been queued for sending.
        !           680: Otherwise,
        !           681: the \verb"td" parameter indicates the reason for failure.
        !           682: 
        !           683: A call to the \verb"TExpdRequest" routine is equivalent to a
        !           684: {\sf T-EXPEDITED-DATA.REQUEST\/} action on the part of the user.
        !           685: \begin{quote}\index{TExpdRequest}\small\begin{verbatim}
        !           686: int     TExpdRequest (sd, data, cc, td)
        !           687: int     sd;
        !           688: char   *data;
        !           689: int     cc;
        !           690: struct TSAPdisconnect  *td;
        !           691: \end{verbatim}\end{quote}
        !           692: The parameters to this procedure are:
        !           693: \begin{describe}
        !           694: \item[\verb"sd":] the transport-descriptor;
        !           695: 
        !           696: \item[\verb"data"/\verb"cc":] the data to be written
        !           697: (and the length of that data, which may not exceed \verb"TX_SIZE" octets);
        !           698: and,
        !           699: 
        !           700: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           701: updated only if the call fails.
        !           702: \end{describe}
        !           703: If the call to \verb"TExpdRequest" is successful,
        !           704: then the data has been queued for expedited sending.
        !           705: Otherwise,
        !           706: the \verb"td" parameter indicates the reason for failure.
        !           707: 
        !           708: \subsection    {Receiving Data}
        !           709: There is one routine that is used to read data,
        !           710: \verb"TReadRequest",
        !           711: a call to which is equivalent to waiting for a {\sf T-DATA.INDICATION\/}
        !           712: or {\sf T-EXPEDITED-DA\-TA.IN\-DI\-CA\-TION} event.
        !           713: \begin{quote}\index{TReadRequest}\small\begin{verbatim}
        !           714: int     TReadRequest (sd, tx, secs, td)
        !           715: int     sd;
        !           716: struct TSAPdata *tx;
        !           717: int     secs;
        !           718: struct TSAPdisconnect  *td;
        !           719: \end{verbatim}\end{quote}
        !           720: The parameters to this procedure are:
        !           721: \begin{describe}
        !           722: \item[\verb"sd":] the transport-descriptor;
        !           723: 
        !           724: \item[\verb"tx":] a pointer to the \verb"TSAPdata" structure to be given
        !           725: the data;
        !           726: 
        !           727: \item[\verb"secs":] the maximum number of seconds to wait for the data
        !           728: (a value of \verb"NOTOK" indicates that the call should block indefinitely,
        !           729: whereas a value of \verb"OK" indicates that the call should not block at all,
        !           730: e.g., a polling action);
        !           731: and,
        !           732: 
        !           733: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           734: updated only if the call fails.
        !           735: \end{describe}
        !           736: If the call to \verb"TReadRequest" is successful,
        !           737: then the data has been read into the \verb"tx" parameter.
        !           738: \begin{quote}\index{TSAPdata}\small\begin{verbatim}
        !           739: struct TSAPdata {
        !           740:     int     tx_expedited;
        !           741: 
        !           742:     int     tx_cc;
        !           743:     struct qbuf tx_qbuf;
        !           744: };
        !           745: \end{verbatim}\end{quote}
        !           746: The elements of a \verb"TSAPdata" structure are:
        !           747: \begin{describe}
        !           748: \item[\verb"tx\_expedited":] whether the data was received via expedited
        !           749: transfer
        !           750: (i.e., an {\sf T-EXPEDITED-DATA.INDICATION\/} event occurred);
        !           751: 
        !           752: \item[\verb"tx\_cc":] the total number of octets that was read;
        !           753: and,
        !           754: 
        !           755: \item[\verb"tx\_qbuf":] the data that was read, in a buffer-queue form.
        !           756: \begin{quote}\index{qbuf}\small\begin{verbatim}
        !           757: struct qbuf {
        !           758:     struct qbuf *qb_forw;
        !           759:     struct qbuf *qb_back;
        !           760: 
        !           761:     int    qb_len;
        !           762:     char  *qb_data;
        !           763: 
        !           764:     char   qb_base[1];
        !           765: };
        !           766: \end{verbatim}\end{quote}
        !           767: The elements of a \verb"qbuf" structure are:\label{tsap:qbuf}
        !           768: \begin{describe}
        !           769: \item[\verb"qb\_forw"/\verb"qb\_back":] forward and back pointers;
        !           770: 
        !           771: \item[\verb"qb\_data"/\verb"qb\_len":] the user data
        !           772: (and the length of that data);
        !           773: and,
        !           774: 
        !           775: \item[\verb"qb\_base":] the extensible array containing the data.
        !           776: \end{describe}
        !           777: \end{describe}
        !           778: Note that the data contained in the structure was allocated via \man malloc(3),
        !           779: and should be released by using the \verb"TXFREE" macro when no longer
        !           780: referenced.
        !           781: The \verb"TXFREE" macro,
        !           782: which is used for this purpose,
        !           783: behaves as if it was defined as:\label{TXFREE}
        !           784: \begin{quote}\index{TXFREE}\small\begin{verbatim}
        !           785: void    TXFREE (tx)
        !           786: struct TSAPdata *tx;
        !           787: \end{verbatim}\end{quote}
        !           788: The macro frees only the data allocated by \verb"TDataRequest",
        !           789: and not the \verb"TSAPdata" structure itself.
        !           790: Further,
        !           791: \verb"TXFREE" should be called only if the call to the \verb"TDataRequest"
        !           792: routine returned \verb"OK".
        !           793: 
        !           794: \[\fbox{\begin{tabular}{lp{0.8\textwidth}}
        !           795: \bf NOTE:&     Because the \verb"TSAPdata" structure contains a
        !           796:                \verb"qbuf" element, care must be taken in initializing
        !           797:                and copying variables of this type.
        !           798:                The routines in \man libtsap(3n) library will correctly
        !           799:                initialize these structures when given as parameters.
        !           800:                But, users who otherwise manipulate \verb"TSAPdata"
        !           801:                structures should take great care.
        !           802: \end{tabular}}\]
        !           803: 
        !           804: Otherwise if the call to \verb"TReadRequest" did not succeed,
        !           805: the \verb"td" parameter indicates the reason for failure.
        !           806: 
        !           807: \subsection    {Asynchronous Event Handling}
        !           808: The data transfer events discussed thus far have been synchronous in nature.
        !           809: Some users of the transport service may wish an asynchronous interface.
        !           810: The \verb"TSetIndications" routine is used to change the service associated
        !           811: with a transport-descriptor to or from an asynchronous interface.
        !           812: \begin{quote}\index{TSetIndications}\small\begin{verbatim}
        !           813: int     TSetIndications (sd, data, disc, td)
        !           814: int     sd;
        !           815: int   (*data) (),
        !           816:       (*disc) ();
        !           817: struct TSAPdisconnect  *td;
        !           818: \end{verbatim}\end{quote}
        !           819: The parameters to this procedure are:
        !           820: \begin{describe}
        !           821: \item[\verb"sd":] the transport-descriptor;
        !           822: 
        !           823: \item[\verb"data":] the address of an event-handler routine to be invoked when
        !           824: data has arrived
        !           825: (either a {\sf T-DATA.INDICATION\/} or {\sf T-EXPEDITED-DATA.INDICATION} event
        !           826: occurs);
        !           827: 
        !           828: \item[\verb"disc":] the address of an event-handler routine to be invoked when
        !           829: the connection has been closed
        !           830: (a {\sf T-DISCONNECT.INDICATION\/} event occurs);
        !           831: and,
        !           832: 
        !           833: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           834: updated only if the call fails.
        !           835: \end{describe}
        !           836: If the service is to be made asynchronous,
        !           837: then both \verb"data" and \verb"disc" are specified;
        !           838: otherwise,
        !           839: if the service is to be made synchronous,
        !           840: neither should be specified (use the manifest constant \verb"NULLIFP").
        !           841: The most likely reason for the call failing is \verb"DR_WAITING",
        !           842: which indicates that an event is waiting for the user.
        !           843: 
        !           844: When an event-handler is invoked,
        !           845: future invocations of the event-hander are blocked until it returns.
        !           846: The return value of the event-handler is ignored.
        !           847: Further,
        !           848: during the execution of a synchronous call to the library,
        !           849: the event-handler will be blocked from being invoked.
        !           850: 
        !           851: When an event associated with data arriving occurs,
        !           852: the event-handler routine is invoked with two parameters:
        !           853: \begin{quote}\small\begin{verbatim}
        !           854: (*data) (sd, tx);
        !           855: int     sd;
        !           856: struct TSAPdata *tx;
        !           857: \end{verbatim}\end{quote}
        !           858: The parameters are:
        !           859: \begin{describe}
        !           860: \item[\verb"sd":] the transport-descriptor;
        !           861: and,
        !           862: 
        !           863: \item[\verb"tx":] a pointer to a \verb"TSAPdata" structure containing
        !           864: the data.
        !           865: \end{describe}
        !           866: Note that the data contained in the structure was allocated via \man malloc(3),
        !           867: and should be released with the \verb"TXFREE" macro
        !           868: (described on page~\pageref{TXFREE}) when no longer needed.
        !           869: 
        !           870: Similarly,
        !           871: when an event associated with connection release occurs,
        !           872: the event-handler is also invoked with two parameters:
        !           873: \begin{quote}\small\begin{verbatim}
        !           874: (*disc) (sd, td);
        !           875: int     sd;
        !           876: struct TSAPdisconnect *td;
        !           877: \end{verbatim}\end{quote}
        !           878: The parameters are
        !           879: \begin{describe}
        !           880: \item[\verb"sd":] the transport-descriptor;
        !           881: and,
        !           882: 
        !           883: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure
        !           884: indicating why the connection was released.
        !           885: \end{describe}
        !           886: Note that the transport-descriptor is no longer valid at the instant the
        !           887: call is made.
        !           888: 
        !           889: \[\fbox{\begin{tabular}{lp{0.8\textwidth}}
        !           890: \bf NOTE:&     The \man libtsap(3n) library uses the SIGEMT signal to provide
        !           891:                these services.
        !           892:                Programs using asynchronous transport-descriptors should NOT
        !           893:                use SIGEMT for other purposes.
        !           894: \end{tabular}}\]
        !           895: 
        !           896: \subsection    {Synchronous Event Multiplexing}
        !           897: A user of the transport service may wish to manage multiple
        !           898: transport-descriptors simultaneously;
        !           899: the routine \verb"TSelectMask" is provided for this purpose.
        !           900: This routine updates a file-descriptor mask and associated counter for use
        !           901: with \verb"xselect".
        !           902: \begin{quote}\index{TSelectMask}\small\begin{verbatim}
        !           903: int     TSelectMask (sd, mask, nfds, td)
        !           904: int     sd;
        !           905: fd_set *mask,
        !           906: int    *nfds;
        !           907: struct TSAPdisconnect  *td;
        !           908: \end{verbatim}\end{quote}
        !           909: The parameters to this procedure are:
        !           910: \begin{describe}
        !           911: \item[\verb"sd":] the transport-descriptor;
        !           912: 
        !           913: \item[\verb"mask":] a pointer to a file-descriptor mask meaningful to
        !           914: \verb"xselect";
        !           915: 
        !           916: \item[\verb"nfds":] a pointer to an integer-valued location meaningful to
        !           917: \verb"xselect";
        !           918: and,
        !           919: 
        !           920: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           921: updated only if the call fails.
        !           922: \end{describe}
        !           923: If the call is successful, then the \verb"mask" and \verb"nfds" parameters can
        !           924: be used as arguments to \verb"xselect".
        !           925: The most likely reason for the call failing is \verb"DR_WAITING",
        !           926: which indicates that an event is waiting for the user.
        !           927: 
        !           928: If \verb"xselect" indicates that the transport-descriptor is ready for reading,
        !           929: \verb"TReadRequest" should be called with the \verb"secs" parameter equal to
        !           930: \verb"OK".
        !           931: If the network activity does not constitute an entire event for the user,
        !           932: then \verb"TReadRequest" will return \verb"NOTOK" with error code
        !           933: \verb"DR_TIMER".
        !           934: 
        !           935: In addition,
        !           936: the routine \verb"TSelectOctets" is provided to return an estimate of how many
        !           937: octets might be returned by the next call to \verb"TReadRequest":
        !           938: \begin{quote}\index{TSelectOctets}\small\begin{verbatim}
        !           939: int     TSelectOctets (sd, nbytes, td)
        !           940: int     sd;
        !           941: long   *nbytes;
        !           942: struct TSAPdisconnect  *td;
        !           943: \end{verbatim}\end{quote}
        !           944: The parameters to this procedure are:
        !           945: \begin{describe}
        !           946: \item[\verb"sd":] the transport-descriptor;
        !           947: 
        !           948: \item[\verb"nbytes":] a pointer to a longword location that, on success, will
        !           949: be updated to contain the number of octets that might be returned;
        !           950: and,
        !           951: 
        !           952: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           953: updated only if the call fails.
        !           954: \end{describe}
        !           955: 
        !           956: \section      {Connection Release}
        !           957: The \verb"TDiscRequest" routine is used to release a connection.
        !           958: Note, that the TSAP makes no guarantee that any queued data will be received
        !           959: before the connection closes.
        !           960: \begin{quote}\index{TDiscRequest}\small\begin{verbatim}
        !           961: int     TDiscRequest (sd, data, cc, td)
        !           962: int     sd;
        !           963: char   *data;
        !           964: int     cc;
        !           965: struct TSAPdisconnect  *td;
        !           966: \end{verbatim}\end{quote}
        !           967: The parameters to the procedure are described on page~\pageref{TDiscRequest}.
        !           968: 
        !           969: \section      {State Saving and Restoration}
        !           970: Some users of the transport service,
        !           971: and in particular the session provider,
        !           972: require the ability to \man execve(2) another process image and have that
        !           973: process use the transport connection.
        !           974: Since the \man libtsap(3n) library is not kernel-resident,
        !           975: special provisions are necessary to support this behavior.
        !           976: 
        !           977: \subsection    {Saving the State}
        !           978: The routine \verb"TSaveState" is used to record the state of the TSAP for a
        !           979: given transport-descriptor.
        !           980: \begin{quote}\index{TSaveState}\small\begin{verbatim}
        !           981: int     TSaveState (sd, vec, td)
        !           982: int     sd;
        !           983: char  **vec;
        !           984: struct TSAPdisconnect  *td;
        !           985: \end{verbatim}\end{quote}
        !           986: The parameters to this procedure are:
        !           987: \begin{describe}
        !           988: \item[\verb"sd":] the transport-descriptor;
        !           989: 
        !           990: \item[\verb"vec":] a pointer to the first free slot in the argument vector for
        !           991: \man execve(2);
        !           992: and,
        !           993: 
        !           994: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !           995: updated only if the call fails.
        !           996: \end{describe}
        !           997: If the call succeeds,
        !           998: then an extra {\em magic argument\/} has been placed in the argument vector.
        !           999: The most likely reason for the call failing is \verb"DR_WAITING",
        !          1000: which indicates that an event is waiting for the user.
        !          1001: 
        !          1002: \[\fbox{\begin{tabular}{lp{0.8\textwidth}}
        !          1003: \bf NOTE:&     Once a successful call to \verb"TSaveState" is made on a
        !          1004:                transport descriptor, that descriptor may no longer be
        !          1005:                referenced until a corresponding call to \verb"TRestoreState"
        !          1006:                is successful.
        !          1007: \end{tabular}}\]
        !          1008: 
        !          1009: \subsection    {Restoring the State}
        !          1010: The routine \verb"TRestoreState" is used to re-initialize the state of the
        !          1011: TSAP.
        !          1012: \begin{quote}\index{TRestoreState}\small\begin{verbatim}
        !          1013: int     TRestoreState (buffer, ts, td)
        !          1014: char   *buffer;
        !          1015: struct TSAPstart  *ts;
        !          1016: struct TSAPdisconnect  *td;
        !          1017: \end{verbatim}\end{quote}
        !          1018: The parameters to this procedure are:
        !          1019: \begin{describe}
        !          1020: \item[\verb"buffer":] the {\em magic argument\/} constructed by
        !          1021: \verb"TSaveState";
        !          1022: 
        !          1023: \item[\verb"ts":] a pointer to a \verb"TSAPstart" structure, which is updated
        !          1024: only if the call succeeds;
        !          1025: and,
        !          1026: 
        !          1027: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure, which is
        !          1028: updated only if the call fails.
        !          1029: \end{describe}
        !          1030: If \verb"TRestoreState" is successful,
        !          1031: it returns information in a \verb"TSAPstart" structure,
        !          1032: as defined on page~\pageref{TSAPstart}.
        !          1033: There is one exception however:
        !          1034: in the current implementation the \verb"ts_cc" and
        !          1035: \verb"ts_data" elements are undefined on a successful return from
        !          1036: \verb"TRestoreState".
        !          1037: 
        !          1038: \section      {Cookie Parameters}
        !          1039: There are two {\em cookie\/} parameters:
        !          1040: network addresses and quality of service.
        !          1041: 
        !          1042: \subsection    {Network Addresses}\label{nsap:addresses}
        !          1043: Network addresses can vary greatly.
        !          1044: In this software distribution,
        !          1045: a ``unified'' format has been adopted in the \verb"NSAPaddr" structure:
        !          1046: \begin{quote}\index{NSAPaddr}\small\begin{verbatim}
        !          1047: struct NSAPaddr {
        !          1048:     long    na_stack;
        !          1049: #define NA_NSAP 0
        !          1050: #define NA_TCP  1
        !          1051: #define NA_X25  2
        !          1052: #define NA_BRG  3
        !          1053: 
        !          1054:     long    na_community;
        !          1055: 
        !          1056:     union {
        !          1057:         struct na_nsap {
        !          1058: #define NASIZE  64
        !          1059:             char    na_nsap_address[NASIZE];
        !          1060:             char    na_nsap_addrlen;
        !          1061:         }               un_na_nsap;
        !          1062: 
        !          1063:         struct na_tcp {
        !          1064: #define NSAP_DOMAINLEN  63
        !          1065:             char    na_tcp_domain[NSAP_DOMAINLEN + 1];
        !          1066:             u_short na_tcp_port;
        !          1067:             u_short na_tcp_tset;
        !          1068: #define NA_TSET_TCP    0x0001
        !          1069: #define NA_TSET_UDP    0x0002
        !          1070:         }               un_na_tcp;
        !          1071: 
        !          1072:         struct na_x25 {
        !          1073: #define NSAP_DTELEN     15
        !          1074:             char    na_x25_dte[NSAP_DTELEN + 1];
        !          1075:             char    na_x25_dtelen;
        !          1076: 
        !          1077: #define NPSIZE  4
        !          1078:             char    na_x25_pid[NPSIZE];
        !          1079:             char    na_x25_pidlen;
        !          1080: 
        !          1081: #define CUDFSIZE 16
        !          1082:             char    na_x25_cudf[CUDFSIZE];
        !          1083:             char    na_x25_cudflen;
        !          1084: 
        !          1085: #define FACSIZE 6
        !          1086:             char    na_x25_fac[FACSIZE];
        !          1087:             char    na_x25_faclen;
        !          1088:         }               un_na_x25;
        !          1089:     }               na_un;
        !          1090: 
        !          1091: #define na_address      na_un.un_na_nsap.na_nsap_address
        !          1092: #define na_addrlen      na_un.un_na_nsap.na_nsap_addrlen
        !          1093: 
        !          1094: #define na_domain       na_un.un_na_tcp.na_tcp_domain
        !          1095: #define na_port         na_un.un_na_tcp.na_tcp_port
        !          1096: 
        !          1097: #define na_dte          na_un.un_na_x25.na_x25_dte
        !          1098: #define na_dtelen       na_un.un_na_x25.na_x25_dtelen
        !          1099: #define na_pid          na_un.un_na_x25.na_x25_pid
        !          1100: #define na_pidlen       na_un.un_na_x25.na_x25_pidlen
        !          1101: #define na_cudf         na_un.un_na_x25.na_x25_cudf
        !          1102: #define na_cudflen      na_un.un_na_x25.na_x25_cudflen
        !          1103: #define na_fac          na_un.un_na_x25.na_x25_fac
        !          1104: #define na_faclen       na_un.un_na_x25.na_x25_faclen
        !          1105: };                                
        !          1106: #define NULLNA  ((struct NSAPaddr *) 0)
        !          1107: \end{verbatim}\end{quote}
        !          1108: As shown, this structure is really a discriminated union
        !          1109: (a structure with a tag element followed by a union).
        !          1110: Based on the value of the tag (\verb"na_stack"),
        !          1111: a different structure is selected.
        !          1112: 
        !          1113: For a native OSI CO-mode transport service,
        !          1114: the value of the tag is \verb"NA_NSAP",
        !          1115: and the following elements are meaningful:
        !          1116: \begin{describe}
        !          1117: \item[\verb"na\_address"/\verb"na\_addrlen":] the network address
        !          1118: (and its length), binary-valued.
        !          1119: \end{describe}
        !          1120: 
        !          1121: For emulation of the OSI transport service on top of the TCP,
        !          1122: the value of the tag is \verb"NA_TCP",
        !          1123: and the following elements are meaningful:
        !          1124: \begin{describe}
        !          1125: \item[\verb"na\_domain":] the null-terminated domain name
        !          1126: (e.g., ``gonzo.twg.com'') or dotted-quad (e.g., ``128.99.0.17'');
        !          1127: 
        !          1128: \item[\verb"na\_port":] the TCP-port number offering the service
        !          1129: (if zero, the service on port~102 is used);
        !          1130: and,
        !          1131: 
        !          1132: \item[\verb"na\_tset":] the set of IP-based transport services available at
        !          1133: the address
        !          1134: (if zero, the TCP service is used).
        !          1135: \end{describe}
        !          1136: 
        !          1137: For use of a single-subnet X.25,
        !          1138: the value of the tag is \verb"NA_X25",
        !          1139: and the following elements are meaningful:
        !          1140: \begin{describe}
        !          1141: \item[\verb"na\_dte"/\verb"na\_dtelen":] the X.121 address (and its length),
        !          1142: ascii-valued, possibly null-terminated;
        !          1143: 
        !          1144: \item[\verb"na\_pid"/\verb"na\_pidlen":] the protocol id (and its length),
        !          1145: binary-valued;
        !          1146: 
        !          1147: \item[\verb"na\_cudf"/\verb"na\_cudflen":] the call user data (and its length),
        !          1148: binary-valued;
        !          1149: and,
        !          1150: 
        !          1151: \item[\verb"na\_fac"/\verb"na\_faclen":] the negotiated facilities proposed
        !          1152: in the call request packet (and its length),
        !          1153: binary-valued.
        !          1154: \end{describe}
        !          1155: For use of a TP0-bridge between the TCP and X.25,
        !          1156: the value of the tag is \verb"NA_BRG",
        !          1157: and the elements above are meaningful.
        !          1158: 
        !          1159: If the value of the tag is not \verb"NA_NSAP",
        !          1160: it may be useful to normalize the address into a ``real'' OSI address.
        !          1161: The routine \verb"na2norm" is used:
        !          1162: \begin{quote}\index{na2norm}\begin{verbatim}
        !          1163: char   *na2norm (na)
        !          1164: struct NSAPaddr *na;
        !          1165: \end{verbatim}\end{quote}
        !          1166: The parameter to this procedure is:
        !          1167: \begin{describe}
        !          1168: \item[\verb"na"]: the network address to be normalized.
        !          1169: \end{describe}
        !          1170: A new network address is returned from a static area which contains the
        !          1171: normalized form.
        !          1172: 
        !          1173: The routine \verb"na2str" takes a network address and returns a
        !          1174: null-ter\-mi\-na\-ted ascii string suitable for viewing:
        !          1175: \begin{quote}\index{na2str}\begin{verbatim}
        !          1176: char   *na2str (na)
        !          1177: struct NSAPaddr *na;
        !          1178: \end{verbatim}\end{quote}
        !          1179: The parameter to this procedure is:
        !          1180: \begin{describe}
        !          1181: \item[\verb"na"]: the network address to be printed.
        !          1182: \end{describe}
        !          1183: 
        !          1184: The \verb"na_community" field is an internal number used to distinguish
        !          1185: between different OSI communities.
        !          1186: Consult Chapter~\ref{tswitch} starting on page~\pageref{tswitch} for further
        !          1187: details.
        !          1188: 
        !          1189: \subsection    {Quality of Service}\label{tsap:qos}
        !          1190: Currently, quality of service is largely uninterpreted by the software.
        !          1191: However,
        !          1192: the quality of service structure contains those parameters which are supported:
        !          1193: \begin{quote}\index{QOStype}\small\begin{verbatim}
        !          1194: struct QOStype {
        !          1195:                               /* transport QOS */
        !          1196:     int    qos_reliability;
        !          1197: #define HIGH_QUALITY   0
        !          1198: #define LOW_QUALITY    1
        !          1199: 
        !          1200:                               /* session QOS */
        !          1201:     int    qos_sversion;
        !          1202:     int    qos_extended;
        !          1203:     int    qos_maxtime;
        !          1204: };
        !          1205: #define NULLQOS ((struct QOStype *) 0)
        !          1206: \end{verbatim}\end{quote}
        !          1207: The elements of this structure are:
        !          1208: \begin{describe}
        !          1209: \item[\verb"qos\_reliability":] the ``reliability'' level of the connection,
        !          1210: either high- or low-quality;
        !          1211: 
        !          1212: \item[\verb"qos\_sversion":] the session version requested/negotiated on this
        !          1213: connection (only applicable above the transport layer, obviously),
        !          1214: if the manifest constant \verb"NOTOK" is used when initiating a connection,
        !          1215: this indicates that the highest possible version should be negotiated;
        !          1216: 
        !          1217: \item[\verb"qos\_extended":] the extended control parameter for the connection,
        !          1218: (if non-zero, extended control is used by the session layer);
        !          1219: and,
        !          1220: 
        !          1221: \item[\verb"qos\_maxtime":] after a transport connection is established,
        !          1222: the maximum number of seconds to wait for an acknowledgement from the
        !          1223: responding SPM
        !          1224: (any non-positive number indicates that no timelimit is desired).
        !          1225: \end{describe}
        !          1226: 
        !          1227: \section      {Listen Facility}\label{tsap:listen}
        !          1228: The \man libtsap(3n) library,
        !          1229: supports a facility which permits a process to {\em listen\/} for certain
        !          1230: connections.
        !          1231: This can be useful for implementing an application which requires that a
        !          1232: single server process handle multiple clients,
        !          1233: or for connection recovery.
        !          1234: These routines return the manifest constant \verb"NOTOK" on error,
        !          1235: and \verb"OK" on success,
        !          1236: they also update the \verb"td" parameter given to the routine.
        !          1237: This parameter is a pointer to a \verb"TSAPdisconnect" structure.
        !          1238: 
        !          1239: Although this facility is described in terms of the \man libtsap(3n) library,
        !          1240: it will function at any other higher-layer in the system
        !          1241: (e.g., the listen facility can be used for session or application-entities).
        !          1242: 
        !          1243: A program starts listening for an particular connection by calling the routine
        !          1244: \verb"TNetListen".
        !          1245: \begin{quote}\index{TNetListen}\small\begin{verbatim}
        !          1246: int     TNetListen (ta, td)
        !          1247: struct TSAPaddr *ta;
        !          1248: struct TSAPdisconnect *td;
        !          1249: \end{verbatim}\end{quote}
        !          1250: The parameters to this procedure are:
        !          1251: \begin{describe}
        !          1252: \item[\verb"ta":] the transport address (0 or more network addresses)
        !          1253: to listen on; and,
        !          1254: 
        !          1255: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure,
        !          1256: which is updated only if the call fails.
        !          1257: \end{describe}
        !          1258: If the call is successful,
        !          1259: then the program is now listening for incoming connections on that network
        !          1260: address.
        !          1261: Otherwise,
        !          1262: the \verb"td" parameter indicates the reason for failure.
        !          1263: 
        !          1264: A variant of \verb"TNetListen" is the \verb"TNetUnique" routine,
        !          1265: which starts the process listening on a set of unique network (sub)addresses.
        !          1266: \begin{quote}\index{TNetUnique}\small\begin{verbatim}
        !          1267: int     TNetUnique (ta, td)
        !          1268: struct TSAPaddr *ta;
        !          1269: struct TSAPdisconnect *td;
        !          1270: \end{verbatim}\end{quote}
        !          1271: The parameters to this procedure are:
        !          1272: \begin{describe}
        !          1273: \item[\verb"ta":] a transport address containing  one or more partially
        !          1274: filled-in network addresses; and,
        !          1275: 
        !          1276: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure,
        !          1277: which is updated only if the call fails.
        !          1278: \end{describe}
        !          1279: If the call is successful,
        !          1280: each network address in the \verb"ta" parameter is fully filled-in,
        !          1281: the program is now listening for incoming connections on the resulting
        !          1282: transport.
        !          1283: Otherwise,
        !          1284: the \verb"td" parameter indicates the reason for failure.
        !          1285: 
        !          1286: To check when a new connection is waiting,
        !          1287: or when existing connections have activity on them,
        !          1288: the routine \verb"TNetAccept" is used.\label{tsap:accept}
        !          1289: \begin{quote}\index{TNetAccept}\small\begin{verbatim}
        !          1290: int     TNetAccept (vecp, vec, nfds, rfds, wfds, efds, secs,
        !          1291:                 td)
        !          1292: int    *vecp,
        !          1293: char  **vec;
        !          1294: int     nfds;
        !          1295: fd_set *rfds,
        !          1296:        *wfds,
        !          1297:        *efds;
        !          1298: int     secs;
        !          1299: struct TSAPdisconnect *td;
        !          1300: \end{verbatim}\end{quote}
        !          1301: The parameters to this procedure are:
        !          1302: \begin{describe}
        !          1303: \item[\verb"vecp"/\verb"vec":] the initialization vector for the new
        !          1304: connection.
        !          1305: 
        !          1306: \item[\verb"nfds"/\verb"rfds"/\verb"wfds"/\verb"efds":] connection-descriptors
        !          1307: for use with \verb"xselect";
        !          1308: 
        !          1309: \item[\verb"secs":] the maximum number of seconds to wait for activity
        !          1310: (a value of \verb"NOTOK" indicates that the call should block indefinitely,
        !          1311: whereas a value of \verb"OK" indicates that the call should not block at all,
        !          1312: e.g., a polling action); and,
        !          1313: 
        !          1314: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure,
        !          1315: which is updated only if the call fails.
        !          1316: \end{describe}
        !          1317: If the call to \verb"TNetAccept" succeeds then the value of \verb"vecp"
        !          1318: should be checked.
        !          1319: If \verb"vecp" is greater than zero,
        !          1320: a new connection has been accepted,
        !          1321: and \verb"TInit" should be called,
        !          1322: presumably followed by \verb"TConnResponse".%
        !          1323: \footnote{Actually, any service addressable via a transport selector
        !          1324: can use this service,
        !          1325: e.g., if appropriate, a call to \verb"AcInit",
        !          1326: followed by a call to \verb"AcAssocResponse",
        !          1327: can be made.}
        !          1328: Regardless of the value of \verb"vecp",
        !          1329: the value of \verb"rfds" and \verb"wfds" should be checked to see which
        !          1330: connections have activity pending.
        !          1331: For these connections,
        !          1332: any reads should probably be done with a \verb"secs" argument indicating a
        !          1333: polling operation (i.e., a value of \verb"OK").
        !          1334: Otherwise,
        !          1335: if the call to \verb"TNetAccept" fails,
        !          1336: then the \verb"td" parameter indicates the reason for failure.
        !          1337: 
        !          1338: \[\fbox{\begin{tabular}{lp{0.8\textwidth}}
        !          1339: \bf NOTE:&     The \verb|TNetAccept| procedure when first called arranges to
        !          1340:                clean up dead child processes. If the program will run any
        !          1341:                sub-processes and check their exit status, the automatic
        !          1342:                collection of zombie process should be disabled, by first
        !          1343:                calling \verb|TNetAccept| with a timeout of \verb|OK| and then
        !          1344:                setting the child signal handler to it's default state. 
        !          1345: \end{tabular}}\]
        !          1346: 
        !          1347: The routine \verb"TNetAccept" is actually a macro which invokes a routine
        !          1348: called \verb"TNetAcceptAux":
        !          1349: \begin{quote}\index{TNetAcceptAux}\small\begin{verbatim}
        !          1350: int     TNetAcceptAux (vecp, vec, newfd, ta, nfds, rfds, wfds,
        !          1351:                 efds, secs, td)
        !          1352: int    *vecp,
        !          1353: char  **vec;
        !          1354: int     newfd;
        !          1355: struct TSAPaddr *ta;
        !          1356: int     nfds;
        !          1357: fd_set *rfds,
        !          1358:        *wfds,
        !          1359:        *efds;
        !          1360: int     secs;
        !          1361: struct TSAPdisconnect *td;
        !          1362: \end{verbatim}\end{quote}
        !          1363: The additional parameters to this procedure are:
        !          1364: \begin{describe}
        !          1365: \item[\verb"newfd":] a pointer to an integer which will be given the value of
        !          1366: the connection-descriptor associated with the new connection;
        !          1367: and,
        !          1368: 
        !          1369: \item[\verb"ta":] a pointer to a \verb"TSAPaddr" structure which will be given
        !          1370: the value of the transport address receiving the new connection
        !          1371: (the called or listening address).
        !          1372: \end{describe}
        !          1373: 
        !          1374: Prior to exiting,
        !          1375: the user should call \verb"TNetClose" to stop listening for connections.
        !          1376: \begin{quote}\index{TNetClose}\small\begin{verbatim}
        !          1377: int     TNetClose (ta, td)
        !          1378: struct TSAPaddr *ta;
        !          1379: struct TSAPdisconnect *td;
        !          1380: \end{verbatim}\end{quote}
        !          1381: The parameters to this procedure are:
        !          1382: \begin{describe}
        !          1383: \item[\verb"ta":] the transport address to stop listening on
        !          1384: (use the manifest constant \verb"NULLTA" to stop listening on all addresses);
        !          1385: and,
        !          1386: 
        !          1387: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure,
        !          1388: which is updated only if the call fails.
        !          1389: \end{describe}
        !          1390: If the call is successful,
        !          1391: then the program has stopped listening for incoming connections on that network
        !          1392: address.
        !          1393: Otherwise,
        !          1394: the \verb"td" parameter indicates the reason for failure.
        !          1395: 
        !          1396: \section      {Queued (non-blocking) Writes Facility}
        !          1397: All ``read'' operations in the ISODE are inherently non-blocking.
        !          1398: Historically, ``write'' operations have not required this capability.
        !          1399: However,
        !          1400: some applications (e.g., the QUIPU DSA) require non-blocking writes.
        !          1401: The routine \verb"TSetQueuesOK" is used to enable or disable this facility:
        !          1402: \begin{quote}\index{TSetQueuesOK}\small\begin{verbatim}
        !          1403: int     TSetQueuesOK (sd, onoff, td)
        !          1404: int     sd;
        !          1405: int     onoff;
        !          1406: struct TSAPdisconnect *td;
        !          1407: \end{verbatim}\end{quote}
        !          1408: The parameters to this procedure are:
        !          1409: \begin{describe}
        !          1410: \item[\verb"sd":] the transport-descriptor;
        !          1411: 
        !          1412: \item[\verb"onoff":] a flag indicating whether the facility is to be enabled
        !          1413: (non-zero value) or disabled (zero value) for the transport-descriptor;
        !          1414: and,
        !          1415: 
        !          1416: \item[\verb"td":] a pointer to a \verb"TSAPdisconnect" structure,
        !          1417: which is updated only if the call fails.
        !          1418: \end{describe}
        !          1419: If the call is not successful,
        !          1420: the \verb"td" parameter indicates the reason for failure.
        !          1421: Otherwise,
        !          1422: if the \verb"onoff" parameter has a non-zero value,
        !          1423: then any ``write'' operations which ultimately map to this
        !          1424: transport-descriptor will not block the process.
        !          1425: This is done by maintaining a queue of write operations and periodically
        !          1426: retrying them.
        !          1427: In order to schedule retries,
        !          1428: the routine \verb"TNetAccept" described earlier should be called frequently.
        !          1429: In addition,
        !          1430: if some failure occurs during the retry
        !          1431: (e.g., the transport connection is disconnected),
        !          1432: then \verb"TNetAccept" will mark that descriptor as being ready for reading.
        !          1433: When the program interrogates the descriptor,
        !          1434: the appropriate error code will be returned.
        !          1435: Note that in order for this action to occur,
        !          1436: any descriptor which has queued writes enabled must be included in the
        !          1437: \verb"rfs" parameter supplied when the \verb"TNetAccept" routine is called.
        !          1438: 
        !          1439: \section      {Error Conventions}
        !          1440: All of the routines in this library return the manifest constant \verb"NOTOK"
        !          1441: on error,
        !          1442: and also update the \verb"td" parameter given to the routine.
        !          1443: The \verb"td_reason" element of the \verb"TSAPdisconnect" structure can be
        !          1444: given as an parameter to the routine \verb"TErrString" which returns a
        !          1445: null-terminated diagnostic string.
        !          1446: \begin{quote}\index{TErrString}\small\begin{verbatim}
        !          1447: char   *TErrString (c)
        !          1448: int     c;
        !          1449: \end{verbatim}\end{quote}
        !          1450: 
        !          1451: \section      {Compiling and Loading}
        !          1452: Programs using the \man libtsap(3n) library should include
        !          1453: \verb"<isode/tsap.h>".
        !          1454: These programs should also be loaded with \verb"-ltsap" and,
        !          1455: for reasons explained momentarily,
        !          1456: \verb"-licompat".
        !          1457: 
        !          1458: \section      {An Example}
        !          1459: Let's consider how one might construct a loopback entity that resides on the
        !          1460: TSAP.
        !          1461: This entity will use a synchronous interface.
        !          1462: 
        !          1463: First, we must decide at what address the entity will reside.
        !          1464: For simplicity's sake,
        !          1465: we'll say that the location is \verb"tsap/echo",
        !          1466: as defined in the \man isoservices(5) database.
        !          1467: 
        !          1468: Next, we actually code the loopback entity.
        !          1469: There are two parts to the program: initialization and data transfer;
        !          1470: release will occur whenever data transfer fails.
        !          1471: In our example,
        !          1472: we assume that the routine \verb"error" results in the process being
        !          1473: terminated after printing a diagnostic.
        !          1474: 
        !          1475: In Figure~\ref{initTSloopback},
        !          1476: the initialization steps for the loopback entity,
        !          1477: including the outer {\em C\/} wrapper, is shown.
        !          1478: The entity does not examine any of its arguments,
        !          1479: but could do so after the call to \verb"TInit".
        !          1480: After examining the arguments,
        !          1481: it could decide to reject the connection attempt,
        !          1482: by using \verb"TDiscRequest".
        !          1483: Instead,
        !          1484: it uses \verb"TConnResponse" with the exact negotiated parameters with which
        !          1485: it was supplied.
        !          1486: Hence,
        !          1487: if the initiator wanted to use expedited data transfer,
        !          1488: the loopback entity responding to the connection would honor that.
        !          1489: 
        !          1490: In Figure~\ref{dataTSloopback} on page~\pageref{dataTSloopback},
        !          1491: the data transfer loop is realized.
        !          1492: The loopback entity awaits an event from the service provider,
        !          1493: which either indicates that data has arrived or that the connection has been
        !          1494: closed.
        !          1495: If a disconnection occurred
        !          1496: (a {\sf T-DISCONNECT.INDICATION\/} event is reported),
        !          1497: then the reason is checked.
        !          1498: If the event did not occur because the initiator performed a
        !          1499: {\sf T-DISCONNECT.REQUEST\/} indication,
        !          1500: then an error is signaled.
        !          1501: Otherwise, the inner-loop is terminated and the process will gracefully
        !          1502: terminate.
        !          1503: If instead data arrived,
        !          1504: it is echoed back to the initiator.
        !          1505: \clearpage
        !          1506: \tagrind[tp]{grind6-2}{Initializing the loopback entity}{initTSloopback}
        !          1507: \clearpage
        !          1508: \tagrind[tp]{grind6-3}{Data Transfer for the loopback entity}{dataTSloopback}
        !          1509: 
        !          1510: \section      {Compatibility Issues}
        !          1511: The \man libicompat(3) library is used as an aid for porting the software from
        !          1512: one system to another.
        !          1513: This library contains generic service routines,
        !          1514: which are in turn composed of the native facilities available on the target
        !          1515: host.
        !          1516: All of the higher layer \verb"#include" files automatically reference parts
        !          1517: of this library as appropriate.
        !          1518: Hence, when loading the the portions of the software independently,
        !          1519: the loader must be given the \verb"-licompat" flag.
        !          1520: 
        !          1521: The problem of this approach, of course, is that not all facilities can be
        !          1522: precisely emulated.
        !          1523: To misquote M.A.~Padlipsky\cite{Gateways.Heffalumps}:
        !          1524: \begin{quote}\em
        !          1525: Sometimes when you try to make an apple look like an orange you get back
        !          1526: something that smells like a lemon.
        !          1527: \end{quote}
        !          1528: 
        !          1529: \section      {For Further Reading}
        !          1530: The ISO specification for transport services is defined in
        !          1531: \cite{ISO.TP.Service}.
        !          1532: The corresponding CCITT recommendation is defined in \cite{CCITT.TP.Service}.
        !          1533: The document describing how these services can be implemented on top of the
        !          1534: TCP\cite{TCP} is \cite{TSAP.on.TCP}.
        !          1535: 
        !          1536: \section      {Changes Since the Last Release}\label{tsap:changes}
        !          1537: A brief summary of the major changes between v~\tsaprevrsn/ and
        !          1538: v~\tsapvrsn/ are now presented.
        !          1539: These are the user-visible changes only;
        !          1540: changes of a strictly internal nature are not discussed.
        !          1541: 
        !          1542: The \verb"na_type" and \verb"na_subnet" fields of the \verb"NSAPaddr"
        !          1543: structure are now called \verb"na_stack" and \verb"na_community" respectively.
        !          1544: For compatibility,
        !          1545: macros are provided.
        !          1546: These macros will be removed after this release.

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.