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);
331 /* Same as above but encode the buffer from SilcArgumentPayload structure
332 instead of raw data. */
334 SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
340 SILC_LOG_DEBUG(("Encoding Argument payload"));
343 for (i = 0; i < payload->argc; i++)
344 len += 3 + payload->argv_lens[i];
346 buffer = silc_buffer_alloc(len);
347 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
350 for (i = 0; i < payload->argc; i++) {
351 silc_buffer_format(buffer,
352 SILC_STR_UI_SHORT(payload->argv_lens[i]),
353 SILC_STR_UI_CHAR(payload->argv_types[i]),
354 SILC_STR_UI_XNSTRING(payload->argv[i],
355 payload->argv_lens[i]),
357 silc_buffer_pull(buffer, 3 + payload->argv_lens[i]);
360 silc_buffer_push(buffer, len);
366 /* Encodes Argument payload with variable argument list. The arguments
367 must be: unsigned int, unsigned char *, unsigned int, ... One
368 {unsigned int, unsigned char * and unsigned int} forms one argument,
369 thus `argc' in case when sending one {unsigned int, unsigned char *
370 and unsigned int} equals one (1) and when sending two of those it
371 equals two (2), and so on. This has to be preserved or bad things
372 will happen. The variable arguments is: {type, data, data_len}. */
374 SilcBuffer silc_command_encode_payload_va(unsigned int argc, ...)
377 unsigned char **argv;
378 unsigned int *argv_lens = NULL, *argv_types = NULL;
387 argv = silc_calloc(argc, sizeof(unsigned char *));
388 argv_lens = silc_calloc(argc, sizeof(unsigned int));
389 argv_types = silc_calloc(argc, sizeof(unsigned int));
391 for (i = 0; i < argc; i++) {
392 x_type = va_arg(ap, unsigned int);
393 x = va_arg(ap, unsigned char *);
394 x_len = va_arg(ap, unsigned int);
396 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
397 memcpy(argv[i], x, x_len);
398 argv_lens[i] = x_len;
399 argv_types[i] = x_type;
402 buffer = silc_argument_payload_encode(argc, argv,
403 argv_lens, argv_types);
405 for (i = 0; i < argc; i++)
408 silc_free(argv_lens);
409 silc_free(argv_types);
415 /* Free's Command Payload */
417 void silc_argument_payload_free(SilcArgumentPayload payload)
422 for (i = 0; i < payload->argc; i++)
423 silc_free(payload->argv[i]);
425 silc_free(payload->argv);
430 /* Returns number of arguments in payload */
432 unsigned int silc_argument_get_arg_num(SilcArgumentPayload payload)
434 return payload->argc;
437 /* Returns first argument from payload. */
439 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
440 unsigned int *ret_len)
445 *ret_len = payload->argv_lens[payload->pos];
447 return payload->argv[payload->pos++];
450 /* Returns next argument from payload or NULL if no more arguments. */
452 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
453 unsigned int *ret_len)
455 if (payload->pos >= payload->argc)
459 *ret_len = payload->argv_lens[payload->pos];
461 return payload->argv[payload->pos++];
464 /* Returns argument which type is `type'. */
466 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
468 unsigned int *ret_len)
472 for (i = 0; i < payload->argc; i++)
473 if (payload->argv_types[i] == type)
476 if (i >= payload->argc)
480 *ret_len = payload->argv_lens[i];
482 return payload->argv[i];