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 under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
17 * @file json/mhd_json.c
18 * @brief functions to parse JSON snippets we receive via MHD
19 * @author Florian Dold
20 * @author Benedikt Mueller
21 * @author Christian Grothoff
24 #include "gnunet_json_lib.h"
27 * Initial size for POST request buffers. Should be big enough to
28 * usually not require a reallocation, but not so big that it hurts in
29 * terms of memory use.
31 #define REQUEST_BUFFER_INITIAL (2*1024)
35 * Buffer for POST requests.
45 * Number of valid bytes in buffer.
50 * Number of allocated bytes in buffer.
57 * Initialize a buffer.
59 * @param buf the buffer to initialize
60 * @param data the initial data
61 * @param data_size size of the initial data
62 * @param alloc_size size of the buffer
63 * @param max_size maximum size that the buffer can grow to
64 * @return a GNUnet result code
67 buffer_init (struct Buffer *buf,
73 if ( (data_size > max_size) ||
74 (alloc_size > max_size) )
76 if (data_size > alloc_size)
77 alloc_size = data_size;
78 buf->data = GNUNET_malloc (alloc_size);
79 GNUNET_memcpy (buf->data, data, data_size);
85 * Free the data in a buffer. Does *not* free
86 * the buffer object itself.
88 * @param buf buffer to de-initialize
91 buffer_deinit (struct Buffer *buf)
93 GNUNET_free (buf->data);
99 * Append data to a buffer, growing the buffer if necessary.
101 * @param buf the buffer to append to
102 * @param data the data to append
103 * @param data_size the size of @a data
104 * @param max_size maximum size that the buffer can grow to
105 * @return #GNUNET_OK on success,
106 * #GNUNET_NO if the buffer can't accomodate for the new data
109 buffer_append (struct Buffer *buf,
114 if (buf->fill + data_size > max_size)
116 if (data_size + buf->fill > buf->alloc)
119 size_t new_size = buf->alloc;
120 while (new_size < buf->fill + data_size)
122 if (new_size > max_size)
124 new_buf = GNUNET_malloc (new_size);
125 GNUNET_memcpy (new_buf, buf->data, buf->fill);
126 GNUNET_free (buf->data);
128 buf->alloc = new_size;
130 GNUNET_memcpy (buf->data + buf->fill, data, data_size);
131 buf->fill += data_size;
137 * Process a POST request containing a JSON object. This function
138 * realizes an MHD POST processor that will (incrementally) process
139 * JSON data uploaded to the HTTP server. It will store the required
140 * state in the @a con_cls, which must be cleaned up using
141 * #GNUNET_JSON_post_parser_callback().
143 * @param buffer_max maximum allowed size for the buffer
144 * @param con_cls the closure (will point to a `struct Buffer *`)
145 * @param upload_data the POST data
146 * @param upload_data_size number of bytes in @a upload_data
147 * @param json the JSON object for a completed request
148 * @return result code indicating the status of the operation
150 enum GNUNET_JSON_PostResult
151 GNUNET_JSON_post_parser (size_t buffer_max,
153 const char *upload_data,
154 size_t *upload_data_size,
157 struct Buffer *r = *con_cls;
160 if (NULL == *con_cls)
162 /* We are seeing a fresh POST request. */
163 r = GNUNET_new (struct Buffer);
168 REQUEST_BUFFER_INITIAL,
174 return GNUNET_JSON_PR_OUT_OF_MEMORY;
176 /* everything OK, wait for more POST data */
177 *upload_data_size = 0;
179 return GNUNET_JSON_PR_CONTINUE;
181 if (0 != *upload_data_size)
183 /* We are seeing an old request with more data available. */
191 /* Request too long */
195 return GNUNET_JSON_PR_REQUEST_TOO_LARGE;
197 /* everything OK, wait for more POST data */
198 *upload_data_size = 0;
199 return GNUNET_JSON_PR_CONTINUE;
202 /* We have seen the whole request. */
204 *json = json_loadb (r->data,
210 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
211 "Failed to parse JSON request body\n");
212 return GNUNET_JSON_PR_JSON_INVALID;
218 return GNUNET_JSON_PR_SUCCESS;
223 * Function called whenever we are done with a request
224 * to clean up our state.
226 * @param con_cls value as it was left by
227 * #GNUNET_JSON_post_parser(), to be cleaned up
230 GNUNET_JSON_post_parser_cleanup (void *con_cls)
232 struct Buffer *r = con_cls;
241 /* end of mhd_json.c */