+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
+ msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
+ msg.tunnel_id = htonl (tunnel->tid);
+ destroy_tunnel (tunnel);
+ send_packet (h, &msg.header);
+}
+
+
+/**
+ * Request that a peer should be added to the tunnel. The existing
+ * connect handler will be called ONCE with either success or failure.
+ * This function should NOT be called again with the same peer before the
+ * connect handler is called.
+ *
+ * @param tunnel handle to existing tunnel
+ * @param peer peer to add
+ */
+void
+GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
+ const struct GNUNET_PeerIdentity *peer)
+{
+ struct GNUNET_MESH_PeerControl msg;
+ GNUNET_PEER_Id peer_id;
+ unsigned int i;
+
+ peer_id = GNUNET_PEER_intern (peer);
+ for (i = 0; i < tunnel->npeers; i++)
+ {
+ if (tunnel->peers[i]->id == peer_id)
+ {
+ /* Peer already exists in tunnel */
+ GNUNET_PEER_change_rc (peer_id, -1);
+ GNUNET_break (0);
+ return;
+ }
+ }
+ if (NULL == add_peer_to_tunnel (tunnel, peer))
+ return;
+
+ msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
+ msg.tunnel_id = htonl (tunnel->tid);
+ msg.peer = *peer;
+ send_packet (tunnel->mesh, &msg.header);
+
+ return;
+}
+
+
+/**
+ * Request that a peer should be removed from the tunnel. The existing
+ * disconnect handler will be called ONCE if we were connected.
+ *
+ * @param tunnel handle to existing tunnel
+ * @param peer peer to remove
+ */
+void
+GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
+ const struct GNUNET_PeerIdentity *peer)
+{
+ struct GNUNET_MESH_PeerControl msg;
+ GNUNET_PEER_Id peer_id;
+ unsigned int i;
+
+ peer_id = GNUNET_PEER_search (peer);
+ if (0 == peer_id)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ for (i = 0; i < tunnel->npeers; i++)
+ if (tunnel->peers[i]->id == peer_id)
+ break;
+ if (i == tunnel->npeers)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (NULL != tunnel->disconnect_handler && tunnel->peers[i]->connected == 1)
+ tunnel->disconnect_handler (tunnel->cls, peer);
+ GNUNET_PEER_change_rc (peer_id, -1);
+ GNUNET_free (tunnel->peers[i]);
+ tunnel->peers[i] = tunnel->peers[tunnel->npeers - 1];
+ GNUNET_array_grow (tunnel->peers, tunnel->npeers, tunnel->npeers - 1);
+
+ msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
+ msg.tunnel_id = htonl (tunnel->tid);
+ memcpy (&msg.peer, peer, sizeof (struct GNUNET_PeerIdentity));
+ send_packet (tunnel->mesh, &msg.header);
+}
+
+
+/**
+ * Request that the mesh should try to connect to a peer supporting the given
+ * message type.
+ *
+ * @param tunnel handle to existing tunnel
+ * @param app_type application type that must be supported by the peer (MESH
+ * should discover peer in proximity handling this type)
+ */
+void
+GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
+ GNUNET_MESH_ApplicationType app_type)
+{
+ struct GNUNET_MESH_ConnectPeerByType msg;
+
+ GNUNET_array_append (tunnel->apps, tunnel->napps, app_type);
+
+ msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
+ msg.tunnel_id = htonl (tunnel->tid);
+ msg.type = htonl (app_type);
+ send_packet (tunnel->mesh, &msg.header);