diff options
author | Bart Polot <bart@net.in.tum.de> | 2013-06-28 14:34:55 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2013-06-28 14:34:55 +0000 |
commit | cf19b5082fe8de33e38957f54d28647635b46b60 (patch) | |
tree | e6e41da7d5cb14d9a342ef6533633ecb2f34b18d /src | |
parent | 166d8f9122bf7ebbaa2a662d09a3fa4d34f6d092 (diff) |
Replace mesh with new version
Diffstat (limited to 'src')
41 files changed, 2005 insertions, 18060 deletions
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c index 4e94ea5968..f26ddf7347 100644 --- a/src/exit/gnunet-daemon-exit.c +++ b/src/exit/gnunet-daemon-exit.c @@ -209,6 +209,12 @@ struct TunnelState struct GNUNET_MESH_Tunnel *tunnel; /** + * Who is the other end of this tunnel. + * FIXME is this needed? Only used for debugging messages + */ + struct GNUNET_PeerIdentity peer; + + /** * Active tunnel transmission request (or NULL). */ struct GNUNET_MESH_TransmitHandle *th; @@ -493,7 +499,6 @@ process_dns_result (void *cls, ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, - NULL, sizeof (struct GNUNET_MessageHeader) + r, &transmit_reply_to_mesh, ts); @@ -506,18 +511,15 @@ process_dns_result (void *cls, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_dns_request (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + const struct GNUNET_MessageHeader *message) { struct TunnelState *ts = *tunnel_ctx; const struct GNUNET_TUN_DnsHeader *dns; @@ -782,7 +784,6 @@ send_to_peer_notify_callback (void *cls, size_t size, void *buf) s->th = GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO /* corking */, GNUNET_TIME_UNIT_FOREVER_REL, - NULL, tnq->len, &send_to_peer_notify_callback, s); @@ -799,7 +800,6 @@ send_to_peer_notify_callback (void *cls, size_t size, void *buf) s->th = GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO /* corking */, GNUNET_TIME_UNIT_FOREVER_REL, - NULL, tnq->len, &send_to_peer_notify_callback, s); @@ -817,19 +817,19 @@ send_to_peer_notify_callback (void *cls, size_t size, void *buf) * @param tnq message to queue */ static void -send_packet_to_mesh_tunnel (struct GNUNET_MESH_Tunnel *mesh_tunnel, +send_packet_to_mesh_tunnel (struct TunnelState *s, struct TunnelMessageQueue *tnq) { - struct TunnelState *s; + struct GNUNET_MESH_Tunnel *mesh_tunnel; - s = GNUNET_MESH_tunnel_get_data (mesh_tunnel); + mesh_tunnel = s->tunnel; GNUNET_assert (NULL != s); GNUNET_CONTAINER_DLL_insert_tail (s->specifics.tcp_udp.head, s->specifics.tcp_udp.tail, tnq); if (NULL == s->th) s->th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO /* cork */, GNUNET_TIME_UNIT_FOREVER_REL, - NULL, tnq->len, + tnq->len, &send_to_peer_notify_callback, s); } @@ -1019,8 +1019,7 @@ icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp, memcpy (&i2v->icmp_header, icmp, pktlen); - send_packet_to_mesh_tunnel (state->tunnel, - tnq); + send_packet_to_mesh_tunnel (state, tnq); } @@ -1097,8 +1096,7 @@ udp_from_helper (const struct GNUNET_TUN_UdpHeader *udp, memcpy (&urm[1], &udp[1], pktlen - sizeof (struct GNUNET_TUN_UdpHeader)); - send_packet_to_mesh_tunnel (state->tunnel, - tnq); + send_packet_to_mesh_tunnel (state, tnq); } @@ -1186,8 +1184,7 @@ tcp_from_helper (const struct GNUNET_TUN_TcpHeader *tcp, memcpy (&tdm->tcp_header, buf, pktlen); - send_packet_to_mesh_tunnel (state->tunnel, - tnq); + send_packet_to_mesh_tunnel (state, tnq); } @@ -1796,18 +1793,15 @@ send_tcp_packet_via_tun (const struct SocketAddress *destination_address, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_tcp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx GNUNET_UNUSED, - const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + const struct GNUNET_MessageHeader *message) { struct TunnelState *state = *tunnel_ctx; const struct GNUNET_EXIT_TcpServiceStartMessage *start; @@ -1853,7 +1847,7 @@ receive_tcp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, /* setup fresh connection */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received data from %s for forwarding to TCP service %s on port %u\n", - GNUNET_i2s (sender), + GNUNET_i2s (&state->peer), GNUNET_h2s (&start->service_descriptor), (unsigned int) ntohs (start->tcp_header.destination_port)); if (NULL == (state->specifics.tcp_udp.serv = find_service (tcp_services, &start->service_descriptor, @@ -1884,18 +1878,15 @@ receive_tcp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx GNUNET_UNUSED, - const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + const struct GNUNET_MessageHeader *message) { struct TunnelState *state = *tunnel_ctx; const struct GNUNET_EXIT_TcpInternetStartMessage *start; @@ -1984,7 +1975,7 @@ receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, char buf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received data from %s for starting TCP stream to %s:%u\n", - GNUNET_i2s (sender), + GNUNET_i2s (&state->peer), inet_ntop (af, &state->specifics.tcp_udp.ri.remote_address.address, buf, sizeof (buf)), @@ -2008,18 +1999,15 @@ receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_tcp_data (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx GNUNET_UNUSED, - const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + const struct GNUNET_MessageHeader *message) { struct TunnelState *state = *tunnel_ctx; const struct GNUNET_EXIT_TcpDataMessage *data; @@ -2069,7 +2057,7 @@ receive_tcp_data (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received additional %u bytes of data from %s for TCP stream to %s:%u\n", pkt_len, - GNUNET_i2s (sender), + GNUNET_i2s (&state->peer), inet_ntop (state->specifics.tcp_udp.ri.remote_address.af, &state->specifics.tcp_udp.ri.remote_address.address, buf, sizeof (buf)), @@ -2244,18 +2232,15 @@ make_up_icmpv6_payload (struct TunnelState *state, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_icmp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx GNUNET_UNUSED, - const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + const struct GNUNET_MessageHeader *message) { struct TunnelState *state = *tunnel_ctx; const struct GNUNET_EXIT_IcmpInternetMessage *msg; @@ -2428,7 +2413,7 @@ receive_icmp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, char buf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ICMP data from %s for forwarding to %s\n", - GNUNET_i2s (sender), + GNUNET_i2s (&state->peer), inet_ntop (af, &state->specifics.tcp_udp.ri.remote_address.address, buf, sizeof (buf))); @@ -2498,18 +2483,15 @@ make_up_icmp_service_payload (struct TunnelState *state, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_icmp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + const struct GNUNET_MessageHeader *message) { struct TunnelState *state = *tunnel_ctx; const struct GNUNET_EXIT_IcmpServiceMessage *msg; @@ -2544,7 +2526,7 @@ receive_icmp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received data from %s for forwarding to ICMP service %s\n", - GNUNET_i2s (sender), + GNUNET_i2s (&state->peer), GNUNET_h2s (&msg->service_descriptor)); if (NULL == state->specifics.tcp_udp.serv) { @@ -2789,18 +2771,15 @@ send_udp_packet_via_tun (const struct SocketAddress *destination_address, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx GNUNET_UNUSED, - const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + const struct GNUNET_MessageHeader *message) { struct TunnelState *state = *tunnel_ctx; const struct GNUNET_EXIT_UdpInternetMessage *msg; @@ -2877,7 +2856,7 @@ receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, char buf[INET6_ADDRSTRLEN]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received data from %s for forwarding to UDP %s:%u\n", - GNUNET_i2s (sender), + GNUNET_i2s (&state->peer), inet_ntop (af, &state->specifics.tcp_udp.ri.remote_address.address, buf, sizeof (buf)), @@ -2903,18 +2882,15 @@ receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + const struct GNUNET_MessageHeader *message) { struct TunnelState *state = *tunnel_ctx; const struct GNUNET_EXIT_UdpServiceMessage *msg; @@ -2946,7 +2922,7 @@ receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, pkt_len -= sizeof (struct GNUNET_EXIT_UdpServiceMessage); LOG (GNUNET_ERROR_TYPE_DEBUG, "Received data from %s for forwarding to UDP service %s on port %u\n", - GNUNET_i2s (sender), + GNUNET_i2s (&state->peer), GNUNET_h2s (&msg->service_descriptor), (unsigned int) ntohs (msg->destination_port)); if (NULL == (state->specifics.tcp_udp.serv = find_service (udp_services, &msg->service_descriptor, @@ -2978,17 +2954,17 @@ receive_udp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, * @param cls closure * @param tunnel new handle to the tunnel * @param initiator peer that started the tunnel - * @param atsi performance information for the tunnel + * @param port destination port * @return initial tunnel context for the tunnel */ static void * new_tunnel (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *initiator GNUNET_UNUSED, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + const struct GNUNET_PeerIdentity *initiator, uint32_t port) { struct TunnelState *s = GNUNET_malloc (sizeof (struct TunnelState)); s->is_dns = GNUNET_SYSERR; + s->peer = *initiator; GNUNET_STATISTICS_update (stats, gettext_noop ("# Inbound MESH tunnels created"), 1, GNUNET_NO); @@ -3338,7 +3314,7 @@ run (void *cls, char *const *args GNUNET_UNUSED, {NULL, 0, 0} }; - static GNUNET_MESH_ApplicationType apptypes[] = { + static uint32_t apptypes[] = { GNUNET_APPLICATION_TYPE_END, GNUNET_APPLICATION_TYPE_END, GNUNET_APPLICATION_TYPE_END, @@ -3413,7 +3389,7 @@ run (void *cls, char *const *args GNUNET_UNUSED, GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("No useful service enabled. Exiting.\n")); GNUNET_SCHEDULER_shutdown (); - return; + return; } dns_exit = NULL; @@ -3436,18 +3412,21 @@ run (void *cls, char *const *args GNUNET_UNUSED, app_idx = 0; - if (GNUNET_YES == ipv4_exit) + if (GNUNET_YES == ipv4_exit) { + // FIXME use regex to put info apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV4_GATEWAY; app_idx++; } - if (GNUNET_YES == ipv6_exit) + if (GNUNET_YES == ipv6_exit) { + // FIXME use regex to put info apptypes[app_idx] = GNUNET_APPLICATION_TYPE_IPV6_GATEWAY; app_idx++; } if (NULL != dns_exit) { + // FIXME use regex to put info apptypes[app_idx] = GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER; app_idx++; } @@ -3568,7 +3547,7 @@ run (void *cls, char *const *args GNUNET_UNUSED, = GNUNET_MESH_connect (cfg, NULL, &new_tunnel, &clean_tunnel, handlers, - apptypes); + apptypes); // FIXME use ports if (NULL == mesh_handle) { GNUNET_SCHEDULER_shutdown (); diff --git a/src/fs/gnunet-service-fs_mesh.c b/src/fs/gnunet-service-fs_mesh.c index 10b29fa844..9eda536a9f 100644 --- a/src/fs/gnunet-service-fs_mesh.c +++ b/src/fs/gnunet-service-fs_mesh.c @@ -41,7 +41,7 @@ #include "platform.h" #include "gnunet_constants.h" #include "gnunet_util_lib.h" -#include "gnunet_mesh2_service.h" +#include "gnunet_mesh_service.h" #include "gnunet_protocols.h" #include "gnunet_applications.h" #include "gnunet-service-fs.h" diff --git a/src/include/block_mesh.h b/src/include/block_mesh.h index 9dfb859454..508f52699b 100644 --- a/src/include/block_mesh.h +++ b/src/include/block_mesh.h @@ -48,10 +48,6 @@ struct PBlock */ struct GNUNET_PeerIdentity id; - /** - * Type of service offered - */ - GNUNET_MESH_ApplicationType type; }; #if 0 /* keep Emacsens' auto-indent happy */ diff --git a/src/include/gnunet_mesh2_service.h b/src/include/gnunet_mesh2_service.h deleted file mode 100644 index 019dc8431f..0000000000 --- a/src/include/gnunet_mesh2_service.h +++ /dev/null @@ -1,398 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009, 2010, 2011, 2012, 2013 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file include/gnunet_mesh2_service.h - * @brief mesh service; establish tunnels to distant peers - * @author Christian Grothoff - * - * TODO: - * - need to do sanity check that this is consistent - * with current ideas for the multicast layer's needs - */ - -#ifndef GNUNET_MESH_SERVICE_H -#define GNUNET_MESH_SERVICE_H - -#ifdef __cplusplus -extern "C" -{ -#if 0 /* keep Emacsens' auto-indent happy */ -} -#endif -#endif - -#include "gnunet_util_lib.h" -#include "gnunet_transport_service.h" - -/** - * Version number of GNUnet-mesh API. - */ -#define GNUNET_MESH_VERSION 0x00000001 - - -/** - * Opaque handle to the service. - */ -struct GNUNET_MESH_Handle; - -/** - * Opaque handle to a tunnel. - */ -struct GNUNET_MESH_Tunnel; - - -/** - * Functions with this signature are called whenever a message is - * received. - * - * Each time the function must call GNUNET_MESH_receive_done on the tunnel - * in order to receive the next message. This doesn't need to be immediate: - * can be delayed if some processing is done on the message. - * - * @param cls Closure (set from GNUNET_MESH_connect). - * @param tunnel Connection to the other end. - * @param tunnel_ctx Place to store local state associated with the tunnel. - * @param message The actual message. - * - * @return GNUNET_OK to keep the tunnel open, - * GNUNET_SYSERR to close it (signal serious error). - */ -typedef int (*GNUNET_MESH_MessageCallback) (void *cls, - struct GNUNET_MESH_Tunnel *tunnel, - void **tunnel_ctx, - const struct GNUNET_MessageHeader *message); - - -/** - * Message handler. Each struct specifies how to handle on particular - * type of message received. - */ -struct GNUNET_MESH_MessageHandler -{ - /** - * Function to call for messages of "type". - */ - GNUNET_MESH_MessageCallback callback; - - /** - * Type of the message this handler covers. - */ - uint16_t type; - - /** - * Expected size of messages of this type. Use 0 for variable-size. - * If non-zero, messages of the given type will be discarded if they - * do not have the right size. - */ - uint16_t expected_size; -}; - - -/** - * Method called whenever another peer has added us to a tunnel - * the other peer initiated. - * Only called (once) upon reception of data with a message type which was - * subscribed to in GNUNET_MESH_connect. A call to GNUNET_MESH_tunnel_destroy - * causes te tunnel to be ignored and no further notifications are sent about - * the same tunnel. - * - * @param cls closure - * @param tunnel new handle to the tunnel - * @param initiator peer that started the tunnel - * @param port Port this tunnel is for. - * @return initial tunnel context for the tunnel - * (can be NULL -- that's not an error) - */ -typedef void *(GNUNET_MESH_InboundTunnelNotificationHandler) (void *cls, - struct - GNUNET_MESH_Tunnel - * tunnel, - const struct - GNUNET_PeerIdentity - * initiator, - uint32_t port); - - -/** - * Function called whenever a tunnel is destroyed. Should clean up - * any associated state. - * - * It must NOT call GNUNET_MESH_tunnel_destroy on the tunnel. - * - * @param cls closure (set from GNUNET_MESH_connect) - * @param tunnel connection to the other end (henceforth invalid) - * @param tunnel_ctx place where local state associated - * with the tunnel is stored - */ -typedef void (GNUNET_MESH_TunnelEndHandler) (void *cls, - const struct GNUNET_MESH_Tunnel * - tunnel, void *tunnel_ctx); - - -/** - * Connect to the mesh service. - * - * @param cfg Configuration to use. - * @param cls Closure for the various callbacks that follow (including - * handlers in the handlers array). - * @param new_tunnel Function called when an *inbound* tunnel is created. - * Can be NULL if no inbound tunnels are desired. - * @param cleaner Function called when a tunnel is destroyed by the remote peer. - * It is NOT called if GNUNET_MESH_tunnel_destroy is called on - * the tunnel. - * @param handlers Callbacks for messages we care about, NULL-terminated. Each - * one must call GNUNET_MESH_receive_done on the tunnel to - * receive the next message. Messages of a type that is not - * in the handlers array are ignored if received. - * @param ports NULL or 0-terminated array of port numbers for incoming tunnels. - * - * @return handle to the mesh service NULL on error - * (in this case, init is never called) - */ -struct GNUNET_MESH_Handle * -GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, - GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, - GNUNET_MESH_TunnelEndHandler cleaner, - const struct GNUNET_MESH_MessageHandler *handlers, - const uint32_t *ports); - - -/** - * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel - * disconnect callbacks will be called on any still connected peers, notifying - * about their disconnection. The registered inbound tunnel cleaner will be - * called should any inbound tunnels still exist. - * - * @param handle connection to mesh to disconnect - */ -void -GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle); - - -/** - * Create a new tunnel (we're initiator and will be allowed to add/remove peers - * and to broadcast). - * - * @param h mesh handle - * @param tunnel_ctx client's tunnel context to associate with the tunnel - * @param peer peer identity the tunnel should go to - * @param port Port number. - * @return handle to the tunnel - */ -struct GNUNET_MESH_Tunnel * -GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, - void *tunnel_ctx, - const struct GNUNET_PeerIdentity *peer, - uint32_t port); - - -/** - * Destroy an existing tunnel. - * - * The existing end callback for the tunnel will be called immediately. - * Any pending outgoing messages will be sent but no incoming messages will be - * accepted and no data callbacks will be called. - * - * @param tunnel Tunnel handle, becomes invalid after this call. - */ -void -GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel); - - -/** - * Turn on/off the buffering status of the tunnel. - * - * @param tunnel Tunnel affected. - * @param buffer GNUNET_YES to turn buffering on (default), - * GNUNET_NO otherwise. - */ -void -GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer); - - -/** - * Handle for a transmission request. - */ -struct GNUNET_MESH_TransmitHandle; - - -/** - * Ask the mesh to call "notify" once it is ready to transmit the - * given number of bytes to the specified tunnel. - * Only one call can be active at any time, to issue another request, - * wait for the callback or cancel the current request. - * - * @param tunnel tunnel to use for transmission - * @param cork is corking allowed for this transmission? - * @param maxdelay how long can the message wait? - * @param notify_size how many bytes of buffer space does notify want? - * @param notify function to call when buffer space is available; - * will be called with NULL on timeout or if the overall queue - * for this peer is larger than queue_size and this is currently - * the message with the lowest priority - * @param notify_cls closure for notify - * @return non-NULL if the notify callback was queued, - * NULL if we can not even queue the request (insufficient - * memory); if NULL is returned, "notify" will NOT be called. - */ -struct GNUNET_MESH_TransmitHandle * -GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork, - struct GNUNET_TIME_Relative maxdelay, - size_t notify_size, - GNUNET_CONNECTION_TransmitReadyNotify notify, - void *notify_cls); - - -/** - * Cancel the specified transmission-ready notification. - * - * @param th handle that was returned by "notify_transmit_ready". - */ -void -GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle - *th); - - -/** - * Indicate readiness to receive the next message on a tunnel. - * - * Should only be called once per handler called. - * - * @param tunnel Tunnel that will be allowed to call another handler. - */ -void -GNUNET_MESH_receive_done (struct GNUNET_MESH_Tunnel *tunnel); - - - -/******************************************************************************/ -/******************** MONITORING /DEBUG API *************************/ -/******************************************************************************/ -/* The following calls are not useful for normal MESH operation, but for */ -/* debug and monitoring of the mesh state. They can be safely ignored. */ -/* The API can change at any point without notice. */ -/* Please contact the developer if you consider any of this calls useful for */ -/* normal mesh applications. */ -/******************************************************************************/ - -/** - * Method called to retrieve information about each tunnel the mesh peer - * is aware of. - * - * @param cls Closure. - * @param tunnel_number Tunnel number. - * @param origin that started the tunnel (owner). - * @param target other endpoint of the tunnel - */ -typedef void (*GNUNET_MESH_TunnelsCB) (void *cls, - uint32_t tunnel_number, - const struct GNUNET_PeerIdentity *origin, - const struct GNUNET_PeerIdentity *target); - - -/** - * Method called to retrieve information about a specific tunnel the mesh peer - * is aware of, including all transit nodes. - * - * @param cls Closure. - * @param peer Peer in the tunnel's tree. - * @param parent Parent of the current peer. All 0 when peer is root. - */ -typedef void (*GNUNET_MESH_TunnelCB) (void *cls, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_PeerIdentity *parent); - - -/** - * Request information about the running mesh peer. - * The callback will be called for every tunnel known to the service, - * listing all active peers that belong to the tunnel. - * - * If called again on the same handle, it will overwrite the previous - * callback and cls. To retrieve the cls, monitor_cancel must be - * called first. - * - * WARNING: unstable API, likely to change in the future! - * - * @param h Handle to the mesh peer. - * @param callback Function to call with the requested data. - * @param callback_cls Closure for @c callback. - */ -void -GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h, - GNUNET_MESH_TunnelsCB callback, - void *callback_cls); - - -/** - * Request information about a specific tunnel of the running mesh peer. - * - * WARNING: unstable API, likely to change in the future! - * - * @param h Handle to the mesh peer. - * @param initiator ID of the owner of the tunnel. - * @param tunnel_number Tunnel number. - * @param callback Function to call with the requested data. - * @param callback_cls Closure for @c callback. - */ -void -GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h, - struct GNUNET_PeerIdentity *initiator, - uint32_t tunnel_number, - GNUNET_MESH_TunnelCB callback, - void *callback_cls); - - -/** - * Cancel a monitor request. The monitor callback will not be called. - * - * WARNING: unstable API, likely to change in the future! - * - * @param h Mesh handle. - * - * @return Closure given to GNUNET_MESH_monitor, if any. - */ -void * -GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h); - - -/** - * Create a message queue for a mesh tunnel. - * The message queue can only be used to transmit messages, - * not to receive them. - * - * @param tunnel the tunnel to create the message qeue for - * @return a message queue to messages over the tunnel - */ -struct GNUNET_MQ_Handle * -GNUNET_MESH_mq_create (struct GNUNET_MESH_Tunnel *tunnel); - - -#if 0 /* keep Emacsens' auto-indent happy */ -{ -#endif -#ifdef __cplusplus -} -#endif - -/* ifndef GNUNET_MESH_SERVICE_H */ -#endif -/* end of gnunet_mesh_service.h */ diff --git a/src/include/gnunet_mesh_service.h b/src/include/gnunet_mesh_service.h index 3005c1239d..c64cfb64cf 100644 --- a/src/include/gnunet_mesh_service.h +++ b/src/include/gnunet_mesh_service.h @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2009, 2010 Christian Grothoff (and other contributing authors) + (C) 2009, 2010, 2011, 2012, 2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -22,6 +22,10 @@ * @file include/gnunet_mesh_service.h * @brief mesh service; establish tunnels to distant peers * @author Christian Grothoff + * + * TODO: + * - need to do sanity check that this is consistent + * with current ideas for the multicast layer's needs */ #ifndef GNUNET_MESH_SERVICE_H @@ -41,7 +45,7 @@ extern "C" /** * Version number of GNUnet-mesh API. */ -#define GNUNET_MESH_VERSION 0x00000000 +#define GNUNET_MESH_VERSION 0x00000001 /** @@ -54,28 +58,27 @@ struct GNUNET_MESH_Handle; */ struct GNUNET_MESH_Tunnel; + /** * Functions with this signature are called whenever a message is * received. + * + * Each time the function must call GNUNET_MESH_receive_done on the tunnel + * in order to receive the next message. This doesn't need to be immediate: + * can be delayed if some processing is done on the message. * - * @param cls closure (set from GNUNET_MESH_connect) - * @param tunnel connection to the other end - * @param tunnel_ctx place to store local state associated with the tunnel - * @param sender who sent the message - * @param message the actual message - * @param atsi performance data for the connection - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) + * @param cls Closure (set from GNUNET_MESH_connect). + * @param tunnel Connection to the other end. + * @param tunnel_ctx Place to store local state associated with the tunnel. + * @param message The actual message. + * + * @return GNUNET_OK to keep the tunnel open, + * GNUNET_SYSERR to close it (signal serious error). */ typedef int (*GNUNET_MESH_MessageCallback) (void *cls, - struct GNUNET_MESH_Tunnel * tunnel, + struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity * - sender, - const struct GNUNET_MessageHeader * - message, - const struct GNUNET_ATS_Information - * atsi); + const struct GNUNET_MessageHeader *message); /** @@ -100,7 +103,6 @@ struct GNUNET_MESH_MessageHandler * do not have the right size. */ uint16_t expected_size; - }; @@ -115,7 +117,7 @@ struct GNUNET_MESH_MessageHandler * @param cls closure * @param tunnel new handle to the tunnel * @param initiator peer that started the tunnel - * @param atsi performance information for the tunnel + * @param port Port this tunnel is for. * @return initial tunnel context for the tunnel * (can be NULL -- that's not an error) */ @@ -126,17 +128,14 @@ typedef void *(GNUNET_MESH_InboundTunnelNotificationHandler) (void *cls, const struct GNUNET_PeerIdentity * initiator, - const struct - GNUNET_ATS_Information - * atsi); + uint32_t port); /** - * Function called whenever an inbound tunnel is destroyed. Should clean up - * any associated state. This function is NOT called if the client has - * explicitly asked for the tunnel to be destroyed using - * GNUNET_MESH_tunnel_destroy. It must NOT call GNUNET_MESH_tunnel_destroy on - * the tunnel. + * Function called whenever a tunnel is destroyed. Should clean up + * any associated state. + * + * It must NOT call GNUNET_MESH_tunnel_destroy on the tunnel. * * @param cls closure (set from GNUNET_MESH_connect) * @param tunnel connection to the other end (henceforth invalid) @@ -149,27 +148,22 @@ typedef void (GNUNET_MESH_TunnelEndHandler) (void *cls, /** - * Type for an application. Values defined in gnunet_applications.h - * DEPRECATED - not present in mesh2 - */ -typedef uint32_t GNUNET_MESH_ApplicationType; - - -/** * Connect to the mesh service. * - * @param cfg configuration to use - * @param cls closure for the various callbacks that follow - * (including handlers in the handlers array) - * @param new_tunnel function called when an *inbound* tunnel is created - * @param cleaner function called when an *inbound* tunnel is destroyed by the - * remote peer, it is *not* called if GNUNET_MESH_tunnel_destroy - * is called on the tunnel - * @param handlers callbacks for messages we care about, NULL-terminated - * note that the mesh is allowed to drop notifications about - * inbound messages if the client does not process them fast - * enough (for this notification type, a bounded queue is used) - * @param stypes list of the applications that this client claims to provide + * @param cfg Configuration to use. + * @param cls Closure for the various callbacks that follow (including + * handlers in the handlers array). + * @param new_tunnel Function called when an *inbound* tunnel is created. + * Can be NULL if no inbound tunnels are desired. + * @param cleaner Function called when a tunnel is destroyed by the remote peer. + * It is NOT called if GNUNET_MESH_tunnel_destroy is called on + * the tunnel. + * @param handlers Callbacks for messages we care about, NULL-terminated. Each + * one must call GNUNET_MESH_receive_done on the tunnel to + * receive the next message. Messages of a type that is not + * in the handlers array are ignored if received. + * @param ports NULL or 0-terminated array of port numbers for incoming tunnels. + * * @return handle to the mesh service NULL on error * (in this case, init is never called) */ @@ -178,7 +172,7 @@ GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, GNUNET_MESH_TunnelEndHandler cleaner, const struct GNUNET_MESH_MessageHandler *handlers, - const GNUNET_MESH_ApplicationType *stypes); + const uint32_t *ports); /** @@ -194,104 +188,33 @@ GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle); /** - * Method called whenever a peer has disconnected from the tunnel. - * Implementations of this callback must NOT call - * GNUNET_MESH_tunnel_destroy immediately, but instead schedule those - * to run in some other task later. However, calling - * "GNUNET_MESH_notify_transmit_ready_cancel" is allowed. - * - * @param cls closure - * @param peer peer identity the tunnel stopped working with - */ -typedef void (*GNUNET_MESH_PeerDisconnectHandler) (void *cls, - const struct - GNUNET_PeerIdentity * peer); - - -/** - * Method called whenever a peer has connected to the tunnel. - * - * @param cls closure - * @param peer peer identity the tunnel was created to, NULL on timeout - * @param atsi performance data for the connection - * - * TODO: change to return int to let client allow the new peer or not? - */ -typedef void (*GNUNET_MESH_PeerConnectHandler) (void *cls, - const struct GNUNET_PeerIdentity - * peer, - const struct - GNUNET_ATS_Information * atsi); - - -/** - * Announce to ther peer the availability of services described by the regex, - * in order to be reachable to other peers via connect_by_string. - * - * Note that the first GNUNET_REGEX_INITIAL_BYTES characters are considered - * to be part of a prefix, (for instance 'gnunet://'). - * If you put a variable part in there (*, +. ()), all matching strings - * will be stored in the DHT. - * - * @param h Handle to mesh. - * @param regex String with the regular expression describing local services. - * @param compression_characters How many characters can be assigned to one - * edge of the graph. The bigger the variability - * of the data, the smaller this parameter should - * be (down to 1). - * For maximum compression, use strlen (regex) - * or 0 (special value). Use with care! - */ -void -GNUNET_MESH_announce_regex (struct GNUNET_MESH_Handle *h, - const char *regex, - unsigned int compression_characters); - - -/** * Create a new tunnel (we're initiator and will be allowed to add/remove peers * and to broadcast). * * @param h mesh handle * @param tunnel_ctx client's tunnel context to associate with the tunnel - * @param connect_handler function to call when peers are actually connected - * @param disconnect_handler function to call when peers are disconnected - * @param handler_cls closure for connect/disconnect handlers + * @param peer peer identity the tunnel should go to + * @param port Port number. + * @return handle to the tunnel */ struct GNUNET_MESH_Tunnel * -GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx, - GNUNET_MESH_PeerConnectHandler connect_handler, - GNUNET_MESH_PeerDisconnectHandler disconnect_handler, - void *handler_cls); - -/** - * Destroy an existing tunnel. The existing callback for the tunnel will NOT - * be called. - * - * @param tunnel tunnel handle - */ -void -GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel); +GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, + void *tunnel_ctx, + const struct GNUNET_PeerIdentity *peer, + uint32_t port); /** - * Request that the tunnel data rate is limited to the speed of the slowest - * receiver. + * Destroy an existing tunnel. * - * @param tunnel Tunnel affected. - */ -void -GNUNET_MESH_tunnel_speed_min (struct GNUNET_MESH_Tunnel *tunnel); - - -/** - * Request that the tunnel data rate is limited to the speed of the fastest - * receiver. This is the default behavior. - * - * @param tunnel Tunnel affected. + * The existing end callback for the tunnel will be called immediately. + * Any pending outgoing messages will be sent but no incoming messages will be + * accepted and no data callbacks will be called. + * + * @param tunnel Tunnel handle, becomes invalid after this call. */ void -GNUNET_MESH_tunnel_speed_max (struct GNUNET_MESH_Tunnel *tunnel); +GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel); /** @@ -306,82 +229,6 @@ GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer); /** - * Request that a peer should be added to the tunnel. The connect handler - * will be called when the peer connects - * - * @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); - - -/** - * 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); - - -/** - * 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); - - -/** - * Request that the mesh should try to connect to a peer matching the - * description given in the service string. - * - * @param tunnel handle to existing tunnel - * @param description string describing the destination node requirements - */ -void -GNUNET_MESH_peer_request_connect_by_string (struct GNUNET_MESH_Tunnel *tunnel, - const char *description); - - -/** - * Request that the given peer isn't added to this tunnel in calls to - * connect_by_* calls, (due to misbehaviour, bad performance, ...). - * - * @param tunnel handle to existing tunnel. - * @param peer peer identity of the peer which should be blacklisted - * for the tunnel. - */ -void -GNUNET_MESH_peer_blacklist (struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *peer); - - -/** - * Request that the given peer isn't blacklisted anymore from this tunnel, - * and therefore can be added in future calls to connect_by_*. - * The peer must have been previously blacklisted for this tunnel. - * - * @param tunnel handle to existing tunnel. - * @param peer peer identity of the peer which shouldn't be blacklisted - * for the tunnel anymore. - */ -void -GNUNET_MESH_peer_unblacklist (struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *peer); - - -/** * Handle for a transmission request. */ struct GNUNET_MESH_TransmitHandle; @@ -389,15 +236,13 @@ struct GNUNET_MESH_TransmitHandle; /** * Ask the mesh to call "notify" once it is ready to transmit the - * given number of bytes to the specified tunnel or target. + * given number of bytes to the specified tunnel. * Only one call can be active at any time, to issue another request, * wait for the callback or cancel the current request. * * @param tunnel tunnel to use for transmission * @param cork is corking allowed for this transmission? * @param maxdelay how long can the message wait? - * @param target destination for the message - * NULL for multicast to all tunnel targets * @param notify_size how many bytes of buffer space does notify want? * @param notify function to call when buffer space is available; * will be called with NULL on timeout or if the overall queue @@ -411,7 +256,6 @@ struct GNUNET_MESH_TransmitHandle; struct GNUNET_MESH_TransmitHandle * GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork, struct GNUNET_TIME_Relative maxdelay, - const struct GNUNET_PeerIdentity *target, size_t notify_size, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls); @@ -428,20 +272,40 @@ GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle /** + * Indicate readiness to receive the next message on a tunnel. + * + * Should only be called once per handler called. + * + * @param tunnel Tunnel that will be allowed to call another handler. + */ +void +GNUNET_MESH_receive_done (struct GNUNET_MESH_Tunnel *tunnel); + + + +/******************************************************************************/ +/******************** MONITORING /DEBUG API *************************/ +/******************************************************************************/ +/* The following calls are not useful for normal MESH operation, but for */ +/* debug and monitoring of the mesh state. They can be safely ignored. */ +/* The API can change at any point without notice. */ +/* Please contact the developer if you consider any of this calls useful for */ +/* normal mesh applications. */ +/******************************************************************************/ + +/** * Method called to retrieve information about each tunnel the mesh peer * is aware of. * * @param cls Closure. - * @param initiator Peer that started the tunnel (owner). * @param tunnel_number Tunnel number. - * @param peers Array of peer identities that participate in the tunnel. - * @param npeers Number of peers in peers. + * @param origin that started the tunnel (owner). + * @param target other endpoint of the tunnel */ typedef void (*GNUNET_MESH_TunnelsCB) (void *cls, - const struct GNUNET_PeerIdentity *owner, - unsigned int tunnel_number, - const struct GNUNET_PeerIdentity *peers, - unsigned int npeers); + uint32_t tunnel_number, + const struct GNUNET_PeerIdentity *origin, + const struct GNUNET_PeerIdentity *target); /** @@ -460,7 +324,7 @@ typedef void (*GNUNET_MESH_TunnelCB) (void *cls, /** * Request information about the running mesh peer. * The callback will be called for every tunnel known to the service, - * listing all active peers that blong to the tunnel. + * listing all active peers that belong to the tunnel. * * If called again on the same handle, it will overwrite the previous * callback and cls. To retrieve the cls, monitor_cancel must be @@ -492,7 +356,7 @@ GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h, void GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h, struct GNUNET_PeerIdentity *initiator, - unsigned int tunnel_number, + uint32_t tunnel_number, GNUNET_MESH_TunnelCB callback, void *callback_cls); @@ -511,20 +375,15 @@ GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h); /** - * Transition API for tunnel ctx management - * - * FIXME deprecated - */ -void -GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data); - -/** - * Transition API for tunnel ctx management - * - * FIXME deprecated + * Create a message queue for a mesh tunnel. + * The message queue can only be used to transmit messages, + * not to receive them. + * + * @param tunnel the tunnel to create the message qeue for + * @return a message queue to messages over the tunnel */ -void * -GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel); +struct GNUNET_MQ_Handle * +GNUNET_MESH_mq_create (struct GNUNET_MESH_Tunnel *tunnel); #if 0 /* keep Emacsens' auto-indent happy */ diff --git a/src/include/gnunet_stream_lib.h b/src/include/gnunet_stream_lib.h index f89815c57c..8ee430f5a6 100644 --- a/src/include/gnunet_stream_lib.h +++ b/src/include/gnunet_stream_lib.h @@ -151,7 +151,7 @@ enum GNUNET_STREAM_Option struct GNUNET_STREAM_Socket * GNUNET_STREAM_open (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *target, - GNUNET_MESH_ApplicationType app_port, + uint32_t app_port, GNUNET_STREAM_OpenCallback open_cb, void *open_cb_cls, ...); @@ -252,7 +252,7 @@ struct GNUNET_STREAM_ListenSocket; */ struct GNUNET_STREAM_ListenSocket * GNUNET_STREAM_listen (const struct GNUNET_CONFIGURATION_Handle *cfg, - GNUNET_MESH_ApplicationType app_port, + uint32_t app_port, GNUNET_STREAM_ListenCallback listen_cb, void *listen_cb_cls, ...); diff --git a/src/mesh/Makefile.am b/src/mesh/Makefile.am index c0d66ace3f..e1c607d7fc 100644 --- a/src/mesh/Makefile.am +++ b/src/mesh/Makefile.am @@ -20,21 +20,6 @@ plugindir = $(libdir)/gnunet AM_CLFAGS = -g -if HAVE_EXPERIMENTAL - noinst_LIB_EXP = libgnunetmesh2test.a - EXP_LIB = libgnunetmesh2.la - EXP_LIBEXEC = gnunet-service-mesh-new - EXP_TESTS = \ - test_mesh2_local \ - test_mesh2_small_forward \ - test_mesh2_small_signal \ - test_mesh2_small_speed \ - test_mesh2_small_speed_ack \ - test_mesh2_small_speed_nobuf \ - test_mesh2_small_speed_backwards \ - test_mesh2_small_speed_nobuf_backwards -endif - libexec_PROGRAMS = \ gnunet-service-mesh $(EXP_LIBEXEC) @@ -58,6 +43,7 @@ libgnunet_plugin_block_mesh_la_DEPENDENCIES = \ $(top_builddir)/src/block/libgnunetblock.la \ $(top_builddir)/src/util/libgnunetutil.la + libgnunetmesh_la_SOURCES = \ mesh_api.c mesh_common.c libgnunetmesh_la_LIBADD = \ @@ -66,41 +52,7 @@ libgnunetmesh_la_LIBADD = \ $(LTLIBINTL) libgnunetmesh_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 2:1:1 - -libgnunetmesh2_la_SOURCES = \ - mesh2_api.c mesh_common.c -libgnunetmesh2_la_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(XLIB) \ - $(LTLIBINTL) -libgnunetmesh2_la_LDFLAGS = \ - $(GN_LIB_LDFLAGS) $(WINFLAGS) \ - -version-info 2:2:1 - - -gnunet_service_mesh_SOURCES = \ - gnunet-service-mesh.c \ - mesh_tunnel_tree.c mesh_tunnel_tree.h \ - mesh_common.c -gnunet_service_mesh_CFLAGS = $(AM_CFLAGS) -gnunet_service_mesh_LDADD = \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/regex/libgnunetregex.la \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/block/libgnunetblock.la -gnunet_service_mesh_DEPENDENCIES = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/dht/libgnunetdht.la \ - $(top_builddir)/src/statistics/libgnunetstatistics.la \ - $(top_builddir)/src/block/libgnunetblock.la \ - $(top_builddir)/src/regex/libgnunetregex.la -if LINUX -gnunet_service_mesh_LDFLAGS = -lrt -endif + -version-info 3:0:0 gnunet_mesh_SOURCES = \ gnunet-mesh.c @@ -110,25 +62,25 @@ gnunet_mesh_LDADD = \ gnunet_mesh_DEPENDENCIES = \ libgnunetmesh.la -gnunet_service_mesh_new_SOURCES = \ - gnunet-service-mesh-new.c \ +gnunet_service_mesh_SOURCES = \ + gnunet-service-mesh.c \ mesh_path.c \ mesh_common.c -gnunet_service_mesh_new_CFLAGS = $(AM_CFLAGS) -gnunet_service_mesh_new_LDADD = \ +gnunet_service_mesh_CFLAGS = $(AM_CFLAGS) +gnunet_service_mesh_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/block/libgnunetblock.la -gnunet_service_mesh_new_DEPENDENCIES = \ +gnunet_service_mesh_DEPENDENCIES = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ $(top_builddir)/src/dht/libgnunetdht.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/block/libgnunetblock.la if LINUX -gnunet_service_mesh_new_LDFLAGS = -lrt + gnunet_service_mesh_LDFLAGS = -lrt endif if HAVE_TESTING @@ -144,222 +96,75 @@ libgnunetmeshtest_a_LIBADD = \ libgnunetmeshtest_a_DEPENDENCIES = \ libgnunetmesh.la -libgnunetmesh2test_a_SOURCES = \ - mesh2_test_lib.c mesh2_test_lib.h -libgnunetmesh2test_a_LIBADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testbed/libgnunettestbed.la \ - $(top_builddir)/src/mesh/libgnunetmesh2.la -libgnunetmesh2test_a_DEPENDENCIES = \ - libgnunetmesh2.la - if HAVE_TESTING check_PROGRAMS = \ - test_mesh_api \ - test_mesh_tree_api \ - test_mesh_local_1 \ - test_mesh_local_2 \ - test_mesh_local_traffic_fwd \ - test_mesh_local_traffic_bck \ - test_mesh_local_traffic_both \ - test_mesh_2dtorus \ - test_mesh_small_unicast \ - test_mesh_small_signal \ - test_mesh_small_speed \ - test_mesh_small_speed_nobuf \ - test_mesh_small_speed_backwards \ - test_mesh_small_speed_nobuf_backwards \ - test_mesh_small_speed_ack \ - $(EXP_TESTS) + test_mesh_local \ + test_mesh_small_forward \ + test_mesh_small_signal \ + test_mesh_small_speed \ + test_mesh_small_speed_ack \ + test_mesh_small_speed_nobuf \ + test_mesh_small_speed_backwards \ + test_mesh_small_speed_nobuf_backwards endif -test_mesh_api_SOURCES = \ - test_mesh_api.c -test_mesh_api_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/mesh/libgnunetmesh.la -test_mesh_api_DEPENDENCIES = \ - libgnunetmesh.la \ - $(top_builddir)/src/util/libgnunetutil.la - -test_mesh_tree_api_SOURCES = \ - test_mesh_tree_api.c -test_mesh_tree_api_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/dht/libgnunetdht.la -test_mesh_tree_api_DEPENDENCIES = \ - libgnunetmesh.la \ - $(top_builddir)/src/dht/libgnunetdht.la - -test_mesh_local_1_SOURCES = \ - test_mesh_local_1.c -test_mesh_local_1_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/mesh/libgnunetmesh.la -test_mesh_local_1_DEPENDENCIES = \ - libgnunetmesh.la - -test_mesh_local_2_SOURCES = \ - test_mesh_local_2.c -test_mesh_local_2_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/mesh/libgnunetmesh.la -test_mesh_local_2_DEPENDENCIES = \ - libgnunetmesh.la - -test_mesh_local_traffic_fwd_SOURCES = \ - test_mesh_local_traffic.c -test_mesh_local_traffic_fwd_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/mesh/libgnunetmesh.la -test_mesh_local_traffic_fwd_DEPENDENCIES = \ - libgnunetmesh.la - -test_mesh_local_traffic_bck_SOURCES = \ - test_mesh_local_traffic.c -test_mesh_local_traffic_bck_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/mesh/libgnunetmesh.la -test_mesh_local_traffic_bck_DEPENDENCIES = \ - libgnunetmesh.la - -test_mesh_local_traffic_both_SOURCES = \ - test_mesh_local_traffic.c -test_mesh_local_traffic_both_LDADD = \ - $(top_builddir)/src/util/libgnunetutil.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/mesh/libgnunetmesh.la -test_mesh_local_traffic_both_DEPENDENCIES = \ - libgnunetmesh.la - - ld_mesh_test_lib = \ - $(top_builddir)/src/mesh/libgnunetmeshtest.a \ - $(top_builddir)/src/mesh/libgnunetmesh.la \ + $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/testing/libgnunettesting.la \ $(top_builddir)/src/testbed/libgnunettestbed.la \ - $(top_builddir)/src/util/libgnunetutil.la + $(top_builddir)/src/mesh/libgnunetmesh.la \ + $(top_builddir)/src/mesh/libgnunetmeshtest.a dep_mesh_test_lib = \ - libgnunetmeshtest.a \ - libgnunetmesh.la + libgnunetmesh.la \ + libgnunetmeshtest.a -test_mesh_2dtorus_SOURCES = \ - test_mesh_2dtorus.c -test_mesh_2dtorus_LDADD = $(ld_mesh_test_lib) -test_mesh_2dtorus_DEPENDENCIES = $(dep_mesh_test_lib) +test_mesh_local_SOURCES = \ + test_mesh_local.c +test_mesh_local_LDADD = $(ld_mesh_test_lib) +test_mesh_local_DEPENDENCIES = $(dep_mesh_test_lib) -test_mesh_small_unicast_SOURCES = \ - test_mesh_small.c -test_mesh_small_unicast_LDADD = $(ld_mesh_test_lib) -test_mesh_small_unicast_DEPENDENCIES = $(dep_mesh_test_lib) +test_mesh_small_forward_SOURCES = \ + test_mesh_small.c +test_mesh_small_forward_LDADD = $(ld_mesh_test_lib) +test_mesh_small_forward_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_signal_SOURCES = \ - test_mesh_small.c + test_mesh_small.c test_mesh_small_signal_LDADD = $(ld_mesh_test_lib) test_mesh_small_signal_DEPENDENCIES = $(dep_mesh_test_lib) -test_mesh_small_speed_ack_SOURCES = \ - test_mesh_small.c -test_mesh_small_speed_ack_LDADD = $(ld_mesh_test_lib) -test_mesh_small_speed_ack_DEPENDENCIES = $(dep_mesh_test_lib) - test_mesh_small_speed_SOURCES = \ - test_mesh_small.c + test_mesh_small.c test_mesh_small_speed_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_DEPENDENCIES = $(dep_mesh_test_lib) +test_mesh_small_speed_ack_SOURCES = \ + test_mesh_small.c +test_mesh_small_speed_ack_LDADD = $(ld_mesh_test_lib) +test_mesh_small_speed_ack_DEPENDENCIES = $(dep_mesh_test_lib) + test_mesh_small_speed_nobuf_SOURCES = \ - test_mesh_small.c + test_mesh_small.c test_mesh_small_speed_nobuf_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_nobuf_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_backwards_SOURCES = \ - test_mesh_small.c + test_mesh_small.c test_mesh_small_speed_backwards_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_backwards_DEPENDENCIES = $(dep_mesh_test_lib) test_mesh_small_speed_nobuf_backwards_SOURCES = \ - test_mesh_small.c + test_mesh_small.c test_mesh_small_speed_nobuf_backwards_LDADD = $(ld_mesh_test_lib) test_mesh_small_speed_nobuf_backwards_DEPENDENCIES = $(dep_mesh_test_lib) -ld_mesh2_test_lib = \ - $(top_builddir)/src/mesh/libgnunetmesh2test.a \ - $(top_builddir)/src/mesh/libgnunetmesh2.la \ - $(top_builddir)/src/testing/libgnunettesting.la \ - $(top_builddir)/src/testbed/libgnunettestbed.la \ - $(top_builddir)/src/util/libgnunetutil.la - -dep_mesh2_test_lib = \ - libgnunetmesh2test.a \ - libgnunetmesh2.la - -test_mesh2_local_SOURCES = \ - test_mesh2_local.c -test_mesh2_local_LDADD = $(ld_mesh2_test_lib) -test_mesh2_local_DEPENDENCIES = $(dep_mesh2_test_lib) - -test_mesh2_small_forward_SOURCES = \ - test_mesh2_small.c -test_mesh2_small_forward_LDADD = $(ld_mesh2_test_lib) -test_mesh2_small_forward_DEPENDENCIES = $(dep_mesh2_test_lib) - -test_mesh2_small_signal_SOURCES = \ - test_mesh2_small.c -test_mesh2_small_signal_LDADD = $(ld_mesh2_test_lib) -test_mesh2_small_signal_DEPENDENCIES = $(dep_mesh2_test_lib) - -test_mesh2_small_speed_SOURCES = \ - test_mesh2_small.c -test_mesh2_small_speed_LDADD = $(ld_mesh2_test_lib) -test_mesh2_small_speed_DEPENDENCIES = $(dep_mesh2_test_lib) - -test_mesh2_small_speed_ack_SOURCES = \ - test_mesh2_small.c -test_mesh2_small_speed_ack_LDADD = $(ld_mesh2_test_lib) -test_mesh2_small_speed_ack_DEPENDENCIES = $(dep_mesh2_test_lib) - -test_mesh2_small_speed_nobuf_SOURCES = \ - test_mesh2_small.c -test_mesh2_small_speed_nobuf_LDADD = $(ld_mesh2_test_lib) -test_mesh2_small_speed_nobuf_DEPENDENCIES = $(dep_mesh2_test_lib) - -test_mesh2_small_speed_backwards_SOURCES = \ - test_mesh2_small.c -test_mesh2_small_speed_backwards_LDADD = $(ld_mesh2_test_lib) -test_mesh2_small_speed_backwards_DEPENDENCIES = $(dep_mesh2_test_lib) - -test_mesh2_small_speed_nobuf_backwards_SOURCES = \ - test_mesh2_small.c -test_mesh2_small_speed_nobuf_backwards_LDADD = $(ld_mesh2_test_lib) -test_mesh2_small_speed_nobuf_backwards_DEPENDENCIES = $(dep_mesh2_test_lib) - - if ENABLE_TEST_RUN TESTS = \ - $(EXP_TESTS) \ - test_mesh_api \ - test_mesh_tree_api \ - test_mesh_local_1 test_mesh_local_2 \ - test_mesh_local_traffic_fwd \ - test_mesh_local_traffic_bck \ - test_mesh_local_traffic_both \ - test_mesh_2dtorus \ - test_mesh_small_unicast \ - test_mesh_small_signal \ - test_mesh_small_speed \ - test_mesh_small_speed_nobuf \ - test_mesh_small_speed_backwards + $(check_PROGRAMS) endif EXTRA_DIST = \ mesh.h mesh_protocol.h \ - test_mesh.conf \ - test_mesh_2dtorus.conf \ - test_mesh_small.conf + test_mesh.conf diff --git a/src/mesh/gnunet-mesh.c b/src/mesh/gnunet-mesh.c index 21a3f7d601..f9cc1295c6 100644 --- a/src/mesh/gnunet-mesh.c +++ b/src/mesh/gnunet-mesh.c @@ -73,25 +73,19 @@ shutdown_task (void *cls, * Method called to retrieve information about each tunnel the mesh peer * is aware of. * - * @param cls Closure (unused). - * @param initiator Peer that started the tunnel (owner). + * @param cls Closure. * @param tunnel_number Tunnel number. - * @param peers Array of peer identities that participate in the tunnel. - * @param npeers Number of peers in peers. + * @param origin that started the tunnel (owner). + * @param target other endpoint of the tunnel */ static void tunnels_callback (void *cls, - const struct GNUNET_PeerIdentity *initiator, - unsigned int tunnel_number, - const struct GNUNET_PeerIdentity *peers, - unsigned int npeers) + uint32_t tunnel_number, + const struct GNUNET_PeerIdentity *origin, + const struct GNUNET_PeerIdentity *target) { - unsigned int i; - - fprintf (stdout, "Tunnel %s [%u]: %u peers\n", - GNUNET_i2s_full (initiator), tunnel_number, npeers); - for (i = 0; i < npeers; i++) - fprintf (stdout, " * %s\n", GNUNET_i2s_full (&peers[i])); + fprintf (stdout, "Tunnel %s [%u]\n", + GNUNET_i2s_full (origin), tunnel_number); fprintf (stdout, "\n"); } @@ -169,7 +163,7 @@ run (void *cls, char *const *args, const char *cfgfile, static const struct GNUNET_MESH_MessageHandler handlers[] = { {NULL, 0, 0} /* FIXME add option to monitor msg types */ }; - GNUNET_MESH_ApplicationType apps = 0; /* FIXME add option to monitor apps */ + /* FIXME add option to monitor apps */ if (args[0] != NULL) { @@ -178,10 +172,10 @@ run (void *cls, char *const *args, const char *cfgfile, } mh = GNUNET_MESH_connect (cfg, NULL, /* cls */ - NULL, /* nt */ + NULL, /* new tunnel */ NULL, /* cleaner */ handlers, - &apps); + NULL); if (NULL == mh) GNUNET_SCHEDULER_add_now (shutdown_task, NULL); else diff --git a/src/mesh/gnunet-service-mesh-new.c b/src/mesh/gnunet-service-mesh-new.c deleted file mode 100644 index 7925b5241b..0000000000 --- a/src/mesh/gnunet-service-mesh-new.c +++ /dev/null @@ -1,5205 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2001-2013 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file mesh/gnunet-service-mesh-new.c - * @brief GNUnet MESH service - * @author Bartlomiej Polot - * - * TODO: - * - relay corking down to core - * - set ttl relative to path length - * - add signatures - * - add encryption - * - keep queues until receiving ACK - * TODO END - */ - -#include "platform.h" -#include "mesh2.h" -#include "mesh2_protocol.h" -#include "mesh_path.h" -#include "block_mesh.h" -#include "gnunet_dht_service.h" -#include "gnunet_statistics_service.h" - -#define MESH_BLOOM_SIZE 128 - -#define MESH_DEBUG_DHT GNUNET_NO -#define MESH_DEBUG_CONNECTION GNUNET_NO -#define MESH_DEBUG_TIMING __LINUX__ && GNUNET_NO - -#define MESH_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\ - GNUNET_TIME_UNIT_MINUTES,\ - 10) - -#if MESH_DEBUG_CONNECTION -#define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) -#else -#define DEBUG_CONN(...) -#endif - -#if MESH_DEBUG_DHT -#define DEBUG_DHT(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) -#else -#define DEBUG_DHT(...) -#endif - -#if MESH_DEBUG_TIMING -#include <time.h> -double __sum; -uint64_t __count; -struct timespec __mesh_start; -struct timespec __mesh_end; -#define INTERVAL_START clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_start)) -#define INTERVAL_END \ -do {\ - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_end));\ - double __diff = __mesh_end.tv_nsec - __mesh_start.tv_nsec;\ - if (__diff < 0) __diff += 1000000000;\ - __sum += __diff;\ - __count++;\ -} while (0) -#define INTERVAL_SHOW \ -if (0 < __count)\ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "AVG process time: %f ns\n", __sum/__count) -#else -#define INTERVAL_START -#define INTERVAL_END -#define INTERVAL_SHOW -#endif - -/******************************************************************************/ -/************************ DATA STRUCTURES ****************************/ -/******************************************************************************/ - -/** FWD declaration */ -struct MeshPeerInfo; -struct MeshClient; - - -/** - * Struct containing info about a queued transmission to this peer - */ -struct MeshPeerQueue -{ - /** - * DLL next - */ - struct MeshPeerQueue *next; - - /** - * DLL previous - */ - struct MeshPeerQueue *prev; - - /** - * Peer this transmission is directed to. - */ - struct MeshPeerInfo *peer; - - /** - * Tunnel this message belongs to. - */ - struct MeshTunnel *tunnel; - - /** - * Pointer to info stucture used as cls. - */ - void *cls; - - /** - * Type of message - */ - uint16_t type; - - /** - * Size of the message - */ - size_t size; -}; - - -/** - * Struct containing all information regarding a given peer - */ -struct MeshPeerInfo -{ - /** - * ID of the peer - */ - GNUNET_PEER_Id id; - - /** - * Last time we heard from this peer - */ - struct GNUNET_TIME_Absolute last_contact; - - /** - * Number of attempts to reconnect so far - */ - int n_reconnect_attempts; - - /** - * Paths to reach the peer, ordered by ascending hop count - */ - struct MeshPeerPath *path_head; - - /** - * Paths to reach the peer, ordered by ascending hop count - */ - struct MeshPeerPath *path_tail; - - /** - * Handle to stop the DHT search for a path to this peer - */ - struct GNUNET_DHT_GetHandle *dhtget; - - /** - * Array of tunnels this peer is the target of. - * Most probably a small amount, therefore not a hashmap. - * When the path to the peer changes, notify these tunnels to let them - * re-adjust their path trees. - */ - struct MeshTunnel **tunnels; - - /** - * Number of tunnels this peers participates in - */ - unsigned int ntunnels; - - /** - * Transmission queue to core DLL head - */ - struct MeshPeerQueue *queue_head; - - /** - * Transmission queue to core DLL tail - */ - struct MeshPeerQueue *queue_tail; - - /** - * How many messages are in the queue to this peer. - */ - unsigned int queue_n; - - /** - * Handle for queued transmissions - */ - struct GNUNET_CORE_TransmitHandle *core_transmit; -}; - - -/** - * Struct to encapsulate all the Flow Control information to a peer in the - * context of a tunnel: Same peer in different tunnels will have independent - * flow control structures, allowing to choke/free tunnels according to its - * own criteria. - */ -struct MeshFlowControl -{ - /** - * ID of the last packet sent towards the peer. - */ - uint32_t last_pid_sent; - - /** - * ID of the last packet received from the peer. - */ - uint32_t last_pid_recv; - - /** - * Last ACK sent to the peer (peer can't send more than this PID). - */ - uint32_t last_ack_sent; - - /** - * Last ACK sent towards the origin (for traffic towards leaf node). - */ - uint32_t last_ack_recv; - - /** - * How many payload messages are in the queue towards this peer. - */ - uint32_t queue_n; - - /** - * Task to poll the peer in case of a lost ACK causes stall. - */ - GNUNET_SCHEDULER_TaskIdentifier poll_task; - - /** - * How frequently to poll for ACKs. - */ - struct GNUNET_TIME_Relative poll_time; - - /** - * On which tunnel to poll. - * Using an explicit poll_ctx would not help memory wise, - * since the allocated context would have to be stored in the - * fc struct in order to free it upon cancelling poll_task. - */ - struct MeshTunnel *t; -}; - - -/** - * Globally unique tunnel identification (owner + number) - * DO NOT USE OVER THE NETWORK - */ -struct MESH_TunnelID -{ - /** - * Node that owns the tunnel - */ - GNUNET_PEER_Id oid; - - /** - * Tunnel number to differentiate all the tunnels owned by the node oid - * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI ) - */ - MESH_TunnelNumber tid; -}; - - -/** - * Struct containing all information regarding a tunnel - * For an intermediate node the improtant info used will be: - * - id Tunnel unique identification - * - paths[0] To know where to send it next - * - metainfo: ready, speeds, accounting - */ -struct MeshTunnel -{ - /** - * Tunnel ID - */ - struct MESH_TunnelID id; - - /** - * Port of the tunnel. - */ - uint32_t port; - - /** - * State of the tunnel. - */ - enum MeshTunnelState state; - - /** - * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 ) - */ - MESH_TunnelNumber local_tid; - - /** - * Local tunnel number for local destination clients (incoming number) - * ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV or 0). All clients share the same - * number. - */ - MESH_TunnelNumber local_tid_dest; - - /** - * Is the tunnel bufferless (minimum latency)? - */ - int nobuffer; - - /** - * Force sending ACK? Flag to allow duplicate ACK on POLL. - */ - int force_ack; - - /** - * How many messages do we accept in the forward queue. - */ - unsigned int queue_max; - - /** - * Last time the tunnel was used - */ - struct GNUNET_TIME_Absolute timestamp; - - /** - * Destination of the tunnel. - */ - GNUNET_PEER_Id dest; - - /** - * Next hop in the tunnel. If 0, @c client must be set. - */ - GNUNET_PEER_Id next_hop; - - /** - * Previous hop in the tunnel. If 0, @c owner must be set. - */ - GNUNET_PEER_Id prev_hop; - - /** - * Flow control information about @c next_hop or @c client. - */ - struct MeshFlowControl next_fc; - - /** - * Flow control information about @c prev_hop or @c owner. - */ - struct MeshFlowControl prev_fc; - - /** - * Client owner of the tunnel, if any - */ - struct MeshClient *owner; - - /** - * Client destination of the tunnel, if any. - */ - struct MeshClient *client; - - /** - * Task to keep the used paths alive at the owner, - * time tunnel out on all the other peers. - */ - GNUNET_SCHEDULER_TaskIdentifier maintenance_task; - - /** - * Path being used for the tunnel. - */ - struct MeshPeerPath *path; - - /** - * Flag to signal the destruction of the tunnel. - * If this is set GNUNET_YES the tunnel will be destroyed - * when the queue is empty. - */ - int destroy; - - /** - * Total messages pending for this tunnels, payload or not. - */ - unsigned int pending_messages; -}; - - -/** - * Struct containing information about a client of the service - * - * TODO: add a list of 'waiting' ports - */ -struct MeshClient -{ - /** - * Linked list next - */ - struct MeshClient *next; - - /** - * Linked list prev - */ - struct MeshClient *prev; - - /** - * Tunnels that belong to this client, indexed by local id - */ - struct GNUNET_CONTAINER_MultiHashMap *own_tunnels; - - /** - * Tunnels this client has accepted, indexed by incoming local id - */ - struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels; - - /** - * Handle to communicate with the client - */ - struct GNUNET_SERVER_Client *handle; - - /** - * Ports that this client has declared interest in. - * Indexed by a GMC_hash32 (type), contains *Client. - */ - struct GNUNET_CONTAINER_MultiHashMap *ports; - - /** - * Whether the client is active or shutting down (don't send confirmations - * to a client that is shutting down. - */ - int shutting_down; - - /** - * ID of the client, mainly for debug messages - */ - unsigned int id; - -}; - - -/******************************************************************************/ -/************************ DEBUG FUNCTIONS ****************************/ -/******************************************************************************/ - -#if MESH_DEBUG -/** - * GNUNET_SCHEDULER_Task for printing a message after some operation is done - * @param cls string to print - * @param success GNUNET_OK if the PUT was transmitted, - * GNUNET_NO on timeout, - * GNUNET_SYSERR on disconnect from service - * after the PUT message was transmitted - * (so we don't know if it was received or not) - */ - -#if 0 -static void -mesh_debug (void *cls, int success) -{ - char *s = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s (%d)\n", s, success); -} -#endif - -/* FIXME */ -unsigned int debug_fwd_ack; -unsigned int debug_bck_ack; - -#endif - -/******************************************************************************/ -/*********************** GLOBAL VARIABLES ****************************/ -/******************************************************************************/ - -/************************** Configuration parameters **************************/ - -/** - * How often to send tunnel keepalives. Tunnels timeout after 4 missed. - */ -static struct GNUNET_TIME_Relative refresh_path_time; - -/** - * How often to PUT own ID in the DHT. - */ -static struct GNUNET_TIME_Relative id_announce_time; - -/** - * Maximum time allowed to connect to a peer found by string. - */ -static struct GNUNET_TIME_Relative connect_timeout; - -/** - * Default TTL for payload packets. - */ -static unsigned long long default_ttl; - -/** - * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put. - */ -static unsigned long long dht_replication_level; - -/** - * How many tunnels are we willing to maintain. - * Local tunnels are always allowed, even if there are more tunnels than max. - */ -static unsigned long long max_tunnels; - -/** - * How many messages *in total* are we willing to queue, divided by number of - * tunnels to get tunnel queue size. - */ -static unsigned long long max_msgs_queue; - -/** - * How many peers do we want to remember? - */ -static unsigned long long max_peers; - - -/*************************** Static global variables **************************/ - -/** - * Hostkey generation context - */ -static struct GNUNET_CRYPTO_EccKeyGenerationContext *keygen; - -/** - * DLL with all the clients, head. - */ -static struct MeshClient *clients_head; - -/** - * DLL with all the clients, tail. - */ -static struct MeshClient *clients_tail; - -/** - * Tunnels known, indexed by MESH_TunnelID (MeshTunnel). - */ -static struct GNUNET_CONTAINER_MultiHashMap *tunnels; - -/** - * Number of tunnels known. - */ -static unsigned long long n_tunnels; - -/** - * Tunnels incoming, indexed by MESH_TunnelNumber - * (which is greater than GNUNET_MESH_LOCAL_TUNNEL_ID_SERV). - */ -static struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels; - -/** - * Peers known, indexed by PeerIdentity (MeshPeerInfo). - */ -static struct GNUNET_CONTAINER_MultiHashMap *peers; - -/* - * Handle to communicate with transport - */ -// static struct GNUNET_TRANSPORT_Handle *transport_handle; - -/** - * Handle to communicate with core. - */ -static struct GNUNET_CORE_Handle *core_handle; - -/** - * Handle to use DHT. - */ -static struct GNUNET_DHT_Handle *dht_handle; - -/** - * Handle to server. - */ -static struct GNUNET_SERVER_Handle *server_handle; - -/** - * Handle to the statistics service. - */ -static struct GNUNET_STATISTICS_Handle *stats; - -/** - * Notification context, to send messages to local clients. - */ -static struct GNUNET_SERVER_NotificationContext *nc; - -/** - * Local peer own ID (memory efficient handle). - */ -static GNUNET_PEER_Id myid; - -/** - * Local peer own ID (full value). - */ -static struct GNUNET_PeerIdentity my_full_id; - -/** - * Own private key. - */ -static struct GNUNET_CRYPTO_EccPrivateKey *my_private_key; - -/** - * Own public key. - */ -static struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded my_public_key; - -/** - * Tunnel ID for the next created tunnel (global tunnel number). - */ -static MESH_TunnelNumber next_tid; - -/** - * Tunnel ID for the next incoming tunnel (local tunnel number). - */ -static MESH_TunnelNumber next_local_tid; - -/** - * All ports clients of this peer have opened. - */ -static struct GNUNET_CONTAINER_MultiHashMap *ports; - -/** - * Task to periodically announce itself in the network. - */ -GNUNET_SCHEDULER_TaskIdentifier announce_id_task; - -/** - * Next ID to assign to a client. - */ -unsigned int next_client_id; - - -/******************************************************************************/ -/*********************** DECLARATIONS **************************/ -/******************************************************************************/ - -/** - * Function to process paths received for a new peer addition. The recorded - * paths form the initial tunnel, which can be optimized later. - * Called on each result obtained for the DHT search. - * - * @param cls closure - * @param exp when will this value expire - * @param key key of the result - * @param type type of the result - * @param size number of bytes in data - * @param data pointer to the result data - */ -static void -dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, - const struct GNUNET_HashCode * key, - const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length, enum GNUNET_BLOCK_Type type, - size_t size, const void *data); - - -/** - * Retrieve the MeshPeerInfo stucture associated with the peer, create one - * and insert it in the appropriate structures if the peer is not known yet. - * - * @param peer Full identity of the peer. - * - * @return Existing or newly created peer info. - */ -static struct MeshPeerInfo * -peer_get (const struct GNUNET_PeerIdentity *peer); - - -/** - * Retrieve the MeshPeerInfo stucture associated with the peer, create one - * and insert it in the appropriate structures if the peer is not known yet. - * - * @param peer Short identity of the peer. - * - * @return Existing or newly created peer info. - */ -static struct MeshPeerInfo * -peer_get_short (const GNUNET_PEER_Id peer); - - -/** - * Build a PeerPath from the paths returned from the DHT, reversing the paths - * to obtain a local peer -> destination path and interning the peer ids. - * - * @return Newly allocated and created path - */ -static struct MeshPeerPath * -path_build_from_dht (const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length); - - -/** - * 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. - */ -static void -path_add_to_peers (struct MeshPeerPath *p, int confirmed); - - - -/** - * Search for a tunnel by global ID using full PeerIdentities. - * - * @param oid owner of the tunnel. - * @param tid global tunnel number. - * - * @return tunnel handler, NULL if doesn't exist. - */ -static struct MeshTunnel * -tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid); - - -/** - * Notify a tunnel that a connection has broken that affects at least - * some of its peers. - * - * @param t Tunnel affected. - * @param p1 Peer that got disconnected from p2. - * @param p2 Peer that got disconnected from p1. - * - * @return Short ID of the peer disconnected (either p1 or p2). - * 0 if the tunnel remained unaffected. - */ -static GNUNET_PEER_Id -tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1, - GNUNET_PEER_Id p2); - - -/** - * @brief Use the given path for the tunnel. - * Update the next and prev hops (and RCs). - * (Re)start the path refresh in case the tunnel is locally owned. - * - * @param t Tunnel to update. - * @param p Path to use. - */ -static void -tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p); - -/** - * Tunnel is empty: destroy it. - * - * Notifies all participants (peers, cleints) about the destruction. - * - * @param t Tunnel to destroy. - */ -static void -tunnel_destroy_empty (struct MeshTunnel *t); - -/** - * @brief Queue and pass message to core when possible. - * - * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status - * and accounts for it. In case the queue is full, the message is dropped and - * a break issued. - * - * Otherwise, message is treated as internal and allowed to go regardless of - * queue status. - * - * @param cls Closure (@c type dependant). It will be used by queue_send to - * build the message to be sent if not already prebuilt. - * @param type Type of the message, 0 for a raw message. - * @param size Size of the message. - * @param dst Neighbor to send message to. - * @param t Tunnel this message belongs to. - */ -static void -queue_add (void *cls, uint16_t type, size_t size, - struct MeshPeerInfo *dst, struct MeshTunnel *t); - - -/** - * Free a transmission that was already queued with all resources - * associated to the request. - * - * @param queue Queue handler to cancel. - * @param clear_cls Is it necessary to free associated cls? - */ -static void -queue_destroy (struct MeshPeerQueue *queue, int clear_cls); - - -/** - * @brief Get the next transmittable message from the queue. - * - * This will be the head, except in the case of being a data packet - * not allowed by the destination peer. - * - * @param peer Destination peer. - * - * @return The next viable MeshPeerQueue element to send to that peer. - * NULL when there are no transmittable messages. - */ -struct MeshPeerQueue * -queue_get_next (const struct MeshPeerInfo *peer); - - -/** - * Core callback to write a queued packet to core buffer - * - * @param cls Closure (peer info). - * @param size Number of bytes available in buf. - * @param buf Where the to write the message. - * - * @return number of bytes written to buf - */ -static size_t -queue_send (void *cls, size_t size, void *buf); - - -/******************************************************************************/ -/************************ PERIODIC FUNCTIONS ****************************/ -/******************************************************************************/ - -/** - * Periodically announce self id in the DHT - * - * @param cls closure - * @param tc task context - */ -static void -announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct PBlock block; - - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - { - announce_id_task = GNUNET_SCHEDULER_NO_TASK; - return; - } - /* TODO - * - Set data expiration in function of X - * - Adapt X to churn - */ - DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (&my_full_id)); - - block.id = my_full_id; - block.type = htonl (0); - GNUNET_DHT_put (dht_handle, /* DHT handle */ - &my_full_id.hashPubKey, /* Key to use */ - dht_replication_level, /* Replication level */ - GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ - GNUNET_BLOCK_TYPE_MESH_PEER, /* Block type */ - sizeof (block), /* Size of the data */ - (const char *) &block, /* Data itself */ - GNUNET_TIME_UNIT_FOREVER_ABS, /* Data expiration */ - GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */ - NULL, /* Continuation */ - NULL); /* Continuation closure */ - announce_id_task = - GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls); -} - - -/******************************************************************************/ -/****************** GENERAL HELPER FUNCTIONS ************************/ -/******************************************************************************/ - - -/** - * Check if client has registered with the service and has not disconnected - * - * @param client the client to check - * - * @return non-NULL if client exists in the global DLL - */ -static struct MeshClient * -client_get (struct GNUNET_SERVER_Client *client) -{ - struct MeshClient *c; - - c = clients_head; - while (NULL != c) - { - if (c->handle == client) - return c; - c = c->next; - } - return NULL; -} - - -/** - * Deletes a tunnel from a client (either owner or destination). To be used on - * tunnel destroy. - * - * @param c Client whose tunnel to delete. - * @param t Tunnel which should be deleted. - */ -static void -client_delete_tunnel (struct MeshClient *c, struct MeshTunnel *t) -{ - struct GNUNET_HashCode hash; - - if (c == t->owner) - { - GMC_hash32 (t->local_tid, &hash); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, - &hash, - t)); - } - else if (c == t->client) - { - GMC_hash32 (t->local_tid_dest, &hash); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, - &hash, - t)); - } - else - { - GNUNET_break (0); - } -} - -/** - * Notify the appropriate client that a new incoming tunnel was created. - * - * @param t Tunnel that was created. - */ -static void -send_client_tunnel_create (struct MeshTunnel *t) -{ - struct GNUNET_MESH_TunnelMessage msg; - - if (NULL == t->client) - return; - msg.header.size = htons (sizeof (msg)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); - msg.tunnel_id = htonl (t->local_tid_dest); - msg.port = htonl (t->port); - GNUNET_PEER_resolve (t->id.oid, &msg.peer); - GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, - &msg.header, GNUNET_NO); -} - - -/** - * Notify dest client that the incoming tunnel is no longer valid. - * - * @param c Client to notify.. - * @param t Tunnel that is destroyed. - */ -static void -send_client_tunnel_destroy (struct MeshClient *c, struct MeshTunnel *t) -{ - struct GNUNET_MESH_TunnelMessage msg; - - if (NULL == c) - { - GNUNET_break (0); - return; - } - if (c != t->client && c != t->owner) - { - GNUNET_break (0); - return; - } - msg.header.size = htons (sizeof (msg)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); - msg.tunnel_id = htonl (t->local_tid_dest); - msg.port = htonl (0); - memset(&msg.peer, 0, sizeof (msg.peer)); - GNUNET_SERVER_notification_context_unicast (nc, c->handle, - &msg.header, GNUNET_NO); -} - - -/** - * Iterator over all the peers to remove the oldest not-used entry. - * - * @param cls Closure (unsued). - * @param key ID of the peer. - * @param value Peer_Info of the peer. - * - * FIXME implement - */ -static int -peer_info_timeout (void *cls, - const struct GNUNET_HashCode *key, - void *value) -{ - return GNUNET_YES; -} - -/** - * Retrieve the MeshPeerInfo stucture associated with the peer, create one - * and insert it in the appropriate structures if the peer is not known yet. - * - * @param peer Full identity of the peer. - * - * @return Existing or newly created peer info. - */ -static struct MeshPeerInfo * -peer_get (const struct GNUNET_PeerIdentity *peer) -{ - struct MeshPeerInfo *peer_info; - - peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey); - if (NULL == peer_info) - { - peer_info = - (struct MeshPeerInfo *) GNUNET_malloc (sizeof (struct MeshPeerInfo)); - if (GNUNET_CONTAINER_multihashmap_size (peers) > max_peers) - { - GNUNET_CONTAINER_multihashmap_iterate (peers, - &peer_info_timeout, - NULL); - } - GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); - peer_info->id = GNUNET_PEER_intern (peer); - } - peer_info->last_contact = GNUNET_TIME_absolute_get(); - - return peer_info; -} - - -/** - * Retrieve the MeshPeerInfo stucture associated with the peer, create one - * and insert it in the appropriate structures if the peer is not known yet. - * - * @param peer Short identity of the peer. - * - * @return Existing or newly created peer info. - */ -static struct MeshPeerInfo * -peer_get_short (const GNUNET_PEER_Id peer) -{ - struct GNUNET_PeerIdentity id; - - GNUNET_PEER_resolve (peer, &id); - return peer_get (&id); -} - - -/** - * Choose the best path towards a peer considering the tunnel properties. - * - * @param peer The destination peer. - * @param t The tunnel the path is for. - * - * @return Best current known path towards the peer, if any. - */ -static struct MeshPeerPath * -peer_get_best_path (const struct MeshPeerInfo *peer, const struct MeshTunnel *t) -{ - struct MeshPeerPath *best_p; - struct MeshPeerPath *p; - unsigned int best_cost; - unsigned int cost; - - best_p = p = peer->path_head; - best_cost = cost = p->length; - while (NULL != p) - { - if ((cost = p->length) < best_cost) - { - best_cost = cost; - best_p = p; - } - p = p->next; - } - return best_p; -} - -/** - * Core callback to write a pre-constructed data packet to core buffer - * - * @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. - * - * @return number of bytes written to buf - */ -static size_t -send_core_data_raw (void *cls, size_t size, void *buf) -{ - struct GNUNET_MessageHeader *msg = cls; - size_t total_size; - - GNUNET_assert (NULL != msg); - total_size = ntohs (msg->size); - - if (total_size > size) - { - GNUNET_break (0); - return 0; - } - memcpy (buf, msg, total_size); - GNUNET_free (cls); - return total_size; -} - - -/** - * Sends an already built message to a peer, properly registrating - * all used resources. - * - * @param message Message to send. Function makes a copy of it. - * @param peer Short ID of the neighbor whom to send the message. - * @param t Tunnel on which this message is transmitted. - */ -static void -send_prebuilt_message (const struct GNUNET_MessageHeader *message, - GNUNET_PEER_Id peer, - struct MeshTunnel *t) -{ - struct GNUNET_PeerIdentity id; - struct MeshPeerInfo *neighbor; - struct MeshPeerPath *p; - void *data; - size_t size; - uint16_t type; - -// GNUNET_TRANSPORT_try_connect(); FIXME use? - - if (0 == peer) - return; - - size = ntohs (message->size); - data = GNUNET_malloc (size); - memcpy (data, message, size); - type = ntohs(message->type); - if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type || - GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type) - { - struct GNUNET_MESH_Data *u; - - u = (struct GNUNET_MESH_Data *) data; - u->ttl = htonl (ntohl (u->ttl) - 1); - } - GNUNET_PEER_resolve (peer, &id); - neighbor = peer_get (&id); - for (p = neighbor->path_head; NULL != p; p = p->next) - { - if (2 >= p->length) - { - break; - } - } - if (NULL == p) - { -#if MESH_DEBUG - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " %s IS NOT DIRECTLY CONNECTED\n", - GNUNET_i2s(&id)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " PATHS TO %s:\n", - GNUNET_i2s(&id)); - for (p = neighbor->path_head; NULL != p; p = p->next) - { - struct GNUNET_PeerIdentity debug_id; - unsigned int i; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " path with %u hops through:\n", - p->length); - for (i = 0; i < p->length; i++) - { - GNUNET_PEER_resolve(p->peers[i], &debug_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " hop %u: %s\n", - i, GNUNET_i2s(&debug_id)); - } - } -#endif - GNUNET_break (0); // FIXME sometimes fails (testing disconnect?) - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - " no direct connection to %s\n", - GNUNET_i2s (&id)); - GNUNET_free (data); - return; - } - if (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK == type) - type = 0; - queue_add (data, - type, - size, - neighbor, - t); -} - - -/** - * Sends a CREATE PATH message for a path to a peer, properly registrating - * all used resources. - * - * @param t Tunnel for which the path is created. - */ -static void -send_create_path (struct MeshTunnel *t) -{ - struct MeshPeerInfo *neighbor; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send create path\n"); - neighbor = peer_get_short (t->next_hop); - queue_add (t, - GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, - sizeof (struct GNUNET_MESH_CreateTunnel) + - (t->path->length * sizeof (struct GNUNET_PeerIdentity)), - neighbor, - t); - t->state = MESH_TUNNEL_WAITING; -} - - -/** - * Sends a PATH ACK message in reponse to a received PATH_CREATE directed to us. - * - * @param t Tunnel which to confirm. - */ -static void -send_path_ack (struct MeshTunnel *t) -{ - struct MeshPeerInfo *peer; - - peer = peer_get_short (t->prev_hop); - - queue_add (t, - GNUNET_MESSAGE_TYPE_MESH_PATH_ACK, - sizeof (struct GNUNET_MESH_PathACK), - peer, - t); -} - - -/** - * Try to establish a new connection to this peer in the given tunnel. - * If the peer doesn't have any path to it yet, try to get one. - * If the peer already has some path, send a CREATE PATH towards it. - * - * @param peer PeerInfo of the peer. - * @param t Tunnel for which to create the path, if possible. - */ -static void -peer_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t) -{ - struct MeshPeerPath *p; - - if (NULL != peer->path_head) - { - p = peer_get_best_path (peer, t); - tunnel_use_path (t, p); - send_create_path (t); - } - else if (NULL == peer->dhtget) - { - struct GNUNET_PeerIdentity id; - - GNUNET_PEER_resolve (peer->id, &id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Starting DHT GET for peer %s\n", GNUNET_i2s (&id)); - peer->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ - GNUNET_BLOCK_TYPE_MESH_PEER, /* type */ - &id.hashPubKey, /* key to search */ - dht_replication_level, /* replication level */ - GNUNET_DHT_RO_RECORD_ROUTE | - GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, - NULL, /* xquery */ - 0, /* xquery bits */ - &dht_get_id_handler, peer); - t->state = MESH_TUNNEL_SEARCHING; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "There is no path but the DHT GET is already started.\n"); - } -} - - -/** - * Destroy the peer_info and free any allocated resources linked to it - * - * @param pi The peer_info to destroy. - * - * @return GNUNET_OK on success - */ -static int -peer_info_destroy (struct MeshPeerInfo *pi) -{ - struct GNUNET_PeerIdentity id; - struct MeshPeerPath *p; - struct MeshPeerPath *nextp; - unsigned int i; - - GNUNET_PEER_resolve (pi->id, &id); - GNUNET_PEER_change_rc (pi->id, -1); - - if (GNUNET_YES != - GNUNET_CONTAINER_multihashmap_remove (peers, &id.hashPubKey, pi)) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "removing peer %s, not in hashmap\n", GNUNET_i2s (&id)); - } - if (NULL != pi->dhtget) - { - GNUNET_DHT_get_stop (pi->dhtget); - } - p = pi->path_head; - while (NULL != p) - { - nextp = p->next; - GNUNET_CONTAINER_DLL_remove (pi->path_head, pi->path_tail, p); - path_destroy (p); - p = nextp; - } - for (i = 0; i < pi->ntunnels; i++) - tunnel_destroy_empty (pi->tunnels[i]); - GNUNET_array_grow (pi->tunnels, pi->ntunnels, 0); - GNUNET_free (pi); - return GNUNET_OK; -} - - -/** - * Remove all paths that rely on a direct connection between p1 and p2 - * from the peer itself and notify all tunnels about it. - * - * @param peer PeerInfo of affected peer. - * @param p1 GNUNET_PEER_Id of one peer. - * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and - * no longer is. - * - * TODO: optimize (see below) - */ -static void -peer_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, - GNUNET_PEER_Id p2) -{ - struct MeshPeerPath *p; - struct MeshPeerPath *next; - struct MeshPeerInfo *peer_d; - GNUNET_PEER_Id d; - unsigned int destroyed; - unsigned int i; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path\n"); - destroyed = 0; - for (p = peer->path_head; NULL != p; p = next) - { - next = p->next; - for (i = 0; i < (p->length - 1); i++) - { - if ((p->peers[i] == p1 && p->peers[i + 1] == p2) || - (p->peers[i] == p2 && p->peers[i + 1] == p1)) - { - GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p); - path_destroy (p); - destroyed++; - break; - } - } - } - if (0 == destroyed) - return; - - for (i = 0; i < peer->ntunnels; i++) - { - d = tunnel_notify_connection_broken (peer->tunnels[i], p1, p2); - if (0 == d) - continue; - - peer_d = peer_get_short (d); - next = peer_get_best_path (peer_d, peer->tunnels[i]); - tunnel_use_path (peer->tunnels[i], next); - peer_connect (peer_d, peer->tunnels[i]); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path END\n"); -} - - -/** - * Add the path to the peer and update the path used to reach it in case this - * is the shortest. - * - * @param peer_info Destination peer to add the path to. - * @param path New path to add. Last peer must be the peer in arg 1. - * Path will be either used of freed if already known. - * @param trusted Do we trust that this path is real? - */ -void -peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path, - int trusted) -{ - struct MeshPeerPath *aux; - unsigned int l; - unsigned int l2; - - if ((NULL == peer_info) || (NULL == path)) - { - GNUNET_break (0); - path_destroy (path); - return; - } - if (path->peers[path->length - 1] != peer_info->id) - { - GNUNET_break (0); - path_destroy (path); - return; - } - if (2 >= path->length && GNUNET_NO == trusted) - { - /* Only allow CORE to tell us about direct paths */ - path_destroy (path); - return; - } - for (l = 1; l < path->length; l++) - { - if (path->peers[l] == myid) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l); - for (l2 = 0; l2 < path->length - l; l2++) - { - path->peers[l2] = path->peers[l + l2]; - } - path->length -= l; - l = 1; - path->peers = - GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id)); - } - } -#if MESH_DEBUG - { - struct GNUNET_PeerIdentity id; - - GNUNET_PEER_resolve (peer_info->id, &id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n", - path->length, GNUNET_i2s (&id)); - } -#endif - l = path_get_length (path); - if (0 == l) - { - path_destroy (path); - return; - } - - GNUNET_assert (peer_info->id == path->peers[path->length - 1]); - for (aux = peer_info->path_head; aux != NULL; aux = aux->next) - { - l2 = path_get_length (aux); - if (l2 > l) - { - GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head, - peer_info->path_tail, aux, path); - return; - } - else - { - if (l2 == l && memcmp (path->peers, aux->peers, l) == 0) - { - path_destroy (path); - return; - } - } - } - GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail, - path); - return; -} - - -/** - * Add the path to the origin peer and update the path used to reach it in case - * this is the shortest. - * The path is given in peer_info -> destination, therefore we turn the path - * upside down first. - * - * @param peer_info Peer to add the path to, being the origin of the path. - * @param path New path to add after being inversed. - * Path will be either used or freed. - * @param trusted Do we trust that this path is real? - */ -static void -peer_info_add_path_to_origin (struct MeshPeerInfo *peer_info, - struct MeshPeerPath *path, int trusted) -{ - path_invert (path); - peer_info_add_path (peer_info, path, trusted); -} - - -/** - * Add a tunnel to the list of tunnels a peer participates in. - * Update the tunnel's destination. - * - * @param p Peer to add to. - * @param t Tunnel to add. - */ -static void -peer_info_add_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t) -{ - if (0 != t->dest) - { - GNUNET_break (t->dest == p->id); - return; - } - t->dest = p->id; - GNUNET_PEER_change_rc (t->dest, 1); - GNUNET_array_append (p->tunnels, p->ntunnels, t); -} - - -/** - * Remove a tunnel from the list of tunnels a peer participates in. - * Free the tunnel's destination. - * - * @param p Peer to clean. - * @param t Tunnel to remove. - */ -static void -peer_info_remove_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t) -{ - unsigned int i; - - if (t->dest == p->id) - { - GNUNET_PEER_change_rc (t->dest, -1); - t->dest = 0; - } - for (i = 0; i < p->ntunnels; i++) - { - if (p->tunnels[i] == t) - { - p->tunnels[i] = p->tunnels[p->ntunnels - 1]; - GNUNET_array_grow (p->tunnels, p->ntunnels, p->ntunnels - 1); - return; - } - } -} - - -/** - * Function called if the connection to the peer has been stalled for a while, - * possibly due to a missed ACK. Poll the peer about its ACK status. - * - * @param cls Closure (poll ctx). - * @param tc TaskContext. - */ -static void -tunnel_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct MeshFlowControl *fc = cls; - struct GNUNET_MESH_Poll msg; - struct MeshTunnel *t = fc->t; - GNUNET_PEER_Id peer; - - fc->poll_task = GNUNET_SCHEDULER_NO_TASK; - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - { - return; - } - - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL); - msg.header.size = htons (sizeof (msg)); - msg.tid = htonl (t->id.tid); - GNUNET_PEER_resolve (t->id.oid, &msg.oid); - - if (fc == &t->prev_fc) - { - peer = t->prev_hop; - } - else if (fc == &t->next_fc) - { - peer = t->next_hop; - } - else - { - GNUNET_break (0); - return; - } - send_prebuilt_message (&msg.header, peer, t); - fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time); - fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, - &tunnel_poll, fc); -} - - -/** - * Build a PeerPath from the paths returned from the DHT, reversing the paths - * to obtain a local peer -> destination path and interning the peer ids. - * - * @return Newly allocated and created path - */ -static struct MeshPeerPath * -path_build_from_dht (const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length) -{ - struct MeshPeerPath *p; - GNUNET_PEER_Id id; - int i; - - p = path_new (1); - p->peers[0] = myid; - GNUNET_PEER_change_rc (myid, 1); - i = get_path_length; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " GET has %d hops.\n", i); - for (i--; i >= 0; i--) - { - id = GNUNET_PEER_intern (&get_path[i]); - if (p->length > 0 && id == p->peers[p->length - 1]) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n"); - GNUNET_PEER_change_rc (id, -1); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Adding from GET: %s.\n", - GNUNET_i2s (&get_path[i])); - p->length++; - p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length); - p->peers[p->length - 1] = id; - } - } - i = put_path_length; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " PUT has %d hops.\n", i); - for (i--; i >= 0; i--) - { - id = GNUNET_PEER_intern (&put_path[i]); - if (id == myid) - { - /* PUT path went through us, so discard the path up until now and start - * from here to get a much shorter (and loop-free) path. - */ - path_destroy (p); - p = path_new (0); - } - if (p->length > 0 && id == p->peers[p->length - 1]) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n"); - GNUNET_PEER_change_rc (id, -1); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Adding from PUT: %s.\n", - GNUNET_i2s (&put_path[i])); - p->length++; - p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length); - p->peers[p->length - 1] = id; - } - } -#if MESH_DEBUG - if (get_path_length > 0) - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (first of GET: %s)\n", - GNUNET_i2s (&get_path[0])); - if (put_path_length > 0) - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (first of PUT: %s)\n", - GNUNET_i2s (&put_path[0])); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " In total: %d hops\n", - p->length); - for (i = 0; i < p->length; i++) - { - struct GNUNET_PeerIdentity peer_id; - - GNUNET_PEER_resolve (p->peers[i], &peer_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %u: %s\n", p->peers[i], - GNUNET_i2s (&peer_id)); - } -#endif - return p; -} - - -/** - * 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. - */ -static void -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++; i < p->length; i++) - { - struct MeshPeerInfo *aux; - struct MeshPeerPath *copy; - - aux = peer_get_short (p->peers[i]); - copy = path_duplicate (p); - copy->length = i + 1; - peer_info_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed); - } -} - - -/** - * Send keepalive packets for a peer - * - * @param cls Closure (tunnel for which to send the keepalive). - * @param tc Notification context. - */ -static void -path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); - - -/** - * Search for a tunnel among the incoming tunnels - * - * @param tid the local id of the tunnel - * - * @return tunnel handler, NULL if doesn't exist - */ -static struct MeshTunnel * -tunnel_get_incoming (MESH_TunnelNumber tid) -{ - struct GNUNET_HashCode hash; - - GNUNET_assert (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV); - GMC_hash32 (tid, &hash); - return GNUNET_CONTAINER_multihashmap_get (incoming_tunnels, &hash); -} - - -/** - * Search for a tunnel among the tunnels for a client - * - * @param c the client whose tunnels to search in - * @param tid the local id of the tunnel - * - * @return tunnel handler, NULL if doesn't exist - */ -static struct MeshTunnel * -tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid) -{ - if (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) - { - return tunnel_get_incoming (tid); - } - else - { - struct GNUNET_HashCode hash; - - GMC_hash32 (tid, &hash); - return GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash); - } -} - - -/** - * Search for a tunnel by global ID using PEER_ID - * - * @param pi owner of the tunnel - * @param tid global tunnel number - * - * @return tunnel handler, NULL if doesn't exist - */ -static struct MeshTunnel * -tunnel_get_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid) -{ - struct MESH_TunnelID id; - struct GNUNET_HashCode hash; - - id.oid = pi; - id.tid = tid; - - GNUNET_CRYPTO_hash (&id, sizeof (struct MESH_TunnelID), &hash); - return GNUNET_CONTAINER_multihashmap_get (tunnels, &hash); -} - - -/** - * Search for a tunnel by global ID using full PeerIdentities - * - * @param oid owner of the tunnel - * @param tid global tunnel number - * - * @return tunnel handler, NULL if doesn't exist - */ -static struct MeshTunnel * -tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid) -{ - return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid); -} - - -/** - * Add a client to a tunnel, initializing all needed data structures. - * - * @param t Tunnel to which add the client. - * @param c Client which to add to the tunnel. - */ -static void -tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c) -{ - struct GNUNET_HashCode hash; - - if (NULL != t->client) - { - GNUNET_break(0); - return; - } - GMC_hash32 (t->local_tid_dest, &hash); - if (GNUNET_OK != - GNUNET_CONTAINER_multihashmap_put (c->incoming_tunnels, &hash, t, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) - { - GNUNET_break (0); - return; - } - if (GNUNET_OK != - GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) - { - GNUNET_break (0); - return; - } - t->client = c; -} - - -static void -tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p) -{ - unsigned int own_pos; - - for (own_pos = 0; own_pos < p->length; own_pos++) - { - if (p->peers[own_pos] == myid) - break; - } - if (own_pos > p->length - 1) - { - GNUNET_break (0); - return; - } - - if (own_pos < p->length - 1) - t->next_hop = p->peers[own_pos + 1]; - else - t->next_hop = p->peers[own_pos]; - GNUNET_PEER_change_rc (t->next_hop, 1); - if (0 < own_pos) - t->prev_hop = p->peers[own_pos - 1]; - else - t->prev_hop = p->peers[0]; - GNUNET_PEER_change_rc (t->prev_hop, 1); - - if (NULL != t->path) - path_destroy (t->path); - t->path = path_duplicate (p); - if (0 == own_pos) - { - if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task) - GNUNET_SCHEDULER_cancel (t->maintenance_task); - t->maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_path_time, - &path_refresh, t); - } -} - - -/** - * Notifies a tunnel that a connection has broken that affects at least - * some of its peers. Sends a notification towards the root of the tree. - * In case the peer is the owner of the tree, notifies the client that owns - * the tunnel and tries to reconnect. - * - * @param t Tunnel affected. - * @param p1 Peer that got disconnected from p2. - * @param p2 Peer that got disconnected from p1. - * - * @return Short ID of the peer disconnected (either p1 or p2). - * 0 if the tunnel remained unaffected. - */ -static GNUNET_PEER_Id -tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1, - GNUNET_PEER_Id p2) -{ -// if (myid != p1 && myid != p2) FIXME -// { -// return; -// } -// -// if (tree_get_predecessor (t->tree) != 0) -// { -// /* We are the peer still connected, notify owner of the disconnection. */ -// struct GNUNET_MESH_PathBroken msg; -// struct GNUNET_PeerIdentity neighbor; -// -// msg.header.size = htons (sizeof (msg)); -// msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN); -// GNUNET_PEER_resolve (t->id.oid, &msg.oid); -// msg.tid = htonl (t->id.tid); -// msg.peer1 = my_full_id; -// GNUNET_PEER_resolve (pid, &msg.peer2); -// GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor); -// send_prebuilt_message (&msg.header, &neighbor, t); -// } - return 0; -} - - -/** - * Build a local ACK message and send it to a local client. - * - * @param t Tunnel on which to send the ACK. - * @param c Client to whom send the ACK. - * @param ack Value of the ACK. - */ -static void -send_local_ack (struct MeshTunnel *t, struct MeshClient *c, uint32_t ack) -{ - struct GNUNET_MESH_LocalAck msg; - - msg.header.size = htons (sizeof (msg)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); - msg.tunnel_id = htonl (t->owner == c ? t->local_tid : t->local_tid_dest); - msg.ack = htonl (ack); - GNUNET_SERVER_notification_context_unicast(nc, - c->handle, - &msg.header, - GNUNET_NO); -} - -/** - * Build an ACK message and queue it to send to the given peer. - * - * @param t Tunnel on which to send the ACK. - * @param peer Peer to whom send the ACK. - * @param ack Value of the ACK. - */ -static void -send_ack (struct MeshTunnel *t, GNUNET_PEER_Id peer, uint32_t ack) -{ - struct GNUNET_MESH_ACK msg; - - GNUNET_PEER_resolve (t->id.oid, &msg.oid); - msg.header.size = htons (sizeof (msg)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK); - msg.pid = htonl (ack); - msg.tid = htonl (t->id.tid); - - send_prebuilt_message (&msg.header, peer, t); -} - - -/** - * Send an ACK informing the predecessor about the available buffer space. - * In case there is no predecessor, inform the owning client. - * If buffering is off, send only on behalf of children or self if endpoint. - * If buffering is on, send when sent to children and buffer space is free. - * Note that although the name is fwd_ack, the FWD mean forward *traffic*, - * the ACK itself goes "back" (towards root). - * - * @param t Tunnel on which to send the ACK. - * @param type Type of message that triggered the ACK transmission. - */ -static void -tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type) -{ - uint32_t ack; - - /* Is it after unicast retransmission? */ - switch (type) - { - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "ACK due to FWD DATA retransmission\n"); - if (GNUNET_YES == t->nobuffer) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, nobuffer\n"); - return; - } - break; - case GNUNET_MESSAGE_TYPE_MESH_ACK: - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: - break; - case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK: - case GNUNET_MESSAGE_TYPE_MESH_POLL: - t->force_ack = GNUNET_YES; - break; - default: - GNUNET_break (0); - } - - /* Check if we need to transmit the ACK */ - if (t->queue_max > t->next_fc.queue_n * 4 && - GMC_is_pid_bigger(t->prev_fc.last_ack_sent, t->prev_fc.last_pid_recv) && - GNUNET_NO == t->force_ack) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " t->qmax: %u, t->qn: %u\n", - t->queue_max, t->next_fc.queue_n); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " t->pid: %u, t->ack: %u\n", - t->prev_fc.last_pid_recv, t->prev_fc.last_ack_sent); - return; - } - - /* Ok, ACK might be necessary, what PID to ACK? */ - ack = t->prev_fc.last_pid_recv + t->queue_max - t->next_fc.queue_n; - if (ack == t->prev_fc.last_ack_sent && GNUNET_NO == t->force_ack) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n"); - return; - } - - t->prev_fc.last_ack_sent = ack; - if (NULL != t->owner) - send_local_ack (t, t->owner, ack); - else if (0 != t->prev_hop) - send_ack (t, t->prev_hop, ack); - else - GNUNET_break (0); - debug_fwd_ack++; - t->force_ack = GNUNET_NO; -} - - -/** - * Send an ACK informing the children node/client about the available - * buffer space. - * If buffering is off, send only on behalf of root (can be self). - * If buffering is on, send when sent to predecessor and buffer space is free. - * Note that although the name is bck_ack, the BCK mean backwards *traffic*, - * the ACK itself goes "forward" (towards children/clients). - * - * @param t Tunnel on which to send the ACK. - * @param type Type of message that triggered the ACK transmission. - */ -static void -tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type) -{ - uint32_t ack; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending BCK ACK on tunnel %u [%u] due to %s\n", - t->id.oid, t->id.tid, GNUNET_MESH_DEBUG_M2S(type)); - /* Is it after data to_origin retransmission? */ - switch (type) - { - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - if (GNUNET_YES == t->nobuffer) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Not sending ACK, nobuffer + traffic\n"); - return; - } - break; - case GNUNET_MESSAGE_TYPE_MESH_ACK: - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: - break; - case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK: - case GNUNET_MESSAGE_TYPE_MESH_POLL: - t->force_ack = GNUNET_YES; - break; - default: - GNUNET_break (0); - } - - /* TODO: Check if we need to transmit the ACK (as in fwd) */ - - ack = t->next_fc.last_pid_recv + t->queue_max - t->prev_fc.queue_n; - - if (t->next_fc.last_ack_sent == ack && GNUNET_NO == t->force_ack) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Not sending ACK, not needed, last ack sent was %u\n", - t->next_fc.last_ack_sent); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Sending BCK ACK %u (last sent: %u)\n", - ack, t->next_fc.last_ack_sent); - t->next_fc.last_ack_sent = ack; - - if (NULL != t->client) - send_local_ack (t, t->client, ack); - else if (0 != t->next_hop) - send_ack (t, t->next_hop, ack); - else - GNUNET_break (0); - t->force_ack = GNUNET_NO; -} - - -/** - * Modify the unicast message TID from global to local and send to client. - * - * @param t Tunnel on which to send the message. - * @param msg Message to modify and send. - */ -static void -tunnel_send_client_ucast (struct MeshTunnel *t, - const struct GNUNET_MESH_Data *msg) -{ - struct GNUNET_MESH_Data *copy; - uint16_t size = ntohs (msg->header.size); - char cbuf[size]; - - if (size < sizeof (struct GNUNET_MESH_Data) + - sizeof (struct GNUNET_MessageHeader)) - { - GNUNET_break_op (0); - return; - } - if (NULL == t->client) - { - GNUNET_break (0); - return; - } - copy = (struct GNUNET_MESH_Data *) cbuf; - memcpy (copy, msg, size); - copy->tid = htonl (t->local_tid_dest); - GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, - ©->header, GNUNET_NO); -} - - -/** - * Modify the to_origin message TID from global to local and send to client. - * - * @param t Tunnel on which to send the message. - * @param msg Message to modify and send. - */ -static void -tunnel_send_client_to_orig (struct MeshTunnel *t, - const struct GNUNET_MESH_Data *msg) -{ - struct GNUNET_MESH_Data *copy; - uint16_t size = ntohs (msg->header.size); - char cbuf[size]; - - if (size < sizeof (struct GNUNET_MESH_Data) + - sizeof (struct GNUNET_MessageHeader)) - { - GNUNET_break_op (0); - return; - } - if (NULL == t->owner) - { - GNUNET_break (0); - return; - } - copy = (struct GNUNET_MESH_Data *) cbuf; - memcpy (cbuf, msg, size); - copy->tid = htonl (t->local_tid); - GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, - ©->header, GNUNET_NO); -} - - -/** - * @brief Re-initiate traffic to this peer if necessary. - * - * Check if there is traffic queued towards this peer - * and the core transmit handle is NULL (traffic was stalled). - * If so, call core tmt rdy. - * - * @param peer_id Short ID of peer to which initiate traffic. - */ -static void -peer_unlock_queue(GNUNET_PEER_Id peer_id) -{ - struct MeshPeerInfo *peer; - struct GNUNET_PeerIdentity id; - struct MeshPeerQueue *q; - size_t size; - - peer = peer_get_short (peer_id); - if (NULL != peer->core_transmit) - return; - - q = queue_get_next (peer); - if (NULL == q) - { - /* Might br multicast traffic already sent to this particular peer but - * not to other children in this tunnel. - * This way t->queue_n would be > 0 but the queue of this particular peer - * would be empty. - */ - return; - } - size = q->size; - GNUNET_PEER_resolve (peer->id, &id); - peer->core_transmit = - GNUNET_CORE_notify_transmit_ready(core_handle, - 0, - 0, - GNUNET_TIME_UNIT_FOREVER_REL, - &id, - size, - &queue_send, - peer); - return; -} - - -/** - * Send a message to all peers and clients in this tunnel that the tunnel - * is no longer valid. If some peer or client should not receive the message, - * should be zero'ed out before calling this function. - * - * @param t The tunnel whose peers and clients to notify. - */ -static void -tunnel_send_destroy (struct MeshTunnel *t) -{ - struct GNUNET_MESH_TunnelDestroy msg; - struct GNUNET_PeerIdentity id; - - msg.header.size = htons (sizeof (msg)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY); - GNUNET_PEER_resolve (t->id.oid, &msg.oid); - msg.tid = htonl (t->id.tid); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " sending tunnel destroy for tunnel: %s [%X]\n", - GNUNET_i2s (&msg.oid), t->id.tid); - - if (NULL == t->client && 0 != t->next_hop) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " child: %u\n", t->next_hop); - GNUNET_PEER_resolve (t->next_hop, &id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " sending forward to %s\n", - GNUNET_i2s (&id)); - send_prebuilt_message (&msg.header, t->next_hop, t); - } - if (NULL == t->owner && 0 != t->prev_hop) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " parent: %u\n", t->prev_hop); - GNUNET_PEER_resolve (t->prev_hop, &id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " sending back to %s\n", - GNUNET_i2s (&id)); - send_prebuilt_message (&msg.header, t->prev_hop, t); - } - if (NULL != t->owner) - { - send_client_tunnel_destroy (t->owner, t); - } - if (NULL != t->client) - { - send_client_tunnel_destroy (t->client, t); - } -} - - -/** - * Cancel all transmissions towards a neighbor that belongs to a certain tunnel. - * - * @param t Tunnel which to cancel. - * @param neighbor Short ID of the neighbor to whom cancel the transmissions. - */ -static void -peer_cancel_queues (GNUNET_PEER_Id neighbor, struct MeshTunnel *t) -{ - struct MeshPeerInfo *peer_info; - struct MeshPeerQueue *pq; - struct MeshPeerQueue *next; - - if (0 == neighbor) - return; /* Was local peer, 0'ed in tunnel_destroy_iterator */ - peer_info = peer_get_short (neighbor); - for (pq = peer_info->queue_head; NULL != pq; pq = next) - { - next = pq->next; - if (pq->tunnel == t) - { - if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == pq->type || - GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == pq->type) - { - /* Should have been removed on destroy children */ - GNUNET_break (0); - } - queue_destroy (pq, GNUNET_YES); - } - } - if (NULL == peer_info->queue_head && NULL != peer_info->core_transmit) - { - GNUNET_CORE_notify_transmit_ready_cancel(peer_info->core_transmit); - peer_info->core_transmit = NULL; - } -} - - -/** - * Destroy the tunnel. - * - * This function does not generate any warning traffic to clients or peers. - * - * Tasks: - * Remove the tunnel from peer_info's and clients' hashmaps. - * Cancel messages belonging to this tunnel queued to neighbors. - * Free any allocated resources linked to the tunnel. - * - * @param t the tunnel to destroy - * - * @return GNUNET_OK on success - */ -static int -tunnel_destroy (struct MeshTunnel *t) -{ - struct MeshClient *c; - struct GNUNET_HashCode hash; - int r; - - if (NULL == t) - return GNUNET_OK; - - r = GNUNET_OK; - c = t->owner; -#if MESH_DEBUG - { - struct GNUNET_PeerIdentity id; - - GNUNET_PEER_resolve (t->id.oid, &id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s [%x]\n", - GNUNET_i2s (&id), t->id.tid); - if (NULL != c) - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); - } -#endif - - GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash); - if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t)) - { - GNUNET_break (0); - r = GNUNET_SYSERR; - } - - if (NULL != c) - { - GMC_hash32 (t->local_tid, &hash); - if (GNUNET_YES != - GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t)) - { - GNUNET_break (0); - r = GNUNET_SYSERR; - } - } - - if (NULL != t->client) - { - c = t->client; - GMC_hash32 (t->local_tid_dest, &hash); - if (GNUNET_YES != - GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t)) - { - GNUNET_break (0); - r = GNUNET_SYSERR; - } - if (GNUNET_YES != - GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t)) - { - GNUNET_break (0); - r = GNUNET_SYSERR; - } - } - - if (0 != t->prev_hop) - { - peer_cancel_queues (t->prev_hop, t); - GNUNET_PEER_change_rc (t->prev_hop, -1); - } - if (0 != t->next_hop) - { - peer_cancel_queues (t->next_hop, t); - GNUNET_PEER_change_rc (t->next_hop, -1); - } - if (0 != t->dest) { - peer_info_remove_tunnel (peer_get_short (t->dest), t); - } - - if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task) - GNUNET_SCHEDULER_cancel (t->maintenance_task); - - n_tunnels--; - GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO); - path_destroy (t->path); - GNUNET_free (t); - return r; -} - -/** - * Tunnel is empty: destroy it. - * - * Notifies all participants (peers, cleints) about the destruction. - * - * @param t Tunnel to destroy. - */ -static void -tunnel_destroy_empty (struct MeshTunnel *t) -{ - #if MESH_DEBUG - { - struct GNUNET_PeerIdentity id; - - GNUNET_PEER_resolve (t->id.oid, &id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "executing destruction of empty tunnel %s [%X]\n", - GNUNET_i2s (&id), t->id.tid); - } - #endif - - if (GNUNET_NO == t->destroy) - tunnel_send_destroy (t); - if (0 == t->pending_messages) - tunnel_destroy (t); - else - t->destroy = GNUNET_YES; -} - -/** - * Initialize a Flow Control structure to the initial state. - * - * @param fc Flow Control structure to initialize. - */ -static void -fc_init (struct MeshFlowControl *fc) -{ - fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */ - fc->last_pid_recv = (uint32_t) -1; - fc->last_ack_sent = (uint32_t) -1; /* No traffic allowed yet */ - fc->last_ack_recv = (uint32_t) -1; - fc->poll_task = GNUNET_SCHEDULER_NO_TASK; - fc->poll_time = GNUNET_TIME_UNIT_SECONDS; - fc->queue_n = 0; -} - -/** - * Create a new tunnel - * - * @param owner Who is the owner of the tunnel (short ID). - * @param tid Tunnel Number of the tunnel. - * @param client Clients that owns the tunnel, NULL for foreign tunnels. - * @param local Tunnel Number for the tunnel, for the client point of view. - * - * @return A new initialized tunnel. NULL on error. - */ -static struct MeshTunnel * -tunnel_new (GNUNET_PEER_Id owner, - MESH_TunnelNumber tid, - struct MeshClient *client, - MESH_TunnelNumber local) -{ - struct MeshTunnel *t; - struct GNUNET_HashCode hash; - - if (n_tunnels >= max_tunnels && NULL == client) - return NULL; - - t = GNUNET_malloc (sizeof (struct MeshTunnel)); - t->id.oid = owner; - t->id.tid = tid; - t->queue_max = (max_msgs_queue / max_tunnels) + 1; - t->owner = client; - fc_init (&t->next_fc); - fc_init (&t->prev_fc); - t->local_tid = local; - n_tunnels++; - GNUNET_STATISTICS_update (stats, "# tunnels", 1, GNUNET_NO); - - GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash); - if (GNUNET_OK != - GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) - { - GNUNET_break (0); - tunnel_destroy (t); - if (NULL != client) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR); - } - return NULL; - } - - if (NULL != client) - { - GMC_hash32 (t->local_tid, &hash); - if (GNUNET_OK != - GNUNET_CONTAINER_multihashmap_put (client->own_tunnels, &hash, t, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) - { - tunnel_destroy (t); - GNUNET_break (0); - GNUNET_SERVER_receive_done (client->handle, GNUNET_SYSERR); - return NULL; - } - } - - return t; -} - - - -/** - * Iterator for deleting each tunnel whose client endpoint disconnected. - * - * @param cls Closure (client that has disconnected). - * @param key The hash of the local tunnel id (used to access the hashmap). - * @param value The value stored at the key (tunnel to destroy). - * - * @return GNUNET_OK, keep iterating. - */ -static int -tunnel_destroy_iterator (void *cls, - const struct GNUNET_HashCode * key, - void *value) -{ - struct MeshTunnel *t = value; - struct MeshClient *c = cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Tunnel %X / %X destroy, due to client %u shutdown.\n", - t->local_tid, t->local_tid_dest, c->id); - client_delete_tunnel (c, t); - if (c == t->client) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is destination.\n", c->id); - t->client = NULL; - if (0 != t->next_hop) { /* destroy could come before a path is used */ - GNUNET_PEER_change_rc (t->next_hop, -1); - t->next_hop = 0; - } - } - else if (c == t->owner) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is owner.\n", c->id); - t->owner = NULL; - if (0 != t->prev_hop) { /* destroy could come before a path is used */ - GNUNET_PEER_change_rc (t->prev_hop, -1); - t->prev_hop = 0; - } - } - else - { - GNUNET_break (0); - } - tunnel_destroy_empty (t); - - return GNUNET_OK; -} - - -/** - * Timeout function, destroys tunnel if called - * - * @param cls Closure (tunnel to destroy). - * @param tc TaskContext - */ -static void -tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct MeshTunnel *t = cls; - struct GNUNET_PeerIdentity id; - - t->maintenance_task = GNUNET_SCHEDULER_NO_TASK; - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - return; - GNUNET_PEER_resolve(t->id.oid, &id); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Tunnel %s [%X] timed out. Destroying.\n", - GNUNET_i2s(&id), t->id.tid); - if (NULL != t->client) - send_client_tunnel_destroy (t->client, t); - tunnel_destroy (t); /* Do not notify other */ -} - - -/** - * Resets the tunnel timeout. Starts it if no timeout was running. - * - * @param t Tunnel whose timeout to reset. - * - * TODO use heap to improve efficiency of scheduler. - */ -static void -tunnel_reset_timeout (struct MeshTunnel *t) -{ - if (NULL != t->owner || 0 != t->local_tid || 0 == t->prev_hop) - return; - if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task) - GNUNET_SCHEDULER_cancel (t->maintenance_task); - t->maintenance_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (refresh_path_time, 4), &tunnel_timeout, t); -} - - -/******************************************************************************/ -/**************** MESH NETWORK HANDLER HELPERS ***********************/ -/******************************************************************************/ - -/** - * Function to send a create path packet to a peer. - * - * @param cls closure - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf - */ -static size_t -send_core_path_create (void *cls, size_t size, void *buf) -{ - struct MeshTunnel *t = cls; - struct GNUNET_MESH_CreateTunnel *msg; - struct GNUNET_PeerIdentity *peer_ptr; - struct MeshPeerPath *p = t->path; - size_t size_needed; - uint32_t opt; - int i; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATE PATH sending...\n"); - size_needed = - sizeof (struct GNUNET_MESH_CreateTunnel) + - p->length * sizeof (struct GNUNET_PeerIdentity); - - if (size < size_needed || NULL == buf) - { - GNUNET_break (0); - return 0; - } - msg = (struct GNUNET_MESH_CreateTunnel *) buf; - msg->header.size = htons (size_needed); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE); - msg->tid = ntohl (t->id.tid); - - opt = 0; - if (GNUNET_YES == t->nobuffer) - opt |= MESH_TUNNEL_OPT_NOBUFFER; - msg->opt = htonl (opt); - msg->port = htonl (t->port); - - peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1]; - for (i = 0; i < p->length; i++) - { - GNUNET_PEER_resolve (p->peers[i], peer_ptr++); - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "CREATE PATH (%u bytes long) sent!\n", size_needed); - return size_needed; -} - - -/** - * Creates a path ack message in buf and frees all unused resources. - * - * @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 - */ -static size_t -send_core_path_ack (void *cls, size_t size, void *buf) -{ - struct MeshTunnel *t = cls; - struct GNUNET_MESH_PathACK *msg = buf; - - GNUNET_assert (NULL != t); - if (sizeof (struct GNUNET_MESH_PathACK) > size) - { - GNUNET_break (0); - return 0; - } - t->prev_fc.last_ack_sent = t->nobuffer ? 0 : t->queue_max - 1; - msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK)); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK); - GNUNET_PEER_resolve (t->id.oid, &msg->oid); - msg->tid = htonl (t->id.tid); - msg->peer_id = my_full_id; - msg->ack = htonl (t->prev_fc.last_ack_sent); - - /* TODO add signature */ - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH ACK sent!\n"); - return sizeof (struct GNUNET_MESH_PathACK); -} - - -/** - * Free a transmission that was already queued with all resources - * associated to the request. - * - * @param queue Queue handler to cancel. - * @param clear_cls Is it necessary to free associated cls? - */ -static void -queue_destroy (struct MeshPeerQueue *queue, int clear_cls) -{ - struct MeshFlowControl *fc; - - if (GNUNET_YES == clear_cls) - { - switch (queue->type) - { - case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, " cancelling TUNNEL_DESTROY\n"); - GNUNET_break (GNUNET_YES == queue->tunnel->destroy); - /* fall through */ - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - case GNUNET_MESSAGE_TYPE_MESH_ACK: - case GNUNET_MESSAGE_TYPE_MESH_POLL: - case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " prebuilt message\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " type %s\n", - GNUNET_MESH_DEBUG_M2S (queue->type)); - break; - case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type create path\n"); - break; - default: - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - " type %s unknown!\n", - GNUNET_MESH_DEBUG_M2S (queue->type)); - } - GNUNET_free_non_null (queue->cls); - } - GNUNET_CONTAINER_DLL_remove (queue->peer->queue_head, - queue->peer->queue_tail, - queue); - - /* Delete from appropriate fc in the tunnel */ - if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == queue->type || - GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == queue->type ) - { - if (queue->peer->id == queue->tunnel->prev_hop) - fc = &queue->tunnel->prev_fc; - else if (queue->peer->id == queue->tunnel->next_hop) - fc = &queue->tunnel->next_fc; - else - { - GNUNET_break (0); - return; - } - fc->queue_n--; - } - GNUNET_free (queue); -} - - -/** - * @brief Get the next transmittable message from the queue. - * - * This will be the head, except in the case of being a data packet - * not allowed by the destination peer. - * - * @param peer Destination peer. - * - * @return The next viable MeshPeerQueue element to send to that peer. - * NULL when there are no transmittable messages. - */ -struct MeshPeerQueue * -queue_get_next (const struct MeshPeerInfo *peer) -{ - struct MeshPeerQueue *q; - - struct GNUNET_MESH_Data *dmsg; - struct MeshTunnel* t; - uint32_t pid; - uint32_t ack; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* selecting message\n"); - for (q = peer->queue_head; NULL != q; q = q->next) - { - t = q->tunnel; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "* %s\n", - GNUNET_MESH_DEBUG_M2S (q->type)); - dmsg = (struct GNUNET_MESH_Data *) q->cls; - pid = ntohl (dmsg->pid); - switch (q->type) - { - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - ack = t->next_fc.last_ack_recv; - break; - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - ack = t->prev_fc.last_ack_recv; - break; - default: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "* OK!\n"); - return q; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "* ACK: %u, PID: %u\n", - ack, pid); - if (GNUNET_NO == GMC_is_pid_bigger (pid, ack)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "* OK!\n"); - return q; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "* NEXT!\n"); - } - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "* nothing found\n"); - return NULL; -} - - -static size_t -queue_send (void *cls, size_t size, void *buf) -{ - struct MeshPeerInfo *peer = cls; - struct GNUNET_MessageHeader *msg; - struct MeshPeerQueue *queue; - struct MeshTunnel *t; - struct GNUNET_PeerIdentity dst_id; - struct MeshFlowControl *fc; - size_t data_size; - uint32_t pid; - uint16_t type; - - peer->core_transmit = NULL; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Queue send\n"); - queue = queue_get_next (peer); - - /* Queue has no internal mesh traffic nor sendable payload */ - if (NULL == queue) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* not ready, return\n"); - if (NULL == peer->queue_head) - GNUNET_break (0); /* Core tmt_rdy should've been canceled */ - return 0; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* not empty\n"); - - GNUNET_PEER_resolve (peer->id, &dst_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "* towards %s\n", - GNUNET_i2s (&dst_id)); - /* Check if buffer size is enough for the message */ - if (queue->size > size) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "* not enough room, reissue\n"); - peer->core_transmit = - GNUNET_CORE_notify_transmit_ready (core_handle, - GNUNET_NO, - 0, - GNUNET_TIME_UNIT_FOREVER_REL, - &dst_id, - queue->size, - &queue_send, - peer); - return 0; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* size ok\n"); - - t = queue->tunnel; - GNUNET_assert (0 < t->pending_messages); - t->pending_messages--; - type = 0; - - /* Fill buf */ - switch (queue->type) - { - case 0: - case GNUNET_MESSAGE_TYPE_MESH_ACK: - case GNUNET_MESSAGE_TYPE_MESH_POLL: - case GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN: - case GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY: - case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY: - case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "* raw: %s\n", - GNUNET_MESH_DEBUG_M2S (queue->type)); - /* Fall through */ - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - data_size = send_core_data_raw (queue->cls, size, buf); - msg = (struct GNUNET_MessageHeader *) buf; - type = ntohs (msg->type); - break; - case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path create\n"); - data_size = send_core_path_create (queue->cls, size, buf); - break; - case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path ack\n"); - data_size = send_core_path_ack (queue->cls, size, buf); - break; - default: - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "* type unknown: %u\n", - queue->type); - data_size = 0; - } - - /* Free queue, but cls was freed by send_core_* */ - queue_destroy (queue, GNUNET_NO); - - /* Send ACK if needed, after accounting for sent ID in fc->queue_n */ - pid = ((struct GNUNET_MESH_Data *) buf)->pid; - switch (type) - { - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - t->next_fc.last_pid_sent = pid; - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST); - break; - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - t->prev_fc.last_pid_sent = pid; - tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN); - break; - default: - break; - } - - if (GNUNET_YES == t->destroy && 0 == t->pending_messages) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* destroying tunnel!\n"); - tunnel_destroy (t); - } - - /* If more data in queue, send next */ - queue = queue_get_next (peer); - if (NULL != queue) - { - struct GNUNET_PeerIdentity id; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* more data!\n"); - GNUNET_PEER_resolve (peer->id, &id); - peer->core_transmit = - GNUNET_CORE_notify_transmit_ready(core_handle, - 0, - 0, - GNUNET_TIME_UNIT_FOREVER_REL, - &id, - queue->size, - &queue_send, - peer); - } - else if (NULL != peer->queue_head) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "* %s stalled\n", - GNUNET_i2s (&my_full_id)); - if (peer->id == t->next_hop) - fc = &t->next_fc; - else if (peer->id == t->prev_hop) - fc = &t->prev_fc; - else - { - GNUNET_break (0); - fc = NULL; - } - if (NULL != fc && GNUNET_SCHEDULER_NO_TASK == fc->poll_task) - { - fc->t = t; - fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, - &tunnel_poll, fc); - } - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Return %d\n", data_size); - return data_size; -} - - -/** - * @brief Queue and pass message to core when possible. - * - * If type is payload (UNICAST, TO_ORIGIN) checks for queue status and - * accounts for it. In case the queue is full, the message is dropped and - * a break issued. - * - * Otherwise, message is treated as internal and allowed to go regardless of - * queue status. - * - * @param cls Closure (@c type dependant). It will be used by queue_send to - * build the message to be sent if not already prebuilt. - * @param type Type of the message, 0 for a raw message. - * @param size Size of the message. - * @param dst Neighbor to send message to. - * @param t Tunnel this message belongs to. - */ -static void -queue_add (void *cls, uint16_t type, size_t size, - struct MeshPeerInfo *dst, struct MeshTunnel *t) -{ - struct MeshPeerQueue *queue; - struct GNUNET_PeerIdentity id; - unsigned int *n; - - n = NULL; - if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type) - { - n = &t->next_fc.queue_n; - } - else if (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type) - { - n = &t->prev_fc.queue_n; - } - if (NULL != n) - { - if (*n >= t->queue_max) - { - GNUNET_break(0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "queue full: %u/%u\n", - *n, t->queue_max); - GNUNET_STATISTICS_update(stats, - "# messages dropped (buffer full)", - 1, GNUNET_NO); - return; /* Drop message */ - } - (*n)++; - } - queue = GNUNET_malloc (sizeof (struct MeshPeerQueue)); - queue->cls = cls; - queue->type = type; - queue->size = size; - queue->peer = dst; - queue->tunnel = t; - GNUNET_CONTAINER_DLL_insert_tail (dst->queue_head, dst->queue_tail, queue); - if (NULL == dst->core_transmit) - { - GNUNET_PEER_resolve (dst->id, &id); - dst->core_transmit = - GNUNET_CORE_notify_transmit_ready (core_handle, - 0, - 0, - GNUNET_TIME_UNIT_FOREVER_REL, - &id, - size, - &queue_send, - dst); - } - t->pending_messages++; -} - - -/******************************************************************************/ -/******************** MESH NETWORK HANDLERS **************************/ -/******************************************************************************/ - - -/** - * Core handler for path creation - * - * @param cls closure - * @param message message - * @param peer peer identity this notification is about - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - unsigned int own_pos; - uint16_t size; - uint16_t i; - MESH_TunnelNumber tid; - struct GNUNET_MESH_CreateTunnel *msg; - struct GNUNET_PeerIdentity *pi; - struct MeshPeerPath *path; - struct MeshPeerInfo *dest_peer_info; - struct MeshPeerInfo *orig_peer_info; - struct MeshTunnel *t; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received a path create msg [%s]\n", - GNUNET_i2s (&my_full_id)); - size = ntohs (message->size); - if (size < sizeof (struct GNUNET_MESH_CreateTunnel)) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - - size -= sizeof (struct GNUNET_MESH_CreateTunnel); - if (size % sizeof (struct GNUNET_PeerIdentity)) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - size /= sizeof (struct GNUNET_PeerIdentity); - if (size < 1) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); - msg = (struct GNUNET_MESH_CreateTunnel *) message; - - tid = ntohl (msg->tid); - pi = (struct GNUNET_PeerIdentity *) &msg[1]; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " path is for tunnel %s[%X].\n", GNUNET_i2s (pi), tid); - t = tunnel_get (pi, tid); - if (NULL == t) /* might be a local tunnel */ - { - uint32_t opt; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating tunnel\n"); - t = tunnel_new (GNUNET_PEER_intern (pi), tid, NULL, 0); - if (NULL == t) - { - GNUNET_break (0); - return GNUNET_OK; - } - t->port = ntohl (msg->port); - opt = ntohl (msg->opt); - if (0 != (opt & MESH_TUNNEL_OPT_NOBUFFER)) - { - t->nobuffer = GNUNET_YES; - t->queue_max = 1; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " nobuffer:%d\n", t->nobuffer); - - tunnel_reset_timeout (t); - } - t->state = MESH_TUNNEL_WAITING; - dest_peer_info = - GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey); - if (NULL == dest_peer_info) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Creating PeerInfo for destination.\n"); - dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo)); - dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]); - GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey, - dest_peer_info, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); - } - orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey); - if (NULL == orig_peer_info) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Creating PeerInfo for origin.\n"); - orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo)); - orig_peer_info->id = GNUNET_PEER_intern (pi); - GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n"); - path = path_new (size); - own_pos = 0; - for (i = 0; i < size; i++) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... adding %s\n", - GNUNET_i2s (&pi[i])); - path->peers[i] = GNUNET_PEER_intern (&pi[i]); - if (path->peers[i] == myid) - own_pos = i; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos); - if (own_pos == 0 && path->peers[own_pos] != myid) - { - /* create path: self not found in path through self */ - GNUNET_break_op (0); - path_destroy (path); - tunnel_destroy (t); - return GNUNET_OK; - } - path_add_to_peers (path, GNUNET_NO); - tunnel_use_path (t, path); - - peer_info_add_tunnel (dest_peer_info, t); - - if (own_pos == size - 1) - { - struct MeshClient *c; - struct GNUNET_HashCode hc; - - /* Find target client */ - GMC_hash32 (t->port, &hc); - c = GNUNET_CONTAINER_multihashmap_get (ports, &hc); - if (NULL == c) - { - /* TODO send reject */ - return GNUNET_OK; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); - peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_YES); - - /* Assign local tid */ - while (NULL != tunnel_get_incoming (next_local_tid)) - next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; - t->local_tid_dest = next_local_tid++; - next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; - - tunnel_add_client (t, c); - send_client_tunnel_create (t); - send_path_ack (t); - } - else - { - struct MeshPeerPath *path2; - - t->next_hop = path->peers[own_pos + 1]; - GNUNET_PEER_change_rc(t->next_hop, 1); - - /* It's for somebody else! Retransmit. */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n"); - path2 = path_duplicate (path); - peer_info_add_path (dest_peer_info, path2, GNUNET_NO); - peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO); - send_create_path (t); - } - return GNUNET_OK; -} - - - -/** - * Core handler for path ACKs - * - * @param cls closure - * @param message message - * @param peer peer identity this notification is about - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_PathACK *msg; - struct MeshPeerInfo *peer_info; - struct MeshPeerPath *p; - struct MeshTunnel *t; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a path ACK msg [%s]\n", - GNUNET_i2s (&my_full_id)); - msg = (struct GNUNET_MESH_PathACK *) message; - t = tunnel_get (&msg->oid, ntohl(msg->tid)); - if (NULL == t) - { - /* TODO notify that we don't know the tunnel */ - GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the tunnel %s [%X]!\n", - GNUNET_i2s (&msg->oid), ntohl(msg->tid)); - return GNUNET_OK; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %s [%X]\n", - GNUNET_i2s (&msg->oid), ntohl(msg->tid)); - - peer_info = peer_get (&msg->peer_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by peer %s\n", - GNUNET_i2s (&msg->peer_id)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", - GNUNET_i2s (peer)); - - /* Add path to peers? */ - p = t->path; - if (NULL != p) - { - path_add_to_peers (p, GNUNET_YES); - } - else - { - GNUNET_break (0); - } - t->state = MESH_TUNNEL_READY; - t->next_fc.last_ack_recv = (NULL == t->client) ? ntohl (msg->ack) : 0; - t->prev_fc.last_ack_sent = ntohl (msg->ack); - - /* Message for us? */ - if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity))) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); - if (NULL == t->owner) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - if (NULL != peer_info->dhtget) - { - GNUNET_DHT_get_stop (peer_info->dhtget); - peer_info->dhtget = NULL; - } - tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK); - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK); - return GNUNET_OK; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " not for us, retransmitting...\n"); - peer_info = peer_get (&msg->oid); - send_prebuilt_message (message, t->prev_hop, t); - return GNUNET_OK; -} - - -/** - * Core handler for notifications of broken paths - * - * @param cls closure - * @param message message - * @param peer peer identity this notification is about - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_path_broken (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_PathBroken *msg; - struct MeshTunnel *t; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received a PATH BROKEN msg from %s\n", GNUNET_i2s (peer)); - msg = (struct GNUNET_MESH_PathBroken *) message; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", - GNUNET_i2s (&msg->peer1)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", - GNUNET_i2s (&msg->peer2)); - t = tunnel_get (&msg->oid, ntohl (msg->tid)); - if (NULL == t) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - tunnel_notify_connection_broken (t, GNUNET_PEER_search (&msg->peer1), - GNUNET_PEER_search (&msg->peer2)); - return GNUNET_OK; - -} - - -/** - * Core handler for tunnel destruction - * - * @param cls closure - * @param message message - * @param peer peer identity this notification is about - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_TunnelDestroy *msg; - struct MeshTunnel *t; - - msg = (struct GNUNET_MESH_TunnelDestroy *) message; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got a TUNNEL DESTROY packet from %s\n", - GNUNET_i2s (peer)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " for tunnel %s [%u]\n", - GNUNET_i2s (&msg->oid), ntohl (msg->tid)); - t = tunnel_get (&msg->oid, ntohl (msg->tid)); - if (NULL == t) - { - /* Probably already got the message from another path, - * destroyed the tunnel and retransmitted to children. - * Safe to ignore. - */ - GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", - 1, GNUNET_NO); - return GNUNET_OK; - } - if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "INCOMING TUNNEL %X %X\n", - t->local_tid, t->local_tid_dest); - } - if (GNUNET_PEER_search (peer) == t->prev_hop) - { - // TODO check owner's signature - // TODO add owner's signatue to tunnel for retransmission - peer_cancel_queues (t->prev_hop, t); - GNUNET_PEER_change_rc (t->prev_hop, -1); - t->prev_hop = 0; - } - else if (GNUNET_PEER_search (peer) == t->next_hop) - { - // TODO check dest's signature - // TODO add dest's signatue to tunnel for retransmission - peer_cancel_queues (t->next_hop, t); - GNUNET_PEER_change_rc (t->next_hop, -1); - t->next_hop = 0; - } - else - { - GNUNET_break_op (0); - // TODO check both owner AND destination's signature to see which matches - // TODO restransmit in appropriate direction - return GNUNET_OK; - } - tunnel_destroy_empty (t); - - // TODO: add timeout to destroy the tunnel anyway - return GNUNET_OK; -} - - -/** - * Core handler for mesh network traffic going from the origin to a peer - * - * @param cls closure - * @param peer peer identity this notification is about - * @param message message - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_Data *msg; - struct MeshTunnel *t; - uint32_t pid; - uint32_t ttl; - size_t size; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a unicast packet from %s\n", - GNUNET_i2s (peer)); - /* Check size */ - size = ntohs (message->size); - if (size < - sizeof (struct GNUNET_MESH_Data) + - sizeof (struct GNUNET_MessageHeader)) - { - GNUNET_break (0); - return GNUNET_OK; - } - msg = (struct GNUNET_MESH_Data *) message; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n", - GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type))); - /* Check tunnel */ - t = tunnel_get (&msg->oid, ntohl (msg->tid)); - if (NULL == t) - { - /* TODO notify back: we don't know this tunnel */ - GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO); - GNUNET_break_op (0); - return GNUNET_OK; - } - pid = ntohl (msg->pid); - if (t->prev_fc.last_pid_recv == pid) - { - GNUNET_STATISTICS_update (stats, "# duplicate PID drops", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - " Already seen pid %u, DROPPING!\n", pid); - return GNUNET_OK; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " pid %u not seen yet, forwarding\n", pid); - } - - if (GMC_is_pid_bigger (pid, t->prev_fc.last_ack_sent)) - { - GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO); - GNUNET_break_op (0); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received PID %u, ACK %u\n", - pid, t->prev_fc.last_ack_sent); - tunnel_send_fwd_ack(t, GNUNET_MESSAGE_TYPE_MESH_POLL); - return GNUNET_OK; - } - t->prev_fc.last_pid_recv = pid; - - tunnel_reset_timeout (t); - if (t->dest == myid) - { - /* TODO signature verification */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " it's for us! sending to clients...\n"); - GNUNET_STATISTICS_update (stats, "# unicast received", 1, GNUNET_NO); - tunnel_send_client_ucast (t, msg); - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST); - return GNUNET_OK; - } - if (0 == t->next_hop) - { - GNUNET_break (0); - return GNUNET_OK; - } - ttl = ntohl (msg->ttl); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl); - if (ttl == 0) - { - GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n"); - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); - return GNUNET_OK; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " not for us, retransmitting...\n"); - - send_prebuilt_message (message, t->next_hop, t); - GNUNET_STATISTICS_update (stats, "# unicast forwarded", 1, GNUNET_NO); - return GNUNET_OK; -} - - -/** - * Core handler for mesh network traffic toward the owner of a tunnel - * - * @param cls closure - * @param message message - * @param peer peer identity this notification is about - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_Data *msg; - struct MeshTunnel *t; - size_t size; - uint32_t pid; - uint32_t ttl; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a ToOrigin packet from %s\n", - GNUNET_i2s (peer)); - size = ntohs (message->size); - if (size < sizeof (struct GNUNET_MESH_Data) + /* Payload must be */ - sizeof (struct GNUNET_MessageHeader)) /* at least a header */ - { - GNUNET_break_op (0); - return GNUNET_OK; - } - msg = (struct GNUNET_MESH_Data *) message; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n", - GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type))); - t = tunnel_get (&msg->oid, ntohl (msg->tid)); - pid = ntohl (msg->pid); - - if (NULL == t) - { - /* TODO notify that we dont know this tunnel (whom)? */ - GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received to_origin with PID %u on unknown tunnel %s [%u]\n", - pid, GNUNET_i2s (&msg->oid), ntohl (msg->tid)); - return GNUNET_OK; - } - - if (t->next_fc.last_pid_recv == pid) - { - /* already seen this packet, drop */ - GNUNET_STATISTICS_update (stats, "# duplicate PID drops BCK", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Already seen pid %u, DROPPING!\n", pid); - tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); - return GNUNET_OK; - } - - if (GMC_is_pid_bigger (pid, t->next_fc.last_ack_sent)) - { - GNUNET_STATISTICS_update (stats, "# unsolicited to_orig", 1, GNUNET_NO); - GNUNET_break_op (0); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received PID %u, ACK %u\n", - pid, t->next_fc.last_ack_sent); - tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL); - return GNUNET_OK; - } - t->next_fc.last_pid_recv = pid; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " pid %u not seen yet, forwarding\n", pid); - - if (myid == t->id.oid) - { - /* TODO signature verification */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " it's for us! sending to clients...\n"); - GNUNET_STATISTICS_update (stats, "# to origin received", 1, GNUNET_NO); - tunnel_send_client_to_orig (t, msg); - tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN); - return GNUNET_OK; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " not for us, retransmitting...\n"); - - if (0 == t->prev_hop) /* No owner AND no prev hop */ - { - if (GNUNET_YES == t->destroy) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "to orig received on a dying tunnel %s [%X]\n", - GNUNET_i2s (&msg->oid), ntohl(msg->tid)); - return GNUNET_OK; - } - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "unknown to origin at %s\n", - GNUNET_i2s (&my_full_id)); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "from peer %s\n", - GNUNET_i2s (peer)); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "on tunnel %s [%X]\n", - GNUNET_i2s (&msg->oid), ntohl(msg->tid)); - return GNUNET_OK; - } - ttl = ntohl (msg->ttl); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl); - if (ttl == 0) - { - GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n"); - tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); - return GNUNET_OK; - } - send_prebuilt_message (message, t->prev_hop, t); - GNUNET_STATISTICS_update (stats, "# to origin forwarded", 1, GNUNET_NO); - - return GNUNET_OK; -} - - -/** - * Core handler for mesh network traffic point-to-point acks. - * - * @param cls closure - * @param message message - * @param peer peer identity this notification is about - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_ACK *msg; - struct MeshTunnel *t; - GNUNET_PEER_Id id; - uint32_t ack; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n", - GNUNET_i2s (peer)); - msg = (struct GNUNET_MESH_ACK *) message; - - t = tunnel_get (&msg->oid, ntohl (msg->tid)); - - if (NULL == t) - { - /* TODO notify that we dont know this tunnel (whom)? */ - GNUNET_STATISTICS_update (stats, "# ack on unknown tunnel", 1, GNUNET_NO); - return GNUNET_OK; - } - ack = ntohl (msg->pid); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack); - - /* Is this a forward or backward ACK? */ - id = GNUNET_PEER_search (peer); - if (t->next_hop == id) - { - debug_fwd_ack++; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); - if (GNUNET_SCHEDULER_NO_TASK != t->next_fc.poll_task && - GMC_is_pid_bigger (ack, t->next_fc.last_ack_recv)) - { - GNUNET_SCHEDULER_cancel (t->next_fc.poll_task); - t->next_fc.poll_task = GNUNET_SCHEDULER_NO_TASK; - t->next_fc.poll_time = GNUNET_TIME_UNIT_SECONDS; - } - t->next_fc.last_ack_recv = ack; - peer_unlock_queue (t->next_hop); - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); - } - else if (t->prev_hop == id) - { - debug_bck_ack++; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n"); - if (GNUNET_SCHEDULER_NO_TASK != t->prev_fc.poll_task && - GMC_is_pid_bigger (ack, t->prev_fc.last_ack_recv)) - { - GNUNET_SCHEDULER_cancel (t->prev_fc.poll_task); - t->prev_fc.poll_task = GNUNET_SCHEDULER_NO_TASK; - t->prev_fc.poll_time = GNUNET_TIME_UNIT_SECONDS; - } - t->prev_fc.last_ack_recv = ack; - peer_unlock_queue (t->prev_hop); - tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); - } - else - GNUNET_break_op (0); - return GNUNET_OK; -} - - -/** - * Core handler for mesh network traffic point-to-point ack polls. - * - * @param cls closure - * @param message message - * @param peer peer identity this notification is about - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_Poll *msg; - struct MeshTunnel *t; - GNUNET_PEER_Id id; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an POLL packet from %s!\n", - GNUNET_i2s (peer)); - - msg = (struct GNUNET_MESH_Poll *) message; - - t = tunnel_get (&msg->oid, ntohl (msg->tid)); - - if (NULL == t) - { - /* TODO notify that we dont know this tunnel (whom)? */ - GNUNET_STATISTICS_update (stats, "# poll on unknown tunnel", 1, GNUNET_NO); - GNUNET_break_op (0); - return GNUNET_OK; - } - - /* Is this a forward or backward ACK? */ - id = GNUNET_PEER_search(peer); - if (t->next_hop == id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from FWD\n"); - tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL); - } - else if (t->prev_hop == id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from BCK\n"); - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL); - } - else - GNUNET_break (0); - - return GNUNET_OK; -} - - -/** - * Core handler for mesh keepalives. - * - * @param cls closure - * @param message message - * @param peer peer identity this notification is about - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - * - * TODO: Check who we got this from, to validate route. - */ -static int -handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_TunnelKeepAlive *msg; - struct MeshTunnel *t; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n", - GNUNET_i2s (peer)); - - msg = (struct GNUNET_MESH_TunnelKeepAlive *) message; - t = tunnel_get (&msg->oid, ntohl (msg->tid)); - - if (NULL == t) - { - /* TODO notify that we dont know that tunnel */ - GNUNET_STATISTICS_update (stats, "# keepalive on unknown tunnel", 1, - GNUNET_NO); - return GNUNET_OK; - } - - tunnel_reset_timeout (t); - - GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO); - send_prebuilt_message (message, t->next_hop, t); - return GNUNET_OK; - } - - - -/** - * Functions to handle messages from core - */ -static struct GNUNET_CORE_MessageHandler core_handlers[] = { - {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0}, - {&handle_mesh_path_broken, GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN, - sizeof (struct GNUNET_MESH_PathBroken)}, - {&handle_mesh_tunnel_destroy, GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY, - sizeof (struct GNUNET_MESH_TunnelDestroy)}, - {&handle_mesh_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0}, - {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE, - sizeof (struct GNUNET_MESH_TunnelKeepAlive)}, - {&handle_mesh_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0}, - {&handle_mesh_ack, GNUNET_MESSAGE_TYPE_MESH_ACK, - sizeof (struct GNUNET_MESH_ACK)}, - {&handle_mesh_poll, GNUNET_MESSAGE_TYPE_MESH_POLL, - sizeof (struct GNUNET_MESH_Poll)}, - {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK, - sizeof (struct GNUNET_MESH_PathACK)}, - {NULL, 0, 0} -}; - - - -/******************************************************************************/ -/**************** MESH LOCAL HANDLER HELPERS ***********************/ -/******************************************************************************/ - - -#if LATER -/** - * notify_client_connection_failure: notify a client that the connection to the - * requested remote peer is not possible (for instance, no route found) - * Function called when the socket is ready to queue more data. "buf" will be - * NULL and "size" zero if the socket was closed for writing in the meantime. - * - * @param cls closure - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf - */ -static size_t -notify_client_connection_failure (void *cls, size_t size, void *buf) -{ - int size_needed; - struct MeshPeerInfo *peer_info; - struct GNUNET_MESH_PeerControl *msg; - struct GNUNET_PeerIdentity id; - - if (0 == size && NULL == buf) - { - // TODO retry? cancel? - return 0; - } - - size_needed = sizeof (struct GNUNET_MESH_PeerControl); - peer_info = (struct MeshPeerInfo *) cls; - msg = (struct GNUNET_MESH_PeerControl *) buf; - msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED); -// msg->tunnel_id = htonl(peer_info->t->tid); - GNUNET_PEER_resolve (peer_info->id, &id); - memcpy (&msg->peer, &id, sizeof (struct GNUNET_PeerIdentity)); - - return size_needed; -} -#endif - - -/** - * Send keepalive packets for a tunnel. - * - * @param cls Closure (tunnel for which to send the keepalive). - * @param tc Notification context. - * - * FIXME: add a refresh reset in case of normal unicast traffic is doing the job - */ -static void -path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct MeshTunnel *t = cls; - struct GNUNET_MESH_TunnelKeepAlive *msg; - size_t size = sizeof (struct GNUNET_MESH_TunnelKeepAlive); - char cbuf[size]; - - t->maintenance_task = GNUNET_SCHEDULER_NO_TASK; - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) || - NULL == t->owner || 0 == t->local_tid) - { - return; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "sending keepalive for tunnel %d\n", t->id.tid); - - msg = (struct GNUNET_MESH_TunnelKeepAlive *) cbuf; - msg->header.size = htons (size); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE); - msg->oid = my_full_id; - msg->tid = htonl (t->id.tid); - send_prebuilt_message (&msg->header, t->next_hop, t); - - t->maintenance_task = - GNUNET_SCHEDULER_add_delayed (refresh_path_time, &path_refresh, t); -} - - -/** - * Function to process paths received for a new peer addition. The recorded - * paths form the initial tunnel, which can be optimized later. - * Called on each result obtained for the DHT search. - * - * @param cls closure - * @param exp when will this value expire - * @param key key of the result - * @param get_path path of the get request - * @param get_path_length lenght of get_path - * @param put_path path of the put request - * @param put_path_length length of the put_path - * @param type type of the result - * @param size number of bytes in data - * @param data pointer to the result data - */ -static void -dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, - const struct GNUNET_HashCode * key, - const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length, enum GNUNET_BLOCK_Type type, - size_t size, const void *data) -{ - struct MeshPeerInfo *peer = cls; - struct MeshPeerPath *p; - struct GNUNET_PeerIdentity pi; - int i; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got results from DHT!\n"); - GNUNET_PEER_resolve (peer->id, &pi); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", GNUNET_i2s (&pi)); - - p = path_build_from_dht (get_path, get_path_length, - put_path, put_path_length); - path_add_to_peers (p, GNUNET_NO); - path_destroy (p); - for (i = 0; i < peer->ntunnels; i++) - { - struct GNUNET_PeerIdentity id; - - GNUNET_PEER_resolve (peer->tunnels[i]->id.oid, &id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... tunnel %s:%X (%X / %X)\n", - GNUNET_i2s (&id), peer->tunnels[i]->id.tid, - peer->tunnels[i]->local_tid, - peer->tunnels[i]->local_tid_dest); - if (peer->tunnels[i]->state == MESH_TUNNEL_SEARCHING) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n"); - peer_connect (peer, peer->tunnels[i]); - } - } - - return; -} - - -/******************************************************************************/ -/********************* MESH LOCAL HANDLES **************************/ -/******************************************************************************/ - - -/** - * Handler for client disconnection - * - * @param cls closure - * @param client identification of the client; NULL - * for the last call when the server is destroyed - */ -static void -handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) -{ - struct MeshClient *c; - struct MeshClient *next; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client); - if (client == NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n"); - return; - } - - c = clients_head; - while (NULL != c) - { - if (c->handle != client) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " ... searching %p (%u)\n", - c->handle, c->id); - c = c->next; - continue; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u)\n", - c->id); - GNUNET_SERVER_client_drop (c->handle); - c->shutting_down = GNUNET_YES; - GNUNET_CONTAINER_multihashmap_iterate (c->own_tunnels, - &tunnel_destroy_iterator, c); - GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels, - &tunnel_destroy_iterator, c); - GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels); - GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels); - - if (NULL != c->ports) - GNUNET_CONTAINER_multihashmap_destroy (c->ports); - next = c->next; - GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " CLIENT FREE at %p\n", c); - GNUNET_free (c); - GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO); - c = next; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done!\n"); - return; -} - - -/** - * Handler for new clients - * - * @param cls closure - * @param client identification of the client - * @param message the actual message, which includes messages the client wants - */ -static void -handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_ClientConnect *cc_msg; - struct MeshClient *c; - unsigned int size; - uint32_t *p; - unsigned int i; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client); - - /* Check data sanity */ - size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect); - cc_msg = (struct GNUNET_MESH_ClientConnect *) message; - if (0 != (size % sizeof (uint32_t))) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - size /= sizeof (uint32_t); - - /* Create new client structure */ - c = GNUNET_malloc (sizeof (struct MeshClient)); - c->id = next_client_id++; /* overflow not important: just for debug */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client id %u\n", c->id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client has %u ports\n", size); - c->handle = client; - GNUNET_SERVER_client_keep (client); - if (size > 0) - { - uint32_t u32; - struct GNUNET_HashCode hc; - - p = (uint32_t *) &cc_msg[1]; - c->ports = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_NO); - for (i = 0; i < size; i++) - { - u32 = ntohl (p[i]); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " port: %u\n", u32); - GMC_hash32 (u32, &hc); - - /* store in client's hashmap */ - GNUNET_CONTAINER_multihashmap_put (c->ports, &hc, c, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); - /* store in global hashmap */ - /* FIXME only allow one client to have the port open, - * have a backup hashmap with waiting clients */ - GNUNET_CONTAINER_multihashmap_put (ports, &hc, c, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - } - } - - GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c); - c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); - c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); - GNUNET_SERVER_notification_context_add (nc, 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"); -} - - -/** - * Handler for requests of new tunnels - * - * @param cls Closure. - * @param client Identification of the client. - * @param message The actual message. - */ -static void -handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_TunnelMessage *t_msg; - struct MeshPeerInfo *peer_info; - struct MeshTunnel *t; - struct MeshClient *c; - MESH_TunnelNumber tid; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new tunnel requested\n"); - - /* Sanity check for client registration */ - if (NULL == (c = 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); - - /* Message size sanity check */ - if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size)) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - t_msg = (struct GNUNET_MESH_TunnelMessage *) message; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " towards %s\n", - GNUNET_i2s (&t_msg->peer)); - /* Sanity check for tunnel numbering */ - tid = ntohl (t_msg->tunnel_id); - if (0 == (tid & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI)) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - /* Sanity check for duplicate tunnel IDs */ - if (NULL != tunnel_get_by_local_id (c, tid)) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Create tunnel */ - while (NULL != tunnel_get_by_pi (myid, next_tid)) - next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; - t = tunnel_new (myid, next_tid, c, tid); - next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; - if (NULL == t) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - t->port = ntohl (t_msg->port); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s[%x]:%u (%x)\n", - GNUNET_i2s (&my_full_id), t->id.tid, t->port, t->local_tid); - - peer_info = peer_get (&t_msg->peer); - peer_info_add_tunnel (peer_info, t); - peer_connect (peer_info, t); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; -} - - -/** - * 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_log (GNUNET_ERROR_TYPE_DEBUG, - "Got a DESTROY TUNNEL from client!\n"); - - /* Sanity check for client registration */ - if (NULL == (c = 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); - - /* 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); - t = tunnel_get_by_local_id(c, tid); - if (NULL == t) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " tunnel %X not found\n", tid); - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Cleanup after the tunnel */ - client_delete_tunnel (c, t); - if (c == t->client) - { - t->client = NULL; - } - else if (c == t->owner) - { - peer_info_remove_tunnel (peer_get_short (t->dest), t); - t->owner = NULL; - } - - /* The tunnel will be destroyed when the last message is transmitted. */ - tunnel_destroy_empty (t); - - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; -} - - -/** - * Handler for requests of seeting tunnel's buffering policy. - * - * @param cls Closure (unused). - * @param client Identification of the client. - * @param message The actual message. - */ -static void -handle_local_tunnel_buffer (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_log (GNUNET_ERROR_TYPE_DEBUG, - "Got a BUFFER request from client!\n"); - - /* Sanity check for client registration */ - if (NULL == (c = 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); - - tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message; - - /* Retrieve tunnel */ - tid = ntohl (tunnel_msg->tunnel_id); - t = tunnel_get_by_local_id(c, tid); - if (NULL == t) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " tunnel %X not found\n", tid); - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - switch (ntohs(message->type)) - { - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER: - t->nobuffer = GNUNET_NO; - break; - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER: - t->nobuffer = GNUNET_YES; - break; - default: - GNUNET_break (0); - } - - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * Handler for client traffic directed to one peer - * - * @param cls closure - * @param client identification of the client - * @param message the actual message - */ -static void -handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - struct MeshClient *c; - struct MeshTunnel *t; - struct GNUNET_MESH_Data *data_msg; - MESH_TunnelNumber tid; - size_t size; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got a unicast request from a client!\n"); - - /* Sanity check for client registration */ - if (NULL == (c = 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); - - data_msg = (struct GNUNET_MESH_Data *) message; - - /* Sanity check for message size */ - size = ntohs (message->size); - if (sizeof (struct GNUNET_MESH_Data) + - sizeof (struct GNUNET_MessageHeader) > size) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Tunnel exists? */ - tid = ntohl (data_msg->tid); - t = tunnel_get_by_local_id (c, tid); - if (NULL == t) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Is it a local tunnel? Then, does client own the tunnel? */ - if (t->owner->handle != client) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* PID should be as expected: client<->service communication */ - if (ntohl (data_msg->pid) != t->prev_fc.last_pid_recv + 1) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Unicast PID, expected %u, got %u\n", - t->prev_fc.last_pid_recv + 1, ntohl (data_msg->pid)); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Ok, everything is correct, send the message - * (pretend we got it from a mesh peer) - */ - { - /* Work around const limitation */ - char buf[ntohs (message->size)] GNUNET_ALIGN; - struct GNUNET_MESH_Data *copy; - - copy = (struct GNUNET_MESH_Data *) buf; - memcpy (buf, data_msg, size); - copy->oid = my_full_id; - copy->tid = htonl (t->id.tid); - copy->ttl = htonl (default_ttl); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " calling generic handler...\n"); - handle_mesh_unicast (NULL, &my_full_id, ©->header); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - - return; -} - - -/** - * Handler for client traffic directed to the origin - * - * @param cls closure - * @param client identification of the client - * @param message the actual message - */ -static void -handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_Data *data_msg; - struct MeshFlowControl *fc; - struct MeshClient *c; - struct MeshTunnel *t; - MESH_TunnelNumber tid; - size_t size; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got a ToOrigin request from a client!\n"); - /* Sanity check for client registration */ - if (NULL == (c = 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); - - data_msg = (struct GNUNET_MESH_Data *) message; - - /* Sanity check for message size */ - size = ntohs (message->size); - if (sizeof (struct GNUNET_MESH_Data) + - sizeof (struct GNUNET_MessageHeader) > size) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Tunnel exists? */ - tid = ntohl (data_msg->tid); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tid); - if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - t = tunnel_get_by_local_id (c, tid); - if (NULL == t) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " for client %u.\n", c->id); - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* It should be sent by someone who has this as incoming tunnel. */ - if (t->client != c) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* PID should be as expected */ - fc = &t->next_fc; - if (ntohl (data_msg->pid) != fc->last_pid_recv + 1) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "To Origin PID, expected %u, got %u\n", - fc->last_pid_recv + 1, - ntohl (data_msg->pid)); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Ok, everything is correct, send the message - * (pretend we got it from a mesh peer) - */ - { - char buf[ntohs (message->size)] GNUNET_ALIGN; - struct GNUNET_MESH_Data *copy; - - /* Work around 'const' limitation */ - memcpy (buf, data_msg, size); - copy = (struct GNUNET_MESH_Data *) buf; - GNUNET_PEER_resolve (t->id.oid, ©->oid); - copy->tid = htonl (t->id.tid); - copy->ttl = htonl (default_ttl); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " calling generic handler...\n"); - handle_mesh_to_orig (NULL, &my_full_id, ©->header); - } - GNUNET_SERVER_receive_done (client, GNUNET_OK); - - return; -} - - -/** - * Handler for client's ACKs for payload traffic. - * - * @param cls Closure (unused). - * @param client Identification of the client. - * @param message The actual message. - */ -static void -handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_LocalAck *msg; - struct MeshTunnel *t; - struct MeshClient *c; - MESH_TunnelNumber tid; - uint32_t ack; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n"); - /* Sanity check for client registration */ - if (NULL == (c = 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); - - msg = (struct GNUNET_MESH_LocalAck *) message; - - /* Tunnel exists? */ - tid = ntohl (msg->tunnel_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tid); - t = tunnel_get_by_local_id (c, tid); - if (NULL == t) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " for client %u.\n", c->id); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - ack = ntohl (msg->ack); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack); - - /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */ - if (t->owner == c) - { - /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */ - t->prev_fc.last_ack_recv = ack; - tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); - } - else - { - /* The client doesn't own the tunnel, this ACK is for FWD traffic. */ - t->next_fc.last_ack_recv = ack; - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); - } - - GNUNET_SERVER_receive_done (client, GNUNET_OK); - - return; -} - - - -/** - * Iterator over all tunnels to send a monitoring client info about each tunnel. - * - * @param cls Closure (client handle). - * @param key Key (hashed tunnel ID, unused). - * @param value Tunnel info. - * - * @return GNUNET_YES, to keep iterating. - */ -static int -monitor_all_tunnels_iterator (void *cls, - const struct GNUNET_HashCode * key, - void *value) -{ - struct GNUNET_SERVER_Client *client = cls; - struct MeshTunnel *t = value; - struct GNUNET_MESH_LocalMonitor *msg; - - msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor)); - GNUNET_PEER_resolve(t->id.oid, &msg->owner); - msg->tunnel_id = htonl (t->id.tid); - msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor)); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS); - GNUNET_PEER_resolve (t->dest, &msg->destination); - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "* sending info about tunnel %s [%u]\n", - GNUNET_i2s (&msg->owner), t->id.tid); - - GNUNET_SERVER_notification_context_unicast (nc, client, - &msg->header, GNUNET_NO); - return GNUNET_YES; -} - - -/** - * Handler for client's MONITOR request. - * - * @param cls Closure (unused). - * @param client Identification of the client. - * @param message The actual message. - */ -static void -handle_local_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - struct MeshClient *c; - - /* Sanity check for client registration */ - if (NULL == (c = client_get (client))) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - GNUNET_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, - "Get tunnels request from client %u completed\n", - c->id); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * Handler for client's MONITOR_TUNNEL request. - * - * @param cls Closure (unused). - * @param client Identification of the client. - * @param message The actual message. - */ -static void -handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_MESH_LocalMonitor *msg; - struct GNUNET_MESH_LocalMonitor *resp; - struct MeshClient *c; - struct MeshTunnel *t; - - /* Sanity check for client registration */ - if (NULL == (c = client_get (client))) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - msg = (struct GNUNET_MESH_LocalMonitor *) message; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Received tunnel info request from client %u for tunnel %s[%X]\n", - c->id, - &msg->owner, - ntohl (msg->tunnel_id)); - t = tunnel_get (&msg->owner, ntohl (msg->tunnel_id)); - if (NULL == t) - { - /* We don't know the tunnel FIXME */ - struct GNUNET_MESH_LocalMonitor warn; - - warn = *msg; - GNUNET_SERVER_notification_context_unicast (nc, client, - &warn.header, - GNUNET_NO); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - - /* Initialize context */ - resp = GNUNET_malloc (sizeof (struct GNUNET_MESH_LocalMonitor)); - *resp = *msg; - GNUNET_PEER_resolve (t->dest, &resp->destination); - resp->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor)); - GNUNET_SERVER_notification_context_unicast (nc, c->handle, - &resp->header, GNUNET_NO); - GNUNET_free (resp); - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Monitor tunnel request from client %u completed\n", - c->id); - GNUNET_SERVER_receive_done (client, GNUNET_OK); -} - - -/** - * Functions to handle messages from clients - */ -static struct GNUNET_SERVER_MessageHandler client_handlers[] = { - {&handle_local_new_client, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0}, - {&handle_local_tunnel_create, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE, - sizeof (struct GNUNET_MESH_TunnelMessage)}, - {&handle_local_tunnel_destroy, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY, - sizeof (struct GNUNET_MESH_TunnelMessage)}, - {&handle_local_tunnel_buffer, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER, - sizeof (struct GNUNET_MESH_TunnelMessage)}, - {&handle_local_tunnel_buffer, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER, - sizeof (struct GNUNET_MESH_TunnelMessage)}, - {&handle_local_unicast, NULL, - GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0}, - {&handle_local_to_origin, NULL, - GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0}, - {&handle_local_ack, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK, - sizeof (struct GNUNET_MESH_LocalAck)}, - {&handle_local_get_tunnels, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS, - sizeof (struct GNUNET_MessageHeader)}, - {&handle_local_show_tunnel, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL, - sizeof (struct GNUNET_MESH_LocalMonitor)}, - {NULL, NULL, 0, 0} -}; - - -/** - * Method called whenever a given peer connects. - * - * @param cls closure - * @param peer peer identity this notification is about - */ -static void -core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) -{ - struct MeshPeerInfo *peer_info; - struct MeshPeerPath *path; - - DEBUG_CONN ("Peer connected\n"); - DEBUG_CONN (" %s\n", GNUNET_i2s (&my_full_id)); - peer_info = peer_get (peer); - if (myid == peer_info->id) - { - DEBUG_CONN (" (self)\n"); - path = path_new (1); - } - else - { - DEBUG_CONN (" %s\n", GNUNET_i2s (peer)); - path = path_new (2); - path->peers[1] = peer_info->id; - GNUNET_PEER_change_rc (peer_info->id, 1); - GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO); - } - path->peers[0] = myid; - GNUNET_PEER_change_rc (myid, 1); - peer_info_add_path (peer_info, path, GNUNET_YES); - return; -} - - -/** - * Method called whenever a peer disconnects. - * - * @param cls closure - * @param peer peer identity this notification is about - */ -static void -core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) -{ - struct MeshPeerInfo *pi; - struct MeshPeerQueue *q; - struct MeshPeerQueue *n; - - DEBUG_CONN ("Peer disconnected\n"); - pi = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey); - if (NULL == pi) - { - GNUNET_break (0); - return; - } - q = pi->queue_head; - while (NULL != q) - { - n = q->next; - /* TODO try to reroute this traffic instead */ - queue_destroy(q, GNUNET_YES); - q = n; - } - if (NULL != pi->core_transmit) - { - GNUNET_CORE_notify_transmit_ready_cancel(pi->core_transmit); - pi->core_transmit = NULL; - } - peer_remove_path (pi, pi->id, myid); - if (myid == pi->id) - { - DEBUG_CONN (" (self)\n"); - } - GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO); - return; -} - - -/** - * Install server (service) handlers and start listening to clients. - */ -static void -server_init (void) -{ - GNUNET_SERVER_add_handlers (server_handle, client_handlers); - GNUNET_SERVER_disconnect_notify (server_handle, - &handle_local_client_disconnect, NULL); - nc = GNUNET_SERVER_notification_context_create (server_handle, 1); - - clients_head = NULL; - clients_tail = NULL; - next_client_id = 0; - GNUNET_SERVER_resume (server_handle); -} - - -/** - * To be called on core init/fail. - * - * @param cls Closure (config) - * @param server handle to the server for this service - * @param identity the public identity of this peer - */ -static void -core_init (void *cls, struct GNUNET_CORE_Handle *server, - const struct GNUNET_PeerIdentity *identity) -{ - const struct GNUNET_CONFIGURATION_Handle *c = cls; - static int i = 0; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n"); - GNUNET_break (core_handle == server); - if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)) || - NULL == server) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n")); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - " core id %s\n", - GNUNET_i2s (identity)); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - " my id %s\n", - GNUNET_i2s (&my_full_id)); - GNUNET_CORE_disconnect (core_handle); - core_handle = GNUNET_CORE_connect (c, /* Main configuration */ - NULL, /* Closure passed to MESH functions */ - &core_init, /* Call core_init once connected */ - &core_connect, /* Handle connects */ - &core_disconnect, /* remove peers on disconnects */ - NULL, /* Don't notify about all incoming messages */ - GNUNET_NO, /* For header only in notification */ - NULL, /* Don't notify about all outbound messages */ - GNUNET_NO, /* For header-only out notification */ - core_handlers); /* Register these handlers */ - if (10 < i++) - GNUNET_abort(); - } - server_init (); - return; -} - - -/******************************************************************************/ -/************************ MAIN FUNCTIONS ****************************/ -/******************************************************************************/ - -/** - * Iterator over tunnel hash map entries to destroy the tunnel during shutdown. - * - * @param cls closure - * @param key current key code - * @param value value in the hash map - * @return GNUNET_YES if we should continue to iterate, - * GNUNET_NO if not. - */ -static int -shutdown_tunnel (void *cls, const struct GNUNET_HashCode * key, void *value) -{ - struct MeshTunnel *t = value; - - tunnel_destroy (t); - return GNUNET_YES; -} - -/** - * Iterator over peer hash map entries to destroy the tunnel during shutdown. - * - * @param cls closure - * @param key current key code - * @param value value in the hash map - * @return GNUNET_YES if we should continue to iterate, - * GNUNET_NO if not. - */ -static int -shutdown_peer (void *cls, const struct GNUNET_HashCode * key, void *value) -{ - struct MeshPeerInfo *p = value; - struct MeshPeerQueue *q; - struct MeshPeerQueue *n; - - q = p->queue_head; - while (NULL != q) - { - n = q->next; - if (q->peer == p) - { - queue_destroy(q, GNUNET_YES); - } - q = n; - } - peer_info_destroy (p); - return GNUNET_YES; -} - - -/** - * Task run during shutdown. - * - * @param cls unused - * @param tc unused - */ -static void -shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n"); - - if (core_handle != NULL) - { - GNUNET_CORE_disconnect (core_handle); - core_handle = NULL; - } - if (NULL != keygen) - { - GNUNET_CRYPTO_ecc_key_create_stop (keygen); - keygen = NULL; - } - GNUNET_CONTAINER_multihashmap_iterate (tunnels, &shutdown_tunnel, NULL); - GNUNET_CONTAINER_multihashmap_iterate (peers, &shutdown_peer, NULL); - if (dht_handle != NULL) - { - GNUNET_DHT_disconnect (dht_handle); - dht_handle = NULL; - } - if (nc != NULL) - { - GNUNET_SERVER_notification_context_destroy (nc); - nc = NULL; - } - if (GNUNET_SCHEDULER_NO_TASK != announce_id_task) - { - GNUNET_SCHEDULER_cancel (announce_id_task); - announce_id_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); -} - - -/** - * Callback for hostkey read/generation. - * - * @param cls Closure (Configuration handle). - * @param pk The ECC private key. - * @param emsg Error message, if any. - */ -static void -key_generation_cb (void *cls, - struct GNUNET_CRYPTO_EccPrivateKey *pk, - const char *emsg) -{ - const struct GNUNET_CONFIGURATION_Handle *c = cls; - - keygen = NULL; - if (NULL == pk) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Could not access hostkey: %s. Exiting.\n"), - emsg); - GNUNET_SCHEDULER_shutdown (); - return; - } - my_private_key = pk; - GNUNET_CRYPTO_ecc_key_get_public (my_private_key, &my_public_key); - GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), - &my_full_id.hashPubKey); - myid = GNUNET_PEER_intern (&my_full_id); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Mesh for peer [%s] starting\n", - GNUNET_i2s(&my_full_id)); - - core_handle = GNUNET_CORE_connect (c, /* Main configuration */ - NULL, /* Closure passed to MESH functions */ - &core_init, /* Call core_init once connected */ - &core_connect, /* Handle connects */ - &core_disconnect, /* remove peers on disconnects */ - NULL, /* Don't notify about all incoming messages */ - GNUNET_NO, /* For header only in notification */ - NULL, /* Don't notify about all outbound messages */ - GNUNET_NO, /* For header-only out notification */ - core_handlers); /* Register these handlers */ - if (core_handle == NULL) - { - GNUNET_break (0); - GNUNET_SCHEDULER_shutdown (); - return; - } - - next_tid = 0; - next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; - - announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n"); -} - - -/** - * Process mesh requests. - * - * @param cls closure - * @param server the initialized server - * @param c configuration to use - */ -static void -run (void *cls, struct GNUNET_SERVER_Handle *server, - const struct GNUNET_CONFIGURATION_Handle *c) -{ - char *keyfile; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n"); - server_handle = server; - GNUNET_SERVER_suspend (server_handle); - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (c, "PEER", "PRIVATE_KEY", - &keyfile)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("%s service is lacking key configuration settings (%s). Exiting.\n"), - "mesh", "peer/privatekey"); - GNUNET_SCHEDULER_shutdown (); - return; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_PATH_TIME", - &refresh_path_time)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("%s service is lacking key configuration settings (%s). Exiting.\n"), - "mesh", "refresh path time"); - GNUNET_SCHEDULER_shutdown (); - return; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME", - &id_announce_time)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("%s service is lacking key configuration settings (%s). Exiting.\n"), - "mesh", "id announce time"); - GNUNET_SCHEDULER_shutdown (); - return; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (c, "MESH", "CONNECT_TIMEOUT", - &connect_timeout)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("%s service is lacking key configuration settings (%s). Exiting.\n"), - "mesh", "connect timeout"); - GNUNET_SCHEDULER_shutdown (); - return; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE", - &max_msgs_queue)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("%s service is lacking key configuration settings (%s). Exiting.\n"), - "mesh", "max msgs queue"); - GNUNET_SCHEDULER_shutdown (); - return; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_TUNNELS", - &max_tunnels)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("%s service is lacking key configuration settings (%s). Exiting.\n"), - "mesh", "max tunnels"); - GNUNET_SCHEDULER_shutdown (); - return; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DEFAULT_TTL", - &default_ttl)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("%s service is lacking key configuration settings (%s). Using default (%u).\n"), - "mesh", "default ttl", 64); - default_ttl = 64; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS", - &max_peers)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("%s service is lacking key configuration settings (%s). Using default (%u).\n"), - "mesh", "max peers", 1000); - max_peers = 1000; - } - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DHT_REPLICATION_LEVEL", - &dht_replication_level)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("%s service is lacking key configuration settings (%s). Using default (%u).\n"), - "mesh", "dht replication level", 3); - dht_replication_level = 3; - } - - tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); - incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); - peers = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); - ports = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); - - dht_handle = GNUNET_DHT_connect (c, 64); - if (NULL == dht_handle) - { - GNUNET_break (0); - } - stats = GNUNET_STATISTICS_create ("mesh", c); - - /* Scheduled the task to clean up when shutdown is called */ - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, - NULL); - keygen = GNUNET_CRYPTO_ecc_key_create_start (keyfile, - &key_generation_cb, - (void *) c); - GNUNET_free (keyfile); -} - - -/** - * The main function for the mesh service. - * - * @param argc number of arguments from the command line - * @param argv command line arguments - * @return 0 ok, 1 on error - */ -int -main (int argc, char *const *argv) -{ - int ret; - int r; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main()\n"); - r = GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run, - NULL); - ret = (GNUNET_OK == r) ? 0 : 1; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main() END\n"); - - INTERVAL_SHOW; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Mesh for peer [%s] FWD ACKs %u, BCK ACKs %u\n", - GNUNET_i2s(&my_full_id), debug_fwd_ack, debug_bck_ack); - - return ret; -} diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index 0ba69882fb..622d399b48 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2001-2012 Christian Grothoff (and other contributing authors) + (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -23,40 +23,25 @@ * @brief GNUnet MESH service * @author Bartlomiej Polot * - * STRUCTURE: - * - DATA STRUCTURES - * - GLOBAL VARIABLES - * - GENERAL HELPERS - * - PERIODIC FUNCTIONS - * - MESH NETWORK HANDLER HELPERS - * - MESH NETWORK HANDLES - * - MESH LOCAL HANDLER HELPERS - * - MESH LOCAL HANDLES - * - MAIN FUNCTIONS (main & run) - * * TODO: - * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message! - * - partial disconnect reporting -- same as error reporting? - * - add ping message * - relay corking down to core - * - set ttl relative to tree depth - * - Add data ACK count in path ACK - * - Make common GNUNET_MESH_Data header for unicast, to_orig, multicast + * - set ttl relative to path length + * - add signatures + * - add encryption + * - keep queues until receiving ACK * TODO END */ #include "platform.h" #include "mesh.h" #include "mesh_protocol.h" -#include "mesh_tunnel_tree.h" +#include "mesh_path.h" #include "block_mesh.h" #include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" -#include "gnunet_regex_service.h" #define MESH_BLOOM_SIZE 128 -#define MESH_DEBUG_REGEX GNUNET_YES #define MESH_DEBUG_DHT GNUNET_NO #define MESH_DEBUG_CONNECTION GNUNET_NO #define MESH_DEBUG_TIMING __LINUX__ && GNUNET_NO @@ -65,7 +50,6 @@ GNUNET_TIME_UNIT_MINUTES,\ 10) - #if MESH_DEBUG_CONNECTION #define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) #else @@ -78,12 +62,6 @@ #define DEBUG_DHT(...) #endif -#if MESH_DEBUG_REGEX -#define DEBUG_REGEX(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) -#else -#define DEBUG_REGEX(...) -#endif - #if MESH_DEBUG_TIMING #include <time.h> double __sum; @@ -118,28 +96,6 @@ struct MeshClient; /** - * Struct representing a piece of data being sent to other peers - */ -struct MeshData -{ - /** Tunnel it belongs to. */ - struct MeshTunnel *t; - - /** How many remaining neighbors still hav't got it. */ - unsigned int reference_counter; - - /** How many remaining neighbors we need to send this to. */ - unsigned int total_out; - - /** Size of the data. */ - size_t data_len; - - /** Data itself */ - void *data; -}; - - -/** * Struct containing info about a queued transmission to this peer */ struct MeshPeerQueue @@ -182,99 +138,6 @@ struct MeshPeerQueue /** - * Struct to store regex information announced by clients. - */ -struct MeshRegexDescriptor -{ - /** - * Regular expression itself. - */ - char *regex; - - /** - * How many characters per edge can we squeeze? - */ - uint16_t compression; - - /** - * Handle to announce the regex. - */ - struct GNUNET_REGEX_Announcement *h; -}; - - -/** - * Struct to keep information of searches of services described by a regex - * using a user-provided string service description. - */ -struct MeshRegexSearchInfo -{ - /** - * Which tunnel is this for - */ - struct MeshTunnel *t; - - /** - * User provided description of the searched service. - */ - char *description; - - /** - * Regex search handle. - */ - struct GNUNET_REGEX_Search *search_handle; - - /** - * Peer that is connecting via connect_by_string. When connected, free ctx. - */ - GNUNET_PEER_Id peer; - - /** - * Other peers that are found but not yet being connected to. - */ - GNUNET_PEER_Id *peers; - - /** - * Number of elements in peers. - */ - unsigned int n_peers; - - /** - * Next peer to try to connect to. - */ - unsigned int i_peer; - - /** - * Timeout for a connect attempt. - * When reached, try to connect to a different peer, if any. If not, - * try the same peer again. - */ - GNUNET_SCHEDULER_TaskIdentifier timeout; - -}; - - -/** - * Struct containing all info possibly needed to build a package when called - * back by core. - */ -struct MeshTransmissionDescriptor -{ - /** ID of the tunnel this packet travels in */ - struct MESH_TunnelID *origin; - - /** Who was this message being sent to */ - struct MeshPeerInfo *peer; - - /** Ultimate destination of the packet */ - GNUNET_PEER_Id destination; - - /** Data descriptor */ - struct MeshData* mesh_data; -}; - - -/** * Struct containing all information regarding a given peer */ struct MeshPeerInfo @@ -290,11 +153,6 @@ struct MeshPeerInfo struct GNUNET_TIME_Absolute last_contact; /** - * Task handler for delayed connect task; - */ - GNUNET_SCHEDULER_TaskIdentifier connect_task; - - /** * Number of attempts to reconnect so far */ int n_reconnect_attempts; @@ -315,13 +173,8 @@ struct MeshPeerInfo struct GNUNET_DHT_GetHandle *dhtget; /** - * Closure given to the DHT GET - */ - struct MeshPathInfo *dhtgetcls; - - /** - * Array of tunnels this peer participates in - * (most probably a small amount, therefore not a hashmap) + * Array of tunnels this peer is the target of. + * Most probably a small amount, therefore not a hashmap. * When the path to the peer changes, notify these tunnels to let them * re-adjust their path trees. */ @@ -348,13 +201,66 @@ struct MeshPeerInfo unsigned int queue_n; /** - * Handle to for queued transmissions + * Handle for queued transmissions */ struct GNUNET_CORE_TransmitHandle *core_transmit; }; /** + * Struct to encapsulate all the Flow Control information to a peer in the + * context of a tunnel: Same peer in different tunnels will have independent + * flow control structures, allowing to choke/free tunnels according to its + * own criteria. + */ +struct MeshFlowControl +{ + /** + * ID of the last packet sent towards the peer. + */ + uint32_t last_pid_sent; + + /** + * ID of the last packet received from the peer. + */ + uint32_t last_pid_recv; + + /** + * Last ACK sent to the peer (peer can't send more than this PID). + */ + uint32_t last_ack_sent; + + /** + * Last ACK sent towards the origin (for traffic towards leaf node). + */ + uint32_t last_ack_recv; + + /** + * How many payload messages are in the queue towards this peer. + */ + uint32_t queue_n; + + /** + * Task to poll the peer in case of a lost ACK causes stall. + */ + GNUNET_SCHEDULER_TaskIdentifier poll_task; + + /** + * How frequently to poll for ACKs. + */ + struct GNUNET_TIME_Relative poll_time; + + /** + * On which tunnel to poll. + * Using an explicit poll_ctx would not help memory wise, + * since the allocated context would have to be stored in the + * fc struct in order to free it upon cancelling poll_task. + */ + struct MeshTunnel *t; +}; + + +/** * Globally unique tunnel identification (owner + number) * DO NOT USE OVER THE NETWORK */ @@ -388,6 +294,16 @@ struct MeshTunnel struct MESH_TunnelID id; /** + * Port of the tunnel. + */ + uint32_t port; + + /** + * State of the tunnel. + */ + enum MeshTunnelState state; + + /** * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 ) */ MESH_TunnelNumber local_tid; @@ -400,77 +316,19 @@ struct MeshTunnel MESH_TunnelNumber local_tid_dest; /** - * Is the speed on the tunnel limited to the slowest peer? - */ - int speed_min; - - /** * Is the tunnel bufferless (minimum latency)? */ int nobuffer; /** - * Packet ID of the last fwd packet seen (sent/retransmitted/received). - */ - uint32_t fwd_pid; - - /** - * Packet ID of the last bck packet sent (unique counter per hop). - */ - uint32_t bck_pid; - - /** - * SKIP value for this tunnel. - */ - uint32_t skip; - - /** * Force sending ACK? Flag to allow duplicate ACK on POLL. */ int force_ack; /** - * MeshTunnelChildInfo of all children, indexed by GNUNET_PEER_Id. - * Contains the Flow Control info: FWD ACK value received, - * last BCK ACK sent, PID and SKIP values. - */ - struct GNUNET_CONTAINER_MultiHashMap *children_fc; - - /** - * Last ACK sent towards the origin (for traffic towards leaf node). - */ - uint32_t last_fwd_ack; - - /** - * BCK ACK value received from the hop towards the owner of the tunnel, - * (previous node / owner): up to what message PID can we sent back to him. - */ - uint32_t bck_ack; - - /** - * How many messages are in the forward queue (towards leaves). - */ - unsigned int fwd_queue_n; - - /** * How many messages do we accept in the forward queue. */ - unsigned int fwd_queue_max; - - /** - * How many messages are in the backward queue (towards origin). - */ - unsigned int bck_queue_n; - - /** - * How many messages do we accept in the backward queue. - */ - unsigned int bck_queue_max; - - /** - * Task to poll peer in case of a stall. - */ - GNUNET_SCHEDULER_TaskIdentifier fc_poll_bck; + unsigned int queue_max; /** * Last time the tunnel was used @@ -478,93 +336,50 @@ struct MeshTunnel struct GNUNET_TIME_Absolute timestamp; /** - * Peers in the tunnel, indexed by PeerIdentity -> (MeshPeerInfo) - * containing peers added by id or by type, not intermediate peers. - */ - struct GNUNET_CONTAINER_MultiHashMap *peers; - - /** - * Number of peers that are connected and potentially ready to receive data - */ - unsigned int peers_ready; - - /** - * Client owner of the tunnel, if any - */ - struct MeshClient *owner; - - /** - * Clients that have been informed about and want to stay in the tunnel. - */ - struct MeshClient **clients; - - /** - * Flow control info for each client. + * Destination of the tunnel. */ - struct MeshTunnelClientInfo *clients_fc; - - /** - * Number of elements in clients/clients_fc - */ - unsigned int nclients; - - /** - * Clients that have been informed but requested to leave the tunnel. - */ - struct MeshClient **ignore; + GNUNET_PEER_Id dest; /** - * Number of elements in clients + * Next hop in the tunnel. If 0, @c client must be set. */ - unsigned int nignore; + GNUNET_PEER_Id next_hop; /** - * Blacklisted peers + * Previous hop in the tunnel. If 0, @c owner must be set. */ - GNUNET_PEER_Id *blacklisted; + GNUNET_PEER_Id prev_hop; /** - * Number of elements in blacklisted + * Flow control information about @c next_hop or @c client. */ - unsigned int nblacklisted; + struct MeshFlowControl next_fc; /** - * Bloomfilter (for peer identities) to stop circular routes + * Flow control information about @c prev_hop or @c owner. */ - char bloomfilter[MESH_BLOOM_SIZE]; - - /** - * Tunnel paths - */ - struct MeshTunnelTree *tree; - - /** - * Application type we are looking for in this tunnel - */ - GNUNET_MESH_ApplicationType type; + struct MeshFlowControl prev_fc; /** - * Used to search peers offering a service + * Client owner of the tunnel, if any */ - struct GNUNET_DHT_GetHandle *dht_get_type; + struct MeshClient *owner; /** - * Handle for the regex search for a connect_by_string + * Client destination of the tunnel, if any. */ - struct MeshRegexSearchInfo *regex_search; + struct MeshClient *client; /** - * Task to keep the used paths alive + * Task to keep the used paths alive at the owner, + * time tunnel out on all the other peers. */ - GNUNET_SCHEDULER_TaskIdentifier path_refresh_task; + GNUNET_SCHEDULER_TaskIdentifier maintenance_task; /** - * Task to destroy the tunnel after timeout - * - * FIXME: merge the two? a tunnel will have either - * a path refresh OR a timeout, never both! + * Path being used for the tunnel. */ - GNUNET_SCHEDULER_TaskIdentifier timeout_task; + struct MeshPeerPath *path; /** * Flag to signal the destruction of the tunnel. @@ -577,163 +392,13 @@ struct MeshTunnel * Total messages pending for this tunnels, payload or not. */ unsigned int pending_messages; - - /** - * If the tunnel is empty, destoy it. - */ - GNUNET_SCHEDULER_TaskIdentifier delayed_destroy; -}; - - -/** - * Info about a child node in a tunnel, needed to perform flow control. - */ -struct MeshTunnelChildInfo -{ - /** - * ID of the child node. - */ - GNUNET_PEER_Id id; - - /** - * SKIP value. - */ - uint32_t skip; - - /** - * Last sent PID. - */ - uint32_t fwd_pid; - - /** - * Last received PID. - */ - uint32_t bck_pid; - - /** - * Maximum PID allowed (FWD ACK received). - */ - uint32_t fwd_ack; - - /** - * Last ACK sent to that child (BCK ACK). - */ - uint32_t bck_ack; - - /** - * Circular buffer pointing to MeshPeerQueue elements for all - * payload traffic going to this child. - * Size determined by the tunnel queue size (@c t->fwd_queue_max). - */ - struct MeshPeerQueue **send_buffer; - - /** - * Index of the oldest element in the send_buffer. - */ - unsigned int send_buffer_start; - - /** - * How many elements are already in the buffer. - */ - unsigned int send_buffer_n; - - /** - * Tunnel this info is about - */ - struct MeshTunnel *t; - - /** - * Task to poll peer in case of a stall. - */ - GNUNET_SCHEDULER_TaskIdentifier fc_poll; - - /** - * Time to use for next polling call. - */ - struct GNUNET_TIME_Relative fc_poll_time; -}; - - -/** - * Info about a leaf client of a tunnel, needed to perform flow control. - */ -struct MeshTunnelClientInfo -{ - /** - * PID of the last packet sent to the client (FWD). - */ - uint32_t fwd_pid; - - /** - * PID of the last packet received from the client (BCK). - */ - uint32_t bck_pid; - - /** - * Maximum PID allowed (FWD ACK received). - */ - uint32_t fwd_ack; - - /** - * Last ACK sent to that child (BCK ACK). - */ - uint32_t bck_ack; -}; - - - -/** - * Info collected during iteration of child nodes in order to get the ACK value - * for a tunnel. - */ -struct MeshTunnelChildIteratorContext -{ - /** - * Tunnel whose info is being collected. - */ - struct MeshTunnel *t; - - /** - * Is this context initialized? Is the value in max_child_ack valid? - */ - int init; - - /** - * Maximum child ACK so far. - */ - uint32_t max_child_ack; - - /** - * Number of children nodes - */ - unsigned int nchildren; -}; - - -/** - * Info needed to work with tunnel paths and peers - */ -struct MeshPathInfo -{ - /** - * Tunnel - */ - struct MeshTunnel *t; - - /** - * Neighbouring peer to whom we send the packet to - */ - struct MeshPeerInfo *peer; - - /** - * Path itself - */ - struct MeshPeerPath *path; }; /** * Struct containing information about a client of the service + * + * TODO: add a list of 'waiting' ports */ struct MeshClient { @@ -757,24 +422,16 @@ struct MeshClient */ struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels; - /** - * Tunnels this client has rejected, indexed by incoming local id - */ - struct GNUNET_CONTAINER_MultiHashMap *ignore_tunnels; /** * Handle to communicate with the client */ struct GNUNET_SERVER_Client *handle; /** - * Applications that this client has claimed to provide: H(app) = app. - */ - struct GNUNET_CONTAINER_MultiHashMap *apps; - - /** - * Messages that this client has declared interest in + * Ports that this client has declared interest in. + * Indexed by a GMC_hash32 (type), contains *Client. */ - struct GNUNET_CONTAINER_MultiHashMap *types; + struct GNUNET_CONTAINER_MultiHashMap *ports; /** * Whether the client is active or shutting down (don't send confirmations @@ -786,26 +443,6 @@ struct MeshClient * ID of the client, mainly for debug messages */ unsigned int id; - - /** - * Regular expressions describing the services offered by this client. - */ - struct MeshRegexDescriptor *regexes; // FIXME regex add timeout? API to remove a regex? - - /** - * Number of regular expressions in regexes. - */ - unsigned int n_regex; - - /** - * Task to refresh all regular expresions in the DHT. - */ - GNUNET_SCHEDULER_TaskIdentifier regex_announce_task; - - /** - * Tmp store for partially retrieved regex. - */ - char *partial_regex; }; @@ -835,6 +472,7 @@ mesh_debug (void *cls, int success) } #endif +/* FIXME */ unsigned int debug_fwd_ack; unsigned int debug_bck_ack; @@ -852,11 +490,6 @@ unsigned int debug_bck_ack; static struct GNUNET_TIME_Relative refresh_path_time; /** - * How often to PUT local application numbers in the DHT. - */ -static struct GNUNET_TIME_Relative app_announce_time; - -/** * How often to PUT own ID in the DHT. */ static struct GNUNET_TIME_Relative id_announce_time; @@ -904,7 +537,7 @@ static struct GNUNET_CRYPTO_EccKeyGenerationContext *keygen; /** * DLL with all the clients, head. */ -static struct MeshClient *clients; +static struct MeshClient *clients_head; /** * DLL with all the clients, tail. @@ -932,10 +565,10 @@ static struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels; */ static struct GNUNET_CONTAINER_MultiHashMap *peers; -/** - * Configuration handle +/* + * Handle to communicate with transport */ -static const struct GNUNET_CONFIGURATION_Handle *cfg; +// static struct GNUNET_TRANSPORT_Handle *transport_handle; /** * Handle to communicate with core. @@ -993,19 +626,9 @@ static MESH_TunnelNumber next_tid; static MESH_TunnelNumber next_local_tid; /** - * All application types provided by this peer: H(app) = *Client. - */ -static struct GNUNET_CONTAINER_MultiHashMap *applications; - -/** - * All message types clients of this peer are interested in. + * All ports clients of this peer have opened. */ -static struct GNUNET_CONTAINER_MultiHashMap *types; - -/** - * Task to periodically announce provided applications. - */ -GNUNET_SCHEDULER_TaskIdentifier announce_applications_task; +static struct GNUNET_CONTAINER_MultiHashMap *ports; /** * Task to periodically announce itself in the network. @@ -1046,39 +669,26 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, /** * Retrieve the MeshPeerInfo stucture associated with the peer, create one - * and insert it in the appropiate structures if the peer is not known yet. + * and insert it in the appropriate structures if the peer is not known yet. * * @param peer Full identity of the peer. * * @return Existing or newly created peer info. */ static struct MeshPeerInfo * -peer_info_get (const struct GNUNET_PeerIdentity *peer); +peer_get (const struct GNUNET_PeerIdentity *peer); /** * Retrieve the MeshPeerInfo stucture associated with the peer, create one - * and insert it in the appropiate structures if the peer is not known yet. + * and insert it in the appropriate structures if the peer is not known yet. * * @param peer Short identity of the peer. * * @return Existing or newly created peer info. */ static struct MeshPeerInfo * -peer_info_get_short (const GNUNET_PEER_Id peer); - - -/** - * Try to establish a new connection to this peer. - * Use the best path for the given tunnel. - * If the peer doesn't have any path to it yet, try to get one. - * If the peer already has some path, send a CREATE PATH towards it. - * - * @param peer PeerInfo of the peer. - * @param t Tunnel for which to create the path, if possible. - */ -static void -peer_info_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t); +peer_get_short (const GNUNET_PEER_Id peer); /** @@ -1104,30 +714,6 @@ static void path_add_to_peers (struct MeshPeerPath *p, int confirmed); -/** - * Add a peer to a tunnel, accomodating paths accordingly and initializing all - * needed rescources. - * If peer already exists, reevaluate shortest path and change if different. - * - * @param t Tunnel we want to add a new peer to - * @param peer PeerInfo of the peer being added - * - */ -static void -tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer); - - -/** - * Removes an explicit path from a tunnel, freeing all intermediate nodes - * that are no longer needed, as well as nodes of no longer reachable peers. - * The tunnel itself is also destoyed if results in a remote empty tunnel. - * - * @param t Tunnel from which to remove the path. - * @param peer Short id of the peer which should be removed. - */ -static void -tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer); - /** * Search for a tunnel by global ID using full PeerIdentities. @@ -1142,15 +728,6 @@ tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid); /** - * Delete an active client from the tunnel. - * - * @param t Tunnel. - * @param c Client. - */ -static void -tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c); - -/** * Notify a tunnel that a connection has broken that affects at least * some of its peers. * @@ -1167,26 +744,25 @@ tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1, /** - * Get the current ack value for a tunnel, for data going from root to leaves, - * taking in account the tunnel mode and the status of all children and clients. - * - * @param t Tunnel. - * - * @return Maximum PID allowed. + * @brief Use the given path for the tunnel. + * Update the next and prev hops (and RCs). + * (Re)start the path refresh in case the tunnel is locally owned. + * + * @param t Tunnel to update. + * @param p Path to use. */ -static uint32_t -tunnel_get_fwd_ack (struct MeshTunnel *t); - +static void +tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p); /** - * Add a client to a tunnel, initializing all needed data structures. + * Tunnel is empty: destroy it. * - * @param t Tunnel to which add the client. - * @param c Client which to add to the tunnel. + * Notifies all participants (peers, cleints) about the destruction. + * + * @param t Tunnel to destroy. */ static void -tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c); - +tunnel_destroy_empty (struct MeshTunnel *t); /** * @brief Queue and pass message to core when possible. @@ -1248,255 +824,12 @@ queue_get_next (const struct MeshPeerInfo *peer); static size_t queue_send (void *cls, size_t size, void *buf); -/******************************************************************************/ -/************************ REGEX INTEGRATION ****************************/ -/******************************************************************************/ - -/** - * Cancel a mesh regex search and free resources. - */ -static void -regex_cancel_search (struct MeshRegexSearchInfo *regex_search) -{ - DEBUG_REGEX ("Search for %s canelled.\n", regex_search->description); - GNUNET_REGEX_search_cancel (regex_search->search_handle); - if (0 < regex_search->n_peers) - GNUNET_free (regex_search->peers); - if (GNUNET_SCHEDULER_NO_TASK != regex_search->timeout) - { - GNUNET_SCHEDULER_cancel(regex_search->timeout); - } - GNUNET_free (regex_search); -} - - -/** - * Function called if the connect attempt to a peer found via - * connect_by_string times out. Try to connect to another peer, if any. - * Otherwise try to reconnect to the same peer. - * - * @param cls Closure (info about regex search). - * @param tc TaskContext. - */ -static void -regex_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct MeshRegexSearchInfo *info = cls; - struct MeshPeerInfo *peer_info; - GNUNET_PEER_Id id; - GNUNET_PEER_Id old; - - DEBUG_REGEX ("Regex connect timeout\n"); - info->timeout = GNUNET_SCHEDULER_NO_TASK; - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - { - DEBUG_REGEX (" due to shutdown\n"); - return; - } - - old = info->peer; - DEBUG_REGEX (" timed out: %u\n", old); - - if (0 < info->n_peers) - { - // Select next peer, put current in that spot. - id = info->peers[info->i_peer]; - info->peers[info->i_peer] = info->peer; - info->i_peer = (info->i_peer + 1) % info->n_peers; - } - else - { - // Try to connect to same peer again. - id = info->peer; - } - DEBUG_REGEX (" trying: %u\n", id); - - peer_info = peer_info_get_short(id); - tunnel_add_peer (info->t, peer_info); - if (old != id) - tunnel_delete_peer (info->t, old); - peer_info_connect (peer_info, info->t); - info->timeout = GNUNET_SCHEDULER_add_delayed (connect_timeout, - ®ex_connect_timeout, - info); - DEBUG_REGEX ("Regex connect timeout END\n"); -} - - -/** - * Function to process DHT string to regex matching. - * Called on each result obtained for the DHT search. - * - * @param cls Closure provided in GNUNET_REGEX_search. - * @param id Peer providing a regex that matches the string. - * @param get_path Path of the get request. - * @param get_path_length Lenght of get_path. - * @param put_path Path of the put request. - * @param put_path_length Length of the put_path. - */ -static void -regex_found_handler (void *cls, - const struct GNUNET_PeerIdentity *id, - const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length) -{ - struct MeshRegexSearchInfo *info = cls; - struct MeshPeerPath *p; - struct MeshPeerInfo *peer_info; - - DEBUG_REGEX ("Got regex results from DHT!\n"); - DEBUG_REGEX (" for %s\n", info->description); - - peer_info = peer_info_get (id); - p = path_build_from_dht (get_path, get_path_length, - put_path, put_path_length); - path_add_to_peers (p, GNUNET_NO); - path_destroy(p); - - tunnel_add_peer (info->t, peer_info); - peer_info_connect (peer_info, info->t); - if (0 == info->peer) - { - info->peer = peer_info->id; - } - else - { - GNUNET_array_append (info->peers, info->n_peers, peer_info->id); - } - - if (GNUNET_SCHEDULER_NO_TASK != info->timeout) - return; - - info->timeout = GNUNET_SCHEDULER_add_delayed (connect_timeout, - ®ex_connect_timeout, - info); - - return; -} - - -/** - * Store the regular expression describing a local service into the DHT. - * - * @param regex The regular expresion. - */ -static void -regex_put (struct MeshRegexDescriptor *regex) -{ - DEBUG_REGEX (" regex_put (%s) start\n", regex->regex); - if (NULL == regex->h) - { - DEBUG_REGEX (" first put, creating DFA\n"); - regex->h = GNUNET_REGEX_announce (cfg, - regex->regex, - app_announce_time, - regex->compression); - } - DEBUG_REGEX (" regex_put (%s) end\n", regex->regex); -} - - -/** - * Periodically announce what applications are provided by local clients - * (by regex) - * - * @param cls closure - * @param tc task context - */ -static void -regex_announce (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct MeshClient *c = cls; - unsigned int i; - - c->regex_announce_task = GNUNET_SCHEDULER_NO_TASK; - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - return; - DEBUG_REGEX ("Starting announce for regex\n"); - for (i = 0; i < c->n_regex; i++) - regex_put (&c->regexes[i]); - c->regex_announce_task = GNUNET_SCHEDULER_add_delayed (app_announce_time, - ®ex_announce, - cls); - DEBUG_REGEX ("Finished announce for regex\n"); -} - /******************************************************************************/ /************************ PERIODIC FUNCTIONS ****************************/ /******************************************************************************/ /** - * Announce iterator over for each application provided by the peer - * - * @param cls closure - * @param key current key code - * @param value value in the hash map - * @return GNUNET_YES if we should continue to - * iterate, - * GNUNET_NO if not. - */ -static int -announce_application (void *cls, const struct GNUNET_HashCode * key, void *value) -{ - struct PBlock block; - struct MeshClient *c; - - block.id = my_full_id; - c = GNUNET_CONTAINER_multihashmap_get (applications, key); - GNUNET_assert(NULL != c); - block.type = (long) GNUNET_CONTAINER_multihashmap_get (c->apps, key); - if (0 == block.type) - { - GNUNET_break(0); - return GNUNET_YES; - } - block.type = htonl (block.type); - DEBUG_DHT ("Putting APP key: %s\n", GNUNET_h2s (key)); - GNUNET_break (NULL != - GNUNET_DHT_put (dht_handle, key, - dht_replication_level, - GNUNET_DHT_RO_RECORD_ROUTE | - GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, - GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE, - sizeof (block), - (const char *) &block, - GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_HOURS), /* FIXME: this should be an option */ - app_announce_time, NULL, NULL)); - return GNUNET_OK; -} - - -/** - * Periodically announce what applications are provided by local clients - * (by type) - * - * @param cls closure - * @param tc task context - */ -static void -announce_applications (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - { - announce_applications_task = GNUNET_SCHEDULER_NO_TASK; - return; - } - - DEBUG_DHT ("Starting PUT for apps\n"); - - GNUNET_CONTAINER_multihashmap_iterate (applications, &announce_application, - NULL); - announce_applications_task = - GNUNET_SCHEDULER_add_delayed (app_announce_time, &announce_applications, - cls); - DEBUG_DHT ("Finished PUT for apps\n"); -} - - -/** * Periodically announce self id in the DHT * * @param cls closure @@ -1519,7 +852,6 @@ announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (&my_full_id)); block.id = my_full_id; - block.type = htonl (0); GNUNET_DHT_put (dht_handle, /* DHT handle */ &my_full_id.hashPubKey, /* Key to use */ dht_replication_level, /* Replication level */ @@ -1540,23 +872,6 @@ announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) /****************** GENERAL HELPER FUNCTIONS ************************/ /******************************************************************************/ -/** - * Decrements the reference counter and frees all resources if needed - * - * @param mesh_data Data Descriptor used in a multicast message. - * Freed no longer needed (last message). - */ -static void -data_descriptor_decrement_rc (struct MeshData *mesh_data) -{ - if (0 == --(mesh_data->reference_counter)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last copy!\n"); - GNUNET_free (mesh_data->data); - GNUNET_free (mesh_data); - } -} - /** * Check if client has registered with the service and has not disconnected @@ -1570,7 +885,7 @@ client_get (struct GNUNET_SERVER_Client *client) { struct MeshClient *c; - c = clients; + c = clients_head; while (NULL != c) { if (c->handle == client) @@ -1582,104 +897,8 @@ client_get (struct GNUNET_SERVER_Client *client) /** - * Checks if a given client has subscribed to certain message type - * - * @param message_type Type of message to check - * @param c Client to check - * - * @return GNUNET_YES or GNUNET_NO, depending on subscription status - * - * FIXME: use of crypto_hash slows it down - * The hash function alone takes 8-10us out of the ~55us for the whole - * process of retransmitting the message from one local client to another. - * Find faster implementation! - */ -static int -client_is_subscribed (uint16_t message_type, struct MeshClient *c) -{ - struct GNUNET_HashCode hc; - - if (NULL == c->types) - return GNUNET_NO; - - GNUNET_CRYPTO_hash (&message_type, sizeof (uint16_t), &hc); - return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc); -} - - -/** - * Check whether client wants traffic from a tunnel. - * - * @param c Client to check. - * @param t Tunnel to be found. - * - * @return GNUNET_YES if client knows tunnel. - * - * TODO look in client hashmap - */ -static int -client_wants_tunnel (struct MeshClient *c, struct MeshTunnel *t) -{ - unsigned int i; - - for (i = 0; i < t->nclients; i++) - if (t->clients[i] == c) - return GNUNET_YES; - return GNUNET_NO; -} - - -/** - * Check whether client has been informed about a tunnel. - * - * @param c Client to check. - * @param t Tunnel to be found. - * - * @return GNUNET_YES if client knows tunnel. - * - * TODO look in client hashmap - */ -static int -client_knows_tunnel (struct MeshClient *c, struct MeshTunnel *t) -{ - unsigned int i; - - for (i = 0; i < t->nignore; i++) - if (t->ignore[i] == c) - return GNUNET_YES; - return client_wants_tunnel(c, t); -} - - -/** - * Marks a client as uninterested in traffic from the tunnel, updating both - * client and tunnel to reflect this. - * - * @param c Client that doesn't want traffic anymore. - * @param t Tunnel which should be ignored. - * - * FIXME when to delete an incoming tunnel? - */ -static void -client_ignore_tunnel (struct MeshClient *c, struct MeshTunnel *t) -{ - struct GNUNET_HashCode hash; - - GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); - GNUNET_break (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, - &hash, t)); - GNUNET_break (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_put (c->ignore_tunnels, &hash, t, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - tunnel_delete_active_client (t, c); - GNUNET_array_append (t->ignore, t->nignore, c); -} - - -/** * Deletes a tunnel from a client (either owner or destination). To be used on - * tunnel destroy, otherwise, use client_ignore_tunnel. + * tunnel destroy. * * @param c Client whose tunnel to delete. * @param t Tunnel which should be deleted. @@ -1691,240 +910,76 @@ client_delete_tunnel (struct MeshClient *c, struct MeshTunnel *t) if (c == t->owner) { - GNUNET_CRYPTO_hash(&t->local_tid, sizeof (MESH_TunnelNumber), &hash); + GMC_hash32 (t->local_tid, &hash); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t)); } - else + else if (c == t->client) { - GNUNET_CRYPTO_hash(&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); - // FIXME XOR? + GMC_hash32 (t->local_tid_dest, &hash); GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, - t) || - GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels, - &hash, t)); } -} - - -/** - * Notify the owner of a tunnel that a peer has disconnected. - * - * @param c Client (owner of tunnel). - * @param t Tunnel this message is about. - * @param peer_id Short ID of the disconnected peer. - */ -void -client_notify_peer_disconnected (struct MeshClient *c, - struct MeshTunnel *t, - GNUNET_PEER_Id peer_id) -{ - struct GNUNET_MESH_PeerControl msg; - - if (NULL == t->owner || NULL == nc) - return; - - msg.header.size = htons (sizeof (msg)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL); - msg.tunnel_id = htonl (t->local_tid); - GNUNET_PEER_resolve (peer_id, &msg.peer); - GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, - &msg.header, GNUNET_NO); -} - - -/** - * Send the message to all clients that have subscribed to its type - * - * @param msg Pointer to the message itself - * @param payload Pointer to the payload of the message. - * @param t The tunnel to whose clients this message goes. - * - * @return number of clients this message was sent to - */ -static unsigned int -send_subscribed_clients (const struct GNUNET_MessageHeader *msg, - const struct GNUNET_MessageHeader *payload, - struct MeshTunnel *t) -{ - struct MeshClient *c; - MESH_TunnelNumber *tid; - unsigned int count; - uint16_t type; - char cbuf[htons (msg->size)]; - - type = ntohs (payload->type); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending to clients...\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "message of type %s\n", - GNUNET_MESH_DEBUG_M2S (type)); - - memcpy (cbuf, msg, sizeof (cbuf)); - switch (htons (msg->type)) - { - struct GNUNET_MESH_Unicast *uc; - struct GNUNET_MESH_Multicast *mc; - struct GNUNET_MESH_ToOrigin *to; - - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - uc = (struct GNUNET_MESH_Unicast *) cbuf; - tid = &uc->tid; - break; - case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: - mc = (struct GNUNET_MESH_Multicast *) cbuf; - tid = &mc->tid; - break; - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - to = (struct GNUNET_MESH_ToOrigin *) cbuf; - tid = &to->tid; - break; - default: - GNUNET_break (0); - return 0; - } - - for (count = 0, c = clients; c != NULL; c = c->next) + else { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client %u\n", c->id); - if (client_is_subscribed (type, c)) - { - if (htons (msg->type) == GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN) - { - if (c != t->owner) - continue; - *tid = htonl (t->local_tid); - } - else - { - if (GNUNET_NO == client_knows_tunnel (c, t)) - { - /* This client doesn't know the tunnel */ - struct GNUNET_MESH_TunnelNotification tmsg; - struct GNUNET_HashCode hash; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending tunnel create\n"); - tmsg.header.size = htons (sizeof (tmsg)); - tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); - GNUNET_PEER_resolve (t->id.oid, &tmsg.peer); - tmsg.tunnel_id = htonl (t->local_tid_dest); - tmsg.opt = 0; - if (GNUNET_YES == t->speed_min) - tmsg.opt |= MESH_TUNNEL_OPT_SPEED_MIN; - if (GNUNET_YES == t->nobuffer) - tmsg.opt |= MESH_TUNNEL_OPT_NOBUFFER; - GNUNET_SERVER_notification_context_unicast (nc, c->handle, - &tmsg.header, GNUNET_NO); - tunnel_add_client (t, c); - GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), - &hash); - GNUNET_break (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put ( - c->incoming_tunnels, &hash, t, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - } - *tid = htonl (t->local_tid_dest); - } - - /* Check if the client wants to get traffic from the tunnel */ - if (GNUNET_NO == client_wants_tunnel(c, t)) - continue; - count++; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending\n"); - GNUNET_SERVER_notification_context_unicast (nc, c->handle, - (struct GNUNET_MessageHeader - *) cbuf, GNUNET_NO); - } + GNUNET_break (0); } - - return count; -} - - -/** - * Notify the client that owns the tunnel that a peer has connected to it - * (the requested path to it has been confirmed). - * - * @param t Tunnel whose owner to notify - * @param id Short id of the peer that has connected - */ -static void -send_client_peer_connected (const struct MeshTunnel *t, const GNUNET_PEER_Id id) -{ - struct GNUNET_MESH_PeerControl pc; - - if (NULL == t->owner || GNUNET_YES == t->destroy) - return; - - pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); - pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); - pc.tunnel_id = htonl (t->local_tid); - GNUNET_PEER_resolve (id, &pc.peer); - GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, &pc.header, - GNUNET_NO); } - /** - * Notify all clients (not depending on registration status) that the incoming - * tunnel is no longer valid. + * Notify the appropriate client that a new incoming tunnel was created. * - * @param t Tunnel that was destroyed. + * @param t Tunnel that was created. */ static void -send_clients_tunnel_destroy (struct MeshTunnel *t) +send_client_tunnel_create (struct MeshTunnel *t) { struct GNUNET_MESH_TunnelMessage msg; + if (NULL == t->client) + return; msg.header.size = htons (sizeof (msg)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); + msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); msg.tunnel_id = htonl (t->local_tid_dest); - GNUNET_SERVER_notification_context_broadcast (nc, &msg.header, GNUNET_NO); + msg.port = htonl (t->port); + GNUNET_PEER_resolve (t->id.oid, &msg.peer); + GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, + &msg.header, GNUNET_NO); } /** - * Notify clients of tunnel disconnections, if needed. - * In case the origin disconnects, the destination clients get a tunnel destroy - * notification. If the last destination disconnects (only one remaining client - * in tunnel), the origin gets a (local ID) peer disconnected. - * Note that the function must be called BEFORE removing the client from - * the tunnel. + * Notify dest client that the incoming tunnel is no longer valid. * - * @param t Tunnel that was destroyed. - * @param c Client that disconnected. + * @param c Client to notify.. + * @param t Tunnel that is destroyed. */ static void -send_client_tunnel_disconnect (struct MeshTunnel *t, struct MeshClient *c) +send_client_tunnel_destroy (struct MeshClient *c, struct MeshTunnel *t) { - unsigned int i; + struct GNUNET_MESH_TunnelMessage msg; - if (c == t->owner) + if (NULL == c) { - struct GNUNET_MESH_TunnelMessage msg; - - msg.header.size = htons (sizeof (msg)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); - msg.tunnel_id = htonl (t->local_tid_dest); - for (i = 0; i < t->nclients; i++) - GNUNET_SERVER_notification_context_unicast (nc, t->clients[i]->handle, - &msg.header, GNUNET_NO); + GNUNET_break (0); + return; } - // FIXME when to disconnect an incoming tunnel? - else if (1 == t->nclients && NULL != t->owner) + if (c != t->client && c != t->owner) { - struct GNUNET_MESH_PeerControl msg; - - msg.header.size = htons (sizeof (msg)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL); - msg.tunnel_id = htonl (t->local_tid); - msg.peer = my_full_id; - GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, - &msg.header, GNUNET_NO); + GNUNET_break (0); + return; } + msg.header.size = htons (sizeof (msg)); + msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); + msg.tunnel_id = htonl (t->local_tid_dest); + msg.port = htonl (0); + memset(&msg.peer, 0, sizeof (msg.peer)); + GNUNET_SERVER_notification_context_unicast (nc, c->handle, + &msg.header, GNUNET_NO); } @@ -1947,14 +1002,14 @@ peer_info_timeout (void *cls, /** * Retrieve the MeshPeerInfo stucture associated with the peer, create one - * and insert it in the appropiate structures if the peer is not known yet. + * and insert it in the appropriate structures if the peer is not known yet. * * @param peer Full identity of the peer. * * @return Existing or newly created peer info. */ static struct MeshPeerInfo * -peer_info_get (const struct GNUNET_PeerIdentity *peer) +peer_get (const struct GNUNET_PeerIdentity *peer) { struct MeshPeerInfo *peer_info; @@ -1981,56 +1036,52 @@ peer_info_get (const struct GNUNET_PeerIdentity *peer) /** * Retrieve the MeshPeerInfo stucture associated with the peer, create one - * and insert it in the appropiate structures if the peer is not known yet. + * and insert it in the appropriate structures if the peer is not known yet. * * @param peer Short identity of the peer. * * @return Existing or newly created peer info. */ static struct MeshPeerInfo * -peer_info_get_short (const GNUNET_PEER_Id peer) +peer_get_short (const GNUNET_PEER_Id peer) { struct GNUNET_PeerIdentity id; GNUNET_PEER_resolve (peer, &id); - return peer_info_get (&id); + return peer_get (&id); } /** - * Iterator to remove the tunnel from the list of tunnels a peer participates - * in. - * - * @param cls Closure (tunnel info) - * @param key GNUNET_PeerIdentity of the peer (unused) - * @param value PeerInfo of the peer + * Choose the best path towards a peer considering the tunnel properties. + * + * @param peer The destination peer. + * @param t The tunnel the path is for. * - * @return always GNUNET_YES, to keep iterating + * @return Best current known path towards the peer, if any. */ -static int -peer_info_delete_tunnel (void *cls, const struct GNUNET_HashCode * key, void *value) +static struct MeshPeerPath * +peer_get_best_path (const struct MeshPeerInfo *peer, const struct MeshTunnel *t) { - struct MeshTunnel *t = cls; - struct MeshPeerInfo *peer = value; - unsigned int i; + struct MeshPeerPath *best_p; + struct MeshPeerPath *p; + unsigned int best_cost; + unsigned int cost; - for (i = 0; i < peer->ntunnels; i++) + best_p = p = peer->path_head; + best_cost = cost = p->length; + while (NULL != p) { - if (0 == - memcmp (&peer->tunnels[i]->id, &t->id, sizeof (struct MESH_TunnelID))) + if ((cost = p->length) < best_cost) { - peer->ntunnels--; - peer->tunnels[i] = peer->tunnels[peer->ntunnels]; - peer->tunnels = - GNUNET_realloc (peer->tunnels, - peer->ntunnels * sizeof(struct MeshTunnel *)); - return GNUNET_YES; + best_cost = cost; + best_p = p; } + p = p->next; } - return GNUNET_YES; + return best_p; } - /** * Core callback to write a pre-constructed data packet to core buffer * @@ -2043,13 +1094,10 @@ peer_info_delete_tunnel (void *cls, const struct GNUNET_HashCode * key, void *va static size_t send_core_data_raw (void *cls, size_t size, void *buf) { - struct MeshTransmissionDescriptor *info = cls; - struct GNUNET_MessageHeader *msg; + struct GNUNET_MessageHeader *msg = cls; size_t total_size; - GNUNET_assert (NULL != info); - GNUNET_assert (NULL != info->mesh_data); - msg = (struct GNUNET_MessageHeader *) info->mesh_data->data; + GNUNET_assert (NULL != msg); total_size = ntohs (msg->size); if (total_size > size) @@ -2058,15 +1106,14 @@ send_core_data_raw (void *cls, size_t size, void *buf) return 0; } memcpy (buf, msg, total_size); - data_descriptor_decrement_rc (info->mesh_data); - GNUNET_free (info); + GNUNET_free (cls); return total_size; } /** - * Sends an already built non-multicast message to a peer, - * properly registrating all used resources. + * Sends an already built message to a peer, properly registrating + * all used resources. * * @param message Message to send. Function makes a copy of it. * @param peer Short ID of the neighbor whom to send the message. @@ -2074,41 +1121,35 @@ send_core_data_raw (void *cls, size_t size, void *buf) */ static void send_prebuilt_message (const struct GNUNET_MessageHeader *message, - const struct GNUNET_PeerIdentity *peer, + GNUNET_PEER_Id peer, struct MeshTunnel *t) { - struct MeshTransmissionDescriptor *info; + struct GNUNET_PeerIdentity id; struct MeshPeerInfo *neighbor; struct MeshPeerPath *p; + void *data; size_t size; uint16_t type; // GNUNET_TRANSPORT_try_connect(); FIXME use? + if (0 == peer) + return; + size = ntohs (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); + data = GNUNET_malloc (size); + memcpy (data, message, size); type = ntohs(message->type); - switch (type) + if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type || + GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type) { - struct GNUNET_MESH_Unicast *m; - struct GNUNET_MESH_ToOrigin *to; + struct GNUNET_MESH_Data *u; - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - m = (struct GNUNET_MESH_Unicast *) info->mesh_data->data; - m->ttl = htonl (ntohl (m->ttl) - 1); - break; - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - to = (struct GNUNET_MESH_ToOrigin *) info->mesh_data->data; - t->bck_pid++; - to->pid = htonl(t->bck_pid); - } - info->mesh_data->data_len = size; - info->mesh_data->reference_counter = 1; - info->mesh_data->total_out = 1; - neighbor = peer_info_get (peer); + u = (struct GNUNET_MESH_Data *) data; + u->ttl = htonl (ntohl (u->ttl) - 1); + } + GNUNET_PEER_resolve (peer, &id); + neighbor = peer_get (&id); for (p = neighbor->path_head; NULL != p; p = p->next) { if (2 >= p->length) @@ -2121,10 +1162,10 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message, #if MESH_DEBUG GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s IS NOT DIRECTLY CONNECTED\n", - GNUNET_i2s(peer)); + GNUNET_i2s(&id)); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " PATHS TO %s:\n", - GNUNET_i2s(peer)); + GNUNET_i2s(&id)); for (p = neighbor->path_head; NULL != p; p = p->next) { struct GNUNET_PeerIdentity debug_id; @@ -2143,18 +1184,15 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message, } #endif GNUNET_break (0); // FIXME sometimes fails (testing disconnect?) - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " no direct connection to %s\n", - GNUNET_i2s (peer)); - GNUNET_free (info->mesh_data->data); - GNUNET_free (info->mesh_data); - GNUNET_free (info); + GNUNET_i2s (&id)); + GNUNET_free (data); return; } - info->peer = neighbor; if (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK == type) type = 0; - queue_add (info, + queue_add (data, type, size, neighbor, @@ -2166,94 +1204,22 @@ send_prebuilt_message (const struct GNUNET_MessageHeader *message, * Sends a CREATE PATH message for a path to a peer, properly registrating * all used resources. * - * @param peer PeerInfo of the final peer for whom this path is being created. - * @param p Path itself. * @param t Tunnel for which the path is created. */ static void -send_create_path (struct MeshPeerInfo *peer, struct MeshPeerPath *p, - struct MeshTunnel *t) +send_create_path (struct MeshTunnel *t) { - struct GNUNET_PeerIdentity id; - struct MeshPathInfo *path_info; struct MeshPeerInfo *neighbor; - unsigned int i; - - if (NULL == p) - { - p = tree_get_path_to_peer (t->tree, peer->id); - if (NULL == p) - { - GNUNET_break (0); - return; - } - } - for (i = 0; i < p->length; i++) - { - if (p->peers[i] == myid) - break; - } - if (i >= p->length - 1) - { - path_destroy (p); - GNUNET_break (0); - return; - } - GNUNET_PEER_resolve (p->peers[i + 1], &id); - - path_info = GNUNET_malloc (sizeof (struct MeshPathInfo)); - path_info->path = p; - path_info->t = t; - neighbor = peer_info_get (&id); - path_info->peer = neighbor; - queue_add (path_info, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send create path\n"); + neighbor = peer_get_short (t->next_hop); + queue_add (t, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, - sizeof (struct GNUNET_MESH_ManipulatePath) + - (p->length * sizeof (struct GNUNET_PeerIdentity)), + sizeof (struct GNUNET_MESH_CreateTunnel) + + (t->path->length * sizeof (struct GNUNET_PeerIdentity)), neighbor, t); -} - - -/** - * Sends a DESTROY PATH message to free resources for a path in a tunnel - * - * @param t Tunnel whose path to destroy. - * @param destination Short ID of the peer to whom the path to destroy. - */ -static void -send_destroy_path (struct MeshTunnel *t, GNUNET_PEER_Id destination) -{ - struct MeshPeerPath *p; - size_t size; - - p = tree_get_path_to_peer (t->tree, destination); - if (NULL == p) - { - GNUNET_break (0); - return; - } - size = sizeof (struct GNUNET_MESH_ManipulatePath); - size += p->length * sizeof (struct GNUNET_PeerIdentity); - { - struct GNUNET_MESH_ManipulatePath *msg; - struct GNUNET_PeerIdentity *pi; - char cbuf[size]; - unsigned int i; - - msg = (struct GNUNET_MESH_ManipulatePath *) cbuf; - msg->header.size = htons (size); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY); - msg->tid = htonl (t->id.tid); - pi = (struct GNUNET_PeerIdentity *) &msg[1]; - for (i = 0; i < p->length; i++) - { - GNUNET_PEER_resolve (p->peers[i], &pi[i]); - } - send_prebuilt_message (&msg->header, tree_get_first_hop (t->tree, destination), t); - } - path_destroy (p); + t->state = MESH_TUNNEL_WAITING; } @@ -2265,28 +1231,20 @@ send_destroy_path (struct MeshTunnel *t, GNUNET_PEER_Id destination) static void send_path_ack (struct MeshTunnel *t) { - struct MeshTransmissionDescriptor *info; - struct GNUNET_PeerIdentity id; - GNUNET_PEER_Id peer; + struct MeshPeerInfo *peer; - peer = tree_get_predecessor (t->tree); - GNUNET_PEER_resolve (peer, &id); - info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor)); - info->origin = &t->id; - info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey); - GNUNET_assert (NULL != info->peer); + peer = peer_get_short (t->prev_hop); - queue_add (info, + queue_add (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK, sizeof (struct GNUNET_MESH_PathACK), - info->peer, + peer, t); } /** - * Try to establish a new connection to this peer. - * Use the best path for the given tunnel. + * Try to establish a new connection to this peer in the given tunnel. * If the peer doesn't have any path to it yet, try to get one. * If the peer already has some path, send a CREATE PATH towards it. * @@ -2294,90 +1252,39 @@ send_path_ack (struct MeshTunnel *t) * @param t Tunnel for which to create the path, if possible. */ static void -peer_info_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t) +peer_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t) { struct MeshPeerPath *p; - struct MeshPathInfo *path_info; if (NULL != peer->path_head) { - p = tree_get_path_to_peer (t->tree, peer->id); - if (NULL == p) - { - GNUNET_break (0); - return; - } - - // FIXME always send create path to self - if (p->length > 1) - { - send_create_path (peer, p, t); - } - else - { - struct GNUNET_HashCode hash; - - path_destroy (p); - send_client_peer_connected (t, myid); - t->local_tid_dest = next_local_tid++; - GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), - &hash); - if (GNUNET_OK != - GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) - { - GNUNET_break (0); - return; - } - } + p = peer_get_best_path (peer, t); + tunnel_use_path (t, p); + send_create_path (t); } else if (NULL == peer->dhtget) { struct GNUNET_PeerIdentity id; GNUNET_PEER_resolve (peer->id, &id); - path_info = GNUNET_malloc (sizeof (struct MeshPathInfo)); - path_info->peer = peer; - path_info->t = t; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Starting DHT GET for peer %s\n", GNUNET_i2s (&id)); - peer->dhtgetcls = path_info; peer->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ GNUNET_BLOCK_TYPE_MESH_PEER, /* type */ &id.hashPubKey, /* key to search */ dht_replication_level, /* replication level */ GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, - NULL, /* xquery */ // FIXME BLOOMFILTER - 0, /* xquery bits */ // FIXME BLOOMFILTER SIZE - &dht_get_id_handler, path_info); + NULL, /* xquery */ + 0, /* xquery bits */ + &dht_get_id_handler, peer); + t->state = MESH_TUNNEL_SEARCHING; } - /* Otherwise, there is no path but the DHT get is already started. */ -} - - -/** - * Task to delay the connection of a peer - * - * @param cls Closure (path info with tunnel and peer to connect). - * Will be free'd on exection. - * @param tc TaskContext - */ -static void -peer_info_connect_task (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct MeshPathInfo *path_info = cls; - - path_info->peer->connect_task = GNUNET_SCHEDULER_NO_TASK; - - if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) + else { - GNUNET_free (cls); - return; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "There is no path but the DHT GET is already started.\n"); } - peer_info_connect (path_info->peer, path_info->t); - GNUNET_free (cls); } @@ -2394,6 +1301,7 @@ peer_info_destroy (struct MeshPeerInfo *pi) struct GNUNET_PeerIdentity id; struct MeshPeerPath *p; struct MeshPeerPath *nextp; + unsigned int i; GNUNET_PEER_resolve (pi->id, &id); GNUNET_PEER_change_rc (pi->id, -1); @@ -2408,7 +1316,6 @@ peer_info_destroy (struct MeshPeerInfo *pi) if (NULL != pi->dhtget) { GNUNET_DHT_get_stop (pi->dhtget); - GNUNET_free (pi->dhtgetcls); } p = pi->path_head; while (NULL != p) @@ -2418,10 +1325,9 @@ peer_info_destroy (struct MeshPeerInfo *pi) path_destroy (p); p = nextp; } - if (GNUNET_SCHEDULER_NO_TASK != pi->connect_task) - { - GNUNET_free (GNUNET_SCHEDULER_cancel (pi->connect_task)); - } + for (i = 0; i < pi->ntunnels; i++) + tunnel_destroy_empty (pi->tunnels[i]); + GNUNET_array_grow (pi->tunnels, pi->ntunnels, 0); GNUNET_free (pi); return GNUNET_OK; } @@ -2439,24 +1345,21 @@ peer_info_destroy (struct MeshPeerInfo *pi) * TODO: optimize (see below) */ static void -peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, +peer_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, GNUNET_PEER_Id p2) { struct MeshPeerPath *p; - struct MeshPeerPath *aux; + struct MeshPeerPath *next; struct MeshPeerInfo *peer_d; GNUNET_PEER_Id d; unsigned int destroyed; - unsigned int best; - unsigned int cost; unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path\n"); destroyed = 0; - p = peer->path_head; - while (NULL != p) + for (p = peer->path_head; NULL != p; p = next) { - aux = p->next; + next = p->next; for (i = 0; i < (p->length - 1); i++) { if ((p->peers[i] == p1 && p->peers[i + 1] == p2) || @@ -2468,7 +1371,6 @@ peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, break; } } - p = aux; } if (0 == destroyed) return; @@ -2478,39 +1380,11 @@ peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, d = tunnel_notify_connection_broken (peer->tunnels[i], p1, p2); 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. - * We need to try to find a new path for each of the disconnected peers. - * Some of them might already have a path to reach them that does not - * involve p1 and p2. Adding all anew might render in a better tree than - * the trivial immediate fix. - * - * Trivial immiediate fix: try to reconnect to the disconnected node. All - * its children will be reachable trough him. - */ - peer_d = peer_info_get_short (d); - best = UINT_MAX; - aux = NULL; - for (p = peer_d->path_head; NULL != p; p = p->next) - { - if ((cost = tree_get_path_cost (peer->tunnels[i]->tree, p)) < best) - { - best = cost; - aux = p; - } - } - if (NULL != aux) - { - /* No callback, as peer will be already disconnected and a connection - * scheduled by tunnel_notify_connection_broken. - */ - tree_add_path (peer->tunnels[i]->tree, aux, NULL, NULL); - } - else - { - peer_info_connect (peer_d, peer->tunnels[i]); - } + + peer_d = peer_get_short (d); + next = peer_get_best_path (peer_d, peer->tunnels[i]); + tunnel_use_path (peer->tunnels[i], next); + peer_connect (peer_d, peer->tunnels[i]); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer_info_remove_path END\n"); } @@ -2545,13 +1419,12 @@ peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path, path_destroy (path); return; } - if (path->length <= 2 && GNUNET_NO == trusted) + if (2 >= path->length && GNUNET_NO == trusted) { /* Only allow CORE to tell us about direct paths */ path_destroy (path); return; } - GNUNET_assert (peer_info->id == path->peers[path->length - 1]); for (l = 1; l < path->length; l++) { if (path->peers[l] == myid) @@ -2579,7 +1452,7 @@ peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path, l = path_get_length (path); if (0 == l) { - GNUNET_free (path); + path_destroy (path); return; } @@ -2616,6 +1489,7 @@ peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path, * * @param peer_info Peer to add the path to, being the origin of the path. * @param path New path to add after being inversed. + * Path will be either used or freed. * @param trusted Do we trust that this path is real? */ static void @@ -2628,40 +1502,98 @@ peer_info_add_path_to_origin (struct MeshPeerInfo *peer_info, /** + * Add a tunnel to the list of tunnels a peer participates in. + * Update the tunnel's destination. + * + * @param p Peer to add to. + * @param t Tunnel to add. + */ +static void +peer_info_add_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t) +{ + if (0 != t->dest) + { + GNUNET_break (t->dest == p->id); + return; + } + t->dest = p->id; + GNUNET_PEER_change_rc (t->dest, 1); + GNUNET_array_append (p->tunnels, p->ntunnels, t); +} + + +/** + * Remove a tunnel from the list of tunnels a peer participates in. + * Free the tunnel's destination. + * + * @param p Peer to clean. + * @param t Tunnel to remove. + */ +static void +peer_info_remove_tunnel (struct MeshPeerInfo *p, struct MeshTunnel *t) +{ + unsigned int i; + + if (t->dest == p->id) + { + GNUNET_PEER_change_rc (t->dest, -1); + t->dest = 0; + } + for (i = 0; i < p->ntunnels; i++) + { + if (p->tunnels[i] == t) + { + p->tunnels[i] = p->tunnels[p->ntunnels - 1]; + GNUNET_array_grow (p->tunnels, p->ntunnels, p->ntunnels - 1); + return; + } + } +} + + +/** * Function called if the connection to the peer has been stalled for a while, * possibly due to a missed ACK. Poll the peer about its ACK status. * - * @param cls Closure (cinfo). + * @param cls Closure (poll ctx). * @param tc TaskContext. */ static void tunnel_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct MeshTunnelChildInfo *cinfo = cls; + struct MeshFlowControl *fc = cls; struct GNUNET_MESH_Poll msg; - struct GNUNET_PeerIdentity id; - struct MeshTunnel *t; + struct MeshTunnel *t = fc->t; + GNUNET_PEER_Id peer; - cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; + fc->poll_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { return; } - t = cinfo->t; msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL); msg.header.size = htons (sizeof (msg)); msg.tid = htonl (t->id.tid); GNUNET_PEER_resolve (t->id.oid, &msg.oid); - msg.last_ack = htonl (cinfo->fwd_ack); - - GNUNET_PEER_resolve (cinfo->id, &id); - send_prebuilt_message (&msg.header, &id, cinfo->t); - cinfo->fc_poll_time = GNUNET_TIME_relative_min ( - MESH_MAX_POLL_TIME, - GNUNET_TIME_relative_multiply (cinfo->fc_poll_time, 2)); - cinfo->fc_poll = GNUNET_SCHEDULER_add_delayed (cinfo->fc_poll_time, - &tunnel_poll, cinfo); + + if (fc == &t->prev_fc) + { + peer = t->prev_hop; + } + else if (fc == &t->next_fc) + { + peer = t->next_hop; + } + else + { + GNUNET_break (0); + return; + } + send_prebuilt_message (&msg.header, peer, t); + fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time); + fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, + &tunnel_poll, fc); } @@ -2770,10 +1702,10 @@ path_add_to_peers (struct MeshPeerPath *p, int confirmed) struct MeshPeerInfo *aux; struct MeshPeerPath *copy; - aux = peer_info_get_short (p->peers[i]); + aux = peer_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, p->length < 3 ? GNUNET_NO : confirmed); } } @@ -2783,8 +1715,6 @@ path_add_to_peers (struct MeshPeerPath *p, int confirmed) * * @param cls Closure (tunnel for which to send the keepalive). * @param tc Notification context. - * - * TODO: implement explicit multicast keepalive? */ static void path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); @@ -2803,7 +1733,7 @@ tunnel_get_incoming (MESH_TunnelNumber tid) struct GNUNET_HashCode hash; GNUNET_assert (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV); - GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash); + GMC_hash32 (tid, &hash); return GNUNET_CONTAINER_multihashmap_get (incoming_tunnels, &hash); } @@ -2827,7 +1757,7 @@ tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid) { struct GNUNET_HashCode hash; - GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash); + GMC_hash32 (tid, &hash); return GNUNET_CONTAINER_multihashmap_get (c->own_tunnels, &hash); } } @@ -2871,240 +1801,77 @@ tunnel_get (const struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid) /** - * Delete an active client from the tunnel. - * - * @param t Tunnel. - * @param c Client. - */ -static void -tunnel_delete_active_client (struct MeshTunnel *t, const struct MeshClient *c) -{ - unsigned int i; - - for (i = 0; i < t->nclients; i++) - { - if (t->clients[i] == c) - { - t->clients[i] = t->clients[t->nclients - 1]; - t->clients_fc[i] = t->clients_fc[t->nclients - 1]; - GNUNET_array_grow (t->clients, t->nclients, t->nclients - 1); - t->nclients++; - GNUNET_array_grow (t->clients_fc, t->nclients, t->nclients - 1); - break; - } - } -} - - -/** - * Delete an ignored client from the tunnel. + * Add a client to a tunnel, initializing all needed data structures. * - * @param t Tunnel. - * @param c Client. + * @param t Tunnel to which add the client. + * @param c Client which to add to the tunnel. */ static void -tunnel_delete_ignored_client (struct MeshTunnel *t, const struct MeshClient *c) +tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c) { - unsigned int i; + struct GNUNET_HashCode hash; - for (i = 0; i < t->nignore; i++) + if (NULL != t->client) { - if (t->ignore[i] == c) - { - t->ignore[i] = t->ignore[t->nignore - 1]; - GNUNET_array_grow (t->ignore, t->nignore, t->nignore - 1); - break; - } + GNUNET_break(0); + return; } -} - - -/** - * Delete a client from the tunnel. It should be only done on - * client disconnection, otherwise use client_ignore_tunnel. - * - * @param t Tunnel. - * @param c Client. - */ -static void -tunnel_delete_client (struct MeshTunnel *t, const struct MeshClient *c) -{ - tunnel_delete_ignored_client (t, c); - tunnel_delete_active_client (t, c); -} - - -/** - * @brief Iterator to destroy MeshTunnelChildInfo of tunnel children. - * - * Destroys queue elements of all waiting transmissions and frees all memory - * used by the struct and its elements. - * - * @param cls Closure (tunnel info). - * @param key Hash of GNUNET_PEER_Id (unused). - * @param value MeshTunnelChildInfo of the child. - * - * @return always GNUNET_YES, to keep iterating - */ -static int -tunnel_destroy_child (void *cls, - const struct GNUNET_HashCode * key, - void *value) -{ - struct MeshTunnelChildInfo *cinfo = value; - struct MeshTunnel *t = cls; - struct MeshPeerQueue *q; - unsigned int c; - unsigned int i; - - for (c = 0; c < cinfo->send_buffer_n; c++) + GMC_hash32 (t->local_tid_dest, &hash); + if (GNUNET_OK != + GNUNET_CONTAINER_multihashmap_put (c->incoming_tunnels, &hash, t, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) { - i = (cinfo->send_buffer_start + c) % t->fwd_queue_max; - q = cinfo->send_buffer[i]; - cinfo->send_buffer[i] = NULL; - if (NULL != q) - queue_destroy (q, GNUNET_YES); - else - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u %u\n", c, cinfo->send_buffer_n); + GNUNET_break (0); + return; } - GNUNET_free_non_null (cinfo->send_buffer); - if (GNUNET_SCHEDULER_NO_TASK != cinfo->fc_poll) + if (GNUNET_OK != + GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) { - GNUNET_SCHEDULER_cancel (cinfo->fc_poll); - cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; + GNUNET_break (0); + return; } - GNUNET_free (cinfo); - return GNUNET_YES; + t->client = c; } -/** - * Callback used to notify a client owner of a tunnel that a peer has - * disconnected, most likely because of a path change. - * - * @param cls Closure (tunnel this notification is about). - * @param peer_id Short ID of disconnected peer. - */ -void -tunnel_notify_client_peer_disconnected (void *cls, GNUNET_PEER_Id peer_id) -{ - struct MeshTunnel *t = cls; - struct MeshPeerInfo *peer; - struct MeshPathInfo *path_info; - - client_notify_peer_disconnected (t->owner, t, peer_id); - - peer = peer_info_get_short (peer_id); - path_info = GNUNET_malloc (sizeof (struct MeshPathInfo)); - path_info->peer = peer; - path_info->t = t; - peer->connect_task = GNUNET_SCHEDULER_add_now (&peer_info_connect_task, - path_info); -} - - -/** - * Add a peer to a tunnel, accomodating paths accordingly and initializing all - * needed rescources. - * If peer already exists, reevaluate shortest path and change if different. - * - * @param t Tunnel we want to add a new peer to - * @param peer PeerInfo of the peer being added - * - */ static void -tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer) +tunnel_use_path (struct MeshTunnel *t, struct MeshPeerPath *p) { - struct GNUNET_PeerIdentity id; - struct MeshPeerPath *best_p; - struct MeshPeerPath *p; - unsigned int best_cost; - unsigned int cost; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_peer\n"); - GNUNET_PEER_resolve (peer->id, &id); - if (GNUNET_NO == - GNUNET_CONTAINER_multihashmap_contains (t->peers, &id.hashPubKey)) - { - GNUNET_array_append (peer->tunnels, peer->ntunnels, t); - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (t->peers, &id.hashPubKey, - peer, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - } + unsigned int own_pos; - if (NULL != (p = peer->path_head)) + for (own_pos = 0; own_pos < p->length; own_pos++) { - best_p = p; - best_cost = tree_get_path_cost (t->tree, p); - while (NULL != p) - { - if ((cost = tree_get_path_cost (t->tree, p)) < best_cost) - { - best_cost = cost; - best_p = p; - } - p = p->next; - } - tree_add_path (t->tree, best_p, &tunnel_notify_client_peer_disconnected, t); - if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task) - t->path_refresh_task = - GNUNET_SCHEDULER_add_delayed (refresh_path_time, &path_refresh, t); + if (p->peers[own_pos] == myid) + break; } - else + if (own_pos > p->length - 1) { - /* Start a DHT get */ - peer_info_connect (peer, t); + GNUNET_break (0); + return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_peer END\n"); -} - -/** - * Add a path to a tunnel which we don't own, just to remember the next hop. - * If destination node was already in the tunnel, the first hop information - * will be replaced with the new path. - * - * @param t Tunnel we want to add a new peer to - * @param p Path to add - * @param own_pos Position of local node in path. - * - */ -static void -tunnel_add_path (struct MeshTunnel *t, struct MeshPeerPath *p, - unsigned int own_pos) -{ - struct GNUNET_PeerIdentity id; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_path\n"); - GNUNET_assert (0 != own_pos); - tree_add_path (t->tree, p, NULL, NULL); if (own_pos < p->length - 1) + t->next_hop = p->peers[own_pos + 1]; + else + t->next_hop = p->peers[own_pos]; + GNUNET_PEER_change_rc (t->next_hop, 1); + if (0 < own_pos) + t->prev_hop = p->peers[own_pos - 1]; + else + t->prev_hop = p->peers[0]; + GNUNET_PEER_change_rc (t->prev_hop, 1); + + if (NULL != t->path) + path_destroy (t->path); + t->path = path_duplicate (p); + if (0 == own_pos) { - GNUNET_PEER_resolve (p->peers[own_pos + 1], &id); - tree_update_first_hops (t->tree, myid, &id); + if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task) + GNUNET_SCHEDULER_cancel (t->maintenance_task); + t->maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_path_time, + &path_refresh, t); } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_add_path END\n"); -} - -/** - * Add a client to a tunnel, initializing all needed data structures. - * - * @param t Tunnel to which add the client. - * @param c Client which to add to the tunnel. - */ -static void -tunnel_add_client (struct MeshTunnel *t, struct MeshClient *c) -{ - struct MeshTunnelClientInfo clinfo; - - GNUNET_array_append (t->clients, t->nclients, c); - clinfo.fwd_ack = t->fwd_pid + 1; - clinfo.bck_ack = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE - 1; - clinfo.fwd_pid = t->fwd_pid; - clinfo.bck_pid = (uint32_t) -1; // Expected next: 0 - t->nclients--; - GNUNET_array_append (t->clients_fc, t->nclients, clinfo); } @@ -3125,452 +1892,27 @@ static GNUNET_PEER_Id tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1, GNUNET_PEER_Id p2) { - GNUNET_PEER_Id pid; - - pid = - tree_notify_connection_broken (t->tree, p1, p2, - &tunnel_notify_client_peer_disconnected, - t); - if (myid != p1 && myid != p2) - { - return pid; - } - if (pid != myid) - { - if (tree_get_predecessor (t->tree) != 0) - { - /* We are the peer still connected, notify owner of the disconnection. */ - struct GNUNET_MESH_PathBroken msg; - struct GNUNET_PeerIdentity neighbor; - - msg.header.size = htons (sizeof (msg)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN); - GNUNET_PEER_resolve (t->id.oid, &msg.oid); - msg.tid = htonl (t->id.tid); - msg.peer1 = my_full_id; - GNUNET_PEER_resolve (pid, &msg.peer2); - GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor); - send_prebuilt_message (&msg.header, &neighbor, t); - } - } - return pid; -} - - -/** - * 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 MeshData *mdata = cls; - struct MeshTransmissionDescriptor *info; - struct GNUNET_PeerIdentity neighbor; - struct GNUNET_MessageHeader *msg; - - info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor)); - - info->mesh_data = mdata; - (mdata->reference_counter) ++; - info->destination = neighbor_id; - GNUNET_PEER_resolve (neighbor_id, &neighbor); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending to %s...\n", - GNUNET_i2s (&neighbor)); - info->peer = peer_info_get (&neighbor); - GNUNET_assert (NULL != info->peer); - msg = (struct GNUNET_MessageHeader *) mdata->data; - queue_add(info, - ntohs (msg->type), - info->mesh_data->data_len, - info->peer, - mdata->t); -} - - -/** - * Queue a message in a tunnel in multicast, sending a copy to each child node - * down the local one in the tunnel tree. - * - * @param t Tunnel in which to send the data. - * @param msg Message to be sent. - */ -static void -tunnel_send_multicast (struct MeshTunnel *t, - const struct GNUNET_MessageHeader *msg) -{ - struct MeshData *mdata; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " sending a multicast packet...\n"); - - mdata = GNUNET_malloc (sizeof (struct MeshData)); - mdata->data_len = ntohs (msg->size); - mdata->t = t; - mdata->data = GNUNET_malloc (mdata->data_len); - memcpy (mdata->data, msg, mdata->data_len); - if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST) - { - struct GNUNET_MESH_Multicast *mcast; - - mcast = (struct GNUNET_MESH_Multicast *) mdata->data; - if (t->fwd_queue_n >= t->fwd_queue_max) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " queue full!\n"); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - " message from %s!\n", - GNUNET_i2s(&mcast->oid)); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - " message at %s!\n", - GNUNET_i2s(&my_full_id)); - GNUNET_free (mdata->data); - GNUNET_free (mdata); - return; - } - t->fwd_queue_n++; - mcast->ttl = htonl (ntohl (mcast->ttl) - 1); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " data packet, ttl: %u\n", - ntohl (mcast->ttl)); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not a data packet, no ttl\n"); - } - - tree_iterate_children (t->tree, &tunnel_send_multicast_iterator, mdata); - if (mdata->reference_counter == 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " no one to send data to\n"); - GNUNET_free (mdata->data); - GNUNET_free (mdata); - if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST) - t->fwd_queue_n--; - } - else - { - mdata->total_out = mdata->reference_counter; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " sending a multicast packet done\n"); - return; -} - - -/** - * Increase the SKIP value of all peers that - * have not received a unicast message. - * - * @param cls Closure (ID of the peer that HAS received the message). - * @param key ID of the neighbor. - * @param value Information about the neighbor. - * - * @return GNUNET_YES to keep iterating. - */ -static int -tunnel_add_skip (void *cls, - const struct GNUNET_HashCode * key, - void *value) -{ - struct GNUNET_PeerIdentity *neighbor = cls; - struct MeshTunnelChildInfo *cinfo = value; - - /* TODO compare only pointers? key == neighbor? */ - if (0 == memcmp (&neighbor->hashPubKey, key, sizeof (struct GNUNET_HashCode))) - { - return GNUNET_YES; - } - cinfo->skip++; - return GNUNET_YES; -} - - -/** - * @brief Get neighbor's Flow Control information. - * - * Retrieves the MeshTunnelChildInfo containing Flow Control data about a direct - * descendant of the local node in a certain tunnel. - * If the info is not yet there (recently created path), creates the data struct - * and inserts it into the tunnel info, initialized to the current tunnel ACK - * values. - * - * @param t Tunnel related. - * @param peer Neighbor whose Flow Control info is needed. - * - * @return Neighbor's Flow Control info. - */ -static struct MeshTunnelChildInfo * -tunnel_get_neighbor_fc (struct MeshTunnel *t, - const struct GNUNET_PeerIdentity *peer) -{ - struct MeshTunnelChildInfo *cinfo; - - if (NULL == t->children_fc) - return NULL; - - cinfo = GNUNET_CONTAINER_multihashmap_get (t->children_fc, - &peer->hashPubKey); - if (NULL == cinfo) - { - uint32_t delta; - - cinfo = GNUNET_malloc (sizeof (struct MeshTunnelChildInfo)); - cinfo->id = GNUNET_PEER_intern (peer); - cinfo->skip = t->fwd_pid; - cinfo->t = t; - - delta = t->nobuffer ? 1 : INITIAL_WINDOW_SIZE; - cinfo->fwd_ack = t->fwd_pid + delta; - cinfo->bck_ack = delta; - cinfo->bck_pid = -1; - - cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; - cinfo->fc_poll_time = GNUNET_TIME_UNIT_SECONDS; - - cinfo->send_buffer = - GNUNET_malloc (sizeof(struct MeshPeerQueue *) * t->fwd_queue_max); - - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (t->children_fc, - &peer->hashPubKey, - cinfo, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); - } - return cinfo; -} - - -/** - * Get the Flow Control info of a client. - * - * @param t Tunnel on which to look. - * @param c Client whose ACK to get. - * - * @return ACK value. - */ -static struct MeshTunnelClientInfo * -tunnel_get_client_fc (struct MeshTunnel *t, - struct MeshClient *c) -{ - unsigned int i; - - for (i = 0; i < t->nclients; i++) - { - if (t->clients[i] != c) - continue; - return &t->clients_fc[i]; - } - GNUNET_assert (0); - return NULL; // avoid compiler / coverity complaints -} - - -/** - * Iterator to get the appropiate ACK value from all children nodes. - * - * @param cls Closue (tunnel). - * @param id Id of the child node. - */ -static void -tunnel_get_child_fwd_ack (void *cls, - GNUNET_PEER_Id id) -{ - struct GNUNET_PeerIdentity peer_id; - struct MeshTunnelChildInfo *cinfo; - struct MeshTunnelChildIteratorContext *ctx = cls; - struct MeshTunnel *t = ctx->t; - uint32_t ack; - - GNUNET_PEER_resolve (id, &peer_id); - cinfo = tunnel_get_neighbor_fc (t, &peer_id); - ack = cinfo->fwd_ack; - - ctx->nchildren++; - if (GNUNET_NO == ctx->init) - { - ctx->max_child_ack = ack; - ctx->init = GNUNET_YES; - } - - if (GNUNET_YES == t->speed_min) - { - ctx->max_child_ack = ctx->max_child_ack > ack ? ack : ctx->max_child_ack; - } - else - { - ctx->max_child_ack = ctx->max_child_ack > ack ? ctx->max_child_ack : ack; - } - -} - - -/** - * Get the maximum PID allowed to transmit to any - * tunnel child of the local peer, depending on the tunnel - * buffering/speed settings. - * - * @param t Tunnel. - * - * @return Maximum PID allowed (uint32 MAX), -1LL if node has no children. - */ -static int64_t -tunnel_get_children_fwd_ack (struct MeshTunnel *t) -{ - struct MeshTunnelChildIteratorContext ctx; - ctx.t = t; - ctx.max_child_ack = 0; - ctx.nchildren = 0; - ctx.init = GNUNET_NO; - tree_iterate_children (t->tree, tunnel_get_child_fwd_ack, &ctx); - - if (0 == ctx.nchildren) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " tunnel has no children, no FWD ACK\n"); - return -1LL; - } - - if (GNUNET_YES == t->nobuffer && GMC_is_pid_bigger(ctx.max_child_ack, t->fwd_pid)) - ctx.max_child_ack = t->fwd_pid + 1; // Might overflow, it's ok. - - return (int64_t) ctx.max_child_ack; -} - - -/** - * Set the FWD ACK value of a client in a particular tunnel. - * - * @param t Tunnel affected. - * @param c Client whose ACK to set. - * @param ack ACK value. - */ -static void -tunnel_set_client_fwd_ack (struct MeshTunnel *t, - struct MeshClient *c, - uint32_t ack) -{ - unsigned int i; - - for (i = 0; i < t->nclients; i++) - { - if (t->clients[i] != c) - continue; - t->clients_fc[i].fwd_ack = ack; - return; - } - GNUNET_break (0); -} - - -/** - * Get the highest ACK value of all clients in a particular tunnel, - * according to the buffering/speed settings. - * - * @param t Tunnel on which to look. - * - * @return Corresponding ACK value (max uint32_t). - * If no clients are suscribed, -1LL. - */ -static int64_t -tunnel_get_clients_fwd_ack (struct MeshTunnel *t) -{ - unsigned int i; - int64_t ack; - - if (0 == t->nclients) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " tunnel has no clients, no FWD ACK\n"); - return -1LL; - } - - for (ack = -1LL, i = 0; i < t->nclients; i++) - { - if (-1LL == ack || - (GNUNET_YES == t->speed_min && - GNUNET_YES == GMC_is_pid_bigger (ack, t->clients_fc[i].fwd_ack)) || - (GNUNET_NO == t->speed_min && - GNUNET_YES == GMC_is_pid_bigger (t->clients_fc[i].fwd_ack, ack))) - { - ack = t->clients_fc[i].fwd_ack; - } - } - - if (GNUNET_YES == t->nobuffer && GMC_is_pid_bigger(ack, t->fwd_pid)) - ack = (uint32_t) t->fwd_pid + 1; // Might overflow, it's ok. - - return (uint32_t) ack; -} - - -/** - * Get the current fwd ack value for a tunnel, taking in account the tunnel - * mode and the status of all children nodes. - * - * @param t Tunnel. - * - * @return Maximum PID allowed. - */ -static uint32_t -tunnel_get_fwd_ack (struct MeshTunnel *t) -{ - uint32_t ack; - uint32_t count; - uint32_t buffer_free; - int64_t child_ack; - int64_t client_ack; - - count = t->fwd_pid - t->skip; - buffer_free = t->fwd_queue_max - t->fwd_queue_n; - child_ack = tunnel_get_children_fwd_ack (t); - client_ack = tunnel_get_clients_fwd_ack (t); - if (GNUNET_YES == t->nobuffer) - { - ack = count; - if (-1LL == child_ack) - child_ack = client_ack; - if (-1LL == child_ack) - { - GNUNET_break (0); - client_ack = child_ack = ack; - } - } - else - { - ack = count + buffer_free; // Overflow? OK! - } - if (-1LL == child_ack) - { - // Node has no children, child_ack AND core buffer are irrelevant. - if (-1LL == client_ack) // No children AND no clients? Not good! - { - GNUNET_STATISTICS_update (stats, "# mesh acks with no target", - 1, GNUNET_NO); - - } - return (uint32_t) client_ack; - } - if (-1LL == client_ack) - { - client_ack = ack; - } - if (GNUNET_YES == t->speed_min) - { - ack = GMC_min_pid ((uint32_t) child_ack, ack); - ack = GMC_min_pid ((uint32_t) client_ack, ack); - } - else - { - ack = GMC_max_pid ((uint32_t) child_ack, ack); - ack = GMC_max_pid ((uint32_t) client_ack, ack); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "c %u, bf %u, ch %lld, cl %lld, ACK: %u\n", - count, buffer_free, child_ack, client_ack, ack); - return ack; +// if (myid != p1 && myid != p2) FIXME +// { +// return; +// } +// +// if (tree_get_predecessor (t->tree) != 0) +// { +// /* We are the peer still connected, notify owner of the disconnection. */ +// struct GNUNET_MESH_PathBroken msg; +// struct GNUNET_PeerIdentity neighbor; +// +// msg.header.size = htons (sizeof (msg)); +// msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN); +// GNUNET_PEER_resolve (t->id.oid, &msg.oid); +// msg.tid = htonl (t->id.tid); +// msg.peer1 = my_full_id; +// GNUNET_PEER_resolve (pid, &msg.peer2); +// GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor); +// send_prebuilt_message (&msg.header, &neighbor, t); +// } + return 0; } @@ -3589,7 +1931,7 @@ send_local_ack (struct MeshTunnel *t, struct MeshClient *c, uint32_t ack) msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); msg.tunnel_id = htonl (t->owner == c ? t->local_tid : t->local_tid_dest); - msg.max_pid = htonl (ack); + msg.ack = htonl (ack); GNUNET_SERVER_notification_context_unicast(nc, c->handle, &msg.header, @@ -3604,7 +1946,7 @@ send_local_ack (struct MeshTunnel *t, struct MeshClient *c, uint32_t ack) * @param ack Value of the ACK. */ static void -send_ack (struct MeshTunnel *t, struct GNUNET_PeerIdentity *peer, uint32_t ack) +send_ack (struct MeshTunnel *t, GNUNET_PEER_Id peer, uint32_t ack) { struct GNUNET_MESH_ACK msg; @@ -3619,36 +1961,6 @@ send_ack (struct MeshTunnel *t, struct GNUNET_PeerIdentity *peer, uint32_t ack) /** - * Notify a the owner of a tunnel about how many more - * payload packages will we accept on a given tunnel. - * - * @param t Tunnel on which to send the ACK. - */ -static void -tunnel_send_client_fwd_ack (struct MeshTunnel *t) -{ - uint32_t ack; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending client FWD ACK on tunnel %X\n", - t->local_tid); - - ack = tunnel_get_fwd_ack (t); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack); - if (t->last_fwd_ack == ack) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " same as last, not sending!\n"); - return; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending!\n"); - t->last_fwd_ack = ack; - send_local_ack (t, t->owner, ack); -} - - -/** * Send an ACK informing the predecessor about the available buffer space. * In case there is no predecessor, inform the owning client. * If buffering is off, send only on behalf of children or self if endpoint. @@ -3662,19 +1974,12 @@ tunnel_send_client_fwd_ack (struct MeshTunnel *t) static void tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type) { - struct GNUNET_PeerIdentity id; uint32_t ack; - if (NULL != t->owner) - { - tunnel_send_client_fwd_ack (t); - return; - } - /* Is it after unicast / multicast retransmission? */ + /* Is it after unicast retransmission? */ switch (type) { case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ACK due to FWD DATA retransmission\n"); if (GNUNET_YES == t->nobuffer) @@ -3686,6 +1991,7 @@ tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type) case GNUNET_MESSAGE_TYPE_MESH_ACK: case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: break; + case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK: case GNUNET_MESSAGE_TYPE_MESH_POLL: t->force_ack = GNUNET_YES; break; @@ -3694,136 +2000,43 @@ tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type) } /* Check if we need to transmit the ACK */ - if (t->fwd_queue_max > t->fwd_queue_n * 4 && - GMC_is_pid_bigger(t->last_fwd_ack, t->fwd_pid) && + if (t->queue_max > t->next_fc.queue_n * 4 && + GMC_is_pid_bigger(t->prev_fc.last_ack_sent, t->prev_fc.last_pid_recv) && GNUNET_NO == t->force_ack) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " t->qmax: %u, t->qn: %u\n", - t->fwd_queue_max, t->fwd_queue_n); + t->queue_max, t->next_fc.queue_n); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " t->pid: %u, t->ack: %u\n", - t->fwd_pid, t->last_fwd_ack); + t->prev_fc.last_pid_recv, t->prev_fc.last_ack_sent); return; } /* Ok, ACK might be necessary, what PID to ACK? */ - ack = tunnel_get_fwd_ack (t); - - /* If speed_min and not all children have ack'd, dont send yet */ - if (ack == t->last_fwd_ack && GNUNET_NO == t->force_ack) + ack = t->prev_fc.last_pid_recv + t->queue_max - t->next_fc.queue_n; + if (ack == t->prev_fc.last_ack_sent && GNUNET_NO == t->force_ack) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not ready\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n"); return; } - t->last_fwd_ack = ack; - GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id); - send_ack (t, &id, ack); + t->prev_fc.last_ack_sent = ack; + if (NULL != t->owner) + send_local_ack (t, t->owner, ack); + else if (0 != t->prev_hop) + send_ack (t, t->prev_hop, ack); + else + GNUNET_break (0); debug_fwd_ack++; t->force_ack = GNUNET_NO; } /** - * Iterator to send a child node a BCK ACK to allow him to send more - * to_origin data. - * - * @param cls Closure (tunnel). - * @param id Id of the child node. - */ -static void -tunnel_send_child_bck_ack (void *cls, - GNUNET_PEER_Id id) -{ - struct MeshTunnel *t = cls; - struct MeshTunnelChildInfo *cinfo; - struct GNUNET_PeerIdentity peer; - uint32_t ack; - - GNUNET_PEER_resolve (id, &peer); - cinfo = tunnel_get_neighbor_fc (t, &peer); - ack = cinfo->bck_pid + t->bck_queue_max - t->bck_queue_n; - - if (cinfo->bck_ack == ack && GNUNET_NO == t->force_ack) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Not sending ACK, not needed\n"); - return; - } - cinfo->bck_ack = ack; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Sending BCK ACK %u (last sent: %u)\n", - ack, cinfo->bck_ack); - send_ack (t, &peer, ack); -} - - -/** - * @brief Send BCK ACKs to clients to allow them more to_origin traffic - * - * Iterates over all clients and sends BCK ACKs to the ones that need it. - * - * FIXME fc: what happens if we have 2 clients but q_size is 1? - * - implement a size 1 buffer in each client_fc AND children_fc - * to hold at least 1 message per "child". - * problem: violates no buffer policy - * - ack 0 and make "children" poll for transmission slots - * problem: big overhead, extra latency even in low traffic - * settings - * - * @param t Tunnel on which to send the BCK ACKs. - */ -static void -tunnel_send_clients_bck_ack (struct MeshTunnel *t) -{ - unsigned int i; - unsigned int tunnel_delta; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Sending BCK ACK to clients\n"); - - tunnel_delta = t->bck_queue_max - t->bck_queue_n; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " tunnel delta: %u\n", tunnel_delta); - - /* Find client whom to allow to send to origin (with lowest buffer space) */ - for (i = 0; i < t->nclients; i++) - { - struct MeshTunnelClientInfo *clinfo; - unsigned int delta; - - clinfo = &t->clients_fc[i]; - delta = clinfo->bck_ack - clinfo->bck_pid; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client %u delta: %u\n", - t->clients[i]->id, delta); - - if ((GNUNET_NO == t->nobuffer && tunnel_delta > delta) || - (GNUNET_YES == t->nobuffer && 0 == delta)) - { - uint32_t ack; - - ack = clinfo->bck_pid; - ack += t->nobuffer ? 1 : tunnel_delta; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " sending ack to client %u: %u\n", - t->clients[i]->id, ack); - send_local_ack (t, t->clients[i], ack); - clinfo->bck_ack = ack; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " not sending ack to client %u (td %u, d %u)\n", - t->clients[i]->id, tunnel_delta, delta); - } - } -} - - -/** - * Send an ACK informing the children nodes and destination clients about - * the available buffer space. + * Send an ACK informing the children node/client about the available + * buffer space. * If buffering is off, send only on behalf of root (can be self). * If buffering is on, send when sent to predecessor and buffer space is free. * Note that although the name is bck_ack, the BCK mean backwards *traffic*, @@ -3835,6 +2048,7 @@ tunnel_send_clients_bck_ack (struct MeshTunnel *t) static void tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type) { + uint32_t ack; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending BCK ACK on tunnel %u [%u] due to %s\n", t->id.oid, t->id.tid, GNUNET_MESH_DEBUG_M2S(type)); @@ -3845,13 +2059,14 @@ tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type) if (GNUNET_YES == t->nobuffer) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Not sending ACK, nobuffer\n"); + " Not sending ACK, nobuffer + traffic\n"); return; } break; case GNUNET_MESSAGE_TYPE_MESH_ACK: case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: break; + case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK: case GNUNET_MESSAGE_TYPE_MESH_POLL: t->force_ack = GNUNET_YES; break; @@ -3859,35 +2074,120 @@ tunnel_send_bck_ack (struct MeshTunnel *t, uint16_t type) GNUNET_break (0); } - tunnel_send_clients_bck_ack (t); - tree_iterate_children (t->tree, &tunnel_send_child_bck_ack, t); + /* TODO: Check if we need to transmit the ACK (as in fwd) */ + + ack = t->next_fc.last_pid_recv + t->queue_max - t->prev_fc.queue_n; + + if (t->next_fc.last_ack_sent == ack && GNUNET_NO == t->force_ack) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + " Not sending ACK, not needed, last ack sent was %u\n", + t->next_fc.last_ack_sent); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + " Sending BCK ACK %u (last sent: %u)\n", + ack, t->next_fc.last_ack_sent); + t->next_fc.last_ack_sent = ack; + + if (NULL != t->client) + send_local_ack (t, t->client, ack); + else if (0 != t->next_hop) + send_ack (t, t->next_hop, ack); + else + GNUNET_break (0); t->force_ack = GNUNET_NO; } /** + * Modify the unicast message TID from global to local and send to client. + * + * @param t Tunnel on which to send the message. + * @param msg Message to modify and send. + */ +static void +tunnel_send_client_ucast (struct MeshTunnel *t, + const struct GNUNET_MESH_Data *msg) +{ + struct GNUNET_MESH_Data *copy; + uint16_t size = ntohs (msg->header.size); + char cbuf[size]; + + if (size < sizeof (struct GNUNET_MESH_Data) + + sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break_op (0); + return; + } + if (NULL == t->client) + { + GNUNET_break (0); + return; + } + copy = (struct GNUNET_MESH_Data *) cbuf; + memcpy (copy, msg, size); + copy->tid = htonl (t->local_tid_dest); + GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, + ©->header, GNUNET_NO); +} + + +/** + * Modify the to_origin message TID from global to local and send to client. + * + * @param t Tunnel on which to send the message. + * @param msg Message to modify and send. + */ +static void +tunnel_send_client_to_orig (struct MeshTunnel *t, + const struct GNUNET_MESH_Data *msg) +{ + struct GNUNET_MESH_Data *copy; + uint16_t size = ntohs (msg->header.size); + char cbuf[size]; + + if (size < sizeof (struct GNUNET_MESH_Data) + + sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break_op (0); + return; + } + if (NULL == t->owner) + { + GNUNET_break (0); + return; + } + copy = (struct GNUNET_MESH_Data *) cbuf; + memcpy (cbuf, msg, size); + copy->tid = htonl (t->local_tid); + GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, + ©->header, GNUNET_NO); +} + + +/** * @brief Re-initiate traffic to this peer if necessary. * * Check if there is traffic queued towards this peer * and the core transmit handle is NULL (traffic was stalled). * If so, call core tmt rdy. * - * @param cls Closure (unused) * @param peer_id Short ID of peer to which initiate traffic. */ static void -peer_unlock_queue(void *cls, GNUNET_PEER_Id peer_id) +peer_unlock_queue(GNUNET_PEER_Id peer_id) { struct MeshPeerInfo *peer; struct GNUNET_PeerIdentity id; struct MeshPeerQueue *q; size_t size; - peer = peer_info_get_short(peer_id); + peer = peer_get_short (peer_id); if (NULL != peer->core_transmit) return; - q = queue_get_next(peer); + q = queue_get_next (peer); if (NULL == q) { /* Might br multicast traffic already sent to this particular peer but @@ -3913,50 +2213,14 @@ peer_unlock_queue(void *cls, GNUNET_PEER_Id peer_id) /** - * @brief Allow transmission of FWD traffic on this tunnel - * - * Check if there is traffic queued towards any children - * and the core transmit handle is NULL, and if so, call core tmt rdy. - * - * @param t Tunnel on which to unlock FWD traffic. - */ -static void -tunnel_unlock_fwd_queues (struct MeshTunnel *t) -{ - if (0 == t->fwd_queue_n) - return; - - tree_iterate_children (t->tree, &peer_unlock_queue, NULL); -} - - -/** - * @brief Allow transmission of BCK traffic on this tunnel + * Send a message to all peers and clients in this tunnel that the tunnel + * is no longer valid. If some peer or client should not receive the message, + * should be zero'ed out before calling this function. * - * Check if there is traffic queued towards the root of the tree - * and the core transmit handle is NULL, and if so, call core tmt rdy. - * - * @param t Tunnel on which to unlock BCK traffic. + * @param t The tunnel whose peers and clients to notify. */ static void -tunnel_unlock_bck_queue (struct MeshTunnel *t) -{ - if (0 == t->bck_queue_n) - return; - - peer_unlock_queue(NULL, tree_get_predecessor(t->tree)); -} - - -/** - * Send a message to all peers in this tunnel that the tunnel is no longer - * valid. - * - * @param t The tunnel whose peers to notify. - * @param parent ID of the parent, in case the tree is already destroyed. - */ -static void -tunnel_send_destroy (struct MeshTunnel *t, GNUNET_PEER_Id parent) +tunnel_send_destroy (struct MeshTunnel *t) { struct GNUNET_MESH_TunnelDestroy msg; struct GNUNET_PeerIdentity id; @@ -3968,50 +2232,61 @@ tunnel_send_destroy (struct MeshTunnel *t, GNUNET_PEER_Id parent) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending tunnel destroy for tunnel: %s [%X]\n", GNUNET_i2s (&msg.oid), t->id.tid); - if (tree_count_children(t->tree) > 0) + + if (NULL == t->client && 0 != t->next_hop) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending multicast to children\n"); - tunnel_send_multicast (t, &msg.header); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " child: %u\n", t->next_hop); + GNUNET_PEER_resolve (t->next_hop, &id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + " sending forward to %s\n", + GNUNET_i2s (&id)); + send_prebuilt_message (&msg.header, t->next_hop, t); + } + if (NULL == t->owner && 0 != t->prev_hop) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " parent: %u\n", t->prev_hop); + GNUNET_PEER_resolve (t->prev_hop, &id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + " sending back to %s\n", + GNUNET_i2s (&id)); + send_prebuilt_message (&msg.header, t->prev_hop, t); + } + if (NULL != t->owner) + { + send_client_tunnel_destroy (t->owner, t); + } + if (NULL != t->client) + { + send_client_tunnel_destroy (t->client, t); } - if (0 == parent) - parent = tree_get_predecessor (t->tree); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " parent: %u\n", parent); - if (0 == parent) - return; - - GNUNET_PEER_resolve (parent, &id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " sending back to %s\n", - GNUNET_i2s (&id)); - send_prebuilt_message (&msg.header, &id, t); } /** - * Cancel all transmissions towards a neighbor that belong to a certain tunnel. + * Cancel all transmissions towards a neighbor that belongs to a certain tunnel. * - * @param cls Closure (Tunnel which to cancel). - * @param neighbor_id Short ID of the neighbor to whom cancel the transmissions. + * @param t Tunnel which to cancel. + * @param neighbor Short ID of the neighbor to whom cancel the transmissions. */ static void -tunnel_cancel_queues (void *cls, GNUNET_PEER_Id neighbor_id) +peer_cancel_queues (GNUNET_PEER_Id neighbor, struct MeshTunnel *t) { - struct MeshTunnel *t = cls; struct MeshPeerInfo *peer_info; struct MeshPeerQueue *pq; struct MeshPeerQueue *next; - peer_info = peer_info_get_short (neighbor_id); + if (0 == neighbor) + return; /* Was local peer, 0'ed in tunnel_destroy_iterator */ + peer_info = peer_get_short (neighbor); for (pq = peer_info->queue_head; NULL != pq; pq = next) { next = pq->next; if (pq->tunnel == t) { - if (GNUNET_MESSAGE_TYPE_MESH_MULTICAST == pq->type || - GNUNET_MESSAGE_TYPE_MESH_UNICAST == pq->type || + if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == pq->type || GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == pq->type) { - // Should have been removed on destroy children + /* Should have been removed on destroy children */ GNUNET_break (0); } queue_destroy (pq, GNUNET_YES); @@ -4024,8 +2299,16 @@ tunnel_cancel_queues (void *cls, GNUNET_PEER_Id neighbor_id) } } + /** - * Destroy the tunnel and free any allocated resources linked to it. + * Destroy the tunnel. + * + * This function does not generate any warning traffic to clients or peers. + * + * Tasks: + * Remove the tunnel from peer_info's and clients' hashmaps. + * Cancel messages belonging to this tunnel queued to neighbors. + * Free any allocated resources linked to the tunnel. * * @param t the tunnel to destroy * @@ -4036,7 +2319,6 @@ tunnel_destroy (struct MeshTunnel *t) { struct MeshClient *c; struct GNUNET_HashCode hash; - unsigned int i; int r; if (NULL == t) @@ -4065,7 +2347,7 @@ tunnel_destroy (struct MeshTunnel *t) if (NULL != c) { - GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); + GMC_hash32 (t->local_tid, &hash); if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (c->own_tunnels, &hash, t)) { @@ -4074,86 +2356,58 @@ tunnel_destroy (struct MeshTunnel *t) } } - GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); - for (i = 0; i < t->nclients; i++) + if (NULL != t->client) { - c = t->clients[i]; + c = t->client; + GMC_hash32 (t->local_tid_dest, &hash); if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (c->incoming_tunnels, &hash, t)) { GNUNET_break (0); r = GNUNET_SYSERR; } - } - for (i = 0; i < t->nignore; i++) - { - c = t->ignore[i]; - if (GNUNET_YES != - GNUNET_CONTAINER_multihashmap_remove (c->ignore_tunnels, &hash, t)) + if (GNUNET_YES != + GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t)) { GNUNET_break (0); r = GNUNET_SYSERR; } } - (void) GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t); - GNUNET_free_non_null (t->clients); - GNUNET_free_non_null (t->ignore); - GNUNET_free_non_null (t->clients_fc); - - if (NULL != t->peers) + if (0 != t->prev_hop) { - GNUNET_CONTAINER_multihashmap_iterate (t->peers, &peer_info_delete_tunnel, - t); - GNUNET_CONTAINER_multihashmap_destroy (t->peers); + peer_cancel_queues (t->prev_hop, t); + GNUNET_PEER_change_rc (t->prev_hop, -1); + } + if (0 != t->next_hop) + { + peer_cancel_queues (t->next_hop, t); + GNUNET_PEER_change_rc (t->next_hop, -1); + } + if (0 != t->dest) { + peer_info_remove_tunnel (peer_get_short (t->dest), t); } - GNUNET_CONTAINER_multihashmap_iterate (t->children_fc, - &tunnel_destroy_child, - t); - GNUNET_CONTAINER_multihashmap_destroy (t->children_fc); - t->children_fc = NULL; - - tree_iterate_children (t->tree, &tunnel_cancel_queues, t); - tree_destroy (t->tree); - - if (NULL != t->regex_search) - GNUNET_REGEX_search_cancel (t->regex_search->search_handle); - if (NULL != t->dht_get_type) - GNUNET_DHT_get_stop (t->dht_get_type); - if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task) - GNUNET_SCHEDULER_cancel (t->timeout_task); - if (GNUNET_SCHEDULER_NO_TASK != t->path_refresh_task) - GNUNET_SCHEDULER_cancel (t->path_refresh_task); + if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task) + GNUNET_SCHEDULER_cancel (t->maintenance_task); n_tunnels--; GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO); + path_destroy (t->path); GNUNET_free (t); return r; } -#define TUNNEL_DESTROY_EMPTY_TIME GNUNET_TIME_UNIT_MILLISECONDS - /** * Tunnel is empty: destroy it. * - * @param cls Closure (Tunnel). - * @param tc TaskContext. + * Notifies all participants (peers, cleints) about the destruction. + * + * @param t Tunnel to destroy. */ static void -tunnel_destroy_empty_delayed (void *cls, - const struct GNUNET_SCHEDULER_TaskContext *tc) +tunnel_destroy_empty (struct MeshTunnel *t) { - struct MeshTunnel *t = cls; - - t->delayed_destroy = GNUNET_SCHEDULER_NO_TASK; - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - return; - - if (0 != t->nclients || - 0 != tree_count_children (t->tree)) - return; - #if MESH_DEBUG { struct GNUNET_PeerIdentity id; @@ -4165,50 +2419,31 @@ tunnel_destroy_empty_delayed (void *cls, } #endif - tunnel_send_destroy (t, 0); + if (GNUNET_NO == t->destroy) + tunnel_send_destroy (t); if (0 == t->pending_messages) tunnel_destroy (t); else t->destroy = GNUNET_YES; } - /** - * Schedule tunnel destruction if is empty and no new traffic comes in a time. + * Initialize a Flow Control structure to the initial state. * - * @param t Tunnel to destroy if empty. + * @param fc Flow Control structure to initialize. */ static void -tunnel_destroy_empty (struct MeshTunnel *t) +fc_init (struct MeshFlowControl *fc) { - if (GNUNET_SCHEDULER_NO_TASK != t->delayed_destroy || - 0 != t->nclients || - 0 != tree_count_children (t->tree)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "%u %u %u\n", - t->delayed_destroy, t->nclients, tree_count_children(t->tree)); - return; - } - - #if MESH_DEBUG - { - struct GNUNET_PeerIdentity id; - - GNUNET_PEER_resolve (t->id.oid, &id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "scheduling destruction of empty tunnel %s [%X]\n", - GNUNET_i2s (&id), t->id.tid); - } - #endif - - t->delayed_destroy = - GNUNET_SCHEDULER_add_delayed (TUNNEL_DESTROY_EMPTY_TIME, - &tunnel_destroy_empty_delayed, - t); + fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */ + fc->last_pid_recv = (uint32_t) -1; + fc->last_ack_sent = (uint32_t) -1; /* No traffic allowed yet */ + fc->last_ack_recv = (uint32_t) -1; + fc->poll_task = GNUNET_SCHEDULER_NO_TASK; + fc->poll_time = GNUNET_TIME_UNIT_SECONDS; + fc->queue_n = 0; } - /** * Create a new tunnel * @@ -4234,16 +2469,11 @@ tunnel_new (GNUNET_PEER_Id owner, t = GNUNET_malloc (sizeof (struct MeshTunnel)); t->id.oid = owner; t->id.tid = tid; - t->fwd_queue_max = (max_msgs_queue / max_tunnels) + 1; - t->bck_queue_max = t->fwd_queue_max; - t->tree = tree_new (owner); + t->queue_max = (max_msgs_queue / max_tunnels) + 1; t->owner = client; - t->fwd_pid = (uint32_t) -1; // Next (expected) = 0 - t->bck_pid = (uint32_t) -1; // Next (expected) = 0 - t->bck_ack = INITIAL_WINDOW_SIZE - 1; - t->last_fwd_ack = INITIAL_WINDOW_SIZE - 1; + fc_init (&t->next_fc); + fc_init (&t->prev_fc); t->local_tid = local; - t->children_fc = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); n_tunnels++; GNUNET_STATISTICS_update (stats, "# tunnels", 1, GNUNET_NO); @@ -4264,7 +2494,7 @@ tunnel_new (GNUNET_PEER_Id owner, if (NULL != client) { - GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash); + GMC_hash32 (t->local_tid, &hash); if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (client->own_tunnels, &hash, t, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) @@ -4279,52 +2509,14 @@ tunnel_new (GNUNET_PEER_Id owner, return t; } -/** - * Callback when removing children from a tunnel tree. Notify owner. - * - * @param cls Closure (tunnel). - * @param peer_id Short ID of the peer deleted. - */ -void -tunnel_child_removed (void *cls, GNUNET_PEER_Id peer_id) -{ - struct MeshTunnel *t = cls; - - client_notify_peer_disconnected (t->owner, t, peer_id); -} - -/** - * Removes an explicit path from a tunnel, freeing all intermediate nodes - * that are no longer needed, as well as nodes of no longer reachable peers. - * The tunnel itself is also destoyed if results in a remote empty tunnel. - * - * @param t Tunnel from which to remove the path. - * @param peer Short id of the peer which should be removed. - */ -static void -tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer) -{ - int r; - - r = tree_del_peer (t->tree, peer, &tunnel_child_removed, t); - if (GNUNET_NO == r) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Tunnel %u [%u] has no more nodes\n", - t->id.oid, t->id.tid); - } -} /** - * tunnel_destroy_iterator: iterator for deleting each tunnel that belongs to a - * client when the client disconnects. If the client is not the owner, the - * owner will get notified if no more clients are in the tunnel and the client - * get removed from the tunnel's list. + * Iterator for deleting each tunnel whose client endpoint disconnected. * - * @param cls closure (client that is disconnecting) - * @param key the hash of the local tunnel id (used to access the hashmap) - * @param value the value stored at the key (tunnel to destroy) + * @param cls Closure (client that has disconnected). + * @param key The hash of the local tunnel id (used to access the hashmap). + * @param value The value stored at the key (tunnel to destroy). * * @return GNUNET_OK, keep iterating. */ @@ -4336,18 +2528,33 @@ tunnel_destroy_iterator (void *cls, struct MeshTunnel *t = value; struct MeshClient *c = cls; - send_client_tunnel_disconnect (t, c); - if (c != t->owner) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + " Tunnel %X / %X destroy, due to client %u shutdown.\n", + t->local_tid, t->local_tid_dest, c->id); + client_delete_tunnel (c, t); + if (c == t->client) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %u is destination.\n", c->id); - tunnel_delete_client (t, c); - client_delete_tunnel (c, t); - tunnel_destroy_empty (t); - return GNUNET_OK; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is destination.\n", c->id); + t->client = NULL; + if (0 != t->next_hop) { /* destroy could come before a path is used */ + GNUNET_PEER_change_rc (t->next_hop, -1); + t->next_hop = 0; + } + } + else if (c == t->owner) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Client %u is owner.\n", c->id); + t->owner = NULL; + if (0 != t->prev_hop) { /* destroy could come before a path is used */ + GNUNET_PEER_change_rc (t->prev_hop, -1); + t->prev_hop = 0; + } } - tunnel_send_destroy (t, 0); - t->owner = NULL; - t->destroy = GNUNET_YES; + else + { + GNUNET_break (0); + } + tunnel_destroy_empty (t); return GNUNET_OK; } @@ -4365,17 +2572,19 @@ tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct MeshTunnel *t = cls; struct GNUNET_PeerIdentity id; - t->timeout_task = GNUNET_SCHEDULER_NO_TASK; + t->maintenance_task = GNUNET_SCHEDULER_NO_TASK; if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) return; GNUNET_PEER_resolve(t->id.oid, &id); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Tunnel %s [%X] timed out. Destroying.\n", GNUNET_i2s(&id), t->id.tid); - send_clients_tunnel_destroy (t); - tunnel_destroy (t); + if (NULL != t->client) + send_client_tunnel_destroy (t->client, t); + tunnel_destroy (t); /* Do not notify other */ } + /** * Resets the tunnel timeout. Starts it if no timeout was running. * @@ -4386,9 +2595,11 @@ tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void tunnel_reset_timeout (struct MeshTunnel *t) { - if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task) - GNUNET_SCHEDULER_cancel (t->timeout_task); - t->timeout_task = + if (NULL != t->owner || 0 != t->local_tid || 0 == t->prev_hop) + return; + if (GNUNET_SCHEDULER_NO_TASK != t->maintenance_task) + GNUNET_SCHEDULER_cancel (t->maintenance_task); + t->maintenance_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (refresh_path_time, 4), &tunnel_timeout, t); } @@ -4409,18 +2620,17 @@ tunnel_reset_timeout (struct MeshTunnel *t) static size_t send_core_path_create (void *cls, size_t size, void *buf) { - struct MeshPathInfo *info = cls; - struct GNUNET_MESH_ManipulatePath *msg; + struct MeshTunnel *t = cls; + struct GNUNET_MESH_CreateTunnel *msg; struct GNUNET_PeerIdentity *peer_ptr; - struct MeshTunnel *t = info->t; - struct MeshPeerPath *p = info->path; + struct MeshPeerPath *p = t->path; size_t size_needed; uint32_t opt; int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATE PATH sending...\n"); size_needed = - sizeof (struct GNUNET_MESH_ManipulatePath) + + sizeof (struct GNUNET_MESH_CreateTunnel) + p->length * sizeof (struct GNUNET_PeerIdentity); if (size < size_needed || NULL == buf) @@ -4428,18 +2638,16 @@ send_core_path_create (void *cls, size_t size, void *buf) GNUNET_break (0); return 0; } - msg = (struct GNUNET_MESH_ManipulatePath *) buf; + msg = (struct GNUNET_MESH_CreateTunnel *) buf; msg->header.size = htons (size_needed); msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE); msg->tid = ntohl (t->id.tid); opt = 0; - if (GNUNET_YES == t->speed_min) - opt |= MESH_TUNNEL_OPT_SPEED_MIN; if (GNUNET_YES == t->nobuffer) opt |= MESH_TUNNEL_OPT_NOBUFFER; - msg->opt = htonl(opt); - msg->reserved = 0; + msg->opt = htonl (opt); + msg->port = htonl (t->port); peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1]; for (i = 0; i < p->length; i++) @@ -4447,9 +2655,6 @@ send_core_path_create (void *cls, size_t size, void *buf) GNUNET_PEER_resolve (p->peers[i], peer_ptr++); } - path_destroy (p); - GNUNET_free (info); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATE PATH (%u bytes long) sent!\n", size_needed); return size_needed; @@ -4457,65 +2662,6 @@ send_core_path_create (void *cls, size_t size, void *buf) /** - * Fill the core buffer - * - * @param cls closure (data itself) - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * - * @return number of bytes written to buf - */ -static size_t -send_core_data_multicast (void *cls, size_t size, void *buf) -{ - struct MeshTransmissionDescriptor *info = cls; - size_t total_size; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Multicast callback.\n"); - GNUNET_assert (NULL != info); - GNUNET_assert (NULL != info->peer); - total_size = info->mesh_data->data_len; - GNUNET_assert (total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE); - - if (total_size > size) - { - GNUNET_break (0); - return 0; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " copying data...\n"); - memcpy (buf, info->mesh_data->data, total_size); -#if MESH_DEBUG - { - struct GNUNET_MESH_Multicast *mc; - struct GNUNET_MessageHeader *mh; - - mh = buf; - if (ntohs (mh->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST) - { - mc = (struct GNUNET_MESH_Multicast *) mh; - mh = (struct GNUNET_MessageHeader *) &mc[1]; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " multicast, payload type %s\n", - GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " multicast, payload size %u\n", ntohs (mh->size)); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type %s\n", - GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); - } - } -#endif - data_descriptor_decrement_rc (info->mesh_data); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "freeing info...\n"); - GNUNET_free (info); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "return %u\n", total_size); - return total_size; -} - - -/** * Creates a path ack message in buf and frees all unused resources. * * @param cls closure (MeshTransmissionDescriptor) @@ -4526,22 +2672,23 @@ 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 MeshTransmissionDescriptor *info = cls; + struct MeshTunnel *t = cls; struct GNUNET_MESH_PathACK *msg = buf; - GNUNET_assert (NULL != info); + GNUNET_assert (NULL != t); if (sizeof (struct GNUNET_MESH_PathACK) > size) { GNUNET_break (0); return 0; } + t->prev_fc.last_ack_sent = t->nobuffer ? 0 : t->queue_max - 1; msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK); - GNUNET_PEER_resolve (info->origin->oid, &msg->oid); - msg->tid = htonl (info->origin->tid); + GNUNET_PEER_resolve (t->id.oid, &msg->oid); + msg->tid = htonl (t->id.tid); msg->peer_id = my_full_id; + msg->ack = htonl (t->prev_fc.last_ack_sent); - GNUNET_free (info); /* TODO add signature */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH ACK sent!\n"); @@ -4559,12 +2706,7 @@ send_core_path_ack (void *cls, size_t size, void *buf) static void queue_destroy (struct MeshPeerQueue *queue, int clear_cls) { - struct MeshTransmissionDescriptor *dd; - struct MeshPathInfo *path_info; - struct MeshTunnelChildInfo *cinfo; - struct GNUNET_PeerIdentity id; - unsigned int i; - unsigned int max; + struct MeshFlowControl *fc; if (GNUNET_YES == clear_cls) { @@ -4575,7 +2717,6 @@ queue_destroy (struct MeshPeerQueue *queue, int clear_cls) GNUNET_break (GNUNET_YES == queue->tunnel->destroy); /* fall through */ case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: case GNUNET_MESSAGE_TYPE_MESH_ACK: case GNUNET_MESSAGE_TYPE_MESH_POLL: @@ -4584,20 +2725,16 @@ queue_destroy (struct MeshPeerQueue *queue, int clear_cls) " prebuilt message\n"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type %s\n", - GNUNET_MESH_DEBUG_M2S(queue->type)); - dd = queue->cls; - data_descriptor_decrement_rc (dd->mesh_data); + GNUNET_MESH_DEBUG_M2S (queue->type)); break; case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type create path\n"); - path_info = queue->cls; - path_destroy (path_info->path); break; default: GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " type %s unknown!\n", - GNUNET_MESH_DEBUG_M2S(queue->type)); + GNUNET_MESH_DEBUG_M2S (queue->type)); } GNUNET_free_non_null (queue->cls); } @@ -4605,36 +2742,21 @@ queue_destroy (struct MeshPeerQueue *queue, int clear_cls) queue->peer->queue_tail, queue); - /* Delete from child_fc in the appropiate tunnel */ - max = queue->tunnel->fwd_queue_max; - GNUNET_PEER_resolve (queue->peer->id, &id); - cinfo = tunnel_get_neighbor_fc (queue->tunnel, &id); - if (NULL != cinfo) + /* Delete from appropriate fc in the tunnel */ + if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == queue->type || + GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == queue->type ) { - for (i = 0; i < cinfo->send_buffer_n; i++) + if (queue->peer->id == queue->tunnel->prev_hop) + fc = &queue->tunnel->prev_fc; + else if (queue->peer->id == queue->tunnel->next_hop) + fc = &queue->tunnel->next_fc; + else { - unsigned int i2; - i2 = (cinfo->send_buffer_start + i) % max; - if (cinfo->send_buffer[i2] == queue) - { - /* Found corresponding entry in the send_buffer. Move all others back. */ - unsigned int j; - unsigned int j2; - unsigned int j3; - - for (j = i, j2 = 0, j3 = 0; j < cinfo->send_buffer_n - 1; j++) - { - j2 = (cinfo->send_buffer_start + j) % max; - j3 = (cinfo->send_buffer_start + j + 1) % max; - cinfo->send_buffer[j2] = cinfo->send_buffer[j3]; - } - - cinfo->send_buffer[j3] = NULL; - cinfo->send_buffer_n--; - } + GNUNET_break (0); + return; } + fc->queue_n--; } - GNUNET_free (queue); } @@ -4654,308 +2776,220 @@ struct MeshPeerQueue * queue_get_next (const struct MeshPeerInfo *peer) { struct MeshPeerQueue *q; - struct MeshTunnel *t; - struct MeshTransmissionDescriptor *info; - struct MeshTunnelChildInfo *cinfo; - struct GNUNET_MESH_Unicast *ucast; - struct GNUNET_MESH_ToOrigin *to_orig; - struct GNUNET_MESH_Multicast *mcast; - struct GNUNET_PeerIdentity id; + + struct GNUNET_MESH_Data *dmsg; + struct MeshTunnel* t; uint32_t pid; uint32_t ack; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* selecting message\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* selecting message\n"); for (q = peer->queue_head; NULL != q; q = q->next) { t = q->tunnel; - info = q->cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* %s\n", - GNUNET_MESH_DEBUG_M2S(q->type)); + "* %s\n", + GNUNET_MESH_DEBUG_M2S (q->type)); + dmsg = (struct GNUNET_MESH_Data *) q->cls; + pid = ntohl (dmsg->pid); switch (q->type) { case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - ucast = (struct GNUNET_MESH_Unicast *) info->mesh_data->data; - pid = ntohl (ucast->pid); - GNUNET_PEER_resolve (info->peer->id, &id); - cinfo = tunnel_get_neighbor_fc(t, &id); - ack = cinfo->fwd_ack; + ack = t->next_fc.last_ack_recv; break; case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - to_orig = (struct GNUNET_MESH_ToOrigin *) info->mesh_data->data; - pid = ntohl (to_orig->pid); - ack = t->bck_ack; - break; - case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: - mcast = (struct GNUNET_MESH_Multicast *) info->mesh_data->data; - if (GNUNET_MESSAGE_TYPE_MESH_MULTICAST != ntohs(mcast->header.type)) - { - // Not a multicast payload: multicast control traffic (destroy, etc) - return q; - } - pid = ntohl (mcast->pid); - GNUNET_PEER_resolve (info->peer->id, &id); - cinfo = tunnel_get_neighbor_fc(t, &id); - ack = cinfo->fwd_ack; + ack = t->prev_fc.last_ack_recv; break; default: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* OK!\n"); + "* OK!\n"); return q; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* ACK: %u, PID: %u\n", - ack, pid); - if (GNUNET_NO == GMC_is_pid_bigger(pid, ack)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "* ACK: %u, PID: %u\n", + ack, pid); + if (GNUNET_NO == GMC_is_pid_bigger (pid, ack)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* OK!\n"); + "* OK!\n"); return q; } else { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* NEXT!\n"); + "* NEXT!\n"); } } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* nothing found\n"); + "* nothing found\n"); return NULL; } -/** - * Core callback to write a queued packet to core buffer - * - * @param cls Closure (peer info). - * @param size Number of bytes available in buf. - * @param buf Where the to write the message. - * - * @return number of bytes written to buf - */ static size_t queue_send (void *cls, size_t size, void *buf) { - struct MeshPeerInfo *peer = cls; - struct GNUNET_MessageHeader *msg; - struct MeshPeerQueue *queue; - struct MeshTunnel *t; - struct MeshTunnelChildInfo *cinfo; - struct GNUNET_PeerIdentity dst_id; - size_t data_size; - - peer->core_transmit = NULL; - cinfo = NULL; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* Queue send\n"); - queue = queue_get_next (peer); - - /* Queue has no internal mesh traffic nor sendable payload */ - if (NULL == queue) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* not ready, return\n"); - if (NULL == peer->queue_head) - GNUNET_break (0); // Should've been canceled + struct MeshPeerInfo *peer = cls; + struct GNUNET_MessageHeader *msg; + struct MeshPeerQueue *queue; + struct MeshTunnel *t; + struct GNUNET_PeerIdentity dst_id; + struct MeshFlowControl *fc; + size_t data_size; + uint32_t pid; + uint16_t type; + + peer->core_transmit = NULL; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Queue send\n"); + queue = queue_get_next (peer); + + /* Queue has no internal mesh traffic nor sendable payload */ + if (NULL == queue) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* not ready, return\n"); + if (NULL == peer->queue_head) + GNUNET_break (0); /* Core tmt_rdy should've been canceled */ + return 0; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* not empty\n"); + + GNUNET_PEER_resolve (peer->id, &dst_id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "* towards %s\n", + GNUNET_i2s (&dst_id)); + /* Check if buffer size is enough for the message */ + if (queue->size > size) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "* not enough room, reissue\n"); + peer->core_transmit = + GNUNET_CORE_notify_transmit_ready (core_handle, + GNUNET_NO, + 0, + GNUNET_TIME_UNIT_FOREVER_REL, + &dst_id, + queue->size, + &queue_send, + peer); return 0; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* not empty\n"); + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* size ok\n"); - GNUNET_PEER_resolve (peer->id, &dst_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* towards %s\n", - GNUNET_i2s(&dst_id)); - /* Check if buffer size is enough for the message */ - if (queue->size > size) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* not enough room, reissue\n"); - peer->core_transmit = - GNUNET_CORE_notify_transmit_ready (core_handle, - 0, - 0, - GNUNET_TIME_UNIT_FOREVER_REL, - &dst_id, - queue->size, - &queue_send, - peer); - return 0; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* size ok\n"); + t = queue->tunnel; + GNUNET_assert (0 < t->pending_messages); + t->pending_messages--; + type = 0; - t = queue->tunnel; - GNUNET_assert (0 < t->pending_messages); - t->pending_messages--; - if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == queue->type) - { - t->fwd_queue_n--; + /* Fill buf */ + switch (queue->type) + { + case 0: + case GNUNET_MESSAGE_TYPE_MESH_ACK: + case GNUNET_MESSAGE_TYPE_MESH_POLL: + case GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN: + case GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY: + case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY: + case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE: GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* unicast: t->q (%u/%u)\n", - t->fwd_queue_n, t->fwd_queue_max); - } - else if (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == queue->type) - { - t->bck_queue_n--; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* to origin\n"); - } + "* raw: %s\n", + GNUNET_MESH_DEBUG_M2S (queue->type)); + /* Fall through */ + case GNUNET_MESSAGE_TYPE_MESH_UNICAST: + case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: + data_size = send_core_data_raw (queue->cls, size, buf); + msg = (struct GNUNET_MessageHeader *) buf; + type = ntohs (msg->type); + break; + case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path create\n"); + data_size = send_core_path_create (queue->cls, size, buf); + break; + case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK: + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path ack\n"); + data_size = send_core_path_ack (queue->cls, size, buf); + break; + default: + GNUNET_break (0); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "* type unknown: %u\n", + queue->type); + data_size = 0; + } - /* Fill buf */ - switch (queue->type) - { - case 0: - case GNUNET_MESSAGE_TYPE_MESH_ACK: - case GNUNET_MESSAGE_TYPE_MESH_POLL: - case GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN: - case GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY: - case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* raw: %s\n", - GNUNET_MESH_DEBUG_M2S (queue->type)); - /* Fall through */ - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - data_size = send_core_data_raw (queue->cls, size, buf); - msg = (struct GNUNET_MessageHeader *) buf; - switch (ntohs (msg->type)) // Type of preconstructed message - { - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST); - break; - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN); - break; - default: - break; - } - break; - case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* multicast\n"); - { - struct MeshTransmissionDescriptor *info = queue->cls; - - if ((1 == info->mesh_data->reference_counter - && GNUNET_YES == t->speed_min) - || - (info->mesh_data->total_out == info->mesh_data->reference_counter - && GNUNET_NO == t->speed_min)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* considered sent\n"); - t->fwd_queue_n--; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "********* NOT considered sent yet\n"); - t->pending_messages++; - } - } - data_size = send_core_data_multicast(queue->cls, size, buf); - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_MULTICAST); - break; - case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* path create\n"); - data_size = send_core_path_create (queue->cls, size, buf); - break; - case GNUNET_MESSAGE_TYPE_MESH_PATH_ACK: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* path ack\n"); - data_size = send_core_path_ack (queue->cls, size, buf); - break; - case GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE: - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* path keepalive\n"); - data_size = send_core_data_multicast (queue->cls, size, buf); - break; - default: - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "********* type unknown: %u\n", - queue->type); - data_size = 0; - } - switch (queue->type) - { - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: - cinfo = tunnel_get_neighbor_fc (t, &dst_id); - if (cinfo->send_buffer[cinfo->send_buffer_start] != queue) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "at pos %u (%p) != %p\n", - cinfo->send_buffer_start, - cinfo->send_buffer[cinfo->send_buffer_start], - queue); - } - if (cinfo->send_buffer_n > 0) - { - cinfo->send_buffer[cinfo->send_buffer_start] = NULL; - cinfo->send_buffer_n--; - cinfo->send_buffer_start++; - cinfo->send_buffer_start %= t->fwd_queue_max; - } - else - { - GNUNET_break (0); - } - break; - default: - break; - } + /* Free queue, but cls was freed by send_core_* */ + queue_destroy (queue, GNUNET_NO); + + /* Send ACK if needed, after accounting for sent ID in fc->queue_n */ + pid = ((struct GNUNET_MESH_Data *) buf)->pid; + switch (type) + { + case GNUNET_MESSAGE_TYPE_MESH_UNICAST: + t->next_fc.last_pid_sent = pid; + tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST); + break; + case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: + t->prev_fc.last_pid_sent = pid; + tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN); + break; + default: + break; + } - /* Free queue, but cls was freed by send_core_* */ - queue_destroy (queue, GNUNET_NO); + if (GNUNET_YES == t->destroy && 0 == t->pending_messages) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* destroying tunnel!\n"); + tunnel_destroy (t); + } - if (GNUNET_YES == t->destroy && 0 == t->pending_messages) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* destroying tunnel!\n"); - tunnel_destroy (t); - } + /* If more data in queue, send next */ + queue = queue_get_next (peer); + if (NULL != queue) + { + struct GNUNET_PeerIdentity id; - /* If more data in queue, send next */ - queue = queue_get_next(peer); - if (NULL != queue) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* more data!\n"); + GNUNET_PEER_resolve (peer->id, &id); + peer->core_transmit = + GNUNET_CORE_notify_transmit_ready(core_handle, + 0, + 0, + GNUNET_TIME_UNIT_FOREVER_REL, + &id, + queue->size, + &queue_send, + peer); + } + else if (NULL != peer->queue_head) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "* %s stalled\n", + GNUNET_i2s (&my_full_id)); + if (peer->id == t->next_hop) + fc = &t->next_fc; + else if (peer->id == t->prev_hop) + fc = &t->prev_fc; + else { - struct GNUNET_PeerIdentity id; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* more data!\n"); - GNUNET_PEER_resolve (peer->id, &id); - peer->core_transmit = - GNUNET_CORE_notify_transmit_ready(core_handle, - 0, - 0, - GNUNET_TIME_UNIT_FOREVER_REL, - &id, - queue->size, - &queue_send, - peer); + GNUNET_break (0); + fc = NULL; } - else + if (NULL != fc && GNUNET_SCHEDULER_NO_TASK == fc->poll_task) { - if (NULL != peer->queue_head) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "********* %s stalled\n", - GNUNET_i2s(&my_full_id)); - if (NULL == cinfo) - cinfo = tunnel_get_neighbor_fc (t, &dst_id); - // FIXME unify bck/fwd structures, bck does not have cinfo right now - if (NULL != cinfo && GNUNET_SCHEDULER_NO_TASK == cinfo->fc_poll) - { - cinfo->fc_poll = GNUNET_SCHEDULER_add_delayed (cinfo->fc_poll_time, - &tunnel_poll, cinfo); - } - } + fc->t = t; + fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, + &tunnel_poll, fc); } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* return %d\n", data_size); - return data_size; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Return %d\n", data_size); + return data_size; } /** * @brief Queue and pass message to core when possible. * - * If type is payload (UNICAST, TO_ORIGIN, MULTICAST) checks for queue status - * and accounts for it. In case the queue is full, the message is dropped and + * If type is payload (UNICAST, TO_ORIGIN) checks for queue status and + * accounts for it. In case the queue is full, the message is dropped and * a break issued. * * Otherwise, message is treated as internal and allowed to go regardless of @@ -4973,33 +3007,30 @@ queue_add (void *cls, uint16_t type, size_t size, struct MeshPeerInfo *dst, struct MeshTunnel *t) { struct MeshPeerQueue *queue; - struct MeshTunnelChildInfo *cinfo; struct GNUNET_PeerIdentity id; - unsigned int *max; unsigned int *n; - unsigned int i; n = NULL; - if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type || - GNUNET_MESSAGE_TYPE_MESH_MULTICAST == type) + if (GNUNET_MESSAGE_TYPE_MESH_UNICAST == type) { - n = &t->fwd_queue_n; - max = &t->fwd_queue_max; + n = &t->next_fc.queue_n; } else if (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN == type) { - n = &t->bck_queue_n; - max = &t->bck_queue_max; + n = &t->prev_fc.queue_n; } if (NULL != n) { - if (*n >= *max) + if (*n >= t->queue_max) { GNUNET_break(0); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "queue full: %u/%u\n", + *n, t->queue_max); GNUNET_STATISTICS_update(stats, "# messages dropped (buffer full)", 1, GNUNET_NO); - return; // Drop message + return; /* Drop message */ } (*n)++; } @@ -5010,43 +3041,20 @@ queue_add (void *cls, uint16_t type, size_t size, queue->peer = dst; queue->tunnel = t; GNUNET_CONTAINER_DLL_insert_tail (dst->queue_head, dst->queue_tail, queue); - GNUNET_PEER_resolve (dst->id, &id); if (NULL == dst->core_transmit) { - dst->core_transmit = - GNUNET_CORE_notify_transmit_ready (core_handle, - 0, - 0, - GNUNET_TIME_UNIT_FOREVER_REL, - &id, - size, - &queue_send, - dst); + GNUNET_PEER_resolve (dst->id, &id); + dst->core_transmit = + GNUNET_CORE_notify_transmit_ready (core_handle, + 0, + 0, + GNUNET_TIME_UNIT_FOREVER_REL, + &id, + size, + &queue_send, + dst); } t->pending_messages++; - if (NULL == n) // Is this internal mesh traffic? - return; - - // It's payload, keep track of buffer per peer. - cinfo = tunnel_get_neighbor_fc(t, &id); - i = (cinfo->send_buffer_start + cinfo->send_buffer_n) % t->fwd_queue_max; - if (NULL != cinfo->send_buffer[i]) - { - GNUNET_break (cinfo->send_buffer_n == t->fwd_queue_max); // aka i == start - queue_destroy (cinfo->send_buffer[cinfo->send_buffer_start], GNUNET_YES); - cinfo->send_buffer_start++; - cinfo->send_buffer_start %= t->fwd_queue_max; - } - else - { - cinfo->send_buffer_n++; - } - cinfo->send_buffer[i] = queue; - if (cinfo->send_buffer_n > t->fwd_queue_max) - { - GNUNET_break (0); - cinfo->send_buffer_n = t->fwd_queue_max; - } } @@ -5073,9 +3081,8 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, uint16_t size; uint16_t i; MESH_TunnelNumber tid; - struct GNUNET_MESH_ManipulatePath *msg; + struct GNUNET_MESH_CreateTunnel *msg; struct GNUNET_PeerIdentity *pi; - struct GNUNET_HashCode hash; struct MeshPeerPath *path; struct MeshPeerInfo *dest_peer_info; struct MeshPeerInfo *orig_peer_info; @@ -5085,33 +3092,33 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, "Received a path create msg [%s]\n", GNUNET_i2s (&my_full_id)); size = ntohs (message->size); - if (size < sizeof (struct GNUNET_MESH_ManipulatePath)) + if (size < sizeof (struct GNUNET_MESH_CreateTunnel)) { GNUNET_break_op (0); return GNUNET_OK; } - size -= sizeof (struct GNUNET_MESH_ManipulatePath); + size -= sizeof (struct GNUNET_MESH_CreateTunnel); if (size % sizeof (struct GNUNET_PeerIdentity)) { GNUNET_break_op (0); return GNUNET_OK; } size /= sizeof (struct GNUNET_PeerIdentity); - if (size < 2) + if (size < 1) { GNUNET_break_op (0); return GNUNET_OK; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); - msg = (struct GNUNET_MESH_ManipulatePath *) message; + msg = (struct GNUNET_MESH_CreateTunnel *) message; tid = ntohl (msg->tid); pi = (struct GNUNET_PeerIdentity *) &msg[1]; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " path is for tunnel %s [%X].\n", GNUNET_i2s (pi), tid); + " path is for tunnel %s[%X].\n", GNUNET_i2s (pi), tid); t = tunnel_get (pi, tid); - if (NULL == t) // FIXME only for INCOMING tunnels? + if (NULL == t) /* might be a local tunnel */ { uint32_t opt; @@ -5119,45 +3126,21 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, t = tunnel_new (GNUNET_PEER_intern (pi), tid, NULL, 0); if (NULL == t) { - // FIXME notify failure + GNUNET_break (0); return GNUNET_OK; } + t->port = ntohl (msg->port); opt = ntohl (msg->opt); - t->speed_min = (0 != (opt & MESH_TUNNEL_OPT_SPEED_MIN)) ? - GNUNET_YES : GNUNET_NO; if (0 != (opt & MESH_TUNNEL_OPT_NOBUFFER)) { t->nobuffer = GNUNET_YES; - t->last_fwd_ack = t->fwd_pid + 1; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " speed_min: %d, nobuffer:%d\n", - t->speed_min, t->nobuffer); - - if (GNUNET_YES == t->nobuffer) - { - t->bck_queue_max = 1; - t->fwd_queue_max = 1; + t->queue_max = 1; } - - // FIXME only assign a local tid if a local client is interested (on demand) - while (NULL != tunnel_get_incoming (next_local_tid)) - next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; - t->local_tid_dest = next_local_tid++; - next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; - // FIXME end + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " nobuffer:%d\n", t->nobuffer); tunnel_reset_timeout (t); - GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); - if (GNUNET_OK != - GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) - { - tunnel_destroy (t); - GNUNET_break (0); - return GNUNET_OK; - } } + t->state = MESH_TUNNEL_WAITING; dest_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey); if (NULL == dest_peer_info) @@ -5192,9 +3175,8 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, own_pos = i; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos); - if (own_pos == 0) + if (own_pos == 0 && path->peers[own_pos] != myid) { - /* cannot be self, must be 'not found' */ /* create path: self not found in path through self */ GNUNET_break_op (0); path_destroy (path); @@ -5202,43 +3184,58 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, return GNUNET_OK; } path_add_to_peers (path, GNUNET_NO); - tunnel_add_path (t, path, own_pos); + tunnel_use_path (t, path); + + peer_info_add_tunnel (dest_peer_info, t); + if (own_pos == size - 1) { - /* It is for us! Send ack. */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); - peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO); - if (NULL == t->peers) + struct MeshClient *c; + struct GNUNET_HashCode hc; + + /* Find target client */ + GMC_hash32 (t->port, &hc); + c = GNUNET_CONTAINER_multihashmap_get (ports, &hc); + if (NULL == c) { - /* New tunnel! Notify clients on first payload message. */ - t->peers = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO); + /* TODO send reject */ + return GNUNET_OK; } - GNUNET_break (GNUNET_SYSERR != - GNUNET_CONTAINER_multihashmap_put (t->peers, - &my_full_id.hashPubKey, - peer_info_get - (&my_full_id), - GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE)); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); + peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_YES); + + /* Assign local tid */ + while (NULL != tunnel_get_incoming (next_local_tid)) + next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; + t->local_tid_dest = next_local_tid++; + next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; + + tunnel_add_client (t, c); + send_client_tunnel_create (t); send_path_ack (t); } else { struct MeshPeerPath *path2; + t->next_hop = path->peers[own_pos + 1]; + GNUNET_PEER_change_rc(t->next_hop, 1); + /* It's for somebody else! Retransmit. */ - path2 = path_duplicate (path); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n"); - peer_info_add_path (dest_peer_info, path2, GNUNET_NO); path2 = path_duplicate (path); - peer_info_add_path_to_origin (orig_peer_info, path2, GNUNET_NO); - send_create_path (dest_peer_info, path, t); + peer_info_add_path (dest_peer_info, path2, GNUNET_NO); + peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO); + send_create_path (t); } return GNUNET_OK; } + /** - * Core handler for path destruction + * Core handler for path ACKs * * @param cls closure * @param message message @@ -5248,71 +3245,72 @@ handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer, * GNUNET_SYSERR to close it (signal serious error) */ static int -handle_mesh_path_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) +handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) { - struct GNUNET_MESH_ManipulatePath *msg; - struct GNUNET_PeerIdentity *pi; - struct MeshPeerPath *path; + struct GNUNET_MESH_PathACK *msg; + struct MeshPeerInfo *peer_info; + struct MeshPeerPath *p; struct MeshTunnel *t; - unsigned int own_pos; - unsigned int i; - size_t size; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received a PATH DESTROY msg from %s\n", GNUNET_i2s (peer)); - size = ntohs (message->size); - if (size < sizeof (struct GNUNET_MESH_ManipulatePath)) + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a path ACK msg [%s]\n", + GNUNET_i2s (&my_full_id)); + msg = (struct GNUNET_MESH_PathACK *) message; + t = tunnel_get (&msg->oid, ntohl(msg->tid)); + if (NULL == t) { - GNUNET_break_op (0); + /* TODO notify that we don't know the tunnel */ + GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", 1, GNUNET_NO); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the tunnel %s [%X]!\n", + GNUNET_i2s (&msg->oid), ntohl(msg->tid)); return GNUNET_OK; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %s [%X]\n", + GNUNET_i2s (&msg->oid), ntohl(msg->tid)); - size -= sizeof (struct GNUNET_MESH_ManipulatePath); - if (size % sizeof (struct GNUNET_PeerIdentity)) + peer_info = peer_get (&msg->peer_id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by peer %s\n", + GNUNET_i2s (&msg->peer_id)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", + GNUNET_i2s (peer)); + + /* Add path to peers? */ + p = t->path; + if (NULL != p) { - GNUNET_break_op (0); - return GNUNET_OK; + path_add_to_peers (p, GNUNET_YES); } - size /= sizeof (struct GNUNET_PeerIdentity); - if (size < 2) + else { - GNUNET_break_op (0); - return GNUNET_OK; + GNUNET_break (0); } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); + t->state = MESH_TUNNEL_READY; + t->next_fc.last_ack_recv = (NULL == t->client) ? ntohl (msg->ack) : 0; + t->prev_fc.last_ack_sent = ntohl (msg->ack); - msg = (struct GNUNET_MESH_ManipulatePath *) message; - pi = (struct GNUNET_PeerIdentity *) &msg[1]; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " path is for tunnel %s [%X].\n", GNUNET_i2s (pi), - msg->tid); - t = tunnel_get (pi, ntohl (msg->tid)); - if (NULL == t) + /* Message for us? */ + if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity))) { - /* TODO notify back: we don't know this tunnel */ - GNUNET_break_op (0); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); + if (NULL == t->owner) + { + GNUNET_break_op (0); + return GNUNET_OK; + } + if (NULL != peer_info->dhtget) + { + GNUNET_DHT_get_stop (peer_info->dhtget); + peer_info->dhtget = NULL; + } + tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK); + tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK); return GNUNET_OK; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n"); - path = path_new (size); - own_pos = 0; - for (i = 0; i < size; i++) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... adding %s\n", - GNUNET_i2s (&pi[i])); - path->peers[i] = GNUNET_PEER_intern (&pi[i]); - if (path->peers[i] == myid) - own_pos = i; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos); - if (own_pos < path->length - 1) - send_prebuilt_message (message, &pi[own_pos + 1], t); - else - send_client_tunnel_disconnect(t, NULL); - tunnel_delete_peer (t, path->peers[path->length - 1]); - path_destroy (path); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + " not for us, retransmitting...\n"); + peer_info = peer_get (&msg->oid); + send_prebuilt_message (message, t->prev_hop, t); return GNUNET_OK; } @@ -5370,8 +3368,6 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, { struct GNUNET_MESH_TunnelDestroy *msg; struct MeshTunnel *t; - GNUNET_PEER_Id parent; - GNUNET_PEER_Id pid; msg = (struct GNUNET_MESH_TunnelDestroy *) message; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -5381,7 +3377,6 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, " for tunnel %s [%u]\n", GNUNET_i2s (&msg->oid), ntohl (msg->tid)); t = tunnel_get (&msg->oid, ntohl (msg->tid)); - /* Check signature */ if (NULL == t) { /* Probably already got the message from another path, @@ -5392,31 +3387,36 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, 1, GNUNET_NO); return GNUNET_OK; } - parent = tree_get_predecessor (t->tree); - pid = GNUNET_PEER_search (peer); - if (pid != parent) - { - unsigned int nc; - - tree_del_peer (t->tree, pid, &tunnel_child_removed, t); - nc = tree_count_children (t->tree); - if (nc > 0 || NULL != t->owner || t->nclients > 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "still in use: %u cl, %u ch\n", - t->nclients, nc); - return GNUNET_OK; - } - } if (t->local_tid_dest >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) { - /* Tunnel was incoming, notify clients */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "INCOMING TUNNEL %X %X\n", t->local_tid, t->local_tid_dest); - send_clients_tunnel_destroy (t); } - tunnel_send_destroy (t, parent); - t->destroy = GNUNET_YES; + if (GNUNET_PEER_search (peer) == t->prev_hop) + { + // TODO check owner's signature + // TODO add owner's signatue to tunnel for retransmission + peer_cancel_queues (t->prev_hop, t); + GNUNET_PEER_change_rc (t->prev_hop, -1); + t->prev_hop = 0; + } + else if (GNUNET_PEER_search (peer) == t->next_hop) + { + // TODO check dest's signature + // TODO add dest's signatue to tunnel for retransmission + peer_cancel_queues (t->next_hop, t); + GNUNET_PEER_change_rc (t->next_hop, -1); + t->next_hop = 0; + } + else + { + GNUNET_break_op (0); + // TODO check both owner AND destination's signature to see which matches + // TODO restransmit in appropriate direction + return GNUNET_OK; + } + tunnel_destroy_empty (t); + // TODO: add timeout to destroy the tunnel anyway return GNUNET_OK; } @@ -5432,14 +3432,11 @@ handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, * GNUNET_SYSERR to close it (signal serious error) */ static int -handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, +handle_mesh_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { - struct GNUNET_MESH_Unicast *msg; - struct GNUNET_PeerIdentity *neighbor; - struct MeshTunnelChildInfo *cinfo; + struct GNUNET_MESH_Data *msg; struct MeshTunnel *t; - GNUNET_PEER_Id dest_id; uint32_t pid; uint32_t ttl; size_t size; @@ -5449,13 +3446,13 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, /* Check size */ size = ntohs (message->size); if (size < - sizeof (struct GNUNET_MESH_Unicast) + + sizeof (struct GNUNET_MESH_Data) + sizeof (struct GNUNET_MessageHeader)) { GNUNET_break (0); return GNUNET_OK; } - msg = (struct GNUNET_MESH_Unicast *) message; + msg = (struct GNUNET_MESH_Data *) message; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n", GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type))); /* Check tunnel */ @@ -5468,7 +3465,7 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, return GNUNET_OK; } pid = ntohl (msg->pid); - if (t->fwd_pid == pid) + if (t->prev_fc.last_pid_recv == pid) { GNUNET_STATISTICS_update (stats, "# duplicate PID drops", 1, GNUNET_NO); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -5481,30 +3478,34 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, " pid %u not seen yet, forwarding\n", pid); } - t->skip += (pid - t->fwd_pid) - 1; - t->fwd_pid = pid; - - if (GMC_is_pid_bigger (pid, t->last_fwd_ack)) + if (GMC_is_pid_bigger (pid, t->prev_fc.last_ack_sent)) { GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO); GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received PID %u, ACK %u\n", - pid, t->last_fwd_ack); + pid, t->prev_fc.last_ack_sent); + tunnel_send_fwd_ack(t, GNUNET_MESSAGE_TYPE_MESH_POLL); return GNUNET_OK; } + t->prev_fc.last_pid_recv = pid; tunnel_reset_timeout (t); - dest_id = GNUNET_PEER_search (&msg->destination); - if (dest_id == myid) + if (t->dest == myid) { + /* TODO signature verification */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " it's for us! sending to clients...\n"); GNUNET_STATISTICS_update (stats, "# unicast received", 1, GNUNET_NO); - send_subscribed_clients (message, &msg[1].header, t); + tunnel_send_client_ucast (t, msg); tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_UNICAST); return GNUNET_OK; } + if (0 == t->next_hop) + { + GNUNET_break (0); + return GNUNET_OK; + } ttl = ntohl (msg->ttl); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl); if (ttl == 0) @@ -5517,107 +3518,13 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); - neighbor = tree_get_first_hop (t->tree, dest_id); - cinfo = tunnel_get_neighbor_fc (t, neighbor); - cinfo->fwd_pid = pid; - GNUNET_CONTAINER_multihashmap_iterate (t->children_fc, - &tunnel_add_skip, - &neighbor); - if (GNUNET_YES == t->nobuffer && - GNUNET_YES == GMC_is_pid_bigger (pid, cinfo->fwd_ack)) - { - GNUNET_STATISTICS_update (stats, "# unsolicited unicast", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, " %u > %u\n", pid, cinfo->fwd_ack); - GNUNET_break_op (0); - return GNUNET_OK; - } - send_prebuilt_message (message, neighbor, t); + send_prebuilt_message (message, t->next_hop, t); GNUNET_STATISTICS_update (stats, "# unicast forwarded", 1, GNUNET_NO); return GNUNET_OK; } /** - * Core handler for mesh network traffic going from the origin to all peers - * - * @param cls closure - * @param message message - * @param peer peer identity this notification is about - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - * - * TODO: Check who we got this from, to validate route. - */ -static int -handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_Multicast *msg; - struct MeshTunnel *t; - size_t size; - uint32_t pid; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a multicast packet from %s\n", - GNUNET_i2s (peer)); - size = ntohs (message->size); - if (sizeof (struct GNUNET_MESH_Multicast) + - sizeof (struct GNUNET_MessageHeader) > size) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - msg = (struct GNUNET_MESH_Multicast *) message; - t = tunnel_get (&msg->oid, ntohl (msg->tid)); - - if (NULL == t) - { - /* TODO notify that we dont know that tunnel */ - GNUNET_STATISTICS_update (stats, "# data on unknown tunnel", 1, GNUNET_NO); - GNUNET_break_op (0); - return GNUNET_OK; - } - pid = ntohl (msg->pid); - if (t->fwd_pid == pid) - { - /* already seen this packet, drop */ - GNUNET_STATISTICS_update (stats, "# duplicate PID drops", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Already seen pid %u, DROPPING!\n", pid); - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); - return GNUNET_OK; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " pid %u not seen yet, forwarding\n", pid); - } - t->skip += (pid - t->fwd_pid) - 1; - t->fwd_pid = pid; - tunnel_reset_timeout (t); - - /* Transmit to locally interested clients */ - if (NULL != t->peers && - GNUNET_CONTAINER_multihashmap_contains (t->peers, &my_full_id.hashPubKey)) - { - GNUNET_STATISTICS_update (stats, "# multicast received", 1, GNUNET_NO); - send_subscribed_clients (message, &msg[1].header, t); - tunnel_send_fwd_ack(t, GNUNET_MESSAGE_TYPE_MESH_MULTICAST); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ntohl (msg->ttl)); - if (ntohl (msg->ttl) == 0) - { - GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n"); - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); - return GNUNET_OK; - } - GNUNET_STATISTICS_update (stats, "# multicast forwarded", 1, GNUNET_NO); - tunnel_send_multicast (t, message); - return GNUNET_OK; -} - - -/** * Core handler for mesh network traffic toward the owner of a tunnel * * @param cls closure @@ -5628,28 +3535,25 @@ handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer, * GNUNET_SYSERR to close it (signal serious error) */ static int -handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, +handle_mesh_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_MessageHeader *message) { - struct GNUNET_MESH_ToOrigin *msg; - struct GNUNET_PeerIdentity id; - struct MeshPeerInfo *peer_info; + struct GNUNET_MESH_Data *msg; struct MeshTunnel *t; - struct MeshTunnelChildInfo *cinfo; - GNUNET_PEER_Id predecessor; size_t size; uint32_t pid; + uint32_t ttl; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a ToOrigin packet from %s\n", GNUNET_i2s (peer)); size = ntohs (message->size); - if (size < sizeof (struct GNUNET_MESH_ToOrigin) + /* Payload must be */ + if (size < sizeof (struct GNUNET_MESH_Data) + /* Payload must be */ sizeof (struct GNUNET_MessageHeader)) /* at least a header */ { GNUNET_break_op (0); return GNUNET_OK; } - msg = (struct GNUNET_MESH_ToOrigin *) message; + msg = (struct GNUNET_MESH_Data *) message; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " of type %s\n", GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type))); t = tunnel_get (&msg->oid, ntohl (msg->tid)); @@ -5665,14 +3569,7 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, return GNUNET_OK; } - cinfo = tunnel_get_neighbor_fc(t, peer); - if (NULL == cinfo) - { - GNUNET_break (0); - return GNUNET_OK; - } - - if (cinfo->bck_pid == pid) + if (t->next_fc.last_pid_recv == pid) { /* already seen this packet, drop */ GNUNET_STATISTICS_update (stats, "# duplicate PID drops BCK", 1, GNUNET_NO); @@ -5682,41 +3579,34 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, return GNUNET_OK; } + if (GMC_is_pid_bigger (pid, t->next_fc.last_ack_sent)) + { + GNUNET_STATISTICS_update (stats, "# unsolicited to_orig", 1, GNUNET_NO); + GNUNET_break_op (0); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received PID %u, ACK %u\n", + pid, t->next_fc.last_ack_sent); + tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL); + return GNUNET_OK; + } + t->next_fc.last_pid_recv = pid; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " pid %u not seen yet, forwarding\n", pid); - cinfo->bck_pid = pid; - if (NULL != t->owner) + if (myid == t->id.oid) { - char cbuf[size]; - struct GNUNET_MESH_ToOrigin *copy; - + /* TODO signature verification */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " it's for us! sending to clients...\n"); - /* TODO signature verification */ - memcpy (cbuf, message, size); - copy = (struct GNUNET_MESH_ToOrigin *) cbuf; - copy->tid = htonl (t->local_tid); - t->bck_pid++; - copy->pid = htonl (t->bck_pid); GNUNET_STATISTICS_update (stats, "# to origin received", 1, GNUNET_NO); - GNUNET_SERVER_notification_context_unicast (nc, t->owner->handle, - ©->header, GNUNET_NO); + tunnel_send_client_to_orig (t, msg); tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN); return GNUNET_OK; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); - peer_info = peer_info_get (&msg->oid); - if (NULL == peer_info) - { - /* unknown origin of tunnel */ - GNUNET_break (0); - return GNUNET_OK; - } - predecessor = tree_get_predecessor (t->tree); - if (0 == predecessor) + if (0 == t->prev_hop) /* No owner AND no prev hop */ { if (GNUNET_YES == t->destroy) { @@ -5732,15 +3622,20 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer, "from peer %s\n", GNUNET_i2s (peer)); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "for tunnel %s [%X]\n", + "on tunnel %s [%X]\n", GNUNET_i2s (&msg->oid), ntohl(msg->tid)); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "current tree:\n"); - tree_debug (t->tree); return GNUNET_OK; } - GNUNET_PEER_resolve (predecessor, &id); - send_prebuilt_message (message, &id, t); + ttl = ntohl (msg->ttl); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl); + if (ttl == 0) + { + GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n"); + tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); + return GNUNET_OK; + } + send_prebuilt_message (message, t->prev_hop, t); GNUNET_STATISTICS_update (stats, "# to origin forwarded", 1, GNUNET_NO); return GNUNET_OK; @@ -5763,6 +3658,7 @@ handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer, { struct GNUNET_MESH_ACK *msg; struct MeshTunnel *t; + GNUNET_PEER_Id id; uint32_t ack; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n", @@ -5781,30 +3677,39 @@ handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack); /* Is this a forward or backward ACK? */ - if (tree_get_predecessor(t->tree) != GNUNET_PEER_search(peer)) + id = GNUNET_PEER_search (peer); + if (t->next_hop == id) { - struct MeshTunnelChildInfo *cinfo; - - debug_bck_ack++; + debug_fwd_ack++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); - cinfo = tunnel_get_neighbor_fc (t, peer); - cinfo->fwd_ack = ack; - tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); - tunnel_unlock_fwd_queues (t); - if (GNUNET_SCHEDULER_NO_TASK != cinfo->fc_poll) + if (GNUNET_SCHEDULER_NO_TASK != t->next_fc.poll_task && + GMC_is_pid_bigger (ack, t->next_fc.last_ack_recv)) { - GNUNET_SCHEDULER_cancel (cinfo->fc_poll); - cinfo->fc_poll = GNUNET_SCHEDULER_NO_TASK; - cinfo->fc_poll_time = GNUNET_TIME_UNIT_SECONDS; + GNUNET_SCHEDULER_cancel (t->next_fc.poll_task); + t->next_fc.poll_task = GNUNET_SCHEDULER_NO_TASK; + t->next_fc.poll_time = GNUNET_TIME_UNIT_SECONDS; } + t->next_fc.last_ack_recv = ack; + peer_unlock_queue (t->next_hop); + tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); } - else + else if (t->prev_hop == id) { + debug_bck_ack++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n"); - t->bck_ack = ack; + if (GNUNET_SCHEDULER_NO_TASK != t->prev_fc.poll_task && + GMC_is_pid_bigger (ack, t->prev_fc.last_ack_recv)) + { + GNUNET_SCHEDULER_cancel (t->prev_fc.poll_task); + t->prev_fc.poll_task = GNUNET_SCHEDULER_NO_TASK; + t->prev_fc.poll_time = GNUNET_TIME_UNIT_SECONDS; + } + t->prev_fc.last_ack_recv = ack; + peer_unlock_queue (t->prev_hop); tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_ACK); - tunnel_unlock_bck_queue (t); } + else + GNUNET_break_op (0); return GNUNET_OK; } @@ -5825,6 +3730,7 @@ handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer, { struct GNUNET_MESH_Poll *msg; struct MeshTunnel *t; + GNUNET_PEER_Id id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an POLL packet from %s!\n", GNUNET_i2s (peer)); @@ -5842,117 +3748,20 @@ handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer, } /* Is this a forward or backward ACK? */ - if (tree_get_predecessor(t->tree) != GNUNET_PEER_search(peer)) + id = GNUNET_PEER_search(peer); + if (t->next_hop == id) { - struct MeshTunnelChildInfo *cinfo; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from FWD\n"); - cinfo = tunnel_get_neighbor_fc (t, peer); - cinfo->bck_ack = cinfo->fwd_pid; // mark as ready to send tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL); } - else + else if (t->prev_hop == id) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " from BCK\n"); tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_POLL); } - - return GNUNET_OK; -} - -/** - * Core handler for path ACKs - * - * @param cls closure - * @param message message - * @param peer peer identity this notification is about - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_PathACK *msg; - struct GNUNET_PeerIdentity id; - struct MeshPeerInfo *peer_info; - struct MeshPeerPath *p; - struct MeshTunnel *t; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a path ACK msg [%s]\n", - GNUNET_i2s (&my_full_id)); - msg = (struct GNUNET_MESH_PathACK *) message; - t = tunnel_get (&msg->oid, ntohl(msg->tid)); - if (NULL == t) - { - /* TODO notify that we don't know the tunnel */ - GNUNET_STATISTICS_update (stats, "# control on unknown tunnel", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the tunnel %s [%X]!\n", - GNUNET_i2s (&msg->oid), ntohl(msg->tid)); - return GNUNET_OK; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %s [%X]\n", - GNUNET_i2s (&msg->oid), ntohl(msg->tid)); - - peer_info = peer_info_get (&msg->peer_id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by peer %s\n", - GNUNET_i2s (&msg->peer_id)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", - GNUNET_i2s (peer)); - - if (NULL != t->regex_search && t->regex_search->peer == peer_info->id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "connect_by_string completed, stopping search\n"); - regex_cancel_search (t->regex_search); - t->regex_search = NULL; - } - - /* Add paths to peers? */ - p = tree_get_path_to_peer (t->tree, peer_info->id); - if (NULL != p) - { - path_add_to_peers (p, GNUNET_YES); - path_destroy (p); - } else - { GNUNET_break (0); - } - /* Message for us? */ - if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity))) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); - if (NULL == t->owner) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - if (NULL != t->dht_get_type) - { - 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) - { - tree_set_status (t->tree, peer_info->id, MESH_PEER_READY); - send_client_peer_connected (t, peer_info->id); - } - if (NULL != peer_info->dhtget) - { - GNUNET_DHT_get_stop (peer_info->dhtget); - peer_info->dhtget = NULL; - } - return GNUNET_OK; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " not for us, retransmitting...\n"); - GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id); - peer_info = peer_info_get (&msg->oid); - send_prebuilt_message (message, &id, t); return GNUNET_OK; } @@ -5992,7 +3801,7 @@ handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer, tunnel_reset_timeout (t); GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO); - tunnel_send_multicast (t, message); + send_prebuilt_message (message, t->next_hop, t); return GNUNET_OK; } @@ -6003,16 +3812,14 @@ handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer, */ static struct GNUNET_CORE_MessageHandler core_handlers[] = { {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0}, - {&handle_mesh_path_destroy, GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY, 0}, {&handle_mesh_path_broken, GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN, sizeof (struct GNUNET_MESH_PathBroken)}, {&handle_mesh_tunnel_destroy, GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY, sizeof (struct GNUNET_MESH_TunnelDestroy)}, - {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0}, - {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0}, + {&handle_mesh_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0}, {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE, sizeof (struct GNUNET_MESH_TunnelKeepAlive)}, - {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0}, + {&handle_mesh_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0}, {&handle_mesh_ack, GNUNET_MESSAGE_TYPE_MESH_ACK, sizeof (struct GNUNET_MESH_ACK)}, {&handle_mesh_poll, GNUNET_MESSAGE_TYPE_MESH_POLL, @@ -6028,24 +3835,6 @@ static struct GNUNET_CORE_MessageHandler core_handlers[] = { /**************** MESH LOCAL HANDLER HELPERS ***********************/ /******************************************************************************/ -/** - * deregister_app: iterator for removing each application registered by a client - * - * @param cls closure - * @param key the hash of the application id (used to access the hashmap) - * @param value the value stored at the key (client) - * - * @return GNUNET_OK on success - */ -static int -deregister_app (void *cls, const struct GNUNET_HashCode * key, void *value) -{ - struct MeshClient *c = cls; - - GNUNET_break (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (applications, key, c)); - return GNUNET_OK; -} #if LATER /** @@ -6088,10 +3877,12 @@ notify_client_connection_failure (void *cls, size_t size, void *buf) /** - * Send keepalive packets for a peer + * Send keepalive packets for a tunnel. * * @param cls Closure (tunnel for which to send the keepalive). * @param tc Notification context. + * + * FIXME: add a refresh reset in case of normal unicast traffic is doing the job */ static void path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) @@ -6101,8 +3892,9 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) size_t size = sizeof (struct GNUNET_MESH_TunnelKeepAlive); char cbuf[size]; - t->path_refresh_task = GNUNET_SCHEDULER_NO_TASK; - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) + t->maintenance_task = GNUNET_SCHEDULER_NO_TASK; + if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) || + NULL == t->owner || 0 == t->local_tid) { return; } @@ -6115,11 +3907,10 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE); msg->oid = my_full_id; msg->tid = htonl (t->id.tid); - tunnel_send_multicast (t, &msg->header); + send_prebuilt_message (&msg->header, t->next_hop, t); - t->path_refresh_task = + t->maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_path_time, &path_refresh, t); - tunnel_reset_timeout(t); } @@ -6138,8 +3929,6 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * @param type type of the result * @param size number of bytes in data * @param data pointer to the result data - * - * TODO: re-issue the request after certain time? cancel after X results? */ static void dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, @@ -6150,83 +3939,36 @@ dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, unsigned int put_path_length, enum GNUNET_BLOCK_Type type, size_t size, const void *data) { - struct MeshPathInfo *path_info = cls; + struct MeshPeerInfo *peer = cls; struct MeshPeerPath *p; struct GNUNET_PeerIdentity pi; int i; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got results from DHT!\n"); - GNUNET_PEER_resolve (path_info->peer->id, &pi); + GNUNET_PEER_resolve (peer->id, &pi); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", GNUNET_i2s (&pi)); p = path_build_from_dht (get_path, get_path_length, put_path, put_path_length); path_add_to_peers (p, GNUNET_NO); path_destroy (p); - for (i = 0; i < path_info->peer->ntunnels; i++) + for (i = 0; i < peer->ntunnels; i++) { - tunnel_add_peer (path_info->peer->tunnels[i], path_info->peer); - peer_info_connect (path_info->peer, path_info->t); - } - - return; -} - - -/** - * Function to process paths received for a new peer addition. The recorded - * paths form the initial tunnel, which can be optimized later. - * Called on each result obtained for the DHT search. - * - * @param cls closure - * @param exp when will this value expire - * @param key key of the result - * @param get_path path of the get request - * @param get_path_length lenght of get_path - * @param put_path path of the put request - * @param put_path_length length of the put_path - * @param type type of the result - * @param size number of bytes in data - * @param data pointer to the result data - */ -static void -dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp, - const struct GNUNET_HashCode * key, - const struct GNUNET_PeerIdentity *get_path, - unsigned int get_path_length, - const struct GNUNET_PeerIdentity *put_path, - unsigned int put_path_length, enum GNUNET_BLOCK_Type type, - size_t size, const void *data) -{ - const struct PBlock *pb = data; - const struct GNUNET_PeerIdentity *pi = &pb->id; - struct MeshTunnel *t = cls; - struct MeshPeerInfo *peer_info; - struct MeshPeerPath *p; + struct GNUNET_PeerIdentity id; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got type DHT result!\n"); - if (size != sizeof (struct PBlock)) - { - GNUNET_break_op (0); - return; - } - if (ntohl(pb->type) != t->type) - { - GNUNET_break_op (0); - return; + GNUNET_PEER_resolve (peer->tunnels[i]->id.oid, &id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... tunnel %s:%X (%X / %X)\n", + GNUNET_i2s (&id), peer->tunnels[i]->id.tid, + peer->tunnels[i]->local_tid, + peer->tunnels[i]->local_tid_dest); + if (peer->tunnels[i]->state == MESH_TUNNEL_SEARCHING) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n"); + peer_connect (peer, peer->tunnels[i]); + } } - GNUNET_assert (NULL != t->owner); - peer_info = peer_info_get (pi); - (void) GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey, - peer_info, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); - p = path_build_from_dht (get_path, get_path_length, put_path, - put_path_length); - path_add_to_peers (p, GNUNET_NO); - path_destroy(p); - tunnel_add_peer (t, peer_info); - peer_info_connect (peer_info, t); + return; } @@ -6247,21 +3989,22 @@ handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) { struct MeshClient *c; struct MeshClient *next; - unsigned int i; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client); if (client == NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n"); return; } - c = clients; + c = clients_head; while (NULL != c) { if (c->handle != client) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... searching\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + " ... searching %p (%u)\n", + c->handle, c->id); c = c->next; continue; } @@ -6269,49 +4012,24 @@ handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) c->id); GNUNET_SERVER_client_drop (c->handle); c->shutting_down = GNUNET_YES; - GNUNET_assert (NULL != c->own_tunnels); - GNUNET_assert (NULL != c->incoming_tunnels); GNUNET_CONTAINER_multihashmap_iterate (c->own_tunnels, &tunnel_destroy_iterator, c); GNUNET_CONTAINER_multihashmap_iterate (c->incoming_tunnels, &tunnel_destroy_iterator, c); - GNUNET_CONTAINER_multihashmap_iterate (c->ignore_tunnels, - &tunnel_destroy_iterator, c); GNUNET_CONTAINER_multihashmap_destroy (c->own_tunnels); GNUNET_CONTAINER_multihashmap_destroy (c->incoming_tunnels); - GNUNET_CONTAINER_multihashmap_destroy (c->ignore_tunnels); - /* deregister clients applications */ - if (NULL != c->apps) - { - GNUNET_CONTAINER_multihashmap_iterate (c->apps, &deregister_app, c); - GNUNET_CONTAINER_multihashmap_destroy (c->apps); - } - if (0 == GNUNET_CONTAINER_multihashmap_size (applications) && - GNUNET_SCHEDULER_NO_TASK != announce_applications_task) - { - GNUNET_SCHEDULER_cancel (announce_applications_task); - announce_applications_task = GNUNET_SCHEDULER_NO_TASK; - } - if (NULL != c->types) - GNUNET_CONTAINER_multihashmap_destroy (c->types); - for (i = 0; i < c->n_regex; i++) - { - GNUNET_free (c->regexes[i].regex); - if (NULL != c->regexes[i].h) - GNUNET_REGEX_announce_cancel (c->regexes[i].h); - } - GNUNET_free_non_null (c->regexes); - if (GNUNET_SCHEDULER_NO_TASK != c->regex_announce_task) - GNUNET_SCHEDULER_cancel (c->regex_announce_task); + if (NULL != c->ports) + GNUNET_CONTAINER_multihashmap_destroy (c->ports); next = c->next; - GNUNET_CONTAINER_DLL_remove (clients, clients_tail, c); + GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " CLIENT FREE at %p\n", c); GNUNET_free (c); GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO); c = next; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " done!\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done!\n"); + return; } @@ -6328,85 +4046,57 @@ handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client, { struct GNUNET_MESH_ClientConnect *cc_msg; struct MeshClient *c; - GNUNET_MESH_ApplicationType *a; unsigned int size; - uint16_t ntypes; - uint16_t *t; - uint16_t napps; - uint16_t i; + uint32_t *p; + unsigned int i; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected\n"); /* Check data sanity */ size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect); cc_msg = (struct GNUNET_MESH_ClientConnect *) message; - ntypes = ntohs (cc_msg->types); - napps = ntohs (cc_msg->applications); - if (size != - ntypes * sizeof (uint16_t) + napps * sizeof (GNUNET_MESH_ApplicationType)) + if (0 != (size % sizeof (uint32_t))) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } + size /= sizeof (uint32_t); /* Create new client structure */ c = GNUNET_malloc (sizeof (struct MeshClient)); - c->id = next_client_id++; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " CLIENT NEW %u\n", c->id); + c->id = next_client_id++; /* overflow not important: just for debug */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client id %u\n", c->id); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client has %u ports\n", size); c->handle = client; GNUNET_SERVER_client_keep (client); - a = (GNUNET_MESH_ApplicationType *) &cc_msg[1]; - if (napps > 0) + if (size > 0) { - GNUNET_MESH_ApplicationType at; + uint32_t u32; struct GNUNET_HashCode hc; - c->apps = GNUNET_CONTAINER_multihashmap_create (napps, GNUNET_NO); - for (i = 0; i < napps; i++) + p = (uint32_t *) &cc_msg[1]; + c->ports = GNUNET_CONTAINER_multihashmap_create (size, GNUNET_NO); + for (i = 0; i < size; i++) { - at = ntohl (a[i]); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " app type: %u\n", at); - GNUNET_CRYPTO_hash (&at, sizeof (at), &hc); - /* store in clients hashmap */ - GNUNET_CONTAINER_multihashmap_put (c->apps, &hc, (void *) (long) at, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - /* store in global hashmap, for announcements */ - GNUNET_CONTAINER_multihashmap_put (applications, &hc, c, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - } - if (GNUNET_SCHEDULER_NO_TASK == announce_applications_task) - announce_applications_task = - GNUNET_SCHEDULER_add_now (&announce_applications, NULL); - - } - if (ntypes > 0) - { - uint16_t u16; - struct GNUNET_HashCode hc; + u32 = ntohl (p[i]); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " port: %u\n", u32); + GMC_hash32 (u32, &hc); - t = (uint16_t *) & a[napps]; - c->types = GNUNET_CONTAINER_multihashmap_create (ntypes, GNUNET_NO); - for (i = 0; i < ntypes; i++) - { - u16 = ntohs (t[i]); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " msg type: %u\n", u16); - GNUNET_CRYPTO_hash (&u16, sizeof (u16), &hc); - - /* store in clients hashmap */ - GNUNET_CONTAINER_multihashmap_put (c->types, &hc, c, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); + /* store in client's hashmap */ + GNUNET_CONTAINER_multihashmap_put (c->ports, &hc, c, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); /* store in global hashmap */ - GNUNET_CONTAINER_multihashmap_put (types, &hc, c, + /* FIXME only allow one client to have the port open, + * have a backup hashmap with waiting clients */ + GNUNET_CONTAINER_multihashmap_put (ports, &hc, c, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " client has %u+%u subscriptions\n", napps, ntypes); - GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c); + GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c); c->own_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); c->incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); - c->ignore_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); GNUNET_SERVER_notification_context_add (nc, client); GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO); @@ -6416,96 +4106,18 @@ handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client, /** - * Handler for clients announcing available services by a regular expression. - * - * @param cls closure - * @param client identification of the client - * @param message the actual message, which includes messages the client wants - */ -static void -handle_local_announce_regex (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_MESH_RegexAnnounce *msg; - struct MeshRegexDescriptor rd; - struct MeshClient *c; - char *regex; - size_t len; - size_t offset; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "announce regex started\n"); - - /* Sanity check for client registration */ - if (NULL == (c = 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); - - msg = (const struct GNUNET_MESH_RegexAnnounce *) message; - - len = ntohs (message->size) - sizeof(struct GNUNET_MESH_RegexAnnounce); - if (NULL != c->partial_regex) - { - regex = c->partial_regex; - offset = strlen (c->partial_regex); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " continuation, already have %u bytes\n", - offset); - } - else - { - regex = NULL; - offset = 0; - } - - regex = GNUNET_realloc (regex, offset + len + 1); - memcpy (®ex[offset], &msg[1], len); - regex[offset + len] = '\0'; - if (0 == ntohs (msg->last)) - { - c->partial_regex = regex; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " not ended, stored %u bytes for later\n", - len); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - rd.regex = regex; - rd.compression = ntohs (msg->compression_characters); - rd.h = NULL; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " length %u\n", len); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regex %s\n", regex); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " compr %u\n", ntohs (rd.compression)); - GNUNET_array_append (c->regexes, c->n_regex, rd); - c->partial_regex = NULL; - if (GNUNET_SCHEDULER_NO_TASK == c->regex_announce_task) - { - c->regex_announce_task = GNUNET_SCHEDULER_add_now (®ex_announce, c); - } - else - { - regex_put (&rd); - } - GNUNET_SERVER_receive_done (client, GNUNET_OK); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "announce regex processed\n"); -} - - -/** * Handler for requests of new tunnels * - * @param cls closure - * @param client identification of the client - * @param message the actual message + * @param cls Closure. + * @param client Identification of the client. + * @param message The actual message. */ static void handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_TunnelMessage *t_msg; + struct MeshPeerInfo *peer_info; struct MeshTunnel *t; struct MeshClient *c; MESH_TunnelNumber tid; @@ -6521,7 +4133,7 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); - /* Message sanity check */ + /* Message size sanity check */ if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size)) { GNUNET_break (0); @@ -6530,6 +4142,8 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, } t_msg = (struct GNUNET_MESH_TunnelMessage *) message; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " towards %s\n", + GNUNET_i2s (&t_msg->peer)); /* Sanity check for tunnel numbering */ tid = ntohl (t_msg->tunnel_id); if (0 == (tid & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI)) @@ -6546,22 +4160,24 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, return; } + /* Create tunnel */ while (NULL != tunnel_get_by_pi (myid, next_tid)) next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; - t = tunnel_new (myid, next_tid++, c, tid); + t = tunnel_new (myid, next_tid, c, tid); + next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; if (NULL == t) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Tunnel creation failed.\n"); GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - next_tid = next_tid & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s [%x] (%x)\n", - GNUNET_i2s (&my_full_id), t->id.tid, t->local_tid); - t->peers = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); + t->port = ntohl (t_msg->port); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED TUNNEL %s[%x]:%u (%x)\n", + GNUNET_i2s (&my_full_id), t->id.tid, t->port, t->local_tid); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new tunnel created\n"); + peer_info = peer_get (&t_msg->peer); + peer_info_add_tunnel (peer_info, t); + peer_connect (peer_info, t); GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } @@ -6615,80 +4231,24 @@ handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client, GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - if (c != t->owner || tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) - { - client_ignore_tunnel (c, t); - tunnel_destroy_empty (t); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } - send_client_tunnel_disconnect (t, c); - client_delete_tunnel (c, t); - /* Don't try to ACK the client about the tunnel_destroy multicast packet */ - t->owner = NULL; - tunnel_send_destroy (t, 0); - t->destroy = GNUNET_YES; - /* The tunnel will be destroyed when the last message is transmitted. */ - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; -} - - -/** - * Handler for requests of seeting tunnel's speed. - * - * @param cls Closure (unused). - * @param client Identification of the client. - * @param message The actual message. - */ -static void -handle_local_tunnel_speed (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_log (GNUNET_ERROR_TYPE_DEBUG, - "Got a SPEED request from client!\n"); - - /* Sanity check for client registration */ - if (NULL == (c = client_get (client))) + /* Cleanup after the tunnel */ + client_delete_tunnel (c, t); + if (c == t->client) { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; + t->client = NULL; } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); - - tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message; - - /* Retrieve tunnel */ - tid = ntohl (tunnel_msg->tunnel_id); - t = tunnel_get_by_local_id(c, tid); - if (NULL == t) + else if (c == t->owner) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " tunnel %X not found\n", tid); - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; + peer_info_remove_tunnel (peer_get_short (t->dest), t); + t->owner = NULL; } - switch (ntohs(message->type)) - { - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN: - t->speed_min = GNUNET_YES; - break; - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX: - t->speed_min = GNUNET_NO; - break; - default: - GNUNET_break (0); - } + /* The tunnel will be destroyed when the last message is transmitted. */ + tunnel_destroy_empty (t); + GNUNET_SERVER_receive_done (client, GNUNET_OK); + return; } @@ -6750,479 +4310,6 @@ handle_local_tunnel_buffer (void *cls, struct GNUNET_SERVER_Client *client, /** - * 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 MeshPeerInfo *peer_info; - struct MeshClient *c; - struct MeshTunnel *t; - MESH_TunnelNumber tid; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got connection request\n"); - /* Sanity check for client registration */ - if (NULL == (c = 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); - - 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 = tunnel_get_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->owner->handle != client) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", - GNUNET_i2s (&peer_msg->peer)); - peer_info = peer_info_get (&peer_msg->peer); - - tunnel_add_peer (t, peer_info); - peer_info_connect (peer_info, t); - - 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 MeshPeerInfo *peer_info; - struct MeshClient *c; - struct MeshTunnel *t; - MESH_TunnelNumber tid; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER DEL request\n"); - /* Sanity check for client registration */ - if (NULL == (c = 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); - - 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 = tunnel_get_by_local_id (c, tid); - if (NULL == t) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", t->id.tid); - - /* Does client own tunnel? */ - if (t->owner->handle != client) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for peer %s\n", - GNUNET_i2s (&peer_msg->peer)); - /* Is the peer in the tunnel? */ - peer_info = - GNUNET_CONTAINER_multihashmap_get (t->peers, &peer_msg->peer.hashPubKey); - if (NULL == peer_info) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Ok, delete peer from tunnel */ - GNUNET_CONTAINER_multihashmap_remove_all (t->peers, - &peer_msg->peer.hashPubKey); - - send_destroy_path (t, peer_info->id); - tunnel_delete_peer (t, peer_info->id); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; -} - -/** - * Handler for blacklist requests of peers in a tunnel - * - * @param cls closure - * @param client identification of the client - * @param message the actual message (PeerControl) - * - * FIXME implement DHT block bloomfilter - */ -static void -handle_local_blacklist (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_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER BLACKLIST request\n"); - /* Sanity check for client registration */ - if (NULL == (c = 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); - - 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 = tunnel_get_by_local_id (c, tid); - if (NULL == t) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", t->id.tid); - - GNUNET_array_append(t->blacklisted, t->nblacklisted, - GNUNET_PEER_intern(&peer_msg->peer)); -} - - -/** - * Handler for unblacklist 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_unblacklist (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 pid; - unsigned int i; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a PEER UNBLACKLIST request\n"); - /* Sanity check for client registration */ - if (NULL == (c = 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); - - 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 = tunnel_get_by_local_id (c, tid); - if (NULL == t) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", t->id.tid); - - /* if peer is not known, complain */ - pid = GNUNET_PEER_search (&peer_msg->peer); - if (0 == pid) - { - GNUNET_break (0); - return; - } - - /* search and remove from list */ - for (i = 0; i < t->nblacklisted; i++) - { - if (t->blacklisted[i] == pid) - { - t->blacklisted[i] = t->blacklisted[t->nblacklisted - 1]; - GNUNET_array_grow (t->blacklisted, t->nblacklisted, t->nblacklisted - 1); - return; - } - } - - /* if peer hasn't been blacklisted, complain */ - GNUNET_break (0); -} - - -/** - * 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; - struct MeshClient *c; - struct MeshTunnel *t; - struct GNUNET_HashCode hash; - MESH_TunnelNumber tid; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got connect by type request\n"); - /* Sanity check for client registration */ - if (NULL == (c = 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); - - connect_msg = (struct GNUNET_MESH_ConnectPeerByType *) message; - - /* Sanity check for message size */ - if (sizeof (struct GNUNET_MESH_ConnectPeerByType) != - 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 = tunnel_get_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->owner->handle != client) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Do WE have the service? */ - t->type = ntohl (connect_msg->type); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " type requested: %u\n", t->type); - GNUNET_CRYPTO_hash (&t->type, sizeof (GNUNET_MESH_ApplicationType), &hash); - if (GNUNET_CONTAINER_multihashmap_contains (applications, &hash) == - GNUNET_YES) - { - /* Yes! Fast forward, add ourselves to the tunnel and send the - * good news to the client, and alert the destination client of - * an incoming tunnel. - * - * FIXME send a path create to self, avoid code duplication - */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " available locally\n"); - GNUNET_CONTAINER_multihashmap_put (t->peers, &my_full_id.hashPubKey, - peer_info_get (&my_full_id), - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " notifying client\n"); - send_client_peer_connected (t, myid); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Done\n"); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - - t->local_tid_dest = next_local_tid++; - GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash); - GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); - - return; - } - /* Ok, lets find a peer offering the service */ - if (NULL != t->dht_get_type) - { - GNUNET_DHT_get_stop (t->dht_get_type); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " looking in DHT for %s\n", - GNUNET_h2s (&hash)); - t->dht_get_type = - GNUNET_DHT_get_start (dht_handle, - GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE, - &hash, - dht_replication_level, - GNUNET_DHT_RO_RECORD_ROUTE | - GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, - NULL, 0, - &dht_get_type_handler, t); - - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; -} - - -/** - * Handler for connection requests to new peers by a string service description. - * - * @param cls closure - * @param client identification of the client - * @param message the actual message, which includes messages the client wants - */ -static void -handle_local_connect_by_string (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_ConnectPeerByString *msg; - struct MeshRegexSearchInfo *info; - struct MeshTunnel *t; - struct MeshClient *c; - MESH_TunnelNumber tid; - const char *string; - size_t size; - size_t len; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connect by string started\n"); - msg = (struct GNUNET_MESH_ConnectPeerByString *) message; - size = htons (message->size); - - /* Sanity check for client registration */ - if (NULL == (c = 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); - - /* Message size sanity check */ - if (sizeof(struct GNUNET_MESH_ConnectPeerByString) >= size) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Tunnel exists? */ - tid = ntohl (msg->tunnel_id); - t = tunnel_get_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->owner->handle != client) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " on tunnel %s [%u]\n", - GNUNET_i2s(&my_full_id), - t->id.tid); - - /* Only one connect_by_string allowed at the same time! */ - /* FIXME: allow more, return handle at api level to cancel, document */ - if (NULL != t->regex_search) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Find string itself */ - len = size - sizeof(struct GNUNET_MESH_ConnectPeerByString); - string = (const char *) &msg[1]; - - info = GNUNET_malloc (sizeof (struct MeshRegexSearchInfo)); - info->t = t; - info->description = GNUNET_strndup (string, len); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " string: %s\n", info->description); - - t->regex_search = info; - - info->search_handle = GNUNET_REGEX_search (cfg, - info->description, - ®ex_found_handler, info); - - GNUNET_SERVER_receive_done (client, GNUNET_OK); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connect by string processed\n"); -} - - -/** * Handler for client traffic directed to one peer * * @param cls closure @@ -7235,8 +4322,7 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client, { struct MeshClient *c; struct MeshTunnel *t; - struct MeshPeerInfo *pi; - struct GNUNET_MESH_Unicast *data_msg; + struct GNUNET_MESH_Data *data_msg; MESH_TunnelNumber tid; size_t size; @@ -7252,11 +4338,11 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client, } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); - data_msg = (struct GNUNET_MESH_Unicast *) message; + data_msg = (struct GNUNET_MESH_Data *) message; /* Sanity check for message size */ size = ntohs (message->size); - if (sizeof (struct GNUNET_MESH_Unicast) + + if (sizeof (struct GNUNET_MESH_Data) + sizeof (struct GNUNET_MessageHeader) > size) { GNUNET_break (0); @@ -7282,23 +4368,13 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client, return; } - pi = GNUNET_CONTAINER_multihashmap_get (t->peers, - &data_msg->destination.hashPubKey); - /* Is the selected peer in the tunnel? */ - if (NULL == pi) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* PID should be as expected */ - if (ntohl (data_msg->pid) != t->fwd_pid + 1) + /* PID should be as expected: client<->service communication */ + if (ntohl (data_msg->pid) != t->prev_fc.last_pid_recv + 1) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unicast PID, expected %u, got %u\n", - t->fwd_pid + 1, ntohl (data_msg->pid)); + t->prev_fc.last_pid_recv + 1, ntohl (data_msg->pid)); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } @@ -7309,16 +4385,16 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client, { /* Work around const limitation */ char buf[ntohs (message->size)] GNUNET_ALIGN; - struct GNUNET_MESH_Unicast *copy; + struct GNUNET_MESH_Data *copy; - copy = (struct GNUNET_MESH_Unicast *) buf; + copy = (struct GNUNET_MESH_Data *) buf; memcpy (buf, data_msg, size); copy->oid = my_full_id; copy->tid = htonl (t->id.tid); copy->ttl = htonl (default_ttl); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " calling generic handler...\n"); - handle_mesh_data_unicast (NULL, &my_full_id, ©->header); + handle_mesh_unicast (NULL, &my_full_id, ©->header); } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n"); GNUNET_SERVER_receive_done (client, GNUNET_OK); @@ -7338,8 +4414,8 @@ static void handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { - struct GNUNET_MESH_ToOrigin *data_msg; - struct MeshTunnelClientInfo *clinfo; + struct GNUNET_MESH_Data *data_msg; + struct MeshFlowControl *fc; struct MeshClient *c; struct MeshTunnel *t; MESH_TunnelNumber tid; @@ -7356,11 +4432,11 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); - data_msg = (struct GNUNET_MESH_ToOrigin *) message; + data_msg = (struct GNUNET_MESH_Data *) message; /* Sanity check for message size */ size = ntohs (message->size); - if (sizeof (struct GNUNET_MESH_ToOrigin) + + if (sizeof (struct GNUNET_MESH_Data) + sizeof (struct GNUNET_MessageHeader) > size) { GNUNET_break (0); @@ -7388,7 +4464,7 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, } /* It should be sent by someone who has this as incoming tunnel. */ - if (GNUNET_NO == client_knows_tunnel (c, t)) + if (t->client != c) { GNUNET_break (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); @@ -7396,38 +4472,35 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, } /* PID should be as expected */ - clinfo = tunnel_get_client_fc (t, c); - if (ntohl (data_msg->pid) != clinfo->bck_pid + 1) + fc = &t->next_fc; + if (ntohl (data_msg->pid) != fc->last_pid_recv + 1) { GNUNET_break (0); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "To Origin PID, expected %u, got %u\n", - clinfo->bck_pid + 1, + fc->last_pid_recv + 1, ntohl (data_msg->pid)); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); return; } - clinfo->bck_pid++; /* Ok, everything is correct, send the message * (pretend we got it from a mesh peer) */ { char buf[ntohs (message->size)] GNUNET_ALIGN; - struct GNUNET_MESH_ToOrigin *copy; + struct GNUNET_MESH_Data *copy; - /* Work around const limitation */ - copy = (struct GNUNET_MESH_ToOrigin *) buf; + /* Work around 'const' limitation */ memcpy (buf, data_msg, size); + copy = (struct GNUNET_MESH_Data *) buf; GNUNET_PEER_resolve (t->id.oid, ©->oid); copy->tid = htonl (t->id.tid); copy->ttl = htonl (default_ttl); - copy->pid = htonl (t->bck_pid + 1); - copy->sender = my_full_id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " calling generic handler...\n"); - handle_mesh_data_to_orig (NULL, &my_full_id, ©->header); + handle_mesh_to_orig (NULL, &my_full_id, ©->header); } GNUNET_SERVER_receive_done (client, GNUNET_OK); @@ -7436,97 +4509,6 @@ handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client, /** - * Handler for client traffic directed to all peers in a tunnel - * - * @param cls closure - * @param client identification of the client - * @param message the actual message - */ -static void -handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) -{ - struct MeshClient *c; - struct MeshTunnel *t; - struct GNUNET_MESH_Multicast *data_msg; - MESH_TunnelNumber tid; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got a multicast request from a client!\n"); - - /* Sanity check for client registration */ - if (NULL == (c = 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); - - data_msg = (struct GNUNET_MESH_Multicast *) message; - - /* Sanity check for message size */ - if (sizeof (struct GNUNET_MESH_Multicast) + - sizeof (struct GNUNET_MessageHeader) > ntohs (data_msg->header.size)) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Tunnel exists? */ - tid = ntohl (data_msg->tid); - t = tunnel_get_by_local_id (c, tid); - if (NULL == t) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel %X unknown.\n", tid); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " for client %u.\n", c->id); - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* Does client own tunnel? */ - if (t->owner->handle != client) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - /* PID should be as expected */ - if (ntohl (data_msg->pid) != t->fwd_pid + 1) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Multicast PID, expected %u, got %u\n", - t->fwd_pid + 1, ntohl (data_msg->pid)); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } - - { - char buf[ntohs (message->size)] GNUNET_ALIGN; - struct GNUNET_MESH_Multicast *copy; - - copy = (struct GNUNET_MESH_Multicast *) buf; - memcpy (buf, message, ntohs (message->size)); - copy->oid = my_full_id; - copy->tid = htonl (t->id.tid); - copy->ttl = htonl (default_ttl); - GNUNET_assert (ntohl (copy->pid) == (t->fwd_pid + 1)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " calling generic handler...\n"); - handle_mesh_data_multicast (client, &my_full_id, ©->header); - } - - GNUNET_SERVER_receive_done (t->owner->handle, GNUNET_OK); - return; -} - - -/** * Handler for client's ACKs for payload traffic. * * @param cls Closure (unused). @@ -7568,20 +4550,20 @@ handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client, return; } - ack = ntohl (msg->max_pid); + ack = ntohl (msg->ack); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack); /* Does client own tunnel? I.E: Is this an ACK for BCK traffic? */ - if (NULL != t->owner && t->owner->handle == client) + if (t->owner == c) { /* The client owns the tunnel, ACK is for data to_origin, send BCK ACK. */ - t->bck_ack = ack; - tunnel_send_bck_ack(t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); + t->prev_fc.last_ack_recv = ack; + tunnel_send_bck_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); } else { /* The client doesn't own the tunnel, this ACK is for FWD traffic. */ - tunnel_set_client_fwd_ack (t, c, ack); + t->next_fc.last_ack_recv = ack; tunnel_send_fwd_ack (t, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); } @@ -7591,36 +4573,6 @@ handle_local_ack (void *cls, struct GNUNET_SERVER_Client *client, } -/** - * Iterator over all peers to send a monitoring client info about a tunnel. - * - * @param cls Closure (message being built). - * @param key Key (hashed tunnel ID, unused). - * @param value Peer info. - * - * @return GNUNET_YES, to keep iterating. - */ -static int -monitor_peers_iterator (void *cls, - const struct GNUNET_HashCode * key, - void *value) -{ - struct GNUNET_MESH_LocalMonitor *msg = cls; - struct GNUNET_PeerIdentity *id; - struct MeshPeerInfo *info = value; - - id = (struct GNUNET_PeerIdentity *) &msg[1]; - GNUNET_PEER_resolve (info->id, &id[msg->npeers]); - msg->npeers++; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "* sending info about peer %s [%u]\n", - GNUNET_i2s (&id[msg->npeers - 1]), msg->npeers); - - return GNUNET_YES; -} - - /** * Iterator over all tunnels to send a monitoring client info about each tunnel. @@ -7639,37 +4591,21 @@ monitor_all_tunnels_iterator (void *cls, struct GNUNET_SERVER_Client *client = cls; struct MeshTunnel *t = value; struct GNUNET_MESH_LocalMonitor *msg; - uint32_t npeers; - - npeers = GNUNET_CONTAINER_multihashmap_size (t->peers); - msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor) + - npeers * sizeof (struct GNUNET_PeerIdentity)); + + msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor)); GNUNET_PEER_resolve(t->id.oid, &msg->owner); msg->tunnel_id = htonl (t->id.tid); - msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor) + - npeers * sizeof (struct GNUNET_PeerIdentity)); + msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor)); msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS); - msg->npeers = 0; - (void) GNUNET_CONTAINER_multihashmap_iterate (t->peers, - monitor_peers_iterator, - msg); - + GNUNET_PEER_resolve (t->dest, &msg->destination); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "* sending info about tunnel %s [%u] (%u peers)\n", - GNUNET_i2s (&msg->owner), t->id.tid, npeers); - - if (msg->npeers != npeers) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Get tunnels fail: size %u - iter %u\n", - npeers, msg->npeers); - } - - msg->npeers = htonl (npeers); - GNUNET_SERVER_notification_context_unicast (nc, client, - &msg->header, GNUNET_NO); - return GNUNET_YES; + "* sending info about tunnel %s [%u]\n", + GNUNET_i2s (&msg->owner), t->id.tid); + + GNUNET_SERVER_notification_context_unicast (nc, client, + &msg->header, GNUNET_NO); + return GNUNET_YES; } @@ -7708,107 +4644,6 @@ handle_local_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client, /** - * Data needed to build a Monitor_Tunnel message. - */ -struct MeshMonitorTunnelContext -{ - /** - * Partial message, including peer count. - */ - struct GNUNET_MESH_LocalMonitor *msg; - - /** - * Hashmap with positions: peer->position. - */ - struct GNUNET_CONTAINER_MultiHashMap *lookup; - - /** - * Index of the parent of each peer in the message, realtive to the absolute - * order in the array (can be in a previous message). - */ - uint32_t parents[1024]; - - /** - * Peers visited so far in the tree, aka position of the current peer. - */ - unsigned int npeers; - - /** - * Client requesting the info. - */ - struct MeshClient *c; -}; - - -/** - * Send a client a message about the structure of a tunnel. - * - * @param ctx Context of the tunnel iteration, with info regarding the state - * of the execution and the number of peers visited for this message. - */ -static void -send_client_tunnel_info (struct MeshMonitorTunnelContext *ctx) -{ - struct GNUNET_MESH_LocalMonitor *resp = ctx->msg; - struct GNUNET_PeerIdentity *pid; - unsigned int *parent; - size_t size; - - size = sizeof (struct GNUNET_MESH_LocalMonitor); - size += (sizeof (struct GNUNET_PeerIdentity) + sizeof (int)) * resp->npeers; - resp->header.size = htons (size); - pid = (struct GNUNET_PeerIdentity *) &resp[1]; - parent = (unsigned int *) &pid[resp->npeers]; - memcpy (parent, ctx->parents, sizeof(uint32_t) * resp->npeers); - GNUNET_SERVER_notification_context_unicast (nc, ctx->c->handle, - &resp->header, GNUNET_NO); -} - -/** - * Iterator over a tunnel tree to build a message containing all peers - * the in the tunnel, including relay nodes. - * - * @param cls Closure (pointer to pointer of message being built). - * @param peer Short ID of a peer. - * @param parent Short ID of the @c peer 's parent. - */ -static void -tunnel_tree_iterator (void *cls, - GNUNET_PEER_Id peer, - GNUNET_PEER_Id parent) -{ - struct MeshMonitorTunnelContext *ctx = cls; - struct GNUNET_MESH_LocalMonitor *msg; - struct GNUNET_PeerIdentity *pid; - struct GNUNET_PeerIdentity ppid; - - msg = ctx->msg; - pid = (struct GNUNET_PeerIdentity *) &msg[1]; - GNUNET_PEER_resolve (peer, &pid[msg->npeers]); - GNUNET_CONTAINER_multihashmap_put (ctx->lookup, - &pid[msg->npeers].hashPubKey, - (void *) (long) ctx->npeers, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); - GNUNET_PEER_resolve (parent, &ppid); - ctx->parents[msg->npeers] = - htonl ((long) GNUNET_CONTAINER_multihashmap_get (ctx->lookup, - &ppid.hashPubKey)); - - ctx->npeers++; - msg->npeers++; - - if (sizeof (struct GNUNET_MESH_LocalMonitor) + - (msg->npeers + 1) * - (sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t)) - > USHRT_MAX) - { - send_client_tunnel_info (ctx); - msg->npeers = 0; - } -} - - -/** * Handler for client's MONITOR_TUNNEL request. * * @param cls Closure (unused). @@ -7821,7 +4656,6 @@ handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, { const struct GNUNET_MESH_LocalMonitor *msg; struct GNUNET_MESH_LocalMonitor *resp; - struct MeshMonitorTunnelContext ctx; struct MeshClient *c; struct MeshTunnel *t; @@ -7842,11 +4676,10 @@ handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, t = tunnel_get (&msg->owner, ntohl (msg->tunnel_id)); if (NULL == t) { - /* We don't know the tunnel */ + /* We don't know the tunnel FIXME */ struct GNUNET_MESH_LocalMonitor warn; warn = *msg; - warn.npeers = htonl (UINT_MAX); GNUNET_SERVER_notification_context_unicast (nc, client, &warn.header, GNUNET_NO); @@ -7855,19 +4688,12 @@ handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, } /* Initialize context */ - resp = GNUNET_malloc (USHRT_MAX); /* avoid realloc'ing on each step */ + resp = GNUNET_malloc (sizeof (struct GNUNET_MESH_LocalMonitor)); *resp = *msg; - resp->npeers = 0; - ctx.msg = resp; - ctx.lookup = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES); - ctx.c = c; - - /* Collect and send information */ - tree_iterate_all (t->tree, &tunnel_tree_iterator, &ctx); - send_client_tunnel_info (&ctx); - - /* Free context */ - GNUNET_CONTAINER_multihashmap_destroy (ctx.lookup); + GNUNET_PEER_resolve (t->dest, &resp->destination); + resp->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor)); + GNUNET_SERVER_notification_context_unicast (nc, c->handle, + &resp->header, GNUNET_NO); GNUNET_free (resp); GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -7883,49 +4709,22 @@ handle_local_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, static struct GNUNET_SERVER_MessageHandler client_handlers[] = { {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0}, - {&handle_local_announce_regex, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX, 0}, {&handle_local_tunnel_create, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE, sizeof (struct GNUNET_MESH_TunnelMessage)}, {&handle_local_tunnel_destroy, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY, sizeof (struct GNUNET_MESH_TunnelMessage)}, - {&handle_local_tunnel_speed, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN, - sizeof (struct GNUNET_MESH_TunnelMessage)}, - {&handle_local_tunnel_speed, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX, - sizeof (struct GNUNET_MESH_TunnelMessage)}, {&handle_local_tunnel_buffer, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER, sizeof (struct GNUNET_MESH_TunnelMessage)}, {&handle_local_tunnel_buffer, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER, sizeof (struct GNUNET_MESH_TunnelMessage)}, - {&handle_local_connect_add, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD, - sizeof (struct GNUNET_MESH_PeerControl)}, - {&handle_local_connect_del, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL, - sizeof (struct GNUNET_MESH_PeerControl)}, - {&handle_local_blacklist, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST, - sizeof (struct GNUNET_MESH_PeerControl)}, - {&handle_local_unblacklist, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST, - sizeof (struct GNUNET_MESH_PeerControl)}, - {&handle_local_connect_by_type, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE, - sizeof (struct GNUNET_MESH_ConnectPeerByType)}, - {&handle_local_connect_by_string, NULL, - GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING, 0}, {&handle_local_unicast, NULL, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0}, {&handle_local_to_origin, NULL, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0}, - {&handle_local_multicast, NULL, - GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0}, {&handle_local_ack, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK, sizeof (struct GNUNET_MESH_LocalAck)}, @@ -7940,38 +4739,6 @@ static struct GNUNET_SERVER_MessageHandler client_handlers[] = { /** - * To be called on core init/fail. - * - * @param cls service closure - * @param server handle to the server for this service - * @param identity the public identity of this peer - */ -static void -core_init (void *cls, struct GNUNET_CORE_Handle *server, - const struct GNUNET_PeerIdentity *identity) -{ - static int i = 0; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n"); - core_handle = server; - if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)) || - NULL == server) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n")); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - " core id %s\n", - GNUNET_i2s (identity)); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - " my id %s\n", - GNUNET_i2s (&my_full_id)); - GNUNET_SCHEDULER_shutdown (); // Try gracefully - if (10 < i++) - GNUNET_abort(); // Try harder - } - return; -} - - -/** * Method called whenever a given peer connects. * * @param cls closure @@ -7985,23 +4752,23 @@ core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) DEBUG_CONN ("Peer connected\n"); DEBUG_CONN (" %s\n", GNUNET_i2s (&my_full_id)); - peer_info = peer_info_get (peer); + peer_info = peer_get (peer); if (myid == peer_info->id) { DEBUG_CONN (" (self)\n"); - return; + path = path_new (1); } else { DEBUG_CONN (" %s\n", GNUNET_i2s (peer)); + path = path_new (2); + path->peers[1] = peer_info->id; + GNUNET_PEER_change_rc (peer_info->id, 1); + GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO); } - path = path_new (2); path->peers[0] = myid; - path->peers[1] = peer_info->id; GNUNET_PEER_change_rc (myid, 1); - GNUNET_PEER_change_rc (peer_info->id, 1); peer_info_add_path (peer_info, path, GNUNET_YES); - GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO); return; } @@ -8039,7 +4806,7 @@ core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) GNUNET_CORE_notify_transmit_ready_cancel(pi->core_transmit); pi->core_transmit = NULL; } - peer_info_remove_path (pi, pi->id, myid); + peer_remove_path (pi, pi->id, myid); if (myid == pi->id) { DEBUG_CONN (" (self)\n"); @@ -8049,6 +4816,69 @@ core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) } +/** + * Install server (service) handlers and start listening to clients. + */ +static void +server_init (void) +{ + GNUNET_SERVER_add_handlers (server_handle, client_handlers); + GNUNET_SERVER_disconnect_notify (server_handle, + &handle_local_client_disconnect, NULL); + nc = GNUNET_SERVER_notification_context_create (server_handle, 1); + + clients_head = NULL; + clients_tail = NULL; + next_client_id = 0; + GNUNET_SERVER_resume (server_handle); +} + + +/** + * To be called on core init/fail. + * + * @param cls Closure (config) + * @param server handle to the server for this service + * @param identity the public identity of this peer + */ +static void +core_init (void *cls, struct GNUNET_CORE_Handle *server, + const struct GNUNET_PeerIdentity *identity) +{ + const struct GNUNET_CONFIGURATION_Handle *c = cls; + static int i = 0; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n"); + GNUNET_break (core_handle == server); + if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)) || + NULL == server) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n")); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + " core id %s\n", + GNUNET_i2s (identity)); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + " my id %s\n", + GNUNET_i2s (&my_full_id)); + GNUNET_CORE_disconnect (core_handle); + core_handle = GNUNET_CORE_connect (c, /* Main configuration */ + NULL, /* Closure passed to MESH functions */ + &core_init, /* Call core_init once connected */ + &core_connect, /* Handle connects */ + &core_disconnect, /* remove peers on disconnects */ + NULL, /* Don't notify about all incoming messages */ + GNUNET_NO, /* For header only in notification */ + NULL, /* Don't notify about all outbound messages */ + GNUNET_NO, /* For header-only out notification */ + core_handlers); /* Register these handlers */ + if (10 < i++) + GNUNET_abort(); + } + server_init (); + return; +} + + /******************************************************************************/ /************************ MAIN FUNCTIONS ****************************/ /******************************************************************************/ @@ -8140,11 +4970,6 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_SCHEDULER_cancel (announce_id_task); announce_id_task = GNUNET_SCHEDULER_NO_TASK; } - if (GNUNET_SCHEDULER_NO_TASK != announce_applications_task) - { - GNUNET_SCHEDULER_cancel (announce_applications_task); - announce_applications_task = GNUNET_SCHEDULER_NO_TASK; - } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); } @@ -8162,10 +4987,8 @@ key_generation_cb (void *cls, const char *emsg) { const struct GNUNET_CONFIGURATION_Handle *c = cls; - struct MeshPeerInfo *peer; - struct MeshPeerPath *p; - keygen = NULL; + keygen = NULL; if (NULL == pk) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -8193,7 +5016,6 @@ key_generation_cb (void *cls, NULL, /* Don't notify about all outbound messages */ GNUNET_NO, /* For header-only out notification */ core_handlers); /* Register these handlers */ - if (core_handle == NULL) { GNUNET_break (0); @@ -8204,27 +5026,8 @@ key_generation_cb (void *cls, next_tid = 0; next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; - - GNUNET_SERVER_add_handlers (server_handle, client_handlers); - nc = GNUNET_SERVER_notification_context_create (server_handle, 1); - GNUNET_SERVER_disconnect_notify (server_handle, - &handle_local_client_disconnect, NULL); - - - clients = NULL; - clients_tail = NULL; - next_client_id = 0; - - announce_applications_task = GNUNET_SCHEDULER_NO_TASK; announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls); - /* Create a peer_info for the local peer */ - peer = peer_info_get (&my_full_id); - p = path_new (1); - p->peers[0] = myid; - GNUNET_PEER_change_rc (myid, 1); - peer_info_add_path (peer, p, GNUNET_YES); - GNUNET_SERVER_resume (server_handle); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n"); } @@ -8242,9 +5045,9 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, { char *keyfile; - cfg = c; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n"); server_handle = server; + GNUNET_SERVER_suspend (server_handle); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (c, "PEER", "PRIVATE_KEY", @@ -8271,20 +5074,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, } if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (c, "MESH", "APP_ANNOUNCE_TIME", - &app_announce_time)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("%s service is lacking key configuration settings (%s). Exiting.\n"), - "mesh", "app announce time"); - GNUNET_SCHEDULER_shutdown (); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "APP_ANNOUNCE_TIME %llu ms\n", - app_announce_time.rel_value); - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME", &id_announce_time)) { @@ -8367,8 +5156,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); peers = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); - applications = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); - types = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); + ports = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); dht_handle = GNUNET_DHT_connect (c, 64); if (NULL == dht_handle) @@ -8377,7 +5165,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, } stats = GNUNET_STATISTICS_create ("mesh", c); - GNUNET_SERVER_suspend (server_handle); /* Scheduled the task to clean up when shutdown is called */ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, NULL); diff --git a/src/mesh/mesh.h b/src/mesh/mesh.h index a5a817c486..360bfabb44 100644 --- a/src/mesh/mesh.h +++ b/src/mesh/mesh.h @@ -38,9 +38,6 @@ extern "C" #define MESH_DEBUG GNUNET_YES -#define INITIAL_WINDOW_SIZE 8 -#define ACK_THRESHOLD INITIAL_WINDOW_SIZE / 2 - #include "platform.h" #include "gnunet_common.h" #include "gnunet_util_lib.h" @@ -63,18 +60,8 @@ extern "C" * * tunnel_create GNUNET_MESH_TunnelMessage * tunnel_destroy GNUNET_MESH_TunnelMessage - * tunnel_speed_max GNUNET_MESH_TunnelMessage - * tunnel_speed_min GNUNET_MESH_TunnelMessage * tunnel_buffer GNUNET_MESH_TunnelMessage * - * peer_request_connect_add GNUNET_MESH_PeerControl - * peer_request_connect_del GNUNET_MESH_PeerControl - * peer_request_connect_by_type GNUNET_MESH_ConnectPeerByType - * peer_request_connect_by_string GNUNET_MESH_ConnectPeerByString - * - * peer_blacklist GNUNET_MESH_PeerControl - * peer_unblacklist GNUNET_MESH_PeerControl - * * notify_transmit_ready None (queue / GNUNET_CLIENT_ntf_tmt_rdy) * notify_transmit_ready_cancel None (clear of internal data structures) * @@ -87,8 +74,8 @@ extern "C" * data ack GNUNET_MESH_LocalAck * * new incoming tunnel GNUNET_MESH_PeerControl - * peer connects to a tunnel GNUNET_MESH_PeerControl - * peer disconnects from a tunnel GNUNET_MESH_PeerControl + * peer connects to a tunnel FIXME + * peer disconnects from a tunnel FIXME */ /******************************************************************************/ @@ -122,10 +109,7 @@ struct GNUNET_MESH_ClientConnect * sizeof(uint16_t) * types */ struct GNUNET_MessageHeader header; - uint16_t applications GNUNET_PACKED; - uint16_t types GNUNET_PACKED; - /* uint32_t list_apps[applications] */ - /* uint16_t list_types[types] */ + /* uint32_t list_ports[] */ }; @@ -137,6 +121,7 @@ struct GNUNET_MESH_ClientConnect */ typedef uint32_t MESH_TunnelNumber; + /** * Message for a client to create and destroy tunnels. */ @@ -144,26 +129,6 @@ struct GNUNET_MESH_TunnelMessage { /** * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[CREATE|DESTROY] - * GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[MAX|MIN] - * - * Size: sizeof(struct GNUNET_MESH_TunnelMessage) - */ - struct GNUNET_MessageHeader header; - - /** - * ID of a tunnel controlled by this client. - */ - MESH_TunnelNumber tunnel_id GNUNET_PACKED; -}; - - -/** - * Message for the service to let a client know about created tunnels. - */ -struct GNUNET_MESH_TunnelNotification -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE * * Size: sizeof(struct GNUNET_MESH_TunnelMessage) */ @@ -175,60 +140,26 @@ struct GNUNET_MESH_TunnelNotification MESH_TunnelNumber tunnel_id GNUNET_PACKED; /** - * Peer at the other end, if any + * Tunnel's peer */ struct GNUNET_PeerIdentity peer; /** - * Tunnel options (speed, buffering) - */ - uint32_t opt; -}; - -/** - * Message for announce of regular expressions. - */ -struct GNUNET_MESH_RegexAnnounce -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX - * - * Size: sizeof(struct GNUNET_MESH_RegexAnnounce) + strlen (regex) - */ - struct GNUNET_MessageHeader header; - - /** - * How many characters do we want to put in an edge label. - */ - uint16_t compression_characters; - - /** - * Is this the last message for this regex? (for regex > 65k) + * Port of the tunnel. */ - int16_t last; - - /* regex payload */ + uint32_t port GNUNET_PACKED; }; /** - * Message for: - * - request adding and deleting peers from a tunnel - * - notify the client that peers have connected: - * -- requested - * -- unrequested (new incoming tunnels) - * - notify the client that peers have disconnected + * Message for the service to let a client know about created tunnels. */ -struct GNUNET_MESH_PeerControl +struct GNUNET_MESH_TunnelNotification { - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_[ADD|DEL|[UN]BLACKLIST] - * (client to service, client created tunnel) - * GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_[CONNECTED|DISCONNECTED] - * (service to client) + * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE * - * Size: sizeof(struct GNUNET_MESH_PeerControl) + * Size: sizeof(struct GNUNET_MESH_TunnelMessage) */ struct GNUNET_MessageHeader header; @@ -238,55 +169,19 @@ struct GNUNET_MESH_PeerControl MESH_TunnelNumber tunnel_id GNUNET_PACKED; /** - * Peer to connect/disconnect. + * Peer at the other end. */ struct GNUNET_PeerIdentity peer; -}; - - -/** - * Message for connecting to peers offering a service, by service number. - */ -struct GNUNET_MESH_ConnectPeerByType -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE | - * GNUNET_MESSAGE_TYPE_MESH_LOCAL_DISCONNECT_PEER_BY_TYPE - * - * Size: sizeof(struct GNUNET_MESH_ConnectPeerByType) - */ - struct GNUNET_MessageHeader header; - - /** - * ID of a tunnel controlled by this client. - */ - MESH_TunnelNumber tunnel_id GNUNET_PACKED; /** - * Type specification - */ - GNUNET_MESH_ApplicationType type GNUNET_PACKED; -}; - - -/** - * Message for connecting to peers offering a service, by service string. - */ -struct GNUNET_MESH_ConnectPeerByString -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING - * - * Size: sizeof(struct GNUNET_MESH_ConnectPeerByString) + strlen (string) + * Port for this tunnel */ - struct GNUNET_MessageHeader header; + uint32_t port GNUNET_PACKED; /** - * ID of a tunnel controlled by this client. + * Tunnel options (speed, buffering) */ - MESH_TunnelNumber tunnel_id GNUNET_PACKED; - - /* String describing the service */ + uint32_t opt GNUNET_PACKED; }; @@ -309,7 +204,7 @@ struct GNUNET_MESH_LocalAck /** * ID of the last packet allowed. */ - uint32_t max_pid GNUNET_PACKED; + uint32_t ack GNUNET_PACKED; }; @@ -329,11 +224,6 @@ struct GNUNET_MESH_LocalMonitor MESH_TunnelNumber tunnel_id GNUNET_PACKED; /** - * Number of peers in the tunnel. - */ - uint32_t npeers GNUNET_PACKED; - - /** * Alignment. */ uint32_t reserved GNUNET_PACKED; @@ -343,7 +233,10 @@ struct GNUNET_MESH_LocalMonitor */ struct GNUNET_PeerIdentity owner; - /* struct GNUNET_PeerIdentity peers[npeers] */ + /** + * ID of the destination of the tunnel (can be local peer). + */ + struct GNUNET_PeerIdentity destination; }; @@ -354,44 +247,34 @@ GNUNET_NETWORK_STRUCT_END /******************************************************************************/ /** - * All the states a peer participating in a tunnel can be in. + * All the states a tunnel can be in. */ -enum MeshPeerState +enum MeshTunnelState { /** * Uninitialized status, should never appear in operation. */ - MESH_PEER_INVALID, - - /** - * Peer is the root and owner of the tree - */ - MESH_PEER_ROOT, - - /** - * Peer only retransmits traffic, is not a final destination - */ - MESH_PEER_RELAY, + MESH_TUNNEL_NEW, /** * Path to the peer not known yet */ - MESH_PEER_SEARCHING, + MESH_TUNNEL_SEARCHING, /** * Request sent, not yet answered. */ - MESH_PEER_WAITING, + MESH_TUNNEL_WAITING, /** * Peer connected and ready to accept data */ - MESH_PEER_READY, + MESH_TUNNEL_READY, /** * Peer connected previosly but not responding */ - MESH_PEER_RECONNECTING + MESH_TUNNEL_RECONNECTING }; @@ -432,6 +315,18 @@ GMC_min_pid (uint32_t a, uint32_t b); /** + * Expand a 32 bit value (message type) into a hash for a MultiHashMap (fast). + * WARNING: do not use for anything other than MultiHashMap! + * does not alter anything other than bits used by idx_of ! + * + * @param i 32 bit integer value. + * @param h Hash code to fill. + */ +void +GMC_hash32 (uint32_t i, struct GNUNET_HashCode *h); + + +/** * Convert a message type into a string to help debug * Generated with: * FIND: "#define ([^ ]+)[ ]*([0-9]+)" diff --git a/src/mesh/mesh2.h b/src/mesh/mesh2.h deleted file mode 100644 index 360bfabb44..0000000000 --- a/src/mesh/mesh2.h +++ /dev/null @@ -1,349 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2001 - 2011 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @author Bartlomiej Polot - * @file mesh/mesh.h - */ - -#ifndef MESH_H_ -#define MESH_H_ - -#ifdef __cplusplus -extern "C" -{ -#if 0 /* keep Emacsens' auto-indent happy */ -} -#endif -#endif - -#include <stdint.h> - -#define MESH_DEBUG GNUNET_YES - -#include "platform.h" -#include "gnunet_common.h" -#include "gnunet_util_lib.h" -#include "gnunet_peer_lib.h" -#include "gnunet_core_service.h" -#include "gnunet_protocols.h" -#include <gnunet_mesh_service.h> - -/******************************************************************************/ -/******************** MESH LOCAL MESSAGES *************************/ -/******************************************************************************/ -/* Any API call should be documented in the folowing table under API CALL. - * Also, any message type should be documented in the following table, with the - * associated event. - * - * API CALL (GNUNET_MESH_*) MESSAGE USED - * ------------------------ ------------ - * connect GNUNET_MESH_ClientConnect - * disconnect None (network level disconnect) - * - * tunnel_create GNUNET_MESH_TunnelMessage - * tunnel_destroy GNUNET_MESH_TunnelMessage - * tunnel_buffer GNUNET_MESH_TunnelMessage - * - * notify_transmit_ready None (queue / GNUNET_CLIENT_ntf_tmt_rdy) - * notify_transmit_ready_cancel None (clear of internal data structures) - * - * - * EVENT MESSAGE USED - * ----- ------------ - * data GNUNET_MESH_Unicast OR - * GNUNET_MESH_Multicast OR - * GNUNET_MESH_ToOrigin - * data ack GNUNET_MESH_LocalAck - * - * new incoming tunnel GNUNET_MESH_PeerControl - * peer connects to a tunnel FIXME - * peer disconnects from a tunnel FIXME - */ - -/******************************************************************************/ -/************************** CONSTANTS ******************************/ -/******************************************************************************/ - -#define GNUNET_MESH_LOCAL_TUNNEL_ID_CLI 0x80000000 -#define GNUNET_MESH_LOCAL_TUNNEL_ID_SERV 0xB0000000 - -#define HIGH_PID 0xFFFF0000 -#define LOW_PID 0x0000FFFF - -#define PID_OVERFLOW(pid, max) (pid > HIGH_PID && max < LOW_PID) - -/******************************************************************************/ -/************************** MESSAGES ******************************/ -/******************************************************************************/ - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * Message for a client to register to the service - */ -struct GNUNET_MESH_ClientConnect -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT - * - * Size: sizeof(struct GNUNET_MESH_ClientConnect) + - * sizeof(MESH_ApplicationType) * applications + - * sizeof(uint16_t) * types - */ - struct GNUNET_MessageHeader header; - /* uint32_t list_ports[] */ -}; - - -/** - * Type for tunnel numbering. - * - Local tunnel numbers given by the service (incoming) are >= 0xB0000000 - * - Local tunnel numbers given by the client (created) are >= 0x80000000 - * - Global tunnel numbers are < 0x80000000 - */ -typedef uint32_t MESH_TunnelNumber; - - -/** - * Message for a client to create and destroy tunnels. - */ -struct GNUNET_MESH_TunnelMessage -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_[CREATE|DESTROY] - * - * Size: sizeof(struct GNUNET_MESH_TunnelMessage) - */ - struct GNUNET_MessageHeader header; - - /** - * ID of a tunnel controlled by this client. - */ - MESH_TunnelNumber tunnel_id GNUNET_PACKED; - - /** - * Tunnel's peer - */ - struct GNUNET_PeerIdentity peer; - - /** - * Port of the tunnel. - */ - uint32_t port GNUNET_PACKED; -}; - - -/** - * Message for the service to let a client know about created tunnels. - */ -struct GNUNET_MESH_TunnelNotification -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE - * - * Size: sizeof(struct GNUNET_MESH_TunnelMessage) - */ - struct GNUNET_MessageHeader header; - - /** - * ID of a tunnel controlled by this client. - */ - MESH_TunnelNumber tunnel_id GNUNET_PACKED; - - /** - * Peer at the other end. - */ - struct GNUNET_PeerIdentity peer; - - /** - * Port for this tunnel - */ - uint32_t port GNUNET_PACKED; - - /** - * Tunnel options (speed, buffering) - */ - uint32_t opt GNUNET_PACKED; -}; - - -/** - * Message to allow the client send more data to the service - * (always service -> client). - */ -struct GNUNET_MESH_LocalAck -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK - */ - struct GNUNET_MessageHeader header; - - /** - * ID of the tunnel allowed to send more data. - */ - MESH_TunnelNumber tunnel_id GNUNET_PACKED; - - /** - * ID of the last packet allowed. - */ - uint32_t ack GNUNET_PACKED; -}; - - -/** - * Message to inform the client about tunnels in the service. - */ -struct GNUNET_MESH_LocalMonitor -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_LOCAL_MONITOR[_TUNNEL] - */ - struct GNUNET_MessageHeader header; - - /** - * ID of the tunnel allowed to send more data. - */ - MESH_TunnelNumber tunnel_id GNUNET_PACKED; - - /** - * Alignment. - */ - uint32_t reserved GNUNET_PACKED; - - /** - * ID of the owner of the tunnel (can be local peer). - */ - struct GNUNET_PeerIdentity owner; - - /** - * ID of the destination of the tunnel (can be local peer). - */ - struct GNUNET_PeerIdentity destination; -}; - - -GNUNET_NETWORK_STRUCT_END - -/******************************************************************************/ -/************************ ENUMERATIONS ****************************/ -/******************************************************************************/ - -/** - * All the states a tunnel can be in. - */ -enum MeshTunnelState -{ - /** - * Uninitialized status, should never appear in operation. - */ - MESH_TUNNEL_NEW, - - /** - * Path to the peer not known yet - */ - MESH_TUNNEL_SEARCHING, - - /** - * Request sent, not yet answered. - */ - MESH_TUNNEL_WAITING, - - /** - * Peer connected and ready to accept data - */ - MESH_TUNNEL_READY, - - /** - * Peer connected previosly but not responding - */ - MESH_TUNNEL_RECONNECTING -}; - - -/** - * Check if one pid is bigger than other, accounting for overflow. - * - * @param bigger Argument that should be bigger. - * @param smaller Argument that should be smaller. - * - * @return True if bigger (arg1) has a higher value than smaller (arg 2). - */ -int -GMC_is_pid_bigger (uint32_t bigger, uint32_t smaller); - - -/** - * Get the higher ACK value out of two values, taking in account overflow. - * - * @param a First ACK value. - * @param b Second ACK value. - * - * @return Highest ACK value from the two. - */ -uint32_t -GMC_max_pid (uint32_t a, uint32_t b); - - -/** - * Get the lower ACK value out of two values, taking in account overflow. - * - * @param a First ACK value. - * @param b Second ACK value. - * - * @return Lowest ACK value from the two. - */ -uint32_t -GMC_min_pid (uint32_t a, uint32_t b); - - -/** - * Expand a 32 bit value (message type) into a hash for a MultiHashMap (fast). - * WARNING: do not use for anything other than MultiHashMap! - * does not alter anything other than bits used by idx_of ! - * - * @param i 32 bit integer value. - * @param h Hash code to fill. - */ -void -GMC_hash32 (uint32_t i, struct GNUNET_HashCode *h); - - -/** - * Convert a message type into a string to help debug - * Generated with: - * FIND: "#define ([^ ]+)[ ]*([0-9]+)" - * REPLACE: " case \2: return "\1"; break;" - * - * @param m Message type. - * - * @return Human readable string description. - */ -const char * -GNUNET_MESH_DEBUG_M2S (uint16_t m); - -#if 0 /* keep Emacsens' auto-indent happy */ -{ -#endif -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/mesh/mesh2_api.c b/src/mesh/mesh2_api.c deleted file mode 100644 index ef940f7e4d..0000000000 --- a/src/mesh/mesh2_api.c +++ /dev/null @@ -1,1787 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2011 Christian Grothoff (and other contributing authors) - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file mesh/mesh2_api.c - * @brief mesh2 api: client implementation of new mesh service - * @author Bartlomiej Polot - * - * STRUCTURE: - * - DATA STRUCTURES - * - DECLARATIONS - * - AUXILIARY FUNCTIONS - * - RECEIVE HANDLERS - * - SEND FUNCTIONS - * - API CALL DEFINITIONS - * - * TODO: add regex to reconnect - */ -#include "platform.h" -#include "gnunet_common.h" -#include "gnunet_client_lib.h" -#include "gnunet_util_lib.h" -#include "gnunet_peer_lib.h" -#include "gnunet_mesh2_service.h" -#include "mesh2.h" -#include "mesh2_protocol.h" - -#define LOG(kind,...) GNUNET_log_from (kind, "mesh2-api",__VA_ARGS__) -#define DEBUG_ACK GNUNET_YES - -/******************************************************************************/ -/************************ DATA STRUCTURES ****************************/ -/******************************************************************************/ - -/** - * Transmission queue to the service - */ -struct GNUNET_MESH_TransmitHandle -{ - - /** - * Double Linked list - */ - struct GNUNET_MESH_TransmitHandle *next; - - /** - * Double Linked list - */ - struct GNUNET_MESH_TransmitHandle *prev; - - /** - * Tunnel this message is sent on / for (may be NULL for control messages). - */ - struct GNUNET_MESH_Tunnel *tunnel; - - /** - * Callback to obtain the message to transmit, or NULL if we - * got the message in 'data'. Notice that messages built - * by 'notify' need to be encapsulated with information about - * the 'target'. - */ - GNUNET_CONNECTION_TransmitReadyNotify notify; - - /** - * Closure for 'notify' - */ - void *notify_cls; - - /** - * How long is this message valid. Once the timeout has been - * reached, the message must no longer be sent. If this - * is a message with a 'notify' callback set, the 'notify' - * function should be called with 'buf' NULL and size 0. - */ - struct GNUNET_TIME_Absolute timeout; - - /** - * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER. - */ - GNUNET_SCHEDULER_TaskIdentifier timeout_task; - - /** - * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL. - */ - size_t size; -}; - - -/** - * Opaque handle to the service. - */ -struct GNUNET_MESH_Handle -{ - - /** - * Handle to the server connection, to send messages later - */ - struct GNUNET_CLIENT_Connection *client; - - /** - * Set of handlers used for processing incoming messages in the tunnels - */ - const struct GNUNET_MESH_MessageHandler *message_handlers; - - /** - * Number of handlers in the handlers array. - */ - unsigned int n_handlers; - - /** - * Ports open. - */ - const uint32_t *ports; - - /** - * Number of ports. - */ - unsigned int n_ports; - - /** - * Double linked list of the tunnels this client is connected to, head. - */ - struct GNUNET_MESH_Tunnel *tunnels_head; - - /** - * Double linked list of the tunnels this client is connected to, tail. - */ - struct GNUNET_MESH_Tunnel *tunnels_tail; - - /** - * Callback for inbound tunnel creation - */ - GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel; - - /** - * Callback for inbound tunnel disconnection - */ - GNUNET_MESH_TunnelEndHandler *cleaner; - - /** - * Handle to cancel pending transmissions in case of disconnection - */ - struct GNUNET_CLIENT_TransmitHandle *th; - - /** - * Closure for all the handlers given by the client - */ - void *cls; - - /** - * Messages to send to the service, head. - */ - struct GNUNET_MESH_TransmitHandle *th_head; - - /** - * Messages to send to the service, tail. - */ - struct GNUNET_MESH_TransmitHandle *th_tail; - - /** - * tid of the next tunnel to create (to avoid reusing IDs often) - */ - MESH_TunnelNumber next_tid; - - /** - * Have we started the task to receive messages from the service - * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message. - */ - int in_receive; - - /** - * Configuration given by the client, in case of reconnection - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Time to the next reconnect in case one reconnect fails - */ - struct GNUNET_TIME_Relative reconnect_time; - - /** - * Task for trying to reconnect. - */ - GNUNET_SCHEDULER_TaskIdentifier reconnect_task; - - /** - * Monitor callback - */ - GNUNET_MESH_TunnelsCB tunnels_cb; - - /** - * Monitor callback closure. - */ - void *tunnels_cls; - - /** - * Tunnel callback. - */ - GNUNET_MESH_TunnelCB tunnel_cb; - - /** - * Tunnel callback closure. - */ - void *tunnel_cls; - -#if DEBUG_ACK - unsigned int acks_sent; - unsigned int acks_recv; -#endif -}; - - -/** - * Description of a peer - */ -struct GNUNET_MESH_Peer -{ - /** - * ID of the peer in short form - */ - GNUNET_PEER_Id id; - - /** - * Tunnel this peer belongs to - */ - struct GNUNET_MESH_Tunnel *t; - - /** - * Flag indicating whether service has informed about its connection - */ - int connected; - -}; - - -/** - * Opaque handle to a tunnel. - */ -struct GNUNET_MESH_Tunnel -{ - - /** - * DLL next - */ - struct GNUNET_MESH_Tunnel *next; - - /** - * DLL prev - */ - struct GNUNET_MESH_Tunnel *prev; - - /** - * Handle to the mesh this tunnel belongs to - */ - struct GNUNET_MESH_Handle *mesh; - - /** - * Local ID of the tunnel - */ - MESH_TunnelNumber tid; - - /** - * Port number. - */ - uint32_t port; - - /** - * Other end of the tunnel. - */ - GNUNET_PEER_Id peer; - - /** - * Any data the caller wants to put in here - */ - void *ctx; - - /** - * Size of packet queued in this tunnel - */ - unsigned int packet_size; - - /** - * Is the tunnel allowed to buffer? - */ - int buffering; - - /** - * Maximum allowed PID to send (last ACK recevied). - */ - uint32_t last_ack_recv; - - /** - * Last PID received from the service. - */ - uint32_t last_pid_recv; - - /** - * Last packet ID sent to the service. - */ - uint32_t last_pid_sent; - - /** - * Last ACK value sent to the service: how much are we willing to accept? - */ - uint32_t last_ack_sent; -}; - - -/** - * Implementation state for mesh's message queue. - */ -struct MeshMQState -{ - /** - * The current transmit handle, or NULL - * if no transmit is active. - */ - struct GNUNET_MESH_TransmitHandle *th; - - /** - * Tunnel to send the data over. - */ - struct GNUNET_MESH_Tunnel *tunnel; -}; - - -/******************************************************************************/ -/*********************** DECLARATIONS *************************/ -/******************************************************************************/ - -/** - * Function called to send a message to the service. - * "buf" will be NULL and "size" zero if the socket was closed for writing in - * the meantime. - * - * @param cls closure, the mesh handle - * @param size number of bytes available in buf - * @param buf where the callee should write the connect message - * @return number of bytes written to buf - */ -static size_t -send_callback (void *cls, size_t size, void *buf); - - -/******************************************************************************/ -/*********************** AUXILIARY FUNCTIONS *************************/ -/******************************************************************************/ - -/** - * Check if transmission is a payload packet. - * - * @param th Transmission handle. - * - * @return GNUNET_YES if it is a payload packet, - * GNUNET_NO if it is a mesh management packet. - */ -static int -th_is_payload (struct GNUNET_MESH_TransmitHandle *th) -{ - return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO; -} - - -/** - * Check whether there is any message ready in the queue and find the size. - * - * @param h Mesh handle. - * - * @return The size of the first ready message in the queue, - * 0 if there is none. - */ -static size_t -message_ready_size (struct GNUNET_MESH_Handle *h) -{ - struct GNUNET_MESH_TransmitHandle *th; - struct GNUNET_MESH_Tunnel *t; - - for (th = h->th_head; NULL != th; th = th->next) - { - t = th->tunnel; - if (GNUNET_NO == th_is_payload (th)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "# message internal\n"); - return th->size; - } - if (GNUNET_YES == GMC_is_pid_bigger(t->last_ack_recv, t->last_pid_sent)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "# message payload ok (%u =< %u)\n", - t->last_pid_sent + 1, t->last_ack_recv); - return th->size; - } - } - return 0; -} - - -/** - * Get the tunnel handler for the tunnel specified by id from the given handle - * @param h Mesh handle - * @param tid ID of the wanted tunnel - * @return handle to the required tunnel or NULL if not found - */ -static struct GNUNET_MESH_Tunnel * -retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid) -{ - struct GNUNET_MESH_Tunnel *t; - - t = h->tunnels_head; - while (t != NULL) - { - if (t->tid == tid) - return t; - t = t->next; - } - return NULL; -} - - -/** - * Create a new tunnel and insert it in the tunnel list of the mesh handle - * @param h Mesh handle - * @param tid desired tid of the tunnel, 0 to assign one automatically - * @return handle to the created tunnel - */ -static struct GNUNET_MESH_Tunnel * -create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid) -{ - struct GNUNET_MESH_Tunnel *t; - - t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel)); - GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t); - t->mesh = h; - if (0 == tid) - { - t->tid = h->next_tid; - while (NULL != retrieve_tunnel (h, h->next_tid)) - { - h->next_tid++; - h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV; - h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; - } - } - else - { - t->tid = tid; - } - t->last_ack_recv = (uint32_t) -1; - t->last_pid_recv = (uint32_t) -1; - t->last_ack_sent = (uint32_t) -1; - t->last_pid_sent = (uint32_t) -1; - t->buffering = GNUNET_YES; - return t; -} - - -/** - * Destroy the specified tunnel. - * - Destroys all peers, calling the disconnect callback on each if needed - * - Cancels all outgoing traffic for that tunnel, calling respective notifys - * - Calls cleaner if tunnel was inbound - * - Frees all memory used - * - * @param t Pointer to the tunnel. - * @param call_cleaner Whether to call the cleaner handler. - * - * @return Handle to the required tunnel or NULL if not found. - */ -static void -destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner) -{ - struct GNUNET_MESH_Handle *h; - struct GNUNET_MESH_TransmitHandle *th; - struct GNUNET_MESH_TransmitHandle *next; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid); - - if (NULL == t) - { - GNUNET_break (0); - return; - } - h = t->mesh; - - GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t); - - /* signal tunnel destruction */ - if ( (NULL != h->cleaner) && (0 != t->peer) && (GNUNET_YES == call_cleaner) ) - h->cleaner (h->cls, t, t->ctx); - - /* check that clients did not leave messages behind in the queue */ - for (th = h->th_head; NULL != th; th = next) - { - next = th->next; - if (th->tunnel != t) - continue; - /* Clients should have aborted their requests already. - * Management traffic should be ok, as clients can't cancel that */ - GNUNET_break (GNUNET_NO == th_is_payload(th)); - GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); - - /* clean up request */ - if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task) - GNUNET_SCHEDULER_cancel (th->timeout_task); - GNUNET_free (th); - } - - /* if there are no more pending requests with mesh service, cancel active request */ - /* Note: this should be unnecessary... */ - if ((0 == message_ready_size (h)) && (NULL != h->th)) - { - GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); - h->th = NULL; - } - - if (0 != t->peer) - GNUNET_PEER_change_rc (t->peer, -1); - GNUNET_free (t); - return; -} - - -/** - * Notify client that the transmission has timed out - * - * @param cls closure - * @param tc task context - */ -static void -timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_MESH_TransmitHandle *th = cls; - struct GNUNET_MESH_Handle *mesh; - - mesh = th->tunnel->mesh; - GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th); - th->tunnel->packet_size = 0; - if (GNUNET_YES == th_is_payload (th)) - th->notify (th->notify_cls, 0, NULL); - GNUNET_free (th); - if ((0 == message_ready_size (mesh)) && (NULL != mesh->th)) - { - /* nothing ready to transmit, no point in asking for transmission */ - GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th); - mesh->th = NULL; - } -} - - -/** - * Add a transmit handle to the transmission queue and set the - * timeout if needed. - * - * @param h mesh handle with the queue head and tail - * @param th handle to the packet to be transmitted - */ -static void -add_to_queue (struct GNUNET_MESH_Handle *h, - struct GNUNET_MESH_TransmitHandle *th) -{ - GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th); - if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value) - return; - th->timeout_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining - (th->timeout), &timeout_transmission, th); -} - - -/** - * Auxiliary function to send an already constructed packet to the service. - * Takes care of creating a new queue element, copying the message and - * calling the tmt_rdy function if necessary. - * - * @param h mesh handle - * @param msg message to transmit - * @param tunnel tunnel this send is related to (NULL if N/A) - */ -static void -send_packet (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MessageHeader *msg, - struct GNUNET_MESH_Tunnel *tunnel); - - -/** - * Send an ack on the tunnel to confirm the processing of a message. - * - * @param h Mesh handle. - * @param t Tunnel on which to send the ACK. - */ -static void -send_ack (struct GNUNET_MESH_Tunnel *t) -{ - struct GNUNET_MESH_LocalAck msg; - - t->last_ack_sent = t->last_pid_recv + 1; - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Sending ACK on tunnel %X: %u\n", - t->tid, t->last_ack_sent); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); - msg.header.size = htons (sizeof (msg)); - msg.tunnel_id = htonl (t->tid); - msg.ack = htonl (t->last_ack_sent); - -#if DEBUG_ACK - t->mesh->acks_sent++; -#endif - - send_packet (t->mesh, &msg.header, t); - return; -} - - - -/** - * Reconnect callback: tries to reconnect again after a failer previous - * reconnecttion - * @param cls closure (mesh handle) - * @param tc task context - */ -static void -reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); - - -/** - * Send a connect packet to the service with the applications and types - * requested by the user. - * - * @param h The mesh handle. - * - */ -static void -send_connect (struct GNUNET_MESH_Handle *h) -{ - size_t size; - - size = sizeof (struct GNUNET_MESH_ClientConnect); - size += h->n_ports * sizeof (uint32_t); - { - char buf[size] GNUNET_ALIGN; - struct GNUNET_MESH_ClientConnect *msg; - uint32_t *ports; - uint16_t i; - - /* build connection packet */ - msg = (struct GNUNET_MESH_ClientConnect *) buf; - msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT); - msg->header.size = htons (size); - ports = (uint32_t *) &msg[1]; - for (i = 0; i < h->n_ports; i++) - { - ports[i] = htonl (h->ports[i]); - LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n", - h->ports[i]); - } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Sending %lu bytes long message with %u ports\n", - ntohs (msg->header.size), h->n_ports); - send_packet (h, &msg->header, NULL); - } -} - - -/** - * Reconnect to the service, retransmit all infomation to try to restore the - * original state. - * - * @param h handle to the mesh - * - * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...) - */ -static int -do_reconnect (struct GNUNET_MESH_Handle *h) -{ - struct GNUNET_MESH_Tunnel *t; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); - LOG (GNUNET_ERROR_TYPE_DEBUG, "******* RECONNECT *******\n"); - LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); - LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h); - LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); - - /* disconnect */ - if (NULL != h->th) - { - GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); - h->th = NULL; - } - if (NULL != h->client) - { - GNUNET_CLIENT_disconnect (h->client); - } - - /* connect again */ - h->client = GNUNET_CLIENT_connect ("mesh", h->cfg); - if (h->client == NULL) - { - h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, - &reconnect_cbk, h); - h->reconnect_time = - GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, - GNUNET_TIME_relative_multiply - (h->reconnect_time, 2)); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Next retry in %s\n", - GNUNET_STRINGS_relative_time_to_string (h->reconnect_time, - GNUNET_NO)); - GNUNET_break (0); - return GNUNET_NO; - } - else - { - h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; - } - send_connect (h); - /* Rebuild all tunnels */ - for (t = h->tunnels_head; NULL != t; t = t->next) - { - struct GNUNET_MESH_TunnelMessage tmsg; - - if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) - { - /* Tunnel was created by service (incoming tunnel) */ - /* TODO: Notify service of missing tunnel, to request - * creator to recreate path (find a path to him via DHT?) - */ - continue; - } - t->last_ack_sent = (uint32_t) -1; - t->last_pid_sent = (uint32_t) -1; - t->last_ack_recv = (uint32_t) -1; - t->last_pid_recv = (uint32_t) -1; - tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); - tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); - tmsg.tunnel_id = htonl (t->tid); - GNUNET_PEER_resolve (t->peer, &tmsg.peer); - send_packet (h, &tmsg.header, t); - - if (GNUNET_NO == t->buffering) - GNUNET_MESH_tunnel_buffer (t, GNUNET_NO); - } - return GNUNET_YES; -} - -/** - * Reconnect callback: tries to reconnect again after a failer previous - * reconnecttion - * @param cls closure (mesh handle) - * @param tc task context - */ -static void -reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_MESH_Handle *h = cls; - - h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; - if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) - return; - do_reconnect (h); -} - - -/** - * Reconnect to the service, retransmit all infomation to try to restore the - * original state. - * - * @param h handle to the mesh - * - * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...) - */ -static void -reconnect (struct GNUNET_MESH_Handle *h) -{ - LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n"); - h->in_receive = GNUNET_NO; - if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task) - h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, - &reconnect_cbk, h); -} - - -/******************************************************************************/ -/*********************** RECEIVE HANDLERS ****************************/ -/******************************************************************************/ - -/** - * Process the new tunnel notification and add it to the tunnels in the handle - * - * @param h The mesh handle - * @param msg A message with the details of the new incoming tunnel - */ -static void -process_tunnel_created (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MESH_TunnelNotification *msg) -{ - struct GNUNET_MESH_Tunnel *t; - MESH_TunnelNumber tid; - - tid = ntohl (msg->tunnel_id); - LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid); - if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) - { - GNUNET_break (0); - return; - } - if (NULL != h->new_tunnel) - { - t = create_tunnel (h, tid); - t->last_ack_sent = 0; - t->peer = GNUNET_PEER_intern (&msg->peer); - t->mesh = h; - t->tid = tid; - t->port = ntohl (msg->port); - if (0 != (msg->opt & MESH_TUNNEL_OPT_NOBUFFER)) - t->buffering = GNUNET_NO; - else - t->buffering = GNUNET_YES; - LOG (GNUNET_ERROR_TYPE_DEBUG, " created tunnel %p\n", t); - t->ctx = h->new_tunnel (h->cls, t, &msg->peer, t->port); - LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n"); - } - else - { - struct GNUNET_MESH_TunnelMessage d_msg; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n"); - - d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); - d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); - d_msg.tunnel_id = msg->tunnel_id; - - send_packet (h, &d_msg.header, NULL); - } - return; -} - - -/** - * Process the tunnel destroy notification and free associated resources - * - * @param h The mesh handle - * @param msg A message with the details of the tunnel being destroyed - */ -static void -process_tunnel_destroy (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MESH_TunnelMessage *msg) -{ - struct GNUNET_MESH_Tunnel *t; - MESH_TunnelNumber tid; - - tid = ntohl (msg->tunnel_id); - t = retrieve_tunnel (h, tid); - - if (NULL == t) - { - return; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid); - destroy_tunnel (t, GNUNET_YES); - return; -} - - -/** - * Process the incoming data packets, call appropriate handlers. - * - * @param h The mesh handle - * @param message A message encapsulating the data - */ -static void -process_incoming_data (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MessageHeader *message) -{ - const struct GNUNET_MessageHeader *payload; - const struct GNUNET_MESH_MessageHandler *handler; - const struct GNUNET_PeerIdentity *peer; - struct GNUNET_PeerIdentity id; - struct GNUNET_MESH_Data *dmsg; - struct GNUNET_MESH_Tunnel *t; - unsigned int i; - uint32_t pid; - uint16_t type; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n"); - type = ntohs (message->type); - switch (type) - { - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - dmsg = (struct GNUNET_MESH_Data *) message; - - t = retrieve_tunnel (h, ntohl (dmsg->tid)); - payload = (struct GNUNET_MessageHeader *) &dmsg[1]; - GNUNET_PEER_resolve (t->peer, &id); - peer = &id; - pid = ntohl (dmsg->pid); - LOG (GNUNET_ERROR_TYPE_DEBUG, " %s data on tunnel %s [%X]\n", - type == GNUNET_MESSAGE_TYPE_MESH_UNICAST ? "fwd" : "bck", - GNUNET_i2s (peer), ntohl (dmsg->tid)); - break; - default: - GNUNET_break (0); - return; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", pid); - if (NULL == t) - { - /* Tunnel was ignored/destroyed, probably service didn't get it yet */ - LOG (GNUNET_ERROR_TYPE_DEBUG, " ignored!\n"); - return; - } - if (GNUNET_YES == - GMC_is_pid_bigger(pid, t->last_ack_sent)) - { - GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_WARNING, - " unauthorized message! (%u, ACK %u)\n", - pid, t->last_ack_sent); - // FIXME fc what now? accept? reject? - return; - } - t->last_pid_recv = pid; - type = ntohs (payload->type); - for (i = 0; i < h->n_handlers; i++) - { - handler = &h->message_handlers[i]; - if (handler->type == type) - { - if (GNUNET_OK != - handler->callback (h->cls, t, &t->ctx, payload)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n"); - GNUNET_MESH_tunnel_destroy (t); - return; - } - else - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "callback completed successfully\n"); - } - } - } -} - - -/** - * Process a local ACK message, enabling the client to send - * more data to the service. - * - * @param h Mesh handle. - * @param message Message itself. - */ -static void -process_ack (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_LocalAck *msg; - struct GNUNET_MESH_Tunnel *t; - uint32_t ack; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n"); - h->acks_recv++; - msg = (struct GNUNET_MESH_LocalAck *) message; - - t = retrieve_tunnel (h, ntohl (msg->tunnel_id)); - - if (NULL == t) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - "ACK on unknown tunnel %X\n", - ntohl (msg->tunnel_id)); - return; - } - ack = ntohl (msg->ack); - LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X, ack %u!\n", t->tid, ack); - if (GNUNET_YES == GMC_is_pid_bigger(ack, t->last_ack_recv)) - t->last_ack_recv = ack; - else - return; - if (NULL == h->th && 0 < t->packet_size) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, " tmt rdy was NULL, requesting!\n", t->tid, ack); - h->th = - GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size, - GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_YES, &send_callback, h); - } -} - - -/** - * Process a local reply about info on all tunnels, pass info to the user. - * - * @param h Mesh handle. - * @param message Message itself. - */ -static void -process_get_tunnels (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_LocalMonitor *msg; - - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n"); - - if (NULL == h->tunnels_cb) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); - return; - } - - msg = (struct GNUNET_MESH_LocalMonitor *) message; - if (ntohs (message->size) != - (sizeof (struct GNUNET_MESH_LocalMonitor) + - sizeof (struct GNUNET_PeerIdentity))) - { - GNUNET_break_op (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Get tunnels message: size %hu - expected %u\n", - ntohs (message->size), - sizeof (struct GNUNET_MESH_LocalMonitor)); - return; - } - h->tunnels_cb (h->tunnels_cls, - ntohl (msg->tunnel_id), - &msg->owner, - &msg->destination); -} - - - -/** - * Process a local monitor_tunnel reply, pass info to the user. - * - * @param h Mesh handle. - * @param message Message itself. - */ -static void -process_show_tunnel (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_LocalMonitor *msg; - size_t esize; - - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n"); - - if (NULL == h->tunnel_cb) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); - return; - } - - /* Verify message sanity */ - msg = (struct GNUNET_MESH_LocalMonitor *) message; - esize = sizeof (struct GNUNET_MESH_LocalMonitor); - if (ntohs (message->size) != esize) - { - GNUNET_break_op (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Show tunnel message: size %hu - expected %u\n", - ntohs (message->size), - esize); - - h->tunnel_cb (h->tunnel_cls, NULL, NULL); - h->tunnel_cb = NULL; - h->tunnel_cls = NULL; - - return; - } - - h->tunnel_cb (h->tunnel_cls, - &msg->destination, - &msg->owner); -} - - -/** - * Function to process all messages received from the service - * - * @param cls closure - * @param msg message received, NULL on timeout or fatal error - */ -static void -msg_received (void *cls, const struct GNUNET_MessageHeader *msg) -{ - struct GNUNET_MESH_Handle *h = cls; - - if (msg == NULL) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Mesh service disconnected, reconnecting\n", h); - reconnect (h); - return; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, "\n", - GNUNET_MESH_DEBUG_M2S (ntohs (msg->type))); - LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n", - GNUNET_MESH_DEBUG_M2S (ntohs (msg->type))); - switch (ntohs (msg->type)) - { - /* Notify of a new incoming tunnel */ - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE: - process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg); - break; - /* Notify of a tunnel disconnection */ - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY: - process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg); - break; - /* Notify of a new data packet in the tunnel */ - case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: - case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - process_incoming_data (h, msg); - break; - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: - process_ack (h, msg); - break; - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS: - process_get_tunnels (h, msg); - break; - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL: - process_show_tunnel (h, msg); - break; - default: - /* We shouldn't get any other packages, log and ignore */ - LOG (GNUNET_ERROR_TYPE_WARNING, - "unsolicited message form service (type %s)\n", - GNUNET_MESH_DEBUG_M2S (ntohs (msg->type))); - } - LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n"); - if (GNUNET_YES == h->in_receive) - { - GNUNET_CLIENT_receive (h->client, &msg_received, h, - GNUNET_TIME_UNIT_FOREVER_REL); - } - else - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "in receive off, not calling CLIENT_receive\n"); - } -} - - -/******************************************************************************/ -/************************ SEND FUNCTIONS ****************************/ -/******************************************************************************/ - -/** - * Function called to send a message to the service. - * "buf" will be NULL and "size" zero if the socket was closed for writing in - * the meantime. - * - * @param cls closure, the mesh handle - * @param size number of bytes available in buf - * @param buf where the callee should write the connect message - * @return number of bytes written to buf - */ -static size_t -send_callback (void *cls, size_t size, void *buf) -{ - struct GNUNET_MESH_Handle *h = cls; - struct GNUNET_MESH_TransmitHandle *th; - struct GNUNET_MESH_TransmitHandle *next; - struct GNUNET_MESH_Tunnel *t; - char *cbuf = buf; - size_t tsize; - size_t psize; - size_t nsize; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); - LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size); - if ((0 == size) || (NULL == buf)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h); - reconnect (h); - h->th = NULL; - return 0; - } - tsize = 0; - next = h->th_head; - nsize = message_ready_size (h); - while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize)) - { - t = th->tunnel; - if (GNUNET_YES == th_is_payload (th)) - { - struct GNUNET_MESH_Data *dmsg; - struct GNUNET_MessageHeader *mh; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload\n"); - if (GNUNET_NO == GMC_is_pid_bigger (t->last_ack_recv, t->last_pid_sent)) - { - /* This tunnel is not ready to transmit yet, try next message */ - next = th->next; - continue; - } - t->packet_size = 0; - GNUNET_assert (size >= th->size); - dmsg = (struct GNUNET_MESH_Data *) cbuf; - mh = (struct GNUNET_MessageHeader *) &dmsg[1]; - psize = th->notify (th->notify_cls, - size - sizeof (struct GNUNET_MESH_Data), - mh); - if (psize > 0) - { - psize += sizeof (struct GNUNET_MESH_Data); - GNUNET_assert (size >= psize); - dmsg->header.size = htons (psize); - dmsg->tid = htonl (t->tid); - dmsg->pid = htonl (t->last_pid_sent + 1); - dmsg->ttl = 0; - memset (&dmsg->oid, 0, sizeof (struct GNUNET_PeerIdentity)); - t->last_pid_sent++; - } - if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) - { - dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN); - LOG (GNUNET_ERROR_TYPE_DEBUG, "# to origin, type %s\n", - GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); - } - else - { - dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST); - LOG (GNUNET_ERROR_TYPE_DEBUG, "# unicast, type %s\n", - GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); - } - } - else - { - struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1]; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "# mesh traffic, type %s\n", - GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); - memcpy (cbuf, &th[1], th->size); - psize = th->size; - } - if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (th->timeout_task); - GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); - GNUNET_free (th); - next = h->th_head; - nsize = message_ready_size (h); - cbuf += psize; - size -= psize; - tsize += psize; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, "# total size: %u\n", tsize); - h->th = NULL; - size = message_ready_size (h); - if (0 != size) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "# next size: %u\n", size); - h->th = - GNUNET_CLIENT_notify_transmit_ready (h->client, size, - GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_YES, &send_callback, h); - } - else - { - if (NULL != h->th_head) - LOG (GNUNET_ERROR_TYPE_DEBUG, "# can't transmit any more\n"); - else - LOG (GNUNET_ERROR_TYPE_DEBUG, "# nothing left to transmit\n"); - } - if (GNUNET_NO == h->in_receive) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n"); - h->in_receive = GNUNET_YES; - GNUNET_CLIENT_receive (h->client, &msg_received, h, - GNUNET_TIME_UNIT_FOREVER_REL); - } - LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n"); - return tsize; -} - - -/** - * Auxiliary function to send an already constructed packet to the service. - * Takes care of creating a new queue element, copying the message and - * calling the tmt_rdy function if necessary. - * - * @param h mesh handle - * @param msg message to transmit - * @param tunnel tunnel this send is related to (NULL if N/A) - */ -static void -send_packet (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MessageHeader *msg, - struct GNUNET_MESH_Tunnel *tunnel) -{ - struct GNUNET_MESH_TransmitHandle *th; - size_t msize; - - LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n", - GNUNET_MESH_DEBUG_M2S(ntohs(msg->type))); - msize = ntohs (msg->size); - th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize); - th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; - th->size = msize; - th->tunnel = tunnel; - memcpy (&th[1], msg, msize); - add_to_queue (h, th); - LOG (GNUNET_ERROR_TYPE_DEBUG, " queued\n"); - if (NULL != h->th) - return; - LOG (GNUNET_ERROR_TYPE_DEBUG, " calling ntfy tmt rdy for %u bytes\n", msize); - h->th = - GNUNET_CLIENT_notify_transmit_ready (h->client, msize, - GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_YES, &send_callback, h); -} - - -/******************************************************************************/ -/********************** API CALL DEFINITIONS *************************/ -/******************************************************************************/ - -struct GNUNET_MESH_Handle * -GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, - GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, - GNUNET_MESH_TunnelEndHandler cleaner, - const struct GNUNET_MESH_MessageHandler *handlers, - const uint32_t *ports) -{ - struct GNUNET_MESH_Handle *h; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n"); - h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle)); - LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h); - h->cfg = cfg; - h->new_tunnel = new_tunnel; - h->cleaner = cleaner; - h->client = GNUNET_CLIENT_connect ("mesh", cfg); - if (h->client == NULL) - { - GNUNET_break (0); - GNUNET_free (h); - return NULL; - } - h->cls = cls; - h->message_handlers = handlers; - h->ports = ports; - h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; - h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; - h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; - - /* count handlers */ - for (h->n_handlers = 0; - handlers && handlers[h->n_handlers].type; - h->n_handlers++) ; - for (h->n_ports = 0; - ports && ports[h->n_ports]; - h->n_ports++) ; - send_connect (h); - LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n"); - return h; -} - - -void -GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) -{ - struct GNUNET_MESH_Tunnel *t; - struct GNUNET_MESH_Tunnel *aux; - struct GNUNET_MESH_TransmitHandle *th; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n"); - -#if DEBUG_ACK - LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent); - LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv); -#endif - - t = handle->tunnels_head; - while (NULL != t) - { - aux = t->next; - if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) - { - GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid); - } - destroy_tunnel (t, GNUNET_YES); - t = aux; - } - while ( (th = handle->th_head) != NULL) - { - struct GNUNET_MessageHeader *msg; - - /* Make sure it is an allowed packet (everything else should have been - * already canceled). - */ - GNUNET_break (GNUNET_NO == th_is_payload (th)); - msg = (struct GNUNET_MessageHeader *) &th[1]; - switch (ntohs(msg->type)) - { - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT: - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY: - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS: - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL: - break; - default: - GNUNET_break (0); - LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n", - ntohs(msg->type)); - } - - GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th); - GNUNET_free (th); - } - - if (NULL != handle->th) - { - GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th); - handle->th = NULL; - } - if (NULL != handle->client) - { - GNUNET_CLIENT_disconnect (handle->client); - handle->client = NULL; - } - if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task) - { - GNUNET_SCHEDULER_cancel(handle->reconnect_task); - handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; - } - GNUNET_free (handle); -} - - -struct GNUNET_MESH_Tunnel * -GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, - void *tunnel_ctx, - const struct GNUNET_PeerIdentity *peer, - uint32_t port) -{ - struct GNUNET_MESH_Tunnel *t; - struct GNUNET_MESH_TunnelMessage msg; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n"); - t = create_tunnel (h, 0); - LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", t); - LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", t->tid); - t->ctx = tunnel_ctx; - t->peer = GNUNET_PEER_intern (peer); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); - msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); - msg.tunnel_id = htonl (t->tid); - msg.port = htonl (port); - msg.peer = *peer; - t->last_ack_sent = 0; - send_packet (h, &msg.header, t); - return t; -} - - -void -GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel) -{ - struct GNUNET_MESH_Handle *h; - struct GNUNET_MESH_TunnelMessage msg; - struct GNUNET_MESH_TransmitHandle *th; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n"); - h = tunnel->mesh; - - 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); - th = h->th_head; - while (th != NULL) - { - struct GNUNET_MESH_TransmitHandle *aux; - if (th->tunnel == tunnel) - { - aux = th->next; - /* FIXME call the handler? */ - if (GNUNET_YES == th_is_payload (th)) - th->notify (th->notify_cls, 0, NULL); - GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); - GNUNET_free (th); - th = aux; - } - else - th = th->next; - } - - destroy_tunnel (tunnel, GNUNET_YES); - send_packet (h, &msg.header, NULL); -} - - -void -GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer) -{ - struct GNUNET_MESH_TunnelMessage msg; - struct GNUNET_MESH_Handle *h; - - h = tunnel->mesh; - tunnel->buffering = buffer; - - if (GNUNET_YES == buffer) - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER); - else - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER); - msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); - msg.tunnel_id = htonl (tunnel->tid); - - send_packet (h, &msg.header, NULL); -} - - -struct GNUNET_MESH_TransmitHandle * -GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork, - struct GNUNET_TIME_Relative maxdelay, - size_t notify_size, - GNUNET_CONNECTION_TransmitReadyNotify notify, - void *notify_cls) -{ - struct GNUNET_MESH_TransmitHandle *th; - - GNUNET_assert (NULL != tunnel); - LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n"); - LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tunnel->tid); - if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) - LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n"); - else - LOG (GNUNET_ERROR_TYPE_DEBUG, " to destination\n"); - LOG (GNUNET_ERROR_TYPE_DEBUG, " payload size %u\n", notify_size); - GNUNET_assert (NULL != notify); - GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed - th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle)); - th->tunnel = tunnel; - th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); - th->size = notify_size + sizeof (struct GNUNET_MESH_Data); - tunnel->packet_size = th->size; - LOG (GNUNET_ERROR_TYPE_DEBUG, " total size %u\n", th->size); - th->notify = notify; - th->notify_cls = notify_cls; - add_to_queue (tunnel->mesh, th); - if (NULL != tunnel->mesh->th) - return th; - if (!GMC_is_pid_bigger (tunnel->last_ack_recv, tunnel->last_pid_sent)) - return th; - LOG (GNUNET_ERROR_TYPE_DEBUG, " call client notify tmt rdy\n"); - tunnel->mesh->th = - GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size, - GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_YES, &send_callback, - tunnel->mesh); - LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n"); - return th; -} - - -void -GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th) -{ - struct GNUNET_MESH_Handle *mesh; - - th->tunnel->packet_size = 0; - mesh = th->tunnel->mesh; - if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK) - GNUNET_SCHEDULER_cancel (th->timeout_task); - GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th); - GNUNET_free (th); - if ((0 == message_ready_size (mesh)) && (NULL != mesh->th)) - { - /* queue empty, no point in asking for transmission */ - GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th); - mesh->th = NULL; - } -} - -void -GNUNET_MESH_receive_done (struct GNUNET_MESH_Tunnel *tunnel) -{ - send_ack (tunnel); -} - - -/** - * Request information about the running mesh peer. - * The callback will be called for every tunnel known to the service, - * listing all active peers that blong to the tunnel. - * - * If called again on the same handle, it will overwrite the previous - * callback and cls. To retrieve the cls, monitor_cancel must be - * called first. - * - * WARNING: unstable API, likely to change in the future! - * - * @param h Handle to the mesh peer. - * @param callback Function to call with the requested data. - * @param callback_cls Closure for @c callback. - */ -void -GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h, - GNUNET_MESH_TunnelsCB callback, - void *callback_cls) -{ - struct GNUNET_MessageHeader msg; - - msg.size = htons (sizeof (msg)); - msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS); - send_packet (h, &msg, NULL); - h->tunnels_cb = callback; - h->tunnels_cls = callback_cls; - - return; -} - - -/** - * Cancel a monitor request. The monitor callback will not be called. - * - * @param h Mesh handle. - * - * @return Closure given to GNUNET_MESH_monitor, if any. - */ -void * -GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h) -{ - void *cls; - - cls = h->tunnels_cls; - h->tunnels_cb = NULL; - h->tunnels_cls = NULL; - return cls; -} - - -/** - * Request information about a specific tunnel of the running mesh peer. - * - * WARNING: unstable API, likely to change in the future! - * FIXME Add destination option. - * - * @param h Handle to the mesh peer. - * @param initiator ID of the owner of the tunnel. - * @param tunnel_number Tunnel number. - * @param callback Function to call with the requested data. - * @param callback_cls Closure for @c callback. - */ -void -GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h, - struct GNUNET_PeerIdentity *initiator, - unsigned int tunnel_number, - GNUNET_MESH_TunnelCB callback, - void *callback_cls) -{ - struct GNUNET_MESH_LocalMonitor msg; - - msg.header.size = htons (sizeof (msg)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL); - msg.owner = *initiator; - msg.tunnel_id = htonl (tunnel_number); - msg.reserved = 0; - send_packet (h, &msg.header, NULL); - h->tunnel_cb = callback; - h->tunnel_cls = callback_cls; - - return; -} - - -/** - * Function called to notify a client about the connection - * begin ready to queue more data. "buf" will be - * NULL and "size" zero if the connection was closed for - * writing in the meantime. - * - * @param cls closure - * @param size number of bytes available in buf - * @param buf where the callee should write the message - * @return number of bytes written to buf - */ -static size_t -mesh_mq_ntr (void *cls, size_t size, - void *buf) -{ - struct GNUNET_MQ_Handle *mq = cls; - struct MeshMQState *state = GNUNET_MQ_impl_state (mq); - const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq); - uint16_t msize; - - state->th = NULL; - if (NULL == buf) - { - GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE); - return 0; - } - msize = ntohs (msg->size); - GNUNET_assert (msize <= size); - memcpy (buf, msg, msize); - GNUNET_MQ_impl_send_continue (mq); - return msize; -} - - -/** - * Signature of functions implementing the - * sending functionality of a message queue. - * - * @param mq the message queue - * @param msg the message to send - * @param impl_state state of the implementation - */ -static void -mesh_mq_send_impl (struct GNUNET_MQ_Handle *mq, - const struct GNUNET_MessageHeader *msg, void *impl_state) -{ - struct MeshMQState *state = impl_state; - - GNUNET_assert (NULL == state->th); - GNUNET_MQ_impl_send_commit (mq); - state->th = - GNUNET_MESH_notify_transmit_ready (state->tunnel, - /* FIXME: add option for corking */ - GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - ntohs (msg->size), - mesh_mq_ntr, mq); - -} - - -/** - * Signature of functions implementing the - * destruction of a message queue. - * Implementations must not free 'mq', but should - * take care of 'impl_state'. - * - * @param mq the message queue to destroy - * @param impl_state state of the implementation - */ -static void -mesh_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state) -{ - struct MeshMQState *state = impl_state; - - if (NULL != state->th) - GNUNET_MESH_notify_transmit_ready_cancel (state->th); - - GNUNET_free (state); -} - - -/** - * Create a message queue for a mesh tunnel. - * The message queue can only be used to transmit messages, - * not to receive them. - * - * @param tunnel the tunnel to create the message qeue for - * @return a message queue to messages over the tunnel - */ -struct GNUNET_MQ_Handle * -GNUNET_MESH_mq_create (struct GNUNET_MESH_Tunnel *tunnel) -{ - struct GNUNET_MQ_Handle *mq; - struct MeshMQState *state; - - state = GNUNET_new (struct MeshMQState); - state->tunnel = tunnel; - - mq = GNUNET_MQ_queue_for_callbacks (mesh_mq_send_impl, - mesh_mq_destroy_impl, - NULL, /* FIXME: cancel impl. */ - state, - NULL, /* no msg handlers */ - NULL, /* no err handlers */ - NULL); /* no handler cls */ - return mq; -} - diff --git a/src/mesh/mesh2_protocol.h b/src/mesh/mesh2_protocol.h deleted file mode 100644 index d35d7141ee..0000000000 --- a/src/mesh/mesh2_protocol.h +++ /dev/null @@ -1,316 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2001 - 2011 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @author Bartlomiej Polot - * @file mesh/mesh_protocol.h - */ - -#ifndef MESH_PROTOCOL_H_ -#define MESH_PROTOCOL_H_ - -#ifdef __cplusplus -extern "C" -{ -#if 0 - /* keep Emacsens' auto-indent happy */ -} -#endif -#endif - -#define MESH_TUNNEL_OPT_NOBUFFER 0x2 - - -/******************************************************************************/ -/******************** MESH NETWORK MESSAGES **************************/ -/******************************************************************************/ - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * Message for mesh path creation. - */ -struct GNUNET_MESH_CreateTunnel -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE - * - * Size: sizeof(struct GNUNET_MESH_ManipulatePath) + - * path_length * sizeof (struct GNUNET_PeerIdentity) - */ - struct GNUNET_MessageHeader header; - - /** - * Global id of the tunnel this path belongs to, - * unique in conjunction with the origin. - */ - uint32_t tid GNUNET_PACKED; - - /** - * Tunnel options (MESH_TUNNEL_OPT_*). - */ - uint32_t opt GNUNET_PACKED; - - /** - * Destination port. - */ - uint32_t port GNUNET_PACKED; - - /** - * FIXME do not add the first hop - * path_length structs defining the *whole* path from the origin [0] to the - * final destination [path_length-1]. - */ - /* struct GNUNET_PeerIdentity peers[path_length]; */ -}; - -/** - * Message for mesh path destruction. - */ -struct GNUNET_MESH_DestroyTunnel -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY - * - * Size: sizeof(struct GNUNET_MESH_ManipulatePath) + - * path_length * sizeof (struct GNUNET_PeerIdentity) - */ - struct GNUNET_MessageHeader header; - - /** - * Global id of the tunnel this path belongs to, - * unique in conjunction with the origin. - */ - uint32_t tid GNUNET_PACKED; -}; - - -/** - * Message for mesh data traffic. - */ -struct GNUNET_MESH_Data -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_UNICAST, - * GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN - */ - struct GNUNET_MessageHeader header; - - /** - * TID of the tunnel - */ - uint32_t tid GNUNET_PACKED; - - /** - * Number of hops to live - */ - uint32_t ttl GNUNET_PACKED; - - /** - * Unique ID of the packet - */ - uint32_t pid GNUNET_PACKED; - - /** - * OID of the tunnel - */ - struct GNUNET_PeerIdentity oid; - - /** - * Payload follows - */ -}; - - -/** - * Message to acknowledge mesh data traffic. - */ -struct GNUNET_MESH_ACK -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_ACK - */ - struct GNUNET_MessageHeader header; - - /** - * TID of the tunnel - */ - uint32_t tid GNUNET_PACKED; - - /** - * OID of the tunnel - */ - struct GNUNET_PeerIdentity oid; - - /** - * Maximum packet ID authorized. - */ - uint32_t pid; - -}; - -/** - * Message to query a peer about its Flow Control status regarding a tunnel. - */ -struct GNUNET_MESH_Poll -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_POLL - */ - struct GNUNET_MessageHeader header; - - /** - * TID of the tunnel - */ - uint32_t tid GNUNET_PACKED; - - /** - * OID of the tunnel - */ - struct GNUNET_PeerIdentity oid; -}; - -/** - * Message for ack'ing a path - */ -struct GNUNET_MESH_PathACK -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_ACK - */ - struct GNUNET_MessageHeader header; - - /** - * TID of the tunnel - */ - uint32_t tid GNUNET_PACKED; - - /** - * OID of the tunnel - */ - struct GNUNET_PeerIdentity oid; - - /** - * ID of the endpoint - */ - struct GNUNET_PeerIdentity peer_id; - - /** - * Initial ACK value for payload. - */ - uint32_t ack GNUNET_PACKED; - - /* TODO: signature */ -}; - - -/** - * Message for notifying a disconnection in a path - */ -struct GNUNET_MESH_PathBroken -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN - */ - struct GNUNET_MessageHeader header; - - /** - * TID of the tunnel - */ - uint32_t tid GNUNET_PACKED; - - /** - * OID of the tunnel - */ - struct GNUNET_PeerIdentity oid; - - /** - * ID of the endpoint - */ - struct GNUNET_PeerIdentity peer1; - - /** - * ID of the endpoint - */ - struct GNUNET_PeerIdentity peer2; - - /* TODO: signature */ -}; - - -/** - * Message to destroy a tunnel - */ -struct GNUNET_MESH_TunnelDestroy -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY - */ - struct GNUNET_MessageHeader header; - - /** - * TID of the tunnel - */ - uint32_t tid GNUNET_PACKED; - - /** - * OID of the tunnel - */ - struct GNUNET_PeerIdentity oid; - - /* TODO: signature */ -}; - - -/** - * Message to destroy a tunnel - */ -struct GNUNET_MESH_TunnelKeepAlive -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE - */ - struct GNUNET_MessageHeader header; - - /** - * TID of the tunnel - */ - uint32_t tid GNUNET_PACKED; - - /** - * OID of the tunnel - */ - struct GNUNET_PeerIdentity oid; -}; - - - -GNUNET_NETWORK_STRUCT_END - -#if 0 /* keep Emacsens' auto-indent happy */ -{ -#endif -#ifdef __cplusplus -} -#endif - -/* ifndef MESH_PROTOCOL_H */ -#endif -/* end of mesh_protocol.h */ diff --git a/src/mesh/mesh2_test_lib.c b/src/mesh/mesh2_test_lib.c deleted file mode 100644 index 95de93edd8..0000000000 --- a/src/mesh/mesh2_test_lib.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2012 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ -/** - * @file mesh/mesh2_test_lib.c - * @author Bartlomiej Polot - * @brief library for writing MESH tests - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "mesh2_test_lib.h" -#include "gnunet_mesh2_service.h" - -/** - * Test context for a MESH Test. - */ -struct GNUNET_MESH_TEST_Context -{ - /** - * Array of running peers. - */ - struct GNUNET_TESTBED_Peer **peers; - - /** - * Array of handles to the MESH for each peer. - */ - struct GNUNET_MESH_Handle **meshes; - - /** - * Operation associated with the connection to the MESH. - */ - struct GNUNET_TESTBED_Operation **ops; - - /** - * Main function of the test to run once all MESHs are available. - */ - GNUNET_MESH_TEST_AppMain app_main; - - /** - * Closure for 'app_main'. - */ - void *app_main_cls; - - /** - * Number of peers running, size of the arrays above. - */ - unsigned int num_peers; - - /** - * Handler for incoming tunnels. - */ - GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel; - - /** - * Cleaner for destroyed incoming tunnels. - */ - GNUNET_MESH_TunnelEndHandler *cleaner; - - /** - * Message handlers. - */ - struct GNUNET_MESH_MessageHandler* handlers; - - /** - * Application ports. - */ - const uint32_t *ports; - -}; - - -/** - * Context for a mesh adapter callback. - */ -struct GNUNET_MESH_TEST_AdapterContext -{ - /** - * Peer number for the particular peer. - */ - unsigned int peer; - - /** - * General context. - */ - struct GNUNET_MESH_TEST_Context *ctx; -}; - - -/** - * Adapter function called to establish a connection to - * the MESH service. - * - * @param cls closure - * @param cfg configuration of the peer to connect to; will be available until - * GNUNET_TESTBED_operation_done() is called on the operation returned - * from GNUNET_TESTBED_service_connect() - * @return service handle to return in 'op_result', NULL on error - */ -static void * -mesh_connect_adapter (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct GNUNET_MESH_TEST_AdapterContext *actx = cls; - struct GNUNET_MESH_TEST_Context *ctx = actx->ctx; - struct GNUNET_MESH_Handle *h; - - h = GNUNET_MESH_connect (cfg, - (void *) (long) actx->peer, - ctx->new_tunnel, - ctx->cleaner, - ctx->handlers, - ctx->ports); - return h; -} - - -/** - * Adapter function called to destroy a connection to - * the MESH service. - * - * @param cls closure - * @param op_result service handle returned from the connect adapter - */ -static void -mesh_disconnect_adapter (void *cls, - void *op_result) -{ - struct GNUNET_MESH_Handle *mesh = op_result; - struct GNUNET_MESH_TEST_AdapterContext *actx = cls; - - GNUNET_free (actx); - GNUNET_MESH_disconnect (mesh); -} - - -/** - * Callback to be called when a service connect operation is completed. - * - * @param cls The callback closure from functions generating an operation. - * @param op The operation that has been finished. - * @param ca_result The service handle returned from - * GNUNET_TESTBED_ConnectAdapter() (mesh handle). - * @param emsg Error message in case the operation has failed. - * NULL if operation has executed successfully. - */ -static void -mesh_connect_cb (void *cls, - struct GNUNET_TESTBED_Operation *op, - void *ca_result, - const char *emsg) -{ - struct GNUNET_MESH_TEST_Context *ctx = cls; - unsigned int i; - - if (NULL != emsg) - { - fprintf (stderr, "Failed to connect to MESH service: %s\n", - emsg); - GNUNET_SCHEDULER_shutdown (); - return; - } - for (i = 0; i < ctx->num_peers; i++) - if (op == ctx->ops[i]) - ctx->meshes[i] = ca_result; - for (i = 0; i < ctx->num_peers; i++) - if (NULL == ctx->meshes[i]) - return; /* still some MESH connections missing */ - /* all MESH connections ready! */ - ctx->app_main (ctx->app_main_cls, - ctx, - ctx->num_peers, - ctx->peers, - ctx->meshes); -} - - -void -GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx) -{ - unsigned int i; - - for (i = 0; i < ctx->num_peers; i++) - { - GNUNET_assert (NULL != ctx->ops[i]); - GNUNET_TESTBED_operation_done (ctx->ops[i]); - ctx->ops[i] = NULL; - } - GNUNET_free (ctx->ops); - GNUNET_free (ctx->meshes); - GNUNET_free (ctx); - GNUNET_SCHEDULER_shutdown (); -} - - -/** - * Callback run when the testbed is ready (peers running and connected to - * each other) - * - * @param cls Closure (context). - * @param num_peers Number of peers that are running. - * @param peers Handles to each one of the @c num_peers peers. - * @param links_succeeded the number of overlay link connection attempts that - * succeeded - * @param links_failed the number of overlay link connection attempts that - * failed - */ -static void -mesh_test_run (void *cls, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers, - unsigned int links_succeeded, - unsigned int links_failed) -{ - struct GNUNET_MESH_TEST_Context *ctx = cls; - unsigned int i; - - GNUNET_assert (num_peers == ctx->num_peers); - ctx->peers = peers; - for (i = 0; i < num_peers; i++) - { - struct GNUNET_MESH_TEST_AdapterContext *newctx; - newctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_AdapterContext)); - newctx->peer = i; - newctx->ctx = ctx; - ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx, - peers[i], - "mesh", - &mesh_connect_cb, - ctx, - &mesh_connect_adapter, - &mesh_disconnect_adapter, - newctx); - } -} - - -void -GNUNET_MESH_TEST_run (const char *testname, - const char *cfgname, - unsigned int num_peers, - GNUNET_MESH_TEST_AppMain tmain, - void *tmain_cls, - GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, - GNUNET_MESH_TunnelEndHandler cleaner, - struct GNUNET_MESH_MessageHandler* handlers, - const uint32_t *ports) -{ - struct GNUNET_MESH_TEST_Context *ctx; - - ctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_Context)); - ctx->num_peers = num_peers; - ctx->ops = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *)); - ctx->meshes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_MESH_Handle *)); - ctx->app_main = tmain; - ctx->app_main_cls = tmain_cls; - ctx->new_tunnel = new_tunnel; - ctx->cleaner = cleaner; - ctx->handlers = handlers; - ctx->ports = ports; - GNUNET_TESTBED_test_run (testname, - cfgname, - num_peers, - 0LL, NULL, NULL, - &mesh_test_run, ctx); -} - -/* end of mesh_test_lib.c */ diff --git a/src/mesh/mesh2_test_lib.h b/src/mesh/mesh2_test_lib.h deleted file mode 100644 index 096c0ebc1c..0000000000 --- a/src/mesh/mesh2_test_lib.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2012 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ -/** - * @file mesh/mesh2_test_lib.h - * @author Bartlomiej Polot - * @brief library for writing MESH tests - */ -#ifndef MESH_TEST_LIB_H -#define MESH_TEST_LIB_H - -#ifdef __cplusplus -extern "C" -{ -#if 0 /* keep Emacsens' auto-indent happy */ -} -#endif -#endif - -#include "gnunet_testbed_service.h" -#include "gnunet_mesh2_service.h" - -/** - * Test context for a MESH Test. - */ -struct GNUNET_MESH_TEST_Context; - - -/** - * Main function of a MESH test. - * - * @param cls Closure. - * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end. - * @param num_peers Number of peers that are running. - * @param peers Array of peers. - * @param meshes Handle to each of the MESHs of the peers. - */ -typedef void (*GNUNET_MESH_TEST_AppMain) (void *cls, - struct GNUNET_MESH_TEST_Context *ctx, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers, - struct GNUNET_MESH_Handle **meshes); - - -/** - * Run a test using the given name, configuration file and number of - * peers. - * All mesh callbacks will receive the peer number as the closure. - * - * @param testname Name of the test (for logging). - * @param cfgname Name of the configuration file. - * @param num_peers Number of peers to start. - * @param tmain Main function to run once the testbed is ready. - * @param tmain_cls Closure for 'tmain'. - * @param new_tunnel Handler for incoming tunnels. - * @param cleaner Cleaner for destroyed incoming tunnels. - * @param handlers Message handlers. - * @param ports Ports the peers offer. - */ -void -GNUNET_MESH_TEST_run (const char *testname, - const char *cfgname, - unsigned int num_peers, - GNUNET_MESH_TEST_AppMain tmain, - void *tmain_cls, - GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, - GNUNET_MESH_TunnelEndHandler cleaner, - struct GNUNET_MESH_MessageHandler* handlers, - const uint32_t* ports); - - -/** - * Clean up the testbed. - * - * @param ctx handle for the testbed - */ -void -GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx); - - -#if 0 /* keep Emacsens' auto-indent happy */ -{ -#endif -#ifdef __cplusplus -} -#endif - - -/* ifndef MESH_TEST_LIB_H */ -#endif diff --git a/src/mesh/mesh_api.c b/src/mesh/mesh_api.c index 8683d7f247..189580e505 100644 --- a/src/mesh/mesh_api.c +++ b/src/mesh/mesh_api.c @@ -17,7 +17,7 @@ /** * @file mesh/mesh_api.c - * @brief mesh api: client implementation of mesh service + * @brief mesh api: client implementation of new mesh service * @author Bartlomiej Polot * * STRUCTURE: @@ -40,7 +40,6 @@ #include "mesh_protocol.h" #define LOG(kind,...) GNUNET_log_from (kind, "mesh-api",__VA_ARGS__) - #define DEBUG_ACK GNUNET_YES /******************************************************************************/ @@ -95,12 +94,6 @@ struct GNUNET_MESH_TransmitHandle GNUNET_SCHEDULER_TaskIdentifier timeout_task; /** - * Target of the message, 0 for multicast. This field - * is only valid if 'notify' is non-NULL. - */ - GNUNET_PEER_Id target; - - /** * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL. */ size_t size; @@ -123,13 +116,20 @@ struct GNUNET_MESH_Handle */ const struct GNUNET_MESH_MessageHandler *message_handlers; - /** - * Set of applications that should be claimed to be offered at this node. - * Note that this is just informative, the appropiate handlers must be - * registered independently and the mapping is up to the developer of the - * client application. - */ - GNUNET_MESH_ApplicationType *applications; + /** + * Number of handlers in the handlers array. + */ + unsigned int n_handlers; + + /** + * Ports open. + */ + const uint32_t *ports; + + /** + * Number of ports. + */ + unsigned int n_ports; /** * Double linked list of the tunnels this client is connected to, head. @@ -177,16 +177,6 @@ struct GNUNET_MESH_Handle MESH_TunnelNumber next_tid; /** - * Number of handlers in the handlers array. - */ - unsigned int n_handlers; - - /** - * Number of applications in the applications array. - */ - unsigned int n_applications; - - /** * Have we started the task to receive messages from the service * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message. */ @@ -227,16 +217,6 @@ struct GNUNET_MESH_Handle */ void *tunnel_cls; - /** - * All the peer in the tunnel so far. - */ - struct GNUNET_PeerIdentity *peers; - - /** - * How many peers we have in this tunnel so far. - */ - unsigned int tunnel_npeers; - #if DEBUG_ACK unsigned int acks_sent; unsigned int acks_recv; @@ -284,21 +264,6 @@ struct GNUNET_MESH_Tunnel struct GNUNET_MESH_Tunnel *prev; /** - * Callback to execute when peers connect to the tunnel - */ - GNUNET_MESH_PeerConnectHandler connect_handler; - - /** - * Callback to execute when peers disconnect from the tunnel - */ - GNUNET_MESH_PeerDisconnectHandler disconnect_handler; - - /** - * Closure for the connect/disconnect handlers - */ - void *cls; - - /** * Handle to the mesh this tunnel belongs to */ struct GNUNET_MESH_Handle *mesh; @@ -309,69 +274,67 @@ struct GNUNET_MESH_Tunnel MESH_TunnelNumber tid; /** - * Owner of the tunnel. 0 if the tunnel is the local client. + * Port number. */ - GNUNET_PEER_Id owner; + uint32_t port; /** - * All peers added to the tunnel + * Other end of the tunnel. */ - struct GNUNET_MESH_Peer **peers; - - /** - * List of application types that have been requested for this tunnel - */ - GNUNET_MESH_ApplicationType *apps; + GNUNET_PEER_Id peer; /** * Any data the caller wants to put in here */ void *ctx; - /** - * Number of peers added to the tunnel - */ - unsigned int npeers; - /** * Size of packet queued in this tunnel */ unsigned int packet_size; /** - * Number of applications requested this tunnel - */ - unsigned int napps; - - /** - * Is the tunnel throttled to the slowest peer? - */ - int speed_min; - - /** * Is the tunnel allowed to buffer? */ int buffering; /** - * Next packet ID to send. + * Maximum allowed PID to send (last ACK recevied). */ - uint32_t next_send_pid; + uint32_t last_ack_recv; /** - * Maximum allowed PID to send (ACK recevied). + * Last PID received from the service. */ - uint32_t max_send_pid; + uint32_t last_pid_recv; + + /** + * Last packet ID sent to the service. + */ + uint32_t last_pid_sent; + + /** + * Last ACK value sent to the service: how much are we willing to accept? + */ + uint32_t last_ack_sent; +}; - /** - * Last pid received from the service. - */ - uint32_t last_recv_pid; + +/** + * Implementation state for mesh's message queue. + */ +struct MeshMQState +{ + /** + * The current transmit handle, or NULL + * if no transmit is active. + */ + struct GNUNET_MESH_TransmitHandle *th; /** - * Which ACK value have we last sent to the service? + * Tunnel to send the data over. */ - uint32_t max_recv_pid; + struct GNUNET_MESH_Tunnel *tunnel; }; @@ -431,13 +394,13 @@ message_ready_size (struct GNUNET_MESH_Handle *h) t = th->tunnel; if (GNUNET_NO == th_is_payload (th)) { - LOG (GNUNET_ERROR_TYPE_DEBUG, " message internal\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# message internal\n"); return th->size; } - if (GNUNET_NO == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid)) + if (GNUNET_YES == GMC_is_pid_bigger(t->last_ack_recv, t->last_pid_sent)) { - LOG (GNUNET_ERROR_TYPE_DEBUG, " message payload ok (%u <= %u)\n", - t->next_send_pid, t->max_send_pid); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# message payload ok (%u =< %u)\n", + t->last_pid_sent + 1, t->last_ack_recv); return th->size; } } @@ -495,8 +458,10 @@ create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid) { t->tid = tid; } - t->max_send_pid = INITIAL_WINDOW_SIZE - 1; - t->last_recv_pid = (uint32_t) -1; + t->last_ack_recv = (uint32_t) -1; + t->last_pid_recv = (uint32_t) -1; + t->last_ack_sent = (uint32_t) -1; + t->last_pid_sent = (uint32_t) -1; t->buffering = GNUNET_YES; return t; } @@ -518,10 +483,8 @@ static void destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner) { struct GNUNET_MESH_Handle *h; - struct GNUNET_PeerIdentity pi; struct GNUNET_MESH_TransmitHandle *th; struct GNUNET_MESH_TransmitHandle *next; - unsigned int i; LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid); @@ -532,21 +495,10 @@ destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner) } h = t->mesh; - /* disconnect all peers */ GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t); - for (i = 0; i < t->npeers; i++) - { - if ( (NULL != t->disconnect_handler) && t->peers[i]->connected) - { - GNUNET_PEER_resolve (t->peers[i]->id, &pi); - t->disconnect_handler (t->cls, &pi); - } - GNUNET_PEER_change_rc (t->peers[i]->id, -1); - GNUNET_free (t->peers[i]); - } /* signal tunnel destruction */ - if ( (NULL != h->cleaner) && (0 != t->owner) && (GNUNET_YES == call_cleaner) ) + if ( (NULL != h->cleaner) && (0 != t->peer) && (GNUNET_YES == call_cleaner) ) h->cleaner (h->cls, t, t->ctx); /* check that clients did not leave messages behind in the queue */ @@ -574,89 +526,14 @@ destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner) h->th = NULL; } - - if (t->npeers > 0) - GNUNET_free (t->peers); - if (0 != t->owner) - GNUNET_PEER_change_rc (t->owner, -1); - if (0 != t->napps && t->apps) - GNUNET_free (t->apps); + if (0 != t->peer) + GNUNET_PEER_change_rc (t->peer, -1); GNUNET_free (t); return; } /** - * Get the peer descriptor for the peer with id from the given tunnel - * @param t Tunnel handle - * @param id Short form ID of the wanted peer - * @return handle to the requested peer or NULL if not found - */ -static struct GNUNET_MESH_Peer * -retrieve_peer (struct GNUNET_MESH_Tunnel *t, GNUNET_PEER_Id id) -{ - unsigned int i; - - for (i = 0; i < t->npeers; i++) - if (t->peers[i]->id == id) - return t->peers[i]; - return NULL; -} - - -/** - * Add a peer into a tunnel - * @param t Tunnel handle - * @param pi Full ID of the new peer - * @return handle to the newly created peer - */ -static struct GNUNET_MESH_Peer * -add_peer_to_tunnel (struct GNUNET_MESH_Tunnel *t, - const struct GNUNET_PeerIdentity *pi) -{ - struct GNUNET_MESH_Peer *p; - GNUNET_PEER_Id id; - - if (0 != t->owner) - { - GNUNET_break (0); - return NULL; - } - id = GNUNET_PEER_intern (pi); - - p = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer)); - p->id = id; - p->t = t; - GNUNET_array_append (t->peers, t->npeers, p); - return p; -} - - -/** - * Remove a peer from a tunnel - * @param p Peer handle - */ -static void -remove_peer_from_tunnel (struct GNUNET_MESH_Peer *p) -{ - unsigned int i; - - for (i = 0; i < p->t->npeers; i++) - { - if (p->t->peers[i] == p) - break; - } - if (i == p->t->npeers) - { - GNUNET_break (0); - return; - } - p->t->peers[i] = p->t->peers[p->t->npeers - 1]; - GNUNET_array_grow (p->t->peers, p->t->npeers, p->t->npeers - 1); -} - - -/** * Notify client that the transmission has timed out * * @param cls closure @@ -725,36 +602,24 @@ send_packet (struct GNUNET_MESH_Handle *h, * @param t Tunnel on which to send the ACK. */ static void -send_ack (struct GNUNET_MESH_Handle *h, struct GNUNET_MESH_Tunnel *t) +send_ack (struct GNUNET_MESH_Tunnel *t) { struct GNUNET_MESH_LocalAck msg; - uint32_t delta; - delta = t->max_recv_pid - t->last_recv_pid; - if (delta > ACK_THRESHOLD) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Not sending ACK on tunnel %X: ACK: %u, PID: %u, buffer %u\n", - t->tid, t->max_recv_pid, t->last_recv_pid, delta); - return; - } - if (GNUNET_YES == t->buffering) - t->max_recv_pid = t->last_recv_pid + INITIAL_WINDOW_SIZE; - else - t->max_recv_pid = t->last_recv_pid + 1; + t->last_ack_sent = t->last_pid_recv + 1; LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK on tunnel %X: %u\n", - t->tid, t->max_recv_pid); + t->tid, t->last_ack_sent); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK); msg.header.size = htons (sizeof (msg)); msg.tunnel_id = htonl (t->tid); - msg.max_pid = htonl (t->max_recv_pid); + msg.ack = htonl (t->last_ack_sent); #if DEBUG_ACK t->mesh->acks_sent++; #endif - send_packet (h, &msg.header, t); + send_packet (t->mesh, &msg.header, t); return; } @@ -783,39 +648,27 @@ send_connect (struct GNUNET_MESH_Handle *h) size_t size; size = sizeof (struct GNUNET_MESH_ClientConnect); - size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType); - size += h->n_handlers * sizeof (uint16_t); + size += h->n_ports * sizeof (uint32_t); { char buf[size] GNUNET_ALIGN; struct GNUNET_MESH_ClientConnect *msg; - GNUNET_MESH_ApplicationType *apps; - uint16_t napps; - uint16_t *types; - uint16_t ntypes; + uint32_t *ports; + uint16_t i; /* build connection packet */ msg = (struct GNUNET_MESH_ClientConnect *) buf; msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT); msg->header.size = htons (size); - apps = (GNUNET_MESH_ApplicationType *) &msg[1]; - for (napps = 0; napps < h->n_applications; napps++) - { - apps[napps] = htonl (h->applications[napps]); - LOG (GNUNET_ERROR_TYPE_DEBUG, " app %u\n", - h->applications[napps]); - } - types = (uint16_t *) & apps[napps]; - for (ntypes = 0; ntypes < h->n_handlers; ntypes++) + ports = (uint32_t *) &msg[1]; + for (i = 0; i < h->n_ports; i++) { - types[ntypes] = htons (h->message_handlers[ntypes].type); - LOG (GNUNET_ERROR_TYPE_DEBUG, " type %u\n", - h->message_handlers[ntypes].type); + ports[i] = htonl (h->ports[i]); + LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n", + h->ports[i]); } - msg->applications = htons (napps); - msg->types = htons (ntypes); LOG (GNUNET_ERROR_TYPE_DEBUG, - "Sending %lu bytes long message %d types and %d apps\n", - ntohs (msg->header.size), ntypes, napps); + "Sending %lu bytes long message with %u ports\n", + ntohs (msg->header.size), h->n_ports); send_packet (h, &msg->header, NULL); } } @@ -833,7 +686,6 @@ static int do_reconnect (struct GNUNET_MESH_Handle *h) { struct GNUNET_MESH_Tunnel *t; - unsigned int i; LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, "******* RECONNECT *******\n"); @@ -878,7 +730,6 @@ do_reconnect (struct GNUNET_MESH_Handle *h) for (t = h->tunnels_head; NULL != t; t = t->next) { struct GNUNET_MESH_TunnelMessage tmsg; - struct GNUNET_MESH_PeerControl pmsg; if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) { @@ -888,42 +739,18 @@ do_reconnect (struct GNUNET_MESH_Handle *h) */ continue; } - t->next_send_pid = 0; - t->max_send_pid = INITIAL_WINDOW_SIZE - 1; - t->last_recv_pid = (uint32_t) -1; + t->last_ack_sent = (uint32_t) -1; + t->last_pid_sent = (uint32_t) -1; + t->last_ack_recv = (uint32_t) -1; + t->last_pid_recv = (uint32_t) -1; tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); tmsg.tunnel_id = htonl (t->tid); + GNUNET_PEER_resolve (t->peer, &tmsg.peer); send_packet (h, &tmsg.header, t); - pmsg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); - pmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD); - pmsg.tunnel_id = htonl (t->tid); - - /* Reconnect all peers */ - /* If the tunnel was "by type", dont connect individual peers */ - for (i = 0; i < t->npeers && 0 == t->napps; i++) - { - GNUNET_PEER_resolve (t->peers[i]->id, &pmsg.peer); - if (NULL != t->disconnect_handler && t->peers[i]->connected) - t->disconnect_handler (t->cls, &pmsg.peer); - send_packet (t->mesh, &pmsg.header, t); - } - /* Reconnect all types, if any */ - for (i = 0; i < t->napps; i++) - { - struct GNUNET_MESH_ConnectPeerByType msg; - - 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 (t->tid); - msg.type = htonl (t->apps[i]); - send_packet (t->mesh, &msg.header, t); - } if (GNUNET_NO == t->buffering) GNUNET_MESH_tunnel_buffer (t, GNUNET_NO); - if (GNUNET_YES == t->speed_min) - GNUNET_MESH_tunnel_speed_min (t); } return GNUNET_YES; } @@ -991,29 +818,18 @@ process_tunnel_created (struct GNUNET_MESH_Handle *h, } if (NULL != h->new_tunnel) { - struct GNUNET_ATS_Information atsi; - t = create_tunnel (h, tid); - t->owner = GNUNET_PEER_intern (&msg->peer); - t->npeers = 1; - t->peers = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer *)); - t->peers[0] = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer)); - t->peers[0]->t = t; - t->peers[0]->connected = 1; - t->peers[0]->id = t->owner; - GNUNET_PEER_change_rc (t->owner, 1); + t->last_ack_sent = 0; + t->peer = GNUNET_PEER_intern (&msg->peer); t->mesh = h; t->tid = tid; - if ((msg->opt & MESH_TUNNEL_OPT_NOBUFFER) != 0) + t->port = ntohl (msg->port); + if (0 != (msg->opt & MESH_TUNNEL_OPT_NOBUFFER)) t->buffering = GNUNET_NO; else t->buffering = GNUNET_YES; - if ((msg->opt & MESH_TUNNEL_OPT_SPEED_MIN) != 0) - t->speed_min = GNUNET_YES; - atsi.type = 0; - atsi.value = 0; LOG (GNUNET_ERROR_TYPE_DEBUG, " created tunnel %p\n", t); - t->ctx = h->new_tunnel (h->cls, t, &msg->peer, &atsi); + t->ctx = h->new_tunnel (h->cls, t, &msg->peer, t->port); LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n"); } else @@ -1052,10 +868,6 @@ process_tunnel_destroy (struct GNUNET_MESH_Handle *h, { return; } - if (0 == t->owner) - { - GNUNET_break (0); - } LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid); destroy_tunnel (t, GNUNET_YES); return; @@ -1063,81 +875,20 @@ process_tunnel_destroy (struct GNUNET_MESH_Handle *h, /** - * Process the new peer event and notify the upper level of it - * - * @param h The mesh handle - * @param msg A message with the details of the peer event - */ -static void -process_peer_event (struct GNUNET_MESH_Handle *h, - const struct GNUNET_MESH_PeerControl *msg) -{ - struct GNUNET_MESH_Tunnel *t; - struct GNUNET_MESH_Peer *p; - struct GNUNET_ATS_Information atsi; - GNUNET_PEER_Id id; - uint16_t size; - - LOG (GNUNET_ERROR_TYPE_DEBUG, "processig peer event\n"); - size = ntohs (msg->header.size); - if (size != sizeof (struct GNUNET_MESH_PeerControl)) - { - GNUNET_break (0); - return; - } - t = retrieve_tunnel (h, ntohl (msg->tunnel_id)); - if (NULL == t) - { - GNUNET_break (0); - return; - } - id = GNUNET_PEER_search (&msg->peer); - if ((p = retrieve_peer (t, id)) == NULL) - p = add_peer_to_tunnel (t, &msg->peer); - if (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD == ntohs (msg->header.type)) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "adding peer\n"); - if (NULL != t->connect_handler) - { - atsi.type = 0; - atsi.value = 0; - t->connect_handler (t->cls, &msg->peer, &atsi); - } - p->connected = 1; - } - else - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "removing peer\n"); - if (NULL != t->disconnect_handler && p->connected) - { - t->disconnect_handler (t->cls, &msg->peer); - } - remove_peer_from_tunnel (p); - GNUNET_free (p); - } - LOG (GNUNET_ERROR_TYPE_DEBUG, "processing peer event END\n"); -} - - -/** - * Process the incoming data packets + * Process the incoming data packets, call appropriate handlers. * * @param h The mesh handle * @param message A message encapsulating the data - * - * @return GNUNET_YES if everything went fine - * GNUNET_NO if client closed connection (h no longer valid) */ -static int +static void process_incoming_data (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *message) { const struct GNUNET_MessageHeader *payload; const struct GNUNET_MESH_MessageHandler *handler; const struct GNUNET_PeerIdentity *peer; - struct GNUNET_MESH_Unicast *ucast; - struct GNUNET_MESH_Multicast *mcast; - struct GNUNET_MESH_ToOrigin *to_orig; + struct GNUNET_PeerIdentity id; + struct GNUNET_MESH_Data *dmsg; struct GNUNET_MESH_Tunnel *t; unsigned int i; uint32_t pid; @@ -1148,72 +899,52 @@ process_incoming_data (struct GNUNET_MESH_Handle *h, switch (type) { case GNUNET_MESSAGE_TYPE_MESH_UNICAST: - ucast = (struct GNUNET_MESH_Unicast *) message; - - t = retrieve_tunnel (h, ntohl (ucast->tid)); - payload = (struct GNUNET_MessageHeader *) &ucast[1]; - peer = &ucast->oid; - pid = ntohl (ucast->pid); - LOG (GNUNET_ERROR_TYPE_DEBUG, " ucast on tunnel %s [%X]\n", - GNUNET_i2s (peer), ntohl (ucast->tid)); - break; - case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: - mcast = (struct GNUNET_MESH_Multicast *) message; - t = retrieve_tunnel (h, ntohl (mcast->tid)); - payload = (struct GNUNET_MessageHeader *) &mcast[1]; - peer = &mcast->oid; - pid = ntohl (mcast->pid); - LOG (GNUNET_ERROR_TYPE_DEBUG, " mcast on tunnel %s [%X]\n", - GNUNET_i2s (peer), ntohl (mcast->tid)); - break; case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - to_orig = (struct GNUNET_MESH_ToOrigin *) message; - t = retrieve_tunnel (h, ntohl (to_orig->tid)); - payload = (struct GNUNET_MessageHeader *) &to_orig[1]; - peer = &to_orig->sender; - pid = ntohl (to_orig->pid); - LOG (GNUNET_ERROR_TYPE_DEBUG, " torig on tunnel %s [%X]\n", - GNUNET_i2s (peer), ntohl (to_orig->tid)); + dmsg = (struct GNUNET_MESH_Data *) message; + + t = retrieve_tunnel (h, ntohl (dmsg->tid)); + payload = (struct GNUNET_MessageHeader *) &dmsg[1]; + GNUNET_PEER_resolve (t->peer, &id); + peer = &id; + pid = ntohl (dmsg->pid); + LOG (GNUNET_ERROR_TYPE_DEBUG, " %s data on tunnel %s [%X]\n", + type == GNUNET_MESSAGE_TYPE_MESH_UNICAST ? "fwd" : "bck", + GNUNET_i2s (peer), ntohl (dmsg->tid)); break; default: GNUNET_break (0); - return GNUNET_YES; + return; } LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", pid); if (NULL == t) { /* Tunnel was ignored/destroyed, probably service didn't get it yet */ LOG (GNUNET_ERROR_TYPE_DEBUG, " ignored!\n"); - return GNUNET_YES; + return; } if (GNUNET_YES == - GMC_is_pid_bigger(pid, t->max_recv_pid)) + GMC_is_pid_bigger(pid, t->last_ack_sent)) { GNUNET_break (0); LOG (GNUNET_ERROR_TYPE_WARNING, - " unauthorized message! (%u, max %u)\n", - pid, t->max_recv_pid); + " unauthorized message! (%u, ACK %u)\n", + pid, t->last_ack_sent); // FIXME fc what now? accept? reject? - return GNUNET_YES; + return; } - t->last_recv_pid = pid; + t->last_pid_recv = pid; type = ntohs (payload->type); - send_ack (h, t); for (i = 0; i < h->n_handlers; i++) { handler = &h->message_handlers[i]; if (handler->type == type) { - struct GNUNET_ATS_Information atsi; - - atsi.type = 0; - atsi.value = 0; if (GNUNET_OK != - handler->callback (h->cls, t, &t->ctx, peer, payload, &atsi)) + handler->callback (h->cls, t, &t->ctx, payload)) { LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n"); - GNUNET_MESH_disconnect (h); - return GNUNET_NO; + GNUNET_MESH_tunnel_destroy (t); + return; } else { @@ -1222,7 +953,6 @@ process_incoming_data (struct GNUNET_MESH_Handle *h, } } } - return GNUNET_YES; } @@ -1254,10 +984,10 @@ process_ack (struct GNUNET_MESH_Handle *h, ntohl (msg->tunnel_id)); return; } - ack = ntohl (msg->max_pid); + ack = ntohl (msg->ack); LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X, ack %u!\n", t->tid, ack); - if (GNUNET_YES == GMC_is_pid_bigger(ack, t->max_send_pid)) - t->max_send_pid = ack; + if (GNUNET_YES == GMC_is_pid_bigger(ack, t->last_ack_recv)) + t->last_ack_recv = ack; else return; if (NULL == h->th && 0 < t->packet_size) @@ -1282,7 +1012,6 @@ process_get_tunnels (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_LocalMonitor *msg; - uint32_t npeers; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n"); @@ -1293,25 +1022,21 @@ process_get_tunnels (struct GNUNET_MESH_Handle *h, } msg = (struct GNUNET_MESH_LocalMonitor *) message; - npeers = ntohl (msg->npeers); if (ntohs (message->size) != (sizeof (struct GNUNET_MESH_LocalMonitor) + - npeers * sizeof (struct GNUNET_PeerIdentity))) + sizeof (struct GNUNET_PeerIdentity))) { GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Get tunnels message: size %hu - expected %u (%u peers)\n", + "Get tunnels message: size %hu - expected %u\n", ntohs (message->size), - sizeof (struct GNUNET_MESH_LocalMonitor) + - npeers * sizeof (struct GNUNET_PeerIdentity), - npeers); + sizeof (struct GNUNET_MESH_LocalMonitor)); return; } h->tunnels_cb (h->tunnels_cls, - &msg->owner, ntohl (msg->tunnel_id), - (struct GNUNET_PeerIdentity *) &msg[1], - npeers); + &msg->owner, + &msg->destination); } @@ -1327,11 +1052,7 @@ process_show_tunnel (struct GNUNET_MESH_Handle *h, const struct GNUNET_MessageHeader *message) { struct GNUNET_MESH_LocalMonitor *msg; - struct GNUNET_PeerIdentity *new_peers; - uint32_t *new_parents; size_t esize; - uint32_t npeers; - unsigned int i; GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n"); @@ -1343,40 +1064,25 @@ process_show_tunnel (struct GNUNET_MESH_Handle *h, /* Verify message sanity */ msg = (struct GNUNET_MESH_LocalMonitor *) message; - npeers = ntohl (msg->npeers); esize = sizeof (struct GNUNET_MESH_LocalMonitor); - esize += npeers * (sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t)); if (ntohs (message->size) != esize) { GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Show tunnel message: size %hu - expected %u (%u peers)\n", + "Show tunnel message: size %hu - expected %u\n", ntohs (message->size), - esize, - npeers); + esize); h->tunnel_cb (h->tunnel_cls, NULL, NULL); h->tunnel_cb = NULL; h->tunnel_cls = NULL; - h->tunnel_npeers = 0; - GNUNET_free_non_null (h->peers); - h->peers = NULL; return; } - new_peers = (struct GNUNET_PeerIdentity *) &msg[1]; - new_parents = (uint32_t *) &new_peers[npeers]; - - h->peers = GNUNET_realloc (h->peers, h->tunnel_npeers + npeers); - memcpy (&h->peers[h->tunnel_npeers], - new_peers, - npeers * sizeof (struct GNUNET_PeerIdentity)); - h->tunnel_npeers += npeers; - for (i = 0; i < npeers; i++) - h->tunnel_cb (h->tunnel_cls, - &new_peers[i], - &h->peers[new_parents[i]]); + h->tunnel_cb (h->tunnel_cls, + &msg->destination, + &msg->owner); } @@ -1412,17 +1118,11 @@ msg_received (void *cls, const struct GNUNET_MessageHeader *msg) case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY: process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg); break; - /* Notify of a new peer or a peer disconnect in the tunnel */ - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD: - case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL: - process_peer_event (h, (struct GNUNET_MESH_PeerControl *) msg); - break; /* Notify of a new data packet in the tunnel */ case GNUNET_MESSAGE_TYPE_MESH_UNICAST: case GNUNET_MESSAGE_TYPE_MESH_MULTICAST: case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN: - if (GNUNET_NO == process_incoming_data (h, msg)) - return; + process_incoming_data (h, msg); break; case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK: process_ack (h, msg); @@ -1480,10 +1180,10 @@ send_callback (void *cls, size_t size, void *buf) size_t nsize; LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); - LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() Buffer %u\n", size); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size); if ((0 == size) || (NULL == buf)) { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Received NULL send callback on %p\n", h); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h); reconnect (h); h->th = NULL; return 0; @@ -1496,95 +1196,52 @@ send_callback (void *cls, size_t size, void *buf) t = th->tunnel; if (GNUNET_YES == th_is_payload (th)) { - LOG (GNUNET_ERROR_TYPE_DEBUG, " payload\n"); - if (GNUNET_YES == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid)) + struct GNUNET_MESH_Data *dmsg; + struct GNUNET_MessageHeader *mh; + + LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload\n"); + if (GNUNET_NO == GMC_is_pid_bigger (t->last_ack_recv, t->last_pid_sent)) { /* This tunnel is not ready to transmit yet, try next message */ next = th->next; continue; } t->packet_size = 0; - if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) + GNUNET_assert (size >= th->size); + dmsg = (struct GNUNET_MESH_Data *) cbuf; + mh = (struct GNUNET_MessageHeader *) &dmsg[1]; + psize = th->notify (th->notify_cls, + size - sizeof (struct GNUNET_MESH_Data), + mh); + if (psize > 0) { - /* traffic to origin */ - struct GNUNET_MESH_ToOrigin to; - struct GNUNET_MessageHeader *mh; - - GNUNET_assert (size >= th->size); - mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (to)]; - psize = th->notify (th->notify_cls, size - sizeof (to), mh); - LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin, type %s\n", - GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); - if (psize > 0) - { - psize += sizeof (to); - GNUNET_assert (size >= psize); - to.header.size = htons (psize); - to.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN); - to.tid = htonl (t->tid); - to.pid = htonl (t->next_send_pid); - to.ttl = 0; - memset (&to.oid, 0, sizeof (struct GNUNET_PeerIdentity)); - memset (&to.sender, 0, sizeof (struct GNUNET_PeerIdentity)); - memcpy (cbuf, &to, sizeof (to)); - } + psize += sizeof (struct GNUNET_MESH_Data); + GNUNET_assert (size >= psize); + dmsg->header.size = htons (psize); + dmsg->tid = htonl (t->tid); + dmsg->pid = htonl (t->last_pid_sent + 1); + dmsg->ttl = 0; + memset (&dmsg->oid, 0, sizeof (struct GNUNET_PeerIdentity)); + t->last_pid_sent++; } - else if (th->target == 0) + if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) { - /* multicast */ - struct GNUNET_MESH_Multicast mc; - struct GNUNET_MessageHeader *mh; - - GNUNET_assert (size >= th->size); - mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (mc)]; - psize = th->notify (th->notify_cls, size - sizeof (mc), mh); - LOG (GNUNET_ERROR_TYPE_DEBUG, " multicast, type %s\n", + dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# to origin, type %s\n", GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); - if (psize > 0) - { - psize += sizeof (mc); - GNUNET_assert (size >= psize); - mc.header.size = htons (psize); - mc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST); - mc.tid = htonl (t->tid); - mc.pid = htonl (t->next_send_pid); - mc.ttl = 0; - memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity)); - memcpy (cbuf, &mc, sizeof (mc)); - } } else { - /* unicast */ - struct GNUNET_MESH_Unicast uc; - struct GNUNET_MessageHeader *mh; - - GNUNET_assert (size >= th->size); - mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (uc)]; - psize = th->notify (th->notify_cls, size - sizeof (uc), mh); - LOG (GNUNET_ERROR_TYPE_DEBUG, " unicast, type %s\n", + dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# unicast, type %s\n", GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); - if (psize > 0) - { - psize += sizeof (uc); - GNUNET_assert (size >= psize); - uc.header.size = htons (psize); - uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST); - uc.tid = htonl (t->tid); - uc.pid = htonl (t->next_send_pid); - uc.ttl = 0; - memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity)); - GNUNET_PEER_resolve (th->target, &uc.destination); - memcpy (cbuf, &uc, sizeof (uc)); - } } - t->next_send_pid++; } else { struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1]; - LOG (GNUNET_ERROR_TYPE_DEBUG, " mesh traffic, type %s\n", + LOG (GNUNET_ERROR_TYPE_DEBUG, "# mesh traffic, type %s\n", GNUNET_MESH_DEBUG_M2S (ntohs (mh->type))); memcpy (cbuf, &th[1], th->size); psize = th->size; @@ -1599,12 +1256,12 @@ send_callback (void *cls, size_t size, void *buf) size -= psize; tsize += psize; } - LOG (GNUNET_ERROR_TYPE_DEBUG, " total size: %u\n", tsize); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# total size: %u\n", tsize); h->th = NULL; size = message_ready_size (h); if (0 != size) { - LOG (GNUNET_ERROR_TYPE_DEBUG, " next size: %u\n", size); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# next size: %u\n", size); h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, size, GNUNET_TIME_UNIT_FOREVER_REL, @@ -1613,18 +1270,18 @@ send_callback (void *cls, size_t size, void *buf) else { if (NULL != h->th_head) - LOG (GNUNET_ERROR_TYPE_DEBUG, " can't transmit any more\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# can't transmit any more\n"); else - LOG (GNUNET_ERROR_TYPE_DEBUG, " nothing left to transmit\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# nothing left to transmit\n"); } if (GNUNET_NO == h->in_receive) { - LOG (GNUNET_ERROR_TYPE_DEBUG, " start receiving from service\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n"); h->in_receive = GNUNET_YES; GNUNET_CLIENT_receive (h->client, &msg_received, h, GNUNET_TIME_UNIT_FOREVER_REL); } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() END\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n"); return tsize; } @@ -1670,33 +1327,14 @@ send_packet (struct GNUNET_MESH_Handle *h, /********************** API CALL DEFINITIONS *************************/ /******************************************************************************/ -/** - * Connect to the mesh service. - * - * @param cfg configuration to use - * @param cls closure for the various callbacks that follow - * (including handlers in the handlers array) - * @param new_tunnel function called when an *inbound* tunnel is created - * @param cleaner function called when an *inbound* tunnel is destroyed by the - * remote peer, it is *not* called if GNUNET_MESH_tunnel_destroy - * is called on the tunnel - * @param handlers callbacks for messages we care about, NULL-terminated - * note that the mesh is allowed to drop notifications about - * inbound messages if the client does not process them fast - * enough (for this notification type, a bounded queue is used) - * @param stypes list of the applications that this client claims to provide - * @return handle to the mesh service NULL on error - * (in this case, init is never called) - */ struct GNUNET_MESH_Handle * GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, GNUNET_MESH_TunnelEndHandler cleaner, const struct GNUNET_MESH_MessageHandler *handlers, - const GNUNET_MESH_ApplicationType *stypes) + const uint32_t *ports) { struct GNUNET_MESH_Handle *h; - size_t size; LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n"); h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle)); @@ -1713,38 +1351,24 @@ GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, } h->cls = cls; h->message_handlers = handlers; + h->ports = ports; h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI; h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; - /* count apps */ - for (h->n_applications = 0; - stypes && stypes[h->n_applications]; - h->n_applications++) ; - if (0 < h->n_applications) - { - size = h->n_applications * sizeof (GNUNET_MESH_ApplicationType *); - h->applications = GNUNET_malloc (size); - memcpy (h->applications, stypes, size); - } /* count handlers */ for (h->n_handlers = 0; handlers && handlers[h->n_handlers].type; h->n_handlers++) ; + for (h->n_ports = 0; + ports && ports[h->n_ports]; + h->n_ports++) ; send_connect (h); LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n"); return h; } -/** - * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel - * disconnect callbacks will be called on any still connected peers, notifying - * about their disconnection. The registered inbound tunnel cleaner will be - * called should any inbound tunnels still exist. - * - * @param handle connection to mesh to disconnect - */ void GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) { @@ -1812,75 +1436,15 @@ GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle) GNUNET_SCHEDULER_cancel(handle->reconnect_task); handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; } - GNUNET_free_non_null (handle->applications); GNUNET_free (handle); } -/** - * Announce to ther peer the availability of services described by the regex, - * in order to be reachable to other peers via connect_by_string. - * - * Note that the first 8 characters are considered to be part of a prefix, - * (for instance 'gnunet://'). If you put a variable part in there (*, +. ()), - * all matching strings will be stored in the DHT. - * - * @param h Handle to mesh. - * @param regex String with the regular expression describing local services. - * @param compression_characters How many characters can be assigned to one - * edge of the graph. The bigger the variability - * of the data, the smaller this parameter should - * be (down to 1). - * For maximum compression, use strlen (regex) - * or 0 (special value). Use with care! - */ -void -GNUNET_MESH_announce_regex (struct GNUNET_MESH_Handle *h, - const char *regex, - unsigned int compression_characters) -{ - struct GNUNET_MESH_RegexAnnounce *msg; - size_t payload; - size_t len; - size_t msgsize; - size_t offset; - char buffer[UINT16_MAX]; - - len = strlen (regex); - payload = UINT16_MAX - sizeof(struct GNUNET_MESH_RegexAnnounce); - msg = (struct GNUNET_MESH_RegexAnnounce *) buffer; - msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX); - msg->compression_characters = htons (compression_characters); - offset = 0; - do - { - msgsize = (len - offset > payload) ? payload : len - offset; - memcpy (&msg[1], ®ex[offset], msgsize); - offset += msgsize; - msgsize += sizeof(struct GNUNET_MESH_RegexAnnounce); - - msg->header.size = htons (msgsize); - msg->last = htons (offset >= len); - - send_packet (h, &msg->header, NULL); - } while (len > offset); -} - -/** - * Create a new tunnel (we're initiator and will be allowed to add/remove peers - * and to broadcast). - * - * @param h mesh handle - * @param tunnel_ctx client's tunnel context to associate with the tunnel - * @param connect_handler function to call when peers are actually connected - * @param disconnect_handler function to call when peers are disconnected - * @param handler_cls closure for connect/disconnect handlers - */ struct GNUNET_MESH_Tunnel * -GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx, - GNUNET_MESH_PeerConnectHandler connect_handler, - GNUNET_MESH_PeerDisconnectHandler disconnect_handler, - void *handler_cls) +GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, + void *tunnel_ctx, + const struct GNUNET_PeerIdentity *peer, + uint32_t port) { struct GNUNET_MESH_Tunnel *t; struct GNUNET_MESH_TunnelMessage msg; @@ -1889,24 +1453,19 @@ GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx, t = create_tunnel (h, 0); LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", t); LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", t->tid); - t->connect_handler = connect_handler; - t->disconnect_handler = disconnect_handler; - t->cls = handler_cls; t->ctx = tunnel_ctx; + t->peer = GNUNET_PEER_intern (peer); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE); msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); msg.tunnel_id = htonl (t->tid); + msg.port = htonl (port); + msg.peer = *peer; + t->last_ack_sent = 0; send_packet (h, &msg.header, t); return t; } -/** - * Destroy an existing tunnel. The existing callback for the tunnel will NOT - * be called. - * - * @param tunnel tunnel handle - */ void GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel) { @@ -1938,62 +1497,11 @@ GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel) th = th->next; } - destroy_tunnel (tunnel, GNUNET_NO); + destroy_tunnel (tunnel, GNUNET_YES); send_packet (h, &msg.header, NULL); } -/** - * Request that the tunnel data rate is limited to the speed of the slowest - * receiver. - * - * @param tunnel Tunnel affected. - */ -void -GNUNET_MESH_tunnel_speed_min (struct GNUNET_MESH_Tunnel *tunnel) -{ - struct GNUNET_MESH_TunnelMessage msg; - struct GNUNET_MESH_Handle *h; - - h = tunnel->mesh; - tunnel->speed_min = GNUNET_YES; - - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN); - msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); - msg.tunnel_id = htonl (tunnel->tid); - - send_packet (h, &msg.header, NULL); -} - - -/** - * Request that the tunnel data rate is limited to the speed of the fastest - * receiver. This is the default behavior. - * - * @param tunnel Tunnel affected. - */ -void -GNUNET_MESH_tunnel_speed_max (struct GNUNET_MESH_Tunnel *tunnel) -{ - struct GNUNET_MESH_TunnelMessage msg; - struct GNUNET_MESH_Handle *h; - - h = tunnel->mesh; - tunnel->speed_min = GNUNET_NO; - - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX); - msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage)); - msg.tunnel_id = htonl (tunnel->tid); - - send_packet (h, &msg.header, NULL); -} -/** - * Turn on/off the buffering status of the tunnel. - * - * @param tunnel Tunnel affected. - * @param buffer GNUNET_YES to turn buffering on (default), - * GNUNET_NO otherwise. - */ void GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer) { @@ -2002,7 +1510,6 @@ GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer) h = tunnel->mesh; tunnel->buffering = buffer; - tunnel->max_send_pid = tunnel->next_send_pid; if (GNUNET_YES == buffer) msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER); @@ -2015,267 +1522,39 @@ GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer) } -/** - * 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. - * FIXME: I think the above documentation is false. I think it should - * read: "The connect handler will be called once the peer was actually - * successfully added to the multicast group. This function should - * not be called twice for the same peer (unless, of course, - * the peer was removed using GNUNET_MESH_peer_Request_connect_del in - * the meantime). - * - * @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, tunnel); -} - - -/** - * 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, tunnel); -} - - -/** - * 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); - - LOG (GNUNET_ERROR_TYPE_DEBUG, "* CONNECT BY TYPE *\n"); - 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, tunnel); -} - - -/** - * Request that the mesh should try to connect to a peer matching the - * description given in the service string. - * - * FIXME: allow multiple? how to deal with reconnect? - * - * @param tunnel handle to existing tunnel - * @param description string describing the destination node requirements - */ -void -GNUNET_MESH_peer_request_connect_by_string (struct GNUNET_MESH_Tunnel *tunnel, - const char *description) -{ - struct GNUNET_MESH_ConnectPeerByString *m; - size_t len; - size_t msgsize; - - len = strlen (description); - msgsize = sizeof(struct GNUNET_MESH_ConnectPeerByString) + len; - GNUNET_assert (UINT16_MAX > msgsize); - { - char buffer[msgsize]; - - m = (struct GNUNET_MESH_ConnectPeerByString *) buffer; - m->header.size = htons (msgsize); - m->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING); - m->tunnel_id = htonl (tunnel->tid); - memcpy(&m[1], description, len); - - send_packet (tunnel->mesh, &m->header, tunnel); - } -} - - -/** - * Request that the given peer isn't added to this tunnel in calls to - * connect_by_* calls, (due to misbehaviour, bad performance, ...). - * - * @param tunnel handle to existing tunnel. - * @param peer peer identity of the peer which should be blacklisted - * for the tunnel. - */ -void -GNUNET_MESH_peer_blacklist (struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *peer) -{ - struct GNUNET_MESH_PeerControl msg; - - msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST); - msg.tunnel_id = htonl (tunnel->tid); - msg.peer = *peer; - send_packet (tunnel->mesh, &msg.header, tunnel); - - return; -} - - -/** - * Request that the given peer isn't blacklisted anymore from this tunnel, - * and therefore can be added in future calls to connect_by_*. - * The peer must have been previously blacklisted for this tunnel. - * - * @param tunnel handle to existing tunnel. - * @param peer peer identity of the peer which shouldn't be blacklisted - * for the tunnel anymore. - */ -void -GNUNET_MESH_peer_unblacklist (struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *peer) -{ - struct GNUNET_MESH_PeerControl msg; - - msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl)); - msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST); - msg.tunnel_id = htonl (tunnel->tid); - msg.peer = *peer; - send_packet (tunnel->mesh, &msg.header, tunnel); - - return; -} - - -/** - * Ask the mesh to call "notify" once it is ready to transmit the - * given number of bytes to the specified tunnel or target. - * Only one call can be active at any time, to issue another request, - * wait for the callback or cancel the current request. - * - * @param tunnel tunnel to use for transmission - * @param cork is corking allowed for this transmission? - * @param maxdelay how long can the message wait? - * @param target destination for the message - * NULL for multicast to all tunnel targets - * @param notify_size how many bytes of buffer space does notify want? - * @param notify function to call when buffer space is available; - * will be called with NULL on timeout or if the overall queue - * for this peer is larger than queue_size and this is currently - * the message with the lowest priority - * @param notify_cls closure for notify - * @return non-NULL if the notify callback was queued, - * NULL if we can not even queue the request (insufficient - * memory); if NULL is returned, "notify" will NOT be called. - */ struct GNUNET_MESH_TransmitHandle * GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork, struct GNUNET_TIME_Relative maxdelay, - const struct GNUNET_PeerIdentity *target, size_t notify_size, GNUNET_CONNECTION_TransmitReadyNotify notify, void *notify_cls) { struct GNUNET_MESH_TransmitHandle *th; - size_t overhead; GNUNET_assert (NULL != tunnel); LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tunnel->tid); if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n"); - else if (NULL != target) - LOG (GNUNET_ERROR_TYPE_DEBUG, " target %s\n", GNUNET_i2s (target)); else - LOG (GNUNET_ERROR_TYPE_DEBUG, " target multicast\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, " to destination\n"); LOG (GNUNET_ERROR_TYPE_DEBUG, " payload size %u\n", notify_size); GNUNET_assert (NULL != notify); GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle)); th->tunnel = tunnel; th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); - th->target = GNUNET_PEER_intern (target); - if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV) - overhead = sizeof (struct GNUNET_MESH_ToOrigin); - else if (NULL == target) - overhead = sizeof (struct GNUNET_MESH_Multicast); - else - overhead = sizeof (struct GNUNET_MESH_Unicast); - tunnel->packet_size = th->size = notify_size + overhead; + th->size = notify_size + sizeof (struct GNUNET_MESH_Data); + tunnel->packet_size = th->size; LOG (GNUNET_ERROR_TYPE_DEBUG, " total size %u\n", th->size); th->notify = notify; th->notify_cls = notify_cls; add_to_queue (tunnel->mesh, th); if (NULL != tunnel->mesh->th) return th; - if (GMC_is_pid_bigger(tunnel->next_send_pid, tunnel->max_send_pid)) + if (!GMC_is_pid_bigger (tunnel->last_ack_recv, tunnel->last_pid_sent)) return th; - LOG (GNUNET_ERROR_TYPE_DEBUG, " call notify tmt rdy\n"); + LOG (GNUNET_ERROR_TYPE_DEBUG, " call client notify tmt rdy\n"); tunnel->mesh->th = GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size, GNUNET_TIME_UNIT_FOREVER_REL, @@ -2286,11 +1565,6 @@ GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork, } -/** - * Cancel the specified transmission-ready notification. - * - * @param th handle that was returned by "notify_transmit_ready". - */ void GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th) { @@ -2310,6 +1584,12 @@ GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th) } } +void +GNUNET_MESH_receive_done (struct GNUNET_MESH_Tunnel *tunnel) +{ + send_ack (tunnel); +} + /** * Request information about the running mesh peer. @@ -2366,6 +1646,7 @@ GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h) * Request information about a specific tunnel of the running mesh peer. * * WARNING: unstable API, likely to change in the future! + * FIXME Add destination option. * * @param h Handle to the mesh peer. * @param initiator ID of the owner of the tunnel. @@ -2384,7 +1665,6 @@ GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h, msg.header.size = htons (sizeof (msg)); msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL); - msg.npeers = htonl (0); msg.owner = *initiator; msg.tunnel_id = htonl (tunnel_number); msg.reserved = 0; @@ -2397,21 +1677,111 @@ GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h, /** - * Transition API for tunnel ctx management + * Function called to notify a client about the connection + * begin ready to queue more data. "buf" will be + * NULL and "size" zero if the connection was closed for + * writing in the meantime. + * + * @param cls closure + * @param size number of bytes available in buf + * @param buf where the callee should write the message + * @return number of bytes written to buf */ -void -GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data) +static size_t +mesh_mq_ntr (void *cls, size_t size, + void *buf) { - tunnel->ctx = data; + struct GNUNET_MQ_Handle *mq = cls; + struct MeshMQState *state = GNUNET_MQ_impl_state (mq); + const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq); + uint16_t msize; + + state->th = NULL; + if (NULL == buf) + { + GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE); + return 0; + } + msize = ntohs (msg->size); + GNUNET_assert (msize <= size); + memcpy (buf, msg, msize); + GNUNET_MQ_impl_send_continue (mq); + return msize; } + /** - * Transition API for tunnel ctx management + * Signature of functions implementing the + * sending functionality of a message queue. + * + * @param mq the message queue + * @param msg the message to send + * @param impl_state state of the implementation */ -void * -GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel) +static void +mesh_mq_send_impl (struct GNUNET_MQ_Handle *mq, + const struct GNUNET_MessageHeader *msg, void *impl_state) { - return tunnel->ctx; + struct MeshMQState *state = impl_state; + + GNUNET_assert (NULL == state->th); + GNUNET_MQ_impl_send_commit (mq); + state->th = + GNUNET_MESH_notify_transmit_ready (state->tunnel, + /* FIXME: add option for corking */ + GNUNET_NO, + GNUNET_TIME_UNIT_FOREVER_REL, + ntohs (msg->size), + mesh_mq_ntr, mq); + } +/** + * Signature of functions implementing the + * destruction of a message queue. + * Implementations must not free 'mq', but should + * take care of 'impl_state'. + * + * @param mq the message queue to destroy + * @param impl_state state of the implementation + */ +static void +mesh_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state) +{ + struct MeshMQState *state = impl_state; + + if (NULL != state->th) + GNUNET_MESH_notify_transmit_ready_cancel (state->th); + + GNUNET_free (state); +} + + +/** + * Create a message queue for a mesh tunnel. + * The message queue can only be used to transmit messages, + * not to receive them. + * + * @param tunnel the tunnel to create the message qeue for + * @return a message queue to messages over the tunnel + */ +struct GNUNET_MQ_Handle * +GNUNET_MESH_mq_create (struct GNUNET_MESH_Tunnel *tunnel) +{ + struct GNUNET_MQ_Handle *mq; + struct MeshMQState *state; + + state = GNUNET_new (struct MeshMQState); + state->tunnel = tunnel; + + mq = GNUNET_MQ_queue_for_callbacks (mesh_mq_send_impl, + mesh_mq_destroy_impl, + NULL, /* FIXME: cancel impl. */ + state, + NULL, /* no msg handlers */ + NULL, /* no err handlers */ + NULL); /* no handler cls */ + return mq; +} + diff --git a/src/mesh/mesh_path.c b/src/mesh/mesh_path.c index 05444655aa..1a3d40f9fe 100644 --- a/src/mesh/mesh_path.c +++ b/src/mesh/mesh_path.c @@ -24,7 +24,7 @@ * @author Bartlomiej Polot */ -#include "mesh2.h" +#include "mesh.h" #include "mesh_path.h" diff --git a/src/mesh/mesh_path.h b/src/mesh/mesh_path.h index c3f3264b00..74a35b2257 100644 --- a/src/mesh/mesh_path.h +++ b/src/mesh/mesh_path.h @@ -35,7 +35,7 @@ extern "C" #endif #endif -#include "mesh2.h" +#include "mesh.h" /******************************************************************************/ /************************ DATA STRUCTURES ****************************/ diff --git a/src/mesh/mesh_protocol.h b/src/mesh/mesh_protocol.h index 01f7f3487d..d35d7141ee 100644 --- a/src/mesh/mesh_protocol.h +++ b/src/mesh/mesh_protocol.h @@ -35,7 +35,6 @@ extern "C" #endif #endif -#define MESH_TUNNEL_OPT_SPEED_MIN 0x1 #define MESH_TUNNEL_OPT_NOBUFFER 0x2 @@ -46,12 +45,12 @@ extern "C" GNUNET_NETWORK_STRUCT_BEGIN /** - * Message for mesh path management + * Message for mesh path creation. */ -struct GNUNET_MESH_ManipulatePath +struct GNUNET_MESH_CreateTunnel { /** - * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_[CREATE|CHANGE|ADD|DESTROY] + * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE * * Size: sizeof(struct GNUNET_MESH_ManipulatePath) + * path_length * sizeof (struct GNUNET_PeerIdentity) @@ -70,11 +69,12 @@ struct GNUNET_MESH_ManipulatePath uint32_t opt GNUNET_PACKED; /** - * 64 bit alignment padding. + * Destination port. */ - uint32_t reserved GNUNET_PACKED; + uint32_t port GNUNET_PACKED; /** + * FIXME do not add the first hop * path_length structs defining the *whole* path from the origin [0] to the * final destination [path_length-1]. */ @@ -82,89 +82,34 @@ struct GNUNET_MESH_ManipulatePath }; /** - * Message for mesh data traffic to all tunnel targets. + * Message for mesh path destruction. */ -struct GNUNET_MESH_Multicast +struct GNUNET_MESH_DestroyTunnel { - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_MULTICAST - */ - struct GNUNET_MessageHeader header; - - /** - * TID of the tunnel - */ - uint32_t tid GNUNET_PACKED; - - /** - * Number of hops to live - */ - uint32_t ttl GNUNET_PACKED; - - /** - * Unique ID of the packet - */ - uint32_t pid GNUNET_PACKED; - - /** - * OID of the tunnel - */ - struct GNUNET_PeerIdentity oid; - - /** - * Payload follows - */ -}; - - -/** - * Message for mesh data traffic to a particular destination from origin. - */ -struct GNUNET_MESH_Unicast -{ - /** - * Type: GNUNET_MESSAGE_TYPE_MESH_UNICAST - */ + /** + * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY + * + * Size: sizeof(struct GNUNET_MESH_ManipulatePath) + + * path_length * sizeof (struct GNUNET_PeerIdentity) + */ struct GNUNET_MessageHeader header; - - /** - * TID of the tunnel - */ + + /** + * Global id of the tunnel this path belongs to, + * unique in conjunction with the origin. + */ uint32_t tid GNUNET_PACKED; - - /** - * Number of hops to live - */ - uint32_t ttl GNUNET_PACKED; - - /** - * Unique ID of the packet - */ - uint32_t pid GNUNET_PACKED; - - /** - * OID of the tunnel - */ - struct GNUNET_PeerIdentity oid; - - /** - * Destination. - */ - struct GNUNET_PeerIdentity destination; - - /** - * Payload follows - */ }; /** - * Message for mesh data traffic from a tunnel participant to origin. + * Message for mesh data traffic. */ -struct GNUNET_MESH_ToOrigin +struct GNUNET_MESH_Data { /** - * Type: GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN + * Type: GNUNET_MESSAGE_TYPE_MESH_UNICAST, + * GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN */ struct GNUNET_MessageHeader header; @@ -189,11 +134,6 @@ struct GNUNET_MESH_ToOrigin struct GNUNET_PeerIdentity oid; /** - * Sender of the message. - */ - struct GNUNET_PeerIdentity sender; - - /** * Payload follows */ }; @@ -245,11 +185,6 @@ struct GNUNET_MESH_Poll * OID of the tunnel */ struct GNUNET_PeerIdentity oid; - - /** - * Last ACK received. - */ - uint32_t last_ack; }; /** @@ -277,6 +212,11 @@ struct GNUNET_MESH_PathACK */ struct GNUNET_PeerIdentity peer_id; + /** + * Initial ACK value for payload. + */ + uint32_t ack GNUNET_PACKED; + /* TODO: signature */ }; diff --git a/src/mesh/mesh_test_lib.c b/src/mesh/mesh_test_lib.c index 7c4d884a66..e9ccb631fa 100644 --- a/src/mesh/mesh_test_lib.c +++ b/src/mesh/mesh_test_lib.c @@ -78,9 +78,9 @@ struct GNUNET_MESH_TEST_Context struct GNUNET_MESH_MessageHandler* handlers; /** - * Application types. + * Application ports. */ - const GNUNET_MESH_ApplicationType* stypes; + const uint32_t *ports; }; @@ -125,7 +125,7 @@ mesh_connect_adapter (void *cls, ctx->new_tunnel, ctx->cleaner, ctx->handlers, - ctx->stypes); + ctx->ports); return h; } @@ -190,11 +190,6 @@ mesh_connect_cb (void *cls, } -/** - * Clean up the testbed. - * - * @param ctx handle for the testbed - */ void GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx) { @@ -255,21 +250,6 @@ mesh_test_run (void *cls, } -/** - * Run a test using the given name, configuration file and number of - * peers. - * All mesh callbacks will receive the peer number as the closure. - * - * @param testname Name of the test (for logging). - * @param cfgname Name of the configuration file. - * @param num_peers Number of peers to start. - * @param tmain Main function to run once the testbed is ready. - * @param tmain_cls Closure for 'tmain'. - * @param new_tunnel Handler for incoming tunnels. - * @param cleaner Cleaner for destroyed incoming tunnels. - * @param handlers Message handlers. - * @param stypes Application types. - */ void GNUNET_MESH_TEST_run (const char *testname, const char *cfgname, @@ -279,7 +259,7 @@ GNUNET_MESH_TEST_run (const char *testname, GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, GNUNET_MESH_TunnelEndHandler cleaner, struct GNUNET_MESH_MessageHandler* handlers, - const GNUNET_MESH_ApplicationType* stypes) + const uint32_t *ports) { struct GNUNET_MESH_TEST_Context *ctx; @@ -292,7 +272,7 @@ GNUNET_MESH_TEST_run (const char *testname, ctx->new_tunnel = new_tunnel; ctx->cleaner = cleaner; ctx->handlers = handlers; - ctx->stypes = stypes; + ctx->ports = ports; GNUNET_TESTBED_test_run (testname, cfgname, num_peers, diff --git a/src/mesh/mesh_test_lib.h b/src/mesh/mesh_test_lib.h index 554d06541e..4dd2151b8a 100644 --- a/src/mesh/mesh_test_lib.h +++ b/src/mesh/mesh_test_lib.h @@ -71,7 +71,7 @@ typedef void (*GNUNET_MESH_TEST_AppMain) (void *cls, * @param new_tunnel Handler for incoming tunnels. * @param cleaner Cleaner for destroyed incoming tunnels. * @param handlers Message handlers. - * @param stypes Application types. + * @param ports Ports the peers offer. */ void GNUNET_MESH_TEST_run (const char *testname, @@ -82,7 +82,7 @@ GNUNET_MESH_TEST_run (const char *testname, GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel, GNUNET_MESH_TunnelEndHandler cleaner, struct GNUNET_MESH_MessageHandler* handlers, - const GNUNET_MESH_ApplicationType* stypes); + const uint32_t* ports); /** diff --git a/src/mesh/plugin_block_mesh.c b/src/mesh/plugin_block_mesh.c index 3d99201f78..cbfd57eb4a 100644 --- a/src/mesh/plugin_block_mesh.c +++ b/src/mesh/plugin_block_mesh.c @@ -149,7 +149,6 @@ block_plugin_mesh_get_key (void *cls, enum GNUNET_BLOCK_Type type, struct GNUNET_HashCode * key) { const struct PBlock *pb; - GNUNET_MESH_ApplicationType app_type; pb = block; switch (type) @@ -159,10 +158,6 @@ block_plugin_mesh_get_key (void *cls, enum GNUNET_BLOCK_Type type, return GNUNET_SYSERR; *key = pb->id.hashPubKey; return GNUNET_OK; - case GNUNET_BLOCK_TYPE_MESH_PEER_BY_TYPE: - app_type = ntohl (pb->type); - GNUNET_CRYPTO_hash (&app_type, sizeof(GNUNET_MESH_ApplicationType), key); - return GNUNET_OK; default: GNUNET_break (0); return GNUNET_SYSERR; diff --git a/src/mesh/test_mesh.conf b/src/mesh/test_mesh.conf index 3b35a16b46..58dff5adce 100644 --- a/src/mesh/test_mesh.conf +++ b/src/mesh/test_mesh.conf @@ -1,17 +1,15 @@ -[fs] -AUTOSTART = NO - -[resolver] -AUTOSTART = NO +[PATHS] +SERVICEHOME = /tmp/test-mesh/ [mesh] -AUTOSTART = YES +BINARY = gnunet-service-mesh-new +AUTOSTART = NO ACCEPT_FROM = 127.0.0.1; HOSTNAME = localhost PORT = 10511 -# PREFIX = valgrind --leak-check=full -# PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args -REFRESH_PATH_TIME = 3 s +#PREFIX = valgrind --leak-check=full +#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args +REFRESH_PATH_TIME = 2 s APP_ANNOUNCE_TIME = 5 s ID_ANNOUNCE_TIME = 5 s CONNECT_TIMEOUT = 30 s @@ -20,6 +18,16 @@ DHT_REPLICATION_LEVEL = 3 MAX_TUNNELS = 10 MAX_MSGS_QUEUE = 20 +[testbed] +NUM_PEERS = 5 +OVERLAY_TOPOLOGY = LINE + +[fs] +AUTOSTART = NO + +[resolver] +AUTOSTART = NO + [vpn] AUTOSTART = NO PORT = 10012 @@ -30,6 +38,8 @@ ACCEPT_FROM6 = ::1; ACCEPT_FROM = 127.0.0.1; HOSTNAME = localhost PORT = 12100 +DISABLE_TRY_CONNECT = YES +FORCE_NSE = 3 [block] plugins = dht test @@ -53,7 +63,7 @@ WAN_QUOTA_IN = 3932160 PORT = 12092 [arm] -DEFAULTSERVICES = core +DEFAULTSERVICES = core mesh PORT = 12366 [transport-tcp] @@ -66,9 +76,6 @@ WEAKRANDOM = YES [gnunetd] HOSTKEY = $SERVICEHOME/.hostkey -[PATHS] -SERVICEHOME = /tmp/test-mesh/ - [dns] AUTOSTART = NO diff --git a/src/mesh/test_mesh2.conf b/src/mesh/test_mesh2.conf deleted file mode 100644 index 58dff5adce..0000000000 --- a/src/mesh/test_mesh2.conf +++ /dev/null @@ -1,89 +0,0 @@ -[PATHS] -SERVICEHOME = /tmp/test-mesh/ - -[mesh] -BINARY = gnunet-service-mesh-new -AUTOSTART = NO -ACCEPT_FROM = 127.0.0.1; -HOSTNAME = localhost -PORT = 10511 -#PREFIX = valgrind --leak-check=full -#PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args -REFRESH_PATH_TIME = 2 s -APP_ANNOUNCE_TIME = 5 s -ID_ANNOUNCE_TIME = 5 s -CONNECT_TIMEOUT = 30 s -DEFAULT_TTL = 16 -DHT_REPLICATION_LEVEL = 3 -MAX_TUNNELS = 10 -MAX_MSGS_QUEUE = 20 - -[testbed] -NUM_PEERS = 5 -OVERLAY_TOPOLOGY = LINE - -[fs] -AUTOSTART = NO - -[resolver] -AUTOSTART = NO - -[vpn] -AUTOSTART = NO -PORT = 10012 - -[dht] -AUTOSTART = YES -ACCEPT_FROM6 = ::1; -ACCEPT_FROM = 127.0.0.1; -HOSTNAME = localhost -PORT = 12100 -DISABLE_TRY_CONNECT = YES -FORCE_NSE = 3 - -[block] -plugins = dht test - -[dhtcache] -QUOTA = 1 MB -DATABASE = sqlite - -[transport] -PLUGINS = tcp -ACCEPT_FROM6 = ::1; -ACCEPT_FROM = 127.0.0.1; -NEIGHBOUR_LIMIT = 50 -PORT = 12365 - -[ats] -WAN_QUOTA_OUT = 3932160 -WAN_QUOTA_IN = 3932160 - -[core] -PORT = 12092 - -[arm] -DEFAULTSERVICES = core mesh -PORT = 12366 - -[transport-tcp] -TIMEOUT = 300 s -PORT = 12368 - -[TESTING] -WEAKRANDOM = YES - -[gnunetd] -HOSTKEY = $SERVICEHOME/.hostkey - -[dns] -AUTOSTART = NO - -[nse] -AUTOSTART = NO - -[namestore] -AUTOSTART = NO - -[consensus] -AUTOSTART = NO diff --git a/src/mesh/test_mesh2_small.c b/src/mesh/test_mesh2_small.c deleted file mode 100644 index 0a184d56f0..0000000000 --- a/src/mesh/test_mesh2_small.c +++ /dev/null @@ -1,833 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2011 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ -/** - * @file mesh/test_mesh2_small.c - * - * @brief Test for the mesh service: retransmission of traffic. - */ -#include <stdio.h> -#include "platform.h" -#include "mesh2_test_lib.h" -#include "gnunet_mesh2_service.h" -#include <gauger.h> - - -/** - * How namy messages to send - */ -#define TOTAL_PACKETS 1000 - -/** - * How long until we give up on connecting the peers? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) - -/** - * Time to wait for stuff that should be rather fast - */ -#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) - -/** - * DIFFERENT TESTS TO RUN - */ -#define SETUP 0 -#define FORWARD 1 -#define SPEED 3 -#define SPEED_ACK 4 -#define SPEED_NOBUF 6 -#define P2P_SIGNAL 10 - -/** - * Which test are we running? - */ -static int test; - -/** - * String with test name - */ -char *test_name; - -/** - * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic. - */ -static int test_backwards = GNUNET_NO; - -/** - * How many events have happened - */ -static int ok; - - /** - * Each peer is supposed to generate the following callbacks: - * 1 incoming tunnel (@dest) - * 1 connected peer (@orig) - * 1 received data packet (@dest) - * 1 received data packet (@orig) - * 1 received tunnel destroy (@dest) - * _________________________________ - * 5 x ok expected per peer - */ -int ok_goal; - - -/** - * Size of each test packet - */ -size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t); - -/** - * Operation to get peer ids. - */ -struct GNUNET_TESTBED_Operation *t_op[2]; - -/** - * Peer ids. - */ -struct GNUNET_PeerIdentity *p_id[2]; - -/** - * Peer ids counter. - */ -unsigned int p_ids; - -/** - * Is the setup initialized? - */ -static int initialized; - -/** - * Peers that have responded - */ -static int peers_responded; - -/** - * Number of payload packes sent - */ -static int data_sent; - -/** - * Number of payload packets received - */ -static int data_received; - -/** - * Number of payload packed explicitly (app level) acknowledged - */ -static int data_ack; - -/** - * Total number of currently running peers. - */ -static unsigned long long peers_running; - -/** - * Test context (to shut down). - */ -struct GNUNET_MESH_TEST_Context *test_ctx; - -/** - * Task called to disconnect peers. - */ -static GNUNET_SCHEDULER_TaskIdentifier disconnect_task; - -/** - * Task To perform tests - */ -static GNUNET_SCHEDULER_TaskIdentifier test_task; - -/** - * Task called to shutdown test. - */ -static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; - -/** - * Mesh handle for the root peer - */ -static struct GNUNET_MESH_Handle *h1; - -/** - * Mesh handle for the first leaf peer - */ -static struct GNUNET_MESH_Handle *h2; - -/** - * Tunnel handle for the root peer - */ -static struct GNUNET_MESH_Tunnel *t; - -/** - * Tunnel handle for the first leaf peer - */ -static struct GNUNET_MESH_Tunnel *incoming_t; - -/** - * Time we started the data transmission (after tunnel has been established - * and initilized). - */ -static struct GNUNET_TIME_Absolute start_time; - - -/** - * Show the results of the test (banwidth acheived) and log them to GAUGER - */ -static void -show_end_data (void) -{ - static struct GNUNET_TIME_Absolute end_time; - static struct GNUNET_TIME_Relative total_time; - - end_time = GNUNET_TIME_absolute_get(); - total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time); - FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name); - FPRINTF (stderr, "Test time %llu ms\n", - (unsigned long long) total_time.rel_value); - FPRINTF (stderr, "Test bandwidth: %f kb/s\n", - 4 * TOTAL_PACKETS * 1.0 / total_time.rel_value); // 4bytes * ms - FPRINTF (stderr, "Test throughput: %f packets/s\n\n", - TOTAL_PACKETS * 1000.0 / total_time.rel_value); // packets * ms - GAUGER ("MESH", test_name, - TOTAL_PACKETS * 1000.0 / total_time.rel_value, - "packets/s"); -} - - -/** - * Shut down peergroup, clean up. - * - * @param cls Closure (unused). - * @param tc Task Context. - */ -static void -shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); - shutdown_handle = GNUNET_SCHEDULER_NO_TASK; -} - - -/** - * Disconnect from mesh services af all peers, call shutdown. - * - * @param cls Closure (unused). - * @param tc Task Context. - */ -static void -disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - long line = (long) cls; - unsigned int i; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "disconnecting mesh service of peers, called from line %ld\n", - line); - disconnect_task = GNUNET_SCHEDULER_NO_TASK; - for (i = 0; i < 2; i++) - { - GNUNET_TESTBED_operation_done (t_op[i]); - } - if (NULL != t) - { - GNUNET_MESH_tunnel_destroy (t); - t = NULL; - } - if (NULL != incoming_t) - { - GNUNET_MESH_tunnel_destroy (incoming_t); - incoming_t = NULL; - } - GNUNET_MESH_TEST_cleanup (test_ctx); - if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle) - { - GNUNET_SCHEDULER_cancel (shutdown_handle); - } - shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); -} - - -/** - * Abort test: schedule disconnect and shutdown immediately - * - * @param line Line in the code the abort is requested from (__LINE__). - */ -static void -abort_test (long line) -{ - if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) - { - GNUNET_SCHEDULER_cancel (disconnect_task); - disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, - (void *) line); - } -} - -/** - * Transmit ready callback. - * - * @param cls Closure (message type). - * @param size Size of the tranmist buffer. - * @param buf Pointer to the beginning of the buffer. - * - * @return Number of bytes written to buf. - */ -static size_t -tmt_rdy (void *cls, size_t size, void *buf); - - -/** - * Task to schedule a new data transmission. - * - * @param cls Closure (peer #). - * @param tc Task Context. - */ -static void -data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - struct GNUNET_MESH_TransmitHandle *th; - struct GNUNET_MESH_Tunnel *tunnel; - - if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) - return; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n"); - if (GNUNET_YES == test_backwards) - { - tunnel = incoming_t; - } - else - { - tunnel = t; - } - th = GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - size_payload, &tmt_rdy, (void *) 1L); - if (NULL == th) - { - unsigned long i = (unsigned long) cls; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retransmission\n"); - if (0 == i) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, " in 1 ms\n"); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, - &data_task, (void *)1UL); - } - else - { - i++; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "in %u ms\n", i); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply( - GNUNET_TIME_UNIT_MILLISECONDS, - i), - &data_task, (void *)i); - } - } -} - - -/** - * Transmit ready callback - * - * @param cls Closure (message type). - * @param size Size of the buffer we have. - * @param buf Buffer to copy data to. - */ -size_t -tmt_rdy (void *cls, size_t size, void *buf) -{ - struct GNUNET_MessageHeader *msg = buf; - uint32_t *data; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " tmt_rdy called\n"); - if (size < size_payload || NULL == buf) - { - GNUNET_break (0); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "size %u, buf %p, data_sent %u, data_received %u\n", - size, - buf, - data_sent, - data_received); - return 0; - } - msg->size = htons (size); - msg->type = htons ((long) cls); - data = (uint32_t *) &msg[1]; - *data = htonl (data_sent); - if (SPEED == test && GNUNET_YES == initialized) - { - data_sent++; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Sent packet %d\n", data_sent); - if (data_sent < TOTAL_PACKETS) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Scheduling packet %d\n", data_sent + 1); - GNUNET_SCHEDULER_add_now(&data_task, NULL); - } - } - return size_payload; -} - - -/** - * Function is called whenever a message is received. - * - * @param cls closure (set from GNUNET_MESH_connect) - * @param tunnel connection to the other end - * @param tunnel_ctx place to store local state associated with the tunnel - * @param message the actual message - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -int -data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_MessageHeader *message) -{ - long client = (long) cls; - long expected_target_client; - uint32_t *data; - - ok++; - - GNUNET_MESH_receive_done (tunnel); - - if ((ok % 20) == 0) - { - if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) - { - GNUNET_SCHEDULER_cancel (disconnect_task); - disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, - &disconnect_mesh_peers, - (void *) __LINE__); - } - } - - switch (client) - { - case 0L: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n"); - peers_responded++; - break; - case 4L: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Leaf client %li got a message.\n", - client); - client = 4L; - break; - default: - GNUNET_assert (0); - break; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal); - data = (uint32_t *) &message[1]; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload: (%u)\n", ntohl (*data)); - if (SPEED == test && GNUNET_YES == test_backwards) - { - expected_target_client = 0L; - } - else - { - expected_target_client = 4L; - } - - if (GNUNET_NO == initialized) - { - initialized = GNUNET_YES; - start_time = GNUNET_TIME_absolute_get (); - if (SPEED == test) - { - GNUNET_assert (4L == client); - GNUNET_SCHEDULER_add_now (&data_task, NULL); - return GNUNET_OK; - } - } - - if (client == expected_target_client) // Normally 3 or 4 - { - data_received++; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - " received data %u\n", data_received); - if (SPEED != test || (ok_goal - 2) == ok) - { - GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - size_payload, &tmt_rdy, (void *) 1L); - return GNUNET_OK; - } - else - { - if (data_received < TOTAL_PACKETS) - return GNUNET_OK; - } - } - else // Normally 0 - { - if (test == SPEED_ACK || test == SPEED) - { - data_ack++; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - " received ack %u\n", data_ack); - GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - size_payload, &tmt_rdy, (void *) 1L); - if (data_ack < TOTAL_PACKETS && SPEED != test) - return GNUNET_OK; - if (ok == 2 && SPEED == test) - return GNUNET_OK; - show_end_data(); - } - if (test == P2P_SIGNAL) - { - GNUNET_MESH_tunnel_destroy (incoming_t); - incoming_t = NULL; - } - else - { - GNUNET_MESH_tunnel_destroy (t); - t = NULL; - } - } - - if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) - { - GNUNET_SCHEDULER_cancel (disconnect_task); - disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, - &disconnect_mesh_peers, - (void *) __LINE__); - } - - return GNUNET_OK; -} - - -/** - * Handlers, for diverse services - */ -static struct GNUNET_MESH_MessageHandler handlers[] = { - {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)}, - {NULL, 0, 0} -}; - - -/** - * Method called whenever another peer has added us to a tunnel - * the other peer initiated. - * - * @param cls Closure. - * @param tunnel New handle to the tunnel. - * @param initiator Peer that started the tunnel. - * @param port Port this tunnels is connected to. - * @return Initial tunnel context for the tunnel - * (can be NULL -- that's not an error). - */ -static void * -incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *initiator, - uint32_t port) -{ - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Incoming tunnel from %s to peer %d\n", - GNUNET_i2s (initiator), (long) cls); - ok++; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); - if ((long) cls == 4L) - incoming_t = tunnel; - else - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Incoming tunnel for unknown client %lu\n", (long) cls); - GNUNET_break(0); - } - if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) - { - GNUNET_SCHEDULER_cancel (disconnect_task); - disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, - &disconnect_mesh_peers, - (void *) __LINE__); - } - - return NULL; -} - -/** - * Function called whenever an inbound tunnel is destroyed. Should clean up - * any associated state. - * - * @param cls closure (set from GNUNET_MESH_connect) - * @param tunnel connection to the other end (henceforth invalid) - * @param tunnel_ctx place where local state associated - * with the tunnel is stored - */ -static void -tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, - void *tunnel_ctx) -{ - long i = (long) cls; - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Incoming tunnel disconnected at peer %d\n", - i); - if (4L == i) - { - ok++; - incoming_t = NULL; - } - else if (0L == i && P2P_SIGNAL == test) - { - ok ++; - } - else - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Unknown peer! %d\n", i); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); - - if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) - { - GNUNET_SCHEDULER_cancel (disconnect_task); - disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, - (void *) __LINE__); - } - - return; -} - - -/** - * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE MESH SERVICES. - * - * Testcase continues when the root receives confirmation of connected peers, - * on callback funtion ch. - * - * @param cls Closure (unsued). - * @param tc Task Context. - */ -static void -do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "add peer 2\n"); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "schedule timeout in TIMEOUT\n"); - if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) - { - GNUNET_SCHEDULER_cancel (disconnect_task); - } - t = GNUNET_MESH_tunnel_create (h1, NULL, p_id[1], 1); - if (SPEED_NOBUF == test) - { - GNUNET_MESH_tunnel_buffer(t, GNUNET_NO); - test = SPEED; - } - - disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, - &disconnect_mesh_peers, - (void *) __LINE__); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending data initializer...\n"); - peers_responded = 0; - data_ack = 0; - data_received = 0; - data_sent = 0; - GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - size_payload, &tmt_rdy, (void *) 1L); -} - -/** - * Callback to be called when the requested peer information is available - * - * @param cls the closure from GNUNET_TESTBED_peer_get_information() - * @param op the operation this callback corresponds to - * @param pinfo the result; will be NULL if the operation has failed - * @param emsg error message if the operation has failed; - * NULL if the operation is successfull - */ -static void -pi_cb (void *cls, - struct GNUNET_TESTBED_Operation *op, - const struct GNUNET_TESTBED_PeerInformation *pinfo, - const char *emsg) -{ - long i = (long) cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i); - - if (NULL == pinfo || NULL != emsg) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); - abort_test (__LINE__); - return; - } - p_id[i] = pinfo->result.id; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i])); - p_ids++; - if (p_ids < 2) - return; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n"); - test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, - &do_test, NULL); -} - -/** - * test main: start test when all peers are connected - * - * @param cls Closure. - * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end. - * @param num_peers Number of peers that are running. - * @param peers Array of peers. - * @param meshes Handle to each of the MESHs of the peers. - */ -static void -tmain (void *cls, - struct GNUNET_MESH_TEST_Context *ctx, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers, - struct GNUNET_MESH_Handle **meshes) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n"); - ok = 0; - test_ctx = ctx; - peers_running = num_peers; - h1 = meshes[0]; - h2 = meshes[num_peers - 1]; - disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, - &disconnect_mesh_peers, - (void *) __LINE__); - shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, - &shutdown_task, NULL); - t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], - GNUNET_TESTBED_PIT_IDENTITY, - &pi_cb, (void *) 0L); - t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], - GNUNET_TESTBED_PIT_IDENTITY, - &pi_cb, (void *) 1L); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n"); -} - - -/** - * Main: start test - */ -int -main (int argc, char *argv[]) -{ - initialized = GNUNET_NO; - uint32_t ports[2]; - - GNUNET_log_setup ("test", "DEBUG", NULL); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n"); - if (strstr (argv[0], "_small_forward") != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n"); - test = FORWARD; - test_name = "unicast2"; - ok_goal = 4; - } - else if (strstr (argv[0], "_small_signal") != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n"); - test = P2P_SIGNAL; - test_name = "signal2"; - ok_goal = 4; - } - else if (strstr (argv[0], "_small_speed_ack") != NULL) - { - /* Each peer is supposed to generate the following callbacks: - * 1 incoming tunnel (@dest) - * TOTAL_PACKETS received data packet (@dest) - * TOTAL_PACKETS received data packet (@orig) - * 1 received tunnel destroy (@dest) - * _________________________________ - * 5 x ok expected per peer - */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); - test = SPEED_ACK; - test_name = "speed2 ack"; - ok_goal = TOTAL_PACKETS * 2 + 2; - } - else if (strstr (argv[0], "_small_speed") != NULL) - { - /* Each peer is supposed to generate the following callbacks: - * 1 incoming tunnel (@dest) - * 1 initial packet (@dest) - * TOTAL_PACKETS received data packet (@dest) - * 1 received data packet (@orig) - * 1 received tunnel destroy (@dest) - * _________________________________ - */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); - ok_goal = TOTAL_PACKETS + 4; - if (strstr (argv[0], "_nobuf") != NULL) - { - test = SPEED_NOBUF; - test_name = "speed2 nobuf"; - } - else - { - test = SPEED; - test_name = "speed2"; - } - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n"); - test = SETUP; - ok_goal = 0; - } - - if (strstr (argv[0], "backwards") != NULL) - { - char *aux; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n"); - test_backwards = GNUNET_YES; - aux = GNUNET_malloc (32); - sprintf (aux, "backwards %s", test_name); - test_name = aux; - } - - p_ids = 0; - ports[0] = 1; - ports[1] = 0; - GNUNET_MESH_TEST_run ("test_mesh2_small", - "test_mesh2.conf", - 5, - &tmain, - NULL, /* tmain cls */ - &incoming_tunnel, - &tunnel_cleaner, - handlers, - ports); - - if (ok_goal > ok) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "FAILED! (%d/%d)\n", ok, ok_goal); - return 1; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n"); - return 0; -} - -/* end of test_mesh_small.c */ - diff --git a/src/mesh/test_mesh_2dtorus.c b/src/mesh/test_mesh_2dtorus.c deleted file mode 100644 index 4b6affcc8e..0000000000 --- a/src/mesh/test_mesh_2dtorus.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2011 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ -/** - * @file mesh/test_mesh_2dtorus.c - * - * @brief Test for creating a 2dtorus. - */ -#include "platform.h" -#include "mesh_test_lib.h" -#include "gnunet_mesh_service.h" - -#define REMOVE_DIR GNUNET_YES - -/** - * How long until we give up on connecting the peers? - */ -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500) - -/** - * Time to wait for stuff that should be rather fast - */ -#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) - - -/** - * How many events have happened - */ -static int ok; - -/** - * Total number of currently running peers. - */ -static unsigned long long peers_running; - -/** - * Task to time out. - */ -static GNUNET_SCHEDULER_TaskIdentifier timeout_task; - - -static void -shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down test\n"); -} - - -/** - * test main: start test when all peers are connected - * - * @param cls Closure. - * @param ctx Argument to give to GNUNET_MESH_TEST_cleanup on test end. - * @param num_peers Number of peers that are running. - * @param peers Array of peers. - * @param meshes Handle to each of the MESHs of the peers. - */ -static void -tmain (void *cls, - struct GNUNET_MESH_TEST_Context *ctx, - unsigned int num_peers, - struct GNUNET_TESTBED_Peer **peers, - struct GNUNET_MESH_Handle **meshes) -{ - if (16 != num_peers) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "running peers mismatch, aborting test!\n"); - ok--; - GNUNET_MESH_TEST_cleanup (ctx); - return; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "testbed started successfully with ?? connections\n"); - peers_running = num_peers; - timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, - &shutdown_task, ctx); - ok = GNUNET_OK; - GNUNET_MESH_TEST_cleanup (ctx); -} - - -/** - * Main: start test - */ -int -main (int argc, char *argv[]) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Start\n"); - ok = GNUNET_SYSERR; - - GNUNET_MESH_TEST_run ("test_mesh_2dtorus", - "test_mesh_2dtorus.conf", - 16, - &tmain, - NULL, - NULL, - NULL, - NULL, - NULL - ); - - if (GNUNET_OK != ok) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "FAILED!\n"); - return 1; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n"); - return 0; -} - -/* end of test_mesh_2dtorus.c */ diff --git a/src/mesh/test_mesh_2dtorus.conf b/src/mesh/test_mesh_2dtorus.conf deleted file mode 100644 index 708ab0a504..0000000000 --- a/src/mesh/test_mesh_2dtorus.conf +++ /dev/null @@ -1,71 +0,0 @@ -[PATHS] -SERVICEHOME = /tmp/test_mesh_small/ - -[mesh] -PORT = 10005 -ACCEPT_FROM = 127.0.0.1; -HOSTNAME = localhost -DHT_REPLICATION_LEVEL = 10 -# PREFIX = valgrind --leak-check=full -# PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args - -[testing] -WEAKRANDOM = YES - -[testbed] -NUM_PEERS = 16 -OVERLAY_TOPOLOGY = 2D_TORUS - -[arm] -PORT = 10010 -DEFAULTSERVICES = core dht mesh - -[statistics] -AUTOSTART = YES -PORT = 10000 - -[dht] -AUTOSTART = YES -ACCEPT_FROM6 = ::1; -ACCEPT_FROM = 127.0.0.1; -HOSTNAME = localhost -PORT = 10001 -DISABLE_TRY_CONNECT = YES - -[nse] -WORKBITS = 0 - -[dns] -AUTOSTART = NO -PORT = 10011 - -[vpn] -AUTOSTART = NO -PORT = 10012 - -[transport] -PORT = 10002 -AUTOSTART = YES - -[nat] -DISABLEV6 = YES -BINDTO = 127.0.0.1 -ENABLE_UPNP = NO -BEHIND_NAT = NO -ALLOW_NAT = NO -INTERNAL_ADDRESS = 127.0.0.1 -EXTERNAL_ADDRESS = 127.0.0.1 -RETURN_LOCAL_ADDRESSES = YES -USE_LOCALADDR = YES - -[ats] -WAN_QUOTA_IN = 1 GB -WAN_QUOTA_OUT = 1 GB - -[core] -AUTOSTART = YES -PORT = 10003 - -[peerinfo] -AUTOSTART = YES -PORT = 10004 diff --git a/src/mesh/test_mesh_api.c b/src/mesh/test_mesh_api.c deleted file mode 100644 index 349ec80f0e..0000000000 --- a/src/mesh/test_mesh_api.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2011 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file mesh/test_mesh_api.c - * @brief test mesh api: dummy test of callbacks - * @author Bartlomiej Polot - */ -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testing_lib.h" -#include "gnunet_dht_service.h" -#include "gnunet_mesh_service.h" - -static struct GNUNET_MESH_Handle *mesh; - -static struct GNUNET_MESH_Tunnel *t; - -static int result; - -static GNUNET_SCHEDULER_TaskIdentifier abort_task; - - -/** - * Function is called whenever a message is received. - * - * @param cls closure (set from GNUNET_MESH_connect) - * @param tunnel connection to the other end - * @param tunnel_ctx place to store local state associated with the tunnel - * @param sender who sent the message - * @param message the actual message - * @param atsi performance data for the connection - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi) -{ - return GNUNET_OK; -} - - -static struct GNUNET_MESH_MessageHandler handlers[] = { - { &callback, 1, 0 }, - { NULL, 0, 0 } -}; - - -static void -do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - if (NULL != t) - { - GNUNET_MESH_tunnel_destroy (t); - } - if (0 != abort_task) - { - GNUNET_SCHEDULER_cancel (abort_task); - } - if (NULL != mesh) - { - GNUNET_MESH_disconnect (mesh); - } -} - - -static void -do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - result = GNUNET_SYSERR; - abort_task = 0; - do_shutdown (cls, tc); -} - - -static void -run (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Peer *peer) -{ - static const GNUNET_MESH_ApplicationType app[] = - { 1, 2, 3, 4, 5, 6, 7, 8, 0 }; - - mesh = GNUNET_MESH_connect (cfg, NULL, NULL, NULL, handlers, app); - if (NULL == mesh) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: Couldn't connect to mesh :(\n"); - result = GNUNET_SYSERR; - return; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: YAY! CONNECTED TO MESH :D\n"); - } - t = GNUNET_MESH_tunnel_create (mesh, NULL, NULL, NULL, NULL); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 5), &do_shutdown, - NULL); - abort_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort, - NULL); -} - - -int -main (int argc, char *argv[]) -{ - result = GNUNET_OK; - if (0 != GNUNET_TESTING_peer_run ("test-mesh-api", - "test_mesh.conf", - &run, NULL)) - return 1; - return (result == GNUNET_OK) ? 0 : 1; -} - -/* end of test_mesh_api.c */ - diff --git a/src/mesh/test_mesh2_local.c b/src/mesh/test_mesh_local.c index 483135afa6..058f02af6a 100644 --- a/src/mesh/test_mesh2_local.c +++ b/src/mesh/test_mesh_local.c @@ -19,8 +19,8 @@ */ /** - * @file mesh/test_mesh2_local.c - * @brief test mesh2 local: test of mesh2 tunnels with just one peer + * @file mesh/test_mesh_local.c + * @brief test mesh local: test of mesh tunnels with just one peer * @author Bartlomiej Polot */ @@ -28,7 +28,7 @@ #include "gnunet_util_lib.h" #include "gnunet_dht_service.h" #include "gnunet_testing_lib.h" -#include "gnunet_mesh2_service.h" +#include "gnunet_mesh_service.h" struct GNUNET_TESTING_Peer *me; @@ -286,7 +286,7 @@ int main (int argc, char *argv[]) { if (0 != GNUNET_TESTING_peer_run ("test-mesh-local", - "test_mesh2.conf", + "test_mesh.conf", &run, NULL)) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n"); diff --git a/src/mesh/test_mesh_local_1.c b/src/mesh/test_mesh_local_1.c deleted file mode 100644 index 4f40688f57..0000000000 --- a/src/mesh/test_mesh_local_1.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2011 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file mesh/test_mesh_local_1.c - * @brief test mesh local: test of tunnels with just one peer - * @author Bartlomiej Polot - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_dht_service.h" -#include "gnunet_testing_lib.h" -#include "gnunet_mesh_service.h" - - -static struct GNUNET_MESH_Handle *mesh_peer_1; - -static struct GNUNET_MESH_Handle *mesh_peer_2; - -static struct GNUNET_MESH_Tunnel *t; - -static unsigned int one = 1; - -static unsigned int two = 2; - -static int result = GNUNET_OK; - -static GNUNET_SCHEDULER_TaskIdentifier abort_task; - -static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; - - -/** - * Shutdown nicely - */ -static void -do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: shutdown\n"); - if (0 != abort_task) - { - GNUNET_SCHEDULER_cancel (abort_task); - } - if (NULL != t) - { - GNUNET_MESH_tunnel_destroy(t); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D1\n"); - if (NULL != mesh_peer_1) - { - GNUNET_MESH_disconnect (mesh_peer_1); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D2\n"); - if (NULL != mesh_peer_2) - { - GNUNET_MESH_disconnect (mesh_peer_2); - } -} - - -/** - * Something went wrong and timed out. Kill everything and set error flag - */ -static void -do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n"); - result = GNUNET_SYSERR; - abort_task = 0; - if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) - { - GNUNET_SCHEDULER_cancel (shutdown_task); - shutdown_task = GNUNET_SCHEDULER_NO_TASK; - } - do_shutdown (cls, tc); -} - - -/** - * Function is called whenever a message is received. - * - * @param cls closure (set from GNUNET_MESH_connect) - * @param tunnel connection to the other end - * @param tunnel_ctx place to store local state associated with the tunnel - * @param sender who sent the message - * @param message the actual message - * @param atsi performance data for the connection - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Data callback\n"); - if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) - GNUNET_SCHEDULER_cancel (shutdown_task); - shutdown_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 2), &do_shutdown, - NULL); - return GNUNET_OK; -} - - -/** - * Method called whenever another peer has added us to a tunnel - * the other peer initiated. - * - * @param cls closure - * @param tunnel new handle to the tunnel - * @param initiator peer that started the tunnel - * @param atsi performance information for the tunnel - * @return initial tunnel context for the tunnel (can be NULL -- that's not an error) - */ -static void * -inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *initiator, - const struct GNUNET_ATS_Information *atsi) -{ - unsigned int id = *(unsigned int *) cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: received incoming tunnel\n"); - if (id != 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "test: received incoming tunnel on peer 2\n"); - result = GNUNET_SYSERR; - } - return NULL; -} - - -/** - * Function called whenever an inbound tunnel is destroyed. Should clean up - * any associated state. - * - * @param cls closure (set from GNUNET_MESH_connect) - * @param tunnel connection to the other end (henceforth invalid) - * @param tunnel_ctx place where local state associated - * with the tunnel is stored - */ -static void -inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, - void *tunnel_ctx) -{ - unsigned int id = *(unsigned int *) cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: incoming tunnel closed\n"); - if (id != 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "test: received closing tunnel on peer 2\n"); - result = GNUNET_SYSERR; - } -} - - -/** - * Method called whenever a peer has connected to the tunnel. - * - * @param cls closure - * @param peer peer identity the tunnel stopped working with - */ -static void -peer_conected (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_ATS_Information *atsi) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer connected\n"); - if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) - GNUNET_SCHEDULER_cancel(shutdown_task); - shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, - &do_shutdown, NULL); -} - - -/** - * Method called whenever a peer has connected to the tunnel. - * - * @param cls closure - * @param peer peer identity the tunnel was created to, NULL on timeout - * @param atsi performance data for the connection - */ -static void -peer_disconnected (void *cls, const struct GNUNET_PeerIdentity *peer) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer disconnected\n"); -} - - -/** - * Handler array for traffic received on peer1 - */ -static struct GNUNET_MESH_MessageHandler handlers1[] = { - {&data_callback, 1, 0}, - {NULL, 0, 0} -}; - - -/** - * Handler array for traffic received on peer2 (none expected) - */ -static struct GNUNET_MESH_MessageHandler handlers2[] = { {NULL, 0, 0} }; - - -/** - * Start looking for a peer by type - */ -static void -do_find (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: CONNECT BY TYPE\n"); - GNUNET_MESH_peer_request_connect_by_type (t, 1); -} - - -/** - * Initialize framework and start test - */ -static void -run (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Peer *peer) -{ - static const GNUNET_MESH_ApplicationType app1[] = { 1, 0 }; - static const GNUNET_MESH_ApplicationType app2[] = { 0 }; - - abort_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort, - NULL); - mesh_peer_1 = GNUNET_MESH_connect (cfg, /* configuration */ - (void *) &one, /* cls */ - &inbound_tunnel, /* inbound new hndlr */ - &inbound_end, /* inbound end hndlr */ - handlers1, /* traffic handlers */ - app1); /* apps offered */ - - mesh_peer_2 = GNUNET_MESH_connect (cfg, /* configuration */ - (void *) &two, /* cls */ - &inbound_tunnel, /* inbound new hndlr */ - &inbound_end, /* inbound end hndlr */ - handlers2, /* traffic handlers */ - app2); /* apps offered */ - if (NULL == mesh_peer_1 || NULL == mesh_peer_2) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: Couldn't connect to mesh :(\n"); - result = GNUNET_SYSERR; - return; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: YAY! CONNECTED TO MESH :D\n"); - } - t = GNUNET_MESH_tunnel_create (mesh_peer_2, NULL, &peer_conected, - &peer_disconnected, (void *) &two); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_find, NULL); -} - - -/** - * Main - */ -int -main (int argc, char *argv[]) -{ - if (0 != GNUNET_TESTING_peer_run ("test-mesh-local-1", - "test_mesh.conf", - &run, NULL)) - return 1; - return (result == GNUNET_OK) ? 0 : 1; -} - -/* end of test_mesh_local_1.c */ diff --git a/src/mesh/test_mesh_local_2.c b/src/mesh/test_mesh_local_2.c deleted file mode 100644 index 935c3b2eb2..0000000000 --- a/src/mesh/test_mesh_local_2.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2011 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file mesh/test_mesh_local.c - * @brief test mesh local: test of tunnels with just one peer - * @author Bartlomiej Polot - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_testing_lib.h" -#include "gnunet_dht_service.h" -#include "gnunet_mesh_service.h" - -static struct GNUNET_MESH_Handle *mesh_peer_1; - -static struct GNUNET_MESH_Handle *mesh_peer_2; - -static struct GNUNET_MESH_Tunnel *t; - -static unsigned int one = 1; - -static unsigned int two = 2; - -static int result = GNUNET_OK; - -static GNUNET_SCHEDULER_TaskIdentifier abort_task; - -static GNUNET_SCHEDULER_TaskIdentifier test_task; - - -/** - * Shutdown nicely - */ -static void -do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: shutdown\n"); - if (0 != abort_task) - { - GNUNET_SCHEDULER_cancel (abort_task); - } - if (NULL != t) - { - GNUNET_MESH_tunnel_destroy(t); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D1\n"); - if (NULL != mesh_peer_1) - { - GNUNET_MESH_disconnect (mesh_peer_1); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: D2\n"); - if (NULL != mesh_peer_2) - { - GNUNET_MESH_disconnect (mesh_peer_2); - } -} - - -/** - * Something went wrong and timed out. Kill everything and set error flag - */ -static void -do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: ABORT\n"); - if (0 != test_task) - { - GNUNET_SCHEDULER_cancel (test_task); - } - result = GNUNET_SYSERR; - abort_task = 0; - do_shutdown (cls, tc); -} - - -/** - * Function is called whenever a message is received. - * - * @param cls closure (set from GNUNET_MESH_connect) - * @param tunnel connection to the other end - * @param tunnel_ctx place to store local state associated with the tunnel - * @param sender who sent the message - * @param message the actual message - * @param atsi performance data for the connection - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Data callback\n"); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 2), &do_shutdown, - NULL); - return GNUNET_OK; -} - - -/** - * Method called whenever another peer has added us to a tunnel - * the other peer initiated. - * - * @param cls closure - * @param tunnel new handle to the tunnel - * @param initiator peer that started the tunnel - * @param atsi performance information for the tunnel - * @return initial tunnel context for the tunnel (can be NULL -- that's not an error) - */ -static void * -inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *initiator, - const struct GNUNET_ATS_Information *atsi) -{ - unsigned int id = *(unsigned int *) cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: received incoming tunnel\n"); - if (id != 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "test: received incoming tunnel on peer 2\n"); - result = GNUNET_SYSERR; - } - return NULL; -} - - -/** - * Function called whenever an inbound tunnel is destroyed. Should clean up - * any associated state. - * - * @param cls closure (set from GNUNET_MESH_connect) - * @param tunnel connection to the other end (henceforth invalid) - * @param tunnel_ctx place where local state associated - * with the tunnel is stored - */ -static void -inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, - void *tunnel_ctx) -{ - unsigned int id = *(unsigned int *) cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: incoming tunnel closed\n"); - if (id != 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "test: received closing tunnel on peer 2\n"); - result = GNUNET_SYSERR; - } -} - - -/** - * Method called whenever a peer has disconnected from the tunnel. - * - * @param cls closure - * @param peer peer identity the tunnel stopped working with - */ -static void -peer_conected (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_ATS_Information *atsi) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer connected\n"); - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, NULL); -} - - -/** - * Method called whenever a peer has connected to the tunnel. - * - * @param cls closure - * @param peer peer identity the tunnel was created to, NULL on timeout - * @param atsi performance data for the connection - */ -static void -peer_disconnected (void *cls, const struct GNUNET_PeerIdentity *peer) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: peer disconnected\n"); -} - - -/** - * Handler array for traffic received on peer1 - */ -static struct GNUNET_MESH_MessageHandler handlers1[] = { - {&data_callback, 1, 0}, - {NULL, 0, 0} -}; - - -/** - * Handler array for traffic received on peer2 (none expected) - */ -static struct GNUNET_MESH_MessageHandler handlers2[] = { {NULL, 0, 0} }; - - -/** - * Start looking for a peer by type - */ -static void -do_connect_peer_1 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - const struct GNUNET_CONFIGURATION_Handle *cfg = cls; - static const GNUNET_MESH_ApplicationType app1[] = { 1, 0 }; - - test_task = GNUNET_SCHEDULER_NO_TASK; - mesh_peer_1 = GNUNET_MESH_connect (cfg, /* configuration */ - (void *) &one, /* cls */ - &inbound_tunnel, /* inbound new hndlr */ - &inbound_end, /* inbound end hndlr */ - handlers1, /* traffic handlers */ - app1); /* apps offered */ -} - - -/** - * Initialize framework and start test - */ -static void -run (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Peer *peer) -{ - static const GNUNET_MESH_ApplicationType app2[] = { 0 }; - - abort_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort, - NULL); - mesh_peer_2 = GNUNET_MESH_connect (cfg, /* configuration */ - (void *) &two, /* cls */ - &inbound_tunnel, /* inbound new hndlr */ - &inbound_end, /* inbound end hndlr */ - handlers2, /* traffic handlers */ - app2); /* apps offered */ - if (NULL == mesh_peer_2) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: Couldn't connect to mesh :(\n"); - result = GNUNET_SYSERR; - return; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: YAY! CONNECTED TO MESH :D\n"); - } - t = GNUNET_MESH_tunnel_create (mesh_peer_2, NULL, &peer_conected, - &peer_disconnected, (void *) &two); - GNUNET_MESH_peer_request_connect_by_type (t, 1); - test_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 5), - &do_connect_peer_1, (void*) cfg); -} - - -/** - * Main - */ -int -main (int argc, char *argv[]) -{ - if (0 != GNUNET_TESTING_peer_run ("test-mesh-local-2", - "test_mesh.conf", - &run, NULL)) - return 1; - return (result == GNUNET_OK) ? 0 : 1; -} - -/* end of test_mesh_local_2.c */ diff --git a/src/mesh/test_mesh_local_traffic.c b/src/mesh/test_mesh_local_traffic.c deleted file mode 100644 index cd54ea8eb3..0000000000 --- a/src/mesh/test_mesh_local_traffic.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2012 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file mesh/test_mesh_local_traffic.c - * @brief test mesh local traffic: test of tunnels with just one peer - * @author Bartlomiej Polot - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_mesh_service.h" -#include "gnunet_testing_lib.h" -#include <gauger.h> - -#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) - -#define TARGET 1000 - -/** - * DIFFERENT TESTS TO RUN - */ -#define FWD 0 -#define BCK 1 -#define BOTH 2 - - -GNUNET_NETWORK_STRUCT_BEGIN - -struct test_traffic_message -{ - struct GNUNET_MessageHeader header; - uint32_t data GNUNET_PACKED; -}; - -GNUNET_NETWORK_STRUCT_END - - -/** Which test to run, based on executable name */ -static int test; - -static int started; - -/** How many packets to send from root to leaf */ -static unsigned int to_send_fwd; - -/** How many packets to send from leaf to root */ -static unsigned int to_send_bck; - -static unsigned int sent_fwd = 0; - -static unsigned int got_fwd = 0; - -static unsigned int sent_bck = 0; - -static unsigned int got_bck = 0; - -static struct GNUNET_MESH_Handle *mesh_peer_1; - -static struct GNUNET_MESH_Handle *mesh_peer_2; - -static struct GNUNET_MESH_Tunnel *t_fwd; - -static struct GNUNET_MESH_Tunnel *t_bck; - -static unsigned int one = 1; - -static unsigned int two = 2; - -static int result = GNUNET_SYSERR; - -static GNUNET_SCHEDULER_TaskIdentifier abort_task; - -static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; - -static struct GNUNET_TIME_Absolute start_time; - -static struct GNUNET_TIME_Absolute end_time; - -static struct GNUNET_PeerIdentity peer_id; - - -/** - * Shutdown nicely - */ -static void -do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n"); - if (0 != abort_task) - { - GNUNET_SCHEDULER_cancel (abort_task); - } - if (NULL != t_fwd) - { - GNUNET_MESH_tunnel_destroy(t_fwd); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "D1\n"); - if (NULL != mesh_peer_1) - { - GNUNET_MESH_disconnect (mesh_peer_1); - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "D2\n"); - if (NULL != mesh_peer_2) - { - GNUNET_MESH_disconnect (mesh_peer_2); - } -} - - -/** - * Something went wrong and timed out. Kill everything and set error flag - */ -static void -do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "ABORT\n"); - result = GNUNET_SYSERR; - abort_task = 0; - if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) - { - GNUNET_SCHEDULER_cancel (shutdown_task); - shutdown_task = GNUNET_SCHEDULER_NO_TASK; - } - do_shutdown (cls, tc); -} - -static void -finish(void) -{ - if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) - GNUNET_SCHEDULER_cancel(shutdown_task); - shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, - &do_shutdown, NULL); -} - - -/** - * Transmit ready callback. - * - * @param cls Closure (peer number of peer sending the data). - * @param size Buffer size. - * @param buf Buffer. - */ -static size_t -tmt_rdy (void *cls, size_t size, void *buf) -{ - unsigned int peer_number = *(unsigned int *) cls; - struct GNUNET_MessageHeader *m = buf; - struct GNUNET_MESH_Tunnel *t; - struct test_traffic_message *msg = buf; - size_t msize = sizeof (struct test_traffic_message); - unsigned int *sent; - unsigned int target; - char *s; - - if (0 == size || NULL == buf) - return 0; - - if (1 == peer_number) - { - sent = &sent_fwd; - target = to_send_fwd; - t = t_fwd; - s = "FWD"; - } - else if (2 == peer_number) - { - sent = &sent_bck; - target = to_send_bck; - t = t_bck; - s = "BCK"; - } - else - GNUNET_abort(); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %s data packet # %4u\n", - s, *sent); - GNUNET_assert (size >= msize); - if (GNUNET_YES == started) - { - (*sent)++; - if (target > *sent) { - GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - &peer_id, msize, &tmt_rdy, cls); - } - } - m->size = htons (msize); - m->type = htons (1); - msg->data = htonl (*sent - 1); - return msize; -} - - -/** - * Function is called whenever a message is received. - * - * @param cls closure (set from GNUNET_MESH_connect) - * @param tunnel connection to the other end - * @param tunnel_ctx place to store local state associated with the tunnel - * @param sender who sent the message - * @param message the actual message - * @param atsi performance data for the connection - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi) -{ - struct test_traffic_message *msg; - unsigned int *peer_number = cls; - unsigned int *got; - unsigned int target; - - if (GNUNET_NO == started) - { - GNUNET_break (2 == *peer_number); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got initial data packet\n"); - started = GNUNET_YES; - start_time = GNUNET_TIME_absolute_get(); - if (FWD != test) // Send leaf -> root - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending first BCK data\n"); - GNUNET_MESH_notify_transmit_ready (t_bck, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - NULL, - sizeof (struct test_traffic_message), - &tmt_rdy, &two); - } - if (BCK != test) // Send root -> leaf - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending first FWD data\n"); - GNUNET_MESH_notify_transmit_ready (t_fwd, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, - &peer_id, - sizeof (struct test_traffic_message), - &tmt_rdy, &one); - } - return GNUNET_OK; - } - - if (*peer_number == 1) - { - got = &got_bck; - target = to_send_bck; - } - else if (*peer_number == 2) - { - got = &got_fwd; - target = to_send_fwd; - } - else - { - GNUNET_abort(); - } - msg = (struct test_traffic_message *) message; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got data packet # %u [%u]\n", - ntohl (msg->data), *got + 1); - (*got)++; - if (target == *got) - { - if (to_send_bck == sent_bck && to_send_fwd == sent_fwd) { - end_time = GNUNET_TIME_absolute_get(); - result = GNUNET_OK; - finish(); - } - return GNUNET_OK; - } - if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) - GNUNET_SCHEDULER_cancel (shutdown_task); - shutdown_task = - GNUNET_SCHEDULER_add_delayed (TIMEOUT, &do_shutdown, - NULL); - return GNUNET_OK; -} - - -/** - * Method called whenever another peer has added us to a tunnel - * the other peer initiated. - * - * @param cls closure - * @param tunnel new handle to the tunnel - * @param initiator peer that started the tunnel - * @param atsi performance information for the tunnel - * @return initial tunnel context for the tunnel (can be NULL -- that's not an error) - */ -static void * -inbound_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *initiator, - const struct GNUNET_ATS_Information *atsi) -{ - unsigned int id = *(unsigned int *) cls; - - t_bck = tunnel; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "received incoming tunnel %p\n", tunnel); - if (id != 2) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "received incoming tunnel on peer 1\n"); - result = GNUNET_SYSERR; - } - return NULL; -} - - -/** - * Function called whenever an inbound tunnel is destroyed. Should clean up - * any associated state. - * - * @param cls closure (set from GNUNET_MESH_connect) - * @param tunnel connection to the other end (henceforth invalid) - * @param tunnel_ctx place where local state associated - * with the tunnel is stored - */ -static void -inbound_end (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, - void *tunnel_ctx) -{ - unsigned int id = *(unsigned int *) cls; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "incoming tunnel closed\n"); - if (id != 2) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "received closing tunnel on peer 1\n"); - result = GNUNET_SYSERR; - } -} - - -/** - * Method called whenever a peer has connected to the tunnel. - * - * @param cls Closure. - * @param peer Peer identity of connected peer. - */ -static void -peer_connected (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_ATS_Information *atsi) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer connected\n"); - peer_id = *peer; - /* Force an inbound tunnel notification on peer 2 */ - GNUNET_MESH_notify_transmit_ready (t_fwd, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, - peer, sizeof (struct test_traffic_message), - &tmt_rdy, &one); -} - - -/** - * Method called whenever a peer has connected to the tunnel. - * - * @param cls closure - * @param peer peer identity the tunnel was created to, NULL on timeout - * @param atsi performance data for the connection - */ -static void -peer_disconnected (void *cls, const struct GNUNET_PeerIdentity *peer) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "peer disconnected\n"); -} - - -/** - * Handler array for traffic received on peer1 - */ -static struct GNUNET_MESH_MessageHandler handlers[] = { - {&data_callback, 1, sizeof (struct test_traffic_message)}, - {NULL, 0, 0} -}; - - -/** - * Handler array for traffic received on peer2 (none expected) - */ -static struct GNUNET_MESH_MessageHandler handlers_null[] = { {NULL, 0, 0} }; - - -/** - * Initialize framework and start test - */ -static void -run (void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_TESTING_Peer *peer) -{ - static const GNUNET_MESH_ApplicationType app1[] = { 0 }; - static const GNUNET_MESH_ApplicationType app2[] = { 1, 0 }; - - abort_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply - (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort, - NULL); - mesh_peer_1 = GNUNET_MESH_connect (cfg, /* configuration */ - (void *) &one, /* cls */ - NULL, /* inbound new hndlr */ - NULL, /* inbound end hndlr */ - /* traffic handlers */ - test == FWD ? handlers_null : handlers, - app1); /* apps offered */ - - mesh_peer_2 = GNUNET_MESH_connect (cfg, /* configuration */ - (void *) &two, /* cls */ - &inbound_tunnel, /* inbound new hndlr */ - &inbound_end, /* inbound end hndlr */ - handlers, /* traffic handlers */ - app2); /* apps offered */ - if (NULL == mesh_peer_1 || NULL == mesh_peer_2) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to mesh\n"); - result = GNUNET_SYSERR; - return; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected to mesh\n"); - } - t_fwd = GNUNET_MESH_tunnel_create (mesh_peer_1, NULL, &peer_connected, - &peer_disconnected, (void *) &two); - GNUNET_MESH_peer_request_connect_by_type (t_fwd, 1); -} - - -/** - * Main - */ -int -main (int argc, char *argv[]) -{ - if (strstr (argv[0], "test_mesh_local_traffic_fwd") != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FWD\n"); - test = FWD; - to_send_fwd = TARGET; - } - else if (strstr (argv[0], "test_mesh_local_traffic_bck") != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BCK\n"); - test = BCK; - to_send_bck = TARGET; - } - else if (strstr (argv[0], "test_mesh_local_traffic_both") != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BOTH\n"); - test = BOTH; - to_send_bck = to_send_fwd = TARGET; - } - else - { - return 1; - } - - if (0 != GNUNET_TESTING_peer_run ("test-mesh-local-traffic", - "test_mesh.conf", - &run, NULL)) - return 1; - if (result != GNUNET_OK) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed.\nFWD expected: %u, Sent: %u, Got: %u\n", - to_send_fwd, sent_fwd, got_fwd); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "BCK expected: %u, Sent: %u, Got: %u\n", - to_send_bck, sent_bck, got_bck); - return 1; - } - else - { - struct GNUNET_TIME_Relative total_time; - unsigned int total_traffic; - char *name; - - total_traffic = BOTH == test ? 2 * TARGET : TARGET; - switch (test) - { - case FWD: - name = "Local traffic Root to Leaf"; - break; - case BCK: - name = "Local traffic Leaf to Root"; - break; - case BOTH: - name = "Local traffic bidirectional"; - break; - default: - GNUNET_assert (0); - } - - total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time); - FPRINTF (stderr, "\nTest time %llu ms\n", - (unsigned long long) total_time.rel_value); - FPRINTF (stderr, "Test payload bandwidth: %f kb/s\n", - total_traffic * 4.0 / total_time.rel_value); // 4bytes * kb/ms - FPRINTF (stderr, "Test throughput: %f packets/s\n\n", - total_traffic * 1000.0 / total_time.rel_value); // 1000 packets * ms - GAUGER ("MESH", - name, - total_traffic * 1000.0 / total_time.rel_value, - "packets/s"); - } - return 0; -} - -/* end of test_mesh_local_traffic.c */ diff --git a/src/mesh/test_mesh_small.c b/src/mesh/test_mesh_small.c index efe939876f..81f9c566c3 100644 --- a/src/mesh/test_mesh_small.c +++ b/src/mesh/test_mesh_small.c @@ -48,11 +48,9 @@ * DIFFERENT TESTS TO RUN */ #define SETUP 0 -#define UNICAST 1 -#define MULTICAST 2 +#define FORWARD 1 #define SPEED 3 #define SPEED_ACK 4 -#define SPEED_MIN 5 #define SPEED_NOBUF 6 #define P2P_SIGNAL 10 @@ -97,12 +95,12 @@ size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t); /** * Operation to get peer ids. */ -struct GNUNET_TESTBED_Operation *t_op[3]; +struct GNUNET_TESTBED_Operation *t_op[2]; /** * Peer ids. */ -struct GNUNET_PeerIdentity *p_id[3]; +struct GNUNET_PeerIdentity *p_id[2]; /** * Peer ids counter. @@ -115,11 +113,6 @@ unsigned int p_ids; static int initialized; /** - * Peers that have been connected - */ -static int peers_in_tunnel; - -/** * Peers that have responded */ static int peers_responded; @@ -175,11 +168,6 @@ static struct GNUNET_MESH_Handle *h1; static struct GNUNET_MESH_Handle *h2; /** - * Mesh handle for the second leaf peer - */ -static struct GNUNET_MESH_Handle *h3; - -/** * Tunnel handle for the root peer */ static struct GNUNET_MESH_Tunnel *t; @@ -190,11 +178,6 @@ static struct GNUNET_MESH_Tunnel *t; static struct GNUNET_MESH_Tunnel *incoming_t; /** - * Tunnel handle for the second leaf peer - */ -static struct GNUNET_MESH_Tunnel *incoming_t2; - -/** * Time we started the data transmission (after tunnel has been established * and initilized). */ @@ -251,16 +234,14 @@ disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) long line = (long) cls; unsigned int i; - for (i = 0; i < 3; i++) - if (NULL != t_op[i]) - { - GNUNET_TESTBED_operation_done (t_op[i]); - t_op[i] = NULL; - } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "disconnecting mesh service of peers, called from line %ld\n", line); disconnect_task = GNUNET_SCHEDULER_NO_TASK; + for (i = 0; i < 2; i++) + { + GNUNET_TESTBED_operation_done (t_op[i]); + } if (NULL != t) { GNUNET_MESH_tunnel_destroy (t); @@ -271,11 +252,6 @@ disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_MESH_tunnel_destroy (incoming_t); incoming_t = NULL; } - if (NULL != incoming_t2) - { - GNUNET_MESH_tunnel_destroy (incoming_t2); - incoming_t2 = NULL; - } GNUNET_MESH_TEST_cleanup (test_ctx); if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle) { @@ -290,16 +266,15 @@ disconnect_mesh_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * * @param line Line in the code the abort is requested from (__LINE__). */ -void +static void abort_test (long line) { if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) { GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, + (void *) line); } - disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, - &disconnect_mesh_peers, - (void *) line); } /** @@ -326,7 +301,6 @@ data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_MESH_TransmitHandle *th; struct GNUNET_MESH_Tunnel *tunnel; - struct GNUNET_PeerIdentity *destination; if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) return; @@ -335,18 +309,14 @@ data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (GNUNET_YES == test_backwards) { tunnel = incoming_t; - destination = p_id[0]; } else { tunnel = t; - destination = p_id[2]; } th = GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, - destination, - size_payload, - &tmt_rdy, (void *) 1L); + size_payload, &tmt_rdy, (void *) 1L); if (NULL == th) { unsigned long i = (unsigned long) cls; @@ -423,17 +393,13 @@ tmt_rdy (void *cls, size_t size, void *buf) * @param cls closure (set from GNUNET_MESH_connect) * @param tunnel connection to the other end * @param tunnel_ctx place to store local state associated with the tunnel - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi) + const struct GNUNET_MessageHeader *message) { long client = (long) cls; long expected_target_client; @@ -441,15 +407,17 @@ data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, ok++; + GNUNET_MESH_receive_done (tunnel); + if ((ok % 20) == 0) { if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) { GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, + &disconnect_mesh_peers, + (void *) __LINE__); } - disconnect_task = - GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, - (void *) __LINE__); } switch (client) @@ -457,10 +425,7 @@ data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, case 0L: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n"); peers_responded++; - if (test == MULTICAST && peers_responded < 2) - return GNUNET_OK; break; - case 3L: case 4L: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client %li got a message.\n", @@ -503,9 +468,8 @@ data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, if (SPEED != test || (ok_goal - 2) == ok) { GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, sender, - size_payload, - &tmt_rdy, (void *) 1L); + GNUNET_TIME_UNIT_FOREVER_REL, + size_payload, &tmt_rdy, (void *) 1L); return GNUNET_OK; } else @@ -522,9 +486,8 @@ data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", data_ack); GNUNET_MESH_notify_transmit_ready (tunnel, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, sender, - size_payload, - &tmt_rdy, (void *) 1L); + GNUNET_TIME_UNIT_FOREVER_REL, + size_payload, &tmt_rdy, (void *) 1L); if (data_ack < TOTAL_PACKETS && SPEED != test) return GNUNET_OK; if (ok == 2 && SPEED == test) @@ -546,10 +509,10 @@ data_callback (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) { GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, + &disconnect_mesh_peers, + (void *) __LINE__); } - disconnect_task = - GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, - (void *) __LINE__); return GNUNET_OK; } @@ -568,17 +531,17 @@ static struct GNUNET_MESH_MessageHandler handlers[] = { * Method called whenever another peer has added us to a tunnel * the other peer initiated. * - * @param cls closure - * @param tunnel new handle to the tunnel - * @param initiator peer that started the tunnel - * @param atsi performance information for the tunnel - * @return initial tunnel context for the tunnel - * (can be NULL -- that's not an error) + * @param cls Closure. + * @param tunnel New handle to the tunnel. + * @param initiator Peer that started the tunnel. + * @param port Port this tunnels is connected to. + * @return Initial tunnel context for the tunnel + * (can be NULL -- that's not an error). */ static void * incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, const struct GNUNET_PeerIdentity *initiator, - const struct GNUNET_ATS_Information *atsi) + uint32_t port) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Incoming tunnel from %s to peer %d\n", @@ -587,8 +550,6 @@ incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); if ((long) cls == 4L) incoming_t = tunnel; - else if ((long) cls == 3L) - incoming_t2 = tunnel; else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -598,10 +559,10 @@ incoming_tunnel (void *cls, struct GNUNET_MESH_Tunnel *tunnel, if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) { GNUNET_SCHEDULER_cancel (disconnect_task); + disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, + &disconnect_mesh_peers, + (void *) __LINE__); } - disconnect_task = - GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, - (void *) __LINE__); return NULL; } @@ -629,129 +590,22 @@ tunnel_cleaner (void *cls, const struct GNUNET_MESH_Tunnel *tunnel, ok++; incoming_t = NULL; } - else if (3L == i) + else if (0L == i && P2P_SIGNAL == test) { - ok++; - incoming_t2 = NULL; + ok ++; } else GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown peer! %d\n", i); GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); - peers_in_tunnel--; - if (peers_in_tunnel > 0) - return; if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) { GNUNET_SCHEDULER_cancel (disconnect_task); - } - disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, - (void *) __LINE__); - - return; -} - - -/** - * Method called whenever a tunnel falls apart. - * - * @param cls closure - * @param peer peer identity the tunnel stopped working with - */ -static void -dh (void *cls, const struct GNUNET_PeerIdentity *peer) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "peer %s disconnected\n", - GNUNET_i2s (peer)); - if (P2P_SIGNAL == test) - { - ok ++; - if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) - { - GNUNET_SCHEDULER_cancel (disconnect_task); - } disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_mesh_peers, (void *) __LINE__); } - return; -} - - -/** - * Method called whenever a peer connects to a tunnel. - * - * @param cls closure - * @param peer peer identity the tunnel was created to, NULL on timeout - * @param atsi performance data for the connection - */ -static void -ch (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_ATS_Information *atsi) -{ - long i = (long) cls; - - struct GNUNET_PeerIdentity *dest; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "%ld peer %s connected\n", i, GNUNET_i2s (peer)); - - if (0 == memcmp (p_id[2], peer, sizeof (struct GNUNET_PeerIdentity)) && - i == 0L) - { - ok++; - } - if (test == MULTICAST && - 0 == memcmp (p_id[1], peer, sizeof (struct GNUNET_PeerIdentity)) && - i == 0L) - { - ok++; - } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); - switch (test) - { - case UNICAST: - case P2P_SIGNAL: - case SPEED: - case SPEED_ACK: - // incoming_t is NULL unless we send a relevant data packet - dest = p_id[2]; - break; - case MULTICAST: - peers_in_tunnel++; - if (peers_in_tunnel < 2) - return; - dest = NULL; - break; - default: - GNUNET_assert (0); - return; - } - if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) - { - GNUNET_SCHEDULER_cancel (disconnect_task); - disconnect_task = - GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, - (void *) __LINE__); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending data initializer...\n"); - peers_responded = 0; - data_ack = 0; - data_received = 0; - data_sent = 0; - GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO, - GNUNET_TIME_UNIT_FOREVER_REL, dest, - size_payload, - &tmt_rdy, (void *) 1L); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Disconnect already run?\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Aborting...\n"); - } return; } @@ -770,14 +624,6 @@ do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n"); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "add peer 2\n"); - GNUNET_MESH_peer_request_connect_add (t, p_id[2]); - - if (test == MULTICAST) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "add peer 3\n"); - GNUNET_MESH_peer_request_connect_add (t, p_id[1]); - } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "schedule timeout in TIMEOUT\n"); @@ -785,21 +631,37 @@ do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_SCHEDULER_cancel (disconnect_task); } - disconnect_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, + t = GNUNET_MESH_tunnel_create (h1, NULL, p_id[1], 1); + if (SPEED_NOBUF == test) + { + GNUNET_MESH_tunnel_buffer(t, GNUNET_NO); + test = SPEED; + } + + disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, (void *) __LINE__); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Sending data initializer...\n"); + peers_responded = 0; + data_ack = 0; + data_received = 0; + data_sent = 0; + GNUNET_MESH_notify_transmit_ready (t, GNUNET_NO, + GNUNET_TIME_UNIT_FOREVER_REL, + size_payload, &tmt_rdy, (void *) 1L); } /** * Callback to be called when the requested peer information is available * - * @param cls the closure from GNUNET_TETSBED_peer_get_information() + * @param cls the closure from GNUNET_TESTBED_peer_get_information() * @param op the operation this callback corresponds to * @param pinfo the result; will be NULL if the operation has failed * @param emsg error message if the operation has failed; * NULL if the operation is successfull */ -void +static void pi_cb (void *cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo, @@ -808,6 +670,7 @@ pi_cb (void *cls, long i = (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i); + if (NULL == pinfo || NULL != emsg) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); @@ -817,7 +680,7 @@ pi_cb (void *cls, p_id[i] = pinfo->result.id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i])); p_ids++; - if ((MULTICAST == test && p_ids < 3) || p_ids < 2) + if (p_ids < 2) return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n"); test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, @@ -846,18 +709,6 @@ tmain (void *cls, peers_running = num_peers; h1 = meshes[0]; h2 = meshes[num_peers - 1]; - t = GNUNET_MESH_tunnel_create (h1, NULL, &ch, &dh, (void *) 0L); - if (SPEED_MIN == test) - { - GNUNET_MESH_tunnel_speed_min(t); - test = SPEED; - } - if (SPEED_NOBUF == test) - { - GNUNET_MESH_tunnel_buffer(t, GNUNET_NO); - test = SPEED; - } - peers_in_tunnel = 0; disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_mesh_peers, (void *) __LINE__); @@ -866,20 +717,9 @@ tmain (void *cls, t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], GNUNET_TESTBED_PIT_IDENTITY, &pi_cb, (void *) 0L); - t_op[2] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], + t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], GNUNET_TESTBED_PIT_IDENTITY, - &pi_cb, (void *) 2L); - if (MULTICAST == test) - { - h3 = meshes[num_peers - 2]; - t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 2], - GNUNET_TESTBED_PIT_IDENTITY, - &pi_cb, (void *) 1L); - } - else - { - t_op[1] = NULL; - } + &pi_cb, (void *) 1L); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n"); } @@ -891,36 +731,29 @@ int main (int argc, char *argv[]) { initialized = GNUNET_NO; + uint32_t ports[2]; GNUNET_log_setup ("test", "DEBUG", NULL); - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n"); - if (strstr (argv[0], "test_mesh_small_unicast") != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNICAST\n"); - test = UNICAST; - test_name = "unicast"; - ok_goal = 5; - } - else if (strstr (argv[0], "test_mesh_small_multicast") != NULL) + if (strstr (argv[0], "_small_forward") != NULL) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MULTICAST\n"); - test = MULTICAST; - test_name = "multicast"; - ok_goal = 10; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n"); + test = FORWARD; + test_name = "unicast2"; + ok_goal = 4; } - else if (strstr (argv[0], "test_mesh_small_signal") != NULL) + else if (strstr (argv[0], "_small_signal") != NULL) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n"); test = P2P_SIGNAL; - test_name = "signal"; - ok_goal = 5; + test_name = "signal2"; + ok_goal = 4; } - else if (strstr (argv[0], "test_mesh_small_speed_ack") != NULL) + else if (strstr (argv[0], "_small_speed_ack") != NULL) { /* Each peer is supposed to generate the following callbacks: * 1 incoming tunnel (@dest) - * 1 connected peer (@orig) * TOTAL_PACKETS received data packet (@dest) * TOTAL_PACKETS received data packet (@orig) * 1 received tunnel destroy (@dest) @@ -929,14 +762,13 @@ main (int argc, char *argv[]) */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); test = SPEED_ACK; - test_name = "speed ack"; - ok_goal = TOTAL_PACKETS * 2 + 3; + test_name = "speed2 ack"; + ok_goal = TOTAL_PACKETS * 2 + 2; } - else if (strstr (argv[0], "test_mesh_small_speed") != NULL) + else if (strstr (argv[0], "_small_speed") != NULL) { /* Each peer is supposed to generate the following callbacks: * 1 incoming tunnel (@dest) - * 1 connected peer (@orig) * 1 initial packet (@dest) * TOTAL_PACKETS received data packet (@dest) * 1 received data packet (@orig) @@ -944,21 +776,16 @@ main (int argc, char *argv[]) * _________________________________ */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); - ok_goal = TOTAL_PACKETS + 5; - if (strstr (argv[0], "_min") != NULL) - { - test = SPEED_MIN; - test_name = "speed min"; - } - else if (strstr (argv[0], "_nobuf") != NULL) + ok_goal = TOTAL_PACKETS + 4; + if (strstr (argv[0], "_nobuf") != NULL) { test = SPEED_NOBUF; - test_name = "speed nobuf"; + test_name = "speed2 nobuf"; } else { test = SPEED; - test_name = "speed"; + test_name = "speed2"; } } else @@ -980,15 +807,17 @@ main (int argc, char *argv[]) } p_ids = 0; + ports[0] = 1; + ports[1] = 0; GNUNET_MESH_TEST_run ("test_mesh_small", - "test_mesh_small.conf", + "test_mesh.conf", 5, &tmain, - NULL, + NULL, /* tmain cls */ &incoming_tunnel, &tunnel_cleaner, handlers, - NULL); + ports); if (ok_goal > ok) { @@ -1001,3 +830,4 @@ main (int argc, char *argv[]) } /* end of test_mesh_small.c */ + diff --git a/src/mesh/test_mesh_small.conf b/src/mesh/test_mesh_small.conf deleted file mode 100644 index 943ef3638a..0000000000 --- a/src/mesh/test_mesh_small.conf +++ /dev/null @@ -1,78 +0,0 @@ -[PATHS] -SERVICEHOME = /tmp/test_mesh_small/ - -[mesh] -PORT = 10005 -ACCEPT_FROM = 127.0.0.1; -HOSTNAME = localhost -REFRESH_PATH_TIME = 5 s -APP_ANNOUNCE_TIME = 2 s -ID_ANNOUNCE_TIME = 2 s -CONNECT_TIMEOUT = 30 s -DEFAULT_TTL = 64 -DHT_REPLICAITON_LEVEL = 3 -# PREFIX = valgrind --leak-check=full --suppressions=valgrind-mesh.supp -# PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args - -[testbed] -NUM_PEERS = 5 -OVERLAY_TOPOLOGY = LINE - -[arm] -PORT = 10010 -DEFAULTSERVICES = core dht mesh - -[statistics] -AUTOSTART = YES -PORT = 10000 - -[dht] -AUTOSTART = YES -ACCEPT_FROM6 = ::1; -ACCEPT_FROM = 127.0.0.1; -HOSTNAME = localhost -PORT = 10001 - -[nse] -WORKBITS = 0 -INTERVAL = 60 s -WORKDELAY = 500 ms - -[dns] -AUTOSTART = NO -PORT = 10011 - -[vpn] -AUTOSTART = NO -PORT = 10012 - -[transport] -PORT = 10002 -AUTOSTART = YES - -[nat] -DISABLEV6 = YES -BINDTO = 127.0.0.1 -ENABLE_UPNP = NO -BEHIND_NAT = NO -ALLOW_NAT = NO -INTERNAL_ADDRESS = 127.0.0.1 -EXTERNAL_ADDRESS = 127.0.0.1 -RETURN_LOCAL_ADDRESSES = YES -USE_LOCALADDR = YES - -[ats] -WAN_QUOTA_IN = 1 GB -WAN_QUOTA_OUT = 1 GB - -[core] -AUTOSTART = YES -PORT = 10003 - -[peerinfo] -AUTOSTART = YES -PORT = 10004 - -[testing] -WEAKRANDOM = YES - diff --git a/src/mesh/test_mesh_tree_api.c b/src/mesh/test_mesh_tree_api.c deleted file mode 100644 index 3bdb82e0fc..0000000000 --- a/src/mesh/test_mesh_tree_api.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2011 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file mesh/test_mesh_tree_api.c - * @brief test mesh tree api: test of tree & path management api - * @author Bartlomiej Polot - */ - -#include "platform.h" -#include "gnunet_common.h" -#include "gnunet_util_lib.h" -#include "gnunet_dht_service.h" -#include "gnunet_mesh_service.h" -#include "mesh.h" -#ifndef MESH_TUNNEL_TREE_C -#include "mesh_tunnel_tree.c" -#define MESH_TUNNEL_TREE_C -#endif - -static int failed; -static int cb_call; -static struct GNUNET_PeerIdentity *pi[10]; -static struct MeshTunnelTree *tree; - - -/** - * Whole tree iterator. - * - * @param cls Closure (unused). - * @param peer_id Short ID of the node. - * @param parent_id Short ID of the parent node. - */ -static void -tree_cb (void *cls, GNUNET_PEER_Id peer_id, GNUNET_PEER_Id parent_id) -{ - fprintf (stdout, "%u -> %u\n", peer_id, parent_id);; -} - - -/** - * Node children iterator. - * - * @param cls Closure (unused). - * @param peer_idShort ID of the child. - */ -static void -cb (void *cls, GNUNET_PEER_Id peer_id) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: CB: Disconnected %u\n", peer_id); - if (0 == cb_call) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: and it shouldn't!\n"); - failed++; - } - cb_call--; -} - - -/** - * Print debug information about the state of the tree. - * - * @param tree Tree to debug-print. - */ -static void -test_debug (struct MeshTunnelTree *tree) -{ - tree_debug (tree); - tree_iterate_all (tree, &tree_cb, NULL); -} - - -/** - * Check if a node has all expected properties. - * - * @param peer_id Short ID of the peer to test. - * @param status Expected status of the peer. - * @param children Expected number of children of the peer. - * @param first_hop Short ID of the expected first hop towards the peer. - */ -static void -test_assert (GNUNET_PEER_Id peer_id, enum MeshPeerState status, - unsigned int children, GNUNET_PEER_Id first_hop) -{ - struct MeshTunnelTreeNode *n; - struct MeshTunnelTreeNode *c; - unsigned int i; - int pre_failed; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Checking peer %u\n", peer_id); - pre_failed = failed; - n = tree_find_peer (tree, peer_id); - if (n->peer != peer_id) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Retrieved peer has wrong ID! (Got %u, expected %u)\n", n->peer, - peer_id); - failed++; - } - if (n->status != status) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Retrieved peer has wrong status! (Got %u, expected %u)\n", - n->status, status); - failed++; - } - for (c = n->children_head, i = 0; NULL != c; c = c->next, i++) ; - if (i != children) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Retrieved peer wrong has number of children! (Got %u, expected %u)\n", - i, children); - failed++; - } - if (0 != first_hop && - GNUNET_PEER_search (tree_get_first_hop (tree, peer_id)) != first_hop) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Wrong first hop! (Got %u, expected %u)\n", - GNUNET_PEER_search (tree_get_first_hop (tree, peer_id)), - first_hop); - failed++; - } - if (pre_failed != failed) - { - struct GNUNET_PeerIdentity id; - - GNUNET_PEER_resolve (peer_id, &id); - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "*** Peer %s (%u) has failed %d checks!\n", GNUNET_i2s (&id), - peer_id, failed - pre_failed); - } -} - - -/** - * Clean up and free all memory. - */ -static void -finish (void) -{ - unsigned int i; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Finishing...\n"); - for (i = 0; i < 10; i++) - { - GNUNET_free (pi[i]); - } -} - -/** - * Convert an integer int to a peer identity - */ -static struct GNUNET_PeerIdentity * -get_pi (uint32_t id) -{ - struct GNUNET_PeerIdentity *pi; - - pi = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity)); - pi->hashPubKey.bits[0] = id + 1; - return pi; -} - - -int -main (int argc, char *argv[]) -{ - struct MeshTunnelTreeNode *node; - struct MeshPeerPath *path; - struct MeshPeerPath *path1; - unsigned int i; - - failed = 0; - cb_call = 0; - GNUNET_log_setup ("test_mesh_api_tree", - "WARNING", - NULL); - for (i = 0; i < 10; i++) - { - pi[i] = get_pi (i); - GNUNET_break (i + 1 == GNUNET_PEER_intern (pi[i])); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Peer %u: %s\n", i + 1, - GNUNET_h2s (&pi[i]->hashPubKey)); - } - tree = tree_new (1); - tree->me = tree->root; - path = path_new (5); - path->peers[0] = 1; - path->peers[1] = 2; - path->peers[2] = 3; - path->peers[3] = 4; - path->length = 4; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 1 2 3 4\n"); - tree_add_path (tree, path, &cb, NULL); - test_debug (tree); - path1 = tree_get_path_to_peer (tree, 4); - if (NULL == path1 || path->length != path1->length || - memcmp (path->peers, path1->peers, path->length) != 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Retrieved path != original\n"); - failed++; - } - path_destroy (path1); - test_assert (4, MESH_PEER_SEARCHING, 0, 2); - test_assert (3, MESH_PEER_RELAY, 1, 0); - test_assert (2, MESH_PEER_RELAY, 1, 0); - test_assert (1, MESH_PEER_ROOT, 1, 0); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding second path: 1 2 3\n"); - path->length--; - tree_add_path (tree, path, &cb, NULL); - test_debug (tree); - - test_assert (4, MESH_PEER_SEARCHING, 0, 2); - test_assert (3, MESH_PEER_SEARCHING, 1, 2); - test_assert (2, MESH_PEER_RELAY, 1, 0); - test_assert (1, MESH_PEER_ROOT, 1, 0); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding third path 1 2 3 5\n"); - path->length++; - path->peers[3] = 5; - tree_add_path (tree, path, &cb, NULL); - test_debug (tree); - - test_assert (5, MESH_PEER_SEARCHING, 0, 2); - test_assert (4, MESH_PEER_SEARCHING, 0, 2); - test_assert (3, MESH_PEER_SEARCHING, 2, 2); - test_assert (2, MESH_PEER_RELAY, 1, 0); - test_assert (1, MESH_PEER_ROOT, 1, 0); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Calculating costs...\n"); - for (i = 1; i < 5; i++) - { - path->length = i; - if (tree_get_path_cost (tree, path) != 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", - i); - failed++; - } - } - path->length++; - path->peers[4] = 6; - if (tree_get_path_cost (tree, path) != 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", i); - failed++; - } - path->peers[3] = 7; - if (tree_get_path_cost (tree, path) != 2) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", i); - failed++; - } - path->length--; - if (tree_get_path_cost (tree, path) != 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: length %u cost failed!\n", i); - failed++; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Deleting third path (5)\n"); - tree_set_status (tree, 5, MESH_PEER_READY); - cb_call = 1; - node = tree_del_path (tree, 5, &cb, NULL); - test_debug (tree); - if (cb_call != 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call); - failed++; - } - if (node->peer != 5) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Retrieved peer != original\n"); - failed++; - } - - test_assert (4, MESH_PEER_SEARCHING, 0, 2); - test_assert (3, MESH_PEER_SEARCHING, 1, 2); - test_assert (2, MESH_PEER_RELAY, 1, 0); - test_assert (1, MESH_PEER_ROOT, 1, 0); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Destroying node copy...\n"); - GNUNET_free (node); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "test: Adding new shorter first path...\n"); - path->length = 2; - path->peers[1] = 4; - cb_call = 1; - tree_find_peer (tree, 4)->status = MESH_PEER_READY; - tree_add_path (tree, path, &cb, NULL); - test_debug (tree); - if (cb_call != 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call); - failed++; - } - - test_assert (4, MESH_PEER_SEARCHING, 0, 4); - test_assert (3, MESH_PEER_SEARCHING, 0, 2); - test_assert (2, MESH_PEER_RELAY, 1, 0); - test_assert (1, MESH_PEER_ROOT, 2, 0); - - GNUNET_free (path->peers); - GNUNET_free (path); - tree_destroy (tree); - - /****************************************************************************/ - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Testing relay trees\n"); - for (i = 0; i < 10; i++) - { - GNUNET_break (i + 1 == GNUNET_PEER_intern (pi[i])); - } - tree = tree_new (2); - path = path_new (8); - path->peers[0] = 2; - path->peers[1] = 1; - path->peers[2] = 3; - path->length = 3; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 2 1 3\n"); - tree_add_path (tree, path, &cb, NULL); - test_debug (tree); - - test_assert (3, MESH_PEER_SEARCHING, 0, 3); - test_assert (1, MESH_PEER_RELAY, 1, 0); - test_assert (2, MESH_PEER_ROOT, 1, 0); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding long path: 2 1 4 5 3\n"); - path->peers[2] = 4; - path->peers[3] = 5; - path->peers[4] = 3; - path->length = 5; - tree_add_path (tree, path, &cb, NULL); - test_debug (tree); - - test_assert (3, MESH_PEER_SEARCHING, 0, 4); - test_assert (5, MESH_PEER_RELAY, 1, 4); - test_assert (4, MESH_PEER_RELAY, 1, 4); - test_assert (1, MESH_PEER_RELAY, 1, 0); - test_assert (2, MESH_PEER_ROOT, 1, 0); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "test: Even longer path: 2 6 1 7 8 4 5 3\n"); - path->peers[0] = 2; - path->peers[1] = 6; - path->peers[2] = 1; - path->peers[3] = 7; - path->peers[4] = 8; - path->peers[5] = 4; - path->peers[6] = 5; - path->peers[7] = 3; - path->length = 8; - tree_add_path (tree, path, &cb, NULL); - test_debug (tree); - - test_assert (3, MESH_PEER_SEARCHING, 0, 7); - test_assert (5, MESH_PEER_RELAY, 1, 7); - test_assert (4, MESH_PEER_RELAY, 1, 7); - test_assert (8, MESH_PEER_RELAY, 1, 7); - test_assert (7, MESH_PEER_RELAY, 1, 7); - test_assert (1, MESH_PEER_RELAY, 1, 0); - test_assert (6, MESH_PEER_RELAY, 1, 0); - test_assert (2, MESH_PEER_ROOT, 1, 0); - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 2 1 3\n"); - path->peers[1] = 1; - path->peers[2] = 3; - path->length = 3; - tree_add_path (tree, path, &cb, NULL); - test_debug (tree); - - test_assert (3, MESH_PEER_SEARCHING, 0, 3); - test_assert (1, MESH_PEER_RELAY, 1, 0); - test_assert (2, MESH_PEER_ROOT, 1, 0); - - GNUNET_free (path->peers); - GNUNET_free (path); - tree_destroy (tree); - finish (); - if (failed > 0) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u tests failed\n", failed); - return 1; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: OK\n"); - - return 0; -} diff --git a/src/pt/gnunet-daemon-pt.c b/src/pt/gnunet-daemon-pt.c index 8044f930c8..466584f0f7 100644 --- a/src/pt/gnunet-daemon-pt.c +++ b/src/pt/gnunet-daemon-pt.c @@ -33,6 +33,8 @@ #include "gnunet_statistics_service.h" #include "gnunet_applications.h" +#define PORT_PT 4242 // FIXME + /** * After how long do we time out if we could not get an IP from VPN or MESH? @@ -548,11 +550,11 @@ transmit_dns_request_to_mesh (void *cls, return 0; mlen = ntohs (rc->mesh_message->size); if (mlen > size) - { + { mesh_th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO, TIMEOUT, - NULL, mlen, + mlen, &transmit_dns_request_to_mesh, NULL); return 0; @@ -571,7 +573,7 @@ transmit_dns_request_to_mesh (void *cls, mesh_th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO, TIMEOUT, - NULL, ntohs (rc->mesh_message->size), + ntohs (rc->mesh_message->size), &transmit_dns_request_to_mesh, NULL); return mlen; @@ -670,7 +672,7 @@ dns_pre_request_handler (void *cls, mesh_th = GNUNET_MESH_notify_transmit_ready (mesh_tunnel, GNUNET_NO, TIMEOUT, - NULL, mlen, + mlen, &transmit_dns_request_to_mesh, NULL); } @@ -682,18 +684,15 @@ dns_pre_request_handler (void *cls, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_dns_response (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + const struct GNUNET_MessageHeader *message) { struct GNUNET_TUN_DnsHeader dns; size_t mlen; @@ -772,10 +771,12 @@ abort_all_requests () /** * Method called whenever a peer has disconnected from the tunnel. * + * FIXME merge with inbound cleaner + * * @param cls closure * @param peer peer identity the tunnel stopped working with */ -static void +void mesh_disconnect_handler (void *cls, const struct GNUNET_PeerIdentity * peer) @@ -797,11 +798,13 @@ mesh_disconnect_handler (void *cls, /** * Method called whenever a peer has connected to the tunnel. * + * FIXME find anouther way (in tmt_ready_callback ?) + * * @param cls closure * @param peer peer identity the tunnel was created to, NULL on timeout * @param atsi performance data for the connection */ -static void +void mesh_connect_handler (void *cls, const struct GNUNET_PeerIdentity * peer, @@ -916,9 +919,6 @@ run (void *cls, char *const *args GNUNET_UNUSED, {&receive_dns_response, GNUNET_MESSAGE_TYPE_VPN_DNS_FROM_INTERNET, 0}, {NULL, 0, 0} }; - static GNUNET_MESH_ApplicationType mesh_types[] = { - GNUNET_APPLICATION_TYPE_END - }; dns_pre_handle = GNUNET_DNS_connect (cfg, @@ -932,8 +932,8 @@ run (void *cls, char *const *args GNUNET_UNUSED, GNUNET_SCHEDULER_shutdown (); return; } - mesh_handle = GNUNET_MESH_connect (cfg, NULL, NULL, NULL, - mesh_handlers, mesh_types); + mesh_handle = GNUNET_MESH_connect (cfg, NULL, NULL, NULL, // FIXME use end handler + mesh_handlers, NULL); if (NULL == mesh_handle) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -944,11 +944,10 @@ run (void *cls, char *const *args GNUNET_UNUSED, } mesh_tunnel = GNUNET_MESH_tunnel_create (mesh_handle, NULL, - &mesh_connect_handler, - &mesh_disconnect_handler, - NULL); - GNUNET_MESH_peer_request_connect_by_type (mesh_tunnel, - GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER); + NULL, /* FIXME peer ID*/ + PORT_PT); +// GNUNET_MESH_peer_request_connect_by_type (mesh_tunnel, FIXME use regex +// GNUNET_APPLICATION_TYPE_INTERNET_RESOLVER); } } diff --git a/src/set/Makefile.am b/src/set/Makefile.am index 68ed551904..f373be20df 100644 --- a/src/set/Makefile.am +++ b/src/set/Makefile.am @@ -50,7 +50,7 @@ gnunet_service_set_SOURCES = \ gnunet_service_set_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la \ $(top_builddir)/src/core/libgnunetcore.la \ - $(top_builddir)/src/mesh/libgnunetmesh2.la \ + $(top_builddir)/src/mesh/libgnunetmesh.la \ $(GN_LIBINTL) libgnunetset_la_SOURCES = \ diff --git a/src/set/gnunet-service-set.h b/src/set/gnunet-service-set.h index 26b1d361e5..74cbf584e5 100644 --- a/src/set/gnunet-service-set.h +++ b/src/set/gnunet-service-set.h @@ -33,7 +33,7 @@ #include "gnunet_applications.h" #include "gnunet_util_lib.h" #include "gnunet_core_service.h" -#include "gnunet_mesh2_service.h" +#include "gnunet_mesh_service.h" #include "gnunet_set_service.h" #include "set.h" diff --git a/src/stream/stream_api.c b/src/stream/stream_api.c index b221d3a1df..f8c0af1cf6 100644 --- a/src/stream/stream_api.c +++ b/src/stream/stream_api.c @@ -42,6 +42,8 @@ #include "gnunet_stream_lib.h" #include "stream.h" +#define STREAM_PORT 4242 + /** * Generic logging shorthand */ @@ -311,9 +313,9 @@ struct GNUNET_STREAM_Socket int transmit_closed; /** - * The application port number (type: uint32_t) + * The application port number */ - GNUNET_MESH_ApplicationType port; + uint32_t port; /** * The write sequence number to be set incase of testing @@ -416,7 +418,7 @@ struct GNUNET_STREAM_ListenSocket /** * The service port */ - GNUNET_MESH_ApplicationType port; + uint32_t port; /** * The id of the lockmanager timeout task @@ -651,7 +653,6 @@ send_message_notify (void *cls, size_t size, void *buf) GNUNET_MESH_notify_transmit_ready (socket->tunnel, GNUNET_NO, /* Corking */ socket->mesh_retry_timeout, - &socket->other_peer, ntohs (head->message->size), &send_message_notify, socket); @@ -679,7 +680,6 @@ send_message_notify (void *cls, size_t size, void *buf) GNUNET_MESH_notify_transmit_ready (socket->tunnel, GNUNET_NO, /* Corking */ socket->mesh_retry_timeout, - &socket->other_peer, ntohs (head->message->size), &send_message_notify, socket); @@ -739,7 +739,6 @@ queue_message (struct GNUNET_STREAM_Socket *socket, GNUNET_MESH_notify_transmit_ready (socket->tunnel, GNUNET_NO, /* Corking */ socket->mesh_retry_timeout, - &socket->other_peer, ntohs (message->size), &send_message_notify, socket); @@ -1159,18 +1158,14 @@ read_io_timeout (void *cls, * * @param socket the socket through which the ack was received * @param tunnel connection to the other end - * @param sender who sent the message * @param msg the data message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int handle_data (struct GNUNET_STREAM_Socket *socket, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_STREAM_DataMessage *msg, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_STREAM_DataMessage *msg) { const void *payload; struct GNUNET_TIME_Relative ack_deadline_rel; @@ -1185,14 +1180,6 @@ handle_data (struct GNUNET_STREAM_Socket *socket, GNUNET_break_op (0); return GNUNET_SYSERR; } - if (0 != memcmp (sender, &socket->other_peer, - sizeof (struct GNUNET_PeerIdentity))) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "%s: Received DATA from non-confirming peer\n", - GNUNET_i2s (&socket->other_peer)); - return GNUNET_YES; - } switch (socket->state) { case STATE_ESTABLISHED: @@ -1333,9 +1320,7 @@ handle_data (struct GNUNET_STREAM_Socket *socket, * @param cls the socket (set from GNUNET_MESH_connect) * @param tunnel connection to the other end * @param tunnel_ctx place to store local state associated with the tunnel - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -1343,14 +1328,12 @@ static int client_handle_data (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = cls; - return handle_data (socket, tunnel, sender, - (const struct GNUNET_STREAM_DataMessage *) message, atsi); + return handle_data (socket, tunnel, + (const struct GNUNET_STREAM_DataMessage *) message); } @@ -1598,9 +1581,7 @@ control_retransmission_task (void *cls, * @param cls the socket (set from GNUNET_MESH_connect) * @param tunnel connection to the other end * @param tunnel_ctx this is NULL - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -1608,22 +1589,12 @@ static int client_handle_hello_ack (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = cls; const struct GNUNET_STREAM_HelloAckMessage *ack_msg; struct GNUNET_STREAM_HelloAckMessage *reply; - if (0 != memcmp (sender, &socket->other_peer, - sizeof (struct GNUNET_PeerIdentity))) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "%s: Received HELLO_ACK from non-confirming peer\n", - GNUNET_i2s (&socket->other_peer)); - return GNUNET_YES; - } ack_msg = (const struct GNUNET_STREAM_HelloAckMessage *) message; LOG (GNUNET_ERROR_TYPE_DEBUG, "%s: Received HELLO_ACK from %s\n", GNUNET_i2s (&socket->other_peer), GNUNET_i2s (&socket->other_peer)); @@ -1661,9 +1632,7 @@ client_handle_hello_ack (void *cls, * @param cls the socket (set from GNUNET_MESH_connect) * @param tunnel connection to the other end * @param tunnel_ctx this is NULL - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -1671,9 +1640,7 @@ static int client_handle_reset (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { // struct GNUNET_STREAM_Socket *socket = cls; @@ -1743,18 +1710,14 @@ do_transmit_shutdown (struct GNUNET_STREAM_Socket *socket) * * @param socket the socket through which the ack was received * @param tunnel connection to the other end - * @param sender who sent the message * @param msg the transmit close message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int handle_transmit_close (struct GNUNET_STREAM_Socket *socket, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *msg, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *msg) { struct GNUNET_MessageHeader *reply; @@ -1802,9 +1765,7 @@ handle_transmit_close (struct GNUNET_STREAM_Socket *socket, * @param cls the socket (set from GNUNET_MESH_connect) * @param tunnel connection to the other end * @param tunnel_ctx this is NULL - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -1812,17 +1773,13 @@ static int client_handle_transmit_close (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = cls; return handle_transmit_close (socket, tunnel, - sender, - (struct GNUNET_MessageHeader *)message, - atsi); + (struct GNUNET_MessageHeader *)message); } @@ -1853,9 +1810,7 @@ call_cont_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) * * @param socket the socket * @param tunnel connection to the other end - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @param operation the close operation which is being ACK'ed * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) @@ -1863,9 +1818,7 @@ call_cont_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static int handle_generic_close_ack (struct GNUNET_STREAM_Socket *socket, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi, int operation) { struct GNUNET_STREAM_ShutdownHandle *shutdown_handle; @@ -1971,9 +1924,7 @@ handle_generic_close_ack (struct GNUNET_STREAM_Socket *socket, * @param cls the socket (set from GNUNET_MESH_connect) * @param tunnel connection to the other end * @param tunnel_ctx this is NULL - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -1981,18 +1932,14 @@ static int client_handle_transmit_close_ack (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = cls; return handle_generic_close_ack (socket, tunnel, - sender, (const struct GNUNET_MessageHeader *) message, - atsi, SHUT_WR); } @@ -2002,18 +1949,14 @@ client_handle_transmit_close_ack (void *cls, * * @param socket the socket * @param tunnel connection to the other end - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int handle_receive_close (struct GNUNET_STREAM_Socket *socket, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_MessageHeader *receive_close_ack; @@ -2061,9 +2004,7 @@ handle_receive_close (struct GNUNET_STREAM_Socket *socket, * @param cls the socket (set from GNUNET_MESH_connect) * @param tunnel connection to the other end * @param tunnel_ctx this is NULL - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2071,18 +2012,14 @@ static int client_handle_receive_close (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = cls; return handle_receive_close (socket, tunnel, - sender, - (const struct GNUNET_MessageHeader *) message, - atsi); + (const struct GNUNET_MessageHeader *) message); } @@ -2092,9 +2029,7 @@ client_handle_receive_close (void *cls, * @param cls the socket (set from GNUNET_MESH_connect) * @param tunnel connection to the other end * @param tunnel_ctx this is NULL - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2102,18 +2037,14 @@ static int client_handle_receive_close_ack (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = cls; return handle_generic_close_ack (socket, tunnel, - sender, (const struct GNUNET_MessageHeader *) message, - atsi, SHUT_RD); } @@ -2123,18 +2054,14 @@ client_handle_receive_close_ack (void *cls, * * @param socket the socket * @param tunnel connection to the other end - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int handle_close (struct GNUNET_STREAM_Socket *socket, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_MessageHeader *close_ack; @@ -2172,9 +2099,7 @@ handle_close (struct GNUNET_STREAM_Socket *socket, * @param cls the socket (set from GNUNET_MESH_connect) * @param tunnel connection to the other end * @param tunnel_ctx this is NULL - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2182,17 +2107,13 @@ static int client_handle_close (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = cls; return handle_close (socket, tunnel, - sender, - (const struct GNUNET_MessageHeader *) message, - atsi); + (const struct GNUNET_MessageHeader *) message); } @@ -2202,9 +2123,7 @@ client_handle_close (void *cls, * @param cls the socket (set from GNUNET_MESH_connect) * @param tunnel connection to the other end * @param tunnel_ctx this is NULL - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2212,18 +2131,14 @@ static int client_handle_close_ack (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = cls; return handle_generic_close_ack (socket, tunnel, - sender, (const struct GNUNET_MessageHeader *) message, - atsi, SHUT_RDWR); } @@ -2237,9 +2152,7 @@ client_handle_close_ack (void *cls, * @param cls the closure * @param tunnel connection to the other end * @param tunnel_ctx the socket - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2247,17 +2160,13 @@ static int server_handle_data (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; return handle_data (socket, tunnel, - sender, - (const struct GNUNET_STREAM_DataMessage *)message, - atsi); + (const struct GNUNET_STREAM_DataMessage *)message); } @@ -2267,9 +2176,7 @@ server_handle_data (void *cls, * @param cls the closure * @param tunnel connection to the other end * @param tunnel_ctx the socket - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2277,9 +2184,7 @@ static int server_handle_hello (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; const struct GNUNET_STREAM_HelloMessage *hello; @@ -2287,14 +2192,6 @@ server_handle_hello (void *cls, uint32_t port; hello = (const struct GNUNET_STREAM_HelloMessage *) message; - if (0 != memcmp (sender, - &socket->other_peer, - sizeof (struct GNUNET_PeerIdentity))) - { - LOG_DEBUG ("%s: Received HELLO from non-confirming peer\n", - GNUNET_i2s (&socket->other_peer)); - return GNUNET_YES; - } GNUNET_assert (GNUNET_MESSAGE_TYPE_STREAM_HELLO == ntohs (message->type)); GNUNET_assert (socket->tunnel == tunnel); LOG_DEBUG ("%1$s: Received HELLO from %1$s\n", @@ -2342,9 +2239,7 @@ server_handle_hello (void *cls, * @param cls the closure * @param tunnel connection to the other end * @param tunnel_ctx the socket - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2352,9 +2247,7 @@ static int server_handle_hello_ack (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; const struct GNUNET_STREAM_HelloAckMessage *ack_message; @@ -2393,9 +2286,7 @@ server_handle_hello_ack (void *cls, * @param cls the closure * @param tunnel connection to the other end * @param tunnel_ctx the socket - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2403,9 +2294,7 @@ static int server_handle_reset (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { // struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; /* FIXME */ @@ -2419,9 +2308,7 @@ server_handle_reset (void *cls, * @param cls the closure * @param tunnel connection to the other end * @param tunnel_ctx the socket - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2429,13 +2316,11 @@ static int server_handle_transmit_close (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; - return handle_transmit_close (socket, tunnel, sender, message, atsi); + return handle_transmit_close (socket, tunnel, message); } @@ -2445,9 +2330,7 @@ server_handle_transmit_close (void *cls, * @param cls the closure * @param tunnel connection to the other end * @param tunnel_ctx the socket - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2455,14 +2338,11 @@ static int server_handle_transmit_close_ack (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; - return handle_generic_close_ack (socket, tunnel, sender, message, atsi, - SHUT_WR); + return handle_generic_close_ack (socket, tunnel, message, SHUT_WR); } @@ -2472,9 +2352,7 @@ server_handle_transmit_close_ack (void *cls, * @param cls the closure * @param tunnel connection to the other end * @param tunnel_ctx the socket - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2482,13 +2360,11 @@ static int server_handle_receive_close (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; - return handle_receive_close (socket, tunnel, sender, message, atsi); + return handle_receive_close (socket, tunnel, message); } @@ -2498,9 +2374,7 @@ server_handle_receive_close (void *cls, * @param cls the closure * @param tunnel connection to the other end * @param tunnel_ctx the socket - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2508,14 +2382,11 @@ static int server_handle_receive_close_ack (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; - return handle_generic_close_ack (socket, tunnel, sender, message, atsi, - SHUT_RD); + return handle_generic_close_ack (socket, tunnel, message, SHUT_RD); } @@ -2526,9 +2397,7 @@ server_handle_receive_close_ack (void *cls, * GNUNET_STREAM_listen) * @param tunnel connection to the other end * @param tunnel_ctx the socket - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2536,13 +2405,11 @@ static int server_handle_close (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; - return handle_close (socket, tunnel, sender, message, atsi); + return handle_close (socket, tunnel, message); } @@ -2552,9 +2419,7 @@ server_handle_close (void *cls, * @param cls the closure * @param tunnel connection to the other end * @param tunnel_ctx the socket - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2562,14 +2427,11 @@ static int server_handle_close_ack (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; - return handle_generic_close_ack (socket, tunnel, sender, message, atsi, - SHUT_RDWR); + return handle_generic_close_ack (socket, tunnel, message, SHUT_RDWR); } @@ -2578,18 +2440,14 @@ server_handle_close_ack (void *cls, * * @param socket the socket through which the ack was received * @param tunnel connection to the other end - * @param sender who sent the message * @param ack the acknowledgment message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int handle_ack (struct GNUNET_STREAM_Socket *socket, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_STREAM_AckMessage *ack, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_STREAM_AckMessage *ack) { struct GNUNET_STREAM_WriteHandle *write_handle; uint64_t ack_bitmap; @@ -2597,15 +2455,6 @@ handle_ack (struct GNUNET_STREAM_Socket *socket, int need_retransmission; uint32_t sequence_difference; - if (0 != memcmp (sender, - &socket->other_peer, - sizeof (struct GNUNET_PeerIdentity))) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, - "%s: Received ACK from non-confirming peer\n", - GNUNET_i2s (&socket->other_peer)); - return GNUNET_YES; - } switch (socket->state) { case (STATE_ESTABLISHED): @@ -2734,9 +2583,7 @@ handle_ack (struct GNUNET_STREAM_Socket *socket, * @param cls the 'struct GNUNET_STREAM_Socket' * @param tunnel connection to the other end * @param tunnel_ctx unused - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2744,15 +2591,13 @@ static int client_handle_ack (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = cls; const struct GNUNET_STREAM_AckMessage *ack; ack = (const struct GNUNET_STREAM_AckMessage *) message; - return handle_ack (socket, tunnel, sender, ack, atsi); + return handle_ack (socket, tunnel, ack); } @@ -2762,9 +2607,7 @@ client_handle_ack (void *cls, * @param cls the server's listen socket * @param tunnel connection to the other end * @param tunnel_ctx pointer to the 'struct GNUNET_STREAM_Socket*' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ @@ -2772,14 +2615,12 @@ static int server_handle_ack (void *cls, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information*atsi) + const struct GNUNET_MessageHeader *message) { struct GNUNET_STREAM_Socket *socket = *tunnel_ctx; const struct GNUNET_STREAM_AckMessage *ack = (const struct GNUNET_STREAM_AckMessage *) message; - return handle_ack (socket, tunnel, sender, ack, atsi); + return handle_ack (socket, tunnel, ack); } @@ -2847,8 +2688,10 @@ static struct GNUNET_MESH_MessageHandler server_message_handlers[] = { * @param cls the socket for which this tunnel is created * @param peer the peer identity of the target * @param atsi performance data for the connection + * + * FIXME static */ -static void +void mesh_peer_connect_callback (void *cls, const struct GNUNET_PeerIdentity *peer, const struct GNUNET_ATS_Information * atsi) @@ -2887,8 +2730,10 @@ mesh_peer_connect_callback (void *cls, * * @param cls the socket associated which this tunnel * @param peer the peer identity of the target + * + * FIXME static */ -static void +void mesh_peer_disconnect_callback (void *cls, const struct GNUNET_PeerIdentity *peer) { @@ -2906,7 +2751,7 @@ mesh_peer_disconnect_callback (void *cls, * @param cls closure * @param tunnel new handle to the tunnel * @param initiator peer that started the tunnel - * @param atsi performance information for the tunnel + * @param port incoming port * @return initial tunnel context for the tunnel * (can be NULL -- that's not an error) */ @@ -2914,7 +2759,7 @@ static void * new_tunnel_notify (void *cls, struct GNUNET_MESH_Tunnel *tunnel, const struct GNUNET_PeerIdentity *initiator, - const struct GNUNET_ATS_Information *atsi) + uint32_t port) { struct GNUNET_STREAM_ListenSocket *lsocket = cls; struct GNUNET_STREAM_Socket *socket; @@ -3067,7 +2912,7 @@ lock_status_change_cb (void *cls, const char *domain, uint32_t lock, } if (NULL == lsocket->mesh) { - GNUNET_MESH_ApplicationType ports[] = {lsocket->port, 0}; + uint32_t ports[] = {lsocket->port, 0}; lsocket->mesh = GNUNET_MESH_connect (lsocket->cfg, lsocket, /* Closure */ @@ -3109,7 +2954,7 @@ lock_status_change_cb (void *cls, const char *domain, uint32_t lock, struct GNUNET_STREAM_Socket * GNUNET_STREAM_open (const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *target, - GNUNET_MESH_ApplicationType app_port, + uint32_t app_port, GNUNET_STREAM_OpenCallback open_cb, void *open_cb_cls, ...) @@ -3177,13 +3022,10 @@ GNUNET_STREAM_open (const struct GNUNET_CONFIGURATION_Handle *cfg, /* Now create the mesh tunnel to target */ LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating MESH Tunnel\n"); socket->tunnel = GNUNET_MESH_tunnel_create (socket->mesh, - NULL, /* Tunnel context */ - &mesh_peer_connect_callback, - &mesh_peer_disconnect_callback, - socket); + socket, /* Tunnel context */ + &socket->other_peer, + STREAM_PORT); GNUNET_assert (NULL != socket->tunnel); - GNUNET_MESH_peer_request_connect_add (socket->tunnel, - &socket->other_peer); socket->stat_handle = GNUNET_STATISTICS_create ("stream", cfg); LOG (GNUNET_ERROR_TYPE_DEBUG, "%s() END\n", __func__); return socket; @@ -3388,7 +3230,7 @@ GNUNET_STREAM_close (struct GNUNET_STREAM_Socket *socket) */ struct GNUNET_STREAM_ListenSocket * GNUNET_STREAM_listen (const struct GNUNET_CONFIGURATION_Handle *cfg, - GNUNET_MESH_ApplicationType app_port, + uint32_t app_port, GNUNET_STREAM_ListenCallback listen_cb, void *listen_cb_cls, ...) diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c index bc2327e96a..7844df15b1 100644 --- a/src/vpn/gnunet-service-vpn.c +++ b/src/vpn/gnunet-service-vpn.c @@ -50,6 +50,8 @@ #define MAX_MESSAGE_QUEUE_SIZE 4 +#define PORT_VPN 42 + /** * State we keep for each of our tunnels. */ @@ -601,10 +603,12 @@ destroy_tunnel_task (void *cls, /** * Method called whenever a peer has disconnected from the tunnel. * + * FIXME merge with inbound_cleaner + * * @param cls closure * @param peer peer identity the tunnel stopped working with */ -static void +void tunnel_peer_disconnect_handler (void *cls, const struct GNUNET_PeerIdentity * peer) @@ -635,11 +639,13 @@ tunnel_peer_disconnect_handler (void *cls, * Method called whenever a peer has connected to the tunnel. Notifies * the waiting client that the tunnel is now up. * + * FIXME merge with tunnel_create + * * @param cls closure * @param peer peer identity the tunnel was created to, NULL on timeout * @param atsi performance data for the connection */ -static void +void tunnel_peer_connect_handler (void *cls, const struct GNUNET_PeerIdentity * peer, @@ -699,7 +705,6 @@ send_to_peer_notify_callback (void *cls, size_t size, void *buf) ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, GNUNET_NO /* cork */, GNUNET_TIME_UNIT_FOREVER_REL, - NULL, tnq->len, &send_to_peer_notify_callback, ts); @@ -751,7 +756,6 @@ send_to_tunnel (struct TunnelMessageQueueEntry *tnq, ts->th = GNUNET_MESH_notify_transmit_ready (ts->tunnel, GNUNET_NO /* cork */, GNUNET_TIME_UNIT_FOREVER_REL, - NULL, tnq->len, &send_to_peer_notify_callback, ts); @@ -782,11 +786,8 @@ handle_regex_result (void *cls, ts->search = NULL; ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle, ts, - &tunnel_peer_connect_handler, - &tunnel_peer_disconnect_handler, - ts); - GNUNET_MESH_peer_request_connect_add (ts->tunnel, - id); + id, + PORT_VPN); } @@ -826,9 +827,8 @@ create_tunnel_to_destination (struct DestinationEntry *de, { ts->tunnel = GNUNET_MESH_tunnel_create (mesh_handle, ts, - &tunnel_peer_connect_handler, - &tunnel_peer_disconnect_handler, - ts); + &de->details.service_destination.target, + PORT_VPN); if (NULL == ts->tunnel) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -840,8 +840,6 @@ create_tunnel_to_destination (struct DestinationEntry *de, "Creating tunnel to peer %s offering service %s\n", GNUNET_i2s (&de->details.service_destination.target), GNUNET_h2s (&de->details.service_destination.service_descriptor)); - GNUNET_MESH_peer_request_connect_add (ts->tunnel, - &de->details.service_destination.target); } else { @@ -1741,17 +1739,15 @@ make_up_icmpv6_payload (struct TunnelState *ts, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, - void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + void **tunnel_ctx, + const struct GNUNET_MessageHeader *message) { struct TunnelState *ts = *tunnel_ctx; const struct GNUNET_EXIT_IcmpToVPNMessage *i2v; @@ -2082,17 +2078,15 @@ receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, - void **tunnel_ctx, const struct GNUNET_PeerIdentity *sender, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + void **tunnel_ctx, + const struct GNUNET_MessageHeader *message) { struct TunnelState *ts = *tunnel_ctx; const struct GNUNET_EXIT_UdpReplyMessage *reply; @@ -2239,18 +2233,15 @@ receive_udp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, * @param cls closure, NULL * @param tunnel connection to the other end * @param tunnel_ctx pointer to our 'struct TunnelState *' - * @param sender who sent the message * @param message the actual message - * @param atsi performance data for the connection + * * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ static int receive_tcp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, void **tunnel_ctx, - const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, - const struct GNUNET_MessageHeader *message, - const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) + const struct GNUNET_MessageHeader *message) { struct TunnelState *ts = *tunnel_ctx; const struct GNUNET_EXIT_TcpDataMessage *data; @@ -2842,32 +2833,11 @@ service_redirect_to_service (void *cls GNUNET_UNUSED, struct GNUNET_SERVER_Clien } - -/** - * Function called for inbound tunnels. As we don't offer - * any mesh services, this function should never be called. - * - * @param cls closure - * @param tunnel new handle to the tunnel - * @param initiator peer that started the tunnel - * @param atsi performance information for the tunnel - * @return initial tunnel context for the tunnel - * (can be NULL -- that's not an error) - */ -static void * -inbound_tunnel_cb (void *cls, struct GNUNET_MESH_Tunnel *tunnel, - const struct GNUNET_PeerIdentity *initiator, - const struct GNUNET_ATS_Information *atsi) -{ - /* How can and why should anyone open an inbound tunnel to vpn? */ - GNUNET_break (0); - return NULL; -} - - /** * Function called whenever an inbound tunnel is destroyed. Should clean up * any associated state. + * + * FIXME now its also user for disconnections * * @param cls closure (set from GNUNET_MESH_connect) * @param tunnel connection to the other end (henceforth invalid) @@ -3081,9 +3051,6 @@ run (void *cls, { &receive_icmp_back, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN, 0}, {NULL, 0, 0} }; - static const GNUNET_MESH_ApplicationType types[] = { - GNUNET_APPLICATION_TYPE_END - }; char *ifname; char *ipv6addr; char *ipv6prefix_s; @@ -3209,10 +3176,10 @@ run (void *cls, mesh_handle = GNUNET_MESH_connect (cfg_, NULL, - &inbound_tunnel_cb, + NULL, &tunnel_cleaner, mesh_handlers, - types); + NULL); helper_handle = GNUNET_HELPER_start (GNUNET_NO, "gnunet-helper-vpn", vpn_argv, &message_token, NULL, NULL); |