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_UI8_STRING:
140 case SILC_BUFFER_PARAM_UI16_STRING:
141 case SILC_BUFFER_PARAM_UI32_STRING:
142 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
143 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
144 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
146 unsigned char *x = va_arg(ap, unsigned char *);
147 uint32 tmp_len = strlen(x);
148 HAS_SPACE(dst, tmp_len);
149 silc_buffer_put(dst, x, tmp_len);
150 silc_buffer_pull(dst, tmp_len);
153 case SILC_BUFFER_PARAM_UI8_NSTRING:
154 case SILC_BUFFER_PARAM_UI16_NSTRING:
155 case SILC_BUFFER_PARAM_UI32_NSTRING:
156 case SILC_BUFFER_PARAM_UI_XNSTRING:
157 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
158 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
159 case SILC_BUFFER_PARAM_UI32_NSTRING_ALLOC:
160 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
162 unsigned char *x = va_arg(ap, unsigned char *);
163 uint32 len = va_arg(ap, uint32);
165 silc_buffer_put(dst, x, len);
166 silc_buffer_pull(dst, len);
169 case SILC_BUFFER_PARAM_END:
173 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
174 "format the data.", fmt));
181 SILC_LOG_DEBUG(("Error occured while formatting data"));
185 /* Push the buffer back to where it belongs. */
186 len = dst->data - start_ptr;
187 silc_buffer_push(dst, len);
191 /* Unformats the buffer sent as argument. The unformatted data is returned
192 to the variable argument list of pointers. The buffer must point to the
193 start of the data area to be unformatted. Buffer maybe be safely free'd
194 after this returns succesfully. */
196 int silc_buffer_unformat(SilcBuffer src, ...)
202 ret = silc_buffer_unformat_vp(src, ap);
208 int silc_buffer_unformat_vp(SilcBuffer src, va_list ap)
210 SilcBufferParamType fmt;
211 unsigned char *start_ptr = src->data;
214 /* Parse the arguments by formatting type. */
216 fmt = va_arg(ap, SilcBufferParamType);
219 case SILC_BUFFER_PARAM_SI8_CHAR:
221 char *x = va_arg(ap, char *);
225 silc_buffer_pull(src, 1);
228 case SILC_BUFFER_PARAM_UI8_CHAR:
230 unsigned char *x = va_arg(ap, unsigned char *);
234 silc_buffer_pull(src, 1);
237 case SILC_BUFFER_PARAM_SI16_SHORT:
239 int16 *x = va_arg(ap, int16 *);
242 SILC_GET16_MSB(*x, src->data);
243 silc_buffer_pull(src, 2);
246 case SILC_BUFFER_PARAM_UI16_SHORT:
248 uint16 *x = va_arg(ap, uint16 *);
251 SILC_GET16_MSB(*x, src->data);
252 silc_buffer_pull(src, 2);
255 case SILC_BUFFER_PARAM_SI32_INT:
257 int32 *x = va_arg(ap, int32 *);
260 SILC_GET32_MSB(*x, src->data);
261 silc_buffer_pull(src, 4);
264 case SILC_BUFFER_PARAM_UI32_INT:
266 uint32 *x = va_arg(ap, uint32 *);
269 SILC_GET32_MSB(*x, src->data);
270 silc_buffer_pull(src, 4);
273 case SILC_BUFFER_PARAM_SI64_INT:
275 int64 *x = va_arg(ap, int64 *);
278 SILC_GET64_MSB(*x, src->data);
279 silc_buffer_pull(src, 8);
282 case SILC_BUFFER_PARAM_UI64_INT:
284 uint64 *x = va_arg(ap, uint64 *);
287 SILC_GET64_MSB(*x, src->data);
288 silc_buffer_pull(src, 8);
291 case SILC_BUFFER_PARAM_UI8_STRING:
294 unsigned char **x = va_arg(ap, unsigned char **);
296 len2 = (uint8)src->data[0];
297 silc_buffer_pull(src, 1);
298 HAS_SPACE(src, len2);
301 silc_buffer_pull(src, len2);
304 case SILC_BUFFER_PARAM_UI16_STRING:
307 unsigned char **x = va_arg(ap, unsigned char **);
309 SILC_GET16_MSB(len2, src->data);
310 silc_buffer_pull(src, 2);
311 HAS_SPACE(src, len2);
314 silc_buffer_pull(src, len2);
317 case SILC_BUFFER_PARAM_UI8_STRING_ALLOC:
320 unsigned char **x = va_arg(ap, unsigned char **);
322 len2 = (uint8)src->data[0];
323 silc_buffer_pull(src, 1);
324 HAS_SPACE(src, len2);
326 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
327 memcpy(*x, src->data, len2);
329 silc_buffer_pull(src, len2);
332 case SILC_BUFFER_PARAM_UI16_STRING_ALLOC:
335 unsigned char **x = va_arg(ap, unsigned char **);
337 SILC_GET16_MSB(len2, src->data);
338 silc_buffer_pull(src, 2);
339 HAS_SPACE(src, len2);
341 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
342 memcpy(*x, src->data, len2);
344 silc_buffer_pull(src, len2);
347 case SILC_BUFFER_PARAM_UI32_STRING:
350 unsigned char **x = va_arg(ap, unsigned char **);
352 SILC_GET32_MSB(len2, src->data);
353 silc_buffer_pull(src, 4);
354 HAS_SPACE(src, len2);
357 silc_buffer_pull(src, len2);
360 case SILC_BUFFER_PARAM_UI32_STRING_ALLOC:
363 unsigned char **x = va_arg(ap, unsigned char **);
365 SILC_GET32_MSB(len2, src->data);
366 silc_buffer_pull(src, 4);
367 HAS_SPACE(src, len2);
369 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
370 memcpy(*x, src->data, len2);
372 silc_buffer_pull(src, len2);
375 case SILC_BUFFER_PARAM_UI8_NSTRING:
378 unsigned char **x = va_arg(ap, unsigned char **);
379 uint8 *len = va_arg(ap, uint8 *);
381 len2 = (uint8)src->data[0];
382 silc_buffer_pull(src, 1);
383 HAS_SPACE(src, len2);
388 silc_buffer_pull(src, len2);
391 case SILC_BUFFER_PARAM_UI16_NSTRING:
394 unsigned char **x = va_arg(ap, unsigned char **);
395 uint16 *len = va_arg(ap, uint16 *);
397 SILC_GET16_MSB(len2, src->data);
398 silc_buffer_pull(src, 2);
399 HAS_SPACE(src, len2);
404 silc_buffer_pull(src, len2);
407 case SILC_BUFFER_PARAM_UI8_NSTRING_ALLOC:
410 unsigned char **x = va_arg(ap, unsigned char **);
411 uint8 *len = va_arg(ap, uint8 *);
413 len2 = (uint8)src->data[0];
414 silc_buffer_pull(src, 1);
415 HAS_SPACE(src, len2);
419 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
420 memcpy(*x, src->data, len2);
422 silc_buffer_pull(src, len2);
425 case SILC_BUFFER_PARAM_UI16_NSTRING_ALLOC:
428 unsigned char **x = va_arg(ap, unsigned char **);
429 uint16 *len = va_arg(ap, uint16 *);
431 SILC_GET16_MSB(len2, src->data);
432 silc_buffer_pull(src, 2);
433 HAS_SPACE(src, len2);
437 *x = silc_calloc(len2 + 1, sizeof(unsigned char));
438 memcpy(*x, src->data, len2);
440 silc_buffer_pull(src, len2);
443 case SILC_BUFFER_PARAM_UI32_NSTRING:
446 unsigned char **x = va_arg(ap, unsigned char **);
447 uint32 *len = va_arg(ap, uint32 *);
449 SILC_GET32_MSB(len2, src->data);
450 silc_buffer_pull(src, 4);
451 HAS_SPACE(src, len2);
456 silc_buffer_pull(src, len2);
459 case SILC_BUFFER_PARAM_UI_XNSTRING:
461 unsigned char **x = va_arg(ap, unsigned char **);
462 uint32 len = va_arg(ap, uint32);
466 silc_buffer_pull(src, len);
469 case SILC_BUFFER_PARAM_UI_XNSTRING_ALLOC:
471 unsigned char **x = va_arg(ap, unsigned char **);
472 uint32 len = va_arg(ap, uint32);
475 *x = silc_calloc(len + 1, sizeof(unsigned char));
476 memcpy(*x, src->data, len);
478 silc_buffer_pull(src, len);
481 case SILC_BUFFER_PARAM_END:
485 SILC_LOG_DEBUG(("Bad buffer formatting type `%d'. Could not "
486 "format the data.", fmt));
493 SILC_LOG_DEBUG(("Error occured while unformatting buffer"));
497 /* Push the buffer back to the start. */
498 len = src->data - start_ptr;
499 silc_buffer_push(src, len);