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.2 2000/07/05 06:06:35 priikone
24 * Global cosmetic change.
26 * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
27 * Imported from internal CVS/Added Log headers.
32 #include "silcincludes.h"
33 #include "silccommand.h"
35 /* Command Payload structure. Contents of this structure is parsed
37 struct SilcCommandPayloadStruct {
41 unsigned int *argv_lens;
42 unsigned int *argv_types;
46 /* Length of the command payload */
47 #define SILC_COMMAND_PAYLOAD_LEN 4
49 /* Parses command payload returning new command payload structure */
51 SilcCommandPayload silc_command_parse_payload(SilcBuffer buffer)
53 SilcCommandPayload new;
54 unsigned short payload_len = 0;
55 unsigned char args_num = 0;
56 unsigned char arg_num = 0;
57 unsigned int arg_type = 0;
58 unsigned int pull_len = 0;
61 SILC_LOG_DEBUG(("Parsing command payload"));
63 new = silc_calloc(1, sizeof(*new));
65 /* Parse the Command Payload */
66 silc_buffer_unformat(buffer,
67 SILC_STR_UI_CHAR(&new->cmd),
68 SILC_STR_UI_CHAR(&args_num),
69 SILC_STR_UI_SHORT(&payload_len),
72 if (payload_len != buffer->len) {
73 SILC_LOG_ERROR(("Incorrect command payload in packet, packet dropped"));
80 if (args_num && payload_len) {
82 new->argv = silc_calloc(args_num, sizeof(unsigned char *));
83 new->argv_lens = silc_calloc(args_num, sizeof(unsigned int));
84 new->argv_types = silc_calloc(args_num, sizeof(unsigned int));
86 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
87 pull_len += SILC_COMMAND_PAYLOAD_LEN;
89 /* Parse Command Argument Payloads */
92 silc_buffer_unformat(buffer,
93 SILC_STR_UI_CHAR(&arg_num),
94 SILC_STR_UI_CHAR(&arg_type),
95 SILC_STR_UI_SHORT(&payload_len),
98 /* Check that argument number is correct */
102 new->argv_lens[i] = payload_len;
103 new->argv_types[i] = arg_type;
105 /* Get argument data */
106 silc_buffer_pull(buffer, 4);
107 silc_buffer_unformat(buffer,
108 SILC_STR_UI_XNSTRING_ALLOC(&new->argv[i],
111 silc_buffer_pull(buffer, payload_len);
112 pull_len += 4 + payload_len;
120 /* Check the number of arguments */
121 if (arg_num != args_num)
128 silc_buffer_push(buffer, pull_len);
136 for (k = 0; k < i; k++)
137 silc_free(new->argv[k]);
140 silc_free(new->argv);
141 silc_free(new->argv_lens);
142 silc_free(new->argv_types);
150 /* Encodes Command Payload returning it to SilcBuffer. */
152 SilcBuffer silc_command_encode_payload(SilcCommand cmd,
154 unsigned char **argv,
155 unsigned int *argv_lens,
156 unsigned int *argv_types)
162 SILC_LOG_DEBUG(("Encoding command payload"));
165 for (i = 0; i < argc; i++)
166 len += 1 + 1 + 2 + argv_lens[i];
168 buffer = silc_buffer_alloc(len);
169 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
171 /* Create Command payload */
172 silc_buffer_format(buffer,
173 SILC_STR_UI_CHAR(cmd),
174 SILC_STR_UI_CHAR(argc),
175 SILC_STR_UI_SHORT(len),
180 silc_buffer_pull(buffer, 4);
182 for (i = 0; i < argc; i++) {
183 silc_buffer_format(buffer,
184 SILC_STR_UI_CHAR(i + 1),
185 SILC_STR_UI_CHAR(argv_types[i]),
186 SILC_STR_UI_SHORT(argv_lens[i]),
187 SILC_STR_UI_XNSTRING(argv[i], argv_lens[i]),
189 silc_buffer_pull(buffer, 4 + argv_lens[i]);
192 silc_buffer_push(buffer, len);
198 /* Encodes Command payload with variable argument list. The arguments
199 must be: unsigned char *, unsigned int, ... One unsigned char *
200 and unsigned int forms one argument, hence `argc' in case when
201 sending one unsigned char * and unsigned int equals one (1) and
202 when sending two of those it equals two (2), and so on. This has
203 to be preserved or bad things will happen. */
205 SilcBuffer silc_command_encode_payload_va(SilcCommand cmd,
206 unsigned int argc, ...)
209 unsigned char **argv;
210 unsigned int *argv_lens = NULL, *argv_types = NULL;
218 argv = silc_calloc(argc, sizeof(unsigned char *));
219 argv_lens = silc_calloc(argc, sizeof(unsigned int));
220 argv_types = silc_calloc(argc, sizeof(unsigned int));
222 for (i = 0; i < argc; i++) {
223 x = va_arg(ap, unsigned char *);
224 x_len = va_arg(ap, unsigned int);
226 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
227 memcpy(argv[i], x, x_len);
228 argv_lens[i] = x_len;
229 argv_types[i] = i + 1;
232 buffer = silc_command_encode_payload(cmd, argc, argv,
233 argv_lens, argv_types);
235 for (i = 0; i < argc; i++)
238 silc_free(argv_lens);
239 silc_free(argv_types);
244 /* Free's Command Payload */
246 void silc_command_free_payload(SilcCommandPayload payload)
251 for (i = 0; i < payload->argc; i++)
252 silc_free(payload->argv[i]);
254 silc_free(payload->argv);
259 /* Returns the command type in payload */
261 SilcCommand silc_command_get(SilcCommandPayload payload)
266 /* Returns number of arguments in payload */
268 unsigned int silc_command_get_arg_num(SilcCommandPayload payload)
270 return payload->argc;
273 /* Returns first argument from payload. */
275 unsigned char *silc_command_get_first_arg(SilcCommandPayload payload,
276 unsigned int *ret_len)
281 *ret_len = payload->argv_lens[payload->pos];
283 return payload->argv[payload->pos++];
286 /* Returns next argument from payload or NULL if no more arguments. */
288 unsigned char *silc_command_get_next_arg(SilcCommandPayload payload,
289 unsigned int *ret_len)
291 if (payload->pos >= payload->argc)
295 *ret_len = payload->argv_lens[payload->pos];
297 return payload->argv[payload->pos++];
300 /* Returns argument which type is `type'. */
302 unsigned char *silc_command_get_arg_type(SilcCommandPayload payload,
304 unsigned int *ret_len)
308 for (i = 0; i < payload->argc; i++)
309 if (payload->argv_types[i] == type)
312 if (i >= payload->argc)
316 *ret_len = payload->argv_lens[i];
318 return payload->argv[i];
321 /* Encodes command status payload. Status payload is sent as one reply
322 argument. The returned payload still has to be saved into the
323 Command Argument payload. */
325 SilcBuffer silc_command_encode_status_payload(SilcCommandStatus status,
331 sp = silc_buffer_alloc(len + 2);
332 silc_buffer_pull_tail(sp, SILC_BUFFER_END(sp));
333 silc_buffer_format(sp,
334 SILC_STR_UI_SHORT(status),
335 SILC_STR_UI_XNSTRING(data, len),