diff options
author | Schanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de> | 2018-08-09 23:57:14 +0200 |
---|---|---|
committer | Schanzenbach, Martin <martin.schanzenbach@aisec.fraunhofer.de> | 2018-08-09 23:57:14 +0200 |
commit | 08c410658159c0975ad87d7b7582259cd2ac6ee4 (patch) | |
tree | f567c9020be2505f1c16a7249020e3e965ba7194 | |
parent | 389f4939845a0cb00e5ce0d8ea3ab7fc0541fd1c (diff) | |
parent | 1ad7b69834fffc95e05354983009e435030c0861 (diff) | |
download | gnunet-08c410658159c0975ad87d7b7582259cd2ac6ee4.tar.gz gnunet-08c410658159c0975ad87d7b7582259cd2ac6ee4.zip |
Merge branch 'gsoc2018/rest_api'
-rw-r--r-- | src/gns/plugin_rest_gns.c | 674 | ||||
-rwxr-xr-x | src/gns/test_plugin_rest_gns.sh | 50 | ||||
-rw-r--r-- | src/gnsrecord/gnsrecord.c | 3 | ||||
-rw-r--r-- | src/identity/Makefile.am | 2 | ||||
-rw-r--r-- | src/identity/plugin_rest_identity.c | 1057 | ||||
-rwxr-xr-x | src/identity/test_plugin_rest_identity.sh | 159 | ||||
-rw-r--r-- | src/include/gnunet_json_lib.h | 23 | ||||
-rw-r--r-- | src/json/Makefile.am | 4 | ||||
-rw-r--r-- | src/json/json_generator.c | 35 | ||||
-rw-r--r-- | src/json/json_gnsrecord.c | 177 | ||||
-rw-r--r-- | src/namestore/Makefile.am | 4 | ||||
-rw-r--r-- | src/namestore/plugin_rest_namestore.c | 1276 | ||||
-rwxr-xr-x | src/namestore/test_plugin_rest_namestore.sh | 208 | ||||
-rw-r--r-- | src/peerinfo/Makefile.am | 22 | ||||
-rw-r--r-- | src/peerinfo/plugin_rest_peerinfo.c | 801 |
15 files changed, 2819 insertions, 1676 deletions
diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c index e76a5d116..fd2469577 100644 --- a/src/gns/plugin_rest_gns.c +++ b/src/gns/plugin_rest_gns.c | |||
@@ -11,42 +11,42 @@ | |||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Affero General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Affero General Public License | 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/>. | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | /** | 18 | /** |
19 | * @author Martin Schanzenbach | 19 | * @author Philippe Buschmann |
20 | * @file gns/plugin_rest_gns.c | 20 | * @file gns/plugin_rest_gns.c |
21 | * @brief GNUnet GNS REST plugin | 21 | * @brief GNUnet Gns REST plugin |
22 | * | ||
23 | */ | 22 | */ |
24 | 23 | ||
25 | #include "platform.h" | 24 | #include "platform.h" |
26 | #include "gnunet_rest_plugin.h" | 25 | #include "gnunet_rest_plugin.h" |
27 | #include <gnunet_dnsparser_lib.h> | 26 | #include "gnunet_rest_lib.h" |
28 | #include <gnunet_identity_service.h> | 27 | #include "gnunet_json_lib.h" |
29 | #include <gnunet_gnsrecord_lib.h> | 28 | #include "gnunet_gnsrecord_lib.h" |
30 | #include <gnunet_namestore_service.h> | 29 | #include "gnunet_gns_service.h" |
31 | #include <gnunet_gns_service.h> | 30 | #include "microhttpd.h" |
32 | #include <gnunet_rest_lib.h> | ||
33 | #include <gnunet_jsonapi_lib.h> | ||
34 | #include <gnunet_jsonapi_util.h> | ||
35 | #include <jansson.h> | 31 | #include <jansson.h> |
36 | 32 | ||
37 | #define GNUNET_REST_API_NS_GNS "/gns" | 33 | #define GNUNET_REST_API_NS_GNS "/gns" |
38 | 34 | ||
39 | #define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type" | ||
40 | |||
41 | #define GNUNET_REST_JSONAPI_GNS_TYPEINFO "gns_name" | ||
42 | 35 | ||
43 | #define GNUNET_REST_JSONAPI_GNS_RECORD "records" | 36 | #define GNUNET_REST_GNS_PARAM_NAME "name" |
44 | 37 | ||
45 | #define GNUNET_REST_JSONAPI_GNS_EGO "ego" | 38 | #define GNUNET_REST_GNS_PARAM_RECORD_TYPE "record_type" |
39 | #define GNUNET_REST_GNS_ERROR_UNKNOWN "Unknown Error" | ||
46 | 40 | ||
47 | #define GNUNET_REST_JSONAPI_GNS_PKEY "pkey" | 41 | /** |
42 | * The configuration handle | ||
43 | */ | ||
44 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
48 | 45 | ||
49 | #define GNUNET_REST_JSONAPI_GNS_OPTIONS "options" | 46 | /** |
47 | * HTTP methods allows for this plugin | ||
48 | */ | ||
49 | static char* allow_methods; | ||
50 | 50 | ||
51 | /** | 51 | /** |
52 | * @brief struct returned by the initialization function of the plugin | 52 | * @brief struct returned by the initialization function of the plugin |
@@ -56,54 +56,44 @@ struct Plugin | |||
56 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 56 | const struct GNUNET_CONFIGURATION_Handle *cfg; |
57 | }; | 57 | }; |
58 | 58 | ||
59 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
60 | 59 | ||
61 | struct LookupHandle | 60 | struct RequestHandle |
62 | { | 61 | { |
63 | /** | ||
64 | * Handle to GNS service. | ||
65 | */ | ||
66 | struct GNUNET_GNS_Handle *gns; | ||
67 | 62 | ||
68 | /** | 63 | /** |
69 | * Desired timeout for the lookup (default is no timeout). | 64 | * Connection to GNS |
70 | */ | 65 | */ |
71 | struct GNUNET_TIME_Relative timeout; | 66 | struct GNUNET_GNS_Handle *gns; |
72 | 67 | ||
73 | /** | 68 | /** |
74 | * Handle to lookup request | 69 | * Active GNS lookup |
75 | */ | 70 | */ |
76 | struct GNUNET_GNS_LookupRequest *lookup_request; | 71 | struct GNUNET_GNS_LookupWithTldRequest *gns_lookup; |
77 | 72 | ||
78 | /** | 73 | /** |
79 | * Handle to rest request | 74 | * Name to look up |
80 | */ | 75 | */ |
81 | struct GNUNET_REST_RequestHandle *rest_handle; | 76 | char *name; |
82 | 77 | ||
83 | /** | 78 | /** |
84 | * Lookup an ego with the identity service. | 79 | * Record type to look up |
85 | */ | 80 | */ |
86 | struct GNUNET_IDENTITY_EgoLookup *el; | 81 | int record_type; |
87 | 82 | ||
88 | /** | 83 | /** |
89 | * Handle for identity service. | 84 | * Rest connection |
90 | */ | 85 | */ |
91 | struct GNUNET_IDENTITY_Handle *identity; | 86 | struct GNUNET_REST_RequestHandle *rest_handle; |
92 | 87 | ||
93 | /** | 88 | /** |
94 | * Active operation on identity service. | 89 | * Desired timeout for the lookup (default is no timeout). |
95 | */ | 90 | */ |
96 | struct GNUNET_IDENTITY_Operation *id_op; | 91 | struct GNUNET_TIME_Relative timeout; |
97 | 92 | ||
98 | /** | 93 | /** |
99 | * ID of a task associated with the resolution process. | 94 | * ID of a task associated with the resolution process. |
100 | */ | 95 | */ |
101 | struct GNUNET_SCHEDULER_Task * timeout_task; | 96 | struct GNUNET_SCHEDULER_Task *timeout_task; |
102 | |||
103 | /** | ||
104 | * The root of the received JSON or NULL | ||
105 | */ | ||
106 | json_t *json_root; | ||
107 | 97 | ||
108 | /** | 98 | /** |
109 | * The plugin result processor | 99 | * The plugin result processor |
@@ -116,49 +106,17 @@ struct LookupHandle | |||
116 | void *proc_cls; | 106 | void *proc_cls; |
117 | 107 | ||
118 | /** | 108 | /** |
119 | * The name to look up | 109 | * The url |
120 | */ | ||
121 | char *name; | ||
122 | |||
123 | /** | ||
124 | * The ego to use | ||
125 | * In string representation from JSON | ||
126 | */ | ||
127 | const char *ego_str; | ||
128 | |||
129 | /** | ||
130 | * The Pkey to use | ||
131 | * In string representation from JSON | ||
132 | */ | ||
133 | const char *pkey_str; | ||
134 | |||
135 | /** | ||
136 | * The record type | ||
137 | */ | 110 | */ |
138 | int type; | 111 | char *url; |
139 | 112 | ||
140 | /** | 113 | /** |
141 | * The public key of to use for lookup | 114 | * Error response message |
142 | */ | 115 | */ |
143 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; | 116 | char *emsg; |
144 | 117 | ||
145 | /** | 118 | /** |
146 | * The public key to use for lookup | 119 | * Reponse code |
147 | */ | ||
148 | struct GNUNET_CRYPTO_EcdsaPublicKey pkeym; | ||
149 | |||
150 | /** | ||
151 | * The resolver options | ||
152 | */ | ||
153 | enum GNUNET_GNS_LocalOptions options; | ||
154 | |||
155 | /** | ||
156 | * the shorten key | ||
157 | */ | ||
158 | struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key; | ||
159 | |||
160 | /** | ||
161 | * HTTP response code | ||
162 | */ | 120 | */ |
163 | int response_code; | 121 | int response_code; |
164 | 122 | ||
@@ -166,39 +124,20 @@ struct LookupHandle | |||
166 | 124 | ||
167 | 125 | ||
168 | /** | 126 | /** |
169 | * Cleanup lookup handle. | 127 | * Cleanup lookup handle |
170 | * | ||
171 | * @param handle Handle to clean up | 128 | * @param handle Handle to clean up |
172 | */ | 129 | */ |
173 | static void | 130 | static void |
174 | cleanup_handle (struct LookupHandle *handle) | 131 | cleanup_handle (void *cls) |
175 | { | 132 | { |
133 | struct RequestHandle *handle = cls; | ||
176 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 134 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
177 | "Cleaning up\n"); | 135 | "Cleaning up\n"); |
178 | if (NULL != handle->json_root) | ||
179 | json_decref (handle->json_root); | ||
180 | 136 | ||
181 | if (NULL != handle->name) | 137 | if (NULL != handle->gns_lookup) |
182 | GNUNET_free (handle->name); | ||
183 | if (NULL != handle->el) | ||
184 | { | ||
185 | GNUNET_IDENTITY_ego_lookup_cancel (handle->el); | ||
186 | handle->el = NULL; | ||
187 | } | ||
188 | if (NULL != handle->id_op) | ||
189 | { | ||
190 | GNUNET_IDENTITY_cancel (handle->id_op); | ||
191 | handle->id_op = NULL; | ||
192 | } | ||
193 | if (NULL != handle->lookup_request) | ||
194 | { | ||
195 | GNUNET_GNS_lookup_cancel (handle->lookup_request); | ||
196 | handle->lookup_request = NULL; | ||
197 | } | ||
198 | if (NULL != handle->identity) | ||
199 | { | 138 | { |
200 | GNUNET_IDENTITY_disconnect (handle->identity); | 139 | GNUNET_GNS_lookup_with_tld_cancel (handle->gns_lookup); |
201 | handle->identity = NULL; | 140 | handle->gns_lookup = NULL; |
202 | } | 141 | } |
203 | if (NULL != handle->gns) | 142 | if (NULL != handle->gns) |
204 | { | 143 | { |
@@ -209,387 +148,181 @@ cleanup_handle (struct LookupHandle *handle) | |||
209 | if (NULL != handle->timeout_task) | 148 | if (NULL != handle->timeout_task) |
210 | { | 149 | { |
211 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | 150 | GNUNET_SCHEDULER_cancel (handle->timeout_task); |
151 | handle->timeout_task = NULL; | ||
212 | } | 152 | } |
153 | if (NULL != handle->url) | ||
154 | GNUNET_free (handle->url); | ||
155 | if (NULL != handle->name) | ||
156 | GNUNET_free (handle->name); | ||
157 | if (NULL != handle->emsg) | ||
158 | GNUNET_free (handle->emsg); | ||
159 | |||
213 | GNUNET_free (handle); | 160 | GNUNET_free (handle); |
214 | } | 161 | } |
215 | 162 | ||
216 | 163 | ||
217 | /** | 164 | /** |
218 | * Task run on shutdown. Cleans up everything. | 165 | * Task run on errors. Reports an error and cleans up everything. |
219 | * | 166 | * |
220 | * @param cls unused | 167 | * @param cls the `struct RequestHandle` |
221 | * @param tc scheduler context | ||
222 | */ | 168 | */ |
223 | static void | 169 | static void |
224 | do_error (void *cls) | 170 | do_error (void *cls) |
225 | { | 171 | { |
226 | struct LookupHandle *handle = cls; | 172 | struct RequestHandle *handle = cls; |
227 | struct MHD_Response *resp; | 173 | struct MHD_Response *resp; |
174 | json_t *json_error = json_object(); | ||
175 | char *response; | ||
228 | 176 | ||
229 | resp = GNUNET_REST_create_response (NULL); | 177 | if (NULL == handle->emsg) |
230 | handle->proc (handle->proc_cls, resp, handle->response_code); | 178 | handle->emsg = GNUNET_strdup(GNUNET_REST_GNS_ERROR_UNKNOWN); |
231 | cleanup_handle (handle); | ||
232 | } | ||
233 | |||
234 | 179 | ||
235 | /** | 180 | json_object_set_new(json_error,"error", json_string(handle->emsg)); |
236 | * Create json representation of a GNSRECORD | ||
237 | * | ||
238 | * @param rd the GNSRECORD_Data | ||
239 | */ | ||
240 | static json_t * | ||
241 | gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) | ||
242 | { | ||
243 | const char *typename; | ||
244 | char *string_val; | ||
245 | const char *exp_str; | ||
246 | json_t *record_obj; | ||
247 | |||
248 | typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); | ||
249 | string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type, | ||
250 | rd->data, | ||
251 | rd->data_size); | ||
252 | 181 | ||
253 | if (NULL == string_val) | 182 | if (0 == handle->response_code) |
254 | { | 183 | handle->response_code = MHD_HTTP_OK; |
255 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 184 | response = json_dumps (json_error, 0); |
256 | "Record of type %d malformed, skipping\n", | 185 | resp = GNUNET_REST_create_response (response); |
257 | (int) rd->record_type); | 186 | handle->proc (handle->proc_cls, resp, handle->response_code); |
258 | return NULL; | 187 | json_decref(json_error); |
259 | } | 188 | GNUNET_free(response); |
260 | record_obj = json_object (); | 189 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); |
261 | json_object_set_new (record_obj, "type", json_string (typename)); | ||
262 | json_object_set_new (record_obj, "value", json_string (string_val)); | ||
263 | GNUNET_free (string_val); | ||
264 | |||
265 | if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) | ||
266 | { | ||
267 | struct GNUNET_TIME_Relative time_rel; | ||
268 | time_rel.rel_value_us = rd->expiration_time; | ||
269 | exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); | ||
270 | } | ||
271 | else | ||
272 | { | ||
273 | struct GNUNET_TIME_Absolute time_abs; | ||
274 | time_abs.abs_value_us = rd->expiration_time; | ||
275 | exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); | ||
276 | } | ||
277 | json_object_set_new (record_obj, "expiration_time", json_string (exp_str)); | ||
278 | |||
279 | json_object_set_new (record_obj, "expired", | ||
280 | json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); | ||
281 | return record_obj; | ||
282 | } | ||
283 | |||
284 | |||
285 | static void | ||
286 | do_cleanup (void *cls) | ||
287 | { | ||
288 | struct LookupHandle *handle = cls; | ||
289 | cleanup_handle (handle); | ||
290 | } | 190 | } |
291 | 191 | ||
292 | 192 | ||
293 | /** | 193 | /** |
294 | * Function called with the result of a GNS lookup. | 194 | * Iterator called on obtained result for a GNS lookup. |
295 | * | 195 | * |
296 | * @param cls the 'const char *' name that was resolved | 196 | * @param cls closure with the object |
297 | * @param rd_count number of records returned | 197 | * @param was_gns #GNUNET_NO if name was not a GNS name |
298 | * @param rd array of @a rd_count records with the results | 198 | * @param rd_count number of records in @a rd |
199 | * @param rd the records in reply | ||
299 | */ | 200 | */ |
300 | static void | 201 | static void |
301 | process_lookup_result (void *cls, uint32_t rd_count, | 202 | handle_gns_response (void *cls, |
302 | const struct GNUNET_GNSRECORD_Data *rd) | 203 | int was_gns, |
204 | uint32_t rd_count, | ||
205 | const struct GNUNET_GNSRECORD_Data *rd) | ||
303 | { | 206 | { |
304 | struct LookupHandle *handle = cls; | 207 | struct RequestHandle *handle = cls; |
305 | struct MHD_Response *resp; | 208 | struct MHD_Response *resp; |
306 | struct GNUNET_JSONAPI_Document *json_document; | ||
307 | struct GNUNET_JSONAPI_Resource *json_resource; | ||
308 | uint32_t i; | ||
309 | char *result; | ||
310 | json_t *result_array; | 209 | json_t *result_array; |
311 | json_t *record_obj; | 210 | json_t *record_obj; |
211 | char *result; | ||
212 | |||
213 | handle->gns_lookup = NULL; | ||
214 | |||
215 | if (GNUNET_NO == was_gns) | ||
216 | { | ||
217 | handle->emsg = GNUNET_strdup("Name not found in GNS"); | ||
218 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
219 | return; | ||
220 | } | ||
312 | 221 | ||
313 | result_array = json_array(); | 222 | result_array = json_array(); |
314 | json_document = GNUNET_JSONAPI_document_new (); | 223 | for (uint32_t i=0;i<rd_count;i++) |
315 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_GNS_TYPEINFO, handle->name); | ||
316 | handle->lookup_request = NULL; | ||
317 | for (i=0; i<rd_count; i++) | ||
318 | { | 224 | { |
319 | if ( (rd[i].record_type != handle->type) && | 225 | if ((rd[i].record_type != handle->record_type) && |
320 | (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) | 226 | (GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) ) |
227 | { | ||
321 | continue; | 228 | continue; |
322 | record_obj = gnsrecord_to_json (&(rd[i])); | 229 | } |
230 | |||
231 | record_obj = GNUNET_JSON_from_gns_record(NULL,&rd[i]); | ||
323 | json_array_append (result_array, record_obj); | 232 | json_array_append (result_array, record_obj); |
324 | json_decref (record_obj); | 233 | json_decref (record_obj); |
325 | } | 234 | } |
326 | GNUNET_JSONAPI_resource_add_attr (json_resource, | 235 | |
327 | GNUNET_REST_JSONAPI_GNS_RECORD, | 236 | result = json_dumps(result_array, 0); |
328 | result_array); | ||
329 | GNUNET_JSONAPI_document_resource_add (json_document, json_resource); | ||
330 | GNUNET_JSONAPI_document_serialize (json_document, &result); | ||
331 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result); | 237 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result); |
332 | json_decref (result_array); | ||
333 | GNUNET_JSONAPI_document_delete (json_document); | ||
334 | resp = GNUNET_REST_create_response (result); | 238 | resp = GNUNET_REST_create_response (result); |
335 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | 239 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); |
336 | GNUNET_free (result); | 240 | GNUNET_free (result); |
337 | GNUNET_SCHEDULER_add_now (&do_cleanup, handle); | 241 | json_decref (result_array); |
242 | GNUNET_SCHEDULER_add_now(&cleanup_handle, handle); | ||
338 | } | 243 | } |
339 | 244 | ||
340 | 245 | ||
341 | /** | 246 | /** |
342 | * Perform the actual resolution, starting with the zone | 247 | * Handle gns GET request |
343 | * identified by the given public key and the shorten zone. | ||
344 | * | 248 | * |
345 | * @param pkey public key to use for the zone, can be NULL | 249 | * @param con_handle the connection handle |
250 | * @param url the url | ||
251 | * @param cls the RequestHandle | ||
346 | */ | 252 | */ |
347 | static void | 253 | void |
348 | lookup_with_public_key (struct LookupHandle *handle) | 254 | get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, |
255 | const char* url, | ||
256 | void *cls) | ||
349 | { | 257 | { |
350 | if (UINT32_MAX == handle->type) | 258 | struct RequestHandle *handle = cls; |
351 | { | 259 | struct GNUNET_HashCode key; |
352 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 260 | char *record_type; |
353 | _("Invalid typename specified, assuming `ANY'\n")); | 261 | char *name; |
354 | handle->type = GNUNET_GNSRECORD_TYPE_ANY; | 262 | |
355 | } | 263 | GNUNET_CRYPTO_hash (GNUNET_REST_GNS_PARAM_NAME, |
356 | if (NULL != handle->name) | 264 | strlen (GNUNET_REST_GNS_PARAM_NAME), |
357 | { | 265 | &key); |
358 | handle->lookup_request = GNUNET_GNS_lookup (handle->gns, | 266 | if ( GNUNET_NO |
359 | handle->name, | 267 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, |
360 | &handle->pkey, | 268 | &key)) |
361 | handle->type, | ||
362 | handle->options, | ||
363 | &process_lookup_result, | ||
364 | handle); | ||
365 | } | ||
366 | else | ||
367 | { | 269 | { |
270 | handle->emsg = GNUNET_strdup("Parameter name is missing"); | ||
368 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 271 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
369 | return; | 272 | return; |
370 | } | 273 | } |
371 | } | 274 | name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key); |
372 | 275 | if(0 >= strlen (name)) | |
373 | |||
374 | /** | ||
375 | * Method called to with the ego we are to use for the lookup, | ||
376 | * when the ego is determined by a name. | ||
377 | * | ||
378 | * @param cls closure (NULL, unused) | ||
379 | * @param ego ego handle, NULL if not found | ||
380 | */ | ||
381 | static void | ||
382 | identity_zone_cb (void *cls, | ||
383 | const struct GNUNET_IDENTITY_Ego *ego) | ||
384 | { | ||
385 | struct LookupHandle *handle = cls; | ||
386 | |||
387 | handle->el = NULL; | ||
388 | if (NULL == ego) | ||
389 | { | 276 | { |
390 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 277 | handle->emsg = GNUNET_strdup("Length of parameter name is zero"); |
391 | _("Ego for not found, cannot perform lookup.\n")); | ||
392 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 278 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
393 | return; | 279 | return; |
394 | } | 280 | } |
395 | else | 281 | handle->name = GNUNET_strdup(name); |
396 | { | ||
397 | GNUNET_IDENTITY_ego_get_public_key (ego, &handle->pkey); | ||
398 | lookup_with_public_key (handle); | ||
399 | } | ||
400 | json_decref(handle->json_root); | ||
401 | } | ||
402 | |||
403 | 282 | ||
404 | /** | 283 | handle->record_type = UINT32_MAX; |
405 | * Method called to with the ego we are to use for the lookup, | 284 | GNUNET_CRYPTO_hash (GNUNET_REST_GNS_PARAM_RECORD_TYPE, |
406 | * when the ego is the one for the default master zone. | 285 | strlen (GNUNET_REST_GNS_PARAM_RECORD_TYPE), |
407 | * | 286 | &key); |
408 | * @param cls closure (NULL, unused) | 287 | if ( GNUNET_YES |
409 | * @param ego ego handle, NULL if not found | 288 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, |
410 | * @param ctx context for application to store data for this ego | 289 | &key)) |
411 | * (during the lifetime of this process, initially NULL) | ||
412 | * @param name name assigned by the user for this ego, | ||
413 | * NULL if the user just deleted the ego and it | ||
414 | * must thus no longer be used | ||
415 | */ | ||
416 | static void | ||
417 | identity_master_cb (void *cls, | ||
418 | struct GNUNET_IDENTITY_Ego *ego, | ||
419 | void **ctx, | ||
420 | const char *name) | ||
421 | { | ||
422 | const char *dot; | ||
423 | struct LookupHandle *handle = cls; | ||
424 | |||
425 | handle->id_op = NULL; | ||
426 | if (NULL == ego) | ||
427 | { | 290 | { |
428 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 291 | record_type = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key); |
429 | _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n")); | 292 | handle->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); |
430 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
431 | return; | ||
432 | } | 293 | } |
433 | GNUNET_IDENTITY_ego_get_public_key (ego, | ||
434 | &handle->pkey); | ||
435 | /* main name is our own master zone, do no look for that in the DHT */ | ||
436 | handle->options = GNUNET_GNS_LO_LOCAL_MASTER; | ||
437 | /* if the name is of the form 'label.gnu', never go to the DHT */ | ||
438 | dot = NULL; | ||
439 | if (NULL != handle->name) | ||
440 | dot = strchr (handle->name, '.'); | ||
441 | if ( (NULL != dot) && | ||
442 | (0 == strcasecmp (dot, ".gnu")) ) | ||
443 | handle->options = GNUNET_GNS_LO_NO_DHT; | ||
444 | lookup_with_public_key (handle); | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * Parse REST uri for name and record type | ||
449 | * | ||
450 | * @param url Url to parse | ||
451 | * @param handle lookup handle to populate | ||
452 | * @return GNUNET_SYSERR on error | ||
453 | */ | ||
454 | static int | ||
455 | parse_url (const char *url, struct LookupHandle *handle) | ||
456 | { | ||
457 | char *name; | ||
458 | char tmp_url[strlen(url)+1]; | ||
459 | char *tok; | ||
460 | |||
461 | strcpy (tmp_url, url); | ||
462 | tok = strtok ((char*)tmp_url, "/"); | ||
463 | if (NULL == tok) | ||
464 | return GNUNET_SYSERR; | ||
465 | name = strtok (NULL, "/"); | ||
466 | if (NULL == name) | ||
467 | return GNUNET_SYSERR; | ||
468 | GNUNET_asprintf (&handle->name, | ||
469 | "%s", | ||
470 | name); | ||
471 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
472 | "Got name: %s\n", handle->name); | ||
473 | return GNUNET_OK; | ||
474 | } | ||
475 | |||
476 | 294 | ||
477 | static void | ||
478 | get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle, | ||
479 | const char* url, | ||
480 | void *cls) | ||
481 | { | ||
482 | struct LookupHandle *handle = cls; | ||
483 | struct GNUNET_HashCode key; | ||
484 | 295 | ||
485 | //parse name and type from url | 296 | if(UINT32_MAX == handle->record_type) |
486 | if (GNUNET_OK != parse_url (url, handle)) | ||
487 | { | 297 | { |
488 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing url...\n"); | 298 | handle->record_type = GNUNET_GNSRECORD_TYPE_ANY; |
489 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
490 | return; | ||
491 | } | 299 | } |
492 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 300 | |
493 | "Connecting...\n"); | ||
494 | handle->gns = GNUNET_GNS_connect (cfg); | 301 | handle->gns = GNUNET_GNS_connect (cfg); |
495 | handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL); | ||
496 | handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
497 | &do_error, handle); | ||
498 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
499 | "Connected\n"); | ||
500 | if (NULL == handle->gns) | 302 | if (NULL == handle->gns) |
501 | { | 303 | { |
502 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 304 | handle->emsg = GNUNET_strdup ("GNS not available"); |
503 | "Connecting to GNS failed\n"); | ||
504 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 305 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
505 | return; | 306 | return; |
506 | } | 307 | } |
507 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS, | ||
508 | strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS), | ||
509 | &key); | ||
510 | handle->options = GNUNET_GNS_LO_DEFAULT; | ||
511 | if ( GNUNET_YES == | ||
512 | GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, | ||
513 | &key) ) | ||
514 | { | ||
515 | handle->options = GNUNET_GNS_LO_DEFAULT;//TODO(char*) GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, | ||
516 | //&key); | ||
517 | } | ||
518 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE, | ||
519 | strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE), | ||
520 | &key); | ||
521 | if ( GNUNET_YES == | ||
522 | GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, | ||
523 | &key) ) | ||
524 | { | ||
525 | handle->type = GNUNET_GNSRECORD_typename_to_number | ||
526 | (GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, | ||
527 | &key)); | ||
528 | } | ||
529 | else | ||
530 | handle->type = GNUNET_GNSRECORD_TYPE_ANY; | ||
531 | 308 | ||
532 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_PKEY, | 309 | handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns, |
533 | strlen (GNUNET_REST_JSONAPI_GNS_PKEY), | 310 | handle->name, |
534 | &key); | 311 | handle->record_type, |
535 | if ( GNUNET_YES == | 312 | GNUNET_NO, |
536 | GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, | 313 | &handle_gns_response, |
537 | &key) ) | 314 | handle); |
538 | { | 315 | return; |
539 | handle->pkey_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, | ||
540 | &key); | ||
541 | GNUNET_assert (NULL != handle->pkey_str); | ||
542 | if (GNUNET_OK != | ||
543 | GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->pkey_str, | ||
544 | strlen(handle->pkey_str), | ||
545 | &(handle->pkey))) | ||
546 | { | ||
547 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
548 | return; | ||
549 | } | ||
550 | lookup_with_public_key (handle); | ||
551 | return; | ||
552 | } | ||
553 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_EGO, | ||
554 | strlen (GNUNET_REST_JSONAPI_GNS_EGO), | ||
555 | &key); | ||
556 | if ( GNUNET_YES == | ||
557 | GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, | ||
558 | &key) ) | ||
559 | { | ||
560 | handle->ego_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, | ||
561 | &key); | ||
562 | handle->el = GNUNET_IDENTITY_ego_lookup (cfg, | ||
563 | handle->ego_str, | ||
564 | &identity_zone_cb, | ||
565 | handle); | ||
566 | return; | ||
567 | } | ||
568 | if ( (NULL != handle->name) && | ||
569 | (strlen (handle->name) > 4) && | ||
570 | (0 == strcmp (".zkey", | ||
571 | &handle->name[strlen (handle->name) - 4])) ) | ||
572 | { | ||
573 | GNUNET_CRYPTO_ecdsa_key_get_public | ||
574 | (GNUNET_CRYPTO_ecdsa_key_get_anonymous (), | ||
575 | &(handle->pkey)); | ||
576 | lookup_with_public_key (handle); | ||
577 | } | ||
578 | else | ||
579 | { | ||
580 | GNUNET_break (NULL == handle->id_op); | ||
581 | handle->id_op = GNUNET_IDENTITY_get (handle->identity, | ||
582 | "gns-master", | ||
583 | &identity_master_cb, | ||
584 | handle); | ||
585 | GNUNET_assert (NULL != handle->id_op); | ||
586 | } | ||
587 | } | 316 | } |
588 | 317 | ||
318 | |||
319 | |||
589 | /** | 320 | /** |
590 | * Handle rest request | 321 | * Respond to OPTIONS request |
591 | * | 322 | * |
592 | * @param handle the lookup handle | 323 | * @param con_handle the connection handle |
324 | * @param url the url | ||
325 | * @param cls the RequestHandle | ||
593 | */ | 326 | */ |
594 | static void | 327 | static void |
595 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, | 328 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, |
@@ -597,53 +330,38 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
597 | void *cls) | 330 | void *cls) |
598 | { | 331 | { |
599 | struct MHD_Response *resp; | 332 | struct MHD_Response *resp; |
600 | struct LookupHandle *handle = cls; | 333 | struct RequestHandle *handle = cls; |
601 | 334 | ||
602 | //For GNS, independent of path return all options | 335 | //independent of path return all options |
603 | resp = GNUNET_REST_create_response (NULL); | 336 | resp = GNUNET_REST_create_response (NULL); |
604 | MHD_add_response_header (resp, | 337 | MHD_add_response_header (resp, |
605 | "Access-Control-Allow-Methods", | 338 | "Access-Control-Allow-Methods", |
606 | MHD_HTTP_METHOD_GET); | 339 | allow_methods); |
607 | handle->proc (handle->proc_cls, | 340 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); |
608 | resp, | 341 | GNUNET_SCHEDULER_add_now(&cleanup_handle, handle); |
609 | MHD_HTTP_OK); | 342 | return; |
610 | cleanup_handle (handle); | ||
611 | } | 343 | } |
612 | 344 | ||
613 | 345 | ||
614 | /** | 346 | /** |
615 | * Function processing the REST call | 347 | * Handle rest request |
616 | * | 348 | * |
617 | * @param method HTTP method | 349 | * @param handle the request handle |
618 | * @param url URL of the HTTP request | ||
619 | * @param data body of the HTTP request (optional) | ||
620 | * @param data_size length of the body | ||
621 | * @param proc callback function for the result | ||
622 | * @param proc_cls closure for @a proc | ||
623 | * @return #GNUNET_OK if request accepted | ||
624 | */ | 350 | */ |
625 | static void | 351 | static void |
626 | rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, | 352 | init_cont (struct RequestHandle *handle) |
627 | GNUNET_REST_ResultProcessor proc, | ||
628 | void *proc_cls) | ||
629 | { | 353 | { |
354 | struct GNUNET_REST_RequestHandlerError err; | ||
630 | static const struct GNUNET_REST_RequestHandler handlers[] = { | 355 | static const struct GNUNET_REST_RequestHandler handlers[] = { |
631 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont}, | 356 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont}, |
632 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont}, | 357 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont}, |
633 | GNUNET_REST_HANDLER_END | 358 | GNUNET_REST_HANDLER_END |
634 | }; | 359 | }; |
635 | struct LookupHandle *handle = GNUNET_new (struct LookupHandle); | ||
636 | struct GNUNET_REST_RequestHandlerError err; | ||
637 | |||
638 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | ||
639 | handle->proc_cls = proc_cls; | ||
640 | handle->proc = proc; | ||
641 | handle->rest_handle = conndata_handle; | ||
642 | 360 | ||
643 | if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle, | 361 | if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, |
644 | handlers, | 362 | handlers, |
645 | &err, | 363 | &err, |
646 | handle)) | 364 | handle)) |
647 | { | 365 | { |
648 | handle->response_code = err.error_code; | 366 | handle->response_code = err.error_code; |
649 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 367 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
@@ -652,18 +370,58 @@ rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, | |||
652 | 370 | ||
653 | 371 | ||
654 | /** | 372 | /** |
373 | * Function processing the REST call | ||
374 | * | ||
375 | * @param method HTTP method | ||
376 | * @param url URL of the HTTP request | ||
377 | * @param data body of the HTTP request (optional) | ||
378 | * @param data_size length of the body | ||
379 | * @param proc callback function for the result | ||
380 | * @param proc_cls closure for callback function | ||
381 | * @return GNUNET_OK if request accepted | ||
382 | */ | ||
383 | static void | ||
384 | rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, | ||
385 | GNUNET_REST_ResultProcessor proc, | ||
386 | void *proc_cls) | ||
387 | { | ||
388 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | ||
389 | |||
390 | handle->response_code = 0; | ||
391 | handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60); | ||
392 | handle->proc_cls = proc_cls; | ||
393 | handle->proc = proc; | ||
394 | handle->rest_handle = rest_handle; | ||
395 | |||
396 | handle->url = GNUNET_strdup (rest_handle->url); | ||
397 | if (handle->url[strlen (handle->url)-1] == '/') | ||
398 | handle->url[strlen (handle->url)-1] = '\0'; | ||
399 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); | ||
400 | |||
401 | init_cont(handle); | ||
402 | |||
403 | handle->timeout_task = | ||
404 | GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
405 | &do_error, | ||
406 | handle); | ||
407 | |||
408 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); | ||
409 | } | ||
410 | |||
411 | |||
412 | /** | ||
655 | * Entry point for the plugin. | 413 | * Entry point for the plugin. |
656 | * | 414 | * |
657 | * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" | 415 | * @param cls Config info |
658 | * @return NULL on error, otherwise the plugin context | 416 | * @return NULL on error, otherwise the plugin context |
659 | */ | 417 | */ |
660 | void * | 418 | void * |
661 | libgnunet_plugin_rest_gns_init (void *cls) | 419 | libgnunet_plugin_rest_gns_init (void *cls) |
662 | { | 420 | { |
663 | static struct Plugin plugin; | 421 | static struct Plugin plugin; |
664 | cfg = cls; | ||
665 | struct GNUNET_REST_Plugin *api; | 422 | struct GNUNET_REST_Plugin *api; |
666 | 423 | ||
424 | cfg = cls; | ||
667 | if (NULL != plugin.cfg) | 425 | if (NULL != plugin.cfg) |
668 | return NULL; /* can only initialize once! */ | 426 | return NULL; /* can only initialize once! */ |
669 | memset (&plugin, 0, sizeof (struct Plugin)); | 427 | memset (&plugin, 0, sizeof (struct Plugin)); |
@@ -671,9 +429,17 @@ libgnunet_plugin_rest_gns_init (void *cls) | |||
671 | api = GNUNET_new (struct GNUNET_REST_Plugin); | 429 | api = GNUNET_new (struct GNUNET_REST_Plugin); |
672 | api->cls = &plugin; | 430 | api->cls = &plugin; |
673 | api->name = GNUNET_REST_API_NS_GNS; | 431 | api->name = GNUNET_REST_API_NS_GNS; |
674 | api->process_request = &rest_gns_process_request; | 432 | api->process_request = &rest_process_request; |
675 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 433 | GNUNET_asprintf (&allow_methods, |
676 | _("GNS REST API initialized\n")); | 434 | "%s, %s, %s, %s, %s", |
435 | MHD_HTTP_METHOD_GET, | ||
436 | MHD_HTTP_METHOD_POST, | ||
437 | MHD_HTTP_METHOD_PUT, | ||
438 | MHD_HTTP_METHOD_DELETE, | ||
439 | MHD_HTTP_METHOD_OPTIONS); | ||
440 | |||
441 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
442 | _("Gns REST API initialized\n")); | ||
677 | return api; | 443 | return api; |
678 | } | 444 | } |
679 | 445 | ||
@@ -689,12 +455,14 @@ libgnunet_plugin_rest_gns_done (void *cls) | |||
689 | { | 455 | { |
690 | struct GNUNET_REST_Plugin *api = cls; | 456 | struct GNUNET_REST_Plugin *api = cls; |
691 | struct Plugin *plugin = api->cls; | 457 | struct Plugin *plugin = api->cls; |
692 | |||
693 | plugin->cfg = NULL; | 458 | plugin->cfg = NULL; |
459 | |||
460 | GNUNET_free_non_null (allow_methods); | ||
694 | GNUNET_free (api); | 461 | GNUNET_free (api); |
695 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 462 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
696 | "GNS REST plugin is finished\n"); | 463 | "Gns REST plugin is finished\n"); |
697 | return NULL; | 464 | return NULL; |
698 | } | 465 | } |
699 | 466 | ||
700 | /* end of plugin_rest_gns.c */ | 467 | /* end of plugin_rest_gns.c */ |
468 | |||
diff --git a/src/gns/test_plugin_rest_gns.sh b/src/gns/test_plugin_rest_gns.sh new file mode 100755 index 000000000..7ede44501 --- /dev/null +++ b/src/gns/test_plugin_rest_gns.sh | |||
@@ -0,0 +1,50 @@ | |||
1 | #!/usr/bin/bash | ||
2 | |||
3 | #First, start gnunet-arm and the rest-service. | ||
4 | #Exit 0 means success, exit 1 means failed test | ||
5 | |||
6 | gns_link="http://localhost:7776/gns" | ||
7 | wrong_link="http://localhost:7776/gnsandmore" | ||
8 | |||
9 | curl_get () { | ||
10 | #$1 is link | ||
11 | #$2 is grep | ||
12 | cache="$(curl -v "$1" 2>&1 | grep "$2")" | ||
13 | #echo $cache | ||
14 | if [ "" == "$cache" ] | ||
15 | then | ||
16 | exit 1 | ||
17 | fi | ||
18 | } | ||
19 | |||
20 | gnunet-identity -D "test_plugin_rest_gns" > /dev/null 2>&1 | ||
21 | |||
22 | curl_get "$gns_link?name=www.test_plugin_rest_gns" "error" | ||
23 | |||
24 | gnunet-identity -C "test_plugin_rest_gns" | ||
25 | |||
26 | curl_get "$gns_link?name=www.test_plugin_rest_gns" "\[\]" | ||
27 | |||
28 | gnunet-namestore -z "test_plugin_rest_gns" -p -a -n www -e 1d -V 1.1.1.1 -t A | ||
29 | |||
30 | curl_get "$gns_link?name=www.test_plugin_rest_gns" "1.1.1.1" | ||
31 | |||
32 | gnunet-namestore -z "test_plugin_rest_gns" -p -a -n www -e 1d -V 1::1 -t AAAA | ||
33 | |||
34 | curl_get "$gns_link?name=www.test_plugin_rest_gns" "1::1.*1.1.1.1" | ||
35 | |||
36 | gnunet-namestore -z "test_plugin_rest_gns" -p -a -n www -e 1d -V 1.1.1.2 -t A | ||
37 | |||
38 | curl_get "$gns_link?name=www.test_plugin_rest_gns" "1.1.1.2.*1::1.*1.1.1.1" | ||
39 | curl_get "$gns_link?name=www.test_plugin_rest_gns&record_type=A" "1.1.1.2.*1.1.1.1" | ||
40 | curl_get "$gns_link?name=www.test_plugin_rest_gns&record_type=AAAA" "1::1" | ||
41 | curl_get "$gns_link?name=www.test_plugin_rest_gns&record_type=WRONG_TYPE" "1.1.1.2.*1::1.*1.1.1.1" | ||
42 | |||
43 | gnunet-namestore -z "test_plugin_rest_gns" -p -a -n www1 -e 1d -V 1.1.1.1 -t A | ||
44 | curl_get "$gns_link?name=www1.test_plugin_rest_gns" "1.1.1.1" | ||
45 | |||
46 | gnunet-identity -D "test_plugin_rest_gns" | ||
47 | |||
48 | curl_get "$gns_link?name=www1.test_plugin_rest_gns" "error" | ||
49 | |||
50 | exit 0 | ||
diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c index da34846e7..b80d86073 100644 --- a/src/gnsrecord/gnsrecord.c +++ b/src/gnsrecord/gnsrecord.c | |||
@@ -28,7 +28,9 @@ | |||
28 | #include "gnunet_constants.h" | 28 | #include "gnunet_constants.h" |
29 | #include "gnunet_gnsrecord_lib.h" | 29 | #include "gnunet_gnsrecord_lib.h" |
30 | #include "gnunet_gnsrecord_plugin.h" | 30 | #include "gnunet_gnsrecord_plugin.h" |
31 | #include "gnunet_json_lib.h" | ||
31 | #include "gnunet_tun_lib.h" | 32 | #include "gnunet_tun_lib.h" |
33 | #include <jansson.h> | ||
32 | 34 | ||
33 | 35 | ||
34 | #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) | 36 | #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) |
@@ -245,5 +247,4 @@ GNUNET_GNSRECORD_number_to_typename (uint32_t type) | |||
245 | return NULL; | 247 | return NULL; |
246 | } | 248 | } |
247 | 249 | ||
248 | |||
249 | /* end of gnsrecord.c */ | 250 | /* end of gnsrecord.c */ |
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am index b8e70fffb..e7104f0c3 100644 --- a/src/identity/Makefile.am +++ b/src/identity/Makefile.am | |||
@@ -60,8 +60,6 @@ libgnunet_plugin_rest_identity_la_SOURCES = \ | |||
60 | libgnunet_plugin_rest_identity_la_LIBADD = \ | 60 | libgnunet_plugin_rest_identity_la_LIBADD = \ |
61 | libgnunetidentity.la \ | 61 | libgnunetidentity.la \ |
62 | $(top_builddir)/src/rest/libgnunetrest.la \ | 62 | $(top_builddir)/src/rest/libgnunetrest.la \ |
63 | $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ | ||
64 | $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \ | ||
65 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | 63 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ |
66 | $(LTLIBINTL) -ljansson -lmicrohttpd | 64 | $(LTLIBINTL) -ljansson -lmicrohttpd |
67 | libgnunet_plugin_rest_identity_la_LDFLAGS = \ | 65 | libgnunet_plugin_rest_identity_la_LDFLAGS = \ |
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 355d75fd9..a518a74cc 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2012-2015 GNUnet e.V. | 3 | Copyright (C) 2012-2015 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software: you can redistribute it and/or modify it | 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 | 6 | under the terms of the GNU Affero General Public License as published |
@@ -11,74 +11,51 @@ | |||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Affero General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Affero General Public License | 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/>. | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | /** | 18 | /** |
19 | * @author Martin Schanzenbach | 19 | * @author Martin Schanzenbach |
20 | * @author Philippe Buschmann | ||
20 | * @file identity/plugin_rest_identity.c | 21 | * @file identity/plugin_rest_identity.c |
21 | * @brief GNUnet Namestore REST plugin | 22 | * @brief GNUnet Identity REST plugin |
22 | * | ||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "platform.h" | 25 | #include "platform.h" |
26 | #include "gnunet_rest_plugin.h" | 26 | #include "gnunet_rest_plugin.h" |
27 | #include "gnunet_identity_service.h" | 27 | #include "gnunet_identity_service.h" |
28 | #include "gnunet_rest_lib.h" | 28 | #include "gnunet_rest_lib.h" |
29 | #include "gnunet_jsonapi_lib.h" | ||
30 | #include "gnunet_jsonapi_util.h" | ||
31 | #include "microhttpd.h" | 29 | #include "microhttpd.h" |
32 | #include <jansson.h> | 30 | #include <jansson.h> |
33 | #include "gnunet_signatures.h" | ||
34 | 31 | ||
35 | /** | ||
36 | * REST root namespace | ||
37 | */ | ||
38 | #define GNUNET_REST_API_NS_IDENTITY "/identity" | 32 | #define GNUNET_REST_API_NS_IDENTITY "/identity" |
39 | 33 | ||
40 | /** | 34 | /** |
41 | * State while collecting all egos | 35 | * Parameter names |
42 | */ | ||
43 | #define ID_REST_STATE_INIT 0 | ||
44 | |||
45 | /** | ||
46 | * Done collecting egos | ||
47 | */ | ||
48 | #define ID_REST_STATE_POST_INIT 1 | ||
49 | |||
50 | /** | ||
51 | * Resource type | ||
52 | */ | ||
53 | #define GNUNET_REST_JSONAPI_IDENTITY_EGO "ego" | ||
54 | |||
55 | /** | ||
56 | * Name attribute | ||
57 | */ | ||
58 | #define GNUNET_REST_JSONAPI_IDENTITY_NAME "name" | ||
59 | |||
60 | /** | ||
61 | * Attribute to rename "name" TODO we changed id to the pubkey | ||
62 | * so this can be unified with "name" | ||
63 | */ | ||
64 | #define GNUNET_REST_JSONAPI_IDENTITY_NEWNAME "newname" | ||
65 | |||
66 | /** | ||
67 | * URL parameter to change the subsytem for ego | ||
68 | */ | 36 | */ |
69 | #define GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM "subsystem" | 37 | #define GNUNET_REST_PARAM_PUBKEY "pubkey" |
70 | 38 | #define GNUNET_REST_PARAM_SUBSYSTEM "subsystem" | |
39 | #define GNUNET_REST_PARAM_NAME "name" | ||
40 | #define GNUNET_REST_PARAM_NEWNAME "newname" | ||
71 | 41 | ||
72 | /** | 42 | /** |
73 | * Error messages | 43 | * Error messages |
74 | */ | 44 | */ |
45 | #define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error" | ||
75 | #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid" | 46 | #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid" |
76 | #define GNUNET_REST_ERROR_NO_DATA "No data" | 47 | #define GNUNET_REST_ERROR_NO_DATA "No data" |
48 | #define GNUNET_REST_ERROR_DATA_INVALID "Data invalid" | ||
77 | 49 | ||
78 | /** | 50 | /** |
79 | * GNUid token lifetime | 51 | * State while collecting all egos |
80 | */ | 52 | */ |
81 | #define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000 | 53 | #define ID_REST_STATE_INIT 0 |
54 | |||
55 | /** | ||
56 | * Done collecting egos | ||
57 | */ | ||
58 | #define ID_REST_STATE_POST_INIT 1 | ||
82 | 59 | ||
83 | /** | 60 | /** |
84 | * The configuration handle | 61 | * The configuration handle |
@@ -129,28 +106,37 @@ struct EgoEntry | |||
129 | struct GNUNET_IDENTITY_Ego *ego; | 106 | struct GNUNET_IDENTITY_Ego *ego; |
130 | }; | 107 | }; |
131 | 108 | ||
132 | |||
133 | struct RequestHandle | 109 | struct RequestHandle |
134 | { | 110 | { |
135 | /** | 111 | /** |
136 | * Ego list | 112 | * The data from the REST request |
137 | */ | 113 | */ |
138 | struct EgoEntry *ego_head; | 114 | const char* data; |
139 | 115 | ||
140 | /** | 116 | /** |
141 | * Ego list | 117 | * The name to look up |
142 | */ | 118 | */ |
143 | struct EgoEntry *ego_tail; | 119 | char *name; |
144 | 120 | ||
145 | /** | 121 | /** |
146 | * Handle to the rest connection | 122 | * the length of the REST data |
147 | */ | 123 | */ |
148 | struct GNUNET_REST_RequestHandle *conndata_handle; | 124 | size_t data_size; |
149 | 125 | ||
150 | /** | 126 | /** |
151 | * response code | 127 | * Requested Subsystem |
152 | */ | 128 | */ |
153 | int response_code; | 129 | char *subsystem; |
130 | |||
131 | /** | ||
132 | * Ego list | ||
133 | */ | ||
134 | struct EgoEntry *ego_head; | ||
135 | |||
136 | /** | ||
137 | * Ego list | ||
138 | */ | ||
139 | struct EgoEntry *ego_tail; | ||
154 | 140 | ||
155 | /** | 141 | /** |
156 | * The processing state | 142 | * The processing state |
@@ -158,7 +144,7 @@ struct RequestHandle | |||
158 | int state; | 144 | int state; |
159 | 145 | ||
160 | /** | 146 | /** |
161 | * Handle to GNS service. | 147 | * Handle to Identity service. |
162 | */ | 148 | */ |
163 | struct GNUNET_IDENTITY_Handle *identity_handle; | 149 | struct GNUNET_IDENTITY_Handle *identity_handle; |
164 | 150 | ||
@@ -168,6 +154,11 @@ struct RequestHandle | |||
168 | struct GNUNET_IDENTITY_Operation *op; | 154 | struct GNUNET_IDENTITY_Operation *op; |
169 | 155 | ||
170 | /** | 156 | /** |
157 | * Rest connection | ||
158 | */ | ||
159 | struct GNUNET_REST_RequestHandle *rest_handle; | ||
160 | |||
161 | /** | ||
171 | * Desired timeout for the lookup (default is no timeout). | 162 | * Desired timeout for the lookup (default is no timeout). |
172 | */ | 163 | */ |
173 | struct GNUNET_TIME_Relative timeout; | 164 | struct GNUNET_TIME_Relative timeout; |
@@ -175,7 +166,7 @@ struct RequestHandle | |||
175 | /** | 166 | /** |
176 | * ID of a task associated with the resolution process. | 167 | * ID of a task associated with the resolution process. |
177 | */ | 168 | */ |
178 | struct GNUNET_SCHEDULER_Task * timeout_task; | 169 | struct GNUNET_SCHEDULER_Task *timeout_task; |
179 | 170 | ||
180 | /** | 171 | /** |
181 | * The plugin result processor | 172 | * The plugin result processor |
@@ -188,81 +179,63 @@ struct RequestHandle | |||
188 | void *proc_cls; | 179 | void *proc_cls; |
189 | 180 | ||
190 | /** | 181 | /** |
191 | * The name to look up | ||
192 | */ | ||
193 | char *name; | ||
194 | |||
195 | /** | ||
196 | * The subsystem set from REST | ||
197 | */ | ||
198 | char *subsys; | ||
199 | |||
200 | /** | ||
201 | * The url | 182 | * The url |
202 | */ | 183 | */ |
203 | char *url; | 184 | char *url; |
204 | 185 | ||
205 | /** | 186 | /** |
206 | * The data from the REST request | 187 | * Error response message |
207 | */ | ||
208 | const char* data; | ||
209 | |||
210 | /** | ||
211 | * the length of the REST data | ||
212 | */ | ||
213 | size_t data_size; | ||
214 | |||
215 | /** | ||
216 | * HTTP method | ||
217 | */ | 188 | */ |
218 | const char* method; | 189 | char *emsg; |
219 | 190 | ||
220 | /** | 191 | /** |
221 | * Error response message | 192 | * Reponse code |
222 | */ | 193 | */ |
223 | char *emsg; | 194 | int response_code; |
224 | 195 | ||
225 | }; | 196 | }; |
226 | 197 | ||
227 | |||
228 | /** | 198 | /** |
229 | * Cleanup lookup handle | 199 | * Cleanup lookup handle |
230 | * @param handle Handle to clean up | 200 | * @param handle Handle to clean up |
231 | */ | 201 | */ |
232 | static void | 202 | static void |
233 | cleanup_handle (struct RequestHandle *handle) | 203 | cleanup_handle (void *cls) |
234 | { | 204 | { |
205 | struct RequestHandle *handle = cls; | ||
235 | struct EgoEntry *ego_entry; | 206 | struct EgoEntry *ego_entry; |
236 | struct EgoEntry *ego_tmp; | 207 | struct EgoEntry *ego_tmp; |
237 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 208 | |
238 | "Cleaning up\n"); | 209 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); |
239 | if (NULL != handle->name) | ||
240 | GNUNET_free (handle->name); | ||
241 | if (NULL != handle->timeout_task) | 210 | if (NULL != handle->timeout_task) |
242 | { | 211 | { |
243 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | 212 | GNUNET_SCHEDULER_cancel (handle->timeout_task); |
244 | handle->timeout_task = NULL; | 213 | handle->timeout_task = NULL; |
245 | } | 214 | } |
246 | if (NULL != handle->identity_handle) | 215 | |
247 | GNUNET_IDENTITY_disconnect (handle->identity_handle); | 216 | if (NULL != handle->subsystem) |
248 | if (NULL != handle->subsys) | 217 | GNUNET_free(handle->subsystem); |
249 | GNUNET_free (handle->subsys); | ||
250 | if (NULL != handle->url) | 218 | if (NULL != handle->url) |
251 | GNUNET_free (handle->url); | 219 | GNUNET_free(handle->url); |
252 | if (NULL != handle->emsg) | 220 | if (NULL != handle->emsg) |
253 | GNUNET_free (handle->emsg); | 221 | GNUNET_free(handle->emsg); |
222 | if (NULL != handle->name) | ||
223 | GNUNET_free (handle->name); | ||
224 | if (NULL != handle->identity_handle) | ||
225 | GNUNET_IDENTITY_disconnect (handle->identity_handle); | ||
226 | |||
254 | for (ego_entry = handle->ego_head; | 227 | for (ego_entry = handle->ego_head; |
255 | NULL != ego_entry;) | 228 | NULL != ego_entry;) |
256 | { | 229 | { |
257 | ego_tmp = ego_entry; | 230 | ego_tmp = ego_entry; |
258 | ego_entry = ego_entry->next; | 231 | ego_entry = ego_entry->next; |
259 | GNUNET_free (ego_tmp->identifier); | 232 | GNUNET_free(ego_tmp->identifier); |
260 | GNUNET_free (ego_tmp->keystring); | 233 | GNUNET_free(ego_tmp->keystring); |
261 | GNUNET_free (ego_tmp); | 234 | GNUNET_free(ego_tmp); |
262 | } | 235 | } |
263 | GNUNET_free (handle); | ||
264 | } | ||
265 | 236 | ||
237 | GNUNET_free(handle); | ||
238 | } | ||
266 | 239 | ||
267 | /** | 240 | /** |
268 | * Task run on errors. Reports an error and cleans up everything. | 241 | * Task run on errors. Reports an error and cleans up everything. |
@@ -274,23 +247,67 @@ do_error (void *cls) | |||
274 | { | 247 | { |
275 | struct RequestHandle *handle = cls; | 248 | struct RequestHandle *handle = cls; |
276 | struct MHD_Response *resp; | 249 | struct MHD_Response *resp; |
277 | char *json_error; | 250 | json_t *json_error = json_object(); |
278 | 251 | char *response; | |
279 | GNUNET_asprintf (&json_error, | 252 | |
280 | "{Error while processing request: %s}", | 253 | if (NULL == handle->emsg) |
281 | &handle->emsg); | 254 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_ERROR_UNKNOWN); |
282 | 255 | ||
283 | resp = GNUNET_REST_create_response (json_error); | 256 | json_object_set_new(json_error,"error", json_string(handle->emsg)); |
284 | handle->proc (handle->proc_cls, | 257 | |
285 | resp, | 258 | if (0 == handle->response_code) |
286 | handle->response_code); | 259 | handle->response_code = MHD_HTTP_OK; |
287 | cleanup_handle (handle); | 260 | response = json_dumps (json_error, 0); |
288 | GNUNET_free (json_error); | 261 | resp = GNUNET_REST_create_response (response); |
262 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
263 | json_decref(json_error); | ||
264 | GNUNET_free(response); | ||
265 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
289 | } | 266 | } |
290 | 267 | ||
291 | 268 | ||
269 | |||
292 | /** | 270 | /** |
293 | * Callback for IDENTITY_get() | 271 | * Get EgoEntry from list with either a public key or a name |
272 | * If public key and name are not NULL, it returns the public key result first | ||
273 | * | ||
274 | * @param handle the RequestHandle | ||
275 | * @param pubkey the public key of an identity (only one can be NULL) | ||
276 | * @param name the name of an identity (only one can be NULL) | ||
277 | * @return EgoEntry or NULL if not found | ||
278 | */ | ||
279 | struct EgoEntry* | ||
280 | get_egoentry(struct RequestHandle *handle, char* pubkey, char *name) | ||
281 | { | ||
282 | struct EgoEntry *ego_entry; | ||
283 | if (NULL != pubkey) | ||
284 | { | ||
285 | for (ego_entry = handle->ego_head; | ||
286 | NULL != ego_entry; | ||
287 | ego_entry = ego_entry->next) | ||
288 | { | ||
289 | if (0 != strcasecmp (pubkey, ego_entry->keystring)) | ||
290 | continue; | ||
291 | return ego_entry; | ||
292 | } | ||
293 | } | ||
294 | if (NULL != name) | ||
295 | { | ||
296 | for (ego_entry = handle->ego_head; | ||
297 | NULL != ego_entry; | ||
298 | ego_entry = ego_entry->next) | ||
299 | { | ||
300 | if (0 != strcasecmp (name, ego_entry->identifier)) | ||
301 | continue; | ||
302 | return ego_entry; | ||
303 | } | ||
304 | } | ||
305 | return NULL; | ||
306 | } | ||
307 | |||
308 | |||
309 | /** | ||
310 | * Callback for GET Request with subsystem | ||
294 | * | 311 | * |
295 | * @param cls the RequestHandle | 312 | * @param cls the RequestHandle |
296 | * @param ego the Ego found | 313 | * @param ego the Ego found |
@@ -298,153 +315,177 @@ do_error (void *cls) | |||
298 | * @param name the id of the ego | 315 | * @param name the id of the ego |
299 | */ | 316 | */ |
300 | static void | 317 | static void |
301 | get_ego_for_subsys (void *cls, | 318 | ego_get_for_subsystem (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, |
302 | struct GNUNET_IDENTITY_Ego *ego, | 319 | const char *name) |
303 | void **ctx, | ||
304 | const char *name) | ||
305 | { | 320 | { |
306 | struct RequestHandle *handle = cls; | 321 | struct RequestHandle *handle = cls; |
307 | struct GNUNET_JSONAPI_Document *json_document; | ||
308 | struct GNUNET_JSONAPI_Resource *json_resource; | ||
309 | struct EgoEntry *ego_entry; | ||
310 | struct MHD_Response *resp; | 322 | struct MHD_Response *resp; |
311 | json_t *name_json; | 323 | struct GNUNET_CRYPTO_EcdsaPublicKey public_key; |
324 | json_t *json_root; | ||
312 | char *result_str; | 325 | char *result_str; |
326 | char *public_key_string; | ||
313 | 327 | ||
314 | json_document = GNUNET_JSONAPI_document_new (); | 328 | if(NULL == ego) |
315 | |||
316 | for (ego_entry = handle->ego_head; | ||
317 | NULL != ego_entry; | ||
318 | ego_entry = ego_entry->next) | ||
319 | { | 329 | { |
320 | if ( (NULL != name) && (0 != strcmp (name, ego_entry->identifier)) ) | 330 | handle->emsg = GNUNET_strdup("No identity found for subsystem"); |
321 | continue; | ||
322 | if (NULL == name) | ||
323 | continue; | ||
324 | json_resource = GNUNET_JSONAPI_resource_new | ||
325 | (GNUNET_REST_JSONAPI_IDENTITY_EGO, ego_entry->keystring); | ||
326 | name_json = json_string (ego_entry->identifier); | ||
327 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
328 | GNUNET_REST_JSONAPI_IDENTITY_NAME, | ||
329 | name_json); | ||
330 | json_decref (name_json); | ||
331 | GNUNET_JSONAPI_document_resource_add (json_document, json_resource); | ||
332 | break; | ||
333 | } | ||
334 | if (0 == GNUNET_JSONAPI_document_resource_count (json_document)) | ||
335 | { | ||
336 | GNUNET_JSONAPI_document_delete (json_document); | ||
337 | handle->emsg = GNUNET_strdup("No identity matches results!"); | ||
338 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 331 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
339 | return; | 332 | return; |
340 | } | 333 | } |
341 | GNUNET_JSONAPI_document_serialize (json_document, &result_str); | 334 | |
342 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | 335 | GNUNET_IDENTITY_ego_get_public_key(ego,&public_key); |
336 | public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string(&public_key); | ||
337 | |||
338 | // create json with subsystem identity | ||
339 | json_root = json_object (); | ||
340 | json_object_set_new (json_root, GNUNET_REST_PARAM_PUBKEY, json_string(public_key_string)); | ||
341 | json_object_set_new (json_root, GNUNET_REST_PARAM_NAME, json_string(name)); | ||
342 | |||
343 | result_str = json_dumps (json_root, 0); | ||
344 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
343 | resp = GNUNET_REST_create_response (result_str); | 345 | resp = GNUNET_REST_create_response (result_str); |
344 | GNUNET_JSONAPI_document_delete (json_document); | 346 | |
347 | json_decref (json_root); | ||
345 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | 348 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); |
346 | GNUNET_free (result_str); | 349 | GNUNET_free(result_str); |
347 | cleanup_handle (handle); | 350 | GNUNET_free(public_key_string); |
351 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
348 | } | 352 | } |
349 | 353 | ||
350 | /** | 354 | /** |
351 | * Create a response with requested ego(s) | 355 | * Handle identity GET request |
352 | * | 356 | * |
353 | * @param con the Rest handle | 357 | * @param con_handle the connection handle |
354 | * @param url the requested url | 358 | * @param url the url |
355 | * @param cls the request handle | 359 | * @param cls the RequestHandle |
356 | */ | 360 | */ |
357 | static void | 361 | void |
358 | ego_info_response (struct GNUNET_REST_RequestHandle *con, | 362 | ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, |
359 | const char *url, | 363 | void *cls) |
360 | void *cls) | ||
361 | { | 364 | { |
362 | const char *egoname; | ||
363 | char *result_str; | ||
364 | char *subsys_val; | ||
365 | char *keystring; | ||
366 | struct RequestHandle *handle = cls; | 365 | struct RequestHandle *handle = cls; |
367 | struct EgoEntry *ego_entry; | 366 | struct EgoEntry *ego_entry; |
368 | struct GNUNET_HashCode key; | 367 | struct GNUNET_HashCode key; |
369 | struct MHD_Response *resp; | 368 | struct MHD_Response *resp; |
370 | struct GNUNET_JSONAPI_Document *json_document; | 369 | char *keystring; |
371 | struct GNUNET_JSONAPI_Resource *json_resource; | 370 | char *egoname; |
372 | json_t *name_str; | 371 | json_t *json_root; |
372 | json_t *json_ego; | ||
373 | char *result_str; | ||
373 | 374 | ||
374 | if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, GNUNET_REST_API_NS_IDENTITY)) | 375 | //requested default identity of subsystem |
376 | GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_SUBSYSTEM, | ||
377 | strlen (GNUNET_REST_PARAM_SUBSYSTEM), &key); | ||
378 | if ( GNUNET_YES | ||
379 | == GNUNET_CONTAINER_multihashmap_contains ( | ||
380 | handle->rest_handle->url_param_map, &key)) | ||
375 | { | 381 | { |
376 | resp = GNUNET_REST_create_response (NULL); | 382 | handle->subsystem = GNUNET_strdup( |
377 | handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); | 383 | GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, |
378 | cleanup_handle (handle); | 384 | &key)); |
385 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", | ||
386 | handle->subsystem); | ||
387 | |||
388 | handle->op = GNUNET_IDENTITY_get (handle->identity_handle, | ||
389 | handle->subsystem, | ||
390 | &ego_get_for_subsystem, | ||
391 | handle); | ||
392 | if (NULL == handle->op) | ||
393 | { | ||
394 | handle->emsg = GNUNET_strdup("No identity found for subsystem"); | ||
395 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
396 | return; | ||
397 | } | ||
379 | return; | 398 | return; |
380 | } | 399 | } |
381 | egoname = NULL; | 400 | egoname = NULL; |
382 | keystring = NULL; | 401 | keystring = NULL; |
383 | if (strlen (GNUNET_REST_API_NS_IDENTITY) < strlen (handle->url)) | 402 | |
403 | //one identity requested with key | ||
404 | GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY, | ||
405 | strlen (GNUNET_REST_PARAM_PUBKEY), | ||
406 | &key); | ||
407 | if ( GNUNET_YES | ||
408 | == GNUNET_CONTAINER_multihashmap_contains ( | ||
409 | handle->rest_handle->url_param_map, &key)) | ||
384 | { | 410 | { |
385 | keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY)+1]; | 411 | keystring = GNUNET_CONTAINER_multihashmap_get ( |
386 | //Return all egos | 412 | handle->rest_handle->url_param_map, &key); |
387 | for (ego_entry = handle->ego_head; | 413 | |
388 | NULL != ego_entry; | 414 | ego_entry = get_egoentry(handle, keystring, NULL); |
389 | ego_entry = ego_entry->next) | 415 | if (NULL == ego_entry) |
390 | { | 416 | { |
391 | if ( (NULL != keystring) && (0 != strcmp (keystring, ego_entry->keystring)) ) | 417 | handle->emsg = GNUNET_strdup("No identity found for public key"); |
392 | continue; | 418 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
393 | egoname = ego_entry->identifier; | 419 | return; |
394 | } | 420 | } |
421 | egoname = ego_entry->identifier; | ||
395 | } | 422 | } |
396 | 423 | ||
397 | if ( NULL == egoname ) { | 424 | //one identity requested with name |
398 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM, | 425 | if (NULL == egoname) |
399 | strlen (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM), | 426 | { |
400 | &key); | 427 | GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_NAME, |
401 | if ( GNUNET_YES == | 428 | strlen (GNUNET_REST_PARAM_NAME), |
402 | GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, | 429 | &key); |
403 | &key) ) | 430 | if ( GNUNET_YES |
431 | == GNUNET_CONTAINER_multihashmap_contains ( | ||
432 | handle->rest_handle->url_param_map, &key)) | ||
404 | { | 433 | { |
405 | subsys_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, | 434 | egoname = GNUNET_CONTAINER_multihashmap_get ( |
406 | &key); | 435 | handle->rest_handle->url_param_map, &key); |
407 | if (NULL != subsys_val) | 436 | if (0 >= strlen(egoname)) |
408 | { | 437 | { |
409 | GNUNET_asprintf (&handle->subsys, "%s", subsys_val); | 438 | handle->emsg = GNUNET_strdup("No identity found for name"); |
410 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsys_val); | 439 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
411 | handle->op = GNUNET_IDENTITY_get (handle->identity_handle, | ||
412 | handle->subsys, | ||
413 | &get_ego_for_subsys, | ||
414 | handle); | ||
415 | return; | 440 | return; |
416 | } | 441 | } |
442 | //LOWERCASE ego names? | ||
443 | GNUNET_STRINGS_utf8_tolower(egoname, egoname); | ||
417 | } | 444 | } |
418 | } | 445 | } |
419 | 446 | ||
420 | json_document = GNUNET_JSONAPI_document_new (); | 447 | json_root = json_array (); |
421 | 448 | //Return ego/egos | |
422 | //Return all egos | ||
423 | for (ego_entry = handle->ego_head; | 449 | for (ego_entry = handle->ego_head; |
424 | NULL != ego_entry; | 450 | NULL != ego_entry; ego_entry = ego_entry->next) |
425 | ego_entry = ego_entry->next) | ||
426 | { | 451 | { |
427 | if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) ) | 452 | //if only one ego requested |
428 | continue; | 453 | if ((NULL != egoname)){ |
429 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, | 454 | if(0 != strcmp (egoname, ego_entry->identifier)){ |
430 | ego_entry->keystring); | 455 | continue; |
431 | name_str = json_string (ego_entry->identifier); | 456 | } |
432 | GNUNET_JSONAPI_resource_add_attr ( | 457 | } |
433 | json_resource, | 458 | |
434 | GNUNET_REST_JSONAPI_IDENTITY_NAME, | 459 | json_ego = json_object (); |
435 | name_str); | 460 | json_object_set_new (json_ego, |
436 | json_decref (name_str); | 461 | GNUNET_REST_PARAM_PUBKEY, |
437 | GNUNET_JSONAPI_document_resource_add (json_document, json_resource); | 462 | json_string (ego_entry->keystring)); |
463 | json_object_set_new (json_ego, | ||
464 | GNUNET_REST_PARAM_NAME, | ||
465 | json_string (ego_entry->identifier)); | ||
466 | json_array_append (json_root, json_ego); | ||
467 | json_decref (json_ego); | ||
468 | } | ||
469 | |||
470 | if ((size_t) 0 == json_array_size (json_root)) | ||
471 | { | ||
472 | json_decref (json_root); | ||
473 | handle->emsg = GNUNET_strdup("No identities found!"); | ||
474 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
475 | return; | ||
438 | } | 476 | } |
439 | GNUNET_JSONAPI_document_serialize (json_document, &result_str); | 477 | |
440 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | 478 | result_str = json_dumps (json_root, 0); |
479 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
441 | resp = GNUNET_REST_create_response (result_str); | 480 | resp = GNUNET_REST_create_response (result_str); |
442 | GNUNET_JSONAPI_document_delete (json_document); | 481 | |
482 | json_decref (json_root); | ||
443 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | 483 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); |
444 | GNUNET_free (result_str); | 484 | GNUNET_free(result_str); |
445 | cleanup_handle (handle); | 485 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); |
446 | } | 486 | } |
447 | 487 | ||
488 | |||
448 | /** | 489 | /** |
449 | * Processing finished | 490 | * Processing finished |
450 | * | 491 | * |
@@ -460,311 +501,363 @@ do_finished (void *cls, const char *emsg) | |||
460 | handle->op = NULL; | 501 | handle->op = NULL; |
461 | if (NULL != emsg) | 502 | if (NULL != emsg) |
462 | { | 503 | { |
463 | handle->emsg = GNUNET_strdup (emsg); | 504 | handle->emsg = GNUNET_strdup(emsg); |
464 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 505 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
465 | return; | 506 | return; |
466 | } | 507 | } |
467 | resp = GNUNET_REST_create_response (NULL); | 508 | resp = GNUNET_REST_create_response (NULL); |
468 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); | 509 | handle->proc (handle->proc_cls, resp, handle->response_code); |
469 | cleanup_handle (handle); | 510 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); |
470 | } | 511 | } |
471 | 512 | ||
513 | |||
472 | /** | 514 | /** |
473 | * Create a new ego | 515 | * Handle identity PUT request |
474 | * | 516 | * |
475 | * @param con rest handle | 517 | * @param con_handle the connection handle |
476 | * @param url url | 518 | * @param url the url |
477 | * @param cls request handle | 519 | * @param cls the RequestHandle |
478 | */ | 520 | */ |
479 | static void | 521 | void |
480 | ego_create_cont (struct GNUNET_REST_RequestHandle *con, | 522 | ego_edit (struct GNUNET_REST_RequestHandle *con_handle, |
481 | const char *url, | 523 | const char* url, |
482 | void *cls) | 524 | void *cls) |
483 | { | 525 | { |
484 | struct RequestHandle *handle = cls; | 526 | struct RequestHandle *handle = cls; |
485 | struct EgoEntry *ego_entry; | 527 | struct EgoEntry *ego_entry; |
528 | struct EgoEntry *ego_entry_tmp; | ||
486 | struct MHD_Response *resp; | 529 | struct MHD_Response *resp; |
487 | struct GNUNET_JSONAPI_Document *json_obj; | 530 | int json_state; |
488 | struct GNUNET_JSONAPI_Resource *json_res; | ||
489 | json_t *egoname_json; | ||
490 | json_t *data_js; | 531 | json_t *data_js; |
491 | json_error_t err; | 532 | json_error_t err; |
492 | const char* egoname; | 533 | char *pubkey; |
493 | char term_data[handle->data_size+1]; | 534 | char *name; |
494 | struct GNUNET_JSON_Specification docspec[] = { | 535 | char *newsubsys; |
495 | GNUNET_JSON_spec_jsonapi_document (&json_obj), | 536 | char *newname; |
496 | GNUNET_JSON_spec_end() | 537 | char term_data[handle->data_size + 1]; |
497 | }; | 538 | |
498 | if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url)) | 539 | //if no data |
499 | { | ||
500 | handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); | ||
501 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
502 | return; | ||
503 | } | ||
504 | if (0 >= handle->data_size) | 540 | if (0 >= handle->data_size) |
505 | { | 541 | { |
506 | handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); | 542 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); |
507 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 543 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
508 | return; | 544 | return; |
509 | } | 545 | } |
546 | //if not json | ||
510 | term_data[handle->data_size] = '\0'; | 547 | term_data[handle->data_size] = '\0'; |
511 | GNUNET_memcpy (term_data, handle->data, handle->data_size); | 548 | GNUNET_memcpy(term_data, handle->data, handle->data_size); |
512 | data_js = json_loads (term_data, | 549 | data_js = json_loads (term_data,JSON_DECODE_ANY,&err); |
513 | JSON_DECODE_ANY, | ||
514 | &err); | ||
515 | GNUNET_assert (NULL != data_js); | ||
516 | GNUNET_assert (GNUNET_OK == | ||
517 | GNUNET_JSON_parse (data_js, docspec, | ||
518 | NULL, NULL)); | ||
519 | 550 | ||
520 | json_decref (data_js); | 551 | if (NULL == data_js) |
521 | |||
522 | if (NULL == json_obj) | ||
523 | { | 552 | { |
553 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); | ||
524 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 554 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
525 | return; | 555 | return; |
526 | } | 556 | } |
527 | if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) | 557 | |
528 | { | 558 | ego_entry = NULL; |
529 | GNUNET_JSONAPI_document_delete (json_obj); | 559 | pubkey = NULL; |
530 | handle->emsg = GNUNET_strdup ("Provided resource count invalid"); | 560 | name = NULL; |
531 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 561 | newname = NULL; |
532 | return; | 562 | //NEW NAME |
533 | } | 563 | json_state = 0; |
534 | json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); | 564 | json_state = json_unpack(data_js, |
535 | if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO)) | 565 | "{s:s,s?:s,s?:s}", |
536 | { | 566 | GNUNET_REST_PARAM_NEWNAME, |
537 | GNUNET_JSONAPI_document_delete (json_obj); | 567 | &newname, |
538 | resp = GNUNET_REST_create_response (NULL); | 568 | GNUNET_REST_PARAM_PUBKEY, |
539 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | 569 | &pubkey, |
540 | cleanup_handle (handle); | 570 | GNUNET_REST_PARAM_NAME, |
541 | return; | 571 | &name); |
542 | } | 572 | //Change name with pubkey or name identifier |
543 | egoname_json = GNUNET_JSONAPI_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_NAME); | 573 | if (0 == json_state) |
544 | if (!json_is_string (egoname_json)) | ||
545 | { | 574 | { |
546 | GNUNET_JSONAPI_document_delete (json_obj); | 575 | if (NULL == newname) |
547 | handle->emsg = GNUNET_strdup ("No name provided"); | 576 | { |
548 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 577 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); |
578 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
579 | json_decref (data_js); | ||
580 | return; | ||
581 | } | ||
582 | |||
583 | if (0 >= strlen(newname)) | ||
584 | { | ||
585 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
586 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
587 | json_decref (data_js); | ||
588 | return; | ||
589 | } | ||
590 | //lower case name | ||
591 | GNUNET_STRINGS_utf8_tolower(newname,newname); | ||
592 | |||
593 | ego_entry = get_egoentry(handle,pubkey,name); | ||
594 | |||
595 | if (NULL == ego_entry) | ||
596 | { | ||
597 | resp = GNUNET_REST_create_response (NULL); | ||
598 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); | ||
599 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
600 | json_decref (data_js); | ||
601 | return; | ||
602 | } | ||
603 | |||
604 | for (ego_entry_tmp = handle->ego_head; | ||
605 | NULL != ego_entry_tmp; ego_entry_tmp = ego_entry_tmp->next) | ||
606 | { | ||
607 | if (0 == strcasecmp (newname, ego_entry_tmp->identifier)) | ||
608 | { | ||
609 | //Ego with same name not allowed | ||
610 | resp = GNUNET_REST_create_response (NULL); | ||
611 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | ||
612 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
613 | json_decref (data_js); | ||
614 | return; | ||
615 | } | ||
616 | } | ||
617 | handle->response_code = MHD_HTTP_NO_CONTENT; | ||
618 | handle->op = GNUNET_IDENTITY_rename (handle->identity_handle, | ||
619 | ego_entry->identifier, newname, | ||
620 | &do_finished, handle); | ||
621 | json_decref (data_js); | ||
549 | return; | 622 | return; |
550 | } | 623 | } |
551 | egoname = json_string_value (egoname_json); | 624 | |
552 | for (ego_entry = handle->ego_head; | 625 | newsubsys = NULL; |
553 | NULL != ego_entry; | 626 | //SUBSYSTEM |
554 | ego_entry = ego_entry->next) | 627 | json_state = 0; |
628 | json_state = json_unpack(data_js, | ||
629 | "{s:s,s?:s,s?:s}", | ||
630 | GNUNET_REST_PARAM_SUBSYSTEM, | ||
631 | &newsubsys, | ||
632 | GNUNET_REST_PARAM_PUBKEY, | ||
633 | &pubkey, | ||
634 | GNUNET_REST_PARAM_NAME, | ||
635 | &name); | ||
636 | //Change subsystem with pubkey or name identifier | ||
637 | if (0 == json_state) | ||
555 | { | 638 | { |
556 | if (0 == strcasecmp (egoname, ego_entry->identifier)) | 639 | if (NULL == newsubsys || (NULL == pubkey && NULL == name)) |
557 | { | 640 | { |
558 | GNUNET_JSONAPI_document_delete (json_obj); | 641 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); |
559 | resp = GNUNET_REST_create_response (NULL); | 642 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
560 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | 643 | json_decref (data_js); |
561 | cleanup_handle (handle); | 644 | return; |
645 | } | ||
646 | |||
647 | if (0 >= strlen(newsubsys)) | ||
648 | { | ||
649 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
650 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
651 | json_decref (data_js); | ||
562 | return; | 652 | return; |
563 | } | 653 | } |
654 | |||
655 | ego_entry = get_egoentry(handle, pubkey, name); | ||
656 | |||
657 | if (NULL == ego_entry) | ||
658 | { | ||
659 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
660 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
661 | json_decref (data_js); | ||
662 | return; | ||
663 | } | ||
664 | |||
665 | handle->response_code = MHD_HTTP_NO_CONTENT; | ||
666 | handle->op = GNUNET_IDENTITY_set (handle->identity_handle, | ||
667 | newsubsys, | ||
668 | ego_entry->ego, | ||
669 | &do_finished, | ||
670 | handle); | ||
671 | json_decref (data_js); | ||
672 | return; | ||
564 | } | 673 | } |
565 | GNUNET_asprintf (&handle->name, "%s", egoname); | ||
566 | GNUNET_JSONAPI_document_delete (json_obj); | ||
567 | handle->op = GNUNET_IDENTITY_create (handle->identity_handle, | ||
568 | handle->name, | ||
569 | &do_finished, | ||
570 | handle); | ||
571 | } | ||
572 | 674 | ||
675 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
676 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
677 | json_decref (data_js); | ||
678 | return; | ||
679 | } | ||
573 | 680 | ||
574 | /** | 681 | /** |
575 | * Handle ego edit request | 682 | * Handle identity POST request |
576 | * | 683 | * |
577 | * @param con rest connection handle | 684 | * @param con_handle the connection handle |
578 | * @param url the url that is requested | 685 | * @param url the url |
579 | * @param cls the RequestHandle | 686 | * @param cls the RequestHandle |
580 | */ | 687 | */ |
581 | static void | 688 | void |
582 | ego_edit_cont (struct GNUNET_REST_RequestHandle *con, | 689 | ego_create (struct GNUNET_REST_RequestHandle *con_handle, const char* url, |
583 | const char *url, | 690 | void *cls) |
584 | void *cls) | ||
585 | { | 691 | { |
586 | struct GNUNET_JSONAPI_Document *json_obj; | ||
587 | struct GNUNET_JSONAPI_Resource *json_res; | ||
588 | struct RequestHandle *handle = cls; | 692 | struct RequestHandle *handle = cls; |
589 | struct EgoEntry *ego_entry; | 693 | struct EgoEntry *ego_entry; |
590 | struct EgoEntry *ego_entry_tmp; | ||
591 | struct MHD_Response *resp; | 694 | struct MHD_Response *resp; |
592 | json_t *subsys_json; | ||
593 | json_t *name_json; | ||
594 | json_t *data_js; | 695 | json_t *data_js; |
595 | json_error_t err; | 696 | json_error_t err; |
596 | const char *keystring; | 697 | char* egoname; |
597 | const char *subsys; | 698 | int json_unpack_state; |
598 | const char *newname; | 699 | char term_data[handle->data_size + 1]; |
599 | char term_data[handle->data_size+1]; | ||
600 | int ego_exists = GNUNET_NO; | ||
601 | struct GNUNET_JSON_Specification docspec[] = { | ||
602 | GNUNET_JSON_spec_jsonapi_document (&json_obj), | ||
603 | GNUNET_JSON_spec_end() | ||
604 | }; | ||
605 | 700 | ||
606 | if (strlen (GNUNET_REST_API_NS_IDENTITY) > strlen (handle->url)) | 701 | if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url)) |
607 | { | 702 | { |
608 | handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); | 703 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_RESOURCE_INVALID); |
609 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 704 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
610 | return; | 705 | return; |
611 | } | 706 | } |
612 | 707 | ||
613 | keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1]; | ||
614 | |||
615 | for (ego_entry = handle->ego_head; | ||
616 | NULL != ego_entry; | ||
617 | ego_entry = ego_entry->next) | ||
618 | { | ||
619 | if (0 != strcasecmp (keystring, ego_entry->keystring)) | ||
620 | continue; | ||
621 | ego_exists = GNUNET_YES; | ||
622 | break; | ||
623 | } | ||
624 | |||
625 | if (GNUNET_NO == ego_exists) | ||
626 | { | ||
627 | resp = GNUNET_REST_create_response (NULL); | ||
628 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); | ||
629 | cleanup_handle (handle); | ||
630 | return; | ||
631 | } | ||
632 | |||
633 | if (0 >= handle->data_size) | 708 | if (0 >= handle->data_size) |
634 | { | 709 | { |
635 | handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); | 710 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); |
636 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 711 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
637 | return; | 712 | return; |
638 | } | 713 | } |
639 | |||
640 | term_data[handle->data_size] = '\0'; | 714 | term_data[handle->data_size] = '\0'; |
641 | GNUNET_memcpy (term_data, handle->data, handle->data_size); | 715 | GNUNET_memcpy(term_data, handle->data, handle->data_size); |
642 | data_js = json_loads (term_data, | 716 | data_js = json_loads (term_data, |
643 | JSON_DECODE_ANY, | 717 | JSON_DECODE_ANY, |
644 | &err); | 718 | &err); |
645 | GNUNET_assert (NULL != data_js); | 719 | if (NULL == data_js) |
646 | GNUNET_assert (GNUNET_OK == | ||
647 | GNUNET_JSON_parse (data_js, docspec, | ||
648 | NULL, NULL)); | ||
649 | |||
650 | json_decref (data_js); | ||
651 | |||
652 | if (NULL == json_obj) | ||
653 | { | 720 | { |
654 | handle->emsg = GNUNET_strdup ("Data invalid"); | 721 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); |
655 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 722 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
723 | json_decref (data_js); | ||
656 | return; | 724 | return; |
657 | } | 725 | } |
658 | 726 | json_unpack_state = 0; | |
659 | if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) | 727 | json_unpack_state = json_unpack(data_js, |
728 | "{s:s!}", | ||
729 | GNUNET_REST_PARAM_NAME, | ||
730 | &egoname); | ||
731 | if (0 != json_unpack_state) | ||
660 | { | 732 | { |
661 | GNUNET_JSONAPI_document_delete (json_obj); | 733 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); |
662 | handle->emsg = GNUNET_strdup ("Resource amount invalid"); | ||
663 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 734 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
735 | json_decref (data_js); | ||
664 | return; | 736 | return; |
665 | } | 737 | } |
666 | json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); | ||
667 | 738 | ||
668 | if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO)) | 739 | if (NULL == egoname) |
669 | { | 740 | { |
670 | GNUNET_JSONAPI_document_delete (json_obj); | 741 | handle->emsg = GNUNET_strdup("No name provided"); |
671 | handle->emsg = GNUNET_strdup ("Resource type invalid"); | ||
672 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 742 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
743 | json_decref (data_js); | ||
673 | return; | 744 | return; |
674 | } | 745 | } |
675 | 746 | if (0 >= strlen (egoname)) | |
676 | //This is a rename | ||
677 | name_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
678 | GNUNET_REST_JSONAPI_IDENTITY_NEWNAME); | ||
679 | if ((NULL != name_json) && json_is_string (name_json)) | ||
680 | { | 747 | { |
681 | newname = json_string_value (name_json); | 748 | json_decref (data_js); |
682 | for (ego_entry_tmp = handle->ego_head; | 749 | handle->emsg = GNUNET_strdup("No name provided"); |
683 | NULL != ego_entry_tmp; | 750 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
684 | ego_entry_tmp = ego_entry_tmp->next) | ||
685 | { | ||
686 | if (0 == strcasecmp (newname, ego_entry_tmp->identifier) && | ||
687 | 0 != strcasecmp (keystring, ego_entry_tmp->keystring)) | ||
688 | { | ||
689 | //Ego with same name not allowed | ||
690 | GNUNET_JSONAPI_document_delete (json_obj); | ||
691 | resp = GNUNET_REST_create_response (NULL); | ||
692 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | ||
693 | cleanup_handle (handle); | ||
694 | return; | ||
695 | } | ||
696 | } | ||
697 | handle->op = GNUNET_IDENTITY_rename (handle->identity_handle, | ||
698 | ego_entry->identifier, | ||
699 | newname, | ||
700 | &do_finished, | ||
701 | handle); | ||
702 | GNUNET_JSONAPI_document_delete (json_obj); | ||
703 | return; | 751 | return; |
704 | } | 752 | } |
705 | 753 | GNUNET_STRINGS_utf8_tolower(egoname, egoname); | |
706 | //Set subsystem | 754 | for (ego_entry = handle->ego_head; |
707 | subsys_json = GNUNET_JSONAPI_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM); | 755 | NULL != ego_entry; ego_entry = ego_entry->next) |
708 | if ( (NULL != subsys_json) && json_is_string (subsys_json)) | ||
709 | { | 756 | { |
710 | subsys = json_string_value (subsys_json); | 757 | if (0 == strcasecmp (egoname, ego_entry->identifier)) |
711 | GNUNET_asprintf (&handle->subsys, "%s", subsys); | 758 | { |
712 | GNUNET_JSONAPI_document_delete (json_obj); | 759 | resp = GNUNET_REST_create_response (NULL); |
713 | handle->op = GNUNET_IDENTITY_set (handle->identity_handle, | 760 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); |
714 | handle->subsys, | 761 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); |
715 | ego_entry->ego, | 762 | json_decref (data_js); |
716 | &do_finished, | 763 | return; |
717 | handle); | 764 | } |
718 | return; | ||
719 | } | 765 | } |
720 | GNUNET_JSONAPI_document_delete (json_obj); | 766 | handle->name = GNUNET_strdup(egoname); |
721 | handle->emsg = GNUNET_strdup ("Subsystem not provided"); | 767 | json_decref (data_js); |
722 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 768 | handle->response_code = MHD_HTTP_CREATED; |
769 | handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name, | ||
770 | &do_finished, handle); | ||
723 | } | 771 | } |
724 | 772 | ||
773 | /** | ||
774 | * Handle identity DELETE request | ||
775 | * | ||
776 | * @param con_handle the connection handle | ||
777 | * @param url the url | ||
778 | * @param cls the RequestHandle | ||
779 | */ | ||
725 | void | 780 | void |
726 | ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, | 781 | ego_delete (struct GNUNET_REST_RequestHandle *con_handle, const char* url, |
727 | const char* url, | 782 | void *cls) |
728 | void *cls) | ||
729 | { | 783 | { |
730 | const char *keystring; | 784 | struct RequestHandle *handle = cls; |
731 | struct EgoEntry *ego_entry; | 785 | struct EgoEntry *ego_entry; |
786 | struct GNUNET_HashCode key; | ||
732 | struct MHD_Response *resp; | 787 | struct MHD_Response *resp; |
733 | struct RequestHandle *handle = cls; | 788 | const char *keystring; |
789 | char *egoname; | ||
734 | int ego_exists = GNUNET_NO; | 790 | int ego_exists = GNUNET_NO; |
735 | 791 | ||
736 | if (strlen (GNUNET_REST_API_NS_IDENTITY) >= strlen (handle->url)) | 792 | keystring = NULL; |
793 | egoname = NULL; | ||
794 | |||
795 | //delete with pubkey | ||
796 | GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY, | ||
797 | strlen (GNUNET_REST_PARAM_PUBKEY), &key); | ||
798 | if ( GNUNET_YES | ||
799 | == GNUNET_CONTAINER_multihashmap_contains ( | ||
800 | handle->rest_handle->url_param_map, &key)) | ||
737 | { | 801 | { |
738 | handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); | 802 | keystring = GNUNET_CONTAINER_multihashmap_get ( |
739 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 803 | handle->rest_handle->url_param_map,&key); |
740 | return; | ||
741 | } | 804 | } |
742 | 805 | ||
743 | keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1]; | 806 | GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_NAME, |
744 | for (ego_entry = handle->ego_head; | 807 | strlen (GNUNET_REST_PARAM_NAME), &key); |
745 | NULL != ego_entry; | 808 | if ( GNUNET_YES |
746 | ego_entry = ego_entry->next) | 809 | == GNUNET_CONTAINER_multihashmap_contains ( |
810 | handle->rest_handle->url_param_map, &key)) | ||
747 | { | 811 | { |
748 | if (0 != strcasecmp (keystring, ego_entry->keystring)) | 812 | egoname = GNUNET_CONTAINER_multihashmap_get ( |
749 | continue; | 813 | handle->rest_handle->url_param_map, &key); |
750 | ego_exists = GNUNET_YES; | 814 | //LOWERCASE ego names? |
751 | break; | 815 | //GNUNET_STRINGS_utf8_tolower(egoname, egoname); |
752 | } | 816 | } |
817 | |||
818 | if (NULL != keystring) | ||
819 | { | ||
820 | for (ego_entry = handle->ego_head; | ||
821 | NULL != ego_entry; ego_entry = ego_entry->next) | ||
822 | { | ||
823 | if (0 != strcasecmp (keystring, ego_entry->keystring)) | ||
824 | continue; | ||
825 | ego_exists = GNUNET_YES; | ||
826 | break; | ||
827 | } | ||
828 | } | ||
829 | else if (NULL != egoname) | ||
830 | { | ||
831 | for (ego_entry = handle->ego_head; | ||
832 | NULL != ego_entry; ego_entry = ego_entry->next) | ||
833 | { | ||
834 | if (0 != strcmp (egoname, ego_entry->identifier)) | ||
835 | continue; | ||
836 | ego_exists = GNUNET_YES; | ||
837 | break; | ||
838 | } | ||
839 | } | ||
840 | else | ||
841 | { | ||
842 | handle->emsg = GNUNET_strdup("Missing parameter pubkey or name"); | ||
843 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
844 | return; | ||
845 | } | ||
846 | |||
753 | if (GNUNET_NO == ego_exists) | 847 | if (GNUNET_NO == ego_exists) |
754 | { | 848 | { |
755 | resp = GNUNET_REST_create_response (NULL); | 849 | resp = GNUNET_REST_create_response (NULL); |
756 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); | 850 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); |
757 | cleanup_handle (handle); | 851 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); |
758 | return; | 852 | return; |
759 | } | 853 | } |
854 | handle->response_code = MHD_HTTP_NO_CONTENT; | ||
760 | handle->op = GNUNET_IDENTITY_delete (handle->identity_handle, | 855 | handle->op = GNUNET_IDENTITY_delete (handle->identity_handle, |
761 | ego_entry->identifier, | 856 | ego_entry->identifier, &do_finished, |
762 | &do_finished, | 857 | handle); |
763 | handle); | ||
764 | 858 | ||
765 | } | 859 | } |
766 | 860 | ||
767 | |||
768 | /** | 861 | /** |
769 | * Respond to OPTIONS request | 862 | * Respond to OPTIONS request |
770 | * | 863 | * |
@@ -773,20 +866,17 @@ ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
773 | * @param cls the RequestHandle | 866 | * @param cls the RequestHandle |
774 | */ | 867 | */ |
775 | static void | 868 | static void |
776 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, | 869 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url, |
777 | const char* url, | 870 | void *cls) |
778 | void *cls) | ||
779 | { | 871 | { |
780 | struct MHD_Response *resp; | 872 | struct MHD_Response *resp; |
781 | struct RequestHandle *handle = cls; | 873 | struct RequestHandle *handle = cls; |
782 | 874 | ||
783 | //For now, independent of path return all options | 875 | //For now, independent of path return all options |
784 | resp = GNUNET_REST_create_response (NULL); | 876 | resp = GNUNET_REST_create_response (NULL); |
785 | MHD_add_response_header (resp, | 877 | MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); |
786 | "Access-Control-Allow-Methods", | ||
787 | allow_methods); | ||
788 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | 878 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); |
789 | cleanup_handle (handle); | 879 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); |
790 | return; | 880 | return; |
791 | } | 881 | } |
792 | 882 | ||
@@ -800,18 +890,17 @@ init_cont (struct RequestHandle *handle) | |||
800 | { | 890 | { |
801 | struct GNUNET_REST_RequestHandlerError err; | 891 | struct GNUNET_REST_RequestHandlerError err; |
802 | static const struct GNUNET_REST_RequestHandler handlers[] = { | 892 | static const struct GNUNET_REST_RequestHandler handlers[] = { |
803 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_info_response}, | 893 | { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get }, |
804 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create_cont}, | 894 | { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit }, |
805 | {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit_cont}, | 895 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create }, |
806 | {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete_cont}, | 896 | { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete }, |
807 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont}, | 897 | { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont }, |
808 | GNUNET_REST_HANDLER_END | 898 | GNUNET_REST_HANDLER_END |
809 | }; | 899 | }; |
810 | 900 | ||
811 | if (GNUNET_NO == GNUNET_JSONAPI_handle_request (handle->conndata_handle, | 901 | if (GNUNET_NO |
812 | handlers, | 902 | == GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, |
813 | &err, | 903 | handle)) |
814 | handle)) | ||
815 | { | 904 | { |
816 | handle->response_code = err.error_code; | 905 | handle->response_code = err.error_code; |
817 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 906 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
@@ -852,10 +941,8 @@ init_cont (struct RequestHandle *handle) | |||
852 | * must thus no longer be used | 941 | * must thus no longer be used |
853 | */ | 942 | */ |
854 | static void | 943 | static void |
855 | list_ego (void *cls, | 944 | init_egos (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, |
856 | struct GNUNET_IDENTITY_Ego *ego, | 945 | const char *identifier) |
857 | void **ctx, | ||
858 | const char *identifier) | ||
859 | { | 946 | { |
860 | struct RequestHandle *handle = cls; | 947 | struct RequestHandle *handle = cls; |
861 | struct EgoEntry *ego_entry; | 948 | struct EgoEntry *ego_entry; |
@@ -867,16 +954,16 @@ list_ego (void *cls, | |||
867 | init_cont (handle); | 954 | init_cont (handle); |
868 | return; | 955 | return; |
869 | } | 956 | } |
870 | if (ID_REST_STATE_INIT == handle->state) { | 957 | if (ID_REST_STATE_INIT == handle->state) |
871 | ego_entry = GNUNET_new (struct EgoEntry); | 958 | { |
959 | ego_entry = GNUNET_new(struct EgoEntry); | ||
872 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | 960 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); |
873 | ego_entry->keystring = | 961 | ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); |
874 | GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); | ||
875 | ego_entry->ego = ego; | 962 | ego_entry->ego = ego; |
876 | GNUNET_asprintf (&ego_entry->identifier, "%s", identifier); | 963 | GNUNET_asprintf (&ego_entry->identifier, "%s", identifier); |
877 | GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); | 964 | GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail, |
965 | ego_entry); | ||
878 | } | 966 | } |
879 | |||
880 | } | 967 | } |
881 | 968 | ||
882 | /** | 969 | /** |
@@ -891,39 +978,30 @@ list_ego (void *cls, | |||
891 | * @return GNUNET_OK if request accepted | 978 | * @return GNUNET_OK if request accepted |
892 | */ | 979 | */ |
893 | static void | 980 | static void |
894 | rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, | 981 | rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle, |
895 | GNUNET_REST_ResultProcessor proc, | 982 | GNUNET_REST_ResultProcessor proc, void *proc_cls) |
896 | void *proc_cls) | ||
897 | { | 983 | { |
898 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | 984 | struct RequestHandle *handle = GNUNET_new(struct RequestHandle); |
899 | |||
900 | |||
901 | 985 | ||
986 | handle->response_code = 0; | ||
902 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | 987 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; |
903 | |||
904 | handle->proc_cls = proc_cls; | 988 | handle->proc_cls = proc_cls; |
905 | handle->proc = proc; | 989 | handle->proc = proc; |
906 | handle->state = ID_REST_STATE_INIT; | 990 | handle->rest_handle = rest_handle; |
907 | handle->conndata_handle = conndata_handle; | 991 | handle->data = rest_handle->data; |
908 | handle->data = conndata_handle->data; | 992 | handle->data_size = rest_handle->data_size; |
909 | handle->data_size = conndata_handle->data_size; | 993 | |
910 | handle->method = conndata_handle->method; | 994 | handle->url = GNUNET_strdup(rest_handle->url); |
911 | GNUNET_asprintf (&handle->url, "%s", conndata_handle->url); | 995 | if (handle->url[strlen (handle->url) - 1] == '/') |
912 | if (handle->url[strlen (handle->url)-1] == '/') | 996 | handle->url[strlen (handle->url) - 1] = '\0'; |
913 | handle->url[strlen (handle->url)-1] = '\0'; | 997 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); |
914 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 998 | |
915 | "Connecting...\n"); | 999 | handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle); |
916 | handle->identity_handle = GNUNET_IDENTITY_connect (cfg, | 1000 | |
917 | &list_ego, | 1001 | handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, |
918 | handle); | 1002 | &do_error, handle); |
919 | handle->timeout_task = | 1003 | |
920 | GNUNET_SCHEDULER_add_delayed (handle->timeout, | 1004 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); |
921 | &do_error, | ||
922 | handle); | ||
923 | |||
924 | |||
925 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
926 | "Connected\n"); | ||
927 | } | 1005 | } |
928 | 1006 | ||
929 | /** | 1007 | /** |
@@ -940,27 +1018,24 @@ libgnunet_plugin_rest_identity_init (void *cls) | |||
940 | 1018 | ||
941 | cfg = cls; | 1019 | cfg = cls; |
942 | if (NULL != plugin.cfg) | 1020 | if (NULL != plugin.cfg) |
943 | return NULL; /* can only initialize once! */ | 1021 | return NULL; /* can only initialize once! */ |
944 | memset (&plugin, 0, sizeof (struct Plugin)); | 1022 | memset (&plugin, 0, sizeof(struct Plugin)); |
945 | plugin.cfg = cfg; | 1023 | plugin.cfg = cfg; |
946 | api = GNUNET_new (struct GNUNET_REST_Plugin); | 1024 | api = GNUNET_new(struct GNUNET_REST_Plugin); |
947 | api->cls = &plugin; | 1025 | api->cls = &plugin; |
948 | api->name = GNUNET_REST_API_NS_IDENTITY; | 1026 | api->name = GNUNET_REST_API_NS_IDENTITY; |
949 | api->process_request = &rest_identity_process_request; | 1027 | api->process_request = &rest_process_request; |
950 | GNUNET_asprintf (&allow_methods, | 1028 | GNUNET_asprintf (&allow_methods, "%s, %s, %s, %s, %s", |
951 | "%s, %s, %s, %s, %s", | 1029 | MHD_HTTP_METHOD_GET, |
952 | MHD_HTTP_METHOD_GET, | 1030 | MHD_HTTP_METHOD_POST, |
953 | MHD_HTTP_METHOD_POST, | 1031 | MHD_HTTP_METHOD_PUT, |
954 | MHD_HTTP_METHOD_PUT, | 1032 | MHD_HTTP_METHOD_DELETE, |
955 | MHD_HTTP_METHOD_DELETE, | 1033 | MHD_HTTP_METHOD_OPTIONS); |
956 | MHD_HTTP_METHOD_OPTIONS); | 1034 | |
957 | 1035 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Identity REST API initialized\n")); | |
958 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
959 | _("Identity REST API initialized\n")); | ||
960 | return api; | 1036 | return api; |
961 | } | 1037 | } |
962 | 1038 | ||
963 | |||
964 | /** | 1039 | /** |
965 | * Exit point from the plugin. | 1040 | * Exit point from the plugin. |
966 | * | 1041 | * |
@@ -972,13 +1047,13 @@ libgnunet_plugin_rest_identity_done (void *cls) | |||
972 | { | 1047 | { |
973 | struct GNUNET_REST_Plugin *api = cls; | 1048 | struct GNUNET_REST_Plugin *api = cls; |
974 | struct Plugin *plugin = api->cls; | 1049 | struct Plugin *plugin = api->cls; |
975 | |||
976 | plugin->cfg = NULL; | 1050 | plugin->cfg = NULL; |
977 | GNUNET_free_non_null (allow_methods); | 1051 | |
978 | GNUNET_free (api); | 1052 | GNUNET_free_non_null(allow_methods); |
979 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1053 | GNUNET_free(api); |
980 | "Identity REST plugin is finished\n"); | 1054 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n"); |
981 | return NULL; | 1055 | return NULL; |
982 | } | 1056 | } |
983 | 1057 | ||
984 | /* end of plugin_rest_gns.c */ | 1058 | /* end of plugin_rest_identity.c */ |
1059 | |||
diff --git a/src/identity/test_plugin_rest_identity.sh b/src/identity/test_plugin_rest_identity.sh new file mode 100755 index 000000000..d9377500e --- /dev/null +++ b/src/identity/test_plugin_rest_identity.sh | |||
@@ -0,0 +1,159 @@ | |||
1 | #!/usr/bin/bash | ||
2 | |||
3 | #First, start gnunet-arm and the rest-service. | ||
4 | #Exit 0 means success, exit 1 means failed test | ||
5 | |||
6 | identity_link="http://localhost:7776/identity" | ||
7 | wrong_link="http://localhost:7776/identityandmore" | ||
8 | |||
9 | |||
10 | curl_get () { | ||
11 | #$1 is link | ||
12 | #$2 is grep | ||
13 | cache="$(curl -v "$1" 2>&1 | grep "$2")" | ||
14 | #echo $cache | ||
15 | if [ "" == "$cache" ] | ||
16 | then | ||
17 | exit 1 | ||
18 | fi | ||
19 | } | ||
20 | |||
21 | curl_post () { | ||
22 | #$1 is link | ||
23 | #$2 is data | ||
24 | #$3 is grep | ||
25 | cache="$(curl -v -X "POST" "$1" --data "$2" 2>&1 | grep "$3")" | ||
26 | #echo $cache | ||
27 | if [ "" == "$cache" ] | ||
28 | then | ||
29 | exit 1 | ||
30 | fi | ||
31 | } | ||
32 | |||
33 | curl_delete () { | ||
34 | #$1 is link | ||
35 | #$2 is grep | ||
36 | cache="$(curl -v -X "DELETE" "$1" 2>&1 | grep "$2")" | ||
37 | #echo $cache | ||
38 | if [ "" == "$cache" ] | ||
39 | then | ||
40 | exit 1 | ||
41 | fi | ||
42 | } | ||
43 | |||
44 | curl_put () { | ||
45 | #$1 is link | ||
46 | #$2 is data | ||
47 | #$3 is grep | ||
48 | cache="$(curl -v -X "PUT" "$1" --data "$2" 2>&1 | grep "$3")" | ||
49 | #echo $cache | ||
50 | if [ "" == "$cache" ] | ||
51 | then | ||
52 | exit 1 | ||
53 | fi | ||
54 | } | ||
55 | |||
56 | #Test GET | ||
57 | test="$(gnunet-identity -d)" | ||
58 | #if no identity exists | ||
59 | if [ "" == "$test" ] | ||
60 | then | ||
61 | curl_get "$identity_link" "error" | ||
62 | gnunet-identity -C "test_plugin_rest_identity" | ||
63 | name="$(gnunet-identity -d | awk 'NR==1{print $1}')" | ||
64 | public="$(gnunet-identity -d | awk 'NR==1{print $3}')" | ||
65 | |||
66 | curl_get "${identity_link}?name=$name" "$public" | ||
67 | curl_get "${identity_link}?name=" "error" | ||
68 | curl_get "${identity_link}?name=$public" "error" | ||
69 | |||
70 | curl_get "${identity_link}?pubkey=$public" "$name" | ||
71 | curl_get "${identity_link}?pubkey=$name" "error" | ||
72 | curl_get "${identity_link}?pubkey=" "error" | ||
73 | |||
74 | gnunet-identity -D "test_plugin_rest_identity" | ||
75 | else | ||
76 | name="$(gnunet-identity -d | awk 'NR==1{print $1}')" | ||
77 | public="$(gnunet-identity -d | awk 'NR==1{print $3}')" | ||
78 | |||
79 | curl_get "${identity_link}?name=$name" "$public" | ||
80 | curl_get "${identity_link}?name=" "error" | ||
81 | curl_get "${identity_link}?name=$public" "error" | ||
82 | |||
83 | curl_get "${identity_link}?pubkey=$public" "$name" | ||
84 | curl_get "${identity_link}?pubkey=$name" "error" | ||
85 | curl_get "${identity_link}?pubkey=" "error" | ||
86 | fi | ||
87 | |||
88 | #Test POST | ||
89 | gnunet-identity -D "test_plugin_rest_identity" > /dev/null 2>&1 | ||
90 | gnunet-identity -D "test_plugin_rest_identity1" > /dev/null 2>&1 | ||
91 | |||
92 | curl_post "${identity_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 201 Created" | ||
93 | curl_post "${identity_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 409" | ||
94 | curl_post "${identity_link}" '{"name":"Test_plugin_rest_identity"}' "HTTP/1.1 409" | ||
95 | curl_post "${identity_link}" '{}' "error" | ||
96 | curl_post "${identity_link}" '' "error" | ||
97 | curl_post "${identity_link}" '{"name":""}' "error" | ||
98 | curl_post "${identity_link}" '{"name":123}' "error" | ||
99 | curl_post "${identity_link}" '{"name":[]}' "error" | ||
100 | curl_post "${identity_link}" '{"name1":"test_plugin_rest_identity"}' "error" | ||
101 | curl_post "${identity_link}" '{"other":""}' "error" | ||
102 | curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1", "other":"test_plugin_rest_identity2"}' "error" | ||
103 | |||
104 | #Test PUT | ||
105 | name="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $1}')" | ||
106 | public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')" | ||
107 | |||
108 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'"}' "HTTP/1.1 204" | ||
109 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'"}' "HTTP/1.1 409" | ||
110 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'xx"}' "HTTP/1.1 404" | ||
111 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":""}' "HTTP/1.1 404" | ||
112 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubke":""}' "HTTP/1.1 404" | ||
113 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubke":"","other":"sdfdsf"}' "HTTP/1.1 404" | ||
114 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubke":"","name":"sdfdsf"}' "HTTP/1.1 404" | ||
115 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity","pubke":"","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" | ||
116 | curl_put "${identity_link}" '{"newnam":"test_plugin_rest_identity","pubkey":"'$public'"}' "error" | ||
117 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" | ||
118 | curl_put "${identity_link}" '{"newname":"TEST_plugin_rest_identity1","name":"test_plugin_rest_identity1"}' "HTTP/1.1 409" | ||
119 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity1"}' "HTTP/1.1 409" | ||
120 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity","name":"test_plugin_rest_identityxxx"}' "HTTP/1.1 404" | ||
121 | curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" | ||
122 | curl_put "${identity_link}" '{"newnam":"test_plugin_rest_identityfail","name":"test_plugin_rest_identity"}' "error" | ||
123 | |||
124 | |||
125 | #Test subsystem | ||
126 | curl_put "${identity_link}" '{"subsystem":"namestore","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" | ||
127 | curl_put "${identity_link}" '{"subsystem":"namestore","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" | ||
128 | curl_get "${identity_link}?subsystem=namestore" "test_plugin_rest_identity" | ||
129 | curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created" | ||
130 | public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')" | ||
131 | curl_put "${identity_link}" '{"subsystem":"namestore","pubkey":"'"$public"'"}' "HTTP/1.1 204" | ||
132 | curl_get "${identity_link}?subsystem=namestore" "test_plugin_rest_identity1" | ||
133 | curl_get "${identity_link}?subsystem=test_plugin_rest_identity_no_subsystem" "error" | ||
134 | curl_put "${identity_link}" '{"subsystem":"test_plugin_rest_identity_no_subsystem","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" | ||
135 | curl_get "${identity_link}?subsystem=test_plugin_rest_identity_no_subsystem" "test_plugin_rest_identity1" | ||
136 | |||
137 | curl_put "${identity_link}" '{"subsyste":"test_plugin_rest_identity_no_subsystem","name":"test_plugin_rest_identity1"}' "error" | ||
138 | curl_put "${identity_link}" '{"subsystem":"test_plugin_rest_identity_no_subsystem","name":"Test_plugin_rest_identity1"}' "HTTP/1.1 204" | ||
139 | |||
140 | #Test DELETE | ||
141 | curl_delete "${identity_link}?name=test_plugin_rest_identity" "HTTP/1.1 204" | ||
142 | curl_get "${identity_link}?name=test_plugin_rest_identity" "error" | ||
143 | curl_delete "${identity_link}?name=TEST_plugin_rest_identity1" "HTTP/1.1 404" | ||
144 | curl_delete "${identity_link}?name=test_plugin_rest_identity1" "HTTP/1.1 204" | ||
145 | curl_get "${identity_link}?name=test_plugin_rest_identity1" "error" | ||
146 | curl_delete "${identity_link}?name=test_plugin_rest_identity_not_found" "HTTP/1.1 404" | ||
147 | curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created" | ||
148 | public="$(gnunet-identity -d | grep "test_plugin_rest_identity1" | awk 'NR==1{print $3}')" | ||
149 | curl_delete "${identity_link}?pubkey=$public" "HTTP/1.1 204" | ||
150 | curl_delete "${identity_link}?pubke=$public" "error" | ||
151 | curl_delete "${identity_link}?pubkey=$public&other=232" "HTTP/1.1 404" | ||
152 | |||
153 | #Test wrong_link | ||
154 | curl_get "$wrong_link" "HTTP/1.1 404" | ||
155 | curl_post "$wrong_link" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 404" | ||
156 | curl_put "$wrong_link" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity"}' "HTTP/1.1 404" | ||
157 | curl_delete "$wrong_link?name=test_plugin_rest_identity1" "HTTP/1.1 404" | ||
158 | |||
159 | exit 0; | ||
diff --git a/src/include/gnunet_json_lib.h b/src/include/gnunet_json_lib.h index 06749590c..781d5698b 100644 --- a/src/include/gnunet_json_lib.h +++ b/src/include/gnunet_json_lib.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #define GNUNET_JSON_LIB_H | 26 | #define GNUNET_JSON_LIB_H |
27 | 27 | ||
28 | #include "gnunet_util_lib.h" | 28 | #include "gnunet_util_lib.h" |
29 | #include "gnunet_gnsrecord_lib.h" | ||
29 | #include <jansson.h> | 30 | #include <jansson.h> |
30 | 31 | ||
31 | 32 | ||
@@ -318,6 +319,17 @@ GNUNET_JSON_spec_rsa_signature (const char *name, | |||
318 | struct GNUNET_CRYPTO_RsaSignature **sig); | 319 | struct GNUNET_CRYPTO_RsaSignature **sig); |
319 | 320 | ||
320 | 321 | ||
322 | |||
323 | /** | ||
324 | * JSON Specification for GNS Records. | ||
325 | * | ||
326 | * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill | ||
327 | * @return JSON Specification | ||
328 | */ | ||
329 | struct GNUNET_JSON_Specification | ||
330 | GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object); | ||
331 | |||
332 | |||
321 | /* ****************** Generic generator interface ******************* */ | 333 | /* ****************** Generic generator interface ******************* */ |
322 | 334 | ||
323 | 335 | ||
@@ -393,6 +405,16 @@ GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_RsaPublicKey *pk); | |||
393 | json_t * | 405 | json_t * |
394 | GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig); | 406 | GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig); |
395 | 407 | ||
408 | /** | ||
409 | * Convert Gns record to JSON. | ||
410 | * | ||
411 | * @param rname name of record | ||
412 | * @param rd record data | ||
413 | * @return corresponding JSON encoding | ||
414 | */ | ||
415 | json_t * | ||
416 | GNUNET_JSON_from_gns_record (const char* rname, | ||
417 | const struct GNUNET_GNSRECORD_Data *rd); | ||
396 | 418 | ||
397 | /* ******************* Helpers for MHD upload handling ******************* */ | 419 | /* ******************* Helpers for MHD upload handling ******************* */ |
398 | 420 | ||
@@ -479,7 +501,6 @@ GNUNET_JSON_getopt (char shortName, | |||
479 | const char *description, | 501 | const char *description, |
480 | json_t **json); | 502 | json_t **json); |
481 | 503 | ||
482 | |||
483 | #endif | 504 | #endif |
484 | 505 | ||
485 | /* end of gnunet_json_lib.h */ | 506 | /* end of gnunet_json_lib.h */ |
diff --git a/src/json/Makefile.am b/src/json/Makefile.am index da19e7955..f3fa28d69 100644 --- a/src/json/Makefile.am +++ b/src/json/Makefile.am | |||
@@ -16,9 +16,11 @@ libgnunetjson_la_SOURCES = \ | |||
16 | json.c \ | 16 | json.c \ |
17 | json_mhd.c \ | 17 | json_mhd.c \ |
18 | json_generator.c \ | 18 | json_generator.c \ |
19 | json_helper.c | 19 | json_helper.c \ |
20 | json_gnsrecord.c | ||
20 | libgnunetjson_la_LIBADD = \ | 21 | libgnunetjson_la_LIBADD = \ |
21 | $(top_builddir)/src/util/libgnunetutil.la \ | 22 | $(top_builddir)/src/util/libgnunetutil.la \ |
23 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
22 | -ljansson \ | 24 | -ljansson \ |
23 | $(XLIB) | 25 | $(XLIB) |
24 | 26 | ||
diff --git a/src/json/json_generator.c b/src/json/json_generator.c index dd6df4f74..d8c82bc86 100644 --- a/src/json/json_generator.c +++ b/src/json/json_generator.c | |||
@@ -157,5 +157,40 @@ GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig) | |||
157 | return ret; | 157 | return ret; |
158 | } | 158 | } |
159 | 159 | ||
160 | /** | ||
161 | * Convert Gns record to JSON. | ||
162 | * | ||
163 | * @param rname name of record | ||
164 | * @param rd record data | ||
165 | * @return corresponding JSON encoding | ||
166 | */ | ||
167 | json_t * | ||
168 | GNUNET_JSON_from_gns_record (const char* rname, | ||
169 | const struct GNUNET_GNSRECORD_Data *rd) | ||
170 | { | ||
171 | struct GNUNET_TIME_Absolute expiration_time; | ||
172 | const char *expiration_time_str; | ||
173 | const char *record_type_str; | ||
174 | char *value_str; | ||
175 | json_t *ret; | ||
176 | int flags; | ||
177 | |||
178 | value_str = GNUNET_GNSRECORD_value_to_string(rd->record_type,rd->data,rd->data_size); | ||
179 | expiration_time = GNUNET_GNSRECORD_record_get_expiration_time(1, rd); | ||
180 | expiration_time_str = GNUNET_STRINGS_absolute_time_to_string(expiration_time); | ||
181 | flags = (int)rd->flags; //maybe necessary | ||
182 | record_type_str = GNUNET_GNSRECORD_number_to_typename(rd->record_type); | ||
183 | |||
184 | // ? for possible NULL values | ||
185 | ret = json_pack("{s:s?,s:s?,s:s?,s:i,s:s?}", | ||
186 | "value", value_str, | ||
187 | "type", record_type_str, | ||
188 | "expiration_time", expiration_time_str, | ||
189 | "flag", flags, | ||
190 | "label", rname); | ||
191 | GNUNET_free_non_null(value_str); | ||
192 | return ret; | ||
193 | } | ||
194 | |||
160 | 195 | ||
161 | /* End of json/json_generator.c */ | 196 | /* End of json/json_generator.c */ |
diff --git a/src/json/json_gnsrecord.c b/src/json/json_gnsrecord.c new file mode 100644 index 000000000..7bdf97f06 --- /dev/null +++ b/src/json/json_gnsrecord.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009-2013 GNUnet e.V. | ||
4 | |||
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. | ||
9 | |||
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. | ||
14 | |||
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/>. | ||
17 | */ | ||
18 | |||
19 | /** | ||
20 | * @file json/json_gnsrecord.c | ||
21 | * @brief JSON handling of GNS record data | ||
22 | * @author Philippe Buschmann | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_util_lib.h" | ||
26 | #include "gnunet_json_lib.h" | ||
27 | |||
28 | #define GNUNET_JSON_GNSRECORD_VALUE "value" | ||
29 | #define GNUNET_JSON_GNSRECORD_TYPE "type" | ||
30 | #define GNUNET_JSON_GNSRECORD_EXPIRATION_TIME "expiration_time" | ||
31 | #define GNUNET_JSON_GNSRECORD_FLAG "flag" | ||
32 | #define GNUNET_JSON_GNSRECORD_LABEL "label" | ||
33 | #define GNUNET_JSON_GNSRECORD_NEVER "never" | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Parse given JSON object to gns record | ||
38 | * | ||
39 | * @param cls closure, NULL | ||
40 | * @param root the json object representing data | ||
41 | * @param spec where to write the data | ||
42 | * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error | ||
43 | */ | ||
44 | static int | ||
45 | parse_gnsrecordobject (void *cls, | ||
46 | json_t *root, | ||
47 | struct GNUNET_JSON_Specification *spec) | ||
48 | { | ||
49 | struct GNUNET_GNSRECORD_Data *gnsrecord_object; | ||
50 | struct GNUNET_TIME_Absolute abs_expiration_time; | ||
51 | int unpack_state=0; | ||
52 | const char *value; | ||
53 | const char *expiration_time; | ||
54 | const char *record_type; | ||
55 | const char *label; | ||
56 | int flag; | ||
57 | void *rdata = NULL; | ||
58 | size_t rdata_size; | ||
59 | |||
60 | GNUNET_assert(NULL != root); | ||
61 | if(!json_is_object(root)) | ||
62 | { | ||
63 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
64 | "Error json is not array nor object!\n"); | ||
65 | return GNUNET_SYSERR; | ||
66 | } | ||
67 | //interpret single gns record | ||
68 | unpack_state = json_unpack(root, | ||
69 | "{s:s, s:s, s:s, s?:i, s:s!}", | ||
70 | GNUNET_JSON_GNSRECORD_VALUE, &value, | ||
71 | GNUNET_JSON_GNSRECORD_TYPE, &record_type, | ||
72 | GNUNET_JSON_GNSRECORD_EXPIRATION_TIME, &expiration_time, | ||
73 | GNUNET_JSON_GNSRECORD_FLAG, &flag, | ||
74 | GNUNET_JSON_GNSRECORD_LABEL, &label); | ||
75 | if (0 != unpack_state) | ||
76 | { | ||
77 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, | ||
78 | "Error json object has a wrong format!\n"); | ||
79 | return GNUNET_SYSERR; | ||
80 | } | ||
81 | gnsrecord_object = GNUNET_new (struct GNUNET_GNSRECORD_Data); | ||
82 | gnsrecord_object->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); | ||
83 | if (UINT32_MAX == gnsrecord_object->record_type) | ||
84 | { | ||
85 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Unsupported type\n"); | ||
86 | GNUNET_free(gnsrecord_object); | ||
87 | return GNUNET_SYSERR; | ||
88 | } | ||
89 | if (GNUNET_OK | ||
90 | != GNUNET_GNSRECORD_string_to_value (gnsrecord_object->record_type, | ||
91 | value, | ||
92 | &rdata, | ||
93 | &rdata_size)) | ||
94 | { | ||
95 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Value invalid for record type\n"); | ||
96 | GNUNET_free(gnsrecord_object); | ||
97 | return GNUNET_SYSERR; | ||
98 | } | ||
99 | |||
100 | gnsrecord_object->data = rdata; | ||
101 | gnsrecord_object->data_size = rdata_size; | ||
102 | |||
103 | if (0 == strcmp (expiration_time, GNUNET_JSON_GNSRECORD_NEVER)) | ||
104 | { | ||
105 | gnsrecord_object->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
106 | } | ||
107 | else if (GNUNET_OK | ||
108 | == GNUNET_STRINGS_fancy_time_to_absolute (expiration_time, | ||
109 | &abs_expiration_time)) | ||
110 | { | ||
111 | gnsrecord_object->expiration_time = abs_expiration_time.abs_value_us; | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Expiration time invalid\n"); | ||
116 | GNUNET_free_non_null(rdata); | ||
117 | GNUNET_free(gnsrecord_object); | ||
118 | return GNUNET_SYSERR; | ||
119 | } | ||
120 | // check if flag is a valid enum value | ||
121 | if ((GNUNET_GNSRECORD_RF_NONE != flag) | ||
122 | && (GNUNET_GNSRECORD_RF_PRIVATE != flag) | ||
123 | && (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION != flag) | ||
124 | && (GNUNET_GNSRECORD_RF_SHADOW_RECORD) != flag) | ||
125 | { | ||
126 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Flag invalid\n"); | ||
127 | GNUNET_free_non_null(rdata); | ||
128 | GNUNET_free(gnsrecord_object); | ||
129 | return GNUNET_SYSERR; | ||
130 | } | ||
131 | gnsrecord_object->flags = (enum GNUNET_GNSRECORD_Flags)flag; | ||
132 | *(struct GNUNET_GNSRECORD_Data **) spec->ptr = gnsrecord_object; | ||
133 | return GNUNET_OK; | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * Cleanup data left from parsing RSA public key. | ||
138 | * | ||
139 | * @param cls closure, NULL | ||
140 | * @param[out] spec where to free the data | ||
141 | */ | ||
142 | static void | ||
143 | clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec) | ||
144 | { | ||
145 | struct GNUNET_GNSRECORD_Data **gnsrecord_object; | ||
146 | gnsrecord_object = (struct GNUNET_GNSRECORD_Data **) spec->ptr; | ||
147 | if (NULL != *gnsrecord_object) | ||
148 | { | ||
149 | if (NULL != (*gnsrecord_object)->data) | ||
150 | GNUNET_free((char*)(*gnsrecord_object)->data); | ||
151 | |||
152 | GNUNET_free(*gnsrecord_object); | ||
153 | *gnsrecord_object = NULL; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * JSON Specification for GNS Records. | ||
159 | * | ||
160 | * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill | ||
161 | * @return JSON Specification | ||
162 | */ | ||
163 | struct GNUNET_JSON_Specification | ||
164 | GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object) | ||
165 | { | ||
166 | struct GNUNET_JSON_Specification ret = { | ||
167 | .parser = &parse_gnsrecordobject, | ||
168 | .cleaner = &clean_gnsrecordobject, | ||
169 | .cls = NULL, | ||
170 | .field = NULL, | ||
171 | .ptr = gnsrecord_object, | ||
172 | .ptr_size = 0, | ||
173 | .size_ptr = NULL | ||
174 | }; | ||
175 | *gnsrecord_object = NULL; | ||
176 | return ret; | ||
177 | } | ||
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am index 777e722c2..7f44c2a71 100644 --- a/src/namestore/Makefile.am +++ b/src/namestore/Makefile.am | |||
@@ -230,8 +230,8 @@ libgnunet_plugin_rest_namestore_la_LIBADD = \ | |||
230 | libgnunetnamestore.la \ | 230 | libgnunetnamestore.la \ |
231 | $(top_builddir)/src/rest/libgnunetrest.la \ | 231 | $(top_builddir)/src/rest/libgnunetrest.la \ |
232 | $(top_builddir)/src/identity/libgnunetidentity.la \ | 232 | $(top_builddir)/src/identity/libgnunetidentity.la \ |
233 | $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ | 233 | $(top_builddir)/src/json/libgnunetjson.la \ |
234 | $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \ | 234 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
235 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | 235 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ |
236 | $(LTLIBINTL) -ljansson -lmicrohttpd | 236 | $(LTLIBINTL) -ljansson -lmicrohttpd |
237 | libgnunet_plugin_rest_namestore_la_LDFLAGS = \ | 237 | libgnunet_plugin_rest_namestore_la_LDFLAGS = \ |
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index ec44046e0..f14707cce 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c | |||
@@ -11,15 +11,15 @@ | |||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Affero General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Affero General Public License | 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/>. | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | /** | 18 | /** |
19 | * @author Martin Schanzenbach | 19 | * @author Martin Schanzenbach |
20 | * @author Philippe Buschmann | ||
20 | * @file namestore/plugin_rest_namestore.c | 21 | * @file namestore/plugin_rest_namestore.c |
21 | * @brief GNUnet Namestore REST plugin | 22 | * @brief GNUnet Namestore REST plugin |
22 | * | ||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "platform.h" | 25 | #include "platform.h" |
@@ -28,38 +28,45 @@ | |||
28 | #include "gnunet_namestore_service.h" | 28 | #include "gnunet_namestore_service.h" |
29 | #include "gnunet_identity_service.h" | 29 | #include "gnunet_identity_service.h" |
30 | #include "gnunet_rest_lib.h" | 30 | #include "gnunet_rest_lib.h" |
31 | #include "gnunet_jsonapi_lib.h" | 31 | #include "gnunet_json_lib.h" |
32 | #include "gnunet_jsonapi_util.h" | ||
33 | #include "microhttpd.h" | 32 | #include "microhttpd.h" |
34 | #include <jansson.h> | 33 | #include <jansson.h> |
35 | 34 | ||
36 | #define GNUNET_REST_API_NS_NAMESTORE "/names" | ||
37 | |||
38 | #define GNUNET_REST_API_NS_NAMESTORE_ZKEY "/names/zkey" | ||
39 | |||
40 | #define GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO "record" | ||
41 | |||
42 | #define GNUNET_REST_JSONAPI_NAMESTORE_NAME "name" | ||
43 | |||
44 | #define GNUNET_REST_JSONAPI_NAMESTORE_REVINFO "revinfo" | ||
45 | 35 | ||
46 | #define GNUNET_REST_JSONAPI_NAMESTORE_RECORD GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO | 36 | #define GNUNET_REST_API_NS_NAMESTORE "/namestore" |
37 | #define GNUNET_REST_SUBSYSTEM_NAMESTORE "namestore" | ||
47 | 38 | ||
48 | #define GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE "record_type" | 39 | /** |
49 | 40 | * Parameter names | |
50 | #define GNUNET_REST_JSONAPI_NAMESTORE_VALUE "value" | 41 | */ |
51 | 42 | #define GNUNET_REST_API_PARAM_PUBKEY "pubkey" | |
52 | #define GNUNET_REST_JSONAPI_NAMESTORE_PUBLIC "public" | 43 | #define GNUNET_REST_API_PARAM_NAME "name" |
53 | 44 | ||
54 | #define GNUNET_REST_JSONAPI_NAMESTORE_SHADOW "shadow" | 45 | /** |
46 | * Error messages | ||
47 | */ | ||
48 | #define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error" | ||
55 | 49 | ||
56 | #define GNUNET_REST_JSONAPI_NAMESTORE_PKEY "pkey" | 50 | #define GNUNET_REST_NAMESTORE_RD_COUNT 1 |
57 | 51 | ||
58 | #define GNUNET_REST_JSONAPI_NAMESTORE_ZKEY "zkey" | 52 | /** |
53 | * State while collecting all egos | ||
54 | */ | ||
55 | #define ID_REST_STATE_INIT 0 | ||
59 | 56 | ||
60 | #define GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION "expiration" | 57 | /** |
58 | * Done collecting egos | ||
59 | */ | ||
60 | #define ID_REST_STATE_POST_INIT 1 | ||
61 | /** | ||
62 | * The configuration handle | ||
63 | */ | ||
64 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
61 | 65 | ||
62 | #define GNUNET_REST_JSONAPI_NAMESTORE_EGO "ego" | 66 | /** |
67 | * HTTP methods allows for this plugin | ||
68 | */ | ||
69 | static char* allow_methods; | ||
63 | 70 | ||
64 | /** | 71 | /** |
65 | * @brief struct returned by the initialization function of the plugin | 72 | * @brief struct returned by the initialization function of the plugin |
@@ -69,135 +76,110 @@ struct Plugin | |||
69 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 76 | const struct GNUNET_CONFIGURATION_Handle *cfg; |
70 | }; | 77 | }; |
71 | 78 | ||
72 | |||
73 | /** | 79 | /** |
74 | * HTTP methods allows for this plugin | 80 | * The default namestore ego |
75 | */ | 81 | */ |
76 | static char* allow_methods; | 82 | struct EgoEntry |
77 | |||
78 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
79 | |||
80 | struct RecordEntry | ||
81 | { | 83 | { |
82 | /** | 84 | /** |
83 | * DLL | 85 | * DLL |
84 | */ | 86 | */ |
85 | struct RecordEntry *next; | 87 | struct EgoEntry *next; |
86 | 88 | ||
87 | /** | 89 | /** |
88 | * DLL | 90 | * DLL |
89 | */ | 91 | */ |
90 | struct RecordEntry *prev; | 92 | struct EgoEntry *prev; |
91 | |||
92 | }; | ||
93 | |||
94 | struct RequestHandle | ||
95 | { | ||
96 | /** | ||
97 | * Ego list | ||
98 | */ | ||
99 | struct RecordEntry *record_head; | ||
100 | |||
101 | /** | ||
102 | * Ego list | ||
103 | */ | ||
104 | struct record_entry *record_tail; | ||
105 | 93 | ||
106 | /** | 94 | /** |
107 | * JSON response object | 95 | * Ego Identifier |
108 | */ | 96 | */ |
109 | struct GNUNET_JSONAPI_Document *resp_object; | 97 | char *identifier; |
110 | 98 | ||
111 | /** | 99 | /** |
112 | * Rest connection | 100 | * Public key string |
113 | */ | 101 | */ |
114 | struct GNUNET_REST_RequestHandle *rest_handle; | 102 | char *keystring; |
115 | 103 | ||
116 | /** | 104 | /** |
117 | * Handle to GNS service. | 105 | * The Ego |
118 | */ | ||
119 | struct GNUNET_IDENTITY_Handle *identity_handle; | ||
120 | |||
121 | /** | ||
122 | * Handle to NAMESTORE | ||
123 | */ | 106 | */ |
124 | struct GNUNET_NAMESTORE_Handle *ns_handle; | 107 | struct GNUNET_IDENTITY_Ego *ego; |
108 | }; | ||
125 | 109 | ||
126 | /** | ||
127 | * Handle to NAMESTORE it | ||
128 | */ | ||
129 | struct GNUNET_NAMESTORE_ZoneIterator *list_it; | ||
130 | 110 | ||
111 | struct RequestHandle | ||
112 | { | ||
131 | /** | 113 | /** |
132 | * Private key for the zone | 114 | * Records to store |
133 | */ | 115 | */ |
134 | struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey; | 116 | char *label_name; |
135 | 117 | ||
136 | /** | 118 | /** |
137 | * Handle to identity lookup | 119 | * Records to store |
138 | */ | 120 | */ |
139 | struct GNUNET_IDENTITY_EgoLookup *ego_lookup; | 121 | struct GNUNET_GNSRECORD_Data *rd; |
140 | 122 | ||
141 | /** | 123 | /** |
142 | * Default Ego operation | 124 | * NAMESTORE Operation |
143 | */ | 125 | */ |
144 | struct GNUNET_IDENTITY_Operation *get_default; | 126 | struct GNUNET_NAMESTORE_QueueEntry *add_qe; |
145 | 127 | ||
146 | /** | 128 | /** |
147 | * Name of the ego | 129 | * Response object |
148 | */ | 130 | */ |
149 | char *ego_name; | 131 | json_t *resp_object; |
150 | 132 | ||
151 | /** | 133 | /** |
152 | * Record is public | 134 | * The processing state |
153 | */ | 135 | */ |
154 | int is_public; | 136 | int state; |
155 | 137 | ||
156 | /** | 138 | /** |
157 | * Shadow record | 139 | * Handle to NAMESTORE |
158 | */ | 140 | */ |
159 | int is_shadow; | 141 | struct GNUNET_NAMESTORE_Handle *ns_handle; |
160 | 142 | ||
161 | /** | 143 | /** |
162 | * Name of the record to modify | 144 | * Handle to NAMESTORE it |
163 | */ | 145 | */ |
164 | char *name; | 146 | struct GNUNET_NAMESTORE_ZoneIterator *list_it; |
165 | 147 | ||
166 | /** | 148 | /** |
167 | * Value of the record | 149 | * Private key for the zone |
168 | */ | 150 | */ |
169 | char *value; | 151 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_pkey; |
170 | 152 | ||
171 | /** | 153 | /** |
172 | * Zkey string | 154 | * IDENTITY Operation |
173 | */ | 155 | */ |
174 | const char* zkey_str; | 156 | struct EgoEntry *ego_entry; |
175 | 157 | ||
176 | /** | 158 | /** |
177 | * record type | 159 | * Ego list |
178 | */ | 160 | */ |
179 | uint32_t type; | 161 | struct EgoEntry *ego_head; |
180 | 162 | ||
181 | /** | 163 | /** |
182 | * Records to store | 164 | * Ego list |
183 | */ | 165 | */ |
184 | struct GNUNET_GNSRECORD_Data *rd; | 166 | struct EgoEntry *ego_tail; |
185 | 167 | ||
186 | /** | 168 | /** |
187 | * record count | 169 | * IDENTITY Operation |
188 | */ | 170 | */ |
189 | unsigned int rd_count; | 171 | struct GNUNET_IDENTITY_Operation *op; |
190 | 172 | ||
191 | /** | 173 | /** |
192 | * NAMESTORE Operation | 174 | * Handle to Identity service. |
193 | */ | 175 | */ |
194 | struct GNUNET_NAMESTORE_QueueEntry *add_qe; | 176 | struct GNUNET_IDENTITY_Handle *identity_handle; |
195 | 177 | ||
196 | /** | 178 | /** |
197 | * NAMESTORE Operation | 179 | * Rest connection |
198 | */ | 180 | */ |
199 | struct GNUNET_NAMESTORE_QueueEntry *reverse_qe; | 181 | struct GNUNET_REST_RequestHandle *rest_handle; |
200 | 182 | ||
201 | /** | 183 | /** |
202 | * Desired timeout for the lookup (default is no timeout). | 184 | * Desired timeout for the lookup (default is no timeout). |
203 | */ | 185 | */ |
@@ -206,7 +188,7 @@ struct RequestHandle | |||
206 | /** | 188 | /** |
207 | * ID of a task associated with the resolution process. | 189 | * ID of a task associated with the resolution process. |
208 | */ | 190 | */ |
209 | struct GNUNET_SCHEDULER_Task * timeout_task; | 191 | struct GNUNET_SCHEDULER_Task *timeout_task; |
210 | 192 | ||
211 | /** | 193 | /** |
212 | * The plugin result processor | 194 | * The plugin result processor |
@@ -224,164 +206,201 @@ struct RequestHandle | |||
224 | char *url; | 206 | char *url; |
225 | 207 | ||
226 | /** | 208 | /** |
227 | * Cfg | 209 | * Error response message |
228 | */ | 210 | */ |
229 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 211 | char *emsg; |
230 | 212 | ||
231 | /** | 213 | /** |
232 | * HTTP response code | 214 | * Reponse code |
233 | */ | 215 | */ |
234 | int response_code; | 216 | int response_code; |
235 | 217 | ||
236 | }; | 218 | }; |
237 | 219 | ||
238 | |||
239 | /** | 220 | /** |
240 | * Cleanup lookup handle | 221 | * Cleanup lookup handle |
241 | * | ||
242 | * @param handle Handle to clean up | 222 | * @param handle Handle to clean up |
243 | */ | 223 | */ |
244 | static void | 224 | static void |
245 | cleanup_handle (struct RequestHandle *handle) | 225 | cleanup_handle (void *cls) |
246 | { | 226 | { |
247 | struct RecordEntry *record_entry; | 227 | struct RequestHandle *handle = cls; |
248 | struct RecordEntry *record_tmp; | 228 | struct EgoEntry *ego_entry; |
229 | struct EgoEntry *ego_tmp; | ||
249 | 230 | ||
250 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 231 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
251 | "Cleaning up\n"); | 232 | "Cleaning up\n"); |
252 | if (NULL != handle->resp_object) | ||
253 | GNUNET_JSONAPI_document_delete (handle->resp_object); | ||
254 | if (NULL != handle->name) | ||
255 | GNUNET_free (handle->name); | ||
256 | if (NULL != handle->timeout_task) | 233 | if (NULL != handle->timeout_task) |
234 | { | ||
257 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | 235 | GNUNET_SCHEDULER_cancel (handle->timeout_task); |
258 | if (NULL != handle->ego_lookup) | 236 | handle->timeout_task = NULL; |
259 | GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup); | 237 | } |
260 | if (NULL != handle->get_default) | 238 | if (NULL != handle->label_name) |
261 | GNUNET_IDENTITY_cancel (handle->get_default); | 239 | GNUNET_free(handle->label_name); |
240 | if (NULL != handle->url) | ||
241 | GNUNET_free(handle->url); | ||
242 | if (NULL != handle->emsg) | ||
243 | GNUNET_free(handle->emsg); | ||
244 | if (NULL != handle->rd) | ||
245 | { | ||
246 | if (NULL != handle->rd->data) | ||
247 | GNUNET_free((void*)handle->rd->data); | ||
248 | GNUNET_free(handle->rd); | ||
249 | } | ||
250 | if (NULL != handle->timeout_task) | ||
251 | GNUNET_SCHEDULER_cancel(handle->timeout_task); | ||
262 | if (NULL != handle->list_it) | 252 | if (NULL != handle->list_it) |
263 | GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it); | 253 | GNUNET_NAMESTORE_zone_iteration_stop(handle->list_it); |
264 | if (NULL != handle->add_qe) | 254 | if (NULL != handle->add_qe) |
265 | GNUNET_NAMESTORE_cancel (handle->add_qe); | 255 | GNUNET_NAMESTORE_cancel(handle->add_qe); |
266 | if (NULL != handle->identity_handle) | 256 | if (NULL != handle->identity_handle) |
267 | GNUNET_IDENTITY_disconnect (handle->identity_handle); | 257 | GNUNET_IDENTITY_disconnect(handle->identity_handle); |
268 | if (NULL != handle->ns_handle) | 258 | if (NULL != handle->ns_handle) |
269 | GNUNET_NAMESTORE_disconnect (handle->ns_handle); | ||
270 | if (NULL != handle->url) | ||
271 | GNUNET_free (handle->url); | ||
272 | if (NULL != handle->value) | ||
273 | GNUNET_free (handle->value); | ||
274 | if (NULL != handle->rd) | ||
275 | { | 259 | { |
276 | for (unsigned int i = 0; i < handle->rd_count; i++) | 260 | GNUNET_NAMESTORE_disconnect(handle->ns_handle); |
277 | { | ||
278 | if (NULL != handle->rd[i].data) | ||
279 | GNUNET_free ((void*)handle->rd[i].data); | ||
280 | } | ||
281 | GNUNET_free (handle->rd); | ||
282 | } | 261 | } |
283 | if (NULL != handle->ego_name) | 262 | |
284 | GNUNET_free (handle->ego_name); | 263 | for (ego_entry = handle->ego_head; |
285 | for (record_entry = handle->record_head; | 264 | NULL != ego_entry;) |
286 | NULL != record_entry;) | ||
287 | { | 265 | { |
288 | record_tmp = record_entry; | 266 | ego_tmp = ego_entry; |
289 | record_entry = record_entry->next; | 267 | ego_entry = ego_entry->next; |
290 | GNUNET_free (record_tmp); | 268 | GNUNET_free(ego_tmp->identifier); |
269 | GNUNET_free(ego_tmp->keystring); | ||
270 | GNUNET_free(ego_tmp); | ||
291 | } | 271 | } |
272 | |||
273 | if(NULL != handle->resp_object) | ||
274 | { | ||
275 | json_decref(handle->resp_object); | ||
276 | } | ||
277 | |||
292 | GNUNET_free (handle); | 278 | GNUNET_free (handle); |
293 | } | 279 | } |
294 | 280 | ||
295 | 281 | ||
296 | /** | 282 | /** |
297 | * Create json representation of a GNSRECORD | 283 | * Task run on errors. Reports an error and cleans up everything. |
298 | * | 284 | * |
299 | * @param rd the GNSRECORD_Data | 285 | * @param cls the `struct RequestHandle` |
300 | */ | 286 | */ |
301 | static json_t * | 287 | static void |
302 | gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) | 288 | do_error (void *cls) |
303 | { | 289 | { |
304 | const char *typename; | 290 | struct RequestHandle *handle = cls; |
305 | char *string_val; | 291 | struct MHD_Response *resp; |
306 | const char *exp_str; | 292 | json_t *json_error = json_object(); |
307 | json_t *record_obj; | 293 | char *response; |
308 | 294 | ||
309 | typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); | 295 | if (NULL == handle->emsg) |
310 | string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type, | 296 | handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_ERROR_UNKNOWN); |
311 | rd->data, | ||
312 | rd->data_size); | ||
313 | 297 | ||
314 | if (NULL == string_val) | 298 | json_object_set_new(json_error,"error", json_string(handle->emsg)); |
315 | { | 299 | |
316 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 300 | if (0 == handle->response_code) |
317 | "Record of type %d malformed, skipping\n", | 301 | handle->response_code = MHD_HTTP_OK; |
318 | (int) rd->record_type); | 302 | response = json_dumps (json_error, 0); |
319 | return NULL; | 303 | resp = GNUNET_REST_create_response (response); |
320 | } | 304 | handle->proc (handle->proc_cls, resp, handle->response_code); |
321 | record_obj = json_object(); | 305 | json_decref(json_error); |
322 | json_object_set_new (record_obj, | 306 | GNUNET_free(response); |
323 | GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE, | 307 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); |
324 | json_string (typename)); | 308 | } |
325 | json_object_set_new (record_obj, | 309 | |
326 | GNUNET_REST_JSONAPI_NAMESTORE_VALUE, | 310 | |
327 | json_string (string_val)); | 311 | /** |
328 | GNUNET_free (string_val); | 312 | * Get EgoEntry from list with either a public key or a name |
329 | 313 | * If public key and name are not NULL, it returns the public key result first | |
330 | if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) | 314 | * |
315 | * @param handle the RequestHandle | ||
316 | * @param pubkey the public key of an identity (only one can be NULL) | ||
317 | * @param name the name of an identity (only one can be NULL) | ||
318 | * @return EgoEntry or NULL if not found | ||
319 | */ | ||
320 | struct EgoEntry* | ||
321 | get_egoentry(struct RequestHandle *handle, char* pubkey, char *name) | ||
322 | { | ||
323 | struct EgoEntry *ego_entry; | ||
324 | if (NULL != pubkey) | ||
331 | { | 325 | { |
332 | struct GNUNET_TIME_Relative time_rel; | 326 | for (ego_entry = handle->ego_head; |
333 | time_rel.rel_value_us = rd->expiration_time; | 327 | NULL != ego_entry; |
334 | exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); | 328 | ego_entry = ego_entry->next) |
329 | { | ||
330 | if (0 != strcasecmp (pubkey, ego_entry->keystring)) | ||
331 | continue; | ||
332 | return ego_entry; | ||
333 | } | ||
335 | } | 334 | } |
336 | else | 335 | if (NULL != name) |
337 | { | 336 | { |
338 | struct GNUNET_TIME_Absolute time_abs; | 337 | for (ego_entry = handle->ego_head; |
339 | time_abs.abs_value_us = rd->expiration_time; | 338 | NULL != ego_entry; |
340 | exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); | 339 | ego_entry = ego_entry->next) |
340 | { | ||
341 | if (0 != strcasecmp (name, ego_entry->identifier)) | ||
342 | continue; | ||
343 | return ego_entry; | ||
344 | } | ||
341 | } | 345 | } |
342 | json_object_set_new (record_obj, GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION, json_string (exp_str)); | 346 | return NULL; |
343 | |||
344 | json_object_set_new (record_obj, "expired", | ||
345 | json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); | ||
346 | return record_obj; | ||
347 | } | 347 | } |
348 | 348 | ||
349 | 349 | ||
350 | /** | 350 | /** |
351 | * Task run on error. Generates error response and cleans up. | 351 | * Does internal server error when iteration failed. |
352 | * | ||
353 | * @param cls the request to generate an error response for | ||
354 | */ | 352 | */ |
355 | static void | 353 | static void |
356 | do_error (void *cls) | 354 | namestore_iteration_error (void *cls) |
357 | { | 355 | { |
358 | struct RequestHandle *handle = cls; | 356 | struct RequestHandle *handle = cls; |
359 | struct MHD_Response *resp = GNUNET_REST_create_response (NULL); | 357 | struct MHD_Response *resp = GNUNET_REST_create_response (NULL); |
360 | 358 | handle->proc (handle->proc_cls, resp, MHD_HTTP_INTERNAL_SERVER_ERROR); | |
361 | handle->proc (handle->proc_cls, resp, handle->response_code); | 359 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); |
362 | cleanup_handle (handle); | ||
363 | } | 360 | } |
364 | 361 | ||
365 | 362 | ||
366 | /** | ||
367 | * Task run on timeout. | ||
368 | * | ||
369 | * @param cls the request to time out | ||
370 | */ | ||
371 | static void | 363 | static void |
372 | do_timeout (void *cls) | 364 | create_finished (void *cls, int32_t success, const char *emsg) |
373 | { | 365 | { |
374 | struct RequestHandle *handle = cls; | 366 | struct RequestHandle *handle = cls; |
367 | struct MHD_Response *resp; | ||
375 | 368 | ||
376 | handle->timeout_task = NULL; | 369 | handle->add_qe = NULL; |
377 | do_error (handle); | 370 | if (GNUNET_YES != success) |
371 | { | ||
372 | handle->emsg = GNUNET_strdup("Error storing records"); | ||
373 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
374 | return; | ||
375 | } | ||
376 | resp = GNUNET_REST_create_response (NULL); | ||
377 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); | ||
378 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
378 | } | 379 | } |
379 | 380 | ||
380 | 381 | ||
381 | static void | 382 | static void |
382 | cleanup_handle_delayed (void *cls) | 383 | del_finished (void *cls, int32_t success, const char *emsg) |
383 | { | 384 | { |
384 | cleanup_handle (cls); | 385 | struct RequestHandle *handle = cls; |
386 | |||
387 | handle->add_qe = NULL; | ||
388 | if (GNUNET_NO == success) | ||
389 | { | ||
390 | handle->emsg = GNUNET_strdup("Deleting record failed. Record does not exist"); | ||
391 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
392 | return; | ||
393 | } | ||
394 | if (GNUNET_SYSERR == success) | ||
395 | { | ||
396 | handle->emsg = GNUNET_strdup("Deleting record failed"); | ||
397 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
398 | return; | ||
399 | } | ||
400 | handle->proc (handle->proc_cls, | ||
401 | GNUNET_REST_create_response (NULL), | ||
402 | MHD_HTTP_NO_CONTENT); | ||
403 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
385 | } | 404 | } |
386 | 405 | ||
387 | 406 | ||
@@ -395,31 +414,24 @@ static void | |||
395 | namestore_list_finished (void *cls) | 414 | namestore_list_finished (void *cls) |
396 | { | 415 | { |
397 | struct RequestHandle *handle = cls; | 416 | struct RequestHandle *handle = cls; |
398 | char *result; | 417 | char *result_str; |
399 | struct MHD_Response *resp; | 418 | struct MHD_Response *resp; |
400 | 419 | ||
401 | handle->list_it = NULL; | 420 | handle->list_it = NULL; |
402 | if (NULL == handle->resp_object) | ||
403 | handle->resp_object = GNUNET_JSONAPI_document_new (); | ||
404 | 421 | ||
405 | if (GNUNET_SYSERR == | 422 | if (NULL == handle->resp_object) |
406 | GNUNET_JSONAPI_document_serialize (handle->resp_object, | ||
407 | &result)) | ||
408 | { | 423 | { |
409 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | 424 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
410 | GNUNET_SCHEDULER_add_now (&do_error, | ||
411 | handle); | ||
412 | return; | 425 | return; |
413 | } | 426 | } |
414 | resp = GNUNET_REST_create_response (result); | ||
415 | handle->proc (handle->proc_cls, | ||
416 | resp, | ||
417 | MHD_HTTP_OK); | ||
418 | GNUNET_free_non_null (result); | ||
419 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, | ||
420 | handle); | ||
421 | } | ||
422 | 427 | ||
428 | result_str = json_dumps (handle->resp_object, 0); | ||
429 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
430 | resp = GNUNET_REST_create_response (result_str); | ||
431 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
432 | GNUNET_free_non_null (result_str); | ||
433 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
434 | } | ||
423 | 435 | ||
424 | 436 | ||
425 | /** | 437 | /** |
@@ -428,84 +440,111 @@ namestore_list_finished (void *cls) | |||
428 | * @param handle the RequestHandle | 440 | * @param handle the RequestHandle |
429 | */ | 441 | */ |
430 | static void | 442 | static void |
431 | namestore_list_response (void *cls, | 443 | namestore_list_iteration (void *cls, |
432 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, | 444 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, |
433 | const char *rname, | 445 | const char *rname, |
434 | unsigned int rd_len, | 446 | unsigned int rd_len, |
435 | const struct GNUNET_GNSRECORD_Data *rd) | 447 | const struct GNUNET_GNSRECORD_Data *rd) |
436 | { | 448 | { |
437 | struct RequestHandle *handle = cls; | 449 | struct RequestHandle *handle = cls; |
438 | struct GNUNET_JSONAPI_Resource *json_resource; | ||
439 | json_t *result_array; | ||
440 | json_t *record_obj; | 450 | json_t *record_obj; |
441 | 451 | ||
442 | if (NULL == handle->resp_object) | 452 | if (NULL == handle->resp_object) |
443 | handle->resp_object = GNUNET_JSONAPI_document_new (); | 453 | handle->resp_object = json_array(); |
444 | 454 | ||
445 | if ( (NULL != handle->name) && | 455 | /*if ( (NULL != handle->ego_entry->identifier) && |
446 | (0 != strcmp (handle->name, | 456 | (0 != strcmp (handle->ego_entry->identifier, |
447 | rname)) ) | 457 | rname)) ) |
448 | { | 458 | { |
449 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 459 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
450 | "%s does not match %s\n", | 460 | "%s does not match %s\n", rname, |
451 | rname, | 461 | handle->ego_entry->identifier); |
452 | handle->name); | 462 | GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1); |
453 | GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, | ||
454 | 1); | ||
455 | return; | 463 | return; |
456 | } | 464 | }*/ |
457 | 465 | ||
458 | result_array = json_array (); | 466 | for (unsigned int i = 0; i < rd_len; i++) |
459 | for (unsigned int i=0; i<rd_len; i++) | ||
460 | { | 467 | { |
461 | if ( (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) && | 468 | if ( (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) && |
462 | (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)) ) | 469 | (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)) ) |
463 | continue; | 470 | continue; |
464 | 471 | ||
465 | if ( (rd[i].record_type != handle->type) && | 472 | record_obj = GNUNET_JSON_from_gns_record(rname,rd); |
466 | (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) | 473 | |
474 | if(NULL == record_obj) | ||
467 | continue; | 475 | continue; |
468 | record_obj = gnsrecord_to_json (&rd[i]); | ||
469 | json_array_append (result_array, | ||
470 | record_obj); | ||
471 | json_decref (record_obj); | ||
472 | } | ||
473 | 476 | ||
474 | if (0 < json_array_size(result_array)) | 477 | json_array_append (handle->resp_object, record_obj); |
475 | { | 478 | json_decref (record_obj); |
476 | json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO, | ||
477 | rname); | ||
478 | GNUNET_JSONAPI_resource_add_attr (json_resource, | ||
479 | GNUNET_REST_JSONAPI_NAMESTORE_RECORD, | ||
480 | result_array); | ||
481 | GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); | ||
482 | } | 479 | } |
483 | 480 | ||
484 | json_decref (result_array); | 481 | GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1); |
485 | GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, | ||
486 | 1); | ||
487 | } | 482 | } |
488 | 483 | ||
489 | 484 | ||
490 | static void | 485 | /** |
491 | create_finished (void *cls, int32_t success, const char *emsg) | 486 | * Handle namestore GET request |
487 | * | ||
488 | * @param con_handle the connection handle | ||
489 | * @param url the url | ||
490 | * @param cls the RequestHandle | ||
491 | */ | ||
492 | void | ||
493 | namestore_get (struct GNUNET_REST_RequestHandle *con_handle, | ||
494 | const char* url, | ||
495 | void *cls) | ||
492 | { | 496 | { |
493 | struct RequestHandle *handle = cls; | 497 | struct RequestHandle *handle = cls; |
494 | struct MHD_Response *resp; | 498 | struct EgoEntry *ego_entry = NULL; |
499 | struct GNUNET_HashCode key; | ||
500 | char *pubkey = NULL; | ||
501 | char *name = NULL; | ||
502 | |||
503 | //change zone if pubkey or name specified | ||
504 | GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_PUBKEY, | ||
505 | strlen (GNUNET_REST_API_PARAM_PUBKEY), | ||
506 | &key); | ||
507 | if ( GNUNET_YES | ||
508 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, | ||
509 | &key)) | ||
510 | { | ||
511 | pubkey = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, | ||
512 | &key); | ||
513 | } | ||
514 | GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_NAME, | ||
515 | strlen (GNUNET_REST_API_PARAM_NAME), | ||
516 | &key); | ||
517 | if ( GNUNET_YES | ||
518 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, | ||
519 | &key)) | ||
520 | { | ||
521 | name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, | ||
522 | &key); | ||
523 | } | ||
495 | 524 | ||
496 | handle->add_qe = NULL; | 525 | ego_entry = get_egoentry(handle,pubkey,name); |
497 | if (GNUNET_YES != success) | 526 | if (NULL == ego_entry) |
498 | { | 527 | { |
499 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 528 | if (NULL != pubkey || NULL != name) |
500 | "Error storing records%s%s\n", | 529 | { |
501 | (NULL == emsg) ? "" : ": ", | 530 | handle->emsg = GNUNET_strdup("Invalid identity"); |
502 | (NULL == emsg) ? "" : emsg); | 531 | handle->response_code = MHD_HTTP_NOT_FOUND; |
503 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | 532 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
504 | return; | 533 | return; |
534 | } | ||
505 | } | 535 | } |
506 | resp = GNUNET_REST_create_response (NULL); | 536 | if ( NULL != ego_entry ) |
507 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); | 537 | { |
508 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | 538 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego); |
539 | } | ||
540 | handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, | ||
541 | handle->zone_pkey, | ||
542 | &namestore_iteration_error, | ||
543 | handle, | ||
544 | &namestore_list_iteration, | ||
545 | handle, | ||
546 | &namestore_list_finished, | ||
547 | handle); | ||
509 | } | 548 | } |
510 | 549 | ||
511 | 550 | ||
@@ -529,10 +568,10 @@ create_new_record_cont (void *cls, | |||
529 | struct RequestHandle *handle = cls; | 568 | struct RequestHandle *handle = cls; |
530 | 569 | ||
531 | handle->add_qe = NULL; | 570 | handle->add_qe = NULL; |
532 | if (0 != strcmp (rec_name, handle->name)) | 571 | if (0 != strcmp (rec_name, handle->label_name)) |
533 | { | 572 | { |
534 | GNUNET_break (0); | 573 | GNUNET_break (0); |
535 | do_error (handle); | 574 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
536 | return; | 575 | return; |
537 | } | 576 | } |
538 | 577 | ||
@@ -541,426 +580,262 @@ create_new_record_cont (void *cls, | |||
541 | handle->proc (handle->proc_cls, | 580 | handle->proc (handle->proc_cls, |
542 | GNUNET_REST_create_response (NULL), | 581 | GNUNET_REST_create_response (NULL), |
543 | MHD_HTTP_CONFLICT); | 582 | MHD_HTTP_CONFLICT); |
544 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | 583 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); |
545 | return; | 584 | return; |
546 | } | 585 | } |
547 | |||
548 | GNUNET_assert (NULL != handle->name); | ||
549 | handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, | 586 | handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, |
550 | &handle->zone_pkey, | 587 | handle->zone_pkey, |
551 | handle->name, | 588 | handle->label_name, |
552 | handle->rd_count, | 589 | GNUNET_REST_NAMESTORE_RD_COUNT, |
553 | handle->rd, | 590 | handle->rd, |
554 | &create_finished, | 591 | &create_finished, |
555 | handle); | 592 | handle); |
556 | } | 593 | } |
557 | 594 | ||
558 | 595 | /** | |
559 | static void | 596 | * Handle namestore POST request |
560 | del_finished (void *cls, | 597 | * |
561 | int32_t success, | 598 | * @param con_handle the connection handle |
562 | const char *emsg) | 599 | * @param url the url |
600 | * @param cls the RequestHandle | ||
601 | */ | ||
602 | void | ||
603 | namestore_add (struct GNUNET_REST_RequestHandle *con_handle, | ||
604 | const char* url, | ||
605 | void *cls) | ||
563 | { | 606 | { |
564 | struct RequestHandle *handle = cls; | 607 | struct RequestHandle *handle = cls; |
608 | struct GNUNET_GNSRECORD_Data *gns_record; | ||
609 | json_t *data_js; | ||
610 | json_t *name_json; | ||
611 | json_error_t err; | ||
565 | 612 | ||
566 | handle->add_qe = NULL; | 613 | struct EgoEntry *ego_entry = NULL; |
567 | if (GNUNET_NO == success) | 614 | struct GNUNET_HashCode key; |
615 | char *pubkey = NULL; | ||
616 | char *name = NULL; | ||
617 | |||
618 | char term_data[handle->rest_handle->data_size + 1]; | ||
619 | struct GNUNET_JSON_Specification gnsspec[] = { | ||
620 | GNUNET_JSON_spec_gnsrecord_data(&gns_record), | ||
621 | GNUNET_JSON_spec_end () | ||
622 | }; | ||
623 | |||
624 | if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url)) | ||
568 | { | 625 | { |
569 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 626 | handle->emsg = GNUNET_strdup("Wrong URL"); |
570 | _("Deleting record failed, record does not exist%s%s\n"), | 627 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
571 | (NULL != emsg) ? ": " : "", | ||
572 | (NULL != emsg) ? emsg : ""); | ||
573 | GNUNET_SCHEDULER_add_now (&do_error, handle); //do_not_found TODO | ||
574 | return; | 628 | return; |
575 | } | 629 | } |
576 | if (GNUNET_SYSERR == success) | 630 | if (0 >= handle->rest_handle->data_size) |
577 | { | 631 | { |
578 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 632 | handle->emsg = GNUNET_strdup("No data"); |
579 | _("Deleting record failed%s%s\n"), | ||
580 | (NULL != emsg) ? ": " : "", | ||
581 | (NULL != emsg) ? emsg : ""); | ||
582 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 633 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
583 | return; | 634 | return; |
584 | } | 635 | } |
585 | handle->proc (handle->proc_cls, | 636 | term_data[handle->rest_handle->data_size] = '\0'; |
586 | GNUNET_REST_create_response (NULL), | 637 | GNUNET_memcpy(term_data, handle->rest_handle->data, |
587 | MHD_HTTP_NO_CONTENT); | 638 | handle->rest_handle->data_size); |
588 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | 639 | data_js = json_loads (term_data, JSON_DECODE_ANY, &err); |
589 | } | 640 | if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL)) |
590 | |||
591 | |||
592 | static void | ||
593 | del_cont (void *cls, | ||
594 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
595 | const char *label, | ||
596 | unsigned int rd_count, | ||
597 | const struct GNUNET_GNSRECORD_Data *rd) | ||
598 | { | ||
599 | struct RequestHandle *handle = cls; | ||
600 | |||
601 | handle->add_qe = NULL; | ||
602 | if (0 == rd_count) | ||
603 | { | 641 | { |
604 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 642 | handle->emsg = GNUNET_strdup("Invalid data"); |
605 | _("There are no records under label `%s' that could be deleted.\n"), | 643 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
606 | label); | 644 | GNUNET_JSON_parse_free(gnsspec); |
607 | do_error (handle); | 645 | json_decref (data_js); |
608 | return; | 646 | return; |
609 | } | 647 | } |
648 | handle->rd = gns_record; | ||
610 | 649 | ||
611 | handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, | 650 | name_json = json_object_get(data_js, "label"); |
612 | &handle->zone_pkey, | 651 | if (!json_is_string(name_json)) |
613 | handle->name, | ||
614 | 0, NULL, | ||
615 | &del_finished, | ||
616 | handle); | ||
617 | } | ||
618 | |||
619 | |||
620 | static void | ||
621 | namestore_delete_cont (struct GNUNET_REST_RequestHandle *con, | ||
622 | const char *url, | ||
623 | void *cls) | ||
624 | { | ||
625 | struct RequestHandle *handle = cls; | ||
626 | |||
627 | if (NULL == handle->name) | ||
628 | { | 652 | { |
653 | handle->emsg = GNUNET_strdup("Missing name"); | ||
629 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 654 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
655 | json_decref (data_js); | ||
630 | return; | 656 | return; |
631 | } | 657 | } |
632 | 658 | handle->label_name = GNUNET_strdup(json_string_value(name_json)); | |
633 | handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, | 659 | if(NULL == handle->label_name) |
634 | &handle->zone_pkey, | ||
635 | handle->name, | ||
636 | &do_error, | ||
637 | handle, | ||
638 | &del_cont, | ||
639 | handle); | ||
640 | } | ||
641 | |||
642 | |||
643 | static int | ||
644 | json_to_gnsrecord (const json_t *records_json, | ||
645 | struct GNUNET_GNSRECORD_Data **rd, | ||
646 | unsigned int *rd_count) | ||
647 | { | ||
648 | struct GNUNET_TIME_Relative etime_rel; | ||
649 | struct GNUNET_TIME_Absolute etime_abs; | ||
650 | char *value; | ||
651 | void *rdata; | ||
652 | size_t rdata_size; | ||
653 | const char *typestring; | ||
654 | const char *expirationstring; | ||
655 | json_t *type_json; | ||
656 | json_t *value_json; | ||
657 | json_t *record_json; | ||
658 | json_t *exp_json; | ||
659 | |||
660 | *rd_count = json_array_size (records_json); | ||
661 | *rd = GNUNET_new_array (*rd_count, | ||
662 | struct GNUNET_GNSRECORD_Data); | ||
663 | for (unsigned int i = 0; i < *rd_count; i++) | ||
664 | { | 660 | { |
665 | memset (&(*rd)[i], | 661 | handle->emsg = GNUNET_strdup("Missing name"); |
666 | 0, | ||
667 | sizeof (struct GNUNET_GNSRECORD_Data)); | ||
668 | record_json = json_array_get (records_json, | ||
669 | i); | ||
670 | type_json = json_object_get (record_json, | ||
671 | GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE); | ||
672 | if (! json_is_string (type_json)) | ||
673 | { | ||
674 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
675 | "Type property is no string\n"); | ||
676 | return GNUNET_SYSERR; | ||
677 | } | ||
678 | typestring = json_string_value (type_json); | ||
679 | (*rd)[i].record_type = GNUNET_GNSRECORD_typename_to_number (typestring); | ||
680 | if (UINT32_MAX == (*rd)[i].record_type) | ||
681 | { | ||
682 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported type `%s'\n"), | ||
683 | json_string_value (type_json)); | ||
684 | return GNUNET_SYSERR; | ||
685 | } | ||
686 | value_json = json_object_get (record_json, | ||
687 | GNUNET_REST_JSONAPI_NAMESTORE_VALUE); | ||
688 | if (! json_is_string (value_json)) | ||
689 | { | ||
690 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
691 | "Value property is no string\n"); | ||
692 | return GNUNET_SYSERR; | ||
693 | } | ||
694 | value = GNUNET_strdup (json_string_value (value_json)); | ||
695 | if (GNUNET_OK != | ||
696 | GNUNET_GNSRECORD_string_to_value ((*rd)[i].record_type, | ||
697 | value, | ||
698 | &rdata, | ||
699 | &rdata_size)) | ||
700 | { | ||
701 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
702 | _("Value `%s' invalid for record type `%s'\n"), | ||
703 | value, | ||
704 | typestring); | ||
705 | return GNUNET_SYSERR; | ||
706 | } | ||
707 | (*rd)[i].data = rdata; | ||
708 | (*rd)[i].data_size = rdata_size; | ||
709 | /**TODO | ||
710 | * if (1 == handle->is_shadow) | ||
711 | rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; | ||
712 | if (1 != handle->is_public) | ||
713 | rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; | ||
714 | */ | ||
715 | exp_json = json_object_get (record_json, | ||
716 | GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION); | ||
717 | if (! json_is_string (exp_json)) | ||
718 | { | ||
719 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
720 | "Expiration property is no string\n"); | ||
721 | return GNUNET_SYSERR; | ||
722 | } | ||
723 | expirationstring = json_string_value (exp_json); | ||
724 | if (0 == strcmp (expirationstring, "never")) | ||
725 | { | ||
726 | (*rd)[i].expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; | ||
727 | } | ||
728 | else if (GNUNET_OK == | ||
729 | GNUNET_STRINGS_fancy_time_to_relative (expirationstring, | ||
730 | &etime_rel)) | ||
731 | { | ||
732 | (*rd)[i].expiration_time = etime_rel.rel_value_us; | ||
733 | (*rd)[i].flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; | ||
734 | } | ||
735 | else if (GNUNET_OK == | ||
736 | GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, | ||
737 | &etime_abs)) | ||
738 | { | ||
739 | (*rd)[i].expiration_time = etime_abs.abs_value_us; | ||
740 | } | ||
741 | else | ||
742 | { | ||
743 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
744 | _("Value `%s' invalid for record type `%s'\n"), | ||
745 | value, | ||
746 | typestring); | ||
747 | return GNUNET_SYSERR; | ||
748 | } | ||
749 | } | ||
750 | return GNUNET_OK; | ||
751 | } | ||
752 | |||
753 | |||
754 | static void | ||
755 | namestore_create_cont (struct GNUNET_REST_RequestHandle *con, | ||
756 | const char *url, | ||
757 | void *cls) | ||
758 | { | ||
759 | struct RequestHandle *handle = cls; | ||
760 | struct MHD_Response *resp; | ||
761 | struct GNUNET_JSONAPI_Document *json_obj; | ||
762 | struct GNUNET_JSONAPI_Resource *json_res; | ||
763 | json_t *records_json; | ||
764 | json_t *data_js; | ||
765 | json_error_t err; | ||
766 | char term_data[handle->rest_handle->data_size+1]; | ||
767 | struct GNUNET_JSON_Specification docspec[] = { | ||
768 | GNUNET_JSON_spec_jsonapi_document (&json_obj), | ||
769 | GNUNET_JSON_spec_end() | ||
770 | }; | ||
771 | |||
772 | if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url)) | ||
773 | { | ||
774 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
775 | "Cannot create under %s\n", handle->url); | ||
776 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 662 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
663 | json_decref (data_js); | ||
777 | return; | 664 | return; |
778 | } | 665 | } |
779 | if (0 >= handle->rest_handle->data_size) | 666 | if (0 >= strlen(handle->label_name)) |
780 | { | 667 | { |
668 | handle->emsg = GNUNET_strdup("Missing name"); | ||
781 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 669 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
670 | json_decref (data_js); | ||
782 | return; | 671 | return; |
783 | } | 672 | } |
784 | term_data[handle->rest_handle->data_size] = '\0'; | ||
785 | GNUNET_memcpy (term_data, | ||
786 | handle->rest_handle->data, | ||
787 | handle->rest_handle->data_size); | ||
788 | data_js = json_loads (term_data, | ||
789 | JSON_DECODE_ANY, | ||
790 | &err); | ||
791 | GNUNET_assert (GNUNET_OK == | ||
792 | GNUNET_JSON_parse (data_js, docspec, | ||
793 | NULL, NULL)); | ||
794 | json_decref (data_js); | 673 | json_decref (data_js); |
795 | if (NULL == json_obj) | 674 | |
675 | //change zone if pubkey or name specified | ||
676 | GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_PUBKEY, | ||
677 | strlen (GNUNET_REST_API_PARAM_PUBKEY), | ||
678 | &key); | ||
679 | if ( GNUNET_YES | ||
680 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, | ||
681 | &key)) | ||
796 | { | 682 | { |
797 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 683 | pubkey = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, |
798 | "Unable to parse JSONAPI Object from %s\n", | 684 | &key); |
799 | term_data); | ||
800 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
801 | return; | ||
802 | } | 685 | } |
803 | if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) | 686 | GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_NAME, |
687 | strlen (GNUNET_REST_API_PARAM_NAME), | ||
688 | &key); | ||
689 | if ( GNUNET_YES | ||
690 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, | ||
691 | &key)) | ||
804 | { | 692 | { |
805 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 693 | name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, |
806 | "Cannot create more than 1 resource! (Got %d)\n", | 694 | &key); |
807 | GNUNET_JSONAPI_document_resource_count (json_obj)); | ||
808 | GNUNET_JSONAPI_document_delete (json_obj); | ||
809 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
810 | return; | ||
811 | } | 695 | } |
812 | json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); | 696 | |
813 | if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, | 697 | ego_entry = get_egoentry(handle,pubkey,name); |
814 | GNUNET_REST_JSONAPI_NAMESTORE_RECORD)) | 698 | if (NULL == ego_entry) |
815 | { | 699 | { |
816 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 700 | if (NULL != pubkey || NULL != name) |
817 | "Unsupported JSON data type\n"); | 701 | { |
818 | GNUNET_JSONAPI_document_delete (json_obj); | 702 | handle->emsg = GNUNET_strdup("Invalid identity"); |
819 | resp = GNUNET_REST_create_response (NULL); | 703 | handle->response_code = MHD_HTTP_NOT_FOUND; |
820 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | 704 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
821 | cleanup_handle (handle); | 705 | return; |
822 | return; | 706 | } |
823 | } | 707 | } |
824 | handle->name = GNUNET_strdup (GNUNET_JSONAPI_resource_get_id (json_res)); | 708 | if ( NULL != ego_entry ) |
825 | records_json = GNUNET_JSONAPI_resource_read_attr (json_res, | ||
826 | GNUNET_REST_JSONAPI_NAMESTORE_RECORD); | ||
827 | if (NULL == records_json) | ||
828 | { | 709 | { |
829 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 710 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego); |
830 | "No records given\n"); | ||
831 | GNUNET_JSONAPI_document_delete (json_obj); | ||
832 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
833 | return; | ||
834 | } | 711 | } |
835 | if (GNUNET_SYSERR == json_to_gnsrecord (records_json, &handle->rd, &handle->rd_count)) | 712 | if (NULL == handle->zone_pkey) |
836 | { | 713 | { |
837 | GNUNET_JSONAPI_document_delete (json_obj); | 714 | handle->emsg = GNUNET_strdup("No default identity for namestore"); |
838 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 715 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
839 | return; | 716 | return; |
840 | } | 717 | } |
841 | GNUNET_JSONAPI_document_delete (json_obj); | ||
842 | |||
843 | handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, | 718 | handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, |
844 | &handle->zone_pkey, | 719 | handle->zone_pkey, |
845 | handle->name, | 720 | handle->label_name, |
846 | &do_error, | 721 | &do_error, |
847 | handle, | 722 | handle, |
848 | &create_new_record_cont, | 723 | &create_new_record_cont, |
849 | handle); | 724 | handle); |
850 | } | 725 | } |
851 | 726 | ||
852 | 727 | ||
853 | static void | 728 | static void |
854 | namestore_zkey_response (void *cls, | 729 | del_cont (void *cls, |
855 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | 730 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, |
856 | const char *label, | 731 | const char *label, |
857 | unsigned int rd_count, | 732 | unsigned int rd_count, |
858 | const struct GNUNET_GNSRECORD_Data *rd) | 733 | const struct GNUNET_GNSRECORD_Data *rd) |
859 | { | 734 | { |
860 | struct RequestHandle *handle = cls; | 735 | struct RequestHandle *handle = cls; |
861 | struct MHD_Response *resp; | ||
862 | struct GNUNET_JSONAPI_Document *json_obj; | ||
863 | struct GNUNET_JSONAPI_Resource *json_res; | ||
864 | json_t *name_json; | ||
865 | char* result; | ||
866 | 736 | ||
867 | handle->reverse_qe = NULL; | 737 | handle->add_qe = NULL; |
868 | json_obj = GNUNET_JSONAPI_document_new (); | 738 | if (0 == rd_count) |
869 | if (NULL != label) | ||
870 | { | ||
871 | name_json = json_string (label); | ||
872 | json_res = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_REVINFO, | ||
873 | handle->zkey_str); | ||
874 | GNUNET_JSONAPI_resource_add_attr (json_res, | ||
875 | GNUNET_REST_JSONAPI_NAMESTORE_NAME, | ||
876 | name_json); | ||
877 | GNUNET_JSONAPI_document_resource_add (json_obj, json_res); | ||
878 | json_decref (name_json); | ||
879 | } | ||
880 | //Handle response | ||
881 | if (GNUNET_SYSERR == GNUNET_JSONAPI_document_serialize (json_obj, &result)) | ||
882 | { | 739 | { |
883 | GNUNET_JSONAPI_document_delete (json_obj); | 740 | handle->emsg = GNUNET_strdup("Record not found"); |
884 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 741 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
885 | return; | 742 | return; |
886 | } | 743 | } |
887 | resp = GNUNET_REST_create_response (result); | ||
888 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
889 | GNUNET_JSONAPI_document_delete (json_obj); | ||
890 | GNUNET_free (result); | ||
891 | GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); | ||
892 | } | ||
893 | 744 | ||
745 | handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, | ||
746 | handle->zone_pkey, | ||
747 | handle->label_name, | ||
748 | 0, NULL, | ||
749 | &del_finished, | ||
750 | handle); | ||
751 | } | ||
894 | 752 | ||
895 | static void | 753 | /** |
896 | namestore_zkey_cont (struct GNUNET_REST_RequestHandle *con, | 754 | * Handle namestore DELETE request |
897 | const char *url, | 755 | * |
898 | void *cls) | 756 | * @param con_handle the connection handle |
757 | * @param url the url | ||
758 | * @param cls the RequestHandle | ||
759 | */ | ||
760 | void | ||
761 | namestore_delete (struct GNUNET_REST_RequestHandle *con_handle, | ||
762 | const char* url, | ||
763 | void *cls) | ||
899 | { | 764 | { |
900 | struct RequestHandle *handle = cls; | 765 | struct RequestHandle *handle = cls; |
901 | struct GNUNET_HashCode key; | 766 | struct GNUNET_HashCode key; |
902 | struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; | 767 | struct EgoEntry *ego_entry = NULL; |
903 | 768 | char *pubkey = NULL; | |
904 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY, | 769 | char *name = NULL; |
905 | strlen (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY), | 770 | |
906 | &key); | 771 | //change zone if pubkey or name specified |
907 | if ( GNUNET_NO == | 772 | GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_PUBKEY, |
908 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | 773 | strlen (GNUNET_REST_API_PARAM_PUBKEY), |
909 | &key) ) | 774 | &key); |
775 | if ( GNUNET_YES | ||
776 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, | ||
777 | &key)) | ||
910 | { | 778 | { |
911 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 779 | pubkey = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, |
912 | "No zkey given %s\n", handle->url); | 780 | &key); |
781 | } | ||
782 | GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_NAME, | ||
783 | strlen (GNUNET_REST_API_PARAM_NAME), | ||
784 | &key); | ||
785 | if ( GNUNET_YES | ||
786 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, | ||
787 | &key)) | ||
788 | { | ||
789 | name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, | ||
790 | &key); | ||
791 | } | ||
792 | |||
793 | ego_entry = get_egoentry(handle,pubkey,name); | ||
794 | if (NULL == ego_entry) | ||
795 | { | ||
796 | if (NULL != pubkey || NULL != name) | ||
797 | { | ||
798 | handle->emsg = GNUNET_strdup("Invalid identity"); | ||
799 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
800 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
801 | return; | ||
802 | } | ||
803 | } | ||
804 | if ( NULL != ego_entry ) | ||
805 | { | ||
806 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego); | ||
807 | } | ||
808 | |||
809 | GNUNET_CRYPTO_hash ("label", strlen ("label"), &key); | ||
810 | if ( GNUNET_NO | ||
811 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, | ||
812 | &key)) | ||
813 | { | ||
814 | handle->emsg = GNUNET_strdup("Missing name"); | ||
913 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 815 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
914 | return; | 816 | return; |
915 | } | 817 | } |
916 | handle->zkey_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, | 818 | handle->label_name = GNUNET_strdup( |
917 | &key); | 819 | GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key)); |
918 | if ((NULL == handle->zkey_str) || | 820 | |
919 | (GNUNET_OK != | 821 | if (NULL == handle->zone_pkey) |
920 | GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str, | ||
921 | strlen (handle->zkey_str), | ||
922 | &pubkey))) | ||
923 | { | 822 | { |
924 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 823 | handle->emsg = GNUNET_strdup("No default identity for namestore"); |
925 | "Zkey invalid %s\n", handle->zkey_str); | ||
926 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 824 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
927 | return; | 825 | return; |
928 | } | 826 | } |
929 | handle->reverse_qe = GNUNET_NAMESTORE_zone_to_name (handle->ns_handle, | ||
930 | &handle->zone_pkey, | ||
931 | &pubkey, | ||
932 | &do_error, | ||
933 | handle, | ||
934 | &namestore_zkey_response, | ||
935 | handle); | ||
936 | } | ||
937 | |||
938 | 827 | ||
939 | static void | 828 | handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, |
940 | namestore_info_cont (struct GNUNET_REST_RequestHandle *con, | 829 | handle->zone_pkey, |
941 | const char *url, | 830 | handle->label_name, |
942 | void *cls) | 831 | &do_error, |
943 | { | 832 | handle, |
944 | struct RequestHandle *handle = cls; | 833 | &del_cont, |
834 | handle); | ||
945 | 835 | ||
946 | handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, | ||
947 | &handle->zone_pkey, | ||
948 | &do_error, | ||
949 | handle, | ||
950 | &namestore_list_response, | ||
951 | handle, | ||
952 | &namestore_list_finished, | ||
953 | handle); | ||
954 | } | 836 | } |
955 | 837 | ||
956 | 838 | ||
957 | static char* | ||
958 | get_name_from_url (const char* url) | ||
959 | { | ||
960 | if (strlen (url) <= strlen (GNUNET_REST_API_NS_NAMESTORE)) | ||
961 | return NULL; | ||
962 | return (char*)url + strlen (GNUNET_REST_API_NS_NAMESTORE) + 1; | ||
963 | } | ||
964 | 839 | ||
965 | /** | 840 | /** |
966 | * Respond to OPTIONS request | 841 | * Respond to OPTIONS request |
@@ -977,101 +852,72 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, | |||
977 | struct MHD_Response *resp; | 852 | struct MHD_Response *resp; |
978 | struct RequestHandle *handle = cls; | 853 | struct RequestHandle *handle = cls; |
979 | 854 | ||
980 | //For now, independent of path return all options | 855 | //independent of path return all options |
981 | resp = GNUNET_REST_create_response (NULL); | 856 | resp = GNUNET_REST_create_response (NULL); |
982 | MHD_add_response_header (resp, | 857 | MHD_add_response_header (resp, |
983 | "Access-Control-Allow-Methods", | 858 | "Access-Control-Allow-Methods", |
984 | allow_methods); | 859 | allow_methods); |
985 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | 860 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); |
986 | cleanup_handle (handle); | 861 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); |
862 | return; | ||
987 | } | 863 | } |
988 | 864 | ||
989 | 865 | ||
990 | /** | 866 | /** |
991 | * Callback invoked from identity service with ego information. | 867 | * Handle rest request |
992 | * An @a ego of NULL means the ego was not found. | ||
993 | * | 868 | * |
994 | * @param cls closure with the configuration | 869 | * @param handle the request handle |
995 | * @param ego an ego known to identity service, or NULL | ||
996 | */ | 870 | */ |
997 | static void | 871 | static void |
998 | identity_cb (void *cls, | 872 | init_cont (struct RequestHandle *handle) |
999 | const struct GNUNET_IDENTITY_Ego *ego) | ||
1000 | { | 873 | { |
1001 | struct RequestHandle *handle = cls; | ||
1002 | struct MHD_Response *resp; | ||
1003 | struct GNUNET_REST_RequestHandlerError err; | 874 | struct GNUNET_REST_RequestHandlerError err; |
1004 | static const struct GNUNET_REST_RequestHandler handlers[] = { | 875 | static const struct GNUNET_REST_RequestHandler handlers[] = { |
1005 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE_ZKEY, &namestore_zkey_cont}, //reverse | 876 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get}, |
1006 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_info_cont}, //list | 877 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add}, |
1007 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_create_cont}, //create | 878 | {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete}, |
1008 | // {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_edit_cont}, //update. TODO this shoul be PATCH | ||
1009 | {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete_cont}, //delete | ||
1010 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont}, | 879 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont}, |
1011 | GNUNET_REST_HANDLER_END | 880 | GNUNET_REST_HANDLER_END |
1012 | }; | 881 | }; |
1013 | 882 | ||
1014 | handle->ego_lookup = NULL; | 883 | if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, |
1015 | if (NULL == ego) | 884 | handlers, |
1016 | { | 885 | &err, |
1017 | if (NULL != handle->ego_name) | 886 | handle)) |
1018 | { | ||
1019 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1020 | _("Ego `%s' not known to identity service\n"), | ||
1021 | handle->ego_name); | ||
1022 | } | ||
1023 | resp = GNUNET_REST_create_response (NULL); | ||
1024 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); | ||
1025 | cleanup_handle (handle); | ||
1026 | return; | ||
1027 | } | ||
1028 | handle->zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); | ||
1029 | handle->ns_handle = GNUNET_NAMESTORE_connect (cfg); | ||
1030 | if (NULL == handle->ns_handle) | ||
1031 | { | ||
1032 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1033 | _("Failed to connect to namestore\n")); | ||
1034 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1035 | return; | ||
1036 | } | ||
1037 | |||
1038 | if (GNUNET_OK != | ||
1039 | GNUNET_JSONAPI_handle_request (handle->rest_handle, | ||
1040 | handlers, | ||
1041 | &err, | ||
1042 | handle)) | ||
1043 | { | 887 | { |
1044 | handle->response_code = err.error_code; | 888 | handle->response_code = err.error_code; |
1045 | GNUNET_SCHEDULER_add_now (&do_error, | 889 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
1046 | (void *) handle); | ||
1047 | } | 890 | } |
1048 | } | 891 | } |
1049 | 892 | ||
1050 | 893 | /** | |
894 | * @param cls closure | ||
895 | * @param ego ego handle | ||
896 | * @param ctx context for application to store data for this ego | ||
897 | * (during the lifetime of this process, initially NULL) | ||
898 | * @param identifier identifier assigned by the user for this ego, | ||
899 | * NULL if the user just deleted the ego and it | ||
900 | * must thus no longer be used | ||
901 | */ | ||
1051 | static void | 902 | static void |
1052 | default_ego_cb (void *cls, | 903 | default_ego_cb (void *cls, |
1053 | struct GNUNET_IDENTITY_Ego *ego, | 904 | struct GNUNET_IDENTITY_Ego *ego, |
1054 | void **ctx, | 905 | void **ctx, |
1055 | const char *name) | 906 | const char *identifier) |
1056 | { | 907 | { |
1057 | struct RequestHandle *handle = cls; | 908 | struct RequestHandle *handle = cls; |
1058 | struct MHD_Response *resp; | 909 | handle->op = NULL; |
1059 | handle->get_default = NULL; | 910 | |
1060 | if (NULL == ego) | 911 | if (ego != NULL) |
1061 | { | ||
1062 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1063 | _("No default ego configured in identity service\n")); | ||
1064 | resp = GNUNET_REST_create_response (NULL); | ||
1065 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); | ||
1066 | cleanup_handle (handle); | ||
1067 | return; | ||
1068 | } | ||
1069 | else | ||
1070 | { | 912 | { |
1071 | identity_cb (cls, ego); | 913 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego); |
1072 | } | 914 | } |
1073 | } | 915 | } |
1074 | 916 | ||
917 | |||
918 | /** | ||
919 | * Connect to identity callback | ||
920 | */ | ||
1075 | static void | 921 | static void |
1076 | id_connect_cb (void *cls, | 922 | id_connect_cb (void *cls, |
1077 | struct GNUNET_IDENTITY_Ego *ego, | 923 | struct GNUNET_IDENTITY_Ego *ego, |
@@ -1079,12 +925,33 @@ id_connect_cb (void *cls, | |||
1079 | const char *name) | 925 | const char *name) |
1080 | { | 926 | { |
1081 | struct RequestHandle *handle = cls; | 927 | struct RequestHandle *handle = cls; |
1082 | if (NULL == ego) | 928 | struct EgoEntry *ego_entry; |
929 | struct GNUNET_CRYPTO_EcdsaPublicKey pk; | ||
930 | |||
931 | if ((NULL == ego) && (NULL == handle->zone_pkey)) | ||
932 | { | ||
933 | handle->op = GNUNET_IDENTITY_get (handle->identity_handle, | ||
934 | GNUNET_REST_SUBSYSTEM_NAMESTORE, | ||
935 | &default_ego_cb, | ||
936 | handle); | ||
937 | } | ||
938 | if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) | ||
939 | { | ||
940 | handle->state = ID_REST_STATE_POST_INIT; | ||
941 | init_cont (handle); | ||
942 | return; | ||
943 | } | ||
944 | if (ID_REST_STATE_INIT == handle->state) | ||
1083 | { | 945 | { |
1084 | handle->get_default = GNUNET_IDENTITY_get (handle->identity_handle, | 946 | ego_entry = GNUNET_new(struct EgoEntry); |
1085 | "namestore", | 947 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); |
1086 | &default_ego_cb, handle); | 948 | ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); |
949 | ego_entry->ego = ego; | ||
950 | GNUNET_asprintf (&ego_entry->identifier, "%s", name); | ||
951 | GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail, | ||
952 | ego_entry); | ||
1087 | } | 953 | } |
954 | |||
1088 | } | 955 | } |
1089 | 956 | ||
1090 | 957 | ||
@@ -1097,81 +964,38 @@ id_connect_cb (void *cls, | |||
1097 | * @param data_size length of the body | 964 | * @param data_size length of the body |
1098 | * @param proc callback function for the result | 965 | * @param proc callback function for the result |
1099 | * @param proc_cls closure for callback function | 966 | * @param proc_cls closure for callback function |
1100 | * @return #GNUNET_OK if request accepted | 967 | * @return GNUNET_OK if request accepted |
1101 | */ | 968 | */ |
1102 | static void | 969 | static void |
1103 | rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, | 970 | rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, |
1104 | GNUNET_REST_ResultProcessor proc, | 971 | GNUNET_REST_ResultProcessor proc, |
1105 | void *proc_cls) | 972 | void *proc_cls) |
1106 | { | 973 | { |
1107 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | 974 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); |
1108 | struct MHD_Response *resp; | 975 | |
1109 | struct GNUNET_HashCode key; | 976 | handle->response_code = 0; |
1110 | char *ego; | ||
1111 | char *name; | ||
1112 | char *type; | ||
1113 | |||
1114 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | 977 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; |
1115 | handle->proc_cls = proc_cls; | 978 | handle->proc_cls = proc_cls; |
1116 | handle->proc = proc; | 979 | handle->proc = proc; |
1117 | handle->rest_handle = rest_handle; | 980 | handle->rest_handle = rest_handle; |
981 | handle->zone_pkey = NULL; | ||
982 | |||
1118 | handle->url = GNUNET_strdup (rest_handle->url); | 983 | handle->url = GNUNET_strdup (rest_handle->url); |
1119 | if (handle->url[strlen (handle->url)-1] == '/') | 984 | if (handle->url[strlen (handle->url)-1] == '/') |
1120 | handle->url[strlen (handle->url)-1] = '\0'; | 985 | handle->url[strlen (handle->url)-1] = '\0'; |
1121 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 986 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); |
1122 | "Connecting...\n"); | ||
1123 | handle->cfg = cfg; | ||
1124 | ego = NULL; | ||
1125 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_EGO, | ||
1126 | strlen (GNUNET_REST_JSONAPI_NAMESTORE_EGO), | ||
1127 | &key); | ||
1128 | if ( GNUNET_YES == | ||
1129 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | ||
1130 | &key) ) | ||
1131 | { | ||
1132 | ego = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, | ||
1133 | &key); | ||
1134 | } | ||
1135 | 987 | ||
1136 | handle->type = GNUNET_GNSRECORD_TYPE_ANY; | 988 | handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, handle); |
1137 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE, | 989 | handle->ns_handle = GNUNET_NAMESTORE_connect (cfg); |
1138 | strlen (GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE), | 990 | handle->timeout_task = |
1139 | &key); | 991 | GNUNET_SCHEDULER_add_delayed (handle->timeout, |
1140 | if ( GNUNET_YES == | 992 | &do_error, |
1141 | GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, | 993 | handle); |
1142 | &key) ) | 994 | |
1143 | { | 995 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); |
1144 | type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, | ||
1145 | &key); | ||
1146 | if (NULL != type) | ||
1147 | handle->type = GNUNET_GNSRECORD_typename_to_number (type); | ||
1148 | } | ||
1149 | name = get_name_from_url (handle->url); | ||
1150 | if (NULL != ego) | ||
1151 | handle->ego_name = GNUNET_strdup (ego); | ||
1152 | if (NULL != name) | ||
1153 | handle->name = GNUNET_strdup (name); | ||
1154 | if (NULL == handle->ego_name) | ||
1155 | { | ||
1156 | handle->identity_handle = GNUNET_IDENTITY_connect (handle->cfg, &id_connect_cb, handle); | ||
1157 | if (NULL == handle->identity_handle) | ||
1158 | { | ||
1159 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Cannot connect to identity service\n")); | ||
1160 | resp = GNUNET_REST_create_response (NULL); | ||
1161 | handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); | ||
1162 | cleanup_handle (handle); | ||
1163 | } | ||
1164 | return; | ||
1165 | } | ||
1166 | handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg, | ||
1167 | handle->ego_name, | ||
1168 | &identity_cb, | ||
1169 | handle); | ||
1170 | handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
1171 | &do_timeout, | ||
1172 | handle); | ||
1173 | } | 996 | } |
1174 | 997 | ||
998 | |||
1175 | /** | 999 | /** |
1176 | * Entry point for the plugin. | 1000 | * Entry point for the plugin. |
1177 | * | 1001 | * |
@@ -1182,9 +1006,9 @@ void * | |||
1182 | libgnunet_plugin_rest_namestore_init (void *cls) | 1006 | libgnunet_plugin_rest_namestore_init (void *cls) |
1183 | { | 1007 | { |
1184 | static struct Plugin plugin; | 1008 | static struct Plugin plugin; |
1185 | cfg = cls; | ||
1186 | struct GNUNET_REST_Plugin *api; | 1009 | struct GNUNET_REST_Plugin *api; |
1187 | 1010 | ||
1011 | cfg = cls; | ||
1188 | if (NULL != plugin.cfg) | 1012 | if (NULL != plugin.cfg) |
1189 | return NULL; /* can only initialize once! */ | 1013 | return NULL; /* can only initialize once! */ |
1190 | memset (&plugin, 0, sizeof (struct Plugin)); | 1014 | memset (&plugin, 0, sizeof (struct Plugin)); |
@@ -1192,7 +1016,7 @@ libgnunet_plugin_rest_namestore_init (void *cls) | |||
1192 | api = GNUNET_new (struct GNUNET_REST_Plugin); | 1016 | api = GNUNET_new (struct GNUNET_REST_Plugin); |
1193 | api->cls = &plugin; | 1017 | api->cls = &plugin; |
1194 | api->name = GNUNET_REST_API_NS_NAMESTORE; | 1018 | api->name = GNUNET_REST_API_NS_NAMESTORE; |
1195 | api->process_request = &rest_identity_process_request; | 1019 | api->process_request = &rest_process_request; |
1196 | GNUNET_asprintf (&allow_methods, | 1020 | GNUNET_asprintf (&allow_methods, |
1197 | "%s, %s, %s, %s, %s", | 1021 | "%s, %s, %s, %s, %s", |
1198 | MHD_HTTP_METHOD_GET, | 1022 | MHD_HTTP_METHOD_GET, |
@@ -1200,7 +1024,8 @@ libgnunet_plugin_rest_namestore_init (void *cls) | |||
1200 | MHD_HTTP_METHOD_PUT, | 1024 | MHD_HTTP_METHOD_PUT, |
1201 | MHD_HTTP_METHOD_DELETE, | 1025 | MHD_HTTP_METHOD_DELETE, |
1202 | MHD_HTTP_METHOD_OPTIONS); | 1026 | MHD_HTTP_METHOD_OPTIONS); |
1203 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1027 | |
1028 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1204 | _("Namestore REST API initialized\n")); | 1029 | _("Namestore REST API initialized\n")); |
1205 | return api; | 1030 | return api; |
1206 | } | 1031 | } |
@@ -1217,13 +1042,14 @@ libgnunet_plugin_rest_namestore_done (void *cls) | |||
1217 | { | 1042 | { |
1218 | struct GNUNET_REST_Plugin *api = cls; | 1043 | struct GNUNET_REST_Plugin *api = cls; |
1219 | struct Plugin *plugin = api->cls; | 1044 | struct Plugin *plugin = api->cls; |
1220 | |||
1221 | plugin->cfg = NULL; | 1045 | plugin->cfg = NULL; |
1222 | GNUNET_free (api); | 1046 | |
1223 | GNUNET_free_non_null (allow_methods); | 1047 | GNUNET_free_non_null (allow_methods); |
1048 | GNUNET_free (api); | ||
1224 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1049 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1225 | "Namestore REST plugin is finished\n"); | 1050 | "Namestore REST plugin is finished\n"); |
1226 | return NULL; | 1051 | return NULL; |
1227 | } | 1052 | } |
1228 | 1053 | ||
1229 | /* end of plugin_rest_namestore.c */ | 1054 | /* end of plugin_rest_namestore.c */ |
1055 | |||
diff --git a/src/namestore/test_plugin_rest_namestore.sh b/src/namestore/test_plugin_rest_namestore.sh new file mode 100755 index 000000000..de02dfafc --- /dev/null +++ b/src/namestore/test_plugin_rest_namestore.sh | |||
@@ -0,0 +1,208 @@ | |||
1 | #!/usr/bin/bash | ||
2 | |||
3 | #First, start gnunet-arm and the rest-service. | ||
4 | #Exit 0 means success, exit 1 means failed test | ||
5 | |||
6 | namestore_link="http://localhost:7776/namestore" | ||
7 | wrong_link="http://localhost:7776/namestoreandmore" | ||
8 | |||
9 | |||
10 | curl_get () { | ||
11 | #$1 is link | ||
12 | #$2 is grep | ||
13 | cache="$(curl -v "$1" 2>&1 | grep "$2")" | ||
14 | #echo $cache | ||
15 | if [ "" == "$cache" ] | ||
16 | then | ||
17 | exit 1 | ||
18 | fi | ||
19 | } | ||
20 | |||
21 | curl_post () { | ||
22 | #$1 is link | ||
23 | #$2 is data | ||
24 | #$3 is grep | ||
25 | cache="$(curl -v -X "POST" "$1" --data "$2" 2>&1 | grep "$3")" | ||
26 | #echo $cache | ||
27 | if [ "" == "$cache" ] | ||
28 | then | ||
29 | exit 1 | ||
30 | fi | ||
31 | } | ||
32 | |||
33 | curl_delete () { | ||
34 | #$1 is link | ||
35 | #$2 is grep | ||
36 | cache="$(curl -v -X "DELETE" "$1" 2>&1 | grep "$2")" | ||
37 | #echo $cache | ||
38 | if [ "" == "$cache" ] | ||
39 | then | ||
40 | exit 1 | ||
41 | fi | ||
42 | } | ||
43 | |||
44 | # curl_put () { | ||
45 | # #$1 is link | ||
46 | # #$2 is data | ||
47 | # #$3 is grep | ||
48 | # cache="$(curl -v -X "PUT" "$1" --data "$2" 2>&1 | grep "$3")" | ||
49 | # #echo $cache | ||
50 | # if [ "" == "$cache" ] | ||
51 | # then | ||
52 | # exit 1 | ||
53 | # fi | ||
54 | # } | ||
55 | |||
56 | #Test subsystem default identity | ||
57 | |||
58 | #Test GET | ||
59 | gnunet-identity -D "test_plugin_rest_namestore" | ||
60 | gnunet-identity -C "test_plugin_rest_namestore" | ||
61 | test="$(gnunet-namestore -D -z "test_plugin_rest_namestore")" | ||
62 | name="test_plugin_rest_namestore" | ||
63 | public="$(gnunet-identity -d | grep "test_plugin_rest_namestore" | awk 'NR==1{print $3}')" | ||
64 | if [ "" == "$test" ] | ||
65 | then | ||
66 | #if no entries for test_plugin_rest_namestore | ||
67 | curl_get "${namestore_link}?name=$name" "error" | ||
68 | curl_get "${namestore_link}?name=" "error" | ||
69 | curl_get "${namestore_link}?name=$public" "error" | ||
70 | |||
71 | curl_get "${namestore_link}?pubkey=$public" "error" | ||
72 | curl_get "${namestore_link}?pubkey=$name" "error" | ||
73 | curl_get "${namestore_link}?pubkey=" "error" | ||
74 | else | ||
75 | #if entries exists (that should not be possible) | ||
76 | curl_get "${namestore_link}" "HTTP/1.1 200 OK" | ||
77 | curl_get "${namestore_link}?name=$name" "HTTP/1.1 200 OK" | ||
78 | curl_get "${namestore_link}?name=" "error" | ||
79 | curl_get "${namestore_link}?name=$public" "error" | ||
80 | |||
81 | curl_get "${namestore_link}?pubkey=$public" "HTTP/1.1 200 OK" | ||
82 | curl_get "${namestore_link}?pubkey=$name" "error" | ||
83 | curl_get "${namestore_link}?pubkey=" "error" | ||
84 | fi | ||
85 | gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG" -t "PKEY" | ||
86 | curl_get "${namestore_link}" "HTTP/1.1 200 OK" | ||
87 | curl_get "${namestore_link}?name=$name" "HTTP/1.1 200 OK" | ||
88 | curl_get "${namestore_link}?name=" "error" | ||
89 | curl_get "${namestore_link}?name=$public" "error" | ||
90 | curl_get "${namestore_link}?pubkey=$public" "HTTP/1.1 200 OK" | ||
91 | curl_get "${namestore_link}?pubkey=$name" "error" | ||
92 | curl_get "${namestore_link}?pubkey=" "error" | ||
93 | gnunet-namestore -z $name -d -n "test_entry" | ||
94 | |||
95 | #Test POST with NAME | ||
96 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
97 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
98 | #value | ||
99 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRGxxx", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" | ||
100 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
101 | curl_post "${namestore_link}?name=$name" '{"value":"", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" | ||
102 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
103 | curl_post "${namestore_link}?name=$name" '{"value_missing":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRGxxx", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" | ||
104 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
105 | #time | ||
106 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"0d","flag":0,"label":"test_entry"}' "HTTP/1.1 204" | ||
107 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
108 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"10000d","flag":0,"label":"test_entry"}' "HTTP/1.1 204" | ||
109 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
110 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"now","flag":0,"label":"test_entry"}' "error" | ||
111 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
112 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"","flag":0,"label":"test_entry"}' "error" | ||
113 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
114 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time_missing":"1d","flag":0,"label":"test_entry"}' "error" | ||
115 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
116 | #flag | ||
117 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
118 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
119 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":2,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
120 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
121 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":8,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
122 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
123 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":16,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
124 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
125 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":-1,"label":"test_entry"}' "error" | ||
126 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
127 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":"Test","label":"test_entry"}' "error" | ||
128 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
129 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":,"label":"test_entry"}' "error" | ||
130 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
131 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag_missing":0,"label":"test_entry"}' "error" | ||
132 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
133 | #label | ||
134 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
135 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 409" | ||
136 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
137 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":""}' "error" | ||
138 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
139 | curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label_missing":"test_entry"}' "error" | ||
140 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
141 | |||
142 | #Test POST with PUBKEY | ||
143 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
144 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
145 | #value | ||
146 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRGxxx", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" | ||
147 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
148 | curl_post "${namestore_link}?pubkey=$public" '{"value":"", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" | ||
149 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
150 | curl_post "${namestore_link}?pubkey=$public" '{"value_missing":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRGxxx", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" | ||
151 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
152 | #time | ||
153 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"0d","flag":0,"label":"test_entry"}' "HTTP/1.1 204" | ||
154 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
155 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"10000d","flag":0,"label":"test_entry"}' "HTTP/1.1 204" | ||
156 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
157 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"now","flag":0,"label":"test_entry"}' "error" | ||
158 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
159 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"","flag":0,"label":"test_entry"}' "error" | ||
160 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
161 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time_missing":"1d","flag":0,"label":"test_entry"}' "error" | ||
162 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
163 | #flag | ||
164 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
165 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
166 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":2,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
167 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
168 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":8,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
169 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
170 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":16,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
171 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
172 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":-1,"label":"test_entry"}' "error" | ||
173 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
174 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":"Test","label":"test_entry"}' "error" | ||
175 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
176 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":,"label":"test_entry"}' "error" | ||
177 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
178 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag_missing":0,"label":"test_entry"}' "error" | ||
179 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
180 | #label | ||
181 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" | ||
182 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 409" | ||
183 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
184 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":""}' "error" | ||
185 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
186 | curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label_missing":"test_entry"}' "error" | ||
187 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
188 | |||
189 | #wrong zone | ||
190 | curl_post "${namestore_link}?name=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" | ||
191 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
192 | curl_post "${namestore_link}?pubkey=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" | ||
193 | gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 | ||
194 | |||
195 | #Test DELETE | ||
196 | gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG" -t "PKEY" | ||
197 | curl_delete "${namestore_link}?label=test_entry&name=$name" "HTTP/1.1 204" | ||
198 | gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG" -t "PKEY" | ||
199 | curl_delete "${namestore_link}?label=test_entry&pubkey=$public" "HTTP/1.1 204" | ||
200 | gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG" -t "PKEY" | ||
201 | curl_delete "${namestore_link}?label=test_entry&pubkey=$name" "HTTP/1.1 404" | ||
202 | |||
203 | |||
204 | #Test default identity | ||
205 | #not possible without defining | ||
206 | |||
207 | exit 0; | ||
208 | |||
diff --git a/src/peerinfo/Makefile.am b/src/peerinfo/Makefile.am index eeb5ee54e..5e96250b1 100644 --- a/src/peerinfo/Makefile.am +++ b/src/peerinfo/Makefile.am | |||
@@ -5,6 +5,8 @@ pkgcfgdir= $(pkgdatadir)/config.d/ | |||
5 | 5 | ||
6 | libexecdir= $(pkglibdir)/libexec/ | 6 | libexecdir= $(pkglibdir)/libexec/ |
7 | 7 | ||
8 | plugindir = $(libdir)/gnunet | ||
9 | |||
8 | pkgcfg_DATA = \ | 10 | pkgcfg_DATA = \ |
9 | peerinfo.conf | 11 | peerinfo.conf |
10 | 12 | ||
@@ -25,6 +27,8 @@ libgnunetpeerinfo_la_SOURCES = \ | |||
25 | libgnunetpeerinfo_la_LIBADD = \ | 27 | libgnunetpeerinfo_la_LIBADD = \ |
26 | $(top_builddir)/src/hello/libgnunethello.la \ | 28 | $(top_builddir)/src/hello/libgnunethello.la \ |
27 | $(top_builddir)/src/util/libgnunetutil.la \ | 29 | $(top_builddir)/src/util/libgnunetutil.la \ |
30 | $(top_builddir)/src/json/libgnunetjson.la \ | ||
31 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
28 | $(XLIB) \ | 32 | $(XLIB) \ |
29 | $(LTLIBINTL) | 33 | $(LTLIBINTL) |
30 | libgnunetpeerinfo_la_LDFLAGS = \ | 34 | libgnunetpeerinfo_la_LDFLAGS = \ |
@@ -35,12 +39,30 @@ libgnunetpeerinfo_la_LDFLAGS = \ | |||
35 | libexec_PROGRAMS = \ | 39 | libexec_PROGRAMS = \ |
36 | gnunet-service-peerinfo | 40 | gnunet-service-peerinfo |
37 | 41 | ||
42 | if HAVE_MHD | ||
43 | if HAVE_JSON | ||
44 | plugin_LTLIBRARIES = \ | ||
45 | libgnunet_plugin_rest_peerinfo.la | ||
46 | endif | ||
47 | endif | ||
48 | |||
38 | gnunet_service_peerinfo_SOURCES = \ | 49 | gnunet_service_peerinfo_SOURCES = \ |
39 | gnunet-service-peerinfo.c | 50 | gnunet-service-peerinfo.c |
40 | gnunet_service_peerinfo_LDADD = \ | 51 | gnunet_service_peerinfo_LDADD = \ |
41 | $(top_builddir)/src/hello/libgnunethello.la \ | 52 | $(top_builddir)/src/hello/libgnunethello.la \ |
42 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 53 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
43 | $(top_builddir)/src/util/libgnunetutil.la | 54 | $(top_builddir)/src/util/libgnunetutil.la |
55 | |||
56 | |||
57 | libgnunet_plugin_rest_peerinfo_la_SOURCES = \ | ||
58 | plugin_rest_peerinfo.c | ||
59 | libgnunet_plugin_rest_peerinfo_la_LIBADD = \ | ||
60 | libgnunetpeerinfo.la \ | ||
61 | $(top_builddir)/src/rest/libgnunetrest.la \ | ||
62 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | ||
63 | $(LTLIBINTL) -ljansson -lmicrohttpd | ||
64 | libgnunet_plugin_rest_peerinfo_la_LDFLAGS = \ | ||
65 | $(GN_PLUGIN_LDFLAGS) | ||
44 | 66 | ||
45 | if HAVE_BENCHMARKS | 67 | if HAVE_BENCHMARKS |
46 | PEERINFO_BENCHMARKS = \ | 68 | PEERINFO_BENCHMARKS = \ |
diff --git a/src/peerinfo/plugin_rest_peerinfo.c b/src/peerinfo/plugin_rest_peerinfo.c new file mode 100644 index 000000000..97c473e36 --- /dev/null +++ b/src/peerinfo/plugin_rest_peerinfo.c | |||
@@ -0,0 +1,801 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2015 GNUnet e.V. | ||
4 | |||
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. | ||
9 | |||
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. | ||
14 | |||
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/>. | ||
17 | */ | ||
18 | /** | ||
19 | * @author Martin Schanzenbach | ||
20 | * @author Philippe Buschmann | ||
21 | * @file peerinfo/plugin_rest_peerinfo.c | ||
22 | * @brief GNUnet Peerinfo REST plugin | ||
23 | */ | ||
24 | |||
25 | #include "platform.h" | ||
26 | #include "gnunet_rest_plugin.h" | ||
27 | #include "gnunet_peerinfo_service.h" | ||
28 | #include "gnunet_transport_service.h" | ||
29 | #include "gnunet_rest_lib.h" | ||
30 | #include "gnunet_json_lib.h" | ||
31 | #include "microhttpd.h" | ||
32 | #include <jansson.h> | ||
33 | |||
34 | #define GNUNET_REST_API_NS_PEERINFO "/peerinfo" | ||
35 | |||
36 | #define GNUNET_REST_API_PEERINFO_PEER "peer" | ||
37 | #define GNUNET_REST_API_PEERINFO_FRIEND "friend" | ||
38 | #define GNUNET_REST_API_PEERINFO_ARRAY "array" | ||
39 | |||
40 | #define GNUNET_REST_ERROR_UNKNOWN "Unkown Error" | ||
41 | |||
42 | /** | ||
43 | * How long until we time out during address lookup? | ||
44 | */ | ||
45 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
46 | /** | ||
47 | * The configuration handle | ||
48 | */ | ||
49 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
50 | |||
51 | /** | ||
52 | * HTTP methods allows for this plugin | ||
53 | */ | ||
54 | static char* allow_methods; | ||
55 | |||
56 | /** | ||
57 | * @brief struct returned by the initialization function of the plugin | ||
58 | */ | ||
59 | struct Plugin | ||
60 | { | ||
61 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
62 | }; | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Record we keep for each printable address. | ||
67 | */ | ||
68 | struct AddressRecord | ||
69 | { | ||
70 | /** | ||
71 | * Current address-to-string context (if active, otherwise NULL). | ||
72 | */ | ||
73 | struct GNUNET_TRANSPORT_AddressToStringContext *atsc; | ||
74 | |||
75 | /** | ||
76 | * Address expiration time | ||
77 | */ | ||
78 | struct GNUNET_TIME_Absolute expiration; | ||
79 | |||
80 | /** | ||
81 | * Printable address. | ||
82 | */ | ||
83 | char *result; | ||
84 | |||
85 | /** | ||
86 | * Print context this address record belongs to. | ||
87 | */ | ||
88 | struct PrintContext *pc; | ||
89 | }; | ||
90 | |||
91 | |||
92 | /** | ||
93 | * Structure we use to collect printable address information. | ||
94 | */ | ||
95 | struct PrintContext | ||
96 | { | ||
97 | |||
98 | /** | ||
99 | * Kept in DLL. | ||
100 | */ | ||
101 | struct PrintContext *next; | ||
102 | |||
103 | /** | ||
104 | * Kept in DLL. | ||
105 | */ | ||
106 | struct PrintContext *prev; | ||
107 | |||
108 | /** | ||
109 | * Identity of the peer. | ||
110 | */ | ||
111 | struct GNUNET_PeerIdentity peer; | ||
112 | |||
113 | /** | ||
114 | * List of printable addresses. | ||
115 | */ | ||
116 | struct AddressRecord *address_list; | ||
117 | |||
118 | /** | ||
119 | * Number of completed addresses in @e address_list. | ||
120 | */ | ||
121 | unsigned int num_addresses; | ||
122 | |||
123 | /** | ||
124 | * Number of addresses allocated in @e address_list. | ||
125 | */ | ||
126 | unsigned int address_list_size; | ||
127 | |||
128 | /** | ||
129 | * Current offset in @e address_list (counted down). | ||
130 | */ | ||
131 | unsigned int off; | ||
132 | |||
133 | /** | ||
134 | * Hello was friend only, #GNUNET_YES or #GNUNET_NO | ||
135 | */ | ||
136 | int friend_only; | ||
137 | |||
138 | /** | ||
139 | * RequestHandle | ||
140 | */ | ||
141 | struct RequestHandle *handle; | ||
142 | |||
143 | }; | ||
144 | |||
145 | /** | ||
146 | * Head of list of print contexts. | ||
147 | */ | ||
148 | static struct PrintContext *pc_head; | ||
149 | |||
150 | /** | ||
151 | * Tail of list of print contexts. | ||
152 | */ | ||
153 | static struct PrintContext *pc_tail; | ||
154 | |||
155 | struct RequestHandle | ||
156 | { | ||
157 | /** | ||
158 | * JSON temporary array | ||
159 | */ | ||
160 | json_t *temp_array; | ||
161 | |||
162 | /** | ||
163 | * Expiration time string | ||
164 | */ | ||
165 | char *expiration_str; | ||
166 | |||
167 | /** | ||
168 | * Address string | ||
169 | */ | ||
170 | const char *address; | ||
171 | |||
172 | /** | ||
173 | * Iteration peer public key | ||
174 | */ | ||
175 | char *pubkey; | ||
176 | |||
177 | /** | ||
178 | * JSON response | ||
179 | */ | ||
180 | json_t *response; | ||
181 | |||
182 | /** | ||
183 | * Handle to PEERINFO it | ||
184 | */ | ||
185 | struct GNUNET_PEERINFO_IteratorContext *list_it; | ||
186 | |||
187 | /** | ||
188 | * Handle to PEERINFO | ||
189 | */ | ||
190 | struct GNUNET_PEERINFO_Handle *peerinfo_handle; | ||
191 | |||
192 | /** | ||
193 | * Rest connection | ||
194 | */ | ||
195 | struct GNUNET_REST_RequestHandle *rest_handle; | ||
196 | |||
197 | /** | ||
198 | * Desired timeout for the lookup (default is no timeout). | ||
199 | */ | ||
200 | struct GNUNET_TIME_Relative timeout; | ||
201 | |||
202 | /** | ||
203 | * ID of a task associated with the resolution process. | ||
204 | */ | ||
205 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
206 | |||
207 | /** | ||
208 | * The plugin result processor | ||
209 | */ | ||
210 | GNUNET_REST_ResultProcessor proc; | ||
211 | |||
212 | /** | ||
213 | * The closure of the result processor | ||
214 | */ | ||
215 | void *proc_cls; | ||
216 | |||
217 | /** | ||
218 | * The url | ||
219 | */ | ||
220 | char *url; | ||
221 | |||
222 | /** | ||
223 | * Error response message | ||
224 | */ | ||
225 | char *emsg; | ||
226 | |||
227 | /** | ||
228 | * Reponse code | ||
229 | */ | ||
230 | int response_code; | ||
231 | |||
232 | }; | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Cleanup lookup handle | ||
237 | * @param handle Handle to clean up | ||
238 | */ | ||
239 | static void | ||
240 | cleanup_handle (void *cls) | ||
241 | { | ||
242 | struct RequestHandle *handle = cls; | ||
243 | |||
244 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
245 | "Cleaning up\n"); | ||
246 | if (NULL != handle->timeout_task) | ||
247 | { | ||
248 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
249 | handle->timeout_task = NULL; | ||
250 | } | ||
251 | if (NULL != handle->url) | ||
252 | GNUNET_free (handle->url); | ||
253 | if (NULL != handle->emsg) | ||
254 | GNUNET_free (handle->emsg); | ||
255 | if (NULL != handle->address) | ||
256 | GNUNET_free ((char*)handle->address); | ||
257 | if (NULL != handle->expiration_str) | ||
258 | GNUNET_free (handle->expiration_str); | ||
259 | if (NULL != handle->pubkey) | ||
260 | GNUNET_free (handle->pubkey); | ||
261 | |||
262 | if (NULL != handle->temp_array) | ||
263 | { | ||
264 | json_decref(handle->temp_array); | ||
265 | handle->temp_array = NULL; | ||
266 | } | ||
267 | if (NULL != handle->response) | ||
268 | { | ||
269 | json_decref(handle->response); | ||
270 | handle->response = NULL; | ||
271 | } | ||
272 | |||
273 | if (NULL != handle->list_it) | ||
274 | { | ||
275 | GNUNET_PEERINFO_iterate_cancel(handle->list_it); | ||
276 | handle->list_it = NULL; | ||
277 | } | ||
278 | if (NULL != handle->peerinfo_handle) | ||
279 | { | ||
280 | GNUNET_PEERINFO_disconnect(handle->peerinfo_handle); | ||
281 | handle->peerinfo_handle = NULL; | ||
282 | } | ||
283 | |||
284 | GNUNET_free (handle); | ||
285 | } | ||
286 | |||
287 | |||
288 | /** | ||
289 | * Task run on errors. Reports an error and cleans up everything. | ||
290 | * | ||
291 | * @param cls the `struct RequestHandle` | ||
292 | */ | ||
293 | static void | ||
294 | do_error (void *cls) | ||
295 | { | ||
296 | struct RequestHandle *handle = cls; | ||
297 | struct MHD_Response *resp; | ||
298 | json_t *json_error = json_object(); | ||
299 | char *response; | ||
300 | |||
301 | if (NULL == handle->emsg) | ||
302 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); | ||
303 | |||
304 | json_object_set_new(json_error,"error", json_string(handle->emsg)); | ||
305 | |||
306 | if (0 == handle->response_code) | ||
307 | handle->response_code = MHD_HTTP_OK; | ||
308 | response = json_dumps (json_error, 0); | ||
309 | resp = GNUNET_REST_create_response (response); | ||
310 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
311 | json_decref(json_error); | ||
312 | GNUNET_free(response); | ||
313 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
314 | } | ||
315 | |||
316 | |||
317 | /** | ||
318 | * Function that assembles our response. | ||
319 | */ | ||
320 | static void | ||
321 | peerinfo_list_finished (void *cls) | ||
322 | { | ||
323 | struct RequestHandle *handle = cls; | ||
324 | char *result_str; | ||
325 | struct MHD_Response *resp; | ||
326 | |||
327 | if (NULL == handle->response) | ||
328 | { | ||
329 | handle->emsg = GNUNET_strdup ("No peers found"); | ||
330 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
331 | return; | ||
332 | } | ||
333 | |||
334 | result_str = json_dumps (handle->response, 0); | ||
335 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
336 | resp = GNUNET_REST_create_response (result_str); | ||
337 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
338 | GNUNET_free_non_null (result_str); | ||
339 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
340 | } | ||
341 | |||
342 | |||
343 | /** | ||
344 | * Iterator callback to go over all addresses and count them. | ||
345 | * | ||
346 | * @param cls `struct PrintContext *` with `off` to increment | ||
347 | * @param address the address | ||
348 | * @param expiration expiration time | ||
349 | * @return #GNUNET_OK to keep the address and continue | ||
350 | */ | ||
351 | static int | ||
352 | count_address (void *cls, | ||
353 | const struct GNUNET_HELLO_Address *address, | ||
354 | struct GNUNET_TIME_Absolute expiration) | ||
355 | { | ||
356 | struct PrintContext *pc = cls; | ||
357 | |||
358 | if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) | ||
359 | { | ||
360 | return GNUNET_OK; /* ignore expired address */ | ||
361 | } | ||
362 | |||
363 | pc->off++; | ||
364 | return GNUNET_OK; | ||
365 | } | ||
366 | |||
367 | |||
368 | /** | ||
369 | * Print the collected address information to the console and free @a pc. | ||
370 | * | ||
371 | * @param pc printing context | ||
372 | */ | ||
373 | static void | ||
374 | dump_pc (struct PrintContext *pc) | ||
375 | { | ||
376 | struct RequestHandle *handle; | ||
377 | unsigned int i; | ||
378 | json_t *response_entry; | ||
379 | json_t *temp_array; | ||
380 | json_t *object; | ||
381 | json_t *address; | ||
382 | json_t *expires; | ||
383 | json_t *friend_and_peer_json; | ||
384 | char *friend_and_peer; | ||
385 | |||
386 | temp_array = json_array(); | ||
387 | response_entry = json_object(); | ||
388 | |||
389 | // printf (_("%sPeer `%s'\n"), | ||
390 | // (GNUNET_YES == pc->friend_only) ? "F2F: " : "", | ||
391 | // GNUNET_i2s_full (&pc->peer)); | ||
392 | for (i = 0; i < pc->num_addresses; i++) | ||
393 | { | ||
394 | if (NULL != pc->address_list[i].result) | ||
395 | { | ||
396 | object = json_object (); | ||
397 | address = json_string(pc->address_list[i].result); | ||
398 | expires = json_string( | ||
399 | GNUNET_STRINGS_absolute_time_to_string (pc->address_list[i].expiration)); | ||
400 | json_object_set (object, "address", address); | ||
401 | json_object_set (object, "expires", expires); | ||
402 | |||
403 | json_decref(address); | ||
404 | json_decref(expires); | ||
405 | |||
406 | json_array_append(temp_array, object); | ||
407 | json_decref(object); | ||
408 | GNUNET_free (pc->address_list[i].result); | ||
409 | } | ||
410 | } | ||
411 | |||
412 | if (0 < json_array_size(temp_array)) | ||
413 | { | ||
414 | GNUNET_asprintf(&friend_and_peer, | ||
415 | "%s%s", | ||
416 | (GNUNET_YES == pc->friend_only) ? "F2F:" : "", | ||
417 | GNUNET_i2s_full (&pc->peer)); | ||
418 | friend_and_peer_json = json_string(friend_and_peer); | ||
419 | json_object_set(response_entry, | ||
420 | GNUNET_REST_API_PEERINFO_PEER, | ||
421 | friend_and_peer_json); | ||
422 | json_object_set(response_entry, | ||
423 | GNUNET_REST_API_PEERINFO_ARRAY, | ||
424 | temp_array); | ||
425 | json_array_append(pc->handle->response, response_entry); | ||
426 | json_decref(friend_and_peer_json); | ||
427 | GNUNET_free(friend_and_peer); | ||
428 | } | ||
429 | |||
430 | json_decref (temp_array); | ||
431 | json_decref(response_entry); | ||
432 | |||
433 | GNUNET_free_non_null (pc->address_list); | ||
434 | GNUNET_CONTAINER_DLL_remove (pc_head, | ||
435 | pc_tail, | ||
436 | pc); | ||
437 | handle = pc->handle; | ||
438 | GNUNET_free (pc); | ||
439 | |||
440 | if ( (NULL == pc_head) && | ||
441 | (NULL == handle->list_it) ) | ||
442 | { | ||
443 | GNUNET_SCHEDULER_add_now (&peerinfo_list_finished, handle); | ||
444 | } | ||
445 | |||
446 | } | ||
447 | |||
448 | |||
449 | /** | ||
450 | * Function to call with a human-readable format of an address | ||
451 | * | ||
452 | * @param cls closure | ||
453 | * @param address NULL on error, otherwise 0-terminated printable UTF-8 string | ||
454 | * @param res result of the address to string conversion: | ||
455 | * if #GNUNET_OK: address was valid (conversion to | ||
456 | * string might still have failed) | ||
457 | * if #GNUNET_SYSERR: address is invalid | ||
458 | */ | ||
459 | static void | ||
460 | process_resolved_address (void *cls, | ||
461 | const char *address, | ||
462 | int res) | ||
463 | { | ||
464 | struct AddressRecord *ar = cls; | ||
465 | struct PrintContext *pc = ar->pc; | ||
466 | |||
467 | if (NULL != address) | ||
468 | { | ||
469 | if (0 != strlen (address)) | ||
470 | { | ||
471 | if (NULL != ar->result) | ||
472 | GNUNET_free (ar->result); | ||
473 | ar->result = GNUNET_strdup (address); | ||
474 | } | ||
475 | return; | ||
476 | } | ||
477 | ar->atsc = NULL; | ||
478 | if (GNUNET_SYSERR == res) | ||
479 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
480 | _("Failure: Cannot convert address to string for peer `%s'\n"), | ||
481 | GNUNET_i2s (&ar->pc->peer)); | ||
482 | pc->num_addresses++; | ||
483 | if (pc->num_addresses == pc->address_list_size) | ||
484 | dump_pc (ar->pc); | ||
485 | } | ||
486 | |||
487 | |||
488 | /** | ||
489 | * Iterator callback to go over all addresses. | ||
490 | * | ||
491 | * @param cls closure | ||
492 | * @param address the address | ||
493 | * @param expiration expiration time | ||
494 | * @return #GNUNET_OK to keep the address and continue | ||
495 | */ | ||
496 | static int | ||
497 | print_address (void *cls, | ||
498 | const struct GNUNET_HELLO_Address *address, | ||
499 | struct GNUNET_TIME_Absolute expiration) | ||
500 | { | ||
501 | struct PrintContext *pc = cls; | ||
502 | struct AddressRecord *ar; | ||
503 | |||
504 | if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) | ||
505 | { | ||
506 | return GNUNET_OK; /* ignore expired address */ | ||
507 | } | ||
508 | |||
509 | GNUNET_assert (0 < pc->off); | ||
510 | ar = &pc->address_list[--pc->off]; | ||
511 | ar->pc = pc; | ||
512 | ar->expiration = expiration; | ||
513 | GNUNET_asprintf (&ar->result, | ||
514 | "%s:%u:%u", | ||
515 | address->transport_name, | ||
516 | address->address_length, | ||
517 | address->local_info); | ||
518 | ar->atsc = GNUNET_TRANSPORT_address_to_string (cfg, | ||
519 | address, | ||
520 | GNUNET_NO, | ||
521 | TIMEOUT, | ||
522 | &process_resolved_address, | ||
523 | ar); | ||
524 | return GNUNET_OK; | ||
525 | } | ||
526 | |||
527 | |||
528 | /** | ||
529 | * Callback that processes each of the known HELLOs for the | ||
530 | * iteration response construction. | ||
531 | * | ||
532 | * @param cls closure, NULL | ||
533 | * @param peer id of the peer, NULL for last call | ||
534 | * @param hello hello message for the peer (can be NULL) | ||
535 | * @param err_msg message | ||
536 | */ | ||
537 | void | ||
538 | peerinfo_list_iteration(void *cls, | ||
539 | const struct GNUNET_PeerIdentity *peer, | ||
540 | const struct GNUNET_HELLO_Message *hello, | ||
541 | const char *err_msg) | ||
542 | { | ||
543 | struct RequestHandle *handle = cls; | ||
544 | struct PrintContext *pc; | ||
545 | int friend_only; | ||
546 | |||
547 | if (NULL == handle->response) | ||
548 | { | ||
549 | handle->response = json_array(); | ||
550 | } | ||
551 | |||
552 | if (NULL == peer) | ||
553 | { | ||
554 | handle->list_it = NULL; | ||
555 | handle->emsg = GNUNET_strdup ("Error in communication with peerinfo"); | ||
556 | if (NULL != err_msg) | ||
557 | { | ||
558 | GNUNET_free(handle->emsg); | ||
559 | handle->emsg = GNUNET_strdup (err_msg); | ||
560 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
561 | } | ||
562 | if (NULL == pc_head) | ||
563 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
564 | return; | ||
565 | } | ||
566 | if (NULL == hello) | ||
567 | return; | ||
568 | |||
569 | friend_only = GNUNET_NO; | ||
570 | if (NULL != hello) | ||
571 | friend_only = GNUNET_HELLO_is_friend_only (hello); | ||
572 | |||
573 | pc = GNUNET_new(struct PrintContext); | ||
574 | GNUNET_CONTAINER_DLL_insert (pc_head, | ||
575 | pc_tail, | ||
576 | pc); | ||
577 | pc->peer = *peer; | ||
578 | pc->friend_only = friend_only; | ||
579 | pc->handle = handle; | ||
580 | GNUNET_HELLO_iterate_addresses (hello, | ||
581 | GNUNET_NO, | ||
582 | &count_address, | ||
583 | pc); | ||
584 | if (0 == pc->off) | ||
585 | { | ||
586 | dump_pc (pc); | ||
587 | return; | ||
588 | } | ||
589 | pc->address_list_size = pc->off; | ||
590 | pc->address_list = GNUNET_malloc( | ||
591 | sizeof(struct AddressRecord) * pc->off); | ||
592 | GNUNET_HELLO_iterate_addresses (hello, | ||
593 | GNUNET_NO, | ||
594 | &print_address, | ||
595 | pc); | ||
596 | } | ||
597 | |||
598 | /** | ||
599 | * Handle peerinfo GET request | ||
600 | * | ||
601 | * @param con_handle the connection handle | ||
602 | * @param url the url | ||
603 | * @param cls the RequestHandle | ||
604 | */ | ||
605 | void | ||
606 | peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle, | ||
607 | const char* url, | ||
608 | void *cls) | ||
609 | { | ||
610 | struct RequestHandle *handle = cls; | ||
611 | struct GNUNET_HashCode key; | ||
612 | const struct GNUNET_PeerIdentity *specific_peer; | ||
613 | GNUNET_PEER_Id peer_id; | ||
614 | int include_friend_only; | ||
615 | char* include_friend_only_str; | ||
616 | |||
617 | include_friend_only = GNUNET_NO; | ||
618 | GNUNET_CRYPTO_hash (GNUNET_REST_API_PEERINFO_FRIEND, | ||
619 | strlen (GNUNET_REST_API_PEERINFO_FRIEND), | ||
620 | &key); | ||
621 | if ( GNUNET_YES | ||
622 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, | ||
623 | &key)) | ||
624 | { | ||
625 | include_friend_only_str = GNUNET_CONTAINER_multihashmap_get ( | ||
626 | con_handle->url_param_map, &key); | ||
627 | if (0 == strcmp(include_friend_only_str, "yes")) | ||
628 | { | ||
629 | include_friend_only = GNUNET_YES; | ||
630 | } | ||
631 | } | ||
632 | |||
633 | specific_peer = NULL; | ||
634 | GNUNET_CRYPTO_hash (GNUNET_REST_API_PEERINFO_PEER, | ||
635 | strlen (GNUNET_REST_API_PEERINFO_PEER), | ||
636 | &key); | ||
637 | if ( GNUNET_YES | ||
638 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, | ||
639 | &key)) | ||
640 | { | ||
641 | peer_id = *(unsigned int*)GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key); | ||
642 | specific_peer = GNUNET_PEER_resolve2(peer_id); | ||
643 | } | ||
644 | |||
645 | handle->list_it = GNUNET_PEERINFO_iterate(handle->peerinfo_handle, | ||
646 | include_friend_only, | ||
647 | specific_peer, | ||
648 | &peerinfo_list_iteration, | ||
649 | handle); | ||
650 | } | ||
651 | |||
652 | |||
653 | |||
654 | /** | ||
655 | * Respond to OPTIONS request | ||
656 | * | ||
657 | * @param con_handle the connection handle | ||
658 | * @param url the url | ||
659 | * @param cls the RequestHandle | ||
660 | */ | ||
661 | static void | ||
662 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
663 | const char* url, | ||
664 | void *cls) | ||
665 | { | ||
666 | struct MHD_Response *resp; | ||
667 | struct RequestHandle *handle = cls; | ||
668 | |||
669 | //independent of path return all options | ||
670 | resp = GNUNET_REST_create_response (NULL); | ||
671 | MHD_add_response_header (resp, | ||
672 | "Access-Control-Allow-Methods", | ||
673 | allow_methods); | ||
674 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
675 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
676 | return; | ||
677 | } | ||
678 | |||
679 | |||
680 | /** | ||
681 | * Handle rest request | ||
682 | * | ||
683 | * @param handle the request handle | ||
684 | */ | ||
685 | static void | ||
686 | init_cont (struct RequestHandle *handle) | ||
687 | { | ||
688 | struct GNUNET_REST_RequestHandlerError err; | ||
689 | static const struct GNUNET_REST_RequestHandler handlers[] = { | ||
690 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_PEERINFO, &peerinfo_get}, | ||
691 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_PEERINFO, &options_cont}, | ||
692 | GNUNET_REST_HANDLER_END | ||
693 | }; | ||
694 | |||
695 | if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, | ||
696 | handlers, | ||
697 | &err, | ||
698 | handle)) | ||
699 | { | ||
700 | handle->response_code = err.error_code; | ||
701 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
702 | } | ||
703 | } | ||
704 | |||
705 | |||
706 | /** | ||
707 | * Function processing the REST call | ||
708 | * | ||
709 | * @param method HTTP method | ||
710 | * @param url URL of the HTTP request | ||
711 | * @param data body of the HTTP request (optional) | ||
712 | * @param data_size length of the body | ||
713 | * @param proc callback function for the result | ||
714 | * @param proc_cls closure for callback function | ||
715 | * @return GNUNET_OK if request accepted | ||
716 | */ | ||
717 | static void | ||
718 | rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, | ||
719 | GNUNET_REST_ResultProcessor proc, | ||
720 | void *proc_cls) | ||
721 | { | ||
722 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | ||
723 | |||
724 | handle->response_code = 0; | ||
725 | handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60); | ||
726 | handle->proc_cls = proc_cls; | ||
727 | handle->proc = proc; | ||
728 | handle->rest_handle = rest_handle; | ||
729 | |||
730 | handle->url = GNUNET_strdup (rest_handle->url); | ||
731 | if (handle->url[strlen (handle->url)-1] == '/') | ||
732 | handle->url[strlen (handle->url)-1] = '\0'; | ||
733 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); | ||
734 | handle->peerinfo_handle = GNUNET_PEERINFO_connect(cfg); | ||
735 | init_cont(handle); | ||
736 | handle->timeout_task = | ||
737 | GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
738 | &do_error, | ||
739 | handle); | ||
740 | |||
741 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); | ||
742 | } | ||
743 | |||
744 | |||
745 | /** | ||
746 | * Entry point for the plugin. | ||
747 | * | ||
748 | * @param cls Config info | ||
749 | * @return NULL on error, otherwise the plugin context | ||
750 | */ | ||
751 | void * | ||
752 | libgnunet_plugin_rest_peerinfo_init (void *cls) | ||
753 | { | ||
754 | static struct Plugin plugin; | ||
755 | struct GNUNET_REST_Plugin *api; | ||
756 | |||
757 | cfg = cls; | ||
758 | if (NULL != plugin.cfg) | ||
759 | return NULL; /* can only initialize once! */ | ||
760 | memset (&plugin, 0, sizeof (struct Plugin)); | ||
761 | plugin.cfg = cfg; | ||
762 | api = GNUNET_new (struct GNUNET_REST_Plugin); | ||
763 | api->cls = &plugin; | ||
764 | api->name = GNUNET_REST_API_NS_PEERINFO; | ||
765 | api->process_request = &rest_process_request; | ||
766 | GNUNET_asprintf (&allow_methods, | ||
767 | "%s, %s, %s, %s, %s", | ||
768 | MHD_HTTP_METHOD_GET, | ||
769 | MHD_HTTP_METHOD_POST, | ||
770 | MHD_HTTP_METHOD_PUT, | ||
771 | MHD_HTTP_METHOD_DELETE, | ||
772 | MHD_HTTP_METHOD_OPTIONS); | ||
773 | |||
774 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
775 | _("Peerinfo REST API initialized\n")); | ||
776 | return api; | ||
777 | } | ||
778 | |||
779 | |||
780 | /** | ||
781 | * Exit point from the plugin. | ||
782 | * | ||
783 | * @param cls the plugin context (as returned by "init") | ||
784 | * @return always NULL | ||
785 | */ | ||
786 | void * | ||
787 | libgnunet_plugin_rest_peerinfo_done (void *cls) | ||
788 | { | ||
789 | struct GNUNET_REST_Plugin *api = cls; | ||
790 | struct Plugin *plugin = api->cls; | ||
791 | plugin->cfg = NULL; | ||
792 | |||
793 | GNUNET_free_non_null (allow_methods); | ||
794 | GNUNET_free (api); | ||
795 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
796 | "Peerinfo REST plugin is finished\n"); | ||
797 | return NULL; | ||
798 | } | ||
799 | |||
800 | /* end of plugin_rest_peerinfo.c */ | ||
801 | |||