blob: ed529c57153b435c85726c2bc579eca7564612cc [file] [log] [blame]
Lev Walkina737f3b2004-09-02 12:11:47 +00001/*-
2 * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
4 */
Lev Walkina9cc46e2004-09-22 16:06:28 +00005#include <asn_internal.h>
Lev Walkina737f3b2004-09-02 12:11:47 +00006#include <ANY.h>
7#include <assert.h>
8#include <errno.h>
9
10asn1_TYPE_descriptor_t asn1_DEF_ANY = {
11 "ANY",
Lev Walkina9cc46e2004-09-22 16:06:28 +000012 OCTET_STRING_free,
13 OCTET_STRING_print,
Lev Walkina737f3b2004-09-02 12:11:47 +000014 asn_generic_no_constraint,
15 OCTET_STRING_decode_ber,
16 OCTET_STRING_encode_der,
Lev Walkina9cc46e2004-09-22 16:06:28 +000017 0, /* Not implemented yet */
18 ANY_encode_xer,
Lev Walkina737f3b2004-09-02 12:11:47 +000019 0, /* Use generic outmost tag fetcher */
Lev Walkind563d392004-09-13 08:26:57 +000020 0, 0, 0, 0,
Lev Walkina737f3b2004-09-02 12:11:47 +000021 -1, /* Both ways are fine (primitive and constructed) */
22 0, 0, /* No members */
23 (void *)1 /* Special indicator that this is an ANY type */
24};
Lev Walkind563d392004-09-13 08:26:57 +000025
26
Lev Walkina9cc46e2004-09-22 16:06:28 +000027asn_enc_rval_t
28ANY_encode_xer(asn1_TYPE_descriptor_t *td, void *sptr,
29 int ilevel, enum xer_encoder_flags_e flags,
30 asn_app_consume_bytes_f *cb, void *app_key) {
31
Lev Walkincc6a9102004-09-23 22:06:26 +000032 if(flags & XER_F_CANONICAL) {
33 /*
34 * Canonical XER-encoding of ANY type is not supported.
35 */
36 _ASN_ENCODE_FAILED;
37 }
Lev Walkina9cc46e2004-09-22 16:06:28 +000038
Lev Walkincc6a9102004-09-23 22:06:26 +000039 /* Dump as binary */
40 return OCTET_STRING_encode_xer(td, sptr, ilevel, flags, cb, app_key);
Lev Walkina9cc46e2004-09-22 16:06:28 +000041}
42
Lev Walkind563d392004-09-13 08:26:57 +000043struct _callback_arg {
44 uint8_t *buffer;
45 size_t offset;
46 size_t size;
47};
48
49static int ANY__consume_bytes(const void *buffer, size_t size, void *key);
50
51int
52ANY_fromType(ANY_t *st, asn1_TYPE_descriptor_t *td, void *sptr) {
53 struct _callback_arg arg;
Lev Walkina9cc46e2004-09-22 16:06:28 +000054 asn_enc_rval_t erval;
Lev Walkind563d392004-09-13 08:26:57 +000055
56 if(!st || !td) {
57 errno = EINVAL;
58 return -1;
59 }
60
61 if(!sptr) {
62 if(st->buf) FREEMEM(st->buf);
63 st->size = 0;
64 return 0;
65 }
66
67 arg.offset = arg.size = 0;
68 arg.buffer = 0;
69
70 erval = der_encode(td, sptr, ANY__consume_bytes, &arg);
71 if(erval.encoded == -1) {
72 if(arg.buffer) FREEMEM(arg.buffer);
73 return -1;
74 }
Lev Walkina9cc46e2004-09-22 16:06:28 +000075 assert((size_t)erval.encoded == arg.offset);
Lev Walkind563d392004-09-13 08:26:57 +000076
77 if(st->buf) FREEMEM(st->buf);
78 st->buf = arg.buffer;
79 st->size = arg.offset;
80
81 return 0;
82}
83
84ANY_t *
85ANY_new_fromType(asn1_TYPE_descriptor_t *td, void *sptr) {
86 ANY_t tmp;
87 ANY_t *st;
88
89 if(!td || !sptr) {
90 errno = EINVAL;
91 return 0;
92 }
93
94 memset(&tmp, 0, sizeof(tmp));
95
96 if(ANY_fromType(&tmp, td, sptr)) return 0;
97
98 st = (ANY_t *)MALLOC(sizeof(*st));
99 if(st) {
100 *st = tmp;
101 return st;
102 } else {
103 FREEMEM(tmp.buf);
104 return 0;
105 }
106}
107
108int
109ANY_to_type(ANY_t *st, asn1_TYPE_descriptor_t *td, void **struct_ptr) {
110 ber_dec_rval_t rval;
111 void *newst = 0;
112
113 if(!st || !td || !struct_ptr) {
114 errno = EINVAL;
115 return -1;
116 }
117
118 if(st->buf == 0) {
119 /* Nothing to convert, make it empty. */
120 *struct_ptr = (void *)0;
121 return 0;
122 }
123
124 rval = ber_decode(td, (void **)&newst, st->buf, st->size);
125 if(rval.code == RC_OK) {
126 *struct_ptr = newst;
127 return 0;
128 } else {
129 /* Remove possibly partially decoded data. */
130 td->free_struct(td, newst, 0);
131 return -1;
132 }
133}
134
135static int ANY__consume_bytes(const void *buffer, size_t size, void *key) {
136 struct _callback_arg *arg = (struct _callback_arg *)key;
137
138 if((arg->offset + size) >= arg->size) {
139 size_t nsize = (arg->size ? arg->size << 2 : 16) + size;
140 void *p = REALLOC(arg->buffer, nsize);
141 if(!p) return -1;
142 (void *)arg->buffer = p;
143 arg->size = nsize;
144 }
145
146 memcpy(arg->buffer + arg->offset, buffer, size);
147 arg->offset += size;
148 assert(arg->offset < arg->size);
149
150 return 0;
151}
152