X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmesh%2Fgnunet-service-mesh_local.c;h=9b868124a1d96b3f2d5c4dfbafd9151d2ed6386d;hb=33354bfe79f97acb2c98d08fa4f1c32f2d2b1220;hp=7b58f0854b998a4cef0f44d1202b004da09a1360;hpb=61c39c60565b386e0e12ea669556b030e8cd7180;p=oweals%2Fgnunet.git diff --git a/src/mesh/gnunet-service-mesh_local.c b/src/mesh/gnunet-service-mesh_local.c index 7b58f0854..9b868124a 100644 --- a/src/mesh/gnunet-service-mesh_local.c +++ b/src/mesh/gnunet-service-mesh_local.c @@ -20,10 +20,17 @@ #include "platform.h" +#include "gnunet_util_lib.h" + +#include "gnunet_statistics_service.h" + #include "mesh_enc.h" #include "mesh_protocol_enc.h" // GNUNET_MESH_Data is shared + #include "gnunet-service-mesh_local.h" +#define LOG(level, ...) GNUNET_log_from(level,"mesh-loc",__VA_ARGS__) + /******************************************************************************/ /******************************** STRUCTS **********************************/ /******************************************************************************/ @@ -50,11 +57,16 @@ struct MeshClient */ struct GNUNET_CONTAINER_MultiHashMap32 *own_channels; - /** + /** * Tunnels this client has accepted, indexed by incoming local id */ struct GNUNET_CONTAINER_MultiHashMap32 *incoming_channels; + /** + * Channel ID for the next incoming channel. + */ + MESH_ChannelNumber next_chid; + /** * Handle to communicate with the client */ @@ -82,6 +94,11 @@ struct MeshClient /******************************* GLOBALS ***********************************/ /******************************************************************************/ +/** + * Global handle to the statistics service. + */ +extern struct GNUNET_STATISTICS_Handle *stats; + /** * Handle to server lib. */ @@ -137,7 +154,7 @@ client_release_ports (void *cls, if (GNUNET_YES != res) { GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + LOG (GNUNET_ERROR_TYPE_WARNING, "Port %u by client %p was not registered.\n", key, value); } @@ -162,17 +179,44 @@ handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client) { struct MeshClient *c; + LOG (GNUNET_ERROR_TYPE_DEBUG, "client connected: %p\n", client); if (NULL == client) return; - c = GNUNET_malloc (sizeof (struct MeshClient)); + c = GNUNET_new (struct MeshClient); c->handle = client; c->id = next_client_id++; /* overflow not important: just for debug */ + c->next_chid = GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; GNUNET_SERVER_client_keep (client); GNUNET_SERVER_client_set_user_context (client, c); GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c); } +/** + * Iterator for deleting each channel whose client endpoint disconnected. + * + * @param cls Closure (client that has disconnected). + * @param key The local channel id (used to access the hashmap). + * @param value The value stored at the key (channel to destroy). + * + * @return GNUNET_OK, keep iterating. + */ +static int +channel_destroy_iterator (void *cls, + uint32_t key, + void *value) +{ + struct MeshChannel *ch = value; + struct MeshClient *c = cls; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + " Channel %s destroy, due to client %s shutdown.\n", + GMCH_2s (ch), GML_2s (c)); + + GMCH_handle_local_destroy (ch, c); + return GNUNET_OK; +} + /** * Handler for client disconnection * @@ -185,17 +229,17 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct MeshClient *c; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client); + LOG (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client); if (client == NULL) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n"); return; } - c = client_get (client); + c = GML_client_get (client); if (NULL != c) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u, %p)\n", + LOG (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u, %p)\n", c->id, c); GNUNET_SERVER_client_drop (c->handle); c->shutting_down = GNUNET_YES; @@ -221,14 +265,14 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) } GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c); GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client free (%p)\n", c); + LOG (GNUNET_ERROR_TYPE_DEBUG, " client free (%p)\n", c); GNUNET_free (c); } else { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " context NULL!\n"); + LOG (GNUNET_ERROR_TYPE_WARNING, " context NULL!\n"); } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done!\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "done!\n"); return; } @@ -250,7 +294,7 @@ handle_new_client (void *cls, struct GNUNET_SERVER_Client *client, uint32_t *p; unsigned int i; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client); + LOG (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client); /* Check data sanity */ size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect); @@ -265,8 +309,8 @@ handle_new_client (void *cls, struct GNUNET_SERVER_Client *client, /* Initialize new client structure */ c = GNUNET_SERVER_client_get_user_context (client, struct MeshClient); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client id %u\n", c->id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client has %u ports\n", size); + LOG (GNUNET_ERROR_TYPE_DEBUG, " client id %u\n", c->id); + LOG (GNUNET_ERROR_TYPE_DEBUG, " client has %u ports\n", size); if (size > 0) { uint32_t u32; @@ -276,7 +320,7 @@ handle_new_client (void *cls, struct GNUNET_SERVER_Client *client, for (i = 0; i < size; i++) { u32 = ntohl (p[i]); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " port: %u\n", u32); + LOG (GNUNET_ERROR_TYPE_DEBUG, " port: %u\n", u32); /* store in client's hashmap */ GNUNET_CONTAINER_multihashmap32_put (c->ports, u32, c, @@ -295,7 +339,7 @@ handle_new_client (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO); GNUNET_SERVER_receive_done (client, GNUNET_OK); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n"); } @@ -310,23 +354,18 @@ static void handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { - struct GNUNET_MESH_ChannelMessage *msg; - struct MeshPeer *peer; - struct MeshTunnel2 *t; - struct MeshChannel *ch; struct MeshClient *c; - MESH_ChannelNumber chid; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n"); /* Sanity check for client registration */ - if (NULL == (c = client_get (client))) + if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); + LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); /* Message size sanity check */ if (sizeof (struct GNUNET_MESH_ChannelMessage) != ntohs (message->size)) @@ -336,67 +375,14 @@ handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client, return; } - msg = (struct GNUNET_MESH_ChannelMessage *) message; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " towards %s:%u\n", - GNUNET_i2s (&msg->peer), ntohl (msg->port)); - chid = ntohl (msg->channel_id); - - /* Sanity check for duplicate channel IDs */ - if (NULL != channel_get_by_local_id (c, chid)) + if (GNUNET_OK != + GMCH_handle_local_create (c, + (struct GNUNET_MESH_ChannelMessage *) message)) { - GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - peer = peer_get (&msg->peer); - if (NULL == peer->tunnel) - { - peer->tunnel = tunnel_new (); - peer->tunnel->peer = peer; - if (peer->id == myid) - { - tunnel_change_state (peer->tunnel, MESH_TUNNEL_READY); - } - else - { - peer_connect (peer); - } - } - t = peer->tunnel; - - /* Create channel */ - ch = channel_new (t, c, chid); - if (NULL == ch) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - ch->port = ntohl (msg->port); - channel_set_options (ch, ntohl (msg->opt)); - - /* In unreliable channels, we'll use the DLL to buffer BCK data */ - ch->root_rel = GNUNET_new (struct MeshChannelReliability); - ch->root_rel->ch = ch; - ch->root_rel->expected_delay = MESH_RETRANSMIT_TIME; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s[%x]:%u (%x)\n", - peer2s (t->peer), ch->gid, ch->port, ch->lid_root); - - /* Send create channel */ - { - struct GNUNET_MESH_ChannelCreate msgcc; - - msgcc.header.size = htons (sizeof (msgcc)); - msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE); - msgcc.chid = htonl (ch->gid); - msgcc.port = msg->port; - msgcc.opt = msg->opt; - - tunnel_queue_data (t, ch, &msgcc.header, GNUNET_YES); - } - GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } @@ -416,20 +402,19 @@ handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client, struct GNUNET_MESH_ChannelMessage *msg; struct MeshClient *c; struct MeshChannel *ch; - struct MeshTunnel2 *t; MESH_ChannelNumber chid; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n"); /* Sanity check for client registration */ - if (NULL == (c = client_get (client))) + if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); + LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); /* Message sanity check */ if (sizeof (struct GNUNET_MESH_ChannelMessage) != ntohs (message->size)) @@ -443,36 +428,16 @@ handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client, /* Retrieve tunnel */ chid = ntohl (msg->channel_id); - ch = channel_get_by_local_id (c, chid); + ch = GML_channel_get (c, chid); if (NULL == ch) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " channel %X not found\n", chid); + LOG (GNUNET_ERROR_TYPE_ERROR, " channel %X not found\n", chid); GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - /* Cleanup after the tunnel */ - client_delete_channel (c, ch); - if (c == ch->dest && GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= chid) - { - ch->dest = NULL; - } - else if (c == ch->root && GNUNET_MESH_LOCAL_CHANNEL_ID_SERV > chid) - { - ch->root = NULL; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - " channel %X client %p (%p, %p)\n", - chid, c, ch->root, ch->dest); - GNUNET_break (0); - } - - t = ch->t; - channel_destroy (ch); - tunnel_destroy_if_empty (t); + GMCH_handle_local_destroy (ch, c); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; @@ -493,22 +458,21 @@ handle_data (void *cls, struct GNUNET_SERVER_Client *client, struct GNUNET_MESH_LocalData *msg; struct MeshClient *c; struct MeshChannel *ch; - struct MeshChannelReliability *rel; MESH_ChannelNumber chid; size_t size; int fwd; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_DEBUG, "Got data from a client!\n"); /* Sanity check for client registration */ - if (NULL == (c = client_get (client))) + if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); + LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); msg = (struct GNUNET_MESH_LocalData *) message; @@ -524,7 +488,7 @@ handle_data (void *cls, struct GNUNET_SERVER_Client *client, /* Channel exists? */ chid = ntohl (msg->id); fwd = chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; - ch = channel_get_by_local_id (c, chid); + ch = GML_channel_get (c, chid); if (NULL == ch) { GNUNET_break (0); @@ -532,45 +496,15 @@ handle_data (void *cls, struct GNUNET_SERVER_Client *client, return; } - /* Is the client in the channel? */ - if ( !( (fwd && - ch->root && - ch->root->handle == client) - || - (!fwd && - ch->dest && - ch->dest->handle == client) ) ) + if (GNUNET_OK != + GMCH_handle_local_data (ch, c, + (struct GNUNET_MessageHeader *)&msg[1], fwd)) { - GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - rel = fwd ? ch->root_rel : ch->dest_rel; - rel->client_ready = GNUNET_NO; - - /* Ok, everything is correct, send the message. */ - { - struct GNUNET_MESH_Data *payload; - uint16_t p2p_size = sizeof(struct GNUNET_MESH_Data) + size; - unsigned char cbuf[p2p_size]; - - payload = (struct GNUNET_MESH_Data *) cbuf; - payload->mid = htonl (rel->mid_send); - rel->mid_send++; - memcpy (&payload[1], &msg[1], size); - payload->header.size = htons (p2p_size); - payload->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_DATA); - payload->chid = htonl (ch->gid); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n"); - send_prebuilt_message_channel (&payload->header, ch, fwd); - - if (GNUNET_YES == ch->reliable) - channel_save_copy (ch, &payload->header, fwd); - } - if (tunnel_get_buffer (ch->t, fwd) > 0) - send_local_ack (ch, fwd); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; @@ -589,48 +523,43 @@ handle_ack (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_LocalAck *msg; - struct MeshChannelReliability *rel; struct MeshChannel *ch; struct MeshClient *c; MESH_ChannelNumber chid; int fwd; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n"); /* Sanity check for client registration */ - if (NULL == (c = client_get (client))) + if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); + LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); msg = (struct GNUNET_MESH_LocalAck *) message; /* Channel exists? */ chid = ntohl (msg->channel_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", chid); - ch = channel_get_by_local_id (c, chid); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " -- ch %p\n", ch); + LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", chid); + ch = GML_channel_get (c, chid); + LOG (GNUNET_ERROR_TYPE_DEBUG, " -- ch %p\n", ch); if (NULL == ch) { GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Channel %X unknown.\n", chid); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " for client %u.\n", c->id); + LOG (GNUNET_ERROR_TYPE_WARNING, "Channel %X unknown.\n", chid); + LOG (GNUNET_ERROR_TYPE_WARNING, " for client %u.\n", c->id); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - /* If client is root, the ACK is going FWD, therefore this is "BCK". */ - /* If client is dest, the ACK is going BCK, therefore this is "FWD" */ + /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */ + /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */ fwd = chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; - rel = fwd ? ch->dest_rel : ch->root_rel; - - rel->client_ready = GNUNET_YES; - channel_send_client_buffered_data (ch, c, fwd); - send_ack (NULL, ch, fwd); + GMCH_handle_local_ack (ch, fwd); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; @@ -660,7 +589,7 @@ handle_ack (void *cls, struct GNUNET_SERVER_Client *client, // msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor)); // msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS); // -// GNUNET_log (GNUNET_ERROR_TYPE_INFO, +// LOG (GNUNET_ERROR_TYPE_INFO, // "* sending info about tunnel %s\n", // GNUNET_i2s (&msg->owner)); // @@ -684,20 +613,20 @@ handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client, struct MeshClient *c; /* Sanity check for client registration */ - if (NULL == (c = client_get (client))) + if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + LOG (GNUNET_ERROR_TYPE_INFO, "Received get tunnels request from client %u\n", c->id); // GNUNET_CONTAINER_multihashmap_iterate (tunnels, // monitor_all_tunnels_iterator, // client); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + LOG (GNUNET_ERROR_TYPE_INFO, "Get tunnels request from client %u completed\n", c->id); GNUNET_SERVER_receive_done (client, GNUNET_OK); @@ -721,7 +650,7 @@ handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, struct MeshChannel *ch; /* Sanity check for client registration */ - if (NULL == (c = client_get (client))) + if (NULL == (c = GML_client_get (client))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); @@ -729,7 +658,7 @@ handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, } msg = (struct GNUNET_MESH_LocalMonitor *) message; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + LOG (GNUNET_ERROR_TYPE_INFO, "Received tunnel info request from client %u for tunnel %s[%X]\n", c->id, &msg->owner, @@ -757,7 +686,7 @@ handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, &resp->header, GNUNET_NO); GNUNET_free (resp); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + LOG (GNUNET_ERROR_TYPE_INFO, "Monitor tunnel request from client %u completed\n", c->id); GNUNET_SERVER_receive_done (client, GNUNET_OK); @@ -797,6 +726,7 @@ static struct GNUNET_SERVER_MessageHandler client_handlers[] = { void GML_init (struct GNUNET_SERVER_Handle *handle) { + LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); server_handle = handle; GNUNET_SERVER_suspend (server_handle); ports = GNUNET_CONTAINER_multihashmap32_create (32); @@ -836,6 +766,97 @@ GML_shutdown (void) } +/** + * Get a chennel from a client + * + * @param c the client to check + * @param chid Channel ID, must be local (> 0x800...) + * + * @return non-NULL if channel exists in the clients lists + */ +struct MeshChannel * +GML_channel_get (struct MeshClient *c, MESH_ChannelNumber chid) +{ + if (0 == (chid & GNUNET_MESH_LOCAL_CHANNEL_ID_CLI)) + { + GNUNET_break_op (0); + LOG (GNUNET_ERROR_TYPE_DEBUG, "CHID %X not a local chid\n", chid); + return NULL; + } + if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV) + return GNUNET_CONTAINER_multihashmap32_get (c->incoming_channels, chid); + return GNUNET_CONTAINER_multihashmap32_get (c->own_channels, chid); +} + + +/** + * Add a channel to a client + * + * @param client Client. + * @param chid Channel ID. + * @param ch Channel. + */ +void +GML_channel_add (struct MeshClient *client, + uint32_t chid, + struct MeshChannel *ch) +{ + if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV) + GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels, chid, ch, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + else if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI) + GNUNET_CONTAINER_multihashmap32_put (client->own_channels, chid, ch, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); + else + GNUNET_break (0); +} + + +/** + * Remove a channel from a client + * + * @param client Client. + * @param chid Channel ID. + * @param ch Channel. + */ +void +GML_channel_remove (struct MeshClient *client, + uint32_t chid, + struct MeshChannel *ch) +{ + if (GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= chid) + GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels, chid, ch); + else if (GNUNET_MESH_LOCAL_CHANNEL_ID_CLI <= chid) + GNUNET_CONTAINER_multihashmap32_remove (client->own_channels, chid, ch); + else + GNUNET_break (0); +} + + +/** + * Get the tunnel's next free local channel ID. + * + * @param c Client. + * + * @return LID of a channel free to use. + */ +MESH_ChannelNumber +GML_get_next_chid (struct MeshClient *c) +{ + MESH_ChannelNumber chid; + + while (NULL != GML_channel_get (c, c->next_chid)) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", c->next_chid); + c->next_chid = (c->next_chid + 1) | GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; + } + chid = c->next_chid; + c->next_chid = (c->next_chid + 1) | GNUNET_MESH_LOCAL_CHANNEL_ID_SERV; + + return chid; +} + + /** * Check if client has registered with the service and has not disconnected * @@ -849,31 +870,51 @@ GML_client_get (struct GNUNET_SERVER_Client *client) return GNUNET_SERVER_client_get_user_context (client, struct MeshClient); } +/** + * Find a client that has opened a port + * + * @param port Port to check. + * + * @return non-NULL if a client has the port. + */ +struct MeshClient * +GML_client_get_by_port (uint32_t port) +{ + return GNUNET_CONTAINER_multihashmap32_get (ports, port); +} + /** - * Deletes a tunnel from a client (either owner or destination). + * Deletes a channel from a client (either owner or destination). * * @param c Client whose tunnel to delete. * @param ch Channel which should be deleted. + * @param id Channel ID. */ void -GML_client_delete_channel (struct MeshClient *c, struct MeshChannel *ch) +GML_client_delete_channel (struct MeshClient *c, + struct MeshChannel *ch, + MESH_ChannelNumber id) { int res; - if (c == ch->root) + if (GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= id) { - res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels, - ch->lid_root, ch); + res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels, + id, ch); if (GNUNET_YES != res) - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel owner KO\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n"); } - if (c == ch->dest) + else if (GNUNET_MESH_LOCAL_CHANNEL_ID_CLI <= id) { - res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels, - ch->lid_dest, ch); + res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels, + id, ch); if (GNUNET_YES != res) - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel client KO\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n"); + } + else + { + GNUNET_break (0); } } @@ -882,39 +923,21 @@ GML_client_delete_channel (struct MeshClient *c, struct MeshChannel *ch) * * If the client was already allowed to send data, do nothing. * - * @param ch Channel on which to send the ACK. * @param c Client to whom send the ACK. - * @param fwd Set to GNUNET_YES for FWD ACK (dest->root) + * @param id Channel ID to use */ void -GML_send_ack (struct MeshChannel *ch, int fwd) +GML_send_ack (struct MeshClient *c, MESH_ChannelNumber id) { struct GNUNET_MESH_LocalAck msg; - struct MeshChannelReliability *rel; - struct MeshClient *c; - - c = fwd ? ch->root : ch->dest; - rel = fwd ? ch->root_rel : ch->dest_rel; - if (GNUNET_YES == rel->client_ready) - return; /* don't send double ACKs to client */ + LOG (GNUNET_ERROR_TYPE_DEBUG, + "send local %s ack on %X towards %p\n", + id < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV ? "FWD" : "BCK", id, c); - rel->client_ready = GNUNET_YES; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "send local %s ack on %s:%X towards %p\n", - fwd ? "FWD" : "BCK", peer2s (ch->t->peer), ch->gid, c); - - if (NULL == c - || ( fwd && (0 == ch->lid_root || c != ch->root)) - || (!fwd && (0 == ch->lid_dest || c != ch->dest)) ) - { - GNUNET_break (0); - return; - } msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); - msg.channel_id = htonl (fwd ? ch->lid_root : ch->lid_dest); + msg.channel_id = htonl (id); GNUNET_SERVER_notification_context_unicast (nc, c->handle, &msg.header, @@ -931,7 +954,7 @@ GML_send_ack (struct MeshChannel *ch, int fwd) void GML_send_channel_create (struct MeshClient *c, uint32_t id, uint32_t port, uint32_t opt, - struct GNUNET_PeerIdentity *peer) + const struct GNUNET_PeerIdentity *peer) { struct GNUNET_MESH_ChannelMessage msg; @@ -976,11 +999,11 @@ GML_send_channel_destroy (struct MeshClient *c, uint32_t id) /** * Modify the mesh message ID from global to local and send to client. * - * @param msg Message to modify and send. * @param c Client to send to. - * @param tid Tunnel ID to use (c can be both owner and client). + * @param msg Message to modify and send. + * @param id Channel ID to use (c can be both owner and client). */ -static void +void GML_send_data (struct MeshClient *c, const struct GNUNET_MESH_Data *msg, MESH_ChannelNumber id) @@ -1009,4 +1032,18 @@ GML_send_data (struct MeshClient *c, } +/** + * Get the static string to represent a client. + * + * @param c Client. + * + * @return Static string for the client. + */ +const char * +GML_2s (const struct MeshClient *c) +{ + static char buf[32]; + sprintf (buf, "%u", c->id); + return buf; +}