~ubuntu-branches/ubuntu/raring/freerdp/raring

« back to all changes in this revision

Viewing changes to asn1/asn_codecs_prim.c

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2010-06-23 21:39:09 UTC
  • Revision ID: james.westby@ubuntu.com-20100623213909-bb9pvvv03913tdv6
Tags: upstream-0.7.1
ImportĀ upstreamĀ versionĀ 0.7.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 */
 
12
asn_dec_rval_t
 
13
ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
 
14
        asn_TYPE_descriptor_t *td,
 
15
        void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
 
16
        ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
 
17
        asn_dec_rval_t rval;
 
18
        ber_tlv_len_t length;
 
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;
 
58
                _ASN_DECODE_FAILED;
 
59
        }
 
60
 
 
61
        st->buf = (uint8_t *)MALLOC(length + 1);
 
62
        if(!st->buf) {
 
63
                st->size = 0;
 
64
                _ASN_DECODE_FAILED;
 
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
 */
 
83
asn_enc_rval_t
 
84
der_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
        _ASN_ENCODED_OK(erval);
 
115
}
 
116
 
 
117
void
 
118
ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr,
 
119
                int contents_only) {
 
120
        ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
 
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 {
 
139
        asn_TYPE_descriptor_t *type_descriptor;
 
140
        void *struct_key;
 
141
        xer_primitive_body_decoder_f *prim_body_decoder;
 
142
        int decoded_something;
 
143
        int want_more;
 
144
};
 
145
 
 
146
 
 
147
static int
 
148
xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) {
 
149
        struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
 
150
        enum xer_pbd_rval bret;
 
151
 
 
152
        if(arg->decoded_something) {
 
153
                if(xer_is_whitespace(chunk_buf, chunk_size))
 
154
                        return 0;       /* Skip it. */
 
155
                /*
 
156
                 * Decoding was done once already. Prohibit doing it again.
 
157
                 */
 
158
                return -1;
 
159
        }
 
160
 
 
161
        bret = arg->prim_body_decoder(arg->type_descriptor,
 
162
                arg->struct_key, chunk_buf, chunk_size);
 
163
        switch(bret) {
 
164
        case XPBD_SYSTEM_FAILURE:
 
165
        case XPBD_DECODER_LIMIT:
 
166
        case XPBD_BROKEN_ENCODING:
 
167
                break;
 
168
        case XPBD_BODY_CONSUMED:
 
169
                /* Tag decoded successfully */
 
170
                arg->decoded_something = 1;
 
171
                /* Fall through */
 
172
        case XPBD_NOT_BODY_IGNORE:      /* Safe to proceed further */
 
173
                return 0;
 
174
        }
 
175
 
 
176
        return -1;
 
177
}
 
178
 
 
179
static ssize_t
 
180
xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) {
 
181
        struct xdp_arg_s *arg = (struct xdp_arg_s *)key;
 
182
        enum xer_pbd_rval bret;
 
183
 
 
184
        if(arg->decoded_something) {
 
185
                if(xer_is_whitespace(chunk_buf, chunk_size))
 
186
                        return chunk_size;
 
187
                /*
 
188
                 * Decoding was done once already. Prohibit doing it again.
 
189
                 */
 
190
                return -1;
 
191
        }
 
192
 
 
193
        if(!have_more) {
 
194
                /*
 
195
                 * If we've received something like "1", we can't really
 
196
                 * tell whether it is really `1` or `123`, until we know
 
197
                 * that there is no more data coming.
 
198
                 * The have_more argument will be set to 1 once something
 
199
                 * like this is available to the caller of this callback:
 
200
                 * "1<tag_start..."
 
201
                 */
 
202
                arg->want_more = 1;
 
203
                return -1;
 
204
        }
 
205
 
 
206
        bret = arg->prim_body_decoder(arg->type_descriptor,
 
207
                arg->struct_key, chunk_buf, chunk_size);
 
208
        switch(bret) {
 
209
        case XPBD_SYSTEM_FAILURE:
 
210
        case XPBD_DECODER_LIMIT:
 
211
        case XPBD_BROKEN_ENCODING:
 
212
                break;
 
213
        case XPBD_BODY_CONSUMED:
 
214
                /* Tag decoded successfully */
 
215
                arg->decoded_something = 1;
 
216
                /* Fall through */
 
217
        case XPBD_NOT_BODY_IGNORE:      /* Safe to proceed further */
 
218
                return chunk_size;
 
219
        }
 
220
 
 
221
        return -1;
 
222
}
 
223
 
 
224
 
 
225
asn_dec_rval_t
 
226
xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx,
 
227
        asn_TYPE_descriptor_t *td,
 
228
        void **sptr,
 
229
        size_t struct_size,
 
230
        const char *opt_mname,
 
231
        const void *buf_ptr, size_t size,
 
232
        xer_primitive_body_decoder_f *prim_body_decoder
 
233
) {
 
234
        const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
 
235
        asn_struct_ctx_t s_ctx;
 
236
        struct xdp_arg_s s_arg;
 
237
        asn_dec_rval_t rc;
 
238
 
 
239
        /*
 
240
         * Create the structure if does not exist.
 
241
         */
 
242
        if(!*sptr) {
 
243
                *sptr = CALLOC(1, struct_size);
 
244
                if(!*sptr) _ASN_DECODE_FAILED;
 
245
        }
 
246
 
 
247
        memset(&s_ctx, 0, sizeof(s_ctx));
 
248
        s_arg.type_descriptor = td;
 
249
        s_arg.struct_key = *sptr;
 
250
        s_arg.prim_body_decoder = prim_body_decoder;
 
251
        s_arg.decoded_something = 0;
 
252
        s_arg.want_more = 0;
 
253
 
 
254
        rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg,
 
255
                xml_tag, buf_ptr, size,
 
256
                xer_decode__unexpected_tag, xer_decode__body);
 
257
        switch(rc.code) {
 
258
        case RC_OK:
 
259
                if(!s_arg.decoded_something) {
 
260
                        char ch;
 
261
                        ASN_DEBUG("Primitive body is not recognized, "
 
262
                                "supplying empty one");
 
263
                        /*
 
264
                         * Decoding opportunity has come and gone.
 
265
                         * Where's the result?
 
266
                         * Try to feed with empty body, see if it eats it.
 
267
                         */
 
268
                        if(prim_body_decoder(s_arg.type_descriptor,
 
269
                                s_arg.struct_key, &ch, 0)
 
270
                                        != XPBD_BODY_CONSUMED) {
 
271
                                /*
 
272
                                 * This decoder does not like empty stuff.
 
273
                                 */
 
274
                                _ASN_DECODE_FAILED;
 
275
                        }
 
276
                }
 
277
                break;
 
278
        case RC_WMORE:
 
279
                /*
 
280
                 * Redo the whole thing later.
 
281
                 * We don't have a context to save intermediate parsing state.
 
282
                 */
 
283
                rc.consumed = 0;
 
284
                break;
 
285
        case RC_FAIL:
 
286
                rc.consumed = 0;
 
287
                if(s_arg.want_more)
 
288
                        rc.code = RC_WMORE;
 
289
                else
 
290
                        _ASN_DECODE_FAILED;
 
291
                break;
 
292
        }
 
293
        return rc;
 
294
}
 
295