aboutsummaryrefslogtreecommitdiff
path: root/src/peerinfo/plugin_rest_peerinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/peerinfo/plugin_rest_peerinfo.c')
-rw-r--r--src/peerinfo/plugin_rest_peerinfo.c398
1 files changed, 267 insertions, 131 deletions
diff --git a/src/peerinfo/plugin_rest_peerinfo.c b/src/peerinfo/plugin_rest_peerinfo.c
index 408f9a6f7..a65089b32 100644
--- a/src/peerinfo/plugin_rest_peerinfo.c
+++ b/src/peerinfo/plugin_rest_peerinfo.c
@@ -39,6 +39,10 @@
39#define GNUNET_REST_ERROR_UNKNOWN "Unkown Error" 39#define GNUNET_REST_ERROR_UNKNOWN "Unkown Error"
40 40
41/** 41/**
42 * How long until we time out during address lookup?
43 */
44#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
45/**
42 * The configuration handle 46 * The configuration handle
43 */ 47 */
44const struct GNUNET_CONFIGURATION_Handle *cfg; 48const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -59,6 +63,95 @@ struct Plugin
59//TODO add specific structs 63//TODO add specific structs
60 64
61 65
66/**
67 * Record we keep for each printable address.
68 */
69struct AddressRecord
70{
71 /**
72 * Current address-to-string context (if active, otherwise NULL).
73 */
74 struct GNUNET_TRANSPORT_AddressToStringContext *atsc;
75
76 /**
77 * Address expiration time
78 */
79 struct GNUNET_TIME_Absolute expiration;
80
81 /**
82 * Printable address.
83 */
84 char *result;
85
86 /**
87 * Print context this address record belongs to.
88 */
89 struct PrintContext *pc;
90};
91
92
93/**
94 * Structure we use to collect printable address information.
95 */
96struct PrintContext
97{
98
99 /**
100 * Kept in DLL.
101 */
102 struct PrintContext *next;
103
104 /**
105 * Kept in DLL.
106 */
107 struct PrintContext *prev;
108
109 /**
110 * Identity of the peer.
111 */
112 struct GNUNET_PeerIdentity peer;
113
114 /**
115 * List of printable addresses.
116 */
117 struct AddressRecord *address_list;
118
119 /**
120 * Number of completed addresses in @e address_list.
121 */
122 unsigned int num_addresses;
123
124 /**
125 * Number of addresses allocated in @e address_list.
126 */
127 unsigned int address_list_size;
128
129 /**
130 * Current offset in @e address_list (counted down).
131 */
132 unsigned int off;
133
134 /**
135 * Hello was friend only, #GNUNET_YES or #GNUNET_NO
136 */
137 int friend_only;
138
139 /**
140 * RequestHandle
141 */
142 struct RequestHandle *handle;
143
144};
145
146/**
147 * Head of list of print contexts.
148 */
149static struct PrintContext *pc_head;
150
151/**
152 * Tail of list of print contexts.
153 */
154static struct PrintContext *pc_tail;
62 155
63struct RequestHandle 156struct RequestHandle
64{ 157{
@@ -139,8 +232,6 @@ cleanup_handle (void *cls)
139{ 232{
140 struct RequestHandle *handle = cls; 233 struct RequestHandle *handle = cls;
141 234
142 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test: %i\n", NULL == handle);
143
144 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 235 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
145 "Cleaning up\n"); 236 "Cleaning up\n");
146 if (NULL != handle->timeout_task) 237 if (NULL != handle->timeout_task)
@@ -212,7 +303,6 @@ do_error (void *cls)
212static void 303static void
213peerinfo_list_finished (void *cls) 304peerinfo_list_finished (void *cls)
214{ 305{
215 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "6\n");
216 struct RequestHandle *handle = cls; 306 struct RequestHandle *handle = cls;
217 char *result_str; 307 char *result_str;
218 struct MHD_Response *resp; 308 struct MHD_Response *resp;
@@ -234,132 +324,177 @@ peerinfo_list_finished (void *cls)
234 324
235 325
236/** 326/**
237 * Set @a cls to #GNUNET_YES (we have an address!). 327 * Iterator callback to go over all addresses and count them.
238 * 328 *
239 * @param cls closure, an `int *` 329 * @param cls `struct PrintContext *` with `off` to increment
240 * @param address the address (ignored) 330 * @param address the address
241 * @param expiration expiration time (call is ignored if this is in the past) 331 * @param expiration expiration time
242 * @return #GNUNET_SYSERR to stop iterating (unless expiration has occured) 332 * @return #GNUNET_OK to keep the address and continue
243 */ 333 */
244static int 334static int
245check_has_addr (void *cls, 335count_address (void *cls,
246 const struct GNUNET_HELLO_Address *address, 336 const struct GNUNET_HELLO_Address *address,
247 struct GNUNET_TIME_Absolute expiration) 337 struct GNUNET_TIME_Absolute expiration)
248{ 338{
249 int *arg = cls; 339 struct PrintContext *pc = cls;
340
250 if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) 341 if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
251 { 342 {
252 return GNUNET_YES; /* ignore this address */ 343 return GNUNET_OK; /* ignore expired address */
253 } 344 }
254 *arg = GNUNET_YES;
255 return GNUNET_SYSERR;
256}
257 345
258static void 346 pc->off++;
259create_array(void *cls) 347 return GNUNET_OK;
260{
261 struct RequestHandle *handle = cls;
262// json_t *object;
263// object = json_object();
264//
265// json_object_set(object,"address",json_string(handle->address));
266// json_object_set(object,"expires",json_string(handle->expiration_str));
267//
268// if(NULL == handle->temp_array)
269// {
270// handle->temp_array = json_array();
271// }
272//
273// json_array_append(handle->temp_array,object);
274//
275// json_decref(object);
276 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "5\n");
277 json_object_set(handle->response, handle->pubkey, handle->temp_array);
278 json_decref (handle->temp_array);
279} 348}
280 349
350
351/**
352 * Print the collected address information to the console and free @a pc.
353 *
354 * @param pc printing context
355 */
281static void 356static void
282create_tmp_array (void *cls) 357dump_pc (struct PrintContext *pc)
283{ 358{
284 struct RequestHandle *handle = cls; 359 struct RequestHandle *handle;
285 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "4\n"); 360 unsigned int i;
361 json_t *temp_array;
286 json_t *object; 362 json_t *object;
287 json_t *address_json = json_string (handle->address); 363 json_t *address;
288 json_t *expires_json = json_string (handle->expiration_str); 364 json_t *expires;
289 object = json_object (); 365 char *friend_and_peer;
290 366
291 json_object_set (object, "address", address_json); 367 temp_array = json_array();
292 json_decref(address_json);
293 json_object_set (object, "expires", expires_json);
294 json_decref(expires_json);
295 GNUNET_free(handle->expiration_str);
296 368
297 if (NULL == handle->temp_array) 369// printf (_("%sPeer `%s'\n"),
370// (GNUNET_YES == pc->friend_only) ? "F2F: " : "",
371// GNUNET_i2s_full (&pc->peer));
372 for (i = 0; i < pc->num_addresses; i++)
298 { 373 {
299 handle->temp_array = json_array (); 374 if (NULL != pc->address_list[i].result)
375 {
376 object = json_object ();
377 address = json_string(pc->address_list[i].result);
378 expires = json_string(
379 GNUNET_STRINGS_absolute_time_to_string (pc->address_list[i].expiration));
380 json_object_set (object, "address", address);
381 json_object_set (object, "expires", expires);
382
383 json_decref(address);
384 json_decref(expires);
385
386 json_array_append(temp_array, object);
387 json_decref(object);
388 GNUNET_free (pc->address_list[i].result);
389 }
300 } 390 }
301 391
302 json_array_append (handle->temp_array, object); 392 if (0 < json_array_size(temp_array))
393 {
394 GNUNET_asprintf(&friend_and_peer,
395 "%s%s",
396 (GNUNET_YES == pc->friend_only) ? "F2F:" : "",
397 GNUNET_i2s_full (&pc->peer));
398 json_object_set(pc->handle->response,
399 friend_and_peer,
400 temp_array);
401 GNUNET_free(friend_and_peer);
402 }
403
404 json_decref (temp_array);
405
406 GNUNET_free_non_null (pc->address_list);
407 GNUNET_CONTAINER_DLL_remove (pc_head,
408 pc_tail,
409 pc);
410 handle = pc->handle;
411 GNUNET_free (pc);
412
413 if ( (NULL == pc_head) &&
414 (NULL == handle->list_it) )
415 {
416 GNUNET_SCHEDULER_add_now (&peerinfo_list_finished, handle);
417 }
303 418
304 json_decref (object);
305} 419}
306 420
421
422/**
423 * Function to call with a human-readable format of an address
424 *
425 * @param cls closure
426 * @param address NULL on error, otherwise 0-terminated printable UTF-8 string
427 * @param res result of the address to string conversion:
428 * if #GNUNET_OK: address was valid (conversion to
429 * string might still have failed)
430 * if #GNUNET_SYSERR: address is invalid
431 */
307static void 432static void
308addr_to_str_cb (void *cls, 433process_resolved_address (void *cls,
309 const char *address, 434 const char *address,
310 int res) 435 int res)
311{ 436{
312 struct RequestHandle *handle = cls; 437 struct AddressRecord *ar = cls;
313 if (NULL == address) 438 struct PrintContext *pc = ar->pc;
314 { 439
315 return; 440 if (NULL != address)
316 }
317 if (GNUNET_OK != res)
318 { 441 {
442 if (0 != strlen (address))
443 {
444 if (NULL != ar->result)
445 GNUNET_free (ar->result);
446 ar->result = GNUNET_strdup (address);
447 }
319 return; 448 return;
320 } 449 }
321 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "3\n"); 450 ar->atsc = NULL;
322 handle->address = GNUNET_strdup(address); 451 if (GNUNET_SYSERR == res)
323 GNUNET_assert(false); 452 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
453 _("Failure: Cannot convert address to string for peer `%s'\n"),
454 GNUNET_i2s (&ar->pc->peer));
455 pc->num_addresses++;
456 if (pc->num_addresses == pc->address_list_size)
457 dump_pc (ar->pc);
324} 458}
325 459
460
326/** 461/**
327 * Set @a cls to #GNUNET_YES (we have an address!). 462 * Iterator callback to go over all addresses.
328 * 463 *
329 * @param cls closure 464 * @param cls closure
330 * @param address the address (ignored) 465 * @param address the address
331 * @param expiration expiration time (call is ignored if this is in the past) 466 * @param expiration expiration time
332 * @return #GNUNET_SYSERR to stop iterating (unless expiration has occured) 467 * @return #GNUNET_OK to keep the address and continue
333 */ 468 */
334static int 469static int
335address_iteration (void *cls, 470print_address (void *cls,
336 const struct GNUNET_HELLO_Address *address, 471 const struct GNUNET_HELLO_Address *address,
337 struct GNUNET_TIME_Absolute expiration) 472 struct GNUNET_TIME_Absolute expiration)
338{ 473{
339 struct RequestHandle *handle = cls; 474 struct PrintContext *pc = cls;
340 char *expiration_tmp; 475 struct AddressRecord *ar;
341 476
342 if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) 477 if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us)
343 { 478 {
344 return GNUNET_YES; /* ignore this address */ 479 return GNUNET_OK; /* ignore expired address */
345 } 480 }
346 expiration_tmp = GNUNET_STRINGS_absolute_time_to_string(expiration); 481
347 handle->expiration_str = GNUNET_strdup(expiration_tmp); 482 GNUNET_assert (0 < pc->off);
348 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "2\n"); 483 ar = &pc->address_list[--pc->off];
349 GNUNET_TRANSPORT_address_to_string(cfg, 484 ar->pc = pc;
350 address, 485 ar->expiration = expiration;
351 GNUNET_NO, 486 GNUNET_asprintf (&ar->result,
352 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10), 487 "%s:%u:%u",
353 &addr_to_str_cb, 488 address->transport_name,
354 handle); 489 address->address_length,
355 490 address->local_info);
356 GNUNET_SCHEDULER_add_now(&create_tmp_array,handle); 491 ar->atsc = GNUNET_TRANSPORT_address_to_string (cfg,
357 492 address,
358// GNUNET_SCHEDULER_add_delayed ( 493 GNUNET_NO,
359// GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 11), 494 TIMEOUT,
360// &create_array, 495 &process_resolved_address,
361// handle); 496 ar);
362 return GNUNET_YES; 497 return GNUNET_OK;
363} 498}
364 499
365 500
@@ -379,52 +514,58 @@ peerinfo_list_iteration(void *cls,
379 const char *err_msg) 514 const char *err_msg)
380{ 515{
381 struct RequestHandle *handle = cls; 516 struct RequestHandle *handle = cls;
382 int has_addr; 517 struct PrintContext *pc;
518 int friend_only;
383 519
384 if (NULL == handle->response) 520 if (NULL == handle->response)
385 { 521 {
386 handle->response = json_object(); 522 handle->response = json_object();
387 } 523 }
388 524
389 if (NULL != err_msg)
390 {
391 GNUNET_assert (NULL == peer);
392 handle->list_it = NULL;
393 handle->emsg = GNUNET_strdup ("Error in communication with peerinfo");
394 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
395 GNUNET_SCHEDULER_add_now (&do_error, handle);
396 return;
397 }
398 if (NULL == peer) 525 if (NULL == peer)
399 { 526 {
400 handle->list_it = NULL; 527 handle->list_it = NULL;
401 GNUNET_SCHEDULER_add_now (&peerinfo_list_finished, handle); 528 handle->emsg = GNUNET_strdup ("Error in communication with peerinfo");
529 if (NULL != err_msg)
530 {
531 GNUNET_free(handle->emsg);
532 handle->emsg = GNUNET_strdup (err_msg);
533 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
534 }
535 if (NULL == pc_head)
536 GNUNET_SCHEDULER_add_now (&do_error, handle);
402 return; 537 return;
403 } 538 }
404 if (NULL == hello) 539 if (NULL == hello)
405 return; 540 return;
406 has_addr = GNUNET_NO; 541
542 friend_only = GNUNET_NO;
543 if (NULL != hello)
544 friend_only = GNUNET_HELLO_is_friend_only (hello);
545
546 pc = GNUNET_new(struct PrintContext);
547 GNUNET_CONTAINER_DLL_insert (pc_head,
548 pc_tail,
549 pc);
550 pc->peer = *peer;
551 pc->friend_only = friend_only;
552 pc->handle = handle;
407 GNUNET_HELLO_iterate_addresses (hello, 553 GNUNET_HELLO_iterate_addresses (hello,
408 GNUNET_NO, 554 GNUNET_NO,
409 &check_has_addr, 555 &count_address,
410 &has_addr); 556 pc);
411 if (GNUNET_NO == has_addr) 557 if (0 == pc->off)
412 { 558 {
413 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 559 dump_pc (pc);
414 "HELLO for peer `%4s' has no address, not suitable for hostlist!\n",
415 GNUNET_i2s (peer));
416 return; 560 return;
417 } 561 }
418 562 pc->address_list_size = pc->off;
419 if (NULL != handle->pubkey) 563 pc->address_list = GNUNET_malloc(
420 GNUNET_free (handle->pubkey); 564 sizeof(struct AddressRecord) * pc->off);
421 handle->pubkey = GNUNET_CRYPTO_eddsa_public_key_to_string(&peer->public_key);
422 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "1\n");
423 GNUNET_HELLO_iterate_addresses (hello, 565 GNUNET_HELLO_iterate_addresses (hello,
424 GNUNET_NO, 566 GNUNET_NO,
425 &address_iteration, 567 &print_address,
426 handle); 568 pc);
427 GNUNET_SCHEDULER_add_now(&create_array,handle);
428} 569}
429 570
430/** 571/**
@@ -444,6 +585,7 @@ peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle,
444 const struct GNUNET_PeerIdentity *specific_peer; 585 const struct GNUNET_PeerIdentity *specific_peer;
445 GNUNET_PEER_Id peer_id; 586 GNUNET_PEER_Id peer_id;
446 int include_friend_only; 587 int include_friend_only;
588 char* include_friend_only_str;
447 589
448 include_friend_only = GNUNET_NO; 590 include_friend_only = GNUNET_NO;
449 GNUNET_CRYPTO_hash (GNUNET_REST_API_PEERINFO_FRIEND, 591 GNUNET_CRYPTO_hash (GNUNET_REST_API_PEERINFO_FRIEND,
@@ -453,12 +595,12 @@ peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle,
453 == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, 595 == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
454 &key)) 596 &key))
455 { 597 {
456 include_friend_only = *(int*)GNUNET_CONTAINER_multihashmap_get ( 598 include_friend_only_str = GNUNET_CONTAINER_multihashmap_get (
457 con_handle->url_param_map, &key); 599 con_handle->url_param_map, &key);
458 } 600 if (0 == strcmp(include_friend_only_str, "yes"))
459 if(GNUNET_YES != include_friend_only) 601 {
460 { 602 include_friend_only = GNUNET_YES;
461 include_friend_only = GNUNET_NO; 603 }
462 } 604 }
463 605
464 specific_peer = NULL; 606 specific_peer = NULL;
@@ -473,12 +615,6 @@ peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle,
473 specific_peer = GNUNET_PEER_resolve2(peer_id); 615 specific_peer = GNUNET_PEER_resolve2(peer_id);
474 } 616 }
475 617
476
477 //TODO friend_only and special peer
478
479 //TODO add behaviour and response
480 //TODO maybe notify better than iteration
481
482 handle->list_it = GNUNET_PEERINFO_iterate(handle->peerinfo_handle, 618 handle->list_it = GNUNET_PEERINFO_iterate(handle->peerinfo_handle,
483 include_friend_only, 619 include_friend_only,
484 specific_peer, 620 specific_peer,
@@ -560,7 +696,7 @@ rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
560 struct RequestHandle *handle = GNUNET_new (struct RequestHandle); 696 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
561 697
562 handle->response_code = 0; 698 handle->response_code = 0;
563 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 699 handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60);
564 handle->proc_cls = proc_cls; 700 handle->proc_cls = proc_cls;
565 handle->proc = proc; 701 handle->proc = proc;
566 handle->rest_handle = rest_handle; 702 handle->rest_handle = rest_handle;