1 <html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>2. Using ODR</title><meta name="generator" content="DocBook XSL Stylesheets V1.70.1"><link rel="start" href="index.html" title="YAZ User's Guide and Reference"><link rel="up" href="odr.html" title="Chapter 9. The ODR Module"><link rel="prev" href="odr.html" title="Chapter 9. The ODR Module"><link rel="next" href="odr.programming.html" title="3. Programming with ODR"></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">2. Using ODR</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="odr.html">Prev</a> </td><th width="60%" align="center">Chapter 9. The ODR Module</th><td width="20%" align="right"> <a accesskey="n" href="odr.programming.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.use"></a>2. Using ODR</h2></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2601431"></a>2.1. ODR Streams</h3></div></div></div><p>
2 Conceptually, the ODR stream is the source of encoded data in the
3 decoding mode; when encoding, it is the receptacle for the encoded
4 data. Before you can use an ODR stream it must be allocated. This is
6 </p><pre class="synopsis">
7 ODR odr_createmem(int direction);
9 The <code class="function">odr_createmem()</code> function takes as argument one
10 of three manifest constants: <code class="literal">ODR_ENCODE</code>,
11 <code class="literal">ODR_DECODE</code>, or <code class="literal">ODR_PRINT</code>.
12 An <acronym class="acronym">ODR</acronym> stream can be in only one mode - it is not possible to change
13 its mode once it's selected. Typically, your program will allocate
14 at least two ODR streams - one for decoding, and one for encoding.
16 When you're done with the stream, you can use
17 </p><pre class="synopsis">
18 void odr_destroy(ODR o);
20 to release the resources allocated for the stream.
21 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2601499"></a>2.2. Memory Management</h3></div></div></div><p>
22 Two forms of memory management take place in the <acronym class="acronym">ODR</acronym> system. The first
23 one, which has to do with allocating little bits of memory (sometimes
24 quite large bits of memory, actually) when a protocol package is
25 decoded, and turned into a complex of interlinked structures. This
26 section deals with this system, and how you can use it for your own
27 purposes. The next section deals with the memory management which is
28 required when encoding data - to make sure that a large enough buffer is
29 available to hold the fully encoded PDU.
31 The <acronym class="acronym">ODR</acronym> module has its own memory management system, which is
32 used whenever memory is required. Specifically, it is used to allocate
33 space for data when decoding incoming PDUs. You can use the memory
34 system for your own purposes, by using the function
35 </p><pre class="synopsis">
36 void *odr_malloc(ODR o, int size);
38 You can't use the normal <code class="function">free(2)</code> routine to free
39 memory allocated by this function, and <acronym class="acronym">ODR</acronym> doesn't provide a parallel
40 function. Instead, you can call
41 </p><pre class="synopsis">
42 void odr_reset(ODR o, int size);
44 when you are done with the
45 memory: Everything allocated since the last call to
46 <code class="function">odr_reset()</code> is released.
47 The <code class="function">odr_reset()</code> call is also required to clear
48 up an error condition on a stream.
51 </p><pre class="synopsis">
54 returns the number of bytes allocated on the stream since the last call to
55 <code class="function">odr_reset()</code>.
57 The memory subsystem of <acronym class="acronym">ODR</acronym> is fairly efficient at allocating and
58 releasing little bits of memory. Rather than managing the individual,
59 small bits of space, the system maintains a free-list of larger chunks
60 of memory, which are handed out in small bits. This scheme is
61 generally known as a <span class="emphasis"><em>nibble memory</em></span> system.
62 It is very useful for maintaining short-lived constructions such
65 If you want to retain a bit of memory beyond the next call to
66 <code class="function">odr_reset()</code>, you can use the function
67 </p><pre class="synopsis">
68 ODR_MEM odr_extract_mem(ODR o);
70 This function will give you control of the memory recently allocated
71 on the ODR stream. The memory will live (past calls to
72 <code class="function">odr_reset()</code>), until you call the function
73 </p><pre class="synopsis">
74 void odr_release_mem(ODR_MEM p);
76 The opaque <code class="literal">ODR_MEM</code> handle has no other purpose than
77 referencing the memory block for you until you want to release it.
79 You can use <code class="function">odr_extract_mem()</code> repeatedly between
80 allocating data, to retain individual control of separate chunks of data.
81 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2601680"></a>2.3. Encoding and Decoding Data</h3></div></div></div><p>
82 When encoding data, the ODR stream will write the encoded octet string
83 in an internal buffer. To retrieve the data, use the function
84 </p><pre class="synopsis">
85 char *odr_getbuf(ODR o, int *len, int *size);
87 The integer pointed to by len is set to the length of the encoded
88 data, and a pointer to that data is returned. <code class="literal">*size</code>
89 is set to the size of the buffer (unless <code class="literal">size</code> is null,
90 signaling that you are not interested in the size). The next call to
91 a primitive function using the same <acronym class="acronym">ODR</acronym> stream will overwrite the
92 data, unless a different buffer has been supplied using the call
93 </p><pre class="synopsis">
94 void odr_setbuf(ODR o, char *buf, int len, int can_grow);
96 which sets the encoding (or decoding) buffer used by
97 <code class="literal">o</code> to <code class="literal">buf</code>, using the length
98 <code class="literal">len</code>.
99 Before a call to an encoding function, you can use
100 <code class="function">odr_setbuf()</code> to provide the stream with an encoding
101 buffer of sufficient size (length). The <code class="literal">can_grow</code>
102 parameter tells the encoding <acronym class="acronym">ODR</acronym> stream whether it is allowed to use
103 <code class="function">realloc(2)</code> to increase the size of the buffer when
104 necessary. The default condition of a new encoding stream is equivalent
105 to the results of calling
106 </p><pre class="synopsis">
107 odr_setbuf(stream, 0, 0, 1);
109 In this case, the stream will allocate and reallocate memory as
110 necessary. The stream reallocates memory by repeatedly doubling the
111 size of the buffer - the result is that the buffer will typically
112 reach its maximum, working size with only a small number of reallocation
113 operations. The memory is freed by the stream when the latter is destroyed,
114 unless it was assigned by the user with the <code class="literal">can_grow</code>
115 parameter set to zero (in this case, you are expected to retain
116 control of the memory yourself).
118 To assume full control of an encoded buffer, you must first call
119 <code class="function">odr_getbuf()</code> to fetch the buffer and its length.
120 Next, you should call <code class="function">odr_setbuf()</code> to provide a
121 different buffer (or a null pointer) to the stream. In the simplest
122 case, you will reuse the same buffer over and over again, and you
123 will just need to call <code class="function">odr_getbuf()</code> after each
124 encoding operation to get the length and address of the buffer.
125 Note that the stream may reallocate the buffer during an encoding
126 operation, so it is necessary to retrieve the correct address after
127 each encoding operation.
129 It is important to realize that the ODR stream will not release this
130 memory when you call <code class="function">odr_reset()</code>: It will
131 merely update its internal pointers to prepare for the encoding of a
133 When the stream is released by the <code class="function">odr_destroy()</code>
134 function, the memory given to it by <code class="function">odr_setbuf</code> will
135 be released <span class="emphasis"><em>only</em></span> if the <code class="literal">can_grow</code>
136 parameter to <code class="function">odr_setbuf()</code> was nonzero. The
137 <code class="literal">can_grow</code> parameter, in other words, is a way of
138 signaling who is to own the buffer, you or the ODR stream. If you never call
139 <code class="function">odr_setbuf()</code> on your encoding stream, which is
140 typically the case, the buffer allocated by the stream will belong to
141 the stream by default.
143 When you wish to decode data, you should first call
144 <code class="function">odr_setbuf()</code>, to tell the decoding stream
145 where to find the encoded data, and how long the buffer is
146 (the <code class="literal">can_grow</code> parameter is ignored by a decoding
147 stream). After this, you can call the function corresponding to the
148 data you wish to decode (eg, <code class="function">odr_integer()</code> odr
149 <code class="function">z_APDU()</code>).
150 </p><div class="example"><a name="id2601357"></a><p class="title"><b>Example 9.1. Encoding and decoding functions</b></p><div class="example-contents"><pre class="synopsis">
151 int odr_integer(ODR o, int **p, int optional, const char *name);
153 int z_APDU(ODR o, Z_APDU **p, int optional, const char *name);
154 </pre></div></div><br class="example-break"><p>
155 If the data is absent (or doesn't match the tag corresponding to
156 the type), the return value will be either 0 or 1 depending on the
157 <code class="literal">optional</code> flag. If <code class="literal">optional</code>
158 is 0 and the data is absent, an error flag will be raised in the
159 stream, and you'll need to call <code class="function">odr_reset()</code> before
160 you can use the stream again. If <code class="literal">optional</code> is
161 nonzero, the pointer <span class="emphasis"><em>pointed</em></span> to/ by
162 <code class="literal">p</code> will be set to the null value, and the function
164 The <code class="literal">name</code> argument is used to pretty-print the
165 tag in question. It may be set to <code class="literal">NULL</code> if
166 pretty-printing is not desired.
168 If the data value is found where it's expected, the pointer
169 <span class="emphasis"><em>pointed to</em></span> by the <code class="literal">p</code> argument
170 will be set to point to the decoded type.
171 The space for the type will be allocated and owned by the <acronym class="acronym">ODR</acronym>
172 stream, and it will live until you call
173 <code class="function">odr_reset()</code> on the stream. You cannot use
174 <code class="function">free(2)</code> to release the memory.
175 You can decode several data elements (by repeated calls to
176 <code class="function">odr_setbuf()</code> and your decoding function), and
177 new memory will be allocated each time. When you do call
178 <code class="function">odr_reset()</code>, everything decoded since the
179 last call to <code class="function">odr_reset()</code> will be released.
180 </p><div class="example"><a name="id2602189"></a><p class="title"><b>Example 9.2. Encoding and decoding of an integer</b></p><div class="example-contents"><p>
181 The use of the double indirection can be a little confusing at first
182 (its purpose will become clear later on, hopefully),
183 so an example is in order. We'll encode an integer value, and
184 immediately decode it again using a different stream. A useless, but
185 informative operation.
186 </p><pre class="programlisting">
187 void do_nothing_useful(int value)
194 /* allocate streams */
195 if (!(encode = odr_createmem(ODR_ENCODE)))
197 if (!(decode = odr_createmem(ODR_DECODE)))
200 valp = &amp;value;
201 if (odr_integer(encode, &amp;valp, 0, 0) == 0)
203 printf("encoding went bad\n");
206 bufferp = odr_getbuf(encode, &amp;len);
207 printf("length of encoded data is &percnt;d\n", len);
209 /* now let's decode the thing again */
210 odr_setbuf(decode, bufferp, len);
211 if (odr_integer(decode, &amp;resvalp, 0, 0) == 0)
213 printf("decoding went bad\n");
216 printf("the value is &percnt;d\n", *resvalp);
224 This looks like a lot of work, offhand. In practice, the <acronym class="acronym">ODR</acronym> streams
225 will typically be allocated once, in the beginning of your program
226 (or at the beginning of a new network session), and the encoding
227 and decoding will only take place in a few, isolated places in your
228 program, so the overhead is quite manageable.
229 </p></div></div><br class="example-break"></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2602222"></a>2.4. Printing</h3></div></div></div><p>
230 When an ODR stream is created of type <code class="literal">ODR_PRINT</code>
231 the ODR module will print the contents of a PDU in a readable format.
232 By default output is written to the <code class="literal">stderr</code> stream.
233 This behavior can be changed, however, by calling the function
234 </p><pre class="synopsis">
235 odr_setprint(ODR o, FILE *file);
237 before encoders or decoders are being invoked.
238 It is also possible to direct the output to a buffer (of indeed
239 another file), by using the more generic mechanism:
240 </p><pre class="synopsis">
241 void odr_set_stream(ODR o, void *handle,
242 void (*stream_write)(ODR o, void *handle, int type,
243 const char *buf, int len),
244 void (*stream_close)(void *handle));
246 Here the user provides an opaque handle and two handlers,
247 <em class="replaceable"><code>stream_write</code></em> for writing,
248 and <em class="replaceable"><code>stream_close</code></em> which is supposed
249 to close/free resources associated with handle.
250 The <em class="replaceable"><code>stream_close</code></em> handler is optional and
251 if NULL for the function is provided, it will not be invoked.
252 The <em class="replaceable"><code>stream_write</code></em> takes the ODR handle
253 as parameter, the user defined handle, a type
254 <code class="literal">ODR_OCTETSTRING</code>, <code class="literal">ODR_VISIBLESTRING</code>
255 which indicates the type of contents is being written.
257 Another utility useful for diagnostics (error handling) or as
258 part of the printing facilities is:
259 </p><pre class="synopsis">
260 const char **odr_get_element_path(ODR o);
262 which returns a list of current elements that ODR deals with at the
263 moment. For the returned array, say <code class="literal">ar</code>,
264 <code class="literal">ar[0]</code> is the top level element,
265 <code class="literal">ar[n]</code> is the last. The last element has the
266 property that <code class="literal">ar[n+1] == NULL</code>.
267 </p><div class="example"><a name="id2602368"></a><p class="title"><b>Example 9.3. Element Path for record</b></p><div class="example-contents"><p>
268 For a database record part of a PresentResponse the
269 array returned by <code class="function">odr_get_element</code>
270 is <code class="literal">presentResponse</code>, <code class="literal">databaseOrSurDiagnostics</code>, <code class="literal">?</code>, <code class="literal">record</code>, <code class="literal">?</code>, <code class="literal">databaseRecord</code> . The question mark appears due to
271 unnamed constructions.
272 </p></div></div><br class="example-break"></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2602422"></a>2.5. Diagnostics</h3></div></div></div><p>
273 The encoding/decoding functions all return 0 when an error occurs.
274 Until you call <code class="function">odr_reset()</code>, you cannot use the
275 stream again, and any function called will immediately return 0.
277 To provide information to the programmer or administrator, the function
278 </p><pre class="synopsis">
279 void odr_perror(ODR o, char *message);
281 is provided, which prints the <code class="literal">message</code> argument to
282 <code class="literal">stderr</code> along with an error message from the stream.
284 You can also use the function
285 </p><pre class="synopsis">
286 int odr_geterror(ODR o);
288 to get the current error number from the screen. The number will be
289 one of these constants:
290 </p><div class="table"><a name="id2602483"></a><p class="title"><b>Table 9.1. ODR Error codes</b></p><div class="table-contents"><table summary="ODR Error codes" border="1"><colgroup><col><col></colgroup><thead><tr><th>code</th><th>Description</th></tr></thead><tbody><tr><td>OMEMORY</td><td>Memory allocation failed.</td></tr><tr><td>OSYSERR</td><td>A system- or library call has failed.
291 The standard diagnostic variable <code class="literal">errno</code> should be
292 examined to determine the actual error.</td></tr><tr><td>OSPACE</td><td>No more space for encoding.
293 This will only occur when the user has explicitly provided a
294 buffer for an encoding stream without allowing the system to
295 allocate more space.</td></tr><tr><td>OREQUIRED</td><td>This is a common protocol error; A
296 required data element was missing during encoding or decoding.</td></tr><tr><td>OUNEXPECTED</td><td>An unexpected data element was
297 found during decoding.</td></tr><tr><td>OOTHER</td><td>Other error. This is typically an
298 indication of misuse of the <acronym class="acronym">ODR</acronym> system by the programmer, and also
299 that the diagnostic system isn't as good as it should be, yet.</td></tr></tbody></table></div></div><br class="table-break"><p>
300 The character string array
301 </p><pre class="synopsis">
304 can be indexed by the error code to obtain a human-readable
305 representation of the problem.
306 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="id2602602"></a>2.6. Summary and Synopsis</h3></div></div></div><pre class="synopsis">
307 #include <odr.h>
309 ODR odr_createmem(int direction);
311 void odr_destroy(ODR o);
313 void odr_reset(ODR o);
315 char *odr_getbuf(ODR o, int *len);
317 void odr_setbuf(ODR o, char *buf, int len);
319 void *odr_malloc(ODR o, int size);
321 ODR_MEM odr_extract_mem(ODR o);
323 void odr_release_mem(ODR_MEM r);
325 int odr_geterror(ODR o);
327 void odr_perror(char *message);
329 extern char *odr_errlist[];
330 </pre></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="odr.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.programming.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 9. The ODR Module </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 3. Programming with ODR</td></tr></table></div></body></html>