X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fhello%2Fhello.c;h=5b30dc167cb962cf1d052adee3c06b79a1686ba3;hb=92f98f49ff789fadc01e829263cc9d5376fb2f14;hp=79d0edf8dac6049265d8fab6d9c7315fbd97a39f;hpb=120afa6058ba579887a9b417ec86cf06926d765e;p=oweals%2Fgnunet.git diff --git a/src/hello/hello.c b/src/hello/hello.c index 79d0edf8d..5b30dc167 100644 --- a/src/hello/hello.c +++ b/src/hello/hello.c @@ -35,7 +35,7 @@ * the format: * * 1) transport-name (0-terminated) - * 2) address-length (uint32_t, network byte order; possibly + * 2) address-length (uint16_t, network byte order; possibly * unaligned!) * 3) address expiration (GNUNET_TIME_AbsoluteNBO); possibly * unaligned!) @@ -78,21 +78,21 @@ size_t GNUNET_HELLO_add_address (const char *tname, struct GNUNET_TIME_Absolute expiration, const void *addr, - size_t addr_len, char *target, size_t max) + uint16_t addr_len, char *target, size_t max) { - uint32_t alen; + uint16_t alen; size_t slen; struct GNUNET_TIME_AbsoluteNBO exp; slen = strlen (tname) + 1; - if (slen + sizeof (uint32_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + + if (slen + sizeof (uint16_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO) + addr_len > max) return 0; exp = GNUNET_TIME_absolute_hton (expiration); - alen = htonl ((uint32_t) addr_len); + alen = htons (addr_len); memcpy (target, tname, slen); - memcpy (&target[slen], &alen, sizeof (uint32_t)); - slen += sizeof (uint32_t); + memcpy (&target[slen], &alen, sizeof (uint16_t)); + slen += sizeof (uint16_t); memcpy (&target[slen], &exp, sizeof (struct GNUNET_TIME_AbsoluteNBO)); slen += sizeof (struct GNUNET_TIME_AbsoluteNBO); memcpy (&target[slen], addr, addr_len); @@ -110,10 +110,10 @@ GNUNET_HELLO_add_address (const char *tname, * @return size of the entry, or 0 if max is not large enough */ static size_t -get_hello_address_size (const char *buf, size_t max, uint32_t * ralen) +get_hello_address_size (const char *buf, size_t max, uint16_t * ralen) { const char *pos; - uint32_t alen; + uint16_t alen; size_t left; size_t slen; @@ -134,16 +134,16 @@ get_hello_address_size (const char *buf, size_t max, uint32_t * ralen) return 0; } pos++; - if (left < sizeof (uint32_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO)) + if (left < sizeof (uint16_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO)) { /* not enough space for addrlen */ GNUNET_break_op (0); return 0; } - memcpy (&alen, pos, sizeof (uint32_t)); - alen = ntohl (alen); + memcpy (&alen, pos, sizeof (uint16_t)); + alen = ntohs (alen); *ralen = alen; - slen += alen + sizeof (uint32_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO); + slen += alen + sizeof (uint16_t) + sizeof (struct GNUNET_TIME_AbsoluteNBO); if (max < slen) { /* not enough space for addr */ @@ -176,10 +176,13 @@ GNUNET_HELLO_create (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded max = sizeof (buffer); used = 0; - while (0 != (ret = addrgen (addrgen_cls, max, &buffer[used]))) + if (addrgen != NULL) { - max -= ret; - used += ret; + while (0 != (ret = addrgen (addrgen_cls, max, &buffer[used]))) + { + max -= ret; + used += ret; + } } hello = GNUNET_malloc (sizeof (struct GNUNET_HELLO_Message) + used); hello->header.type = htons (GNUNET_MESSAGE_TYPE_HELLO); @@ -212,7 +215,7 @@ GNUNET_HELLO_iterate_addresses (const struct GNUNET_HELLO_Message *msg, size_t esize; size_t wpos; char *woff; - uint32_t alen; + uint16_t alen; struct GNUNET_TIME_AbsoluteNBO expire; int iret; @@ -271,7 +274,8 @@ GNUNET_HELLO_iterate_addresses (const struct GNUNET_HELLO_Message *msg, struct ExpireContext { const void *addr; - size_t addrlen; + const char *tname; + uint16_t addrlen; int found; struct GNUNET_TIME_Absolute expiration; }; @@ -281,11 +285,13 @@ static int get_match_exp (void *cls, const char *tname, struct GNUNET_TIME_Absolute expiration, - const void *addr, size_t addrlen) + const void *addr, uint16_t addrlen) { struct ExpireContext *ec = cls; - if ((addrlen == ec->addrlen) && (0 == memcmp (addr, ec->addr, addrlen))) + if ( (addrlen == ec->addrlen) && + (0 == memcmp (addr, ec->addr, addrlen)) && + (0 == strcmp (tname, ec->tname)) ) { ec->found = GNUNET_YES; ec->expiration = expiration; @@ -312,7 +318,7 @@ static int copy_latest (void *cls, const char *tname, struct GNUNET_TIME_Absolute expiration, - const void *addr, size_t addrlen) + const void *addr, uint16_t addrlen) { struct MergeContext *mc = cls; struct ExpireContext ec; @@ -320,17 +326,20 @@ copy_latest (void *cls, ec.addr = addr; ec.addrlen = addrlen; ec.found = GNUNET_NO; + ec.tname = tname; GNUNET_HELLO_iterate_addresses (mc->other, GNUNET_NO, &get_match_exp, &ec); - if ((ec.found == GNUNET_NO) || - ((ec.expiration.value < expiration.value) || - ((ec.expiration.value == expiration.value) && - (mc->take_equal == GNUNET_YES)))) - mc->ret += GNUNET_HELLO_add_address (tname, - expiration, - addr, - addrlen, - &mc->buf[mc->ret], - mc->max - mc->ret); + if ( (ec.found == GNUNET_NO) || + (ec.expiration.value < expiration.value) || + ( (ec.expiration.value == expiration.value) && + (mc->take_equal == GNUNET_YES) ) ) + { + mc->ret += GNUNET_HELLO_add_address (tname, + expiration, + addr, + addrlen, + &mc->buf[mc->ret], + mc->max - mc->ret); + } return GNUNET_OK; } @@ -391,7 +400,7 @@ static int delta_match (void *cls, const char *tname, struct GNUNET_TIME_Absolute expiration, - const void *addr, size_t addrlen) + const void *addr, uint16_t addrlen) { struct DeltaContext *dc = cls; int ret; @@ -400,6 +409,7 @@ delta_match (void *cls, ec.addr = addr; ec.addrlen = addrlen; ec.found = GNUNET_NO; + ec.tname = tname; GNUNET_HELLO_iterate_addresses (dc->old_hello, GNUNET_NO, &get_match_exp, &ec); if ((ec.found == GNUNET_YES) && @@ -479,5 +489,167 @@ GNUNET_HELLO_get_key (const struct GNUNET_HELLO_Message *hello, } +/** + * Get the peer identity from a HELLO message. + * + * @param hello the hello message + * @param peer where to store the peer's identity + * @return GNUNET_SYSERR if the HELLO was malformed + */ +int +GNUNET_HELLO_get_id (const struct GNUNET_HELLO_Message *hello, + struct GNUNET_PeerIdentity *peer) +{ + uint16_t ret = ntohs (hello->header.size); + if ((ret < sizeof (struct GNUNET_HELLO_Message)) || + (ntohs (hello->header.type) != GNUNET_MESSAGE_TYPE_HELLO)) + return GNUNET_SYSERR; + GNUNET_CRYPTO_hash (&hello->publicKey, + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &peer->hashPubKey); + return GNUNET_OK; +} + + +/** + * Get the header from a HELLO message, used so other code + * can correctly send HELLO messages. + * + * @param hello the hello message + * + * @return header or NULL if the HELLO was malformed + */ +struct GNUNET_MessageHeader * +GNUNET_HELLO_get_header (struct GNUNET_HELLO_Message *hello) +{ + uint16_t ret = ntohs (hello->header.size); + if ((ret < sizeof (struct GNUNET_HELLO_Message)) || + (ntohs (hello->header.type) != GNUNET_MESSAGE_TYPE_HELLO)) + return NULL; + + return &hello->header; +} + + +struct EqualsContext +{ + struct GNUNET_TIME_Absolute expiration_limit; + + struct GNUNET_TIME_Absolute result; + + const struct GNUNET_HELLO_Message *h2; + + const char *tname; + + const void *addr; + + struct GNUNET_TIME_Absolute expiration; + + int found; + + uint16_t addrlen; + +}; + + +static int +find_other_matching (void *cls, + const char *tname, + struct GNUNET_TIME_Absolute expiration, + const void *addr, uint16_t addrlen) +{ + struct EqualsContext *ec = cls; + + if (expiration.value < ec->expiration_limit.value) + return GNUNET_YES; + if ( (addrlen == ec->addrlen) && + (0 == strcmp (tname, + ec->tname)) && + (0 == memcmp (addr, + ec->addr, + addrlen)) ) + { + ec->found = GNUNET_YES; + if (expiration.value < ec->expiration.value) + { + ec->result = GNUNET_TIME_absolute_min (expiration, + ec->result); + } + return GNUNET_SYSERR; + } + return GNUNET_YES; +} + + +static int +find_matching (void *cls, + const char *tname, + struct GNUNET_TIME_Absolute expiration, + const void *addr, uint16_t addrlen) +{ + struct EqualsContext *ec = cls; + + if (expiration.value < ec->expiration_limit.value) + return GNUNET_YES; + ec->tname = tname; + ec->expiration = expiration; + ec->addr = addr; + ec->addrlen = addrlen; + ec->found = GNUNET_NO; + GNUNET_HELLO_iterate_addresses (ec->h2, + GNUNET_NO, + &find_other_matching, + ec); + if (ec->found == GNUNET_NO) + { + ec->result = GNUNET_TIME_UNIT_ZERO_ABS; + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + +/** + * Test if two HELLO messages contain the same addresses. + * If they only differ in expiration time, the lowest + * expiration time larger than 'now' where they differ + * is returned. + * + * @param h1 first HELLO message + * @param h2 the second HELLO message + * @param now time to use for deciding which addresses have + * expired and should not be considered at all + * @return absolute time zero if the two HELLOs are + * totally identical; smallest timestamp >= now if + * they only differ in timestamps; + * forever if the some addresses with expirations >= now + * do not match at all + */ +struct GNUNET_TIME_Absolute +GNUNET_HELLO_equals (const struct + GNUNET_HELLO_Message *h1, + const struct + GNUNET_HELLO_Message *h2, + struct GNUNET_TIME_Absolute now) +{ + struct EqualsContext ec; + + ec.expiration_limit = now; + ec.result = GNUNET_TIME_UNIT_FOREVER_ABS; + ec.h2 = h2; + GNUNET_HELLO_iterate_addresses (h1, + GNUNET_NO, + &find_matching, + &ec); + if (ec.result.value == + GNUNET_TIME_UNIT_ZERO.value) + return ec.result; + ec.h2 = h1; + GNUNET_HELLO_iterate_addresses (h2, + GNUNET_NO, + &find_matching, + &ec); + return ec.result; +} + /* end of hello.c */