From 2e9731ebda48bf2549aed64ca9cdfea5b298f9d7 Mon Sep 17 00:00:00 2001 From: Bart Polot Date: Thu, 13 Oct 2011 13:44:18 +0000 Subject: Extended testcase, fixed bugs in client -> service data traffic handling --- src/mesh/gnunet-service-mesh.c | 31 +++++++---- src/mesh/mesh_api_new.c | 25 +++++++-- src/mesh/mesh_tunnel_tree.c | 22 +++----- src/mesh/mesh_tunnel_tree.h | 13 +++++ src/mesh/test_mesh_small_unicast.c | 109 +++++++++++++++++++++++++++++++++---- 5 files changed, 159 insertions(+), 41 deletions(-) (limited to 'src/mesh') diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index cff27272c..a19aa268d 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c @@ -1427,10 +1427,14 @@ tunnel_add_path (struct MeshTunnel *t, struct MeshPeerPath *p, unsigned int own_pos) { + struct GNUNET_PeerIdentity id; + GNUNET_assert (0 != own_pos); tree_add_path(t->tree, p, NULL); if (NULL == t->tree->me) t->tree->me = tree_find_peer(t->tree->root, p->peers[own_pos]); + GNUNET_PEER_resolve (p->peers[own_pos + 1], &id); + tree_update_first_hops(t->tree, t->tree->me, &id); } @@ -2028,9 +2032,12 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, { struct GNUNET_MESH_Unicast *msg; struct MeshTunnel *t; - struct MeshPeerInfo *pi; + GNUNET_PEER_Id pid; size_t size; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MESH: got a unicast packet from %s\n", + GNUNET_i2s (peer)); size = ntohs (message->size); if (size < sizeof (struct GNUNET_MESH_Unicast) + @@ -2047,24 +2054,21 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, GNUNET_break_op (0); return GNUNET_OK; } - pi = GNUNET_CONTAINER_multihashmap_get (t->peers, - &msg->destination.hashPubKey); - if (NULL == pi) - { - /* TODO maybe feedback, log to statistics */ - GNUNET_break_op (0); - return GNUNET_OK; - } - if (pi->id == myid) + pid = GNUNET_PEER_search(&msg->destination); + if (pid == myid) { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MESH: it's for us! sending to clients...\n"); send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]); return GNUNET_OK; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MESH: not for us, retransmitting...\n"); msg = GNUNET_malloc (size); memcpy (msg, message, size); GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, GNUNET_TIME_UNIT_FOREVER_REL, - path_get_first_hop (t->tree, pi->id), + path_get_first_hop (t->tree, pid), size, &send_core_data_raw, msg); return GNUNET_OK; @@ -3125,6 +3129,9 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client, MESH_TunnelNumber tid; size_t size; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MESH: Got a unicast request from a client!\n"); + /* Sanity check for client registration */ if (NULL == (c = client_get (client))) { @@ -3183,6 +3190,8 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client, memcpy (buf, data_msg, size); copy->oid = my_full_id; copy->tid = htonl (t->id.tid); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MESH: calling generic handler...\n"); handle_mesh_data_unicast (NULL, &my_full_id, ©->header, NULL); } GNUNET_SERVER_receive_done (client, GNUNET_OK); diff --git a/src/mesh/mesh_api_new.c b/src/mesh/mesh_api_new.c index d3ce0b2ae..ff655166d 100644 --- a/src/mesh/mesh_api_new.c +++ b/src/mesh/mesh_api_new.c @@ -1044,7 +1044,7 @@ send_callback (void *cls, size_t size, void *buf) /* multicast */ struct GNUNET_MESH_Multicast mc; - GNUNET_assert (size >= sizeof (mc) + th->size); + GNUNET_assert (size >= th->size); psize = th->notify (th->notify_cls, size - sizeof (mc), &cbuf[sizeof (mc)]); if (psize > 0) @@ -1054,7 +1054,7 @@ send_callback (void *cls, size_t size, void *buf) mc.tid = htonl (th->tunnel->tid); memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity)); memcpy (cbuf, &mc, sizeof (mc)); - psize = th->size + sizeof (mc); + psize += sizeof (mc); } } else @@ -1062,18 +1062,18 @@ send_callback (void *cls, size_t size, void *buf) /* unicast */ struct GNUNET_MESH_Unicast uc; - GNUNET_assert (size >= sizeof (uc) + th->size); + GNUNET_assert (size >= th->size); psize = th->notify (th->notify_cls, size - sizeof (uc), &cbuf[sizeof (uc)]); if (psize > 0) { - uc.header.size = htons (sizeof (uc) + th->size); + uc.header.size = htons (th->size); uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST); uc.tid = htonl (th->tunnel->tid); memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity)); GNUNET_PEER_resolve (th->target, &uc.destination); memcpy (cbuf, &uc, sizeof (uc)); - psize = th->size + sizeof (uc); + psize += sizeof (uc); } } } @@ -1434,6 +1434,12 @@ GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork, uint32_t least_priority; size_t overhead; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "mesh: mesh notify transmit ready called\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "mesh: target %s\n", + GNUNET_i2s (target)); + GNUNET_assert (NULL != notify); if (tunnel->mesh->npackets >= tunnel->mesh->max_queue_size && tunnel->npackets > 0) @@ -1481,6 +1487,15 @@ GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork, th->notify = notify; th->notify_cls = notify_cls; add_to_queue (tunnel->mesh, th); + if (NULL != tunnel->mesh->th) + return th; + tunnel->mesh->th = + GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, + th->size, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_YES, + &send_callback, + tunnel->mesh); return th; } diff --git a/src/mesh/mesh_tunnel_tree.c b/src/mesh/mesh_tunnel_tree.c index 7ad5bfbd7..b2c03247e 100644 --- a/src/mesh/mesh_tunnel_tree.c +++ b/src/mesh/mesh_tunnel_tree.c @@ -336,7 +336,7 @@ tree_mark_peers_disconnected (struct MeshTunnelTree *tree, * @param hop If known, ID of the first hop. * If not known, NULL to find out and pass on children. */ -static void +void tree_update_first_hops (struct MeshTunnelTree *tree, struct MeshTunnelTreeNode *parent, struct GNUNET_PeerIdentity *hop) @@ -486,6 +486,7 @@ tree_get_path_to_peer(struct MeshTunnelTree *t, GNUNET_PEER_Id peer) } + /** * Integrate a stand alone path into the tunnel tree. * If the peer toward which the new path is already in the tree, the peer @@ -516,7 +517,6 @@ tree_add_path (struct MeshTunnelTree *t, struct MeshTunnelTreeNode *n; struct MeshTunnelTreeNode *c; struct GNUNET_PeerIdentity id; - struct GNUNET_PeerIdentity *hop; GNUNET_PEER_Id myid; int me; unsigned int i; @@ -604,20 +604,12 @@ tree_add_path (struct MeshTunnelTree *t, n->status = MESH_PEER_SEARCHING; /* Add info about first hop into hashmap. */ - if (me < p->length - 1) + if (-1 != me && me < p->length - 1) { - GNUNET_PEER_resolve (p->peers[p->length - 1], &id); - hop = GNUNET_CONTAINER_multihashmap_get(t->first_hops, &id.hashPubKey); - if (NULL != hop) - { - GNUNET_CONTAINER_multihashmap_remove_all(t->first_hops, &id.hashPubKey); - GNUNET_free(hop); - } - hop = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity)); - GNUNET_PEER_resolve (p->peers[me + 1], hop); - GNUNET_CONTAINER_multihashmap_put (t->first_hops, &id.hashPubKey, - hop, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); + GNUNET_PEER_resolve (p->peers[me + 1], &id); + tree_update_first_hops(t, + tree_find_peer(t->root, p->peers[p->length - 1]), + &id); } GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "tree: New node added.\n"); return GNUNET_OK; diff --git a/src/mesh/mesh_tunnel_tree.h b/src/mesh/mesh_tunnel_tree.h index 509d254a1..82a1d1d1b 100644 --- a/src/mesh/mesh_tunnel_tree.h +++ b/src/mesh/mesh_tunnel_tree.h @@ -266,6 +266,19 @@ tree_find_peer (struct MeshTunnelTreeNode *parent, GNUNET_PEER_Id peer); +/** + * Recusively update the info about what is the first hop to reach the node + * + * @param tree Tree this nodes belongs to + * @param parent Node to be start updating + * @param hop If known, ID of the first hop. + * If not known, NULL to find out and pass on children. + */ +void +tree_update_first_hops (struct MeshTunnelTree *tree, + struct MeshTunnelTreeNode *parent, + struct GNUNET_PeerIdentity *hop); + /** * Delete the current path to the peer, including all now unused relays. * The destination peer is NOT destroyed, it is returned in order to either set diff --git a/src/mesh/test_mesh_small_unicast.c b/src/mesh/test_mesh_small_unicast.c index 5660dc0b0..2aee7ad6b 100644 --- a/src/mesh/test_mesh_small_unicast.c +++ b/src/mesh/test_mesh_small_unicast.c @@ -57,7 +57,7 @@ struct StatsContext */ #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) -#define OK_GOAL 2 +#define OK_GOAL 4 static int ok; @@ -137,6 +137,8 @@ static struct GNUNET_MESH_Handle *h2; static struct GNUNET_MESH_Tunnel *t; +static struct GNUNET_MESH_Tunnel *incoming_t; + static uint16_t *mesh_peers; /** @@ -181,11 +183,77 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } +/** + * Transmit ready callback + */ +size_t +tmt_rdy (void *cls, size_t size, void *buf) +{ + struct GNUNET_MessageHeader *msg = buf; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: tmt_rdy called\n"); + if (size < sizeof(struct GNUNET_MessageHeader) || NULL == buf) + return 0; + msg->size = htons (sizeof(struct GNUNET_MessageHeader)); + msg->type = htonl ((long) cls); + return sizeof(struct GNUNET_MessageHeader); +} + + +/** + * Function is called whenever a message is received. + * + * @param cls closure (set from GNUNET_MESH_connect) + * @param tunnel connection to the other end + * @param tunnel_ctx place to store local state associated with the tunnel + * @param sender who sent the message + * @param message the actual message + * @param atsi performance data for the connection + * @return GNUNET_OK to keep the connection open, + * GNUNET_SYSERR to close it (signal serious error) + */ +int +data_callback (void *cls, + struct GNUNET_MESH_Tunnel * tunnel, + void **tunnel_ctx, + const struct GNUNET_PeerIdentity *sender, + const struct GNUNET_MessageHeader *message, + const struct GNUNET_TRANSPORT_ATS_Information *atsi) +{ + long client = (long) cls; + + switch (client) + { + case 1L: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "test: Origin client got a response!\n"); + ok++; + break; + case 2L: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "test: Destination client got a message \n"); + ok++; + GNUNET_MESH_notify_transmit_ready(incoming_t, + GNUNET_NO, + 0, + GNUNET_TIME_UNIT_FOREVER_REL, + sender, + sizeof(struct GNUNET_MessageHeader), + &tmt_rdy, + (void *) 1L); + break; + default: + break; + } + return GNUNET_OK; +} + + /** * Handlers, for diverse services */ static struct GNUNET_MESH_MessageHandler handlers[] = { -// {&callback, 1, 0}, + {&data_callback, 1, sizeof(struct GNUNET_MessageHeader)}, {NULL, 0, 0} }; @@ -224,6 +292,7 @@ incoming_tunnel (void *cls, "test: Incoming tunnel from %s\n", GNUNET_i2s(initiator)); ok++; + incoming_t = tunnel; GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = GNUNET_SCHEDULER_add_delayed(SHORT_TIME, &disconnect_mesh_peers, @@ -251,6 +320,7 @@ tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, return; } + /** * Method called whenever a tunnel falls apart. * @@ -263,8 +333,6 @@ dh (void *cls, const struct GNUNET_PeerIdentity *peer) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer %s disconnected\n", GNUNET_i2s(peer)); - if (memcmp(&d2->id, peer, sizeof(d2->id))) - ok++; return; } @@ -283,6 +351,24 @@ ch (void *cls, const struct GNUNET_PeerIdentity *peer, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer %s connected\n", GNUNET_i2s(peer)); + if (0 == memcmp(&d2->id, peer, sizeof(d2->id)) && (long) cls == 1L) + ok++; + if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) + { + GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = GNUNET_SCHEDULER_add_delayed(SHORT_TIME, + &disconnect_mesh_peers, + NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Sending data unicast...\n"); + GNUNET_MESH_notify_transmit_ready(t, + GNUNET_NO, + 0, + GNUNET_TIME_UNIT_FOREVER_REL, + &d2->id, + sizeof(struct GNUNET_MessageHeader), + &tmt_rdy, + (void *) 1L); + } return; } @@ -388,14 +474,14 @@ connect_mesh_service (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) #endif h1 = GNUNET_MESH_connect (d1->cfg, 10, - NULL, + (void *) 1L, NULL, &tunnel_cleaner, handlers, &app); h2 = GNUNET_MESH_connect (d2->cfg, 10, - NULL, + (void *) 2L, &incoming_tunnel, &tunnel_cleaner, handlers, @@ -408,7 +494,7 @@ connect_mesh_service (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) "test: connected to mesh service of peer %s\n", GNUNET_i2s (&d2->id)); #endif - t = GNUNET_MESH_tunnel_create (h1, NULL, &ch, &dh, NULL); + t = GNUNET_MESH_tunnel_create (h1, NULL, &ch, &dh, (void *) 1L); test_task = GNUNET_SCHEDULER_add_delayed( GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 6), @@ -664,16 +750,19 @@ int main (int argc, char *argv[]) { GNUNET_PROGRAM_run (argc, argv, "test_mesh_small_unicast", - gettext_noop ("Test mesh unicast in a small network."), options, - &run, NULL); + gettext_noop ("Test mesh unicast in a small network."), + options, &run, NULL); #if REMOVE_DIR GNUNET_DISK_directory_remove ("/tmp/test_mesh_small_unicast"); #endif if (OK_GOAL != ok) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: FAILED!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "test: FAILED! (%d/%d)\n", + ok, OK_GOAL); return 1; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: success\n"); return 0; } -- cgit v1.2.3