|
|
1.1 root 1: % run this through LaTeX with the appropriate wrapper
2:
3: \chapter {Boilerplate for Responders}\label{cook:responder}
4: Let's consider how to build a responder which is also a performer.
5: In Chapter~\ref{cook:discipline},
6: two forms for a responder were identified:
7: {\em dynamic},
8: in which each incoming association caused the instantiation of a new responder,
9: and,
10: {\em static},
11: in which each incoming association was given to a pre-existing single
12: instantiation of a responder.
13: The dynamic responder can be thought of as simply being a special case of a
14: static responder.
15: Hence,
16: we will describe how one builds a static responder in this chapter.
17:
18: If you have access to the source tree for this release,
19: the directory \file{others/lookup/} contains the boilerplate described herein.
20:
21: \section {Static Responder}
22: There are three areas for the boilerplate:
23: association management, operation response, and, error handling.
24:
25: Before proceeding however,
26: let's consider what an \verb"#include" file, say \verb"ryresponder.h",
27: might look like.
28: First, the standard \man librosy(3n) definitions are included,
29: along with the definitions for the daemon logging package.
30: Next, a \verb"dispatch" structure is defined
31: along with the boilerplate routines.
32: The \verb"dispatch" structure will be used by the boilerplate to invoke a
33: user-supplied routine that will respond to an invocation.
34:
35: \newpage
36: \tgrindfile{ryresponder-h}
37:
38: \subsection {Association Management}
39: Association management is performed precisely the way it is outlined in
40: Section~\ref{acs:server} of \volone/.
41: This is implemented by the routine \verb"ryresponder":
42: \begin{quote}\index{ryresponder}\small\begin{verbatim}
43: int ryresponder (argc, argv, myservice, dispatches, ops,
44: start, stop)
45: int argc;
46: char **argv,
47: *myservice;
48: struct dispatch *dispatches;
49: struct RyOperation *ops;
50: IFP start,
51: stop;
52: \end{verbatim}\end{quote}
53: The parameters to this procedure are:
54: \begin{describe}
55: \item[\verb"argc"/\verb"argv":] the argument vector (and its length)
56: that the program was invoked with;
57:
58: \item[\verb"myservice":] the non-host portion of the application-entity
59: information;
60:
61: \item[\verb"dispatches":] a pointer to a \verb"dispatch" table;
62:
63: \item[\verb"ops":] a pointer to a \verb"RyOperation" table;
64:
65: \item[\verb"start":] the address of a routine to decide if incoming
66: associations should be accepted
67: (use \verb"NULLIFP" if associations should always be accepted);
68: and,
69:
70: \item[\verb"stop":] the address of a routine to note that an association
71: requests termination or has been terminated
72: (use \verb"NULLIFP" if associations termination is unremarkable).
73: \end{describe}
74: The function of this routine is straight-forward though tedious.
75: First, \verb"myname" is initialized to the name that the program was invoked
76: with.
77: Next, a debug flag is possibly set and the daemon logging package is
78: initialized,
79: and the responder's application-entity information is computed.
80: Finally,
81: each operation is registered with the \verb"RyDispatch" routine,
82: and the \verb"start" and \verb"stop" routines are remembered.
83:
84: The routine \verb"isodeserver" is then called to manage any associations.
85: As a result,
86: the \verb"ros_init" routine will be informed of new associations,
87: the \verb"ros_work" routine will be informed of network activity,
88: and the \verb"ros_lose" routine will be advised if network listening fails.
89:
90: The \verb"ros_init" routine is also straight-forward.
91: First, \verb"AcInit" is called to recapture the ACSE-state,
92: then the user-defined association acceptance routine is called (if any).
93: This routine should return either \verb"ACS_ACCEPT" if the association is to
94: be accepted,
95: or either
96: \begin{quote}\tt
97: ACS\_TRANSIENT, ACS\_PERMANENT,\\
98: \end{quote}
99: otherwise
100: (these latter two codes are discussed in Table~\ref{AcSAPreasons} on
101: page~\pageref{AcSAPreasons} of \volone/).
102: The routine \verb"AcAssocResponse" is then called to deal with the incoming
103: association.
104: The arguments are strictly boilerplate:
105: they will work unaltered for most applications.
106: If the association was accepted,
107: then the routine \verb"RoSetService" is used to tell the remote operations
108: library to use the presentation service as the underlying service.
109:
110: The routine \verb"ros_work" is called when activity occurs on an association,
111: and is somewhat complex.
112: The routine sets a global return vector using \man setjmp (3)
113: and then calls \verb"RyWait" to poll for the next operation-related event.
114: This usually results in one of the operations registered earlier being
115: dispatched immediately,
116: and then \verb"RyWait" will return \verb"NOTOK"
117: with an error condition of \verb"ROS_TIMER" indicating that there is no
118: more network activity pending.
119: Otherwise, the routine \verb"ros_indication" is called to handle
120: extraordinary conditions on the association.
121: If some error occurred during the handling of an invocation,
122: use of the routine \verb"ros_adios" will cause control to return to the
123: \verb"setjmp" call.
124: In this case,
125: several things happen.
126: First,
127: the user-defined association termination routine routine is called (if any).
128: This routine should note that the association is now abruptly terminated.
129: Next,
130: the \verb"AcUAbortRequest" routine is called to make sure that the association
131: is (ungracefully) released.
132: Following this,
133: the \verb"RyLose" routine is called to expunge any information regarding
134: queued operations from the run-time environment.
135: Finally, \verb"NOTOK" is returned to \verb"isodeserver",
136: which causes the association to be removed from the list of current
137: associations.
138:
139: The \verb"ros_indication" routine is used to handle uncommon events for an
140: association: user-rejections, provider-rejections, and association termination.
141: In all three cases,
142: the event is logged.
143: In the case of the initiator requesting that the association be terminated,
144: several things happen.
145: First,
146: the user-defined association termination routine is called (if any).
147: This routine should return either \verb"ACS_ACCEPT" if the association is to
148: be released,
149: or \verb"ACS_REJECT" if the termination is to be refused.
150: The routine \verb"AcRelResponse" is then called to deal with the request to
151: terminate the association.
152: If the termination was accepted,
153: then control returns to the \verb"setjmp" call in \verb"ros_work",
154: which finalizes things.
155:
156: The \verb"ros_lose" routine is simple:
157: the error condition is logged.
158:
159: \tgrindfile{ryresp-assoc}
160: \newpage
161:
162: \subsection {Operation Response}
163: When an operation is invoked,
164: its dispatch routine is called from the routine \verb"RyWait"
165: as described in Section~\ref{librosy:register} on
166: Page~\pageref{librosy:register}.
167: The boilerplate for a dispatch routine is fairly uniform.
168: A check is made to see if the invocation is linked to a previous invocation,
169: and the invocation is logged.
170: Any user-rejections are performed by the routine \verb"ureject" which is a
171: simple wrapper for the \verb"RyDsUReject" routine.
172: Next, the operation is attempted.
173: If it succeeded (as denoted by \verb"won"),
174: then a result is allocated, and initialized and returned to the initiator by
175: the \verb"RyDsResult" routine.
176: Otherwise,
177: an error is selected,
178: and
179: its parameter is allocated, initialized and returned to the initiator by the
180: \verb"error" routine which is a simple wrapper for the \verb"RyDsError"
181: routine.
182: Finally,
183: the argument is freed and the handler returns.
184:
185: \tgrindfile{ryresp-invoke}
186: \newpage
187:
188: \subsection {Error Handling}
189: These routines for the most part are all straight-forward.
190: \begin{describe}
191: \item[\verb"ros\_adios":] used to report a ROS error and terminate;
192:
193: \item[\verb"ros\_advise":] used to report a ROS error;
194:
195: \item[\verb"acs\_advise":] used to report an ACS error;
196:
197: \item[\verb"adios":] used to report an error and terminate;
198:
199: \item[\verb"advise":] used to report an error;
200: and,
201:
202: \end{describe}
203: \pgm{pepy} generate errors are normally caught by the routine
204: \verb"PY_advise"\index{PY\_advise} by using the \verb"-a" switch to
205: \pgm{pepy}. The \man librosy(3n) routines use these to build up error
206: message when \pgm{pepy} routines fail.
207:
208: \tgrindfile{ryresp-error}
209: \newpage
210:
211: \subsection {An Example}
212: An example of a responder written using this boilerplate is
213: shown in Section~\ref{passwd:responder} on page~\pageref{passwd:responder}.
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.