-<!-- $Id: odr.xml,v 1.12 2004-03-19 21:12:13 adam Exp $ -->
+<!-- $Id: odr.xml,v 1.19 2006-10-05 08:26:58 adam Exp $ -->
<chapter id="odr"><title>The ODR Module</title>
<sect1 id="odr.introduction"><title>Introduction</title>
</sect1>
<sect1 id="odr.use"><title>Using ODR</title>
- <sect2><title>ODR Streams</title>
+ <sect2 id="odr.streams"><title>ODR Streams</title>
<para>
Conceptually, the ODR stream is the source of encoded data in the
</para>
</sect2>
- <sect2><title id="memory">Memory Management</title>
+ <sect2 id="odr.memory.management"><title id="memory">Memory Management</title>
<para>
Two forms of memory management take place in the &odr; system. The first
</para>
</sect2>
- <sect2><title>Encoding and Decoding Data</title>
+ <sect2 id="odr.encoding.and.decoding"><title>Encoding and Decoding Data</title>
<para>
When encoding data, the ODR stream will write the encoded octet string
<function>z_APDU()</function>).
</para>
- <example><title>Encoding and decoding functions</title>
+ <example id="example.odr.encoding.and.decoding.functions">
+ <title>Encoding and decoding functions</title>
<synopsis>
int odr_integer(ODR o, int **p, int optional, const char *name);
last call to <function>odr_reset()</function> will be released.
</para>
- <example><title>Encoding and decoding of an integer</title>
+ <example id="example.odr.encoding.of.integer">
+ <title>Encoding and decoding of an integer</title>
<para>
The use of the double indirection can be a little confusing at first
(its purpose will become clear later on, hopefully),
</sect2>
- <sect2><title>Diagnostics</title>
+ <sect2 id="odr.printing"><title>Printing</title>
+ <para>
+ When an ODR stream is created of type <literal>ODR_PRINT</literal>
+ the ODR module will print the contents of a PDU in a readable format.
+ By default output is written to the <literal>stderr</literal> stream.
+ This behavior can be changed, however, by calling the function
+ <synopsis>
+ odr_setprint(ODR o, FILE *file);
+ </synopsis>
+ before encoders or decoders are being invoked.
+ It is also possible to direct the output to a buffer (of indeed
+ another file), by using the more generic mechanism:
+ <synopsis>
+ void odr_set_stream(ODR o, void *handle,
+ void (*stream_write)(ODR o, void *handle, int type,
+ const char *buf, int len),
+ void (*stream_close)(void *handle));
+ </synopsis>
+ Here the user provides an opaque handle and two handlers,
+ <replaceable>stream_write</replaceable> for writing,
+ and <replaceable>stream_close</replaceable> which is supposed
+ to close/free resources associated with handle.
+ The <replaceable>stream_close</replaceable> handler is optional and
+ if NULL for the function is provided, it will not be invoked.
+ The <replaceable>stream_write</replaceable> takes the ODR handle
+ as parameter, the user defined handle, a type
+ <literal>ODR_OCTETSTRING</literal>, <literal>ODR_VISIBLESTRING</literal>
+ which indicates the type of contents is being written.
+ </para>
+ <para>
+ Another utility useful for diagnostics (error handling) or as
+ part of the printing facilities is:
+ <synopsis>
+ const char **odr_get_element_path(ODR o);
+ </synopsis>
+ which returns a list of current elements that ODR deals with at the
+ moment. For the returned array, say <literal>ar</literal>,
+ <literal>ar[0]</literal> is the top level element,
+ <literal>ar[n]</literal> is the last. The last element has the
+ property that <literal>ar[n+1] == NULL</literal>.
+ </para>
+ <example id="example.odr.element.path.record">
+ <title>Element Path for record</title>
+ <para>
+ For a database record part of a PresentResponse the
+ array returned by <function>odr_get_element</function>
+ is <literal>presentResponse</literal>, <literal>databaseOrSurDiagnostics</literal>, <literal>?</literal>, <literal>record</literal>, <literal>?</literal>, <literal>databaseRecord</literal> . The question mark appears due to
+ unnamed constructions.
+ </para>
+ </example>
+ </sect2>
+ <sect2 id="odr.diagnostics"><title>Diagnostics</title>
<para>
The encoding/decoding functions all return 0 when an error occurs.
one of these constants:
</para>
- <table frame="top"><title>ODR Error codes</title>
+ <table frame="top" id="odr.error.codes">
+ <title>ODR Error codes</title>
<tgroup cols="2">
<thead>
<row>
</para>
</sect2>
- <sect2><title>Summary and Synopsis</title>
+ <sect2 id="odr.summary.and.synopsis">
+ <title>Summary and Synopsis</title>
<synopsis>
#include <odr.h>
<tip>
<para>
There is an ASN.1 tutorial available at
- <ulink url="http://asn1.elibel.tm.fr/en/introduction/">this site</ulink>.
+ <ulink url="&url.asn.1.tutorial;">this site</ulink>.
This site also has standards for ASN.1 (X.680) and BER (X.690)
- <ulink url="http://asn1.elibel.tm.fr/en/standards/">online</ulink>.
+ <ulink url="&url.asn.1.standards;">online</ulink>.
</para>
</tip>
SEQUENCE members which don't exist in XDR.
</para>
- <sect2><title>The Primitive ASN.1 Types</title>
+ <sect2 id="odr.primitive.asn1.types">
+ <title>The Primitive ASN.1 Types</title>
<para>
ASN.1 defines a number of primitive types (many of which correspond
roughly to primitive types in structured programming languages, such as C).
</para>
- <sect3><title>INTEGER</title>
+ <sect3 id="odr.integer"><title>INTEGER</title>
<para>
The &odr; function for encoding or decoding (or printing) the ASN.1
similar manners:
</para>
</sect3>
- <sect3><title>BOOLEAN</title>
+ <sect3 id="odr.boolean"><title>BOOLEAN</title>
<synopsis>
int odr_bool(ODR o, bool_t **p, int optional, const char *name);
</synopsis>
</sect3>
- <sect3><title>REAL</title>
+ <sect3 id="odr.real"><title>REAL</title>
<para>
Not defined.
</para>
</sect3>
- <sect3><title>NULL</title>
+ <sect3 id="odr.null"><title>NULL</title>
<synopsis>
int odr_null(ODR o, bool_t **p, int optional, const char *name);
</para>
</sect3>
- <sect3><title>OCTET STRING</title>
+ <sect3 id="odr.octet.string"><title>OCTET STRING</title>
<synopsis>
typedef struct odr_oct
</synopsis>
</sect3>
- <sect3><title>BIT STRING</title>
+ <sect3 id="odr.bit.string"><title>BIT STRING</title>
<synopsis>
int odr_bitstring(ODR o, Odr_bitmask **p, int optional,
</para>
</sect3>
- <sect3><title>OBJECT IDENTIFIER</title>
+ <sect3 id="odr.object.identifier"><title>OBJECT IDENTIFIER</title>
<synopsis>
int odr_oid(ODR o, Odr_oid **p, int optional, const char *name);
</sect3>
</sect2>
- <sect2 id="tag.prim"><title>Tagging Primitive Types</title>
+ <sect2 id="odr.tagging.primitive.types"><title>Tagging Primitive Types</title> <!-- tag.prim -->
<para>
The simplest way of tagging a type is to use the
</para>
</sect2>
- <sect2><title>Constructed Types</title>
+ <sect2 id="odr.constructed.types"><title>Constructed Types</title>
<para>
Constructed types are created by combining primitive types. The
</para>
</sect2>
- <sect2><title>Tagging Constructed Types</title>
+ <sect2 id="odr.tagging.constructed.types">
+ <title>Tagging Constructed Types</title>
<note>
<para>
- See <xref linkend="tag.prim"/> for information on how to tag
+ See <xref linkend="odr.tagging.primitive.types"/> for information on how to tag
the primitive types, as well as types that are already defined.
</para>
</note>
- <sect3><title>Implicit Tagging</title>
+ <sect3 id="odr.implicit.tagging">
+ <title>Implicit Tagging</title>
<para>
Assume the type above had been defined as
</para>
</sect3>
- <sect3><title>Explicit Tagging</title>
+ <sect3 id="odr.explicit.tagging"><title>Explicit Tagging</title>
<para>
Explicit tagging of constructed types is a little more complicated,
</sect3>
</sect2>
- <sect2><title>SEQUENCE OF</title>
+ <sect2 id="odr.sequence.of"><title>SEQUENCE OF</title>
<para>
To handle sequences (arrays) of a specific type, the function
</screen>
</sect2>
- <sect2><title>CHOICE Types</title>
+ <sect2 id="odr.choice.types"><title>CHOICE Types</title>
<para>
The choice type is used fairly often in some ASN.1 definitions, so