X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmesh%2Fgnunet-service-mesh.c;h=63700504860f550761679d45ac7bb822cfb332f4;hb=7c6b8edcc300e1be76803a9b80bfd720ddf0283a;hp=c67c8ceb863d62a96ce03c759784190c3c35a05e;hpb=78259b33f194ac9901465f2f4c37431f74c3d971;p=oweals%2Fgnunet.git diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index c67c8ceb8..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; } @@ -1978,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 @@ -2030,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); } @@ -2045,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; @@ -2075,9 +2086,11 @@ tunnel_send_multicast (struct MeshTunnel *t, 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); @@ -2087,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"); @@ -2361,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) @@ -2389,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; @@ -2412,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); @@ -2426,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 @@ -2434,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); @@ -2522,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"); @@ -2605,7 +2621,7 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, 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"); @@ -2631,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); @@ -3884,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), @@ -3895,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 */ @@ -4348,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);