GNUnet 0.22.2
gns_plugin.c
Go to the documentation of this file.
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 SPDX-License-Identifier: AGPL3.0-or-later
19 */
26#include "platform.h"
27#include "gnunet_rest_plugin.h"
28#include "gnunet_rest_lib.h"
31#include "gnunet_gns_service.h"
32#include "microhttpd.h"
33#include <jansson.h>
34#include "gns_plugin.h"
35
39#define GNUNET_REST_API_NS_GNS "/gns"
40
44#define GNUNET_REST_GNS_PARAM_RECORD_TYPE "record_type"
45
49#define GNUNET_REST_GNS_ERROR_UNKNOWN "Unknown Error"
50
54#define GNUNET_REST_GNS_NOT_FOUND "Record not found"
55
60
64static char *allow_methods;
65
69static struct GNUNET_GNS_Handle *gns;
70
74struct Plugin
75{
76 const struct GNUNET_CONFIGURATION_Handle *cfg;
77};
78
82struct RequestHandle
83{
87 struct RequestHandle *next;
88
92 struct RequestHandle *prev;
93
98
102 char *name;
103
108
113
118
123
128
132 void *proc_cls;
133
137 char *url;
138
142 char *emsg;
143
147 int response_code;
148};
149
154
159
164static void
165cleanup_handle (void *cls)
166{
167 struct RequestHandle *handle = cls;
168
169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
170
171 if (NULL != handle->gns_lookup)
172 {
174 handle->gns_lookup = NULL;
175 }
176 if (NULL != handle->timeout_task)
177 {
178 GNUNET_SCHEDULER_cancel (handle->timeout_task);
179 handle->timeout_task = NULL;
180 }
181 if (NULL != handle->url)
182 GNUNET_free (handle->url);
183 if (NULL != handle->name)
184 GNUNET_free (handle->name);
185 if (NULL != handle->emsg)
186 GNUNET_free (handle->emsg);
187
190 handle);
192}
193
194
200static void
201do_error (void *cls)
202{
203 struct RequestHandle *handle = cls;
204 struct MHD_Response *resp;
205 json_t *json_error = json_object ();
206 char *response;
207
208 if (NULL != handle->timeout_task)
209 GNUNET_SCHEDULER_cancel (handle->timeout_task);
210 handle->timeout_task = NULL;
211 if (NULL == handle->emsg)
213
214 json_object_set_new (json_error, "error", json_string (handle->emsg));
215
216 if (0 == handle->response_code)
217 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
218 response = json_dumps (json_error, 0);
220 MHD_add_response_header (resp, "Content-Type", "application/json");
221 handle->proc (handle->proc_cls, resp, handle->response_code);
222 json_decref (json_error);
225}
226
227
228static void
229do_timeout (void *cls)
230{
231 struct RequestHandle *handle = cls;
232
233 handle->timeout_task = NULL;
234 handle->response_code = MHD_HTTP_REQUEST_TIMEOUT;
236}
237
238
247static void
249 int was_gns,
250 uint32_t rd_count,
251 const struct GNUNET_GNSRECORD_Data *rd)
252{
253 struct RequestHandle *handle = cls;
254 struct MHD_Response *resp;
255 json_t *result_obj;
256 char *result;
257
258 handle->gns_lookup = NULL;
259
260 if (GNUNET_NO == was_gns)
261 {
262 handle->response_code = MHD_HTTP_NOT_FOUND;
265 return;
266 }
267
269 rd_count);
270
271 result = json_dumps (result_obj, 0);
272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
274 GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
275 "Content-Type",
276 "application/json"));
277 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
279 json_decref (result_obj);
281}
282
283
291static void
293 const char *url,
294 void *cls)
295{
296 struct RequestHandle *handle = cls;
297 struct GNUNET_HashCode key;
298 char *record_type;
299 char *name;
300
301 name = NULL;
302 handle->name = NULL;
303 if (strlen (GNUNET_REST_API_NS_GNS) < strlen (handle->url))
304 {
305 name = &handle->url[strlen (GNUNET_REST_API_NS_GNS) + 1];
306 }
307
308 if (NULL == name)
309 {
310 handle->response_code = MHD_HTTP_NOT_FOUND;
313 return;
314 }
315 if (0 >= strlen (name))
316 {
317 handle->response_code = MHD_HTTP_NOT_FOUND;
320 return;
321 }
322 handle->name = GNUNET_strdup (name);
323
324 handle->record_type = UINT32_MAX;
327 &key);
328 if (GNUNET_YES ==
330 {
331 record_type =
333 handle->record_type = GNUNET_GNSRECORD_typename_to_number (record_type);
334 }
335
336 if (UINT32_MAX == handle->record_type)
337 {
338 handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
339 }
340
342 handle->name,
343 handle->record_type,
346 handle);
347}
348
349
357static void
359 const char *url,
360 void *cls)
361{
362 struct MHD_Response *resp;
363 struct RequestHandle *handle = cls;
364
365 // independent of path return all options
366 resp = GNUNET_REST_create_response (NULL);
367 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
368 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
370 return;
371}
372
373
389 void *proc_cls)
390{
391 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
393 static const struct GNUNET_REST_RequestHandler handlers[] =
394 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont },
395 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont },
397
398 handle->response_code = 0;
399 handle->timeout =
401 handle->proc_cls = proc_cls;
402 handle->proc = proc;
403 handle->rest_handle = rest_handle;
404 handle->url = GNUNET_strdup (rest_handle->url);
405 handle->timeout_task =
409 handle);
410 if (handle->url[strlen (handle->url) - 1] == '/')
411 handle->url[strlen (handle->url) - 1] = '\0';
412 if (GNUNET_NO ==
413 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
414 {
416 return GNUNET_NO;
417 }
418
419
420 return GNUNET_YES;
421}
422
423
430void *
432{
433 static struct Plugin plugin;
434 struct GNUNET_REST_Plugin *api;
435
436 gns_cfg = c;
437 memset (&plugin, 0, sizeof(struct Plugin));
438 plugin.cfg = gns_cfg;
439 api = GNUNET_new (struct GNUNET_REST_Plugin);
440 api->cls = &plugin;
443 "%s, %s, %s, %s, %s",
444 MHD_HTTP_METHOD_GET,
445 MHD_HTTP_METHOD_POST,
446 MHD_HTTP_METHOD_PUT,
447 MHD_HTTP_METHOD_DELETE,
448 MHD_HTTP_METHOD_OPTIONS);
450
451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Gns REST API initialized\n"));
452 return api;
453}
454
455
462void
464{
465 struct RequestHandle *request;
466 struct Plugin *plugin;
467
468 while (NULL != (request = requests_head))
470
471 if (NULL != gns)
473
474 plugin = api->cls;
475
476 plugin->cfg = NULL;
477
480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Gns REST plugin is finished\n");
481}
482
483
484/* end of plugin_rest_gns.c */
struct GNUNET_MQ_MessageHandlers handlers[]
Definition: 003.c:1
static struct GNUNET_GNS_Handle * gns
Connection to GNS.
Definition: gns_plugin.c:69
void * REST_gns_init(const struct GNUNET_CONFIGURATION_Handle *c)
Entry point for the plugin.
Definition: gns_plugin.c:431
static void get_gns_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle gns GET request.
Definition: gns_plugin.c:292
static void do_timeout(void *cls)
Definition: gns_plugin.c:229
#define GNUNET_REST_GNS_ERROR_UNKNOWN
Rest API GNS ERROR Unknown Error.
Definition: gns_plugin.c:49
static struct RequestHandle * requests_head
DLL.
Definition: gns_plugin.c:153
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
Definition: gns_plugin.c:358
void REST_gns_done(struct GNUNET_REST_Plugin *api)
Exit point from the plugin.
Definition: gns_plugin.c:463
static void handle_gns_response(void *cls, int was_gns, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd)
Iterator called on obtained result for a GNS lookup.
Definition: gns_plugin.c:248
#define GNUNET_REST_API_NS_GNS
Rest API GNS Namespace.
Definition: gns_plugin.c:39
static char * allow_methods
HTTP methods allows for this plugin.
Definition: gns_plugin.c:64
enum GNUNET_GenericReturnValue REST_gns_process_request(void *plugin, struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
Definition: gns_plugin.c:386
static struct RequestHandle * requests_tail
DLL.
Definition: gns_plugin.c:158
#define GNUNET_REST_GNS_NOT_FOUND
Rest API GNS ERROR Record not found.
Definition: gns_plugin.c:54
#define GNUNET_REST_GNS_PARAM_RECORD_TYPE
Rest API GNS Parameter record_type.
Definition: gns_plugin.c:44
const struct GNUNET_CONFIGURATION_Handle * gns_cfg
The configuration handle.
Definition: gns_plugin.c:59
static void do_error(void *cls)
Task run on errors.
Definition: gns_plugin.c:201
static void cleanup_handle(void *cls)
Cleanup lookup handle.
Definition: gns_plugin.c:165
static struct GNUNET_TESTING_PluginFunctions * plugin
Plugin to dynamically load a test case.
static struct MHD_Response * response
Our canonical response.
struct GNUNET_HashCode key
The key used in the DHT.
static char * name
Name (label) of the records to list.
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static int result
Global testing status.
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:40
static struct GNUNET_VPN_Handle * handle
Handle to vpn service.
Definition: gnunet-vpn.c:35
API to the GNS service.
API that can be used to manipulate JSON GNS record data.
API that can be used to manipulate GNS record data.
API for helper library to parse/create REST.
GNUnet service REST plugin header.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition: gns_api.c:289
struct GNUNET_GNS_LookupWithTldRequest * GNUNET_GNS_lookup_with_tld(struct GNUNET_GNS_Handle *handle, const char *name, uint32_t type, enum GNUNET_GNS_LocalOptions options, GNUNET_GNS_LookupResultProcessor2 proc, void *proc_cls)
Perform an asynchronous lookup operation on the GNS, determining the zone using the TLD of the given ...
Definition: gns_tld_api.c:240
void * GNUNET_GNS_lookup_with_tld_cancel(struct GNUNET_GNS_LookupWithTldRequest *ltr)
Cancel pending lookup request.
Definition: gns_tld_api.c:331
struct GNUNET_GNS_Handle * GNUNET_GNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the connection with the GNS service.
Definition: gns_api.c:267
@ GNUNET_GNS_LO_DEFAULT
Defaults, look in cache, then in DHT.
json_t * GNUNET_GNSRECORD_JSON_from_gnsrecord(const char *rname, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count)
Convert GNS record to JSON.
uint32_t GNUNET_GNSRECORD_typename_to_number(const char *dns_typename)
Convert a type name (e.g.
Definition: gnsrecord.c:192
#define GNUNET_GNSRECORD_TYPE_ANY
Record type indicating any record/'*'.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
#define GNUNET_log(kind,...)
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
int GNUNET_REST_handle_request(struct GNUNET_REST_RequestHandle *conn, const struct GNUNET_REST_RequestHandler *handlers, struct GNUNET_REST_RequestHandlerError *err, void *cls)
Definition: rest.c:64
void(* GNUNET_REST_ResultProcessor)(void *cls, struct MHD_Response *resp, int status)
Iterator called on obtained result for a REST result.
#define GNUNET_REST_HANDLER_END
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:44
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1304
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1277
#define GNUNET_TIME_UNIT_SECONDS
One second.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_multiply(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Multiply relative time by a given factor.
Definition: time.c:486
@ MHD_HTTP_OK
OK [RFC7231, Section 6.3.1].
@ MHD_HTTP_NOT_FOUND
Not Found [RFC7231, Section 6.5.4].
@ MHD_HTTP_REQUEST_TIMEOUT
Request Timeout [RFC7231, Section 6.5.7].
@ MHD_HTTP_INTERNAL_SERVER_ERROR
Internal Server Error [RFC7231, Section 6.6.1].
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
void * cls
Closure for all of the callbacks.
Connection to the GNS service.
Definition: gns_api.h:36
Handle to a lookup request.
Definition: gns_tld_api.c:45
A 512-bit hashcode.
struct returned by the initialization function of the plugin
void * cls
The closure of the plugin.
const char * name
Plugin name.
const char * url
The url as string.
struct GNUNET_CONTAINER_MultiHashMap * url_param_map
Map of url parameters.
void(* proc)(struct GNUNET_REST_RequestHandle *handle, const char *url, void *cls)
Namespace to handle.
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for relative time used by GNUnet, in microseconds.
Handle for a plugin.
Definition: block.c:38
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
The request handle.
Definition: config_plugin.c:47
char * emsg
Error response message.
Definition: gns_plugin.c:142
struct RequestHandle * prev
DLL.
Definition: config_plugin.c:56
int response_code
HTTP response code.
Definition: config_plugin.c:76
struct GNUNET_SCHEDULER_Task * timeout_task
ID of a task associated with the resolution process.
Definition: gns_plugin.c:122
void * proc_cls
The closure of the result processor.
Definition: config_plugin.c:71
int record_type
Record type to look up.
Definition: gns_plugin.c:107
GNUNET_REST_ResultProcessor proc
The plugin result processor.
Definition: config_plugin.c:66
struct RequestHandle * next
DLL.
Definition: config_plugin.c:51
struct GNUNET_REST_RequestHandle * rest_handle
Handle to rest request.
Definition: config_plugin.c:61
struct GNUNET_GNS_LookupWithTldRequest * gns_lookup
Active GNS lookup.
Definition: gns_plugin.c:97
char * name
Name to look up.
Definition: gns_plugin.c:102
char * url
The URL.
Definition: config_plugin.c:81
struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gns_plugin.c:117