5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
22 #include "silcincludes.h"
24 /* Macro to check whether there is enough free space to add the
25 required amount of data. For unformatting this means that there must
26 be the data that is to be extracted. */
27 #define HAS_SPACE(x, req) \
33 /* Formats the arguments sent and puts them into the buffer sent as
34 argument. The buffer must be initialized beforehand and it must have
35 enough free space to include the formatted data. If this function
36 fails caller should not trust the buffer anymore and should free it.
37 This function is used, for example, to create packets to send over
40 int silc_buffer_format(SilcBuffer dst, ...)
46 ret = silc_buffer_format_vp(dst, ap);
52 int silc_buffer_format_vp(SilcBuffer dst, va_list ap)
54 SilcBufferParamType fmt;
55 unsigned char *start_ptr = dst->data;
58 /* Parse the arguments by formatting type. */
60 fmt = va_arg(ap, SilcBufferParamType);
63 case SILC_BUFFER_PARAM_SI8_CHAR:
65 char x = (char)va_arg(ap, int);
67 silc_buffer_put(dst, &x, 1);
68 silc_buffer_pull(dst, 1);
71 case SILC_BUFFER_PARAM_UI8_CHAR:
73 unsigned char x = (unsigned char)va_arg(ap, int);
75 silc_buffer_put(dst, &x, 1);
76 silc_buffer_pull(dst, 1);
79 case SILC_BUFFER_PARAM_SI16_SHORT:
82 int16 x = (int16)va_arg(ap, int);
84 SILC_PUT16_MSB(x, xf);
85 silc_buffer_put(dst, xf, 2);
86 silc_buffer_pull(dst, 2);
89 case SILC_BUFFER_PARAM_UI16_SHORT:
92 uint16 x = (uint16)va_arg(ap, int);
94 SILC_PUT16_MSB(x, xf);
95 silc_buffer_put(dst, xf, 2);
96 silc_buffer_pull(dst, 2);
99 case SILC_BUFFER_PARAM_SI32_INT:
102 int32 x = va_arg(ap, int32);
104 SILC_PUT32_MSB(x, xf);
105 silc_buffer_put(dst, xf, 4);
106 silc_buffer_pull(dst, 4);
109 case SILC_BUFFER_PARAM_UI32_INT:
112 uint32 x = va_arg(ap, uint32);
114 SILC_PUT32_MSB(x, xf);
115 silc_buffer_put(dst, xf, 4);
116 silc_buffer_pull(dst, 4);
119 case SILC_BUFFER_PARAM_SI64_INT:
122 int64 x = va_arg(ap, int64);
124 SILC_PUT64_MSB(x, xf);
125 silc_buffer_put(dst, xf, 8);
126 silc_buffer_pull(dst, 8);
129 case SILC_BUFFER_PARAM_UI64_INT:
132 uint64 x = va_arg(ap, uint64);
134 SILC_PUT64_MSB(x, xf);
135 silc_buffer_put(dst, xf, 8);
136 silc_buffer_pull(dst, 8);
139 case SILC_BUFFER_PARAM_UI16_STRING:
140 case SILC_BUFFER_PARAM_UI32_STRING:
141 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
142 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
144 unsigned char *x = va_arg(ap, unsigned char *);
145 uint32 tmp_len = strlen(x);
146 HAS_SPACE(dst, tmp_len);
147 silc_buffer_put(dst, x, tmp_len);
148 silc_buffer_pull(dst, tmp_len);
151 case SILC_BUFFER_PARAM_UI16_NSTRING:
152 case SILC_BUFFER_PARAM_UI32_NSTRING:
153 case SILC_BUFFER_PARAM_UI_XNSTRING:
154 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
155 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
156 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
158 unsigned char *x = va_arg(ap, unsigned char *);
159 uint32 len = va_arg(ap, uint32);
161 silc_buffer_put(dst, x, len);
162 silc_buffer_pull(dst, len);
165 case SILC_BUFFER_PARAM_END:
169 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
170 "format the data.", fmt));
177 SILC_LOG_DEBUG(("Error occured while formatting data"));
181 /* Push the buffer back to where it belongs. */
182 len = dst->data - start_ptr;
183 silc_buffer_push(dst, len);
187 /* Unformats the buffer sent as argument. The unformatted data is returned
188 to the variable argument list of pointers. The buffer must point to the
189 start of the data area to be unformatted. Buffer maybe be safely free'd
190 after this returns succesfully. */
192 int silc_buffer_unformat(SilcBuffer src, ...)
198 ret = silc_buffer_unformat_vp(src, ap);
204 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
206 SilcBufferParamType fmt;
207 unsigned char *start_ptr = src->data;
210 /* Parse the arguments by formatting type. */
212 fmt = va_arg(ap, SilcBufferParamType);
215 case SILC_BUFFER_PARAM_SI8_CHAR:
217 char *x = va_arg(ap, char *);
221 silc_buffer_pull(src, 1);
224 case SILC_BUFFER_PARAM_UI8_CHAR:
226 unsigned char *x = va_arg(ap, unsigned char *);
230 silc_buffer_pull(src, 1);
233 case SILC_BUFFER_PARAM_SI16_SHORT:
235 int16 *x = va_arg(ap, int16 *);
238 SILC_GET16_MSB(*x, src->data);
239 silc_buffer_pull(src, 2);
242 case SILC_BUFFER_PARAM_UI16_SHORT:
244 uint16 *x = va_arg(ap, uint16 *);
247 SILC_GET16_MSB(*x, src->data);
248 silc_buffer_pull(src, 2);
251 case SILC_BUFFER_PARAM_SI32_INT:
253 int32 *x = va_arg(ap, int32 *);
256 SILC_GET32_MSB(*x, src->data);
257 silc_buffer_pull(src, 4);
260 case SILC_BUFFER_PARAM_UI32_INT:
262 uint32 *x = va_arg(ap, uint32 *);
265 SILC_GET32_MSB(*x, src->data);
266 silc_buffer_pull(src, 4);
269 case SILC_BUFFER_PARAM_SI64_INT:
271 int64 *x = va_arg(ap, int64 *);
274 SILC_GET64_MSB(*x, src->data);
275 silc_buffer_pull(src, 8);
278 case SILC_BUFFER_PARAM_UI64_INT:
280 uint64 *x = va_arg(ap, uint64 *);
283 SILC_GET64_MSB(*x, src->data);
284 silc_buffer_pull(src, 8);
287 case SILC_BUFFER_PARAM_UI16_STRING:
290 unsigned char **x = va_arg(ap, unsigned char **);
292 SILC_GET16_MSB(len2, src->data);
293 silc_buffer_pull(src, 2);
294 HAS_SPACE(src, len2);
297 silc_buffer_pull(src, len2);
300 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
303 unsigned char **x = va_arg(ap, unsigned char **);
305 SILC_GET16_MSB(len2, src->data);
306 silc_buffer_pull(src, 2);
307 HAS_SPACE(src, len2);
309 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
310 memcpy(*x, src->data, len2);
312 silc_buffer_pull(src, len2);
315 case SILC_BUFFER_PARAM_UI32_STRING:
318 unsigned char **x = va_arg(ap, unsigned char **);
320 SILC_GET32_MSB(len2, src->data);
321 silc_buffer_pull(src, 4);
322 HAS_SPACE(src, len2);
325 silc_buffer_pull(src, len2);
328 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
331 unsigned char **x = va_arg(ap, unsigned char **);
333 SILC_GET32_MSB(len2, src->data);
334 silc_buffer_pull(src, 4);
335 HAS_SPACE(src, len2);
337 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
338 memcpy(*x, src->data, len2);
340 silc_buffer_pull(src, len2);
343 case SILC_BUFFER_PARAM_UI16_NSTRING:
346 unsigned char **x = va_arg(ap, unsigned char **);
347 uint16 *len = va_arg(ap, unsigned short *);
349 SILC_GET16_MSB(len2, src->data);
350 silc_buffer_pull(src, 2);
351 HAS_SPACE(src, len2);
356 silc_buffer_pull(src, len2);
359 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
362 unsigned char **x = va_arg(ap, unsigned char **);
363 uint16 *len = va_arg(ap, uint16 *);
365 SILC_GET16_MSB(len2, src->data);
366 silc_buffer_pull(src, 2);
367 HAS_SPACE(src, len2);
371 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
372 memcpy(*x, src->data, len2);
374 silc_buffer_pull(src, len2);
377 case SILC_BUFFER_PARAM_UI32_NSTRING:
380 unsigned char **x = va_arg(ap, unsigned char **);
381 uint32 *len = va_arg(ap, uint32 *);
383 SILC_GET32_MSB(len2, src->data);
384 silc_buffer_pull(src, 4);
385 HAS_SPACE(src, len2);
390 silc_buffer_pull(src, len2);
393 case SILC_BUFFER_PARAM_UI_XNSTRING:
395 unsigned char **x = va_arg(ap, unsigned char **);
396 uint32 len = va_arg(ap, uint32);
400 silc_buffer_pull(src, len);
403 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
405 unsigned char **x = va_arg(ap, unsigned char **);
406 uint32 len = va_arg(ap, uint32);
409 *x = silc_calloc(len + 1, sizeof(unsigned char));
410 memcpy(*x, src->data, len);
412 silc_buffer_pull(src, len);
415 case SILC_BUFFER_PARAM_END:
419 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
420 "format the data.", fmt));
427 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
431 /* Push the buffer back to the start. */
432 len = src->data - start_ptr;
433 silc_buffer_push(src, len);