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.
23 * Revision 1.3 2000/07/06 07:11:06 priikone
24 * Removed status paylaod encoding functions -> not needed anymore.
25 * Added encode_reply_payload_va to encode reply packets only.
26 * Normal encode_payload_va accepts now argument type as variable
29 * Revision 1.2 2000/07/05 06:06:35 priikone
30 * Global cosmetic change.
32 * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
33 * Imported from internal CVS/Added Log headers.
38 #include "silcincludes.h"
39 #include "silccommand.h"
41 /* Command Payload structure. Contents of this structure is parsed
43 struct SilcCommandPayloadStruct {
47 unsigned int *argv_lens;
48 unsigned int *argv_types;
52 /* Length of the command payload */
53 #define SILC_COMMAND_PAYLOAD_LEN 4
55 /* Parses command payload returning new command payload structure */
57 SilcCommandPayload silc_command_parse_payload(SilcBuffer buffer)
59 SilcCommandPayload new;
60 unsigned short payload_len = 0;
61 unsigned char args_num = 0;
62 unsigned char arg_num = 0;
63 unsigned int arg_type = 0;
64 unsigned int pull_len = 0;
67 SILC_LOG_DEBUG(("Parsing command payload"));
69 new = silc_calloc(1, sizeof(*new));
71 /* Parse the Command Payload */
72 silc_buffer_unformat(buffer,
73 SILC_STR_UI_CHAR(&new->cmd),
74 SILC_STR_UI_CHAR(&args_num),
75 SILC_STR_UI_SHORT(&payload_len),
78 if (payload_len != buffer->len) {
79 SILC_LOG_ERROR(("Incorrect command payload in packet, packet dropped"));
86 if (args_num && payload_len) {
88 new->argv = silc_calloc(args_num, sizeof(unsigned char *));
89 new->argv_lens = silc_calloc(args_num, sizeof(unsigned int));
90 new->argv_types = silc_calloc(args_num, sizeof(unsigned int));
92 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
93 pull_len += SILC_COMMAND_PAYLOAD_LEN;
95 /* Parse Command Argument Payloads */
98 silc_buffer_unformat(buffer,
99 SILC_STR_UI_CHAR(&arg_num),
100 SILC_STR_UI_CHAR(&arg_type),
101 SILC_STR_UI_SHORT(&payload_len),
104 /* Check that argument number is correct */
105 if (arg_num != i + 1)
108 new->argv_lens[i] = payload_len;
109 new->argv_types[i] = arg_type;
111 /* Get argument data */
112 silc_buffer_pull(buffer, 4);
113 silc_buffer_unformat(buffer,
114 SILC_STR_UI_XNSTRING_ALLOC(&new->argv[i],
117 silc_buffer_pull(buffer, payload_len);
118 pull_len += 4 + payload_len;
126 /* Check the number of arguments */
127 if (arg_num != args_num)
134 silc_buffer_push(buffer, pull_len);
142 for (k = 0; k < i; k++)
143 silc_free(new->argv[k]);
146 silc_free(new->argv);
147 silc_free(new->argv_lens);
148 silc_free(new->argv_types);
156 /* Encodes Command Payload returning it to SilcBuffer. */
158 SilcBuffer silc_command_encode_payload(SilcCommand cmd,
160 unsigned char **argv,
161 unsigned int *argv_lens,
162 unsigned int *argv_types)
168 SILC_LOG_DEBUG(("Encoding command payload"));
171 for (i = 0; i < argc; i++)
172 len += 1 + 1 + 2 + argv_lens[i];
174 buffer = silc_buffer_alloc(len);
175 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
177 /* Create Command payload */
178 silc_buffer_format(buffer,
179 SILC_STR_UI_CHAR(cmd),
180 SILC_STR_UI_CHAR(argc),
181 SILC_STR_UI_SHORT(len),
186 silc_buffer_pull(buffer, 4);
188 for (i = 0; i < argc; i++) {
189 silc_buffer_format(buffer,
190 SILC_STR_UI_CHAR(i + 1),
191 SILC_STR_UI_CHAR(argv_types[i]),
192 SILC_STR_UI_SHORT(argv_lens[i]),
193 SILC_STR_UI_XNSTRING(argv[i], argv_lens[i]),
195 silc_buffer_pull(buffer, 4 + argv_lens[i]);
198 silc_buffer_push(buffer, len);
204 /* Encodes Command payload with variable argument list. The arguments
205 must be: unsigned int, unsigned char *, unsigned int, ... One
206 {unsigned int, unsigned char * and unsigned int} forms one argument,
207 thus `argc' in case when sending one {unsigned int, unsigned char *
208 and unsigned int} equals one (1) and when sending two of those it
209 equals two (2), and so on. This has to be preserved or bad things
210 will happen. The variable arguments is: {type, data, data_len}. */
212 SilcBuffer silc_command_encode_payload_va(SilcCommand cmd,
213 unsigned int argc, ...)
216 unsigned char **argv;
217 unsigned int *argv_lens = NULL, *argv_types = NULL;
226 argv = silc_calloc(argc, sizeof(unsigned char *));
227 argv_lens = silc_calloc(argc, sizeof(unsigned int));
228 argv_types = silc_calloc(argc, sizeof(unsigned int));
230 for (i = 0; i < argc; i++) {
231 x_type = va_arg(ap, unsigned int);
232 x = va_arg(ap, unsigned char *);
233 x_len = va_arg(ap, unsigned int);
235 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
236 memcpy(argv[i], x, x_len);
237 argv_lens[i] = x_len;
238 argv_types[i] = x_type;
241 buffer = silc_command_encode_payload(cmd, argc, argv,
242 argv_lens, argv_types);
244 for (i = 0; i < argc; i++)
247 silc_free(argv_lens);
248 silc_free(argv_types);
253 /* Same as above except that this is used to encode strictly command
254 reply packets. The command status message to be returned is sent as
255 extra argument to this function. The `argc' must not count `status'
259 silc_command_encode_reply_payload_va(SilcCommand cmd,
260 SilcCommandStatus status,
261 unsigned int argc, ...)
264 unsigned char **argv;
265 unsigned int *argv_lens = NULL, *argv_types = NULL;
266 unsigned char status_data[2];
276 argv = silc_calloc(argc, sizeof(unsigned char *));
277 argv_lens = silc_calloc(argc, sizeof(unsigned int));
278 argv_types = silc_calloc(argc, sizeof(unsigned int));
280 SILC_PUT16_MSB(status, status_data);
281 argv[0] = silc_calloc(sizeof(status_data) + 1, sizeof(unsigned char));
282 memcpy(argv[0], status_data, sizeof(status_data));
283 argv_lens[0] = sizeof(status_data);
286 for (i = 1; i < argc; i++) {
287 x_type = va_arg(ap, unsigned int);
288 x = va_arg(ap, unsigned char *);
289 x_len = va_arg(ap, unsigned int);
291 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
292 memcpy(argv[i], x, x_len);
293 argv_lens[i] = x_len;
294 argv_types[i] = x_type;
297 buffer = silc_command_encode_payload(cmd, argc, argv,
298 argv_lens, argv_types);
300 for (i = 0; i < argc; i++)
303 silc_free(argv_lens);
304 silc_free(argv_types);
309 /* Free's Command Payload */
311 void silc_command_free_payload(SilcCommandPayload payload)
316 for (i = 0; i < payload->argc; i++)
317 silc_free(payload->argv[i]);
319 silc_free(payload->argv);
324 /* Returns the command type in payload */
326 SilcCommand silc_command_get(SilcCommandPayload payload)
331 /* Returns number of arguments in payload */
333 unsigned int silc_command_get_arg_num(SilcCommandPayload payload)
335 return payload->argc;
338 /* Returns first argument from payload. */
340 unsigned char *silc_command_get_first_arg(SilcCommandPayload payload,
341 unsigned int *ret_len)
346 *ret_len = payload->argv_lens[payload->pos];
348 return payload->argv[payload->pos++];
351 /* Returns next argument from payload or NULL if no more arguments. */
353 unsigned char *silc_command_get_next_arg(SilcCommandPayload payload,
354 unsigned int *ret_len)
356 if (payload->pos >= payload->argc)
360 *ret_len = payload->argv_lens[payload->pos];
362 return payload->argv[payload->pos++];
365 /* Returns argument which type is `type'. */
367 unsigned char *silc_command_get_arg_type(SilcCommandPayload payload,
369 unsigned int *ret_len)
373 for (i = 0; i < payload->argc; i++)
374 if (payload->argv_types[i] == type)
377 if (i >= payload->argc)
381 *ret_len = payload->argv_lens[i];
383 return payload->argv[i];