|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T a
Length: 56193 (0xdb81) Types: TextFile Names: »acsap.tex«
└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« └─⟦d3ac74d73⟧ └─⟦this⟧ »isode-5.0/doc/manual/acsap.tex«
% run this through LaTeX with the appropriate wrapper \f \chapter {Association Control}\label{libacsap} The \man libacsap(3n) library implements the Association Control Service (ACS). Logically, one views an application to consist of several {\em application service elements\/} (ASE's). Although these ASEs cooperate, each performs a different function for the application. The Association Control Service Element (ACSE) is concerned with the task of ``starting'' and ``stopping'' the network for the application. That is, an application uses the ACSE to establish a connection, termed an {\em association}, between two users. The association {\em binds\/} the two users, which are referred to as the {\em initiator\/} and the {\em responder}. This association, once established is used by other ASEs (e.g., the remote operations service element). Later, the ACSE is called upon to release the association, either gracefully (perhaps with some negotiation), or abruptly (with possible loss of information). Like most models of OSI services, the underlying assumption is one of an asynchronous environment: the service provider may generate events for the service user without the latter entity triggering the actions which led to the event. For example, in a synchronous environment, an indication that data has arrived usually occurs only when the service user asks the service provider to read data; in an asynchronous environment, the service provider may interrupt the service user at any time to announce the arrival of data. The \verb"acsap" module in this release presents a synchronous interface. However once the association is established, an asynchronous interface may be selected. The \verb"acsap" module itself is naive as to the interface being used: the particular application service element which is responsible for transferring data will manage the association once the ACSE has established it. All of the routines in the \man libacsap(3n) library are integer-valued. They return the manifest constant \verb"OK" on success, or \verb"NOTOK" otherwise. In some circumstances, failures are fatal and cause (or are caused by) the association being released. Section~\ref{acs:errors} describes how such failures may be distinguished. \f \section {An Important Note}\label{acs:note} In the current release there are several ways to establish an association. This is due to recent changes in the OSI application layer, and a desire to remain compatible with previous work. Users are strongly encouraged to use the new facilities described herein, as the older facilities will eventually be removed. Here are the new facilities available: \[\begin{tabular}{|l|l|l|} \hline \multicolumn{1}{|c|}{\bf Desired Service}& \multicolumn{1}{c|}{\bf Association Primitives}& \multicolumn{1}{c|}{\bf Section(s)}\\ \hline Remote Operations& {\sf A-ASSOCIATE}& \ref{acs:associations}\\ \ (complete discipline)& {\sf A-RELEASE}& \ref{ros:underlying}\\ \ \cite{ISO.ROS.Service,CCITT.ROS.Service}& {\sf A-ABORT}& \\[0.1in] \hline Remote Operations& {\sf RT-OPEN}& \ref{rts:associations}\\ \ (complete discipline& {\sf RT-CLOSE}& \ref{ros:underlying}\\ \ \ with reliable transfer)&& \\ \ \cite{ISO.ROS.Service,CCITT.ROS.Service}& & \\[0.1in] \hline Reliable Transfer& {\sf RT-OPEN}& \ref{rts:associations}\\ \ \cite{ISO.RTS.Service,CCITT.RTS.Service}& {\sf RT-CLOSE}& \\ \hline \end{tabular}\] \clearpage %%% yikes! Here are the old facilities available: \[\begin{tabular}{|l|l|l|} \hline \multicolumn{1}{|c|}{\bf Desired Service}& \multicolumn{1}{c|}{\bf Association Primitives}& \multicolumn{1}{c|}{\bf Section}\\ \hline Remote Operations& {\sf RO-BEGIN}& \ref{ros:old-style}\\ \ (basic discipline)& {\sf RO-END}& \\ \ \cite{ECMA.ROS}& & \\[0.1in] \hline Remote Operations& {\sf X.410 OPEN}& \ref{rts:old-style}\\ \ (advanced discipline& {\sf X.410 CLOSE}& \ref{ros:underlying}\\ \ \ with reliable transfer)&& \\ \ \cite{MHS.RTS}& & \\[0.1in] \hline Reliable Transfer& {\sf X.410 OPEN}& \ref{rts:old-style}\\ \ \cite{MHS.RTS}& {\sf X.410 CLOSE}& \\ \hline \end{tabular}\] In short, depending on whether a Reliable Transfer Service Element (RTSE) is desired, for the purposes of association control, all new applications should use either the library discussed below, or the reliable transfer routines discussed in Section~\ref{rts:associations} on page~\pageref{rts:associations}. \f \section {Associations}\label{acs:associations} There are three aspects of association management: {\em association establishment}, {\em association release}, and, {\em association abort}. Each of these are now described in turn. \subsection {Association Establishment} The \man libacsap(3n) library distinguishes between the user which started an association, the {\em initiator}, and the user which was subsequently bound to the association, the {\em responder}. We sometimes term these two entities the {\em client\/} and the {\em server}, respectively. \subsubsection {Addresses}\label{acs:addresses}\label{acs:aei} Addresses for the association control service entity consist of two parts: a presentation address (as discussed in Section~\ref{psap:addresses} on page~\pageref{psap:addresses} of \voltwo/), and application-entity information. Internally, the \verb"AEInfo" is used to represent this notion: \begin{quote}\index{AEInfo}\small\begin{verbatim} typedef struct AEInfo { PE aei_ap_title; PE aei_ae_qualifier; int aei_ap_id; int aei_ae_id; int aei_flags; #define AEI_NULL 0x00 #define AEI_AP_ID 0x01 #define AEI_AE_ID 0x02 } AEInfo, *AEI; #define NULLAEI ((AEI) 0) \end{verbatim}\end{quote} This structure contains several elements: \begin{describe} \item[\verb"aei\_ap\_title":] the application-process title; \item[\verb"aei\_ae\_qualifier":] the application-entity qualifier; \item[\verb"aei\_ap\_id":] the application-process invocation identifier; \item[\verb"aei\_ae\_id":] the application-entity invocation identifier; and, \item[\verb"aei\_flags":] flags, indicating which, if any, of the invocation-identifiers are present. \end{describe} The routing \verb"sprintaei" can be used to return a null-terminated string describing the application-entity. \begin{quote}\index{sprintaei}\small\begin{verbatim} char *sprintaei (aei) AEI aei; \end{verbatim}\end{quote} Finally, the routine \verb"oid2aei" converts object identifiers (discussed in Section~\ref{psap:oid} on page~\pageref{psap:oid}) and converts them to application-entity information. This is used by the stub-directory service: \begin{quote}\index{oid2aei}\small\begin{verbatim} AEI oid2aei (oid) OID oid; \end{verbatim}\end{quote} In Figure~\ref{getFTAMentity}, an example of how one constructs the address for the File Transfer, Access and Management (FTAM) service on host \verb"RemoteHost" is presented. The routine \verb"str2aei" takes a designator and a qualifier, combining them into a description of an application-entity. It then consults either the ``higher performance'' nameservice (as described in Section~\ref{acsap:ns}), or the stub-directory service (as described in Chapter~\ref{isoentities}). \begin{quote}\index{str2aei}\small\begin{verbatim} AEI str2aei (designator, qualifier) char *designator, *qualifier; \end{verbatim}\end{quote} The routine \verb"aei2addr" takes application-entity information, and returns the appropriate presentation address. \begin{quote}\index{aei2addr}\small\begin{verbatim} struct PSAPaddr *aei2addr (aei) AEI aei; \end{verbatim}\end{quote} \tagrind[tp]{grind2a-1}% {Constructing the address for the FTAM entity}{getFTAMentity} \subsubsection {Address Encodings}\label{addr:encodings} It may be useful to encode a presentation address for viewing. Although a consensus for a standard way of doing this has not yet been reached, the routines \verb"paddr2str" and \verb"str2paddr" may be used in the interim. These implement the encodings defined in \cite{String.Addresses}. The BNF syntax for this encoding is shown in Figure~\ref{str:format} on page~\pageref{str:format}. \begin{quote}\index{paddr2str}\small\begin{verbatim} char *paddr2str (pa, na) struct PSAPaddr *pa; struct NSAPaddr *na; \end{verbatim}\end{quote} The parameters to this procedure are: \begin{describe} \item[\verb"pa":] the presentation address; and, \item[\verb"na":] a network address to use instead of the network addresses in the \verb"pa" parameter (use the manifest constant \verb"NULLNA" otherwise). \end{describe} If \verb"paddr2str" fails, it returns the manifest constant \verb"NULLCP". The routine \verb"str2paddr" takes an ascii string encoding and returns a presentation address. \begin{quote}\index{str2paddr}\small\begin{verbatim} struct PSAPaddr *str2paddr (str) char *str; \end{verbatim}\end{quote} The parameter to this procedure is: \begin{describe} \item[\verb"str":] the ascii string. \end{describe} If \verb"str2paddr" fails, it returns the manifest constant \verb"NULLPA". \tagrind[tp]{grind2a-2f}{BNF Syntax for paddr2str/str2paddr}{str:format} \tagrind[tp]{grind2a-2g}{BNF Syntax for paddr2str/str2paddr (continued)}\empty \verb"paddr2str" is really a macro which calls the routine \verb"_paddr2str": \begin{quote}\index{\_paddr2str}\small\begin{verbatim} char *_paddr2str (pa, na, compact) struct PSAPaddr *pa; struct NSAPaddr *na; int compact; \end{verbatim}\end{quote} The parameters to this procedure are: \begin{describe} \item[\verb"pa":] the presentation address; \item[\verb"na":] a network address to use instead of the network addresses in the \verb"pa" parameter (use the manifest constant \verb"NULLNA" otherwise); and, \item[\verb"compact":] indicates the style of encoding. \end{describe} If \verb"compact" is greater than zero, then the encoding reflects a normalized network address. This is useful for passing to arbitrary processes in the network. If \verb"compact" is less than zero, then the encoding reflects the BNF in Figure~\ref{str:format}, without any macro substitutions. If \verb"compact" is equal to zero (which is what \verb"paddr2str" uses), then the encoding reflects the above BNF with macro substitutions. \subsubsection {Server Initialization} The \man tsapd(8c) daemon, upon accepting a connection from an initiating host, consults the ISO services database to determine which program on the local system implements the desired application context. Once the program has been ascertained, the daemon runs the program with any arguments listed in the database. In addition, it appends some {\em magic arguments\/} to the argument vector. Hence, the very first action performed by the responder is to re-capture the ACSE state contained in the magic arguments. This is done by calling the routine \verb"AcInit", which on a successful return, is equivalent to a {\sf A-ASSOCIATE.INDICATION\/} event from the association control service provider. \begin{quote}\index{AcInit}\small\begin{verbatim} int AcInit (vecp, vec, acs, aci) int vecp; char **vec; struct AcSAPstart *acs; struct AcSAPindication *aci; \end{verbatim}\end{quote} The parameters to this procedure are: \begin{describe} \item[\verb"vecp":] the length of the argument vector; \item[\verb"vec":] the argument vector; \item[\verb"acs":] a pointer to an \verb"AcSAPstart" structure, which is updated only if the call succeeds; and, \item[\verb"aci":] a pointer to an \verb"AcSAPindication" structure, which is updated only if the call fails. \end{describe} If \verb"AcInit" is successful, it returns information in the \verb"acs" parameter, which is a pointer to an \verb"AcSAPstart" structure. \begin{quote}\index{AcSAPstart}\small\begin{verbatim} struct AcSAPstart { int acs_sd; OID acs_context; AEInfo acs_callingtitle; AEInfo acs_calledtitle; struct PSAPstart acs_start; int acs_ninfo; PE acs_info[NACDATA]; }; \end{verbatim}\end{quote} The elements of this structure are:\label{AcSAPstart} \begin{describe} \item[\verb"acs\_sd":] the association-descriptor to be used to reference this association; \item[\verb"acs\_context":] the application context name; \item[\verb"acs\_callingtitle":] information on the calling application-entity (if any); \item[\verb"acs\_calledtitle":] information on the called application-entity (if any); \item[\verb"acs\_start":] an \verb"PSAPstart" structure (consult page~\pageref{PSAPstart} of \voltwo/); and, \item[\verb"acs\_info"/\verb"acs\_ninfo":] any initial data (and the length of that data). \end{describe} Note that the proposed contexts list in the \verb"acs_start" element will contain a context for the ACSE. The routine \verb"AcFindPCI" can be used to determine the PCI being used by the ACSE: \begin{quote}\index{AcFindPCI}\small\begin{verbatim} int AcFindPCI (sd, pci, aci) int sd; int *pci; struct AcSAPindication *aci; \end{verbatim}\end{quote} The parameters to this procedure are: \begin{describe} \item[\verb"sd":] the association-descriptor; \item[\verb"pci":] a pointer to an integer location, which is updated only if the call succeeds; and, \item[\verb"aci":] a pointer to an \verb"AcSAPindication" structure, which is updated only if the call fails. \end{describe} Further, note that the data contained in the structure was allocated via \man malloc(3), and should be released by using the \verb"ACSFREE" macro when no longer referenced. The \verb"ACSFREE" macro, behaves as if it was defined as:\label{ACSFREE} \begin{quote}\index{ACSFREE}\small\begin{verbatim} void ACSFREE (acs) struct AcSAPstart *acs; \end{verbatim}\end{quote} The macro frees only the data allocated by \verb"AcInit", and not the \verb"AcSAPstart" structure itself. Further, \verb"ACSFREE" should be called only if the call to the \verb"AcInit" routine returned \verb"OK". If the call to \verb"AcInit" is not successful, then a {\sf A-P-ABORT.INDICATION\/} event is simulated, and the relevant information is returned in an encoded \verb"AcSAPindication" structure.\label{AcSAPindication} \begin{quote}\index{AcSAPindication}\small\begin{verbatim} struct AcSAPindication { int aci_type; #define ACI_FINISH 0x00 #define ACI_ABORT 0x01 union { struct AcSAPfinish aci_un_finish; struct AcSAPabort aci_un_abort; } aci_un; #define aci_finish aci_un.aci_un_finish #define aci_abort aci_un.aci_un_abort }; \end{verbatim}\end{quote} As shown, this structure is really a discriminated union (a structure with a tag element followed by a union). Hence, on a failure return, one first coerces a pointer to the \verb"AcSAPabort" structure contained therein, and then consults the elements of that structure. \begin{quote}\index{AcSAPabort}\small\begin{verbatim} struct AcSAPabort { int aca_source; int aca_reason; int aca_ninfo; PE aca_info[NACDATA]; #define ACA_SIZE 512 int aca_cc; char aca_data[ACA_SIZE]; }; \end{verbatim}\end{quote} The elements of an \verb"AcSAPabort" structure are: \begin{describe} \item[\verb"aca\_source":] the source of the abort, one of: \[\begin{tabular}{|l|l|} \hline \multicolumn{1}{|c|}{\bf Value}& \multicolumn{1}{c|}{\bf Source}\\ \hline \tt ACA\_USER& service-user (peer)\\ \tt ACA\_PROVIDER& service-provider\\ \tt ACA\_LOCAL& local ACPM\\ \hline \end{tabular}\] \item[\verb"aca\_reason":] the reason for the provider-initiated abort (meaningful only if \verb"aca_source" is not \verb"ACA_REQUESTOR"), consult Table~\ref{AcSAPreasons}; \item[\verb"aca\_info"/\verb"aca\_ninfo":] any abort data (and the length of that data) from the peer (if \verb"aca_source" is \verb"ACA_USER"); and, \item[\verb"aca\_data"/\verb"aca\_cc":] a diagnostic string from the provider. \end{describe} \tagtable[tp]{2a-1}{AcSAP Failure Codes}{AcSAPreasons} Note that the data contained in the structure was allocated via \man malloc(3), and should be released by using the \verb"ACAFREE" macro when no longer referenced. The \verb"ACAFREE" macro, behaves as if it was defined as:\label{ACAFREE} \begin{quote}\index{ACAFREE}\small\begin{verbatim} void ACAFREE (aca) struct AcSAPabort *aca; \end{verbatim}\end{quote} The macro frees only the data contained in the structure, and not the \verb"AcSAPabort" structure itself. After examining the information returned by \verb"AcInit" on a successful call (and possibly after examining the argument vector), the responder should either accept or reject the association. For either response, the responder should use the \verb"AcAssocResponse" routine (which corresponds to the {\sf A-ASSOCIATE.RESPONSE\/} action). \begin{quote}\index{AcAssocResponse}\small\begin{verbatim} int AcAssocResponse (sd, status, reason, context, respondtitle, respondaddr, ctxlist, defctxresult, prequirements, srequirements, isn, settings, ref, data, ndata, aci) int sd; int status, reason; OID context; AEI respondtitle; struct PSAPaddr *respondaddr; int prequirements, srequirements, settings, ndata; long isn; struct PSAPctxlist *ctxlist; int defctxresult; struct SSAPref *ref; PE *data; struct AcSAPindication *aci; \end{verbatim}\end{quote} The parameters to this procedure are:\label{AcAssocResponse} \begin{describe} \item[\verb"sd":] the association-descriptor; \item[\verb"status":] the acceptance indicator (either \verb"ACS_ACCEPT" if the association is to be accepted, or one of the user-initiated rejection codes listed in Table~\ref{AcSAPreasons} on page~\pageref{AcSAPreasons}); \item[\verb"reason":] the diagnostic (either \verb"ACS_USER_NULL" if the association is to be accepted, or one of the user-initiated diagnostic codes listed in Table~\ref{AcSAPdiagnostics} on page~\pageref{AcSAPdiagnostics}); \item[\verb"context":] the application context to be used over the association (defaults to the context proposed); \item[\verb"respondtitle":] information on the responding application-entity (optional); \item[\verb"data"/\verb"ndata":] an array of user data (and the number of elements in that array, consult the warning on page~\pageref{AcSAPdata}); and, \item[\verb"aci":] a pointer to an \verb"AcSAPindication" structure, which is updated only if the call fails. \end{describe} The remaining parameters are for the presentation service, consult the description of the \verb"PConnResponse" routine on page~\pageref{PConnResponse} of \voltwo/. \tagtable[tp]{2a-2}{AcSAP Diagnostic Codes}{AcSAPdiagnostics} If the call to \verb"AcAssocResponse" is successful, and the \verb"status" parameter is set to \verb"ACS_ACCEPT", then association establishment has now been completed. If the call is successful, but the \verb"status" parameter is not \verb"ACS_ACCEPT", then the association has been rejected and the responder may exit. Otherwise, if the call failed and the reason is ``fatal'', then the association is lost. \subsubsection {Client Initialization} A program wishing to associate itself with another application-level user calls the \verb"AcAssocRequest" routine, which corresponds to the user taking the {\sf A-ASSOCIATE.REQUEST\/} action. \begin{quote}\index{AcAssocRequest}\small\begin{verbatim} int AcAssocRequest (context, callingtitle, calledtitle, callingaddr, calledaddr, ctxlist, defctxname, prequirements, srequirements, isn, settings, ref, data, ndata, qos, acc, aci) OID context; AEI callingtitle, calledtitle; struct PSAPaddr *callingaddr, *calledaddr; int prequirements, srequirements, settings, ndata; long isn; struct PSAPctxlist *ctxlist; OID defctxname; struct SSAPref *ref; PE *data; struct QOStype *qos; struct AcSAPconnect *acc; struct AcSAPindication *aci; \end{verbatim}\end{quote} The parameters to this procedure are:\label{AcAssocRequest} \begin{describe} \item[\verb"context":] the application context to be used over the association; \item[\verb"callingtitle":] information on the calling application-entity (use the manifest constant \verb"NULLAEI" if not specified); \item[\verb"calledtitle":] information on the called application-entity (use the manifest constant \verb"NULLAEI" if not specified); \item[\verb"data"/\verb"ndata":] an array of initial data (and the number of elements in that array, consult the warning on page~\pageref{AcSAPdata}); \item[\verb"qos":] the quality of service on the connection (see Section~\ref{tsap:qos} in \voltwo/); \item[\verb"acc":] a pointer to an \verb"AcSAPconnect" structure, which is updated only if the call succeeds; and, \item[\verb"aci":] a pointer to an \verb"AcSAPindication" structure, which is updated only if the call fails. \end{describe} The remaining parameters are for the presentation service, consult the description of the \verb"PConnRequest" routine on page~\pageref{PConnRequest} of \voltwo/ for additional information. Note that the \verb"ctxlist" parameter is mandatory: the association control service element will look for the ACSE PCI there. If not present, it will add the PCI to the list. If the call to \verb"AcAssocRequest" is successful (the {\sf A-ASSOCIATE.CON\-FIR\-MA\-TION\/} event occurs), it returns information in the \verb"acc" parameter which is a pointer to an \verb"AcSAPconnect" structure. \begin{quote}\index{AcSAPconnect}\small\begin{verbatim} struct AcSAPconnect { int acc_sd; int acc_result; int acc_diagnostic; OID acc_context; AEInfo acc_respondtitle; struct PSAPconnect acc_connect; int acc_ninfo; PE acc_info[NACDATA]; }; \end{verbatim}\end{quote} The elements of an \verb"AcSAPconnect" structure are:\label{AcSAPconnect} \begin{describe} \item[\verb"acc\_sd":] the association-descriptor to be used to reference this association; \item[\verb"acc\_result"/\verb"acc\_diagnostic":] the association response and diagnostic; \item[\verb"acc\_context":] the application context name; \item[\verb"acc\_respondtitle":] information on the responding application-entity (if any); \item[\verb"acc\_connect":] an \verb"PSAPconnect" structure (consult page~\pageref{PSAPconnect} of \voltwo/); and, \item[\verb"acc\_info"/\verb"acc\_ninfo":] any initial data (and the length of that data). \end{describe} Note that the negotiated contexts list in the \verb"acc_connect" element will contain a context for the ACSE. To determine the PCI for the ACSE context, the routine \verb"AcFindPCI" routine, described above can be used. If the call to \verb"AcAssocRequest" is successful, and the \verb"acc_result" element is set to \verb"ACC_ACCEPT", then association establishment has completed. If the call is successful, but the \verb"acc_result" element is not \verb"ACC_ACCEPT", then the association attempt has been rejected; consult Table~\ref{AcSAPreasons} on page~\pageref{AcSAPreasons} and Table~\ref{AcSAPdiagnostics} on page~\pageref{AcSAPdiagnostics} to determine the reason for the rejection (further information can be found in the \verb"aci" parameter). Otherwise, if the call fails then the association is not established and the \verb"AcSAPabort" structure of the \verb"AsCAPindication" discriminated union has been updated. Note that the data contained in the structure was allocated via \man malloc(3), and should be released by using the \verb"ACCFREE" macro when no longer referenced. The \verb"ACCFREE" macro, behaves as if it was defined as:\label{ACCFREE} \begin{quote}\index{ACCFREE}\small\begin{verbatim} void ACCFREE (acc) struct AcSAPconnect *acc; \end{verbatim}\end{quote} The macro frees only the data allocated by \verb"AcAssocRequest", and not the \verb"AcSAPconnect" structure itself. Further, \verb"ACCFREE" should be called only if the call to the \verb"AcAssocRequest" routine returned \verb"OK". Normally \verb"AcAssocRequest" returns only after an association has succeeded or failed. This is termed a {\em synchronous\/} association initiation. If the user desires, an {\em asynchronous\/} association may be initiated. This routine is really a macro which calls the routine \verb"AcAsynAssocRequest" with an argument indicating that a association should be attempted synchronously. \begin{quote}\index{AcAsynAssocRequest}\small\begin{verbatim} int AcAsynAssocRequest (context, callingtitle, calledtitle, callingaddr, calledaddr, ctxlist, defctxname, prequirements, srequirements, isn, settings, ref, data, ndata, qos, acc, aci, async) OID context; AEI callingtitle, calledtitle; struct PSAPaddr *callingaddr, *calledaddr; int prequirements, srequirements, settings, ndata, async; long isn; struct PSAPctxlist *ctxlist; OID defctxname; struct SSAPref *ref; PE *data; struct QOStype *qos; struct AcSAPconnect *acc; struct AcSAPindication *aci; \end{verbatim}\end{quote} The additional parameter to this procedure is: \begin{describe} \item[\verb"async":] whether the association should be initiated asynchronously. \end{describe} If the \verb"async" parameter is non-zero, then \verb"AcAsynAssocRequest" returns one of three values: \verb"NOTOK", which indicates that the association request failed; \verb"DONE", which indicates that the association request succeeded; and, \verb"OK", which indicates that the association request is still in progress. In the first two cases, the usual procedures for \verb"AcAssocRequest" are employed (i.e., a \verb"NOTOK" return from \verb"AcAsynAssocRequest" is equivalent to a \verb"NOTOK" return from \verb"AcAssocRequest", and, a \verb"DONE" return from \verb"AcAsynAssocRequest" is equivalent to a \verb"OK" return from \verb"AcAssocRequest"). In the final case, when \verb"OK" is returned, only the \verb"acc_sd" element of the \verb"acc" parameter has been updated; it reflects the association-descriptor to be used to reference this association. To determine when the association attempt has been completed, the routine \verb"xselect" (consult Section~\ref{acs:select}) should be used after calling \verb"PSelectMask". In order to determine if the association attempt is successful, the routine \verb"AcAsynRetryRequest" is called: \begin{quote}\index{AcAsynRetryRequest}\small\begin{verbatim} int AcAsynRetryRequest (sd, acc, aci) int sd; struct AcSAPconnect *acc; struct AcSAPindication *aci; \end{verbatim}\end{quote} The parameters to this procedure are: \begin{describe} \item[\verb"sd":] the association-descriptor; \item[\verb"acc":] a pointer to an \verb"AcSAPconnect" structure, which is updated only if the call succeeds; and, \item[\verb"aci":] a pointer to an \verb"AcSAPindication" structure, which is updated only if the call fails. \end{describe} Again, one of three values are returned: \verb"NOTOK", which indicates that the association request failed; \verb"DONE", which indicates that the association request succeeded; and, \verb"OK", which indicates that the association request is still in progress. Refer to Section~\ref{tsap:async} on page~\pageref{tsap:async} in \voltwo/ for information on how to make efficient use of the asynchronous connection facility. \subsection {Association Release} The \verb"AcRelRequest" routine is used to request the release of an association, and corresponds to a {\sf A-RELEASE.REQUEST\/} action. \begin{quote}\index{AcRelRequest}\small\begin{verbatim} int AcRelRequest (sd, reason, data, ndata, acr, aci) int sd; int reason; PE *data; int ndata; struct AcSAPrelease *acr; struct AcSAPindication *aci; \end{verbatim}\end{quote} The parameters to this procedure: \begin{describe} \item[\verb"sd":] the association-descriptor; \item[\verb"reason":] the reason why the association should be released, one of: \[\begin{tabular}{|l|l|} \hline \multicolumn{1}{|c|}{\bf Value}& \multicolumn{1}{c|}{\bf Reason}\\ \hline \tt ACF\_NORMAL& normal\\ \tt ACF\_URGENT& urgent\\ \tt ACF\_UNDEFINED& undefined\\ \hline \end{tabular}\] \item[\verb"data"/\verb"ndata":] an array of final data (and the number of elements in that array, consult the warning on page~\pageref{AcSAPdata}); \item[\verb"acr":] a pointer to an \verb"AcSAPrelease" structure, which is updated only if the call succeeds; and, \item[\verb"aci":] a pointer to an \verb"AcSAPindication" structure, which is updated only if the call fails. \end{describe} If the call to \verb"AcRelRequest" is successful, then this corresponds to a {\sf A-RELEASE.CONFIRMATION\/} event, and it returns information in the \verb"acr" parameter, which is a pointer to an \verb"AcSAPrelease" structure. \begin{quote}\index{AcSAPrelease}\small\begin{verbatim} struct AcSAPrelease { int acr_affirmative; int acr_reason; int acr_ninfo; char acr_info[NACDATA]; }; \end{verbatim}\end{quote} The elements of this structure are:\label{AcSAPrelease} \begin{describe} \item[\verb"acr\_affirmative":] the acceptance indicator; \item[\verb"acr\_reason":] the reason for the indicator, one of: \[\begin{tabular}{|l|l|} \hline \multicolumn{1}{|c|}{\bf Value}& \multicolumn{1}{c|}{\bf Reason}\\ \hline \tt ACR\_NORMAL& normal\\ \tt ACR\_NOTFINISHED& not finished\\ \tt ACR\_UNDEFINED& undefined\\ \hline \end{tabular}\] \item[\verb"acr\_info"/\verb"acr\_ninfo":] any final data (and the length of that data). \end{describe} Note that the data contained in the structure was allocated via \man malloc(3), and should be released by using the \verb"ACRFREE" macro when no longer referenced. The \verb"ACRFREE" macro, behaves as if it was defined as:\label{ACRFREE} \begin{quote}\index{ACRFREE}\small\begin{verbatim} void ACRFREE (acr) struct AcSAPrelease *acr; \end{verbatim}\end{quote} The macro frees only the data allocated by \verb"AcRelRequest", and not the \verb"AcSAPrelease" structure itself. Further, \verb"ACRFREE" should be called only if the call to the \verb"AcRelRequest" routine returned \verb"OK". If the call to \verb"AcRelRequest" is successful, and the \verb"acr_affirmative" element is set, then the association has been released. If the call is successful, but the \verb"acr_affirmative" element is not set (i.e., zero), then the request to release the association has been rejected by the remote user, and the association is still established. Otherwise the \verb"AcSAPabort" element of the \verb"AcSAPindication" parameter \verb"aci" contains the reason for failure. Upon receiving a {\sf A-RELEASE.INDICATION\/} event, the user is required to generate a {\sf A-RELEASE.RESPONSE\/} action using the \verb"AcRelResponse" routine. \begin{quote}\index{AcRelResponse}\small\begin{verbatim} int AcRelResponse (sd, status, reason, data, ndata, aci) int sd; int status, reason; PE *data; int ndata; struct AcSAPindication *aci; \end{verbatim}\end{quote} The parameters to this procedure: \begin{describe} \item[\verb"sd":] the association-descriptor; \item[\verb"status":] the acceptance indicator (either \verb"ACS_ACCEPT" if the association is to be released, or \verb"ACS_REJECT" otherwise); \item[\verb"reason":] the reason for the indicator, one of: \[\begin{tabular}{|l|l|} \hline \multicolumn{1}{|c|}{\bf Value}& \multicolumn{1}{c|}{\bf Reason}\\ \hline \tt ACR\_NORMAL& normal\\ \tt ACR\_NOTFINISHED& not finished\\ \tt ACR\_UNDEFINED& undefined\\ \hline \end{tabular}\] \item[\verb"data"/\verb"ndata":] an array of final data (and the number of elements in that array, consult the warning on page~\pageref{AcSAPdata}); and, \item[\verb"aci":] a pointer to an \verb"AcSAPindication" structure, which is updated only if the call fails. \end{describe} If the call to \verb"AcRelResponse" is successful, and if the \verb"result" parameter is set to \verb"ACS_ACCEPT", then the association has been released. If the call is successful, but the \verb"result" parameter is not \verb"ACS_ACCEPT", then the association remains established. \subsection {Association Abort} To unilaterally abort an association, the routine \verb"AcUAbortRequest" routine is used which corresponds to the {\sf A-ABORT.REQUEST\/} action. \begin{quote}\index{AcUAbortRequest}\small\begin{verbatim} int AcUAbortRequest (sd, data, ndata, aci) int sd; PE *data; int ndata; struct AcSAPindication *aci; \end{verbatim}\end{quote} The parameters to this procedure: \begin{describe} \item[\verb"sd":] the association-descriptor; \item[\verb"data"/\verb"ndata":] an array of abort data (and the number of elements in that array, consult the warning on page~\pageref{AcSAPdata}); and, \item[\verb"aci":] a pointer to an \verb"AcSAPindication" structure, which is updated only if the call fails. \end{describe} If the call to \verb"AcUAbortRequest" is successful, then the association is immediately released, and any data queued for the association may be lost. \f \section {Higher-Performance Nameservice}\label{acsap:ns} Rather than containing a Directory User Agent (DUA) directly, programs loaded with the \man libacsap(3n) library contain an interface to a ``higher performance'' nameservice (NS). See Section~\ref{dse:tailor} on page~\pageref{dse:tailor} in \voltwo/ for information on how to enable this facility. This is a simple interface to an OSI directory that contains the most essential aspects of the functionality which a DUA could offer, but does so without the high-overhead protocol used by a DUA. In essence, a lightweight protocol is used to talk to the local Directory Service Agent (DSA), and, if anything complicated arises when resolving the name (e.g., a referral is returned), then the DSA will do the work on behalf of the client. The protocol is described in \cite{QUIPU.Design}. The interface to the NS consists of one routine: \begin{quote}\index{}\small\begin{verbatim} PE name2value (name, attribute, real_name) char *name, *attribute; PE *real_name; \end{verbatim}\end{quote} The parameters to this procedure are: \begin{describe} \item[\verb"name":] a string containing a Distinguished Name in QUIPU string format (refer to Figure~\ref{bnf-name} on page~\pageref{bnf-name} in \volfive/); \item[\verb"attribute":] a string representation of an Attribute Name (refer to Section~\ref{oidtables} on page~\pageref{oidtables} in \volfive/); and, \item[\verb"attribute":] a pointer to a location to store the actual Distinguished Name (use the manifest constant \verb"NULLPEP" if this information is not desired). \end{describe} If the lookup is successful, a presentation-element corresponding to the ASN.1 value of the named attribute of the named object is returned. Otherwise, the manifest constant \verb"NULLPE" is returned. It should be stressed that the nameservice is designed to do a simple job in as efficient a manner as possible. Its goals are: \begin{itemize} \item Lookup of publically readable information~---~no access control. \item Retrieval of a single attribute value~---~for multi-valued attributes, only one value is returned and the order is currently undefined. \item Lightweight (connectionless-mode) access to the nameservice~---~a overly-simplistic transaction protocol is used. \end{itemize} If an application needs more than this service, then it should use a real DUA in order to meet its needs. \f \section {Association Events} Typically, the presentation service generates events which lead to the {\sf A-RELEASE.INDICATION}, {\sf A-ABORT.INDICATION}, and {\sf A-P-ABORT.IN\-DI\-CA\-TION\/} events being raised. For those interested in writing application service elements which interpret this information, this section describes the necessary mappings. \subsection {Release Indication} Upon receiving a {\sf P-RELEASE.INDICATION\/} event, the routine \verb"AcFINISHser" should be called to map this into a {\sf A-RELEASE.INDICATION\/} event. \begin{quote}\index{AcFINISHser}\small\begin{verbatim} int AcFINISHser (sd, pf, aci) int sd; struct PSAPfinish *pf; struct AcSAPindication *aci; \end{verbatim}\end{quote} The parameters to this procedure: \begin{describe} \item[\verb"sd":] the association-descriptor; \item[\verb"pa":] a pointer to an \verb"PSAPfinish" structure, containing information on the presentation-level release; and, \item[\verb"aci":] a pointer to an \verb"AcSAPindication" structure. \end{describe} If the call to \verb"AcFINISHser" is successful, then the \verb"aci_type" field of the \verb"aci" parameter contains the value \verb"ACI_FINISH", and an \verb"AcSAPfinish" structure is contained inside the \verb"aci" parameter. \begin{quote}\index{AcSAPfinish}\small\begin{verbatim} struct AcSAPfinish { int acf_reason; int acf_ninfo; char acf_info[NACDATA]; }; \end{verbatim}\end{quote} The elements of this structure are: \begin{describe} \item[\verb"acf\_reason":] the reason for the release request, one of: \[\begin{tabular}{|l|l|} \hline \multicolumn{1}{|c|}{\bf Value}& \multicolumn{1}{c|}{\bf Reason}\\ \hline \tt ACF\_NORMAL& normal\\ \tt ACF\_URGENT& urgent\\ \tt ACF\_UNDEFINED& undefined\\ \hline \end{tabular}\] \item[\verb"acf\_info"/\verb"acf\_ninfo":] any final data (and the length of that data). \end{describe} Note that the data contained in the structure was allocated via \man malloc(3), and should be released by using the \verb"ACFFREE" macro when no longer referenced. The \verb"ACFFREE" macro, behaves as if it was defined as:\label{ACFFREE} \begin{quote}\index{ACFFREE}\small\begin{verbatim} void ACFFREE (acf) struct AcSAPfinish *acf; \end{verbatim}\end{quote} The macro frees only the data allocated by \verb"AcFINISHser", and not the \verb"AcSAPfinish" structure itself. Further, \verb"ACFFREE" should be called only if the call to the \verb"AcFINISHser" routine returned \verb"OK". Otherwise, if the call fails, the \verb"aci" parameter contains information pertaining to the failure. \subsection {Abort Indication} Upon receiving a {\sf P-U-ABORT.INDICATION\/} or {\sf P-P-ABORT.INDICATION\/} event, the routine \verb"AcABORTser" should be called to map this into a {\sf A-ABORT.INDICATION\/} or {\sf A-P-ABORT.INDICATION\/} event. \begin{quote}\index{AcABORTser}\small\begin{verbatim} int AcABORTser (sd, pa, aci) int sd; struct PSAPabort *pa; struct AcSAPindication *aci; \end{verbatim}\end{quote} The parameters to this procedure: \begin{describe} \item[\verb"sd":] the association-descriptor; \item[\verb"pa":] a pointer to an \verb"PSAPabort" structure, containing information on the presentation-level abort; and, \item[\verb"aci":] a pointer to an \verb"AcSAPindication" structure. \end{describe} If the call to \verb"AcABORTser" is successful, then the \verb"aci" parameter is updated to reflect information on the abort indication. Otherwise, if the call fails, the \verb"aci" parameter contains information pertaining to the failure. \f \section {Select Facility}\label{acs:select} Ideally, the \man select(2) system call should be used on all descriptors, regardless of the level of abstraction (e.g., association-descriptor, presentation-descriptor, and so on). The routines with a \verb"SelectMask" suffix, such as \verb"PSelectMask" are supplied to determine if there are already queued events. These routines should always be called prior to using the select facility of the kernel. Sadly, some networking subsystems used by the software do not support \man select(2). To provide a consistent interface, the \verb"xselect" routine should be used instead of \man select(2). \begin{quote}\index{xselect}\small\begin{verbatim} int xselect (nfds, rfds, wfds, efds, secs) int nfds; fd_set *rfds, *wfds, *efds, secs; \end{verbatim}\end{quote} The parameters to this procedure are: \begin{describe} \item[\verb"nfds":] the number of descriptors present in the masks (actually the \verb"width" of descriptors from zero to the highest meaningful descriptor); \item[\verb"rfds"/\verb"wfds"/\verb"efds":] the locations of masks interested in read, write, and exception events; and, \item[\verb"secs":] the maximum number of seconds to wait for an event (a value of \verb"NOTOK" indicates that the call should block indefinitely, whereas a value of \verb"OK" indicates that the call should not block at all, e.g., a polling action). \end{describe} Unlike most routines, the \verb"xselect" routine returns one of several values: \verb"NOTOK" (on failure), \verb"OK" (if no events occurred within the time limit), or, the number of descriptors on which events occurred (the masks are updated appropriately). \f \section {Generic Server Dispatch}\label{acs:server} Ideally, one should write a server which can operate in one of two modes: \begin{itemize} \item Each incoming connection results in \man tsapd(8c) invoking another instance of the server; or, \item All incoming connections are given to exactly one instance of the server (the server is invoked without arguments during system initialization). \end{itemize} The choice as to which mode is used is made by the system administrator. By default, the first mode, termed the {\em dynamic\/} approach, is used. The second mode, termed the {\em static\/} approach, is described in Section~\ref{static:services} on page~\pageref{static:services}. There are several ways in which this dual-approach scheme can be realized. One such implementation is based on the routine \verb"isodeserver".\label{isodeserver} \begin{quote}\index{isodeserver}\small\begin{verbatim} int isodeserver (argc, argv, aei, initfnx, workfnx, losefnx, td) int argc; char **argv; AEI aei; IFP initfnx, workfnx, losefnx; struct TSAPdisconnect *td; \end{verbatim}\end{quote} The parameters to this procedure are: \begin{describe} \item[\verb"argc":] the length of the argument vector which the program was invoked with; \item[\verb"argv":] the argument vector which the program was invoked with; \item[\verb"aei":] the information on the application-entity offering the service; \item[\verb"initfnx":] the address of an event-handler routine to be invoked when a new connection arrives; \item[\verb"workfnx":] the address of an event-handler routine to be invoked when activity occurs on an association; \item[\verb"losefnx":] the address of an event-handler routine to be invoked if \verb"TNetAccept" (described in Section~\ref{tsap:listen}) fails and, \item[\verb"td":] a pointer to an \verb"TSAPdisconnect" structure, which is updated only if the call fails. \end{describe} If the call is successful, then the program may terminate immediately, as no work remains to be done (in the case of the single instance mode, \verb"isodeserver" returns only on error). Otherwise, the \verb"td" parameter indicates the reason for failure (consult Section~\ref{TSAPdisconnect} on page~\pageref{TSAPdisconnect} of \voltwo/). When an event associated with a new connection occurs, the event-handler routine is invoked with two parameters: \begin{quote}\small\begin{verbatim} (*initfnx) (vecp, vec); int vecp; char **vec; \end{verbatim}\end{quote} The parameters are: \begin{describe} \item[\verb"vecp":] the length of the argument vector; and, \item[\verb"vec":] the argument vector. \end{describe} The event-handler should then call \verb"AcInit" with these parameters to achieve an {\sf A-ASSOCIATION.INDICATION\/} event. If \verb"AcInit" is successful, the event-handler should decide if it wishes to honor the association and then call \verb"AcAssocResponse" with the appropriate parameters. The event-handler should return the assocation-descriptor if it accepted the association. Otherwise (or upon any errors), it should return \verb"NOTOK". When an activity associated with an association occurs, the event-handler routine is invoked with one parameter: \begin{quote}\small\begin{verbatim} (*workfnx) (fd); int fd; \end{verbatim}\end{quote} The parameter is: \begin{describe} \item[\verb"fd":] the association-descriptor of the association. \end{describe} The event-handler should then call the appropriate routine to read the next event from the association (e.g., \verb"RoWaitRequest" if remote operations are being used). The event-handler should return \verb"NOTOK" if the association is terminated or aborted, or \verb"OK" otherwise. The \verb"isodeserver" routine uses the \verb"TNetAccept" routine to wait for the next event on existing associations and for new connections. It is possible, though unlikely for a failure to occur during this operation. In this event, the event-handler routine is invoked with one parameter: \begin{quote}\small\begin{verbatim} (*losefnx) (td); struct TSAPdisconnect *td; \end{verbatim}\end{quote} The parameter is: \begin{describe} \item[\verb"td":] a pointer to an \verb"TSAPdisconnect" structure updated by \verb"TNetAccept". \end{describe} The event-handler should handle the error however it deems proper (usually by logging it and then returning). An example of this facility is presented in Section~\ref{acs:example} below. Another interface to this approach is provided for servers that may be engaged in other operations besides answering incoming calls (e.g. initiating outgoing calls too). This interface provides indentical functionality to the \verb|isodeserver| interface, but allows access to other events. The interface is provided by two calls. The first is \verb|iserver_init|. \begin{quote}\index{iserver\_init}\small\begin{verbatim} int iserver_init (argc, argv, aei, initfnx, td) int argc; char **argv; AEI aei; IFP initfnx; struct TSAPdisconnect *td; \end{verbatim}\end{quote} The parameters to this procedure are similar in part to the \verb|isodeserver| procedure: \begin{describe} \item[\verb|argc|:] the length of the argument vector which the program was invoked with; \item[\verb|argv|:] the argument vector which the program was invoked with; \item[\verb|aei|:] the information on the application-entity offering the service; \item[\verb"initfnx":] the address of an event-handler routine to be invoked when a new connection arrives, and \item[\verb|td|:] a pointer to an \verb"TSAPdisconnect" structure, which is updated only if the call fails. \end{describe} This procedure registers a listener for the address and may may call the \verb|initfnx| if the server is running in dynamic mode. If the call fails the \verb|td| parameter will indicate the reason for failure. One this function has been called, the \verb|iserver_wait| procedure should be called at regular intervals to handle incoming events, typically in a loop of some kind. It is called as follows: \begin{quote}\index{iserver\_wait}\small\begin{verbatim} int iserver_wait (initfnx, workfnx, losefnx, nfds, nfds, rfds, wfds, efds, secs, td) IFP initfnx, workfnx, losefnx; int nfds; fd_set *rfds, *wfds, *efds; int secs; struct TSAPdisconnect *td; \end{verbatim}\end{quote} The parameters to this procedure are: \begin{describe} \item[\verb"initfnx":] the address of an event-handler routine to be invoked when a new connection arrives; \item[\verb"workfnx":] the address of an event-handler routine to be invoked when activity occurs on an association; \item[\verb"losefnx":] the address of an event-handler routine to be invoked if \verb"TNetAccept" (described in Section~\ref{tsap:listen}) fails; \item[\verb|nfds/rfds/wfds/efds|:] additional association-descriptors/file descriptors to await for activity on; \item[\verb|secs|:] the maximum number of seconds to wait for activity (a value of \verb|NOTOK| indicates that the call should block indefinitely, whereas a value of \verb|OK| indicates that the call should not block at all, e.g., a polling action); and \item[\verb"td":] a pointer to an \verb"TSAPdisconnect" structure, which is updated only if the call fails. \end{describe} This routine calls the \verb|TNetAccept| routine to wait for incoming calls. It will call the procedures \verb|initfnx|, \verb|workfnx| and \verb|losefnx| in an indetical way to the \verb|isodeserver|. The routine returns on a number of conditions. \begin{itemize} \item If one of the supplied association/file descriptors registers activity the procedure returns with the mask updated. \item If an incoming association occurs. It should be accepted or rejected by the \verb|initfnx| then the procedure will return. \item If some activity happens on one of the accepted calls. This is handled by the \verb|workfnx| then the procedure will return. \item If the time given runs out, the procedure will return. \end{itemize} An outline usage of these procedures might be something like: \begin{quote}\small\begin{verbatim} if (iserver_init (argc, argv, aei, ros_init, td) == NOTOK) /* error */ for (;;) { /* set up descriptors */ switch (iserver_wait (ros_init, ros_work, ros_lose, nfds, &rfds, &wfds, NULLFD, timeout, td)) { case DONE: exit (0); case NOTOK: /* error */ case OK: /* check fds for activitiy, do other things */ } \end{verbatim}\end{quote} Please note that \verb"isodeserver" and \verb|iserver_wait| implement one possible discipline for association management. Many others are possible, depending on the needs of the service being provided. Further, note that while the text above and the example below are expressed in terms of association control (i.e., they make use of \verb"AcInit" and \verb"AcAssocResponse"), this facility will provide similar support at any other layer in the system (e.g., \verb"isodeserver" can be used for transport or session entities). Also note that as these routines use the \verb|TNetAccept| routines, child process are collected automatically. If you wish to start child processes and wait for their exit status, you should take note of the warnings associated with the \verb|TNetAccept| procedure (see Section~\ref{tsap:accept} on page~\pageref{tsap:accept} of \voltwo/). \f \section {Restrictions on User Data}\label{AcSAPdata} To quote the \cite{ISO.ACS.Service} specification: \[\fbox{\begin{tabular}{lp{0.8\textwidth}} \bf NOTE:& Use of the services $\ldots$ may be subject to some constraints from (the) session services until work on providing unlimited length user data field parameters on session primitives is completed. \end{tabular}}\] \f \section {Error Conventions}\label{acs:errors} All of the routines in this library return the manifest constant \verb"NOTOK" on error, and also update the \verb"aci" parameter given to the routine. The \verb"aci_abort" element of the \verb"AcSAPindication" structure encodes the reason for the failure. One coerces the pointer to an \verb"AcSAPabort" structure, and consults the \verb"aca_reason" element of this latter structure. This element can be given as a parameter to the routine \verb"AcErrString" which returns a null-terminated diagnostic string. \begin{quote}\index{AcErrString}\small\begin{verbatim} char *AcErrString (c) int c; \end{verbatim}\end{quote} The \verb"" macro can be used to determine if the failure is fatal (the association has been lost). \begin{quote}\index{ACS\_FATAL}\small\begin{verbatim} int ACS_FATAL(r) int r; \end{verbatim}\end{quote} For protocol purists, the \verb"ACS_OFFICIAL" macro can be used to determine if the error is an ``official'' error as defined by the specification, or an ``unofficial'' error used by the implementation. \begin{quote}\index{ACS\_OFFICIAL}\small\begin{verbatim} int ACS_OFFICIAL (r) int r; \end{verbatim}\end{quote} \f \section {Compiling and Loading} Programs using the \man libacsap(3n) library should include \verb"<isode/acsap.h>". The programs should also be loaded with \verb"-lisode". \f \section {An Example}\label{acs:example} One example of the use of the \man libacsap(3n) library is found in Section~\ref{ros:example:server} on page~\pageref{ros:example:server}. This example is straight-forward in presenting the interaction of association control and remote operations. Now let's consider how to rewrite the server to use the facilities described above in Section~\ref{acs:server}. Instead of using an asynchronous interface, a synchronous interface will be employed. Only Figure~\ref{initROSresponder} from the example in Section~\ref{ros:example:server} need be changed. We assume that there are three exception-logging routines: {\em fatal}, which prints a diagnostic and terminates the process; {\em error}, which prints a diagnostic and then executes the statement \begin{quote}\small\begin{verbatim} longjmp (toplevel, NOTOK); \end{verbatim}\end{quote} and, {\em warn}, which simply prints a diagnostic. In Figure~\ref{doROSserver}, the replacement routines are shown. First, the application-entity title for the service is deteremined. The routine \verb"isodeserver" is then called with its requisite arguments. If the routine fails, the process terminates after printing a diagnostic. Otherwise the process exits. In the case where the \man tsapd(8c) daemon invokes a new instance of the server each time an incoming connection is received, \verb"isodeserver" will return after that assocation has been released. In the case where all incoming connections are given to a single instance of the server, then \verb"isodeserver" returns only if a fatal error is detected. The routine \verb"ros_init" is called for each incoming connection. First, the ACSE state is re-captured by calling \verb"AcInit". If this succeeds, then any command line arguments are parsed. These arguments are present only if the server was invoked by the \man tsapd(8c) daemon, and are specified in the \man isoservices(5) file described in Chapter~\ref{isoservices} of \voltwo/. Assuming that the responder is satisfied with the proposed association, the routine then calls \verb"AcAssocResponse" to accept the association. Then, \verb"RoSetService" is called to set the underlying service to be used for remote operations. Finally, the association-descriptor is returned to \verb"isodeserver". The routine \verb"ros_work" is called when activity occurs on an association. The routine sets a global return vector using \man setjmp (3) and then calls \verb"RoWaitRequest" to read the next indication. This usually results in the routine \verb"ros_indication" (found in Figure~\ref{doROSresponder} on page~\pageref{doROSresponder}) being called. If the association was not released, then \verb"ros_work" returns \verb"OK". Otherwise if some error occurred, use of the routine \verb"error" will cause control to return to the \verb"setjmp" call. In this case, \verb"AcUAbortRequest" is called to make sure that the association is (ungracefully) released, then \verb"NOTOK" is returned to \verb"isodeserver". The routine \verb"ros_lose" simply logs the failure of \verb"TNetAccept" when called from \verb"isodeserver". {\let\small=\scriptsize %%% yikes! \clearpage \tagrind[tp]{grind2a-2a}{The generic ROS server}{doROSserver} \clearpage \tagrind[tp]{grind2a-2b}{The generic ROS server (continued)}\empty \clearpage \tagrind[tp]{grind2a-2c}{The generic ROS server (continued)}\empty \clearpage \tagrind[tp]{grind2a-2d}{The generic ROS server (continued)}\empty} \f \section {For Further Reading} The ISO specification for association control services is defined in \cite{ISO.ACS.Service}. The corresponding protocol definition is \cite{ISO.ACS.Protocol}. \f \section {Changes Since the Last Release}\label{acsap:changes} A brief summary of the changes between \verb"acsap"~\acsaprevrsn/ and \verb"acsap"~\acsapvrsn/ are now presented. These are the user-visible changes only; changes of a strictly internal nature are not discussed. The routines \verb"paddr2str" and \verb"str2paddr" were modified to support multiple network addresses in a single presentation address. The routines \verb"paddr2asn" and \verb"asn2paddr" were removed. The \verb"name2value" routine was documented.