5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2001 - 2006 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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
19 /* Implementation of Argument Payload routines */
23 #include "silcargument.h"
25 /******************************************************************************
29 ******************************************************************************/
31 struct SilcArgumentPayloadStruct {
34 SilcUInt32 *argv_lens;
35 SilcUInt32 *argv_types;
39 /* Parses arguments and returns them into Argument Payload structure. */
41 SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
42 SilcUInt32 payload_len,
45 SilcBufferStruct buffer;
46 SilcArgumentPayload newp;
48 unsigned char arg_num = 0;
49 unsigned char arg_type = 0;
50 SilcUInt32 pull_len = 0;
53 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
54 newp = silc_calloc(1, sizeof(*newp));
57 newp->argv = silc_calloc(argc, sizeof(unsigned char *));
60 newp->argv_lens = silc_calloc(argc, sizeof(SilcUInt32));
63 newp->argv_types = silc_calloc(argc, sizeof(SilcUInt32));
64 if (!newp->argv_types)
69 for (i = 0; i < argc; i++) {
70 ret = silc_buffer_unformat(&buffer,
71 SILC_STR_UI_SHORT(&p_len),
72 SILC_STR_UI_CHAR(&arg_type),
74 if (ret == -1 || p_len > silc_buffer_len(&buffer) - 3)
77 newp->argv_lens[i] = p_len;
78 newp->argv_types[i] = arg_type;
80 /* Get argument data */
81 silc_buffer_pull(&buffer, 3);
82 ret = silc_buffer_unformat(&buffer,
83 SILC_STR_UI_XNSTRING_ALLOC(&newp->argv[i],
89 silc_buffer_pull(&buffer, p_len);
90 pull_len += 3 + p_len;
93 if (silc_buffer_len(&buffer) != 0) {
94 SILC_LOG_DEBUG(("Malformed argument payload"));
101 silc_buffer_push(&buffer, pull_len);
106 SILC_LOG_DEBUG(("Error parsing argument payload"));
108 for (ret = 0; ret < i; ret++)
109 silc_free(newp->argv[ret]);
111 silc_free(newp->argv);
112 silc_free(newp->argv_lens);
113 silc_free(newp->argv_types);
119 /* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
121 SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
122 unsigned char **argv,
123 SilcUInt32 *argv_lens,
124 SilcUInt32 *argv_types)
131 for (i = 0; i < argc; i++)
132 len += 3 + (SilcUInt16)argv_lens[i];
134 buffer = silc_buffer_alloc_size(len);
139 for (i = 0; i < argc; i++) {
140 silc_buffer_format(buffer,
141 SILC_STR_UI_SHORT(argv_lens[i]),
142 SILC_STR_UI_CHAR(argv_types[i]),
143 SILC_STR_UI_XNSTRING(argv[i], (SilcUInt16)argv_lens[i]),
145 silc_buffer_pull(buffer, 3 + (SilcUInt16)argv_lens[i]);
148 silc_buffer_push(buffer, len);
153 /* Encode one argument to buffer */
155 SilcBuffer silc_argument_payload_encode_one(SilcBuffer args,
160 SilcBuffer buffer = args;
163 len = 3 + (SilcUInt16)arg_len;
164 buffer = silc_buffer_realloc(buffer,
165 (buffer ? silc_buffer_truelen(buffer) +
169 silc_buffer_pull(buffer, silc_buffer_len(buffer));
170 silc_buffer_pull_tail(buffer, len);
171 silc_buffer_format(buffer,
172 SILC_STR_UI_SHORT(arg_len),
173 SILC_STR_UI_CHAR(arg_type),
174 SILC_STR_UI_XNSTRING(arg, (SilcUInt16)arg_len),
176 silc_buffer_push(buffer, buffer->data - buffer->head);
181 /* Same as above but encode the buffer from SilcArgumentPayload structure
182 instead of raw data. */
184 SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
191 for (i = 0; i < payload->argc; i++)
192 len += 3 + payload->argv_lens[i];
194 buffer = silc_buffer_alloc_size(len);
199 for (i = 0; i < payload->argc; i++) {
200 silc_buffer_format(buffer,
201 SILC_STR_UI_SHORT(payload->argv_lens[i]),
202 SILC_STR_UI_CHAR(payload->argv_types[i]),
203 SILC_STR_UI_XNSTRING(payload->argv[i],
204 payload->argv_lens[i]),
206 silc_buffer_pull(buffer, 3 + payload->argv_lens[i]);
209 silc_buffer_push(buffer, len);
214 /* Frees Argument Payload */
216 void silc_argument_payload_free(SilcArgumentPayload payload)
221 for (i = 0; i < payload->argc; i++)
222 silc_free(payload->argv[i]);
224 silc_free(payload->argv);
225 silc_free(payload->argv_lens);
226 silc_free(payload->argv_types);
231 /* Returns number of arguments in payload */
233 SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload)
235 return payload ? payload->argc : 0;
238 /* Returns first argument from payload. */
240 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
250 *type = payload->argv_types[payload->pos];
252 *ret_len = payload->argv_lens[payload->pos];
254 return payload->argv[payload->pos++];
257 /* Returns next argument from payload or NULL if no more arguments. */
259 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
266 if (payload->pos >= payload->argc)
270 *type = payload->argv_types[payload->pos];
272 *ret_len = payload->argv_lens[payload->pos];
274 return payload->argv[payload->pos++];
277 /* Returns argument which type is `type'. */
279 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
288 for (i = 0; i < payload->argc; i++)
289 if (payload->argv_types[i] == type)
292 if (i >= payload->argc)
296 *ret_len = payload->argv_lens[i];
298 return payload->argv[i];