diff options
Diffstat (limited to 'src/gns/plugin_rest_gns.c')
-rw-r--r-- | src/gns/plugin_rest_gns.c | 674 |
1 files changed, 221 insertions, 453 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 | |||