aboutsummaryrefslogtreecommitdiff
path: root/src/json
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-04-04 12:05:15 +0000
committerChristian Grothoff <christian@grothoff.org>2016-04-04 12:05:15 +0000
commit4bbc354bfb43932064017af6a2394a282907d6a5 (patch)
tree437175d0ee9ac52600b3b4875f08e3b2a517b659 /src/json
parent50db224938033455429d17fce85ed77292d4c29a (diff)
downloadgnunet-4bbc354bfb43932064017af6a2394a282907d6a5.tar.gz
gnunet-4bbc354bfb43932064017af6a2394a282907d6a5.zip
actually add new source...
Diffstat (limited to 'src/json')
-rw-r--r--src/json/Makefile.am1
-rw-r--r--src/json/json_mhd.c241
2 files changed, 242 insertions, 0 deletions
diff --git a/src/json/Makefile.am b/src/json/Makefile.am
index 104fbe06e..d874d7507 100644
--- a/src/json/Makefile.am
+++ b/src/json/Makefile.am
@@ -14,6 +14,7 @@ libgnunetjson_la_LDFLAGS = \
14 -no-undefined 14 -no-undefined
15libgnunetjson_la_SOURCES = \ 15libgnunetjson_la_SOURCES = \
16 json.c \ 16 json.c \
17 json_mhd.c \
17 json_generator.c \ 18 json_generator.c \
18 json_helper.c 19 json_helper.c
19libgnunetjson_la_LIBADD = \ 20libgnunetjson_la_LIBADD = \
diff --git a/src/json/json_mhd.c b/src/json/json_mhd.c
new file mode 100644
index 000000000..e94c05009
--- /dev/null
+++ b/src/json/json_mhd.c
@@ -0,0 +1,241 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
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.
8
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.
12
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/>
15*/
16/**
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
22 */
23#include "platform.h"
24#include "gnunet_json_lib.h"
25
26/**
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.
30 */
31#define REQUEST_BUFFER_INITIAL (2*1024)
32
33
34/**
35 * Buffer for POST requests.
36 */
37struct Buffer
38{
39 /**
40 * Allocated memory
41 */
42 char *data;
43
44 /**
45 * Number of valid bytes in buffer.
46 */
47 size_t fill;
48
49 /**
50 * Number of allocated bytes in buffer.
51 */
52 size_t alloc;
53};
54
55
56/**
57 * Initialize a buffer.
58 *
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
65 */
66static int
67buffer_init (struct Buffer *buf,
68 const void *data,
69 size_t data_size,
70 size_t alloc_size,
71 size_t max_size)
72{
73 if ( (data_size > max_size) ||
74 (alloc_size > max_size) )
75 return GNUNET_SYSERR;
76 if (data_size > alloc_size)
77 alloc_size = data_size;
78 buf->data = GNUNET_malloc (alloc_size);
79 memcpy (buf->data, data, data_size);
80 return GNUNET_OK;
81}
82
83
84/**
85 * Free the data in a buffer. Does *not* free
86 * the buffer object itself.
87 *
88 * @param buf buffer to de-initialize
89 */
90static void
91buffer_deinit (struct Buffer *buf)
92{
93 GNUNET_free (buf->data);
94 buf->data = NULL;
95}
96
97
98/**
99 * Append data to a buffer, growing the buffer if necessary.
100 *
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
107 */
108static int
109buffer_append (struct Buffer *buf,
110 const void *data,
111 size_t data_size,
112 size_t max_size)
113{
114 if (buf->fill + data_size > max_size)
115 return GNUNET_NO;
116 if (data_size + buf->fill > buf->alloc)
117 {
118 char *new_buf;
119 size_t new_size = buf->alloc;
120 while (new_size < buf->fill + data_size)
121 new_size += 2;
122 if (new_size > max_size)
123 return GNUNET_NO;
124 new_buf = GNUNET_malloc (new_size);
125 memcpy (new_buf, buf->data, buf->fill);
126 GNUNET_free (buf->data);
127 buf->data = new_buf;
128 buf->alloc = new_size;
129 }
130 memcpy (buf->data + buf->fill, data, data_size);
131 buf->fill += data_size;
132 return GNUNET_OK;
133}
134
135
136/**
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().
142 *
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
149 */
150enum GNUNET_JSON_PostResult
151GNUNET_JSON_post_parser (size_t buffer_max,
152 void **con_cls,
153 const char *upload_data,
154 size_t *upload_data_size,
155 json_t **json)
156{
157 struct Buffer *r = *con_cls;
158
159 *json = NULL;
160 if (NULL == *con_cls)
161 {
162 /* We are seeing a fresh POST request. */
163 r = GNUNET_new (struct Buffer);
164 if (GNUNET_OK !=
165 buffer_init (r,
166 upload_data,
167 *upload_data_size,
168 REQUEST_BUFFER_INITIAL,
169 buffer_max))
170 {
171 *con_cls = NULL;
172 buffer_deinit (r);
173 GNUNET_free (r);
174 return GNUNET_JSON_PR_OUT_OF_MEMORY;
175 }
176 /* everything OK, wait for more POST data */
177 *upload_data_size = 0;
178 *con_cls = r;
179 return GNUNET_JSON_PR_CONTINUE;
180 }
181 if (0 != *upload_data_size)
182 {
183 /* We are seeing an old request with more data available. */
184
185 if (GNUNET_OK !=
186 buffer_append (r,
187 upload_data,
188 *upload_data_size,
189 buffer_max))
190 {
191 /* Request too long */
192 *con_cls = NULL;
193 buffer_deinit (r);
194 GNUNET_free (r);
195 return GNUNET_JSON_PR_REQUEST_TOO_LARGE;
196 }
197 /* everything OK, wait for more POST data */
198 *upload_data_size = 0;
199 return GNUNET_JSON_PR_CONTINUE;
200 }
201
202 /* We have seen the whole request. */
203
204 *json = json_loadb (r->data,
205 r->fill,
206 0,
207 NULL);
208 if (NULL == *json)
209 {
210 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
211 "Failed to parse JSON request body\n");
212 return GNUNET_JSON_PR_JSON_INVALID;
213 }
214 buffer_deinit (r);
215 GNUNET_free (r);
216 *con_cls = NULL;
217
218 return GNUNET_JSON_PR_SUCCESS;
219}
220
221
222/**
223 * Function called whenever we are done with a request
224 * to clean up our state.
225 *
226 * @param con_cls value as it was left by
227 * #GNUNET_JSON_post_parser(), to be cleaned up
228 */
229void
230GNUNET_JSON_post_parser_cleanup (void *con_cls)
231{
232 struct Buffer *r = con_cls;
233
234 if (NULL != r)
235 {
236 buffer_deinit (r);
237 GNUNET_free (r);
238 }
239}
240
241/* end of mhd_json.c */