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 data 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 if (new->len > buffer->len)
57 silc_buffer_pull(buffer, 4);
58 silc_buffer_unformat(buffer,
59 SILC_STR_UI_XNSTRING_ALLOC(&new->id, new->len),
61 silc_buffer_push(buffer, 4);
70 /* Encodes ID Payload */
72 SilcBuffer silc_id_payload_encode(void *id, unsigned short len,
76 unsigned char *id_data;
78 SILC_LOG_DEBUG(("Parsing ID payload"));
80 id_data = silc_id_id2str(id, type);
82 buffer = silc_buffer_alloc(4 + len);
83 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
84 silc_buffer_format(buffer,
85 SILC_STR_UI_SHORT(type),
86 SILC_STR_UI_SHORT(len),
87 SILC_STR_UI_XNSTRING(id_data, len),
96 void silc_id_payload_free(SilcIDPayload payload)
99 silc_free(payload->id);
105 SilcIdType silc_id_payload_get_type(SilcIDPayload payload)
107 return payload->type;
112 void *silc_id_payload_get_id(SilcIDPayload payload)
114 return silc_id_str2id(payload->id, payload->type);
117 /******************************************************************************
121 ******************************************************************************/
123 struct SilcArgumentPayloadStruct {
125 unsigned char **argv;
126 unsigned int *argv_lens;
127 unsigned int *argv_types;
131 /* Parses arguments and returns them into Argument Payload structure. */
133 SilcArgumentPayload silc_argument_payload_parse(SilcBuffer buffer,
136 SilcArgumentPayload new;
137 unsigned short payload_len = 0;
138 unsigned char arg_num = 0;
139 unsigned int arg_type = 0;
140 unsigned int pull_len = 0;
143 SILC_LOG_DEBUG(("Parsing argument payload"));
145 new = silc_calloc(1, sizeof(*new));
146 new->argv = silc_calloc(argc, sizeof(unsigned char *));
147 new->argv_lens = silc_calloc(argc, sizeof(unsigned int));
148 new->argv_types = silc_calloc(argc, sizeof(unsigned int));
152 for (i = 0; i < argc; i++) {
153 silc_buffer_unformat(buffer,
154 SILC_STR_UI_SHORT(&payload_len),
155 SILC_STR_UI_CHAR(&arg_type),
158 new->argv_lens[i] = payload_len;
159 new->argv_types[i] = arg_type;
161 if (payload_len > buffer->len)
164 /* Get argument data */
165 silc_buffer_pull(buffer, 3);
166 silc_buffer_unformat(buffer,
167 SILC_STR_UI_XNSTRING_ALLOC(&new->argv[i],
171 silc_buffer_pull(buffer, payload_len);
172 pull_len += 3 + payload_len;
175 if (buffer->len != 0)
181 silc_buffer_push(buffer, pull_len);
189 for (k = 0; k < i; k++)
190 silc_free(new->argv[k]);
193 silc_free(new->argv);
194 silc_free(new->argv_lens);
195 silc_free(new->argv_types);
203 /* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
205 SilcBuffer silc_argument_payload_encode(unsigned int argc,
206 unsigned char **argv,
207 unsigned int *argv_lens,
208 unsigned int *argv_types)
214 SILC_LOG_DEBUG(("Encoding Argument payload"));
217 for (i = 0; i < argc; i++)
218 len += 3 + argv_lens[i];
220 buffer = silc_buffer_alloc(len);
221 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
224 for (i = 0; i < argc; i++) {
225 silc_buffer_format(buffer,
226 SILC_STR_UI_SHORT(argv_lens[i]),
227 SILC_STR_UI_CHAR(argv_types[i]),
228 SILC_STR_UI_XNSTRING(argv[i], argv_lens[i]),
230 silc_buffer_pull(buffer, 3 + argv_lens[i]);
233 silc_buffer_push(buffer, len);
239 /* Encodes Argument payload with variable argument list. The arguments
240 must be: unsigned int, unsigned char *, unsigned int, ... One
241 {unsigned int, unsigned char * and unsigned int} forms one argument,
242 thus `argc' in case when sending one {unsigned int, unsigned char *
243 and unsigned int} equals one (1) and when sending two of those it
244 equals two (2), and so on. This has to be preserved or bad things
245 will happen. The variable arguments is: {type, data, data_len}. */
247 SilcBuffer silc_command_encode_payload_va(unsigned int argc, ...)
250 unsigned char **argv;
251 unsigned int *argv_lens = NULL, *argv_types = NULL;
260 argv = silc_calloc(argc, sizeof(unsigned char *));
261 argv_lens = silc_calloc(argc, sizeof(unsigned int));
262 argv_types = silc_calloc(argc, sizeof(unsigned int));
264 for (i = 0; i < argc; i++) {
265 x_type = va_arg(ap, unsigned int);
266 x = va_arg(ap, unsigned char *);
267 x_len = va_arg(ap, unsigned int);
269 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
270 memcpy(argv[i], x, x_len);
271 argv_lens[i] = x_len;
272 argv_types[i] = x_type;
275 buffer = silc_argument_payload_encode(argc, argv,
276 argv_lens, argv_types);
278 for (i = 0; i < argc; i++)
281 silc_free(argv_lens);
282 silc_free(argv_types);
288 /* Free's Command Payload */
290 void silc_argument_payload_free(SilcArgumentPayload payload)
295 for (i = 0; i < payload->argc; i++)
296 silc_free(payload->argv[i]);
298 silc_free(payload->argv);
303 /* Returns number of arguments in payload */
305 unsigned int silc_argument_get_arg_num(SilcArgumentPayload payload)
307 return payload->argc;
310 /* Returns first argument from payload. */
312 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
313 unsigned int *ret_len)
318 *ret_len = payload->argv_lens[payload->pos];
320 return payload->argv[payload->pos++];
323 /* Returns next argument from payload or NULL if no more arguments. */
325 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
326 unsigned int *ret_len)
328 if (payload->pos >= payload->argc)
332 *ret_len = payload->argv_lens[payload->pos];
334 return payload->argv[payload->pos++];
337 /* Returns argument which type is `type'. */
339 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
341 unsigned int *ret_len)
345 for (i = 0; i < payload->argc; i++)
346 if (payload->argv_types[i] == type)
349 if (i >= payload->argc)
353 *ret_len = payload->argv_lens[i];
355 return payload->argv[i];