blob: 5fe09adbf6db42d2b6f4776e1aafc87b2941061c [file] [log] [blame]
vlmc4436cf2004-10-21 11:20:50 +00001/*-
2 * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
4 */
5#include <asn_internal.h>
6#include <asn_codecs_prim.h>
7#include <assert.h>
8#include <errno.h>
9
10/*
11 * Decode an always-primitive type.
12 */
13asn_dec_rval_t
14ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
15 asn_TYPE_descriptor_t *td,
16 void **sptr, void *buf_ptr, size_t size, int tag_mode) {
17 ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
18 asn_dec_rval_t rval;
19 ber_tlv_len_t length;
20
21 /*
22 * If the structure is not there, allocate it.
23 */
24 if(st == NULL) {
vlm82e317b2004-12-14 13:31:01 +000025 st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
vlmc4436cf2004-10-21 11:20:50 +000026 if(st == NULL) {
27 rval.code = RC_FAIL;
28 rval.consumed = 0;
29 return rval;
30 }
vlm82e317b2004-12-14 13:31:01 +000031 *sptr = (void *)st;
vlmc4436cf2004-10-21 11:20:50 +000032 }
33
34 ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
35 td->name, tag_mode);
36
37 /*
38 * Check tags and extract value length.
39 */
40 rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
41 tag_mode, 0, &length, 0);
42 if(rval.code != RC_OK)
43 return rval;
44
45 ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
46
47 /*
48 * Make sure we have this length.
49 */
50 buf_ptr = ((char *)buf_ptr) + rval.consumed;
51 size -= rval.consumed;
52 if(length > (ber_tlv_len_t)size) {
53 rval.code = RC_WMORE;
54 rval.consumed = 0;
55 return rval;
56 }
57
58 st->buf = (uint8_t *)MALLOC(length + 1);
59 if(st->buf) {
60 st->size = length;
61 } else {
62 rval.code = RC_FAIL;
63 rval.consumed = 0;
64 return rval;
65 }
66
67 memcpy(st->buf, buf_ptr, length);
68 st->buf[length] = '\0'; /* Just in case */
69
70 rval.code = RC_OK;
71 rval.consumed += length;
72
73 ASN_DEBUG("Took %ld/%ld bytes to encode %s",
74 (long)rval.consumed,
75 (long)length, td->name);
76
77 return rval;
78}
79
80/*
81 * Encode an always-primitive type using DER.
82 */
83asn_enc_rval_t
84der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr,
85 int tag_mode, ber_tlv_tag_t tag,
86 asn_app_consume_bytes_f *cb, void *app_key) {
87 asn_enc_rval_t erval;
88 ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
89
90 ASN_DEBUG("%s %s as a primitive type (tm=%d)",
91 cb?"Encoding":"Estimating", td->name, tag_mode);
92
93 erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
94 cb, app_key);
95 ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
96 if(erval.encoded == -1) {
97 erval.failed_type = td;
98 erval.structure_ptr = sptr;
99 return erval;
100 }
101
102 if(cb && st->buf) {
103 if(cb(st->buf, st->size, app_key) < 0) {
104 erval.encoded = -1;
105 erval.failed_type = td;
106 erval.structure_ptr = sptr;
107 return erval;
108 }
109 } else {
110 assert(st->buf || st->size == 0);
111 }
112
113 erval.encoded += st->size;
114
115 return erval;
116}
117
118void
119ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
120 int contents_only) {
121 ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
122
123 if(!td || !sptr)
124 return;
125
126 ASN_DEBUG("Freeing %s as a primitive type", td->name);
127
128 if(st->buf)
129 FREEMEM(st->buf);
130
131 if(!contents_only)
132 FREEMEM(st);
133}
134
135
136/*
137 * Local internal type passed around as an argument.
138 */
139struct xdp_arg_s {
vlm80a48592005-02-25 12:10:27 +0000140 asn_TYPE_descriptor_t *type_descriptor;
vlmb848b2a2004-10-21 14:02:19 +0000141 void *struct_key;
vlm80a48592005-02-25 12:10:27 +0000142 ssize_t (*prim_body_decode)(asn_TYPE_descriptor_t *td,
143 void *struct_key, void *chunk_buf, size_t chunk_size);
vlmc4436cf2004-10-21 11:20:50 +0000144 int decoded_something;
145 int want_more;
146};
147
vlme4f9cac2004-10-21 12:11:57 +0000148
vlmc4436cf2004-10-21 11:20:50 +0000149static int
150xer_decode__unexpected_tag(void *key, void *chunk_buf, size_t chunk_size) {
151 struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
152 ssize_t decoded;
153
154 if(arg->decoded_something) {
vlm2a4245f2004-10-22 08:17:16 +0000155 if(xer_is_whitespace(chunk_buf, chunk_size))
vlme4f9cac2004-10-21 12:11:57 +0000156 return chunk_size;
vlmc4436cf2004-10-21 11:20:50 +0000157 /*
158 * Decoding was done once already. Prohibit doing it again.
159 */
160 return -1;
161 }
162
vlm80a48592005-02-25 12:10:27 +0000163 decoded = arg->prim_body_decode(arg->type_descriptor,
164 arg->struct_key, chunk_buf, chunk_size);
vlmc4436cf2004-10-21 11:20:50 +0000165 if(decoded < 0) {
166 return -1;
167 } else {
168 /* Tag decoded successfully */
169 arg->decoded_something = 1;
170 return 0;
171 }
172}
173
174static ssize_t
175xer_decode__body(void *key, void *chunk_buf, size_t chunk_size, int have_more) {
176 struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
177 ssize_t decoded;
178
179 if(arg->decoded_something) {
vlm2a4245f2004-10-22 08:17:16 +0000180 if(xer_is_whitespace(chunk_buf, chunk_size))
vlme4f9cac2004-10-21 12:11:57 +0000181 return chunk_size;
vlmc4436cf2004-10-21 11:20:50 +0000182 /*
183 * Decoding was done once already. Prohibit doing it again.
184 */
185 return -1;
186 }
187
188 if(!have_more) {
189 /*
190 * If we've received something like "1", we can't really
191 * tell whether it is really `1` or `123`, until we know
192 * that there is no more data coming.
193 * The have_more argument will be set to 1 once something
194 * like this is available to the caller of this callback:
195 * "1<tag_start..."
196 */
197 arg->want_more = 1;
198 return -1;
199 }
200
vlm80a48592005-02-25 12:10:27 +0000201 decoded = arg->prim_body_decode(arg->type_descriptor,
202 arg->struct_key, chunk_buf, chunk_size);
vlmc4436cf2004-10-21 11:20:50 +0000203 if(decoded < 0) {
204 return -1;
205 } else {
206 arg->decoded_something = 1;
207 return decoded;
208 }
209}
210
211
212asn_dec_rval_t
213xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
214 asn_TYPE_descriptor_t *td,
vlmb848b2a2004-10-21 14:02:19 +0000215 void **sptr,
216 size_t struct_size,
vlmc4436cf2004-10-21 11:20:50 +0000217 const char *opt_mname,
218 void *buf_ptr, size_t size,
vlm80a48592005-02-25 12:10:27 +0000219 ssize_t (*prim_body_decode)(asn_TYPE_descriptor_t *td,
220 void *struct_key, void *chunk_buf, size_t chunk_size)
vlmc4436cf2004-10-21 11:20:50 +0000221) {
222 const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
223 asn_struct_ctx_t s_ctx;
224 struct xdp_arg_s s_arg;
225 asn_dec_rval_t rc;
226
227 /*
228 * Create the structure if does not exist.
229 */
230 if(!*sptr) {
vlmb848b2a2004-10-21 14:02:19 +0000231 *sptr = CALLOC(1, struct_size);
vlmc4436cf2004-10-21 11:20:50 +0000232 if(!*sptr) {
233 asn_dec_rval_t rval;
234 rval.code = RC_FAIL;
235 rval.consumed = 0;
236 return rval;
237 }
238 }
239
240 memset(&s_ctx, 0, sizeof(s_ctx));
vlm80a48592005-02-25 12:10:27 +0000241 s_arg.type_descriptor = td;
vlmb848b2a2004-10-21 14:02:19 +0000242 s_arg.struct_key = *sptr;
vlmc4436cf2004-10-21 11:20:50 +0000243 s_arg.prim_body_decode = prim_body_decode;
244 s_arg.decoded_something = 0;
245 s_arg.want_more = 0;
246
247 rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
248 xml_tag, buf_ptr, size,
249 xer_decode__unexpected_tag, xer_decode__body);
250 switch(rc.code) {
251 case RC_OK:
252 if(!s_arg.decoded_something) {
vlm64f1ba22004-10-23 11:19:43 +0000253 char ch;
vlmc4436cf2004-10-21 11:20:50 +0000254 /* Opportunity has come and gone. Where's the result? */
vlm80a48592005-02-25 12:10:27 +0000255 if(prim_body_decode(s_arg.type_descriptor,
256 s_arg.struct_key, &ch, 0) != 0) {
vlmf7de4de2004-10-23 10:17:34 +0000257 /*
258 * This decoder does not like empty stuff.
259 */
260 rc.code = RC_FAIL;
261 rc.consumed = 0;
262 }
vlmc4436cf2004-10-21 11:20:50 +0000263 }
264 break;
265 case RC_WMORE:
266 /*
267 * Redo the whole thing later.
268 * We don't have a context to save intermediate parsing state.
269 */
270 rc.consumed = 0;
271 break;
272 case RC_FAIL:
273 rc.consumed = 0;
274 if(s_arg.want_more)
275 rc.code = RC_WMORE;
276 break;
277 }
278 return rc;
279}
280