From a4221fb791366837276e7bc17ffddfaf8ec758f8 Mon Sep 17 00:00:00 2001 From: Bart Polot Date: Wed, 2 Oct 2013 16:39:56 +0000 Subject: [PATCH] - more refactoring --- src/mesh/Makefile.am | 8 +- src/mesh/gnunet-service-mesh-enc | 228 +++++ src/mesh/gnunet-service-mesh-enc.c | 999 +--------------------- src/mesh/gnunet-service-mesh_connection.c | 788 ++++++++++++++++- src/mesh/gnunet-service-mesh_connection.h | 13 +- src/mesh/gnunet-service-mesh_dht.c | 183 ++++ src/mesh/gnunet-service-mesh_dht.h | 71 ++ src/mesh/gnunet-service-mesh_local.c | 10 +- src/mesh/gnunet-service-mesh_local.h | 4 +- src/mesh/gnunet-service-mesh_peer.c | 166 ++++ src/mesh/gnunet-service-mesh_peer.h | 77 ++ 11 files changed, 1540 insertions(+), 1007 deletions(-) create mode 100755 src/mesh/gnunet-service-mesh-enc create mode 100644 src/mesh/gnunet-service-mesh_dht.c create mode 100644 src/mesh/gnunet-service-mesh_dht.h create mode 100644 src/mesh/gnunet-service-mesh_peer.c create mode 100644 src/mesh/gnunet-service-mesh_peer.h diff --git a/src/mesh/Makefile.am b/src/mesh/Makefile.am index dd2e7a866..50d617caf 100644 --- a/src/mesh/Makefile.am +++ b/src/mesh/Makefile.am @@ -20,11 +20,11 @@ plugindir = $(libdir)/gnunet AM_CLFAGS = -g -EXP_LIB = \ - libgnunetmeshenc.la +#EXP_LIB = \ +# libgnunetmeshenc.la -EXP_LIBEXEC = \ - gnunet-service-mesh-enc +#EXP_LIBEXEC = \ +# gnunet-service-mesh-enc libexec_PROGRAMS = \ gnunet-service-mesh $(EXP_LIBEXEC) diff --git a/src/mesh/gnunet-service-mesh-enc b/src/mesh/gnunet-service-mesh-enc new file mode 100755 index 000000000..2af28be78 --- /dev/null +++ b/src/mesh/gnunet-service-mesh-enc @@ -0,0 +1,228 @@ +#! /bin/sh + +# gnunet-service-mesh-enc - temporary wrapper script for .libs/gnunet-service-mesh-enc +# Generated by libtool (GNU libtool) 2.4.2 +# +# The gnunet-service-mesh-enc program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command="(cd /home/bart/g/src/mesh; { test -z \"\${LIBRARY_PATH+set}\" || unset LIBRARY_PATH || { LIBRARY_PATH=; export LIBRARY_PATH; }; }; { test -z \"\${COMPILER_PATH+set}\" || unset COMPILER_PATH || { COMPILER_PATH=; export COMPILER_PATH; }; }; { test -z \"\${GCC_EXEC_PREFIX+set}\" || unset GCC_EXEC_PREFIX || { GCC_EXEC_PREFIX=; export GCC_EXEC_PREFIX; }; }; { test -z \"\${LD_RUN_PATH+set}\" || unset LD_RUN_PATH || { LD_RUN_PATH=; export LD_RUN_PATH; }; }; { test -z \"\${LD_LIBRARY_PATH+set}\" || unset LD_LIBRARY_PATH || { LD_LIBRARY_PATH=; export LD_LIBRARY_PATH; }; }; PATH=/home/bart/bin:/tmp/bartgnunet/bin:/home/bart/bin:/tmp/bartgnunet/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/opt/cuda/bin:/usr/bin/vendor_perl:/usr/bin/core_perl; export PATH; gcc -fno-strict-aliasing -Wall -O0 -g -Wall -I/tmp/bartgnunet/include -o \$progdir/\$file gnunet_service_mesh_enc-gnunet-service-mesh-enc.o gnunet_service_mesh_enc-mesh_path.o gnunet_service_mesh_enc-mesh_common.o -lrt ../../src/util/.libs/libgnunetutil.so -L/tmp/bartgnunet/lib ../../src/core/.libs/libgnunetcore.so ../../src/dht/.libs/libgnunetdht.so ../../src/statistics/.libs/libgnunetstatistics.so ../../src/block/.libs/libgnunetblock.so /home/bart/g/src/util/.libs/libgnunetutil.so /tmp/bartgnunet/lib/libgcrypt.so -lgpg-error -lltdl -lz -lunistring -lm -Wl,-rpath -Wl,/home/bart/g/src/util/.libs -Wl,-rpath -Wl,/home/bart/g/src/core/.libs -Wl,-rpath -Wl,/home/bart/g/src/dht/.libs -Wl,-rpath -Wl,/home/bart/g/src/statistics/.libs -Wl,-rpath -Wl,/home/bart/g/src/block/.libs -Wl,-rpath -Wl,/tmp/bartgnunet/lib -Wl,-rpath -Wl,/tmp/bartgnunet/lib)" + +# This environment variable determines our operation mode. +if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then + # install mode needs the following variables: + generated_by_libtool_version='2.4.2' + notinst_deplibs=' ../../src/util/libgnunetutil.la ../../src/core/libgnunetcore.la ../../src/dht/libgnunetdht.la ../../src/statistics/libgnunetstatistics.la ../../src/block/libgnunetblock.la /home/bart/g/src/util/libgnunetutil.la' +else + # When we are sourced in execute mode, $file and $ECHO are already set. + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + file="$0" + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + ECHO="printf %s\\n" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string --lt- +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's ../../libtool value, followed by no. +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=$0 + shift + for lt_opt + do + case "$lt_opt" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` + test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. + lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` + cat "$lt_dump_D/$lt_dump_F" + exit 0 + ;; + --lt-*) + $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n "$lt_option_debug"; then + echo "gnunet-service-mesh-enc:gnunet-service-mesh-enc:${LINENO}: libtool wrapper (GNU libtool) 2.4.2" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + $ECHO "gnunet-service-mesh-enc:gnunet-service-mesh-enc:${LINENO}: newargv[$lt_dump_args_N]: $lt_arg" + lt_dump_args_N=`expr $lt_dump_args_N + 1` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ + + if test -n "$lt_option_debug"; then + $ECHO "gnunet-service-mesh-enc:gnunet-service-mesh-enc:${LINENO}: newargv[0]: $progdir/$program" 1>&2 + func_lt_dump_args ${1+"$@"} 1>&2 + fi + exec "$progdir/$program" ${1+"$@"} + + $ECHO "$0: cannot exec $program $*" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from $@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + case " $* " in + *\ --lt-*) + for lt_wr_arg + do + case $lt_wr_arg in + --lt-*) ;; + *) set x "$@" "$lt_wr_arg"; shift;; + esac + shift + done ;; + esac + func_exec_program_core ${1+"$@"} +} + + # Parse options + func_parse_lt_options "$0" ${1+"$@"} + + # Find the directory that this script lives in. + thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + test "x$thisdir" = "x$file" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` + while test -n "$file"; do + destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` + + # If there was a directory component, then change thisdir. + if test "x$destdir" != "x$file"; then + case "$destdir" in + [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; + *) thisdir="$thisdir/$destdir" ;; + esac + fi + + file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` + file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no + if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then + # special case for '.' + if test "$thisdir" = "."; then + thisdir=`pwd` + fi + # remove .libs from thisdir + case "$thisdir" in + *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; + .libs ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=`cd "$thisdir" && pwd` + test -n "$absdir" && thisdir="$absdir" + + program=lt-'gnunet-service-mesh-enc' + progdir="$thisdir/.libs" + + if test ! -f "$progdir/$program" || + { file=`ls -1dt "$progdir/$program" "$progdir/../$program" 2>/dev/null | /usr/bin/sed 1q`; \ + test "X$file" != "X$progdir/$program"; }; then + + file="$$-$program" + + if test ! -d "$progdir"; then + mkdir "$progdir" + else + rm -f "$progdir/$file" + fi + + # relink executable if necessary + if test -n "$relink_command"; then + if relink_command_output=`eval $relink_command 2>&1`; then : + else + printf %s\n "$relink_command_output" >&2 + rm -f "$progdir/$file" + exit 1 + fi + fi + + mv -f "$progdir/$file" "$progdir/$program" 2>/dev/null || + { rm -f "$progdir/$program"; + mv -f "$progdir/$file" "$progdir/$program"; } + rm -f "$progdir/$file" + fi + + if test -f "$progdir/$program"; then + if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then + # Run the actual program with our arguments. + func_exec_program ${1+"$@"} + fi + else + # The program doesn't exist. + $ECHO "$0: error: \`$progdir/$program' does not exist" 1>&2 + $ECHO "This script is just a wrapper for $program." 1>&2 + $ECHO "See the libtool documentation for more information." 1>&2 + exit 1 + fi +fi diff --git a/src/mesh/gnunet-service-mesh-enc.c b/src/mesh/gnunet-service-mesh-enc.c index a5670fff3..dc053639d 100644 --- a/src/mesh/gnunet-service-mesh-enc.c +++ b/src/mesh/gnunet-service-mesh-enc.c @@ -46,38 +46,20 @@ #include "platform.h" #include "gnunet_util_lib.h" #include "mesh_enc.h" -#include "mesh_protocol_enc.h" -#include "mesh_path.h" #include "block_mesh.h" -#include "gnunet_dht_service.h" #include "gnunet_statistics_service.h" #include "gnunet-service-mesh_local.h" #include "gnunet-service-mesh_channel.h" #include "gnunet-service-mesh_connection.h" +#include "gnunet-service-mesh_dht.h" +#include "gnunet-service-mesh_peer.h" #define MESH_BLOOM_SIZE 128 -#define MESH_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\ - GNUNET_TIME_UNIT_MINUTES,\ - 10) -#define MESH_RETRANSMIT_TIME GNUNET_TIME_UNIT_SECONDS -#define MESH_RETRANSMIT_MARGIN 4 - -#define MESH_DEBUG_DHT GNUNET_NO -#define MESH_DEBUG_CONNECTION GNUNET_NO -#define MESH_DEBUG_TIMING __LINUX__ && GNUNET_NO -#if MESH_DEBUG_DHT -#define DEBUG_DHT(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) -#else -#define DEBUG_DHT(...) -#endif -#if MESH_DEBUG_CONNECTION -#define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) -#else -#define DEBUG_CONN(...) -#endif +#define MESH_DEBUG_TIMING __LINUX__ && GNUNET_NO + #if MESH_DEBUG_TIMING #include @@ -141,75 +123,7 @@ enum MeshTunnelState /******************************************************************************/ /** FWD declaration */ -struct MeshClient; -struct MeshPeer; struct MeshTunnel2; -struct MeshConnection; - - - -/** - * Struct containing all information regarding a given peer - */ -struct MeshPeer -{ - /** - * ID of the peer - */ - GNUNET_PEER_Id id; - - /** - * Last time we heard from this peer - */ - struct GNUNET_TIME_Absolute last_contact; - - /** - * 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 paths to this peer - */ - struct GNUNET_DHT_GetHandle *dhtget; - - /** - * Tunnel to this peer, if any. - */ - struct MeshTunnel2 *tunnel; - - /** - * Connections that go through this peer, indexed by tid; - */ - struct GNUNET_CONTAINER_MultiHashMap *connections; - - /** - * Handle for queued transmissions - */ - struct GNUNET_CORE_TransmitHandle *core_transmit; - - /** - * 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; -}; - - /** @@ -354,10 +268,6 @@ mesh_debug (void *cls, int success) /************************** Configuration parameters **************************/ -/** - * 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. @@ -369,16 +279,6 @@ static struct GNUNET_TIME_Relative connect_timeout; */ 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 peers do we want to remember? - */ -static unsigned long long max_peers; - /** * Percentage of messages that will be dropped (for test purposes only). */ @@ -386,21 +286,6 @@ static unsigned long long drop_percent; /*************************** Static global variables **************************/ -/** - * Peers known, indexed by PeerIdentity (MeshPeer). - */ -static struct GNUNET_CONTAINER_MultiPeerMap *peers; - -/** - * 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 the statistics service. */ @@ -421,11 +306,6 @@ static struct GNUNET_PeerIdentity my_full_id; */ static struct GNUNET_CRYPTO_EccPrivateKey *my_private_key; -/** - * Task to periodically announce itself in the network. - */ -GNUNET_SCHEDULER_TaskIdentifier announce_id_task; - /******************************************************************************/ /*********************** DECLARATIONS **************************/ @@ -643,51 +523,6 @@ GNUNET_MESH_DEBUG_CS2S (enum MeshTunnelState s) -/******************************************************************************/ -/************************ 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; - struct GNUNET_HashCode phash; - - 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; - GNUNET_CRYPTO_hash (&my_full_id, sizeof (struct GNUNET_PeerIdentity), &phash); - GNUNET_DHT_put (dht_handle, /* DHT handle */ - &phash, /* 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 ************************/ /******************************************************************************/ @@ -2330,339 +2165,6 @@ handle_data_ack (struct MeshTunnel2 *t, } -/** - * Core handler for connection creation. - * - * @param cls Closure (unused). - * @param peer Sender (neighbor). - * @param message Message. - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_connection_create (void *cls, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_ConnectionCreate *msg; - struct GNUNET_PeerIdentity *id; - struct GNUNET_HashCode *cid; - struct MeshPeerPath *path; - struct MeshPeer *dest_peer; - struct MeshPeer *orig_peer; - struct MeshConnection *c; - unsigned int own_pos; - uint16_t size; - uint16_t i; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n"); - - /* Check size */ - size = ntohs (message->size); - if (size < sizeof (struct GNUNET_MESH_ConnectionCreate)) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - - /* Calculate hops */ - size -= sizeof (struct GNUNET_MESH_ConnectionCreate); - if (size % sizeof (struct GNUNET_PeerIdentity)) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - size /= sizeof (struct GNUNET_PeerIdentity); - if (1 > size) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); - - /* Get parameters */ - msg = (struct GNUNET_MESH_ConnectionCreate *) message; - cid = &msg->cid; - id = (struct GNUNET_PeerIdentity *) &msg[1]; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " connection %s (%s).\n", - GNUNET_h2s (cid), GNUNET_i2s (id)); - - /* Create connection */ - c = connection_get (cid); - if (NULL == c) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n"); - c = connection_new (cid); - if (NULL == c) - return GNUNET_OK; - connection_reset_timeout (c, GNUNET_YES); - - /* Create path */ - 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 (&id[i])); - path->peers[i] = GNUNET_PEER_intern (&id[i]); - if (path->peers[i] == myid) - own_pos = i; - } - 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); - connection_destroy (c); - return GNUNET_OK; - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos); - path_add_to_peers (path, GNUNET_NO); - c->path = path_duplicate (path); - c->own_pos = own_pos; - } - else - { - path = NULL; - } - if (MESH_CONNECTION_NEW == c->state) - connection_change_state (c, MESH_CONNECTION_SENT); - - /* Remember peers */ - dest_peer = peer_get (&id[size - 1]); - orig_peer = peer_get (&id[0]); - - /* Is it a connection to us? */ - if (c->own_pos == size - 1) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); - peer_add_path_to_origin (orig_peer, path, GNUNET_YES); - - if (NULL == orig_peer->tunnel) - { - orig_peer->tunnel = tunnel_new (); - orig_peer->tunnel->peer = orig_peer; - } - tunnel_add_connection (orig_peer->tunnel, c); - if (MESH_TUNNEL_NEW == c->t->state) - tunnel_change_state (c->t, MESH_TUNNEL_WAITING); - - send_connection_ack (c, GNUNET_NO); - if (MESH_CONNECTION_SENT == c->state) - connection_change_state (c, MESH_CONNECTION_ACK); - - /* Keep tunnel alive in direction dest->owner*/ - connection_reset_timeout (c, GNUNET_NO); - } - else - { - /* It's for somebody else! Retransmit. */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n"); - peer_add_path (dest_peer, path_duplicate (path), GNUNET_NO); - peer_add_path_to_origin (orig_peer, path, GNUNET_NO); - send_prebuilt_message_connection (message, c, NULL, GNUNET_YES); - } - 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_connection_ack (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_ConnectionACK *msg; - struct MeshConnection *c; - struct MeshPeerPath *p; - struct MeshPeer *pi; - int fwd; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n"); - msg = (struct GNUNET_MESH_ConnectionACK *) message; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n", - GNUNET_h2s (&msg->cid)); - c = connection_get (&msg->cid); - if (NULL == c) - { - GNUNET_STATISTICS_update (stats, "# control on unknown connection", - 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the connection!\n"); - return GNUNET_OK; - } - - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", - GNUNET_i2s (peer)); - pi = peer_get (peer); - if (connection_get_next_hop (c) == pi) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n"); - fwd = GNUNET_NO; - if (MESH_CONNECTION_SENT == c->state) - connection_change_state (c, MESH_CONNECTION_ACK); - } - else if (connection_get_prev_hop (c) == pi) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK\n"); - fwd = GNUNET_YES; - connection_change_state (c, MESH_CONNECTION_READY); - } - else - { - GNUNET_break_op (0); - return GNUNET_OK; - } - connection_reset_timeout (c, fwd); - - /* Add path to peers? */ - p = c->path; - if (NULL != p) - { - path_add_to_peers (p, GNUNET_YES); - } - else - { - GNUNET_break (0); - } - - /* Message for us as creator? */ - if (connection_is_origin (c, GNUNET_YES)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n"); - connection_change_state (c, MESH_CONNECTION_READY); - if (MESH_TUNNEL_READY != c->t->state) - tunnel_change_state (c->t, MESH_TUNNEL_READY); - send_connection_ack (c, GNUNET_YES); - tunnel_send_queued_data (c->t, GNUNET_YES); - if (3 <= tunnel_count_connections (c->t) && NULL != c->t->peer->dhtget) - { - GNUNET_DHT_get_stop (c->t->peer->dhtget); - c->t->peer->dhtget = NULL; - } - return GNUNET_OK; - } - - /* Message for us as destination? */ - if (GMC_is_terminal (c, GNUNET_YES)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n"); - if (MESH_TUNNEL_READY != c->t->state) - tunnel_change_state (c->t, MESH_TUNNEL_READY); - connection_change_state (c, MESH_CONNECTION_READY); - tunnel_send_queued_data (c->t, GNUNET_NO); - return GNUNET_OK; - } - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); - send_prebuilt_message_connection (message, c, NULL, fwd); - return GNUNET_OK; -} - - -/** - * Core handler for notifications of broken paths - * - * @param cls Closure (unused). - * @param peer Peer identity of sending neighbor. - * @param message Message. - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_connection_broken (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_ConnectionBroken *msg; - struct MeshConnection *c; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer)); - msg = (struct GNUNET_MESH_ConnectionBroken *) 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)); - c = connection_get (&msg->cid); - if (NULL == c) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1), - GNUNET_PEER_search (&msg->peer2)); - return GNUNET_OK; - -} - - -/** - * Core handler for tunnel destruction - * - * @param cls Closure (unused). - * @param peer Peer identity of sending neighbor. - * @param message Message. - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_connection_destroy (void *cls, - const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - struct GNUNET_MESH_ConnectionDestroy *msg; - struct MeshConnection *c; - GNUNET_PEER_Id id; - int fwd; - - msg = (struct GNUNET_MESH_ConnectionDestroy *) message; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got a CONNECTION DESTROY message from %s\n", - GNUNET_i2s (peer)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " for connection %s\n", - GNUNET_h2s (&msg->cid)); - c = connection_get (&msg->cid); - if (NULL == c) - { - /* 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; - } - id = GNUNET_PEER_search (peer); - if (id == connection_get_prev_hop (c)->id) - fwd = GNUNET_YES; - else if (id == connection_get_next_hop (c)->id) - fwd = GNUNET_NO; - else - { - GNUNET_break_op (0); - return GNUNET_OK; - } - send_prebuilt_message_connection (message, c, NULL, fwd); - c->destroy = GNUNET_YES; - - return GNUNET_OK; -} /** @@ -2855,399 +2357,6 @@ handle_decrypted (struct MeshTunnel2 *t, } -/** - * Generic handler for mesh network encrypted traffic. - * - * @param peer Peer identity this notification is about. - * @param message Encrypted message. - * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO; - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MESH_Encrypted *msg, - int fwd) -{ - struct MeshConnection *c; - struct MeshTunnel2 *t; - struct MeshPeer *neighbor; - struct MeshFlowControl *fc; - uint32_t pid; - uint32_t ttl; - uint16_t type; - size_t size; - - /* Check size */ - size = ntohs (msg->header.size); - if (size < - sizeof (struct GNUNET_MESH_Encrypted) + - sizeof (struct GNUNET_MessageHeader)) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - type = ntohs (msg->header.type); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n", - GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer)); - - /* Check connection */ - c = connection_get (&msg->cid); - if (NULL == c) - { - GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n"); - return GNUNET_OK; - } - t = c->t; - fc = fwd ? &c->bck_fc : &c->fwd_fc; - - /* Check if origin is as expected */ - neighbor = connection_get_hop (c, !fwd); - if (peer_get (peer)->id != neighbor->id) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - - /* Check PID */ - pid = ntohl (msg->pid); - if (GMC_is_pid_bigger (pid, fc->last_ack_sent)) - { - GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "WARNING Received PID %u, (prev %u), ACK %u\n", - pid, fc->last_pid_recv, fc->last_ack_sent); - return GNUNET_OK; - } - if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv)) - { - GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - " Pid %u not expected (%u+), dropping!\n", - pid, fc->last_pid_recv + 1); - return GNUNET_OK; - } - if (MESH_CONNECTION_SENT == c->state) - connection_change_state (c, MESH_CONNECTION_READY); - connection_reset_timeout (c, fwd); - fc->last_pid_recv = pid; - - /* Is this message for us? */ - if (GMC_is_terminal (c, fwd)) - { - size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted); - char cbuf[dsize]; - struct GNUNET_MessageHeader *msgh; - unsigned int off; - - /* TODO signature verification */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n"); - GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO); - - fc->last_pid_recv = pid; - tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd); - off = 0; - while (off < dsize) - { - msgh = (struct GNUNET_MessageHeader *) &cbuf[off]; - handle_decrypted (t, msgh, fwd); - off += ntohs (msgh->size); - } - send_ack (c, NULL, fwd); - return GNUNET_OK; - } - - /* Message not for us: forward to next hop */ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); - 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"); - send_ack (c, NULL, fwd); - return GNUNET_OK; - } - GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); - - send_prebuilt_message_connection (&msg->header, c, NULL, fwd); - - return GNUNET_OK; -} - - -/** - * Core handler for mesh network traffic going orig->dest. - * - * @param cls Closure (unused). - * @param message Message received. - * @param peer Peer who sent the message. - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_fwd (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - return handle_mesh_encrypted (peer, - (struct GNUNET_MESH_Encrypted *)message, - GNUNET_YES); -} - -/** - * Core handler for mesh network traffic going dest->orig. - * - * @param cls Closure (unused). - * @param message Message received. - * @param peer Peer who sent the message. - * - * @return GNUNET_OK to keep the connection open, - * GNUNET_SYSERR to close it (signal serious error) - */ -static int -handle_mesh_bck (void *cls, const struct GNUNET_PeerIdentity *peer, - const struct GNUNET_MessageHeader *message) -{ - return handle_mesh_encrypted (peer, - (struct GNUNET_MESH_Encrypted *)message, - GNUNET_NO); -} - - -/** - * 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 MeshConnection *c; - struct MeshFlowControl *fc; - GNUNET_PEER_Id id; - uint32_t ack; - int fwd; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n", - GNUNET_i2s (peer)); - msg = (struct GNUNET_MESH_ACK *) message; - - c = connection_get (&msg->cid); - - if (NULL == c) - { - GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1, - GNUNET_NO); - return GNUNET_OK; - } - - /* Is this a forward or backward ACK? */ - id = GNUNET_PEER_search (peer); - if (connection_get_next_hop (c)->id == id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); - fc = &c->fwd_fc; - fwd = GNUNET_YES; - } - else if (connection_get_prev_hop (c)->id == id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n"); - fc = &c->bck_fc; - fwd = GNUNET_NO; - } - else - { - GNUNET_break_op (0); - return GNUNET_OK; - } - - ack = ntohl (msg->ack); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n", - ack, fc->last_ack_recv); - if (GMC_is_pid_bigger (ack, fc->last_ack_recv)) - fc->last_ack_recv = ack; - - /* Cancel polling if the ACK is big enough. */ - if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task && - GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n"); - GNUNET_SCHEDULER_cancel (fc->poll_task); - fc->poll_task = GNUNET_SCHEDULER_NO_TASK; - fc->poll_time = GNUNET_TIME_UNIT_SECONDS; - } - - connection_unlock_queue (c, fwd); - - 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 MeshConnection *c; - struct MeshFlowControl *fc; - GNUNET_PEER_Id id; - uint32_t pid; - int fwd; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n"); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n", - GNUNET_i2s (peer)); - - msg = (struct GNUNET_MESH_Poll *) message; - - c = connection_get (&msg->cid); - - if (NULL == c) - { - GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1, - GNUNET_NO); - GNUNET_break_op (0); - return GNUNET_OK; - } - - /* Is this a forward or backward ACK? - * Note: a poll should never be needed in a loopback case, - * since there is no possiblility of packet loss there, so - * this way of discerining FWD/BCK should not be a problem. - */ - id = GNUNET_PEER_search (peer); - if (connection_get_next_hop (c)->id == id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); - fc = &c->fwd_fc; - } - else if (connection_get_prev_hop (c)->id == id) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n"); - fc = &c->bck_fc; - } - else - { - GNUNET_break_op (0); - return GNUNET_OK; - } - - pid = ntohl (msg->pid); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n", - pid, fc->last_pid_recv); - fc->last_pid_recv = pid; - fwd = fc == &c->fwd_fc; - send_ack (c, NULL, fwd); - - 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_ConnectionKeepAlive *msg; - struct MeshConnection *c; - struct MeshPeer *neighbor; - int fwd; - - msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n", - GNUNET_i2s (peer)); - - c = connection_get (&msg->cid); - if (NULL == c) - { - GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1, - GNUNET_NO); - return GNUNET_OK; - } - - fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ? - GNUNET_YES : GNUNET_NO; - - /* Check if origin is as expected */ - neighbor = connection_get_hop (c, fwd); - if (peer_get (peer)->id != neighbor->id) - { - GNUNET_break_op (0); - return GNUNET_OK; - } - - connection_change_state (c, MESH_CONNECTION_READY); - connection_reset_timeout (c, fwd); - - if (GMC_is_terminal (c, fwd)) - return GNUNET_OK; - - GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO); - send_prebuilt_message_connection (message, c, NULL, fwd); - - return GNUNET_OK; -} - - - -/** - * Functions to handle messages from core - */ -static struct GNUNET_CORE_MessageHandler core_handlers[] = { - {&handle_mesh_connection_create, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE, - 0}, - {&handle_mesh_connection_ack, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK, - sizeof (struct GNUNET_MESH_ConnectionACK)}, - {&handle_mesh_connection_broken, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN, - sizeof (struct GNUNET_MESH_ConnectionBroken)}, - {&handle_mesh_connection_destroy, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY, - sizeof (struct GNUNET_MESH_ConnectionDestroy)}, - {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE, - sizeof (struct GNUNET_MESH_ConnectionKeepAlive)}, - {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE, - sizeof (struct GNUNET_MESH_ConnectionKeepAlive)}, - {&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_fwd, GNUNET_MESSAGE_TYPE_MESH_FWD, 0}, - {&handle_mesh_bck, GNUNET_MESSAGE_TYPE_MESH_BCK, 0}, - {NULL, 0, 0} -}; - - /** * Function to process paths received for a new peer addition. The recorded * paths form the initial tunnel, which can be optimized later. @@ -3428,27 +2537,7 @@ core_init (void *cls, /************************ 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_PeerIdentity *key, - void *value) -{ - struct MeshPeer *p = value; - struct MeshTunnel2 *t = p->tunnel; - if (NULL != t) - tunnel_destroy (t); - return GNUNET_YES; -} /** @@ -3462,23 +2551,11 @@ 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; - } - GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL); - if (dht_handle != NULL) - { - GNUNET_DHT_disconnect (dht_handle); - dht_handle = NULL; - } GML_shutdown (); - if (GNUNET_SCHEDULER_NO_TASK != announce_id_task) - { - GNUNET_SCHEDULER_cancel (announce_id_task); - announce_id_task = GNUNET_SCHEDULER_NO_TASK; - } + GMD_shutdown (); + GMP_shutdown (); + GMC_shutdown (); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); } @@ -3498,16 +2575,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n"); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME", - &id_announce_time)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "MESH", "ID_ANNOUNCE_TIME", "MISSING"); - GNUNET_SCHEDULER_shutdown (); - return; - } - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (c, "MESH", "CONNECT_TIMEOUT", &connect_timeout)) @@ -3527,15 +2594,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, default_ttl = 64; } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS", - &max_peers)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, - "MESH", "MAX_PEERS", "USING DEFAULT"); - max_peers = 1000; - } - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DROP_PERCENT", &drop_percent)) @@ -3552,22 +2610,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, "***************************************\n"); } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DHT_REPLICATION_LEVEL", - &dht_replication_level)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, - "MESH", "DHT_REPLICATION_LEVEL", "USING DEFAULT"); - dht_replication_level = 3; - } - - peers = GNUNET_CONTAINER_multipeermap_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 */ @@ -3578,31 +2621,17 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_assert (NULL != pk); my_private_key = pk; GNUNET_CRYPTO_ecc_key_get_public_for_signature (my_private_key, - &my_full_id.public_key); + &my_full_id.public_key); myid = GNUNET_PEER_intern (&my_full_id); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Mesh for peer [%s] starting\n", GNUNET_i2s(&my_full_id)); - GML_init (server); - GMC_init (c); - - 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 (NULL == core_handle) - { - GNUNET_break (0); - GNUNET_SCHEDULER_shutdown (); - return; - } + GML_init (server); /* Local clients */ + GMC_init (c); /* Connections */ + GMP_init (c); /* Peers */ + GMD_init (c); /* DHT */ + announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n"); } diff --git a/src/mesh/gnunet-service-mesh_connection.c b/src/mesh/gnunet-service-mesh_connection.c index 93ba8766d..b4bb8b279 100644 --- a/src/mesh/gnunet-service-mesh_connection.c +++ b/src/mesh/gnunet-service-mesh_connection.c @@ -25,11 +25,30 @@ */ #include "platform.h" +#include "gnunet_util_lib.h" + #include "gnunet_core_service.h" + #include "gnunet-service-mesh_connection.h" +#include "gnunet-service-mesh_peer.h" +#include "mesh_protocol_enc.h" +#include "mesh_path.h" + +#define MESH_DEBUG_CONNECTION GNUNET_NO +#define MESH_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\ + GNUNET_TIME_UNIT_MINUTES,\ + 10) +#define MESH_RETRANSMIT_TIME GNUNET_TIME_UNIT_SECONDS +#define MESH_RETRANSMIT_MARGIN 4 +#if MESH_DEBUG_CONNECTION +#define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) +#else +#define DEBUG_CONN(...) +#endif + /** * All the states a connection can be in. @@ -239,10 +258,6 @@ struct MeshConnection }; - - - - /** * Connections known, indexed by cid (MeshConnection). */ @@ -265,7 +280,10 @@ static unsigned long long max_msgs_queue; */ static struct GNUNET_TIME_Relative refresh_connection_time; - +/** + * Handle to communicate with core. + */ +static struct GNUNET_CORE_Handle *core_handle; /** @@ -1464,6 +1482,732 @@ connection_reset_timeout (struct MeshConnection *c, int fwd) } + +/** + * Core handler for connection creation. + * + * @param cls Closure (unused). + * @param peer Sender (neighbor). + * @param message Message. + * + * @return GNUNET_OK to keep the connection open, + * GNUNET_SYSERR to close it (signal serious error) + */ +static int +handle_create (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) +{ + struct GNUNET_MESH_ConnectionCreate *msg; + struct GNUNET_PeerIdentity *id; + struct GNUNET_HashCode *cid; + struct MeshPeerPath *path; + struct MeshPeer *dest_peer; + struct MeshPeer *orig_peer; + struct MeshConnection *c; + unsigned int own_pos; + uint16_t size; + uint16_t i; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n"); + + /* Check size */ + size = ntohs (message->size); + if (size < sizeof (struct GNUNET_MESH_ConnectionCreate)) + { + GNUNET_break_op (0); + return GNUNET_OK; + } + + /* Calculate hops */ + size -= sizeof (struct GNUNET_MESH_ConnectionCreate); + if (size % sizeof (struct GNUNET_PeerIdentity)) + { + GNUNET_break_op (0); + return GNUNET_OK; + } + size /= sizeof (struct GNUNET_PeerIdentity); + if (1 > size) + { + GNUNET_break_op (0); + return GNUNET_OK; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); + + /* Get parameters */ + msg = (struct GNUNET_MESH_ConnectionCreate *) message; + cid = &msg->cid; + id = (struct GNUNET_PeerIdentity *) &msg[1]; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + " connection %s (%s).\n", + GNUNET_h2s (cid), GNUNET_i2s (id)); + + /* Create connection */ + c = connection_get (cid); + if (NULL == c) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n"); + c = connection_new (cid); + if (NULL == c) + return GNUNET_OK; + connection_reset_timeout (c, GNUNET_YES); + + /* Create path */ + 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 (&id[i])); + path->peers[i] = GNUNET_PEER_intern (&id[i]); + if (path->peers[i] == myid) + own_pos = i; + } + 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); + connection_destroy (c); + return GNUNET_OK; + } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos); + path_add_to_peers (path, GNUNET_NO); + c->path = path_duplicate (path); + c->own_pos = own_pos; + } + else + { + path = NULL; + } + if (MESH_CONNECTION_NEW == c->state) + connection_change_state (c, MESH_CONNECTION_SENT); + + /* Remember peers */ + dest_peer = peer_get (&id[size - 1]); + orig_peer = peer_get (&id[0]); + + /* Is it a connection to us? */ + if (c->own_pos == size - 1) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); + peer_add_path_to_origin (orig_peer, path, GNUNET_YES); + + if (NULL == orig_peer->tunnel) + { + orig_peer->tunnel = tunnel_new (); + orig_peer->tunnel->peer = orig_peer; + } + tunnel_add_connection (orig_peer->tunnel, c); + if (MESH_TUNNEL_NEW == c->t->state) + tunnel_change_state (c->t, MESH_TUNNEL_WAITING); + + send_connection_ack (c, GNUNET_NO); + if (MESH_CONNECTION_SENT == c->state) + connection_change_state (c, MESH_CONNECTION_ACK); + + /* Keep tunnel alive in direction dest->owner*/ + connection_reset_timeout (c, GNUNET_NO); + } + else + { + /* It's for somebody else! Retransmit. */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n"); + peer_add_path (dest_peer, path_duplicate (path), GNUNET_NO); + peer_add_path_to_origin (orig_peer, path, GNUNET_NO); + send_prebuilt_message_connection (message, c, NULL, GNUNET_YES); + } + return GNUNET_OK; +} + + +/** + * Core handler for path confirmations. + * + * @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_confirm (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) +{ + struct GNUNET_MESH_ConnectionACK *msg; + struct MeshConnection *c; + struct MeshPeerPath *p; + struct MeshPeer *pi; + int fwd; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n"); + msg = (struct GNUNET_MESH_ConnectionACK *) message; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n", + GNUNET_h2s (&msg->cid)); + c = connection_get (&msg->cid); + if (NULL == c) + { + GNUNET_STATISTICS_update (stats, "# control on unknown connection", + 1, GNUNET_NO); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the connection!\n"); + return GNUNET_OK; + } + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", + GNUNET_i2s (peer)); + pi = peer_get (peer); + if (connection_get_next_hop (c) == pi) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n"); + fwd = GNUNET_NO; + if (MESH_CONNECTION_SENT == c->state) + connection_change_state (c, MESH_CONNECTION_ACK); + } + else if (connection_get_prev_hop (c) == pi) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK\n"); + fwd = GNUNET_YES; + connection_change_state (c, MESH_CONNECTION_READY); + } + else + { + GNUNET_break_op (0); + return GNUNET_OK; + } + connection_reset_timeout (c, fwd); + + /* Add path to peers? */ + p = c->path; + if (NULL != p) + { + path_add_to_peers (p, GNUNET_YES); + } + else + { + GNUNET_break (0); + } + + /* Message for us as creator? */ + if (connection_is_origin (c, GNUNET_YES)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n"); + connection_change_state (c, MESH_CONNECTION_READY); + if (MESH_TUNNEL_READY != c->t->state) + tunnel_change_state (c->t, MESH_TUNNEL_READY); + send_connection_ack (c, GNUNET_YES); + tunnel_send_queued_data (c->t, GNUNET_YES); + if (3 <= tunnel_count_connections (c->t) && NULL != c->t->peer->dhtget) + { + GNUNET_DHT_get_stop (c->t->peer->dhtget); + c->t->peer->dhtget = NULL; + } + return GNUNET_OK; + } + + /* Message for us as destination? */ + if (GMC_is_terminal (c, GNUNET_YES)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n"); + if (MESH_TUNNEL_READY != c->t->state) + tunnel_change_state (c->t, MESH_TUNNEL_READY); + connection_change_state (c, MESH_CONNECTION_READY); + tunnel_send_queued_data (c->t, GNUNET_NO); + return GNUNET_OK; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); + send_prebuilt_message_connection (message, c, NULL, fwd); + return GNUNET_OK; +} + + +/** + * Core handler for notifications of broken paths + * + * @param cls Closure (unused). + * @param peer Peer identity of sending neighbor. + * @param message Message. + * + * @return GNUNET_OK to keep the connection open, + * GNUNET_SYSERR to close it (signal serious error) + */ +static int +handle_broken (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) +{ + struct GNUNET_MESH_ConnectionBroken *msg; + struct MeshConnection *c; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer)); + msg = (struct GNUNET_MESH_ConnectionBroken *) 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)); + c = connection_get (&msg->cid); + if (NULL == c) + { + GNUNET_break_op (0); + return GNUNET_OK; + } + tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1), + GNUNET_PEER_search (&msg->peer2)); + return GNUNET_OK; + +} + + +/** + * Core handler for tunnel destruction + * + * @param cls Closure (unused). + * @param peer Peer identity of sending neighbor. + * @param message Message. + * + * @return GNUNET_OK to keep the connection open, + * GNUNET_SYSERR to close it (signal serious error) + */ +static int +handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) +{ + struct GNUNET_MESH_ConnectionDestroy *msg; + struct MeshConnection *c; + GNUNET_PEER_Id id; + int fwd; + + msg = (struct GNUNET_MESH_ConnectionDestroy *) message; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got a CONNECTION DESTROY message from %s\n", + GNUNET_i2s (peer)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + " for connection %s\n", + GNUNET_h2s (&msg->cid)); + c = connection_get (&msg->cid); + if (NULL == c) + { + /* 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; + } + id = GNUNET_PEER_search (peer); + if (id == connection_get_prev_hop (c)->id) + fwd = GNUNET_YES; + else if (id == connection_get_next_hop (c)->id) + fwd = GNUNET_NO; + else + { + GNUNET_break_op (0); + return GNUNET_OK; + } + send_prebuilt_message_connection (message, c, NULL, fwd); + c->destroy = GNUNET_YES; + + return GNUNET_OK; +} + +/** + * Generic handler for mesh network encrypted traffic. + * + * @param peer Peer identity this notification is about. + * @param message Encrypted message. + * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO; + * + * @return GNUNET_OK to keep the connection open, + * GNUNET_SYSERR to close it (signal serious error) + */ +static int +handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MESH_Encrypted *msg, + int fwd) +{ + struct MeshConnection *c; + struct MeshTunnel2 *t; + struct MeshPeer *neighbor; + struct MeshFlowControl *fc; + uint32_t pid; + uint32_t ttl; + uint16_t type; + size_t size; + + /* Check size */ + size = ntohs (msg->header.size); + if (size < + sizeof (struct GNUNET_MESH_Encrypted) + + sizeof (struct GNUNET_MessageHeader)) + { + GNUNET_break_op (0); + return GNUNET_OK; + } + type = ntohs (msg->header.type); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n", + GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer)); + + /* Check connection */ + c = connection_get (&msg->cid); + if (NULL == c) + { + GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n"); + return GNUNET_OK; + } + t = c->t; + fc = fwd ? &c->bck_fc : &c->fwd_fc; + + /* Check if origin is as expected */ + neighbor = connection_get_hop (c, !fwd); + if (peer_get (peer)->id != neighbor->id) + { + GNUNET_break_op (0); + return GNUNET_OK; + } + + /* Check PID */ + pid = ntohl (msg->pid); + if (GMC_is_pid_bigger (pid, fc->last_ack_sent)) + { + GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "WARNING Received PID %u, (prev %u), ACK %u\n", + pid, fc->last_pid_recv, fc->last_ack_sent); + return GNUNET_OK; + } + if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv)) + { + GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + " Pid %u not expected (%u+), dropping!\n", + pid, fc->last_pid_recv + 1); + return GNUNET_OK; + } + if (MESH_CONNECTION_SENT == c->state) + connection_change_state (c, MESH_CONNECTION_READY); + connection_reset_timeout (c, fwd); + fc->last_pid_recv = pid; + + /* Is this message for us? */ + if (GMC_is_terminal (c, fwd)) + { + size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted); + char cbuf[dsize]; + struct GNUNET_MessageHeader *msgh; + unsigned int off; + + /* TODO signature verification */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n"); + GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO); + + fc->last_pid_recv = pid; + tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd); + off = 0; + while (off < dsize) + { + msgh = (struct GNUNET_MessageHeader *) &cbuf[off]; + handle_decrypted (t, msgh, fwd); + off += ntohs (msgh->size); + } + send_ack (c, NULL, fwd); + return GNUNET_OK; + } + + /* Message not for us: forward to next hop */ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); + 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"); + send_ack (c, NULL, fwd); + return GNUNET_OK; + } + GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); + + send_prebuilt_message_connection (&msg->header, c, NULL, fwd); + + return GNUNET_OK; +} + + +/** + * Core handler for mesh network traffic going orig->dest. + * + * @param cls Closure (unused). + * @param message Message received. + * @param peer Peer who sent the message. + * + * @return GNUNET_OK to keep the connection open, + * GNUNET_SYSERR to close it (signal serious error) + */ +static int +handle_fwd (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) +{ + return handle_mesh_encrypted (peer, + (struct GNUNET_MESH_Encrypted *)message, + GNUNET_YES); +} + +/** + * Core handler for mesh network traffic going dest->orig. + * + * @param cls Closure (unused). + * @param message Message received. + * @param peer Peer who sent the message. + * + * @return GNUNET_OK to keep the connection open, + * GNUNET_SYSERR to close it (signal serious error) + */ +static int +handle_bck (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) +{ + return handle_mesh_encrypted (peer, + (struct GNUNET_MESH_Encrypted *)message, + GNUNET_NO); +} + + +/** + * 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_ack (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) +{ + struct GNUNET_MESH_ACK *msg; + struct MeshConnection *c; + struct MeshFlowControl *fc; + GNUNET_PEER_Id id; + uint32_t ack; + int fwd; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n", + GNUNET_i2s (peer)); + msg = (struct GNUNET_MESH_ACK *) message; + + c = connection_get (&msg->cid); + + if (NULL == c) + { + GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1, + GNUNET_NO); + return GNUNET_OK; + } + + /* Is this a forward or backward ACK? */ + id = GNUNET_PEER_search (peer); + if (connection_get_next_hop (c)->id == id) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); + fc = &c->fwd_fc; + fwd = GNUNET_YES; + } + else if (connection_get_prev_hop (c)->id == id) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n"); + fc = &c->bck_fc; + fwd = GNUNET_NO; + } + else + { + GNUNET_break_op (0); + return GNUNET_OK; + } + + ack = ntohl (msg->ack); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n", + ack, fc->last_ack_recv); + if (GMC_is_pid_bigger (ack, fc->last_ack_recv)) + fc->last_ack_recv = ack; + + /* Cancel polling if the ACK is big enough. */ + if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task && + GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n"); + GNUNET_SCHEDULER_cancel (fc->poll_task); + fc->poll_task = GNUNET_SCHEDULER_NO_TASK; + fc->poll_time = GNUNET_TIME_UNIT_SECONDS; + } + + connection_unlock_queue (c, fwd); + + 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_poll (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) +{ + struct GNUNET_MESH_Poll *msg; + struct MeshConnection *c; + struct MeshFlowControl *fc; + GNUNET_PEER_Id id; + uint32_t pid; + int fwd; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n", + GNUNET_i2s (peer)); + + msg = (struct GNUNET_MESH_Poll *) message; + + c = connection_get (&msg->cid); + + if (NULL == c) + { + GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1, + GNUNET_NO); + GNUNET_break_op (0); + return GNUNET_OK; + } + + /* Is this a forward or backward ACK? + * Note: a poll should never be needed in a loopback case, + * since there is no possiblility of packet loss there, so + * this way of discerining FWD/BCK should not be a problem. + */ + id = GNUNET_PEER_search (peer); + if (connection_get_next_hop (c)->id == id) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); + fc = &c->fwd_fc; + } + else if (connection_get_prev_hop (c)->id == id) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n"); + fc = &c->bck_fc; + } + else + { + GNUNET_break_op (0); + return GNUNET_OK; + } + + pid = ntohl (msg->pid); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n", + pid, fc->last_pid_recv); + fc->last_pid_recv = pid; + fwd = fc == &c->fwd_fc; + send_ack (c, NULL, fwd); + + 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_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_MessageHeader *message) +{ + struct GNUNET_MESH_ConnectionKeepAlive *msg; + struct MeshConnection *c; + struct MeshPeer *neighbor; + int fwd; + + msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n", + GNUNET_i2s (peer)); + + c = connection_get (&msg->cid); + if (NULL == c) + { + GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1, + GNUNET_NO); + return GNUNET_OK; + } + + fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ? + GNUNET_YES : GNUNET_NO; + + /* Check if origin is as expected */ + neighbor = connection_get_hop (c, fwd); + if (peer_get (peer)->id != neighbor->id) + { + GNUNET_break_op (0); + return GNUNET_OK; + } + + connection_change_state (c, MESH_CONNECTION_READY); + connection_reset_timeout (c, fwd); + + if (GMC_is_terminal (c, fwd)) + return GNUNET_OK; + + GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO); + send_prebuilt_message_connection (message, c, NULL, fwd); + + return GNUNET_OK; +} + + +/** + * Functions to handle messages from core + */ +static struct GNUNET_CORE_MessageHandler core_handlers[] = { + {&handle_create, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE, + 0}, + {&handle_confirm, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK, + sizeof (struct GNUNET_MESH_ConnectionACK)}, + {&handle_broken, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN, + sizeof (struct GNUNET_MESH_ConnectionBroken)}, + {&handle_destroy, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY, + sizeof (struct GNUNET_MESH_ConnectionDestroy)}, + {&handle_keepalive, GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE, + sizeof (struct GNUNET_MESH_ConnectionKeepAlive)}, + {&handle_keepalive, GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE, + sizeof (struct GNUNET_MESH_ConnectionKeepAlive)}, + {&handle_ack, GNUNET_MESSAGE_TYPE_MESH_ACK, + sizeof (struct GNUNET_MESH_ACK)}, + {&handle_poll, GNUNET_MESSAGE_TYPE_MESH_POLL, + sizeof (struct GNUNET_MESH_Poll)}, + {&handle_fwd, GNUNET_MESSAGE_TYPE_MESH_FWD, 0}, + {&handle_bck, GNUNET_MESSAGE_TYPE_MESH_BCK, 0}, + {NULL, 0, 0} +}; + + + /** * Iterator to notify all connections of a broken link. Mark connections * to destroy after all traffic has been sent. @@ -1513,7 +2257,7 @@ GMC_notify_broken (void *cls, * @param c Configuration handle. */ void -GMC_init (struct GNUNET_CONFIGURATION_Handle *c) +GMC_init (const struct GNUNET_CONFIGURATION_Handle *c) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE", @@ -1545,6 +2289,36 @@ GMC_init (struct GNUNET_CONFIGURATION_Handle *c) return; } connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES); + + 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 (NULL == core_handle) + { + GNUNET_break (0); + GNUNET_SCHEDULER_shutdown (); + return; + } +} + +/** + * Shut down the connections subsystem. + */ +void +GMC_shutdown (void) +{ + if (core_handle != NULL) + { + GNUNET_CORE_disconnect (core_handle); + core_handle = NULL; + } } @@ -1580,4 +2354,4 @@ int GMC_is_terminal (struct MeshConnection *c, int fwd) { return GMC_is_origin (c, !fwd); -} \ No newline at end of file +} diff --git a/src/mesh/gnunet-service-mesh_connection.h b/src/mesh/gnunet-service-mesh_connection.h index a1715e3cd..5db12f2fb 100644 --- a/src/mesh/gnunet-service-mesh_connection.h +++ b/src/mesh/gnunet-service-mesh_connection.h @@ -39,7 +39,9 @@ extern "C" #include "gnunet_util_lib.h" - +/** + * Struct containing all information regarding a connection to a peer. + */ struct MeshConnection; /** @@ -48,7 +50,13 @@ struct MeshConnection; * @param c Configuration handle. */ void -GMC_init (struct GNUNET_CONFIGURATION_Handle *c); +GMC_init (const struct GNUNET_CONFIGURATION_Handle *c); + +/** + * Shut down the connections subsystem. + */ +void +GMC_shutdown (void); /** * Create a connection. @@ -185,6 +193,7 @@ int GMC_is_terminal (struct MeshConnection *c, int fwd); + #if 0 /* keep Emacsens' auto-indent happy */ { #endif diff --git a/src/mesh/gnunet-service-mesh_dht.c b/src/mesh/gnunet-service-mesh_dht.c new file mode 100644 index 000000000..710b95f45 --- /dev/null +++ b/src/mesh/gnunet-service-mesh_dht.c @@ -0,0 +1,183 @@ +/* + This file is part of GNUnet. + (C) 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. +*/ + + +#include "platform.h" +#include "gnunet_util_lib.h" + +#include "gnunet_dht_service.h" + +#include "gnunet-service-mesh_dht.h" +#include "gnunet-service-mesh_peer.h" + +#define MESH_DEBUG_DHT GNUNET_NO + +#if MESH_DEBUG_DHT +#define DEBUG_DHT(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__) +#else +#define DEBUG_DHT(...) +#endif + +/******************************************************************************/ +/******************************** STRUCTS **********************************/ +/******************************************************************************/ + + + + +/******************************************************************************/ +/******************************* GLOBALS ***********************************/ +/******************************************************************************/ + +/** + * Handle to use DHT. + */ +static struct GNUNET_DHT_Handle *dht_handle; + +/** + * How often to PUT own ID in the DHT. + */ +static struct GNUNET_TIME_Relative id_announce_time; + +/** + * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put. + */ +static unsigned long long dht_replication_level; + +/** + * Task to periodically announce itself in the network. + */ +static GNUNET_SCHEDULER_TaskIdentifier announce_id_task; + +/** + * Own ID (full value). + */ +static struct GNUNET_PeerIdentity *id; + +/** + * Own private key. + */ +static struct GNUNET_CRYPTO_EccPrivateKey *private_key; + + +/******************************************************************************/ +/******************************** STATIC ***********************************/ +/******************************************************************************/ + + +/** + * 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; + struct GNUNET_HashCode phash; + + 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; + GNUNET_CRYPTO_hash (&my_full_id, sizeof (struct GNUNET_PeerIdentity), &phash); + GNUNET_DHT_put (dht_handle, /* DHT handle */ + &phash, /* 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); +} + + +/******************************************************************************/ +/******************************** API ***********************************/ +/******************************************************************************/ + +/** + * Initialize the DHT subsystem. + * + * @param c Configuration. + */ +void +GMD_init (const struct GNUNET_CONFIGURATION_Handle *c) +{ + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DHT_REPLICATION_LEVEL", + &dht_replication_level)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, + "MESH", "DHT_REPLICATION_LEVEL", "USING DEFAULT"); + dht_replication_level = 3; + } + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME", + &id_announce_time)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + "MESH", "ID_ANNOUNCE_TIME", "MISSING"); + GNUNET_SCHEDULER_shutdown (); + return; + } + + dht_handle = GNUNET_DHT_connect (c, 64); + if (NULL == dht_handle) + { + GNUNET_break (0); + } + + announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls); +} + + +/** + * Shut down the DHT subsystem. + */ +void +GMD_shutdown(void ) +{ + if (dht_handle != NULL) + { + GNUNET_DHT_disconnect (dht_handle); + dht_handle = NULL; + } + if (GNUNET_SCHEDULER_NO_TASK != announce_id_task) + { + GNUNET_SCHEDULER_cancel (announce_id_task); + announce_id_task = GNUNET_SCHEDULER_NO_TASK; + } +} diff --git a/src/mesh/gnunet-service-mesh_dht.h b/src/mesh/gnunet-service-mesh_dht.h new file mode 100644 index 000000000..d491020bf --- /dev/null +++ b/src/mesh/gnunet-service-mesh_dht.h @@ -0,0 +1,71 @@ +/* + This file is part of GNUnet. + (C) 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_dht.h + * @brief mesh service; dealing with DHT requests and results + * @author Bartlomiej Polot + * + * All functions in this file should use the prefix GMD (Gnunet Mesh Dht) + */ + +#ifndef GNUNET_SERVICE_MESH_DHT_H +#define GNUNET_SERVICE_MESH_DHT_H + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + +#include "platform.h" +#include "gnunet_util_lib.h" + + +/******************************************************************************/ +/******************************** API ***********************************/ +/******************************************************************************/ + +/** + * Initialize DHT subsystem. + * + * @param c Configuration. + */ +void +GMD_init (const struct GNUNET_CONFIGURATION_Handle *c); + +/** + * Shut down the DHT subsystem. + */ +void +GMD_shutdown (void); + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + +/* ifndef GNUNET_MESH_SERVICE_LOCAL_H */ +#endif +/* end of gnunet-mesh-service_LOCAL.h */ \ No newline at end of file diff --git a/src/mesh/gnunet-service-mesh_local.c b/src/mesh/gnunet-service-mesh_local.c index 762264e0c..989def211 100644 --- a/src/mesh/gnunet-service-mesh_local.c +++ b/src/mesh/gnunet-service-mesh_local.c @@ -789,16 +789,9 @@ static struct GNUNET_SERVER_MessageHandler client_handlers[] = { /******************************** API ***********************************/ /******************************************************************************/ -void -GML_init (void) -{ - ports = GNUNET_CONTAINER_multihashmap32_create (32); -} - - /** * Initialize server subsystem. - * + * * @param handle Server handle. */ void @@ -806,6 +799,7 @@ GML_init (struct GNUNET_SERVER_Handle *handle) { server_handle = handle; GNUNET_SERVER_suspend (server_handle); + ports = GNUNET_CONTAINER_multihashmap32_create (32); } /** diff --git a/src/mesh/gnunet-service-mesh_local.h b/src/mesh/gnunet-service-mesh_local.h index 7779c6507..b3a7ad621 100644 --- a/src/mesh/gnunet-service-mesh_local.h +++ b/src/mesh/gnunet-service-mesh_local.h @@ -21,7 +21,7 @@ /** * @file mesh/gnunet-service-mesh_local.h * @brief mesh service; dealing with local clients - * @author Bart Polot + * @author Bartlomiej Polot * * All functions in this file should use the prefix GML (Gnunet Mesh Local) */ @@ -37,7 +37,9 @@ extern "C" #endif #endif +#include "platform.h" #include "gnunet_util_lib.h" + #include "gnunet-service-mesh_channel.h" /** diff --git a/src/mesh/gnunet-service-mesh_peer.c b/src/mesh/gnunet-service-mesh_peer.c new file mode 100644 index 000000000..904e1957e --- /dev/null +++ b/src/mesh/gnunet-service-mesh_peer.c @@ -0,0 +1,166 @@ +/* + This file is part of GNUnet. + (C) 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. +*/ + + +#include "platform.h" +#include "gnunet_util_lib.h" + +#include "gnunet-service-mesh_peer.h" + +/******************************************************************************/ +/******************************** STRUCTS **********************************/ +/******************************************************************************/ + +/** + * Struct containing all information regarding a given peer + */ +struct MeshPeer +{ + /** + * ID of the peer + */ + GNUNET_PEER_Id id; + + /** + * Last time we heard from this peer + */ + struct GNUNET_TIME_Absolute last_contact; + + /** + * 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 paths to this peer + */ + struct GNUNET_DHT_GetHandle *dhtget; + + /** + * Tunnel to this peer, if any. + */ + struct MeshTunnel2 *tunnel; + + /** + * Connections that go through this peer, indexed by tid; + */ + struct GNUNET_CONTAINER_MultiHashMap *connections; + + /** + * Handle for queued transmissions + */ + struct GNUNET_CORE_TransmitHandle *core_transmit; + + /** + * 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; +}; + + +/******************************************************************************/ +/******************************* GLOBALS ***********************************/ +/******************************************************************************/ + +/** + * Peers known, indexed by PeerIdentity (MeshPeer). + */ +static struct GNUNET_CONTAINER_MultiPeerMap *peers; + +/** + * How many peers do we want to remember? + */ +static unsigned long long max_peers; + + +/******************************************************************************/ +/******************************** STATIC ***********************************/ +/******************************************************************************/ + +/** + * 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_PeerIdentity *key, + void *value) +{ + struct MeshPeer *p = value; + struct MeshTunnel2 *t = p->tunnel; + + if (NULL != t) + GMT_destroy (t); + return GNUNET_YES; +} + + +/******************************************************************************/ +/******************************** API ***********************************/ +/******************************************************************************/ + +/** + * Initialize the peer subsystem. + * + * @param c Configuration. + */ +void +GMP_init (const struct GNUNET_CONFIGURATION_Handle *c) +{ + peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS", + &max_peers)) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, + "MESH", "MAX_PEERS", "USING DEFAULT"); + max_peers = 1000; + } +} + +/** + * Shut down the peer subsystem. + */ +void +GMP_shutdown (void) +{ + GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL); +} + diff --git a/src/mesh/gnunet-service-mesh_peer.h b/src/mesh/gnunet-service-mesh_peer.h new file mode 100644 index 000000000..1f829b48f --- /dev/null +++ b/src/mesh/gnunet-service-mesh_peer.h @@ -0,0 +1,77 @@ +/* + This file is part of GNUnet. + (C) 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_peer.h + * @brief mesh service; dealing with remote peers + * @author Bartlomiej Polot + * + * All functions in this file should use the prefix GMP (Gnunet Mesh Peer) + */ + +#ifndef GNUNET_SERVICE_MESH_PEER_H +#define GNUNET_SERVICE_MESH_PEER_H + +#ifdef __cplusplus +extern "C" +{ +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + +#include "platform.h" +#include "gnunet_util_lib.h" + +/** + * Struct containing all information regarding a given peer + */ +struct MeshPeer; + + +/******************************************************************************/ +/******************************** API ***********************************/ +/******************************************************************************/ + +/** + * Initialize peer subsystem. + * + * @param c Configuration. + */ +void +GMP_init (const struct GNUNET_CONFIGURATION_Handle *c); + +/** + * Shut down the peer subsystem. + */ +void +GMP_shutdown (void); + + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + +/* ifndef GNUNET_MESH_SERVICE_PEER_H */ +#endif +/* end of gnunet-mesh-service_peer.h */ \ No newline at end of file -- 2.25.1