aboutsummaryrefslogtreecommitdiff
path: root/src/transport
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport')
-rw-r--r--src/transport/Makefile.am4
-rw-r--r--src/transport/Makefile.in88
-rw-r--r--src/transport/gnunet-helper-transport-wlan-dummy.c302
-rw-r--r--src/transport/gnunet-helper-transport-wlan.c1453
-rw-r--r--src/transport/gnunet-service-transport.c61
-rw-r--r--src/transport/gnunet-service-transport_blacklist.c55
-rw-r--r--src/transport/gnunet-service-transport_blacklist.h2
-rw-r--r--src/transport/gnunet-service-transport_clients.c36
-rw-r--r--src/transport/gnunet-service-transport_hello.c17
-rw-r--r--src/transport/gnunet-service-transport_neighbours.c4102
-rw-r--r--src/transport/gnunet-service-transport_neighbours.h30
-rw-r--r--src/transport/gnunet-service-transport_validation.c53
-rw-r--r--src/transport/gnunet-service-transport_validation.h7
-rwxr-xr-xsrc/transport/gnunet-transport-certificate-creation2
-rw-r--r--src/transport/gnunet-transport-certificate-creation.c4
-rw-r--r--src/transport/gnunet-transport-wlan-sender.c80
-rw-r--r--src/transport/gnunet-transport.c51
-rw-r--r--src/transport/plugin_transport_http.c452
-rw-r--r--src/transport/plugin_transport_http.h63
-rw-r--r--src/transport/plugin_transport_http_client.c199
-rw-r--r--src/transport/plugin_transport_http_server.c269
-rw-r--r--src/transport/plugin_transport_tcp.c876
-rw-r--r--src/transport/plugin_transport_udp.c783
-rw-r--r--src/transport/plugin_transport_udp_broadcasting.c106
-rw-r--r--src/transport/plugin_transport_unix.c572
-rw-r--r--src/transport/plugin_transport_wlan.c3727
-rw-r--r--src/transport/plugin_transport_wlan.h167
-rw-r--r--src/transport/template_cfg_peer1.conf3
-rw-r--r--src/transport/template_cfg_peer2.conf3
-rw-r--r--src/transport/test_quota_compliance_tcp_asymmetric_peer1.conf1
-rw-r--r--src/transport/test_quota_compliance_tcp_asymmetric_peer2.conf1
-rw-r--r--src/transport/test_quota_compliance_tcp_peer1.conf1
-rw-r--r--src/transport/test_quota_compliance_tcp_peer2.conf1
-rw-r--r--src/transport/test_transport_api.c58
-rw-r--r--src/transport/test_transport_api_bidirectional_connect.c58
-rw-r--r--src/transport/test_transport_api_bidirectional_connect_peer1.conf33
-rw-r--r--src/transport/test_transport_api_bidirectional_connect_peer2.conf31
-rw-r--r--src/transport/test_transport_api_blacklisting.c18
-rw-r--r--src/transport/test_transport_api_disconnect_tcp_peer1.conf1
-rw-r--r--src/transport/test_transport_api_disconnect_tcp_peer2.conf1
-rw-r--r--src/transport/test_transport_api_limited_sockets.c26
-rw-r--r--src/transport/test_transport_api_limited_sockets_tcp_peer1.conf1
-rw-r--r--src/transport/test_transport_api_limited_sockets_tcp_peer2.conf1
-rw-r--r--src/transport/test_transport_api_reliability.c2
-rw-r--r--src/transport/test_transport_api_reliability_tcp_nat_peer1.conf1
-rw-r--r--src/transport/test_transport_api_reliability_tcp_nat_peer2.conf1
-rw-r--r--src/transport/test_transport_api_reliability_tcp_peer1.conf1
-rw-r--r--src/transport/test_transport_api_reliability_tcp_peer2.conf1
-rw-r--r--src/transport/test_transport_api_restart_1peer.c55
-rw-r--r--src/transport/test_transport_api_restart_2peers.c70
-rw-r--r--src/transport/test_transport_api_tcp_nat_peer1.conf1
-rw-r--r--src/transport/test_transport_api_tcp_nat_peer2.conf1
-rw-r--r--src/transport/test_transport_api_tcp_peer1.conf1
-rw-r--r--src/transport/test_transport_api_tcp_peer2.conf1
-rw-r--r--src/transport/test_transport_api_timeout.c27
-rw-r--r--src/transport/test_transport_api_timeout_tcp_peer1.conf1
-rw-r--r--src/transport/test_transport_api_timeout_tcp_peer2.conf1
-rw-r--r--src/transport/test_transport_defaults.conf6
-rw-r--r--src/transport/transport-testing.c103
-rw-r--r--src/transport/transport.conf.in4
-rw-r--r--src/transport/transport.h7
-rw-r--r--src/transport/transport_api.c54
-rw-r--r--src/transport/transport_api_address_lookup.c10
-rw-r--r--src/transport/transport_api_address_to_string.c14
-rw-r--r--src/transport/transport_api_blacklist.c4
65 files changed, 7348 insertions, 6817 deletions
diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am
index 0692450..b040874 100644
--- a/src/transport/Makefile.am
+++ b/src/transport/Makefile.am
@@ -61,7 +61,6 @@ UNIX_QUOTA_TEST = test_quota_compliance_unix \
endif
noinst_PROGRAMS = \
- $(WLAN_BIN_DUMMY) \
$(WLAN_BIN_SENDER)
# gnunet-transport-connect-running-peers
@@ -92,11 +91,12 @@ libgnunettransport_la_LIBADD = \
$(GN_LIBINTL)
libgnunettransport_la_LDFLAGS = \
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
- -version-info 0:0:0
+ -version-info 1:0:0
bin_PROGRAMS = \
gnunet-transport \
$(WLAN_BIN) \
+ $(WLAN_BIN_DUMMY) \
gnunet-service-transport \
gnunet-transport-certificate-creation
diff --git a/src/transport/Makefile.in b/src/transport/Makefile.in
index 36df686..b5f2c64 100644
--- a/src/transport/Makefile.in
+++ b/src/transport/Makefile.in
@@ -37,9 +37,9 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
-noinst_PROGRAMS = $(am__EXEEXT_21) $(am__EXEEXT_22)
+noinst_PROGRAMS = $(am__EXEEXT_22)
bin_PROGRAMS = gnunet-transport$(EXEEXT) $(am__EXEEXT_1) \
- gnunet-service-transport$(EXEEXT) \
+ $(am__EXEEXT_2) gnunet-service-transport$(EXEEXT) \
gnunet-transport-certificate-creation$(EXEEXT)
check_PROGRAMS = test_transport_testing$(EXEEXT) \
test_transport_startonly$(EXEEXT) \
@@ -53,22 +53,22 @@ check_PROGRAMS = test_transport_testing$(EXEEXT) \
test_transport_api_limited_sockets_tcp$(EXEEXT) \
test_transport_api_tcp_nat$(EXEEXT) \
test_transport_api_udp$(EXEEXT) \
- test_transport_api_timeout_udp$(EXEEXT) $(am__EXEEXT_2) \
- $(am__EXEEXT_3) test_transport_api_udp_nat$(EXEEXT) \
- $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \
- $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_9) \
+ test_transport_api_timeout_udp$(EXEEXT) $(am__EXEEXT_3) \
+ $(am__EXEEXT_4) test_transport_api_udp_nat$(EXEEXT) \
+ $(am__EXEEXT_5) $(am__EXEEXT_6) $(am__EXEEXT_7) \
+ $(am__EXEEXT_8) $(am__EXEEXT_9) $(am__EXEEXT_10) \
test_transport_api_multi$(EXEEXT) \
test_transport_api_reliability_tcp$(EXEEXT) \
test_transport_api_reliability_tcp_nat$(EXEEXT) \
test_transport_api_unreliability_udp$(EXEEXT) \
test_transport_api_unreliability_constant_udp$(EXEEXT) \
- $(am__EXEEXT_10) $(am__EXEEXT_11) $(am__EXEEXT_12) \
- $(am__EXEEXT_13) $(am__EXEEXT_14) \
+ $(am__EXEEXT_11) $(am__EXEEXT_12) $(am__EXEEXT_13) \
+ $(am__EXEEXT_14) $(am__EXEEXT_15) \
test_quota_compliance_tcp$(EXEEXT) \
test_quota_compliance_tcp_asymmetric$(EXEEXT) \
- test_quota_compliance_udp$(EXEEXT) $(am__EXEEXT_15) \
- $(am__EXEEXT_16) $(am__EXEEXT_17) $(am__EXEEXT_18) \
- $(am__EXEEXT_19) $(am__EXEEXT_20)
+ test_quota_compliance_udp$(EXEEXT) $(am__EXEEXT_16) \
+ $(am__EXEEXT_17) $(am__EXEEXT_18) $(am__EXEEXT_19) \
+ $(am__EXEEXT_20) $(am__EXEEXT_21)
@ENABLE_TEST_RUN_TRUE@TESTS = test_transport_testing$(EXEEXT) \
@ENABLE_TEST_RUN_TRUE@ test_transport_startonly$(EXEEXT) \
@ENABLE_TEST_RUN_TRUE@ test_transport_api_blacklisting$(EXEEXT) \
@@ -82,25 +82,25 @@ check_PROGRAMS = test_transport_testing$(EXEEXT) \
@ENABLE_TEST_RUN_TRUE@ test_transport_api_tcp_nat$(EXEEXT) \
@ENABLE_TEST_RUN_TRUE@ test_transport_api_udp$(EXEEXT) \
@ENABLE_TEST_RUN_TRUE@ test_transport_api_timeout_udp$(EXEEXT) \
-@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_2) $(am__EXEEXT_3) \
+@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_3) $(am__EXEEXT_4) \
@ENABLE_TEST_RUN_TRUE@ test_transport_api_udp_nat$(EXEEXT) \
-@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_4) $(am__EXEEXT_5) \
-@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_6) $(am__EXEEXT_7) \
-@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_8) $(am__EXEEXT_9) \
+@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_5) $(am__EXEEXT_6) \
+@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_7) $(am__EXEEXT_8) \
+@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_9) $(am__EXEEXT_10) \
@ENABLE_TEST_RUN_TRUE@ test_transport_api_multi$(EXEEXT) \
@ENABLE_TEST_RUN_TRUE@ test_transport_api_reliability_tcp$(EXEEXT) \
@ENABLE_TEST_RUN_TRUE@ test_transport_api_reliability_tcp_nat$(EXEEXT) \
@ENABLE_TEST_RUN_TRUE@ test_transport_api_unreliability_udp$(EXEEXT) \
@ENABLE_TEST_RUN_TRUE@ test_transport_api_unreliability_constant_udp$(EXEEXT) \
-@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_10) $(am__EXEEXT_11) \
-@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_12) $(am__EXEEXT_13) \
-@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_14) \
+@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_11) $(am__EXEEXT_12) \
+@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_13) $(am__EXEEXT_14) \
+@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_15) \
@ENABLE_TEST_RUN_TRUE@ test_quota_compliance_tcp$(EXEEXT) \
@ENABLE_TEST_RUN_TRUE@ test_quota_compliance_tcp_asymmetric$(EXEEXT) \
@ENABLE_TEST_RUN_TRUE@ test_quota_compliance_udp$(EXEEXT) \
-@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_15) $(am__EXEEXT_16) \
-@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_17) $(am__EXEEXT_18) \
-@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_19) $(am__EXEEXT_20)
+@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_16) $(am__EXEEXT_17) \
+@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_18) $(am__EXEEXT_19) \
+@ENABLE_TEST_RUN_TRUE@ $(am__EXEEXT_20) $(am__EXEEXT_21)
subdir = src/transport
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/transport.conf.in
@@ -279,37 +279,37 @@ libgnunettransporttesting_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_CFLAGS) $(CFLAGS) $(libgnunettransporttesting_la_LDFLAGS) \
$(LDFLAGS) -o $@
@LINUX_TRUE@am__EXEEXT_1 = gnunet-helper-transport-wlan$(EXEEXT)
-@MINGW_FALSE@am__EXEEXT_2 = test_transport_api_unix$(EXEEXT)
-@MINGW_FALSE@am__EXEEXT_3 = test_transport_api_timeout_unix$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_4 = test_transport_api_http$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_5 = test_transport_api_http_nat$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_6 = \
+@LINUX_TRUE@am__EXEEXT_2 = \
+@LINUX_TRUE@ gnunet-helper-transport-wlan-dummy$(EXEEXT)
+@MINGW_FALSE@am__EXEEXT_3 = test_transport_api_unix$(EXEEXT)
+@MINGW_FALSE@am__EXEEXT_4 = test_transport_api_timeout_unix$(EXEEXT)
+@HAVE_MHD_TRUE@am__EXEEXT_5 = test_transport_api_http$(EXEEXT)
+@HAVE_MHD_TRUE@am__EXEEXT_6 = test_transport_api_http_nat$(EXEEXT)
+@HAVE_MHD_TRUE@am__EXEEXT_7 = \
@HAVE_MHD_TRUE@ test_transport_api_timeout_http$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_7 = test_transport_api_https$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_8 = test_transport_api_https_nat$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_9 = \
+@HAVE_MHD_TRUE@am__EXEEXT_8 = test_transport_api_https$(EXEEXT)
+@HAVE_MHD_TRUE@am__EXEEXT_9 = test_transport_api_https_nat$(EXEEXT)
+@HAVE_MHD_TRUE@am__EXEEXT_10 = \
@HAVE_MHD_TRUE@ test_transport_api_timeout_https$(EXEEXT)
-@MINGW_FALSE@am__EXEEXT_10 = \
+@MINGW_FALSE@am__EXEEXT_11 = \
@MINGW_FALSE@ test_transport_api_unreliability_unix$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_11 = \
+@HAVE_MHD_TRUE@am__EXEEXT_12 = \
@HAVE_MHD_TRUE@ test_transport_api_reliability_http$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_12 = test_transport_api_reliability_http_nat$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_13 = \
+@HAVE_MHD_TRUE@am__EXEEXT_13 = test_transport_api_reliability_http_nat$(EXEEXT)
+@HAVE_MHD_TRUE@am__EXEEXT_14 = \
@HAVE_MHD_TRUE@ test_transport_api_reliability_https$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_14 = test_transport_api_reliability_https_nat$(EXEEXT)
-@MINGW_FALSE@am__EXEEXT_15 = test_quota_compliance_unix$(EXEEXT) \
+@HAVE_MHD_TRUE@am__EXEEXT_15 = test_transport_api_reliability_https_nat$(EXEEXT)
+@MINGW_FALSE@am__EXEEXT_16 = test_quota_compliance_unix$(EXEEXT) \
@MINGW_FALSE@ test_quota_compliance_unix_asymmetric$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_16 = test_quota_compliance_http$(EXEEXT) \
+@HAVE_MHD_TRUE@am__EXEEXT_17 = test_quota_compliance_http$(EXEEXT) \
@HAVE_MHD_TRUE@ test_quota_compliance_http_asymmetric$(EXEEXT)
-@HAVE_MHD_TRUE@am__EXEEXT_17 = test_quota_compliance_https$(EXEEXT) \
+@HAVE_MHD_TRUE@am__EXEEXT_18 = test_quota_compliance_https$(EXEEXT) \
@HAVE_MHD_TRUE@ test_quota_compliance_https_asymmetric$(EXEEXT)
-@LINUX_TRUE@am__EXEEXT_18 = test_transport_api_wlan$(EXEEXT)
-@LINUX_TRUE@am__EXEEXT_19 = \
-@LINUX_TRUE@ test_transport_api_reliability_wlan$(EXEEXT)
+@LINUX_TRUE@am__EXEEXT_19 = test_transport_api_wlan$(EXEEXT)
@LINUX_TRUE@am__EXEEXT_20 = \
-@LINUX_TRUE@ test_transport_api_unreliability_wlan$(EXEEXT)
+@LINUX_TRUE@ test_transport_api_reliability_wlan$(EXEEXT)
@LINUX_TRUE@am__EXEEXT_21 = \
-@LINUX_TRUE@ gnunet-helper-transport-wlan-dummy$(EXEEXT)
+@LINUX_TRUE@ test_transport_api_unreliability_wlan$(EXEEXT)
@LINUX_TRUE@am__EXEEXT_22 = gnunet-transport-wlan-sender$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
am_gnunet_helper_transport_wlan_OBJECTS = \
@@ -947,6 +947,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+JAVAPORT = @JAVAPORT@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBADD_DL = @LIBADD_DL@
@@ -980,6 +981,7 @@ LT_DLLOADERS = @LT_DLLOADERS@
LT_DLPREOPEN = @LT_DLPREOPEN@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
+MONKEYPREFIX = @MONKEYPREFIX@
MSGFMT = @MSGFMT@
MSGFMT_015 = @MSGFMT_015@
MSGMERGE = @MSGMERGE@
@@ -1169,7 +1171,7 @@ libgnunettransport_la_LIBADD = \
libgnunettransport_la_LDFLAGS = \
$(GN_LIB_LDFLAGS) $(WINFLAGS) \
- -version-info 0:0:0
+ -version-info 1:0:0
#bin_SCRIPTS = \
diff --git a/src/transport/gnunet-helper-transport-wlan-dummy.c b/src/transport/gnunet-helper-transport-wlan-dummy.c
index 6fff758..a7015ac 100644
--- a/src/transport/gnunet-helper-transport-wlan-dummy.c
+++ b/src/transport/gnunet-helper-transport-wlan-dummy.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2010 Christian Grothoff (and other contributing authors)
+ (C) 2010, 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
@@ -27,22 +27,60 @@
#include "gnunet_util_lib.h"
#include "plugin_transport_wlan.h"
-#define FIFO_FILE1 "/tmp/test-transport/api-wlan-p1/WLAN_FIFO_in"
-#define FIFO_FILE2 "/tmp/test-transport/api-wlan-p1/WLAN_FIFO_out"
+/**
+ * Name of the fifo to use for IPC with the other dummy process.
+ */
+#define FIFO_FILE1 "/tmp/test-transport/api-wlan-p1/WLAN_FIFO_in"
+
+/**
+ * Name of the fifo to use for IPC with the other dummy process.
+ */
+#define FIFO_FILE2 "/tmp/test-transport/api-wlan-p1/WLAN_FIFO_out"
+/**
+ * Maximum size of a message allowed in either direction
+ * (used for our receive and sent buffers).
+ */
#define MAXLINE 4096
-struct sendbuf
+
+/**
+ * IO buffer used for buffering data in transit.
+ */
+struct SendBuffer
{
- unsigned int pos;
- unsigned int size;
+
+ /**
+ * How many bytes that were stored in 'buf' did we already write to the
+ * destination? Always smaller than 'size'.
+ */
+ size_t pos;
+
+ /**
+ * How many bytes of data are stored in 'buf' for transmission right now?
+ * Data always starts at offset 0 and extends to 'size'.
+ */
+ size_t size;
+
+ /**
+ * Buffered data; twice the maximum allowed message size as we add some
+ * headers.
+ */
char buf[MAXLINE * 2];
};
-static int first;
+/**
+ * Flag set to 1 if we are to terminate, otherwise 0.
+ */
static int closeprog;
+
+/**
+ * We're being killed, clean up.
+ *
+ * @param sig killing signal
+ */
static void
sigfunc (int sig)
{
@@ -53,7 +91,8 @@ sigfunc (int sig)
/**
- * function to create GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL message for plugin
+ * Create control message for plugin
+ *
* @param buffer pointer to buffer for the message
* @param mac pointer to the mac address
* @return number of bytes written
@@ -67,83 +106,90 @@ send_mac_to_plugin (char *buffer, struct GNUNET_TRANSPORT_WLAN_MacAddress *mac)
memcpy (&macmsg.mac, (char *) mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
macmsg.hdr.size = htons (sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage));
macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
-
memcpy (buffer, &macmsg, sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage));
return sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage);
}
-static void
+
+/**
+ * We got a message from the FIFO, check it, convert the message
+ * type to the output forward and copy it to the buffer for stdout.
+ *
+ * @param cls the 'struct SendBuffer' to copy the converted message to
+ * @param client unused
+ * @param hdr inbound message from the FIFO
+ */
+static int
stdin_send (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
{
- struct sendbuf *write_pout = cls;
- int sendsize;
- struct GNUNET_MessageHeader newheader;
- char *to_data;
- char *to_radiotap;
- char *to_start;
-
- sendsize =
- ntohs (hdr->size) - sizeof (struct Radiotap_Send) +
- sizeof (struct Radiotap_rx);
-
- if (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs (hdr->type))
+ struct SendBuffer *write_pout = cls;
+ const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *in;
+ size_t payload_size;
+ struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage newheader;
+ uint16_t sendsize;
+
+ sendsize = ntohs (hdr->size);
+ in = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr;
+ if ( (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) ||
+ (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) > sendsize) )
{
- fprintf (stderr, "Function stdin_send: wrong packet type\n");
+ FPRINTF (stderr, "%s", "Received malformed message\n");
exit (1);
}
- if ((sendsize + write_pout->size) > MAXLINE * 2)
+ payload_size = sendsize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage);
+ if ((payload_size + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) + write_pout->size) > MAXLINE * 2)
{
- fprintf (stderr, "Function stdin_send: Packet too big for buffer\n");
+ FPRINTF (stderr, "%s", "Packet too big for buffer\n");
exit (1);
}
-
- newheader.size = htons (sendsize);
- newheader.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
-
- to_start = write_pout->buf + write_pout->size;
- memcpy (to_start, &newheader, sizeof (struct GNUNET_MessageHeader));
- write_pout->size += sizeof (struct GNUNET_MessageHeader);
-
- to_radiotap = to_start + sizeof (struct GNUNET_MessageHeader);
- memset (to_radiotap, 0, sizeof (struct Radiotap_rx));
- write_pout->size += sizeof (struct Radiotap_rx);
-
- to_data = to_radiotap + sizeof (struct Radiotap_rx);
- memcpy (to_data,
- ((char *) hdr) + sizeof (struct Radiotap_Send) +
- sizeof (struct GNUNET_MessageHeader),
- ntohs (hdr->size) - sizeof (struct Radiotap_Send) -
- sizeof (struct GNUNET_MessageHeader));
- write_pout->size +=
- ntohs (hdr->size) - sizeof (struct Radiotap_Send) -
- sizeof (struct GNUNET_MessageHeader);
+ memset (&newheader, 0, sizeof (newheader));
+ newheader.header.size = htons (payload_size + sizeof (newheader));
+ newheader.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER);
+ newheader.frame = in->frame;
+ memcpy (write_pout->buf + write_pout->size,
+ &newheader,
+ sizeof (newheader));
+ write_pout->size += sizeof (newheader);
+ memcpy (write_pout->buf + write_pout->size,
+ &in[1],
+ payload_size);
+ write_pout->size += payload_size;
+ return GNUNET_OK;
}
-static void
+/**
+ * We read a full message from stdin. Copy it to our send buffer.
+ *
+ * @param cls the 'struct SendBuffer' to copy to
+ * @param client unused
+ * @param hdr the message we received to copy to the buffer
+ */
+static int
file_in_send (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
{
- struct sendbuf *write_std = cls;
+ struct SendBuffer *write_std = cls;
uint16_t sendsize;
sendsize = ntohs (hdr->size);
-
- if (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs (hdr->type))
- {
- fprintf (stderr, "Function file_in_send: wrong packet type\n");
- exit (1);
- }
if ((sendsize + write_std->size) > MAXLINE * 2)
{
- fprintf (stderr, "Function file_in_send: Packet too big for buffer\n");
+ FPRINTF (stderr, "%s", "Packet too big for buffer\n");
exit (1);
}
-
memcpy (write_std->buf + write_std->size, hdr, sendsize);
write_std->size += sendsize;
+ return GNUNET_OK;
}
+/**
+ * Main function of a program that pretends to be a WLAN card.
+ *
+ * @param argc should be 2
+ * @param argv either '1' or '2', depending on which of the two cards this dummy is to emulate
+ * @return 1 on error, 0 if terminated normally via signal
+ */
int
main (int argc, char *argv[])
{
@@ -154,105 +200,104 @@ main (int argc, char *argv[])
int fdpin;
int fdpout;
char readbuf[MAXLINE];
- int readsize = 0;
- struct sendbuf write_std;
- struct sendbuf write_pout;
- int ret = 0;
- int maxfd = 0;
+ int readsize;
+ struct SendBuffer write_std;
+ struct SendBuffer write_pout;
+ int ret;
+ int maxfd;
fd_set rfds;
fd_set wfds;
struct timeval tv;
int retval;
- struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst;
- struct GNUNET_SERVER_MessageStreamTokenizer *file_in_mst;
+ struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst = NULL;
+ struct GNUNET_SERVER_MessageStreamTokenizer *file_in_mst = NULL;
struct GNUNET_TRANSPORT_WLAN_MacAddress macaddr;
+ int first;
- if (2 != argc)
+ if ( (2 != argc) ||
+ ((0 != strcmp (argv[1], "1")) && (0 != strcmp (argv[1], "2"))) )
{
- fprintf (stderr,
- "This program must be started with the operating mode (1 or 2) as the only argument.\n");
+ FPRINTF (stderr,
+ "%s",
+ "This program must be started with the operating mode (1 or 2) as the only argument.\n");
return 1;
}
- if ((0 != strstr (argv[1], "1")) && (0 != strstr (argv[1], "2")))
- return 1;
- //make the fifos if needed
- if (0 != stat (FIFO_FILE1, &st))
+ /* make the fifos if needed */
+ umask (0);
+ if ( (GNUNET_OK != GNUNET_DISK_directory_create_for_file (FIFO_FILE1)) ||
+ (GNUNET_OK != GNUNET_DISK_directory_create_for_file (FIFO_FILE2)) )
{
- if (0 == stat (FIFO_FILE2, &st))
- {
- fprintf (stderr, "FIFO_FILE2 exists, but FIFO_FILE1 not\n");
- exit (1);
- }
- umask (0);
- erg = mkfifo (FIFO_FILE1, 0666);
- if (0 != erg)
- {
- fprintf (stderr, "Error in mkfifo(%s): %s\n", FIFO_FILE1,
- strerror (errno));
- //exit(1);
- }
- erg = mkfifo (FIFO_FILE2, 0666);
- if (0 != erg)
+ FPRINTF (stderr, "Failed to create directory for file `%s'\n", FIFO_FILE1);
+ return 1;
+ }
+ if (0 == strcmp (argv[1], "1") )
+ {
+ if (0 != stat (FIFO_FILE1, &st))
{
- fprintf (stderr, "Error in mkfifo(%s): %s\n", FIFO_FILE2,
- strerror (errno));
- //exit(1);
+ erg = mkfifo (FIFO_FILE1, 0666);
+ if ( (0 != erg) && (EEXIST != errno) )
+ FPRINTF (stderr, "Error in mkfifo(%s): %s\n", FIFO_FILE1,
+ strerror (errno));
}
-
}
else
{
if (0 != stat (FIFO_FILE2, &st))
{
- fprintf (stderr, "FIFO_FILE1 exists, but FIFO_FILE2 not\n");
- exit (1);
+ erg = mkfifo (FIFO_FILE2, 0666);
+ if ( (0 != erg) && (EEXIST != errno) )
+ FPRINTF (stderr, "Error in mkfifo(%s): %s\n", FIFO_FILE2,
+ strerror (errno));
}
}
- if (strstr (argv[1], "1"))
+ if (0 == strcmp (argv[1], "1"))
{
- //fprintf(stderr, "First\n");
first = 1;
fpin = fopen (FIFO_FILE1, "r");
if (NULL == fpin)
{
- fprintf (stderr, "fopen of read FIFO_FILE1\n");
+ FPRINTF (stderr, "fopen of read FIFO_FILE1 failed: %s\n", STRERROR (errno));
goto end;
}
- fpout = fopen (FIFO_FILE2, "w");
+ if (NULL == (fpout = fopen (FIFO_FILE2, "w")))
+ {
+ erg = mkfifo (FIFO_FILE2, 0666);
+ fpout = fopen (FIFO_FILE2, "w");
+ }
if (NULL == fpout)
{
- fprintf (stderr, "fopen of write FIFO_FILE2\n");
+ FPRINTF (stderr, "fopen of write FIFO_FILE2 failed: %s\n", STRERROR (errno));
goto end;
}
-
}
else
{
first = 0;
- //fprintf(stderr, "Second\n");
- fpout = fopen (FIFO_FILE1, "w");
+ if (NULL == (fpout = fopen (FIFO_FILE1, "w")))
+ {
+ erg = mkfifo (FIFO_FILE1, 0666);
+ fpout = fopen (FIFO_FILE1, "w");
+ }
if (NULL == fpout)
{
- fprintf (stderr, "fopen of write FIFO_FILE1\n");
+ FPRINTF (stderr, "fopen of write FIFO_FILE1 failed: %s\n", STRERROR (errno));
goto end;
}
fpin = fopen (FIFO_FILE2, "r");
if (NULL == fpin)
{
- fprintf (stderr, "fopen of read FIFO_FILE2\n");
+ FPRINTF (stderr, "fopen of read FIFO_FILE2 failed: %s\n", STRERROR (errno));
goto end;
}
-
}
fdpin = fileno (fpin);
GNUNET_assert (fpin >= 0);
-
if (fdpin >= FD_SETSIZE)
{
- fprintf (stderr, "File fdpin number too large (%d > %u)\n", fdpin,
+ FPRINTF (stderr, "File fdpin number too large (%d > %u)\n", fdpin,
(unsigned int) FD_SETSIZE);
goto end;
}
@@ -262,10 +307,9 @@ main (int argc, char *argv[])
if (fdpout >= FD_SETSIZE)
{
- fprintf (stderr, "File fdpout number too large (%d > %u)\n", fdpout,
+ FPRINTF (stderr, "File fdpout number too large (%d > %u)\n", fdpout,
(unsigned int) FD_SETSIZE);
goto end;
-
}
signal (SIGINT, &sigfunc);
@@ -278,7 +322,7 @@ main (int argc, char *argv[])
stdin_mst = GNUNET_SERVER_mst_create (&stdin_send, &write_pout);
file_in_mst = GNUNET_SERVER_mst_create (&file_in_send, &write_std);
- //Send random mac address
+ /* Send 'random' mac address */
macaddr.mac[0] = 0x13;
macaddr.mac[1] = 0x22;
macaddr.mac[2] = 0x33;
@@ -290,12 +334,12 @@ main (int argc, char *argv[])
while (0 == closeprog)
{
maxfd = -1;
- //set timeout
tv.tv_sec = 5;
tv.tv_usec = 0;
FD_ZERO (&rfds);
- // if output queue is empty
+ FD_ZERO (&wfds);
+ /* if output queue is empty, read */
if (0 == write_pout.size)
{
FD_SET (STDIN_FILENO, &rfds);
@@ -306,8 +350,8 @@ main (int argc, char *argv[])
FD_SET (fdpin, &rfds);
maxfd = MAX (fdpin, maxfd);
}
- FD_ZERO (&wfds);
- // if there is something to write
+
+ /* if there is something to write, try to write */
if (0 < write_std.size)
{
FD_SET (STDOUT_FILENO, &wfds);
@@ -324,7 +368,7 @@ main (int argc, char *argv[])
continue;
if (0 > retval)
{
- fprintf (stderr, "select failed: %s\n", strerror (errno));
+ FPRINTF (stderr, "select failed: %s\n", STRERROR (errno));
closeprog = 1;
break;
}
@@ -337,14 +381,14 @@ main (int argc, char *argv[])
if (0 > ret)
{
closeprog = 1;
- fprintf (stderr, "Write ERROR to STDOUT_FILENO: %s\n",
- strerror (errno));
+ FPRINTF (stderr, "Write ERROR to STDOUT_FILENO: %s\n",
+ STRERROR (errno));
break;
}
else
{
write_std.pos += ret;
- // check if finished
+ /* check if finished writing */
if (write_std.pos == write_std.size)
{
write_std.pos = 0;
@@ -362,12 +406,12 @@ main (int argc, char *argv[])
if (0 > ret)
{
closeprog = 1;
- fprintf (stderr, "Write ERROR to fdpout: %s\n", strerror (errno));
+ FPRINTF (stderr, "Write ERROR to fdpout failed: %s\n", STRERROR (errno));
}
else
{
write_pout.pos += ret;
- // check if finished
+ /* check if finished writing */
if (write_pout.pos == write_pout.size)
{
write_pout.pos = 0;
@@ -383,8 +427,8 @@ main (int argc, char *argv[])
if (0 > readsize)
{
closeprog = 1;
- fprintf (stderr, "Error reading from STDIN_FILENO: %s\n",
- strerror (errno));
+ FPRINTF (stderr, "Error reading from STDIN_FILENO: %s\n",
+ STRERROR (errno));
}
else if (0 < readsize)
{
@@ -394,7 +438,7 @@ main (int argc, char *argv[])
}
else
{
- //eof
+ /* eof */
closeprog = 1;
}
}
@@ -405,7 +449,7 @@ main (int argc, char *argv[])
if (0 > readsize)
{
closeprog = 1;
- fprintf (stderr, "Error reading from fdpin: %s\n", strerror (errno));
+ FPRINTF (stderr, "Error reading from fdpin: %s\n", STRERROR (errno));
break;
}
else if (0 < readsize)
@@ -415,20 +459,22 @@ main (int argc, char *argv[])
}
else
{
- //eof
+ /* eof */
closeprog = 1;
}
}
}
- //clean up
- GNUNET_SERVER_mst_destroy (stdin_mst);
- GNUNET_SERVER_mst_destroy (file_in_mst);
-
end:
- if (fpout != NULL)
+ /* clean up */
+ if (NULL != stdin_mst)
+ GNUNET_SERVER_mst_destroy (stdin_mst);
+ if (NULL != file_in_mst)
+ GNUNET_SERVER_mst_destroy (file_in_mst);
+
+ if (NULL != fpout)
fclose (fpout);
- if (fpin != NULL)
+ if (NULL != fpin)
fclose (fpin);
if (1 == first)
{
diff --git a/src/transport/gnunet-helper-transport-wlan.c b/src/transport/gnunet-helper-transport-wlan.c
index 582df7c..363925c 100644
--- a/src/transport/gnunet-helper-transport-wlan.c
+++ b/src/transport/gnunet-helper-transport-wlan.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2010, 2011 Christian Grothoff (and other contributing authors)
+ (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors)
Copyright (c) 2007, 2008, Andy Green <andy@warmcat.com>
Copyright (C) 2009 Thomas d'Otreppe
@@ -21,12 +21,48 @@
*/
/**
* @file src/transport/gnunet-helper-transport-wlan.c
- * @brief wlan layer two server; must run as root (SUID will do)
+ * @brief mediator between the wlan interface and gnunet; must run as root (SUID will do)
* This code will work under GNU/Linux only.
* @author David Brodski
+ * @author Christian Grothoff
*
- * This program serves as the mediator between the wlan interface and
- * gnunet
+ * This program will allow receiving and sending traffic from the WLAN
+ * interface. It will force traffic to be in 'ad-hoc' mode, use the
+ * proper MAC address of the WLAN interface and use a GNUnet-specific
+ * SSID (and a GNUnet-specific SNAP header). It only takes a single
+ * argument, which is the name of the WLAN interface to use. The
+ * program detects if the interface is not a WLAN interface and exits
+ * with an error in that case.
+ *
+ * Once initialized, the program will first send a 'struct
+ * GNUNET_TRANSPORT_WLAN_HelperControlMessage' to 'stdout'. That
+ * message contains the MAC address of the WLAN interface. It will
+ * then read messages from the WLAN interface and send them together
+ * with performance information as 'struct
+ * GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage' messages to 'stdout'.
+ * Furthermore, it will read a stream of messages from 'stdin' that
+ * have the format from 'struct
+ * GNUNET_TRANSPORT_WLAN_RadiotapSendMessage'. Those messages will
+ * then be sent via the WLAN interface; however, the sender MAC
+ * address will be forced to be the correct address from our WLAN
+ * card. If 'stdin' closes, receiving from the WLAN interface will
+ * continue. If 'stdout' causes a SIGPIPE, the process dies from the
+ * signal. Errors cause an error message to be reported to 'stderr',
+ * in most cases the process also exits (with status code '1'). The
+ * program never terminates normally; it is safe to kill the
+ * process with SIGTERM or SIGKILL at any time.
+ *
+ * Since it uses RAW sockets, the binary must be installed SUID or run
+ * as 'root'. In order to keep the security risk of the resulting
+ * SUID binary minimal, the program ONLY opens the RAW socket with
+ * root privileges, then drops them and only then starts to process
+ * command line arguments. The code also does not link against any
+ * shared libraries (except libc) and is strictly minimal (except for
+ * checking for errors). The following list of people have reviewed
+ * this code and considered it safe since the last modification (if
+ * you reviewed it, please have your name added to the list):
+ *
+ * - Christian Grothoff (Apr 3rd 2012)
*/
/*-
@@ -70,10 +106,10 @@
* Modifications to fit into the linux IEEE 802.11 stack,
* Mike Kershaw (dragorn@kismetwireless.net)
*/
-
-/**
+/*
* parts taken from aircrack-ng, parts changend.
*/
+
#define _GNU_SOURCE
#include <sys/socket.h>
#include <sys/ioctl.h>
@@ -102,183 +138,429 @@
#include "gnunet_protocols.h"
#include "plugin_transport_wlan.h"
+/**
+ * Packet format type for the messages we receive from
+ * the kernel. This is for plain messages (with no
+ * performance information included).
+ */
#define ARPHRD_IEEE80211 801
+
+/**
+ * Packet format type for the messages we receive from
+ * the kernel. This is for the PRISM format.
+ */
#define ARPHRD_IEEE80211_PRISM 802
-#define ARPHRD_IEEE80211_FULL 803
/**
- * size of 802.11 address
+ * Packet format type for the messages we receive from
+ * the kernel. This is for messages with a
+ * 'struct Ieee80211RadiotapHeader' (see below).
*/
-#define IEEE80211_ADDR_LEN 6
+#define ARPHRD_IEEE80211_FULL 803
+
/**
- * Maximum size of a message allowed in either direction.
+ * Maximum size of a message allowed in either direction
+ * (used for our receive and sent buffers).
*/
#define MAXLINE 4096
-#define IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK 0x80000000
+/* ********* structure of messages of type ARPHRD_IEEE80211_PRISM *********** */
-/* Name Data type Units
- * ---- --------- -----
- *
- * IEEE80211_RADIOTAP_TSFT __le64 microseconds
- *
- * Value in microseconds of the MAC's 64-bit 802.11 Time
- * Synchronization Function timer when the first bit of the
- * MPDU arrived at the MAC. For received frames, only.
- *
- * IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap
- *
- * Tx/Rx frequency in MHz, followed by flags (see below).
- *
- * IEEE80211_RADIOTAP_FHSS __le16 see below
- *
- * For frequency-hopping radios, the hop set (first byte)
- * and pattern (second byte).
- *
- * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s
- *
- * Tx/Rx data rate
- *
- * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from
- * one milliwatt (dBm)
- *
- * RF signal power at the antenna, decibel difference from
- * one milliwatt.
- *
- * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from
- * one milliwatt (dBm)
- *
- * RF noise power at the antenna, decibel difference from one
- * milliwatt.
- *
- * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB)
- *
- * RF signal power at the antenna, decibel difference from an
- * arbitrary, fixed reference.
- *
- * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB)
- *
- * RF noise power at the antenna, decibel difference from an
- * arbitrary, fixed reference point.
- *
- * IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless
- *
- * Quality of Barker code lock. Unitless. Monotonically
- * nondecreasing with "better" lock strength. Called "Signal
- * Quality" in datasheets. (Is there a standard way to measure
- * this?)
- *
- * IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless
- *
- * Transmit power expressed as unitless distance from max
- * power set at factory calibration. 0 is max power.
- * Monotonically nondecreasing with lower power levels.
- *
- * IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB)
- *
- * Transmit power expressed as decibel distance from max power
- * set at factory calibration. 0 is max power. Monotonically
- * nondecreasing with lower power levels.
- *
- * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from
- * one milliwatt (dBm)
- *
- * Transmit power expressed as dBm (decibels from a 1 milliwatt
- * reference). This is the absolute power level measured at
- * the antenna port.
- *
- * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap
- *
- * Properties of transmitted and received frames. See flags
- * defined below.
- *
- * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index
- *
- * Unitless indication of the Rx/Tx antenna for this packet.
- * The first antenna is antenna 0.
- *
- * IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap
- *
- * Properties of received frames. See flags defined below.
- *
- * IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap
- *
- * Properties of transmitted frames. See flags defined below.
- *
- * IEEE80211_RADIOTAP_RTS_RETRIES uint8_t data
- *
- * Number of rts retries a transmitted frame used.
- *
- * IEEE80211_RADIOTAP_DATA_RETRIES uint8_t data
- *
- * Number of unicast retries a transmitted frame used.
- *
+/**
+ * Device name length in PRISM frames.
+ * (In the kernel, this is "WLAN_DEVNAMELEN_MAX")
+ */
+#define PRISM_DEVICE_NAME_LENGTH 16
+
+/**
+ * Monitor Frame (indicator that we have a 'struct PrismHeader').
+ */
+#define PRISM_MSGCODE_MONITOR 0x0041
+
+/**
+ * Mac time element. In micro-seconds.
+ * Drivers appear to use a 64bit counter to hold mactime internal
+ * the then fill the prism header with the lower 32 bits
+ */
+#define PRISM_DID_MACTIME 0x2041
+
+/**
+ * Channel element
+ */
+#define PRISM_DID_CHANNEL 0x3041
+
+/**
+ * Signal element. Should be the signal strength in dbm, some people
+ * suggest that instead "100 - (strength in dbm)" is used (to make this
+ * a positive integer).
+ */
+#define PRISM_DID_SIGNAL 0x6041
+
+/**
+ * Noise element
+ */
+#define PRISM_DID_NOISE 0x7041
+
+/**
+ * Rate element, in units/multiples of 500Khz
+ */
+#define PRISM_DID_RATE 0x8041
+
+
+/**
+ * Value is set (supplied)
+ */
+#define PRISM_STATUS_OK 0
+
+/**
+ * Value not supplied.
+ */
+#define PRISM_STATUS_NO_VALUE 1
+
+
+/**
+ * Values in the 'struct PrismHeader'. All in host byte order (!).
+ */
+struct PrismValue
+{
+ /**
+ * This has a different ID for each parameter, see
+ * PRISM_DID_* constants.
+ */
+ uint32_t did;
+
+ /**
+ * See PRISM_STATUS_*-constants. Note that they are unusual: 0 = set; 1 = not set
+ */
+ uint16_t status;
+
+ /**
+ * length of data (which is always a uint32_t, but presumably this can be used
+ * to specify that fewer bytes are used (with values in 'len' from 0-4). We
+ * ignore this field.
+ */
+ uint16_t len;
+
+ /**
+ * The data value
+ */
+ uint32_t data;
+
+} __attribute__ ((packed));
+
+
+/**
+ * Prism header format ('struct p80211msg' in Linux). All in host byte order (!).
+ */
+struct PrismHeader
+{
+ /**
+ * We expect this to be a PRISM_MSGCODE_*.
+ */
+ uint32_t msgcode;
+
+ /**
+ * The length of the entire header.
+ */
+ uint32_t msglen;
+
+ /**
+ * Name of the device that captured the packet.
+ */
+ char devname[PRISM_DEVICE_NAME_LENGTH];
+
+ /* followed by 'struct PrismValue's. Documentation suggests that these
+ are typically the hosttime, mactime, channel, rssi, sq, signal, noise,
+ rate, istx and frmlen values, but documentation is sparse. So we
+ will use the 'did' fields to find out what we actually got. */
+
+} __attribute__ ((packed));
+
+
+/* ****** end of structure of messages of type ARPHRD_IEEE80211_PRISM ******* */
+
+/* ********** structure of messages of type ARPHRD_IEEE80211_FULL *********** */
+
+/**
+ * Bits in the 'it_present' bitmask from the 'struct
+ * Ieee80211RadiotapHeader'. For each value, we give the name, data
+ * type, unit and then a description below. Note that the actual size
+ * of the extension can be bigger as arguments must be padded so that
+ * args of a given length must begin at a boundary of that length.
+ * However, note that compound args are allowed (eg, 2 x uint16_t for
+ * IEEE80211_RADIOTAP_CHANNEL) so total argument length is not a
+ * reliable indicator of alignment requirement. See also
+ * 'man 9 ieee80211_radiotap'.
*/
enum RadiotapType
{
+
+ /**
+ * IEEE80211_RADIOTAP_TSFT __le64 microseconds
+ *
+ * Value in microseconds of the MAC's 64-bit 802.11 Time
+ * Synchronization Function timer when the first bit of the
+ * MPDU arrived at the MAC. For received frames, only.
+ */
IEEE80211_RADIOTAP_TSFT = 0,
+
+ /**
+ * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap
+ *
+ * Properties of transmitted and received frames. See flags
+ * defined below.
+ */
IEEE80211_RADIOTAP_FLAGS = 1,
+
+ /**
+ * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s
+ *
+ * Tx/Rx data rate
+ */
IEEE80211_RADIOTAP_RATE = 2,
+
+ /**
+ * IEEE80211_RADIOTAP_CHANNEL 2 x __le16 MHz, bitmap
+ *
+ * Tx/Rx frequency in MHz, followed by flags (see below).
+ */
IEEE80211_RADIOTAP_CHANNEL = 3,
+ /**
+ * IEEE80211_RADIOTAP_FHSS __le16 see below
+ *
+ * For frequency-hopping radios, the hop set (first byte)
+ * and pattern (second byte).
+ */
IEEE80211_RADIOTAP_FHSS = 4,
+
+ /**
+ * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * RF signal power at the antenna, decibel difference from
+ * one milliwatt.
+ */
IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
+
+ /**
+ * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * RF noise power at the antenna, decibel difference from one
+ * milliwatt.
+ */
IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
+
+ /**
+ * IEEE80211_RADIOTAP_LOCK_QUALITY __le16 unitless
+ *
+ * Quality of Barker code lock. Unitless. Monotonically
+ * nondecreasing with "better" lock strength. Called "Signal
+ * Quality" in datasheets. (Is there a standard way to measure
+ * this?)
+ */
IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
+
+ /**
+ * IEEE80211_RADIOTAP_TX_ATTENUATION __le16 unitless
+ *
+ * Transmit power expressed as unitless distance from max
+ * power set at factory calibration. 0 is max power.
+ * Monotonically nondecreasing with lower power levels.
+ */
IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
+
+ /**
+ * IEEE80211_RADIOTAP_DB_TX_ATTENUATION __le16 decibels (dB)
+ *
+ * Transmit power expressed as decibel distance from max power
+ * set at factory calibration. 0 is max power. Monotonically
+ * nondecreasing with lower power levels.
+ */
IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
+
+ /**
+ * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from
+ * one milliwatt (dBm)
+ *
+ * Transmit power expressed as dBm (decibels from a 1 milliwatt
+ * reference). This is the absolute power level measured at
+ * the antenna port.
+ */
IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
+
+ /**
+ * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index
+ *
+ * Unitless indication of the Rx/Tx antenna for this packet.
+ * The first antenna is antenna 0.
+ */
IEEE80211_RADIOTAP_ANTENNA = 11,
+
+ /**
+ * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB)
+ *
+ * RF signal power at the antenna, decibel difference from an
+ * arbitrary, fixed reference.
+ */
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
+
+ /**
+ * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB)
+ *
+ * RF noise power at the antenna, decibel difference from an
+ * arbitrary, fixed reference point.
+ */
IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
+
+ /**
+ * IEEE80211_RADIOTAP_RX_FLAGS __le16 bitmap
+ *
+ * Properties of received frames. See flags defined below.
+ */
IEEE80211_RADIOTAP_RX_FLAGS = 14,
+
+ /**
+ * IEEE80211_RADIOTAP_TX_FLAGS __le16 bitmap
+ *
+ * Properties of transmitted frames. See flags defined below.
+ */
IEEE80211_RADIOTAP_TX_FLAGS = 15,
+
+ /**
+ * IEEE80211_RADIOTAP_RTS_RETRIES uint8_t data
+ *
+ * Number of rts retries a transmitted frame used.
+ */
IEEE80211_RADIOTAP_RTS_RETRIES = 16,
+
+ /**
+ * IEEE80211_RADIOTAP_DATA_RETRIES uint8_t data
+ *
+ * Number of unicast retries a transmitted frame used.
+ */
IEEE80211_RADIOTAP_DATA_RETRIES = 17,
+
+ /**
+ * Extension bit, used to indicate that more bits are needed for
+ * the bitmask.
+ */
IEEE80211_RADIOTAP_EXT = 31
};
-/* For IEEE80211_RADIOTAP_FLAGS */
-#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
- * during CFP
- */
-#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
- * with short
- * preamble
- */
-#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
- * with WEP encryption
- */
-#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
- * with fragmentation
- */
-#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
-#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
- * 802.11 header and payload
- * (to 32-bit boundary)
- */
-/* For IEEE80211_RADIOTAP_RX_FLAGS */
-#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
-
-/* For IEEE80211_RADIOTAP_TX_FLAGS */
-#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive
- * retries */
-#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
-#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
-#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* frame should not be ACKed */
-#define IEEE80211_RADIOTAP_F_TX_NOSEQ 0x0010 /* sequence number handled
- * by userspace */
+/**
+ * Bitmask indicating an extension of the bitmask is used.
+ * (Mask corresponding to IEEE80211_RADIOTAP_EXT).
+ */
+#define IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK (1 << IEEE80211_RADIOTAP_EXT)
+
+
+
+/**
+ * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get
+ * as part of a 'struct Ieee80211RadiotapHeader' extension
+ * if the IEEE80211_RADIOTAP_FLAGS bit is set in
+ * 'it_present'). The radiotap flags are an 8-bit field.
+ *
+ * Frame was sent/received during CFP (Contention Free Period)
+ */
+#define IEEE80211_RADIOTAP_F_CFP 0x01
+/**
+ * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get
+ * as part of a 'struct Ieee80211RadiotapHeader' extension
+ * if the IEEE80211_RADIOTAP_FLAGS bit is set in
+ * 'it_present'). The radiotap flags are an 8-bit field.
+ *
+ * Frame was sent/received with short preamble
+ */
+#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02
+
+/**
+ * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get
+ * as part of a 'struct Ieee80211RadiotapHeader' extension
+ * if the IEEE80211_RADIOTAP_FLAGS bit is set in
+ * 'it_present'). The radiotap flags are an 8-bit field.
+ *
+ * Frame was sent/received with WEP encryption
+ */
+#define IEEE80211_RADIOTAP_F_WEP 0x04
/**
- * A generic radio capture format is desirable. There is one for
- * Linux, but it is neither rigidly defined (there were not even
- * units given for some fields) nor easily extensible.
+ * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get
+ * as part of a 'struct Ieee80211RadiotapHeader' extension
+ * if the IEEE80211_RADIOTAP_FLAGS bit is set in
+ * 'it_present'). The radiotap flags are an 8-bit field.
*
- * I suggest the following extensible radio capture format. It is
- * based on a bitmap indicating which fields are present.
+ * Frame was sent/received with fragmentation
+ */
+#define IEEE80211_RADIOTAP_F_FRAG 0x08
+
+/**
+ * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get
+ * as part of a 'struct Ieee80211RadiotapHeader' extension
+ * if the IEEE80211_RADIOTAP_FLAGS bit is set in
+ * 'it_present'). The radiotap flags are an 8-bit field.
+ *
+ * Frame includes FCS (CRC at the end that needs to be removeD).
+ */
+#define IEEE80211_RADIOTAP_F_FCS 0x10
+
+/**
+ * Bit in IEEE80211_RADIOTAP_FLAGS (which we might get
+ * as part of a 'struct Ieee80211RadiotapHeader' extension
+ * if the IEEE80211_RADIOTAP_FLAGS bit is set in
+ * 'it_present'). The radiotap flags are an 8-bit field.
+ *
+ * Frame has padding between 802.11 header and payload
+ * (to 32-bit boundary)
+ */
+#define IEEE80211_RADIOTAP_F_DATAPAD 0x20
+
+
+/**
+ * For IEEE80211_RADIOTAP_RX_FLAGS:
+ * frame failed crc check
+ */
+#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001
+
+/**
+ * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'):
+ * failed due to excessive retries
+ */
+#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001
+
+/**
+ * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'):
+ * used cts 'protection'
+ */
+#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002
+
+/**
+ * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'):
+ * used rts/cts handshake
+ */
+#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004
+
+/**
+ * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'):
+ * frame should not be ACKed
+ */
+#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008
+
+/**
+ * For IEEE80211_RADIOTAP_TX_FLAGS ('txflags' in 'struct RadiotapTransmissionHeader'):
+ * sequence number handled by userspace
+ */
+#define IEEE80211_RADIOTAP_F_TX_NOSEQ 0x0010
+
+
+/**
+ * Generic header for radiotap messages (receiving and sending). A
+ * bit mask (it_present) determines which specific records follow.
*
* I am trying to describe precisely what the application programmer
* should expect in the following, and for that reason I tell the
@@ -290,13 +572,17 @@ enum RadiotapType
* The radio capture header precedes the 802.11 header.
* All data in the header is little endian on all platforms.
*/
-struct ieee80211_radiotap_header
+struct Ieee80211RadiotapHeader
{
/**
* Version 0. Only increases for drastic changes, introduction of
* compatible new fields does not count.
*/
uint8_t it_version;
+
+ /**
+ * Padding. Set to 0.
+ */
uint8_t it_pad;
/**
@@ -313,89 +599,106 @@ struct ieee80211_radiotap_header
uint32_t it_present;
};
+
/**
- *
+ * Format of the header we need to prepend to messages to be sent to the
+ * Kernel.
*/
-struct RadioTapheader
+struct RadiotapTransmissionHeader
{
+
/**
- *
+ * First we begin with the 'generic' header we also get when receiving
+ * messages.
*/
- struct ieee80211_radiotap_header header;
+ struct Ieee80211RadiotapHeader header;
/**
- *
+ * Transmission rate (we use 0, kernel makes up its mind anyway).
*/
uint8_t rate;
/**
- *
+ * Padding (we use 0). There is a requirement to pad args, so that
+ * args of a given length must begin at a boundary of that length.
+ * As our next argument is the 'it_len' with 2 bytes, we need 1 byte
+ * of padding.
*/
uint8_t pad1;
/**
- *
+ * Transmission flags from on the IEEE80211_RADIOTAP_F_TX_* constant family.
*/
uint16_t txflags;
+
};
+/**
+ * The above 'struct RadiotapTransmissionHeader' should have the
+ * following value for 'header.it_present' based on the presence of
+ * the 'rate' and 'txflags' in the overall struct.
+ */
+#define IEEE80211_RADIOTAP_OUR_TRANSMISSION_HEADER_MASK ((1 << IEEE80211_RADIOTAP_RATE) | (1 << IEEE80211_RADIOTAP_TX_FLAGS))
+
+
/**
- * IO buffer used for buffering data in transit (to wireless or to stdout).
+ * struct Ieee80211RadiotapHeaderIterator - tracks walk through present radiotap arguments
+ * in the radiotap header. Used when we parse radiotap packets received from the kernel.
*/
-struct SendBuffer
+struct Ieee80211RadiotapHeaderIterator
{
/**
- * How many bytes of data are stored in 'buf' for transmission right now?
- * Data always starts at offset 0 and extends to 'size'.
+ * pointer to the radiotap header we are walking through
*/
- size_t size;
+ const struct Ieee80211RadiotapHeader *rtheader;
/**
- * How many bytes that were stored in 'buf' did we already write to the
- * destination? Always smaller than 'size'.
+ * pointer to current radiotap arg
*/
- size_t pos;
-
+ const uint8_t *this_arg;
+
/**
- * Buffered data; twice the maximum allowed message size as we add some
- * headers.
+ * internal next argument pointer
*/
- char buf[MAXLINE * 2];
-};
+ const uint8_t *arg;
-/**
- * Buffer for data read from stdin to be transmitted to the wirless card.
- */
-static struct SendBuffer write_pout;
+ /**
+ * internal pointer to next present uint32_t (if IEEE80211_RADIOTAP_EXT is used).
+ */
+ const uint32_t *next_bitmap;
-/**
- * Buffer for data read from the wireless card to be transmitted to stdout.
- */
-static struct SendBuffer write_std;
+ /**
+ * length of radiotap header in host byte ordering
+ */
+ size_t max_length;
+ /**
+ * internal shifter for current uint32_t bitmap, (it_present in host byte order),
+ * If bit 0 is set, the 'arg_index' argument is present.
+ */
+ uint32_t bitmap_shifter;
-GNUNET_NETWORK_STRUCT_BEGIN
+ /**
+ * IEEE80211_RADIOTAP_... index of current arg
+ */
+ unsigned int this_arg_index;
+
+ /**
+ * internal next argument index
+ */
+ unsigned int arg_index;
+
+};
-/**
- * generic definitions for IEEE 802.11 frames
- */
-struct ieee80211_frame
-{
- uint8_t i_fc[2];
- uint8_t i_dur[2];
- uint8_t i_addr1[IEEE80211_ADDR_LEN];
- uint8_t i_addr2[IEEE80211_ADDR_LEN];
- uint8_t i_addr3[IEEE80211_ADDR_LEN];
- uint8_t i_seq[2];
- /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
- /* see below */
-} GNUNET_PACKED;
-GNUNET_NETWORK_STRUCT_END
+/* ************** end of structure of ARPHRD_IEEE80211_FULL ************** */
+
+/* ************************** our globals ******************************* */
/**
- * struct for storing the information of the hardware
+ * struct for storing the information of the hardware. There is only
+ * one of these.
*/
struct HardwareInfos
{
@@ -424,56 +727,48 @@ struct HardwareInfos
/**
- * struct ieee80211_radiotap_iterator - tracks walk through present radiotap arguments
- * in the radiotap header.
+ * IO buffer used for buffering data in transit (to wireless or to stdout).
*/
-struct ieee80211_radiotap_iterator
+struct SendBuffer
{
/**
- * pointer to the radiotap header we are walking through
- */
- const struct ieee80211_radiotap_header *rtheader;
-
- /**
- * length of radiotap header in cpu byte ordering
- */
- size_t max_length;
-
- /**
- * IEEE80211_RADIOTAP_... index of current arg
+ * How many bytes of data are stored in 'buf' for transmission right now?
+ * Data always starts at offset 0 and extends to 'size'.
*/
- unsigned int this_arg_index;
+ size_t size;
/**
- * pointer to current radiotap arg
+ * How many bytes that were stored in 'buf' did we already write to the
+ * destination? Always smaller than 'size'.
*/
- uint8_t *this_arg;
-
+ size_t pos;
+
/**
- * internal next argument index
+ * Buffered data; twice the maximum allowed message size as we add some
+ * headers.
*/
- unsigned int arg_index;
+ char buf[MAXLINE * 2];
+};
- /**
- * internal next argument pointer
- */
- uint8_t *arg;
- /**
- * internal pointer to next present uint32_t
- */
- uint32_t *next_bitmap;
+/**
+ * Buffer for data read from stdin to be transmitted to the wirless card.
+ */
+static struct SendBuffer write_pout;
- /**
- * internal shifter for curr uint32_t bitmap, b0 set == arg present
- */
- uint32_t bitmap_shifter;
-};
+/**
+ * Buffer for data read from the wireless card to be transmitted to stdout.
+ */
+static struct SendBuffer write_std;
-/* specialized version of server_mst.c begins here */
+/* *********** specialized version of server_mst.c begins here ********** */
+/**
+ * To what multiple do we align messages? 8 byte should suffice for everyone
+ * for now.
+ */
#define ALIGN_FACTOR 8
/**
@@ -533,7 +828,6 @@ struct MessageStreamTokenizer
};
-
/**
* Create a message stream tokenizer.
*
@@ -549,10 +843,16 @@ mst_create (MessageTokenizerCallback cb,
ret = malloc (sizeof (struct MessageStreamTokenizer));
if (NULL == ret)
+ {
+ fprintf (stderr, "Failed to allocate buffer for tokenizer\n");
exit (1);
+ }
ret->hdr = malloc (MIN_BUFFER_SIZE);
if (NULL == ret->hdr)
- exit (2);
+ {
+ fprintf (stderr, "Failed to allocate buffer for alignment\n");
+ exit (1);
+ }
ret->curr_buf = MIN_BUFFER_SIZE;
ret->cb = cb;
ret->cb_cls = cb_cls;
@@ -613,8 +913,9 @@ do_align:
want = ntohs (hdr->size);
if (want < sizeof (struct GNUNET_MessageHeader))
{
- // GNUNET_break_op (0);
- return GNUNET_SYSERR;
+ fprintf (stderr,
+ "Received invalid message from stdin\n");
+ exit (1);
}
if (mst->curr_buf - mst->off < want)
{
@@ -627,7 +928,10 @@ do_align:
{
mst->hdr = realloc (mst->hdr, want);
if (NULL == mst->hdr)
- exit (3);
+ {
+ fprintf (stderr, "Failed to allocate buffer for alignment\n");
+ exit (1);
+ }
ibuf = (char *) mst->hdr;
mst->curr_buf = want;
}
@@ -666,9 +970,9 @@ do_align:
want = ntohs (hdr->size);
if (want < sizeof (struct GNUNET_MessageHeader))
{
- // GNUNET_break_op (0);
- mst->off = 0;
- return GNUNET_SYSERR;
+ fprintf (stderr,
+ "Received invalid message from stdin\n");
+ exit (1);
}
if (size < want)
break; /* or not, buffer incomplete, so copy to private buffer... */
@@ -689,11 +993,19 @@ do_align:
{
mst->hdr = realloc (mst->hdr, size + mst->pos);
if (NULL == mst->hdr)
- exit (4);
+ {
+ fprintf (stderr, "Failed to allocate buffer for alignment\n");
+ exit (1);
+ }
ibuf = (char *) mst->hdr;
mst->curr_buf = size + mst->pos;
}
- // GNUNET_assert (mst->pos + size <= mst->curr_buf);
+ if (mst->pos + size > mst->curr_buf)
+ {
+ fprintf (stderr,
+ "Assertion failed\n");
+ exit (1);
+ }
memcpy (&ibuf[mst->pos], buf, size);
mst->pos += size;
}
@@ -713,16 +1025,16 @@ mst_destroy (struct MessageStreamTokenizer *mst)
free (mst);
}
-/* end of server_mst.c copy */
-
+/* ***************** end of server_mst.c clone ***************** **/
+/* ************** code for handling of ARPHRD_IEEE80211_FULL ************** */
/**
* Radiotap header iteration
*
* call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
- * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
+ * struct Ieee80211RadiotapHeaderIterator (no need to init the struct beforehand)
* then loop calling __ieee80211_radiotap_iterator_next()... it returns -1
* if there are no more args in the header, or the next argument type index
* that is present. The iterator's this_arg member points to the start of the
@@ -736,9 +1048,8 @@ mst_destroy (struct MessageStreamTokenizer *mst)
* @return 0 on success, -1 on error
*/
static int
-ieee80211_radiotap_iterator_init (struct ieee80211_radiotap_iterator *iterator,
- const struct ieee80211_radiotap_header
- *radiotap_header,
+ieee80211_radiotap_iterator_init (struct Ieee80211RadiotapHeaderIterator *iterator,
+ const struct Ieee80211RadiotapHeader *radiotap_header,
size_t max_length)
{
if ( (iterator == NULL) ||
@@ -750,26 +1061,22 @@ ieee80211_radiotap_iterator_init (struct ieee80211_radiotap_iterator *iterator,
return -1;
/* sanity check for allowed length and radiotap length field */
- if ( (max_length < sizeof (struct ieee80211_radiotap_header)) ||
+ if ( (max_length < sizeof (struct Ieee80211RadiotapHeader)) ||
(max_length < (GNUNET_le16toh (radiotap_header->it_len))) )
return -1;
+ memset (iterator, 0, sizeof (struct Ieee80211RadiotapHeaderIterator));
iterator->rtheader = radiotap_header;
iterator->max_length = GNUNET_le16toh (radiotap_header->it_len);
- iterator->arg_index = 0;
iterator->bitmap_shifter = GNUNET_le32toh (radiotap_header->it_present);
- iterator->arg =
- ((uint8_t *) radiotap_header) + sizeof (struct ieee80211_radiotap_header);
- iterator->this_arg = 0;
+ iterator->arg = ((uint8_t *) radiotap_header) + sizeof (struct Ieee80211RadiotapHeader);
/* find payload start allowing for extended bitmap(s) */
- if ((iterator->bitmap_shifter & IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK))
+ if (0 != (iterator->bitmap_shifter & IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK))
{
- while (GNUNET_le32toh (*((uint32_t *) iterator->arg)) &
- IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK)
+ while (GNUNET_le32toh (*((uint32_t *) iterator->arg)) & IEEE80211_RADIOTAP_PRESENT_EXTEND_MASK)
{
iterator->arg += sizeof (uint32_t);
-
/*
* check for insanity where the present bitmaps
* keep claiming to extend up to or even beyond the
@@ -791,7 +1098,7 @@ ieee80211_radiotap_iterator_init (struct ieee80211_radiotap_iterator *iterator,
/**
- * @brief ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
+ * Returns the next radiotap parser iterator arg.
*
* This function returns the next radiotap arg index (IEEE80211_RADIOTAP_...)
* and sets iterator->this_arg to point to the payload for the arg. It takes
@@ -800,13 +1107,11 @@ ieee80211_radiotap_iterator_init (struct ieee80211_radiotap_iterator *iterator,
* format.
*
* @param iterator: radiotap_iterator to move to next arg (if any)
- *
* @return next present arg index on success or -1 if no more or error
*/
static int
-ieee80211_radiotap_iterator_next (struct ieee80211_radiotap_iterator *iterator)
+ieee80211_radiotap_iterator_next (struct Ieee80211RadiotapHeaderIterator *iterator)
{
-
/*
* small length lookup table for all radiotap types we heard of
* starting from b0 in the bitmap, so we can walk the payload
@@ -851,120 +1156,103 @@ ieee80211_radiotap_iterator_next (struct ieee80211_radiotap_iterator *iterator)
* for every radiotap entry we can at
* least skip (by knowing the length)...
*/
-
while (iterator->arg_index < sizeof (rt_sizes))
{
- int hit = 0;
-
- if (!(iterator->bitmap_shifter & 1))
- goto next_entry; /* arg not present */
-
- /*
- * arg is present, account for alignment padding
- * 8-bit args can be at any alignment
- * 16-bit args must start on 16-bit boundary
- * 32-bit args must start on 32-bit boundary
- * 64-bit args must start on 64-bit boundary
- *
- * note that total arg size can differ from alignment of
- * elements inside arg, so we use upper nybble of length
- * table to base alignment on
- *
- * also note: these alignments are ** relative to the
- * start of the radiotap header **. There is no guarantee
- * that the radiotap header itself is aligned on any
- * kind of boundary.
- */
-
- if ((((void *) iterator->arg) -
- ((void *) iterator->rtheader)) & ((rt_sizes[iterator->arg_index] >> 4)
- - 1))
- iterator->arg_index +=
- (rt_sizes[iterator->arg_index] >> 4) -
- ((((void *) iterator->arg) -
- ((void *) iterator->rtheader)) & ((rt_sizes[iterator->arg_index] >>
- 4) - 1));
-
- /*
- * this is what we will return to user, but we need to
- * move on first so next call has something fresh to test
- */
-
- iterator->this_arg_index = iterator->arg_index;
- iterator->this_arg = iterator->arg;
- hit = 1;
-
- /* internally move on the size of this arg */
-
- iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
-
- /*
- * check for insanity where we are given a bitmap that
- * claims to have more arg content than the length of the
- * radiotap section. We will normally end up equalling this
- * max_length on the last arg, never exceeding it.
- */
-
- if ((((void *) iterator->arg) - ((void *) iterator->rtheader)) >
- iterator->max_length)
- return -1;
+ int hit = (0 != (iterator->bitmap_shifter & 1));
-next_entry:
+ if (hit)
+ {
+ unsigned int wanted_alignment;
+ unsigned int unalignment;
+ /*
+ * arg is present, account for alignment padding
+ * 8-bit args can be at any alignment
+ * 16-bit args must start on 16-bit boundary
+ * 32-bit args must start on 32-bit boundary
+ * 64-bit args must start on 64-bit boundary
+ *
+ * note that total arg size can differ from alignment of
+ * elements inside arg, so we use upper nybble of length table
+ * to base alignment on. First, 'wanted_alignment' is set to be
+ * 1 for 8-bit, 2 for 16-bit, 4 for 32-bit and 8 for 64-bit
+ * arguments. Then, we calculate the 'unalignment' (how many
+ * bytes we are over by taking the difference of 'arg' and the
+ * overall starting point modulo the desired alignment. As
+ * desired alignments are powers of two, we can do modulo with
+ * binary "&" (and also avoid the possibility of a division by
+ * zero if the 'rt_sizes' table contains bogus entries).
+ *
+ * also note: these alignments are relative to the start of the
+ * radiotap header. There is no guarantee that the radiotap
+ * header itself is aligned on any kind of boundary, thus we
+ * need to really look at the delta here.
+ */
+ wanted_alignment = rt_sizes[iterator->arg_index] >> 4;
+ unalignment = (((void *) iterator->arg) - ((void *) iterator->rtheader)) & (wanted_alignment - 1);
+ if (0 != unalignment)
+ {
+ /* need padding (by 'wanted_alignment - unalignment') */
+ iterator->arg_index += wanted_alignment - unalignment;
+ }
+
+ /*
+ * this is what we will return to user, but we need to
+ * move on first so next call has something fresh to test
+ */
+ iterator->this_arg_index = iterator->arg_index;
+ iterator->this_arg = iterator->arg;
+
+ /* internally move on the size of this arg (using lower nybble from
+ the table) */
+ iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
+
+ /*
+ * check for insanity where we are given a bitmap that
+ * claims to have more arg content than the length of the
+ * radiotap section. We will normally end up equalling this
+ * max_length on the last arg, never exceeding it.
+ */
+ if ((((void *) iterator->arg) - ((void *) iterator->rtheader)) > iterator->max_length)
+ return -1;
+ }
+ /* Now, move on to next bit / next entry */
iterator->arg_index++;
- if (((iterator->arg_index & 31) == 0))
+
+ if (0 == (iterator->arg_index % 32))
{
/* completed current uint32_t bitmap */
- if (iterator->bitmap_shifter & 1)
+ if (0 != (iterator->bitmap_shifter & 1))
{
- /* b31 was set, there is more */
- /* move to next uint32_t bitmap */
+ /* bit 31 was set, there is more; move to next uint32_t bitmap */
iterator->bitmap_shifter = GNUNET_le32toh (*iterator->next_bitmap);
iterator->next_bitmap++;
}
else
{
- /* no more bitmaps: end */
+ /* no more bitmaps: end (by setting arg_index to high, unsupported value) */
iterator->arg_index = sizeof (rt_sizes);
}
}
else
- { /* just try the next bit */
+ {
+ /* just try the next bit (while loop will move on) */
iterator->bitmap_shifter >>= 1;
}
/* if we found a valid arg earlier, return it now */
-
if (hit)
return iterator->this_arg_index;
-
}
- /* we don't know how to handle any more args, we're done */
+ /* we don't know how to handle any more args (or there are no more),
+ so we're done (this is not an error) */
return -1;
}
/**
- * Return the channel from the frequency (in Mhz)
- * @param frequency of the channel
- * @return number of the channel
- */
-static int
-get_channel_from_frequency (int frequency)
-{
- if (frequency >= 2412 && frequency <= 2472)
- return (frequency - 2407) / 5;
- if (frequency == 2484)
- return 14;
- if (frequency >= 5000 && frequency <= 6100)
- return (frequency - 5000) / 5;
- return -1;
-}
-
-
-/**
- * function to calculate the crc, the start of the calculation
+ * Calculate crc32, the start of the calculation
*
* @param buf buffer to calc the crc
* @param len len of the buffer
@@ -1049,7 +1337,7 @@ calc_crc_osdep (const unsigned char *buf, size_t len)
/**
- * Function to calculate and check crc of the wlan packet
+ * Calculate and check crc of the wlan packet
*
* @param buf buffer of the packet, with len + 4 bytes of data,
* the last 4 bytes being the checksum
@@ -1070,6 +1358,30 @@ check_crc_buf_osdep (const unsigned char *buf, size_t len)
}
+/* ************end of code for handling of ARPHRD_IEEE80211_FULL ************** */
+
+
+/* ************beginning of code for reading packets from kernel ************** */
+
+/**
+ * Return the channel from the frequency (in Mhz)
+ *
+ * @param frequency of the channel
+ * @return number of the channel
+ */
+static int
+get_channel_from_frequency (int32_t frequency)
+{
+ if (frequency >= 2412 && frequency <= 2472)
+ return (frequency - 2407) / 5;
+ if (frequency == 2484)
+ return 14;
+ if (frequency >= 5000 && frequency <= 6100)
+ return (frequency - 5000) / 5;
+ return -1;
+}
+
+
/**
* Get the channel used by our WLAN interface.
*
@@ -1080,46 +1392,46 @@ static int
linux_get_channel (const struct HardwareInfos *dev)
{
struct iwreq wrq;
- int fd;
- int frequency;
- int chan;
+ int32_t frequency;
memset (&wrq, 0, sizeof (struct iwreq));
strncpy (wrq.ifr_name, dev->iface, IFNAMSIZ);
- fd = dev->fd_raw;
- if (0 > ioctl (fd, SIOCGIWFREQ, &wrq))
+ if (0 > ioctl (dev->fd_raw, SIOCGIWFREQ, &wrq))
return -1;
-
- frequency = wrq.u.freq.m;
+ frequency = wrq.u.freq.m; /* 'iw_freq' defines 'm' as '__s32', so we keep it signed */
if (100000000 < frequency)
frequency /= 100000;
else if (1000000 < frequency)
frequency /= 1000;
if (1000 < frequency)
- chan = get_channel_from_frequency (frequency);
- else
- chan = frequency;
- return chan;
+ return get_channel_from_frequency (frequency);
+ return frequency;
}
/**
- * function to read from a wlan card
+ * Read from the raw socket (the wlan card), parse the packet and
+ * put the result into the buffer for transmission to 'stdout'.
+ *
* @param dev pointer to the struct of the wlan card
- * @param buf buffer to read to
+ * @param buf buffer to read to; first bytes will be the 'struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame',
+ * followed by the actual payload
* @param buf_size size of the buffer
- * @param ri radiotap_rx info
- * @return size read from the buffer
+ * @param ri where to write radiotap_rx info
+ * @return number of bytes written to 'buf'
*/
static ssize_t
-linux_read (struct HardwareInfos *dev, unsigned char *buf, size_t buf_size,
- struct Radiotap_rx *ri)
+linux_read (struct HardwareInfos *dev,
+ unsigned char *buf, size_t buf_size,
+ struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *ri)
{
unsigned char tmpbuf[buf_size];
ssize_t caplen;
- int n, got_signal, got_noise, got_channel, fcs_removed;
-
- n = got_signal = got_noise = got_channel = fcs_removed = 0;
+ size_t n;
+ int got_signal = 0;
+ int got_noise = 0;
+ int got_channel = 0;
+ int fcs_removed = 0;
caplen = read (dev->fd_raw, tmpbuf, buf_size);
if (0 > caplen)
@@ -1130,171 +1442,181 @@ linux_read (struct HardwareInfos *dev, unsigned char *buf, size_t buf_size,
return -1;
}
- memset (buf, 0, buf_size);
- memset (ri, 0, sizeof (*ri));
-
+ memset (ri, 0, sizeof (*ri));
switch (dev->arptype_in)
{
case ARPHRD_IEEE80211_PRISM:
- {
- /* skip the prism header */
- if (tmpbuf[7] == 0x40)
{
- /* prism54 uses a different format */
- ri->ri_power = tmpbuf[0x33];
- ri->ri_noise = *(unsigned int *) (tmpbuf + 0x33 + 12);
- ri->ri_rate = (*(unsigned int *) (tmpbuf + 0x33 + 24)) * 500000;
- got_signal = 1;
- got_noise = 1;
- n = 0x40;
- }
- else
- {
- ri->ri_mactime = *(uint64_t *) (tmpbuf + 0x5C - 48);
- ri->ri_channel = *(unsigned int *) (tmpbuf + 0x5C - 36);
- ri->ri_power = *(unsigned int *) (tmpbuf + 0x5C);
- ri->ri_noise = *(unsigned int *) (tmpbuf + 0x5C + 12);
- ri->ri_rate = (*(unsigned int *) (tmpbuf + 0x5C + 24)) * 500000;
- got_channel = 1;
- got_signal = 1;
- got_noise = 1;
- n = *(int *) (tmpbuf + 4);
+ const struct PrismHeader *ph;
+
+ ph = (const struct PrismHeader*) tmpbuf;
+ n = ph->msglen;
+ if ( (n < 8) || (n >= caplen) )
+ return 0; /* invalid format */
+ if ( (PRISM_MSGCODE_MONITOR == ph->msgcode) &&
+ (n >= sizeof (struct PrismHeader)) )
+ {
+ const char *pos;
+ size_t left;
+ struct PrismValue pv;
+
+ left = n - sizeof (struct PrismHeader);
+ pos = (const char *) &ph[1];
+ while (left > sizeof (struct PrismValue))
+ {
+ left -= sizeof (struct PrismValue);
+ memcpy (&pv, pos, sizeof (struct PrismValue));
+ pos += sizeof (struct PrismValue);
+
+ switch (pv.did)
+ {
+ case PRISM_DID_NOISE:
+ if (PRISM_STATUS_OK == pv.status)
+ {
+ ri->ri_noise = pv.data;
+ got_noise = 1;
+ }
+ break;
+ case PRISM_DID_RATE:
+ if (PRISM_STATUS_OK == pv.status)
+ ri->ri_rate = pv.data * 500000;
+ break;
+ case PRISM_DID_CHANNEL:
+ if (PRISM_STATUS_OK == pv.status)
+ {
+ ri->ri_channel = pv.data;
+ got_channel = 1;
+ }
+ break;
+ case PRISM_DID_MACTIME:
+ if (PRISM_STATUS_OK == pv.status)
+ ri->ri_mactime = pv.data;
+ break;
+ case PRISM_DID_SIGNAL:
+ if (PRISM_STATUS_OK == pv.status)
+ {
+ ri->ri_power = pv.data;
+ got_signal = 1;
+ }
+ break;
+ }
+ }
+ }
+ if ( (n < 8) || (n >= caplen) )
+ return 0; /* invalid format */
}
-
- if ( (n < 8) || (n >= caplen) )
- return 0;
- }
break;
-
case ARPHRD_IEEE80211_FULL:
- {
- struct ieee80211_radiotap_iterator iterator;
- struct ieee80211_radiotap_header *rthdr;
-
- rthdr = (struct ieee80211_radiotap_header *) tmpbuf;
-
- if (0 != ieee80211_radiotap_iterator_init (&iterator, rthdr, caplen))
- return 0;
-
- /* go through the radiotap arguments we have been given
- * by the driver
- */
-
- while (ieee80211_radiotap_iterator_next (&iterator) >= 0)
{
-
- switch (iterator.this_arg_index)
+ struct Ieee80211RadiotapHeaderIterator iterator;
+ struct Ieee80211RadiotapHeader *rthdr;
+
+ memset (&iterator, 0, sizeof (iterator));
+ rthdr = (struct Ieee80211RadiotapHeader *) tmpbuf;
+ n = GNUNET_le16toh (rthdr->it_len);
+ if ( (n < sizeof (struct Ieee80211RadiotapHeader)) || (n >= caplen))
+ return 0; /* invalid 'it_len' */
+ if (0 != ieee80211_radiotap_iterator_init (&iterator, rthdr, caplen))
+ return 0;
+ /* go through the radiotap arguments we have been given by the driver */
+ while (0 <= ieee80211_radiotap_iterator_next (&iterator))
{
-
- case IEEE80211_RADIOTAP_TSFT:
- ri->ri_mactime = GNUNET_le64toh (*((uint64_t *) iterator.this_arg));
- break;
-
- case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
- if (!got_signal)
- {
- if (*iterator.this_arg < 127)
- ri->ri_power = *iterator.this_arg;
- else
- ri->ri_power = *iterator.this_arg - 255;
-
- got_signal = 1;
- }
- break;
-
- case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
- if (!got_signal)
- {
- if (*iterator.this_arg < 127)
- ri->ri_power = *iterator.this_arg;
- else
- ri->ri_power = *iterator.this_arg - 255;
-
- got_signal = 1;
- }
- break;
-
- case IEEE80211_RADIOTAP_DBM_ANTNOISE:
- if (!got_noise)
- {
- if (*iterator.this_arg < 127)
- ri->ri_noise = *iterator.this_arg;
- else
- ri->ri_noise = *iterator.this_arg - 255;
-
- got_noise = 1;
- }
- break;
-
- case IEEE80211_RADIOTAP_DB_ANTNOISE:
- if (!got_noise)
- {
- if (*iterator.this_arg < 127)
- ri->ri_noise = *iterator.this_arg;
- else
- ri->ri_noise = *iterator.this_arg - 255;
-
- got_noise = 1;
- }
- break;
-
- case IEEE80211_RADIOTAP_ANTENNA:
- ri->ri_antenna = *iterator.this_arg;
- break;
-
- case IEEE80211_RADIOTAP_CHANNEL:
- ri->ri_channel = *iterator.this_arg;
- got_channel = 1;
- break;
-
- case IEEE80211_RADIOTAP_RATE:
- ri->ri_rate = (*iterator.this_arg) * 500000;
- break;
-
- case IEEE80211_RADIOTAP_FLAGS:
- /* is the CRC visible at the end?
- * remove
- */
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS)
- {
- fcs_removed = 1;
- caplen -= 4;
- }
-
- if (*iterator.this_arg & IEEE80211_RADIOTAP_F_RX_BADFCS)
- return (0);
-
- break;
- }
- }
- n = GNUNET_le16toh (rthdr->it_len);
- if (n <= 0 || n >= caplen)
- return 0;
- }
+ switch (iterator.this_arg_index)
+ {
+ case IEEE80211_RADIOTAP_TSFT:
+ ri->ri_mactime = GNUNET_le64toh (*((uint64_t *) iterator.this_arg));
+ break;
+ case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
+ if (!got_signal)
+ {
+ ri->ri_power = * ((int8_t*) iterator.this_arg);
+ got_signal = 1;
+ }
+ break;
+ case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+ if (!got_signal)
+ {
+ ri->ri_power = * ((int8_t*) iterator.this_arg);
+ got_signal = 1;
+ }
+ break;
+ case IEEE80211_RADIOTAP_DBM_ANTNOISE:
+ if (!got_noise)
+ {
+ ri->ri_noise = * ((int8_t*) iterator.this_arg);
+ got_noise = 1;
+ }
+ break;
+ case IEEE80211_RADIOTAP_DB_ANTNOISE:
+ if (!got_noise)
+ {
+ ri->ri_noise = * ((int8_t*) iterator.this_arg);
+ got_noise = 1;
+ }
+ break;
+ case IEEE80211_RADIOTAP_ANTENNA:
+ ri->ri_antenna = *iterator.this_arg;
+ break;
+ case IEEE80211_RADIOTAP_CHANNEL:
+ ri->ri_channel = *iterator.this_arg;
+ got_channel = 1;
+ break;
+ case IEEE80211_RADIOTAP_RATE:
+ ri->ri_rate = (*iterator.this_arg) * 500000;
+ break;
+ case IEEE80211_RADIOTAP_FLAGS:
+ {
+ uint8_t flags = *iterator.this_arg;
+ /* is the CRC visible at the end? if so, remove */
+ if (0 != (flags & IEEE80211_RADIOTAP_F_FCS))
+ {
+ fcs_removed = 1;
+ caplen -= sizeof (uint32_t);
+ }
+ break;
+ }
+ case IEEE80211_RADIOTAP_RX_FLAGS:
+ {
+ uint16_t flags = ntohs (* ((uint16_t *) iterator.this_arg));
+ if (0 != (flags & IEEE80211_RADIOTAP_F_RX_BADFCS))
+ return 0;
+ }
+ break;
+ } /* end of 'switch' */
+ } /* end of the 'while' loop */
+ }
break;
case ARPHRD_IEEE80211:
- /* do nothing? */
+ n = 0; /* no header */
break;
default:
- errno = ENOTSUP;
+ errno = ENOTSUP; /* unsupported format */
return -1;
}
-
caplen -= n;
+ if (! got_channel)
+ ri->ri_channel = linux_get_channel (dev);
- //detect fcs at the end, even if the flag wasn't set and remove it
- if ((0 == fcs_removed) && (0 == check_crc_buf_osdep (tmpbuf + n, caplen - 4)))
+ /* detect CRC32 at the end, even if the flag wasn't set and remove it */
+ if ( (0 == fcs_removed) &&
+ (0 == check_crc_buf_osdep (tmpbuf + n, caplen - sizeof (uint32_t))) )
{
- caplen -= 4;
+ /* NOTE: this heuristic can of course fail if there happens to
+ be a matching checksum at the end. Would be good to have
+ some data to see how often this heuristic actually works. */
+ caplen -= sizeof (uint32_t);
}
+ /* copy payload to target buffer */
memcpy (buf, tmpbuf + n, caplen);
- if (!got_channel)
- ri->ri_channel = linux_get_channel (dev);
-
return caplen;
}
+/* ************end of code for reading packets from kernel ************** */
+
+/* ************other helper functions for main start here ************** */
+
+
/**
* Open the wireless network interface for reading/writing.
*
@@ -1400,11 +1722,12 @@ open_device_raw (struct HardwareInfos *dev)
setsockopt (dev->fd_raw, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr,
sizeof (mr)))
{
- fprintf (stderr, "Failed to enable promiscuous mode on interface `%.*s'\n",
- IFNAMSIZ, dev->iface);
+ fprintf (stderr,
+ "Failed to enable promiscuous mode on interface `%.*s'\n",
+ IFNAMSIZ,
+ dev->iface);
return 1;
}
-
return 0;
}
@@ -1423,106 +1746,101 @@ test_wlan_interface (const char *iface)
struct stat sbuf;
int ret;
- /* mac80211 stack detection */
- ret =
- snprintf (strbuf, sizeof (strbuf), "/sys/class/net/%s/phy80211/subsystem",
- iface);
+ ret = snprintf (strbuf, sizeof (strbuf),
+ "/sys/class/net/%s/phy80211/subsystem",
+ iface);
if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf)))
{
- fprintf (stderr, "Did not find 802.11 interface `%s'. Exiting.\n", iface);
- return 1;
+ fprintf (stderr,
+ "Did not find 802.11 interface `%s'. Exiting.\n",
+ iface);
+ exit (1);
}
return 0;
}
/**
- * Function to test incoming packets mac for being our own.
+ * Test incoming packets mac for being our own.
*
- * @param uint8_taIeeeHeader buffer of the packet
+ * @param taIeeeHeader buffer of the packet
* @param dev the Hardware_Infos struct
* @return 0 if mac belongs to us, 1 if mac is for another target
*/
static int
-mac_test (const struct ieee80211_frame *uint8_taIeeeHeader,
+mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
const struct HardwareInfos *dev)
{
- if (0 != memcmp (uint8_taIeeeHeader->i_addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE))
- return 1;
- if (0 == memcmp (uint8_taIeeeHeader->i_addr1, &dev->pl_mac, MAC_ADDR_SIZE))
- return 0;
- if (0 == memcmp (uint8_taIeeeHeader->i_addr1, &bc_all_mac, MAC_ADDR_SIZE))
- return 0;
- return 1;
+ if (0 != memcmp (&taIeeeHeader->addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE))
+ return 1; /* not a GNUnet ad-hoc package */
+ if ( (0 == memcmp (&taIeeeHeader->addr1, &dev->pl_mac, MAC_ADDR_SIZE)) ||
+ (0 == memcmp (&taIeeeHeader->addr1, &bc_all_mac, MAC_ADDR_SIZE)) )
+ return 0; /* for us, or broadcast */
+ return 1; /* not for us */
}
/**
- * function to set the wlan header to make attacks more difficult
- * @param uint8_taIeeeHeader pointer to the header of the packet
+ * Set the wlan header to sane values to make attacks more difficult
+ *
+ * @param taIeeeHeader pointer to the header of the packet
* @param dev pointer to the Hardware_Infos struct
*/
static void
-mac_set (struct ieee80211_frame *uint8_taIeeeHeader,
+mac_set (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
const struct HardwareInfos *dev)
{
- uint8_taIeeeHeader->i_fc[0] = 0x08;
- uint8_taIeeeHeader->i_fc[1] = 0x00;
- memcpy (uint8_taIeeeHeader->i_addr2, &dev->pl_mac, MAC_ADDR_SIZE);
- memcpy (uint8_taIeeeHeader->i_addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE);
+ taIeeeHeader->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
+ taIeeeHeader->addr2 = dev->pl_mac;
+ taIeeeHeader->addr3 = mac_bssid_gnunet;
}
/**
- * function to process the data from the stdin
- * @param cls pointer to the device struct
+ * Process data from the stdin. Takes the message, prepends the
+ * radiotap transmission header, forces the sender MAC to be correct
+ * and puts it into our buffer for transmission to the kernel.
+ *
+ * @param cls pointer to the device struct ('struct HardwareInfos*')
* @param hdr pointer to the start of the packet
*/
static void
stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr)
{
struct HardwareInfos *dev = cls;
- struct Radiotap_Send *header = (struct Radiotap_Send *) &hdr[1];
- struct ieee80211_frame *wlanheader;
+ const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header;
+ struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *wlanheader;
size_t sendsize;
- struct RadioTapheader rtheader;
-
- rtheader.header.it_version = 0; /* radiotap version */
- rtheader.header.it_len = GNUNET_htole16 (0x0c); /* radiotap header length */
- rtheader.header.it_present = GNUNET_le16toh (0x00008004); /* our bitmap */
- rtheader.rate = 0x00;
- rtheader.pad1 = 0x00;
- rtheader.txflags =
- GNUNET_htole16 (IEEE80211_RADIOTAP_F_TX_NOACK | IEEE80211_RADIOTAP_F_TX_NOSEQ);
+ struct RadiotapTransmissionHeader rtheader;
sendsize = ntohs (hdr->size);
- if (sendsize <
- sizeof (struct Radiotap_Send) + sizeof (struct GNUNET_MessageHeader))
+ if ( (sendsize <
+ sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage)) ||
+ (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) )
{
- fprintf (stderr, "Function stdin_send_hw: malformed packet (too small)\n");
+ fprintf (stderr, "Received malformed message\n");
exit (1);
}
- sendsize -=
- sizeof (struct Radiotap_Send) + sizeof (struct GNUNET_MessageHeader);
-
+ sendsize -= (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame));
if (MAXLINE < sendsize)
{
- fprintf (stderr, "Function stdin_send_hw: Packet too big for buffer\n");
- exit (1);
- }
- if (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs (hdr->type))
- {
- fprintf (stderr, "Function stdin_send_hw: wrong packet type\n");
+ fprintf (stderr, "Packet too big for buffer\n");
exit (1);
}
-
+ header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr;
+ rtheader.header.it_version = 0;
+ rtheader.header.it_pad = 0;
rtheader.header.it_len = GNUNET_htole16 (sizeof (rtheader));
- rtheader.rate = header->rate;
+ rtheader.header.it_present = GNUNET_htole16 (IEEE80211_RADIOTAP_OUR_TRANSMISSION_HEADER_MASK);
+ rtheader.rate = header->rate;
+ rtheader.pad1 = 0;
+ rtheader.txflags = GNUNET_htole16 (IEEE80211_RADIOTAP_F_TX_NOACK | IEEE80211_RADIOTAP_F_TX_NOSEQ);
memcpy (write_pout.buf, &rtheader, sizeof (rtheader));
- memcpy (write_pout.buf + sizeof (rtheader), &header[1], sendsize);
+ memcpy (&write_pout.buf[sizeof (rtheader)], &header->frame, sendsize);
+ wlanheader = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &write_pout.buf[sizeof (rtheader)];
+
/* payload contains MAC address, but we don't trust it, so we'll
- * overwrite it with OUR MAC address again to prevent mischief */
- wlanheader = (struct ieee80211_frame *) (write_pout.buf + sizeof (rtheader));
+ * overwrite it with OUR MAC address to prevent mischief */
mac_set (wlanheader, dev);
write_pout.size = sendsize + sizeof (rtheader);
}
@@ -1721,33 +2039,30 @@ main (int argc, char *argv[])
if (FD_ISSET (dev.fd_raw, &rfds))
{
- struct GNUNET_MessageHeader *header;
- struct Radiotap_rx *rxinfo;
- struct ieee80211_frame *datastart;
+ struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rrm;
ssize_t ret;
- header = (struct GNUNET_MessageHeader *) write_std.buf;
- rxinfo = (struct Radiotap_rx *) &header[1];
- datastart = (struct ieee80211_frame *) &rxinfo[1];
+ rrm = (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) write_std.buf;
ret =
- linux_read (&dev, (unsigned char *) datastart,
- sizeof (write_std.buf) - sizeof (struct Radiotap_rx) -
- sizeof (struct GNUNET_MessageHeader), rxinfo);
+ linux_read (&dev, (unsigned char *) &rrm->frame,
+ sizeof (write_std.buf)
+ - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
+ + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame),
+ rrm);
if (0 > ret)
{
fprintf (stderr, "Read error from raw socket: %s\n", strerror (errno));
break;
}
- if ((0 < ret) && (0 == mac_test (datastart, &dev)))
+ if ((0 < ret) && (0 == mac_test (&rrm->frame, &dev)))
{
- write_std.size =
- ret + sizeof (struct GNUNET_MessageHeader) +
- sizeof (struct Radiotap_rx);
- header->size = htons (write_std.size);
- header->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
+ write_std.size = ret
+ + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
+ - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame);
+ rrm->header.size = htons (write_std.size);
+ rrm->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER);
}
}
-
}
/* Error handling, try to clean up a bit at least */
mst_destroy (stdin_mst);
diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c
index cd9bb5c..c200cb5 100644
--- a/src/transport/gnunet-service-transport.c
+++ b/src/transport/gnunet-service-transport.c
@@ -76,6 +76,11 @@ struct GNUNET_CRYPTO_RsaPrivateKey *GST_my_private_key;
*/
struct GNUNET_ATS_SchedulingHandle *GST_ats;
+/**
+ * DEBUGGING connection counter
+ */
+static int connections;
+
/**
* Transmit our HELLO message to the given (connected) neighbour.
@@ -139,7 +144,7 @@ process_payload (const struct GNUNET_PeerIdentity *peer,
size_t size =
sizeof (struct InboundMessage) + msg_size +
sizeof (struct GNUNET_ATS_Information) * (ats_count + 1);
- char buf[size];
+ char buf[size] GNUNET_ALIGN;
struct GNUNET_ATS_Information *ap;
ret = GNUNET_TIME_UNIT_ZERO;
@@ -225,10 +230,12 @@ plugin_env_receive_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
if (NULL == message)
goto end;
type = ntohs (message->type);
-#if DEBUG_TRANSPORT
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received Message with type %u from peer `%s'\n", type, GNUNET_i2s (peer));
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received Message with type %u\n", type);
-#endif
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# bytes total received"),
+ ntohs (message->size), GNUNET_NO);
switch (type)
{
@@ -236,21 +243,17 @@ plugin_env_receive_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
GST_validation_handle_hello (message);
return ret;
case GNUNET_MESSAGE_TYPE_TRANSPORT_PING:
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"Processing `%s' from `%s'\n", "PING",
(sender_address !=
NULL) ? GST_plugins_a2s (&address) : "<inbound>");
-#endif
GST_validation_handle_ping (peer, message, &address, session);
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_PONG:
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"Processing `%s' from `%s'\n", "PONG",
(sender_address !=
NULL) ? GST_plugins_a2s (&address) : "<inbound>");
-#endif
GST_validation_handle_pong (peer, message);
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT:
@@ -262,8 +265,8 @@ plugin_env_receive_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
ats_count);
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK:
- GST_neighbours_handle_ack (message, peer, &address, session, ats,
- ats_count);
+ GST_neighbours_handle_session_ack (message, peer, &address, session, ats,
+ ats_count);
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT:
GST_neighbours_handle_disconnect_message (peer, message);
@@ -276,6 +279,10 @@ plugin_env_receive_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
break;
default:
/* should be payload */
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# bytes payload received"),
+ ntohs (message->size), GNUNET_NO);
ret = process_payload (peer, &address, session, message, ats, ats_count);
break;
}
@@ -285,11 +292,9 @@ end:
* this connections seem to go extra-slow */
GNUNET_ATS_address_update (GST_ats, &address, session, ats, ats_count);
#endif
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Allowing receive from peer %s to continue in %llu ms\n",
GNUNET_i2s (peer), (unsigned long long) ret.rel_value);
-#endif
return ret;
}
@@ -341,12 +346,10 @@ plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
struct GNUNET_HELLO_Address address;
GNUNET_assert (strlen (transport_name) > 0);
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Session %X to peer `%s' ended \n",
session, GNUNET_i2s (peer));
-#endif
if (NULL != session)
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"transport-ats",
"Telling ATS to destroy session %p from peer %s\n",
session, GNUNET_i2s (peer));
@@ -368,7 +371,7 @@ plugin_env_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
* @param addrlen length of the address
* @return ATS Information containing the network type
*/
-static const struct GNUNET_ATS_Information
+static struct GNUNET_ATS_Information
plugin_env_address_to_type (void *cls,
const struct sockaddr *addr,
size_t addrlen)
@@ -425,15 +428,12 @@ ats_request_address_change (void *cls,
/* ATS tells me to disconnect from peer */
if ((bw_in == 0) && (bw_out == 0))
{
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"ATS tells me to disconnect from peer `%s'\n",
GNUNET_i2s (&address->peer));
-#endif
GST_neighbours_force_disconnect (&address->peer);
return;
}
- /* will never return GNUNET_YES since connection is to be established */
GST_neighbours_switch_to_address (&address->peer, address, session, ats,
ats_count, bandwidth_in,
bandwidth_out);
@@ -458,10 +458,15 @@ neighbours_connect_notification (void *cls,
size_t len =
sizeof (struct ConnectInfoMessage) +
ats_count * sizeof (struct GNUNET_ATS_Information);
- char buf[len];
+ char buf[len] GNUNET_ALIGN;
struct ConnectInfoMessage *connect_msg = (struct ConnectInfoMessage *) buf;
struct GNUNET_ATS_Information *ap;
+ connections++;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "We are now connected to peer `%s' and %u peers in total\n",
+ GNUNET_i2s (peer), connections);
+
connect_msg->header.size = htons (sizeof (buf));
connect_msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_CONNECT);
connect_msg->ats_count = htonl (ats_count);
@@ -485,6 +490,11 @@ neighbours_disconnect_notification (void *cls,
{
struct DisconnectInfoMessage disconnect_msg;
+ connections--;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Peer `%s' disconnected and we are connected to %u peers\n",
+ GNUNET_i2s (peer), connections);
+
disconnect_msg.header.size = htons (sizeof (struct DisconnectInfoMessage));
disconnect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_DISCONNECT);
disconnect_msg.reserved = htonl (0);
@@ -560,7 +570,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
const struct GNUNET_CONFIGURATION_Handle *c)
{
char *keyfile;
-
+ struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded tmp;
/* setup globals */
GST_cfg = c;
if (GNUNET_OK !=
@@ -584,9 +594,15 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
}
GST_stats = GNUNET_STATISTICS_create ("transport", c);
GST_peerinfo = GNUNET_PEERINFO_connect (c);
+ memset (&GST_my_public_key, '\0', sizeof (GST_my_public_key));
+ memset (&tmp, '\0', sizeof (tmp));
GNUNET_CRYPTO_rsa_key_get_public (GST_my_private_key, &GST_my_public_key);
GNUNET_CRYPTO_hash (&GST_my_public_key, sizeof (GST_my_public_key),
&GST_my_identity.hashPubKey);
+
+ GNUNET_assert (NULL != GST_my_private_key);
+ GNUNET_assert (0 != memcmp (&GST_my_public_key, &tmp, sizeof (GST_my_public_key)));
+
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
NULL);
if (GST_peerinfo == NULL)
@@ -599,6 +615,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server,
/* start subsystems */
GST_hello_start (&process_hello_update, NULL);
+ GNUNET_assert (NULL != GST_hello_get());
GST_blacklist_start (server);
GST_ats =
GNUNET_ATS_scheduling_init (GST_cfg, &ats_request_address_change, NULL);
@@ -630,4 +647,4 @@ main (int argc, char *const *argv)
GNUNET_SERVICE_OPTION_NONE, &run, NULL)) ? 0 : 1;
}
-/* end of file gnunet-service-transport-new.c */
+/* end of file gnunet-service-transport.c */
diff --git a/src/transport/gnunet-service-transport_blacklist.c b/src/transport/gnunet-service-transport_blacklist.c
index 2089949..8c36888 100644
--- a/src/transport/gnunet-service-transport_blacklist.c
+++ b/src/transport/gnunet-service-transport_blacklist.c
@@ -113,7 +113,7 @@ struct GST_BlacklistCheck
* Current transmission request handle for this client, or NULL if no
* request is pending.
*/
- struct GNUNET_CONNECTION_TransmitHandle *th;
+ struct GNUNET_SERVER_TransmitHandle *th;
/**
* Our current position in the blacklisters list.
@@ -191,7 +191,7 @@ client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
bc->bl_pos = bl->next;
if (bc->th != NULL)
{
- GNUNET_CONNECTION_notify_transmit_ready_cancel (bc->th);
+ GNUNET_SERVER_notify_transmit_ready_cancel (bc->th);
bc->th = NULL;
}
if (bc->task == GNUNET_SCHEDULER_NO_TASK)
@@ -221,7 +221,7 @@ read_blacklist_file ()
size_t colon_pos;
int tsize;
struct GNUNET_PeerIdentity pid;
- struct stat frstat;
+ uint64_t fsize;
struct GNUNET_CRYPTO_HashAsciiEncoded enc;
unsigned int entries_found;
char *transport_name;
@@ -230,37 +230,34 @@ read_blacklist_file ()
GNUNET_CONFIGURATION_get_value_filename (GST_cfg, "TRANSPORT",
"BLACKLIST_FILE", &fn))
{
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Option `%s' in section `%s' not specified!\n",
"BLACKLIST_FILE", "TRANSPORT");
-#endif
return;
}
if (GNUNET_OK != GNUNET_DISK_file_test (fn))
GNUNET_DISK_fn_write (fn, NULL, 0,
GNUNET_DISK_PERM_USER_READ |
GNUNET_DISK_PERM_USER_WRITE);
- if (0 != STAT (fn, &frstat))
+ if (GNUNET_OK != GNUNET_DISK_file_size (fn,
+ &fsize, GNUNET_NO, GNUNET_YES))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_("Could not read blacklist file `%s'\n"), fn);
GNUNET_free (fn);
return;
}
- if (frstat.st_size == 0)
+ if (fsize == 0)
{
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Blacklist file `%s' is empty.\n"),
fn);
-#endif
GNUNET_free (fn);
return;
}
/* FIXME: use mmap */
- data = GNUNET_malloc_large (frstat.st_size);
+ data = GNUNET_malloc_large (fsize);
GNUNET_assert (data != NULL);
- if (frstat.st_size != GNUNET_DISK_fn_read (fn, data, frstat.st_size))
+ if (fsize != GNUNET_DISK_fn_read (fn, data, fsize))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_("Failed to read blacklist from `%s'\n"), fn);
@@ -270,17 +267,17 @@ read_blacklist_file ()
}
entries_found = 0;
pos = 0;
- while ((pos < frstat.st_size) && isspace ((unsigned char) data[pos]))
+ while ((pos < fsize) && isspace ((unsigned char) data[pos]))
pos++;
- while ((frstat.st_size >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
+ while ((fsize >= sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)) &&
(pos <=
- frstat.st_size - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
+ fsize - sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded)))
{
colon_pos = pos;
- while ((colon_pos < frstat.st_size) && (data[colon_pos] != ':') &&
+ while ((colon_pos < fsize) && (data[colon_pos] != ':') &&
(!isspace ((unsigned char) data[colon_pos])))
colon_pos++;
- if (colon_pos >= frstat.st_size)
+ if (colon_pos >= fsize)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
_
@@ -298,12 +295,12 @@ read_blacklist_file ()
("Syntax error in blacklist file at offset %llu, skipping bytes.\n"),
(unsigned long long) colon_pos);
pos = colon_pos;
- while ((pos < frstat.st_size) && isspace ((unsigned char) data[pos]))
+ while ((pos < fsize) && isspace ((unsigned char) data[pos]))
pos++;
continue;
}
tsize = colon_pos - pos;
- if ((pos >= frstat.st_size) || (pos + tsize >= frstat.st_size) ||
+ if ((pos >= fsize) || (pos + tsize >= fsize) ||
(tsize == 0))
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -321,11 +318,9 @@ read_blacklist_file ()
transport_name = GNUNET_malloc (tsize + 1);
memcpy (transport_name, &data[pos], tsize);
pos = colon_pos + 1;
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Read transport name `%s' in blacklist file.\n",
transport_name);
-#endif
memcpy (&enc, &data[pos], sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded));
if (!isspace
((unsigned char)
@@ -336,7 +331,7 @@ read_blacklist_file ()
("Syntax error in blacklist file at offset %llu, skipping bytes.\n"),
(unsigned long long) pos);
pos++;
- while ((pos < frstat.st_size) && (!isspace ((unsigned char) data[pos])))
+ while ((pos < fsize) && (!isspace ((unsigned char) data[pos])))
pos++;
GNUNET_free_non_null (transport_name);
continue;
@@ -367,7 +362,7 @@ read_blacklist_file ()
}
pos = pos + sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded);
GNUNET_free_non_null (transport_name);
- while ((pos < frstat.st_size) && isspace ((unsigned char) data[pos]))
+ while ((pos < fsize) && isspace ((unsigned char) data[pos]))
pos++;
}
GNUNET_STATISTICS_update (GST_stats, "# Transport entries blacklisted",
@@ -450,11 +445,9 @@ transmit_blacklist_message (void *cls, size_t size, void *buf)
GNUNET_i2s (&bc->peer));
return 0;
}
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Sending blacklist test for peer `%s' to client\n",
GNUNET_i2s (&bc->peer));
-#endif
bl = bc->bl_pos;
bm.header.size = htons (sizeof (struct BlacklistMessage));
bm.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BLACKLIST_QUERY);
@@ -483,11 +476,9 @@ do_blacklist_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
bl = bc->bl_pos;
if (bl == NULL)
{
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"No other blacklist clients active, will allow neighbour `%s'\n",
GNUNET_i2s (&bc->peer));
-#endif
bc->cont (bc->cont_cls, &bc->peer, GNUNET_OK);
GNUNET_CONTAINER_DLL_remove(bc_head, bc_tail, bc);
GNUNET_free (bc);
@@ -578,7 +569,6 @@ test_connection_ok (void *cls, const struct GNUNET_PeerIdentity *neighbour,
}
-
/**
* Initialize a blacklisting client. We got a blacklist-init
* message from this client, add him to the list of clients
@@ -606,6 +596,7 @@ GST_blacklist_handle_init (void *cls, struct GNUNET_SERVER_Client *client,
}
bl = bl->next;
}
+ GNUNET_SERVER_client_mark_monitor (client);
bl = GNUNET_malloc (sizeof (struct Blacklisters));
bl->client = client;
GNUNET_SERVER_client_keep (client);
@@ -639,9 +630,7 @@ GST_blacklist_handle_reply (void *cls, struct GNUNET_SERVER_Client *client,
bl = bl->next;
if (bl == NULL)
{
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Blacklist client disconnected\n");
-#endif
/* FIXME: other error handling here!? */
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
@@ -655,20 +644,16 @@ GST_blacklist_handle_reply (void *cls, struct GNUNET_SERVER_Client *client,
* cancelled in the meantime... */
if (ntohl (msg->is_allowed) == GNUNET_SYSERR)
{
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Blacklist check failed, peer not allowed\n");
-#endif
bc->cont (bc->cont_cls, &bc->peer, GNUNET_NO);
GNUNET_CONTAINER_DLL_remove (bc_head, bc_tail, bc);
GNUNET_free (bc);
}
else
{
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Blacklist check succeeded, continuing with checks\n");
-#endif
bc->bl_pos = bc->bl_pos->next;
bc->task = GNUNET_SCHEDULER_add_now (&do_blacklist_check, bc);
}
@@ -694,11 +679,9 @@ void
GST_blacklist_add_peer (const struct GNUNET_PeerIdentity *peer,
const char *transport_name)
{
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Adding peer `%s' with plugin `%s' to blacklist\n",
GNUNET_i2s (peer), transport_name);
-#endif
if (blacklist == NULL)
blacklist =
GNUNET_CONTAINER_multihashmap_create (TRANSPORT_BLACKLIST_HT_SIZE);
@@ -812,7 +795,7 @@ GST_blacklist_test_cancel (struct GST_BlacklistCheck *bc)
}
if (NULL != bc->th)
{
- GNUNET_CONNECTION_notify_transmit_ready_cancel (bc->th);
+ GNUNET_SERVER_notify_transmit_ready_cancel (bc->th);
bc->th = NULL;
}
GNUNET_free (bc);
diff --git a/src/transport/gnunet-service-transport_blacklist.h b/src/transport/gnunet-service-transport_blacklist.h
index 68da7e4..b8335ab 100644
--- a/src/transport/gnunet-service-transport_blacklist.h
+++ b/src/transport/gnunet-service-transport_blacklist.h
@@ -58,6 +58,7 @@ void
GST_blacklist_handle_init (void *cls, struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message);
+
/**
* A blacklisting client has sent us reply. Process it.
*
@@ -69,6 +70,7 @@ void
GST_blacklist_handle_reply (void *cls, struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message);
+
/**
* Add the given peer to the blacklist (for the given transport).
*
diff --git a/src/transport/gnunet-service-transport_clients.c b/src/transport/gnunet-service-transport_clients.c
index d6ff554..b298195 100644
--- a/src/transport/gnunet-service-transport_clients.c
+++ b/src/transport/gnunet-service-transport_clients.c
@@ -102,7 +102,7 @@ struct TransportClient
/**
* Current transmit request handle.
*/
- struct GNUNET_CONNECTION_TransmitHandle *th;
+ struct GNUNET_SERVER_TransmitHandle *th;
/**
* Length of the list of messages pending for this client.
@@ -208,10 +208,7 @@ setup_client (struct GNUNET_SERVER_Client *client)
GNUNET_assert (lookup_client (client) == NULL);
tc = GNUNET_malloc (sizeof (struct TransportClient));
tc->client = client;
-
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", tc);
-#endif
return tc;
}
@@ -293,10 +290,8 @@ transmit_to_client_callback (void *cls, size_t size, void *buf)
tc->th = NULL;
if (buf == NULL)
{
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Transmission to client failed, closing connection.\n");
-#endif
return 0;
}
cbuf = buf;
@@ -307,11 +302,9 @@ transmit_to_client_callback (void *cls, size_t size, void *buf)
msize = ntohs (msg->size);
if (msize + tsize > size)
break;
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Transmitting message of type %u to client %p.\n",
ntohs (msg->type), tc);
-#endif
GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail,
q);
tc->message_count--;
@@ -346,6 +339,12 @@ unicast (struct TransportClient *tc, const struct GNUNET_MessageHeader *msg,
struct ClientMessageQueueEntry *q;
uint16_t msize;
+ if (msg == NULL)
+ {
+ GNUNET_break (0);
+ return;
+ }
+
if ((tc->message_count >= MAX_PENDING) && (GNUNET_YES == may_drop))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -403,10 +402,8 @@ client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
tc = lookup_client (client);
if (tc == NULL)
return;
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"Client %p disconnected, cleaning up.\n", tc);
-#endif
while (NULL != (mqe = tc->message_queue_head))
{
GNUNET_CONTAINER_DLL_remove (tc->message_queue_head, tc->message_queue_tail,
@@ -417,7 +414,7 @@ client_disconnect_notification (void *cls, struct GNUNET_SERVER_Client *client)
GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, tc);
if (tc->th != NULL)
{
- GNUNET_CONNECTION_notify_transmit_ready_cancel (tc->th);
+ GNUNET_SERVER_notify_transmit_ready_cancel (tc->th);
tc->th = NULL;
}
GNUNET_break (0 == tc->message_count);
@@ -448,7 +445,7 @@ notify_client_about_neighbour (void *cls,
size_t size =
sizeof (struct ConnectInfoMessage) +
ats_count * sizeof (struct GNUNET_ATS_Information);
- char buf[size];
+ char buf[size] GNUNET_ALIGN;
GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
cim = (struct ConnectInfoMessage *) buf;
@@ -481,18 +478,14 @@ clients_handle_start (void *cls, struct GNUNET_SERVER_Client *client,
tc = lookup_client (client);
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"Client %p sent START\n", tc);
-#endif
if (tc != NULL)
{
/* got 'start' twice from the same client, not allowed */
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"TransportClient %p ServerClient %p sent multiple START messages\n",
tc, tc->client);
-#endif
GNUNET_break (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
@@ -623,23 +616,16 @@ clients_handle_send (void *cls, struct GNUNET_SERVER_Client *client,
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# bytes payload received for other peers"), msize,
- GNUNET_NO);
-#if DEBUG_TRANSPORT
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received `%s' request from client with target `%4s' and first message of type %u and total size %u\n",
"SEND", GNUNET_i2s (&obm->peer), ntohs (obmm->type), msize);
-#endif
if (GNUNET_NO == GST_neighbours_test_connected (&obm->peer))
{
/* not connected, not allowed to send; can happen due to asynchronous operations */
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Could not send message to peer `%s': not connected\n",
GNUNET_i2s (&obm->peer));
-#endif
GNUNET_STATISTICS_update (GST_stats,
gettext_noop
("# bytes payload dropped (other peer was not connected)"),
@@ -695,11 +681,9 @@ clients_handle_request_connect (void *cls, struct GNUNET_SERVER_Client *client,
gettext_noop
("# REQUEST CONNECT messages received"), 1,
GNUNET_NO);
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received a request connect message for peer `%s'\n",
GNUNET_i2s (&trcm->peer));
-#endif
(void) GST_blacklist_test_allowed (&trcm->peer, NULL, &try_connect_if_allowed,
NULL);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
diff --git a/src/transport/gnunet-service-transport_hello.c b/src/transport/gnunet-service-transport_hello.c
index 120f176..870c083 100644
--- a/src/transport/gnunet-service-transport_hello.c
+++ b/src/transport/gnunet-service-transport_hello.c
@@ -162,18 +162,18 @@ refresh_hello_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
gc.expiration =
GNUNET_TIME_relative_to_absolute
(GNUNET_CONSTANTS_HELLO_ADDRESS_EXPIRATION);
+
GNUNET_free (our_hello);
our_hello = GNUNET_HELLO_create (&GST_my_public_key, &address_generator, &gc);
-#if DEBUG_TRANSPORT
+ GNUNET_assert (NULL != our_hello);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
"Refreshed my `%s', new size is %d\n", "HELLO",
GNUNET_HELLO_size (our_hello));
-#endif
GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# refreshed my HELLO"), 1,
GNUNET_NO);
if (NULL != hello_cb)
hello_cb (hello_cb_cls, GST_hello_get ());
- GNUNET_PEERINFO_add_peer (GST_peerinfo, our_hello);
+ GNUNET_PEERINFO_add_peer (GST_peerinfo, our_hello, NULL, NULL);
hello_task =
GNUNET_SCHEDULER_add_delayed (HELLO_REFRESH_PERIOD, &refresh_hello_task,
NULL);
@@ -206,6 +206,7 @@ GST_hello_start (GST_HelloCallback cb, void *cb_cls)
hello_cb = cb;
hello_cb_cls = cb_cls;
our_hello = GNUNET_HELLO_create (&GST_my_public_key, NULL, NULL);
+ GNUNET_assert (NULL != our_hello);
refresh_hello ();
}
@@ -255,13 +256,11 @@ GST_hello_modify_addresses (int addremove,
{
struct OwnAddressList *al;
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- (add_remove ==
- GNUNET_YES) ? "Adding `%s':%s to the set of our addresses\n" :
- "Removing `%s':%s from the set of our addresses\n",
- GST_plugins_a2s (address), p->short_name);
-#endif
+ (addremove ==
+ GNUNET_YES) ? "Adding `%s' to the set of our addresses\n" :
+ "Removing `%s' from the set of our addresses\n",
+ GST_plugins_a2s (address));
GNUNET_assert (address != NULL);
if (GNUNET_NO == addremove)
{
diff --git a/src/transport/gnunet-service-transport_neighbours.c b/src/transport/gnunet-service-transport_neighbours.c
index 3e8ef5a..c580168 100644
--- a/src/transport/gnunet-service-transport_neighbours.c
+++ b/src/transport/gnunet-service-transport_neighbours.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet.
- (C) 2010,2011 Christian Grothoff (and other contributing authors)
+ (C) 2010,2011,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
@@ -22,6 +22,10 @@
* @file transport/gnunet-service-transport_neighbours.c
* @brief neighbour management
* @author Christian Grothoff
+ *
+ * TODO:
+ * - "address_change_cb" is NEVER invoked; when should we call this one exactly?
+ * - TEST, TEST, TEST...
*/
#include "platform.h"
#include "gnunet_ats_service.h"
@@ -42,6 +46,12 @@
#define NEIGHBOUR_TABLE_SIZE 256
/**
+ * Time we give plugin to transmit DISCONNECT message before the
+ * neighbour entry self-destructs.
+ */
+#define DISCONNECT_SENT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100)
+
+/**
* How often must a peer violate bandwidth quotas before we start
* to simply drop its messages?
*/
@@ -50,38 +60,53 @@
/**
* How often do we send KEEPALIVE messages to each of our neighbours and measure
* the latency with this neighbour?
- * (idle timeout is 5 minutes or 300 seconds, so with 30s interval we
- * send 10 keepalives in each interval, so 10 messages would need to be
+ * (idle timeout is 5 minutes or 300 seconds, so with 100s interval we
+ * send 3 keepalives in each interval, so 3 messages would need to be
* lost in a row for a disconnect).
*/
-#define KEEPALIVE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+#define KEEPALIVE_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
+/**
+ * How long are we willing to wait for a response from ATS before timing out?
+ */
+#define ATS_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500)
-#define ATS_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
-
-#define FAST_RECONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
-
+/**
+ * How long are we willing to wait for an ACK from the other peer before
+ * giving up on our connect operation?
+ */
#define SETUP_CONNECTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
-#define TEST_NEW_CODE GNUNET_NO
+/**
+ * How long are we willing to wait for a successful reconnect if
+ * an existing connection went down? Much shorter than the
+ * usual SETUP_CONNECTION_TIMEOUT as we do not inform the
+ * higher layers about the disconnect during this period.
+ */
+#define FAST_RECONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
/**
- * Entry in neighbours.
+ * How long are we willing to wait for a response from the blacklist
+ * subsystem before timing out?
*/
-struct NeighbourMapEntry;
+#define BLACKLIST_RESPONSE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500)
+
GNUNET_NETWORK_STRUCT_BEGIN
/**
- * Message a peer sends to another to indicate its
- * preference for communicating via a particular
- * session (and the desire to establish a real
- * connection).
+ * Message a peer sends to another to indicate that it intends to
+ * setup a connection/session for data exchange. A 'SESSION_CONNECT'
+ * should be answered with a 'SESSION_CONNECT_ACK' with the same body
+ * to confirm. A 'SESSION_CONNECT_ACK' should then be followed with
+ * a 'SESSION_ACK'. Once the 'SESSION_ACK' is received, both peers
+ * should be connected.
*/
struct SessionConnectMessage
{
/**
* Header of type 'GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT'
+ * or 'GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT_ACK'
*/
struct GNUNET_MessageHeader header;
@@ -99,6 +124,12 @@ struct SessionConnectMessage
};
+/**
+ * Message we send to the other peer to notify him that we intentionally
+ * are disconnecting (to reduce timeouts). This is just a friendly
+ * notification, peers must not rely on always receiving disconnect
+ * messages.
+ */
struct SessionDisconnectMessage
{
/**
@@ -136,8 +167,10 @@ struct SessionDisconnectMessage
struct GNUNET_CRYPTO_RsaSignature signature;
};
+
GNUNET_NETWORK_STRUCT_END
+
/**
* For each neighbour we keep a list of messages
* that we still want to transmit to the neighbour.
@@ -156,12 +189,6 @@ struct MessageQueue
struct MessageQueue *prev;
/**
- * Once this message is actively being transmitted, which
- * neighbour is it associated with?
- */
- struct NeighbourMapEntry *n;
-
- /**
* Function to call once we're done.
*/
GST_NeighbourSendContinuation cont;
@@ -190,44 +217,196 @@ struct MessageQueue
};
+/**
+ * Possible state of a neighbour. Initially, we are S_NOT_CONNECTED.
+ *
+ * Then, there are two main paths. If we receive a CONNECT message, we
+ * first run a check against the blacklist and ask ATS for a
+ * suggestion. (S_CONNECT_RECV_ATS). If the blacklist comes back
+ * positive, we give the address to ATS. If ATS makes a suggestion,
+ * we ALSO give that suggestion to the blacklist
+ * (S_CONNECT_RECV_BLACKLIST). Once the blacklist approves the
+ * address we got from ATS, we send our CONNECT_ACK and go to
+ * S_CONNECT_RECV_ACK. If we receive a SESSION_ACK, we go to
+ * S_CONNECTED (and notify everyone about the new connection). If the
+ * operation times out, we go to S_DISCONNECT.
+ *
+ * The other case is where we transmit a CONNECT message first. We
+ * start with S_INIT_ATS. If we get an address, we enter
+ * S_INIT_BLACKLIST and check the blacklist. If the blacklist is OK
+ * with the connection, we actually send the CONNECT message and go to
+ * state S_CONNECT_SENT. Once we receive a CONNECT_ACK, we go to
+ * S_CONNECTED (and notify everyone about the new connection and send
+ * back a SESSION_ACK). If the operation times out, we go to
+ * S_DISCONNECT.
+ *
+ * If the session is in trouble (i.e. transport-level disconnect or
+ * timeout), we go to S_RECONNECT_ATS where we ask ATS for a new
+ * address (we don't notify anyone about the disconnect yet). Once we
+ * have a new address, we go to S_RECONNECT_BLACKLIST to check the new
+ * address against the blacklist. If the blacklist approves, we enter
+ * S_RECONNECT_SENT and send a CONNECT message. If we receive a
+ * CONNECT_ACK, we go to S_CONNECTED and nobody noticed that we had
+ * trouble; we also send a SESSION_ACK at this time just in case. If
+ * the operation times out, we go to S_DISCONNECT (and notify everyone
+ * about the lost connection).
+ *
+ * If ATS decides to switch addresses while we have a normal
+ * connection, we go to S_CONNECTED_SWITCHING_BLACKLIST to check the
+ * new address against the blacklist. If the blacklist approves, we
+ * go to S_CONNECTED_SWITCHING_CONNECT_SENT and send a
+ * SESSION_CONNECT. If we get a SESSION_ACK back, we switch the
+ * primary connection to the suggested alternative from ATS, go back
+ * to S_CONNECTED and send a SESSION_ACK to the other peer just to be
+ * sure. If the operation times out (or the blacklist disapproves),
+ * we go to S_CONNECTED (and notify ATS that the given alternative
+ * address is "invalid").
+ *
+ * Once a session is in S_DISCONNECT, it is cleaned up and then goes
+ * to (S_DISCONNECT_FINISHED). If we receive an explicit disconnect
+ * request, we can go from any state to S_DISCONNECT, possibly after
+ * generating disconnect notifications.
+ *
+ * Note that it is quite possible that while we are in any of these
+ * states, we could receive a 'CONNECT' request from the other peer.
+ * We then enter a 'weird' state where we pursue our own primary state
+ * machine (as described above), but with the 'send_connect_ack' flag
+ * set to 1. If our state machine allows us to send a 'CONNECT_ACK'
+ * (because we have an acceptable address), we send the 'CONNECT_ACK'
+ * and set the 'send_connect_ack' to 2. If we then receive a
+ * 'SESSION_ACK', we go to 'S_CONNECTED' (and reset 'send_connect_ack'
+ * to 0).
+ *
+ */
enum State
{
/**
* fresh peer or completely disconnected
*/
- S_NOT_CONNECTED,
+ S_NOT_CONNECTED = 0,
+
+ /**
+ * Asked to initiate connection, trying to get address from ATS
+ */
+ S_INIT_ATS,
+
+ /**
+ * Asked to initiate connection, trying to get address approved
+ * by blacklist.
+ */
+ S_INIT_BLACKLIST,
/**
- * sent CONNECT message to other peer, waiting for CONNECT_ACK
+ * Sent CONNECT message to other peer, waiting for CONNECT_ACK
*/
S_CONNECT_SENT,
/**
- * received CONNECT message to other peer, sending CONNECT_ACK
+ * Received a CONNECT, asking ATS about address suggestions.
+ */
+ S_CONNECT_RECV_ATS,
+
+ /**
+ * Received CONNECT from other peer, got an address, checking with blacklist.
+ */
+ S_CONNECT_RECV_BLACKLIST,
+
+ /**
+ * CONNECT request from other peer was SESSION_ACK'ed, waiting for
+ * SESSION_ACK.
*/
- S_CONNECT_RECV,
+ S_CONNECT_RECV_ACK,
/**
- * received ACK or payload
+ * Got our CONNECT_ACK/SESSION_ACK, connection is up.
*/
S_CONNECTED,
/**
- * connection ended, fast reconnect
+ * Connection got into trouble, rest of the system still believes
+ * it to be up, but we're getting a new address from ATS.
+ */
+ S_RECONNECT_ATS,
+
+ /**
+ * Connection got into trouble, rest of the system still believes
+ * it to be up; we are checking the new address against the blacklist.
+ */
+ S_RECONNECT_BLACKLIST,
+
+ /**
+ * Sent CONNECT over new address (either by ATS telling us to switch
+ * addresses or from RECONNECT_ATS); if this fails, we need to tell
+ * the rest of the system about a disconnect.
+ */
+ S_RECONNECT_SENT,
+
+ /**
+ * We have some primary connection, but ATS suggested we switch
+ * to some alternative; we're now checking the alternative against
+ * the blacklist.
+ */
+ S_CONNECTED_SWITCHING_BLACKLIST,
+
+ /**
+ * We have some primary connection, but ATS suggested we switch
+ * to some alternative; we now sent a CONNECT message for the
+ * alternative session to the other peer and waiting for a
+ * CONNECT_ACK to make this our primary connection.
+ */
+ S_CONNECTED_SWITCHING_CONNECT_SENT,
+
+ /**
+ * Disconnect in progress (we're sending the DISCONNECT message to the
+ * other peer; after that is finished, the state will be cleaned up).
*/
- S_FAST_RECONNECT,
+ S_DISCONNECT,
/**
- * Disconnect in progress
+ * We're finished with the disconnect; clean up state now!
*/
- S_DISCONNECT
+ S_DISCONNECT_FINISHED
};
-enum Address_State
+
+/**
+ * A possible address we could use to communicate with a neighbour.
+ */
+struct NeighbourAddress
{
- USED,
- UNUSED,
- FRESH,
+
+ /**
+ * Active session for this address.
+ */
+ struct Session *session;
+
+ /**
+ * Network-level address information.
+ */
+ struct GNUNET_HELLO_Address *address;
+
+ /**
+ * Timestamp of the 'SESSION_CONNECT' message we sent to the other
+ * peer for this address. Use to check that the ACK is in response
+ * to our most recent 'CONNECT'.
+ */
+ struct GNUNET_TIME_Absolute connect_timestamp;
+
+ /**
+ * Inbound bandwidth from ATS for this address.
+ */
+ struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
+
+ /**
+ * Outbound bandwidth from ATS for this address.
+ */
+ struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
+
+ /**
+ * Did we tell ATS that this is our 'active' address?
+ */
+ int ats_active;
+
};
@@ -255,14 +434,15 @@ struct NeighbourMapEntry
struct MessageQueue *is_active;
/**
- * Active session for communicating with the peer.
+ * Primary address we currently use to communicate with the neighbour.
*/
- struct Session *session;
+ struct NeighbourAddress primary_address;
/**
- * Address we currently use.
+ * Alternative address currently under consideration for communicating
+ * with the neighbour.
*/
- struct GNUNET_HELLO_Address *address;
+ struct NeighbourAddress alternative_address;
/**
* Identity of this neighbour.
@@ -270,93 +450,133 @@ struct NeighbourMapEntry
struct GNUNET_PeerIdentity id;
/**
- * ID of task scheduled to run when this peer is about to
- * time out (will free resources associated with the peer).
+ * Main task that drives this peer (timeouts, keepalives, etc.).
+ * Always runs the 'master_task'.
*/
- GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+ GNUNET_SCHEDULER_TaskIdentifier task;
/**
- * ID of task scheduled to send keepalives.
+ * At what time should we sent the next keep-alive message?
*/
- GNUNET_SCHEDULER_TaskIdentifier keepalive_task;
+ struct GNUNET_TIME_Absolute keep_alive_time;
/**
- * ID of task scheduled to run when we should try transmitting
- * the head of the message queue.
+ * At what time did we sent the last keep-alive message? Used
+ * to calculate round-trip time ("latency").
*/
- GNUNET_SCHEDULER_TaskIdentifier transmission_task;
+ struct GNUNET_TIME_Absolute last_keep_alive_time;
/**
- * Tracker for inbound bandwidth.
+ * Timestamp we should include in our next CONNECT_ACK message.
+ * (only valid if 'send_connect_ack' is GNUNET_YES). Used to build
+ * our CONNECT_ACK message.
*/
- struct GNUNET_BANDWIDTH_Tracker in_tracker;
+ struct GNUNET_TIME_Absolute connect_ack_timestamp;
/**
- * Inbound bandwidth from ATS, activated when connection is up
+ * Time where we should cut the connection (timeout) if we don't
+ * make progress in the state machine (or get a KEEPALIVE_RESPONSE
+ * if we are in S_CONNECTED).
*/
- struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in;
+ struct GNUNET_TIME_Absolute timeout;
/**
- * Inbound bandwidth from ATS, activated when connection is up
+ * Latest calculated latency value
*/
- struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out;
+ struct GNUNET_TIME_Relative latency;
/**
- * Timestamp of the 'SESSION_CONNECT' message we got from the other peer
+ * Tracker for inbound bandwidth.
*/
- struct GNUNET_TIME_Absolute connect_ts;
+ struct GNUNET_BANDWIDTH_Tracker in_tracker;
/**
- * When did we sent the last keep-alive message?
+ * How often has the other peer (recently) violated the inbound
+ * traffic limit? Incremented by 10 per violation, decremented by 1
+ * per non-violation (for each time interval).
*/
- struct GNUNET_TIME_Absolute keep_alive_sent;
+ unsigned int quota_violation_count;
/**
- * Latest calculated latency value
+ * The current state of the peer.
*/
- struct GNUNET_TIME_Relative latency;
+ enum State state;
/**
- * Timeout for ATS
- * We asked ATS for a new address for this peer
+ * Did we sent an KEEP_ALIVE message and are we expecting a response?
*/
- GNUNET_SCHEDULER_TaskIdentifier ats_suggest;
+ int expect_latency_response;
/**
- * Task the resets the peer state after due to an pending
- * unsuccessful connection setup
+ * Flag to set if we still need to send a CONNECT_ACK message to the other peer
+ * (once we have an address to use and the peer has been allowed by our
+ * blacklist). Set to 1 if we need to send a CONNECT_ACK. Set to 2 if we
+ * did send a CONNECT_ACK and should go to 'S_CONNECTED' upon receiving
+ * a 'SESSION_ACK' (regardless of what our own state machine might say).
*/
- GNUNET_SCHEDULER_TaskIdentifier state_reset;
+ int send_connect_ack;
+
+};
+/**
+ * Context for blacklist checks and the 'handle_test_blacklist_cont'
+ * function. Stores information about ongoing blacklist checks.
+ */
+struct BlackListCheckContext
+{
+
/**
- * How often has the other peer (recently) violated the inbound
- * traffic limit? Incremented by 10 per violation, decremented by 1
- * per non-violation (for each time interval).
+ * We keep blacklist checks in a DLL.
*/
- unsigned int quota_violation_count;
+ struct BlackListCheckContext *next;
+ /**
+ * We keep blacklist checks in a DLL.
+ */
+ struct BlackListCheckContext *prev;
/**
- * The current state of the peer
- * Element of enum State
+ * Address that is being checked.
*/
- int state;
+ struct NeighbourAddress na;
+
+ /**
+ * ATS information about the address.
+ */
+ struct GNUNET_ATS_Information *ats;
/**
- * Did we sent an KEEP_ALIVE message and are we expecting a response?
+ * Handle to the ongoing blacklist check.
*/
- int expect_latency_response;
- int address_state;
+ struct GST_BlacklistCheck *bc;
+
+ /**
+ * Size of the 'ats' array.
+ */
+ uint32_t ats_count;
+
};
/**
- * All known neighbours and their HELLOs.
+ * Hash map from peer identities to the respective 'struct NeighbourMapEntry'.
*/
static struct GNUNET_CONTAINER_MultiHashMap *neighbours;
/**
+ * We keep blacklist checks in a DLL so that we can find
+ * the 'sessions' in their 'struct NeighbourAddress' if
+ * a session goes down.
+ */
+static struct BlackListCheckContext *bc_head;
+
+/**
+ * We keep blacklist checks in a DLL.
+ */
+static struct BlackListCheckContext *bc_tail;
+
+/**
* Closure for connect_notify_cb, disconnect_notify_cb and address_change_cb
*/
static void *callback_cls;
@@ -379,7 +599,13 @@ static GNUNET_TRANSPORT_PeerIterateCallback address_change_cb;
/**
* counter for connected neighbours
*/
-static int neighbours_connected;
+static unsigned int neighbours_connected;
+
+/**
+ * Number of bytes we have currently queued for transmission.
+ */
+static unsigned long long bytes_in_send_queue;
+
/**
* Lookup a neighbour entry in the neighbours hash map.
@@ -390,468 +616,395 @@ static int neighbours_connected;
static struct NeighbourMapEntry *
lookup_neighbour (const struct GNUNET_PeerIdentity *pid)
{
+ if (NULL == neighbours)
+ return NULL;
return GNUNET_CONTAINER_multihashmap_get (neighbours, &pid->hashPubKey);
}
-/**
- * Disconnect from the given neighbour, clean up the record.
- *
- * @param n neighbour to disconnect from
- */
-static void
-disconnect_neighbour (struct NeighbourMapEntry *n);
-
-#define change_state(n, state, ...) change (n, state, __LINE__)
-
-static int
-is_connecting (struct NeighbourMapEntry *n)
-{
- if ((n->state > S_NOT_CONNECTED) && (n->state < S_CONNECTED))
- return GNUNET_YES;
- return GNUNET_NO;
-}
-
-static int
-is_connected (struct NeighbourMapEntry *n)
-{
- if (n->state == S_CONNECTED)
- return GNUNET_YES;
- return GNUNET_NO;
-}
-
-static int
-is_disconnecting (struct NeighbourMapEntry *n)
-{
- if (n->state == S_DISCONNECT)
- return GNUNET_YES;
- return GNUNET_NO;
-}
-
static const char *
print_state (int state)
{
+
switch (state)
{
- case S_CONNECTED:
- return "S_CONNECTED";
+ case S_NOT_CONNECTED:
+ return "S_NOT_CONNECTED";
+ break;
+ case S_INIT_ATS:
+ return "S_INIT_ATS";
break;
- case S_CONNECT_RECV:
- return "S_CONNECT_RECV";
+ case S_INIT_BLACKLIST:
+ return "S_INIT_BLACKLIST";
break;
case S_CONNECT_SENT:
return "S_CONNECT_SENT";
break;
- case S_DISCONNECT:
- return "S_DISCONNECT";
+ case S_CONNECT_RECV_ATS:
+ return "S_CONNECT_RECV_ATS";
break;
- case S_NOT_CONNECTED:
- return "S_NOT_CONNECTED";
+ case S_CONNECT_RECV_BLACKLIST:
+ return "S_CONNECT_RECV_BLACKLIST";
break;
- case S_FAST_RECONNECT:
- return "S_FAST_RECONNECT";
+ case S_CONNECT_RECV_ACK:
+ return "S_CONNECT_RECV_ACK";
break;
- default:
- GNUNET_break (0);
+ case S_CONNECTED:
+ return "S_CONNECTED";
break;
- }
- return NULL;
-}
-
-static int
-change (struct NeighbourMapEntry *n, int state, int line);
-
-static void
-ats_suggest_cancel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-static void
-reset_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct NeighbourMapEntry *n = cls;
-
- if (n == NULL)
- return;
-
- n->state_reset = GNUNET_SCHEDULER_NO_TASK;
- if (n->state == S_CONNECTED)
- return;
-
-#if DEBUG_TRANSPORT
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# failed connection attempts due to timeout"), 1,
- GNUNET_NO);
-#endif
-
- /* resetting state */
-
- if (n->state == S_FAST_RECONNECT)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Fast reconnect time out, disconnecting peer `%s'\n",
- GNUNET_i2s (&n->id));
- disconnect_neighbour(n);
- return;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "State for neighbour `%s' %X changed from `%s' to `%s' in line %u\n",
- GNUNET_i2s (&n->id), n, print_state(n->state), "S_NOT_CONNECTED", __LINE__);
-
- n->state = S_NOT_CONNECTED;
-
- /* destroying address */
- if (n->address != NULL)
- {
- GNUNET_assert (strlen (n->address->transport_name) > 0);
- GNUNET_ATS_address_destroyed (GST_ats, n->address, n->session);
- }
-
- /* request new address */
- if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest =
- GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel,
- n);
- GNUNET_ATS_suggest_address (GST_ats, &n->id);
-}
-
-static int
-change (struct NeighbourMapEntry *n, int state, int line)
-{
- int previous_state;
- /* allowed transitions */
- int allowed = GNUNET_NO;
-
- previous_state = n->state;
-
- switch (n->state)
- {
- case S_NOT_CONNECTED:
- if ((state == S_CONNECT_RECV) || (state == S_CONNECT_SENT) ||
- (state == S_DISCONNECT))
- allowed = GNUNET_YES;
+ case S_RECONNECT_ATS:
+ return "S_RECONNECT_ATS";
break;
- case S_CONNECT_RECV:
- allowed = GNUNET_YES;
+ case S_RECONNECT_BLACKLIST:
+ return "S_RECONNECT_BLACKLIST";
break;
- case S_CONNECT_SENT:
- allowed = GNUNET_YES;
+ case S_RECONNECT_SENT:
+ return "S_RECONNECT_SENT";
break;
- case S_CONNECTED:
- if ((state == S_DISCONNECT) || (state == S_FAST_RECONNECT))
- allowed = GNUNET_YES;
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ return "S_CONNECTED_SWITCHING_BLACKLIST";
+ break;
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ return "S_CONNECTED_SWITCHING_CONNECT_SENT";
break;
case S_DISCONNECT:
+ return "S_DISCONNECT";
break;
- case S_FAST_RECONNECT:
- if ((state == S_CONNECTED) || (state == S_DISCONNECT))
- allowed = GNUNET_YES;
+ case S_DISCONNECT_FINISHED:
+ return "S_DISCONNECT_FINISHED";
break;
default:
+ return "UNDEFINED";
GNUNET_break (0);
break;
}
- if (allowed == GNUNET_NO)
- {
- char *old = GNUNET_strdup (print_state (n->state));
- char *new = GNUNET_strdup (print_state (state));
-
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Illegal state transition from `%s' to `%s' in line %u \n", old,
- new, line);
- GNUNET_break (0);
- GNUNET_free (old);
- GNUNET_free (new);
- return GNUNET_SYSERR;
- }
- {
- char *old = GNUNET_strdup (print_state (n->state));
- char *new = GNUNET_strdup (print_state (state));
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "State for neighbour `%s' %X changed from `%s' to `%s' in line %u\n",
- GNUNET_i2s (&n->id), n, old, new, line);
- GNUNET_free (old);
- GNUNET_free (new);
- }
- n->state = state;
+ GNUNET_break (0);
+ return "UNDEFINED";
+}
+/**
+ * Test if we're connected to the given peer.
+ *
+ * @param n neighbour entry of peer to test
+ * @return GNUNET_YES if we are connected, GNUNET_NO if not
+ */
+static int
+test_connected (struct NeighbourMapEntry *n)
+{
+ if (NULL == n)
+ return GNUNET_NO;
switch (n->state)
{
- case S_FAST_RECONNECT:
- case S_CONNECT_RECV:
+ case S_NOT_CONNECTED:
+ case S_INIT_ATS:
+ case S_INIT_BLACKLIST:
case S_CONNECT_SENT:
- if (n->state_reset != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (n->state_reset);
- n->state_reset =
- GNUNET_SCHEDULER_add_delayed (SETUP_CONNECTION_TIMEOUT, &reset_task, n);
- break;
+ case S_CONNECT_RECV_ATS:
+ case S_CONNECT_RECV_BLACKLIST:
+ case S_CONNECT_RECV_ACK:
+ return GNUNET_NO;
case S_CONNECTED:
- case S_NOT_CONNECTED:
+ case S_RECONNECT_ATS:
+ case S_RECONNECT_BLACKLIST:
+ case S_RECONNECT_SENT:
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ return GNUNET_YES;
case S_DISCONNECT:
- if (GNUNET_SCHEDULER_NO_TASK != n->state_reset)
- {
-#if DEBUG_TRANSPORT
- char *old = GNUNET_strdup (print_state (n->state));
- char *new = GNUNET_strdup (print_state (state));
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Removed reset task for peer `%s' %s failed in state transition `%s' -> `%s' \n",
- GNUNET_i2s (&n->id), GST_plugins_a2s (n->address), old, new);
- GNUNET_free (old);
- GNUNET_free (new);
-#endif
- GNUNET_assert (n->state_reset != GNUNET_SCHEDULER_NO_TASK);
- GNUNET_SCHEDULER_cancel (n->state_reset);
- n->state_reset = GNUNET_SCHEDULER_NO_TASK;
- }
- break;
-
+ case S_DISCONNECT_FINISHED:
+ return GNUNET_NO;
default:
- GNUNET_assert (0);
- }
-
- if (NULL != address_change_cb)
- {
- if (n->state == S_CONNECTED)
- address_change_cb (callback_cls, &n->id, n->address);
- else if (previous_state == S_CONNECTED)
- address_change_cb (callback_cls, &n->id, NULL);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
+ GNUNET_break (0);
+ break;
}
-
- return GNUNET_OK;
+ return GNUNET_SYSERR;
}
-static ssize_t
-send_with_session (struct NeighbourMapEntry *n,
- const char *msgbuf, size_t msgbuf_size,
- uint32_t priority,
- struct GNUNET_TIME_Relative timeout,
- GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
+/**
+ * Send information about a new outbound quota to our clients.
+ *
+ * @param target affected peer
+ * @param quota new quota
+ */
+static void
+send_outbound_quota (const struct GNUNET_PeerIdentity *target,
+ struct GNUNET_BANDWIDTH_Value32NBO quota)
{
- struct GNUNET_TRANSPORT_PluginFunctions *papi;
- size_t ret = GNUNET_SYSERR;
-
- GNUNET_assert (n != NULL);
- GNUNET_assert (n->session != NULL);
-
- papi = GST_plugins_find (n->address->transport_name);
- if (papi == NULL)
- {
- if (cont != NULL)
- cont (cont_cls, &n->id, GNUNET_SYSERR);
- return GNUNET_SYSERR;
- }
-
- ret = papi->send (papi->cls,
- n->session,
- msgbuf, msgbuf_size,
- 0,
- timeout,
- cont, cont_cls);
+ struct QuotaSetMessage q_msg;
- if ((ret == -1) && (cont != NULL))
- cont (cont_cls, &n->id, GNUNET_SYSERR);
- return ret;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending outbound quota of %u Bps for peer `%s' to all clients\n",
+ ntohl (quota.value__), GNUNET_i2s (target));
+ q_msg.header.size = htons (sizeof (struct QuotaSetMessage));
+ q_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA);
+ q_msg.quota = quota;
+ q_msg.peer = (*target);
+ GST_clients_broadcast (&q_msg.header, GNUNET_NO);
}
+
/**
- * Task invoked to start a transmission to another peer.
+ * We don't need a given neighbour address any more.
+ * Release its resources and give appropriate notifications
+ * to ATS and other subsystems.
*
- * @param cls the 'struct NeighbourMapEntry'
- * @param tc scheduler context
+ * @param na address we are done with; 'na' itself must NOT be 'free'd, only the contents!
*/
static void
-transmission_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+free_address (struct NeighbourAddress *na)
+{
+ if (GNUNET_YES == na->ats_active)
+ {
+ GST_validation_set_address_use (na->address, na->session, GNUNET_NO, __LINE__);
+ GNUNET_ATS_address_in_use (GST_ats, na->address, na->session, GNUNET_NO);
+ }
+ na->ats_active = GNUNET_NO;
+ if (NULL != na->address)
+ {
+ GNUNET_HELLO_address_free (na->address);
+ na->address = NULL;
+ }
+ na->session = NULL;
+}
/**
- * We're done with our transmission attempt, continue processing.
+ * Initialize the 'struct NeighbourAddress'.
*
- * @param cls the 'struct MessageQueue' of the message
- * @param receiver intended receiver
- * @param success whether it worked or not
+ * @param na neighbour address to initialize
+ * @param address address of the other peer, NULL if other peer
+ * connected to us
+ * @param session session to use (or NULL, in which case an
+ * address must be setup)
+ * @param bandwidth_in inbound quota to be used when connection is up
+ * @param bandwidth_out outbound quota to be used when connection is up
+ * @param is_active GNUNET_YES to mark this as the active address with ATS
*/
static void
-transmit_send_continuation (void *cls,
- const struct GNUNET_PeerIdentity *receiver,
- int success)
+set_address (struct NeighbourAddress *na,
+ const struct GNUNET_HELLO_Address *address,
+ struct Session *session,
+ struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
+ struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
+ int is_active)
{
- struct MessageQueue *mq = cls;
- struct NeighbourMapEntry *n;
- struct NeighbourMapEntry *tmp;
+ struct GNUNET_TRANSPORT_PluginFunctions *papi;
- tmp = lookup_neighbour (receiver);
- n = mq->n;
- if ((NULL != n) && (tmp != NULL) && (tmp == n))
+ if (NULL == (papi = GST_plugins_find (address->transport_name)))
{
- GNUNET_assert (n->is_active == mq);
- n->is_active = NULL;
- if (success == GNUNET_YES)
+ GNUNET_break (0);
+ return;
+ }
+ if (session == na->session)
+ {
+ na->bandwidth_in = bandwidth_in;
+ na->bandwidth_out = bandwidth_out;
+ if (is_active != na->ats_active)
{
- GNUNET_assert (n->transmission_task == GNUNET_SCHEDULER_NO_TASK);
- n->transmission_task = GNUNET_SCHEDULER_add_now (&transmission_task, n);
+ na->ats_active = is_active;
+ GNUNET_ATS_address_in_use (GST_ats, na->address, na->session, is_active);
+ GST_validation_set_address_use (na->address, na->session, is_active, __LINE__);
}
+ if (GNUNET_YES == is_active)
+ {
+ /* FIXME: is this the right place to set quotas? */
+ GST_neighbours_set_incoming_quota (&address->peer, bandwidth_in);
+ send_outbound_quota (&address->peer, bandwidth_out);
+ }
+ return;
+ }
+ free_address (na);
+ if (NULL == session)
+ session = papi->get_session (papi->cls, address);
+ if (NULL == session)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Failed to obtain new session for peer `%s' and address '%s'\n",
+ GNUNET_i2s (&address->peer), GST_plugins_a2s (address));
+ GNUNET_ATS_address_destroyed (GST_ats, address, NULL);
+ return;
+ }
+ na->address = GNUNET_HELLO_address_copy (address);
+ na->bandwidth_in = bandwidth_in;
+ na->bandwidth_out = bandwidth_out;
+ na->session = session;
+ na->ats_active = is_active;
+ if (GNUNET_YES == is_active)
+ {
+ /* Telling ATS about new session */
+ GNUNET_ATS_address_update (GST_ats, na->address, na->session, NULL, 0);
+ GNUNET_ATS_address_in_use (GST_ats, na->address, na->session, GNUNET_YES);
+ GST_validation_set_address_use (na->address, na->session, GNUNET_YES, __LINE__);
+
+ /* FIXME: is this the right place to set quotas? */
+ GST_neighbours_set_incoming_quota (&address->peer, bandwidth_in);
+ send_outbound_quota (&address->peer, bandwidth_out);
}
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message of type %u was %s\n",
- ntohs (((struct GNUNET_MessageHeader *) mq->message_buf)->type),
- (success == GNUNET_OK) ? "successful" : "FAILED");
-#endif
- if (NULL != mq->cont)
- mq->cont (mq->cont_cls, success);
- GNUNET_free (mq);
}
/**
- * Check the ready list for the given neighbour and if a plugin is
- * ready for transmission (and if we have a message), do so!
+ * Free a neighbour map entry.
*
- * @param n target peer for which to transmit
+ * @param n entry to free
+ * @param keep_sessions GNUNET_NO to tell plugin to terminate sessions,
+ * GNUNET_YES to keep all sessions
*/
static void
-try_transmission_to_peer (struct NeighbourMapEntry *n)
+free_neighbour (struct NeighbourMapEntry *n, int keep_sessions)
{
struct MessageQueue *mq;
- struct GNUNET_TIME_Relative timeout;
- ssize_t ret;
+ struct GNUNET_TRANSPORT_PluginFunctions *papi;
- if (n->is_active != NULL)
- {
- GNUNET_break (0);
- return; /* transmission already pending */
- }
- if (n->transmission_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_break (0);
- return; /* currently waiting for bandwidth */
- }
+ n->is_active = NULL; /* always free'd by its own continuation! */
+
+ /* fail messages currently in the queue */
while (NULL != (mq = n->messages_head))
{
- timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout);
- if (timeout.rel_value > 0)
- break;
GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq);
- n->is_active = mq;
- mq->n = n;
- transmit_send_continuation (mq, &n->id, GNUNET_SYSERR); /* timeout */
+ if (NULL != mq->cont)
+ mq->cont (mq->cont_cls, GNUNET_SYSERR);
+ GNUNET_free (mq);
}
- if (NULL == mq)
- return; /* no more messages */
-
- if (n->address == NULL)
+ /* It is too late to send other peer disconnect notifications, but at
+ least internally we need to get clean... */
+ if (GNUNET_YES == test_connected (n))
{
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No address for peer `%s'\n",
- GNUNET_i2s (&n->id));
-#endif
- GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq);
- transmit_send_continuation (mq, &n->id, GNUNET_SYSERR);
- GNUNET_assert (n->transmission_task == GNUNET_SCHEDULER_NO_TASK);
- n->transmission_task = GNUNET_SCHEDULER_add_now (&transmission_task, n);
- return;
+ GNUNET_STATISTICS_set (GST_stats,
+ gettext_noop ("# peers connected"),
+ --neighbours_connected,
+ GNUNET_NO);
+ disconnect_notify_cb (callback_cls, &n->id);
}
- if (GST_plugins_find (n->address->transport_name) == NULL)
- {
- GNUNET_break (0);
- return;
- }
- GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq);
- n->is_active = mq;
- mq->n = n;
+ /* FIXME-PLUGIN-API: This does not seem to guarantee that all
+ transport sessions eventually get killed due to inactivity; they
+ MUST have their own timeout logic (but at least TCP doesn't have
+ one yet). Are we sure that EVERY 'session' of a plugin is
+ actually cleaned up this way!? Note that if we are switching
+ between two TCP sessions to the same peer, the existing plugin
+ API gives us not even the means to selectively kill only one of
+ them! Killing all sessions like this seems to be very, very
+ wrong. */
+ if ((GNUNET_NO == keep_sessions) &&
+ (NULL != n->primary_address.address) &&
+ (NULL != (papi = GST_plugins_find (n->primary_address.address->transport_name))))
+ papi->disconnect (papi->cls, &n->id);
- if ((n->address->address_length == 0) && (n->session == NULL))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No address for peer `%s'\n",
- GNUNET_i2s (&n->id));
- transmit_send_continuation (mq, &n->id, GNUNET_SYSERR);
- GNUNET_assert (n->transmission_task == GNUNET_SCHEDULER_NO_TASK);
- n->transmission_task = GNUNET_SCHEDULER_add_now (&transmission_task, n);
- return;
- }
+ n->state = S_DISCONNECT_FINISHED;
- ret = send_with_session(n,
- mq->message_buf, mq->message_buf_size,
- 0, timeout,
- &transmit_send_continuation, mq);
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove (neighbours,
+ &n->id.hashPubKey, n));
+
+ /* cut transport-level connection */
+ free_address (&n->primary_address);
+ free_address (&n->alternative_address);
- if (ret == -1)
+ // FIXME-ATS-API: we might want to be more specific about
+ // which states we do this from in the future (ATS should
+ // have given us a 'suggest_address' handle, and if we have
+ // such a handle, we should cancel the operation here!
+ GNUNET_ATS_suggest_address_cancel (GST_ats, &n->id);
+
+ if (GNUNET_SCHEDULER_NO_TASK != n->task)
{
- /* failure, but 'send' would not call continuation in this case,
- * so we need to do it here! */
- transmit_send_continuation (mq, &n->id, GNUNET_SYSERR);
+ GNUNET_SCHEDULER_cancel (n->task);
+ n->task = GNUNET_SCHEDULER_NO_TASK;
}
-
+ /* free rest of memory */
+ GNUNET_free (n);
}
/**
- * Task invoked to start a transmission to another peer.
+ * Transmit a message using the current session of the given
+ * neighbour.
*
- * @param cls the 'struct NeighbourMapEntry'
- * @param tc scheduler context
+ * @param n entry for the recipient
+ * @param msgbuf buffer to transmit
+ * @param msgbuf_size number of bytes in buffer
+ * @param priority transmission priority
+ * @param timeout transmission timeout
+ * @param cont continuation to call when finished (can be NULL)
+ * @param cont_cls closure for cont
*/
static void
-transmission_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+send_with_session (struct NeighbourMapEntry *n,
+ const char *msgbuf, size_t msgbuf_size,
+ uint32_t priority,
+ struct GNUNET_TIME_Relative timeout,
+ GNUNET_TRANSPORT_TransmitContinuation cont,
+ void *cont_cls)
{
- struct NeighbourMapEntry *n = cls;
+ struct GNUNET_TRANSPORT_PluginFunctions *papi;
- GNUNET_assert (NULL != lookup_neighbour (&n->id));
- n->transmission_task = GNUNET_SCHEDULER_NO_TASK;
- try_transmission_to_peer (n);
+ GNUNET_assert (n->primary_address.session != NULL);
+ if ( ( (NULL == (papi = GST_plugins_find (n->primary_address.address->transport_name))) ||
+ (-1 == papi->send (papi->cls,
+ n->primary_address.session,
+ msgbuf, msgbuf_size,
+ priority,
+ timeout,
+ cont, cont_cls))) &&
+ (NULL != cont) )
+ cont (cont_cls, &n->id, GNUNET_SYSERR);
+ GNUNET_break (NULL != papi);
}
/**
- * Initialize the neighbours subsystem.
+ * Master task run for every neighbour. Performs all of the time-related
+ * activities (keep alive, send next message, disconnect if idle, finish
+ * clean up after disconnect).
*
- * @param cls closure for callbacks
- * @param connect_cb function to call if we connect to a peer
- * @param disconnect_cb function to call if we disconnect from a peer
- * @param peer_address_cb function to call if we change an active address
- * of a neighbour
+ * @param cls the 'struct NeighbourMapEntry' for which we are running
+ * @param tc scheduler context (unused)
*/
-void
-GST_neighbours_start (void *cls,
- GNUNET_TRANSPORT_NotifyConnect connect_cb,
- GNUNET_TRANSPORT_NotifyDisconnect disconnect_cb,
- GNUNET_TRANSPORT_PeerIterateCallback peer_address_cb)
-{
- callback_cls = cls;
- connect_notify_cb = connect_cb;
- disconnect_notify_cb = disconnect_cb;
- address_change_cb = peer_address_cb;
- neighbours = GNUNET_CONTAINER_multihashmap_create (NEIGHBOUR_TABLE_SIZE);
-}
+static void
+master_task (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc);
+/**
+ * Function called when the 'DISCONNECT' message has been sent by the
+ * plugin. Frees the neighbour --- if the entry still exists.
+ *
+ * @param cls NULL
+ * @param target identity of the neighbour that was disconnected
+ * @param result GNUNET_OK if the disconnect got out successfully
+ */
static void
send_disconnect_cont (void *cls, const struct GNUNET_PeerIdentity *target,
int result)
{
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending DISCONNECT message to peer `%4s': %i\n",
- GNUNET_i2s (target), result);
-#endif
+ struct NeighbourMapEntry *n;
+
+ n = lookup_neighbour (target);
+ if (NULL == n)
+ return; /* already gone */
+ if (S_DISCONNECT != n->state)
+ return; /* have created a fresh entry since */
+ n->state = S_DISCONNECT;
+ if (GNUNET_SCHEDULER_NO_TASK != n->task)
+ GNUNET_SCHEDULER_cancel (n->task);
+ n->task = GNUNET_SCHEDULER_add_now (&master_task, n);
}
-static int
-send_disconnect (struct NeighbourMapEntry * n)
+/**
+ * Transmit a DISCONNECT message to the other peer.
+ *
+ * @param n neighbour to send DISCONNECT message.
+ */
+static void
+send_disconnect (struct NeighbourMapEntry *n)
{
- size_t ret;
struct SessionDisconnectMessage disconnect_msg;
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Sending DISCONNECT message to peer `%4s'\n",
GNUNET_i2s (&n->id));
-#endif
-
disconnect_msg.header.size = htons (sizeof (struct SessionDisconnectMessage));
disconnect_msg.header.type =
htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_DISCONNECT);
@@ -870,19 +1023,14 @@ send_disconnect (struct NeighbourMapEntry * n)
&disconnect_msg.purpose,
&disconnect_msg.signature));
- ret = send_with_session (n,
- (const char *) &disconnect_msg, sizeof (disconnect_msg),
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
- &send_disconnect_cont, NULL);
-
- if (ret == GNUNET_SYSERR)
- return GNUNET_SYSERR;
-
+ send_with_session (n,
+ (const char *) &disconnect_msg, sizeof (disconnect_msg),
+ UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
+ &send_disconnect_cont, NULL);
GNUNET_STATISTICS_update (GST_stats,
gettext_noop
- ("# peers disconnected due to external request"), 1,
+ ("# DISCONNECT messages sent"), 1,
GNUNET_NO);
- return GNUNET_OK;
}
@@ -894,780 +1042,541 @@ send_disconnect (struct NeighbourMapEntry * n)
static void
disconnect_neighbour (struct NeighbourMapEntry *n)
{
- struct MessageQueue *mq;
- int previous_state;
-
- previous_state = n->state;
-
- if (is_disconnecting (n))
- return;
-
- /* send DISCONNECT MESSAGE */
- if (previous_state == S_CONNECTED)
- {
- if (GNUNET_OK == send_disconnect (n))
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent DISCONNECT_MSG to `%s'\n",
- GNUNET_i2s (&n->id));
- else
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Could not send DISCONNECT_MSG to `%s'\n",
- GNUNET_i2s (&n->id));
- }
-
- change_state (n, S_DISCONNECT);
-
- if (previous_state == S_CONNECTED)
- {
- GNUNET_assert (NULL != n->address);
- if (n->address_state == USED)
- {
- GST_validation_set_address_use (n->address, n->session, GNUNET_NO);
- GNUNET_ATS_address_in_use (GST_ats, n->address, n->session, GNUNET_NO);
- n->address_state = UNUSED;
- }
- }
-
- if (n->address != NULL)
- {
- struct GNUNET_TRANSPORT_PluginFunctions *papi;
-
- papi = GST_plugins_find (n->address->transport_name);
- if (papi != NULL)
- papi->disconnect (papi->cls, &n->id);
- }
- while (NULL != (mq = n->messages_head))
- {
- GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq);
- if (NULL != mq->cont)
- mq->cont (mq->cont_cls, GNUNET_SYSERR);
- GNUNET_free (mq);
- }
- if (NULL != n->is_active)
- {
- n->is_active->n = NULL;
- n->is_active = NULL;
- }
-
- switch (previous_state)
+ /* depending on state, notify neighbour and/or upper layers of this peer
+ about disconnect */
+ switch (n->state)
{
+ case S_NOT_CONNECTED:
+ case S_INIT_ATS:
+ case S_INIT_BLACKLIST:
+ /* other peer is completely unaware of us, no need to send DISCONNECT */
+ n->state = S_DISCONNECT_FINISHED;
+ free_neighbour (n, GNUNET_NO);
+ return;
+ case S_CONNECT_SENT:
+ send_disconnect (n);
+ n->state = S_DISCONNECT;
+ break;
+ case S_CONNECT_RECV_ATS:
+ case S_CONNECT_RECV_BLACKLIST:
+ /* we never ACK'ed the other peer's request, no need to send DISCONNECT */
+ n->state = S_DISCONNECT_FINISHED;
+ free_neighbour (n, GNUNET_NO);
+ return;
+ case S_CONNECT_RECV_ACK:
+ /* we DID ACK the other peer's request, must send DISCONNECT */
+ send_disconnect (n);
+ n->state = S_DISCONNECT;
+ break;
case S_CONNECTED:
- GNUNET_assert (neighbours_connected > 0);
- neighbours_connected--;
- GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != n->keepalive_task);
- GNUNET_SCHEDULER_cancel (n->keepalive_task);
- n->keepalive_task = GNUNET_SCHEDULER_NO_TASK;
- n->expect_latency_response = GNUNET_NO;
- GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# peers connected"), -1,
- GNUNET_NO);
+ case S_RECONNECT_BLACKLIST:
+ case S_RECONNECT_SENT:
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ /* we are currently connected, need to send disconnect and do
+ internal notifications and update statistics */
+ send_disconnect (n);
+ GNUNET_STATISTICS_set (GST_stats,
+ gettext_noop ("# peers connected"),
+ --neighbours_connected,
+ GNUNET_NO);
disconnect_notify_cb (callback_cls, &n->id);
+ n->state = S_DISCONNECT;
break;
- case S_FAST_RECONNECT:
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop ("# fast reconnects failed"), 1,
- GNUNET_NO);
+ case S_RECONNECT_ATS:
+ /* ATS address request timeout, disconnect without sending disconnect message */
+ GNUNET_STATISTICS_set (GST_stats,
+ gettext_noop ("# peers connected"),
+ --neighbours_connected,
+ GNUNET_NO);
disconnect_notify_cb (callback_cls, &n->id);
+ n->state = S_DISCONNECT;
+ break;
+ case S_DISCONNECT:
+ /* already disconnected, ignore */
+ break;
+ case S_DISCONNECT_FINISHED:
+ /* already cleaned up, how did we get here!? */
+ GNUNET_assert (0);
break;
default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
+ GNUNET_break (0);
break;
}
+ /* schedule timeout to clean up */
+ if (GNUNET_SCHEDULER_NO_TASK != n->task)
+ GNUNET_SCHEDULER_cancel (n->task);
+ n->task = GNUNET_SCHEDULER_add_delayed (DISCONNECT_SENT_TIMEOUT,
+ &master_task, n);
+}
- GNUNET_ATS_suggest_address_cancel (GST_ats, &n->id);
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove (neighbours,
- &n->id.hashPubKey, n));
- if (GNUNET_SCHEDULER_NO_TASK != n->ats_suggest)
- {
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest = GNUNET_SCHEDULER_NO_TASK;
- }
- if (GNUNET_SCHEDULER_NO_TASK != n->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (n->timeout_task);
- n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- }
- if (GNUNET_SCHEDULER_NO_TASK != n->transmission_task)
+/**
+ * We're done with our transmission attempt, continue processing.
+ *
+ * @param cls the 'struct MessageQueue' of the message
+ * @param receiver intended receiver
+ * @param success whether it worked or not
+ */
+static void
+transmit_send_continuation (void *cls,
+ const struct GNUNET_PeerIdentity *receiver,
+ int success)
+{
+ struct MessageQueue *mq = cls;
+ struct NeighbourMapEntry *n;
+
+ if (NULL == (n = lookup_neighbour (receiver)))
{
- GNUNET_SCHEDULER_cancel (n->transmission_task);
- n->transmission_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_free (mq);
+ return; /* disconnect or other error while transmitting, can happen */
}
- if (NULL != n->address)
+ if (n->is_active == mq)
{
- GNUNET_HELLO_address_free (n->address);
- n->address = NULL;
- }
- n->session = NULL;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting peer `%4s', %X\n",
- GNUNET_i2s (&n->id), n);
- GNUNET_free (n);
+ /* this is still "our" neighbour, remove us from its queue
+ and allow it to send the next message now */
+ n->is_active = NULL;
+ if (GNUNET_SCHEDULER_NO_TASK != n->task)
+ GNUNET_SCHEDULER_cancel (n->task);
+ n->task = GNUNET_SCHEDULER_add_now (&master_task, n);
+ }
+ GNUNET_assert (bytes_in_send_queue >= mq->message_buf_size);
+ bytes_in_send_queue -= mq->message_buf_size;
+ GNUNET_STATISTICS_set (GST_stats,
+ gettext_noop
+ ("# bytes in message queue for other peers"),
+ bytes_in_send_queue, GNUNET_NO);
+ if (GNUNET_OK == success)
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# messages transmitted to other peers"),
+ 1, GNUNET_NO);
+ else
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# transmission failures for messages to other peers"),
+ 1, GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending message to `%s' of type %u was a %s\n",
+ GNUNET_i2s (receiver),
+ ntohs (((struct GNUNET_MessageHeader *) mq->message_buf)->type),
+ (success == GNUNET_OK) ? "success" : "FAILURE");
+ if (NULL != mq->cont)
+ mq->cont (mq->cont_cls, success);
+ GNUNET_free (mq);
}
/**
- * Peer has been idle for too long. Disconnect.
+ * Check the message list for the given neighbour and if we can
+ * send a message, do so. This function should only be called
+ * if the connection is at least generally ready for transmission.
+ * While we will only send one message at a time, no bandwidth
+ * quota management is performed here. If a message was given to
+ * the plugin, the continuation will automatically re-schedule
+ * the 'master' task once the next message might be transmitted.
*
- * @param cls the 'struct NeighbourMapEntry' of the neighbour that went idle
- * @param tc scheduler context
+ * @param n target peer for which to transmit
*/
static void
-neighbour_timeout_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+try_transmission_to_peer (struct NeighbourMapEntry *n)
{
- struct NeighbourMapEntry *n = cls;
+ struct MessageQueue *mq;
+ struct GNUNET_TIME_Relative timeout;
- n->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ if (NULL == n->primary_address.address)
+ {
+ /* no address, why are we here? */
+ GNUNET_break (0);
+ return;
+ }
+ if ((0 == n->primary_address.address->address_length) &&
+ (NULL == n->primary_address.session))
+ {
+ /* no address, why are we here? */
+ GNUNET_break (0);
+ return;
+ }
+ if (NULL != n->is_active)
+ {
+ /* transmission already pending */
+ return;
+ }
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# peers disconnected due to timeout"), 1,
- GNUNET_NO);
- disconnect_neighbour (n);
+ /* timeout messages from the queue that are past their due date */
+ while (NULL != (mq = n->messages_head))
+ {
+ timeout = GNUNET_TIME_absolute_get_remaining (mq->timeout);
+ if (timeout.rel_value > 0)
+ break;
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# messages timed out while in transport queue"),
+ 1, GNUNET_NO);
+ GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq);
+ n->is_active = mq;
+ transmit_send_continuation (mq, &n->id, GNUNET_SYSERR); /* timeout */
+ }
+ if (NULL == mq)
+ return; /* no more messages */
+ GNUNET_CONTAINER_DLL_remove (n->messages_head, n->messages_tail, mq);
+ n->is_active = mq;
+ send_with_session (n,
+ mq->message_buf, mq->message_buf_size,
+ 0 /* priority */, timeout,
+ &transmit_send_continuation, mq);
}
/**
- * Send another keepalive message.
+ * Send keepalive message to the neighbour. Must only be called
+ * if we are on 'connected' state. Will internally determine
+ * if a keepalive is truly needed (so can always be called).
*
- * @param cls the 'struct NeighbourMapEntry' of the neighbour that went idle
- * @param tc scheduler context
+ * @param n neighbour that went idle and needs a keepalive
*/
static void
-neighbour_keepalive_task (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+send_keepalive (struct NeighbourMapEntry *n)
{
- struct NeighbourMapEntry *n = cls;
struct GNUNET_MessageHeader m;
- int ret;
GNUNET_assert (S_CONNECTED == n->state);
- n->keepalive_task =
- GNUNET_SCHEDULER_add_delayed (KEEPALIVE_FREQUENCY,
- &neighbour_keepalive_task, n);
-
- GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# keepalives sent"), 1,
- GNUNET_NO);
+ if (GNUNET_TIME_absolute_get_remaining (n->keep_alive_time).rel_value > 0)
+ return; /* no keepalive needed at this time */
m.size = htons (sizeof (struct GNUNET_MessageHeader));
m.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE);
-
- ret = send_with_session (n,
- (const void *) &m, sizeof (m),
- UINT32_MAX /* priority */ ,
- GNUNET_TIME_UNIT_FOREVER_REL,
- NULL, NULL);
-
- n->expect_latency_response = GNUNET_NO;
- n->keep_alive_sent = GNUNET_TIME_absolute_get_zero ();
- if (ret != GNUNET_SYSERR)
- {
- n->expect_latency_response = GNUNET_YES;
- n->keep_alive_sent = GNUNET_TIME_absolute_get ();
- }
-
+ send_with_session (n,
+ (const void *) &m, sizeof (m),
+ UINT32_MAX /* priority */,
+ KEEPALIVE_FREQUENCY,
+ NULL, NULL);
+ GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# keepalives sent"), 1,
+ GNUNET_NO);
+ n->expect_latency_response = GNUNET_YES;
+ n->last_keep_alive_time = GNUNET_TIME_absolute_get ();
+ n->keep_alive_time = GNUNET_TIME_relative_to_absolute (KEEPALIVE_FREQUENCY);
}
/**
- * Disconnect from the given neighbour.
+ * Keep the connection to the given neighbour alive longer,
+ * we received a KEEPALIVE (or equivalent); send a response.
*
- * @param cls unused
- * @param key hash of neighbour's public key (not used)
- * @param value the 'struct NeighbourMapEntry' of the neighbour
+ * @param neighbour neighbour to keep alive (by sending keep alive response)
*/
-static int
-disconnect_all_neighbours (void *cls, const GNUNET_HashCode * key, void *value)
+void
+GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour)
{
- struct NeighbourMapEntry *n = value;
+ struct NeighbourMapEntry *n;
+ struct GNUNET_MessageHeader m;
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s', %s\n",
- GNUNET_i2s (&n->id), "SHUTDOWN_TASK");
-#endif
- if (S_CONNECTED == n->state)
+ if (NULL == (n = lookup_neighbour (neighbour)))
+ {
GNUNET_STATISTICS_update (GST_stats,
gettext_noop
- ("# peers disconnected due to global disconnect"),
+ ("# KEEPALIVE messages discarded (peer unknown)"),
1, GNUNET_NO);
- disconnect_neighbour (n);
- return GNUNET_OK;
-}
-
-
-static void
-ats_suggest_cancel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
- struct NeighbourMapEntry *n = cls;
-
- n->ats_suggest = GNUNET_SCHEDULER_NO_TASK;
-
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "ATS did not suggested address to connect to peer `%s'\n",
- GNUNET_i2s (&n->id));
-
- disconnect_neighbour (n);
-}
-
-/**
- * Cleanup the neighbours subsystem.
- */
-void
-GST_neighbours_stop ()
-{
- // This can happen during shutdown
- if (neighbours == NULL)
+ return;
+ }
+ if (NULL == n->primary_address.session)
{
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# KEEPALIVE messages discarded (no session)"),
+ 1, GNUNET_NO);
return;
}
-
- GNUNET_CONTAINER_multihashmap_iterate (neighbours, &disconnect_all_neighbours,
- NULL);
- GNUNET_CONTAINER_multihashmap_destroy (neighbours);
-// GNUNET_assert (neighbours_connected == 0);
- neighbours = NULL;
- callback_cls = NULL;
- connect_notify_cb = NULL;
- disconnect_notify_cb = NULL;
- address_change_cb = NULL;
+ /* send reply to allow neighbour to measure latency */
+ m.size = htons (sizeof (struct GNUNET_MessageHeader));
+ m.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE);
+ send_with_session(n,
+ (const void *) &m, sizeof (m),
+ UINT32_MAX /* priority */,
+ KEEPALIVE_FREQUENCY,
+ NULL, NULL);
}
-struct ContinutionContext
-{
- struct GNUNET_HELLO_Address *address;
-
- struct Session *session;
-};
-
-static void
-send_outbound_quota (const struct GNUNET_PeerIdentity *target,
- struct GNUNET_BANDWIDTH_Value32NBO quota)
-{
- struct QuotaSetMessage q_msg;
-
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Sending outbound quota of %u Bps for peer `%s' to all clients\n",
- ntohl (quota.value__), GNUNET_i2s (target));
-#endif
- q_msg.header.size = htons (sizeof (struct QuotaSetMessage));
- q_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA);
- q_msg.quota = quota;
- q_msg.peer = (*target);
- GST_clients_broadcast (&q_msg.header, GNUNET_NO);
-}
/**
- * We tried to send a SESSION_CONNECT message to another peer. If this
- * succeeded, we change the state. If it failed, we should tell
- * ATS to not use this address anymore (until it is re-validated).
+ * We received a KEEP_ALIVE_RESPONSE message and use this to calculate
+ * latency to this peer. Pass the updated information (existing ats
+ * plus calculated latency) to ATS.
*
- * @param cls the 'struct GNUNET_HELLO_Address' of the address that was tried
- * @param target peer to send the message to
- * @param success GNUNET_OK on success
+ * @param neighbour neighbour to keep alive
+ * @param ats performance data
+ * @param ats_count number of entries in ats
*/
-static void
-send_connect_continuation (void *cls, const struct GNUNET_PeerIdentity *target,
- int success)
+void
+GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour,
+ const struct GNUNET_ATS_Information *ats,
+ uint32_t ats_count)
{
- struct ContinutionContext *cc = cls;
- struct NeighbourMapEntry *n = lookup_neighbour (&cc->address->peer);
+ struct NeighbourMapEntry *n;
+ uint32_t latency;
+ struct GNUNET_ATS_Information ats_new[ats_count + 1];
- if (GNUNET_YES != success)
- {
- GNUNET_assert (strlen (cc->address->transport_name) > 0);
- GNUNET_ATS_address_destroyed (GST_ats, cc->address, cc->session);
- }
- if ((NULL == neighbours) || (NULL == n) || (n->state == S_DISCONNECT))
+ if (NULL == (n = lookup_neighbour (neighbour)))
{
- GNUNET_HELLO_address_free (cc->address);
- GNUNET_free (cc);
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# KEEPALIVE_RESPONSE messages discarded (not connected)"),
+ 1, GNUNET_NO);
return;
}
-
- if ((GNUNET_YES == success) &&
- ((n->state == S_NOT_CONNECTED) || (n->state == S_CONNECT_SENT)))
+ if ( (S_CONNECTED != n->state) ||
+ (GNUNET_YES != n->expect_latency_response) )
{
- change_state (n, S_CONNECT_SENT);
- GNUNET_HELLO_address_free (cc->address);
- GNUNET_free (cc);
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# KEEPALIVE_RESPONSE messages discarded (not expected)"),
+ 1, GNUNET_NO);
return;
}
-
- if ((GNUNET_NO == success) &&
- ((n->state == S_NOT_CONNECTED) || (n->state == S_CONNECT_SENT)))
- {
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to send CONNECT_MSG to peer `%4s' with address '%s' session %p, asking ATS for new address \n",
- GNUNET_i2s (&n->id), GST_plugins_a2s (n->address), n->session);
-#endif
- change_state (n, S_NOT_CONNECTED);
- if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest =
- GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, &ats_suggest_cancel,
- n);
- GNUNET_ATS_suggest_address (GST_ats, &n->id);
- }
- GNUNET_HELLO_address_free (cc->address);
- GNUNET_free (cc);
+ n->expect_latency_response = GNUNET_NO;
+ n->latency = GNUNET_TIME_absolute_get_duration (n->last_keep_alive_time);
+ n->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Latency for peer `%s' is %llu ms\n",
+ GNUNET_i2s (&n->id), n->latency.rel_value);
+ memcpy (ats_new, ats, sizeof (struct GNUNET_ATS_Information) * ats_count);
+ /* append latency */
+ ats_new[ats_count].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY);
+ if (n->latency.rel_value > UINT32_MAX)
+ latency = UINT32_MAX;
+ else
+ latency = n->latency.rel_value;
+ ats_new[ats_count].value = htonl (latency);
+ GNUNET_ATS_address_update (GST_ats,
+ n->primary_address.address,
+ n->primary_address.session, ats_new,
+ ats_count + 1);
}
/**
- * We tried to switch addresses with an peer already connected. If it failed,
- * we should tell ATS to not use this address anymore (until it is re-validated).
+ * We have received a message from the given sender. How long should
+ * we delay before receiving more? (Also used to keep the peer marked
+ * as live).
*
- * @param cls the 'struct NeighbourMapEntry'
- * @param target peer to send the message to
- * @param success GNUNET_OK on success
+ * @param sender sender of the message
+ * @param size size of the message
+ * @param do_forward set to GNUNET_YES if the message should be forwarded to clients
+ * GNUNET_NO if the neighbour is not connected or violates the quota,
+ * GNUNET_SYSERR if the connection is not fully up yet
+ * @return how long to wait before reading more from this sender
*/
-static void
-send_switch_address_continuation (void *cls,
- const struct GNUNET_PeerIdentity *target,
- int success)
+struct GNUNET_TIME_Relative
+GST_neighbours_calculate_receive_delay (const struct GNUNET_PeerIdentity
+ *sender, ssize_t size, int *do_forward)
{
- struct ContinutionContext *cc = cls;
struct NeighbourMapEntry *n;
-
- if (neighbours == NULL)
+ struct GNUNET_TIME_Relative ret;
+
+ if (NULL == neighbours)
{
- GNUNET_HELLO_address_free (cc->address);
- GNUNET_free (cc);
- return; /* neighbour is going away */
+ *do_forward = GNUNET_NO;
+ return GNUNET_TIME_UNIT_FOREVER_REL; /* This can happen during shutdown */
}
-
- n = lookup_neighbour (&cc->address->peer);
- if ((n == NULL) || (is_disconnecting (n)))
+ if (NULL == (n = lookup_neighbour (sender)))
+ {
+ GST_neighbours_try_connect (sender);
+ if (NULL == (n = lookup_neighbour (sender)))
+ {
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# messages discarded due to lack of neighbour record"),
+ 1, GNUNET_NO);
+ *do_forward = GNUNET_NO;
+ return GNUNET_TIME_UNIT_ZERO;
+ }
+ }
+ if (! test_connected (n))
{
- GNUNET_HELLO_address_free (cc->address);
- GNUNET_free (cc);
- return; /* neighbour is going away */
+ *do_forward = GNUNET_SYSERR;
+ return GNUNET_TIME_UNIT_ZERO;
}
-
- GNUNET_assert ((n->state == S_CONNECTED) || (n->state == S_FAST_RECONNECT));
- if (GNUNET_YES != success)
+ if (GNUNET_YES == GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, size))
{
-#if DEBUG_TRANSPORT
+ n->quota_violation_count++;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to switch connected peer `%s' to address '%s' session %X, asking ATS for new address \n",
- GNUNET_i2s (&n->id), GST_plugins_a2s (cc->address), cc->session);
-#endif
- GNUNET_assert (strlen (cc->address->transport_name) > 0);
- GNUNET_ATS_address_destroyed (GST_ats, cc->address, cc->session);
-
- if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest =
- GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel,
- n);
- GNUNET_ATS_suggest_address (GST_ats, &n->id);
- GNUNET_HELLO_address_free (cc->address);
- GNUNET_free (cc);
- return;
+ "Bandwidth quota (%u b/s) violation detected (total of %u).\n",
+ n->in_tracker.available_bytes_per_s__,
+ n->quota_violation_count);
+ /* Discount 32k per violation */
+ GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, -32 * 1024);
}
- /* Tell ATS that switching addresses was successful */
- switch (n->state)
+ else
{
- case S_CONNECTED:
- if (n->address_state == FRESH)
+ if (n->quota_violation_count > 0)
{
- GST_validation_set_address_use (cc->address, cc->session, GNUNET_YES);
- GNUNET_ATS_address_update (GST_ats, cc->address, cc->session, NULL, 0);
- if (cc->session != n->session)
- GNUNET_break (0);
- GNUNET_ATS_address_in_use (GST_ats, cc->address, cc->session, GNUNET_YES);
- n->address_state = USED;
+ /* try to add 32k back */
+ GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, 32 * 1024);
+ n->quota_violation_count--;
}
- break;
- case S_FAST_RECONNECT:
-#if DEBUG_TRANSPORT
+ }
+ if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
+ {
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# bandwidth quota violations by other peers"),
+ 1, GNUNET_NO);
+ *do_forward = GNUNET_NO;
+ return GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT;
+ }
+ *do_forward = GNUNET_YES;
+ ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 32 * 1024);
+ if (ret.rel_value > 0)
+ {
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Successful fast reconnect to peer `%s'\n",
- GNUNET_i2s (&n->id));
-#endif
- change_state (n, S_CONNECTED);
- neighbours_connected++;
- GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# peers connected"), 1,
- GNUNET_NO);
-
- if (n->address_state == FRESH)
- {
- GST_validation_set_address_use (cc->address, cc->session, GNUNET_YES);
- GNUNET_ATS_address_update (GST_ats, cc->address, cc->session, NULL, 0);
- GNUNET_ATS_address_in_use (GST_ats, cc->address, cc->session, GNUNET_YES);
- n->address_state = USED;
- }
-
- if (n->keepalive_task == GNUNET_SCHEDULER_NO_TASK)
- n->keepalive_task =
- GNUNET_SCHEDULER_add_now (&neighbour_keepalive_task, n);
-
- /* Updating quotas */
- GST_neighbours_set_incoming_quota (&n->id, n->bandwidth_in);
- send_outbound_quota (target, n->bandwidth_out);
-
- default:
- break;
+ "Throttling read (%llu bytes excess at %u b/s), waiting %llu ms before reading more.\n",
+ (unsigned long long) n->in_tracker.
+ consumption_since_last_update__,
+ (unsigned int) n->in_tracker.available_bytes_per_s__,
+ (unsigned long long) ret.rel_value);
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop ("# ms throttling suggested"),
+ (int64_t) ret.rel_value, GNUNET_NO);
}
- GNUNET_HELLO_address_free (cc->address);
- GNUNET_free (cc);
+ return ret;
}
/**
- * We tried to send a SESSION_CONNECT message to another peer. If this
- * succeeded, we change the state. If it failed, we should tell
- * ATS to not use this address anymore (until it is re-validated).
+ * Transmit a message to the given target using the active connection.
*
- * @param cls the 'struct NeighbourMapEntry'
- * @param target peer to send the message to
- * @param success GNUNET_OK on success
+ * @param target destination
+ * @param msg message to send
+ * @param msg_size number of bytes in msg
+ * @param timeout when to fail with timeout
+ * @param cont function to call when done
+ * @param cont_cls closure for 'cont'
*/
-static void
-send_connect_ack_continuation (void *cls,
- const struct GNUNET_PeerIdentity *target,
- int success)
+void
+GST_neighbours_send (const struct GNUNET_PeerIdentity *target, const void *msg,
+ size_t msg_size, struct GNUNET_TIME_Relative timeout,
+ GST_NeighbourSendContinuation cont, void *cont_cls)
{
- struct ContinutionContext *cc = cls;
struct NeighbourMapEntry *n;
+ struct MessageQueue *mq;
- if (neighbours == NULL)
- {
- GNUNET_HELLO_address_free (cc->address);
- GNUNET_free (cc);
- return; /* neighbour is going away */
- }
-
- n = lookup_neighbour (&cc->address->peer);
- if ((n == NULL) || (is_disconnecting (n)))
+ /* All ove these cases should never happen; they are all API violations.
+ But we check anyway, just to be sure. */
+ if (NULL == (n = lookup_neighbour (target)))
{
- GNUNET_HELLO_address_free (cc->address);
- GNUNET_free (cc);
- return; /* neighbour is going away */
+ GNUNET_break (0);
+ if (NULL != cont)
+ cont (cont_cls, GNUNET_SYSERR);
+ return;
}
-
- if (GNUNET_YES == success)
+ if (GNUNET_YES != test_connected (n))
{
- GNUNET_HELLO_address_free (cc->address);
- GNUNET_free (cc);
- return; /* sending successful */
+ GNUNET_break (0);
+ if (NULL != cont)
+ cont (cont_cls, GNUNET_SYSERR);
+ return;
}
-
- /* sending failed, ask for next address */
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to send CONNECT_MSG to peer `%4s' with address '%s' session %X, asking ATS for new address \n",
- GNUNET_i2s (&n->id), GST_plugins_a2s (n->address), n->session);
-#endif
- change_state (n, S_NOT_CONNECTED);
- GNUNET_assert (strlen (cc->address->transport_name) > 0);
- GNUNET_ATS_address_destroyed (GST_ats, cc->address, cc->session);
-
- if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest =
- GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel,
- n);
- GNUNET_ATS_suggest_address (GST_ats, &n->id);
- GNUNET_HELLO_address_free (cc->address);
- GNUNET_free (cc);
+ bytes_in_send_queue += msg_size;
+ GNUNET_STATISTICS_set (GST_stats,
+ gettext_noop
+ ("# bytes in message queue for other peers"),
+ bytes_in_send_queue, GNUNET_NO);
+ mq = GNUNET_malloc (sizeof (struct MessageQueue) + msg_size);
+ mq->cont = cont;
+ mq->cont_cls = cont_cls;
+ memcpy (&mq[1], msg, msg_size);
+ mq->message_buf = (const char *) &mq[1];
+ mq->message_buf_size = msg_size;
+ mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
+ GNUNET_CONTAINER_DLL_insert_tail (n->messages_head, n->messages_tail, mq);
+ if ( (NULL != n->is_active) ||
+ ( (NULL == n->primary_address.session) && (NULL == n->primary_address.address)) )
+ return;
+ if (GNUNET_SCHEDULER_NO_TASK != n->task)
+ GNUNET_SCHEDULER_cancel (n->task);
+ n->task = GNUNET_SCHEDULER_add_now (&master_task, n);
}
/**
- * For an existing neighbour record, set the active connection to
- * use the given address.
+ * Send a SESSION_CONNECT message via the given address.
*
- * @param peer identity of the peer to switch the address for
- * @param address address of the other peer, NULL if other peer
- * connected to us
- * @param session session to use (or NULL)
- * @param ats performance data
- * @param ats_count number of entries in ats
- * @param bandwidth_in inbound quota to be used when connection is up
- * @param bandwidth_out outbound quota to be used when connection is up
- * @return GNUNET_YES if we are currently connected, GNUNET_NO if the
- * connection is not up (yet)
+ * @param na address to use
*/
-int
-GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Address
- *address,
- struct Session *session,
- const struct GNUNET_ATS_Information *ats,
- uint32_t ats_count,
- struct GNUNET_BANDWIDTH_Value32NBO
- bandwidth_in,
- struct GNUNET_BANDWIDTH_Value32NBO
- bandwidth_out)
+static void
+send_session_connect (struct NeighbourAddress *na)
{
- struct NeighbourMapEntry *n;
- struct SessionConnectMessage connect_msg;
- struct ContinutionContext *cc;
- size_t msg_len;
- size_t ret;
-
- if (neighbours == NULL)
- {
- /* This can happen during shutdown */
- return GNUNET_NO;
- }
- n = lookup_neighbour (peer);
- if (NULL == n)
- return GNUNET_NO;
- if (n->state == S_DISCONNECT)
- {
- /* We are disconnecting, nothing to do here */
- return GNUNET_NO;
- }
- GNUNET_assert (address->transport_name != NULL);
- if ((session == NULL) && (0 == address->address_length))
- {
- GNUNET_break_op (0);
- /* FIXME: is this actually possible? When does this happen? */
- if (strlen (address->transport_name) > 0)
- GNUNET_ATS_address_destroyed (GST_ats, address, session);
- GNUNET_ATS_suggest_address (GST_ats, peer);
- return GNUNET_NO;
- }
-
- /* checks successful and neighbour != NULL */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "ATS tells us to switch to address '%s' session %p for peer `%s' in state `%s'\n",
- (address->address_length != 0) ? GST_plugins_a2s (address): "<inbound>",
- session,
- GNUNET_i2s (peer),
- print_state (n->state));
-
- if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest = GNUNET_SCHEDULER_NO_TASK;
- }
- /* do not switch addresses just update quotas */
-/*
- if (n->state == S_FAST_RECONNECT)
- {
- if (0 == GNUNET_HELLO_address_cmp(address, n->address))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "FAST RECONNECT to peer `%s' and address '%s' with identical ADDRESS\n",
- GNUNET_i2s (&n->id), GST_plugins_a2s (n->address));
- }
- }
-*/
- if ((n->state == S_CONNECTED) && (NULL != n->address) &&
- (0 == GNUNET_HELLO_address_cmp (address, n->address)) &&
- (n->session == session))
- {
- n->bandwidth_in = bandwidth_in;
- n->bandwidth_out = bandwidth_out;
- GST_neighbours_set_incoming_quota (&n->id, n->bandwidth_in);
- send_outbound_quota (peer, n->bandwidth_out);
- return GNUNET_NO;
- }
- if (n->state == S_CONNECTED)
- {
- /* mark old address as no longer used */
- GNUNET_assert (NULL != n->address);
- if (n->address_state == USED)
- {
- GST_validation_set_address_use (n->address, n->session, GNUNET_NO);
- GNUNET_ATS_address_in_use (GST_ats, n->address, n->session, GNUNET_NO);
- n->address_state = UNUSED;
- }
- }
-
- /* set new address */
- if (NULL != n->address)
- GNUNET_HELLO_address_free (n->address);
- n->address = GNUNET_HELLO_address_copy (address);
- n->address_state = FRESH;
- n->bandwidth_in = bandwidth_in;
- n->bandwidth_out = bandwidth_out;
- GNUNET_SCHEDULER_cancel (n->timeout_task);
- n->timeout_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
- &neighbour_timeout_task, n);
-
- if (NULL != address_change_cb && n->state == S_CONNECTED)
- address_change_cb (callback_cls, &n->id, n->address);
-
- /* Obtain an session for this address from plugin */
struct GNUNET_TRANSPORT_PluginFunctions *papi;
- papi = GST_plugins_find (address->transport_name);
-
- if (papi == NULL)
- {
- /* we don't have the plugin for this address */
- GNUNET_ATS_address_destroyed (GST_ats, n->address, NULL);
-
- if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest = GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT,
- ats_suggest_cancel,
- n);
- GNUNET_ATS_suggest_address (GST_ats, &n->id);
- GNUNET_HELLO_address_free (n->address);
- n->address = NULL;
- n->session = NULL;
- return GNUNET_NO;
- }
-
- if (session == NULL)
- {
- n->session = papi->get_session (papi->cls, address);
- /* Session could not be initiated */
- if (n->session == NULL)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to obtain new session %p for peer `%s' and address '%s'\n",
- n->session, GNUNET_i2s (&n->id), GST_plugins_a2s (n->address));
-
- GNUNET_ATS_address_destroyed (GST_ats, n->address, NULL);
-
- if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest = GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT,
- ats_suggest_cancel,
- n);
- GNUNET_ATS_suggest_address (GST_ats, &n->id);
- GNUNET_HELLO_address_free (n->address);
- n->address = NULL;
- n->session = NULL;
- return GNUNET_NO;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Obtained new session %p for peer `%s' and address '%s'\n",
- n->session, GNUNET_i2s (&n->id), GST_plugins_a2s (n->address));
- /* Telling ATS about new session */
- GNUNET_ATS_address_update (GST_ats, n->address, n->session, NULL, 0);
- }
- else
+ struct SessionConnectMessage connect_msg;
+
+ if (NULL == (papi = GST_plugins_find (na->address->transport_name)))
{
- n->session = session;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Using existing session %p for peer `%s' and address '%s'\n",
- n->session,
- GNUNET_i2s (&n->id),
- (address->address_length != 0) ? GST_plugins_a2s (address): "<inbound>");
+ GNUNET_break (0);
+ return;
}
-
- switch (n->state)
+ if (NULL == na->session)
+ na->session = papi->get_session (papi->cls, na->address);
+ if (NULL == na->session)
{
- case S_NOT_CONNECTED:
- case S_CONNECT_SENT:
- msg_len = sizeof (struct SessionConnectMessage);
- connect_msg.header.size = htons (msg_len);
- connect_msg.header.type =
- htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT);
- connect_msg.reserved = htonl (0);
- connect_msg.timestamp =
- GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
-
- cc = GNUNET_malloc (sizeof (struct ContinutionContext));
- cc->session = n->session;
- cc->address = GNUNET_HELLO_address_copy (address);
-
- ret = send_with_session (n,
- (const char *) &connect_msg, msg_len,
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
- &send_connect_continuation, cc);
-
- return GNUNET_NO;
- case S_CONNECT_RECV:
- /* We received a CONNECT message and asked ATS for an address */
- msg_len = sizeof (struct SessionConnectMessage);
- connect_msg.header.size = htons (msg_len);
- connect_msg.header.type =
- htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT_ACK);
- connect_msg.reserved = htonl (0);
- connect_msg.timestamp =
- GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
- cc = GNUNET_malloc (sizeof (struct ContinutionContext));
- cc->session = n->session;
- cc->address = GNUNET_HELLO_address_copy (address);
-
- ret = send_with_session(n,
- (const void *) &connect_msg, msg_len,
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
- &send_connect_ack_continuation,
- cc);
- return GNUNET_NO;
- case S_CONNECTED:
- case S_FAST_RECONNECT:
- /* connected peer is switching addresses or tries fast reconnect */
- msg_len = sizeof (struct SessionConnectMessage);
- connect_msg.header.size = htons (msg_len);
- connect_msg.header.type =
- htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT);
- connect_msg.reserved = htonl (0);
- connect_msg.timestamp =
- GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
- cc = GNUNET_malloc (sizeof (struct ContinutionContext));
- cc->session = n->session;
- cc->address = GNUNET_HELLO_address_copy (address);
- ret = send_with_session(n,
- (const void *) &connect_msg, msg_len,
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
- &send_switch_address_continuation, cc);
- if (ret == GNUNET_SYSERR)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to send CONNECT_MESSAGE to `%4s' using address '%s' session %X\n",
- GNUNET_i2s (peer), GST_plugins_a2s (address), session);
- }
- return GNUNET_NO;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Invalid connection state to switch addresses %u \n", n->state);
- GNUNET_break_op (0);
- return GNUNET_NO;
+ GNUNET_break (0);
+ return;
}
+ na->connect_timestamp = GNUNET_TIME_absolute_get ();
+ connect_msg.header.size = htons (sizeof (struct SessionConnectMessage));
+ connect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT);
+ connect_msg.reserved = htonl (0);
+ connect_msg.timestamp = GNUNET_TIME_absolute_hton (na->connect_timestamp);
+ (void) papi->send (papi->cls,
+ na->session,
+ (const char *) &connect_msg, sizeof (struct SessionConnectMessage),
+ UINT_MAX,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ NULL, NULL);
}
/**
- * Obtain current latency information for the given neighbour.
+ * Send a SESSION_CONNECT_ACK message via the given address.
*
- * @param peer
- * @return observed latency of the address, FOREVER if the address was
- * never successfully validated
+ * @param address address to use
+ * @param session session to use
+ * @param timestamp timestamp to use for the ACK message
*/
-struct GNUNET_TIME_Relative
-GST_neighbour_get_latency (const struct GNUNET_PeerIdentity *peer)
-{
- struct NeighbourMapEntry *n;
-
- n = lookup_neighbour (peer);
- if ((NULL == n) || ((n->address == NULL) && (n->session == NULL)))
- return GNUNET_TIME_UNIT_FOREVER_REL;
-
- return n->latency;
-}
-
-/**
- * Obtain current address information for the given neighbour.
- *
- * @param peer
- * @return address currently used
- */
-struct GNUNET_HELLO_Address *
-GST_neighbour_get_current_address (const struct GNUNET_PeerIdentity *peer)
+static void
+send_session_connect_ack_message (const struct GNUNET_HELLO_Address *address,
+ struct Session *session,
+ struct GNUNET_TIME_Absolute timestamp)
{
- struct NeighbourMapEntry *n;
-
- n = lookup_neighbour (peer);
- if ((NULL == n) || ((n->address == NULL) && (n->session == NULL)))
- return NULL;
-
- return n->address;
+ struct GNUNET_TRANSPORT_PluginFunctions *papi;
+ struct SessionConnectMessage connect_msg;
+
+ if (NULL == (papi = GST_plugins_find (address->transport_name)))
+ {
+ GNUNET_break (0);
+ return;
+ }
+ if (NULL == session)
+ session = papi->get_session (papi->cls, address);
+ if (NULL == session)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ connect_msg.header.size = htons (sizeof (struct SessionConnectMessage));
+ connect_msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_CONNECT_ACK);
+ connect_msg.reserved = htonl (0);
+ connect_msg.timestamp = GNUNET_TIME_absolute_hton (timestamp);
+ (void) papi->send (papi->cls,
+ session,
+ (const char *) &connect_msg, sizeof (struct SessionConnectMessage),
+ UINT_MAX,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ NULL, NULL);
}
-
/**
- * Create an entry in the neighbour map for the given peer
+ * Create a fresh entry in the neighbour map for the given peer
*
* @param peer peer to create an entry for
* @return new neighbour map entry
@@ -1677,20 +1586,17 @@ setup_neighbour (const struct GNUNET_PeerIdentity *peer)
{
struct NeighbourMapEntry *n;
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Unknown peer `%s', creating new neighbour\n", GNUNET_i2s (peer));
-#endif
+ "Creating new neighbour entry for `%s'\n",
+ GNUNET_i2s (peer));
n = GNUNET_malloc (sizeof (struct NeighbourMapEntry));
n->id = *peer;
n->state = S_NOT_CONNECTED;
- n->latency = GNUNET_TIME_relative_get_forever ();
+ n->latency = GNUNET_TIME_UNIT_FOREVER_REL;
GNUNET_BANDWIDTH_tracker_init (&n->in_tracker,
GNUNET_CONSTANTS_DEFAULT_BW_IN_OUT,
MAX_BANDWIDTH_CARRY_S);
- n->timeout_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
- &neighbour_timeout_task, n);
+ n->task = GNUNET_SCHEDULER_add_now (&master_task, n);
GNUNET_assert (GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_put (neighbours,
&n->id.hashPubKey, n,
@@ -1700,6 +1606,32 @@ setup_neighbour (const struct GNUNET_PeerIdentity *peer)
/**
+ * Check if the two given addresses are the same.
+ * Actually only checks if the sessions are non-NULL
+ * (which they should be) and then if they are identical;
+ * the actual addresses don't matter if the session
+ * pointers match anyway, and we must have session pointers
+ * at this time.
+ *
+ * @param a1 first address to compare
+ * @param a2 other address to compare
+ * @return GNUNET_NO if the addresses do not match, GNUNET_YES if they do match
+ */
+static int
+address_matches (const struct NeighbourAddress *a1,
+ const struct NeighbourAddress *a2)
+{
+ if ( (NULL == a1->session) ||
+ (NULL == a2->session) )
+ {
+ GNUNET_break (0);
+ return 0;
+ }
+ return (a1->session == a2->session) ? GNUNET_YES : GNUNET_NO;
+}
+
+
+/**
* Try to create a connection to the given target (eventually).
*
* @param target peer to try to connect to
@@ -1709,585 +1641,1234 @@ GST_neighbours_try_connect (const struct GNUNET_PeerIdentity *target)
{
struct NeighbourMapEntry *n;
- // This can happen during shutdown
- if (neighbours == NULL)
- {
- return;
- }
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to connect to peer `%s'\n",
+ if (NULL == neighbours)
+ return; /* during shutdown, do nothing */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Asked to connect to peer `%s'\n",
GNUNET_i2s (target));
-#endif
if (0 ==
memcmp (target, &GST_my_identity, sizeof (struct GNUNET_PeerIdentity)))
{
- /* my own hello */
+ /* refuse to connect to myself */
+ /* FIXME: can this happen? Is this not an API violation? */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Refusing to try to connect to myself.\n");
return;
}
n = lookup_neighbour (target);
-
if (NULL != n)
{
- if ((S_CONNECTED == n->state) || (is_connecting (n)))
- return; /* already connecting or connected */
- if (is_disconnecting (n))
- change_state (n, S_NOT_CONNECTED);
+ switch (n->state)
+ {
+ case S_NOT_CONNECTED:
+ /* this should not be possible */
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ break;
+ case S_INIT_ATS:
+ case S_INIT_BLACKLIST:
+ case S_CONNECT_SENT:
+ case S_CONNECT_RECV_ATS:
+ case S_CONNECT_RECV_BLACKLIST:
+ case S_CONNECT_RECV_ACK:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Ignoring request to try to connect to `%s', already trying!\n",
+ GNUNET_i2s (target));
+ return; /* already trying */
+ case S_CONNECTED:
+ case S_RECONNECT_ATS:
+ case S_RECONNECT_BLACKLIST:
+ case S_RECONNECT_SENT:
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Ignoring request to try to connect, already connected to `%s'!\n",
+ GNUNET_i2s (target));
+ return; /* already connected */
+ case S_DISCONNECT:
+ /* get rid of remains, ready to re-try immediately */
+ free_neighbour (n, GNUNET_NO);
+ break;
+ case S_DISCONNECT_FINISHED:
+ /* should not be possible */
+ GNUNET_assert (0);
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ break;
+ }
}
+ n = setup_neighbour (target);
+ n->state = S_INIT_ATS;
+ n->timeout = GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT);
-
- if (n == NULL)
- n = setup_neighbour (target);
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Asking ATS for suggested address to connect to peer `%s'\n",
- GNUNET_i2s (&n->id));
-#endif
-
- GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ GNUNET_ATS_reset_backoff (GST_ats, target);
+ GNUNET_ATS_suggest_address (GST_ats, target);
}
+
/**
- * Test if we're connected to the given peer.
+ * Function called with the result of a blacklist check.
*
- * @param target peer to test
- * @return GNUNET_YES if we are connected, GNUNET_NO if not
+ * @param cls closure with the 'struct BlackListCheckContext'
+ * @param peer peer this check affects
+ * @param result GNUNET_OK if the address is allowed
*/
-int
-GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target)
+static void
+handle_test_blacklist_cont (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
+ int result)
{
+ struct BlackListCheckContext *bcc = cls;
struct NeighbourMapEntry *n;
- // This can happen during shutdown
- if (neighbours == NULL)
+ bcc->bc = NULL;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to new address of peer `%s' based on blacklist is `%s'\n",
+ GNUNET_i2s (peer),
+ (GNUNET_OK == result) ? "allowed" : "FORBIDDEN");
+ if (GNUNET_OK == result)
{
- return GNUNET_NO;
+ /* valid new address, let ATS know! */
+ GNUNET_ATS_address_update (GST_ats,
+ bcc->na.address,
+ bcc->na.session,
+ bcc->ats, bcc->ats_count);
+ }
+ if (NULL == (n = lookup_neighbour (peer)))
+ goto cleanup; /* nobody left to care about new address */
+ switch (n->state)
+ {
+ case S_NOT_CONNECTED:
+ /* this should not be possible */
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ break;
+ case S_INIT_ATS:
+ /* still waiting on ATS suggestion */
+ break;
+ case S_INIT_BLACKLIST:
+ /* check if the address the blacklist was fine with matches
+ ATS suggestion, if so, we can move on! */
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (bcc->na.address,
+ bcc->na.session,
+ n->connect_ack_timestamp);
+ }
+ if (GNUNET_YES != address_matches (&bcc->na, &n->primary_address))
+ break; /* result for an address we currently don't care about */
+ if (GNUNET_OK == result)
+ {
+ n->timeout = GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT);
+ n->state = S_CONNECT_SENT;
+ send_session_connect (&n->primary_address);
+ }
+ else
+ {
+ // FIXME: should also possibly destroy session with plugin!?
+ GNUNET_ATS_address_destroyed (GST_ats,
+ bcc->na.address,
+ NULL);
+ free_address (&n->primary_address);
+ n->state = S_INIT_ATS;
+ n->timeout = GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT);
+ // FIXME: do we need to ask ATS again for suggestions?
+ GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ }
+ break;
+ case S_CONNECT_SENT:
+ /* waiting on CONNECT_ACK, send ACK if one is pending */
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (n->primary_address.address,
+ n->primary_address.session,
+ n->connect_ack_timestamp);
+ }
+ break;
+ case S_CONNECT_RECV_ATS:
+ /* still waiting on ATS suggestion, don't care about blacklist */
+ break;
+ case S_CONNECT_RECV_BLACKLIST:
+ if (GNUNET_YES != address_matches (&bcc->na, &n->primary_address))
+ break; /* result for an address we currently don't care about */
+ if (GNUNET_OK == result)
+ {
+ n->timeout = GNUNET_TIME_relative_to_absolute (SETUP_CONNECTION_TIMEOUT);
+ n->state = S_CONNECT_RECV_ACK;
+ send_session_connect_ack_message (bcc->na.address,
+ bcc->na.session,
+ n->connect_ack_timestamp);
+ if (1 == n->send_connect_ack)
+ n->send_connect_ack = 2;
+ }
+ else
+ {
+ // FIXME: should also possibly destroy session with plugin!?
+ GNUNET_ATS_address_destroyed (GST_ats,
+ bcc->na.address,
+ NULL);
+ free_address (&n->primary_address);
+ n->state = S_INIT_ATS;
+ n->timeout = GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT);
+ // FIXME: do we need to ask ATS again for suggestions?
+ GNUNET_ATS_reset_backoff (GST_ats, peer);
+ GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ }
+ break;
+ case S_CONNECT_RECV_ACK:
+ /* waiting on SESSION_ACK, send ACK if one is pending */
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (n->primary_address.address,
+ n->primary_address.session,
+ n->connect_ack_timestamp);
+ }
+ break;
+ case S_CONNECTED:
+ /* already connected, don't care about blacklist */
+ break;
+ case S_RECONNECT_ATS:
+ /* still waiting on ATS suggestion, don't care about blacklist */
+ break;
+ case S_RECONNECT_BLACKLIST:
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (bcc->na.address,
+ bcc->na.session,
+ n->connect_ack_timestamp);
+ }
+ if (GNUNET_YES != address_matches (&bcc->na, &n->primary_address))
+ break; /* result for an address we currently don't care about */
+ if (GNUNET_OK == result)
+ {
+ send_session_connect (&n->primary_address);
+ n->timeout = GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT);
+ n->state = S_RECONNECT_SENT;
+ }
+ else
+ {
+ GNUNET_ATS_address_destroyed (GST_ats,
+ bcc->na.address,
+ NULL);
+ n->state = S_RECONNECT_ATS;
+ n->timeout = GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT);
+ // FIXME: do we need to ask ATS again for suggestions?
+ GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ }
+ break;
+ case S_RECONNECT_SENT:
+ /* waiting on CONNECT_ACK, don't care about blacklist */
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (n->primary_address.address,
+ n->primary_address.session,
+ n->connect_ack_timestamp);
+ }
+ break;
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ if (GNUNET_YES != address_matches (&bcc->na, &n->alternative_address))
+ break; /* result for an address we currently don't care about */
+ if (GNUNET_OK == result)
+ {
+ send_session_connect (&n->alternative_address);
+ n->state = S_CONNECTED_SWITCHING_CONNECT_SENT;
+ }
+ else
+ {
+ GNUNET_ATS_address_destroyed (GST_ats,
+ bcc->na.address,
+ NULL);
+ free_address (&n->alternative_address);
+ n->state = S_CONNECTED;
+ }
+ break;
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ /* waiting on CONNECT_ACK, don't care about blacklist */
+ if ( (GNUNET_OK == result) &&
+ (1 == n->send_connect_ack) )
+ {
+ n->send_connect_ack = 2;
+ send_session_connect_ack_message (n->primary_address.address,
+ n->primary_address.session,
+ n->connect_ack_timestamp);
+ }
+ break;
+ case S_DISCONNECT:
+ /* Nothing to do here, ATS will already do what can be done */
+ break;
+ case S_DISCONNECT_FINISHED:
+ /* should not be possible */
+ GNUNET_assert (0);
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ break;
}
+ cleanup:
+ GNUNET_HELLO_address_free (bcc->na.address);
+ GNUNET_CONTAINER_DLL_remove (bc_head,
+ bc_tail,
+ bcc);
+ GNUNET_free (bcc);
+}
- n = lookup_neighbour (target);
- if ((NULL == n) || (S_CONNECTED != n->state))
- return GNUNET_NO; /* not connected */
- return GNUNET_YES;
+/**
+ * We want to know if connecting to a particular peer via
+ * a particular address is allowed. Check it!
+ *
+ * @param peer identity of the peer to switch the address for
+ * @param ts time at which the check was initiated
+ * @param address address of the other peer, NULL if other peer
+ * connected to us
+ * @param session session to use (or NULL)
+ * @param ats performance data
+ * @param ats_count number of entries in ats (excluding 0-termination)
+ */
+static void
+check_blacklist (const struct GNUNET_PeerIdentity *peer,
+ struct GNUNET_TIME_Absolute ts,
+ const struct GNUNET_HELLO_Address *address,
+ struct Session *session,
+ const struct GNUNET_ATS_Information *ats,
+ uint32_t ats_count)
+{
+ struct BlackListCheckContext *bcc;
+ struct GST_BlacklistCheck *bc;
+
+ bcc =
+ GNUNET_malloc (sizeof (struct BlackListCheckContext) +
+ sizeof (struct GNUNET_ATS_Information) * ats_count);
+ bcc->ats_count = ats_count;
+ bcc->na.address = GNUNET_HELLO_address_copy (address);
+ bcc->na.session = session;
+ bcc->na.connect_timestamp = ts;
+ bcc->ats = (struct GNUNET_ATS_Information *) &bcc[1];
+ memcpy (bcc->ats, ats, sizeof (struct GNUNET_ATS_Information) * ats_count);
+ GNUNET_CONTAINER_DLL_insert (bc_head,
+ bc_tail,
+ bcc);
+ if (NULL != (bc = GST_blacklist_test_allowed (peer,
+ address->transport_name,
+ &handle_test_blacklist_cont, bcc)))
+ bcc->bc = bc;
+ /* if NULL == bc, 'cont' was already called and 'bcc' already free'd, so
+ we must only store 'bc' if 'bc' is non-NULL... */
}
+
/**
- * A session was terminated. Take note.
+ * We received a 'SESSION_CONNECT' message from the other peer.
+ * Consider switching to it.
*
- * @param peer identity of the peer where the session died
- * @param session session that is gone
+ * @param message possibly a 'struct SessionConnectMessage' (check format)
+ * @param peer identity of the peer to switch the address for
+ * @param address address of the other peer, NULL if other peer
+ * connected to us
+ * @param session session to use (or NULL)
+ * @param ats performance data
+ * @param ats_count number of entries in ats (excluding 0-termination)
*/
void
-GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer,
- struct Session *session)
+GST_neighbours_handle_connect (const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct Session *session,
+ const struct GNUNET_ATS_Information *ats,
+ uint32_t ats_count)
{
+ const struct SessionConnectMessage *scm;
struct NeighbourMapEntry *n;
+ struct GNUNET_TIME_Absolute ts;
- if (neighbours == NULL)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received CONNECT message from peer `%s'\n",
+ GNUNET_i2s (peer));
+ if (ntohs (message->size) != sizeof (struct SessionConnectMessage))
{
- /* This can happen during shutdown */
+ GNUNET_break_op (0);
return;
}
-
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Session %X to peer `%s' ended \n",
- session, GNUNET_i2s (peer));
-#endif
-
+ if (NULL == neighbours)
+ return; /* we're shutting down */
+ scm = (const struct SessionConnectMessage *) message;
+ GNUNET_break_op (0 == ntohl (scm->reserved));
+ ts = GNUNET_TIME_absolute_ntoh (scm->timestamp);
n = lookup_neighbour (peer);
if (NULL == n)
- return;
- if (session != n->session)
- return; /* doesn't affect us */
- if (n->state == S_CONNECTED)
- {
- if (n->address_state == USED)
- {
- GST_validation_set_address_use (n->address, n->session, GNUNET_NO);
- GNUNET_ATS_address_in_use (GST_ats, n->address, n->session, GNUNET_NO);
- n->address_state = UNUSED;
- }
- }
-
- if (NULL != n->address)
- {
- GNUNET_HELLO_address_free (n->address);
- n->address = NULL;
- }
- n->session = NULL;
-
- /* not connected anymore anyway, shouldn't matter */
- if (S_CONNECTED != n->state)
- return;
-
- if (n->keepalive_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (n->keepalive_task);
- n->keepalive_task = GNUNET_SCHEDULER_NO_TASK;
- n->expect_latency_response = GNUNET_NO;
+ n = setup_neighbour (peer);
+ n->send_connect_ack = 1;
+ n->connect_ack_timestamp = ts;
+ switch (n->state)
+ {
+ case S_NOT_CONNECTED:
+ n->state = S_CONNECT_RECV_ATS;
+ n->timeout = GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT);
+ GNUNET_ATS_reset_backoff (GST_ats, peer);
+ GNUNET_ATS_suggest_address (GST_ats, peer);
+ check_blacklist (peer, ts, address, session, ats, ats_count);
+ break;
+ case S_INIT_ATS:
+ case S_INIT_BLACKLIST:
+ case S_CONNECT_SENT:
+ case S_CONNECT_RECV_ATS:
+ case S_CONNECT_RECV_BLACKLIST:
+ case S_CONNECT_RECV_ACK:
+ /* It can never hurt to have an alternative address in the above cases,
+ see if it is allowed */
+ check_blacklist (peer, ts, address, session, ats, ats_count);
+ break;
+ case S_CONNECTED:
+ /* we are already connected and can thus send the ACK immediately;
+ still, it can never hurt to have an alternative address, so also
+ tell ATS about it */
+ GNUNET_assert (NULL != n->primary_address.address);
+ GNUNET_assert (NULL != n->primary_address.session);
+ n->send_connect_ack = 0;
+ send_session_connect_ack_message (n->primary_address.address,
+ n->primary_address.session, ts);
+ check_blacklist (peer, ts, address, session, ats, ats_count);
+ break;
+ case S_RECONNECT_ATS:
+ case S_RECONNECT_BLACKLIST:
+ case S_RECONNECT_SENT:
+ /* It can never hurt to have an alternative address in the above cases,
+ see if it is allowed */
+ check_blacklist (peer, ts, address, session, ats, ats_count);
+ break;
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ /* we are already connected and can thus send the ACK immediately;
+ still, it can never hurt to have an alternative address, so also
+ tell ATS about it */
+ GNUNET_assert (NULL != n->primary_address.address);
+ GNUNET_assert (NULL != n->primary_address.session);
+ n->send_connect_ack = 0;
+ send_session_connect_ack_message (n->primary_address.address,
+ n->primary_address.session, ts);
+ check_blacklist (peer, ts, address, session, ats, ats_count);
+ break;
+ case S_DISCONNECT:
+ /* get rid of remains without terminating sessions, ready to re-try */
+ free_neighbour (n, GNUNET_YES);
+ n = setup_neighbour (peer);
+ n->state = S_CONNECT_RECV_ATS;
+ GNUNET_ATS_reset_backoff (GST_ats, peer);
+ GNUNET_ATS_suggest_address (GST_ats, peer);
+ break;
+ case S_DISCONNECT_FINISHED:
+ /* should not be possible */
+ GNUNET_assert (0);
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ break;
}
-
- /* connected, try fast reconnect */
- /* statistics "transport" : "# peers connected" -= 1
- * neighbours_connected -= 1
- * BUT: no disconnect_cb to notify clients about disconnect
- */
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying fast reconnect to peer `%s'\n",
- GNUNET_i2s (peer));
-
- GNUNET_assert (neighbours_connected > 0);
- change_state (n, S_FAST_RECONNECT);
- neighbours_connected--;
- GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# peers connected"), -1,
- GNUNET_NO);
-
-
- /* We are connected, so ask ATS to switch addresses */
- GNUNET_SCHEDULER_cancel (n->timeout_task);
- n->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_DISCONNECT_SESSION_TIMEOUT,
- &neighbour_timeout_task, n);
- /* try QUICKLY to re-establish a connection, reduce timeout! */
- if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest = GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT,
- &ats_suggest_cancel,
- n);
- GNUNET_ATS_suggest_address (GST_ats, peer);
}
/**
- * Transmit a message to the given target using the active connection.
+ * For an existing neighbour record, set the active connection to
+ * use the given address.
*
- * @param target destination
- * @param msg message to send
- * @param msg_size number of bytes in msg
- * @param timeout when to fail with timeout
- * @param cont function to call when done
- * @param cont_cls closure for 'cont'
+ * @param peer identity of the peer to switch the address for
+ * @param address address of the other peer, NULL if other peer
+ * connected to us
+ * @param session session to use (or NULL)
+ * @param ats performance data
+ * @param ats_count number of entries in ats
+ * @param bandwidth_in inbound quota to be used when connection is up
+ * @param bandwidth_out outbound quota to be used when connection is up
*/
void
-GST_neighbours_send (const struct GNUNET_PeerIdentity *target, const void *msg,
- size_t msg_size, struct GNUNET_TIME_Relative timeout,
- GST_NeighbourSendContinuation cont, void *cont_cls)
+GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct Session *session,
+ const struct GNUNET_ATS_Information *ats,
+ uint32_t ats_count,
+ struct GNUNET_BANDWIDTH_Value32NBO
+ bandwidth_in,
+ struct GNUNET_BANDWIDTH_Value32NBO
+ bandwidth_out)
{
struct NeighbourMapEntry *n;
- struct MessageQueue *mq;
+ struct GNUNET_TRANSPORT_PluginFunctions *papi;
+
+ GNUNET_assert (address->transport_name != NULL);
+ if (NULL == (n = lookup_neighbour (peer)))
+ return;
- // This can happen during shutdown
- if (neighbours == NULL)
+ /* Obtain an session for this address from plugin */
+ if (NULL == (papi = GST_plugins_find (address->transport_name)))
{
+ /* we don't have the plugin for this address */
+ GNUNET_ATS_address_destroyed (GST_ats, address, NULL);
return;
}
-
- n = lookup_neighbour (target);
- if ((n == NULL) || (!is_connected (n)))
+ if ((NULL == session) && (0 == address->address_length))
{
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# messages not sent (no such peer or not connected)"),
- 1, GNUNET_NO);
-#if DEBUG_TRANSPORT
- if (n == NULL)
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Could not send message to peer `%s': unknown neighbour",
- GNUNET_i2s (target));
- else if (!is_connected (n))
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Could not send message to peer `%s': not connected\n",
- GNUNET_i2s (target));
-#endif
- if (NULL != cont)
- cont (cont_cls, GNUNET_SYSERR);
+ GNUNET_break (0);
+ if (strlen (address->transport_name) > 0)
+ GNUNET_ATS_address_destroyed (GST_ats, address, session);
return;
}
-
- if ((n->session == NULL) && (n->address == NULL))
+ if (NULL == session)
+ session = papi->get_session (papi->cls, address);
+ if (NULL == session)
{
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# messages not sent (no such peer or not connected)"),
- 1, GNUNET_NO);
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Could not send message to peer `%s': no address available\n",
- GNUNET_i2s (target));
-#endif
-
- if (NULL != cont)
- cont (cont_cls, GNUNET_SYSERR);
+ "Failed to obtain new session for peer `%s' and address '%s'\n",
+ GNUNET_i2s (&address->peer), GST_plugins_a2s (address));
+ GNUNET_ATS_address_destroyed (GST_ats, address, NULL);
return;
}
-
- GNUNET_assert (msg_size >= sizeof (struct GNUNET_MessageHeader));
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# bytes in message queue for other peers"),
- msg_size, GNUNET_NO);
- mq = GNUNET_malloc (sizeof (struct MessageQueue) + msg_size);
- mq->cont = cont;
- mq->cont_cls = cont_cls;
- /* FIXME: this memcpy can be up to 7% of our total runtime! */
- memcpy (&mq[1], msg, msg_size);
- mq->message_buf = (const char *) &mq[1];
- mq->message_buf_size = msg_size;
- mq->timeout = GNUNET_TIME_relative_to_absolute (timeout);
- GNUNET_CONTAINER_DLL_insert_tail (n->messages_head, n->messages_tail, mq);
-
- if ((GNUNET_SCHEDULER_NO_TASK == n->transmission_task) &&
- (NULL == n->is_active))
- n->transmission_task = GNUNET_SCHEDULER_add_now (&transmission_task, n);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "ATS tells us to switch to address '%s' for peer `%s'\n",
+ (address->address_length != 0) ? GST_plugins_a2s (address): "<inbound>",
+ GNUNET_i2s (peer));
+ switch (n->state)
+ {
+ case S_NOT_CONNECTED:
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ return;
+ case S_INIT_ATS:
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_INIT_BLACKLIST;
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_INIT_BLACKLIST:
+ /* ATS suggests a different address, switch again */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECT_SENT:
+ /* ATS suggests a different address, switch again */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_INIT_BLACKLIST;
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECT_RECV_ATS:
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_CONNECT_RECV_BLACKLIST;
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECT_RECV_BLACKLIST:
+ case S_CONNECT_RECV_ACK:
+ /* ATS asks us to switch while we were trying to connect; switch to new
+ address and check blacklist again */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECTED:
+ GNUNET_assert (NULL != n->primary_address.address);
+ GNUNET_assert (NULL != n->primary_address.session);
+ if (n->primary_address.session == session)
+ {
+ /* not an address change, just a quota change */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_YES);
+ break;
+ }
+ /* ATS asks us to switch a life connection; see if we can get
+ a CONNECT_ACK on it before we actually do this! */
+ set_address (&n->alternative_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_CONNECTED_SWITCHING_BLACKLIST;
+ check_blacklist (&n->id,
+ GNUNET_TIME_absolute_get (),
+ address, session, ats, ats_count);
+ break;
+ case S_RECONNECT_ATS:
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_RECONNECT_BLACKLIST;
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_RECONNECT_BLACKLIST:
+ /* ATS asks us to switch while we were trying to reconnect; switch to new
+ address and check blacklist again */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_RECONNECT_SENT:
+ /* ATS asks us to switch while we were trying to reconnect; switch to new
+ address and check blacklist again */
+ set_address (&n->primary_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_RECONNECT_BLACKLIST;
+ n->timeout = GNUNET_TIME_relative_to_absolute (BLACKLIST_RESPONSE_TIMEOUT);
+ check_blacklist (&n->id,
+ n->connect_ack_timestamp,
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ if (n->primary_address.session == session)
+ {
+ /* ATS switches back to still-active session */
+ free_address (&n->alternative_address);
+ n->state = S_CONNECTED;
+ break;
+ }
+ /* ATS asks us to switch a life connection, update blacklist check */
+ set_address (&n->alternative_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ check_blacklist (&n->id,
+ GNUNET_TIME_absolute_get (),
+ address, session, ats, ats_count);
+ break;
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ if (n->primary_address.session == session)
+ {
+ /* ATS switches back to still-active session */
+ free_address (&n->alternative_address);
+ n->state = S_CONNECTED;
+ break;
+ }
+ /* ATS asks us to switch a life connection, update blacklist check */
+ set_address (&n->alternative_address,
+ address, session, bandwidth_in, bandwidth_out, GNUNET_NO);
+ n->state = S_CONNECTED_SWITCHING_BLACKLIST;
+ check_blacklist (&n->id,
+ GNUNET_TIME_absolute_get (),
+ address, session, ats, ats_count);
+ break;
+ case S_DISCONNECT:
+ /* not going to switch addresses while disconnecting */
+ return;
+ case S_DISCONNECT_FINISHED:
+ GNUNET_assert (0);
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
+ GNUNET_break (0);
+ break;
+ }
}
/**
- * We have received a message from the given sender. How long should
- * we delay before receiving more? (Also used to keep the peer marked
- * as live).
+ * Master task run for every neighbour. Performs all of the time-related
+ * activities (keep alive, send next message, disconnect if idle, finish
+ * clean up after disconnect).
*
- * @param sender sender of the message
- * @param size size of the message
- * @param do_forward set to GNUNET_YES if the message should be forwarded to clients
- * GNUNET_NO if the neighbour is not connected or violates the quota,
- * GNUNET_SYSERR if the connection is not fully up yet
- * @return how long to wait before reading more from this sender
+ * @param cls the 'struct NeighbourMapEntry' for which we are running
+ * @param tc scheduler context (unused)
*/
-struct GNUNET_TIME_Relative
-GST_neighbours_calculate_receive_delay (const struct GNUNET_PeerIdentity
- *sender, ssize_t size, int *do_forward)
+static void
+master_task (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct NeighbourMapEntry *n;
- struct GNUNET_TIME_Relative ret;
-
- // This can happen during shutdown
- if (neighbours == NULL)
- {
- return GNUNET_TIME_UNIT_FOREVER_REL;
- }
+ struct NeighbourMapEntry *n = cls;
+ struct GNUNET_TIME_Relative delay;
- n = lookup_neighbour (sender);
- if (n == NULL)
+ n->task = GNUNET_SCHEDULER_NO_TASK;
+ delay = GNUNET_TIME_absolute_get_remaining (n->timeout);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "master task runs for neighbour `%s' in state %d with timeout in %llu ms\n",
+ GNUNET_i2s (&n->id),
+ n->state,
+ (unsigned long long) delay.rel_value);
+ switch (n->state)
{
- GST_neighbours_try_connect (sender);
- n = lookup_neighbour (sender);
- if (NULL == n)
+ case S_NOT_CONNECTED:
+ /* invalid state for master task, clean up */
+ GNUNET_break (0);
+ n->state = S_DISCONNECT_FINISHED;
+ free_neighbour (n, GNUNET_NO);
+ return;
+ case S_INIT_ATS:
+ if (0 == delay.rel_value)
{
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# messages discarded due to lack of neighbour record"),
- 1, GNUNET_NO);
- *do_forward = GNUNET_NO;
- return GNUNET_TIME_UNIT_ZERO;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out waiting for ATS to provide address\n",
+ GNUNET_i2s (&n->id));
+ n->state = S_DISCONNECT_FINISHED;
+ free_neighbour (n, GNUNET_NO);
+ return;
}
- }
- if (!is_connected (n))
- {
- *do_forward = GNUNET_SYSERR;
- return GNUNET_TIME_UNIT_ZERO;
- }
- if (GNUNET_YES == GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, size))
- {
- n->quota_violation_count++;
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Bandwidth quota (%u b/s) violation detected (total of %u).\n",
- n->in_tracker.available_bytes_per_s__,
- n->quota_violation_count);
-#endif
- /* Discount 32k per violation */
- GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, -32 * 1024);
- }
- else
- {
- if (n->quota_violation_count > 0)
+ break;
+ case S_INIT_BLACKLIST:
+ if (0 == delay.rel_value)
{
- /* try to add 32k back */
- GNUNET_BANDWIDTH_tracker_consume (&n->in_tracker, 32 * 1024);
- n->quota_violation_count--;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out waiting for BLACKLIST to approve address\n",
+ GNUNET_i2s (&n->id));
+ n->state = S_DISCONNECT_FINISHED;
+ free_neighbour (n, GNUNET_NO);
+ return;
}
- }
- if (n->quota_violation_count > QUOTA_VIOLATION_DROP_THRESHOLD)
- {
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# bandwidth quota violations by other peers"),
- 1, GNUNET_NO);
- *do_forward = GNUNET_NO;
- return GNUNET_CONSTANTS_QUOTA_VIOLATION_TIMEOUT;
- }
- *do_forward = GNUNET_YES;
- ret = GNUNET_BANDWIDTH_tracker_get_delay (&n->in_tracker, 32 * 1024);
- if (ret.rel_value > 0)
- {
-#if DEBUG_TRANSPORT
+ break;
+ case S_CONNECT_SENT:
+ if (0 == delay.rel_value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out waiting for other peer to send CONNECT_ACK\n",
+ GNUNET_i2s (&n->id));
+ disconnect_neighbour (n);
+ return;
+ }
+ break;
+ case S_CONNECT_RECV_ATS:
+ if (0 == delay.rel_value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out waiting ATS to provide address to use for CONNECT_ACK\n",
+ GNUNET_i2s (&n->id));
+ n->state = S_DISCONNECT_FINISHED;
+ free_neighbour (n, GNUNET_NO);
+ return;
+ }
+ break;
+ case S_CONNECT_RECV_BLACKLIST:
+ if (0 == delay.rel_value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out waiting BLACKLIST to approve address to use for CONNECT_ACK\n",
+ GNUNET_i2s (&n->id));
+ n->state = S_DISCONNECT_FINISHED;
+ free_neighbour (n, GNUNET_NO);
+ return;
+ }
+ break;
+ case S_CONNECT_RECV_ACK:
+ if (0 == delay.rel_value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out waiting for other peer to send SESSION_ACK\n",
+ GNUNET_i2s (&n->id));
+ disconnect_neighbour (n);
+ return;
+ }
+ break;
+ case S_CONNECTED:
+ if (0 == delay.rel_value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out, missing KEEPALIVE_RESPONSEs\n",
+ GNUNET_i2s (&n->id));
+ disconnect_neighbour (n);
+ return;
+ }
+ try_transmission_to_peer (n);
+ send_keepalive (n);
+ break;
+ case S_RECONNECT_ATS:
+ if (0 == delay.rel_value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out, waiting for ATS replacement address\n",
+ GNUNET_i2s (&n->id));
+ disconnect_neighbour (n);
+ return;
+ }
+ break;
+ case S_RECONNECT_BLACKLIST:
+ if (0 == delay.rel_value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out, waiting for BLACKLIST to approve replacement address\n",
+ GNUNET_i2s (&n->id));
+ disconnect_neighbour (n);
+ return;
+ }
+ break;
+ case S_RECONNECT_SENT:
+ if (0 == delay.rel_value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out, waiting for other peer to CONNECT_ACK replacement address\n",
+ GNUNET_i2s (&n->id));
+ disconnect_neighbour (n);
+ return;
+ }
+ break;
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ if (0 == delay.rel_value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out, missing KEEPALIVE_RESPONSEs\n",
+ GNUNET_i2s (&n->id));
+ disconnect_neighbour (n);
+ return;
+ }
+ try_transmission_to_peer (n);
+ send_keepalive (n);
+ break;
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ if (0 == delay.rel_value)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection to `%s' timed out, missing KEEPALIVE_RESPONSEs (after trying to CONNECT on alternative address)\n",
+ GNUNET_i2s (&n->id));
+ disconnect_neighbour (n);
+ return;
+ }
+ try_transmission_to_peer (n);
+ send_keepalive (n);
+ break;
+ case S_DISCONNECT:
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Throttling read (%llu bytes excess at %u b/s), waiting %llu ms before reading more.\n",
- (unsigned long long) n->in_tracker.
- consumption_since_last_update__,
- (unsigned int) n->in_tracker.available_bytes_per_s__,
- (unsigned long long) ret.rel_value);
-#endif
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop ("# ms throttling suggested"),
- (int64_t) ret.rel_value, GNUNET_NO);
- }
- return ret;
+ "Cleaning up connection to `%s' after sending DISCONNECT\n",
+ GNUNET_i2s (&n->id));
+ n->state = S_DISCONNECT_FINISHED;
+ free_neighbour (n, GNUNET_NO);
+ return;
+ case S_DISCONNECT_FINISHED:
+ /* how did we get here!? */
+ GNUNET_assert (0);
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
+ GNUNET_break (0);
+ break;
+ }
+ if ( (S_CONNECTED_SWITCHING_CONNECT_SENT == n->state) ||
+ (S_CONNECTED_SWITCHING_BLACKLIST == n->state) ||
+ (S_CONNECTED == n->state) )
+ {
+ /* if we are *now* in one of these three states, we're sending
+ keep alive messages, so we need to consider the keepalive
+ delay, not just the connection timeout */
+ delay = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (n->keep_alive_time),
+ delay);
+ }
+ if (GNUNET_SCHEDULER_NO_TASK == n->task)
+ n->task = GNUNET_SCHEDULER_add_delayed (delay,
+ &master_task,
+ n);
}
/**
- * Keep the connection to the given neighbour alive longer,
- * we received a KEEPALIVE (or equivalent).
+ * Send a SESSION_ACK message to the neighbour to confirm that we
+ * got his CONNECT_ACK.
*
- * @param neighbour neighbour to keep alive
+ * @param n neighbour to send the SESSION_ACK to
*/
-void
-GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour)
+static void
+send_session_ack_message (struct NeighbourMapEntry *n)
{
- struct NeighbourMapEntry *n;
-
- // This can happen during shutdown
- if (neighbours == NULL)
- {
- return;
- }
-
- n = lookup_neighbour (neighbour);
- if (NULL == n)
- {
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# KEEPALIVE messages discarded (not connected)"),
- 1, GNUNET_NO);
- return;
- }
- GNUNET_SCHEDULER_cancel (n->timeout_task);
- n->timeout_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
- &neighbour_timeout_task, n);
-
- /* send reply to measure latency */
- if (S_CONNECTED != n->state)
- return;
-
- struct GNUNET_MessageHeader m;
-
- m.size = htons (sizeof (struct GNUNET_MessageHeader));
- m.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_KEEPALIVE_RESPONSE);
+ struct GNUNET_MessageHeader msg;
- send_with_session(n,
- (const void *) &m, sizeof (m),
- UINT32_MAX,
- GNUNET_TIME_UNIT_FOREVER_REL,
- NULL, NULL);
+ msg.size = htons (sizeof (struct GNUNET_MessageHeader));
+ msg.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK);
+ (void) send_with_session(n,
+ (const char *) &msg, sizeof (struct GNUNET_MessageHeader),
+ UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
+ NULL, NULL);
}
+
/**
- * We received a KEEP_ALIVE_RESPONSE message and use this to calculate latency
- * to this peer
+ * We received a 'SESSION_CONNECT_ACK' message from the other peer.
+ * Consider switching to it.
*
- * @param neighbour neighbour to keep alive
+ * @param message possibly a 'struct SessionConnectMessage' (check format)
+ * @param peer identity of the peer to switch the address for
+ * @param address address of the other peer, NULL if other peer
+ * connected to us
+ * @param session session to use (or NULL)
* @param ats performance data
* @param ats_count number of entries in ats
*/
void
-GST_neighbours_keepalive_response (const struct GNUNET_PeerIdentity *neighbour,
+GST_neighbours_handle_connect_ack (const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct Session *session,
const struct GNUNET_ATS_Information *ats,
uint32_t ats_count)
{
+ const struct SessionConnectMessage *scm;
+ struct GNUNET_TIME_Absolute ts;
struct NeighbourMapEntry *n;
- struct GNUNET_ATS_Information *ats_new;
- uint32_t latency;
- if (neighbours == NULL)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received CONNECT_ACK message from peer `%s'\n",
+ GNUNET_i2s (peer));
+ if (ntohs (message->size) != sizeof (struct SessionConnectMessage))
{
- // This can happen during shutdown
+ GNUNET_break_op (0);
return;
}
-
- n = lookup_neighbour (neighbour);
- if ((NULL == n) || (n->state != S_CONNECTED))
+ scm = (const struct SessionConnectMessage *) message;
+ GNUNET_break_op (ntohl (scm->reserved) == 0);
+ if (NULL == (n = lookup_neighbour (peer)))
{
GNUNET_STATISTICS_update (GST_stats,
gettext_noop
- ("# KEEPALIVE_RESPONSE messages discarded (not connected)"),
+ ("# unexpected CONNECT_ACK messages (no peer)"),
1, GNUNET_NO);
return;
}
- if (n->expect_latency_response != GNUNET_YES)
+ ts = GNUNET_TIME_absolute_ntoh (scm->timestamp);
+ switch (n->state)
{
+ case S_NOT_CONNECTED:
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ return;
+ case S_INIT_ATS:
+ case S_INIT_BLACKLIST:
GNUNET_STATISTICS_update (GST_stats,
gettext_noop
- ("# KEEPALIVE_RESPONSE messages discarded (not expected)"),
+ ("# unexpected CONNECT_ACK messages (not ready)"),
1, GNUNET_NO);
- return;
+ break;
+ case S_CONNECT_SENT:
+ if (ts.abs_value != n->primary_address.connect_timestamp.abs_value)
+ break; /* ACK does not match our original CONNECT message */
+ n->state = S_CONNECTED;
+ n->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+ GNUNET_STATISTICS_set (GST_stats,
+ gettext_noop ("# peers connected"),
+ ++neighbours_connected,
+ GNUNET_NO);
+ connect_notify_cb (callback_cls, &n->id, ats, ats_count);
+ set_address (&n->primary_address,
+ n->primary_address.address,
+ n->primary_address.session,
+ n->primary_address.bandwidth_in,
+ n->primary_address.bandwidth_out,
+ GNUNET_YES);
+ send_session_ack_message (n);
+ break;
+ case S_CONNECT_RECV_ATS:
+ case S_CONNECT_RECV_BLACKLIST:
+ case S_CONNECT_RECV_ACK:
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# unexpected CONNECT_ACK messages (not ready)"),
+ 1, GNUNET_NO);
+ break;
+ case S_CONNECTED:
+ /* duplicate CONNECT_ACK, let's answer by duplciate SESSION_ACK just in case */
+ send_session_ack_message (n);
+ break;
+ case S_RECONNECT_ATS:
+ case S_RECONNECT_BLACKLIST:
+ /* we didn't expect any CONNECT_ACK, as we are waiting for ATS
+ to give us a new address... */
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# unexpected CONNECT_ACK messages (waiting on ATS)"),
+ 1, GNUNET_NO);
+ break;
+ case S_RECONNECT_SENT:
+ /* new address worked; go back to connected! */
+ n->state = S_CONNECTED;
+ send_session_ack_message (n);
+ break;
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ /* duplicate CONNECT_ACK, let's answer by duplciate SESSION_ACK just in case */
+ send_session_ack_message (n);
+ break;
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ /* new address worked; adopt it and go back to connected! */
+ n->state = S_CONNECTED;
+ n->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+ GNUNET_break (GNUNET_NO == n->alternative_address.ats_active);
+ set_address (&n->primary_address,
+ n->alternative_address.address,
+ n->alternative_address.session,
+ n->alternative_address.bandwidth_in,
+ n->alternative_address.bandwidth_out,
+ GNUNET_YES);
+ free_address (&n->alternative_address);
+ send_session_ack_message (n);
+ break;
+ case S_DISCONNECT:
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# unexpected CONNECT_ACK messages (disconnecting)"),
+ 1, GNUNET_NO);
+ break;
+ case S_DISCONNECT_FINISHED:
+ GNUNET_assert (0);
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
+ GNUNET_break (0);
+ break;
}
- n->expect_latency_response = GNUNET_NO;
+}
- GNUNET_assert (n->keep_alive_sent.abs_value !=
- GNUNET_TIME_absolute_get_zero ().abs_value);
- n->latency =
- GNUNET_TIME_absolute_get_difference (n->keep_alive_sent,
- GNUNET_TIME_absolute_get ());
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Latency for peer `%s' is %llu ms\n",
- GNUNET_i2s (&n->id), n->latency.rel_value);
-#endif
+/**
+ * A session was terminated. Take note; if needed, try to get
+ * an alternative address from ATS.
+ *
+ * @param peer identity of the peer where the session died
+ * @param session session that is gone
+ */
+void
+GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer,
+ struct Session *session)
+{
+ struct NeighbourMapEntry *n;
+ struct BlackListCheckContext *bcc;
+ struct BlackListCheckContext *bcc_next;
- if (n->latency.rel_value == GNUNET_TIME_relative_get_forever ().rel_value)
+ /* make sure to cancel all ongoing blacklist checks involving 'session' */
+ bcc_next = bc_head;
+ while (NULL != (bcc = bcc_next))
{
- GNUNET_ATS_address_update (GST_ats, n->address, n->session, ats, ats_count);
+ bcc_next = bcc->next;
+ if (bcc->na.session == session)
+ {
+ GST_blacklist_test_cancel (bcc->bc);
+ GNUNET_HELLO_address_free (bcc->na.address);
+ GNUNET_CONTAINER_DLL_remove (bc_head,
+ bc_tail,
+ bcc);
+ GNUNET_free (bcc);
+ }
}
- else
+ if (NULL == (n = lookup_neighbour (peer)))
+ return; /* can't affect us */
+ if (session != n->primary_address.session)
{
- ats_new =
- GNUNET_malloc (sizeof (struct GNUNET_ATS_Information) *
- (ats_count + 1));
- memcpy (ats_new, ats, sizeof (struct GNUNET_ATS_Information) * ats_count);
-
- /* add latency */
- ats_new[ats_count].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY);
- if (n->latency.rel_value > UINT32_MAX)
- latency = UINT32_MAX;
- else
- latency = n->latency.rel_value;
- ats_new[ats_count].value = htonl (latency);
+ if (session == n->alternative_address.session)
+ {
+ free_address (&n->alternative_address);
+ if ( (S_CONNECTED_SWITCHING_BLACKLIST == n->state) ||
+ (S_CONNECTED_SWITCHING_CONNECT_SENT == n->state) )
+ n->state = S_CONNECTED;
+ else
+ GNUNET_break (0);
+ }
+ return; /* doesn't affect us further */
+ }
- GNUNET_ATS_address_update (GST_ats, n->address, n->session, ats_new,
- ats_count + 1);
- GNUNET_free (ats_new);
+ n->expect_latency_response = GNUNET_NO;
+
+ switch (n->state)
+ {
+ case S_NOT_CONNECTED:
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ return;
+ case S_INIT_ATS:
+ GNUNET_break (0);
+ free_neighbour (n, GNUNET_NO);
+ return;
+ case S_INIT_BLACKLIST:
+ case S_CONNECT_SENT:
+ free_address (&n->primary_address);
+ n->state = S_INIT_ATS;
+ n->timeout = GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT);
+ // FIXME: need to ask ATS for suggestions again?
+ GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ break;
+ case S_CONNECT_RECV_ATS:
+ case S_CONNECT_RECV_BLACKLIST:
+ case S_CONNECT_RECV_ACK:
+ /* error on inbound session; free neighbour entirely */
+ free_address (&n->primary_address);
+ free_neighbour (n, GNUNET_NO);
+ return;
+ case S_CONNECTED:
+ free_address (&n->primary_address);
+ n->state = S_RECONNECT_ATS;
+ n->timeout = GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT);
+ /* FIXME: is this ATS call needed? */
+ GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ break;
+ case S_RECONNECT_ATS:
+ /* we don't have an address, how can it go down? */
+ GNUNET_break (0);
+ break;
+ case S_RECONNECT_BLACKLIST:
+ case S_RECONNECT_SENT:
+ n->state = S_RECONNECT_ATS;
+ n->timeout = GNUNET_TIME_relative_to_absolute (ATS_RESPONSE_TIMEOUT);
+ // FIXME: need to ask ATS for suggestions again?
+ GNUNET_ATS_suggest_address (GST_ats, &n->id);
+ break;
+ case S_CONNECTED_SWITCHING_BLACKLIST:
+ /* primary went down while we were checking secondary against
+ blacklist, adopt secondary as primary */
+ free_address (&n->primary_address);
+ n->primary_address = n->alternative_address;
+ memset (&n->alternative_address, 0, sizeof (struct NeighbourAddress));
+ n->timeout = GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT);
+ n->state = S_RECONNECT_BLACKLIST;
+ break;
+ case S_CONNECTED_SWITCHING_CONNECT_SENT:
+ /* primary went down while we were waiting for CONNECT_ACK on secondary;
+ secondary as primary */
+ free_address (&n->primary_address);
+ n->primary_address = n->alternative_address;
+ memset (&n->alternative_address, 0, sizeof (struct NeighbourAddress));
+ n->timeout = GNUNET_TIME_relative_to_absolute (FAST_RECONNECT_TIMEOUT);
+ n->state = S_RECONNECT_SENT;
+ break;
+ case S_DISCONNECT:
+ free_address (&n->primary_address);
+ break;
+ case S_DISCONNECT_FINISHED:
+ /* neighbour was freed and plugins told to terminate session */
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
+ GNUNET_break (0);
+ break;
}
+ if (GNUNET_SCHEDULER_NO_TASK != n->task)
+ GNUNET_SCHEDULER_cancel (n->task);
+ n->task = GNUNET_SCHEDULER_add_now (&master_task, n);
}
/**
- * Change the incoming quota for the given peer.
+ * We received a 'SESSION_ACK' message from the other peer.
+ * If we sent a 'CONNECT_ACK' last, this means we are now
+ * connected. Otherwise, do nothing.
*
- * @param neighbour identity of peer to change qutoa for
- * @param quota new quota
+ * @param message possibly a 'struct SessionConnectMessage' (check format)
+ * @param peer identity of the peer to switch the address for
+ * @param address address of the other peer, NULL if other peer
+ * connected to us
+ * @param session session to use (or NULL)
+ * @param ats performance data
+ * @param ats_count number of entries in ats
*/
void
-GST_neighbours_set_incoming_quota (const struct GNUNET_PeerIdentity *neighbour,
- struct GNUNET_BANDWIDTH_Value32NBO quota)
+GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct Session *session,
+ const struct GNUNET_ATS_Information *ats,
+ uint32_t ats_count)
{
struct NeighbourMapEntry *n;
- // This can happen during shutdown
- if (neighbours == NULL)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received SESSION_ACK message from peer `%s'\n",
+ GNUNET_i2s (peer));
+ if (ntohs (message->size) != sizeof (struct GNUNET_MessageHeader))
{
+ GNUNET_break_op (0);
return;
}
-
- n = lookup_neighbour (neighbour);
- if (n == NULL)
+ if (NULL == (n = lookup_neighbour (peer)))
+ return;
+ /* check if we are in a plausible state for having sent
+ a CONNECT_ACK. If not, return, otherwise break */
+ if ( ( (S_CONNECT_RECV_ACK != n->state) &&
+ (S_CONNECT_SENT != n->state) ) ||
+ (2 != n->send_connect_ack) )
{
GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# SET QUOTA messages ignored (no such peer)"),
- 1, GNUNET_NO);
+ gettext_noop ("# unexpected SESSION ACK messages"), 1,
+ GNUNET_NO);
return;
}
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Setting inbound quota of %u Bps for peer `%s' to all clients\n",
- ntohl (quota.value__), GNUNET_i2s (&n->id));
-#endif
- GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker, quota);
- if (0 != ntohl (quota.value__))
- return;
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s' due to `%s'\n",
- GNUNET_i2s (&n->id), "SET_QUOTA");
-#endif
- if (is_connected (n))
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop ("# disconnects due to quota of 0"),
- 1, GNUNET_NO);
- disconnect_neighbour (n);
+ n->state = S_CONNECTED;
+ n->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+ GNUNET_STATISTICS_set (GST_stats,
+ gettext_noop ("# peers connected"),
+ ++neighbours_connected,
+ GNUNET_NO);
+ connect_notify_cb (callback_cls, &n->id, ats, ats_count);
+ set_address (&n->primary_address,
+ n->primary_address.address,
+ n->primary_address.session,
+ n->primary_address.bandwidth_in,
+ n->primary_address.bandwidth_out,
+ GNUNET_YES);
}
/**
- * Closure for the neighbours_iterate function.
- */
-struct IteratorContext
-{
- /**
- * Function to call on each connected neighbour.
- */
- GST_NeighbourIterator cb;
-
- /**
- * Closure for 'cb'.
- */
- void *cb_cls;
-};
-
-
-/**
- * Call the callback from the closure for each connected neighbour.
+ * Test if we're connected to the given peer.
*
- * @param cls the 'struct IteratorContext'
- * @param key the hash of the public key of the neighbour
- * @param value the 'struct NeighbourMapEntry'
- * @return GNUNET_OK (continue to iterate)
+ * @param target peer to test
+ * @return GNUNET_YES if we are connected, GNUNET_NO if not
*/
-static int
-neighbours_iterate (void *cls, const GNUNET_HashCode * key, void *value)
+int
+GST_neighbours_test_connected (const struct GNUNET_PeerIdentity *target)
{
- struct IteratorContext *ic = cls;
- struct NeighbourMapEntry *n = value;
-
- if (!is_connected (n))
- return GNUNET_OK;
-
- ic->cb (ic->cb_cls, &n->id, NULL, 0, n->address);
- return GNUNET_OK;
+ return test_connected (lookup_neighbour (target));
}
/**
- * Iterate over all connected neighbours.
- *
- * @param cb function to call
- * @param cb_cls closure for cb
- */
-void
-GST_neighbours_iterate (GST_NeighbourIterator cb, void *cb_cls)
-{
- struct IteratorContext ic;
-
- // This can happen during shutdown
- if (neighbours == NULL)
- {
- return;
- }
-
- ic.cb = cb;
- ic.cb_cls = cb_cls;
- GNUNET_CONTAINER_multihashmap_iterate (neighbours, &neighbours_iterate, &ic);
-}
-
-/**
- * If we have an active connection to the given target, it must be shutdown.
+ * Change the incoming quota for the given peer.
*
- * @param target peer to disconnect from
+ * @param neighbour identity of peer to change qutoa for
+ * @param quota new quota
*/
void
-GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target)
+GST_neighbours_set_incoming_quota (const struct GNUNET_PeerIdentity *neighbour,
+ struct GNUNET_BANDWIDTH_Value32NBO quota)
{
struct NeighbourMapEntry *n;
- // This can happen during shutdown
- if (neighbours == NULL)
+ if (NULL == (n = lookup_neighbour (neighbour)))
{
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# SET QUOTA messages ignored (no such peer)"),
+ 1, GNUNET_NO);
return;
}
-
- n = lookup_neighbour (target);
- if (NULL == n)
- return; /* not active */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Setting inbound quota of %u Bps for peer `%s' to all clients\n",
+ ntohl (quota.value__), GNUNET_i2s (&n->id));
+ GNUNET_BANDWIDTH_tracker_update_quota (&n->in_tracker, quota);
+ if (0 != ntohl (quota.value__))
+ return;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting peer `%4s' due to `%s'\n",
+ GNUNET_i2s (&n->id), "SET_QUOTA");
+ if (GNUNET_YES == test_connected (n))
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop ("# disconnects due to quota of 0"),
+ 1, GNUNET_NO);
disconnect_neighbour (n);
}
@@ -2309,12 +2890,9 @@ GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity
const struct SessionDisconnectMessage *sdm;
GNUNET_HashCode hc;
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received DISCONNECT message from peer `%s'\n",
GNUNET_i2s (peer));
-#endif
-
if (ntohs (msg->size) != sizeof (struct SessionDisconnectMessage))
{
// GNUNET_break_op (0);
@@ -2325,11 +2903,9 @@ GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity
return;
}
sdm = (const struct SessionDisconnectMessage *) msg;
- n = lookup_neighbour (peer);
- if (NULL == n)
+ if (NULL == (n = lookup_neighbour (peer)))
return; /* gone already */
- if (GNUNET_TIME_absolute_ntoh (sdm->timestamp).abs_value <=
- n->connect_ts.abs_value)
+ if (GNUNET_TIME_absolute_ntoh (sdm->timestamp).abs_value <= n->connect_ack_timestamp.abs_value)
{
GNUNET_STATISTICS_update (GST_stats,
gettext_noop
@@ -2361,360 +2937,210 @@ GST_neighbours_handle_disconnect_message (const struct GNUNET_PeerIdentity
GNUNET_break_op (0);
return;
}
- GST_neighbours_force_disconnect (peer);
+ if (GNUNET_YES == test_connected (n))
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# other peer asked to disconnect from us"), 1,
+ GNUNET_NO);
+ disconnect_neighbour (n);
}
/**
- * We received a 'SESSION_CONNECT_ACK' message from the other peer.
- * Consider switching to it.
- *
- * @param message possibly a 'struct SessionConnectMessage' (check format)
- * @param peer identity of the peer to switch the address for
- * @param address address of the other peer, NULL if other peer
- * connected to us
- * @param session session to use (or NULL)
- * @param ats performance data
- * @param ats_count number of entries in ats
+ * Closure for the neighbours_iterate function.
*/
-void
-GST_neighbours_handle_connect_ack (const struct GNUNET_MessageHeader *message,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Address *address,
- struct Session *session,
- const struct GNUNET_ATS_Information *ats,
- uint32_t ats_count)
+struct IteratorContext
{
- const struct SessionConnectMessage *scm;
- struct GNUNET_MessageHeader msg;
- struct NeighbourMapEntry *n;
- size_t msg_len;
- size_t ret;
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received CONNECT_ACK message from peer `%s'\n",
- GNUNET_i2s (peer));
-
- if (ntohs (message->size) != sizeof (struct SessionConnectMessage))
- {
- GNUNET_break_op (0);
- return;
- }
- scm = (const struct SessionConnectMessage *) message;
- GNUNET_break_op (ntohl (scm->reserved) == 0);
- n = lookup_neighbour (peer);
- if (NULL == n)
- {
- /* we did not send 'CONNECT' -- at least not recently */
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# unexpected CONNECT_ACK messages (no peer)"),
- 1, GNUNET_NO);
- return;
- }
-
- /* Additional check
- *
- * ((n->state != S_CONNECT_RECV) && (n->address != NULL)):
- *
- * We also received an CONNECT message, switched from SENDT to RECV and
- * ATS already suggested us an address after a successful blacklist check
+ /**
+ * Function to call on each connected neighbour.
*/
+ GST_NeighbourIterator cb;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received CONNECT_ACK message from peer `%s' in state `%s'\n",
- GNUNET_i2s (peer),
- print_state(n->state));
-
- if ((n->address != NULL) && (n->state == S_CONNECTED))
- {
- /* After fast reconnect: send ACK (ACK) even when we are connected */
- msg_len = sizeof (msg);
- msg.size = htons (msg_len);
- msg.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK);
-
- ret = send_with_session(n,
- (const char *) &msg, msg_len,
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
- NULL, NULL);
-
- if (ret == GNUNET_SYSERR)
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to send SESSION_ACK to `%4s' using address '%s' session %X\n",
- GNUNET_i2s (&n->id), GST_plugins_a2s (n->address), n->session);
- return;
- }
-
- if ((n->state != S_CONNECT_SENT) &&
- ((n->state != S_CONNECT_RECV) && (n->address != NULL)))
- {
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop
- ("# unexpected CONNECT_ACK messages"), 1,
- GNUNET_NO);
- return;
- }
- if (n->state != S_CONNECTED)
- change_state (n, S_CONNECTED);
-
- if (NULL != session)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "transport-ats",
- "Giving ATS session %p of plugin %s for peer %s\n",
- session, address->transport_name, GNUNET_i2s (peer));
- }
- GNUNET_ATS_address_update (GST_ats, address, session, ats, ats_count);
- GNUNET_assert (NULL != n->address);
+ /**
+ * Closure for 'cb'.
+ */
+ void *cb_cls;
+};
- if ((n->address_state == FRESH) && (0 == GNUNET_HELLO_address_cmp(address, n->address)))
- {
- GST_validation_set_address_use (n->address, n->session, GNUNET_YES);
- GNUNET_ATS_address_in_use (GST_ats, n->address, n->session, GNUNET_YES);
- n->address_state = USED;
- }
- GST_neighbours_set_incoming_quota (&n->id, n->bandwidth_in);
+/**
+ * Call the callback from the closure for each connected neighbour.
+ *
+ * @param cls the 'struct IteratorContext'
+ * @param key the hash of the public key of the neighbour
+ * @param value the 'struct NeighbourMapEntry'
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+neighbours_iterate (void *cls, const GNUNET_HashCode * key, void *value)
+{
+ struct IteratorContext *ic = cls;
+ struct NeighbourMapEntry *n = value;
- /* send ACK (ACK) */
- msg_len = sizeof (msg);
- msg.size = htons (msg_len);
- msg.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_SESSION_ACK);
+ if (GNUNET_YES == test_connected (n))
+ ic->cb (ic->cb_cls, &n->id, NULL, 0, n->primary_address.address);
+ return GNUNET_OK;
+}
- ret = send_with_session(n,
- (const char *) &msg, msg_len,
- UINT32_MAX, GNUNET_TIME_UNIT_FOREVER_REL,
- NULL, NULL);
- if (ret == GNUNET_SYSERR)
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Failed to send SESSION_ACK to `%4s' using address '%s' session %X\n",
- GNUNET_i2s (&n->id), GST_plugins_a2s (n->address), n->session);
+/**
+ * Iterate over all connected neighbours.
+ *
+ * @param cb function to call
+ * @param cb_cls closure for cb
+ */
+void
+GST_neighbours_iterate (GST_NeighbourIterator cb, void *cb_cls)
+{
+ struct IteratorContext ic;
+ if (NULL == neighbours)
+ return; /* can happen during shutdown */
+ ic.cb = cb;
+ ic.cb_cls = cb_cls;
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours, &neighbours_iterate, &ic);
+}
- if (n->keepalive_task == GNUNET_SCHEDULER_NO_TASK)
- n->keepalive_task = GNUNET_SCHEDULER_add_now (&neighbour_keepalive_task, n);
- neighbours_connected++;
- GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# peers connected"), 1,
- GNUNET_NO);
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Notify about connect of `%4s' using address '%s' session %X LINE %u\n",
- GNUNET_i2s (&n->id), GST_plugins_a2s (n->address), n->session,
- __LINE__);
-#endif
- connect_notify_cb (callback_cls, &n->id, ats, ats_count);
- send_outbound_quota (peer, n->bandwidth_out);
+/**
+ * If we have an active connection to the given target, it must be shutdown.
+ *
+ * @param target peer to disconnect from
+ */
+void
+GST_neighbours_force_disconnect (const struct GNUNET_PeerIdentity *target)
+{
+ struct NeighbourMapEntry *n;
+ if (NULL == (n = lookup_neighbour (target)))
+ return; /* not active */
+ if (GNUNET_YES == test_connected (n))
+ GNUNET_STATISTICS_update (GST_stats,
+ gettext_noop
+ ("# disconnected from peer upon explicit request"), 1,
+ GNUNET_NO);
+ disconnect_neighbour (n);
}
-void
-GST_neighbours_handle_ack (const struct GNUNET_MessageHeader *message,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Address *address,
- struct Session *session,
- const struct GNUNET_ATS_Information *ats,
- uint32_t ats_count)
+/**
+ * Obtain current latency information for the given neighbour.
+ *
+ * @param peer to get the latency for
+ * @return observed latency of the address, FOREVER if the
+ * the connection is not up
+ */
+struct GNUNET_TIME_Relative
+GST_neighbour_get_latency (const struct GNUNET_PeerIdentity *peer)
{
struct NeighbourMapEntry *n;
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ACK message from peer `%s'\n",
- GNUNET_i2s (peer));
-#endif
-
- if (ntohs (message->size) != sizeof (struct GNUNET_MessageHeader))
- {
- GNUNET_break_op (0);
- return;
- }
n = lookup_neighbour (peer);
- if (NULL == n)
+ if (NULL == n)
+ return GNUNET_TIME_UNIT_FOREVER_REL;
+ switch (n->state)
{
+ case S_CONNECTED:
+ case S_RECONNECT_SENT:
+ case S_RECONNECT_ATS:
+ return n->latency;
+ case S_NOT_CONNECTED:
+ case S_INIT_BLACKLIST:
+ case S_INIT_ATS:
+ case S_CONNECT_SENT:
+ case S_CONNECT_RECV_BLACKLIST:
+ case S_DISCONNECT:
+ case S_DISCONNECT_FINISHED:
+ return GNUNET_TIME_UNIT_FOREVER_REL;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unhandled state `%s' \n",print_state (n->state));
GNUNET_break (0);
- return;
- }
- if (S_CONNECTED == n->state)
- return;
- if (!is_connecting (n))
- {
- GNUNET_STATISTICS_update (GST_stats,
- gettext_noop ("# unexpected ACK messages"), 1,
- GNUNET_NO);
- return;
- }
- change_state (n, S_CONNECTED);
- if (NULL != session)
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "transport-ats",
- "Giving ATS session %p of plugin %s for peer %s\n",
- session, address->transport_name, GNUNET_i2s (peer));
- GNUNET_ATS_address_update (GST_ats, address, session, ats, ats_count);
- GNUNET_assert (n->address != NULL);
-
- if ((n->address_state == FRESH) && (0 == GNUNET_HELLO_address_cmp(address, n->address)))
- {
- GST_validation_set_address_use (n->address, n->session, GNUNET_YES);
- GNUNET_ATS_address_in_use (GST_ats, n->address, n->session, GNUNET_YES);
- n->address_state = USED;
+ break;
}
-
-
- neighbours_connected++;
- GNUNET_STATISTICS_update (GST_stats, gettext_noop ("# peers connected"), 1,
- GNUNET_NO);
-
- GST_neighbours_set_incoming_quota (&n->id, n->bandwidth_in);
- if (n->keepalive_task == GNUNET_SCHEDULER_NO_TASK)
- n->keepalive_task = GNUNET_SCHEDULER_add_now (&neighbour_keepalive_task, n);
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Notify about connect of `%4s' using address '%s' session %X LINE %u\n",
- GNUNET_i2s (&n->id), GST_plugins_a2s (n->address), n->session,
- __LINE__);
-#endif
- connect_notify_cb (callback_cls, &n->id, ats, ats_count);
- send_outbound_quota (peer, n->bandwidth_out);
+ return GNUNET_TIME_UNIT_FOREVER_REL;
}
-struct BlackListCheckContext
-{
- struct GNUNET_ATS_Information *ats;
-
- uint32_t ats_count;
-
- struct Session *session;
-
- struct GNUNET_HELLO_Address *address;
-
- struct GNUNET_TIME_Absolute ts;
-};
-
-static void
-handle_connect_blacklist_cont (void *cls,
- const struct GNUNET_PeerIdentity *peer,
- int result)
+/**
+ * Obtain current address information for the given neighbour.
+ *
+ * @param peer
+ * @return address currently used
+ */
+struct GNUNET_HELLO_Address *
+GST_neighbour_get_current_address (const struct GNUNET_PeerIdentity *peer)
{
struct NeighbourMapEntry *n;
- struct BlackListCheckContext *bcc = cls;
-
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Blacklist check due to CONNECT message: `%s'\n",
- GNUNET_i2s (peer),
- (result == GNUNET_OK) ? "ALLOWED" : "FORBIDDEN");
-#endif
-
- /* not allowed */
- if (GNUNET_OK != result)
- {
- GNUNET_HELLO_address_free (bcc->address);
- GNUNET_free (bcc);
- return;
- }
n = lookup_neighbour (peer);
if (NULL == n)
- n = setup_neighbour (peer);
-
- if (bcc->ts.abs_value > n->connect_ts.abs_value)
- {
- if (NULL != bcc->session)
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
- "transport-ats",
- "Giving ATS session %p of address `%s' for peer %s\n",
- bcc->session, GST_plugins_a2s (bcc->address),
- GNUNET_i2s (peer));
- /* Tell ATS about the session, so ATS can suggest it if it likes it. */
-
- GNUNET_ATS_address_update (GST_ats, bcc->address, bcc->session, bcc->ats,
- bcc->ats_count);
- n->connect_ts = bcc->ts;
- }
-
- GNUNET_HELLO_address_free (bcc->address);
- GNUNET_free (bcc);
-
- if (n->state != S_CONNECT_RECV)
- change_state (n, S_CONNECT_RECV);
-
-
- /* Ask ATS for an address to connect via that address */
- if (n->ats_suggest != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (n->ats_suggest);
- n->ats_suggest =
- GNUNET_SCHEDULER_add_delayed (ATS_RESPONSE_TIMEOUT, ats_suggest_cancel,
- n);
- GNUNET_ATS_suggest_address (GST_ats, peer);
+ return NULL;
+ return n->primary_address.address;
}
+
/**
- * We received a 'SESSION_CONNECT' message from the other peer.
- * Consider switching to it.
+ * Initialize the neighbours subsystem.
*
- * @param message possibly a 'struct SessionConnectMessage' (check format)
- * @param peer identity of the peer to switch the address for
- * @param address address of the other peer, NULL if other peer
- * connected to us
- * @param session session to use (or NULL)
- * @param ats performance data
- * @param ats_count number of entries in ats (excluding 0-termination)
+ * @param cls closure for callbacks
+ * @param connect_cb function to call if we connect to a peer
+ * @param disconnect_cb function to call if we disconnect from a peer
+ * @param peer_address_cb function to call if we change an active address
+ * of a neighbour
*/
void
-GST_neighbours_handle_connect (const struct GNUNET_MessageHeader *message,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Address *address,
- struct Session *session,
- const struct GNUNET_ATS_Information *ats,
- uint32_t ats_count)
+GST_neighbours_start (void *cls,
+ GNUNET_TRANSPORT_NotifyConnect connect_cb,
+ GNUNET_TRANSPORT_NotifyDisconnect disconnect_cb,
+ GNUNET_TRANSPORT_PeerIterateCallback peer_address_cb)
{
- const struct SessionConnectMessage *scm;
- struct BlackListCheckContext *bcc = NULL;
- struct NeighbourMapEntry *n;
+ callback_cls = cls;
+ connect_notify_cb = connect_cb;
+ disconnect_notify_cb = disconnect_cb;
+ address_change_cb = peer_address_cb;
+ neighbours = GNUNET_CONTAINER_multihashmap_create (NEIGHBOUR_TABLE_SIZE);
+}
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received CONNECT message from peer `%s'\n", GNUNET_i2s (peer));
-#endif
- if (ntohs (message->size) != sizeof (struct SessionConnectMessage))
- {
- GNUNET_break_op (0);
- return;
- }
+/**
+ * Disconnect from the given neighbour.
+ *
+ * @param cls unused
+ * @param key hash of neighbour's public key (not used)
+ * @param value the 'struct NeighbourMapEntry' of the neighbour
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+disconnect_all_neighbours (void *cls, const GNUNET_HashCode * key, void *value)
+{
+ struct NeighbourMapEntry *n = value;
- scm = (const struct SessionConnectMessage *) message;
- GNUNET_break_op (ntohl (scm->reserved) == 0);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Disconnecting peer `%4s', %s\n",
+ GNUNET_i2s (&n->id), "SHUTDOWN_TASK");
+ n->state = S_DISCONNECT_FINISHED;
+ free_neighbour (n, GNUNET_NO);
+ return GNUNET_OK;
+}
- GNUNET_ATS_address_update (GST_ats, address, session, ats, ats_count);
- n = lookup_neighbour (peer);
- if ((n != NULL) && ((S_CONNECTED == n->state) || (S_FAST_RECONNECT == n->state)))
- {
- /* connected peer switches addresses or is trying to do a fast reconnect*/
+/**
+ * Cleanup the neighbours subsystem.
+ */
+void
+GST_neighbours_stop ()
+{
+ if (NULL == neighbours)
return;
- }
-
-
- /* we are not connected to this peer */
- /* do blacklist check */
- bcc =
- GNUNET_malloc (sizeof (struct BlackListCheckContext) +
- sizeof (struct GNUNET_ATS_Information) * (ats_count + 1));
- bcc->ts = GNUNET_TIME_absolute_ntoh (scm->timestamp);
- bcc->ats_count = ats_count + 1;
- bcc->address = GNUNET_HELLO_address_copy (address);
- bcc->session = session;
- bcc->ats = (struct GNUNET_ATS_Information *) &bcc[1];
- memcpy (bcc->ats, ats, sizeof (struct GNUNET_ATS_Information) * ats_count);
- bcc->ats[ats_count].type = htonl (GNUNET_ATS_QUALITY_NET_DELAY);
- bcc->ats[ats_count].value =
- htonl ((uint32_t) GST_neighbour_get_latency (peer).rel_value);
- GST_blacklist_test_allowed (peer, address->transport_name,
- &handle_connect_blacklist_cont, bcc);
+ GNUNET_CONTAINER_multihashmap_iterate (neighbours,
+ &disconnect_all_neighbours,
+ NULL);
+ GNUNET_CONTAINER_multihashmap_destroy (neighbours);
+ neighbours = NULL;
+ callback_cls = NULL;
+ connect_notify_cb = NULL;
+ disconnect_notify_cb = NULL;
+ address_change_cb = NULL;
}
diff --git a/src/transport/gnunet-service-transport_neighbours.h b/src/transport/gnunet-service-transport_neighbours.h
index 33fa1da..23091b7 100644
--- a/src/transport/gnunet-service-transport_neighbours.h
+++ b/src/transport/gnunet-service-transport_neighbours.h
@@ -127,6 +127,7 @@ GST_neighbours_calculate_receive_delay (const struct GNUNET_PeerIdentity
void
GST_neighbours_keepalive (const struct GNUNET_PeerIdentity *neighbour);
+
/**
* We received a KEEP_ALIVE_RESPONSE message and use this to calculate latency
* to this peer
@@ -212,10 +213,8 @@ GST_neighbours_session_terminated (const struct GNUNET_PeerIdentity *peer,
* @param ats_count number of entries in ats
* @param bandwidth_in inbound quota to be used when connection is up
* @param bandwidth_out outbound quota to be used when connection is up
- * @return GNUNET_YES if we are currently connected, GNUNET_NO if the
- * connection is not up (yet)
*/
-int
+void
GST_neighbours_switch_to_address (const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_HELLO_Address
*address, struct Session *session,
@@ -266,13 +265,26 @@ GST_neighbours_handle_connect_ack (const struct GNUNET_MessageHeader *message,
const struct GNUNET_ATS_Information *ats,
uint32_t ats_count);
+
+/**
+ * We received a 'SESSION_ACK' message from the other peer.
+ * FIXME: describe what this means!
+ *
+ * @param message possibly a 'struct SessionConnectMessage' (check format)
+ * @param peer identity of the peer to switch the address for
+ * @param address address of the other peer, NULL if other peer
+ * connected to us
+ * @param session session to use (or NULL)
+ * @param ats performance data
+ * @param ats_count number of entries in ats
+ */
void
-GST_neighbours_handle_ack (const struct GNUNET_MessageHeader *message,
- const struct GNUNET_PeerIdentity *peer,
- const struct GNUNET_HELLO_Address *address,
- struct Session *session,
- const struct GNUNET_ATS_Information *ats,
- uint32_t ats_count);
+GST_neighbours_handle_session_ack (const struct GNUNET_MessageHeader *message,
+ const struct GNUNET_PeerIdentity *peer,
+ const struct GNUNET_HELLO_Address *address,
+ struct Session *session,
+ const struct GNUNET_ATS_Information *ats,
+ uint32_t ats_count);
/**
diff --git a/src/transport/gnunet-service-transport_validation.c b/src/transport/gnunet-service-transport_validation.c
index a6d9424..8421969 100644
--- a/src/transport/gnunet-service-transport_validation.c
+++ b/src/transport/gnunet-service-transport_validation.c
@@ -251,6 +251,10 @@ struct ValidationEntry
* Are we expecting a PONG message for this validation entry?
*/
int expecting_pong;
+
+ /* FIXME: DEBUGGING */
+ int last_line_set_to_no;
+ int last_line_set_to_yes;
};
@@ -600,6 +604,9 @@ find_validation_entry (const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded
if (public_key == NULL)
return NULL;
ve = GNUNET_malloc (sizeof (struct ValidationEntry));
+ ve->in_use = GNUNET_SYSERR; /* not defined */
+ ve->last_line_set_to_no = 0;
+ ve->last_line_set_to_yes = 0;
ve->address = GNUNET_HELLO_address_copy (address);
ve->public_key = *public_key;
ve->pid = address->peer;
@@ -863,10 +870,8 @@ GST_validation_handle_ping (const struct GNUNET_PeerIdentity *sender,
PONG_SIGNATURE_LIFETIME.rel_value / 4)
{
/* create / update cached sig */
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Creating PONG signature to indicate ownership.\n");
-#endif
*sig_cache_exp = GNUNET_TIME_relative_to_absolute (PONG_SIGNATURE_LIFETIME);
pong->expiration = GNUNET_TIME_absolute_hton (*sig_cache_exp);
GNUNET_assert (GNUNET_OK ==
@@ -1076,13 +1081,10 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender,
GNUNET_NO);
return;
}
-#if DEBUG_TRANSPORT
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Address validated for peer `%s' with plugin `%s': `%s'\n",
- GNUNET_i2s (sender), tname, GST_plugins_a2s (tname, addr,
- addrlen));
-#endif
+ GNUNET_i2s (sender), tname, GST_plugins_a2s (ve->address));
/* validity achieved, remember it! */
ve->expecting_pong = GNUNET_NO;
ve->valid_until = GNUNET_TIME_relative_to_absolute (HELLO_ADDRESS_EXPIRATION);
@@ -1097,7 +1099,7 @@ GST_validation_handle_pong (const struct GNUNET_PeerIdentity *sender,
/* build HELLO to store in PEERINFO */
ve->copied = GNUNET_NO;
hello = GNUNET_HELLO_create (&ve->public_key, &add_valid_peer_address, ve);
- GNUNET_PEERINFO_add_peer (GST_peerinfo, hello);
+ GNUNET_PEERINFO_add_peer (GST_peerinfo, hello, NULL, NULL);
GNUNET_free (hello);
}
@@ -1128,7 +1130,7 @@ GST_validation_handle_hello (const struct GNUNET_MessageHeader *hello)
return;
/* Add peer identity without addresses to peerinfo service */
h = GNUNET_HELLO_create (&vac.public_key, NULL, NULL);
- GNUNET_PEERINFO_add_peer (GST_peerinfo, h);
+ GNUNET_PEERINFO_add_peer (GST_peerinfo, h, NULL, NULL);
#if VERBOSE_VALIDATION
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
_("Adding `%s' without addresses for peer `%s'\n"), "HELLO",
@@ -1211,11 +1213,13 @@ GST_validation_get_addresses (const struct GNUNET_PeerIdentity *target,
* @param session the session
* @param in_use GNUNET_YES if we are now using the address for a connection,
* GNUNET_NO if we are no longer using the address for a connection
+ * @param line line of caller just for DEBUGGING!
*/
void
GST_validation_set_address_use (const struct GNUNET_HELLO_Address *address,
struct Session *session,
- int in_use)
+ int in_use,
+ int line)
{
struct ValidationEntry *ve;
@@ -1229,10 +1233,33 @@ GST_validation_set_address_use (const struct GNUNET_HELLO_Address *address,
return;
}
if (ve->in_use == in_use)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "GST_validation_set_address_use: %s %s: ve->in_use %i <-> in_use %i\n",
- GNUNET_i2s (&address->peer), GST_plugins_a2s (address), ve->in_use,
- in_use);
+ {
+
+ if (GNUNET_YES == in_use)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error setting address in use for peer `%s' `%s' to USED: set last time by %i, called now by %i\n",
+ GNUNET_i2s (&address->peer), GST_plugins_a2s (address),
+ ve->last_line_set_to_yes, line);
+ }
+ if (GNUNET_NO == in_use)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error setting address in use for peer `%s' `%s' to NOT_USED: set last time by %i, called now by %i\n",
+ GNUNET_i2s (&address->peer), GST_plugins_a2s (address),
+ ve->last_line_set_to_no, line);
+ }
+ }
+
+ if (GNUNET_YES == in_use)
+ {
+ ve->last_line_set_to_yes = line;
+ }
+ if (GNUNET_NO == in_use)
+ {
+ ve->last_line_set_to_no = line;
+ }
+
GNUNET_break (ve->in_use != in_use); /* should be different... */
ve->in_use = in_use;
if (in_use == GNUNET_YES)
diff --git a/src/transport/gnunet-service-transport_validation.h b/src/transport/gnunet-service-transport_validation.h
index 9b1063b..dd5bcd6 100644
--- a/src/transport/gnunet-service-transport_validation.h
+++ b/src/transport/gnunet-service-transport_validation.h
@@ -52,13 +52,16 @@ GST_validation_stop (void);
* address more or less often.
*
* @param address the address
- * @param session session
+ * @param session the session
* @param in_use GNUNET_YES if we are now using the address for a connection,
* GNUNET_NO if we are no longer using the address for a connection
+ * @param line line of caller just for DEBUGGING!
*/
void
GST_validation_set_address_use (const struct GNUNET_HELLO_Address *address,
- struct Session *session, int in_use);
+ struct Session *session,
+ int in_use,
+ int line);
/**
diff --git a/src/transport/gnunet-transport-certificate-creation b/src/transport/gnunet-transport-certificate-creation
index a38a7b7..b5cffb2 100755
--- a/src/transport/gnunet-transport-certificate-creation
+++ b/src/transport/gnunet-transport-certificate-creation
@@ -32,7 +32,7 @@ DUALCASE=1; export DUALCASE # for MKS sh
# if CDPATH is set.
(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
-relink_command="(cd /home/grothoff/svn/gnunet/src/transport; { 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; }; }; LD_LIBRARY_PATH=/usr/lib/debug:/home/grothoff/lib; export LD_LIBRARY_PATH; PATH=/opt/jdk1.6.0_22/bin:/usr/lib/jvm/java-6-sun//bin:.:/home/grothoff/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games; export PATH; gcc -fno-strict-aliasing -Wall -g -Wall -Werror -O0 -I/home/grothoff//include -o \$progdir/\$file gnunet-transport-certificate-creation.o -L/home/grothoff//lib ../../src/util/.libs/libgnunetutil.so -ldl -Wl,-rpath -Wl,/home/grothoff/svn/gnunet/src/util/.libs -Wl,-rpath -Wl,/home/grothoff/lib)"
+relink_command="(cd /home/grothoff/gnunet-0.9.3/src/transport; { 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; }; }; LD_LIBRARY_PATH=/usr/lib/debug:/home/grothoff/lib; export LD_LIBRARY_PATH; PATH=/opt/jdk1.6.0_22/bin:/usr/lib/jvm/java-6-sun//bin:.:/home/grothoff/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games; export PATH; gcc -fno-strict-aliasing -Wall -g -Wall -Werror -O0 -I/home/grothoff//include -o \$progdir/\$file gnunet-transport-certificate-creation.o -L/home/grothoff//lib ../../src/util/.libs/libgnunetutil.so -ldl -Wl,-rpath -Wl,/home/grothoff/gnunet-0.9.3/src/util/.libs)"
# This environment variable determines our operation mode.
if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then
diff --git a/src/transport/gnunet-transport-certificate-creation.c b/src/transport/gnunet-transport-certificate-creation.c
index 2ec8d36..c4c13dc 100644
--- a/src/transport/gnunet-transport-certificate-creation.c
+++ b/src/transport/gnunet-transport-certificate-creation.c
@@ -62,7 +62,7 @@ main (int argc, char **argv)
if (openssl == NULL)
return 2;
GNUNET_assert (GNUNET_OS_process_wait (openssl) == GNUNET_OK);
- GNUNET_OS_process_close (openssl);
+ GNUNET_OS_process_destroy (openssl);
/* Create a self-signed certificate in batch mode using rsa key */
/* openssl req -batch -days 365 -out $2 -new -x509 -key $1 2> /dev/null */
@@ -73,7 +73,7 @@ main (int argc, char **argv)
if (openssl == NULL)
return 3;
GNUNET_assert (GNUNET_OS_process_wait (openssl) == GNUNET_OK);
- GNUNET_OS_process_close (openssl);
+ GNUNET_OS_process_destroy (openssl);
CHMOD (argv[1], S_IRUSR);
CHMOD (argv[2], S_IRUSR);
return 0;
diff --git a/src/transport/gnunet-transport-wlan-sender.c b/src/transport/gnunet-transport-wlan-sender.c
index 9f06b63..daa8f02 100644
--- a/src/transport/gnunet-transport-wlan-sender.c
+++ b/src/transport/gnunet-transport-wlan-sender.c
@@ -46,35 +46,22 @@
#define IEEE80211_FC0_TYPE_CTL 0x04
#define IEEE80211_FC0_TYPE_DATA 0x08
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/*
- * generic definitions for IEEE 802.11 frames
- */
-struct ieee80211_frame
-{
- u_int8_t i_fc[2];
- u_int8_t i_dur[2];
- u_int8_t i_addr1[IEEE80211_ADDR_LEN];
- u_int8_t i_addr2[IEEE80211_ADDR_LEN];
- u_int8_t i_addr3[IEEE80211_ADDR_LEN];
- u_int8_t i_seq[2];
- u_int8_t llc[4];
-} GNUNET_PACKED;
-GNUNET_NETWORK_STRUCT_END
/**
* function to fill the radiotap header
* @param header pointer to the radiotap header
+ * @param size total message size
* @return GNUNET_YES at success
*/
static int
-getRadiotapHeader (struct Radiotap_Send *header)
+getRadiotapHeader (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header,
+ uint16_t size)
{
+ header->header.size = htons (size);
+ header->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER);
header->rate = 255;
header->tx_power = 0;
header->antenna = 0;
-
return GNUNET_YES;
}
@@ -87,23 +74,21 @@ getRadiotapHeader (struct Radiotap_Send *header)
* @return GNUNET_YES if there was no error
*/
static int
-getWlanHeader (struct ieee80211_frame *Header, const char *to_mac_addr,
- const char *mac, unsigned int size)
+getWlanHeader (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *Header,
+ const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr,
+ const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac, unsigned int size)
{
- uint16_t *tmp16;
const int rate = 11000000;
- Header->i_fc[0] = IEEE80211_FC0_TYPE_DATA;
- Header->i_fc[1] = 0x00;
- memcpy (&Header->i_addr3, &mac_bssid_gnunet, sizeof (mac_bssid_gnunet));
- memcpy (&Header->i_addr2, mac, sizeof (mac_bssid_gnunet));
- memcpy (&Header->i_addr1, to_mac_addr, sizeof (mac_bssid_gnunet));
-
- tmp16 = (uint16_t *) Header->i_dur;
- *tmp16 = (uint16_t) GNUNET_htole16 ((size * 1000000) / rate + 290);
+ Header->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
+ Header->addr3 = mac_bssid_gnunet;
+ Header->addr2 = *mac;
+ Header->addr1 = *to_mac_addr;
+ Header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290);
Header->llc[0] = WLAN_LLC_DSAP_FIELD;
Header->llc[1] = WLAN_LLC_SSAP_FIELD;
-
+ Header->llc[2] = 0; // FIXME
+ Header->llc[3] = 0; // FIXME
return GNUNET_YES;
}
@@ -112,13 +97,10 @@ int
main (int argc, char *argv[])
{
char msg_buf[WLAN_MTU];
- struct GNUNET_MessageHeader *msg;
- struct ieee80211_frame *wlan_header;
- struct Radiotap_Send *radiotap;
-
+ struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radiotap;
unsigned int temp[6];
- char inmac[6];
- char outmac[6];
+ struct GNUNET_TRANSPORT_WLAN_MacAddress inmac;
+ struct GNUNET_TRANSPORT_WLAN_MacAddress outmac;
int pos;
long long count;
double bytes_per_s;
@@ -136,7 +118,7 @@ main (int argc, char *argv[])
return 1;
}
if (6 !=
- sscanf (argv[3], "%x-%x-%x-%x-%x-%x", &temp[0], &temp[1], &temp[2],
+ SSCANF (argv[3], "%x-%x-%x-%x-%x-%x", &temp[0], &temp[1], &temp[2],
&temp[3], &temp[4], &temp[5]))
{
fprintf (stderr,
@@ -144,8 +126,10 @@ main (int argc, char *argv[])
"e.g. mon0 11-22-33-44-55-66 12-34-56-78-90-ab\n");
return 1;
}
+ for (i = 0; i < 6; i++)
+ outmac.mac[i] = temp[i];
if (6 !=
- sscanf (argv[2], "%x-%x-%x-%x-%x-%x", &temp[0], &temp[1], &temp[2],
+ SSCANF (argv[2], "%x-%x-%x-%x-%x-%x", &temp[0], &temp[1], &temp[2],
&temp[3], &temp[4], &temp[5]))
{
fprintf (stderr,
@@ -154,9 +138,7 @@ main (int argc, char *argv[])
return 1;
}
for (i = 0; i < 6; i++)
- inmac[i] = temp[i];
- for (i = 0; i < 6; i++)
- outmac[i] = temp[i];
+ inmac.mac[i] = temp[i];
pid_t pid;
int commpipe[2]; /* This holds the fd for the input & output of the pipe */
@@ -185,22 +167,16 @@ main (int argc, char *argv[])
setvbuf (stdout, (char *) NULL, _IONBF, 0); /* Set non-buffered output on stdout */
- msg = (struct GNUNET_MessageHeader *) msg_buf;
- msg->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
- msg->size = htons (WLAN_MTU);
- radiotap = (struct Radiotap_Send *) &msg[1];
- wlan_header = (struct ieee80211_frame *) &radiotap[1];
+ radiotap = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) msg_buf;
+ getRadiotapHeader (radiotap, WLAN_MTU);
pos = 0;
-
- getRadiotapHeader (radiotap);
- getWlanHeader (wlan_header, outmac, inmac,
- WLAN_MTU - sizeof (struct GNUNET_MessageHeader));
-
+ getWlanHeader (&radiotap->frame, &outmac, &inmac,
+ WLAN_MTU);
start = time (NULL);
count = 0;
while (1)
{
- pos += write (commpipe[1], msg, WLAN_MTU - pos);
+ pos += write (commpipe[1], msg_buf, WLAN_MTU - pos);
if (pos % WLAN_MTU == 0)
{
pos = 0;
diff --git a/src/transport/gnunet-transport.c b/src/transport/gnunet-transport.c
index ee977f5..3b6b7e4 100644
--- a/src/transport/gnunet-transport.c
+++ b/src/transport/gnunet-transport.c
@@ -37,8 +37,10 @@
/**
* How long do we wait for the NAT test to report success?
+ * Should match NAT_SERVER_TIMEOUT in 'nat_test.c'.
*/
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+#define RESOLUTION_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
/**
* Which peer should we connect to?
@@ -121,6 +123,8 @@ static struct GNUNET_PeerIdentity pid;
*/
static GNUNET_SCHEDULER_TaskIdentifier end;
+static struct GNUNET_CONTAINER_MultiHashMap *peers;
+
/**
* Selected level of verbosity.
*/
@@ -193,7 +197,7 @@ display_test_result (struct TestContext *tc, int result)
if ((0 == resolver_users) && (NULL != resolver))
{
GNUNET_break (0 == GNUNET_OS_process_kill (resolver, SIGTERM));
- GNUNET_OS_process_close (resolver);
+ GNUNET_OS_process_destroy (resolver);
resolver = NULL;
}
}
@@ -443,19 +447,32 @@ notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
traffic_received += ntohs (message->size);
}
-void
+struct ResolutionContext
+{
+ struct GNUNET_HELLO_Address *addrcp;
+
+ int printed;
+};
+
+
+static void
process_string (void *cls, const char *address)
{
- struct GNUNET_HELLO_Address *addrcp = cls;
+ struct ResolutionContext *rc = cls;
+ struct GNUNET_HELLO_Address *addrcp = rc->addrcp;
- if ((address != NULL))
+ if (address != NULL)
{
FPRINTF (stdout, _("Peer `%s': %s %s\n"), GNUNET_i2s (&addrcp->peer), addrcp->transport_name, address);
+ rc->printed = GNUNET_YES;
}
else
{
/* done */
- GNUNET_free (addrcp);
+ if (GNUNET_NO == rc->printed)
+ FPRINTF (stdout, _("Peer `%s': %s <unable to resolve address>\n"), GNUNET_i2s (&addrcp->peer), addrcp->transport_name);
+ GNUNET_free (rc->addrcp);
+ GNUNET_free (rc);
}
}
@@ -471,6 +488,7 @@ process_address (void *cls, const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_HELLO_Address *address)
{
const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+ struct ResolutionContext *rc;
if (peer == NULL)
{
@@ -484,10 +502,16 @@ process_address (void *cls, const struct GNUNET_PeerIdentity *peer,
return;
}
+ rc = GNUNET_malloc(sizeof (struct ResolutionContext));
+ rc->addrcp = GNUNET_HELLO_address_copy(address);
+ rc->printed = GNUNET_NO;
+
+ GNUNET_assert (NULL != rc);
+
/* Resolve address to string */
GNUNET_TRANSPORT_address_to_string (cfg, address, numeric,
- GNUNET_TIME_UNIT_MINUTES, &process_string,
- GNUNET_HELLO_address_copy(address));
+ RESOLUTION_TIMEOUT, &process_string,
+ rc);
}
@@ -504,7 +528,13 @@ shutdown_task (void *cls,
{
struct GNUNET_TRANSPORT_PeerIterateContext *pic = cls;
- GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pic);
+ GNUNET_TRANSPORT_peer_get_active_addresses_cancel (pic);
+
+ if (NULL != peers)
+ {
+ GNUNET_CONTAINER_multihashmap_destroy (peers);
+ peers = NULL;
+ }
}
@@ -561,8 +591,9 @@ run (void *cls, char *const *args, const char *cfgfile,
}
if (iterate_connections)
{
+ peers = GNUNET_CONTAINER_multihashmap_create (20);
GNUNET_TRANSPORT_peer_get_active_addresses (cfg, NULL, GNUNET_YES,
- GNUNET_TIME_UNIT_MINUTES,
+ TIMEOUT,
&process_address, (void *) cfg);
}
if (monitor_connections)
diff --git a/src/transport/plugin_transport_http.c b/src/transport/plugin_transport_http.c
index f88ff33..d99f531 100644
--- a/src/transport/plugin_transport_http.c
+++ b/src/transport/plugin_transport_http.c
@@ -106,7 +106,23 @@ struct PrettyPrinterContext
*/
struct Plugin;
+/**
+ * Start session timeout
+ */
+static void
+start_session_timeout (struct Session *s);
+/**
+ * Increment session timeout due to activity
+ */
+static void
+reschedule_session_timeout (struct Session *s);
+
+/**
+ * Cancel timeout
+ */
+static void
+stop_session_timeout (struct Session *s);
/**
* Append our port and forward the result.
@@ -151,6 +167,9 @@ append_port (void *cls, const char *hostname)
}
+
+
+
/**
* Convert the transports address to a nice, human-readable
* format.
@@ -209,6 +228,12 @@ http_plugin_address_pretty_printer (void *cls, const char *type,
sbs = sizeof (struct sockaddr_in);
port = ntohs (a4->u4_port);
}
+ else if (0 == addrlen)
+ {
+ asc (asc_cls, "<inbound connection>");
+ asc (asc_cls, NULL);
+ return;
+ }
else
{
/* invalid address */
@@ -243,13 +268,10 @@ http_plugin_address_pretty_printer (void *cls, const char *type,
static int
http_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
{
-
struct Plugin *plugin = cls;
struct IPv4HttpAddressWrapper *w_tv4 = plugin->ipv4_addr_head;
struct IPv6HttpAddressWrapper *w_tv6 = plugin->ipv6_addr_head;
-
-
GNUNET_assert (cls != NULL);
if ((addrlen != sizeof (struct sockaddr_in)) ||
(addrlen != sizeof (struct sockaddr_in6)))
@@ -311,6 +333,8 @@ http_plugin_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
atsi[1].value = session->ats_address_network_type;
GNUNET_break (session->ats_address_network_type != ntohl (GNUNET_ATS_NET_UNSPECIFIED));
+ reschedule_session_timeout (session);
+
delay =
plugin->env->receive (plugin->env->cls, &s->target, message,
(const struct GNUNET_ATS_Information *) &atsi,
@@ -318,6 +342,104 @@ http_plugin_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
return delay;
}
+
+/**
+ * Function called to convert a string address to
+ * a binary address.
+ *
+ * @param cls closure ('struct Plugin*')
+ * @param addr string address
+ * @param addrlen length of the address
+ * @param buf location to store the buffer
+ * If the function returns GNUNET_SYSERR, its contents are undefined.
+ * @param added length of created address
+ * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ */
+int
+http_string_to_address (void *cls,
+ const char *addr,
+ uint16_t addrlen,
+ void **buf,
+ size_t *added)
+{
+#if !BUILD_HTTPS
+ char *protocol = "http";
+#else
+ char *protocol = "https";
+#endif
+ char *addr_str = NULL;
+ struct sockaddr_in addr_4;
+ struct sockaddr_in6 addr_6;
+ struct IPv4HttpAddress * http_4addr;
+ struct IPv6HttpAddress * http_6addr;
+
+ if ((NULL == addr) || (addrlen == 0))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ if ('\0' != addr[addrlen - 1])
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ if (strlen (addr) != addrlen - 1)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ /* protocoll + "://" + ":" */
+ if (addrlen <= (strlen (protocol) + 4))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid address string `%s' to convert to address\n",
+ addr);
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ if (NULL == (addr_str = strstr(addr, "://")))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid address string `%s' to convert to address\n",
+ addr);
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ addr_str = &addr_str[3];
+
+ if (addr_str[strlen(addr_str)-1] == '/')
+ addr_str[strlen(addr_str)-1] = '\0';
+
+ if (GNUNET_OK == GNUNET_STRINGS_to_address_ipv4(addr_str, strlen(addr_str), &addr_4))
+ {
+ http_4addr = GNUNET_malloc (sizeof (struct IPv4HttpAddress));
+ http_4addr->u4_port = addr_4.sin_port;
+ http_4addr->ipv4_addr = (uint32_t) addr_4.sin_addr.s_addr;
+ (*buf) = http_4addr;
+ (*added) = sizeof (struct IPv4HttpAddress);
+ return GNUNET_OK;
+ }
+ if (GNUNET_OK == GNUNET_STRINGS_to_address_ipv6(addr_str, strlen(addr_str), &addr_6))
+ {
+ http_6addr = GNUNET_malloc (sizeof (struct IPv6HttpAddress));
+ http_6addr->u6_port = addr_6.sin6_port;
+ http_6addr->ipv6_addr = addr_6.sin6_addr;
+ (*buf) = http_6addr;
+ (*added) = sizeof (struct IPv6HttpAddress);
+ return GNUNET_OK;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid address string `%s' to convert to address\n",
+ addr_str);
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+}
+
+
/**
* Function called for a quick conversion of the binary address to
* a numeric address. Note that the caller must not free the
@@ -385,6 +507,7 @@ http_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
return rbuf;
}
+
struct Session *
lookup_session_old (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
struct Session *session, const void *addr, size_t addrlen,
@@ -398,11 +521,11 @@ lookup_session_old (struct Plugin *plugin, const struct GNUNET_PeerIdentity *tar
{
#if 0
GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
- "Comparing peer `%s' address `%s' len %i session %X to \n",
+ "Comparing peer `%s' address `%s' len %i session %p to \n",
GNUNET_i2s (target), GNUNET_a2s (addr, addrlen), addrlen,
session);
GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
- "peer `%s' address `%s' len %i session %X \n\n",
+ "peer `%s' address `%s' len %i session %p \n\n",
GNUNET_i2s (&t->target), GNUNET_a2s (t->addr, t->addrlen),
t->addrlen, t);
GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name, "memcmp %i \n",
@@ -430,6 +553,7 @@ lookup_session_old (struct Plugin *plugin, const struct GNUNET_PeerIdentity *tar
return NULL;
}
+
struct Session *
lookup_session (struct Plugin *plugin,
const struct GNUNET_HELLO_Address *address)
@@ -445,9 +569,28 @@ lookup_session (struct Plugin *plugin,
}
+int
+exist_session (struct Plugin *plugin, struct Session *s)
+{
+ struct Session * head;
+
+ GNUNET_assert (NULL != plugin);
+ GNUNET_assert (NULL != s);
+
+ for (head = plugin->head; head != NULL; head = head->next)
+ {
+ if (head == s)
+ return GNUNET_YES;
+ }
+ return GNUNET_NO;
+}
+
+
void
delete_session (struct Session *s)
{
+ stop_session_timeout(s);
+
if (s->msg_tk != NULL)
{
GNUNET_SERVER_mst_destroy (s->msg_tk);
@@ -459,10 +602,10 @@ delete_session (struct Session *s)
GNUNET_free (s);
}
+
struct Session *
create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
- const void *addr, size_t addrlen,
- GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
+ const void *addr, size_t addrlen)
{
struct Session *s = NULL;
@@ -474,12 +617,12 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
s->addr = GNUNET_malloc (addrlen);
memcpy (s->addr, addr, addrlen);
s->addrlen = addrlen;
- s->next = NULL;
- s->next_receive = GNUNET_TIME_absolute_get_zero ();
s->ats_address_network_type = htonl (GNUNET_ATS_NET_UNSPECIFIED);
+ start_session_timeout(s);
return s;
}
+
void
notify_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
struct Session *s)
@@ -491,6 +634,7 @@ notify_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
delete_session (s);
}
+
/**
* Creates a new outbound session the transport service will use to send data to the
* peer
@@ -499,7 +643,6 @@ notify_session_end (void *cls, const struct GNUNET_PeerIdentity *peer,
* @param address the address
* @return the session or NULL of max connections exceeded
*/
-
static struct Session *
http_get_session (void *cls,
const struct GNUNET_HELLO_Address *address)
@@ -535,16 +678,7 @@ http_get_session (void *cls,
GNUNET_assert ((addrlen == sizeof (struct IPv6HttpAddress)) ||
(addrlen == sizeof (struct IPv4HttpAddress)));
- s = GNUNET_malloc (sizeof (struct Session));
- memcpy (&s->target, &address->peer, sizeof (struct GNUNET_PeerIdentity));
- s->plugin = plugin;
- s->addr = GNUNET_malloc (address->address_length);
- memcpy (s->addr, address->address, address->address_length);
- s->addrlen = addrlen;
- s->next = NULL;
- s->next_receive = GNUNET_TIME_absolute_get_zero ();
- s->inbound = GNUNET_NO;
- s->ats_address_network_type = htonl (GNUNET_ATS_NET_UNSPECIFIED);
+ s = create_session (plugin, &address->peer, address->address, address->address_length);
/* Get ATS type */
if (addrlen == sizeof (struct IPv4HttpAddress))
@@ -592,6 +726,7 @@ http_get_session (void *cls,
return s;
}
+
/**
* Function that can be used by the transport service to transmit
* a message using the plugin. Note that in the case of a
@@ -653,7 +788,6 @@ http_plugin_send (void *cls,
}
/* create new message and schedule */
-
msg = GNUNET_malloc (sizeof (struct HTTP_Message) + msgbuf_size);
msg->next = NULL;
msg->size = msgbuf_size;
@@ -663,25 +797,21 @@ http_plugin_send (void *cls,
msg->transmit_cont_cls = cont_cls;
memcpy (msg->buf, msgbuf, msgbuf_size);
+ reschedule_session_timeout (session);
+
if (session->inbound == GNUNET_NO)
{
-#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Using outbound client session %p to send to `%session'\n", session,
+ "Using outbound client session %p to send to `%s'\n", session,
GNUNET_i2s (&session->target));
-#endif
-
client_send (session, msg);
res = msgbuf_size;
}
if (session->inbound == GNUNET_YES)
{
-#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Using inbound server %p session to send to `%session'\n", session,
+ "Using inbound server %p session to send to `%s'\n", session,
GNUNET_i2s (&session->target));
-#endif
-
server_send (session, msg);
res = msgbuf_size;
}
@@ -741,14 +871,13 @@ http_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
}
}
-static void
-nat_add_address (void *cls, int add_remove, const struct sockaddr *addr,
- socklen_t addrlen)
+
+static void *
+find_address (struct Plugin *plugin, const struct sockaddr *addr, socklen_t addrlen)
{
- struct Plugin *plugin = cls;
+ int af;
struct IPv4HttpAddressWrapper *w_t4 = NULL;
struct IPv6HttpAddressWrapper *w_t6 = NULL;
- int af;
af = addr->sa_family;
switch (af)
@@ -773,25 +902,7 @@ nat_add_address (void *cls, int add_remove, const struct sockaddr *addr,
break;
w_t4 = w_t4->next;
}
- if (w_t4 == NULL)
- {
- w_t4 = GNUNET_malloc (sizeof (struct IPv4HttpAddressWrapper));
- memcpy (&w_t4->addr.ipv4_addr, &a4->sin_addr, sizeof (struct in_addr));
- w_t4->addr.u4_port = a4->sin_port;
-
- GNUNET_CONTAINER_DLL_insert (plugin->ipv4_addr_head,
- plugin->ipv4_addr_tail, w_t4);
- }
-#if DEBUG_HTTP
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Notifying transport to add IPv4 address `%s'\n",
- http_plugin_address_to_string (NULL, &w_t4->addr,
- sizeof (struct
- IPv4HttpAddress)));
-#endif
- plugin->env->notify_address (plugin->env->cls, add_remove, &w_t4->addr,
- sizeof (struct IPv4HttpAddress));
-
+ return w_t4;
break;
case AF_INET6:
w_t6 = plugin->ipv6_addr_head;
@@ -811,25 +922,68 @@ nat_add_address (void *cls, int add_remove, const struct sockaddr *addr,
break;
w_t6 = w_t6->next;
}
+ return w_t6;
+ break;
+ default:
+ return NULL;
+ }
+ return NULL;
+}
+
+
+static void
+nat_add_address (void *cls, int add_remove, const struct sockaddr *addr,
+ socklen_t addrlen)
+{
+ struct Plugin *plugin = cls;
+ struct IPv4HttpAddressWrapper *w_t4 = NULL;
+ struct IPv6HttpAddressWrapper *w_t6 = NULL;
+ int af;
+
+ af = addr->sa_family;
+ switch (af)
+ {
+ case AF_INET:
+ w_t4 = find_address (plugin, addr, addrlen);
+ if (w_t4 == NULL)
+ {
+ struct sockaddr_in *a4 = (struct sockaddr_in *) addr;
+ w_t4 = GNUNET_malloc (sizeof (struct IPv4HttpAddressWrapper));
+ memcpy (&w_t4->addr.ipv4_addr, &a4->sin_addr, sizeof (struct in_addr));
+ w_t4->addr.u4_port = a4->sin_port;
+
+ GNUNET_CONTAINER_DLL_insert (plugin->ipv4_addr_head,
+ plugin->ipv4_addr_tail, w_t4);
+
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+ "Notifying transport to add IPv4 address `%s'\n",
+ http_plugin_address_to_string (NULL, &w_t4->addr,
+ sizeof (struct
+ IPv4HttpAddress)));
+ plugin->env->notify_address (plugin->env->cls, add_remove, &w_t4->addr,
+ sizeof (struct IPv4HttpAddress));
+ }
+ break;
+ case AF_INET6:
+ w_t6 = find_address (plugin, addr, addrlen);
if (w_t6 == NULL)
{
w_t6 = GNUNET_malloc (sizeof (struct IPv6HttpAddressWrapper));
-
+ struct sockaddr_in6 *a6 = (struct sockaddr_in6 *) addr;
memcpy (&w_t6->addr6.ipv6_addr, &a6->sin6_addr, sizeof (struct in6_addr));
w_t6->addr6.u6_port = a6->sin6_port;
GNUNET_CONTAINER_DLL_insert (plugin->ipv6_addr_head,
plugin->ipv6_addr_tail, w_t6);
- }
-#if DEBUG_HTTP
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Notifying transport to add IPv6 address `%s'\n",
http_plugin_address_to_string (NULL, &w_t6->addr6,
sizeof (struct
IPv6HttpAddress)));
-#endif
- plugin->env->notify_address (plugin->env->cls, add_remove, &w_t6->addr6,
+ plugin->env->notify_address (plugin->env->cls, add_remove, &w_t6->addr6,
sizeof (struct IPv6HttpAddress));
+ }
break;
default:
return;
@@ -837,6 +991,7 @@ nat_add_address (void *cls, int add_remove, const struct sockaddr *addr,
}
+
static void
nat_remove_address (void *cls, int add_remove, const struct sockaddr *addr,
socklen_t addrlen)
@@ -850,35 +1005,16 @@ nat_remove_address (void *cls, int add_remove, const struct sockaddr *addr,
switch (af)
{
case AF_INET:
- w_t4 = plugin->ipv4_addr_head;
- struct sockaddr_in *a4 = (struct sockaddr_in *) addr;
-
- while (w_t4 != NULL)
- {
- int res = memcmp (&w_t4->addr.ipv4_addr,
- &a4->sin_addr,
- sizeof (struct in_addr));
-
- if (res == 0)
- {
- if (a4->sin_port != w_t4->addr.u4_port)
- res = -1;
- }
-
- if (0 == res)
- break;
- w_t4 = w_t4->next;
- }
+ w_t4 = find_address (plugin, addr, addrlen);
if (w_t4 == NULL)
return;
-#if DEBUG_HTTP
+
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Notifying transport to remove IPv4 address `%s'\n",
http_plugin_address_to_string (NULL, &w_t4->addr,
sizeof (struct
IPv4HttpAddress)));
-#endif
plugin->env->notify_address (plugin->env->cls, add_remove, &w_t4->addr,
sizeof (struct IPv4HttpAddress));
@@ -887,32 +1023,16 @@ nat_remove_address (void *cls, int add_remove, const struct sockaddr *addr,
GNUNET_free (w_t4);
break;
case AF_INET6:
- w_t6 = plugin->ipv6_addr_head;
- struct sockaddr_in6 *a6 = (struct sockaddr_in6 *) addr;
-
- while (w_t6)
- {
- int res = memcmp (&w_t6->addr6.ipv6_addr, &a6->sin6_addr,
- sizeof (struct in6_addr));
-
- if (res == 0)
- {
- if (a6->sin6_port != w_t6->addr6.u6_port)
- res = -1;
- }
- if (0 == res)
- break;
- w_t6 = w_t6->next;
- }
+ w_t6 = find_address (plugin, addr, addrlen);
if (w_t6 == NULL)
return;
-#if DEBUG_HTTP
+
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Notifying transport to remove IPv6 address `%s'\n",
http_plugin_address_to_string (NULL, &w_t6->addr6,
sizeof (struct
IPv6HttpAddress)));
-#endif
+
plugin->env->notify_address (plugin->env->cls, add_remove, &w_t6->addr6,
sizeof (struct IPv6HttpAddress));
@@ -923,9 +1043,9 @@ nat_remove_address (void *cls, int add_remove, const struct sockaddr *addr,
default:
return;
}
-
}
+
/**
* Our external IP address/port mapping has changed.
*
@@ -940,15 +1060,13 @@ nat_port_map_callback (void *cls, int add_remove, const struct sockaddr *addr,
socklen_t addrlen)
{
GNUNET_assert (cls != NULL);
-#if DEBUG_HTTP
struct Plugin *plugin = cls;
-#endif
-#if DEBUG_HTTP
+
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"NPMC called %s to address `%s'\n",
(add_remove == GNUNET_NO) ? "remove" : "add",
GNUNET_a2s (addr, addrlen));
-#endif
+
switch (add_remove)
{
case GNUNET_YES:
@@ -960,6 +1078,7 @@ nat_port_map_callback (void *cls, int add_remove, const struct sockaddr *addr,
}
}
+
void
http_check_ipv6 (struct Plugin *plugin)
{
@@ -993,6 +1112,7 @@ http_check_ipv6 (struct Plugin *plugin)
}
}
+
int
http_get_addresses (struct Plugin *plugin, const char *serviceName,
const struct GNUNET_CONFIGURATION_Handle *cfg,
@@ -1203,6 +1323,7 @@ start_report_addresses (struct Plugin *plugin)
}
}
+
static void
stop_report_addresses (struct Plugin *plugin)
{
@@ -1230,6 +1351,7 @@ stop_report_addresses (struct Plugin *plugin)
}
}
+
static int
configure_plugin (struct Plugin *plugin)
{
@@ -1362,6 +1484,91 @@ fail:
return res;
}
+
+/**
+ * Session was idle, so disconnect it
+ */
+static void
+session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_assert (NULL != cls);
+ struct Session *s = cls;
+
+ s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Session %p was idle for %llu, disconnecting\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+
+ /* call session destroy function */
+ if (s->inbound == GNUNET_NO)
+ GNUNET_assert (GNUNET_OK == client_disconnect (s));
+ else
+ GNUNET_assert (GNUNET_OK == server_disconnect (s));
+
+}
+
+
+/**
+ * Start session timeout
+ */
+static void
+start_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task);
+
+ s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+ &session_timeout,
+ s);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout for session %p set to %llu\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+}
+
+
+/**
+ * Increment session timeout due to activity
+ */
+static void
+reschedule_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task);
+
+ GNUNET_SCHEDULER_cancel (s->timeout_task);
+ s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+ &session_timeout,
+ s);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout rescheduled for session %p set to %llu\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+}
+
+
+/**
+ * Cancel timeout
+ */
+static void
+stop_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+
+ if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task)
+ {
+ GNUNET_SCHEDULER_cancel (s->timeout_task);
+ s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout rescheduled for session %p canceled\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout for session %p was not active\n",
+ s);
+ }
+}
+
+
/**
* Entry point for the plugin.
*/
@@ -1373,14 +1580,29 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
struct Plugin *plugin;
int res;
+ if (NULL == env->receive)
+ {
+ /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
+ initialze the plugin or the API */
+ api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
+ api->cls = NULL;
+ api->address_pretty_printer = &http_plugin_address_pretty_printer;
+ api->address_to_string = &http_plugin_address_to_string;
+ api->string_to_address = &http_string_to_address;
+ return api;
+ }
+
plugin = GNUNET_malloc (sizeof (struct Plugin));
plugin->env = env;
+ plugin->outbound_sessions = 0;
+ plugin->inbound_sessions = 0;
api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
api->cls = plugin;
api->disconnect = &http_plugin_disconnect;
api->address_pretty_printer = &http_plugin_address_pretty_printer;
api->check_address = &http_plugin_address_suggested;
api->address_to_string = &http_plugin_address_to_string;
+ api->string_to_address = &http_string_to_address;
api->get_session = &http_get_session;
api->send = &http_plugin_send;
@@ -1435,11 +1657,8 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
/* Report addresses to transport service */
start_report_addresses (plugin);
-#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Plugin `%s' loaded\n", plugin->name);
-#endif
-
return api;
}
@@ -1452,7 +1671,13 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
{
struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
struct Plugin *plugin = api->cls;
- struct Session *s = NULL;
+ struct Session *s;
+
+ if (NULL == plugin)
+ {
+ GNUNET_free (api);
+ return NULL;
+ }
/* Stop reporting addresses to transport service */
stop_report_addresses (plugin);
@@ -1461,10 +1686,8 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
s = plugin->head;
while (s != NULL)
{
-#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Disconnecting `%s' \n", GNUNET_i2s (&s->target));
-#endif
if (s->inbound == GNUNET_NO)
GNUNET_assert (GNUNET_OK == client_disconnect (s));
else
@@ -1472,15 +1695,11 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
s = s->next;
}
-#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Stopping server\n");
-#endif
/* Stop server */
server_stop (plugin);
-#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name, "Stopping client\n");
-#endif
/* Stop client */
client_stop (plugin);
@@ -1512,17 +1731,12 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
s = t;
}
-
-#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Plugin `%s' unloaded\n", plugin->name);
-#endif
-
GNUNET_free_non_null (plugin->server_addr_v4);
GNUNET_free_non_null (plugin->server_addr_v6);
GNUNET_free (plugin);
GNUNET_free (api);
-
return NULL;
}
diff --git a/src/transport/plugin_transport_http.h b/src/transport/plugin_transport_http.h
index be8f93d..986d7d7 100644
--- a/src/transport/plugin_transport_http.h
+++ b/src/transport/plugin_transport_http.h
@@ -45,7 +45,7 @@
#define DEBUG_HTTP GNUNET_EXTRA_LOGGING
#define VERBOSE_SERVER GNUNET_EXTRA_LOGGING
#define VERBOSE_CLIENT GNUNET_EXTRA_LOGGING
-#define VERBOSE_CURL GNUNET_EXTRA_LOGGING
+#define VERBOSE_CURL GNUNET_NO
#if BUILD_HTTPS
#define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_https_init
@@ -160,6 +160,16 @@ struct Plugin
int max_connections;
/**
+ * Number of outbound sessions
+ */
+ unsigned int outbound_sessions;
+
+ /**
+ * Number of inbound sessions
+ */
+ unsigned int inbound_sessions;
+
+ /**
* Plugin HTTPS SSL/TLS options
* ----------------------------
*/
@@ -216,6 +226,11 @@ struct Plugin
GNUNET_SCHEDULER_TaskIdentifier server_v4_task;
/**
+ * The IPv4 server is scheduled to run asap
+ */
+ int server_v4_immediately;
+
+ /**
* MHD IPv6 daemon
*/
struct MHD_Daemon *server_v6;
@@ -226,6 +241,12 @@ struct Plugin
GNUNET_SCHEDULER_TaskIdentifier server_v6_task;
/**
+ * The IPv6 server is scheduled to run asap
+ */
+
+ int server_v6_immediately;
+
+ /**
* IPv4 server socket to bind to
*/
struct sockaddr_in *server_addr_v4;
@@ -295,6 +316,24 @@ struct IPv6HttpAddress
};
GNUNET_NETWORK_STRUCT_END
+
+struct ServerConnection
+{
+ /* _RECV or _SEND */
+ int direction;
+
+ /* Should this connection get disconnected? GNUNET_YES/NO */
+ int disconnect;
+
+ /* The session this server connection belongs to */
+ struct Session *session;
+
+ /* The MHD connection */
+ struct MHD_Connection *mhd_conn;
+};
+
+
+
/**
* Session handle for connections.
*/
@@ -390,6 +429,11 @@ struct Session
GNUNET_SCHEDULER_TaskIdentifier recv_wakeup_task;
/**
+ * Session timeout task
+ */
+ GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+ /**
* Is client send handle paused since there are no data to send?
* GNUNET_YES/NO
*/
@@ -402,12 +446,12 @@ struct Session
/**
* Client send handle
*/
- void *server_recv;
+ struct ServerConnection *server_recv;
/**
* Client send handle
*/
- void *server_send;
+ struct ServerConnection *server_send;
};
/**
@@ -453,13 +497,18 @@ struct HTTP_Message
void *transmit_cont_cls;
};
+struct Session *
+create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
+ const void *addr, size_t addrlen);
+
+int
+exist_session (struct Plugin *plugin, struct Session *s);
+
void
delete_session (struct Session *s);
-struct Session *
-create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
- const void *addr, size_t addrlen,
- GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls);
+int
+exist_session (struct Plugin *plugin, struct Session *s);
struct GNUNET_TIME_Relative
http_plugin_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
diff --git a/src/transport/plugin_transport_http_client.c b/src/transport/plugin_transport_http_client.c
index 4679e45..f55311f 100644
--- a/src/transport/plugin_transport_http_client.c
+++ b/src/transport/plugin_transport_http_client.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
+ (C) 2002--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
@@ -26,6 +26,8 @@
#include "plugin_transport_http.h"
+static struct Plugin * p;
+
#if VERBOSE_CURL
/**
* Function to log curl debug messages with GNUNET_log
@@ -53,10 +55,10 @@ client_log (CURL * curl, curl_infotype type, char *data, size_t size, void *cls)
}
#if BUILD_HTTPS
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-https",
- "Client: %X - %s", cls, text);
+ "Client: %p - %s", cls, text);
#else
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-http",
- "Client: %X - %s", cls, text);
+ "Client: %p - %s", cls, text);
#endif
}
return 0;
@@ -71,6 +73,7 @@ client_log (CURL * curl, curl_infotype type, char *data, size_t size, void *cls)
static void
client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
/**
* Function setting up file descriptors and scheduling task to run
*
@@ -97,7 +100,6 @@ client_schedule (struct Plugin *plugin, int now)
GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
plugin->client_perform_task = GNUNET_SCHEDULER_NO_TASK;
}
-
max = -1;
FD_ZERO (&rs);
FD_ZERO (&ws);
@@ -133,7 +135,7 @@ client_schedule (struct Plugin *plugin, int now)
plugin->client_perform_task =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK, timeout, grs, gws,
+ timeout, grs, gws,
&client_run, plugin);
GNUNET_NETWORK_fdset_destroy (gws);
GNUNET_NETWORK_fdset_destroy (grs);
@@ -145,27 +147,29 @@ int
client_send (struct Session *s, struct HTTP_Message *msg)
{
GNUNET_assert (s != NULL);
- GNUNET_CONTAINER_DLL_insert (s->msg_head, s->msg_tail, msg);
+ GNUNET_CONTAINER_DLL_insert_tail (s->msg_head, s->msg_tail, msg);
+ if (GNUNET_YES != exist_session(p, s))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
if (s->client_put_paused == GNUNET_YES)
{
-#if VERBOSE_CLIENT
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
- "Client: %X was suspended, unpausing\n", s->client_put);
-#endif
+ "Client: %p was suspended, unpausing\n", s->client_put);
s->client_put_paused = GNUNET_NO;
curl_easy_pause (s->client_put, CURLPAUSE_CONT);
}
-
client_schedule (s->plugin, GNUNET_YES);
return GNUNET_OK;
}
-
/**
* Task performing curl operations
+ *
* @param cls plugin as closure
* @param tc gnunet scheduler task context
*/
@@ -210,12 +214,19 @@ client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
GNUNET_assert (CURLE_OK ==
curl_easy_getinfo (easy_h, CURLINFO_PRIVATE, &d));
s = (struct Session *) d;
+
+ if (GNUNET_YES != exist_session(plugin, s))
+ {
+ GNUNET_break (0);
+ return;
+ }
+
GNUNET_assert (s != NULL);
if (msg->msg == CURLMSG_DONE)
{
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Client: %X connection to '%s' %s ended with reason %i: `%s'\n",
+ "Client: %p connection to '%s' %s ended with reason %i: `%s'\n",
msg->easy_handle, GNUNET_i2s (&s->target),
http_plugin_address_to_string (NULL, s->addr,
s->addrlen),
@@ -223,7 +234,11 @@ client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
curl_easy_strerror (msg->data.result));
client_disconnect (s);
- //GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,"Notifying about ended session to peer `%s' `%s'\n", GNUNET_i2s (&s->target), http_plugin_address_to_string (plugin, s->addr, s->addrlen));
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
+ plugin->name,
+ "Notifying about ended session to peer `%s' `%s'\n",
+ GNUNET_i2s (&s->target),
+ http_plugin_address_to_string (plugin, s->addr, s->addrlen));
notify_session_end (plugin, &s->target, s);
}
}
@@ -232,6 +247,7 @@ client_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
client_schedule (plugin, GNUNET_NO);
}
+
int
client_disconnect (struct Session *s)
{
@@ -241,15 +257,17 @@ client_disconnect (struct Session *s)
struct HTTP_Message *msg;
struct HTTP_Message *t;
-
+ if (GNUNET_YES != exist_session(plugin, s))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
if (s->client_put != NULL)
{
-#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Client: %X Deleting outbound PUT session to peer `%s'\n",
+ "Client: %p Deleting outbound PUT session to peer `%s'\n",
s->client_put, GNUNET_i2s (&s->target));
-#endif
mret = curl_multi_remove_handle (plugin->client_mh, s->client_put);
if (mret != CURLM_OK)
@@ -271,11 +289,9 @@ client_disconnect (struct Session *s)
if (s->client_get != NULL)
{
-#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Client: %X Deleting outbound GET session to peer `%s'\n",
+ "Client: %p Deleting outbound GET session to peer `%s'\n",
s->client_get, GNUNET_i2s (&s->target));
-#endif
mret = curl_multi_remove_handle (plugin->client_mh, s->client_get);
if (mret != CURLM_OK)
@@ -300,6 +316,14 @@ client_disconnect (struct Session *s)
}
plugin->cur_connections -= 2;
+
+ GNUNET_assert (plugin->outbound_sessions > 0);
+ plugin->outbound_sessions --;
+ GNUNET_STATISTICS_set (plugin->env->stats,
+ "# HTTP outbound sessions",
+ plugin->outbound_sessions,
+ GNUNET_NO);
+
/* Re-schedule since handles have changed */
if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK)
{
@@ -312,84 +336,86 @@ client_disconnect (struct Session *s)
return res;
}
-static void
+static int
client_receive_mst_cb (void *cls, void *client,
const struct GNUNET_MessageHeader *message)
{
struct Session *s = cls;
struct GNUNET_TIME_Relative delay;
+ if (GNUNET_YES != exist_session(p, s))
+ {
+ GNUNET_break (0);
+ return GNUNET_OK;
+ }
+
delay = http_plugin_receive (s, &s->target, message, s, s->addr, s->addrlen);
s->next_receive =
GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), delay);
if (GNUNET_TIME_absolute_get ().abs_value < s->next_receive.abs_value)
{
-#if VERBOSE_CLIENT
struct Plugin *plugin = s->plugin;
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Client: peer `%s' address `%s' next read delayed for %llu ms\n",
GNUNET_i2s (&s->target), GNUNET_a2s (s->addr, s->addrlen),
delay);
-#endif
}
+ return GNUNET_OK;
}
+
static void
client_wake_up (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct Session *s = cls;
+ if (GNUNET_YES != exist_session(p, s))
+ {
+ GNUNET_break (0);
+ return;
+ }
s->recv_wakeup_task = GNUNET_SCHEDULER_NO_TASK;
-
if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
return;
-
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
- "Client: %X Waking up receive handle\n", s->client_get);
-
+ "Client: %p Waking up receive handle\n", s->client_get);
if (s->client_get != NULL)
curl_easy_pause (s->client_get, CURLPAUSE_CONT);
-
}
+
/**
-* Callback method used with libcurl
-* Method is called when libcurl needs to write data during sending
-* @param stream pointer where to write data
-* @param size size of an individual element
-* @param nmemb count of elements that can be written to the buffer
-* @param cls destination pointer, passed to the libcurl handle
-* @return bytes read from stream
-*/
+ * Callback method used with libcurl
+ * Method is called when libcurl needs to write data during sending
+ *
+ * @param stream pointer where to write data
+ * @param size size of an individual element
+ * @param nmemb count of elements that can be written to the buffer
+ * @param cls destination pointer, passed to the libcurl handle
+ * @return bytes read from stream
+ */
static size_t
client_receive (void *stream, size_t size, size_t nmemb, void *cls)
{
struct Session *s = cls;
struct GNUNET_TIME_Absolute now;
size_t len = size * nmemb;
-
-
-#if VERBOSE_CLIENT
struct Plugin *plugin = s->plugin;
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Client: Received %Zu bytes from peer `%s'\n", len,
GNUNET_i2s (&s->target));
-#endif
-
now = GNUNET_TIME_absolute_get ();
if (now.abs_value < s->next_receive.abs_value)
{
struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
struct GNUNET_TIME_Relative delta =
GNUNET_TIME_absolute_get_difference (now, s->next_receive);
-#if DEBUG_CLIENT
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Client: %X No inbound bandwidth available! Next read was delayed for %llu ms\n",
+ "Client: %p No inbound bandwidth available! Next read was delayed for %llu ms\n",
s->client_get, delta.rel_value);
-#endif
if (s->recv_wakeup_task != GNUNET_SCHEDULER_NO_TASK)
{
GNUNET_SCHEDULER_cancel (s->recv_wakeup_task);
@@ -399,19 +425,17 @@ client_receive (void *stream, size_t size, size_t nmemb, void *cls)
GNUNET_SCHEDULER_add_delayed (delta, &client_wake_up, s);
return CURLPAUSE_ALL;
}
-
-
- if (s->msg_tk == NULL)
+ if (NULL == s->msg_tk)
s->msg_tk = GNUNET_SERVER_mst_create (&client_receive_mst_cb, s);
-
GNUNET_SERVER_mst_receive (s->msg_tk, s, stream, len, GNUNET_NO, GNUNET_NO);
-
return len;
}
+
/**
* Callback method used with libcurl
* Method is called when libcurl needs to read data during sending
+ *
* @param stream pointer where to write data
* @param size size of an individual element
* @param nmemb count of elements that can be written to the buffer
@@ -422,69 +446,45 @@ static size_t
client_send_cb (void *stream, size_t size, size_t nmemb, void *cls)
{
struct Session *s = cls;
-
-#if VERBOSE_CLIENT
struct Plugin *plugin = s->plugin;
-#endif
- size_t bytes_sent = 0;
- size_t len;
-
struct HTTP_Message *msg = s->msg_head;
+ size_t len;
- if (msg == NULL)
+ if (GNUNET_YES != exist_session(plugin, s))
+ {
+ GNUNET_break (0);
+ return 0;
+ }
+ if (NULL == msg)
{
-#if VERBOSE_CLIENT
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Client: %X Nothing to send! Suspending PUT handle!\n",
+ "Client: %p Nothing to send! Suspending PUT handle!\n",
s->client_put);
-#endif
s->client_put_paused = GNUNET_YES;
return CURL_READFUNC_PAUSE;
}
-
- GNUNET_assert (msg != NULL);
/* data to send */
- if (msg->pos < msg->size)
- {
- /* data fit in buffer */
- if ((msg->size - msg->pos) <= (size * nmemb))
- {
- len = (msg->size - msg->pos);
- memcpy (stream, &msg->buf[msg->pos], len);
- msg->pos += len;
- bytes_sent = len;
- }
- else
- {
- len = size * nmemb;
- memcpy (stream, &msg->buf[msg->pos], len);
- msg->pos += len;
- bytes_sent = len;
- }
- }
- /* no data to send */
- else
- {
- GNUNET_assert (0);
- bytes_sent = 0;
- }
-
+ GNUNET_assert (msg->pos < msg->size);
+ /* calculate how much fits in buffer */
+ len = GNUNET_MIN (msg->size - msg->pos,
+ size * nmemb);
+ memcpy (stream, &msg->buf[msg->pos], len);
+ msg->pos += len;
if (msg->pos == msg->size)
{
-#if VERBOSE_CLIENT
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Client: %X Message with %u bytes sent, removing message from queue\n",
+ "Client: %p Message with %u bytes sent, removing message from queue\n",
s->client_put, msg->size, msg->pos);
-#endif
/* Calling transmit continuation */
+ GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
if (NULL != msg->transmit_cont)
msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_OK);
- GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
GNUNET_free (msg);
}
- return bytes_sent;
+ return len;
}
+
int
client_connect (struct Session *s)
{
@@ -493,15 +493,10 @@ client_connect (struct Session *s)
char *url;
CURLMcode mret;
-#if VERBOSE_CLIENT
-#endif
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Initiating outbound session peer `%s'\n",
GNUNET_i2s (&s->target));
-
-
s->inbound = GNUNET_NO;
-
plugin->last_tag++;
/* create url */
GNUNET_asprintf (&url, "%s%s;%u",
@@ -595,6 +590,12 @@ client_connect (struct Session *s)
/* Perform connect */
plugin->cur_connections += 2;
+ plugin->outbound_sessions ++;
+ GNUNET_STATISTICS_set (plugin->env->stats,
+ "# HTTP outbound sessions",
+ plugin->outbound_sessions,
+ GNUNET_NO);
+
/* Re-schedule since handles have changed */
if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK)
{
@@ -606,10 +607,12 @@ client_connect (struct Session *s)
return res;
}
+
int
client_start (struct Plugin *plugin)
{
int res = GNUNET_OK;
+ p = plugin;
curl_global_init (CURL_GLOBAL_ALL);
plugin->client_mh = curl_multi_init ();
@@ -619,15 +622,17 @@ client_start (struct Plugin *plugin)
GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
_
("Could not initialize curl multi handle, failed to start %s plugin!\n"),
- plugin->name);
+ plugin->name);
res = GNUNET_SYSERR;
}
return res;
}
+
void
client_stop (struct Plugin *plugin)
{
+ p = NULL;
if (plugin->client_perform_task != GNUNET_SCHEDULER_NO_TASK)
{
GNUNET_SCHEDULER_cancel (plugin->client_perform_task);
diff --git a/src/transport/plugin_transport_http_server.c b/src/transport/plugin_transport_http_server.c
index 8ec5a5e..4b4f504 100644
--- a/src/transport/plugin_transport_http_server.c
+++ b/src/transport/plugin_transport_http_server.c
@@ -30,17 +30,7 @@
#define _RECEIVE 0
#define _SEND 1
-struct ServerConnection
-{
- /* _RECV or _SEND */
- int direction;
-
- /* should this connection get disconnected? GNUNET_YES/NO */
- int disconnect;
-
- struct Session *session;
- struct MHD_Connection *mhd_conn;
-};
+static struct Plugin * p;
/**
* Function that queries MHD's select sets and
@@ -95,12 +85,13 @@ static char *
server_load_file (const char *file)
{
struct GNUNET_DISK_FileHandle *gn_file;
- struct stat fstat;
+ uint64_t fsize;
char *text = NULL;
- if (0 != STAT (file, &fstat))
+ if (GNUNET_OK != GNUNET_DISK_file_size (file,
+ &fsize, GNUNET_NO, GNUNET_YES))
return NULL;
- text = GNUNET_malloc (fstat.st_size + 1);
+ text = GNUNET_malloc (fsize + 1);
gn_file =
GNUNET_DISK_file_open (file, GNUNET_DISK_OPEN_READ,
GNUNET_DISK_PERM_USER_READ);
@@ -109,13 +100,13 @@ server_load_file (const char *file)
GNUNET_free (text);
return NULL;
}
- if (GNUNET_SYSERR == GNUNET_DISK_file_read (gn_file, text, fstat.st_size))
+ if (GNUNET_SYSERR == GNUNET_DISK_file_read (gn_file, text, fsize))
{
GNUNET_free (text);
GNUNET_DISK_file_close (gn_file);
return NULL;
}
- text[fstat.st_size] = '\0';
+ text[fsize] = '\0';
GNUNET_DISK_file_close (gn_file);
return text;
}
@@ -172,10 +163,8 @@ server_load_certificate (struct Plugin *plugin)
GNUNET_free_non_null (plugin->cert);
plugin->cert = NULL;
-#if VERBOSE_SERVER
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"No usable TLS certificate found, creating certificate\n");
-#endif
errno = 0;
cert_creation =
GNUNET_OS_start_process (GNUNET_NO, NULL, NULL,
@@ -200,7 +189,7 @@ server_load_certificate (struct Plugin *plugin)
return GNUNET_SYSERR;
}
GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (cert_creation));
- GNUNET_OS_process_close (cert_creation);
+ GNUNET_OS_process_destroy (cert_creation);
plugin->key = server_load_file (key_file);
plugin->cert = server_load_file (cert_file);
@@ -226,10 +215,7 @@ server_load_certificate (struct Plugin *plugin)
}
GNUNET_free (key_file);
GNUNET_free (cert_file);
-#if DEBUG_HTTP
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TLS certificate loaded\n");
-#endif
-
return res;
}
#endif
@@ -242,12 +228,17 @@ server_load_certificate (struct Plugin *plugin)
* @param now GNUNET_YES to schedule execution immediately, GNUNET_NO to wait
* until timeout
*/
-
static void
server_reschedule (struct Plugin *plugin, struct MHD_Daemon *server, int now)
{
if ((server == plugin->server_v4) && (plugin->server_v4 != NULL))
{
+ if (GNUNET_YES == plugin->server_v4_immediately)
+ return; /* No rescheduling, server will run asap */
+
+ if (GNUNET_YES == now)
+ plugin->server_v4_immediately = GNUNET_YES;
+
if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK)
{
GNUNET_SCHEDULER_cancel (plugin->server_v4_task);
@@ -258,6 +249,12 @@ server_reschedule (struct Plugin *plugin, struct MHD_Daemon *server, int now)
if ((server == plugin->server_v6) && (plugin->server_v6 != NULL))
{
+ if (GNUNET_YES == plugin->server_v6_immediately)
+ return; /* No rescheduling, server will run asap */
+
+ if (GNUNET_YES == now)
+ plugin->server_v6_immediately = GNUNET_YES;
+
if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK)
{
GNUNET_SCHEDULER_cancel (plugin->server_v6_task);
@@ -273,11 +270,16 @@ server_reschedule (struct Plugin *plugin, struct MHD_Daemon *server, int now)
* @param client clien
* @param message the message to be forwarded to transport service
*/
-static void
+static int
server_receive_mst_cb (void *cls, void *client,
const struct GNUNET_MessageHeader *message)
{
struct Session *s = cls;
+
+ GNUNET_assert (NULL != p);
+ if (GNUNET_NO == exist_session(p, s))
+ return GNUNET_OK;
+
struct Plugin *plugin = s->plugin;
struct GNUNET_TIME_Relative delay;
@@ -294,8 +296,10 @@ server_receive_mst_cb (void *cls, void *client,
http_plugin_address_to_string (NULL, s->addr, s->addrlen),
delay);
}
+ return GNUNET_OK;
}
+
/**
* Callback called by MHD when it needs data to send
* @param cls current session
@@ -308,47 +312,54 @@ static ssize_t
server_send_callback (void *cls, uint64_t pos, char *buf, size_t max)
{
struct Session *s = cls;
-
+ ssize_t bytes_read = 0;
struct HTTP_Message *msg;
- int bytes_read = 0;
- //static int c = 0;
+ GNUNET_assert (NULL != p);
+ if (GNUNET_NO == exist_session(p, s))
+ return 0;
msg = s->msg_head;
- if (msg != NULL)
+ if (NULL != msg)
{
/* sending */
- if ((msg->size - msg->pos) <= max)
- {
- memcpy (buf, &msg->buf[msg->pos], (msg->size - msg->pos));
- bytes_read = msg->size - msg->pos;
- msg->pos += (msg->size - msg->pos);
- }
- else
- {
- memcpy (buf, &msg->buf[msg->pos], max);
- msg->pos += max;
- bytes_read = max;
- }
+ bytes_read = GNUNET_MIN (msg->size - msg->pos,
+ max);
+ memcpy (buf, &msg->buf[msg->pos], bytes_read);
+ msg->pos += bytes_read;
/* removing message */
if (msg->pos == msg->size)
{
+ GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
if (NULL != msg->transmit_cont)
msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_OK);
- GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
GNUNET_free (msg);
}
}
+ GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, s->plugin->name,
+ "Server: %p: sent %u bytes\n", s, bytes_read);
+ return bytes_read;
+}
- struct Plugin *plugin = s->plugin;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Server: %X: sent %u bytes\n", s, bytes_read);
- return bytes_read;
+static struct Session *
+server_lookup_session (struct Plugin *plugin,
+ struct ServerConnection * sc)
+{
+ struct Session *s;
+
+ for (s = plugin->head; NULL != s; s = s->next)
+ if ((s->server_recv == sc) || (s->server_send == sc))
+ return s;
+ for (s = plugin->server_semi_head; NULL != s; s = s->next)
+ if ((s->server_recv == sc) || (s->server_send == sc))
+ return s;
+ return NULL;
}
+
static struct ServerConnection *
-server_lookup_session (struct Plugin *plugin,
+server_lookup_serverconnection (struct Plugin *plugin,
struct MHD_Connection *mhd_connection, const char *url,
const char *method)
{
@@ -368,12 +379,11 @@ server_lookup_session (struct Plugin *plugin,
uint32_t tag = 0;
int direction = GNUNET_SYSERR;
- conn_info =
- MHD_get_connection_info (mhd_connection,
+ conn_info = MHD_get_connection_info (mhd_connection,
MHD_CONNECTION_INFO_CLIENT_ADDRESS);
if ((conn_info->client_addr->sa_family != AF_INET) &&
(conn_info->client_addr->sa_family != AF_INET6))
- return MHD_NO;
+ return NULL;
if ((strlen (&url[1]) >= 105) && (url[104] == ';'))
{
@@ -408,12 +418,12 @@ server_lookup_session (struct Plugin *plugin,
plugin->cur_connections++;
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Server: New inbound connection from %s with tag %u\n",
+ "Server: New %s connection from %s with tag %u\n",
+ method,
GNUNET_i2s (&target), tag);
- /* find duplicate session */
+ /* find duplicate session */
t = plugin->head;
-
while (t != NULL)
{
if ((t->inbound) &&
@@ -469,6 +479,12 @@ server_lookup_session (struct Plugin *plugin,
"Server: Found matching semi-session, merging session for peer `%s'\n",
GNUNET_i2s (&target));
+ plugin->inbound_sessions ++;
+ GNUNET_STATISTICS_set (plugin->env->stats,
+ "# HTTP inbound sessions",
+ plugin->inbound_sessions,
+ GNUNET_NO);
+ GNUNET_assert (NULL != s);
goto found;
}
if ((direction == _RECEIVE) && (t->server_recv != NULL))
@@ -487,6 +503,12 @@ server_lookup_session (struct Plugin *plugin,
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Server: Found matching semi-session, merging session for peer `%s'\n",
GNUNET_i2s (&target));
+ plugin->inbound_sessions ++;
+ GNUNET_STATISTICS_set (plugin->env->stats,
+ "# HTTP inbound sessions",
+ plugin->inbound_sessions,
+ GNUNET_NO);
+ GNUNET_assert (NULL != s);
goto found;
}
@@ -517,16 +539,15 @@ create:
GNUNET_break (0);
goto error;
}
- s = create_session (plugin, &target, a, a_len, NULL, NULL);
+ s = create_session (plugin, &target, a, a_len);
+ GNUNET_assert (NULL != s);
s->ats_address_network_type = ats.value;
-
s->inbound = GNUNET_YES;
- s->next_receive = GNUNET_TIME_absolute_get_zero ();
+ s->next_receive = GNUNET_TIME_UNIT_ZERO_ABS;
s->tag = tag;
- if (0 == strcmp (MHD_HTTP_METHOD_PUT, method))
- s->server_recv = s;
- if (0 == strcmp (MHD_HTTP_METHOD_GET, method))
- s->server_send = s;
+ s->server_recv = NULL;
+ s->server_send = NULL;
+
GNUNET_CONTAINER_DLL_insert (plugin->server_semi_head,
plugin->server_semi_tail, s);
goto found;
@@ -550,7 +571,7 @@ found:
int to = (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value / 1000);
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Server: Setting timeout for %X to %u sec.\n", sc, to);
+ "Server: Setting timeout for %p to %u sec.\n", sc, to);
MHD_set_connection_option (mhd_connection, MHD_CONNECTION_OPTION_TIMEOUT, to);
struct MHD_Daemon *d = NULL;
@@ -578,19 +599,17 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
const char *upload_data, size_t * upload_data_size,
void **httpSessionCache)
{
-
struct Plugin *plugin = cls;
struct ServerConnection *sc = *httpSessionCache;
- struct Session *s = NULL;
-
- int res = MHD_YES;
+ struct Session *s;
struct MHD_Response *response;
+ int res = MHD_YES;
GNUNET_assert (cls != NULL);
- /* new connection */
if (sc == NULL)
{
- sc = server_lookup_session (plugin, mhd_connection, url, method);
+ /* new connection */
+ sc = server_lookup_serverconnection (plugin, mhd_connection, url, method);
if (sc != NULL)
(*httpSessionCache) = sc;
else
@@ -603,11 +622,22 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
return res;
}
}
+ else
+ {
+ /* 'old' connection */
+ if (NULL == server_lookup_session (plugin, sc))
+ {
+ /* Session was already disconnected */
+ return MHD_NO;
+ }
+ }
/* existing connection */
sc = (*httpSessionCache);
s = sc->session;
+ GNUNET_assert (NULL != s);
+
/* connection is to be disconnected */
if (sc->disconnect == GNUNET_YES)
{
@@ -663,7 +693,7 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
if ((s->next_receive.abs_value <= now.abs_value))
{
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Server: %X: PUT with %u bytes forwarded to MST\n", s,
+ "Server: %p: PUT with %u bytes forwarded to MST\n", s,
*upload_data_size);
if (s->msg_tk == NULL)
{
@@ -683,7 +713,7 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
{
t = s->server_recv;
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Server: Setting timeout for %X to %u sec.\n", t,
+ "Server: Setting timeout for %p to %u sec.\n", t,
to);
MHD_set_connection_option (t->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT,
to);
@@ -692,7 +722,7 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
{
t = s->server_send;
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Server: Setting timeout for %X to %u sec.\n", t,
+ "Server: Setting timeout for %p to %u sec.\n", t,
to);
MHD_set_connection_option (t->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT,
to);
@@ -710,7 +740,7 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
else
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Server: %X no inbound bandwidth available! Next read was delayed by %llu ms\n",
+ "Server: %p no inbound bandwidth available! Next read was delayed by %llu ms\n",
s, now.abs_value - s->next_receive.abs_value);
}
return MHD_YES;
@@ -734,24 +764,28 @@ server_disconnect_cb (void *cls, struct MHD_Connection *connection,
if (sc == NULL)
return;
- s = sc->session;
+ if (NULL == (s = server_lookup_session (p, sc)))
+ return;
+
+ GNUNET_assert (NULL != p);
+ if (GNUNET_NO == exist_session(p, s))
+ return;
+
plugin = s->plugin;
if (sc->direction == _SEND)
{
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Server: %X peer `%s' GET on address `%s' disconnected\n",
+ "Server: %p peer `%s' GET on address `%s' disconnected\n",
s->server_send, GNUNET_i2s (&s->target),
http_plugin_address_to_string (NULL, s->addr, s->addrlen));
-
s->server_send = NULL;
-
- if (s->server_recv != NULL)
+ if (NULL != (tc = s->server_recv))
{
- tc = s->server_recv;
tc->disconnect = GNUNET_YES;
+ GNUNET_assert (NULL != tc->mhd_conn);
#if MHD_VERSION >= 0x00090E00
- MHD_set_connection_option (sc->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT,
+ MHD_set_connection_option (tc->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT,
1);
#endif
}
@@ -759,16 +793,16 @@ server_disconnect_cb (void *cls, struct MHD_Connection *connection,
if (sc->direction == _RECEIVE)
{
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
- "Server: %X peer `%s' PUT on address `%s' disconnected\n",
+ "Server: %p peer `%s' PUT on address `%s' disconnected\n",
s->server_recv, GNUNET_i2s (&s->target),
http_plugin_address_to_string (NULL, s->addr, s->addrlen));
s->server_recv = NULL;
- if (s->server_send != NULL)
+ if (NULL != (tc = s->server_send))
{
- tc = s->server_send;
tc->disconnect = GNUNET_YES;
+ GNUNET_assert (NULL != tc->mhd_conn);
#if MHD_VERSION >= 0x00090E00
- MHD_set_connection_option (sc->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT,
+ MHD_set_connection_option (tc->mhd_conn, MHD_CONNECTION_OPTION_TIMEOUT,
1);
#endif
}
@@ -778,6 +812,7 @@ server_disconnect_cb (void *cls, struct MHD_Connection *connection,
s->msg_tk = NULL;
}
}
+
GNUNET_free (sc);
t = plugin->server_semi_head;
@@ -814,6 +849,12 @@ server_disconnect_cb (void *cls, struct MHD_Connection *connection,
s->msg_tk = NULL;
}
+ GNUNET_assert (plugin->inbound_sessions > 0);
+ plugin->inbound_sessions --;
+ GNUNET_STATISTICS_set (plugin->env->stats,
+ "# HTTP inbound sessions",
+ plugin->inbound_sessions, GNUNET_NO);
+
notify_session_end (s->plugin, &s->target, s);
}
}
@@ -821,31 +862,22 @@ server_disconnect_cb (void *cls, struct MHD_Connection *connection,
int
server_disconnect (struct Session *s)
{
- struct Plugin *plugin = s->plugin;
- struct Session *t = plugin->head;
-
- while (t != NULL)
+ if (s->server_send != NULL)
{
- if (t->inbound == GNUNET_YES)
- {
- if (t->server_send != NULL)
- {
- ((struct ServerConnection *) t->server_send)->disconnect = GNUNET_YES;
- }
- if (t->server_send != NULL)
- {
- ((struct ServerConnection *) t->server_send)->disconnect = GNUNET_YES;
- }
- }
- t = t->next;
+ ((struct ServerConnection *) s->server_send)->disconnect = GNUNET_YES;
}
+ if (s->server_recv != NULL)
+ {
+ ((struct ServerConnection *) s->server_recv)->disconnect = GNUNET_YES;
+ }
+
return GNUNET_OK;
}
int
server_send (struct Session *s, struct HTTP_Message *msg)
{
- GNUNET_CONTAINER_DLL_insert (s->msg_head, s->msg_tail, msg);
+ GNUNET_CONTAINER_DLL_insert_tail (s->msg_head, s->msg_tail, msg);
if (s->addrlen == sizeof (struct IPv4HttpAddress))
{
@@ -876,17 +908,15 @@ server_v4_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
GNUNET_assert (cls != NULL);
plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK;
-
if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
return;
-
+#if 0
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Running IPv4 server\n");
-
+#endif
+ plugin->server_v4_immediately = GNUNET_NO;
GNUNET_assert (MHD_YES == MHD_run (plugin->server_v4));
- if (plugin->server_v4 != NULL)
- plugin->server_v4_task =
- server_schedule (plugin, plugin->server_v4, GNUNET_NO);
+ server_reschedule (plugin, plugin->server_v4, GNUNET_NO);
}
@@ -902,19 +932,16 @@ server_v6_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
struct Plugin *plugin = cls;
GNUNET_assert (cls != NULL);
-
plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK;
-
if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
return;
-
+#if 0
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Running IPv6 server\n");
-
+#endif
+ plugin->server_v6_immediately = GNUNET_NO;
GNUNET_assert (MHD_YES == MHD_run (plugin->server_v6));
- if (plugin->server_v6 != NULL)
- plugin->server_v6_task =
- server_schedule (plugin, plugin->server_v6, GNUNET_NO);
+ server_reschedule (plugin, plugin->server_v6, GNUNET_NO);
}
/**
@@ -936,7 +963,7 @@ server_schedule (struct Plugin *plugin, struct MHD_Daemon *daemon_handle,
struct GNUNET_NETWORK_FDSet *wws;
struct GNUNET_NETWORK_FDSet *wes;
int max;
- unsigned long long timeout;
+ unsigned MHD_LONG_LONG timeout;
static unsigned long long last_timeout = 0;
int haveto;
@@ -981,13 +1008,13 @@ server_schedule (struct Plugin *plugin, struct MHD_Daemon *daemon_handle,
GNUNET_SCHEDULER_cancel (plugin->server_v4_task);
plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK;
}
-#if VERBOSE_SERVER
+#if 0
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Scheduling IPv4 server task in %llu ms\n", tv);
#endif
ret =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK, tv, wrs, wws,
+ tv, wrs, wws,
&server_v4_run, plugin);
}
if (daemon_handle == plugin->server_v6)
@@ -997,13 +1024,13 @@ server_schedule (struct Plugin *plugin, struct MHD_Daemon *daemon_handle,
GNUNET_SCHEDULER_cancel (plugin->server_v6_task);
plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK;
}
-#if VERBOSE_SERVER
+#if 0
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"Scheduling IPv6 server task in %llu ms\n", tv);
#endif
ret =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK, tv, wrs, wws,
+ tv, wrs, wws,
&server_v6_run, plugin);
}
GNUNET_NETWORK_fdset_destroy (wrs);
@@ -1017,6 +1044,8 @@ server_start (struct Plugin *plugin)
{
int res = GNUNET_OK;
unsigned int timeout;
+ p = plugin;
+ GNUNET_assert (NULL != plugin);
#if BUILD_HTTPS
res = server_load_certificate (plugin);
@@ -1133,13 +1162,9 @@ server_start (struct Plugin *plugin)
return GNUNET_SYSERR;
}
server_reschedule (plugin, plugin->server_v6, GNUNET_NO);
-
-
-#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"%s server component started on port %u\n", plugin->name,
plugin->port);
-#endif
return res;
}
@@ -1206,16 +1231,16 @@ server_stop (struct Plugin *plugin)
s = t;
}
+ p = NULL;
+
#if BUILD_HTTPS
GNUNET_free_non_null (plugin->crypto_init);
GNUNET_free_non_null (plugin->cert);
GNUNET_free_non_null (plugin->key);
#endif
-#if DEBUG_HTTP
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
"%s server component stopped\n", plugin->name);
-#endif
}
diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c
index 2b2d728..af5c715 100644
--- a/src/transport/plugin_transport_tcp.c
+++ b/src/transport/plugin_transport_tcp.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Christian Grothoff (and other contributing authors)
+ (C) 2002--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
@@ -39,9 +39,14 @@
#include "gnunet_transport_plugin.h"
#include "transport.h"
-#define DEBUG_TCP GNUNET_EXTRA_LOGGING
+#define LOG(kind,...) GNUNET_log_from (kind, "transport-tcp",__VA_ARGS__)
+
+/**
+ * How long until we give up on establishing an NAT connection?
+ * Must be > 4 RTT
+ */
+#define NAT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
-#define DEBUG_TCP_NAT GNUNET_EXTRA_LOGGING
GNUNET_NETWORK_STRUCT_BEGIN
@@ -225,11 +230,6 @@ struct Session
struct SessionHeader header;
/**
- * Stored in a linked list.
- */
- struct Session *next;
-
- /**
* Pointer to the global plugin struct.
*/
struct Plugin *plugin;
@@ -240,6 +240,11 @@ struct Session
struct GNUNET_SERVER_Client *client;
/**
+ * Task cleaning up a NAT client connection establishment attempt;
+ */
+ GNUNET_SCHEDULER_TaskIdentifier nat_connection_timeout;
+
+ /**
* Messages currently pending for transmission
* to this peer, if any.
*/
@@ -254,7 +259,7 @@ struct Session
/**
* Handle for pending transmission request.
*/
- struct GNUNET_CONNECTION_TransmitHandle *transmit_handle;
+ struct GNUNET_SERVER_TransmitHandle *transmit_handle;
/**
* To whom are we talking to (set to our identity
@@ -268,6 +273,11 @@ struct Session
GNUNET_SCHEDULER_TaskIdentifier receive_delay_task;
/**
+ * Session timeout task
+ */
+ GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+ /**
* Address of the other peer (either based on our 'connect'
* call or on our 'accept' call).
*
@@ -329,7 +339,10 @@ struct Plugin
*/
struct GNUNET_NAT_Handle *nat;
- struct GNUNET_CONTAINER_MultiHashMap * sessionmap;
+ /**
+ * Map from peer identities to sessions for the given peer.
+ */
+ struct GNUNET_CONTAINER_MultiHashMap *sessionmap;
/**
* Handle to the network service.
@@ -392,6 +405,71 @@ struct Plugin
/**
+ * Start session timeout
+ */
+static void
+start_session_timeout (struct Session *s);
+
+
+/**
+ * Increment session timeout due to activity
+ */
+static void
+reschedule_session_timeout (struct Session *s);
+
+
+/**
+ * Cancel timeout
+ */
+static void
+stop_session_timeout (struct Session *s);
+
+
+/* DEBUG CODE */
+static const char *
+tcp_address_to_string (void *cls, const void *addr, size_t addrlen);
+
+
+static unsigned int sessions;
+
+
+static void
+inc_sessions (struct Plugin *plugin, struct Session *session, int line)
+{
+ sessions++;
+ unsigned int size = GNUNET_CONTAINER_multihashmap_size(plugin->sessionmap);
+ if (sessions != size)
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Inconsistent sessions %u <-> session map size: %u\n",
+ sessions, size);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "%4i Session increased to %u (session map size: %u): `%s' `%s'\n",
+ line,
+ sessions,
+ size,
+ GNUNET_i2s (&session->target),
+ tcp_address_to_string (NULL, session->addr, session->addrlen));
+}
+
+
+static void
+dec_sessions (struct Plugin *plugin, struct Session *session, int line)
+{
+ GNUNET_assert (sessions > 0);
+ unsigned int size = GNUNET_CONTAINER_multihashmap_size(plugin->sessionmap);
+ sessions--;
+ if (sessions != size)
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Inconsistent sessions %u <-> session map size: %u\n",
+ sessions, size);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "%4i Session decreased to %u (session map size: %u): `%s' `%s'\n",
+ line,
+ sessions,
+ size,
+ GNUNET_i2s (&session->target),
+ tcp_address_to_string (NULL, session->addr, session->addrlen));
+}
+/* DEBUG CODE */
+
+
+/**
* Function to check if an inbound connection is acceptable.
* Mostly used to limit the total number of open connections
* we can have.
@@ -410,6 +488,8 @@ plugin_tcp_access_check (void *cls,
{
struct Plugin *plugin = cls;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Accepting new incoming TCP connection\n");
if (0 == plugin->max_connections)
return GNUNET_NO;
plugin->max_connections--;
@@ -436,9 +516,9 @@ tcp_nat_port_map_callback (void *cls, int add_remove,
void *arg;
size_t args;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "NPMC called with %d for address `%s'\n", add_remove,
- GNUNET_a2s (addr, addrlen));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "NPMC called with %d for address `%s'\n", add_remove,
+ GNUNET_a2s (addr, addrlen));
/* convert 'addr' to our internal format */
switch (addr->sa_family)
{
@@ -490,27 +570,26 @@ tcp_address_to_string (void *cls, const void *addr, size_t addrlen)
int af;
uint16_t port;
- if (addrlen == sizeof (struct IPv6TcpAddress))
+ switch (addrlen)
{
+ case sizeof (struct IPv6TcpAddress):
t6 = addr;
af = AF_INET6;
port = ntohs (t6->t6_port);
memcpy (&a6, &t6->ipv6_addr, sizeof (a6));
sb = &a6;
- }
- else if (addrlen == sizeof (struct IPv4TcpAddress))
- {
+ break;
+ case sizeof (struct IPv4TcpAddress):
t4 = addr;
af = AF_INET;
port = ntohs (t4->t4_port);
memcpy (&a4, &t4->ipv4_addr, sizeof (a4));
sb = &a4;
- }
- else
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "tcp",
- _("Unexpected address length: %u bytes\n"),
- (unsigned int) addrlen);
+ break;
+ default:
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Unexpected address length: %u bytes\n"),
+ (unsigned int) addrlen);
GNUNET_break (0);
return NULL;
}
@@ -525,15 +604,88 @@ tcp_address_to_string (void *cls, const void *addr, size_t addrlen)
}
+/**
+ * Function called to convert a string address to
+ * a binary address.
+ *
+ * @param cls closure ('struct Plugin*')
+ * @param addr string address
+ * @param addrlen length of the address
+ * @param buf location to store the buffer
+ * @param added location to store the number of bytes in the buffer.
+ * If the function returns GNUNET_SYSERR, its contents are undefined.
+ * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ */
+static int
+tcp_string_to_address (void *cls, const char *addr, uint16_t addrlen,
+ void **buf, size_t *added)
+{
+ struct sockaddr_storage socket_address;
+
+ if ((NULL == addr) || (addrlen == 0))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if ('\0' != addr[addrlen - 1])
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (strlen (addr) != addrlen - 1)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_to_address_ip (addr, strlen (addr),
+ &socket_address))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ switch (socket_address.ss_family)
+ {
+ case AF_INET:
+ {
+ struct IPv4TcpAddress *t4;
+ struct sockaddr_in *in4 = (struct sockaddr_in *) &socket_address;
+
+ t4 = GNUNET_malloc (sizeof (struct IPv4TcpAddress));
+ t4->ipv4_addr = in4->sin_addr.s_addr;
+ t4->t4_port = in4->sin_port;
+ *buf = t4;
+ *added = sizeof (struct IPv4TcpAddress);
+ return GNUNET_OK;
+ }
+ case AF_INET6:
+ {
+ struct IPv6TcpAddress *t6;
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &socket_address;
+ t6 = GNUNET_malloc (sizeof (struct IPv6TcpAddress));
+ t6->ipv6_addr = in6->sin6_addr;
+ t6->t6_port = in6->sin6_port;
+ *buf = t6;
+ *added = sizeof (struct IPv6TcpAddress);
+ return GNUNET_OK;
+ }
+ default:
+ return GNUNET_SYSERR;
+ }
+}
+
+
struct SessionClientCtx
{
const struct GNUNET_SERVER_Client *client;
struct Session *ret;
};
-int session_lookup_by_client_it (void *cls,
- const GNUNET_HashCode * key,
- void *value)
+
+static int
+session_lookup_by_client_it (void *cls,
+ const GNUNET_HashCode * key,
+ void *value)
{
struct SessionClientCtx *sc_ctx = cls;
struct Session *s = value;
@@ -546,6 +698,7 @@ int session_lookup_by_client_it (void *cls,
return GNUNET_YES;
}
+
/**
* Find the session handle for the given client.
*
@@ -555,14 +708,13 @@ int session_lookup_by_client_it (void *cls,
*/
static struct Session *
lookup_session_by_client (struct Plugin *plugin,
- const struct GNUNET_SERVER_Client *client)
+ const struct GNUNET_SERVER_Client *client)
{
struct SessionClientCtx sc_ctx;
+
sc_ctx.client = client;
sc_ctx.ret = NULL;
-
GNUNET_CONTAINER_multihashmap_iterate (plugin->sessionmap, &session_lookup_by_client_it, &sc_ctx);
-
return sc_ctx.ret;
}
@@ -572,7 +724,7 @@ lookup_session_by_client (struct Plugin *plugin,
*
* @param plugin the plugin
* @param target peer to connect to
- * @param client client to use
+ * @param client client to use, reference counter must have already been increased
* @param is_nat this a NAT session, we should wait for a client to
* connect to us from an address, then assign that to
* the session
@@ -586,15 +738,14 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
struct PendingMessage *pm;
struct WelcomeMessage welcome;
- if (is_nat != GNUNET_YES)
- GNUNET_assert (client != NULL);
+ if (GNUNET_YES != is_nat)
+ GNUNET_assert (NULL != client);
else
- GNUNET_assert (client == NULL);
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Creating new session for peer `%4s'\n",
- GNUNET_i2s (target));
+ GNUNET_assert (NULL == client);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating new session for peer `%4s'\n",
+ GNUNET_i2s (target));
ret = GNUNET_malloc (sizeof (struct Session));
ret->last_activity = GNUNET_TIME_absolute_get ();
ret->plugin = plugin;
@@ -617,10 +768,14 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
pm->message_size, GNUNET_NO);
GNUNET_CONTAINER_DLL_insert (ret->pending_messages_head,
ret->pending_messages_tail, pm);
- if (is_nat != GNUNET_YES)
+ if (GNUNET_YES != is_nat)
+ {
GNUNET_STATISTICS_update (plugin->env->stats,
gettext_noop ("# TCP sessions active"), 1,
GNUNET_NO);
+ }
+ start_session_timeout (ret);
+
return ret;
}
@@ -659,16 +814,14 @@ do_transmit (void *cls, size_t size, void *buf)
char *cbuf;
size_t ret;
- GNUNET_assert (session != NULL);
+ GNUNET_assert (NULL != session);
session->transmit_handle = NULL;
plugin = session->plugin;
- if (buf == NULL)
+ if (NULL == buf)
{
-#if DEBUG_TCP
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Timeout trying to transmit to peer `%4s', discarding message queue.\n",
- GNUNET_i2s (&session->target));
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Timeout trying to transmit to peer `%4s', discarding message queue.\n",
+ GNUNET_i2s (&session->target));
/* timeout; cancel all messages that have already expired */
hd = NULL;
tl = NULL;
@@ -679,11 +832,9 @@ do_transmit (void *cls, size_t size, void *buf)
{
GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
session->pending_messages_tail, pos);
-#if DEBUG_TCP
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Failed to transmit %u byte message to `%4s'.\n",
- pos->message_size, GNUNET_i2s (&session->target));
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Failed to transmit %u byte message to `%4s'.\n",
+ pos->message_size, GNUNET_i2s (&session->target));
ret += pos->message_size;
GNUNET_CONTAINER_DLL_insert_after (hd, tl, tl, pos);
}
@@ -722,9 +873,9 @@ do_transmit (void *cls, size_t size, void *buf)
GNUNET_CONTAINER_DLL_remove (session->pending_messages_head,
session->pending_messages_tail, pos);
GNUNET_assert (size >= pos->message_size);
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Transmitting message of type %u\n",
- ntohs (((struct GNUNET_MessageHeader *) pos->msg)->type));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Transmitting message of type %u\n",
+ ntohs (((struct GNUNET_MessageHeader *) pos->msg)->type));
/* FIXME: this memcpy can be up to 7% of our total runtime */
memcpy (cbuf, pos->msg, pos->message_size);
cbuf += pos->message_size;
@@ -749,10 +900,8 @@ do_transmit (void *cls, size_t size, void *buf)
}
GNUNET_assert (hd == NULL);
GNUNET_assert (tl == NULL);
-#if DEBUG_TCP > 1
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", "Transmitting %u bytes\n",
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u bytes\n",
ret);
-#endif
GNUNET_STATISTICS_update (plugin->env->stats,
gettext_noop ("# bytes currently in TCP buffers"),
-(int64_t) ret, GNUNET_NO);
@@ -801,31 +950,44 @@ disconnect_session (struct Session *session)
struct PendingMessage *pm;
struct Plugin * plugin = session->plugin;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Disconnecting session %p for peer `%s' address `%s'\n",
- session,
- GNUNET_i2s (&session->target),
- tcp_address_to_string(NULL, session->addr, session->addrlen));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Disconnecting session of peer `%s' address `%s'\n",
+ GNUNET_i2s (&session->target),
+ tcp_address_to_string (NULL, session->addr, session->addrlen));
- GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(plugin->sessionmap, &session->target.hashPubKey, session));
+ stop_session_timeout (session);
+
+ if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (plugin->sessionmap, &session->target.hashPubKey, session))
+ {
+ GNUNET_STATISTICS_update (session->plugin->env->stats,
+ gettext_noop ("# TCP sessions active"), -1,
+ GNUNET_NO);
+ dec_sessions (plugin, session, __LINE__);
+ }
+ else GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (plugin->nat_wait_conns, &session->target.hashPubKey, session));
/* clean up state */
if (session->transmit_handle != NULL)
{
- GNUNET_CONNECTION_notify_transmit_ready_cancel (session->transmit_handle);
+ GNUNET_SERVER_notify_transmit_ready_cancel (session->transmit_handle);
session->transmit_handle = NULL;
}
session->plugin->env->session_end (session->plugin->env->cls,
&session->target, session);
+
+ if (GNUNET_SCHEDULER_NO_TASK != session->nat_connection_timeout)
+ {
+ GNUNET_SCHEDULER_cancel (session->nat_connection_timeout);
+ session->nat_connection_timeout = GNUNET_SCHEDULER_NO_TASK;
+ }
+
while (NULL != (pm = session->pending_messages_head))
{
-#if DEBUG_TCP
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- pm->transmit_cont !=
- NULL ? "Could not deliver message to `%4s'.\n" :
- "Could not deliver message to `%4s', notifying.\n",
- GNUNET_i2s (&session->target));
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ pm->transmit_cont !=
+ NULL ? "Could not deliver message to `%4s'.\n" :
+ "Could not deliver message to `%4s', notifying.\n",
+ GNUNET_i2s (&session->target));
GNUNET_STATISTICS_update (session->plugin->env->stats,
gettext_noop ("# bytes currently in TCP buffers"),
-(int64_t) pm->message_size, GNUNET_NO);
@@ -840,21 +1002,18 @@ disconnect_session (struct Session *session)
GNUNET_SYSERR);
GNUNET_free (pm);
}
- GNUNET_break (session->client != NULL);
if (session->receive_delay_task != GNUNET_SCHEDULER_NO_TASK)
{
GNUNET_SCHEDULER_cancel (session->receive_delay_task);
- if (session->client != NULL)
+ if (NULL != session->client)
GNUNET_SERVER_receive_done (session->client, GNUNET_SYSERR);
}
- if (session->client != NULL)
+ if (NULL != session->client)
{
+ GNUNET_SERVER_client_disconnect (session->client);
GNUNET_SERVER_client_drop (session->client);
session->client = NULL;
}
- GNUNET_STATISTICS_update (session->plugin->env->stats,
- gettext_noop ("# TCP sessions active"), -1,
- GNUNET_NO);
GNUNET_free_non_null (session->addr);
GNUNET_assert (NULL == session->transmit_handle);
GNUNET_free (session);
@@ -899,15 +1058,9 @@ tcp_plugin_send (void *cls,
struct Plugin * plugin = cls;
struct PendingMessage *pm;
- GNUNET_assert (plugin != NULL);
- GNUNET_assert (session != NULL);
- GNUNET_assert (session->client != NULL);
+ GNUNET_assert (NULL != plugin);
+ GNUNET_assert (NULL != session);
- GNUNET_SERVER_client_set_timeout (session->client,
- GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
- GNUNET_STATISTICS_update (plugin->env->stats,
- gettext_noop ("# bytes currently in TCP buffers"),
- msgbuf_size, GNUNET_NO);
/* create new message entry */
pm = GNUNET_malloc (sizeof (struct PendingMessage) + msgbuf_size);
pm->msg = (const char *) &pm[1];
@@ -917,40 +1070,79 @@ tcp_plugin_send (void *cls,
pm->transmit_cont = cont;
pm->transmit_cont_cls = cont_cls;
- /* append pm to pending_messages list */
- GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head,
- session->pending_messages_tail, pm);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Asked to transmit %u bytes to `%s', added message to list.\n",
+ msgbuf_size, GNUNET_i2s (&session->target));
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Asked to transmit %u bytes to `%s', added message to list.\n",
- msgbuf_size, GNUNET_i2s (&session->target));
+ reschedule_session_timeout (session);
- process_pending_messages (session);
- return msgbuf_size;
+ if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains_value(plugin->sessionmap, &session->target.hashPubKey, session))
+ {
+ GNUNET_assert (session->client != NULL);
+
+ GNUNET_SERVER_client_set_timeout (session->client,
+ GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+ GNUNET_STATISTICS_update (plugin->env->stats,
+ gettext_noop ("# bytes currently in TCP buffers"),
+ msgbuf_size, GNUNET_NO);
+
+ /* append pm to pending_messages list */
+ GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head,
+ session->pending_messages_tail, pm);
+
+ process_pending_messages (session);
+ return msgbuf_size;
+ }
+ else if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains_value(plugin->nat_wait_conns, &session->target.hashPubKey, session))
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "This NAT WAIT session for peer `%s' is not yet ready!\n",
+ GNUNET_i2s (&session->target));
+
+ GNUNET_STATISTICS_update (plugin->env->stats,
+ gettext_noop ("# bytes currently in TCP buffers"),
+ msgbuf_size, GNUNET_NO);
+
+ /* append pm to pending_messages list */
+ GNUNET_CONTAINER_DLL_insert_tail (session->pending_messages_head,
+ session->pending_messages_tail, pm);
+ return msgbuf_size;
+ }
+ else
+ {
+ if (NULL != cont)
+ cont (cont_cls, &session->target, GNUNET_SYSERR);
+ GNUNET_break (0);
+ GNUNET_free (pm);
+ return GNUNET_SYSERR; /* session does not exist here */
+ }
}
+
struct SessionItCtx
{
- void * addr;
+ void *addr;
size_t addrlen;
- struct Session * result;
+ struct Session *result;
};
-int session_lookup_it (void *cls,
- const GNUNET_HashCode * key,
- void *value)
+
+static int
+session_lookup_it (void *cls,
+ const GNUNET_HashCode *key,
+ void *value)
{
struct SessionItCtx * si_ctx = cls;
struct Session * session = value;
#if 0
char * a1 = strdup (tcp_address_to_string(NULL, session->addr, session->addrlen));
char * a2 = strdup (tcp_address_to_string(NULL, si_ctx->addr, si_ctx->addrlen));
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "tcp",
- "Comparing: %s %u <-> %s %u\n",
- a1,
- session->addrlen,
- a2,
- si_ctx->addrlen);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Comparing: %s %u <-> %s %u\n",
+ a1,
+ session->addrlen,
+ a2,
+ si_ctx->addrlen);
GNUNET_free (a1);
GNUNET_free (a2);
#endif
@@ -965,12 +1157,12 @@ int session_lookup_it (void *cls,
#if 0
a1 = strdup (tcp_address_to_string(NULL, session->addr, session->addrlen));
a2 = strdup (tcp_address_to_string(NULL, si_ctx->addr, si_ctx->addrlen));
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "tcp",
- "Comparing: %s %u <-> %s %u , OK!\n",
- a1,
- session->addrlen,
- a2,
- si_ctx->addrlen);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Comparing: %s %u <-> %s %u , OK!\n",
+ a1,
+ session->addrlen,
+ a2,
+ si_ctx->addrlen);
GNUNET_free (a1);
GNUNET_free (a2);
#endif
@@ -981,6 +1173,21 @@ int session_lookup_it (void *cls,
/**
+ * Task cleaning up a NAT connection attempt after timeout
+ */
+static void
+nat_connect_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct Session *session = cls;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "NAT WAIT connection to `%4s' at `%s' could not be established, removing session\n",
+ GNUNET_i2s (&session->target), tcp_address_to_string(NULL, session->addr, session->addrlen));
+ disconnect_session (session);
+}
+
+
+/**
* Create a new session to transmit data to the target
* This session will used to send data to this peer and the plugin will
* notify us by calling the env->session_end function
@@ -991,11 +1198,10 @@ int session_lookup_it (void *cls,
*/
static struct Session *
tcp_plugin_get_session (void *cls,
- const struct GNUNET_HELLO_Address *address)
+ const struct GNUNET_HELLO_Address *address)
{
struct Plugin * plugin = cls;
struct Session * session = NULL;
-
int af;
const void *sb;
size_t sbs;
@@ -1006,20 +1212,19 @@ tcp_plugin_get_session (void *cls,
const struct IPv6TcpAddress *t6;
struct GNUNET_ATS_Information ats;
unsigned int is_natd = GNUNET_NO;
- size_t addrlen = 0;
+ size_t addrlen;
GNUNET_assert (plugin != NULL);
GNUNET_assert (address != NULL);
-
addrlen = address->address_length;
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Trying to get session for `%s' address length %i\n",
- tcp_address_to_string(NULL, address->address, address->address_length),
- addrlen);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to get session for `%s' address of peer `%s'\n",
+ tcp_address_to_string(NULL, address->address, address->address_length),
+ GNUNET_i2s (&address->peer));
/* look for existing session */
- if (GNUNET_CONTAINER_multihashmap_contains(plugin->sessionmap, &address->peer.hashPubKey))
+ if (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_contains(plugin->sessionmap, &address->peer.hashPubKey))
{
struct SessionItCtx si_ctx;
@@ -1032,13 +1237,17 @@ tcp_plugin_get_session (void *cls,
if (si_ctx.result != NULL)
{
session = si_ctx.result;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Found exisiting session for `%s' address `%s' session %p\n",
- GNUNET_i2s (&address->peer),
- tcp_address_to_string(NULL, address->address, address->address_length),
- session);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Found exisiting session for `%s' address `%s' session %p\n",
+ GNUNET_i2s (&address->peer),
+ tcp_address_to_string(NULL, address->address, address->address_length),
+ session);
return session;
}
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Existing sessions did not match address `%s' or peer `%s'\n",
+ tcp_address_to_string(NULL, address->address, address->address_length),
+ GNUNET_i2s (&address->peer));
}
if (addrlen == sizeof (struct IPv6TcpAddress))
@@ -1077,8 +1286,8 @@ tcp_plugin_get_session (void *cls,
}
else
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "tcp",
- _("Address of unexpected length: %u\n"), addrlen);
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Address of unexpected length: %u\n"), addrlen);
GNUNET_break (0);
return NULL;
}
@@ -1111,26 +1320,34 @@ tcp_plugin_get_session (void *cls,
GNUNET_CONTAINER_multihashmap_contains (plugin->nat_wait_conns,
&address->peer.hashPubKey)))
{
-#if DEBUG_TCP_NAT
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- _("Found valid IPv4 NAT address (creating session)!\n"));
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Found valid IPv4 NAT address (creating session)!\n") ;
session = create_session (plugin, &address->peer, NULL, GNUNET_YES);
session->addrlen = 0;
session->addr = NULL;
session->ats_address_network_type = ats.value;
+ session->nat_connection_timeout = GNUNET_SCHEDULER_add_delayed(NAT_TIMEOUT,
+ &nat_connect_timeout,
+ session);
GNUNET_assert (session != NULL);
-
GNUNET_assert (GNUNET_CONTAINER_multihashmap_put
(plugin->nat_wait_conns, &address->peer.hashPubKey, session,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY) == GNUNET_OK);
-#if DEBUG_TCP_NAT
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Created NAT WAIT connection to `%4s' at `%s'\n",
- GNUNET_i2s (&session->target), GNUNET_a2s (sb, sbs));
-#endif
- GNUNET_NAT_run_client (plugin->nat, &a4);
- return session;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Created NAT WAIT connection to `%4s' at `%s'\n",
+ GNUNET_i2s (&session->target), GNUNET_a2s (sb, sbs));
+
+ if (GNUNET_OK == GNUNET_NAT_run_client (plugin->nat, &a4))
+ return session;
+ else
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Running NAT client for `%4s' at `%s' failed\n",
+ GNUNET_i2s (&session->target), GNUNET_a2s (sb, sbs));
+ disconnect_session (session);
+ return NULL;
+ }
}
/* create new outbound session */
@@ -1138,18 +1355,16 @@ tcp_plugin_get_session (void *cls,
sa = GNUNET_CONNECTION_create_from_sockaddr (af, sb, sbs);
if (sa == NULL)
{
-#if DEBUG_TCP
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Failed to create connection to `%4s' at `%s'\n",
- GNUNET_i2s (&session->target), GNUNET_a2s (sb, sbs));
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Failed to create connection to `%4s' at `%s'\n",
+ GNUNET_i2s (&session->target), GNUNET_a2s (sb, sbs));
return NULL;
}
plugin->max_connections--;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Asked to transmit to `%4s', creating fresh session using address `%s'.\n",
- GNUNET_i2s (&address->peer), GNUNET_a2s (sb, sbs));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Asked to transmit to `%4s', creating fresh session using address `%s'.\n",
+ GNUNET_i2s (&address->peer), GNUNET_a2s (sb, sbs));
session = create_session (plugin,
&address->peer,
@@ -1161,13 +1376,12 @@ tcp_plugin_get_session (void *cls,
session->ats_address_network_type = ats.value;
GNUNET_CONTAINER_multihashmap_put(plugin->sessionmap, &address->peer.hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Creating new session for `%s' address `%s' session %p\n",
- GNUNET_i2s (&address->peer),
- tcp_address_to_string(NULL, address->address, address->address_length),
- session);
-
+ inc_sessions (plugin, session, __LINE__);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating new session for `%s' address `%s' session %p\n",
+ GNUNET_i2s (&address->peer),
+ tcp_address_to_string(NULL, address->address, address->address_length),
+ session);
/* Send TCP Welcome */
process_pending_messages (session);
@@ -1175,9 +1389,10 @@ tcp_plugin_get_session (void *cls,
}
-int session_disconnect_it (void *cls,
- const GNUNET_HashCode * key,
- void *value)
+static int
+session_disconnect_it (void *cls,
+ const GNUNET_HashCode * key,
+ void *value)
{
struct Session *session = value;
@@ -1189,25 +1404,6 @@ int session_disconnect_it (void *cls,
return GNUNET_YES;
}
-int session_nat_disconnect_it (void *cls,
- const GNUNET_HashCode * key,
- void *value)
-{
- struct Session *session = value;
-
- if (session != NULL)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Cleaning up pending NAT session for peer `%4s'\n", GNUNET_i2s (&session->target));
- GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (session->plugin->nat_wait_conns, &session->target.hashPubKey, session));
- GNUNET_SERVER_client_drop (session->client);
- GNUNET_SERVER_receive_done (session->client, GNUNET_SYSERR);
- GNUNET_free (session);
- }
-
- return GNUNET_YES;
-}
-
/**
* Function that can be called to force a disconnect from the
@@ -1229,23 +1425,11 @@ static void
tcp_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
{
struct Plugin *plugin = cls;
- struct Session *nat_session = NULL;
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Disconnecting peer `%4s'\n", GNUNET_i2s (target));
- GNUNET_CONTAINER_multihashmap_get_multiple (plugin->sessionmap, &target->hashPubKey, session_disconnect_it, plugin);
-
- nat_session = GNUNET_CONTAINER_multihashmap_get(plugin->nat_wait_conns, &target->hashPubKey);
- if (nat_session != NULL)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Cleaning up pending NAT session for peer `%4s'\n", GNUNET_i2s (target));
- GNUNET_assert (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (plugin->nat_wait_conns, &target->hashPubKey, nat_session));
- GNUNET_SERVER_client_drop (nat_session->client);
- GNUNET_SERVER_receive_done (nat_session->client, GNUNET_SYSERR);
- GNUNET_free (nat_session);
- }
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Disconnecting peer `%4s'\n", GNUNET_i2s (target));
+ GNUNET_CONTAINER_multihashmap_get_multiple (plugin->sessionmap, &target->hashPubKey, &session_disconnect_it, plugin);
+ GNUNET_CONTAINER_multihashmap_get_multiple (plugin->nat_wait_conns, &target->hashPubKey, &session_disconnect_it, plugin);
}
@@ -1268,6 +1452,8 @@ struct PrettyPrinterContext
* Port to add after the IP address.
*/
uint16_t port;
+
+ int ipv6;
};
@@ -1289,7 +1475,10 @@ append_port (void *cls, const char *hostname)
GNUNET_free (ppc);
return;
}
- GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
+ if (GNUNET_YES == ppc->ipv6)
+ GNUNET_asprintf (&ret, "[%s]:%d", hostname, ppc->port);
+ else
+ GNUNET_asprintf (&ret, "%s:%d", hostname, ppc->port);
ppc->asc (ppc->asc_cls, ret);
GNUNET_free (ret);
}
@@ -1348,6 +1537,12 @@ tcp_plugin_address_pretty_printer (void *cls, const char *type,
sb = &a4;
sbs = sizeof (a4);
}
+ else if (0 == addrlen)
+ {
+ asc (asc_cls, "<inbound connection>");
+ asc (asc_cls, NULL);
+ return;
+ }
else
{
/* invalid address */
@@ -1356,6 +1551,10 @@ tcp_plugin_address_pretty_printer (void *cls, const char *type,
return;
}
ppc = GNUNET_malloc (sizeof (struct PrettyPrinterContext));
+ if (addrlen == sizeof (struct IPv6TcpAddress))
+ ppc->ipv6 = GNUNET_YES;
+ else
+ ppc->ipv6 = GNUNET_NO;
ppc->asc = asc;
ppc->asc_cls = asc_cls;
ppc->port = port;
@@ -1462,7 +1661,7 @@ handle_tcp_nat_probe (void *cls, struct GNUNET_SERVER_Client *client,
const struct sockaddr_in *s4;
const struct sockaddr_in6 *s6;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", "received NAT probe\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "received NAT probe\n");
/* We have received a TCP NAT probe, meaning we (hopefully) initiated
* a connection to this peer by running gnunet-nat-client. This peer
@@ -1493,36 +1692,39 @@ handle_tcp_nat_probe (void *cls, struct GNUNET_SERVER_Client *client,
clientIdentity.hashPubKey);
if (session == NULL)
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Did NOT find session for NAT probe!\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Did NOT find session for NAT probe!\n");
GNUNET_SERVER_receive_done (client, GNUNET_OK);
return;
}
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Found session for NAT probe!\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Found session for NAT probe!\n");
+
+ if (session->nat_connection_timeout != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (session->nat_connection_timeout);
+ session->nat_connection_timeout = GNUNET_SCHEDULER_NO_TASK;
+ }
- GNUNET_assert (GNUNET_CONTAINER_multihashmap_remove
- (plugin->nat_wait_conns,
- &tcp_nat_probe->clientIdentity.hashPubKey,
- session) == GNUNET_YES);
if (GNUNET_OK != GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
{
GNUNET_break (0);
- GNUNET_free (session);
- GNUNET_SERVER_receive_done (client, GNUNET_OK);
+ GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ disconnect_session (session);
return;
}
-
- GNUNET_SERVER_client_keep (client);
- session->client = client;
+ GNUNET_assert (GNUNET_CONTAINER_multihashmap_remove
+ (plugin->nat_wait_conns,
+ &tcp_nat_probe->clientIdentity.hashPubKey,
+ session) == GNUNET_YES);
+ GNUNET_CONTAINER_multihashmap_put(plugin->sessionmap,
+ &session->target.hashPubKey, session,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
session->last_activity = GNUNET_TIME_absolute_get ();
session->inbound = GNUNET_NO;
-
-#if DEBUG_TCP_NAT
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Found address `%s' for incoming connection\n",
- GNUNET_a2s (vaddr, alen));
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Found address `%s' for incoming connection\n",
+ GNUNET_a2s (vaddr, alen));
switch (((const struct sockaddr *) vaddr)->sa_family)
{
case AF_INET:
@@ -1543,20 +1745,18 @@ handle_tcp_nat_probe (void *cls, struct GNUNET_SERVER_Client *client,
break;
default:
GNUNET_break_op (0);
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Bad address for incoming connection!\n");
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Bad address for incoming connection!\n");
GNUNET_free (vaddr);
-
- GNUNET_SERVER_client_drop (client);
- GNUNET_free (session);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ disconnect_session (session);
return;
}
GNUNET_free (vaddr);
-
- GNUNET_CONTAINER_multihashmap_put(plugin->sessionmap, &session->target.hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-
+ GNUNET_break (NULL == session->client);
+ GNUNET_SERVER_client_keep (client);
+ session->client = client;
+ inc_sessions (plugin, session, __LINE__);
GNUNET_STATISTICS_update (plugin->env->stats,
gettext_noop ("# TCP sessions active"), 1,
GNUNET_NO);
@@ -1595,23 +1795,21 @@ handle_tcp_welcome (void *cls, struct GNUNET_SERVER_Client *client,
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Received %s message from `%4s'\n", "WELCOME",
- GNUNET_i2s (&wm->clientIdentity));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received %s message from `%4s'\n", "WELCOME",
+ GNUNET_i2s (&wm->clientIdentity));
GNUNET_STATISTICS_update (plugin->env->stats,
gettext_noop ("# TCP WELCOME messages received"), 1,
GNUNET_NO);
-
session = lookup_session_by_client (plugin, client);
if (session != NULL)
{
if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Found existing session %p for peer `%s'\n",
- session,
- GNUNET_a2s (vaddr, alen));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Found existing session %p for peer `%s'\n",
+ session,
+ GNUNET_a2s (vaddr, alen));
GNUNET_free (vaddr);
}
}
@@ -1620,7 +1818,6 @@ handle_tcp_welcome (void *cls, struct GNUNET_SERVER_Client *client,
GNUNET_SERVER_client_keep (client);
session = create_session (plugin, &wm->clientIdentity, client, GNUNET_NO);
session->inbound = GNUNET_YES;
-
if (GNUNET_OK == GNUNET_SERVER_client_get_address (client, &vaddr, &alen))
{
if (alen == sizeof (struct sockaddr_in))
@@ -1650,12 +1847,11 @@ handle_tcp_welcome (void *cls, struct GNUNET_SERVER_Client *client,
}
else
{
-#if DEBUG_TCP
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Did not obtain TCP socket address for incoming connection\n");
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Did not obtain TCP socket address for incoming connection\n");
}
GNUNET_CONTAINER_multihashmap_put(plugin->sessionmap, &wm->clientIdentity.hashPubKey, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ inc_sessions (plugin, session, __LINE__);
}
if (session->expecting_welcome != GNUNET_YES)
@@ -1695,6 +1891,8 @@ delayed_done (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
session->plugin->env->receive (session->plugin->env->cls,
&session->target, NULL, &ats, 0, session,
NULL, 0);
+ reschedule_session_timeout (session);
+
if (delay.rel_value == 0)
GNUNET_SERVER_receive_done (session->client, GNUNET_OK);
else
@@ -1732,21 +1930,40 @@ handle_tcp_data (void *cls, struct GNUNET_SERVER_Client *client,
if (NULL == session)
{
/* No inbound session found */
+ void *vaddr;
+ size_t alen;
+
+ GNUNET_SERVER_client_get_address (client, &vaddr, &alen);
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Received unexpected %u bytes of type %u from `%s'\n",
+ (unsigned int) ntohs (message->size),
+ (unsigned int) ntohs (message->type),
+ GNUNET_a2s(vaddr, alen));
GNUNET_break_op (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ GNUNET_free_non_null(vaddr);
return;
}
else if (GNUNET_YES == session->expecting_welcome)
{
/* Session is expecting WELCOME message */
+ void *vaddr;
+ size_t alen;
+
+ GNUNET_SERVER_client_get_address (client, &vaddr, &alen);
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "Received unexpected %u bytes of type %u from `%s'\n",
+ (unsigned int) ntohs (message->size),
+ (unsigned int) ntohs (message->type),
+ GNUNET_a2s(vaddr, alen));
GNUNET_break_op (0);
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ GNUNET_free_non_null(vaddr);
return;
}
session->last_activity = GNUNET_TIME_absolute_get ();
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
"Passing %u bytes of type %u from `%4s' to transport service.\n",
(unsigned int) ntohs (message->size),
(unsigned int) ntohs (message->type),
@@ -1763,6 +1980,10 @@ handle_tcp_data (void *cls, struct GNUNET_SERVER_Client *client,
distance[1].value = session->ats_address_network_type;
GNUNET_break (ntohl(session->ats_address_network_type) != GNUNET_ATS_NET_UNSPECIFIED);
+ GNUNET_assert (GNUNET_CONTAINER_multihashmap_contains_value (plugin->sessionmap,
+ &session->target.hashPubKey,
+ session));
+
delay = plugin->env->receive (plugin->env->cls,
&session->target,
message,
@@ -1770,18 +1991,19 @@ handle_tcp_data (void *cls, struct GNUNET_SERVER_Client *client,
1, session,
(GNUNET_YES == session->inbound) ? NULL : session->addr,
(GNUNET_YES == session->inbound) ? 0 : session->addrlen);
+
+ reschedule_session_timeout (session);
+
if (delay.rel_value == 0)
{
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
else
{
-#if DEBUG_TCP
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Throttling receiving from `%s' for %llu ms\n",
- GNUNET_i2s (&session->target),
- (unsigned long long) delay.rel_value);
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Throttling receiving from `%s' for %llu ms\n",
+ GNUNET_i2s (&session->target),
+ (unsigned long long) delay.rel_value);
GNUNET_SERVER_disable_receive_done_warning (client);
session->receive_delay_task =
GNUNET_SCHEDULER_add_delayed (delay, &delayed_done, session);
@@ -1808,16 +2030,14 @@ disconnect_notify (void *cls, struct GNUNET_SERVER_Client *client)
session = lookup_session_by_client (plugin, client);
if (session == NULL)
return; /* unknown, nothing to do */
-#if DEBUG_TCP
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp",
- "Destroying session of `%4s' with %s due to network-level disconnect.\n",
- GNUNET_i2s (&session->target),
- (session->addr !=
- NULL) ? tcp_address_to_string (session->plugin,
- session->addr,
- session->addrlen) :
- "*");
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Destroying session of `%4s' with %s due to network-level disconnect.\n",
+ GNUNET_i2s (&session->target),
+ (session->addr !=
+ NULL) ? tcp_address_to_string (session->plugin,
+ session->addr,
+ session->addrlen) :
+ "*");
GNUNET_STATISTICS_update (session->plugin->env->stats,
gettext_noop
("# network-level TCP disconnect events"), 1,
@@ -1846,7 +2066,7 @@ notify_send_probe (void *cls, size_t size, void *buf)
tcp_probe_ctx);
if (buf == NULL)
{
- GNUNET_CONNECTION_destroy (tcp_probe_ctx->sock, GNUNET_NO);
+ GNUNET_CONNECTION_destroy (tcp_probe_ctx->sock);
GNUNET_free (tcp_probe_ctx);
return 0;
}
@@ -1913,6 +2133,91 @@ try_connection_reversal (void *cls, const struct sockaddr *addr,
/**
+ * Session was idle, so disconnect it
+ */
+static void
+session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_assert (NULL != cls);
+ struct Session *s = cls;
+
+ s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Session %p was idle for %llu, disconnecting\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+ /* call session destroy function */
+ disconnect_session(s);
+}
+
+
+/**
+ * Start session timeout
+ */
+static void
+start_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task);
+ s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+ &session_timeout,
+ s);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Timeout for session %p set to %llu\n",
+ s,
+ GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+}
+
+
+/**
+ * Increment session timeout due to activity
+ */
+static void
+reschedule_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+ if (GNUNET_SCHEDULER_NO_TASK == s->timeout_task)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Timeout for peer `%s' %s not scheduled\n",
+ GNUNET_i2s (&s->target),
+ tcp_address_to_string(NULL, s->addr, s->addrlen));
+ return;
+ }
+ GNUNET_SCHEDULER_cancel (s->timeout_task);
+ s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+ &session_timeout,
+ s);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout rescheduled for session %p set to %llu\n",
+ s,
+ (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+}
+
+
+/**
+ * Cancel timeout
+ */
+static void
+stop_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+ if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task)
+ {
+ GNUNET_SCHEDULER_cancel (s->timeout_task);
+ s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Timeout rescheduled for session %p canceled\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Timeout for session %p was not active\n",
+ s);
+ }
+}
+
+
+/**
* Entry point for the plugin.
*
* @param cls closure, the 'struct GNUNET_TRANSPORT_PluginEnvironment*'
@@ -1942,6 +2247,18 @@ libgnunet_plugin_transport_tcp_init (void *cls)
struct sockaddr **addrs;
socklen_t *addrlens;
+ if (NULL == env->receive)
+ {
+ /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
+ initialze the plugin or the API */
+ api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
+ api->cls = NULL;
+ api->address_pretty_printer = &tcp_plugin_address_pretty_printer;
+ api->address_to_string = &tcp_address_to_string;
+ api->string_to_address = &tcp_string_to_address;
+ return api;
+ }
+
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-tcp",
"MAX_CONNECTIONS",
@@ -1957,10 +2274,10 @@ libgnunet_plugin_transport_tcp_init (void *cls)
"ADVERTISED-PORT", &aport)) &&
(aport > 65535)))
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "tcp",
- _
- ("Require valid port number for service `%s' in configuration!\n"),
- "transport-tcp");
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _
+ ("Require valid port number for service `%s' in configuration!\n"),
+ "transport-tcp");
return NULL;
}
if (aport == 0)
@@ -1969,19 +2286,17 @@ libgnunet_plugin_transport_tcp_init (void *cls)
aport = 0;
if (bport != 0)
{
- service = GNUNET_SERVICE_start ("transport-tcp", env->cfg);
+ service = GNUNET_SERVICE_start ("transport-tcp", env->cfg, GNUNET_SERVICE_OPTION_NONE);
if (service == NULL)
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "tcp",
- _("Failed to start service.\n"));
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ _("Failed to start service.\n"));
return NULL;
}
}
else
service = NULL;
-
-
plugin = GNUNET_malloc (sizeof (struct Plugin));
plugin->sessionmap = GNUNET_CONTAINER_multihashmap_create(max_connections);
plugin->max_connections = max_connections;
@@ -2024,6 +2339,7 @@ libgnunet_plugin_transport_tcp_init (void *cls)
api->address_pretty_printer = &tcp_plugin_address_pretty_printer;
api->check_address = &tcp_plugin_check_address;
api->address_to_string = &tcp_address_to_string;
+ api->string_to_address = &tcp_string_to_address;
plugin->service = service;
if (service != NULL)
{
@@ -2035,9 +2351,9 @@ libgnunet_plugin_transport_tcp_init (void *cls)
GNUNET_CONFIGURATION_get_value_time (env->cfg, "transport-tcp",
"TIMEOUT", &idle_timeout))
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "tcp",
- _("Failed to find option %s in section %s!\n"),
- "TIMEOUT", "transport-tcp");
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Failed to find option %s in section %s!\n"),
+ "TIMEOUT", "transport-tcp");
if (plugin->nat != NULL)
GNUNET_NAT_unregister (plugin->nat);
GNUNET_free (plugin);
@@ -2058,17 +2374,21 @@ libgnunet_plugin_transport_tcp_init (void *cls)
GNUNET_SERVER_disconnect_notify (plugin->server, &disconnect_notify, plugin);
plugin->nat_wait_conns = GNUNET_CONTAINER_multihashmap_create (16);
if (bport != 0)
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "tcp",
- _("TCP transport listening on port %llu\n"), bport);
+ LOG (GNUNET_ERROR_TYPE_INFO,
+ _("TCP transport listening on port %llu\n"), bport);
else
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "tcp",
- _
- ("TCP transport not listening on any port (client only)\n"));
+ LOG (GNUNET_ERROR_TYPE_INFO,
+ _
+ ("TCP transport not listening on any port (client only)\n"));
if (aport != bport)
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, "tcp",
+ LOG (GNUNET_ERROR_TYPE_INFO,
_
("TCP transport advertises itself as being on port %llu\n"),
aport);
+ /* Initially set connections to 0 */
+ GNUNET_STATISTICS_set(plugin->env->stats,
+ gettext_noop ("# TCP sessions active"), 0,
+ GNUNET_NO);
return api;
}
@@ -2083,13 +2403,17 @@ libgnunet_plugin_transport_tcp_done (void *cls)
struct Plugin *plugin = api->cls;
struct TCPProbeContext *tcp_probe;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "tcp", "Shutting down TCP plugin\n");
-
+ if (NULL == plugin)
+ {
+ GNUNET_free (api);
+ return NULL;
+ }
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down TCP plugin\n");
/* Removing leftover sessions */
GNUNET_CONTAINER_multihashmap_iterate(plugin->sessionmap, &session_disconnect_it, NULL);
/* Removing leftover NAT sessions */
- GNUNET_CONTAINER_multihashmap_iterate(plugin->nat_wait_conns, &session_nat_disconnect_it, NULL);
+ GNUNET_CONTAINER_multihashmap_iterate(plugin->nat_wait_conns, &session_disconnect_it, NULL);
if (plugin->service != NULL)
GNUNET_SERVICE_stop (plugin->service);
@@ -2102,7 +2426,7 @@ libgnunet_plugin_transport_tcp_done (void *cls)
{
GNUNET_CONTAINER_DLL_remove (plugin->probe_head, plugin->probe_tail,
tcp_probe);
- GNUNET_CONNECTION_destroy (tcp_probe->sock, GNUNET_NO);
+ GNUNET_CONNECTION_destroy (tcp_probe->sock);
GNUNET_free (tcp_probe);
}
GNUNET_CONTAINER_multihashmap_destroy (plugin->nat_wait_conns);
diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c
index 7141563..c5a4c7b 100644
--- a/src/transport/plugin_transport_udp.c
+++ b/src/transport/plugin_transport_udp.c
@@ -85,6 +85,7 @@ struct PrettyPrinterContext
uint16_t port;
};
+
struct Session
{
/**
@@ -92,13 +93,13 @@ struct Session
*/
struct GNUNET_PeerIdentity target;
+ struct FragmentationContext * frag_ctx;
+
/**
* Address of the other peer
*/
const struct sockaddr *sock_addr;
- size_t addrlen;
-
/**
* Desired delay for next sending we send to other peer
*/
@@ -110,14 +111,23 @@ struct Session
struct GNUNET_TIME_Absolute flow_delay_from_other_peer;
/**
+ * Session timeout task
+ */
+ GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+ /**
* expected delay for ACKs
*/
struct GNUNET_TIME_Relative last_expected_delay;
-
struct GNUNET_ATS_Information ats;
- struct FragmentationContext * frag_ctx;
+ size_t addrlen;
+
+
+ unsigned int rc;
+
+ int in_destroy;
};
@@ -143,12 +153,12 @@ struct SourceInformation
*/
const void *arg;
+ struct Session *session;
/**
* Number of bytes in source address.
*/
size_t args;
- struct Session *session;
};
@@ -167,12 +177,13 @@ struct FindReceiveContext
*/
const struct sockaddr *addr;
+ struct Session *session;
+
/**
* Number of bytes in 'addr'.
*/
socklen_t addr_len;
- struct Session *session;
};
@@ -225,9 +236,6 @@ struct FragmentationContext
struct GNUNET_FRAGMENT_Context * frag;
struct Session * session;
- struct GNUNET_TIME_Absolute timeout;
-
-
/**
* Function to call upon completion of the transmission.
*/
@@ -238,6 +246,8 @@ struct FragmentationContext
*/
void *cont_cls;
+ struct GNUNET_TIME_Absolute timeout;
+
size_t bytes_to_send;
};
@@ -248,9 +258,6 @@ struct UDPMessageWrapper
struct UDPMessageWrapper *prev;
struct UDPMessageWrapper *next;
char *udp;
- size_t msg_size;
-
- struct GNUNET_TIME_Absolute timeout;
/**
* Function to call upon completion of the transmission.
@@ -264,6 +271,9 @@ struct UDPMessageWrapper
struct FragmentationContext *frag_ctx;
+ size_t msg_size;
+
+ struct GNUNET_TIME_Absolute timeout;
};
@@ -290,6 +300,12 @@ struct UDP_ACK_Message
};
/**
+ * Encapsulation of all of the state of the plugin.
+ */
+struct Plugin * plugin;
+
+
+/**
* We have been notified that our readset has something to read. We don't
* know which socket needs to be read, so we have to check each one
* Then reschedule this function to be called again once more is available.
@@ -300,6 +316,7 @@ struct UDP_ACK_Message
static void
udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
/**
* We have been notified that our readset has something to read. We don't
* know which socket needs to be read, so we have to check each one
@@ -311,6 +328,27 @@ udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
static void
udp_plugin_select_v6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+/**
+ * Start session timeout
+ */
+static void
+start_session_timeout (struct Session *s);
+
+/**
+ * Increment session timeout due to activity
+ */
+static void
+reschedule_session_timeout (struct Session *s);
+
+/**
+ * Cancel timeout
+ */
+static void
+stop_session_timeout (struct Session *s);
+
+
+
/**
* Function called for a quick conversion of the binary address to
* a numeric address. Note that the caller must not free the
@@ -364,6 +402,77 @@ udp_address_to_string (void *cls, const void *addr, size_t addrlen)
/**
+ * Function called to convert a string address to
+ * a binary address.
+ *
+ * @param cls closure ('struct Plugin*')
+ * @param addr string address
+ * @param addrlen length of the address
+ * @param buf location to store the buffer
+ * @param added location to store the number of bytes in the buffer.
+ * If the function returns GNUNET_SYSERR, its contents are undefined.
+ * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ */
+static int
+udp_string_to_address (void *cls, const char *addr, uint16_t addrlen,
+ void **buf, size_t *added)
+{
+ struct sockaddr_storage socket_address;
+
+ if ((NULL == addr) || (0 == addrlen))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ if ('\0' != addr[addrlen - 1])
+ {
+ return GNUNET_SYSERR;
+ }
+
+ if (strlen (addr) != addrlen - 1)
+ {
+ return GNUNET_SYSERR;
+ }
+
+ if (GNUNET_OK != GNUNET_STRINGS_to_address_ip (addr, strlen (addr),
+ &socket_address))
+ {
+ return GNUNET_SYSERR;
+ }
+
+ switch (socket_address.ss_family)
+ {
+ case AF_INET:
+ {
+ struct IPv4UdpAddress *u4;
+ struct sockaddr_in *in4 = (struct sockaddr_in *) &socket_address;
+ u4 = GNUNET_malloc (sizeof (struct IPv4UdpAddress));
+ u4->ipv4_addr = in4->sin_addr.s_addr;
+ u4->u4_port = in4->sin_port;
+ *buf = u4;
+ *added = sizeof (struct IPv4UdpAddress);
+ return GNUNET_OK;
+ }
+ case AF_INET6:
+ {
+ struct IPv6UdpAddress *u6;
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) &socket_address;
+ u6 = GNUNET_malloc (sizeof (struct IPv6UdpAddress));
+ u6->ipv6_addr = in6->sin6_addr;
+ u6->u6_port = in6->sin6_port;
+ *buf = u6;
+ *added = sizeof (struct IPv6UdpAddress);
+ return GNUNET_OK;
+ }
+ default:
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+}
+
+
+/**
* Append our port and forward the result.
*
* @param cls a 'struct PrettyPrinterContext'
@@ -446,6 +555,12 @@ udp_plugin_address_pretty_printer (void *cls, const char *type,
sb = &a4;
sbs = sizeof (a4);
}
+ else if (0 == addrlen)
+ {
+ asc (asc_cls, "<inbound connection>");
+ asc (asc_cls, NULL);
+ return;
+ }
else
{
/* invalid address */
@@ -461,6 +576,21 @@ udp_plugin_address_pretty_printer (void *cls, const char *type,
}
+static void
+call_continuation (struct UDPMessageWrapper *udpw, int result)
+{
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Calling continuation for %u byte message to `%s' with result %s\n",
+ udpw->msg_size, GNUNET_i2s (&udpw->session->target),
+ (GNUNET_OK == result) ? "OK" : "SYSERR");
+ if (NULL != udpw->cont)
+ {
+ udpw->cont (udpw->cont_cls, &udpw->session->target,result);
+ }
+
+}
+
+
/**
* Check if the given port is plausible (must be either our listen
* port or our advertised port). If it is neither, we return
@@ -479,7 +609,6 @@ check_port (struct Plugin *plugin, uint16_t in_port)
}
-
/**
* Function that will be called to check if a binary address for this
* plugin is well-formed and corresponds to an address for THIS peer
@@ -539,75 +668,105 @@ udp_plugin_check_address (void *cls, const void *addr, size_t addrlen)
/**
- * Destroy a session, plugin is being unloaded.
+ * Task to free resources associated with a session.
*
- * @param cls unused
- * @param key hash of public key of target peer
- * @param value a 'struct PeerSession*' to clean up
- * @return GNUNET_OK (continue to iterate)
+ * @param s session to free
*/
-static int
-disconnect_and_free_it (void *cls, const GNUNET_HashCode * key, void *value)
+static void
+free_session (struct Session *s)
+{
+ if (s->frag_ctx != NULL)
+ {
+ GNUNET_FRAGMENT_context_destroy(s->frag_ctx->frag);
+ GNUNET_free (s->frag_ctx);
+ s->frag_ctx = NULL;
+ }
+ GNUNET_free (s);
+}
+
+
+/**
+ * Functions with this signature are called whenever we need
+ * to close a session due to a disconnect or failure to
+ * establish a connection.
+ *
+ * @param s session to close down
+ */
+static void
+disconnect_session (struct Session *s)
{
- struct Plugin *plugin = cls;
- struct Session *s = value;
struct UDPMessageWrapper *udpw;
struct UDPMessageWrapper *next;
-#if DEBUG_UDP
+ GNUNET_assert (GNUNET_YES != s->in_destroy);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Session %p to peer `%s' address ended \n",
s,
GNUNET_i2s (&s->target),
GNUNET_a2s (s->sock_addr, s->addrlen));
-#endif
-
- if (s->frag_ctx != NULL)
- {
- GNUNET_FRAGMENT_context_destroy(s->frag_ctx->frag);
- GNUNET_free (s->frag_ctx);
- s->frag_ctx = NULL;
- }
-
- udpw = plugin->ipv4_queue_head;
- while (udpw != NULL)
+ stop_session_timeout(s);
+ next = plugin->ipv4_queue_head;
+ while (NULL != (udpw = next))
{
next = udpw->next;
if (udpw->session == s)
{
GNUNET_CONTAINER_DLL_remove(plugin->ipv4_queue_head, plugin->ipv4_queue_tail, udpw);
-
- if (udpw->cont != NULL)
- udpw->cont (udpw->cont_cls, &s->target, GNUNET_SYSERR);
+ call_continuation(udpw, GNUNET_SYSERR);
GNUNET_free (udpw);
}
- udpw = next;
}
-
- udpw = plugin->ipv6_queue_head;
- while (udpw != NULL)
+ next = plugin->ipv6_queue_head;
+ while (NULL != (udpw = next))
{
next = udpw->next;
if (udpw->session == s)
{
GNUNET_CONTAINER_DLL_remove(plugin->ipv6_queue_head, plugin->ipv6_queue_tail, udpw);
-
- if (udpw->cont != NULL)
- udpw->cont (udpw->cont_cls, &s->target, GNUNET_SYSERR);
+ call_continuation(udpw, GNUNET_SYSERR);
GNUNET_free (udpw);
}
udpw = next;
}
-
plugin->env->session_end (plugin->env->cls, &s->target, s);
+ if (NULL != s->frag_ctx)
+ {
+ if (NULL != s->frag_ctx->cont)
+ {
+ s->frag_ctx->cont (s->frag_ctx->cont_cls, &s->target, GNUNET_SYSERR);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Calling continuation for fragemented message to `%s' with result SYSERR\n",
+ GNUNET_i2s (&s->target));
+ }
+ }
+
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_remove (plugin->sessions,
&s->target.hashPubKey,
s));
+ GNUNET_STATISTICS_set(plugin->env->stats,
+ "# UDP sessions active",
+ GNUNET_CONTAINER_multihashmap_size(plugin->sessions),
+ GNUNET_NO);
+ if (s->rc > 0)
+ s->in_destroy = GNUNET_YES;
+ else
+ free_session (s);
+}
-
- GNUNET_free (s);
+/**
+ * Destroy a session, plugin is being unloaded.
+ *
+ * @param cls unused
+ * @param key hash of public key of target peer
+ * @param value a 'struct PeerSession*' to clean up
+ * @return GNUNET_OK (continue to iterate)
+ */
+static int
+disconnect_and_free_it (void *cls, const GNUNET_HashCode * key, void *value)
+{
+ disconnect_session(value);
return GNUNET_OK;
}
@@ -626,14 +785,13 @@ udp_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
GNUNET_assert (plugin != NULL);
GNUNET_assert (target != NULL);
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Disconnecting from peer `%s'\n", GNUNET_i2s (target));
-#endif
/* Clean up sessions */
GNUNET_CONTAINER_multihashmap_get_multiple (plugin->sessions, &target->hashPubKey, &disconnect_and_free_it, plugin);
}
+
static struct Session *
create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
const void *addr, size_t addrlen,
@@ -688,20 +846,19 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
GNUNET_break_op (0);
return NULL;
}
-
s->addrlen = len;
s->target = *target;
s->sock_addr = (const struct sockaddr *) &s[1];
- s->flow_delay_for_other_peer = GNUNET_TIME_relative_get_zero();
- s->flow_delay_from_other_peer = GNUNET_TIME_absolute_get_zero();
s->last_expected_delay = GNUNET_TIME_UNIT_SECONDS;
-
+ start_session_timeout(s);
return s;
}
-static int session_cmp_it (void *cls,
- const GNUNET_HashCode * key,
- void *value)
+
+static int
+session_cmp_it (void *cls,
+ const GNUNET_HashCode * key,
+ void *value)
{
struct SessionCompareContext * cctx = cls;
const struct GNUNET_HELLO_Address *address = cctx->addr;
@@ -709,12 +866,9 @@ static int session_cmp_it (void *cls,
socklen_t s_addrlen = s->addrlen;
-#if VERBOSE_UDP
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing address %s <-> %s\n",
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Comparing address %s <-> %s\n",
udp_address_to_string (NULL, (void *) address->address, address->address_length),
GNUNET_a2s (s->sock_addr, s->addrlen));
-#endif
-
if ((address->address_length == sizeof (struct IPv4UdpAddress)) &&
(s_addrlen == sizeof (struct sockaddr_in)))
{
@@ -742,8 +896,6 @@ static int session_cmp_it (void *cls,
return GNUNET_NO;
}
}
-
-
return GNUNET_YES;
}
@@ -799,15 +951,14 @@ udp_plugin_get_session (void *cls,
struct SessionCompareContext cctx;
cctx.addr = address;
cctx.res = NULL;
-#if VERBOSE_UDP
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for existing session for peer `%s' `%s' \n", GNUNET_i2s (&address->peer), udp_address_to_string(NULL, address->address, address->address_length));
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Looking for existing session for peer `%s' `%s' \n",
+ GNUNET_i2s (&address->peer),
+ udp_address_to_string(NULL, address->address, address->address_length));
GNUNET_CONTAINER_multihashmap_get_multiple(plugin->sessions, &address->peer.hashPubKey, session_cmp_it, &cctx);
if (cctx.res != NULL)
{
-#if VERBOSE_UDP
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found existing session %p\n", cctx.res);
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Found existing session %p\n", cctx.res);
return cctx.res;
}
@@ -817,23 +968,28 @@ udp_plugin_get_session (void *cls,
address->address,
address->address_length,
NULL, NULL);
-#if VERBOSE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Creating new session %p for peer `%s' address `%s'\n",
- s,
- GNUNET_i2s(&address->peer),
- udp_address_to_string(NULL,address->address,address->address_length));
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating new session %p for peer `%s' address `%s'\n",
+ s,
+ GNUNET_i2s(&address->peer),
+ udp_address_to_string(NULL,address->address,address->address_length));
GNUNET_assert (GNUNET_OK ==
GNUNET_CONTAINER_multihashmap_put (plugin->sessions,
&s->target.hashPubKey,
s,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
+ GNUNET_STATISTICS_set(plugin->env->stats,
+ "# UDP sessions active",
+ GNUNET_CONTAINER_multihashmap_size(plugin->sessions),
+ GNUNET_NO);
+
return s;
}
-static void enqueue (struct Plugin *plugin, struct UDPMessageWrapper * udpw)
+
+static void
+enqueue (struct Plugin *plugin, struct UDPMessageWrapper * udpw)
{
if (udpw->session->addrlen == sizeof (struct sockaddr_in))
@@ -842,6 +998,26 @@ static void enqueue (struct Plugin *plugin, struct UDPMessageWrapper * udpw)
GNUNET_CONTAINER_DLL_insert(plugin->ipv6_queue_head, plugin->ipv6_queue_tail, udpw);
}
+
+/**
+ * Fragment message was transmitted via UDP, let fragmentation know
+ * to send the next fragment now.
+ *
+ * @param cls the 'struct UDPMessageWrapper' of the fragment
+ * @param target destination peer (ignored)
+ * @param result GNUNET_OK on success (ignored)
+ */
+static void
+send_next_fragment (void *cls,
+ const struct GNUNET_PeerIdentity *target,
+ int result)
+{
+ struct UDPMessageWrapper *udpw = cls;
+
+ GNUNET_FRAGMENT_context_transmission_done (udpw->frag_ctx->frag);
+}
+
+
/**
* Function that is called with messages created by the fragmentation
* module. In the case of the 'proc' callback of the
@@ -858,28 +1034,23 @@ enqueue_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
struct Plugin *plugin = frag_ctx->plugin;
struct UDPMessageWrapper * udpw;
struct Session *s;
-
size_t msg_len = ntohs (msg->size);
-#if VERBOSE_UDP
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Enqueuing fragment with %u bytes %u\n", msg_len , sizeof (struct UDPMessageWrapper));
-#endif
-
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Enqueuing fragment with %u bytes %u\n", msg_len , sizeof (struct UDPMessageWrapper));
udpw = GNUNET_malloc (sizeof (struct UDPMessageWrapper) + msg_len);
udpw->session = frag_ctx->session;
s = udpw->session;
udpw->udp = (char *) &udpw[1];
udpw->msg_size = msg_len;
- udpw->cont = frag_ctx->cont;
- udpw->cont_cls = frag_ctx->cont_cls;
+ udpw->cont = &send_next_fragment;
+ udpw->cont_cls = udpw;
udpw->timeout = frag_ctx->timeout;
udpw->frag_ctx = frag_ctx;
memcpy (udpw->udp, msg, msg_len);
-
enqueue (plugin, udpw);
-
if (s->addrlen == sizeof (struct sockaddr_in))
{
if (plugin->with_v4_ws == GNUNET_NO)
@@ -889,7 +1060,6 @@ enqueue_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
plugin->select_task =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
GNUNET_TIME_UNIT_FOREVER_REL,
plugin->rs_v4,
plugin->ws_v4,
@@ -897,7 +1067,6 @@ enqueue_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
plugin->with_v4_ws = GNUNET_YES;
}
}
-
else if (s->addrlen == sizeof (struct sockaddr_in6))
{
if (plugin->with_v6_ws == GNUNET_NO)
@@ -907,7 +1076,6 @@ enqueue_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
plugin->select_task_v6 =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
GNUNET_TIME_UNIT_FOREVER_REL,
plugin->rs_v6,
plugin->ws_v6,
@@ -915,12 +1083,9 @@ enqueue_fragment (void *cls, const struct GNUNET_MessageHeader *msg)
plugin->with_v6_ws = GNUNET_YES;
}
}
-
}
-
-
/**
* Function that can be used by the transport service to transmit
* a message using the plugin. Note that in the case of a
@@ -958,7 +1123,6 @@ udp_plugin_send (void *cls,
{
struct Plugin *plugin = cls;
size_t mlen = msgbuf_size + sizeof (struct UDPMessage);
-
struct UDPMessageWrapper * udpw;
struct UDPMessage *udp;
char mbuf[mlen];
@@ -967,29 +1131,24 @@ udp_plugin_send (void *cls,
if ((s->addrlen == sizeof (struct sockaddr_in6)) && (plugin->sockv6 == NULL))
return GNUNET_SYSERR;
-
- if ((s->addrlen == sizeof (struct sockaddr_in)) && (plugin->sockv4 == NULL))
- return GNUNET_SYSERR;
-
-
+ if ((s->addrlen == sizeof (struct sockaddr_in)) && (plugin->sockv4 == NULL))
+ return GNUNET_SYSERR;
if (mlen >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
-
if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains_value(plugin->sessions, &s->target.hashPubKey, s))
{
GNUNET_break (0);
return GNUNET_SYSERR;
}
-
LOG (GNUNET_ERROR_TYPE_DEBUG,
"UDP transmits %u-byte message to `%s' using address `%s'\n",
- msgbuf_size,
- GNUNET_i2s (&s->target),
- GNUNET_a2s(s->sock_addr, s->addrlen));
-
+ mlen,
+ GNUNET_i2s (&s->target),
+ GNUNET_a2s(s->sock_addr, s->addrlen));
+
/* Message */
udp = (struct UDPMessage *) mbuf;
udp->header.size = htons (mlen);
@@ -997,6 +1156,7 @@ udp_plugin_send (void *cls,
udp->reserved = htonl (0);
udp->sender = *plugin->env->my_identity;
+ reschedule_session_timeout(s);
if (mlen <= UDP_MTU)
{
udpw = GNUNET_malloc (sizeof (struct UDPMessageWrapper) + mlen);
@@ -1007,7 +1167,6 @@ udp_plugin_send (void *cls,
udpw->cont = cont;
udpw->cont_cls = cont_cls;
udpw->frag_ctx = NULL;
-
memcpy (udpw->udp, udp, sizeof (struct UDPMessage));
memcpy (&udpw->udp[sizeof (struct UDPMessage)], msgbuf, msgbuf_size);
@@ -1037,7 +1196,6 @@ udp_plugin_send (void *cls,
frag_ctx);
s->frag_ctx = frag_ctx;
-
}
if (s->addrlen == sizeof (struct sockaddr_in))
@@ -1049,7 +1207,6 @@ udp_plugin_send (void *cls,
plugin->select_task =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
GNUNET_TIME_UNIT_FOREVER_REL,
plugin->rs_v4,
plugin->ws_v4,
@@ -1057,7 +1214,6 @@ udp_plugin_send (void *cls,
plugin->with_v4_ws = GNUNET_YES;
}
}
-
else if (s->addrlen == sizeof (struct sockaddr_in6))
{
if (plugin->with_v6_ws == GNUNET_NO)
@@ -1067,7 +1223,6 @@ udp_plugin_send (void *cls,
plugin->select_task_v6 =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
GNUNET_TIME_UNIT_FOREVER_REL,
plugin->rs_v6,
plugin->ws_v6,
@@ -1135,7 +1290,7 @@ udp_nat_port_map_callback (void *cls, int add_remove,
* @param client the 'struct SourceInformation'
* @param hdr the actual message
*/
-static void
+static int
process_inbound_tokenized_messages (void *cls, void *client,
const struct GNUNET_MessageHeader *hdr)
{
@@ -1145,20 +1300,23 @@ process_inbound_tokenized_messages (void *cls, void *client,
struct GNUNET_TIME_Relative delay;
GNUNET_assert (si->session != NULL);
+ if (GNUNET_YES == si->session->in_destroy)
+ return GNUNET_OK;
/* setup ATS */
ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
ats[0].value = htonl (1);
ats[1] = si->session->ats;
GNUNET_break (ntohl(ats[1].value) != GNUNET_ATS_NET_UNSPECIFIED);
-
delay = plugin->env->receive (plugin->env->cls,
- &si->sender,
- hdr,
- (const struct GNUNET_ATS_Information *) &ats, 2,
- NULL,
- si->arg,
- si->args);
+ &si->sender,
+ hdr,
+ (const struct GNUNET_ATS_Information *) &ats, 2,
+ NULL,
+ si->arg,
+ si->args);
si->session->flow_delay_for_other_peer = delay;
+ reschedule_session_timeout(si->session);
+ return GNUNET_OK;
}
@@ -1176,7 +1334,7 @@ process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
socklen_t sender_addr_len)
{
struct SourceInformation si;
- struct Session * s = NULL;
+ struct Session * s;
struct IPv4UdpAddress u4;
struct IPv6UdpAddress u6;
const void *arg;
@@ -1215,12 +1373,10 @@ process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
GNUNET_break (0);
return;
}
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received message with %u bytes from peer `%s' at `%s'\n",
(unsigned int) ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
GNUNET_a2s (sender_addr, sender_addr_len));
-#endif
struct GNUNET_HELLO_Address * address = GNUNET_HELLO_address_allocate(&msg->sender, "udp", arg, args);
s = udp_plugin_get_session(plugin, address);
@@ -1231,10 +1387,13 @@ process_udp_message (struct Plugin *plugin, const struct UDPMessage *msg,
si.sender = msg->sender;
si.arg = arg;
si.args = args;
-
+ s->rc++;
GNUNET_SERVER_mst_receive (plugin->mst, &si, (const char *) &msg[1],
ntohs (msg->header.size) -
sizeof (struct UDPMessage), GNUNET_YES, GNUNET_NO);
+ s->rc--;
+ if ( (0 == s->rc) && (GNUNET_YES == s->in_destroy))
+ free_session (s);
}
@@ -1290,14 +1449,17 @@ fragment_msg_proc (void *cls, const struct GNUNET_MessageHeader *msg)
rc->src_addr, rc->addr_len);
}
+
struct LookupContext
{
const struct sockaddr * addr;
- size_t addrlen;
struct Session *res;
+
+ size_t addrlen;
};
+
static int
lookup_session_by_addr_it (void *cls, const GNUNET_HashCode * key, void *value)
{
@@ -1313,6 +1475,7 @@ lookup_session_by_addr_it (void *cls, const GNUNET_HashCode * key, void *value)
return GNUNET_YES;
}
+
/**
* Transmit an acknowledgement.
*
@@ -1324,7 +1487,6 @@ static void
ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
{
struct DefragContext *rc = cls;
-
size_t msize = sizeof (struct UDP_ACK_Message) + ntohs (msg->size);
struct UDP_ACK_Message *udp_ack;
uint32_t delay = 0;
@@ -1340,12 +1502,12 @@ ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
&l_ctx);
s = l_ctx.res;
- GNUNET_assert (s != NULL);
+ if (NULL == s)
+ return;
if (s->flow_delay_for_other_peer.rel_value <= UINT32_MAX)
delay = s->flow_delay_for_other_peer.rel_value;
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Sending ACK to `%s' including delay of %u ms\n",
GNUNET_a2s (rc->src_addr,
@@ -1353,16 +1515,11 @@ ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
AF_INET) ? sizeof (struct sockaddr_in) : sizeof (struct
sockaddr_in6)),
delay);
-#endif
udpw = GNUNET_malloc (sizeof (struct UDPMessageWrapper) + msize);
- udpw->cont = NULL;
- udpw->cont_cls = NULL;
- udpw->frag_ctx = NULL;
udpw->msg_size = msize;
udpw->session = s;
- udpw->timeout = GNUNET_TIME_absolute_get_forever();
+ udpw->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
udpw->udp = (char *)&udpw[1];
-
udp_ack = (struct UDP_ACK_Message *) udpw->udp;
udp_ack->header.size = htons ((uint16_t) msize);
udp_ack->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK);
@@ -1374,10 +1531,11 @@ ack_proc (void *cls, uint32_t id, const struct GNUNET_MessageHeader *msg)
}
-static void read_process_msg (struct Plugin *plugin,
- const struct GNUNET_MessageHeader *msg,
- char *addr,
- socklen_t fromlen)
+static void
+read_process_msg (struct Plugin *plugin,
+ const struct GNUNET_MessageHeader *msg,
+ const char *addr,
+ socklen_t fromlen)
{
if (ntohs (msg->size) < sizeof (struct UDPMessage))
{
@@ -1386,18 +1544,19 @@ static void read_process_msg (struct Plugin *plugin,
}
process_udp_message (plugin, (const struct UDPMessage *) msg,
(const struct sockaddr *) addr, fromlen);
- return;
}
-static void read_process_ack (struct Plugin *plugin,
- const struct GNUNET_MessageHeader *msg,
- char *addr,
- socklen_t fromlen)
+
+static void
+read_process_ack (struct Plugin *plugin,
+ const struct GNUNET_MessageHeader *msg,
+ char *addr,
+ socklen_t fromlen)
{
const struct GNUNET_MessageHeader *ack;
const struct UDP_ACK_Message *udp_ack;
struct LookupContext l_ctx;
- struct Session *s = NULL;
+ struct Session *s;
struct GNUNET_TIME_Relative flow_delay;
if (ntohs (msg->size) <
@@ -1406,9 +1565,7 @@ static void read_process_ack (struct Plugin *plugin,
GNUNET_break_op (0);
return;
}
-
udp_ack = (const struct UDP_ACK_Message *) msg;
-
l_ctx.addr = (const struct sockaddr *) addr;
l_ctx.addrlen = fromlen;
l_ctx.res = NULL;
@@ -1436,35 +1593,33 @@ static void read_process_ack (struct Plugin *plugin,
if (GNUNET_OK != GNUNET_FRAGMENT_process_ack (s->frag_ctx->frag, ack))
{
-#if DEBUG_UDP
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
- (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
- GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "UDP processes %u-byte acknowledgement from `%s' at `%s'\n",
+ (unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
+ GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
return;
}
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG,
"FULL MESSAGE ACKed\n",
(unsigned int) ntohs (msg->size), GNUNET_i2s (&udp_ack->sender),
GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
-#endif
s->last_expected_delay = GNUNET_FRAGMENT_context_destroy (s->frag_ctx->frag);
- struct UDPMessageWrapper * udpw = NULL;
+ struct UDPMessageWrapper * udpw;
+ struct UDPMessageWrapper * tmp;
if (s->addrlen == sizeof (struct sockaddr_in6))
{
udpw = plugin->ipv6_queue_head;
- while (udpw!= NULL)
+ while (NULL != udpw)
{
+ tmp = udpw->next;
if ((udpw->frag_ctx != NULL) && (udpw->frag_ctx == s->frag_ctx))
{
GNUNET_CONTAINER_DLL_remove(plugin->ipv6_queue_head, plugin->ipv6_queue_tail, udpw);
GNUNET_free (udpw);
}
- udpw = udpw->next;
+ udpw = tmp;
}
}
if (s->addrlen == sizeof (struct sockaddr_in))
@@ -1472,43 +1627,46 @@ static void read_process_ack (struct Plugin *plugin,
udpw = plugin->ipv4_queue_head;
while (udpw!= NULL)
{
+ tmp = udpw->next;
if ((udpw->frag_ctx != NULL) && (udpw->frag_ctx == s->frag_ctx))
{
GNUNET_CONTAINER_DLL_remove(plugin->ipv4_queue_head, plugin->ipv4_queue_tail, udpw);
GNUNET_free (udpw);
}
- udpw = udpw->next;
+ udpw = tmp;
}
}
if (s->frag_ctx->cont != NULL)
- s->frag_ctx->cont
- (s->frag_ctx->cont_cls, &udp_ack->sender, GNUNET_OK);
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Calling continuation for fragmented message to `%s' with result %s\n",
+ GNUNET_i2s (&s->target), "OK");
+ s->frag_ctx->cont (s->frag_ctx->cont_cls, &udp_ack->sender, GNUNET_OK);
+ }
+
GNUNET_free (s->frag_ctx);
s->frag_ctx = NULL;
- return;
}
-static void read_process_fragment (struct Plugin *plugin,
- const struct GNUNET_MessageHeader *msg,
- char *addr,
- socklen_t fromlen)
+
+static void
+read_process_fragment (struct Plugin *plugin,
+ const struct GNUNET_MessageHeader *msg,
+ char *addr,
+ socklen_t fromlen)
{
struct DefragContext *d_ctx;
struct GNUNET_TIME_Absolute now;
struct FindReceiveContext frc;
-
frc.rc = NULL;
frc.addr = (const struct sockaddr *) addr;
frc.addr_len = fromlen;
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG, "UDP processes %u-byte fragment from `%s'\n",
(unsigned int) ntohs (msg->size),
GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
-#endif
-
/* Lookup existing receive context for this address */
GNUNET_CONTAINER_heap_iterate (plugin->defrag_ctxs,
&find_receive_context,
@@ -1532,19 +1690,17 @@ static void read_process_fragment (struct Plugin *plugin,
GNUNET_CONTAINER_heap_insert (plugin->defrag_ctxs, d_ctx,
(GNUNET_CONTAINER_HeapCostType)
now.abs_value);
-#if DEBUG_UDP
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Created new defragmentation context for %u-byte fragment from `%s'\n",
- (unsigned int) ntohs (msg->size),
- GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Created new defragmentation context for %u-byte fragment from `%s'\n",
+ (unsigned int) ntohs (msg->size),
+ GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
}
else
{
-#if DEBUG_UDP
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Found existing defragmentation context for %u-byte fragment from `%s'\n",
- (unsigned int) ntohs (msg->size),
- GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Found existing defragmentation context for %u-byte fragment from `%s'\n",
+ (unsigned int) ntohs (msg->size),
+ GNUNET_a2s ((const struct sockaddr *) addr, fromlen));
}
if (GNUNET_OK == GNUNET_DEFRAGMENT_process_fragment (d_ctx->defrag, msg))
@@ -1565,6 +1721,7 @@ static void read_process_fragment (struct Plugin *plugin,
}
}
+
/**
* Read and process a message from the given socket.
*
@@ -1576,7 +1733,7 @@ udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
{
socklen_t fromlen;
char addr[32];
- char buf[65536];
+ char buf[65536] GNUNET_ALIGN;
ssize_t size;
const struct GNUNET_MessageHeader *msg;
@@ -1613,7 +1770,7 @@ udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
return;
case GNUNET_MESSAGE_TYPE_TRANSPORT_UDP_ACK:
- read_process_ack (plugin, msg, addr, fromlen);;
+ read_process_ack (plugin, msg, addr, fromlen);
return;
case GNUNET_MESSAGE_TYPE_FRAGMENT:
@@ -1626,14 +1783,13 @@ udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
}
}
-size_t
+
+static size_t
udp_select_send (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
{
ssize_t sent;
size_t slen;
struct GNUNET_TIME_Absolute max;
- struct GNUNET_TIME_Absolute ;
-
struct UDPMessageWrapper *udpw = NULL;
if (sock == plugin->sockv4)
@@ -1660,25 +1816,21 @@ udp_select_send (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
if (max.abs_value != udpw->timeout.abs_value)
{
/* Message timed out */
-
- if (udpw->cont != NULL)
- udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_SYSERR);
+ call_continuation(udpw, GNUNET_SYSERR);
if (udpw->frag_ctx != NULL)
{
-#if DEBUG_UDP
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fragmented message for peer `%s' with size %u timed out\n",
- GNUNET_i2s(&udpw->session->target), udpw->frag_ctx->bytes_to_send);
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Fragmented message for peer `%s' with size %u timed out\n",
+ GNUNET_i2s(&udpw->session->target), udpw->frag_ctx->bytes_to_send);
udpw->session->last_expected_delay = GNUNET_FRAGMENT_context_destroy(udpw->frag_ctx->frag);
GNUNET_free (udpw->frag_ctx);
udpw->session->frag_ctx = NULL;
}
else
{
-#if DEBUG_UDP
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' with size %u timed out\n",
- GNUNET_i2s(&udpw->session->target), udpw->msg_size);
-#endif
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Message for peer `%s' with size %u timed out\n",
+ GNUNET_i2s(&udpw->session->target), udpw->msg_size);
}
if (sock == plugin->sockv4)
@@ -1700,20 +1852,21 @@ udp_select_send (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
if (delta.rel_value == 0)
{
/* this message is not delayed */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' (%u bytes) is not delayed \n",
- GNUNET_i2s(&udpw->session->target), udpw->msg_size);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Message for peer `%s' (%u bytes) is not delayed \n",
+ GNUNET_i2s(&udpw->session->target), udpw->msg_size);
break;
}
else
{
/* this message is delayed, try next */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message for peer `%s' (%u bytes) is delayed for %llu \n",
- GNUNET_i2s(&udpw->session->target), udpw->msg_size,
- delta);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Message for peer `%s' (%u bytes) is delayed for %llu \n",
+ GNUNET_i2s(&udpw->session->target), udpw->msg_size,
+ delta);
udpw = udpw->next;
}
}
-
}
if (udpw == NULL)
@@ -1726,29 +1879,40 @@ udp_select_send (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
if (GNUNET_SYSERR == sent)
{
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "UDP transmitted %u-byte message to %s (%d: %s)\n",
- (unsigned int) (udpw->msg_size), GNUNET_a2s (sa, slen), (int) sent,
- (sent < 0) ? STRERROR (errno) : "ok");
- if (udpw->cont != NULL)
- udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_SYSERR);
- }
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "UDP transmitted %u-byte message to %s (%d: %s)\n",
- (unsigned int) (udpw->msg_size), GNUNET_a2s (sa, slen), (int) sent,
- (sent < 0) ? STRERROR (errno) : "ok");
+ const struct GNUNET_ATS_Information type = plugin->env->get_address_type
+ (plugin->env->cls,sa, slen);
- /* This was just a message fragment */
- if (udpw->frag_ctx != NULL)
- {
- GNUNET_FRAGMENT_context_transmission_done (udpw->frag_ctx->frag);
+ if ((GNUNET_ATS_NET_WAN == type.value) &&
+ ((ENETUNREACH == errno) || (ENETDOWN == errno)))
+ {
+ /* "Network unreachable" or "Network down" */
+ /*
+ * This indicates that this system is IPv6 enabled, but does not
+ * have a valid global IPv6 address assigned
+ */
+ LOG (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+ _("UDP could not message to `%s': `%s'. "
+ "Please check your network configuration and disable IPv6 if your "
+ "connection does not have a global IPv6 address\n"),
+ GNUNET_a2s (sa, slen),
+ STRERROR (errno));
+ }
+ else
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ "UDP could not transmit %u-byte message to `%s': `%s'\n",
+ (unsigned int) (udpw->msg_size), GNUNET_a2s (sa, slen),
+ STRERROR (errno));
+ }
+ call_continuation(udpw, GNUNET_SYSERR);
}
- /* This was a complete message*/
else
{
- if (udpw->cont != NULL)
- udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_OK);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "UDP transmitted %u-byte message to `%s' (%d: %s)\n",
+ (unsigned int) (udpw->msg_size), GNUNET_a2s (sa, slen), (int) sent,
+ (sent < 0) ? STRERROR (errno) : "ok");
+ call_continuation(udpw, GNUNET_OK);
}
if (sock == plugin->sockv4)
@@ -1761,6 +1925,7 @@ udp_select_send (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
return sent;
}
+
/**
* We have been notified that our readset has something to read. We don't
* know which socket needs to be read, so we have to check each one
@@ -1799,7 +1964,6 @@ udp_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (plugin->select_task);
plugin->select_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
GNUNET_TIME_UNIT_FOREVER_REL,
plugin->rs_v4,
(plugin->ipv4_queue_head != NULL) ? plugin->ws_v4 : NULL,
@@ -1847,7 +2011,6 @@ udp_plugin_select_v6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
if (plugin->select_task_v6 != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (plugin->select_task_v6);
plugin->select_task_v6 = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
GNUNET_TIME_UNIT_FOREVER_REL,
plugin->rs_v6,
(plugin->ipv6_queue_head != NULL) ? plugin->ws_v6 : NULL,
@@ -1875,7 +2038,7 @@ setup_sockets (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struct
plugin->sockv6 = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_DGRAM, 0);
if (NULL == plugin->sockv6)
{
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Disabling IPv6 since it is not supported on this system!\n");
+ LOG (GNUNET_ERROR_TYPE_WARNING, "Disabling IPv6 since it is not supported on this system!\n");
plugin->enable_ipv6 = GNUNET_NO;
}
else
@@ -1888,20 +2051,16 @@ setup_sockets (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struct
serverAddrv6->sin6_port = htons (plugin->port);
addrlen = sizeof (struct sockaddr_in6);
serverAddr = (struct sockaddr *) serverAddrv6;
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv6 port %d\n",
ntohs (serverAddrv6->sin6_port));
-#endif
tries = 0;
while (GNUNET_NETWORK_socket_bind (plugin->sockv6, serverAddr, addrlen) !=
GNUNET_OK)
{
serverAddrv6->sin6_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG,
"IPv6 Binding failed, trying new port %d\n",
ntohs (serverAddrv6->sin6_port));
-#endif
tries++;
if (tries > 10)
{
@@ -1912,11 +2071,9 @@ setup_sockets (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struct
}
if (plugin->sockv6 != NULL)
{
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG,
"IPv6 socket created on port %d\n",
ntohs (serverAddrv6->sin6_port));
-#endif
addrs[sockets_created] = (struct sockaddr *) serverAddrv6;
addrlens[sockets_created] = sizeof (struct sockaddr_in6);
sockets_created++;
@@ -1941,19 +2098,15 @@ setup_sockets (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struct
addrlen = sizeof (struct sockaddr_in);
serverAddr = (struct sockaddr *) serverAddrv4;
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG, "Binding to IPv4 port %d\n",
ntohs (serverAddrv4->sin_port));
-#endif
tries = 0;
while (GNUNET_NETWORK_socket_bind (plugin->sockv4, serverAddr, addrlen) !=
GNUNET_OK)
{
serverAddrv4->sin_port = htons (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 33537) + 32000); /* Find a good, non-root port */
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Binding failed, trying new port %d\n",
ntohs (serverAddrv4->sin_port));
-#endif
tries++;
if (tries > 10)
{
@@ -1982,11 +2135,10 @@ setup_sockets (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struct
}
if (sockets_created == 0)
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n"));
+ LOG (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UDP sockets\n"));
plugin->select_task =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
GNUNET_TIME_UNIT_FOREVER_REL,
plugin->rs_v4,
NULL,
@@ -2007,7 +2159,6 @@ setup_sockets (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struct
plugin->select_task_v6 =
GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
GNUNET_TIME_UNIT_FOREVER_REL,
plugin->rs_v6,
NULL,
@@ -2024,6 +2175,82 @@ setup_sockets (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struct
return sockets_created;
}
+/**
+ * Session was idle, so disconnect it
+ */
+static void
+session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_assert (NULL != cls);
+ struct Session *s = cls;
+
+ s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Session %p was idle for %llu, disconnecting\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+
+ /* call session destroy function */
+ disconnect_session(s);
+
+}
+
+/**
+ * Start session timeout
+ */
+static void
+start_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task);
+
+ s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+ &session_timeout,
+ s);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout for session %p set to %llu\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+}
+
+/**
+ * Increment session timeout due to activity
+ */
+static void
+reschedule_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task);
+
+ GNUNET_SCHEDULER_cancel (s->timeout_task);
+ s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+ &session_timeout,
+ s);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout rescheduled for session %p set to %llu\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+}
+
+/**
+ * Cancel timeout
+ */
+static void
+stop_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+
+ if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task)
+ {
+ GNUNET_SCHEDULER_cancel (s->timeout_task);
+ s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout rescheduled for session %p canceled\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout for session %p was not active\n",
+ s);
+ }
+}
/**
* The exported method. Makes the core api available via a global and
@@ -2037,8 +2264,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
{
struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
struct GNUNET_TRANSPORT_PluginFunctions *api;
- struct Plugin *plugin;
-
+ struct Plugin *p;
unsigned long long port;
unsigned long long aport;
unsigned long long broadcast;
@@ -2047,12 +2273,24 @@ libgnunet_plugin_transport_udp_init (void *cls)
char * bind4_address;
char * bind6_address;
struct GNUNET_TIME_Relative interval;
-
struct sockaddr_in serverAddrv4;
struct sockaddr_in6 serverAddrv6;
-
int res;
+ if (NULL == env->receive)
+ {
+ /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
+ initialze the plugin or the API */
+ api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
+ api->cls = NULL;
+ api->address_pretty_printer = &udp_plugin_address_pretty_printer;
+ api->address_to_string = &udp_address_to_string;
+ api->string_to_address = &udp_string_to_address;
+ return api;
+ }
+
+ GNUNET_assert( NULL != env->stats);
+
/* Get port number */
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp", "PORT",
@@ -2080,7 +2318,6 @@ libgnunet_plugin_transport_udp_init (void *cls)
else
enable_v6 = GNUNET_YES;
-
/* Addresses */
memset (&serverAddrv6, 0, sizeof (serverAddrv6));
memset (&serverAddrv4, 0, sizeof (serverAddrv4));
@@ -2117,7 +2354,6 @@ libgnunet_plugin_transport_udp_init (void *cls)
}
}
-
/* Enable neighbour discovery */
broadcast = GNUNET_CONFIGURATION_get_value_yesno (env->cfg, "transport-udp",
"BROADCAST");
@@ -2137,56 +2373,60 @@ libgnunet_plugin_transport_udp_init (void *cls)
udp_max_bps = 1024 * 1024 * 50; /* 50 MB/s == infinity for practical purposes */
}
- plugin = GNUNET_malloc (sizeof (struct Plugin));
+ p = GNUNET_malloc (sizeof (struct Plugin));
api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
- GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
+ GNUNET_BANDWIDTH_tracker_init (&p->tracker,
GNUNET_BANDWIDTH_value_init ((uint32_t)udp_max_bps), 30);
-
-
- plugin->sessions = GNUNET_CONTAINER_multihashmap_create (10);
- plugin->defrag_ctxs = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
- plugin->mst = GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages, plugin);
- plugin->port = port;
- plugin->aport = aport;
- plugin->broadcast_interval = interval;
- plugin->enable_ipv6 = enable_v6;
- plugin->env = env;
-
- api->cls = plugin;
+ p->sessions = GNUNET_CONTAINER_multihashmap_create (10);
+ p->defrag_ctxs = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
+ p->mst = GNUNET_SERVER_mst_create (&process_inbound_tokenized_messages, p);
+ p->port = port;
+ p->aport = aport;
+ p->broadcast_interval = interval;
+ p->enable_ipv6 = enable_v6;
+ p->env = env;
+
+ plugin = p;
+
+ api->cls = p;
api->send = NULL;
api->disconnect = &udp_disconnect;
api->address_pretty_printer = &udp_plugin_address_pretty_printer;
api->address_to_string = &udp_address_to_string;
+ api->string_to_address = &udp_string_to_address;
api->check_address = &udp_plugin_check_address;
api->get_session = &udp_plugin_get_session;
api->send = &udp_plugin_send;
LOG (GNUNET_ERROR_TYPE_DEBUG, "Setting up sockets\n");
- res = setup_sockets (plugin, &serverAddrv6, &serverAddrv4);
- if ((res == 0) || ((plugin->sockv4 == NULL) && (plugin->sockv6 == NULL)))
+ res = setup_sockets (p, &serverAddrv6, &serverAddrv4);
+ if ((res == 0) || ((p->sockv4 == NULL) && (p->sockv6 == NULL)))
{
LOG (GNUNET_ERROR_TYPE_ERROR, "Failed to create network sockets, plugin failed\n");
- GNUNET_free (plugin);
+ GNUNET_free (p);
GNUNET_free (api);
return NULL;
}
- LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting broadcasting\n");
if (broadcast == GNUNET_YES)
- setup_broadcast (plugin, &serverAddrv6, &serverAddrv4);
-
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting broadcasting\n");
+ setup_broadcast (p, &serverAddrv6, &serverAddrv4);
+ }
GNUNET_free_non_null (bind4_address);
GNUNET_free_non_null (bind6_address);
return api;
}
-int heap_cleanup_iterator (void *cls,
- struct GNUNET_CONTAINER_HeapNode *
- node, void *element,
- GNUNET_CONTAINER_HeapCostType
- cost)
+
+static int
+heap_cleanup_iterator (void *cls,
+ struct GNUNET_CONTAINER_HeapNode *
+ node, void *element,
+ GNUNET_CONTAINER_HeapCostType
+ cost)
{
struct DefragContext * d_ctx = element;
@@ -2203,13 +2443,20 @@ int heap_cleanup_iterator (void *cls,
* returns the udp transport API.
*
* @param cls our 'struct GNUNET_TRANSPORT_PluginEnvironment'
- * @return our 'struct GNUNET_TRANSPORT_PluginFunctions'
+ * @return NULL
*/
void *
libgnunet_plugin_transport_udp_done (void *cls)
{
struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
struct Plugin *plugin = api->cls;
+
+ if (NULL == plugin)
+ {
+ GNUNET_free (api);
+ return NULL;
+ }
+
stop_broadcast (plugin);
if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
@@ -2263,8 +2510,7 @@ libgnunet_plugin_transport_udp_done (void *cls)
{
struct UDPMessageWrapper *tmp = udpw->next;
GNUNET_CONTAINER_DLL_remove(plugin->ipv4_queue_head, plugin->ipv4_queue_tail, udpw);
- if (udpw->cont != NULL)
- udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_SYSERR);
+ call_continuation(udpw, GNUNET_SYSERR);
GNUNET_free (udpw);
udpw = tmp;
}
@@ -2273,17 +2519,14 @@ libgnunet_plugin_transport_udp_done (void *cls)
{
struct UDPMessageWrapper *tmp = udpw->next;
GNUNET_CONTAINER_DLL_remove(plugin->ipv6_queue_head, plugin->ipv6_queue_tail, udpw);
- if (udpw->cont != NULL)
- udpw->cont (udpw->cont_cls, &udpw->session->target, GNUNET_SYSERR);
+ call_continuation(udpw, GNUNET_SYSERR);
GNUNET_free (udpw);
udpw = tmp;
}
/* Clean up sessions */
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Cleaning up sessions\n");
-#endif
GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions, &disconnect_and_free_it, plugin);
GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions);
diff --git a/src/transport/plugin_transport_udp_broadcasting.c b/src/transport/plugin_transport_udp_broadcasting.c
index e33af26..baabf45 100644
--- a/src/transport/plugin_transport_udp_broadcasting.c
+++ b/src/transport/plugin_transport_udp_broadcasting.c
@@ -90,7 +90,7 @@ struct Mstv6Context
-void
+int
broadcast_ipv6_mst_cb (void *cls, void *client,
const struct GNUNET_MessageHeader *message)
{
@@ -104,13 +104,11 @@ broadcast_ipv6_mst_cb (void *cls, void *client,
if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
ntohs (msg->header.type))
- return;
-#if DEBUG_UDP_BROADCASTING
+ return GNUNET_OK;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received beacon with %u bytes from peer `%s' via address `%s'\n",
ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr)));
-#endif
struct GNUNET_ATS_Information atsi[2];
/* setup ATS */
@@ -130,9 +128,10 @@ broadcast_ipv6_mst_cb (void *cls, void *client,
("# IPv6 multicast HELLO beacons received via udp"),
1, GNUNET_NO);
GNUNET_free (mc);
+ return GNUNET_OK;
}
-void
+int
broadcast_ipv4_mst_cb (void *cls, void *client,
const struct GNUNET_MessageHeader *message)
{
@@ -145,13 +144,11 @@ broadcast_ipv4_mst_cb (void *cls, void *client,
if (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON !=
ntohs (msg->header.type))
- return;
-#if DEBUG_UDP_BROADCASTING
+ return GNUNET_OK;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received beacon with %u bytes from peer `%s' via address `%s'\n",
ntohs (msg->header.size), GNUNET_i2s (&msg->sender),
udp_address_to_string (NULL, &mc->addr, sizeof (mc->addr)));
-#endif
struct GNUNET_ATS_Information atsi[2];
@@ -172,6 +169,7 @@ broadcast_ipv4_mst_cb (void *cls, void *client,
("# IPv4 broadcast HELLO beacons received via udp"),
1, GNUNET_NO);
GNUNET_free (mc);
+ return GNUNET_OK;
}
void
@@ -179,13 +177,11 @@ udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, st
{
struct GNUNET_ATS_Information ats;
- if (addrlen == sizeof (struct sockaddr_in))
+ if ((GNUNET_YES == plugin->broadcast_ipv4) && (addrlen == sizeof (struct sockaddr_in)))
{
-#if DEBUG_UDP_BROADCASTING
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received IPv4 HELLO beacon broadcast with %i bytes from address %s\n",
size, GNUNET_a2s ((const struct sockaddr *) addr, addrlen));
-#endif
struct Mstv4Context *mc;
mc = GNUNET_malloc (sizeof (struct Mstv4Context));
@@ -195,18 +191,18 @@ udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, st
mc->addr.u4_port = av4->sin_port;
ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen);
mc->ats_address_network_type = ats.value;
+
+ GNUNET_assert (NULL != plugin->broadcast_ipv4_mst);
if (GNUNET_OK !=
GNUNET_SERVER_mst_receive (plugin->broadcast_ipv4_mst, mc, buf, size,
GNUNET_NO, GNUNET_NO))
GNUNET_free (mc);
}
- else if (addrlen == sizeof (struct sockaddr_in6))
+ else if ((GNUNET_YES == plugin->broadcast_ipv4) && (addrlen == sizeof (struct sockaddr_in6)))
{
-#if DEBUG_UDP_BROADCASTING
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received IPv6 HELLO beacon broadcast with %i bytes from address %s\n",
size, GNUNET_a2s ((const struct sockaddr *) &addr, addrlen));
-#endif
struct Mstv6Context *mc;
mc = GNUNET_malloc (sizeof (struct Mstv6Context));
@@ -216,7 +212,7 @@ udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, st
mc->addr.u6_port = av6->sin6_port;
ats = plugin->env->get_address_type (plugin->env->cls, (const struct sockaddr *) addr, addrlen);
mc->ats_address_network_type = ats.value;
-
+ GNUNET_assert (NULL != plugin->broadcast_ipv4_mst);
if (GNUNET_OK !=
GNUNET_SERVER_mst_receive (plugin->broadcast_ipv6_mst, mc, buf, size,
GNUNET_NO, GNUNET_NO))
@@ -224,37 +220,42 @@ udp_broadcast_receive (struct Plugin *plugin, const char * buf, ssize_t size, st
}
}
-static void
-udp_ipv4_broadcast_send (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+static unsigned int
+prepare_beacon (struct Plugin *plugin, struct UDP_Beacon_Message *msg)
{
- struct Plugin *plugin = cls;
- int sent;
- uint16_t msg_size;
uint16_t hello_size;
- char buf[65536];
+ uint16_t msg_size;
const struct GNUNET_MessageHeader *hello;
- struct UDP_Beacon_Message *msg;
- struct BroadcastAddress *baddr;
-
- plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
-
hello = plugin->env->get_our_hello ();
hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
msg_size = hello_size + sizeof (struct UDP_Beacon_Message);
if (hello_size < (sizeof (struct GNUNET_MessageHeader)) ||
(msg_size > (UDP_MTU)))
- return;
+ return 0;
- msg = (struct UDP_Beacon_Message *) buf;
msg->sender = *(plugin->env->my_identity);
- msg->header.size = ntohs (msg_size);
- msg->header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON);
+ msg->header.size = htons (msg_size);
+ msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON);
memcpy (&msg[1], hello, hello_size);
- sent = 0;
+ return msg_size;
+}
+
+static void
+udp_ipv4_broadcast_send (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct Plugin *plugin = cls;
+ int sent;
+ uint16_t msg_size;
+ char buf[65536] GNUNET_ALIGN;
+ struct BroadcastAddress *baddr;
+
+ plugin->send_ipv4_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
+ msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf);
+ sent = 0;
baddr = plugin->ipv4_broadcast_head;
/* just IPv4 */
while ((baddr != NULL) && (baddr->addrlen == sizeof (struct sockaddr_in)))
@@ -263,19 +264,16 @@ udp_ipv4_broadcast_send (void *cls,
addr->sin_port = htons (plugin->port);
- sent =
- GNUNET_NETWORK_socket_sendto (plugin->sockv4, msg, msg_size,
+ sent = GNUNET_NETWORK_socket_sendto (plugin->sockv4, &buf, msg_size,
(const struct sockaddr *) addr,
baddr->addrlen);
if (sent == GNUNET_SYSERR)
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
else
{
-#if DEBUG_UDP_BROADCASTING
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Sent HELLO beacon broadcast with %i bytes to address %s\n", sent,
+ "Sent HELLO beacon broadcast with %i bytes to address %s\n", sent,
GNUNET_a2s (baddr->addr, baddr->addrlen));
-#endif
}
baddr = baddr->next;
}
@@ -292,31 +290,13 @@ udp_ipv6_broadcast_send (void *cls,
struct Plugin *plugin = cls;
int sent;
uint16_t msg_size;
- uint16_t hello_size;
- char buf[65536];
-
- const struct GNUNET_MessageHeader *hello;
- struct UDP_Beacon_Message *msg;
+ char buf[65536] GNUNET_ALIGN;
plugin->send_ipv6_broadcast_task = GNUNET_SCHEDULER_NO_TASK;
- hello = plugin->env->get_our_hello ();
- hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
- msg_size = hello_size + sizeof (struct UDP_Beacon_Message);
-
- if (hello_size < (sizeof (struct GNUNET_MessageHeader)) ||
- (msg_size > (UDP_MTU)))
- return;
-
- msg = (struct UDP_Beacon_Message *) buf;
- msg->sender = *(plugin->env->my_identity);
- msg->header.size = ntohs (msg_size);
- msg->header.type = ntohs (GNUNET_MESSAGE_TYPE_TRANSPORT_BROADCAST_BEACON);
- memcpy (&msg[1], hello, hello_size);
+ msg_size = prepare_beacon(plugin, (struct UDP_Beacon_Message *) &buf);
sent = 0;
-
- sent =
- GNUNET_NETWORK_socket_sendto (plugin->sockv6, msg, msg_size,
+ sent = GNUNET_NETWORK_socket_sendto (plugin->sockv6, &buf, msg_size,
(const struct sockaddr *)
&plugin->ipv6_multicast_address,
sizeof (struct sockaddr_in6));
@@ -324,16 +304,12 @@ udp_ipv6_broadcast_send (void *cls,
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sendto");
else
{
-#if DEBUG_UDP_BROADCASTING
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Sending IPv6 HELLO beacon broadcast with %i bytes to address %s\n",
sent,
GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address,
sizeof (struct sockaddr_in6)));
-#endif
}
-
-
plugin->send_ipv6_broadcast_task =
GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
&udp_ipv6_broadcast_send, plugin);
@@ -349,7 +325,6 @@ iface_proc (void *cls, const char *name, int isDefault,
if (addr != NULL)
{
-#if DEBUG_UDP_BROADCASTING
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "address %s for interface %s %p\n ",
GNUNET_a2s (addr, addrlen), name, addr);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -357,7 +332,6 @@ iface_proc (void *cls, const char *name, int isDefault,
GNUNET_a2s (broadcast_addr, addrlen), name, broadcast_addr);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "netmask %s for interface %s %p\n ",
GNUNET_a2s (netmask, addrlen), name, netmask);
-#endif
/* Collecting broadcast addresses */
if (broadcast_addr != NULL)
@@ -450,9 +424,7 @@ setup_broadcast (struct Plugin *plugin, struct sockaddr_in6 *serverAddrv6, struc
}
else
{
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 broadcasting running\n");
-#endif
plugin->send_ipv6_broadcast_task =
GNUNET_SCHEDULER_add_now (&udp_ipv6_broadcast_send, plugin);
plugin->broadcast_ipv6 = GNUNET_YES;
@@ -503,9 +475,7 @@ stop_broadcast (struct Plugin *plugin)
}
else
{
-#if DEBUG_UDP
LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 Broadcasting stopped\n");
-#endif
}
if (plugin->send_ipv6_broadcast_task != GNUNET_SCHEDULER_NO_TASK)
diff --git a/src/transport/plugin_transport_unix.c b/src/transport/plugin_transport_unix.c
index 499cc23..057479d 100644
--- a/src/transport/plugin_transport_unix.c
+++ b/src/transport/plugin_transport_unix.c
@@ -42,9 +42,6 @@
#include "gnunet_transport_plugin.h"
#include "transport.h"
-#define DEBUG_UNIX GNUNET_EXTRALOGGING
-#define DETAILS GNUNET_NO
-
#define MAX_PROBES 20
/*
@@ -88,6 +85,13 @@ struct Session
void *addr;
size_t addrlen;
struct GNUNET_PeerIdentity target;
+
+ /**
+ * Session timeout task
+ */
+ GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+ struct Plugin * plugin;
};
struct UNIXMessageWrapper
@@ -188,12 +192,7 @@ struct Plugin
*/
struct GNUNET_TRANSPORT_PluginEnvironment *env;
- /*
- * Session of peers with whom we are currently connected
- */
- struct PeerSession *sessions;
-
- /*
+ /**
* Sessions
*/
struct GNUNET_CONTAINER_MultiHashMap *session_map;
@@ -242,30 +241,167 @@ struct Plugin
* ATS network
*/
struct GNUNET_ATS_Information ats_network;
+
+ unsigned int bytes_in_queue;
+ unsigned int bytes_in_sent;
+ unsigned int bytes_in_recv;
+ unsigned int bytes_discarded;
};
+/**
+ * Start session timeout
+ */
+static void
+start_session_timeout (struct Session *s);
-static int
-get_session_delete_it (void *cls, const GNUNET_HashCode * key, void *value)
+/**
+ * Increment session timeout due to activity
+ */
+static void
+reschedule_session_timeout (struct Session *s);
+
+/**
+ * Cancel timeout
+ */
+static void
+stop_session_timeout (struct Session *s);
+
+
+static void
+unix_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+static void
+reschedule_select (struct Plugin * plugin)
{
- struct Session *s = value;
- struct Plugin *plugin = cls;
- GNUNET_assert (plugin != NULL);
-#if DEBUG_UNIX
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deleting session for peer `%s' `%s' \n", GNUNET_i2s (&s->target), s->addr);
-#endif
+ if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (plugin->select_task);
+ plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+
+ if (NULL != plugin->msg_head)
+ {
+ plugin->select_task =
+ GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ plugin->rs,
+ plugin->ws,
+ &unix_plugin_select, plugin);
+ plugin->with_ws = GNUNET_YES;
+ }
+ else
+ {
+ plugin->select_task =
+ GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ plugin->rs,
+ NULL,
+ &unix_plugin_select, plugin);
+ plugin->with_ws = GNUNET_NO;
+ }
+}
+
+struct LookupCtx
+{
+ struct Session *s;
+ const struct sockaddr_un *addr;
+};
+
+int lookup_session_it (void *cls,
+ const GNUNET_HashCode * key,
+ void *value)
+{
+ struct LookupCtx *lctx = cls;
+ struct Session *t = value;
+
+ if (0 == strcmp (t->addr, lctx->addr->sun_path))
+ {
+ lctx->s = t;
+ return GNUNET_NO;
+ }
+ return GNUNET_YES;
+}
+
+static struct Session *
+lookup_session (struct Plugin *plugin, struct GNUNET_PeerIdentity *sender, const struct sockaddr_un *addr)
+{
+ struct LookupCtx lctx;
+
+ GNUNET_assert (NULL != plugin);
+ GNUNET_assert (NULL != sender);
+ GNUNET_assert (NULL != addr);
+
+ lctx.s = NULL;
+ lctx.addr = addr;
+
+ GNUNET_CONTAINER_multihashmap_get_multiple (plugin->session_map, &sender->hashPubKey, &lookup_session_it, &lctx);
+
+ return lctx.s;
+}
+
+/**
+ * Functions with this signature are called whenever we need
+ * to close a session due to a disconnect or failure to
+ * establish a connection.
+ *
+ * @param s session to close down
+ */
+static void
+disconnect_session (struct Session *s)
+{
+ struct UNIXMessageWrapper *msgw;
+ struct UNIXMessageWrapper *next;
+ struct Plugin * plugin = s->plugin;
+ int removed;
+ GNUNET_assert (plugin != NULL);
+ GNUNET_assert (s != NULL);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting session for peer `%s' `%s' \n", GNUNET_i2s (&s->target), s->addr);
+ stop_session_timeout (s);
plugin->env->session_end (plugin->env->cls, &s->target, s);
+ msgw = plugin->msg_head;
+ removed = GNUNET_NO;
+ next = plugin->msg_head;
+ while (NULL != next)
+ {
+ msgw = next;
+ next = msgw->next;
+ if (msgw->session != s)
+ continue;
+ GNUNET_CONTAINER_DLL_remove (plugin->msg_head, plugin->msg_tail, msgw);
+ if (NULL != msgw->cont)
+ msgw->cont (msgw->cont_cls, &msgw->session->target, GNUNET_SYSERR);
+ GNUNET_free (msgw->msg);
+ GNUNET_free (msgw);
+ removed = GNUNET_YES;
+ }
+ if ((GNUNET_YES == removed) && (NULL == plugin->msg_head))
+ reschedule_select (plugin);
+
GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_remove(plugin->session_map, &s->target.hashPubKey, s));
+ GNUNET_CONTAINER_multihashmap_remove(plugin->session_map, &s->target.hashPubKey, s));
+
+ GNUNET_STATISTICS_set(plugin->env->stats,
+ "# UNIX sessions active",
+ GNUNET_CONTAINER_multihashmap_size(plugin->session_map),
+ GNUNET_NO);
GNUNET_free (s);
+}
+static int
+get_session_delete_it (void *cls, const GNUNET_HashCode * key, void *value)
+{
+ struct Session *s = value;
+ disconnect_session (s);
return GNUNET_YES;
}
+
/**
* Disconnect from a remote node. Clean up session if we have one for this peer
*
@@ -273,7 +409,7 @@ get_session_delete_it (void *cls, const GNUNET_HashCode * key, void *value)
* @param target the peeridentity of the peer to disconnect
* @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
*/
-void
+static void
unix_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
{
struct Plugin *plugin = cls;
@@ -314,28 +450,14 @@ unix_transport_server_stop (void *cls)
plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
}
- GNUNET_break (GNUNET_OK ==
- GNUNET_NETWORK_socket_close (plugin->unix_sock.desc));
- plugin->unix_sock.desc = NULL;
- plugin->with_ws = GNUNET_NO;
- return GNUNET_OK;
-}
-
-
-struct PeerSession *
-find_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *peer)
-{
- struct PeerSession *pos;
-
- pos = plugin->sessions;
- while (pos != NULL)
+ if (NULL != plugin->unix_sock.desc)
{
- if (memcmp (&pos->target, peer, sizeof (struct GNUNET_PeerIdentity)) == 0)
- return pos;
- pos = pos->next;
+ GNUNET_break (GNUNET_OK ==
+ GNUNET_NETWORK_socket_close (plugin->unix_sock.desc));
+ plugin->unix_sock.desc = NULL;
+ plugin->with_ws = GNUNET_NO;
}
-
- return pos;
+ return GNUNET_OK;
}
@@ -369,7 +491,7 @@ unix_real_send (void *cls,
size_t addrlen, GNUNET_TRANSPORT_TransmitContinuation cont,
void *cont_cls)
{
-
+ struct Plugin *plugin = cls;
ssize_t sent;
const void *sb;
size_t sbs;
@@ -377,34 +499,31 @@ unix_real_send (void *cls,
size_t slen;
int retry;
+ GNUNET_assert (NULL != plugin);
+
if (send_handle == NULL)
{
-#if DEBUG_UNIX
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "unix_real_send with send_handle NULL!\n");
-#endif
- /* failed to open send socket for AF */
+ /* We do not have a send handle */
+ GNUNET_break (0);
if (cont != NULL)
cont (cont_cls, target, GNUNET_SYSERR);
- return 0;
+ return -1;
}
if ((addr == NULL) || (addrlen == 0))
{
-#if DEBUG_UNIX
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "unix_real_send called without address, returning!\n");
-#endif
+ /* Can never send if we don't have an address */
+ GNUNET_break (0);
if (cont != NULL)
cont (cont_cls, target, GNUNET_SYSERR);
- return 0; /* Can never send if we don't have an address!! */
+ return -1;
}
+ /* Prepare address */
memset (&un, 0, sizeof (un));
un.sun_family = AF_UNIX;
slen = strlen (addr) + 1;
if (slen >= sizeof (un.sun_path))
slen = sizeof (un.sun_path) - 1;
- sent = 0;
GNUNET_assert (slen < sizeof (un.sun_path));
memcpy (un.sun_path, addr, slen);
un.sun_path[slen] = '\0';
@@ -417,11 +536,17 @@ unix_real_send (void *cls,
#endif
sb = (struct sockaddr *) &un;
sbs = slen;
+
+ /* Send the data */
+ sent = 0;
retry = GNUNET_NO;
sent = GNUNET_NETWORK_socket_sendto (send_handle, msgbuf, msgbuf_size, sb, sbs);
if ((GNUNET_SYSERR == sent) && ((errno == EAGAIN) || (errno == ENOBUFS)))
- retry = GNUNET_YES;
+ {
+ /* We have to retry later: retry */
+ return 0;
+ }
if ((GNUNET_SYSERR == sent) && (errno == EMSGSIZE))
{
@@ -436,23 +561,38 @@ unix_real_send (void *cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Trying to increase socket buffer size from %i to %i for message size %i\n",
- size, ((msgbuf_size / 1000) + 2) * 1000, msgbuf_size);
+ size,
+ ((msgbuf_size / 1000) + 2) * 1000,
+ msgbuf_size);
size = ((msgbuf_size / 1000) + 2) * 1000;
if (GNUNET_NETWORK_socket_setsockopt
((struct GNUNET_NETWORK_Handle *) send_handle, SOL_SOCKET, SO_SNDBUF,
&size, sizeof (size)) == GNUNET_OK)
- retry = GNUNET_YES;
+ {
+ /* Increased buffer size, retry sending */
+ return 0;
+ }
else
+ {
+ /* Could not increase buffer size: error, no retry */
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "setsockopt");
+ return -1;
+ }
+ }
+ else
+ {
+ /* Buffer is bigger than message: error, no retry
+ * This should never happen!*/
+ GNUNET_break (0);
+ return -1;
}
}
-#if DEBUG_UNIX
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"UNIX transmit %u-byte message to %s (%d: %s)\n",
(unsigned int) msgbuf_size, GNUNET_a2s (sb, sbs), (int) sent,
(sent < 0) ? STRERROR (errno) : "ok");
-#endif
+
/* Calling continuation */
if (cont != NULL)
{
@@ -465,14 +605,20 @@ unix_real_send (void *cls,
/* return number of bytes successfully sent */
if (sent > 0)
return sent;
+ if (sent == 0)
+ {
+ /* That should never happen */
+ GNUNET_break (0);
+ return -1;
+ }
/* failed and retry: return 0 */
if ((GNUNET_SYSERR == sent) && (retry == GNUNET_YES))
return 0;
/* failed and no retry: return -1 */
if ((GNUNET_SYSERR == sent) && (retry == GNUNET_NO))
return -1;
-
- return sent;
+ /* default */
+ return -1;
}
struct gsi_ctx
@@ -482,15 +628,14 @@ struct gsi_ctx
struct Session *res;
};
+
static int
get_session_it (void *cls, const GNUNET_HashCode * key, void *value)
{
struct gsi_ctx *gsi = cls;
struct Session *s = value;
-#if DEBUG_UNIX
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Comparing session %s %s\n", gsi->address, s->addr);
-#endif
if ((gsi->addrlen == s->addrlen) &&
(0 == memcmp (gsi->address, s->addr, s->addrlen)))
{
@@ -527,27 +672,29 @@ unix_plugin_get_session (void *cls,
GNUNET_CONTAINER_multihashmap_get_multiple (plugin->session_map, &address->peer.hashPubKey, &get_session_it, &gsi);
if (gsi.res != NULL)
{
-#if DEBUG_UNIX
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found existing session\n");
-#endif
return gsi.res;
}
/* Create a new session */
-
s = GNUNET_malloc (sizeof (struct Session) + address->address_length);
s->addr = &s[1];
s->addrlen = address->address_length;
+ s->plugin = plugin;
memcpy(s->addr, address->address, s->addrlen);
memcpy(&s->target, &address->peer, sizeof (struct GNUNET_PeerIdentity));
+ start_session_timeout (s);
+
GNUNET_CONTAINER_multihashmap_put (plugin->session_map,
&address->peer.hashPubKey, s,
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-#if DEBUG_UNIX
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating new session\n");
-#endif
+ GNUNET_STATISTICS_set(plugin->env->stats,
+ "# UNIX sessions active",
+ GNUNET_CONTAINER_multihashmap_size(plugin->session_map),
+ GNUNET_NO);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating new session\n");
return s;
}
@@ -609,7 +756,11 @@ unix_plugin_send (void *cls,
if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_contains_value(plugin->session_map,
&session->target.hashPubKey, session))
{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid session for peer `%s' `%s'\n",
+ GNUNET_i2s (&session->target),
+ (char *) session->addr);
GNUNET_break (0);
+
return GNUNET_SYSERR;
}
@@ -621,6 +772,8 @@ unix_plugin_send (void *cls,
sizeof (struct GNUNET_PeerIdentity));
memcpy (&message[1], msgbuf, msgbuf_size);
+ reschedule_session_timeout (session);
+
wrapper = GNUNET_malloc (sizeof (struct UNIXMessageWrapper));
wrapper->msg = message;
wrapper->msgsize = ssize;
@@ -632,24 +785,15 @@ unix_plugin_send (void *cls,
GNUNET_CONTAINER_DLL_insert(plugin->msg_head, plugin->msg_tail, wrapper);
-#if DEBUG_UNIX
+ plugin->bytes_in_queue += ssize;
+ GNUNET_STATISTICS_set (plugin->env->stats,"# UNIX bytes in send queue",
+ plugin->bytes_in_queue, GNUNET_NO);
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent %d bytes to `%s'\n", ssize,
(char *) session->addr);
-#endif
-
if (plugin->with_ws == GNUNET_NO)
{
- if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel(plugin->select_task);
-
- plugin->select_task =
- GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
- GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->rs,
- plugin->ws,
- &unix_plugin_select, plugin);
- plugin->with_ws = GNUNET_YES;
+ reschedule_select (plugin);
}
return ssize;
}
@@ -670,6 +814,8 @@ unix_demultiplexer (struct Plugin *plugin, struct GNUNET_PeerIdentity *sender,
const struct sockaddr_un *un, size_t fromlen)
{
struct GNUNET_ATS_Information ats[2];
+ struct Session *s = NULL;
+ struct GNUNET_HELLO_Address * addr;
ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
ats[0].value = htonl (UNIX_DIRECT_DISTANCE);
@@ -678,20 +824,30 @@ unix_demultiplexer (struct Plugin *plugin, struct GNUNET_PeerIdentity *sender,
GNUNET_assert (fromlen >= sizeof (struct sockaddr_un));
-#if DEBUG_UNIX
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message from %s\n",
un->sun_path);
-#endif
+
+ plugin->bytes_in_recv += ntohs(currhdr->size);
+ GNUNET_STATISTICS_set (plugin->env->stats,"# UNIX bytes received",
+ plugin->bytes_in_recv, GNUNET_NO);
+
+ addr = GNUNET_HELLO_address_allocate(sender, "unix", un->sun_path, strlen (un->sun_path) + 1);
+ s = lookup_session (plugin, sender, un);
+ if (NULL == s)
+ s = unix_plugin_get_session (plugin, addr);
+ reschedule_session_timeout (s);
+
plugin->env->receive (plugin->env->cls, sender, currhdr,
(const struct GNUNET_ATS_Information *) &ats, 2,
- NULL, un->sun_path, strlen (un->sun_path) + 1);
+ s, un->sun_path, strlen (un->sun_path) + 1);
+ GNUNET_free (addr);
}
static void
unix_plugin_select_read (struct Plugin * plugin)
{
- char buf[65536];
+ char buf[65536] GNUNET_ALIGN;
struct UNIXMessage *msg;
struct GNUNET_PeerIdentity sender;
struct sockaddr_un un;
@@ -723,10 +879,8 @@ unix_plugin_select_read (struct Plugin * plugin)
#if LINUX
un.sun_path[0] = '/';
#endif
-#if DEBUG_UNIX
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Read %d bytes from socket %s\n", ret,
&un.sun_path[0]);
-#endif
}
GNUNET_assert (AF_UNIX == (un.sun_family));
@@ -752,14 +906,17 @@ unix_plugin_select_read (struct Plugin * plugin)
GNUNET_break_op (0);
break;
}
+
unix_demultiplexer (plugin, &sender, currhdr, &un, sizeof (un));
offset += csize;
}
}
+
static void
unix_plugin_select_write (struct Plugin * plugin)
{
+ static int retry_counter;
int sent = 0;
struct UNIXMessageWrapper * msgw = plugin->msg_head;
@@ -774,37 +931,69 @@ unix_plugin_select_write (struct Plugin * plugin)
msgw->session->addrlen,
msgw->cont, msgw->cont_cls);
- /* successfully sent bytes */
- if (sent > 0)
+ if (sent == 0)
+ {
+ /* failed and retry */
+ retry_counter++;
+ GNUNET_STATISTICS_set (plugin->env->stats,"# UNIX retry attempt",
+ retry_counter, GNUNET_NO);
+ return;
+ }
+
+ if (retry_counter > 0 )
+ {
+ /* no retry: reset counter */
+ retry_counter = 0;
+ GNUNET_STATISTICS_set (plugin->env->stats,"# UNIX retry attempt",
+ retry_counter, GNUNET_NO);
+ }
+
+ if (sent == -1)
{
+ /* failed and no retry */
GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, msgw);
+
+ GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize);
+ plugin->bytes_in_queue -= msgw->msgsize;
+ GNUNET_STATISTICS_set (plugin->env->stats,"# UNIX bytes in send queue",
+ plugin->bytes_in_queue, GNUNET_NO);
+ plugin->bytes_discarded += msgw->msgsize;
+ GNUNET_STATISTICS_set (plugin->env->stats,"# UNIX bytes discarded",
+ plugin->bytes_discarded, GNUNET_NO);
+
GNUNET_free (msgw->msg);
GNUNET_free (msgw);
return;
}
- /* failed and no retry */
- if (sent == -1)
+ if (sent > 0)
{
+ /* successfully sent bytes */
GNUNET_CONTAINER_DLL_remove(plugin->msg_head, plugin->msg_tail, msgw);
+
+ GNUNET_assert (plugin->bytes_in_queue >= msgw->msgsize);
+ plugin->bytes_in_queue -= msgw->msgsize;
+ GNUNET_STATISTICS_set (plugin->env->stats,"# UNIX bytes in send queue",
+ plugin->bytes_in_queue, GNUNET_NO);
+ plugin->bytes_in_sent += msgw->msgsize;
+ GNUNET_STATISTICS_set (plugin->env->stats,"# UNIX bytes sent",
+ plugin->bytes_in_sent, GNUNET_NO);
+
GNUNET_free (msgw->msg);
GNUNET_free (msgw);
return;
}
- /* failed and retry */
- if (sent == 0)
- return;
}
-/*
- * @param cls the plugin handle
- * @param tc the scheduling context (for rescheduling this function again)
- *
+
+/**
* We have been notified that our writeset has something to read. We don't
* know which socket needs to be read, so we have to check each one
* Then reschedule this function to be called again once more is available.
*
+ * @param cls the plugin handle
+ * @param tc the scheduling context (for rescheduling this function again)
*/
static void
unix_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
@@ -815,9 +1004,9 @@ unix_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
return;
- plugin->with_ws = GNUNET_NO;
if ((tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY) != 0)
{
+ /* Ready to send data */
GNUNET_assert (GNUNET_NETWORK_fdset_isset
(tc->write_ready, plugin->unix_sock.desc));
if (plugin->msg_head != NULL)
@@ -826,30 +1015,22 @@ unix_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
if ((tc->reason & GNUNET_SCHEDULER_REASON_READ_READY) != 0)
{
+ /* Ready to receive data */
GNUNET_assert (GNUNET_NETWORK_fdset_isset
(tc->read_ready, plugin->unix_sock.desc));
unix_plugin_select_read (plugin);
}
- if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
- GNUNET_SCHEDULER_cancel (plugin->select_task);
- plugin->select_task =
- GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
- GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->rs,
- (plugin->msg_head != NULL) ? plugin->ws : NULL,
- &unix_plugin_select, plugin);
- if (plugin->msg_head != NULL)
- plugin->with_ws = GNUNET_YES;
+ reschedule_select (plugin);
}
+
/**
* Create a slew of UNIX sockets. If possible, use IPv6 and IPv4.
*
* @param cls closure for server start, should be a struct Plugin *
* @return number of sockets created or GNUNET_SYSERR on error
-*/
+ */
static int
unix_transport_server_start (void *cls)
{
@@ -893,10 +1074,8 @@ unix_transport_server_start (void *cls)
plugin->unix_sock.desc = NULL;
return GNUNET_SYSERR;
}
-#if DEBUG_UNIX
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "unix", "Bound to `%s'\n",
&un.sun_path[0]);
-#endif
plugin->rs = GNUNET_NETWORK_fdset_create ();
plugin->ws = GNUNET_NETWORK_fdset_create ();
GNUNET_NETWORK_fdset_zero (plugin->rs);
@@ -904,14 +1083,7 @@ unix_transport_server_start (void *cls)
GNUNET_NETWORK_fdset_set (plugin->rs, plugin->unix_sock.desc);
GNUNET_NETWORK_fdset_set (plugin->ws, plugin->unix_sock.desc);
- plugin->select_task =
- GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
- GNUNET_SCHEDULER_NO_TASK,
- GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->rs,
- NULL,
- &unix_plugin_select, plugin);
- plugin->with_ws = GNUNET_NO;
+ reschedule_select (plugin);
return 1;
}
@@ -936,12 +1108,9 @@ unix_transport_server_start (void *cls)
static int
unix_check_address (void *cls, const void *addr, size_t addrlen)
{
-
-#if DEBUG_UNIX
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Informing transport service about my address `%s'\n",
(char *) addr);
-#endif
return GNUNET_OK;
}
@@ -968,16 +1137,59 @@ unix_plugin_address_pretty_printer (void *cls, const char *type,
GNUNET_TRANSPORT_AddressStringCallback asc,
void *asc_cls)
{
- if ((addr != NULL) && (addrlen > 0))
+ if ((NULL != addr) && (addrlen > 0))
+ {
asc (asc_cls, (const char *) addr);
+ }
else
{
GNUNET_break (0);
- asc (asc_cls, "Invalid UNIX address");
+ asc (asc_cls, "<invalid UNIX address>");
}
+ asc (asc_cls, NULL);
+}
+
+/**
+ * Function called to convert a string address to
+ * a binary address.
+ *
+ * @param cls closure ('struct Plugin*')
+ * @param addr string address
+ * @param addrlen length of the address (strlen(addr) + '\0')
+ * @param buf location to store the buffer
+ * If the function returns GNUNET_SYSERR, its contents are undefined.
+ * @param added length of created address
+ * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ */
+static int
+unix_string_to_address (void *cls, const char *addr, uint16_t addrlen,
+ void **buf, size_t *added)
+{
+ if ((NULL == addr) || (0 == addrlen))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ if ('\0' != addr[addrlen - 1])
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ if (strlen (addr) != addrlen - 1)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ (*buf) = strdup (addr);
+ (*added) = strlen (addr) + 1;
+ return GNUNET_OK;
}
+
/**
* Function called for a quick conversion of the binary address to
* a numeric address. Note that the caller must not free the
@@ -994,10 +1206,10 @@ unix_address_to_string (void *cls, const void *addr, size_t addrlen)
{
if ((addr != NULL) && (addrlen > 0))
return (const char *) addr;
- else
- return NULL;
+ return NULL;
}
+
/**
* Notify transport service about address
*
@@ -1014,6 +1226,85 @@ address_notification (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
strlen (plugin->unix_socket_path) + 1);
}
+
+/**
+ * Session was idle, so disconnect it
+ */
+static void
+session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ GNUNET_assert (NULL != cls);
+ struct Session *s = cls;
+
+ s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Session %p was idle for %llu, disconnecting\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+
+ /* call session destroy function */
+ disconnect_session(s);
+
+}
+
+/**
+ * Start session timeout
+ */
+static void
+start_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task);
+
+ s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+ &session_timeout,
+ s);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout for session %p set to %llu\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+}
+
+/**
+ * Increment session timeout due to activity
+ */
+static void
+reschedule_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+ GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != s->timeout_task);
+
+ GNUNET_SCHEDULER_cancel (s->timeout_task);
+ s->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+ &session_timeout,
+ s);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout rescheduled for session %p set to %llu\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+}
+
+/**
+ * Cancel timeout
+ */
+static void
+stop_session_timeout (struct Session *s)
+{
+ GNUNET_assert (NULL != s);
+
+ if (GNUNET_SCHEDULER_NO_TASK != s->timeout_task)
+ {
+ GNUNET_SCHEDULER_cancel (s->timeout_task);
+ s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout rescheduled for session %p canceled\n",
+ s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout for session %p was not active\n",
+ s);
+ }
+}
+
+
/**
* The exported method. Makes the core api available via a global and
* returns the unix transport API.
@@ -1027,6 +1318,19 @@ libgnunet_plugin_transport_unix_init (void *cls)
struct Plugin *plugin;
int sockets_created;
+ if (NULL == env->receive)
+ {
+ /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
+ initialze the plugin or the API */
+ api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
+ api->cls = NULL;
+ api->address_pretty_printer = &unix_plugin_address_pretty_printer;
+ api->address_to_string = &unix_address_to_string;
+ api->string_to_address = &unix_string_to_address;
+ return api;
+ }
+ GNUNET_assert( NULL != env->stats);
+
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-unix", "PORT",
&port))
@@ -1046,6 +1350,7 @@ libgnunet_plugin_transport_unix_init (void *cls)
api->address_pretty_printer = &unix_plugin_address_pretty_printer;
api->address_to_string = &unix_address_to_string;
api->check_address = &unix_check_address;
+ api->string_to_address = &unix_string_to_address;
sockets_created = unix_transport_server_start (plugin);
if (sockets_created == 0)
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UNIX sockets\n"));
@@ -1062,13 +1367,20 @@ libgnunet_plugin_transport_unix_done (void *cls)
struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
struct Plugin *plugin = api->cls;
+ if (NULL == plugin)
+ {
+ GNUNET_free (api);
+ return NULL;
+ }
unix_transport_server_stop (plugin);
GNUNET_CONTAINER_multihashmap_iterate (plugin->session_map, &get_session_delete_it, plugin);
GNUNET_CONTAINER_multihashmap_destroy (plugin->session_map);
- GNUNET_NETWORK_fdset_destroy (plugin->rs);
- GNUNET_NETWORK_fdset_destroy (plugin->ws);
+ if (NULL != plugin->rs)
+ GNUNET_NETWORK_fdset_destroy (plugin->rs);
+ if (NULL != plugin->ws)
+ GNUNET_NETWORK_fdset_destroy (plugin->ws);
GNUNET_free (plugin->unix_socket_path);
GNUNET_free (plugin);
GNUNET_free (api);
diff --git a/src/transport/plugin_transport_wlan.c b/src/transport/plugin_transport_wlan.c
index 08f9c58..aed4b22 100644
--- a/src/transport/plugin_transport_wlan.c
+++ b/src/transport/plugin_transport_wlan.c
@@ -1,31 +1,29 @@
/*
- This file is part of GNUnet
- (C) 2010 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.
- */
+ This file is part of GNUnet
+ (C) 2010, 2011, 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 transport/plugin_transport_wlan.c
* @brief transport plugin for wlan
* @author David Brodski
+ * @author Christian Grothoff
*/
-
-//TODO split rx and tx structures for better handling
-
#include "platform.h"
#include "gnunet_hello_lib.h"
#include "gnunet_protocols.h"
@@ -39,1808 +37,756 @@
#include "gnunet_fragmentation_lib.h"
#include "gnunet_constants.h"
-/**
- * DEBUG switch
- */
-#define DEBUG_WLAN GNUNET_EXTRA_LOGGING
-
-
-#define PROTOCOL_PREFIX "wlan"
-
-#define PLUGIN_LOG_NAME "wlan-plugin"
+#define LOG(kind,...) GNUNET_log_from (kind, "transport-wlan",__VA_ARGS__)
/**
- * Max size of packet
+ * Max size of packet (that we give to the WLAN driver for transmission)
*/
#define WLAN_MTU 1430
/**
- * time out of a session
- */
-#define SESSION_TIMEOUT GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
-
-/**
* time out of a mac endpoint
*/
#define MACENDPOINT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2)
/**
- * scaling factor for hello beacon
- */
-#define HELLO_BEACON_SCALING_FACTOR 30
-
-/**
- * scaling factor for restarting the helper
- */
-#define HELPER_RESTART_SCALING_FACTOR 2
-
-/**
- * max size of fragment queue
- */
-#define FRAGMENT_QUEUE_SIZE 10
-/**
- * max messages in fragment queue per session/client
+ * We reduce the frequence of HELLO beacons in relation to
+ * the number of MAC addresses currently visible to us.
+ * This is the multiplication factor.
*/
-#define FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION 1
+#define HELLO_BEACON_SCALING_FACTOR GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
/**
- * max messages in fragment queue per MAC
+ * Maximum number of messages in defragmentation queue per MAC
*/
-#define FRAGMENT_QUEUE_MESSAGES_OUT_PER_MACENDPOINT 1
+#define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 2
/**
- * max messages in in queue
- */
-#define MESSAGES_IN_QUEUE_SIZE 10
-/**
- * max messages in in queue per session/client
- */
-#define MESSAGES_IN_DEFRAG_QUEUE_PER_MAC 1
-
-/**
- * LLC fields for better compatibility
+ * Link layer control fields for better compatibility
+ * (i.e. GNUnet over WLAN is not IP-over-WLAN).
*/
#define WLAN_LLC_DSAP_FIELD 0x1f
#define WLAN_LLC_SSAP_FIELD 0x1f
-#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */
-
-#define IEEE80211_FC0_VERSION_MASK 0x03
-#define IEEE80211_FC0_VERSION_SHIFT 0
-#define IEEE80211_FC0_VERSION_0 0x00
-#define IEEE80211_FC0_TYPE_MASK 0x0c
-#define IEEE80211_FC0_TYPE_SHIFT 2
-#define IEEE80211_FC0_TYPE_MGT 0x00
-#define IEEE80211_FC0_TYPE_CTL 0x04
-#define IEEE80211_FC0_TYPE_DATA 0x08
-
GNUNET_NETWORK_STRUCT_BEGIN
-
-/*
- * generic definitions for IEEE 802.11 frames
- */
-struct ieee80211_frame
-{
- u_int8_t i_fc[2];
- u_int8_t i_dur[2];
- u_int8_t i_addr1[IEEE80211_ADDR_LEN];
- u_int8_t i_addr2[IEEE80211_ADDR_LEN];
- u_int8_t i_addr3[IEEE80211_ADDR_LEN];
- u_int8_t i_seq[2];
- u_int8_t llc[4];
-} GNUNET_PACKED;
-GNUNET_NETWORK_STRUCT_END
-
/**
- * Encapsulation of all of the state of the plugin.
+ * Header for messages which need fragmentation. This is the format of
+ * a message we obtain AFTER defragmentation. We then need to check
+ * the CRC and then tokenize the payload and pass it to the
+ * 'receive' callback.
*/
-struct Plugin
+struct WlanHeader
{
- /**
- * Our environment.
- */
- struct GNUNET_TRANSPORT_PluginEnvironment *env;
-
- /**
- * List of open connections. head
- */
- struct MacEndpoint *mac_head;
-
- /**
- * List of open connections. tail
- */
- struct MacEndpoint *mac_tail;
-
- /**
- * Number of connections
- */
- unsigned int mac_count;
-
- /**
- * encapsulation of data from the local wlan helper program
- */
- struct GNUNET_SERVER_MessageStreamTokenizer *suid_tokenizer;
/**
- * encapsulation of packets received from the wlan helper
+ * Message type is GNUNET_MESSAGE_TYPE_WLAN_DATA.
*/
- struct GNUNET_SERVER_MessageStreamTokenizer *data_tokenizer;
+ struct GNUNET_MessageHeader header;
/**
- * stdout pipe handle for the gnunet-helper-transport-wlan process
+ * CRC32 checksum (only over the payload), in NBO.
*/
- struct GNUNET_DISK_PipeHandle *server_stdout;
+ uint32_t crc GNUNET_PACKED;
/**
- * stdout file handle for the gnunet-helper-transport-wlan process
+ * Sender of the message.
*/
- const struct GNUNET_DISK_FileHandle *server_stdout_handle;
+ struct GNUNET_PeerIdentity sender;
/**
- * stdin pipe handle for the gnunet-helper-transport-wlan process
+ * Target of the message.
*/
- struct GNUNET_DISK_PipeHandle *server_stdin;
+ struct GNUNET_PeerIdentity target;
- /**
- * stdin file handle for the gnunet-helper-transport-wlan process
- */
- const struct GNUNET_DISK_FileHandle *server_stdin_handle;
+ /* followed by payload, possibly including
+ multiple messages! */
- /**
- * ID of the gnunet-wlan-server std read task
- */
- GNUNET_SCHEDULER_TaskIdentifier server_read_task;
+};
+GNUNET_NETWORK_STRUCT_END
- /**
- * ID of the gnunet-wlan-server std read task
- */
- GNUNET_SCHEDULER_TaskIdentifier server_write_task;
+/**
+ * Information kept for each message that is yet to be fragmented and
+ * transmitted.
+ */
+struct PendingMessage
+{
/**
- * ID of the delay task for writing
+ * next entry in the DLL
*/
- GNUNET_SCHEDULER_TaskIdentifier server_write_delay_task;
+ struct PendingMessage *next;
/**
- * The process id of the wlan process
+ * previous entry in the DLL
*/
- struct GNUNET_OS_Process *server_proc;
+ struct PendingMessage *prev;
/**
- * The interface of the wlan card given to us by the user.
+ * The pending message
*/
- char *interface;
+ struct WlanHeader *msg;
/**
- * Mode of operation for the helper, 0 = normal, 1 = first loopback, 2 = second loopback
+ * Continuation function to call once the message
+ * has been sent. Can be NULL if there is no
+ * continuation to call.
*/
- long long unsigned int testmode;
+ GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
/**
- * The mac_address of the wlan card given to us by the helper.
+ * Cls for transmit_cont
*/
- struct GNUNET_TRANSPORT_WLAN_MacAddress mac_address;
+ void *transmit_cont_cls;
/**
- * Sessions currently pending for transmission
- * to a peer, if any.
+ * Timeout task (for this message).
*/
- struct Sessionqueue *pending_Sessions_head;
+ GNUNET_SCHEDULER_TaskIdentifier timeout_task;
- /**
- * Sessions currently pending for transmission
- * to a peer (tail), if any.
- */
- struct Sessionqueue *pending_Sessions_tail;
+};
- /**
- * number of pending sessions
- */
- unsigned int pendingsessions;
- /**
- * Messages in the sending queues
- */
- int pending_Fragment_Messages;
+/**
+ * Session handle for connections with other peers.
+ */
+struct Session
+{
/**
- * messages ready for send, head
- */
- struct FragmentMessage_queue *sending_messages_head;
- /**
- * messages ready for send, tail
- */
- struct FragmentMessage_queue *sending_messages_tail;
- /**
- * time of the next "hello-beacon"
+ * API requirement (must be first).
*/
- struct GNUNET_TIME_Absolute beacon_time;
+ struct SessionHeader header;
/**
- * queue to send acks for received fragments (head)
+ * We keep all sessions in a DLL at their respective
+ * 'struct MACEndpoint'.
*/
- struct AckSendQueue *ack_send_queue_head;
+ struct Session *next;
/**
- * queue to send acks for received fragments (tail)
+ * We keep all sessions in a DLL at their respective
+ * 'struct MACEndpoint'.
*/
- struct AckSendQueue *ack_send_queue_tail;
+ struct Session *prev;
/**
- * Tracker for bandwidth limit
+ * MAC endpoint with the address of this peer.
*/
- struct GNUNET_BANDWIDTH_Tracker tracker;
+ struct MacEndpoint *mac;
/**
- * saves the current state of the helper process
+ * Head of messages currently pending for transmission to this peer.
*/
- int helper_is_running;
-};
+ struct PendingMessage *pending_message_head;
-/**
- * Struct to store data if file write did not accept the whole packet
- */
-struct Finish_send
-{
/**
- * pointer to the global plugin struct
+ * Tail of messages currently pending for transmission to this peer.
*/
- struct Plugin *plugin;
+ struct PendingMessage *pending_message_tail;
/**
- * head of the next part to send to the helper
+ * To whom are we talking to (set to our identity
+ * if we are still waiting for the welcome message)
*/
- char *head_of_next_write;
+ struct GNUNET_PeerIdentity target;
/**
- * Start of the message to send, needed for free
+ * When should this session time out?
*/
- struct GNUNET_MessageHeader *msgstart;
+ struct GNUNET_TIME_Absolute timeout;
/**
- * rest size to send
+ * Timeout task (for the session).
*/
- ssize_t size;
-};
-
-/**
- * Queue of sessions, for the general session queue and the pending session queue
- */
-//TODO DOXIGEN
-struct Sessionqueue
-{
- struct Sessionqueue *next;
- struct Sessionqueue *prev;
- struct Session *content;
-#if !HAVE_UNALIGNED_64_ACCESS
- void *dummy; /* for alignment, see #1909 */
-#endif
-};
-
-/**
- * Queue of fragmented messages, for the sending queue of the plugin
- */
-//TODO DOXIGEN
-struct FragmentMessage_queue
-{
- struct FragmentMessage_queue *next;
- struct FragmentMessage_queue *prev;
- struct FragmentMessage *content;
-};
-
-/**
- * Queue for the fragments received
- */
-//TODO DOXIGEN
-struct Receive_Fragment_Queue
-{
- struct Receive_Fragment_Queue *next;
- struct Receive_Fragment_Queue *prev;
- uint16_t num;
- const char *msg;
- uint16_t size;
- struct Radiotap_rx rxinfo;
-};
-
-//TODO DOXIGEN
-struct MacEndpoint_id_fragment_triple
-{
- struct MacEndpoint *endpoint;
- uint32_t message_id;
- struct FragmentMessage *fm;
-};
+ GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-//TODO DOXIGEN
-struct Plugin_Session_pair
-{
- struct Plugin *plugin;
- struct Session *session;
};
-GNUNET_NETWORK_STRUCT_BEGIN
-
/**
- * Header for messages which need fragmentation
+ * Struct for messages that are being fragmented in a MAC's transmission queue.
*/
-struct WlanHeader
+struct FragmentMessage
{
- struct GNUNET_MessageHeader header;
-
/**
- * checksum/error correction
+ * This is a doubly-linked list.
*/
- uint32_t crc GNUNET_PACKED;
+ struct FragmentMessage *next;
/**
- * To whom are we talking to (set to our identity
- * if we are still waiting for the welcome message)
+ * This is a doubly-linked list.
*/
- struct GNUNET_PeerIdentity target;
+ struct FragmentMessage *prev;
/**
- * Where the packet came from
+ * MAC endpoint this message belongs to
*/
- struct GNUNET_PeerIdentity source;
-
-// followed by payload
-
-};
-GNUNET_NETWORK_STRUCT_END
+ struct MacEndpoint *macendpoint;
-/**
- * Information kept for each message that is yet to
- * be transmitted.
- */
-struct PendingMessage
-{
/**
- * dll next
+ * Fragmentation context
*/
- struct PendingMessage *next;
+ struct GNUNET_FRAGMENT_Context *fragcontext;
+
/**
- * dll prev
+ * Transmission handle to helper (to cancel if the frag context
+ * is destroyed early for some reason).
*/
- struct PendingMessage *prev;
+ struct GNUNET_HELPER_SendHandle *sh;
/**
- * The pending message
+ * Intended recipient.
*/
- struct WlanHeader *msg;
+ struct GNUNET_PeerIdentity target;
/**
- * Size of the message
+ * Timeout value for the message.
*/
- size_t message_size;
+ struct GNUNET_TIME_Absolute timeout;
/**
- * Continuation function to call once the message
- * has been sent. Can be NULL if there is no
- * continuation to call.
+ * Timeout task.
*/
- GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
+ GNUNET_SCHEDULER_TaskIdentifier timeout_task;
/**
- * Cls for transmit_cont
+ * Continuation to call when we're done with this message.
*/
- void *transmit_cont_cls;
+ GNUNET_TRANSPORT_TransmitContinuation cont;
/**
- * Timeout value for the pending message.
+ * Closure for 'cont'
*/
- struct GNUNET_TIME_Absolute timeout;
+ void *cont_cls;
};
+
/**
- * Queue for acks to send for fragments recived
+ * Struct to represent one network card connection
*/
-struct AckSendQueue
+struct MacEndpoint
{
/**
- * next ack in the ack send queue
+ * We keep all MACs in a DLL in the plugin.
*/
- struct AckSendQueue *next;
- /**
- * previous ack in the ack send queue
- */
- struct AckSendQueue *prev;
- /**
- * pointer to the session this ack belongs to
- */
- struct MacEndpoint *endpoint;
- /**
- * ID of message, to distinguish between the messages, picked randomly.
- */
- uint32_t message_id;
+ struct MacEndpoint *next;
/**
- * msg to send
+ * We keep all MACs in a DLL in the plugin.
*/
- struct GNUNET_MessageHeader *hdr;
- /**
- * pointer to the ieee wlan header
- */
- struct ieee80211_frame *ieeewlanheader;
+ struct MacEndpoint *prev;
+
/**
- * pointer to the radiotap header
+ * Pointer to the global plugin struct.
*/
- struct Radiotap_Send *radioHeader;
-};
+ struct Plugin *plugin;
-/**
- * Session infos gathered from a messages
- */
-struct Session_light
-{
/**
- * the session this message belongs to
+ * Head of sessions that use this MAC.
*/
- struct Session *session;
+ struct Session *sessions_head;
+
/**
- * peer mac address
+ * Tail of sessions that use this MAC.
*/
- struct GNUNET_TRANSPORT_WLAN_MacAddress addr;
+ struct Session *sessions_tail;
/**
- * mac endpoint
+ * Head of messages we are currently sending to this MAC.
*/
- struct MacEndpoint *macendpoint;
-};
-
-/**
- * Session handle for connections.
- */
-struct Session
-{
+ struct FragmentMessage *sending_messages_head;
/**
- * API requirement.
+ * Tail of messages we are currently sending to this MAC.
*/
- struct SessionHeader header;
+ struct FragmentMessage *sending_messages_tail;
/**
- * Message currently pending for transmission
- * to this peer, if any. head
+ * Defrag context for this MAC
*/
- struct PendingMessage *pending_message_head;
+ struct GNUNET_DEFRAGMENT_Context *defrag;
/**
- * Message currently pending for transmission
- * to this peer, if any. tail
+ * When should this endpoint time out?
*/
- struct PendingMessage *pending_message_tail;
+ struct GNUNET_TIME_Absolute timeout;
/**
- * To whom are we talking to (set to our identity
- * if we are still waiting for the welcome message)
+ * Timeout task.
*/
- struct GNUNET_PeerIdentity target;
+ GNUNET_SCHEDULER_TaskIdentifier timeout_task;
/**
- * Address of the other peer (either based on our 'connect'
- * call or on our 'accept' call).
+ * count of messages in the fragment out queue for this mac endpoint
*/
- void *connect_addr;
+ unsigned int fragment_messages_out_count;
/**
- * Last activity on this connection. Used to select preferred
- * connection and timeout
+ * peer mac address
*/
- struct GNUNET_TIME_Absolute last_activity;
+ struct GNUNET_TRANSPORT_WLAN_MacAddress addr;
/**
- * Timeout task.
+ * Desired transmission power for this MAC
*/
- GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+ uint16_t tx_power;
/**
- * peer connection
+ * Desired transmission rate for this MAC
*/
- struct MacEndpoint *mac;
+ uint8_t rate;
/**
- * count of messages in the fragment out queue for this session
+ * Antenna we should use for this MAC
*/
-
- int fragment_messages_out_count;
+ uint8_t antenna;
};
+
/**
- * Struct to represent one network card connection
+ * Encapsulation of all of the state of the plugin.
*/
-struct MacEndpoint
+struct Plugin
{
/**
- * Pointer to the global plugin struct.
- */
- struct Plugin *plugin;
- /**
- * Struct to hold the session reachable over this mac; head
- */
- struct Sessionqueue *sessions_head;
- /**
- * Struct to hold the session reachable over this mac; tail
- */
- struct Sessionqueue *sessions_tail;
- /**
- * Messages currently sending
- * to a peer, if any.
+ * Our environment.
*/
- struct FragmentMessage *sending_messages_head;
+ struct GNUNET_TRANSPORT_PluginEnvironment *env;
/**
- * Messages currently sending
- * to a peer (tail), if any.
- */
- struct FragmentMessage *sending_messages_tail;
- /**
- * dll next
- */
- struct MacEndpoint *next;
- /**
- * dll prev
- */
- struct MacEndpoint *prev;
+ * Handle to helper process for priviledged operations.
+ */
+ struct GNUNET_HELPER_Handle *suid_helper;
/**
- * peer mac address
+ * ARGV-vector for the helper (all helpers take only the binary
+ * name, one actual argument, plus the NULL terminator for 'argv').
*/
- struct GNUNET_TRANSPORT_WLAN_MacAddress addr;
+ char * helper_argv[3];
/**
- * Defrag context for this mac endpoint
+ * The interface of the wlan card given to us by the user.
*/
- struct GNUNET_DEFRAGMENT_Context *defrag;
+ char *interface;
/**
- * count of messages in the fragment out queue for this mac endpoint
+ * Tokenizer for demultiplexing of data packets resulting from defragmentation.
*/
-
- int fragment_messages_out_count;
-
- //TODO DOXIGEN
- uint8_t rate;
- uint16_t tx_power;
- uint8_t antenna;
+ struct GNUNET_SERVER_MessageStreamTokenizer *fragment_data_tokenizer;
/**
- * Duplicates received
+ * Tokenizer for demultiplexing of data packets received from the suid helper
*/
- int dups;
+ struct GNUNET_SERVER_MessageStreamTokenizer *helper_payload_tokenizer;
/**
- * Fragments received
+ * Tokenizer for demultiplexing of data packets that follow the WLAN Header
*/
- int fragc;
+ struct GNUNET_SERVER_MessageStreamTokenizer *wlan_header_payload_tokenizer;
/**
- * Acks received
+ * Head of list of open connections.
*/
- int acks;
+ struct MacEndpoint *mac_head;
/**
- * Last activity on this endpoint. Used to select preferred
- * connection.
+ * Tail of list of open connections.
*/
- struct GNUNET_TIME_Absolute last_activity;
+ struct MacEndpoint *mac_tail;
/**
- * Timeout task.
+ * Number of connections
*/
- GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-};
-
-/**
- * Struct for Messages in the fragment queue
- */
-struct FragmentMessage
-{
+ unsigned int mac_count;
/**
- * Session this message belongs to
+ * Task that periodically sends a HELLO beacon via the helper.
*/
- struct Session *session;
+ GNUNET_SCHEDULER_TaskIdentifier beacon_task;
/**
- * This is a doubly-linked list.
+ * Tracker for bandwidth limit
*/
- struct FragmentMessage *next;
+ struct GNUNET_BANDWIDTH_Tracker tracker;
/**
- * This is a doubly-linked list.
+ * The mac_address of the wlan card given to us by the helper.
*/
- struct FragmentMessage *prev;
+ struct GNUNET_TRANSPORT_WLAN_MacAddress mac_address;
/**
- * Fragmentation context
+ * Have we received a control message with our MAC address yet?
*/
- struct GNUNET_FRAGMENT_Context *fragcontext;
+ int have_mac;
- /**
- * Timeout value for the message.
- */
- struct GNUNET_TIME_Absolute timeout;
- /**
- * Timeout task.
- */
- GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+};
- /**
- * Fragment to send
- */
- char *frag;
+/**
+ * Information associated with a message. Can contain
+ * the session or the MAC endpoint associated with the
+ * message (or both).
+ */
+struct MacAndSession
+{
/**
- * size of message
+ * NULL if the identity of the other peer is not known.
*/
- size_t size;
+ struct Session *session;
/**
- * pointer to the ieee wlan header
+ * MAC address of the other peer, NULL if not known.
*/
- struct ieee80211_frame *ieeewlanheader;
- /**
- * pointer to the radiotap header
- */
- struct Radiotap_Send *radioHeader;
+ struct MacEndpoint *endpoint;
};
-static void
-do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-static void
-free_session (struct Plugin *plugin, struct Sessionqueue *queue,
- int do_free_macendpoint);
-
-static struct MacEndpoint *
-create_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr);
-
-static void
-finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
/**
- * Generates a nice hexdump of a memory area.
+ * Print MAC addresses nicely.
*
- * \param mem pointer to memory to dump
- * \param length how many bytes to dump
- */
-static void
-hexdump (const void *mem, unsigned length)
-{
- char line[80];
- char *src = (char *) mem;
-
- printf ("dumping %u bytes from %p\r\n"
- " 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\r\n",
- length, src);
- unsigned i;
- int j;
-
- for (i = 0; i < length; i += 16, src += 16)
- {
- char *t = line;
-
- t += sprintf (t, "%04x: ", i);
- for (j = 0; j < 16; j++)
- {
- if (i + j < length)
- t += sprintf (t, "%02X", src[j] & 0xff);
- else
- t += sprintf (t, " ");
-
- t += sprintf (t, (j % 2) ? " " : "-");
- }
-
- t += sprintf (t, " ");
- for (j = 0; j < 16; j++)
- {
- if (i + j < length)
- {
- if (isprint ((unsigned char) src[j]))
- t += sprintf (t, "%c", src[j]);
- else
- t += sprintf (t, ".");
- }
- else
- {
- t += sprintf (t, " ");
- }
- }
-
- t += sprintf (t, "\r\n");
- printf ("%s", line);
- }
-}
-
-/**
- * Function to find a MacEndpoint with a specific mac addr
- * @param plugin pointer to the plugin struct
- * @param addr pointer to the mac address
- * @param create_new GNUNET_YES if a new end point should be created
- * @return
+ * @param mac the mac address
+ * @return string to a static buffer with the human-readable mac, will be overwritten during the next call to this function
*/
-static struct MacEndpoint *
-get_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr,
- int create_new)
+static const char *
+mac_to_string (const struct GNUNET_TRANSPORT_WLAN_MacAddress * mac)
{
- struct MacEndpoint *queue = plugin->mac_head;
-
- while (queue != NULL)
- {
- //GNUNET_assert (queue->sessions_head != NULL);
- if (memcmp (addr, &queue->addr, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0)
- return queue; /* session found */
- queue = queue->next;
- }
-
- if (create_new == GNUNET_YES)
- {
- return create_macendpoint (plugin, addr);
- }
- else
- {
- return NULL;
- }
+ static char macstr[20];
+ GNUNET_snprintf (macstr, sizeof (macstr), "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", mac->mac[0], mac->mac[1],
+ mac->mac[2], mac->mac[3], mac->mac[4], mac->mac[5]);
+ return macstr;
}
-/**
- * search for a session with the macendpoint and peer id
- *
- * @param plugin pointer to the plugin struct
- * @param endpoint pointer to the mac endpoint of the peer
- * @param peer pointer to the peerid
- * @return returns the session
- */
-static struct Session *
-search_session (struct Plugin *plugin, const struct MacEndpoint *endpoint,
- const struct GNUNET_PeerIdentity *peer)
-{
- GNUNET_assert (endpoint != NULL);
- struct Sessionqueue *queue = endpoint->sessions_head;
-
- while (queue != NULL)
- {
- GNUNET_assert (queue->content != NULL);
- if (memcmp
- (peer, &queue->content->target,
- sizeof (struct GNUNET_PeerIdentity)) == 0)
- return queue->content; /* session found */
- queue = queue->next;
- }
- return NULL;
-}
/**
- * Function called for a quick conversion of the binary address to
- * a numeric address. Note that the caller must not free the
- * address and that the next call to this function is allowed
- * to override the address again.
+ * Fill the radiotap header
*
- * @param cls closure
- * @param addr binary address
- * @param addrlen length of the address
- * @return string representing the same address
- */
-static const char *
-wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
-{
- static char ret[40];
- const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac;
-
- if (addrlen != sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))
- {
- GNUNET_break (0);
- return NULL;
- }
- mac = addr;
- GNUNET_snprintf (ret, sizeof (ret), "%s Mac-Address %X:%X:%X:%X:%X:%X",
- PROTOCOL_PREFIX, mac->mac[0], mac->mac[1], mac->mac[2],
- mac->mac[3], mac->mac[4], mac->mac[5]);
-
- return ret;
-}
-
-/**
- * Function for the scheduler if a session times out
- * @param cls pointer to the Sessionqueue
- * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
+ * @param endpoint pointer to the endpoint, can be NULL
+ * @param header pointer to the radiotap header
+ * @param size total message size
*/
static void
-session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+get_radiotap_header (struct MacEndpoint *endpoint,
+ struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header,
+ uint16_t size)
{
- struct Sessionqueue *queue = cls;
-
- GNUNET_assert (queue != NULL);
- GNUNET_assert (queue->content != NULL);
- queue->content->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ header->header.type = ntohs (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER);
+ header->header.size = ntohs (size);
+ if (NULL != endpoint)
{
- return;
- }
- if (GNUNET_TIME_absolute_get_remaining
- (GNUNET_TIME_absolute_add
- (queue->content->last_activity, SESSION_TIMEOUT)).rel_value == 0)
- {
-
- GNUNET_assert (queue->content->mac != NULL);
- GNUNET_assert (queue->content->mac->plugin != NULL);
- GNUNET_STATISTICS_update (queue->content->mac->plugin->env->stats,
- _("# wlan session timeouts"), 1, GNUNET_NO);
- free_session (queue->content->mac->plugin, queue, GNUNET_YES);
+ header->rate = endpoint->rate;
+ header->tx_power = endpoint->tx_power;
+ header->antenna = endpoint->antenna;
}
else
{
- queue->content->timeout_task =
- GNUNET_SCHEDULER_add_delayed (SESSION_TIMEOUT, &session_timeout, queue);
+ header->rate = 255;
+ header->tx_power = 0;
+ header->antenna = 0;
}
}
-/**
- * create a new session
- *
- * @param plugin pointer to the plugin struct
- * @param endpoint pointer to the mac endpoint of the peer
- * @param peer peer identity to use for this session
- * @return returns the session
- */
-static struct Session *
-create_session (struct Plugin *plugin, struct MacEndpoint *endpoint,
- const struct GNUNET_PeerIdentity *peer)
-{
- GNUNET_assert (endpoint != NULL);
- GNUNET_assert (plugin != NULL);
- GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan session created"), 1,
- GNUNET_NO);
- struct Sessionqueue *queue =
- GNUNET_malloc (sizeof (struct Sessionqueue) + sizeof (struct Session));
-
- GNUNET_CONTAINER_DLL_insert_tail (endpoint->sessions_head,
- endpoint->sessions_tail, queue);
-
- queue->content = (struct Session *) &queue[1];
- queue->content->mac = endpoint;
- queue->content->target = *peer;
- queue->content->last_activity = GNUNET_TIME_absolute_get ();
- queue->content->timeout_task =
- GNUNET_SCHEDULER_add_delayed (SESSION_TIMEOUT, &session_timeout, queue);
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "New session %p with endpoint %p: %s\n", queue->content,
- endpoint, wlan_plugin_address_to_string (NULL,
- endpoint->addr.mac,
- 6));
- return queue->content;
-}
/**
- * Get session from address, create if no session exists
+ * Generate the WLAN hardware header for one packet
*
- * @param plugin pointer to the plugin struct
- * @param addr pointer to the mac address of the peer
- * @param peer pointer to the peerid
- * @return returns the session
- */
-static struct Session *
-get_session (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr,
- const struct GNUNET_PeerIdentity *peer)
-{
- struct MacEndpoint *mac;
-
- mac = get_macendpoint (plugin, addr, GNUNET_YES);
- struct Session *session = search_session (plugin, mac, peer);
-
- if (session != NULL)
- return session;
- return create_session (plugin, mac, peer);
-}
-
-/**
- * Queue the session to send data
- * checks if there is a message pending
- * checks if this session is not allready in the queue
- * @param plugin pointer to the plugin
- * @param session pointer to the session to add
+ * @param plugin the plugin handle
+ * @param header address to write the header to
+ * @param to_mac_addr address of the recipient
+ * @param size size of the whole packet, needed to calculate the time to send the packet
*/
static void
-queue_session (struct Plugin *plugin, struct Session *session)
+get_wlan_header (struct Plugin *plugin,
+ struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *header,
+ const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr,
+ unsigned int size)
{
- struct Sessionqueue *queue = plugin->pending_Sessions_head;
-
- if (session->pending_message_head != NULL)
- {
- while (queue != NULL)
- {
- // content is never NULL
- GNUNET_assert (queue->content != NULL);
- // is session already in queue?
- if (session == queue->content)
- {
- return;
- }
- // try next
- queue = queue->next;
- }
-
- // Session is not in the queue
-
- queue = GNUNET_malloc (sizeof (struct Sessionqueue));
- queue->content = session;
-
- //insert at the tail
- GNUNET_CONTAINER_DLL_insert_tail (plugin->pending_Sessions_head,
- plugin->pending_Sessions_tail, queue);
- plugin->pendingsessions++;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
- plugin->pendingsessions, GNUNET_NO);
- }
+ const int rate = 11000000;
+ header->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
+ header->addr1 = *to_mac_addr;
+ header->addr2 = plugin->mac_address;
+ header->addr3 = mac_bssid_gnunet;
+ header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290);
+ header->sequence_control = 0; // FIXME?
+ header->llc[0] = WLAN_LLC_DSAP_FIELD;
+ header->llc[1] = WLAN_LLC_SSAP_FIELD;
+ header->llc[2] = 0; // FIXME?
+ header->llc[3] = 0; // FIXME?
}
+
/**
- * Function to schedule the write task, executed after a delay
- * @param cls pointer to the plugin struct
- * @param tc GNUNET_SCHEDULER_TaskContext pointer
+ * Send an ACK for a fragment we received.
+ *
+ * @param cls the 'struct MacEndpoint' the ACK must be sent to
+ * @param msg_id id of the message
+ * @param hdr pointer to the hdr where the ack is stored
*/
static void
-delay_fragment_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+send_ack (void *cls, uint32_t msg_id,
+ const struct GNUNET_MessageHeader *hdr)
{
- struct Plugin *plugin = cls;
-
- plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
-
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
+ struct MacEndpoint *endpoint = cls;
+ struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage* radio_header;
+ uint16_t msize = ntohs (hdr->size);
+ size_t size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize;
+ char buf[size];
- // GNUNET_TIME_UNIT_FOREVER_REL is needed to clean up old msg
- if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
+ if (size >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
{
- plugin->server_write_task =
- GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->server_stdin_handle,
- &do_transmit, plugin);
+ GNUNET_break (0);
+ return;
}
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending ACK to helper\n");
+ radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf;
+ get_radiotap_header (endpoint, radio_header, size);
+ get_wlan_header (endpoint->plugin,
+ &radio_header->frame,
+ &endpoint->addr,
+ size);
+ memcpy (&radio_header[1], hdr, msize);
+ if (NULL !=
+ GNUNET_HELPER_send (endpoint->plugin->suid_helper,
+ &radio_header->header,
+ GNUNET_NO /* dropping ACKs is bad */,
+ NULL, NULL))
+ GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN ACKs sent"),
+ 1, GNUNET_NO);
}
-/**
- * Function to calculate the time of the next periodic "hello-beacon"
- * @param plugin pointer to the plugin struct
- */
-static void
-set_next_beacon_time (struct Plugin *const plugin)
-{
- //under 10 known peers: once a second
- if (plugin->mac_count < 10)
- {
- plugin->beacon_time =
- GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
- GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS,
- HELLO_BEACON_SCALING_FACTOR));
- }
- //under 30 known peers: every 10 seconds
- else if (plugin->mac_count < 30)
- {
- plugin->beacon_time =
- GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
- GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS,
- 10 * HELLO_BEACON_SCALING_FACTOR));
- }
- //over 30 known peers: once a minute
- else
- {
- plugin->beacon_time =
- GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
- GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MINUTES,
- HELLO_BEACON_SCALING_FACTOR));
- }
-}
/**
- * Function to set the timer for the next timeout of the fragment queue
- * @param plugin the handle to the plugin struct
+ * Handles the data after all fragments are put together
+ *
+ * @param cls macendpoint this messages belongs to
+ * @param hdr pointer to the data
*/
static void
-set_next_send (struct Plugin *const plugin)
+wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
{
- struct GNUNET_TIME_Relative next_send;
-
- //abort if helper is not running
- if (plugin->helper_is_running == GNUNET_NO)
- {
- return;
- }
-
- //cancel old task
- if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task);
- plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
- }
-
- //check if some acks are in the queue
- if (plugin->ack_send_queue_head != NULL)
- {
- next_send = GNUNET_TIME_UNIT_ZERO;
- }
-
- //check if there are some fragments in the queue
- else if (plugin->sending_messages_head != NULL)
- {
- next_send = GNUNET_TIME_UNIT_ZERO;
- }
- else
- {
- next_send = GNUNET_TIME_absolute_get_remaining (plugin->beacon_time);
- }
+ struct MacEndpoint *endpoint = cls;
+ struct Plugin *plugin = endpoint->plugin;
+ struct MacAndSession mas;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Next packet is send in: %u\n", next_send.rel_value);
- if (next_send.rel_value == GNUNET_TIME_UNIT_ZERO.rel_value)
- {
- if (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK)
- {
- plugin->server_write_task =
- GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->server_stdin_handle,
- &do_transmit, plugin);
- }
- }
- else
- {
- if (plugin->server_write_delay_task == GNUNET_SCHEDULER_NO_TASK)
- {
- plugin->server_write_delay_task =
- GNUNET_SCHEDULER_add_delayed (next_send, &delay_fragment_task,
- plugin);
- }
- }
+ GNUNET_STATISTICS_update (plugin->env->stats,
+ _("# WLAN messages defragmented"), 1,
+ GNUNET_NO);
+ mas.session = NULL;
+ mas.endpoint = endpoint;
+ (void) GNUNET_SERVER_mst_receive (plugin->fragment_data_tokenizer,
+ &mas,
+ (const char *) hdr,
+ ntohs (hdr->size),
+ GNUNET_YES, GNUNET_NO);
}
-/**
- * Function to get the next queued Session, removes the session from the queue
- * @param plugin pointer to the plugin struct
- * @return pointer to the session found, returns NULL if there is now session in the queue
- */
-static struct Session *
-get_next_queue_session (struct Plugin *plugin)
-{
- struct Session *session;
- struct Sessionqueue *sessionqueue;
- struct Sessionqueue *sessionqueue_alt;
- struct PendingMessage *pm;
-
- sessionqueue = plugin->pending_Sessions_head;
-
- while (sessionqueue != NULL)
- {
- session = sessionqueue->content;
-
- GNUNET_assert (session != NULL);
- pm = session->pending_message_head;
-
- if (pm == NULL)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- "pending message is empty, should not happen. session %p\n",
- session);
- sessionqueue_alt = sessionqueue;
- sessionqueue = sessionqueue->next;
- plugin->pendingsessions--;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
- plugin->pendingsessions, GNUNET_NO);
- GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
- plugin->pending_Sessions_tail,
- sessionqueue_alt);
-
- GNUNET_free (sessionqueue_alt);
- continue;
-
- }
-
- //check for message timeout
- if (GNUNET_TIME_absolute_get_remaining (pm->timeout).rel_value > 0)
- {
- //check if session has no message in the fragment queue
- if ((session->mac->fragment_messages_out_count <
- FRAGMENT_QUEUE_MESSAGES_OUT_PER_MACENDPOINT) &&
- (session->fragment_messages_out_count <
- FRAGMENT_QUEUE_MESSAGES_OUT_PER_SESSION))
- {
- plugin->pendingsessions--;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
- plugin->pendingsessions, GNUNET_NO);
- GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
- plugin->pending_Sessions_tail,
- sessionqueue);
- GNUNET_free (sessionqueue);
-
- return session;
- }
- else
- {
- sessionqueue = sessionqueue->next;
- }
- }
- else
- {
- GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
- session->pending_message_tail, pm);
-
- //call the cont func that it did not work
- if (pm->transmit_cont != NULL)
- pm->transmit_cont (pm->transmit_cont_cls, &(session->target),
- GNUNET_SYSERR);
- GNUNET_free (pm->msg);
- GNUNET_free (pm);
-
- if (session->pending_message_head == NULL)
- {
- sessionqueue_alt = sessionqueue;
- sessionqueue = sessionqueue->next;
- plugin->pendingsessions--;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
- plugin->pendingsessions, GNUNET_NO);
- GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
- plugin->pending_Sessions_tail,
- sessionqueue_alt);
-
- GNUNET_free (sessionqueue_alt);
- }
- }
-
- }
- return NULL;
-}
/**
- * frees the space of a message in the fragment queue (send queue)
- * @param plugin the plugin struct
- * @param fm message to free
+ * Free a session
+ *
+ * @param session the session free
*/
static void
-free_fragment_message (struct Plugin *plugin, struct FragmentMessage *fm)
+free_session (struct Session *session)
{
- struct Session *session = fm->session;
struct MacEndpoint *endpoint = session->mac;
- struct FragmentMessage_queue *fmq;
- struct FragmentMessage_queue *fmq_next;
-
- fmq = plugin->sending_messages_head;
- while (fmq != NULL)
- {
- fmq_next = fmq->next;
- if (fmq->content == fm)
+ struct PendingMessage *pm;
+
+ endpoint->plugin->env->session_end (endpoint->plugin->env->cls,
+ &session->target,
+ session);
+ while (NULL != (pm = session->pending_message_head))
+ {
+ GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
+ session->pending_message_tail, pm);
+ if (GNUNET_SCHEDULER_NO_TASK != pm->timeout_task)
{
- GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
- plugin->sending_messages_tail, fmq);
- GNUNET_free (fmq);
+ GNUNET_SCHEDULER_cancel (pm->timeout_task);
+ pm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
}
- fmq = fmq_next;
- }
-
- (session->mac->fragment_messages_out_count)--;
- session->fragment_messages_out_count--;
- plugin->pending_Fragment_Messages--;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
- plugin->pending_Fragment_Messages, GNUNET_NO);
- GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head,
- endpoint->sending_messages_tail, fm);
- GNUNET_FRAGMENT_context_destroy (fm->fragcontext);
- if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (fm->timeout_task);
- fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- }
-
- GNUNET_free (fm);
-
- queue_session (plugin, session);
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Free pending fragment messages %p, session %p\n", fm,
- session);
-}
-
-/**
- * function to fill the radiotap header
- * @param plugin pointer to the plugin struct
- * @param endpoint pointer to the endpoint
- * @param header pointer to the radiotap header
- * @return GNUNET_YES at success
- */
-static int
-getRadiotapHeader (struct Plugin *plugin, struct MacEndpoint *endpoint,
- struct Radiotap_Send *header)
-{
-
- if (endpoint != NULL)
- {
- header->rate = endpoint->rate;
- header->tx_power = endpoint->tx_power;
- header->antenna = endpoint->antenna;
+ GNUNET_free (pm->msg);
+ GNUNET_free (pm);
}
- else
+ GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head,
+ endpoint->sessions_tail,
+ session);
+ if (session->timeout_task != GNUNET_SCHEDULER_NO_TASK)
{
- header->rate = 255;
- header->tx_power = 0;
- header->antenna = 0;
+ GNUNET_SCHEDULER_cancel (session->timeout_task);
+ session->timeout_task = GNUNET_SCHEDULER_NO_TASK;
}
-
- return GNUNET_YES;
-}
-
-/**
- * function to generate the wlan hardware header for one packet
- * @param Header address to write the header to
- * @param to_mac_addr address of the recipient
- * @param plugin pointer to the plugin struct
- * @param size size of the whole packet, needed to calculate the time to send the packet
- * @return GNUNET_YES if there was no error
- */
-static int
-getWlanHeader (struct ieee80211_frame *Header,
- const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr, struct Plugin *plugin,
- unsigned int size)
-{
- uint16_t *tmp16;
- const int rate = 11000000;
-
- Header->i_fc[0] = IEEE80211_FC0_TYPE_DATA;
- Header->i_fc[1] = 0x00;
- memcpy (&Header->i_addr3, &mac_bssid_gnunet, sizeof (mac_bssid_gnunet));
- memcpy (&Header->i_addr2, plugin->mac_address.mac,
- sizeof (plugin->mac_address));
- memcpy (&Header->i_addr1, to_mac_addr, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
-
- tmp16 = (uint16_t *) Header->i_dur;
- *tmp16 = (uint16_t) GNUNET_htole16 ((size * 1000000) / rate + 290);
- Header->llc[0] = WLAN_LLC_DSAP_FIELD;
- Header->llc[1] = WLAN_LLC_SSAP_FIELD;
-
- return GNUNET_YES;
-}
-
-
-/**
- * function to add a fragment of a message to send
- * @param cls FragmentMessage this message belongs to
- * @param hdr pointer to the start of the message
- */
-static void
-add_message_for_send (void *cls, const struct GNUNET_MessageHeader *hdr)
-{
-
- struct FragmentMessage *fm = cls;
- struct FragmentMessage_queue *fmqueue;
-
- GNUNET_assert (cls != NULL);
- GNUNET_assert (fm->frag == NULL);
- struct MacEndpoint *endpoint = fm->session->mac;
- struct Plugin *plugin = endpoint->plugin;
- struct GNUNET_MessageHeader *msgheader;
- struct GNUNET_MessageHeader *msgheader2;
- uint16_t size;
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Adding fragment of message %p to send, session %p, endpoint %p, type %u\n",
- fm, fm->session, endpoint, hdr->type);
- size =
- sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
- sizeof (struct ieee80211_frame) + ntohs (hdr->size);
- fm->frag = GNUNET_malloc (size);
- fm->size = size;
-
- msgheader = (struct GNUNET_MessageHeader *) fm->frag;
- msgheader->size = htons (size);
- msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
-
- fm->radioHeader = (struct Radiotap_Send *) &msgheader[1];
- fm->ieeewlanheader = (struct ieee80211_frame *) &fm->radioHeader[1];
- msgheader2 = (struct GNUNET_MessageHeader *) &fm->ieeewlanheader[1];
- memcpy (msgheader2, hdr, ntohs (hdr->size));
-
- fmqueue = GNUNET_malloc (sizeof (struct FragmentMessage_queue));
- fmqueue->content = fm;
-
- GNUNET_CONTAINER_DLL_insert_tail (plugin->sending_messages_head,
- plugin->sending_messages_tail, fmqueue);
- set_next_send (plugin);
+ GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN sessions allocated"), -1,
+ GNUNET_NO);
+ GNUNET_free (session);
}
/**
- * We have been notified that gnunet-helper-transport-wlan has written something to stdout.
- * Handle the output, then reschedule this function to be called again once
- * more is available.
+ * A session is timing out. Clean up.
*
- * @param cls the plugin handle
- * @param tc the scheduling context
+ * @param cls pointer to the Session
+ * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
*/
static void
-wlan_plugin_helper_read (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct Plugin *plugin = cls;
-
- plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
+ struct Session * session = cls;
+ struct GNUNET_TIME_Relative timeout;
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
-
- char mybuf[WLAN_MTU + sizeof (struct GNUNET_MessageHeader)];
- ssize_t bytes;
-
- bytes =
- GNUNET_DISK_file_read (plugin->server_stdout_handle, mybuf,
- sizeof (mybuf));
- if (bytes <= 0)
+ session->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ timeout = GNUNET_TIME_absolute_get_remaining (session->timeout);
+ if (0 == timeout.rel_value)
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- _
- ("Finished reading from gnunet-helper-transport-wlan stdout with code: %d\n"),
- bytes);
+ free_session (session);
return;
}
- GNUNET_SERVER_mst_receive (plugin->suid_tokenizer, NULL, mybuf, bytes,
- GNUNET_NO, GNUNET_NO);
-
- GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
- plugin->server_read_task =
- GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->server_stdout_handle,
- &wlan_plugin_helper_read, plugin);
+ session->timeout_task =
+ GNUNET_SCHEDULER_add_delayed (timeout, &session_timeout, session);
}
+
/**
- * Start the gnunet-helper-transport-wlan process.
+ * Create a new session
*
- * @param plugin the transport plugin
- * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
+ * @param endpoint pointer to the mac endpoint of the peer
+ * @param peer peer identity to use for this session
+ * @return returns the session
*/
-static int
-wlan_transport_start_wlan_helper (struct Plugin *plugin)
+static struct Session *
+create_session (struct MacEndpoint *endpoint,
+ const struct GNUNET_PeerIdentity *peer)
{
- const char *filenamehw = "gnunet-helper-transport-wlan";
- const char *filenameloopback = "gnunet-helper-transport-wlan-dummy";
- char *absolute_filename = NULL;
-
- if (plugin->helper_is_running == GNUNET_YES)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "wlan_transport_start_wlan_helper not needed, helper already running!");
- return GNUNET_YES;
- }
-
- plugin->server_stdout = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_NO, GNUNET_YES);
- if (plugin->server_stdout == NULL)
- return GNUNET_SYSERR;
-
- plugin->server_stdin = GNUNET_DISK_pipe (GNUNET_YES, GNUNET_YES, GNUNET_YES, GNUNET_NO);
- if (plugin->server_stdin == NULL)
- return GNUNET_SYSERR;
-
- if ((plugin->testmode == 1) || (plugin->testmode == 2))
- {
- if (GNUNET_OS_check_helper_binary (filenameloopback) == GNUNET_YES)
- {
- absolute_filename = GNUNET_strdup (filenameloopback);
- }
- else
- {
- char cwd[FILENAME_MAX];
-
- GNUNET_assert (getcwd (cwd, sizeof (cwd)) != NULL);
-
- GNUNET_asprintf (&absolute_filename, "%s%s%s", cwd, DIR_SEPARATOR_STR,
- filenameloopback);
-
- if (GNUNET_DISK_file_test (filenameloopback) != GNUNET_YES)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- "Helper `%s' not found! %i\n", absolute_filename);
- GNUNET_break (0);
- }
- }
- }
-
- /* Start the server process */
-
- if (plugin->testmode == 0)
- {
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Starting gnunet-helper-transport-wlan process cmd: %s %s %i\n",
- filenamehw, plugin->interface, plugin->testmode);
- if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_YES)
- {
- plugin->server_proc =
- GNUNET_OS_start_process (GNUNET_NO, plugin->server_stdin, plugin->server_stdout,
- filenamehw, filenamehw, plugin->interface,
- NULL);
- }
- else if (GNUNET_OS_check_helper_binary (filenamehw) == GNUNET_NO)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- "gnunet-helper-transport-wlan is not suid, please change it or look at the doku\n");
- GNUNET_break (0);
- }
- else
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- "gnunet-helper-transport-wlan not found, please look if it exists and is the $PATH variable!\n");
- GNUNET_break (0);
- }
-
- }
- else if (plugin->testmode == 1)
- {
+ struct Session *session;
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
- "Starting gnunet-helper-transport-wlan-dummy loopback 1 process cmd: %s %s %i\n",
- absolute_filename, plugin->interface, plugin->testmode);
- plugin->server_proc =
- GNUNET_OS_start_process (GNUNET_NO, plugin->server_stdin, plugin->server_stdout,
- absolute_filename, absolute_filename, "1",
- NULL);
- if (plugin->server_proc == NULL)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- "`%s' not found, please look if it exists and is in the $PATH variable!\n",
- absolute_filename);
- GNUNET_break (0);
- }
- }
- else if (plugin->testmode == 2)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
- "Starting gnunet-helper-transport-wlan-dummy loopback 2 process cmd: %s %s %i\n",
- absolute_filename, plugin->interface, plugin->testmode);
- plugin->server_proc =
- GNUNET_OS_start_process (GNUNET_NO, plugin->server_stdin, plugin->server_stdout,
- absolute_filename, absolute_filename, "2",
- NULL);
- if (plugin->server_proc == NULL)
+ for (session = endpoint->sessions_head; NULL != session; session = session->next)
+ if (0 == memcmp (peer, &session->target,
+ sizeof (struct GNUNET_PeerIdentity)))
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- "`%s' not found, please look if it exists and is in the $PATH variable!\n",
- absolute_filename);
- GNUNET_break (0);
+ session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+ return session;
}
- }
- if (absolute_filename != NULL)
- GNUNET_free (absolute_filename);
- if (plugin->server_proc == NULL)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Failed to start gnunet-helper-transport-wlan process\n");
- return GNUNET_SYSERR;
- }
-
-
-
- /* Close the write end of the read pipe */
- GNUNET_DISK_pipe_close_end (plugin->server_stdout,
- GNUNET_DISK_PIPE_END_WRITE);
-
- /* Close the read end of the write pipe */
- GNUNET_DISK_pipe_close_end (plugin->server_stdin, GNUNET_DISK_PIPE_END_READ);
-
- plugin->server_stdout_handle =
- GNUNET_DISK_pipe_handle (plugin->server_stdout,
- GNUNET_DISK_PIPE_END_READ);
- plugin->server_stdin_handle =
- GNUNET_DISK_pipe_handle (plugin->server_stdin,
- GNUNET_DISK_PIPE_END_WRITE);
-
- GNUNET_assert (plugin->server_read_task == GNUNET_SCHEDULER_NO_TASK);
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Adding server_read_task for the gnunet-helper-transport-wlan\n");
- plugin->server_read_task =
- GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->server_stdout_handle,
- &wlan_plugin_helper_read, plugin);
-
- plugin->helper_is_running = GNUNET_YES;
- return GNUNET_YES;
+ GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN sessions allocated"), 1,
+ GNUNET_NO);
+ session = GNUNET_malloc (sizeof (struct Session));
+ GNUNET_CONTAINER_DLL_insert_tail (endpoint->sessions_head,
+ endpoint->sessions_tail,
+ session);
+ session->mac = endpoint;
+ session->target = *peer;
+ session->timeout = GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+ session->timeout_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, &session_timeout, session);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Created new session for peer `%s' with endpoint %s\n",
+ GNUNET_i2s (peer),
+ mac_to_string (&endpoint->addr));
+ return session;
}
-/**
- * Stops the gnunet-helper-transport-wlan process.
- *
- * @param plugin the transport plugin
- * @return GNUNET_YES if process was started, GNUNET_SYSERR on error
- */
-static int
-wlan_transport_stop_wlan_helper (struct Plugin *plugin)
-{
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Stoping WLAN helper process\n");
-
- if (plugin->helper_is_running == GNUNET_NO)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "wlan_transport_stop_wlan_helper not needed, helper already stopped!");
- return GNUNET_YES;
- }
-
- if (plugin->server_write_delay_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (plugin->server_write_delay_task);
- plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
- }
-
- if (plugin->server_write_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (plugin->server_write_task);
- plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
- }
-
- if (plugin->server_read_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (plugin->server_read_task);
- plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
- }
-
- GNUNET_DISK_pipe_close (plugin->server_stdout);
- GNUNET_DISK_pipe_close (plugin->server_stdin);
- GNUNET_OS_process_kill (plugin->server_proc, SIGKILL);
- GNUNET_OS_process_wait (plugin->server_proc);
- GNUNET_OS_process_close (plugin->server_proc);
-
- plugin->helper_is_running = GNUNET_NO;
-
- return GNUNET_YES;
-}
/**
- * function for delayed restart of the helper process
- * @param cls Finish_send struct if message should be finished
- * @param tc TaskContext
+ * Function called once we have successfully given the fragment
+ * message to the SUID helper process and we are thus ready for
+ * the next fragment.
+ *
+ * @param cls the 'struct FragmentMessage'
+ * @param result result of the operation (GNUNET_OK on success, GNUNET_NO if the helper died, GNUNET_SYSERR
+ * if the helper was stopped)
*/
static void
-delay_restart_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+fragment_transmission_done (void *cls,
+ int result)
{
- struct Finish_send *finish = cls;
- struct Plugin *plugin;
-
- plugin = finish->plugin;
-
- plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
- if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
- {
- GNUNET_free_non_null (finish->msgstart);
- GNUNET_free (finish);
- return;
- }
-
- wlan_transport_start_wlan_helper (plugin);
-
- if (finish->size != 0)
- {
- plugin->server_write_task =
- GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->server_stdin_handle,
- &finish_sending, finish);
- }
- else
- {
- set_next_send (plugin);
- GNUNET_free_non_null (finish->msgstart);
- GNUNET_free (finish);
- }
+ struct FragmentMessage *fm = cls;
+ fm->sh = NULL;
+ GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
}
-/**
- * Function to restart the helper
- * @param plugin pointer to the global plugin struct
- * @param finish pointer to the Finish_send struct to finish
- */
-static void
-restart_helper (struct Plugin *plugin, struct Finish_send *finish)
-{
- static struct GNUNET_TIME_Relative next_try = { 1000 };
- GNUNET_assert (finish != NULL);
-
- wlan_transport_stop_wlan_helper (plugin);
- plugin->server_write_task =
- GNUNET_SCHEDULER_add_delayed (next_try, &delay_restart_helper, finish);
- GNUNET_TIME_relative_multiply (next_try, HELPER_RESTART_SCALING_FACTOR);
-
-}
/**
- * function to finish a sending if not all could have been writen befor
- * @param cls pointer to the Finish_send struct
- * @param tc TaskContext
+ * Transmit a fragment of a message.
+ *
+ * @param cls 'struct FragmentMessage' this fragment message belongs to
+ * @param hdr pointer to the start of the fragment message
*/
static void
-finish_sending (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+transmit_fragment (void *cls,
+ const struct GNUNET_MessageHeader *hdr)
{
- struct Finish_send *finish = cls;
- struct Plugin *plugin;
- ssize_t bytes;
-
- plugin = finish->plugin;
- plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
-
- if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
- {
- GNUNET_free (finish->msgstart);
- GNUNET_free (finish);
- return;
- }
- bytes =
- GNUNET_DISK_file_write (plugin->server_stdin_handle,
- finish->head_of_next_write, finish->size);
-
- if (bytes != finish->size)
- {
- if (bytes != GNUNET_SYSERR)
- {
- finish->head_of_next_write += bytes;
- finish->size -= bytes;
- plugin->server_write_task =
- GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->server_stdin_handle,
- &finish_sending, finish);
- }
+ struct FragmentMessage *fm = cls;
+ struct MacEndpoint *endpoint = fm->macendpoint;
+ size_t size;
+ uint16_t msize;
+
+ msize = ntohs (hdr->size);
+ size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + msize;
+ {
+ char buf[size];
+ struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radio_header;
+
+ radio_header = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) buf;
+ get_radiotap_header (endpoint, radio_header, size);
+ get_wlan_header (endpoint->plugin,
+ &radio_header->frame,
+ &endpoint->addr,
+ size);
+ memcpy (&radio_header[1], hdr, msize);
+ GNUNET_assert (NULL == fm->sh);
+ fm->sh = GNUNET_HELPER_send (endpoint->plugin->suid_helper,
+ &radio_header->header,
+ GNUNET_NO,
+ &fragment_transmission_done, fm);
+ if (NULL != fm->sh)
+ GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN message fragments sent"),
+ 1, GNUNET_NO);
else
- {
- restart_helper (plugin, finish);
- }
- }
- else
- {
- GNUNET_free (finish->msgstart);
- GNUNET_free (finish);
- set_next_send (plugin);
+ GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
}
}
+
/**
- * function to send a hello beacon
- * @param plugin pointer to the plugin struct
+ * Frees the space of a message in the fragment queue (send queue)
+ *
+ * @param fm message to free
*/
static void
-send_hello_beacon (struct Plugin *plugin)
+free_fragment_message (struct FragmentMessage *fm)
{
- uint16_t size;
- ssize_t bytes;
- uint16_t hello_size;
- struct GNUNET_MessageHeader *msgheader;
- struct ieee80211_frame *ieeewlanheader;
- struct Radiotap_Send *radioHeader;
- struct GNUNET_MessageHeader *msgheader2;
- const struct GNUNET_MessageHeader *hello;
- struct Finish_send *finish;
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Sending hello beacon\n");
-
- GNUNET_assert (plugin != NULL);
+ struct MacEndpoint *endpoint = fm->macendpoint;
- GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan hello beacons send"),
- 1, GNUNET_NO);
-
- hello = plugin->env->get_our_hello ();
- hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
- GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU);
- size =
- sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
- sizeof (struct ieee80211_frame) + hello_size;
-
- msgheader = GNUNET_malloc (size);
- msgheader->size = htons (size);
- msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
-
- radioHeader = (struct Radiotap_Send *) &msgheader[1];
- getRadiotapHeader (plugin, NULL, radioHeader);
- ieeewlanheader = (struct ieee80211_frame *) &radioHeader[1];
- getWlanHeader (ieeewlanheader, &bc_all_mac, plugin, size);
-
- msgheader2 = (struct GNUNET_MessageHeader *) &ieeewlanheader[1];
- /*msgheader2->size =
- * htons (GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello) +
- * sizeof (struct GNUNET_MessageHeader));
- *
- * msgheader2->type = htons (GNUNET_MESSAGE_TYPE_WLAN_ADVERTISEMENT); */
- memcpy (msgheader2, hello, hello_size);
-
- bytes = GNUNET_DISK_file_write (plugin->server_stdin_handle, msgheader, size);
-
- if (bytes == GNUNET_SYSERR)
+ GNUNET_STATISTICS_update (endpoint->plugin->env->stats, _("# WLAN messages pending (with fragmentation)"),
+ -1, GNUNET_NO);
+ GNUNET_CONTAINER_DLL_remove (endpoint->sending_messages_head,
+ endpoint->sending_messages_tail, fm);
+ if (NULL != fm->sh)
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- _
- ("Error writing to wlan helper. errno == %d, ERROR: %s\n"),
- errno, strerror (errno));
- finish = GNUNET_malloc (sizeof (struct Finish_send));
- finish->plugin = plugin;
- finish->head_of_next_write = NULL;
- finish->size = 0;
- finish->msgstart = NULL;
- restart_helper (plugin, finish);
-
- set_next_beacon_time (plugin);
-
+ GNUNET_HELPER_send_cancel (fm->sh);
+ fm->sh = NULL;
}
- else
+ GNUNET_FRAGMENT_context_destroy (fm->fragcontext);
+ if (fm->timeout_task != GNUNET_SCHEDULER_NO_TASK)
{
- GNUNET_assert (bytes == size);
- set_next_beacon_time (plugin);
- set_next_send (plugin);
+ GNUNET_SCHEDULER_cancel (fm->timeout_task);
+ fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
}
- GNUNET_free (msgheader);
-
-
+ GNUNET_free (fm);
}
-/**
- * function to add an ack to send it for a received fragment
- * @param cls MacEndpoint this ack belongs to
- * @param msg_id id of the message
- * @param hdr pointer to the hdr where the ack is stored
- *
- */
-static void
-add_ack_for_send (void *cls, uint32_t msg_id,
- const struct GNUNET_MessageHeader *hdr)
-{
-
- struct AckSendQueue *ack;
-
- GNUNET_assert (cls != NULL);
- struct MacEndpoint *endpoint = cls;
- struct Plugin *plugin = endpoint->plugin;
- struct GNUNET_MessageHeader *msgheader;
- struct GNUNET_MessageHeader *msgheader2;
- uint16_t size;
-
- size =
- sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
- sizeof (struct ieee80211_frame) + ntohs (hdr->size) +
- sizeof (struct AckSendQueue);
-
- ack = GNUNET_malloc (size);
- ack->message_id = msg_id;
- ack->endpoint = endpoint;
-
- size =
- sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_Send) +
- sizeof (struct ieee80211_frame) + ntohs (hdr->size);
-
- msgheader = (struct GNUNET_MessageHeader *) &ack[1];
- ack->hdr = (struct GNUNET_MessageHeader *) &ack[1];
- msgheader->size = htons (size);
- msgheader->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
-
- ack->radioHeader = (struct Radiotap_Send *) &msgheader[1];
- ack->ieeewlanheader = (struct ieee80211_frame *) &(ack->radioHeader)[1];
- msgheader2 = (struct GNUNET_MessageHeader *) &(ack->ieeewlanheader)[1];
- memcpy (msgheader2, hdr, ntohs (hdr->size));
-
- GNUNET_CONTAINER_DLL_insert_tail (plugin->ack_send_queue_head,
- plugin->ack_send_queue_tail, ack);
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Adding ack with message id %u to send, AckSendQueue %p, endpoint %p\n",
- msg_id, ack, endpoint);
- set_next_send (plugin);
-}
/**
- * Function for the scheduler if a FragmentMessage times out
- * @param cls pointer to the FragmentMessage
+ * A FragmentMessage has timed out. Remove it.
+ *
+ * @param cls pointer to the 'struct FragmentMessage'
* @param tc pointer to the GNUNET_SCHEDULER_TaskContext
*/
static void
@@ -1849,284 +795,162 @@ fragmentmessage_timeout (void *cls,
{
struct FragmentMessage *fm = cls;
- GNUNET_assert (fm != NULL);
fm->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+ if (NULL != fm->cont)
{
- return;
+ fm->cont (fm->cont_cls, &fm->target, GNUNET_SYSERR);
+ fm->cont = NULL;
}
- free_fragment_message (fm->session->mac->plugin, fm);
+ free_fragment_message (fm);
}
+
/**
- * Function to check if there is some space in the fragment queue
- * inserts a message if space is available
- * @param plugin the plugin struct
+ * Transmit a message to the given destination with fragmentation.
+ *
+ * @param endpoint desired destination
+ * @param timeout how long can the message wait?
+ * @param target peer that should receive the message
+ * @param msg message to transmit
+ * @param cont continuation to call once the message has
+ * been transmitted (or if the transport is ready
+ * for the next transmission call; or if the
+ * peer disconnected...); can be NULL
+ * @param cont_cls closure for cont
*/
-
static void
-check_fragment_queue (struct Plugin *plugin)
+send_with_fragmentation (struct MacEndpoint *endpoint,
+ struct GNUNET_TIME_Relative timeout,
+ const struct GNUNET_PeerIdentity *target,
+ const struct GNUNET_MessageHeader *msg,
+ GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
+
{
- struct Session *session;
struct FragmentMessage *fm;
- struct GNUNET_PeerIdentity pid;
-
- struct PendingMessage *pm;
-
- if (plugin->pending_Fragment_Messages < FRAGMENT_QUEUE_SIZE)
- {
- session = get_next_queue_session (plugin);
- if (session != NULL)
- {
- pm = session->pending_message_head;
- GNUNET_assert (pm != NULL);
- GNUNET_CONTAINER_DLL_remove (session->pending_message_head,
- session->pending_message_tail, pm);
- session->mac->fragment_messages_out_count++;
- session->fragment_messages_out_count++;
- plugin->pending_Fragment_Messages++;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending fragments"),
- plugin->pending_Fragment_Messages, GNUNET_NO);
-
- fm = GNUNET_malloc (sizeof (struct FragmentMessage));
- fm->session = session;
- fm->timeout.abs_value = pm->timeout.abs_value;
- fm->frag = NULL;
- fm->fragcontext =
- GNUNET_FRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
- &plugin->tracker,
- GNUNET_TIME_UNIT_SECONDS,
- &(pm->msg->header),
- &add_message_for_send, fm);
- fm->timeout_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
- (fm->timeout), fragmentmessage_timeout,
- fm);
- GNUNET_CONTAINER_DLL_insert_tail (session->mac->sending_messages_head,
- session->mac->sending_messages_tail,
- fm);
-
- if (pm->transmit_cont != NULL)
- {
- pid = session->target;
- pm->transmit_cont (pm->transmit_cont_cls, &pid, GNUNET_OK);
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "called pm->transmit_cont for %p\n", session);
- }
- else
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "no pm->transmit_cont for %p\n", session);
- }
- GNUNET_free (pm);
-
- if (session->pending_message_head != NULL)
- {
- //requeue session
- queue_session (plugin, session);
- }
-
- }
- }
+ struct Plugin *plugin;
- //check if timeout changed
- set_next_send (plugin);
+ plugin = endpoint->plugin;
+ fm = GNUNET_malloc (sizeof (struct FragmentMessage));
+ fm->macendpoint = endpoint;
+ fm->target = *target;
+ fm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
+ fm->cont = cont;
+ fm->cont_cls = cont_cls;
+ fm->fragcontext =
+ GNUNET_FRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
+ &plugin->tracker,
+ GNUNET_TIME_UNIT_SECONDS,
+ msg,
+ &transmit_fragment, fm);
+ fm->timeout_task =
+ GNUNET_SCHEDULER_add_delayed (timeout,
+ &fragmentmessage_timeout, fm);
+ GNUNET_CONTAINER_DLL_insert_tail (endpoint->sending_messages_head,
+ endpoint->sending_messages_tail,
+ fm);
}
+
/**
- * Function to send an ack, does not free the ack
- * @param plugin pointer to the plugin
+ * Free a MAC endpoint.
+ *
+ * @param endpoint pointer to the MacEndpoint to free
*/
static void
-send_ack (struct Plugin *plugin)
+free_macendpoint (struct MacEndpoint *endpoint)
{
+ struct Plugin *plugin = endpoint->plugin;
+ struct FragmentMessage *fm;
+ struct Session *session;
- ssize_t bytes;
- struct AckSendQueue *ack;
- struct Finish_send *finish;
-
- ack = plugin->ack_send_queue_head;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Sending ack for message_id %u for mac endpoint %p, size %u\n",
- ack->message_id, ack->endpoint,
- ntohs (ack->hdr->size) - sizeof (struct Radiotap_Send));
- GNUNET_assert (plugin != NULL);
- GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks send"), 1,
- GNUNET_NO);
-
- getRadiotapHeader (plugin, ack->endpoint, ack->radioHeader);
- getWlanHeader (ack->ieeewlanheader, &ack->endpoint->addr, plugin,
- ntohs (ack->hdr->size));
+ GNUNET_STATISTICS_update (plugin->env->stats,
+ _("# WLAN MAC endpoints allocated"), -1, GNUNET_NO);
+ while (NULL != (session = endpoint->sessions_head))
+ free_session (session);
+ while (NULL != (fm = endpoint->sending_messages_head))
+ free_fragment_message (fm);
+ GNUNET_CONTAINER_DLL_remove (plugin->mac_head,
+ plugin->mac_tail,
+ endpoint);
- bytes =
- GNUNET_DISK_file_write (plugin->server_stdin_handle, ack->hdr,
- ntohs (ack->hdr->size));
- if (bytes == GNUNET_SYSERR)
+ if (NULL != endpoint->defrag)
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- _
- ("Error writing to wlan helper. errno == %d, ERROR: %s\n"),
- errno, strerror (errno));
- finish = GNUNET_malloc (sizeof (struct Finish_send));
- finish->plugin = plugin;
- finish->head_of_next_write = NULL;
- finish->size = 0;
- finish->msgstart = NULL;
- restart_helper (plugin, finish);
+ GNUNET_DEFRAGMENT_context_destroy(endpoint->defrag);
+ endpoint->defrag = NULL;
}
- else
+
+ plugin->mac_count--;
+ if (GNUNET_SCHEDULER_NO_TASK != endpoint->timeout_task)
{
- GNUNET_assert (bytes == ntohs (ack->hdr->size));
- GNUNET_CONTAINER_DLL_remove (plugin->ack_send_queue_head,
- plugin->ack_send_queue_tail, ack);
- GNUNET_free (ack);
- set_next_send (plugin);
+ GNUNET_SCHEDULER_cancel (endpoint->timeout_task);
+ endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
}
+ GNUNET_free (endpoint);
}
+
/**
- * Function called when wlan helper is ready to get some data
+ * A MAC endpoint is timing out. Clean up.
*
- * @param cls closure
- * @param tc GNUNET_SCHEDULER_TaskContext
+ * @param cls pointer to the MacEndpoint
+ * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
*/
static void
-do_transmit (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- struct Plugin *plugin = cls;
-
- GNUNET_assert (plugin != NULL);
-
- plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- return;
-
- struct Session *session;
- struct FragmentMessage *fm;
- struct Finish_send *finish;
- struct FragmentMessage_queue *fmq;
- ssize_t bytes;
-
- if (plugin->ack_send_queue_head != NULL)
- {
- send_ack (plugin);
- return;
- }
+ struct MacEndpoint *endpoint = cls;
+ struct GNUNET_TIME_Relative timeout;
- //test if a "hello-beacon" has to be send
- if (GNUNET_TIME_absolute_get_remaining (plugin->beacon_time).rel_value == 0)
+ endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ timeout = GNUNET_TIME_absolute_get_remaining (endpoint->timeout);
+ if (0 == timeout.rel_value)
{
- send_hello_beacon (plugin);
+ free_macendpoint (endpoint);
return;
}
-
- if (plugin->sending_messages_head != NULL)
- {
- GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan fragments send"), 1,
- GNUNET_NO);
-
- fmq = plugin->sending_messages_head;
- fm = fmq->content;
- GNUNET_CONTAINER_DLL_remove (plugin->sending_messages_head,
- plugin->sending_messages_tail, fmq);
- GNUNET_free (fmq);
-
- session = fm->session;
- GNUNET_assert (session != NULL);
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Sending GNUNET_MESSAGE_TYPE_WLAN_FRAGMENT for fragment message %p, size: %u\n",
- fm, fm->size);
- getRadiotapHeader (plugin, session->mac, fm->radioHeader);
- getWlanHeader (fm->ieeewlanheader, &(fm->session->mac->addr), plugin,
- fm->size);
-
- bytes =
- GNUNET_DISK_file_write (plugin->server_stdin_handle, fm->frag,
- fm->size);
-
-
- if (bytes != fm->size)
- {
- finish = GNUNET_malloc (sizeof (struct Finish_send));
- finish->plugin = plugin;
- finish->msgstart = (struct GNUNET_MessageHeader *) fm->frag;
- GNUNET_assert (plugin->server_write_task == GNUNET_SCHEDULER_NO_TASK);
-
- if (bytes == GNUNET_SYSERR)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- _
- ("Error writing to wlan helper. errno == %d, ERROR: %s\n"),
- errno, strerror (errno));
-
- finish->head_of_next_write = fm->frag;
- finish->size = fm->size;
- restart_helper (plugin, finish);
- }
- else
- {
- finish->head_of_next_write = fm->frag + bytes;
- finish->size = fm->size - bytes;
- plugin->server_write_task =
- GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
- plugin->server_stdin_handle,
- &finish_sending, finish);
- }
-
- fm->frag = NULL;
- }
- else
- {
- GNUNET_free (fm->frag);
- fm->frag = NULL;
- set_next_send (plugin);
- }
- GNUNET_FRAGMENT_context_transmission_done (fm->fragcontext);
- return;
- }
-
-#if 1
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "do_transmit did nothing, should not happen!\n");
-#endif
- set_next_send (plugin);
+ endpoint->timeout_task =
+ GNUNET_SCHEDULER_add_delayed (timeout, &macendpoint_timeout,
+ endpoint);
}
+
/**
- * Another peer has suggested an address for this
- * peer and transport plugin. Check that this could be a valid
- * address. If so, consider adding it to the list
- * of addresses.
+ * Find (or create) a MacEndpoint with a specific MAC address
*
- * @param cls closure
- * @param addr pointer to the address
- * @param addrlen length of addr
- * @return GNUNET_OK if this is a plausible address for this peer
- * and transport
+ * @param plugin pointer to the plugin struct
+ * @param addr the MAC address of the endpoint
+ * @return handle to our data structure for this MAC
*/
-static int
-wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
+static struct MacEndpoint *
+create_macendpoint (struct Plugin *plugin,
+ const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr)
{
- //struct Plugin *plugin = cls;
-
- /* check if the address is plausible; if so,
- * add it to our list! */
-
- GNUNET_assert (cls != NULL);
- //FIXME mitm is not checked
- //Mac Address has 6 bytes
- if (addrlen == 6)
- {
- /* TODO check for bad addresses like multicast, broadcast, etc */
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "wlan_plugin_address_suggested got good address, size %u!\n",
- addrlen);
- return GNUNET_OK;
- }
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "wlan_plugin_address_suggested got bad address, size %u!\n",
- addrlen);
- return GNUNET_SYSERR;
+ struct MacEndpoint *pos;
+
+ for (pos = plugin->mac_head; NULL != pos; pos = pos->next)
+ if (0 == memcmp (addr, &pos->addr, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
+ return pos;
+ pos = GNUNET_malloc (sizeof (struct MacEndpoint));
+ pos->addr = *addr;
+ pos->plugin = plugin;
+ pos->defrag =
+ GNUNET_DEFRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
+ MESSAGES_IN_DEFRAG_QUEUE_PER_MAC,
+ pos,
+ &wlan_data_message_handler,
+ &send_ack);
+ pos->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT);
+ pos->timeout_task =
+ GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
+ pos);
+ GNUNET_CONTAINER_DLL_insert (plugin->mac_head, plugin->mac_tail, pos);
+ plugin->mac_count++;
+ GNUNET_STATISTICS_update (plugin->env->stats, _("# WLAN MAC endpoints allocated"),
+ 1, GNUNET_NO);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "New MAC endpoint `%s'\n",
+ mac_to_string (addr));
+ return pos;
}
@@ -2138,33 +962,55 @@ wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
* @param address the address
* @return the session or NULL of max connections exceeded
*/
-
static struct Session *
wlan_plugin_get_session (void *cls,
- const struct GNUNET_HELLO_Address *address)
+ const struct GNUNET_HELLO_Address *address)
{
struct Plugin *plugin = cls;
- struct Session * s = NULL;
-
- GNUNET_assert (plugin != NULL);
- GNUNET_assert (address != NULL);
+ struct MacEndpoint *endpoint;
- if (GNUNET_OK == wlan_plugin_address_suggested (plugin,
- address->address,
- address->address_length))
- {
- s = get_session (plugin, address->address, &address->peer);
- }
- else
+ if (NULL == address)
+ return NULL;
+ if (sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress) != address->address_length)
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, PLUGIN_LOG_NAME,
- _("Wlan Address len %d is wrong\n"), address->address_length);
- return s;
+ GNUNET_break (0);
+ return NULL;
}
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Service asked to create session for peer `%s' with MAC `%s'\n",
+ GNUNET_i2s (&address->peer),
+ mac_to_string (address->address));
+ endpoint = create_macendpoint (plugin, address->address);
+ return create_session (endpoint, &address->peer);
+}
+
+
+/**
+ * Function that can be used to force the plugin to disconnect
+ * from the given peer and cancel all previous transmissions
+ * (and their continuation).
+ *
+ * @param cls closure
+ * @param target peer from which to disconnect
+ */
+static void
+wlan_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
+{
+ struct Plugin *plugin = cls;
+ struct Session *session;
+ struct MacEndpoint *endpoint;
- return s;
+ for (endpoint = plugin->mac_head; NULL != endpoint; endpoint = endpoint->next)
+ for (session = endpoint->sessions_head; NULL != session; session = session->next)
+ if (0 == memcmp (target, &session->target,
+ sizeof (struct GNUNET_PeerIdentity)))
+ {
+ free_session (session);
+ break; /* inner-loop only (in case peer has another MAC as well!) */
+ }
}
+
/**
* Function that can be used by the transport service to transmit
* a message using the plugin. Note that in the case of a
@@ -2201,925 +1047,586 @@ wlan_plugin_send (void *cls,
GNUNET_TRANSPORT_TransmitContinuation cont, void *cont_cls)
{
struct Plugin *plugin = cls;
- struct PendingMessage *newmsg;
struct WlanHeader *wlanheader;
-
- GNUNET_assert (plugin != NULL);
- GNUNET_assert (session != NULL);
- GNUNET_assert (msgbuf_size > 0);
-
- //queue message:
-
- //queue message in session
- //test if there is no other message in the "queue"
- //FIXME: to many send requests
- if (session->pending_message_head != NULL)
- {
- newmsg = session->pending_message_head;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "wlan_plugin_send: a pending message is already in the queue for this client\n remaining time to send this message is %u, queued fragment messages for this mac connection %u\n",
- GNUNET_TIME_absolute_get_remaining (newmsg->
- timeout).rel_value,
- session->mac->fragment_messages_out_count);
- }
-
- newmsg = GNUNET_malloc (sizeof (struct PendingMessage));
- newmsg->msg = GNUNET_malloc (msgbuf_size + sizeof (struct WlanHeader));
- wlanheader = newmsg->msg;
- //copy msg to buffer, not fragmented / segmented yet, but with message header
+ size_t size = msgbuf_size + sizeof (struct WlanHeader);
+ char buf[size] GNUNET_ALIGN;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Transmitting %u bytes of payload to peer `%s' (starting with %u byte message of type %u)\n",
+ msgbuf_size,
+ GNUNET_i2s (&session->target),
+ (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->size),
+ (unsigned int) ntohs (((struct GNUNET_MessageHeader*)msgbuf)->type));
+ wlanheader = (struct WlanHeader *) buf;
wlanheader->header.size = htons (msgbuf_size + sizeof (struct WlanHeader));
wlanheader->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA);
- memcpy (&(wlanheader->target), &session->target, sizeof (struct GNUNET_PeerIdentity));
- memcpy (&(wlanheader->source), plugin->env->my_identity,
- sizeof (struct GNUNET_PeerIdentity));
- wlanheader->crc = 0;
+ wlanheader->sender = *plugin->env->my_identity;
+ wlanheader->target = session->target;
+ wlanheader->crc = htonl (GNUNET_CRYPTO_crc32_n (msgbuf, msgbuf_size));
memcpy (&wlanheader[1], msgbuf, msgbuf_size);
- wlanheader->crc =
- htonl (GNUNET_CRYPTO_crc32_n
- ((char *) wlanheader, msgbuf_size + sizeof (struct WlanHeader)));
-
- newmsg->transmit_cont = cont;
- newmsg->transmit_cont_cls = cont_cls;
- newmsg->timeout = GNUNET_TIME_relative_to_absolute (to);
-
- newmsg->timeout.abs_value = newmsg->timeout.abs_value - 500;
-
- newmsg->message_size = msgbuf_size + sizeof (struct WlanHeader);
-
- GNUNET_CONTAINER_DLL_insert_tail (session->pending_message_head,
- session->pending_message_tail, newmsg);
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "New message for %p with size (incl wlan header) %u added\n",
- session, newmsg->message_size);
-#if DEBUG_WLAN > 1
- hexdump (msgbuf, GNUNET_MIN (msgbuf_size, 256));
-#endif
- //queue session
- queue_session (plugin, session);
-
- check_fragment_queue (plugin);
- //FIXME not the correct size
- return msgbuf_size;
+ send_with_fragmentation (session->mac,
+ to,
+ &session->target,
+ &wlanheader->header,
+ cont, cont_cls);
+ return size;
}
/**
- * function to free a mac endpoint
- * @param plugin pointer to the plugin struct
- * @param endpoint pointer to the MacEndpoint to free
- */
-static void
-free_macendpoint (struct Plugin *plugin, struct MacEndpoint *endpoint)
-{
- struct Sessionqueue *sessions;
- struct Sessionqueue *sessions_next;
-
- GNUNET_assert (endpoint != NULL);
-
- sessions = endpoint->sessions_head;
- while (sessions != NULL)
- {
- sessions_next = sessions->next;
- free_session (plugin, sessions, GNUNET_NO);
- sessions = sessions_next;
- }
-
- GNUNET_CONTAINER_DLL_remove (plugin->mac_head, plugin->mac_tail, endpoint);
- if (endpoint->timeout_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (endpoint->timeout_task);
- endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- }
- plugin->mac_count--;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
- plugin->mac_count, GNUNET_NO);
- GNUNET_free (endpoint);
-
-}
-
-/**
- * function to free a session
- * @param plugin pointer to the plugin
- * @param queue pointer to the sessionqueue element to free
- * @param do_free_macendpoint if GNUNET_YES and mac endpoint would be empty, free mac endpoint
- */
-static void
-free_session (struct Plugin *plugin, struct Sessionqueue *queue,
- int do_free_macendpoint)
-{
- struct Sessionqueue *pendingsession;
- struct Sessionqueue *pendingsession_tmp;
- struct PendingMessage *pm;
- struct MacEndpoint *endpoint;
- struct FragmentMessage *fm;
- struct FragmentMessage *fmnext;
- int check = 0;
-
- GNUNET_assert (plugin != NULL);
- GNUNET_assert (queue != NULL);
- GNUNET_assert (queue->content != NULL);
-
- //session found
- //is this session pending for send
- pendingsession = plugin->pending_Sessions_head;
- while (pendingsession != NULL)
- {
- pendingsession_tmp = pendingsession;
- pendingsession = pendingsession->next;
- GNUNET_assert (pendingsession_tmp->content != NULL);
- if (pendingsession_tmp->content == queue->content)
- {
- plugin->pendingsessions--;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
- plugin->pendingsessions, GNUNET_NO);
- GNUNET_CONTAINER_DLL_remove (plugin->pending_Sessions_head,
- plugin->pending_Sessions_tail,
- pendingsession_tmp);
- GNUNET_free (pendingsession_tmp);
-
- GNUNET_assert (check == 0);
- check = 1;
- }
- }
-
- endpoint = queue->content->mac;
- fm = endpoint->sending_messages_head;
- while (fm != NULL)
- {
- fmnext = fm->next;
- if (fm->session == queue->content)
- {
- free_fragment_message (plugin, fm);
- }
- fm = fmnext;
- }
-
- // remove PendingMessage
- pm = queue->content->pending_message_head;
- while (pm != NULL)
- {
- GNUNET_CONTAINER_DLL_remove (queue->content->pending_message_head,
- queue->content->pending_message_tail, pm);
- GNUNET_free (pm->msg);
- GNUNET_free (pm);
- pm = queue->content->pending_message_head;
- }
-
- GNUNET_CONTAINER_DLL_remove (endpoint->sessions_head, endpoint->sessions_tail,
- queue);
- //Check that no ohter session on this endpoint for this session exits
- GNUNET_assert (search_session (plugin, endpoint, &queue->content->target) ==
- NULL);
- if (endpoint->sessions_head == NULL && do_free_macendpoint == GNUNET_YES)
- {
- free_macendpoint (plugin, endpoint);
- //check if no endpoint with the same address exists
- GNUNET_assert (get_macendpoint (plugin, &endpoint->addr, GNUNET_NO) ==
- NULL);
- }
-
- if (queue->content->timeout_task != GNUNET_SCHEDULER_NO_TASK)
- {
- GNUNET_SCHEDULER_cancel (queue->content->timeout_task);
- queue->content->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- }
- GNUNET_free (queue);
-
- check_fragment_queue (plugin);
-}
-
-/**
- * Function that can be used to force the plugin to disconnect
- * from the given peer and cancel all previous transmissions
- * (and their continuation).
+ * We have received data from the WLAN via some session. Process depending
+ * on the message type (HELLO, DATA, FRAGMENTATION or FRAGMENTATION-ACK).
*
- * @param cls closure
- * @param target peer from which to disconnect
+ * @param cls pointer to the plugin
+ * @param client pointer to the session this message belongs to
+ * @param hdr start of the message
*/
-static void
-wlan_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target)
+static int
+process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
{
struct Plugin *plugin = cls;
- struct Sessionqueue *queue;
- struct Sessionqueue *queue_next;
- struct MacEndpoint *endpoint = plugin->mac_head;
- struct MacEndpoint *endpoint_next;
+ struct MacAndSession *mas = client;
+ struct MacAndSession xmas;
+#define NUM_ATS 2
+ struct GNUNET_ATS_Information ats[NUM_ATS]; /* FIXME: do better here */
+ struct FragmentMessage *fm;
+ struct GNUNET_PeerIdentity tmpsource;
+ const struct WlanHeader *wlanheader;
+ int ret;
+ uint16_t msize;
- // just look at all the session for the needed one
- while (endpoint != NULL)
+ ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
+ ats[0].value = htonl (1);
+ ats[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
+ ats[1].value = htonl (GNUNET_ATS_NET_WLAN);
+ msize = ntohs (hdr->size);
+ switch (ntohs (hdr->type))
{
- queue = endpoint->sessions_head;
- endpoint_next = endpoint->next;
- while (queue != NULL)
+ case GNUNET_MESSAGE_TYPE_HELLO:
+ if (GNUNET_OK !=
+ GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource))
{
- // content is never NULL
- GNUNET_assert (queue->content != NULL);
- queue_next = queue->next;
- if (memcmp
- (target, &(queue->content->target),
- sizeof (struct GNUNET_PeerIdentity)) == 0)
- {
- free_session (plugin, queue, GNUNET_YES);
- }
- // try next
- queue = queue_next;
+ GNUNET_break_op (0);
+ break;
}
- endpoint = endpoint_next;
- }
-}
-
-/**
- * Convert the transports address to a nice, human-readable
- * format.
- *
- * @param cls closure
- * @param type name of the transport that generated the address
- * @param addr one of the addresses of the host, NULL for the last address
- * the specific address format depends on the transport
- * @param addrlen length of the address
- * @param numeric should (IP) addresses be displayed in numeric form?
- * @param timeout after how long should we give up?
- * @param asc function to call on each string
- * @param asc_cls closure for asc
- */
-static void
-wlan_plugin_address_pretty_printer (void *cls, const char *type,
- const void *addr, size_t addrlen,
- int numeric,
- struct GNUNET_TIME_Relative timeout,
- GNUNET_TRANSPORT_AddressStringCallback asc,
- void *asc_cls)
-{
- char *ret;
- const unsigned char *input;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Processing %u bytes of HELLO from peer `%s' at MAC %s\n",
+ (unsigned int) msize,
+ GNUNET_i2s (&tmpsource),
+ mac_to_string (&mas->endpoint->addr));
- //GNUNET_assert(cls !=NULL);
- if (addrlen != sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))
- {
- /* invalid address (MAC addresses have 6 bytes) */
- //GNUNET_break (0);
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Func wlan_plugin_address_pretty_printer got size: %u, worng size!\n",
- addrlen);
- asc (asc_cls, NULL);
- return;
- }
- input = (const unsigned char *) addr;
- GNUNET_asprintf (&ret,
- "Transport %s: %s Mac-Address %.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
- type, PROTOCOL_PREFIX, input[0], input[1], input[2],
- input[3], input[4], input[5]);
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Func wlan_plugin_address_pretty_printer got size: %u, nummeric %u, type %s; made string: %s\n",
- addrlen, numeric, type, ret);
- asc (asc_cls, ret);
- //only one mac address per plugin
- asc (asc_cls, NULL);
-}
-
-
-
-/**
- * handels the data after all fragments are put together
- * @param cls macendpoint this messages belongs to
- * @param hdr pointer to the data
- */
-static void
-wlan_data_message_handler (void *cls, const struct GNUNET_MessageHeader *hdr)
-{
- struct MacEndpoint *endpoint = (struct MacEndpoint *) cls;
- struct Plugin *plugin = endpoint->plugin;
- struct WlanHeader *wlanheader;
- struct Session *session;
-
- const struct GNUNET_MessageHeader *temp_hdr;
- struct GNUNET_PeerIdentity tmpsource;
- int crc;
-
- GNUNET_assert (plugin != NULL);
-
- if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_WLAN_DATA)
- {
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Func wlan_data_message_handler got GNUNET_MESSAGE_TYPE_WLAN_DATA size: %u\n",
- ntohs (hdr->size));
-
- if (ntohs (hdr->size) <
- sizeof (struct WlanHeader) + sizeof (struct GNUNET_MessageHeader))
+ GNUNET_STATISTICS_update (plugin->env->stats,
+ _("# HELLO messages received via WLAN"), 1,
+ GNUNET_NO);
+ plugin->env->receive (plugin->env->cls,
+ &tmpsource,
+ hdr,
+ ats, NUM_ATS,
+ mas->session,
+ (mas->endpoint == NULL) ? NULL : (const char *) &mas->endpoint->addr,
+ (mas->endpoint == NULL) ? 0 : sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
+ break;
+ case GNUNET_MESSAGE_TYPE_FRAGMENT:
+ if (NULL == mas->endpoint)
{
- //packet not big enought
- return;
+ GNUNET_break (0);
+ break;
}
-
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Processing %u bytes of FRAGMENT from MAC %s\n",
+ (unsigned int) msize,
+ mac_to_string (&mas->endpoint->addr));
GNUNET_STATISTICS_update (plugin->env->stats,
- _("# wlan whole messages received"), 1,
- GNUNET_NO);
- wlanheader = (struct WlanHeader *) hdr;
-
- session = search_session (plugin, endpoint, &wlanheader->source);
-
- temp_hdr = (const struct GNUNET_MessageHeader *) &wlanheader[1];
- crc = ntohl (wlanheader->crc);
- wlanheader->crc = 0;
- if (GNUNET_CRYPTO_crc32_n
- ((char *) wlanheader, ntohs (wlanheader->header.size)) != crc)
+ _("# fragments received via WLAN"), 1, GNUNET_NO);
+ (void) GNUNET_DEFRAGMENT_process_fragment (mas->endpoint->defrag,
+ hdr);
+ break;
+ case GNUNET_MESSAGE_TYPE_FRAGMENT_ACK:
+ if (NULL == mas->endpoint)
{
- //wrong crc, dispose message
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
- "Wlan message header crc was wrong: %u != %u\n",
- GNUNET_CRYPTO_crc32_n ((char *) wlanheader,
- ntohs (wlanheader->header.size)),
- crc);
- hexdump ((void *) hdr, ntohs (hdr->size));
- return;
+ GNUNET_break (0);
+ break;
}
-
- //if not in session list
- if (session == NULL)
+ GNUNET_STATISTICS_update (plugin->env->stats, _("# ACKs received via WLAN"),
+ 1, GNUNET_NO);
+ for (fm = mas->endpoint->sending_messages_head; NULL != fm; fm = fm->next)
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "WLAN client not in session list: packet size = %u, inner size = %u, header size = %u\n",
- ntohs (wlanheader->header.size), ntohs (temp_hdr->size),
- sizeof (struct WlanHeader));
- //try if it is a hello message
- if (ntohs (wlanheader->header.size) >=
- ntohs (temp_hdr->size) + sizeof (struct WlanHeader))
+ ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr);
+ if (GNUNET_OK == ret)
{
- if (ntohs (temp_hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
- {
- if (GNUNET_HELLO_get_id
- ((const struct GNUNET_HELLO_Message *) temp_hdr,
- &tmpsource) == GNUNET_OK)
- {
- session = create_session (plugin, endpoint, &tmpsource);
- }
- else
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
- "WLAN client not in session list and hello message is not okay\n");
- return;
- }
-
- }
- else
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
- "WLAN client not in session list and not a hello message\n");
- return;
- }
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Got last ACK, finished message transmission to `%s' (%p)\n",
+ mac_to_string (&mas->endpoint->addr),
+ fm);
+ mas->endpoint->timeout = GNUNET_TIME_relative_to_absolute (MACENDPOINT_TIMEOUT);
+ if (NULL != fm->cont)
+ {
+ fm->cont (fm->cont_cls, &fm->target, GNUNET_OK);
+ fm->cont = NULL;
+ }
+ free_fragment_message (fm);
+ break;
}
- else
+ if (GNUNET_NO == ret)
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
- "WLAN client not in session list and message size in does not fit\npacket size = %u, inner size = %u, header size = %u\n",
- ntohs (wlanheader->header.size),
- ntohs (temp_hdr->size), sizeof (struct WlanHeader));
- return;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Got an ACK, message transmission to `%s' not yet finished\n",
+ mac_to_string (&mas->endpoint->addr));
+ break;
}
}
-
- //"receive" the message
-
- if (memcmp
- (&wlanheader->source, &session->target,
- sizeof (struct GNUNET_PeerIdentity)) != 0)
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "ACK not matched against any active fragmentation with MAC `%s'\n",
+ mac_to_string (&mas->endpoint->addr));
+ break;
+ case GNUNET_MESSAGE_TYPE_WLAN_DATA:
+ if (NULL == mas->endpoint)
{
- //wrong peer id
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "WLAN peer source id doesn't match packet peer source id: session %p\n",
- session);
- return;
+ GNUNET_break (0);
+ break;
}
-
- if (memcmp
- (&wlanheader->target, plugin->env->my_identity,
- sizeof (struct GNUNET_PeerIdentity)) != 0)
+ if (msize < sizeof (struct WlanHeader))
{
- //wrong peer id
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "WLAN peer target id doesn't match our peer id: session %p\n",
- session);
- return;
+ GNUNET_break (0);
+ break;
+ }
+ wlanheader = (const struct WlanHeader *) hdr;
+ if (0 != memcmp (&wlanheader->target,
+ plugin->env->my_identity,
+ sizeof (struct GNUNET_PeerIdentity)))
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "WLAN data for `%s', not for me, ignoring\n",
+ GNUNET_i2s (&wlanheader->target));
+ break;
}
-
- GNUNET_SERVER_mst_receive (plugin->data_tokenizer, session,
- (const char *) temp_hdr,
- ntohs (hdr->size) - sizeof (struct WlanHeader),
- GNUNET_YES, GNUNET_NO);
-
- return;
- }
- else
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
- "wlan_data_message_handler got wrong message type: %u\n",
- ntohs (hdr->size));
- return;
+ if (ntohl (wlanheader->crc) !=
+ GNUNET_CRYPTO_crc32_n (&wlanheader[1], msize - sizeof (struct WlanHeader)))
+ {
+ GNUNET_STATISTICS_update (plugin->env->stats,
+ _("# WLAN DATA messages discarded due to CRC32 error"), 1,
+ GNUNET_NO);
+ break;
+ }
+ xmas.endpoint = mas->endpoint;
+ xmas.session = create_session (mas->endpoint, &wlanheader->sender);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Processing %u bytes of WLAN DATA from peer `%s'\n",
+ (unsigned int) msize,
+ GNUNET_i2s (&wlanheader->sender));
+ (void) GNUNET_SERVER_mst_receive (plugin->wlan_header_payload_tokenizer,
+ &xmas,
+ (const char *) &wlanheader[1],
+ msize - sizeof (struct WlanHeader),
+ GNUNET_YES, GNUNET_NO);
+ break;
+ default:
+ if (NULL == mas->endpoint)
+ {
+ GNUNET_break (0);
+ break;
+ }
+ if (NULL == mas->session)
+ {
+ GNUNET_break (0);
+ break;
+ }
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received packet with %u bytes of type %u from peer %s\n",
+ (unsigned int) msize,
+ (unsigned int) ntohs (hdr->type),
+ GNUNET_i2s (&mas->session->target));
+ plugin->env->receive (plugin->env->cls,
+ &mas->session->target,
+ hdr,
+ ats, NUM_ATS,
+ mas->session,
+ (mas->endpoint == NULL) ? NULL : (const char *) &mas->endpoint->addr,
+ (mas->endpoint == NULL) ? 0 : sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
+ break;
}
+ return GNUNET_OK;
}
+#undef NUM_ATS
-/**
- * function to process the a message, give it to the higher layer
- * @param cls pointer to the plugin
- * @param client pointer to the session this message belongs to
- * @param hdr start of the message
- */
-//TODO ATS informations
-static void
-process_data (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
-{
-
- GNUNET_assert (client != NULL);
- GNUNET_assert (cls != NULL);
- struct Session *session = (struct Session *) client;
- struct Plugin *plugin = (struct Plugin *) cls;
- struct GNUNET_ATS_Information ats[2];
-
- ats[0].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
- ats[0].value = htonl (1);
- ats[1].type = htonl (GNUNET_ATS_NETWORK_TYPE);
- ats[1].value = htonl (GNUNET_ATS_NET_WLAN);
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Calling plugin->env->receive for session %p; %s; size: %u\n",
- session, wlan_plugin_address_to_string (NULL,
- session->mac->
- addr.mac, 6),
- htons (hdr->size));
- plugin->env->receive (plugin->env->cls, &(session->target), hdr,
- (const struct GNUNET_ATS_Information *) &ats, 2,
- session, (const char *) &session->mac->addr,
- sizeof (session->mac->addr));
-}
/**
- * Function used for to process the data received from the wlan interface
+ * Function used for to process the data from the suid process
*
* @param cls the plugin handle
- * @param session_light pointer to the struct holding known informations
- * @param hdr hdr of the GNUNET_MessageHeader
- * @param rxinfo pointer to the radiotap informations got with this packet FIXME: give ATS for info
+ * @param client client that send the data (not used)
+ * @param hdr header of the GNUNET_MessageHeader
*/
-static void
-wlan_data_helper (void *cls, struct Session_light *session_light,
- const struct GNUNET_MessageHeader *hdr,
- const struct Radiotap_rx *rxinfo)
+static int
+handle_helper_message (void *cls, void *client,
+ const struct GNUNET_MessageHeader *hdr)
{
struct Plugin *plugin = cls;
- struct FragmentMessage *fm;
- struct FragmentMessage *fm2;
- struct GNUNET_PeerIdentity tmpsource;
+ const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rxinfo;
+ const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *cm;
+ struct MacAndSession mas;
+ uint16_t msize;
- GNUNET_assert (plugin != NULL);
-
- //ADVERTISEMENT
- if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_HELLO)
+ msize = ntohs (hdr->size);
+ switch (ntohs (hdr->type))
{
-
- //TODO better DOS protection, error handling
- //TODO test first than create session
- GNUNET_assert (session_light != NULL);
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_HELLO size: %u; %s\n",
- ntohs (hdr->size), wlan_plugin_address_to_string (NULL,
- session_light->addr.
- mac, 6));
- if (session_light->macendpoint == NULL)
- {
- session_light->macendpoint =
- get_macendpoint (plugin, &session_light->addr, GNUNET_YES);
- }
-
-
- if (GNUNET_HELLO_get_id
- ((const struct GNUNET_HELLO_Message *) hdr, &tmpsource) == GNUNET_OK)
- {
- session_light->session =
- search_session (plugin, session_light->macendpoint, &tmpsource);
- if (session_light->session == NULL)
- {
- session_light->session =
- create_session (plugin, session_light->macendpoint, &tmpsource);
- }
- GNUNET_STATISTICS_update (plugin->env->stats,
- _("# wlan hello messages received"), 1,
- GNUNET_NO);
- plugin->env->receive (plugin->env->cls, &session_light->session->target,
- hdr, NULL, 0, session_light->session,
- (const char *) &session_light->session->mac->addr,
- sizeof (session_light->session->mac->addr));
- }
- else
+ case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
+ if (msize != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage))
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, PLUGIN_LOG_NAME,
- "WLAN client not in session list and hello message is not okay\n");
- return;
+ GNUNET_break (0);
+ break;
}
- }
-
- //FRAGMENT
-
- else if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_FRAGMENT)
- {
-
- GNUNET_assert (session_light != NULL);
- if (session_light->macendpoint == NULL)
+ cm = (const struct GNUNET_TRANSPORT_WLAN_HelperControlMessage *) hdr;
+ if (GNUNET_YES == plugin->have_mac)
{
- session_light->macendpoint =
- get_macendpoint (plugin, &session_light->addr, GNUNET_YES);
+ if (0 == memcmp (&plugin->mac_address,
+ &cm->mac,
+ sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
+ break; /* no change */
+ /* remove old address */
+ plugin->env->notify_address (plugin->env->cls, GNUNET_NO,
+ &plugin->mac_address,
+ sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
}
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_FRAGMENT with size: %u; mac endpoint %p: %s\n",
- ntohs (hdr->size), session_light->macendpoint,
- wlan_plugin_address_to_string (NULL,
- session_light->addr.mac,
- 6));
+ plugin->mac_address = cm->mac;
+ plugin->have_mac = GNUNET_YES;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Received WLAN_HELPER_CONTROL message with MAC address `%s' for peer `%s'\n",
+ mac_to_string (&cm->mac),
+ GNUNET_i2s (plugin->env->my_identity));
+ plugin->env->notify_address (plugin->env->cls, GNUNET_YES,
+ &plugin->mac_address,
+ sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
+ break;
+ case GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER:
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Got data message from helper with %u bytes\n",
+ msize);
GNUNET_STATISTICS_update (plugin->env->stats,
- _("# wlan fragments received"), 1, GNUNET_NO);
- int ret =
- GNUNET_DEFRAGMENT_process_fragment (session_light->macendpoint->defrag,
- hdr);
-
- if (ret == GNUNET_NO)
- {
- session_light->macendpoint->dups++;
- }
- else if (ret == GNUNET_OK)
+ _("# DATA messages received via WLAN"), 1,
+ GNUNET_NO);
+ if (msize < sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage))
{
- session_light->macendpoint->fragc++;
+ GNUNET_break (0);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Size of packet is too small (%u bytes)\n",
+ msize);
+ break;
}
- set_next_send (plugin);
-
- }
+ rxinfo = (const struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) hdr;
- //ACK
-
- else if (ntohs (hdr->type) == GNUNET_MESSAGE_TYPE_FRAGMENT_ACK)
- {
- GNUNET_assert (session_light != NULL);
- if (session_light->macendpoint == NULL)
+ /* check if message is actually for us */
+ if (0 != memcmp (&rxinfo->frame.addr3, &mac_bssid_gnunet,
+ sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
{
- session_light->macendpoint =
- get_macendpoint (plugin, &session_light->addr, GNUNET_NO);
+ /* Not the GNUnet BSSID */
+ break;
}
-
- if (session_light->macendpoint == NULL)
+ if ( (0 != memcmp (&rxinfo->frame.addr1, &bc_all_mac,
+ sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) &&
+ (0 != memcmp (&rxinfo->frame.addr1, &plugin->mac_address,
+ sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))) )
{
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Macendpoint does not exist for this GNUNET_MESSAGE_TYPE_FRAGMENT_ACK size: %u; %s\n",
- ntohs (hdr->size), wlan_plugin_address_to_string (NULL,
- session_light->addr.mac,
- 6));
- return;
+ /* Neither broadcast nor specifically for us */
+ break;
}
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Func wlan_data_helper got GNUNET_MESSAGE_TYPE_FRAGMENT_ACK size: %u; mac endpoint: %p; %s\n",
- ntohs (hdr->size), session_light->macendpoint,
- wlan_plugin_address_to_string (NULL,
- session_light->addr.mac,
- 6));
- fm = session_light->macendpoint->sending_messages_head;
- while (fm != NULL)
+ if (0 == memcmp (&rxinfo->frame.addr2, &plugin->mac_address,
+ sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)))
{
- fm2 = fm->next;
- GNUNET_STATISTICS_update (plugin->env->stats, _("# wlan acks received"),
- 1, GNUNET_NO);
- int ret = GNUNET_FRAGMENT_process_ack (fm->fragcontext, hdr);
-
- if (ret == GNUNET_OK)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Got last ack, finished fragment message %p\n", fm);
- session_light->macendpoint->acks++;
- fm->session->last_activity = GNUNET_TIME_absolute_get ();
- session_light->macendpoint->last_activity = fm->session->last_activity;
- free_fragment_message (plugin, fm);
- check_fragment_queue (plugin);
- return;
- }
- if (ret == GNUNET_NO)
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Got ack for: %p\n", fm);
- session_light->macendpoint->acks++;
- return;
- }
- if (ret == GNUNET_SYSERR)
- {
-
- }
-
- fm = fm2;
+ /* packet is FROM us, thus not FOR us */
+ break;
}
-
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "WLAN fragment not in fragment list\n");
- return;
-
- }
- else
- {
- // TODO Wrong data?
- GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, PLUGIN_LOG_NAME,
- "WLAN packet inside the WLAN helper packet has not the right type: %u size: %u\n",
- ntohs (hdr->type), ntohs (hdr->size));
+
+ GNUNET_STATISTICS_update (plugin->env->stats,
+ _("# WLAN DATA messages processed"),
+ 1, GNUNET_NO);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Receiving %u bytes of data from MAC `%s'\n",
+ (unsigned int) (msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)),
+ mac_to_string (&rxinfo->frame.addr2));
+ mas.endpoint = create_macendpoint (plugin, &rxinfo->frame.addr2);
+ mas.session = NULL;
+ (void) GNUNET_SERVER_mst_receive (plugin->helper_payload_tokenizer,
+ &mas,
+ (const char*) &rxinfo[1],
+ msize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage),
+ GNUNET_YES, GNUNET_NO);
+ break;
+ default:
GNUNET_break (0);
- return;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Unexpected message of type %u (%u bytes)",
+ ntohs (hdr->type), ntohs (hdr->size));
+ break;
}
+ return GNUNET_OK;
+}
-#if 0
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Helper finished\n");
-#endif
-}
/**
- * Function to print mac addresses nice *
- * @param pointer to 6 byte with the mac address
- * @return pointer to the chars which hold the print out
+ * Task to (periodically) send a HELLO beacon
+ *
+ * @param cls pointer to the plugin struct
+ * @param tc scheduler context
*/
-static const char *
-macprinter (const u_int8_t * mac)
+static void
+send_hello_beacon (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
{
- static char macstr[20];
+ struct Plugin *plugin = cls;
+ uint16_t size;
+ uint16_t hello_size;
+ struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radioHeader;
+ const struct GNUNET_MessageHeader *hello;
+
+ hello = plugin->env->get_our_hello ();
+ hello_size = GNUNET_HELLO_size ((struct GNUNET_HELLO_Message *) hello);
+ GNUNET_assert (sizeof (struct WlanHeader) + hello_size <= WLAN_MTU);
+ size = sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) + hello_size;
+ {
+ char buf[size] GNUNET_ALIGN;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending %u byte HELLO beacon\n",
+ (unsigned int) size);
+ radioHeader = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage*) buf;
+ get_radiotap_header (NULL, radioHeader, size);
+ get_wlan_header (plugin, &radioHeader->frame, &bc_all_mac, size);
+ memcpy (&radioHeader[1], hello, hello_size);
+ if (NULL !=
+ GNUNET_HELPER_send (plugin->suid_helper,
+ &radioHeader->header,
+ GNUNET_YES /* can drop */,
+ NULL, NULL))
+ GNUNET_STATISTICS_update (plugin->env->stats, _("# HELLO beacons sent via WLAN"),
+ 1, GNUNET_NO);
+ }
+ plugin->beacon_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+ (HELLO_BEACON_SCALING_FACTOR,
+ plugin->mac_count + 1),
+ &send_hello_beacon,
+ plugin);
- GNUNET_snprintf (macstr, sizeof (macstr), "%X:%X:%X:%X:%X:%X", mac[0], mac[1],
- mac[2], mac[3], mac[4], mac[5]);
- return macstr;
}
+
/**
- * Function for the scheduler if a mac endpoint times out
- * @param cls pointer to the MacEndpoint
- * @param tc pointer to the GNUNET_SCHEDULER_TaskContext
+ * Another peer has suggested an address for this
+ * peer and transport plugin. Check that this could be a valid
+ * address. If so, consider adding it to the list
+ * of addresses.
+ *
+ * @param cls closure
+ * @param addr pointer to the address
+ * @param addrlen length of addr
+ * @return GNUNET_OK if this is a plausible address for this peer
+ * and transport
*/
-static void
-macendpoint_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+static int
+wlan_plugin_address_suggested (void *cls, const void *addr, size_t addrlen)
{
- struct MacEndpoint *endpoint = cls;
+ struct Plugin *plugin = cls;
- GNUNET_assert (endpoint != NULL);
- endpoint->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
- {
- return;
+ if (addrlen != sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
}
- if (GNUNET_TIME_absolute_get_remaining
- (GNUNET_TIME_absolute_add
- (endpoint->last_activity, MACENDPOINT_TIMEOUT)).rel_value == 0)
+ if (GNUNET_YES != plugin->have_mac)
{
- GNUNET_assert (endpoint->plugin != NULL);
- GNUNET_STATISTICS_update (endpoint->plugin->env->stats,
- _("# wlan mac endpoints timeouts"), 1, GNUNET_NO);
- free_macendpoint (endpoint->plugin, endpoint);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Rejecting MAC `%s': I don't know my MAC!\n",
+ mac_to_string (addr));
+ return GNUNET_NO; /* don't know my MAC */
}
- else
+ if (0 != memcmp (addr,
+ &plugin->mac_address,
+ addrlen))
{
- endpoint->timeout_task =
- GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
- endpoint);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Rejecting MAC `%s': not my MAC!\n",
+ mac_to_string (addr));
+ return GNUNET_NO; /* not my MAC */
}
+ return GNUNET_OK;
}
+
/**
- * function to create an macendpoint
- * @param plugin pointer to the plugin struct
- * @param addr pointer to the macaddress
- * @return returns a macendpoint
+ * Function called for a quick conversion of the binary address to
+ * a numeric address. Note that the caller must not free the
+ * address and that the next call to this function is allowed
+ * to override the address again.
+ *
+ * @param cls closure
+ * @param addr binary address
+ * @param addrlen length of the address
+ * @return string representing the same address
*/
-static struct MacEndpoint *
-create_macendpoint (struct Plugin *plugin, const struct GNUNET_TRANSPORT_WLAN_MacAddress *addr)
+static const char *
+wlan_plugin_address_to_string (void *cls, const void *addr, size_t addrlen)
{
- struct MacEndpoint *newend = GNUNET_malloc (sizeof (struct MacEndpoint));
-
- GNUNET_assert (plugin != NULL);
- GNUNET_STATISTICS_update (plugin->env->stats,
- _("# wlan mac endpoints created"), 1, GNUNET_NO);
- newend->addr = *addr;
- newend->plugin = plugin;
- newend->addr = *addr;
- newend->fragment_messages_out_count = 0;
- newend->defrag =
- GNUNET_DEFRAGMENT_context_create (plugin->env->stats, WLAN_MTU,
- MESSAGES_IN_DEFRAG_QUEUE_PER_MAC,
- newend, &wlan_data_message_handler,
- &add_ack_for_send);
- newend->last_activity = GNUNET_TIME_absolute_get ();
- newend->timeout_task =
- GNUNET_SCHEDULER_add_delayed (MACENDPOINT_TIMEOUT, &macendpoint_timeout,
- newend);
+ const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac;
- plugin->mac_count++;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
- plugin->mac_count, GNUNET_NO);
- GNUNET_CONTAINER_DLL_insert_tail (plugin->mac_head, plugin->mac_tail, newend);
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "New Mac Endpoint %p: %s\n", newend,
- wlan_plugin_address_to_string (NULL, newend->addr.mac, 6));
- return newend;
+ if (sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress) != addrlen)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ mac = addr;
+ return GNUNET_strdup (mac_to_string (mac));
}
+
/**
- * Function used for to process the data from the suid process
+ * Convert the transports address to a nice, human-readable format.
*
- * @param cls the plugin handle
- * @param client client that send the data (not used)
- * @param hdr header of the GNUNET_MessageHeader
+ * @param cls closure
+ * @param type name of the transport that generated the address
+ * @param addr one of the addresses of the host, NULL for the last address
+ * the specific address format depends on the transport
+ * @param addrlen length of the address
+ * @param numeric should (IP) addresses be displayed in numeric form?
+ * @param timeout after how long should we give up?
+ * @param asc function to call on each string
+ * @param asc_cls closure for asc
*/
static void
-wlan_process_helper (void *cls, void *client,
- const struct GNUNET_MessageHeader *hdr)
+wlan_plugin_address_pretty_printer (void *cls, const char *type,
+ const void *addr, size_t addrlen,
+ int numeric,
+ struct GNUNET_TIME_Relative timeout,
+ GNUNET_TRANSPORT_AddressStringCallback asc,
+ void *asc_cls)
{
- struct Plugin *plugin = cls;
- struct ieee80211_frame *wlanIeeeHeader = NULL;
- struct Session_light *session_light = NULL;
- struct Radiotap_rx *rxinfo;
- const struct GNUNET_MessageHeader *temp_hdr = NULL;
-
- int datasize = 0;
- int pos;
+ const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac;
+ char *ret;
- GNUNET_assert (plugin != NULL);
- switch (ntohs (hdr->type))
+ if (sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress) != addrlen)
{
- case GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA:
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Func wlan_process_helper got GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA size: %u\n",
- ntohs (hdr->size));
- GNUNET_STATISTICS_update (plugin->env->stats,
- _("# wlan WLAN_HELPER_DATA received"), 1,
- GNUNET_NO);
- //call wlan_process_helper with the message inside, later with wlan: analyze signal
- if (ntohs (hdr->size) <
- sizeof (struct ieee80211_frame) +
- 2 * sizeof (struct GNUNET_MessageHeader) + sizeof (struct Radiotap_rx))
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Size of packet is too small; size: %u min size: %u\n",
- ntohs (hdr->size),
- sizeof (struct ieee80211_frame) +
- sizeof (struct GNUNET_MessageHeader));
- //GNUNET_break (0);
- /* FIXME: restart SUID process */
- return;
- }
-
- rxinfo = (struct Radiotap_rx *) &hdr[1];
- wlanIeeeHeader = (struct ieee80211_frame *) &rxinfo[1];
-
- //process only if it is an broadcast or for this computer both with the gnunet bssid
-
- //check for bssid
- if (memcmp
- (&(wlanIeeeHeader->i_addr3), &mac_bssid_gnunet,
- sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0)
- {
- //check for broadcast or mac
- if ((memcmp
- (&(wlanIeeeHeader->i_addr1), &bc_all_mac,
- sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0) ||
- (memcmp
- (&(wlanIeeeHeader->i_addr1), &(plugin->mac_address),
- sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0))
- {
- //if packet is from us return
- if ((memcmp
- (&(wlanIeeeHeader->i_addr2), &(plugin->mac_address),
- sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0))
- {
- return;
- }
- // process the inner data
-
-
- datasize =
- ntohs (hdr->size) - sizeof (struct ieee80211_frame) -
- sizeof (struct GNUNET_MessageHeader) - sizeof (struct Radiotap_rx);
-
- session_light = GNUNET_malloc (sizeof (struct Session_light));
- memcpy (&session_light->addr, &(wlanIeeeHeader->i_addr2),
- sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
- //session_light->session = search_session(plugin,session_light->addr);
- GNUNET_STATISTICS_update (plugin->env->stats,
- _("# wlan messages for this client received"),
- 1, GNUNET_NO);
-
- pos = 0;
- while (pos < datasize)
- {
- temp_hdr = (struct GNUNET_MessageHeader *) &wlanIeeeHeader[1] + pos;
- if (ntohs (temp_hdr->size) <= datasize + pos)
- {
- GNUNET_STATISTICS_update (plugin->env->stats,
- _
- ("# wlan messages inside WLAN_HELPER_DATA received"),
- 1, GNUNET_NO);
- wlan_data_helper (plugin, session_light, temp_hdr, rxinfo);
- }
- else
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Size of packet is too small; size: %u > size of packet: %u\n",
- ntohs (temp_hdr->size), datasize + pos);
- }
- pos += ntohs (temp_hdr->size);
-
- }
-
- //clean up
- GNUNET_free (session_light);
- }
- else
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Func wlan_process_helper got wrong MAC: %s\n",
- macprinter (wlanIeeeHeader->i_addr1));
- }
- }
- else
- {
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Func wlan_process_helper got wrong BSSID: %s\n",
- macprinter (wlanIeeeHeader->i_addr2));
- }
- break;
- case GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL:
- //TODO more control messages
- if (ntohs (hdr->size) != sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage))
- {
- GNUNET_break (0);
- /* FIXME: restart SUID process */
- return;
- }
- memcpy (&plugin->mac_address, &hdr[1], sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Received WLAN_HELPER_CONTROL message with transport of address %s\n",
- wlan_plugin_address_to_string (cls, &plugin->mac_address,
- sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)));
- plugin->env->notify_address (plugin->env->cls, GNUNET_YES,
- &plugin->mac_address,
- sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
- break;
- default:
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "Func wlan_process_helper got unknown message with number %u, size %u\n",
- ntohs (hdr->type), ntohs (hdr->size));
-
-#if DEBUG_WLAN > 1
- hexdump (hdr, GNUNET_MIN (ntohs (hdr->size), 256));
-#endif
- GNUNET_break (0);
+ /* invalid address */
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ _("WLAN address with invalid size encountered\n"));
+ asc (asc_cls, NULL);
return;
}
+ mac = addr;
+ ret = GNUNET_strdup (mac_to_string (mac));
+ asc (asc_cls, ret);
+ GNUNET_free (ret);
+ asc (asc_cls, NULL);
}
+
/**
- * Exit point from the plugin.
+ * Exit point from the plugin.
+ *
* @param cls pointer to the api struct
*/
-
-//FIXME cleanup
void *
libgnunet_plugin_transport_wlan_done (void *cls)
{
struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
struct Plugin *plugin = api->cls;
- struct MacEndpoint *endpoint = plugin->mac_head;
+ struct MacEndpoint *endpoint;
struct MacEndpoint *endpoint_next;
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "libgnunet_plugin_transport_wlan_done started\n");
- wlan_transport_stop_wlan_helper (plugin);
-
- GNUNET_assert (cls != NULL);
- //free sessions
- while (endpoint != NULL)
+ if (NULL == plugin)
+ {
+ GNUNET_free (api);
+ return NULL;
+ }
+ if (GNUNET_SCHEDULER_NO_TASK != plugin->beacon_task)
+ {
+ GNUNET_SCHEDULER_cancel (plugin->beacon_task);
+ plugin->beacon_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ if (NULL != plugin->suid_helper)
+ {
+ GNUNET_HELPER_stop (plugin->suid_helper);
+ plugin->suid_helper = NULL;
+ }
+ endpoint_next = plugin->mac_head;
+ while (NULL != (endpoint = endpoint_next))
{
endpoint_next = endpoint->next;
- free_macendpoint (plugin, endpoint);
- endpoint = endpoint_next;
-
+ free_macendpoint (endpoint);
+ }
+ if (NULL != plugin->fragment_data_tokenizer)
+ {
+ GNUNET_SERVER_mst_destroy (plugin->fragment_data_tokenizer);
+ plugin->fragment_data_tokenizer = NULL;
+ }
+ if (NULL != plugin->wlan_header_payload_tokenizer)
+ {
+ GNUNET_SERVER_mst_destroy (plugin->wlan_header_payload_tokenizer);
+ plugin->wlan_header_payload_tokenizer = NULL;
+ }
+ if (NULL != plugin->helper_payload_tokenizer)
+ {
+ GNUNET_SERVER_mst_destroy (plugin->helper_payload_tokenizer);
+ plugin->helper_payload_tokenizer = NULL;
}
-
-
- if (plugin->suid_tokenizer != NULL)
- GNUNET_SERVER_mst_destroy (plugin->suid_tokenizer);
-
- if (plugin->data_tokenizer != NULL)
- GNUNET_SERVER_mst_destroy (plugin->data_tokenizer);
-
GNUNET_free_non_null (plugin->interface);
GNUNET_free (plugin);
GNUNET_free (api);
return NULL;
}
+
+/**
+ * Function called to convert a string address to
+ * a binary address.
+ *
+ * @param cls closure ('struct Plugin*')
+ * @param addr string address
+ * @param addrlen length of the address
+ * @param buf location to store the buffer
+ * @param added location to store the number of bytes in the buffer.
+ * If the function returns GNUNET_SYSERR, its contents are undefined.
+ * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ */
+static int
+wlan_string_to_address (void *cls, const char *addr, uint16_t addrlen,
+ void **buf, size_t *added)
+{
+ struct GNUNET_TRANSPORT_WLAN_MacAddress *mac;
+ unsigned int a[6];
+ unsigned int i;
+
+ if ((NULL == addr) || (addrlen == 0))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if ('\0' != addr[addrlen - 1])
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (strlen (addr) != addrlen - 1)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (6 != SSCANF (addr,
+ "%X:%X:%X:%X:%X:%X",
+ &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ mac = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
+ for (i=0;i<6;i++)
+ mac->mac[i] = a[i];
+ *buf = mac;
+ *added = sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress);
+ return GNUNET_OK;
+}
+
+
/**
* Entry point for the plugin.
*
@@ -3129,35 +1636,107 @@ libgnunet_plugin_transport_wlan_done (void *cls)
void *
libgnunet_plugin_transport_wlan_init (void *cls)
{
- //struct GNUNET_SERVICE_Context *service;
struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
struct GNUNET_TRANSPORT_PluginFunctions *api;
struct Plugin *plugin;
-
- GNUNET_assert (cls != NULL);
+ char *interface;
+ unsigned long long testmode;
+
+ /* check for 'special' mode */
+ if (NULL == env->receive)
+ {
+ /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
+ initialze the plugin or the API */
+ api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
+ api->cls = NULL;
+ api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
+ api->address_to_string = &wlan_plugin_address_to_string;
+ api->string_to_address = &wlan_string_to_address;
+ return api;
+ }
+
+ testmode = 0;
+ /* check configuration */
+ if ( (GNUNET_YES ==
+ GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE")) &&
+ ( (GNUNET_SYSERR ==
+ GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan",
+ "TESTMODE", &testmode)) ||
+ (testmode > 2) ) )
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Invalid configuration option `%s' in section `%s'\n"),
+ "TESTMODE",
+ "transport-wlan");
+ return NULL;
+ }
+ if ( (0 == testmode) &&
+ (GNUNET_YES != GNUNET_OS_check_helper_binary ("gnunet-helper-transport-wlan")) )
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Helper binary `%s' not SUID, cannot run WLAN transport\n"),
+ "gnunet-helper-transport-wlan");
+ return NULL;
+ }
+ if (GNUNET_YES !=
+ GNUNET_CONFIGURATION_get_value_string
+ (env->cfg, "transport-wlan", "INTERFACE",
+ &interface))
+ {
+ LOG (GNUNET_ERROR_TYPE_ERROR,
+ _("Missing configuration option `%s' in section `%s'\n"),
+ "INTERFACE",
+ "transport-wlan");
+ return NULL;
+ }
plugin = GNUNET_malloc (sizeof (struct Plugin));
+ plugin->interface = interface;
plugin->env = env;
- plugin->pendingsessions = 0;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan pending sessions"),
- plugin->pendingsessions, GNUNET_NO);
- plugin->mac_count = 0;
- GNUNET_STATISTICS_set (plugin->env->stats, _("# wlan mac endpoints"),
- plugin->mac_count, GNUNET_NO);
- plugin->server_write_task = GNUNET_SCHEDULER_NO_TASK;
- plugin->server_read_task = GNUNET_SCHEDULER_NO_TASK;
- plugin->server_write_delay_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_STATISTICS_set (plugin->env->stats, _("# WLAN sessions allocated"),
+ 0, GNUNET_NO);
+ GNUNET_STATISTICS_set (plugin->env->stats, _("# WLAN MAC endpoints allocated"),
+ 0, 0);
GNUNET_BANDWIDTH_tracker_init (&plugin->tracker,
GNUNET_BANDWIDTH_value_init (100 * 1024 *
1024 / 8), 100);
-
- plugin->suid_tokenizer =
- GNUNET_SERVER_mst_create (&wlan_process_helper, plugin);
-
- plugin->data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
-
- //plugin->sessions = GNUNET_malloc (sizeof (struct Sessionqueue));
- //plugin->pending_Sessions_head = GNUNET_malloc (sizeof (struct Sessionqueue));
+ plugin->fragment_data_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
+ plugin->wlan_header_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
+ plugin->helper_payload_tokenizer = GNUNET_SERVER_mst_create (&process_data, plugin);
+ plugin->beacon_task = GNUNET_SCHEDULER_add_now (&send_hello_beacon,
+ plugin);
+ switch (testmode)
+ {
+ case 0: /* normal */
+ plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan";
+ plugin->helper_argv[1] = interface;
+ plugin->helper_argv[2] = NULL;
+ plugin->suid_helper = GNUNET_HELPER_start ("gnunet-helper-transport-wlan",
+ plugin->helper_argv,
+ &handle_helper_message,
+ plugin);
+ break;
+ case 1: /* testmode, peer 1 */
+ plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy";
+ plugin->helper_argv[1] = (char *) "1";
+ plugin->helper_argv[2] = NULL;
+ plugin->suid_helper = GNUNET_HELPER_start ("gnunet-helper-transport-wlan-dummy",
+ plugin->helper_argv,
+ &handle_helper_message,
+ plugin);
+ break;
+ case 2: /* testmode, peer 2 */
+ plugin->helper_argv[0] = (char *) "gnunet-helper-transport-wlan-dummy";
+ plugin->helper_argv[1] = (char *) "2";
+ plugin->helper_argv[2] = NULL;
+ plugin->suid_helper = GNUNET_HELPER_start ("gnunet-helper-transport-wlan-dummy",
+ plugin->helper_argv,
+ &handle_helper_message,
+ plugin);
+ break;
+ default:
+ GNUNET_assert (0);
+ }
api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
api->cls = plugin;
@@ -3167,35 +1746,9 @@ libgnunet_plugin_transport_wlan_init (void *cls)
api->address_pretty_printer = &wlan_plugin_address_pretty_printer;
api->check_address = &wlan_plugin_address_suggested;
api->address_to_string = &wlan_plugin_address_to_string;
-
- //read config
-
- if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "TESTMODE"))
- {
- if (GNUNET_SYSERR ==
- GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-wlan",
- "TESTMODE", &(plugin->testmode)))
- plugin->testmode = 0; //default value
- }
-
- if (GNUNET_CONFIGURATION_have_value (env->cfg, "transport-wlan", "INTERFACE"))
- {
- if (GNUNET_CONFIGURATION_get_value_string
- (env->cfg, "transport-wlan", "INTERFACE",
- &(plugin->interface)) != GNUNET_YES)
- {
- libgnunet_plugin_transport_wlan_done (api);
- return NULL;
- }
- }
-
- //start the plugin
- wlan_transport_start_wlan_helper (plugin);
- set_next_beacon_time (plugin);
- set_next_send (plugin);
- GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, PLUGIN_LOG_NAME,
- "wlan init finished\n");
+ api->string_to_address = &wlan_string_to_address;
return api;
}
+
/* end of plugin_transport_wlan.c */
diff --git a/src/transport/plugin_transport_wlan.h b/src/transport/plugin_transport_wlan.h
index 9e1bc4f..2b70fc0 100644
--- a/src/transport/plugin_transport_wlan.h
+++ b/src/transport/plugin_transport_wlan.h
@@ -34,7 +34,27 @@
*/
#define MAC_ADDR_SIZE 6
+/**
+ * Value for "Management" in the 'frame_control' field of the
+ * struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame.
+ */
+#define IEEE80211_FC0_TYPE_MGT 0x00
+
+/**
+ * Value for "Control" in the 'frame_control' field of the
+ * struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame.
+ */
+#define IEEE80211_FC0_TYPE_CTL 0x04
+
+/**
+ * Value for DATA in the 'frame_control' field of the
+ * struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame.
+ */
+#define IEEE80211_FC0_TYPE_DATA 0x08
+
+
GNUNET_NETWORK_STRUCT_BEGIN
+
/**
* A MAC Address.
*/
@@ -59,26 +79,73 @@ struct GNUNET_TRANSPORT_WLAN_HelperControlMessage
*/
struct GNUNET_TRANSPORT_WLAN_MacAddress mac;
};
-GNUNET_NETWORK_STRUCT_END
+
/**
- * GNUnet bssid
+ * generic definitions for IEEE 802.11 frames
*/
-static const struct GNUNET_TRANSPORT_WLAN_MacAddress mac_bssid_gnunet = {
- {0x13, 0x22, 0x33, 0x44, 0x55, 0x66}
-};
+struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame
+{
+ /**
+ * 802.11 Frame Control field. A bitmask. The overall field is a
+ * 16-bit mask of the respecitve fields. The lowest two bits should
+ * be 0, then comes the "type" (2 bits, see IEEE80211_FC0_TYPE_*
+ * constants), followed by 4-bit subtype (all zeros for ad-hoc),
+ * followed by various flags (to DS, from DS, more frag, retry,
+ * power management, more data, WEP, strict), all of which we also
+ * keep at zero.
+ */
+ uint16_t frame_control GNUNET_PACKED;
+
+ /**
+ * Microseconds to reserve link (duration), 0 by default
+ */
+ uint16_t duration GNUNET_PACKED;
+
+ /**
+ * Address 1: destination address in ad-hoc mode or AP, BSSID if station,
+ */
+ struct GNUNET_TRANSPORT_WLAN_MacAddress addr1;
+
+ /**
+ * Address 2: source address if in ad-hoc-mode or station, BSSID if AP
+ */
+ struct GNUNET_TRANSPORT_WLAN_MacAddress addr2;
+
+ /**
+ * Address 3: BSSID in ad-hoc mode, Destination if station, source if AP
+ */
+ struct GNUNET_TRANSPORT_WLAN_MacAddress addr3;
+
+ /**
+ * 802.11 sequence control field; contains fragment number an sequence
+ * number (we set this to all zeros).
+ */
+ uint16_t sequence_control GNUNET_PACKED;
+
+ /**
+ * Link layer control (LLC). Set to a GNUnet-specific value.
+ */
+ u_int8_t llc[4];
+
+ /* payload */
+
+} GNUNET_PACKED;
+
/**
- * Broadcast MAC
+ * Message from the plugin to the WLAN helper: send the given message with the
+ * given connection parameters.
*/
-static const struct GNUNET_TRANSPORT_WLAN_MacAddress bc_all_mac = {
- {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
-};
+struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage
+{
+ /**
+ * Type is 'GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER'.
+ */
+ struct GNUNET_MessageHeader header;
-struct Radiotap_Send
-{
/**
* wlan send rate
*/
@@ -93,60 +160,100 @@ struct Radiotap_Send
* Transmit power expressed as unitless distance from max power set at factory calibration.
* 0 is max power. Monotonically nondecreasing with lower power levels.
*/
- uint16_t tx_power;
+ uint16_t tx_power GNUNET_PACKED;
+
+ /**
+ * IEEE Frame to transmit (the sender MAC address will be overwritten by the helper as it does not
+ * trust the plugin to set it correctly).
+ */
+ struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame frame;
+
+ /* actual payload follows */
};
/**
+ * Message from the WLAN helper to the plugin: we have received the given message with the
+ * given performance characteristics.
+ */
+/**
* struct to represent infos gathered form the radiotap fields, see RadiotapHeader for more Infos
*/
-struct Radiotap_rx
+struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage
{
+
+ /**
+ * Type is 'GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER'.
+ */
+ struct GNUNET_MessageHeader header;
+
/**
- * FIXME: not initialized properly so far. (supposed to contain
- * information about which of the fields below are actually valid).
+ * Information about which of the fields below are actually valid.
+ * 0 for none. FIXME: not properly initialized so far (always zero).
*/
- uint32_t ri_present;
+ uint32_t ri_present GNUNET_PACKED;
/**
- * IEEE80211_RADIOTAP_TSFT
+ * IEEE80211_RADIOTAP_TSFT, 0 if unknown.
*/
- uint64_t ri_mactime;
+ uint64_t ri_mactime GNUNET_PACKED;
/**
* from radiotap
* either IEEE80211_RADIOTAP_DBM_ANTSIGNAL
- * or IEEE80211_RADIOTAP_DB_ANTSIGNAL
+ * or IEEE80211_RADIOTAP_DB_ANTSIGNAL, 0 if unknown.
*/
- int32_t ri_power;
+ int32_t ri_power GNUNET_PACKED;
/**
* either IEEE80211_RADIOTAP_DBM_ANTNOISE
- * or IEEE80211_RADIOTAP_DB_ANTNOISE
+ * or IEEE80211_RADIOTAP_DB_ANTNOISE, 0 if unknown.
*/
- int32_t ri_noise;
+ int32_t ri_noise GNUNET_PACKED;
/**
- * IEEE80211_RADIOTAP_CHANNEL
+ * IEEE80211_RADIOTAP_CHANNEL, 0 if unknown.
*/
- uint32_t ri_channel;
+ uint32_t ri_channel GNUNET_PACKED;
/**
- * Frequency we use. FIXME: not properly initialized so far!
+ * Frequency we use. 0 if unknown.
*/
- uint32_t ri_freq;
+ uint32_t ri_freq GNUNET_PACKED;
/**
- * IEEE80211_RADIOTAP_RATE * 50000
+ * IEEE80211_RADIOTAP_RATE * 50000, 0 if unknown.
*/
- uint32_t ri_rate;
+ uint32_t ri_rate GNUNET_PACKED;
/**
- * IEEE80211_RADIOTAP_ANTENNA
+ * IEEE80211_RADIOTAP_ANTENNA, 0 if unknown.
*/
- uint32_t ri_antenna;
+ uint32_t ri_antenna GNUNET_PACKED;
+
+ /**
+ * IEEE Frame.
+ */
+ struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame frame;
+
+ /* followed by payload */
};
+GNUNET_NETWORK_STRUCT_END
+/**
+ * GNUnet bssid
+ */
+static const struct GNUNET_TRANSPORT_WLAN_MacAddress mac_bssid_gnunet = {
+ {0x13, 0x22, 0x33, 0x44, 0x55, 0x66}
+};
+
+
+/**
+ * Broadcast MAC
+ */
+static const struct GNUNET_TRANSPORT_WLAN_MacAddress bc_all_mac = {
+ {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
+};
#endif
diff --git a/src/transport/template_cfg_peer1.conf b/src/transport/template_cfg_peer1.conf
index ba05e93..2b8e9b2 100644
--- a/src/transport/template_cfg_peer1.conf
+++ b/src/transport/template_cfg_peer1.conf
@@ -17,6 +17,9 @@ TIMEOUT = 5 s
[transport-udp]
BROADCAST = NO
+[transport-unix]
+PORT = 12007
+
[arm]
PORT = 12005
DEFAULTSERVICES = transport
diff --git a/src/transport/template_cfg_peer2.conf b/src/transport/template_cfg_peer2.conf
index 0a0e74a..3b86137 100644
--- a/src/transport/template_cfg_peer2.conf
+++ b/src/transport/template_cfg_peer2.conf
@@ -17,6 +17,9 @@ TIMEOUT = 5 s
[transport-udp]
BROADCAST = NO
+[transport-unix]
+PORT = 12017
+
[arm]
PORT = 12014
DEFAULTSERVICES = transport
diff --git a/src/transport/test_quota_compliance_tcp_asymmetric_peer1.conf b/src/transport/test_quota_compliance_tcp_asymmetric_peer1.conf
index a7bac62..8a1dad5 100644
--- a/src/transport/test_quota_compliance_tcp_asymmetric_peer1.conf
+++ b/src/transport/test_quota_compliance_tcp_asymmetric_peer1.conf
@@ -27,6 +27,7 @@ UNIXPATH = /tmp/test_quota_compliance_tcp_peerinfo_peer1.sock
[transport]
PORT = 4091
+PLUGINS = tcp
UNIXPATH = /tmp/test_quota_compliance_tcp_transport_peer1.sock
diff --git a/src/transport/test_quota_compliance_tcp_asymmetric_peer2.conf b/src/transport/test_quota_compliance_tcp_asymmetric_peer2.conf
index 75a4fe9..bbfa8ec 100644
--- a/src/transport/test_quota_compliance_tcp_asymmetric_peer2.conf
+++ b/src/transport/test_quota_compliance_tcp_asymmetric_peer2.conf
@@ -26,5 +26,6 @@ UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
[transport]
PORT = 12010
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p2-service-transport.sock
diff --git a/src/transport/test_quota_compliance_tcp_peer1.conf b/src/transport/test_quota_compliance_tcp_peer1.conf
index ff63514..29e56fe 100644
--- a/src/transport/test_quota_compliance_tcp_peer1.conf
+++ b/src/transport/test_quota_compliance_tcp_peer1.conf
@@ -27,6 +27,7 @@ UNIXPATH = /tmp/test_quota_compliance_tcp_peerinfo_peer1.sock
[transport]
PORT = 4091
+PLUGINS = tcp
UNIXPATH = /tmp/test_quota_compliance_tcp_transport_peer1.sock
diff --git a/src/transport/test_quota_compliance_tcp_peer2.conf b/src/transport/test_quota_compliance_tcp_peer2.conf
index 18b199c..5da60d0 100644
--- a/src/transport/test_quota_compliance_tcp_peer2.conf
+++ b/src/transport/test_quota_compliance_tcp_peer2.conf
@@ -26,5 +26,6 @@ UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
[transport]
PORT = 12010
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p2-service-transport.sock
diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c
index 5fb81e1..f944fac 100644
--- a/src/transport/test_transport_api.c
+++ b/src/transport/test_transport_api.c
@@ -37,8 +37,6 @@
#include "transport.h"
#include "transport-testing.h"
-#define VERBOSE GNUNET_NO
-#define VERBOSE_ARM GNUNET_NO
#define START_ARM GNUNET_YES
@@ -52,9 +50,9 @@
*/
#define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
-#define MSIZE 2600
+#define TEST_MESSAGE_SIZE 2600
-#define MTYPE 12345
+#define TEST_MESSAGE_TYPE 12345
static char *test_source;
@@ -65,32 +63,29 @@ static char *test_name;
static int ok;
static int s_started;
+
static int s_connected;
+
static int s_sending;
static GNUNET_SCHEDULER_TaskIdentifier die_task;
static GNUNET_SCHEDULER_TaskIdentifier send_task;
-struct PeerContext *p1;
+static struct PeerContext *p1;
-struct PeerContext *p2;
+static struct PeerContext *p2;
static GNUNET_TRANSPORT_TESTING_ConnectRequest cc;
-struct GNUNET_TRANSPORT_TransmitHandle *th;
+static struct GNUNET_TRANSPORT_TransmitHandle *th;
-struct GNUNET_TRANSPORT_TESTING_handle *tth;
+static struct GNUNET_TRANSPORT_TESTING_handle *tth;
-char *cfg_file_p1;
+static char *cfg_file_p1;
-char *cfg_file_p2;
+static char *cfg_file_p2;
-#if VERBOSE
-#define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
-#else
-#define OKPP do { ok++; } while (0)
-#endif
static void
end ()
@@ -135,9 +130,9 @@ end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not ready to send data\n"));
if (s_started == GNUNET_NO)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were not started n"));
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were not started \n"));
else
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were started n"));
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peers were started \n"));
if (s_connected == GNUNET_NO)
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Peer were not connected\n"));
@@ -186,8 +181,8 @@ notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
GNUNET_i2s (&t->id));
GNUNET_free (ps);
- if ((MTYPE == ntohs (message->type)) &&
- (MSIZE == ntohs (message->size)))
+ if ((TEST_MESSAGE_TYPE == ntohs (message->type)) &&
+ (TEST_MESSAGE_SIZE == ntohs (message->size)))
{
ok = 0;
end ();
@@ -220,13 +215,13 @@ notify_ready (void *cls, size_t size, void *buf)
return 0;
}
- GNUNET_assert (size >= MSIZE);
-
+ GNUNET_assert (size >= TEST_MESSAGE_SIZE);
if (buf != NULL)
{
+ memset (buf, '\0', TEST_MESSAGE_SIZE);
hdr = buf;
- hdr->size = htons (MSIZE);
- hdr->type = htons (MTYPE);
+ hdr->size = htons (TEST_MESSAGE_SIZE);
+ hdr->type = htons (TEST_MESSAGE_TYPE);
}
char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id));
@@ -236,7 +231,7 @@ notify_ready (void *cls, size_t size, void *buf)
GNUNET_i2s (&p->id));
GNUNET_free (ps);
- return MSIZE;
+ return TEST_MESSAGE_SIZE;
}
@@ -254,7 +249,7 @@ sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s);
GNUNET_free (receiver_s);
s_sending = GNUNET_YES;
- th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, MSIZE, 0,
+ th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, TEST_MESSAGE_SIZE, 0,
TIMEOUT_TRANSMIT, &notify_ready,
p1);
}
@@ -302,6 +297,7 @@ notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
th = NULL;
}
+
static void
testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
{
@@ -317,8 +313,7 @@ testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
}
-
-void
+static void
start_cb (struct PeerContext *p, void *cls)
{
static int started;
@@ -344,6 +339,7 @@ start_cb (struct PeerContext *p, void *cls)
}
+
static void
run (void *cls, char *const *args, const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
@@ -381,9 +377,6 @@ check ()
static char *const argv[] = { "test-transport-api",
"-c",
"test_transport_api_data.conf",
-#if VERBOSE
- "-L", "DEBUG",
-#endif
NULL
};
static struct GNUNET_GETOPT_CommandLineOption options[] = {
@@ -413,13 +406,8 @@ main (int argc, char *argv[])
&test_plugin);
GNUNET_log_setup (test_name,
-#if VERBOSE
- "DEBUG",
-#else
"WARNING",
-#endif
NULL);
-
tth = GNUNET_TRANSPORT_TESTING_init ();
GNUNET_TRANSPORT_TESTING_get_config_name (argv[0], &cfg_file_p1, 1);
diff --git a/src/transport/test_transport_api_bidirectional_connect.c b/src/transport/test_transport_api_bidirectional_connect.c
index 604554c..2c4eeab 100644
--- a/src/transport/test_transport_api_bidirectional_connect.c
+++ b/src/transport/test_transport_api_bidirectional_connect.c
@@ -35,10 +35,6 @@
#include "transport.h"
#include "transport-testing.h"
-#define VERBOSE GNUNET_NO
-#define VERBOSE_ARM GNUNET_NO
-
-#define START_ARM GNUNET_YES
/**
* How long until we give up on transmitting the message?
@@ -64,26 +60,20 @@ static GNUNET_SCHEDULER_TaskIdentifier die_task;
static GNUNET_SCHEDULER_TaskIdentifier send_task;
-struct PeerContext *p1;
+static struct PeerContext *p1;
-struct PeerContext *p2;
+static struct PeerContext *p2;
static GNUNET_TRANSPORT_TESTING_ConnectRequest cc1;
static GNUNET_TRANSPORT_TESTING_ConnectRequest cc2;
-struct GNUNET_TRANSPORT_TransmitHandle *th;
-
-struct GNUNET_TRANSPORT_TESTING_handle *tth;
+static struct GNUNET_TRANSPORT_TransmitHandle *th;
-char *cfg_file_p1;
+static struct GNUNET_TRANSPORT_TESTING_handle *tth;
-char *cfg_file_p2;
+static char *cfg_file_p1;
-#if VERBOSE
-#define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
-#else
-#define OKPP do { ok++; } while (0)
-#endif
+static char *cfg_file_p2;
static void
@@ -97,9 +87,11 @@ end ()
if (die_task != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (die_task);
- if (th != NULL)
+ if (NULL != th)
+ {
GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
- th = NULL;
+ th = NULL;
+ }
GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1);
GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2);
@@ -109,24 +101,27 @@ static void
end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
die_task = GNUNET_SCHEDULER_NO_TASK;
-
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n");
-
-
if (send_task != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (send_task);
- if (cc2 != NULL)
+ if (NULL != cc2)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n"));
GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc2);
cc2 = NULL;
}
-
- if (th != NULL)
+ if (NULL != cc1)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Fail! Could not connect peers\n"));
+ GNUNET_TRANSPORT_TESTING_connect_peers_cancel (tth, cc1);
+ cc1 = NULL;
+ }
+ if (NULL != th)
+ {
GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
- th = NULL;
-
+ th = NULL;
+ }
if (p1 != NULL)
GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1);
if (p2 != NULL)
@@ -270,6 +265,7 @@ notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
th = NULL;
}
+
static void
testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
{
@@ -293,7 +289,8 @@ testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
send_task = GNUNET_SCHEDULER_add_now (&sendtask, NULL);
}
-void
+
+static void
start_cb (struct PeerContext *p, void *cls)
{
static int started;
@@ -353,9 +350,6 @@ check ()
static char *const argv[] = { "test-transport-api",
"-c",
"test_transport_api_data.conf",
-#if VERBOSE
- "-L", "DEBUG",
-#endif
NULL
};
static struct GNUNET_GETOPT_CommandLineOption options[] = {
@@ -382,11 +376,7 @@ main (int argc, char *argv[])
GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name);
GNUNET_log_setup (test_name,
-#if VERBOSE
- "DEBUG",
-#else
"WARNING",
-#endif
NULL);
GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source);
diff --git a/src/transport/test_transport_api_bidirectional_connect_peer1.conf b/src/transport/test_transport_api_bidirectional_connect_peer1.conf
index 21591b5..49fc662 100644
--- a/src/transport/test_transport_api_bidirectional_connect_peer1.conf
+++ b/src/transport/test_transport_api_bidirectional_connect_peer1.conf
@@ -3,29 +3,44 @@
SERVICEHOME = /tmp/test-transport/api-tcp-p1/
DEFAULTCONFIG = test_transport_api_bidirectional_connect_peer1.conf
-[transport-tcp]
-PORT = 12000
-TIMEOUT = 5 s
-
[arm]
-PORT = 12005
+PORT = 12000
DEFAULTSERVICES = transport
UNIXPATH = /tmp/gnunet-p1-service-arm.sock
[statistics]
-PORT = 12004
+PORT = 12001
UNIXPATH = /tmp/gnunet-p1-service-statistics.sock
[resolver]
-PORT = 12003
+PORT = 12002
UNIXPATH = /tmp/gnunet-p1-service-resolver.sock
[peerinfo]
-PORT = 12002
+PORT = 12003
UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock
[transport]
-PORT = 12001
+PORT = 12004
UNIXPATH = /tmp/gnunet-p1-service-transport.sock
#DEBUG = YES
+[transport-tcp]
+PORT = 12005
+TIMEOUT = 5 s
+
+[transport-udp]
+PORT = 12006
+TIMEOUT = 5 s
+
+[transport-unix]
+PORT = 12007
+TIMEOUT = 5 s
+
+[transport-http]
+PORT = 12008
+TIMEOUT = 5 s
+
+[transport-https]
+PORT = 12009
+TIMEOUT = 5 s \ No newline at end of file
diff --git a/src/transport/test_transport_api_bidirectional_connect_peer2.conf b/src/transport/test_transport_api_bidirectional_connect_peer2.conf
index db3ba8c..2d64351 100644
--- a/src/transport/test_transport_api_bidirectional_connect_peer2.conf
+++ b/src/transport/test_transport_api_bidirectional_connect_peer2.conf
@@ -3,17 +3,13 @@
SERVICEHOME = /tmp/test-transport/api-tcp-p2/
DEFAULTCONFIG = test_transport_api_bidirectional_connect_peer2.conf
-[transport-tcp]
-PORT = 12015
-TIMEOUT = 5 s
-
[arm]
-PORT = 12014
+PORT = 12010
DEFAULTSERVICES = transport
UNIXPATH = /tmp/gnunet-p2-service-arm.sock
[statistics]
-PORT = 12013
+PORT = 12011
UNIXPATH = /tmp/gnunet-p2-service-statistics.sock
[resolver]
@@ -21,10 +17,29 @@ PORT = 12012
UNIXPATH = /tmp/gnunet-p2-service-resolver.sock
[peerinfo]
-PORT = 12011
+PORT = 12013
UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
[transport]
-PORT = 12010
+PORT = 12014
UNIXPATH = /tmp/gnunet-p2-service-transport.sock
+[transport-tcp]
+PORT = 12015
+TIMEOUT = 5 s
+
+[transport-udp]
+PORT = 12016
+TIMEOUT = 5 s
+
+[transport-unix]
+PORT = 12017
+TIMEOUT = 5 s
+
+[transport-http]
+PORT = 12018
+TIMEOUT = 5 s
+
+[transport-https]
+PORT = 12019
+TIMEOUT = 5 s \ No newline at end of file
diff --git a/src/transport/test_transport_api_blacklisting.c b/src/transport/test_transport_api_blacklisting.c
index f8f6040..909ea57 100644
--- a/src/transport/test_transport_api_blacklisting.c
+++ b/src/transport/test_transport_api_blacklisting.c
@@ -61,9 +61,9 @@ struct GNUNET_TRANSPORT_TESTING_handle *tth;
*/
#define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
-#define MSIZE 2600
+#define TEST_MESSAGE_SIZE 2600
-#define MTYPE 12345
+#define TEST_MESSAGE_TYPE 12345
static int ok;
@@ -212,8 +212,8 @@ notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
GNUNET_i2s (&t->id));
GNUNET_free (ps);
- if ((MTYPE == ntohs (message->type)) &&
- (MSIZE == ntohs (message->size)))
+ if ((TEST_MESSAGE_TYPE == ntohs (message->type)) &&
+ (TEST_MESSAGE_SIZE == ntohs (message->size)))
{
ok = 0;
shutdown_task = GNUNET_SCHEDULER_add_now(&end, NULL);
@@ -249,13 +249,13 @@ notify_ready (void *cls, size_t size, void *buf)
return 0;
}
- GNUNET_assert (size >= MSIZE);
+ GNUNET_assert (size >= TEST_MESSAGE_SIZE);
if (buf != NULL)
{
hdr = buf;
- hdr->size = htons (MSIZE);
- hdr->type = htons (MTYPE);
+ hdr->size = htons (TEST_MESSAGE_SIZE);
+ hdr->type = htons (TEST_MESSAGE_TYPE);
}
char *ps = GNUNET_strdup (GNUNET_i2s (&p2->id));
@@ -265,7 +265,7 @@ notify_ready (void *cls, size_t size, void *buf)
GNUNET_i2s (&p->id));
GNUNET_free (ps);
- return MSIZE;
+ return TEST_MESSAGE_SIZE;
}
static void
@@ -282,7 +282,7 @@ sendtask (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
p2->no, GNUNET_i2s (&p2->id), p1->no, receiver_s);
GNUNET_free (receiver_s);
- th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, MSIZE, 0,
+ th = GNUNET_TRANSPORT_notify_transmit_ready (p2->th, &p1->id, TEST_MESSAGE_SIZE, 0,
TIMEOUT_TRANSMIT, &notify_ready,
p1);
}
diff --git a/src/transport/test_transport_api_disconnect_tcp_peer1.conf b/src/transport/test_transport_api_disconnect_tcp_peer1.conf
index 8bfa374..ebb4fd4 100644
--- a/src/transport/test_transport_api_disconnect_tcp_peer1.conf
+++ b/src/transport/test_transport_api_disconnect_tcp_peer1.conf
@@ -26,6 +26,7 @@ UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock
[transport]
PORT = 12001
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p1-service-transport.sock
#DEBUG = YES
diff --git a/src/transport/test_transport_api_disconnect_tcp_peer2.conf b/src/transport/test_transport_api_disconnect_tcp_peer2.conf
index 6bb7fad..fe6d19b 100644
--- a/src/transport/test_transport_api_disconnect_tcp_peer2.conf
+++ b/src/transport/test_transport_api_disconnect_tcp_peer2.conf
@@ -26,5 +26,6 @@ UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
[transport]
PORT = 12010
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p2-service-transport.sock
diff --git a/src/transport/test_transport_api_limited_sockets.c b/src/transport/test_transport_api_limited_sockets.c
index 8b8cdc0..e6ad84a 100644
--- a/src/transport/test_transport_api_limited_sockets.c
+++ b/src/transport/test_transport_api_limited_sockets.c
@@ -18,7 +18,7 @@
Boston, MA 02111-1307, USA.
*/
/**
- * @file transport/test_transport_api.c
+ * @file transport/test_transport_api_limited_sockets.c
* @brief base test case for transport implementations
*
* This test case serves as a base for tcp, udp, and udp-nat
@@ -69,19 +69,19 @@ static GNUNET_SCHEDULER_TaskIdentifier die_task;
static GNUNET_SCHEDULER_TaskIdentifier send_task;
-struct PeerContext *p1;
+static struct PeerContext *p1;
-struct PeerContext *p2;
+static struct PeerContext *p2;
static GNUNET_TRANSPORT_TESTING_ConnectRequest cc;
-struct GNUNET_TRANSPORT_TransmitHandle *th;
+static struct GNUNET_TRANSPORT_TransmitHandle *th;
-struct GNUNET_TRANSPORT_TESTING_handle *tth;
+static struct GNUNET_TRANSPORT_TESTING_handle *tth;
-char *cfg_file_p1;
+static char *cfg_file_p1;
-char *cfg_file_p2;
+static char *cfg_file_p2;
#if VERBOSE
#define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
@@ -228,7 +228,7 @@ testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &sendtask, NULL);
}
-void
+static void
start_cb (struct PeerContext *p, void *cls)
{
static int started;
@@ -334,11 +334,10 @@ main (int argc, char *argv[])
int res;
res = getrlimit (RLIMIT_NOFILE, &r_file_old);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Maximum number of open files was: %u/%u\n", r_file_old.rlim_cur,
r_file_old.rlim_max);
-
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Setting maximum number of open files to: %u\n", MAX_FILES);
r_file_new.rlim_cur = MAX_FILES;
r_file_new.rlim_max = r_file_old.rlim_max;
@@ -367,7 +366,7 @@ main (int argc, char *argv[])
GNUNET_free (test_name);
#if HAVE_SETRLIMIT
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Restoring previous value maximum number of open files\n");
res = setrlimit (RLIMIT_NOFILE, &r_file_old);
if (res != 0)
@@ -376,8 +375,7 @@ main (int argc, char *argv[])
return 0;
}
#endif
-
return ret;
}
-/* end of test_transport_api.c */
+/* end of test_transport_api_limited_sockets.c */
diff --git a/src/transport/test_transport_api_limited_sockets_tcp_peer1.conf b/src/transport/test_transport_api_limited_sockets_tcp_peer1.conf
index dee44f6..d29b946 100644
--- a/src/transport/test_transport_api_limited_sockets_tcp_peer1.conf
+++ b/src/transport/test_transport_api_limited_sockets_tcp_peer1.conf
@@ -26,6 +26,7 @@ UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock
[transport]
PORT = 12001
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p1-service-transport.sock
diff --git a/src/transport/test_transport_api_limited_sockets_tcp_peer2.conf b/src/transport/test_transport_api_limited_sockets_tcp_peer2.conf
index 04324f4..3c0e496 100644
--- a/src/transport/test_transport_api_limited_sockets_tcp_peer2.conf
+++ b/src/transport/test_transport_api_limited_sockets_tcp_peer2.conf
@@ -26,5 +26,6 @@ UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
[transport]
PORT = 12010
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p2-service-transport.sock
diff --git a/src/transport/test_transport_api_reliability.c b/src/transport/test_transport_api_reliability.c
index f719a42..759241c 100644
--- a/src/transport/test_transport_api_reliability.c
+++ b/src/transport/test_transport_api_reliability.c
@@ -243,7 +243,7 @@ notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
if (0 != memcmp (cbuf, &hdr[1], s - sizeof (struct TestMessage)))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Expected message %u with bits %u, but body did not match\n", n,
+ "Expected message %u with bits %u, but body did not match at position %u\n", n,
(unsigned char) n);
if (die_task != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (die_task);
diff --git a/src/transport/test_transport_api_reliability_tcp_nat_peer1.conf b/src/transport/test_transport_api_reliability_tcp_nat_peer1.conf
index 2f0b3ba..ffd3d2f 100644
--- a/src/transport/test_transport_api_reliability_tcp_nat_peer1.conf
+++ b/src/transport/test_transport_api_reliability_tcp_nat_peer1.conf
@@ -31,6 +31,7 @@ UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock
[transport]
PORT = 29542
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p1-service-transport.sock
diff --git a/src/transport/test_transport_api_reliability_tcp_nat_peer2.conf b/src/transport/test_transport_api_reliability_tcp_nat_peer2.conf
index 20ca7a0..c6020ff 100644
--- a/src/transport/test_transport_api_reliability_tcp_nat_peer2.conf
+++ b/src/transport/test_transport_api_reliability_tcp_nat_peer2.conf
@@ -30,6 +30,7 @@ UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
[transport]
PORT = 45923
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p2-service-transport.sock
diff --git a/src/transport/test_transport_api_reliability_tcp_peer1.conf b/src/transport/test_transport_api_reliability_tcp_peer1.conf
index a05165a..3be982d 100644
--- a/src/transport/test_transport_api_reliability_tcp_peer1.conf
+++ b/src/transport/test_transport_api_reliability_tcp_peer1.conf
@@ -26,5 +26,6 @@ UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock
[transport]
PORT = 12001
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p1-service-transport.sock
diff --git a/src/transport/test_transport_api_reliability_tcp_peer2.conf b/src/transport/test_transport_api_reliability_tcp_peer2.conf
index 2ceff2c..62575a9 100644
--- a/src/transport/test_transport_api_reliability_tcp_peer2.conf
+++ b/src/transport/test_transport_api_reliability_tcp_peer2.conf
@@ -26,5 +26,6 @@ UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
[transport]
PORT = 12010
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p2-service-transport.sock
#DEBUG = YES
diff --git a/src/transport/test_transport_api_restart_1peer.c b/src/transport/test_transport_api_restart_1peer.c
index b414805..b7fc7ab 100644
--- a/src/transport/test_transport_api_restart_1peer.c
+++ b/src/transport/test_transport_api_restart_1peer.c
@@ -36,8 +36,6 @@
#include "transport.h"
#include "transport-testing.h"
-#define VERBOSE GNUNET_NO
-#define VERBOSE_ARM GNUNET_NO
#define START_ARM GNUNET_YES
@@ -63,32 +61,26 @@ static GNUNET_SCHEDULER_TaskIdentifier send_task;
static GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
-struct PeerContext *p1;
+static struct PeerContext *p1;
-int p1_connected;
+static int p1_connected;
-struct PeerContext *p2;
+static struct PeerContext *p2;
-int p2_connected;
+static int p2_connected;
static GNUNET_TRANSPORT_TESTING_ConnectRequest cc;
-struct GNUNET_TRANSPORT_TransmitHandle *th;
+static struct GNUNET_TRANSPORT_TransmitHandle *th;
-struct GNUNET_TRANSPORT_TESTING_handle *tth;
+static struct GNUNET_TRANSPORT_TESTING_handle *tth;
-char *cfg_file_p1;
+static char *cfg_file_p1;
-char *cfg_file_p2;
+static char *cfg_file_p2;
static int restarted;
-#if VERBOSE
-#define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
-#else
-#define OKPP do { ok++; } while (0)
-#endif
-
static void
end ()
@@ -112,7 +104,9 @@ end ()
th = NULL;
GNUNET_TRANSPORT_TESTING_stop_peer (tth, p1);
+ p1 = NULL;
GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2);
+ p2 = NULL;
}
static void
@@ -338,16 +332,16 @@ notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
{
struct PeerContext *p = cls;
- if (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity)))
+ if ( (NULL != p1) &&
+ (0 == memcmp (peer, &p1->id, sizeof (struct GNUNET_PeerIdentity))))
{
p1_connected = GNUNET_NO;
}
- if (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity)))
+ if ( (NULL != p2) &&
+ (0 == memcmp (peer, &p2->id, sizeof (struct GNUNET_PeerIdentity))))
{
p2_connected = GNUNET_NO;
}
-
-
char *ps = GNUNET_strdup (GNUNET_i2s (&p->id));
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -358,6 +352,9 @@ notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
if (th != NULL)
GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
th = NULL;
+ if (GNUNET_SCHEDULER_NO_TASK != send_task)
+ GNUNET_SCHEDULER_cancel (send_task);
+ send_task = GNUNET_SCHEDULER_NO_TASK;
}
static void
@@ -375,7 +372,7 @@ testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
-void
+static void
start_cb (struct PeerContext *p, void *cls)
{
static int started;
@@ -434,9 +431,6 @@ check ()
static char *const argv[] = { "test-transport-api",
"-c",
"test_transport_api_data.conf",
-#if VERBOSE
- "-L", "DEBUG",
-#endif
NULL
};
static struct GNUNET_GETOPT_CommandLineOption options[] = {
@@ -461,30 +455,17 @@ main (int argc, char *argv[])
int ret;
GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name);
-
-
GNUNET_log_setup (test_name,
-#if VERBOSE
- "DEBUG",
-#else
"WARNING",
-#endif
NULL);
-
tth = GNUNET_TRANSPORT_TESTING_init ();
-
GNUNET_asprintf (&cfg_file_p1, "test_transport_api_tcp_peer1.conf");
GNUNET_asprintf (&cfg_file_p2, "test_transport_api_tcp_peer2.conf");
-
ret = check ();
-
GNUNET_free (cfg_file_p1);
GNUNET_free (cfg_file_p2);
-
GNUNET_free (test_name);
-
GNUNET_TRANSPORT_TESTING_done (tth);
-
return ret;
}
diff --git a/src/transport/test_transport_api_restart_2peers.c b/src/transport/test_transport_api_restart_2peers.c
index 86758df..1d7790c 100644
--- a/src/transport/test_transport_api_restart_2peers.c
+++ b/src/transport/test_transport_api_restart_2peers.c
@@ -36,20 +36,17 @@
#include "transport.h"
#include "transport-testing.h"
-#define VERBOSE GNUNET_NO
-#define VERBOSE_ARM GNUNET_NO
-
#define START_ARM GNUNET_YES
/**
* How long until we give up on transmitting the message?
*/
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90)
/**
* How long until we give up on transmitting the message?
*/
-#define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
+#define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
#define MTYPE 12345
@@ -63,34 +60,27 @@ static GNUNET_SCHEDULER_TaskIdentifier send_task;
static GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
-struct PeerContext *p1;
+static struct PeerContext *p1;
-struct PeerContext *p2;
+static struct PeerContext *p2;
static GNUNET_TRANSPORT_TESTING_ConnectRequest cc;
-struct GNUNET_TRANSPORT_TransmitHandle *th;
+static struct GNUNET_TRANSPORT_TransmitHandle *th;
-struct GNUNET_TRANSPORT_TESTING_handle *tth;
+static struct GNUNET_TRANSPORT_TESTING_handle *tth;
-char *cfg_file_p1;
+static char *cfg_file_p1;
-char *cfg_file_p2;
+static char *cfg_file_p2;
static int restarted;
-#if VERBOSE
-#define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
-#else
-#define OKPP do { ok++; } while (0)
-#endif
-
static void
end ()
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peers\n");
-
if (send_task != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (send_task);
send_task = GNUNET_SCHEDULER_NO_TASK;
@@ -111,18 +101,17 @@ end ()
GNUNET_TRANSPORT_TESTING_stop_peer (tth, p2);
}
+
static void
end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
die_task = GNUNET_SCHEDULER_NO_TASK;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Fail! Stopping peers\n");
-
if (restarted == GNUNET_YES)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer was restarted\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer was restarted, but communication did not resume\n");
if (restarted == GNUNET_NO)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer was NOT restarted\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peer was NOT (even) restarted\n");
if (reconnect_task != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (reconnect_task);
@@ -151,35 +140,34 @@ end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
ok = GNUNET_SYSERR;
}
+
static void
reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct PeerContext *p = cls;
reconnect_task = GNUNET_SCHEDULER_NO_TASK;
-
GNUNET_TRANSPORT_try_connect (p1->th, &p2->id);
reconnect_task =
GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect, p);
}
+
static void
restart_cb (struct PeerContext *p, void *cls)
{
static int c;
c++;
-
if (c != 2)
return;
-
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Restarted peer %u (`%4s'), issuing reconnect\n", p->no,
GNUNET_i2s (&p->id));
-
reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, p);
}
+
static void
restart (struct PeerContext *p, char *cfg_file)
{
@@ -187,9 +175,9 @@ restart (struct PeerContext *p, char *cfg_file)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Restarting peer %u (`%4s')\n", p->no,
GNUNET_i2s (&p->id));
GNUNET_TRANSPORT_TESTING_restart_peer (tth, p, cfg_file, &restart_cb, p);
- return;
}
+
static void
notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_MessageHeader *message,
@@ -248,7 +236,6 @@ notify_ready (void *cls, size_t size, void *buf)
struct GNUNET_MessageHeader *hdr;
th = NULL;
-
if (buf == NULL)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -345,8 +332,12 @@ notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
if (th != NULL)
GNUNET_TRANSPORT_notify_transmit_ready_cancel (th);
th = NULL;
+ if (GNUNET_SCHEDULER_NO_TASK != send_task)
+ GNUNET_SCHEDULER_cancel (send_task);
+ send_task = GNUNET_SCHEDULER_NO_TASK;
}
+
static void
testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
{
@@ -361,8 +352,7 @@ testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
}
-
-void
+static void
start_cb (struct PeerContext *p, void *cls)
{
static int started;
@@ -387,6 +377,7 @@ start_cb (struct PeerContext *p, void *cls)
}
+
static void
run (void *cls, char *const *args, const char *cfgfile,
const struct GNUNET_CONFIGURATION_Handle *cfg)
@@ -420,9 +411,6 @@ check ()
static char *const argv[] = { "test-transport-api",
"-c",
"test_transport_api_data.conf",
-#if VERBOSE
- "-L", "DEBUG",
-#endif
NULL
};
static struct GNUNET_GETOPT_CommandLineOption options[] = {
@@ -436,41 +424,29 @@ check ()
ok = 1;
GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv, test_name,
- "nohelp", options, &run, &ok);
+ "nohelp", options, &run, NULL);
return ok;
}
+
int
main (int argc, char *argv[])
{
int ret;
GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name);
-
-
GNUNET_log_setup (test_name,
-#if VERBOSE
- "DEBUG",
-#else
"WARNING",
-#endif
NULL);
-
tth = GNUNET_TRANSPORT_TESTING_init ();
-
GNUNET_asprintf (&cfg_file_p1, "test_transport_api_tcp_peer1.conf");
GNUNET_asprintf (&cfg_file_p2, "test_transport_api_tcp_peer2.conf");
-
ret = check ();
-
GNUNET_free (cfg_file_p1);
GNUNET_free (cfg_file_p2);
-
GNUNET_free (test_name);
-
GNUNET_TRANSPORT_TESTING_done (tth);
-
return ret;
}
diff --git a/src/transport/test_transport_api_tcp_nat_peer1.conf b/src/transport/test_transport_api_tcp_nat_peer1.conf
index 78afb3d..73f36f3 100644
--- a/src/transport/test_transport_api_tcp_nat_peer1.conf
+++ b/src/transport/test_transport_api_tcp_nat_peer1.conf
@@ -31,6 +31,7 @@ UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock
[transport]
PORT = 29542
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p1-service-transport.sock
#DEBUG = YES
diff --git a/src/transport/test_transport_api_tcp_nat_peer2.conf b/src/transport/test_transport_api_tcp_nat_peer2.conf
index d94ebb1..0bf50fd 100644
--- a/src/transport/test_transport_api_tcp_nat_peer2.conf
+++ b/src/transport/test_transport_api_tcp_nat_peer2.conf
@@ -30,5 +30,6 @@ UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
[transport]
PORT = 45923
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p2-service-transport.sock
#DEBUG = YES
diff --git a/src/transport/test_transport_api_tcp_peer1.conf b/src/transport/test_transport_api_tcp_peer1.conf
index 8bfa374..9532b73 100644
--- a/src/transport/test_transport_api_tcp_peer1.conf
+++ b/src/transport/test_transport_api_tcp_peer1.conf
@@ -27,5 +27,6 @@ UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock
[transport]
PORT = 12001
UNIXPATH = /tmp/gnunet-p1-service-transport.sock
+PLUGINS = tcp
#DEBUG = YES
diff --git a/src/transport/test_transport_api_tcp_peer2.conf b/src/transport/test_transport_api_tcp_peer2.conf
index 6bb7fad..fe6d19b 100644
--- a/src/transport/test_transport_api_tcp_peer2.conf
+++ b/src/transport/test_transport_api_tcp_peer2.conf
@@ -26,5 +26,6 @@ UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
[transport]
PORT = 12010
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p2-service-transport.sock
diff --git a/src/transport/test_transport_api_timeout.c b/src/transport/test_transport_api_timeout.c
index 9ce701a..8b92dce 100644
--- a/src/transport/test_transport_api_timeout.c
+++ b/src/transport/test_transport_api_timeout.c
@@ -40,8 +40,6 @@
#define VERBOSE GNUNET_NO
-#define VERBOSE_ARM GNUNET_NO
-
#define START_ARM GNUNET_YES
/**
@@ -65,19 +63,19 @@ static GNUNET_SCHEDULER_TaskIdentifier die_task;
static GNUNET_SCHEDULER_TaskIdentifier timer_task;
-struct GNUNET_TRANSPORT_TESTING_handle *tth;
+static struct GNUNET_TRANSPORT_TESTING_handle *tth;
-struct PeerContext *p1;
+static struct PeerContext *p1;
-struct PeerContext *p2;
+static struct PeerContext *p2;
static GNUNET_TRANSPORT_TESTING_ConnectRequest cc;
-struct GNUNET_TRANSPORT_TransmitHandle *th;
+static struct GNUNET_TRANSPORT_TransmitHandle *th;
-char *cfg_file_p1;
+static char *cfg_file_p1;
-char *cfg_file_p2;
+static char *cfg_file_p2;
static struct GNUNET_TIME_Relative time_running;
@@ -192,6 +190,7 @@ notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
th = NULL;
}
+
static void
timer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
@@ -235,7 +234,7 @@ testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
shutdown_flag = GNUNET_NO;
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Waiting for %llu seconds\n", (WAIT.rel_value) / 1000);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Waiting for %llu seconds\n", (WAIT.rel_value) / 1000);
if (die_task != GNUNET_SCHEDULER_NO_TASK)
GNUNET_SCHEDULER_cancel (die_task);
@@ -244,7 +243,8 @@ testing_connect_cb (struct PeerContext *p1, struct PeerContext *p2, void *cls)
timer_task = GNUNET_SCHEDULER_add_now (&timer, NULL);
}
-void
+
+static void
start_cb (struct PeerContext *p, void *cls)
{
static int started;
@@ -299,9 +299,6 @@ check ()
static char *const argv[] = { "test-transport-api-timeout",
"-c",
"test_transport_api_data.conf",
-#if VERBOSE
- "-L", "DEBUG",
-#endif
NULL
};
static struct GNUNET_GETOPT_CommandLineOption options[] = {
@@ -329,11 +326,7 @@ main (int argc, char *argv[])
GNUNET_TRANSPORT_TESTING_get_test_name (argv[0], &test_name);
GNUNET_log_setup (test_name,
-#if VERBOSE
- "DEBUG",
-#else
"WARNING",
-#endif
NULL);
GNUNET_TRANSPORT_TESTING_get_test_source_name (__FILE__, &test_source);
diff --git a/src/transport/test_transport_api_timeout_tcp_peer1.conf b/src/transport/test_transport_api_timeout_tcp_peer1.conf
index 89beecb..ecb599f 100644
--- a/src/transport/test_transport_api_timeout_tcp_peer1.conf
+++ b/src/transport/test_transport_api_timeout_tcp_peer1.conf
@@ -26,6 +26,7 @@ UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock
[transport]
PORT = 12001
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p1-service-transport.sock
diff --git a/src/transport/test_transport_api_timeout_tcp_peer2.conf b/src/transport/test_transport_api_timeout_tcp_peer2.conf
index a21c4f5..ba2e27e 100644
--- a/src/transport/test_transport_api_timeout_tcp_peer2.conf
+++ b/src/transport/test_transport_api_timeout_tcp_peer2.conf
@@ -28,6 +28,7 @@ UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
[transport]
PORT = 12010
+PLUGINS = tcp
UNIXPATH = /tmp/gnunet-p2-service-transport.sock
diff --git a/src/transport/test_transport_defaults.conf b/src/transport/test_transport_defaults.conf
index f553377..0939a79 100644
--- a/src/transport/test_transport_defaults.conf
+++ b/src/transport/test_transport_defaults.conf
@@ -41,9 +41,15 @@ AUTOSTART = NO
[chat]
AUTOSTART = NO
+[namestore]
+AUTOSTART = NO
+
[vpn]
AUTOSTART = NO
+[lockmanager]
+AUTOSTART = NO
+
[nat]
DISABLEV6 = YES
BINDTO = 127.0.0.1
diff --git a/src/transport/transport-testing.c b/src/transport/transport-testing.c
index 752106b..695c048 100644
--- a/src/transport/transport-testing.c
+++ b/src/transport/transport-testing.c
@@ -52,6 +52,7 @@ get_host_key (struct GNUNET_TRANSPORT_TESTING_handle *tth)
return NULL;
}
+
static struct PeerContext *
find_peer_context (struct GNUNET_TRANSPORT_TESTING_handle *tth,
const struct GNUNET_PeerIdentity *peer)
@@ -69,7 +70,8 @@ find_peer_context (struct GNUNET_TRANSPORT_TESTING_handle *tth,
return t;
}
-struct ConnectingContext *
+
+static struct ConnectingContext *
find_connecting_context (struct GNUNET_TRANSPORT_TESTING_handle *tth,
struct PeerContext *p1, struct PeerContext *p2)
{
@@ -88,6 +90,7 @@ find_connecting_context (struct GNUNET_TRANSPORT_TESTING_handle *tth,
return cc;
}
+
static void
notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_ATS_Information *ats, uint32_t ats_count)
@@ -134,6 +137,7 @@ notify_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
}
}
+
static void
notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
{
@@ -167,6 +171,7 @@ notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
p->nd (p->cb_cls, peer);
}
+
static void
notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_MessageHeader *message,
@@ -180,6 +185,7 @@ notify_receive (void *cls, const struct GNUNET_PeerIdentity *peer,
p->rec (p->cb_cls, peer, message, ats, ats_count);
}
+
static void
get_hello (void *cb_cls, const struct GNUNET_MessageHeader *message)
{
@@ -307,11 +313,7 @@ GNUNET_TRANSPORT_TESTING_start_peer (struct GNUNET_TRANSPORT_TESTING_handle
GNUNET_OS_start_process (GNUNET_YES,
NULL, NULL, "gnunet-service-arm",
"gnunet-service-arm", "-c", cfgname,
-#if VERBOSE_PEERS
- "-L", "DEBUG",
-#else
"-L", "ERROR",
-#endif
NULL);
p->no = peer_id;
@@ -361,10 +363,8 @@ GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_handle
GNUNET_assert (p->servicehome != NULL);
/* shutdown */
-#if VERBOSE
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
"Stopping peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id));
-#endif
if (p->ghh != NULL)
GNUNET_TRANSPORT_get_hello_cancel (p->ghh);
p->ghh = NULL;
@@ -377,7 +377,7 @@ GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_handle
if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
GNUNET_OS_process_wait (p->arm_proc);
- GNUNET_OS_process_close (p->arm_proc);
+ GNUNET_OS_process_destroy (p->arm_proc);
p->arm_proc = NULL;
}
if (p->hello != NULL)
@@ -390,11 +390,8 @@ GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_handle
/* start */
-#if VERBOSE
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
"Restarting peer %u (`%s')\n", p->no, GNUNET_i2s (&p->id));
-#endif
-
sleep (5); // YUCK!
if (GNUNET_DISK_file_test (cfgname) == GNUNET_NO)
@@ -424,11 +421,7 @@ GNUNET_TRANSPORT_TESTING_restart_peer (struct GNUNET_TRANSPORT_TESTING_handle
GNUNET_OS_start_process (GNUNET_YES,
NULL, NULL, "gnunet-service-arm",
"gnunet-service-arm", "-c", cfgname,
-#if VERBOSE_PEERS
- "-L", "DEBUG",
-#else
"-L", "ERROR",
-#endif
NULL);
p->th =
@@ -451,6 +444,7 @@ fail:
return GNUNET_SYSERR;
}
+
/**
* shutdown the given peer
* @param tth testing handle
@@ -461,53 +455,49 @@ GNUNET_TRANSPORT_TESTING_stop_peer (struct GNUNET_TRANSPORT_TESTING_handle *tth,
struct PeerContext *p)
{
GNUNET_assert (p != NULL);
-
if (p->ghh != NULL)
+ {
GNUNET_TRANSPORT_get_hello_cancel (p->ghh);
- p->ghh = NULL;
-
+ p->ghh = NULL;
+ }
if (p->th != NULL)
GNUNET_TRANSPORT_disconnect (p->th);
-
if (NULL != p->arm_proc)
{
if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
GNUNET_OS_process_wait (p->arm_proc);
- GNUNET_OS_process_close (p->arm_proc);
+ GNUNET_OS_process_destroy (p->arm_proc);
p->arm_proc = NULL;
}
-
if (p->hostkeyfile != NULL)
{
GNUNET_DISK_directory_remove (p->hostkeyfile);
GNUNET_free (p->hostkeyfile);
}
-
if (p->servicehome != NULL)
{
GNUNET_DISK_directory_remove (p->servicehome);
GNUNET_free (p->servicehome);
}
-
if (p->hello != NULL)
+ {
GNUNET_free (p->hello);
- p->hello = NULL;
-
+ p->hello = NULL;
+ }
if (p->cfg != NULL)
+ {
GNUNET_CONFIGURATION_destroy (p->cfg);
- p->cfg = NULL;
-
+ p->cfg = NULL;
+ }
GNUNET_CONTAINER_DLL_remove (tth->p_head, tth->p_tail, p);
-
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
"Peer %u (`%s') stopped \n", p->no,
GNUNET_i2s (&p->id));
-
GNUNET_free (p);
- p = NULL;
}
+
/**
* Connect the given peers and call the callback when both peers report the
* inbound connection. Remarks: start_peer's notify_connect callback can be called
@@ -534,24 +524,18 @@ GNUNET_TRANSPORT_TESTING_connect_peers (struct GNUNET_TRANSPORT_TESTING_handle *
GNUNET_assert (p1 != NULL);
GNUNET_assert (p2 != NULL);
-
cc->p1 = p1;
cc->p2 = p2;
-
cc->cb = cb;
if (cls != NULL)
cc->cb_cls = cls;
else
cc->cb_cls = cc;
-
cc->th_p1 = p1->th;
cc->th_p2 = p2->th;
-
GNUNET_assert (cc->th_p1 != NULL);
GNUNET_assert (cc->th_p2 != NULL);
-
GNUNET_CONTAINER_DLL_insert (tth->cc_head, tth->cc_tail, cc);
-
cc->tct = GNUNET_SCHEDULER_add_now (&try_connect, cc);
GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
"New connect request %X\n", cc);
@@ -559,6 +543,7 @@ GNUNET_TRANSPORT_TESTING_connect_peers (struct GNUNET_TRANSPORT_TESTING_handle *
return cc;
}
+
/**
* Cancel the request to connect two peers
* Tou MUST cancel the request if you stop the peers before the peers connected succesfully
@@ -627,6 +612,7 @@ GNUNET_TRANSPORT_TESTING_done (struct GNUNET_TRANSPORT_TESTING_handle *tth)
tth = NULL;
}
+
/**
* Initialize the transport testing
* @return transport testing handle
@@ -661,7 +647,7 @@ GNUNET_TRANSPORT_TESTING_init ()
return NULL;
}
- if (GNUNET_YES != GNUNET_DISK_file_size (hostkeys_file, &fs, GNUNET_YES))
+ if (GNUNET_OK != GNUNET_DISK_file_size (hostkeys_file, &fs, GNUNET_YES, GNUNET_YES))
fs = 0;
if (0 != (fs % HOSTKEYFILESIZE))
@@ -722,6 +708,7 @@ extract_filename (const char *file)
return res;
}
+
/**
* Extracts the test filename from an absolute file name and removes the extension
* @param file absolute file name
@@ -781,7 +768,8 @@ GNUNET_TRANSPORT_TESTING_get_test_source_name (const char *file, char **dest)
/**
- * Extracts the plugin anme from an absolute file name and the test name
+ * Extracts the plugin name from an absolute file name and the test name
+ *
* @param file absolute file name
* @param test test name
* @param dest where to store result
@@ -790,43 +778,39 @@ void
GNUNET_TRANSPORT_TESTING_get_test_plugin_name (const char *file,
const char *test, char **dest)
{
+ char *filename;
+ char *dotexe;
char *e = extract_filename (file);
char *t = extract_filename (test);
- char *filename = NULL;
- char *dotexe;
-
- if (e == NULL)
+ if (NULL == e)
goto fail;
-
/* remove "lt-" */
filename = strstr (e, "tes");
- if (filename == NULL)
+ if (NULL == filename)
goto fail;
-
/* remove ".exe" */
if (NULL != (dotexe = strstr (filename, ".exe")))
dotexe[0] = '\0';
/* find last _ */
filename = strstr (filename, t);
- if (filename == NULL)
+ if (NULL == filename)
goto fail;
-
/* copy plugin */
filename += strlen (t);
- filename++;
+ if ('\0' != *filename)
+ filename++;
GNUNET_asprintf (dest, "%s", filename);
goto suc;
-
fail:
(*dest) = NULL;
suc:
GNUNET_free (t);
GNUNET_free (e);
-
}
+
/**
* This function takes the filename (e.g. argv[0), removes a "lt-"-prefix and
* if existing ".exe"-prefix and adds the peer-number
@@ -843,30 +827,23 @@ GNUNET_TRANSPORT_TESTING_get_config_name (const char *file, char **dest,
char *backup = filename;
char *dotexe;
- if (filename == NULL)
+ if (NULL == filename)
goto fail;
-
/* remove "lt-" */
filename = strstr (filename, "tes");
- if (filename == NULL)
+ if (NULL == filename)
goto fail;
-
/* remove ".exe" */
if (NULL != (dotexe = strstr (filename, ".exe")))
dotexe[0] = '\0';
-
- goto suc;
-
+ GNUNET_asprintf (dest, "%s_peer%u.conf", filename, count);
+ GNUNET_free (backup);
+ return;
fail:
(*dest) = NULL;
- return;
-
-suc:
- /* create cfg filename */
- GNUNET_asprintf (dest, "%s_peer%u.conf", filename, count);
GNUNET_free (backup);
}
-/* end of transport_testing.h */
+/* end of transport-testing.c */
diff --git a/src/transport/transport.conf.in b/src/transport/transport.conf.in
index ff81ff0..9a6f5d9 100644
--- a/src/transport/transport.conf.in
+++ b/src/transport/transport.conf.in
@@ -9,7 +9,7 @@ BINARY = gnunet-service-transport
NEIGHBOUR_LIMIT = 50
ACCEPT_FROM = 127.0.0.1;
ACCEPT_FROM6 = ::1;
-PLUGINS = tcp
+PLUGINS = tcp udp
UNIXPATH = /tmp/gnunet-service-transport.sock
BLACKLIST_FILE = $SERVICEHOME/blacklist
# This could possibly be relaxed
@@ -25,6 +25,8 @@ UNIX_MATCH_GID = YES
# REJECT_FROM6 =
# PREFIX = valgrind --leak-check=full
+[transport-unix]
+PORT = 22086
[transport-tcp]
# Use 0 to ONLY advertise as a peer behind NAT (no port binding)
diff --git a/src/transport/transport.h b/src/transport/transport.h
index ff68188..e0b8819 100644
--- a/src/transport/transport.h
+++ b/src/transport/transport.h
@@ -33,11 +33,6 @@
#define DEBUG_TRANSPORT GNUNET_EXTRA_LOGGING
-#define DEBUG_TRANSPORT_TIMEOUT GNUNET_EXTRA_LOGGING
-
-#define DEBUG_TRANSPORT_DISCONNECT GNUNET_EXTRA_LOGGING
-
-#define DEBUG_TRANSPORT_API GNUNET_EXTRA_LOGGING
/**
* For how long do we allow unused bandwidth
@@ -289,7 +284,7 @@ struct AddressLookupMessage
{
/**
- * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_LOOKUP
+ * Type will be GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING
*/
struct GNUNET_MessageHeader header;
diff --git a/src/transport/transport_api.c b/src/transport/transport_api.c
index 9ff5cec..b97a245 100644
--- a/src/transport/transport_api.c
+++ b/src/transport/transport_api.c
@@ -342,10 +342,8 @@ neighbour_add (struct GNUNET_TRANSPORT_Handle *h,
{
struct Neighbour *n;
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating entry for neighbour `%4s'.\n",
GNUNET_i2s (pid));
-#endif
n = GNUNET_malloc (sizeof (struct Neighbour));
n->id = *pid;
n->h = h;
@@ -416,10 +414,8 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
GNUNET_assert (h->client != NULL);
if (msg == NULL)
{
-#if DEBUG_TRANSPORT_API
- LOG (GNUNET_ERROR_TYPE_INFO,
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
"Error receiving from transport service, disconnecting temporarily.\n");
-#endif
disconnect_and_schedule_reconnect (h);
return;
}
@@ -435,11 +431,9 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
GNUNET_break (0);
break;
}
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Receiving (my own) `%s' message, I am `%4s'.\n", "HELLO",
GNUNET_i2s (&me));
-#endif
GNUNET_free_non_null (h->my_hello);
h->my_hello = NULL;
if (size < sizeof (struct GNUNET_MessageHeader))
@@ -474,10 +468,8 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
break;
}
ats = (const struct GNUNET_ATS_Information *) &cim[1];
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message for `%4s'.\n",
"CONNECT", GNUNET_i2s (&cim->id));
-#endif
n = neighbour_find (h, &cim->id);
if (n != NULL)
{
@@ -496,10 +488,8 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
}
dim = (const struct DisconnectInfoMessage *) msg;
GNUNET_break (ntohl (dim->reserved) == 0);
-#if DEBUG_TRANSPORT_API_DISCONNECT
LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message for `%4s'.\n",
"DISCONNECT", GNUNET_i2s (&dim->peer));
-#endif
n = neighbour_find (h, &dim->peer);
if (n == NULL)
{
@@ -515,10 +505,8 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
break;
}
okm = (const struct SendOkMessage *) msg;
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message, transmission %s.\n",
"SEND_OK", ntohl (okm->success) == GNUNET_OK ? "succeeded" : "failed");
-#endif
n = neighbour_find (h, &okm->peer);
if (n == NULL)
break;
@@ -536,9 +524,7 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
}
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_RECV:
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message.\n", "RECV");
-#endif
if (size <
sizeof (struct InboundMessage) + sizeof (struct GNUNET_MessageHeader))
{
@@ -555,10 +541,8 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
GNUNET_break (0);
break;
}
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %u from `%4s'.\n",
ntohs (imm->type), GNUNET_i2s (&im->peer));
-#endif
n = neighbour_find (h, &im->peer);
if (n == NULL)
{
@@ -569,9 +553,7 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg)
h->rec (h->cls, &im->peer, imm, ats, ats_count);
break;
case GNUNET_MESSAGE_TYPE_TRANSPORT_SET_QUOTA:
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Receiving `%s' message.\n", "SET_QUOTA");
-#endif
if (size != sizeof (struct QuotaSetMessage))
{
GNUNET_break (0);
@@ -653,10 +635,8 @@ transport_notify_ready (void *cls, size_t size, void *buf)
{
GNUNET_CONTAINER_DLL_remove (h->control_head, h->control_tail, th);
nret = th->notify (th->notify_cls, size, &cbuf[ret]);
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Added %u bytes of control message at %u\n",
nret, ret);
-#endif
GNUNET_free (th);
ret += nret;
size -= nret;
@@ -714,10 +694,8 @@ transport_notify_ready (void *cls, size_t size, void *buf)
}
/* if there are more pending messages, try to schedule those */
schedule_transmission (h);
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting %u bytes to transport service\n",
ret);
-#endif
return ret;
}
@@ -750,11 +728,9 @@ schedule_transmission_task (void *cls,
n->th = NULL;
GNUNET_assert (n == GNUNET_CONTAINER_heap_remove_root (h->ready_heap));
n->hn = NULL;
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Signalling timeout for transmission to peer %s due to congestion\n",
GNUNET_i2s (&n->id));
-#endif
GNUNET_assert (0 == th->notify (th->notify_cls, 0, NULL));
GNUNET_free (th);
}
@@ -771,9 +747,7 @@ schedule_transmission_task (void *cls,
return; /* no pending messages */
size = n->th->notify_size + sizeof (struct OutboundMessage);
}
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Calling notify_transmit_ready\n");
-#endif
h->cth =
GNUNET_CLIENT_notify_transmit_ready (h->client, size,
GNUNET_TIME_UNIT_FOREVER_REL,
@@ -809,11 +783,9 @@ schedule_transmission (struct GNUNET_TRANSPORT_Handle *h)
n->th->notify_size);
else
return; /* no work to be done */
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Scheduling next transmission to service in %llu ms\n",
(unsigned long long) delay.rel_value);
-#endif
h->quota_task =
GNUNET_SCHEDULER_add_delayed (delay, &schedule_transmission_task, h);
}
@@ -835,10 +807,8 @@ schedule_control_transmit (struct GNUNET_TRANSPORT_Handle *h, size_t size,
{
struct GNUNET_TRANSPORT_TransmitHandle *th;
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Control transmit of %u bytes requested\n",
size);
-#endif
th = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_TransmitHandle));
th->notify = notify;
th->notify_cls = notify_cls;
@@ -866,15 +836,11 @@ send_start (void *cls, size_t size, void *buf)
if (buf == NULL)
{
/* Can only be shutdown, just give up */
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Shutdown while trying to transmit `%s' request.\n", "START");
-#endif
return 0;
}
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' request.\n", "START");
-#endif
GNUNET_assert (size >= sizeof (struct StartMessage));
s.header.size = htons (sizeof (struct StartMessage));
s.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_START);
@@ -909,9 +875,7 @@ reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
/* shutdown, just give up */
return;
}
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to transport service.\n");
-#endif
GNUNET_assert (h->client == NULL);
GNUNET_assert (h->control_head == NULL);
GNUNET_assert (h->control_tail == NULL);
@@ -940,7 +904,7 @@ disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_Handle *h)
}
if (NULL != h->client)
{
- GNUNET_CLIENT_disconnect (h->client, GNUNET_YES);
+ GNUNET_CLIENT_disconnect (h->client);
h->client = NULL;
}
/* Forget about all neighbours that we used to be connected to */
@@ -956,11 +920,9 @@ disconnect_and_schedule_reconnect (struct GNUNET_TRANSPORT_Handle *h)
th->notify (th->notify_cls, 0, NULL);
GNUNET_free (th);
}
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Scheduling task to reconnect to transport service in %llu ms.\n",
h->reconnect_delay.rel_value);
-#endif
h->reconnect_task =
GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect, h);
if (h->reconnect_delay.rel_value == 0)
@@ -995,11 +957,9 @@ send_try_connect (void *cls, size_t size, void *buf)
GNUNET_free (pid);
return 0;
}
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Transmitting `%s' request with respect to `%4s'.\n", "REQUEST_CONNECT",
GNUNET_i2s (pid));
-#endif
GNUNET_assert (size >= sizeof (struct TransportRequestConnectMessage));
msg.header.size = htons (sizeof (struct TransportRequestConnectMessage));
msg.header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_REQUEST_CONNECT);
@@ -1050,16 +1010,12 @@ send_hello (void *cls, size_t size, void *buf)
if (buf == NULL)
{
-#if DEBUG_TRANSPORT_TIMEOUT
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Timeout while trying to transmit `%s' request.\n", "HELLO");
-#endif
GNUNET_free (msg);
return 0;
}
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Transmitting `%s' request.\n", "HELLO");
-#endif
ssize = ntohs (msg->size);
GNUNET_assert (size >= ssize);
memcpy (buf, msg, ssize);
@@ -1101,11 +1057,9 @@ GNUNET_TRANSPORT_offer_hello (struct GNUNET_TRANSPORT_Handle *handle,
}
msg = GNUNET_malloc (size);
memcpy (msg, hello, size);
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Offering `%s' message of `%4s' to transport for validation.\n", "HELLO",
GNUNET_i2s (&peer));
-#endif
schedule_control_transmit (handle, size, &send_hello, msg);
}
@@ -1204,9 +1158,7 @@ GNUNET_TRANSPORT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
void
GNUNET_TRANSPORT_disconnect (struct GNUNET_TRANSPORT_Handle *handle)
{
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG, "Transport disconnect called!\n");
-#endif
/* this disconnects all neighbours... */
if (handle->reconnect_task == GNUNET_SCHEDULER_NO_TASK)
disconnect_and_schedule_reconnect (handle);
@@ -1291,11 +1243,9 @@ GNUNET_TRANSPORT_notify_transmit_ready (struct GNUNET_TRANSPORT_Handle *handle,
delay = GNUNET_BANDWIDTH_tracker_get_delay (&n->out_tracker, size);
if (delay.rel_value > timeout.rel_value)
delay.rel_value = 0; /* notify immediately (with failure) */
-#if DEBUG_TRANSPORT_API
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Bandwidth tracker allows next transmission to peer %s in %llu ms\n",
GNUNET_i2s (target), (unsigned long long) delay.rel_value);
-#endif
n->hn = GNUNET_CONTAINER_heap_insert (handle->ready_heap, n, delay.rel_value);
schedule_transmission (handle);
return th;
diff --git a/src/transport/transport_api_address_lookup.c b/src/transport/transport_api_address_lookup.c
index 6e03945..655be83 100644
--- a/src/transport/transport_api_address_lookup.c
+++ b/src/transport/transport_api_address_lookup.c
@@ -155,7 +155,7 @@ static void
reconnect (struct GNUNET_TRANSPORT_PeerIterateContext *pal_ctx)
{
GNUNET_assert (GNUNET_NO == pal_ctx->one_shot);
- GNUNET_CLIENT_disconnect (pal_ctx->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (pal_ctx->client);
pal_ctx->client = NULL;
pal_ctx->backoff = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_MILLISECONDS,
GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (pal_ctx->backoff, 2),
@@ -294,17 +294,17 @@ peer_address_response_processor (void *cls,
/**
* Return all the known addresses for a specific peer or all peers.
- * Returns continously all address if one_shot is set to GNUNET_NO
+ * Returns continuously all address if one_shot is set to GNUNET_NO
*
* CHANGE: Returns the address(es) that we are currently using for this
* peer. Upon completion, the 'AddressLookUpCallback' is called one more
* time with 'NULL' for the address and the peer. After this, the operation must no
- * longer be explicitly cancelled.
+ * longer be explicitly canceled.
*
* @param cfg configuration to use
* @param peer peer identity to look up the addresses of, CHANGE: allow NULL for all (connected) peers
* @param one_shot GNUNET_YES to return the current state and then end (with NULL+NULL),
- * GNUNET_NO to monitor the set of addresses used (continuously, must be explicitly cancelled)
+ * GNUNET_NO to monitor the set of addresses used (continuously, must be explicitly canceled)
* @param timeout how long is the lookup allowed to take at most (irrelevant if one_shot is set to GNUNET_NO)
* @param peer_address_callback function to call with the results
* @param peer_address_callback_cls closure for peer_address_callback
@@ -354,7 +354,7 @@ GNUNET_TRANSPORT_peer_get_active_addresses_cancel (struct
{
if (NULL != alc->client)
{
- GNUNET_CLIENT_disconnect (alc->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (alc->client);
alc->client = NULL;
}
if (GNUNET_SCHEDULER_NO_TASK != alc->reconnect_task)
diff --git a/src/transport/transport_api_address_to_string.c b/src/transport/transport_api_address_to_string.c
index 4d80953..152e573 100644
--- a/src/transport/transport_api_address_to_string.c
+++ b/src/transport/transport_api_address_to_string.c
@@ -71,7 +71,7 @@ address_response_processor (void *cls, const struct GNUNET_MessageHeader *msg)
if (msg == NULL)
{
alucb->cb (alucb->cb_cls, NULL);
- GNUNET_CLIENT_disconnect (alucb->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (alucb->client);
GNUNET_free (alucb);
return;
}
@@ -82,7 +82,7 @@ address_response_processor (void *cls, const struct GNUNET_MessageHeader *msg)
{
/* done! */
alucb->cb (alucb->cb_cls, NULL);
- GNUNET_CLIENT_disconnect (alucb->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (alucb->client);
GNUNET_free (alucb);
return;
}
@@ -92,7 +92,7 @@ address_response_processor (void *cls, const struct GNUNET_MessageHeader *msg)
/* invalid reply */
GNUNET_break (0);
alucb->cb (alucb->cb_cls, NULL);
- GNUNET_CLIENT_disconnect (alucb->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (alucb->client);
GNUNET_free (alucb);
return;
}
@@ -141,13 +141,9 @@ GNUNET_TRANSPORT_address_to_string (const struct GNUNET_CONFIGURATION_Handle
GNUNET_break (0);
return NULL;
}
-
client = GNUNET_CLIENT_connect ("transport", cfg);
- if (client == NULL)
+ if (NULL == client)
return NULL;
-#if DEBUG_TRANSPORT
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_TRANSPORT_address_to_string\n");
-#endif
msg = GNUNET_malloc (len);
msg->header.size = htons (len);
msg->header.type = htons (GNUNET_MESSAGE_TYPE_TRANSPORT_ADDRESS_TO_STRING);
@@ -183,7 +179,7 @@ GNUNET_TRANSPORT_address_to_string_cancel (struct
GNUNET_TRANSPORT_AddressToStringContext
*alc)
{
- GNUNET_CLIENT_disconnect (alc->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (alc->client);
GNUNET_free (alc);
}
diff --git a/src/transport/transport_api_blacklist.c b/src/transport/transport_api_blacklist.c
index be52623..0464620 100644
--- a/src/transport/transport_api_blacklist.c
+++ b/src/transport/transport_api_blacklist.c
@@ -168,7 +168,7 @@ static void
reconnect (struct GNUNET_TRANSPORT_Blacklist *br)
{
if (br->client != NULL)
- GNUNET_CLIENT_disconnect (br->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (br->client);
br->client = GNUNET_CLIENT_connect ("transport", br->cfg);
GNUNET_assert (br->client != NULL);
br->th =
@@ -288,7 +288,7 @@ GNUNET_TRANSPORT_blacklist_cancel (struct GNUNET_TRANSPORT_Blacklist *br)
GNUNET_CLIENT_notify_transmit_ready_cancel (br->th);
br->th = NULL;
}
- GNUNET_CLIENT_disconnect (br->client, GNUNET_NO);
+ GNUNET_CLIENT_disconnect (br->client);
GNUNET_free (br);
}