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 /* Encodes ID Payload */
112 SilcBuffer silc_id_payload_encode(void *id, unsigned short len,
116 unsigned char *id_data;
118 SILC_LOG_DEBUG(("Parsing ID payload"));
120 id_data = silc_id_id2str(id, type);
122 buffer = silc_buffer_alloc(4 + len);
123 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
124 silc_buffer_format(buffer,
125 SILC_STR_UI_SHORT(type),
126 SILC_STR_UI_SHORT(len),
127 SILC_STR_UI_XNSTRING(id_data, len),
134 /* Free ID Payload */
136 void silc_id_payload_free(SilcIDPayload payload)
139 silc_free(payload->id);
145 SilcIdType silc_id_payload_get_type(SilcIDPayload payload)
147 return payload->type;
152 void *silc_id_payload_get_id(SilcIDPayload payload)
154 return silc_id_str2id(payload->id, payload->type);
157 /******************************************************************************
161 ******************************************************************************/
163 struct SilcArgumentPayloadStruct {
165 unsigned char **argv;
166 unsigned int *argv_lens;
167 unsigned int *argv_types;
171 /* Parses arguments and returns them into Argument Payload structure. */
173 SilcArgumentPayload silc_argument_payload_parse(SilcBuffer buffer,
176 SilcArgumentPayload new;
177 unsigned short payload_len = 0;
178 unsigned char arg_num = 0;
179 unsigned int arg_type = 0;
180 unsigned int pull_len = 0;
183 SILC_LOG_DEBUG(("Parsing argument payload"));
185 new = silc_calloc(1, sizeof(*new));
186 new->argv = silc_calloc(argc, sizeof(unsigned char *));
187 new->argv_lens = silc_calloc(argc, sizeof(unsigned int));
188 new->argv_types = silc_calloc(argc, sizeof(unsigned int));
192 for (i = 0; i < argc; i++) {
193 silc_buffer_unformat(buffer,
194 SILC_STR_UI_SHORT(&payload_len),
195 SILC_STR_UI_CHAR(&arg_type),
198 new->argv_lens[i] = payload_len;
199 new->argv_types[i] = arg_type;
201 if (payload_len > buffer->len)
204 /* Get argument data */
205 silc_buffer_pull(buffer, 3);
206 silc_buffer_unformat(buffer,
207 SILC_STR_UI_XNSTRING_ALLOC(&new->argv[i],
211 silc_buffer_pull(buffer, payload_len);
212 pull_len += 3 + payload_len;
215 if (buffer->len != 0)
221 silc_buffer_push(buffer, pull_len);
229 for (k = 0; k < i; k++)
230 silc_free(new->argv[k]);
233 silc_free(new->argv);
234 silc_free(new->argv_lens);
235 silc_free(new->argv_types);
243 /* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
245 SilcBuffer silc_argument_payload_encode(unsigned int argc,
246 unsigned char **argv,
247 unsigned int *argv_lens,
248 unsigned int *argv_types)
254 SILC_LOG_DEBUG(("Encoding Argument payload"));
257 for (i = 0; i < argc; i++)
258 len += 3 + argv_lens[i];
260 buffer = silc_buffer_alloc(len);
261 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
264 for (i = 0; i < argc; i++) {
265 silc_buffer_format(buffer,
266 SILC_STR_UI_SHORT(argv_lens[i]),
267 SILC_STR_UI_CHAR(argv_types[i]),
268 SILC_STR_UI_XNSTRING(argv[i], argv_lens[i]),
270 silc_buffer_pull(buffer, 3 + argv_lens[i]);
273 silc_buffer_push(buffer, len);
279 /* Encodes Argument payload with variable argument list. The arguments
280 must be: unsigned int, unsigned char *, unsigned int, ... One
281 {unsigned int, unsigned char * and unsigned int} forms one argument,
282 thus `argc' in case when sending one {unsigned int, unsigned char *
283 and unsigned int} equals one (1) and when sending two of those it
284 equals two (2), and so on. This has to be preserved or bad things
285 will happen. The variable arguments is: {type, data, data_len}. */
287 SilcBuffer silc_command_encode_payload_va(unsigned int argc, ...)
290 unsigned char **argv;
291 unsigned int *argv_lens = NULL, *argv_types = NULL;
300 argv = silc_calloc(argc, sizeof(unsigned char *));
301 argv_lens = silc_calloc(argc, sizeof(unsigned int));
302 argv_types = silc_calloc(argc, sizeof(unsigned int));
304 for (i = 0; i < argc; i++) {
305 x_type = va_arg(ap, unsigned int);
306 x = va_arg(ap, unsigned char *);
307 x_len = va_arg(ap, unsigned int);
309 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
310 memcpy(argv[i], x, x_len);
311 argv_lens[i] = x_len;
312 argv_types[i] = x_type;
315 buffer = silc_argument_payload_encode(argc, argv,
316 argv_lens, argv_types);
318 for (i = 0; i < argc; i++)
321 silc_free(argv_lens);
322 silc_free(argv_types);
328 /* Free's Command Payload */
330 void silc_argument_payload_free(SilcArgumentPayload payload)
335 for (i = 0; i < payload->argc; i++)
336 silc_free(payload->argv[i]);
338 silc_free(payload->argv);
343 /* Returns number of arguments in payload */
345 unsigned int silc_argument_get_arg_num(SilcArgumentPayload payload)
347 return payload->argc;
350 /* Returns first argument from payload. */
352 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
353 unsigned int *ret_len)
358 *ret_len = payload->argv_lens[payload->pos];
360 return payload->argv[payload->pos++];
363 /* Returns next argument from payload or NULL if no more arguments. */
365 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
366 unsigned int *ret_len)
368 if (payload->pos >= payload->argc)
372 *ret_len = payload->argv_lens[payload->pos];
374 return payload->argv[payload->pos++];
377 /* Returns argument which type is `type'. */
379 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
381 unsigned int *ret_len)
385 for (i = 0; i < payload->argc; i++)
386 if (payload->argv_types[i] == type)
389 if (i >= payload->argc)
393 *ret_len = payload->argv_lens[i];
395 return payload->argv[i];