summaryrefslogtreecommitdiff
path: root/src/identity/plugin_rest_identity.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2015-03-12 16:40:40 +0000
committerMartin Schanzenbach <mschanzenbach@posteo.de>2015-03-12 16:40:40 +0000
commit59f6e4b0c42486d16a370c3524b78d88ac7fbcbc (patch)
treef52438b2acf50382cf1edfe9194a65634d1baccc /src/identity/plugin_rest_identity.c
parent02a113da7aed6b497c13e955403b83c801ee95b4 (diff)
downloadgnunet-59f6e4b0c42486d16a370c3524b78d88ac7fbcbc.tar.gz
gnunet-59f6e4b0c42486d16a370c3524b78d88ac7fbcbc.zip
-add identity REST, fixes
Diffstat (limited to 'src/identity/plugin_rest_identity.c')
-rw-r--r--src/identity/plugin_rest_identity.c429
1 files changed, 429 insertions, 0 deletions
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
new file mode 100644
index 000000000..622653b09
--- /dev/null
+++ b/src/identity/plugin_rest_identity.c
@@ -0,0 +1,429 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 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 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20/**
21 * @author Martin Schanzenbach
22 * @file namestore/plugin_rest_namestore.c
23 * @brief GNUnet Namestore REST plugin
24 *
25 */
26
27#include "platform.h"
28#include "gnunet_rest_plugin.h"
29#include "gnunet_identity_service.h"
30#include "microhttpd.h"
31#include <jansson.h>
32
33#define API_NAMESPACE "/identity"
34
35#define EGO_NAMESPACE "/identity/ego"
36
37#define SVC_NAMESPACE "/identity/service"
38
39#define ID_REST_STATE_INIT 0
40
41#define ID_REST_STATE_POST_INIT 1
42
43/**
44 * @brief struct returned by the initialization function of the plugin
45 */
46struct Plugin
47{
48 const struct GNUNET_CONFIGURATION_Handle *cfg;
49};
50
51const struct GNUNET_CONFIGURATION_Handle *cfg;
52
53struct EgoEntry
54{
55 /**
56 * DLL
57 */
58 struct EgoEntry *next;
59
60 /**
61 * DLL
62 */
63 struct EgoEntry *prev;
64
65 /**
66 * Ego Identifier
67 */
68 char *identifier;
69
70 /**
71 * Ego Pkey
72 */
73 struct GNUNET_CRYPTO_EcdsaPublicKey pk;
74};
75
76struct RequestHandle
77{
78 /**
79 * Ego list
80 */
81 struct EgoEntry *ego_head;
82
83 /**
84 * Ego list
85 */
86 struct EgoEntry *ego_tail;
87
88 /**
89 * The processing state
90 */
91 int state;
92
93 /**
94 * Handle to GNS service.
95 */
96 struct GNUNET_IDENTITY_Handle *identity_handle;
97
98 /**
99 * Desired timeout for the lookup (default is no timeout).
100 */
101 struct GNUNET_TIME_Relative timeout;
102
103 /**
104 * ID of a task associated with the resolution process.
105 */
106 struct GNUNET_SCHEDULER_Task * timeout_task;
107
108 /**
109 * The root of the received JSON or NULL
110 */
111 json_t *json_root;
112
113 /**
114 * The plugin result processor
115 */
116 GNUNET_REST_ResultProcessor proc;
117
118 /**
119 * The closure of the result processor
120 */
121 void *proc_cls;
122
123 /**
124 * The name to look up
125 */
126 char *name;
127
128 /**
129 * The ego set from REST
130 */
131 char *set_ego;
132
133 /**
134 * The subsystem set from REST
135 */
136 char *set_subsystem;
137
138 /**
139 * The url
140 */
141 const char *url;
142
143 /**
144 * The data from the REST request
145 */
146 const char* data;
147
148 /**
149 * the length of the REST data
150 */
151 size_t data_size;
152
153};
154
155/**
156 * Cleanup lookup handle
157 * @praram handle Handle to clean up
158 */
159void
160cleanup_handle (struct RequestHandle *handle)
161{
162 struct EgoEntry *ego_entry;
163 struct EgoEntry *ego_tmp;
164 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
165 "Cleaning up\n");
166 if (NULL != handle->json_root)
167 json_decref (handle->json_root);
168 if (NULL != handle->name)
169 GNUNET_free (handle->name);
170 if (NULL != handle->timeout_task)
171 GNUNET_SCHEDULER_cancel (handle->timeout_task);
172 if (NULL != handle->identity_handle)
173 GNUNET_IDENTITY_disconnect (handle->identity_handle);
174 if (NULL != handle->set_subsystem)
175 GNUNET_free (handle->set_subsystem);
176 if (NULL != handle->set_ego)
177 GNUNET_free (handle->set_ego);
178 for (ego_entry = handle->ego_head;
179 NULL != ego_entry;)
180 {
181 ego_tmp = ego_entry;
182 ego_entry = ego_entry->next;
183 GNUNET_free (ego_tmp->identifier);
184 GNUNET_free (ego_tmp);
185 }
186 GNUNET_free (handle);
187}
188
189
190/**
191 * Task run on shutdown. Cleans up everything.
192 *
193 * @param cls unused
194 * @param tc scheduler context
195 */
196static void
197do_error (void *cls,
198 const struct GNUNET_SCHEDULER_TaskContext *tc)
199{
200 struct RequestHandle *handle = cls;
201 handle->proc (handle->proc_cls, NULL, 0, GNUNET_SYSERR);
202 cleanup_handle (handle);
203}
204
205
206
207void
208ego_info_response (struct RequestHandle *handle)
209{
210 const char* egoname;
211 char* keystring;
212 char* result_str;
213 struct EgoEntry *ego_entry;
214 json_t *ego_arr;
215 json_t *ego_json;
216
217 if (strlen (EGO_NAMESPACE) > strlen (handle->url))
218 {
219 handle->proc (handle->proc_cls, NULL, 0, GNUNET_SYSERR);
220 cleanup_handle (handle);
221 GNUNET_break (0);
222 return;
223 }
224 ego_arr = json_array ();
225
226 egoname = &handle->url[strlen (EGO_NAMESPACE)];
227
228 if (strlen (EGO_NAMESPACE) + 1 >= strlen (handle->url))
229 {
230 egoname = NULL;
231 }
232
233 //Return all egos
234 for (ego_entry = handle->ego_head;
235 NULL != ego_entry;
236 ego_entry = ego_entry->next)
237 {
238 if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) )
239 continue;
240 ego_json = json_object ();
241 keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&ego_entry->pk);
242 json_object_set_new (ego_json, "identity", json_string (ego_entry->identifier));
243 json_object_set_new (ego_json, "key", json_string (keystring));
244 json_array_append (ego_arr, ego_json);
245 json_decref (ego_json);
246 GNUNET_free (keystring);
247 }
248 result_str = json_dumps (ego_arr, JSON_COMPACT);
249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
250 json_decref (ego_arr);
251 handle->proc (handle->proc_cls, result_str, strlen (result_str), GNUNET_OK);
252 GNUNET_free (result_str);
253 cleanup_handle (handle);
254
255}
256
257
258/**
259 * If listing is enabled, prints information about the egos.
260 *
261 * This function is initially called for all egos and then again
262 * whenever a ego's identifier changes or if it is deleted. At the
263 * end of the initial pass over all egos, the function is once called
264 * with 'NULL' for 'ego'. That does NOT mean that the callback won't
265 * be invoked in the future or that there was an error.
266 *
267 * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
268 * this function is only called ONCE, and 'NULL' being passed in
269 * 'ego' does indicate an error (i.e. name is taken or no default
270 * value is known). If 'ego' is non-NULL and if '*ctx'
271 * is set in those callbacks, the value WILL be passed to a subsequent
272 * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
273 * that one was not NULL).
274 *
275 * When an identity is renamed, this function is called with the
276 * (known) ego but the NEW identifier.
277 *
278 * When an identity is deleted, this function is called with the
279 * (known) ego and "NULL" for the 'identifier'. In this case,
280 * the 'ego' is henceforth invalid (and the 'ctx' should also be
281 * cleaned up).
282 *
283 * @param cls closure
284 * @param ego ego handle
285 * @param ctx context for application to store data for this ego
286 * (during the lifetime of this process, initially NULL)
287 * @param identifier identifier assigned by the user for this ego,
288 * NULL if the user just deleted the ego and it
289 * must thus no longer be used
290*/
291static void
292list_ego (void *cls,
293 struct GNUNET_IDENTITY_Ego *ego,
294 void **ctx,
295 const char *identifier)
296{
297 struct RequestHandle *handle = cls;
298 struct EgoEntry *ego_entry;
299
300 if ( (NULL == handle->set_ego) &&
301 (NULL != ego) &&
302 (NULL != identifier) &&
303 (0 == strcmp (identifier,
304 handle->set_ego)) )
305 {
306 /*handle->set_op = GNUNET_IDENTITY_set (sh,
307 handle->set_subsystem,
308 ego,
309 &set_done,
310 handle);
311 GNUNET_free (handle->set_subsystem);
312 handle->set_subsystem = NULL;
313 GNUNET_free (handle->set_ego); //decref?
314 handle->set_ego = NULL;TODO*/
315 }
316 if ( (NULL == ego) &&
317 (NULL != handle->set_ego) )
318 {
319 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
320 "Could not set ego to `%s' for subsystem `%s', ego not known\n",
321 handle->set_ego,
322 handle->set_subsystem);
323 GNUNET_free (handle->set_subsystem);
324 handle->set_subsystem = NULL;
325 GNUNET_free (handle->set_ego); //decref?
326 handle->set_ego = NULL;
327 }
328 if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
329 {
330 //TODO all read
331 handle->state = ID_REST_STATE_POST_INIT;
332 ego_info_response (handle);
333 return;
334 }
335 if (ID_REST_STATE_INIT == handle->state) {
336 ego_entry = GNUNET_new (struct EgoEntry);
337 GNUNET_IDENTITY_ego_get_public_key (ego, &(ego_entry->pk));
338 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
339 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry);
340 }
341}
342
343/**
344 * Function processing the REST call
345 *
346 * @param method HTTP method
347 * @param url URL of the HTTP request
348 * @param data body of the HTTP request (optional)
349 * @param data_size length of the body
350 * @param proc callback function for the result
351 * @param proc_cls closure for callback function
352 * @return GNUNET_OK if request accepted
353 */
354void
355rest_identity_process_request(const char *method,
356 const char *url,
357 const char *data,
358 size_t data_size,
359 GNUNET_REST_ResultProcessor proc,
360 void *proc_cls)
361{
362 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
363
364
365
366 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
367
368 handle->proc_cls = proc_cls;
369 handle->proc = proc;
370 handle->state = ID_REST_STATE_INIT;
371 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
372 "Connecting...\n");
373 handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, handle);
374 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
375 &do_error, handle);
376 handle->data = data;
377 handle->data_size = data_size;
378 handle->url = url;
379 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
380 "Connected\n");
381}
382
383/**
384 * Entry point for the plugin.
385 *
386 * @param cls Config info
387 * @return NULL on error, otherwise the plugin context
388 */
389void *
390libgnunet_plugin_rest_identity_init (void *cls)
391{
392 static struct Plugin plugin;
393 cfg = cls;
394 struct GNUNET_REST_Plugin *api;
395
396 if (NULL != plugin.cfg)
397 return NULL; /* can only initialize once! */
398 memset (&plugin, 0, sizeof (struct Plugin));
399 plugin.cfg = cfg;
400 api = GNUNET_new (struct GNUNET_REST_Plugin);
401 api->cls = &plugin;
402 api->name = API_NAMESPACE;
403 api->process_request = &rest_identity_process_request;
404 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
405 _("Identity REST API initialized\n"));
406 return api;
407}
408
409
410/**
411 * Exit point from the plugin.
412 *
413 * @param cls the plugin context (as returned by "init")
414 * @return always NULL
415 */
416void *
417libgnunet_plugin_rest_identity_done (void *cls)
418{
419 struct GNUNET_REST_Plugin *api = cls;
420 struct Plugin *plugin = api->cls;
421
422 plugin->cfg = NULL;
423 GNUNET_free (api);
424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
425 "Identity REST plugin is finished\n");
426 return NULL;
427}
428
429/* end of plugin_rest_gns.c */