+ * Handler for requests of deleting tunnels
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_local_tunnel_destroy (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ struct GNUNET_MESH_TunnelMessage *tunnel_msg;
+ struct MeshClient *c;
+ struct MeshTunnel *t;
+ MESH_TunnelNumber tid;
+ GNUNET_HashCode hash;
+
+
+ /* Sanity check for client registration */
+ if (NULL == (c = retrieve_client(client))) {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+ /* Message sanity check */
+ if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
+
+ /* Retrieve tunnel */
+ tid = ntohl(tunnel_msg->tunnel_id);
+
+ /* Remove from local id hashmap */
+ GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
+ t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
+ GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t);
+
+ /* Remove from global id hashmap */
+ GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
+ GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t);
+
+// notify_tunnel_destroy(t);
+ GNUNET_SERVER_receive_done(client, GNUNET_OK);
+ return;
+}
+
+
+/**
+ * Handler for connection requests to new peers
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message (PeerControl)
+ */
+static void
+handle_local_connect_add (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ struct GNUNET_MESH_PeerControl *peer_msg;
+ struct MeshClient *c;
+ struct MeshTunnel *t;
+ MESH_TunnelNumber tid;
+ struct MeshPeerInfo *peer_info;
+
+
+ /* Sanity check for client registration */
+ if (NULL == (c = retrieve_client(client))) {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ peer_msg = (struct GNUNET_MESH_PeerControl *)message;
+ /* Sanity check for message size */
+ if (sizeof(struct GNUNET_MESH_PeerControl)
+ != ntohs(peer_msg->header.size))
+ {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ /* Tunnel exists? */
+ tid = ntohl(peer_msg->tunnel_id);
+ t = retrieve_tunnel_by_local_id(c, tid);
+ if (NULL == t) {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ /* Does client own tunnel? */
+ if (t->client->handle != client) {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ t->peers_total++;
+ peer_info = get_peer_info(&peer_msg->peer);
+
+ /* Start DHT search if needed */
+ if(MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget) {
+ peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ GNUNET_BLOCK_TYPE_ANY,
+ &peer_msg->peer.hashPubKey,
+ 4, /* replication level */
+ GNUNET_DHT_RO_RECORD_ROUTE,
+ NULL, /* bloom filter */
+ 0, /* mutator */
+ NULL, /* xquery */
+ 0, /* xquery bits */
+ dht_get_response_handler,
+ (void *)peer_info);
+ }
+
+ GNUNET_SERVER_receive_done(client, GNUNET_OK);
+ return;
+}
+
+
+/**
+ * Handler for disconnection requests of peers in a tunnel
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message (PeerControl)
+ */
+static void
+handle_local_connect_del (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ struct GNUNET_MESH_PeerControl *peer_msg;
+ struct MeshClient *c;
+ struct MeshTunnel *t;
+ MESH_TunnelNumber tid;
+ GNUNET_PEER_Id peer_id;
+
+ /* Sanity check for client registration */
+ if (NULL == (c = retrieve_client(client))) {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+ peer_msg = (struct GNUNET_MESH_PeerControl *)message;
+ /* Sanity check for message size */
+ if (sizeof(struct GNUNET_MESH_PeerControl)
+ != ntohs(peer_msg->header.size))
+ {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ /* Tunnel exists? */
+ tid = ntohl(peer_msg->tunnel_id);
+ t = retrieve_tunnel_by_local_id(c, tid);
+ if (NULL == t) {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ /* Does client own tunnel? */
+ if (t->client->handle != client) {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ /* Ok, delete peer from tunnel */
+ peer_id = GNUNET_PEER_intern(&peer_msg->peer);
+
+ /* FIXME Delete paths */
+ /* FIXME Delete peer info */
+
+ GNUNET_PEER_change_rc(peer_id, -1);
+
+ GNUNET_SERVER_receive_done(client, GNUNET_OK);
+ return;
+}
+
+
+/**
+ * Handler for connection requests to new peers by type
+ *
+ * @param cls closure
+ * @param client identification of the client
+ * @param message the actual message (ConnectPeerByType)
+ */
+static void
+handle_local_connect_by_type (void *cls,
+ struct GNUNET_SERVER_Client *client,
+ const struct GNUNET_MessageHeader *message)
+{
+ struct GNUNET_MESH_ConnectPeerByType *connect_msg;
+ MESH_TunnelNumber tid;
+ GNUNET_MESH_ApplicationType application;
+ struct MeshClient *c;
+ struct MeshTunnel *t;
+
+ /* Sanity check for client registration */
+ if (NULL == (c = retrieve_client(client))) {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
+ /* Sanity check for message size */
+ if (sizeof(struct GNUNET_MESH_PeerControl) !=
+ ntohs(connect_msg->header.size))
+ {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ /* Tunnel exists? */
+ tid = ntohl(connect_msg->tunnel_id);
+ t = retrieve_tunnel_by_local_id(c, tid);
+ if (NULL == t) {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ /* Does client own tunnel? */
+ if (t->client->handle != client) {
+ GNUNET_break(0);
+ GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
+ return;
+ }
+
+ /* Ok, lets find a peer offering the service */
+ application = ntohl(connect_msg->type);
+ application++; // FIXME silence warnings
+
+ GNUNET_SERVER_receive_done(client, GNUNET_OK);
+ return;
+}
+
+
+/**
+ * Handler for client traffic directed to one peer