Emacs indent of XML-documentation. Only minor changes in contents.
[yaz-moved-to-github.git] / doc / comstack.xml
1 <!-- $Id: comstack.xml,v 1.2 2001-07-19 23:29:40 adam Exp $ -->
2  <chapter><title id="comstack">The COMSTACK Module</title>
3
4   <sect1><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><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><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 resouces 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 callig <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><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 occured.
304    </para>
305
306   </sect1>
307
308   <sect1><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 finalises 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 hostname 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><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><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
514   <sect1><title>Enabling OSI Communication</title>
515
516    <sect2><title>Installing Xtimosi</title>
517     <para>
518      Although you will have to download Peter Furniss' XTI/mOSI
519      implementation for yourself, we've tried to make the integration as
520      simple as possible.
521     </para>
522
523     <para>
524      The latest version of xtimosi will generally be under
525     </para>
526
527     <screen>
528      ftp://pluto.ulcc.ac.uk/ulcc/thinosi/xtimosi/
529     </screen>
530
531     <para>
532      When you have downloaded and unpacked the archive, it will (we assume)
533      have created a directory called <literal>xtimosi</literal>.
534      We suggest that you place this directory <emphasis>in the same
535       directory</emphasis> where you unpacked the &yaz;
536      distribution. This way, you shouldn't have to fiddle with the
537      makefiles of &yaz; beyond uncommenting a few lines.
538     </para>
539
540     <para>
541      Go to <literal>xtimosi/src</literal>, and type &quot;make libmosi.a/&quot;.
542      This should generally create the library, ready to use.
543     </para>
544
545     <note>
546      <para>
547       The currently available release of xtimosi has some inherent
548       problems that make it disfunction on certain platforms - eg. the
549       Digital OSF/1 workstations. It is supposedly primarily a
550       compiler problem, and we hope to see a release that is generally
551       portable. While we can't guarantee that it can be brought to work
552       on your platform, we'll be happy to talk to you about problems
553       that you might see, and relay information to the author of the
554       software. There are some signs that the <application>gcc</application>
555       compiler is more likely to produce a fully functional library, but this
556       hasn't been verified (we think that the problem is limited to the use
557       of hexadecimal escape-codes used in strings, which are silently
558       ignored by some compilers).
559      </para>
560      <para>
561       A problem has been encountered in the communication with
562       ISODE-based applications. If the ISODE presentation-user calls
563       <function>PReadRequest()</function> with a timeout value different
564       from <literal>OK</literal> or <literal>NOTOK</literal>,
565       he will get an immediate TIMEOUT abort when receiving large (&gt;2041
566       bytes, which is the SPDU-size that the ISODE likes to work with) packages
567       from an xtimosi-based implementation (probably most
568       other implementations as well, in fact). It seems to be a flaw in the
569       ISODE API, and the workaround (for ISODE users) is to either not
570       use an explicit timeout (switching to either blocking or
571       nonblocking mode), or to check that the timer really has expired
572       before closing the connection.
573      </para>
574     </note>
575
576     <para>
577      The next step in the installation is to modify the makefile in the toplevel
578      &yaz;
579      directory. The place to change is in the top of the file, and is
580      clearly marked with a comment.
581     </para>
582
583     <para>
584      Now run <literal>make</literal> in the &yaz; toplevel directory (do a
585      <literal>make clean</literal> first, if the system has been previously
586      made without OSI support). Use the &yaz;
587      <application>yaz-ztest</application> and <application>yaz-client</application>
588      demo programs to verify that OSI communication works OK. Then, you can go
589      ahead and try to talk to other implementations.
590     </para>
591
592     <note>
593      <para>
594       Our interoperability experience is limited to version
595       7 of the Nordic SR-Nett package, which has had several
596       protocol errors fixed from the earlier releases. If you have
597       problems or successes in interoperating with other
598       implementations, we'd be glad to hear about it, or to help
599       you make things work, as our resources allow.
600      </para>
601     </note>
602
603     <para>
604      If you write your own applications based on &yaz;, and you wish to
605      include OSI support, the procedure is equally simple. You should
606      include the <filename>xmosi.h</filename> header file in addition to
607      <filename>comstack.h</filename>. <filename>xmosi.h</filename>
608      will define the manifest constant <literal>mosi_type</literal>, which you
609      should pass to the <function>cs_create()</function> function. In
610      addition, you should use the function <function>mosi_strtoaddr()</function>
611      rather than <function>tcpip_strtoaddr()</function> when you need to
612      prepare an address.
613     </para>
614
615     <para>
616      When you link your application, you should include (after the
617      <filename>libyaz.a</filename> library) the <literal>libmosi.a</literal>
618      library, and the <filename>librfc.a</filename> library provided with
619      &yaz; (for OSI transport).
620     </para>
621     <para>
622      As always, it can be very useful, if not essential, to have a look at the
623      example applications to see how things are done.
624     </para>
625
626    </sect2>
627    <sect2><title>OSI Transport</title>
628
629     <para>
630      Xtimosi requires an implementation of the OSI transport service under
631      the X/OPEN XTI API. We provide an implementation of the RFC1006
632      encapsulation of OSI/TP0 in TCP/IP (through the Berkeley Sockets API),
633      as an independent part of &yaz; (it's found under the
634      <filename>rfc1006</filename> directory).
635      If you have access to an OSI transport provider under XTI,
636      you should be able to make that work too, although it may require
637      tinkering with the <function>mosi_strtoaddr()</function> function.
638     </para>
639    </sect2>
640
641    <sect2><title>Presentation Context Management</title>
642
643     <para>
644      To simplify the implementation, we use Peter Furniss' alternative (PRF)
645      option format
646      for the Control of the presentation negotiation phase. This format
647      is enabled by default when you
648      compile xtimosi.
649     </para>
650
651     <para>
652      The current version of &yaz; does <emphasis>not</emphasis> support
653      presentation-layer negotiation of response record formats. The primary
654      reason is that we have had access to no other SR or Z39.50
655      implementations over OSI that used this
656      method. Secondarily, we believe that the EXPLAIN facility is a superior
657      mechanism for relaying target capabilities in this respect. This is not to
658      say that we have no intentions of supporting presentation context
659      negotiation - we have just hitherto given it a lower priority than other
660      aspects of the protocol.
661     </para>
662     <para>
663      One thing is certain: The addition of this capability to &yaz; should
664      have only a minimal impact on existing applications, and on the
665      interface to the software in general. Most likely, we will add an extra
666      layer of interface to the processing of EXPLAIN records, which will
667      convert back and forth between <literal>oident</literal> records (see
668      section <link linkend="oid">Object Identifiers</link>) and direct or
669      indirect references, given the current association setup. Implementations
670      based on any of the higher-level interfaces will most likely not have to
671      be changed at all.
672     </para>
673    </sect2>
674   </sect1>
675   <sect1><title>Summary and Synopsis</title>
676
677      <synopsis>
678     #include &lt;comstack.h>
679      
680     #include &lt;tcpip.h>      /* this is for TCP/IP support   */
681     #include &lt;xmosi.h>      /* and this is for mOSI support */
682      
683     COMSTACK cs_create(CS_TYPE type, int blocking, int protocol);
684      
685     COMSTACK cs_createbysocket(int s, CS_TYPE type, int blocking,
686                                int protocol);
687      
688     int cs_bind(COMSTACK handle, int mode);
689      
690     int cs_connect(COMSTACK handle, void *address);
691      
692     int cs_rcvconnect(COMSTACK handle);
693      
694     int cs_listen(COMSTACK handle);
695
696     COMSTACK cs_accept(COMSTACK handle);
697
698     int cs_put(COMSTACK handle, char *buf, int len);
699
700     int cs_get(COMSTACK handle, char **buf, int *size);
701
702     int cs_more(COMSTACK handle);
703
704     int cs_close(COMSTACK handle);
705
706     int cs_look(COMSTACK handle);
707
708     struct sockaddr_in *tcpip_strtoaddr(char *str);
709
710     struct netbuf *mosi_strtoaddr(char *str);
711
712     extern int cs_errno;
713
714     void cs_perror(COMSTACK handle char *message);
715
716     const char *cs_stackerr(COMSTACK handle);
717
718     extern const char *cs_errlist[];
719    </synopsis>
720   </sect1>
721
722  </chapter>
723
724  <!-- Keep this comment at the end of the file
725  Local variables:
726  mode: sgml
727  sgml-omittag:t
728  sgml-shorttag:t
729  sgml-minimize-attributes:nil
730  sgml-always-quote-attributes:t
731  sgml-indent-step:1
732  sgml-indent-data:t
733  sgml-parent-document: "yaz.xml"
734  sgml-local-catalogs: "../../docbook/docbook.cat"
735  sgml-namecase-general:t
736  End:
737  -->
738