1 /*
2
3 silcnotify.c
4
5 Author: Pekka Riikonen <priikone@silcnet.org>
6
7 Copyright (C) 2000 - 2007 Pekka Riikonen
8
9 The contents of this file are subject to one of the Licenses specified
10 in the COPYING file; You may not use this file except in compliance
11 with the License.
12
13 The software distributed under the License is distributed on an "AS IS"
14 basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
15 KIND, either expressed or implied. See the COPYING file for more
16 information.
17
18 */
19 /* $Id$ */
20
21 #include "silc.h"
22 #include "silcnotify.h"
23
24 /******************************************************************************
25
26 Notify Payload
27
28 ******************************************************************************/
29
30 struct SilcNotifyPayloadStruct {
31 SilcNotifyType type;
32 unsigned char argc;
33 SilcArgumentPayload args;
34 };
35
36 /* Parse notify payload buffer and return data into payload structure */
37
silc_notify_payload_parse(const unsigned char * payload,SilcUInt32 payload_len)38 SilcNotifyPayload silc_notify_payload_parse(const unsigned char *payload,
39 SilcUInt32 payload_len)
40 {
41 SilcBufferStruct buffer;
42 SilcNotifyPayload newp;
43 SilcUInt16 len;
44 int ret;
45
46 SILC_LOG_DEBUG(("Parsing Notify payload"));
47
48 silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
49 newp = silc_calloc(1, sizeof(*newp));
50 if (!newp)
51 return NULL;
52
53 ret = silc_buffer_unformat(&buffer,
54 SILC_STR_UI_SHORT(&newp->type),
55 SILC_STR_UI_SHORT(&len),
56 SILC_STR_UI_CHAR(&newp->argc),
57 SILC_STR_END);
58 if (ret == -1)
59 goto err;
60
61 if (len > silc_buffer_len(&buffer))
62 goto err;
63
64 if (newp->argc) {
65 silc_buffer_pull(&buffer, 5);
66 newp->args = silc_argument_payload_parse(buffer.data,
67 silc_buffer_len(&buffer),
68 newp->argc);
69 if (!newp->args)
70 goto err;
71 silc_buffer_push(&buffer, 5);
72 }
73
74 return newp;
75
76 err:
77 silc_free(newp);
78 return NULL;
79 }
80
81 /* Encode notify payload with variable argument list. If `argc' is > 0
82 argument payloads will be associated to the notify payload. Variable
83 arguments must be {usigned char *, SilcUInt32 (len)}. */
84
silc_notify_payload_encode(SilcNotifyType type,SilcUInt32 argc,va_list ap)85 SilcBuffer silc_notify_payload_encode(SilcNotifyType type, SilcUInt32 argc,
86 va_list ap)
87 {
88 SilcBuffer buffer;
89 SilcBuffer args = NULL;
90 unsigned char **argv;
91 SilcUInt32 *argv_lens = NULL, *argv_types = NULL;
92 unsigned char *x;
93 SilcUInt32 x_len, len = 0;
94 int i, k = 0;
95
96 if (argc) {
97 argv = silc_calloc(argc, sizeof(unsigned char *));
98 if (!argv)
99 return NULL;
100 argv_lens = silc_calloc(argc, sizeof(SilcUInt32));
101 if (!argv_lens) {
102 silc_free(argv);
103 return NULL;
104 }
105 argv_types = silc_calloc(argc, sizeof(SilcUInt32));
106 if (!argv_types) {
107 silc_free(argv_lens);
108 silc_free(argv);
109 return NULL;
110 }
111
112 for (i = 0, k = 0; i < argc; i++) {
113 x = va_arg(ap, unsigned char *);
114 x_len = va_arg(ap, SilcUInt32);
115
116 if (!x || !x_len)
117 continue;
118
119 argv[k] = silc_memdup(x, x_len);
120 if (!argv[k])
121 return NULL;
122 argv_lens[k] = x_len;
123 argv_types[k] = i + 1;
124 k++;
125 }
126
127 args = silc_argument_payload_encode(k, argv, argv_lens, argv_types);
128 len = silc_buffer_len(args);
129
130 for (i = 0; i < k; i++)
131 silc_free(argv[i]);
132 silc_free(argv);
133 silc_free(argv_lens);
134 silc_free(argv_types);
135 }
136
137 len += 5;
138 buffer = silc_buffer_alloc_size(len);
139 if (!buffer)
140 return NULL;
141 silc_buffer_format(buffer,
142 SILC_STR_UI_SHORT(type),
143 SILC_STR_UI_SHORT(len),
144 SILC_STR_UI_CHAR(k),
145 SILC_STR_END);
146
147 if (k) {
148 silc_buffer_format(buffer,
149 SILC_STR_OFFSET(5),
150 SILC_STR_DATA(args->data, silc_buffer_len(args)),
151 SILC_STR_END);
152 silc_buffer_free(args);
153 }
154
155 return buffer;
156 }
157
158 /* Same as above but takes argument from the `args' Argument Payload. */
159
silc_notify_payload_encode_args(SilcNotifyType type,SilcUInt32 argc,SilcBuffer args)160 SilcBuffer silc_notify_payload_encode_args(SilcNotifyType type,
161 SilcUInt32 argc,
162 SilcBuffer args)
163 {
164 SilcBuffer buffer;
165 SilcUInt32 len;
166
167 len = 5 + (args ? silc_buffer_len(args) : 0);
168 buffer = silc_buffer_alloc_size(len);
169 if (!buffer)
170 return NULL;
171 silc_buffer_format(buffer,
172 SILC_STR_UI_SHORT(type),
173 SILC_STR_UI_SHORT(len),
174 SILC_STR_UI_CHAR(argc),
175 SILC_STR_END);
176
177 if (args)
178 silc_buffer_format(buffer,
179 SILC_STR_OFFSET(5),
180 SILC_STR_DATA(args->data, silc_buffer_len(args)),
181 SILC_STR_END);
182
183 return buffer;
184 }
185
186 /* Frees notify payload */
187
silc_notify_payload_free(SilcNotifyPayload payload)188 void silc_notify_payload_free(SilcNotifyPayload payload)
189 {
190 if (payload) {
191 silc_argument_payload_free(payload->args);
192 silc_free(payload);
193 }
194 }
195
196 /* Return notify type */
197
silc_notify_get_type(SilcNotifyPayload payload)198 SilcNotifyType silc_notify_get_type(SilcNotifyPayload payload)
199 {
200 return payload->type;
201 }
202
203 /* Return argument nums */
204
silc_notify_get_arg_num(SilcNotifyPayload payload)205 SilcUInt32 silc_notify_get_arg_num(SilcNotifyPayload payload)
206 {
207 return payload->argc;
208 }
209
210 /* Return argument payload */
211
silc_notify_get_args(SilcNotifyPayload payload)212 SilcArgumentPayload silc_notify_get_args(SilcNotifyPayload payload)
213 {
214 return payload->args;
215 }
216