aboutsummaryrefslogtreecommitdiff
path: root/src/hello/hello.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-10-03 20:12:09 +0000
committerChristian Grothoff <christian@grothoff.org>2015-10-03 20:12:09 +0000
commit5baf12a487a19225962d15e28ba52f10d1d1f7d4 (patch)
tree59b511a23d38b57ef880e7171a46df6e90562893 /src/hello/hello.c
parentf7f85255bce69204e68b5fca21afae8ea4d6d352 (diff)
downloadgnunet-5baf12a487a19225962d15e28ba52f10d1d1f7d4.tar.gz
gnunet-5baf12a487a19225962d15e28ba52f10d1d1f7d4.zip
improving comments and coding style for libgnunethello library
Diffstat (limited to 'src/hello/hello.c')
-rw-r--r--src/hello/hello.c334
1 files changed, 209 insertions, 125 deletions
diff --git a/src/hello/hello.c b/src/hello/hello.c
index c8c71945d..1013fd5a3 100644
--- a/src/hello/hello.c
+++ b/src/hello/hello.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2009 Christian Grothoff (and other contributing authors) 3 Copyright (C) 2009, 2015 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -108,7 +108,6 @@ struct GNUNET_HELLO_ParseUriContext
108 */ 108 */
109 unsigned int counter_added; 109 unsigned int counter_added;
110 110
111
112 /** 111 /**
113 * Function for finding transport plugins by name. 112 * Function for finding transport plugins by name.
114 */ 113 */
@@ -120,13 +119,13 @@ struct GNUNET_HELLO_ParseUriContext
120 * Return HELLO type 119 * Return HELLO type
121 * 120 *
122 * @param h HELLO Message to test 121 * @param h HELLO Message to test
123 * @return #GNUNET_YES or #GNUNET_NO 122 * @return #GNUNET_YES for friend-only or #GNUNET_NO otherwise
124 */ 123 */
125int 124int
126GNUNET_HELLO_is_friend_only (const struct GNUNET_HELLO_Message *h) 125GNUNET_HELLO_is_friend_only (const struct GNUNET_HELLO_Message *h)
127{ 126{
128 if (GNUNET_YES == ntohl(h->friend_only)) 127 if (GNUNET_YES == ntohl(h->friend_only))
129 return GNUNET_YES; 128 return GNUNET_YES;
130 return GNUNET_NO; 129 return GNUNET_NO;
131} 130}
132 131
@@ -173,9 +172,9 @@ GNUNET_HELLO_add_address (const struct GNUNET_HELLO_Address *address,
173 * Get the size of an address entry in a HELLO message. 172 * Get the size of an address entry in a HELLO message.
174 * 173 *
175 * @param buf pointer to the start of the address entry 174 * @param buf pointer to the start of the address entry
176 * @param max maximum size of the entry (end of buf) 175 * @param max maximum size of the entry (end of @a buf)
177 * @param ralen set to the address length 176 * @param ralen set to the address length
178 * @return size of the entry, or 0 if max is not large enough 177 * @return size of the entry, or 0 if @a max is not large enough
179 */ 178 */
180static size_t 179static size_t
181get_hello_address_size (const char *buf, 180get_hello_address_size (const char *buf,
@@ -228,10 +227,17 @@ get_hello_address_size (const char *buf,
228 * expiration time and an iterator that spews the 227 * expiration time and an iterator that spews the
229 * transport addresses. 228 * transport addresses.
230 * 229 *
230 * If friend only is set to #GNUNET_YES we create a FRIEND_HELLO which
231 * will not be gossiped to other peers.
232 *
233 * @param public_key public key to include in the HELLO
234 * @param addrgen callback to invoke to get addresses
235 * @param addrgen_cls closure for @a addrgen
236 * @param friend_only should the returned HELLO be only visible to friends?
231 * @return the hello message 237 * @return the hello message
232 */ 238 */
233struct GNUNET_HELLO_Message * 239struct GNUNET_HELLO_Message *
234GNUNET_HELLO_create (const struct GNUNET_CRYPTO_EddsaPublicKey *publicKey, 240GNUNET_HELLO_create (const struct GNUNET_CRYPTO_EddsaPublicKey *public_key,
235 GNUNET_HELLO_GenerateAddressListCallback addrgen, 241 GNUNET_HELLO_GenerateAddressListCallback addrgen,
236 void *addrgen_cls, 242 void *addrgen_cls,
237 int friend_only) 243 int friend_only)
@@ -243,14 +249,16 @@ GNUNET_HELLO_create (const struct GNUNET_CRYPTO_EddsaPublicKey *publicKey,
243 size_t ret; 249 size_t ret;
244 struct GNUNET_HELLO_Message *hello; 250 struct GNUNET_HELLO_Message *hello;
245 251
246 GNUNET_assert (NULL != publicKey); 252 GNUNET_assert (NULL != public_key);
247 GNUNET_assert ((GNUNET_YES == friend_only) || (GNUNET_NO == friend_only)); 253 GNUNET_assert ( (GNUNET_YES == friend_only) ||
248 254 (GNUNET_NO == friend_only) );
249 max = sizeof (buffer); 255 max = sizeof (buffer);
250 used = 0; 256 used = 0;
251 if (addrgen != NULL) 257 if (NULL != addrgen)
252 { 258 {
253 while (GNUNET_SYSERR != (ret = addrgen (addrgen_cls, max, &buffer[used]))) 259 while (GNUNET_SYSERR != (ret = addrgen (addrgen_cls,
260 max,
261 &buffer[used])))
254 { 262 {
255 max -= ret; 263 max -= ret;
256 used += ret; 264 used += ret;
@@ -260,10 +268,10 @@ GNUNET_HELLO_create (const struct GNUNET_CRYPTO_EddsaPublicKey *publicKey,
260 hello->header.type = htons (GNUNET_MESSAGE_TYPE_HELLO); 268 hello->header.type = htons (GNUNET_MESSAGE_TYPE_HELLO);
261 hello->header.size = htons (sizeof (struct GNUNET_HELLO_Message) + used); 269 hello->header.size = htons (sizeof (struct GNUNET_HELLO_Message) + used);
262 hello->friend_only = htonl (friend_only); 270 hello->friend_only = htonl (friend_only);
263 271 hello->publicKey = *public_key;
264 memcpy (&hello->publicKey, publicKey, 272 memcpy (&hello[1],
265 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); 273 buffer,
266 memcpy (&hello[1], buffer, used); 274 used);
267 return hello; 275 return hello;
268} 276}
269 277
@@ -304,22 +312,27 @@ GNUNET_HELLO_iterate_addresses (const struct GNUNET_HELLO_Message *msg,
304 if (return_modified) 312 if (return_modified)
305 { 313 {
306 ret = GNUNET_malloc (msize); 314 ret = GNUNET_malloc (msize);
307 memcpy (ret, msg, msize); 315 memcpy (ret,
316 msg,
317 msize);
308 } 318 }
309 inptr = (const char *) &msg[1]; 319 inptr = (const char *) &msg[1];
310 insize = msize - sizeof (struct GNUNET_HELLO_Message); 320 insize = msize - sizeof (struct GNUNET_HELLO_Message);
311 wpos = 0; 321 wpos = 0;
312 woff = (ret != NULL) ? (char *) &ret[1] : NULL; 322 woff = (NULL != ret) ? (char *) &ret[1] : NULL;
313 address.peer.public_key = msg->publicKey; 323 address.peer.public_key = msg->publicKey;
314 while (insize > 0) 324 while (insize > 0)
315 { 325 {
316 esize = get_hello_address_size (inptr, insize, &alen); 326 esize = get_hello_address_size (inptr,
327 insize,
328 &alen);
317 if (0 == esize) 329 if (0 == esize)
318 { 330 {
319 GNUNET_break (0); 331 GNUNET_break (0);
320 GNUNET_free_non_null (ret); 332 GNUNET_free_non_null (ret);
321 return NULL; 333 return NULL;
322 } 334 }
335 /* need memcpy() due to possibility of misalignment */
323 memcpy (&expire, 336 memcpy (&expire,
324 &inptr[esize - alen - sizeof (struct GNUNET_TIME_AbsoluteNBO)], 337 &inptr[esize - alen - sizeof (struct GNUNET_TIME_AbsoluteNBO)],
325 sizeof (struct GNUNET_TIME_AbsoluteNBO)); 338 sizeof (struct GNUNET_TIME_AbsoluteNBO));
@@ -327,23 +340,25 @@ GNUNET_HELLO_iterate_addresses (const struct GNUNET_HELLO_Message *msg,
327 address.address_length = alen; 340 address.address_length = alen;
328 address.transport_name = inptr; 341 address.transport_name = inptr;
329 address.local_info = GNUNET_HELLO_ADDRESS_INFO_NONE; 342 address.local_info = GNUNET_HELLO_ADDRESS_INFO_NONE;
330 iret = it (it_cls, &address, GNUNET_TIME_absolute_ntoh (expire)); 343 iret = it (it_cls,
331 if (iret == GNUNET_SYSERR) 344 &address,
332 { 345 GNUNET_TIME_absolute_ntoh (expire));
333 if (ret != NULL) 346 if (GNUNET_SYSERR == iret)
334 ret->header.size = ntohs (sizeof (struct GNUNET_HELLO_Message) + wpos); 347 break;
335 return ret; 348 if ( (GNUNET_OK == iret) &&
336 } 349 (NULL != ret) )
337 if ((iret == GNUNET_OK) && (ret != NULL))
338 { 350 {
339 memcpy (woff, inptr, esize); 351 /* copy address over */
352 memcpy (woff,
353 inptr,
354 esize);
340 woff += esize; 355 woff += esize;
341 wpos += esize; 356 wpos += esize;
342 } 357 }
343 insize -= esize; 358 insize -= esize;
344 inptr += esize; 359 inptr += esize;
345 } 360 }
346 if (ret != NULL) 361 if (NULL != ret)
347 ret->header.size = ntohs (sizeof (struct GNUNET_HELLO_Message) + wpos); 362 ret->header.size = ntohs (sizeof (struct GNUNET_HELLO_Message) + wpos);
348 return ret; 363 return ret;
349} 364}
@@ -386,53 +401,56 @@ get_match_exp (void *cls,
386{ 401{
387 struct ExpireContext *ec = cls; 402 struct ExpireContext *ec = cls;
388 403
389 if (0 == GNUNET_HELLO_address_cmp (address, ec->address)) 404 if (0 != GNUNET_HELLO_address_cmp (address,
390 { 405 ec->address))
391 ec->found = GNUNET_YES; 406 return GNUNET_OK;
392 ec->expiration = expiration; 407 ec->found = GNUNET_YES;
393 return GNUNET_SYSERR; /* done here */ 408 ec->expiration = expiration;
394 } 409 return GNUNET_SYSERR; /* done here */
395 return GNUNET_OK;
396} 410}
397 411
398 412
399/** 413/**
400 * 414 * Context for a #GNUNET_HELLO_Merge operation.
401 */ 415 */
402struct MergeContext 416struct MergeContext
403{ 417{
404 /** 418 /**
405 * 419 * First HELLO we are merging.
406 */ 420 */
407 const struct GNUNET_HELLO_Message *h1; 421 const struct GNUNET_HELLO_Message *h1;
408 422
409 /** 423 /**
410 * 424 * Second HELLO we are merging.
411 */ 425 */
412 const struct GNUNET_HELLO_Message *h2; 426 const struct GNUNET_HELLO_Message *h2;
413 427
414 /** 428 /**
415 * 429 * Either @e h1 or @e h2, used when copying
430 * to compare against (so we only copy the
431 * most recent entry).
416 */ 432 */
417 const struct GNUNET_HELLO_Message *other; 433 const struct GNUNET_HELLO_Message *other;
418 434
419 /** 435 /**
420 * 436 * Buffer where we copy to.
421 */ 437 */
422 char *buf; 438 char *buf;
423 439
424 /** 440 /**
425 * 441 * Number of bytes allocated in @e buf
426 */ 442 */
427 size_t max; 443 size_t max;
428 444
429 /** 445 /**
430 * 446 * Current (write) offset in @e buf.
431 */ 447 */
432 size_t ret; 448 size_t ret;
433 449
434 /** 450 /**
435 * 451 * Should we copy addresses with an identical value
452 * and expiration time in @e other, or do we only
453 * copy addresses with strictly later expiration times?
436 */ 454 */
437 int take_equal; 455 int take_equal;
438 456
@@ -440,12 +458,14 @@ struct MergeContext
440 458
441 459
442/** 460/**
461 * Append the address @a address to the buffer from
462 * the merge context IF it is more recent than equivalent
463 * addresses in `other`.
443 * 464 *
444 * 465 * @param cls the `struct MergeContext`
445 * @param cls 466 * @param address the HELLO address we might copy
446 * @param address 467 * @param expiration expiration time for @a address
447 * @param expiration 468 * @return always #GNUNET_OK
448 * @return
449 */ 469 */
450static int 470static int
451copy_latest (void *cls, 471copy_latest (void *cls,
@@ -457,14 +477,21 @@ copy_latest (void *cls,
457 477
458 ec.address = address; 478 ec.address = address;
459 ec.found = GNUNET_NO; 479 ec.found = GNUNET_NO;
460 GNUNET_HELLO_iterate_addresses (mc->other, GNUNET_NO, &get_match_exp, &ec); 480 /* check if address exists in other */
461 if ((ec.found == GNUNET_NO) || 481 GNUNET_HELLO_iterate_addresses (mc->other,
462 (ec.expiration.abs_value_us < expiration.abs_value_us) || 482 GNUNET_NO,
463 ((ec.expiration.abs_value_us == expiration.abs_value_us) && 483 &get_match_exp,
464 (mc->take_equal == GNUNET_YES))) 484 &ec);
485 if ( (GNUNET_NO == ec.found) ||
486 (ec.expiration.abs_value_us < expiration.abs_value_us) ||
487 ( (ec.expiration.abs_value_us == expiration.abs_value_us) &&
488 (GNUNET_YES == mc->take_equal) ) )
465 { 489 {
490 /* copy address to buffer */
466 mc->ret += 491 mc->ret +=
467 GNUNET_HELLO_add_address (address, expiration, &mc->buf[mc->ret], 492 GNUNET_HELLO_add_address (address,
493 expiration,
494 &mc->buf[mc->ret],
468 mc->max - mc->ret); 495 mc->max - mc->ret);
469 } 496 }
470 return GNUNET_OK; 497 return GNUNET_OK;
@@ -472,7 +499,14 @@ copy_latest (void *cls,
472 499
473 500
474/** 501/**
502 * Function called to build the HELLO during
503 * #GNUNET_HELLO_merge() by merging addresses from
504 * two original HELLOs.
475 * 505 *
506 * @param cls the `struct MergeContext`
507 * @param max number of bytes we can write at most in @a buf
508 * @param buf where to copy the addresses
509 * @return #GNUNET_SYSERR to end iteration, otherwise number of bytes written to @a buf
476 */ 510 */
477static ssize_t 511static ssize_t
478merge_addr (void *cls, 512merge_addr (void *cls,
@@ -481,17 +515,26 @@ merge_addr (void *cls,
481{ 515{
482 struct MergeContext *mc = cls; 516 struct MergeContext *mc = cls;
483 517
484 if (mc->h1 == NULL) 518 if (NULL == mc->h1)
485 return GNUNET_SYSERR; /* Stop iteration */ 519 return GNUNET_SYSERR; /* Stop iteration */
486 mc->ret = 0; 520 mc->ret = 0;
487 mc->max = max; 521 mc->max = max;
488 mc->buf = buf; 522 mc->buf = buf;
489 mc->take_equal = GNUNET_NO; 523 mc->take_equal = GNUNET_NO;
490 mc->other = mc->h2; 524 mc->other = mc->h2;
491 GNUNET_HELLO_iterate_addresses (mc->h1, GNUNET_NO, &copy_latest, mc); 525 /* copy addresses from h1, if strictly larger expiration than h2 */
526 GNUNET_HELLO_iterate_addresses (mc->h1,
527 GNUNET_NO,
528 &copy_latest,
529 mc);
492 mc->take_equal = GNUNET_YES; 530 mc->take_equal = GNUNET_YES;
493 mc->other = mc->h1; 531 mc->other = mc->h1;
494 GNUNET_HELLO_iterate_addresses (mc->h2, GNUNET_NO, &copy_latest, mc); 532 /* copy addresses from h2, if larger or equal expiration than h1 */
533 GNUNET_HELLO_iterate_addresses (mc->h2,
534 GNUNET_NO,
535 &copy_latest,
536 mc);
537 /* set marker to stop iteration */
495 mc->h1 = NULL; 538 mc->h1 = NULL;
496 return mc->ret; 539 return mc->ret;
497} 540}
@@ -504,7 +547,7 @@ merge_addr (void *cls,
504 * 547 *
505 * @param h1 first HELLO message 548 * @param h1 first HELLO message
506 * @param h2 the second HELLO message 549 * @param h2 the second HELLO message
507 * @return the combined hello message 550 * @return the combined HELLO message
508 */ 551 */
509struct GNUNET_HELLO_Message * 552struct GNUNET_HELLO_Message *
510GNUNET_HELLO_merge (const struct GNUNET_HELLO_Message *h1, 553GNUNET_HELLO_merge (const struct GNUNET_HELLO_Message *h1,
@@ -526,17 +569,18 @@ GNUNET_HELLO_merge (const struct GNUNET_HELLO_Message *h1,
526 569
527 570
528/** 571/**
529 * 572 * Context used in #GNUNET_HELLO_iterate_new_addresses() to
573 * figure out which addresses are in fact 'new'.
530 */ 574 */
531struct DeltaContext 575struct DeltaContext
532{ 576{
533 /** 577 /**
534 * 578 * We should ignore addresses that expire before this time.
535 */ 579 */
536 struct GNUNET_TIME_Absolute expiration_limit; 580 struct GNUNET_TIME_Absolute expiration_limit;
537 581
538 /** 582 /**
539 * 583 * Function to call on addresses that are indeed new.
540 */ 584 */
541 GNUNET_HELLO_AddressIterator it; 585 GNUNET_HELLO_AddressIterator it;
542 586
@@ -546,14 +590,24 @@ struct DeltaContext
546 void *it_cls; 590 void *it_cls;
547 591
548 /** 592 /**
549 * 593 * HELLO with known addresses, addresses in this HELLO
594 * we must always ignore.
550 */ 595 */
551 const struct GNUNET_HELLO_Message *old_hello; 596 const struct GNUNET_HELLO_Message *old_hello;
552}; 597};
553 598
554 599
555/** 600/**
601 * Check if the given address is 'new', and if so, call
602 * the iterator. Compares the existing address against
603 * addresses in the context's `old_hello` and calls the
604 * iterator on those that are new (and not expired).
556 * 605 *
606 * @param cls the `struct DeltaContext`
607 * @param address an address to check whether it is new
608 * @param expiration expiration time for @a address
609 * @return #GNUNET_YES if the address is ignored, otherwise
610 * whatever the iterator returned.
557 */ 611 */
558static int 612static int
559delta_match (void *cls, 613delta_match (void *cls,
@@ -570,22 +624,26 @@ delta_match (void *cls,
570 GNUNET_NO, 624 GNUNET_NO,
571 &get_match_exp, 625 &get_match_exp,
572 &ec); 626 &ec);
573 if ((ec.found == GNUNET_YES) && 627 if ( (GNUNET_YES == ec.found) &&
574 ((ec.expiration.abs_value_us > expiration.abs_value_us) || 628 ( (ec.expiration.abs_value_us > expiration.abs_value_us) ||
575 (ec.expiration.abs_value_us >= dc->expiration_limit.abs_value_us))) 629 (ec.expiration.abs_value_us >= dc->expiration_limit.abs_value_us)))
576 return GNUNET_YES; /* skip */ 630 return GNUNET_YES; /* skip: found and boring */
577 ret = dc->it (dc->it_cls, address, expiration); 631 ret = dc->it (dc->it_cls,
632 address,
633 expiration);
578 return ret; 634 return ret;
579} 635}
580 636
581 637
582/** 638/**
583 * Iterate over addresses in "new_hello" that 639 * Iterate over addresses in @a new_hello that are NOT already present
584 * are NOT already present in "old_hello". 640 * in @a old_hello. Note that if the address is present in @a old_hello
641 * but the expiration time in @a new_hello is more recent, the iterator
642 * is also called.
585 * 643 *
586 * @param new_hello a HELLO message 644 * @param new_hello a HELLO message
587 * @param old_hello a HELLO message 645 * @param old_hello a HELLO message
588 * @param expiration_limit ignore addresses in old_hello 646 * @param expiration_limit ignore addresses in @a old_hello
589 * that expired before the given time stamp 647 * that expired before the given time stamp
590 * @param it iterator to call on each address 648 * @param it iterator to call on each address
591 * @param it_cls closure for @a it 649 * @param it_cls closure for @a it
@@ -603,7 +661,11 @@ GNUNET_HELLO_iterate_new_addresses (const struct GNUNET_HELLO_Message *new_hello
603 dc.it = it; 661 dc.it = it;
604 dc.it_cls = it_cls; 662 dc.it_cls = it_cls;
605 dc.old_hello = old_hello; 663 dc.old_hello = old_hello;
606 GNUNET_HELLO_iterate_addresses (new_hello, GNUNET_NO, &delta_match, &dc); 664 GNUNET_assert (NULL ==
665 GNUNET_HELLO_iterate_addresses (new_hello,
666 GNUNET_NO,
667 &delta_match,
668 &dc));
607} 669}
608 670
609 671
@@ -625,27 +687,6 @@ GNUNET_HELLO_size (const struct GNUNET_HELLO_Message *hello)
625 687
626 688
627/** 689/**
628 * Get the public key from a HELLO message.
629 *
630 * @param hello the hello message
631 * @param publicKey where to copy the public key information, can be NULL
632 * @return #GNUNET_SYSERR if the HELLO was malformed
633 */
634int
635GNUNET_HELLO_get_key (const struct GNUNET_HELLO_Message *hello,
636 struct GNUNET_CRYPTO_EddsaPublicKey *publicKey)
637{
638 uint16_t ret = ntohs (hello->header.size);
639
640 if ((ret < sizeof (struct GNUNET_HELLO_Message)) ||
641 (ntohs (hello->header.type) != GNUNET_MESSAGE_TYPE_HELLO))
642 return GNUNET_SYSERR;
643 *publicKey = hello->publicKey;
644 return GNUNET_OK;
645}
646
647
648/**
649 * Get the peer identity from a HELLO message. 690 * Get the peer identity from a HELLO message.
650 * 691 *
651 * @param hello the hello message 692 * @param hello the hello message
@@ -688,37 +729,41 @@ GNUNET_HELLO_get_header (struct GNUNET_HELLO_Message *hello)
688 729
689 730
690/** 731/**
691 * 732 * Context used for comparing HELLOs in #GNUNET_HELLO_equals().
692 */ 733 */
693struct EqualsContext 734struct EqualsContext
694{ 735{
695 /** 736 /**
696 * 737 * Addresses that expired before this date are ignored for
738 * the comparisson.
697 */ 739 */
698 struct GNUNET_TIME_Absolute expiration_limit; 740 struct GNUNET_TIME_Absolute expiration_limit;
699 741
700 /** 742 /**
701 * 743 * Earliest expiration time for which we found a match
744 * with a difference in expiration times.
745 * At this time, the two HELLOs may start to diverge.
702 */ 746 */
703 struct GNUNET_TIME_Absolute result; 747 struct GNUNET_TIME_Absolute result;
704 748
705 /** 749 /**
706 * 750 * HELLO message to compare against. (First set to the second
751 * HELLO, then set to the first HELLO.)
707 */ 752 */
708 const struct GNUNET_HELLO_Message *h2; 753 const struct GNUNET_HELLO_Message *ref;
709 754
710 /** 755 /**
711 * 756 * Address we are currently looking for.
712 */ 757 */
713 const struct GNUNET_HELLO_Address *address; 758 const struct GNUNET_HELLO_Address *address;
714 759
715 /** 760 /**
716 * 761 * Expiration time of @e address.
717 */ 762 */
718 struct GNUNET_TIME_Absolute expiration; 763 struct GNUNET_TIME_Absolute expiration;
719 764
720 /** 765 /**
721 * 766 * Did we find the address we were looking for?
722 */ 767 */
723 int found; 768 int found;
724 769
@@ -726,7 +771,16 @@ struct EqualsContext
726 771
727 772
728/** 773/**
774 * Check if the given address matches the address we are currently
775 * looking for. If so, sets `found` to #GNUNET_YES and, if the
776 * expiration times for the two addresses differ, updates `result` to
777 * the minimum of our @a expiration and the existing value
729 * 778 *
779 * @param cls the `struct EqualsContext`
780 * @param address address from the reference HELLO
781 * @param expiration expiration time for @a address
782 * @return #GNUNET_YES if the address is expired or does not match
783 * #GNUNET_SYSERR if the address does match.
730 */ 784 */
731static int 785static int
732find_other_matching (void *cls, 786find_other_matching (void *cls,
@@ -741,7 +795,8 @@ find_other_matching (void *cls,
741 { 795 {
742 ec->found = GNUNET_YES; 796 ec->found = GNUNET_YES;
743 if (expiration.abs_value_us < ec->expiration.abs_value_us) 797 if (expiration.abs_value_us < ec->expiration.abs_value_us)
744 ec->result = GNUNET_TIME_absolute_min (expiration, ec->result); 798 ec->result = GNUNET_TIME_absolute_min (expiration,
799 ec->result);
745 return GNUNET_SYSERR; 800 return GNUNET_SYSERR;
746 } 801 }
747 return GNUNET_YES; 802 return GNUNET_YES;
@@ -749,7 +804,16 @@ find_other_matching (void *cls,
749 804
750 805
751/** 806/**
807 * Helper function for #GNUNET_HELLO_equals(). Checks
808 * if the given @a address exists also in the other HELLO;
809 * if not, the result time is set to zero and the iteration
810 * is aborted.
752 * 811 *
812 * @param cls the `struct EqualsContext`
813 * @param address address to locate
814 * @param expiration expiration time of the current address
815 * @return #GNUNET_OK if the address exists or is expired,
816 * #GNUNET_SYSERR if it was not found
753 */ 817 */
754static int 818static int
755find_matching (void *cls, 819find_matching (void *cls,
@@ -759,13 +823,17 @@ find_matching (void *cls,
759 struct EqualsContext *ec = cls; 823 struct EqualsContext *ec = cls;
760 824
761 if (expiration.abs_value_us < ec->expiration_limit.abs_value_us) 825 if (expiration.abs_value_us < ec->expiration_limit.abs_value_us)
762 return GNUNET_YES; 826 return GNUNET_OK; /* expired, we don't care */
763 ec->address = address; 827 ec->address = address;
764 ec->expiration = expiration; 828 ec->expiration = expiration;
765 ec->found = GNUNET_NO; 829 ec->found = GNUNET_NO;
766 GNUNET_HELLO_iterate_addresses (ec->h2, GNUNET_NO, &find_other_matching, ec); 830 GNUNET_HELLO_iterate_addresses (ec->ref,
767 if (ec->found == GNUNET_NO) 831 GNUNET_NO,
832 &find_other_matching,
833 ec);
834 if (GNUNET_NO == ec->found)
768 { 835 {
836 /* not found, we differ *now* */
769 ec->result = GNUNET_TIME_UNIT_ZERO_ABS; 837 ec->result = GNUNET_TIME_UNIT_ZERO_ABS;
770 return GNUNET_SYSERR; 838 return GNUNET_SYSERR;
771 } 839 }
@@ -776,7 +844,7 @@ find_matching (void *cls,
776/** 844/**
777 * Test if two HELLO messages contain the same addresses. 845 * Test if two HELLO messages contain the same addresses.
778 * If they only differ in expiration time, the lowest 846 * If they only differ in expiration time, the lowest
779 * expiration time larger than 'now' where they differ 847 * expiration time larger than @a now where they differ
780 * is returned. 848 * is returned.
781 * 849 *
782 * @param h1 first HELLO message 850 * @param h1 first HELLO message
@@ -784,9 +852,9 @@ find_matching (void *cls,
784 * @param now time to use for deciding which addresses have 852 * @param now time to use for deciding which addresses have
785 * expired and should not be considered at all 853 * expired and should not be considered at all
786 * @return absolute time forever if the two HELLOs are 854 * @return absolute time forever if the two HELLOs are
787 * totally identical; smallest timestamp >= now if 855 * totally identical; smallest timestamp >= @a now if
788 * they only differ in timestamps; 856 * they only differ in timestamps;
789 * zero if the some addresses with expirations >= now 857 * zero if the some addresses with expirations >= @a now
790 * do not match at all 858 * do not match at all
791 */ 859 */
792struct GNUNET_TIME_Absolute 860struct GNUNET_TIME_Absolute
@@ -797,22 +865,22 @@ GNUNET_HELLO_equals (const struct GNUNET_HELLO_Message *h1,
797 struct EqualsContext ec; 865 struct EqualsContext ec;
798 866
799 if (h1->header.type != h2->header.type) 867 if (h1->header.type != h2->header.type)
800 return GNUNET_TIME_UNIT_ZERO_ABS; 868 return GNUNET_TIME_UNIT_ZERO_ABS;
801
802 if (0 != 869 if (0 !=
803 memcmp (&h1->publicKey, &h2->publicKey, 870 memcmp (&h1->publicKey,
871 &h2->publicKey,
804 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) 872 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
805 return GNUNET_TIME_UNIT_ZERO_ABS; 873 return GNUNET_TIME_UNIT_ZERO_ABS;
806 ec.expiration_limit = now; 874 ec.expiration_limit = now;
807 ec.result = GNUNET_TIME_UNIT_FOREVER_ABS; 875 ec.result = GNUNET_TIME_UNIT_FOREVER_ABS;
808 ec.h2 = h2; 876 ec.ref = h2;
809 GNUNET_HELLO_iterate_addresses (h1, 877 GNUNET_HELLO_iterate_addresses (h1,
810 GNUNET_NO, 878 GNUNET_NO,
811 &find_matching, 879 &find_matching,
812 &ec); 880 &ec);
813 if (ec.result.abs_value_us == GNUNET_TIME_UNIT_ZERO.rel_value_us) 881 if (ec.result.abs_value_us == GNUNET_TIME_UNIT_ZERO.rel_value_us)
814 return ec.result; 882 return ec.result;
815 ec.h2 = h1; 883 ec.ref = h1;
816 GNUNET_HELLO_iterate_addresses (h2, 884 GNUNET_HELLO_iterate_addresses (h2,
817 GNUNET_NO, 885 GNUNET_NO,
818 &find_matching, 886 &find_matching,
@@ -822,7 +890,13 @@ GNUNET_HELLO_equals (const struct GNUNET_HELLO_Message *h1,
822 890
823 891
824/** 892/**
893 * Iterator to find the time when the last address will expire.
894 * Updates the maximum value stored in @a cls.
825 * 895 *
896 * @param cls where to store the max, a `struct GNUNET_TIME_Absolute`
897 * @param address an address (ignored)
898 * @param expiration expiration time for @a address
899 * @return #GNUNET_OK (always)
826 */ 900 */
827static int 901static int
828find_max_expire (void *cls, 902find_max_expire (void *cls,
@@ -847,7 +921,7 @@ GNUNET_HELLO_get_last_expiration (const struct GNUNET_HELLO_Message *msg)
847{ 921{
848 struct GNUNET_TIME_Absolute ret; 922 struct GNUNET_TIME_Absolute ret;
849 923
850 ret.abs_value_us = 0; 924 ret = GNUNET_TIME_UNIT_ZERO_ABS;
851 GNUNET_HELLO_iterate_addresses (msg, 925 GNUNET_HELLO_iterate_addresses (msg,
852 GNUNET_NO, 926 GNUNET_NO,
853 &find_max_expire, 927 &find_max_expire,
@@ -954,7 +1028,10 @@ add_address_to_uri (void *cls,
954 "%s%c%s%c%s%c%s", 1028 "%s%c%s%c%s%c%s",
955 ctx->uri, 1029 ctx->uri,
956 GNUNET_HELLO_URI_SEP, 1030 GNUNET_HELLO_URI_SEP,
957 strftime (tbuf, sizeof (tbuf), "%Y%m%d%H%M%S", t) ? tbuf : "0", 1031 strftime (tbuf,
1032 sizeof (tbuf),
1033 "%Y%m%d%H%M%S",
1034 t) ? tbuf : "0",
958 GNUNET_HELLO_URI_SEP, 1035 GNUNET_HELLO_URI_SEP,
959 address->transport_name, 1036 address->transport_name,
960 GNUNET_HELLO_URI_SEP, 1037 GNUNET_HELLO_URI_SEP,
@@ -1006,7 +1083,9 @@ GNUNET_HELLO_compose_uri (const struct GNUNET_HELLO_Message *hello,
1006 * @return number of bytes added to buffer, #GNUNET_SYSERR on error 1083 * @return number of bytes added to buffer, #GNUNET_SYSERR on error
1007 */ 1084 */
1008static ssize_t 1085static ssize_t
1009add_address_to_hello (void *cls, size_t max, void *buffer) 1086add_address_to_hello (void *cls,
1087 size_t max,
1088 void *buffer)
1010{ 1089{
1011 struct GNUNET_HELLO_ParseUriContext *ctx = cls; 1090 struct GNUNET_HELLO_ParseUriContext *ctx = cls;
1012 const char *tname; 1091 const char *tname;
@@ -1033,7 +1112,8 @@ add_address_to_hello (void *cls, size_t max, void *buffer)
1033 } 1112 }
1034 ctx->pos++; 1113 ctx->pos++;
1035 1114
1036 if ('0' == ctx->pos[0] && GNUNET_HELLO_URI_SEP == ctx->pos[1]) 1115 if ( ('0' == ctx->pos[0]) &&
1116 (GNUNET_HELLO_URI_SEP == ctx->pos[1]) )
1037 { 1117 {
1038 expire = GNUNET_TIME_UNIT_FOREVER_ABS; 1118 expire = GNUNET_TIME_UNIT_FOREVER_ABS;
1039 tname = ctx->pos + 1; 1119 tname = ctx->pos + 1;
@@ -1162,18 +1242,18 @@ GNUNET_HELLO_parse_uri (const char *uri,
1162 GNUNET_HELLO_URI_PREFIX, 1242 GNUNET_HELLO_URI_PREFIX,
1163 strlen (GNUNET_HELLO_URI_PREFIX))) 1243 strlen (GNUNET_HELLO_URI_PREFIX)))
1164 { 1244 {
1165 pks = &uri[strlen (GNUNET_HELLO_URI_PREFIX)]; 1245 pks = &uri[strlen (GNUNET_HELLO_URI_PREFIX)];
1166 friend_only = GNUNET_NO; 1246 friend_only = GNUNET_NO;
1167 } 1247 }
1168 else if (0 == strncmp (uri, 1248 else if (0 == strncmp (uri,
1169 GNUNET_FRIEND_HELLO_URI_PREFIX, 1249 GNUNET_FRIEND_HELLO_URI_PREFIX,
1170 strlen (GNUNET_FRIEND_HELLO_URI_PREFIX))) 1250 strlen (GNUNET_FRIEND_HELLO_URI_PREFIX)))
1171 { 1251 {
1172 pks = &uri[strlen (GNUNET_FRIEND_HELLO_URI_PREFIX)]; 1252 pks = &uri[strlen (GNUNET_FRIEND_HELLO_URI_PREFIX)];
1173 friend_only = GNUNET_YES; 1253 friend_only = GNUNET_YES;
1174 } 1254 }
1175 else 1255 else
1176 return GNUNET_SYSERR; 1256 return GNUNET_SYSERR;
1177 exc = strchr (pks, GNUNET_HELLO_URI_SEP); 1257 exc = strchr (pks, GNUNET_HELLO_URI_SEP);
1178 1258
1179 if (GNUNET_OK != 1259 if (GNUNET_OK !=
@@ -1188,11 +1268,15 @@ GNUNET_HELLO_parse_uri (const char *uri,
1188 ctx.counter_total = 0; 1268 ctx.counter_total = 0;
1189 ctx.counter_added = 0; 1269 ctx.counter_added = 0;
1190 ctx.plugins_find = plugins_find; 1270 ctx.plugins_find = plugins_find;
1191 *hello = GNUNET_HELLO_create (pubkey, &add_address_to_hello, &ctx, friend_only); 1271 *hello = GNUNET_HELLO_create (pubkey,
1272 &add_address_to_hello,
1273 &ctx,
1274 friend_only);
1192 1275
1193 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1276 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1194 _("HELLO URI contained %u addresses, added %u addresses\n"), 1277 "HELLO URI contained %u addresses, added %u addresses\n",
1195 ctx.counter_total, ctx.counter_added); 1278 ctx.counter_total,
1279 ctx.counter_added);
1196 1280
1197 return ctx.ret; 1281 return ctx.ret;
1198} 1282}