GNUnet  0.17.6
plugin_rest_gns.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"
29 #include "gnunet_json_lib.h"
30 #include "gnunet_gnsrecord_lib.h"
32 #include "gnunet_gns_service.h"
33 #include "microhttpd.h"
34 #include <jansson.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 
64 static char *allow_methods;
65 
69 static struct GNUNET_GNS_Handle *gns;
70 
74 struct Plugin
75 {
77 };
78 
83 {
88 
93 
98 
102  char *name;
103 
108 
113 
118 
123 
128 
132  void *proc_cls;
133 
137  char *url;
138 
142  char *emsg;
143 
148 };
149 
154 
159 
164 static void
165 cleanup_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 
200 static void
201 do_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 
228 static void
229 do_timeout (void *cls)
230 {
231  struct RequestHandle *handle = cls;
232 
233  handle->timeout_task = NULL;
234  handle->response_code = MHD_HTTP_REQUEST_TIMEOUT;
235  do_error (handle);
236 }
237 
238 
247 static 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 
268  result_obj = GNUNET_GNSRECORD_JSON_from_gnsrecord (handle->name, rd, rd_count);
269 
270  result = json_dumps (result_obj, 0);
271  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
273  GNUNET_assert (MHD_NO != MHD_add_response_header (resp,
274  "Content-Type",
275  "application/json"));
276  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
278  json_decref (result_obj);
280 }
281 
282 
290 void
292  const char *url,
293  void *cls)
294 {
295  struct RequestHandle *handle = cls;
296  struct GNUNET_HashCode key;
297  char *record_type;
298  char *name;
299 
300  name = NULL;
301  handle->name = NULL;
302  if (strlen (GNUNET_REST_API_NS_GNS) < strlen (handle->url))
303  {
304  name = &handle->url[strlen (GNUNET_REST_API_NS_GNS) + 1];
305  }
306 
307  if (NULL == name)
308  {
309  handle->response_code = MHD_HTTP_NOT_FOUND;
312  return;
313  }
314  if (0 >= strlen (name))
315  {
316  handle->response_code = MHD_HTTP_NOT_FOUND;
319  return;
320  }
321  handle->name = GNUNET_strdup (name);
322 
323  handle->record_type = UINT32_MAX;
326  &key);
327  if (GNUNET_YES ==
329  {
330  record_type =
332  handle->record_type = GNUNET_GNSRECORD_typename_to_number (record_type);
333  }
334 
335  if (UINT32_MAX == handle->record_type)
336  {
337  handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
338  }
339 
340  handle->gns_lookup = GNUNET_GNS_lookup_with_tld (gns,
341  handle->name,
342  handle->record_type,
345  handle);
346 }
347 
348 
356 static void
358  const char *url,
359  void *cls)
360 {
361  struct MHD_Response *resp;
362  struct RequestHandle *handle = cls;
363 
364  // independent of path return all options
365  resp = GNUNET_REST_create_response (NULL);
366  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
367  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
369  return;
370 }
371 
372 
384 static enum GNUNET_GenericReturnValue
387  void *proc_cls)
388 {
389  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
391  static const struct GNUNET_REST_RequestHandler handlers[] =
392  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont },
393  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont },
395 
396  handle->response_code = 0;
397  handle->timeout =
399  handle->proc_cls = proc_cls;
400  handle->proc = proc;
401  handle->rest_handle = rest_handle;
402  handle->url = GNUNET_strdup (rest_handle->url);
403  handle->timeout_task =
407  handle);
408  if (handle->url[strlen (handle->url) - 1] == '/')
409  handle->url[strlen (handle->url) - 1] = '\0';
410  if (GNUNET_NO ==
411  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
412  {
414  return GNUNET_NO;
415  }
416 
417 
418  return GNUNET_YES;
419 }
420 
421 
428 void *
430 {
431  static struct Plugin plugin;
432  struct GNUNET_REST_Plugin *api;
433 
434  cfg = cls;
435  memset (&plugin, 0, sizeof(struct Plugin));
436  plugin.cfg = cfg;
437  api = GNUNET_new (struct GNUNET_REST_Plugin);
438  api->cls = &plugin;
442  "%s, %s, %s, %s, %s",
443  MHD_HTTP_METHOD_GET,
444  MHD_HTTP_METHOD_POST,
445  MHD_HTTP_METHOD_PUT,
446  MHD_HTTP_METHOD_DELETE,
447  MHD_HTTP_METHOD_OPTIONS);
449 
450  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Gns REST API initialized\n"));
451  return api;
452 }
453 
454 
461 void *
463 {
464  struct GNUNET_REST_Plugin *api = cls;
465  struct RequestHandle *request;
466  struct Plugin *plugin;
467 
468  while (NULL != (request = requests_head))
469  do_error (request);
470 
471  if (NULL != gns)
473 
474  plugin = api->cls;
475 
476  plugin->cfg = NULL;
477 
479  GNUNET_free (api);
480  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Gns REST plugin is finished\n");
481  return NULL;
482 }
483 
484 
485 /* end of plugin_rest_gns.c */
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
struct Plugin * plugin
The process handle to the testbed service.
static struct MHD_Response * response
Our canonical response.
struct GNUNET_HashCode key
The key used in the DHT.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
static int result
Global testing status.
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
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.
functions to parse JSON objects into GNUnet objects
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:290
void * GNUNET_GNS_lookup_with_tld_cancel(struct GNUNET_GNS_LookupWithTldRequest *ltr)
Cancel pending lookup request.
Definition: gns_tld_api.c:332
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:241
struct GNUNET_GNS_Handle * GNUNET_GNS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Initialize the connection with the GNS service.
Definition: gns_api.c:268
@ GNUNET_GNS_LO_DEFAULT
Defaults, look in cache, then in DHT.
uint32_t GNUNET_GNSRECORD_typename_to_number(const char *dns_typename)
Convert a type name (e.g "AAAA") to the corresponding number.
Definition: gnsrecord.c:217
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.
#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.
Definition: gnunet_common.h:96
@ GNUNET_YES
@ GNUNET_NO
Definition: gnunet_common.h:98
#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.
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:57
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:77
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 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:1281
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:957
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:1254
#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:483
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
const char * name
static struct GNUNET_GNS_Handle * gns
Connection to GNS.
static void do_timeout(void *cls)
#define GNUNET_REST_GNS_ERROR_UNKNOWN
Rest API GNS ERROR Unknown Error.
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration handle.
static struct RequestHandle * requests_head
DLL.
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
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.
static enum GNUNET_GenericReturnValue rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
void * libgnunet_plugin_rest_gns_done(void *cls)
Exit point from the plugin.
#define GNUNET_REST_API_NS_GNS
Rest API GNS Namespace.
static char * allow_methods
HTTP methods allows for this plugin.
static struct RequestHandle * requests_tail
DLL.
void get_gns_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle gns GET request.
void * libgnunet_plugin_rest_gns_init(void *cls)
Entry point for the plugin.
#define GNUNET_REST_GNS_NOT_FOUND
Rest API GNS ERROR Record not found.
#define GNUNET_REST_GNS_PARAM_RECORD_TYPE
Rest API GNS Parameter record_type.
static void do_error(void *cls)
Task run on errors.
static void cleanup_handle(void *cls)
Cleanup lookup handle.
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
char * name
Plugin name.
void * cls
The closure of the plugin.
enum GNUNET_GenericReturnValue(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
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:135
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.
unsigned int rd_count
Number of records in rd.
char * emsg
Error response message.
struct RequestHandle * prev
DLL.
int response_code
Response code.
struct GNUNET_SCHEDULER_Task * timeout_task
ID of a task associated with the resolution process.
void * proc_cls
The closure of the result processor.
struct GNUNET_GNSRECORD_Data * rd
Records to store.
int record_type
Record type to look up.
GNUNET_REST_ResultProcessor proc
The plugin result processor.
struct RequestHandle * next
DLL.
struct GNUNET_REST_RequestHandle * rest_handle
Rest connection.
struct GNUNET_GNS_LookupWithTldRequest * gns_lookup
Active GNS lookup.
char * name
Name to look up.
char * url
The url.
struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).