source: trunk/gsdl/packages/yaz/doc/yaz.txt@ 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: 124.7 KB
Line 
1 YAZ User's Guide and Reference
2 Index Data, [email protected]
3 $Revision: 1343 $
4
5 This document is the programmer's guide and reference to the YAZ pack-
6 age. YAZ is a compact toolkit that provides access to the Z39.50/SR
7 protocol, as well as a set of higher-level tools for implementing the
8 server and client roles, respectively. The documentation can be used
9 on its own, or as a reference when looking at the example applications
10 provided with the package.
11 ______________________________________________________________________
12
13 Table of Contents
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 1. Introduction
68
69 2. Compilation and Installation
70
71 2.1 UNIX
72 2.2 WIN32
73
74 3. The ASN Module
75
76 3.1 Introduction
77 3.2 Preparing PDUs
78 3.3 Object Identifiers
79 3.4 EXTERNAL Data
80 3.5 PDU Contents Table
81
82 4. Supporting Tools
83
84 4.1 Query Syntax Parsers
85 4.1.1 Prefix Query Format
86 4.1.2 Common Command Language
87 4.1.2.1 CCL Syntax
88 4.1.2.2 CCL Qualifiers
89 4.1.2.3 CCL API
90 4.2 Object Identifiers
91 4.3 Nibble Memory
92
93 5. The ODR Module
94
95 5.1 Introduction
96 5.2 Using ODR
97 5.2.1 ODR Streams
98 5.2.2 Memory Management
99 5.2.3 Encoding and Decoding Data
100 5.2.4 Diagnostics
101 5.2.5 Summary and Synopsis
102 5.3 Programming with ODR
103 5.3.1 The Primitive ASN.1 Types
104 5.3.1.1 INTEGER
105 5.3.1.2 BOOLEAN
106 5.3.1.3 REAL
107 5.3.1.4 NULL
108 5.3.1.5 OCTET STRING
109 5.3.1.6 BIT STRING
110 5.3.1.7 OBJECT IDENTIFIER
111 5.3.2 Tagging Primitive Types
112 5.3.3 Constructed Types
113 5.3.4 Tagging Constructed Types
114 5.3.4.1 Implicit Tagging
115 5.3.4.2 Explicit Tagging
116 5.3.5 SEQUENCE OF
117 5.3.6 CHOICE Types
118 5.4 Debugging
119
120 6. The COMSTACK Module
121
122 6.1 Introduction
123 6.2 Common Functions
124 6.2.1 Managing Endpoints
125 6.2.2 Data Exchange
126 6.3 Client Side
127 6.4 Server Side
128 6.5 Addresses
129 6.6 Diagnostics
130 6.7 Enabling OSI Communication
131 6.7.1 Installing Xtimosi
132 6.7.2 OSI Transport
133 6.7.3 Presentation Context Management
134 6.8 Summary and Synopsis
135
136 7. Making an IR Interface for Your Database with YAZ
137
138 7.1 Introduction
139 7.2 The Database Frontend
140 7.3 The Backend API
141 7.4 Your main() Routine
142 7.5 The Backend Functions
143 7.6 Application Invocation
144 7.7 Summary and Synopsis
145
146 8. Future Directions
147
148 9. License
149
150 9.1 Index Data Copyright
151 9.2 Additional Copyright Statements
152
153 10. About Index Data
154
155
156
157 ______________________________________________________________________
158
159 1. Introduction
160
161 The YAZ toolkit offers several different levels of access to the
162 Z39.50 and SR protocols. The level that you need to use depends on
163 your requirements, and the role (server or client) that you want to
164 implement.
165
166 The basic level, which is independent of the role, consists of three
167 primary interfaces:
168
169
170 o ASN, which provides a C representation of the Z39.50/SR protocol
171 packages (PDUs).
172
173 o ODR, which encodes and decodes the packages according to the BER
174 specification.
175
176 o COMSTACK, which exchanges the encoded packages with a peer process
177 over a network.
178
179 The ASN module represents the ASN.1 definition of the SR/Z39.50
180 protocol. It establishes a set of type and structure definitions, with
181 one structure for each of the top-level PDUs, and one structure or
182 type for each of the contained ASN.1 types. For primitive types, or
183 other types that are defined by the ASN.1 standard itself (such as the
184 EXTERNAL type), the C representation is provided by the ODR (Open Data
185 Representation) subsystem.
186
187 ODR is a basic mechanism for representing an ASN.1 type in the C
188 programming language, and for implementing BER encoders and decoders
189 for values of that type. The types defined in the ASN module generally
190 have the prefix Z_, and a suffix corresponding to the name of the type
191 in the ASN.1 specification of the protocol (generally Z39.50-1995). In
192 the case of base types (those originating in the ASN.1 standard
193 itself), the prefix Odr_ is sometimes seen. Either way, look for the
194 actual definition in either proto.h (for the types from the protocol),
195 odr.h (for the primitive ASN.1 types, or odr_use.h (for the ASN.1
196 useful types). The ASN library also provides functions (which are, in
197 turn, defined using ODR primitives) for encoding and decoding data
198 values. Their general form is
199 int z_xxx(ODR o, Z_xxx **p, int optional, const char *name);
200
201
202
203
204 (note the lower-case "z" in the function name)
205
206 NOTE: If you are using the premade definitions of the ASN module, and
207 you are not adding new protocol of your own, the only parts of ODR
208 that you need to worry about are documented in section ``Using ODR''.
209
210 When you have created a BER-encoded buffer, you can use the COMSTACK
211 subsystem to transmit (or receive) data over the network. The COMSTACK
212 module provides simple functions for establishing a connection
213 (passively or actively, depending on the role of your application),
214 and for exchanging BER-encoded PDUs over that connection. When you
215 create a connection endpoint, you need to specify what transport to
216 use (OSI or TCP/IP), and which protocol you want to use (SR or
217 Z39.50). For the remainer of the connection's lifetime, you don't have
218 to worry about the underlying transport protocol at all - the COMSTACK
219 will ensure that the correct mechanism is used.
220
221 We call the combined interfaces to ODR, ASN, and COMSTACK the service
222 level API. It's the API that most closely models the Z39.50/SR
223 service/protocol definition, and it provides unlimited access to all
224 fields and facilities of the protocol definitions.
225
226 The reason that the YAZ service-level API is a conglomerate of the
227 APIs from three different submodules is twofold. First, we wanted to
228 allow the user a choice of different options for each major task. For
229 instance, if you don't like the protocol API provided by ODR/ASN, you
230 can use SNACC or BERUtils instead, and still have the benefits of the
231 transparent transport approach of the COMSTACK module. Secondly, we
232 realise that you may have to fit the toolkit into an existing event-
233 processing structure, in a way that is incompatible with the COMSTACK
234 interface or some other part of YAZ.
235
236
237 2. Compilation and Installation
238
239 The latest version of the software will generally be found at
240
241
242
243 http://ftp.indexdata.dk/pub/yaz/
244
245
246
247
248 We have tried our best to keep the software portable, and on many
249 platforms, you should be able to compile everything with little or no
250 changes. So far, the software has been ported to the following
251 platforms with little or no difficulties.
252
253
254 o Unix systems
255
256 o HP/UX
257
258 o SunOS/Solaris
259
260 o DEC Unix
261
262 o Linux
263
264
265 o IBM AIX
266
267 o Data General DG/UX (with some CFLAGS tinkering)
268
269 o SGI/IRIX
270
271 o DDE Supermax
272
273 o Non-unix systems
274
275 o Apple Macintosh (using the Codewarrior programming environment and
276 the GUSI socket libraries)
277
278 o MS Windows 95/NT (Win32)
279
280 o IBM AS/400
281
282 If you move the software to other platforms, we'd be grateful if you'd
283 let us know about it. If you run into difficulties, we will try to
284 help if we can, and if you solve the problems, we would be happy to
285 include your fixes in the next release. So far, we have mostly avoided
286 #ifdefs for individual platforms, and we'd like to keep it that way as
287 far as it makes sense.
288
289 We maintain a mailing-list for the purpose of announcing new releases
290 and bug-fixes, as well as general discussion. Subscribe by sending
291 mail to [email protected]. General questions and problems can
292 be directed at [email protected], or the address given at the top
293 of this document.
294
295
296 2.1. UNIX
297
298 Note that if your system doesn't have a native ANSI C compiler, you
299 may have to acquire one separately. We recommend gcc.
300
301 For UNIX we use GNU configure to create Makefiles for YAZ. Generally
302 it should be sufficient to run configure without options:
303
304
305
306 ./configure
307
308
309
310
311 The configure script attempts to use use the C compiler specified by
312 the CC environment variable. If not set, GNU C will be used if it is
313 available. The CFLAGS environment variable holds options to be passed
314 to the C compiler. If you're using Bourne-compatible shell you may
315 pass something like this to use a particular C compiler with
316 optimization enabled:
317
318
319 CC=/opt/ccs/bin/cc CFLAGS=-O ./configure
320
321
322
323
324 To customize YAZ the configure script also accepts a set of options.
325 The most important are:
326
327
328 --prefix path
329 Specifies installation prefix. This is only needed if you run
330 make install later to perform a "system" installation. The
331 prefix is /usr/local if not specified.
332
333
334 --enable-comp
335 YAZ will be built using the ASN.1 compiler for YAZ (default). If
336 you wish to use the old decoders (in sub directory asn) use
337 --disable-comp instead.
338
339
340 --enable-threads
341 YAZ will be built using POSIX threads. Specifically, _REENTRANT
342 will be defined during compilation.
343
344 When configured, build the software by typing:
345
346
347 make
348
349
350
351
352 Developers that do modifications to YAZ may wish to run make depend as
353 well to generate object-header file dependencies.
354
355 The following files are generated by make
356
357 lib/libyaz.a
358 The YAZ programmers' library.
359
360
361 ztest/yaz-ztest
362 A test Z39.50 server.
363
364
365 client/yaz-client
366 A command mode Z39.50 client.
367
368
369 yaz-config
370 A Bourne-shell script that holds build settings for YAZ.
371
372
373 If you wish to install YAZ in system directories such as
374 /usr/local/bin, /usr/local/lib) you can type:
375
376
377
378 make install
379
380
381
382
383 You probably need to have root access in order to perform this. You
384 must specify the --prefix option for configure if you going to install
385 in anything but /usr/local/.
386
387
388 2.2. WIN32
389
390 YAZ is shipped with "makefiles" for the NMAKE tool that comes with
391 Visual C++.
392
393 Start an MS-DOS prompt and switch the sub directory WIN where the file
394 makefile is located. Customize the installation by editing the
395 makefile file (for example by using notepad).
396
397 The following summarises the most important settings in that file:
398
399
400 NEW_Z3950
401 If 1, the auto-generated decoder/encoders for Z39.50 as written
402 by the ASN.1 compiler will be used. If 0, the old decoders for
403 Z39.50 will be used. Note, when 1, the setting TCL should point
404 to the Tcl shell on your system.
405
406 DEBUG
407 If set to 1, the software is compiled with debugging libraries.
408 If set to 0, the software is compiled with release (non-
409 debugging) libraries.
410
411 When satisfied with the settings in the makefile type
412
413
414 nmake
415
416
417
418
419 The following is generated upon successful compilation:
420
421 bin/yaz.dll
422 A multithreaded DLL with everything except the frontend server
423 library.
424
425 lib/yaz.lib
426 An import library for yaz.dll.
427
428 lib/server.lib
429 The frontend server library.
430
431 bin/yaz-ztest.exe
432 A test Z39.50 server.
433
434 bin/yaz-client.exe
435 A command mode Z39.50 client.
436
437
438 3. The ASN Module
439
440 3.1. Introduction
441
442 The ASN module provides you with a set of C struct definitions for the
443 various PDUs of the protocol, as well as for the complex types
444 appearing within the PDUs. For the primitive data types, the C
445 representation often takes the form of an ordinary C language type,
446 such as int. For ASN.1 constructs that have no direct representation
447 in C, such as general octet strings and bit strings, the ODR module
448 (see section ``ODR'') provides auxiliary definitions.
449
450
451 3.2. Preparing PDUs
452
453 A structure representing a complex ASN.1 type doesn't in itself
454 contain the members of that type. Instead, the structure contains
455 pointers to the members of the type. This is necessary, in part, to
456 allow a mechanism for specifying which of the optional structure
457 (SEQUENCE) members are present, and which are not. It follows that you
458 will need to somehow provide space for the individual members of the
459 structure, and set the pointers to refer to the members.
460
461 The conversion routines don't care how you allocate and maintain your
462 C structures - they just follow the pointers that you provide.
463 Depending on the complexity of your application, and your personal
464 taste, there are at least three different approaches that you may take
465 when you allocate the structures.
466
467
468 o You can use static or automatic local variables in the function
469 that prepares the PDU. This is a simple approach, and it provides
470 the most efficient form of memory management. While it works well
471 for flat PDUs like the InitReqest, it will generally not be
472 sufficient for say, the generation of an arbitrarily complex RPN
473 query structure.
474
475 o You can individually create the structure and its members using the
476 malloc(2) function. If you want to ensure that the data is freed
477 when it is no longer needed, you will have to define a function
478 that individually releases each member of a structure before
479 freeing the structure itself.
480
481 o You can use the odr_malloc() function (see section ``Using ODR''
482 for details). When you use odr_malloc(), you can release all of the
483 allocated data in a single operation, independent of any pointers
484 and relations between the data. odr_malloc() is based on a "nibble-
485 memory" scheme, in which large portions of memory are allocated,
486 and then gradually handed out with each call to odr_malloc(). The
487 next time you call odr_reset(), all of the memory allocated since
488 the last call is recycled for future use (actually, it is placed on
489 a free-list).
490
491 o You can combine all of the methods described here. This will often
492 be the most practical approach. For instance, you might use
493 odr_malloc() to allocate an entire structure and some of its
494 elements, while you leave other elements pointing to global or per-
495 session default variables.
496
497 The ASN module provides an important aid in creating new PDUs. For
498 each of the PDU types (say, Z_InitRequest), a function is provided
499 that allocates and initializes an instance of that PDU type for you.
500 In the case of the InitRequest, the function is simply named
501 zget_InitRequest(), and it sets up reasonable default value for all of
502 the mandatory members. The optional members are generally initialized
503 to null pointers. This last aspect is very important: it ensures that
504 if the PDU definitions are extended after you finish your
505 implementation (to accommodate new versions of the protocol, say), you
506 won't get into trouble with uninitialized pointers in your structures.
507 The functions use odr_malloc() to allocate the PDUs and its members,
508 so you can free everything again with a single call to odr_reset(). We
509 strongly recommend that you use the zget_* functions whenever you are
510 preparing a PDU (in a C++ API, the zget_ functions would probably be
511 promoted to constructors for the individual types).
512
513 The prototype for the individual PDU types generally look like this:
514
515
516
517 Z_<type> *zget_<type>(ODR o);
518
519
520
521
522 eg.:
523
524
525
526 Z_InitRequest *zget_InitRequest(ODR o);
527
528
529 The ODR handle should generally be your encoding stream, but it
530 needn't be.
531
532 As well as the individual PDU functions, a function zget_APDU() is
533 provided, which allocates a toplevel Z-APDU of the type requested:
534
535
536
537 Z_APDU *zget_APDU(ODR o, int which);
538
539
540
541
542 The which parameter is (of course) the discriminator belonging to the
543 Z_APDU CHOICE type. All of the interface described here is provided by
544 the ASN module, and you access it through the proto.h header file.
545
546
547 3.3. Object Identifiers
548
549 When you refer to object identifiers in your application, you need to
550 be aware that SR and Z39.50 use two different set of OIDs to refer to
551 the same objects. To handle this easily, YAZ provides a utility module
552 to ASN which provides an internal representation of the OIDs used in
553 both protocols. Each oid is described by a structure:
554
555
556
557 typedef struct oident
558 {
559 enum oid_proto proto;
560 enum oid_class class;
561 enum oid_value value;
562 int oidsuffix[OID_SIZE];
563 char *desc;
564 } oident;
565
566
567
568
569 The proto field can be set to either PROTO_SR or PROTO_Z3950. The
570 class might be, say, CLASS_RECSYN, and the value might be VAL_USMARC
571 for the USMARC record format. Functions
572
573
574
575 int *oid_ent_to_oid(struct oident *ent, int *dst);
576 struct oident *oid_getentbyoid(int *o);
577
578
579
580
581 are provided to map between object identifiers and database entries.
582 If you store a member of the oid_proto type in your association state
583 information, it's a simple matter, at runtime, to generate the correct
584 OID when you need it. For decoding, you can simply ignore the proto
585 field, or if you're strict, you can verify that your peer is using the
586 OID family from the correct protocol. The desc field is a short,
587 human-readable name for the PDU, useful mainly for diagnostic output.
588
589 NOTE: The old function oid_getoidbyent still exists but is not thread
590 safe. Use oid_ent_to_oid instead and pass an array of size OID_SIZE.
591
592 NOTE: Plans are underway to merge the two protocols into a single
593 definition, with one set of object identifiers. When this happens, the
594 oid module will no longer be required to support protocol
595 independence, but it should still be useful as a simple OID database.
596
597
598 3.4. EXTERNAL Data
599
600 In order to achieve extensibility and adaptability to different
601 application domains, the new version of the protocol defines many
602 structures outside of the main ASN.1 specification, referencing them
603 through ASN.1 EXTERNAL constructs. To simplify the construction and
604 access to the externally referenced data, the ASN module defines a
605 specialized version of the EXTERNAL construct, called Z_External. It
606 is defined thus:
607
608
609
610 typedef struct Z_External
611 {
612 Odr_oid *direct_reference;
613 int *indirect_reference;
614 char *descriptor;
615 enum
616 {
617 /* Generic types */
618 Z_External_single = 0,
619 Z_External_octet,
620 Z_External_arbitrary,
621
622 /* Specific types */
623 Z_External_SUTRS,
624 Z_External_explainRecord,
625 Z_External_resourceReport1,
626 Z_External_resourceReport2
627
628 ...
629
630 } which;
631 union
632 {
633 /* Generic types */
634 Odr_any *single_ASN1_type;
635 Odr_oct *octet_aligned;
636 Odr_bitmask *arbitrary;
637
638 /* Specific types */
639 Z_SUTRS *sutrs;
640 Z_ExplainRecord *explainRecord;
641 Z_ResourceReport1 *resourceReport1;
642 Z_ResourceReport2 *resourceReport2;
643
644 ...
645
646 } u;
647 } Z_External;
648
649
650
651
652 When decoding, the ASN module will attempt to determine which syntax
653 describes the data by looking at the reference fields (currently only
654 the direct-reference). For ASN.1 structured data, you need only
655 consult the which field to determine the type of data. You can the
656 access the data directly through the union. When constructing data
657 for encoding, you set the union pointer to point to the data, and set
658 the which field accordingly. Remember also to set the direct (or
659 indirect) reference to the correct OID for the data type. For non-
660 ASN.1 data such as MARC records, use the octet_aligned arm of the
661 union.
662
663 Some servers return ASN.1 structured data values (eg. database
664 records) as BER-encoded records placed in the octet-aligned branch of
665 the EXTERNAL CHOICE. The ASN-module will not automatically decode
666 these records. To help you decode the records in the application, the
667 function
668
669
670
671 Z_ext_typeent *z_ext_gettypebyref(oid_value ref);
672
673
674
675
676 Can be used to retrieve information about the known, external data
677 types. The function return a pointer to a static area, or NULL, if no
678 match for the given direct reference is found. The Z_ext_typeent is
679 defined as:
680
681
682
683 typedef struct Z_ext_typeent
684 {
685 oid_value dref; /* the direct-reference OID value. */
686 int what; /* discriminator value for the external CHOICE */
687 Odr_fun fun; /* decoder function */
688 } Z_ext_typeent;
689
690
691
692
693 The what member contains the Z_External union discriminator value for
694 the given type: For the SUTRS record syntax, the value would be
695 Z_External_sutrs. The fun member contains a pointer to the function
696 which encodes/decodes the given type. Again, for the SUTRS record
697 syntax, the value of fun would be z_SUTRS (a function pointer).
698
699 If you receive an EXTERNAL which contains an octet-string value that
700 you suspect of being an ASN.1-structured data value, you can use
701 z_ext_gettypebyref to look for the provided direct-reference. If the
702 return value is different from NULL, you can use the provided function
703 to decode the BER string (see section ``Using ODR'').
704
705 If you want to send EXTERNALs containing ASN.1-structured values in
706 the occtet-aligned branch of the CHOICE, this is possible too.
707 However, on the encoding phase, it requires a somewhat involved
708 juggling around of the various buffers involved.
709
710 If you need to add new, externally defined data types, you must update
711 the struct above, in the source file prt-ext.h, as well as the
712 encoder/decoder in the file prt-ext.c. When changing the latter,
713 remember to update both the arm arrary and the list type_table, which
714 drives the CHOICE biasing that is necessary to tell the different,
715 structured types apart on decoding.
716
717 NOTE: Eventually, the EXTERNAL processing will most likely
718 automatically insert the correct OIDs or indirect-refs. First,
719 however, we need to determine how application-context management
720 (specifically the presentation-context-list) should fit into the
721 various modules.
722
723
724
725
726
727 3.5. PDU Contents Table
728
729 We include, for reference, a listing of the fields of each top-level
730 PDU, as well as their default settings.
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793 Z_InitRequest
794 -------------
795 Field Type Default value
796
797 referenceId Z_ReferenceId NULL
798 protocolVersion Odr_bitmask Empty bitmask
799 options Odr_bitmask Empty bitmask
800 preferredMessageSize int 30*1024
801 maximumRecordSize int 30*1024
802 idAuthentication Z_IdAuthentication NULL
803 implementationId char* "YAZ (id=81)"
804 implementationName char* "Index Data/YAZ"
805 implementationVersion char* YAZ_VERSION
806 userInformationField Z_UserInformation NULL
807 otherInfo Z_OtherInformation NULL
808
809 Z_InitResponse
810 --------------
811 Field Type Default value
812
813 referenceId Z_ReferenceId NULL
814 protocolVersion Odr_bitmask Empty bitmask
815 options Odr_bitmask Empty bitmask
816 preferredMessageSize int 30*1024
817 maximumRecordSize int 30*1024
818 result bool_t TRUE
819 implementationId char* "YAZ (id=81)"
820 implementationName char* "Index Data/YAZ"
821 implementationVersion char* YAZ_VERSION
822 userInformationField Z_UserInformat.. NULL
823 otherInfo Z_OtherInformation NULL
824
825 Z_SearchRequest
826 ---------------
827 Field Type Default value
828
829 referenceId Z_ReferenceId NULL
830 smallSetUpperBound int 0
831 largeSetLowerBound int 1
832 mediumSetPresentNumber int 0
833 replaceIndicator bool_t TRUE
834 resultSetName char* "default"
835 num_databaseNames int 0
836 databaseNames char** NULL
837 smallSetElementSetNames Z_ElementSetNames NULL
838 mediumSetElementSetNames Z_ElementSetNames NULL
839 preferredRecordSyntax Odr_oid NULL
840 query Z_Query NULL
841 additionalSearchInfo Z_OtherInformation NULL
842 otherInfo Z_OtherInformation NULL
843
844 Z_SearchResponse
845 ----------------
846 Field Type Default value
847
848 referenceId Z_ReferenceId NULL
849 resultCount int 0
850 numberOfRecordsReturned int 0
851 nextResultSetPosition int 0
852 searchStatus bool_t TRUE
853 resultSetStatus int NULL
854 presentStatus int NULL
855 records Z_Records NULL
856 additionalSearchInfo Z_OtherInformation NULL
857 otherInfo Z_OtherInformation NULL
858
859 Z_PresentRequest
860 ----------------
861 Field Type Default value
862
863 referenceId Z_ReferenceId NULL
864 resultSetId char* "default"
865 resultSetStartPoint int 1
866 numberOfRecordsRequested int 10
867 num_ranges int 0
868 additionalRanges Z_Range NULL
869 recordComposition Z_RecordComposition NULL
870 preferredRecordSyntax Odr_oid NULL
871 maxSegmentCount int NULL
872 maxRecordSize int NULL
873 maxSegmentSize int NULL
874 otherInfo Z_OtherInformation NULL
875
876 Z_PresentResponse
877 -----------------
878 Field Type Default value
879
880 referenceId Z_ReferenceId NULL
881 numberOfRecordsReturned int 0
882 nextResultSetPosition int 0
883 presentStatus int Z_PRES_SUCCESS
884 records Z_Records NULL
885 otherInfo Z_OtherInformation NULL
886
887 Z_DeleteResultSetRequest
888 ------------------------
889 Field Type Default value
890
891 referenceId Z_ReferenceId NULL
892 deleteFunction int Z_DeleteRequest_list
893 num_ids int 0
894 resultSetList char** NULL
895 otherInfo Z_OtherInformation NULL
896
897 Z_DeleteResultSetResponse
898 -------------------------
899 Field Type Default value
900
901 referenceId Z_ReferenceId NULL
902 deleteOperationStatus int Z_DeleteStatus_success
903 num_statuses int 0
904 deleteListStatuses Z_ListStatus** NULL
905 numberNotDeleted int NULL
906 num_bulkStatuses int 0
907 bulkStatuses Z_ListStatus NULL
908 deleteMessage char* NULL
909 otherInfo Z_OtherInformation NULL
910
911 Z_ScanRequest
912 -------------
913 Field Type Default value
914
915 referenceId Z_ReferenceId NULL
916 num_databaseNames int 0
917 databaseNames char** NULL
918 attributeSet Odr_oid NULL
919 termListAndStartPoint Z_AttributesPlus... NULL
920 stepSize int NULL
921 numberOfTermsRequested int 20
922 preferredPositionInResponse int NULL
923 otherInfo Z_OtherInformation NULL
924
925 Z_ScanResponse
926 --------------
927 Field Type Default value
928
929 referenceId Z_ReferenceId NULL
930 stepSize int NULL
931 scanStatus int Z_Scan_success
932 numberOfEntriesReturned int 0
933 positionOfTerm int NULL
934 entries Z_ListEntris NULL
935 attributeSet Odr_oid NULL
936 otherInfo Z_OtherInformation NULL
937
938 Z_TriggerResourceControlRequest
939 -------------------------------
940 Field Type Default value
941
942 referenceId Z_ReferenceId NULL
943 requestedAction int Z_TriggerResourceCtrl_resou..
944 prefResourceReportFormat Odr_oid NULL
945 resultSetWanted bool_t NULL
946 otherInfo Z_OtherInformation NULL
947
948 Z_ResourceControlRequest
949 ------------------------
950 Field Type Default value
951
952 referenceId Z_ReferenceId NULL
953 suspendedFlag bool_t NULL
954 resourceReport Z_External NULL
955 partialResultsAvailable int NULL
956 responseRequired bool_t FALSE
957 triggeredRequestFlag bool_t NULL
958 otherInfo Z_OtherInformation NULL
959
960 Z_ResourceControlResponse
961 -------------------------
962 Field Type Default value
963
964 referenceId Z_ReferenceId NULL
965 continueFlag bool_t TRUE
966 resultSetWanted bool_t NULL
967 otherInfo Z_OtherInformation NULL
968
969 Z_AccessControlRequest
970 ----------------------
971 Field Type Default value
972
973 referenceId Z_ReferenceId NULL
974 which enum Z_AccessRequest_simpleForm;
975 u union NULL
976 otherInfo Z_OtherInformation NULL
977
978 Z_AccessControlResponse
979 -----------------------
980 Field Type Default value
981
982 referenceId Z_ReferenceId NULL
983 which enum Z_AccessResponse_simpleForm
984 u union NULL
985 diagnostic Z_DiagRec NULL
986 otherInfo Z_OtherInformation NULL
987
988 Z_Segment
989 ---------
990 Field Type Default value
991 referenceId Z_ReferenceId NULL
992 numberOfRecordsReturned int value=0
993 num_segmentRecords int 0
994 segmentRecords Z_NamePlusRecord NULL
995 otherInfo Z_OtherInformation NULL
996
997 Z_Close
998 -------
999 Field Type Default value
1000
1001 referenceId Z_ReferenceId NULL
1002 closeReason int Z_Close_finished
1003 diagnosticInformation char* NULL
1004 resourceReportFormat Odr_oid NULL
1005 resourceFormat Z_External NULL
1006 otherInfo Z_OtherInformation NULL
1007
1008
1009
1010
1011 4. Supporting Tools
1012
1013 In support of the service API - primarily the ASN module, which
1014 provides the programmatic interface to the Z39.50 APDUs, YAZ contains
1015 a collection of tools that support the development of applications.
1016
1017
1018 4.1. Query Syntax Parsers
1019
1020 Since the type-1 (RPN) query structure has no direct, useful string
1021 representation, every origin application needs to provide some form of
1022 mapping from a local query notation or representation to a Z_RPNQuery
1023 structure. Some programmers will prefer to construct the query
1024 manually, perhaps using odr_malloc() to simplify memory management.
1025 The YAZ distribution includes two separate, query-generating tools
1026 that may be of use to you.
1027
1028
1029 4.1.1. Prefix Query Format
1030
1031 Since RPN or reverse polish notation is really just a fancy way of
1032 describing a suffix notation format (operator follows operands), it
1033 would seem that the confusion is total when we now introduce a prefix
1034 notation for RPN. The reason is one of simple laziness - it's somewhat
1035 simpler to interpret a prefix format, and this utility was designed
1036 for maximum simplicity, to provide a baseline representation for use
1037 in simple test applications and scripting environments (like Tcl). The
1038 demonstration client included with YAZ uses the PQF.
1039
1040 The PQF is defined by the pquery module in the YAZ library. The
1041 pquery.h file provides the declaration of the functions
1042
1043
1044
1045 Z_RPNQuery *p_query_rpn (ODR o, oid_proto proto, const char *qbuf);
1046
1047 Z_AttributesPlusTerm *p_query_scan (ODR o, oid_proto proto,
1048 Odr_oid **attributeSetP, const char *qbuf);
1049
1050 int p_query_attset (const char *arg);
1051
1052
1053
1054
1055 The function p_query_rpn() takes as arguments an ODR stream (see
1056 section ``The ODR Module'') to provide a memory source (the structure
1057 created is released on the next call to odr_reset() on the stream/), a
1058 protocol identifier (one of the constants PROTO_Z3950 and PROTO_SR),
1059 an attribute set reference, and finally a null-terminated string
1060 holding the query string.
1061
1062 If the parse went well, p_query_rpn() returns a pointer to a
1063 Z_RPNQuery structure which can be placed directly into a
1064 Z_SearchRequest.
1065
1066 The p_query_attset specifies which attribute set to use if the query
1067 doesn't specify one by the @attrset operator. The p_query_attset
1068 returns 0 if the argument is a valid attribute set specifier;
1069 otherwise the function returns -1.
1070
1071 The grammar of the PQF is as follows:
1072
1073
1074
1075 Query ::= [ AttSet ] QueryStruct.
1076
1077 AttSet ::= string.
1078
1079 QueryStruct ::= { Attribute } Simple | Complex.
1080
1081 Attribute ::= '@attr' AttributeType '=' AttributeValue.
1082
1083 AttributeType ::= integer.
1084
1085 AttributeValue ::= integer.
1086
1087 Complex ::= Operator QueryStruct QueryStruct.
1088
1089 Operator ::= '@and' | '@or' | '@not' | '@prox' Proximity.
1090
1091 Simple ::= ResultSet | Term.
1092
1093 ResultSet ::= '@set' string.
1094
1095 Term ::= string | '"' string '"'.
1096
1097 Proximity ::= Exclusion Distance Ordered Relation WhichCode UnitCode.
1098
1099 Exclusion ::= '1' | '0' | 'void'.
1100
1101 Distance ::= integer.
1102
1103 Ordered ::= '1' | '0'.
1104
1105 Relation ::= integer.
1106
1107 WhichCode ::= 'known' | 'private' | integer.
1108
1109 UnitCode ::= integer.
1110
1111
1112
1113
1114 You will note that the syntax above is a fairly faithful
1115 representation of RPN, except for the Attibute, which has been moved a
1116 step away from the term, allowing you to associate one or more
1117 attributes with an entire query structure. The parser will
1118 automatically apply the given attributes to each term as required.
1119
1120 The following are all examples of valid queries in the PQF.
1121
1122
1123 dylan
1124
1125 "bob dylan"
1126
1127 @or "dylan" "zimmerman"
1128
1129 @set Result-1
1130
1131 @or @and bob dylan @set Result-1
1132
1133 @attr 4=1 @and @attr 1=1 "bob dylan" @attr 1=4 "slow train coming"
1134
1135 @attr 4=1 @attr 1=4 "self portrait"
1136
1137 @prox 0 3 1 2 k 2 dylan zimmerman
1138
1139
1140
1141
1142
1143 4.1.2. Common Command Language
1144
1145 Not all users enjoy typing in prefix query structures and numerical
1146 attribute values, even in a minimalistic test client. In the library
1147 world, the more intuitive Common Command Language (or ISO 8777) has
1148 enjoyed some popularity - especially before the widespread
1149 availability of graphical interfaces. It is still useful in
1150 applications where you for some reason or other need to provide a
1151 symbolic language for expressing boolean query structures.
1152
1153 The EUROPAGATE research project working under the Libraries programme
1154 of the European Commission's DG XIII has, amongst other useful tools,
1155 implemented a general-purpose CCL parser which produces an output
1156 structure that can be trivially converted to the internal RPN
1157 representation of YAZ (The Z_RPNQuery structure). Since the CCL
1158 utility - along with the rest of the software produced by EUROPAGATE -
1159 is made freely available on a liberal license, it is included as a
1160 supplement to YAZ.
1161
1162
1163 4.1.2.1. CCL Syntax
1164
1165 The CCL parser obeys the following grammar for the FIND argument. The
1166 syntax is annotated by in the lines prefixed by --.
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189 CCL-Find ::= CCL-Find Op Elements
1190 | Elements.
1191
1192 Op ::= "and" | "or" | "not"
1193 -- The above means that Elements are separated by boolean operators.
1194
1195 Elements ::= '(' CCL-Find ')'
1196 | Set
1197 | Terms
1198 | Qualifiers Relation Terms
1199 | Qualifiers Relation '(' CCL-Find ')'
1200 | Qualifiers '=' string '-' string
1201 -- Elements is either a recursive definition, a result set reference, a
1202 -- list of terms, qualifiers followed by terms, qualifiers followed
1203 -- by a recursive definition or qualifiers in a range (lower - upper).
1204
1205 Set ::= 'set' = string
1206 -- Reference to a result set
1207
1208 Terms ::= Terms Prox Term
1209 | Term
1210 -- Proximity of terms.
1211
1212 Term ::= Term string
1213 | string
1214 -- This basically means that a term may include a blank
1215
1216 Qualifiers ::= Qualifiers ',' string
1217 | string
1218 -- Qualifiers is a list of strings separated by comma
1219
1220 Relation ::= '=' | '>=' | '<=' | '<>' | '>' | '<'
1221 -- Relational operators. This really doesn't follow the ISO8777
1222 -- standard.
1223
1224 Prox ::= '%' | '!'
1225 -- Proximity operator
1226
1227
1228
1229
1230 The following queries are all valid:
1231
1232
1233
1234 dylan
1235
1236 "bob dylan"
1237
1238 dylan or zimmerman
1239
1240 set=1
1241
1242 (dylan and bob) or set=1
1243
1244
1245
1246
1247 Assuming that the qualifiers ti, au and date are defined we may use:
1248
1249
1250
1251
1252
1253
1254
1255 ti=self portrait
1256
1257 au=(bob dylan and slow train coming)
1258
1259 date>1980 and (ti=((self portrait)))
1260
1261
1262
1263
1264
1265 4.1.2.2. CCL Qualifiers
1266
1267
1268 Qualifiers are used to direct the search to a particular searchable
1269 index, such as title (ti) and author indexes (au). The CCL standard
1270 itself doesn't specify a particular set of qualifiers, but it does
1271 suggest a few short-hand notations. You can customize the CCL parser
1272 to support a particular set of qualifiers to relect the current target
1273 profile. Traditionally, a qualifier would map to a particular use-
1274 attribute within the BIB-1 attribute set. However, you could also
1275 define qualifiers that would set, for example, the structure-
1276 attribute.
1277
1278 Consider a scenario where the target support ranked searches in the
1279 title-index. In this case, the user could specify
1280
1281
1282 ti,ranked=knuth computer
1283
1284
1285
1286
1287 and the ranked would map to structure=free-form-text (4=105) and the
1288 ti would map to title (1=4).
1289
1290 A "profile" with a set predefined CCL qualifiers can be read from a
1291 file. The YAZ client reads its CCL qualifiers from a file named
1292 default.bib. Each line in the file has the form:
1293
1294 qualifier-name type=val type=val ...
1295
1296 where qualifier-name is the name of the qualifier to be used (eg. ti),
1297 type is a BIB-1 category type and val is the corresponding BIB-1
1298 attribute value. The type can be either numeric or it may be either u
1299 (use), r (relation), p (position), s (structure), t (truncation) or c
1300 (completeness). The qualifier-name term has a special meaning. The
1301 types and values for this definition is used when no qualifier is
1302 present.
1303
1304 Consider the following definition:
1305
1306
1307 ti u=4 s=1
1308 au u=1 s=1
1309 term s=105
1310
1311
1312
1313
1314 Two qualifiers are defined, ti and au. They both set the structure-
1315 attribute to phrase (1). ti sets the use-attribute to 4. au sets the
1316 use-attribute to 1. When no qualifiers are used in the query the
1317 structure-attribute is set to free-form-text (105).
1318
1319
1320
1321 4.1.2.3. CCL API
1322
1323
1324 All public definitions can be found in the header file ccl.h. A
1325 profile identifier is of type CCL_bibset. A profile must be created
1326 with the call to the function ccl_qual_mk which returns a profile
1327 handle of type CCL_bibset.
1328
1329 To read a file containing qualifier definitions the function
1330 ccl_qual_file may be convenient. This function takes an already opened
1331 FILE handle pointer as argument along with a CCL_bibset handle.
1332
1333 To parse a simple string with a FIND query use the function
1334
1335
1336 struct ccl_rpn_node *ccl_find_str (CCL_bibset bibset, const char *str,
1337 int *error, int *pos);
1338
1339
1340
1341
1342 which takes the CCL profile (bibset) and query (str) as input. Upon
1343 successful completion the RPN tree is returned. If an error eccur,
1344 such as a syntax error, the integer pointed to by error holds the
1345 error code and pos holds the offset inside query string in which the
1346 parsing failed.
1347
1348 An english representation of the error may be obtained by calling the
1349 ccl_err_msg function. The error codes are listed in ccl.h.
1350
1351 To convert the CCL RPN tree (type struct ccl_rpn_node *) to the
1352 Z_RPNQuery of YAZ the function ccl_rpn_query must be used. This
1353 function which is part of YAZ is implemented in yaz-ccl.c. After
1354 calling this function the CCL RPN tree is probably no longer needed.
1355 The ccl_rpn_delete destroys the CCL RPN tree.
1356
1357 A CCL profile may be destroyed by calling the ccl_qual_rm function.
1358
1359 The token names for the CCL operators may be changed by setting the
1360 globals (all type char *) ccl_token_and, ccl_token_or, ccl_token_not
1361 and ccl_token_set. An operator may have aliases, i.e. there may be
1362 more than one name for the operator. To do this, separate each alias
1363 with a space character.
1364
1365
1366 4.2. Object Identifiers
1367
1368 The basic YAZ representation of an OID is an array of integers,
1369 terminated with the value -1. The ODR module provides two utility-
1370 functions to create and copy this type of data elements:
1371
1372
1373
1374 Odr_oid *odr_getoidbystr(ODR o, char *str);
1375
1376
1377
1378
1379 Creates an OID based on a string-based representation using dots (.)
1380 to separate elements in the OID.
1381
1382
1383
1384 Odr_oid *odr_oiddup(ODR odr, Odr_oid *o);
1385
1386
1387 Creates a copy of the OID referenced by the o parameter. Both
1388 functions take an ODR stream as parameter. This stream is used to
1389 allocate memory for the data elements, which is released on a
1390 subsequent call to odr_reset() on that stream.
1391
1392 The OID module provides a higher-level representation of the family of
1393 object identifers which describe the Z39.50 protocol and its related
1394 objects. The definition of the module interface is given in the oid.h
1395 file.
1396
1397 The interface is mainly based on the oident structure. The definition
1398 of this structure looks like this:
1399
1400
1401
1402 typedef struct oident
1403 {
1404 oid_proto proto;
1405 oid_class oclass;
1406 oid_value value;
1407 int oidsuffix[OID_SIZE];
1408 char *desc;
1409 } oident;
1410
1411
1412
1413
1414 The proto field takes one of the values
1415
1416
1417
1418 PROTO_Z3950
1419 PROTO_SR
1420
1421
1422
1423
1424 If you don't care about talking to SR-based implementations (few
1425 exist, and they may become fewer still if and when the ISO SR and ANSI
1426 Z39.50 documents are merged into a single standard), you can ignore
1427 this field on incoming packages, and always set it to PROTO_Z3950 for
1428 outgoing packages.
1429
1430 The oclass field takes one of the values
1431
1432
1433
1434 CLASS_APPCTX
1435 CLASS_ABSYN
1436 CLASS_ATTSET
1437 CLASS_TRANSYN
1438 CLASS_DIAGSET
1439 CLASS_RECSYN
1440 CLASS_RESFORM
1441 CLASS_ACCFORM
1442 CLASS_EXTSERV
1443 CLASS_USERINFO
1444 CLASS_ELEMSPEC
1445 CLASS_VARSET
1446 CLASS_SCHEMA
1447 CLASS_TAGSET
1448 CLASS_GENERAL
1449
1450
1451
1452
1453 corresponding to the OID classes defined by the Z39.50 standard.
1454
1455 Finally, the value field takes one of the values
1456
1457
1458
1459 VAL_APDU
1460 VAL_BER
1461 VAL_BASIC_CTX
1462 VAL_BIB1
1463 VAL_EXP1
1464 VAL_EXT1
1465 VAL_CCL1
1466 VAL_GILS
1467 VAL_WAIS
1468 VAL_STAS
1469 VAL_DIAG1
1470 VAL_ISO2709
1471 VAL_UNIMARC
1472 VAL_INTERMARC
1473 VAL_CCF
1474 VAL_USMARC
1475 VAL_UKMARC
1476 VAL_NORMARC
1477 VAL_LIBRISMARC
1478 VAL_DANMARC
1479 VAL_FINMARC
1480 VAL_MAB
1481 VAL_CANMARC
1482 VAL_SBN
1483 VAL_PICAMARC
1484 VAL_AUSMARC
1485 VAL_IBERMARC
1486 VAL_EXPLAIN
1487 VAL_SUTRS
1488 VAL_OPAC
1489 VAL_SUMMARY
1490 VAL_GRS0
1491 VAL_GRS1
1492 VAL_EXTENDED
1493 VAL_RESOURCE1
1494 VAL_RESOURCE2
1495 VAL_PROMPT1
1496 VAL_DES1
1497 VAL_KRB1
1498 VAL_PRESSET
1499 VAL_PQUERY
1500 VAL_PCQUERY
1501 VAL_ITEMORDER
1502 VAL_DBUPDATE
1503 VAL_EXPORTSPEC
1504 VAL_EXPORTINV
1505 VAL_NONE
1506 VAL_SETM
1507 VAL_SETG
1508 VAL_VAR1
1509 VAL_ESPEC1
1510
1511
1512
1513
1514 again, corresponding to the specific OIDs defined by the standard.
1515
1516 The desc field contains a brief, mnemonic name for the OID in
1517 question.
1518
1519 The function
1520
1521
1522
1523 struct oident *oid_getentbyoid(int *o);
1524
1525
1526
1527
1528 takes as argument an OID, and returns a pointer to a static area
1529 containing an oident structure. You typically use this function when
1530 you receive a PDU containing an OID, and you wish to branch out
1531 depending on the specific OID value.
1532
1533 The function
1534
1535
1536
1537 int *oid_ent_to_oid(struct oident *ent, int *dst);
1538
1539
1540
1541
1542 Takes as argument an oident structure - in which the proto, oclass,
1543 and value fields are assumed to be set correctly - and returns a
1544 pointer to a the buffer as given by dst containing the base
1545 representation of the corresponding OID. The function returns NULL and
1546 the array dst is unchanged if a mapping couldn't place. The array dst
1547 should be at least of size OID_SIZE.
1548
1549 The oid_ent_to_oid() function can be used whenever you need to prepare
1550 a PDU containing one or more OIDs. The separation of the protocol
1551 element from the remainer of the OID-description makes it simple to
1552 write applications that can communicate with either Z39.50 or OSI SR-
1553 based applications.
1554
1555 The function
1556
1557
1558
1559 oid_value oid_getvalbyname(const char *name);
1560
1561
1562
1563
1564 takes as argument a mnemonic OID name, and returns the value field of
1565 the first entry in the database that contains the given name in its
1566 desc field.
1567
1568 Finally, the module provides the following utility functions, whose
1569 meaning should be obvious:
1570
1571
1572
1573 void oid_oidcpy(int *t, int *s);
1574 void oid_oidcat(int *t, int *s);
1575 int oid_oidcmp(int *o1, int *o2);
1576 int oid_oidlen(int *o);
1577
1578
1579
1580
1581 NOTE: The OID module has been criticized - and perhaps rightly so -
1582 for needlessly abstracting the representation of OIDs. Other toolkits
1583 use a simple string-representation of OIDs with good results. In
1584 practice, we have found the interface comfortable and quick to work
1585 with, and it is a simple matter (for what it's worth) to create
1586 applications compatible with both ISO SR and Z39.50. Finally, the use
1587 of the oident database is by no means mandatory. You can easily create
1588 your own system for representing OIDs, as long as it is compatible
1589 with the low-level integer-array representation of the ODR module.
1590
1591
1592 4.3. Nibble Memory
1593
1594 Sometimes when you need to allocate and construct a large,
1595 interconnected complex of structures, it can be a bit of a pain to
1596 release the associated memory again. For the structures describing the
1597 Z39.50 PDUs and related structures, it is convenient to use the
1598 memory-management system of the ODR subsystem (see ``Using ODR'').
1599 However, in some circumstances where you might otherwise benefit from
1600 using a simple nibble memory management system, it may be impractical
1601 to use odr_malloc() and odr_reset(). For this purpose, the memory
1602 manager which also supports the ODR streams is made available in the
1603 NMEM module. The external interface to this module is given in the
1604 nmem.h file.
1605
1606 The following prototypes are given:
1607
1608
1609
1610 NMEM nmem_create(void);
1611 void nmem_destroy(NMEM n);
1612 void *nmem_malloc(NMEM n, int size);
1613 void nmem_reset(NMEM n);
1614 int nmem_total(NMEM n);
1615 void nmem_init(void);
1616
1617
1618
1619
1620 The nmem_create() function returns a pointer to a memory control
1621 handle, which can be released again by nmem_destroy() when no longer
1622 needed. The function nmem_malloc() allocates a block of memory of the
1623 requested size. A call to nmem_reset() or nmem_destroy() will release
1624 all memory allocated on the handle since it was created (or since the
1625 last call to nmem_reset(). The function nmem_total() returns the
1626 number of bytes currently allocated on the handle.
1627
1628 Note that the nibble memory pool is shared amonst threads. Posix
1629 mutex'es and WIN32 Critical sections are introduced to keep the module
1630 thread safe. On WIN32 function nmem_init() initialises the Critical
1631 Section handle and should be called once before any other nmem
1632 function is used.
1633
1634
1635 5. The ODR Module
1636
1637 5.1. Introduction
1638
1639 ODR is the BER-encoding/decoding subsystem of YAZ. Care as been taken
1640 to isolate ODR from the rest of the package - specifically from the
1641 transport interface. ODR may be used in any context where basic
1642 ASN.1/BER representations are used.
1643
1644 If you are only interested in writing a Z39.50 implementation based on
1645 the PDUs that are already provided with YAZ, you only need to concern
1646 yourself with the section on managing ODR streams (section ``Using
1647 ODR''). Only if you need to implement ASN.1 beyond that which has been
1648 provided, should you worry about the second half of the documentation
1649 (section ``Programming with ODR''). If you use one of the higher-level
1650 interfaces, you can skip this section entirely.
1651 This is important, so we'll repeat it for emphasis: You do not need to
1652 read section ``Programming with ODR'' to implement Z39.50 with YAZ.
1653
1654 If you need a part of the protocol that isn't already in YAZ, you
1655 should contact the authors before going to work on it yourself: We
1656 might already be working on it. Conversely, if you implement a useful
1657 part of the protocol before us, we'd be happy to include it in a
1658 future release.
1659
1660
1661 5.2. Using ODR
1662
1663
1664 5.2.1. ODR Streams
1665
1666 Conceptually, the ODR stream is the source of encoded data in the
1667 decoding mode; when encoding, it is the receptacle for the encoded
1668 data. Before you can use an ODR stream it must be allocated. This is
1669 done with the function
1670
1671
1672
1673 ODR odr_createmem(int direction);
1674
1675
1676
1677
1678 The odr_createmem() function takes as argument one of three manifest
1679 constants: ODR_ENCODE, ODR_DECODE, or ODR_PRINT. An ODR stream can be
1680 in only one mode - it is not possible to change its mode once it's
1681 selected. Typically, your program will allocate at least two ODR
1682 streams - one for decoding, and one for encoding.
1683
1684 When you're done with the stream, you can use
1685
1686
1687
1688 void odr_destroy(ODR o);
1689
1690
1691
1692
1693 to release the resources allocated for the stream.
1694
1695
1696 5.2.2. Memory Management
1697
1698 Two forms of memory management take place in the ODR system. The first
1699 one, which has to do with allocating little bits of memory (sometimes
1700 quite large bits of memory, actually) when a protocol package is
1701 decoded, and turned into a complex of interlinked structures. This
1702 section deals with this system, and how you can use it for your own
1703 purposes. The next section deals with the memory management which is
1704 required when encoding data - to make sure that a large enough buffer
1705 is available to hold the fully encoded PDU.
1706
1707 The ODR module has its own memory management system, which is used
1708 whenever memory is required. Specifically, it is used to allocate
1709 space for data when decoding incoming PDUs. You can use the memory
1710 system for your own purposes, by using the function
1711
1712
1713
1714 void *odr_malloc(ODR o, int size);
1715
1716
1717 You can't use the normal free(2) routine to free memory allocated by
1718 this function, and ODR doesn't provide a parallel function. Instead,
1719 you can call
1720
1721
1722
1723 void odr_reset(ODR o, int size);
1724
1725
1726
1727
1728 when you are done with the memory: Everything allocated since the last
1729 call to odr_reset() is released. The odr_reset() call is also required
1730 to clear up an error condition on a stream.
1731
1732 The function
1733
1734
1735
1736 int odr_total(ODR o);
1737
1738
1739
1740
1741 returns the number of bytes allocated on the stream since the last
1742 call to odr_reset().
1743
1744 The memory subsystem of ODR is fairly efficient at allocating and
1745 releasing little bits of memory. Rather than managing the individual,
1746 small bits of space, the system maintains a freelist of larger chunks
1747 of memory, which are handed out in small bits. This scheme is
1748 generally known as a nibble memory system. It is very useful for
1749 maintaing short-lived constructions such as protocol PDUs.
1750
1751 If you want to retain a bit of memory beyond the next call to
1752 odr_reset(), you can use the function
1753
1754
1755
1756 ODR_MEM odr_extract_mem(ODR o);
1757
1758
1759
1760
1761 This function will give you control of the memory recently allocated
1762 on the ODR stream. The memory will live (past calls to odr_reset()),
1763 until you call the function
1764
1765
1766
1767 void odr_release_mem(ODR_MEM p);
1768
1769
1770
1771
1772 The opaque ODR_MEM handle has no other purpose than referencing the
1773 memory block for you until you want to release it.
1774
1775 You can use odr_extract_mem() repeatedly between allocating data, to
1776 retain individual control of separate chunks of data.
1777
1778
1779 5.2.3. Encoding and Decoding Data
1780
1781 When encoding data, the ODR stream will write the encoded octet string
1782 in an internal buffer. To retrieve the data, use the function
1783 char *odr_getbuf(ODR o, int *len, int *size);
1784
1785
1786
1787
1788 The integer pointed to by len is set to the length of the encoded
1789 data, and a pointer to that data is returned. *size is set to the size
1790 of the buffer (unless size is null, signalling that you are not
1791 interested in the size). The next call to a primitive function using
1792 the same ODR stream will overwrite the data, unless a different buffer
1793 has been supplied using the call
1794
1795
1796
1797 void odr_setbuf(ODR o, char *buf, int len, int can_grow);
1798
1799
1800
1801
1802 which sets the encoding (or decoding) buffer used by o to buf, using
1803 the length len. Before a call to an encoding function, you can use
1804 odr_setbuf() to provide the stream with an encoding buffer of
1805 sufficient size (length). The can_grow parameter tells the encoding
1806 ODR stream whether it is allowed to use realloc(2) to increase the
1807 size of the buffer when necessary. The default condition of a new
1808 encoding stream is equivalent to the results of calling
1809
1810
1811
1812 odr_setbuf(stream, 0, 0, 1);
1813
1814
1815
1816
1817 In this case, the stream will allocate and reallocate memory as
1818 necessary. The stream reallocates memory by repeatedly doubling the
1819 size of the buffer - the result is that the buffer will typically
1820 reach its maximum, working size with only a small number of
1821 reallocation operations. The memory is freed by the stream when the
1822 latter is destroyed, unless it was assigned by the user with the
1823 can_grow parameter set to zero (in this case, you are expected to
1824 retain control of the memory yourself).
1825
1826 To assume full control of an encoded buffer, you must first call
1827 odr_getbuf() to fetch the buffer and its length. Next, you should call
1828 odr_setbuf() to provide a different buffer (or a null pointer) to the
1829 stream. In the simplest case, you will reuse the same buffer over and
1830 over again, and you will just need to call odr_getbuf() after each
1831 encoding operation to get the length and address of the buffer. Note
1832 that the stream may reallocate the buffer during an encoding
1833 operation, so it is necessary to retrieve the correct address after
1834 each encoding operation.
1835
1836 It is important to realise that the ODR stream will not release this
1837 memory when you call odr_reset(): It will merely update its internal
1838 pointers to prepare for the encoding of a new data value. When the
1839 stream is released by the odr_destroy() function, the memory given to
1840 it by odr_setbuf will be released only if the can_grow parameter to
1841 odr_setbuf() was nonzero. The can_grow parameter, in other words, is a
1842 way of signalling who is to own the buffer, you or the ODR stream. If
1843 you never call odr_setbuf() on your encoding stream, which is
1844 typically the case, the buffer allocated by the stream will belong to
1845 the stream by default.
1846
1847 When you wish to decode data, you should first call odr_setbuf(), to
1848 tell the decoding stream where to find the encoded data, and how long
1849 the buffer is (the can_grow parameter is ignored by a decoding
1850 stream). After this, you can call the function corresponding to the
1851 data you wish to decode (eg, odr_integer() odr z_APDU()).
1852
1853 Examples of encoding/decoding functions:
1854
1855
1856
1857 int odr_integer(ODR o, int **p, int optional, const char *name);
1858
1859 int z_APDU(ODR o, Z_APDU **p, int optional, const char *name);
1860
1861
1862
1863
1864 If the data is absent (or doesn't match the tag corresponding to the
1865 type), the return value will be either 0 or 1 depending on the
1866 optional flag. If optional is 0 and the data is absent, an error flag
1867 will be raised in the stream, and you'll need to call odr_reset()
1868 before you can use the stream again. If optional is nonzero, the
1869 pointer pointed to by p will be set to the null value, and the
1870 function will return 1. The name argument is used to pretty-print the
1871 tag in question. It may be set to NULL if pretty-printing is not
1872 desired.
1873
1874 If the data value is found where it's expected, the pointer pointed to
1875 by the p argument will be set to point to the decoded type. The space
1876 for the type will be allocated and owned by the ODR stream, and it
1877 will live until you call odr_reset() on the stream. You cannot use
1878 free(2) to release the memory. You can decode several data elements
1879 (by repeated calls to odr_setbuf() and your decoding function), and
1880 new memory will be allocated each time. When you do call odr_reset(),
1881 everything decoded since the last call to odr_reset() will be
1882 released.
1883
1884 The use of the double indirection can be a little confusing at first
1885 (its purpose will become clear later on, hopefully), so an example is
1886 in order. We'll encode an integer value, and immediately decode it
1887 again using a different stream. A useless, but informative operation.
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915 void do_nothing_useful(int value)
1916 {
1917 ODR encode, decode;
1918 int *valp, *resvalp;
1919 char *bufferp;
1920 int len;
1921
1922 /* allocate streams */
1923 if (!(encode = odr_createmem(ODR_ENCODE)))
1924 return;
1925 if (!(decode = odr_createmem(ODR_DECODE)))
1926 return;
1927
1928 valp = &value;
1929 if (odr_integer(encode, &valp, 0, 0) == 0)
1930 {
1931 printf("encoding went bad\n");
1932 return;
1933 }
1934 bufferp = odr_getbuf(encode, &len);
1935 printf("length of encoded data is %d\n", len);
1936
1937 /* now let's decode the thing again */
1938 odr_setbuf(decode, bufferp, len);
1939 if (odr_integer(decode, &resvalp, 0, 0) == 0)
1940 {
1941 printf("decoding went bad\n");
1942 return;
1943 }
1944 printf("the value is %d\n", *resvalp);
1945
1946 /* clean up */
1947 odr_destroy(encode);
1948 odr_destroy(decode);
1949 }
1950
1951
1952
1953
1954 This looks like a lot of work, offhand. In practice, the ODR streams
1955 will typically be allocated once, in the beginning of your program (or
1956 at the beginning of a new network session), and the encoding and
1957 decoding will only take place in a few, isolated places in your
1958 program, so the overhead is quite manageable.
1959
1960
1961 5.2.4. Diagnostics
1962
1963 The encoding/decoding functions all return 0 when an error occurs.
1964 Until you call odr_reset(), you cannot use the stream again, and any
1965 function called will immediately return 0.
1966
1967 To provide information to the programmer or administrator, the
1968 function
1969
1970
1971
1972 void odr_perror(ODR o, char *message);
1973
1974
1975
1976
1977 is provided, which prints the message argument to stderr along with an
1978 error message from the stream.
1979
1980
1981 You can also use the function
1982
1983
1984
1985 int odr_geterror(ODR o);
1986
1987
1988
1989
1990 to get the current error number from the screen. The number will be
1991 one of these constants:
1992
1993
1994 OMEMORY
1995 Memory allocation failed.
1996
1997 OSYSERR
1998 A system- or library call has failed. The standard diagnostic
1999 variable errno should be examined to determine the actual error.
2000
2001 OSPACE
2002 No more space for encoding. This will only occur when the user
2003 has explicitly provided a buffer for an encoding stream without
2004 allowing the system to allocate more space.
2005
2006 OREQUIRED
2007 This is a common protocol error; A required data element was
2008 missing during encoding or decoding.
2009
2010 OUNEXPECTED
2011 An unexpected data element was found during decoding.
2012
2013 OOTHER
2014 Other error. This is typically an indication of misuse of the
2015 ODR system by the programmer, and also that the diagnostic
2016 system isn't as good as it should be, yet.
2017
2018 The character string array
2019
2020
2021
2022 char *odr_errlist[]
2023
2024
2025
2026
2027 can be indexed by the error code to obtain a human-readable
2028 representation of the problem.
2029
2030
2031 5.2.5. Summary and Synopsis
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047 #include <odr.h>
2048
2049 ODR odr_createmem(int direction);
2050
2051 void odr_destroy(ODR o);
2052
2053 void odr_reset(ODR o);
2054
2055 char *odr_getbuf(ODR o, int *len);
2056
2057 void odr_setbuf(ODR o, char *buf, int len);
2058
2059 void *odr_malloc(ODR o, int size);
2060
2061 ODR_MEM odr_extract_mem(ODR o);
2062
2063 void odr_release_mem(ODR_MEM r);
2064
2065 int odr_geterror(ODR o);
2066
2067 void odr_perror(char *message);
2068
2069 extern char *odr_errlist[];
2070
2071
2072
2073
2074
2075 5.3. Programming with ODR
2076
2077 The API of ODR is designed to reflect the structure of ASN.1, rather
2078 than BER itself. Future releases may be able to represent data in
2079 other external forms.
2080
2081 The interface is based loosely on that of the Sun Microsystems XDR
2082 routines. Specifically, each function which corresponds to an ASN.1
2083 primitive type has a dual function. Depending on the settings of the
2084 ODR stream which is supplied as a parameter, the function may be used
2085 either to encode or decode data. The functions that can be built using
2086 these primitive functions, to represent more complex datatypes, share
2087 this quality. The result is that you only have to enter the definition
2088 for a type once - and you have the functionality of encoding, decoding
2089 (and pretty-printing) all in one unit. The resulting C source code is
2090 quite compact, and is a pretty straightforward representation of the
2091 source ASN.1 specification. Although no ASN.1 compiler is supplied
2092 with ODR at this time, it shouldn't be too difficult to write one, or
2093 perhaps even to adapt an existing compiler to output ODR routines (not
2094 surprisingly, writing encoders/decoders using ODR turns out to be
2095 boring work).
2096
2097 In many cases, the model of the XDR functions works quite well in this
2098 role. In others, it is less elegant. Most of the hassle comes from the
2099 optional SEQUENCE memebers which don't exist in XDR.
2100
2101
2102 5.3.1. The Primitive ASN.1 Types
2103
2104 ASN.1 defines a number of primitive types (many of which correspond
2105 roughly to primitive types in structured programming languages, such
2106 as C).
2107
2108
2109 5.3.1.1. INTEGER
2110
2111 The ODR function for encoding or decoding (or printing) the ASN.1
2112 INTEGER type looks like this:
2113 int odr_integer(ODR o, int **p, int optional, const char *name);
2114
2115
2116
2117
2118 (we don't allow values that can't be contained in a C integer.)
2119
2120 This form is typical of the primitive ODR functions. They are named
2121 after the type of data that they encode or decode. They take an ODR
2122 stream, an indirect reference to the type in question, and an optional
2123 flag (corresponding to the OPTIONAL keyword of ASN.1) as parameters.
2124 They all return an integer value of either one or zero. When you use
2125 the primitive functions to construct encoders for complex types of
2126 your own, you should follow this model as well. This ensures that your
2127 new types can be reused as elements in yet more complex types.
2128
2129 The o parameter should obviously refer to a properly initialized ODR
2130 stream of the right type (encoding/decoding/printing) for the
2131 operation that you wish to perform.
2132
2133 When encoding or printing, the function first looks at *p. If *p (the
2134 pointer pointed to by p) is a null pointer, this is taken to mean that
2135 the data element is absent. If the optional parameter is nonzero, the
2136 function will return one (signifying success) without any further
2137 processing. If the optional is zero, an internal error flag is set in
2138 the ODR stream, and the function will return 0. No further operations
2139 can be carried out on the stream without a call to the function
2140 odr_reset().
2141
2142 If *p is not a null pointer, it is expected to point to an instance of
2143 the data type. The data will be subjected to the encoding rules, and
2144 the result will be placed in the buffer held by the ODR stream.
2145
2146 The other ASN.1 primitives have similar functions that operate in
2147 similar manners:
2148
2149
2150 5.3.1.2. BOOLEAN
2151
2152
2153
2154 int odr_bool(ODR o, bool_t **p, int optional, const char *name);
2155
2156
2157
2158
2159
2160 5.3.1.3. REAL
2161
2162 Not defined.
2163
2164
2165 5.3.1.4. NULL
2166
2167
2168
2169 int odr_null(ODR o, bool_t **p, int optional, const char *name);
2170
2171
2172
2173
2174 In this case, the value of **p is not important. If *p is different
2175 from the null pointer, the null value is present, otherwise it's
2176 absent.
2177
2178
2179 5.3.1.5. OCTET STRING
2180
2181
2182
2183 typedef struct odr_oct
2184 {
2185 unsigned char *buf;
2186 int len;
2187 int size;
2188 } Odr_oct;
2189
2190 int odr_octetstring(ODR o, Odr_oct **p, int optional, const char *name);
2191
2192
2193
2194
2195 The buf field should point to the character array that holds the
2196 octetstring. The len field holds the actual length, while the size
2197 field gives the size of the allocated array (not of interest to you,
2198 in most cases). The character array need not be null terminated.
2199
2200 To make things a little easier, an alternative is given for string
2201 types that are not expected to contain embedded NULL characters (eg.
2202 VisibleString):
2203
2204
2205
2206 int odr_cstring(ODR o, char **p, int optional, const char *name);
2207
2208
2209
2210
2211 Which encoded or decodes between OCTETSTRING representations and null-
2212 terminates C strings.
2213
2214 Functions are provided for the derived string types, eg:
2215
2216
2217
2218 int odr_visiblestring(ODR o, char **p, int optional, const char *name);
2219
2220
2221
2222
2223
2224 5.3.1.6. BIT STRING
2225
2226
2227
2228 int odr_bitstring(ODR o, Odr_bitmask **p, int optional, const char *name);
2229
2230
2231
2232
2233 The opaque type Odr_bitmask is only suitable for holding relatively
2234 brief bit strings, eg. for options fields, etc. The constant
2235 ODR_BITMASK_SIZE multiplied by 8 gives the maximum possible number of
2236 bits.
2237
2238 A set of macros are provided for manipulating the Odr_bitmask type:
2239
2240
2241
2242
2243
2244
2245 void ODR_MASK_ZERO(Odr_bitmask *b);
2246
2247 void ODR_MASK_SET(Odr_bitmask *b, int bitno);
2248
2249 void ODR_MASK_CLEAR(Odr_bitmask *b, int bitno);
2250
2251 int ODR_MASK_GET(Odr_bitmask *b, int bitno);
2252
2253
2254
2255
2256 The functions are modelled after the manipulation functions that
2257 accompany the fd_set type used by the select(2) call. ODR_MASK_ZERO
2258 should always be called first on a new bitmask, to initialize the bits
2259 to zero.
2260
2261
2262 5.3.1.7. OBJECT IDENTIFIER
2263
2264
2265
2266 int odr_oid(ODR o, Odr_oid **p, int optional, const char *name);
2267
2268
2269
2270
2271 The C OID represenation is simply an array of integers, terminated by
2272 the value -1 (the Odr_oid type is synonymous with the int type). We
2273 suggest that you use the OID database module (see section ``Object
2274 Identifiers'') to handle object identifiers in your application.
2275
2276
2277 5.3.2. Tagging Primitive Types
2278
2279 The simplest way of tagging a type is to use the odr_implicit_tag() or
2280 odr_explicit_tag() macros:
2281
2282
2283
2284 int odr_implicit_tag(ODR o, Odr_fun fun, int class, int tag, int
2285 optional, const char *name);
2286
2287 int odr_explicit_tag(ODR o, Odr_fun fun, int class, int tag,
2288 int optional, const char *name);
2289
2290
2291
2292
2293 To create a type derived from the integer type by implicit tagging,
2294 you might write:
2295
2296
2297
2298 MyInt ::= [210] IMPLICIT INTEGER
2299
2300
2301
2302
2303 In the ODR system, this would be written like:
2304
2305
2306
2307
2308
2309
2310
2311 int myInt(ODR o, int **p, int optional, const char *name)
2312 {
2313 return odr_implicit_tag(o, odr_integer, p,
2314 ODR_CONTEXT, 210, optional, name);
2315 }
2316
2317
2318
2319
2320 The function myInt() can then be used like any of the primitive
2321 functions provided by ODR. Note that the behavior of odr_explicit()
2322 and odr_implicit() macros act exactly the same as the functions they
2323 are applied to - they respond to error conditions, etc, in the same
2324 manner - they simply have three extra parameters. The class parameter
2325 may take one of the values: ODR_CONTEXT, ODR_PRIVATE, ODR_UNIVERSAL,
2326 or ODR_APPLICATION.
2327
2328
2329 5.3.3. Constructed Types
2330
2331 Constructed types are created by combining primitive types. The ODR
2332 system only implements the SEQUENCE and SEQUENCE OF constructions
2333 (although adding the rest of the container types should be simple
2334 enough, if the need arises).
2335
2336 For implementing SEQUENCEs, the functions
2337
2338
2339
2340 int odr_sequence_begin(ODR o, void *p, int size, const char *name);
2341 int odr_sequence_end(ODR o);
2342
2343
2344
2345
2346 are provided.
2347
2348 The odr_sequence_begin() function should be called in the beginning of
2349 a function that implements a SEQUENCE type. Its parameters are the ODR
2350 stream, a pointer (to a pointer to the type you're implementing), and
2351 the size of the type (typically a C structure). On encoding, it
2352 returns 1 if *p is a null pointer. The size parameter is ignored. On
2353 decoding, it returns 1 if the type is found in the data stream. size
2354 bytes of memory are allocated, and *p is set to point to this space.
2355 odr_sequence_end() is called at the end of the complex function.
2356 Assume that a type is defined like this:
2357
2358
2359
2360 MySequence ::= SEQUENCE {
2361 intval INTEGER,
2362 boolval BOOLEAN OPTIONAL }
2363
2364
2365
2366
2367 The corresponding ODR encoder/decoder function and the associated data
2368 structures could be written like this:
2369
2370
2371
2372
2373
2374
2375
2376
2377 typedef struct MySequence
2378 {
2379 int *intval;
2380 bool_t *boolval;
2381 } MySequence;
2382
2383 int mySequence(ODR o, MySequence **p, int optional, const char *name)
2384 {
2385 if (odr_sequence_begin(o, p, sizeof(**p), name) == 0)
2386 return optional && odr_ok(o);
2387 return
2388 odr_integer(o, &(*p)->intval, 0, "intval") &&
2389 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
2390 odr_sequence_end(o);
2391 }
2392
2393
2394
2395
2396 Note the 1 in the call to odr_bool(), to mark that the sequence member
2397 is optional. If either of the member types had been tagged, the macros
2398 odr_implicit() or odr_explicit() could have been used. The new
2399 function can be used exactly like the standard functions provided with
2400 ODR. It will encode, decode or pretty-print a data value of the
2401 MySequence type. We like to name types with an initial capital, as
2402 done in ASN.1 definitions, and to name the corresponding function with
2403 the first character of the name in lower case. You could, of course,
2404 name your structures, types, and functions any way you please - as
2405 long as you're consistent, and your code is easily readable. odr_ok
2406 is just that - a predicate that returns the state of the stream. It is
2407 used to ensure that the behaviour of the new type is compatible with
2408 the interface of the primitive types.
2409
2410
2411 5.3.4. Tagging Constructed Types
2412
2413 NOTE: See section ``Tagging Primitive types'' for information on how
2414 to tag the primitive types, as well as types that are already defined.
2415
2416
2417 5.3.4.1. Implicit Tagging
2418
2419 Assume the type above had been defined as
2420
2421
2422
2423 MySequence ::= [10] IMPLICIT SEQUENCE {
2424 intval INTEGER,
2425 boolval BOOLEAN OPTIONAL }
2426
2427
2428
2429
2430 You would implement this in ODR by calling the function
2431
2432
2433
2434 int odr_implicit_settag(ODR o, int class, int tag);
2435
2436
2437
2438
2439 which overrides the tag of the type immediately following it. The
2440 macro odr_implicit() works by calling odr_implicit_settag()
2441 immediately before calling the function pointer argument. Your type
2442 function could look like this:
2443 int mySequence(ODR o, MySequence **p, int optional, const char *name)
2444 {
2445 if (odr_implicit_settag(o, ODR_CONTEXT, 10) == 0 ||
2446 odr_sequence_begin(o, p, sizeof(**p), name) == 0)
2447 return optional && odr_ok(o);
2448 return
2449 odr_integer(o, &(*p)->intval, 0, "intval") &&
2450 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
2451 odr_sequence_end(o);
2452 }
2453
2454
2455
2456
2457 The definition of the structure MySequence would be the same.
2458
2459
2460 5.3.4.2. Explicit Tagging
2461
2462 Explicit tagging of constructed types is a little more complicated,
2463 since you are in effect adding a level of construction to the data.
2464
2465 Assume the definition:
2466
2467
2468
2469 MySequence ::= [10] IMPLICIT SEQUENCE {
2470 intval INTEGER,
2471 boolval BOOLEAN OPTIONAL }
2472
2473
2474
2475
2476 Since the new type has an extra level of construction, two new
2477 functions are needed to encapsulate the base type:
2478
2479
2480
2481 int odr_constructed_begin(ODR o, void *p, int class, int tag,
2482 const char *name);
2483
2484 int odr_constructed_end(ODR o);
2485
2486
2487
2488
2489 Assume that the IMPLICIT in the type definition above were replaced
2490 with EXPLICIT (or that the IMPLICIT keyword were simply deleted, which
2491 would be equivalent). The structure definition would look the same,
2492 but the function would look like this:
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509 int mySequence(ODR o, MySequence **p, int optional, const char *name)
2510 {
2511 if (odr_constructed_begin(o, p, ODR_CONTEXT, 10, name) == 0)
2512 return optional && odr_ok(o);
2513 if (o->direction == ODR_DECODE)
2514 *p = odr_malloc(o, sizeof(**p));
2515 if (odr_sequence_begin(o, p, sizeof(**p), 0) == 0)
2516 {
2517 *p = 0; /* this is almost certainly a protocol error */
2518 return 0;
2519 }
2520 return
2521 odr_integer(o, &(*p)->intval, 0, "intval") &&
2522 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
2523 odr_sequence_end(o) &&
2524 odr_constructed_end(o);
2525 }
2526
2527
2528
2529
2530 Notice that the interface here gets kind of nasty. The reason is
2531 simple: Explicitly tagged, constructed types are fairly rare in the
2532 protocols that we care about, so the aesthetic annoyance (not to
2533 mention the dangers of a cluttered interface) is less than the time
2534 that would be required to develop a better interface. Nevertheless, it
2535 is far from satisfying, and it's a point that will be worked on in the
2536 future. One option for you would be to simply apply the odr_explicit()
2537 macro to the first function, and not have to worry about
2538 odr_constructed_* yourself. Incidentally, as you might have guessed,
2539 the odr_sequence_ functions are themselves implemented using the
2540 odr_constructed_ functions.
2541
2542
2543 5.3.5. SEQUENCE OF
2544
2545 To handle sequences (arrays) of a apecific type, the function
2546
2547
2548
2549 int odr_sequence_of(ODR o, int (*fun)(ODR o, void *p, int optional),
2550 void *p, int *num, const char *name);
2551
2552
2553
2554
2555 The fun parameter is a pointer to the decoder/encoder function of the
2556 type. p is a pointer to an array of pointers to your type. num is the
2557 number of elements in the array.
2558
2559 Assume a type
2560
2561
2562
2563 MyArray ::= SEQUENCE OF INTEGER
2564
2565
2566
2567
2568 The C representation might be
2569
2570
2571
2572
2573
2574
2575 typedef struct MyArray
2576 {
2577 int num_elements;
2578 int **elements;
2579 } MyArray;
2580
2581
2582
2583
2584 And the function might look like
2585
2586
2587
2588 int myArray(ODR o, MyArray **p, int optional, const char *name)
2589 {
2590 if (o->direction == ODR_DECODE)
2591 *p = odr_malloc(o, sizeof(**p));
2592 if (odr_sequence_of(o, odr_integer, &(*p)->elements,
2593 &(*p)->num_elements, name))
2594 return 1;
2595 *p = 0;
2596 return optional && odr_ok(o);
2597 }
2598
2599
2600
2601
2602
2603 5.3.6. CHOICE Types
2604
2605 The choice type is used fairly often in some ASN.1 definitions, so
2606 some work has gone into streamlining its interface.
2607
2608 CHOICE types are handled by the function:
2609
2610
2611
2612 int odr_choice(ODR o, Odr_arm arm[], void *p, void *whichp,
2613 const char *name);
2614
2615
2616
2617
2618 The arm array is used to describe each of the possible types that the
2619 CHOICE type may assume. Internally in your application, the CHOICE
2620 type is represented as a discriminated union. That is, a C union
2621 accompanied by an integer (or enum) identifying the active 'arm' of
2622 the union. whichp is a pointer to the union discriminator. When
2623 encoding, it is examined to determine the current type. When decoding,
2624 it is set to reference the type that was found in the input stream.
2625
2626 The Odr_arm type is defined thus:
2627
2628
2629
2630 typedef struct odr_arm
2631 {
2632 int tagmode;
2633 int class;
2634 int tag;
2635 int which;
2636 Odr_fun fun;
2637 char *name;
2638 } Odr_arm;
2639
2640
2641 The interpretation of the fields are:
2642
2643
2644 tagmode
2645 Either ODR_IMPLICIT, ODR_EXPLICIT, or ODR_NONE (-1) to mark no
2646 tagging.
2647
2648 class, tag
2649 The class and tag of the type (-1 if no tagging is used).
2650
2651 which
2652 The value of the discriminator that corresponds to this CHOICE
2653 element. Typically, it will be a #defined constant, or an enum
2654 member.
2655
2656 fun
2657 A pointer to a function that implements the type of the CHOICE
2658 member. It may be either a standard ODR type or a type defined
2659 by yourself.
2660
2661 name
2662 Name of tag.
2663
2664 A handy way to prepare the array for use by the odr_choice() function
2665 is to define it as a static, initialized array in the beginning of
2666 your decoding/encoding function. Assume the type definition:
2667
2668
2669
2670 MyChoice ::= CHOICE {
2671 untagged INTEGER,
2672 tagged [99] IMPLICIT INTEGER,
2673 other BOOLEAN
2674 }
2675
2676
2677
2678
2679 Your C type might look like
2680
2681
2682
2683 typedef struct MyChoice
2684 {
2685 enum
2686 {
2687 MyChoice_untagged,
2688 MyChoice_tagged,
2689 MyChoice_other
2690 } which;
2691 union
2692 {
2693 int *untagged;
2694 int *tagged;
2695 bool_t *other;
2696 } u;
2697 };
2698
2699
2700
2701
2702 And your function could look like this:
2703
2704
2705
2706
2707 int myChoice(ODR o, MyChoice **p, int optional, const char *name)
2708 {
2709 static Odr_arm arm[] =
2710 {
2711 {-1, -1, -1, MyChoice_untagged, odr_integer, "untagged"},
2712 {ODR_IMPLICIT, ODR_CONTEXT, 99, MyChoice_tagged, odr_integer,
2713 "tagged"},
2714 {-1, -1, -1, MyChoice_other, odr_boolean, "other"},
2715 {-1, -1, -1, -1, 0}
2716 };
2717
2718 if (o->direction == ODR_DECODE)
2719 *p = odr_malloc(o, sizeof(**p);
2720 else if (!*p)
2721 return optional && odr_ok(o);
2722
2723 if (odr_choice(o, arm, &(*p)->u, &(*p)->which), name)
2724 return 1;
2725 *p = 0;
2726 return optional && odr_ok(o);
2727 }
2728
2729
2730
2731
2732 In some cases (say, a non-optional choice which is a member of a
2733 sequence), you can "embed" the union and its discriminator in the
2734 structure belonging to the enclosing type, and you won't need to
2735 fiddle with memory allocation to create a separate structure to wrap
2736 the discriminator and union.
2737
2738 The corresponding function is somewhat nicer in the Sun XDR interface.
2739 Most of the complexity of this interface comes from the possibility of
2740 declaring sequence elements (including CHOICEs) optional.
2741
2742 The ASN.1 specifictions naturally requires that each member of a
2743 CHOICE have a distinct tag, so they can be told apart on decoding.
2744 Sometimes it can be useful to define a CHOICE that has multiple types
2745 that share the same tag. You'll need some other mechanism, perhaps
2746 keyed to the context of the CHOICE type. In effect, we would like to
2747 introduce a level of context-sensitiveness to our ASN.1 specification.
2748 When encoding an internal representation, we have no problem, as long
2749 as each CHOICE member has a distinct discriminator value. For
2750 decoding, we need a way to tell the choice function to look for a
2751 specific arm of the table. The function
2752
2753
2754
2755 void odr_choice_bias(ODR o, int what);
2756
2757
2758
2759
2760 provides this functionality. When called, it leaves a notice for the
2761 next call to odr_choice() to be called on the decoding stream o that
2762 only the arm entry with a which field equal to what should be tried.
2763
2764 The most important application (perhaps the only one, really) is in
2765 the definition of application-specific EXTERNAL encoders/decoders
2766 which will automatically decode an ANY member given the direct or
2767 indirect reference.
2768
2769
2770
2771
2772
2773 5.4. Debugging
2774
2775 The protocol modules are suffering somewhat from a lack of diagnostic
2776 tools at the moment. Specifically ways to pretty-print PDUs that
2777 aren't recognized by the system. We'll include something to this end
2778 in a not-too-distant release. In the meantime, what we do when we get
2779 packages we don't understand is to compile the ODR module with
2780 ODR_DEBUG defined. This causes the module to dump tracing information
2781 as it processes data units. With this output and the protocol
2782 specification (Z39.50), it is generally fairly easy to see what goes
2783 wrong.
2784
2785
2786 6. The COMSTACK Module
2787
2788 6.1. Introduction
2789
2790 The COMSTACK subsystem provides a transparent interface to different
2791 types of transport stacks for the exchange of BER-encoded data. At
2792 present, the RFC1729 method (BER over TCP/IP), and Peter Furniss'
2793 XTImOSI stack are supported, but others may be added in time. The
2794 philosophy of the module is to provide a simple interface by hiding
2795 unused options and facilities of the underlying libraries. This is
2796 always done at the risk of losing generality, and it may prove that
2797 the interface will need extension later on.
2798
2799 The interface is implemented in such a fashion that only the sub-
2800 layers constructed to the transport methods that you wish to use in
2801 your application are linked in.
2802
2803 You will note that even though simplicity was a goal in the design,
2804 the interface is still orders of magnitudes more complex than the
2805 transport systems found in many other packages. One reason is that the
2806 interface needs to support the somewhat different requirements of the
2807 different lower-layer communications stacks; another important reason
2808 is that the interface seeks to provide a more or less industrial-
2809 strength approach to asynchronous event-handling. When no function is
2810 allowed to block, things get more complex - particularly on the server
2811 side. We urge you to have a look at the demonstration client and
2812 server provided with the package. They are meant to be easily readable
2813 and instructive, while still being at least moderately useful.
2814
2815
2816 6.2. Common Functions
2817
2818 6.2.1. Managing Endpoints
2819
2820
2821
2822 COMSTACK cs_create(CS_TYPE type, int blocking, int protocol);
2823
2824
2825
2826
2827 Creates an instance of the protocol stack - a communications endpoint.
2828 The type parameter determines the mode of communication. At present,
2829 the values tcpip_type and mosi_type are recognized. The function
2830 returns a null-pointer if a system error occurs. The blocking
2831 parameter should be one if you wish the association to operate in
2832 blocking mode, zero otherwise. The protocol field should be one of
2833 PROTO_SR or PROTO_Z3950.
2834
2835
2836
2837 int cs_close(COMSTACK handle);
2838
2839 Closes the connection (as elegantly as the lower layers will permit),
2840 and releases the resouces pointed to by the handle parameter. The
2841 handle should not be referenced again after this call.
2842
2843 NOTE: We really need a soft disconnect, don't we?
2844
2845
2846 6.2.2. Data Exchange
2847
2848
2849
2850 int cs_put(COMSTACK handle, char *buf, int len);
2851
2852
2853
2854
2855 Sends buf down the wire. In blocking mode, this function will return
2856 only when a full buffer has been written, or an error has occurred. In
2857 nonblocking mode, it's possible that the function will be unable to
2858 send the full buffer at once, which will be indicated by a return
2859 value of 1. The function will keep track of the number of octets
2860 already written; you should call it repeatedly with the same values of
2861 buf and len, until the buffer has been transmitted. When a full buffer
2862 has been sent, the function will return 0 for success. -1 indicates an
2863 error condition (see below).
2864
2865
2866
2867 int cs_get(COMSTACK handle, char **buf, int *size);
2868
2869
2870
2871
2872 Receives a PDU from the peer. Returns the number of bytes read. In
2873 nonblocking mode, it is possible that not all of the packet can be
2874 read at once. In this case, the function returns 1. To simplify the
2875 interface, the function is responsible for managing the size of the
2876 buffer. It will be reallocated if necessary to contain large packages,
2877 and will sometimes be moved around internally by the subsystem when
2878 partial packages are read. Before calling cs_get for the fist time,
2879 the buffer can be initialized to the null pointer, and the length
2880 should also be set to 0 - cs_get will perform a malloc(2) on the
2881 buffer for you. When a full buffer has been read, the size of the
2882 package is returned (which will always be greater than 1). -1
2883 indicates an error condition.
2884
2885 See also the cs_more() function below.
2886
2887
2888
2889 int cs_more(COMSTACK handle);
2890
2891
2892
2893
2894 The cs_more() function should be used in conjunction with cs_get and
2895 select(2). The cs_get() function will sometimes (notably in the
2896 TCP/IP mode) read more than a single protocol package off the network.
2897 When this happens, the extra package is stored by the subsystem. After
2898 calling cs_get(), and before waiting for more input, You should always
2899 call cs_more() to check if there's a full protocol package already
2900 read. If cs_more() returns 1, cs_get() can be used to immediately
2901 fetch the new package. For the mOSI subsystem, the function should
2902 always return 0, but if you want your stuff to be protocol
2903 independent, you should use it.
2904
2905 NOTE: The cs_more() function is required because the RFC1729-method
2906 does not provide a way of separating individual PDUs, short of
2907 partially decoding the BER. Some other implementations will carefully
2908 nibble at the packet by calling read(2) several times. This was felt
2909 to be too inefficient (or at least clumsy) - hence the call for this
2910 extra function.
2911
2912
2913
2914 int cs_look(COMSTACK handle);
2915
2916
2917
2918
2919 This function is useful when you're operating in nonblocking mode.
2920 Call it when select(2) tells you there's something happening on the
2921 line. It returns one of the following values:
2922
2923
2924 CS_NONE
2925 No event is pending. The data found on the line was not a
2926 complete package.
2927
2928 CS_CONNECT
2929 A response to your connect request has been received. Call
2930 cs_rcvconnect to process the event and to finalize the
2931 connection establishment.
2932
2933 CS_DISCON
2934 The other side has closed the connection (or maybe sent a
2935 disconnect request - but do we care? Maybe later). Call cs_close
2936 To close your end of the association as well.
2937
2938 CS_LISTEN
2939 A connect request has been received. Call cs_listen to process
2940 the event.
2941
2942 CS_DATA
2943 There's data to be found on the line. Call cs_get to get it.
2944
2945 NOTE: You should be aware that even if cs_look() tells you that
2946 there's an event event pending, the corresponding function may still
2947 return and tell you there was nothing to be found. This means that
2948 only part of a package was available for reading. The same event will
2949 show up again, when more data has arrived.
2950
2951
2952
2953 int cs_fileno(COMSTACK h);
2954
2955
2956
2957
2958 Returns the file descriptor of the association. Use this when file-
2959 level operations on the endpoint are required (select(2) operations,
2960 specifically).
2961
2962
2963 6.3. Client Side
2964
2965
2966
2967 int cs_connect(COMSTACK handle, void *address);
2968
2969
2970
2971 Initiate a connection with the target at address (more on addresses
2972 below). The function will return 0 on success, and 1 if the operation
2973 does not complete immediately (this will only happen on a nonblocking
2974 endpoint). In this case, use cs_rcvconnect to complete the operation,
2975 when select(2) reports input pending on the association.
2976
2977
2978
2979 int cs_rcvconnect(COMSTACK handle);
2980
2981
2982
2983
2984 Complete a connect operation initiated by cs_connect(). It will return
2985 0 on success; 1 if the operation has not yet completed (in this case,
2986 call the function again later); -1 if an error has occured.
2987
2988
2989 6.4. Server Side
2990
2991 To establish a server under the inetd server, you can use
2992
2993
2994
2995 COMSTACK cs_createbysocket(int socket, CS_TYPE type, int blocking,
2996 int protocol);
2997
2998
2999
3000
3001 The socket parameter is an established socket (when your application
3002 is invoked from inetd, the socket will typically be 0. The following
3003 parameters are identical to the ones for cs_create.
3004
3005
3006
3007 int cs_bind(COMSTACK handle, void *address, int mode)
3008
3009
3010
3011
3012 Binds a local address to the endpoint. Read about addresses below. The
3013 mode parameter should be either CS_CLIENT or CS_SERVER.
3014
3015
3016
3017 int cs_listen(COMSTACK handle, char *addr, int *addrlen);
3018
3019
3020
3021
3022 Call this to process incoming events on an endpoint that has been
3023 bound in listening mode. It will return 0 to indicate that the connect
3024 request has been received, 1 to signal a partial reception, and -1 to
3025 indicate an error condition.
3026
3027
3028
3029 COMSTACK cs_accept(COMSTACK handle);
3030
3031
3032
3033
3034 This finalises the server-side association establishment, after
3035 cs_listen has completed successfully. It returns a new connection
3036 endpoint, which represents the new association. The application will
3037 typically wish to fork off a process to handle the association at this
3038 point, and continue listen for new connections on the old handle.
3039
3040 You can use the call
3041
3042
3043
3044 char *cs_addrstr(COMSTACK);
3045
3046
3047
3048
3049 on an established connection to retrieve the hostname of the remote
3050 host.
3051
3052 NOTE: You may need to use this function with some care if your name
3053 server service is slow or unreliable
3054
3055
3056 6.5. Addresses
3057
3058 The low-level format of the addresses are different depending on the
3059 mode of communication you have chosen. A function is provided by each
3060 of the lower layers to map a user-friendly string-form address to the
3061 binary form required by the lower layers.
3062
3063
3064
3065 struct sockaddr_in *tcpip_strtoaddr(char *str);
3066
3067 struct netbuf *mosi_strtoaddr(char *str);
3068
3069
3070
3071
3072 The format for TCP/IP addresses is straightforward:
3073
3074
3075
3076 <host> [ ':' <portnum> ]
3077
3078
3079
3080
3081 The hostname can be either a domain name or an IP address. The port
3082 number, if omitted, defaults to 210.
3083
3084 For OSI, the format is
3085
3086
3087
3088 [ <t-selector> '/' ] <host> [ ':' <port> ]
3089
3090
3091
3092
3093 The transport selector is given as an even number of hex digits.
3094
3095 You'll note that the address format for the OSI mode are just a subset
3096 of full presentation addresses. We use presentation addresses because
3097 xtimosi doesn't, in itself, allow access to the X.500 Directory
3098 service. We use a limited form, because we haven't yet come across an
3099 implementation that used more of the elements of a full p-address. It
3100 is a fairly simple matter to add the rest of the elements to the
3101 address format as needed, however: Xtimosi does support the full P-
3102 address structure.
3103 In both transport modes, the special hostname "@" is mapped to any
3104 local address (the manifest constant INADDR_ANY). It is used to
3105 establish local listening endpoints in the server role.
3106
3107 When a connection has been established, you can use
3108
3109
3110
3111 char cs_addrstr(COMSTACK h);
3112
3113
3114
3115
3116 to retrieve the host name of the peer system. The function returns a
3117 pointer to a static area, which is overwritten on the next call to the
3118 function.
3119
3120 NOTE: We have left the issue of X.500 name-to-address mapping open,
3121 for the moment. It would be a simple matter to provide a table-based
3122 mapping, if desired. Alternately, we could use the X.500 client-
3123 function that is provided with the ISODE (although this would defeat
3124 some of the purpose of using ThinOSI in the first place. We have been
3125 told that it should be within the realm of the possible to implement a
3126 lightweight implementation of the necessary X.500 client capabilities
3127 on top of ThinOSI. This would be the ideal solution, we feel. On the
3128 other hand, it still remains to be seen just what role the Directory
3129 will play in a world populated by ThinOSI and other pragmatic
3130 solutions.
3131
3132
3133 6.6. Diagnostics
3134
3135 All functions return -1 if an error occurs. Typically, the functions
3136 will return 0 on success, but the data exchange functions (cs_get,
3137 cs_put, cs_more) follow special rules. Consult their descriptions.
3138
3139 When a function (including the data exchange functions) reports an
3140 error condition, use the function cs_errno() to determine the cause of
3141 the problem. The function
3142
3143
3144
3145 void cs_perror(COMSTACK handle char *message);
3146
3147
3148
3149
3150 works like perror(2) and prints the message argument, along with a
3151 system message, to stderr. Use the character array
3152
3153
3154
3155 extern const char *cs_errlist[];
3156
3157
3158
3159
3160 to get hold of the message, if you want to process it differently.
3161 The function
3162
3163
3164
3165 const char *cs_stackerr(COMSTACK handle);
3166
3167
3168
3169 Returns an error message from the lower layer, if one has been
3170 provided.
3171
3172
3173 6.7. Enabling OSI Communication
3174
3175 6.7.1. Installing Xtimosi
3176
3177 Although you will have to download Peter Furniss' XTI/mOSI
3178 implementation for yourself, we've tried to make the integration as
3179 simple as possible.
3180
3181 The latest version of xtimosi will generally be under
3182
3183
3184
3185 ftp://pluto.ulcc.ac.uk/ulcc/thinosi/xtimosi/
3186
3187
3188
3189
3190 When you have downloaded and unpacked the archive, it will (we assume)
3191 have created a directory called xtimosi. We suggest that you place
3192 this directory in the same directory where you unpacked the YAZ
3193 distribution. This way, you shouldn't have to fiddle with the
3194 makefiles of YAZ beyond uncommenting a few lines.
3195
3196 Go to xtimosi/src, and type "make libmosi.a". This should generally
3197 create the library, ready to use.
3198
3199 CAVEAT
3200
3201 The currently available release of xtimosi has some inherent problems
3202 that make it disfunction on certain platforms - eg. the Digital OSF/1
3203 workstations. It is supposedly primarily a compiler problem, and we
3204 hope to see a release that is generally portable. While we can't
3205 guarantee that it can be brought to work on your platform, we'll be
3206 happy to talk to you about problems that you might see, and relay
3207 information to the author of the software. There are some signs that
3208 the gcc compiler is more likely to produce a fully functional library,
3209 but this hasn't been verified (we think that the problem is limited to
3210 the use of hexadecimal escape-codes used in strings, which are
3211 silently ignored by some compilers).
3212
3213 A problem has been encountered in the communication with ISODE-based
3214 applications. If the ISODE presentation-user calls PReadRequest() with
3215 a timeout value different from OK or NOTOK, he will get an immediate
3216 TIMEOUT abort when receiving large (>2041 bytes, which is the SPDU-
3217 size that the ISODE likes to work with) packages from an xtimosi-based
3218 implementation (probably most other implementations as well, in fact).
3219 It seems to be a flaw in the ISODE API, and the workaround (for ISODE
3220 users) is to either not use an explicit timeout (switching to either
3221 blocking or nonblocking mode), or to check that the timer really has
3222 expired before closing the connection.
3223
3224 The next step in the installation is to modify the makefile in the
3225 toplevel YAZ directory. The place to change is in the top of the file,
3226 and is clearly marked with a comment.
3227
3228 Now run make in the YAZ toplevel directory (do a "make clean" first,
3229 if the system has been previously made without OSI support). Use the
3230 YAZ ztest and client demo programs to verify that OSI communication
3231 works OK. Then, you can go ahead and try to talk to other
3232 implementations.
3233
3234
3235 NOTE: Our interoperability experience is limited to version 7 of the
3236 Nordic SR-Nett package, which has had several protocol errors fixed
3237 from the earlier releases. If you have problems or successes in
3238 interoperating with other implementations, we'd be glad to hear about
3239 it, or to help you make things work, as our resources allow.
3240
3241 If you write your own applications based on YAZ, and you wish to
3242 include OSI support, the procedure is equally simple. You should
3243 include the xmosi.h header file in addition to comstack.h. xmosi.h
3244 will define the manifest constant mosi_type, which you should pass to
3245 the cs_create() function. In addition, you should use the function
3246 mosi_strtoaddr() rather than tcpip_strtoaddr() when you need to
3247 prepare an address.
3248
3249 When you link your application, you should include (after the libyaz.a
3250 library) the libmosi.a library, and the librfc.a library provided with
3251 YAZ (for OSI transport).
3252
3253 As always, it can be very useful, if not essential, to have a look at
3254 the example applications to see how things are done.
3255
3256
3257 6.7.2. OSI Transport
3258
3259 Xtimosi requires an implementation of the OSI transport service under
3260 the X/OPEN XTI API. We provide an implementation of the RFC1006
3261 encapsulation of OSI/TP0 in TCP/IP (through the Berkeley Sockets API),
3262 as an independent part of YAZ (it's found under the rfc1006
3263 directory). If you have access to an OSI transport provider under XTI,
3264 you should be able to make that work too, although it may require
3265 tinkering with the mosi_strtoaddr() function.
3266
3267
3268 6.7.3. Presentation Context Management
3269
3270 To simplify the implementation, we use Peter Furniss' alternative
3271 (PRF) option format for the Control of the presentation negotiation
3272 phase. This format is enabled by default when you compile xtimosi.
3273
3274 The current version of YAZ does not support presentation-layer
3275 negotiation of response record formats. The primary reason is that we
3276 have had access to no other SR or Z39.50 implementations over OSI that
3277 used this method. Secondarily, we believe that the EXPLAIN facility is
3278 a superior mechanism for relaying target capabilities in this respect.
3279 This is not to say that we have no intentions of supporting
3280 presentation context negotiation - we have just hitherto given it a
3281 lower priority than other aspects of the protocol.
3282
3283 One thing is certain: The addition of this capability to YAZ should
3284 have only a minimal impact on existing applications, and on the
3285 interface to the software in general. Most likely, we will add an
3286 extra layer of interface to the processing of EXPLAIN records, which
3287 will convert back and forth between oident records (see section
3288 ``Object Identifiers'') and direct or indirect references, given the
3289 current association setup. Implementations based on any of the higher-
3290 level interfaces will most likely not have to be changed at all.
3291
3292
3293 6.8. Summary and Synopsis
3294
3295
3296
3297
3298
3299
3300
3301 #include <comstack.h>
3302
3303 #include <tcpip.h> /* this is for TCP/IP support */
3304 #include <xmosi.h> /* and this is for mOSI support */
3305
3306 COMSTACK cs_create(CS_TYPE type, int blocking, int protocol);
3307
3308 COMSTACK cs_createbysocket(int s, CS_TYPE type, int blocking,
3309 int protocol);
3310
3311 int cs_bind(COMSTACK handle, int mode);
3312
3313 int cs_connect(COMSTACK handle, void *address);
3314
3315 int cs_rcvconnect(COMSTACK handle);
3316
3317 int cs_listen(COMSTACK handle);
3318
3319 COMSTACK cs_accept(COMSTACK handle);
3320
3321 int cs_put(COMSTACK handle, char *buf, int len);
3322
3323 int cs_get(COMSTACK handle, char **buf, int *size);
3324
3325 int cs_more(COMSTACK handle);
3326
3327 int cs_close(COMSTACK handle);
3328
3329 int cs_look(COMSTACK handle);
3330
3331 struct sockaddr_in *tcpip_strtoaddr(char *str);
3332
3333 struct netbuf *mosi_strtoaddr(char *str);
3334
3335 extern int cs_errno;
3336
3337 void cs_perror(COMSTACK handle char *message);
3338
3339 const char *cs_stackerr(COMSTACK handle);
3340
3341 extern const char *cs_errlist[];
3342
3343
3344
3345
3346
3347 7. Making an IR Interface for Your Database with YAZ
3348
3349 7.1. Introduction
3350
3351 NOTE: If you aren't into documentation, a good way to learn how the
3352 backend interface works is to look at the backend.h file. Then, look
3353 at the small dummy-server in server/ztest.c. Finally, you can have a
3354 look at the seshigh.c file, which is where most of the logic of the
3355 frontend server is located. The backend.h file also makes a good
3356 reference, once you've chewed your way through the prose of this file.
3357
3358 If you have a database system that you would like to make available by
3359 means of Z39.50/SR, YAZ basically offers your two options. You can use
3360 the APIs provided by the ASN, ODR, and COMSTACK modules to create and
3361 decode PDUs, and exchange them with a client. Using this low-level
3362 interface gives you access to all fields and options of the protocol,
3363 and you can construct your server as close to your existing database
3364 as you like. It is also a fairly involved process, requiring you to
3365 set up an event-handling mechanism, protocol state machine, etc. To
3366 simplify server implementation, we have implemented a compact and
3367 simple, but reasonably full-functioned server-frontend that will
3368 handle most of the protocol mechanics, while leaving you to
3369 concentrate on your database interface.
3370
3371 NOTE: The backend interface was designed in anticipation of a specific
3372 integration task, while still attempting to achieve some degree of
3373 generality. We realise fully that there are points where the interface
3374 can be improved significantly. If you have specific functions or
3375 parameters that you think could be useful, send us a mail (or better,
3376 sign on to the mailing list referred to in the toplevel README file).
3377 We will try to fit good suggestions into future releases, to the
3378 extent that it can be done without requiring too many structural
3379 changes in existing applications.
3380
3381
3382 7.2. The Database Frontend
3383
3384 We refer to this software as a generic database frontend. Your
3385 database system is the backend database, and the interface between the
3386 two is called the backend API. The backend API consists of a small
3387 number of function prototypes and structure definitions. You are
3388 required to provide the main() routine for the server (which can be
3389 quite simple), as well as functions to match each of the prototypes.
3390 The interface functions that you write can use any mechanism you like
3391 to communicate with your database system: You might link the whole
3392 thing together with your database application and access it by
3393 function calls; you might use IPC to talk to a database server
3394 somewhere; or you might link with third-party software that handles
3395 the communication for you (like a commercial database client library).
3396 At any rate, the functions will perform the tasks of:
3397
3398
3399 o Initialization.
3400
3401 o Searching.
3402
3403 o Fetching records.
3404
3405 o Scanning the database index (if you wish to implement SCAN).
3406
3407 (more functions will be added in time to support as much of
3408 Z39.50-1995 as possible).
3409
3410 Because the model where pipes or sockets are used to access the
3411 backend database is a fairly common one, we have added a mechanism
3412 that allows this communication to take place asynchronously. In this
3413 mode, the frontend server doesn't have to block while the backend
3414 database is processing a request, but can wait for additional PDUs
3415 from the client.
3416
3417
3418 7.3. The Backend API
3419
3420 The headers files that you need to use the interface are in the
3421 include/ directory. They are called statserv.h and backend.h. They
3422 will include other files from the include directory, so you'll
3423 probably want to use the -I option of your compiler to tell it where
3424 to find the files. When you run make in the toplevel YAZ directory,
3425 everything you need to create your server is put the lib/libyaz.a
3426 library. If you want OSI as well, you'll also need to link in the
3427 libmosi.a library from the xtimosi distribution (see the mosi.txt
3428 file), a well as the lib/librfc.a library (to provide OSI transport
3429 over RFC1006/TCP).
3430
3431
3432
3433 7.4. Your main() Routine
3434
3435 As mentioned, your main() routine can be quite brief. If you want to
3436 initialize global parameters, or read global configuration tables,
3437 this is the place to do it. At the end of the routine, you should call
3438 the function
3439
3440
3441
3442 int statserv_main(int argc, char **argv);
3443
3444
3445
3446
3447 Statserv_main will establish listening sockets according to the
3448 parameters given. When connection requests are received, the event
3449 handler will typically fork() to handle the new request. If you do use
3450 global variables, you should be aware, then, that these cannot be
3451 shared between associations, unless you explicitly disallow forking by
3452 command line parameters (we advise against this for any purposes
3453 except debugging, as a crash or hang in the server process will affect
3454 all users currently signed on to the server).
3455
3456 The server provides a mechanism for controlling some of its behavior
3457 without using command-line options. The function
3458
3459
3460
3461 statserv_options_block *statserv_getcontrol(void);
3462
3463
3464
3465
3466 Will return a pointer to a struct statserv_options_block describing
3467 the current default settings of the server. The structure contains
3468 these elements:
3469
3470
3471 int dynamic
3472 A boolean value, which determines whether the server will fork
3473 on each incoming request (TRUE), or not (FALSE). Default is
3474 TRUE.
3475
3476 int loglevel
3477 Set this by ORing the constants defined in include/log.h.
3478
3479 char logfile[ODR_MAXNAME+1]
3480 File for diagnostic output ("": stderr).
3481
3482 char apdufile[ODR_MAXNAME+1]
3483 Name of file for logging incoming and outgoing APDUs ("": don't
3484 log APDUs, "-": stderr).
3485
3486 char default_listen[1024]
3487 Same form as the command-line specification of listener address.
3488 "": no default listener address. Default is to listen at
3489 "tcp:@:9999". You can only specify one default listener address
3490 in this fashion.
3491
3492 enum oid_proto default_proto;
3493 Either PROTO_SR or PROTO_Z3950. Default is PROTO_Z39_50.
3494
3495 int idle_timeout;
3496 Maximum session idletime, in minutes. Zero indicates no
3497 (infinite) timeout. Default is 120 minutes.
3498
3499 int maxrecordsize;
3500 Maximum permissible record (message) size. Default is 1Mb. This
3501 amount of memory will only be allocated if a client requests a
3502 very large amount of records in one operation (or a big record).
3503 Set it to a lower number if you are worried about resource
3504 consumption on your host system.
3505
3506 char configname[ODR_MAXNAME+1]
3507 Passed to the backend when a new connection is received.
3508
3509 char setuid[ODR_MAXNAME+1]
3510 Set user id to the user specified, after binding the listener
3511 addresses.
3512
3513 The pointer returned by statserv_getcontrol points to a static area.
3514 You are allowed to change the contents of the structure, but the
3515 changes will not take effect before you call
3516
3517
3518
3519 void statserv_setcontrol(statserv_options_block *block);
3520
3521
3522
3523
3524 Note that you should generally update this structure before calling
3525 statserv_main().
3526
3527
3528 7.5. The Backend Functions
3529
3530 For each service of the protocol, the backend interface declares one
3531 or two functions. You are required to provide implementations of the
3532 functions representing the services that you wish to implement.
3533
3534
3535
3536 bend_initresult *bend_init(bend_initrequest *r);
3537
3538
3539
3540
3541 This function is called once for each new connection request, after a
3542 new process has been forked, and an initRequest has been received from
3543 the client. The parameter and result structures are defined as
3544
3545
3546
3547 typedef struct bend_initrequest
3548 {
3549 char *configname;
3550 } bend_initrequest;
3551
3552 typedef struct bend_initresult
3553 {
3554 int errcode; /* 0==OK */
3555 char *errstring; /* system error string or NULL */
3556 void *handle; /* private handle to the backend module */
3557 } bend_initresult;
3558
3559
3560
3561
3562 The configname of bend_initrequest is currently always set to
3563 "default-config". We haven't had use for putting anything special in
3564 the initrequest yet, but something might go there if the need arises
3565 (account/password info would be obvious).
3566
3567 In general, the server frontend expects that the bend_*result pointer
3568 that you return is valid at least until the next call to a bend_*
3569 function. This applies to all of the functions described herein. The
3570 parameter structure passed to you in the call belongs to the server
3571 frontend, and you should not make assumptions about its contents after
3572 the current function call has completed. In other words, if you want
3573 to retain any of the contents of a request structure, you should copy
3574 them.
3575
3576 The errcode should be zero if the initialization of the backend went
3577 well. Any other value will be interpreted as an error. The errstring
3578 isn't used in the current version, but one option would be to stick it
3579 in the initResponse as a VisibleString. The handle is the most
3580 important parameter. It should be set to some value that uniquely
3581 identifies the current session to the backend implementation. It is
3582 used by the frontend server in any future calls to a backend function.
3583 The typical use is to set it to point to a dynamically allocated state
3584 structure that is private to your backend module.
3585
3586
3587
3588 bend_searchresult *bend_search(void *handle, bend_searchrequest *r,
3589 int *fd);
3590 bend_searchresult *bend_searchresponse(void *handle);
3591
3592 typedef struct bend_searchrequest
3593 {
3594 char *setname; /* name to give to this set */
3595 int replace_set; /* replace set, if it already exists */
3596 int num_bases; /* number of databases in list */
3597 char **basenames; /* databases to search */
3598 Z_Query *query; /* query structure */
3599 } bend_searchrequest;
3600
3601 typedef struct bend_searchresult
3602 {
3603 int hits; /* number of hits */
3604 int errcode; /* 0==OK */
3605 char *errstring; /* system error string or NULL */
3606 } bend_searchresult;
3607
3608
3609
3610
3611 The first thing to notice about the search request interface (as well
3612 as all of the following requests), is that it consists of two separate
3613 functions. The idea is to provide a simple facility for asynchronous
3614 communication with the backend server. When a searchrequest comes in,
3615 the server frontend will fill out the bend_searchrequest tructure, and
3616 call the bend_search function. The fd argument will point to an
3617 integer variable. If you are able to do asynchronous I/O with your
3618 database server, you should set *fd to the file descriptor you use for
3619 the communication, and return a null pointer. The server frontend will
3620 then select() on the *fd, and will call bend_searchresult when it sees
3621 that data is available. If you don't support asynchronous I/O, you
3622 should return a pointer to the bend_searchresult immediately, and
3623 leave *fd untouched. This construction is common to all of the bend_
3624 functions (except bend_init). Note that you can choose to support this
3625 facility in none, any, or all of the bend_ functions, and you can
3626 respond differently on each request at run-time. The server frontend
3627 will adapt accordingly.
3628
3629 The bend_searchrequest is a fairly close approximation of a protocol
3630 searchRequest PDU. The setname is the resultSetName from the protocol.
3631 You are required to establish a mapping between the set name and
3632 whatever your backend database likes to use. Similarly, the
3633 replace_set is a boolean value corresponding to the resultSetIndicator
3634 field in the protocol. Num_bases/basenames is a length of/array of
3635 character pointers to the database names provided by the client. The
3636 query is the full query structure as defined in the protocol ASN.1
3637 specification. It can be either of the possible query types, and it's
3638 up to you to determine if you can handle the provided query type.
3639 Rather than reproduce the C interface here, we'll refer you to the
3640 structure definitions in the file include/proto.h. If you want to look
3641 at the attributeSetId OID of the RPN query, you can either match it
3642 against your own internal tables, or you can use the oid_getentbyoid
3643 function provided by YAZ.
3644
3645 The result structure contains a number of hits, and an
3646 errcode/errstring pair. If an error occurs during the search, or if
3647 you're unhappy with the request, you should set the errcode to a value
3648 from the BIB-1 diagnostic set. The value will then be returned to the
3649 user in a nonsurrogate diagnostic record in the response. The
3650 errstring, if provided, will go in the addinfo field. Look at the
3651 protocol definition for the defined error codes, and the suggested
3652 uses of the addinfo field.
3653
3654
3655
3656 bend_fetchresult *bend_fetch(void *handle, bend_fetchrequest *r,
3657 int *fd);
3658 bend_fetchresult *bend_fetchresponse(void *handle);
3659
3660 typedef struct bend_fetchrequest
3661 {
3662 char *setname; /* set name */
3663 int number; /* record number */
3664 oid_value format;
3665 } bend_fetchrequest;
3666
3667 typedef struct bend_fetchresult
3668 {
3669 char *basename; /* name of database that provided record */
3670 int len; /* length of record */
3671 char *record; /* record */
3672 int last_in_set; /* is it? */
3673 oid_value format;
3674 int errcode; /* 0==success */
3675 char *errstring; /* system error string or NULL */
3676 } bend_fetchresult;
3677
3678
3679
3680
3681 NOTE: The bend_fetchresponse() function is not yet supported in this
3682 version of the software. Your implementation of bend_fetch() should
3683 always return a pointer to a bend_fetchresult.
3684
3685 The frontend server calls bend_fetch when it needs database records to
3686 fulfill a searchRequest or a presentRequest. The setname is simply the
3687 name of the result set that holds the reference to the desired record.
3688 The number is the offset into the set (with 1 being the first record
3689 in the set). The format field is the record format requested by the
3690 client (See section ``Object Identifiers''). The value VAL_NONE
3691 indicates that the client did not request a specific format. The
3692 stream argument is an ODR stream which should be used for allocating
3693 space for structured data records. The stream will be reset when all
3694 records have been assembled, and the response package has been
3695 transmitted. For unstructured data, the backend is responsible for
3696 maintaining a static or dynamic buffer for the record between calls.
3697 In the result structure, the basename is the name of the database that
3698 holds the record. Len is the length of the record returned, in bytes,
3699 and record is a pointer to the record. Last_in_set should be nonzero
3700 only if the record returned is the last one in the given result set.
3701 Errcode and errstring, if given, will currently be interpreted as a
3702 global error pertaining to the set, and will be returned in a
3703 nonSurrogateDiagnostic.
3704
3705 NOTE: This is silly. Add a flag to say which is which.
3706
3707 If the len field has the value -1, then record is assumed to point to
3708 a constructed data type. The format field will be used to determine
3709 which encoder should be used to serialize the data.
3710
3711 NOTE: If your backend generates structured records, it should use
3712 odr_malloc() on the provided stream for allocating data: This allows
3713 the frontend server to keep track of the record sizes.
3714
3715 The format field is mapped to an object identifier in the direct
3716 reference of the resulting EXTERNAL representation of the record.
3717
3718 NOTE: The current version of YAZ only supports the direct reference
3719 mode.
3720
3721
3722
3723 bend_deleteresult *bend_delete(void *handle, bend_deleterequest *r,
3724 int *fd);
3725 bend_deleteresult *bend_deleteresponse(void *handle);
3726
3727 typedef struct bend_deleterequest
3728 {
3729 char *setname;
3730 } bend_deleterequest;
3731
3732 typedef struct bend_deleteresult
3733 {
3734 int errcode; /* 0==success */
3735 char *errstring; /* system error string or NULL */
3736 } bend_deleteresult;
3737
3738
3739
3740
3741 NOTE: The "delete" function is not yet supported in this version of
3742 the software.
3743
3744 NOTE: The delete set function definition is rather primitive, mostly
3745 because we have had no practical need for it as of yet. If someone
3746 wants to provide a full delete service, we'd be happy to add the extra
3747 parameters that are required. Are there clients out there that will
3748 actually delete sets they no longer need?
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763 bend_scanresult *bend_scan(void *handle, bend_scanrequest *r,
3764 int *fd);
3765 bend_scanresult *bend_scanresponse(void *handle);
3766
3767 typedef struct bend_scanrequest
3768 {
3769 int num_bases; /* number of elements in databaselist */
3770 char **basenames; /* databases to search */
3771 Z_AttributesPlusTerm *term;
3772 int term_position; /* desired index of term in result list */
3773 int num_entries; /* number of entries requested */
3774 } bend_scanrequest;
3775
3776 typedef struct bend_scanresult
3777 {
3778 int num_entries;
3779 struct scan_entry
3780 {
3781 char *term;
3782 int occurrences;
3783 } *entries;
3784 int term_position;
3785 enum
3786 {
3787 BEND_SCAN_SUCCESS,
3788 BEND_SCAN_PARTIAL
3789 } status;
3790 int errcode;
3791 char *errstring;
3792 } bend_scanresult;
3793
3794
3795
3796
3797 NOTE: The bend_scanresponse() function is not yet supported in this
3798 version of the software. Your implementation of bend_scan() should
3799 always return a pointer to a bend_scanresult.
3800
3801
3802 7.6. Application Invocation
3803
3804 The finished application has the following invocation syntax (by way
3805 of statserv_main()):
3806
3807
3808
3809
3810 appname [-szSu -a apdufile -l logfile -v loglevel]
3811 [listener ...]
3812
3813
3814
3815
3816 The options are
3817
3818
3819 -a APDU file. Specify a file for dumping PDUs (for diagnostic
3820 purposes). The special name "-" sends output to stderr.
3821
3822
3823 -S Don't fork on connection requests. This is good for debugging,
3824 but not recommended for real operation: Although the server is
3825 asynchronous and non-blocking, it can be nice to keep a software
3826 malfunction (okay then, a crash) from affecting all current
3827 users.
3828
3829 -s Use the SR protocol.
3830
3831
3832 -z Use the Z39.50 protocol (default). These two options complement
3833 eachother. You can use both multiple times on the same command
3834 line, between listener-specifications (see below). This way, you
3835 can set up the server to listen for connections in both
3836 protocols concurrently, on different local ports.
3837
3838
3839 -l The logfile.
3840
3841
3842 -v The log level. Use a comma-separated list of members of the set
3843 {fatal,debug,warn,log,all,none}.
3844
3845 -u Set user ID. Sets the real UID of the server process to that of
3846 the given user. It's useful if you aren't comfortable with
3847 having the server run as root, but you need to start it as such
3848 to bind a privileged port.
3849
3850
3851 -w Working directory.
3852
3853 -i Use this when running from the inetd server.
3854
3855
3856 -t Idle session timeout, in minutes.
3857
3858
3859 -k Maximum record size/message size, in kilobytes.
3860
3861
3862 A listener specification consists of a transport mode followed by a
3863 colon (:) followed by a listener address. The transport mode is either
3864 osi or tcp.
3865
3866 For TCP, an address has the form
3867
3868
3869
3870 hostname | IP-number [: portnumber]
3871
3872
3873
3874
3875 The port number defaults to 210 (standard Z39.50 port).
3876
3877 For osi, the address form is
3878
3879
3880
3881 [t-selector /] hostname | IP-number [: portnumber]
3882
3883
3884
3885
3886 The transport selector is given as a string of hex digits (with an
3887 even number of digits). The default port number is 102 (RFC1006 port).
3888
3889 Examples
3890
3891
3892
3893
3894
3895 tcp:dranet.dra.com
3896
3897 osi:0402/dbserver.osiworld.com:3000
3898
3899
3900
3901
3902 In both cases, the special hostname "@" is mapped to the address
3903 INADDR_ANY, which causes the server to listen on any local interface.
3904 To start the server listening on the registered ports for Z39.50 and
3905 SR over OSI/RFC1006, and to drop root privileges once the ports are
3906 bound, execute the server like this (from a root shell):
3907
3908
3909
3910 my-server -u daemon tcp:@ -s osi:@
3911
3912
3913
3914
3915 You can replace daemon with another user, eg. your own account, or a
3916 dedicated IR server account. my-server should be the name of your
3917 server application. You can test the procedure with the ztest
3918 application.
3919
3920
3921 7.7. Summary and Synopsis
3922
3923
3924
3925 #include <backend.h>
3926
3927 bend_initresult *bend_init(bend_initrequest *r);
3928
3929 bend_searchresult *bend_search(void *handle, bend_searchrequest *r,
3930 int *fd);
3931
3932 bend_searchresult *bend_searchresponse(void *handle);
3933
3934 bend_fetchresult *bend_fetch(void *handle, bend_fetchrequest *r,
3935 int *fd);
3936
3937 bend_fetchresult *bend_fetchresponse(void *handle);
3938
3939 bend_scanresult *bend_scan(void *handle, bend_scanrequest *r, int *fd);
3940
3941 bend_scanresult *bend_scanresponse(void *handle);
3942
3943 bend_deleteresult *bend_delete(void *handle, bend_deleterequest *r,
3944 int *fd);
3945
3946 bend_deleteresult *bend_deleteresponse(void *handle);
3947
3948 void bend_close(void *handle);
3949
3950
3951
3952
3953
3954 8. Future Directions
3955
3956 The software has been successfully ported to the Mac as well as
3957 Windows NT/95 - we'd like to test those ports better and make sure
3958 they work as they should.
3959
3960
3961 We have a new and better version of the frontend server on the drawing
3962 board. Resources and external commitments will govern when we'll be
3963 able to do something real with it. Fetures should include greater
3964 flexibility, greter support for access/resource control, and easy
3965 support for Explain (possibly with Zebra as an extra database engine).
3966
3967 We now support all PDUs of Z39.50-1995. If there is one of the
3968 supporting structures that you need but can't find in the prt*.h
3969 files, send us a note; it may be on its way.
3970
3971 The 'retrieval' module needs to be finalized and documented. We think
3972 it can form a useful resource for people dealing with complex record
3973 structures, but for now, you'll mostly have to chew through the code
3974 yourself to make use of it. Not acceptable.
3975
3976 Other than that, YAZ generally moves in the directions which appear to
3977 make the most people happy (including ourselves, as prime users of the
3978 software). If there's something you'd like to see in here, then drop
3979 us a note and let's see what we can come up with.
3980
3981
3982 9. License
3983
3984 9.1. Index Data Copyright
3985
3986 Copyright (C) 1995-2000 Index Data.
3987
3988 Permission to use, copy, modify, distribute, and sell this software
3989 and its documentation, in whole or in part, for any purpose, is hereby
3990 granted, provided that:
3991
3992 1. This copyright and permission notice appear in all copies of the
3993 software and its documentation. Notices of copyright or attribution
3994 which appear at the beginning of any file must remain unchanged.
3995
3996 2. The names of Index Data or the individual authors may not be used
3997 to endorse or promote products derived from this software without
3998 specific prior written permission.
3999
4000 THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
4001 EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
4002 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN
4003 NO EVENT SHALL INDEX DATA BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
4004 INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
4005 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT
4006 ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY,
4007 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4008 SOFTWARE.
4009
4010
4011 9.2. Additional Copyright Statements
4012
4013 The optional CCL query language interpreter is covered by the
4014 following license:
4015
4016 Copyright (C) 1995, the EUROPAGATE consortium (see below).
4017
4018 The EUROPAGATE consortium members are:
4019
4020 University College Dublin Danmarks Teknologiske Videnscenter An
4021 Chomhairle Leabharlanna Consejo Superior de Investigaciones
4022 Cientificas
4023
4024 Permission to use, copy, modify, distribute, and sell this software
4025 and its documentation, in whole or in part, for any purpose, is hereby
4026 granted, provided that:
4027 1. This copyright and permission notice appear in all copies of the
4028 software and its documentation. Notices of copyright or attribution
4029 which appear at the beginning of any file must remain unchanged.
4030
4031 2. The names of EUROPAGATE or the project partners may not be used to
4032 endorse or promote products derived from this software without
4033 specific prior written permission.
4034
4035 3. Users of this software (implementors and gateway operators) agree
4036 to inform the EUROPAGATE consortium of their use of the software. This
4037 information will be used to evaluate the EUROPAGATE project and the
4038 software, and to plan further developments. The consortium may use the
4039 information in later publications.
4040
4041 4. Users of this software agree to make their best efforts, when
4042 documenting their use of the software, to acknowledge the EUROPAGATE
4043 consortium, and the role played by the software in their work.
4044
4045 THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
4046 EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
4047 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN
4048 NO EVENT SHALL THE EUROPAGATE CONSORTIUM OR ITS MEMBERS BE LIABLE FOR
4049 ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
4050 KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
4051 PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON
4052 ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE
4053 OR PERFORMANCE OF THIS SOFTWARE.
4054
4055
4056 10. About Index Data
4057
4058 Index Data is a consulting and software-development enterprise that
4059 specialises in library and information management systems. Our
4060 interests and expertise span a broad range of related fields, and one
4061 of our primary, long-term objectives is the development of a powerful
4062 information management system with open network interfaces and
4063 hypermedia capabilities.
4064
4065 We make this software available free of charge, on a fairly
4066 unrestrictive license; as a service to the networking community, and
4067 to further the development of quality software for open network
4068 communication.
4069
4070 We'll be happy to answer questions about the software, and about
4071 ourselves in general.
4072
4073
4074
4075 Index Data
4076 Ryesgade 3
4077 DK-2200 Copenhagen N
4078
4079
4080
4081
4082
4083
4084
4085 Phone: +45 3536 3672
4086 Fax : +45 3536 0449
4087 Email: [email protected]
4088
4089
4090
4091
4092
4093 The Hacker's Jargon File has the following to say about the use of the
4094 prefix "YA" in the name of a software product.
4095
4096 Yet Another. adj. 1. Of your own work: A humorous allusion often used
4097 in titles to acknowledge that the topic is not original, though the
4098 content is. As in "Yet Another AI Group" or "Yet Another Simulated
4099 Annealing Algorithm". 2. Of others' work: Describes something of
4100 which there are already far too many.
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
Note: See TracBrowser for help on using the repository browser.