1 /*------------------------------------------------------------------------------
2 *
3 * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4 * The YADIFA TM software product is provided under the BSD 3-clause license:
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of EURid nor the names of its contributors may be
16 * used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 *------------------------------------------------------------------------------
32 *
33 */
34
35 /** @defgroup streaming Streams
36 * @ingroup dnscore
37 * @brief
38 *
39 *
40 *
41 * @{
42 *
43 *----------------------------------------------------------------------------*/
44 #include "dnscore/dnscore-config.h"
45 #include <stdio.h>
46 #include <stdlib.h>
47
48 #include "dnscore/shared-heap.h"
49 #include "dnscore/shared-heap-bytearray-output-stream.h"
50
51 #include "dnscore/zalloc.h"
52
53 #define BYTE_ARRAY_OUTPUT_STREAM_DATA_TAG 0x41544144534f4853 /* SHOSDATA */
54
55 #define SHARED_HEAP_STARTSIZE 48
56
57 typedef struct shared_heap_output_stream_data shared_heap_output_stream_data;
58
59 /**
60 * @NOTE: if this changes, take care that shared_heap_output_stream_context in the header file has at least the SAME SIZE
61 */
62
63 struct shared_heap_output_stream_data
64 {
65 u8* buffer;
66 u32 buffer_size;
67 u32 buffer_offset;
68 u8 flags;
69 u8 id;
70 };
71
72 static ya_result
shared_heap_output_stream_write(output_stream * stream,const u8 * buffer,u32 len)73 shared_heap_output_stream_write(output_stream* stream, const u8* buffer, u32 len)
74 {
75 if(len == 0)
76 {
77 return 0;
78 }
79
80 shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data;
81
82 u32 remaining = data->buffer_size - data->buffer_offset;
83 /*
84 1;48 -> 48
85 49;112 -> 112
86 */
87 if(len > remaining)
88 {
89 /* Either we can resize, either we have to trunk */
90
91 if((data->flags & SHARED_HEAP_DYNAMIC) != 0)
92 {
93 u8* newbuffer;
94 u32 newsize = (((data->buffer_offset + len) + 16 + 63) & ~63) - 16;
95
96 newbuffer = (u8*)shared_heap_wait_alloc(data->id, newsize);
97 MEMCOPY(newbuffer, data->buffer, data->buffer_offset);
98
99 if((data->flags & SHARED_HEAP_OWNED) != 0)
100 {
101 shared_heap_free(data->buffer);
102 }
103
104 data->buffer = newbuffer;
105 data->buffer_size = newsize;
106
107 data->flags |= SHARED_HEAP_OWNED;
108 }
109 else
110 {
111 len = remaining;
112 }
113 }
114
115 MEMCOPY(&data->buffer[data->buffer_offset], buffer, len);
116 data->buffer_offset += len;
117
118 return len;
119 }
120
121 static ya_result
shared_heap_output_stream_flush(output_stream * stream)122 shared_heap_output_stream_flush(output_stream* stream)
123 {
124 (void)stream;
125 return SUCCESS;
126 }
127
128 static void
shared_heap_output_stream_close(output_stream * stream)129 shared_heap_output_stream_close(output_stream* stream)
130 {
131 shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data;
132
133 if((data->flags & SHARED_HEAP_OWNED) != 0)
134 {
135 #if DEBUG
136 memset(data->buffer, 0xe5, data->buffer_size);
137 #endif
138 shared_heap_free(data->buffer);
139 }
140
141 if((data->flags & SHARED_HEAP_ZALLOC_CONTEXT) != 0)
142 {
143 ZFREE_OBJECT(data);
144 }
145
146 output_stream_set_void(stream);
147 }
148
149 static const output_stream_vtbl shared_heap_output_stream_vtbl =
150 {
151 shared_heap_output_stream_write,
152 shared_heap_output_stream_flush,
153 shared_heap_output_stream_close,
154 "shared_heap_output_stream",
155 };
156
157 void
shared_heap_output_stream_init_ex_static(output_stream * out_stream,u8 id,u8 * array,u32 size,u8 flags,shared_heap_output_stream_context * ctx)158 shared_heap_output_stream_init_ex_static(output_stream* out_stream, u8 id, u8* array,u32 size, u8 flags, shared_heap_output_stream_context *ctx)
159 {
160 shared_heap_output_stream_data *data = (shared_heap_output_stream_data*)ctx;
161
162 if(array == NULL)
163 {
164 flags |= SHARED_HEAP_OWNED;
165
166 if(size == 0)
167 {
168 flags |= SHARED_HEAP_DYNAMIC;
169
170 size = SHARED_HEAP_STARTSIZE;
171 }
172 else
173 {
174 // size = ((size + 63) & ~63) - 16;
175 }
176
177 array = (u8*)shared_heap_wait_alloc(id, size);
178 }
179
180 data->buffer = array;
181 data->buffer_size = size;
182 data->buffer_offset = 0;
183 data->flags = flags;
184 data->id = id;
185
186 out_stream->data = data;
187 out_stream->vtbl = &shared_heap_output_stream_vtbl;
188 }
189
190 void
shared_heap_output_stream_try_init_ex_static(output_stream * out_stream,u8 id,u8 * array,u32 size,u8 flags,shared_heap_output_stream_context * ctx)191 shared_heap_output_stream_try_init_ex_static(output_stream* out_stream, u8 id, u8* array,u32 size, u8 flags, shared_heap_output_stream_context *ctx)
192 {
193 shared_heap_output_stream_data *data = (shared_heap_output_stream_data*)ctx;
194
195 if(array == NULL)
196 {
197 flags |= SHARED_HEAP_OWNED;
198
199 if(size == 0)
200 {
201 flags |= SHARED_HEAP_DYNAMIC;
202
203 size = SHARED_HEAP_STARTSIZE;
204 }
205 else
206 {
207 // size = ((size + 63) & ~63) - 16;
208 }
209
210 array = (u8*)shared_heap_try_alloc(id, size);
211 }
212
213 data->buffer = array;
214 data->buffer_size = size;
215 data->buffer_offset = 0;
216 data->flags = flags;
217 data->id = id;
218
219 out_stream->data = data;
220 out_stream->vtbl = &shared_heap_output_stream_vtbl;
221 }
222
223 void
shared_heap_output_stream_init_ex(output_stream * out_stream,u8 id,u8 * array,u32 size,u8 flags)224 shared_heap_output_stream_init_ex(output_stream* out_stream, u8 id, u8* array, u32 size, u8 flags)
225 {
226 shared_heap_output_stream_data* data;
227
228 ZALLOC_OBJECT_OR_DIE( data, shared_heap_output_stream_data, BYTE_ARRAY_OUTPUT_STREAM_DATA_TAG);
229
230 array = (u8*)shared_heap_wait_alloc(id, size);
231 flags |= SHARED_HEAP_ZALLOC_CONTEXT;
232
233 shared_heap_output_stream_init_ex_static(out_stream, id, array, size, flags, (shared_heap_output_stream_context*)data);
234 }
235
236 void
shared_heap_output_stream_init(output_stream * out_stream,u8 id,u8 * array,u32 size)237 shared_heap_output_stream_init(output_stream* out_stream, u8 id, u8* array, u32 size)
238 {
239 shared_heap_output_stream_init_ex(out_stream, id, array, size, 0);
240 }
241
242 void
shared_heap_output_stream_reset(output_stream * stream)243 shared_heap_output_stream_reset(output_stream* stream)
244 {
245 shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data;
246 data->buffer_offset = 0;
247 }
248
249 u32
shared_heap_output_stream_size(output_stream * stream)250 shared_heap_output_stream_size(output_stream* stream)
251 {
252 shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data;
253 return data->buffer_offset;
254 }
255
256 u32
shared_heap_output_stream_buffer_size(output_stream * stream)257 shared_heap_output_stream_buffer_size(output_stream* stream)
258 {
259 shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data;
260 return data->buffer_size;
261 }
262
263 u8*
shared_heap_output_stream_buffer(output_stream * stream)264 shared_heap_output_stream_buffer(output_stream* stream)
265 {
266 shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data;
267
268 return data->buffer;
269 }
270
271 u8*
shared_heap_output_stream_detach(output_stream * stream)272 shared_heap_output_stream_detach(output_stream* stream)
273 {
274 shared_heap_output_stream_data* data = (shared_heap_output_stream_data*)stream->data;
275
276 data->flags &= ~SHARED_HEAP_OWNED;
277
278 return data->buffer;
279 }
280
281
282
283 /** @} */
284