GNUnet  0.11.x
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"
31 #include "gnunet_gns_service.h"
32 #include "microhttpd.h"
33 #include <jansson.h>
34 
38 #define GNUNET_REST_API_NS_GNS "/gns"
39 
43 #define GNUNET_REST_GNS_PARAM_RECORD_TYPE "record_type"
44 
48 #define GNUNET_REST_GNS_ERROR_UNKNOWN "Unknown Error"
49 
53 #define GNUNET_REST_GNS_NOT_FOUND "Record not found"
54 
59 
63 static char *allow_methods;
64 
68 static struct GNUNET_GNS_Handle *gns;
69 
73 struct Plugin
74 {
76 };
77 
82 {
87 
92 
97 
101  char *name;
102 
107 
112 
117 
122 
127 
131  void *proc_cls;
132 
136  char *url;
137 
141  char *emsg;
142 
147 };
148 
153 
158 
163 static void
164 cleanup_handle (void *cls)
165 {
166  struct RequestHandle *handle = cls;
167 
168  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
169 
170  if (NULL != handle->gns_lookup)
171  {
173  handle->gns_lookup = NULL;
174  }
175  if (NULL != handle->timeout_task)
176  {
178  handle->timeout_task = NULL;
179  }
180  if (NULL != handle->url)
181  GNUNET_free (handle->url);
182  if (NULL != handle->name)
183  GNUNET_free (handle->name);
184  if (NULL != handle->emsg)
185  GNUNET_free (handle->emsg);
186 
187  GNUNET_CONTAINER_DLL_remove (requests_head,
188  requests_tail,
189  handle);
190  GNUNET_free (handle);
191 }
192 
193 
199 static void
200 do_error (void *cls)
201 {
202  struct RequestHandle *handle = cls;
203  struct MHD_Response *resp;
204  json_t *json_error = json_object ();
205  char *response;
206 
207  if (NULL != handle->timeout_task)
209  handle->timeout_task = NULL;
210  if (NULL == handle->emsg)
212 
213  json_object_set_new (json_error, "error", json_string (handle->emsg));
214 
215  if (0 == handle->response_code)
216  handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
217  response = json_dumps (json_error, 0);
218  resp = GNUNET_REST_create_response (response);
219  MHD_add_response_header (resp, "Content-Type", "application/json");
220  handle->proc (handle->proc_cls, resp, handle->response_code);
221  json_decref (json_error);
222  GNUNET_free (response);
223  cleanup_handle(handle);
224 }
225 
226 
227 static void
228 do_timeout (void *cls)
229 {
230  struct RequestHandle *handle = cls;
231 
232  handle->timeout_task = NULL;
233  handle->response_code = MHD_HTTP_REQUEST_TIMEOUT;
234  do_error (handle);
235 }
236 
237 
246 static void
248  int was_gns,
249  uint32_t rd_count,
250  const struct GNUNET_GNSRECORD_Data *rd)
251 {
252  struct RequestHandle *handle = cls;
253  struct MHD_Response *resp;
254  json_t *result_obj;
255  char *result;
256 
257  handle->gns_lookup = NULL;
258 
259  if (GNUNET_NO == was_gns)
260  {
261  handle->response_code = MHD_HTTP_NOT_FOUND;
264  return;
265  }
266 
267  result_obj = GNUNET_JSON_from_gnsrecord (handle->name, rd, rd_count);
268 
269  result = json_dumps (result_obj, 0);
270  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
271  resp = GNUNET_REST_create_response (result);
272  MHD_add_response_header (resp, "Content-Type", "application/json");
273  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
274  GNUNET_free (result);
275  json_decref (result_obj);
277 }
278 
279 
287 void
289  const char *url,
290  void *cls)
291 {
292  struct RequestHandle *handle = cls;
293  struct GNUNET_HashCode key;
294  char *record_type;
295  char *name;
296 
297  name = NULL;
298  handle->name = NULL;
299  if (strlen (GNUNET_REST_API_NS_GNS) < strlen (handle->url))
300  {
301  name = &handle->url[strlen (GNUNET_REST_API_NS_GNS) + 1];
302  }
303 
304  if (NULL == name)
305  {
306  handle->response_code = MHD_HTTP_NOT_FOUND;
309  return;
310  }
311  if (0 >= strlen (name))
312  {
313  handle->response_code = MHD_HTTP_NOT_FOUND;
316  return;
317  }
318  handle->name = GNUNET_strdup (name);
319 
320  handle->record_type = UINT32_MAX;
323  &key);
324  if (GNUNET_YES ==
326  {
327  record_type =
329  handle->record_type = GNUNET_GNSRECORD_typename_to_number (record_type);
330  }
331 
332  if (UINT32_MAX == handle->record_type)
333  {
335  }
336 
337  handle->gns_lookup = GNUNET_GNS_lookup_with_tld (gns,
338  handle->name,
339  handle->record_type,
342  handle);
343 }
344 
345 
353 static void
355  const char *url,
356  void *cls)
357 {
358  struct MHD_Response *resp;
359  struct RequestHandle *handle = cls;
360 
361  // independent of path return all options
362  resp = GNUNET_REST_create_response (NULL);
363  MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
364  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
366  return;
367 }
368 
369 
381 static enum GNUNET_GenericReturnValue
384  void *proc_cls)
385 {
386  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
388  static const struct GNUNET_REST_RequestHandler handlers[] =
389  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont },
390  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont },
392 
393  handle->response_code = 0;
394  handle->timeout =
396  handle->proc_cls = proc_cls;
397  handle->proc = proc;
398  handle->rest_handle = rest_handle;
399  handle->url = GNUNET_strdup (rest_handle->url);
400  handle->timeout_task =
401  GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
402  GNUNET_CONTAINER_DLL_insert (requests_head,
403  requests_tail,
404  handle);
405  if (handle->url[strlen (handle->url) - 1] == '/')
406  handle->url[strlen (handle->url) - 1] = '\0';
407  if (GNUNET_NO ==
408  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
409  {
410  cleanup_handle (handle);
411  return GNUNET_NO;
412  }
413 
414 
415  return GNUNET_YES;
416 }
417 
418 
425 void *
427 {
428  static struct Plugin plugin;
429  struct GNUNET_REST_Plugin *api;
430 
431  cfg = cls;
432  memset (&plugin, 0, sizeof(struct Plugin));
433  plugin.cfg = cfg;
434  api = GNUNET_new (struct GNUNET_REST_Plugin);
435  api->cls = &plugin;
439  "%s, %s, %s, %s, %s",
440  MHD_HTTP_METHOD_GET,
441  MHD_HTTP_METHOD_POST,
442  MHD_HTTP_METHOD_PUT,
443  MHD_HTTP_METHOD_DELETE,
444  MHD_HTTP_METHOD_OPTIONS);
445  gns = GNUNET_GNS_connect (cfg);
446 
447  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Gns REST API initialized\n"));
448  return api;
449 }
450 
451 
458 void *
460 {
461  struct GNUNET_REST_Plugin *api = cls;
462  struct RequestHandle *request;
463  struct Plugin *plugin;
464 
465  while (NULL != (request = requests_head))
466  do_error (request);
467 
468  if (NULL != gns)
469  GNUNET_GNS_disconnect (gns);
470 
471  plugin = api->cls;
472 
473  plugin->cfg = NULL;
474 
476  GNUNET_free (api);
477  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Gns REST plugin is finished\n");
478  return NULL;
479 }
480 
481 
482 /* end of plugin_rest_gns.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
Connection to the GNS service.
Definition: gns_api.h:35
char * name
Plugin name.
void(* GNUNET_REST_ResultProcessor)(void *cls, struct MHD_Response *resp, int status)
Iterator called on obtained result for a REST result.
int record_type
Record type to look up.
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
void * libgnunet_plugin_rest_gns_init(void *cls)
Entry point for the plugin.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
functions to parse JSON objects into GNUnet objects
void * cls
The closure of the plugin.
void * GNUNET_GNS_lookup_with_tld_cancel(struct GNUNET_GNS_LookupWithTldRequest *ltr)
Cancel pending lookup request.
Definition: gns_tld_api.c:329
GNUNET_REST_ResultProcessor proc
The plugin result processor.
uint32_t GNUNET_GNSRECORD_typename_to_number(const char *dns_typename)
Convert a type name (i.e.
Definition: gnsrecord.c:220
#define GNUNET_GNSRECORD_TYPE_ANY
Record type indicating any record/&#39;*&#39;.
#define GNUNET_TIME_UNIT_SECONDS
One second.
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
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.
void * libgnunet_plugin_rest_gns_done(void *cls)
Exit point from the plugin.
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 returned by the initialization function of the plugin
GNUNET_GenericReturnValue
Named constants for return values.
Definition: gnunet_common.h:83
void get_gns_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle gns GET request.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
void(* proc)(struct GNUNET_REST_RequestHandle *handle, const char *url, void *cls)
Namespace to handle.
int 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)...
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
void * proc_cls
The closure of the result processor.
#define GNUNET_REST_HANDLER_END
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
The request handle.
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 _(String)
GNU gettext support macro.
Definition: platform.h:184
#define GNUNET_REST_GNS_NOT_FOUND
Rest API GNS ERROR Record not found.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
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:1269
char * name
Name to look up.
#define GNUNET_REST_GNS_PARAM_RECORD_TYPE
Rest API GNS Parameter record_type.
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
char * emsg
Error response message.
struct GNUNET_CONTAINER_MultiHashMap * url_param_map
Map of url parameters.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:48
const char * url
The url as string.
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:1296
char * name
Plugin name.
void GNUNET_GNS_disconnect(struct GNUNET_GNS_Handle *handle)
Shutdown connection with the GNS service.
Definition: gns_api.c:290
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration handle.
struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
unsigned int rd_count
Number of records in rd.
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
static int result
Global testing status.
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:442
static void cleanup_handle(void *cls)
Cleanup lookup handle.
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
static struct GNUNET_GNS_Handle * gns
Connection to GNS.
json_t * GNUNET_JSON_from_gnsrecord(const char *rname, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count)
Convert Gns record to JSON.
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
A 512-bit hashcode.
struct GNUNET_REST_RequestHandle * rest_handle
Rest connection.
int response_code
Response code.
static char * plugin
Solver plugin name as string.
struct RequestHandle * next
DLL.
static void do_error(void *cls)
Task run on errors.
struct RequestHandle * prev
DLL.
struct GNUNET_GNS_LookupWithTldRequest * gns_lookup
Active GNS lookup.
configuration data
Definition: configuration.c:84
Handle for a plugin.
Definition: block.c:37
struct GNUNET_SCHEDULER_Task * timeout_task
ID of a task associated with the resolution process.
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:57
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:134
#define GNUNET_REST_GNS_ERROR_UNKNOWN
Rest API GNS ERROR Unknown Error.
static struct MHD_Response * response
Our canonical response.
struct GNUNET_GNSRECORD_Data * rd
Records to store.
Defaults, look in cache, then in DHT.
static struct RequestHandle * requests_head
DLL.
enum GNUNET_GenericReturnValue(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
Handle to a lookup request.
Definition: gns_tld_api.c:44
#define GNUNET_REST_API_NS_GNS
Rest API GNS Namespace.
static struct RequestHandle * requests_tail
DLL.
static void do_timeout(void *cls)
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
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.
char * url
The url.
static char * allow_methods
HTTP methods allows for this plugin.