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.1 2000/06/27 11:36:55 priikone
29 #include "silcincludes.h"
30 #include "silccommand.h"
32 /* Command Payload structure. Contents of this structure is parsed
34 struct SilcCommandPayloadStruct {
38 unsigned int *argv_lens;
39 unsigned int *argv_types;
43 /* Length of the command payload */
44 #define SILC_COMMAND_PAYLOAD_LEN 4
46 /* Parses command payload returning new command payload structure */
48 SilcCommandPayload silc_command_parse_payload(SilcBuffer buffer)
50 SilcCommandPayload new;
51 unsigned short payload_len = 0;
52 unsigned char args_num = 0;
53 unsigned char arg_num = 0;
54 unsigned int arg_type = 0;
55 unsigned int pull_len = 0;
58 SILC_LOG_DEBUG(("Parsing command payload"));
60 new = silc_calloc(1, sizeof(*new));
62 SILC_LOG_ERROR(("Could not allocate new command payload"));
66 /* Parse the Command Payload */
67 silc_buffer_unformat(buffer,
68 SILC_STR_UI_CHAR(&new->cmd),
69 SILC_STR_UI_CHAR(&args_num),
70 SILC_STR_UI_SHORT(&payload_len),
73 if (payload_len != buffer->len) {
74 SILC_LOG_ERROR(("Incorrect command payload in packet, packet dropped"));
81 if (args_num && payload_len) {
83 new->argv = silc_calloc(args_num, sizeof(unsigned char *));
84 new->argv_lens = silc_calloc(args_num, sizeof(unsigned int));
85 new->argv_types = silc_calloc(args_num, sizeof(unsigned int));
87 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
88 pull_len += SILC_COMMAND_PAYLOAD_LEN;
90 /* Parse Command Argument Payloads */
93 silc_buffer_unformat(buffer,
94 SILC_STR_UI_CHAR(&arg_num),
95 SILC_STR_UI_CHAR(&arg_type),
96 SILC_STR_UI_SHORT(&payload_len),
99 /* Check that argument number is correct */
100 if (arg_num != i + 1)
103 new->argv_lens[i] = payload_len;
104 new->argv_types[i] = arg_type;
106 /* Get argument data */
107 silc_buffer_pull(buffer, 4);
108 silc_buffer_unformat(buffer,
109 SILC_STR_UI_XNSTRING_ALLOC(&new->argv[i],
112 silc_buffer_pull(buffer, payload_len);
113 pull_len += 4 + payload_len;
121 /* Check the number of arguments */
122 if (arg_num != args_num)
129 silc_buffer_push(buffer, pull_len);
137 for (k = 0; k < i; k++)
138 silc_free(new->argv[k]);
141 silc_free(new->argv);
142 silc_free(new->argv_lens);
143 silc_free(new->argv_types);
151 /* Encodes Command Payload returning it to SilcBuffer. */
153 SilcBuffer silc_command_encode_payload(SilcCommand cmd,
155 unsigned char **argv,
156 unsigned int *argv_lens,
157 unsigned int *argv_types)
163 SILC_LOG_DEBUG(("Encoding command payload"));
166 for (i = 0; i < argc; i++)
167 len += 1 + 1 + 2 + argv_lens[i];
169 buffer = silc_buffer_alloc(len);
170 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
172 /* Create Command payload */
173 silc_buffer_format(buffer,
174 SILC_STR_UI_CHAR(cmd),
175 SILC_STR_UI_CHAR(argc),
176 SILC_STR_UI_SHORT(len),
181 silc_buffer_pull(buffer, 4);
183 for (i = 0; i < argc; i++) {
184 silc_buffer_format(buffer,
185 SILC_STR_UI_CHAR(i + 1),
186 SILC_STR_UI_CHAR(argv_types[i]),
187 SILC_STR_UI_SHORT(argv_lens[i]),
188 SILC_STR_UI_XNSTRING(argv[i], argv_lens[i]),
190 silc_buffer_pull(buffer, 4 + argv_lens[i]);
193 silc_buffer_push(buffer, len);
199 /* Encodes Command payload with variable argument list. The arguments
200 must be: unsigned char *, unsigned int, ... One unsigned char *
201 and unsigned int forms one argument, hence `argc' in case when
202 sending one unsigned char * and unsigned int equals one (1) and
203 when sending two of those it equals two (2), and so on. This has
204 to be preserved or bad things will happen. */
206 SilcBuffer silc_command_encode_payload_va(SilcCommand cmd,
207 unsigned int argc, ...)
210 unsigned char **argv;
211 unsigned int *argv_lens = NULL, *argv_types = NULL;
219 argv = silc_calloc(argc, sizeof(unsigned char *));
220 argv_lens = silc_calloc(argc, sizeof(unsigned int));
221 argv_types = silc_calloc(argc, sizeof(unsigned int));
223 for (i = 0; i < argc; i++) {
224 x = va_arg(ap, unsigned char *);
225 x_len = va_arg(ap, unsigned int);
227 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
228 memcpy(argv[i], x, x_len);
229 argv_lens[i] = x_len;
230 argv_types[i] = i + 1;
233 buffer = silc_command_encode_payload(cmd, argc, argv,
234 argv_lens, argv_types);
236 for (i = 0; i < argc; i++)
239 silc_free(argv_lens);
240 silc_free(argv_types);
245 /* Free's Command Payload */
247 void silc_command_free_payload(SilcCommandPayload payload)
252 for (i = 0; i < payload->argc; i++)
253 silc_free(payload->argv[i]);
255 silc_free(payload->argv);
260 /* Returns the command type in payload */
262 SilcCommand silc_command_get(SilcCommandPayload payload)
267 /* Returns number of arguments in payload */
269 unsigned int silc_command_get_arg_num(SilcCommandPayload payload)
271 return payload->argc;
274 /* Returns first argument from payload. */
276 unsigned char *silc_command_get_first_arg(SilcCommandPayload payload,
277 unsigned int *ret_len)
282 *ret_len = payload->argv_lens[payload->pos];
284 return payload->argv[payload->pos++];
287 /* Returns next argument from payload or NULL if no more arguments. */
289 unsigned char *silc_command_get_next_arg(SilcCommandPayload payload,
290 unsigned int *ret_len)
292 if (payload->pos >= payload->argc)
296 *ret_len = payload->argv_lens[payload->pos];
298 return payload->argv[payload->pos++];
301 /* Returns argument which type is `type'. */
303 unsigned char *silc_command_get_arg_type(SilcCommandPayload payload,
305 unsigned int *ret_len)
309 for (i = 0; i < payload->argc; i++)
310 if (payload->argv_types[i] == type)
313 if (i >= payload->argc)
317 *ret_len = payload->argv_lens[i];
319 return payload->argv[i];
322 /* Encodes command status payload. Status payload is sent as one reply
323 argument. The returned payload still has to be saved into the
324 Command Argument payload. */
326 SilcBuffer silc_command_encode_status_payload(SilcCommandStatus status,
332 sp = silc_buffer_alloc(len + 2);
333 silc_buffer_pull_tail(sp, SILC_BUFFER_END(sp));
334 silc_buffer_format(sp,
335 SILC_STR_UI_SHORT(status),
336 SILC_STR_UI_XNSTRING(data, len),