blob: 389452cdbac80e38564e9875aeba078fb58ac3ca [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 */
5#include <ANY.h>
6#include <assert.h>
7#include <errno.h>
8
9asn1_TYPE_descriptor_t asn1_DEF_ANY = {
10 "ANY",
11 asn_generic_no_constraint,
12 OCTET_STRING_decode_ber,
13 OCTET_STRING_encode_der,
14 OCTET_STRING_print,
15 OCTET_STRING_free,
16 0, /* Use generic outmost tag fetcher */
Lev Walkind563d392004-09-13 08:26:57 +000017 0, 0, 0, 0,
Lev Walkina737f3b2004-09-02 12:11:47 +000018 -1, /* Both ways are fine (primitive and constructed) */
19 0, 0, /* No members */
20 (void *)1 /* Special indicator that this is an ANY type */
21};
Lev Walkind563d392004-09-13 08:26:57 +000022
23
24struct _callback_arg {
25 uint8_t *buffer;
26 size_t offset;
27 size_t size;
28};
29
30static int ANY__consume_bytes(const void *buffer, size_t size, void *key);
31
32int
33ANY_fromType(ANY_t *st, asn1_TYPE_descriptor_t *td, void *sptr) {
34 struct _callback_arg arg;
35 der_enc_rval_t erval;
36
37 if(!st || !td) {
38 errno = EINVAL;
39 return -1;
40 }
41
42 if(!sptr) {
43 if(st->buf) FREEMEM(st->buf);
44 st->size = 0;
45 return 0;
46 }
47
48 arg.offset = arg.size = 0;
49 arg.buffer = 0;
50
51 erval = der_encode(td, sptr, ANY__consume_bytes, &arg);
52 if(erval.encoded == -1) {
53 if(arg.buffer) FREEMEM(arg.buffer);
54 return -1;
55 }
56 assert(erval.encoded == arg.offset);
57
58 if(st->buf) FREEMEM(st->buf);
59 st->buf = arg.buffer;
60 st->size = arg.offset;
61
62 return 0;
63}
64
65ANY_t *
66ANY_new_fromType(asn1_TYPE_descriptor_t *td, void *sptr) {
67 ANY_t tmp;
68 ANY_t *st;
69
70 if(!td || !sptr) {
71 errno = EINVAL;
72 return 0;
73 }
74
75 memset(&tmp, 0, sizeof(tmp));
76
77 if(ANY_fromType(&tmp, td, sptr)) return 0;
78
79 st = (ANY_t *)MALLOC(sizeof(*st));
80 if(st) {
81 *st = tmp;
82 return st;
83 } else {
84 FREEMEM(tmp.buf);
85 return 0;
86 }
87}
88
89int
90ANY_to_type(ANY_t *st, asn1_TYPE_descriptor_t *td, void **struct_ptr) {
91 ber_dec_rval_t rval;
92 void *newst = 0;
93
94 if(!st || !td || !struct_ptr) {
95 errno = EINVAL;
96 return -1;
97 }
98
99 if(st->buf == 0) {
100 /* Nothing to convert, make it empty. */
101 *struct_ptr = (void *)0;
102 return 0;
103 }
104
105 rval = ber_decode(td, (void **)&newst, st->buf, st->size);
106 if(rval.code == RC_OK) {
107 *struct_ptr = newst;
108 return 0;
109 } else {
110 /* Remove possibly partially decoded data. */
111 td->free_struct(td, newst, 0);
112 return -1;
113 }
114}
115
116static int ANY__consume_bytes(const void *buffer, size_t size, void *key) {
117 struct _callback_arg *arg = (struct _callback_arg *)key;
118
119 if((arg->offset + size) >= arg->size) {
120 size_t nsize = (arg->size ? arg->size << 2 : 16) + size;
121 void *p = REALLOC(arg->buffer, nsize);
122 if(!p) return -1;
123 (void *)arg->buffer = p;
124 arg->size = nsize;
125 }
126
127 memcpy(arg->buffer + arg->offset, buffer, size);
128 arg->offset += size;
129 assert(arg->offset < arg->size);
130
131 return 0;
132}
133