ITS
asn_codecs_prim.c
Go to the documentation of this file.
1 /*-
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 <errno.h>
8 
9 /*
10  * Decode an always-primitive type.
11  */
15  void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
17  asn_dec_rval_t rval;
18  ber_tlv_len_t length = 0; // =0 to avoid [incorrect] warning.
19 
20  /*
21  * If the structure is not there, allocate it.
22  */
23  if(st == NULL) {
24  st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
25  if(st == NULL) _ASN_DECODE_FAILED;
26  *sptr = (void *)st;
27  }
28 
29  ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
30  td->name, tag_mode);
31 
32  /*
33  * Check tags and extract value length.
34  */
35  rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
36  tag_mode, 0, &length, 0);
37  if(rval.code != RC_OK)
38  return rval;
39 
40  ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
41 
42  /*
43  * Make sure we have this length.
44  */
45  buf_ptr = ((const char *)buf_ptr) + rval.consumed;
46  size -= rval.consumed;
47  if(length > (ber_tlv_len_t)size) {
48  rval.code = RC_WMORE;
49  rval.consumed = 0;
50  return rval;
51  }
52 
53  st->size = (int)length;
54  /* The following better be optimized away. */
55  if(sizeof(st->size) != sizeof(length)
56  && (ber_tlv_len_t)st->size != length) {
57  st->size = 0;
59  }
60 
61  st->buf = (uint8_t *)MALLOC(length + 1);
62  if(!st->buf) {
63  st->size = 0;
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  */
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;
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  _ASN_ENCODED_OK(erval);
115 }
116 
117 void
119  int contents_only) {
121 
122  if(!td || !sptr)
123  return;
124 
125  ASN_DEBUG("Freeing %s as a primitive type", td->name);
126 
127  if(st->buf)
128  FREEMEM(st->buf);
129 
130  if(!contents_only)
131  FREEMEM(st);
132 }
133 
134 
135 /*
136  * Local internal type passed around as an argument.
137  */
138 struct xdp_arg_s {
140  void *struct_key;
144 };
145 
146 /*
147  * Since some kinds of primitive values can be encoded using value-specific
148  * tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
149  * be supplied with such tags to parse them as needed.
150  */
151 static int
152 xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
153  struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
154  enum xer_pbd_rval bret;
155 
156  /*
157  * The chunk_buf is guaranteed to start at '<'.
158  */
159  assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
160 
161  /*
162  * Decoding was performed once already. Prohibit doing it again.
163  */
164  if(arg->decoded_something)
165  return -1;
166 
167  bret = arg->prim_body_decoder(arg->type_descriptor,
168  arg->struct_key, chunk_buf, chunk_size);
169  switch(bret) {
170  case XPBD_SYSTEM_FAILURE:
171  case XPBD_DECODER_LIMIT:
173  break;
174  case XPBD_BODY_CONSUMED:
175  /* Tag decoded successfully */
176  arg->decoded_something = 1;
177  /* Fall through */
178  case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
179  return 0;
180  }
181 
182  return -1;
183 }
184 
185 static ssize_t
186 xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
187  struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
188  enum xer_pbd_rval bret;
189  size_t lead_wsp_size;
190 
191  if(arg->decoded_something) {
192  if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
193  /*
194  * Example:
195  * "<INTEGER>123<!--/--> </INTEGER>"
196  * ^- chunk_buf position.
197  */
198  return chunk_size;
199  }
200  /*
201  * Decoding was done once already. Prohibit doing it again.
202  */
203  return -1;
204  }
205 
206  if(!have_more) {
207  /*
208  * If we've received something like "1", we can't really
209  * tell whether it is really `1` or `123`, until we know
210  * that there is no more data coming.
211  * The have_more argument will be set to 1 once something
212  * like this is available to the caller of this callback:
213  * "1<tag_start..."
214  */
215  arg->want_more = 1;
216  return -1;
217  }
218 
219  lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
220  chunk_buf = (const char *)chunk_buf + lead_wsp_size;
221  chunk_size -= lead_wsp_size;
222 
223  bret = arg->prim_body_decoder(arg->type_descriptor,
224  arg->struct_key, chunk_buf, chunk_size);
225  switch(bret) {
226  case XPBD_SYSTEM_FAILURE:
227  case XPBD_DECODER_LIMIT:
229  break;
230  case XPBD_BODY_CONSUMED:
231  /* Tag decoded successfully */
232  arg->decoded_something = 1;
233  /* Fall through */
234  case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */
235  return lead_wsp_size + chunk_size;
236  }
237 
238  return -1;
239 }
240 
241 
245  void **sptr,
246  size_t struct_size,
247  const char *opt_mname,
248  const void *buf_ptr, size_t size,
250 ) {
251  const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
252  asn_struct_ctx_t s_ctx;
253  struct xdp_arg_s s_arg;
254  asn_dec_rval_t rc;
255 
256  /*
257  * Create the structure if does not exist.
258  */
259  if(!*sptr) {
260  *sptr = CALLOC(1, struct_size);
261  if(!*sptr) _ASN_DECODE_FAILED;
262  }
263 
264  memset(&s_ctx, 0, sizeof(s_ctx));
265  s_arg.type_descriptor = td;
266  s_arg.struct_key = *sptr;
268  s_arg.decoded_something = 0;
269  s_arg.want_more = 0;
270 
271  rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
272  xml_tag, buf_ptr, size,
274  switch(rc.code) {
275  case RC_OK:
276  if(!s_arg.decoded_something) {
277  char ch;
278  ASN_DEBUG("Primitive body is not recognized, "
279  "supplying empty one");
280  /*
281  * Decoding opportunity has come and gone.
282  * Where's the result?
283  * Try to feed with empty body, see if it eats it.
284  */
286  s_arg.struct_key, &ch, 0)
287  != XPBD_BODY_CONSUMED) {
288  /*
289  * This decoder does not like empty stuff.
290  */
292  }
293  }
294  break;
295  case RC_WMORE:
296  /*
297  * Redo the whole thing later.
298  * We don't have a context to save intermediate parsing state.
299  */
300  rc.consumed = 0;
301  break;
302  case RC_FAIL:
303  rc.consumed = 0;
304  if(s_arg.want_more)
305  rc.code = RC_WMORE;
306  else
308  break;
309  }
310  return rc;
311 }
312 
ssize_t der_write_tags(struct asn_TYPE_descriptor_s *type_descriptor, size_t struct_length, int tag_mode, int last_tag_form, ber_tlv_tag_t tag, asn_app_consume_bytes_f *consume_bytes_cb, void *app_key)
Definition: der_encoder.c:77
void * structure_ptr
Definition: asn_codecs.h:58
struct asn_TYPE_descriptor_s * failed_type
Definition: asn_codecs.h:55
asn_enc_rval_t der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr, int tag_mode, ber_tlv_tag_t tag, asn_app_consume_bytes_f *cb, void *app_key)
ssize_t encoded
Definition: asn_codecs.h:48
ssize_t ber_tlv_len_t
#define CALLOC(nmemb, size)
Definition: asn_internal.h:26
void ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only)
static ssize_t xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more)
#define _ASN_ENCODED_OK(rval)
Definition: asn_codecs.h:68
asn_dec_rval_t ber_check_tags(struct asn_codec_ctx_s *opt_codec_ctx, struct asn_TYPE_descriptor_s *type_descriptor, asn_struct_ctx_t *opt_ctx, const void *ptr, size_t size, int tag_mode, int last_tag_form, ber_tlv_len_t *last_length, int *opt_tlv_form)
Definition: ber_decoder.c:65
#define FREEMEM(ptr)
Definition: asn_internal.h:29
int decoded_something
xer_pbd_rval
enum xer_pbd_rval() xer_primitive_body_decoder_f(asn_TYPE_descriptor_t *td, void *struct_ptr, const void *chunk_buf, size_t chunk_size)
void * struct_key
int() asn_app_consume_bytes_f(const void *buffer, size_t size, void *application_specific_key)
size_t xer_whitespace_span(const void *chunk_buf, size_t chunk_size)
Definition: xer_decoder.c:320
size_t consumed
Definition: asn_codecs.h:89
xer_primitive_body_decoder_f * prim_body_decoder
enum asn_dec_rval_code_e code
Definition: asn_codecs.h:88
static void ASN_DEBUG(const char *fmt,...)
Definition: asn_internal.h:62
asn_dec_rval_t ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buf_ptr, size_t size, int tag_mode)
static int xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size)
asn_dec_rval_t xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, size_t struct_size, const char *opt_mname, const void *buf_ptr, size_t size, xer_primitive_body_decoder_f *prim_body_decoder)
#define MALLOC(size)
Definition: asn_internal.h:27
asn_TYPE_descriptor_t * type_descriptor
#define _ASN_DECODE_FAILED
Definition: asn_codecs.h:91
unsigned ber_tlv_tag_t
Definition: ber_tlv_tag.h:18
asn_dec_rval_t xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, asn_struct_ctx_t *ctx, void *struct_key, const char *xml_tag, const void *buf_ptr, size_t size, int(*opt_unexpected_tag_decoder)(void *struct_key, const void *chunk_buf, size_t chunk_size), ssize_t(*body_receiver)(void *struct_key, const void *chunk_buf, size_t chunk_size, int have_more))
Definition: xer_decoder.c:201