1 <chapter id="asn"><title>The Z39.50 ASN.1 Module</title>
2 <sect1 id="asn.introduction"><title>Introduction</title>
4 The &asn; module provides you with a set of C struct definitions for the
5 various PDUs of the Z39.50 protocol, as well as for the complex types
6 appearing within the PDUs. For the primitive data types, the C
7 representation often takes the form of an ordinary C language type,
8 such as <literal>int</literal>. For ASN.1 constructs that have no direct
9 representation in C, such as general octet strings and bit strings,
10 the &odr; module (see section <link linkend="odr">The ODR Module</link>)
11 provides auxiliary definitions.
14 The &asn; module is located in sub directory <filename>z39.50</filename>.
15 There you'll find C files that implements encoders and decoders for the
16 Z39.50 types. You'll also find the protocol definitions:
17 <filename>z3950v3.asn</filename>, <filename>esupdate.asn</filename>,
21 <sect1 id="asn.preparing"><title>Preparing PDUs</title>
24 A structure representing a complex ASN.1 type doesn't in itself contain the
25 members of that type. Instead, the structure contains
26 <emphasis>pointers</emphasis> to the members of the type.
27 This is necessary, in part, to allow a mechanism for specifying which
28 of the optional structure (SEQUENCE) members are present, and which
29 are not. It follows that you will need to somehow provide space for
30 the individual members of the structure, and set the pointers to
34 The conversion routines don't care how you allocate and maintain your
35 C structures - they just follow the pointers that you provide.
36 Depending on the complexity of your application, and your personal
37 taste, there are at least three different approaches that you may take
38 when you allocate the structures.
42 You can use static or automatic local variables in the function that
43 prepares the PDU. This is a simple approach, and it provides the most
44 efficient form of memory management. While it works well for flat
45 PDUs like the InitReqest, it will generally not be sufficient for say,
46 the generation of an arbitrarily complex RPN query structure.
49 You can individually create the structure and its members using the
50 <function>malloc(2)</function> function. If you want to ensure that
51 the data is freed when it is no longer needed, you will have to
52 define a function that individually releases each member of a
53 structure before freeing the structure itself.
56 You can use the <function>odr_malloc()</function> function (see
57 <xref linkend="odr.use"/> for details). When you use
58 <function>odr_malloc()</function>, you can release all of the
59 allocated data in a single operation, independent of any pointers and
60 relations between the data. <function>odr_malloc()</function> is based on a
61 "nibble-memory"
62 scheme, in which large portions of memory are allocated, and then
63 gradually handed out with each call to <function>odr_malloc()</function>.
64 The next time you call <function>odr_reset()</function>, all of the
65 memory allocated since the last call is recycled for future use (actually,
66 it is placed on a free-list).
69 You can combine all of the methods described here. This will often be
70 the most practical approach. For instance, you might use
71 <function>odr_malloc()</function> to allocate an entire structure and
72 some of its elements, while you leave other elements pointing to global
73 or per-session default variables.
77 The &asn; module provides an important aid in creating new PDUs. For
78 each of the PDU types (say, <function>Z_InitRequest</function>), a
79 function is provided that allocates and initializes an instance of
80 that PDU type for you. In the case of the InitRequest, the function is
81 simply named <function>zget_InitRequest()</function>, and it sets up
82 reasonable default value for all of the mandatory members. The optional
83 members are generally initialized to null pointers. This last aspect
84 is very important: it ensures that if the PDU definitions are
85 extended after you finish your implementation (to accommodate
86 new versions of the protocol, say), you won't get into trouble with
87 uninitialized pointers in your structures. The functions use
88 <function>odr_malloc()</function> to
89 allocate the PDUs and its members, so you can free everything again with a
90 single call to <function>odr_reset()</function>. We strongly recommend
91 that you use the <literal>zget_*</literal>
92 functions whenever you are preparing a PDU (in a C++ API, the
93 <literal>zget_</literal>
94 functions would probably be promoted to constructors for the
98 The prototype for the individual PDU types generally look like this:
101 Z_<type> *zget_<type>(ODR o);
109 Z_InitRequest *zget_InitRequest(ODR o);
113 The &odr; handle should generally be your encoding stream, but it
117 As well as the individual PDU functions, a function
118 <function>zget_APDU()</function> is provided, which allocates
119 a top-level Z-APDU of the type requested:
123 Z_APDU *zget_APDU(ODR o, int which);
127 The <varname>which</varname> parameter is (of course) the discriminator
128 belonging to the <varname>Z_APDU</varname> <literal>CHOICE</literal> type.
129 All of the interface described here is provided by the &asn; module, and
130 you access it through the <filename>proto.h</filename> header file.
134 <sect1 id="asn.external"><title>EXTERNAL Data</title>
137 In order to achieve extensibility and adaptability to different
138 application domains, the new version of the protocol defines many
139 structures outside of the main ASN.1 specification, referencing them
140 through ASN.1 EXTERNAL constructs. To simplify the construction and
141 access to the externally referenced data, the &asn; module defines a
142 specialized version of the EXTERNAL construct, called
143 <literal>Z_External</literal>.It is defined thus:
147 typedef struct Z_External
149 Odr_oid *direct_reference;
150 int *indirect_reference;
155 Z_External_single = 0,
157 Z_External_arbitrary,
161 Z_External_explainRecord,
162 Z_External_resourceReport1,
163 Z_External_resourceReport2
171 Odr_any *single_ASN1_type;
172 Odr_oct *octet_aligned;
173 Odr_bitmask *arbitrary;
177 Z_ExplainRecord *explainRecord;
178 Z_ResourceReport1 *resourceReport1;
179 Z_ResourceReport2 *resourceReport2;
188 When decoding, the &asn; module will attempt to determine which
189 syntax describes the data by looking at the reference fields
190 (currently only the direct-reference). For ASN.1 structured data, you
191 need only consult the <literal>which</literal> field to determine the
192 type of data. You can the access the data directly through the union.
193 When constructing data for encoding, you set the union pointer to point
194 to the data, and set the <literal>which</literal> field accordingly.
195 Remember also to set the direct (or indirect) reference to the correct
196 OID for the data type.
197 For non-ASN.1 data such as MARC records, use the
198 <literal>octet_aligned</literal> arm of the union.
202 Some servers return ASN.1 structured data values (eg. database
203 records) as BER-encoded records placed in the
204 <literal>octet-aligned</literal> branch of the EXTERNAL CHOICE.
205 The ASN-module will <emphasis>not</emphasis> automatically decode
206 these records. To help you decode the records in the application, the
211 Z_ext_typeent *z_ext_gettypebyref(const oid *oid);
215 Can be used to retrieve information about the known, external data
216 types. The function return a pointer to a static area, or NULL, if no
217 match for the given direct reference is found. The
218 <literal>Z_ext_typeent</literal>
223 typedef struct Z_ext_typeent
225 int oid[OID_SIZE]; /* the direct-reference OID. */
226 int what; /* discriminator value for the external CHOICE */
227 Odr_fun fun; /* decoder function */
232 The <literal>what</literal> member contains the
233 <literal>Z_External</literal> union discriminator value for the
234 given type: For the SUTRS record syntax, the value would be
235 <literal>Z_External_sutrs</literal>.
236 The <literal>fun</literal> member contains a pointer to the
237 function which encodes/decodes the given type. Again, for the SUTRS
238 record syntax, the value of <literal>fun</literal> would be
239 <literal>z_SUTRS</literal> (a function pointer).
243 If you receive an EXTERNAL which contains an octet-string value that
244 you suspect of being an ASN.1-structured data value, you can use
245 <literal>z_ext_gettypebyref</literal> to look for the provided
247 If the return value is different from NULL, you can use the provided
248 function to decode the BER string (see <xref linkend="odr.use"/>
253 If you want to <emphasis>send</emphasis> EXTERNALs containing
254 ASN.1-structured values in the occtet-aligned branch of the CHOICE, this
255 is possible too. However, on the encoding phase, it requires a somewhat
256 involved juggling around of the various buffers involved.
259 If you need to add new, externally defined data types, you must update
260 the struct above, in the source file <filename>prt-ext.h</filename>, as
261 well as the encoder/decoder in the file <filename>prt-ext.c</filename>.
262 When changing the latter, remember to update both the
263 <literal>arm</literal> arrary and the list
264 <literal>type_table</literal>, which drives the CHOICE biasing that
265 is necessary to tell the different, structured types apart
271 Eventually, the EXTERNAL processing will most likely
272 automatically insert the correct OIDs or indirect-refs. First,
273 however, we need to determine how application-context management
274 (specifically the presentation-context-list) should fit into the
280 <sect1 id="asn.pdu"><title>PDU Contents Table</title>
283 We include, for reference, a listing of the fields of each top-level
284 PDU, as well as their default settings.
287 <table frame="top" id="asn.default.initialize.request">
288 <title>Default settings for PDU Initialize Request</title>
290 <colspec colwidth="7*" colname="field"></colspec>
291 <colspec colwidth="5*" colname="type"></colspec>
292 <colspec colwidth="7*" colname="value"></colspec>
297 <entry>Default Value</entry>
302 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
305 protocolVersion</entry><entry>Odr_bitmask</entry><entry>Empty bitmask
308 options</entry><entry>Odr_bitmask</entry><entry>Empty bitmask
311 preferredMessageSize</entry><entry>int</entry><entry>30*1024
314 maximumRecordSize</entry><entry>int</entry><entry>30*1024
317 idAuthentication</entry><entry>Z_IdAuthentication</entry><entry>NULL
320 implementationId</entry><entry>char*</entry><entry>"81"
323 implementationName</entry><entry>char*</entry><entry>"YAZ"
326 implementationVersion</entry><entry>char*</entry><entry>YAZ_VERSION
329 userInformationField</entry><entry>Z_UserInformation</entry><entry>NULL
332 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
338 <table frame="top" id="asn.default.initialize.response">
339 <title>Default settings for PDU Initialize
342 <colspec colwidth="7*" colname="field"></colspec>
343 <colspec colwidth="5*" colname="type"></colspec>
344 <colspec colwidth="7*" colname="value"></colspec>
349 <entry>Default Value</entry>
354 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
357 protocolVersion</entry><entry>Odr_bitmask</entry><entry>Empty bitmask
360 options</entry><entry>Odr_bitmask</entry><entry>Empty bitmask
363 preferredMessageSize</entry><entry>int</entry><entry>30*1024
366 maximumRecordSize</entry><entry>int</entry><entry>30*1024
369 result</entry><entry>bool_t</entry><entry>TRUE
372 implementationId</entry><entry>char*</entry><entry>"id)"
375 implementationName</entry><entry>char*</entry><entry>"YAZ"
378 implementationVersion</entry><entry>char*</entry><entry>YAZ_VERSION
381 userInformationField</entry><entry>Z_UserInformation</entry><entry>NULL
384 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
390 <table frame="top" id="asn.default.search.request">
391 <title>Default settings for PDU Search Request</title>
393 <colspec colwidth="7*" colname="field"></colspec>
394 <colspec colwidth="5*" colname="type"></colspec>
395 <colspec colwidth="7*" colname="value"></colspec>
400 <entry>Default Value</entry>
405 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
408 smallSetUpperBound</entry><entry>int</entry><entry>0
411 largeSetLowerBound</entry><entry>int</entry><entry>1
414 mediumSetPresentNumber</entry><entry>int</entry><entry>0
417 replaceIndicator</entry><entry>bool_t</entry><entry>TRUE
420 resultSetName</entry><entry>char *</entry><entry>"default"
423 num_databaseNames</entry><entry>int</entry><entry>0
426 databaseNames</entry><entry>char **</entry><entry>NULL
429 smallSetElementSetNames</entry><entry>Z_ElementSetNames
433 mediumSetElementSetNames</entry><entry>Z_ElementSetNames
437 preferredRecordSyntax</entry><entry>Odr_oid</entry><entry>NULL
440 query</entry><entry>Z_Query</entry><entry>NULL
443 additionalSearchInfo</entry><entry>Z_OtherInformation
447 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
453 <table frame="top" id="asn.default.search.response">
454 <title>Default settings for PDU Search Response</title>
456 <colspec colwidth="7*" colname="field"></colspec>
457 <colspec colwidth="5*" colname="type"></colspec>
458 <colspec colwidth="7*" colname="value"></colspec>
463 <entry>Default Value</entry>
469 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
472 resultCount</entry><entry>int</entry><entry>0
475 numberOfRecordsReturned</entry><entry>int</entry><entry>0
478 nextResultSetPosition</entry><entry>int</entry><entry>0
481 searchStatus</entry><entry>bool_t</entry><entry>TRUE
484 resultSetStatus</entry><entry>int</entry><entry>NULL
487 presentStatus</entry><entry>int</entry><entry>NULL
490 records</entry><entry>Z_Records</entry><entry>NULL
493 additionalSearchInfo</entry>
494 <entry>Z_OtherInformation</entry><entry>NULL
497 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
503 <table frame="top" id="asn.default.present.request">
504 <title>Default settings for PDU Present Request</title>
506 <colspec colwidth="7*" colname="field"></colspec>
507 <colspec colwidth="5*" colname="type"></colspec>
508 <colspec colwidth="7*" colname="value"></colspec>
513 <entry>Default Value</entry>
518 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
521 resultSetId</entry><entry>char*</entry><entry>"default"
524 resultSetStartPoint</entry><entry>int</entry><entry>1
527 numberOfRecordsRequested</entry><entry>int</entry><entry>10
530 num_ranges</entry><entry>int</entry><entry>0
533 additionalRanges</entry><entry>Z_Range</entry><entry>NULL
536 recordComposition</entry><entry>Z_RecordComposition</entry><entry>NULL
539 preferredRecordSyntax</entry><entry>Odr_oid</entry><entry>NULL
542 maxSegmentCount</entry><entry>int</entry><entry>NULL
545 maxRecordSize</entry><entry>int</entry><entry>NULL
548 maxSegmentSize</entry><entry>int</entry><entry>NULL
551 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
557 <table frame="top" id="asn.default.present.response">
558 <title>Default settings for PDU Present Response</title>
560 <colspec colwidth="7*" colname="field"></colspec>
561 <colspec colwidth="5*" colname="type"></colspec>
562 <colspec colwidth="7*" colname="value"></colspec>
567 <entry>Default Value</entry>
572 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
575 numberOfRecordsReturned</entry><entry>int</entry><entry>0
578 nextResultSetPosition</entry><entry>int</entry><entry>0
581 presentStatus</entry><entry>int</entry><entry>Z_PresentStatus_success
584 records</entry><entry>Z_Records</entry><entry>NULL
587 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
593 <table frame="top" id="asn.default.delete.result.set.request">
594 <title>Default settings for Delete Result Set Request
597 <colspec colwidth="7*" colname="field"></colspec>
598 <colspec colwidth="5*" colname="type"></colspec>
599 <colspec colwidth="7*" colname="value"></colspec>
604 <entry>Default Value</entry>
608 <row><entry>referenceId
609 </entry><entry>Z_ReferenceId</entry><entry>NULL
612 deleteFunction</entry><entry>int</entry><entry>Z_DeleteResultSetRequest_list
615 num_ids</entry><entry>int</entry><entry>0
618 resultSetList</entry><entry>char**</entry><entry>NULL
621 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
627 <table frame="top" id="asn.default.delete.result.set.response">
628 <title>Default settings for Delete Result Set Response
631 <colspec colwidth="7*" colname="field"></colspec>
632 <colspec colwidth="5*" colname="type"></colspec>
633 <colspec colwidth="7*" colname="value"></colspec>
638 <entry>Default Value</entry>
643 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
646 deleteOperationStatus</entry><entry>int</entry>
647 <entry>Z_DeleteStatus_success</entry></row>
649 num_statuses</entry><entry>int</entry><entry>0
652 deleteListStatuses</entry><entry>Z_ListStatus**</entry><entry>NULL
655 numberNotDeleted</entry><entry>int</entry><entry>NULL
658 num_bulkStatuses</entry><entry>int</entry><entry>0
661 bulkStatuses</entry><entry>Z_ListStatus</entry><entry>NUL
664 deleteMessage</entry><entry>char*</entry><entry>NULL
667 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
673 <table frame="top" id="asn.default.scan.request">
674 <title>Default settings for Scan Request
677 <colspec colwidth="7*" colname="field"></colspec>
678 <colspec colwidth="5*" colname="type"></colspec>
679 <colspec colwidth="7*" colname="value"></colspec>
684 <entry>Default Value</entry>
689 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
692 num_databaseNames</entry><entry>int</entry><entry>0
695 databaseNames</entry><entry>char**</entry><entry>NULL
698 attributeSet</entry><entry>Odr_oid</entry><entry>NULL
701 termListAndStartPoint</entry><entry>Z_AttributesPlus...
702 </entry><entry>NULL</entry></row>
704 stepSize</entry><entry>int</entry><entry>NULL
707 numberOfTermsRequested</entry><entry>int</entry><entry>20
710 preferredPositionInResponse</entry><entry>int</entry><entry>NULL
713 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
719 <table frame="top" id="asn.default.scan.response">
720 <title>Default settings for Scan Response
723 <colspec colwidth="7*" colname="field"></colspec>
724 <colspec colwidth="5*" colname="type"></colspec>
725 <colspec colwidth="7*" colname="value"></colspec>
730 <entry>Default Value</entry>
736 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
739 stepSize</entry><entry>int</entry><entry>NULL
742 scanStatus</entry><entry>int</entry><entry>Z_Scan_success
745 numberOfEntriesReturned</entry><entry>int</entry><entry>0
748 positionOfTerm</entry><entry>int</entry><entry>NULL
751 entries</entry><entry>Z_ListEntris</entry><entry>NULL
754 attributeSet</entry><entry>Odr_oid</entry><entry>NULL
757 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
763 <table frame="top" id="asn.default.trigger.resource.control.request">
764 <title>Default settings for Trigger Resource Control Request </title>
766 <colspec colwidth="7*" colname="field"></colspec>
767 <colspec colwidth="5*" colname="type"></colspec>
768 <colspec colwidth="7*" colname="value"></colspec>
773 <entry>Default Value</entry>
779 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
782 requestedAction</entry><entry>int</entry><entry>
783 Z_TriggerResourceCtrl_resou..
786 prefResourceReportFormat</entry><entry>Odr_oid</entry><entry>NULL
789 resultSetWanted</entry><entry>bool_t</entry><entry>NULL
792 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
799 <table frame="top" id="asn.default.resource.control.request">
800 <title>Default settings for Resource Control Request</title>
802 <colspec colwidth="7*" colname="field"></colspec>
803 <colspec colwidth="5*" colname="type"></colspec>
804 <colspec colwidth="7*" colname="value"></colspec>
809 <entry>Default Value</entry>
815 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
818 suspendedFlag</entry><entry>bool_t</entry><entry>NULL
821 resourceReport</entry><entry>Z_External</entry><entry>NULL
824 partialResultsAvailable</entry><entry>int</entry><entry>NULL
827 responseRequired</entry><entry>bool_t</entry><entry>FALSE
830 triggeredRequestFlag</entry><entry>bool_t</entry><entry>NULL
833 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
839 <table frame="top" id="asn.default.resource.control.response">
840 <title>Default settings for Resource Control Response</title>
842 <colspec colwidth="7*" colname="field"></colspec>
843 <colspec colwidth="5*" colname="type"></colspec>
844 <colspec colwidth="7*" colname="value"></colspec>
849 <entry>Default Value</entry>
855 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
858 continueFlag</entry><entry>bool_t</entry><entry>TRUE
861 resultSetWanted</entry><entry>bool_t</entry><entry>NULL
864 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
870 <table frame="top" id="asn.default.access.control.request">
871 <title>Default settings for Access Control Request</title>
873 <colspec colwidth="7*" colname="field"></colspec>
874 <colspec colwidth="5*" colname="type"></colspec>
875 <colspec colwidth="7*" colname="value"></colspec>
880 <entry>Default Value</entry>
886 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
889 which</entry><entry>enum</entry><entry>Z_AccessRequest_simpleForm;
892 u</entry><entry>union</entry><entry>NULL
895 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
901 <table frame="top" id="asn.default.access.control.response">
902 <title>Default settings for Access Control Response</title>
904 <colspec colwidth="7*" colname="field"></colspec>
905 <colspec colwidth="5*" colname="type"></colspec>
906 <colspec colwidth="7*" colname="value"></colspec>
911 <entry>Default Value</entry>
917 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
920 which</entry><entry>enum</entry><entry>Z_AccessResponse_simpleForm
923 u</entry><entry>union</entry><entry>NULL
926 diagnostic</entry><entry>Z_DiagRec</entry><entry>NULL
929 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
935 <table frame="top" id="asn.default.segment">
936 <title>Default settings for Segment</title>
938 <colspec colwidth="7*" colname="field"></colspec>
939 <colspec colwidth="5*" colname="type"></colspec>
940 <colspec colwidth="7*" colname="value"></colspec>
945 <entry>Default Value</entry>
951 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
954 numberOfRecordsReturned</entry><entry>int</entry><entry>value=0
957 num_segmentRecords</entry><entry>int</entry><entry>0
960 segmentRecords</entry><entry>Z_NamePlusRecord</entry><entry>NULL
962 <row><entry>otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
968 <table frame="top" id="asn.default.close">
969 <title>Default settings for Close</title>
971 <colspec colwidth="7*" colname="field"></colspec>
972 <colspec colwidth="5*" colname="type"></colspec>
973 <colspec colwidth="7*" colname="value"></colspec>
978 <entry>Default Value</entry>
984 referenceId</entry><entry>Z_ReferenceId</entry><entry>NULL
987 closeReason</entry><entry>int</entry><entry>Z_Close_finished
990 diagnosticInformation</entry><entry>char*</entry><entry>NULL
993 resourceReportFormat</entry><entry>Odr_oid</entry><entry>NULL
996 resourceFormat</entry><entry>Z_External</entry><entry>NULL
999 otherInfo</entry><entry>Z_OtherInformation</entry><entry>NULL
1009 <!-- Keep this comment at the end of the file
1014 sgml-minimize-attributes:nil
1015 sgml-always-quote-attributes:t
1018 sgml-parent-document: "yaz.xml"
1019 sgml-local-catalogs: nil
1020 sgml-namecase-general:t