Indentation. Variable sgml-local-catalogs set to nil.
[yaz-moved-to-github.git] / doc / comstack.xml
1 <!-- $Id: comstack.xml,v 1.5 2001-10-26 20:13:44 adam Exp $ -->
2  <chapter id="comstack"><title>The COMSTACK Module</title>
3
4   <sect1 id="comstack.synopsis"><title>Synopsis (blocking mode)</title>
5
6    <programlisting>
7
8 COMSTACK *stack;
9 char *buf = 0;
10 int size = 0, length_incoming;
11 char *protocol_package; 
12 int protocol_package_length;
13 char server_address[] = "myserver.com:2100";
14 int status;
15
16 stack = cs_create(tcpip_type, 1, PROTO_Z3950);
17 if (!stack) {
18     perror("cs_create");  /* note use of perror() here since we have no stack yet */
19     exit(1);
20 }
21
22 status = cs_connect(stack, server_address);
23 if (status != 0) {
24     cs_perror(stack, "cs_connect");
25     exit(1);
26 }
27
28 status = cs_put(stack, protocol_package, protocol_package_length);
29 if (status) {
30     cs_perror(stack, "cs_put");
31     exit(1);
32 }
33
34 /* Now get a response */
35
36 length_incoming = cs_get(stack, &amp;buf, &amp;size);
37 if (!length_incoming) {
38     fprintf(stderr, "Connection closed\n");
39     exit(1);
40 } else if (length_incoming < 0) {
41     cs_perror(stack, "cs_get");
42     exit(1);
43 }
44
45 /* Do stuff with buf here */
46
47 /* clean up */
48 cs_close(stack);
49 if (buf)
50     free(buf);
51     
52    </programlisting>
53
54   </sect1>
55   <sect1 id="comstack.introduction"><title>Introduction</title>
56
57    <para>
58     The &comstack;
59     subsystem provides a transparent interface to different types of transport
60     stacks for the exchange of BER-encoded data. At present, the
61     RFC1729 method (BER over TCP/IP), and Peter Furniss' XTImOSI
62     stack are supported, but others may be added in time. The philosophy of the
63     module is to provide a simple interface by hiding unused options and
64     facilities of the underlying libraries. This is always done at the risk
65     of losing generality, and it may prove that the interface will need
66     extension later on.
67    </para>
68
69    <para>
70     The interface is implemented in such a fashion that only the
71     sub-layers constructed to the transport methods that you wish to
72     use in your application are linked in.
73    </para>
74
75    <para>
76     You will note that even though simplicity was a goal in the design,
77     the interface is still orders of magnitudes more complex than the
78     transport systems found in many other packages. One reason is that
79     the interface needs to support the somewhat different requirements of
80     the different lower-layer communications stacks; another important reason is
81     that the interface seeks to provide a more or less industrial-strength
82     approach to asynchronous event-handling. When no function is allowed
83     to block, things get more complex - particularly on the server
84     side. We urge you to have a look at the demonstration client and server
85     provided with the package. They are meant to be easily readable and
86     instructive, while still being at least moderately useful.
87    </para>
88
89   </sect1>
90   <sect1 id="comstack.common"><title>Common Functions</title>
91
92    <sect2><title>Managing Endpoints</title>
93
94     <synopsis>
95      COMSTACK cs_create(CS_TYPE type, int blocking, int protocol);
96     </synopsis>
97
98     <para>
99      Creates an instance of the protocol stack - a communications endpoint.
100      The <literal>type</literal> parameter determines the mode of communication.
101      At present, the values
102      <literal>tcpip_type</literal>
103      and
104      <literal>mosi_type</literal>
105      are recognized. The function returns a null-pointer if a system error
106      occurs. The <literal>blocking</literal> parameter should be one if you wish
107      the association to operate in blocking mode, zero otherwise. The
108      <literal>protocol</literal> field should be one of
109      <literal>PROTO_SR</literal> or <literal>PROTO_Z3950</literal>.
110     </para>
111
112
113     <synopsis>
114      int cs_close(COMSTACK handle);
115     </synopsis>
116
117     <para>
118      Closes the connection (as elegantly as the lower layers will permit),
119      and releases the resources pointed to by the
120      <literal>handle</literal>
121      parameter. The
122      <literal>handle</literal>
123      should not be referenced again after this call.
124     </para>
125
126     <note>
127      <para>
128       We really need a soft disconnect, don't we?
129      </para>
130     </note>
131    </sect2>
132
133    <sect2><title>Data Exchange</title>
134
135     <synopsis>
136      int cs_put(COMSTACK handle, char *buf, int len);
137     </synopsis>
138
139     <para>
140      Sends
141      <literal>buf</literal>
142      down the wire. In blocking mode, this function will return only when a
143      full buffer has been written, or an error has occurred. In nonblocking
144      mode, it's possible that the function will be unable to send the full
145      buffer at once, which will be indicated by a return value of 1. The
146      function will keep track of the number of octets already written; you
147      should call it repeatedly with the same values of <literal>buf</literal>
148      and <literal>len</literal>, until the buffer has been transmitted.
149      When a full buffer has been sent, the function will return 0 for
150      success. -1 indicates an error condition (see below).
151     </para>
152
153     <synopsis>
154      int cs_get(COMSTACK handle, char **buf, int *size);
155     </synopsis>
156
157     <para>
158      Receives a PDU from the peer. Returns the number of bytes
159      read. In nonblocking mode, it is possible that not all of the packet can be
160      read at once. In this case, the function returns 1. To simplify the
161      interface, the function is
162      responsible for managing the size of the buffer. It will be reallocated
163      if necessary to contain large packages, and will sometimes be moved
164      around internally by the subsystem when partial packages are read. Before
165      calling
166      <function>cs_get</function>
167      for the fist time, the buffer can be initialized to the null pointer,
168      and the length should also be set to 0 - cs_get will perform a
169      <function>malloc(2)</function>
170      on the buffer for you. When a full buffer has been read, the size of
171      the package is returned (which will always be greater than 1). -1
172      indicates an error condition.
173     </para>
174
175     <para>
176      See also the <function>cs_more()</function> function below.
177     </para>
178
179     <synopsis>
180      int cs_more(COMSTACK handle);
181     </synopsis>
182
183     <para>
184      The <function>cs_more()</function> function should be used in conjunction
185      with <function>cs_get</function> and
186      <function>select(2)</function>.
187      The <function>cs_get()</function> function will sometimes
188      (notably in the TCP/IP mode) read more than a single protocol package
189      off the network. When this happens, the extra package is stored
190      by the subsystem. After calling <function>cs_get()</function>, and before
191      waiting for more input, You should always call
192      <function>cs_more()</function>
193      to check if there's a full protocol package already read. If
194      <function>cs_more()</function>
195      returns 1,
196      <function>cs_get()</function>
197      can be used to immediately fetch the new package. For the
198      mOSI
199      subsystem, the function should always return 0, but if you want your
200      stuff to be protocol independent, you should use it.
201     </para>
202
203     <note>
204      <para>
205       The <function>cs_more()</function>
206       function is required because the RFC1729-method
207       does not provide a way of separating individual PDUs, short of
208       partially decoding the BER. Some other implementations will carefully
209       nibble at the packet by calling
210       <function>read(2)</function>
211       several times. This was felt to be too inefficient (or at least
212       clumsy) - hence the call for this extra function.
213      </para>
214     </note>
215
216     <synopsis>
217      int cs_look(COMSTACK handle);
218     </synopsis>
219
220     <para>
221      This function is useful when you're operating in nonblocking
222      mode. Call it when
223      <function>select(2)</function>
224      tells you there's something happening on the line. It returns one of
225      the following values:
226     </para>
227
228     <variablelist>
229      <varlistentry><term>CS_NONE</term><listitem><para>
230         No event is pending. The data found on the line was not a complete package.
231        </para></listitem></varlistentry>
232
233      <varlistentry><term>CS_CONNECT</term><listitem><para>
234         A response to your connect request has been received. Call
235         <function>cs_rcvconnect</function>
236         to process the event and to finalize the connection establishment.
237        </para></listitem></varlistentry>
238
239      <varlistentry><term>CS_DISCON</term><listitem><para>
240         The other side has closed the connection (or maybe sent a disconnect
241         request - but do we care? Maybe later). Call
242         <function>cs_close</function> to close your end of the association as well.
243        </para></listitem></varlistentry>
244
245      <varlistentry><term>CS_LISTEN</term><listitem><para>
246         A connect request has been received. Call <function>cs_listen</function>
247         to process the event.
248        </para></listitem></varlistentry>
249
250      <varlistentry><term>CS_DATA</term><listitem><para>
251         There's data to be found on the line. Call <function>cs_get</function>
252         to get it.
253        </para></listitem></varlistentry>
254     </variablelist>
255
256     <note>
257      <para>
258       You should be aware that even if
259       <function>cs_look()</function>
260       tells you that there's an event event pending, the corresponding
261       function may still return and tell you there was nothing to be found.
262       This means that only part of a package was available for reading. The
263       same event will show up again, when more data has arrived.
264      </para>
265     </note>
266
267     <synopsis>
268      int cs_fileno(COMSTACK h);
269     </synopsis>
270
271     <para>
272      Returns the file descriptor of the association. Use this when
273      file-level operations on the endpoint are required
274      (<function>select(2)</function> operations, specifically).
275     </para>
276    </sect2>
277
278   </sect1>
279
280   <sect1 id="comstack.client"><title>Client Side</title>
281
282    <synopsis>
283     int cs_connect(COMSTACK handle, void *address);
284    </synopsis>
285
286    <para>
287     Initiate a connection with the target at <literal>address</literal>
288     (more onaddresses below). The function will return 0 on success, and 1 if
289     the operation does not complete immediately (this will only
290     happen on a nonblocking endpoint). In this case, use
291     <function>cs_rcvconnect</function> to complete the operation,
292     when <function>select(2)</function> reports input pending on the
293     association.
294    </para>
295
296    <synopsis>
297     int cs_rcvconnect(COMSTACK handle);
298    </synopsis>
299
300    <para>
301     Complete a connect operation initiated by <function>cs_connect()</function>.
302     It will return 0 on success; 1 if the operation has not yet completed (in
303     this case, call the function again later); -1 if an error has occurred.
304    </para>
305
306   </sect1>
307
308   <sect1 id="comstack.server"><title>Server Side</title>
309
310    <para>
311     To establish a server under the <application>inetd</application> server, you
312     can use
313    </para>
314
315    <synopsis>
316     COMSTACK cs_createbysocket(int socket, CS_TYPE type, int blocking,
317     int protocol);
318    </synopsis>
319
320    <para>
321     The <literal>socket</literal> parameter is an established socket (when
322     your application is invoked from <application>inetd</application>, the
323     socket will typically be 0.
324     The following parameters are identical to the ones for
325     <function>cs_create</function>.
326    </para>
327
328    <synopsis>
329     int cs_bind(COMSTACK handle, void *address, int mode)
330    </synopsis>
331
332    <para>
333     Binds a local address to the endpoint. Read about addresses below. The
334     <literal>mode</literal> parameter should be either
335     <literal>CS_CLIENT</literal> or <literal>CS_SERVER</literal>.
336    </para>
337
338    <synopsis>
339     int cs_listen(COMSTACK handle, char *addr, int *addrlen);
340    </synopsis>
341
342    <para>
343     Call this to process incoming events on an endpoint that has been
344     bound in listening mode. It will return 0 to indicate that the connect
345     request has been received, 1 to signal a partial reception, and -1 to
346     indicate an error condition.
347    </para>
348
349    <synopsis>
350     COMSTACK cs_accept(COMSTACK handle);
351    </synopsis>
352
353    <para>
354     This finalizes the server-side association establishment, after
355     cs_listen has completed successfully. It returns a new connection
356     endpoint, which represents the new association. The application will
357     typically wish to fork off a process to handle the association at this
358     point, and continue listen for new connections on the old
359     <literal>handle</literal>.
360    </para>
361
362    <para>
363     You can use the call
364    </para>
365
366    <synopsis>
367     char *cs_addrstr(COMSTACK);
368    </synopsis>
369
370    <para>
371     on an established connection to retrieve the host-name of the remote host.
372    </para>
373
374    <note>
375     <para>You may need to use this function with some care if your
376      name server service is slow or unreliable
377     </para>
378    </note>
379
380   </sect1>
381   <sect1 id="comstack.addresses"><title>Addresses</title>
382
383    <para>
384     The low-level format of the addresses are different depending on the
385     mode of communication you have chosen. A function is provided by each
386     of the lower layers to map a user-friendly string-form address to the
387     binary form required by the lower layers.
388    </para>
389
390    <synopsis>
391     struct sockaddr_in *tcpip_strtoaddr(char *str);
392
393     struct netbuf *mosi_strtoaddr(char *str);
394    </synopsis>
395
396    <para>
397     The format for TCP/IP addresses is straightforward:
398    </para>
399
400    <synopsis>
401     &lt;host> &lsqb; ':' &lt;portnum> &rsqb;
402    </synopsis>
403
404    <para>
405     The <literal>hostname</literal> can be either a domain name or an IP address.
406     The port number, if omitted, defaults to 210.
407    </para>
408
409    <para>
410     For OSI, the format is
411    </para>
412
413    <synopsis>
414     &lsqb; &lt;t-selector> '/' &rsqb; &lt;host> &lsqb; ':' &lt;port> &rsqb;
415    </synopsis>
416
417    <para>
418     The transport selector is given as an even number of hex digits.
419    </para>
420
421    <para>
422     You'll note that the address format for the OSI mode are just a subset
423     of full presentation addresses. We use presentation addresses because
424     xtimosi doesn't, in itself, allow access to the X.500 Directory
425     service. We use a limited form, because we haven't yet come across an
426     implementation that used more of the elements of a full p-address. It
427     is a fairly simple matter to add the rest of the elements to the
428     address format as needed, however: Xtimosi <emphasis>does</emphasis>
429     support the full P-address structure.
430    </para>
431
432    <para>
433     In both transport modes, the special hostname &quot;@&quot; is mapped
434     to any local address (the manifest constant <literal>INADDR_ANY</literal>).
435     It is used to establish local listening endpoints in the server role.
436    </para>
437
438    <para>
439     When a connection has been established, you can use
440    </para>
441
442    <synopsis>
443     char cs_addrstr(COMSTACK h);
444    </synopsis>
445
446    <para>
447     to retrieve the host name of the peer system. The function returns a pointer
448     to a static area, which is overwritten on the next call to the function.
449    </para>
450
451    <note>
452     <para>
453      We have left the issue of X.500 name-to-address mapping open, for the
454      moment. It would be a simple matter to provide a table-based mapping,
455      if desired. Alternately, we could use the X.500 client-function that
456      is provided with the ISODE (although this would defeat some of the
457      purpose of using ThinOSI in the first place. We have been told that it
458      should be within the realm of the possible to implement a lightweight
459      implementation of the necessary X.500 client capabilities on top of
460      ThinOSI. This would be the ideal solution, we feel. On the other hand, it
461      still remains to be seen just what role the Directory will play in a world
462      populated by ThinOSI and other pragmatic solutions.
463     </para>
464    </note>
465
466   </sect1>
467
468   <sect1 id="comstack.diagnostics"><title>Diagnostics</title>
469
470    <para>
471     All functions return -1 if an error occurs. Typically, the functions
472     will return 0 on success, but the data exchange functions
473     (<function>cs_get</function>, <function>cs_put</function>,
474     <function>cs_more</function>) follow special rules. Consult their
475     descriptions.
476    </para>
477
478    <para>
479     When a function (including the data exchange functions) reports an
480     error condition, use the function
481     <function>cs_errno()</function> to determine the cause of the
482     problem. The function
483    </para>
484
485    <synopsis>
486     void cs_perror(COMSTACK handle char *message);
487    </synopsis>
488
489    <para>
490     works like <function>perror(2)</function> and prints the
491     <literal>message</literal> argument, along with a system message, to
492     <literal>stderr</literal>. Use the character array
493    </para>
494
495    <synopsis>
496     extern const char *cs_errlist&lsqb;&rsqb;;
497    </synopsis>
498
499    <para>
500     to get hold of the message, if you want to process it differently.
501     The function
502    </para>
503
504    <synopsis>
505     const char *cs_stackerr(COMSTACK handle);
506    </synopsis>
507
508    <para>
509     Returns an error message from the lower layer, if one has been
510     provided.
511    </para>
512   </sect1>
513   <sect1 id="comstack.summary"><title>Summary and Synopsis</title>
514
515      <synopsis>
516     #include &lt;comstack.h>
517      
518     #include &lt;tcpip.h>      /* this is for TCP/IP support   */
519     #include &lt;xmosi.h>      /* and this is for mOSI support */
520      
521     COMSTACK cs_create(CS_TYPE type, int blocking, int protocol);
522      
523     COMSTACK cs_createbysocket(int s, CS_TYPE type, int blocking,
524                                int protocol);
525      
526     int cs_bind(COMSTACK handle, int mode);
527      
528     int cs_connect(COMSTACK handle, void *address);
529      
530     int cs_rcvconnect(COMSTACK handle);
531      
532     int cs_listen(COMSTACK handle);
533
534     COMSTACK cs_accept(COMSTACK handle);
535
536     int cs_put(COMSTACK handle, char *buf, int len);
537
538     int cs_get(COMSTACK handle, char **buf, int *size);
539
540     int cs_more(COMSTACK handle);
541
542     int cs_close(COMSTACK handle);
543
544     int cs_look(COMSTACK handle);
545
546     struct sockaddr_in *tcpip_strtoaddr(char *str);
547
548     struct netbuf *mosi_strtoaddr(char *str);
549
550     extern int cs_errno;
551
552     void cs_perror(COMSTACK handle char *message);
553
554     const char *cs_stackerr(COMSTACK handle);
555
556     extern const char *cs_errlist[];
557    </synopsis>
558   </sect1>
559
560  </chapter>
561
562  <!-- Keep this comment at the end of the file
563  Local variables:
564  mode: sgml
565  sgml-omittag:t
566  sgml-shorttag:t
567  sgml-minimize-attributes:nil
568  sgml-always-quote-attributes:t
569  sgml-indent-step:1
570  sgml-indent-data:t
571  sgml-parent-document: "yaz.xml"
572  sgml-local-catalogs: nil
573  sgml-namecase-general:t
574  End:
575  -->
576