1 <!-- $Id: odr.xml,v 1.14 2004-08-13 07:30:06 adam Exp $ -->
2 <chapter id="odr"><title>The ODR Module</title>
4 <sect1 id="odr.introduction"><title>Introduction</title>
7 &odr; is the BER-encoding/decoding subsystem of &yaz;. Care as been taken
8 to isolate &odr; from the rest of the package - specifically from the
9 transport interface. &odr; may be used in any context where basic
10 ASN.1/BER representations are used.
14 If you are only interested in writing a Z39.50 implementation based on
15 the PDUs that are already provided with &yaz;, you only need to concern
16 yourself with the section on managing ODR streams
17 (<xref linkend="odr.use"/>). Only if you need to
18 implement ASN.1 beyond that which has been provided, should you
19 worry about the second half of the documentation
20 (<xref linkend="odr.programming"/>).
21 If you use one of the higher-level interfaces, you can skip this
26 This is important, so we'll repeat it for emphasis: <emphasis>You do
27 not need to read <xref linkend="odr.programming"/>
28 to implement Z39.50 with &yaz;.</emphasis>
32 If you need a part of the protocol that isn't already in &yaz;, you
33 should contact the authors before going to work on it yourself: We
34 might already be working on it. Conversely, if you implement a useful
35 part of the protocol before us, we'd be happy to include it in a
40 <sect1 id="odr.use"><title>Using ODR</title>
42 <sect2><title>ODR Streams</title>
45 Conceptually, the ODR stream is the source of encoded data in the
46 decoding mode; when encoding, it is the receptacle for the encoded
47 data. Before you can use an ODR stream it must be allocated. This is
48 done with the function
52 ODR odr_createmem(int direction);
56 The <function>odr_createmem()</function> function takes as argument one
57 of three manifest constants: <literal>ODR_ENCODE</literal>,
58 <literal>ODR_DECODE</literal>, or <literal>ODR_PRINT</literal>.
59 An &odr; stream can be in only one mode - it is not possible to change
60 its mode once it's selected. Typically, your program will allocate
61 at least two ODR streams - one for decoding, and one for encoding.
65 When you're done with the stream, you can use
69 void odr_destroy(ODR o);
73 to release the resources allocated for the stream.
77 <sect2><title id="memory">Memory Management</title>
80 Two forms of memory management take place in the &odr; system. The first
81 one, which has to do with allocating little bits of memory (sometimes
82 quite large bits of memory, actually) when a protocol package is
83 decoded, and turned into a complex of interlinked structures. This
84 section deals with this system, and how you can use it for your own
85 purposes. The next section deals with the memory management which is
86 required when encoding data - to make sure that a large enough buffer is
87 available to hold the fully encoded PDU.
91 The &odr; module has its own memory management system, which is
92 used whenever memory is required. Specifically, it is used to allocate
93 space for data when decoding incoming PDUs. You can use the memory
94 system for your own purposes, by using the function
98 void *odr_malloc(ODR o, int size);
102 You can't use the normal <function>free(2)</function> routine to free
103 memory allocated by this function, and &odr; doesn't provide a parallel
104 function. Instead, you can call
108 void odr_reset(ODR o, int size);
112 when you are done with the
113 memory: Everything allocated since the last call to
114 <function>odr_reset()</function> is released.
115 The <function>odr_reset()</function> call is also required to clear
116 up an error condition on a stream.
124 int odr_total(ODR o);
128 returns the number of bytes allocated on the stream since the last call to
129 <function>odr_reset()</function>.
133 The memory subsystem of &odr; is fairly efficient at allocating and
134 releasing little bits of memory. Rather than managing the individual,
135 small bits of space, the system maintains a free-list of larger chunks
136 of memory, which are handed out in small bits. This scheme is
137 generally known as a <emphasis>nibble memory</emphasis> system.
138 It is very useful for maintaining short-lived constructions such
143 If you want to retain a bit of memory beyond the next call to
144 <function>odr_reset()</function>, you can use the function
148 ODR_MEM odr_extract_mem(ODR o);
152 This function will give you control of the memory recently allocated
153 on the ODR stream. The memory will live (past calls to
154 <function>odr_reset()</function>), until you call the function
158 void odr_release_mem(ODR_MEM p);
162 The opaque <literal>ODR_MEM</literal> handle has no other purpose than
163 referencing the memory block for you until you want to release it.
167 You can use <function>odr_extract_mem()</function> repeatedly between
168 allocating data, to retain individual control of separate chunks of data.
172 <sect2><title>Encoding and Decoding Data</title>
175 When encoding data, the ODR stream will write the encoded octet string
176 in an internal buffer. To retrieve the data, use the function
180 char *odr_getbuf(ODR o, int *len, int *size);
184 The integer pointed to by len is set to the length of the encoded
185 data, and a pointer to that data is returned. <literal>*size</literal>
186 is set to the size of the buffer (unless <literal>size</literal> is null,
187 signaling that you are not interested in the size). The next call to
188 a primitive function using the same &odr; stream will overwrite the
189 data, unless a different buffer has been supplied using the call
193 void odr_setbuf(ODR o, char *buf, int len, int can_grow);
197 which sets the encoding (or decoding) buffer used by
198 <literal>o</literal> to <literal>buf</literal>, using the length
199 <literal>len</literal>.
200 Before a call to an encoding function, you can use
201 <function>odr_setbuf()</function> to provide the stream with an encoding
202 buffer of sufficient size (length). The <literal>can_grow</literal>
203 parameter tells the encoding &odr; stream whether it is allowed to use
204 <function>realloc(2)</function> to increase the size of the buffer when
205 necessary. The default condition of a new encoding stream is equivalent
206 to the results of calling
210 odr_setbuf(stream, 0, 0, 1);
214 In this case, the stream will allocate and reallocate memory as
215 necessary. The stream reallocates memory by repeatedly doubling the
216 size of the buffer - the result is that the buffer will typically
217 reach its maximum, working size with only a small number of reallocation
218 operations. The memory is freed by the stream when the latter is destroyed,
219 unless it was assigned by the user with the <literal>can_grow</literal>
220 parameter set to zero (in this case, you are expected to retain
221 control of the memory yourself).
225 To assume full control of an encoded buffer, you must first call
226 <function>odr_getbuf()</function> to fetch the buffer and its length.
227 Next, you should call <function>odr_setbuf()</function> to provide a
228 different buffer (or a null pointer) to the stream. In the simplest
229 case, you will reuse the same buffer over and over again, and you
230 will just need to call <function>odr_getbuf()</function> after each
231 encoding operation to get the length and address of the buffer.
232 Note that the stream may reallocate the buffer during an encoding
233 operation, so it is necessary to retrieve the correct address after
234 each encoding operation.
238 It is important to realize that the ODR stream will not release this
239 memory when you call <function>odr_reset()</function>: It will
240 merely update its internal pointers to prepare for the encoding of a
242 When the stream is released by the <function>odr_destroy()</function>
243 function, the memory given to it by <function>odr_setbuf</function> will
244 be released <emphasis>only</emphasis> if the <literal>can_grow</literal>
245 parameter to <function>odr_setbuf()</function> was nonzero. The
246 <literal>can_grow</literal> parameter, in other words, is a way of
247 signaling who is to own the buffer, you or the ODR stream. If you never call
248 <function>odr_setbuf()</function> on your encoding stream, which is
249 typically the case, the buffer allocated by the stream will belong to
250 the stream by default.
254 When you wish to decode data, you should first call
255 <function>odr_setbuf()</function>, to tell the decoding stream
256 where to find the encoded data, and how long the buffer is
257 (the <literal>can_grow</literal> parameter is ignored by a decoding
258 stream). After this, you can call the function corresponding to the
259 data you wish to decode (eg, <function>odr_integer()</function> odr
260 <function>z_APDU()</function>).
263 <example><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><title>Encoding and decoding of an integer</title>
303 The use of the double indirection can be a little confusing at first
304 (its purpose will become clear later on, hopefully),
305 so an example is in order. We'll encode an integer value, and
306 immediately decode it again using a different stream. A useless, but
307 informative operation.
309 <programlisting><![CDATA[
310 void do_nothing_useful(int value)
317 /* allocate streams */
318 if (!(encode = odr_createmem(ODR_ENCODE)))
320 if (!(decode = odr_createmem(ODR_DECODE)))
324 if (odr_integer(encode, &valp, 0, 0) == 0)
326 printf("encoding went bad\n");
329 bufferp = odr_getbuf(encode, &len);
330 printf("length of encoded data is %d\n", len);
332 /* now let's decode the thing again */
333 odr_setbuf(decode, bufferp, len);
334 if (odr_integer(decode, &resvalp, 0, 0) == 0)
336 printf("decoding went bad\n");
339 printf("the value is %d\n", *resvalp);
348 This looks like a lot of work, offhand. In practice, the &odr; streams
349 will typically be allocated once, in the beginning of your program
350 (or at the beginning of a new network session), and the encoding
351 and decoding will only take place in a few, isolated places in your
352 program, so the overhead is quite manageable.
358 <sect2><title>Printing</title>
360 When an ODR stream is created of type <literal>ODR_PRINT</literal>
361 the ODR module will print the contents of a PDU in a readable format.
362 By default output is written to the <literal>stderr</literal> stream.
363 This behavior can be changed, however, by calling the function
365 odr_setprint(ODR o, FILE *file);
367 before encoders or decoders are being invoked.
368 It is also possible to direct the output to a buffer (of indeed
369 another file), by using the more generic mechanism:
371 void odr_set_stream(ODR o, void *handle,
372 void (*stream_write)(ODR o, void *handle, int type,
373 const char *buf, int len),
374 void (*stream_close)(void *handle));
376 Here the user provides an opaque handle and two handlers,
377 <replaceable>stream_write</replaceable> for writing,
378 and <replaceable>stream_close</replaceable> which is supposed
379 to close/free resources associated with handle.
380 The <replaceable>stream_close</replaceable> handler is optional and
381 if NULL for the function is provided, it will not be invoked.
382 The <replaceable>stream_write</replaceable> takes the ODR handle
383 as parameter, the user defined handle, a type
384 <literal>ODR_OCTETSTRING</literal>, <literal>ODR_VISIBLESTRING</literal>
385 which indicates the type of contents is being written.
388 Another utility useful for diagnostics (error handling) or as
389 part of the printing facilities is:
391 const char **odr_get_element_path(ODR o);
393 which returns a list of current elements that ODR deals with at the
394 moment. For the returned array, say <literal>ar</literal>,
395 <literal>ar[0]</literal> is the top level element,
396 <literal>ar[n]</literal> is the last. The last element has the
397 property that <literal>ar[n+1] == NULL</literal>.
400 <title>Element Path for record</title>
402 For a database record part of a PresentResponse the
403 array returned by <function>odr_get_element</function>
404 is <literal>presentResponse</literal>, <literal>databaseOrSurDiagnostics</literal>, <literal>?</literal>, <literal>record</literal>, <literal>?</literal>, <literal>databaseRecord</literal> . The question mark appears due to
405 unnamed constructions.
409 <sect2><title>Diagnostics</title>
412 The encoding/decoding functions all return 0 when an error occurs.
413 Until you call <function>odr_reset()</function>, you cannot use the
414 stream again, and any function called will immediately return 0.
418 To provide information to the programmer or administrator, the function
422 void odr_perror(ODR o, char *message);
426 is provided, which prints the <literal>message</literal> argument to
427 <literal>stderr</literal> along with an error message from the stream.
431 You can also use the function
435 int odr_geterror(ODR o);
439 to get the current error number from the screen. The number will be
440 one of these constants:
443 <table frame="top"><title>ODR Error codes</title>
448 <entry>Description</entry>
453 <entry>OMEMORY</entry><entry>Memory allocation failed.</entry>
457 <entry>OSYSERR</entry><entry>A system- or library call has failed.
458 The standard diagnostic variable <literal>errno</literal> should be
459 examined to determine the actual error.</entry>
463 <entry>OSPACE</entry><entry>No more space for encoding.
464 This will only occur when the user has explicitly provided a
465 buffer for an encoding stream without allowing the system to
466 allocate more space.</entry>
470 <entry>OREQUIRED</entry><entry>This is a common protocol error; A
471 required data element was missing during encoding or decoding.</entry>
475 <entry>OUNEXPECTED</entry><entry>An unexpected data element was
476 found during decoding.</entry>
479 <row><entry>OOTHER</entry><entry>Other error. This is typically an
480 indication of misuse of the &odr; system by the programmer, and also
481 that the diagnostic system isn't as good as it should be, yet.</entry>
488 The character string array
492 char *odr_errlist[]
496 can be indexed by the error code to obtain a human-readable
497 representation of the problem.
501 <sect2><title>Summary and Synopsis</title>
506 ODR odr_createmem(int direction);
508 void odr_destroy(ODR o);
510 void odr_reset(ODR o);
512 char *odr_getbuf(ODR o, int *len);
514 void odr_setbuf(ODR o, char *buf, int len);
516 void *odr_malloc(ODR o, int size);
518 ODR_MEM odr_extract_mem(ODR o);
520 void odr_release_mem(ODR_MEM r);
522 int odr_geterror(ODR o);
524 void odr_perror(char *message);
526 extern char *odr_errlist[];
532 <sect1 id="odr.programming"><title>Programming with ODR</title>
535 The API of &odr; is designed to reflect the structure of ASN.1, rather
536 than BER itself. Future releases may be able to represent data in
537 other external forms.
542 There is an ASN.1 tutorial available at
543 <ulink url="http://asn1.elibel.tm.fr/en/introduction/">this site</ulink>.
544 This site also has standards for ASN.1 (X.680) and BER (X.690)
545 <ulink url="http://asn1.elibel.tm.fr/en/standards/">online</ulink>.
550 The ODR interface is based loosely on that of the Sun Microsystems
552 Specifically, each function which corresponds to an ASN.1 primitive
553 type has a dual function. Depending on the settings of the ODR
554 stream which is supplied as a parameter, the function may be used
555 either to encode or decode data. The functions that can be built
556 using these primitive functions, to represent more complex data types,
557 share this quality. The result is that you only have to enter the
558 definition for a type once - and you have the functionality of encoding,
559 decoding (and pretty-printing) all in one unit.
560 The resulting C source code is quite compact, and is a pretty
561 straightforward representation of the source ASN.1 specification.
565 In many cases, the model of the XDR functions works quite well in this
567 In others, it is less elegant. Most of the hassle comes from the optional
568 SEQUENCE members which don't exist in XDR.
571 <sect2><title>The Primitive ASN.1 Types</title>
574 ASN.1 defines a number of primitive types (many of which correspond
575 roughly to primitive types in structured programming languages, such as C).
578 <sect3><title>INTEGER</title>
581 The &odr; function for encoding or decoding (or printing) the ASN.1
582 INTEGER type looks like this:
586 int odr_integer(ODR o, int **p, int optional, const char *name);
590 (we don't allow values that can't be contained in a C integer.)
594 This form is typical of the primitive &odr; functions. They are named
595 after the type of data that they encode or decode. They take an &odr;
596 stream, an indirect reference to the type in question, and an
597 <literal>optional</literal> flag (corresponding to the OPTIONAL keyword
598 of ASN.1) as parameters. They all return an integer value of either one
600 When you use the primitive functions to construct encoders for complex
601 types of your own, you should follow this model as well. This
602 ensures that your new types can be reused as elements in yet more
607 The <literal>o</literal> parameter should obviously refer to a properly
608 initialized &odr; stream of the right type (encoding/decoding/printing)
609 for the operation that you wish to perform.
613 When encoding or printing, the function first looks at
614 <literal>* p</literal>. If <literal>* p</literal> (the pointer pointed
615 to by <literal>p</literal>) is a null pointer, this is taken to mean that
616 the data element is absent. If the <literal>optional</literal> parameter
617 is nonzero, the function will return one (signifying success) without
618 any further processing. If the <literal>optional</literal> is zero, an
619 internal error flag is set in the &odr; stream, and the function will
620 return 0. No further operations can be carried out on the stream without
621 a call to the function <function>odr_reset()</function>.
625 If <literal>*p</literal> is not a null pointer, it is expected to
626 point to an instance of the data type. The data will be subjected to
627 the encoding rules, and the result will be placed in the buffer held
632 The other ASN.1 primitives have similar functions that operate in
636 <sect3><title>BOOLEAN</title>
639 int odr_bool(ODR o, bool_t **p, int optional, const char *name);
643 <sect3><title>REAL</title>
650 <sect3><title>NULL</title>
653 int odr_null(ODR o, bool_t **p, int optional, const char *name);
657 In this case, the value of **p is not important. If <literal>*p</literal>
658 is different from the null pointer, the null value is present, otherwise
663 <sect3><title>OCTET STRING</title>
666 typedef struct odr_oct
673 int odr_octetstring(ODR o, Odr_oct **p, int optional,
678 The <literal>buf</literal> field should point to the character array
679 that holds the octetstring. The <literal>len</literal> field holds the
680 actual length, while the <literal>size</literal> field gives the size
681 of the allocated array (not of interest to you, in most cases).
682 The character array need not be null terminated.
686 To make things a little easier, an alternative is given for string
687 types that are not expected to contain embedded NULL characters (eg.
692 int odr_cstring(ODR o, char **p, int optional, const char *name);
696 Which encoded or decodes between OCTETSTRING representations and
697 null-terminates C strings.
701 Functions are provided for the derived string types, eg:
705 int odr_visiblestring(ODR o, char **p, int optional,
710 <sect3><title>BIT STRING</title>
713 int odr_bitstring(ODR o, Odr_bitmask **p, int optional,
718 The opaque type <literal>Odr_bitmask</literal> is only suitable for
719 holding relatively brief bit strings, eg. for options fields, etc.
720 The constant <literal>ODR_BITMASK_SIZE</literal> multiplied by 8
721 gives the maximum possible number of bits.
725 A set of macros are provided for manipulating the
726 <literal>Odr_bitmask</literal> type:
730 void ODR_MASK_ZERO(Odr_bitmask *b);
732 void ODR_MASK_SET(Odr_bitmask *b, int bitno);
734 void ODR_MASK_CLEAR(Odr_bitmask *b, int bitno);
736 int ODR_MASK_GET(Odr_bitmask *b, int bitno);
740 The functions are modeled after the manipulation functions that
741 accompany the <literal>fd_set</literal> type used by the
742 <function>select(2)</function> call.
743 <literal>ODR_MASK_ZERO</literal> should always be called first on a
744 new bitmask, to initialize the bits to zero.
748 <sect3><title>OBJECT IDENTIFIER</title>
751 int odr_oid(ODR o, Odr_oid **p, int optional, const char *name);
755 The C OID representation is simply an array of integers, terminated by
756 the value -1 (the <literal>Odr_oid</literal> type is synonymous with
757 the <literal>int</literal> type).
758 We suggest that you use the OID database module (see
759 <xref linkend="asn.oid"/>) to handle object identifiers
765 <sect2 id="tag.prim"><title>Tagging Primitive Types</title>
768 The simplest way of tagging a type is to use the
769 <function>odr_implicit_tag()</function> or
770 <function>odr_explicit_tag()</function> macros:
774 int odr_implicit_tag(ODR o, Odr_fun fun, int class, int tag,
775 int optional, const char *name);
777 int odr_explicit_tag(ODR o, Odr_fun fun, int class, int tag,
778 int optional, const char *name);
782 To create a type derived from the integer type by implicit tagging, you
787 MyInt ::= [210] IMPLICIT INTEGER
791 In the &odr; system, this would be written like:
795 int myInt(ODR o, int **p, int optional, const char *name)
797 return odr_implicit_tag(o, odr_integer, p,
798 ODR_CONTEXT, 210, optional, name);
803 The function <function>myInt()</function> can then be used like any of
804 the primitive functions provided by &odr;. Note that the behavior of
805 <function>odr_explicit_tag()</function>
806 and <function>odr_implicit_tag()</function> macros
807 act exactly the same as the functions they are applied to - they
808 respond to error conditions, etc, in the same manner - they
809 simply have three extra parameters. The class parameter may
810 take one of the values: <literal>ODR_CONTEXT</literal>,
811 <literal>ODR_PRIVATE</literal>, <literal>ODR_UNIVERSAL</literal>, or
812 <literal>/ODR_APPLICATION</literal>.
816 <sect2><title>Constructed Types</title>
819 Constructed types are created by combining primitive types. The
820 &odr; system only implements the SEQUENCE and SEQUENCE OF constructions
821 (although adding the rest of the container types should be simple
822 enough, if the need arises).
826 For implementing SEQUENCEs, the functions
830 int odr_sequence_begin(ODR o, void *p, int size, const char *name);
831 int odr_sequence_end(ODR o);
839 The <function>odr_sequence_begin()</function> function should be
840 called in the beginning of a function that implements a SEQUENCE type.
841 Its parameters are the &odr; stream, a pointer (to a pointer to the type
842 you're implementing), and the <literal>size</literal> of the type
843 (typically a C structure). On encoding, it returns 1 if
844 <literal>* p</literal> is a null pointer. The <literal>size</literal>
845 parameter is ignored. On decoding, it returns 1 if the type is found in
846 the data stream. <literal>size</literal> bytes of memory are allocated,
847 and <literal>*p</literal> is set to point to this space.
848 <function>odr_sequence_end()</function> is called at the end of the
849 complex function. Assume that a type is defined like this:
853 MySequence ::= SEQUENCE {
855 boolval BOOLEAN OPTIONAL
860 The corresponding &odr; encoder/decoder function and the associated data
861 structures could be written like this:
865 typedef struct MySequence
871 int mySequence(ODR o, MySequence **p, int optional, const char *name)
873 if (odr_sequence_begin(o, p, sizeof(**p), name) == 0)
874 return optional && odr_ok(o);
876 odr_integer(o, &(*p)->intval, 0, "intval") &&
877 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
884 Note the 1 in the call to <function>odr_bool()</function>, to mark
885 that the sequence member is optional.
886 If either of the member types had been tagged, the macros
887 <function>odr_implicit_tag()</function> or
888 <function>odr_explicit_tag()</function>
889 could have been used.
890 The new function can be used exactly like the standard functions provided
891 with &odr;. It will encode, decode or pretty-print a data value of the
892 <literal>MySequence</literal> type. We like to name types with an
893 initial capital, as done in ASN.1 definitions, and to name the
894 corresponding function with the first character of the name in lower case.
895 You could, of course, name your structures, types, and functions any way
896 you please - as long as you're consistent, and your code is easily readable.
897 <literal>odr_ok</literal> is just that - a predicate that returns the
898 state of the stream. It is used to ensure that the behavior of the new
899 type is compatible with the interface of the primitive types.
903 <sect2><title>Tagging Constructed Types</title>
907 See <xref linkend="tag.prim"/> for information on how to tag
908 the primitive types, as well as types that are already defined.
912 <sect3><title>Implicit Tagging</title>
915 Assume the type above had been defined as
919 MySequence ::= [10] IMPLICIT SEQUENCE {
921 boolval BOOLEAN OPTIONAL
926 You would implement this in &odr; by calling the function
930 int odr_implicit_settag(ODR o, int class, int tag);
934 which overrides the tag of the type immediately following it. The
935 macro <function>odr_implicit_tag()</function> works by calling
936 <function>odr_implicit_settag()</function> immediately
937 before calling the function pointer argument.
938 Your type function could look like this:
942 int mySequence(ODR o, MySequence **p, int optional, const char *name)
944 if (odr_implicit_settag(o, ODR_CONTEXT, 10) == 0 ||
945 odr_sequence_begin(o, p, sizeof(**p), name) == 0)
946 return optional && odr_ok(o);
948 odr_integer(o, &(*p)->intval, 0, "intval") &&
949 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
955 The definition of the structure <literal>MySequence</literal> would be
960 <sect3><title>Explicit Tagging</title>
963 Explicit tagging of constructed types is a little more complicated,
964 since you are in effect adding a level of construction to the data.
968 Assume the definition:
972 MySequence ::= [10] IMPLICIT SEQUENCE {
974 boolval BOOLEAN OPTIONAL
979 Since the new type has an extra level of construction, two new functions
980 are needed to encapsulate the base type:
984 int odr_constructed_begin(ODR o, void *p, int class, int tag,
987 int odr_constructed_end(ODR o);
991 Assume that the IMPLICIT in the type definition above were replaced
992 with EXPLICIT (or that the IMPLICIT keyword were simply deleted, which
993 would be equivalent). The structure definition would look the same,
994 but the function would look like this:
998 int mySequence(ODR o, MySequence **p, int optional, const char *name)
1000 if (odr_constructed_begin(o, p, ODR_CONTEXT, 10, name) == 0)
1001 return optional && odr_ok(o);
1002 if (o->direction == ODR_DECODE)
1003 *p = odr_malloc(o, sizeof(**p));
1004 if (odr_sequence_begin(o, p, sizeof(**p), 0) == 0)
1006 *p = 0; /* this is almost certainly a protocol error */
1010 odr_integer(o, &(*p)->intval, 0, "intval") &&
1011 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
1012 odr_sequence_end(o) &&
1013 odr_constructed_end(o);
1018 Notice that the interface here gets kind of nasty. The reason is
1019 simple: Explicitly tagged, constructed types are fairly rare in
1020 the protocols that we care about, so the
1021 esthetic annoyance (not to mention the dangers of a cluttered
1022 interface) is less than the time that would be required to develop a
1023 better interface. Nevertheless, it is far from satisfying, and it's a
1024 point that will be worked on in the future. One option for you would
1025 be to simply apply the <function>odr_explicit_tag()</function> macro to
1026 the first function, and not
1027 have to worry about <function>odr_constructed_*</function> yourself.
1028 Incidentally, as you might have guessed, the
1029 <function>odr_sequence_</function> functions are themselves
1030 implemented using the <function>/odr_constructed_</function> functions.
1035 <sect2><title>SEQUENCE OF</title>
1038 To handle sequences (arrays) of a specific type, the function
1042 int odr_sequence_of(ODR o, int (*fun)(ODR o, void *p, int optional),
1043 void *p, int *num, const char *name);
1047 The <literal>fun</literal> parameter is a pointer to the decoder/encoder
1048 function of the type. <literal>p</literal> is a pointer to an array of
1049 pointers to your type. <literal>num</literal> is the number of elements
1058 MyArray ::= SEQUENCE OF INTEGER
1062 The C representation might be
1066 typedef struct MyArray
1074 And the function might look like
1078 int myArray(ODR o, MyArray **p, int optional, const char *name)
1080 if (o->direction == ODR_DECODE)
1081 *p = odr_malloc(o, sizeof(**p));
1082 if (odr_sequence_of(o, odr_integer, &(*p)->elements,
1083 &(*p)->num_elements, name))
1086 return optional && odr_ok(o);
1091 <sect2><title>CHOICE Types</title>
1094 The choice type is used fairly often in some ASN.1 definitions, so
1095 some work has gone into streamlining its interface.
1099 CHOICE types are handled by the function:
1103 int odr_choice(ODR o, Odr_arm arm[], void *p, void *whichp,
1108 The <literal>arm</literal> array is used to describe each of the possible
1109 types that the CHOICE type may assume. Internally in your application,
1110 the CHOICE type is represented as a discriminated union. That is, a
1111 C union accompanied by an integer (or enum) identifying the active
1113 <literal>whichp</literal> is a pointer to the union discriminator.
1114 When encoding, it is examined to determine the current type.
1115 When decoding, it is set to reference the type that was found in
1120 The Odr_arm type is defined thus:
1124 typedef struct odr_arm
1136 The interpretation of the fields are:
1140 <varlistentry><term>tagmode</term>
1141 <listitem><para>Either <literal>ODR_IMPLICIT</literal>,
1142 <literal>ODR_EXPLICIT</literal>, or <literal>ODR_NONE</literal> (-1)
1143 to mark no tagging.</para></listitem>
1146 <varlistentry><term>which</term>
1147 <listitem><para>The value of the discriminator that corresponds to
1148 this CHOICE element. Typically, it will be a #defined constant, or
1149 an enum member.</para></listitem>
1152 <varlistentry><term>fun</term>
1153 <listitem><para>A pointer to a function that implements the type of
1154 the CHOICE member. It may be either a standard &odr; type or a type
1155 defined by yourself.</para></listitem>
1158 <varlistentry><term>name</term>
1159 <listitem><para>Name of tag.</para></listitem>
1164 A handy way to prepare the array for use by the
1165 <function>odr_choice()</function> function is to
1166 define it as a static, initialized array in the beginning of your
1167 decoding/encoding function. Assume the type definition:
1171 MyChoice ::= CHOICE {
1173 tagged [99] IMPLICIT INTEGER,
1179 Your C type might look like
1183 typedef struct MyChoice
1201 And your function could look like this:
1205 int myChoice(ODR o, MyChoice **p, int optional, const char *name)
1207 static Odr_arm arm[] =
1209 {-1, -1, -1, MyChoice_untagged, odr_integer, "untagged"},
1210 {ODR_IMPLICIT, ODR_CONTEXT, 99, MyChoice_tagged, odr_integer,
1212 {-1, -1, -1, MyChoice_other, odr_boolean, "other"},
1216 if (o->direction == ODR_DECODE)
1217 *p = odr_malloc(o, sizeof(**p);
1219 return optional && odr_ok(o);
1221 if (odr_choice(o, arm, &(*p)->u, &(*p)->which), name)
1224 return optional && odr_ok(o);
1229 In some cases (say, a non-optional choice which is a member of a
1230 sequence), you can "embed" the union and its discriminator in the
1231 structure belonging to the enclosing type, and you won't need to
1232 fiddle with memory allocation to create a separate structure to
1233 wrap the discriminator and union.
1237 The corresponding function is somewhat nicer in the Sun XDR interface.
1238 Most of the complexity of this interface comes from the possibility of
1239 declaring sequence elements (including CHOICEs) optional.
1243 The ASN.1 specifications naturally requires that each member of a
1244 CHOICE have a distinct tag, so they can be told apart on decoding.
1245 Sometimes it can be useful to define a CHOICE that has multiple types
1246 that share the same tag. You'll need some other mechanism, perhaps
1247 keyed to the context of the CHOICE type. In effect, we would like to
1248 introduce a level of context-sensitiveness to our ASN.1 specification.
1249 When encoding an internal representation, we have no problem, as long
1250 as each CHOICE member has a distinct discriminator value. For
1251 decoding, we need a way to tell the choice function to look for a
1252 specific arm of the table. The function
1256 void odr_choice_bias(ODR o, int what);
1260 provides this functionality. When called, it leaves a notice for the next
1261 call to <function>odr_choice()</function> to be called on the decoding
1262 stream <literal>o</literal> that only the <literal>arm</literal> entry with
1263 a <literal>which</literal> field equal to <literal>what</literal>
1268 The most important application (perhaps the only one, really) is in
1269 the definition of application-specific EXTERNAL encoders/decoders
1270 which will automatically decode an ANY member given the direct or
1277 <sect1 id="odr.debugging"><title>Debugging</title>
1280 The protocol modules are suffering somewhat from a lack of diagnostic
1281 tools at the moment. Specifically ways to pretty-print PDUs that
1282 aren't recognized by the system. We'll include something to this end
1283 in a not-too-distant release. In the meantime, what we do when we get
1284 packages we don't understand is to compile the ODR module with
1285 <literal>ODR_DEBUG</literal> defined. This causes the module to dump tracing
1286 information as it processes data units. With this output and the
1287 protocol specification (Z39.50), it is generally fairly easy to see
1292 <!-- Keep this comment at the end of the file
1297 sgml-minimize-attributes:nil
1298 sgml-always-quote-attributes:t
1301 sgml-parent-document: "yaz.xml"
1302 sgml-local-catalogs: nil
1303 sgml-namecase-general:t