diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-08-11 10:40:26 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-08-11 10:41:42 +0200 |
commit | 97e72521285a2ff2189334cb43d0a8f385d73e4a (patch) | |
tree | e3fed58505787f1de6af428230ad768509a5611d /src/peerinfo-tool | |
parent | ba30221f3588d75b3073cd737fbbf6d0c80e5906 (diff) | |
download | gnunet-97e72521285a2ff2189334cb43d0a8f385d73e4a.tar.gz gnunet-97e72521285a2ff2189334cb43d0a8f385d73e4a.zip |
fix build order: peerinfo logic depending on transport must be in peerinfo-tool
Diffstat (limited to 'src/peerinfo-tool')
-rw-r--r-- | src/peerinfo-tool/Makefile.am | 23 | ||||
-rw-r--r-- | src/peerinfo-tool/plugin_rest_peerinfo.c | 801 |
2 files changed, 824 insertions, 0 deletions
diff --git a/src/peerinfo-tool/Makefile.am b/src/peerinfo-tool/Makefile.am index 648957a05..6f9a3360c 100644 --- a/src/peerinfo-tool/Makefile.am +++ b/src/peerinfo-tool/Makefile.am | |||
@@ -10,6 +10,8 @@ if USE_COVERAGE | |||
10 | XLIB = -lgcov | 10 | XLIB = -lgcov |
11 | endif | 11 | endif |
12 | 12 | ||
13 | plugindir = $(libdir)/gnunet | ||
14 | |||
13 | bin_PROGRAMS = \ | 15 | bin_PROGRAMS = \ |
14 | gnunet-peerinfo | 16 | gnunet-peerinfo |
15 | 17 | ||
@@ -24,6 +26,27 @@ gnunet_peerinfo_LDADD = \ | |||
24 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 26 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
25 | $(top_builddir)/src/util/libgnunetutil.la | 27 | $(top_builddir)/src/util/libgnunetutil.la |
26 | 28 | ||
29 | if HAVE_MHD | ||
30 | if HAVE_JSON | ||
31 | plugin_LTLIBRARIES = \ | ||
32 | libgnunet_plugin_rest_peerinfo.la | ||
33 | endif | ||
34 | endif | ||
35 | |||
36 | |||
37 | libgnunet_plugin_rest_peerinfo_la_SOURCES = \ | ||
38 | plugin_rest_peerinfo.c | ||
39 | libgnunet_plugin_rest_peerinfo_la_LIBADD = \ | ||
40 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ | ||
41 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
42 | $(top_builddir)/src/rest/libgnunetrest.la \ | ||
43 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | ||
44 | $(LTLIBINTL) -ljansson -lmicrohttpd | ||
45 | libgnunet_plugin_rest_peerinfo_la_LDFLAGS = \ | ||
46 | $(GN_PLUGIN_LDFLAGS) | ||
47 | |||
48 | |||
49 | |||
27 | if HAVE_PYTHON | 50 | if HAVE_PYTHON |
28 | check_SCRIPTS = \ | 51 | check_SCRIPTS = \ |
29 | test_gnunet_peerinfo.py | 52 | test_gnunet_peerinfo.py |
diff --git a/src/peerinfo-tool/plugin_rest_peerinfo.c b/src/peerinfo-tool/plugin_rest_peerinfo.c new file mode 100644 index 000000000..97c473e36 --- /dev/null +++ b/src/peerinfo-tool/plugin_rest_peerinfo.c | |||
@@ -0,0 +1,801 @@ | |||
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 | /** | ||
19 | * @author Martin Schanzenbach | ||
20 | * @author Philippe Buschmann | ||
21 | * @file peerinfo/plugin_rest_peerinfo.c | ||
22 | * @brief GNUnet Peerinfo REST plugin | ||
23 | */ | ||
24 | |||
25 | #include "platform.h" | ||
26 | #include "gnunet_rest_plugin.h" | ||
27 | #include "gnunet_peerinfo_service.h" | ||
28 | #include "gnunet_transport_service.h" | ||
29 | #include "gnunet_rest_lib.h" | ||
30 | #include "gnunet_json_lib.h" | ||
31 | #include "microhttpd.h" | ||
32 | #include <jansson.h> | ||
33 | |||
34 | #define GNUNET_REST_API_NS_PEERINFO "/peerinfo" | ||
35 | |||
36 | #define GNUNET_REST_API_PEERINFO_PEER "peer" | ||
37 | #define GNUNET_REST_API_PEERINFO_FRIEND "friend" | ||
38 | #define GNUNET_REST_API_PEERINFO_ARRAY "array" | ||
39 | |||
40 | #define GNUNET_REST_ERROR_UNKNOWN "Unkown Error" | ||
41 | |||
42 | /** | ||
43 | * How long until we time out during address lookup? | ||
44 | */ | ||
45 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
46 | /** | ||
47 | * The configuration handle | ||
48 | */ | ||
49 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
50 | |||
51 | /** | ||
52 | * HTTP methods allows for this plugin | ||
53 | */ | ||
54 | static char* allow_methods; | ||
55 | |||
56 | /** | ||
57 | * @brief struct returned by the initialization function of the plugin | ||
58 | */ | ||
59 | struct Plugin | ||
60 | { | ||
61 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
62 | }; | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Record we keep for each printable address. | ||
67 | */ | ||
68 | struct AddressRecord | ||
69 | { | ||
70 | /** | ||
71 | * Current address-to-string context (if active, otherwise NULL). | ||
72 | */ | ||
73 | struct GNUNET_TRANSPORT_AddressToStringContext *atsc; | ||
74 | |||
75 | /** | ||
76 | * Address expiration time | ||
77 | */ | ||
78 | struct GNUNET_TIME_Absolute expiration; | ||
79 | |||
80 | /** | ||
81 | * Printable address. | ||
82 | */ | ||
83 | char *result; | ||
84 | |||
85 | /** | ||
86 | * Print context this address record belongs to. | ||
87 | */ | ||
88 | struct PrintContext *pc; | ||
89 | }; | ||
90 | |||
91 | |||
92 | /** | ||
93 | * Structure we use to collect printable address information. | ||
94 | */ | ||
95 | struct PrintContext | ||
96 | { | ||
97 | |||
98 | /** | ||
99 | * Kept in DLL. | ||
100 | */ | ||
101 | struct PrintContext *next; | ||
102 | |||
103 | /** | ||
104 | * Kept in DLL. | ||
105 | */ | ||
106 | struct PrintContext *prev; | ||
107 | |||
108 | /** | ||
109 | * Identity of the peer. | ||
110 | */ | ||
111 | struct GNUNET_PeerIdentity peer; | ||
112 | |||
113 | /** | ||
114 | * List of printable addresses. | ||
115 | */ | ||
116 | struct AddressRecord *address_list; | ||
117 | |||
118 | /** | ||
119 | * Number of completed addresses in @e address_list. | ||
120 | */ | ||
121 | unsigned int num_addresses; | ||
122 | |||
123 | /** | ||
124 | * Number of addresses allocated in @e address_list. | ||
125 | */ | ||
126 | unsigned int address_list_size; | ||
127 | |||
128 | /** | ||
129 | * Current offset in @e address_list (counted down). | ||
130 | */ | ||
131 | unsigned int off; | ||
132 | |||
133 | /** | ||
134 | * Hello was friend only, #GNUNET_YES or #GNUNET_NO | ||
135 | */ | ||
136 | int friend_only; | ||
137 | |||
138 | /** | ||
139 | * RequestHandle | ||
140 | */ | ||
141 | struct RequestHandle *handle; | ||
142 | |||
143 | }; | ||
144 | |||
145 | /** | ||
146 | * Head of list of print contexts. | ||
147 | */ | ||
148 | static struct PrintContext *pc_head; | ||
149 | |||
150 | /** | ||
151 | * Tail of list of print contexts. | ||
152 | */ | ||
153 | static struct PrintContext *pc_tail; | ||
154 | |||
155 | struct RequestHandle | ||
156 | { | ||
157 | /** | ||
158 | * JSON temporary array | ||
159 | */ | ||
160 | json_t *temp_array; | ||
161 | |||
162 | /** | ||
163 | * Expiration time string | ||
164 | */ | ||
165 | char *expiration_str; | ||
166 | |||
167 | /** | ||
168 | * Address string | ||
169 | */ | ||
170 | const char *address; | ||
171 | |||
172 | /** | ||
173 | * Iteration peer public key | ||
174 | */ | ||
175 | char *pubkey; | ||
176 | |||
177 | /** | ||
178 | * JSON response | ||
179 | */ | ||
180 | json_t *response; | ||
181 | |||
182 | /** | ||
183 | * Handle to PEERINFO it | ||
184 | */ | ||
185 | struct GNUNET_PEERINFO_IteratorContext *list_it; | ||
186 | |||
187 | /** | ||
188 | * Handle to PEERINFO | ||
189 | */ | ||
190 | struct GNUNET_PEERINFO_Handle *peerinfo_handle; | ||
191 | |||
192 | /** | ||
193 | * Rest connection | ||
194 | */ | ||
195 | struct GNUNET_REST_RequestHandle *rest_handle; | ||
196 | |||
197 | /** | ||
198 | * Desired timeout for the lookup (default is no timeout). | ||
199 | */ | ||
200 | struct GNUNET_TIME_Relative timeout; | ||
201 | |||
202 | /** | ||
203 | * ID of a task associated with the resolution process. | ||
204 | */ | ||
205 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
206 | |||
207 | /** | ||
208 | * The plugin result processor | ||
209 | */ | ||
210 | GNUNET_REST_ResultProcessor proc; | ||
211 | |||
212 | /** | ||
213 | * The closure of the result processor | ||
214 | */ | ||
215 | void *proc_cls; | ||
216 | |||
217 | /** | ||
218 | * The url | ||
219 | */ | ||
220 | char *url; | ||
221 | |||
222 | /** | ||
223 | * Error response message | ||
224 | */ | ||
225 | char *emsg; | ||
226 | |||
227 | /** | ||
228 | * Reponse code | ||
229 | */ | ||
230 | int response_code; | ||
231 | |||
232 | }; | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Cleanup lookup handle | ||
237 | * @param handle Handle to clean up | ||
238 | */ | ||
239 | static void | ||
240 | cleanup_handle (void *cls) | ||
241 | { | ||
242 | struct RequestHandle *handle = cls; | ||
243 | |||
244 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
245 | "Cleaning up\n"); | ||
246 | if (NULL != handle->timeout_task) | ||
247 | { | ||
248 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
249 | handle->timeout_task = NULL; | ||
250 | } | ||
251 | if (NULL != handle->url) | ||
252 | GNUNET_free (handle->url); | ||
253 | if (NULL != handle->emsg) | ||
254 | GNUNET_free (handle->emsg); | ||
255 | if (NULL != handle->address) | ||
256 | GNUNET_free ((char*)handle->address); | ||
257 | if (NULL != handle->expiration_str) | ||
258 | GNUNET_free (handle->expiration_str); | ||
259 | if (NULL != handle->pubkey) | ||
260 | GNUNET_free (handle->pubkey); | ||
261 | |||
262 | if (NULL != handle->temp_array) | ||
263 | { | ||
264 | json_decref(handle->temp_array); | ||
265 | handle->temp_array = NULL; | ||
266 | } | ||
267 | if (NULL != handle->response) | ||
268 | { | ||
269 | json_decref(handle->response); | ||
270 | handle->response = NULL; | ||
271 | } | ||
272 | |||
273 | if (NULL != handle->list_it) | ||
274 | { | ||
275 | GNUNET_PEERINFO_iterate_cancel(handle->list_it); | ||
276 | handle->list_it = NULL; | ||
277 | } | ||
278 | if (NULL != handle->peerinfo_handle) | ||
279 | { | ||
280 | GNUNET_PEERINFO_disconnect(handle->peerinfo_handle); | ||
281 | handle->peerinfo_handle = NULL; | ||
282 | } | ||
283 | |||
284 | GNUNET_free (handle); | ||
285 | } | ||
286 | |||
287 | |||
288 | /** | ||
289 | * Task run on errors. Reports an error and cleans up everything. | ||
290 | * | ||
291 | * @param cls the `struct RequestHandle` | ||
292 | */ | ||
293 | static void | ||
294 | do_error (void *cls) | ||
295 | { | ||
296 | struct RequestHandle *handle = cls; | ||
297 | struct MHD_Response *resp; | ||
298 | json_t *json_error = json_object(); | ||
299 | char *response; | ||
300 | |||
301 | if (NULL == handle->emsg) | ||
302 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); | ||
303 | |||
304 | json_object_set_new(json_error,"error", json_string(handle->emsg)); | ||
305 | |||
306 | if (0 == handle->response_code) | ||
307 | handle->response_code = MHD_HTTP_OK; | ||
308 | response = json_dumps (json_error, 0); | ||
309 | resp = GNUNET_REST_create_response (response); | ||
310 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
311 | json_decref(json_error); | ||
312 | GNUNET_free(response); | ||
313 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
314 | } | ||
315 | |||
316 | |||
317 | /** | ||
318 | * Function that assembles our response. | ||
319 | */ | ||
320 | static void | ||
321 | peerinfo_list_finished (void *cls) | ||
322 | { | ||
323 | struct RequestHandle *handle = cls; | ||
324 | char *result_str; | ||
325 | struct MHD_Response *resp; | ||
326 | |||
327 | if (NULL == handle->response) | ||
328 | { | ||
329 | handle->emsg = GNUNET_strdup ("No peers found"); | ||
330 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
331 | return; | ||
332 | } | ||
333 | |||
334 | result_str = json_dumps (handle->response, 0); | ||
335 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
336 | resp = GNUNET_REST_create_response (result_str); | ||
337 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
338 | GNUNET_free_non_null (result_str); | ||
339 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
340 | } | ||
341 | |||
342 | |||
343 | /** | ||
344 | * Iterator callback to go over all addresses and count them. | ||
345 | * | ||
346 | * @param cls `struct PrintContext *` with `off` to increment | ||
347 | * @param address the address | ||
348 | * @param expiration expiration time | ||
349 | * @return #GNUNET_OK to keep the address and continue | ||
350 | */ | ||
351 | static int | ||
352 | count_address (void *cls, | ||
353 | const struct GNUNET_HELLO_Address *address, | ||
354 | struct GNUNET_TIME_Absolute expiration) | ||
355 | { | ||
356 | struct PrintContext *pc = cls; | ||
357 | |||
358 | if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) | ||
359 | { | ||
360 | return GNUNET_OK; /* ignore expired address */ | ||
361 | } | ||
362 | |||
363 | pc->off++; | ||
364 | return GNUNET_OK; | ||
365 | } | ||
366 | |||
367 | |||
368 | /** | ||
369 | * Print the collected address information to the console and free @a pc. | ||
370 | * | ||
371 | * @param pc printing context | ||
372 | */ | ||
373 | static void | ||
374 | dump_pc (struct PrintContext *pc) | ||
375 | { | ||
376 | struct RequestHandle *handle; | ||
377 | unsigned int i; | ||
378 | json_t *response_entry; | ||
379 | json_t *temp_array; | ||
380 | json_t *object; | ||
381 | json_t *address; | ||
382 | json_t *expires; | ||
383 | json_t *friend_and_peer_json; | ||
384 | char *friend_and_peer; | ||
385 | |||
386 | temp_array = json_array(); | ||
387 | response_entry = json_object(); | ||
388 | |||
389 | // printf (_("%sPeer `%s'\n"), | ||
390 | // (GNUNET_YES == pc->friend_only) ? "F2F: " : "", | ||
391 | // GNUNET_i2s_full (&pc->peer)); | ||
392 | for (i = 0; i < pc->num_addresses; i++) | ||
393 | { | ||
394 | if (NULL != pc->address_list[i].result) | ||
395 | { | ||
396 | object = json_object (); | ||
397 | address = json_string(pc->address_list[i].result); | ||
398 | expires = json_string( | ||
399 | GNUNET_STRINGS_absolute_time_to_string (pc->address_list[i].expiration)); | ||
400 | json_object_set (object, "address", address); | ||
401 | json_object_set (object, "expires", expires); | ||
402 | |||
403 | json_decref(address); | ||
404 | json_decref(expires); | ||
405 | |||
406 | json_array_append(temp_array, object); | ||
407 | json_decref(object); | ||
408 | GNUNET_free (pc->address_list[i].result); | ||
409 | } | ||
410 | } | ||
411 | |||
412 | if (0 < json_array_size(temp_array)) | ||
413 | { | ||
414 | GNUNET_asprintf(&friend_and_peer, | ||
415 | "%s%s", | ||
416 | (GNUNET_YES == pc->friend_only) ? "F2F:" : "", | ||
417 | GNUNET_i2s_full (&pc->peer)); | ||
418 | friend_and_peer_json = json_string(friend_and_peer); | ||
419 | json_object_set(response_entry, | ||
420 | GNUNET_REST_API_PEERINFO_PEER, | ||
421 | friend_and_peer_json); | ||
422 | json_object_set(response_entry, | ||
423 | GNUNET_REST_API_PEERINFO_ARRAY, | ||
424 | temp_array); | ||
425 | json_array_append(pc->handle->response, response_entry); | ||
426 | json_decref(friend_and_peer_json); | ||
427 | GNUNET_free(friend_and_peer); | ||
428 | } | ||
429 | |||
430 | json_decref (temp_array); | ||
431 | json_decref(response_entry); | ||
432 | |||
433 | GNUNET_free_non_null (pc->address_list); | ||
434 | GNUNET_CONTAINER_DLL_remove (pc_head, | ||
435 | pc_tail, | ||
436 | pc); | ||
437 | handle = pc->handle; | ||
438 | GNUNET_free (pc); | ||
439 | |||
440 | if ( (NULL == pc_head) && | ||
441 | (NULL == handle->list_it) ) | ||
442 | { | ||
443 | GNUNET_SCHEDULER_add_now (&peerinfo_list_finished, handle); | ||
444 | } | ||
445 | |||
446 | } | ||
447 | |||
448 | |||
449 | /** | ||
450 | * Function to call with a human-readable format of an address | ||
451 | * | ||
452 | * @param cls closure | ||
453 | * @param address NULL on error, otherwise 0-terminated printable UTF-8 string | ||
454 | * @param res result of the address to string conversion: | ||
455 | * if #GNUNET_OK: address was valid (conversion to | ||
456 | * string might still have failed) | ||
457 | * if #GNUNET_SYSERR: address is invalid | ||
458 | */ | ||
459 | static void | ||
460 | process_resolved_address (void *cls, | ||
461 | const char *address, | ||
462 | int res) | ||
463 | { | ||
464 | struct AddressRecord *ar = cls; | ||
465 | struct PrintContext *pc = ar->pc; | ||
466 | |||
467 | if (NULL != address) | ||
468 | { | ||
469 | if (0 != strlen (address)) | ||
470 | { | ||
471 | if (NULL != ar->result) | ||
472 | GNUNET_free (ar->result); | ||
473 | ar->result = GNUNET_strdup (address); | ||
474 | } | ||
475 | return; | ||
476 | } | ||
477 | ar->atsc = NULL; | ||
478 | if (GNUNET_SYSERR == res) | ||
479 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
480 | _("Failure: Cannot convert address to string for peer `%s'\n"), | ||
481 | GNUNET_i2s (&ar->pc->peer)); | ||
482 | pc->num_addresses++; | ||
483 | if (pc->num_addresses == pc->address_list_size) | ||
484 | dump_pc (ar->pc); | ||
485 | } | ||
486 | |||
487 | |||
488 | /** | ||
489 | * Iterator callback to go over all addresses. | ||
490 | * | ||
491 | * @param cls closure | ||
492 | * @param address the address | ||
493 | * @param expiration expiration time | ||
494 | * @return #GNUNET_OK to keep the address and continue | ||
495 | */ | ||
496 | static int | ||
497 | print_address (void *cls, | ||
498 | const struct GNUNET_HELLO_Address *address, | ||
499 | struct GNUNET_TIME_Absolute expiration) | ||
500 | { | ||
501 | struct PrintContext *pc = cls; | ||
502 | struct AddressRecord *ar; | ||
503 | |||
504 | if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) | ||
505 | { | ||
506 | return GNUNET_OK; /* ignore expired address */ | ||
507 | } | ||
508 | |||
509 | GNUNET_assert (0 < pc->off); | ||
510 | ar = &pc->address_list[--pc->off]; | ||
511 | ar->pc = pc; | ||
512 | ar->expiration = expiration; | ||
513 | GNUNET_asprintf (&ar->result, | ||
514 | "%s:%u:%u", | ||
515 | address->transport_name, | ||
516 | address->address_length, | ||
517 | address->local_info); | ||
518 | ar->atsc = GNUNET_TRANSPORT_address_to_string (cfg, | ||
519 | address, | ||
520 | GNUNET_NO, | ||
521 | TIMEOUT, | ||
522 | &process_resolved_address, | ||
523 | ar); | ||
524 | return GNUNET_OK; | ||
525 | } | ||
526 | |||
527 | |||
528 | /** | ||
529 | * Callback that processes each of the known HELLOs for the | ||
530 | * iteration response construction. | ||
531 | * | ||
532 | * @param cls closure, NULL | ||
533 | * @param peer id of the peer, NULL for last call | ||
534 | * @param hello hello message for the peer (can be NULL) | ||
535 | * @param err_msg message | ||
536 | */ | ||
537 | void | ||
538 | peerinfo_list_iteration(void *cls, | ||
539 | const struct GNUNET_PeerIdentity *peer, | ||
540 | const struct GNUNET_HELLO_Message *hello, | ||
541 | const char *err_msg) | ||
542 | { | ||
543 | struct RequestHandle *handle = cls; | ||
544 | struct PrintContext *pc; | ||
545 | int friend_only; | ||
546 | |||
547 | if (NULL == handle->response) | ||
548 | { | ||
549 | handle->response = json_array(); | ||
550 | } | ||
551 | |||
552 | if (NULL == peer) | ||
553 | { | ||
554 | handle->list_it = NULL; | ||
555 | handle->emsg = GNUNET_strdup ("Error in communication with peerinfo"); | ||
556 | if (NULL != err_msg) | ||
557 | { | ||
558 | GNUNET_free(handle->emsg); | ||
559 | handle->emsg = GNUNET_strdup (err_msg); | ||
560 | handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; | ||
561 | } | ||
562 | if (NULL == pc_head) | ||
563 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
564 | return; | ||
565 | } | ||
566 | if (NULL == hello) | ||
567 | return; | ||
568 | |||
569 | friend_only = GNUNET_NO; | ||
570 | if (NULL != hello) | ||
571 | friend_only = GNUNET_HELLO_is_friend_only (hello); | ||
572 | |||
573 | pc = GNUNET_new(struct PrintContext); | ||
574 | GNUNET_CONTAINER_DLL_insert (pc_head, | ||
575 | pc_tail, | ||
576 | pc); | ||
577 | pc->peer = *peer; | ||
578 | pc->friend_only = friend_only; | ||
579 | pc->handle = handle; | ||
580 | GNUNET_HELLO_iterate_addresses (hello, | ||
581 | GNUNET_NO, | ||
582 | &count_address, | ||
583 | pc); | ||
584 | if (0 == pc->off) | ||
585 | { | ||
586 | dump_pc (pc); | ||
587 | return; | ||
588 | } | ||
589 | pc->address_list_size = pc->off; | ||
590 | pc->address_list = GNUNET_malloc( | ||
591 | sizeof(struct AddressRecord) * pc->off); | ||
592 | GNUNET_HELLO_iterate_addresses (hello, | ||
593 | GNUNET_NO, | ||
594 | &print_address, | ||
595 | pc); | ||
596 | } | ||
597 | |||
598 | /** | ||
599 | * Handle peerinfo GET request | ||
600 | * | ||
601 | * @param con_handle the connection handle | ||
602 | * @param url the url | ||
603 | * @param cls the RequestHandle | ||
604 | */ | ||
605 | void | ||
606 | peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle, | ||
607 | const char* url, | ||
608 | void *cls) | ||
609 | { | ||
610 | struct RequestHandle *handle = cls; | ||
611 | struct GNUNET_HashCode key; | ||
612 | const struct GNUNET_PeerIdentity *specific_peer; | ||
613 | GNUNET_PEER_Id peer_id; | ||
614 | int include_friend_only; | ||
615 | char* include_friend_only_str; | ||
616 | |||
617 | include_friend_only = GNUNET_NO; | ||
618 | GNUNET_CRYPTO_hash (GNUNET_REST_API_PEERINFO_FRIEND, | ||
619 | strlen (GNUNET_REST_API_PEERINFO_FRIEND), | ||
620 | &key); | ||
621 | if ( GNUNET_YES | ||
622 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, | ||
623 | &key)) | ||
624 | { | ||
625 | include_friend_only_str = GNUNET_CONTAINER_multihashmap_get ( | ||
626 | con_handle->url_param_map, &key); | ||
627 | if (0 == strcmp(include_friend_only_str, "yes")) | ||
628 | { | ||
629 | include_friend_only = GNUNET_YES; | ||
630 | } | ||
631 | } | ||
632 | |||
633 | specific_peer = NULL; | ||
634 | GNUNET_CRYPTO_hash (GNUNET_REST_API_PEERINFO_PEER, | ||
635 | strlen (GNUNET_REST_API_PEERINFO_PEER), | ||
636 | &key); | ||
637 | if ( GNUNET_YES | ||
638 | == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, | ||
639 | &key)) | ||
640 | { | ||
641 | peer_id = *(unsigned int*)GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key); | ||
642 | specific_peer = GNUNET_PEER_resolve2(peer_id); | ||
643 | } | ||
644 | |||
645 | handle->list_it = GNUNET_PEERINFO_iterate(handle->peerinfo_handle, | ||
646 | include_friend_only, | ||
647 | specific_peer, | ||
648 | &peerinfo_list_iteration, | ||
649 | handle); | ||
650 | } | ||
651 | |||
652 | |||
653 | |||
654 | /** | ||
655 | * Respond to OPTIONS request | ||
656 | * | ||
657 | * @param con_handle the connection handle | ||
658 | * @param url the url | ||
659 | * @param cls the RequestHandle | ||
660 | */ | ||
661 | static void | ||
662 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, | ||
663 | const char* url, | ||
664 | void *cls) | ||
665 | { | ||
666 | struct MHD_Response *resp; | ||
667 | struct RequestHandle *handle = cls; | ||
668 | |||
669 | //independent of path return all options | ||
670 | resp = GNUNET_REST_create_response (NULL); | ||
671 | MHD_add_response_header (resp, | ||
672 | "Access-Control-Allow-Methods", | ||
673 | allow_methods); | ||
674 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
675 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
676 | return; | ||
677 | } | ||
678 | |||
679 | |||
680 | /** | ||
681 | * Handle rest request | ||
682 | * | ||
683 | * @param handle the request handle | ||
684 | */ | ||
685 | static void | ||
686 | init_cont (struct RequestHandle *handle) | ||
687 | { | ||
688 | struct GNUNET_REST_RequestHandlerError err; | ||
689 | static const struct GNUNET_REST_RequestHandler handlers[] = { | ||
690 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_PEERINFO, &peerinfo_get}, | ||
691 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_PEERINFO, &options_cont}, | ||
692 | GNUNET_REST_HANDLER_END | ||
693 | }; | ||
694 | |||
695 | if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, | ||
696 | handlers, | ||
697 | &err, | ||
698 | handle)) | ||
699 | { | ||
700 | handle->response_code = err.error_code; | ||
701 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
702 | } | ||
703 | } | ||
704 | |||
705 | |||
706 | /** | ||
707 | * Function processing the REST call | ||
708 | * | ||
709 | * @param method HTTP method | ||
710 | * @param url URL of the HTTP request | ||
711 | * @param data body of the HTTP request (optional) | ||
712 | * @param data_size length of the body | ||
713 | * @param proc callback function for the result | ||
714 | * @param proc_cls closure for callback function | ||
715 | * @return GNUNET_OK if request accepted | ||
716 | */ | ||
717 | static void | ||
718 | rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, | ||
719 | GNUNET_REST_ResultProcessor proc, | ||
720 | void *proc_cls) | ||
721 | { | ||
722 | struct RequestHandle *handle = GNUNET_new (struct RequestHandle); | ||
723 | |||
724 | handle->response_code = 0; | ||
725 | handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60); | ||
726 | handle->proc_cls = proc_cls; | ||
727 | handle->proc = proc; | ||
728 | handle->rest_handle = rest_handle; | ||
729 | |||
730 | handle->url = GNUNET_strdup (rest_handle->url); | ||
731 | if (handle->url[strlen (handle->url)-1] == '/') | ||
732 | handle->url[strlen (handle->url)-1] = '\0'; | ||
733 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); | ||
734 | handle->peerinfo_handle = GNUNET_PEERINFO_connect(cfg); | ||
735 | init_cont(handle); | ||
736 | handle->timeout_task = | ||
737 | GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
738 | &do_error, | ||
739 | handle); | ||
740 | |||
741 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); | ||
742 | } | ||
743 | |||
744 | |||
745 | /** | ||
746 | * Entry point for the plugin. | ||
747 | * | ||
748 | * @param cls Config info | ||
749 | * @return NULL on error, otherwise the plugin context | ||
750 | */ | ||
751 | void * | ||
752 | libgnunet_plugin_rest_peerinfo_init (void *cls) | ||
753 | { | ||
754 | static struct Plugin plugin; | ||
755 | struct GNUNET_REST_Plugin *api; | ||
756 | |||
757 | cfg = cls; | ||
758 | if (NULL != plugin.cfg) | ||
759 | return NULL; /* can only initialize once! */ | ||
760 | memset (&plugin, 0, sizeof (struct Plugin)); | ||
761 | plugin.cfg = cfg; | ||
762 | api = GNUNET_new (struct GNUNET_REST_Plugin); | ||
763 | api->cls = &plugin; | ||
764 | api->name = GNUNET_REST_API_NS_PEERINFO; | ||
765 | api->process_request = &rest_process_request; | ||
766 | GNUNET_asprintf (&allow_methods, | ||
767 | "%s, %s, %s, %s, %s", | ||
768 | MHD_HTTP_METHOD_GET, | ||
769 | MHD_HTTP_METHOD_POST, | ||
770 | MHD_HTTP_METHOD_PUT, | ||
771 | MHD_HTTP_METHOD_DELETE, | ||
772 | MHD_HTTP_METHOD_OPTIONS); | ||
773 | |||
774 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
775 | _("Peerinfo REST API initialized\n")); | ||
776 | return api; | ||
777 | } | ||
778 | |||
779 | |||
780 | /** | ||
781 | * Exit point from the plugin. | ||
782 | * | ||
783 | * @param cls the plugin context (as returned by "init") | ||
784 | * @return always NULL | ||
785 | */ | ||
786 | void * | ||
787 | libgnunet_plugin_rest_peerinfo_done (void *cls) | ||
788 | { | ||
789 | struct GNUNET_REST_Plugin *api = cls; | ||
790 | struct Plugin *plugin = api->cls; | ||
791 | plugin->cfg = NULL; | ||
792 | |||
793 | GNUNET_free_non_null (allow_methods); | ||
794 | GNUNET_free (api); | ||
795 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
796 | "Peerinfo REST plugin is finished\n"); | ||
797 | return NULL; | ||
798 | } | ||
799 | |||
800 | /* end of plugin_rest_peerinfo.c */ | ||
801 | |||