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.
22 #include "silcincludes.h"
23 #include "silccommand.h"
25 /******************************************************************************
29 ******************************************************************************/
31 /* Command Payload structure. Contents of this structure is parsed
33 struct SilcCommandPayloadStruct {
36 SilcArgumentPayload args;
39 /* Length of the command payload */
40 #define SILC_COMMAND_PAYLOAD_LEN 6
42 /* Parses command payload returning new command payload structure */
44 SilcCommandPayload silc_command_payload_parse(SilcBuffer buffer)
46 SilcCommandPayload new;
47 unsigned char args_num;
48 unsigned short payload_len;
50 SILC_LOG_DEBUG(("Parsing command payload"));
52 new = silc_calloc(1, sizeof(*new));
54 /* Parse the Command Payload */
55 silc_buffer_unformat(buffer,
56 SILC_STR_UI_SHORT(&payload_len),
57 SILC_STR_UI_CHAR(&new->cmd),
58 SILC_STR_UI_CHAR(&args_num),
59 SILC_STR_UI_SHORT(&new->ident),
62 if (payload_len != buffer->len) {
63 SILC_LOG_ERROR(("Incorrect command payload in packet, packet dropped"));
73 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
74 new->args = silc_argument_payload_parse(buffer, args_num);
79 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
84 /* Encodes Command Payload returning it to SilcBuffer. */
86 SilcBuffer silc_command_payload_encode(SilcCommand cmd,
89 unsigned int *argv_lens,
90 unsigned int *argv_types,
94 SilcBuffer args = NULL;
97 SILC_LOG_DEBUG(("Encoding command payload"));
100 args = silc_argument_payload_encode(argc, argv, argv_lens, argv_types);
104 len += SILC_COMMAND_PAYLOAD_LEN;
105 buffer = silc_buffer_alloc(len);
106 silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
108 /* Create Command payload */
109 silc_buffer_format(buffer,
110 SILC_STR_UI_SHORT(len),
111 SILC_STR_UI_CHAR(cmd),
112 SILC_STR_UI_CHAR(argc),
113 SILC_STR_UI_SHORT(ident),
118 silc_buffer_pull(buffer, SILC_COMMAND_PAYLOAD_LEN);
119 silc_buffer_format(buffer,
120 SILC_STR_UI_XNSTRING(args->data, args->len),
122 silc_buffer_push(buffer, SILC_COMMAND_PAYLOAD_LEN);
129 /* Encodes Command payload with variable argument list. The arguments
130 must be: unsigned int, unsigned char *, unsigned int, ... One
131 {unsigned int, unsigned char * and unsigned int} forms one argument,
132 thus `argc' in case when sending one {unsigned int, unsigned char *
133 and unsigned int} equals one (1) and when sending two of those it
134 equals two (2), and so on. This has to be preserved or bad things
135 will happen. The variable arguments is: {type, data, data_len}. */
137 SilcBuffer silc_command_payload_encode_va(SilcCommand cmd,
138 unsigned short ident,
139 unsigned int argc, ...)
142 unsigned char **argv;
143 unsigned int *argv_lens = NULL, *argv_types = NULL;
152 argv = silc_calloc(argc, sizeof(unsigned char *));
153 argv_lens = silc_calloc(argc, sizeof(unsigned int));
154 argv_types = silc_calloc(argc, sizeof(unsigned int));
156 for (i = 0; i < argc; i++) {
157 x_type = va_arg(ap, unsigned int);
158 x = va_arg(ap, unsigned char *);
159 x_len = va_arg(ap, unsigned int);
161 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
162 memcpy(argv[i], x, x_len);
163 argv_lens[i] = x_len;
164 argv_types[i] = x_type;
167 buffer = silc_command_payload_encode(cmd, argc, argv,
168 argv_lens, argv_types, ident);
170 for (i = 0; i < argc; i++)
173 silc_free(argv_lens);
174 silc_free(argv_types);
179 /* Same as above but with va_list. */
181 SilcBuffer silc_command_payload_encode_vap(SilcCommand cmd,
182 unsigned short ident,
183 unsigned int argc, va_list ap)
185 unsigned char **argv;
186 unsigned int *argv_lens = NULL, *argv_types = NULL;
193 argv = silc_calloc(argc, sizeof(unsigned char *));
194 argv_lens = silc_calloc(argc, sizeof(unsigned int));
195 argv_types = silc_calloc(argc, sizeof(unsigned int));
197 for (i = 0; i < argc; i++) {
198 x_type = va_arg(ap, unsigned int);
199 x = va_arg(ap, unsigned char *);
200 x_len = va_arg(ap, unsigned int);
202 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
203 memcpy(argv[i], x, x_len);
204 argv_lens[i] = x_len;
205 argv_types[i] = x_type;
208 buffer = silc_command_payload_encode(cmd, argc, argv,
209 argv_lens, argv_types, ident);
211 for (i = 0; i < argc; i++)
214 silc_free(argv_lens);
215 silc_free(argv_types);
220 /* Same as above except that this is used to encode strictly command
221 reply packets. The command status message to be returned is sent as
222 extra argument to this function. The `argc' must not count `status'
226 silc_command_reply_payload_encode_va(SilcCommand cmd,
227 SilcCommandStatus status,
228 unsigned short ident,
229 unsigned int argc, ...)
232 unsigned char **argv;
233 unsigned int *argv_lens = NULL, *argv_types = NULL;
234 unsigned char status_data[2];
244 argv = silc_calloc(argc, sizeof(unsigned char *));
245 argv_lens = silc_calloc(argc, sizeof(unsigned int));
246 argv_types = silc_calloc(argc, sizeof(unsigned int));
248 SILC_PUT16_MSB(status, status_data);
249 argv[0] = silc_calloc(sizeof(status_data) + 1, sizeof(unsigned char));
250 memcpy(argv[0], status_data, sizeof(status_data));
251 argv_lens[0] = sizeof(status_data);
254 for (i = 1; i < argc; i++) {
255 x_type = va_arg(ap, unsigned int);
256 x = va_arg(ap, unsigned char *);
257 x_len = va_arg(ap, unsigned int);
259 argv[i] = silc_calloc(x_len + 1, sizeof(unsigned char));
260 memcpy(argv[i], x, x_len);
261 argv_lens[i] = x_len;
262 argv_types[i] = x_type;
265 buffer = silc_command_payload_encode(cmd, argc, argv,
266 argv_lens, argv_types, ident);
268 for (i = 0; i < argc; i++)
271 silc_free(argv_lens);
272 silc_free(argv_types);
277 /* Free's Command Payload */
279 void silc_command_free_payload(SilcCommandPayload payload)
282 silc_argument_payload_free(payload->args);
287 /* Returns command */
289 SilcCommand silc_command_get(SilcCommandPayload payload)
294 /* Retuns arguments payload */
296 SilcArgumentPayload silc_command_get_args(SilcCommandPayload payload)
298 return payload->args;
301 /* Returns identifier */
303 unsigned short silc_command_get_ident(SilcCommandPayload payload)
305 return payload->ident;