1 <!-- $Id: comstack.xml,v 1.8 2002-05-22 11:19:20 adam Exp $ -->
2 <chapter id="comstack"><title>The COMSTACK Module</title>
4 <sect1 id="comstack.synopsis"><title>Synopsis (blocking mode)</title>
10 int size = 0, length_incoming;
11 char *protocol_package;
12 int protocol_package_length;
13 char server_address_str[] = "myserver.com:2100";
14 void *server_address_ip;
17 stack = cs_create(tcpip_type, 1, PROTO_Z3950);
19 perror("cs_create"); /* use perror() here since we have no stack yet */
23 server_address_ip = cs_addrstr (stack, server_address_str);
25 status = cs_connect(stack, server_address_ip);
27 cs_perror(stack, "cs_connect");
31 status = cs_put(stack, protocol_package, protocol_package_length);
33 cs_perror(stack, "cs_put");
37 /* Now get a response */
39 length_incoming = cs_get(stack, &buf, &size);
40 if (!length_incoming) {
41 fprintf(stderr, "Connection closed\n");
43 } else if (length_incoming < 0) {
44 cs_perror(stack, "cs_get");
48 /* Do stuff with buf here */
58 <sect1 id="comstack.introduction"><title>Introduction</title>
62 subsystem provides a transparent interface to different types of transport
63 stacks for the exchange of BER-encoded data. At present, the
64 RFC1729 method (BER over TCP/IP), and an experimental SSL stack
65 are supported, but others may be added in time. The philosophy of the
66 module is to provide a simple interface by hiding unused options and
67 facilities of the underlying libraries. This is always done at the risk
68 of losing generality, and it may prove that the interface will need
74 There hasn't been interest in the XTImOSI stack for some years.
75 Therefore, it is no longer supported.
80 The interface is implemented in such a fashion that only the
81 sub-layers constructed to the transport methods that you wish to
82 use in your application are linked in.
86 You will note that even though simplicity was a goal in the design,
87 the interface is still orders of magnitudes more complex than the
88 transport systems found in many other packages. One reason is that
89 the interface needs to support the somewhat different requirements of
90 the different lower-layer communications stacks; another important
91 reason is that the interface seeks to provide a more or less
92 industrial-strength approach to asynchronous event-handling.
93 When no function is allowed to block, things get more complex -
94 particularly on the server side.
95 We urge you to have a look at the demonstration client and server
96 provided with the package. They are meant to be easily readable and
97 instructive, while still being at least moderately useful.
101 <sect1 id="comstack.common"><title>Common Functions</title>
103 <sect2><title>Managing Endpoints</title>
106 COMSTACK cs_create(CS_TYPE type, int blocking, int protocol);
110 Creates an instance of the protocol stack - a communications endpoint.
111 The <literal>type</literal> parameter determines the mode
113 At present, the values
114 <literal>tcpip_type</literal>
116 <literal>ssl_type</literal>
117 are recognized. The function returns a null-pointer if a system error
118 occurs. The <literal>blocking</literal> parameter should be one if
119 you wish the association to operate in blocking mode, zero otherwise.
120 The <literal>protocol</literal> field should be
121 <literal>PROTO_Z3950</literal>.
122 Protocol <literal>PROTO_SR</literal> is no longer supported.
126 int cs_close(COMSTACK handle);
130 Closes the connection (as elegantly as the lower layers will permit),
131 and releases the resources pointed to by the
132 <literal>handle</literal>
134 <literal>handle</literal>
135 should not be referenced again after this call.
140 We really need a soft disconnect, don't we?
145 <sect2><title>Data Exchange</title>
148 int cs_put(COMSTACK handle, char *buf, int len);
153 <literal>buf</literal>
154 down the wire. In blocking mode, this function will return only when a
155 full buffer has been written, or an error has occurred. In nonblocking
156 mode, it's possible that the function will be unable to send the full
157 buffer at once, which will be indicated by a return value of 1. The
158 function will keep track of the number of octets already written; you
159 should call it repeatedly with the same values of <literal>buf</literal>
160 and <literal>len</literal>, until the buffer has been transmitted.
161 When a full buffer has been sent, the function will return 0 for
162 success. -1 indicates an error condition (see below).
166 int cs_get(COMSTACK handle, char **buf, int *size);
170 Receives a PDU from the peer. Returns the number of bytes
171 read. In nonblocking mode, it is possible that not all of the packet can be
172 read at once. In this case, the function returns 1. To simplify the
173 interface, the function is
174 responsible for managing the size of the buffer. It will be reallocated
175 if necessary to contain large packages, and will sometimes be moved
176 around internally by the subsystem when partial packages are read. Before
178 <function>cs_get</function>
179 for the fist time, the buffer can be initialized to the null pointer,
180 and the length should also be set to 0 - cs_get will perform a
181 <function>malloc(2)</function>
182 on the buffer for you. When a full buffer has been read, the size of
183 the package is returned (which will always be greater than 1). -1
184 indicates an error condition.
188 See also the <function>cs_more()</function> function below.
192 int cs_more(COMSTACK handle);
196 The <function>cs_more()</function> function should be used in conjunction
197 with <function>cs_get</function> and
198 <function>select(2)</function>.
199 The <function>cs_get()</function> function will sometimes
200 (notably in the TCP/IP mode) read more than a single protocol package
201 off the network. When this happens, the extra package is stored
202 by the subsystem. After calling <function>cs_get()</function>, and before
203 waiting for more input, You should always call
204 <function>cs_more()</function>
205 to check if there's a full protocol package already read. If
206 <function>cs_more()</function>
208 <function>cs_get()</function>
209 can be used to immediately fetch the new package. For the
211 subsystem, the function should always return 0, but if you want your
212 stuff to be protocol independent, you should use it.
217 The <function>cs_more()</function>
218 function is required because the RFC1729-method
219 does not provide a way of separating individual PDUs, short of
220 partially decoding the BER. Some other implementations will carefully
221 nibble at the packet by calling
222 <function>read(2)</function>
223 several times. This was felt to be too inefficient (or at least
224 clumsy) - hence the call for this extra function.
229 int cs_look(COMSTACK handle);
233 This function is useful when you're operating in nonblocking
235 <function>select(2)</function>
236 tells you there's something happening on the line. It returns one of
237 the following values:
241 <varlistentry><term>CS_NONE</term><listitem><para>
242 No event is pending. The data found on the line was not a
244 </para></listitem></varlistentry>
246 <varlistentry><term>CS_CONNECT</term><listitem><para>
247 A response to your connect request has been received. Call
248 <function>cs_rcvconnect</function>
249 to process the event and to finalize the connection establishment.
250 </para></listitem></varlistentry>
252 <varlistentry><term>CS_DISCON</term><listitem><para>
253 The other side has closed the connection (or maybe sent a disconnect
254 request - but do we care? Maybe later). Call
255 <function>cs_close</function> to close your end of the association
257 </para></listitem></varlistentry>
259 <varlistentry><term>CS_LISTEN</term><listitem><para>
260 A connect request has been received.
261 Call <function>cs_listen</function> to process the event.
262 </para></listitem></varlistentry>
264 <varlistentry><term>CS_DATA</term><listitem><para>
265 There's data to be found on the line.
266 Call <function>cs_get</function> to get it.
267 </para></listitem></varlistentry>
272 You should be aware that even if
273 <function>cs_look()</function>
274 tells you that there's an event event pending, the corresponding
275 function may still return and tell you there was nothing to be found.
276 This means that only part of a package was available for reading. The
277 same event will show up again, when more data has arrived.
282 int cs_fileno(COMSTACK h);
286 Returns the file descriptor of the association. Use this when
287 file-level operations on the endpoint are required
288 (<function>select(2)</function> operations, specifically).
294 <sect1 id="comstack.client"><title>Client Side</title>
297 int cs_connect(COMSTACK handle, void *address);
301 Initiate a connection with the target at <literal>address</literal>
302 (more on addresses below). The function will return 0 on success, and 1 if
303 the operation does not complete immediately (this will only
304 happen on a nonblocking endpoint). In this case, use
305 <function>cs_rcvconnect</function> to complete the operation,
306 when <function>select(2)</function> or <function>poll(2)</function>
307 reports input pending on the association.
311 int cs_rcvconnect(COMSTACK handle);
315 Complete a connect operation initiated by <function>cs_connect()</function>.
316 It will return 0 on success; 1 if the operation has not yet completed (in
317 this case, call the function again later); -1 if an error has occurred.
322 <sect1 id="comstack.server"><title>Server Side</title>
325 To establish a server under the <application>inetd</application>
330 COMSTACK cs_createbysocket(int socket, CS_TYPE type, int blocking,
335 The <literal>socket</literal> parameter is an established socket (when
336 your application is invoked from <application>inetd</application>, the
337 socket will typically be 0.
338 The following parameters are identical to the ones for
339 <function>cs_create</function>.
343 int cs_bind(COMSTACK handle, void *address, int mode)
347 Binds a local address to the endpoint. Read about addresses below. The
348 <literal>mode</literal> parameter should be either
349 <literal>CS_CLIENT</literal> or <literal>CS_SERVER</literal>.
353 int cs_listen(COMSTACK handle, char *addr, int *addrlen);
357 Call this to process incoming events on an endpoint that has been
358 bound in listening mode. It will return 0 to indicate that the connect
359 request has been received, 1 to signal a partial reception, and -1 to
360 indicate an error condition.
364 COMSTACK cs_accept(COMSTACK handle);
368 This finalizes the server-side association establishment, after
369 cs_listen has completed successfully. It returns a new connection
370 endpoint, which represents the new association. The application will
371 typically wish to fork off a process to handle the association at this
372 point, and continue listen for new connections on the old
373 <literal>handle</literal>.
381 char *cs_addrstr(COMSTACK);
385 on an established connection to retrieve the host-name of the remote host.
389 <para>You may need to use this function with some care if your
390 name server service is slow or unreliable
395 <sect1 id="comstack.addresses"><title>Addresses</title>
398 The low-level format of the addresses are different depending on the
399 mode of communication you have chosen. A function is provided by each
400 of the lower layers to map a user-friendly string-form address to the
401 binary form required by the lower layers.
405 void *cs_straddr(COMSTACK handle, const char *str);
409 The format for TCP/IP addresses is straightforward:
413 <host> [ ':' <portnum> ]
417 The <literal>hostname</literal> can be either a domain name or an
418 IP address. The port number, if omitted, defaults to 210.
422 In all transport modes, the special hostname "@" is mapped
423 to any local address (the manifest constant <literal>INADDR_ANY</literal>).
424 It is used to establish local listening endpoints in the server role.
428 When a connection has been established, you can use
432 char *cs_addrstr(COMSTACK h);
436 to retrieve the host name of the peer system. The function returns
437 a pointer to a static area, which is overwritten on the next call
442 A fairly recent addition to the &comstack; module is the utility
446 COMSTACK cs_create_host (const char *str, int blocking, void **vp);
449 which is just a wrapper for <function>cs_create</function> and
450 <function>cs_straddr</function>. The <parameter>str</parameter>
451 is similar to that described for <function>cs_straddr</function>
452 but with a prefix denoting the &comstack; type. Prefixes supported
453 are <literal>tcp:</literal> and <literal>ssl:</literal> for
454 TCP/IP and SSL respectively. If no prefix is given, then TCP/IP
455 is used. The <parameter>blocking</parameter> is passed to
456 function <function>cs_create</function>. The third parameter
457 <parameter>vp</parameter> is a pointer to &comstack; stack type
459 For SSL (ssl_type) <parameter>vp</parameter> is an already create
460 OpenSSL CTX. For TCP/IP <parameter>vp</parameter> is unused (can be
461 set to <literal>NULL</literal>.
466 <sect1 id="comstack.diagnostics"><title>Diagnostics</title>
469 All functions return -1 if an error occurs. Typically, the functions
470 will return 0 on success, but the data exchange functions
471 (<function>cs_get</function>, <function>cs_put</function>,
472 <function>cs_more</function>) follow special rules. Consult their
477 When a function (including the data exchange functions) reports an
478 error condition, use the function
479 <function>cs_errno()</function> to determine the cause of the
480 problem. The function
484 void cs_perror(COMSTACK handle char *message);
488 works like <function>perror(2)</function> and prints the
489 <literal>message</literal> argument, along with a system message, to
490 <literal>stderr</literal>. Use the character array
494 extern const char *cs_errlist[];
498 to get hold of the message, if you want to process it differently.
503 const char *cs_stackerr(COMSTACK handle);
507 Returns an error message from the lower layer, if one has been
511 <sect1 id="comstack.summary"><title>Summary and Synopsis</title>
514 #include <comstack.h>
516 #include <tcpip.h> /* this is for TCP/IP and SSL support */
518 COMSTACK cs_create(CS_TYPE type, int blocking, int protocol);
520 COMSTACK cs_createbysocket(int s, CS_TYPE type, int blocking,
522 COMSTACK cs_create_host (const char *str, int blocking,
525 int cs_bind(COMSTACK handle, int mode);
527 int cs_connect(COMSTACK handle, void *address);
529 int cs_rcvconnect(COMSTACK handle);
531 int cs_listen(COMSTACK handle);
533 COMSTACK cs_accept(COMSTACK handle);
535 int cs_put(COMSTACK handle, char *buf, int len);
537 int cs_get(COMSTACK handle, char **buf, int *size);
539 int cs_more(COMSTACK handle);
541 int cs_close(COMSTACK handle);
543 int cs_look(COMSTACK handle);
545 void *cs_straddr(COMSTACK handle, const char *str);
547 char *cs_addrstr(COMSTACK h);
551 void cs_perror(COMSTACK handle char *message);
553 const char *cs_stackerr(COMSTACK handle);
555 extern const char *cs_errlist[];
561 <!-- Keep this comment at the end of the file
566 sgml-minimize-attributes:nil
567 sgml-always-quote-attributes:t
570 sgml-parent-document: "yaz.xml"
571 sgml-local-catalogs: nil
572 sgml-namecase-general:t