1 /*****************************************************************************
3 # Copyright 2019 AT&T Intellectual Property *
5 # Licensed under the Apache License, Version 2.0 (the "License"); *
6 # you may not use this file except in compliance with the License. *
7 # You may obtain a copy of the License at *
9 # http://www.apache.org/licenses/LICENSE-2.0 *
11 # Unless required by applicable law or agreed to in writing, software *
12 # distributed under the License is distributed on an "AS IS" BASIS, *
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
14 # See the License for the specific language governing permissions and *
15 # limitations under the License. *
17 ******************************************************************************/
20 * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
21 * Redistribution and modifications are permitted subject to BSD license.
23 #include <asn_internal.h>
24 #include <asn_codecs_prim.h>
28 * Decode an always-primitive type.
31 ber_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
32 const asn_TYPE_descriptor_t *td, void **sptr,
33 const void *buf_ptr, size_t size, int tag_mode) {
34 ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
36 ber_tlv_len_t length = 0; /* =0 to avoid [incorrect] warning. */
39 * If the structure is not there, allocate it.
42 st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
43 if(st == NULL) ASN__DECODE_FAILED;
47 ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
51 * Check tags and extract value length.
53 rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
54 tag_mode, 0, &length, 0);
55 if(rval.code != RC_OK)
58 ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
61 * Make sure we have this length.
63 buf_ptr = ((const char *)buf_ptr) + rval.consumed;
64 size -= rval.consumed;
65 if(length > (ber_tlv_len_t)size) {
71 st->size = (int)length;
72 /* The following better be optimized away. */
73 if(sizeof(st->size) != sizeof(length)
74 && (ber_tlv_len_t)st->size != length) {
79 st->buf = (uint8_t *)MALLOC(length + 1);
85 memcpy(st->buf, buf_ptr, length);
86 st->buf[length] = '\0'; /* Just in case */
89 rval.consumed += length;
91 ASN_DEBUG("Took %ld/%ld bytes to encode %s",
93 (long)length, td->name);
99 * Encode an always-primitive type using DER.
102 der_encode_primitive(const asn_TYPE_descriptor_t *td, const void *sptr,
103 int tag_mode, ber_tlv_tag_t tag,
104 asn_app_consume_bytes_f *cb, void *app_key) {
105 asn_enc_rval_t erval = {0,0,0};
106 const ASN__PRIMITIVE_TYPE_t *st = (const ASN__PRIMITIVE_TYPE_t *)sptr;
108 ASN_DEBUG("%s %s as a primitive type (tm=%d)",
109 cb?"Encoding":"Estimating", td->name, tag_mode);
111 erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
113 ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
114 if(erval.encoded == -1) {
115 erval.failed_type = td;
116 erval.structure_ptr = sptr;
121 if(cb(st->buf, st->size, app_key) < 0) {
123 erval.failed_type = td;
124 erval.structure_ptr = sptr;
128 assert(st->buf || st->size == 0);
131 erval.encoded += st->size;
132 ASN__ENCODED_OK(erval);
136 ASN__PRIMITIVE_TYPE_free(const asn_TYPE_descriptor_t *td, void *sptr,
137 enum asn_struct_free_method method) {
138 ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
143 ASN_DEBUG("Freeing %s as a primitive type", td->name);
149 case ASFM_FREE_EVERYTHING:
152 case ASFM_FREE_UNDERLYING:
154 case ASFM_FREE_UNDERLYING_AND_RESET:
155 memset(sptr, 0, sizeof(ASN__PRIMITIVE_TYPE_t));
162 * Local internal type passed around as an argument.
165 const asn_TYPE_descriptor_t *type_descriptor;
167 xer_primitive_body_decoder_f *prim_body_decoder;
168 int decoded_something;
173 * Since some kinds of primitive values can be encoded using value-specific
174 * tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
175 * be supplied with such tags to parse them as needed.
178 xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
179 struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
180 enum xer_pbd_rval bret;
183 * The chunk_buf is guaranteed to start at '<'.
185 assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
188 * Decoding was performed once already. Prohibit doing it again.
190 if(arg->decoded_something)
193 bret = arg->prim_body_decoder(arg->type_descriptor,
194 arg->struct_key, chunk_buf, chunk_size);
196 case XPBD_SYSTEM_FAILURE:
197 case XPBD_DECODER_LIMIT:
198 case XPBD_BROKEN_ENCODING:
200 case XPBD_BODY_CONSUMED:
201 /* Tag decoded successfully */
202 arg->decoded_something = 1;
204 case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
212 xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
213 struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
214 enum xer_pbd_rval bret;
215 size_t lead_wsp_size;
217 if(arg->decoded_something) {
218 if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
221 * "<INTEGER>123<!--/--> </INTEGER>"
222 * ^- chunk_buf position.
227 * Decoding was done once already. Prohibit doing it again.
234 * If we've received something like "1", we can't really
235 * tell whether it is really `1` or `123`, until we know
236 * that there is no more data coming.
237 * The have_more argument will be set to 1 once something
238 * like this is available to the caller of this callback:
245 lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
246 chunk_buf = (const char *)chunk_buf + lead_wsp_size;
247 chunk_size -= lead_wsp_size;
249 bret = arg->prim_body_decoder(arg->type_descriptor,
250 arg->struct_key, chunk_buf, chunk_size);
252 case XPBD_SYSTEM_FAILURE:
253 case XPBD_DECODER_LIMIT:
254 case XPBD_BROKEN_ENCODING:
256 case XPBD_BODY_CONSUMED:
257 /* Tag decoded successfully */
258 arg->decoded_something = 1;
260 case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
261 return lead_wsp_size + chunk_size;
269 xer_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
270 const asn_TYPE_descriptor_t *td, void **sptr,
271 size_t struct_size, const char *opt_mname,
272 const void *buf_ptr, size_t size,
273 xer_primitive_body_decoder_f *prim_body_decoder) {
274 const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
275 asn_struct_ctx_t s_ctx;
276 struct xdp_arg_s s_arg;
280 * Create the structure if does not exist.
283 *sptr = CALLOC(1, struct_size);
284 if(!*sptr) ASN__DECODE_FAILED;
287 memset(&s_ctx, 0, sizeof(s_ctx));
288 s_arg.type_descriptor = td;
289 s_arg.struct_key = *sptr;
290 s_arg.prim_body_decoder = prim_body_decoder;
291 s_arg.decoded_something = 0;
294 rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
295 xml_tag, buf_ptr, size,
296 xer_decode__unexpected_tag, xer_decode__primitive_body);
299 if(!s_arg.decoded_something) {
301 ASN_DEBUG("Primitive body is not recognized, "
302 "supplying empty one");
304 * Decoding opportunity has come and gone.
305 * Where's the result?
306 * Try to feed with empty body, see if it eats it.
308 if(prim_body_decoder(s_arg.type_descriptor,
309 s_arg.struct_key, &ch, 0)
310 != XPBD_BODY_CONSUMED) {
312 * This decoder does not like empty stuff.
320 * Redo the whole thing later.
321 * We don't have a context to save intermediate parsing state.