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.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * @file json/json_mhd.c
20 * @brief functions to parse JSON snippets we receive via MHD
21 * @author Florian Dold
22 * @author Benedikt Mueller
23 * @author Christian Grothoff
26 #include "gnunet_json_lib.h"
29 * Initial size for POST request buffers. Should be big enough to
30 * usually not require a reallocation, but not so big that it hurts in
31 * terms of memory use.
33 #define REQUEST_BUFFER_INITIAL (2*1024)
37 * Buffer for POST requests.
47 * Number of valid bytes in buffer.
52 * Number of allocated bytes in buffer.
59 * Initialize a buffer.
61 * @param buf the buffer to initialize
62 * @param data the initial data
63 * @param data_size size of the initial data
64 * @param alloc_size size of the buffer
65 * @param max_size maximum size that the buffer can grow to
66 * @return a GNUnet result code
69 buffer_init (struct Buffer *buf,
75 if ( (data_size > max_size) ||
76 (alloc_size > max_size) )
78 if (data_size > alloc_size)
79 alloc_size = data_size;
80 buf->data = GNUNET_malloc (alloc_size);
81 GNUNET_memcpy (buf->data, data, data_size);
87 * Free the data in a buffer. Does *not* free
88 * the buffer object itself.
90 * @param buf buffer to de-initialize
93 buffer_deinit (struct Buffer *buf)
95 GNUNET_free (buf->data);
101 * Append data to a buffer, growing the buffer if necessary.
103 * @param buf the buffer to append to
104 * @param data the data to append
105 * @param data_size the size of @a data
106 * @param max_size maximum size that the buffer can grow to
107 * @return #GNUNET_OK on success,
108 * #GNUNET_NO if the buffer can't accomodate for the new data
111 buffer_append (struct Buffer *buf,
116 if (buf->fill + data_size > max_size)
118 if (data_size + buf->fill > buf->alloc)
121 size_t new_size = buf->alloc;
122 while (new_size < buf->fill + data_size)
124 if (new_size > max_size)
126 new_buf = GNUNET_malloc (new_size);
127 GNUNET_memcpy (new_buf, buf->data, buf->fill);
128 GNUNET_free (buf->data);
130 buf->alloc = new_size;
132 GNUNET_memcpy (buf->data + buf->fill, data, data_size);
133 buf->fill += data_size;
139 * Process a POST request containing a JSON object. This function
140 * realizes an MHD POST processor that will (incrementally) process
141 * JSON data uploaded to the HTTP server. It will store the required
142 * state in the @a con_cls, which must be cleaned up using
143 * #GNUNET_JSON_post_parser_callback().
145 * @param buffer_max maximum allowed size for the buffer
146 * @param con_cls the closure (will point to a `struct Buffer *`)
147 * @param upload_data the POST data
148 * @param upload_data_size number of bytes in @a upload_data
149 * @param json the JSON object for a completed request
150 * @return result code indicating the status of the operation
152 enum GNUNET_JSON_PostResult
153 GNUNET_JSON_post_parser (size_t buffer_max,
155 const char *upload_data,
156 size_t *upload_data_size,
159 struct Buffer *r = *con_cls;
162 if (NULL == *con_cls)
164 /* We are seeing a fresh POST request. */
165 r = GNUNET_new (struct Buffer);
170 REQUEST_BUFFER_INITIAL,
176 return GNUNET_JSON_PR_OUT_OF_MEMORY;
178 /* everything OK, wait for more POST data */
179 *upload_data_size = 0;
181 return GNUNET_JSON_PR_CONTINUE;
183 if (0 != *upload_data_size)
185 /* We are seeing an old request with more data available. */
193 /* Request too long */
197 return GNUNET_JSON_PR_REQUEST_TOO_LARGE;
199 /* everything OK, wait for more POST data */
200 *upload_data_size = 0;
201 return GNUNET_JSON_PR_CONTINUE;
204 /* We have seen the whole request. */
206 *json = json_loadb (r->data,
212 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
213 "Failed to parse JSON request body\n");
214 return GNUNET_JSON_PR_JSON_INVALID;
220 return GNUNET_JSON_PR_SUCCESS;
225 * Function called whenever we are done with a request
226 * to clean up our state.
228 * @param con_cls value as it was left by
229 * #GNUNET_JSON_post_parser(), to be cleaned up
232 GNUNET_JSON_post_parser_cleanup (void *con_cls)
234 struct Buffer *r = con_cls;
243 /* end of mhd_json.c */