source: trunk/gsdl/packages/yaz/doc/yaz-6.html@ 1343

Last change on this file since 1343 was 1343, checked in by johnmcp, 24 years ago

Added the YAZ toolkit source to the packages directory (for z39.50 stuff)

  • Property svn:keywords set to Author Date Id Revision
File size: 20.8 KB
Line 
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2<HTML>
3<HEAD>
4 <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
5 <TITLE>YAZ User's Guide and Reference: The COMSTACK Module</TITLE>
6 <LINK HREF="yaz-7.html" REL=next>
7 <LINK HREF="yaz-5.html" REL=previous>
8 <LINK HREF="yaz.html#toc6" REL=contents>
9</HEAD>
10<BODY>
11<A HREF="yaz-7.html">Next</A>
12<A HREF="yaz-5.html">Previous</A>
13<A HREF="yaz.html#toc6">Contents</A>
14<HR>
15<H2><A NAME="comstack"></A> <A NAME="s6">6. The COMSTACK Module</A></H2>
16
17<H2><A NAME="ss6.1">6.1 Introduction</A>
18</H2>
19
20<P>The <B>COMSTACK</B>
21subsystem provides a transparent interface to different types of transport
22stacks for the exchange of BER-encoded data. At present, the
23RFC1729 method (BER over TCP/IP), and Peter Furniss' XTImOSI
24stack are supported, but others may be added in time. The philosophy of the
25module is to provide a simple interface by hiding unused options and
26facilities of the underlying libraries. This is always done at the risk
27of losing generality, and it may prove that the interface will need
28extension later on.
29<P>The interface is implemented in such a fashion that only the
30sub-layers constructed to the transport methods that you wish to
31use in your application are linked in.
32<P>You will note that even though simplicity was a goal in the design,
33the interface is still orders of magnitudes more complex than the
34transport systems found in many other packages. One reason is that
35the interface needs to support the somewhat different requirements of
36the different lower-layer communications stacks; another important reason is
37that the interface seeks to provide a more or less industrial-strength
38approach to asynchronous event-handling. When no function is allowed
39to block, things get more complex - particularly on the server
40side. We urge you to have a look at the demonstration client and server
41provided with the package. They are meant to be easily readable and
42instructive, while still being at least moderately useful.
43<P>
44<H2><A NAME="ss6.2">6.2 Common Functions</A>
45</H2>
46
47<H3>Managing Endpoints</H3>
48
49<P>
50<BLOCKQUOTE><CODE>
51<PRE>
52COMSTACK cs_create(CS_TYPE type, int blocking, int protocol);
53</PRE>
54</CODE></BLOCKQUOTE>
55<P>Creates an instance of the protocol stack - a communications endpoint.
56The
57<CODE>type</CODE>
58parameter determines the mode of communication. At present, the
59values
60<CODE>tcpip_type</CODE>
61and
62<CODE>mosi_type</CODE>
63are recognized. The function returns a null-pointer if a system error
64occurs. The <CODE>blocking</CODE> parameter should be one if you wish the
65association to operate in blocking mode, zero otherwise. The
66<CODE>protocol</CODE> field should be one of <CODE>PROTO_SR</CODE> or <CODE>PROTO_Z3950</CODE>.
67<P>
68<BLOCKQUOTE><CODE>
69<PRE>
70int cs_close(COMSTACK handle);
71</PRE>
72</CODE></BLOCKQUOTE>
73<P>Closes the connection (as elegantly as the lower layers will permit),
74and releases the resouces pointed to by the
75<CODE>handle</CODE>
76parameter. The
77<CODE>handle</CODE>
78should not be referenced again after this call.
79<P><I>NOTE:
80We really need a soft disconnect, don't we?</I>
81<P>
82<H3>Data Exchange</H3>
83
84<P>
85<BLOCKQUOTE><CODE>
86<PRE>
87int cs_put(COMSTACK handle, char *buf, int len);
88</PRE>
89</CODE></BLOCKQUOTE>
90<P>Sends
91<CODE>buf</CODE>
92down the wire. In blocking mode, this function will return only when a
93full buffer has been written, or an error has occurred. In nonblocking
94mode, it's possible that the function will be unable to send the full
95buffer at once, which will be indicated by a return value of 1. The
96function will keep track of the number of octets already written; you
97should call it repeatedly with the same values of <CODE>buf</CODE> and
98<CODE>len</CODE>, until the buffer has been transmitted. When a full buffer
99has been sent, the function will return 0 for success. -1 indicates
100an error condition (see below).
101<P>
102<BLOCKQUOTE><CODE>
103<PRE>
104int cs_get(COMSTACK handle, char **buf, int *size);
105</PRE>
106</CODE></BLOCKQUOTE>
107<P>Receives a PDU from the peer. Returns the number of bytes
108read. In nonblocking mode, it is possible that not all of the packet can be
109read at once. In this case, the function returns 1. To simplify the
110interface, the function is
111responsible for managing the size of the buffer. It will be reallocated
112if necessary to contain large packages, and will sometimes be moved
113around internally by the subsystem when partial packages are read. Before
114calling
115<CODE>cs_get</CODE>
116for the fist time, the buffer can be initialized to the null pointer,
117and the length should also be set to 0 - cs_get will perform a
118<CODE>malloc</CODE>(2)
119on the buffer for you. When a full buffer has been read, the size of
120the package is returned (which will always be greater than 1). -1
121indicates an error condition.
122<P>See also the
123<CODE>cs_more()</CODE>
124function below.
125<P>
126<BLOCKQUOTE><CODE>
127<PRE>
128int cs_more(COMSTACK handle);
129</PRE>
130</CODE></BLOCKQUOTE>
131<P>The <CODE>cs_more()</CODE> function should be used in conjunction with
132<CODE>cs_get</CODE>
133and
134<CODE>select</CODE>(2).
135The <CODE>cs_get()</CODE> function will sometimes (notably in the TCP/IP mode) read
136more than a single protocol package off the network. When this
137happens, the extra package is stored by the subsystem. After calling
138<CODE>cs_get()</CODE>, and before waiting for more input,
139You should always call
140<CODE>cs_more()</CODE>
141to check if there's a full protocol package already read. If
142<CODE>cs_more()</CODE>
143returns 1,
144<CODE>cs_get()</CODE>
145can be used to immediately fetch the new package. For the
146mOSI
147subsystem, the function should always return 0, but if you want your
148stuff to be protocol independent, you should use it.
149<P><I>NOTE: The <CODE>cs_more()</CODE>
150function is required because the
151RFC1729-method
152does not provide a way of separating individual PDUs, short of
153partially decoding the BER. Some other implementations will carefully
154nibble at the packet by calling
155<CODE>read</CODE>(2)
156several times. This was felt to be too inefficient (or at least
157clumsy) - hence the call for this extra function.</I>
158<P>
159<BLOCKQUOTE><CODE>
160<PRE>
161int cs_look(COMSTACK handle);
162</PRE>
163</CODE></BLOCKQUOTE>
164<P>This function is useful when you're operating in nonblocking
165mode. Call it when
166<CODE>select</CODE>(2)
167tells you there's something happening on the line. It returns one of
168the following values:
169<P>
170<DL>
171<DT><B>CS_NONE</B><DD><P>No event is pending. The data found on the line was
172not a complete package.
173<DT><B>CS_CONNECT</B><DD><P>A response to your connect request has been received. Call
174<CODE>cs_rcvconnect</CODE>
175to process the event and to finalize the connection establishment.
176<DT><B>CS_DISCON</B><DD><P>The other side has closed the connection (or maybe
177sent a disconnect
178request - but do we care? Maybe later). Call
179<CODE>cs_close</CODE> To close your end of the association as well.
180<DT><B>CS_LISTEN</B><DD><P>A connect request has been received. Call
181<CODE>cs_listen</CODE>
182to process the event.
183<DT><B>CS_DATA</B><DD><P>There's data to be found on the line. Call
184<CODE>cs_get</CODE>
185to get it.
186</DL>
187<P><I>NOTE:
188You should be aware that even if
189<CODE>cs_look()</CODE>
190tells you that there's an event event pending, the corresponding
191function may still return and tell you there was nothing to be found.
192This means that only part of a package was available for reading. The
193same event will show up again, when more data has arrived.</I>
194<P>
195<BLOCKQUOTE><CODE>
196<PRE>
197int cs_fileno(COMSTACK h);
198</PRE>
199</CODE></BLOCKQUOTE>
200<P>Returns the file descriptor of the association. Use this when
201file-level operations on the endpoint are required (<CODE>select</CODE>(2)
202operations, specifically).
203<P>
204<H2><A NAME="ss6.3">6.3 Client Side</A>
205</H2>
206
207<P>
208<BLOCKQUOTE><CODE>
209<PRE>
210int cs_connect(COMSTACK handle, void *address);
211</PRE>
212</CODE></BLOCKQUOTE>
213<P>Initiate a connection with the target at <CODE>address</CODE> (more on
214addresses below). The function will return 0 on success, and 1 if
215the operation does not complete immediately (this will only
216happen on a nonblocking endpoint). In this case, use
217<CODE>cs_rcvconnect</CODE> to complete the operation, when <CODE>select</CODE>(2)
218reports input pending on the association.
219<P>
220<BLOCKQUOTE><CODE>
221<PRE>
222int cs_rcvconnect(COMSTACK handle);
223</PRE>
224</CODE></BLOCKQUOTE>
225<P>Complete a connect operation initiated by <CODE>cs_connect()</CODE>. It will
226return 0 on success; 1 if the operation has not yet completed (in this
227case, call the function again later); -1 if an error has occured.
228<P>
229<H2><A NAME="ss6.4">6.4 Server Side</A>
230</H2>
231
232<P>To establish a server under the <CODE>inetd</CODE> server, you can use
233<P>
234<BLOCKQUOTE><CODE>
235<PRE>
236COMSTACK cs_createbysocket(int socket, CS_TYPE type, int blocking,
237 int protocol);
238</PRE>
239</CODE></BLOCKQUOTE>
240<P>The <I>socket</I> parameter is an established socket (when your
241application is invoked from <CODE>inetd</CODE>, the socket will typically be
2420. The following parameters are identical to the ones for
243<CODE>cs_create</CODE>.
244<P>
245<BLOCKQUOTE><CODE>
246<PRE>
247int cs_bind(COMSTACK handle, void *address, int mode)
248</PRE>
249</CODE></BLOCKQUOTE>
250<P>Binds a local address to the endpoint. Read about addresses below. The
251<CODE>mode</CODE> parameter should be either <CODE>CS_CLIENT</CODE> or <CODE>CS_SERVER</CODE>.
252<P>
253<BLOCKQUOTE><CODE>
254<PRE>
255int cs_listen(COMSTACK handle, char *addr, int *addrlen);
256</PRE>
257</CODE></BLOCKQUOTE>
258<P>Call this to process incoming events on an endpoint that has been
259bound in listening mode. It will return 0 to indicate that the connect
260request has been received, 1 to signal a partial reception, and -1 to
261indicate an error condition.
262<P>
263<BLOCKQUOTE><CODE>
264<PRE>
265COMSTACK cs_accept(COMSTACK handle);
266</PRE>
267</CODE></BLOCKQUOTE>
268<P>This finalises the server-side association establishment, after
269cs_listen has completed successfully. It returns a new connection
270endpoint, which represents the new association. The application will
271typically wish to fork off a process to handle the association at this
272point, and continue listen for new connections on the old <CODE>handle</CODE>.
273<P>You can use the call
274<P>
275<BLOCKQUOTE><CODE>
276<PRE>
277char *cs_addrstr(COMSTACK);
278</PRE>
279</CODE></BLOCKQUOTE>
280<P>on an established connection to retrieve the hostname of the remote host.
281<P><I>NOTE: You may need to use this function with some care if your
282name server service is slow or unreliable</I>
283<P>
284<H2><A NAME="ss6.5">6.5 Addresses</A>
285</H2>
286
287<P>The low-level format of the addresses are different depending on the
288mode of communication you have chosen. A function is provided by each
289of the lower layers to map a user-friendly string-form address to the
290binary form required by the lower layers.
291<P>
292<BLOCKQUOTE><CODE>
293<PRE>
294struct sockaddr_in *tcpip_strtoaddr(char *str);
295
296struct netbuf *mosi_strtoaddr(char *str);
297</PRE>
298</CODE></BLOCKQUOTE>
299<P>The format for TCP/IP addresses is straightforward:
300<P>
301<BLOCKQUOTE><CODE>
302<PRE>
303&lt;host> [ ':' &lt;portnum> ]
304</PRE>
305</CODE></BLOCKQUOTE>
306<P>The <CODE>hostname</CODE> can be either a domain name or an IP address. The
307port number, if omitted, defaults to 210.
308<P>For OSI, the format is
309<P>
310<BLOCKQUOTE><CODE>
311<PRE>
312[ &lt;t-selector> '/' ] &lt;host> [ ':' &lt;port> ]
313</PRE>
314</CODE></BLOCKQUOTE>
315<P>The transport selector is given as an even number of hex digits.
316<P>You'll note that the address format for the OSI mode are just a subset
317of full presentation addresses. We use presentation addresses because
318xtimosi doesn't, in itself, allow access to the X.500 Directory
319service. We use a limited form, because we haven't yet come across an
320implementation that used more of the elements of a full p-address. It
321is a fairly simple matter to add the rest of the elements to the
322address format as needed, however: Xtimosi <I>does</I> support the full
323P-address structure.
324<P>In both transport modes, the special hostname &quot;@&quot; is mapped
325to any local address (the manifest constant INADDR_ANY). It is used
326to establish local listening endpoints in the server role.
327<P>When a connection has been established, you can use
328<P>
329<BLOCKQUOTE><CODE>
330<PRE>
331char cs_addrstr(COMSTACK h);
332</PRE>
333</CODE></BLOCKQUOTE>
334<P>to retrieve the host name of the peer system. The function returns a pointer
335to a static area, which is overwritten on the next call to the function.
336<P><I>NOTE: We have left the issue of X.500 name-to-address mapping open, for the
337moment. It would be a simple matter to provide a table-based mapping,
338if desired. Alternately, we could use the X.500 client-function that
339is provided with the ISODE (although this would defeat some of the
340purpose of using ThinOSI in the first place. We have been told that it
341should be within the realm of the possible to implement a lightweight
342implementation of the necessary X.500 client capabilities on top of
343ThinOSI. This would be the ideal solution, we feel. On the other hand, it
344still remains to be seen just what role the Directory will play in a world
345populated by ThinOSI and other pragmatic solutions.</I>
346<P>
347<H2><A NAME="ss6.6">6.6 Diagnostics</A>
348</H2>
349
350<P>All functions return -1 if an error occurs. Typically, the functions
351will return 0 on success, but the data exchange functions
352(<CODE>cs_get</CODE>, <CODE>cs_put</CODE>, <CODE>cs_more</CODE>)
353follow special rules. Consult their descriptions.
354<P>When a function (including the data exchange functions) reports an
355error condition,
356use the function
357<CODE>cs_errno()</CODE>
358to determine the cause of the
359problem. The function
360<P>
361<BLOCKQUOTE><CODE>
362<PRE>
363void cs_perror(COMSTACK handle char *message);
364</PRE>
365</CODE></BLOCKQUOTE>
366<P>works like
367<CODE>perror</CODE>(2)
368and prints the
369<CODE>message</CODE>
370argument, along with a system message, to
371<CODE>stderr</CODE>.
372Use the character array
373<P>
374<BLOCKQUOTE><CODE>
375<PRE>
376extern const char *cs_errlist[];
377</PRE>
378</CODE></BLOCKQUOTE>
379<P>to get hold of the message, if you want to process it differently.
380The function
381<P>
382<BLOCKQUOTE><CODE>
383<PRE>
384const char *cs_stackerr(COMSTACK handle);
385</PRE>
386</CODE></BLOCKQUOTE>
387<P>Returns an error message from the lower layer, if one has been
388provided.
389<P>
390<H2><A NAME="ss6.7">6.7 Enabling OSI Communication</A>
391</H2>
392
393<H3>Installing Xtimosi</H3>
394
395<P>Although you will have to download Peter Furniss' XTI/mOSI
396implementation for yourself, we've tried to make the integration as
397simple as possible.
398<P>The latest version of xtimosi will generally be under
399<P>
400<BLOCKQUOTE><CODE>
401<PRE>
402ftp://pluto.ulcc.ac.uk/ulcc/thinosi/xtimosi/
403</PRE>
404</CODE></BLOCKQUOTE>
405<P>When you have downloaded and unpacked the archive, it will (we assume)
406have created a directory called <CODE>xtimosi</CODE>. We suggest that you place
407this directory <I>in the same directory</I> where you unpacked the
408<B>YAZ</B>
409distribution. This way, you shouldn't have to fiddle with the
410makefiles of <CODE>YAZ</CODE> beyond uncommenting a few lines.
411<P>Go to <CODE>xtimosi/src</CODE>, and type &quot;<CODE>make libmosi.a</CODE>&quot;.
412This should generally
413create the library, ready to use.
414<P><B>CAVEAT</B>
415<P><I>The currently available release of xtimosi has some inherent
416problems that make it disfunction on certain platforms - eg. the
417Digital OSF/1 workstations. It is supposedly primarily a
418compiler problem, and we hope to see a release that is generally
419portable. While we can't guarantee that it can be brought to work
420on your platform, we'll be happy to talk to you about problems
421that you might see, and relay information to the author of the
422software. There are some signs that the <B>gcc</B> compiler is more
423likely to produce a fully functional library, but this hasn't
424been verified (we think that the problem is limited to the use
425of hexadecimal escape-codes used in strings, which are silently
426ignored by some compilers).</I>
427<P><I>A problem has been encountered in the communication with
428ISODE-based applications. If the ISODE presentation-user calls
429<CODE>PReadRequest()</CODE> with a timeout value different from <CODE>OK</CODE> or <CODE>NOTOK</CODE>,
430he will get an immediate TIMEOUT abort when receiving large (&gt;2041
431bytes, which is the SPDU-size that the ISODE likes to work with) packages
432from an xtimosi-based implementation (probably most
433other implementations as well, in fact). It seems to be a flaw in the
434ISODE API, and the workaround (for ISODE users) is to either not
435use an explicit timeout (switching to either blocking or
436nonblocking mode), or to check that the timer really has expired
437before closing the connection.</I>
438<P>The next step in the installation is to modify the makefile in the toplevel
439<B>YAZ</B>
440directory. The place to change is in the top of the file, and is
441clearly marked with a comment.
442<P>Now run <CODE>make</CODE> in the <B>YAZ</B> toplevel directory (do a
443&quot;<CODE>make clean</CODE>&quot; first, if the
444system has been previously made without OSI support). Use the <B>YAZ</B>
445<B>ztest</B>
446and <B>client</B> demo programs to verify that OSI communication works OK. Then,
447you can go ahead and try to talk to other implementations.
448<P><I>NOTE: Our interoperability experience is limited to version
4497 of the Nordic SR-Nett package, which has had several
450protocol errors fixed from the earlier releases. If you have
451problems or successes in interoperating with other
452implementations, we'd be glad to hear about it, or to help
453you make things work, as our resources allow.</I>
454<P>If you write your own applications based on <B>YAZ</B>, and you wish to
455include OSI support, the procedure is equally simple. You should
456include the <CODE>xmosi.h</CODE> header file in addition to <CODE>comstack.h</CODE>.
457<CODE>xmosi.h</CODE>
458will define the manifest constant <CODE>mosi_type</CODE>, which you should pass
459to the <CODE>cs_create()</CODE> function. In
460addition, you should use the function <CODE>mosi_strtoaddr()</CODE> rather than
461<CODE>tcpip_strtoaddr()</CODE> when you need to prepare an address.
462<P>When you link your application, you should include (after the
463<CODE>libyaz.a</CODE>
464library) the <CODE>libmosi.a</CODE> library, and the <CODE>librfc.a</CODE> library
465provided with
466<B>YAZ</B> (for OSI transport).
467<P>As always, it can be very useful, if not essential, to have a look at the
468example applications
469to see how things are done.
470<P>
471<H3>OSI Transport</H3>
472
473<P>Xtimosi requires an implementation of the OSI transport service under
474the X/OPEN XTI API. We provide an implementation of the RFC1006
475encapsulation of OSI/TP0 in TCP/IP (through the Berkeley Sockets API),
476as an independent part of <B>YAZ</B> (it's found under the <CODE>rfc1006</CODE>
477directory). If you have access to an OSI transport provider under XTI,
478you should be able to make that work too, although it may require
479tinkering with the <CODE>mosi_strtoaddr()</CODE> function.
480<P>
481<H3>Presentation Context Management</H3>
482
483<P>To simplify the implementation, we use Peter Furniss' alternative (PRF)
484option format
485for the Control of the presentation negotiation phase. This format
486is enabled by default when you
487compile xtimosi.
488<P>The current version of <B>YAZ</B> does <I>not</I> support presentation-layer
489negotiation of response record formats. The primary reason is that we
490have had access to no other SR or Z39.50 implementations over OSI that
491used this
492method. Secondarily, we believe that the EXPLAIN facility is a superior
493mechanism for relaying target capabilities in this respect. This is not to
494say that we have no intentions of supporting presentation context
495negotiation - we have just hitherto given it a lower priority than other
496aspects of the protocol.
497<P>One thing is certain: The addition of this capability to <B>YAZ</B> should
498have only a minimal impact on existing applications, and on the
499interface to the software in general. Most likely, we will add an extra
500layer of interface to the processing of EXPLAIN records, which will
501convert back and forth between <CODE>oident</CODE> records (see section
502<A HREF="yaz-3.html#oid">Object Identifiers</A>) and direct or indirect
503references, given the current association setup. Implementations based
504on any of the higher-level interfaces will most likely not have to be
505changed at all.
506<P>
507<H2><A NAME="ss6.8">6.8 Summary and Synopsis</A>
508</H2>
509
510<P>
511<BLOCKQUOTE><CODE>
512<PRE>
513#include &lt;comstack.h>
514
515#include &lt;tcpip.h> /* this is for TCP/IP support */
516#include &lt;xmosi.h> /* and this is for mOSI support */
517
518COMSTACK cs_create(CS_TYPE type, int blocking, int protocol);
519
520COMSTACK cs_createbysocket(int s, CS_TYPE type, int blocking,
521 int protocol);
522
523int cs_bind(COMSTACK handle, int mode);
524
525int cs_connect(COMSTACK handle, void *address);
526
527int cs_rcvconnect(COMSTACK handle);
528
529int cs_listen(COMSTACK handle);
530
531COMSTACK cs_accept(COMSTACK handle);
532
533int cs_put(COMSTACK handle, char *buf, int len);
534
535int cs_get(COMSTACK handle, char **buf, int *size);
536
537int cs_more(COMSTACK handle);
538
539int cs_close(COMSTACK handle);
540
541int cs_look(COMSTACK handle);
542
543struct sockaddr_in *tcpip_strtoaddr(char *str);
544
545struct netbuf *mosi_strtoaddr(char *str);
546
547extern int cs_errno;
548
549void cs_perror(COMSTACK handle char *message);
550
551const char *cs_stackerr(COMSTACK handle);
552
553extern const char *cs_errlist[];
554</PRE>
555</CODE></BLOCKQUOTE>
556<P>
557<HR>
558<A HREF="yaz-7.html">Next</A>
559<A HREF="yaz-5.html">Previous</A>
560<A HREF="yaz.html#toc6">Contents</A>
561</BODY>
562</HTML>
Note: See TracBrowser for help on using the repository browser.