1 <html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>3. Programming with ODR</title><meta name="generator" content="DocBook XSL Stylesheets V1.73.2"><link rel="start" href="index.html" title="YAZ User's Guide and Reference"><link rel="up" href="odr.html" title="Chapter 10. The ODR Module"><link rel="prev" href="odr.use.html" title="2. Using ODR"><link rel="next" href="odr.debugging.html" title="4. Debugging"></head><body><link rel="stylesheet" type="text/css" href="common/style1.css"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">3. Programming with ODR</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="odr.use.html">Prev</a> </td><th width="60%" align="center">Chapter 10. The ODR Module</th><td width="20%" align="right"> <a accesskey="n" href="odr.debugging.html">Next</a></td></tr></table><hr></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="odr.programming"></a>3. Programming with ODR</h2></div></div></div><p>
2 The API of <acronym class="acronym">ODR</acronym> is designed to reflect the structure of ASN.1, rather
3 than BER itself. Future releases may be able to represent data in
5 </p><div class="tip" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Tip</h3><p>
6 There is an ASN.1 tutorial available at
7 <a class="ulink" href="http://asn1.elibel.tm.fr/en/introduction/" target="_top">this site</a>.
8 This site also has standards for ASN.1 (X.680) and BER (X.690)
9 <a class="ulink" href="http://asn1.elibel.tm.fr/en/standards/" target="_top">online</a>.
11 The ODR interface is based loosely on that of the Sun Microsystems
13 Specifically, each function which corresponds to an ASN.1 primitive
14 type has a dual function. Depending on the settings of the ODR
15 stream which is supplied as a parameter, the function may be used
16 either to encode or decode data. The functions that can be built
17 using these primitive functions, to represent more complex data types,
18 share this quality. The result is that you only have to enter the
19 definition for a type once - and you have the functionality of encoding,
20 decoding (and pretty-printing) all in one unit.
21 The resulting C source code is quite compact, and is a pretty
22 straightforward representation of the source ASN.1 specification.
24 In many cases, the model of the XDR functions works quite well in this
26 In others, it is less elegant. Most of the hassle comes from the optional
27 SEQUENCE members which don't exist in XDR.
28 </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.primitive.asn1.types"></a>3.1. The Primitive ASN.1 Types</h3></div></div></div><p>
29 ASN.1 defines a number of primitive types (many of which correspond
30 roughly to primitive types in structured programming languages, such as C).
31 </p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.integer"></a>3.1.1. INTEGER</h4></div></div></div><p>
32 The <acronym class="acronym">ODR</acronym> function for encoding or decoding (or printing) the ASN.1
33 INTEGER type looks like this:
34 </p><pre class="synopsis">
35 int odr_integer(ODR o, int **p, int optional, const char *name);
37 (we don't allow values that can't be contained in a C integer.)
39 This form is typical of the primitive <acronym class="acronym">ODR</acronym> functions. They are named
40 after the type of data that they encode or decode. They take an <acronym class="acronym">ODR</acronym>
41 stream, an indirect reference to the type in question, and an
42 <code class="literal">optional</code> flag (corresponding to the OPTIONAL keyword
43 of ASN.1) as parameters. They all return an integer value of either one
45 When you use the primitive functions to construct encoders for complex
46 types of your own, you should follow this model as well. This
47 ensures that your new types can be reused as elements in yet more
50 The <code class="literal">o</code> parameter should obviously refer to a properly
51 initialized <acronym class="acronym">ODR</acronym> stream of the right type (encoding/decoding/printing)
52 for the operation that you wish to perform.
54 When encoding or printing, the function first looks at
55 <code class="literal">* p</code>. If <code class="literal">* p</code> (the pointer pointed
56 to by <code class="literal">p</code>) is a null pointer, this is taken to mean that
57 the data element is absent. If the <code class="literal">optional</code> parameter
58 is nonzero, the function will return one (signifying success) without
59 any further processing. If the <code class="literal">optional</code> is zero, an
60 internal error flag is set in the <acronym class="acronym">ODR</acronym> stream, and the function will
61 return 0. No further operations can be carried out on the stream without
62 a call to the function <code class="function">odr_reset()</code>.
64 If <code class="literal">*p</code> is not a null pointer, it is expected to
65 point to an instance of the data type. The data will be subjected to
66 the encoding rules, and the result will be placed in the buffer held
67 by the <acronym class="acronym">ODR</acronym> stream.
69 The other ASN.1 primitives have similar functions that operate in
71 </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.boolean"></a>3.1.2. BOOLEAN</h4></div></div></div><pre class="synopsis">
72 int odr_bool(ODR o, bool_t **p, int optional, const char *name);
73 </pre></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.real"></a>3.1.3. REAL</h4></div></div></div><p>
75 </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.null"></a>3.1.4. NULL</h4></div></div></div><pre class="synopsis">
76 int odr_null(ODR o, bool_t **p, int optional, const char *name);
78 In this case, the value of **p is not important. If <code class="literal">*p</code>
79 is different from the null pointer, the null value is present, otherwise
81 </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.octet.string"></a>3.1.5. OCTET STRING</h4></div></div></div><pre class="synopsis">
82 typedef struct odr_oct
89 int odr_octetstring(ODR o, Odr_oct **p, int optional,
92 The <code class="literal">buf</code> field should point to the character array
93 that holds the octetstring. The <code class="literal">len</code> field holds the
94 actual length, while the <code class="literal">size</code> field gives the size
95 of the allocated array (not of interest to you, in most cases).
96 The character array need not be null terminated.
98 To make things a little easier, an alternative is given for string
99 types that are not expected to contain embedded NULL characters (eg.
101 </p><pre class="synopsis">
102 int odr_cstring(ODR o, char **p, int optional, const char *name);
104 Which encoded or decodes between OCTETSTRING representations and
105 null-terminates C strings.
107 Functions are provided for the derived string types, eg:
108 </p><pre class="synopsis">
109 int odr_visiblestring(ODR o, char **p, int optional,
111 </pre></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.bit.string"></a>3.1.6. BIT STRING</h4></div></div></div><pre class="synopsis">
112 int odr_bitstring(ODR o, Odr_bitmask **p, int optional,
115 The opaque type <code class="literal">Odr_bitmask</code> is only suitable for
116 holding relatively brief bit strings, eg. for options fields, etc.
117 The constant <code class="literal">ODR_BITMASK_SIZE</code> multiplied by 8
118 gives the maximum possible number of bits.
120 A set of macros are provided for manipulating the
121 <code class="literal">Odr_bitmask</code> type:
122 </p><pre class="synopsis">
123 void ODR_MASK_ZERO(Odr_bitmask *b);
125 void ODR_MASK_SET(Odr_bitmask *b, int bitno);
127 void ODR_MASK_CLEAR(Odr_bitmask *b, int bitno);
129 int ODR_MASK_GET(Odr_bitmask *b, int bitno);
131 The functions are modeled after the manipulation functions that
132 accompany the <code class="literal">fd_set</code> type used by the
133 <code class="function">select(2)</code> call.
134 <code class="literal">ODR_MASK_ZERO</code> should always be called first on a
135 new bitmask, to initialize the bits to zero.
136 </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.object.identifier"></a>3.1.7. OBJECT IDENTIFIER</h4></div></div></div><pre class="synopsis">
137 int odr_oid(ODR o, Odr_oid **p, int optional, const char *name);
139 The C OID representation is simply an array of integers, terminated by
140 the value -1 (the <code class="literal">Odr_oid</code> type is synonymous with
141 the <code class="literal">int</code> type).
142 We suggest that you use the OID database module (see
143 <a class="xref" href="asn.oid.html" title="3. Object Identifiers (YAZ 2)">Section 3, “Object Identifiers (YAZ 2)”</a>) to handle object identifiers
145 </p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.tagging.primitive.types"></a>3.2. Tagging Primitive Types</h3></div></div></div><p>
146 The simplest way of tagging a type is to use the
147 <code class="function">odr_implicit_tag()</code> or
148 <code class="function">odr_explicit_tag()</code> macros:
149 </p><pre class="synopsis">
150 int odr_implicit_tag(ODR o, Odr_fun fun, int class, int tag,
151 int optional, const char *name);
153 int odr_explicit_tag(ODR o, Odr_fun fun, int class, int tag,
154 int optional, const char *name);
156 To create a type derived from the integer type by implicit tagging, you
158 </p><pre class="screen">
159 MyInt ::= [210] IMPLICIT INTEGER
161 In the <acronym class="acronym">ODR</acronym> system, this would be written like:
162 </p><pre class="screen">
163 int myInt(ODR o, int **p, int optional, const char *name)
165 return odr_implicit_tag(o, odr_integer, p,
166 ODR_CONTEXT, 210, optional, name);
169 The function <code class="function">myInt()</code> can then be used like any of
170 the primitive functions provided by <acronym class="acronym">ODR</acronym>. Note that the behavior of
171 <code class="function">odr_explicit_tag()</code>
172 and <code class="function">odr_implicit_tag()</code> macros
173 act exactly the same as the functions they are applied to - they
174 respond to error conditions, etc, in the same manner - they
175 simply have three extra parameters. The class parameter may
176 take one of the values: <code class="literal">ODR_CONTEXT</code>,
177 <code class="literal">ODR_PRIVATE</code>, <code class="literal">ODR_UNIVERSAL</code>, or
178 <code class="literal">/ODR_APPLICATION</code>.
179 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.constructed.types"></a>3.3. Constructed Types</h3></div></div></div><p>
180 Constructed types are created by combining primitive types. The
181 <acronym class="acronym">ODR</acronym> system only implements the SEQUENCE and SEQUENCE OF constructions
182 (although adding the rest of the container types should be simple
183 enough, if the need arises).
185 For implementing SEQUENCEs, the functions
186 </p><pre class="synopsis">
187 int odr_sequence_begin(ODR o, void *p, int size, const char *name);
188 int odr_sequence_end(ODR o);
192 The <code class="function">odr_sequence_begin()</code> function should be
193 called in the beginning of a function that implements a SEQUENCE type.
194 Its parameters are the <acronym class="acronym">ODR</acronym> stream, a pointer (to a pointer to the type
195 you're implementing), and the <code class="literal">size</code> of the type
196 (typically a C structure). On encoding, it returns 1 if
197 <code class="literal">* p</code> is a null pointer. The <code class="literal">size</code>
198 parameter is ignored. On decoding, it returns 1 if the type is found in
199 the data stream. <code class="literal">size</code> bytes of memory are allocated,
200 and <code class="literal">*p</code> is set to point to this space.
201 <code class="function">odr_sequence_end()</code> is called at the end of the
202 complex function. Assume that a type is defined like this:
203 </p><pre class="screen">
204 MySequence ::= SEQUENCE {
206 boolval BOOLEAN OPTIONAL
209 The corresponding <acronym class="acronym">ODR</acronym> encoder/decoder function and the associated data
210 structures could be written like this:
211 </p><pre class="screen">
212 typedef struct MySequence
218 int mySequence(ODR o, MySequence **p, int optional, const char *name)
220 if (odr_sequence_begin(o, p, sizeof(**p), name) == 0)
221 return optional && odr_ok(o);
223 odr_integer(o, &(*p)->intval, 0, "intval") &&
224 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
229 Note the 1 in the call to <code class="function">odr_bool()</code>, to mark
230 that the sequence member is optional.
231 If either of the member types had been tagged, the macros
232 <code class="function">odr_implicit_tag()</code> or
233 <code class="function">odr_explicit_tag()</code>
234 could have been used.
235 The new function can be used exactly like the standard functions provided
236 with <acronym class="acronym">ODR</acronym>. It will encode, decode or pretty-print a data value of the
237 <code class="literal">MySequence</code> type. We like to name types with an
238 initial capital, as done in ASN.1 definitions, and to name the
239 corresponding function with the first character of the name in lower case.
240 You could, of course, name your structures, types, and functions any way
241 you please - as long as you're consistent, and your code is easily readable.
242 <code class="literal">odr_ok</code> is just that - a predicate that returns the
243 state of the stream. It is used to ensure that the behavior of the new
244 type is compatible with the interface of the primitive types.
245 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.tagging.constructed.types"></a>3.4. Tagging Constructed Types</h3></div></div></div><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
246 See <a class="xref" href="odr.programming.html#odr.tagging.primitive.types" title="3.2. Tagging Primitive Types">Section 3.2, “Tagging Primitive Types”</a> for information on how to tag
247 the primitive types, as well as types that are already defined.
248 </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.implicit.tagging"></a>3.4.1. Implicit Tagging</h4></div></div></div><p>
249 Assume the type above had been defined as
250 </p><pre class="screen">
251 MySequence ::= [10] IMPLICIT SEQUENCE {
253 boolval BOOLEAN OPTIONAL
256 You would implement this in <acronym class="acronym">ODR</acronym> by calling the function
257 </p><pre class="synopsis">
258 int odr_implicit_settag(ODR o, int class, int tag);
260 which overrides the tag of the type immediately following it. The
261 macro <code class="function">odr_implicit_tag()</code> works by calling
262 <code class="function">odr_implicit_settag()</code> immediately
263 before calling the function pointer argument.
264 Your type function could look like this:
265 </p><pre class="screen">
266 int mySequence(ODR o, MySequence **p, int optional, const char *name)
268 if (odr_implicit_settag(o, ODR_CONTEXT, 10) == 0 ||
269 odr_sequence_begin(o, p, sizeof(**p), name) == 0)
270 return optional && odr_ok(o);
272 odr_integer(o, &(*p)->intval, 0, "intval") &&
273 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
277 The definition of the structure <code class="literal">MySequence</code> would be
279 </p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="odr.explicit.tagging"></a>3.4.2. Explicit Tagging</h4></div></div></div><p>
280 Explicit tagging of constructed types is a little more complicated,
281 since you are in effect adding a level of construction to the data.
283 Assume the definition:
284 </p><pre class="screen">
285 MySequence ::= [10] IMPLICIT SEQUENCE {
287 boolval BOOLEAN OPTIONAL
290 Since the new type has an extra level of construction, two new functions
291 are needed to encapsulate the base type:
292 </p><pre class="synopsis">
293 int odr_constructed_begin(ODR o, void *p, int class, int tag,
296 int odr_constructed_end(ODR o);
298 Assume that the IMPLICIT in the type definition above were replaced
299 with EXPLICIT (or that the IMPLICIT keyword were simply deleted, which
300 would be equivalent). The structure definition would look the same,
301 but the function would look like this:
302 </p><pre class="screen">
303 int mySequence(ODR o, MySequence **p, int optional, const char *name)
305 if (odr_constructed_begin(o, p, ODR_CONTEXT, 10, name) == 0)
306 return optional && odr_ok(o);
307 if (o->direction == ODR_DECODE)
308 *p = odr_malloc(o, sizeof(**p));
309 if (odr_sequence_begin(o, p, sizeof(**p), 0) == 0)
311 *p = 0; /* this is almost certainly a protocol error */
315 odr_integer(o, &(*p)->intval, 0, "intval") &&
316 odr_bool(o, &(*p)->boolval, 1, "boolval") &&
317 odr_sequence_end(o) &&
318 odr_constructed_end(o);
321 Notice that the interface here gets kind of nasty. The reason is
322 simple: Explicitly tagged, constructed types are fairly rare in
323 the protocols that we care about, so the
324 esthetic annoyance (not to mention the dangers of a cluttered
325 interface) is less than the time that would be required to develop a
326 better interface. Nevertheless, it is far from satisfying, and it's a
327 point that will be worked on in the future. One option for you would
328 be to simply apply the <code class="function">odr_explicit_tag()</code> macro to
329 the first function, and not
330 have to worry about <code class="function">odr_constructed_*</code> yourself.
331 Incidentally, as you might have guessed, the
332 <code class="function">odr_sequence_</code> functions are themselves
333 implemented using the <code class="function">/odr_constructed_</code> functions.
334 </p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.sequence.of"></a>3.5. SEQUENCE OF</h3></div></div></div><p>
335 To handle sequences (arrays) of a specific type, the function
336 </p><pre class="synopsis">
337 int odr_sequence_of(ODR o, int (*fun)(ODR o, void *p, int optional),
338 void *p, int *num, const char *name);
340 The <code class="literal">fun</code> parameter is a pointer to the decoder/encoder
341 function of the type. <code class="literal">p</code> is a pointer to an array of
342 pointers to your type. <code class="literal">num</code> is the number of elements
346 </p><pre class="screen">
347 MyArray ::= SEQUENCE OF INTEGER
349 The C representation might be
350 </p><pre class="screen">
351 typedef struct MyArray
357 And the function might look like
358 </p><pre class="screen">
359 int myArray(ODR o, MyArray **p, int optional, const char *name)
361 if (o->direction == ODR_DECODE)
362 *p = odr_malloc(o, sizeof(**p));
363 if (odr_sequence_of(o, odr_integer, &(*p)->elements,
364 &(*p)->num_elements, name))
367 return optional && odr_ok(o);
369 </pre></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="odr.choice.types"></a>3.6. CHOICE Types</h3></div></div></div><p>
370 The choice type is used fairly often in some ASN.1 definitions, so
371 some work has gone into streamlining its interface.
373 CHOICE types are handled by the function:
374 </p><pre class="synopsis">
375 int odr_choice(ODR o, Odr_arm arm[], void *p, void *whichp,
378 The <code class="literal">arm</code> array is used to describe each of the possible
379 types that the CHOICE type may assume. Internally in your application,
380 the CHOICE type is represented as a discriminated union. That is, a
381 C union accompanied by an integer (or enum) identifying the active
383 <code class="literal">whichp</code> is a pointer to the union discriminator.
384 When encoding, it is examined to determine the current type.
385 When decoding, it is set to reference the type that was found in
388 The Odr_arm type is defined thus:
389 </p><pre class="screen">
390 typedef struct odr_arm
400 The interpretation of the fields are:
401 </p><div class="variablelist"><dl><dt><span class="term">tagmode</span></dt><dd><p>Either <code class="literal">ODR_IMPLICIT</code>,
402 <code class="literal">ODR_EXPLICIT</code>, or <code class="literal">ODR_NONE</code> (-1)
403 to mark no tagging.</p></dd><dt><span class="term">which</span></dt><dd><p>The value of the discriminator that corresponds to
404 this CHOICE element. Typically, it will be a #defined constant, or
405 an enum member.</p></dd><dt><span class="term">fun</span></dt><dd><p>A pointer to a function that implements the type of
406 the CHOICE member. It may be either a standard <acronym class="acronym">ODR</acronym> type or a type
407 defined by yourself.</p></dd><dt><span class="term">name</span></dt><dd><p>Name of tag.</p></dd></dl></div><p>
408 A handy way to prepare the array for use by the
409 <code class="function">odr_choice()</code> function is to
410 define it as a static, initialized array in the beginning of your
411 decoding/encoding function. Assume the type definition:
412 </p><pre class="screen">
413 MyChoice ::= CHOICE {
415 tagged [99] IMPLICIT INTEGER,
419 Your C type might look like
420 </p><pre class="screen">
421 typedef struct MyChoice
437 And your function could look like this:
438 </p><pre class="screen">
439 int myChoice(ODR o, MyChoice **p, int optional, const char *name)
441 static Odr_arm arm[] =
443 {-1, -1, -1, MyChoice_untagged, odr_integer, "untagged"},
444 {ODR_IMPLICIT, ODR_CONTEXT, 99, MyChoice_tagged, odr_integer,
446 {-1, -1, -1, MyChoice_other, odr_boolean, "other"},
450 if (o->direction == ODR_DECODE)
451 *p = odr_malloc(o, sizeof(**p);
453 return optional && odr_ok(o);
455 if (odr_choice(o, arm, &(*p)->u, &(*p)->which), name)
458 return optional && odr_ok(o);
461 In some cases (say, a non-optional choice which is a member of a
462 sequence), you can "embed" the union and its discriminator in the
463 structure belonging to the enclosing type, and you won't need to
464 fiddle with memory allocation to create a separate structure to
465 wrap the discriminator and union.
467 The corresponding function is somewhat nicer in the Sun XDR interface.
468 Most of the complexity of this interface comes from the possibility of
469 declaring sequence elements (including CHOICEs) optional.
471 The ASN.1 specifications naturally requires that each member of a
472 CHOICE have a distinct tag, so they can be told apart on decoding.
473 Sometimes it can be useful to define a CHOICE that has multiple types
474 that share the same tag. You'll need some other mechanism, perhaps
475 keyed to the context of the CHOICE type. In effect, we would like to
476 introduce a level of context-sensitiveness to our ASN.1 specification.
477 When encoding an internal representation, we have no problem, as long
478 as each CHOICE member has a distinct discriminator value. For
479 decoding, we need a way to tell the choice function to look for a
480 specific arm of the table. The function
481 </p><pre class="synopsis">
482 void odr_choice_bias(ODR o, int what);
484 provides this functionality. When called, it leaves a notice for the next
485 call to <code class="function">odr_choice()</code> to be called on the decoding
486 stream <code class="literal">o</code> that only the <code class="literal">arm</code> entry with
487 a <code class="literal">which</code> field equal to <code class="literal">what</code>
490 The most important application (perhaps the only one, really) is in
491 the definition of application-specific EXTERNAL encoders/decoders
492 which will automatically decode an ANY member given the direct or
494 </p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="odr.use.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="odr.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="odr.debugging.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">2. Using ODR </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 4. Debugging</td></tr></table></div></body></html>