From c14ff64b5c9ca4cfc5004e30622499cc782694c5 Mon Sep 17 00:00:00 2001 From: Bart Polot Date: Fri, 31 Jul 2015 06:58:55 +0000 Subject: - refactor GCP_get_peer, fix get peer info --- src/cadet/cadet_api.c | 54 ++++++++++++++--- src/cadet/cadet_path.c | 7 ++- src/cadet/gnunet-cadet.c | 6 +- src/cadet/gnunet-service-cadet_channel.c | 2 +- src/cadet/gnunet-service-cadet_connection.c | 19 +++--- src/cadet/gnunet-service-cadet_dht.c | 2 +- src/cadet/gnunet-service-cadet_hello.c | 9 ++- src/cadet/gnunet-service-cadet_local.c | 92 ++++++++++++++++++++++------- src/cadet/gnunet-service-cadet_peer.c | 54 ++++++++++++++--- src/cadet/gnunet-service-cadet_peer.h | 48 ++++++++++++--- 10 files changed, 229 insertions(+), 64 deletions(-) (limited to 'src/cadet') diff --git a/src/cadet/cadet_api.c b/src/cadet/cadet_api.c index 055682d40..aaec91ede 100644 --- a/src/cadet/cadet_api.c +++ b/src/cadet/cadet_api.c @@ -1058,11 +1058,17 @@ static void process_get_peer (struct GNUNET_CADET_Handle *h, const struct GNUNET_MessageHeader *message) { - struct GNUNET_CADET_LocalInfoTunnel *msg; + struct GNUNET_CADET_LocalInfoPeer *msg; + struct GNUNET_PeerIdentity *id; + unsigned int epaths; + unsigned int paths; + unsigned int path_length; + unsigned int i; + int neighbor; size_t esize; size_t msize; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnel messasge received\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Info Peer messasge received\n"); if (NULL == h->info_cb.peer_cb) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ignored\n"); @@ -1070,17 +1076,34 @@ process_get_peer (struct GNUNET_CADET_Handle *h, } /* Verify message sanity */ - msg = (struct GNUNET_CADET_LocalInfoTunnel *) message; - msize = ntohs (message->size); - esize = sizeof (struct GNUNET_CADET_LocalInfoPeer); - if (esize > msize) + msg = (struct GNUNET_CADET_LocalInfoPeer *) message; + esize = ntohs (message->size); + msize = sizeof (struct GNUNET_CADET_LocalInfoPeer); + if (esize < msize) { GNUNET_break_op (0); h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL); goto clean_cls; } -// esize += ch_n * sizeof (CADET_ChannelNumber); -// esize += c_n * sizeof (struct GNUNET_CADET_Hash); + epaths = (unsigned int) ntohs (msg->paths); + paths = 0; + path_length = 0; + neighbor = GNUNET_NO; + id = (struct GNUNET_PeerIdentity *) &msg[1]; + for (i = 0; msize < esize; i++) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&id[i])); + msize += sizeof (struct GNUNET_PeerIdentity); + path_length++; + if (0 == memcmp (&id[i], &msg->destination, + sizeof (struct GNUNET_PeerIdentity))) + { + if (1 == path_length) + neighbor = GNUNET_YES; + path_length = 0; + paths++; + } + } if (msize != esize) { GNUNET_break_op (0); @@ -1088,9 +1111,22 @@ process_get_peer (struct GNUNET_CADET_Handle *h, h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL); goto clean_cls; } + if (paths != epaths) + { + GNUNET_break_op (0); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "p:%u, e: %u\n", paths, epaths); + h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL); + goto clean_cls; + } /* Call Callback with tunnel info. */ - h->info_cb.peer_cb (h->info_cls, &msg->destination, 0, 0, 0, NULL); + id = (struct GNUNET_PeerIdentity *) &msg[1]; + h->info_cb.peer_cb (h->info_cls, + &msg->destination, + (int) ntohs (msg->tunnel), + neighbor, + paths, + id); clean_cls: h->info_cb.peer_cb = NULL; diff --git a/src/cadet/cadet_path.c b/src/cadet/cadet_path.c index 4177d1529..0845f5a00 100644 --- a/src/cadet/cadet_path.c +++ b/src/cadet/cadet_path.c @@ -50,11 +50,12 @@ path_destroy_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) LOG (GNUNET_ERROR_TYPE_INFO, "Destroy delayed %p (%u)\n", path, path->length); path->path_delete = NULL; + /* During shutdown, the peers peermap might not exist anymore. */ if (2 < path->length && (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) == 0) { - /* During shutdown, the peers peermap might not exist anymore. */ - peer = GCP_get_short (path->peers[path->length - 1]); - GCP_remove_path (peer, path); + peer = GCP_get_short (path->peers[path->length - 1], GNUNET_NO); + if (NULL != peer) + GCP_remove_path (peer, path); } else path_destroy (path); diff --git a/src/cadet/gnunet-cadet.c b/src/cadet/gnunet-cadet.c index 7e6bf3fce..f0537adc6 100644 --- a/src/cadet/gnunet-cadet.c +++ b/src/cadet/gnunet-cadet.c @@ -515,15 +515,17 @@ peer_callback (void *cls, GNUNET_i2s_full (peer), tunnel ? "Y" : "N", neighbor ? "Y" : "N", n_paths); p = paths; - for (i = 0; i < n_paths && NULL != p; i++) + for (i = 0; i < n_paths && NULL != p;) { - FPRINTF (stdout, "%s ", GNUNET_i2s_full (p)); + FPRINTF (stdout, "%s ", GNUNET_i2s (p)); if (0 == memcmp (p, peer, sizeof (*p))) { FPRINTF (stdout, "\n"); + i++; } p++; } + GNUNET_SCHEDULER_shutdown(); } diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c index 234785732..158fc0ea6 100644 --- a/src/cadet/gnunet-service-cadet_channel.c +++ b/src/cadet/gnunet-service-cadet_channel.c @@ -1863,7 +1863,7 @@ GCCH_handle_local_create (struct CadetClient *c, return GNUNET_SYSERR; } - peer = GCP_get (&msg->peer); + peer = GCP_get (&msg->peer, GNUNET_YES); GCP_add_tunnel (peer); t = GCP_get_tunnel (peer); diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c index 97d184e8e..af1f03ee1 100644 --- a/src/cadet/gnunet-service-cadet_connection.c +++ b/src/cadet/gnunet-service-cadet_connection.c @@ -783,7 +783,7 @@ get_prev_hop (const struct CadetConnection *c) LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); - return GCP_get_short (id); + return GCP_get_short (id, GNUNET_YES); } @@ -812,7 +812,7 @@ get_next_hop (const struct CadetConnection *c) LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); - return GCP_get_short (id); + return GCP_get_short (id, GNUNET_YES); } @@ -1038,7 +1038,8 @@ send_broken_unknown (const struct GNUNET_CADET_Hash *connection_id, msg->peer2 = *id2; else memset (&msg->peer2, 0, sizeof (msg->peer2)); - neighbor = GCP_get (peer_id); + neighbor = GCP_get (peer_id, GNUNET_NO); /* We MUST know neighbor. */ + GNUNET_assert (NULL != neighbor); GCP_queue_add (neighbor, msg, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 0, 2, sizeof (struct GNUNET_CADET_ConnectionBroken), NULL, GNUNET_SYSERR, /* connection, fwd */ @@ -1777,7 +1778,9 @@ does_connection_exist (struct CadetConnection *conn) struct CadetTunnel *t; struct CadetConnection *c; - p = GCP_get_short (conn->path->peers[0]); + p = GCP_get_short (conn->path->peers[0], GNUNET_NO); + if (NULL == p) + return GNUNET_NO; t = GCP_get_tunnel (p); if (NULL == t) return GNUNET_NO; @@ -1967,8 +1970,8 @@ GCC_handle_create (void *cls, connection_change_state (c, CADET_CONNECTION_SENT); /* Remember peers */ - dest_peer = GCP_get (&id[size - 1]); - orig_peer = GCP_get (&id[0]); + dest_peer = GCP_get (&id[size - 1], GNUNET_YES); + orig_peer = GCP_get (&id[0], GNUNET_YES); /* Is it a connection to us? */ if (c->own_pos == path->length - 1) @@ -2056,7 +2059,7 @@ GCC_handle_confirm (void *cls, oldstate = c->state; LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", GNUNET_i2s (peer)); - pi = GCP_get (peer); + pi = GCP_get (peer, GNUNET_YES); if (get_next_hop (c) == pi) { LOG (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n"); @@ -2194,7 +2197,7 @@ GCC_handle_broken (void* cls, GCC_debug (c, GNUNET_ERROR_TYPE_ERROR); return GNUNET_OK; } - endpoint = GCP_get_short (c->path->peers[c->path->length - 1]); + endpoint = GCP_get_short (c->path->peers[c->path->length - 1], GNUNET_YES); if (2 < c->path->length) path_invalidate (c->path); GCP_notify_broken_link (endpoint, &msg->peer1, &msg->peer2); diff --git a/src/cadet/gnunet-service-cadet_dht.c b/src/cadet/gnunet-service-cadet_dht.c index 81051a700..cdc1f5a7f 100644 --- a/src/cadet/gnunet-service-cadet_dht.c +++ b/src/cadet/gnunet-service-cadet_dht.c @@ -187,7 +187,7 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, s = path_2s (p); LOG (GNUNET_ERROR_TYPE_INFO, "Got path from DHT: %s\n", s); GNUNET_free_non_null (s); - peer = GCP_get_short (p->peers[p->length - 1]); + peer = GCP_get_short (p->peers[p->length - 1], GNUNET_YES); LOG (GNUNET_ERROR_TYPE_DEBUG, "Got HELLO for %s\n", GCP_2s (peer)); h->callback (h->cls, p); path_destroy (p); diff --git a/src/cadet/gnunet-service-cadet_hello.c b/src/cadet/gnunet-service-cadet_hello.c index 9229483fe..19b45c9cd 100644 --- a/src/cadet/gnunet-service-cadet_hello.c +++ b/src/cadet/gnunet-service-cadet_hello.c @@ -108,7 +108,7 @@ got_hello (void *cls, const struct GNUNET_PeerIdentity *id, LOG (GNUNET_ERROR_TYPE_DEBUG, " hello for %s (%d bytes), expires on %s\n", GNUNET_i2s (id), GNUNET_HELLO_size (hello), GNUNET_STRINGS_absolute_time_to_string (GNUNET_HELLO_get_last_expiration(hello))); - peer = GCP_get (id); + peer = GCP_get (id, GNUNET_YES); GCP_set_hello (peer, hello); if (GCP_get_short_id (peer) == myid) @@ -176,7 +176,12 @@ GCH_get_mine (void) const struct GNUNET_HELLO_Message * GCH_get (const struct GNUNET_PeerIdentity *id) { - return GCP_get_hello (GCP_get (id)); + struct CadetPeer *p; + + p = GCP_get (id, GNUNET_NO); + if (NULL == p) + return NULL; + return GCP_get_hello (p); } diff --git a/src/cadet/gnunet-service-cadet_local.c b/src/cadet/gnunet-service-cadet_local.c index f2be87dfb..9c39ac6c6 100644 --- a/src/cadet/gnunet-service-cadet_local.c +++ b/src/cadet/gnunet-service-cadet_local.c @@ -671,6 +671,61 @@ show_peer_iterator (void *cls, } +/** + * Iterator over all paths of a peer to build an InfoPeer message. + * + * Message contains blocks of peers, first not included. + * + * @param cls Closure (message to build). + * @param peer Peer this path is towards. + * @param path Path itself + * @return #GNUNET_YES if should keep iterating. + * #GNUNET_NO otherwise. + */ +static int +path_info_iterator (void *cls, + struct CadetPeer *peer, + struct CadetPeerPath *path) +{ + struct GNUNET_CADET_LocalInfoPeer *resp = cls; + struct GNUNET_PeerIdentity *id; + uint16_t msg_size; + uint16_t path_size; + unsigned int i; + + msg_size = ntohs (resp->header.size); + path_size = sizeof (struct GNUNET_PeerIdentity) * (path->length - 1); + + LOG (GNUNET_ERROR_TYPE_DEBUG, "Info Path %u\n", path->length); + if (msg_size + path_size > UINT16_MAX) + { + LOG (GNUNET_ERROR_TYPE_WARNING, "path too long for info message\n"); + return GNUNET_NO; + } + + i = msg_size - sizeof (struct GNUNET_CADET_LocalInfoPeer); + i = i / sizeof (struct GNUNET_PeerIdentity); + + /* Set id to the address of the first free peer slot. */ + id = (struct GNUNET_PeerIdentity *) &resp[1]; + id = &id[i]; + + /* Don't copy first peers. + * First peer is always the local one. + * Last peer is always the destination (leave as 0, EOL). + */ + for (i = 0; i < path->length - 1; i++) + { + GNUNET_PEER_resolve (path->peers[i + 1], &id[i]); + LOG (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&id[i])); + } + + resp->header.size = htons (msg_size + path_size); + + return GNUNET_YES; +} + + /** * Handler for client's INFO PEERS request. * @@ -723,7 +778,7 @@ handle_show_peer (void *cls, struct GNUNET_SERVER_Client *client, struct GNUNET_CADET_LocalInfoPeer *resp; struct CadetPeer *p; struct CadetClient *c; - size_t size; + unsigned char cbuf[64 * 1024]; /* Sanity check for client registration */ if (NULL == (c = GML_client_get (client))) @@ -734,44 +789,37 @@ handle_show_peer (void *cls, struct GNUNET_SERVER_Client *client, } msg = (struct GNUNET_CADET_LocalInfo *) message; + resp = (struct GNUNET_CADET_LocalInfoPeer *) cbuf; LOG (GNUNET_ERROR_TYPE_INFO, "Received peer info request from client %u for peer %s\n", c->id, GNUNET_i2s_full (&msg->peer)); - p = GCP_get (&msg->peer); + resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); + resp->header.size = htons (sizeof (struct GNUNET_CADET_LocalInfoPeer)); + resp->destination = msg->peer; + p = GCP_get (&msg->peer, GNUNET_NO); if (NULL == p) { /* We don't know the peer */ - struct GNUNET_CADET_LocalInfoPeer warn; - LOG (GNUNET_ERROR_TYPE_INFO, "Peer %s unknown %u\n", - GNUNET_i2s_full (&msg->peer), sizeof (warn)); - warn.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); - warn.header.size = htons (sizeof (warn)); - warn.destination = msg->peer; - warn.paths = htons (0); - warn.tunnel = htons (NULL != GCP_get_tunnel (p)); + LOG (GNUNET_ERROR_TYPE_INFO, "Peer %s unknown\n", + GNUNET_i2s_full (&msg->peer)); + resp->paths = htons (0); + resp->tunnel = htons (NULL != GCP_get_tunnel (p)); GNUNET_SERVER_notification_context_unicast (nc, client, - &warn.header, + &resp->header, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } - size = sizeof (struct GNUNET_CADET_LocalInfoPeer); -// size += c_n * sizeof (struct GNUNET_CADET_Hash); - - resp = GNUNET_malloc (size); - resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); - resp->header.size = htons (size); - resp->destination = msg->peer; - resp->paths = htons (0); - resp->tunnel = htons (0); + resp->paths = htons (GCP_count_paths (p)); + resp->tunnel = htons (NULL != GCP_get_tunnel (p)); + GCP_iterate_paths (p, &path_info_iterator, resp); GNUNET_SERVER_notification_context_unicast (nc, c->handle, &resp->header, GNUNET_NO); - GNUNET_free (resp); LOG (GNUNET_ERROR_TYPE_INFO, "Show peer request from client %u completed.\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); @@ -904,7 +952,7 @@ handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, "Received tunnel info request from client %u for tunnel %s\n", c->id, GNUNET_i2s_full(&msg->peer)); - t = GCP_get_tunnel (GCP_get (&msg->peer)); + t = GCP_get_tunnel (GCP_get (&msg->peer, GNUNET_NO)); if (NULL == t) { /* We don't know the tunnel */ diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c index 66b1b8ff3..4d3eccc53 100644 --- a/src/cadet/gnunet-service-cadet_peer.c +++ b/src/cadet/gnunet-service-cadet_peer.c @@ -414,7 +414,7 @@ core_connect (void *cls, sizeof (own_id), "%s", GNUNET_i2s (&my_full_id)); - mp = GCP_get (peer); + mp = GCP_get (peer, GNUNET_YES); if (myid == mp->id) { LOG (GNUNET_ERROR_TYPE_INFO, @@ -1817,15 +1817,18 @@ GCP_shutdown (void) /** - * Retrieve the CadetPeer stucture associated with the peer, create one - * and insert it in the appropriate structures if the peer is not known yet. + * Retrieve the CadetPeer stucture associated with the peer. Optionally create + * one and insert it in the appropriate structures if the peer is not known yet. * * @param peer_id Full identity of the peer. + * @param create #GNUNET_YES if a new peer should be created if unknown. + * #GNUNET_NO otherwise. * * @return Existing or newly created peer structure. + * NULL if unknown and not requested @a create */ struct CadetPeer * -GCP_get (const struct GNUNET_PeerIdentity *peer_id) +GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create) { struct CadetPeer *peer; @@ -1851,17 +1854,20 @@ GCP_get (const struct GNUNET_PeerIdentity *peer_id) /** - * Retrieve the CadetPeer stucture associated with the peer, create one - * and insert it in the appropriate structures if the peer is not known yet. + * Retrieve the CadetPeer stucture associated with the peer. Optionally create + * one and insert it in the appropriate structures if the peer is not known yet. * * @param peer Short identity of the peer. + * @param create #GNUNET_YES if a new peer should be created if unknown. + * #GNUNET_NO otherwise. * * @return Existing or newly created peer structure. + * NULL if unknown and not requested @a create */ struct CadetPeer * -GCP_get_short (const GNUNET_PEER_Id peer) +GCP_get_short (const GNUNET_PEER_Id peer, int create) { - return GCP_get (GNUNET_PEER_resolve2 (peer)); + return GCP_get (GNUNET_PEER_resolve2 (peer), create); } @@ -2199,7 +2205,7 @@ GCP_add_path_to_all (const struct CadetPeerPath *p, int confirmed) struct CadetPeer *aux; struct CadetPeerPath *copy; - aux = GCP_get_short (p->peers[i]); + aux = GCP_get_short (p->peers[i], GNUNET_YES); copy = path_duplicate (p); copy->length = i + 1; GCP_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed); @@ -2417,6 +2423,8 @@ GCP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel *t) struct CadetTunnel * GCP_get_tunnel (const struct CadetPeer *peer) { + if (NULL == peer) + return NULL; return peer->tunnel; } @@ -2582,6 +2590,34 @@ GCP_count_paths (const struct CadetPeer *peer) } +/** + * Iterate over the paths to a peer. + * + * @param peer Peer to get path info. + * @param callback Function to call for every path. + * @param cls Closure for @a callback. + * + * @return Number of iterated paths. + */ +unsigned int +GCP_iterate_paths (struct CadetPeer *peer, + GCP_path_iterator callback, + void *cls) +{ + struct CadetPeerPath *iter; + unsigned int i; + + for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next) + { + i++; + if (GNUNET_YES != callback (cls, peer, iter)) + break; + } + + return i; +} + + /** * Iterate all known peers. * diff --git a/src/cadet/gnunet-service-cadet_peer.h b/src/cadet/gnunet-service-cadet_peer.h index 87e828b66..7a60b33bd 100644 --- a/src/cadet/gnunet-service-cadet_peer.h +++ b/src/cadet/gnunet-service-cadet_peer.h @@ -39,6 +39,7 @@ extern "C" #include "platform.h" #include "gnunet_util_lib.h" +#include "cadet_path.h" /** * Struct containing all information regarding a given peer @@ -72,6 +73,20 @@ typedef int uint16_t type, uint32_t pid, int fwd, size_t size, struct GNUNET_TIME_Relative wait); +/** + * Peer path iterator. + * + * @param cls Closure. + * @param peer Peer this path is towards. + * @param path Path itself + * @return #GNUNET_YES if should keep iterating. + * #GNUNET_NO otherwise. + */ +typedef int +(*GCP_path_iterator) (void *cls, + struct CadetPeer *peer, + struct CadetPeerPath *path); + /******************************************************************************/ /******************************** API ***********************************/ @@ -93,27 +108,32 @@ GCP_shutdown (void); /** - * Retrieve the CadetPeer stucture associated with the peer, create one - * and insert it in the appropriate structures if the peer is not known yet. + * Retrieve the CadetPeer stucture associated with the peer. Optionally create + * one and insert it in the appropriate structures if the peer is not known yet. * * @param peer_id Full identity of the peer. + * @param create #GNUNET_YES if a new peer should be created if unknown. + * #GNUNET_NO otherwise. * * @return Existing or newly created peer structure. + * NULL if unknown and not requested @a create */ struct CadetPeer * -GCP_get (const struct GNUNET_PeerIdentity *peer_id); - +GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create); /** - * Retrieve the CadetPeer stucture associated with the peer, create one - * and insert it in the appropriate structures if the peer is not known yet. + * Retrieve the CadetPeer stucture associated with the peer. Optionally create + * one and insert it in the appropriate structures if the peer is not known yet. * * @param peer Short identity of the peer. + * @param create #GNUNET_YES if a new peer should be created if unknown. + * #GNUNET_NO otherwise. * * @return Existing or newly created peer structure. + * NULL if unknown and not requested @a create */ struct CadetPeer * -GCP_get_short (const GNUNET_PEER_Id peer); +GCP_get_short (const GNUNET_PEER_Id peer, int create); /** * Try to establish a new connection to this peer (in its tunnel). @@ -444,6 +464,20 @@ GCP_notify_broken_link (struct CadetPeer *peer, unsigned int GCP_count_paths (const struct CadetPeer *peer); +/** + * Iterate over the paths to a peer. + * + * @param peer Peer to get path info. + * @param callback Function to call for every path. + * @param cls Closure for @a callback. + * + * @return Number of iterated paths. + */ +unsigned int +GCP_iterate_paths (struct CadetPeer *peer, + GCP_path_iterator callback, + void *cls); + /** * Iterate all known peers. -- cgit v1.2.3