diff options
Diffstat (limited to 'src/json/json_mhd.c')
-rw-r--r-- | src/json/json_mhd.c | 331 |
1 files changed, 166 insertions, 165 deletions
diff --git a/src/json/json_mhd.c b/src/json/json_mhd.c index 0b4dcfee8..602a15b7a 100644 --- a/src/json/json_mhd.c +++ b/src/json/json_mhd.c | |||
@@ -40,7 +40,8 @@ | |||
40 | /** | 40 | /** |
41 | * Buffer for POST requests. | 41 | * Buffer for POST requests. |
42 | */ | 42 | */ |
43 | struct Buffer { | 43 | struct Buffer |
44 | { | ||
44 | /** | 45 | /** |
45 | * Allocated memory | 46 | * Allocated memory |
46 | */ | 47 | */ |
@@ -74,19 +75,19 @@ struct Buffer { | |||
74 | * @return a GNUnet result code | 75 | * @return a GNUnet result code |
75 | */ | 76 | */ |
76 | static int | 77 | static int |
77 | buffer_init(struct Buffer *buf, | 78 | buffer_init (struct Buffer *buf, |
78 | const void *data, | 79 | const void *data, |
79 | size_t data_size, | 80 | size_t data_size, |
80 | size_t alloc_size, | 81 | size_t alloc_size, |
81 | size_t max_size) | 82 | size_t max_size) |
82 | { | 83 | { |
83 | if ((data_size > max_size) || (alloc_size > max_size)) | 84 | if ((data_size > max_size) || (alloc_size > max_size)) |
84 | return GNUNET_SYSERR; | 85 | return GNUNET_SYSERR; |
85 | if (data_size > alloc_size) | 86 | if (data_size > alloc_size) |
86 | alloc_size = data_size; | 87 | alloc_size = data_size; |
87 | buf->data = GNUNET_malloc(alloc_size); | 88 | buf->data = GNUNET_malloc (alloc_size); |
88 | buf->alloc = alloc_size; | 89 | buf->alloc = alloc_size; |
89 | GNUNET_memcpy(buf->data, data, data_size); | 90 | GNUNET_memcpy (buf->data, data, data_size); |
90 | buf->fill = data_size; | 91 | buf->fill = data_size; |
91 | buf->max = max_size; | 92 | buf->max = max_size; |
92 | return GNUNET_OK; | 93 | return GNUNET_OK; |
@@ -100,9 +101,9 @@ buffer_init(struct Buffer *buf, | |||
100 | * @param buf buffer to de-initialize | 101 | * @param buf buffer to de-initialize |
101 | */ | 102 | */ |
102 | static void | 103 | static void |
103 | buffer_deinit(struct Buffer *buf) | 104 | buffer_deinit (struct Buffer *buf) |
104 | { | 105 | { |
105 | GNUNET_free(buf->data); | 106 | GNUNET_free (buf->data); |
106 | buf->data = NULL; | 107 | buf->data = NULL; |
107 | } | 108 | } |
108 | 109 | ||
@@ -118,28 +119,28 @@ buffer_deinit(struct Buffer *buf) | |||
118 | * #GNUNET_NO if the buffer can't accomodate for the new data | 119 | * #GNUNET_NO if the buffer can't accomodate for the new data |
119 | */ | 120 | */ |
120 | static int | 121 | static int |
121 | buffer_append(struct Buffer *buf, | 122 | buffer_append (struct Buffer *buf, |
122 | const void *data, | 123 | const void *data, |
123 | size_t data_size, | 124 | size_t data_size, |
124 | size_t max_size) | 125 | size_t max_size) |
125 | { | 126 | { |
126 | if (buf->fill + data_size > max_size) | 127 | if (buf->fill + data_size > max_size) |
127 | return GNUNET_NO; | 128 | return GNUNET_NO; |
128 | if (buf->fill + data_size > buf->alloc) | 129 | if (buf->fill + data_size > buf->alloc) |
129 | { | 130 | { |
130 | char *new_buf; | 131 | char *new_buf; |
131 | size_t new_size = buf->alloc; | 132 | size_t new_size = buf->alloc; |
132 | while (new_size < buf->fill + data_size) | 133 | while (new_size < buf->fill + data_size) |
133 | new_size += 2; | 134 | new_size += 2; |
134 | if (new_size > max_size) | 135 | if (new_size > max_size) |
135 | return GNUNET_NO; | 136 | return GNUNET_NO; |
136 | new_buf = GNUNET_malloc(new_size); | 137 | new_buf = GNUNET_malloc (new_size); |
137 | GNUNET_memcpy(new_buf, buf->data, buf->fill); | 138 | GNUNET_memcpy (new_buf, buf->data, buf->fill); |
138 | GNUNET_free(buf->data); | 139 | GNUNET_free (buf->data); |
139 | buf->data = new_buf; | 140 | buf->data = new_buf; |
140 | buf->alloc = new_size; | 141 | buf->alloc = new_size; |
141 | } | 142 | } |
142 | GNUNET_memcpy(buf->data + buf->fill, data, data_size); | 143 | GNUNET_memcpy (buf->data + buf->fill, data, data_size); |
143 | buf->fill += data_size; | 144 | buf->fill += data_size; |
144 | return GNUNET_OK; | 145 | return GNUNET_OK; |
145 | } | 146 | } |
@@ -152,95 +153,95 @@ buffer_append(struct Buffer *buf, | |||
152 | * @return result code indicating the status of the operation | 153 | * @return result code indicating the status of the operation |
153 | */ | 154 | */ |
154 | static enum GNUNET_JSON_PostResult | 155 | static enum GNUNET_JSON_PostResult |
155 | inflate_data(struct Buffer *buf) | 156 | inflate_data (struct Buffer *buf) |
156 | { | 157 | { |
157 | z_stream z; | 158 | z_stream z; |
158 | char *tmp; | 159 | char *tmp; |
159 | size_t tmp_size; | 160 | size_t tmp_size; |
160 | int ret; | 161 | int ret; |
161 | 162 | ||
162 | memset(&z, 0, sizeof(z)); | 163 | memset (&z, 0, sizeof(z)); |
163 | z.next_in = (Bytef *)buf->data; | 164 | z.next_in = (Bytef *) buf->data; |
164 | z.avail_in = buf->fill; | 165 | z.avail_in = buf->fill; |
165 | tmp_size = GNUNET_MIN(buf->max, buf->fill * 4); | 166 | tmp_size = GNUNET_MIN (buf->max, buf->fill * 4); |
166 | tmp = GNUNET_malloc(tmp_size); | 167 | tmp = GNUNET_malloc (tmp_size); |
167 | z.next_out = (Bytef *)tmp; | 168 | z.next_out = (Bytef *) tmp; |
168 | z.avail_out = tmp_size; | 169 | z.avail_out = tmp_size; |
169 | ret = inflateInit(&z); | 170 | ret = inflateInit (&z); |
170 | switch (ret) | 171 | switch (ret) |
172 | { | ||
173 | case Z_MEM_ERROR: | ||
174 | GNUNET_break (0); | ||
175 | return GNUNET_JSON_PR_OUT_OF_MEMORY; | ||
176 | |||
177 | case Z_STREAM_ERROR: | ||
178 | GNUNET_break_op (0); | ||
179 | return GNUNET_JSON_PR_JSON_INVALID; | ||
180 | |||
181 | case Z_OK: | ||
182 | break; | ||
183 | } | ||
184 | while (1) | ||
185 | { | ||
186 | ret = inflate (&z, 0); | ||
187 | switch (ret) | ||
171 | { | 188 | { |
172 | case Z_MEM_ERROR: | 189 | case Z_MEM_ERROR: |
173 | GNUNET_break(0); | 190 | GNUNET_break (0); |
191 | GNUNET_break (Z_OK == inflateEnd (&z)); | ||
192 | GNUNET_free (tmp); | ||
174 | return GNUNET_JSON_PR_OUT_OF_MEMORY; | 193 | return GNUNET_JSON_PR_OUT_OF_MEMORY; |
175 | 194 | ||
176 | case Z_STREAM_ERROR: | 195 | case Z_DATA_ERROR: |
177 | GNUNET_break_op(0); | 196 | GNUNET_break (0); |
197 | GNUNET_break (Z_OK == inflateEnd (&z)); | ||
198 | GNUNET_free (tmp); | ||
199 | return GNUNET_JSON_PR_JSON_INVALID; | ||
200 | |||
201 | case Z_NEED_DICT: | ||
202 | GNUNET_break (0); | ||
203 | GNUNET_break (Z_OK == inflateEnd (&z)); | ||
204 | GNUNET_free (tmp); | ||
178 | return GNUNET_JSON_PR_JSON_INVALID; | 205 | return GNUNET_JSON_PR_JSON_INVALID; |
179 | 206 | ||
180 | case Z_OK: | 207 | case Z_OK: |
181 | break; | 208 | if ((0 < z.avail_out) && (0 == z.avail_in)) |
209 | { | ||
210 | /* truncated input stream */ | ||
211 | GNUNET_break (0); | ||
212 | GNUNET_break (Z_OK == inflateEnd (&z)); | ||
213 | GNUNET_free (tmp); | ||
214 | return GNUNET_JSON_PR_JSON_INVALID; | ||
215 | } | ||
216 | if (0 < z.avail_out) | ||
217 | continue; /* just call it again */ | ||
218 | /* output buffer full, can we grow it? */ | ||
219 | if (tmp_size == buf->max) | ||
220 | { | ||
221 | /* already at max */ | ||
222 | GNUNET_break (0); | ||
223 | GNUNET_break (Z_OK == inflateEnd (&z)); | ||
224 | GNUNET_free (tmp); | ||
225 | return GNUNET_JSON_PR_OUT_OF_MEMORY; | ||
226 | } | ||
227 | if (tmp_size * 2 < tmp_size) | ||
228 | tmp_size = buf->max; | ||
229 | else | ||
230 | tmp_size = GNUNET_MIN (buf->max, tmp_size * 2); | ||
231 | tmp = GNUNET_realloc (tmp, tmp_size); | ||
232 | z.next_out = (Bytef *) &tmp[z.total_out]; | ||
233 | continue; | ||
234 | |||
235 | case Z_STREAM_END: | ||
236 | /* decompression successful, make 'tmp' the new 'data' */ | ||
237 | GNUNET_free (buf->data); | ||
238 | buf->data = tmp; | ||
239 | buf->alloc = tmp_size; | ||
240 | buf->fill = z.total_out; | ||
241 | GNUNET_break (Z_OK == inflateEnd (&z)); | ||
242 | return GNUNET_JSON_PR_SUCCESS; /* at least for now */ | ||
182 | } | 243 | } |
183 | while (1) | 244 | } /* while (1) */ |
184 | { | ||
185 | ret = inflate(&z, 0); | ||
186 | switch (ret) | ||
187 | { | ||
188 | case Z_MEM_ERROR: | ||
189 | GNUNET_break(0); | ||
190 | GNUNET_break(Z_OK == inflateEnd(&z)); | ||
191 | GNUNET_free(tmp); | ||
192 | return GNUNET_JSON_PR_OUT_OF_MEMORY; | ||
193 | |||
194 | case Z_DATA_ERROR: | ||
195 | GNUNET_break(0); | ||
196 | GNUNET_break(Z_OK == inflateEnd(&z)); | ||
197 | GNUNET_free(tmp); | ||
198 | return GNUNET_JSON_PR_JSON_INVALID; | ||
199 | |||
200 | case Z_NEED_DICT: | ||
201 | GNUNET_break(0); | ||
202 | GNUNET_break(Z_OK == inflateEnd(&z)); | ||
203 | GNUNET_free(tmp); | ||
204 | return GNUNET_JSON_PR_JSON_INVALID; | ||
205 | |||
206 | case Z_OK: | ||
207 | if ((0 < z.avail_out) && (0 == z.avail_in)) | ||
208 | { | ||
209 | /* truncated input stream */ | ||
210 | GNUNET_break(0); | ||
211 | GNUNET_break(Z_OK == inflateEnd(&z)); | ||
212 | GNUNET_free(tmp); | ||
213 | return GNUNET_JSON_PR_JSON_INVALID; | ||
214 | } | ||
215 | if (0 < z.avail_out) | ||
216 | continue; /* just call it again */ | ||
217 | /* output buffer full, can we grow it? */ | ||
218 | if (tmp_size == buf->max) | ||
219 | { | ||
220 | /* already at max */ | ||
221 | GNUNET_break(0); | ||
222 | GNUNET_break(Z_OK == inflateEnd(&z)); | ||
223 | GNUNET_free(tmp); | ||
224 | return GNUNET_JSON_PR_OUT_OF_MEMORY; | ||
225 | } | ||
226 | if (tmp_size * 2 < tmp_size) | ||
227 | tmp_size = buf->max; | ||
228 | else | ||
229 | tmp_size = GNUNET_MIN(buf->max, tmp_size * 2); | ||
230 | tmp = GNUNET_realloc(tmp, tmp_size); | ||
231 | z.next_out = (Bytef *)&tmp[z.total_out]; | ||
232 | continue; | ||
233 | |||
234 | case Z_STREAM_END: | ||
235 | /* decompression successful, make 'tmp' the new 'data' */ | ||
236 | GNUNET_free(buf->data); | ||
237 | buf->data = tmp; | ||
238 | buf->alloc = tmp_size; | ||
239 | buf->fill = z.total_out; | ||
240 | GNUNET_break(Z_OK == inflateEnd(&z)); | ||
241 | return GNUNET_JSON_PR_SUCCESS; /* at least for now */ | ||
242 | } | ||
243 | } /* while (1) */ | ||
244 | } | 245 | } |
245 | 246 | ||
246 | 247 | ||
@@ -260,12 +261,12 @@ inflate_data(struct Buffer *buf) | |||
260 | * @return result code indicating the status of the operation | 261 | * @return result code indicating the status of the operation |
261 | */ | 262 | */ |
262 | enum GNUNET_JSON_PostResult | 263 | enum GNUNET_JSON_PostResult |
263 | GNUNET_JSON_post_parser(size_t buffer_max, | 264 | GNUNET_JSON_post_parser (size_t buffer_max, |
264 | struct MHD_Connection *connection, | 265 | struct MHD_Connection *connection, |
265 | void **con_cls, | 266 | void **con_cls, |
266 | const char *upload_data, | 267 | const char *upload_data, |
267 | size_t *upload_data_size, | 268 | size_t *upload_data_size, |
268 | json_t **json) | 269 | json_t **json) |
269 | { | 270 | { |
270 | struct Buffer *r = *con_cls; | 271 | struct Buffer *r = *con_cls; |
271 | const char *ce; | 272 | const char *ce; |
@@ -273,71 +274,71 @@ GNUNET_JSON_post_parser(size_t buffer_max, | |||
273 | 274 | ||
274 | *json = NULL; | 275 | *json = NULL; |
275 | if (NULL == *con_cls) | 276 | if (NULL == *con_cls) |
277 | { | ||
278 | /* We are seeing a fresh POST request. */ | ||
279 | r = GNUNET_new (struct Buffer); | ||
280 | if (GNUNET_OK != buffer_init (r, | ||
281 | upload_data, | ||
282 | *upload_data_size, | ||
283 | REQUEST_BUFFER_INITIAL, | ||
284 | buffer_max)) | ||
276 | { | 285 | { |
277 | /* We are seeing a fresh POST request. */ | 286 | *con_cls = NULL; |
278 | r = GNUNET_new(struct Buffer); | 287 | buffer_deinit (r); |
279 | if (GNUNET_OK != buffer_init(r, | 288 | GNUNET_free (r); |
280 | upload_data, | 289 | return GNUNET_JSON_PR_OUT_OF_MEMORY; |
281 | *upload_data_size, | ||
282 | REQUEST_BUFFER_INITIAL, | ||
283 | buffer_max)) | ||
284 | { | ||
285 | *con_cls = NULL; | ||
286 | buffer_deinit(r); | ||
287 | GNUNET_free(r); | ||
288 | return GNUNET_JSON_PR_OUT_OF_MEMORY; | ||
289 | } | ||
290 | /* everything OK, wait for more POST data */ | ||
291 | *upload_data_size = 0; | ||
292 | *con_cls = r; | ||
293 | return GNUNET_JSON_PR_CONTINUE; | ||
294 | } | 290 | } |
291 | /* everything OK, wait for more POST data */ | ||
292 | *upload_data_size = 0; | ||
293 | *con_cls = r; | ||
294 | return GNUNET_JSON_PR_CONTINUE; | ||
295 | } | ||
295 | if (0 != *upload_data_size) | 296 | if (0 != *upload_data_size) |
297 | { | ||
298 | /* We are seeing an old request with more data available. */ | ||
299 | |||
300 | if (GNUNET_OK != | ||
301 | buffer_append (r, upload_data, *upload_data_size, buffer_max)) | ||
296 | { | 302 | { |
297 | /* We are seeing an old request with more data available. */ | 303 | /* Request too long */ |
298 | 304 | *con_cls = NULL; | |
299 | if (GNUNET_OK != | 305 | buffer_deinit (r); |
300 | buffer_append(r, upload_data, *upload_data_size, buffer_max)) | 306 | GNUNET_free (r); |
301 | { | 307 | return GNUNET_JSON_PR_REQUEST_TOO_LARGE; |
302 | /* Request too long */ | ||
303 | *con_cls = NULL; | ||
304 | buffer_deinit(r); | ||
305 | GNUNET_free(r); | ||
306 | return GNUNET_JSON_PR_REQUEST_TOO_LARGE; | ||
307 | } | ||
308 | /* everything OK, wait for more POST data */ | ||
309 | *upload_data_size = 0; | ||
310 | return GNUNET_JSON_PR_CONTINUE; | ||
311 | } | 308 | } |
309 | /* everything OK, wait for more POST data */ | ||
310 | *upload_data_size = 0; | ||
311 | return GNUNET_JSON_PR_CONTINUE; | ||
312 | } | ||
312 | 313 | ||
313 | /* We have seen the whole request. */ | 314 | /* We have seen the whole request. */ |
314 | ce = MHD_lookup_connection_value(connection, | 315 | ce = MHD_lookup_connection_value (connection, |
315 | MHD_HEADER_KIND, | 316 | MHD_HEADER_KIND, |
316 | MHD_HTTP_HEADER_CONTENT_ENCODING); | 317 | MHD_HTTP_HEADER_CONTENT_ENCODING); |
317 | if ((NULL != ce) && (0 == strcasecmp("deflate", ce))) | 318 | if ((NULL != ce) && (0 == strcasecmp ("deflate", ce))) |
319 | { | ||
320 | ret = inflate_data (r); | ||
321 | if (GNUNET_JSON_PR_SUCCESS != ret) | ||
318 | { | 322 | { |
319 | ret = inflate_data(r); | 323 | buffer_deinit (r); |
320 | if (GNUNET_JSON_PR_SUCCESS != ret) | 324 | GNUNET_free (r); |
321 | { | 325 | *con_cls = NULL; |
322 | buffer_deinit(r); | 326 | return ret; |
323 | GNUNET_free(r); | ||
324 | *con_cls = NULL; | ||
325 | return ret; | ||
326 | } | ||
327 | } | 327 | } |
328 | } | ||
328 | 329 | ||
329 | *json = json_loadb(r->data, r->fill, 0, NULL); | 330 | *json = json_loadb (r->data, r->fill, 0, NULL); |
330 | if (NULL == *json) | 331 | if (NULL == *json) |
331 | { | 332 | { |
332 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, | 333 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
333 | "Failed to parse JSON request body\n"); | 334 | "Failed to parse JSON request body\n"); |
334 | buffer_deinit(r); | 335 | buffer_deinit (r); |
335 | GNUNET_free(r); | 336 | GNUNET_free (r); |
336 | *con_cls = NULL; | 337 | *con_cls = NULL; |
337 | return GNUNET_JSON_PR_JSON_INVALID; | 338 | return GNUNET_JSON_PR_JSON_INVALID; |
338 | } | 339 | } |
339 | buffer_deinit(r); | 340 | buffer_deinit (r); |
340 | GNUNET_free(r); | 341 | GNUNET_free (r); |
341 | *con_cls = NULL; | 342 | *con_cls = NULL; |
342 | 343 | ||
343 | return GNUNET_JSON_PR_SUCCESS; | 344 | return GNUNET_JSON_PR_SUCCESS; |
@@ -352,15 +353,15 @@ GNUNET_JSON_post_parser(size_t buffer_max, | |||
352 | * #GNUNET_JSON_post_parser(), to be cleaned up | 353 | * #GNUNET_JSON_post_parser(), to be cleaned up |
353 | */ | 354 | */ |
354 | void | 355 | void |
355 | GNUNET_JSON_post_parser_cleanup(void *con_cls) | 356 | GNUNET_JSON_post_parser_cleanup (void *con_cls) |
356 | { | 357 | { |
357 | struct Buffer *r = con_cls; | 358 | struct Buffer *r = con_cls; |
358 | 359 | ||
359 | if (NULL != r) | 360 | if (NULL != r) |
360 | { | 361 | { |
361 | buffer_deinit(r); | 362 | buffer_deinit (r); |
362 | GNUNET_free(r); | 363 | GNUNET_free (r); |
363 | } | 364 | } |
364 | } | 365 | } |
365 | 366 | ||
366 | /* end of mhd_json.c */ | 367 | /* end of mhd_json.c */ |