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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
21 * @file json/json_mhd.c
22 * @brief functions to parse JSON snippets we receive via MHD
23 * @author Florian Dold
24 * @author Benedikt Mueller
25 * @author Christian Grothoff
28 #include "gnunet_json_lib.h"
31 * Initial size for POST request buffers. Should be big enough to
32 * usually not require a reallocation, but not so big that it hurts in
33 * terms of memory use.
35 #define REQUEST_BUFFER_INITIAL (2*1024)
39 * Buffer for POST requests.
49 * Number of valid bytes in buffer.
54 * Number of allocated bytes in buffer.
61 * Initialize a buffer.
63 * @param buf the buffer to initialize
64 * @param data the initial data
65 * @param data_size size of the initial data
66 * @param alloc_size size of the buffer
67 * @param max_size maximum size that the buffer can grow to
68 * @return a GNUnet result code
71 buffer_init (struct Buffer *buf,
77 if ( (data_size > max_size) ||
78 (alloc_size > max_size) )
80 if (data_size > alloc_size)
81 alloc_size = data_size;
82 buf->data = GNUNET_malloc (alloc_size);
83 GNUNET_memcpy (buf->data, data, data_size);
89 * Free the data in a buffer. Does *not* free
90 * the buffer object itself.
92 * @param buf buffer to de-initialize
95 buffer_deinit (struct Buffer *buf)
97 GNUNET_free (buf->data);
103 * Append data to a buffer, growing the buffer if necessary.
105 * @param buf the buffer to append to
106 * @param data the data to append
107 * @param data_size the size of @a data
108 * @param max_size maximum size that the buffer can grow to
109 * @return #GNUNET_OK on success,
110 * #GNUNET_NO if the buffer can't accomodate for the new data
113 buffer_append (struct Buffer *buf,
118 if (buf->fill + data_size > max_size)
120 if (data_size + buf->fill > buf->alloc)
123 size_t new_size = buf->alloc;
124 while (new_size < buf->fill + data_size)
126 if (new_size > max_size)
128 new_buf = GNUNET_malloc (new_size);
129 GNUNET_memcpy (new_buf, buf->data, buf->fill);
130 GNUNET_free (buf->data);
132 buf->alloc = new_size;
134 GNUNET_memcpy (buf->data + buf->fill, data, data_size);
135 buf->fill += data_size;
141 * Process a POST request containing a JSON object. This function
142 * realizes an MHD POST processor that will (incrementally) process
143 * JSON data uploaded to the HTTP server. It will store the required
144 * state in the @a con_cls, which must be cleaned up using
145 * #GNUNET_JSON_post_parser_callback().
147 * @param buffer_max maximum allowed size for the buffer
148 * @param con_cls the closure (will point to a `struct Buffer *`)
149 * @param upload_data the POST data
150 * @param upload_data_size number of bytes in @a upload_data
151 * @param json the JSON object for a completed request
152 * @return result code indicating the status of the operation
154 enum GNUNET_JSON_PostResult
155 GNUNET_JSON_post_parser (size_t buffer_max,
157 const char *upload_data,
158 size_t *upload_data_size,
161 struct Buffer *r = *con_cls;
164 if (NULL == *con_cls)
166 /* We are seeing a fresh POST request. */
167 r = GNUNET_new (struct Buffer);
172 REQUEST_BUFFER_INITIAL,
178 return GNUNET_JSON_PR_OUT_OF_MEMORY;
180 /* everything OK, wait for more POST data */
181 *upload_data_size = 0;
183 return GNUNET_JSON_PR_CONTINUE;
185 if (0 != *upload_data_size)
187 /* We are seeing an old request with more data available. */
195 /* Request too long */
199 return GNUNET_JSON_PR_REQUEST_TOO_LARGE;
201 /* everything OK, wait for more POST data */
202 *upload_data_size = 0;
203 return GNUNET_JSON_PR_CONTINUE;
206 /* We have seen the whole request. */
208 *json = json_loadb (r->data,
214 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
215 "Failed to parse JSON request body\n");
216 return GNUNET_JSON_PR_JSON_INVALID;
222 return GNUNET_JSON_PR_SUCCESS;
227 * Function called whenever we are done with a request
228 * to clean up our state.
230 * @param con_cls value as it was left by
231 * #GNUNET_JSON_post_parser(), to be cleaned up
234 GNUNET_JSON_post_parser_cleanup (void *con_cls)
236 struct Buffer *r = con_cls;
245 /* end of mhd_json.c */