2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
16 * @file json/json_mhd.c
17 * @brief functions to parse JSON snippets we receive via MHD
18 * @author Florian Dold
19 * @author Benedikt Mueller
20 * @author Christian Grothoff
23 #include "gnunet_json_lib.h"
26 * Initial size for POST request buffers. Should be big enough to
27 * usually not require a reallocation, but not so big that it hurts in
28 * terms of memory use.
30 #define REQUEST_BUFFER_INITIAL (2*1024)
34 * Buffer for POST requests.
44 * Number of valid bytes in buffer.
49 * Number of allocated bytes in buffer.
56 * Initialize a buffer.
58 * @param buf the buffer to initialize
59 * @param data the initial data
60 * @param data_size size of the initial data
61 * @param alloc_size size of the buffer
62 * @param max_size maximum size that the buffer can grow to
63 * @return a GNUnet result code
66 buffer_init (struct Buffer *buf,
72 if ( (data_size > max_size) ||
73 (alloc_size > max_size) )
75 if (data_size > alloc_size)
76 alloc_size = data_size;
77 buf->data = GNUNET_malloc (alloc_size);
78 GNUNET_memcpy (buf->data, data, data_size);
84 * Free the data in a buffer. Does *not* free
85 * the buffer object itself.
87 * @param buf buffer to de-initialize
90 buffer_deinit (struct Buffer *buf)
92 GNUNET_free (buf->data);
98 * Append data to a buffer, growing the buffer if necessary.
100 * @param buf the buffer to append to
101 * @param data the data to append
102 * @param data_size the size of @a data
103 * @param max_size maximum size that the buffer can grow to
104 * @return #GNUNET_OK on success,
105 * #GNUNET_NO if the buffer can't accomodate for the new data
108 buffer_append (struct Buffer *buf,
113 if (buf->fill + data_size > max_size)
115 if (data_size + buf->fill > buf->alloc)
118 size_t new_size = buf->alloc;
119 while (new_size < buf->fill + data_size)
121 if (new_size > max_size)
123 new_buf = GNUNET_malloc (new_size);
124 GNUNET_memcpy (new_buf, buf->data, buf->fill);
125 GNUNET_free (buf->data);
127 buf->alloc = new_size;
129 GNUNET_memcpy (buf->data + buf->fill, data, data_size);
130 buf->fill += data_size;
136 * Process a POST request containing a JSON object. This function
137 * realizes an MHD POST processor that will (incrementally) process
138 * JSON data uploaded to the HTTP server. It will store the required
139 * state in the @a con_cls, which must be cleaned up using
140 * #GNUNET_JSON_post_parser_callback().
142 * @param buffer_max maximum allowed size for the buffer
143 * @param con_cls the closure (will point to a `struct Buffer *`)
144 * @param upload_data the POST data
145 * @param upload_data_size number of bytes in @a upload_data
146 * @param json the JSON object for a completed request
147 * @return result code indicating the status of the operation
149 enum GNUNET_JSON_PostResult
150 GNUNET_JSON_post_parser (size_t buffer_max,
152 const char *upload_data,
153 size_t *upload_data_size,
156 struct Buffer *r = *con_cls;
159 if (NULL == *con_cls)
161 /* We are seeing a fresh POST request. */
162 r = GNUNET_new (struct Buffer);
167 REQUEST_BUFFER_INITIAL,
173 return GNUNET_JSON_PR_OUT_OF_MEMORY;
175 /* everything OK, wait for more POST data */
176 *upload_data_size = 0;
178 return GNUNET_JSON_PR_CONTINUE;
180 if (0 != *upload_data_size)
182 /* We are seeing an old request with more data available. */
190 /* Request too long */
194 return GNUNET_JSON_PR_REQUEST_TOO_LARGE;
196 /* everything OK, wait for more POST data */
197 *upload_data_size = 0;
198 return GNUNET_JSON_PR_CONTINUE;
201 /* We have seen the whole request. */
203 *json = json_loadb (r->data,
209 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
210 "Failed to parse JSON request body\n");
211 return GNUNET_JSON_PR_JSON_INVALID;
217 return GNUNET_JSON_PR_SUCCESS;
222 * Function called whenever we are done with a request
223 * to clean up our state.
225 * @param con_cls value as it was left by
226 * #GNUNET_JSON_post_parser(), to be cleaned up
229 GNUNET_JSON_post_parser_cleanup (void *con_cls)
231 struct Buffer *r = con_cls;
240 /* end of mhd_json.c */