X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmesh%2Fgnunet-service-mesh.c;h=63700504860f550761679d45ac7bb822cfb332f4;hb=7c6b8edcc300e1be76803a9b80bfd720ddf0283a;hp=8883602ab6a47c97922a4dad0b9e210987c68db7;hpb=34298120a3b660139b08a449ed56ab38c7dbe719;p=oweals%2Fgnunet.git diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index 8883602ab..637005048 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c @@ -82,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; }; @@ -265,6 +276,11 @@ 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. */ @@ -723,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); } @@ -784,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)) @@ -820,7 +839,11 @@ 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 @@ -912,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); } } @@ -951,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 @@ -974,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"); @@ -1099,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. * @@ -1108,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) @@ -1130,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; } @@ -1142,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; @@ -1156,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) { @@ -1170,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; } @@ -1461,7 +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; + 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. @@ -1699,7 +1730,7 @@ 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 */ @@ -1709,16 +1740,16 @@ 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 = 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); + aux = peer_info_get_short (p->peers[i]); + copy = path_duplicate (p); copy->length = i + 1; - peer_info_add_path(aux, copy, GNUNET_NO); + peer_info_add_path (aux, copy, GNUNET_NO); } } @@ -1977,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 = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor)); - info->data = mdata->data; - info->size = mdata->data_len; - info->copies = mdata->reference_counter; - (*(mdata->reference_counter))++; - - 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 @@ -2029,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); } @@ -2044,13 +2056,13 @@ 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 - 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->t = t; @@ -2063,22 +2075,22 @@ tunnel_send_multicast (struct MeshTunnel *t, 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", + 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"); + 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); @@ -2088,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"); @@ -2362,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) @@ -2390,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; @@ -2413,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); @@ -2427,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 @@ -2435,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); @@ -2523,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"); @@ -2601,12 +2616,12 @@ 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); + 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 MeshDataDescriptor *info; + struct MeshTransmissionDescriptor *info; unsigned int j; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: It's for us!\n"); @@ -2632,7 +2647,7 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, (&my_full_id), 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); @@ -2938,16 +2953,14 @@ handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer, { /* FIXME: already seen this packet, log dropping */ GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "MESH: Already seen mid %u, DROPPING!\n", - t->mid); + "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)); + "MESH: mid %u not seen yet, forwarding\n", ntohl (msg->mid)); } #endif t->mid = ntohl (msg->mid); @@ -2960,15 +2973,12 @@ 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)); + 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"); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "MESH: TTL is 0, DROPPING!\n"); return GNUNET_OK; } tunnel_send_multicast (t, message); @@ -3097,11 +3107,11 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, peer_info = peer_info_get (&msg->peer_id); /* Add paths to peers? */ - p = tree_get_path_to_peer(t->tree, peer_info->id); + p = tree_get_path_to_peer (t->tree, peer_info->id); if (NULL != p) { path_add_to_peers (p, GNUNET_YES); - path_destroy(p); + path_destroy (p); } else { @@ -3122,7 +3132,7 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, GNUNET_DHT_get_stop (t->dht_get_type); t->dht_get_type = NULL; } - if (tree_get_status(t->tree, peer_info->id) != MESH_PEER_READY) + 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); @@ -3308,7 +3318,8 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, p = path_build_from_dht (get_path, get_path_length, put_path, put_path_length); - path_add_to_peers(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); @@ -3362,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); - path_add_to_peers(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); } @@ -3888,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), @@ -3899,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 */ @@ -4352,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);