X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmesh%2Fgnunet-service-mesh.c;h=63700504860f550761679d45ac7bb822cfb332f4;hb=7c6b8edcc300e1be76803a9b80bfd720ddf0283a;hp=f1bef6b4df8e725c49236d33763282a00981b83d;hpb=3937c27e06bcc2d59f9a00a959a0375c282d71e6;p=oweals%2Fgnunet.git diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index f1bef6b4d..637005048 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c @@ -41,6 +41,7 @@ * - speed requirement specification (change?) in mesh API -- API call * - add ping message * - relay corking down to core + * - set ttl relative to tree depth */ #include "platform.h" @@ -68,9 +69,12 @@ #define UNACKNOWLEDGED_WAIT GNUNET_TIME_relative_multiply(\ GNUNET_TIME_UNIT_SECONDS,\ 2) +#define DEFAULT_TTL 64 #define MESH_DEBUG_DHT GNUNET_NO + + /******************************************************************************/ /************************ DATA STRUCTURES ****************************/ /******************************************************************************/ @@ -78,39 +82,50 @@ /** FWD declaration */ struct MeshPeerInfo; + +/** + * Struct representing a piece of data being sent to other peers + */ +struct MeshData +{ + /** Tunnel it belongs to. */ + struct MeshTunnel *t; + + /** In case of a multicast, task to allow a client to send more data if + * some neighbor is too slow. */ + GNUNET_SCHEDULER_TaskIdentifier *task; + + /** How many remaining neighbors we need to send this to. */ + unsigned int *reference_counter; + + /** Size of the data. */ + size_t data_len; + + /** Data itself */ + void *data; +}; + + /** * Struct containing all info possibly needed to build a package when called * back by core. */ -struct MeshDataDescriptor +struct MeshTransmissionDescriptor { /** ID of the tunnel this packet travels in */ struct MESH_TunnelID *origin; - /** Data itself */ - void *data; - - /** Client that asked for the transmission, if any */ - struct GNUNET_SERVER_Client *client; - /** Who was this message being sent to */ struct MeshPeerInfo *peer; /** Ultimate destination of the packet */ GNUNET_PEER_Id destination; - /** Number of identical messages sent to different hops (multicast) */ - unsigned int *copies; - /** Which handler was used to request the transmission */ unsigned int handler_n; - /** Size of the data */ - size_t size; - - /** Used to allow a client send more traffic to the service after a - * previous packet was tried to be sent to a neighbor and couldn't */ - GNUNET_SCHEDULER_TaskIdentifier *timeout_task; + /** Data descriptor */ + struct MeshData* mesh_data; }; @@ -261,6 +276,16 @@ struct MeshTunnel */ MESH_TunnelNumber local_tid; + /** + * Local tunnel number for local destination clients + */ + MESH_TunnelNumber local_tid_dest; + + /** + * ID of the last multicast packet seen/sent. + */ + uint32_t mid; + /** * Last time the tunnel was used */ @@ -396,7 +421,7 @@ struct MeshClient /************************ DEBUG FUNCTIONS ****************************/ /******************************************************************************/ - +#if MESH_DEBUG /** * GNUNET_SCHEDULER_Task for printing a message after some operation is done * @param cls string to print @@ -413,7 +438,7 @@ mesh_debug (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: %s\n", s); } - +#endif /******************************************************************************/ /*********************** GLOBAL VARIABLES ****************************/ @@ -714,17 +739,18 @@ client_is_subscribed (uint16_t message_type, struct MeshClient *c) static void client_allow_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct MeshDataDescriptor *info = cls; + struct MeshData *mdata = cls; if (GNUNET_SCHEDULER_REASON_SHUTDOWN == tc->reason) return; #if MESH_DEBUG + GNUNET_assert (NULL != mdata->reference_counter); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CLIENT ALLOW SEND DESPITE %u COPIES PENDING\n", - *(info->copies)); + mdata->reference_counter); #endif - *(info->timeout_task) = GNUNET_SCHEDULER_NO_TASK; - GNUNET_SERVER_receive_done (info->client, GNUNET_OK); + *(mdata->task) = GNUNET_SCHEDULER_NO_TASK; + GNUNET_SERVER_receive_done (mdata->t->client->handle, GNUNET_OK); } @@ -760,6 +786,7 @@ tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1, * Send the message to all clients that have subscribed to its type * * @param msg Pointer to the message itself + * @param payload Pointer to the payload of the message. * @return number of clients this message was sent to */ static unsigned int @@ -774,9 +801,11 @@ send_subscribed_clients (const struct GNUNET_MessageHeader *msg, uint16_t type; char cbuf[htons (msg->size)]; +#if MESH_DEBUG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Sending to clients...\n"); type = ntohs (payload->type); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: message of type %u\n", type); +#endif memcpy (cbuf, msg, sizeof (cbuf)); switch (htons (msg->type)) @@ -810,10 +839,16 @@ send_subscribed_clients (const struct GNUNET_MessageHeader *msg, GNUNET_break (0); return 0; } - *tid = htonl (t->local_tid); + // FIXME proper client differentiation mechanism required + if (htons (msg->type) == GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN) + *tid = htonl (t->local_tid); + else + *tid = htonl (t->local_tid_dest != 0 ? t->local_tid_dest : t->local_tid); for (count = 0, c = clients; c != NULL; c = c->next) { +#if MESH_DEBUG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: client %u\n", c->id); +#endif if (client_is_subscribed (type, c)) { count++; @@ -900,29 +935,30 @@ send_core_data_multicast (void *cls, size_t size, void *buf); /** * Decrements the reference counter and frees all resources if needed * - * @param dd Data Descriptor used in a multicast message + * @param dd Data Descriptor used in a multicast message. Freed if needed. */ static void -data_descriptor_decrement_multicast (struct MeshDataDescriptor *dd) +data_descriptor_decrement_multicast (struct MeshData *mesh_data) { - if (0 == --(*(dd->copies))) + /* Make sure it's a multicast packet */ + GNUNET_assert (NULL != mesh_data->reference_counter); + + if (0 == --(*(mesh_data->reference_counter))) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Last copy!\n"); - if (NULL != dd->client) + if (NULL != mesh_data->task) { - if (GNUNET_SCHEDULER_NO_TASK != *(dd->timeout_task)) + if (GNUNET_SCHEDULER_NO_TASK != *(mesh_data->task)) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "MESH: cancelling client timeout (%u)...\n", - *(dd->timeout_task)); - GNUNET_SCHEDULER_cancel (*(dd->timeout_task)); + GNUNET_SCHEDULER_cancel (*(mesh_data->task)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: notifying client...\n"); - GNUNET_SERVER_receive_done (dd->client, GNUNET_OK); + GNUNET_SERVER_receive_done (mesh_data->t->client->handle, GNUNET_OK); } - GNUNET_free (dd->timeout_task); + GNUNET_free (mesh_data->task); } - GNUNET_free (dd->copies); - GNUNET_free (dd->data); + GNUNET_free (mesh_data->reference_counter); + GNUNET_free (mesh_data->data); + GNUNET_free (mesh_data); } } @@ -939,7 +975,7 @@ peer_info_cancel_transmission (struct MeshPeerInfo *peer, unsigned int i) { if (NULL != peer->core_transmit[i]) { - struct MeshDataDescriptor *dd; + struct MeshTransmissionDescriptor *dd; struct MeshPathInfo *path_info; #if MESH_DEBUG @@ -962,7 +998,7 @@ peer_info_cancel_transmission (struct MeshPeerInfo *peer, unsigned int i) case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: type payload\n"); dd = peer->infos[i]; - data_descriptor_decrement_multicast (dd); + data_descriptor_decrement_multicast (dd->mesh_data); break; case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: type create path\n"); @@ -1087,7 +1123,7 @@ peer_info_delete_tunnel (void *cls, const GNUNET_HashCode * key, void *value) /** * Core callback to write a * - * @param cls Closure (MeshDataDescriptor with data in "data" member). + * @param cls Closure (MeshTransmissionDescriptor with data in "data" member). * @param size Number of bytes available in buf. * @param buf Where the to write the message. * @@ -1096,13 +1132,13 @@ peer_info_delete_tunnel (void *cls, const GNUNET_HashCode * key, void *value) static size_t send_core_data_raw (void *cls, size_t size, void *buf) { - struct MeshDataDescriptor *info = cls; + struct MeshTransmissionDescriptor *info = cls; struct GNUNET_MessageHeader *msg; size_t total_size; GNUNET_assert (NULL != info); - GNUNET_assert (NULL != info->data); - msg = (struct GNUNET_MessageHeader *) info->data; + GNUNET_assert (NULL != info->mesh_data); + msg = (struct GNUNET_MessageHeader *) info->mesh_data->data; total_size = ntohs (msg->size); if (total_size > size) @@ -1118,7 +1154,7 @@ send_core_data_raw (void *cls, size_t size, void *buf) } info->peer->core_transmit[info->handler_n] = NULL; memcpy (buf, msg, total_size); - GNUNET_free (info->data); + GNUNET_free (info->mesh_data); GNUNET_free (info); return total_size; } @@ -1130,12 +1166,14 @@ send_core_data_raw (void *cls, size_t size, void *buf) * * @param message Message to send. Fucntion makes a copy of it. * @param peer Short ID of the neighbor whom to send the message. + * + * FIXME tunnel? */ static void send_message (const struct GNUNET_MessageHeader *message, const struct GNUNET_PeerIdentity *peer) { - struct MeshDataDescriptor *info; + struct MeshTransmissionDescriptor *info; struct MeshPeerInfo *neighbor; struct MeshPeerPath *p; unsigned int i; @@ -1144,9 +1182,11 @@ send_message (const struct GNUNET_MessageHeader *message, // GNUNET_TRANSPORT_try_connect(); size = ntohs (message->size); - info = GNUNET_malloc (sizeof (struct MeshDataDescriptor)); - info->data = GNUNET_malloc (size); - memcpy (info->data, message, size); + info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor)); + info->mesh_data = GNUNET_malloc (sizeof (struct MeshData)); + info->mesh_data->data = GNUNET_malloc (size); + memcpy (info->mesh_data->data, message, size); + info->mesh_data->data_len = size; neighbor = peer_info_get (peer); for (p = neighbor->path_head; NULL != p; p = p->next) { @@ -1158,6 +1198,8 @@ send_message (const struct GNUNET_MessageHeader *message, if (NULL == p) { GNUNET_break (0); + GNUNET_free (info->mesh_data->data); + GNUNET_free (info->mesh_data); GNUNET_free (info); return; } @@ -1267,7 +1309,7 @@ send_destroy_path (struct MeshTunnel *t, GNUNET_PEER_Id destination) { GNUNET_PEER_resolve (p->peers[i], &pi[i]); } - send_message (&msg->header, path_get_first_hop (t->tree, destination)); + send_message (&msg->header, tree_get_first_hop (t->tree, destination)); } path_destroy (p); } @@ -1449,6 +1491,8 @@ peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, for (i = 0; i < peer->ntunnels; i++) { d = tunnel_notify_connection_broken (peer->tunnels[i], p1, p2); + if (0 == d) + continue; /* TODO * Problem: one or more peers have been deleted from the tunnel tree. * We don't know who they are to try to add them again. @@ -1465,7 +1509,7 @@ peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, aux = NULL; for (p = peer_d->path_head; NULL != p; p = p->next) { - if ((cost = path_get_cost (peer->tunnels[i]->tree, p)) < best) + if ((cost = tree_get_path_cost (peer->tunnels[i]->tree, p)) < best) { best = cost; aux = p; @@ -1473,7 +1517,9 @@ peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, } if (NULL != aux) { - /* No callback, as peer will be already disconnected */ + /* No callback, as peer will be already disconnected and a connection + * scheduled by tunnel_notify_connection_broken. + */ tree_add_path (peer->tunnels[i]->tree, aux, NULL, NULL); } else @@ -1507,6 +1553,12 @@ peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path, path_destroy (path); return; } + if (path->peers[path->length - 1] != peer_info->id) + { + GNUNET_break (0); + path_destroy (path); + return; + } if (path->length <= 2 && GNUNET_NO == trusted) { /* Only allow CORE to tell us about direct paths */ @@ -1676,6 +1728,32 @@ path_build_from_dht (const struct GNUNET_PeerIdentity *get_path, } +/** + * Adds a path to the peer_infos of all the peers in the path + * + * @param p Path to process. + * @param confirmed Whether we know if the path works or not. FIXME use + */ +static void +path_add_to_peers (struct MeshPeerPath *p, int confirmed) +{ + unsigned int i; + + /* TODO: invert and add */ + for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ; + for (i++; i < p->length; i++) + { + struct MeshPeerInfo *aux; + struct MeshPeerPath *copy; + + aux = peer_info_get_short (p->peers[i]); + copy = path_duplicate (p); + copy->length = i + 1; + peer_info_add_path (aux, copy, GNUNET_NO); + } +} + + /** * Send keepalive packets for a peer * @@ -1834,10 +1912,10 @@ tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer) if (NULL != (p = peer->path_head)) { best_p = p; - best_cost = path_get_cost (t->tree, p); + best_cost = tree_get_path_cost (t->tree, p); while (NULL != p) { - if ((cost = path_get_cost (t->tree, p)) < best_cost) + if ((cost = tree_get_path_cost (t->tree, p)) < best_cost) { best_cost = cost; best_p = p; @@ -1851,7 +1929,7 @@ tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer) } else { - /* Start a DHT get if necessary */ + /* Start a DHT get */ peer_info_connect (peer, t); } } @@ -1874,12 +1952,10 @@ tunnel_add_path (struct MeshTunnel *t, struct MeshPeerPath *p, GNUNET_assert (0 != own_pos); tree_add_path (t->tree, p, NULL, NULL); - if (tree_get_me (t->tree) == 0) - tree_set_me (t->tree, p->peers[own_pos]); if (own_pos < p->length - 1) { GNUNET_PEER_resolve (p->peers[own_pos + 1], &id); - tree_update_first_hops (t->tree, tree_get_me (t->tree), &id); + tree_update_first_hops (t->tree, myid, &id); } } @@ -1932,43 +2008,24 @@ tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1, } -struct MeshMulticastData -{ - struct MeshTunnel *t; - - GNUNET_SCHEDULER_TaskIdentifier *task; - - unsigned int *reference_counter; - - size_t data_len; - - void *data; -}; - - /** * Send a multicast packet to a neighbor. + * + * @param cls Closure (Info about the multicast packet) + * @param neighbor_id Short ID of the neighbor to send the packet to. */ static void tunnel_send_multicast_iterator (void *cls, GNUNET_PEER_Id neighbor_id) { - struct MeshMulticastData *mdata = cls; - struct MeshDataDescriptor *info; + struct MeshData *mdata = cls; + struct MeshTransmissionDescriptor *info; struct GNUNET_PeerIdentity neighbor; unsigned int i; - info = GNUNET_malloc (sizeof (struct MeshDataDescriptor)); - - info->data = mdata->data; - info->size = mdata->data_len; - info->copies = mdata->reference_counter; - (*(mdata->reference_counter))++; + info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor)); - if (NULL != mdata->t->client) - { - info->client = mdata->t->client->handle; - info->timeout_task = mdata->task; - } + info->mesh_data = mdata; + (*(mdata->reference_counter)) ++; info->destination = neighbor_id; GNUNET_PEER_resolve (neighbor_id, &neighbor); #if MESH_DEBUG @@ -1984,7 +2041,7 @@ tunnel_send_multicast_iterator (void *cls, GNUNET_PEER_Id neighbor_id) info->peer->core_transmit[i] = GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, GNUNET_TIME_UNIT_FOREVER_REL, - &neighbor, info->size, + &neighbor, info->mesh_data->data_len, &send_core_data_multicast, info); } @@ -1999,25 +2056,41 @@ static void tunnel_send_multicast (struct MeshTunnel *t, const struct GNUNET_MessageHeader *msg) { - struct MeshMulticastData *mdata; + struct MeshData *mdata; #if MESH_DEBUG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: sending a multicast packet...\n"); #endif - GNUNET_assert (tree_get_me (t->tree) != 0); - mdata = GNUNET_malloc (sizeof (struct MeshMulticastData)); + mdata = GNUNET_malloc (sizeof (struct MeshData)); mdata->data_len = ntohs (msg->size); mdata->reference_counter = GNUNET_malloc (sizeof (unsigned int)); - mdata->data = GNUNET_malloc (mdata->data_len); mdata->t = t; + mdata->data = GNUNET_malloc (mdata->data_len); memcpy (mdata->data, msg, mdata->data_len); + if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST) + { + struct GNUNET_MESH_Multicast *mcast; + + mcast = (struct GNUNET_MESH_Multicast *) mdata->data; + mcast->ttl = htonl (ntohl (mcast->ttl) - 1); +#if MESH_DEBUG + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: data packet, ttl: %u\n", + ntohl (mcast->ttl)); + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: not a data packet, no ttl\n"); +#endif + } if (NULL != t->client) { mdata->task = GNUNET_malloc (sizeof (GNUNET_SCHEDULER_TaskIdentifier)); - *(mdata->task) = + (*(mdata->task)) = GNUNET_SCHEDULER_add_delayed (UNACKNOWLEDGED_WAIT, &client_allow_send, - t->client->handle); + mdata); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: timeout task %u\n", + *(mdata->task)); } tree_iterate_children (t->tree, &tunnel_send_multicast_iterator, mdata); @@ -2027,10 +2100,13 @@ tunnel_send_multicast (struct MeshTunnel *t, GNUNET_free (mdata->reference_counter); if (NULL != mdata->task) { + GNUNET_SCHEDULER_cancel(*(mdata->task)); GNUNET_free (mdata->task); + GNUNET_SERVER_receive_done(t->client->handle, GNUNET_OK); } + // FIXME change order? + GNUNET_free (mdata); } - GNUNET_free (mdata); #if MESH_DEBUG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: sending a multicast packet done\n"); @@ -2144,7 +2220,7 @@ tunnel_destroy (struct MeshTunnel *t) * The tunnel itself is also destoyed if results in a remote empty tunnel. * * @param t Tunnel from which to remove the path. - * @param p Peer which should be removed. + * @param peer Short id of the peer which should be removed. */ static void tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer) @@ -2249,7 +2325,7 @@ send_core_create_path (void *cls, size_t size, void *buf) info->peer->core_transmit[info->pos] = GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, GNUNET_TIME_UNIT_FOREVER_REL, - path_get_first_hop (t->tree, + tree_get_first_hop (t->tree, peer->id), size_needed, &send_core_create_path, info); @@ -2301,13 +2377,13 @@ send_core_create_path (void *cls, size_t size, void *buf) static size_t send_core_data_multicast (void *cls, size_t size, void *buf) { - struct MeshDataDescriptor *info = cls; + struct MeshTransmissionDescriptor *info = cls; size_t total_size; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Multicast callback.\n"); GNUNET_assert (NULL != info); GNUNET_assert (NULL != info->peer); - total_size = info->size; + total_size = info->mesh_data->data_len; GNUNET_assert (total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE); if (total_size > size) @@ -2329,7 +2405,7 @@ send_core_data_multicast (void *cls, size_t size, void *buf) info->peer->core_transmit[info->handler_n] = NULL; info->peer->infos[info->handler_n] = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: copying data...\n"); - memcpy (buf, info->data, total_size); + memcpy (buf, info->mesh_data->data, total_size); #if MESH_DEBUG { struct GNUNET_MESH_Multicast *mc; @@ -2352,7 +2428,7 @@ send_core_data_multicast (void *cls, size_t size, void *buf) } } #endif - data_descriptor_decrement_multicast (info); + data_descriptor_decrement_multicast (info->mesh_data); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: freeing info...\n"); GNUNET_free (info); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: return %u\n", total_size); @@ -2366,7 +2442,7 @@ send_core_data_multicast (void *cls, size_t size, void *buf) * NULL and "size" zero if the socket was closed for * writing in the meantime. * - * @param cls closure (MeshDataDescriptor) + * @param cls closure (MeshTransmissionDescriptor) * @param size number of bytes available in buf * @param buf where the callee should write the message * @return number of bytes written to buf @@ -2374,7 +2450,7 @@ send_core_data_multicast (void *cls, size_t size, void *buf) static size_t send_core_path_ack (void *cls, size_t size, void *buf) { - struct MeshDataDescriptor *info = cls; + struct MeshTransmissionDescriptor *info = cls; struct GNUNET_MESH_PathACK *msg = buf; GNUNET_assert (NULL != info); @@ -2462,9 +2538,9 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, tid = ntohl (msg->tid); pi = (struct GNUNET_PeerIdentity *) &msg[1]; - t = tunnel_get (pi, tid); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: path is for tunnel %s [%X].\n", GNUNET_i2s (pi), tid); + t = tunnel_get (pi, tid); if (NULL == t) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Creating tunnel\n"); @@ -2540,26 +2616,38 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, /* FIXME error. destroy tunnel? leave for timeout? */ return 0; } + path_add_to_peers (path, GNUNET_NO); tunnel_add_path (t, path, own_pos); if (own_pos == size - 1) { /* It is for us! Send ack. */ - struct GNUNET_MESH_TunnelNotification cmsg; - struct MeshDataDescriptor *info; + struct MeshTransmissionDescriptor *info; unsigned int j; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: It's for us!\n"); peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO); if (NULL == t->peers) + { + /* New tunnel! Notify clients! */ + struct GNUNET_MESH_TunnelNotification cmsg; + + cmsg.header.size = htons (sizeof (cmsg)); + cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); + GNUNET_PEER_resolve (t->id.oid, &cmsg.peer); + cmsg.tunnel_id = htonl (t->local_tid); + GNUNET_SERVER_notification_context_broadcast (nc, &cmsg.header, + GNUNET_NO); + t->peers = GNUNET_CONTAINER_multihashmap_create (4); + } GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (t->peers, &my_full_id.hashPubKey, peer_info_get (&my_full_id), - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); + GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); /* FIXME use send_message */ - info = GNUNET_malloc (sizeof (struct MeshDataDescriptor)); + info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor)); info->origin = &t->id; info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey); GNUNET_assert (NULL != info->peer); @@ -2572,11 +2660,6 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, GNUNET_TIME_UNIT_FOREVER_REL, peer, sizeof (struct GNUNET_MESH_PathACK), &send_core_path_ack, info); - cmsg.header.size = htons (sizeof (cmsg)); - cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); - GNUNET_PEER_resolve (t->id.oid, &cmsg.peer); - cmsg.tunnel_id = htonl (t->local_tid); - GNUNET_SERVER_notification_context_broadcast (nc, &cmsg.header, GNUNET_NO); } else { @@ -2820,7 +2903,7 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: not for us, retransmitting...\n"); - send_message (message, path_get_first_hop (t->tree, pid)); + send_message (message, tree_get_first_hop (t->tree, pid)); return GNUNET_OK; } @@ -2866,6 +2949,21 @@ handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer, GNUNET_break_op (0); return GNUNET_OK; } + if (t->mid == ntohl (msg->mid)) + { + /* FIXME: already seen this packet, log dropping */ + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "MESH: Already seen mid %u, DROPPING!\n", t->mid); + return GNUNET_OK; + } +#if MESH_DEBUG + else + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MESH: mid %u not seen yet, forwarding\n", ntohl (msg->mid)); + } +#endif + t->mid = ntohl (msg->mid); tunnel_reset_timeout (t); /* Transmit to locally interested clients */ @@ -2874,6 +2972,15 @@ handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer, { send_subscribed_clients (message, &msg[1].header); } +#if MESH_DEBUG + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: ttl: %u\n", ntohl (msg->ttl)); +#endif + if (ntohl (msg->ttl) == 0) + { + /* FIXME: ttl is 0, log dropping */ + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "MESH: TTL is 0, DROPPING!\n"); + return GNUNET_OK; + } tunnel_send_multicast (t, message); return GNUNET_OK; } @@ -2984,6 +3091,7 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, struct GNUNET_MESH_PathACK *msg; struct GNUNET_PeerIdentity id; struct MeshPeerInfo *peer_info; + struct MeshPeerPath *p; struct MeshTunnel *t; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Received a path ACK msg [%s]\n", @@ -2996,6 +3104,20 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, return GNUNET_OK; } + peer_info = peer_info_get (&msg->peer_id); + + /* Add paths to peers? */ + p = tree_get_path_to_peer (t->tree, peer_info->id); + if (NULL != p) + { + path_add_to_peers (p, GNUNET_YES); + path_destroy (p); + } + else + { + GNUNET_break (0); + } + /* Message for us? */ if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity))) { @@ -3010,9 +3132,11 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, GNUNET_DHT_get_stop (t->dht_get_type); t->dht_get_type = NULL; } - peer_info = peer_info_get (&msg->peer_id); - tree_set_status (t->tree, peer_info->id, MESH_PEER_READY); - send_client_peer_connected (t, peer_info->id); + if (tree_get_status (t->tree, peer_info->id) != MESH_PEER_READY) + { + tree_set_status (t->tree, peer_info->id, MESH_PEER_READY); + send_client_peer_connected (t, peer_info->id); + } return GNUNET_OK; } @@ -3164,6 +3288,10 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * @param cls closure * @param exp when will this value expire * @param key key of the result + * @param get_path path of the get request + * @param get_path_length lenght of get_path + * @param put_path path of the put request + * @param put_path_length length of the put_path * @param type type of the result * @param size number of bytes in data * @param data pointer to the result data @@ -3187,18 +3315,16 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Got results from DHT!\n"); GNUNET_PEER_resolve (path_info->peer->id, &pi); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: for %s\n", GNUNET_i2s (&pi)); -// GNUNET_DHT_get_stop(path_info->peer->dhtget); -// path_info->peer->dhtget = NULL; p = path_build_from_dht (get_path, get_path_length, put_path, put_path_length); - peer_info_add_path (path_info->peer, p, GNUNET_NO); + path_add_to_peers (p, GNUNET_NO); + path_destroy(p); for (i = 0; i < path_info->peer->ntunnels; i++) { tunnel_add_peer (path_info->peer->tunnels[i], path_info->peer); peer_info_connect (path_info->peer, path_info->t); } -// GNUNET_free (path_info); return; } @@ -3212,6 +3338,10 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, * @param cls closure * @param exp when will this value expire * @param key key of the result + * @param get_path path of the get request + * @param get_path_length lenght of get_path + * @param put_path path of the put request + * @param put_path_length length of the put_path * @param type type of the result * @param size number of bytes in data * @param data pointer to the result data @@ -3243,7 +3373,8 @@ dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp, p = path_build_from_dht (get_path, get_path_length, put_path, put_path_length); - peer_info_add_path (peer_info, p, GNUNET_NO); + path_add_to_peers (p, GNUNET_NO); + path_destroy(p); tunnel_add_peer (t, peer_info); peer_info_connect (peer_info, t); } @@ -3355,9 +3486,9 @@ handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client, c = GNUNET_malloc (sizeof (struct MeshClient)); #if MESH_DEBUG c->id = next_client_id++; -#endif GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CLIENT NEW %u at %p\n", c->id, c); +#endif c->handle = client; GNUNET_SERVER_client_keep (client); a = (GNUNET_MESH_ApplicationType *) &cc_msg[1]; @@ -3505,7 +3636,6 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, return; } t->tree = tree_new (myid); - tree_set_me (t->tree, myid); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; @@ -3770,8 +3900,12 @@ handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_YES) { /* Yes! Fast forward, add ourselves to the tunnel and send the - * good news to the client + * good news to the client, and alert the destination client of + * an incoming tunnel. */ + struct GNUNET_MESH_TunnelNotification cmsg; + struct MeshClient *c; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: available locally\n"); GNUNET_CONTAINER_multihashmap_put (t->peers, &my_full_id.hashPubKey, peer_info_get (&my_full_id), @@ -3781,6 +3915,20 @@ handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client, send_client_peer_connected (t, myid); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Done\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); + + /* FIXME implement a proper handling of this case, + a client differentiation mechanism */ + cmsg.header.size = htons (sizeof (cmsg)); + cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); + cmsg.peer = my_full_id; + t->local_tid_dest = next_local_tid++; + cmsg.tunnel_id = htonl (t->local_tid_dest); + c = (struct MeshClient *) GNUNET_CONTAINER_multihashmap_get(applications, + &hash); + GNUNET_SERVER_notification_context_unicast (nc, c->handle, &cmsg.header, + GNUNET_NO); + + return; } /* Ok, lets find a peer offering the service */ @@ -4039,6 +4187,8 @@ handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client, memcpy (buf, message, ntohs (message->size)); copy->oid = my_full_id; copy->tid = htonl (t->id.tid); + copy->ttl = htonl (DEFAULT_TTL); + copy->mid = htonl (t->mid + 1); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: calling generic handler...\n"); handle_mesh_data_multicast (client, &my_full_id, ©->header, NULL, 0); @@ -4232,7 +4382,7 @@ static void shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shutting down\n"); - /* TODO: destroy tunnels? */ + if (core_handle != NULL) { GNUNET_CORE_disconnect (core_handle);