]> git.stg.codes - stg.git/blobdiff - libs/smux/asn_codecs_prim.c
Merge remote-tracking branch 'github/master'
[stg.git] / libs / smux / asn_codecs_prim.c
index 4e5c63937adafc40a56b67fe5b3d9482220907d5..78448a8ecb760a66f2405dac67bdf0c87aebe247 100644 (file)
  * Decode an always-primitive type.
  */
 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) {
-       ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
+ber_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
+                     const asn_TYPE_descriptor_t *td, void **sptr,
+                     const void *buf_ptr, size_t size, int tag_mode) {
+    ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
        asn_dec_rval_t rval;
-       ber_tlv_len_t length;
+       ber_tlv_len_t length = 0; /* =0 to avoid [incorrect] warning. */
 
        /*
         * If the structure is not there, allocate it.
         */
        if(st == NULL) {
                st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st));
-               if(st == NULL) _ASN_DECODE_FAILED;
+               if(st == NULL) ASN__DECODE_FAILED;
                *sptr = (void *)st;
        }
 
@@ -55,13 +55,13 @@ ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
        if(sizeof(st->size) != sizeof(length)
                        && (ber_tlv_len_t)st->size != length) {
                st->size = 0;
-               _ASN_DECODE_FAILED;
+               ASN__DECODE_FAILED;
        }
 
        st->buf = (uint8_t *)MALLOC(length + 1);
        if(!st->buf) {
                st->size = 0;
-               _ASN_DECODE_FAILED;
+               ASN__DECODE_FAILED;
        }
 
        memcpy(st->buf, buf_ptr, length);
@@ -81,11 +81,11 @@ ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
  * Encode an always-primitive type using DER.
  */
 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) {
-       asn_enc_rval_t erval;
-       ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
+der_encode_primitive(const asn_TYPE_descriptor_t *td, const void *sptr,
+                     int tag_mode, ber_tlv_tag_t tag,
+                     asn_app_consume_bytes_f *cb, void *app_key) {
+    asn_enc_rval_t erval;
+       const ASN__PRIMITIVE_TYPE_t *st = (const ASN__PRIMITIVE_TYPE_t *)sptr;
 
        ASN_DEBUG("%s %s as a primitive type (tm=%d)",
                cb?"Encoding":"Estimating", td->name, tag_mode);
@@ -111,13 +111,13 @@ der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr,
        }
 
        erval.encoded += st->size;
-       _ASN_ENCODED_OK(erval);
+       ASN__ENCODED_OK(erval);
 }
 
 void
-ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
-               int contents_only) {
-       ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
+ASN__PRIMITIVE_TYPE_free(const asn_TYPE_descriptor_t *td, void *sptr,
+                         enum asn_struct_free_method method) {
+    ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
 
        if(!td || !sptr)
                return;
@@ -127,8 +127,16 @@ ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
        if(st->buf)
                FREEMEM(st->buf);
 
-       if(!contents_only)
-               FREEMEM(st);
+    switch(method) {
+    case ASFM_FREE_EVERYTHING:
+        FREEMEM(sptr);
+        break;
+    case ASFM_FREE_UNDERLYING:
+        break;
+    case ASFM_FREE_UNDERLYING_AND_RESET:
+        memset(sptr, 0, sizeof(ASN__PRIMITIVE_TYPE_t));
+        break;
+    }
 }
 
 
@@ -136,27 +144,33 @@ ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
  * Local internal type passed around as an argument.
  */
 struct xdp_arg_s {
-       asn_TYPE_descriptor_t *type_descriptor;
-       void *struct_key;
+    const asn_TYPE_descriptor_t *type_descriptor;
+    void *struct_key;
        xer_primitive_body_decoder_f *prim_body_decoder;
        int decoded_something;
        int want_more;
 };
 
-
+/*
+ * Since some kinds of primitive values can be encoded using value-specific
+ * tags (<MINUS-INFINITY>, <enum-element>, etc), the primitive decoder must
+ * be supplied with such tags to parse them as needed.
+ */
 static int
 xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
        struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
        enum xer_pbd_rval bret;
 
-       if(arg->decoded_something) {
-               if(xer_is_whitespace(chunk_buf, chunk_size))
-                       return 0;       /* Skip it. */
-               /*
-                * Decoding was done once already. Prohibit doing it again.
-                */
+       /*
+        * The chunk_buf is guaranteed to start at '<'.
+        */
+       assert(chunk_size && ((const char *)chunk_buf)[0] == 0x3c);
+
+       /*
+        * Decoding was performed once already. Prohibit doing it again.
+        */
+       if(arg->decoded_something)
                return -1;
-       }
 
        bret = arg->prim_body_decoder(arg->type_descriptor,
                arg->struct_key, chunk_buf, chunk_size);
@@ -177,13 +191,20 @@ xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size)
 }
 
 static ssize_t
-xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
+xer_decode__primitive_body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
        struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
        enum xer_pbd_rval bret;
+       size_t lead_wsp_size;
 
        if(arg->decoded_something) {
-               if(xer_is_whitespace(chunk_buf, chunk_size))
+               if(xer_whitespace_span(chunk_buf, chunk_size) == chunk_size) {
+                       /*
+                        * Example:
+                        * "<INTEGER>123<!--/--> </INTEGER>"
+                        *                      ^- chunk_buf position.
+                        */
                        return chunk_size;
+               }
                /*
                 * Decoding was done once already. Prohibit doing it again.
                 */
@@ -203,6 +224,10 @@ xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_m
                return -1;
        }
 
+       lead_wsp_size = xer_whitespace_span(chunk_buf, chunk_size);
+       chunk_buf = (const char *)chunk_buf + lead_wsp_size;
+       chunk_size -= lead_wsp_size;
+
        bret = arg->prim_body_decoder(arg->type_descriptor,
                arg->struct_key, chunk_buf, chunk_size);
        switch(bret) {
@@ -215,7 +240,7 @@ xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_m
                arg->decoded_something = 1;
                /* Fall through */
        case XPBD_NOT_BODY_IGNORE:      /* Safe to proceed further */
-               return chunk_size;
+               return lead_wsp_size + chunk_size;
        }
 
        return -1;
@@ -223,15 +248,12 @@ xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_m
 
 
 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
-) {
-       const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
+xer_decode_primitive(const asn_codec_ctx_t *opt_codec_ctx,
+                     const 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) {
+    const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
        asn_struct_ctx_t s_ctx;
        struct xdp_arg_s s_arg;
        asn_dec_rval_t rc;
@@ -241,7 +263,7 @@ xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
         */
        if(!*sptr) {
                *sptr = CALLOC(1, struct_size);
-               if(!*sptr) _ASN_DECODE_FAILED;
+               if(!*sptr) ASN__DECODE_FAILED;
        }
 
        memset(&s_ctx, 0, sizeof(s_ctx));
@@ -253,7 +275,7 @@ xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
 
        rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
                xml_tag, buf_ptr, size,
-               xer_decode__unexpected_tag, xer_decode__body);
+               xer_decode__unexpected_tag, xer_decode__primitive_body);
        switch(rc.code) {
        case RC_OK:
                if(!s_arg.decoded_something) {
@@ -271,7 +293,7 @@ xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
                                /*
                                 * This decoder does not like empty stuff.
                                 */
-                               _ASN_DECODE_FAILED;
+                               ASN__DECODE_FAILED;
                        }
                }
                break;
@@ -287,7 +309,7 @@ xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
                if(s_arg.want_more)
                        rc.code = RC_WMORE;
                else
-                       _ASN_DECODE_FAILED;
+                       ASN__DECODE_FAILED;
                break;
        }
        return rc;