5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 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.
20 /* Implementation of generic payloads described in the protocol
21 specification drafts. */
24 #include "silcincludes.h"
25 #include "silcpayload.h"
27 /******************************************************************************
31 ******************************************************************************/
33 struct SilcIDPayloadStruct {
39 /* Parses buffer and return ID payload into payload structure */
41 SilcIDPayload silc_id_payload_parse(SilcBuffer buffer)
45 SILC_LOG_DEBUG(("Parsing ID payload"));
47 new = silc_calloc(1, sizeof(*new));
49 silc_buffer_unformat(buffer,
50 SILC_STR_UI_SHORT(&new->type),
51 SILC_STR_UI_SHORT(&new->len),
54 silc_buffer_pull(buffer, 4);
56 if (new->len > buffer->len)
59 silc_buffer_unformat(buffer,
60 SILC_STR_UI_XNSTRING_ALLOC(&new->id, new->len),
62 silc_buffer_push(buffer, 4);
71 /* Parses data and return ID payload into payload structure. */
73 SilcIDPayload silc_id_payload_parse_data(unsigned char *data,
79 SILC_LOG_DEBUG(("Parsing ID payload"));
81 buffer = silc_buffer_alloc(len);
82 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
83 silc_buffer_put(buffer, data, len);
85 new = silc_calloc(1, sizeof(*new));
87 silc_buffer_unformat(buffer,
88 SILC_STR_UI_SHORT(&new->type),
89 SILC_STR_UI_SHORT(&new->len),
92 silc_buffer_pull(buffer, 4);
94 if (new->len > buffer->len)
97 silc_buffer_unformat(buffer,
98 SILC_STR_UI_XNSTRING_ALLOC(&new->id, new->len),
101 silc_buffer_free(buffer);
105 silc_buffer_free(buffer);
110 /* Return the ID directly from the raw payload data. */
112 void *silc_id_payload_parse_id(unsigned char *data, unsigned int len)
116 unsigned short idlen;
119 buffer = silc_buffer_alloc(len);
120 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
121 silc_buffer_put(buffer, data, len);
123 silc_buffer_unformat(buffer,
124 SILC_STR_UI_SHORT(&type),
125 SILC_STR_UI_SHORT(&idlen),
128 silc_buffer_pull(buffer, 4);
130 if (idlen > buffer->len)
133 silc_buffer_unformat(buffer,
134 SILC_STR_UI_XNSTRING_ALLOC(&id, idlen),
137 silc_buffer_free(buffer);
139 return silc_id_str2id(id, type);
142 silc_buffer_free(buffer);
146 /* Encodes ID Payload */
148 SilcBuffer silc_id_payload_encode(void *id, SilcIdType type)
151 unsigned char *id_data;
154 SILC_LOG_DEBUG(("Parsing ID payload"));
156 id_data = silc_id_id2str(id, type);
157 len = silc_id_get_len(type);
159 buffer = silc_buffer_alloc(4 + len);
160 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
161 silc_buffer_format(buffer,
162 SILC_STR_UI_SHORT(type),
163 SILC_STR_UI_SHORT(len),
164 SILC_STR_UI_XNSTRING(id_data, len),
171 /* Free ID Payload */
173 void silc_id_payload_free(SilcIDPayload payload)
176 silc_free(payload->id);
182 SilcIdType silc_id_payload_get_type(SilcIDPayload payload)
184 return payload->type;
189 void *silc_id_payload_get_id(SilcIDPayload payload)
191 return silc_id_str2id(payload->id, payload->type);
194 /* Get raw ID data. Data is duplicated. */
196 unsigned char *silc_id_payload_get_data(SilcIDPayload payload)
198 unsigned char *ret = silc_calloc(payload->len, sizeof(*ret));
199 memcpy(ret, payload->id, payload->len);
203 /* Get length of ID */
205 unsigned int silc_id_payload_get_len(SilcIDPayload payload)
210 /******************************************************************************
214 ******************************************************************************/
216 struct SilcArgumentPayloadStruct {
218 unsigned char **argv;
219 unsigned int *argv_lens;
220 unsigned int *argv_types;
224 /* Parses arguments and returns them into Argument Payload structure. */
226 SilcArgumentPayload silc_argument_payload_parse(SilcBuffer buffer,
229 SilcArgumentPayload new;
230 unsigned short payload_len = 0;
231 unsigned char arg_num = 0;
232 unsigned int arg_type = 0;
233 unsigned int pull_len = 0;
236 SILC_LOG_DEBUG(("Parsing argument payload"));
238 new = silc_calloc(1, sizeof(*new));
239 new->argv = silc_calloc(argc, sizeof(unsigned char *));
240 new->argv_lens = silc_calloc(argc, sizeof(unsigned int));
241 new->argv_types = silc_calloc(argc, sizeof(unsigned int));
245 for (i = 0; i < argc; i++) {
246 silc_buffer_unformat(buffer,
247 SILC_STR_UI_SHORT(&payload_len),
248 SILC_STR_UI_CHAR(&arg_type),
251 new->argv_lens[i] = payload_len;
252 new->argv_types[i] = arg_type;
254 if (payload_len > buffer->len)
257 /* Get argument data */
258 silc_buffer_pull(buffer, 3);
259 silc_buffer_unformat(buffer,
260 SILC_STR_UI_XNSTRING_ALLOC(&new->argv[i],
264 silc_buffer_pull(buffer, payload_len);
265 pull_len += 3 + payload_len;
268 if (buffer->len != 0)
274 silc_buffer_push(buffer, pull_len);
282 for (k = 0; k < i; k++)
283 silc_free(new->argv[k]);
286 silc_free(new->argv);
287 silc_free(new->argv_lens);
288 silc_free(new->argv_types);
296 /* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
298 SilcBuffer silc_argument_payload_encode(unsigned int argc,
299 unsigned char **argv,
300 unsigned int *argv_lens,
301 unsigned int *argv_types)
307 SILC_LOG_DEBUG(("Encoding Argument payload"));
310 for (i = 0; i < argc; i++)
311 len += 3 + argv_lens[i];
313 buffer = silc_buffer_alloc(len);
314 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
317 for (i = 0; i < argc; i++) {
318 silc_buffer_format(buffer,
319 SILC_STR_UI_SHORT(argv_lens[i]),
320 SILC_STR_UI_CHAR(argv_types[i]),
321 SILC_STR_UI_XNSTRING(argv[i], argv_lens[i]),
323 silc_buffer_pull(buffer, 3 + argv_lens[i]);
326 silc_buffer_push(buffer, len);
332 /* Encodes Argument payload with variable argument list. The arguments
333 must be: unsigned int, unsigned char *, unsigned int, ... One
334 {unsigned int, unsigned char * and unsigned int} forms one argument,
335 thus `argc' in case when sending one {unsigned int, unsigned char *
336 and unsigned int} equals one (1) and when sending two of those it
337 equals two (2), and so on. This has to be preserved or bad things
338 will happen. The variable arguments is: {type, data, data_len}. */
340 SilcBuffer silc_command_encode_payload_va(unsigned int argc, ...)
343 unsigned char **argv;
344 unsigned int *argv_lens = NULL, *argv_types = NULL;
353 argv = silc_calloc(argc, sizeof(unsigned char *));
354 argv_lens = silc_calloc(argc, sizeof(unsigned int));
355 argv_types = silc_calloc(argc, sizeof(unsigned int));
357 for (i = 0; i < argc; i++) {
358 x_type = va_arg(ap, unsigned int);
359 x = va_arg(ap, unsigned char *);
360 x_len = va_arg(ap, unsigned int);
362 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
363 memcpy(argv[i], x, x_len);
364 argv_lens[i] = x_len;
365 argv_types[i] = x_type;
368 buffer = silc_argument_payload_encode(argc, argv,
369 argv_lens, argv_types);
371 for (i = 0; i < argc; i++)
374 silc_free(argv_lens);
375 silc_free(argv_types);
381 /* Free's Command Payload */
383 void silc_argument_payload_free(SilcArgumentPayload payload)
388 for (i = 0; i < payload->argc; i++)
389 silc_free(payload->argv[i]);
391 silc_free(payload->argv);
396 /* Returns number of arguments in payload */
398 unsigned int silc_argument_get_arg_num(SilcArgumentPayload payload)
400 return payload->argc;
403 /* Returns first argument from payload. */
405 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
406 unsigned int *ret_len)
411 *ret_len = payload->argv_lens[payload->pos];
413 return payload->argv[payload->pos++];
416 /* Returns next argument from payload or NULL if no more arguments. */
418 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
419 unsigned int *ret_len)
421 if (payload->pos >= payload->argc)
425 *ret_len = payload->argv_lens[payload->pos];
427 return payload->argv[payload->pos++];
430 /* Returns argument which type is `type'. */
432 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
434 unsigned int *ret_len)
438 for (i = 0; i < payload->argc; i++)
439 if (payload->argv_types[i] == type)
442 if (i >= payload->argc)
446 *ret_len = payload->argv_lens[i];
448 return payload->argv[i];