1 <chapter id="odr"><title>The ODR Module</title>
3 <sect1 id="odr.introduction"><title>Introduction</title>
6 &odr; is the BER-encoding/decoding subsystem of &yaz;. Care as been taken
7 to isolate &odr; from the rest of the package - specifically from the
8 transport interface. &odr; may be used in any context where basic
9 ASN.1/BER representations are used.
13 If you are only interested in writing a Z39.50 implementation based on
14 the PDUs that are already provided with &yaz;, you only need to concern
15 yourself with the section on managing ODR streams
16 (<xref linkend="odr.use"/>). Only if you need to
17 implement ASN.1 beyond that which has been provided, should you
18 worry about the second half of the documentation
19 (<xref linkend="odr.programming"/>).
20 If you use one of the higher-level interfaces, you can skip this
25 This is important, so we'll repeat it for emphasis: <emphasis>You do
26 not need to read <xref linkend="odr.programming"/>
27 to implement Z39.50 with &yaz;.</emphasis>
31 If you need a part of the protocol that isn't already in &yaz;, you
32 should contact the authors before going to work on it yourself: We
33 might already be working on it. Conversely, if you implement a useful
34 part of the protocol before us, we'd be happy to include it in a
39 <sect1 id="odr.use"><title>Using ODR</title>
41 <sect2 id="odr.streams"><title>ODR Streams</title>
44 Conceptually, the ODR stream is the source of encoded data in the
45 decoding mode; when encoding, it is the receptacle for the encoded
46 data. Before you can use an ODR stream it must be allocated. This is
47 done with the function
51 ODR odr_createmem(int direction);
55 The <function>odr_createmem()</function> function takes as argument one
56 of three manifest constants: <literal>ODR_ENCODE</literal>,
57 <literal>ODR_DECODE</literal>, or <literal>ODR_PRINT</literal>.
58 An &odr; stream can be in only one mode - it is not possible to change
59 its mode once it's selected. Typically, your program will allocate
60 at least two ODR streams - one for decoding, and one for encoding.
64 When you're done with the stream, you can use
68 void odr_destroy(ODR o);
72 to release the resources allocated for the stream.
76 <sect2 id="odr.memory.management"><title id="memory">Memory Management</title>
79 Two forms of memory management take place in the &odr; system. The first
80 one, which has to do with allocating little bits of memory (sometimes
81 quite large bits of memory, actually) when a protocol package is
82 decoded, and turned into a complex of interlinked structures. This
83 section deals with this system, and how you can use it for your own
84 purposes. The next section deals with the memory management which is
85 required when encoding data - to make sure that a large enough buffer is
86 available to hold the fully encoded PDU.
90 The &odr; module has its own memory management system, which is
91 used whenever memory is required. Specifically, it is used to allocate
92 space for data when decoding incoming PDUs. You can use the memory
93 system for your own purposes, by using the function
97 void *odr_malloc(ODR o, int size);
101 You can't use the normal <function>free(2)</function> routine to free
102 memory allocated by this function, and &odr; doesn't provide a parallel
103 function. Instead, you can call
107 void odr_reset(ODR o);
111 when you are done with the
112 memory: Everything allocated since the last call to
113 <function>odr_reset()</function> is released.
114 The <function>odr_reset()</function> call is also required to clear
115 up an error condition on a stream.
123 int odr_total(ODR o);
127 returns the number of bytes allocated on the stream since the last call to
128 <function>odr_reset()</function>.
132 The memory subsystem of &odr; is fairly efficient at allocating and
133 releasing little bits of memory. Rather than managing the individual,
134 small bits of space, the system maintains a free-list of larger chunks
135 of memory, which are handed out in small bits. This scheme is
136 generally known as a <emphasis>nibble memory</emphasis> system.
137 It is very useful for maintaining short-lived constructions such
142 If you want to retain a bit of memory beyond the next call to
143 <function>odr_reset()</function>, you can use the function
147 ODR_MEM odr_extract_mem(ODR o);
151 This function will give you control of the memory recently allocated
152 on the ODR stream. The memory will live (past calls to
153 <function>odr_reset()</function>), until you call the function
157 void odr_release_mem(ODR_MEM p);
161 The opaque <literal>ODR_MEM</literal> handle has no other purpose than
162 referencing the memory block for you until you want to release it.
166 You can use <function>odr_extract_mem()</function> repeatedly between
167 allocating data, to retain individual control of separate chunks of data.
171 <sect2 id="odr.encoding.and.decoding"><title>Encoding and Decoding Data</title>
174 When encoding data, the ODR stream will write the encoded octet string
175 in an internal buffer. To retrieve the data, use the function
179 char *odr_getbuf(ODR o, int *len, int *size);
183 The integer pointed to by len is set to the length of the encoded
184 data, and a pointer to that data is returned. <literal>*size</literal>
185 is set to the size of the buffer (unless <literal>size</literal> is null,
186 signaling that you are not interested in the size). The next call to
187 a primitive function using the same &odr; stream will overwrite the
188 data, unless a different buffer has been supplied using the call
192 void odr_setbuf(ODR o, char *buf, int len, int can_grow);
196 which sets the encoding (or decoding) buffer used by
197 <literal>o</literal> to <literal>buf</literal>, using the length
198 <literal>len</literal>.
199 Before a call to an encoding function, you can use
200 <function>odr_setbuf()</function> to provide the stream with an encoding
201 buffer of sufficient size (length). The <literal>can_grow</literal>
202 parameter tells the encoding &odr; stream whether it is allowed to use
203 <function>realloc(2)</function> to increase the size of the buffer when
204 necessary. The default condition of a new encoding stream is equivalent
205 to the results of calling
209 odr_setbuf(stream, 0, 0, 1);
213 In this case, the stream will allocate and reallocate memory as
214 necessary. The stream reallocates memory by repeatedly doubling the
215 size of the buffer - the result is that the buffer will typically
216 reach its maximum, working size with only a small number of reallocation
217 operations. The memory is freed by the stream when the latter is destroyed,
218 unless it was assigned by the user with the <literal>can_grow</literal>
219 parameter set to zero (in this case, you are expected to retain
220 control of the memory yourself).
224 To assume full control of an encoded buffer, you must first call
225 <function>odr_getbuf()</function> to fetch the buffer and its length.
226 Next, you should call <function>odr_setbuf()</function> to provide a
227 different buffer (or a null pointer) to the stream. In the simplest
228 case, you will reuse the same buffer over and over again, and you
229 will just need to call <function>odr_getbuf()</function> after each
230 encoding operation to get the length and address of the buffer.
231 Note that the stream may reallocate the buffer during an encoding
232 operation, so it is necessary to retrieve the correct address after
233 each encoding operation.
237 It is important to realize that the ODR stream will not release this
238 memory when you call <function>odr_reset()</function>: It will
239 merely update its internal pointers to prepare for the encoding of a
241 When the stream is released by the <function>odr_destroy()</function>
242 function, the memory given to it by <function>odr_setbuf</function> will
243 be released <emphasis>only</emphasis> if the <literal>can_grow</literal>
244 parameter to <function>odr_setbuf()</function> was nonzero. The
245 <literal>can_grow</literal> parameter, in other words, is a way of
246 signaling who is to own the buffer, you or the ODR stream. If you never call
247 <function>odr_setbuf()</function> on your encoding stream, which is
248 typically the case, the buffer allocated by the stream will belong to
249 the stream by default.
253 When you wish to decode data, you should first call
254 <function>odr_setbuf()</function>, to tell the decoding stream
255 where to find the encoded data, and how long the buffer is
256 (the <literal>can_grow</literal> parameter is ignored by a decoding
257 stream). After this, you can call the function corresponding to the
258 data you wish to decode (eg, <function>odr_integer()</function> odr
259 <function>z_APDU()</function>).
262 <example id="example.odr.encoding.and.decoding.functions">
263 <title>Encoding and decoding functions</title>
265 int odr_integer(ODR o, int **p, int optional, const char *name);
267 int z_APDU(ODR o, Z_APDU **p, int optional, const char *name);
272 If the data is absent (or doesn't match the tag corresponding to
273 the type), the return value will be either 0 or 1 depending on the
274 <literal>optional</literal> flag. If <literal>optional</literal>
275 is 0 and the data is absent, an error flag will be raised in the
276 stream, and you'll need to call <function>odr_reset()</function> before
277 you can use the stream again. If <literal>optional</literal> is
278 nonzero, the pointer <emphasis>pointed</emphasis> to/ by
279 <literal>p</literal> will be set to the null value, and the function
281 The <literal>name</literal> argument is used to pretty-print the
282 tag in question. It may be set to <literal>NULL</literal> if
283 pretty-printing is not desired.
287 If the data value is found where it's expected, the pointer
288 <emphasis>pointed to</emphasis> by the <literal>p</literal> argument
289 will be set to point to the decoded type.
290 The space for the type will be allocated and owned by the &odr;
291 stream, and it will live until you call
292 <function>odr_reset()</function> on the stream. You cannot use
293 <function>free(2)</function> to release the memory.
294 You can decode several data elements (by repeated calls to
295 <function>odr_setbuf()</function> and your decoding function), and
296 new memory will be allocated each time. When you do call
297 <function>odr_reset()</function>, everything decoded since the
298 last call to <function>odr_reset()</function> will be released.
301 <example id="example.odr.encoding.of.integer">
302 <title>Encoding and decoding of an integer</title>
304 The use of the double indirection can be a little confusing at first
305 (its purpose will become clear later on, hopefully),
306 so an example is in order. We'll encode an integer value, and
307 immediately decode it again using a different stream. A useless, but
308 informative operation.
310 <programlisting><![CDATA[
311 void do_nothing_useful(int value)
318 /* allocate streams */
319 if (!(encode = odr_createmem(ODR_ENCODE)))
321 if (!(decode = odr_createmem(ODR_DECODE)))
325 if (odr_integer(encode, &valp, 0, 0) == 0)
327 printf("encoding went bad\n");
330 bufferp = odr_getbuf(encode, &len, 0);
331 printf("length of encoded data is %d\n", len);
333 /* now let's decode the thing again */
334 odr_setbuf(decode, bufferp, len, 0);
335 if (odr_integer(decode, &resvalp, 0, 0) == 0)
337 printf("decoding went bad\n");
340 printf("the value is %d\n", *resvalp);
349 This looks like a lot of work, offhand. In practice, the &odr; streams
350 will typically be allocated once, in the beginning of your program
351 (or at the beginning of a new network session), and the encoding
352 and decoding will only take place in a few, isolated places in your
353 program, so the overhead is quite manageable.
359 <sect2 id="odr.printing"><title>Printing</title>
361 When an ODR stream is created of type <literal>ODR_PRINT</literal>
362 the ODR module will print the contents of a PDU in a readable format.
363 By default output is written to the <literal>stderr</literal> stream.
364 This behavior can be changed, however, by calling the function
366 odr_setprint(ODR o, FILE *file);
368 before encoders or decoders are being invoked.
369 It is also possible to direct the output to a buffer (of indeed
370 another file), by using the more generic mechanism:
372 void odr_set_stream(ODR o, void *handle,
373 void (*stream_write)(ODR o, void *handle, int type,
374 const char *buf, int len),
375 void (*stream_close)(void *handle));
377 Here the user provides an opaque handle and two handlers,
378 <replaceable>stream_write</replaceable> for writing,
379 and <replaceable>stream_close</replaceable> which is supposed
380 to close/free resources associated with handle.
381 The <replaceable>stream_close</replaceable> handler is optional and
382 if NULL for the function is provided, it will not be invoked.
383 The <replaceable>stream_write</replaceable> takes the ODR handle
384 as parameter, the user defined handle, a type
385 <literal>ODR_OCTETSTRING</literal>, <literal>ODR_VISIBLESTRING</literal>
386 which indicates the type of contents is being written.
389 Another utility useful for diagnostics (error handling) or as
390 part of the printing facilities is:
392 const char **odr_get_element_path(ODR o);
394 which returns a list of current elements that ODR deals with at the
395 moment. For the returned array, say <literal>ar</literal>,
396 <literal>ar[0]</literal> is the top level element,
397 <literal>ar[n]</literal> is the last. The last element has the
398 property that <literal>ar[n+1] == NULL</literal>.
400 <example id="example.odr.element.path.record">
401 <title>Element Path for record</title>
403 For a database record part of a PresentResponse the
404 array returned by <function>odr_get_element</function>
405 is <literal>presentResponse</literal>, <literal>databaseOrSurDiagnostics</literal>, <literal>?</literal>, <literal>record</literal>, <literal>?</literal>, <literal>databaseRecord</literal> . The question mark appears due to
406 unnamed constructions.
410 <sect2 id="odr.diagnostics"><title>Diagnostics</title>
413 The encoding/decoding functions all return 0 when an error occurs.
414 Until you call <function>odr_reset()</function>, you cannot use the
415 stream again, and any function called will immediately return 0.
419 To provide information to the programmer or administrator, the function
423 void odr_perror(ODR o, char *message);
427 is provided, which prints the <literal>message</literal> argument to
428 <literal>stderr</literal> along with an error message from the stream.
432 You can also use the function
436 int odr_geterror(ODR o);
440 to get the current error number from the screen. The number will be
441 one of these constants:
444 <table frame="top" id="odr.error.codes">
445 <title>ODR Error codes</title>
450 <entry>Description</entry>
455 <entry>OMEMORY</entry><entry>Memory allocation failed.</entry>
459 <entry>OSYSERR</entry><entry>A system- or library call has failed.
460 The standard diagnostic variable <literal>errno</literal> should be
461 examined to determine the actual error.</entry>
465 <entry>OSPACE</entry><entry>No more space for encoding.
466 This will only occur when the user has explicitly provided a
467 buffer for an encoding stream without allowing the system to
468 allocate more space.</entry>
472 <entry>OREQUIRED</entry><entry>This is a common protocol error; A
473 required data element was missing during encoding or decoding.</entry>
477 <entry>OUNEXPECTED</entry><entry>An unexpected data element was
478 found during decoding.</entry>
481 <row><entry>OOTHER</entry><entry>Other error. This is typically an
482 indication of misuse of the &odr; system by the programmer, and also
483 that the diagnostic system isn't as good as it should be, yet.</entry>
490 The character string array
498 can be indexed by the error code to obtain a human-readable
499 representation of the problem.
503 <sect2 id="odr.summary.and.synopsis">
504 <title>Summary and Synopsis</title>
507 #include <yaz/odr.h>
509 ODR odr_createmem(int direction);
511 void odr_destroy(ODR o);
513 void odr_reset(ODR o);
515 char *odr_getbuf(ODR o, int *len, int *size);
517 void odr_setbuf(ODR o, char *buf, int len, int can_grow);
519 void *odr_malloc(ODR o, int size);
521 NMEM odr_extract_mem(ODR o);
523 int odr_geterror(ODR o);
525 void odr_perror(ODR o, const char *message);
527 extern char *odr_errlist[];
533 <sect1 id="odr.programming"><title>Programming with ODR</title>
536 The API of &odr; is designed to reflect the structure of ASN.1, rather
537 than BER itself. Future releases may be able to represent data in
538 other external forms.
543 There is an ASN.1 tutorial available at
544 <ulink url="&url.asn.1.tutorial;">this site</ulink>.
545 This site also has standards for ASN.1 (X.680) and BER (X.690)
546 <ulink url="&url.asn.1.standards;">online</ulink>.
551 The ODR interface is based loosely on that of the Sun Microsystems
553 Specifically, each function which corresponds to an ASN.1 primitive
554 type has a dual function. Depending on the settings of the ODR
555 stream which is supplied as a parameter, the function may be used
556 either to encode or decode data. The functions that can be built
557 using these primitive functions, to represent more complex data types,
558 share this quality. The result is that you only have to enter the
559 definition for a type once - and you have the functionality of encoding,
560 decoding (and pretty-printing) all in one unit.
561 The resulting C source code is quite compact, and is a pretty
562 straightforward representation of the source ASN.1 specification.
566 In many cases, the model of the XDR functions works quite well in this
568 In others, it is less elegant. Most of the hassle comes from the optional
569 SEQUENCE members which don't exist in XDR.
572 <sect2 id="odr.primitive.asn1.types">
573 <title>The Primitive ASN.1 Types</title>
576 ASN.1 defines a number of primitive types (many of which correspond
577 roughly to primitive types in structured programming languages, such as C).
580 <sect3 id="odr.integer"><title>INTEGER</title>
583 The &odr; function for encoding or decoding (or printing) the ASN.1
584 INTEGER type looks like this:
588 int odr_integer(ODR o, int **p, int optional, const char *name);
592 (we don't allow values that can't be contained in a C integer.)
596 This form is typical of the primitive &odr; functions. They are named
597 after the type of data that they encode or decode. They take an &odr;
598 stream, an indirect reference to the type in question, and an
599 <literal>optional</literal> flag (corresponding to the OPTIONAL keyword
600 of ASN.1) as parameters. They all return an integer value of either one
602 When you use the primitive functions to construct encoders for complex
603 types of your own, you should follow this model as well. This
604 ensures that your new types can be reused as elements in yet more
609 The <literal>o</literal> parameter should obviously refer to a properly
610 initialized &odr; stream of the right type (encoding/decoding/printing)
611 for the operation that you wish to perform.
615 When encoding or printing, the function first looks at
616 <literal>* p</literal>. If <literal>* p</literal> (the pointer pointed
617 to by <literal>p</literal>) is a null pointer, this is taken to mean that
618 the data element is absent. If the <literal>optional</literal> parameter
619 is nonzero, the function will return one (signifying success) without
620 any further processing. If the <literal>optional</literal> is zero, an
621 internal error flag is set in the &odr; stream, and the function will
622 return 0. No further operations can be carried out on the stream without
623 a call to the function <function>odr_reset()</function>.
627 If <literal>*p</literal> is not a null pointer, it is expected to
628 point to an instance of the data type. The data will be subjected to
629 the encoding rules, and the result will be placed in the buffer held
634 The other ASN.1 primitives have similar functions that operate in
638 <sect3 id="odr.boolean"><title>BOOLEAN</title>
641 int odr_bool(ODR o, bool_t **p, int optional, const char *name);
645 <sect3 id="odr.real"><title>REAL</title>
652 <sect3 id="odr.null"><title>NULL</title>
655 int odr_null(ODR o, bool_t **p, int optional, const char *name);
659 In this case, the value of **p is not important. If <literal>*p</literal>
660 is different from the null pointer, the null value is present, otherwise
665 <sect3 id="odr.octet.string"><title>OCTET STRING</title>
668 typedef struct odr_oct
675 int odr_octetstring(ODR o, Odr_oct **p, int optional,
680 The <literal>buf</literal> field should point to the character array
681 that holds the octetstring. The <literal>len</literal> field holds the
682 actual length, while the <literal>size</literal> field gives the size
683 of the allocated array (not of interest to you, in most cases).
684 The character array need not be null terminated.
688 To make things a little easier, an alternative is given for string
689 types that are not expected to contain embedded NULL characters (eg.
694 int odr_cstring(ODR o, char **p, int optional, const char *name);
698 Which encoded or decodes between OCTETSTRING representations and
699 null-terminates C strings.
703 Functions are provided for the derived string types, eg:
707 int odr_visiblestring(ODR o, char **p, int optional,
712 <sect3 id="odr.bit.string"><title>BIT STRING</title>
715 int odr_bitstring(ODR o, Odr_bitmask **p, int optional,
720 The opaque type <literal>Odr_bitmask</literal> is only suitable for
721 holding relatively brief bit strings, eg. for options fields, etc.
722 The constant <literal>ODR_BITMASK_SIZE</literal> multiplied by 8
723 gives the maximum possible number of bits.
727 A set of macros are provided for manipulating the
728 <literal>Odr_bitmask</literal> type:
732 void ODR_MASK_ZERO(Odr_bitmask *b);
734 void ODR_MASK_SET(Odr_bitmask *b, int bitno);
736 void ODR_MASK_CLEAR(Odr_bitmask *b, int bitno);
738 int ODR_MASK_GET(Odr_bitmask *b, int bitno);
742 The functions are modeled after the manipulation functions that
743 accompany the <literal>fd_set</literal> type used by the
744 <function>select(2)</function> call.
745 <literal>ODR_MASK_ZERO</literal> should always be called first on a
746 new bitmask, to initialize the bits to zero.
750 <sect3 id="odr.object.identifier"><title>OBJECT IDENTIFIER</title>
753 int odr_oid(ODR o, Odr_oid **p, int optional, const char *name);
757 The C OID representation is simply an array of integers, terminated by
758 the value -1 (the <literal>Odr_oid</literal> type is synonymous with
759 the <literal>short</literal> type).
760 We suggest that you use the OID database module (see
761 <xref linkend="tools.oid.database"/>) to handle object identifiers
767 <sect2 id="odr.tagging.primitive.types"><title>Tagging Primitive Types</title> <!-- tag.prim -->
770 The simplest way of tagging a type is to use the
771 <function>odr_implicit_tag()</function> or
772 <function>odr_explicit_tag()</function> macros:
776 int odr_implicit_tag(ODR o, Odr_fun fun, int class, int tag,
777 int optional, const char *name);
779 int odr_explicit_tag(ODR o, Odr_fun fun, int class, int tag,
780 int optional, const char *name);
784 To create a type derived from the integer type by implicit tagging, you
789 MyInt ::= [210] IMPLICIT INTEGER
793 In the &odr; system, this would be written like:
797 int myInt(ODR o, int **p, int optional, const char *name)
799 return odr_implicit_tag(o, odr_integer, p,
800 ODR_CONTEXT, 210, optional, name);
805 The function <function>myInt()</function> can then be used like any of
806 the primitive functions provided by &odr;. Note that the behavior of
807 <function>odr_explicit_tag()</function>
808 and <function>odr_implicit_tag()</function> macros
809 act exactly the same as the functions they are applied to - they
810 respond to error conditions, etc, in the same manner - they
811 simply have three extra parameters. The class parameter may
812 take one of the values: <literal>ODR_CONTEXT</literal>,
813 <literal>ODR_PRIVATE</literal>, <literal>ODR_UNIVERSAL</literal>, or
814 <literal>/ODR_APPLICATION</literal>.
818 <sect2 id="odr.constructed.types"><title>Constructed Types</title>
821 Constructed types are created by combining primitive types. The
822 &odr; system only implements the SEQUENCE and SEQUENCE OF constructions
823 (although adding the rest of the container types should be simple
824 enough, if the need arises).
828 For implementing SEQUENCEs, the functions
832 int odr_sequence_begin(ODR o, void *p, int size, const char *name);
833 int odr_sequence_end(ODR o);
841 The <function>odr_sequence_begin()</function> function should be
842 called in the beginning of a function that implements a SEQUENCE type.
843 Its parameters are the &odr; stream, a pointer (to a pointer to the type
844 you're implementing), and the <literal>size</literal> of the type
845 (typically a C structure). On encoding, it returns 1 if
846 <literal>* p</literal> is a null pointer. The <literal>size</literal>
847 parameter is ignored. On decoding, it returns 1 if the type is found in
848 the data stream. <literal>size</literal> bytes of memory are allocated,
849 and <literal>*p</literal> is set to point to this space.
850 <function>odr_sequence_end()</function> is called at the end of the
851 complex function. Assume that a type is defined like this:
855 MySequence ::= SEQUENCE {
857 boolval BOOLEAN OPTIONAL
862 The corresponding &odr; encoder/decoder function and the associated data
863 structures could be written like this:
867 typedef struct MySequence
873 int mySequence(ODR o, MySequence **p, int optional, const char *name)
875 if (odr_sequence_begin(o, p, sizeof(**p), name) == 0)
876 return optional && odr_ok(o);
878 odr_integer(o, &(*p)->intval, 0, "intval") &&
879 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
886 Note the 1 in the call to <function>odr_bool()</function>, to mark
887 that the sequence member is optional.
888 If either of the member types had been tagged, the macros
889 <function>odr_implicit_tag()</function> or
890 <function>odr_explicit_tag()</function>
891 could have been used.
892 The new function can be used exactly like the standard functions provided
893 with &odr;. It will encode, decode or pretty-print a data value of the
894 <literal>MySequence</literal> type. We like to name types with an
895 initial capital, as done in ASN.1 definitions, and to name the
896 corresponding function with the first character of the name in lower case.
897 You could, of course, name your structures, types, and functions any way
898 you please - as long as you're consistent, and your code is easily readable.
899 <literal>odr_ok</literal> is just that - a predicate that returns the
900 state of the stream. It is used to ensure that the behavior of the new
901 type is compatible with the interface of the primitive types.
905 <sect2 id="odr.tagging.constructed.types">
906 <title>Tagging Constructed Types</title>
910 See <xref linkend="odr.tagging.primitive.types"/> for information on how to tag
911 the primitive types, as well as types that are already defined.
915 <sect3 id="odr.implicit.tagging">
916 <title>Implicit Tagging</title>
919 Assume the type above had been defined as
923 MySequence ::= [10] IMPLICIT SEQUENCE {
925 boolval BOOLEAN OPTIONAL
930 You would implement this in &odr; by calling the function
934 int odr_implicit_settag(ODR o, int class, int tag);
938 which overrides the tag of the type immediately following it. The
939 macro <function>odr_implicit_tag()</function> works by calling
940 <function>odr_implicit_settag()</function> immediately
941 before calling the function pointer argument.
942 Your type function could look like this:
946 int mySequence(ODR o, MySequence **p, int optional, const char *name)
948 if (odr_implicit_settag(o, ODR_CONTEXT, 10) == 0 ||
949 odr_sequence_begin(o, p, sizeof(**p), name) == 0)
950 return optional && odr_ok(o);
952 odr_integer(o, &(*p)->intval, 0, "intval") &&
953 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
959 The definition of the structure <literal>MySequence</literal> would be
964 <sect3 id="odr.explicit.tagging"><title>Explicit Tagging</title>
967 Explicit tagging of constructed types is a little more complicated,
968 since you are in effect adding a level of construction to the data.
972 Assume the definition:
976 MySequence ::= [10] IMPLICIT SEQUENCE {
978 boolval BOOLEAN OPTIONAL
983 Since the new type has an extra level of construction, two new functions
984 are needed to encapsulate the base type:
988 int odr_constructed_begin(ODR o, void *p, int class, int tag,
991 int odr_constructed_end(ODR o);
995 Assume that the IMPLICIT in the type definition above were replaced
996 with EXPLICIT (or that the IMPLICIT keyword were simply deleted, which
997 would be equivalent). The structure definition would look the same,
998 but the function would look like this:
1002 int mySequence(ODR o, MySequence **p, int optional, const char *name)
1004 if (odr_constructed_begin(o, p, ODR_CONTEXT, 10, name) == 0)
1005 return optional && odr_ok(o);
1006 if (o->direction == ODR_DECODE)
1007 *p = odr_malloc(o, sizeof(**p));
1008 if (odr_sequence_begin(o, p, sizeof(**p), 0) == 0)
1010 *p = 0; /* this is almost certainly a protocol error */
1014 odr_integer(o, &(*p)->intval, 0, "intval") &&
1015 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
1016 odr_sequence_end(o) &&
1017 odr_constructed_end(o);
1022 Notice that the interface here gets kind of nasty. The reason is
1023 simple: Explicitly tagged, constructed types are fairly rare in
1024 the protocols that we care about, so the
1025 esthetic annoyance (not to mention the dangers of a cluttered
1026 interface) is less than the time that would be required to develop a
1027 better interface. Nevertheless, it is far from satisfying, and it's a
1028 point that will be worked on in the future. One option for you would
1029 be to simply apply the <function>odr_explicit_tag()</function> macro to
1030 the first function, and not
1031 have to worry about <function>odr_constructed_*</function> yourself.
1032 Incidentally, as you might have guessed, the
1033 <function>odr_sequence_</function> functions are themselves
1034 implemented using the <function>/odr_constructed_</function> functions.
1039 <sect2 id="odr.sequence.of"><title>SEQUENCE OF</title>
1042 To handle sequences (arrays) of a specific type, the function
1046 int odr_sequence_of(ODR o, int (*fun)(ODR o, void *p, int optional),
1047 void *p, int *num, const char *name);
1051 The <literal>fun</literal> parameter is a pointer to the decoder/encoder
1052 function of the type. <literal>p</literal> is a pointer to an array of
1053 pointers to your type. <literal>num</literal> is the number of elements
1062 MyArray ::= SEQUENCE OF INTEGER
1066 The C representation might be
1070 typedef struct MyArray
1078 And the function might look like
1082 int myArray(ODR o, MyArray **p, int optional, const char *name)
1084 if (o->direction == ODR_DECODE)
1085 *p = odr_malloc(o, sizeof(**p));
1086 if (odr_sequence_of(o, odr_integer, &(*p)->elements,
1087 &(*p)->num_elements, name))
1090 return optional && odr_ok(o);
1095 <sect2 id="odr.choice.types"><title>CHOICE Types</title>
1098 The choice type is used fairly often in some ASN.1 definitions, so
1099 some work has gone into streamlining its interface.
1103 CHOICE types are handled by the function:
1107 int odr_choice(ODR o, Odr_arm arm[], void *p, void *whichp,
1112 The <literal>arm</literal> array is used to describe each of the possible
1113 types that the CHOICE type may assume. Internally in your application,
1114 the CHOICE type is represented as a discriminated union. That is, a
1115 C union accompanied by an integer (or enum) identifying the active
1117 <literal>whichp</literal> is a pointer to the union discriminator.
1118 When encoding, it is examined to determine the current type.
1119 When decoding, it is set to reference the type that was found in
1124 The Odr_arm type is defined thus:
1128 typedef struct odr_arm
1140 The interpretation of the fields are:
1144 <varlistentry><term>tagmode</term>
1145 <listitem><para>Either <literal>ODR_IMPLICIT</literal>,
1146 <literal>ODR_EXPLICIT</literal>, or <literal>ODR_NONE</literal> (-1)
1147 to mark no tagging.</para></listitem>
1150 <varlistentry><term>which</term>
1151 <listitem><para>The value of the discriminator that corresponds to
1152 this CHOICE element. Typically, it will be a #defined constant, or
1153 an enum member.</para></listitem>
1156 <varlistentry><term>fun</term>
1157 <listitem><para>A pointer to a function that implements the type of
1158 the CHOICE member. It may be either a standard &odr; type or a type
1159 defined by yourself.</para></listitem>
1162 <varlistentry><term>name</term>
1163 <listitem><para>Name of tag.</para></listitem>
1168 A handy way to prepare the array for use by the
1169 <function>odr_choice()</function> function is to
1170 define it as a static, initialized array in the beginning of your
1171 decoding/encoding function. Assume the type definition:
1175 MyChoice ::= CHOICE {
1177 tagged [99] IMPLICIT INTEGER,
1183 Your C type might look like
1187 typedef struct MyChoice
1205 And your function could look like this:
1209 int myChoice(ODR o, MyChoice **p, int optional, const char *name)
1211 static Odr_arm arm[] =
1213 {-1, -1, -1, MyChoice_untagged, odr_integer, "untagged"},
1214 {ODR_IMPLICIT, ODR_CONTEXT, 99, MyChoice_tagged, odr_integer,
1216 {-1, -1, -1, MyChoice_other, odr_boolean, "other"},
1220 if (o->direction == ODR_DECODE)
1221 *p = odr_malloc(o, sizeof(**p);
1223 return optional && odr_ok(o);
1225 if (odr_choice(o, arm, &(*p)->u, &(*p)->which), name)
1228 return optional && odr_ok(o);
1233 In some cases (say, a non-optional choice which is a member of a
1234 sequence), you can "embed" the union and its discriminator in the
1235 structure belonging to the enclosing type, and you won't need to
1236 fiddle with memory allocation to create a separate structure to
1237 wrap the discriminator and union.
1241 The corresponding function is somewhat nicer in the Sun XDR interface.
1242 Most of the complexity of this interface comes from the possibility of
1243 declaring sequence elements (including CHOICEs) optional.
1247 The ASN.1 specifications naturally requires that each member of a
1248 CHOICE have a distinct tag, so they can be told apart on decoding.
1249 Sometimes it can be useful to define a CHOICE that has multiple types
1250 that share the same tag. You'll need some other mechanism, perhaps
1251 keyed to the context of the CHOICE type. In effect, we would like to
1252 introduce a level of context-sensitiveness to our ASN.1 specification.
1253 When encoding an internal representation, we have no problem, as long
1254 as each CHOICE member has a distinct discriminator value. For
1255 decoding, we need a way to tell the choice function to look for a
1256 specific arm of the table. The function
1260 void odr_choice_bias(ODR o, int what);
1264 provides this functionality. When called, it leaves a notice for the next
1265 call to <function>odr_choice()</function> to be called on the decoding
1266 stream <literal>o</literal> that only the <literal>arm</literal> entry with
1267 a <literal>which</literal> field equal to <literal>what</literal>
1272 The most important application (perhaps the only one, really) is in
1273 the definition of application-specific EXTERNAL encoders/decoders
1274 which will automatically decode an ANY member given the direct or
1281 <sect1 id="odr.debugging"><title>Debugging</title>
1284 The protocol modules are suffering somewhat from a lack of diagnostic
1285 tools at the moment. Specifically ways to pretty-print PDUs that
1286 aren't recognized by the system. We'll include something to this end
1287 in a not-too-distant release. In the meantime, what we do when we get
1288 packages we don't understand is to compile the ODR module with
1289 <literal>ODR_DEBUG</literal> defined. This causes the module to dump tracing
1290 information as it processes data units. With this output and the
1291 protocol specification (Z39.50), it is generally fairly easy to see
1296 <!-- Keep this comment at the end of the file
1301 sgml-minimize-attributes:nil
1302 sgml-always-quote-attributes:t
1305 sgml-parent-document: "yaz.xml"
1306 sgml-local-catalogs: nil
1307 sgml-namecase-general:t