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

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

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

  • Property svn:keywords set to Author Date Id Revision
File size: 20.9 KB
Line 
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2<HTML>
3<HEAD>
4 <META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
5 <TITLE>YAZ User's Guide and Reference: The ASN Module</TITLE>
6 <LINK HREF="yaz-4.html" REL=next>
7 <LINK HREF="yaz-2.html" REL=previous>
8 <LINK HREF="yaz.html#toc3" REL=contents>
9</HEAD>
10<BODY>
11<A HREF="yaz-4.html">Next</A>
12<A HREF="yaz-2.html">Previous</A>
13<A HREF="yaz.html#toc3">Contents</A>
14<HR>
15<H2><A NAME="s3">3. The ASN Module</A></H2>
16
17<H2><A NAME="ss3.1">3.1 Introduction</A>
18</H2>
19
20<P>The <B>ASN</B> module provides you with a set of C struct definitions for the
21various PDUs of the protocol, as well as for the complex types
22appearing within the PDUs. For the primitive data types, the C
23representation often takes the form of an ordinary C language type,
24such as <CODE>int</CODE>. For ASN.1 constructs that have no direct
25representation in C, such as general octet strings and bit strings,
26the <B>ODR</B> module (see section
27<A HREF="yaz-5.html#odr">ODR</A>) provides auxiliary
28definitions.
29<P>
30<H2><A NAME="ss3.2">3.2 Preparing PDUs</A>
31</H2>
32
33<P>A structure representing a complex ASN.1 type doesn't in itself contain the
34members of that type. Instead, the structure contains <I>pointers</I> to
35the members of the type. This is necessary, in part, to allow a mechanism for
36specifying which of the optional structure (SEQUENCE) members are
37present, and which are not. It follows that you will need to somehow
38provide space for the individual members of the structure, and
39set the pointers to refer to the members.
40<P>The conversion routines don't care how you allocate and maintain your
41C structures - they just follow the pointers that you provide.
42Depending on the complexity of your application, and your personal
43taste, there are at least three different approaches that you may take
44when you allocate the structures.
45<P>
46<UL>
47<LI>You can use static or automatic local variables in the function that
48prepares the PDU. This is a simple approach, and it provides the most
49efficient form of memory management. While it works well for flat
50PDUs like the InitReqest, it will generally not be sufficient for say,
51the generation of an arbitrarily complex RPN query structure.</LI>
52<LI>You can individually create the structure and its members using the
53<CODE>malloc</CODE>(2) function. If you want to ensure that the data is freed when
54it is no longer needed, you will have to define a function that
55individually releases each member of a structure before freeing the
56structure itself.</LI>
57<LI>You can use the <CODE>odr_malloc()</CODE> function (see section
58<A HREF="yaz-5.html#odr-use">Using ODR</A> for details). When you use <CODE>odr_malloc()</CODE>, you can release
59all of the
60allocated data in a single operation, independent of any pointers and
61relations between the data. <CODE>odr_malloc()</CODE> is based on a
62&quot;nibble-memory&quot;
63scheme, in which large portions of memory are allocated, and then
64gradually handed out with each call to <CODE>odr_malloc()</CODE>. The next time you
65call <CODE>odr_reset()</CODE>, all of the memory allocated since the last call is
66recycled for future use (actually, it is placed on a free-list).</LI>
67<LI>You can combine all of the methods described here. This will often be
68the most practical approach. For instance, you might use <CODE>odr_malloc()</CODE> to
69allocate an entire structure and some of its elements, while you leave
70other elements pointing to global or per-session default variables.</LI>
71</UL>
72<P>The <B>ASN</B> module provides an important aid in creating new PDUs. For
73each of the PDU types (say, <CODE>Z_InitRequest</CODE>), a function is provided
74that allocates and initializes an instance of that PDU type for you.
75In the case of the InitRequest, the function is simply named
76<CODE>zget_InitRequest()</CODE>, and it sets up reasonable default value for all of
77the mandatory members. The optional members are generally initialized to null
78pointers. This last aspect is very important: it ensures that if the
79PDU definitions are extended after you finish your implementation
80(to accommodate
81new versions of the protocol, say), you won't get into trouble with
82uninitialized pointers in your structures. The functions use
83<CODE>odr_malloc()</CODE> to
84allocate the PDUs and its members, so you can free everything again with a
85single call to <CODE>odr_reset()</CODE>. We strongly recommend that you use the
86<CODE>zget_*</CODE>
87functions whenever you are preparing a PDU (in a C++ API, the
88<CODE>zget_</CODE>
89functions would probably be promoted to constructors for the
90individual types).
91<P>The prototype for the individual PDU types generally look like this:
92<P>
93<BLOCKQUOTE><CODE>
94<PRE>
95Z_&lt;type> *zget_&lt;type>(ODR o);
96</PRE>
97</CODE></BLOCKQUOTE>
98<P>eg.:
99<P>
100<BLOCKQUOTE><CODE>
101<PRE>
102Z_InitRequest *zget_InitRequest(ODR o);
103</PRE>
104</CODE></BLOCKQUOTE>
105<P>The <B>ODR</B> handle should generally be your encoding stream, but it
106needn't be.
107<P>As well as the individual PDU functions, a function <CODE>zget_APDU()</CODE> is
108provided, which allocates a toplevel Z-APDU of the type requested:
109<P>
110<BLOCKQUOTE><CODE>
111<PRE>
112Z_APDU *zget_APDU(ODR o, int which);
113</PRE>
114</CODE></BLOCKQUOTE>
115<P>The <CODE>which</CODE> parameter is (of course) the discriminator belonging to the
116<CODE>Z_APDU</CODE> CHOICE type. All of the interface described here is provided by
117the <B>ASN</B> module, and you access it through the <CODE>proto.h</CODE> header file.
118<P>
119<H2><A NAME="oid"></A> <A NAME="ss3.3">3.3 Object Identifiers</A>
120</H2>
121
122<P>When you refer to object identifiers in your application, you need to
123be aware that SR and Z39.50 use two different set of OIDs to refer to
124the same objects. To handle this easily, <B>YAZ</B> provides a utility module
125to <B>ASN</B> which provides an internal representation of the OIDs used in
126both protocols. Each oid is described by a structure:
127<P>
128<BLOCKQUOTE><CODE>
129<PRE>
130typedef struct oident
131{
132 enum oid_proto proto;
133 enum oid_class class;
134 enum oid_value value;
135 int oidsuffix[OID_SIZE];
136 char *desc;
137} oident;
138</PRE>
139</CODE></BLOCKQUOTE>
140<P>The <CODE>proto</CODE> field can be set to either <CODE>PROTO_SR</CODE> or
141<CODE>PROTO_Z3950</CODE>. The <CODE>class</CODE> might be, say, <CODE>CLASS_RECSYN</CODE>, and the
142<CODE>value</CODE> might be <CODE>VAL_USMARC</CODE> for the USMARC record format. Functions
143<P>
144<BLOCKQUOTE><CODE>
145<PRE>
146int *oid_ent_to_oid(struct oident *ent, int *dst);
147struct oident *oid_getentbyoid(int *o);
148</PRE>
149</CODE></BLOCKQUOTE>
150<P>are provided to map between object identifiers and database entries.
151If you store a member of the <CODE>oid_proto</CODE> type in your association
152state information, it's a simple matter, at runtime, to generate the
153correct OID when you need it. For decoding, you can simply ignore the
154proto field, or if you're strict, you can verify that your peer is
155using the OID family from the correct protocol. The <CODE>desc</CODE> field is
156a short, human-readable name for the PDU, useful mainly for diagnostic
157output.
158<P><I>NOTE: The old function oid_getoidbyent still exists but is
159not thread safe. Use oid_ent_to_oid instead and pass an array of
160size OID_SIZE.</I>
161<P><I>NOTE: Plans are underway to merge the two protocols into a single
162definition, with one set of object identifiers. When this happens, the
163oid module will no longer be required to support protocol
164independence, but it should still be useful as a simple OID database.</I>
165<P>
166<H2><A NAME="ss3.4">3.4 EXTERNAL Data</A>
167</H2>
168
169<P>In order to achieve extensibility and adaptability to different
170application domains, the new version of the protocol defines many
171structures outside of the main ASN.1 specification, referencing them
172through ASN.1 EXTERNAL constructs. To simplify the construction and access
173to the externally referenced data, the <B>ASN</B> module defines a
174specialized version of the EXTERNAL construct, called <CODE>Z_External</CODE>.
175It is defined thus:
176<P>
177<BLOCKQUOTE><CODE>
178<PRE>
179typedef struct Z_External
180{
181 Odr_oid *direct_reference;
182 int *indirect_reference;
183 char *descriptor;
184 enum
185 {
186 /* Generic types */
187 Z_External_single = 0,
188 Z_External_octet,
189 Z_External_arbitrary,
190
191 /* Specific types */
192 Z_External_SUTRS,
193 Z_External_explainRecord,
194 Z_External_resourceReport1,
195 Z_External_resourceReport2
196
197 ...
198
199 } which;
200 union
201 {
202 /* Generic types */
203 Odr_any *single_ASN1_type;
204 Odr_oct *octet_aligned;
205 Odr_bitmask *arbitrary;
206
207 /* Specific types */
208 Z_SUTRS *sutrs;
209 Z_ExplainRecord *explainRecord;
210 Z_ResourceReport1 *resourceReport1;
211 Z_ResourceReport2 *resourceReport2;
212
213 ...
214
215 } u;
216} Z_External;
217</PRE>
218</CODE></BLOCKQUOTE>
219<P>When decoding, the <B>ASN</B> module will attempt to determine which
220syntax describes the data by looking at the reference fields
221(currently only the direct-reference). For ASN.1 structured data, you
222need only consult the <CODE>which</CODE> field to determine the type of data.
223You can the access the data directly through the union. When
224constructing data for encoding, you set the union pointer to point to
225the data, and set the <CODE>which</CODE> field accordingly. Remember also to
226set the direct (or indirect) reference to the correct OID for the data
227type. For non-ASN.1 data such as MARC records, use the
228<CODE>octet_aligned</CODE> arm of the union.
229<P>Some servers return ASN.1 structured data values (eg. database
230records) as BER-encoded records placed in the <CODE>octet-aligned</CODE>
231branch of the EXTERNAL CHOICE. The ASN-module will <I>not</I>
232automatically decode these records. To help you decode the records in
233the application, the function
234<P>
235<BLOCKQUOTE><CODE>
236<PRE>
237Z_ext_typeent *z_ext_gettypebyref(oid_value ref);
238</PRE>
239</CODE></BLOCKQUOTE>
240<P>Can be used to retrieve information about the known, external data
241types. The function return a pointer to a static area, or NULL, if no
242match for the given direct reference is found. The <CODE>Z_ext_typeent</CODE>
243is defined as:
244<P>
245<BLOCKQUOTE><CODE>
246<PRE>
247typedef struct Z_ext_typeent
248{
249 oid_value dref; /* the direct-reference OID value. */
250 int what; /* discriminator value for the external CHOICE */
251 Odr_fun fun; /* decoder function */
252} Z_ext_typeent;
253</PRE>
254</CODE></BLOCKQUOTE>
255<P>The <CODE>what</CODE> member contains the Z_External union discriminator value
256for the given type: For the SUTRS record syntax, the value would be
257<CODE>Z_External_sutrs</CODE>. The <CODE>fun</CODE> member contains a pointer to the
258function which encodes/decodes the given type. Again, for the SUTRS
259record syntax, the value of <CODE>fun</CODE> would be <CODE>z_SUTRS</CODE> (a function
260pointer).
261<P>If you receive an EXTERNAL which contains an octet-string value that
262you suspect of being an ASN.1-structured data value, you can use
263<CODE>z_ext_gettypebyref</CODE> to look for the provided direct-reference. If
264the return value is different from NULL, you can use the provided
265function to decode the BER string (see section
266<A HREF="yaz-5.html#odr-use">Using ODR</A>).
267<P>If you want to <I>send</I> EXTERNALs containing ASN.1-structured values
268in the occtet-aligned branch of the CHOICE, this is possible too.
269However, on the encoding phase, it requires a somewhat involved
270juggling around of the various buffers involved.
271<P>If you need to add new, externally defined data types, you must update
272the struct above, in the source file <CODE>prt-ext.h</CODE>, as well as the
273encoder/decoder in the file <CODE>prt-ext.c</CODE>. When changing the latter,
274remember to update both the <CODE>arm</CODE> arrary and the list <CODE>type_table</CODE>,
275which drives the CHOICE biasing that is necessary to tell the
276different, structured types apart on decoding.
277<P><I>NOTE: Eventually, the EXTERNAL processing will most likely
278automatically insert the correct OIDs or indirect-refs. First,
279however, we need to determine how application-context management
280(specifically the presentation-context-list) should fit into the
281various modules.</I>
282<P>
283<H2><A NAME="ss3.5">3.5 PDU Contents Table</A>
284</H2>
285
286<P>We include, for reference, a listing of the fields of each top-level
287PDU, as well as their default settings.
288<P>
289<PRE>
290Z_InitRequest
291-------------
292Field Type Default value
293
294referenceId Z_ReferenceId NULL
295protocolVersion Odr_bitmask Empty bitmask
296options Odr_bitmask Empty bitmask
297preferredMessageSize int 30*1024
298maximumRecordSize int 30*1024
299idAuthentication Z_IdAuthentication NULL
300implementationId char* "YAZ (id=81)"
301implementationName char* "Index Data/YAZ"
302implementationVersion char* YAZ_VERSION
303userInformationField Z_UserInformation NULL
304otherInfo Z_OtherInformation NULL
305
306Z_InitResponse
307--------------
308Field Type Default value
309
310referenceId Z_ReferenceId NULL
311protocolVersion Odr_bitmask Empty bitmask
312options Odr_bitmask Empty bitmask
313preferredMessageSize int 30*1024
314maximumRecordSize int 30*1024
315result bool_t TRUE
316implementationId char* "YAZ (id=81)"
317implementationName char* "Index Data/YAZ"
318implementationVersion char* YAZ_VERSION
319userInformationField Z_UserInformat.. NULL
320otherInfo Z_OtherInformation NULL
321
322Z_SearchRequest
323---------------
324Field Type Default value
325
326referenceId Z_ReferenceId NULL
327smallSetUpperBound int 0
328largeSetLowerBound int 1
329mediumSetPresentNumber int 0
330replaceIndicator bool_t TRUE
331resultSetName char* "default"
332num_databaseNames int 0
333databaseNames char** NULL
334smallSetElementSetNames Z_ElementSetNames NULL
335mediumSetElementSetNames Z_ElementSetNames NULL
336preferredRecordSyntax Odr_oid NULL
337query Z_Query NULL
338additionalSearchInfo Z_OtherInformation NULL
339otherInfo Z_OtherInformation NULL
340
341Z_SearchResponse
342----------------
343Field Type Default value
344
345referenceId Z_ReferenceId NULL
346resultCount int 0
347numberOfRecordsReturned int 0
348nextResultSetPosition int 0
349searchStatus bool_t TRUE
350resultSetStatus int NULL
351presentStatus int NULL
352records Z_Records NULL
353additionalSearchInfo Z_OtherInformation NULL
354otherInfo Z_OtherInformation NULL
355
356Z_PresentRequest
357----------------
358Field Type Default value
359
360referenceId Z_ReferenceId NULL
361resultSetId char* "default"
362resultSetStartPoint int 1
363numberOfRecordsRequested int 10
364num_ranges int 0
365additionalRanges Z_Range NULL
366recordComposition Z_RecordComposition NULL
367preferredRecordSyntax Odr_oid NULL
368maxSegmentCount int NULL
369maxRecordSize int NULL
370maxSegmentSize int NULL
371otherInfo Z_OtherInformation NULL
372
373Z_PresentResponse
374-----------------
375Field Type Default value
376
377referenceId Z_ReferenceId NULL
378numberOfRecordsReturned int 0
379nextResultSetPosition int 0
380presentStatus int Z_PRES_SUCCESS
381records Z_Records NULL
382otherInfo Z_OtherInformation NULL
383
384Z_DeleteResultSetRequest
385------------------------
386Field Type Default value
387
388referenceId Z_ReferenceId NULL
389deleteFunction int Z_DeleteRequest_list
390num_ids int 0
391resultSetList char** NULL
392otherInfo Z_OtherInformation NULL
393
394Z_DeleteResultSetResponse
395-------------------------
396Field Type Default value
397
398referenceId Z_ReferenceId NULL
399deleteOperationStatus int Z_DeleteStatus_success
400num_statuses int 0
401deleteListStatuses Z_ListStatus** NULL
402numberNotDeleted int NULL
403num_bulkStatuses int 0
404bulkStatuses Z_ListStatus NULL
405deleteMessage char* NULL
406otherInfo Z_OtherInformation NULL
407
408Z_ScanRequest
409-------------
410Field Type Default value
411
412referenceId Z_ReferenceId NULL
413num_databaseNames int 0
414databaseNames char** NULL
415attributeSet Odr_oid NULL
416termListAndStartPoint Z_AttributesPlus... NULL
417stepSize int NULL
418numberOfTermsRequested int 20
419preferredPositionInResponse int NULL
420otherInfo Z_OtherInformation NULL
421
422Z_ScanResponse
423--------------
424Field Type Default value
425
426referenceId Z_ReferenceId NULL
427stepSize int NULL
428scanStatus int Z_Scan_success
429numberOfEntriesReturned int 0
430positionOfTerm int NULL
431entries Z_ListEntris NULL
432attributeSet Odr_oid NULL
433otherInfo Z_OtherInformation NULL
434
435Z_TriggerResourceControlRequest
436-------------------------------
437Field Type Default value
438
439referenceId Z_ReferenceId NULL
440requestedAction int Z_TriggerResourceCtrl_resou..
441prefResourceReportFormat Odr_oid NULL
442resultSetWanted bool_t NULL
443otherInfo Z_OtherInformation NULL
444
445Z_ResourceControlRequest
446------------------------
447Field Type Default value
448
449referenceId Z_ReferenceId NULL
450suspendedFlag bool_t NULL
451resourceReport Z_External NULL
452partialResultsAvailable int NULL
453responseRequired bool_t FALSE
454triggeredRequestFlag bool_t NULL
455otherInfo Z_OtherInformation NULL
456
457Z_ResourceControlResponse
458-------------------------
459Field Type Default value
460
461referenceId Z_ReferenceId NULL
462continueFlag bool_t TRUE
463resultSetWanted bool_t NULL
464otherInfo Z_OtherInformation NULL
465
466Z_AccessControlRequest
467----------------------
468Field Type Default value
469
470referenceId Z_ReferenceId NULL
471which enum Z_AccessRequest_simpleForm;
472u union NULL
473otherInfo Z_OtherInformation NULL
474
475Z_AccessControlResponse
476-----------------------
477Field Type Default value
478
479referenceId Z_ReferenceId NULL
480which enum Z_AccessResponse_simpleForm
481u union NULL
482diagnostic Z_DiagRec NULL
483otherInfo Z_OtherInformation NULL
484
485Z_Segment
486---------
487Field Type Default value
488
489referenceId Z_ReferenceId NULL
490numberOfRecordsReturned int value=0
491num_segmentRecords int 0
492segmentRecords Z_NamePlusRecord NULL
493otherInfo Z_OtherInformation NULL
494
495Z_Close
496-------
497Field Type Default value
498
499referenceId Z_ReferenceId NULL
500closeReason int Z_Close_finished
501diagnosticInformation char* NULL
502resourceReportFormat Odr_oid NULL
503resourceFormat Z_External NULL
504otherInfo Z_OtherInformation NULL
505</PRE>
506<P>
507<HR>
508<A HREF="yaz-4.html">Next</A>
509<A HREF="yaz-2.html">Previous</A>
510<A HREF="yaz.html#toc3">Contents</A>
511</BODY>
512</HTML>
Note: See TracBrowser for help on using the repository browser.