diff options
Diffstat (limited to 'src/cadet')
52 files changed, 9515 insertions, 25372 deletions
diff --git a/src/cadet/.gitignore b/src/cadet/.gitignore index 096ee06eb..44382fde9 100644 --- a/src/cadet/.gitignore +++ b/src/cadet/.gitignore | |||
@@ -19,3 +19,6 @@ test_cadet_5_speed_reliable | |||
19 | test_cadet_5_speed_reliable_backwards | 19 | test_cadet_5_speed_reliable_backwards |
20 | test_cadet_local | 20 | test_cadet_local |
21 | test_cadet_single | 21 | test_cadet_single |
22 | gnunet-service-cadet-new | ||
23 | test_cadet_local_mq | ||
24 | test_cadet_*_new \ No newline at end of file | ||
diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am index 53d17dd9c..ce30ebe46 100644 --- a/src/cadet/Makefile.am +++ b/src/cadet/Makefile.am | |||
@@ -23,24 +23,24 @@ AM_CLFAGS = -g | |||
23 | 23 | ||
24 | libexec_PROGRAMS = \ | 24 | libexec_PROGRAMS = \ |
25 | gnunet-service-cadet \ | 25 | gnunet-service-cadet \ |
26 | gnunet-service-cadet-new \ | ||
27 | $(EXP_LIBEXEC) | 26 | $(EXP_LIBEXEC) |
28 | 27 | ||
29 | bin_PROGRAMS = \ | 28 | bin_PROGRAMS = \ |
30 | gnunet-cadet | 29 | gnunet-cadet |
31 | 30 | ||
32 | lib_LTLIBRARIES = \ | 31 | lib_LTLIBRARIES = \ |
33 | libgnunetcadet.la $(EXP_LIB) | 32 | libgnunetcadet.la \ |
33 | $(EXP_LIB) | ||
34 | 34 | ||
35 | libgnunetcadet_la_SOURCES = \ | 35 | libgnunetcadet_la_SOURCES = \ |
36 | cadet_api.c cadet_common.c | 36 | cadet_api.c |
37 | libgnunetcadet_la_LIBADD = \ | 37 | libgnunetcadet_la_LIBADD = \ |
38 | $(top_builddir)/src/util/libgnunetutil.la \ | 38 | $(top_builddir)/src/util/libgnunetutil.la \ |
39 | $(XLIB) \ | 39 | $(XLIB) \ |
40 | $(LTLIBINTL) | 40 | $(LTLIBINTL) |
41 | libgnunetcadet_la_LDFLAGS = \ | 41 | libgnunetcadet_la_LDFLAGS = \ |
42 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | 42 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ |
43 | -version-info 5:0:0 | 43 | -version-info 7:0:0 |
44 | 44 | ||
45 | gnunet_cadet_SOURCES = \ | 45 | gnunet_cadet_SOURCES = \ |
46 | gnunet-cadet.c | 46 | gnunet-cadet.c |
@@ -48,46 +48,23 @@ gnunet_cadet_LDADD = \ | |||
48 | libgnunetcadet.la \ | 48 | libgnunetcadet.la \ |
49 | $(top_builddir)/src/util/libgnunetutil.la | 49 | $(top_builddir)/src/util/libgnunetutil.la |
50 | 50 | ||
51 | gnunet_service_cadet_new_SOURCES = \ | ||
52 | gnunet-service-cadet-new.c gnunet-service-cadet-new.h \ | ||
53 | gnunet-service-cadet-new_channel.c gnunet-service-cadet-new_channel.h \ | ||
54 | gnunet-service-cadet-new_connection.c gnunet-service-cadet-new_connection.h \ | ||
55 | gnunet-service-cadet-new_core.c gnunet-service-cadet-new_core.h \ | ||
56 | gnunet-service-cadet-new_dht.c gnunet-service-cadet-new_dht.h \ | ||
57 | gnunet-service-cadet-new_hello.c gnunet-service-cadet-new_hello.h \ | ||
58 | gnunet-service-cadet-new_tunnels.c gnunet-service-cadet-new_tunnels.h \ | ||
59 | gnunet-service-cadet-new_paths.c gnunet-service-cadet-new_paths.h \ | ||
60 | gnunet-service-cadet-new_peer.c gnunet-service-cadet-new_peer.h | ||
61 | gnunet_service_cadet_new_LDADD = \ | ||
62 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
63 | $(top_builddir)/src/ats/libgnunetats.la \ | ||
64 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
65 | $(top_builddir)/src/dht/libgnunetdht.la \ | ||
66 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
67 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
68 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ | ||
69 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
70 | $(top_builddir)/src/block/libgnunetblock.la | ||
71 | |||
72 | gnunet_service_cadet_SOURCES = \ | 51 | gnunet_service_cadet_SOURCES = \ |
73 | gnunet-service-cadet_tunnel.c gnunet-service-cadet_tunnel.h \ | 52 | gnunet-service-cadet.c gnunet-service-cadet.h \ |
74 | gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \ | ||
75 | gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \ | 53 | gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \ |
76 | gnunet-service-cadet_local.c gnunet-service-cadet_local.h \ | 54 | gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \ |
77 | gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h \ | 55 | gnunet-service-cadet_core.c gnunet-service-cadet_core.h \ |
78 | gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \ | 56 | gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \ |
79 | gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \ | 57 | gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \ |
80 | cadet_path.c cadet_path.h \ | 58 | gnunet-service-cadet_tunnels.c gnunet-service-cadet_tunnels.h \ |
81 | cadet_common.c \ | 59 | gnunet-service-cadet_paths.c gnunet-service-cadet_paths.h \ |
82 | gnunet-service-cadet.c | 60 | gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h |
83 | gnunet_service_cadet_CFLAGS = $(AM_CFLAGS) | ||
84 | gnunet_service_cadet_LDADD = \ | 61 | gnunet_service_cadet_LDADD = \ |
85 | $(top_builddir)/src/util/libgnunetutil.la \ | 62 | $(top_builddir)/src/util/libgnunetutil.la \ |
86 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
87 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
88 | $(top_builddir)/src/ats/libgnunetats.la \ | 63 | $(top_builddir)/src/ats/libgnunetats.la \ |
64 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
89 | $(top_builddir)/src/dht/libgnunetdht.la \ | 65 | $(top_builddir)/src/dht/libgnunetdht.la \ |
90 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 66 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
67 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
91 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ | 68 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ |
92 | $(top_builddir)/src/hello/libgnunethello.la \ | 69 | $(top_builddir)/src/hello/libgnunethello.la \ |
93 | $(top_builddir)/src/block/libgnunetblock.la | 70 | $(top_builddir)/src/block/libgnunetblock.la |
@@ -97,26 +74,14 @@ endif | |||
97 | 74 | ||
98 | 75 | ||
99 | if HAVE_TESTING | 76 | if HAVE_TESTING |
100 | noinst_LIBRARIES = libgnunetcadettest.a $(noinst_LIB_EXP) | 77 | noinst_LTLIBRARIES = libgnunetcadettest.la $(noinst_LIB_EXP) |
101 | noinst_PROGRAMS = gnunet-cadet-profiler | 78 | # noinst_PROGRAMS = gnunet-cadet-profiler |
102 | endif | 79 | endif |
103 | 80 | ||
104 | libgnunetcadettest_a_SOURCES = \ | ||
105 | cadet_test_lib.c cadet_test_lib.h | ||
106 | libgnunetcadettest_a_LIBADD = \ | ||
107 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
108 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
109 | libgnunetcadet.la | ||
110 | |||
111 | if HAVE_TESTING | 81 | if HAVE_TESTING |
112 | check_PROGRAMS = \ | 82 | check_PROGRAMS = \ |
113 | test_cadet_2_speed_reliable_backwards \ | 83 | test_cadet_local_mq \ |
114 | test_cadet_5_speed \ | 84 | test_cadet_2_forward \ |
115 | test_cadet_5_speed_ack \ | ||
116 | test_cadet_5_speed_reliable \ | ||
117 | test_cadet_5_speed_reliable_backwards \ | ||
118 | test_cadet_single \ | ||
119 | test_cadet_local \ | ||
120 | test_cadet_2_forward \ | 85 | test_cadet_2_forward \ |
121 | test_cadet_2_signal \ | 86 | test_cadet_2_signal \ |
122 | test_cadet_2_keepalive \ | 87 | test_cadet_2_keepalive \ |
@@ -124,40 +89,50 @@ check_PROGRAMS = \ | |||
124 | test_cadet_2_speed_ack \ | 89 | test_cadet_2_speed_ack \ |
125 | test_cadet_2_speed_backwards \ | 90 | test_cadet_2_speed_backwards \ |
126 | test_cadet_2_speed_reliable \ | 91 | test_cadet_2_speed_reliable \ |
92 | test_cadet_2_speed_reliable_backwards \ | ||
127 | test_cadet_5_forward \ | 93 | test_cadet_5_forward \ |
128 | test_cadet_5_signal \ | 94 | test_cadet_5_signal \ |
129 | test_cadet_5_keepalive \ | 95 | test_cadet_5_keepalive \ |
96 | test_cadet_5_speed \ | ||
97 | test_cadet_5_speed_ack \ | ||
98 | test_cadet_5_speed_reliable \ | ||
99 | test_cadet_5_speed_reliable_backwards \ | ||
130 | test_cadet_5_speed_backwards | 100 | test_cadet_5_speed_backwards |
131 | endif | 101 | endif |
132 | 102 | ||
103 | |||
104 | #gnunet_cadet_profiler_SOURCES = \ | ||
105 | # gnunet-cadet-profiler.c | ||
106 | #gnunet_cadet_profiler_LDADD = $(ld_cadet_test_lib) | ||
107 | |||
108 | |||
109 | test_cadet_local_mq_SOURCES = \ | ||
110 | test_cadet_local_mq.c | ||
111 | test_cadet_local_mq_LDADD = \ | ||
112 | libgnunetcadet.la \ | ||
113 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
114 | $(top_builddir)/src/util/libgnunetutil.la | ||
115 | |||
116 | |||
117 | libgnunetcadettest_la_SOURCES = \ | ||
118 | cadet_test_lib.c cadet_test_lib.h | ||
119 | libgnunetcadettest_la_LIBADD = \ | ||
120 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
121 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
122 | libgnunetcadet.la | ||
123 | |||
133 | ld_cadet_test_lib = \ | 124 | ld_cadet_test_lib = \ |
134 | $(top_builddir)/src/util/libgnunetutil.la \ | 125 | $(top_builddir)/src/util/libgnunetutil.la \ |
135 | $(top_builddir)/src/testing/libgnunettesting.la \ | 126 | $(top_builddir)/src/testing/libgnunettesting.la \ |
136 | libgnunetcadettest.a \ | ||
137 | libgnunetcadet.la \ | 127 | libgnunetcadet.la \ |
128 | libgnunetcadettest.la \ | ||
138 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | 129 | $(top_builddir)/src/testbed/libgnunettestbed.la \ |
139 | $(top_builddir)/src/statistics/libgnunetstatistics.la | 130 | $(top_builddir)/src/statistics/libgnunetstatistics.la |
140 | |||
141 | dep_cadet_test_lib = \ | 131 | dep_cadet_test_lib = \ |
142 | libgnunetcadet.la \ | 132 | libgnunetcadet.la \ |
143 | libgnunetcadettest.a \ | 133 | libgnunetcadettest.la \ |
144 | $(top_builddir)/src/statistics/libgnunetstatistics.la | 134 | $(top_builddir)/src/statistics/libgnunetstatistics.la |
145 | 135 | ||
146 | |||
147 | gnunet_cadet_profiler_SOURCES = \ | ||
148 | gnunet-cadet-profiler.c | ||
149 | gnunet_cadet_profiler_LDADD = $(ld_cadet_test_lib) | ||
150 | |||
151 | |||
152 | test_cadet_single_SOURCES = \ | ||
153 | test_cadet_single.c | ||
154 | test_cadet_single_LDADD = $(ld_cadet_test_lib) | ||
155 | |||
156 | test_cadet_local_SOURCES = \ | ||
157 | test_cadet_local.c | ||
158 | test_cadet_local_LDADD = $(ld_cadet_test_lib) | ||
159 | |||
160 | |||
161 | test_cadet_2_forward_SOURCES = \ | 136 | test_cadet_2_forward_SOURCES = \ |
162 | test_cadet.c | 137 | test_cadet.c |
163 | test_cadet_2_forward_LDADD = $(ld_cadet_test_lib) | 138 | test_cadet_2_forward_LDADD = $(ld_cadet_test_lib) |
@@ -190,7 +165,6 @@ test_cadet_2_speed_reliable_backwards_SOURCES = \ | |||
190 | test_cadet.c | 165 | test_cadet.c |
191 | test_cadet_2_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) | 166 | test_cadet_2_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) |
192 | 167 | ||
193 | |||
194 | test_cadet_5_forward_SOURCES = \ | 168 | test_cadet_5_forward_SOURCES = \ |
195 | test_cadet.c | 169 | test_cadet.c |
196 | test_cadet_5_forward_LDADD = $(ld_cadet_test_lib) | 170 | test_cadet_5_forward_LDADD = $(ld_cadet_test_lib) |
@@ -225,7 +199,7 @@ test_cadet_5_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) | |||
225 | 199 | ||
226 | 200 | ||
227 | if ENABLE_TEST_RUN | 201 | if ENABLE_TEST_RUN |
228 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; | 202 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; |
229 | TESTS = \ | 203 | TESTS = \ |
230 | $(check_PROGRAMS) | 204 | $(check_PROGRAMS) |
231 | endif | 205 | endif |
diff --git a/src/cadet/TODO b/src/cadet/TODO new file mode 100644 index 000000000..06567b0ad --- /dev/null +++ b/src/cadet/TODO | |||
@@ -0,0 +1,36 @@ | |||
1 | - URGENT: | ||
2 | + if 'client-not-ready', we do not ACK at all, and sender keeps | ||
3 | retransmitting again and again; would be good to do flow-control notification instead | ||
4 | of not ACKing that we got the data but are simply not ready for more! | ||
5 | + Congestion/flow control (CHANNEL): | ||
6 | estimate max bandwidth using bursts and use to for CONGESTION CONTROL! | ||
7 | (and figure out how/where to use this!) | ||
8 | |||
9 | - HIGH: revisit handling of 'unbuffered' traffic! (CHANNEL/TUNNEL) | ||
10 | (need to push down through tunnel into connection selection); | ||
11 | At Tunnel-level, try to create connections that match channel | ||
12 | preferences (buffered/unbuffered) and select connections for | ||
13 | channel traffic that match channel preferences. | ||
14 | BUT: not sure this is ideal, discloses traffic type to | ||
15 | routers. We don't want that! (Maybe revise decision to do this?) | ||
16 | |||
17 | - HIGH: revisit handling of 'buffered' traffic: 4 is a rather small buffer; (CHANNEL) | ||
18 | maybe reserve more bits in 'options' to allow for buffer size control? | ||
19 | Or: maybe even better, calculated required buffer size based on latency | ||
20 | and throughput (and available memory) | ||
21 | |||
22 | - HIGH: if we receive BROKEN messages, cut down corresponding PATH (up to the | ||
23 | point of breakage) as well as connection/route (CORE) | ||
24 | |||
25 | - OPTIMIZATION: proper connection evaluation during connection management: | ||
26 | + TUNNELS: | ||
27 | * consider quality of current connection set when deciding | ||
28 | how often to do maintenance | ||
29 | * interact with PEER to drive DHT GET/PUT operations based | ||
30 | on how much we like our connections | ||
31 | |||
32 | |||
33 | - OPTIMIZATION: optimize stopping/restarting DHT search to situations | ||
34 | where we actually need it (i.e. not if we have a direct connection, | ||
35 | or if we already have plenty of good short ones, or maybe even | ||
36 | to take a break if we have some connections and have searched a lot (?)) (PEER) | ||
diff --git a/src/cadet/cadet.conf.in b/src/cadet/cadet.conf.in index 48fd03329..d50e168f0 100644 --- a/src/cadet/cadet.conf.in +++ b/src/cadet/cadet.conf.in | |||
@@ -11,13 +11,43 @@ UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-cadet.sock | |||
11 | UNIX_MATCH_UID = YES | 11 | UNIX_MATCH_UID = YES |
12 | UNIX_MATCH_GID = YES | 12 | UNIX_MATCH_GID = YES |
13 | 13 | ||
14 | |||
15 | # How often do we send KEEPALIVE messages on connections to keep them | ||
16 | # from timing out? | ||
14 | REFRESH_CONNECTION_TIME = 5 min | 17 | REFRESH_CONNECTION_TIME = 5 min |
18 | |||
19 | # Percentage of packets CADET is artificially dropping. Used for testing only! | ||
20 | # DROP_PERCENT = | ||
21 | |||
22 | # How frequently do we usually anounce our presence in the DHT? | ||
15 | ID_ANNOUNCE_TIME = 1 h | 23 | ID_ANNOUNCE_TIME = 1 h |
24 | |||
25 | # FIXME: document | ||
16 | CONNECT_TIMEOUT = 30 s | 26 | CONNECT_TIMEOUT = 30 s |
27 | |||
28 | # What is the replication level we give to the DHT when announcing our | ||
29 | # existence? Usually there is no need to change this. | ||
17 | DHT_REPLICATION_LEVEL = 3 | 30 | DHT_REPLICATION_LEVEL = 3 |
18 | MAX_TUNNELS = 1000 | 31 | |
32 | # FIXME: not implemented | ||
33 | # MAX_TUNNELS = 1000 | ||
34 | |||
35 | # FIXME: not implemented, replaced by MAX_ROUTES in NEW CADET! | ||
19 | MAX_CONNECTIONS = 1000 | 36 | MAX_CONNECTIONS = 1000 |
37 | |||
38 | # How many routes do we participate in at most? Should be smaller | ||
39 | # than MAX_MSGS_QUEUE | ||
40 | MAX_ROUTES = 5000 | ||
41 | |||
42 | # FIXME: not implemented | ||
20 | MAX_MSGS_QUEUE = 10000 | 43 | MAX_MSGS_QUEUE = 10000 |
44 | |||
45 | # FIXME: not implemented | ||
21 | MAX_PEERS = 1000 | 46 | MAX_PEERS = 1000 |
47 | |||
48 | # How often do we advance the ratchet even if there is not | ||
49 | # any traffic? | ||
22 | RATCHET_TIME = 1 h | 50 | RATCHET_TIME = 1 h |
51 | |||
52 | # How often do we advance the ratched if there is traffic? | ||
23 | RATCHET_MESSAGES = 64 | 53 | RATCHET_MESSAGES = 64 |
diff --git a/src/cadet/cadet.h b/src/cadet/cadet.h index 451d1f354..99f9f2653 100644 --- a/src/cadet/cadet.h +++ b/src/cadet/cadet.h | |||
@@ -59,7 +59,7 @@ extern "C" | |||
59 | #include "gnunet_core_service.h" | 59 | #include "gnunet_core_service.h" |
60 | #include "gnunet_cadet_service.h" | 60 | #include "gnunet_cadet_service.h" |
61 | #include "gnunet_protocols.h" | 61 | #include "gnunet_protocols.h" |
62 | #include <gnunet_cadet_service.h> | 62 | #include "gnunet_cadet_service.h" |
63 | 63 | ||
64 | /******************************************************************************/ | 64 | /******************************************************************************/ |
65 | /************************** CONSTANTS ******************************/ | 65 | /************************** CONSTANTS ******************************/ |
diff --git a/src/cadet/cadet_api.c b/src/cadet/cadet_api.c index 72b7b692d..decf473a9 100644 --- a/src/cadet/cadet_api.c +++ b/src/cadet/cadet_api.c | |||
@@ -21,8 +21,8 @@ | |||
21 | * @file cadet/cadet_api.c | 21 | * @file cadet/cadet_api.c |
22 | * @brief cadet api: client implementation of cadet service | 22 | * @brief cadet api: client implementation of cadet service |
23 | * @author Bartlomiej Polot | 23 | * @author Bartlomiej Polot |
24 | * @author Christian Grothoff | ||
24 | */ | 25 | */ |
25 | |||
26 | #include "platform.h" | 26 | #include "platform.h" |
27 | #include "gnunet_util_lib.h" | 27 | #include "gnunet_util_lib.h" |
28 | #include "gnunet_constants.h" | 28 | #include "gnunet_constants.h" |
@@ -32,55 +32,9 @@ | |||
32 | 32 | ||
33 | #define LOG(kind,...) GNUNET_log_from (kind, "cadet-api",__VA_ARGS__) | 33 | #define LOG(kind,...) GNUNET_log_from (kind, "cadet-api",__VA_ARGS__) |
34 | 34 | ||
35 | /******************************************************************************/ | ||
36 | /************************ DATA STRUCTURES ****************************/ | ||
37 | /******************************************************************************/ | ||
38 | |||
39 | /** | 35 | /** |
40 | * Transmission queue to the service | 36 | * Ugly legacy hack. |
41 | */ | 37 | */ |
42 | struct GNUNET_CADET_TransmitHandle | ||
43 | { | ||
44 | /** | ||
45 | * Double Linked list | ||
46 | */ | ||
47 | struct GNUNET_CADET_TransmitHandle *next; | ||
48 | |||
49 | /** | ||
50 | * Double Linked list | ||
51 | */ | ||
52 | struct GNUNET_CADET_TransmitHandle *prev; | ||
53 | |||
54 | /** | ||
55 | * Channel this message is sent on / for (may be NULL for control messages). | ||
56 | */ | ||
57 | struct GNUNET_CADET_Channel *channel; | ||
58 | |||
59 | /** | ||
60 | * Request data task. | ||
61 | */ | ||
62 | struct GNUNET_SCHEDULER_Task *request_data_task; | ||
63 | |||
64 | /** | ||
65 | * Callback to obtain the message to transmit, or NULL if we | ||
66 | * got the message in 'data'. Notice that messages built | ||
67 | * by 'notify' need to be encapsulated with information about | ||
68 | * the 'target'. | ||
69 | */ | ||
70 | GNUNET_CONNECTION_TransmitReadyNotify notify; | ||
71 | |||
72 | /** | ||
73 | * Closure for 'notify' | ||
74 | */ | ||
75 | void *notify_cls; | ||
76 | |||
77 | /** | ||
78 | * Size of the payload. | ||
79 | */ | ||
80 | size_t size; | ||
81 | }; | ||
82 | |||
83 | |||
84 | union CadetInfoCB | 38 | union CadetInfoCB |
85 | { | 39 | { |
86 | 40 | ||
@@ -117,54 +71,19 @@ union CadetInfoCB | |||
117 | struct GNUNET_CADET_Handle | 71 | struct GNUNET_CADET_Handle |
118 | { | 72 | { |
119 | /** | 73 | /** |
120 | * Message queue (if available). | 74 | * Message queue. |
121 | */ | 75 | */ |
122 | struct GNUNET_MQ_Handle *mq; | 76 | struct GNUNET_MQ_Handle *mq; |
123 | 77 | ||
124 | /** | 78 | /** |
125 | * Set of handlers used for processing incoming messages in the channels | ||
126 | */ | ||
127 | const struct GNUNET_CADET_MessageHandler *message_handlers; | ||
128 | |||
129 | /** | ||
130 | * Number of handlers in the handlers array. | ||
131 | */ | ||
132 | unsigned int n_handlers; | ||
133 | |||
134 | /** | ||
135 | * Ports open. | 79 | * Ports open. |
136 | */ | 80 | */ |
137 | struct GNUNET_CONTAINER_MultiHashMap *ports; | 81 | struct GNUNET_CONTAINER_MultiHashMap *ports; |
138 | 82 | ||
139 | /** | 83 | /** |
140 | * Double linked list of the channels this client is connected to, head. | 84 | * Channels open. |
141 | */ | ||
142 | struct GNUNET_CADET_Channel *channels_head; | ||
143 | |||
144 | /** | ||
145 | * Double linked list of the channels this client is connected to, tail. | ||
146 | */ | 85 | */ |
147 | struct GNUNET_CADET_Channel *channels_tail; | 86 | struct GNUNET_CONTAINER_MultiHashMap32 *channels; |
148 | |||
149 | /** | ||
150 | * Callback for inbound channel disconnection | ||
151 | */ | ||
152 | GNUNET_CADET_ChannelEndHandler *cleaner; | ||
153 | |||
154 | /** | ||
155 | * Closure for all the handlers given by the client | ||
156 | */ | ||
157 | void *cls; | ||
158 | |||
159 | /** | ||
160 | * Messages to send to the service, head. | ||
161 | */ | ||
162 | struct GNUNET_CADET_TransmitHandle *th_head; | ||
163 | |||
164 | /** | ||
165 | * Messages to send to the service, tail. | ||
166 | */ | ||
167 | struct GNUNET_CADET_TransmitHandle *th_tail; | ||
168 | 87 | ||
169 | /** | 88 | /** |
170 | * child of the next channel to create (to avoid reusing IDs often) | 89 | * child of the next channel to create (to avoid reusing IDs often) |
@@ -177,14 +96,9 @@ struct GNUNET_CADET_Handle | |||
177 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 96 | const struct GNUNET_CONFIGURATION_Handle *cfg; |
178 | 97 | ||
179 | /** | 98 | /** |
180 | * Time to the next reconnect in case one reconnect fails | ||
181 | */ | ||
182 | struct GNUNET_TIME_Relative reconnect_time; | ||
183 | |||
184 | /** | ||
185 | * Task for trying to reconnect. | 99 | * Task for trying to reconnect. |
186 | */ | 100 | */ |
187 | struct GNUNET_SCHEDULER_Task * reconnect_task; | 101 | struct GNUNET_SCHEDULER_Task *reconnect_task; |
188 | 102 | ||
189 | /** | 103 | /** |
190 | * Callback for an info task (only one active at a time). | 104 | * Callback for an info task (only one active at a time). |
@@ -195,65 +109,73 @@ struct GNUNET_CADET_Handle | |||
195 | * Info callback closure for @c info_cb. | 109 | * Info callback closure for @c info_cb. |
196 | */ | 110 | */ |
197 | void *info_cls; | 111 | void *info_cls; |
112 | |||
113 | /** | ||
114 | * Time to the next reconnect in case one reconnect fails | ||
115 | */ | ||
116 | struct GNUNET_TIME_Relative reconnect_time; | ||
117 | |||
198 | }; | 118 | }; |
199 | 119 | ||
200 | 120 | ||
201 | /** | 121 | /** |
202 | * Description of a peer | 122 | * Opaque handle to a channel. |
203 | */ | 123 | */ |
204 | struct GNUNET_CADET_Peer | 124 | struct GNUNET_CADET_Channel |
205 | { | 125 | { |
126 | |||
206 | /** | 127 | /** |
207 | * ID of the peer in short form | 128 | * Other end of the channel. |
208 | */ | 129 | */ |
209 | GNUNET_PEER_Id id; | 130 | struct GNUNET_PeerIdentity peer; |
210 | 131 | ||
211 | /** | 132 | /** |
212 | * Channel this peer belongs to | 133 | * Handle to the cadet this channel belongs to |
213 | */ | 134 | */ |
214 | struct GNUNET_CADET_Channel *t; | 135 | struct GNUNET_CADET_Handle *cadet; |
215 | }; | ||
216 | 136 | ||
137 | /** | ||
138 | * Channel's port, if incoming. | ||
139 | */ | ||
140 | struct GNUNET_CADET_Port *incoming_port; | ||
217 | 141 | ||
218 | /** | ||
219 | * Opaque handle to a channel. | ||
220 | */ | ||
221 | struct GNUNET_CADET_Channel | ||
222 | { | ||
223 | /** | 142 | /** |
224 | * DLL next | 143 | * Any data the caller wants to put in here, used for the |
144 | * various callbacks (@e disconnects, @e window_changes, handlers). | ||
225 | */ | 145 | */ |
226 | struct GNUNET_CADET_Channel *next; | 146 | void *ctx; |
227 | 147 | ||
228 | /** | 148 | /** |
229 | * DLL prev | 149 | * Message Queue for the channel (which we are implementing). |
230 | */ | 150 | */ |
231 | struct GNUNET_CADET_Channel *prev; | 151 | struct GNUNET_MQ_Handle *mq; |
232 | 152 | ||
233 | /** | 153 | /** |
234 | * Handle to the cadet this channel belongs to | 154 | * Task to allow mq to send more traffic. |
235 | */ | 155 | */ |
236 | struct GNUNET_CADET_Handle *cadet; | 156 | struct GNUNET_SCHEDULER_Task *mq_cont; |
237 | 157 | ||
238 | /** | 158 | /** |
239 | * Local ID of the channel | 159 | * Pending envelope with a message to be transmitted to the |
160 | * service as soon as we are allowed to. Should only be | ||
161 | * non-NULL if @e allow_send is 0. | ||
240 | */ | 162 | */ |
241 | struct GNUNET_CADET_ClientChannelNumber ccn; | 163 | struct GNUNET_MQ_Envelope *pending_env; |
242 | 164 | ||
243 | /** | 165 | /** |
244 | * Channel's port, if any. | 166 | * Window change handler. |
245 | */ | 167 | */ |
246 | struct GNUNET_CADET_Port *port; | 168 | GNUNET_CADET_WindowSizeEventHandler window_changes; |
247 | 169 | ||
248 | /** | 170 | /** |
249 | * Other end of the channel. | 171 | * Disconnect handler. |
250 | */ | 172 | */ |
251 | GNUNET_PEER_Id peer; | 173 | GNUNET_CADET_DisconnectEventHandler disconnects; |
252 | 174 | ||
253 | /** | 175 | /** |
254 | * Any data the caller wants to put in here | 176 | * Local ID of the channel, #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI bit is set if outbound. |
255 | */ | 177 | */ |
256 | void *ctx; | 178 | struct GNUNET_CADET_ClientChannelNumber ccn; |
257 | 179 | ||
258 | /** | 180 | /** |
259 | * Channel options: reliability, etc. | 181 | * Channel options: reliability, etc. |
@@ -261,7 +183,7 @@ struct GNUNET_CADET_Channel | |||
261 | enum GNUNET_CADET_ChannelOption options; | 183 | enum GNUNET_CADET_ChannelOption options; |
262 | 184 | ||
263 | /** | 185 | /** |
264 | * Are we allowed to send to the service? | 186 | * How many messages are we allowed to send to the service right now? |
265 | */ | 187 | */ |
266 | unsigned int allow_send; | 188 | unsigned int allow_send; |
267 | 189 | ||
@@ -273,82 +195,62 @@ struct GNUNET_CADET_Channel | |||
273 | */ | 195 | */ |
274 | struct GNUNET_CADET_Port | 196 | struct GNUNET_CADET_Port |
275 | { | 197 | { |
198 | |||
199 | /** | ||
200 | * Port "number" | ||
201 | */ | ||
202 | struct GNUNET_HashCode id; | ||
203 | |||
276 | /** | 204 | /** |
277 | * Handle to the CADET session this port belongs to. | 205 | * Handle to the CADET session this port belongs to. |
278 | */ | 206 | */ |
279 | struct GNUNET_CADET_Handle *cadet; | 207 | struct GNUNET_CADET_Handle *cadet; |
280 | 208 | ||
281 | /** | 209 | /** |
282 | * Port ID. | 210 | * Closure for @a handler. |
283 | */ | 211 | */ |
284 | struct GNUNET_HashCode *hash; | 212 | void *cls; |
285 | 213 | ||
286 | /** | 214 | /** |
287 | * Callback handler for incoming channels on this port. | 215 | * Handler for incoming channels on this port |
288 | */ | 216 | */ |
289 | GNUNET_CADET_InboundChannelNotificationHandler *handler; | 217 | GNUNET_CADET_ConnectEventHandler connects; |
290 | 218 | ||
291 | /** | 219 | /** |
292 | * Closure for @a handler. | 220 | * Closure for @ref connects |
293 | */ | 221 | */ |
294 | void *cls; | 222 | void *connects_cls; |
295 | }; | ||
296 | 223 | ||
224 | /** | ||
225 | * Window size change handler. | ||
226 | */ | ||
227 | GNUNET_CADET_WindowSizeEventHandler window_changes; | ||
297 | 228 | ||
298 | /** | ||
299 | * Implementation state for cadet's message queue. | ||
300 | */ | ||
301 | struct CadetMQState | ||
302 | { | ||
303 | /** | 229 | /** |
304 | * The current transmit handle, or NULL | 230 | * Handler called when an incoming channel is destroyed. |
305 | * if no transmit is active. | ||
306 | */ | 231 | */ |
307 | struct GNUNET_CADET_TransmitHandle *th; | 232 | GNUNET_CADET_DisconnectEventHandler disconnects; |
308 | 233 | ||
309 | /** | 234 | /** |
310 | * Channel to send the data over. | 235 | * Payload handlers for incoming channels. |
311 | */ | 236 | */ |
312 | struct GNUNET_CADET_Channel *channel; | 237 | struct GNUNET_MQ_MessageHandler *handlers; |
313 | }; | 238 | }; |
314 | 239 | ||
315 | 240 | ||
316 | /******************************************************************************/ | ||
317 | /*********************** AUXILIARY FUNCTIONS *************************/ | ||
318 | /******************************************************************************/ | ||
319 | |||
320 | /** | ||
321 | * Check if transmission is a payload packet. | ||
322 | * | ||
323 | * @param th Transmission handle. | ||
324 | * | ||
325 | * @return #GNUNET_YES if it is a payload packet, | ||
326 | * #GNUNET_NO if it is a cadet management packet. | ||
327 | */ | ||
328 | static int | ||
329 | th_is_payload (struct GNUNET_CADET_TransmitHandle *th) | ||
330 | { | ||
331 | return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO; | ||
332 | } | ||
333 | |||
334 | |||
335 | /** | 241 | /** |
336 | * Find the Port struct for a hash. | 242 | * Find the Port struct for a hash. |
337 | * | 243 | * |
338 | * @param h CADET handle. | 244 | * @param h CADET handle. |
339 | * @param hash HashCode for the port number. | 245 | * @param hash HashCode for the port number. |
340 | * | ||
341 | * @return The port handle if known, NULL otherwise. | 246 | * @return The port handle if known, NULL otherwise. |
342 | */ | 247 | */ |
343 | static struct GNUNET_CADET_Port * | 248 | static struct GNUNET_CADET_Port * |
344 | find_port (const struct GNUNET_CADET_Handle *h, | 249 | find_port (const struct GNUNET_CADET_Handle *h, |
345 | const struct GNUNET_HashCode *hash) | 250 | const struct GNUNET_HashCode *hash) |
346 | { | 251 | { |
347 | struct GNUNET_CADET_Port *p; | 252 | return GNUNET_CONTAINER_multihashmap_get (h->ports, |
348 | 253 | hash); | |
349 | p = GNUNET_CONTAINER_multihashmap_get (h->ports, hash); | ||
350 | |||
351 | return p; | ||
352 | } | 254 | } |
353 | 255 | ||
354 | 256 | ||
@@ -360,15 +262,11 @@ find_port (const struct GNUNET_CADET_Handle *h, | |||
360 | * @return handle to the required channel or NULL if not found | 262 | * @return handle to the required channel or NULL if not found |
361 | */ | 263 | */ |
362 | static struct GNUNET_CADET_Channel * | 264 | static struct GNUNET_CADET_Channel * |
363 | retrieve_channel (struct GNUNET_CADET_Handle *h, | 265 | find_channel (struct GNUNET_CADET_Handle *h, |
364 | struct GNUNET_CADET_ClientChannelNumber ccn) | 266 | struct GNUNET_CADET_ClientChannelNumber ccn) |
365 | { | 267 | { |
366 | struct GNUNET_CADET_Channel *ch; | 268 | return GNUNET_CONTAINER_multihashmap32_get (h->channels, |
367 | 269 | ntohl (ccn.channel_of_client)); | |
368 | for (ch = h->channels_head; NULL != ch; ch = ch->next) | ||
369 | if (ch->ccn.channel_of_client == ccn.channel_of_client) | ||
370 | return ch; | ||
371 | return NULL; | ||
372 | } | 270 | } |
373 | 271 | ||
374 | 272 | ||
@@ -376,38 +274,37 @@ retrieve_channel (struct GNUNET_CADET_Handle *h, | |||
376 | * Create a new channel and insert it in the channel list of the cadet handle | 274 | * Create a new channel and insert it in the channel list of the cadet handle |
377 | * | 275 | * |
378 | * @param h Cadet handle | 276 | * @param h Cadet handle |
379 | * @param ccn Desired ccn of the channel, 0 to assign one automatically. | 277 | * @param ccnp pointer to desired ccn of the channel, NULL to assign one automatically. |
380 | * | ||
381 | * @return Handle to the created channel. | 278 | * @return Handle to the created channel. |
382 | */ | 279 | */ |
383 | static struct GNUNET_CADET_Channel * | 280 | static struct GNUNET_CADET_Channel * |
384 | create_channel (struct GNUNET_CADET_Handle *h, | 281 | create_channel (struct GNUNET_CADET_Handle *h, |
385 | struct GNUNET_CADET_ClientChannelNumber ccn) | 282 | const struct GNUNET_CADET_ClientChannelNumber *ccnp) |
386 | { | 283 | { |
387 | struct GNUNET_CADET_Channel *ch; | 284 | struct GNUNET_CADET_Channel *ch; |
285 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
388 | 286 | ||
389 | ch = GNUNET_new (struct GNUNET_CADET_Channel); | 287 | ch = GNUNET_new (struct GNUNET_CADET_Channel); |
390 | GNUNET_CONTAINER_DLL_insert (h->channels_head, | ||
391 | h->channels_tail, | ||
392 | ch); | ||
393 | ch->cadet = h; | 288 | ch->cadet = h; |
394 | if (0 == ccn.channel_of_client) | 289 | if (NULL == ccnp) |
395 | { | 290 | { |
396 | ch->ccn = h->next_ccn; | 291 | while (NULL != |
397 | while (NULL != retrieve_channel (h, | 292 | find_channel (h, |
398 | h->next_ccn)) | 293 | h->next_ccn)) |
399 | { | ||
400 | h->next_ccn.channel_of_client | 294 | h->next_ccn.channel_of_client |
401 | = htonl (1 + ntohl (h->next_ccn.channel_of_client)); | 295 | = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI | (1 + ntohl (h->next_ccn.channel_of_client))); |
402 | if (0 == ntohl (h->next_ccn.channel_of_client)) | 296 | ccn = h->next_ccn; |
403 | h->next_ccn.channel_of_client | ||
404 | = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
405 | } | ||
406 | } | 297 | } |
407 | else | 298 | else |
408 | { | 299 | { |
409 | ch->ccn = ccn; | 300 | ccn = *ccnp; |
410 | } | 301 | } |
302 | ch->ccn = ccn; | ||
303 | GNUNET_assert (GNUNET_OK == | ||
304 | GNUNET_CONTAINER_multihashmap32_put (h->channels, | ||
305 | ntohl (ch->ccn.channel_of_client), | ||
306 | ch, | ||
307 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
411 | return ch; | 308 | return ch; |
412 | } | 309 | } |
413 | 310 | ||
@@ -421,145 +318,273 @@ create_channel (struct GNUNET_CADET_Handle *h, | |||
421 | * | 318 | * |
422 | * @param ch Pointer to the channel. | 319 | * @param ch Pointer to the channel. |
423 | * @param call_cleaner Whether to call the cleaner handler. | 320 | * @param call_cleaner Whether to call the cleaner handler. |
321 | */ | ||
322 | static void | ||
323 | destroy_channel (struct GNUNET_CADET_Channel *ch) | ||
324 | { | ||
325 | struct GNUNET_CADET_Handle *h = ch->cadet; | ||
326 | |||
327 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
328 | "Destroying channel %X of %p\n", | ||
329 | ch->ccn, | ||
330 | h); | ||
331 | GNUNET_assert (GNUNET_YES == | ||
332 | GNUNET_CONTAINER_multihashmap32_remove (h->channels, | ||
333 | ntohl (ch->ccn.channel_of_client), | ||
334 | ch)); | ||
335 | if (NULL != ch->mq_cont) | ||
336 | { | ||
337 | GNUNET_SCHEDULER_cancel (ch->mq_cont); | ||
338 | ch->mq_cont = NULL; | ||
339 | } | ||
340 | /* signal channel destruction */ | ||
341 | if (NULL != ch->disconnects) | ||
342 | ch->disconnects (ch->ctx, | ||
343 | ch); | ||
344 | if (NULL != ch->pending_env) | ||
345 | GNUNET_MQ_discard (ch->pending_env); | ||
346 | GNUNET_MQ_destroy (ch->mq); | ||
347 | GNUNET_free (ch); | ||
348 | } | ||
349 | |||
350 | |||
351 | /** | ||
352 | * Reconnect to the service, retransmit all infomation to try to restore the | ||
353 | * original state. | ||
424 | * | 354 | * |
425 | * @return Handle to the required channel or NULL if not found. | 355 | * @param h handle to the cadet |
426 | */ | 356 | */ |
427 | // FIXME: simplify: call_cleaner is always #GNUNET_YES!!! | ||
428 | static void | 357 | static void |
429 | destroy_channel (struct GNUNET_CADET_Channel *ch, | 358 | reconnect (struct GNUNET_CADET_Handle *h); |
430 | int call_cleaner) | 359 | |
360 | |||
361 | /** | ||
362 | * Reconnect callback: tries to reconnect again after a failer previous | ||
363 | * reconnecttion | ||
364 | * | ||
365 | * @param cls closure (cadet handle) | ||
366 | */ | ||
367 | static void | ||
368 | reconnect_cbk (void *cls) | ||
431 | { | 369 | { |
432 | struct GNUNET_CADET_Handle *h; | 370 | struct GNUNET_CADET_Handle *h = cls; |
433 | struct GNUNET_CADET_TransmitHandle *th; | ||
434 | struct GNUNET_CADET_TransmitHandle *next; | ||
435 | 371 | ||
436 | if (NULL == ch) | 372 | h->reconnect_task = NULL; |
373 | reconnect (h); | ||
374 | } | ||
375 | |||
376 | |||
377 | /** | ||
378 | * Function called during #reconnect() to destroy | ||
379 | * all channels that are still open. | ||
380 | * | ||
381 | * @param cls the `struct GNUNET_CADET_Handle` | ||
382 | * @param cid chanenl ID | ||
383 | * @param value a `struct GNUNET_CADET_Channel` to destroy | ||
384 | * @return #GNUNET_OK (continue to iterate) | ||
385 | */ | ||
386 | static int | ||
387 | destroy_channel_on_reconnect_cb (void *cls, | ||
388 | uint32_t cid, | ||
389 | void *value) | ||
390 | { | ||
391 | /* struct GNUNET_CADET_Handle *handle = cls; */ | ||
392 | struct GNUNET_CADET_Channel *ch = value; | ||
393 | |||
394 | destroy_channel (ch); | ||
395 | return GNUNET_OK; | ||
396 | } | ||
397 | |||
398 | |||
399 | /** | ||
400 | * Reconnect to the service, retransmit all infomation to try to restore the | ||
401 | * original state. | ||
402 | * | ||
403 | * @param h handle to the cadet | ||
404 | * | ||
405 | * @return #GNUNET_YES in case of sucess, #GNUNET_NO otherwise (service down...) | ||
406 | */ | ||
407 | static void | ||
408 | schedule_reconnect (struct GNUNET_CADET_Handle *h) | ||
409 | { | ||
410 | if (NULL != h->reconnect_task) | ||
411 | return; | ||
412 | GNUNET_CONTAINER_multihashmap32_iterate (h->channels, | ||
413 | &destroy_channel_on_reconnect_cb, | ||
414 | h); | ||
415 | h->reconnect_task | ||
416 | = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, | ||
417 | &reconnect_cbk, | ||
418 | h); | ||
419 | h->reconnect_time | ||
420 | = GNUNET_TIME_STD_BACKOFF (h->reconnect_time); | ||
421 | } | ||
422 | |||
423 | |||
424 | /** | ||
425 | * Notify the application about a change in the window size (if needed). | ||
426 | * | ||
427 | * @param ch Channel to notify about. | ||
428 | */ | ||
429 | static void | ||
430 | notify_window_size (struct GNUNET_CADET_Channel *ch) | ||
431 | { | ||
432 | if (NULL != ch->window_changes) | ||
433 | ch->window_changes (ch->ctx, | ||
434 | ch, /* FIXME: remove 'ch'? */ | ||
435 | ch->allow_send); | ||
436 | } | ||
437 | |||
438 | |||
439 | /** | ||
440 | * Transmit the next message from our queue. | ||
441 | * | ||
442 | * @param cls Closure (channel whose mq to activate). | ||
443 | */ | ||
444 | static void | ||
445 | cadet_mq_send_now (void *cls) | ||
446 | { | ||
447 | struct GNUNET_CADET_Channel *ch = cls; | ||
448 | struct GNUNET_MQ_Envelope *env = ch->pending_env; | ||
449 | |||
450 | ch->mq_cont = NULL; | ||
451 | if (0 == ch->allow_send) | ||
437 | { | 452 | { |
453 | /* how did we get here? */ | ||
438 | GNUNET_break (0); | 454 | GNUNET_break (0); |
439 | return; | 455 | return; |
440 | } | 456 | } |
441 | h = ch->cadet; | 457 | if (NULL == env) |
442 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 458 | { |
443 | " destroy_channel %X of %p\n", | 459 | /* how did we get here? */ |
444 | ch->ccn, | 460 | GNUNET_break (0); |
445 | h); | 461 | return; |
462 | } | ||
463 | ch->allow_send--; | ||
464 | ch->pending_env = NULL; | ||
465 | GNUNET_MQ_send (ch->cadet->mq, | ||
466 | env); | ||
467 | GNUNET_MQ_impl_send_continue (ch->mq); | ||
468 | } | ||
446 | 469 | ||
447 | GNUNET_CONTAINER_DLL_remove (h->channels_head, | ||
448 | h->channels_tail, | ||
449 | ch); | ||
450 | 470 | ||
451 | /* signal channel destruction */ | 471 | /** |
452 | if ( (NULL != h->cleaner) && | 472 | * Implement sending functionality of a message queue for |
453 | (0 != ch->peer) && | 473 | * us sending messages to a peer. |
454 | (GNUNET_YES == call_cleaner) ) | 474 | * |
475 | * Encapsulates the payload message in a #GNUNET_CADET_LocalData message | ||
476 | * in order to label the message with the channel ID and send the | ||
477 | * encapsulated message to the service. | ||
478 | * | ||
479 | * @param mq the message queue | ||
480 | * @param msg the message to send | ||
481 | * @param impl_state state of the implementation | ||
482 | */ | ||
483 | static void | ||
484 | cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq, | ||
485 | const struct GNUNET_MessageHeader *msg, | ||
486 | void *impl_state) | ||
487 | { | ||
488 | struct GNUNET_CADET_Channel *ch = impl_state; | ||
489 | struct GNUNET_CADET_Handle *h = ch->cadet; | ||
490 | uint16_t msize; | ||
491 | struct GNUNET_MQ_Envelope *env; | ||
492 | struct GNUNET_CADET_LocalData *cadet_msg; | ||
493 | |||
494 | if (NULL == h->mq) | ||
455 | { | 495 | { |
456 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 496 | /* We're currently reconnecting, pretend this worked */ |
457 | " calling cleaner\n"); | 497 | GNUNET_MQ_impl_send_continue (mq); |
458 | h->cleaner (h->cls, ch, ch->ctx); | 498 | return; |
459 | } | 499 | } |
460 | 500 | ||
461 | /* check that clients did not leave messages behind in the queue */ | 501 | /* check message size for sanity */ |
462 | for (th = h->th_head; NULL != th; th = next) | 502 | msize = ntohs (msg->size); |
503 | if (msize > GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE) | ||
463 | { | 504 | { |
464 | next = th->next; | 505 | GNUNET_break (0); |
465 | if (th->channel != ch) | 506 | GNUNET_MQ_impl_send_continue (mq); |
466 | continue; | 507 | return; |
467 | /* Clients should have aborted their requests already. | ||
468 | * Management traffic should be ok, as clients can't cancel that. | ||
469 | * If the service crashed and we are reconnecting, it's ok. | ||
470 | */ | ||
471 | GNUNET_break (GNUNET_NO == th_is_payload (th)); | ||
472 | GNUNET_CADET_notify_transmit_ready_cancel (th); | ||
473 | } | 508 | } |
474 | 509 | env = GNUNET_MQ_msg_nested_mh (cadet_msg, | |
475 | if (0 != ch->peer) | 510 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, |
476 | GNUNET_PEER_change_rc (ch->peer, -1); | 511 | msg); |
477 | GNUNET_free (ch); | 512 | cadet_msg->ccn = ch->ccn; |
513 | GNUNET_assert (NULL == ch->pending_env); | ||
514 | ch->pending_env = env; | ||
515 | if (0 < ch->allow_send) | ||
516 | ch->mq_cont | ||
517 | = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, | ||
518 | ch); | ||
478 | } | 519 | } |
479 | 520 | ||
480 | 521 | ||
481 | /** | 522 | /** |
482 | * Add a transmit handle to the transmission queue and set the | 523 | * Handle destruction of a message queue. Implementations must not |
483 | * timeout if needed. | 524 | * free @a mq, but should take care of @a impl_state. |
484 | * | 525 | * |
485 | * @param h cadet handle with the queue head and tail | 526 | * @param mq the message queue to destroy |
486 | * @param th handle to the packet to be transmitted | 527 | * @param impl_state state of the implementation |
487 | */ | 528 | */ |
488 | static void | 529 | static void |
489 | add_to_queue (struct GNUNET_CADET_Handle *h, | 530 | cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, |
490 | struct GNUNET_CADET_TransmitHandle *th) | 531 | void *impl_state) |
491 | { | 532 | { |
492 | GNUNET_CONTAINER_DLL_insert_tail (h->th_head, | 533 | struct GNUNET_CADET_Channel *ch = impl_state; |
493 | h->th_tail, | 534 | |
494 | th); | 535 | GNUNET_assert (mq == ch->mq); |
536 | ch->mq = NULL; | ||
495 | } | 537 | } |
496 | 538 | ||
497 | 539 | ||
498 | /** | 540 | /** |
499 | * Remove a transmit handle from the transmission queue, if present. | 541 | * We had an error processing a message we forwarded from a peer to |
500 | * | 542 | * the CADET service. We should just complain about it but otherwise |
501 | * Safe to call even if not queued. | 543 | * continue processing. |
502 | * | 544 | * |
503 | * @param th handle to the packet to be unqueued. | 545 | * @param cls closure with our `struct GNUNET_CADET_Channel` |
546 | * @param error error code | ||
504 | */ | 547 | */ |
505 | static void | 548 | static void |
506 | remove_from_queue (struct GNUNET_CADET_TransmitHandle *th) | 549 | cadet_mq_error_handler (void *cls, |
550 | enum GNUNET_MQ_Error error) | ||
507 | { | 551 | { |
508 | struct GNUNET_CADET_Handle *h = th->channel->cadet; | 552 | struct GNUNET_CADET_Channel *ch = cls; |
509 | 553 | ||
510 | /* It might or might not have been queued (rarely not), but check anyway. */ | 554 | GNUNET_break (0); |
511 | if (NULL != th->next || h->th_tail == th) | 555 | if (GNUNET_MQ_ERROR_NO_MATCH == error) |
556 | { | ||
557 | /* Got a message we did not understand, still try to continue! */ | ||
558 | GNUNET_CADET_receive_done (ch); | ||
559 | } | ||
560 | else | ||
512 | { | 561 | { |
513 | GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); | 562 | schedule_reconnect (ch->cadet); |
514 | } | 563 | } |
515 | } | 564 | } |
516 | 565 | ||
517 | 566 | ||
518 | |||
519 | /******************************************************************************/ | ||
520 | /*********************** RECEIVE HANDLERS ****************************/ | ||
521 | /******************************************************************************/ | ||
522 | |||
523 | |||
524 | /** | 567 | /** |
525 | * Call the @a notify callback given to #GNUNET_CADET_notify_transmit_ready to | 568 | * Implementation function that cancels the currently sent message. |
526 | * request the data to send over MQ. Since MQ manages the queue, this function | 569 | * Should basically undo whatever #mq_send_impl() did. |
527 | * is scheduled immediatly after a transmit ready notification. | ||
528 | * | 570 | * |
529 | * @param cls Closure (transmit handle). | 571 | * @param mq message queue |
572 | * @param impl_state state specific to the implementation | ||
530 | */ | 573 | */ |
531 | static void | 574 | static void |
532 | request_data (void *cls) | 575 | cadet_mq_cancel_impl (struct GNUNET_MQ_Handle *mq, |
576 | void *impl_state) | ||
533 | { | 577 | { |
534 | struct GNUNET_CADET_TransmitHandle *th = cls; | 578 | struct GNUNET_CADET_Channel *ch = impl_state; |
535 | struct GNUNET_CADET_LocalData *msg; | ||
536 | struct GNUNET_MQ_Envelope *env; | ||
537 | size_t osize; | ||
538 | 579 | ||
539 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 580 | GNUNET_assert (NULL != ch->pending_env); |
540 | "Requesting Data: %u bytes (allow send is %u)\n", | 581 | GNUNET_MQ_discard (ch->pending_env); |
541 | th->size, | 582 | ch->pending_env = NULL; |
542 | th->channel->allow_send); | 583 | if (NULL != ch->mq_cont) |
543 | 584 | { | |
544 | GNUNET_assert (0 < th->channel->allow_send); | 585 | GNUNET_SCHEDULER_cancel (ch->mq_cont); |
545 | th->channel->allow_send--; | 586 | ch->mq_cont = NULL; |
546 | /* NOTE: we may be allowed to send another packet immediately, | 587 | } |
547 | albeit the current logic waits for the ACK. */ | ||
548 | th->request_data_task = NULL; | ||
549 | remove_from_queue (th); | ||
550 | |||
551 | env = GNUNET_MQ_msg_extra (msg, | ||
552 | th->size, | ||
553 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
554 | msg->ccn = th->channel->ccn; | ||
555 | osize = th->notify (th->notify_cls, | ||
556 | th->size, | ||
557 | &msg[1]); | ||
558 | GNUNET_assert (osize == th->size); | ||
559 | |||
560 | GNUNET_MQ_send (th->channel->cadet->mq, | ||
561 | env); | ||
562 | GNUNET_free (th); | ||
563 | } | 588 | } |
564 | 589 | ||
565 | 590 | ||
@@ -586,18 +611,20 @@ handle_channel_created (void *cls, | |||
586 | GNUNET_break (0); | 611 | GNUNET_break (0); |
587 | return; | 612 | return; |
588 | } | 613 | } |
589 | port = find_port (h, port_number); | 614 | port = find_port (h, |
615 | port_number); | ||
590 | if (NULL == port) | 616 | if (NULL == port) |
591 | { | 617 | { |
618 | /* We could have closed the port but the service didn't know about it yet | ||
619 | * This is not an error. | ||
620 | */ | ||
592 | struct GNUNET_CADET_LocalChannelDestroyMessage *d_msg; | 621 | struct GNUNET_CADET_LocalChannelDestroyMessage *d_msg; |
593 | struct GNUNET_MQ_Envelope *env; | 622 | struct GNUNET_MQ_Envelope *env; |
594 | 623 | ||
595 | GNUNET_break (0); | ||
596 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 624 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
597 | "No handler for incoming channel %X [%s]\n", | 625 | "No handler for incoming channel %X (on port %s, recently closed?)\n", |
598 | ntohl (ccn.channel_of_client), | 626 | ntohl (ccn.channel_of_client), |
599 | GNUNET_h2s (port_number)); | 627 | GNUNET_h2s (port_number)); |
600 | /* FIXME: should disconnect instead, this is a serious error! */ | ||
601 | env = GNUNET_MQ_msg (d_msg, | 628 | env = GNUNET_MQ_msg (d_msg, |
602 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | 629 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); |
603 | d_msg->ccn = msg->ccn; | 630 | d_msg->ccn = msg->ccn; |
@@ -607,23 +634,32 @@ handle_channel_created (void *cls, | |||
607 | } | 634 | } |
608 | 635 | ||
609 | ch = create_channel (h, | 636 | ch = create_channel (h, |
610 | ccn); | 637 | &ccn); |
611 | ch->peer = GNUNET_PEER_intern (&msg->peer); | 638 | ch->peer = msg->peer; |
612 | ch->cadet = h; | 639 | ch->cadet = h; |
613 | ch->ccn = ccn; | 640 | ch->incoming_port = port; |
614 | ch->port = port; | ||
615 | ch->options = ntohl (msg->opt); | 641 | ch->options = ntohl (msg->opt); |
616 | |||
617 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 642 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
618 | "Creating incoming channel %X [%s] %p\n", | 643 | "Creating incoming channel %X [%s] %p\n", |
619 | ntohl (ccn.channel_of_client), | 644 | ntohl (ccn.channel_of_client), |
620 | GNUNET_h2s (port_number), | 645 | GNUNET_h2s (port_number), |
621 | ch); | 646 | ch); |
622 | ch->ctx = port->handler (port->cls, | 647 | |
623 | ch, | 648 | GNUNET_assert (NULL != port->connects); |
624 | &msg->peer, | 649 | ch->window_changes = port->window_changes; |
625 | port->hash, | 650 | ch->disconnects = port->disconnects; |
626 | ch->options); | 651 | ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl, |
652 | &cadet_mq_destroy_impl, | ||
653 | &cadet_mq_cancel_impl, | ||
654 | ch, | ||
655 | port->handlers, | ||
656 | &cadet_mq_error_handler, | ||
657 | ch); | ||
658 | ch->ctx = port->connects (port->cls, | ||
659 | ch, | ||
660 | &msg->peer); | ||
661 | GNUNET_MQ_set_handlers_closure (ch->mq, | ||
662 | ch->ctx); | ||
627 | } | 663 | } |
628 | 664 | ||
629 | 665 | ||
@@ -639,24 +675,20 @@ handle_channel_destroy (void *cls, | |||
639 | { | 675 | { |
640 | struct GNUNET_CADET_Handle *h = cls; | 676 | struct GNUNET_CADET_Handle *h = cls; |
641 | struct GNUNET_CADET_Channel *ch; | 677 | struct GNUNET_CADET_Channel *ch; |
642 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
643 | |||
644 | ccn = msg->ccn; | ||
645 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
646 | "Channel %X Destroy from service\n", | ||
647 | ntohl (ccn.channel_of_client)); | ||
648 | ch = retrieve_channel (h, | ||
649 | ccn); | ||
650 | 678 | ||
679 | ch = find_channel (h, | ||
680 | msg->ccn); | ||
651 | if (NULL == ch) | 681 | if (NULL == ch) |
652 | { | 682 | { |
653 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 683 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
654 | "channel %X unknown\n", | 684 | "Received channel destroy for unknown channel %X from CADET service (recently close?)\n", |
655 | ntohl (ccn.channel_of_client)); | 685 | ntohl (msg->ccn.channel_of_client)); |
656 | return; | 686 | return; |
657 | } | 687 | } |
658 | destroy_channel (ch, | 688 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
659 | GNUNET_YES); | 689 | "Received channel destroy for channel %X from CADET service\n", |
690 | ntohl (msg->ccn.channel_of_client)); | ||
691 | destroy_channel (ch); | ||
660 | } | 692 | } |
661 | 693 | ||
662 | 694 | ||
@@ -672,25 +704,14 @@ static int | |||
672 | check_local_data (void *cls, | 704 | check_local_data (void *cls, |
673 | const struct GNUNET_CADET_LocalData *message) | 705 | const struct GNUNET_CADET_LocalData *message) |
674 | { | 706 | { |
675 | struct GNUNET_CADET_Handle *h = cls; | ||
676 | struct GNUNET_CADET_Channel *ch; | ||
677 | uint16_t size; | 707 | uint16_t size; |
678 | 708 | ||
679 | size = ntohs (message->header.size); | 709 | size = ntohs (message->header.size); |
680 | if (sizeof (*message) + sizeof (struct GNUNET_MessageHeader) > size) | 710 | if (sizeof (*message) + sizeof (struct GNUNET_MessageHeader) > size) |
681 | { | 711 | { |
682 | GNUNET_break_op (0); | 712 | GNUNET_break (0); |
683 | return GNUNET_SYSERR; | ||
684 | } | ||
685 | |||
686 | ch = retrieve_channel (h, | ||
687 | message->ccn); | ||
688 | if (NULL == ch) | ||
689 | { | ||
690 | GNUNET_break_op (0); | ||
691 | return GNUNET_SYSERR; | 713 | return GNUNET_SYSERR; |
692 | } | 714 | } |
693 | |||
694 | return GNUNET_OK; | 715 | return GNUNET_OK; |
695 | } | 716 | } |
696 | 717 | ||
@@ -707,46 +728,31 @@ handle_local_data (void *cls, | |||
707 | { | 728 | { |
708 | struct GNUNET_CADET_Handle *h = cls; | 729 | struct GNUNET_CADET_Handle *h = cls; |
709 | const struct GNUNET_MessageHeader *payload; | 730 | const struct GNUNET_MessageHeader *payload; |
710 | const struct GNUNET_CADET_MessageHandler *handler; | ||
711 | struct GNUNET_CADET_Channel *ch; | 731 | struct GNUNET_CADET_Channel *ch; |
712 | uint16_t type; | 732 | uint16_t type; |
733 | int fwd; | ||
713 | 734 | ||
714 | ch = retrieve_channel (h, | 735 | ch = find_channel (h, |
715 | message->ccn); | 736 | message->ccn); |
716 | GNUNET_assert (NULL != ch); | 737 | if (NULL == ch) |
738 | { | ||
739 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
740 | "Unknown channel %X for incoming data (recently closed?)\n", | ||
741 | ntohl (message->ccn.channel_of_client)); | ||
742 | return; | ||
743 | } | ||
717 | 744 | ||
718 | payload = (struct GNUNET_MessageHeader *) &message[1]; | 745 | payload = (const struct GNUNET_MessageHeader *) &message[1]; |
719 | type = ntohs (payload->type); | 746 | type = ntohs (payload->type); |
747 | fwd = ntohl (ch->ccn.channel_of_client) <= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; | ||
720 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 748 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
721 | "Got a %s data on channel %s [%X] of type %s (%u)\n", | 749 | "Got a %s data on channel %s [%X] of type %u\n", |
722 | GC_f2s (ntohl (ch->ccn.channel_of_client) >= | 750 | fwd ? "FWD" : "BWD", |
723 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI), | 751 | GNUNET_i2s (&ch->peer), |
724 | GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)), | ||
725 | ntohl (message->ccn.channel_of_client), | 752 | ntohl (message->ccn.channel_of_client), |
726 | GC_m2s (type), | ||
727 | type); | 753 | type); |
728 | for (unsigned i=0;i<h->n_handlers;i++) | 754 | GNUNET_MQ_inject_message (ch->mq, |
729 | { | 755 | payload); |
730 | handler = &h->message_handlers[i]; | ||
731 | if (handler->type == type) | ||
732 | { | ||
733 | if (GNUNET_OK != | ||
734 | handler->callback (h->cls, | ||
735 | ch, | ||
736 | &ch->ctx, | ||
737 | payload)) | ||
738 | { | ||
739 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
740 | "callback caused disconnection\n"); | ||
741 | GNUNET_CADET_channel_destroy (ch); | ||
742 | return; | ||
743 | } | ||
744 | return; | ||
745 | } | ||
746 | } | ||
747 | /* Other peer sent message we do not comprehend. */ | ||
748 | GNUNET_break_op (0); | ||
749 | GNUNET_CADET_receive_done (ch); | ||
750 | } | 756 | } |
751 | 757 | ||
752 | 758 | ||
@@ -763,57 +769,36 @@ handle_local_ack (void *cls, | |||
763 | { | 769 | { |
764 | struct GNUNET_CADET_Handle *h = cls; | 770 | struct GNUNET_CADET_Handle *h = cls; |
765 | struct GNUNET_CADET_Channel *ch; | 771 | struct GNUNET_CADET_Channel *ch; |
766 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
767 | struct GNUNET_CADET_TransmitHandle *th; | ||
768 | 772 | ||
769 | ccn = message->ccn; | 773 | ch = find_channel (h, |
770 | ch = retrieve_channel (h, ccn); | 774 | message->ccn); |
771 | if (NULL == ch) | 775 | if (NULL == ch) |
772 | { | 776 | { |
773 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 777 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
774 | "ACK on unknown channel %X\n", | 778 | "ACK on unknown channel %X\n", |
775 | ntohl (ccn.channel_of_client)); | 779 | ntohl (message->ccn.channel_of_client)); |
776 | return; | 780 | return; |
777 | } | 781 | } |
778 | ch->allow_send++; | 782 | ch->allow_send++; |
779 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 783 | if (NULL == ch->pending_env) |
780 | "Got an ACK on channel %X, allow send now %u!\n", | ||
781 | ntohl (ch->ccn.channel_of_client), | ||
782 | ch->allow_send); | ||
783 | for (th = h->th_head; NULL != th; th = th->next) | ||
784 | { | 784 | { |
785 | if ( (th->channel == ch) && | 785 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
786 | (NULL == th->request_data_task) ) | 786 | "Got an ACK on mq channel %X, allow send now %u!\n", |
787 | { | 787 | ntohl (ch->ccn.channel_of_client), |
788 | th->request_data_task | 788 | ch->allow_send); |
789 | = GNUNET_SCHEDULER_add_now (&request_data, | 789 | notify_window_size (ch); |
790 | th); | 790 | return; |
791 | break; | ||
792 | } | ||
793 | } | 791 | } |
792 | if (NULL != ch->mq_cont) | ||
793 | return; /* already working on it! */ | ||
794 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
795 | "Got an ACK on mq channel %X, sending pending message!\n", | ||
796 | ntohl (ch->ccn.channel_of_client)); | ||
797 | ch->mq_cont | ||
798 | = GNUNET_SCHEDULER_add_now (&cadet_mq_send_now, | ||
799 | ch); | ||
794 | } | 800 | } |
795 | 801 | ||
796 | /** | ||
797 | * Reconnect to the service, retransmit all infomation to try to restore the | ||
798 | * original state. | ||
799 | * | ||
800 | * @param h handle to the cadet | ||
801 | * | ||
802 | * @return #GNUNET_YES in case of sucess, #GNUNET_NO otherwise (service down...) | ||
803 | */ | ||
804 | static void | ||
805 | reconnect (struct GNUNET_CADET_Handle *h); | ||
806 | |||
807 | |||
808 | /** | ||
809 | * Reconnect callback: tries to reconnect again after a failer previous | ||
810 | * reconnection. | ||
811 | * | ||
812 | * @param cls closure (cadet handle) | ||
813 | */ | ||
814 | static void | ||
815 | reconnect_cbk (void *cls); | ||
816 | |||
817 | 802 | ||
818 | /** | 803 | /** |
819 | * Generic error handler, called with the appropriate error code and | 804 | * Generic error handler, called with the appropriate error code and |
@@ -829,134 +814,15 @@ handle_mq_error (void *cls, | |||
829 | { | 814 | { |
830 | struct GNUNET_CADET_Handle *h = cls; | 815 | struct GNUNET_CADET_Handle *h = cls; |
831 | 816 | ||
832 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %u\n", error); | 817 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
818 | "MQ ERROR: %u\n", | ||
819 | error); | ||
833 | GNUNET_MQ_destroy (h->mq); | 820 | GNUNET_MQ_destroy (h->mq); |
834 | h->mq = NULL; | 821 | h->mq = NULL; |
835 | reconnect (h); | 822 | reconnect (h); |
836 | } | 823 | } |
837 | 824 | ||
838 | 825 | ||
839 | /* | ||
840 | * Process a local reply about info on all channels, pass info to the user. | ||
841 | * | ||
842 | * @param h Cadet handle. | ||
843 | * @param message Message itself. | ||
844 | */ | ||
845 | // static void | ||
846 | // process_get_channels (struct GNUNET_CADET_Handle *h, | ||
847 | // const struct GNUNET_MessageHeader *message) | ||
848 | // { | ||
849 | // struct GNUNET_CADET_LocalInfo *msg; | ||
850 | // | ||
851 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Channels messasge received\n"); | ||
852 | // | ||
853 | // if (NULL == h->channels_cb) | ||
854 | // { | ||
855 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); | ||
856 | // return; | ||
857 | // } | ||
858 | // | ||
859 | // msg = (struct GNUNET_CADET_LocalInfo *) message; | ||
860 | // if (ntohs (message->size) != | ||
861 | // (sizeof (struct GNUNET_CADET_LocalInfo) + | ||
862 | // sizeof (struct GNUNET_PeerIdentity))) | ||
863 | // { | ||
864 | // GNUNET_break_op (0); | ||
865 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
866 | // "Get channels message: size %hu - expected %u\n", | ||
867 | // ntohs (message->size), | ||
868 | // sizeof (struct GNUNET_CADET_LocalInfo)); | ||
869 | // return; | ||
870 | // } | ||
871 | // h->channels_cb (h->channels_cls, | ||
872 | // ntohl (msg->channel_id), | ||
873 | // &msg->owner, | ||
874 | // &msg->destination); | ||
875 | // } | ||
876 | |||
877 | |||
878 | |||
879 | /* | ||
880 | * Process a local monitor_channel reply, pass info to the user. | ||
881 | * | ||
882 | * @param h Cadet handle. | ||
883 | * @param message Message itself. | ||
884 | */ | ||
885 | // static void | ||
886 | // process_show_channel (struct GNUNET_CADET_Handle *h, | ||
887 | // const struct GNUNET_MessageHeader *message) | ||
888 | // { | ||
889 | // struct GNUNET_CADET_LocalInfo *msg; | ||
890 | // size_t esize; | ||
891 | // | ||
892 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Channel messasge received\n"); | ||
893 | // | ||
894 | // if (NULL == h->channel_cb) | ||
895 | // { | ||
896 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); | ||
897 | // return; | ||
898 | // } | ||
899 | // | ||
900 | // /* Verify message sanity */ | ||
901 | // msg = (struct GNUNET_CADET_LocalInfo *) message; | ||
902 | // esize = sizeof (struct GNUNET_CADET_LocalInfo); | ||
903 | // if (ntohs (message->size) != esize) | ||
904 | // { | ||
905 | // GNUNET_break_op (0); | ||
906 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
907 | // "Show channel message: size %hu - expected %u\n", | ||
908 | // ntohs (message->size), | ||
909 | // esize); | ||
910 | // | ||
911 | // h->channel_cb (h->channel_cls, NULL, NULL); | ||
912 | // h->channel_cb = NULL; | ||
913 | // h->channel_cls = NULL; | ||
914 | // | ||
915 | // return; | ||
916 | // } | ||
917 | // | ||
918 | // h->channel_cb (h->channel_cls, | ||
919 | // &msg->destination, | ||
920 | // &msg->owner); | ||
921 | // } | ||
922 | |||
923 | |||
924 | |||
925 | /** | ||
926 | * Check that message received from CADET service is well-formed. | ||
927 | * | ||
928 | * @param cls the `struct GNUNET_CADET_Handle` | ||
929 | * @param message the message we got | ||
930 | * @return #GNUNET_OK if the message is well-formed, | ||
931 | * #GNUNET_SYSERR otherwise | ||
932 | */ | ||
933 | static int | ||
934 | check_get_peers (void *cls, | ||
935 | const struct GNUNET_CADET_LocalInfoPeer *message) | ||
936 | { | ||
937 | struct GNUNET_CADET_Handle *h = cls; | ||
938 | uint16_t size; | ||
939 | |||
940 | if (NULL == h->info_cb.peers_cb) | ||
941 | { | ||
942 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
943 | " no handler for peesr monitor message!\n"); | ||
944 | return GNUNET_SYSERR; | ||
945 | } | ||
946 | |||
947 | size = ntohs (message->header.size); | ||
948 | if (sizeof (struct GNUNET_CADET_LocalInfoPeer) > size) | ||
949 | { | ||
950 | h->info_cb.peers_cb (h->info_cls, NULL, -1, 0, 0); | ||
951 | h->info_cb.peers_cb = NULL; | ||
952 | h->info_cls = NULL; | ||
953 | return GNUNET_SYSERR; | ||
954 | } | ||
955 | |||
956 | return GNUNET_OK; | ||
957 | } | ||
958 | |||
959 | |||
960 | /** | 826 | /** |
961 | * Process a local reply about info on all tunnels, pass info to the user. | 827 | * Process a local reply about info on all tunnels, pass info to the user. |
962 | * | 828 | * |
@@ -968,9 +834,13 @@ handle_get_peers (void *cls, | |||
968 | const struct GNUNET_CADET_LocalInfoPeer *msg) | 834 | const struct GNUNET_CADET_LocalInfoPeer *msg) |
969 | { | 835 | { |
970 | struct GNUNET_CADET_Handle *h = cls; | 836 | struct GNUNET_CADET_Handle *h = cls; |
971 | h->info_cb.peers_cb (h->info_cls, &msg->destination, | 837 | |
838 | if (NULL == h->info_cb.peers_cb) | ||
839 | return; | ||
840 | h->info_cb.peers_cb (h->info_cls, | ||
841 | &msg->destination, | ||
972 | (int) ntohs (msg->tunnel), | 842 | (int) ntohs (msg->tunnel), |
973 | (unsigned int ) ntohs (msg->paths), | 843 | (unsigned int) ntohs (msg->paths), |
974 | 0); | 844 | 0); |
975 | } | 845 | } |
976 | 846 | ||
@@ -987,62 +857,39 @@ static int | |||
987 | check_get_peer (void *cls, | 857 | check_get_peer (void *cls, |
988 | const struct GNUNET_CADET_LocalInfoPeer *message) | 858 | const struct GNUNET_CADET_LocalInfoPeer *message) |
989 | { | 859 | { |
990 | struct GNUNET_CADET_Handle *h = cls; | 860 | size_t msize = sizeof (struct GNUNET_CADET_LocalInfoPeer); |
991 | const size_t msize = sizeof (struct GNUNET_CADET_LocalInfoPeer); | 861 | const struct GNUNET_PeerIdentity *paths_array; |
992 | struct GNUNET_PeerIdentity *paths_array; | ||
993 | size_t esize; | 862 | size_t esize; |
994 | unsigned int epaths; | 863 | unsigned int epaths; |
995 | unsigned int paths; | 864 | unsigned int paths; |
996 | unsigned int peers; | 865 | unsigned int peers; |
997 | 866 | ||
998 | if (NULL == h->info_cb.peer_cb) | ||
999 | { | ||
1000 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1001 | " no handler for peer monitor message!\n"); | ||
1002 | goto clean_cls; | ||
1003 | } | ||
1004 | |||
1005 | /* Verify message sanity */ | ||
1006 | esize = ntohs (message->header.size); | 867 | esize = ntohs (message->header.size); |
1007 | if (esize < msize) | 868 | if (esize < msize) |
1008 | { | 869 | { |
1009 | GNUNET_break_op (0); | 870 | GNUNET_break (0); |
1010 | h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL); | 871 | return GNUNET_SYSERR; |
1011 | goto clean_cls; | ||
1012 | } | 872 | } |
1013 | if (0 != ((esize - msize) % sizeof (struct GNUNET_PeerIdentity))) | 873 | if (0 != ((esize - msize) % sizeof (struct GNUNET_PeerIdentity))) |
1014 | { | 874 | { |
1015 | GNUNET_break_op (0); | 875 | GNUNET_break (0); |
1016 | h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL); | 876 | return GNUNET_SYSERR; |
1017 | goto clean_cls; | ||
1018 | |||
1019 | } | 877 | } |
1020 | peers = (esize - msize) / sizeof (struct GNUNET_PeerIdentity); | 878 | peers = (esize - msize) / sizeof (struct GNUNET_PeerIdentity); |
1021 | epaths = (unsigned int) ntohs (message->paths); | 879 | epaths = ntohs (message->paths); |
1022 | paths_array = (struct GNUNET_PeerIdentity *) &message[1]; | 880 | paths_array = (const struct GNUNET_PeerIdentity *) &message[1]; |
1023 | paths = 0; | 881 | paths = 0; |
1024 | for (int i = 0; i < peers; i++) | 882 | for (unsigned int i = 0; i < peers; i++) |
1025 | { | 883 | if (0 == memcmp (&paths_array[i], |
1026 | if (0 == memcmp (&paths_array[i], &message->destination, | 884 | &message->destination, |
1027 | sizeof (struct GNUNET_PeerIdentity))) | 885 | sizeof (struct GNUNET_PeerIdentity))) |
1028 | { | ||
1029 | paths++; | 886 | paths++; |
1030 | } | ||
1031 | } | ||
1032 | if (paths != epaths) | 887 | if (paths != epaths) |
1033 | { | 888 | { |
1034 | GNUNET_break_op (0); | 889 | GNUNET_break (0); |
1035 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "p:%u, e: %u\n", paths, epaths); | 890 | return GNUNET_SYSERR; |
1036 | h->info_cb.peer_cb (h->info_cls, NULL, 0, 0, 0, NULL); | ||
1037 | goto clean_cls; | ||
1038 | } | 891 | } |
1039 | |||
1040 | return GNUNET_OK; | 892 | return GNUNET_OK; |
1041 | |||
1042 | clean_cls: | ||
1043 | h->info_cb.peer_cb = NULL; | ||
1044 | h->info_cls = NULL; | ||
1045 | return GNUNET_SYSERR; | ||
1046 | } | 893 | } |
1047 | 894 | ||
1048 | 895 | ||
@@ -1057,22 +904,26 @@ handle_get_peer (void *cls, | |||
1057 | const struct GNUNET_CADET_LocalInfoPeer *message) | 904 | const struct GNUNET_CADET_LocalInfoPeer *message) |
1058 | { | 905 | { |
1059 | struct GNUNET_CADET_Handle *h = cls; | 906 | struct GNUNET_CADET_Handle *h = cls; |
1060 | struct GNUNET_PeerIdentity *paths_array; | 907 | const struct GNUNET_PeerIdentity *paths_array; |
1061 | unsigned int paths; | 908 | unsigned int paths; |
1062 | unsigned int path_length; | 909 | unsigned int path_length; |
1063 | int neighbor; | 910 | int neighbor; |
1064 | unsigned int peers; | 911 | unsigned int peers; |
1065 | 912 | ||
1066 | paths = (unsigned int) ntohs (message->paths); | 913 | if (NULL == h->info_cb.peer_cb) |
1067 | paths_array = (struct GNUNET_PeerIdentity *) &message[1]; | 914 | return; |
915 | paths = ntohs (message->paths); | ||
916 | paths_array = (const struct GNUNET_PeerIdentity *) &message[1]; | ||
1068 | peers = (ntohs (message->header.size) - sizeof (*message)) | 917 | peers = (ntohs (message->header.size) - sizeof (*message)) |
1069 | / sizeof (struct GNUNET_PeerIdentity); | 918 | / sizeof (struct GNUNET_PeerIdentity); |
1070 | path_length = 0; | 919 | path_length = 0; |
1071 | neighbor = GNUNET_NO; | 920 | neighbor = GNUNET_NO; |
1072 | 921 | ||
1073 | for (int i = 0; i < peers; i++) | 922 | for (unsigned int i = 0; i < peers; i++) |
1074 | { | 923 | { |
1075 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&paths_array[i])); | 924 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
925 | " %s\n", | ||
926 | GNUNET_i2s (&paths_array[i])); | ||
1076 | path_length++; | 927 | path_length++; |
1077 | if (0 == memcmp (&paths_array[i], &message->destination, | 928 | if (0 == memcmp (&paths_array[i], &message->destination, |
1078 | sizeof (struct GNUNET_PeerIdentity))) | 929 | sizeof (struct GNUNET_PeerIdentity))) |
@@ -1084,7 +935,7 @@ handle_get_peer (void *cls, | |||
1084 | } | 935 | } |
1085 | 936 | ||
1086 | /* Call Callback with tunnel info. */ | 937 | /* Call Callback with tunnel info. */ |
1087 | paths_array = (struct GNUNET_PeerIdentity *) &message[1]; | 938 | paths_array = (const struct GNUNET_PeerIdentity *) &message[1]; |
1088 | h->info_cb.peer_cb (h->info_cls, | 939 | h->info_cb.peer_cb (h->info_cls, |
1089 | &message->destination, | 940 | &message->destination, |
1090 | (int) ntohs (message->tunnel), | 941 | (int) ntohs (message->tunnel), |
@@ -1095,40 +946,6 @@ handle_get_peer (void *cls, | |||
1095 | 946 | ||
1096 | 947 | ||
1097 | /** | 948 | /** |
1098 | * Check that message received from CADET service is well-formed. | ||
1099 | * | ||
1100 | * @param cls the `struct GNUNET_CADET_Handle` | ||
1101 | * @param msg the message we got | ||
1102 | * @return #GNUNET_OK if the message is well-formed, | ||
1103 | * #GNUNET_SYSERR otherwise | ||
1104 | */ | ||
1105 | static int | ||
1106 | check_get_tunnels (void *cls, | ||
1107 | const struct GNUNET_CADET_LocalInfoTunnel *msg) | ||
1108 | { | ||
1109 | struct GNUNET_CADET_Handle *h = cls; | ||
1110 | uint16_t size; | ||
1111 | |||
1112 | if (NULL == h->info_cb.tunnels_cb) | ||
1113 | { | ||
1114 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1115 | " no handler for tunnels monitor message!\n"); | ||
1116 | return GNUNET_SYSERR; | ||
1117 | } | ||
1118 | |||
1119 | size = ntohs (msg->header.size); | ||
1120 | if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) > size) | ||
1121 | { | ||
1122 | h->info_cb.tunnels_cb (h->info_cls, NULL, 0, 0, 0, 0); | ||
1123 | h->info_cb.tunnels_cb = NULL; | ||
1124 | h->info_cls = NULL; | ||
1125 | return GNUNET_SYSERR; | ||
1126 | } | ||
1127 | return GNUNET_OK; | ||
1128 | } | ||
1129 | |||
1130 | |||
1131 | /** | ||
1132 | * Process a local reply about info on all tunnels, pass info to the user. | 949 | * Process a local reply about info on all tunnels, pass info to the user. |
1133 | * | 950 | * |
1134 | * @param cls Closure (Cadet handle). | 951 | * @param cls Closure (Cadet handle). |
@@ -1140,6 +957,8 @@ handle_get_tunnels (void *cls, | |||
1140 | { | 957 | { |
1141 | struct GNUNET_CADET_Handle *h = cls; | 958 | struct GNUNET_CADET_Handle *h = cls; |
1142 | 959 | ||
960 | if (NULL == h->info_cb.tunnels_cb) | ||
961 | return; | ||
1143 | h->info_cb.tunnels_cb (h->info_cls, | 962 | h->info_cb.tunnels_cb (h->info_cls, |
1144 | &msg->destination, | 963 | &msg->destination, |
1145 | ntohl (msg->channels), | 964 | ntohl (msg->channels), |
@@ -1162,28 +981,18 @@ static int | |||
1162 | check_get_tunnel (void *cls, | 981 | check_get_tunnel (void *cls, |
1163 | const struct GNUNET_CADET_LocalInfoTunnel *msg) | 982 | const struct GNUNET_CADET_LocalInfoTunnel *msg) |
1164 | { | 983 | { |
1165 | struct GNUNET_CADET_Handle *h = cls; | ||
1166 | unsigned int ch_n; | 984 | unsigned int ch_n; |
1167 | unsigned int c_n; | 985 | unsigned int c_n; |
1168 | size_t esize; | 986 | size_t esize; |
1169 | size_t msize; | 987 | size_t msize; |
1170 | 988 | ||
1171 | if (NULL == h->info_cb.tunnel_cb) | ||
1172 | { | ||
1173 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1174 | " no handler for tunnel monitor message!\n"); | ||
1175 | goto clean_cls; | ||
1176 | } | ||
1177 | |||
1178 | /* Verify message sanity */ | 989 | /* Verify message sanity */ |
1179 | msize = ntohs (msg->header.size); | 990 | msize = ntohs (msg->header.size); |
1180 | esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel); | 991 | esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel); |
1181 | if (esize > msize) | 992 | if (esize > msize) |
1182 | { | 993 | { |
1183 | GNUNET_break_op (0); | 994 | GNUNET_break (0); |
1184 | h->info_cb.tunnel_cb (h->info_cls, | 995 | return GNUNET_SYSERR; |
1185 | NULL, 0, 0, NULL, NULL, 0, 0); | ||
1186 | goto clean_cls; | ||
1187 | } | 996 | } |
1188 | ch_n = ntohl (msg->channels); | 997 | ch_n = ntohl (msg->channels); |
1189 | c_n = ntohl (msg->connections); | 998 | c_n = ntohl (msg->connections); |
@@ -1198,17 +1007,9 @@ check_get_tunnel (void *cls, | |||
1198 | (unsigned int) esize, | 1007 | (unsigned int) esize, |
1199 | ch_n, | 1008 | ch_n, |
1200 | c_n); | 1009 | c_n); |
1201 | h->info_cb.tunnel_cb (h->info_cls, | 1010 | return GNUNET_SYSERR; |
1202 | NULL, 0, 0, NULL, NULL, 0, 0); | ||
1203 | goto clean_cls; | ||
1204 | } | 1011 | } |
1205 | |||
1206 | return GNUNET_OK; | 1012 | return GNUNET_OK; |
1207 | |||
1208 | clean_cls: | ||
1209 | h->info_cb.tunnel_cb = NULL; | ||
1210 | h->info_cls = NULL; | ||
1211 | return GNUNET_SYSERR; | ||
1212 | } | 1013 | } |
1213 | 1014 | ||
1214 | 1015 | ||
@@ -1228,6 +1029,9 @@ handle_get_tunnel (void *cls, | |||
1228 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns; | 1029 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *conns; |
1229 | const struct GNUNET_CADET_ChannelTunnelNumber *chns; | 1030 | const struct GNUNET_CADET_ChannelTunnelNumber *chns; |
1230 | 1031 | ||
1032 | if (NULL == h->info_cb.tunnel_cb) | ||
1033 | return; | ||
1034 | |||
1231 | ch_n = ntohl (msg->channels); | 1035 | ch_n = ntohl (msg->channels); |
1232 | c_n = ntohl (msg->connections); | 1036 | c_n = ntohl (msg->connections); |
1233 | 1037 | ||
@@ -1245,16 +1049,14 @@ handle_get_tunnel (void *cls, | |||
1245 | } | 1049 | } |
1246 | 1050 | ||
1247 | 1051 | ||
1248 | |||
1249 | /** | 1052 | /** |
1250 | * Reconnect to the service, retransmit all infomation to try to restore the | 1053 | * Reconnect to the service, retransmit all infomation to try to restore the |
1251 | * original state. | 1054 | * original state. |
1252 | * | 1055 | * |
1253 | * @param h handle to the cadet | 1056 | * @param h handle to the cadet |
1254 | * @return #GNUNET_YES in case of success, #GNUNET_NO otherwise (service down...) | ||
1255 | */ | 1057 | */ |
1256 | static int | 1058 | static void |
1257 | do_reconnect (struct GNUNET_CADET_Handle *h) | 1059 | reconnect (struct GNUNET_CADET_Handle *h) |
1258 | { | 1060 | { |
1259 | struct GNUNET_MQ_MessageHandler handlers[] = { | 1061 | struct GNUNET_MQ_MessageHandler handlers[] = { |
1260 | GNUNET_MQ_hd_fixed_size (channel_created, | 1062 | GNUNET_MQ_hd_fixed_size (channel_created, |
@@ -1273,32 +1075,25 @@ do_reconnect (struct GNUNET_CADET_Handle *h) | |||
1273 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, | 1075 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, |
1274 | struct GNUNET_CADET_LocalAck, | 1076 | struct GNUNET_CADET_LocalAck, |
1275 | h), | 1077 | h), |
1276 | GNUNET_MQ_hd_var_size (get_peers, | 1078 | GNUNET_MQ_hd_fixed_size (get_peers, |
1277 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, | 1079 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, |
1278 | struct GNUNET_CADET_LocalInfoPeer, | 1080 | struct GNUNET_CADET_LocalInfoPeer, |
1279 | h), | 1081 | h), |
1280 | GNUNET_MQ_hd_var_size (get_peer, | 1082 | GNUNET_MQ_hd_var_size (get_peer, |
1281 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER, | 1083 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER, |
1282 | struct GNUNET_CADET_LocalInfoPeer, | 1084 | struct GNUNET_CADET_LocalInfoPeer, |
1283 | h), | 1085 | h), |
1284 | GNUNET_MQ_hd_var_size (get_tunnels, | 1086 | GNUNET_MQ_hd_fixed_size (get_tunnels, |
1285 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS, | 1087 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS, |
1286 | struct GNUNET_CADET_LocalInfoTunnel, | 1088 | struct GNUNET_CADET_LocalInfoTunnel, |
1287 | h), | 1089 | h), |
1288 | GNUNET_MQ_hd_var_size (get_tunnel, | 1090 | GNUNET_MQ_hd_var_size (get_tunnel, |
1289 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL, | 1091 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL, |
1290 | struct GNUNET_CADET_LocalInfoTunnel, | 1092 | struct GNUNET_CADET_LocalInfoTunnel, |
1291 | h), | 1093 | h), |
1292 | // FIXME | ||
1293 | // GNUNET_MQ_hd_fixed_Y size (channel_destroyed, | ||
1294 | // GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED, | ||
1295 | // struct GNUNET_CADET_ChannelDestroyMessage); | ||
1296 | GNUNET_MQ_handler_end () | 1094 | GNUNET_MQ_handler_end () |
1297 | }; | 1095 | }; |
1298 | 1096 | ||
1299 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CADET\n"); | ||
1300 | |||
1301 | GNUNET_assert (NULL == h->mq); | ||
1302 | h->mq = GNUNET_CLIENT_connect (h->cfg, | 1097 | h->mq = GNUNET_CLIENT_connect (h->cfg, |
1303 | "cadet", | 1098 | "cadet", |
1304 | handlers, | 1099 | handlers, |
@@ -1306,92 +1101,63 @@ do_reconnect (struct GNUNET_CADET_Handle *h) | |||
1306 | h); | 1101 | h); |
1307 | if (NULL == h->mq) | 1102 | if (NULL == h->mq) |
1308 | { | 1103 | { |
1309 | reconnect (h); | 1104 | schedule_reconnect (h); |
1310 | return GNUNET_NO; | 1105 | return; |
1311 | } | ||
1312 | else | ||
1313 | { | ||
1314 | h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1315 | } | 1106 | } |
1316 | return GNUNET_YES; | 1107 | h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; |
1317 | } | 1108 | } |
1318 | 1109 | ||
1110 | |||
1319 | /** | 1111 | /** |
1320 | * Reconnect callback: tries to reconnect again after a failer previous | 1112 | * Function called during #GNUNET_CADET_disconnect() to destroy |
1321 | * reconnecttion | 1113 | * all channels that are still open. |
1322 | * | 1114 | * |
1323 | * @param cls closure (cadet handle) | 1115 | * @param cls the `struct GNUNET_CADET_Handle` |
1116 | * @param cid chanenl ID | ||
1117 | * @param value a `struct GNUNET_CADET_Channel` to destroy | ||
1118 | * @return #GNUNET_OK (continue to iterate) | ||
1324 | */ | 1119 | */ |
1325 | static void | 1120 | static int |
1326 | reconnect_cbk (void *cls) | 1121 | destroy_channel_cb (void *cls, |
1122 | uint32_t cid, | ||
1123 | void *value) | ||
1327 | { | 1124 | { |
1328 | struct GNUNET_CADET_Handle *h = cls; | 1125 | /* struct GNUNET_CADET_Handle *handle = cls; */ |
1126 | struct GNUNET_CADET_Channel *ch = value; | ||
1329 | 1127 | ||
1330 | h->reconnect_task = NULL; | 1128 | if (ntohl (ch->ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) |
1331 | do_reconnect (h); | 1129 | { |
1130 | GNUNET_break (0); | ||
1131 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1132 | "channel %X not destroyed\n", | ||
1133 | ntohl (ch->ccn.channel_of_client)); | ||
1134 | } | ||
1135 | destroy_channel (ch); | ||
1136 | return GNUNET_OK; | ||
1332 | } | 1137 | } |
1333 | 1138 | ||
1334 | 1139 | ||
1335 | /** | 1140 | /** |
1336 | * Reconnect to the service, retransmit all infomation to try to restore the | 1141 | * Function called during #GNUNET_CADET_disconnect() to destroy |
1337 | * original state. | 1142 | * all ports that are still open. |
1338 | * | ||
1339 | * @param h handle to the cadet | ||
1340 | * | 1143 | * |
1341 | * @return #GNUNET_YES in case of sucess, #GNUNET_NO otherwise (service down...) | 1144 | * @param cls the `struct GNUNET_CADET_Handle` |
1145 | * @param id port ID | ||
1146 | * @param value a `struct GNUNET_CADET_Channel` to destroy | ||
1147 | * @return #GNUNET_OK (continue to iterate) | ||
1342 | */ | 1148 | */ |
1343 | static void | 1149 | static int |
1344 | reconnect (struct GNUNET_CADET_Handle *h) | 1150 | destroy_port_cb (void *cls, |
1345 | { | 1151 | const struct GNUNET_HashCode *id, |
1346 | struct GNUNET_CADET_Channel *ch; | 1152 | void *value) |
1347 | |||
1348 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1349 | "Requested RECONNECT, destroying all channels\n"); | ||
1350 | while (NULL != (ch = h->channels_head)) | ||
1351 | destroy_channel (ch, GNUNET_YES); | ||
1352 | if (NULL == h->reconnect_task) | ||
1353 | h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, | ||
1354 | &reconnect_cbk, h); | ||
1355 | } | ||
1356 | |||
1357 | |||
1358 | /******************************************************************************/ | ||
1359 | /********************** API CALL DEFINITIONS *************************/ | ||
1360 | /******************************************************************************/ | ||
1361 | |||
1362 | struct GNUNET_CADET_Handle * | ||
1363 | GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
1364 | void *cls, | ||
1365 | GNUNET_CADET_ChannelEndHandler cleaner, | ||
1366 | const struct GNUNET_CADET_MessageHandler *handlers) | ||
1367 | { | 1153 | { |
1368 | struct GNUNET_CADET_Handle *h; | 1154 | /* struct GNUNET_CADET_Handle *handle = cls; */ |
1369 | 1155 | struct GNUNET_CADET_Port *port = value; | |
1370 | h = GNUNET_new (struct GNUNET_CADET_Handle); | ||
1371 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1372 | "GNUNET_CADET_connect() %p\n", | ||
1373 | h); | ||
1374 | h->cfg = cfg; | ||
1375 | h->cleaner = cleaner; | ||
1376 | h->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_YES); | ||
1377 | do_reconnect (h); | ||
1378 | if (h->mq == NULL) | ||
1379 | { | ||
1380 | GNUNET_break (0); | ||
1381 | GNUNET_CADET_disconnect (h); | ||
1382 | return NULL; | ||
1383 | } | ||
1384 | h->cls = cls; | ||
1385 | h->message_handlers = handlers; | ||
1386 | h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
1387 | h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1388 | h->reconnect_task = NULL; | ||
1389 | 1156 | ||
1390 | /* count handlers */ | 1157 | /* This is a warning, the app should have cleanly closed all open ports */ |
1391 | for (h->n_handlers = 0; | 1158 | GNUNET_break (0); |
1392 | handlers && handlers[h->n_handlers].type; | 1159 | GNUNET_CADET_close_port (port); |
1393 | h->n_handlers++) ; | 1160 | return GNUNET_OK; |
1394 | return h; | ||
1395 | } | 1161 | } |
1396 | 1162 | ||
1397 | 1163 | ||
@@ -1406,58 +1172,16 @@ GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
1406 | void | 1172 | void |
1407 | GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle) | 1173 | GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle) |
1408 | { | 1174 | { |
1409 | struct GNUNET_CADET_Channel *ch; | 1175 | GNUNET_CONTAINER_multihashmap_iterate (handle->ports, |
1410 | struct GNUNET_CADET_Channel *aux; | 1176 | &destroy_port_cb, |
1411 | struct GNUNET_CADET_TransmitHandle *th; | 1177 | handle); |
1412 | 1178 | GNUNET_CONTAINER_multihashmap_destroy (handle->ports); | |
1413 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1179 | handle->ports = NULL; |
1414 | "CADET DISCONNECT\n"); | 1180 | GNUNET_CONTAINER_multihashmap32_iterate (handle->channels, |
1415 | ch = handle->channels_head; | 1181 | &destroy_channel_cb, |
1416 | while (NULL != ch) | 1182 | handle); |
1417 | { | 1183 | GNUNET_CONTAINER_multihashmap32_destroy (handle->channels); |
1418 | aux = ch->next; | 1184 | handle->channels = NULL; |
1419 | if (ntohl (ch->ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
1420 | { | ||
1421 | GNUNET_break (0); | ||
1422 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1423 | "channel %X not destroyed\n", | ||
1424 | ntohl (ch->ccn.channel_of_client)); | ||
1425 | } | ||
1426 | destroy_channel (ch, | ||
1427 | GNUNET_YES); | ||
1428 | ch = aux; | ||
1429 | } | ||
1430 | while (NULL != (th = handle->th_head)) | ||
1431 | { | ||
1432 | struct GNUNET_MessageHeader *msg; | ||
1433 | |||
1434 | /* Make sure it is an allowed packet (everything else should have been | ||
1435 | * already canceled). | ||
1436 | */ | ||
1437 | GNUNET_break (GNUNET_NO == th_is_payload (th)); | ||
1438 | msg = (struct GNUNET_MessageHeader *) &th[1]; | ||
1439 | switch (ntohs(msg->type)) | ||
1440 | { | ||
1441 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN: | ||
1442 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
1443 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN: | ||
1444 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE: | ||
1445 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS: | ||
1446 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL: | ||
1447 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER: | ||
1448 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS: | ||
1449 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL: | ||
1450 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS: | ||
1451 | break; | ||
1452 | default: | ||
1453 | GNUNET_break (0); | ||
1454 | LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected unsent msg %s\n", | ||
1455 | GC_m2s (ntohs(msg->type))); | ||
1456 | } | ||
1457 | |||
1458 | GNUNET_CADET_notify_transmit_ready_cancel (th); | ||
1459 | } | ||
1460 | |||
1461 | if (NULL != handle->mq) | 1185 | if (NULL != handle->mq) |
1462 | { | 1186 | { |
1463 | GNUNET_MQ_destroy (handle->mq); | 1187 | GNUNET_MQ_destroy (handle->mq); |
@@ -1465,58 +1189,15 @@ GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle) | |||
1465 | } | 1189 | } |
1466 | if (NULL != handle->reconnect_task) | 1190 | if (NULL != handle->reconnect_task) |
1467 | { | 1191 | { |
1468 | GNUNET_SCHEDULER_cancel(handle->reconnect_task); | 1192 | GNUNET_SCHEDULER_cancel (handle->reconnect_task); |
1469 | handle->reconnect_task = NULL; | 1193 | handle->reconnect_task = NULL; |
1470 | } | 1194 | } |
1471 | |||
1472 | GNUNET_CONTAINER_multihashmap_destroy (handle->ports); | ||
1473 | handle->ports = NULL; | ||
1474 | GNUNET_free (handle); | 1195 | GNUNET_free (handle); |
1475 | } | 1196 | } |
1476 | 1197 | ||
1477 | 1198 | ||
1478 | /** | 1199 | /** |
1479 | * Open a port to receive incomming channels. | 1200 | * Close a port opened with @a GNUNET_CADET_open_port(). |
1480 | * | ||
1481 | * @param h CADET handle. | ||
1482 | * @param port Hash representing the port number. | ||
1483 | * @param new_channel Function called when an channel is received. | ||
1484 | * @param new_channel_cls Closure for @a new_channel. | ||
1485 | * @return Port handle. | ||
1486 | */ | ||
1487 | struct GNUNET_CADET_Port * | ||
1488 | GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h, | ||
1489 | const struct GNUNET_HashCode *port, | ||
1490 | GNUNET_CADET_InboundChannelNotificationHandler | ||
1491 | new_channel, | ||
1492 | void *new_channel_cls) | ||
1493 | { | ||
1494 | struct GNUNET_CADET_PortMessage *msg; | ||
1495 | struct GNUNET_MQ_Envelope *env; | ||
1496 | struct GNUNET_CADET_Port *p; | ||
1497 | |||
1498 | GNUNET_assert (NULL != new_channel); | ||
1499 | p = GNUNET_new (struct GNUNET_CADET_Port); | ||
1500 | p->cadet = h; | ||
1501 | p->hash = GNUNET_new (struct GNUNET_HashCode); | ||
1502 | *p->hash = *port; | ||
1503 | p->handler = new_channel; | ||
1504 | p->cls = new_channel_cls; | ||
1505 | GNUNET_assert (GNUNET_OK == | ||
1506 | GNUNET_CONTAINER_multihashmap_put (h->ports, | ||
1507 | p->hash, | ||
1508 | p, | ||
1509 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1510 | |||
1511 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN); | ||
1512 | msg->port = *p->hash; | ||
1513 | GNUNET_MQ_send (h->mq, env); | ||
1514 | |||
1515 | return p; | ||
1516 | } | ||
1517 | |||
1518 | /** | ||
1519 | * Close a port opened with @a GNUNET_CADET_open_port. | ||
1520 | * The @a new_channel callback will no longer be called. | 1201 | * The @a new_channel callback will no longer be called. |
1521 | * | 1202 | * |
1522 | * @param p Port handle. | 1203 | * @param p Port handle. |
@@ -1527,110 +1208,45 @@ GNUNET_CADET_close_port (struct GNUNET_CADET_Port *p) | |||
1527 | struct GNUNET_CADET_PortMessage *msg; | 1208 | struct GNUNET_CADET_PortMessage *msg; |
1528 | struct GNUNET_MQ_Envelope *env; | 1209 | struct GNUNET_MQ_Envelope *env; |
1529 | 1210 | ||
1530 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE); | 1211 | env = GNUNET_MQ_msg (msg, |
1531 | 1212 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE); | |
1532 | msg->port = *p->hash; | 1213 | msg->port = p->id; |
1533 | GNUNET_MQ_send (p->cadet->mq, env); | 1214 | GNUNET_MQ_send (p->cadet->mq, |
1534 | GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, p->hash, p); | 1215 | env); |
1535 | GNUNET_free (p->hash); | 1216 | GNUNET_assert (GNUNET_YES == |
1217 | GNUNET_CONTAINER_multihashmap_remove (p->cadet->ports, | ||
1218 | &p->id, | ||
1219 | p)); | ||
1220 | GNUNET_free_non_null (p->handlers); | ||
1536 | GNUNET_free (p); | 1221 | GNUNET_free (p); |
1537 | } | 1222 | } |
1538 | 1223 | ||
1539 | 1224 | ||
1540 | /** | 1225 | /** |
1541 | * Create a new channel towards a remote peer. | 1226 | * Destroy an existing channel. |
1542 | * | 1227 | * |
1543 | * If the destination port is not open by any peer or the destination peer | 1228 | * The existing end callback for the channel will be called immediately. |
1544 | * does not accept the channel, #GNUNET_CADET_ChannelEndHandler will be called | 1229 | * Any pending outgoing messages will be sent but no incoming messages will be |
1545 | * for this channel. | 1230 | * accepted and no data callbacks will be called. |
1546 | * | 1231 | * |
1547 | * @param h cadet handle | 1232 | * @param channel Channel handle, becomes invalid after this call. |
1548 | * @param channel_ctx client's channel context to associate with the channel | ||
1549 | * @param peer peer identity the channel should go to | ||
1550 | * @param port Port hash (port number). | ||
1551 | * @param options CadetOption flag field, with all desired option bits set to 1. | ||
1552 | * @return handle to the channel | ||
1553 | */ | 1233 | */ |
1554 | struct GNUNET_CADET_Channel * | ||
1555 | GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h, | ||
1556 | void *channel_ctx, | ||
1557 | const struct GNUNET_PeerIdentity *peer, | ||
1558 | const struct GNUNET_HashCode *port, | ||
1559 | enum GNUNET_CADET_ChannelOption options) | ||
1560 | { | ||
1561 | struct GNUNET_CADET_LocalChannelCreateMessage *msg; | ||
1562 | struct GNUNET_MQ_Envelope *env; | ||
1563 | struct GNUNET_CADET_Channel *ch; | ||
1564 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
1565 | |||
1566 | ccn.channel_of_client = htonl (0); | ||
1567 | ch = create_channel (h, ccn); | ||
1568 | ch->ctx = channel_ctx; | ||
1569 | ch->peer = GNUNET_PEER_intern (peer); | ||
1570 | |||
1571 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1572 | "Creating new channel to %s:%u at %p number %X\n", | ||
1573 | GNUNET_i2s (peer), | ||
1574 | port, | ||
1575 | ch, | ||
1576 | ntohl (ch->ccn.channel_of_client)); | ||
1577 | env = GNUNET_MQ_msg (msg, | ||
1578 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); | ||
1579 | msg->ccn = ch->ccn; | ||
1580 | msg->port = *port; | ||
1581 | msg->peer = *peer; | ||
1582 | msg->opt = htonl (options); | ||
1583 | GNUNET_MQ_send (h->mq, | ||
1584 | env); | ||
1585 | return ch; | ||
1586 | } | ||
1587 | |||
1588 | |||
1589 | void | 1234 | void |
1590 | GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel) | 1235 | GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel) |
1591 | { | 1236 | { |
1592 | struct GNUNET_CADET_Handle *h; | 1237 | struct GNUNET_CADET_Handle *h = channel->cadet; |
1593 | struct GNUNET_CADET_LocalChannelDestroyMessage *msg; | 1238 | struct GNUNET_CADET_LocalChannelDestroyMessage *msg; |
1594 | struct GNUNET_MQ_Envelope *env; | 1239 | struct GNUNET_MQ_Envelope *env; |
1595 | struct GNUNET_CADET_TransmitHandle *th; | ||
1596 | struct GNUNET_CADET_TransmitHandle *next; | ||
1597 | 1240 | ||
1598 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1241 | if (NULL != h->mq) |
1599 | "Destroying channel\n"); | ||
1600 | h = channel->cadet; | ||
1601 | for (th = h->th_head; th != NULL; th = next) | ||
1602 | { | 1242 | { |
1603 | next = th->next; | 1243 | env = GNUNET_MQ_msg (msg, |
1604 | if (th->channel == channel) | 1244 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); |
1605 | { | 1245 | msg->ccn = channel->ccn; |
1606 | GNUNET_break (0); | 1246 | GNUNET_MQ_send (h->mq, |
1607 | if (GNUNET_YES == th_is_payload (th)) | 1247 | env); |
1608 | { | ||
1609 | /* applications should cancel before destroying channel */ | ||
1610 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1611 | "Channel destroyed without cancelling transmission requests\n"); | ||
1612 | th->notify (th->notify_cls, 0, NULL); | ||
1613 | } | ||
1614 | else | ||
1615 | { | ||
1616 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1617 | "no meta-traffic should be queued\n"); | ||
1618 | } | ||
1619 | GNUNET_CONTAINER_DLL_remove (h->th_head, | ||
1620 | h->th_tail, | ||
1621 | th); | ||
1622 | GNUNET_CADET_notify_transmit_ready_cancel (th); | ||
1623 | } | ||
1624 | } | 1248 | } |
1625 | 1249 | destroy_channel (channel); | |
1626 | env = GNUNET_MQ_msg (msg, | ||
1627 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
1628 | msg->ccn = channel->ccn; | ||
1629 | GNUNET_MQ_send (h->mq, | ||
1630 | env); | ||
1631 | |||
1632 | destroy_channel (channel, | ||
1633 | GNUNET_YES); | ||
1634 | } | 1250 | } |
1635 | 1251 | ||
1636 | 1252 | ||
@@ -1645,10 +1261,10 @@ GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel) | |||
1645 | */ | 1261 | */ |
1646 | const union GNUNET_CADET_ChannelInfo * | 1262 | const union GNUNET_CADET_ChannelInfo * |
1647 | GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel, | 1263 | GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel, |
1648 | enum GNUNET_CADET_ChannelOption option, ...) | 1264 | enum GNUNET_CADET_ChannelOption option, |
1265 | ...) | ||
1649 | { | 1266 | { |
1650 | static int bool_flag; | 1267 | static int bool_flag; |
1651 | const union GNUNET_CADET_ChannelInfo *ret; | ||
1652 | 1268 | ||
1653 | switch (option) | 1269 | switch (option) |
1654 | { | 1270 | { |
@@ -1659,74 +1275,15 @@ GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel, | |||
1659 | bool_flag = GNUNET_YES; | 1275 | bool_flag = GNUNET_YES; |
1660 | else | 1276 | else |
1661 | bool_flag = GNUNET_NO; | 1277 | bool_flag = GNUNET_NO; |
1662 | ret = (const union GNUNET_CADET_ChannelInfo *) &bool_flag; | 1278 | return (const union GNUNET_CADET_ChannelInfo *) &bool_flag; |
1663 | break; | 1279 | break; |
1664 | case GNUNET_CADET_OPTION_PEER: | 1280 | case GNUNET_CADET_OPTION_PEER: |
1665 | ret = (const union GNUNET_CADET_ChannelInfo *) GNUNET_PEER_resolve2 (channel->peer); | 1281 | return (const union GNUNET_CADET_ChannelInfo *) &channel->peer; |
1666 | break; | 1282 | break; |
1667 | default: | 1283 | default: |
1668 | GNUNET_break (0); | 1284 | GNUNET_break (0); |
1669 | return NULL; | 1285 | return NULL; |
1670 | } | 1286 | } |
1671 | |||
1672 | return ret; | ||
1673 | } | ||
1674 | |||
1675 | |||
1676 | struct GNUNET_CADET_TransmitHandle * | ||
1677 | GNUNET_CADET_notify_transmit_ready (struct GNUNET_CADET_Channel *channel, | ||
1678 | int cork, | ||
1679 | struct GNUNET_TIME_Relative maxdelay, | ||
1680 | size_t notify_size, | ||
1681 | GNUNET_CONNECTION_TransmitReadyNotify notify, | ||
1682 | void *notify_cls) | ||
1683 | { | ||
1684 | struct GNUNET_CADET_TransmitHandle *th; | ||
1685 | |||
1686 | GNUNET_assert (NULL != channel); | ||
1687 | GNUNET_assert (NULL != notify); | ||
1688 | GNUNET_assert (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE >= notify_size); | ||
1689 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1690 | "CADET NOTIFY TRANSMIT READY on channel %X allow_send is %u to %s with %u bytes\n", | ||
1691 | channel->ccn, | ||
1692 | channel->allow_send, | ||
1693 | (ntohl (channel->ccn.channel_of_client) >= | ||
1694 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
1695 | ? "origin" | ||
1696 | : "destination", | ||
1697 | (unsigned int) notify_size); | ||
1698 | if (GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us != maxdelay.rel_value_us) | ||
1699 | { | ||
1700 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1701 | "CADET transmit ready timeout is deprected (has no effect)\n"); | ||
1702 | } | ||
1703 | |||
1704 | th = GNUNET_new (struct GNUNET_CADET_TransmitHandle); | ||
1705 | th->channel = channel; | ||
1706 | th->size = notify_size; | ||
1707 | th->notify = notify; | ||
1708 | th->notify_cls = notify_cls; | ||
1709 | if (0 != channel->allow_send) | ||
1710 | th->request_data_task | ||
1711 | = GNUNET_SCHEDULER_add_now (&request_data, | ||
1712 | th); | ||
1713 | else | ||
1714 | add_to_queue (channel->cadet, | ||
1715 | th); | ||
1716 | return th; | ||
1717 | } | ||
1718 | |||
1719 | |||
1720 | void | ||
1721 | GNUNET_CADET_notify_transmit_ready_cancel (struct GNUNET_CADET_TransmitHandle *th) | ||
1722 | { | ||
1723 | if (NULL != th->request_data_task) | ||
1724 | { | ||
1725 | GNUNET_SCHEDULER_cancel (th->request_data_task); | ||
1726 | th->request_data_task = NULL; | ||
1727 | } | ||
1728 | remove_from_queue (th); | ||
1729 | GNUNET_free (th); | ||
1730 | } | 1287 | } |
1731 | 1288 | ||
1732 | 1289 | ||
@@ -1745,25 +1302,30 @@ GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel) | |||
1745 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | 1302 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); |
1746 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1303 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1747 | "Sending ACK on channel %X\n", | 1304 | "Sending ACK on channel %X\n", |
1748 | channel->ccn.channel_of_client); | 1305 | ntohl (channel->ccn.channel_of_client)); |
1749 | msg->ccn = channel->ccn; | 1306 | msg->ccn = channel->ccn; |
1750 | GNUNET_MQ_send (channel->cadet->mq, | 1307 | GNUNET_MQ_send (channel->cadet->mq, |
1751 | env); | 1308 | env); |
1752 | } | 1309 | } |
1753 | 1310 | ||
1754 | 1311 | ||
1312 | /** | ||
1313 | * Send message of @a type to CADET service of @a h | ||
1314 | * | ||
1315 | * @param h handle to CADET service | ||
1316 | * @param type message type of trivial information request to send | ||
1317 | */ | ||
1755 | static void | 1318 | static void |
1756 | send_info_request (struct GNUNET_CADET_Handle *h, uint16_t type) | 1319 | send_info_request (struct GNUNET_CADET_Handle *h, |
1320 | uint16_t type) | ||
1757 | { | 1321 | { |
1758 | struct GNUNET_MessageHeader *msg; | 1322 | struct GNUNET_MessageHeader *msg; |
1759 | struct GNUNET_MQ_Envelope *env; | 1323 | struct GNUNET_MQ_Envelope *env; |
1760 | 1324 | ||
1761 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1325 | env = GNUNET_MQ_msg (msg, |
1762 | " Sending %s monitor message to service\n", | 1326 | type); |
1763 | GC_m2s(type)); | 1327 | GNUNET_MQ_send (h->mq, |
1764 | 1328 | env); | |
1765 | env = GNUNET_MQ_msg (msg, type); | ||
1766 | GNUNET_MQ_send (h->mq, env); | ||
1767 | } | 1329 | } |
1768 | 1330 | ||
1769 | 1331 | ||
@@ -1777,8 +1339,8 @@ send_info_request (struct GNUNET_CADET_Handle *h, uint16_t type) | |||
1777 | void | 1339 | void |
1778 | GNUNET_CADET_request_dump (struct GNUNET_CADET_Handle *h) | 1340 | GNUNET_CADET_request_dump (struct GNUNET_CADET_Handle *h) |
1779 | { | 1341 | { |
1780 | LOG (GNUNET_ERROR_TYPE_DEBUG, "requesting dump\n"); | 1342 | send_info_request (h, |
1781 | send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP); | 1343 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP); |
1782 | } | 1344 | } |
1783 | 1345 | ||
1784 | 1346 | ||
@@ -1787,13 +1349,11 @@ GNUNET_CADET_request_dump (struct GNUNET_CADET_Handle *h) | |||
1787 | * The callback will be called for every peer known to the service. | 1349 | * The callback will be called for every peer known to the service. |
1788 | * Only one info request (of any kind) can be active at once. | 1350 | * Only one info request (of any kind) can be active at once. |
1789 | * | 1351 | * |
1790 | * | ||
1791 | * WARNING: unstable API, likely to change in the future! | 1352 | * WARNING: unstable API, likely to change in the future! |
1792 | * | 1353 | * |
1793 | * @param h Handle to the cadet peer. | 1354 | * @param h Handle to the cadet peer. |
1794 | * @param callback Function to call with the requested data. | 1355 | * @param callback Function to call with the requested data. |
1795 | * @param callback_cls Closure for @c callback. | 1356 | * @param callback_cls Closure for @c callback. |
1796 | * | ||
1797 | * @return #GNUNET_OK / #GNUNET_SYSERR | 1357 | * @return #GNUNET_OK / #GNUNET_SYSERR |
1798 | */ | 1358 | */ |
1799 | int | 1359 | int |
@@ -1806,7 +1366,8 @@ GNUNET_CADET_get_peers (struct GNUNET_CADET_Handle *h, | |||
1806 | GNUNET_break (0); | 1366 | GNUNET_break (0); |
1807 | return GNUNET_SYSERR; | 1367 | return GNUNET_SYSERR; |
1808 | } | 1368 | } |
1809 | send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | 1369 | send_info_request (h, |
1370 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
1810 | h->info_cb.peers_cb = callback; | 1371 | h->info_cb.peers_cb = callback; |
1811 | h->info_cls = callback_cls; | 1372 | h->info_cls = callback_cls; |
1812 | return GNUNET_OK; | 1373 | return GNUNET_OK; |
@@ -1819,15 +1380,13 @@ GNUNET_CADET_get_peers (struct GNUNET_CADET_Handle *h, | |||
1819 | * WARNING: unstable API, likely to change in the future! | 1380 | * WARNING: unstable API, likely to change in the future! |
1820 | * | 1381 | * |
1821 | * @param h Cadet handle. | 1382 | * @param h Cadet handle. |
1822 | * | 1383 | * @return Closure given to GNUNET_CADET_get_peers(). |
1823 | * @return Closure given to GNUNET_CADET_get_peers. | ||
1824 | */ | 1384 | */ |
1825 | void * | 1385 | void * |
1826 | GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h) | 1386 | GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h) |
1827 | { | 1387 | { |
1828 | void *cls; | 1388 | void *cls = h->info_cls; |
1829 | 1389 | ||
1830 | cls = h->info_cls; | ||
1831 | h->info_cb.peers_cb = NULL; | 1390 | h->info_cb.peers_cb = NULL; |
1832 | h->info_cls = NULL; | 1391 | h->info_cls = NULL; |
1833 | return cls; | 1392 | return cls; |
@@ -1845,7 +1404,6 @@ GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h) | |||
1845 | * @param id Peer whose tunnel to examine. | 1404 | * @param id Peer whose tunnel to examine. |
1846 | * @param callback Function to call with the requested data. | 1405 | * @param callback Function to call with the requested data. |
1847 | * @param callback_cls Closure for @c callback. | 1406 | * @param callback_cls Closure for @c callback. |
1848 | * | ||
1849 | * @return #GNUNET_OK / #GNUNET_SYSERR | 1407 | * @return #GNUNET_OK / #GNUNET_SYSERR |
1850 | */ | 1408 | */ |
1851 | int | 1409 | int |
@@ -1862,11 +1420,11 @@ GNUNET_CADET_get_peer (struct GNUNET_CADET_Handle *h, | |||
1862 | GNUNET_break (0); | 1420 | GNUNET_break (0); |
1863 | return GNUNET_SYSERR; | 1421 | return GNUNET_SYSERR; |
1864 | } | 1422 | } |
1865 | 1423 | env = GNUNET_MQ_msg (msg, | |
1866 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); | 1424 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); |
1867 | msg->peer = *id; | 1425 | msg->peer = *id; |
1868 | GNUNET_MQ_send (h->mq, env); | 1426 | GNUNET_MQ_send (h->mq, |
1869 | 1427 | env); | |
1870 | h->info_cb.peer_cb = callback; | 1428 | h->info_cb.peer_cb = callback; |
1871 | h->info_cls = callback_cls; | 1429 | h->info_cls = callback_cls; |
1872 | return GNUNET_OK; | 1430 | return GNUNET_OK; |
@@ -1883,7 +1441,6 @@ GNUNET_CADET_get_peer (struct GNUNET_CADET_Handle *h, | |||
1883 | * @param h Handle to the cadet peer. | 1441 | * @param h Handle to the cadet peer. |
1884 | * @param callback Function to call with the requested data. | 1442 | * @param callback Function to call with the requested data. |
1885 | * @param callback_cls Closure for @c callback. | 1443 | * @param callback_cls Closure for @c callback. |
1886 | * | ||
1887 | * @return #GNUNET_OK / #GNUNET_SYSERR | 1444 | * @return #GNUNET_OK / #GNUNET_SYSERR |
1888 | */ | 1445 | */ |
1889 | int | 1446 | int |
@@ -1896,7 +1453,8 @@ GNUNET_CADET_get_tunnels (struct GNUNET_CADET_Handle *h, | |||
1896 | GNUNET_break (0); | 1453 | GNUNET_break (0); |
1897 | return GNUNET_SYSERR; | 1454 | return GNUNET_SYSERR; |
1898 | } | 1455 | } |
1899 | send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | 1456 | send_info_request (h, |
1457 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
1900 | h->info_cb.tunnels_cb = callback; | 1458 | h->info_cb.tunnels_cb = callback; |
1901 | h->info_cls = callback_cls; | 1459 | h->info_cls = callback_cls; |
1902 | return GNUNET_OK; | 1460 | return GNUNET_OK; |
@@ -1907,23 +1465,19 @@ GNUNET_CADET_get_tunnels (struct GNUNET_CADET_Handle *h, | |||
1907 | * Cancel a monitor request. The monitor callback will not be called. | 1465 | * Cancel a monitor request. The monitor callback will not be called. |
1908 | * | 1466 | * |
1909 | * @param h Cadet handle. | 1467 | * @param h Cadet handle. |
1910 | * | 1468 | * @return Closure given to GNUNET_CADET_get_tunnels(). |
1911 | * @return Closure given to GNUNET_CADET_get_tunnels. | ||
1912 | */ | 1469 | */ |
1913 | void * | 1470 | void * |
1914 | GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h) | 1471 | GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h) |
1915 | { | 1472 | { |
1916 | void *cls; | 1473 | void *cls = h->info_cls; |
1917 | 1474 | ||
1918 | h->info_cb.tunnels_cb = NULL; | 1475 | h->info_cb.tunnels_cb = NULL; |
1919 | cls = h->info_cls; | ||
1920 | h->info_cls = NULL; | 1476 | h->info_cls = NULL; |
1921 | |||
1922 | return cls; | 1477 | return cls; |
1923 | } | 1478 | } |
1924 | 1479 | ||
1925 | 1480 | ||
1926 | |||
1927 | /** | 1481 | /** |
1928 | * Request information about a tunnel of the running cadet peer. | 1482 | * Request information about a tunnel of the running cadet peer. |
1929 | * The callback will be called for the tunnel once. | 1483 | * The callback will be called for the tunnel once. |
@@ -1935,7 +1489,6 @@ GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h) | |||
1935 | * @param id Peer whose tunnel to examine. | 1489 | * @param id Peer whose tunnel to examine. |
1936 | * @param callback Function to call with the requested data. | 1490 | * @param callback Function to call with the requested data. |
1937 | * @param callback_cls Closure for @c callback. | 1491 | * @param callback_cls Closure for @c callback. |
1938 | * | ||
1939 | * @return #GNUNET_OK / #GNUNET_SYSERR | 1492 | * @return #GNUNET_OK / #GNUNET_SYSERR |
1940 | */ | 1493 | */ |
1941 | int | 1494 | int |
@@ -1952,11 +1505,11 @@ GNUNET_CADET_get_tunnel (struct GNUNET_CADET_Handle *h, | |||
1952 | GNUNET_break (0); | 1505 | GNUNET_break (0); |
1953 | return GNUNET_SYSERR; | 1506 | return GNUNET_SYSERR; |
1954 | } | 1507 | } |
1955 | 1508 | env = GNUNET_MQ_msg (msg, | |
1956 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | 1509 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); |
1957 | msg->peer = *id; | 1510 | msg->peer = *id; |
1958 | GNUNET_MQ_send (h->mq, env); | 1511 | GNUNET_MQ_send (h->mq, |
1959 | 1512 | env); | |
1960 | h->info_cb.tunnel_cb = callback; | 1513 | h->info_cb.tunnel_cb = callback; |
1961 | h->info_cls = callback_cls; | 1514 | h->info_cls = callback_cls; |
1962 | return GNUNET_OK; | 1515 | return GNUNET_OK; |
@@ -1964,175 +1517,190 @@ GNUNET_CADET_get_tunnel (struct GNUNET_CADET_Handle *h, | |||
1964 | 1517 | ||
1965 | 1518 | ||
1966 | /** | 1519 | /** |
1967 | * Request information about a specific channel of the running cadet peer. | 1520 | * Transitional function to convert an unsigned int port to a hash value. |
1968 | * | 1521 | * WARNING: local static value returned, NOT reentrant! |
1969 | * WARNING: unstable API, likely to change in the future! | 1522 | * WARNING: do not use this function for new code! |
1970 | * FIXME Add destination option. | ||
1971 | * | 1523 | * |
1972 | * @param h Handle to the cadet peer. | 1524 | * @param port Numerical port (unsigned int format). |
1973 | * @param initiator ID of the owner of the channel. | ||
1974 | * @param channel_number Channel number. | ||
1975 | * @param callback Function to call with the requested data. | ||
1976 | * @param callback_cls Closure for @c callback. | ||
1977 | * | 1525 | * |
1978 | * @return #GNUNET_OK / #GNUNET_SYSERR | 1526 | * @return A GNUNET_HashCode usable for the new CADET API. |
1979 | */ | 1527 | */ |
1980 | int | 1528 | const struct GNUNET_HashCode * |
1981 | GNUNET_CADET_show_channel (struct GNUNET_CADET_Handle *h, | 1529 | GC_u2h (uint32_t port) |
1982 | struct GNUNET_PeerIdentity *initiator, | ||
1983 | unsigned int channel_number, | ||
1984 | GNUNET_CADET_ChannelCB callback, | ||
1985 | void *callback_cls) | ||
1986 | { | 1530 | { |
1987 | struct GNUNET_CADET_LocalInfo *msg; | 1531 | static struct GNUNET_HashCode hash; |
1988 | struct GNUNET_MQ_Envelope *env; | ||
1989 | |||
1990 | if (NULL != h->info_cb.channel_cb) | ||
1991 | { | ||
1992 | GNUNET_break (0); | ||
1993 | return GNUNET_SYSERR; | ||
1994 | } | ||
1995 | |||
1996 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL); | ||
1997 | msg->peer = *initiator; | ||
1998 | msg->ccn.channel_of_client = htonl (channel_number); | ||
1999 | GNUNET_MQ_send (h->mq, env); | ||
2000 | 1532 | ||
2001 | h->info_cb.channel_cb = callback; | 1533 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
2002 | h->info_cls = callback_cls; | 1534 | "This is a transitional function, use proper crypto hashes as CADET ports\n"); |
2003 | return GNUNET_OK; | 1535 | GNUNET_CRYPTO_hash (&port, |
1536 | sizeof (port), | ||
1537 | &hash); | ||
1538 | return &hash; | ||
2004 | } | 1539 | } |
2005 | 1540 | ||
2006 | 1541 | ||
2007 | /** | 1542 | /** |
2008 | * Function called to notify a client about the connection | 1543 | * Connect to the MQ-based cadet service. |
2009 | * begin ready to queue more data. "buf" will be | ||
2010 | * NULL and "size" zero if the connection was closed for | ||
2011 | * writing in the meantime. | ||
2012 | * | 1544 | * |
2013 | * @param cls closure | 1545 | * @param cfg Configuration to use. |
2014 | * @param size number of bytes available in buf | 1546 | * |
2015 | * @param buf where the callee should write the message | 1547 | * @return Handle to the cadet service NULL on error. |
2016 | * @return number of bytes written to buf | ||
2017 | */ | 1548 | */ |
2018 | static size_t | 1549 | struct GNUNET_CADET_Handle * |
2019 | cadet_mq_ntr (void *cls, size_t size, | 1550 | GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) |
2020 | void *buf) | ||
2021 | { | 1551 | { |
2022 | struct GNUNET_MQ_Handle *mq = cls; | 1552 | struct GNUNET_CADET_Handle *h; |
2023 | struct CadetMQState *state = GNUNET_MQ_impl_state (mq); | ||
2024 | const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq); | ||
2025 | uint16_t msize; | ||
2026 | 1553 | ||
2027 | state->th = NULL; | 1554 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2028 | if (NULL == buf) | 1555 | "GNUNET_CADET_connect()\n"); |
1556 | h = GNUNET_new (struct GNUNET_CADET_Handle); | ||
1557 | h->cfg = cfg; | ||
1558 | h->ports = GNUNET_CONTAINER_multihashmap_create (4, | ||
1559 | GNUNET_YES); | ||
1560 | h->channels = GNUNET_CONTAINER_multihashmap32_create (4); | ||
1561 | reconnect (h); | ||
1562 | if (NULL == h->mq) | ||
2029 | { | 1563 | { |
2030 | GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE); | 1564 | GNUNET_break (0); |
2031 | return 0; | 1565 | GNUNET_CADET_disconnect (h); |
1566 | return NULL; | ||
2032 | } | 1567 | } |
2033 | msize = ntohs (msg->size); | 1568 | h->next_ccn.channel_of_client = htonl (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); |
2034 | GNUNET_assert (msize <= size); | 1569 | h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; |
2035 | GNUNET_memcpy (buf, msg, msize); | 1570 | h->reconnect_task = NULL; |
2036 | GNUNET_MQ_impl_send_continue (mq); | 1571 | |
2037 | return msize; | 1572 | return h; |
2038 | } | 1573 | } |
2039 | 1574 | ||
2040 | 1575 | ||
2041 | /** | 1576 | /** |
2042 | * Signature of functions implementing the | 1577 | * Open a port to receive incomming MQ-based channels. |
2043 | * sending functionality of a message queue. | ||
2044 | * | 1578 | * |
2045 | * @param mq the message queue | 1579 | * @param h CADET handle. |
2046 | * @param msg the message to send | 1580 | * @param port Hash identifying the port. |
2047 | * @param impl_state state of the implementation | 1581 | * @param connects Function called when an incoming channel is connected. |
1582 | * @param connects_cls Closure for the @a connects handler. | ||
1583 | * @param window_changes Function called when the transmit window size changes. | ||
1584 | * @param disconnects Function called when a channel is disconnected. | ||
1585 | * @param handlers Callbacks for messages we care about, NULL-terminated. | ||
1586 | * @return Port handle. | ||
2048 | */ | 1587 | */ |
2049 | static void | 1588 | struct GNUNET_CADET_Port * |
2050 | cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq, | 1589 | GNUNET_CADET_open_port (struct GNUNET_CADET_Handle *h, |
2051 | const struct GNUNET_MessageHeader *msg, | 1590 | const struct GNUNET_HashCode *port, |
2052 | void *impl_state) | 1591 | GNUNET_CADET_ConnectEventHandler connects, |
1592 | void * connects_cls, | ||
1593 | GNUNET_CADET_WindowSizeEventHandler window_changes, | ||
1594 | GNUNET_CADET_DisconnectEventHandler disconnects, | ||
1595 | const struct GNUNET_MQ_MessageHandler *handlers) | ||
2053 | { | 1596 | { |
2054 | struct CadetMQState *state = impl_state; | 1597 | struct GNUNET_CADET_PortMessage *msg; |
2055 | 1598 | struct GNUNET_MQ_Envelope *env; | |
2056 | GNUNET_assert (NULL == state->th); | 1599 | struct GNUNET_CADET_Port *p; |
2057 | state->th = | ||
2058 | GNUNET_CADET_notify_transmit_ready (state->channel, | ||
2059 | /* FIXME: add option for corking */ | ||
2060 | GNUNET_NO, | ||
2061 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
2062 | ntohs (msg->size), | ||
2063 | &cadet_mq_ntr, mq); | ||
2064 | |||
2065 | } | ||
2066 | 1600 | ||
1601 | GNUNET_assert (NULL != connects); | ||
1602 | GNUNET_assert (NULL != disconnects); | ||
2067 | 1603 | ||
2068 | /** | 1604 | p = GNUNET_new (struct GNUNET_CADET_Port); |
2069 | * Signature of functions implementing the | 1605 | p->cadet = h; |
2070 | * destruction of a message queue. | 1606 | p->id = *port; |
2071 | * Implementations must not free 'mq', but should | 1607 | p->connects = connects; |
2072 | * take care of 'impl_state'. | 1608 | p->cls = connects_cls; |
2073 | * | 1609 | p->window_changes = window_changes; |
2074 | * @param mq the message queue to destroy | 1610 | p->disconnects = disconnects; |
2075 | * @param impl_state state of the implementation | 1611 | p->handlers = GNUNET_MQ_copy_handlers (handlers); |
2076 | */ | ||
2077 | static void | ||
2078 | cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, | ||
2079 | void *impl_state) | ||
2080 | { | ||
2081 | struct CadetMQState *state = impl_state; | ||
2082 | 1612 | ||
2083 | if (NULL != state->th) | 1613 | GNUNET_assert (GNUNET_OK == |
2084 | GNUNET_CADET_notify_transmit_ready_cancel (state->th); | 1614 | GNUNET_CONTAINER_multihashmap_put (h->ports, |
1615 | &p->id, | ||
1616 | p, | ||
1617 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
2085 | 1618 | ||
2086 | GNUNET_free (state); | 1619 | env = GNUNET_MQ_msg (msg, |
1620 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN); | ||
1621 | msg->port = p->id; | ||
1622 | GNUNET_MQ_send (h->mq, | ||
1623 | env); | ||
1624 | return p; | ||
2087 | } | 1625 | } |
2088 | 1626 | ||
2089 | 1627 | ||
2090 | /** | 1628 | /** |
2091 | * Create a message queue for a cadet channel. | 1629 | * Create a new channel towards a remote peer. |
2092 | * The message queue can only be used to transmit messages, | ||
2093 | * not to receive them. | ||
2094 | * | 1630 | * |
2095 | * @param channel the channel to create the message qeue for | 1631 | * If the destination port is not open by any peer or the destination peer |
2096 | * @return a message queue to messages over the channel | 1632 | * does not accept the channel, #GNUNET_CADET_ChannelEndHandler will be called |
1633 | * for this channel. | ||
1634 | * | ||
1635 | * @param h CADET handle. | ||
1636 | * @param channel_cls Closure for the channel. It's given to: | ||
1637 | * - The disconnect handler @a disconnects | ||
1638 | * - Each message type callback in @a handlers | ||
1639 | * @param destination Peer identity the channel should go to. | ||
1640 | * @param port Identification of the destination port. | ||
1641 | * @param options CadetOption flag field, with all desired option bits set to 1. | ||
1642 | * @param window_changes Function called when the transmit window size changes. | ||
1643 | * @param disconnects Function called when the channel is disconnected. | ||
1644 | * @param handlers Callbacks for messages we care about, NULL-terminated. | ||
1645 | * @return Handle to the channel. | ||
2097 | */ | 1646 | */ |
2098 | struct GNUNET_MQ_Handle * | 1647 | struct GNUNET_CADET_Channel * |
2099 | GNUNET_CADET_mq_create (struct GNUNET_CADET_Channel *channel) | 1648 | GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h, |
1649 | void *channel_cls, | ||
1650 | const struct GNUNET_PeerIdentity *destination, | ||
1651 | const struct GNUNET_HashCode *port, | ||
1652 | enum GNUNET_CADET_ChannelOption options, | ||
1653 | GNUNET_CADET_WindowSizeEventHandler window_changes, | ||
1654 | GNUNET_CADET_DisconnectEventHandler disconnects, | ||
1655 | const struct GNUNET_MQ_MessageHandler *handlers) | ||
2100 | { | 1656 | { |
2101 | struct GNUNET_MQ_Handle *mq; | 1657 | struct GNUNET_CADET_Channel *ch; |
2102 | struct CadetMQState *state; | 1658 | struct GNUNET_CADET_LocalChannelCreateMessage *msg; |
2103 | 1659 | struct GNUNET_MQ_Envelope *env; | |
2104 | state = GNUNET_new (struct CadetMQState); | 1660 | |
2105 | state->channel = channel; | 1661 | GNUNET_assert (NULL != disconnects); |
2106 | 1662 | ch = create_channel (h, | |
2107 | mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl, | 1663 | NULL); |
2108 | &cadet_mq_destroy_impl, | 1664 | ch->ctx = channel_cls; |
2109 | NULL, /* FIXME: cancel impl. */ | 1665 | ch->peer = *destination; |
2110 | state, | 1666 | ch->options = options; |
2111 | NULL, /* no msg handlers */ | 1667 | ch->window_changes = window_changes; |
2112 | NULL, /* no err handlers */ | 1668 | ch->disconnects = disconnects; |
2113 | NULL); /* no handler cls */ | 1669 | |
2114 | return mq; | 1670 | /* Create MQ for channel */ |
1671 | ch->mq = GNUNET_MQ_queue_for_callbacks (&cadet_mq_send_impl, | ||
1672 | &cadet_mq_destroy_impl, | ||
1673 | &cadet_mq_cancel_impl, | ||
1674 | ch, | ||
1675 | handlers, | ||
1676 | &cadet_mq_error_handler, | ||
1677 | ch); | ||
1678 | GNUNET_MQ_set_handlers_closure (ch->mq, channel_cls); | ||
1679 | |||
1680 | /* Request channel creation to service */ | ||
1681 | env = GNUNET_MQ_msg (msg, | ||
1682 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); | ||
1683 | msg->ccn = ch->ccn; | ||
1684 | msg->port = *port; | ||
1685 | msg->peer = *destination; | ||
1686 | msg->opt = htonl (options); | ||
1687 | GNUNET_MQ_send (h->mq, | ||
1688 | env); | ||
1689 | return ch; | ||
2115 | } | 1690 | } |
2116 | 1691 | ||
2117 | 1692 | ||
2118 | /** | 1693 | /** |
2119 | * Transitional function to convert an unsigned int port to a hash value. | 1694 | * Obtain the message queue for a connected peer. |
2120 | * WARNING: local static value returned, NOT reentrant! | ||
2121 | * WARNING: do not use this function for new code! | ||
2122 | * | 1695 | * |
2123 | * @param port Numerical port (unsigned int format). | 1696 | * @param channel The channel handle from which to get the MQ. |
2124 | * | 1697 | * |
2125 | * @return A GNUNET_HashCode usable for the new CADET API. | 1698 | * @return NULL if @a channel is not yet connected. |
2126 | */ | 1699 | */ |
2127 | const struct GNUNET_HashCode * | 1700 | struct GNUNET_MQ_Handle * |
2128 | GC_u2h (uint32_t port) | 1701 | GNUNET_CADET_get_mq (const struct GNUNET_CADET_Channel *channel) |
2129 | { | 1702 | { |
2130 | static struct GNUNET_HashCode hash; | 1703 | return channel->mq; |
2131 | |||
2132 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
2133 | "This is a transitional function, " | ||
2134 | "use proper crypto hashes as CADET ports\n"); | ||
2135 | GNUNET_CRYPTO_hash (&port, sizeof (port), &hash); | ||
2136 | |||
2137 | return &hash; | ||
2138 | } | 1704 | } |
1705 | |||
1706 | /* end of cadet_api.c */ | ||
diff --git a/src/cadet/cadet_common.c b/src/cadet/cadet_common.c deleted file mode 100644 index 95a3144e4..000000000 --- a/src/cadet/cadet_common.c +++ /dev/null | |||
@@ -1,370 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/cadet_common.c | ||
23 | * @brief CADET helper functions | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "cadet.h" | ||
28 | |||
29 | /** | ||
30 | * @brief Translate a fwd variable into a string representation, for logging. | ||
31 | * | ||
32 | * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO) | ||
33 | * | ||
34 | * @return String representing FWD or BCK. | ||
35 | */ | ||
36 | char * | ||
37 | GC_f2s (int fwd) | ||
38 | { | ||
39 | if (GNUNET_YES == fwd) | ||
40 | { | ||
41 | return "FWD"; | ||
42 | } | ||
43 | else if (GNUNET_NO == fwd) | ||
44 | { | ||
45 | return "BCK"; | ||
46 | } | ||
47 | else | ||
48 | { | ||
49 | /* Not an error, can happen with CONNECTION_BROKEN messages. */ | ||
50 | return "\???"; | ||
51 | } | ||
52 | } | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Test if @a bigger is larger than @a smaller. | ||
57 | * Considers the case that @a bigger just overflowed | ||
58 | * and is thus tiny while @a smaller is still below | ||
59 | * `UINT32_MAX`. | ||
60 | */ | ||
61 | int | ||
62 | GC_is_pid_bigger (uint32_t bigger, | ||
63 | uint32_t smaller) | ||
64 | { | ||
65 | return (PID_OVERFLOW (smaller, bigger) || | ||
66 | ( (bigger > smaller) && | ||
67 | (! PID_OVERFLOW (bigger, smaller))) ); | ||
68 | } | ||
69 | |||
70 | |||
71 | uint32_t | ||
72 | GC_max_pid (uint32_t a, uint32_t b) | ||
73 | { | ||
74 | if (GC_is_pid_bigger(a, b)) | ||
75 | return a; | ||
76 | return b; | ||
77 | } | ||
78 | |||
79 | |||
80 | uint32_t | ||
81 | GC_min_pid (uint32_t a, uint32_t b) | ||
82 | { | ||
83 | if (GC_is_pid_bigger(a, b)) | ||
84 | return b; | ||
85 | return a; | ||
86 | } | ||
87 | |||
88 | |||
89 | /** | ||
90 | * Allocate a string with a hexdump of any binary data. | ||
91 | * | ||
92 | * @param bin Arbitrary binary data. | ||
93 | * @param len Length of @a bin in bytes. | ||
94 | * @param output Where to write the output (if *output be NULL it's allocated). | ||
95 | * | ||
96 | * @return The size of the output. | ||
97 | */ | ||
98 | size_t | ||
99 | GC_bin2s (void *bin, unsigned int len, char **output) | ||
100 | { | ||
101 | char *data = bin; | ||
102 | char *buf; | ||
103 | unsigned int s_len; | ||
104 | unsigned int i; | ||
105 | |||
106 | s_len = 2 * len + 1; | ||
107 | if (NULL == *output) | ||
108 | *output = GNUNET_malloc (s_len); | ||
109 | buf = *output; | ||
110 | |||
111 | for (i = 0; i < len; i++) | ||
112 | { | ||
113 | SPRINTF (&buf[2 * i], "%2X", data[i]); | ||
114 | } | ||
115 | buf[s_len - 1] = '\0'; | ||
116 | |||
117 | return s_len; | ||
118 | } | ||
119 | |||
120 | |||
121 | #if !defined(GNUNET_CULL_LOGGING) | ||
122 | const char * | ||
123 | GC_m2s (uint16_t m) | ||
124 | { | ||
125 | static char buf[2][16]; | ||
126 | static int idx; | ||
127 | const char *s; | ||
128 | |||
129 | idx = (idx + 1) % 2; | ||
130 | switch (m) | ||
131 | { | ||
132 | /** | ||
133 | * Used to mark the "payload" of a non-payload message. | ||
134 | */ | ||
135 | case 0: | ||
136 | s = "retransmit"; | ||
137 | break; | ||
138 | |||
139 | /** | ||
140 | * Request the creation of a path | ||
141 | */ | ||
142 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
143 | s = "CONN_CREAT"; | ||
144 | break; | ||
145 | |||
146 | /** | ||
147 | * Request the modification of an existing path | ||
148 | */ | ||
149 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK: | ||
150 | s = "CONN_ACK"; | ||
151 | break; | ||
152 | |||
153 | /** | ||
154 | * Notify that a connection of a path is no longer valid | ||
155 | */ | ||
156 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
157 | s = "CONN_BRKN"; | ||
158 | break; | ||
159 | |||
160 | /** | ||
161 | * At some point, the route will spontaneously change | ||
162 | */ | ||
163 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_PATH_CHANGED_UNIMPLEMENTED: | ||
164 | s = "PATH_CHNGD"; | ||
165 | break; | ||
166 | |||
167 | /** | ||
168 | * Transport payload data. | ||
169 | */ | ||
170 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA: | ||
171 | s = "DATA"; | ||
172 | break; | ||
173 | |||
174 | /** | ||
175 | * Confirm receipt of payload data. | ||
176 | */ | ||
177 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK: | ||
178 | s = "DATA_ACK"; | ||
179 | break; | ||
180 | |||
181 | /** | ||
182 | * Key exchange message. | ||
183 | */ | ||
184 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX: | ||
185 | s = "KX"; | ||
186 | break; | ||
187 | |||
188 | /** | ||
189 | * Encrypted. | ||
190 | */ | ||
191 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED: | ||
192 | s = "ENCRYPTED"; | ||
193 | break; | ||
194 | |||
195 | /** | ||
196 | * Request the destuction of a path | ||
197 | */ | ||
198 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
199 | s = "CONN_DSTRY"; | ||
200 | break; | ||
201 | |||
202 | /** | ||
203 | * ACK for a data packet. | ||
204 | */ | ||
205 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK: | ||
206 | s = "ACK"; | ||
207 | break; | ||
208 | |||
209 | /** | ||
210 | * POLL for ACK. | ||
211 | */ | ||
212 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL: | ||
213 | s = "POLL"; | ||
214 | break; | ||
215 | |||
216 | /** | ||
217 | * Announce origin is still alive. | ||
218 | */ | ||
219 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE: | ||
220 | s = "KEEPALIVE"; | ||
221 | break; | ||
222 | |||
223 | /** | ||
224 | * Open port | ||
225 | */ | ||
226 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN: | ||
227 | s = "OPEN_PORT"; | ||
228 | break; | ||
229 | |||
230 | /** | ||
231 | * Close port | ||
232 | */ | ||
233 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE: | ||
234 | s = "CLOSE_PORT"; | ||
235 | break; | ||
236 | |||
237 | /** | ||
238 | * Ask the cadet service to create a new tunnel | ||
239 | */ | ||
240 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN: | ||
241 | s = "CHAN_CREAT"; | ||
242 | break; | ||
243 | |||
244 | /** | ||
245 | * Ask the cadet service to destroy a tunnel | ||
246 | */ | ||
247 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
248 | s = "CHAN_DSTRY"; | ||
249 | break; | ||
250 | |||
251 | /** | ||
252 | * Confirm the creation of a channel. | ||
253 | */ | ||
254 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK: | ||
255 | s = "CHAN_ACK"; | ||
256 | break; | ||
257 | |||
258 | /** | ||
259 | * Confirm the creation of a channel. | ||
260 | */ | ||
261 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED: | ||
262 | s = "CHAN_NACK"; | ||
263 | break; | ||
264 | |||
265 | /** | ||
266 | * Local payload traffic | ||
267 | */ | ||
268 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA: | ||
269 | s = "LOC_DATA"; | ||
270 | break; | ||
271 | |||
272 | /** | ||
273 | * Local ACK for data. | ||
274 | */ | ||
275 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK: | ||
276 | s = "LOC_ACK"; | ||
277 | break; | ||
278 | |||
279 | /** | ||
280 | * Local monitoring of channels. | ||
281 | */ | ||
282 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS: | ||
283 | s = "INFO_CHANS"; | ||
284 | break; | ||
285 | |||
286 | /** | ||
287 | * Local monitoring of a channel. | ||
288 | */ | ||
289 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL: | ||
290 | s = "INFO_CHAN"; | ||
291 | break; | ||
292 | |||
293 | /** | ||
294 | * Local monitoring of service. | ||
295 | */ | ||
296 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS: | ||
297 | s = "INFO_TUNS"; | ||
298 | break; | ||
299 | |||
300 | /** | ||
301 | * Local monitoring of service. | ||
302 | */ | ||
303 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL: | ||
304 | s = "INFO_TUN"; | ||
305 | break; | ||
306 | |||
307 | /** | ||
308 | * Local information about all connections of service. | ||
309 | */ | ||
310 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CONNECTIONS: | ||
311 | s = "INFO_CONNS"; | ||
312 | break; | ||
313 | |||
314 | /** | ||
315 | * Local information of service about a specific connection. | ||
316 | */ | ||
317 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CONNECTION: | ||
318 | s = "INFO_CONN"; | ||
319 | break; | ||
320 | |||
321 | /** | ||
322 | * Local information about all peers known to the service. | ||
323 | */ | ||
324 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS: | ||
325 | s = "INFO_PEERS"; | ||
326 | break; | ||
327 | |||
328 | /** | ||
329 | * Local information of service about a specific peer. | ||
330 | */ | ||
331 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER: | ||
332 | s = "INFO_PEER"; | ||
333 | break; | ||
334 | |||
335 | /** | ||
336 | * Traffic (net-cat style) used by the Command Line Interface. | ||
337 | */ | ||
338 | case GNUNET_MESSAGE_TYPE_CADET_CLI: | ||
339 | s = "CLI"; | ||
340 | break; | ||
341 | |||
342 | /** | ||
343 | * Debug request. | ||
344 | */ | ||
345 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP: | ||
346 | s = "INFO_DUMP"; | ||
347 | break; | ||
348 | |||
349 | /** | ||
350 | * Used to mark the "payload" of a non-payload message. | ||
351 | */ | ||
352 | case UINT16_MAX: | ||
353 | s = " N/A"; | ||
354 | break; | ||
355 | |||
356 | |||
357 | default: | ||
358 | SPRINTF (buf[idx], "{UNK: %5u}", m); | ||
359 | return buf[idx]; | ||
360 | } | ||
361 | SPRINTF (buf[idx], "{%10s}", s); | ||
362 | return buf[idx]; | ||
363 | } | ||
364 | #else | ||
365 | const char * | ||
366 | GC_m2s (uint16_t m) | ||
367 | { | ||
368 | return ""; | ||
369 | } | ||
370 | #endif | ||
diff --git a/src/cadet/cadet_path.c b/src/cadet/cadet_path.c deleted file mode 100644 index 79a498805..000000000 --- a/src/cadet/cadet_path.c +++ /dev/null | |||
@@ -1,363 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001 - 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/cadet_path.c | ||
23 | * @brief Path handling functions | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "cadet.h" | ||
28 | #include "cadet_path.h" | ||
29 | #include "gnunet-service-cadet_peer.h" | ||
30 | |||
31 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-pth",__VA_ARGS__) | ||
32 | |||
33 | |||
34 | /** | ||
35 | * @brief Destroy a path after some time has past. | ||
36 | * Removes the path from the peer (must not be used for direct paths). | ||
37 | * | ||
38 | * @param cls Closure (path to destroy). | ||
39 | */ | ||
40 | static void | ||
41 | path_destroy_delayed (void *cls) | ||
42 | { | ||
43 | struct CadetPeerPath *path = cls; | ||
44 | struct CadetPeer *peer; | ||
45 | |||
46 | path->path_delete = NULL; | ||
47 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
48 | "Destroy delayed %p (%u)\n", | ||
49 | path, | ||
50 | path->length); | ||
51 | GNUNET_assert (2 < path->length); | ||
52 | peer = GCP_get_short (path->peers[path->length - 1], | ||
53 | GNUNET_NO); | ||
54 | GNUNET_assert (NULL != peer); | ||
55 | GCP_remove_path (peer, path); | ||
56 | } | ||
57 | |||
58 | |||
59 | /** | ||
60 | * Create a new path | ||
61 | * | ||
62 | * @param length How many hops will the path have. | ||
63 | * @return A newly allocated path with a peer array of the specified length. | ||
64 | */ | ||
65 | struct CadetPeerPath * | ||
66 | path_new (unsigned int length) | ||
67 | { | ||
68 | struct CadetPeerPath *p; | ||
69 | |||
70 | p = GNUNET_new (struct CadetPeerPath); | ||
71 | if (length > 0) | ||
72 | { | ||
73 | p->length = length; | ||
74 | p->peers = GNUNET_malloc (length * sizeof (GNUNET_PEER_Id)); | ||
75 | } | ||
76 | LOG (GNUNET_ERROR_TYPE_DEBUG, "New path %p (%u)\n", p, p->length); | ||
77 | return p; | ||
78 | } | ||
79 | |||
80 | |||
81 | /** | ||
82 | * Invert the path | ||
83 | * | ||
84 | * @param path the path to invert | ||
85 | */ | ||
86 | void | ||
87 | path_invert (struct CadetPeerPath *path) | ||
88 | { | ||
89 | GNUNET_PEER_Id aux; | ||
90 | unsigned int i; | ||
91 | |||
92 | for (i = 0; i < path->length / 2; i++) | ||
93 | { | ||
94 | aux = path->peers[i]; | ||
95 | path->peers[i] = path->peers[path->length - i - 1]; | ||
96 | path->peers[path->length - i - 1] = aux; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | |||
101 | /** | ||
102 | * Duplicate a path, incrementing short peer's rc. | ||
103 | * | ||
104 | * @param path The path to duplicate. | ||
105 | */ | ||
106 | struct CadetPeerPath * | ||
107 | path_duplicate (const struct CadetPeerPath *path) | ||
108 | { | ||
109 | struct CadetPeerPath *aux; | ||
110 | unsigned int i; | ||
111 | |||
112 | aux = path_new (path->length); | ||
113 | GNUNET_memcpy (aux->peers, | ||
114 | path->peers, | ||
115 | path->length * sizeof (GNUNET_PEER_Id)); | ||
116 | for (i = 0; i < aux->length; i++) | ||
117 | GNUNET_PEER_change_rc (aux->peers[i], 1); | ||
118 | return aux; | ||
119 | } | ||
120 | |||
121 | |||
122 | /** | ||
123 | * Get the length of a path. | ||
124 | * | ||
125 | * @param path The path to measure, with the local peer at any point of it. | ||
126 | * | ||
127 | * @return Number of hops to reach destination. | ||
128 | * UINT_MAX in case the peer is not in the path. | ||
129 | */ | ||
130 | unsigned int | ||
131 | path_get_length (struct CadetPeerPath *path) | ||
132 | { | ||
133 | if (NULL == path) | ||
134 | return UINT_MAX; | ||
135 | return path->length; | ||
136 | } | ||
137 | |||
138 | |||
139 | |||
140 | /** | ||
141 | * Mark path as invalid: keep it aroud for a while to avoid trying it in a loop. | ||
142 | * | ||
143 | * Never invalidates a two-hop (direct) path, only a core handler can do that. | ||
144 | * | ||
145 | * Rationale: DHT_get sometimes returns bad cached results, for instance, | ||
146 | * on a locally cached result where the PUT followed a path that is no longer | ||
147 | * current. The path must remain "known and marked as invalid" for a while. | ||
148 | * | ||
149 | * @param p Path to invalidate. | ||
150 | */ | ||
151 | void | ||
152 | path_invalidate (struct CadetPeerPath *p) | ||
153 | { | ||
154 | if (NULL != p->path_delete) | ||
155 | return; | ||
156 | |||
157 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
158 | "Invalidating path %p (%u)\n", | ||
159 | p, | ||
160 | p->length); | ||
161 | p->path_delete | ||
162 | = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, | ||
163 | &path_destroy_delayed, p); | ||
164 | } | ||
165 | |||
166 | |||
167 | /** | ||
168 | * Builds a path from a PeerIdentity array. | ||
169 | * | ||
170 | * @param peers PeerIdentity array. | ||
171 | * @param size Size of the @c peers array. | ||
172 | * @param myid ID of local peer, to find @c own_pos. | ||
173 | * @param own_pos Output parameter: own position in the path. | ||
174 | * | ||
175 | * @return Fixed and shortened path. | ||
176 | */ | ||
177 | struct CadetPeerPath * | ||
178 | path_build_from_peer_ids (struct GNUNET_PeerIdentity *peers, | ||
179 | unsigned int size, | ||
180 | GNUNET_PEER_Id myid, | ||
181 | unsigned int *own_pos) | ||
182 | { | ||
183 | struct CadetPeerPath *path; | ||
184 | GNUNET_PEER_Id shortid; | ||
185 | unsigned int i; | ||
186 | unsigned int j; | ||
187 | unsigned int offset; | ||
188 | |||
189 | /* Create path */ | ||
190 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n"); | ||
191 | path = path_new (size); | ||
192 | *own_pos = 0; | ||
193 | offset = 0; | ||
194 | for (i = 0; i < size; i++) | ||
195 | { | ||
196 | LOG (GNUNET_ERROR_TYPE_DEBUG, " - %u: taking %s\n", | ||
197 | i, GNUNET_i2s (&peers[i])); | ||
198 | shortid = GNUNET_PEER_intern (&peers[i]); | ||
199 | |||
200 | /* Check for loops / duplicates */ | ||
201 | for (j = 0; j < i - offset; j++) | ||
202 | { | ||
203 | if (path->peers[j] == shortid) | ||
204 | { | ||
205 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already exists at pos %u\n", j); | ||
206 | offset = i - j; | ||
207 | LOG (GNUNET_ERROR_TYPE_DEBUG, " offset now %u\n", offset); | ||
208 | GNUNET_PEER_change_rc (shortid, -1); | ||
209 | } | ||
210 | } | ||
211 | LOG (GNUNET_ERROR_TYPE_DEBUG, " storing at %u\n", i - offset); | ||
212 | path->peers[i - offset] = shortid; | ||
213 | if (path->peers[i - offset] == myid) | ||
214 | *own_pos = i - offset; | ||
215 | } | ||
216 | path->length -= offset; | ||
217 | |||
218 | if (path->peers[*own_pos] != myid) | ||
219 | { | ||
220 | /* create path: self not found in path through self */ | ||
221 | GNUNET_break_op (0); | ||
222 | path_destroy (path); | ||
223 | return NULL; | ||
224 | } | ||
225 | |||
226 | return path; | ||
227 | } | ||
228 | |||
229 | |||
230 | /** | ||
231 | * Test if two paths are equivalent (equal or revese of each other). | ||
232 | * | ||
233 | * @param p1 First path | ||
234 | * @param p2 Second path | ||
235 | * | ||
236 | * @return #GNUNET_YES if both paths are equivalent | ||
237 | * #GNUNET_NO otherwise | ||
238 | */ | ||
239 | int | ||
240 | path_equivalent (const struct CadetPeerPath *p1, | ||
241 | const struct CadetPeerPath *p2) | ||
242 | { | ||
243 | unsigned int i; | ||
244 | unsigned int l; | ||
245 | unsigned int half; | ||
246 | |||
247 | if (NULL == p1 || NULL == p2) | ||
248 | return GNUNET_NO; | ||
249 | |||
250 | if (p1->length != p2->length) | ||
251 | return GNUNET_NO; | ||
252 | |||
253 | l = p1->length; | ||
254 | if (0 == memcmp (p1->peers, p2->peers, sizeof (p1->peers[0]) * l)) | ||
255 | return GNUNET_YES; | ||
256 | |||
257 | half = l / 2; | ||
258 | l = l - 1; | ||
259 | for (i = 0; i <= half; i++) | ||
260 | if (p1->peers[i] != p2->peers[l - i]) | ||
261 | return GNUNET_NO; | ||
262 | |||
263 | return GNUNET_YES; | ||
264 | } | ||
265 | |||
266 | |||
267 | /** | ||
268 | * Test if a path is valid (or at least not known to be invalid). | ||
269 | * | ||
270 | * @param path Path to test. | ||
271 | * | ||
272 | * @return #GNUNET_YES If the path is valid or unknown, | ||
273 | * #GNUNET_NO If the path is known to be invalid. | ||
274 | */ | ||
275 | int | ||
276 | path_is_valid (const struct CadetPeerPath *path) | ||
277 | { | ||
278 | return (NULL == path->path_delete); | ||
279 | } | ||
280 | |||
281 | |||
282 | /** | ||
283 | * Destroy the path and free any allocated resources linked to it | ||
284 | * | ||
285 | * @param p the path to destroy | ||
286 | * | ||
287 | * @return #GNUNET_OK on success | ||
288 | */ | ||
289 | int | ||
290 | path_destroy (struct CadetPeerPath *p) | ||
291 | { | ||
292 | if (NULL == p) | ||
293 | return GNUNET_OK; | ||
294 | |||
295 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
296 | "destroying path %p (%u)\n", | ||
297 | p, | ||
298 | p->length); | ||
299 | GNUNET_PEER_decrement_rcs (p->peers, p->length); | ||
300 | GNUNET_free_non_null (p->peers); | ||
301 | if (NULL != p->path_delete) | ||
302 | GNUNET_SCHEDULER_cancel (p->path_delete); | ||
303 | GNUNET_free (p); | ||
304 | return GNUNET_OK; | ||
305 | } | ||
306 | |||
307 | |||
308 | /** | ||
309 | * Compare two paths. | ||
310 | * | ||
311 | * @param p1 First path. | ||
312 | * @param p2 Second path. | ||
313 | * | ||
314 | * @return > 0 if p1 is longer, or the first differing PEER_Id is higher on p1. | ||
315 | * < 0 if p2 is longer, or the first differing PEER_Id is higher on p2. | ||
316 | * 0 if they are identical. | ||
317 | */ | ||
318 | int | ||
319 | path_cmp (const struct CadetPeerPath *p1, | ||
320 | const struct CadetPeerPath *p2) | ||
321 | { | ||
322 | if (p1->length > p2->length) | ||
323 | return 1; | ||
324 | |||
325 | if (p1->length < p2->length) | ||
326 | return -1; | ||
327 | |||
328 | return memcmp (p1->peers, | ||
329 | p2->peers, | ||
330 | sizeof (GNUNET_PEER_Id) * p1->length); | ||
331 | } | ||
332 | |||
333 | |||
334 | char * | ||
335 | path_2s (struct CadetPeerPath *p) | ||
336 | { | ||
337 | char *s; | ||
338 | char *old; | ||
339 | unsigned int i; | ||
340 | |||
341 | old = GNUNET_strdup (""); | ||
342 | for (i = 0; i < p->length; i++) | ||
343 | { | ||
344 | GNUNET_asprintf (&s, "%s %s", | ||
345 | old, GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i]))); | ||
346 | GNUNET_free_non_null (old); | ||
347 | old = s; | ||
348 | } | ||
349 | return old; | ||
350 | } | ||
351 | |||
352 | |||
353 | void | ||
354 | path_debug (struct CadetPeerPath *p) | ||
355 | { | ||
356 | unsigned int i; | ||
357 | |||
358 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH:\n"); | ||
359 | for (i = 0; i < p->length; i++) | ||
360 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", | ||
361 | GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i]))); | ||
362 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "END\n"); | ||
363 | } | ||
diff --git a/src/cadet/cadet_path.h b/src/cadet/cadet_path.h deleted file mode 100644 index bb68eec42..000000000 --- a/src/cadet/cadet_path.h +++ /dev/null | |||
@@ -1,226 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001 - 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/cadet_path.h | ||
23 | * @brief Path handling functions | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #ifndef CADET_PATH_H_ | ||
28 | #define CADET_PATH_H_ | ||
29 | |||
30 | #ifdef __cplusplus | ||
31 | extern "C" | ||
32 | { | ||
33 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
34 | } | ||
35 | #endif | ||
36 | #endif | ||
37 | |||
38 | |||
39 | /******************************************************************************/ | ||
40 | /************************ DATA STRUCTURES ****************************/ | ||
41 | /******************************************************************************/ | ||
42 | |||
43 | /** | ||
44 | * Information regarding a possible path to reach a single peer | ||
45 | */ | ||
46 | struct CadetPeerPath | ||
47 | { | ||
48 | |||
49 | /** | ||
50 | * Linked list | ||
51 | */ | ||
52 | struct CadetPeerPath *next; | ||
53 | struct CadetPeerPath *prev; | ||
54 | |||
55 | /** | ||
56 | * List of all the peers that form the path from origin to target. | ||
57 | */ | ||
58 | GNUNET_PEER_Id *peers; | ||
59 | |||
60 | /** | ||
61 | * Number of peers (hops) in the path | ||
62 | */ | ||
63 | unsigned int length; | ||
64 | |||
65 | /** | ||
66 | * User defined data store. | ||
67 | */ | ||
68 | struct CadetConnection *c; | ||
69 | |||
70 | /** | ||
71 | * Path's score, how reliable is the path. | ||
72 | */ | ||
73 | // int score; | ||
74 | |||
75 | /** | ||
76 | * Task to delete the path. | ||
77 | * We tried it, it didn't work, don't try again in a while. | ||
78 | */ | ||
79 | struct GNUNET_SCHEDULER_Task * path_delete; | ||
80 | |||
81 | }; | ||
82 | |||
83 | /******************************************************************************/ | ||
84 | /************************* FUNCTIONS *****************************/ | ||
85 | /******************************************************************************/ | ||
86 | |||
87 | /** | ||
88 | * Create a new path. | ||
89 | * | ||
90 | * @param length How many hops will the path have. | ||
91 | * | ||
92 | * @return A newly allocated path with a peer array of the specified length. | ||
93 | */ | ||
94 | struct CadetPeerPath * | ||
95 | path_new (unsigned int length); | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Invert the path. | ||
100 | * | ||
101 | * @param path The path to invert. | ||
102 | */ | ||
103 | void | ||
104 | path_invert (struct CadetPeerPath *path); | ||
105 | |||
106 | |||
107 | /** | ||
108 | * Duplicate a path, incrementing short peer's rc. | ||
109 | * | ||
110 | * @param path The path to duplicate. | ||
111 | */ | ||
112 | struct CadetPeerPath * | ||
113 | path_duplicate (const struct CadetPeerPath *path); | ||
114 | |||
115 | |||
116 | /** | ||
117 | * Get the length of a path. | ||
118 | * | ||
119 | * @param path The path to measure, with the local peer at any point of it. | ||
120 | * | ||
121 | * @return Number of hops to reach destination. | ||
122 | * UINT_MAX in case the peer is not in the path. | ||
123 | */ | ||
124 | unsigned int | ||
125 | path_get_length (struct CadetPeerPath *path); | ||
126 | |||
127 | /** | ||
128 | * Mark path as invalid: keep it aroud for a while to avoid trying it in a loop. | ||
129 | * | ||
130 | * DHT_get sometimes returns bad cached results, for instance, on a locally | ||
131 | * cached result where the PUT followed a path that is no longer current. | ||
132 | * | ||
133 | * @param p Path to invalidate. | ||
134 | */ | ||
135 | void | ||
136 | path_invalidate (struct CadetPeerPath *p); | ||
137 | |||
138 | /** | ||
139 | * Test if two paths are equivalent (equal or revese of each other). | ||
140 | * | ||
141 | * @param p1 First path | ||
142 | * @param p2 Second path | ||
143 | * | ||
144 | * @return GNUNET_YES if both paths are equivalent | ||
145 | * GNUNET_NO otherwise | ||
146 | */ | ||
147 | int | ||
148 | path_equivalent (const struct CadetPeerPath *p1, | ||
149 | const struct CadetPeerPath *p2); | ||
150 | |||
151 | /** | ||
152 | * Test if a path is valid (or at least not known to be invalid). | ||
153 | * | ||
154 | * @param path Path to test. | ||
155 | * | ||
156 | * @return #GNUNET_YES If the path is valid or unknown, | ||
157 | * #GNUNET_NO If the path is known to be invalid. | ||
158 | */ | ||
159 | int | ||
160 | path_is_valid (const struct CadetPeerPath *path); | ||
161 | |||
162 | /** | ||
163 | * Destroy the path and free any allocated resources linked to it | ||
164 | * | ||
165 | * @param p the path to destroy | ||
166 | * | ||
167 | * @return GNUNET_OK on success | ||
168 | */ | ||
169 | int | ||
170 | path_destroy (struct CadetPeerPath *p); | ||
171 | |||
172 | /** | ||
173 | * Compare two paths. | ||
174 | * | ||
175 | * @param p1 First path. | ||
176 | * @param p2 Second path. | ||
177 | * | ||
178 | * @return > 0 if p1 is longer, or the first differing PEER_Id is higher on p1. | ||
179 | * < 0 if p2 is longer, or the first differing PEER_Id is higher on p2. | ||
180 | * 0 if they are identical. | ||
181 | */ | ||
182 | int | ||
183 | path_cmp (const struct CadetPeerPath *p1, const struct CadetPeerPath *p2); | ||
184 | |||
185 | /** | ||
186 | * Builds a path from a PeerIdentity array. | ||
187 | * | ||
188 | * @param peers PeerIdentity array. | ||
189 | * @param size Size of the @c peers array. | ||
190 | * @param myid ID of local peer, to find @c own_pos. | ||
191 | * @param own_pos Output parameter: own position in the path. | ||
192 | * | ||
193 | * @return Fixed and shortened path. | ||
194 | */ | ||
195 | struct CadetPeerPath * | ||
196 | path_build_from_peer_ids (struct GNUNET_PeerIdentity *peers, | ||
197 | unsigned int size, | ||
198 | GNUNET_PEER_Id myid, | ||
199 | unsigned int *own_pos); | ||
200 | |||
201 | /** | ||
202 | * Path -> allocated one line string. Caller must free. | ||
203 | * | ||
204 | * @param p Path. | ||
205 | */ | ||
206 | char * | ||
207 | path_2s (struct CadetPeerPath *p); | ||
208 | |||
209 | /** | ||
210 | * Print info about the path for debug. | ||
211 | * | ||
212 | * @param p Path to debug. | ||
213 | */ | ||
214 | void | ||
215 | path_debug (struct CadetPeerPath *p); | ||
216 | |||
217 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
218 | { | ||
219 | #endif | ||
220 | #ifdef __cplusplus | ||
221 | } | ||
222 | #endif | ||
223 | |||
224 | |||
225 | /* ifndef CADET_PATH_H */ | ||
226 | #endif | ||
diff --git a/src/cadet/cadet_protocol.h b/src/cadet/cadet_protocol.h index 5ec34f7d7..de0cec5d0 100644 --- a/src/cadet/cadet_protocol.h +++ b/src/cadet/cadet_protocol.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2001 - 2011 GNUnet e.V. | 3 | Copyright (C) 2007 - 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -19,8 +19,10 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @author Bartlomiej Polot | ||
23 | * @file cadet/cadet_protocol.h | 22 | * @file cadet/cadet_protocol.h |
23 | * @brief P2P messages used by CADET | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
24 | */ | 26 | */ |
25 | 27 | ||
26 | #ifndef CADET_PROTOCOL_H_ | 28 | #ifndef CADET_PROTOCOL_H_ |
@@ -67,9 +69,12 @@ struct GNUNET_CADET_ConnectionCreateMessage | |||
67 | struct GNUNET_MessageHeader header; | 69 | struct GNUNET_MessageHeader header; |
68 | 70 | ||
69 | /** | 71 | /** |
70 | * For alignment. | 72 | * Connection options in network byte order. |
73 | * #GNUNET_CADET_OPTION_DEFAULT for buffered; | ||
74 | * #GNUNET_CADET_OPTION_NOBUFFER for unbuffered. | ||
75 | * Other flags are ignored and should not be set at this level. | ||
71 | */ | 76 | */ |
72 | uint32_t reserved GNUNET_PACKED; | 77 | uint32_t options GNUNET_PACKED; |
73 | 78 | ||
74 | /** | 79 | /** |
75 | * ID of the connection | 80 | * ID of the connection |
@@ -205,7 +210,9 @@ enum GNUNET_CADET_KX_Flags { | |||
205 | struct GNUNET_CADET_TunnelKeyExchangeMessage | 210 | struct GNUNET_CADET_TunnelKeyExchangeMessage |
206 | { | 211 | { |
207 | /** | 212 | /** |
208 | * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX. | 213 | * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX or |
214 | * #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH as part | ||
215 | * of `struct GNUNET_CADET_TunnelKeyExchangeAuthMessage`. | ||
209 | */ | 216 | */ |
210 | struct GNUNET_MessageHeader header; | 217 | struct GNUNET_MessageHeader header; |
211 | 218 | ||
@@ -234,50 +241,36 @@ struct GNUNET_CADET_TunnelKeyExchangeMessage | |||
234 | */ | 241 | */ |
235 | struct GNUNET_CRYPTO_EcdhePublicKey ratchet_key; | 242 | struct GNUNET_CRYPTO_EcdhePublicKey ratchet_key; |
236 | 243 | ||
237 | #ifdef NEW_CADET | ||
238 | /** | ||
239 | * Proof that sender could compute the 3-DH, in lieu of a signature. | ||
240 | */ | ||
241 | struct GNUNET_HashCode triple_dh_proof; | ||
242 | #endif | ||
243 | }; | 244 | }; |
244 | 245 | ||
245 | 246 | ||
246 | /** | 247 | /** |
247 | * Axolotl tunnel message. | 248 | * Message for a Key eXchange for a tunnel, with authentication. |
249 | * Used as a response to the initial KX as well as for rekeying. | ||
248 | */ | 250 | */ |
249 | struct GNUNET_CADET_TunnelEncryptedMessage | 251 | struct GNUNET_CADET_TunnelKeyExchangeAuthMessage |
250 | { | 252 | { |
251 | /** | ||
252 | * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED | ||
253 | */ | ||
254 | struct GNUNET_MessageHeader header; | ||
255 | 253 | ||
256 | #if NEW_CADET | ||
257 | /** | 254 | /** |
258 | * Reserved, for alignment. | 255 | * Message header with key material. |
259 | */ | 256 | */ |
260 | uint32_t reserved GNUNET_PACKED; | 257 | struct GNUNET_CADET_TunnelKeyExchangeMessage kx; |
261 | #else | ||
262 | /** | ||
263 | * Maximum packet ID authorized. | ||
264 | */ | ||
265 | struct CadetEncryptedMessageIdentifier cemi; | ||
266 | #endif | ||
267 | 258 | ||
268 | /** | 259 | /** |
269 | * ID of the connection. | 260 | * KDF-proof that sender could compute the 3-DH, used in lieu of a |
261 | * signature or payload data. | ||
270 | */ | 262 | */ |
271 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | 263 | struct GNUNET_HashCode auth; |
264 | |||
265 | }; | ||
272 | 266 | ||
273 | /** | ||
274 | * MAC of the encrypted message, used to verify message integrity. | ||
275 | * Everything after this value will be encrypted with the header key | ||
276 | * and authenticated. | ||
277 | */ | ||
278 | struct GNUNET_ShortHashCode hmac; | ||
279 | 267 | ||
280 | /**************** AX_HEADER start ****************/ | 268 | /** |
269 | * Encrypted axolotl header with numbers that identify which | ||
270 | * keys in which ratchet are to be used to decrypt the body. | ||
271 | */ | ||
272 | struct GNUNET_CADET_AxHeader | ||
273 | { | ||
281 | 274 | ||
282 | /** | 275 | /** |
283 | * Number of messages sent with the current ratchet key. | 276 | * Number of messages sent with the current ratchet key. |
@@ -294,68 +287,47 @@ struct GNUNET_CADET_TunnelEncryptedMessage | |||
294 | */ | 287 | */ |
295 | struct GNUNET_CRYPTO_EcdhePublicKey DHRs; | 288 | struct GNUNET_CRYPTO_EcdhePublicKey DHRs; |
296 | 289 | ||
297 | /**************** AX_HEADER end ****************/ | ||
298 | |||
299 | /** | ||
300 | * Encrypted content follows. | ||
301 | */ | ||
302 | }; | 290 | }; |
303 | 291 | ||
304 | 292 | ||
305 | #ifndef NEW_CADET | ||
306 | |||
307 | /** | 293 | /** |
308 | * Message to query a peer about its Flow Control status regarding a tunnel. | 294 | * Axolotl-encrypted tunnel message with application payload. |
309 | * | ||
310 | * It is NOT yet clear if we need this. | ||
311 | */ | 295 | */ |
312 | struct GNUNET_CADET_ConnectionHopByHopPollMessage | 296 | struct GNUNET_CADET_TunnelEncryptedMessage |
313 | { | 297 | { |
314 | /** | 298 | /** |
315 | * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL | 299 | * Type: #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED |
316 | */ | 300 | */ |
317 | struct GNUNET_MessageHeader header; | 301 | struct GNUNET_MessageHeader header; |
318 | 302 | ||
319 | /** | 303 | /** |
320 | * Last packet sent. | 304 | * Reserved, for alignment. |
321 | */ | 305 | */ |
322 | struct CadetEncryptedMessageIdentifier cemi; | 306 | uint32_t reserved GNUNET_PACKED; |
323 | 307 | ||
324 | /** | 308 | /** |
325 | * ID of the connection. | 309 | * ID of the connection. |
326 | */ | 310 | */ |
327 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | 311 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; |
328 | 312 | ||
329 | }; | ||
330 | |||
331 | |||
332 | /** | ||
333 | * Message to acknowledge cadet encrypted traffic, used for | ||
334 | * flow-control on a hop-by-hop basis on the connection-level. Note | ||
335 | * that we do use the @e cemi from the tunnel layer as the connection | ||
336 | * layer's header is included/shared with the tunnel layer messages, | ||
337 | * and we only do flow control for the payload. | ||
338 | */ | ||
339 | struct GNUNET_CADET_ConnectionEncryptedAckMessage | ||
340 | { | ||
341 | /** | 313 | /** |
342 | * Type: #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK | 314 | * MAC of the encrypted message, used to verify message integrity. |
315 | * Everything after this value will be encrypted with the header key | ||
316 | * and authenticated. | ||
343 | */ | 317 | */ |
344 | struct GNUNET_MessageHeader header; | 318 | struct GNUNET_ShortHashCode hmac; |
345 | 319 | ||
346 | /** | 320 | /** |
347 | * Maximum packet ID authorized. | 321 | * Axolotl-header that specifies which keys to use in which ratchet |
322 | * to decrypt the body that follows. | ||
348 | */ | 323 | */ |
349 | struct CadetEncryptedMessageIdentifier cemi_max; | 324 | struct GNUNET_CADET_AxHeader ax_header; |
350 | 325 | ||
351 | /** | 326 | /** |
352 | * ID of the connection. | 327 | * Encrypted content follows. |
353 | */ | 328 | */ |
354 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
355 | }; | 329 | }; |
356 | 330 | ||
357 | #endif | ||
358 | |||
359 | 331 | ||
360 | /******************************************************************************/ | 332 | /******************************************************************************/ |
361 | /******************************* CHANNEL ***********************************/ | 333 | /******************************* CHANNEL ***********************************/ |
@@ -378,9 +350,9 @@ struct GNUNET_CADET_ChannelOpenMessage | |||
378 | uint32_t opt GNUNET_PACKED; | 350 | uint32_t opt GNUNET_PACKED; |
379 | 351 | ||
380 | /** | 352 | /** |
381 | * Destination port. | 353 | * Hash of destination port and listener. |
382 | */ | 354 | */ |
383 | struct GNUNET_HashCode port; | 355 | struct GNUNET_HashCode h_port; |
384 | 356 | ||
385 | /** | 357 | /** |
386 | * ID of the channel within the tunnel. | 358 | * ID of the channel within the tunnel. |
@@ -390,93 +362,56 @@ struct GNUNET_CADET_ChannelOpenMessage | |||
390 | 362 | ||
391 | 363 | ||
392 | /** | 364 | /** |
393 | * Message to manage a Channel | 365 | * Message to acknowledge opening a channel of type |
394 | * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK, | 366 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK. |
395 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY). | ||
396 | */ | 367 | */ |
397 | struct GNUNET_CADET_ChannelManageMessage | 368 | struct GNUNET_CADET_ChannelOpenAckMessage |
398 | { | 369 | { |
399 | /** | 370 | /** |
400 | * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK or | 371 | * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK |
401 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY | ||
402 | */ | 372 | */ |
403 | struct GNUNET_MessageHeader header; | 373 | struct GNUNET_MessageHeader header; |
404 | 374 | ||
405 | #ifdef NEW_CADET | ||
406 | /** | 375 | /** |
407 | * For alignment. | 376 | * For alignment. |
408 | */ | 377 | */ |
409 | uint32_t reserved GNUNET_PACKED; | 378 | uint32_t reserved GNUNET_PACKED; |
410 | #endif | ||
411 | 379 | ||
412 | /** | 380 | /** |
413 | * ID of the channel | 381 | * ID of the channel |
414 | */ | 382 | */ |
415 | struct GNUNET_CADET_ChannelTunnelNumber ctn; | 383 | struct GNUNET_CADET_ChannelTunnelNumber ctn; |
416 | }; | ||
417 | |||
418 | |||
419 | #ifndef NEW_CADET | ||
420 | |||
421 | /** | ||
422 | * Message for cadet data traffic. | ||
423 | */ | ||
424 | struct GNUNET_CADET_ChannelAppDataMessage | ||
425 | { | ||
426 | /** | ||
427 | * Type: #GNUNET_MESSAGE_TYPE_CADET_UNICAST, | ||
428 | * #GNUNET_MESSAGE_TYPE_CADET_TO_ORIGIN | ||
429 | */ | ||
430 | struct GNUNET_MessageHeader header; | ||
431 | |||
432 | /** | ||
433 | * Unique ID of the payload message | ||
434 | */ | ||
435 | /* NEW: struct ChannelMessageIdentifier */ | ||
436 | uint32_t mid GNUNET_PACKED; | ||
437 | 384 | ||
438 | /** | 385 | /** |
439 | * ID of the channel | 386 | * Port number of the channel, used to prove to the |
440 | */ | 387 | * initiator that the receiver knows the port. |
441 | struct GNUNET_CADET_ChannelTunnelNumber ctn; | ||
442 | |||
443 | /** | ||
444 | * Payload follows | ||
445 | */ | 388 | */ |
389 | struct GNUNET_HashCode port; | ||
446 | }; | 390 | }; |
447 | 391 | ||
448 | 392 | ||
449 | /** | 393 | /** |
450 | * Message to acknowledge end-to-end data. | 394 | * Message to destroy a channel of type |
395 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY. | ||
451 | */ | 396 | */ |
452 | struct GNUNET_CADET_ChannelDataAckMessage | 397 | struct GNUNET_CADET_ChannelDestroyMessage |
453 | { | 398 | { |
454 | /** | 399 | /** |
455 | * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK | 400 | * Type: #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY |
456 | */ | 401 | */ |
457 | struct GNUNET_MessageHeader header; | 402 | struct GNUNET_MessageHeader header; |
458 | 403 | ||
459 | /** | 404 | /** |
460 | * ID of the channel | 405 | * For alignment. |
461 | */ | ||
462 | struct GNUNET_CADET_ChannelTunnelNumber ctn; | ||
463 | |||
464 | /** | ||
465 | * Bitfield of already-received newer messages | ||
466 | * pid + 1 @ LSB | ||
467 | * pid + 64 @ MSB | ||
468 | */ | 406 | */ |
469 | uint64_t futures GNUNET_PACKED; | 407 | uint32_t reserved GNUNET_PACKED; |
470 | 408 | ||
471 | /** | 409 | /** |
472 | * Last message ID received. | 410 | * ID of the channel |
473 | */ | 411 | */ |
474 | /* NEW: struct ChannelMessageIdentifier */ | 412 | struct GNUNET_CADET_ChannelTunnelNumber ctn; |
475 | uint32_t mid GNUNET_PACKED; | ||
476 | }; | 413 | }; |
477 | 414 | ||
478 | #else | ||
479 | |||
480 | 415 | ||
481 | /** | 416 | /** |
482 | * Number used to uniquely identify messages in a CADET Channel. | 417 | * Number used to uniquely identify messages in a CADET Channel. |
@@ -532,21 +467,21 @@ struct GNUNET_CADET_ChannelDataAckMessage | |||
532 | struct GNUNET_CADET_ChannelTunnelNumber ctn; | 467 | struct GNUNET_CADET_ChannelTunnelNumber ctn; |
533 | 468 | ||
534 | /** | 469 | /** |
535 | * Bitfield of already-received messages past @e mid. | 470 | * Bitfield of already-received newer messages. Note that bit 0 |
536 | * pid + 1 @ LSB | 471 | * corresponds to @e mid + 1. |
537 | * pid + 64 @ MSB | 472 | * |
473 | * pid + 0 @ LSB | ||
474 | * pid + 63 @ MSB | ||
538 | */ | 475 | */ |
539 | uint64_t futures GNUNET_PACKED; | 476 | uint64_t futures GNUNET_PACKED; |
540 | 477 | ||
541 | /** | 478 | /** |
542 | * Last message ID received. | 479 | * Next message ID expected. |
543 | */ | 480 | */ |
544 | struct ChannelMessageIdentifier mid; | 481 | struct ChannelMessageIdentifier mid; |
545 | }; | 482 | }; |
546 | 483 | ||
547 | 484 | ||
548 | #endif | ||
549 | |||
550 | GNUNET_NETWORK_STRUCT_END | 485 | GNUNET_NETWORK_STRUCT_END |
551 | 486 | ||
552 | #if 0 /* keep Emacsens' auto-indent happy */ | 487 | #if 0 /* keep Emacsens' auto-indent happy */ |
diff --git a/src/cadet/cadet_test_lib.c b/src/cadet/cadet_test_lib.c index 9a70dad49..1df6bff0d 100644 --- a/src/cadet/cadet_test_lib.c +++ b/src/cadet/cadet_test_lib.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2012 GNUnet e.V. | 3 | Copyright (C) 2012, 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -27,6 +27,7 @@ | |||
27 | #include "cadet_test_lib.h" | 27 | #include "cadet_test_lib.h" |
28 | #include "gnunet_cadet_service.h" | 28 | #include "gnunet_cadet_service.h" |
29 | 29 | ||
30 | |||
30 | /** | 31 | /** |
31 | * Test context for a CADET Test. | 32 | * Test context for a CADET Test. |
32 | */ | 33 | */ |
@@ -40,7 +41,7 @@ struct GNUNET_CADET_TEST_Context | |||
40 | /** | 41 | /** |
41 | * Array of handles to the CADET for each peer. | 42 | * Array of handles to the CADET for each peer. |
42 | */ | 43 | */ |
43 | struct GNUNET_CADET_Handle **cadetes; | 44 | struct GNUNET_CADET_Handle **cadets; |
44 | 45 | ||
45 | /** | 46 | /** |
46 | * Operation associated with the connection to the CADET. | 47 | * Operation associated with the connection to the CADET. |
@@ -48,6 +49,11 @@ struct GNUNET_CADET_TEST_Context | |||
48 | struct GNUNET_TESTBED_Operation **ops; | 49 | struct GNUNET_TESTBED_Operation **ops; |
49 | 50 | ||
50 | /** | 51 | /** |
52 | * Number of peers running, size of the arrays above. | ||
53 | */ | ||
54 | unsigned int num_peers; | ||
55 | |||
56 | /** | ||
51 | * Main function of the test to run once all CADETs are available. | 57 | * Main function of the test to run once all CADETs are available. |
52 | */ | 58 | */ |
53 | GNUNET_CADET_TEST_AppMain app_main; | 59 | GNUNET_CADET_TEST_AppMain app_main; |
@@ -58,30 +64,35 @@ struct GNUNET_CADET_TEST_Context | |||
58 | void *app_main_cls; | 64 | void *app_main_cls; |
59 | 65 | ||
60 | /** | 66 | /** |
61 | * Number of peers running, size of the arrays above. | 67 | * Handler for incoming tunnels. |
62 | */ | 68 | */ |
63 | unsigned int num_peers; | 69 | GNUNET_CADET_ConnectEventHandler connects; |
64 | 70 | ||
65 | /** | 71 | /** |
66 | * Handler for incoming tunnels. | 72 | * Function called when the transmit window size changes. |
67 | */ | 73 | */ |
68 | GNUNET_CADET_InboundChannelNotificationHandler *new_channel; | 74 | GNUNET_CADET_WindowSizeEventHandler window_changes; |
69 | 75 | ||
70 | /** | 76 | /** |
71 | * Cleaner for destroyed incoming tunnels. | 77 | * Cleaner for destroyed incoming tunnels. |
72 | */ | 78 | */ |
73 | GNUNET_CADET_ChannelEndHandler *cleaner; | 79 | GNUNET_CADET_DisconnectEventHandler disconnects; |
74 | 80 | ||
75 | /** | 81 | /** |
76 | * Message handlers. | 82 | * Message handlers. |
77 | */ | 83 | */ |
78 | struct GNUNET_CADET_MessageHandler* handlers; | 84 | struct GNUNET_MQ_MessageHandler *handlers; |
79 | 85 | ||
80 | /** | 86 | /** |
81 | * Application ports. | 87 | * Application ports. |
82 | */ | 88 | */ |
83 | const struct GNUNET_HashCode **ports; | 89 | const struct GNUNET_HashCode **ports; |
84 | 90 | ||
91 | /** | ||
92 | * Number of ports in #ports. | ||
93 | */ | ||
94 | unsigned int port_count; | ||
95 | |||
85 | }; | 96 | }; |
86 | 97 | ||
87 | 98 | ||
@@ -94,6 +105,11 @@ struct GNUNET_CADET_TEST_AdapterContext | |||
94 | * Peer number for the particular peer. | 105 | * Peer number for the particular peer. |
95 | */ | 106 | */ |
96 | unsigned int peer; | 107 | unsigned int peer; |
108 | |||
109 | /** | ||
110 | * Port handlers for open ports. | ||
111 | */ | ||
112 | struct GNUNET_CADET_Port **ports; | ||
97 | 113 | ||
98 | /** | 114 | /** |
99 | * General context. | 115 | * General context. |
@@ -114,26 +130,28 @@ struct GNUNET_CADET_TEST_AdapterContext | |||
114 | */ | 130 | */ |
115 | static void * | 131 | static void * |
116 | cadet_connect_adapter (void *cls, | 132 | cadet_connect_adapter (void *cls, |
117 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 133 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
118 | { | 134 | { |
119 | struct GNUNET_CADET_TEST_AdapterContext *actx = cls; | 135 | struct GNUNET_CADET_TEST_AdapterContext *actx = cls; |
120 | struct GNUNET_CADET_TEST_Context *ctx = actx->ctx; | 136 | struct GNUNET_CADET_TEST_Context *ctx = actx->ctx; |
121 | struct GNUNET_CADET_Handle *h; | 137 | struct GNUNET_CADET_Handle *h; |
138 | unsigned int i; | ||
122 | 139 | ||
123 | h = GNUNET_CADET_connect (cfg, | 140 | h = GNUNET_CADET_connect (cfg); |
124 | (void *) (long) actx->peer, | ||
125 | ctx->cleaner, | ||
126 | ctx->handlers); | ||
127 | if (NULL == ctx->ports) | 141 | if (NULL == ctx->ports) |
128 | return h; | 142 | return h; |
129 | 143 | ||
130 | for (int i = 0; NULL != ctx->ports[i]; i++) | 144 | actx->ports = GNUNET_new_array (ctx->port_count, struct GNUNET_CADET_Port *); |
145 | for (i = 0; i < ctx->port_count; i++) | ||
131 | { | 146 | { |
132 | (void ) GNUNET_CADET_open_port (h, ctx->ports[i], | 147 | actx->ports[i] = GNUNET_CADET_open_port (h, |
133 | ctx->new_channel, | 148 | ctx->ports[i], |
134 | (void *) (long) actx->peer); | 149 | ctx->connects, |
150 | (void *) (long) actx->peer, | ||
151 | ctx->window_changes, | ||
152 | ctx->disconnects, | ||
153 | ctx->handlers); | ||
135 | } | 154 | } |
136 | |||
137 | return h; | 155 | return h; |
138 | } | 156 | } |
139 | 157 | ||
@@ -152,6 +170,15 @@ cadet_disconnect_adapter (void *cls, | |||
152 | struct GNUNET_CADET_Handle *cadet = op_result; | 170 | struct GNUNET_CADET_Handle *cadet = op_result; |
153 | struct GNUNET_CADET_TEST_AdapterContext *actx = cls; | 171 | struct GNUNET_CADET_TEST_AdapterContext *actx = cls; |
154 | 172 | ||
173 | if (NULL != actx->ports) | ||
174 | { | ||
175 | for (int i = 0; i < actx->ctx->port_count; i++) | ||
176 | { | ||
177 | GNUNET_CADET_close_port (actx->ports[i]); | ||
178 | actx->ports[i] = NULL; | ||
179 | } | ||
180 | GNUNET_free (actx->ports); | ||
181 | } | ||
155 | GNUNET_free (actx); | 182 | GNUNET_free (actx); |
156 | GNUNET_CADET_disconnect (cadet); | 183 | GNUNET_CADET_disconnect (cadet); |
157 | } | 184 | } |
@@ -186,18 +213,18 @@ cadet_connect_cb (void *cls, | |||
186 | for (i = 0; i < ctx->num_peers; i++) | 213 | for (i = 0; i < ctx->num_peers; i++) |
187 | if (op == ctx->ops[i]) | 214 | if (op == ctx->ops[i]) |
188 | { | 215 | { |
189 | ctx->cadetes[i] = ca_result; | 216 | ctx->cadets[i] = ca_result; |
190 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...cadet %u connected\n", i); | 217 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...cadet %u connected\n", i); |
191 | } | 218 | } |
192 | for (i = 0; i < ctx->num_peers; i++) | 219 | for (i = 0; i < ctx->num_peers; i++) |
193 | if (NULL == ctx->cadetes[i]) | 220 | if (NULL == ctx->cadets[i]) |
194 | return; /* still some CADET connections missing */ | 221 | return; /* still some CADET connections missing */ |
195 | /* all CADET connections ready! */ | 222 | /* all CADET connections ready! */ |
196 | ctx->app_main (ctx->app_main_cls, | 223 | ctx->app_main (ctx->app_main_cls, |
197 | ctx, | 224 | ctx, |
198 | ctx->num_peers, | 225 | ctx->num_peers, |
199 | ctx->peers, | 226 | ctx->peers, |
200 | ctx->cadetes); | 227 | ctx->cadets); |
201 | } | 228 | } |
202 | 229 | ||
203 | 230 | ||
@@ -213,7 +240,7 @@ GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx) | |||
213 | ctx->ops[i] = NULL; | 240 | ctx->ops[i] = NULL; |
214 | } | 241 | } |
215 | GNUNET_free (ctx->ops); | 242 | GNUNET_free (ctx->ops); |
216 | GNUNET_free (ctx->cadetes); | 243 | GNUNET_free (ctx->cadets); |
217 | GNUNET_free (ctx); | 244 | GNUNET_free (ctx); |
218 | GNUNET_SCHEDULER_shutdown (); | 245 | GNUNET_SCHEDULER_shutdown (); |
219 | } | 246 | } |
@@ -243,12 +270,23 @@ cadet_test_run (void *cls, | |||
243 | struct GNUNET_CADET_TEST_Context *ctx = cls; | 270 | struct GNUNET_CADET_TEST_Context *ctx = cls; |
244 | unsigned int i; | 271 | unsigned int i; |
245 | 272 | ||
273 | if (0 != links_failed) | ||
274 | { | ||
275 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Some links failed (%u), ending\n", | ||
276 | links_failed); | ||
277 | exit (2); | ||
278 | } | ||
279 | |||
246 | if (num_peers != ctx->num_peers) | 280 | if (num_peers != ctx->num_peers) |
247 | { | 281 | { |
248 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n", | 282 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n", |
249 | num_peers, ctx->num_peers); | 283 | num_peers, ctx->num_peers); |
250 | exit (1); | 284 | exit (1); |
251 | } | 285 | } |
286 | |||
287 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
288 | "Testbed up, %u peers and %u links\n", | ||
289 | num_peers, links_succeeded); | ||
252 | ctx->peers = peers; | 290 | ctx->peers = peers; |
253 | for (i = 0; i < num_peers; i++) | 291 | for (i = 0; i < num_peers; i++) |
254 | { | 292 | { |
@@ -270,31 +308,52 @@ cadet_test_run (void *cls, | |||
270 | } | 308 | } |
271 | 309 | ||
272 | 310 | ||
311 | /** | ||
312 | * Run a test using the given name, configuration file and number of peers. | ||
313 | * All cadet callbacks will receive the peer number (long) as the closure. | ||
314 | * | ||
315 | * @param testname Name of the test (for logging). | ||
316 | * @param cfgfile Name of the configuration file. | ||
317 | * @param num_peers Number of peers to start. | ||
318 | * @param tmain Main function to run once the testbed is ready. | ||
319 | * @param tmain_cls Closure for @a tmain. | ||
320 | * @param connects Handler for incoming channels. | ||
321 | * @param window_changes Handler for the window size change notification. | ||
322 | * @param disconnects Cleaner for destroyed incoming channels. | ||
323 | * @param handlers Message handlers. | ||
324 | * @param ports Ports the peers offer, NULL-terminated. | ||
325 | */ | ||
273 | void | 326 | void |
274 | GNUNET_CADET_TEST_run (const char *testname, | 327 | GNUNET_CADET_TEST_ruN (const char *testname, |
275 | const char *cfgname, | 328 | const char *cfgfile, |
276 | unsigned int num_peers, | 329 | unsigned int num_peers, |
277 | GNUNET_CADET_TEST_AppMain tmain, | 330 | GNUNET_CADET_TEST_AppMain tmain, |
278 | void *tmain_cls, | 331 | void *tmain_cls, |
279 | GNUNET_CADET_InboundChannelNotificationHandler new_channel, | 332 | GNUNET_CADET_ConnectEventHandler connects, |
280 | GNUNET_CADET_ChannelEndHandler cleaner, | 333 | GNUNET_CADET_WindowSizeEventHandler window_changes, |
281 | struct GNUNET_CADET_MessageHandler* handlers, | 334 | GNUNET_CADET_DisconnectEventHandler disconnects, |
282 | const struct GNUNET_HashCode **ports) | 335 | struct GNUNET_MQ_MessageHandler *handlers, |
336 | const struct GNUNET_HashCode **ports) | ||
283 | { | 337 | { |
284 | struct GNUNET_CADET_TEST_Context *ctx; | 338 | struct GNUNET_CADET_TEST_Context *ctx; |
285 | 339 | ||
286 | ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context); | 340 | ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context); |
287 | ctx->num_peers = num_peers; | 341 | ctx->num_peers = num_peers; |
288 | ctx->ops = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *)); | 342 | ctx->ops = GNUNET_new_array (num_peers, struct GNUNET_TESTBED_Operation *); |
289 | ctx->cadetes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_CADET_Handle *)); | 343 | ctx->cadets = GNUNET_new_array (num_peers, struct GNUNET_CADET_Handle *); |
290 | ctx->app_main = tmain; | 344 | ctx->app_main = tmain; |
291 | ctx->app_main_cls = tmain_cls; | 345 | ctx->app_main_cls = tmain_cls; |
292 | ctx->new_channel = new_channel; | 346 | ctx->connects = connects; |
293 | ctx->cleaner = cleaner; | 347 | ctx->window_changes = window_changes; |
294 | ctx->handlers = handlers; | 348 | ctx->disconnects = disconnects; |
349 | ctx->handlers = GNUNET_MQ_copy_handlers (handlers); | ||
295 | ctx->ports = ports; | 350 | ctx->ports = ports; |
351 | ctx->port_count = 0; | ||
352 | while (NULL != ctx->ports[ctx->port_count]) | ||
353 | ctx->port_count++; | ||
354 | |||
296 | GNUNET_TESTBED_test_run (testname, | 355 | GNUNET_TESTBED_test_run (testname, |
297 | cfgname, | 356 | cfgfile, |
298 | num_peers, | 357 | num_peers, |
299 | 0LL, NULL, NULL, | 358 | 0LL, NULL, NULL, |
300 | &cadet_test_run, ctx); | 359 | &cadet_test_run, ctx); |
diff --git a/src/cadet/cadet_test_lib.h b/src/cadet/cadet_test_lib.h index 464977d42..4b3a6b18d 100644 --- a/src/cadet/cadet_test_lib.h +++ b/src/cadet/cadet_test_lib.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2012 GNUnet e.V. | 3 | Copyright (C) 2012,2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -49,41 +49,41 @@ struct GNUNET_CADET_TEST_Context; | |||
49 | * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. | 49 | * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. |
50 | * @param num_peers Number of peers that are running. | 50 | * @param num_peers Number of peers that are running. |
51 | * @param peers Array of peers. | 51 | * @param peers Array of peers. |
52 | * @param cadetes Handle to each of the CADETs of the peers. | 52 | * @param cadets Handle to each of the CADETs of the peers. |
53 | */ | 53 | */ |
54 | typedef void (*GNUNET_CADET_TEST_AppMain) (void *cls, | 54 | typedef void (*GNUNET_CADET_TEST_AppMain) (void *cls, |
55 | struct GNUNET_CADET_TEST_Context *ctx, | 55 | struct GNUNET_CADET_TEST_Context *ctx, |
56 | unsigned int num_peers, | 56 | unsigned int num_peers, |
57 | struct GNUNET_TESTBED_Peer **peers, | 57 | struct GNUNET_TESTBED_Peer **peers, |
58 | struct GNUNET_CADET_Handle **cadetes); | 58 | struct GNUNET_CADET_Handle **cadets); |
59 | 59 | ||
60 | 60 | ||
61 | /** | 61 | /** |
62 | * Run a test using the given name, configuration file and number of | 62 | * Run a test using the given name, configuration file and number of peers. |
63 | * peers. | 63 | * All cadet callbacks will receive the peer number (long) as the closure. |
64 | * All cadet callbacks will receive the peer number as the closure. | ||
65 | * | 64 | * |
66 | * @param testname Name of the test (for logging). | 65 | * @param testname Name of the test (for logging). |
67 | * @param cfgname Name of the configuration file. | 66 | * @param cfgfile Name of the configuration file. |
68 | * @param num_peers Number of peers to start. | 67 | * @param num_peers Number of peers to start. |
69 | * @param tmain Main function to run once the testbed is ready. | 68 | * @param tmain Main function to run once the testbed is ready. |
70 | * @param tmain_cls Closure for 'tmain'. | 69 | * @param tmain_cls Closure for @a tmain. |
71 | * @param new_channel Handler for incoming tunnels. | 70 | * @param connects Handler for incoming channels. |
72 | * @param cleaner Cleaner for destroyed incoming tunnels. | 71 | * @param window_changes Handler for the window size change notification. |
72 | * @param disconnects Cleaner for destroyed incoming channels. | ||
73 | * @param handlers Message handlers. | 73 | * @param handlers Message handlers. |
74 | * @param ports Ports the peers offer, NULL-terminated. | 74 | * @param ports Ports the peers offer, NULL-terminated. |
75 | */ | 75 | */ |
76 | void | 76 | void |
77 | GNUNET_CADET_TEST_run (const char *testname, | 77 | GNUNET_CADET_TEST_ruN (const char *testname, |
78 | const char *cfgname, | 78 | const char *cfgfile, |
79 | unsigned int num_peers, | 79 | unsigned int num_peers, |
80 | GNUNET_CADET_TEST_AppMain tmain, | 80 | GNUNET_CADET_TEST_AppMain tmain, |
81 | void *tmain_cls, | 81 | void *tmain_cls, |
82 | GNUNET_CADET_InboundChannelNotificationHandler new_channel, | 82 | GNUNET_CADET_ConnectEventHandler connects, |
83 | GNUNET_CADET_ChannelEndHandler cleaner, | 83 | GNUNET_CADET_WindowSizeEventHandler window_changes, |
84 | struct GNUNET_CADET_MessageHandler* handlers, | 84 | GNUNET_CADET_DisconnectEventHandler disconnects, |
85 | const struct GNUNET_HashCode **ports); | 85 | struct GNUNET_MQ_MessageHandler *handlers, |
86 | 86 | const struct GNUNET_HashCode **ports); | |
87 | 87 | ||
88 | /** | 88 | /** |
89 | * Clean up the testbed. | 89 | * Clean up the testbed. |
diff --git a/src/cadet/desirability_table.c b/src/cadet/desirability_table.c new file mode 100644 index 000000000..21ec3e388 --- /dev/null +++ b/src/cadet/desirability_table.c | |||
@@ -0,0 +1,35 @@ | |||
1 | /* This file is in the public domain. */ | ||
2 | |||
3 | /** | ||
4 | * @brief Program to simulate results from #GCP_get_desirability_of_path() | ||
5 | * for various plausible inputs. | ||
6 | * @author Christian Grothoff | ||
7 | */ | ||
8 | #include <stdio.h> | ||
9 | |||
10 | int | ||
11 | main () | ||
12 | { | ||
13 | for (unsigned int num_alts=1; num_alts<10; num_alts++) | ||
14 | for (unsigned int off=0; off<10; off++) | ||
15 | for (double delta=-(int) off;delta<=5;delta += 0.25) | ||
16 | { | ||
17 | double weight_alts; | ||
18 | |||
19 | if (delta <= - 1.0) | ||
20 | weight_alts = - 1.0 * num_alts / delta; /* discount alternative paths */ | ||
21 | else if (delta >= 1.0) | ||
22 | weight_alts = 1.0 * num_alts * delta; /* overcount alternative paths */ | ||
23 | else | ||
24 | weight_alts = 1.0 * num_alts; /* count alternative paths normally */ | ||
25 | |||
26 | fprintf (stderr, | ||
27 | "Paths: %u Offset: %u Delta: %5.2f SCORE: %f\n", | ||
28 | num_alts, | ||
29 | off, | ||
30 | delta, | ||
31 | ((off + 1.0) / (weight_alts * weight_alts))); | ||
32 | } | ||
33 | |||
34 | |||
35 | } | ||
diff --git a/src/cadet/gnunet-cadet-profiler.c b/src/cadet/gnunet-cadet-profiler.c index d688dc60b..15da05b6d 100644 --- a/src/cadet/gnunet-cadet-profiler.c +++ b/src/cadet/gnunet-cadet-profiler.c | |||
@@ -778,7 +778,9 @@ pong_handler (void *cls, struct GNUNET_CADET_Channel *channel, | |||
778 | latency = GNUNET_TIME_absolute_get_duration (send_time); | 778 | latency = GNUNET_TIME_absolute_get_duration (send_time); |
779 | r = ntohl (msg->round_number); | 779 | r = ntohl (msg->round_number); |
780 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <- %u (%u) latency: %s\n", | 780 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <- %u (%u) latency: %s\n", |
781 | get_index (peer), get_index (peer->dest), ntohl (msg->counter), | 781 | get_index (peer), |
782 | get_index (peer->dest), | ||
783 | (uint32_t) ntohl (msg->counter), | ||
782 | GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO)); | 784 | GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO)); |
783 | 785 | ||
784 | /* Online variance calculation */ | 786 | /* Online variance calculation */ |
diff --git a/src/cadet/gnunet-cadet.c b/src/cadet/gnunet-cadet.c index 80010ec54..675e7faf0 100644 --- a/src/cadet/gnunet-cadet.c +++ b/src/cadet/gnunet-cadet.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2012 GNUnet e.V. | 3 | Copyright (C) 2012, 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -22,6 +22,7 @@ | |||
22 | * @file cadet/gnunet-cadet.c | 22 | * @file cadet/gnunet-cadet.c |
23 | * @brief Print information about cadet tunnels and peers. | 23 | * @brief Print information about cadet tunnels and peers. |
24 | * @author Bartlomiej Polot | 24 | * @author Bartlomiej Polot |
25 | * @author Christian Grothoff | ||
25 | */ | 26 | */ |
26 | #include "platform.h" | 27 | #include "platform.h" |
27 | #include "gnunet_util_lib.h" | 28 | #include "gnunet_util_lib.h" |
@@ -30,11 +31,6 @@ | |||
30 | 31 | ||
31 | 32 | ||
32 | /** | 33 | /** |
33 | * Option -m. | ||
34 | */ | ||
35 | static int monitor_mode; | ||
36 | |||
37 | /** | ||
38 | * Option -P. | 34 | * Option -P. |
39 | */ | 35 | */ |
40 | static int request_peers; | 36 | static int request_peers; |
@@ -100,11 +96,6 @@ static char *target_id; | |||
100 | static char *target_port = "default"; | 96 | static char *target_port = "default"; |
101 | 97 | ||
102 | /** | 98 | /** |
103 | * Data pending in netcat mode. | ||
104 | */ | ||
105 | static size_t data_size; | ||
106 | |||
107 | /** | ||
108 | * Cadet handle. | 99 | * Cadet handle. |
109 | */ | 100 | */ |
110 | static struct GNUNET_CADET_Handle *mh; | 101 | static struct GNUNET_CADET_Handle *mh; |
@@ -115,11 +106,6 @@ static struct GNUNET_CADET_Handle *mh; | |||
115 | static struct GNUNET_CADET_Channel *ch; | 106 | static struct GNUNET_CADET_Channel *ch; |
116 | 107 | ||
117 | /** | 108 | /** |
118 | * Transmit handle. | ||
119 | */ | ||
120 | static struct GNUNET_CADET_TransmitHandle *th; | ||
121 | |||
122 | /** | ||
123 | * HashCode of the given port string | 109 | * HashCode of the given port string |
124 | */ | 110 | */ |
125 | static struct GNUNET_HashCode porthash; | 111 | static struct GNUNET_HashCode porthash; |
@@ -130,11 +116,6 @@ static struct GNUNET_HashCode porthash; | |||
130 | struct GNUNET_CADET_Port *lp; | 116 | struct GNUNET_CADET_Port *lp; |
131 | 117 | ||
132 | /** | 118 | /** |
133 | * Shutdown task handle. | ||
134 | */ | ||
135 | static struct GNUNET_SCHEDULER_Task *sd; | ||
136 | |||
137 | /** | ||
138 | * Task for reading from stdin. | 119 | * Task for reading from stdin. |
139 | */ | 120 | */ |
140 | static struct GNUNET_SCHEDULER_Task *rd_task; | 121 | static struct GNUNET_SCHEDULER_Task *rd_task; |
@@ -145,6 +126,9 @@ static struct GNUNET_SCHEDULER_Task *rd_task; | |||
145 | static struct GNUNET_SCHEDULER_Task *job; | 126 | static struct GNUNET_SCHEDULER_Task *job; |
146 | 127 | ||
147 | 128 | ||
129 | /** | ||
130 | * Wait for input on STDIO and send it out over the #ch. | ||
131 | */ | ||
148 | static void | 132 | static void |
149 | listen_stdio (void); | 133 | listen_stdio (void); |
150 | 134 | ||
@@ -214,22 +198,11 @@ shutdown_task (void *cls) | |||
214 | { | 198 | { |
215 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 199 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
216 | "Shutdown\n"); | 200 | "Shutdown\n"); |
217 | if (NULL != th) | ||
218 | { | ||
219 | GNUNET_CADET_notify_transmit_ready_cancel (th); | ||
220 | th = NULL; | ||
221 | } | ||
222 | if (NULL != ch) | 201 | if (NULL != ch) |
223 | { | 202 | { |
224 | GNUNET_CADET_channel_destroy (ch); | 203 | GNUNET_CADET_channel_destroy (ch); |
225 | ch = NULL; | 204 | ch = NULL; |
226 | } | 205 | } |
227 | else if (NULL != target_id) { | ||
228 | // FIXME: would be nicer to have proper NACK support from cadet_api | ||
229 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
230 | "Connection refused to %s\n", | ||
231 | target_id); | ||
232 | } | ||
233 | if (NULL != mh) | 206 | if (NULL != mh) |
234 | { | 207 | { |
235 | GNUNET_CADET_disconnect (mh); | 208 | GNUNET_CADET_disconnect (mh); |
@@ -254,42 +227,38 @@ shutdown_task (void *cls) | |||
254 | 227 | ||
255 | 228 | ||
256 | /** | 229 | /** |
257 | * Function called to notify a client about the connection | 230 | * Task run in stdio mode, after some data is available at stdin. |
258 | * begin ready to queue more data. "buf" will be | ||
259 | * NULL and "size" zero if the connection was closed for | ||
260 | * writing in the meantime. | ||
261 | * | ||
262 | * FIXME | ||
263 | * | 231 | * |
264 | * @param cls closure | 232 | * @param cls Closure (unused). |
265 | * @param size number of bytes available in buf | ||
266 | * @param buf where the callee should write the message | ||
267 | * @return number of bytes written to buf | ||
268 | */ | 233 | */ |
269 | static size_t | 234 | static void |
270 | data_ready (void *cls, size_t size, void *buf) | 235 | read_stdio (void *cls) |
271 | { | 236 | { |
237 | struct GNUNET_MQ_Envelope *env; | ||
272 | struct GNUNET_MessageHeader *msg; | 238 | struct GNUNET_MessageHeader *msg; |
273 | size_t total_size; | 239 | char buf[60000]; |
274 | 240 | ssize_t data_size; | |
275 | th = NULL; | ||
276 | 241 | ||
277 | if (NULL == buf || 0 == size) | 242 | rd_task = NULL; |
243 | data_size = read (0, | ||
244 | buf, | ||
245 | 60000); | ||
246 | if (data_size < 1) | ||
278 | { | 247 | { |
279 | GNUNET_SCHEDULER_shutdown(); | 248 | GNUNET_SCHEDULER_shutdown(); |
280 | return 0; | 249 | return; |
281 | } | 250 | } |
282 | |||
283 | total_size = data_size + sizeof (struct GNUNET_MessageHeader); | ||
284 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 251 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
285 | "sending %u bytes\n", | 252 | "Read %u bytes from stdio\n", |
286 | (unsigned int) data_size); | 253 | (unsigned int) data_size); |
287 | GNUNET_assert (size >= total_size); | 254 | env = GNUNET_MQ_msg_extra (msg, |
288 | 255 | data_size, | |
289 | msg = buf; | 256 | GNUNET_MESSAGE_TYPE_CADET_CLI); |
290 | msg->size = htons (total_size); | 257 | GNUNET_memcpy (&msg[1], |
291 | msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_CLI); | 258 | buf, |
292 | GNUNET_memcpy (&msg[1], cls, data_size); | 259 | data_size); |
260 | GNUNET_MQ_send (GNUNET_CADET_get_mq (ch), | ||
261 | env); | ||
293 | if (GNUNET_NO == echo) | 262 | if (GNUNET_NO == echo) |
294 | { | 263 | { |
295 | listen_stdio (); | 264 | listen_stdio (); |
@@ -298,53 +267,27 @@ data_ready (void *cls, size_t size, void *buf) | |||
298 | { | 267 | { |
299 | echo_time = GNUNET_TIME_absolute_get (); | 268 | echo_time = GNUNET_TIME_absolute_get (); |
300 | } | 269 | } |
301 | |||
302 | return total_size; | ||
303 | } | 270 | } |
304 | 271 | ||
305 | 272 | ||
306 | /** | 273 | /** |
307 | * Task run in stdio mode, after some data is available at stdin. | 274 | * Wait for input on STDIO and send it out over the #ch. |
308 | * | ||
309 | * @param cls Closure (unused). | ||
310 | */ | 275 | */ |
311 | static void | 276 | static void |
312 | read_stdio (void *cls) | 277 | listen_stdio () |
313 | { | ||
314 | static char buf[60000]; | ||
315 | |||
316 | data_size = read (0, buf, 60000); | ||
317 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
318 | "stdio read %u bytes\n", | ||
319 | (unsigned int) data_size); | ||
320 | if (data_size < 1) | ||
321 | { | ||
322 | GNUNET_SCHEDULER_shutdown(); | ||
323 | return; | ||
324 | } | ||
325 | GNUNET_assert (NULL == th); | ||
326 | th = GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO, | ||
327 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
328 | sizeof (struct GNUNET_MessageHeader) | ||
329 | + data_size, | ||
330 | &data_ready, buf); | ||
331 | } | ||
332 | |||
333 | |||
334 | /** | ||
335 | * Start listening to stdin | ||
336 | */ | ||
337 | static void | ||
338 | listen_stdio (void) | ||
339 | { | 278 | { |
340 | struct GNUNET_NETWORK_FDSet *rs; | 279 | struct GNUNET_NETWORK_FDSet *rs; |
341 | 280 | ||
281 | /* FIXME: why use 'rs' here, seems overly complicated... */ | ||
342 | rs = GNUNET_NETWORK_fdset_create (); | 282 | rs = GNUNET_NETWORK_fdset_create (); |
343 | GNUNET_NETWORK_fdset_set_native (rs, 0); | 283 | GNUNET_NETWORK_fdset_set_native (rs, |
284 | 0); /* STDIN */ | ||
344 | rd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | 285 | rd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, |
345 | GNUNET_TIME_UNIT_FOREVER_REL, | 286 | GNUNET_TIME_UNIT_FOREVER_REL, |
346 | rs, NULL, | 287 | rs, |
347 | &read_stdio, NULL); | 288 | NULL, |
289 | &read_stdio, | ||
290 | NULL); | ||
348 | GNUNET_NETWORK_fdset_destroy (rs); | 291 | GNUNET_NETWORK_fdset_destroy (rs); |
349 | } | 292 | } |
350 | 293 | ||
@@ -355,32 +298,17 @@ listen_stdio (void) | |||
355 | * | 298 | * |
356 | * It must NOT call #GNUNET_CADET_channel_destroy on the channel. | 299 | * It must NOT call #GNUNET_CADET_channel_destroy on the channel. |
357 | * | 300 | * |
358 | * @param cls closure (set from #GNUNET_CADET_connect) | 301 | * @param cls closure |
359 | * @param channel connection to the other end (henceforth invalid) | 302 | * @param channel connection to the other end (henceforth invalid) |
360 | * @param channel_ctx place where local state associated | ||
361 | * with the channel is stored | ||
362 | */ | 303 | */ |
363 | static void | 304 | static void |
364 | channel_ended (void *cls, | 305 | channel_ended (void *cls, |
365 | const struct GNUNET_CADET_Channel *channel, | 306 | const struct GNUNET_CADET_Channel *channel) |
366 | void *channel_ctx) | ||
367 | { | 307 | { |
368 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel ended!\n"); | 308 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
369 | if (channel != ch) | 309 | "Channel ended!\n"); |
370 | { | 310 | GNUNET_assert (channel == ch); |
371 | GNUNET_break (0); | 311 | ch = NULL; |
372 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ended: %p, expected: %p\n", channel, ch); | ||
373 | } | ||
374 | else | ||
375 | { | ||
376 | ch = NULL; | ||
377 | } | ||
378 | if (NULL != th) | ||
379 | { | ||
380 | GNUNET_CADET_notify_transmit_ready_cancel (th); | ||
381 | th = NULL; | ||
382 | } | ||
383 | |||
384 | GNUNET_SCHEDULER_shutdown (); | 312 | GNUNET_SCHEDULER_shutdown (); |
385 | } | 313 | } |
386 | 314 | ||
@@ -397,65 +325,27 @@ channel_ended (void *cls, | |||
397 | * @param cls closure | 325 | * @param cls closure |
398 | * @param channel new handle to the channel | 326 | * @param channel new handle to the channel |
399 | * @param initiator peer that started the channel | 327 | * @param initiator peer that started the channel |
400 | * @param port Port this channel is for. | 328 | * @return initial channel context for the channel, we use @a channel |
401 | * @param options CadetOption flag field, with all active option bits set to 1. | ||
402 | * | ||
403 | * @return initial channel context for the channel | ||
404 | * (can be NULL -- that's not an error) | ||
405 | */ | 329 | */ |
406 | static void * | 330 | static void * |
407 | channel_incoming (void *cls, | 331 | channel_incoming (void *cls, |
408 | struct GNUNET_CADET_Channel *channel, | 332 | struct GNUNET_CADET_Channel *channel, |
409 | const struct GNUNET_PeerIdentity *initiator, | 333 | const struct GNUNET_PeerIdentity *initiator) |
410 | const struct GNUNET_HashCode *port, | ||
411 | enum GNUNET_CADET_ChannelOption options) | ||
412 | { | 334 | { |
413 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | 335 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, |
414 | "Connected from %s\n", | 336 | "Incoming connection from %s\n", |
415 | GNUNET_i2s_full (initiator)); | 337 | GNUNET_i2s_full (initiator)); |
416 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 338 | GNUNET_assert (NULL == ch); |
417 | "Incoming channel %p on port %s\n", | 339 | GNUNET_assert (NULL != lp); |
418 | channel, GNUNET_h2s (port)); | 340 | GNUNET_CADET_close_port (lp); |
419 | if (NULL != ch) | 341 | lp = NULL; |
420 | { | ||
421 | GNUNET_break (0); | ||
422 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
423 | "A channel already exists (%p)\n", ch); | ||
424 | /* | ||
425 | * From now on multiple channels will be sending data to us | ||
426 | * making the service of this command unpredictable in its | ||
427 | * current implementation. So for now let's just bail out. | ||
428 | */ | ||
429 | GNUNET_SCHEDULER_shutdown(); | ||
430 | return NULL; | ||
431 | } | ||
432 | if (NULL == listen_port) | ||
433 | { | ||
434 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Not listening to channels\n"); | ||
435 | return NULL; | ||
436 | } | ||
437 | #if 0 | ||
438 | // Closing the listen port currently breaks open connections. | ||
439 | // Is this an intentional departure from POSIX socket behavior? | ||
440 | // | ||
441 | if (NULL != lp) { | ||
442 | /* Now that we have our circuit up and running, let's not | ||
443 | * get confused by further incoming connect requests. | ||
444 | */ | ||
445 | GNUNET_CADET_close_port (lp); | ||
446 | lp = NULL; | ||
447 | } | ||
448 | #endif | ||
449 | ch = channel; | 342 | ch = channel; |
450 | if (GNUNET_NO == echo) | 343 | if (GNUNET_NO == echo) |
451 | { | ||
452 | listen_stdio (); | 344 | listen_stdio (); |
453 | return NULL; | 345 | return channel; |
454 | } | ||
455 | data_size = 0; | ||
456 | return NULL; | ||
457 | } | 346 | } |
458 | 347 | ||
348 | |||
459 | /** | 349 | /** |
460 | * @brief Send an echo request to the remote peer. | 350 | * @brief Send an echo request to the remote peer. |
461 | * | 351 | * |
@@ -464,13 +354,16 @@ channel_incoming (void *cls, | |||
464 | static void | 354 | static void |
465 | send_echo (void *cls) | 355 | send_echo (void *cls) |
466 | { | 356 | { |
357 | struct GNUNET_MQ_Envelope *env; | ||
358 | struct GNUNET_MessageHeader *msg; | ||
359 | |||
360 | echo_task = NULL; | ||
467 | if (NULL == ch) | 361 | if (NULL == ch) |
468 | return; | 362 | return; |
469 | GNUNET_assert (NULL == th); | 363 | env = GNUNET_MQ_msg (msg, |
470 | th = GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO, | 364 | GNUNET_MESSAGE_TYPE_CADET_CLI); |
471 | GNUNET_TIME_UNIT_FOREVER_REL, | 365 | GNUNET_MQ_send (GNUNET_CADET_get_mq (ch), |
472 | sizeof (struct GNUNET_MessageHeader), | 366 | env); |
473 | &data_ready, NULL); | ||
474 | } | 367 | } |
475 | 368 | ||
476 | 369 | ||
@@ -483,44 +376,23 @@ static void | |||
483 | request_dump (void *cls) | 376 | request_dump (void *cls) |
484 | { | 377 | { |
485 | GNUNET_CADET_request_dump (mh); | 378 | GNUNET_CADET_request_dump (mh); |
486 | GNUNET_SCHEDULER_cancel (sd); | 379 | GNUNET_SCHEDULER_shutdown (); |
487 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
488 | &shutdown_task, NULL); | ||
489 | } | 380 | } |
490 | 381 | ||
491 | 382 | ||
492 | /** | 383 | /** |
493 | * Call CADET's monitor API, get info of one connection. | 384 | * Check data message sanity. Does nothing so far (all messages are OK). |
494 | * | 385 | * |
495 | * @param cls Closure (unused). | 386 | * @param cls Closure (unused). |
387 | * @param message The message to check. | ||
388 | * @return #GNUNET_OK to keep the channel open, | ||
389 | * #GNUNET_SYSERR to close it (signal serious error). | ||
496 | */ | 390 | */ |
497 | static void | 391 | static int |
498 | create_channel (void *cls) | 392 | check_data (void *cls, |
393 | const struct GNUNET_MessageHeader *message) | ||
499 | { | 394 | { |
500 | struct GNUNET_PeerIdentity pid; | 395 | return GNUNET_OK; /* all is well-formed */ |
501 | enum GNUNET_CADET_ChannelOption opt; | ||
502 | |||
503 | GNUNET_assert (NULL == ch); | ||
504 | |||
505 | if (GNUNET_OK != | ||
506 | GNUNET_CRYPTO_eddsa_public_key_from_string (target_id, | ||
507 | strlen (target_id), | ||
508 | &pid.public_key)) | ||
509 | { | ||
510 | FPRINTF (stderr, | ||
511 | _("Invalid target `%s'\n"), | ||
512 | target_id); | ||
513 | GNUNET_SCHEDULER_shutdown (); | ||
514 | return; | ||
515 | } | ||
516 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to `%s'\n", target_id); | ||
517 | opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE; | ||
518 | GNUNET_CRYPTO_hash (target_port, strlen(target_port), &porthash); | ||
519 | ch = GNUNET_CADET_channel_create (mh, NULL, &pid, &porthash, opt); | ||
520 | if (GNUNET_NO == echo) | ||
521 | listen_stdio (); | ||
522 | else | ||
523 | echo_task = GNUNET_SCHEDULER_add_now (&send_echo, NULL); | ||
524 | } | 396 | } |
525 | 397 | ||
526 | 398 | ||
@@ -531,42 +403,36 @@ create_channel (void *cls) | |||
531 | * in order to receive the next message. This doesn't need to be immediate: | 403 | * in order to receive the next message. This doesn't need to be immediate: |
532 | * can be delayed if some processing is done on the message. | 404 | * can be delayed if some processing is done on the message. |
533 | * | 405 | * |
534 | * @param cls Closure (set from #GNUNET_CADET_connect). | 406 | * @param cls NULL |
535 | * @param channel Connection to the other end. | ||
536 | * @param channel_ctx Place to store local state associated with the channel. | ||
537 | * @param message The actual message. | 407 | * @param message The actual message. |
538 | * @return #GNUNET_OK to keep the channel open, | ||
539 | * #GNUNET_SYSERR to close it (signal serious error). | ||
540 | */ | 408 | */ |
541 | static int | 409 | static void |
542 | data_callback (void *cls, | 410 | handle_data (void *cls, |
543 | struct GNUNET_CADET_Channel *channel, | 411 | const struct GNUNET_MessageHeader *message) |
544 | void **channel_ctx, | ||
545 | const struct GNUNET_MessageHeader *message) | ||
546 | { | 412 | { |
413 | size_t payload_size = ntohs (message->size) - sizeof (*message); | ||
547 | uint16_t len; | 414 | uint16_t len; |
548 | ssize_t done; | 415 | ssize_t done; |
549 | uint16_t off; | 416 | uint16_t off; |
550 | const char *buf; | 417 | const char *buf; |
551 | GNUNET_break (ch == channel); | ||
552 | GNUNET_CADET_receive_done (channel); | ||
553 | 418 | ||
419 | GNUNET_CADET_receive_done (ch); | ||
554 | if (GNUNET_YES == echo) | 420 | if (GNUNET_YES == echo) |
555 | { | 421 | { |
556 | if (NULL != listen_port) | 422 | if (NULL != listen_port) |
557 | { | 423 | { |
558 | /* Just listening to echo incoming messages*/ | 424 | struct GNUNET_MQ_Envelope *env; |
559 | if (NULL != th) | 425 | struct GNUNET_MessageHeader *msg; |
560 | { | 426 | |
561 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 427 | env = GNUNET_MQ_msg_extra (msg, |
562 | "Last echo reply not yet sent, dropping current reply.\n"); | 428 | payload_size, |
563 | return GNUNET_OK; | 429 | GNUNET_MESSAGE_TYPE_CADET_CLI); |
564 | } | 430 | GNUNET_memcpy (&msg[1], |
565 | th = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, | 431 | &message[1], |
566 | GNUNET_TIME_UNIT_FOREVER_REL, | 432 | payload_size); |
567 | sizeof (struct GNUNET_MessageHeader), | 433 | GNUNET_MQ_send (GNUNET_CADET_get_mq (ch), |
568 | &data_ready, NULL); | 434 | env); |
569 | return GNUNET_OK; | 435 | return; |
570 | } | 436 | } |
571 | else | 437 | else |
572 | { | 438 | { |
@@ -574,30 +440,37 @@ data_callback (void *cls, | |||
574 | 440 | ||
575 | latency = GNUNET_TIME_absolute_get_duration (echo_time); | 441 | latency = GNUNET_TIME_absolute_get_duration (echo_time); |
576 | echo_time = GNUNET_TIME_UNIT_FOREVER_ABS; | 442 | echo_time = GNUNET_TIME_UNIT_FOREVER_ABS; |
577 | FPRINTF (stdout, "time: %s\n", | 443 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, |
578 | GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO)); | 444 | "time: %s\n", |
445 | GNUNET_STRINGS_relative_time_to_string (latency, | ||
446 | GNUNET_NO)); | ||
579 | echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | 447 | echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, |
580 | &send_echo, NULL); | 448 | &send_echo, |
449 | NULL); | ||
581 | } | 450 | } |
582 | } | 451 | } |
583 | 452 | ||
584 | len = ntohs (message->size) - sizeof (*message); | 453 | len = ntohs (message->size) - sizeof (*message); |
585 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u bytes\n", len); | 454 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
455 | "Got %u bytes\n", | ||
456 | len); | ||
586 | buf = (const char *) &message[1]; | 457 | buf = (const char *) &message[1]; |
587 | off = 0; | 458 | off = 0; |
588 | while (off < len) | 459 | while (off < len) |
589 | { | 460 | { |
590 | done = write (1, &buf[off], len - off); | 461 | done = write (1, |
462 | &buf[off], | ||
463 | len - off); | ||
591 | if (done <= 0) | 464 | if (done <= 0) |
592 | { | 465 | { |
593 | if (-1 == done) | 466 | if (-1 == done) |
594 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, | 467 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, |
595 | "write"); | 468 | "write"); |
596 | return GNUNET_SYSERR; | 469 | GNUNET_SCHEDULER_shutdown (); |
470 | return; | ||
597 | } | 471 | } |
598 | off += done; | 472 | off += done; |
599 | } | 473 | } |
600 | return GNUNET_OK; | ||
601 | } | 474 | } |
602 | 475 | ||
603 | 476 | ||
@@ -623,16 +496,17 @@ peers_callback (void *cls, | |||
623 | { | 496 | { |
624 | if (NULL == peer) | 497 | if (NULL == peer) |
625 | { | 498 | { |
626 | if (GNUNET_YES != monitor_mode) | 499 | GNUNET_SCHEDULER_shutdown(); |
627 | { | ||
628 | GNUNET_SCHEDULER_shutdown(); | ||
629 | } | ||
630 | return; | 500 | return; |
631 | } | 501 | } |
632 | FPRINTF (stdout, "%s tunnel: %c, paths: %u\n", | 502 | FPRINTF (stdout, |
633 | GNUNET_i2s_full (peer), tunnel ? 'Y' : 'N', n_paths); | 503 | "%s tunnel: %c, paths: %u\n", |
504 | GNUNET_i2s_full (peer), | ||
505 | tunnel ? 'Y' : 'N', | ||
506 | n_paths); | ||
634 | } | 507 | } |
635 | 508 | ||
509 | |||
636 | /** | 510 | /** |
637 | * Method called to retrieve information about a specific peer | 511 | * Method called to retrieve information about a specific peer |
638 | * known to the service. | 512 | * known to the service. |
@@ -652,19 +526,26 @@ peer_callback (void *cls, | |||
652 | int tunnel, | 526 | int tunnel, |
653 | int neighbor, | 527 | int neighbor, |
654 | unsigned int n_paths, | 528 | unsigned int n_paths, |
655 | struct GNUNET_PeerIdentity *paths) | 529 | const struct GNUNET_PeerIdentity *paths) |
656 | { | 530 | { |
657 | unsigned int i; | 531 | unsigned int i; |
658 | struct GNUNET_PeerIdentity *p; | 532 | const struct GNUNET_PeerIdentity *p; |
659 | 533 | ||
660 | FPRINTF (stdout, "%s [TUNNEL: %s, NEIGHBOR: %s, PATHS: %u]\n", | 534 | FPRINTF (stdout, |
535 | "%s [TUNNEL: %s, NEIGHBOR: %s, PATHS: %u]\n", | ||
661 | GNUNET_i2s_full (peer), | 536 | GNUNET_i2s_full (peer), |
662 | tunnel ? "Y" : "N", neighbor ? "Y" : "N", n_paths); | 537 | tunnel ? "Y" : "N", |
538 | neighbor ? "Y" : "N", | ||
539 | n_paths); | ||
663 | p = paths; | 540 | p = paths; |
664 | for (i = 0; i < n_paths && NULL != p;) | 541 | for (i = 0; i < n_paths && NULL != p;) |
665 | { | 542 | { |
666 | FPRINTF (stdout, "%s ", GNUNET_i2s (p)); | 543 | FPRINTF (stdout, |
667 | if (0 == memcmp (p, peer, sizeof (*p))) | 544 | "%s ", |
545 | GNUNET_i2s (p)); | ||
546 | if (0 == memcmp (p, | ||
547 | peer, | ||
548 | sizeof (*p))) | ||
668 | { | 549 | { |
669 | FPRINTF (stdout, "\n"); | 550 | FPRINTF (stdout, "\n"); |
670 | i++; | 551 | i++; |
@@ -696,16 +577,16 @@ tunnels_callback (void *cls, | |||
696 | { | 577 | { |
697 | if (NULL == peer) | 578 | if (NULL == peer) |
698 | { | 579 | { |
699 | if (GNUNET_YES != monitor_mode) | 580 | GNUNET_SCHEDULER_shutdown(); |
700 | { | ||
701 | GNUNET_SCHEDULER_shutdown(); | ||
702 | } | ||
703 | return; | 581 | return; |
704 | } | 582 | } |
705 | FPRINTF (stdout, "%s [ENC: %s, CON: %s] CHs: %u, CONNs: %u\n", | 583 | FPRINTF (stdout, |
584 | "%s [ENC: %s, CON: %s] CHs: %u, CONNs: %u\n", | ||
706 | GNUNET_i2s_full (peer), | 585 | GNUNET_i2s_full (peer), |
707 | enc_2s (estate), conn_2s (cstate), | 586 | enc_2s (estate), |
708 | channels, connections); | 587 | conn_2s (cstate), |
588 | channels, | ||
589 | connections); | ||
709 | } | 590 | } |
710 | 591 | ||
711 | 592 | ||
@@ -746,11 +627,7 @@ tunnel_callback (void *cls, | |||
746 | FPRINTF (stdout, "\tencryption state: %s\n", enc_2s (estate)); | 627 | FPRINTF (stdout, "\tencryption state: %s\n", enc_2s (estate)); |
747 | FPRINTF (stdout, "\tconnection state: %s\n", conn_2s (cstate)); | 628 | FPRINTF (stdout, "\tconnection state: %s\n", conn_2s (cstate)); |
748 | } | 629 | } |
749 | if (GNUNET_YES != monitor_mode) | 630 | GNUNET_SCHEDULER_shutdown (); |
750 | { | ||
751 | GNUNET_SCHEDULER_shutdown (); | ||
752 | } | ||
753 | return; | ||
754 | } | 631 | } |
755 | 632 | ||
756 | 633 | ||
@@ -874,93 +751,158 @@ run (void *cls, | |||
874 | const char *cfgfile, | 751 | const char *cfgfile, |
875 | const struct GNUNET_CONFIGURATION_Handle *cfg) | 752 | const struct GNUNET_CONFIGURATION_Handle *cfg) |
876 | { | 753 | { |
877 | static const struct GNUNET_CADET_MessageHandler handlers[] = { | 754 | struct GNUNET_MQ_MessageHandler handlers[] = { |
878 | {&data_callback, GNUNET_MESSAGE_TYPE_CADET_CLI, 0}, | 755 | GNUNET_MQ_hd_var_size (data, |
879 | {NULL, 0, 0} /* FIXME add option to monitor msg types */ | 756 | GNUNET_MESSAGE_TYPE_CADET_CLI, |
757 | struct GNUNET_MessageHeader, | ||
758 | NULL), | ||
759 | GNUNET_MQ_handler_end () | ||
880 | }; | 760 | }; |
881 | 761 | ||
882 | /* FIXME add option to monitor apps */ | 762 | /* FIXME add option to monitor apps */ |
883 | 763 | ||
884 | target_id = args[0]; | 764 | target_id = args[0]; |
885 | if (target_id && args[1]) target_port = args[1]; | 765 | if (target_id && args[1]) |
766 | target_port = args[1]; | ||
886 | 767 | ||
887 | if ( (0 != (request_peers | request_tunnels) | 768 | if ( (0 != (request_peers | request_tunnels) |
888 | || 0 != monitor_mode | ||
889 | || NULL != tunnel_id | 769 | || NULL != tunnel_id |
890 | || NULL != conn_id | 770 | || NULL != conn_id |
891 | || NULL != channel_id) | 771 | || NULL != channel_id) |
892 | && target_id != NULL) | 772 | && target_id != NULL) |
893 | { | 773 | { |
894 | FPRINTF (stderr, | 774 | FPRINTF (stderr, |
895 | _("You must NOT give a TARGET " | 775 | _("Extra arguments are not applicable " |
896 | "when using 'request all' options\n")); | 776 | "in combination with this option.\n")); |
897 | return; | 777 | return; |
898 | } | 778 | } |
899 | 779 | ||
900 | if (GNUNET_YES == dump) | 780 | if (GNUNET_YES == dump) |
901 | { | 781 | { |
902 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 782 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
903 | "requesting debug dump\n"); | 783 | "Requesting debug dump\n"); |
904 | GNUNET_SCHEDULER_add_now (&request_dump, NULL); | 784 | job = GNUNET_SCHEDULER_add_now (&request_dump, |
905 | } | 785 | NULL); |
906 | else if (NULL != target_id) | ||
907 | { | ||
908 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
909 | "Creating channel to %s\n", | ||
910 | target_id); | ||
911 | GNUNET_SCHEDULER_add_now (&create_channel, NULL); | ||
912 | } | 786 | } |
913 | else if (NULL != peer_id) | 787 | else if (NULL != peer_id) |
914 | { | 788 | { |
915 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show peer\n"); | 789 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
916 | job = GNUNET_SCHEDULER_add_now (&show_peer, NULL); | 790 | "Show peer\n"); |
791 | job = GNUNET_SCHEDULER_add_now (&show_peer, | ||
792 | NULL); | ||
917 | } | 793 | } |
918 | else if (NULL != tunnel_id) | 794 | else if (NULL != tunnel_id) |
919 | { | 795 | { |
920 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show tunnel\n"); | 796 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
921 | job = GNUNET_SCHEDULER_add_now (&show_tunnel, NULL); | 797 | "Show tunnel\n"); |
798 | job = GNUNET_SCHEDULER_add_now (&show_tunnel, | ||
799 | NULL); | ||
922 | } | 800 | } |
923 | else if (NULL != channel_id) | 801 | else if (NULL != channel_id) |
924 | { | 802 | { |
925 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show channel\n"); | 803 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
926 | job = GNUNET_SCHEDULER_add_now (&show_channel, NULL); | 804 | "Show channel\n"); |
805 | job = GNUNET_SCHEDULER_add_now (&show_channel, | ||
806 | NULL); | ||
927 | } | 807 | } |
928 | else if (NULL != conn_id) | 808 | else if (NULL != conn_id) |
929 | { | 809 | { |
930 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show connection\n"); | 810 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
931 | job = GNUNET_SCHEDULER_add_now (&show_connection, NULL); | 811 | "Show connection\n"); |
812 | job = GNUNET_SCHEDULER_add_now (&show_connection, | ||
813 | NULL); | ||
932 | } | 814 | } |
933 | else if (GNUNET_YES == request_peers) | 815 | else if (GNUNET_YES == request_peers) |
934 | { | 816 | { |
935 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all peers\n"); | 817 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
936 | job = GNUNET_SCHEDULER_add_now (&get_peers, NULL); | 818 | "Show all peers\n"); |
819 | job = GNUNET_SCHEDULER_add_now (&get_peers, | ||
820 | NULL); | ||
937 | } | 821 | } |
938 | else if (GNUNET_YES == request_tunnels) | 822 | else if (GNUNET_YES == request_tunnels) |
939 | { | 823 | { |
940 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all tunnels\n"); | 824 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
941 | job = GNUNET_SCHEDULER_add_now (&get_tunnels, NULL); | 825 | "Show all tunnels\n"); |
826 | job = GNUNET_SCHEDULER_add_now (&get_tunnels, | ||
827 | NULL); | ||
942 | } | 828 | } |
943 | else if (NULL == listen_port) | 829 | |
830 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
831 | "Connecting to CADET service\n"); | ||
832 | mh = GNUNET_CADET_connect (cfg); | ||
833 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | ||
834 | NULL); | ||
835 | if (NULL == mh) | ||
944 | { | 836 | { |
945 | FPRINTF (stderr, "No action requested\n"); | 837 | GNUNET_SCHEDULER_shutdown (); |
946 | return; | 838 | return; |
947 | } | 839 | } |
948 | |||
949 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CADET service\n"); | ||
950 | mh = GNUNET_CADET_connect (cfg, | ||
951 | NULL, /* cls */ | ||
952 | &channel_ended, /* cleaner */ | ||
953 | handlers); | ||
954 | if (NULL == mh) | ||
955 | GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
956 | else | ||
957 | sd = GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
958 | |||
959 | if (NULL != listen_port) | 840 | if (NULL != listen_port) |
960 | { | 841 | { |
961 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opening CADET listen port\n"); | 842 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
962 | GNUNET_CRYPTO_hash (listen_port, strlen(listen_port), &porthash); | 843 | "Opening CADET listen port\n"); |
963 | lp = GNUNET_CADET_open_port (mh, &porthash, &channel_incoming, NULL); | 844 | GNUNET_CRYPTO_hash (listen_port, |
845 | strlen (listen_port), | ||
846 | &porthash); | ||
847 | lp = GNUNET_CADET_open_port (mh, | ||
848 | &porthash, | ||
849 | &channel_incoming, | ||
850 | NULL, | ||
851 | NULL /* window changes */, | ||
852 | &channel_ended, | ||
853 | handlers); | ||
854 | } | ||
855 | if (NULL != target_id) | ||
856 | { | ||
857 | struct GNUNET_PeerIdentity pid; | ||
858 | enum GNUNET_CADET_ChannelOption opt; | ||
859 | |||
860 | if (GNUNET_OK != | ||
861 | GNUNET_CRYPTO_eddsa_public_key_from_string (target_id, | ||
862 | strlen (target_id), | ||
863 | &pid.public_key)) | ||
864 | { | ||
865 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
866 | _("Invalid target `%s'\n"), | ||
867 | target_id); | ||
868 | GNUNET_SCHEDULER_shutdown (); | ||
869 | return; | ||
870 | } | ||
871 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
872 | "Connecting to `%s:%s'\n", | ||
873 | target_id, | ||
874 | target_port); | ||
875 | opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE; | ||
876 | GNUNET_CRYPTO_hash (target_port, | ||
877 | strlen(target_port), | ||
878 | &porthash); | ||
879 | ch = GNUNET_CADET_channel_create (mh, | ||
880 | NULL, | ||
881 | &pid, | ||
882 | &porthash, | ||
883 | opt, | ||
884 | NULL /* window changes */, | ||
885 | &channel_ended, | ||
886 | handlers); | ||
887 | if (GNUNET_YES == echo) | ||
888 | { | ||
889 | echo_task = GNUNET_SCHEDULER_add_now (&send_echo, | ||
890 | NULL); | ||
891 | } | ||
892 | else | ||
893 | { | ||
894 | listen_stdio (); | ||
895 | } | ||
896 | } | ||
897 | |||
898 | if ( (NULL == lp) && | ||
899 | (NULL == job) && | ||
900 | (NULL == ch) ) | ||
901 | { | ||
902 | GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, | ||
903 | _("No action requested\n")); | ||
904 | GNUNET_SCHEDULER_shutdown (); | ||
905 | return; | ||
964 | } | 906 | } |
965 | } | 907 | } |
966 | 908 | ||
@@ -973,51 +915,70 @@ run (void *cls, | |||
973 | * @return 0 ok, 1 on error | 915 | * @return 0 ok, 1 on error |
974 | */ | 916 | */ |
975 | int | 917 | int |
976 | main (int argc, char *const *argv) | 918 | main (int argc, |
919 | char *const *argv) | ||
977 | { | 920 | { |
978 | int res; | 921 | int res; |
979 | const char helpstr[] = "Create channels and retreive info about cadets status."; | 922 | const char helpstr[] = "Create tunnels and retrieve info about CADET's status."; |
980 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | 923 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
981 | // {'a', "channel", "TUNNEL_ID:CHANNEL_ID", | 924 | /* I would use the terminology 'circuit' here... --lynX */ |
982 | // gettext_noop ("provide information about a particular channel"), | 925 | GNUNET_GETOPT_option_string ('C', |
983 | // GNUNET_YES, &GNUNET_GETOPT_set_string, &channel_id}, | 926 | "connection", |
984 | {'C', "connection", "CONNECTION_ID", | 927 | "CONNECTION_ID", |
985 | gettext_noop ("provide information about a particular connection"), | 928 | gettext_noop ("Provide information about a particular connection"), |
986 | GNUNET_YES, &GNUNET_GETOPT_set_string, &conn_id}, | 929 | &conn_id), |
987 | {'e', "echo", NULL, | 930 | |
988 | gettext_noop ("activate echo mode"), | 931 | GNUNET_GETOPT_option_flag ('e', |
989 | GNUNET_NO, &GNUNET_GETOPT_set_one, &echo}, | 932 | "echo", |
990 | {'d', "dump", NULL, | 933 | gettext_noop ("Activate echo mode"), |
991 | gettext_noop ("dump debug information to STDERR"), | 934 | &echo), |
992 | GNUNET_NO, &GNUNET_GETOPT_set_one, &dump}, | 935 | |
993 | // {'m', "monitor", NULL, | 936 | GNUNET_GETOPT_option_flag ('d', |
994 | // gettext_noop ("provide information about all events (continuously)"), | 937 | "dump", |
995 | // GNUNET_NO, &GNUNET_GETOPT_set_one, &monitor_mode}, | 938 | gettext_noop ("Dump debug information to STDERR"), |
996 | {'o', "open-port", NULL, | 939 | &dump), |
997 | gettext_noop ("port to listen to"), | 940 | |
998 | GNUNET_YES, &GNUNET_GETOPT_set_string, &listen_port}, | 941 | GNUNET_GETOPT_option_string ('o', |
999 | {'p', "peer", "PEER_ID", | 942 | "open-port", |
1000 | gettext_noop ("provide information about a patricular peer"), | 943 | "SHARED_SECRET", |
1001 | GNUNET_YES, &GNUNET_GETOPT_set_string, &peer_id}, | 944 | gettext_noop ("Listen for connections using a shared secret among sender and recipient"), |
1002 | {'P', "peers", NULL, | 945 | &listen_port), |
1003 | gettext_noop ("provide information about all peers"), | 946 | |
1004 | GNUNET_NO, &GNUNET_GETOPT_set_one, &request_peers}, | 947 | |
1005 | {'t', "tunnel", "TUNNEL_ID", | 948 | GNUNET_GETOPT_option_string ('p', |
1006 | gettext_noop ("provide information about a particular tunnel"), | 949 | "peer", |
1007 | GNUNET_YES, &GNUNET_GETOPT_set_string, &tunnel_id}, | 950 | "PEER_ID", |
1008 | {'T', "tunnels", NULL, | 951 | gettext_noop ("Provide information about a patricular peer"), |
1009 | gettext_noop ("provide information about all tunnels"), | 952 | &peer_id), |
1010 | GNUNET_NO, &GNUNET_GETOPT_set_one, &request_tunnels}, | 953 | |
954 | |||
955 | GNUNET_GETOPT_option_flag ('P', | ||
956 | "peers", | ||
957 | gettext_noop ("Provide information about all peers"), | ||
958 | &request_peers), | ||
959 | |||
960 | GNUNET_GETOPT_option_string ('t', | ||
961 | "tunnel", | ||
962 | "TUNNEL_ID", | ||
963 | gettext_noop ("Provide information about a particular tunnel"), | ||
964 | &tunnel_id), | ||
965 | |||
966 | |||
967 | GNUNET_GETOPT_option_flag ('T', | ||
968 | "tunnels", | ||
969 | gettext_noop ("Provide information about all tunnels"), | ||
970 | &request_tunnels), | ||
1011 | 971 | ||
1012 | GNUNET_GETOPT_OPTION_END | 972 | GNUNET_GETOPT_OPTION_END |
1013 | }; | 973 | }; |
1014 | 974 | ||
1015 | monitor_mode = GNUNET_NO; | 975 | if (GNUNET_OK != |
1016 | 976 | GNUNET_STRINGS_get_utf8_args (argc, argv, | |
1017 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | 977 | &argc, &argv)) |
1018 | return 2; | 978 | return 2; |
1019 | 979 | ||
1020 | res = GNUNET_PROGRAM_run (argc, argv, "gnunet-cadet (OPTIONS | TARGET PORT)", | 980 | res = GNUNET_PROGRAM_run (argc, argv, |
981 | "gnunet-cadet (OPTIONS | PEER_ID SHARED_SECRET)", | ||
1021 | gettext_noop (helpstr), | 982 | gettext_noop (helpstr), |
1022 | options, &run, NULL); | 983 | options, &run, NULL); |
1023 | 984 | ||
@@ -1025,8 +986,7 @@ main (int argc, char *const *argv) | |||
1025 | 986 | ||
1026 | if (GNUNET_OK == res) | 987 | if (GNUNET_OK == res) |
1027 | return 0; | 988 | return 0; |
1028 | else | 989 | return 1; |
1029 | return 1; | ||
1030 | } | 990 | } |
1031 | 991 | ||
1032 | /* end of gnunet-cadet.c */ | 992 | /* end of gnunet-cadet.c */ |
diff --git a/src/cadet/gnunet-service-cadet-new.c b/src/cadet/gnunet-service-cadet-new.c deleted file mode 100644 index 97489f3fd..000000000 --- a/src/cadet/gnunet-service-cadet-new.c +++ /dev/null | |||
@@ -1,1428 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2013, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet-new.c | ||
23 | * @brief GNUnet CADET service with encryption | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * Dictionary: | ||
28 | * - peer: other cadet instance. If there is direct connection it's a neighbor. | ||
29 | * - path: series of directly connected peer from one peer to another. | ||
30 | * - connection: path which is being used in a tunnel. | ||
31 | * - tunnel: encrypted connection to a peer, neighbor or not. | ||
32 | * - channel: logical link between two clients, on the same or different peers. | ||
33 | * have properties like reliability. | ||
34 | */ | ||
35 | |||
36 | #include "platform.h" | ||
37 | #include "gnunet_util_lib.h" | ||
38 | #include "cadet.h" | ||
39 | #include "gnunet_statistics_service.h" | ||
40 | #include "gnunet-service-cadet-new.h" | ||
41 | #include "gnunet-service-cadet-new_channel.h" | ||
42 | #include "gnunet-service-cadet-new_connection.h" | ||
43 | #include "gnunet-service-cadet-new_core.h" | ||
44 | #include "gnunet-service-cadet-new_dht.h" | ||
45 | #include "gnunet-service-cadet-new_hello.h" | ||
46 | #include "gnunet-service-cadet-new_tunnels.h" | ||
47 | #include "gnunet-service-cadet-new_peer.h" | ||
48 | #include "gnunet-service-cadet-new_paths.h" | ||
49 | |||
50 | #define LOG(level, ...) GNUNET_log (level,__VA_ARGS__) | ||
51 | |||
52 | |||
53 | /** | ||
54 | * Struct containing information about a client of the service | ||
55 | */ | ||
56 | struct CadetClient | ||
57 | { | ||
58 | /** | ||
59 | * Linked list next | ||
60 | */ | ||
61 | struct CadetClient *next; | ||
62 | |||
63 | /** | ||
64 | * Linked list prev | ||
65 | */ | ||
66 | struct CadetClient *prev; | ||
67 | |||
68 | /** | ||
69 | * Tunnels that belong to this client, indexed by local id, | ||
70 | * value is a `struct CadetChannel`. | ||
71 | */ | ||
72 | struct GNUNET_CONTAINER_MultiHashMap32 *channels; | ||
73 | |||
74 | /** | ||
75 | * Handle to communicate with the client | ||
76 | */ | ||
77 | struct GNUNET_MQ_Handle *mq; | ||
78 | |||
79 | /** | ||
80 | * Client handle. | ||
81 | */ | ||
82 | struct GNUNET_SERVICE_Client *client; | ||
83 | |||
84 | /** | ||
85 | * Ports that this client has declared interest in. | ||
86 | * Indexed by port, contains *Client. | ||
87 | */ | ||
88 | struct GNUNET_CONTAINER_MultiHashMap *ports; | ||
89 | |||
90 | /** | ||
91 | * Channel ID to use for the next incoming channel for this client. | ||
92 | * Wraps around (in theory). | ||
93 | */ | ||
94 | struct GNUNET_CADET_ClientChannelNumber next_ccn; | ||
95 | |||
96 | /** | ||
97 | * ID of the client, mainly for debug messages. Purely internal to this file. | ||
98 | */ | ||
99 | unsigned int id; | ||
100 | }; | ||
101 | |||
102 | /******************************************************************************/ | ||
103 | /*********************** GLOBAL VARIABLES ****************************/ | ||
104 | /******************************************************************************/ | ||
105 | |||
106 | /****************************** Global variables ******************************/ | ||
107 | |||
108 | /** | ||
109 | * Handle to our configuration. | ||
110 | */ | ||
111 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
112 | |||
113 | /** | ||
114 | * Handle to the statistics service. | ||
115 | */ | ||
116 | struct GNUNET_STATISTICS_Handle *stats; | ||
117 | |||
118 | /** | ||
119 | * Handle to communicate with ATS. | ||
120 | */ | ||
121 | struct GNUNET_ATS_ConnectivityHandle *ats_ch; | ||
122 | |||
123 | /** | ||
124 | * Local peer own ID. | ||
125 | */ | ||
126 | struct GNUNET_PeerIdentity my_full_id; | ||
127 | |||
128 | /** | ||
129 | * Own private key. | ||
130 | */ | ||
131 | struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | ||
132 | |||
133 | /** | ||
134 | * Signal that shutdown is happening: prevent recovery measures. | ||
135 | */ | ||
136 | int shutting_down; | ||
137 | |||
138 | /** | ||
139 | * DLL with all the clients, head. | ||
140 | */ | ||
141 | static struct CadetClient *clients_head; | ||
142 | |||
143 | /** | ||
144 | * DLL with all the clients, tail. | ||
145 | */ | ||
146 | static struct CadetClient *clients_tail; | ||
147 | |||
148 | /** | ||
149 | * Next ID to assign to a client. | ||
150 | */ | ||
151 | static unsigned int next_client_id; | ||
152 | |||
153 | /** | ||
154 | * All ports clients of this peer have opened. | ||
155 | */ | ||
156 | struct GNUNET_CONTAINER_MultiHashMap *open_ports; | ||
157 | |||
158 | /** | ||
159 | * Map from ports to channels where the ports were closed at the | ||
160 | * time we got the inbound connection. | ||
161 | * Indexed by port, contains `struct CadetChannel`. | ||
162 | */ | ||
163 | struct GNUNET_CONTAINER_MultiHashMap *loose_channels; | ||
164 | |||
165 | /** | ||
166 | * Map from PIDs to `struct CadetPeer` entries. | ||
167 | */ | ||
168 | struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
169 | |||
170 | /** | ||
171 | * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier` | ||
172 | * hash codes to `struct CadetConnection` objects. | ||
173 | */ | ||
174 | struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
175 | |||
176 | /** | ||
177 | * How many messages are needed to trigger an AXOLOTL ratchet advance. | ||
178 | */ | ||
179 | unsigned long long ratchet_messages; | ||
180 | |||
181 | /** | ||
182 | * How long until we trigger a ratched advance due to time. | ||
183 | */ | ||
184 | struct GNUNET_TIME_Relative ratchet_time; | ||
185 | |||
186 | |||
187 | /** | ||
188 | * Send a message to a client. | ||
189 | * | ||
190 | * @param c client to get the message | ||
191 | * @param env envelope with the message | ||
192 | */ | ||
193 | void | ||
194 | GSC_send_to_client (struct CadetClient *c, | ||
195 | struct GNUNET_MQ_Envelope *env) | ||
196 | { | ||
197 | GNUNET_MQ_send (c->mq, | ||
198 | env); | ||
199 | } | ||
200 | |||
201 | |||
202 | /** | ||
203 | * Return identifier for a client as a string. | ||
204 | * | ||
205 | * @param c client to identify | ||
206 | * @return string for debugging | ||
207 | */ | ||
208 | const char * | ||
209 | GSC_2s (struct CadetClient *c) | ||
210 | { | ||
211 | static char buf[32]; | ||
212 | |||
213 | GNUNET_snprintf (buf, | ||
214 | sizeof (buf), | ||
215 | "Client(%u)", | ||
216 | c->id); | ||
217 | return buf; | ||
218 | } | ||
219 | |||
220 | |||
221 | /** | ||
222 | * Lookup channel of client @a c by @a ccn. | ||
223 | * | ||
224 | * @param c client to look in | ||
225 | * @param ccn channel ID to look up | ||
226 | * @return NULL if no such channel exists | ||
227 | */ | ||
228 | static struct CadetChannel * | ||
229 | lookup_channel (struct CadetClient *c, | ||
230 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
231 | { | ||
232 | return GNUNET_CONTAINER_multihashmap32_get (c->channels, | ||
233 | ntohl (ccn.channel_of_client)); | ||
234 | } | ||
235 | |||
236 | |||
237 | /** | ||
238 | * Obtain the next LID to use for incoming connections to | ||
239 | * the given client. | ||
240 | * | ||
241 | * @param c client handle | ||
242 | */ | ||
243 | static struct GNUNET_CADET_ClientChannelNumber | ||
244 | client_get_next_ccn (struct CadetClient *c) | ||
245 | { | ||
246 | struct GNUNET_CADET_ClientChannelNumber ccn = c->next_ccn; | ||
247 | |||
248 | /* increment until we have a free one... */ | ||
249 | while (NULL != | ||
250 | lookup_channel (c, | ||
251 | ccn)) | ||
252 | { | ||
253 | ccn.channel_of_client | ||
254 | = htonl (1 + (ntohl (ccn.channel_of_client))); | ||
255 | if (ntohl (ccn.channel_of_client) >= | ||
256 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
257 | ccn.channel_of_client = htonl (0); | ||
258 | } | ||
259 | c->next_ccn.channel_of_client | ||
260 | = htonl (1 + (ntohl (ccn.channel_of_client))); | ||
261 | return ccn; | ||
262 | } | ||
263 | |||
264 | |||
265 | /** | ||
266 | * Bind incoming channel to this client, and notify client about | ||
267 | * incoming connection. Caller is responsible for notifying the other | ||
268 | * peer about our acceptance of the channel. | ||
269 | * | ||
270 | * @param c client to bind to | ||
271 | * @param ch channel to be bound | ||
272 | * @param dest peer that establishes the connection | ||
273 | * @param port port number | ||
274 | * @param options options | ||
275 | * @return local channel number assigned to the new client | ||
276 | */ | ||
277 | struct GNUNET_CADET_ClientChannelNumber | ||
278 | GSC_bind (struct CadetClient *c, | ||
279 | struct CadetChannel *ch, | ||
280 | struct CadetPeer *dest, | ||
281 | const struct GNUNET_HashCode *port, | ||
282 | uint32_t options) | ||
283 | { | ||
284 | struct GNUNET_MQ_Envelope *env; | ||
285 | struct GNUNET_CADET_LocalChannelCreateMessage *cm; | ||
286 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
287 | |||
288 | ccn = client_get_next_ccn (c); | ||
289 | GNUNET_assert (GNUNET_YES == | ||
290 | GNUNET_CONTAINER_multihashmap32_put (c->channels, | ||
291 | ntohl (ccn.channel_of_client), | ||
292 | ch, | ||
293 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
294 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
295 | "Accepting incoming %s from %s on open port %s (%u), assigning ccn %X\n", | ||
296 | GCCH_2s (ch), | ||
297 | GCP_2s (dest), | ||
298 | GNUNET_h2s (port), | ||
299 | ntohl (options), | ||
300 | ntohl (ccn.channel_of_client)); | ||
301 | /* notify local client about incoming connection! */ | ||
302 | env = GNUNET_MQ_msg (cm, | ||
303 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); | ||
304 | cm->ccn = ccn; | ||
305 | cm->port = *port; | ||
306 | cm->opt = htonl (options); | ||
307 | cm->peer = *GCP_get_id (dest); | ||
308 | GSC_send_to_client (c, | ||
309 | env); | ||
310 | return ccn; | ||
311 | } | ||
312 | |||
313 | |||
314 | /** | ||
315 | * Callback invoked on all peers to destroy all tunnels | ||
316 | * that may still exist. | ||
317 | * | ||
318 | * @param cls NULL | ||
319 | * @param pid identify of a peer | ||
320 | * @param value a `struct CadetPeer` that may still have a tunnel | ||
321 | * @return #GNUNET_OK (iterate over all entries) | ||
322 | */ | ||
323 | static int | ||
324 | destroy_tunnels_now (void *cls, | ||
325 | const struct GNUNET_PeerIdentity *pid, | ||
326 | void *value) | ||
327 | { | ||
328 | struct CadetPeer *cp = value; | ||
329 | struct CadetTunnel *t = GCP_get_tunnel (cp, | ||
330 | GNUNET_NO); | ||
331 | |||
332 | if (NULL != t) | ||
333 | GCT_destroy_tunnel_now (t); | ||
334 | return GNUNET_OK; | ||
335 | } | ||
336 | |||
337 | |||
338 | /** | ||
339 | * Callback invoked on all peers to destroy all tunnels | ||
340 | * that may still exist. | ||
341 | * | ||
342 | * @param cls NULL | ||
343 | * @param pid identify of a peer | ||
344 | * @param value a `struct CadetPeer` that may still have a tunnel | ||
345 | * @return #GNUNET_OK (iterate over all entries) | ||
346 | */ | ||
347 | static int | ||
348 | destroy_paths_now (void *cls, | ||
349 | const struct GNUNET_PeerIdentity *pid, | ||
350 | void *value) | ||
351 | { | ||
352 | struct CadetPeer *cp = value; | ||
353 | |||
354 | GCP_drop_owned_paths (cp); | ||
355 | return GNUNET_OK; | ||
356 | } | ||
357 | |||
358 | |||
359 | /** | ||
360 | * Shutdown everything once the clients have disconnected. | ||
361 | */ | ||
362 | static void | ||
363 | shutdown_rest () | ||
364 | { | ||
365 | if (NULL != stats) | ||
366 | { | ||
367 | GNUNET_STATISTICS_destroy (stats, | ||
368 | GNUNET_NO); | ||
369 | stats = NULL; | ||
370 | } | ||
371 | if (NULL != open_ports) | ||
372 | { | ||
373 | GNUNET_CONTAINER_multihashmap_destroy (open_ports); | ||
374 | open_ports = NULL; | ||
375 | } | ||
376 | if (NULL != loose_channels) | ||
377 | { | ||
378 | GNUNET_CONTAINER_multihashmap_destroy (loose_channels); | ||
379 | loose_channels = NULL; | ||
380 | } | ||
381 | /* Destroy tunnels. Note that all channels must be destroyed first! */ | ||
382 | GCP_iterate_all (&destroy_tunnels_now, | ||
383 | NULL); | ||
384 | /* All tunnels, channels, connections and CORE must be down before this point. */ | ||
385 | GCP_iterate_all (&destroy_paths_now, | ||
386 | NULL); | ||
387 | /* All paths, tunnels, channels, connections and CORE must be down before this point. */ | ||
388 | GCP_destroy_all_peers (); | ||
389 | if (NULL != peers) | ||
390 | { | ||
391 | GNUNET_CONTAINER_multipeermap_destroy (peers); | ||
392 | peers = NULL; | ||
393 | } | ||
394 | if (NULL != connections) | ||
395 | { | ||
396 | GNUNET_CONTAINER_multishortmap_destroy (connections); | ||
397 | connections = NULL; | ||
398 | } | ||
399 | if (NULL != ats_ch) | ||
400 | { | ||
401 | GNUNET_ATS_connectivity_done (ats_ch); | ||
402 | ats_ch = NULL; | ||
403 | } | ||
404 | GCD_shutdown (); | ||
405 | GCH_shutdown (); | ||
406 | GNUNET_free_non_null (my_private_key); | ||
407 | my_private_key = NULL; | ||
408 | } | ||
409 | |||
410 | |||
411 | /** | ||
412 | * Task run during shutdown. | ||
413 | * | ||
414 | * @param cls unused | ||
415 | */ | ||
416 | static void | ||
417 | shutdown_task (void *cls) | ||
418 | { | ||
419 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
420 | "Shutting down\n"); | ||
421 | shutting_down = GNUNET_YES; | ||
422 | GCO_shutdown (); | ||
423 | if (NULL == clients_head) | ||
424 | shutdown_rest (); | ||
425 | } | ||
426 | |||
427 | |||
428 | /** | ||
429 | * We had a remote connection @a value to port @a port before | ||
430 | * client @a cls opened port @a port. Bind them now. | ||
431 | * | ||
432 | * @param cls the `struct CadetClient` | ||
433 | * @param port the port | ||
434 | * @param value the `struct CadetChannel` | ||
435 | * @return #GNUNET_YES (iterate over all such channels) | ||
436 | */ | ||
437 | static int | ||
438 | bind_loose_channel (void *cls, | ||
439 | const struct GNUNET_HashCode *port, | ||
440 | void *value) | ||
441 | { | ||
442 | struct CadetClient *c = cls; | ||
443 | struct CadetChannel *ch = value; | ||
444 | |||
445 | GCCH_bind (ch, | ||
446 | c); | ||
447 | GNUNET_assert (GNUNET_YES == | ||
448 | GNUNET_CONTAINER_multihashmap_remove (loose_channels, | ||
449 | port, | ||
450 | value)); | ||
451 | return GNUNET_YES; | ||
452 | } | ||
453 | |||
454 | |||
455 | /** | ||
456 | * Handle port open request. Creates a mapping from the | ||
457 | * port to the respective client and checks whether we have | ||
458 | * loose channels trying to bind to the port. If so, those | ||
459 | * are bound. | ||
460 | * | ||
461 | * @param cls Identification of the client. | ||
462 | * @param pmsg The actual message. | ||
463 | */ | ||
464 | static void | ||
465 | handle_port_open (void *cls, | ||
466 | const struct GNUNET_CADET_PortMessage *pmsg) | ||
467 | { | ||
468 | struct CadetClient *c = cls; | ||
469 | |||
470 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
471 | "Open port %s requested by %s\n", | ||
472 | GNUNET_h2s (&pmsg->port), | ||
473 | GSC_2s (c)); | ||
474 | if (NULL == c->ports) | ||
475 | c->ports = GNUNET_CONTAINER_multihashmap_create (4, | ||
476 | GNUNET_NO); | ||
477 | if (GNUNET_OK != | ||
478 | GNUNET_CONTAINER_multihashmap_put (c->ports, | ||
479 | &pmsg->port, | ||
480 | c, | ||
481 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
482 | { | ||
483 | GNUNET_break (0); | ||
484 | GNUNET_SERVICE_client_drop (c->client); | ||
485 | return; | ||
486 | } | ||
487 | (void) GNUNET_CONTAINER_multihashmap_put (open_ports, | ||
488 | &pmsg->port, | ||
489 | c, | ||
490 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
491 | GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels, | ||
492 | &pmsg->port, | ||
493 | &bind_loose_channel, | ||
494 | c); | ||
495 | GNUNET_SERVICE_client_continue (c->client); | ||
496 | } | ||
497 | |||
498 | |||
499 | /** | ||
500 | * Handler for port close requests. Marks this port as closed | ||
501 | * (unless of course we have another client with the same port | ||
502 | * open). Note that existing channels accepted on the port are | ||
503 | * not affected. | ||
504 | * | ||
505 | * @param cls Identification of the client. | ||
506 | * @param pmsg The actual message. | ||
507 | */ | ||
508 | static void | ||
509 | handle_port_close (void *cls, | ||
510 | const struct GNUNET_CADET_PortMessage *pmsg) | ||
511 | { | ||
512 | struct CadetClient *c = cls; | ||
513 | |||
514 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
515 | "Closing port %s as requested by %s\n", | ||
516 | GNUNET_h2s (&pmsg->port), | ||
517 | GSC_2s (c)); | ||
518 | if (GNUNET_YES != | ||
519 | GNUNET_CONTAINER_multihashmap_remove (c->ports, | ||
520 | &pmsg->port, | ||
521 | c)) | ||
522 | { | ||
523 | GNUNET_break (0); | ||
524 | GNUNET_SERVICE_client_drop (c->client); | ||
525 | return; | ||
526 | } | ||
527 | GNUNET_assert (GNUNET_YES == | ||
528 | GNUNET_CONTAINER_multihashmap_remove (open_ports, | ||
529 | &pmsg->port, | ||
530 | c)); | ||
531 | GNUNET_SERVICE_client_continue (c->client); | ||
532 | } | ||
533 | |||
534 | |||
535 | /** | ||
536 | * Handler for requests for us creating a new channel to another peer and port. | ||
537 | * | ||
538 | * @param cls Identification of the client. | ||
539 | * @param tcm The actual message. | ||
540 | */ | ||
541 | static void | ||
542 | handle_channel_create (void *cls, | ||
543 | const struct GNUNET_CADET_LocalChannelCreateMessage *tcm) | ||
544 | { | ||
545 | struct CadetClient *c = cls; | ||
546 | struct CadetChannel *ch; | ||
547 | |||
548 | if (ntohl (tcm->ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
549 | { | ||
550 | /* Channel ID not in allowed range. */ | ||
551 | GNUNET_break (0); | ||
552 | GNUNET_SERVICE_client_drop (c->client); | ||
553 | return; | ||
554 | } | ||
555 | ch = lookup_channel (c, | ||
556 | tcm->ccn); | ||
557 | if (NULL != ch) | ||
558 | { | ||
559 | /* Channel ID already in use. Not allowed. */ | ||
560 | GNUNET_break (0); | ||
561 | GNUNET_SERVICE_client_drop (c->client); | ||
562 | return; | ||
563 | } | ||
564 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
565 | "New channel to %s at port %s requested by %s\n", | ||
566 | GNUNET_i2s (&tcm->peer), | ||
567 | GNUNET_h2s (&tcm->port), | ||
568 | GSC_2s (c)); | ||
569 | |||
570 | /* Create channel */ | ||
571 | ch = GCCH_channel_local_new (c, | ||
572 | tcm->ccn, | ||
573 | GCP_get (&tcm->peer, | ||
574 | GNUNET_YES), | ||
575 | &tcm->port, | ||
576 | ntohl (tcm->opt)); | ||
577 | if (NULL == ch) | ||
578 | { | ||
579 | GNUNET_break (0); | ||
580 | GNUNET_SERVICE_client_drop (c->client); | ||
581 | return; | ||
582 | } | ||
583 | GNUNET_assert (GNUNET_YES == | ||
584 | GNUNET_CONTAINER_multihashmap32_put (c->channels, | ||
585 | ntohl (tcm->ccn.channel_of_client), | ||
586 | ch, | ||
587 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
588 | |||
589 | GNUNET_SERVICE_client_continue (c->client); | ||
590 | } | ||
591 | |||
592 | |||
593 | /** | ||
594 | * Handler for requests of destroying an existing channel. | ||
595 | * | ||
596 | * @param cls client identification of the client | ||
597 | * @param msg the actual message | ||
598 | */ | ||
599 | static void | ||
600 | handle_channel_destroy (void *cls, | ||
601 | const struct GNUNET_CADET_LocalChannelDestroyMessage *msg) | ||
602 | { | ||
603 | struct CadetClient *c = cls; | ||
604 | struct CadetChannel *ch; | ||
605 | |||
606 | ch = lookup_channel (c, | ||
607 | msg->ccn); | ||
608 | if (NULL == ch) | ||
609 | { | ||
610 | /* Client attempted to destroy unknown channel */ | ||
611 | GNUNET_break (0); | ||
612 | GNUNET_SERVICE_client_drop (c->client); | ||
613 | return; | ||
614 | } | ||
615 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
616 | "%s is destroying %s\n", | ||
617 | GSC_2s(c), | ||
618 | GCCH_2s (ch)); | ||
619 | GNUNET_assert (GNUNET_YES == | ||
620 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
621 | ntohl (msg->ccn.channel_of_client), | ||
622 | ch)); | ||
623 | GCCH_channel_local_destroy (ch, | ||
624 | c, | ||
625 | msg->ccn); | ||
626 | GNUNET_SERVICE_client_continue (c->client); | ||
627 | } | ||
628 | |||
629 | |||
630 | /** | ||
631 | * Check for client traffic data message is well-formed. | ||
632 | * | ||
633 | * @param cls identification of the client | ||
634 | * @param msg the actual message | ||
635 | * @return #GNUNET_OK if @a msg is OK, #GNUNET_SYSERR if not | ||
636 | */ | ||
637 | static int | ||
638 | check_local_data (void *cls, | ||
639 | const struct GNUNET_CADET_LocalData *msg) | ||
640 | { | ||
641 | size_t payload_size; | ||
642 | size_t payload_claimed_size; | ||
643 | const char *buf; | ||
644 | struct GNUNET_MessageHeader pa; | ||
645 | |||
646 | /* FIXME: what is the format we shall allow for @a msg? | ||
647 | ONE payload item or multiple? Seems current cadet_api | ||
648 | at least in theory allows more than one. Next-gen | ||
649 | cadet_api will likely no more, so we could then | ||
650 | simplify this mess again. */ | ||
651 | /* Sanity check for message size */ | ||
652 | payload_size = ntohs (msg->header.size) - sizeof (*msg); | ||
653 | buf = (const char *) &msg[1]; | ||
654 | while (payload_size >= sizeof (struct GNUNET_MessageHeader)) | ||
655 | { | ||
656 | /* need to memcpy() for alignment */ | ||
657 | GNUNET_memcpy (&pa, | ||
658 | buf, | ||
659 | sizeof (pa)); | ||
660 | payload_claimed_size = ntohs (pa.size); | ||
661 | if ( (payload_size < payload_claimed_size) || | ||
662 | (payload_claimed_size < sizeof (struct GNUNET_MessageHeader)) || | ||
663 | (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size) ) | ||
664 | { | ||
665 | GNUNET_break (0); | ||
666 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
667 | "Local data of %u total size had sub-message %u at %u with %u bytes\n", | ||
668 | ntohs (msg->header.size), | ||
669 | ntohs (pa.type), | ||
670 | (unsigned int) (buf - (const char *) &msg[1]), | ||
671 | (unsigned int) payload_claimed_size); | ||
672 | return GNUNET_SYSERR; | ||
673 | } | ||
674 | payload_size -= payload_claimed_size; | ||
675 | buf += payload_claimed_size; | ||
676 | } | ||
677 | if (0 != payload_size) | ||
678 | { | ||
679 | GNUNET_break_op (0); | ||
680 | return GNUNET_SYSERR; | ||
681 | } | ||
682 | return GNUNET_OK; | ||
683 | } | ||
684 | |||
685 | |||
686 | /** | ||
687 | * Handler for client payload traffic to be send on a channel to | ||
688 | * another peer. | ||
689 | * | ||
690 | * @param cls identification of the client | ||
691 | * @param msg the actual message | ||
692 | */ | ||
693 | static void | ||
694 | handle_local_data (void *cls, | ||
695 | const struct GNUNET_CADET_LocalData *msg) | ||
696 | { | ||
697 | struct CadetClient *c = cls; | ||
698 | struct CadetChannel *ch; | ||
699 | size_t payload_size; | ||
700 | const char *buf; | ||
701 | |||
702 | ch = lookup_channel (c, | ||
703 | msg->ccn); | ||
704 | if (NULL == ch) | ||
705 | { | ||
706 | /* Channel does not exist! */ | ||
707 | GNUNET_break (0); | ||
708 | GNUNET_SERVICE_client_drop (c->client); | ||
709 | return; | ||
710 | } | ||
711 | payload_size = ntohs (msg->header.size) - sizeof (*msg); | ||
712 | buf = (const char *) &msg[1]; | ||
713 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
714 | "Received %u bytes payload from %s for %s\n", | ||
715 | (unsigned int) payload_size, | ||
716 | GSC_2s (c), | ||
717 | GCCH_2s (ch)); | ||
718 | if (GNUNET_OK != | ||
719 | GCCH_handle_local_data (ch, | ||
720 | msg->ccn, | ||
721 | buf, | ||
722 | payload_size)) | ||
723 | { | ||
724 | GNUNET_SERVICE_client_drop (c->client); | ||
725 | return; | ||
726 | } | ||
727 | GNUNET_SERVICE_client_continue (c->client); | ||
728 | } | ||
729 | |||
730 | |||
731 | /** | ||
732 | * Handler for client's ACKs for payload traffic. | ||
733 | * | ||
734 | * @param cls identification of the client. | ||
735 | * @param msg The actual message. | ||
736 | */ | ||
737 | static void | ||
738 | handle_local_ack (void *cls, | ||
739 | const struct GNUNET_CADET_LocalAck *msg) | ||
740 | { | ||
741 | struct CadetClient *c = cls; | ||
742 | struct CadetChannel *ch; | ||
743 | |||
744 | ch = lookup_channel (c, | ||
745 | msg->ccn); | ||
746 | if (NULL == ch) | ||
747 | { | ||
748 | /* Channel does not exist! */ | ||
749 | GNUNET_break (0); | ||
750 | GNUNET_SERVICE_client_drop (c->client); | ||
751 | return; | ||
752 | } | ||
753 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
754 | "Got a local ACK from %s for %s\n", | ||
755 | GSC_2s(c), | ||
756 | GCCH_2s (ch)); | ||
757 | GCCH_handle_local_ack (ch, | ||
758 | msg->ccn); | ||
759 | GNUNET_SERVICE_client_continue (c->client); | ||
760 | } | ||
761 | |||
762 | |||
763 | /** | ||
764 | * Iterator over all peers to send a monitoring client info about each peer. | ||
765 | * | ||
766 | * @param cls Closure (). | ||
767 | * @param peer Peer ID (tunnel remote peer). | ||
768 | * @param value Peer info. | ||
769 | * @return #GNUNET_YES, to keep iterating. | ||
770 | */ | ||
771 | static int | ||
772 | get_all_peers_iterator (void *cls, | ||
773 | const struct GNUNET_PeerIdentity *peer, | ||
774 | void *value) | ||
775 | { | ||
776 | struct CadetClient *c = cls; | ||
777 | struct CadetPeer *p = value; | ||
778 | struct GNUNET_MQ_Envelope *env; | ||
779 | struct GNUNET_CADET_LocalInfoPeer *msg; | ||
780 | |||
781 | env = GNUNET_MQ_msg (msg, | ||
782 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
783 | msg->destination = *peer; | ||
784 | msg->paths = htons (GCP_count_paths (p)); | ||
785 | msg->tunnel = htons (NULL != GCP_get_tunnel (p, | ||
786 | GNUNET_NO)); | ||
787 | GNUNET_MQ_send (c->mq, | ||
788 | env); | ||
789 | return GNUNET_YES; | ||
790 | } | ||
791 | |||
792 | |||
793 | /** | ||
794 | * Handler for client's INFO PEERS request. | ||
795 | * | ||
796 | * @param cls Identification of the client. | ||
797 | * @param message The actual message. | ||
798 | */ | ||
799 | static void | ||
800 | handle_get_peers (void *cls, | ||
801 | const struct GNUNET_MessageHeader *message) | ||
802 | { | ||
803 | struct CadetClient *c = cls; | ||
804 | struct GNUNET_MQ_Envelope *env; | ||
805 | struct GNUNET_MessageHeader *reply; | ||
806 | |||
807 | GCP_iterate_all (&get_all_peers_iterator, | ||
808 | c); | ||
809 | env = GNUNET_MQ_msg (reply, | ||
810 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
811 | GNUNET_MQ_send (c->mq, | ||
812 | env); | ||
813 | GNUNET_SERVICE_client_continue (c->client); | ||
814 | } | ||
815 | |||
816 | |||
817 | /** | ||
818 | * Iterator over all paths of a peer to build an InfoPeer message. | ||
819 | * Message contains blocks of peers, first not included. | ||
820 | * | ||
821 | * @param cls message queue for transmission | ||
822 | * @param path Path itself | ||
823 | * @param off offset of the peer on @a path | ||
824 | * @return #GNUNET_YES if should keep iterating. | ||
825 | * #GNUNET_NO otherwise. | ||
826 | */ | ||
827 | static int | ||
828 | path_info_iterator (void *cls, | ||
829 | struct CadetPeerPath *path, | ||
830 | unsigned int off) | ||
831 | { | ||
832 | struct GNUNET_MQ_Handle *mq = cls; | ||
833 | struct GNUNET_MQ_Envelope *env; | ||
834 | struct GNUNET_MessageHeader *resp; | ||
835 | struct GNUNET_PeerIdentity *id; | ||
836 | uint16_t path_size; | ||
837 | unsigned int i; | ||
838 | unsigned int path_length; | ||
839 | |||
840 | path_length = GCPP_get_length (path); | ||
841 | path_size = sizeof (struct GNUNET_PeerIdentity) * (path_length - 1); | ||
842 | if (sizeof (*resp) + path_size > UINT16_MAX) | ||
843 | { | ||
844 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
845 | "Path of %u entries is too long for info message\n", | ||
846 | path_length); | ||
847 | return GNUNET_YES; | ||
848 | } | ||
849 | env = GNUNET_MQ_msg_extra (resp, | ||
850 | path_size, | ||
851 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); | ||
852 | id = (struct GNUNET_PeerIdentity *) &resp[1]; | ||
853 | |||
854 | /* Don't copy first peer. First peer is always the local one. Last | ||
855 | * peer is always the destination (leave as 0, EOL). | ||
856 | */ | ||
857 | for (i = 0; i < off; i++) | ||
858 | id[i] = *GCP_get_id (GCPP_get_peer_at_offset (path, | ||
859 | i + 1)); | ||
860 | GNUNET_MQ_send (mq, | ||
861 | env); | ||
862 | return GNUNET_YES; | ||
863 | } | ||
864 | |||
865 | |||
866 | /** | ||
867 | * Handler for client's SHOW_PEER request. | ||
868 | * | ||
869 | * @param cls Identification of the client. | ||
870 | * @param msg The actual message. | ||
871 | */ | ||
872 | static void | ||
873 | handle_show_peer (void *cls, | ||
874 | const struct GNUNET_CADET_LocalInfo *msg) | ||
875 | { | ||
876 | struct CadetClient *c = cls; | ||
877 | struct CadetPeer *p; | ||
878 | struct GNUNET_MQ_Envelope *env; | ||
879 | struct GNUNET_MessageHeader *resp; | ||
880 | |||
881 | p = GCP_get (&msg->peer, | ||
882 | GNUNET_NO); | ||
883 | if (NULL != p) | ||
884 | GCP_iterate_paths (p, | ||
885 | &path_info_iterator, | ||
886 | c->mq); | ||
887 | /* Send message with 0/0 to indicate the end */ | ||
888 | env = GNUNET_MQ_msg (resp, | ||
889 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER_END); | ||
890 | GNUNET_MQ_send (c->mq, | ||
891 | env); | ||
892 | GNUNET_SERVICE_client_continue (c->client); | ||
893 | } | ||
894 | |||
895 | |||
896 | /** | ||
897 | * Iterator over all tunnels to send a monitoring client info about each tunnel. | ||
898 | * | ||
899 | * @param cls Closure (). | ||
900 | * @param peer Peer ID (tunnel remote peer). | ||
901 | * @param value a `struct CadetPeer` | ||
902 | * @return #GNUNET_YES, to keep iterating. | ||
903 | */ | ||
904 | static int | ||
905 | get_all_tunnels_iterator (void *cls, | ||
906 | const struct GNUNET_PeerIdentity *peer, | ||
907 | void *value) | ||
908 | { | ||
909 | struct CadetClient *c = cls; | ||
910 | struct CadetPeer *p = value; | ||
911 | struct GNUNET_MQ_Envelope *env; | ||
912 | struct GNUNET_CADET_LocalInfoTunnel *msg; | ||
913 | struct CadetTunnel *t; | ||
914 | |||
915 | t = GCP_get_tunnel (p, | ||
916 | GNUNET_NO); | ||
917 | if (NULL == t) | ||
918 | return GNUNET_YES; | ||
919 | env = GNUNET_MQ_msg (msg, | ||
920 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
921 | msg->destination = *peer; | ||
922 | msg->channels = htonl (GCT_count_channels (t)); | ||
923 | msg->connections = htonl (GCT_count_any_connections (t)); | ||
924 | msg->cstate = htons (0); | ||
925 | msg->estate = htons ((uint16_t) GCT_get_estate (t)); | ||
926 | GNUNET_MQ_send (c->mq, | ||
927 | env); | ||
928 | return GNUNET_YES; | ||
929 | } | ||
930 | |||
931 | |||
932 | /** | ||
933 | * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS request. | ||
934 | * | ||
935 | * @param cls client Identification of the client. | ||
936 | * @param message The actual message. | ||
937 | */ | ||
938 | static void | ||
939 | handle_info_tunnels (void *cls, | ||
940 | const struct GNUNET_MessageHeader *message) | ||
941 | { | ||
942 | struct CadetClient *c = cls; | ||
943 | struct GNUNET_MQ_Envelope *env; | ||
944 | struct GNUNET_MessageHeader *reply; | ||
945 | |||
946 | GCP_iterate_all (&get_all_tunnels_iterator, | ||
947 | c); | ||
948 | env = GNUNET_MQ_msg (reply, | ||
949 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
950 | GNUNET_MQ_send (c->mq, | ||
951 | env); | ||
952 | GNUNET_SERVICE_client_continue (c->client); | ||
953 | } | ||
954 | |||
955 | |||
956 | /** | ||
957 | * Update the message with information about the connection. | ||
958 | * | ||
959 | * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update | ||
960 | * @param c a connection about which we should store information in @a cls | ||
961 | */ | ||
962 | static void | ||
963 | iter_connection (void *cls, | ||
964 | struct CadetConnection *c) | ||
965 | { | ||
966 | struct GNUNET_CADET_LocalInfoTunnel *msg = cls; | ||
967 | struct GNUNET_CADET_ConnectionTunnelIdentifier *h; | ||
968 | |||
969 | h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1]; | ||
970 | h[msg->connections++] = *(GCC_get_id (c)); | ||
971 | } | ||
972 | |||
973 | |||
974 | /** | ||
975 | * Update the message with information about the channel. | ||
976 | * | ||
977 | * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update | ||
978 | * @param ch a channel about which we should store information in @a cls | ||
979 | */ | ||
980 | static void | ||
981 | iter_channel (void *cls, | ||
982 | struct CadetChannel *ch) | ||
983 | { | ||
984 | struct GNUNET_CADET_LocalInfoTunnel *msg = cls; | ||
985 | struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1]; | ||
986 | struct GNUNET_CADET_ChannelTunnelNumber *chn | ||
987 | = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections]; | ||
988 | |||
989 | chn[msg->channels++] = GCCH_get_id (ch); | ||
990 | } | ||
991 | |||
992 | |||
993 | /** | ||
994 | * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL request. | ||
995 | * | ||
996 | * @param cls Identification of the client. | ||
997 | * @param msg The actual message. | ||
998 | */ | ||
999 | static void | ||
1000 | handle_info_tunnel (void *cls, | ||
1001 | const struct GNUNET_CADET_LocalInfo *msg) | ||
1002 | { | ||
1003 | struct CadetClient *c = cls; | ||
1004 | struct GNUNET_MQ_Envelope *env; | ||
1005 | struct GNUNET_CADET_LocalInfoTunnel *resp; | ||
1006 | struct CadetTunnel *t; | ||
1007 | struct CadetPeer *p; | ||
1008 | unsigned int ch_n; | ||
1009 | unsigned int c_n; | ||
1010 | |||
1011 | p = GCP_get (&msg->peer, | ||
1012 | GNUNET_NO); | ||
1013 | t = GCP_get_tunnel (p, | ||
1014 | GNUNET_NO); | ||
1015 | if (NULL == t) | ||
1016 | { | ||
1017 | /* We don't know the tunnel */ | ||
1018 | struct GNUNET_MQ_Envelope *env; | ||
1019 | struct GNUNET_CADET_LocalInfoTunnel *warn; | ||
1020 | |||
1021 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1022 | "Tunnel to %s unknown\n", | ||
1023 | GNUNET_i2s_full (&msg->peer)); | ||
1024 | env = GNUNET_MQ_msg (warn, | ||
1025 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
1026 | warn->destination = msg->peer; | ||
1027 | GNUNET_MQ_send (c->mq, | ||
1028 | env); | ||
1029 | GNUNET_SERVICE_client_continue (c->client); | ||
1030 | return; | ||
1031 | } | ||
1032 | |||
1033 | /* Initialize context */ | ||
1034 | ch_n = GCT_count_channels (t); | ||
1035 | c_n = GCT_count_any_connections (t); | ||
1036 | env = GNUNET_MQ_msg_extra (resp, | ||
1037 | c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier) + | ||
1038 | ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber), | ||
1039 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
1040 | resp->destination = msg->peer; | ||
1041 | /* Do not reorder! #iter_channel needs counters in HBO! */ | ||
1042 | GCT_iterate_connections (t, | ||
1043 | &iter_connection, | ||
1044 | resp); | ||
1045 | GCT_iterate_channels (t, | ||
1046 | &iter_channel, | ||
1047 | resp); | ||
1048 | resp->connections = htonl (resp->connections); | ||
1049 | resp->channels = htonl (resp->channels); | ||
1050 | resp->cstate = htons (0); | ||
1051 | resp->estate = htons (GCT_get_estate (t)); | ||
1052 | GNUNET_MQ_send (c->mq, | ||
1053 | env); | ||
1054 | GNUNET_SERVICE_client_continue (c->client); | ||
1055 | } | ||
1056 | |||
1057 | |||
1058 | /** | ||
1059 | * Iterator over all peers to dump info for each peer. | ||
1060 | * | ||
1061 | * @param cls Closure (unused). | ||
1062 | * @param peer Peer ID (tunnel remote peer). | ||
1063 | * @param value Peer info. | ||
1064 | * | ||
1065 | * @return #GNUNET_YES, to keep iterating. | ||
1066 | */ | ||
1067 | static int | ||
1068 | show_peer_iterator (void *cls, | ||
1069 | const struct GNUNET_PeerIdentity *peer, | ||
1070 | void *value) | ||
1071 | { | ||
1072 | struct CadetPeer *p = value; | ||
1073 | struct CadetTunnel *t; | ||
1074 | |||
1075 | t = GCP_get_tunnel (p, | ||
1076 | GNUNET_NO); | ||
1077 | if (NULL != t) | ||
1078 | GCT_debug (t, | ||
1079 | GNUNET_ERROR_TYPE_ERROR); | ||
1080 | LOG (GNUNET_ERROR_TYPE_ERROR, "\n"); | ||
1081 | return GNUNET_YES; | ||
1082 | } | ||
1083 | |||
1084 | |||
1085 | /** | ||
1086 | * Handler for client's INFO_DUMP request. | ||
1087 | * | ||
1088 | * @param cls Identification of the client. | ||
1089 | * @param message The actual message. | ||
1090 | */ | ||
1091 | static void | ||
1092 | handle_info_dump (void *cls, | ||
1093 | const struct GNUNET_MessageHeader *message) | ||
1094 | { | ||
1095 | struct CadetClient *c = cls; | ||
1096 | |||
1097 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1098 | "Received dump info request from client %u\n", | ||
1099 | c->id); | ||
1100 | |||
1101 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1102 | "*************************** DUMP START ***************************\n"); | ||
1103 | for (struct CadetClient *ci = clients_head; | ||
1104 | NULL != ci; | ||
1105 | ci = ci->next) | ||
1106 | { | ||
1107 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1108 | "Client %u (%p), handle: %p, ports: %u, channels: %u\n", | ||
1109 | ci->id, | ||
1110 | ci, | ||
1111 | ci->client, | ||
1112 | (NULL != c->ports) | ||
1113 | ? GNUNET_CONTAINER_multihashmap_size (ci->ports) | ||
1114 | : 0, | ||
1115 | GNUNET_CONTAINER_multihashmap32_size (ci->channels)); | ||
1116 | } | ||
1117 | LOG (GNUNET_ERROR_TYPE_ERROR, "***************************\n"); | ||
1118 | GCP_iterate_all (&show_peer_iterator, | ||
1119 | NULL); | ||
1120 | |||
1121 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1122 | "**************************** DUMP END ****************************\n"); | ||
1123 | |||
1124 | GNUNET_SERVICE_client_continue (c->client); | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | |||
1129 | /** | ||
1130 | * Callback called when a client connects to the service. | ||
1131 | * | ||
1132 | * @param cls closure for the service | ||
1133 | * @param client the new client that connected to the service | ||
1134 | * @param mq the message queue used to send messages to the client | ||
1135 | * @return @a c | ||
1136 | */ | ||
1137 | static void * | ||
1138 | client_connect_cb (void *cls, | ||
1139 | struct GNUNET_SERVICE_Client *client, | ||
1140 | struct GNUNET_MQ_Handle *mq) | ||
1141 | { | ||
1142 | struct CadetClient *c; | ||
1143 | |||
1144 | c = GNUNET_new (struct CadetClient); | ||
1145 | c->client = client; | ||
1146 | c->mq = mq; | ||
1147 | c->id = next_client_id++; /* overflow not important: just for debug */ | ||
1148 | c->channels | ||
1149 | = GNUNET_CONTAINER_multihashmap32_create (32); | ||
1150 | GNUNET_CONTAINER_DLL_insert (clients_head, | ||
1151 | clients_tail, | ||
1152 | c); | ||
1153 | GNUNET_STATISTICS_update (stats, | ||
1154 | "# clients", | ||
1155 | +1, | ||
1156 | GNUNET_NO); | ||
1157 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1158 | "%s connected\n", | ||
1159 | GSC_2s (c)); | ||
1160 | return c; | ||
1161 | } | ||
1162 | |||
1163 | |||
1164 | /** | ||
1165 | * A channel was destroyed by the other peer. Tell our client. | ||
1166 | * | ||
1167 | * @param c client that lost a channel | ||
1168 | * @param ccn channel identification number for the client | ||
1169 | * @param ch the channel object | ||
1170 | */ | ||
1171 | void | ||
1172 | GSC_handle_remote_channel_destroy (struct CadetClient *c, | ||
1173 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
1174 | struct CadetChannel *ch) | ||
1175 | { | ||
1176 | struct GNUNET_MQ_Envelope *env; | ||
1177 | struct GNUNET_CADET_LocalChannelDestroyMessage *tdm; | ||
1178 | |||
1179 | env = GNUNET_MQ_msg (tdm, | ||
1180 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
1181 | tdm->ccn = ccn; | ||
1182 | GSC_send_to_client (c, | ||
1183 | env); | ||
1184 | GNUNET_assert (GNUNET_YES == | ||
1185 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
1186 | ntohl (ccn.channel_of_client), | ||
1187 | ch)); | ||
1188 | } | ||
1189 | |||
1190 | |||
1191 | /** | ||
1192 | * Iterator for deleting each channel whose client endpoint disconnected. | ||
1193 | * | ||
1194 | * @param cls Closure (client that has disconnected). | ||
1195 | * @param key The local channel id in host byte order | ||
1196 | * @param value The value stored at the key (channel to destroy). | ||
1197 | * @return #GNUNET_OK, keep iterating. | ||
1198 | */ | ||
1199 | static int | ||
1200 | channel_destroy_iterator (void *cls, | ||
1201 | uint32_t key, | ||
1202 | void *value) | ||
1203 | { | ||
1204 | struct CadetClient *c = cls; | ||
1205 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
1206 | struct CadetChannel *ch = value; | ||
1207 | |||
1208 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1209 | "Destroying %s, due to %s disconnecting.\n", | ||
1210 | GCCH_2s (ch), | ||
1211 | GSC_2s (c)); | ||
1212 | GNUNET_assert (GNUNET_YES == | ||
1213 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
1214 | key, | ||
1215 | ch)); | ||
1216 | ccn.channel_of_client = htonl (key); | ||
1217 | GCCH_channel_local_destroy (ch, | ||
1218 | c, | ||
1219 | ccn); | ||
1220 | return GNUNET_OK; | ||
1221 | } | ||
1222 | |||
1223 | |||
1224 | /** | ||
1225 | * Remove client's ports from the global hashmap on disconnect. | ||
1226 | * | ||
1227 | * @param cls Closure (unused). | ||
1228 | * @param key the port. | ||
1229 | * @param value the `struct CadetClient` to remove | ||
1230 | * @return #GNUNET_OK, keep iterating. | ||
1231 | */ | ||
1232 | static int | ||
1233 | client_release_ports (void *cls, | ||
1234 | const struct GNUNET_HashCode *key, | ||
1235 | void *value) | ||
1236 | { | ||
1237 | struct CadetClient *c = value; | ||
1238 | |||
1239 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1240 | "Closing port %s due to %s disconnect.\n", | ||
1241 | GNUNET_h2s (key), | ||
1242 | GSC_2s (c)); | ||
1243 | GNUNET_assert (GNUNET_YES == | ||
1244 | GNUNET_CONTAINER_multihashmap_remove (open_ports, | ||
1245 | key, | ||
1246 | value)); | ||
1247 | GNUNET_assert (GNUNET_YES == | ||
1248 | GNUNET_CONTAINER_multihashmap_remove (c->ports, | ||
1249 | key, | ||
1250 | value)); | ||
1251 | return GNUNET_OK; | ||
1252 | } | ||
1253 | |||
1254 | |||
1255 | /** | ||
1256 | * Callback called when a client disconnected from the service | ||
1257 | * | ||
1258 | * @param cls closure for the service | ||
1259 | * @param client the client that disconnected | ||
1260 | * @param internal_cls should be equal to @a c | ||
1261 | */ | ||
1262 | static void | ||
1263 | client_disconnect_cb (void *cls, | ||
1264 | struct GNUNET_SERVICE_Client *client, | ||
1265 | void *internal_cls) | ||
1266 | { | ||
1267 | struct CadetClient *c = internal_cls; | ||
1268 | |||
1269 | GNUNET_assert (c->client == client); | ||
1270 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1271 | "%s is disconnecting.\n", | ||
1272 | GSC_2s (c)); | ||
1273 | if (NULL != c->channels) | ||
1274 | { | ||
1275 | GNUNET_CONTAINER_multihashmap32_iterate (c->channels, | ||
1276 | &channel_destroy_iterator, | ||
1277 | c); | ||
1278 | GNUNET_CONTAINER_multihashmap32_destroy (c->channels); | ||
1279 | } | ||
1280 | if (NULL != c->ports) | ||
1281 | { | ||
1282 | GNUNET_CONTAINER_multihashmap_iterate (c->ports, | ||
1283 | &client_release_ports, | ||
1284 | c); | ||
1285 | GNUNET_CONTAINER_multihashmap_destroy (c->ports); | ||
1286 | } | ||
1287 | GNUNET_CONTAINER_DLL_remove (clients_head, | ||
1288 | clients_tail, | ||
1289 | c); | ||
1290 | GNUNET_STATISTICS_update (stats, | ||
1291 | "# clients", | ||
1292 | -1, | ||
1293 | GNUNET_NO); | ||
1294 | GNUNET_free (c); | ||
1295 | if ( (NULL == clients_head) && | ||
1296 | (GNUNET_YES == shutting_down) ) | ||
1297 | shutdown_rest (); | ||
1298 | } | ||
1299 | |||
1300 | |||
1301 | /** | ||
1302 | * Setup CADET internals. | ||
1303 | * | ||
1304 | * @param cls closure | ||
1305 | * @param server the initialized server | ||
1306 | * @param c configuration to use | ||
1307 | */ | ||
1308 | static void | ||
1309 | run (void *cls, | ||
1310 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
1311 | struct GNUNET_SERVICE_Handle *service) | ||
1312 | { | ||
1313 | cfg = c; | ||
1314 | if (GNUNET_OK != | ||
1315 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1316 | "CADET", | ||
1317 | "RATCHET_MESSAGES", | ||
1318 | &ratchet_messages)) | ||
1319 | { | ||
1320 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1321 | "CADET", | ||
1322 | "RATCHET_MESSAGES", | ||
1323 | "needs to be a number"); | ||
1324 | ratchet_messages = 64; | ||
1325 | } | ||
1326 | if (GNUNET_OK != | ||
1327 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1328 | "CADET", | ||
1329 | "RATCHET_TIME", | ||
1330 | &ratchet_time)) | ||
1331 | { | ||
1332 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1333 | "CADET", | ||
1334 | "RATCHET_TIME", | ||
1335 | "need delay value"); | ||
1336 | ratchet_time = GNUNET_TIME_UNIT_HOURS; | ||
1337 | } | ||
1338 | |||
1339 | my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c); | ||
1340 | if (NULL == my_private_key) | ||
1341 | { | ||
1342 | GNUNET_break (0); | ||
1343 | GNUNET_SCHEDULER_shutdown (); | ||
1344 | return; | ||
1345 | } | ||
1346 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, | ||
1347 | &my_full_id.public_key); | ||
1348 | stats = GNUNET_STATISTICS_create ("cadet", | ||
1349 | c); | ||
1350 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | ||
1351 | NULL); | ||
1352 | ats_ch = GNUNET_ATS_connectivity_init (c); | ||
1353 | /* FIXME: optimize code to allow GNUNET_YES here! */ | ||
1354 | open_ports = GNUNET_CONTAINER_multihashmap_create (16, | ||
1355 | GNUNET_NO); | ||
1356 | loose_channels = GNUNET_CONTAINER_multihashmap_create (16, | ||
1357 | GNUNET_NO); | ||
1358 | peers = GNUNET_CONTAINER_multipeermap_create (16, | ||
1359 | GNUNET_YES); | ||
1360 | connections = GNUNET_CONTAINER_multishortmap_create (256, | ||
1361 | GNUNET_YES); | ||
1362 | GCH_init (c); | ||
1363 | GCD_init (c); | ||
1364 | GCO_init (c); | ||
1365 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1366 | "CADET started for peer %s\n", | ||
1367 | GNUNET_i2s (&my_full_id)); | ||
1368 | |||
1369 | } | ||
1370 | |||
1371 | |||
1372 | /** | ||
1373 | * Define "main" method using service macro. | ||
1374 | */ | ||
1375 | GNUNET_SERVICE_MAIN | ||
1376 | ("cadet", | ||
1377 | GNUNET_SERVICE_OPTION_NONE, | ||
1378 | &run, | ||
1379 | &client_connect_cb, | ||
1380 | &client_disconnect_cb, | ||
1381 | NULL, | ||
1382 | GNUNET_MQ_hd_fixed_size (port_open, | ||
1383 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN, | ||
1384 | struct GNUNET_CADET_PortMessage, | ||
1385 | NULL), | ||
1386 | GNUNET_MQ_hd_fixed_size (port_close, | ||
1387 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE, | ||
1388 | struct GNUNET_CADET_PortMessage, | ||
1389 | NULL), | ||
1390 | GNUNET_MQ_hd_fixed_size (channel_create, | ||
1391 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE, | ||
1392 | struct GNUNET_CADET_LocalChannelCreateMessage, | ||
1393 | NULL), | ||
1394 | GNUNET_MQ_hd_fixed_size (channel_destroy, | ||
1395 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY, | ||
1396 | struct GNUNET_CADET_LocalChannelDestroyMessage, | ||
1397 | NULL), | ||
1398 | GNUNET_MQ_hd_var_size (local_data, | ||
1399 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, | ||
1400 | struct GNUNET_CADET_LocalData, | ||
1401 | NULL), | ||
1402 | GNUNET_MQ_hd_fixed_size (local_ack, | ||
1403 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, | ||
1404 | struct GNUNET_CADET_LocalAck, | ||
1405 | NULL), | ||
1406 | GNUNET_MQ_hd_fixed_size (get_peers, | ||
1407 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, | ||
1408 | struct GNUNET_MessageHeader, | ||
1409 | NULL), | ||
1410 | GNUNET_MQ_hd_fixed_size (show_peer, | ||
1411 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER, | ||
1412 | struct GNUNET_CADET_LocalInfo, | ||
1413 | NULL), | ||
1414 | GNUNET_MQ_hd_fixed_size (info_tunnels, | ||
1415 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS, | ||
1416 | struct GNUNET_MessageHeader, | ||
1417 | NULL), | ||
1418 | GNUNET_MQ_hd_fixed_size (info_tunnel, | ||
1419 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL, | ||
1420 | struct GNUNET_CADET_LocalInfo, | ||
1421 | NULL), | ||
1422 | GNUNET_MQ_hd_fixed_size (info_dump, | ||
1423 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP, | ||
1424 | struct GNUNET_MessageHeader, | ||
1425 | NULL), | ||
1426 | GNUNET_MQ_handler_end ()); | ||
1427 | |||
1428 | /* end of gnunet-service-cadet-new.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new_channel.c b/src/cadet/gnunet-service-cadet-new_channel.c deleted file mode 100644 index 0c6241817..000000000 --- a/src/cadet/gnunet-service-cadet-new_channel.c +++ /dev/null | |||
@@ -1,1613 +0,0 @@ | |||
1 | |||
2 | /* | ||
3 | This file is part of GNUnet. | ||
4 | Copyright (C) 2001-2017 GNUnet e.V. | ||
5 | |||
6 | GNUnet is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published | ||
8 | by the Free Software Foundation; either version 3, or (at your | ||
9 | option) any later version. | ||
10 | |||
11 | GNUnet is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNUnet; see the file COPYING. If not, write to the | ||
18 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
19 | Boston, MA 02110-1301, USA. | ||
20 | */ | ||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet-new_channel.c | ||
23 | * @brief logical links between CADET clients | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * TODO: | ||
28 | * - FIXME: send ACKs back to loopback clients! | ||
29 | * | ||
30 | * - introduce shutdown so we can have half-closed channels, modify | ||
31 | * destroy to include MID to have FIN-ACK equivalents, etc. | ||
32 | * - estimate max bandwidth using bursts and use to for CONGESTION CONTROL! | ||
33 | * - check that '0xFFULL' really is sufficient for flow control! | ||
34 | * - revisit handling of 'unreliable' traffic! | ||
35 | * - revisit handling of 'out-of-order' option, especially in combination with/without 'reliable'. | ||
36 | * - figure out flow control without ACKs (unreliable traffic!) | ||
37 | */ | ||
38 | #include "platform.h" | ||
39 | #include "gnunet_util_lib.h" | ||
40 | #include "cadet.h" | ||
41 | #include "gnunet_statistics_service.h" | ||
42 | #include "gnunet-service-cadet-new.h" | ||
43 | #include "gnunet-service-cadet-new_channel.h" | ||
44 | #include "gnunet-service-cadet-new_connection.h" | ||
45 | #include "gnunet-service-cadet-new_tunnels.h" | ||
46 | #include "gnunet-service-cadet-new_peer.h" | ||
47 | #include "gnunet-service-cadet-new_paths.h" | ||
48 | |||
49 | #define LOG(level,...) GNUNET_log_from (level,"cadet-chn",__VA_ARGS__) | ||
50 | |||
51 | /** | ||
52 | * How long do we initially wait before retransmitting? | ||
53 | */ | ||
54 | #define CADET_INITIAL_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250) | ||
55 | |||
56 | /** | ||
57 | * How long do we wait before dropping state about incoming | ||
58 | * connection to closed port? | ||
59 | */ | ||
60 | #define TIMEOUT_CLOSED_PORT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30) | ||
61 | |||
62 | |||
63 | /** | ||
64 | * All the states a connection can be in. | ||
65 | */ | ||
66 | enum CadetChannelState | ||
67 | { | ||
68 | /** | ||
69 | * Uninitialized status, should never appear in operation. | ||
70 | */ | ||
71 | CADET_CHANNEL_NEW, | ||
72 | |||
73 | /** | ||
74 | * Connection create message sent, waiting for ACK. | ||
75 | */ | ||
76 | CADET_CHANNEL_OPEN_SENT, | ||
77 | |||
78 | /** | ||
79 | * Connection confirmed, ready to carry traffic. | ||
80 | */ | ||
81 | CADET_CHANNEL_READY | ||
82 | }; | ||
83 | |||
84 | |||
85 | /** | ||
86 | * Info needed to retry a message in case it gets lost. | ||
87 | * Note that we DO use this structure also for unreliable | ||
88 | * messages. | ||
89 | */ | ||
90 | struct CadetReliableMessage | ||
91 | { | ||
92 | /** | ||
93 | * Double linked list, FIFO style | ||
94 | */ | ||
95 | struct CadetReliableMessage *next; | ||
96 | |||
97 | /** | ||
98 | * Double linked list, FIFO style | ||
99 | */ | ||
100 | struct CadetReliableMessage *prev; | ||
101 | |||
102 | /** | ||
103 | * Which channel is this message in? | ||
104 | */ | ||
105 | struct CadetChannel *ch; | ||
106 | |||
107 | /** | ||
108 | * Entry in the tunnels queue for this message, NULL if it has left | ||
109 | * the tunnel. Used to cancel transmission in case we receive an | ||
110 | * ACK in time. | ||
111 | */ | ||
112 | struct CadetTunnelQueueEntry *qe; | ||
113 | |||
114 | /** | ||
115 | * How soon should we retry if we fail to get an ACK? | ||
116 | * Messages in the queue are sorted by this value. | ||
117 | */ | ||
118 | struct GNUNET_TIME_Absolute next_retry; | ||
119 | |||
120 | /** | ||
121 | * How long do we wait for an ACK after transmission? | ||
122 | * Use for the back-off calculation. | ||
123 | */ | ||
124 | struct GNUNET_TIME_Relative retry_delay; | ||
125 | |||
126 | /** | ||
127 | * Data message we are trying to send. | ||
128 | */ | ||
129 | struct GNUNET_CADET_ChannelAppDataMessage *data_message; | ||
130 | |||
131 | }; | ||
132 | |||
133 | |||
134 | /** | ||
135 | * List of received out-of-order data messages. | ||
136 | */ | ||
137 | struct CadetOutOfOrderMessage | ||
138 | { | ||
139 | /** | ||
140 | * Double linked list, FIFO style | ||
141 | */ | ||
142 | struct CadetOutOfOrderMessage *next; | ||
143 | |||
144 | /** | ||
145 | * Double linked list, FIFO style | ||
146 | */ | ||
147 | struct CadetOutOfOrderMessage *prev; | ||
148 | |||
149 | /** | ||
150 | * ID of the message (messages up to this point needed | ||
151 | * before we give this one to the client). | ||
152 | */ | ||
153 | struct ChannelMessageIdentifier mid; | ||
154 | |||
155 | /** | ||
156 | * The envelope with the payload of the out-of-order message | ||
157 | */ | ||
158 | struct GNUNET_MQ_Envelope *env; | ||
159 | |||
160 | }; | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Client endpoint of a `struct CadetChannel`. A channel may be a | ||
165 | * loopback channel, in which case it has two of these endpoints. | ||
166 | * Note that flow control also is required in both directions. | ||
167 | */ | ||
168 | struct CadetChannelClient | ||
169 | { | ||
170 | /** | ||
171 | * Client handle. Not by itself sufficient to designate | ||
172 | * the client endpoint, as the same client handle may | ||
173 | * be used for both the owner and the destination, and | ||
174 | * we thus also need the channel ID to identify the client. | ||
175 | */ | ||
176 | struct CadetClient *c; | ||
177 | |||
178 | /** | ||
179 | * Head of DLL of messages received out of order or while client was unready. | ||
180 | */ | ||
181 | struct CadetOutOfOrderMessage *head_recv; | ||
182 | |||
183 | /** | ||
184 | * Tail DLL of messages received out of order or while client was unready. | ||
185 | */ | ||
186 | struct CadetOutOfOrderMessage *tail_recv; | ||
187 | |||
188 | /** | ||
189 | * Local tunnel number for this client. | ||
190 | * (if owner >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI, | ||
191 | * otherwise < #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
192 | */ | ||
193 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
194 | |||
195 | /** | ||
196 | * Can we send data to the client? | ||
197 | */ | ||
198 | int client_ready; | ||
199 | |||
200 | }; | ||
201 | |||
202 | |||
203 | /** | ||
204 | * Struct containing all information regarding a channel to a remote client. | ||
205 | */ | ||
206 | struct CadetChannel | ||
207 | { | ||
208 | /** | ||
209 | * Tunnel this channel is in. | ||
210 | */ | ||
211 | struct CadetTunnel *t; | ||
212 | |||
213 | /** | ||
214 | * Client owner of the tunnel, if any. | ||
215 | * (Used if this channel represends the initiating end of the tunnel.) | ||
216 | */ | ||
217 | struct CadetChannelClient *owner; | ||
218 | |||
219 | /** | ||
220 | * Client destination of the tunnel, if any. | ||
221 | * (Used if this channel represents the listening end of the tunnel.) | ||
222 | */ | ||
223 | struct CadetChannelClient *dest; | ||
224 | |||
225 | /** | ||
226 | * Last entry in the tunnel's queue relating to control messages | ||
227 | * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or | ||
228 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel | ||
229 | * transmission in case we receive updated information. | ||
230 | */ | ||
231 | struct CadetTunnelQueueEntry *last_control_qe; | ||
232 | |||
233 | /** | ||
234 | * Head of DLL of messages sent and not yet ACK'd. | ||
235 | */ | ||
236 | struct CadetReliableMessage *head_sent; | ||
237 | |||
238 | /** | ||
239 | * Tail of DLL of messages sent and not yet ACK'd. | ||
240 | */ | ||
241 | struct CadetReliableMessage *tail_sent; | ||
242 | |||
243 | /** | ||
244 | * Task to resend/poll in case no ACK is received. | ||
245 | */ | ||
246 | struct GNUNET_SCHEDULER_Task *retry_control_task; | ||
247 | |||
248 | /** | ||
249 | * Task to resend/poll in case no ACK is received. | ||
250 | */ | ||
251 | struct GNUNET_SCHEDULER_Task *retry_data_task; | ||
252 | |||
253 | /** | ||
254 | * Last time the channel was used | ||
255 | */ | ||
256 | struct GNUNET_TIME_Absolute timestamp; | ||
257 | |||
258 | /** | ||
259 | * Destination port of the channel. | ||
260 | */ | ||
261 | struct GNUNET_HashCode port; | ||
262 | |||
263 | /** | ||
264 | * Counter for exponential backoff. | ||
265 | */ | ||
266 | struct GNUNET_TIME_Relative retry_time; | ||
267 | |||
268 | /** | ||
269 | * How long does it usually take to get an ACK. | ||
270 | */ | ||
271 | struct GNUNET_TIME_Relative expected_delay; | ||
272 | |||
273 | /** | ||
274 | * Bitfield of already-received messages past @e mid_recv. | ||
275 | */ | ||
276 | uint64_t mid_futures; | ||
277 | |||
278 | /** | ||
279 | * Next MID expected for incoming traffic. | ||
280 | */ | ||
281 | struct ChannelMessageIdentifier mid_recv; | ||
282 | |||
283 | /** | ||
284 | * Next MID to use for outgoing traffic. | ||
285 | */ | ||
286 | struct ChannelMessageIdentifier mid_send; | ||
287 | |||
288 | /** | ||
289 | * Total (reliable) messages pending ACK for this channel. | ||
290 | */ | ||
291 | unsigned int pending_messages; | ||
292 | |||
293 | /** | ||
294 | * Maximum (reliable) messages pending ACK for this channel | ||
295 | * before we throttle the client. | ||
296 | */ | ||
297 | unsigned int max_pending_messages; | ||
298 | |||
299 | /** | ||
300 | * Number identifying this channel in its tunnel. | ||
301 | */ | ||
302 | struct GNUNET_CADET_ChannelTunnelNumber ctn; | ||
303 | |||
304 | /** | ||
305 | * Channel state. | ||
306 | */ | ||
307 | enum CadetChannelState state; | ||
308 | |||
309 | /** | ||
310 | * Is the tunnel bufferless (minimum latency)? | ||
311 | */ | ||
312 | int nobuffer; | ||
313 | |||
314 | /** | ||
315 | * Is the tunnel reliable? | ||
316 | */ | ||
317 | int reliable; | ||
318 | |||
319 | /** | ||
320 | * Is the tunnel out-of-order? | ||
321 | */ | ||
322 | int out_of_order; | ||
323 | |||
324 | /** | ||
325 | * Is this channel a loopback channel, where the destination is us again? | ||
326 | */ | ||
327 | int is_loopback; | ||
328 | |||
329 | /** | ||
330 | * Flag to signal the destruction of the channel. If this is set to | ||
331 | * #GNUNET_YES the channel will be destroyed once the queue is | ||
332 | * empty. | ||
333 | */ | ||
334 | int destroy; | ||
335 | |||
336 | }; | ||
337 | |||
338 | |||
339 | /** | ||
340 | * Get the static string for identification of the channel. | ||
341 | * | ||
342 | * @param ch Channel. | ||
343 | * | ||
344 | * @return Static string with the channel IDs. | ||
345 | */ | ||
346 | const char * | ||
347 | GCCH_2s (const struct CadetChannel *ch) | ||
348 | { | ||
349 | static char buf[128]; | ||
350 | |||
351 | GNUNET_snprintf (buf, | ||
352 | sizeof (buf), | ||
353 | "Channel %s:%s ctn:%X(%X/%X)", | ||
354 | (GNUNET_YES == ch->is_loopback) | ||
355 | ? "loopback" | ||
356 | : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))), | ||
357 | GNUNET_h2s (&ch->port), | ||
358 | ch->ctn, | ||
359 | (NULL == ch->owner) ? 0 : ntohl (ch->owner->ccn.channel_of_client), | ||
360 | (NULL == ch->dest) ? 0 : ntohl (ch->dest->ccn.channel_of_client)); | ||
361 | return buf; | ||
362 | } | ||
363 | |||
364 | |||
365 | /** | ||
366 | * Get the channel's public ID. | ||
367 | * | ||
368 | * @param ch Channel. | ||
369 | * | ||
370 | * @return ID used to identify the channel with the remote peer. | ||
371 | */ | ||
372 | struct GNUNET_CADET_ChannelTunnelNumber | ||
373 | GCCH_get_id (const struct CadetChannel *ch) | ||
374 | { | ||
375 | return ch->ctn; | ||
376 | } | ||
377 | |||
378 | |||
379 | /** | ||
380 | * Release memory associated with @a ccc | ||
381 | * | ||
382 | * @param ccc data structure to clean up | ||
383 | */ | ||
384 | static void | ||
385 | free_channel_client (struct CadetChannelClient *ccc) | ||
386 | { | ||
387 | struct CadetOutOfOrderMessage *com; | ||
388 | |||
389 | while (NULL != (com = ccc->head_recv)) | ||
390 | { | ||
391 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, | ||
392 | ccc->tail_recv, | ||
393 | com); | ||
394 | GNUNET_MQ_discard (com->env); | ||
395 | GNUNET_free (com); | ||
396 | } | ||
397 | GNUNET_free (ccc); | ||
398 | } | ||
399 | |||
400 | |||
401 | /** | ||
402 | * Destroy the given channel. | ||
403 | * | ||
404 | * @param ch channel to destroy | ||
405 | */ | ||
406 | static void | ||
407 | channel_destroy (struct CadetChannel *ch) | ||
408 | { | ||
409 | struct CadetReliableMessage *crm; | ||
410 | |||
411 | while (NULL != (crm = ch->head_sent)) | ||
412 | { | ||
413 | GNUNET_assert (ch == crm->ch); | ||
414 | if (NULL != crm->qe) | ||
415 | { | ||
416 | GCT_send_cancel (crm->qe); | ||
417 | crm->qe = NULL; | ||
418 | } | ||
419 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, | ||
420 | ch->tail_sent, | ||
421 | crm); | ||
422 | GNUNET_free (crm->data_message); | ||
423 | GNUNET_free (crm); | ||
424 | } | ||
425 | if (NULL != ch->owner) | ||
426 | { | ||
427 | free_channel_client (ch->owner); | ||
428 | ch->owner = NULL; | ||
429 | } | ||
430 | if (NULL != ch->dest) | ||
431 | { | ||
432 | free_channel_client (ch->dest); | ||
433 | ch->dest = NULL; | ||
434 | } | ||
435 | if (NULL != ch->last_control_qe) | ||
436 | { | ||
437 | GCT_send_cancel (ch->last_control_qe); | ||
438 | ch->last_control_qe = NULL; | ||
439 | } | ||
440 | if (NULL != ch->retry_data_task) | ||
441 | { | ||
442 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
443 | ch->retry_data_task = NULL; | ||
444 | } | ||
445 | if (NULL != ch->retry_control_task) | ||
446 | { | ||
447 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
448 | ch->retry_control_task = NULL; | ||
449 | } | ||
450 | if (GNUNET_NO == ch->is_loopback) | ||
451 | { | ||
452 | GCT_remove_channel (ch->t, | ||
453 | ch, | ||
454 | ch->ctn); | ||
455 | ch->t = NULL; | ||
456 | } | ||
457 | GNUNET_free (ch); | ||
458 | } | ||
459 | |||
460 | |||
461 | /** | ||
462 | * Send a channel create message. | ||
463 | * | ||
464 | * @param cls Channel for which to send. | ||
465 | */ | ||
466 | static void | ||
467 | send_channel_open (void *cls); | ||
468 | |||
469 | |||
470 | /** | ||
471 | * Function called once the tunnel confirms that we sent the | ||
472 | * create message. Delays for a bit until we retry. | ||
473 | * | ||
474 | * @param cls our `struct CadetChannel`. | ||
475 | */ | ||
476 | static void | ||
477 | channel_open_sent_cb (void *cls) | ||
478 | { | ||
479 | struct CadetChannel *ch = cls; | ||
480 | |||
481 | GNUNET_assert (NULL != ch->last_control_qe); | ||
482 | ch->last_control_qe = NULL; | ||
483 | ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time); | ||
484 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
485 | "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n", | ||
486 | GCCH_2s (ch), | ||
487 | GNUNET_STRINGS_relative_time_to_string (ch->retry_time, | ||
488 | GNUNET_YES)); | ||
489 | ch->retry_control_task | ||
490 | = GNUNET_SCHEDULER_add_delayed (ch->retry_time, | ||
491 | &send_channel_open, | ||
492 | ch); | ||
493 | } | ||
494 | |||
495 | |||
496 | /** | ||
497 | * Send a channel open message. | ||
498 | * | ||
499 | * @param cls Channel for which to send. | ||
500 | */ | ||
501 | static void | ||
502 | send_channel_open (void *cls) | ||
503 | { | ||
504 | struct CadetChannel *ch = cls; | ||
505 | struct GNUNET_CADET_ChannelOpenMessage msgcc; | ||
506 | uint32_t options; | ||
507 | |||
508 | ch->retry_control_task = NULL; | ||
509 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
510 | "Sending CHANNEL_OPEN message for %s\n", | ||
511 | GCCH_2s (ch)); | ||
512 | options = 0; | ||
513 | if (ch->nobuffer) | ||
514 | options |= GNUNET_CADET_OPTION_NOBUFFER; | ||
515 | if (ch->reliable) | ||
516 | options |= GNUNET_CADET_OPTION_RELIABLE; | ||
517 | if (ch->out_of_order) | ||
518 | options |= GNUNET_CADET_OPTION_OUT_OF_ORDER; | ||
519 | msgcc.header.size = htons (sizeof (msgcc)); | ||
520 | msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN); | ||
521 | msgcc.opt = htonl (options); | ||
522 | msgcc.port = ch->port; | ||
523 | msgcc.ctn = ch->ctn; | ||
524 | ch->state = CADET_CHANNEL_OPEN_SENT; | ||
525 | ch->last_control_qe = GCT_send (ch->t, | ||
526 | &msgcc.header, | ||
527 | &channel_open_sent_cb, | ||
528 | ch); | ||
529 | } | ||
530 | |||
531 | |||
532 | /** | ||
533 | * Function called once and only once after a channel was bound | ||
534 | * to its tunnel via #GCT_add_channel() is ready for transmission. | ||
535 | * Note that this is only the case for channels that this peer | ||
536 | * initiates, as for incoming channels we assume that they are | ||
537 | * ready for transmission immediately upon receiving the open | ||
538 | * message. Used to bootstrap the #GCT_send() process. | ||
539 | * | ||
540 | * @param ch the channel for which the tunnel is now ready | ||
541 | */ | ||
542 | void | ||
543 | GCCH_tunnel_up (struct CadetChannel *ch) | ||
544 | { | ||
545 | GNUNET_assert (NULL == ch->retry_control_task); | ||
546 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
547 | "Tunnel up, sending CHANNEL_OPEN on %s now\n", | ||
548 | GCCH_2s (ch)); | ||
549 | ch->retry_control_task | ||
550 | = GNUNET_SCHEDULER_add_now (&send_channel_open, | ||
551 | ch); | ||
552 | } | ||
553 | |||
554 | |||
555 | /** | ||
556 | * Create a new channel. | ||
557 | * | ||
558 | * @param owner local client owning the channel | ||
559 | * @param ccn local number of this channel at the @a owner | ||
560 | * @param destination peer to which we should build the channel | ||
561 | * @param port desired port at @a destination | ||
562 | * @param options options for the channel | ||
563 | * @return handle to the new channel | ||
564 | */ | ||
565 | struct CadetChannel * | ||
566 | GCCH_channel_local_new (struct CadetClient *owner, | ||
567 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
568 | struct CadetPeer *destination, | ||
569 | const struct GNUNET_HashCode *port, | ||
570 | uint32_t options) | ||
571 | { | ||
572 | struct CadetChannel *ch; | ||
573 | struct CadetChannelClient *ccco; | ||
574 | |||
575 | ccco = GNUNET_new (struct CadetChannelClient); | ||
576 | ccco->c = owner; | ||
577 | ccco->ccn = ccn; | ||
578 | ccco->client_ready = GNUNET_YES; | ||
579 | |||
580 | ch = GNUNET_new (struct CadetChannel); | ||
581 | ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */ | ||
582 | ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER)); | ||
583 | ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE)); | ||
584 | ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER)); | ||
585 | ch->max_pending_messages = (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */ | ||
586 | ch->owner = ccco; | ||
587 | ch->port = *port; | ||
588 | if (0 == memcmp (&my_full_id, | ||
589 | GCP_get_id (destination), | ||
590 | sizeof (struct GNUNET_PeerIdentity))) | ||
591 | { | ||
592 | struct CadetClient *c; | ||
593 | |||
594 | ch->is_loopback = GNUNET_YES; | ||
595 | c = GNUNET_CONTAINER_multihashmap_get (open_ports, | ||
596 | port); | ||
597 | if (NULL == c) | ||
598 | { | ||
599 | /* port closed, wait for it to possibly open */ | ||
600 | (void) GNUNET_CONTAINER_multihashmap_put (loose_channels, | ||
601 | port, | ||
602 | ch, | ||
603 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
604 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
605 | "Created loose incoming loopback channel to port %s\n", | ||
606 | GNUNET_h2s (&ch->port)); | ||
607 | } | ||
608 | else | ||
609 | { | ||
610 | ch->dest = GNUNET_new (struct CadetChannelClient); | ||
611 | ch->dest->c = c; | ||
612 | ch->dest->client_ready = GNUNET_YES; | ||
613 | GCCH_bind (ch, | ||
614 | ch->dest->c); | ||
615 | } | ||
616 | } | ||
617 | else | ||
618 | { | ||
619 | ch->t = GCP_get_tunnel (destination, | ||
620 | GNUNET_YES); | ||
621 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; | ||
622 | ch->ctn = GCT_add_channel (ch->t, | ||
623 | ch); | ||
624 | } | ||
625 | GNUNET_STATISTICS_update (stats, | ||
626 | "# channels", | ||
627 | 1, | ||
628 | GNUNET_NO); | ||
629 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
630 | "Created channel to port %s at peer %s for %s using %s\n", | ||
631 | GNUNET_h2s (port), | ||
632 | GCP_2s (destination), | ||
633 | GSC_2s (owner), | ||
634 | (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t)); | ||
635 | return ch; | ||
636 | } | ||
637 | |||
638 | |||
639 | /** | ||
640 | * We had an incoming channel to a port that is closed. | ||
641 | * It has not been opened for a while, drop it. | ||
642 | * | ||
643 | * @param cls the channel to drop | ||
644 | */ | ||
645 | static void | ||
646 | timeout_closed_cb (void *cls) | ||
647 | { | ||
648 | struct CadetChannel *ch = cls; | ||
649 | |||
650 | ch->retry_control_task = NULL; | ||
651 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
652 | "Closing incoming channel to port %s from peer %s due to timeout\n", | ||
653 | GNUNET_h2s (&ch->port), | ||
654 | GCP_2s (GCT_get_destination (ch->t))); | ||
655 | channel_destroy (ch); | ||
656 | } | ||
657 | |||
658 | |||
659 | /** | ||
660 | * Create a new channel based on a request coming in over the network. | ||
661 | * | ||
662 | * @param t tunnel to the remote peer | ||
663 | * @param ctn identifier of this channel in the tunnel | ||
664 | * @param port desired local port | ||
665 | * @param options options for the channel | ||
666 | * @return handle to the new channel | ||
667 | */ | ||
668 | struct CadetChannel * | ||
669 | GCCH_channel_incoming_new (struct CadetTunnel *t, | ||
670 | struct GNUNET_CADET_ChannelTunnelNumber ctn, | ||
671 | const struct GNUNET_HashCode *port, | ||
672 | uint32_t options) | ||
673 | { | ||
674 | struct CadetChannel *ch; | ||
675 | struct CadetClient *c; | ||
676 | |||
677 | ch = GNUNET_new (struct CadetChannel); | ||
678 | ch->port = *port; | ||
679 | ch->t = t; | ||
680 | ch->ctn = ctn; | ||
681 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; | ||
682 | ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER)); | ||
683 | ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE)); | ||
684 | ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER)); | ||
685 | ch->max_pending_messages = (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */ | ||
686 | GNUNET_STATISTICS_update (stats, | ||
687 | "# channels", | ||
688 | 1, | ||
689 | GNUNET_NO); | ||
690 | |||
691 | c = GNUNET_CONTAINER_multihashmap_get (open_ports, | ||
692 | port); | ||
693 | if (NULL == c) | ||
694 | { | ||
695 | /* port closed, wait for it to possibly open */ | ||
696 | (void) GNUNET_CONTAINER_multihashmap_put (loose_channels, | ||
697 | port, | ||
698 | ch, | ||
699 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
700 | ch->retry_control_task | ||
701 | = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT, | ||
702 | &timeout_closed_cb, | ||
703 | ch); | ||
704 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
705 | "Created loose incoming channel to port %s from peer %s\n", | ||
706 | GNUNET_h2s (&ch->port), | ||
707 | GCP_2s (GCT_get_destination (ch->t))); | ||
708 | } | ||
709 | else | ||
710 | { | ||
711 | GCCH_bind (ch, | ||
712 | c); | ||
713 | } | ||
714 | GNUNET_STATISTICS_update (stats, | ||
715 | "# channels", | ||
716 | 1, | ||
717 | GNUNET_NO); | ||
718 | return ch; | ||
719 | } | ||
720 | |||
721 | |||
722 | /** | ||
723 | * Function called once the tunnel confirms that we sent the | ||
724 | * ACK message. Just remembers it was sent, we do not expect | ||
725 | * ACKs for ACKs ;-). | ||
726 | * | ||
727 | * @param cls our `struct CadetChannel`. | ||
728 | */ | ||
729 | static void | ||
730 | send_ack_cb (void *cls) | ||
731 | { | ||
732 | struct CadetChannel *ch = cls; | ||
733 | |||
734 | GNUNET_assert (NULL != ch->last_control_qe); | ||
735 | ch->last_control_qe = NULL; | ||
736 | } | ||
737 | |||
738 | |||
739 | /** | ||
740 | * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer. | ||
741 | * | ||
742 | * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for | ||
743 | */ | ||
744 | static void | ||
745 | send_channel_data_ack (struct CadetChannel *ch) | ||
746 | { | ||
747 | struct GNUNET_CADET_ChannelDataAckMessage msg; | ||
748 | |||
749 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK); | ||
750 | msg.header.size = htons (sizeof (msg)); | ||
751 | msg.ctn = ch->ctn; | ||
752 | msg.mid.mid = htonl (ntohl (ch->mid_recv.mid) - 1); | ||
753 | msg.futures = GNUNET_htonll (ch->mid_futures); | ||
754 | if (NULL != ch->last_control_qe) | ||
755 | GCT_send_cancel (ch->last_control_qe); | ||
756 | ch->last_control_qe = GCT_send (ch->t, | ||
757 | &msg.header, | ||
758 | &send_ack_cb, | ||
759 | ch); | ||
760 | } | ||
761 | |||
762 | |||
763 | /** | ||
764 | * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the | ||
765 | * connection is up. | ||
766 | * | ||
767 | * @param cls the `struct CadetChannel` | ||
768 | */ | ||
769 | static void | ||
770 | send_open_ack (void *cls) | ||
771 | { | ||
772 | struct CadetChannel *ch = cls; | ||
773 | struct GNUNET_CADET_ChannelManageMessage msg; | ||
774 | |||
775 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
776 | "Sending CHANNEL_OPEN_ACK on %s\n", | ||
777 | GCCH_2s (ch)); | ||
778 | ch->retry_control_task = NULL; | ||
779 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK); | ||
780 | msg.header.size = htons (sizeof (msg)); | ||
781 | msg.reserved = htonl (0); | ||
782 | msg.ctn = ch->ctn; | ||
783 | if (NULL != ch->last_control_qe) | ||
784 | GCT_send_cancel (ch->last_control_qe); | ||
785 | ch->last_control_qe = GCT_send (ch->t, | ||
786 | &msg.header, | ||
787 | &send_ack_cb, | ||
788 | ch); | ||
789 | } | ||
790 | |||
791 | |||
792 | /** | ||
793 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for | ||
794 | * this channel. If the binding was successful, (re)transmit the | ||
795 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK. | ||
796 | * | ||
797 | * @param ch channel that got the duplicate open | ||
798 | */ | ||
799 | void | ||
800 | GCCH_handle_duplicate_open (struct CadetChannel *ch) | ||
801 | { | ||
802 | if (NULL == ch->dest) | ||
803 | { | ||
804 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
805 | "Ignoring duplicate channel OPEN on %s: port is closed\n", | ||
806 | GCCH_2s (ch)); | ||
807 | return; | ||
808 | } | ||
809 | if (NULL != ch->retry_control_task) | ||
810 | { | ||
811 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
812 | "Ignoring duplicate channel OPEN on %s: control message is pending\n", | ||
813 | GCCH_2s (ch)); | ||
814 | return; | ||
815 | } | ||
816 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
817 | "Retransmitting OPEN_ACK on %s\n", | ||
818 | GCCH_2s (ch)); | ||
819 | ch->retry_control_task | ||
820 | = GNUNET_SCHEDULER_add_now (&send_open_ack, | ||
821 | ch); | ||
822 | } | ||
823 | |||
824 | |||
825 | /** | ||
826 | * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages. | ||
827 | * | ||
828 | * @param ch channel the ack is for | ||
829 | * @param to_owner #GNUNET_YES to send to owner, | ||
830 | * #GNUNET_NO to send to dest | ||
831 | */ | ||
832 | static void | ||
833 | send_ack_to_client (struct CadetChannel *ch, | ||
834 | int to_owner) | ||
835 | { | ||
836 | struct GNUNET_MQ_Envelope *env; | ||
837 | struct GNUNET_CADET_LocalAck *ack; | ||
838 | struct CadetChannelClient *ccc; | ||
839 | |||
840 | env = GNUNET_MQ_msg (ack, | ||
841 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | ||
842 | ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest; | ||
843 | ack->ccn = ccc->ccn; | ||
844 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
845 | "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X\n", | ||
846 | GSC_2s (ccc->c), | ||
847 | (GNUNET_YES == to_owner) ? "owner" : "dest", | ||
848 | ntohl (ack->ccn.channel_of_client)); | ||
849 | GSC_send_to_client (ccc->c, | ||
850 | env); | ||
851 | } | ||
852 | |||
853 | |||
854 | /** | ||
855 | * A client is bound to the port that we have a channel | ||
856 | * open to. Send the acknowledgement for the connection | ||
857 | * request and establish the link with the client. | ||
858 | * | ||
859 | * @param ch open incoming channel | ||
860 | * @param c client listening on the respective port | ||
861 | */ | ||
862 | void | ||
863 | GCCH_bind (struct CadetChannel *ch, | ||
864 | struct CadetClient *c) | ||
865 | { | ||
866 | uint32_t options; | ||
867 | struct CadetChannelClient *cccd; | ||
868 | |||
869 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
870 | "Binding %s from %s to port %s of %s\n", | ||
871 | GCCH_2s (ch), | ||
872 | GCT_2s (ch->t), | ||
873 | GNUNET_h2s (&ch->port), | ||
874 | GSC_2s (c)); | ||
875 | if (NULL != ch->retry_control_task) | ||
876 | { | ||
877 | /* there might be a timeout task here */ | ||
878 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
879 | ch->retry_control_task = NULL; | ||
880 | } | ||
881 | options = 0; | ||
882 | if (ch->nobuffer) | ||
883 | options |= GNUNET_CADET_OPTION_NOBUFFER; | ||
884 | if (ch->reliable) | ||
885 | options |= GNUNET_CADET_OPTION_RELIABLE; | ||
886 | if (ch->out_of_order) | ||
887 | options |= GNUNET_CADET_OPTION_OUT_OF_ORDER; | ||
888 | cccd = GNUNET_new (struct CadetChannelClient); | ||
889 | ch->dest = cccd; | ||
890 | cccd->c = c; | ||
891 | cccd->client_ready = GNUNET_YES; | ||
892 | cccd->ccn = GSC_bind (c, | ||
893 | ch, | ||
894 | (GNUNET_YES == ch->is_loopback) | ||
895 | ? GCP_get (&my_full_id, | ||
896 | GNUNET_YES) | ||
897 | : GCT_get_destination (ch->t), | ||
898 | &ch->port, | ||
899 | options); | ||
900 | GNUNET_assert (ntohl (cccd->ccn.channel_of_client) < | ||
901 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
902 | ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */ | ||
903 | if (GNUNET_YES == ch->is_loopback) | ||
904 | { | ||
905 | ch->state = CADET_CHANNEL_OPEN_SENT; | ||
906 | GCCH_handle_channel_open_ack (ch); | ||
907 | } | ||
908 | else | ||
909 | { | ||
910 | /* notify other peer that we accepted the connection */ | ||
911 | ch->retry_control_task | ||
912 | = GNUNET_SCHEDULER_add_now (&send_open_ack, | ||
913 | ch); | ||
914 | } | ||
915 | /* give client it's initial supply of ACKs */ | ||
916 | GNUNET_assert (ntohl (cccd->ccn.channel_of_client) < | ||
917 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
918 | for (unsigned int i=0;i<ch->max_pending_messages;i++) | ||
919 | send_ack_to_client (ch, | ||
920 | GNUNET_NO); | ||
921 | } | ||
922 | |||
923 | |||
924 | /** | ||
925 | * Destroy locally created channel. Called by the local client, so no | ||
926 | * need to tell the client. | ||
927 | * | ||
928 | * @param ch channel to destroy | ||
929 | * @param c client that caused the destruction | ||
930 | * @param ccn client number of the client @a c | ||
931 | */ | ||
932 | void | ||
933 | GCCH_channel_local_destroy (struct CadetChannel *ch, | ||
934 | struct CadetClient *c, | ||
935 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
936 | { | ||
937 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
938 | "%s asks for destruction of %s\n", | ||
939 | GSC_2s (c), | ||
940 | GCCH_2s (ch)); | ||
941 | GNUNET_assert (NULL != c); | ||
942 | if ( (NULL != ch->owner) && | ||
943 | (c == ch->owner->c) && | ||
944 | (ccn.channel_of_client == ch->owner->ccn.channel_of_client) ) | ||
945 | { | ||
946 | free_channel_client (ch->owner); | ||
947 | ch->owner = NULL; | ||
948 | } | ||
949 | else if ( (NULL != ch->dest) && | ||
950 | (c == ch->dest->c) && | ||
951 | (ccn.channel_of_client == ch->dest->ccn.channel_of_client) ) | ||
952 | { | ||
953 | free_channel_client (ch->dest); | ||
954 | ch->dest = NULL; | ||
955 | } | ||
956 | else | ||
957 | { | ||
958 | GNUNET_assert (0); | ||
959 | } | ||
960 | |||
961 | if (GNUNET_YES == ch->destroy) | ||
962 | { | ||
963 | /* other end already destroyed, with the local client gone, no need | ||
964 | to finish transmissions, just destroy immediately. */ | ||
965 | channel_destroy (ch); | ||
966 | return; | ||
967 | } | ||
968 | if ( (NULL != ch->head_sent) || | ||
969 | (NULL != ch->owner) || | ||
970 | (NULL != ch->dest) ) | ||
971 | { | ||
972 | /* Wait for other end to destroy us as well, | ||
973 | and otherwise allow send queue to be transmitted first */ | ||
974 | ch->destroy = GNUNET_YES; | ||
975 | return; | ||
976 | } | ||
977 | /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */ | ||
978 | if (CADET_CHANNEL_NEW != ch->state) | ||
979 | GCT_send_channel_destroy (ch->t, | ||
980 | ch->ctn); | ||
981 | /* Nothing left to do, just finish destruction */ | ||
982 | channel_destroy (ch); | ||
983 | } | ||
984 | |||
985 | |||
986 | /** | ||
987 | * We got an acknowledgement for the creation of the channel | ||
988 | * (the port is open on the other side). Begin transmissions. | ||
989 | * | ||
990 | * @param ch channel to destroy | ||
991 | */ | ||
992 | void | ||
993 | GCCH_handle_channel_open_ack (struct CadetChannel *ch) | ||
994 | { | ||
995 | switch (ch->state) | ||
996 | { | ||
997 | case CADET_CHANNEL_NEW: | ||
998 | /* this should be impossible */ | ||
999 | GNUNET_break (0); | ||
1000 | break; | ||
1001 | case CADET_CHANNEL_OPEN_SENT: | ||
1002 | if (NULL == ch->owner) | ||
1003 | { | ||
1004 | /* We're not the owner, wrong direction! */ | ||
1005 | GNUNET_break_op (0); | ||
1006 | return; | ||
1007 | } | ||
1008 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1009 | "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n", | ||
1010 | GCCH_2s (ch)); | ||
1011 | if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */ | ||
1012 | { | ||
1013 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
1014 | ch->retry_control_task = NULL; | ||
1015 | } | ||
1016 | ch->state = CADET_CHANNEL_READY; | ||
1017 | /* On first connect, send client as many ACKs as we allow messages | ||
1018 | to be buffered! */ | ||
1019 | for (unsigned int i=0;i<ch->max_pending_messages;i++) | ||
1020 | send_ack_to_client (ch, | ||
1021 | GNUNET_YES); | ||
1022 | break; | ||
1023 | case CADET_CHANNEL_READY: | ||
1024 | /* duplicate ACK, maybe we retried the CREATE. Ignore. */ | ||
1025 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1026 | "Received duplicate channel OPEN_ACK for %s\n", | ||
1027 | GCCH_2s (ch)); | ||
1028 | GNUNET_STATISTICS_update (stats, | ||
1029 | "# duplicate CREATE_ACKs", | ||
1030 | 1, | ||
1031 | GNUNET_NO); | ||
1032 | break; | ||
1033 | } | ||
1034 | } | ||
1035 | |||
1036 | |||
1037 | /** | ||
1038 | * Test if element @a e1 comes before element @a e2. | ||
1039 | * | ||
1040 | * TODO: use opportunity to create generic list insertion sort | ||
1041 | * logic in container! | ||
1042 | * | ||
1043 | * @param cls closure, our `struct CadetChannel` | ||
1044 | * @param e1 an element of to sort | ||
1045 | * @param e2 another element to sort | ||
1046 | * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO | ||
1047 | */ | ||
1048 | static int | ||
1049 | is_before (void *cls, | ||
1050 | void *e1, | ||
1051 | void *e2) | ||
1052 | { | ||
1053 | struct CadetOutOfOrderMessage *m1 = e1; | ||
1054 | struct CadetOutOfOrderMessage *m2 = e2; | ||
1055 | uint32_t v1 = ntohl (m1->mid.mid); | ||
1056 | uint32_t v2 = ntohl (m2->mid.mid); | ||
1057 | uint32_t delta; | ||
1058 | |||
1059 | delta = v1 - v2; | ||
1060 | if (delta > (uint32_t) INT_MAX) | ||
1061 | { | ||
1062 | /* in overflow range, we can safely assume we wrapped around */ | ||
1063 | return GNUNET_NO; | ||
1064 | } | ||
1065 | else | ||
1066 | { | ||
1067 | return GNUNET_YES; | ||
1068 | } | ||
1069 | } | ||
1070 | |||
1071 | |||
1072 | /** | ||
1073 | * We got payload data for a channel. Pass it on to the client | ||
1074 | * and send an ACK to the other end (once flow control allows it!) | ||
1075 | * | ||
1076 | * @param ch channel that got data | ||
1077 | * @param msg message that was received | ||
1078 | */ | ||
1079 | void | ||
1080 | GCCH_handle_channel_plaintext_data (struct CadetChannel *ch, | ||
1081 | const struct GNUNET_CADET_ChannelAppDataMessage *msg) | ||
1082 | { | ||
1083 | struct GNUNET_MQ_Envelope *env; | ||
1084 | struct GNUNET_CADET_LocalData *ld; | ||
1085 | struct CadetChannelClient *ccc; | ||
1086 | struct CadetOutOfOrderMessage *com; | ||
1087 | size_t payload_size; | ||
1088 | |||
1089 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1090 | if ( (GNUNET_YES == ch->destroy) && | ||
1091 | (NULL == ch->owner) && | ||
1092 | (NULL == ch->dest) ) | ||
1093 | { | ||
1094 | /* This client is gone, but we still have messages to send to | ||
1095 | the other end (which is why @a ch is not yet dead). However, | ||
1096 | we cannot pass messages to our client anymore. */ | ||
1097 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1098 | "Dropping incoming payload on %s as this end is already closed\n", | ||
1099 | GCCH_2s (ch)); | ||
1100 | /* FIXME: send back ACK/NACK/Closed notification | ||
1101 | to stop retransmissions! */ | ||
1102 | return; | ||
1103 | } | ||
1104 | payload_size = ntohs (msg->header.size) - sizeof (*msg); | ||
1105 | env = GNUNET_MQ_msg_extra (ld, | ||
1106 | payload_size, | ||
1107 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1108 | ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn; | ||
1109 | GNUNET_memcpy (&ld[1], | ||
1110 | &msg[1], | ||
1111 | payload_size); | ||
1112 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1113 | if ( (GNUNET_YES == ccc->client_ready) && | ||
1114 | ( (GNUNET_YES == ch->out_of_order) || | ||
1115 | (msg->mid.mid == ch->mid_recv.mid) ) ) | ||
1116 | { | ||
1117 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1118 | "Giving %u bytes of payload from %s to client %s\n", | ||
1119 | (unsigned int) payload_size, | ||
1120 | GCCH_2s (ch), | ||
1121 | GSC_2s (ccc->c)); | ||
1122 | ccc->client_ready = GNUNET_NO; | ||
1123 | GSC_send_to_client (ccc->c, | ||
1124 | env); | ||
1125 | ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid)); | ||
1126 | ch->mid_futures >>= 1; | ||
1127 | } | ||
1128 | else | ||
1129 | { | ||
1130 | /* FIXME-SECURITY: if the element is WAY too far ahead, | ||
1131 | drop it (can't buffer too much!) */ | ||
1132 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1133 | "Queuing %s payload of %u bytes on %s (mid %u, need %u first)\n", | ||
1134 | (GNUNET_YES == ccc->client_ready) | ||
1135 | ? "out-of-order" | ||
1136 | : "client-not-ready", | ||
1137 | (unsigned int) payload_size, | ||
1138 | GCCH_2s (ch), | ||
1139 | ntohl (msg->mid.mid), | ||
1140 | ntohl (ch->mid_recv.mid)); | ||
1141 | |||
1142 | com = GNUNET_new (struct CadetOutOfOrderMessage); | ||
1143 | com->mid = msg->mid; | ||
1144 | com->env = env; | ||
1145 | /* sort into list ordered by "is_before" */ | ||
1146 | if ( (NULL == ccc->head_recv) || | ||
1147 | (GNUNET_YES == is_before (ch, | ||
1148 | com, | ||
1149 | ccc->head_recv)) ) | ||
1150 | { | ||
1151 | GNUNET_CONTAINER_DLL_insert (ccc->head_recv, | ||
1152 | ccc->tail_recv, | ||
1153 | com); | ||
1154 | } | ||
1155 | else | ||
1156 | { | ||
1157 | struct CadetOutOfOrderMessage *pos; | ||
1158 | |||
1159 | for (pos = ccc->head_recv; | ||
1160 | NULL != pos; | ||
1161 | pos = pos->next) | ||
1162 | { | ||
1163 | if (GNUNET_YES != | ||
1164 | is_before (NULL, | ||
1165 | pos, | ||
1166 | com)) | ||
1167 | break; | ||
1168 | } | ||
1169 | if (NULL == pos) | ||
1170 | GNUNET_CONTAINER_DLL_insert_tail (ccc->head_recv, | ||
1171 | ccc->tail_recv, | ||
1172 | com); | ||
1173 | else | ||
1174 | GNUNET_CONTAINER_DLL_insert_after (ccc->head_recv, | ||
1175 | ccc->tail_recv, | ||
1176 | com, | ||
1177 | pos->prev); | ||
1178 | } | ||
1179 | } | ||
1180 | } | ||
1181 | |||
1182 | |||
1183 | /** | ||
1184 | * We got an acknowledgement for payload data for a channel. | ||
1185 | * Possibly resume transmissions. | ||
1186 | * | ||
1187 | * @param ch channel that got the ack | ||
1188 | * @param ack details about what was received | ||
1189 | */ | ||
1190 | void | ||
1191 | GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch, | ||
1192 | const struct GNUNET_CADET_ChannelDataAckMessage *ack) | ||
1193 | { | ||
1194 | struct CadetReliableMessage *crm; | ||
1195 | |||
1196 | GNUNET_break (GNUNET_NO == ch->is_loopback); | ||
1197 | if (GNUNET_NO == ch->reliable) | ||
1198 | { | ||
1199 | /* not expecting ACKs on unreliable channel, odd */ | ||
1200 | GNUNET_break_op (0); | ||
1201 | return; | ||
1202 | } | ||
1203 | for (crm = ch->head_sent; | ||
1204 | NULL != crm; | ||
1205 | crm = crm->next) | ||
1206 | if (ack->mid.mid == crm->data_message->mid.mid) | ||
1207 | break; | ||
1208 | if (NULL == crm) | ||
1209 | { | ||
1210 | /* ACK for message we already dropped, might have been a | ||
1211 | duplicate ACK? Ignore. */ | ||
1212 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1213 | "Duplicate DATA_ACK on %s, ignoring\n", | ||
1214 | GCCH_2s (ch)); | ||
1215 | GNUNET_STATISTICS_update (stats, | ||
1216 | "# duplicate DATA_ACKs", | ||
1217 | 1, | ||
1218 | GNUNET_NO); | ||
1219 | return; | ||
1220 | } | ||
1221 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, | ||
1222 | ch->tail_sent, | ||
1223 | crm); | ||
1224 | GNUNET_free (crm->data_message); | ||
1225 | GNUNET_free (crm); | ||
1226 | ch->pending_messages--; | ||
1227 | send_ack_to_client (ch, | ||
1228 | (NULL == ch->owner) | ||
1229 | ? GNUNET_NO | ||
1230 | : GNUNET_YES); | ||
1231 | GNUNET_assert (ch->pending_messages < ch->max_pending_messages); | ||
1232 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1233 | "Received DATA_ACK on %s for message %u (%u ACKs pending)\n", | ||
1234 | GCCH_2s (ch), | ||
1235 | (unsigned int) ntohl (ack->mid.mid), | ||
1236 | ch->pending_messages); | ||
1237 | send_ack_to_client (ch, | ||
1238 | (NULL == ch->owner) | ||
1239 | ? GNUNET_NO | ||
1240 | : GNUNET_YES); | ||
1241 | } | ||
1242 | |||
1243 | |||
1244 | /** | ||
1245 | * Destroy channel, based on the other peer closing the | ||
1246 | * connection. Also needs to remove this channel from | ||
1247 | * the tunnel. | ||
1248 | * | ||
1249 | * @param ch channel to destroy | ||
1250 | */ | ||
1251 | void | ||
1252 | GCCH_handle_remote_destroy (struct CadetChannel *ch) | ||
1253 | { | ||
1254 | struct CadetChannelClient *ccc; | ||
1255 | |||
1256 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1257 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1258 | "Received remote channel DESTROY for %s\n", | ||
1259 | GCCH_2s (ch)); | ||
1260 | if (GNUNET_YES == ch->destroy) | ||
1261 | { | ||
1262 | /* Local client already gone, this is instant-death. */ | ||
1263 | channel_destroy (ch); | ||
1264 | return; | ||
1265 | } | ||
1266 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1267 | if (NULL != ccc->head_recv) | ||
1268 | { | ||
1269 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1270 | "Lost end of transmission due to remote shutdown on %s\n", | ||
1271 | GCCH_2s (ch)); | ||
1272 | /* FIXME: change API to notify client about truncated transmission! */ | ||
1273 | } | ||
1274 | ch->destroy = GNUNET_YES; | ||
1275 | GSC_handle_remote_channel_destroy (ccc->c, | ||
1276 | ccc->ccn, | ||
1277 | ch); | ||
1278 | channel_destroy (ch); | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | /** | ||
1283 | * Function called once the tunnel has sent one of our messages. | ||
1284 | * If the message is unreliable, simply frees the `crm`. If the | ||
1285 | * message was reliable, calculate retransmission time and | ||
1286 | * wait for ACK (or retransmit). | ||
1287 | * | ||
1288 | * @param cls the `struct CadetReliableMessage` that was sent | ||
1289 | */ | ||
1290 | static void | ||
1291 | data_sent_cb (void *cls); | ||
1292 | |||
1293 | |||
1294 | /** | ||
1295 | * We need to retry a transmission, the last one took too long to | ||
1296 | * be acknowledged. | ||
1297 | * | ||
1298 | * @param cls the `struct CadetChannel` where we need to retransmit | ||
1299 | */ | ||
1300 | static void | ||
1301 | retry_transmission (void *cls) | ||
1302 | { | ||
1303 | struct CadetChannel *ch = cls; | ||
1304 | struct CadetReliableMessage *crm = ch->head_sent; | ||
1305 | |||
1306 | ch->retry_data_task = NULL; | ||
1307 | GNUNET_assert (NULL == crm->qe); | ||
1308 | crm->qe = GCT_send (ch->t, | ||
1309 | &crm->data_message->header, | ||
1310 | &data_sent_cb, | ||
1311 | crm); | ||
1312 | } | ||
1313 | |||
1314 | |||
1315 | /** | ||
1316 | * Function called once the tunnel has sent one of our messages. | ||
1317 | * If the message is unreliable, simply frees the `crm`. If the | ||
1318 | * message was reliable, calculate retransmission time and | ||
1319 | * wait for ACK (or retransmit). | ||
1320 | * | ||
1321 | * @param cls the `struct CadetReliableMessage` that was sent | ||
1322 | */ | ||
1323 | static void | ||
1324 | data_sent_cb (void *cls) | ||
1325 | { | ||
1326 | struct CadetReliableMessage *crm = cls; | ||
1327 | struct CadetChannel *ch = crm->ch; | ||
1328 | struct CadetReliableMessage *off; | ||
1329 | |||
1330 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1331 | crm->qe = NULL; | ||
1332 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, | ||
1333 | ch->tail_sent, | ||
1334 | crm); | ||
1335 | if (GNUNET_NO == ch->reliable) | ||
1336 | { | ||
1337 | GNUNET_free (crm); | ||
1338 | ch->pending_messages--; | ||
1339 | send_ack_to_client (ch, | ||
1340 | (NULL == ch->owner) | ||
1341 | ? GNUNET_NO | ||
1342 | : GNUNET_YES); | ||
1343 | return; | ||
1344 | } | ||
1345 | if (0 == crm->retry_delay.rel_value_us) | ||
1346 | crm->retry_delay = ch->expected_delay; | ||
1347 | crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay); | ||
1348 | |||
1349 | /* find position for re-insertion into the DLL */ | ||
1350 | if ( (NULL == ch->head_sent) || | ||
1351 | (crm->next_retry.abs_value_us < ch->head_sent->next_retry.abs_value_us) ) | ||
1352 | { | ||
1353 | /* insert at HEAD, also (re)schedule retry task! */ | ||
1354 | GNUNET_CONTAINER_DLL_insert (ch->head_sent, | ||
1355 | ch->tail_sent, | ||
1356 | crm); | ||
1357 | if (NULL != ch->retry_data_task) | ||
1358 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1359 | ch->retry_data_task | ||
1360 | = GNUNET_SCHEDULER_add_delayed (crm->retry_delay, | ||
1361 | &retry_transmission, | ||
1362 | ch); | ||
1363 | return; | ||
1364 | } | ||
1365 | for (off = ch->head_sent; NULL != off; off = off->next) | ||
1366 | if (crm->next_retry.abs_value_us < off->next_retry.abs_value_us) | ||
1367 | break; | ||
1368 | if (NULL == off) | ||
1369 | { | ||
1370 | /* insert at tail */ | ||
1371 | GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, | ||
1372 | ch->tail_sent, | ||
1373 | crm); | ||
1374 | } | ||
1375 | else | ||
1376 | { | ||
1377 | /* insert before off */ | ||
1378 | GNUNET_CONTAINER_DLL_insert_after (ch->head_sent, | ||
1379 | ch->tail_sent, | ||
1380 | off->prev, | ||
1381 | crm); | ||
1382 | } | ||
1383 | } | ||
1384 | |||
1385 | |||
1386 | /** | ||
1387 | * Handle data given by a client. | ||
1388 | * | ||
1389 | * Check whether the client is allowed to send in this tunnel, save if | ||
1390 | * channel is reliable and send an ACK to the client if there is still | ||
1391 | * buffer space in the tunnel. | ||
1392 | * | ||
1393 | * @param ch Channel. | ||
1394 | * @param sender_ccn ccn of the sender | ||
1395 | * @param buf payload to transmit. | ||
1396 | * @param buf_len number of bytes in @a buf | ||
1397 | * @return #GNUNET_OK if everything goes well, | ||
1398 | * #GNUNET_SYSERR in case of an error. | ||
1399 | */ | ||
1400 | int | ||
1401 | GCCH_handle_local_data (struct CadetChannel *ch, | ||
1402 | struct GNUNET_CADET_ClientChannelNumber sender_ccn, | ||
1403 | const char *buf, | ||
1404 | size_t buf_len) | ||
1405 | { | ||
1406 | struct CadetReliableMessage *crm; | ||
1407 | |||
1408 | if (ch->pending_messages > ch->max_pending_messages) | ||
1409 | { | ||
1410 | GNUNET_break (0); | ||
1411 | return GNUNET_SYSERR; | ||
1412 | } | ||
1413 | ch->pending_messages++; | ||
1414 | |||
1415 | if (GNUNET_YES == ch->is_loopback) | ||
1416 | { | ||
1417 | struct CadetChannelClient *receiver; | ||
1418 | struct GNUNET_MQ_Envelope *env; | ||
1419 | struct GNUNET_CADET_LocalData *ld; | ||
1420 | int to_owner; | ||
1421 | |||
1422 | env = GNUNET_MQ_msg_extra (ld, | ||
1423 | buf_len, | ||
1424 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1425 | if (sender_ccn.channel_of_client == | ||
1426 | ch->owner->ccn.channel_of_client) | ||
1427 | { | ||
1428 | receiver = ch->dest; | ||
1429 | to_owner = GNUNET_NO; | ||
1430 | } | ||
1431 | else | ||
1432 | { | ||
1433 | GNUNET_assert (sender_ccn.channel_of_client == | ||
1434 | ch->dest->ccn.channel_of_client); | ||
1435 | receiver = ch->owner; | ||
1436 | to_owner = GNUNET_YES; | ||
1437 | } | ||
1438 | ld->ccn = receiver->ccn; | ||
1439 | GNUNET_memcpy (&ld[1], | ||
1440 | buf, | ||
1441 | buf_len); | ||
1442 | /* FIXME: this does not provide for flow control! */ | ||
1443 | GSC_send_to_client (receiver->c, | ||
1444 | env); | ||
1445 | send_ack_to_client (ch, | ||
1446 | to_owner); | ||
1447 | return GNUNET_OK; | ||
1448 | } | ||
1449 | |||
1450 | /* Everything is correct, send the message. */ | ||
1451 | crm = GNUNET_malloc (sizeof (*crm)); | ||
1452 | crm->ch = ch; | ||
1453 | crm->data_message = GNUNET_malloc (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) | ||
1454 | + buf_len); | ||
1455 | crm->data_message->header.size = htons (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + buf_len); | ||
1456 | crm->data_message->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA); | ||
1457 | ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1); | ||
1458 | crm->data_message->mid = ch->mid_send; | ||
1459 | crm->data_message->ctn = ch->ctn; | ||
1460 | GNUNET_memcpy (&crm->data_message[1], | ||
1461 | buf, | ||
1462 | buf_len); | ||
1463 | GNUNET_CONTAINER_DLL_insert (ch->head_sent, | ||
1464 | ch->tail_sent, | ||
1465 | crm); | ||
1466 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1467 | "Sending %u bytes from local client to %s\n", | ||
1468 | buf_len, | ||
1469 | GCCH_2s (ch)); | ||
1470 | crm->qe = GCT_send (ch->t, | ||
1471 | &crm->data_message->header, | ||
1472 | &data_sent_cb, | ||
1473 | crm); | ||
1474 | return GNUNET_OK; | ||
1475 | } | ||
1476 | |||
1477 | |||
1478 | /** | ||
1479 | * Handle ACK from client on local channel. Means the client is ready | ||
1480 | * for more data, see if we have any for it. | ||
1481 | * | ||
1482 | * @param ch channel to destroy | ||
1483 | * @param client_ccn ccn of the client sending the ack | ||
1484 | */ | ||
1485 | void | ||
1486 | GCCH_handle_local_ack (struct CadetChannel *ch, | ||
1487 | struct GNUNET_CADET_ClientChannelNumber client_ccn) | ||
1488 | { | ||
1489 | struct CadetChannelClient *ccc; | ||
1490 | struct CadetOutOfOrderMessage *com; | ||
1491 | |||
1492 | if ( (NULL != ch->owner) && | ||
1493 | (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client) ) | ||
1494 | ccc = ch->owner; | ||
1495 | else if ( (NULL != ch->dest) && | ||
1496 | (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client) ) | ||
1497 | ccc = ch->dest; | ||
1498 | else | ||
1499 | GNUNET_assert (0); | ||
1500 | ccc->client_ready = GNUNET_YES; | ||
1501 | com = ccc->head_recv; | ||
1502 | if (NULL == com) | ||
1503 | { | ||
1504 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1505 | "Got LOCAL_ACK, %s-%X ready to receive more data (but none pending)!\n", | ||
1506 | GSC_2s (ccc->c), | ||
1507 | ntohl (ccc->ccn.channel_of_client)); | ||
1508 | return; /* none pending */ | ||
1509 | } | ||
1510 | if ( (com->mid.mid != ch->mid_recv.mid) && | ||
1511 | (GNUNET_NO == ch->out_of_order) ) | ||
1512 | return; /* missing next one in-order */ | ||
1513 | |||
1514 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1515 | "Got LOCAL ACK, passing payload message to %s-%X on %s\n", | ||
1516 | GSC_2s (ccc->c), | ||
1517 | ntohl (ccc->ccn.channel_of_client), | ||
1518 | GCCH_2s (ch)); | ||
1519 | |||
1520 | /* all good, pass next message to client */ | ||
1521 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, | ||
1522 | ccc->tail_recv, | ||
1523 | com); | ||
1524 | /* FIXME: if unreliable, this is not aggressive | ||
1525 | enough, as it would be OK to have lost some! */ | ||
1526 | ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid)); | ||
1527 | ch->mid_futures >>= 1; /* equivalent to division by 2 */ | ||
1528 | ccc->client_ready = GNUNET_NO; | ||
1529 | GSC_send_to_client (ccc->c, | ||
1530 | com->env); | ||
1531 | GNUNET_free (com); | ||
1532 | if ( (0xFFULL == (ch->mid_futures & 0xFFULL)) && | ||
1533 | (GNUNET_YES == ch->reliable) ) | ||
1534 | { | ||
1535 | /* The next 15 messages were also already received (0xFF), this | ||
1536 | suggests that the sender may be blocked on flow control | ||
1537 | urgently waiting for an ACK from us. (As we have an inherent | ||
1538 | maximum of 64 bits, and 15 is getting too close for comfort.) | ||
1539 | So we should send one now. */ | ||
1540 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1541 | "Sender on %s likely blocked on flow-control, sending ACK now.\n", | ||
1542 | GCCH_2s (ch)); | ||
1543 | if (GNUNET_YES == ch->reliable) | ||
1544 | send_channel_data_ack (ch); | ||
1545 | } | ||
1546 | |||
1547 | if (NULL != ccc->head_recv) | ||
1548 | return; | ||
1549 | if (GNUNET_NO == ch->destroy) | ||
1550 | return; | ||
1551 | GCT_send_channel_destroy (ch->t, | ||
1552 | ch->ctn); | ||
1553 | channel_destroy (ch); | ||
1554 | } | ||
1555 | |||
1556 | |||
1557 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__) | ||
1558 | |||
1559 | |||
1560 | /** | ||
1561 | * Log channel info. | ||
1562 | * | ||
1563 | * @param ch Channel. | ||
1564 | * @param level Debug level to use. | ||
1565 | */ | ||
1566 | void | ||
1567 | GCCH_debug (struct CadetChannel *ch, | ||
1568 | enum GNUNET_ErrorType level) | ||
1569 | { | ||
1570 | int do_log; | ||
1571 | |||
1572 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
1573 | "cadet-chn", | ||
1574 | __FILE__, __FUNCTION__, __LINE__); | ||
1575 | if (0 == do_log) | ||
1576 | return; | ||
1577 | |||
1578 | if (NULL == ch) | ||
1579 | { | ||
1580 | LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n"); | ||
1581 | return; | ||
1582 | } | ||
1583 | LOG2 (level, | ||
1584 | "CHN %s:%X (%p)\n", | ||
1585 | GCT_2s (ch->t), | ||
1586 | ch->ctn, | ||
1587 | ch); | ||
1588 | if (NULL != ch->owner) | ||
1589 | { | ||
1590 | LOG2 (level, | ||
1591 | "CHN origin %s ready %s local-id: %u\n", | ||
1592 | GSC_2s (ch->owner->c), | ||
1593 | ch->owner->client_ready ? "YES" : "NO", | ||
1594 | ntohl (ch->owner->ccn.channel_of_client)); | ||
1595 | } | ||
1596 | if (NULL != ch->dest) | ||
1597 | { | ||
1598 | LOG2 (level, | ||
1599 | "CHN destination %s ready %s local-id: %u\n", | ||
1600 | GSC_2s (ch->dest->c), | ||
1601 | ch->dest->client_ready ? "YES" : "NO", | ||
1602 | ntohl (ch->dest->ccn.channel_of_client)); | ||
1603 | } | ||
1604 | LOG2 (level, | ||
1605 | "CHN Message IDs recv: %d (%LLX), send: %d\n", | ||
1606 | ntohl (ch->mid_recv.mid), | ||
1607 | (unsigned long long) ch->mid_futures, | ||
1608 | ntohl (ch->mid_send.mid)); | ||
1609 | } | ||
1610 | |||
1611 | |||
1612 | |||
1613 | /* end of gnunet-service-cadet-new_channel.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new_channel.h b/src/cadet/gnunet-service-cadet-new_channel.h deleted file mode 100644 index e572b7633..000000000 --- a/src/cadet/gnunet-service-cadet-new_channel.h +++ /dev/null | |||
@@ -1,249 +0,0 @@ | |||
1 | |||
2 | /* | ||
3 | This file is part of GNUnet. | ||
4 | Copyright (C) 2001-2017 GNUnet e.V. | ||
5 | |||
6 | GNUnet is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published | ||
8 | by the Free Software Foundation; either version 3, or (at your | ||
9 | option) any later version. | ||
10 | |||
11 | GNUnet is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNUnet; see the file COPYING. If not, write to the | ||
18 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
19 | Boston, MA 02110-1301, USA. | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * @file cadet/gnunet-service-cadet-new_channel.h | ||
24 | * @brief GNUnet CADET service with encryption | ||
25 | * @author Bartlomiej Polot | ||
26 | * @author Christian Grothoff | ||
27 | */ | ||
28 | #ifndef GNUNET_SERVICE_CADET_CHANNEL_H | ||
29 | #define GNUNET_SERVICE_CADET_CHANNEL_H | ||
30 | |||
31 | #include "gnunet-service-cadet-new.h" | ||
32 | #include "gnunet-service-cadet-new_peer.h" | ||
33 | #include "cadet_protocol.h" | ||
34 | |||
35 | |||
36 | /** | ||
37 | * A channel is a bidirectional connection between two CADET | ||
38 | * clients. Communiation can be reliable, unreliable, in-order | ||
39 | * or out-of-order. One client is the "local" client, this | ||
40 | * one initiated the connection. The other client is the | ||
41 | * "incoming" client, this one listened on a port to accept | ||
42 | * the connection from the "local" client. | ||
43 | */ | ||
44 | struct CadetChannel; | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Get the static string for identification of the channel. | ||
49 | * | ||
50 | * @param ch Channel. | ||
51 | * | ||
52 | * @return Static string with the channel IDs. | ||
53 | */ | ||
54 | const char * | ||
55 | GCCH_2s (const struct CadetChannel *ch); | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Log channel info. | ||
60 | * | ||
61 | * @param ch Channel. | ||
62 | * @param level Debug level to use. | ||
63 | */ | ||
64 | void | ||
65 | GCCH_debug (struct CadetChannel *ch, | ||
66 | enum GNUNET_ErrorType level); | ||
67 | |||
68 | |||
69 | /** | ||
70 | * Get the channel's public ID. | ||
71 | * | ||
72 | * @param ch Channel. | ||
73 | * | ||
74 | * @return ID used to identify the channel with the remote peer. | ||
75 | */ | ||
76 | struct GNUNET_CADET_ChannelTunnelNumber | ||
77 | GCCH_get_id (const struct CadetChannel *ch); | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Create a new channel. | ||
82 | * | ||
83 | * @param owner local client owning the channel | ||
84 | * @param owner_id local chid of this channel at the @a owner | ||
85 | * @param destination peer to which we should build the channel | ||
86 | * @param port desired port at @a destination | ||
87 | * @param options options for the channel | ||
88 | * @return handle to the new channel | ||
89 | */ | ||
90 | struct CadetChannel * | ||
91 | GCCH_channel_local_new (struct CadetClient *owner, | ||
92 | struct GNUNET_CADET_ClientChannelNumber owner_id, | ||
93 | struct CadetPeer *destination, | ||
94 | const struct GNUNET_HashCode *port, | ||
95 | uint32_t options); | ||
96 | |||
97 | |||
98 | /** | ||
99 | * A client is bound to the port that we have a channel | ||
100 | * open to. Send the acknowledgement for the connection | ||
101 | * request and establish the link with the client. | ||
102 | * | ||
103 | * @param ch open incoming channel | ||
104 | * @param c client listening on the respective port | ||
105 | */ | ||
106 | void | ||
107 | GCCH_bind (struct CadetChannel *ch, | ||
108 | struct CadetClient *c); | ||
109 | |||
110 | |||
111 | /** | ||
112 | * Destroy locally created channel. Called by the | ||
113 | * local client, so no need to tell the client. | ||
114 | * | ||
115 | * @param ch channel to destroy | ||
116 | * @param c client that caused the destruction | ||
117 | * @param ccn client number of the client @a c | ||
118 | */ | ||
119 | void | ||
120 | GCCH_channel_local_destroy (struct CadetChannel *ch, | ||
121 | struct CadetClient *c, | ||
122 | struct GNUNET_CADET_ClientChannelNumber ccn); | ||
123 | |||
124 | |||
125 | /** | ||
126 | * Function called once and only once after a channel was bound | ||
127 | * to its tunnel via #GCT_add_channel() is ready for transmission. | ||
128 | * Note that this is only the case for channels that this peer | ||
129 | * initiates, as for incoming channels we assume that they are | ||
130 | * ready for transmission immediately upon receiving the open | ||
131 | * message. Used to bootstrap the #GCT_send() process. | ||
132 | * | ||
133 | * @param ch the channel for which the tunnel is now ready | ||
134 | */ | ||
135 | void | ||
136 | GCCH_tunnel_up (struct CadetChannel *ch); | ||
137 | |||
138 | |||
139 | /** | ||
140 | * Create a new channel based on a request coming in over the network. | ||
141 | * | ||
142 | * @param t tunnel to the remote peer | ||
143 | * @param chid identifier of this channel in the tunnel | ||
144 | * @param origin peer to who initiated the channel | ||
145 | * @param port desired local port | ||
146 | * @param options options for the channel | ||
147 | * @return handle to the new channel | ||
148 | */ | ||
149 | struct CadetChannel * | ||
150 | GCCH_channel_incoming_new (struct CadetTunnel *t, | ||
151 | struct GNUNET_CADET_ChannelTunnelNumber chid, | ||
152 | const struct GNUNET_HashCode *port, | ||
153 | uint32_t options); | ||
154 | |||
155 | |||
156 | /** | ||
157 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for | ||
158 | * this channel. If the binding was successful, (re)transmit the | ||
159 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK. | ||
160 | * | ||
161 | * @param ch channel that got the duplicate open | ||
162 | */ | ||
163 | void | ||
164 | GCCH_handle_duplicate_open (struct CadetChannel *ch); | ||
165 | |||
166 | |||
167 | /** | ||
168 | * We got payload data for a channel. Pass it on to the client. | ||
169 | * | ||
170 | * @param ch channel that got data | ||
171 | * @param msg message that was received | ||
172 | */ | ||
173 | void | ||
174 | GCCH_handle_channel_plaintext_data (struct CadetChannel *ch, | ||
175 | const struct GNUNET_CADET_ChannelAppDataMessage *msg); | ||
176 | |||
177 | |||
178 | /** | ||
179 | * We got an acknowledgement for payload data for a channel. | ||
180 | * Possibly resume transmissions. | ||
181 | * | ||
182 | * @param ch channel that got the ack | ||
183 | * @param ack details about what was received | ||
184 | */ | ||
185 | void | ||
186 | GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch, | ||
187 | const struct GNUNET_CADET_ChannelDataAckMessage *ack); | ||
188 | |||
189 | |||
190 | /** | ||
191 | * We got an acknowledgement for the creation of the channel | ||
192 | * (the port is open on the other side). Begin transmissions. | ||
193 | * | ||
194 | * @param ch channel to destroy | ||
195 | */ | ||
196 | void | ||
197 | GCCH_handle_channel_open_ack (struct CadetChannel *ch); | ||
198 | |||
199 | |||
200 | /** | ||
201 | * Destroy channel, based on the other peer closing the | ||
202 | * connection. Also needs to remove this channel from | ||
203 | * the tunnel. | ||
204 | * | ||
205 | * FIXME: need to make it possible to defer destruction until we have | ||
206 | * received all messages up to the destroy, and right now the destroy | ||
207 | * message (and this API) fails to give is the information we need! | ||
208 | * | ||
209 | * FIXME: also need to know if the other peer got a destroy from | ||
210 | * us before! | ||
211 | * | ||
212 | * @param ch channel to destroy | ||
213 | */ | ||
214 | void | ||
215 | GCCH_handle_remote_destroy (struct CadetChannel *ch); | ||
216 | |||
217 | |||
218 | /** | ||
219 | * Handle data given by a client. | ||
220 | * | ||
221 | * Check whether the client is allowed to send in this tunnel, save if | ||
222 | * channel is reliable and send an ACK to the client if there is still | ||
223 | * buffer space in the tunnel. | ||
224 | * | ||
225 | * @param ch Channel. | ||
226 | * @param sender_ccn ccn of the sender | ||
227 | * @param buf payload to transmit. | ||
228 | * @param buf_len number of bytes in @a buf | ||
229 | * @return #GNUNET_OK if everything goes well, | ||
230 | * #GNUNET_SYSERR in case of an error. | ||
231 | */ | ||
232 | int | ||
233 | GCCH_handle_local_data (struct CadetChannel *ch, | ||
234 | struct GNUNET_CADET_ClientChannelNumber sender_ccn, | ||
235 | const char *buf, | ||
236 | size_t buf_len); | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Handle ACK from client on local channel. | ||
241 | * | ||
242 | * @param ch channel to destroy | ||
243 | * @param client_ccn ccn of the client sending the ack | ||
244 | */ | ||
245 | void | ||
246 | GCCH_handle_local_ack (struct CadetChannel *ch, | ||
247 | struct GNUNET_CADET_ClientChannelNumber client_ccn); | ||
248 | |||
249 | #endif | ||
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c b/src/cadet/gnunet-service-cadet-new_connection.c deleted file mode 100644 index 60389008c..000000000 --- a/src/cadet/gnunet-service-cadet-new_connection.c +++ /dev/null | |||
@@ -1,709 +0,0 @@ | |||
1 | |||
2 | /* | ||
3 | This file is part of GNUnet. | ||
4 | Copyright (C) 2001-2017 GNUnet e.V. | ||
5 | |||
6 | GNUnet is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published | ||
8 | by the Free Software Foundation; either version 3, or (at your | ||
9 | option) any later version. | ||
10 | |||
11 | GNUnet is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNUnet; see the file COPYING. If not, write to the | ||
18 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
19 | Boston, MA 02110-1301, USA. | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * @file cadet/gnunet-service-cadet-new_connection.c | ||
24 | * @brief management of CORE-level end-to-end connections; establishes | ||
25 | * end-to-end routes and transmits messages along the route | ||
26 | * @author Bartlomiej Polot | ||
27 | * @author Christian Grothoff | ||
28 | * | ||
29 | * TODO: | ||
30 | * - Optimization: keepalive messages / timeout (timeout to be done @ peer level!) | ||
31 | * - Optimization: keep performance metrics (?) | ||
32 | */ | ||
33 | #include "platform.h" | ||
34 | #include "gnunet-service-cadet-new_channel.h" | ||
35 | #include "gnunet-service-cadet-new_connection.h" | ||
36 | #include "gnunet-service-cadet-new_paths.h" | ||
37 | #include "gnunet-service-cadet-new_peer.h" | ||
38 | #include "gnunet-service-cadet-new_tunnels.h" | ||
39 | #include "gnunet_cadet_service.h" | ||
40 | #include "cadet_protocol.h" | ||
41 | |||
42 | |||
43 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__) | ||
44 | |||
45 | |||
46 | /** | ||
47 | * All the states a connection can be in. | ||
48 | */ | ||
49 | enum CadetConnectionState | ||
50 | { | ||
51 | /** | ||
52 | * Uninitialized status, we have not yet even gotten the message queue. | ||
53 | */ | ||
54 | CADET_CONNECTION_NEW, | ||
55 | |||
56 | /** | ||
57 | * Connection create message in queue, awaiting transmission by CORE. | ||
58 | */ | ||
59 | CADET_CONNECTION_SENDING_CREATE, | ||
60 | |||
61 | /** | ||
62 | * Connection create message sent, waiting for ACK. | ||
63 | */ | ||
64 | CADET_CONNECTION_SENT, | ||
65 | |||
66 | /** | ||
67 | * We are an inbound connection, and received a CREATE. Need to | ||
68 | * send an CREATE_ACK back. | ||
69 | */ | ||
70 | CADET_CONNECTION_CREATE_RECEIVED, | ||
71 | |||
72 | /** | ||
73 | * Connection confirmed, ready to carry traffic. | ||
74 | */ | ||
75 | CADET_CONNECTION_READY | ||
76 | |||
77 | }; | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Low-level connection to a destination. | ||
82 | */ | ||
83 | struct CadetConnection | ||
84 | { | ||
85 | |||
86 | /** | ||
87 | * ID of the connection. | ||
88 | */ | ||
89 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
90 | |||
91 | /** | ||
92 | * To which peer does this connection go? | ||
93 | */ | ||
94 | struct CadetPeer *destination; | ||
95 | |||
96 | /** | ||
97 | * Which tunnel is using this connection? | ||
98 | */ | ||
99 | struct CadetTConnection *ct; | ||
100 | |||
101 | /** | ||
102 | * Path we are using to our destination. | ||
103 | */ | ||
104 | struct CadetPeerPath *path; | ||
105 | |||
106 | /** | ||
107 | * Pending message, NULL if we are ready to transmit. | ||
108 | */ | ||
109 | struct GNUNET_MQ_Envelope *env; | ||
110 | |||
111 | /** | ||
112 | * Handle for calling #GCP_request_mq_cancel() once we are finished. | ||
113 | */ | ||
114 | struct GCP_MessageQueueManager *mq_man; | ||
115 | |||
116 | /** | ||
117 | * Task for connection maintenance. | ||
118 | */ | ||
119 | struct GNUNET_SCHEDULER_Task *task; | ||
120 | |||
121 | /** | ||
122 | * Function to call once we are ready to transmit. | ||
123 | */ | ||
124 | GCC_ReadyCallback ready_cb; | ||
125 | |||
126 | /** | ||
127 | * Closure for @e ready_cb. | ||
128 | */ | ||
129 | void *ready_cb_cls; | ||
130 | |||
131 | /** | ||
132 | * How long do we wait before we try again with a CREATE message? | ||
133 | */ | ||
134 | struct GNUNET_TIME_Relative retry_delay; | ||
135 | |||
136 | /** | ||
137 | * State of the connection. | ||
138 | */ | ||
139 | enum CadetConnectionState state; | ||
140 | |||
141 | /** | ||
142 | * Offset of our @e destination in @e path. | ||
143 | */ | ||
144 | unsigned int off; | ||
145 | |||
146 | /** | ||
147 | * Are we ready to transmit via @e mq_man right now? | ||
148 | */ | ||
149 | int mqm_ready; | ||
150 | |||
151 | }; | ||
152 | |||
153 | |||
154 | /** | ||
155 | * Destroy a connection. | ||
156 | * | ||
157 | * @param cc connection to destroy | ||
158 | */ | ||
159 | void | ||
160 | GCC_destroy (struct CadetConnection *cc) | ||
161 | { | ||
162 | struct GNUNET_MQ_Envelope *env = NULL; | ||
163 | |||
164 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
165 | "Destroying %s\n", | ||
166 | GCC_2s (cc)); | ||
167 | if (CADET_CONNECTION_SENDING_CREATE != cc->state) | ||
168 | { | ||
169 | struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg; | ||
170 | |||
171 | /* Need to notify next hop that we are down. */ | ||
172 | env = GNUNET_MQ_msg (destroy_msg, | ||
173 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); | ||
174 | destroy_msg->cid = cc->cid; | ||
175 | } | ||
176 | if (NULL != cc->mq_man) | ||
177 | { | ||
178 | GCP_request_mq_cancel (cc->mq_man, | ||
179 | env); | ||
180 | cc->mq_man = NULL; | ||
181 | } | ||
182 | if (NULL != cc->task) | ||
183 | { | ||
184 | GNUNET_SCHEDULER_cancel (cc->task); | ||
185 | cc->task = NULL; | ||
186 | } | ||
187 | GCPP_del_connection (cc->path, | ||
188 | cc->off, | ||
189 | cc); | ||
190 | GNUNET_assert (GNUNET_YES == | ||
191 | GNUNET_CONTAINER_multishortmap_remove (connections, | ||
192 | &GCC_get_id (cc)->connection_of_tunnel, | ||
193 | cc)); | ||
194 | GNUNET_free (cc); | ||
195 | } | ||
196 | |||
197 | |||
198 | /** | ||
199 | * Return the tunnel associated with this connection. | ||
200 | * | ||
201 | * @param cc connection to query | ||
202 | * @return corresponding entry in the tunnel's connection list | ||
203 | */ | ||
204 | struct CadetTConnection * | ||
205 | GCC_get_ct (struct CadetConnection *cc) | ||
206 | { | ||
207 | return cc->ct; | ||
208 | } | ||
209 | |||
210 | |||
211 | /** | ||
212 | * A CADET_CONNECTION_ACK was received for this connection, implying | ||
213 | * that the end-to-end connection is up. Process it. | ||
214 | * | ||
215 | * @param cc the connection that got the ACK. | ||
216 | */ | ||
217 | void | ||
218 | GCC_handle_connection_create_ack (struct CadetConnection *cc) | ||
219 | { | ||
220 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
221 | "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n", | ||
222 | GCC_2s (cc), | ||
223 | cc->state, | ||
224 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); | ||
225 | if (NULL != cc->task) | ||
226 | { | ||
227 | GNUNET_SCHEDULER_cancel (cc->task); | ||
228 | cc->task = NULL; | ||
229 | } | ||
230 | #if FIXME_KEEPALIVE | ||
231 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->keepalive_period, | ||
232 | &send_keepalive, | ||
233 | cc); | ||
234 | #endif | ||
235 | cc->state = CADET_CONNECTION_READY; | ||
236 | if (GNUNET_YES == cc->mqm_ready) | ||
237 | cc->ready_cb (cc->ready_cb_cls, | ||
238 | GNUNET_YES); | ||
239 | } | ||
240 | |||
241 | |||
242 | /** | ||
243 | * Handle KX message. | ||
244 | * | ||
245 | * @param cc connection that received encrypted message | ||
246 | * @param msg the key exchange message | ||
247 | */ | ||
248 | void | ||
249 | GCC_handle_kx (struct CadetConnection *cc, | ||
250 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
251 | { | ||
252 | if (CADET_CONNECTION_SENT == cc->state) | ||
253 | { | ||
254 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, | ||
255 | clearly something is working, so pretend we got an ACK. */ | ||
256 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
257 | "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n", | ||
258 | GCC_2s (cc)); | ||
259 | GCC_handle_connection_create_ack (cc); | ||
260 | } | ||
261 | GCT_handle_kx (cc->ct, | ||
262 | msg); | ||
263 | } | ||
264 | |||
265 | |||
266 | /** | ||
267 | * Handle encrypted message. | ||
268 | * | ||
269 | * @param cc connection that received encrypted message | ||
270 | * @param msg the encrypted message to decrypt | ||
271 | */ | ||
272 | void | ||
273 | GCC_handle_encrypted (struct CadetConnection *cc, | ||
274 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
275 | { | ||
276 | if (CADET_CONNECTION_SENT == cc->state) | ||
277 | { | ||
278 | /* We didn't get the CREATE_ACK, but instead got payload. That's fine, | ||
279 | clearly something is working, so pretend we got an ACK. */ | ||
280 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
281 | "Faking connection ACK for %s due to ENCRYPTED payload\n", | ||
282 | GCC_2s (cc)); | ||
283 | GCC_handle_connection_create_ack (cc); | ||
284 | } | ||
285 | GCT_handle_encrypted (cc->ct, | ||
286 | msg); | ||
287 | } | ||
288 | |||
289 | |||
290 | /** | ||
291 | * Send a CREATE message to the first hop. | ||
292 | * | ||
293 | * @param cls the `struct CadetConnection` to initiate | ||
294 | */ | ||
295 | static void | ||
296 | send_create (void *cls) | ||
297 | { | ||
298 | struct CadetConnection *cc = cls; | ||
299 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; | ||
300 | struct GNUNET_PeerIdentity *pids; | ||
301 | struct GNUNET_MQ_Envelope *env; | ||
302 | unsigned int path_length; | ||
303 | |||
304 | cc->task = NULL; | ||
305 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
306 | path_length = GCPP_get_length (cc->path); | ||
307 | env = GNUNET_MQ_msg_extra (create_msg, | ||
308 | (1 + path_length) * sizeof (struct GNUNET_PeerIdentity), | ||
309 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | ||
310 | create_msg->cid = cc->cid; | ||
311 | pids = (struct GNUNET_PeerIdentity *) &create_msg[1]; | ||
312 | pids[0] = my_full_id; | ||
313 | for (unsigned int i=0;i<path_length;i++) | ||
314 | pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, | ||
315 | i)); | ||
316 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
317 | "Sending CADET_CONNECTION_CREATE message for %s\n", | ||
318 | GCC_2s (cc)); | ||
319 | cc->env = env; | ||
320 | cc->mqm_ready = GNUNET_NO; | ||
321 | cc->state = CADET_CONNECTION_SENT; | ||
322 | GCP_send (cc->mq_man, | ||
323 | env); | ||
324 | } | ||
325 | |||
326 | |||
327 | /** | ||
328 | * Send a CREATE_ACK message towards the origin. | ||
329 | * | ||
330 | * @param cls the `struct CadetConnection` to initiate | ||
331 | */ | ||
332 | static void | ||
333 | send_create_ack (void *cls) | ||
334 | { | ||
335 | struct CadetConnection *cc = cls; | ||
336 | struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg; | ||
337 | struct GNUNET_MQ_Envelope *env; | ||
338 | |||
339 | cc->task = NULL; | ||
340 | GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state); | ||
341 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
342 | "Sending CONNECTION_CREATE_ACK message for %s\n", | ||
343 | GCC_2s (cc)); | ||
344 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
345 | env = GNUNET_MQ_msg (ack_msg, | ||
346 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK); | ||
347 | ack_msg->cid = cc->cid; | ||
348 | cc->env = env; | ||
349 | cc->mqm_ready = GNUNET_NO; | ||
350 | cc->state = CADET_CONNECTION_READY; | ||
351 | GCP_send (cc->mq_man, | ||
352 | env); | ||
353 | } | ||
354 | |||
355 | |||
356 | /** | ||
357 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a | ||
358 | * connection that we already have. Either our ACK got lost | ||
359 | * or something is fishy. Consider retransmitting the ACK. | ||
360 | * | ||
361 | * @param cc connection that got the duplicate CREATE | ||
362 | */ | ||
363 | void | ||
364 | GCC_handle_duplicate_create (struct CadetConnection *cc) | ||
365 | { | ||
366 | if (GNUNET_YES == cc->mqm_ready) | ||
367 | { | ||
368 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
369 | "Got duplicate CREATE for %s, scheduling another ACK (%s)\n", | ||
370 | GCC_2s (cc), | ||
371 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); | ||
372 | /* Tell tunnel that we are not ready for transmission anymore | ||
373 | (until CREATE_ACK is done) */ | ||
374 | cc->ready_cb (cc->ready_cb_cls, | ||
375 | GNUNET_NO); | ||
376 | /* Revert back to the state of having only received the 'CREATE', | ||
377 | and immediately proceed to send the CREATE_ACK. */ | ||
378 | cc->state = CADET_CONNECTION_CREATE_RECEIVED; | ||
379 | if (NULL != cc->task) | ||
380 | GNUNET_SCHEDULER_cancel (cc->task); | ||
381 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | ||
382 | cc); | ||
383 | } | ||
384 | else | ||
385 | { | ||
386 | /* We are currently sending something else back, which | ||
387 | can only be an ACK or payload, either of which would | ||
388 | do. So actually no need to do anything. */ | ||
389 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
390 | "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n", | ||
391 | GCC_2s (cc)); | ||
392 | } | ||
393 | } | ||
394 | |||
395 | |||
396 | /** | ||
397 | * There has been a change in the message queue existence for our | ||
398 | * peer at the first hop. Adjust accordingly. | ||
399 | * | ||
400 | * @param cls the `struct CadetConnection` | ||
401 | * @param available #GNUNET_YES if sending is now possible, | ||
402 | * #GNUNET_NO if sending is no longer possible | ||
403 | * #GNUNET_SYSERR if sending is no longer possible | ||
404 | * and the last envelope was discarded | ||
405 | */ | ||
406 | static void | ||
407 | manage_first_hop_mq (void *cls, | ||
408 | int available) | ||
409 | { | ||
410 | struct CadetConnection *cc = cls; | ||
411 | |||
412 | if (GNUNET_YES != available) | ||
413 | { | ||
414 | /* Connection is down, for now... */ | ||
415 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
416 | "Core MQ for %s went down\n", | ||
417 | GCC_2s (cc)); | ||
418 | cc->mqm_ready = GNUNET_NO; | ||
419 | cc->state = CADET_CONNECTION_NEW; | ||
420 | cc->retry_delay = GNUNET_TIME_UNIT_ZERO; | ||
421 | if (NULL != cc->task) | ||
422 | { | ||
423 | GNUNET_SCHEDULER_cancel (cc->task); | ||
424 | cc->task = NULL; | ||
425 | } | ||
426 | cc->ready_cb (cc->ready_cb_cls, | ||
427 | GNUNET_NO); | ||
428 | return; | ||
429 | } | ||
430 | |||
431 | cc->mqm_ready = GNUNET_YES; | ||
432 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
433 | "Core MQ for %s became available in state %d\n", | ||
434 | GCC_2s (cc), | ||
435 | cc->state); | ||
436 | switch (cc->state) | ||
437 | { | ||
438 | case CADET_CONNECTION_NEW: | ||
439 | /* Transmit immediately */ | ||
440 | cc->task = GNUNET_SCHEDULER_add_now (&send_create, | ||
441 | cc); | ||
442 | break; | ||
443 | case CADET_CONNECTION_SENDING_CREATE: | ||
444 | /* Should not be possible to be called in this state. */ | ||
445 | GNUNET_assert (0); | ||
446 | break; | ||
447 | case CADET_CONNECTION_SENT: | ||
448 | /* Retry a bit later... */ | ||
449 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
450 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay, | ||
451 | &send_create, | ||
452 | cc); | ||
453 | break; | ||
454 | case CADET_CONNECTION_CREATE_RECEIVED: | ||
455 | /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */ | ||
456 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | ||
457 | cc); | ||
458 | break; | ||
459 | case CADET_CONNECTION_READY: | ||
460 | cc->ready_cb (cc->ready_cb_cls, | ||
461 | GNUNET_YES); | ||
462 | break; | ||
463 | } | ||
464 | } | ||
465 | |||
466 | |||
467 | /** | ||
468 | * Create a connection to @a destination via @a path and notify @a cb | ||
469 | * whenever we are ready for more data. Shared logic independent of | ||
470 | * who is initiating the connection. | ||
471 | * | ||
472 | * @param destination where to go | ||
473 | * @param path which path to take (may not be the full path) | ||
474 | * @param ct which tunnel uses this connection | ||
475 | * @param init_state initial state for the connection | ||
476 | * @param ready_cb function to call when ready to transmit | ||
477 | * @param ready_cb_cls closure for @a cb | ||
478 | * @return handle to the connection | ||
479 | */ | ||
480 | static struct CadetConnection * | ||
481 | connection_create (struct CadetPeer *destination, | ||
482 | struct CadetPeerPath *path, | ||
483 | struct CadetTConnection *ct, | ||
484 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
485 | enum CadetConnectionState init_state, | ||
486 | GCC_ReadyCallback ready_cb, | ||
487 | void *ready_cb_cls) | ||
488 | { | ||
489 | struct CadetConnection *cc; | ||
490 | struct CadetPeer *first_hop; | ||
491 | unsigned int off; | ||
492 | |||
493 | off = GCPP_find_peer (path, | ||
494 | destination); | ||
495 | GNUNET_assert (UINT_MAX > off); | ||
496 | cc = GNUNET_new (struct CadetConnection); | ||
497 | cc->state = init_state; | ||
498 | cc->ct = ct; | ||
499 | cc->cid = *cid; | ||
500 | GNUNET_assert (GNUNET_OK == | ||
501 | GNUNET_CONTAINER_multishortmap_put (connections, | ||
502 | &GCC_get_id (cc)->connection_of_tunnel, | ||
503 | cc, | ||
504 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
505 | cc->ready_cb = ready_cb; | ||
506 | cc->ready_cb_cls = ready_cb_cls; | ||
507 | cc->path = path; | ||
508 | cc->off = off; | ||
509 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
510 | "Creating %s using path %s\n", | ||
511 | GCC_2s (cc), | ||
512 | GCPP_2s (path)); | ||
513 | GCPP_add_connection (path, | ||
514 | off, | ||
515 | cc); | ||
516 | for (unsigned int i=0;i<off;i++) | ||
517 | GCP_add_connection (GCPP_get_peer_at_offset (path, | ||
518 | off), | ||
519 | cc); | ||
520 | |||
521 | first_hop = GCPP_get_peer_at_offset (path, | ||
522 | 0); | ||
523 | cc->mq_man = GCP_request_mq (first_hop, | ||
524 | &manage_first_hop_mq, | ||
525 | cc); | ||
526 | return cc; | ||
527 | } | ||
528 | |||
529 | |||
530 | /** | ||
531 | * Create a connection to @a destination via @a path and | ||
532 | * notify @a cb whenever we are ready for more data. This | ||
533 | * is an inbound tunnel, so we must use the existing @a cid | ||
534 | * | ||
535 | * @param destination where to go | ||
536 | * @param path which path to take (may not be the full path) | ||
537 | * @param ct which tunnel uses this connection | ||
538 | * @param ready_cb function to call when ready to transmit | ||
539 | * @param ready_cb_cls closure for @a cb | ||
540 | * @return handle to the connection | ||
541 | */ | ||
542 | struct CadetConnection * | ||
543 | GCC_create_inbound (struct CadetPeer *destination, | ||
544 | struct CadetPeerPath *path, | ||
545 | struct CadetTConnection *ct, | ||
546 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
547 | GCC_ReadyCallback ready_cb, | ||
548 | void *ready_cb_cls) | ||
549 | { | ||
550 | return connection_create (destination, | ||
551 | path, | ||
552 | ct, | ||
553 | cid, | ||
554 | CADET_CONNECTION_CREATE_RECEIVED, | ||
555 | ready_cb, | ||
556 | ready_cb_cls); | ||
557 | } | ||
558 | |||
559 | |||
560 | /** | ||
561 | * Create a connection to @a destination via @a path and | ||
562 | * notify @a cb whenever we are ready for more data. | ||
563 | * | ||
564 | * @param destination where to go | ||
565 | * @param path which path to take (may not be the full path) | ||
566 | * @param ct tunnel that uses the connection | ||
567 | * @param ready_cb function to call when ready to transmit | ||
568 | * @param ready_cb_cls closure for @a cb | ||
569 | * @return handle to the connection | ||
570 | */ | ||
571 | struct CadetConnection * | ||
572 | GCC_create (struct CadetPeer *destination, | ||
573 | struct CadetPeerPath *path, | ||
574 | struct CadetTConnection *ct, | ||
575 | GCC_ReadyCallback ready_cb, | ||
576 | void *ready_cb_cls) | ||
577 | { | ||
578 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
579 | |||
580 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | ||
581 | &cid, | ||
582 | sizeof (cid)); | ||
583 | return connection_create (destination, | ||
584 | path, | ||
585 | ct, | ||
586 | &cid, | ||
587 | CADET_CONNECTION_NEW, | ||
588 | ready_cb, | ||
589 | ready_cb_cls); | ||
590 | } | ||
591 | |||
592 | |||
593 | /** | ||
594 | * Transmit message @a msg via connection @a cc. Must only be called | ||
595 | * (once) after the connection has signalled that it is ready via the | ||
596 | * `ready_cb`. Clients can also use #GCC_is_ready() to check if the | ||
597 | * connection is right now ready for transmission. | ||
598 | * | ||
599 | * @param cc connection identification | ||
600 | * @param env envelope with message to transmit; must NOT | ||
601 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
602 | */ | ||
603 | void | ||
604 | GCC_transmit (struct CadetConnection *cc, | ||
605 | struct GNUNET_MQ_Envelope *env) | ||
606 | { | ||
607 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
608 | "Scheduling message for transmission on %s\n", | ||
609 | GCC_2s (cc)); | ||
610 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | ||
611 | GNUNET_assert (CADET_CONNECTION_READY == cc->state); | ||
612 | cc->mqm_ready = GNUNET_NO; | ||
613 | GCP_send (cc->mq_man, | ||
614 | env); | ||
615 | } | ||
616 | |||
617 | |||
618 | /** | ||
619 | * Obtain the path used by this connection. | ||
620 | * | ||
621 | * @param cc connection | ||
622 | * @return path to @a cc | ||
623 | */ | ||
624 | struct CadetPeerPath * | ||
625 | GCC_get_path (struct CadetConnection *cc) | ||
626 | { | ||
627 | return cc->path; | ||
628 | } | ||
629 | |||
630 | |||
631 | /** | ||
632 | * Obtain unique ID for the connection. | ||
633 | * | ||
634 | * @param cc connection. | ||
635 | * @return unique number of the connection | ||
636 | */ | ||
637 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
638 | GCC_get_id (struct CadetConnection *cc) | ||
639 | { | ||
640 | return &cc->cid; | ||
641 | } | ||
642 | |||
643 | |||
644 | /** | ||
645 | * Get a (static) string for a connection. | ||
646 | * | ||
647 | * @param cc Connection. | ||
648 | */ | ||
649 | const char * | ||
650 | GCC_2s (const struct CadetConnection *cc) | ||
651 | { | ||
652 | static char buf[128]; | ||
653 | |||
654 | if (NULL == cc) | ||
655 | return "Connection(NULL)"; | ||
656 | |||
657 | if (NULL != cc->ct) | ||
658 | { | ||
659 | GNUNET_snprintf (buf, | ||
660 | sizeof (buf), | ||
661 | "Connection %s (%s)", | ||
662 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
663 | GCT_2s (cc->ct->t)); | ||
664 | return buf; | ||
665 | } | ||
666 | GNUNET_snprintf (buf, | ||
667 | sizeof (buf), | ||
668 | "Connection %s", | ||
669 | GNUNET_sh2s (&cc->cid.connection_of_tunnel)); | ||
670 | return buf; | ||
671 | } | ||
672 | |||
673 | |||
674 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__) | ||
675 | |||
676 | |||
677 | /** | ||
678 | * Log connection info. | ||
679 | * | ||
680 | * @param cc connection | ||
681 | * @param level Debug level to use. | ||
682 | */ | ||
683 | void | ||
684 | GCC_debug (struct CadetConnection *cc, | ||
685 | enum GNUNET_ErrorType level) | ||
686 | { | ||
687 | int do_log; | ||
688 | |||
689 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
690 | "cadet-con", | ||
691 | __FILE__, __FUNCTION__, __LINE__); | ||
692 | if (0 == do_log) | ||
693 | return; | ||
694 | if (NULL == cc) | ||
695 | { | ||
696 | LOG2 (level, | ||
697 | "Connection (NULL)\n"); | ||
698 | return; | ||
699 | } | ||
700 | LOG2 (level, | ||
701 | "%s to %s via path %s in state %d is %s\n", | ||
702 | GCC_2s (cc), | ||
703 | GCP_2s (cc->destination), | ||
704 | GCPP_2s (cc->path), | ||
705 | cc->state, | ||
706 | (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy"); | ||
707 | } | ||
708 | |||
709 | /* end of gnunet-service-cadet-new_connection.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new_connection.h b/src/cadet/gnunet-service-cadet-new_connection.h deleted file mode 100644 index efdf9929a..000000000 --- a/src/cadet/gnunet-service-cadet-new_connection.h +++ /dev/null | |||
@@ -1,207 +0,0 @@ | |||
1 | |||
2 | /* | ||
3 | This file is part of GNUnet. | ||
4 | Copyright (C) 2001-2017 GNUnet e.V. | ||
5 | |||
6 | GNUnet is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published | ||
8 | by the Free Software Foundation; either version 3, or (at your | ||
9 | option) any later version. | ||
10 | |||
11 | GNUnet is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNUnet; see the file COPYING. If not, write to the | ||
18 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
19 | Boston, MA 02110-1301, USA. | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * @file cadet/gnunet-service-cadet-new_connection.h | ||
24 | * @brief | ||
25 | * @author Bartlomiej Polot | ||
26 | * @author Christian Grothoff | ||
27 | */ | ||
28 | #ifndef GNUNET_SERVICE_CADET_CONNECTION_H | ||
29 | #define GNUNET_SERVICE_CADET_CONNECTION_H | ||
30 | |||
31 | #include "gnunet_util_lib.h" | ||
32 | #include "gnunet-service-cadet-new.h" | ||
33 | #include "gnunet-service-cadet-new_peer.h" | ||
34 | #include "cadet_protocol.h" | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Function called to notify tunnel about change in our readyness. | ||
39 | * | ||
40 | * @param cls closure | ||
41 | * @param is_ready #GNUNET_YES if the connection is now ready for transmission, | ||
42 | * #GNUNET_NO if the connection is no longer ready for transmission | ||
43 | */ | ||
44 | typedef void | ||
45 | (*GCC_ReadyCallback)(void *cls, | ||
46 | int is_ready); | ||
47 | |||
48 | |||
49 | /** | ||
50 | * Destroy a connection. | ||
51 | * | ||
52 | * @param cc connection to destroy | ||
53 | */ | ||
54 | void | ||
55 | GCC_destroy (struct CadetConnection *cc); | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Create a connection to @a destination via @a path and | ||
60 | * notify @a cb whenever we are ready for more data. | ||
61 | * | ||
62 | * @param destination where to go | ||
63 | * @param path which path to take (may not be the full path) | ||
64 | * @param ct which tunnel uses this connection | ||
65 | * @param ready_cb function to call when ready to transmit | ||
66 | * @param ready_cb_cls closure for @a cb | ||
67 | * @return handle to the connection | ||
68 | */ | ||
69 | struct CadetConnection * | ||
70 | GCC_create (struct CadetPeer *destination, | ||
71 | struct CadetPeerPath *path, | ||
72 | struct CadetTConnection *ct, | ||
73 | GCC_ReadyCallback ready_cb, | ||
74 | void *ready_cb_cls); | ||
75 | |||
76 | |||
77 | /** | ||
78 | * Create a connection to @a destination via @a path and | ||
79 | * notify @a cb whenever we are ready for more data. This | ||
80 | * is an inbound tunnel, so we must use the existing @a cid | ||
81 | * | ||
82 | * @param destination where to go | ||
83 | * @param path which path to take (may not be the full path) | ||
84 | * @param ct which tunnel uses this connection | ||
85 | * @param ready_cb function to call when ready to transmit | ||
86 | * @param ready_cb_cls closure for @a cb | ||
87 | * @return handle to the connection | ||
88 | */ | ||
89 | struct CadetConnection * | ||
90 | GCC_create_inbound (struct CadetPeer *destination, | ||
91 | struct CadetPeerPath *path, | ||
92 | struct CadetTConnection *ct, | ||
93 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
94 | GCC_ReadyCallback ready_cb, | ||
95 | void *ready_cb_cls); | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Transmit message @a msg via connection @a cc. Must only be called | ||
100 | * (once) after the connection has signalled that it is ready via the | ||
101 | * `ready_cb`. Clients can also use #GCC_is_ready() to check if the | ||
102 | * connection is right now ready for transmission. | ||
103 | * | ||
104 | * @param cc connection identification | ||
105 | * @param env envelope with message to transmit; | ||
106 | * the #GNUNET_MQ_notify_send() must not have yet been used | ||
107 | * for the envelope. Also, the message better match the | ||
108 | * connection identifier of this connection... | ||
109 | */ | ||
110 | void | ||
111 | GCC_transmit (struct CadetConnection *cc, | ||
112 | struct GNUNET_MQ_Envelope *env); | ||
113 | |||
114 | |||
115 | /** | ||
116 | * A CREATE_ACK was received for this connection, process it. | ||
117 | * | ||
118 | * @param cc the connection that got the ACK. | ||
119 | */ | ||
120 | void | ||
121 | GCC_handle_connection_create_ack (struct CadetConnection *cc); | ||
122 | |||
123 | |||
124 | /** | ||
125 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a | ||
126 | * connection that we already have. Either our ACK got lost | ||
127 | * or something is fishy. Consider retransmitting the ACK. | ||
128 | * | ||
129 | * @param cc connection that got the duplicate CREATE | ||
130 | */ | ||
131 | void | ||
132 | GCC_handle_duplicate_create (struct CadetConnection *cc); | ||
133 | |||
134 | |||
135 | /** | ||
136 | * Handle KX message. | ||
137 | * | ||
138 | * @param cc connection that received encrypted message | ||
139 | * @param msg the key exchange message | ||
140 | */ | ||
141 | void | ||
142 | GCC_handle_kx (struct CadetConnection *cc, | ||
143 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg); | ||
144 | |||
145 | |||
146 | /** | ||
147 | * Handle encrypted message. | ||
148 | * | ||
149 | * @param cc connection that received encrypted message | ||
150 | * @param msg the encrypted message to decrypt | ||
151 | */ | ||
152 | void | ||
153 | GCC_handle_encrypted (struct CadetConnection *cc, | ||
154 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg); | ||
155 | |||
156 | |||
157 | /** | ||
158 | * Return the tunnel associated with this connection. | ||
159 | * | ||
160 | * @param cc connection to query | ||
161 | * @return corresponding entry in the tunnel's connection list | ||
162 | */ | ||
163 | struct CadetTConnection * | ||
164 | GCC_get_ct (struct CadetConnection *cc); | ||
165 | |||
166 | |||
167 | /** | ||
168 | * Obtain the path used by this connection. | ||
169 | * | ||
170 | * @param cc connection | ||
171 | * @return path to @a cc | ||
172 | */ | ||
173 | struct CadetPeerPath * | ||
174 | GCC_get_path (struct CadetConnection *cc); | ||
175 | |||
176 | |||
177 | /** | ||
178 | * Obtain unique ID for the connection. | ||
179 | * | ||
180 | * @param cc connection. | ||
181 | * @return unique number of the connection | ||
182 | */ | ||
183 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
184 | GCC_get_id (struct CadetConnection *cc); | ||
185 | |||
186 | |||
187 | /** | ||
188 | * Get a (static) string for a connection. | ||
189 | * | ||
190 | * @param cc Connection. | ||
191 | */ | ||
192 | const char * | ||
193 | GCC_2s (const struct CadetConnection *cc); | ||
194 | |||
195 | |||
196 | /** | ||
197 | * Log connection info. | ||
198 | * | ||
199 | * @param cc connection | ||
200 | * @param level Debug level to use. | ||
201 | */ | ||
202 | void | ||
203 | GCC_debug (struct CadetConnection *cc, | ||
204 | enum GNUNET_ErrorType level); | ||
205 | |||
206 | |||
207 | #endif | ||
diff --git a/src/cadet/gnunet-service-cadet-new_dht.c b/src/cadet/gnunet-service-cadet-new_dht.c deleted file mode 100644 index 849562f23..000000000 --- a/src/cadet/gnunet-service-cadet-new_dht.c +++ /dev/null | |||
@@ -1,351 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet-new_dht.c | ||
22 | * @brief Information we track per peer. | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_dht_service.h" | ||
30 | #include "gnunet_statistics_service.h" | ||
31 | #include "gnunet-service-cadet-new.h" | ||
32 | #include "gnunet-service-cadet-new_dht.h" | ||
33 | #include "gnunet-service-cadet-new_hello.h" | ||
34 | #include "gnunet-service-cadet-new_peer.h" | ||
35 | #include "gnunet-service-cadet-new_paths.h" | ||
36 | |||
37 | /** | ||
38 | * How long do we wait before first announcing our presence to the DHT. | ||
39 | * Used to wait for our HELLO to be available. Note that we also get | ||
40 | * notifications when our HELLO is ready, so this is just the maximum | ||
41 | * we wait for the first notification. | ||
42 | */ | ||
43 | #define STARTUP_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500) | ||
44 | |||
45 | /** | ||
46 | * How long do we wait after we get an updated HELLO before publishing? | ||
47 | * Allows for the HELLO to be updated again quickly, for example in | ||
48 | * case multiple addresses changed and we got a partial update. | ||
49 | */ | ||
50 | #define CHANGE_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100) | ||
51 | |||
52 | |||
53 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__) | ||
54 | |||
55 | |||
56 | /** | ||
57 | * Handle for DHT searches. | ||
58 | */ | ||
59 | struct GCD_search_handle | ||
60 | { | ||
61 | /** | ||
62 | * DHT_GET handle. | ||
63 | */ | ||
64 | struct GNUNET_DHT_GetHandle *dhtget; | ||
65 | |||
66 | }; | ||
67 | |||
68 | |||
69 | /** | ||
70 | * Handle to use DHT. | ||
71 | */ | ||
72 | static struct GNUNET_DHT_Handle *dht_handle; | ||
73 | |||
74 | /** | ||
75 | * How often to PUT own ID in the DHT. | ||
76 | */ | ||
77 | static struct GNUNET_TIME_Relative id_announce_time; | ||
78 | |||
79 | /** | ||
80 | * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put(). | ||
81 | */ | ||
82 | static unsigned long long dht_replication_level; | ||
83 | |||
84 | /** | ||
85 | * Task to periodically announce itself in the network. | ||
86 | */ | ||
87 | static struct GNUNET_SCHEDULER_Task *announce_id_task; | ||
88 | |||
89 | /** | ||
90 | * Delay for the next ID announce. | ||
91 | */ | ||
92 | static struct GNUNET_TIME_Relative announce_delay; | ||
93 | |||
94 | |||
95 | /** | ||
96 | * Function to process paths received for a new peer addition. The recorded | ||
97 | * paths form the initial tunnel, which can be optimized later. | ||
98 | * Called on each result obtained for the DHT search. | ||
99 | * | ||
100 | * @param cls closure | ||
101 | * @param exp when will this value expire | ||
102 | * @param key key of the result | ||
103 | * @param get_path path of the get request | ||
104 | * @param get_path_length lenght of @a get_path | ||
105 | * @param put_path path of the put request | ||
106 | * @param put_path_length length of the @a put_path | ||
107 | * @param type type of the result | ||
108 | * @param size number of bytes in data | ||
109 | * @param data pointer to the result data | ||
110 | */ | ||
111 | static void | ||
112 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
113 | const struct GNUNET_HashCode *key, | ||
114 | const struct GNUNET_PeerIdentity *get_path, | ||
115 | unsigned int get_path_length, | ||
116 | const struct GNUNET_PeerIdentity *put_path, | ||
117 | unsigned int put_path_length, | ||
118 | enum GNUNET_BLOCK_Type type, | ||
119 | size_t size, | ||
120 | const void *data) | ||
121 | { | ||
122 | const struct GNUNET_HELLO_Message *hello = data; | ||
123 | struct CadetPeer *peer; | ||
124 | |||
125 | GCPP_try_path_from_dht (get_path, | ||
126 | get_path_length, | ||
127 | put_path, | ||
128 | put_path_length); | ||
129 | if ( (size >= sizeof (struct GNUNET_HELLO_Message)) && | ||
130 | (ntohs (hello->header.size) == size) && | ||
131 | (size == GNUNET_HELLO_size (hello)) ) | ||
132 | { | ||
133 | peer = GCP_get (&put_path[0], | ||
134 | GNUNET_YES); | ||
135 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
136 | "Got HELLO for %s\n", | ||
137 | GCP_2s (peer)); | ||
138 | GCP_set_hello (peer, | ||
139 | hello); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | |||
144 | /** | ||
145 | * Periodically announce self id in the DHT | ||
146 | * | ||
147 | * @param cls closure | ||
148 | */ | ||
149 | static void | ||
150 | announce_id (void *cls) | ||
151 | { | ||
152 | struct GNUNET_HashCode phash; | ||
153 | const struct GNUNET_HELLO_Message *hello; | ||
154 | size_t size; | ||
155 | struct GNUNET_TIME_Absolute expiration; | ||
156 | struct GNUNET_TIME_Relative next_put; | ||
157 | |||
158 | hello = GCH_get_mine (); | ||
159 | size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0; | ||
160 | if (0 == size) | ||
161 | { | ||
162 | expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | ||
163 | announce_delay); | ||
164 | announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay); | ||
165 | } | ||
166 | else | ||
167 | { | ||
168 | expiration = GNUNET_HELLO_get_last_expiration (hello); | ||
169 | announce_delay = GNUNET_TIME_UNIT_SECONDS; | ||
170 | } | ||
171 | |||
172 | /* Call again in id_announce_time, unless HELLO expires first, | ||
173 | * but wait at least 1s. */ | ||
174 | next_put | ||
175 | = GNUNET_TIME_absolute_get_remaining (expiration); | ||
176 | next_put | ||
177 | = GNUNET_TIME_relative_min (next_put, | ||
178 | id_announce_time); | ||
179 | next_put | ||
180 | = GNUNET_TIME_relative_max (next_put, | ||
181 | GNUNET_TIME_UNIT_SECONDS); | ||
182 | announce_id_task | ||
183 | = GNUNET_SCHEDULER_add_delayed (next_put, | ||
184 | &announce_id, | ||
185 | cls); | ||
186 | GNUNET_STATISTICS_update (stats, | ||
187 | "# DHT announce", | ||
188 | 1, | ||
189 | GNUNET_NO); | ||
190 | memset (&phash, | ||
191 | 0, | ||
192 | sizeof (phash)); | ||
193 | GNUNET_memcpy (&phash, | ||
194 | &my_full_id, | ||
195 | sizeof (my_full_id)); | ||
196 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
197 | "Announcing my HELLO (%u bytes) in the DHT\n", | ||
198 | size); | ||
199 | GNUNET_DHT_put (dht_handle, /* DHT handle */ | ||
200 | &phash, /* Key to use */ | ||
201 | dht_replication_level, /* Replication level */ | ||
202 | GNUNET_DHT_RO_RECORD_ROUTE | ||
203 | | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ | ||
204 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */ | ||
205 | size, /* Size of the data */ | ||
206 | (const char *) hello, /* Data itself */ | ||
207 | expiration, /* Data expiration */ | ||
208 | NULL, /* Continuation */ | ||
209 | NULL); /* Continuation closure */ | ||
210 | } | ||
211 | |||
212 | |||
213 | /** | ||
214 | * Function called by the HELLO subsystem whenever OUR hello | ||
215 | * changes. Re-triggers the DHT PUT immediately. | ||
216 | */ | ||
217 | void | ||
218 | GCD_hello_update () | ||
219 | { | ||
220 | if (NULL == announce_id_task) | ||
221 | return; /* too early */ | ||
222 | GNUNET_SCHEDULER_cancel (announce_id_task); | ||
223 | announce_id_task | ||
224 | = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY, | ||
225 | &announce_id, | ||
226 | NULL); | ||
227 | } | ||
228 | |||
229 | |||
230 | /** | ||
231 | * Initialize the DHT subsystem. | ||
232 | * | ||
233 | * @param c Configuration. | ||
234 | */ | ||
235 | void | ||
236 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
237 | { | ||
238 | if (GNUNET_OK != | ||
239 | GNUNET_CONFIGURATION_get_value_number (c, | ||
240 | "CADET", | ||
241 | "DHT_REPLICATION_LEVEL", | ||
242 | &dht_replication_level)) | ||
243 | { | ||
244 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
245 | "CADET", | ||
246 | "DHT_REPLICATION_LEVEL", | ||
247 | "USING DEFAULT"); | ||
248 | dht_replication_level = 3; | ||
249 | } | ||
250 | |||
251 | if (GNUNET_OK != | ||
252 | GNUNET_CONFIGURATION_get_value_time (c, | ||
253 | "CADET", | ||
254 | "ID_ANNOUNCE_TIME", | ||
255 | &id_announce_time)) | ||
256 | { | ||
257 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
258 | "CADET", | ||
259 | "ID_ANNOUNCE_TIME", | ||
260 | "MISSING"); | ||
261 | GNUNET_SCHEDULER_shutdown (); | ||
262 | return; | ||
263 | } | ||
264 | |||
265 | dht_handle = GNUNET_DHT_connect (c, | ||
266 | 64); | ||
267 | GNUNET_break (NULL != dht_handle); | ||
268 | announce_delay = GNUNET_TIME_UNIT_SECONDS; | ||
269 | announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY, | ||
270 | &announce_id, | ||
271 | NULL); | ||
272 | } | ||
273 | |||
274 | |||
275 | /** | ||
276 | * Shut down the DHT subsystem. | ||
277 | */ | ||
278 | void | ||
279 | GCD_shutdown (void) | ||
280 | { | ||
281 | if (NULL != dht_handle) | ||
282 | { | ||
283 | GNUNET_DHT_disconnect (dht_handle); | ||
284 | dht_handle = NULL; | ||
285 | } | ||
286 | if (NULL != announce_id_task) | ||
287 | { | ||
288 | GNUNET_SCHEDULER_cancel (announce_id_task); | ||
289 | announce_id_task = NULL; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | |||
294 | /** | ||
295 | * Search DHT for paths to @a peeR_id | ||
296 | * | ||
297 | * @param peer_id peer to search for | ||
298 | * @return handle to abort search | ||
299 | */ | ||
300 | struct GCD_search_handle * | ||
301 | GCD_search (const struct GNUNET_PeerIdentity *peer_id) | ||
302 | { | ||
303 | struct GNUNET_HashCode phash; | ||
304 | struct GCD_search_handle *h; | ||
305 | |||
306 | GNUNET_STATISTICS_update (stats, | ||
307 | "# DHT search", | ||
308 | 1, | ||
309 | GNUNET_NO); | ||
310 | memset (&phash, | ||
311 | 0, | ||
312 | sizeof (phash)); | ||
313 | GNUNET_memcpy (&phash, | ||
314 | peer_id, | ||
315 | sizeof (*peer_id)); | ||
316 | |||
317 | h = GNUNET_new (struct GCD_search_handle); | ||
318 | h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ | ||
319 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */ | ||
320 | &phash, /* key to search */ | ||
321 | dht_replication_level, /* replication level */ | ||
322 | GNUNET_DHT_RO_RECORD_ROUTE | | ||
323 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
324 | NULL, /* xquery */ | ||
325 | 0, /* xquery bits */ | ||
326 | &dht_get_id_handler, | ||
327 | h); | ||
328 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
329 | "Starting DHT GET for peer %s (%p)\n", | ||
330 | GNUNET_i2s (peer_id), | ||
331 | h); | ||
332 | return h; | ||
333 | } | ||
334 | |||
335 | |||
336 | /** | ||
337 | * Stop DHT search started with #GCD_search(). | ||
338 | * | ||
339 | * @param h handle to search to stop | ||
340 | */ | ||
341 | void | ||
342 | GCD_search_stop (struct GCD_search_handle *h) | ||
343 | { | ||
344 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
345 | "Stopping DHT GET %p\n", | ||
346 | h); | ||
347 | GNUNET_DHT_get_stop (h->dhtget); | ||
348 | GNUNET_free (h); | ||
349 | } | ||
350 | |||
351 | /* end of gnunet-service-cadet_dht.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new_dht.h b/src/cadet/gnunet-service-cadet-new_dht.h deleted file mode 100644 index 5d7ab29a0..000000000 --- a/src/cadet/gnunet-service-cadet-new_dht.h +++ /dev/null | |||
@@ -1,100 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_dht.h | ||
23 | * @brief cadet service; dealing with DHT requests and results | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * All functions in this file should use the prefix GCD (Gnunet Cadet Dht) | ||
28 | */ | ||
29 | #ifndef GNUNET_SERVICE_CADET_DHT_H | ||
30 | #define GNUNET_SERVICE_CADET_DHT_H | ||
31 | |||
32 | #ifdef __cplusplus | ||
33 | extern "C" | ||
34 | { | ||
35 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
36 | } | ||
37 | #endif | ||
38 | #endif | ||
39 | |||
40 | #include "platform.h" | ||
41 | #include "gnunet_util_lib.h" | ||
42 | |||
43 | /** | ||
44 | * Handle for DHT search operation. | ||
45 | */ | ||
46 | struct GCD_search_handle; | ||
47 | |||
48 | |||
49 | /** | ||
50 | * Initialize the DHT subsystem. | ||
51 | * | ||
52 | * @param c Configuration. | ||
53 | */ | ||
54 | void | ||
55 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Shut down the DHT subsystem. | ||
60 | */ | ||
61 | void | ||
62 | GCD_shutdown (void); | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Function called by the HELLO subsystem whenever OUR hello | ||
67 | * changes. Re-triggers the DHT PUT immediately. | ||
68 | */ | ||
69 | void | ||
70 | GCD_hello_update (void); | ||
71 | |||
72 | /** | ||
73 | * Search DHT for paths to @a peeR_id | ||
74 | * | ||
75 | * @param peer_id peer to search for | ||
76 | * @return handle to abort search | ||
77 | */ | ||
78 | struct GCD_search_handle * | ||
79 | GCD_search (const struct GNUNET_PeerIdentity *peer_id); | ||
80 | |||
81 | |||
82 | /** | ||
83 | * Stop DHT search started with #GCD_search(). | ||
84 | * | ||
85 | * @param h handle to search to stop | ||
86 | */ | ||
87 | void | ||
88 | GCD_search_stop (struct GCD_search_handle *h); | ||
89 | |||
90 | |||
91 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
92 | { | ||
93 | #endif | ||
94 | #ifdef __cplusplus | ||
95 | } | ||
96 | #endif | ||
97 | |||
98 | /* ifndef GNUNET_CADET_SERVICE_DHT_H */ | ||
99 | #endif | ||
100 | /* end of gnunet-service-cadet_dht.h */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new_hello.c b/src/cadet/gnunet-service-cadet-new_hello.c deleted file mode 100644 index a24325ada..000000000 --- a/src/cadet/gnunet-service-cadet-new_hello.c +++ /dev/null | |||
@@ -1,152 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2014, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet-new_hello.c | ||
22 | * @brief spread knowledge about how to contact other peers from PEERINFO | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | * | ||
26 | * TODO: | ||
27 | * - is most of this necessary/helpful? | ||
28 | * - should we not simply restrict this to OUR hello? | ||
29 | */ | ||
30 | #include "platform.h" | ||
31 | #include "gnunet_util_lib.h" | ||
32 | |||
33 | #include "gnunet_statistics_service.h" | ||
34 | #include "gnunet_peerinfo_service.h" | ||
35 | #include "cadet_protocol.h" | ||
36 | #include "gnunet-service-cadet-new.h" | ||
37 | #include "gnunet-service-cadet-new_dht.h" | ||
38 | #include "gnunet-service-cadet-new_hello.h" | ||
39 | #include "gnunet-service-cadet-new_peer.h" | ||
40 | |||
41 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__) | ||
42 | |||
43 | /** | ||
44 | * Hello message of local peer. | ||
45 | */ | ||
46 | static struct GNUNET_HELLO_Message *mine; | ||
47 | |||
48 | /** | ||
49 | * Handle to peerinfo service. | ||
50 | */ | ||
51 | static struct GNUNET_PEERINFO_Handle *peerinfo; | ||
52 | |||
53 | /** | ||
54 | * Iterator context. | ||
55 | */ | ||
56 | static struct GNUNET_PEERINFO_NotifyContext *nc; | ||
57 | |||
58 | |||
59 | /** | ||
60 | * Process each hello message received from peerinfo. | ||
61 | * | ||
62 | * @param cls Closure (unused). | ||
63 | * @param peer Identity of the peer. | ||
64 | * @param hello Hello of the peer. | ||
65 | * @param err_msg Error message. | ||
66 | */ | ||
67 | static void | ||
68 | got_hello (void *cls, | ||
69 | const struct GNUNET_PeerIdentity *id, | ||
70 | const struct GNUNET_HELLO_Message *hello, | ||
71 | const char *err_msg) | ||
72 | { | ||
73 | struct CadetPeer *peer; | ||
74 | |||
75 | if ( (NULL == id) || | ||
76 | (NULL == hello) ) | ||
77 | return; | ||
78 | if (0 == memcmp (id, | ||
79 | &my_full_id, | ||
80 | sizeof (struct GNUNET_PeerIdentity))) | ||
81 | { | ||
82 | GNUNET_free_non_null (mine); | ||
83 | mine = (struct GNUNET_HELLO_Message *) GNUNET_copy_message (&hello->header); | ||
84 | GCD_hello_update (); | ||
85 | return; | ||
86 | } | ||
87 | |||
88 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
89 | "Hello for %s (%d bytes), expires on %s\n", | ||
90 | GNUNET_i2s (id), | ||
91 | GNUNET_HELLO_size (hello), | ||
92 | GNUNET_STRINGS_absolute_time_to_string (GNUNET_HELLO_get_last_expiration (hello))); | ||
93 | peer = GCP_get (id, | ||
94 | GNUNET_YES); | ||
95 | GCP_set_hello (peer, | ||
96 | hello); | ||
97 | } | ||
98 | |||
99 | |||
100 | /** | ||
101 | * Initialize the hello subsystem. | ||
102 | * | ||
103 | * @param c Configuration. | ||
104 | */ | ||
105 | void | ||
106 | GCH_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
107 | { | ||
108 | GNUNET_assert (NULL == nc); | ||
109 | peerinfo = GNUNET_PEERINFO_connect (c); | ||
110 | nc = GNUNET_PEERINFO_notify (c, | ||
111 | GNUNET_NO, | ||
112 | &got_hello, | ||
113 | NULL); | ||
114 | } | ||
115 | |||
116 | |||
117 | /** | ||
118 | * Shut down the hello subsystem. | ||
119 | */ | ||
120 | void | ||
121 | GCH_shutdown () | ||
122 | { | ||
123 | if (NULL != nc) | ||
124 | { | ||
125 | GNUNET_PEERINFO_notify_cancel (nc); | ||
126 | nc = NULL; | ||
127 | } | ||
128 | if (NULL != peerinfo) | ||
129 | { | ||
130 | GNUNET_PEERINFO_disconnect (peerinfo); | ||
131 | peerinfo = NULL; | ||
132 | } | ||
133 | if (NULL != mine) | ||
134 | { | ||
135 | GNUNET_free (mine); | ||
136 | mine = NULL; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | |||
141 | /** | ||
142 | * Get own hello message. | ||
143 | * | ||
144 | * @return Own hello message. | ||
145 | */ | ||
146 | const struct GNUNET_HELLO_Message * | ||
147 | GCH_get_mine (void) | ||
148 | { | ||
149 | return mine; | ||
150 | } | ||
151 | |||
152 | /* end of gnunet-service-cadet-new_hello.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new_hello.h b/src/cadet/gnunet-service-cadet-new_hello.h deleted file mode 100644 index 4291ae985..000000000 --- a/src/cadet/gnunet-service-cadet-new_hello.h +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2014, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_hello.h | ||
23 | * @brief cadet service; dealing with hello messages | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * All functions in this file should use the prefix GCH (Gnunet Cadet Hello) | ||
28 | */ | ||
29 | |||
30 | #ifndef GNUNET_SERVICE_CADET_HELLO_H | ||
31 | #define GNUNET_SERVICE_CADET_HELLO_H | ||
32 | |||
33 | #ifdef __cplusplus | ||
34 | extern "C" | ||
35 | { | ||
36 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
37 | } | ||
38 | #endif | ||
39 | #endif | ||
40 | |||
41 | #include "platform.h" | ||
42 | #include "gnunet_util_lib.h" | ||
43 | #include "gnunet_hello_lib.h" | ||
44 | |||
45 | |||
46 | /** | ||
47 | * Initialize the hello subsystem. | ||
48 | * | ||
49 | * @param c Configuration. | ||
50 | */ | ||
51 | void | ||
52 | GCH_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
53 | |||
54 | |||
55 | /** | ||
56 | * Shut down the hello subsystem. | ||
57 | */ | ||
58 | void | ||
59 | GCH_shutdown (void); | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Get own hello message. | ||
64 | * | ||
65 | * @return Own hello message. | ||
66 | */ | ||
67 | const struct GNUNET_HELLO_Message * | ||
68 | GCH_get_mine (void); | ||
69 | |||
70 | |||
71 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
72 | { | ||
73 | #endif | ||
74 | #ifdef __cplusplus | ||
75 | } | ||
76 | #endif | ||
77 | |||
78 | /* ifndef GNUNET_CADET_SERVICE_HELLO_H */ | ||
79 | #endif | ||
80 | /* end of gnunet-cadet-service_hello.h */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new_peer.c b/src/cadet/gnunet-service-cadet-new_peer.c deleted file mode 100644 index fe40d76b6..000000000 --- a/src/cadet/gnunet-service-cadet-new_peer.c +++ /dev/null | |||
@@ -1,1282 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2001-2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet-new_peer.c | ||
23 | * @brief Information we track per peer. | ||
24 | * @author Bartlomiej Polot | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * TODO: | ||
28 | * - optimize stopping/restarting DHT search to situations | ||
29 | * where we actually need it (i.e. not if we have a direct connection, | ||
30 | * or if we already have plenty of good short ones, or maybe even | ||
31 | * to take a break if we have some connections and have searched a lot (?)) | ||
32 | * - optimize MQM ready scans (O(n) -> O(1)) | ||
33 | */ | ||
34 | #include "platform.h" | ||
35 | #include "gnunet_util_lib.h" | ||
36 | #include "gnunet_hello_lib.h" | ||
37 | #include "gnunet_signatures.h" | ||
38 | #include "gnunet_transport_service.h" | ||
39 | #include "gnunet_ats_service.h" | ||
40 | #include "gnunet_core_service.h" | ||
41 | #include "gnunet_statistics_service.h" | ||
42 | #include "cadet_protocol.h" | ||
43 | #include "gnunet-service-cadet-new.h" | ||
44 | #include "gnunet-service-cadet-new_connection.h" | ||
45 | #include "gnunet-service-cadet-new_dht.h" | ||
46 | #include "gnunet-service-cadet-new_peer.h" | ||
47 | #include "gnunet-service-cadet-new_paths.h" | ||
48 | #include "gnunet-service-cadet-new_tunnels.h" | ||
49 | |||
50 | |||
51 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-per",__VA_ARGS__) | ||
52 | |||
53 | |||
54 | /** | ||
55 | * How long do we wait until tearing down an idle peer? | ||
56 | */ | ||
57 | #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5) | ||
58 | |||
59 | /** | ||
60 | * How long do we keep paths around if we no longer care about the peer? | ||
61 | */ | ||
62 | #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2) | ||
63 | |||
64 | |||
65 | |||
66 | |||
67 | /** | ||
68 | * Data structure used to track whom we have to notify about changes | ||
69 | * to our message queue. | ||
70 | */ | ||
71 | struct GCP_MessageQueueManager | ||
72 | { | ||
73 | |||
74 | /** | ||
75 | * Kept in a DLL. | ||
76 | */ | ||
77 | struct GCP_MessageQueueManager *next; | ||
78 | |||
79 | /** | ||
80 | * Kept in a DLL. | ||
81 | */ | ||
82 | struct GCP_MessageQueueManager *prev; | ||
83 | |||
84 | /** | ||
85 | * Function to call with updated message queue object. | ||
86 | */ | ||
87 | GCP_MessageQueueNotificationCallback cb; | ||
88 | |||
89 | /** | ||
90 | * Closure for @e cb. | ||
91 | */ | ||
92 | void *cb_cls; | ||
93 | |||
94 | /** | ||
95 | * The peer this is for. | ||
96 | */ | ||
97 | struct CadetPeer *cp; | ||
98 | |||
99 | /** | ||
100 | * Envelope this manager would like to transmit once it is its turn. | ||
101 | */ | ||
102 | struct GNUNET_MQ_Envelope *env; | ||
103 | |||
104 | }; | ||
105 | |||
106 | |||
107 | /** | ||
108 | * Struct containing all information regarding a given peer | ||
109 | */ | ||
110 | struct CadetPeer | ||
111 | { | ||
112 | /** | ||
113 | * ID of the peer | ||
114 | */ | ||
115 | struct GNUNET_PeerIdentity pid; | ||
116 | |||
117 | /** | ||
118 | * Last time we heard from this peer | ||
119 | */ | ||
120 | struct GNUNET_TIME_Absolute last_contact; | ||
121 | |||
122 | /** | ||
123 | * Array of DLLs of paths traversing the peer, organized by the | ||
124 | * offset of the peer on the larger path. | ||
125 | */ | ||
126 | struct CadetPeerPathEntry **path_heads; | ||
127 | |||
128 | /** | ||
129 | * Array of DLL of paths traversing the peer, organized by the | ||
130 | * offset of the peer on the larger path. | ||
131 | */ | ||
132 | struct CadetPeerPathEntry **path_tails; | ||
133 | |||
134 | /** | ||
135 | * Notifications to call when @e core_mq changes. | ||
136 | */ | ||
137 | struct GCP_MessageQueueManager *mqm_head; | ||
138 | |||
139 | /** | ||
140 | * Notifications to call when @e core_mq changes. | ||
141 | */ | ||
142 | struct GCP_MessageQueueManager *mqm_tail; | ||
143 | |||
144 | /** | ||
145 | * MIN-heap of paths owned by this peer (they also end at this | ||
146 | * peer). Ordered by desirability. | ||
147 | */ | ||
148 | struct GNUNET_CONTAINER_Heap *path_heap; | ||
149 | |||
150 | /** | ||
151 | * Handle to stop the DHT search for paths to this peer | ||
152 | */ | ||
153 | struct GCD_search_handle *search_h; | ||
154 | |||
155 | /** | ||
156 | * Task to stop the DHT search for paths to this peer | ||
157 | */ | ||
158 | struct GNUNET_SCHEDULER_Task *search_delayedXXX; | ||
159 | |||
160 | /** | ||
161 | * Task to destroy this entry. | ||
162 | */ | ||
163 | struct GNUNET_SCHEDULER_Task *destroy_task; | ||
164 | |||
165 | /** | ||
166 | * Tunnel to this peer, if any. | ||
167 | */ | ||
168 | struct CadetTunnel *t; | ||
169 | |||
170 | /** | ||
171 | * Connections that go through this peer; indexed by tid. | ||
172 | */ | ||
173 | struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
174 | |||
175 | /** | ||
176 | * Handle for core transmissions. | ||
177 | */ | ||
178 | struct GNUNET_MQ_Handle *core_mq; | ||
179 | |||
180 | /** | ||
181 | * Hello message of the peer. | ||
182 | */ | ||
183 | struct GNUNET_HELLO_Message *hello; | ||
184 | |||
185 | /** | ||
186 | * Handle to us offering the HELLO to the transport. | ||
187 | */ | ||
188 | struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer; | ||
189 | |||
190 | /** | ||
191 | * Handle to our ATS request asking ATS to suggest an address | ||
192 | * to TRANSPORT for this peer (to establish a direct link). | ||
193 | */ | ||
194 | struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion; | ||
195 | |||
196 | /** | ||
197 | * How many messages are in the queue to this peer. | ||
198 | */ | ||
199 | unsigned int queue_n; | ||
200 | |||
201 | /** | ||
202 | * How many paths do we have to this peer (in all @e path_heads DLLs combined). | ||
203 | */ | ||
204 | unsigned int num_paths; | ||
205 | |||
206 | /** | ||
207 | * Number of message queue managers of this peer that have a message in waiting. | ||
208 | * | ||
209 | * Used to quickly see if we need to bother scanning the @e msm_head DLL. | ||
210 | * TODO: could be replaced by another DLL that would then allow us to avoid | ||
211 | * the O(n)-scan of the DLL for ready entries! | ||
212 | */ | ||
213 | unsigned int mqm_ready_counter; | ||
214 | |||
215 | /** | ||
216 | * Current length of the @e path_heads and @path_tails arrays. | ||
217 | * The arrays should be grown as needed. | ||
218 | */ | ||
219 | unsigned int path_dll_length; | ||
220 | |||
221 | }; | ||
222 | |||
223 | |||
224 | /** | ||
225 | * Get the static string for a peer ID. | ||
226 | * | ||
227 | * @param cp Peer. | ||
228 | * @return Static string for it's ID. | ||
229 | */ | ||
230 | const char * | ||
231 | GCP_2s (const struct CadetPeer *cp) | ||
232 | { | ||
233 | static char buf[32]; | ||
234 | |||
235 | GNUNET_snprintf (buf, | ||
236 | sizeof (buf), | ||
237 | "P(%s)", | ||
238 | GNUNET_i2s (&cp->pid)); | ||
239 | return buf; | ||
240 | } | ||
241 | |||
242 | |||
243 | /** | ||
244 | * This peer is no longer be needed, clean it up now. | ||
245 | * | ||
246 | * @param cls peer to clean up | ||
247 | */ | ||
248 | static void | ||
249 | destroy_peer (void *cls) | ||
250 | { | ||
251 | struct CadetPeer *cp = cls; | ||
252 | |||
253 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
254 | "Destroying state about peer %s\n", | ||
255 | GCP_2s (cp)); | ||
256 | cp->destroy_task = NULL; | ||
257 | GNUNET_assert (NULL == cp->t); | ||
258 | GNUNET_assert (NULL == cp->core_mq); | ||
259 | for (unsigned int i=0;i<cp->path_dll_length;i++) | ||
260 | GNUNET_assert (NULL == cp->path_heads[i]); | ||
261 | GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)); | ||
262 | GNUNET_assert (GNUNET_YES == | ||
263 | GNUNET_CONTAINER_multipeermap_remove (peers, | ||
264 | &cp->pid, | ||
265 | cp)); | ||
266 | GNUNET_free_non_null (cp->path_heads); | ||
267 | GNUNET_free_non_null (cp->path_tails); | ||
268 | cp->path_dll_length = 0; | ||
269 | if (NULL != cp->search_h) | ||
270 | { | ||
271 | GCD_search_stop (cp->search_h); | ||
272 | cp->search_h = NULL; | ||
273 | } | ||
274 | /* FIXME: clean up search_delayedXXX! */ | ||
275 | |||
276 | if (NULL != cp->hello_offer) | ||
277 | { | ||
278 | GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer); | ||
279 | cp->hello_offer = NULL; | ||
280 | } | ||
281 | if (NULL != cp->connectivity_suggestion) | ||
282 | { | ||
283 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
284 | cp->connectivity_suggestion = NULL; | ||
285 | } | ||
286 | GNUNET_CONTAINER_multishortmap_destroy (cp->connections); | ||
287 | if (NULL != cp->path_heap) | ||
288 | { | ||
289 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); | ||
290 | cp->path_heap = NULL; | ||
291 | } | ||
292 | GNUNET_free_non_null (cp->hello); | ||
293 | /* Peer should not be freed if paths exist; if there are no paths, | ||
294 | there ought to be no connections, and without connections, no | ||
295 | notifications. Thus we can assert that mqm_head is empty at this | ||
296 | point. */ | ||
297 | GNUNET_assert (NULL == cp->mqm_head); | ||
298 | GNUNET_free (cp); | ||
299 | } | ||
300 | |||
301 | |||
302 | /** | ||
303 | * This peer is now on more "active" duty, activate processes related to it. | ||
304 | * | ||
305 | * @param cp the more-active peer | ||
306 | */ | ||
307 | static void | ||
308 | consider_peer_activate (struct CadetPeer *cp) | ||
309 | { | ||
310 | uint32_t strength; | ||
311 | |||
312 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
313 | "Updating peer %s activation state (%u connections)%s%s\n", | ||
314 | GCP_2s (cp), | ||
315 | GNUNET_CONTAINER_multishortmap_size (cp->connections), | ||
316 | (NULL == cp->t) ? "" : " with tunnel", | ||
317 | (NULL == cp->core_mq) ? "" : " with CORE link"); | ||
318 | if (NULL != cp->destroy_task) | ||
319 | { | ||
320 | /* It's active, do not destory! */ | ||
321 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
322 | cp->destroy_task = NULL; | ||
323 | } | ||
324 | if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) && | ||
325 | (NULL == cp->t) ) | ||
326 | { | ||
327 | /* We're just on a path or directly connected; don't bother too much */ | ||
328 | if (NULL != cp->connectivity_suggestion) | ||
329 | { | ||
330 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
331 | cp->connectivity_suggestion = NULL; | ||
332 | } | ||
333 | if (NULL != cp->search_h) | ||
334 | { | ||
335 | GCD_search_stop (cp->search_h); | ||
336 | cp->search_h = NULL; | ||
337 | } | ||
338 | return; | ||
339 | } | ||
340 | if (NULL == cp->core_mq) | ||
341 | { | ||
342 | /* Lacks direct connection, try to create one by querying the DHT */ | ||
343 | if ( (NULL == cp->search_h) && | ||
344 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) ) | ||
345 | cp->search_h | ||
346 | = GCD_search (&cp->pid); | ||
347 | } | ||
348 | else | ||
349 | { | ||
350 | /* Have direct connection, stop DHT search if active */ | ||
351 | if (NULL != cp->search_h) | ||
352 | { | ||
353 | GCD_search_stop (cp->search_h); | ||
354 | cp->search_h = NULL; | ||
355 | } | ||
356 | } | ||
357 | |||
358 | /* If we have a tunnel, our urge for connections is much bigger */ | ||
359 | strength = (NULL != cp->t) ? 32 : 1; | ||
360 | if (NULL != cp->connectivity_suggestion) | ||
361 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
362 | cp->connectivity_suggestion | ||
363 | = GNUNET_ATS_connectivity_suggest (ats_ch, | ||
364 | &cp->pid, | ||
365 | strength); | ||
366 | } | ||
367 | |||
368 | |||
369 | /** | ||
370 | * This peer may no longer be needed, consider cleaning it up. | ||
371 | * | ||
372 | * @param cp peer to clean up | ||
373 | */ | ||
374 | static void | ||
375 | consider_peer_destroy (struct CadetPeer *cp); | ||
376 | |||
377 | |||
378 | /** | ||
379 | * We really no longere care about a peer, stop hogging memory with paths to it. | ||
380 | * Afterwards, see if there is more to be cleaned up about this peer. | ||
381 | * | ||
382 | * @param cls a `struct CadetPeer`. | ||
383 | */ | ||
384 | static void | ||
385 | drop_paths (void *cls) | ||
386 | { | ||
387 | struct CadetPeer *cp = cls; | ||
388 | struct CadetPeerPath *path; | ||
389 | |||
390 | cp->destroy_task = NULL; | ||
391 | while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) | ||
392 | GCPP_release (path); | ||
393 | consider_peer_destroy (cp); | ||
394 | } | ||
395 | |||
396 | |||
397 | /** | ||
398 | * This peer may no longer be needed, consider cleaning it up. | ||
399 | * | ||
400 | * @param cp peer to clean up | ||
401 | */ | ||
402 | static void | ||
403 | consider_peer_destroy (struct CadetPeer *cp) | ||
404 | { | ||
405 | struct GNUNET_TIME_Relative exp; | ||
406 | |||
407 | if (NULL != cp->destroy_task) | ||
408 | { | ||
409 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
410 | cp->destroy_task = NULL; | ||
411 | } | ||
412 | if (NULL != cp->t) | ||
413 | return; /* still relevant! */ | ||
414 | if (NULL != cp->core_mq) | ||
415 | return; /* still relevant! */ | ||
416 | if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections)) | ||
417 | return; /* still relevant! */ | ||
418 | if (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap)) | ||
419 | { | ||
420 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT, | ||
421 | &drop_paths, | ||
422 | cp); | ||
423 | return; | ||
424 | } | ||
425 | for (unsigned int i=0;i<cp->path_dll_length;i++) | ||
426 | if (NULL != cp->path_heads[i]) | ||
427 | return; /* still relevant! */ | ||
428 | if (NULL != cp->hello) | ||
429 | { | ||
430 | /* relevant only until HELLO expires */ | ||
431 | exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello)); | ||
432 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp, | ||
433 | &destroy_peer, | ||
434 | cp); | ||
435 | return; | ||
436 | } | ||
437 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT, | ||
438 | &destroy_peer, | ||
439 | cp); | ||
440 | } | ||
441 | |||
442 | |||
443 | /** | ||
444 | * Set the message queue to @a mq for peer @a cp and notify watchers. | ||
445 | * | ||
446 | * @param cp peer to modify | ||
447 | * @param mq message queue to set (can be NULL) | ||
448 | */ | ||
449 | void | ||
450 | GCP_set_mq (struct CadetPeer *cp, | ||
451 | struct GNUNET_MQ_Handle *mq) | ||
452 | { | ||
453 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
454 | "Message queue for peer %s is now %p\n", | ||
455 | GCP_2s (cp), | ||
456 | mq); | ||
457 | cp->core_mq = mq; | ||
458 | for (struct GCP_MessageQueueManager *mqm = cp->mqm_head; | ||
459 | NULL != mqm; | ||
460 | mqm = mqm->next) | ||
461 | { | ||
462 | if (NULL == mq) | ||
463 | { | ||
464 | if (NULL != mqm->env) | ||
465 | { | ||
466 | GNUNET_MQ_discard (mqm->env); | ||
467 | mqm->env = NULL; | ||
468 | mqm->cb (mqm->cb_cls, | ||
469 | GNUNET_SYSERR); | ||
470 | } | ||
471 | else | ||
472 | { | ||
473 | mqm->cb (mqm->cb_cls, | ||
474 | GNUNET_NO); | ||
475 | } | ||
476 | } | ||
477 | else | ||
478 | { | ||
479 | GNUNET_assert (NULL == mqm->env); | ||
480 | mqm->cb (mqm->cb_cls, | ||
481 | GNUNET_YES); | ||
482 | } | ||
483 | } | ||
484 | if ( (NULL != mq) || | ||
485 | (NULL != cp->t) ) | ||
486 | consider_peer_activate (cp); | ||
487 | else | ||
488 | consider_peer_destroy (cp); | ||
489 | |||
490 | if ( (NULL != mq) && | ||
491 | (NULL != cp->t) ) | ||
492 | { | ||
493 | /* have a new, direct path to the target, notify tunnel */ | ||
494 | struct CadetPeerPath *path; | ||
495 | |||
496 | path = GCPP_get_path_from_route (1, | ||
497 | &cp->pid); | ||
498 | GCT_consider_path (cp->t, | ||
499 | path, | ||
500 | 0); | ||
501 | } | ||
502 | } | ||
503 | |||
504 | |||
505 | /** | ||
506 | * Transmit current envelope from this @a mqm. | ||
507 | * | ||
508 | * @param mqm mqm to transmit message for now | ||
509 | */ | ||
510 | static void | ||
511 | mqm_execute (struct GCP_MessageQueueManager *mqm) | ||
512 | { | ||
513 | struct CadetPeer *cp = mqm->cp; | ||
514 | |||
515 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
516 | "Sending to peer %s from MQM %p\n", | ||
517 | GCP_2s (cp), | ||
518 | mqm); | ||
519 | /* Move entry to the end of the DLL, to be fair. */ | ||
520 | if (mqm != cp->mqm_tail) | ||
521 | { | ||
522 | GNUNET_CONTAINER_DLL_remove (cp->mqm_head, | ||
523 | cp->mqm_tail, | ||
524 | mqm); | ||
525 | GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head, | ||
526 | cp->mqm_tail, | ||
527 | mqm); | ||
528 | } | ||
529 | GNUNET_MQ_send (cp->core_mq, | ||
530 | mqm->env); | ||
531 | mqm->env = NULL; | ||
532 | cp->mqm_ready_counter--; | ||
533 | mqm->cb (mqm->cb_cls, | ||
534 | GNUNET_YES); | ||
535 | } | ||
536 | |||
537 | |||
538 | /** | ||
539 | * Function called when CORE took one of the messages from | ||
540 | * a message queue manager and transmitted it. | ||
541 | * | ||
542 | * @param cls the `struct CadetPeeer` where we made progress | ||
543 | */ | ||
544 | static void | ||
545 | mqm_send_done (void *cls) | ||
546 | { | ||
547 | struct CadetPeer *cp = cls; | ||
548 | |||
549 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
550 | "Sending to peer %s completed\n", | ||
551 | GCP_2s (cp)); | ||
552 | if (0 == cp->mqm_ready_counter) | ||
553 | return; /* nothing to do */ | ||
554 | for (struct GCP_MessageQueueManager *mqm = cp->mqm_head; | ||
555 | NULL != mqm; | ||
556 | mqm = mqm->next) | ||
557 | { | ||
558 | if (NULL == mqm->env) | ||
559 | continue; | ||
560 | mqm_execute (mqm); | ||
561 | return; | ||
562 | } | ||
563 | } | ||
564 | |||
565 | |||
566 | /** | ||
567 | * Send the message in @a env to @a cp. | ||
568 | * | ||
569 | * @param mqm the message queue manager to use for transmission | ||
570 | * @param env envelope with the message to send; must NOT | ||
571 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
572 | */ | ||
573 | void | ||
574 | GCP_send (struct GCP_MessageQueueManager *mqm, | ||
575 | struct GNUNET_MQ_Envelope *env) | ||
576 | { | ||
577 | struct CadetPeer *cp = mqm->cp; | ||
578 | |||
579 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
580 | "Queueing message to peer %s in MQM %p\n", | ||
581 | GCP_2s (cp), | ||
582 | mqm); | ||
583 | GNUNET_assert (NULL != cp->core_mq); | ||
584 | GNUNET_assert (NULL == mqm->env); | ||
585 | GNUNET_MQ_notify_sent (env, | ||
586 | &mqm_send_done, | ||
587 | cp); | ||
588 | mqm->env = env; | ||
589 | cp->mqm_ready_counter++; | ||
590 | if (0 != GNUNET_MQ_get_length (cp->core_mq)) | ||
591 | return; | ||
592 | mqm_execute (mqm); | ||
593 | } | ||
594 | |||
595 | |||
596 | /** | ||
597 | * Function called to destroy a peer now. | ||
598 | * | ||
599 | * @param cls NULL | ||
600 | * @param pid identity of the peer (unused) | ||
601 | * @param value the `struct CadetPeer` to clean up | ||
602 | * @return #GNUNET_OK (continue to iterate) | ||
603 | */ | ||
604 | static int | ||
605 | destroy_iterator_cb (void *cls, | ||
606 | const struct GNUNET_PeerIdentity *pid, | ||
607 | void *value) | ||
608 | { | ||
609 | struct CadetPeer *cp = value; | ||
610 | |||
611 | if (NULL != cp->destroy_task) | ||
612 | { | ||
613 | GNUNET_SCHEDULER_cancel (cp->destroy_task); | ||
614 | cp->destroy_task = NULL; | ||
615 | } | ||
616 | destroy_peer (cp); | ||
617 | return GNUNET_OK; | ||
618 | } | ||
619 | |||
620 | |||
621 | /** | ||
622 | * Clean up all entries about all peers. | ||
623 | * Must only be called after all tunnels, CORE-connections and | ||
624 | * connections are down. | ||
625 | */ | ||
626 | void | ||
627 | GCP_destroy_all_peers () | ||
628 | { | ||
629 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
630 | "Destroying all peers now\n"); | ||
631 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
632 | &destroy_iterator_cb, | ||
633 | NULL); | ||
634 | } | ||
635 | |||
636 | |||
637 | /** | ||
638 | * Drop all paths owned by this peer, and do not | ||
639 | * allow new ones to be added: We are shutting down. | ||
640 | * | ||
641 | * @param cp peer to drop paths to | ||
642 | */ | ||
643 | void | ||
644 | GCP_drop_owned_paths (struct CadetPeer *cp) | ||
645 | { | ||
646 | struct CadetPeerPath *path; | ||
647 | |||
648 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
649 | "Destroying all paths to %s\n", | ||
650 | GCP_2s (cp)); | ||
651 | while (NULL != (path = | ||
652 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) | ||
653 | GCPP_release (path); | ||
654 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); | ||
655 | cp->path_heap = NULL; | ||
656 | } | ||
657 | |||
658 | |||
659 | /** | ||
660 | * Add an entry to the DLL of all of the paths that this peer is on. | ||
661 | * | ||
662 | * @param cp peer to modify | ||
663 | * @param entry an entry on a path | ||
664 | * @param off offset of this peer on the path | ||
665 | */ | ||
666 | void | ||
667 | GCP_path_entry_add (struct CadetPeer *cp, | ||
668 | struct CadetPeerPathEntry *entry, | ||
669 | unsigned int off) | ||
670 | { | ||
671 | GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path, | ||
672 | off)); | ||
673 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
674 | "Discovered that peer %s is on path %s at offset %u\n", | ||
675 | GCP_2s (cp), | ||
676 | GCPP_2s (entry->path), | ||
677 | off); | ||
678 | if (off >= cp->path_dll_length) | ||
679 | { | ||
680 | unsigned int len = cp->path_dll_length; | ||
681 | |||
682 | GNUNET_array_grow (cp->path_heads, | ||
683 | len, | ||
684 | off + 4); | ||
685 | GNUNET_array_grow (cp->path_tails, | ||
686 | cp->path_dll_length, | ||
687 | off + 4); | ||
688 | } | ||
689 | GNUNET_CONTAINER_DLL_insert (cp->path_heads[off], | ||
690 | cp->path_tails[off], | ||
691 | entry); | ||
692 | cp->num_paths++; | ||
693 | |||
694 | /* If we have a tunnel to this peer, tell the tunnel that there is a | ||
695 | new path available. */ | ||
696 | if (NULL != cp->t) | ||
697 | GCT_consider_path (cp->t, | ||
698 | entry->path, | ||
699 | off); | ||
700 | |||
701 | if ( (NULL != cp->search_h) && | ||
702 | (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) ) | ||
703 | { | ||
704 | /* Now I have enough paths, stop search */ | ||
705 | GCD_search_stop (cp->search_h); | ||
706 | cp->search_h = NULL; | ||
707 | } | ||
708 | } | ||
709 | |||
710 | |||
711 | /** | ||
712 | * Remove an entry from the DLL of all of the paths that this peer is on. | ||
713 | * | ||
714 | * @param cp peer to modify | ||
715 | * @param entry an entry on a path | ||
716 | * @param off offset of this peer on the path | ||
717 | */ | ||
718 | void | ||
719 | GCP_path_entry_remove (struct CadetPeer *cp, | ||
720 | struct CadetPeerPathEntry *entry, | ||
721 | unsigned int off) | ||
722 | { | ||
723 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
724 | "Removing knowledge about peer %s beging on path %s at offset %u\n", | ||
725 | GCP_2s (cp), | ||
726 | GCPP_2s (entry->path), | ||
727 | off); | ||
728 | GNUNET_CONTAINER_DLL_remove (cp->path_heads[off], | ||
729 | cp->path_tails[off], | ||
730 | entry); | ||
731 | GNUNET_assert (0 < cp->num_paths); | ||
732 | cp->num_paths--; | ||
733 | if ( (NULL == cp->core_mq) && | ||
734 | (NULL != cp->t) && | ||
735 | (NULL == cp->search_h) && | ||
736 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) ) | ||
737 | cp->search_h | ||
738 | = GCD_search (&cp->pid); | ||
739 | } | ||
740 | |||
741 | |||
742 | /** | ||
743 | * Try adding a @a path to this @a peer. If the peer already | ||
744 | * has plenty of paths, return NULL. | ||
745 | * | ||
746 | * @param cp peer to which the @a path leads to | ||
747 | * @param path a path looking for an owner; may not be fully initialized yet! | ||
748 | * @param off offset of @a cp in @a path | ||
749 | * @param force force attaching the path | ||
750 | * @return NULL if this peer does not care to become a new owner, | ||
751 | * otherwise the node in the peer's path heap for the @a path. | ||
752 | */ | ||
753 | struct GNUNET_CONTAINER_HeapNode * | ||
754 | GCP_attach_path (struct CadetPeer *cp, | ||
755 | struct CadetPeerPath *path, | ||
756 | unsigned int off, | ||
757 | int force) | ||
758 | { | ||
759 | GNUNET_CONTAINER_HeapCostType desirability; | ||
760 | struct CadetPeerPath *root; | ||
761 | GNUNET_CONTAINER_HeapCostType root_desirability; | ||
762 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
763 | |||
764 | GNUNET_assert (cp == GCPP_get_peer_at_offset (path, | ||
765 | off)); | ||
766 | if (NULL == cp->path_heap) | ||
767 | { | ||
768 | /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */ | ||
769 | GNUNET_assert (GNUNET_NO == force); | ||
770 | return NULL; | ||
771 | } | ||
772 | desirability = GCPP_get_desirability (path); | ||
773 | if (GNUNET_NO == force) | ||
774 | { | ||
775 | /* FIXME: desirability is not yet initialized; tricky! */ | ||
776 | if (GNUNET_NO == | ||
777 | GNUNET_CONTAINER_heap_peek2 (cp->path_heap, | ||
778 | (void **) &root, | ||
779 | &root_desirability)) | ||
780 | { | ||
781 | root = NULL; | ||
782 | root_desirability = 0; | ||
783 | } | ||
784 | |||
785 | if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) && | ||
786 | (desirability < root_desirability) ) | ||
787 | { | ||
788 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
789 | "Decided to not attach path %p to peer %s due to undesirability\n", | ||
790 | GCPP_2s (path), | ||
791 | GCP_2s (cp)); | ||
792 | return NULL; | ||
793 | } | ||
794 | } | ||
795 | |||
796 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
797 | "Attaching path %s to peer %s (%s)\n", | ||
798 | GCPP_2s (path), | ||
799 | GCP_2s (cp), | ||
800 | (GNUNET_NO == force) ? "desirable" : "forced"); | ||
801 | |||
802 | /* Yes, we'd like to add this path, add to our heap */ | ||
803 | hn = GNUNET_CONTAINER_heap_insert (cp->path_heap, | ||
804 | path, | ||
805 | desirability); | ||
806 | |||
807 | /* Consider maybe dropping other paths because of the new one */ | ||
808 | if (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= | ||
809 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) | ||
810 | { | ||
811 | /* Now we have way too many, drop least desirable UNLESS it is in use! | ||
812 | (Note that this intentionally keeps highly desireable, but currently | ||
813 | unused paths around in the hope that we might be able to switch, even | ||
814 | if the number of paths exceeds the threshold.) */ | ||
815 | root = GNUNET_CONTAINER_heap_peek (cp->path_heap); | ||
816 | if ( (path != root) && | ||
817 | (NULL == | ||
818 | GCPP_get_connection (root, | ||
819 | cp, | ||
820 | GCPP_get_length (root) - 1)) ) | ||
821 | { | ||
822 | /* Got plenty of paths to this destination, and this is a low-quality | ||
823 | one that we don't care, allow it to die. */ | ||
824 | GNUNET_assert (root == | ||
825 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap)); | ||
826 | GCPP_release (root); | ||
827 | } | ||
828 | } | ||
829 | return hn; | ||
830 | } | ||
831 | |||
832 | |||
833 | /** | ||
834 | * This peer can no longer own @a path as the path | ||
835 | * has been extended and a peer further down the line | ||
836 | * is now the new owner. | ||
837 | * | ||
838 | * @param cp old owner of the @a path | ||
839 | * @param path path where the ownership is lost | ||
840 | * @param hn note in @a cp's path heap that must be deleted | ||
841 | */ | ||
842 | void | ||
843 | GCP_detach_path (struct CadetPeer *cp, | ||
844 | struct CadetPeerPath *path, | ||
845 | struct GNUNET_CONTAINER_HeapNode *hn) | ||
846 | { | ||
847 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
848 | "Detatching path %s from peer %s\n", | ||
849 | GCPP_2s (path), | ||
850 | GCP_2s (cp)); | ||
851 | GNUNET_assert (path == | ||
852 | GNUNET_CONTAINER_heap_remove_node (hn)); | ||
853 | } | ||
854 | |||
855 | |||
856 | /** | ||
857 | * Add a @a connection to this @a cp. | ||
858 | * | ||
859 | * @param cp peer via which the @a connection goes | ||
860 | * @param cc the connection to add | ||
861 | */ | ||
862 | void | ||
863 | GCP_add_connection (struct CadetPeer *cp, | ||
864 | struct CadetConnection *cc) | ||
865 | { | ||
866 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
867 | "Adding connection %s to peer %s\n", | ||
868 | GCC_2s (cc), | ||
869 | GCP_2s (cp)); | ||
870 | GNUNET_assert (GNUNET_OK == | ||
871 | GNUNET_CONTAINER_multishortmap_put (cp->connections, | ||
872 | &GCC_get_id (cc)->connection_of_tunnel, | ||
873 | cc, | ||
874 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
875 | } | ||
876 | |||
877 | |||
878 | /** | ||
879 | * Remove a @a connection that went via this @a cp. | ||
880 | * | ||
881 | * @param cp peer via which the @a connection went | ||
882 | * @param cc the connection to remove | ||
883 | */ | ||
884 | void | ||
885 | GCP_remove_connection (struct CadetPeer *cp, | ||
886 | struct CadetConnection *cc) | ||
887 | { | ||
888 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
889 | "Removing connection %s from peer %s\n", | ||
890 | GCC_2s (cc), | ||
891 | GCP_2s (cp)); | ||
892 | GNUNET_assert (GNUNET_YES == | ||
893 | GNUNET_CONTAINER_multishortmap_remove (cp->connections, | ||
894 | &GCC_get_id (cc)->connection_of_tunnel, | ||
895 | cc)); | ||
896 | } | ||
897 | |||
898 | |||
899 | /** | ||
900 | * Retrieve the CadetPeer stucture associated with the | ||
901 | * peer. Optionally create one and insert it in the appropriate | ||
902 | * structures if the peer is not known yet. | ||
903 | * | ||
904 | * @param peer_id Full identity of the peer. | ||
905 | * @param create #GNUNET_YES if a new peer should be created if unknown. | ||
906 | * #GNUNET_NO to return NULL if peer is unknown. | ||
907 | * @return Existing or newly created peer structure. | ||
908 | * NULL if unknown and not requested @a create | ||
909 | */ | ||
910 | struct CadetPeer * | ||
911 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, | ||
912 | int create) | ||
913 | { | ||
914 | struct CadetPeer *cp; | ||
915 | |||
916 | cp = GNUNET_CONTAINER_multipeermap_get (peers, | ||
917 | peer_id); | ||
918 | if (NULL != cp) | ||
919 | return cp; | ||
920 | if (GNUNET_NO == create) | ||
921 | return NULL; | ||
922 | cp = GNUNET_new (struct CadetPeer); | ||
923 | cp->pid = *peer_id; | ||
924 | cp->connections = GNUNET_CONTAINER_multishortmap_create (32, | ||
925 | GNUNET_YES); | ||
926 | cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
927 | GNUNET_assert (GNUNET_YES == | ||
928 | GNUNET_CONTAINER_multipeermap_put (peers, | ||
929 | &cp->pid, | ||
930 | cp, | ||
931 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
932 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
933 | "Creating peer %s\n", | ||
934 | GCP_2s (cp)); | ||
935 | return cp; | ||
936 | } | ||
937 | |||
938 | |||
939 | /** | ||
940 | * Obtain the peer identity for a `struct CadetPeer`. | ||
941 | * | ||
942 | * @param cp our peer handle | ||
943 | * @return the peer identity | ||
944 | */ | ||
945 | const struct GNUNET_PeerIdentity * | ||
946 | GCP_get_id (struct CadetPeer *cp) | ||
947 | { | ||
948 | return &cp->pid; | ||
949 | } | ||
950 | |||
951 | |||
952 | /** | ||
953 | * Iterate over all known peers. | ||
954 | * | ||
955 | * @param iter Iterator. | ||
956 | * @param cls Closure for @c iter. | ||
957 | */ | ||
958 | void | ||
959 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | ||
960 | void *cls) | ||
961 | { | ||
962 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
963 | iter, | ||
964 | cls); | ||
965 | } | ||
966 | |||
967 | |||
968 | /** | ||
969 | * Count the number of known paths toward the peer. | ||
970 | * | ||
971 | * @param cp Peer to get path info. | ||
972 | * @return Number of known paths. | ||
973 | */ | ||
974 | unsigned int | ||
975 | GCP_count_paths (const struct CadetPeer *cp) | ||
976 | { | ||
977 | return cp->num_paths; | ||
978 | } | ||
979 | |||
980 | |||
981 | /** | ||
982 | * Iterate over the paths to a peer. | ||
983 | * | ||
984 | * @param cp Peer to get path info. | ||
985 | * @param callback Function to call for every path. | ||
986 | * @param callback_cls Closure for @a callback. | ||
987 | * @return Number of iterated paths. | ||
988 | */ | ||
989 | unsigned int | ||
990 | GCP_iterate_paths (struct CadetPeer *cp, | ||
991 | GCP_PathIterator callback, | ||
992 | void *callback_cls) | ||
993 | { | ||
994 | unsigned int ret = 0; | ||
995 | |||
996 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
997 | "Iterating over paths to peer %s%s\n", | ||
998 | GCP_2s (cp), | ||
999 | (NULL == cp->core_mq) ? "" : " including direct link"); | ||
1000 | if (NULL != cp->core_mq) | ||
1001 | { | ||
1002 | struct CadetPeerPath *path; | ||
1003 | |||
1004 | path = GCPP_get_path_from_route (1, | ||
1005 | &cp->pid); | ||
1006 | ret++; | ||
1007 | if (GNUNET_NO == | ||
1008 | callback (callback_cls, | ||
1009 | path, | ||
1010 | 1)) | ||
1011 | return ret; | ||
1012 | } | ||
1013 | for (unsigned int i=0;i<cp->path_dll_length;i++) | ||
1014 | { | ||
1015 | for (struct CadetPeerPathEntry *pe = cp->path_heads[i]; | ||
1016 | NULL != pe; | ||
1017 | pe = pe->next) | ||
1018 | { | ||
1019 | ret++; | ||
1020 | if (GNUNET_NO == | ||
1021 | callback (callback_cls, | ||
1022 | pe->path, | ||
1023 | i)) | ||
1024 | return ret; | ||
1025 | } | ||
1026 | } | ||
1027 | return ret; | ||
1028 | } | ||
1029 | |||
1030 | |||
1031 | /** | ||
1032 | * Iterate over the paths to @a cp where | ||
1033 | * @a cp is at distance @a dist from us. | ||
1034 | * | ||
1035 | * @param cp Peer to get path info. | ||
1036 | * @param dist desired distance of @a cp to us on the path | ||
1037 | * @param callback Function to call for every path. | ||
1038 | * @param callback_cls Closure for @a callback. | ||
1039 | * @return Number of iterated paths. | ||
1040 | */ | ||
1041 | unsigned int | ||
1042 | GCP_iterate_paths_at (struct CadetPeer *cp, | ||
1043 | unsigned int dist, | ||
1044 | GCP_PathIterator callback, | ||
1045 | void *callback_cls) | ||
1046 | { | ||
1047 | unsigned int ret = 0; | ||
1048 | |||
1049 | if (dist >= cp->path_dll_length) | ||
1050 | { | ||
1051 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1052 | "Asked to look for paths at distance %u, but maximum for me is < %u\n", | ||
1053 | dist, | ||
1054 | cp->path_dll_length); | ||
1055 | return 0; | ||
1056 | } | ||
1057 | for (struct CadetPeerPathEntry *pe = cp->path_heads[dist]; | ||
1058 | NULL != pe; | ||
1059 | pe = pe->next) | ||
1060 | { | ||
1061 | if (GNUNET_NO == | ||
1062 | callback (callback_cls, | ||
1063 | pe->path, | ||
1064 | dist)) | ||
1065 | return ret; | ||
1066 | ret++; | ||
1067 | } | ||
1068 | return ret; | ||
1069 | } | ||
1070 | |||
1071 | |||
1072 | /** | ||
1073 | * Get the tunnel towards a peer. | ||
1074 | * | ||
1075 | * @param cp Peer to get from. | ||
1076 | * @param create #GNUNET_YES to create a tunnel if we do not have one | ||
1077 | * @return Tunnel towards peer. | ||
1078 | */ | ||
1079 | struct CadetTunnel * | ||
1080 | GCP_get_tunnel (struct CadetPeer *cp, | ||
1081 | int create) | ||
1082 | { | ||
1083 | if (NULL == cp) | ||
1084 | return NULL; | ||
1085 | if ( (NULL != cp->t) || | ||
1086 | (GNUNET_NO == create) ) | ||
1087 | return cp->t; | ||
1088 | cp->t = GCT_create_tunnel (cp); | ||
1089 | consider_peer_activate (cp); | ||
1090 | return cp->t; | ||
1091 | } | ||
1092 | |||
1093 | |||
1094 | /** | ||
1095 | * Hello offer was passed to the transport service. Mark it | ||
1096 | * as done. | ||
1097 | * | ||
1098 | * @param cls the `struct CadetPeer` where the offer completed | ||
1099 | */ | ||
1100 | static void | ||
1101 | hello_offer_done (void *cls) | ||
1102 | { | ||
1103 | struct CadetPeer *cp = cls; | ||
1104 | |||
1105 | cp->hello_offer = NULL; | ||
1106 | } | ||
1107 | |||
1108 | |||
1109 | /** | ||
1110 | * We got a HELLO for a @a peer, remember it, and possibly | ||
1111 | * trigger adequate actions (like trying to connect). | ||
1112 | * | ||
1113 | * @param cp the peer we got a HELLO for | ||
1114 | * @param hello the HELLO to remember | ||
1115 | */ | ||
1116 | void | ||
1117 | GCP_set_hello (struct CadetPeer *cp, | ||
1118 | const struct GNUNET_HELLO_Message *hello) | ||
1119 | { | ||
1120 | struct GNUNET_HELLO_Message *mrg; | ||
1121 | |||
1122 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1123 | "Got %u byte HELLO for peer %s\n", | ||
1124 | (unsigned int) GNUNET_HELLO_size (hello), | ||
1125 | GCP_2s (cp)); | ||
1126 | if (NULL != cp->hello_offer) | ||
1127 | { | ||
1128 | GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer); | ||
1129 | cp->hello_offer = NULL; | ||
1130 | } | ||
1131 | if (NULL != cp->hello) | ||
1132 | { | ||
1133 | mrg = GNUNET_HELLO_merge (hello, | ||
1134 | cp->hello); | ||
1135 | GNUNET_free (cp->hello); | ||
1136 | cp->hello = mrg; | ||
1137 | } | ||
1138 | else | ||
1139 | { | ||
1140 | cp->hello = GNUNET_memdup (hello, | ||
1141 | GNUNET_HELLO_size (hello)); | ||
1142 | } | ||
1143 | cp->hello_offer | ||
1144 | = GNUNET_TRANSPORT_offer_hello (cfg, | ||
1145 | GNUNET_HELLO_get_header (cp->hello) , | ||
1146 | &hello_offer_done, | ||
1147 | cp); | ||
1148 | /* New HELLO means cp's destruction time may change... */ | ||
1149 | consider_peer_destroy (cp); | ||
1150 | } | ||
1151 | |||
1152 | |||
1153 | /** | ||
1154 | * The tunnel to the given peer no longer exists, remove it from our | ||
1155 | * data structures, and possibly clean up the peer itself. | ||
1156 | * | ||
1157 | * @param cp the peer affected | ||
1158 | * @param t the dead tunnel | ||
1159 | */ | ||
1160 | void | ||
1161 | GCP_drop_tunnel (struct CadetPeer *cp, | ||
1162 | struct CadetTunnel *t) | ||
1163 | { | ||
1164 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1165 | "Dropping tunnel %s to peer %s\n", | ||
1166 | GCT_2s (t), | ||
1167 | GCP_2s (cp)); | ||
1168 | GNUNET_assert (cp->t == t); | ||
1169 | cp->t = NULL; | ||
1170 | consider_peer_destroy (cp); | ||
1171 | } | ||
1172 | |||
1173 | |||
1174 | /** | ||
1175 | * Test if @a cp has a core-level connection | ||
1176 | * | ||
1177 | * @param cp peer to test | ||
1178 | * @return #GNUNET_YES if @a cp has a core-level connection | ||
1179 | */ | ||
1180 | int | ||
1181 | GCP_has_core_connection (struct CadetPeer *cp) | ||
1182 | { | ||
1183 | return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO; | ||
1184 | } | ||
1185 | |||
1186 | |||
1187 | /** | ||
1188 | * Start message queue change notifications. | ||
1189 | * | ||
1190 | * @param cp peer to notify for | ||
1191 | * @param cb function to call if mq becomes available or unavailable | ||
1192 | * @param cb_cls closure for @a cb | ||
1193 | * @return handle to cancel request | ||
1194 | */ | ||
1195 | struct GCP_MessageQueueManager * | ||
1196 | GCP_request_mq (struct CadetPeer *cp, | ||
1197 | GCP_MessageQueueNotificationCallback cb, | ||
1198 | void *cb_cls) | ||
1199 | { | ||
1200 | struct GCP_MessageQueueManager *mqm; | ||
1201 | |||
1202 | mqm = GNUNET_new (struct GCP_MessageQueueManager); | ||
1203 | mqm->cb = cb; | ||
1204 | mqm->cb_cls = cb_cls; | ||
1205 | mqm->cp = cp; | ||
1206 | GNUNET_CONTAINER_DLL_insert (cp->mqm_head, | ||
1207 | cp->mqm_tail, | ||
1208 | mqm); | ||
1209 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1210 | "Creating MQM %p for peer %s\n", | ||
1211 | mqm, | ||
1212 | GCP_2s (cp)); | ||
1213 | if (NULL != cp->core_mq) | ||
1214 | cb (cb_cls, | ||
1215 | GNUNET_YES); | ||
1216 | return mqm; | ||
1217 | } | ||
1218 | |||
1219 | |||
1220 | /** | ||
1221 | * Stops message queue change notifications. | ||
1222 | * | ||
1223 | * @param mqm handle matching request to cancel | ||
1224 | * @param last_env final message to transmit, or NULL | ||
1225 | */ | ||
1226 | void | ||
1227 | GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm, | ||
1228 | struct GNUNET_MQ_Envelope *last_env) | ||
1229 | { | ||
1230 | struct CadetPeer *cp = mqm->cp; | ||
1231 | |||
1232 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1233 | "Destroying MQM %p for peer %s%s\n", | ||
1234 | mqm, | ||
1235 | GCP_2s (cp), | ||
1236 | (NULL == last_env) ? "" : " with last ditch transmission"); | ||
1237 | if (NULL != mqm->env) | ||
1238 | GNUNET_MQ_discard (mqm->env); | ||
1239 | if (NULL != last_env) | ||
1240 | { | ||
1241 | if (NULL != cp->core_mq) | ||
1242 | GNUNET_MQ_send (cp->core_mq, | ||
1243 | last_env); | ||
1244 | else | ||
1245 | GNUNET_MQ_discard (last_env); | ||
1246 | } | ||
1247 | GNUNET_CONTAINER_DLL_remove (cp->mqm_head, | ||
1248 | cp->mqm_tail, | ||
1249 | mqm); | ||
1250 | GNUNET_free (mqm); | ||
1251 | } | ||
1252 | |||
1253 | |||
1254 | /** | ||
1255 | * Send the message in @a env to @a cp, overriding queueing logic. | ||
1256 | * This function should only be used to send error messages outside | ||
1257 | * of flow and congestion control, similar to ICMP. Note that | ||
1258 | * the envelope may be silently discarded as well. | ||
1259 | * | ||
1260 | * @param cp peer to send the message to | ||
1261 | * @param env envelope with the message to send | ||
1262 | */ | ||
1263 | void | ||
1264 | GCP_send_ooo (struct CadetPeer *cp, | ||
1265 | struct GNUNET_MQ_Envelope *env) | ||
1266 | { | ||
1267 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1268 | "Sending message to %s out of management\n", | ||
1269 | GCP_2s (cp)); | ||
1270 | if (NULL == cp->core_mq) | ||
1271 | { | ||
1272 | GNUNET_MQ_discard (env); | ||
1273 | return; | ||
1274 | } | ||
1275 | GNUNET_MQ_send (cp->core_mq, | ||
1276 | env); | ||
1277 | } | ||
1278 | |||
1279 | |||
1280 | |||
1281 | |||
1282 | /* end of gnunet-service-cadet-new_peer.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new_peer.h b/src/cadet/gnunet-service-cadet-new_peer.h deleted file mode 100644 index aaaef15b8..000000000 --- a/src/cadet/gnunet-service-cadet-new_peer.h +++ /dev/null | |||
@@ -1,380 +0,0 @@ | |||
1 | |||
2 | /* | ||
3 | This file is part of GNUnet. | ||
4 | Copyright (C) 2001-2017 GNUnet e.V. | ||
5 | |||
6 | GNUnet is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published | ||
8 | by the Free Software Foundation; either version 3, or (at your | ||
9 | option) any later version. | ||
10 | |||
11 | GNUnet is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNUnet; see the file COPYING. If not, write to the | ||
18 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
19 | Boston, MA 02110-1301, USA. | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * @file cadet/gnunet-service-cadet-new_peer.h | ||
24 | * @brief Information we track per peer. | ||
25 | * @author Bartlomiej Polot | ||
26 | * @author Christian Grothoff | ||
27 | */ | ||
28 | #ifndef GNUNET_SERVICE_CADET_PEER_H | ||
29 | #define GNUNET_SERVICE_CADET_PEER_H | ||
30 | |||
31 | #include "gnunet-service-cadet-new.h" | ||
32 | #include "gnunet_hello_lib.h" | ||
33 | |||
34 | |||
35 | /** | ||
36 | * Get the static string for a peer ID. | ||
37 | * | ||
38 | * @param peer Peer. | ||
39 | * | ||
40 | * @return Static string for it's ID. | ||
41 | */ | ||
42 | const char * | ||
43 | GCP_2s (const struct CadetPeer *peer); | ||
44 | |||
45 | |||
46 | /** | ||
47 | * Retrieve the CadetPeer stucture associated with the | ||
48 | * peer. Optionally create one and insert it in the appropriate | ||
49 | * structures if the peer is not known yet. | ||
50 | * | ||
51 | * @param peer_id Full identity of the peer. | ||
52 | * @param create #GNUNET_YES if a new peer should be created if unknown. | ||
53 | * #GNUNET_NO to return NULL if peer is unknown. | ||
54 | * @return Existing or newly created peer structure. | ||
55 | * NULL if unknown and not requested @a create | ||
56 | */ | ||
57 | struct CadetPeer * | ||
58 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, | ||
59 | int create); | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Obtain the peer identity for a `struct CadetPeer`. | ||
64 | * | ||
65 | * @param cp our peer handle | ||
66 | * @return the peer identity | ||
67 | */ | ||
68 | const struct GNUNET_PeerIdentity * | ||
69 | GCP_get_id (struct CadetPeer *cp); | ||
70 | |||
71 | |||
72 | /** | ||
73 | * Iterate over all known peers. | ||
74 | * | ||
75 | * @param iter Iterator. | ||
76 | * @param cls Closure for @c iter. | ||
77 | */ | ||
78 | void | ||
79 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | ||
80 | void *cls); | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Count the number of known paths toward the peer. | ||
85 | * | ||
86 | * @param cp Peer to get path info. | ||
87 | * @return Number of known paths. | ||
88 | */ | ||
89 | unsigned int | ||
90 | GCP_count_paths (const struct CadetPeer *cp); | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Drop all paths owned by this peer, and do not | ||
95 | * allow new ones to be added: We are shutting down. | ||
96 | * | ||
97 | * @param cp peer to drop paths to | ||
98 | */ | ||
99 | void | ||
100 | GCP_drop_owned_paths (struct CadetPeer *cp); | ||
101 | |||
102 | |||
103 | /** | ||
104 | * Peer path iterator. | ||
105 | * | ||
106 | * @param cls Closure. | ||
107 | * @param path Path itself | ||
108 | * @param off offset of the target peer in @a path | ||
109 | * @return #GNUNET_YES if should keep iterating. | ||
110 | * #GNUNET_NO otherwise. | ||
111 | */ | ||
112 | typedef int | ||
113 | (*GCP_PathIterator) (void *cls, | ||
114 | struct CadetPeerPath *path, | ||
115 | unsigned int off); | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Iterate over the paths to a peer. | ||
120 | * | ||
121 | * @param cp Peer to get path info. | ||
122 | * @param callback Function to call for every path. | ||
123 | * @param callback_cls Closure for @a callback. | ||
124 | * @return Number of iterated paths. | ||
125 | */ | ||
126 | unsigned int | ||
127 | GCP_iterate_paths (struct CadetPeer *cp, | ||
128 | GCP_PathIterator callback, | ||
129 | void *callback_cls); | ||
130 | |||
131 | |||
132 | /** | ||
133 | * Iterate over the paths to @a peer where | ||
134 | * @a peer is at distance @a dist from us. | ||
135 | * | ||
136 | * @param cp Peer to get path info. | ||
137 | * @param dist desired distance of @a peer to us on the path | ||
138 | * @param callback Function to call for every path. | ||
139 | * @param callback_cls Closure for @a callback. | ||
140 | * @return Number of iterated paths. | ||
141 | */ | ||
142 | unsigned int | ||
143 | GCP_iterate_paths_at (struct CadetPeer *cp, | ||
144 | unsigned int dist, | ||
145 | GCP_PathIterator callback, | ||
146 | void *callback_cls); | ||
147 | |||
148 | |||
149 | /** | ||
150 | * Remove an entry from the DLL of all of the paths that this peer is on. | ||
151 | * | ||
152 | * @param cp peer to modify | ||
153 | * @param entry an entry on a path | ||
154 | * @param off offset of this peer on the path | ||
155 | */ | ||
156 | void | ||
157 | GCP_path_entry_remove (struct CadetPeer *cp, | ||
158 | struct CadetPeerPathEntry *entry, | ||
159 | unsigned int off); | ||
160 | |||
161 | |||
162 | /** | ||
163 | * Add an entry to the DLL of all of the paths that this peer is on. | ||
164 | * | ||
165 | * @param cp peer to modify | ||
166 | * @param entry an entry on a path | ||
167 | * @param off offset of this peer on the path | ||
168 | */ | ||
169 | void | ||
170 | GCP_path_entry_add (struct CadetPeer *cp, | ||
171 | struct CadetPeerPathEntry *entry, | ||
172 | unsigned int off); | ||
173 | |||
174 | |||
175 | /** | ||
176 | * Get the tunnel towards a peer. | ||
177 | * | ||
178 | * @param cp Peer to get from. | ||
179 | * @param create #GNUNET_YES to create a tunnel if we do not have one | ||
180 | * @return Tunnel towards peer. | ||
181 | */ | ||
182 | struct CadetTunnel * | ||
183 | GCP_get_tunnel (struct CadetPeer *cp, | ||
184 | int create); | ||
185 | |||
186 | |||
187 | /** | ||
188 | * The tunnel to the given peer no longer exists, remove it from our | ||
189 | * data structures, and possibly clean up the peer itself. | ||
190 | * | ||
191 | * @param cp the peer affected | ||
192 | * @param t the dead tunnel | ||
193 | */ | ||
194 | void | ||
195 | GCP_drop_tunnel (struct CadetPeer *cp, | ||
196 | struct CadetTunnel *t); | ||
197 | |||
198 | |||
199 | /** | ||
200 | * Try adding a @a path to this @a cp. If the peer already | ||
201 | * has plenty of paths, return NULL. | ||
202 | * | ||
203 | * @param cp peer to which the @a path leads to | ||
204 | * @param path a path looking for an owner; may not be fully initialized yet! | ||
205 | * @param off offset of @a cp in @a path | ||
206 | * @param force for attaching the path | ||
207 | * @return NULL if this peer does not care to become a new owner, | ||
208 | * otherwise the node in the peer's path heap for the @a path. | ||
209 | */ | ||
210 | struct GNUNET_CONTAINER_HeapNode * | ||
211 | GCP_attach_path (struct CadetPeer *cp, | ||
212 | struct CadetPeerPath *path, | ||
213 | unsigned int off, | ||
214 | int force); | ||
215 | |||
216 | |||
217 | /** | ||
218 | * This peer can no longer own @a path as the path | ||
219 | * has been extended and a peer further down the line | ||
220 | * is now the new owner. | ||
221 | * | ||
222 | * @param cp old owner of the @a path | ||
223 | * @param path path where the ownership is lost | ||
224 | * @param hn note in @a cp's path heap that must be deleted | ||
225 | */ | ||
226 | void | ||
227 | GCP_detach_path (struct CadetPeer *cp, | ||
228 | struct CadetPeerPath *path, | ||
229 | struct GNUNET_CONTAINER_HeapNode *hn); | ||
230 | |||
231 | |||
232 | /** | ||
233 | * Add a @a connection to this @a cp. | ||
234 | * | ||
235 | * @param cp peer via which the @a connection goes | ||
236 | * @param cc the connection to add | ||
237 | */ | ||
238 | void | ||
239 | GCP_add_connection (struct CadetPeer *cp, | ||
240 | struct CadetConnection *cc); | ||
241 | |||
242 | |||
243 | /** | ||
244 | * Remove a @a connection that went via this @a cp. | ||
245 | * | ||
246 | * @param cp peer via which the @a connection went | ||
247 | * @param cc the connection to remove | ||
248 | */ | ||
249 | void | ||
250 | GCP_remove_connection (struct CadetPeer *cp, | ||
251 | struct CadetConnection *cc); | ||
252 | |||
253 | |||
254 | /** | ||
255 | * We got a HELLO for a @a cp, remember it, and possibly | ||
256 | * trigger adequate actions (like trying to connect). | ||
257 | * | ||
258 | * @param cp the peer we got a HELLO for | ||
259 | * @param hello the HELLO to remember | ||
260 | */ | ||
261 | void | ||
262 | GCP_set_hello (struct CadetPeer *cp, | ||
263 | const struct GNUNET_HELLO_Message *hello); | ||
264 | |||
265 | |||
266 | /** | ||
267 | * Clean up all entries about all peers. | ||
268 | * Must only be called after all tunnels, CORE-connections and | ||
269 | * connections are down. | ||
270 | */ | ||
271 | void | ||
272 | GCP_destroy_all_peers (void); | ||
273 | |||
274 | |||
275 | /** | ||
276 | * Data structure used to track whom we have to notify about changes | ||
277 | * in our ability to transmit to a given peer. | ||
278 | * | ||
279 | * All queue managers will be given equal chance for sending messages | ||
280 | * to @a cp. This construct this guarantees fairness for access to @a | ||
281 | * cp among the different message queues. Each connection or route | ||
282 | * will have its respective message queue managers for each direction. | ||
283 | */ | ||
284 | struct GCP_MessageQueueManager; | ||
285 | |||
286 | |||
287 | /** | ||
288 | * Function to call with updated message queue object. | ||
289 | * | ||
290 | * @param cls closure | ||
291 | * @param available #GNUNET_YES if sending is now possible, | ||
292 | * #GNUNET_NO if sending is no longer possible | ||
293 | * #GNUNET_SYSERR if sending is no longer possible | ||
294 | * and the last envelope was discarded | ||
295 | */ | ||
296 | typedef void | ||
297 | (*GCP_MessageQueueNotificationCallback)(void *cls, | ||
298 | int available); | ||
299 | |||
300 | |||
301 | /** | ||
302 | * Start message queue change notifications. Will create a new slot | ||
303 | * to manage the message queue to the given @a cp. | ||
304 | * | ||
305 | * @param cp peer to notify for | ||
306 | * @param cb function to call if mq becomes available or unavailable | ||
307 | * @param cb_cls closure for @a cb | ||
308 | * @return handle to cancel request | ||
309 | */ | ||
310 | struct GCP_MessageQueueManager * | ||
311 | GCP_request_mq (struct CadetPeer *cp, | ||
312 | GCP_MessageQueueNotificationCallback cb, | ||
313 | void *cb_cls); | ||
314 | |||
315 | |||
316 | /** | ||
317 | * Test if @a cp has a core-level connection | ||
318 | * | ||
319 | * @param cp peer to test | ||
320 | * @return #GNUNET_YES if @a cp has a core-level connection | ||
321 | */ | ||
322 | int | ||
323 | GCP_has_core_connection (struct CadetPeer *cp); | ||
324 | |||
325 | |||
326 | /** | ||
327 | * Send the message in @a env via a @a mqm. Must only be called at | ||
328 | * most once after the respective | ||
329 | * #GCP_MessageQueueNotificationCallback was called with `available` | ||
330 | * set to #GNUNET_YES, and not after the callback was called with | ||
331 | * `available` set to #GNUNET_NO or #GNUNET_SYSERR. | ||
332 | * | ||
333 | * @param mqm message queue manager for the transmission | ||
334 | * @param env envelope with the message to send; must NOT | ||
335 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
336 | */ | ||
337 | void | ||
338 | GCP_send (struct GCP_MessageQueueManager *mqm, | ||
339 | struct GNUNET_MQ_Envelope *env); | ||
340 | |||
341 | |||
342 | /** | ||
343 | * Send the message in @a env to @a cp, overriding queueing logic. | ||
344 | * This function should only be used to send error messages outside | ||
345 | * of flow and congestion control, similar to ICMP. Note that | ||
346 | * the envelope may be silently discarded as well. | ||
347 | * | ||
348 | * @param cp peer to send the message to | ||
349 | * @param env envelope with the message to send | ||
350 | */ | ||
351 | void | ||
352 | GCP_send_ooo (struct CadetPeer *cp, | ||
353 | struct GNUNET_MQ_Envelope *env); | ||
354 | |||
355 | |||
356 | /** | ||
357 | * Stops message queue change notifications and sends a last message. | ||
358 | * In practice, this is implemented by sending that @a last_env | ||
359 | * message immediately (if any), ignoring queue order. | ||
360 | * | ||
361 | * @param mqm handle matching request to cancel | ||
362 | * @param last_env final message to transmit, or NULL | ||
363 | */ | ||
364 | void | ||
365 | GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm, | ||
366 | struct GNUNET_MQ_Envelope *last_env); | ||
367 | |||
368 | |||
369 | /** | ||
370 | * Set the message queue to @a mq for peer @a cp and notify watchers. | ||
371 | * | ||
372 | * @param cp peer to modify | ||
373 | * @param mq message queue to set (can be NULL) | ||
374 | */ | ||
375 | void | ||
376 | GCP_set_mq (struct CadetPeer *cp, | ||
377 | struct GNUNET_MQ_Handle *mq); | ||
378 | |||
379 | |||
380 | #endif | ||
diff --git a/src/cadet/gnunet-service-cadet.c b/src/cadet/gnunet-service-cadet.c index 3a07f0ee5..af4cebfaa 100644 --- a/src/cadet/gnunet-service-cadet.c +++ b/src/cadet/gnunet-service-cadet.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2001-2013 GNUnet e.V. | 3 | Copyright (C) 2001-2013, 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -22,37 +22,82 @@ | |||
22 | * @file cadet/gnunet-service-cadet.c | 22 | * @file cadet/gnunet-service-cadet.c |
23 | * @brief GNUnet CADET service with encryption | 23 | * @brief GNUnet CADET service with encryption |
24 | * @author Bartlomiej Polot | 24 | * @author Bartlomiej Polot |
25 | * | 25 | * @author Christian Grothoff |
26 | * FIXME in progress: | ||
27 | * - rekey - reliability interaction | ||
28 | * - channel retransmit timing | ||
29 | * | ||
30 | * TODO: | ||
31 | * - relay corking down to core | ||
32 | * - set ttl relative to path length | ||
33 | * TODO END | ||
34 | * | 26 | * |
35 | * Dictionary: | 27 | * Dictionary: |
36 | * - peer: other cadet instance. If there is direct connection it's a neighbor. | 28 | * - peer: other cadet instance. If there is direct connection it's a neighbor. |
37 | * - tunnel: encrypted connection to a peer, neighbor or not. | ||
38 | * - channel: connection between two clients, on the same or different peers. | ||
39 | * have properties like reliability. | ||
40 | * - path: series of directly connected peer from one peer to another. | 29 | * - path: series of directly connected peer from one peer to another. |
41 | * - connection: path which is being used in a tunnel. | 30 | * - connection: path which is being used in a tunnel. |
31 | * - tunnel: encrypted connection to a peer, neighbor or not. | ||
32 | * - channel: logical link between two clients, on the same or different peers. | ||
33 | * have properties like reliability. | ||
42 | */ | 34 | */ |
43 | 35 | ||
44 | #include "platform.h" | 36 | #include "platform.h" |
45 | #include "gnunet_util_lib.h" | 37 | #include "gnunet_util_lib.h" |
46 | #include "cadet.h" | 38 | #include "cadet.h" |
47 | #include "gnunet_statistics_service.h" | 39 | #include "gnunet_statistics_service.h" |
48 | 40 | #include "gnunet-service-cadet.h" | |
49 | #include "gnunet-service-cadet_local.h" | ||
50 | #include "gnunet-service-cadet_channel.h" | 41 | #include "gnunet-service-cadet_channel.h" |
51 | #include "gnunet-service-cadet_connection.h" | 42 | #include "gnunet-service-cadet_connection.h" |
52 | #include "gnunet-service-cadet_tunnel.h" | 43 | #include "gnunet-service-cadet_core.h" |
53 | #include "gnunet-service-cadet_dht.h" | 44 | #include "gnunet-service-cadet_dht.h" |
54 | #include "gnunet-service-cadet_peer.h" | ||
55 | #include "gnunet-service-cadet_hello.h" | 45 | #include "gnunet-service-cadet_hello.h" |
46 | #include "gnunet-service-cadet_tunnels.h" | ||
47 | #include "gnunet-service-cadet_peer.h" | ||
48 | #include "gnunet-service-cadet_paths.h" | ||
49 | |||
50 | #define LOG(level, ...) GNUNET_log (level,__VA_ARGS__) | ||
51 | |||
52 | |||
53 | /** | ||
54 | * Struct containing information about a client of the service | ||
55 | */ | ||
56 | struct CadetClient | ||
57 | { | ||
58 | /** | ||
59 | * Linked list next | ||
60 | */ | ||
61 | struct CadetClient *next; | ||
62 | |||
63 | /** | ||
64 | * Linked list prev | ||
65 | */ | ||
66 | struct CadetClient *prev; | ||
67 | |||
68 | /** | ||
69 | * Tunnels that belong to this client, indexed by local id, | ||
70 | * value is a `struct CadetChannel`. | ||
71 | */ | ||
72 | struct GNUNET_CONTAINER_MultiHashMap32 *channels; | ||
73 | |||
74 | /** | ||
75 | * Handle to communicate with the client | ||
76 | */ | ||
77 | struct GNUNET_MQ_Handle *mq; | ||
78 | |||
79 | /** | ||
80 | * Client handle. | ||
81 | */ | ||
82 | struct GNUNET_SERVICE_Client *client; | ||
83 | |||
84 | /** | ||
85 | * Ports that this client has declared interest in. | ||
86 | * Indexed by port, contains `struct OpenPort` | ||
87 | */ | ||
88 | struct GNUNET_CONTAINER_MultiHashMap *ports; | ||
89 | |||
90 | /** | ||
91 | * Channel ID to use for the next incoming channel for this client. | ||
92 | * Wraps around (in theory). | ||
93 | */ | ||
94 | struct GNUNET_CADET_ClientChannelNumber next_ccn; | ||
95 | |||
96 | /** | ||
97 | * ID of the client, mainly for debug messages. Purely internal to this file. | ||
98 | */ | ||
99 | unsigned int id; | ||
100 | }; | ||
56 | 101 | ||
57 | 102 | ||
58 | /******************************************************************************/ | 103 | /******************************************************************************/ |
@@ -62,37 +107,318 @@ | |||
62 | /****************************** Global variables ******************************/ | 107 | /****************************** Global variables ******************************/ |
63 | 108 | ||
64 | /** | 109 | /** |
110 | * Handle to our configuration. | ||
111 | */ | ||
112 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
113 | |||
114 | /** | ||
65 | * Handle to the statistics service. | 115 | * Handle to the statistics service. |
66 | */ | 116 | */ |
67 | struct GNUNET_STATISTICS_Handle *stats; | 117 | struct GNUNET_STATISTICS_Handle *stats; |
68 | 118 | ||
69 | /** | 119 | /** |
70 | * Local peer own ID (memory efficient handle). | 120 | * Handle to communicate with ATS. |
71 | */ | 121 | */ |
72 | GNUNET_PEER_Id myid; | 122 | struct GNUNET_ATS_ConnectivityHandle *ats_ch; |
73 | 123 | ||
74 | /** | 124 | /** |
75 | * Local peer own ID (full value). | 125 | * Local peer own ID. |
76 | */ | 126 | */ |
77 | struct GNUNET_PeerIdentity my_full_id; | 127 | struct GNUNET_PeerIdentity my_full_id; |
78 | 128 | ||
129 | /** | ||
130 | * Own private key. | ||
131 | */ | ||
132 | struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | ||
79 | 133 | ||
80 | /** | 134 | /** |
81 | * Signal that shutdown is happening: prevent recover measures. | 135 | * Signal that shutdown is happening: prevent recovery measures. |
82 | */ | 136 | */ |
83 | int shutting_down; | 137 | int shutting_down; |
84 | 138 | ||
85 | /*************************** Static global variables **************************/ | 139 | /** |
140 | * DLL with all the clients, head. | ||
141 | */ | ||
142 | static struct CadetClient *clients_head; | ||
86 | 143 | ||
87 | /** | 144 | /** |
88 | * Own private key. | 145 | * DLL with all the clients, tail. |
89 | */ | 146 | */ |
90 | static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | 147 | static struct CadetClient *clients_tail; |
91 | 148 | ||
149 | /** | ||
150 | * Next ID to assign to a client. | ||
151 | */ | ||
152 | static unsigned int next_client_id; | ||
153 | |||
154 | /** | ||
155 | * All ports clients of this peer have opened. Maps from | ||
156 | * a hashed port to a `struct OpenPort`. | ||
157 | */ | ||
158 | struct GNUNET_CONTAINER_MultiHashMap *open_ports; | ||
159 | |||
160 | /** | ||
161 | * Map from ports to channels where the ports were closed at the | ||
162 | * time we got the inbound connection. | ||
163 | * Indexed by h_port, contains `struct CadetChannel`. | ||
164 | */ | ||
165 | struct GNUNET_CONTAINER_MultiHashMap *loose_channels; | ||
166 | |||
167 | /** | ||
168 | * Map from PIDs to `struct CadetPeer` entries. | ||
169 | */ | ||
170 | struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
171 | |||
172 | /** | ||
173 | * Map from `struct GNUNET_CADET_ConnectionTunnelIdentifier` | ||
174 | * hash codes to `struct CadetConnection` objects. | ||
175 | */ | ||
176 | struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
177 | |||
178 | /** | ||
179 | * How many messages are needed to trigger an AXOLOTL ratchet advance. | ||
180 | */ | ||
181 | unsigned long long ratchet_messages; | ||
182 | |||
183 | /** | ||
184 | * How long until we trigger a ratched advance due to time. | ||
185 | */ | ||
186 | struct GNUNET_TIME_Relative ratchet_time; | ||
187 | |||
188 | /** | ||
189 | * How frequently do we send KEEPALIVE messages on idle connections? | ||
190 | */ | ||
191 | struct GNUNET_TIME_Relative keepalive_period; | ||
192 | |||
193 | /** | ||
194 | * Set to non-zero values to create random drops to test retransmissions. | ||
195 | */ | ||
196 | unsigned long long drop_percent; | ||
197 | |||
198 | |||
199 | /** | ||
200 | * Send a message to a client. | ||
201 | * | ||
202 | * @param c client to get the message | ||
203 | * @param env envelope with the message | ||
204 | */ | ||
205 | void | ||
206 | GSC_send_to_client (struct CadetClient *c, | ||
207 | struct GNUNET_MQ_Envelope *env) | ||
208 | { | ||
209 | GNUNET_MQ_send (c->mq, | ||
210 | env); | ||
211 | } | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Return identifier for a client as a string. | ||
216 | * | ||
217 | * @param c client to identify | ||
218 | * @return string for debugging | ||
219 | */ | ||
220 | const char * | ||
221 | GSC_2s (struct CadetClient *c) | ||
222 | { | ||
223 | static char buf[32]; | ||
224 | |||
225 | GNUNET_snprintf (buf, | ||
226 | sizeof (buf), | ||
227 | "Client(%u)", | ||
228 | c->id); | ||
229 | return buf; | ||
230 | } | ||
231 | |||
232 | |||
233 | /** | ||
234 | * Lookup channel of client @a c by @a ccn. | ||
235 | * | ||
236 | * @param c client to look in | ||
237 | * @param ccn channel ID to look up | ||
238 | * @return NULL if no such channel exists | ||
239 | */ | ||
240 | static struct CadetChannel * | ||
241 | lookup_channel (struct CadetClient *c, | ||
242 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
243 | { | ||
244 | return GNUNET_CONTAINER_multihashmap32_get (c->channels, | ||
245 | ntohl (ccn.channel_of_client)); | ||
246 | } | ||
247 | |||
248 | |||
249 | /** | ||
250 | * Obtain the next LID to use for incoming connections to | ||
251 | * the given client. | ||
252 | * | ||
253 | * @param c client handle | ||
254 | */ | ||
255 | static struct GNUNET_CADET_ClientChannelNumber | ||
256 | client_get_next_ccn (struct CadetClient *c) | ||
257 | { | ||
258 | struct GNUNET_CADET_ClientChannelNumber ccn = c->next_ccn; | ||
259 | |||
260 | /* increment until we have a free one... */ | ||
261 | while (NULL != | ||
262 | lookup_channel (c, | ||
263 | ccn)) | ||
264 | { | ||
265 | ccn.channel_of_client | ||
266 | = htonl (1 + (ntohl (ccn.channel_of_client))); | ||
267 | if (ntohl (ccn.channel_of_client) >= | ||
268 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
269 | ccn.channel_of_client = htonl (0); | ||
270 | } | ||
271 | c->next_ccn.channel_of_client | ||
272 | = htonl (1 + (ntohl (ccn.channel_of_client))); | ||
273 | return ccn; | ||
274 | } | ||
275 | |||
276 | |||
277 | /** | ||
278 | * Bind incoming channel to this client, and notify client about | ||
279 | * incoming connection. Caller is responsible for notifying the other | ||
280 | * peer about our acceptance of the channel. | ||
281 | * | ||
282 | * @param c client to bind to | ||
283 | * @param ch channel to be bound | ||
284 | * @param dest peer that establishes the connection | ||
285 | * @param port port number | ||
286 | * @param options options | ||
287 | * @return local channel number assigned to the new client | ||
288 | */ | ||
289 | struct GNUNET_CADET_ClientChannelNumber | ||
290 | GSC_bind (struct CadetClient *c, | ||
291 | struct CadetChannel *ch, | ||
292 | struct CadetPeer *dest, | ||
293 | const struct GNUNET_HashCode *port, | ||
294 | uint32_t options) | ||
295 | { | ||
296 | struct GNUNET_MQ_Envelope *env; | ||
297 | struct GNUNET_CADET_LocalChannelCreateMessage *cm; | ||
298 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
299 | |||
300 | ccn = client_get_next_ccn (c); | ||
301 | GNUNET_assert (GNUNET_YES == | ||
302 | GNUNET_CONTAINER_multihashmap32_put (c->channels, | ||
303 | ntohl (ccn.channel_of_client), | ||
304 | ch, | ||
305 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
306 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
307 | "Accepting incoming %s from %s on open port %s (%u), assigning ccn %X\n", | ||
308 | GCCH_2s (ch), | ||
309 | GCP_2s (dest), | ||
310 | GNUNET_h2s (port), | ||
311 | (uint32_t) ntohl (options), | ||
312 | (uint32_t) ntohl (ccn.channel_of_client)); | ||
313 | /* notify local client about incoming connection! */ | ||
314 | env = GNUNET_MQ_msg (cm, | ||
315 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); | ||
316 | cm->ccn = ccn; | ||
317 | cm->port = *port; | ||
318 | cm->opt = htonl (options); | ||
319 | cm->peer = *GCP_get_id (dest); | ||
320 | GSC_send_to_client (c, | ||
321 | env); | ||
322 | return ccn; | ||
323 | } | ||
324 | |||
325 | |||
326 | /** | ||
327 | * Callback invoked on all peers to destroy all tunnels | ||
328 | * that may still exist. | ||
329 | * | ||
330 | * @param cls NULL | ||
331 | * @param pid identify of a peer | ||
332 | * @param value a `struct CadetPeer` that may still have a tunnel | ||
333 | * @return #GNUNET_OK (iterate over all entries) | ||
334 | */ | ||
335 | static int | ||
336 | destroy_tunnels_now (void *cls, | ||
337 | const struct GNUNET_PeerIdentity *pid, | ||
338 | void *value) | ||
339 | { | ||
340 | struct CadetPeer *cp = value; | ||
341 | struct CadetTunnel *t = GCP_get_tunnel (cp, | ||
342 | GNUNET_NO); | ||
343 | |||
344 | if (NULL != t) | ||
345 | GCT_destroy_tunnel_now (t); | ||
346 | return GNUNET_OK; | ||
347 | } | ||
348 | |||
349 | |||
350 | /** | ||
351 | * Callback invoked on all peers to destroy all tunnels | ||
352 | * that may still exist. | ||
353 | * | ||
354 | * @param cls NULL | ||
355 | * @param pid identify of a peer | ||
356 | * @param value a `struct CadetPeer` that may still have a tunnel | ||
357 | * @return #GNUNET_OK (iterate over all entries) | ||
358 | */ | ||
359 | static int | ||
360 | destroy_paths_now (void *cls, | ||
361 | const struct GNUNET_PeerIdentity *pid, | ||
362 | void *value) | ||
363 | { | ||
364 | struct CadetPeer *cp = value; | ||
365 | |||
366 | GCP_drop_owned_paths (cp); | ||
367 | return GNUNET_OK; | ||
368 | } | ||
369 | |||
370 | |||
371 | /** | ||
372 | * Shutdown everything once the clients have disconnected. | ||
373 | */ | ||
374 | static void | ||
375 | shutdown_rest () | ||
376 | { | ||
377 | if (NULL != stats) | ||
378 | { | ||
379 | GNUNET_STATISTICS_destroy (stats, | ||
380 | GNUNET_NO); | ||
381 | stats = NULL; | ||
382 | } | ||
383 | if (NULL != open_ports) | ||
384 | { | ||
385 | GNUNET_CONTAINER_multihashmap_destroy (open_ports); | ||
386 | open_ports = NULL; | ||
387 | } | ||
388 | if (NULL != loose_channels) | ||
389 | { | ||
390 | GNUNET_CONTAINER_multihashmap_destroy (loose_channels); | ||
391 | loose_channels = NULL; | ||
392 | } | ||
393 | /* Destroy tunnels. Note that all channels must be destroyed first! */ | ||
394 | GCP_iterate_all (&destroy_tunnels_now, | ||
395 | NULL); | ||
396 | /* All tunnels, channels, connections and CORE must be down before this point. */ | ||
397 | GCP_iterate_all (&destroy_paths_now, | ||
398 | NULL); | ||
399 | /* All paths, tunnels, channels, connections and CORE must be down before this point. */ | ||
400 | GCP_destroy_all_peers (); | ||
401 | if (NULL != peers) | ||
402 | { | ||
403 | GNUNET_CONTAINER_multipeermap_destroy (peers); | ||
404 | peers = NULL; | ||
405 | } | ||
406 | if (NULL != connections) | ||
407 | { | ||
408 | GNUNET_CONTAINER_multishortmap_destroy (connections); | ||
409 | connections = NULL; | ||
410 | } | ||
411 | if (NULL != ats_ch) | ||
412 | { | ||
413 | GNUNET_ATS_connectivity_done (ats_ch); | ||
414 | ats_ch = NULL; | ||
415 | } | ||
416 | GCD_shutdown (); | ||
417 | GCH_shutdown (); | ||
418 | GNUNET_free_non_null (my_private_key); | ||
419 | my_private_key = NULL; | ||
420 | } | ||
92 | 421 | ||
93 | /******************************************************************************/ | ||
94 | /************************ MAIN FUNCTIONS ****************************/ | ||
95 | /******************************************************************************/ | ||
96 | 422 | ||
97 | /** | 423 | /** |
98 | * Task run during shutdown. | 424 | * Task run during shutdown. |
@@ -102,83 +428,1087 @@ static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | |||
102 | static void | 428 | static void |
103 | shutdown_task (void *cls) | 429 | shutdown_task (void *cls) |
104 | { | 430 | { |
105 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n"); | 431 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
106 | 432 | "Shutting down\n"); | |
107 | shutting_down = GNUNET_YES; | 433 | shutting_down = GNUNET_YES; |
434 | GCO_shutdown (); | ||
435 | if (NULL == clients_head) | ||
436 | shutdown_rest (); | ||
437 | } | ||
108 | 438 | ||
109 | GML_shutdown (); | ||
110 | GCH_shutdown (); | ||
111 | GCC_shutdown (); | ||
112 | GCT_shutdown (); | ||
113 | GCD_shutdown (); | ||
114 | GCP_shutdown (); | ||
115 | 439 | ||
116 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | 440 | /** |
117 | stats = NULL; | 441 | * We had a remote connection @a value to port @a h_port before |
118 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); | 442 | * client @a cls opened port @a port. Bind them now. |
443 | * | ||
444 | * @param cls the `struct CadetClient` | ||
445 | * @param h_port the hashed port | ||
446 | * @param value the `struct CadetChannel` | ||
447 | * @return #GNUNET_YES (iterate over all such channels) | ||
448 | */ | ||
449 | static int | ||
450 | bind_loose_channel (void *cls, | ||
451 | const struct GNUNET_HashCode *port, | ||
452 | void *value) | ||
453 | { | ||
454 | struct OpenPort *op = cls; | ||
455 | struct CadetChannel *ch = value; | ||
456 | |||
457 | GCCH_bind (ch, | ||
458 | op->c, | ||
459 | &op->port); | ||
460 | GNUNET_assert (GNUNET_YES == | ||
461 | GNUNET_CONTAINER_multihashmap_remove (loose_channels, | ||
462 | &op->h_port, | ||
463 | ch)); | ||
464 | return GNUNET_YES; | ||
119 | } | 465 | } |
120 | 466 | ||
121 | 467 | ||
122 | /** | 468 | /** |
123 | * Process cadet requests. | 469 | * Handle port open request. Creates a mapping from the |
470 | * port to the respective client and checks whether we have | ||
471 | * loose channels trying to bind to the port. If so, those | ||
472 | * are bound. | ||
124 | * | 473 | * |
125 | * @param cls closure | 474 | * @param cls Identification of the client. |
126 | * @param server the initialized server | 475 | * @param pmsg The actual message. |
127 | * @param c configuration to use | ||
128 | */ | 476 | */ |
129 | static void | 477 | static void |
130 | run (void *cls, struct GNUNET_SERVER_Handle *server, | 478 | handle_port_open (void *cls, |
131 | const struct GNUNET_CONFIGURATION_Handle *c) | 479 | const struct GNUNET_CADET_PortMessage *pmsg) |
132 | { | 480 | { |
133 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n"); | 481 | struct CadetClient *c = cls; |
482 | struct OpenPort *op; | ||
134 | 483 | ||
135 | stats = GNUNET_STATISTICS_create ("cadet", c); | 484 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
485 | "Open port %s requested by %s\n", | ||
486 | GNUNET_h2s (&pmsg->port), | ||
487 | GSC_2s (c)); | ||
488 | if (NULL == c->ports) | ||
489 | c->ports = GNUNET_CONTAINER_multihashmap_create (4, | ||
490 | GNUNET_NO); | ||
491 | op = GNUNET_new (struct OpenPort); | ||
492 | op->c = c; | ||
493 | op->port = pmsg->port; | ||
494 | GCCH_hash_port (&op->h_port, | ||
495 | &pmsg->port, | ||
496 | &my_full_id); | ||
497 | if (GNUNET_OK != | ||
498 | GNUNET_CONTAINER_multihashmap_put (c->ports, | ||
499 | &op->port, | ||
500 | op, | ||
501 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
502 | { | ||
503 | GNUNET_break (0); | ||
504 | GNUNET_SERVICE_client_drop (c->client); | ||
505 | return; | ||
506 | } | ||
507 | (void) GNUNET_CONTAINER_multihashmap_put (open_ports, | ||
508 | &op->h_port, | ||
509 | op, | ||
510 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
511 | GNUNET_CONTAINER_multihashmap_get_multiple (loose_channels, | ||
512 | &op->h_port, | ||
513 | &bind_loose_channel, | ||
514 | op); | ||
515 | GNUNET_SERVICE_client_continue (c->client); | ||
516 | } | ||
136 | 517 | ||
137 | /* Scheduled the task to clean up when shutdown is called */ | ||
138 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | ||
139 | NULL); | ||
140 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "reading key\n"); | ||
141 | my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c); | ||
142 | GNUNET_assert (NULL != my_private_key); | ||
143 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_full_id.public_key); | ||
144 | myid = GNUNET_PEER_intern (&my_full_id); | ||
145 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
146 | "STARTING SERVICE (cadet) for peer [%s]\n", | ||
147 | GNUNET_i2s (&my_full_id)); | ||
148 | 518 | ||
149 | GML_init (server); /* Local clients */ | 519 | /** |
150 | GCH_init (c); /* Hellos */ | 520 | * Handler for port close requests. Marks this port as closed |
151 | GCC_init (c); /* Connections */ | 521 | * (unless of course we have another client with the same port |
152 | GCP_init (c); /* Peers */ | 522 | * open). Note that existing channels accepted on the port are |
153 | GCD_init (c); /* DHT */ | 523 | * not affected. |
154 | GCT_init (c, my_private_key); /* Tunnels */ | 524 | * |
525 | * @param cls Identification of the client. | ||
526 | * @param pmsg The actual message. | ||
527 | */ | ||
528 | static void | ||
529 | handle_port_close (void *cls, | ||
530 | const struct GNUNET_CADET_PortMessage *pmsg) | ||
531 | { | ||
532 | struct CadetClient *c = cls; | ||
533 | struct OpenPort *op; | ||
155 | 534 | ||
156 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cadet service running\n"); | 535 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
536 | "Closing port %s as requested by %s\n", | ||
537 | GNUNET_h2s (&pmsg->port), | ||
538 | GSC_2s (c)); | ||
539 | op = GNUNET_CONTAINER_multihashmap_get (c->ports, | ||
540 | &pmsg->port); | ||
541 | if (NULL == op) | ||
542 | { | ||
543 | GNUNET_break (0); | ||
544 | GNUNET_SERVICE_client_drop (c->client); | ||
545 | return; | ||
546 | } | ||
547 | GNUNET_assert (GNUNET_YES == | ||
548 | GNUNET_CONTAINER_multihashmap_remove (c->ports, | ||
549 | &op->port, | ||
550 | op)); | ||
551 | GNUNET_assert (GNUNET_YES == | ||
552 | GNUNET_CONTAINER_multihashmap_remove (open_ports, | ||
553 | &op->h_port, | ||
554 | op)); | ||
555 | GNUNET_free (op); | ||
556 | GNUNET_SERVICE_client_continue (c->client); | ||
157 | } | 557 | } |
158 | 558 | ||
159 | 559 | ||
160 | /** | 560 | /** |
161 | * The main function for the cadet service. | 561 | * Handler for requests for us creating a new channel to another peer and port. |
162 | * | 562 | * |
163 | * @param argc number of arguments from the command line | 563 | * @param cls Identification of the client. |
164 | * @param argv command line arguments | 564 | * @param tcm The actual message. |
165 | * @return 0 ok, 1 on error | ||
166 | */ | 565 | */ |
167 | int | 566 | static void |
168 | main (int argc, char *const *argv) | 567 | handle_channel_create (void *cls, |
568 | const struct GNUNET_CADET_LocalChannelCreateMessage *tcm) | ||
169 | { | 569 | { |
170 | int r; | 570 | struct CadetClient *c = cls; |
571 | struct CadetChannel *ch; | ||
171 | 572 | ||
172 | shutting_down = GNUNET_NO; | 573 | if (ntohl (tcm->ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) |
173 | r = GNUNET_SERVICE_run (argc, argv, "cadet", GNUNET_SERVICE_OPTION_NONE, &run, | 574 | { |
174 | NULL); | 575 | /* Channel ID not in allowed range. */ |
175 | GNUNET_free (my_private_key); | 576 | GNUNET_break (0); |
577 | GNUNET_SERVICE_client_drop (c->client); | ||
578 | return; | ||
579 | } | ||
580 | ch = lookup_channel (c, | ||
581 | tcm->ccn); | ||
582 | if (NULL != ch) | ||
583 | { | ||
584 | /* Channel ID already in use. Not allowed. */ | ||
585 | GNUNET_break (0); | ||
586 | GNUNET_SERVICE_client_drop (c->client); | ||
587 | return; | ||
588 | } | ||
589 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
590 | "New channel to %s at port %s requested by %s\n", | ||
591 | GNUNET_i2s (&tcm->peer), | ||
592 | GNUNET_h2s (&tcm->port), | ||
593 | GSC_2s (c)); | ||
176 | 594 | ||
177 | if (GNUNET_OK != r) | 595 | /* Create channel */ |
596 | ch = GCCH_channel_local_new (c, | ||
597 | tcm->ccn, | ||
598 | GCP_get (&tcm->peer, | ||
599 | GNUNET_YES), | ||
600 | &tcm->port, | ||
601 | ntohl (tcm->opt)); | ||
602 | if (NULL == ch) | ||
178 | { | 603 | { |
179 | FPRINTF (stderr, "GNUNET_SERVICE_run for CADET has failed!\n"); | 604 | GNUNET_break (0); |
180 | return 1; | 605 | GNUNET_SERVICE_client_drop (c->client); |
606 | return; | ||
181 | } | 607 | } |
608 | GNUNET_assert (GNUNET_YES == | ||
609 | GNUNET_CONTAINER_multihashmap32_put (c->channels, | ||
610 | ntohl (tcm->ccn.channel_of_client), | ||
611 | ch, | ||
612 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
182 | 613 | ||
183 | return 0; | 614 | GNUNET_SERVICE_client_continue (c->client); |
184 | } | 615 | } |
616 | |||
617 | |||
618 | /** | ||
619 | * Handler for requests of destroying an existing channel. | ||
620 | * | ||
621 | * @param cls client identification of the client | ||
622 | * @param msg the actual message | ||
623 | */ | ||
624 | static void | ||
625 | handle_channel_destroy (void *cls, | ||
626 | const struct GNUNET_CADET_LocalChannelDestroyMessage *msg) | ||
627 | { | ||
628 | struct CadetClient *c = cls; | ||
629 | struct CadetChannel *ch; | ||
630 | |||
631 | ch = lookup_channel (c, | ||
632 | msg->ccn); | ||
633 | if (NULL == ch) | ||
634 | { | ||
635 | /* Client attempted to destroy unknown channel. | ||
636 | Can happen if the other side went down at the same time.*/ | ||
637 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
638 | "%s tried to destroy unknown channel %X\n", | ||
639 | GSC_2s(c), | ||
640 | (uint32_t) ntohl (msg->ccn.channel_of_client)); | ||
641 | return; | ||
642 | } | ||
643 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
644 | "%s is destroying %s\n", | ||
645 | GSC_2s(c), | ||
646 | GCCH_2s (ch)); | ||
647 | GNUNET_assert (GNUNET_YES == | ||
648 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
649 | ntohl (msg->ccn.channel_of_client), | ||
650 | ch)); | ||
651 | GCCH_channel_local_destroy (ch, | ||
652 | c, | ||
653 | msg->ccn); | ||
654 | GNUNET_SERVICE_client_continue (c->client); | ||
655 | } | ||
656 | |||
657 | |||
658 | /** | ||
659 | * Check for client traffic data message is well-formed. | ||
660 | * | ||
661 | * @param cls identification of the client | ||
662 | * @param msg the actual message | ||
663 | * @return #GNUNET_OK if @a msg is OK, #GNUNET_SYSERR if not | ||
664 | */ | ||
665 | static int | ||
666 | check_local_data (void *cls, | ||
667 | const struct GNUNET_CADET_LocalData *msg) | ||
668 | { | ||
669 | size_t payload_size; | ||
670 | size_t payload_claimed_size; | ||
671 | const char *buf; | ||
672 | struct GNUNET_MessageHeader pa; | ||
673 | |||
674 | /* FIXME: what is the format we shall allow for @a msg? | ||
675 | ONE payload item or multiple? Seems current cadet_api | ||
676 | at least in theory allows more than one. Next-gen | ||
677 | cadet_api will likely no more, so we could then | ||
678 | simplify this mess again. */ | ||
679 | /* Sanity check for message size */ | ||
680 | payload_size = ntohs (msg->header.size) - sizeof (*msg); | ||
681 | buf = (const char *) &msg[1]; | ||
682 | while (payload_size >= sizeof (struct GNUNET_MessageHeader)) | ||
683 | { | ||
684 | /* need to memcpy() for alignment */ | ||
685 | GNUNET_memcpy (&pa, | ||
686 | buf, | ||
687 | sizeof (pa)); | ||
688 | payload_claimed_size = ntohs (pa.size); | ||
689 | if ( (payload_size < payload_claimed_size) || | ||
690 | (payload_claimed_size < sizeof (struct GNUNET_MessageHeader)) || | ||
691 | (GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size) ) | ||
692 | { | ||
693 | GNUNET_break (0); | ||
694 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
695 | "Local data of %u total size had sub-message %u at %u with %u bytes\n", | ||
696 | ntohs (msg->header.size), | ||
697 | ntohs (pa.type), | ||
698 | (unsigned int) (buf - (const char *) &msg[1]), | ||
699 | (unsigned int) payload_claimed_size); | ||
700 | return GNUNET_SYSERR; | ||
701 | } | ||
702 | payload_size -= payload_claimed_size; | ||
703 | buf += payload_claimed_size; | ||
704 | } | ||
705 | if (0 != payload_size) | ||
706 | { | ||
707 | GNUNET_break_op (0); | ||
708 | return GNUNET_SYSERR; | ||
709 | } | ||
710 | return GNUNET_OK; | ||
711 | } | ||
712 | |||
713 | |||
714 | /** | ||
715 | * Handler for client payload traffic to be send on a channel to | ||
716 | * another peer. | ||
717 | * | ||
718 | * @param cls identification of the client | ||
719 | * @param msg the actual message | ||
720 | */ | ||
721 | static void | ||
722 | handle_local_data (void *cls, | ||
723 | const struct GNUNET_CADET_LocalData *msg) | ||
724 | { | ||
725 | struct CadetClient *c = cls; | ||
726 | struct CadetChannel *ch; | ||
727 | size_t payload_size; | ||
728 | const char *buf; | ||
729 | |||
730 | ch = lookup_channel (c, | ||
731 | msg->ccn); | ||
732 | if (NULL == ch) | ||
733 | { | ||
734 | /* Channel does not exist (anymore) */ | ||
735 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
736 | "Dropping payload for channel %u from client (channel unknown, other endpoint may have disconnected)\n", | ||
737 | (unsigned int) ntohl (msg->ccn.channel_of_client)); | ||
738 | GNUNET_SERVICE_client_continue (c->client); | ||
739 | return; | ||
740 | } | ||
741 | payload_size = ntohs (msg->header.size) - sizeof (*msg); | ||
742 | GNUNET_STATISTICS_update (stats, | ||
743 | "# payload received from clients", | ||
744 | payload_size, | ||
745 | GNUNET_NO); | ||
746 | buf = (const char *) &msg[1]; | ||
747 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
748 | "Received %u bytes payload from %s for %s\n", | ||
749 | (unsigned int) payload_size, | ||
750 | GSC_2s (c), | ||
751 | GCCH_2s (ch)); | ||
752 | if (GNUNET_OK != | ||
753 | GCCH_handle_local_data (ch, | ||
754 | msg->ccn, | ||
755 | buf, | ||
756 | payload_size)) | ||
757 | { | ||
758 | GNUNET_SERVICE_client_drop (c->client); | ||
759 | return; | ||
760 | } | ||
761 | GNUNET_SERVICE_client_continue (c->client); | ||
762 | } | ||
763 | |||
764 | |||
765 | /** | ||
766 | * Handler for client's ACKs for payload traffic. | ||
767 | * | ||
768 | * @param cls identification of the client. | ||
769 | * @param msg The actual message. | ||
770 | */ | ||
771 | static void | ||
772 | handle_local_ack (void *cls, | ||
773 | const struct GNUNET_CADET_LocalAck *msg) | ||
774 | { | ||
775 | struct CadetClient *c = cls; | ||
776 | struct CadetChannel *ch; | ||
777 | |||
778 | ch = lookup_channel (c, | ||
779 | msg->ccn); | ||
780 | if (NULL == ch) | ||
781 | { | ||
782 | /* Channel does not exist (anymore) */ | ||
783 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
784 | "Ignoring local ACK for channel %u from client (channel unknown, other endpoint may have disconnected)\n", | ||
785 | (unsigned int) ntohl (msg->ccn.channel_of_client)); | ||
786 | GNUNET_SERVICE_client_continue (c->client); | ||
787 | return; | ||
788 | } | ||
789 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
790 | "Got a local ACK from %s for %s\n", | ||
791 | GSC_2s(c), | ||
792 | GCCH_2s (ch)); | ||
793 | GCCH_handle_local_ack (ch, | ||
794 | msg->ccn); | ||
795 | GNUNET_SERVICE_client_continue (c->client); | ||
796 | } | ||
797 | |||
798 | |||
799 | /** | ||
800 | * Iterator over all peers to send a monitoring client info about each peer. | ||
801 | * | ||
802 | * @param cls Closure (). | ||
803 | * @param peer Peer ID (tunnel remote peer). | ||
804 | * @param value Peer info. | ||
805 | * @return #GNUNET_YES, to keep iterating. | ||
806 | */ | ||
807 | static int | ||
808 | get_all_peers_iterator (void *cls, | ||
809 | const struct GNUNET_PeerIdentity *peer, | ||
810 | void *value) | ||
811 | { | ||
812 | struct CadetClient *c = cls; | ||
813 | struct CadetPeer *p = value; | ||
814 | struct GNUNET_MQ_Envelope *env; | ||
815 | struct GNUNET_CADET_LocalInfoPeer *msg; | ||
816 | |||
817 | env = GNUNET_MQ_msg (msg, | ||
818 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
819 | msg->destination = *peer; | ||
820 | msg->paths = htons (GCP_count_paths (p)); | ||
821 | msg->tunnel = htons (NULL != GCP_get_tunnel (p, | ||
822 | GNUNET_NO)); | ||
823 | GNUNET_MQ_send (c->mq, | ||
824 | env); | ||
825 | return GNUNET_YES; | ||
826 | } | ||
827 | |||
828 | |||
829 | /** | ||
830 | * Handler for client's INFO PEERS request. | ||
831 | * | ||
832 | * @param cls Identification of the client. | ||
833 | * @param message The actual message. | ||
834 | */ | ||
835 | static void | ||
836 | handle_get_peers (void *cls, | ||
837 | const struct GNUNET_MessageHeader *message) | ||
838 | { | ||
839 | struct CadetClient *c = cls; | ||
840 | struct GNUNET_MQ_Envelope *env; | ||
841 | struct GNUNET_MessageHeader *reply; | ||
842 | |||
843 | GCP_iterate_all (&get_all_peers_iterator, | ||
844 | c); | ||
845 | env = GNUNET_MQ_msg (reply, | ||
846 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
847 | GNUNET_MQ_send (c->mq, | ||
848 | env); | ||
849 | GNUNET_SERVICE_client_continue (c->client); | ||
850 | } | ||
851 | |||
852 | |||
853 | /** | ||
854 | * Iterator over all paths of a peer to build an InfoPeer message. | ||
855 | * Message contains blocks of peers, first not included. | ||
856 | * | ||
857 | * @param cls message queue for transmission | ||
858 | * @param path Path itself | ||
859 | * @param off offset of the peer on @a path | ||
860 | * @return #GNUNET_YES if should keep iterating. | ||
861 | * #GNUNET_NO otherwise. | ||
862 | */ | ||
863 | static int | ||
864 | path_info_iterator (void *cls, | ||
865 | struct CadetPeerPath *path, | ||
866 | unsigned int off) | ||
867 | { | ||
868 | struct GNUNET_MQ_Handle *mq = cls; | ||
869 | struct GNUNET_MQ_Envelope *env; | ||
870 | struct GNUNET_MessageHeader *resp; | ||
871 | struct GNUNET_PeerIdentity *id; | ||
872 | uint16_t path_size; | ||
873 | unsigned int i; | ||
874 | unsigned int path_length; | ||
875 | |||
876 | path_length = GCPP_get_length (path); | ||
877 | path_size = sizeof (struct GNUNET_PeerIdentity) * (path_length - 1); | ||
878 | if (sizeof (*resp) + path_size > UINT16_MAX) | ||
879 | { | ||
880 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
881 | "Path of %u entries is too long for info message\n", | ||
882 | path_length); | ||
883 | return GNUNET_YES; | ||
884 | } | ||
885 | env = GNUNET_MQ_msg_extra (resp, | ||
886 | path_size, | ||
887 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); | ||
888 | id = (struct GNUNET_PeerIdentity *) &resp[1]; | ||
889 | |||
890 | /* Don't copy first peer. First peer is always the local one. Last | ||
891 | * peer is always the destination (leave as 0, EOL). | ||
892 | */ | ||
893 | for (i = 0; i < off; i++) | ||
894 | id[i] = *GCP_get_id (GCPP_get_peer_at_offset (path, | ||
895 | i + 1)); | ||
896 | GNUNET_MQ_send (mq, | ||
897 | env); | ||
898 | return GNUNET_YES; | ||
899 | } | ||
900 | |||
901 | |||
902 | /** | ||
903 | * Handler for client's SHOW_PEER request. | ||
904 | * | ||
905 | * @param cls Identification of the client. | ||
906 | * @param msg The actual message. | ||
907 | */ | ||
908 | static void | ||
909 | handle_show_peer (void *cls, | ||
910 | const struct GNUNET_CADET_LocalInfo *msg) | ||
911 | { | ||
912 | struct CadetClient *c = cls; | ||
913 | struct CadetPeer *p; | ||
914 | struct GNUNET_MQ_Envelope *env; | ||
915 | struct GNUNET_MessageHeader *resp; | ||
916 | |||
917 | p = GCP_get (&msg->peer, | ||
918 | GNUNET_NO); | ||
919 | if (NULL != p) | ||
920 | GCP_iterate_paths (p, | ||
921 | &path_info_iterator, | ||
922 | c->mq); | ||
923 | /* Send message with 0/0 to indicate the end */ | ||
924 | env = GNUNET_MQ_msg (resp, | ||
925 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER_END); | ||
926 | GNUNET_MQ_send (c->mq, | ||
927 | env); | ||
928 | GNUNET_SERVICE_client_continue (c->client); | ||
929 | } | ||
930 | |||
931 | |||
932 | /** | ||
933 | * Iterator over all tunnels to send a monitoring client info about each tunnel. | ||
934 | * | ||
935 | * @param cls Closure (). | ||
936 | * @param peer Peer ID (tunnel remote peer). | ||
937 | * @param value a `struct CadetPeer` | ||
938 | * @return #GNUNET_YES, to keep iterating. | ||
939 | */ | ||
940 | static int | ||
941 | get_all_tunnels_iterator (void *cls, | ||
942 | const struct GNUNET_PeerIdentity *peer, | ||
943 | void *value) | ||
944 | { | ||
945 | struct CadetClient *c = cls; | ||
946 | struct CadetPeer *p = value; | ||
947 | struct GNUNET_MQ_Envelope *env; | ||
948 | struct GNUNET_CADET_LocalInfoTunnel *msg; | ||
949 | struct CadetTunnel *t; | ||
950 | |||
951 | t = GCP_get_tunnel (p, | ||
952 | GNUNET_NO); | ||
953 | if (NULL == t) | ||
954 | return GNUNET_YES; | ||
955 | env = GNUNET_MQ_msg (msg, | ||
956 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
957 | msg->destination = *peer; | ||
958 | msg->channels = htonl (GCT_count_channels (t)); | ||
959 | msg->connections = htonl (GCT_count_any_connections (t)); | ||
960 | msg->cstate = htons (0); | ||
961 | msg->estate = htons ((uint16_t) GCT_get_estate (t)); | ||
962 | GNUNET_MQ_send (c->mq, | ||
963 | env); | ||
964 | return GNUNET_YES; | ||
965 | } | ||
966 | |||
967 | |||
968 | /** | ||
969 | * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS request. | ||
970 | * | ||
971 | * @param cls client Identification of the client. | ||
972 | * @param message The actual message. | ||
973 | */ | ||
974 | static void | ||
975 | handle_info_tunnels (void *cls, | ||
976 | const struct GNUNET_MessageHeader *message) | ||
977 | { | ||
978 | struct CadetClient *c = cls; | ||
979 | struct GNUNET_MQ_Envelope *env; | ||
980 | struct GNUNET_MessageHeader *reply; | ||
981 | |||
982 | GCP_iterate_all (&get_all_tunnels_iterator, | ||
983 | c); | ||
984 | env = GNUNET_MQ_msg (reply, | ||
985 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
986 | GNUNET_MQ_send (c->mq, | ||
987 | env); | ||
988 | GNUNET_SERVICE_client_continue (c->client); | ||
989 | } | ||
990 | |||
991 | |||
992 | /** | ||
993 | * Update the message with information about the connection. | ||
994 | * | ||
995 | * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update | ||
996 | * @param ct a connection about which we should store information in @a cls | ||
997 | */ | ||
998 | static void | ||
999 | iter_connection (void *cls, | ||
1000 | struct CadetTConnection *ct) | ||
1001 | { | ||
1002 | struct GNUNET_CADET_LocalInfoTunnel *msg = cls; | ||
1003 | struct CadetConnection *cc = ct->cc; | ||
1004 | struct GNUNET_CADET_ConnectionTunnelIdentifier *h; | ||
1005 | |||
1006 | h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1]; | ||
1007 | h[msg->connections++] = *(GCC_get_id (cc)); | ||
1008 | } | ||
1009 | |||
1010 | |||
1011 | /** | ||
1012 | * Update the message with information about the channel. | ||
1013 | * | ||
1014 | * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update | ||
1015 | * @param ch a channel about which we should store information in @a cls | ||
1016 | */ | ||
1017 | static void | ||
1018 | iter_channel (void *cls, | ||
1019 | struct CadetChannel *ch) | ||
1020 | { | ||
1021 | struct GNUNET_CADET_LocalInfoTunnel *msg = cls; | ||
1022 | struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1]; | ||
1023 | struct GNUNET_CADET_ChannelTunnelNumber *chn | ||
1024 | = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections]; | ||
1025 | |||
1026 | chn[msg->channels++] = GCCH_get_id (ch); | ||
1027 | } | ||
1028 | |||
1029 | |||
1030 | /** | ||
1031 | * Handler for client's #GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL request. | ||
1032 | * | ||
1033 | * @param cls Identification of the client. | ||
1034 | * @param msg The actual message. | ||
1035 | */ | ||
1036 | static void | ||
1037 | handle_info_tunnel (void *cls, | ||
1038 | const struct GNUNET_CADET_LocalInfo *msg) | ||
1039 | { | ||
1040 | struct CadetClient *c = cls; | ||
1041 | struct GNUNET_MQ_Envelope *env; | ||
1042 | struct GNUNET_CADET_LocalInfoTunnel *resp; | ||
1043 | struct CadetTunnel *t; | ||
1044 | struct CadetPeer *p; | ||
1045 | unsigned int ch_n; | ||
1046 | unsigned int c_n; | ||
1047 | |||
1048 | p = GCP_get (&msg->peer, | ||
1049 | GNUNET_NO); | ||
1050 | t = GCP_get_tunnel (p, | ||
1051 | GNUNET_NO); | ||
1052 | if (NULL == t) | ||
1053 | { | ||
1054 | /* We don't know the tunnel */ | ||
1055 | struct GNUNET_MQ_Envelope *env; | ||
1056 | struct GNUNET_CADET_LocalInfoTunnel *warn; | ||
1057 | |||
1058 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1059 | "Tunnel to %s unknown\n", | ||
1060 | GNUNET_i2s_full (&msg->peer)); | ||
1061 | env = GNUNET_MQ_msg (warn, | ||
1062 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
1063 | warn->destination = msg->peer; | ||
1064 | GNUNET_MQ_send (c->mq, | ||
1065 | env); | ||
1066 | GNUNET_SERVICE_client_continue (c->client); | ||
1067 | return; | ||
1068 | } | ||
1069 | |||
1070 | /* Initialize context */ | ||
1071 | ch_n = GCT_count_channels (t); | ||
1072 | c_n = GCT_count_any_connections (t); | ||
1073 | env = GNUNET_MQ_msg_extra (resp, | ||
1074 | c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier) + | ||
1075 | ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber), | ||
1076 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
1077 | resp->destination = msg->peer; | ||
1078 | /* Do not reorder! #iter_channel needs counters in HBO! */ | ||
1079 | GCT_iterate_connections (t, | ||
1080 | &iter_connection, | ||
1081 | resp); | ||
1082 | GCT_iterate_channels (t, | ||
1083 | &iter_channel, | ||
1084 | resp); | ||
1085 | resp->connections = htonl (resp->connections); | ||
1086 | resp->channels = htonl (resp->channels); | ||
1087 | resp->cstate = htons (0); | ||
1088 | resp->estate = htons (GCT_get_estate (t)); | ||
1089 | GNUNET_MQ_send (c->mq, | ||
1090 | env); | ||
1091 | GNUNET_SERVICE_client_continue (c->client); | ||
1092 | } | ||
1093 | |||
1094 | |||
1095 | /** | ||
1096 | * Iterator over all peers to dump info for each peer. | ||
1097 | * | ||
1098 | * @param cls Closure (unused). | ||
1099 | * @param peer Peer ID (tunnel remote peer). | ||
1100 | * @param value Peer info. | ||
1101 | * | ||
1102 | * @return #GNUNET_YES, to keep iterating. | ||
1103 | */ | ||
1104 | static int | ||
1105 | show_peer_iterator (void *cls, | ||
1106 | const struct GNUNET_PeerIdentity *peer, | ||
1107 | void *value) | ||
1108 | { | ||
1109 | struct CadetPeer *p = value; | ||
1110 | struct CadetTunnel *t; | ||
1111 | |||
1112 | t = GCP_get_tunnel (p, | ||
1113 | GNUNET_NO); | ||
1114 | if (NULL != t) | ||
1115 | GCT_debug (t, | ||
1116 | GNUNET_ERROR_TYPE_ERROR); | ||
1117 | LOG (GNUNET_ERROR_TYPE_ERROR, "\n"); | ||
1118 | return GNUNET_YES; | ||
1119 | } | ||
1120 | |||
1121 | |||
1122 | /** | ||
1123 | * Handler for client's INFO_DUMP request. | ||
1124 | * | ||
1125 | * @param cls Identification of the client. | ||
1126 | * @param message The actual message. | ||
1127 | */ | ||
1128 | static void | ||
1129 | handle_info_dump (void *cls, | ||
1130 | const struct GNUNET_MessageHeader *message) | ||
1131 | { | ||
1132 | struct CadetClient *c = cls; | ||
1133 | |||
1134 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1135 | "Received dump info request from client %u\n", | ||
1136 | c->id); | ||
1137 | |||
1138 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1139 | "*************************** DUMP START ***************************\n"); | ||
1140 | for (struct CadetClient *ci = clients_head; | ||
1141 | NULL != ci; | ||
1142 | ci = ci->next) | ||
1143 | { | ||
1144 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1145 | "Client %u (%p), handle: %p, ports: %u, channels: %u\n", | ||
1146 | ci->id, | ||
1147 | ci, | ||
1148 | ci->client, | ||
1149 | (NULL != c->ports) | ||
1150 | ? GNUNET_CONTAINER_multihashmap_size (ci->ports) | ||
1151 | : 0, | ||
1152 | GNUNET_CONTAINER_multihashmap32_size (ci->channels)); | ||
1153 | } | ||
1154 | LOG (GNUNET_ERROR_TYPE_ERROR, "***************************\n"); | ||
1155 | GCP_iterate_all (&show_peer_iterator, | ||
1156 | NULL); | ||
1157 | |||
1158 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1159 | "**************************** DUMP END ****************************\n"); | ||
1160 | |||
1161 | GNUNET_SERVICE_client_continue (c->client); | ||
1162 | } | ||
1163 | |||
1164 | |||
1165 | |||
1166 | /** | ||
1167 | * Callback called when a client connects to the service. | ||
1168 | * | ||
1169 | * @param cls closure for the service | ||
1170 | * @param client the new client that connected to the service | ||
1171 | * @param mq the message queue used to send messages to the client | ||
1172 | * @return @a c | ||
1173 | */ | ||
1174 | static void * | ||
1175 | client_connect_cb (void *cls, | ||
1176 | struct GNUNET_SERVICE_Client *client, | ||
1177 | struct GNUNET_MQ_Handle *mq) | ||
1178 | { | ||
1179 | struct CadetClient *c; | ||
1180 | |||
1181 | c = GNUNET_new (struct CadetClient); | ||
1182 | c->client = client; | ||
1183 | c->mq = mq; | ||
1184 | c->id = next_client_id++; /* overflow not important: just for debug */ | ||
1185 | c->channels | ||
1186 | = GNUNET_CONTAINER_multihashmap32_create (32); | ||
1187 | GNUNET_CONTAINER_DLL_insert (clients_head, | ||
1188 | clients_tail, | ||
1189 | c); | ||
1190 | GNUNET_STATISTICS_update (stats, | ||
1191 | "# clients", | ||
1192 | +1, | ||
1193 | GNUNET_NO); | ||
1194 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1195 | "%s connected\n", | ||
1196 | GSC_2s (c)); | ||
1197 | return c; | ||
1198 | } | ||
1199 | |||
1200 | |||
1201 | /** | ||
1202 | * A channel was destroyed by the other peer. Tell our client. | ||
1203 | * | ||
1204 | * @param c client that lost a channel | ||
1205 | * @param ccn channel identification number for the client | ||
1206 | * @param ch the channel object | ||
1207 | */ | ||
1208 | void | ||
1209 | GSC_handle_remote_channel_destroy (struct CadetClient *c, | ||
1210 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
1211 | struct CadetChannel *ch) | ||
1212 | { | ||
1213 | struct GNUNET_MQ_Envelope *env; | ||
1214 | struct GNUNET_CADET_LocalChannelDestroyMessage *tdm; | ||
1215 | |||
1216 | env = GNUNET_MQ_msg (tdm, | ||
1217 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
1218 | tdm->ccn = ccn; | ||
1219 | GSC_send_to_client (c, | ||
1220 | env); | ||
1221 | GNUNET_assert (GNUNET_YES == | ||
1222 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
1223 | ntohl (ccn.channel_of_client), | ||
1224 | ch)); | ||
1225 | } | ||
1226 | |||
1227 | |||
1228 | /** | ||
1229 | * A client that created a loose channel that was not bound to a port | ||
1230 | * disconnected, drop it from the #loose_channels list. | ||
1231 | * | ||
1232 | * @param h_port the hashed port the channel was trying to bind to | ||
1233 | * @param ch the channel that was lost | ||
1234 | */ | ||
1235 | void | ||
1236 | GSC_drop_loose_channel (const struct GNUNET_HashCode *h_port, | ||
1237 | struct CadetChannel *ch) | ||
1238 | { | ||
1239 | GNUNET_assert (GNUNET_YES == | ||
1240 | GNUNET_CONTAINER_multihashmap_remove (loose_channels, | ||
1241 | h_port, | ||
1242 | ch)); | ||
1243 | } | ||
1244 | |||
1245 | |||
1246 | /** | ||
1247 | * Iterator for deleting each channel whose client endpoint disconnected. | ||
1248 | * | ||
1249 | * @param cls Closure (client that has disconnected). | ||
1250 | * @param key The local channel id in host byte order | ||
1251 | * @param value The value stored at the key (channel to destroy). | ||
1252 | * @return #GNUNET_OK, keep iterating. | ||
1253 | */ | ||
1254 | static int | ||
1255 | channel_destroy_iterator (void *cls, | ||
1256 | uint32_t key, | ||
1257 | void *value) | ||
1258 | { | ||
1259 | struct CadetClient *c = cls; | ||
1260 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
1261 | struct CadetChannel *ch = value; | ||
1262 | |||
1263 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1264 | "Destroying %s, due to %s disconnecting.\n", | ||
1265 | GCCH_2s (ch), | ||
1266 | GSC_2s (c)); | ||
1267 | ccn.channel_of_client = htonl (key); | ||
1268 | GCCH_channel_local_destroy (ch, | ||
1269 | c, | ||
1270 | ccn); | ||
1271 | GNUNET_assert (GNUNET_YES == | ||
1272 | GNUNET_CONTAINER_multihashmap32_remove (c->channels, | ||
1273 | key, | ||
1274 | ch)); | ||
1275 | return GNUNET_OK; | ||
1276 | } | ||
1277 | |||
1278 | |||
1279 | /** | ||
1280 | * Remove client's ports from the global hashmap on disconnect. | ||
1281 | * | ||
1282 | * @param cls the `struct CadetClient` | ||
1283 | * @param port the port. | ||
1284 | * @param value the `struct OpenPort` to remove | ||
1285 | * @return #GNUNET_OK, keep iterating. | ||
1286 | */ | ||
1287 | static int | ||
1288 | client_release_ports (void *cls, | ||
1289 | const struct GNUNET_HashCode *port, | ||
1290 | void *value) | ||
1291 | { | ||
1292 | struct CadetClient *c = cls; | ||
1293 | struct OpenPort *op = value; | ||
1294 | |||
1295 | GNUNET_assert (c == op->c); | ||
1296 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1297 | "Closing port %s due to %s disconnect.\n", | ||
1298 | GNUNET_h2s (port), | ||
1299 | GSC_2s (c)); | ||
1300 | GNUNET_assert (GNUNET_YES == | ||
1301 | GNUNET_CONTAINER_multihashmap_remove (open_ports, | ||
1302 | &op->h_port, | ||
1303 | op)); | ||
1304 | GNUNET_assert (GNUNET_YES == | ||
1305 | GNUNET_CONTAINER_multihashmap_remove (c->ports, | ||
1306 | port, | ||
1307 | op)); | ||
1308 | GNUNET_free (op); | ||
1309 | return GNUNET_OK; | ||
1310 | } | ||
1311 | |||
1312 | |||
1313 | /** | ||
1314 | * Callback called when a client disconnected from the service | ||
1315 | * | ||
1316 | * @param cls closure for the service | ||
1317 | * @param client the client that disconnected | ||
1318 | * @param internal_cls should be equal to @a c | ||
1319 | */ | ||
1320 | static void | ||
1321 | client_disconnect_cb (void *cls, | ||
1322 | struct GNUNET_SERVICE_Client *client, | ||
1323 | void *internal_cls) | ||
1324 | { | ||
1325 | struct CadetClient *c = internal_cls; | ||
1326 | |||
1327 | GNUNET_assert (c->client == client); | ||
1328 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1329 | "%s is disconnecting.\n", | ||
1330 | GSC_2s (c)); | ||
1331 | if (NULL != c->channels) | ||
1332 | { | ||
1333 | GNUNET_CONTAINER_multihashmap32_iterate (c->channels, | ||
1334 | &channel_destroy_iterator, | ||
1335 | c); | ||
1336 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->channels)); | ||
1337 | GNUNET_CONTAINER_multihashmap32_destroy (c->channels); | ||
1338 | } | ||
1339 | if (NULL != c->ports) | ||
1340 | { | ||
1341 | GNUNET_CONTAINER_multihashmap_iterate (c->ports, | ||
1342 | &client_release_ports, | ||
1343 | c); | ||
1344 | GNUNET_CONTAINER_multihashmap_destroy (c->ports); | ||
1345 | } | ||
1346 | GNUNET_CONTAINER_DLL_remove (clients_head, | ||
1347 | clients_tail, | ||
1348 | c); | ||
1349 | GNUNET_STATISTICS_update (stats, | ||
1350 | "# clients", | ||
1351 | -1, | ||
1352 | GNUNET_NO); | ||
1353 | GNUNET_free (c); | ||
1354 | if ( (NULL == clients_head) && | ||
1355 | (GNUNET_YES == shutting_down) ) | ||
1356 | shutdown_rest (); | ||
1357 | } | ||
1358 | |||
1359 | |||
1360 | /** | ||
1361 | * Setup CADET internals. | ||
1362 | * | ||
1363 | * @param cls closure | ||
1364 | * @param server the initialized server | ||
1365 | * @param c configuration to use | ||
1366 | */ | ||
1367 | static void | ||
1368 | run (void *cls, | ||
1369 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
1370 | struct GNUNET_SERVICE_Handle *service) | ||
1371 | { | ||
1372 | cfg = c; | ||
1373 | if (GNUNET_OK != | ||
1374 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1375 | "CADET", | ||
1376 | "RATCHET_MESSAGES", | ||
1377 | &ratchet_messages)) | ||
1378 | { | ||
1379 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1380 | "CADET", | ||
1381 | "RATCHET_MESSAGES", | ||
1382 | "needs to be a number"); | ||
1383 | ratchet_messages = 64; | ||
1384 | } | ||
1385 | if (GNUNET_OK != | ||
1386 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1387 | "CADET", | ||
1388 | "RATCHET_TIME", | ||
1389 | &ratchet_time)) | ||
1390 | { | ||
1391 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1392 | "CADET", | ||
1393 | "RATCHET_TIME", | ||
1394 | "need delay value"); | ||
1395 | ratchet_time = GNUNET_TIME_UNIT_HOURS; | ||
1396 | } | ||
1397 | if (GNUNET_OK != | ||
1398 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1399 | "CADET", | ||
1400 | "REFRESH_CONNECTION_TIME", | ||
1401 | &keepalive_period)) | ||
1402 | { | ||
1403 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1404 | "CADET", | ||
1405 | "REFRESH_CONNECTION_TIME", | ||
1406 | "need delay value"); | ||
1407 | keepalive_period = GNUNET_TIME_UNIT_MINUTES; | ||
1408 | } | ||
1409 | if (GNUNET_OK != | ||
1410 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1411 | "CADET", | ||
1412 | "DROP_PERCENT", | ||
1413 | &drop_percent)) | ||
1414 | { | ||
1415 | drop_percent = 0; | ||
1416 | } | ||
1417 | else | ||
1418 | { | ||
1419 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1420 | LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n"); | ||
1421 | LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n"); | ||
1422 | LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n"); | ||
1423 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1424 | } | ||
1425 | my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c); | ||
1426 | if (NULL == my_private_key) | ||
1427 | { | ||
1428 | GNUNET_break (0); | ||
1429 | GNUNET_SCHEDULER_shutdown (); | ||
1430 | return; | ||
1431 | } | ||
1432 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, | ||
1433 | &my_full_id.public_key); | ||
1434 | stats = GNUNET_STATISTICS_create ("cadet", | ||
1435 | c); | ||
1436 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | ||
1437 | NULL); | ||
1438 | ats_ch = GNUNET_ATS_connectivity_init (c); | ||
1439 | /* FIXME: optimize code to allow GNUNET_YES here! */ | ||
1440 | open_ports = GNUNET_CONTAINER_multihashmap_create (16, | ||
1441 | GNUNET_NO); | ||
1442 | loose_channels = GNUNET_CONTAINER_multihashmap_create (16, | ||
1443 | GNUNET_NO); | ||
1444 | peers = GNUNET_CONTAINER_multipeermap_create (16, | ||
1445 | GNUNET_YES); | ||
1446 | connections = GNUNET_CONTAINER_multishortmap_create (256, | ||
1447 | GNUNET_YES); | ||
1448 | GCH_init (c); | ||
1449 | GCD_init (c); | ||
1450 | GCO_init (c); | ||
1451 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
1452 | "CADET started for peer %s\n", | ||
1453 | GNUNET_i2s (&my_full_id)); | ||
1454 | |||
1455 | } | ||
1456 | |||
1457 | |||
1458 | /** | ||
1459 | * Define "main" method using service macro. | ||
1460 | */ | ||
1461 | GNUNET_SERVICE_MAIN | ||
1462 | ("cadet", | ||
1463 | GNUNET_SERVICE_OPTION_NONE, | ||
1464 | &run, | ||
1465 | &client_connect_cb, | ||
1466 | &client_disconnect_cb, | ||
1467 | NULL, | ||
1468 | GNUNET_MQ_hd_fixed_size (port_open, | ||
1469 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN, | ||
1470 | struct GNUNET_CADET_PortMessage, | ||
1471 | NULL), | ||
1472 | GNUNET_MQ_hd_fixed_size (port_close, | ||
1473 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE, | ||
1474 | struct GNUNET_CADET_PortMessage, | ||
1475 | NULL), | ||
1476 | GNUNET_MQ_hd_fixed_size (channel_create, | ||
1477 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE, | ||
1478 | struct GNUNET_CADET_LocalChannelCreateMessage, | ||
1479 | NULL), | ||
1480 | GNUNET_MQ_hd_fixed_size (channel_destroy, | ||
1481 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY, | ||
1482 | struct GNUNET_CADET_LocalChannelDestroyMessage, | ||
1483 | NULL), | ||
1484 | GNUNET_MQ_hd_var_size (local_data, | ||
1485 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, | ||
1486 | struct GNUNET_CADET_LocalData, | ||
1487 | NULL), | ||
1488 | GNUNET_MQ_hd_fixed_size (local_ack, | ||
1489 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, | ||
1490 | struct GNUNET_CADET_LocalAck, | ||
1491 | NULL), | ||
1492 | GNUNET_MQ_hd_fixed_size (get_peers, | ||
1493 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, | ||
1494 | struct GNUNET_MessageHeader, | ||
1495 | NULL), | ||
1496 | GNUNET_MQ_hd_fixed_size (show_peer, | ||
1497 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER, | ||
1498 | struct GNUNET_CADET_LocalInfo, | ||
1499 | NULL), | ||
1500 | GNUNET_MQ_hd_fixed_size (info_tunnels, | ||
1501 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS, | ||
1502 | struct GNUNET_MessageHeader, | ||
1503 | NULL), | ||
1504 | GNUNET_MQ_hd_fixed_size (info_tunnel, | ||
1505 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL, | ||
1506 | struct GNUNET_CADET_LocalInfo, | ||
1507 | NULL), | ||
1508 | GNUNET_MQ_hd_fixed_size (info_dump, | ||
1509 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP, | ||
1510 | struct GNUNET_MessageHeader, | ||
1511 | NULL), | ||
1512 | GNUNET_MQ_handler_end ()); | ||
1513 | |||
1514 | /* end of gnunet-service-cadet-new.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new.h b/src/cadet/gnunet-service-cadet.h index 4a76c578b..162867823 100644 --- a/src/cadet/gnunet-service-cadet-new.h +++ b/src/cadet/gnunet-service-cadet.h | |||
@@ -20,7 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * @file cadet/gnunet-service-cadet-new.h | 23 | * @file cadet/gnunet-service-cadet.h |
24 | * @brief Information we track per peer. | 24 | * @brief Information we track per peer. |
25 | * @author Bartlomiej Polot | 25 | * @author Bartlomiej Polot |
26 | * @author Christian Grothoff | 26 | * @author Christian Grothoff |
@@ -29,7 +29,6 @@ | |||
29 | #define GNUNET_SERVICE_CADET_H | 29 | #define GNUNET_SERVICE_CADET_H |
30 | 30 | ||
31 | #include "gnunet_util_lib.h" | 31 | #include "gnunet_util_lib.h" |
32 | #define NEW_CADET 1 | ||
33 | #include "cadet_protocol.h" | 32 | #include "cadet_protocol.h" |
34 | 33 | ||
35 | /** | 34 | /** |
@@ -146,6 +145,30 @@ struct CadetTConnection | |||
146 | 145 | ||
147 | 146 | ||
148 | /** | 147 | /** |
148 | * Port opened by a client. | ||
149 | */ | ||
150 | struct OpenPort | ||
151 | { | ||
152 | |||
153 | /** | ||
154 | * Client that opened the port. | ||
155 | */ | ||
156 | struct CadetClient *c; | ||
157 | |||
158 | /** | ||
159 | * Port number. | ||
160 | */ | ||
161 | struct GNUNET_HashCode port; | ||
162 | |||
163 | /** | ||
164 | * Port hashed with our PID (matches incoming OPEN messages). | ||
165 | */ | ||
166 | struct GNUNET_HashCode h_port; | ||
167 | |||
168 | }; | ||
169 | |||
170 | |||
171 | /** | ||
149 | * Active path through the network (used by a tunnel). There may | 172 | * Active path through the network (used by a tunnel). There may |
150 | * be at most one connection per path. | 173 | * be at most one connection per path. |
151 | */ | 174 | */ |
@@ -193,7 +216,8 @@ extern struct GNUNET_PeerIdentity my_full_id; | |||
193 | extern struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | 216 | extern struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; |
194 | 217 | ||
195 | /** | 218 | /** |
196 | * All ports clients of this peer have opened. | 219 | * All ports clients of this peer have opened. Maps from |
220 | * a hashed port to a `struct OpenPort`. | ||
197 | */ | 221 | */ |
198 | extern struct GNUNET_CONTAINER_MultiHashMap *open_ports; | 222 | extern struct GNUNET_CONTAINER_MultiHashMap *open_ports; |
199 | 223 | ||
@@ -206,7 +230,7 @@ extern struct GNUNET_CONTAINER_MultiShortmap *connections; | |||
206 | /** | 230 | /** |
207 | * Map from ports to channels where the ports were closed at the | 231 | * Map from ports to channels where the ports were closed at the |
208 | * time we got the inbound connection. | 232 | * time we got the inbound connection. |
209 | * Indexed by port, contains `struct CadetChannel`. | 233 | * Indexed by h_port, contains `struct CadetChannel`. |
210 | */ | 234 | */ |
211 | extern struct GNUNET_CONTAINER_MultiHashMap *loose_channels; | 235 | extern struct GNUNET_CONTAINER_MultiHashMap *loose_channels; |
212 | 236 | ||
@@ -226,10 +250,20 @@ extern unsigned long long ratchet_messages; | |||
226 | extern struct GNUNET_TIME_Relative ratchet_time; | 250 | extern struct GNUNET_TIME_Relative ratchet_time; |
227 | 251 | ||
228 | /** | 252 | /** |
253 | * How frequently do we send KEEPALIVE messages on idle connections? | ||
254 | */ | ||
255 | extern struct GNUNET_TIME_Relative keepalive_period; | ||
256 | |||
257 | /** | ||
229 | * Signal that shutdown is happening: prevent recovery measures. | 258 | * Signal that shutdown is happening: prevent recovery measures. |
230 | */ | 259 | */ |
231 | extern int shutting_down; | 260 | extern int shutting_down; |
232 | 261 | ||
262 | /** | ||
263 | * Set to non-zero values to create random drops to test retransmissions. | ||
264 | */ | ||
265 | extern unsigned long long drop_percent; | ||
266 | |||
233 | 267 | ||
234 | /** | 268 | /** |
235 | * Send a message to a client. | 269 | * Send a message to a client. |
@@ -254,6 +288,17 @@ GSC_handle_remote_channel_destroy (struct CadetClient *c, | |||
254 | struct GNUNET_CADET_ClientChannelNumber ccn, | 288 | struct GNUNET_CADET_ClientChannelNumber ccn, |
255 | struct CadetChannel *ch); | 289 | struct CadetChannel *ch); |
256 | 290 | ||
291 | /** | ||
292 | * A client that created a loose channel that was not bound to a port | ||
293 | * disconnected, drop it from the #loose_channels list. | ||
294 | * | ||
295 | * @param h_port the hashed port the channel was trying to bind to | ||
296 | * @param ch the channel that was lost | ||
297 | */ | ||
298 | void | ||
299 | GSC_drop_loose_channel (const struct GNUNET_HashCode *h_port, | ||
300 | struct CadetChannel *ch); | ||
301 | |||
257 | 302 | ||
258 | /** | 303 | /** |
259 | * Bind incoming channel to this client, and notify client | 304 | * Bind incoming channel to this client, and notify client |
diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c index 7b7c6e57c..739b68228 100644 --- a/src/cadet/gnunet-service-cadet_channel.c +++ b/src/cadet/gnunet-service-cadet_channel.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2013 GNUnet e.V. | 3 | Copyright (C) 2001-2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -17,31 +17,63 @@ | |||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. | 18 | Boston, MA 02110-1301, USA. |
19 | */ | 19 | */ |
20 | 20 | /** | |
21 | 21 | * @file cadet/gnunet-service-cadet_channel.c | |
22 | * @brief logical links between CADET clients | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | * | ||
26 | * TODO: | ||
27 | * - Congestion/flow control: | ||
28 | * + estimate max bandwidth using bursts and use to for CONGESTION CONTROL! | ||
29 | * (and figure out how/where to use this!) | ||
30 | * + figure out flow control without ACKs (unreliable traffic!) | ||
31 | * - revisit handling of 'unbuffered' traffic! | ||
32 | * (need to push down through tunnel into connection selection) | ||
33 | * - revisit handling of 'buffered' traffic: 4 is a rather small buffer; maybe | ||
34 | * reserve more bits in 'options' to allow for buffer size control? | ||
35 | */ | ||
22 | #include "platform.h" | 36 | #include "platform.h" |
23 | #include "gnunet_util_lib.h" | 37 | #include "cadet.h" |
24 | |||
25 | #include "gnunet_statistics_service.h" | 38 | #include "gnunet_statistics_service.h" |
39 | #include "gnunet-service-cadet_channel.h" | ||
40 | #include "gnunet-service-cadet_connection.h" | ||
41 | #include "gnunet-service-cadet_tunnels.h" | ||
42 | #include "gnunet-service-cadet_paths.h" | ||
26 | 43 | ||
27 | #include "cadet.h" | 44 | #define LOG(level,...) GNUNET_log_from (level,"cadet-chn",__VA_ARGS__) |
28 | #include "cadet_protocol.h" | ||
29 | 45 | ||
30 | #include "gnunet-service-cadet_channel.h" | 46 | /** |
31 | #include "gnunet-service-cadet_local.h" | 47 | * How long do we initially wait before retransmitting? |
32 | #include "gnunet-service-cadet_tunnel.h" | 48 | */ |
33 | #include "gnunet-service-cadet_peer.h" | 49 | #define CADET_INITIAL_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250) |
34 | 50 | ||
35 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-chn",__VA_ARGS__) | 51 | /** |
36 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__) | 52 | * How long do we wait before dropping state about incoming |
53 | * connection to closed port? | ||
54 | */ | ||
55 | #define TIMEOUT_CLOSED_PORT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30) | ||
37 | 56 | ||
38 | #define CADET_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(\ | 57 | /** |
39 | GNUNET_TIME_UNIT_MILLISECONDS, 250) | 58 | * How long do we wait at least before retransmitting ever? |
40 | #define CADET_RETRANSMIT_MARGIN 4 | 59 | */ |
60 | #define MIN_RTT_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 75) | ||
61 | |||
62 | /** | ||
63 | * Maximum message ID into the future we accept for out-of-order messages. | ||
64 | * If the message is more than this into the future, we drop it. This is | ||
65 | * important both to detect values that are actually in the past, as well | ||
66 | * as to limit adversarially triggerable memory consumption. | ||
67 | * | ||
68 | * Note that right now we have "max_pending_messages = 4" hard-coded in | ||
69 | * the logic below, so a value of 4 would suffice here. But we plan to | ||
70 | * allow larger windows in the future... | ||
71 | */ | ||
72 | #define MAX_OUT_OF_ORDER_DISTANCE 1024 | ||
41 | 73 | ||
42 | 74 | ||
43 | /** | 75 | /** |
44 | * All the states a connection can be in. | 76 | * All the states a channel can be in. |
45 | */ | 77 | */ |
46 | enum CadetChannelState | 78 | enum CadetChannelState |
47 | { | 79 | { |
@@ -51,9 +83,15 @@ enum CadetChannelState | |||
51 | CADET_CHANNEL_NEW, | 83 | CADET_CHANNEL_NEW, |
52 | 84 | ||
53 | /** | 85 | /** |
54 | * Connection create message sent, waiting for ACK. | 86 | * Channel is to a port that is not open, we're waiting for the |
87 | * port to be opened. | ||
88 | */ | ||
89 | CADET_CHANNEL_LOOSE, | ||
90 | |||
91 | /** | ||
92 | * CHANNEL_OPEN message sent, waiting for CHANNEL_OPEN_ACK. | ||
55 | */ | 93 | */ |
56 | CADET_CHANNEL_SENT, | 94 | CADET_CHANNEL_OPEN_SENT, |
57 | 95 | ||
58 | /** | 96 | /** |
59 | * Connection confirmed, ready to carry traffic. | 97 | * Connection confirmed, ready to carry traffic. |
@@ -63,138 +101,144 @@ enum CadetChannelState | |||
63 | 101 | ||
64 | 102 | ||
65 | /** | 103 | /** |
66 | * Info holder for channel messages in queues. | 104 | * Info needed to retry a message in case it gets lost. |
105 | * Note that we DO use this structure also for unreliable | ||
106 | * messages. | ||
67 | */ | 107 | */ |
68 | struct CadetChannelQueue | 108 | struct CadetReliableMessage |
69 | { | 109 | { |
70 | /** | 110 | /** |
71 | * Tunnel Queue. | 111 | * Double linked list, FIFO style |
72 | */ | 112 | */ |
73 | struct CadetTunnelQueue *tq; | 113 | struct CadetReliableMessage *next; |
74 | 114 | ||
75 | /** | 115 | /** |
76 | * Message type (DATA/DATA_ACK) | 116 | * Double linked list, FIFO style |
77 | */ | 117 | */ |
78 | uint16_t type; | 118 | struct CadetReliableMessage *prev; |
79 | 119 | ||
80 | /** | 120 | /** |
81 | * Message copy (for DATAs, to start retransmission timer) | 121 | * Which channel is this message in? |
82 | */ | 122 | */ |
83 | struct CadetReliableMessage *copy; | 123 | struct CadetChannel *ch; |
84 | 124 | ||
85 | /** | 125 | /** |
86 | * Reliability (for DATA_ACKs, to access rel->ack_q) | 126 | * Entry in the tunnels queue for this message, NULL if it has left |
127 | * the tunnel. Used to cancel transmission in case we receive an | ||
128 | * ACK in time. | ||
87 | */ | 129 | */ |
88 | struct CadetChannelReliability *rel; | 130 | struct CadetTunnelQueueEntry *qe; |
89 | }; | ||
90 | |||
91 | 131 | ||
92 | /** | ||
93 | * Info needed to retry a message in case it gets lost. | ||
94 | */ | ||
95 | struct CadetReliableMessage | ||
96 | { | ||
97 | /** | 132 | /** |
98 | * Double linked list, FIFO style | 133 | * Data message we are trying to send. |
99 | */ | 134 | */ |
100 | struct CadetReliableMessage *next; | 135 | struct GNUNET_CADET_ChannelAppDataMessage *data_message; |
101 | struct CadetReliableMessage *prev; | ||
102 | 136 | ||
103 | /** | 137 | /** |
104 | * Type of message (payload, channel management). | 138 | * How soon should we retry if we fail to get an ACK? |
139 | * Messages in the queue are sorted by this value. | ||
105 | */ | 140 | */ |
106 | int16_t type; | 141 | struct GNUNET_TIME_Absolute next_retry; |
107 | 142 | ||
108 | /** | 143 | /** |
109 | * Tunnel Reliability queue this message is in. | 144 | * How long do we wait for an ACK after transmission? |
145 | * Use for the back-off calculation. | ||
110 | */ | 146 | */ |
111 | struct CadetChannelReliability *rel; | 147 | struct GNUNET_TIME_Relative retry_delay; |
112 | 148 | ||
113 | /** | 149 | /** |
114 | * ID of the message (ACK needed to free) | 150 | * Time when we first successfully transmitted the message |
151 | * (that is, set @e num_transmissions to 1). | ||
115 | */ | 152 | */ |
116 | uint32_t mid; | 153 | struct GNUNET_TIME_Absolute first_transmission_time; |
117 | 154 | ||
118 | /** | 155 | /** |
119 | * Tunnel Queue. | 156 | * Identifier of the connection that this message took when it |
157 | * was first transmitted. Only useful if @e num_transmissions is 1. | ||
120 | */ | 158 | */ |
121 | struct CadetChannelQueue *chq; | 159 | struct GNUNET_CADET_ConnectionTunnelIdentifier connection_taken; |
122 | 160 | ||
123 | /** | 161 | /** |
124 | * When was this message issued (to calculate ACK delay) | 162 | * How often was this message transmitted? #GNUNET_SYSERR if there |
163 | * was an error transmitting the message, #GNUNET_NO if it was not | ||
164 | * yet transmitted ever, otherwise the number of (re) transmissions. | ||
125 | */ | 165 | */ |
126 | struct GNUNET_TIME_Absolute timestamp; | 166 | int num_transmissions; |
127 | 167 | ||
128 | /* struct GNUNET_CADET_ChannelAppDataMessage with payload */ | ||
129 | }; | 168 | }; |
130 | 169 | ||
131 | 170 | ||
132 | /** | 171 | /** |
133 | * Info about the traffic state for a client in a channel. | 172 | * List of received out-of-order data messages. |
134 | */ | 173 | */ |
135 | struct CadetChannelReliability | 174 | struct CadetOutOfOrderMessage |
136 | { | 175 | { |
137 | /** | 176 | /** |
138 | * Channel this is about. | 177 | * Double linked list, FIFO style |
139 | */ | 178 | */ |
140 | struct CadetChannel *ch; | 179 | struct CadetOutOfOrderMessage *next; |
141 | 180 | ||
142 | /** | 181 | /** |
143 | * DLL of messages sent and not yet ACK'd. | 182 | * Double linked list, FIFO style |
144 | */ | 183 | */ |
145 | struct CadetReliableMessage *head_sent; | 184 | struct CadetOutOfOrderMessage *prev; |
146 | struct CadetReliableMessage *tail_sent; | ||
147 | 185 | ||
148 | /** | 186 | /** |
149 | * DLL of messages received out of order. | 187 | * ID of the message (messages up to this point needed |
188 | * before we give this one to the client). | ||
150 | */ | 189 | */ |
151 | struct CadetReliableMessage *head_recv; | 190 | struct ChannelMessageIdentifier mid; |
152 | struct CadetReliableMessage *tail_recv; | ||
153 | 191 | ||
154 | /** | 192 | /** |
155 | * Messages received. | 193 | * The envelope with the payload of the out-of-order message |
156 | */ | 194 | */ |
157 | unsigned int n_recv; | 195 | struct GNUNET_MQ_Envelope *env; |
158 | 196 | ||
159 | /** | 197 | }; |
160 | * Next MID to use for outgoing traffic. | ||
161 | */ | ||
162 | uint32_t mid_send; | ||
163 | 198 | ||
164 | /** | ||
165 | * Next MID expected for incoming traffic. | ||
166 | */ | ||
167 | uint32_t mid_recv; | ||
168 | 199 | ||
200 | /** | ||
201 | * Client endpoint of a `struct CadetChannel`. A channel may be a | ||
202 | * loopback channel, in which case it has two of these endpoints. | ||
203 | * Note that flow control also is required in both directions. | ||
204 | */ | ||
205 | struct CadetChannelClient | ||
206 | { | ||
169 | /** | 207 | /** |
170 | * Handle for queued unique data CREATE, DATA_ACK. | 208 | * Client handle. Not by itself sufficient to designate |
209 | * the client endpoint, as the same client handle may | ||
210 | * be used for both the owner and the destination, and | ||
211 | * we thus also need the channel ID to identify the client. | ||
171 | */ | 212 | */ |
172 | struct CadetChannelQueue *uniq; | 213 | struct CadetClient *c; |
173 | 214 | ||
174 | /** | 215 | /** |
175 | * Can we send data to the client? | 216 | * Head of DLL of messages received out of order or while client was unready. |
176 | */ | 217 | */ |
177 | int client_ready; | 218 | struct CadetOutOfOrderMessage *head_recv; |
178 | 219 | ||
179 | /** | 220 | /** |
180 | * Can the client send data to us? | 221 | * Tail DLL of messages received out of order or while client was unready. |
181 | */ | 222 | */ |
182 | int client_allowed; | 223 | struct CadetOutOfOrderMessage *tail_recv; |
183 | 224 | ||
184 | /** | 225 | /** |
185 | * Task to resend/poll in case no ACK is received. | 226 | * Local tunnel number for this client. |
227 | * (if owner >= #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI, | ||
228 | * otherwise < #GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
186 | */ | 229 | */ |
187 | struct GNUNET_SCHEDULER_Task * retry_task; | 230 | struct GNUNET_CADET_ClientChannelNumber ccn; |
188 | 231 | ||
189 | /** | 232 | /** |
190 | * Counter for exponential backoff. | 233 | * Number of entries currently in @a head_recv DLL. |
191 | */ | 234 | */ |
192 | struct GNUNET_TIME_Relative retry_timer; | 235 | unsigned int num_recv; |
193 | 236 | ||
194 | /** | 237 | /** |
195 | * How long does it usually take to get an ACK. | 238 | * Can we send data to the client? |
196 | */ | 239 | */ |
197 | struct GNUNET_TIME_Relative expected_delay; | 240 | int client_ready; |
241 | |||
198 | }; | 242 | }; |
199 | 243 | ||
200 | 244 | ||
@@ -209,41 +253,44 @@ struct CadetChannel | |||
209 | struct CadetTunnel *t; | 253 | struct CadetTunnel *t; |
210 | 254 | ||
211 | /** | 255 | /** |
212 | * Destination port of the channel. | 256 | * Client owner of the tunnel, if any. |
257 | * (Used if this channel represends the initiating end of the tunnel.) | ||
213 | */ | 258 | */ |
214 | struct GNUNET_HashCode port; | 259 | struct CadetChannelClient *owner; |
215 | 260 | ||
216 | /** | 261 | /** |
217 | * Global channel number ( < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | 262 | * Client destination of the tunnel, if any. |
263 | * (Used if this channel represents the listening end of the tunnel.) | ||
218 | */ | 264 | */ |
219 | struct GNUNET_CADET_ChannelTunnelNumber gid; | 265 | struct CadetChannelClient *dest; |
220 | 266 | ||
221 | /** | 267 | /** |
222 | * Local tunnel number for root (owner) client. | 268 | * Last entry in the tunnel's queue relating to control messages |
223 | * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 ) | 269 | * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or |
270 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel | ||
271 | * transmission in case we receive updated information. | ||
224 | */ | 272 | */ |
225 | struct GNUNET_CADET_ClientChannelNumber lid_root; | 273 | struct CadetTunnelQueueEntry *last_control_qe; |
226 | 274 | ||
227 | /** | 275 | /** |
228 | * Local tunnel number for local destination clients (incoming number) | 276 | * Head of DLL of messages sent and not yet ACK'd. |
229 | * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV or 0). | ||
230 | */ | 277 | */ |
231 | struct GNUNET_CADET_ClientChannelNumber lid_dest; | 278 | struct CadetReliableMessage *head_sent; |
232 | 279 | ||
233 | /** | 280 | /** |
234 | * Channel state. | 281 | * Tail of DLL of messages sent and not yet ACK'd. |
235 | */ | 282 | */ |
236 | enum CadetChannelState state; | 283 | struct CadetReliableMessage *tail_sent; |
237 | 284 | ||
238 | /** | 285 | /** |
239 | * Is the tunnel bufferless (minimum latency)? | 286 | * Task to resend/poll in case no ACK is received. |
240 | */ | 287 | */ |
241 | int nobuffer; | 288 | struct GNUNET_SCHEDULER_Task *retry_control_task; |
242 | 289 | ||
243 | /** | 290 | /** |
244 | * Is the tunnel reliable? | 291 | * Task to resend/poll in case no ACK is received. |
245 | */ | 292 | */ |
246 | int reliable; | 293 | struct GNUNET_SCHEDULER_Task *retry_data_task; |
247 | 294 | ||
248 | /** | 295 | /** |
249 | * Last time the channel was used | 296 | * Last time the channel was used |
@@ -251,21 +298,34 @@ struct CadetChannel | |||
251 | struct GNUNET_TIME_Absolute timestamp; | 298 | struct GNUNET_TIME_Absolute timestamp; |
252 | 299 | ||
253 | /** | 300 | /** |
254 | * Client owner of the tunnel, if any | 301 | * Destination port of the channel. |
255 | */ | 302 | */ |
256 | struct CadetClient *root; | 303 | struct GNUNET_HashCode port; |
257 | 304 | ||
258 | /** | 305 | /** |
259 | * Client destination of the tunnel, if any. | 306 | * Hash'ed port of the channel with initiator and destination PID. |
260 | */ | 307 | */ |
261 | struct CadetClient *dest; | 308 | struct GNUNET_HashCode h_port; |
262 | 309 | ||
263 | /** | 310 | /** |
264 | * Flag to signal the destruction of the channel. | 311 | * Counter for exponential backoff. |
265 | * If this is set to #GNUNET_YES the channel will be destroyed | ||
266 | * when the queue is empty. | ||
267 | */ | 312 | */ |
268 | int destroy; | 313 | struct GNUNET_TIME_Relative retry_time; |
314 | |||
315 | /** | ||
316 | * Bitfield of already-received messages past @e mid_recv. | ||
317 | */ | ||
318 | uint64_t mid_futures; | ||
319 | |||
320 | /** | ||
321 | * Next MID expected for incoming traffic. | ||
322 | */ | ||
323 | struct ChannelMessageIdentifier mid_recv; | ||
324 | |||
325 | /** | ||
326 | * Next MID to use for outgoing traffic. | ||
327 | */ | ||
328 | struct ChannelMessageIdentifier mid_send; | ||
269 | 329 | ||
270 | /** | 330 | /** |
271 | * Total (reliable) messages pending ACK for this channel. | 331 | * Total (reliable) messages pending ACK for this channel. |
@@ -273,2290 +333,1763 @@ struct CadetChannel | |||
273 | unsigned int pending_messages; | 333 | unsigned int pending_messages; |
274 | 334 | ||
275 | /** | 335 | /** |
276 | * Reliability data. | 336 | * Maximum (reliable) messages pending ACK for this channel |
277 | * Only present (non-NULL) at the owner of a tunnel. | 337 | * before we throttle the client. |
278 | */ | 338 | */ |
279 | struct CadetChannelReliability *root_rel; | 339 | unsigned int max_pending_messages; |
280 | 340 | ||
281 | /** | 341 | /** |
282 | * Reliability data. | 342 | * Number identifying this channel in its tunnel. |
283 | * Only present (non-NULL) at the destination of a tunnel. | ||
284 | */ | 343 | */ |
285 | struct CadetChannelReliability *dest_rel; | 344 | struct GNUNET_CADET_ChannelTunnelNumber ctn; |
286 | 345 | ||
287 | }; | 346 | /** |
347 | * Channel state. | ||
348 | */ | ||
349 | enum CadetChannelState state; | ||
350 | |||
351 | /** | ||
352 | * Count how many ACKs we skipped, used to prevent long | ||
353 | * sequences of ACK skipping. | ||
354 | */ | ||
355 | unsigned int skip_ack_series; | ||
288 | 356 | ||
357 | /** | ||
358 | * Is the tunnel bufferless (minimum latency)? | ||
359 | */ | ||
360 | int nobuffer; | ||
289 | 361 | ||
290 | /******************************************************************************/ | 362 | /** |
291 | /******************************* GLOBALS ***********************************/ | 363 | * Is the tunnel reliable? |
292 | /******************************************************************************/ | 364 | */ |
365 | int reliable; | ||
293 | 366 | ||
294 | /** | 367 | /** |
295 | * Global handle to the statistics service. | 368 | * Is the tunnel out-of-order? |
296 | */ | 369 | */ |
297 | extern struct GNUNET_STATISTICS_Handle *stats; | 370 | int out_of_order; |
298 | 371 | ||
299 | /** | 372 | /** |
300 | * Local peer own ID (memory efficient handle). | 373 | * Is this channel a loopback channel, where the destination is us again? |
301 | */ | 374 | */ |
302 | extern GNUNET_PEER_Id myid; | 375 | int is_loopback; |
303 | 376 | ||
377 | /** | ||
378 | * Flag to signal the destruction of the channel. If this is set to | ||
379 | * #GNUNET_YES the channel will be destroyed once the queue is | ||
380 | * empty. | ||
381 | */ | ||
382 | int destroy; | ||
304 | 383 | ||
305 | /******************************************************************************/ | 384 | }; |
306 | /******************************** STATIC ***********************************/ | ||
307 | /******************************************************************************/ | ||
308 | 385 | ||
309 | 386 | ||
310 | /** | 387 | /** |
311 | * Destroy a reliable message after it has been acknowledged, either by | 388 | * Get the static string for identification of the channel. |
312 | * direct mid ACK or bitfield. Updates the appropriate data structures and | ||
313 | * timers and frees all memory. | ||
314 | * | 389 | * |
315 | * @param copy Message that is no longer needed: remote peer got it. | 390 | * @param ch Channel. |
316 | * @param update_time Is the timing information relevant? | ||
317 | * If this message is ACK in a batch the timing information | ||
318 | * is skewed by the retransmission, count only for the | ||
319 | * retransmitted message. | ||
320 | * | 391 | * |
321 | * @return #GNUNET_YES if channel was destroyed as a result of the call, | 392 | * @return Static string with the channel IDs. |
322 | * #GNUNET_NO otherwise. | ||
323 | */ | 393 | */ |
324 | static int | 394 | const char * |
325 | rel_message_free (struct CadetReliableMessage *copy, int update_time); | 395 | GCCH_2s (const struct CadetChannel *ch) |
396 | { | ||
397 | static char buf[128]; | ||
398 | |||
399 | GNUNET_snprintf (buf, | ||
400 | sizeof (buf), | ||
401 | "Channel %s:%s ctn:%X(%X/%X)", | ||
402 | (GNUNET_YES == ch->is_loopback) | ||
403 | ? "loopback" | ||
404 | : GNUNET_i2s (GCP_get_id (GCT_get_destination (ch->t))), | ||
405 | GNUNET_h2s (&ch->port), | ||
406 | ch->ctn, | ||
407 | (NULL == ch->owner) ? 0 : ntohl (ch->owner->ccn.channel_of_client), | ||
408 | (NULL == ch->dest) ? 0 : ntohl (ch->dest->ccn.channel_of_client)); | ||
409 | return buf; | ||
410 | } | ||
326 | 411 | ||
327 | /** | ||
328 | * send a channel create message. | ||
329 | * | ||
330 | * @param ch Channel for which to send. | ||
331 | */ | ||
332 | static void | ||
333 | send_create (struct CadetChannel *ch); | ||
334 | 412 | ||
335 | /** | 413 | /** |
336 | * Confirm we got a channel create, FWD ack. | 414 | * Hash the @a port and @a initiator and @a listener to |
415 | * calculate the "challenge" @a h_port we send to the other | ||
416 | * peer on #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN. | ||
337 | * | 417 | * |
338 | * @param ch The channel to confirm. | 418 | * @param[out] h_port set to the hash of @a port, @a initiator and @a listener |
339 | * @param fwd Should we send a FWD ACK? (going dest->root) | 419 | * @param port cadet port, as seen by CADET clients |
420 | * @param listener peer that is listining on @a port | ||
340 | */ | 421 | */ |
341 | static void | 422 | void |
342 | send_ack (struct CadetChannel *ch, int fwd); | 423 | GCCH_hash_port (struct GNUNET_HashCode *h_port, |
343 | 424 | const struct GNUNET_HashCode *port, | |
425 | const struct GNUNET_PeerIdentity *listener) | ||
426 | { | ||
427 | struct GNUNET_HashContext *hc; | ||
428 | |||
429 | hc = GNUNET_CRYPTO_hash_context_start (); | ||
430 | GNUNET_CRYPTO_hash_context_read (hc, | ||
431 | port, | ||
432 | sizeof (*port)); | ||
433 | GNUNET_CRYPTO_hash_context_read (hc, | ||
434 | listener, | ||
435 | sizeof (*listener)); | ||
436 | GNUNET_CRYPTO_hash_context_finish (hc, | ||
437 | h_port); | ||
438 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
439 | "Calculated port hash %s\n", | ||
440 | GNUNET_h2s (h_port)); | ||
441 | } | ||
344 | 442 | ||
345 | 443 | ||
346 | /** | 444 | /** |
347 | * Test if the channel is loopback: both root and dest are on the local peer. | 445 | * Get the channel's public ID. |
348 | * | 446 | * |
349 | * @param ch Channel to test. | 447 | * @param ch Channel. |
350 | * | 448 | * |
351 | * @return #GNUNET_YES if channel is loopback, #GNUNET_NO otherwise. | 449 | * @return ID used to identify the channel with the remote peer. |
352 | */ | 450 | */ |
353 | static int | 451 | struct GNUNET_CADET_ChannelTunnelNumber |
354 | is_loopback (const struct CadetChannel *ch) | 452 | GCCH_get_id (const struct CadetChannel *ch) |
355 | { | 453 | { |
356 | if (NULL != ch->t) | 454 | return ch->ctn; |
357 | return GCT_is_loopback (ch->t); | ||
358 | |||
359 | return (NULL != ch->root && NULL != ch->dest); | ||
360 | } | 455 | } |
361 | 456 | ||
362 | 457 | ||
363 | /** | 458 | /** |
364 | * Save a copy of the data message for later retransmission. | 459 | * Release memory associated with @a ccc |
365 | * | 460 | * |
366 | * @param msg Message to copy. | 461 | * @param ccc data structure to clean up |
367 | * @param mid Message ID. | ||
368 | * @param rel Reliability data for retransmission. | ||
369 | */ | 462 | */ |
370 | static struct CadetReliableMessage * | 463 | static void |
371 | copy_message (const struct GNUNET_CADET_ChannelAppDataMessage *msg, uint32_t mid, | 464 | free_channel_client (struct CadetChannelClient *ccc) |
372 | struct CadetChannelReliability *rel) | ||
373 | { | 465 | { |
374 | struct CadetReliableMessage *copy; | 466 | struct CadetOutOfOrderMessage *com; |
375 | uint16_t size; | ||
376 | |||
377 | size = ntohs (msg->header.size); | ||
378 | copy = GNUNET_malloc (sizeof (*copy) + size); | ||
379 | copy->mid = mid; | ||
380 | copy->rel = rel; | ||
381 | copy->type = GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA; | ||
382 | GNUNET_memcpy (©[1], msg, size); | ||
383 | 467 | ||
384 | return copy; | 468 | while (NULL != (com = ccc->head_recv)) |
469 | { | ||
470 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, | ||
471 | ccc->tail_recv, | ||
472 | com); | ||
473 | ccc->num_recv--; | ||
474 | GNUNET_MQ_discard (com->env); | ||
475 | GNUNET_free (com); | ||
476 | } | ||
477 | GNUNET_free (ccc); | ||
385 | } | 478 | } |
386 | 479 | ||
480 | |||
387 | /** | 481 | /** |
388 | * We have received a message out of order, or the client is not ready. | 482 | * Destroy the given channel. |
389 | * Buffer it until we receive an ACK from the client or the missing | ||
390 | * message from the channel. | ||
391 | * | 483 | * |
392 | * @param msg Message to buffer (MUST be of type CADET_DATA). | 484 | * @param ch channel to destroy |
393 | * @param rel Reliability data to the corresponding direction. | ||
394 | */ | 485 | */ |
395 | static void | 486 | static void |
396 | add_buffered_data (const struct GNUNET_CADET_ChannelAppDataMessage *msg, | 487 | channel_destroy (struct CadetChannel *ch) |
397 | struct CadetChannelReliability *rel) | ||
398 | { | 488 | { |
399 | struct CadetReliableMessage *copy; | 489 | struct CadetReliableMessage *crm; |
400 | struct CadetReliableMessage *prev; | ||
401 | uint32_t mid; | ||
402 | 490 | ||
403 | mid = ntohl (msg->mid); | 491 | while (NULL != (crm = ch->head_sent)) |
404 | |||
405 | LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data MID %u (%u)\n", | ||
406 | mid, rel->n_recv); | ||
407 | |||
408 | rel->n_recv++; | ||
409 | |||
410 | // FIXME do something better than O(n), although n < 64... | ||
411 | // FIXME start from the end (most messages are the latest ones) | ||
412 | for (prev = rel->head_recv; NULL != prev; prev = prev->next) | ||
413 | { | 492 | { |
414 | LOG (GNUNET_ERROR_TYPE_DEBUG, " prev %u\n", prev->mid); | 493 | GNUNET_assert (ch == crm->ch); |
415 | if (prev->mid == mid) | 494 | if (NULL != crm->qe) |
416 | { | 495 | { |
417 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already there!\n"); | 496 | GCT_send_cancel (crm->qe); |
418 | rel->n_recv--; | 497 | crm->qe = NULL; |
419 | return; | ||
420 | } | ||
421 | else if (GC_is_pid_bigger (prev->mid, mid)) | ||
422 | { | ||
423 | LOG (GNUNET_ERROR_TYPE_DEBUG, " bingo!\n"); | ||
424 | copy = copy_message (msg, mid, rel); | ||
425 | GNUNET_CONTAINER_DLL_insert_before (rel->head_recv, rel->tail_recv, | ||
426 | prev, copy); | ||
427 | return; | ||
428 | } | 498 | } |
499 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, | ||
500 | ch->tail_sent, | ||
501 | crm); | ||
502 | GNUNET_free (crm->data_message); | ||
503 | GNUNET_free (crm); | ||
429 | } | 504 | } |
430 | copy = copy_message (msg, mid, rel); | 505 | if (NULL != ch->owner) |
431 | LOG (GNUNET_ERROR_TYPE_DEBUG, " insert at tail! (now: %u)\n", rel->n_recv); | 506 | { |
432 | GNUNET_CONTAINER_DLL_insert_tail (rel->head_recv, rel->tail_recv, copy); | 507 | free_channel_client (ch->owner); |
433 | LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data END\n"); | 508 | ch->owner = NULL; |
509 | } | ||
510 | if (NULL != ch->dest) | ||
511 | { | ||
512 | free_channel_client (ch->dest); | ||
513 | ch->dest = NULL; | ||
514 | } | ||
515 | if (NULL != ch->last_control_qe) | ||
516 | { | ||
517 | GCT_send_cancel (ch->last_control_qe); | ||
518 | ch->last_control_qe = NULL; | ||
519 | } | ||
520 | if (NULL != ch->retry_data_task) | ||
521 | { | ||
522 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
523 | ch->retry_data_task = NULL; | ||
524 | } | ||
525 | if (NULL != ch->retry_control_task) | ||
526 | { | ||
527 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
528 | ch->retry_control_task = NULL; | ||
529 | } | ||
530 | if (GNUNET_NO == ch->is_loopback) | ||
531 | { | ||
532 | GCT_remove_channel (ch->t, | ||
533 | ch, | ||
534 | ch->ctn); | ||
535 | ch->t = NULL; | ||
536 | } | ||
537 | GNUNET_free (ch); | ||
434 | } | 538 | } |
435 | 539 | ||
436 | 540 | ||
437 | /** | 541 | /** |
438 | * Add a destination client to a channel, initializing all data structures | 542 | * Send a channel create message. |
439 | * in the channel and the client. | ||
440 | * | 543 | * |
441 | * @param ch Channel to which add the destination. | 544 | * @param cls Channel for which to send. |
442 | * @param c Client which to add to the channel. | ||
443 | */ | 545 | */ |
444 | static void | 546 | static void |
445 | add_destination (struct CadetChannel *ch, struct CadetClient *c) | 547 | send_channel_open (void *cls); |
446 | { | ||
447 | if (NULL != ch->dest) | ||
448 | { | ||
449 | GNUNET_break (0); | ||
450 | return; | ||
451 | } | ||
452 | |||
453 | /* Assign local id as destination */ | ||
454 | ch->lid_dest = GML_get_next_ccn (c); | ||
455 | |||
456 | /* Store in client's hashmap */ | ||
457 | GML_channel_add (c, ch->lid_dest, ch); | ||
458 | |||
459 | GNUNET_break (NULL == ch->dest_rel); | ||
460 | ch->dest_rel = GNUNET_new (struct CadetChannelReliability); | ||
461 | ch->dest_rel->ch = ch; | ||
462 | ch->dest_rel->expected_delay.rel_value_us = 0; | ||
463 | ch->dest_rel->retry_timer = CADET_RETRANSMIT_TIME; | ||
464 | |||
465 | ch->dest = c; | ||
466 | } | ||
467 | 548 | ||
468 | 549 | ||
469 | /** | 550 | /** |
470 | * Set options in a channel, extracted from a bit flag field. | 551 | * Function called once the tunnel confirms that we sent the |
552 | * create message. Delays for a bit until we retry. | ||
471 | * | 553 | * |
472 | * @param ch Channel to set options to. | 554 | * @param cls our `struct CadetChannel`. |
473 | * @param options Bit array in host byte order. | 555 | * @param cid identifier of the connection within the tunnel, NULL |
556 | * if transmission failed | ||
474 | */ | 557 | */ |
475 | static void | 558 | static void |
476 | channel_set_options (struct CadetChannel *ch, uint32_t options) | 559 | channel_open_sent_cb (void *cls, |
560 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
477 | { | 561 | { |
478 | ch->nobuffer = (options & GNUNET_CADET_OPTION_NOBUFFER) != 0 ? | 562 | struct CadetChannel *ch = cls; |
479 | GNUNET_YES : GNUNET_NO; | 563 | |
480 | ch->reliable = (options & GNUNET_CADET_OPTION_RELIABLE) != 0 ? | 564 | GNUNET_assert (NULL != ch->last_control_qe); |
481 | GNUNET_YES : GNUNET_NO; | 565 | ch->last_control_qe = NULL; |
566 | ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time); | ||
567 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
568 | "Sent CADET_CHANNEL_OPEN on %s, retrying in %s\n", | ||
569 | GCCH_2s (ch), | ||
570 | GNUNET_STRINGS_relative_time_to_string (ch->retry_time, | ||
571 | GNUNET_YES)); | ||
572 | ch->retry_control_task | ||
573 | = GNUNET_SCHEDULER_add_delayed (ch->retry_time, | ||
574 | &send_channel_open, | ||
575 | ch); | ||
482 | } | 576 | } |
483 | 577 | ||
484 | 578 | ||
485 | /** | 579 | /** |
486 | * Get a bit flag field with the options of a channel. | 580 | * Send a channel open message. |
487 | * | ||
488 | * @param ch Channel to get options from. | ||
489 | * | 581 | * |
490 | * @return Bit array in host byte order. | 582 | * @param cls Channel for which to send. |
491 | */ | 583 | */ |
492 | static uint32_t | 584 | static void |
493 | channel_get_options (struct CadetChannel *ch) | 585 | send_channel_open (void *cls) |
494 | { | 586 | { |
587 | struct CadetChannel *ch = cls; | ||
588 | struct GNUNET_CADET_ChannelOpenMessage msgcc; | ||
495 | uint32_t options; | 589 | uint32_t options; |
496 | 590 | ||
591 | ch->retry_control_task = NULL; | ||
592 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
593 | "Sending CHANNEL_OPEN message for %s\n", | ||
594 | GCCH_2s (ch)); | ||
497 | options = 0; | 595 | options = 0; |
498 | if (ch->nobuffer) | 596 | if (ch->nobuffer) |
499 | options |= GNUNET_CADET_OPTION_NOBUFFER; | 597 | options |= GNUNET_CADET_OPTION_NOBUFFER; |
500 | if (ch->reliable) | 598 | if (ch->reliable) |
501 | options |= GNUNET_CADET_OPTION_RELIABLE; | 599 | options |= GNUNET_CADET_OPTION_RELIABLE; |
502 | 600 | if (ch->out_of_order) | |
503 | return options; | 601 | options |= GNUNET_CADET_OPTION_OUT_OF_ORDER; |
602 | msgcc.header.size = htons (sizeof (msgcc)); | ||
603 | msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN); | ||
604 | msgcc.opt = htonl (options); | ||
605 | msgcc.h_port = ch->h_port; | ||
606 | msgcc.ctn = ch->ctn; | ||
607 | ch->state = CADET_CHANNEL_OPEN_SENT; | ||
608 | if (NULL != ch->last_control_qe) | ||
609 | GCT_send_cancel (ch->last_control_qe); | ||
610 | ch->last_control_qe = GCT_send (ch->t, | ||
611 | &msgcc.header, | ||
612 | &channel_open_sent_cb, | ||
613 | ch); | ||
614 | GNUNET_assert (NULL == ch->retry_control_task); | ||
504 | } | 615 | } |
505 | 616 | ||
506 | 617 | ||
507 | /** | 618 | /** |
508 | * Notify a client that the channel is no longer valid. | 619 | * Function called once and only once after a channel was bound |
509 | * | 620 | * to its tunnel via #GCT_add_channel() is ready for transmission. |
510 | * @param ch Channel that is destroyed. | 621 | * Note that this is only the case for channels that this peer |
511 | * @param local_only Should we avoid sending it to other peers? | 622 | * initiates, as for incoming channels we assume that they are |
623 | * ready for transmission immediately upon receiving the open | ||
624 | * message. Used to bootstrap the #GCT_send() process. | ||
625 | * | ||
626 | * @param ch the channel for which the tunnel is now ready | ||
512 | */ | 627 | */ |
513 | static void | 628 | void |
514 | send_destroy (struct CadetChannel *ch, int local_only) | 629 | GCCH_tunnel_up (struct CadetChannel *ch) |
515 | { | 630 | { |
516 | struct GNUNET_CADET_ChannelManageMessage msg; | 631 | GNUNET_assert (NULL == ch->retry_control_task); |
517 | 632 | LOG (GNUNET_ERROR_TYPE_DEBUG, | |
518 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); | 633 | "Tunnel up, sending CHANNEL_OPEN on %s now\n", |
519 | msg.header.size = htons (sizeof (msg)); | 634 | GCCH_2s (ch)); |
520 | msg.ctn = ch->gid; | 635 | ch->retry_control_task |
521 | 636 | = GNUNET_SCHEDULER_add_now (&send_channel_open, | |
522 | /* If root is not NULL, notify. | 637 | ch); |
523 | * If it's NULL, check lid_root. When a local destroy comes in, root | ||
524 | * is set to NULL but lid_root is left untouched. In this case, do nothing, | ||
525 | * the client is the one who requested the channel to be destroyed. | ||
526 | */ | ||
527 | if (NULL != ch->root) | ||
528 | GML_send_channel_destroy (ch->root, ch->lid_root); | ||
529 | else if (0 == ch->lid_root.channel_of_client && GNUNET_NO == local_only) | ||
530 | GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL); | ||
531 | |||
532 | if (NULL != ch->dest) | ||
533 | GML_send_channel_destroy (ch->dest, ch->lid_dest); | ||
534 | else if (0 == ch->lid_dest.channel_of_client && GNUNET_NO == local_only) | ||
535 | GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, NULL); | ||
536 | } | 638 | } |
537 | 639 | ||
538 | 640 | ||
539 | /** | 641 | /** |
540 | * Notify the destination client that a new incoming channel was created. | 642 | * Create a new channel. |
541 | * | 643 | * |
542 | * @param ch Channel that was created. | 644 | * @param owner local client owning the channel |
645 | * @param ccn local number of this channel at the @a owner | ||
646 | * @param destination peer to which we should build the channel | ||
647 | * @param port desired port at @a destination | ||
648 | * @param options options for the channel | ||
649 | * @return handle to the new channel | ||
543 | */ | 650 | */ |
544 | static void | 651 | struct CadetChannel * |
545 | send_client_create (struct CadetChannel *ch) | 652 | GCCH_channel_local_new (struct CadetClient *owner, |
653 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
654 | struct CadetPeer *destination, | ||
655 | const struct GNUNET_HashCode *port, | ||
656 | uint32_t options) | ||
546 | { | 657 | { |
547 | uint32_t opt; | 658 | struct CadetChannel *ch; |
548 | 659 | struct CadetChannelClient *ccco; | |
549 | if (NULL == ch->dest) | ||
550 | return; | ||
551 | |||
552 | opt = 0; | ||
553 | opt |= GNUNET_YES == ch->reliable ? GNUNET_CADET_OPTION_RELIABLE : 0; | ||
554 | opt |= GNUNET_YES == ch->nobuffer ? GNUNET_CADET_OPTION_NOBUFFER : 0; | ||
555 | GML_send_channel_create (ch->dest, | ||
556 | ch->lid_dest, | ||
557 | &ch->port, | ||
558 | opt, | ||
559 | GCT_get_destination (ch->t)); | ||
560 | |||
561 | } | ||
562 | 660 | ||
661 | ccco = GNUNET_new (struct CadetChannelClient); | ||
662 | ccco->c = owner; | ||
663 | ccco->ccn = ccn; | ||
664 | ccco->client_ready = GNUNET_YES; | ||
563 | 665 | ||
564 | /** | 666 | ch = GNUNET_new (struct CadetChannel); |
565 | * Send data to a client. | 667 | ch->mid_recv.mid = htonl (1); /* The OPEN_ACK counts as message 0! */ |
566 | * | 668 | ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER)); |
567 | * If the client is ready, send directly, otherwise buffer while listening | 669 | ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE)); |
568 | * for a local ACK. | 670 | ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER)); |
569 | * | 671 | ch->max_pending_messages = (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */ |
570 | * @param ch Channel | 672 | ch->owner = ccco; |
571 | * @param msg Message. | 673 | ch->port = *port; |
572 | * @param fwd Is this a fwd (root->dest) message? | 674 | GCCH_hash_port (&ch->h_port, |
573 | */ | 675 | port, |
574 | static void | 676 | GCP_get_id (destination)); |
575 | send_client_data (struct CadetChannel *ch, | 677 | if (0 == memcmp (&my_full_id, |
576 | const struct GNUNET_CADET_ChannelAppDataMessage *msg, | 678 | GCP_get_id (destination), |
577 | int fwd) | 679 | sizeof (struct GNUNET_PeerIdentity))) |
578 | { | 680 | { |
579 | if (fwd) | 681 | struct OpenPort *op; |
580 | { | 682 | |
581 | if (ch->dest_rel->client_ready) | 683 | ch->is_loopback = GNUNET_YES; |
684 | op = GNUNET_CONTAINER_multihashmap_get (open_ports, | ||
685 | &ch->h_port); | ||
686 | if (NULL == op) | ||
582 | { | 687 | { |
583 | GML_send_data (ch->dest, msg, ch->lid_dest); | 688 | /* port closed, wait for it to possibly open */ |
584 | ch->dest_rel->client_ready = GNUNET_NO; | 689 | ch->state = CADET_CHANNEL_LOOSE; |
585 | ch->dest_rel->mid_recv++; | 690 | (void) GNUNET_CONTAINER_multihashmap_put (loose_channels, |
691 | &ch->h_port, | ||
692 | ch, | ||
693 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
694 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
695 | "Created loose incoming loopback channel to port %s\n", | ||
696 | GNUNET_h2s (&ch->port)); | ||
586 | } | 697 | } |
587 | else | 698 | else |
588 | add_buffered_data (msg, ch->dest_rel); | 699 | { |
700 | GCCH_bind (ch, | ||
701 | op->c, | ||
702 | &op->port); | ||
703 | } | ||
589 | } | 704 | } |
590 | else | 705 | else |
591 | { | 706 | { |
592 | if (ch->root_rel->client_ready) | 707 | ch->t = GCP_get_tunnel (destination, |
593 | { | 708 | GNUNET_YES); |
594 | GML_send_data (ch->root, msg, ch->lid_root); | 709 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; |
595 | ch->root_rel->client_ready = GNUNET_NO; | 710 | ch->ctn = GCT_add_channel (ch->t, |
596 | ch->root_rel->mid_recv++; | 711 | ch); |
597 | } | ||
598 | else | ||
599 | add_buffered_data (msg, ch->root_rel); | ||
600 | } | 712 | } |
713 | GNUNET_STATISTICS_update (stats, | ||
714 | "# channels", | ||
715 | 1, | ||
716 | GNUNET_NO); | ||
717 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
718 | "Created channel to port %s at peer %s for %s using %s\n", | ||
719 | GNUNET_h2s (port), | ||
720 | GCP_2s (destination), | ||
721 | GSC_2s (owner), | ||
722 | (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t)); | ||
723 | return ch; | ||
601 | } | 724 | } |
602 | 725 | ||
603 | 726 | ||
604 | /** | 727 | /** |
605 | * Send a buffered message to the client, for in order delivery or | 728 | * We had an incoming channel to a port that is closed. |
606 | * as result of client ACK. | 729 | * It has not been opened for a while, drop it. |
607 | * | 730 | * |
608 | * @param ch Channel on which to empty the message buffer. | 731 | * @param cls the channel to drop |
609 | * @param c Client to send to. | ||
610 | * @param fwd Is this to send FWD data?. | ||
611 | */ | 732 | */ |
612 | static void | 733 | static void |
613 | send_client_buffered_data (struct CadetChannel *ch, | 734 | timeout_closed_cb (void *cls) |
614 | struct CadetClient *c, | ||
615 | int fwd) | ||
616 | { | 735 | { |
617 | struct CadetReliableMessage *copy; | 736 | struct CadetChannel *ch = cls; |
618 | struct CadetChannelReliability *rel; | ||
619 | |||
620 | LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data\n"); | ||
621 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
622 | if (GNUNET_NO == rel->client_ready) | ||
623 | { | ||
624 | LOG (GNUNET_ERROR_TYPE_DEBUG, "client not ready\n"); | ||
625 | return; | ||
626 | } | ||
627 | 737 | ||
628 | copy = rel->head_recv; | 738 | ch->retry_control_task = NULL; |
629 | /* We never buffer channel management messages */ | 739 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
630 | if (NULL != copy) | 740 | "Closing incoming channel to port %s from peer %s due to timeout\n", |
631 | { | 741 | GNUNET_h2s (&ch->port), |
632 | if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable) | 742 | GCP_2s (GCT_get_destination (ch->t))); |
633 | { | 743 | channel_destroy (ch); |
634 | struct GNUNET_CADET_ChannelAppDataMessage *msg = (struct GNUNET_CADET_ChannelAppDataMessage *) ©[1]; | ||
635 | |||
636 | LOG (GNUNET_ERROR_TYPE_DEBUG, " have %u! now expecting %u\n", | ||
637 | copy->mid, rel->mid_recv + 1); | ||
638 | send_client_data (ch, msg, fwd); | ||
639 | rel->n_recv--; | ||
640 | GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy); | ||
641 | LOG (GNUNET_ERROR_TYPE_DEBUG, " free copy recv MID %u (%p), %u left\n", | ||
642 | copy->mid, copy, rel->n_recv); | ||
643 | GNUNET_free (copy); | ||
644 | GCCH_send_data_ack (ch, fwd); | ||
645 | } | ||
646 | else | ||
647 | { | ||
648 | LOG (GNUNET_ERROR_TYPE_DEBUG, " reliable && don't have %u, next is %u\n", | ||
649 | rel->mid_recv, copy->mid); | ||
650 | if (GNUNET_YES == ch->destroy) | ||
651 | { | ||
652 | /* We don't have the next data piece and the remote peer has closed the | ||
653 | * channel. We won't receive it anymore, so just destroy the channel. | ||
654 | * FIXME: wait some time to allow other connections to | ||
655 | * deliver missing messages | ||
656 | */ | ||
657 | send_destroy (ch, GNUNET_YES); | ||
658 | GCCH_destroy (ch); | ||
659 | } | ||
660 | } | ||
661 | } | ||
662 | LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data END\n"); | ||
663 | } | 744 | } |
664 | 745 | ||
665 | 746 | ||
666 | /** | 747 | /** |
667 | * Allow a client to send more data. | 748 | * Create a new channel based on a request coming in over the network. |
668 | * | ||
669 | * In case the client was already allowed to send data, do nothing. | ||
670 | * | 749 | * |
671 | * @param ch Channel. | 750 | * @param t tunnel to the remote peer |
672 | * @param fwd Is this a FWD ACK? (FWD ACKs are sent to root) | 751 | * @param ctn identifier of this channel in the tunnel |
752 | * @param h_port desired hash of local port | ||
753 | * @param options options for the channel | ||
754 | * @return handle to the new channel | ||
673 | */ | 755 | */ |
674 | static void | 756 | struct CadetChannel * |
675 | send_client_ack (struct CadetChannel *ch, int fwd) | 757 | GCCH_channel_incoming_new (struct CadetTunnel *t, |
758 | struct GNUNET_CADET_ChannelTunnelNumber ctn, | ||
759 | const struct GNUNET_HashCode *h_port, | ||
760 | uint32_t options) | ||
676 | { | 761 | { |
677 | struct CadetChannelReliability *rel = fwd ? ch->root_rel : ch->dest_rel; | 762 | struct CadetChannel *ch; |
678 | struct CadetClient *c = fwd ? ch->root : ch->dest; | 763 | struct OpenPort *op; |
679 | |||
680 | if (NULL == c) | ||
681 | { | ||
682 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
683 | return; | ||
684 | } | ||
685 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
686 | " sending %s ack to client on channel %s\n", | ||
687 | GC_f2s (fwd), GCCH_2s (ch)); | ||
688 | 764 | ||
689 | if (NULL == rel) | 765 | ch = GNUNET_new (struct CadetChannel); |
690 | { | 766 | ch->h_port = *h_port; |
691 | GNUNET_break (0); | 767 | ch->t = t; |
692 | return; | 768 | ch->ctn = ctn; |
769 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; | ||
770 | ch->nobuffer = (0 != (options & GNUNET_CADET_OPTION_NOBUFFER)); | ||
771 | ch->reliable = (0 != (options & GNUNET_CADET_OPTION_RELIABLE)); | ||
772 | ch->out_of_order = (0 != (options & GNUNET_CADET_OPTION_OUT_OF_ORDER)); | ||
773 | ch->max_pending_messages = (ch->nobuffer) ? 1 : 4; /* FIXME: 4!? Do not hardcode! */ | ||
774 | GNUNET_STATISTICS_update (stats, | ||
775 | "# channels", | ||
776 | 1, | ||
777 | GNUNET_NO); | ||
778 | |||
779 | op = GNUNET_CONTAINER_multihashmap_get (open_ports, | ||
780 | h_port); | ||
781 | if (NULL == op) | ||
782 | { | ||
783 | /* port closed, wait for it to possibly open */ | ||
784 | ch->state = CADET_CHANNEL_LOOSE; | ||
785 | (void) GNUNET_CONTAINER_multihashmap_put (loose_channels, | ||
786 | &ch->h_port, | ||
787 | ch, | ||
788 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
789 | GNUNET_assert (NULL == ch->retry_control_task); | ||
790 | ch->retry_control_task | ||
791 | = GNUNET_SCHEDULER_add_delayed (TIMEOUT_CLOSED_PORT, | ||
792 | &timeout_closed_cb, | ||
793 | ch); | ||
794 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
795 | "Created loose incoming channel to port %s from peer %s\n", | ||
796 | GNUNET_h2s (&ch->port), | ||
797 | GCP_2s (GCT_get_destination (ch->t))); | ||
693 | } | 798 | } |
694 | 799 | else | |
695 | if (GNUNET_YES == rel->client_allowed) | ||
696 | { | 800 | { |
697 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already allowed\n"); | 801 | GCCH_bind (ch, |
698 | return; | 802 | op->c, |
803 | &op->port); | ||
699 | } | 804 | } |
700 | rel->client_allowed = GNUNET_YES; | 805 | GNUNET_STATISTICS_update (stats, |
701 | 806 | "# channels", | |
702 | GML_send_ack (c, fwd ? ch->lid_root : ch->lid_dest); | 807 | 1, |
808 | GNUNET_NO); | ||
809 | return ch; | ||
703 | } | 810 | } |
704 | 811 | ||
705 | 812 | ||
706 | /** | 813 | /** |
707 | * Notify the root that the destination rejected the channel. | 814 | * Function called once the tunnel confirms that we sent the |
815 | * ACK message. Just remembers it was sent, we do not expect | ||
816 | * ACKs for ACKs ;-). | ||
708 | * | 817 | * |
709 | * @param ch Rejected channel. | 818 | * @param cls our `struct CadetChannel`. |
819 | * @param cid identifier of the connection within the tunnel, NULL | ||
820 | * if transmission failed | ||
710 | */ | 821 | */ |
711 | static void | 822 | static void |
712 | send_client_nack (struct CadetChannel *ch) | 823 | send_ack_cb (void *cls, |
824 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
713 | { | 825 | { |
714 | if (NULL == ch->root) | 826 | struct CadetChannel *ch = cls; |
715 | { | 827 | |
716 | GNUNET_break (0); | 828 | GNUNET_assert (NULL != ch->last_control_qe); |
717 | return; | 829 | ch->last_control_qe = NULL; |
718 | } | ||
719 | GML_send_channel_nack (ch->root, ch->lid_root); | ||
720 | } | 830 | } |
721 | 831 | ||
722 | 832 | ||
723 | /** | 833 | /** |
724 | * We haven't received an ACK after a certain time: restransmit the message. | 834 | * Compute and send the current #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK to the other peer. |
725 | * | 835 | * |
726 | * @param cls Closure (CadetChannelReliability with the message to restransmit) | 836 | * @param ch channel to send the #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK for |
727 | */ | 837 | */ |
728 | static void | 838 | static void |
729 | channel_retransmit_message (void *cls) | 839 | send_channel_data_ack (struct CadetChannel *ch) |
730 | { | 840 | { |
731 | struct CadetChannelReliability *rel = cls; | 841 | struct GNUNET_CADET_ChannelDataAckMessage msg; |
732 | struct CadetReliableMessage *copy; | ||
733 | struct CadetChannel *ch; | ||
734 | struct GNUNET_CADET_ChannelAppDataMessage *payload; | ||
735 | int fwd; | ||
736 | |||
737 | rel->retry_task = NULL; | ||
738 | ch = rel->ch; | ||
739 | copy = rel->head_sent; | ||
740 | if (NULL == copy) | ||
741 | { | ||
742 | GNUNET_break (0); // FIXME tripped in rps testcase | ||
743 | return; | ||
744 | } | ||
745 | |||
746 | payload = (struct GNUNET_CADET_ChannelAppDataMessage *) ©[1]; | ||
747 | fwd = (rel == ch->root_rel); | ||
748 | |||
749 | /* Message not found in the queue that we are going to use. */ | ||
750 | LOG (GNUNET_ERROR_TYPE_DEBUG, "RETRANSMIT MID %u\n", copy->mid); | ||
751 | 842 | ||
752 | GCCH_send_prebuilt_message (&payload->header, ch, fwd, copy); | 843 | if (GNUNET_NO == ch->reliable) |
753 | GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO); | 844 | return; /* no ACKs */ |
845 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK); | ||
846 | msg.header.size = htons (sizeof (msg)); | ||
847 | msg.ctn = ch->ctn; | ||
848 | msg.mid.mid = htonl (ntohl (ch->mid_recv.mid)); | ||
849 | msg.futures = GNUNET_htonll (ch->mid_futures); | ||
850 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
851 | "Sending DATA_ACK %u:%llX via %s\n", | ||
852 | (unsigned int) ntohl (msg.mid.mid), | ||
853 | (unsigned long long) ch->mid_futures, | ||
854 | GCCH_2s (ch)); | ||
855 | if (NULL != ch->last_control_qe) | ||
856 | GCT_send_cancel (ch->last_control_qe); | ||
857 | ch->last_control_qe = GCT_send (ch->t, | ||
858 | &msg.header, | ||
859 | &send_ack_cb, | ||
860 | ch); | ||
754 | } | 861 | } |
755 | 862 | ||
756 | 863 | ||
757 | /** | 864 | /** |
758 | * We haven't received an Channel ACK after a certain time: resend the CREATE. | 865 | * Send our initial #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK to the client confirming that the |
866 | * connection is up. | ||
759 | * | 867 | * |
760 | * @param cls Closure (CadetChannelReliability of the channel to recreate) | 868 | * @param cls the `struct CadetChannel` |
761 | */ | 869 | */ |
762 | static void | 870 | static void |
763 | channel_recreate (void *cls) | 871 | send_open_ack (void *cls) |
764 | { | 872 | { |
765 | struct CadetChannelReliability *rel = cls; | 873 | struct CadetChannel *ch = cls; |
874 | struct GNUNET_CADET_ChannelOpenAckMessage msg; | ||
766 | 875 | ||
767 | rel->retry_task = NULL; | 876 | ch->retry_control_task = NULL; |
768 | LOG (GNUNET_ERROR_TYPE_DEBUG, "RE-CREATE\n"); | 877 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
769 | GNUNET_STATISTICS_update (stats, | 878 | "Sending CHANNEL_OPEN_ACK on %s\n", |
770 | "# data retransmitted", 1, GNUNET_NO); | 879 | GCCH_2s (ch)); |
771 | 880 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK); | |
772 | if (rel == rel->ch->root_rel) | 881 | msg.header.size = htons (sizeof (msg)); |
773 | { | 882 | msg.reserved = htonl (0); |
774 | send_create (rel->ch); | 883 | msg.ctn = ch->ctn; |
775 | } | 884 | msg.port = ch->port; |
776 | else if (rel == rel->ch->dest_rel) | 885 | if (NULL != ch->last_control_qe) |
777 | { | 886 | GCT_send_cancel (ch->last_control_qe); |
778 | send_ack (rel->ch, GNUNET_YES); | 887 | ch->last_control_qe = GCT_send (ch->t, |
779 | } | 888 | &msg.header, |
780 | else | 889 | &send_ack_cb, |
781 | { | 890 | ch); |
782 | GNUNET_break (0); | ||
783 | } | ||
784 | } | 891 | } |
785 | 892 | ||
786 | 893 | ||
787 | /** | 894 | /** |
788 | * Message has been sent: start retransmission timer. | 895 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for |
896 | * this channel. If the binding was successful, (re)transmit the | ||
897 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK. | ||
789 | * | 898 | * |
790 | * @param cls Closure (queue structure). | 899 | * @param ch channel that got the duplicate open |
791 | * @param t Tunnel. | 900 | * @param cti identifier of the connection that delivered the message |
792 | * @param q Queue handler (no longer valid). | ||
793 | * @param type Type of message. | ||
794 | * @param size Size of the message. | ||
795 | */ | 901 | */ |
796 | static void | 902 | void |
797 | ch_message_sent (void *cls, | 903 | GCCH_handle_duplicate_open (struct CadetChannel *ch, |
798 | struct CadetTunnel *t, | 904 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti) |
799 | struct CadetTunnelQueue *q, | ||
800 | uint16_t type, size_t size) | ||
801 | { | 905 | { |
802 | struct CadetChannelQueue *chq = cls; | 906 | if (NULL == ch->dest) |
803 | struct CadetReliableMessage *copy = chq->copy; | ||
804 | struct CadetChannelReliability *rel; | ||
805 | |||
806 | LOG (GNUNET_ERROR_TYPE_DEBUG, "channel_message_sent callback %s\n", | ||
807 | GC_m2s (chq->type)); | ||
808 | |||
809 | switch (chq->type) | ||
810 | { | 907 | { |
811 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA: | 908 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
812 | LOG (GNUNET_ERROR_TYPE_DEBUG, "data MID %u sent\n", copy->mid); | 909 | "Ignoring duplicate CHANNEL_OPEN on %s: port is closed\n", |
813 | GNUNET_assert (chq == copy->chq); | 910 | GCCH_2s (ch)); |
814 | copy->timestamp = GNUNET_TIME_absolute_get (); | 911 | return; |
815 | rel = copy->rel; | ||
816 | if (NULL == rel->retry_task) | ||
817 | { | ||
818 | LOG (GNUNET_ERROR_TYPE_DEBUG, " scheduling retry in %d * %s\n", | ||
819 | CADET_RETRANSMIT_MARGIN, | ||
820 | GNUNET_STRINGS_relative_time_to_string (rel->expected_delay, | ||
821 | GNUNET_YES)); | ||
822 | if (0 != rel->expected_delay.rel_value_us) | ||
823 | { | ||
824 | rel->retry_timer = | ||
825 | GNUNET_TIME_relative_saturating_multiply (rel->expected_delay, | ||
826 | CADET_RETRANSMIT_MARGIN); | ||
827 | } | ||
828 | else | ||
829 | { | ||
830 | rel->retry_timer = CADET_RETRANSMIT_TIME; | ||
831 | } | ||
832 | LOG (GNUNET_ERROR_TYPE_DEBUG, " using delay %s\n", | ||
833 | GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, | ||
834 | GNUNET_NO)); | ||
835 | rel->retry_task = | ||
836 | GNUNET_SCHEDULER_add_delayed (rel->retry_timer, | ||
837 | &channel_retransmit_message, rel); | ||
838 | } | ||
839 | else | ||
840 | { | ||
841 | LOG (GNUNET_ERROR_TYPE_DEBUG, "retry running %p\n", rel->retry_task); | ||
842 | } | ||
843 | copy->chq = NULL; | ||
844 | break; | ||
845 | |||
846 | |||
847 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK: | ||
848 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN: | ||
849 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK: | ||
850 | LOG (GNUNET_ERROR_TYPE_DEBUG, "sent %s\n", GC_m2s (chq->type)); | ||
851 | rel = chq->rel; | ||
852 | GNUNET_assert (rel->uniq == chq); | ||
853 | rel->uniq = NULL; | ||
854 | |||
855 | if (CADET_CHANNEL_READY != rel->ch->state | ||
856 | && GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK != type | ||
857 | && GNUNET_NO == rel->ch->destroy) | ||
858 | { | ||
859 | GNUNET_assert (NULL == rel->retry_task); | ||
860 | LOG (GNUNET_ERROR_TYPE_DEBUG, "STD BACKOFF %s\n", | ||
861 | GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, | ||
862 | GNUNET_NO)); | ||
863 | rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer); | ||
864 | rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer, | ||
865 | &channel_recreate, rel); | ||
866 | } | ||
867 | break; | ||
868 | |||
869 | default: | ||
870 | GNUNET_break (0); | ||
871 | } | 912 | } |
872 | 913 | if (NULL != ch->retry_control_task) | |
873 | GNUNET_free (chq); | 914 | { |
915 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
916 | "Ignoring duplicate CHANNEL_OPEN on %s: control message is pending\n", | ||
917 | GCCH_2s (ch)); | ||
918 | return; | ||
919 | } | ||
920 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
921 | "Retransmitting CHANNEL_OPEN_ACK on %s\n", | ||
922 | GCCH_2s (ch)); | ||
923 | ch->retry_control_task | ||
924 | = GNUNET_SCHEDULER_add_now (&send_open_ack, | ||
925 | ch); | ||
874 | } | 926 | } |
875 | 927 | ||
876 | 928 | ||
877 | /** | 929 | /** |
878 | * send a channel create message. | 930 | * Send a #GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK to the client to solicit more messages. |
879 | * | 931 | * |
880 | * @param ch Channel for which to send. | 932 | * @param ch channel the ack is for |
933 | * @param to_owner #GNUNET_YES to send to owner, | ||
934 | * #GNUNET_NO to send to dest | ||
881 | */ | 935 | */ |
882 | static void | 936 | static void |
883 | send_create (struct CadetChannel *ch) | 937 | send_ack_to_client (struct CadetChannel *ch, |
938 | int to_owner) | ||
884 | { | 939 | { |
885 | struct GNUNET_CADET_ChannelOpenMessage msgcc; | 940 | struct GNUNET_MQ_Envelope *env; |
941 | struct GNUNET_CADET_LocalAck *ack; | ||
942 | struct CadetChannelClient *ccc; | ||
886 | 943 | ||
887 | msgcc.header.size = htons (sizeof (msgcc)); | 944 | ccc = (GNUNET_YES == to_owner) ? ch->owner : ch->dest; |
888 | msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN); | 945 | if (NULL == ccc) |
889 | msgcc.ctn = ch->gid; | 946 | { |
890 | msgcc.port = ch->port; | 947 | /* This can happen if we are just getting ACKs after |
891 | msgcc.opt = htonl (channel_get_options (ch)); | 948 | our local client already disconnected. */ |
892 | 949 | GNUNET_assert (GNUNET_YES == ch->destroy); | |
893 | GCCH_send_prebuilt_message (&msgcc.header, ch, GNUNET_YES, NULL); | 950 | return; |
951 | } | ||
952 | env = GNUNET_MQ_msg (ack, | ||
953 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | ||
954 | ack->ccn = ccc->ccn; | ||
955 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
956 | "Sending CADET_LOCAL_ACK to %s (%s) at ccn %X (%u/%u pending)\n", | ||
957 | GSC_2s (ccc->c), | ||
958 | (GNUNET_YES == to_owner) ? "owner" : "dest", | ||
959 | ntohl (ack->ccn.channel_of_client), | ||
960 | ch->pending_messages, | ||
961 | ch->max_pending_messages); | ||
962 | GSC_send_to_client (ccc->c, | ||
963 | env); | ||
894 | } | 964 | } |
895 | 965 | ||
896 | 966 | ||
897 | /** | 967 | /** |
898 | * Confirm we got a channel create or FWD ack. | 968 | * A client is bound to the port that we have a channel |
969 | * open to. Send the acknowledgement for the connection | ||
970 | * request and establish the link with the client. | ||
899 | * | 971 | * |
900 | * @param ch The channel to confirm. | 972 | * @param ch open incoming channel |
901 | * @param fwd Should we send a FWD ACK? (going dest->root) | 973 | * @param c client listening on the respective @a port |
974 | * @param port the port @a is listening on | ||
902 | */ | 975 | */ |
903 | static void | 976 | void |
904 | send_ack (struct CadetChannel *ch, int fwd) | 977 | GCCH_bind (struct CadetChannel *ch, |
978 | struct CadetClient *c, | ||
979 | const struct GNUNET_HashCode *port) | ||
905 | { | 980 | { |
906 | struct GNUNET_CADET_ChannelManageMessage msg; | 981 | uint32_t options; |
982 | struct CadetChannelClient *cccd; | ||
907 | 983 | ||
908 | msg.header.size = htons (sizeof (msg)); | ||
909 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK); | ||
910 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 984 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
911 | " sending channel %s ack for channel %s\n", | 985 | "Binding %s from %s to port %s of %s\n", |
912 | GC_f2s (fwd), GCCH_2s (ch)); | 986 | GCCH_2s (ch), |
913 | 987 | GCT_2s (ch->t), | |
914 | msg.ctn =ch->gid; | 988 | GNUNET_h2s (&ch->port), |
915 | GCCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL); | 989 | GSC_2s (c)); |
990 | if (NULL != ch->retry_control_task) | ||
991 | { | ||
992 | /* there might be a timeout task here */ | ||
993 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); | ||
994 | ch->retry_control_task = NULL; | ||
995 | } | ||
996 | options = 0; | ||
997 | if (ch->nobuffer) | ||
998 | options |= GNUNET_CADET_OPTION_NOBUFFER; | ||
999 | if (ch->reliable) | ||
1000 | options |= GNUNET_CADET_OPTION_RELIABLE; | ||
1001 | if (ch->out_of_order) | ||
1002 | options |= GNUNET_CADET_OPTION_OUT_OF_ORDER; | ||
1003 | cccd = GNUNET_new (struct CadetChannelClient); | ||
1004 | GNUNET_assert (NULL == ch->dest); | ||
1005 | ch->dest = cccd; | ||
1006 | ch->port = *port; | ||
1007 | cccd->c = c; | ||
1008 | cccd->client_ready = GNUNET_YES; | ||
1009 | cccd->ccn = GSC_bind (c, | ||
1010 | ch, | ||
1011 | (GNUNET_YES == ch->is_loopback) | ||
1012 | ? GCP_get (&my_full_id, | ||
1013 | GNUNET_YES) | ||
1014 | : GCT_get_destination (ch->t), | ||
1015 | port, | ||
1016 | options); | ||
1017 | GNUNET_assert (ntohl (cccd->ccn.channel_of_client) < | ||
1018 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
1019 | ch->mid_recv.mid = htonl (1); /* The OPEN counts as message 0! */ | ||
1020 | if (GNUNET_YES == ch->is_loopback) | ||
1021 | { | ||
1022 | ch->state = CADET_CHANNEL_OPEN_SENT; | ||
1023 | GCCH_handle_channel_open_ack (ch, | ||
1024 | NULL, | ||
1025 | port); | ||
1026 | } | ||
1027 | else | ||
1028 | { | ||
1029 | /* notify other peer that we accepted the connection */ | ||
1030 | ch->state = CADET_CHANNEL_READY; | ||
1031 | ch->retry_control_task | ||
1032 | = GNUNET_SCHEDULER_add_now (&send_open_ack, | ||
1033 | ch); | ||
1034 | } | ||
1035 | /* give client it's initial supply of ACKs */ | ||
1036 | GNUNET_assert (ntohl (cccd->ccn.channel_of_client) < | ||
1037 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
1038 | for (unsigned int i=0;i<ch->max_pending_messages;i++) | ||
1039 | send_ack_to_client (ch, | ||
1040 | GNUNET_NO); | ||
916 | } | 1041 | } |
917 | 1042 | ||
918 | 1043 | ||
919 | /** | 1044 | /** |
920 | * Send a message and don't keep any info about it: we won't need to cancel it | 1045 | * One of our clients has disconnected, tell the other one that we |
921 | * or resend it. | 1046 | * are finished. Done asynchronously to avoid concurrent modification |
1047 | * issues if this is the same client. | ||
922 | * | 1048 | * |
923 | * @param msg Header of the message to fire away. | 1049 | * @param cls the `struct CadetChannel` where one of the ends is now dead |
924 | * @param ch Channel on which the message should go. | ||
925 | * @param force Is this a forced (undroppable) message? | ||
926 | */ | 1050 | */ |
927 | static void | 1051 | static void |
928 | fire_and_forget (const struct GNUNET_MessageHeader *msg, | 1052 | signal_remote_destroy_cb (void *cls) |
929 | struct CadetChannel *ch, | ||
930 | int force) | ||
931 | { | 1053 | { |
932 | GNUNET_break (NULL == | 1054 | struct CadetChannel *ch = cls; |
933 | GCT_send_prebuilt_message (msg, ch->t, NULL, | 1055 | struct CadetChannelClient *ccc; |
934 | force, NULL, NULL)); | 1056 | |
1057 | /* Find which end is left... */ | ||
1058 | ch->retry_control_task = NULL; | ||
1059 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1060 | GSC_handle_remote_channel_destroy (ccc->c, | ||
1061 | ccc->ccn, | ||
1062 | ch); | ||
1063 | channel_destroy (ch); | ||
935 | } | 1064 | } |
936 | 1065 | ||
937 | 1066 | ||
938 | /** | 1067 | /** |
939 | * Notify that a channel create didn't succeed. | 1068 | * Destroy locally created channel. Called by the local client, so no |
1069 | * need to tell the client. | ||
940 | * | 1070 | * |
941 | * @param ch The channel to reject. | 1071 | * @param ch channel to destroy |
1072 | * @param c client that caused the destruction | ||
1073 | * @param ccn client number of the client @a c | ||
942 | */ | 1074 | */ |
943 | static void | 1075 | void |
944 | send_nack (struct CadetChannel *ch) | 1076 | GCCH_channel_local_destroy (struct CadetChannel *ch, |
1077 | struct CadetClient *c, | ||
1078 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
945 | { | 1079 | { |
946 | struct GNUNET_CADET_ChannelManageMessage msg; | ||
947 | |||
948 | msg.header.size = htons (sizeof (msg)); | ||
949 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED); | ||
950 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1080 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
951 | " sending channel NACK for channel %s\n", | 1081 | "%s asks for destruction of %s\n", |
1082 | GSC_2s (c), | ||
952 | GCCH_2s (ch)); | 1083 | GCCH_2s (ch)); |
1084 | GNUNET_assert (NULL != c); | ||
1085 | if ( (NULL != ch->owner) && | ||
1086 | (c == ch->owner->c) && | ||
1087 | (ccn.channel_of_client == ch->owner->ccn.channel_of_client) ) | ||
1088 | { | ||
1089 | free_channel_client (ch->owner); | ||
1090 | ch->owner = NULL; | ||
1091 | } | ||
1092 | else if ( (NULL != ch->dest) && | ||
1093 | (c == ch->dest->c) && | ||
1094 | (ccn.channel_of_client == ch->dest->ccn.channel_of_client) ) | ||
1095 | { | ||
1096 | free_channel_client (ch->dest); | ||
1097 | ch->dest = NULL; | ||
1098 | } | ||
1099 | else | ||
1100 | { | ||
1101 | GNUNET_assert (0); | ||
1102 | } | ||
953 | 1103 | ||
954 | msg.ctn = ch->gid; | 1104 | if (GNUNET_YES == ch->destroy) |
955 | GCCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL); | ||
956 | } | ||
957 | |||
958 | |||
959 | /** | ||
960 | * Destroy all reliable messages queued for a channel, | ||
961 | * during a channel destruction. | ||
962 | * Frees the reliability structure itself. | ||
963 | * | ||
964 | * @param rel Reliability data for a channel. | ||
965 | */ | ||
966 | static void | ||
967 | channel_rel_free_all (struct CadetChannelReliability *rel) | ||
968 | { | ||
969 | struct CadetReliableMessage *copy; | ||
970 | struct CadetReliableMessage *next; | ||
971 | |||
972 | if (NULL == rel) | ||
973 | return; | ||
974 | |||
975 | for (copy = rel->head_recv; NULL != copy; copy = next) | ||
976 | { | 1105 | { |
977 | next = copy->next; | 1106 | /* other end already destroyed, with the local client gone, no need |
978 | GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy); | 1107 | to finish transmissions, just destroy immediately. */ |
979 | LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE ALL RECV %p\n", copy); | 1108 | channel_destroy (ch); |
980 | GNUNET_break (NULL == copy->chq); | 1109 | return; |
981 | GNUNET_free (copy); | ||
982 | } | 1110 | } |
983 | for (copy = rel->head_sent; NULL != copy; copy = next) | 1111 | if ( (NULL != ch->head_sent) && |
1112 | ( (NULL != ch->owner) || | ||
1113 | (NULL != ch->dest) ) ) | ||
984 | { | 1114 | { |
985 | next = copy->next; | 1115 | /* Wait for other end to destroy us as well, |
986 | GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy); | 1116 | and otherwise allow send queue to be transmitted first */ |
987 | LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE ALL SEND %p\n", copy); | 1117 | ch->destroy = GNUNET_YES; |
988 | if (NULL != copy->chq) | 1118 | return; |
989 | { | ||
990 | if (NULL != copy->chq->tq) | ||
991 | { | ||
992 | GCT_cancel (copy->chq->tq); | ||
993 | /* ch_message_sent will free copy->q */ | ||
994 | } | ||
995 | else | ||
996 | { | ||
997 | GNUNET_free (copy->chq); | ||
998 | GNUNET_break (0); | ||
999 | } | ||
1000 | } | ||
1001 | GNUNET_free (copy); | ||
1002 | } | 1119 | } |
1003 | if (NULL != rel->uniq && NULL != rel->uniq->tq) | 1120 | if ( (GNUNET_YES == ch->is_loopback) && |
1121 | ( (NULL != ch->owner) || | ||
1122 | (NULL != ch->dest) ) ) | ||
1004 | { | 1123 | { |
1005 | GCT_cancel (rel->uniq->tq); | 1124 | if (NULL != ch->retry_control_task) |
1006 | /* ch_message_sent is called freeing uniq */ | 1125 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); |
1126 | ch->retry_control_task | ||
1127 | = GNUNET_SCHEDULER_add_now (&signal_remote_destroy_cb, | ||
1128 | ch); | ||
1129 | return; | ||
1007 | } | 1130 | } |
1008 | if (NULL != rel->retry_task) | 1131 | if (GNUNET_NO == ch->is_loopback) |
1009 | { | 1132 | { |
1010 | GNUNET_SCHEDULER_cancel (rel->retry_task); | 1133 | /* If the we ever sent the CHANNEL_CREATE, we need to send a destroy message. */ |
1011 | rel->retry_task = NULL; | 1134 | switch (ch->state) |
1135 | { | ||
1136 | case CADET_CHANNEL_NEW: | ||
1137 | /* We gave up on a channel that we created as a client to a remote | ||
1138 | target, but that never went anywhere. Nothing to do here. */ | ||
1139 | break; | ||
1140 | case CADET_CHANNEL_LOOSE: | ||
1141 | GSC_drop_loose_channel (&ch->h_port, | ||
1142 | ch); | ||
1143 | break; | ||
1144 | default: | ||
1145 | GCT_send_channel_destroy (ch->t, | ||
1146 | ch->ctn); | ||
1147 | } | ||
1012 | } | 1148 | } |
1013 | GNUNET_free (rel); | 1149 | /* Nothing left to do, just finish destruction */ |
1150 | channel_destroy (ch); | ||
1014 | } | 1151 | } |
1015 | 1152 | ||
1016 | 1153 | ||
1017 | /** | 1154 | /** |
1018 | * Mark future messages as ACK'd. | 1155 | * We got an acknowledgement for the creation of the channel |
1156 | * (the port is open on the other side). Verify that the | ||
1157 | * other end really has the right port, and begin transmissions. | ||
1019 | * | 1158 | * |
1020 | * @param rel Reliability data. | 1159 | * @param ch channel to destroy |
1021 | * @param msg DataACK message with a bitfield of future ACK'd messages. | 1160 | * @param cti identifier of the connection that delivered the message |
1022 | * | 1161 | * @param port port number (needed to verify receiver knows the port) |
1023 | * @return How many messages have been freed. | ||
1024 | */ | 1162 | */ |
1025 | static unsigned int | 1163 | void |
1026 | channel_rel_free_sent (struct CadetChannelReliability *rel, | 1164 | GCCH_handle_channel_open_ack (struct CadetChannel *ch, |
1027 | const struct GNUNET_CADET_ChannelDataAckMessage *msg) | 1165 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, |
1166 | const struct GNUNET_HashCode *port) | ||
1028 | { | 1167 | { |
1029 | struct CadetReliableMessage *copy; | 1168 | switch (ch->state) |
1030 | struct CadetReliableMessage *next; | ||
1031 | uint64_t bitfield; | ||
1032 | uint64_t mask; | ||
1033 | uint32_t mid; | ||
1034 | uint32_t target; | ||
1035 | unsigned int i; | ||
1036 | unsigned int r; | ||
1037 | |||
1038 | bitfield = msg->futures; | ||
1039 | mid = ntohl (msg->mid); | ||
1040 | LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable %u %lX\n", mid, bitfield); | ||
1041 | LOG (GNUNET_ERROR_TYPE_DEBUG, " rel %p, head %p\n", rel, rel->head_sent); | ||
1042 | for (i = 0, r = 0, copy = rel->head_sent; | ||
1043 | i < 64 && NULL != copy && 0 != bitfield; | ||
1044 | i++) | ||
1045 | { | 1169 | { |
1046 | LOG (GNUNET_ERROR_TYPE_DEBUG, " trying bit %u (mid %u)\n", i, mid + i + 1); | 1170 | case CADET_CHANNEL_NEW: |
1047 | mask = 0x1LL << i; | 1171 | /* this should be impossible */ |
1048 | if (0 == (bitfield & mask)) | 1172 | GNUNET_break (0); |
1049 | continue; | 1173 | break; |
1050 | 1174 | case CADET_CHANNEL_LOOSE: | |
1051 | LOG (GNUNET_ERROR_TYPE_DEBUG, " set!\n"); | 1175 | /* This makes no sense. */ |
1052 | /* Bit was set, clear the bit from the bitfield */ | 1176 | GNUNET_break_op (0); |
1053 | bitfield &= ~mask; | 1177 | break; |
1054 | 1178 | case CADET_CHANNEL_OPEN_SENT: | |
1055 | /* The i-th bit was set. Do we have that copy? */ | 1179 | if (NULL == ch->owner) |
1056 | /* Skip copies with mid < target */ | 1180 | { |
1057 | target = mid + i + 1; | 1181 | /* We're not the owner, wrong direction! */ |
1058 | LOG (GNUNET_ERROR_TYPE_DEBUG, " target %u\n", target); | 1182 | GNUNET_break_op (0); |
1059 | while (NULL != copy && GC_is_pid_bigger (target, copy->mid)) | 1183 | return; |
1060 | copy = copy->next; | 1184 | } |
1061 | 1185 | if (0 != memcmp (&ch->port, | |
1062 | /* Did we run out of copies? (previously freed, it's ok) */ | 1186 | port, |
1063 | if (NULL == copy) | 1187 | sizeof (struct GNUNET_HashCode))) |
1064 | { | 1188 | { |
1065 | LOG (GNUNET_ERROR_TYPE_DEBUG, "run out of copies...\n"); | 1189 | /* Other peer failed to provide the right port, |
1066 | return r; | 1190 | refuse connection. */ |
1191 | GNUNET_break_op (0); | ||
1192 | return; | ||
1067 | } | 1193 | } |
1068 | 1194 | LOG (GNUNET_ERROR_TYPE_DEBUG, | |
1069 | /* Did we overshoot the target? (previously freed, it's ok) */ | 1195 | "Received CHANNEL_OPEN_ACK for waiting %s, entering READY state\n", |
1070 | if (GC_is_pid_bigger (copy->mid, target)) | 1196 | GCCH_2s (ch)); |
1197 | if (NULL != ch->retry_control_task) /* can be NULL if ch->is_loopback */ | ||
1071 | { | 1198 | { |
1072 | LOG (GNUNET_ERROR_TYPE_DEBUG, " next copy %u\n", copy->mid); | 1199 | GNUNET_SCHEDULER_cancel (ch->retry_control_task); |
1073 | i += copy->mid - target - 1; /* MID: 90, t = 85, i += 4 (i++ later) */ | 1200 | ch->retry_control_task = NULL; |
1074 | mask = (0x1LL << (i + 1)) - 1; /* Mask = i-th bit and all before */ | ||
1075 | bitfield &= ~mask; /* Clear all bits up to MID - 1 */ | ||
1076 | continue; | ||
1077 | } | 1201 | } |
1078 | 1202 | ch->state = CADET_CHANNEL_READY; | |
1079 | /* Now copy->mid == target, free it */ | 1203 | /* On first connect, send client as many ACKs as we allow messages |
1080 | next = copy->next; | 1204 | to be buffered! */ |
1081 | GNUNET_break (GNUNET_YES != rel_message_free (copy, GNUNET_YES)); | 1205 | for (unsigned int i=0;i<ch->max_pending_messages;i++) |
1082 | r++; | 1206 | send_ack_to_client (ch, |
1083 | copy = next; | 1207 | GNUNET_YES); |
1208 | break; | ||
1209 | case CADET_CHANNEL_READY: | ||
1210 | /* duplicate ACK, maybe we retried the CREATE. Ignore. */ | ||
1211 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1212 | "Received duplicate channel OPEN_ACK for %s\n", | ||
1213 | GCCH_2s (ch)); | ||
1214 | GNUNET_STATISTICS_update (stats, | ||
1215 | "# duplicate CREATE_ACKs", | ||
1216 | 1, | ||
1217 | GNUNET_NO); | ||
1218 | break; | ||
1084 | } | 1219 | } |
1085 | LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable END\n"); | ||
1086 | return r; | ||
1087 | } | 1220 | } |
1088 | 1221 | ||
1089 | 1222 | ||
1090 | /** | 1223 | /** |
1091 | * Destroy a reliable message after it has been acknowledged, either by | 1224 | * Test if element @a e1 comes before element @a e2. |
1092 | * direct mid ACK or bitfield. Updates the appropriate data structures and | ||
1093 | * timers and frees all memory. | ||
1094 | * | ||
1095 | * @param copy Message that is no longer needed: remote peer got it. | ||
1096 | * @param update_time Is the timing information relevant? | ||
1097 | * If this message is ACK in a batch the timing information | ||
1098 | * is skewed by the retransmission, count only for the | ||
1099 | * retransmitted message. | ||
1100 | * | 1225 | * |
1101 | * @return #GNUNET_YES if channel was destroyed as a result of the call, | 1226 | * @param cls closure, to a flag where we indicate duplicate packets |
1102 | * #GNUNET_NO otherwise. | 1227 | * @param m1 a message of to sort |
1228 | * @param m2 another message to sort | ||
1229 | * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO | ||
1103 | */ | 1230 | */ |
1104 | static int | 1231 | static int |
1105 | rel_message_free (struct CadetReliableMessage *copy, int update_time) | 1232 | is_before (void *cls, |
1233 | struct CadetOutOfOrderMessage *m1, | ||
1234 | struct CadetOutOfOrderMessage *m2) | ||
1106 | { | 1235 | { |
1107 | struct CadetChannelReliability *rel; | 1236 | int *duplicate = cls; |
1108 | struct GNUNET_TIME_Relative time; | 1237 | uint32_t v1 = ntohl (m1->mid.mid); |
1238 | uint32_t v2 = ntohl (m2->mid.mid); | ||
1239 | uint32_t delta; | ||
1109 | 1240 | ||
1110 | rel = copy->rel; | 1241 | delta = v2 - v1; |
1111 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Freeing %u\n", copy->mid); | 1242 | if (0 == delta) |
1112 | if (GNUNET_YES == update_time) | 1243 | *duplicate = GNUNET_YES; |
1244 | if (delta > (uint32_t) INT_MAX) | ||
1113 | { | 1245 | { |
1114 | time = GNUNET_TIME_absolute_get_duration (copy->timestamp); | 1246 | /* in overflow range, we can safely assume we wrapped around */ |
1115 | if (0 == rel->expected_delay.rel_value_us) | 1247 | return GNUNET_NO; |
1116 | rel->expected_delay = time; | ||
1117 | else | ||
1118 | { | ||
1119 | rel->expected_delay.rel_value_us *= 7; | ||
1120 | rel->expected_delay.rel_value_us += time.rel_value_us; | ||
1121 | rel->expected_delay.rel_value_us /= 8; | ||
1122 | } | ||
1123 | LOG (GNUNET_ERROR_TYPE_DEBUG, " message time %12s\n", | ||
1124 | GNUNET_STRINGS_relative_time_to_string (time, GNUNET_NO)); | ||
1125 | LOG (GNUNET_ERROR_TYPE_DEBUG, " new delay %12s\n", | ||
1126 | GNUNET_STRINGS_relative_time_to_string (rel->expected_delay, | ||
1127 | GNUNET_NO)); | ||
1128 | rel->retry_timer = rel->expected_delay; | ||
1129 | } | 1248 | } |
1130 | else | 1249 | else |
1131 | { | 1250 | { |
1132 | LOG (GNUNET_ERROR_TYPE_DEBUG, "batch free, ignoring timing\n"); | 1251 | /* result is small, thus v2 > v1, thus m1 < m2 */ |
1133 | } | ||
1134 | rel->ch->pending_messages--; | ||
1135 | if (NULL != copy->chq) | ||
1136 | { | ||
1137 | GCT_cancel (copy->chq->tq); | ||
1138 | /* copy->q is set to NULL by ch_message_sent */ | ||
1139 | } | ||
1140 | GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy); | ||
1141 | LOG (GNUNET_ERROR_TYPE_DEBUG, " free send copy MID %u at %p\n", | ||
1142 | copy->mid, copy); | ||
1143 | GNUNET_free (copy); | ||
1144 | |||
1145 | if (GNUNET_NO != rel->ch->destroy && 0 == rel->ch->pending_messages) | ||
1146 | { | ||
1147 | GCCH_destroy (rel->ch); | ||
1148 | return GNUNET_YES; | 1252 | return GNUNET_YES; |
1149 | } | 1253 | } |
1150 | return GNUNET_NO; | ||
1151 | } | 1254 | } |
1152 | 1255 | ||
1153 | 1256 | ||
1154 | /** | 1257 | /** |
1155 | * Channel was ACK'd by remote peer, mark as ready and cancel retransmission. | 1258 | * We got payload data for a channel. Pass it on to the client |
1259 | * and send an ACK to the other end (once flow control allows it!) | ||
1156 | * | 1260 | * |
1157 | * @param ch Channel to mark as ready. | 1261 | * @param ch channel that got data |
1158 | * @param fwd Was the ACK message a FWD ACK? (dest->root, SYNACK) | 1262 | * @param cti identifier of the connection that delivered the message |
1263 | * @param msg message that was received | ||
1159 | */ | 1264 | */ |
1160 | static void | 1265 | void |
1161 | channel_confirm (struct CadetChannel *ch, int fwd) | 1266 | GCCH_handle_channel_plaintext_data (struct CadetChannel *ch, |
1267 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1268 | const struct GNUNET_CADET_ChannelAppDataMessage *msg) | ||
1162 | { | 1269 | { |
1163 | struct CadetChannelReliability *rel; | 1270 | struct GNUNET_MQ_Envelope *env; |
1164 | enum CadetChannelState oldstate; | 1271 | struct GNUNET_CADET_LocalData *ld; |
1165 | 1272 | struct CadetChannelClient *ccc; | |
1166 | rel = fwd ? ch->root_rel : ch->dest_rel; | 1273 | size_t payload_size; |
1167 | if (NULL == rel) | 1274 | struct CadetOutOfOrderMessage *com; |
1275 | int duplicate; | ||
1276 | uint32_t mid_min; | ||
1277 | uint32_t mid_max; | ||
1278 | uint32_t mid_msg; | ||
1279 | uint32_t delta; | ||
1280 | |||
1281 | GNUNET_assert (GNUNET_NO == ch->is_loopback); | ||
1282 | if ( (GNUNET_YES == ch->destroy) && | ||
1283 | (NULL == ch->owner) && | ||
1284 | (NULL == ch->dest) ) | ||
1285 | { | ||
1286 | /* This client is gone, but we still have messages to send to | ||
1287 | the other end (which is why @a ch is not yet dead). However, | ||
1288 | we cannot pass messages to our client anymore. */ | ||
1289 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1290 | "Dropping incoming payload on %s as this end is already closed\n", | ||
1291 | GCCH_2s (ch)); | ||
1292 | /* send back DESTROY notification to stop further retransmissions! */ | ||
1293 | GCT_send_channel_destroy (ch->t, | ||
1294 | ch->ctn); | ||
1295 | return; | ||
1296 | } | ||
1297 | payload_size = ntohs (msg->header.size) - sizeof (*msg); | ||
1298 | env = GNUNET_MQ_msg_extra (ld, | ||
1299 | payload_size, | ||
1300 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1301 | ld->ccn = (NULL == ch->dest) ? ch->owner->ccn : ch->dest->ccn; | ||
1302 | GNUNET_memcpy (&ld[1], | ||
1303 | &msg[1], | ||
1304 | payload_size); | ||
1305 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; | ||
1306 | if ( (GNUNET_YES == ccc->client_ready) && | ||
1307 | ( (GNUNET_YES == ch->out_of_order) || | ||
1308 | (msg->mid.mid == ch->mid_recv.mid) ) ) | ||
1168 | { | 1309 | { |
1169 | GNUNET_break (GNUNET_NO != ch->destroy); | 1310 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1311 | "Giving %u bytes of payload with MID %u from %s to client %s\n", | ||
1312 | (unsigned int) payload_size, | ||
1313 | ntohl (msg->mid.mid), | ||
1314 | GCCH_2s (ch), | ||
1315 | GSC_2s (ccc->c)); | ||
1316 | ccc->client_ready = GNUNET_NO; | ||
1317 | GSC_send_to_client (ccc->c, | ||
1318 | env); | ||
1319 | ch->mid_recv.mid = htonl (1 + ntohl (ch->mid_recv.mid)); | ||
1320 | ch->mid_futures >>= 1; | ||
1321 | send_channel_data_ack (ch); | ||
1170 | return; | 1322 | return; |
1171 | } | 1323 | } |
1172 | LOG (GNUNET_ERROR_TYPE_DEBUG, " channel confirm %s %s\n", | ||
1173 | GC_f2s (fwd), GCCH_2s (ch)); | ||
1174 | oldstate = ch->state; | ||
1175 | ch->state = CADET_CHANNEL_READY; | ||
1176 | 1324 | ||
1177 | if (CADET_CHANNEL_READY != oldstate || GNUNET_YES == is_loopback (ch)) | 1325 | if (GNUNET_YES == ch->reliable) |
1178 | { | 1326 | { |
1179 | rel->client_ready = GNUNET_YES; | 1327 | /* check if message ought to be dropped because it is ancient/too distant/duplicate */ |
1180 | rel->expected_delay = rel->retry_timer; | 1328 | mid_min = ntohl (ch->mid_recv.mid); |
1181 | LOG (GNUNET_ERROR_TYPE_DEBUG, " confirm retry timer %s\n", | 1329 | mid_max = mid_min + ch->max_pending_messages; |
1182 | GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, GNUNET_NO)); | 1330 | mid_msg = ntohl (msg->mid.mid); |
1183 | if (GCT_get_connections_buffer (ch->t) > 0 || GCT_is_loopback (ch->t)) | 1331 | if ( ( (uint32_t) (mid_msg - mid_min) > ch->max_pending_messages) || |
1184 | send_client_ack (ch, fwd); | 1332 | ( (uint32_t) (mid_max - mid_msg) > ch->max_pending_messages) ) |
1185 | |||
1186 | if (NULL != rel->retry_task) | ||
1187 | { | 1333 | { |
1188 | GNUNET_SCHEDULER_cancel (rel->retry_task); | 1334 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1189 | rel->retry_task = NULL; | 1335 | "%s at %u drops ancient or far-future message %u\n", |
1190 | } | 1336 | GCCH_2s (ch), |
1191 | else if (NULL != rel->uniq) | 1337 | (unsigned int) mid_min, |
1192 | { | 1338 | ntohl (msg->mid.mid)); |
1193 | GCT_cancel (rel->uniq->tq); | 1339 | |
1194 | /* ch_message_sent will free and NULL uniq */ | 1340 | GNUNET_STATISTICS_update (stats, |
1341 | "# duplicate DATA (ancient or future)", | ||
1342 | 1, | ||
1343 | GNUNET_NO); | ||
1344 | GNUNET_MQ_discard (env); | ||
1345 | send_channel_data_ack (ch); | ||
1346 | return; | ||
1195 | } | 1347 | } |
1196 | else if (GNUNET_NO == is_loopback (ch)) | 1348 | /* mark bit for future ACKs */ |
1349 | delta = mid_msg - mid_min - 1; /* overflow/underflow are OK here */ | ||
1350 | if (delta < 64) | ||
1197 | { | 1351 | { |
1198 | /* We SHOULD have been trying to retransmit this! */ | 1352 | if (0 != (ch->mid_futures & (1LLU << delta))) |
1199 | GNUNET_break (0); | 1353 | { |
1354 | /* Duplicate within the queue, drop also */ | ||
1355 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1356 | "Duplicate payload of %u bytes on %s (mid %u) dropped\n", | ||
1357 | (unsigned int) payload_size, | ||
1358 | GCCH_2s (ch), | ||
1359 | ntohl (msg->mid.mid)); | ||
1360 | GNUNET_STATISTICS_update (stats, | ||
1361 | "# duplicate DATA", | ||
1362 | 1, | ||
1363 | GNUNET_NO); | ||
1364 | GNUNET_MQ_discard (env); | ||
1365 | send_channel_data_ack (ch); | ||
1366 | return; | ||
1367 | } | ||
1368 | ch->mid_futures |= (1LLU << delta); | ||
1369 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1370 | "Marked bit %llX for mid %u (base: %u); now: %llX\n", | ||
1371 | (1LLU << delta), | ||
1372 | mid_msg, | ||
1373 | mid_min, | ||
1374 | ch->mid_futures); | ||
1200 | } | 1375 | } |
1201 | } | 1376 | } |
1202 | 1377 | else /* ! ch->reliable */ | |
1203 | /* In case of a FWD ACK (SYNACK) send a BCK ACK (ACK). */ | ||
1204 | if (GNUNET_YES == fwd) | ||
1205 | send_ack (ch, GNUNET_NO); | ||
1206 | } | ||
1207 | |||
1208 | |||
1209 | /** | ||
1210 | * Save a copy to retransmit in case it gets lost. | ||
1211 | * | ||
1212 | * Initializes all needed callbacks and timers. | ||
1213 | * | ||
1214 | * @param ch Channel this message goes on. | ||
1215 | * @param msg Message to copy. | ||
1216 | * @param fwd Is this fwd traffic? | ||
1217 | */ | ||
1218 | static struct CadetReliableMessage * | ||
1219 | channel_save_copy (struct CadetChannel *ch, | ||
1220 | const struct GNUNET_MessageHeader *msg, | ||
1221 | int fwd) | ||
1222 | { | ||
1223 | struct CadetChannelReliability *rel; | ||
1224 | struct CadetReliableMessage *copy; | ||
1225 | uint32_t mid; | ||
1226 | uint16_t type; | ||
1227 | uint16_t size; | ||
1228 | |||
1229 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1230 | mid = rel->mid_send - 1; | ||
1231 | type = ntohs (msg->type); | ||
1232 | size = ntohs (msg->size); | ||
1233 | |||
1234 | LOG (GNUNET_ERROR_TYPE_DEBUG, "save MID %u %s\n", mid, GC_m2s (type)); | ||
1235 | copy = GNUNET_malloc (sizeof (struct CadetReliableMessage) + size); | ||
1236 | LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", copy); | ||
1237 | copy->mid = mid; | ||
1238 | copy->rel = rel; | ||
1239 | copy->type = type; | ||
1240 | GNUNET_memcpy (©[1], msg, size); | ||
1241 | GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy); | ||
1242 | ch->pending_messages++; | ||
1243 | |||
1244 | return copy; | ||
1245 | } | ||
1246 | |||
1247 | |||
1248 | /** | ||
1249 | * Create a new channel. | ||
1250 | * | ||
1251 | * @param t Tunnel this channel is in. | ||
1252 | * @param owner Client that owns the channel, NULL for foreign channels. | ||
1253 | * @param lid_root Local ID for root client. | ||
1254 | * | ||
1255 | * @return A new initialized channel. NULL on error. | ||
1256 | */ | ||
1257 | static struct CadetChannel * | ||
1258 | channel_new (struct CadetTunnel *t, | ||
1259 | struct CadetClient *owner, | ||
1260 | struct GNUNET_CADET_ClientChannelNumber lid_root) | ||
1261 | { | ||
1262 | struct CadetChannel *ch; | ||
1263 | |||
1264 | ch = GNUNET_new (struct CadetChannel); | ||
1265 | ch->root = owner; | ||
1266 | ch->lid_root = lid_root; | ||
1267 | ch->t = t; | ||
1268 | |||
1269 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
1270 | |||
1271 | if (NULL != owner) | ||
1272 | { | ||
1273 | ch->gid = GCT_get_next_ctn (t); | ||
1274 | GML_channel_add (owner, lid_root, ch); | ||
1275 | } | ||
1276 | GCT_add_channel (t, ch); | ||
1277 | |||
1278 | return ch; | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | /** | ||
1283 | * Handle a loopback message: call the appropriate handler for the message type. | ||
1284 | * | ||
1285 | * @param ch Channel this message is on. | ||
1286 | * @param msgh Message header. | ||
1287 | * @param fwd Is this FWD traffic? | ||
1288 | */ | ||
1289 | void | ||
1290 | handle_loopback (struct CadetChannel *ch, | ||
1291 | const struct GNUNET_MessageHeader *msgh, | ||
1292 | int fwd) | ||
1293 | { | ||
1294 | uint16_t type; | ||
1295 | |||
1296 | type = ntohs (msgh->type); | ||
1297 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1298 | "Loopback %s %s message!\n", | ||
1299 | GC_f2s (fwd), GC_m2s (type)); | ||
1300 | |||
1301 | switch (type) | ||
1302 | { | 1378 | { |
1303 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA: | 1379 | /* Channel is unreliable, so we do not ACK. But we also cannot |
1304 | /* Don't send hop ACK, wait for client to ACK */ | 1380 | allow buffering everything, so check if we have space... */ |
1305 | LOG (GNUNET_ERROR_TYPE_DEBUG, "SEND loopback %u (%u)\n", | 1381 | if (ccc->num_recv >= ch->max_pending_messages) |
1306 | ntohl (((struct GNUNET_CADET_ChannelAppDataMessage *) msgh)->mid), ntohs (msgh->size)); | 1382 | { |
1307 | GCCH_handle_data (ch, (struct GNUNET_CADET_ChannelAppDataMessage *) msgh, fwd); | 1383 | struct CadetOutOfOrderMessage *drop; |
1308 | break; | ||
1309 | |||
1310 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK: | ||
1311 | GCCH_handle_data_ack (ch, | ||
1312 | (const struct GNUNET_CADET_ChannelDataAckMessage *) msgh, fwd); | ||
1313 | break; | ||
1314 | |||
1315 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN: | ||
1316 | GCCH_handle_create (ch->t, | ||
1317 | (const struct GNUNET_CADET_ChannelOpenMessage *) msgh); | ||
1318 | break; | ||
1319 | |||
1320 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK: | ||
1321 | GCCH_handle_ack (ch, | ||
1322 | (const struct GNUNET_CADET_ChannelManageMessage *) msgh, | ||
1323 | fwd); | ||
1324 | break; | ||
1325 | |||
1326 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED: | ||
1327 | GCCH_handle_nack (ch); | ||
1328 | break; | ||
1329 | |||
1330 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
1331 | GCCH_handle_destroy (ch, | ||
1332 | (const struct GNUNET_CADET_ChannelManageMessage *) msgh, | ||
1333 | fwd); | ||
1334 | break; | ||
1335 | 1384 | ||
1336 | default: | 1385 | /* Yep, need to drop. Drop the oldest message in |
1337 | GNUNET_break_op (0); | 1386 | the buffer. */ |
1338 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1387 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1339 | "end-to-end message not known (%u)\n", | 1388 | "Queue full due slow client on %s, dropping oldest message\n", |
1340 | ntohs (msgh->type)); | 1389 | GCCH_2s (ch)); |
1390 | GNUNET_STATISTICS_update (stats, | ||
1391 | "# messages dropped due to slow client", | ||
1392 | 1, | ||
1393 | GNUNET_NO); | ||
1394 | drop = ccc->head_recv; | ||
1395 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, | ||
1396 | ccc->tail_recv, | ||
1397 | drop); | ||
1398 | ccc->num_recv--; | ||
1399 | GNUNET_MQ_discard (drop->env); | ||
1400 | GNUNET_free (drop); | ||
1401 | } | ||
1341 | } | 1402 | } |
1342 | } | ||
1343 | |||
1344 | |||
1345 | |||
1346 | /******************************************************************************/ | ||
1347 | /******************************** API ***********************************/ | ||
1348 | /******************************************************************************/ | ||
1349 | |||
1350 | /** | ||
1351 | * Destroy a channel and free all resources. | ||
1352 | * | ||
1353 | * @param ch Channel to destroy. | ||
1354 | */ | ||
1355 | void | ||
1356 | GCCH_destroy (struct CadetChannel *ch) | ||
1357 | { | ||
1358 | struct CadetClient *c; | ||
1359 | struct CadetTunnel *t; | ||
1360 | 1403 | ||
1361 | if (NULL == ch) | 1404 | /* Insert message into sorted out-of-order queue */ |
1405 | com = GNUNET_new (struct CadetOutOfOrderMessage); | ||
1406 | com->mid = msg->mid; | ||
1407 | com->env = env; | ||
1408 | duplicate = GNUNET_NO; | ||
1409 | GNUNET_CONTAINER_DLL_insert_sorted (struct CadetOutOfOrderMessage, | ||
1410 | is_before, | ||
1411 | &duplicate, | ||
1412 | ccc->head_recv, | ||
1413 | ccc->tail_recv, | ||
1414 | com); | ||
1415 | ccc->num_recv++; | ||
1416 | if (GNUNET_YES == duplicate) | ||
1417 | { | ||
1418 | /* Duplicate within the queue, drop also (this is not covered by | ||
1419 | the case above if "delta" >= 64, which could be the case if | ||
1420 | max_pending_messages is also >= 64 or if our client is unready | ||
1421 | and we are seeing retransmissions of the message our client is | ||
1422 | blocked on. */ | ||
1423 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1424 | "Duplicate payload of %u bytes on %s (mid %u) dropped\n", | ||
1425 | (unsigned int) payload_size, | ||
1426 | GCCH_2s (ch), | ||
1427 | ntohl (msg->mid.mid)); | ||
1428 | GNUNET_STATISTICS_update (stats, | ||
1429 | "# duplicate DATA", | ||
1430 | 1, | ||
1431 | GNUNET_NO); | ||
1432 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, | ||
1433 | ccc->tail_recv, | ||
1434 | com); | ||
1435 | ccc->num_recv--; | ||
1436 | GNUNET_MQ_discard (com->env); | ||
1437 | GNUNET_free (com); | ||
1438 | send_channel_data_ack (ch); | ||
1362 | return; | 1439 | return; |
1363 | if (2 == ch->destroy) | ||
1364 | return; /* recursive call */ | ||
1365 | ch->destroy = 2; | ||
1366 | |||
1367 | LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying channel %s:%u\n", | ||
1368 | GCT_2s (ch->t), ch->gid); | ||
1369 | GCCH_debug (ch, GNUNET_ERROR_TYPE_DEBUG); | ||
1370 | |||
1371 | c = ch->root; | ||
1372 | if (NULL != c) | ||
1373 | { | ||
1374 | GML_channel_remove (c, ch->lid_root, ch); | ||
1375 | } | 1440 | } |
1376 | 1441 | LOG (GNUNET_ERROR_TYPE_DEBUG, | |
1377 | c = ch->dest; | 1442 | "Queued %s payload of %u bytes on %s-%X(%p) (mid %u, need %u first)\n", |
1378 | if (NULL != c) | 1443 | (GNUNET_YES == ccc->client_ready) |
1379 | { | 1444 | ? "out-of-order" |
1380 | GML_channel_remove (c, ch->lid_dest, ch); | 1445 | : "client-not-ready", |
1381 | } | 1446 | (unsigned int) payload_size, |
1382 | 1447 | GCCH_2s (ch), | |
1383 | channel_rel_free_all (ch->root_rel); | 1448 | ntohl (ccc->ccn.channel_of_client), |
1384 | channel_rel_free_all (ch->dest_rel); | 1449 | ccc, |
1385 | 1450 | ntohl (msg->mid.mid), | |
1386 | t = ch->t; | 1451 | ntohl (ch->mid_recv.mid)); |
1387 | GCT_remove_channel (t, ch); | 1452 | /* NOTE: this ACK we _could_ skip, as the packet is out-of-order and |
1388 | GNUNET_STATISTICS_update (stats, "# channels", -1, GNUNET_NO); | 1453 | the sender may already be transmitting the previous one. Needs |
1389 | 1454 | experimental evaluation to see if/when this ACK helps or | |
1390 | GNUNET_free (ch); | 1455 | hurts. (We might even want another option.) */ |
1391 | GCT_destroy_if_empty (t); | 1456 | send_channel_data_ack (ch); |
1392 | } | ||
1393 | |||
1394 | |||
1395 | /** | ||
1396 | * Get the channel's public ID. | ||
1397 | * | ||
1398 | * @param ch Channel. | ||
1399 | * | ||
1400 | * @return ID used to identify the channel with the remote peer. | ||
1401 | */ | ||
1402 | struct GNUNET_CADET_ChannelTunnelNumber | ||
1403 | GCCH_get_id (const struct CadetChannel *ch) | ||
1404 | { | ||
1405 | return ch->gid; | ||
1406 | } | ||
1407 | |||
1408 | |||
1409 | /** | ||
1410 | * Get the channel tunnel. | ||
1411 | * | ||
1412 | * @param ch Channel to get the tunnel from. | ||
1413 | * | ||
1414 | * @return tunnel of the channel. | ||
1415 | */ | ||
1416 | struct CadetTunnel * | ||
1417 | GCCH_get_tunnel (const struct CadetChannel *ch) | ||
1418 | { | ||
1419 | return ch->t; | ||
1420 | } | ||
1421 | |||
1422 | |||
1423 | /** | ||
1424 | * Get free buffer space towards the client on a specific channel. | ||
1425 | * | ||
1426 | * @param ch Channel. | ||
1427 | * @param fwd Is query about FWD traffic? | ||
1428 | * | ||
1429 | * @return Free buffer space [0 - 64] | ||
1430 | */ | ||
1431 | unsigned int | ||
1432 | GCCH_get_buffer (struct CadetChannel *ch, int fwd) | ||
1433 | { | ||
1434 | struct CadetChannelReliability *rel; | ||
1435 | |||
1436 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
1437 | LOG (GNUNET_ERROR_TYPE_DEBUG, " get buffer, channel %s\n", GCCH_2s (ch)); | ||
1438 | GCCH_debug (ch, GNUNET_ERROR_TYPE_DEBUG); | ||
1439 | /* If rel is NULL it means that the end is not yet created, | ||
1440 | * most probably is a loopback channel at the point of sending | ||
1441 | * the ChannelCreate to itself. | ||
1442 | */ | ||
1443 | if (NULL == rel) | ||
1444 | { | ||
1445 | LOG (GNUNET_ERROR_TYPE_DEBUG, " rel is NULL: max\n"); | ||
1446 | return 64; | ||
1447 | } | ||
1448 | |||
1449 | LOG (GNUNET_ERROR_TYPE_DEBUG, " n_recv %d\n", rel->n_recv); | ||
1450 | return (64 - rel->n_recv); | ||
1451 | } | ||
1452 | |||
1453 | |||
1454 | /** | ||
1455 | * Get flow control status of end point: is client allow to send? | ||
1456 | * | ||
1457 | * @param ch Channel. | ||
1458 | * @param fwd Is query about FWD traffic? (Request root status). | ||
1459 | * | ||
1460 | * @return #GNUNET_YES if client is allowed to send us data. | ||
1461 | */ | ||
1462 | int | ||
1463 | GCCH_get_allowed (struct CadetChannel *ch, int fwd) | ||
1464 | { | ||
1465 | struct CadetChannelReliability *rel; | ||
1466 | |||
1467 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1468 | |||
1469 | if (NULL == rel) | ||
1470 | { | ||
1471 | /* Probably shutting down: root/dest NULL'ed to mark disconnection */ | ||
1472 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
1473 | return 0; | ||
1474 | } | ||
1475 | |||
1476 | return rel->client_allowed; | ||
1477 | } | 1457 | } |
1478 | 1458 | ||
1479 | 1459 | ||
1480 | /** | 1460 | /** |
1481 | * Is the root client for this channel on this peer? | 1461 | * Function called once the tunnel has sent one of our messages. |
1482 | * | 1462 | * If the message is unreliable, simply frees the `crm`. If the |
1483 | * @param ch Channel. | 1463 | * message was reliable, calculate retransmission time and |
1484 | * @param fwd Is this for fwd traffic? | 1464 | * wait for ACK (or retransmit). |
1485 | * | 1465 | * |
1486 | * @return #GNUNET_YES in case it is. | 1466 | * @param cls the `struct CadetReliableMessage` that was sent |
1467 | * @param cid identifier of the connection within the tunnel, NULL | ||
1468 | * if transmission failed | ||
1487 | */ | 1469 | */ |
1488 | int | 1470 | static void |
1489 | GCCH_is_origin (struct CadetChannel *ch, int fwd) | 1471 | data_sent_cb (void *cls, |
1490 | { | 1472 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); |
1491 | struct CadetClient *c; | ||
1492 | |||
1493 | c = fwd ? ch->root : ch->dest; | ||
1494 | return NULL != c; | ||
1495 | } | ||
1496 | 1473 | ||
1497 | 1474 | ||
1498 | /** | 1475 | /** |
1499 | * Is the destination client for this channel on this peer? | 1476 | * We need to retry a transmission, the last one took too long to |
1500 | * | 1477 | * be acknowledged. |
1501 | * @param ch Channel. | ||
1502 | * @param fwd Is this for fwd traffic? | ||
1503 | * | 1478 | * |
1504 | * @return #GNUNET_YES in case it is. | 1479 | * @param cls the `struct CadetChannel` where we need to retransmit |
1505 | */ | 1480 | */ |
1506 | int | 1481 | static void |
1507 | GCCH_is_terminal (struct CadetChannel *ch, int fwd) | 1482 | retry_transmission (void *cls) |
1508 | { | 1483 | { |
1509 | struct CadetClient *c; | 1484 | struct CadetChannel *ch = cls; |
1485 | struct CadetReliableMessage *crm = ch->head_sent; | ||
1510 | 1486 | ||
1511 | c = fwd ? ch->dest : ch->root; | 1487 | ch->retry_data_task = NULL; |
1512 | return NULL != c; | 1488 | GNUNET_assert (NULL == crm->qe); |
1489 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1490 | "Retrying transmission on %s of message %u\n", | ||
1491 | GCCH_2s (ch), | ||
1492 | (unsigned int) ntohl (crm->data_message->mid.mid)); | ||
1493 | crm->qe = GCT_send (ch->t, | ||
1494 | &crm->data_message->header, | ||
1495 | &data_sent_cb, | ||
1496 | crm); | ||
1497 | GNUNET_assert (NULL == ch->retry_data_task); | ||
1513 | } | 1498 | } |
1514 | 1499 | ||
1515 | 1500 | ||
1516 | /** | 1501 | /** |
1517 | * Send an end-to-end ACK message for the most recent in-sequence payload. | 1502 | * We got an PLAINTEXT_DATA_ACK for a message in our queue, remove it from |
1518 | * | 1503 | * the queue and tell our client that it can send more. |
1519 | * If channel is not reliable, do nothing. | ||
1520 | * | 1504 | * |
1521 | * @param ch Channel this is about. | 1505 | * @param ch the channel that got the PLAINTEXT_DATA_ACK |
1522 | * @param fwd Is for FWD traffic? (ACK dest->owner) | 1506 | * @param cti identifier of the connection that delivered the message |
1507 | * @param crm the message that got acknowledged | ||
1523 | */ | 1508 | */ |
1524 | void | 1509 | static void |
1525 | GCCH_send_data_ack (struct CadetChannel *ch, int fwd) | 1510 | handle_matching_ack (struct CadetChannel *ch, |
1511 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1512 | struct CadetReliableMessage *crm) | ||
1526 | { | 1513 | { |
1527 | struct GNUNET_CADET_ChannelDataAckMessage msg; | 1514 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, |
1528 | struct CadetChannelReliability *rel; | 1515 | ch->tail_sent, |
1529 | struct CadetReliableMessage *copy; | 1516 | crm); |
1530 | unsigned int delta; | 1517 | ch->pending_messages--; |
1531 | uint64_t mask; | 1518 | GNUNET_assert (ch->pending_messages < ch->max_pending_messages); |
1532 | uint32_t ack; | 1519 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1533 | 1520 | "Received DATA_ACK on %s for message %u (%u ACKs pending)\n", | |
1534 | if (GNUNET_NO == ch->reliable) | 1521 | GCCH_2s (ch), |
1535 | return; | 1522 | (unsigned int) ntohl (crm->data_message->mid.mid), |
1536 | 1523 | ch->pending_messages); | |
1537 | rel = fwd ? ch->dest_rel : ch->root_rel; | 1524 | if (NULL != crm->qe) |
1538 | ack = rel->mid_recv - 1; | 1525 | { |
1539 | 1526 | GCT_send_cancel (crm->qe); | |
1540 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK); | 1527 | crm->qe = NULL; |
1541 | msg.header.size = htons (sizeof (msg)); | 1528 | } |
1542 | msg.ctn = ch->gid; | 1529 | if ( (1 == crm->num_transmissions) && |
1543 | msg.mid = htonl (ack); | 1530 | (NULL != cti) ) |
1544 | 1531 | { | |
1545 | msg.futures = 0LL; | 1532 | GCC_ack_observed (cti); |
1546 | for (copy = rel->head_recv; NULL != copy; copy = copy->next) | 1533 | if (0 == memcmp (cti, |
1547 | { | 1534 | &crm->connection_taken, |
1548 | if (copy->type != GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA) | 1535 | sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier))) |
1549 | { | 1536 | { |
1550 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Type %s, expected DATA\n", | 1537 | GCC_latency_observed (cti, |
1551 | GC_m2s (copy->type)); | 1538 | GNUNET_TIME_absolute_get_duration (crm->first_transmission_time)); |
1552 | continue; | ||
1553 | } | 1539 | } |
1554 | GNUNET_assert (GC_is_pid_bigger(copy->mid, ack)); | ||
1555 | delta = copy->mid - (ack + 1); | ||
1556 | if (63 < delta) | ||
1557 | break; | ||
1558 | mask = 0x1LL << delta; | ||
1559 | msg.futures |= mask; | ||
1560 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1561 | " setting bit for %u (delta %u) (%lX) -> %lX\n", | ||
1562 | copy->mid, delta, mask, msg.futures); | ||
1563 | } | 1540 | } |
1564 | 1541 | GNUNET_free (crm->data_message); | |
1565 | GCCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL); | 1542 | GNUNET_free (crm); |
1566 | LOG (GNUNET_ERROR_TYPE_DEBUG, "send_data_ack END\n"); | 1543 | send_ack_to_client (ch, |
1544 | (NULL == ch->owner) | ||
1545 | ? GNUNET_NO | ||
1546 | : GNUNET_YES); | ||
1567 | } | 1547 | } |
1568 | 1548 | ||
1569 | 1549 | ||
1570 | /** | 1550 | /** |
1571 | * Allow a client to send us more data, in case it was choked. | 1551 | * We got an acknowledgement for payload data for a channel. |
1552 | * Possibly resume transmissions. | ||
1572 | * | 1553 | * |
1573 | * @param ch Channel. | 1554 | * @param ch channel that got the ack |
1574 | * @param fwd Is this about FWD traffic? (Root client). | 1555 | * @param cti identifier of the connection that delivered the message |
1556 | * @param ack details about what was received | ||
1575 | */ | 1557 | */ |
1576 | void | 1558 | void |
1577 | GCCH_allow_client (struct CadetChannel *ch, int fwd) | 1559 | GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch, |
1560 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
1561 | const struct GNUNET_CADET_ChannelDataAckMessage *ack) | ||
1578 | { | 1562 | { |
1579 | struct CadetChannelReliability *rel; | 1563 | struct CadetReliableMessage *crm; |
1580 | unsigned int buffer; | 1564 | struct CadetReliableMessage *crmn; |
1581 | 1565 | int found; | |
1582 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMCH allow\n"); | 1566 | uint32_t mid_base; |
1567 | uint64_t mid_mask; | ||
1568 | unsigned int delta; | ||
1583 | 1569 | ||
1584 | if (CADET_CHANNEL_READY != ch->state) | 1570 | GNUNET_break (GNUNET_NO == ch->is_loopback); |
1571 | if (GNUNET_NO == ch->reliable) | ||
1585 | { | 1572 | { |
1586 | LOG (GNUNET_ERROR_TYPE_DEBUG, " channel not ready yet!\n"); | 1573 | /* not expecting ACKs on unreliable channel, odd */ |
1574 | GNUNET_break_op (0); | ||
1587 | return; | 1575 | return; |
1588 | } | 1576 | } |
1589 | 1577 | /* mid_base is the MID of the next message that the | |
1590 | if (GNUNET_YES == ch->reliable) | 1578 | other peer expects (i.e. that is missing!), everything |
1591 | { | 1579 | LOWER (but excluding mid_base itself) was received. */ |
1592 | rel = fwd ? ch->root_rel : ch->dest_rel; | 1580 | mid_base = ntohl (ack->mid.mid); |
1593 | if (NULL == rel) | 1581 | mid_mask = GNUNET_htonll (ack->futures); |
1582 | found = GNUNET_NO; | ||
1583 | for (crm = ch->head_sent; | ||
1584 | NULL != crm; | ||
1585 | crm = crmn) | ||
1586 | { | ||
1587 | crmn = crm->next; | ||
1588 | delta = (unsigned int) (ntohl (crm->data_message->mid.mid) - mid_base); | ||
1589 | if (delta >= UINT_MAX - ch->max_pending_messages) | ||
1594 | { | 1590 | { |
1595 | GNUNET_break (GNUNET_NO != ch->destroy); | 1591 | /* overflow, means crm was a bit in the past, so this ACK counts for it. */ |
1596 | return; | 1592 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1597 | } | 1593 | "Got DATA_ACK with base %u satisfying past message %u on %s\n", |
1598 | if (NULL != rel->head_sent) | 1594 | (unsigned int) mid_base, |
1599 | { | 1595 | ntohl (crm->data_message->mid.mid), |
1600 | if (64 <= rel->mid_send - rel->head_sent->mid) | 1596 | GCCH_2s (ch)); |
1601 | { | 1597 | handle_matching_ack (ch, |
1602 | LOG (GNUNET_ERROR_TYPE_DEBUG, " too big MID gap! Wait for ACK.\n"); | 1598 | cti, |
1603 | return; | 1599 | crm); |
1604 | } | 1600 | found = GNUNET_YES; |
1605 | else | 1601 | continue; |
1606 | { | ||
1607 | LOG (GNUNET_ERROR_TYPE_DEBUG, " gap ok: %u - %u\n", | ||
1608 | rel->head_sent->mid, rel->mid_send); | ||
1609 | struct CadetReliableMessage *aux; | ||
1610 | for (aux = rel->head_sent; NULL != aux; aux = aux->next) | ||
1611 | { | ||
1612 | LOG (GNUNET_ERROR_TYPE_DEBUG, " - sent mid %u\n", aux->mid); | ||
1613 | } | ||
1614 | } | ||
1615 | } | 1602 | } |
1616 | else | 1603 | delta--; |
1604 | if (delta >= 64) | ||
1605 | continue; | ||
1606 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1607 | "Testing bit %llX for mid %u (base: %u)\n", | ||
1608 | (1LLU << delta), | ||
1609 | ntohl (crm->data_message->mid.mid), | ||
1610 | mid_base); | ||
1611 | if (0 != (mid_mask & (1LLU << delta))) | ||
1617 | { | 1612 | { |
1618 | LOG (GNUNET_ERROR_TYPE_DEBUG, " head sent is NULL\n"); | 1613 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1614 | "Got DATA_ACK with mask for %u on %s\n", | ||
1615 | ntohl (crm->data_message->mid.mid), | ||
1616 | GCCH_2s (ch)); | ||
1617 | handle_matching_ack (ch, | ||
1618 | cti, | ||
1619 | crm); | ||
1620 | found = GNUNET_YES; | ||
1619 | } | 1621 | } |
1620 | } | 1622 | } |
1621 | 1623 | if (GNUNET_NO == found) | |
1622 | if (is_loopback (ch)) | ||
1623 | buffer = GCCH_get_buffer (ch, fwd); | ||
1624 | else | ||
1625 | buffer = GCT_get_connections_buffer (ch->t); | ||
1626 | |||
1627 | if (0 == buffer) | ||
1628 | { | 1624 | { |
1629 | LOG (GNUNET_ERROR_TYPE_DEBUG, " no buffer space.\n"); | 1625 | /* ACK for message we already dropped, might have been a |
1626 | duplicate ACK? Ignore. */ | ||
1627 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1628 | "Duplicate DATA_ACK on %s, ignoring\n", | ||
1629 | GCCH_2s (ch)); | ||
1630 | GNUNET_STATISTICS_update (stats, | ||
1631 | "# duplicate DATA_ACKs", | ||
1632 | 1, | ||
1633 | GNUNET_NO); | ||
1630 | return; | 1634 | return; |
1631 | } | 1635 | } |
1632 | 1636 | if (NULL != ch->retry_data_task) | |
1633 | LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space %u, allowing\n", buffer); | 1637 | { |
1634 | send_client_ack (ch, fwd); | 1638 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); |
1639 | ch->retry_data_task = NULL; | ||
1640 | } | ||
1641 | if ( (NULL != ch->head_sent) && | ||
1642 | (NULL == ch->head_sent->qe) ) | ||
1643 | ch->retry_data_task | ||
1644 | = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry, | ||
1645 | &retry_transmission, | ||
1646 | ch); | ||
1635 | } | 1647 | } |
1636 | 1648 | ||
1637 | 1649 | ||
1638 | /** | 1650 | /** |
1639 | * Log channel info. | 1651 | * Destroy channel, based on the other peer closing the |
1652 | * connection. Also needs to remove this channel from | ||
1653 | * the tunnel. | ||
1640 | * | 1654 | * |
1641 | * @param ch Channel. | 1655 | * @param ch channel to destroy |
1642 | * @param level Debug level to use. | 1656 | * @param cti identifier of the connection that delivered the message, |
1657 | * NULL if we are simulating receiving a destroy due to shutdown | ||
1643 | */ | 1658 | */ |
1644 | void | 1659 | void |
1645 | GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level) | 1660 | GCCH_handle_remote_destroy (struct CadetChannel *ch, |
1661 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti) | ||
1646 | { | 1662 | { |
1647 | int do_log; | 1663 | struct CadetChannelClient *ccc; |
1648 | 1664 | ||
1649 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | 1665 | GNUNET_assert (GNUNET_NO == ch->is_loopback); |
1650 | "cadet-chn", | 1666 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1651 | __FILE__, __FUNCTION__, __LINE__); | 1667 | "Received remote channel DESTROY for %s\n", |
1652 | if (0 == do_log) | 1668 | GCCH_2s (ch)); |
1653 | return; | 1669 | if (GNUNET_YES == ch->destroy) |
1654 | |||
1655 | if (NULL == ch) | ||
1656 | { | 1670 | { |
1657 | LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n"); | 1671 | /* Local client already gone, this is instant-death. */ |
1672 | channel_destroy (ch); | ||
1658 | return; | 1673 | return; |
1659 | } | 1674 | } |
1660 | LOG2 (level, "CHN Channel %s:%X (%p)\n", GCT_2s (ch->t), ch->gid, ch); | 1675 | ccc = (NULL != ch->owner) ? ch->owner : ch->dest; |
1661 | LOG2 (level, "CHN root %p/%p\n", ch->root, ch->root_rel); | 1676 | if ( (NULL != ccc) && |
1662 | if (NULL != ch->root) | 1677 | (NULL != ccc->head_recv) ) |
1663 | { | ||
1664 | LOG2 (level, "CHN cli %s\n", GML_2s (ch->root)); | ||
1665 | LOG2 (level, "CHN ready %s\n", ch->root_rel->client_ready ? "YES" : "NO"); | ||
1666 | LOG2 (level, "CHN id %X\n", ch->lid_root.channel_of_client); | ||
1667 | LOG2 (level, "CHN recv %d\n", ch->root_rel->n_recv); | ||
1668 | LOG2 (level, "CHN MID r: %d, s: %d\n", | ||
1669 | ch->root_rel->mid_recv, ch->root_rel->mid_send); | ||
1670 | } | ||
1671 | LOG2 (level, "CHN dest %p/%p\n", | ||
1672 | ch->dest, ch->dest_rel); | ||
1673 | if (NULL != ch->dest) | ||
1674 | { | 1678 | { |
1675 | LOG2 (level, "CHN cli %s\n", GML_2s (ch->dest)); | 1679 | LOG (GNUNET_ERROR_TYPE_WARNING, |
1676 | LOG2 (level, "CHN ready %s\n", ch->dest_rel->client_ready ? "YES" : "NO"); | 1680 | "Lost end of transmission due to remote shutdown on %s\n", |
1677 | LOG2 (level, "CHN id %X\n", ch->lid_dest); | 1681 | GCCH_2s (ch)); |
1678 | LOG2 (level, "CHN recv %d\n", ch->dest_rel->n_recv); | 1682 | /* FIXME: change API to notify client about truncated transmission! */ |
1679 | LOG2 (level, "CHN MID r: %d, s: %d\n", | ||
1680 | ch->dest_rel->mid_recv, ch->dest_rel->mid_send); | ||
1681 | |||
1682 | } | 1683 | } |
1684 | ch->destroy = GNUNET_YES; | ||
1685 | if (NULL != ccc) | ||
1686 | GSC_handle_remote_channel_destroy (ccc->c, | ||
1687 | ccc->ccn, | ||
1688 | ch); | ||
1689 | channel_destroy (ch); | ||
1683 | } | 1690 | } |
1684 | 1691 | ||
1685 | 1692 | ||
1686 | /** | 1693 | /** |
1687 | * Handle an ACK given by a client. | 1694 | * Test if element @a e1 comes before element @a e2. |
1688 | * | 1695 | * |
1689 | * Mark client as ready and send him any buffered data we could have for him. | 1696 | * @param cls closure, to a flag where we indicate duplicate packets |
1690 | * | 1697 | * @param crm1 an element of to sort |
1691 | * @param ch Channel. | 1698 | * @param crm2 another element to sort |
1692 | * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by dest and go BCK) | 1699 | * @return #GNUNET_YES if @e1 < @e2, otherwise #GNUNET_NO |
1693 | */ | 1700 | */ |
1694 | void | 1701 | static int |
1695 | GCCH_handle_local_ack (struct CadetChannel *ch, int fwd) | 1702 | cmp_crm_by_next_retry (void *cls, |
1703 | struct CadetReliableMessage *crm1, | ||
1704 | struct CadetReliableMessage *crm2) | ||
1696 | { | 1705 | { |
1697 | struct CadetChannelReliability *rel; | 1706 | if (crm1->next_retry.abs_value_us < |
1698 | struct CadetClient *c; | 1707 | crm2->next_retry.abs_value_us) |
1699 | 1708 | return GNUNET_YES; | |
1700 | rel = fwd ? ch->dest_rel : ch->root_rel; | 1709 | return GNUNET_NO; |
1701 | c = fwd ? ch->dest : ch->root; | ||
1702 | |||
1703 | rel->client_ready = GNUNET_YES; | ||
1704 | send_client_buffered_data (ch, c, fwd); | ||
1705 | |||
1706 | if (GNUNET_YES == ch->destroy && 0 == rel->n_recv) | ||
1707 | { | ||
1708 | send_destroy (ch, GNUNET_YES); | ||
1709 | GCCH_destroy (ch); | ||
1710 | return; | ||
1711 | } | ||
1712 | /* if loopback is marked for destruction, no need to ACK to the other peer, | ||
1713 | * it requested the destruction and is already gone, therefore, else if. | ||
1714 | */ | ||
1715 | else if (is_loopback (ch)) | ||
1716 | { | ||
1717 | unsigned int buffer; | ||
1718 | |||
1719 | buffer = GCCH_get_buffer (ch, fwd); | ||
1720 | if (0 < buffer) | ||
1721 | GCCH_allow_client (ch, fwd); | ||
1722 | |||
1723 | return; | ||
1724 | } | ||
1725 | GCT_send_connection_acks (ch->t); | ||
1726 | } | 1710 | } |
1727 | 1711 | ||
1728 | 1712 | ||
1729 | /** | 1713 | /** |
1730 | * Handle data given by a client. | 1714 | * Function called once the tunnel has sent one of our messages. |
1731 | * | 1715 | * If the message is unreliable, simply frees the `crm`. If the |
1732 | * Check whether the client is allowed to send in this tunnel, save if channel | 1716 | * message was reliable, calculate retransmission time and |
1733 | * is reliable and send an ACK to the client if there is still buffer space | 1717 | * wait for ACK (or retransmit). |
1734 | * in the tunnel. | 1718 | * |
1735 | * | 1719 | * @param cls the `struct CadetReliableMessage` that was sent |
1736 | * @param ch Channel. | 1720 | * @param cid identifier of the connection within the tunnel, NULL |
1737 | * @param c Client which sent the data. | 1721 | * if transmission failed |
1738 | * @param fwd Is this a FWD data? | ||
1739 | * @param message Data message. | ||
1740 | * @param size Size of data. | ||
1741 | * | ||
1742 | * @return #GNUNET_OK if everything goes well, #GNUNET_SYSERR in case of en error. | ||
1743 | */ | 1722 | */ |
1744 | int | 1723 | static void |
1745 | GCCH_handle_local_data (struct CadetChannel *ch, | 1724 | data_sent_cb (void *cls, |
1746 | struct CadetClient *c, | 1725 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) |
1747 | int fwd, | ||
1748 | const struct GNUNET_MessageHeader *message, | ||
1749 | size_t size) | ||
1750 | { | 1726 | { |
1751 | struct CadetChannelReliability *rel; | 1727 | struct CadetReliableMessage *crm = cls; |
1752 | struct GNUNET_CADET_ChannelAppDataMessage *payload; | 1728 | struct CadetChannel *ch = crm->ch; |
1753 | uint16_t p2p_size = sizeof(struct GNUNET_CADET_ChannelAppDataMessage) + size; | 1729 | |
1754 | unsigned char cbuf[p2p_size]; | 1730 | GNUNET_assert (GNUNET_NO == ch->is_loopback); |
1755 | unsigned char buffer; | 1731 | GNUNET_assert (NULL != crm->qe); |
1756 | 1732 | crm->qe = NULL; | |
1757 | /* Is the client in the channel? */ | 1733 | GNUNET_CONTAINER_DLL_remove (ch->head_sent, |
1758 | if ( !( (fwd && | 1734 | ch->tail_sent, |
1759 | ch->root == c) | 1735 | crm); |
1760 | || | 1736 | if (GNUNET_NO == ch->reliable) |
1761 | (!fwd && | ||
1762 | ch->dest == c) ) ) | ||
1763 | { | 1737 | { |
1764 | GNUNET_break_op (0); | 1738 | GNUNET_free (crm->data_message); |
1765 | return GNUNET_SYSERR; | 1739 | GNUNET_free (crm); |
1740 | ch->pending_messages--; | ||
1741 | send_ack_to_client (ch, | ||
1742 | (NULL == ch->owner) | ||
1743 | ? GNUNET_NO | ||
1744 | : GNUNET_YES); | ||
1745 | return; | ||
1766 | } | 1746 | } |
1767 | 1747 | if (NULL == cid) | |
1768 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1769 | |||
1770 | if (GNUNET_NO == rel->client_allowed) | ||
1771 | { | 1748 | { |
1772 | GNUNET_break_op (0); | 1749 | /* There was an error sending. */ |
1773 | return GNUNET_SYSERR; | 1750 | crm->num_transmissions = GNUNET_SYSERR; |
1774 | } | 1751 | } |
1775 | 1752 | else if (GNUNET_SYSERR != crm->num_transmissions) | |
1776 | rel->client_allowed = GNUNET_NO; | ||
1777 | |||
1778 | /* Ok, everything is correct, send the message. */ | ||
1779 | payload = (struct GNUNET_CADET_ChannelAppDataMessage *) cbuf; | ||
1780 | payload->mid = htonl (rel->mid_send); | ||
1781 | rel->mid_send++; | ||
1782 | GNUNET_memcpy (&payload[1], message, size); | ||
1783 | payload->header.size = htons (p2p_size); | ||
1784 | payload->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA); | ||
1785 | payload->ctn = ch->gid; | ||
1786 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n"); | ||
1787 | GCCH_send_prebuilt_message (&payload->header, ch, fwd, NULL); | ||
1788 | |||
1789 | if (is_loopback (ch)) | ||
1790 | buffer = GCCH_get_buffer (ch, fwd); | ||
1791 | else | ||
1792 | buffer = GCT_get_connections_buffer (ch->t); | ||
1793 | |||
1794 | if (0 < buffer) | ||
1795 | GCCH_allow_client (ch, fwd); | ||
1796 | |||
1797 | return GNUNET_OK; | ||
1798 | } | ||
1799 | |||
1800 | |||
1801 | /** | ||
1802 | * Handle a channel destroy requested by a client. | ||
1803 | * | ||
1804 | * TODO: add "reason" field | ||
1805 | * | ||
1806 | * Destroy the channel and the tunnel in case this was the last channel. | ||
1807 | * | ||
1808 | * @param ch Channel. | ||
1809 | * @param c Client that requested the destruction (to avoid notifying him). | ||
1810 | * @param is_root Is the request coming from root? | ||
1811 | */ | ||
1812 | void | ||
1813 | GCCH_handle_local_destroy (struct CadetChannel *ch, | ||
1814 | struct CadetClient *c, | ||
1815 | int is_root) | ||
1816 | { | ||
1817 | ch->destroy = GNUNET_YES; | ||
1818 | /* Cleanup after the tunnel */ | ||
1819 | if (GNUNET_NO == is_root && c == ch->dest) | ||
1820 | { | 1753 | { |
1821 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is destination.\n", GML_2s (c)); | 1754 | /* Increment transmission counter, and possibly store @a cid |
1822 | GML_client_delete_channel (c, ch, ch->lid_dest); | 1755 | if this was the first transmission. */ |
1823 | ch->dest = NULL; | 1756 | crm->num_transmissions++; |
1757 | if (1 == crm->num_transmissions) | ||
1758 | { | ||
1759 | crm->first_transmission_time = GNUNET_TIME_absolute_get (); | ||
1760 | crm->connection_taken = *cid; | ||
1761 | GCC_ack_expected (cid); | ||
1762 | } | ||
1824 | } | 1763 | } |
1825 | if (GNUNET_YES == is_root && c == ch->root) | 1764 | if ( (0 == crm->retry_delay.rel_value_us) && |
1765 | (NULL != cid) ) | ||
1826 | { | 1766 | { |
1827 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is owner.\n", GML_2s (c)); | 1767 | struct CadetConnection *cc = GCC_lookup (cid); |
1828 | GML_client_delete_channel (c, ch, ch->lid_root); | ||
1829 | ch->root = NULL; | ||
1830 | } | ||
1831 | 1768 | ||
1832 | send_destroy (ch, GNUNET_NO); | 1769 | if (NULL != cc) |
1833 | if (0 == ch->pending_messages) | 1770 | crm->retry_delay = GCC_get_metrics (cc)->aged_latency; |
1834 | GCCH_destroy (ch); | 1771 | else |
1772 | crm->retry_delay = ch->retry_time; | ||
1773 | } | ||
1774 | crm->retry_delay = GNUNET_TIME_STD_BACKOFF (crm->retry_delay); | ||
1775 | crm->retry_delay = GNUNET_TIME_relative_max (crm->retry_delay, | ||
1776 | MIN_RTT_DELAY); | ||
1777 | crm->next_retry = GNUNET_TIME_relative_to_absolute (crm->retry_delay); | ||
1778 | |||
1779 | GNUNET_CONTAINER_DLL_insert_sorted (struct CadetReliableMessage, | ||
1780 | cmp_crm_by_next_retry, | ||
1781 | NULL, | ||
1782 | ch->head_sent, | ||
1783 | ch->tail_sent, | ||
1784 | crm); | ||
1785 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1786 | "Message %u sent, next transmission on %s in %s\n", | ||
1787 | (unsigned int) ntohl (crm->data_message->mid.mid), | ||
1788 | GCCH_2s (ch), | ||
1789 | GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (ch->head_sent->next_retry), | ||
1790 | GNUNET_YES)); | ||
1791 | if (NULL == ch->head_sent->qe) | ||
1792 | { | ||
1793 | if (NULL != ch->retry_data_task) | ||
1794 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1795 | ch->retry_data_task | ||
1796 | = GNUNET_SCHEDULER_add_at (ch->head_sent->next_retry, | ||
1797 | &retry_transmission, | ||
1798 | ch); | ||
1799 | } | ||
1835 | } | 1800 | } |
1836 | 1801 | ||
1837 | 1802 | ||
1838 | /** | 1803 | /** |
1839 | * Handle a channel create requested by a client. | 1804 | * Handle data given by a client. |
1840 | * | ||
1841 | * Create the channel and the tunnel in case this was the first0 channel. | ||
1842 | * | 1805 | * |
1843 | * @param c Client that requested the creation (will be the root). | 1806 | * Check whether the client is allowed to send in this tunnel, save if |
1844 | * @param msg Create Channel message. | 1807 | * channel is reliable and send an ACK to the client if there is still |
1808 | * buffer space in the tunnel. | ||
1845 | * | 1809 | * |
1846 | * @return #GNUNET_OK if everything went fine, #GNUNET_SYSERR otherwise. | 1810 | * @param ch Channel. |
1811 | * @param sender_ccn ccn of the sender | ||
1812 | * @param buf payload to transmit. | ||
1813 | * @param buf_len number of bytes in @a buf | ||
1814 | * @return #GNUNET_OK if everything goes well, | ||
1815 | * #GNUNET_SYSERR in case of an error. | ||
1847 | */ | 1816 | */ |
1848 | int | 1817 | int |
1849 | GCCH_handle_local_create (struct CadetClient *c, | 1818 | GCCH_handle_local_data (struct CadetChannel *ch, |
1850 | struct GNUNET_CADET_LocalChannelCreateMessage *msg) | 1819 | struct GNUNET_CADET_ClientChannelNumber sender_ccn, |
1820 | const char *buf, | ||
1821 | size_t buf_len) | ||
1851 | { | 1822 | { |
1852 | struct CadetChannel *ch; | 1823 | struct CadetReliableMessage *crm; |
1853 | struct CadetTunnel *t; | ||
1854 | struct CadetPeer *peer; | ||
1855 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
1856 | |||
1857 | LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s:%u\n", | ||
1858 | GNUNET_i2s (&msg->peer), GNUNET_h2s (&msg->port)); | ||
1859 | ccn = msg->ccn; | ||
1860 | 1824 | ||
1861 | /* Sanity check for duplicate channel IDs */ | 1825 | if (ch->pending_messages > ch->max_pending_messages) |
1862 | if (NULL != GML_channel_get (c, ccn)) | ||
1863 | { | 1826 | { |
1864 | GNUNET_break (0); | 1827 | GNUNET_break (0); |
1865 | return GNUNET_SYSERR; | 1828 | return GNUNET_SYSERR; |
1866 | } | 1829 | } |
1867 | 1830 | if (GNUNET_YES == ch->destroy) | |
1868 | peer = GCP_get (&msg->peer, GNUNET_YES); | ||
1869 | GCP_add_tunnel (peer); | ||
1870 | t = GCP_get_tunnel (peer); | ||
1871 | |||
1872 | if (GCP_get_short_id (peer) == myid) | ||
1873 | { | ||
1874 | GCT_change_cstate (t, CADET_TUNNEL_READY); | ||
1875 | } | ||
1876 | else | ||
1877 | { | 1831 | { |
1878 | /* FIXME change to a tunnel API, eliminate ch <-> peer connection */ | 1832 | /* we are going down, drop messages */ |
1879 | GCP_connect (peer); | 1833 | return GNUNET_OK; |
1880 | } | 1834 | } |
1835 | ch->pending_messages++; | ||
1881 | 1836 | ||
1882 | /* Create channel */ | 1837 | if (GNUNET_YES == ch->is_loopback) |
1883 | ch = channel_new (t, c, ccn); | ||
1884 | if (NULL == ch) | ||
1885 | { | ||
1886 | GNUNET_break (0); | ||
1887 | return GNUNET_SYSERR; | ||
1888 | } | ||
1889 | ch->port = msg->port; | ||
1890 | channel_set_options (ch, ntohl (msg->opt)); | ||
1891 | |||
1892 | /* In unreliable channels, we'll use the DLL to buffer BCK data */ | ||
1893 | ch->root_rel = GNUNET_new (struct CadetChannelReliability); | ||
1894 | ch->root_rel->ch = ch; | ||
1895 | ch->root_rel->retry_timer = CADET_RETRANSMIT_TIME; | ||
1896 | ch->root_rel->expected_delay.rel_value_us = 0; | ||
1897 | |||
1898 | LOG (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s\n", GCCH_2s (ch)); | ||
1899 | |||
1900 | send_create (ch); | ||
1901 | |||
1902 | return GNUNET_OK; | ||
1903 | } | ||
1904 | |||
1905 | |||
1906 | /** | ||
1907 | * Handler for cadet network payload traffic. | ||
1908 | * | ||
1909 | * @param ch Channel for the message. | ||
1910 | * @param msg Unencryted data message. | ||
1911 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1912 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1913 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1914 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1915 | */ | ||
1916 | void | ||
1917 | GCCH_handle_data (struct CadetChannel *ch, | ||
1918 | const struct GNUNET_CADET_ChannelAppDataMessage *msg, | ||
1919 | int fwd) | ||
1920 | { | ||
1921 | struct CadetChannelReliability *rel; | ||
1922 | struct CadetClient *c; | ||
1923 | struct GNUNET_MessageHeader *payload_msg; | ||
1924 | uint32_t mid; | ||
1925 | uint16_t payload_type; | ||
1926 | uint16_t payload_size; | ||
1927 | |||
1928 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | ||
1929 | if (GNUNET_SYSERR == fwd) | ||
1930 | { | ||
1931 | if (is_loopback (ch)) | ||
1932 | { | ||
1933 | /* It is a loopback channel after all... */ | ||
1934 | GNUNET_break (0); | ||
1935 | return; | ||
1936 | } | ||
1937 | fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; | ||
1938 | } | ||
1939 | |||
1940 | /* Initialize FWD/BCK data */ | ||
1941 | c = fwd ? ch->dest : ch->root; | ||
1942 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
1943 | |||
1944 | if (NULL == c) | ||
1945 | { | 1838 | { |
1946 | GNUNET_break (GNUNET_NO != ch->destroy); | 1839 | struct CadetChannelClient *receiver; |
1947 | return; | 1840 | struct GNUNET_MQ_Envelope *env; |
1948 | } | 1841 | struct GNUNET_CADET_LocalData *ld; |
1842 | int ack_to_owner; | ||
1949 | 1843 | ||
1950 | if (CADET_CHANNEL_READY != ch->state) | 1844 | env = GNUNET_MQ_msg_extra (ld, |
1951 | { | 1845 | buf_len, |
1952 | if (GNUNET_NO == fwd) | 1846 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); |
1847 | if ( (NULL != ch->owner) && | ||
1848 | (sender_ccn.channel_of_client == | ||
1849 | ch->owner->ccn.channel_of_client) ) | ||
1953 | { | 1850 | { |
1954 | /* If we are the root, this means the other peer has sent traffic before | 1851 | receiver = ch->dest; |
1955 | * receiving our ACK. Even if the SYNACK goes missing, no traffic should | 1852 | ack_to_owner = GNUNET_YES; |
1956 | * be sent before the ACK. | ||
1957 | */ | ||
1958 | GNUNET_break_op (0); | ||
1959 | return; | ||
1960 | } | 1853 | } |
1961 | /* If we are the dest, this means that the SYNACK got to the root but | 1854 | else if ( (NULL != ch->dest) && |
1962 | * the ACK went missing. Treat this as an ACK. | 1855 | (sender_ccn.channel_of_client == |
1963 | */ | 1856 | ch->dest->ccn.channel_of_client) ) |
1964 | channel_confirm (ch, GNUNET_NO); | ||
1965 | } | ||
1966 | |||
1967 | payload_msg = (struct GNUNET_MessageHeader *) &msg[1]; | ||
1968 | payload_type = ntohs (payload_msg->type); | ||
1969 | payload_size = ntohs (payload_msg->size); | ||
1970 | |||
1971 | GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO); | ||
1972 | GNUNET_STATISTICS_update (stats, "# bytes received", payload_size, GNUNET_NO); | ||
1973 | |||
1974 | mid = ntohl (msg->mid); | ||
1975 | LOG (GNUNET_ERROR_TYPE_INFO, "<== %s (%s %4u) on chan %s (%p) %s [%5u]\n", | ||
1976 | GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA), GC_m2s (payload_type), mid, | ||
1977 | GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size)); | ||
1978 | |||
1979 | if ( (GNUNET_NO == ch->reliable) || | ||
1980 | ( (! GC_is_pid_bigger (rel->mid_recv, mid)) && | ||
1981 | GC_is_pid_bigger (rel->mid_recv + 64, mid) ) ) | ||
1982 | { | ||
1983 | if (GNUNET_YES == ch->reliable) | ||
1984 | { | 1857 | { |
1985 | /* Is this the exact next expected messasge? */ | 1858 | receiver = ch->owner; |
1986 | if (mid == rel->mid_recv) | 1859 | ack_to_owner = GNUNET_NO; |
1987 | { | ||
1988 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1989 | "as expected, sending to client\n"); | ||
1990 | send_client_data (ch, msg, fwd); | ||
1991 | } | ||
1992 | else | ||
1993 | { | ||
1994 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1995 | "save for later\n"); | ||
1996 | add_buffered_data (msg, rel); | ||
1997 | } | ||
1998 | } | 1860 | } |
1999 | else | 1861 | else |
2000 | { | 1862 | { |
2001 | /* Tunnel is unreliable: send to clients directly */ | 1863 | GNUNET_break (0); |
2002 | /* FIXME: accept Out Of Order traffic */ | 1864 | return GNUNET_SYSERR; |
2003 | rel->mid_recv = mid + 1; | ||
2004 | send_client_data (ch, msg, fwd); | ||
2005 | } | 1865 | } |
2006 | } | 1866 | GNUNET_assert (NULL != receiver); |
2007 | else | 1867 | ld->ccn = receiver->ccn; |
2008 | { | 1868 | GNUNET_memcpy (&ld[1], |
2009 | GNUNET_STATISTICS_update (stats, "# duplicate MID", 1, GNUNET_NO); | 1869 | buf, |
2010 | if (GC_is_pid_bigger (rel->mid_recv, mid)) | 1870 | buf_len); |
1871 | if (GNUNET_YES == receiver->client_ready) | ||
2011 | { | 1872 | { |
2012 | GNUNET_break_op (0); | 1873 | ch->pending_messages--; |
2013 | LOG (GNUNET_ERROR_TYPE_WARNING, | 1874 | GSC_send_to_client (receiver->c, |
2014 | "MID %u on channel %s not expected (window: %u - %u). Dropping!\n", | 1875 | env); |
2015 | mid, GCCH_2s (ch), rel->mid_recv, rel->mid_recv + 63); | 1876 | send_ack_to_client (ch, |
1877 | ack_to_owner); | ||
2016 | } | 1878 | } |
2017 | else | 1879 | else |
2018 | { | 1880 | { |
2019 | LOG (GNUNET_ERROR_TYPE_INFO, | 1881 | struct CadetOutOfOrderMessage *oom; |
2020 | "Duplicate MID %u, channel %s (expecting MID %u). Re-sending ACK!\n", | 1882 | |
2021 | mid, GCCH_2s (ch), rel->mid_recv); | 1883 | oom = GNUNET_new (struct CadetOutOfOrderMessage); |
2022 | if (NULL != rel->uniq) | 1884 | oom->env = env; |
2023 | { | 1885 | GNUNET_CONTAINER_DLL_insert_tail (receiver->head_recv, |
2024 | LOG (GNUNET_ERROR_TYPE_WARNING, | 1886 | receiver->tail_recv, |
2025 | "We are trying to send an ACK, but don't seem have the " | 1887 | oom); |
2026 | "bandwidth. Have you set enough [ats] QUOTA in your config?\n"); | 1888 | receiver->num_recv++; |
2027 | } | ||
2028 | |||
2029 | } | 1889 | } |
2030 | } | 1890 | return GNUNET_OK; |
2031 | 1891 | } | |
2032 | GCCH_send_data_ack (ch, fwd); | 1892 | |
1893 | /* Everything is correct, send the message. */ | ||
1894 | crm = GNUNET_malloc (sizeof (*crm)); | ||
1895 | crm->ch = ch; | ||
1896 | crm->data_message = GNUNET_malloc (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) | ||
1897 | + buf_len); | ||
1898 | crm->data_message->header.size = htons (sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + buf_len); | ||
1899 | crm->data_message->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA); | ||
1900 | ch->mid_send.mid = htonl (ntohl (ch->mid_send.mid) + 1); | ||
1901 | crm->data_message->mid = ch->mid_send; | ||
1902 | crm->data_message->ctn = ch->ctn; | ||
1903 | GNUNET_memcpy (&crm->data_message[1], | ||
1904 | buf, | ||
1905 | buf_len); | ||
1906 | GNUNET_CONTAINER_DLL_insert_tail (ch->head_sent, | ||
1907 | ch->tail_sent, | ||
1908 | crm); | ||
1909 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1910 | "Sending message %u from local client to %s with %u bytes\n", | ||
1911 | ntohl (crm->data_message->mid.mid), | ||
1912 | GCCH_2s (ch), | ||
1913 | buf_len); | ||
1914 | if (NULL != ch->retry_data_task) | ||
1915 | { | ||
1916 | GNUNET_SCHEDULER_cancel (ch->retry_data_task); | ||
1917 | ch->retry_data_task = NULL; | ||
1918 | } | ||
1919 | crm->qe = GCT_send (ch->t, | ||
1920 | &crm->data_message->header, | ||
1921 | &data_sent_cb, | ||
1922 | crm); | ||
1923 | GNUNET_assert (NULL == ch->retry_data_task); | ||
1924 | return GNUNET_OK; | ||
2033 | } | 1925 | } |
2034 | 1926 | ||
2035 | 1927 | ||
2036 | /** | 1928 | /** |
2037 | * Handler for cadet network traffic end-to-end ACKs. | 1929 | * Handle ACK from client on local channel. Means the client is ready |
1930 | * for more data, see if we have any for it. | ||
2038 | * | 1931 | * |
2039 | * @param ch Channel on which we got this message. | 1932 | * @param ch channel to destroy |
2040 | * @param msg Data message. | 1933 | * @param client_ccn ccn of the client sending the ack |
2041 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
2042 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
2043 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
2044 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
2045 | */ | 1934 | */ |
2046 | void | 1935 | void |
2047 | GCCH_handle_data_ack (struct CadetChannel *ch, | 1936 | GCCH_handle_local_ack (struct CadetChannel *ch, |
2048 | const struct GNUNET_CADET_ChannelDataAckMessage *msg, | 1937 | struct GNUNET_CADET_ClientChannelNumber client_ccn) |
2049 | int fwd) | ||
2050 | { | 1938 | { |
2051 | struct CadetChannelReliability *rel; | 1939 | struct CadetChannelClient *ccc; |
2052 | struct CadetReliableMessage *copy; | 1940 | struct CadetOutOfOrderMessage *com; |
2053 | struct CadetReliableMessage *next; | 1941 | |
2054 | uint32_t ack; | 1942 | if ( (NULL != ch->owner) && |
2055 | int work; | 1943 | (ch->owner->ccn.channel_of_client == client_ccn.channel_of_client) ) |
2056 | 1944 | ccc = ch->owner; | |
2057 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | 1945 | else if ( (NULL != ch->dest) && |
2058 | if (GNUNET_SYSERR == fwd) | 1946 | (ch->dest->ccn.channel_of_client == client_ccn.channel_of_client) ) |
2059 | { | 1947 | ccc = ch->dest; |
2060 | if (is_loopback (ch)) | ||
2061 | { | ||
2062 | /* It is a loopback channel after all... */ | ||
2063 | GNUNET_break (0); | ||
2064 | return; | ||
2065 | } | ||
2066 | /* Inverted: if message came 'FWD' is a 'BCK ACK'. */ | ||
2067 | fwd = (NULL != ch->dest) ? GNUNET_NO : GNUNET_YES; | ||
2068 | } | ||
2069 | |||
2070 | ack = ntohl (msg->mid); | ||
2071 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
2072 | "<== %s (0x%010lX %4u) on chan %s (%p) %s [%5u]\n", | ||
2073 | GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK), msg->futures, ack, | ||
2074 | GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size)); | ||
2075 | |||
2076 | if (GNUNET_YES == fwd) | ||
2077 | rel = ch->root_rel; | ||
2078 | else | 1948 | else |
2079 | rel = ch->dest_rel; | 1949 | GNUNET_assert (0); |
2080 | 1950 | ccc->client_ready = GNUNET_YES; | |
2081 | if (NULL == rel) | 1951 | com = ccc->head_recv; |
2082 | { | 1952 | if (NULL == com) |
2083 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
2084 | return; | ||
2085 | } | ||
2086 | |||
2087 | /* Free ACK'd copies: no need to retransmit those anymore FIXME refactor */ | ||
2088 | for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next) | ||
2089 | { | 1953 | { |
2090 | if (GC_is_pid_bigger (copy->mid, ack)) | 1954 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2091 | { | 1955 | "Got LOCAL_ACK, %s-%X ready to receive more data, but none pending on %s-%X(%p)!\n", |
2092 | LOG (GNUNET_ERROR_TYPE_DEBUG, " head %u, out!\n", copy->mid); | 1956 | GSC_2s (ccc->c), |
2093 | if (0 < channel_rel_free_sent (rel, msg)) | 1957 | ntohl (client_ccn.channel_of_client), |
2094 | work = GNUNET_YES; | 1958 | GCCH_2s (ch), |
2095 | break; | 1959 | ntohl (ccc->ccn.channel_of_client), |
2096 | } | 1960 | ccc); |
2097 | work = GNUNET_YES; | 1961 | return; /* none pending */ |
2098 | LOG (GNUNET_ERROR_TYPE_DEBUG, " id %u\n", copy->mid); | 1962 | } |
2099 | next = copy->next; | 1963 | if (GNUNET_YES == ch->is_loopback) |
2100 | if (GNUNET_YES == rel_message_free (copy, GNUNET_YES)) | 1964 | { |
2101 | { | 1965 | int to_owner; |
2102 | LOG (GNUNET_ERROR_TYPE_DEBUG, " channel destoyed\n"); | 1966 | |
2103 | return; | 1967 | /* Messages are always in-order, just send */ |
2104 | } | 1968 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, |
2105 | } | 1969 | ccc->tail_recv, |
2106 | 1970 | com); | |
2107 | /* ACK client if needed and possible */ | 1971 | ccc->num_recv--; |
2108 | GCCH_allow_client (ch, fwd); | 1972 | GSC_send_to_client (ccc->c, |
2109 | 1973 | com->env); | |
2110 | /* If some message was free'd, update the retransmission delay */ | 1974 | /* Notify sender that we can receive more */ |
2111 | if (GNUNET_YES == work) | 1975 | if ( (NULL != ch->owner) && |
2112 | { | 1976 | (ccc->ccn.channel_of_client == |
2113 | if (NULL != rel->retry_task) | 1977 | ch->owner->ccn.channel_of_client) ) |
2114 | { | 1978 | { |
2115 | GNUNET_SCHEDULER_cancel (rel->retry_task); | 1979 | to_owner = GNUNET_NO; |
2116 | rel->retry_task = NULL; | ||
2117 | if (NULL != rel->head_sent && NULL == rel->head_sent->chq) | ||
2118 | { | ||
2119 | struct GNUNET_TIME_Absolute new_target; | ||
2120 | struct GNUNET_TIME_Relative delay; | ||
2121 | |||
2122 | delay = GNUNET_TIME_relative_saturating_multiply (rel->retry_timer, | ||
2123 | CADET_RETRANSMIT_MARGIN); | ||
2124 | new_target = GNUNET_TIME_absolute_add (rel->head_sent->timestamp, | ||
2125 | delay); | ||
2126 | delay = GNUNET_TIME_absolute_get_remaining (new_target); | ||
2127 | rel->retry_task = | ||
2128 | GNUNET_SCHEDULER_add_delayed (delay, | ||
2129 | &channel_retransmit_message, | ||
2130 | rel); | ||
2131 | } | ||
2132 | } | 1980 | } |
2133 | else | 1981 | else |
2134 | { | 1982 | { |
2135 | /* Work was done but no task was pending. | 1983 | GNUNET_assert ( (NULL != ch->dest) && |
2136 | * Task was cancelled by a retransmission that is sitting in the queue. | 1984 | (ccc->ccn.channel_of_client == |
2137 | */ | 1985 | ch->dest->ccn.channel_of_client) ); |
2138 | // FIXME add test to make sure this is the case, probably add return | 1986 | to_owner = GNUNET_YES; |
2139 | // value to GCCH_send_prebuilt_message | ||
2140 | } | 1987 | } |
1988 | send_ack_to_client (ch, | ||
1989 | to_owner); | ||
1990 | GNUNET_free (com); | ||
1991 | return; | ||
2141 | } | 1992 | } |
2142 | } | ||
2143 | |||
2144 | 1993 | ||
2145 | /** | 1994 | if ( (com->mid.mid != ch->mid_recv.mid) && |
2146 | * Handler for channel create messages. | 1995 | (GNUNET_NO == ch->out_of_order) && |
2147 | * | 1996 | (GNUNET_YES == ch->reliable) ) |
2148 | * Does not have fwd parameter because it's always 'FWD': channel is incoming. | ||
2149 | * | ||
2150 | * @param t Tunnel this channel will be in. | ||
2151 | * @param msg Channel crate message. | ||
2152 | */ | ||
2153 | struct CadetChannel * | ||
2154 | GCCH_handle_create (struct CadetTunnel *t, | ||
2155 | const struct GNUNET_CADET_ChannelOpenMessage *msg) | ||
2156 | { | ||
2157 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
2158 | struct GNUNET_CADET_ChannelTunnelNumber gid; | ||
2159 | struct CadetChannel *ch; | ||
2160 | struct CadetClient *c; | ||
2161 | int new_channel; | ||
2162 | const struct GNUNET_HashCode *port; | ||
2163 | |||
2164 | gid = msg->ctn; | ||
2165 | ch = GCT_get_channel (t, gid); | ||
2166 | if (NULL == ch) | ||
2167 | { | 1997 | { |
2168 | /* Create channel */ | 1998 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2169 | ccn.channel_of_client = htonl (0); | 1999 | "Got LOCAL_ACK, %s-%X ready to receive more data (but next one is out-of-order %u vs. %u)!\n", |
2170 | ch = channel_new (t, NULL, ccn); | 2000 | GSC_2s (ccc->c), |
2171 | ch->gid = gid; | 2001 | ntohl (ccc->ccn.channel_of_client), |
2172 | channel_set_options (ch, ntohl (msg->opt)); | 2002 | ntohl (com->mid.mid), |
2173 | new_channel = GNUNET_YES; | 2003 | ntohl (ch->mid_recv.mid)); |
2174 | } | 2004 | return; /* missing next one in-order */ |
2175 | else | ||
2176 | { | ||
2177 | new_channel = GNUNET_NO; | ||
2178 | } | 2005 | } |
2179 | port = &msg->port; | ||
2180 | |||
2181 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
2182 | "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n", | ||
2183 | GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN), ccn, port, | ||
2184 | GCCH_2s (ch), ch, GC_f2s (GNUNET_YES), ntohs (msg->header.size)); | ||
2185 | |||
2186 | if (GNUNET_YES == new_channel || GCT_is_loopback (t)) | ||
2187 | { | ||
2188 | /* Find a destination client */ | ||
2189 | ch->port = *port; | ||
2190 | LOG (GNUNET_ERROR_TYPE_DEBUG, " port %s\n", GNUNET_h2s (port)); | ||
2191 | c = GML_client_get_by_port (port); | ||
2192 | if (NULL == c) | ||
2193 | { | ||
2194 | LOG (GNUNET_ERROR_TYPE_DEBUG, " no client has port registered\n"); | ||
2195 | if (is_loopback (ch)) | ||
2196 | { | ||
2197 | LOG (GNUNET_ERROR_TYPE_DEBUG, " loopback: destroy on handler\n"); | ||
2198 | send_nack (ch); | ||
2199 | } | ||
2200 | else | ||
2201 | { | ||
2202 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not loopback: destroy now\n"); | ||
2203 | send_nack (ch); | ||
2204 | GCCH_destroy (ch); | ||
2205 | } | ||
2206 | return NULL; | ||
2207 | } | ||
2208 | else | ||
2209 | { | ||
2210 | LOG (GNUNET_ERROR_TYPE_DEBUG, " client %p has port registered\n", c); | ||
2211 | } | ||
2212 | |||
2213 | add_destination (ch, c); | ||
2214 | if (GNUNET_YES == ch->reliable) | ||
2215 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Reliable\n"); | ||
2216 | else | ||
2217 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Not Reliable\n"); | ||
2218 | 2006 | ||
2219 | send_client_create (ch); | 2007 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2220 | ch->state = CADET_CHANNEL_SENT; | 2008 | "Got LOCAL_ACK, giving payload message %u to %s-%X on %s\n", |
2221 | } | 2009 | ntohl (com->mid.mid), |
2222 | else | 2010 | GSC_2s (ccc->c), |
2223 | { | 2011 | ntohl (ccc->ccn.channel_of_client), |
2224 | LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate create channel\n"); | 2012 | GCCH_2s (ch)); |
2225 | if (NULL != ch->dest_rel->retry_task) | ||
2226 | { | ||
2227 | LOG (GNUNET_ERROR_TYPE_DEBUG, " clearing retry task\n"); | ||
2228 | /* we were waiting to re-send our 'SYNACK', wait no more! */ | ||
2229 | GNUNET_SCHEDULER_cancel (ch->dest_rel->retry_task); | ||
2230 | ch->dest_rel->retry_task = NULL; | ||
2231 | } | ||
2232 | else if (NULL != ch->dest_rel->uniq) | ||
2233 | { | ||
2234 | /* we are waiting to for our 'SYNACK' to leave the queue, all done! */ | ||
2235 | return ch; | ||
2236 | } | ||
2237 | } | ||
2238 | send_ack (ch, GNUNET_YES); | ||
2239 | 2013 | ||
2240 | return ch; | 2014 | /* all good, pass next message to client */ |
2015 | GNUNET_CONTAINER_DLL_remove (ccc->head_recv, | ||
2016 | ccc->tail_recv, | ||
2017 | com); | ||
2018 | ccc->num_recv--; | ||
2019 | /* FIXME: if unreliable, this is not aggressive | ||
2020 | enough, as it would be OK to have lost some! */ | ||
2021 | |||
2022 | ch->mid_recv.mid = htonl (1 + ntohl (com->mid.mid)); | ||
2023 | ch->mid_futures >>= 1; /* equivalent to division by 2 */ | ||
2024 | ccc->client_ready = GNUNET_NO; | ||
2025 | GSC_send_to_client (ccc->c, | ||
2026 | com->env); | ||
2027 | GNUNET_free (com); | ||
2028 | send_channel_data_ack (ch); | ||
2029 | if (NULL != ccc->head_recv) | ||
2030 | return; | ||
2031 | if (GNUNET_NO == ch->destroy) | ||
2032 | return; | ||
2033 | GCT_send_channel_destroy (ch->t, | ||
2034 | ch->ctn); | ||
2035 | channel_destroy (ch); | ||
2241 | } | 2036 | } |
2242 | 2037 | ||
2243 | 2038 | ||
2244 | /** | 2039 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-chn",__VA_ARGS__) |
2245 | * Handler for channel NACK messages. | ||
2246 | * | ||
2247 | * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter. | ||
2248 | * | ||
2249 | * @param ch Channel. | ||
2250 | */ | ||
2251 | void | ||
2252 | GCCH_handle_nack (struct CadetChannel *ch) | ||
2253 | { | ||
2254 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
2255 | "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n", | ||
2256 | GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED), ch->gid, 0, | ||
2257 | GCCH_2s (ch), ch, "---", 0); | ||
2258 | |||
2259 | send_client_nack (ch); | ||
2260 | GCCH_destroy (ch); | ||
2261 | } | ||
2262 | 2040 | ||
2263 | 2041 | ||
2264 | /** | 2042 | /** |
2265 | * Handler for channel ack messages. | 2043 | * Log channel info. |
2266 | * | 2044 | * |
2267 | * @param ch Channel. | 2045 | * @param ch Channel. |
2268 | * @param msg Message. | 2046 | * @param level Debug level to use. |
2269 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
2270 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
2271 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
2272 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
2273 | */ | ||
2274 | void | ||
2275 | GCCH_handle_ack (struct CadetChannel *ch, | ||
2276 | const struct GNUNET_CADET_ChannelManageMessage *msg, | ||
2277 | int fwd) | ||
2278 | { | ||
2279 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
2280 | "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n", | ||
2281 | GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK), ch->gid, 0, | ||
2282 | GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size)); | ||
2283 | |||
2284 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | ||
2285 | if (GNUNET_SYSERR == fwd) | ||
2286 | { | ||
2287 | if (is_loopback (ch)) | ||
2288 | { | ||
2289 | /* It is a loopback channel after all... */ | ||
2290 | GNUNET_break (0); | ||
2291 | return; | ||
2292 | } | ||
2293 | fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; | ||
2294 | } | ||
2295 | |||
2296 | channel_confirm (ch, !fwd); | ||
2297 | } | ||
2298 | |||
2299 | |||
2300 | /** | ||
2301 | * Handler for channel destroy messages. | ||
2302 | * | ||
2303 | * @param ch Channel to be destroyed of. | ||
2304 | * @param msg Message. | ||
2305 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
2306 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
2307 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
2308 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
2309 | */ | 2047 | */ |
2310 | void | 2048 | void |
2311 | GCCH_handle_destroy (struct CadetChannel *ch, | 2049 | GCCH_debug (struct CadetChannel *ch, |
2312 | const struct GNUNET_CADET_ChannelManageMessage *msg, | 2050 | enum GNUNET_ErrorType level) |
2313 | int fwd) | ||
2314 | { | 2051 | { |
2315 | struct CadetChannelReliability *rel; | 2052 | int do_log; |
2316 | |||
2317 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
2318 | "<== %s ( 0x%08X %4u) on chan %s (%p) %s [%5u]\n", | ||
2319 | GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY), ch->gid, 0, | ||
2320 | GCCH_2s (ch), ch, GC_f2s (fwd), ntohs (msg->header.size)); | ||
2321 | |||
2322 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | ||
2323 | if (GNUNET_SYSERR == fwd) | ||
2324 | { | ||
2325 | if (is_loopback (ch)) | ||
2326 | { | ||
2327 | /* It is a loopback channel after all... */ | ||
2328 | GNUNET_break (0); | ||
2329 | return; | ||
2330 | } | ||
2331 | fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; | ||
2332 | } | ||
2333 | 2053 | ||
2334 | GCCH_debug (ch, GNUNET_ERROR_TYPE_DEBUG); | 2054 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), |
2335 | if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) ) | 2055 | "cadet-chn", |
2336 | { | 2056 | __FILE__, __FUNCTION__, __LINE__); |
2337 | /* Not for us (don't destroy twice a half-open loopback channel) */ | 2057 | if (0 == do_log) |
2338 | return; | 2058 | return; |
2339 | } | ||
2340 | |||
2341 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
2342 | if (0 == rel->n_recv) | ||
2343 | { | ||
2344 | send_destroy (ch, GNUNET_YES); | ||
2345 | GCCH_destroy (ch); | ||
2346 | } | ||
2347 | else | ||
2348 | { | ||
2349 | ch->destroy = GNUNET_YES; | ||
2350 | } | ||
2351 | } | ||
2352 | |||
2353 | |||
2354 | /** | ||
2355 | * Sends an already built message on a channel. | ||
2356 | * | ||
2357 | * If the channel is on a loopback tunnel, notifies the appropriate destination | ||
2358 | * client locally. | ||
2359 | * | ||
2360 | * On a normal channel passes the message to the tunnel for encryption and | ||
2361 | * sending on a connection. | ||
2362 | * | ||
2363 | * This function DOES NOT save the message for retransmission. | ||
2364 | * | ||
2365 | * @param message Message to send. Function makes a copy of it. | ||
2366 | * @param ch Channel on which this message is transmitted. | ||
2367 | * @param fwd Is this a fwd message? | ||
2368 | * @param existing_copy This is a retransmission, don't save a copy. | ||
2369 | */ | ||
2370 | void | ||
2371 | GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
2372 | struct CadetChannel *ch, int fwd, | ||
2373 | void *existing_copy) | ||
2374 | { | ||
2375 | struct CadetChannelQueue *chq; | ||
2376 | uint32_t data_id; | ||
2377 | uint16_t type; | ||
2378 | uint16_t size; | ||
2379 | char info[32]; | ||
2380 | |||
2381 | type = ntohs (message->type); | ||
2382 | size = ntohs (message->size); | ||
2383 | |||
2384 | data_id = 0; | ||
2385 | switch (type) | ||
2386 | { | ||
2387 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA: | ||
2388 | { | ||
2389 | struct GNUNET_CADET_ChannelAppDataMessage *data_msg; | ||
2390 | struct GNUNET_MessageHeader *payload_msg; | ||
2391 | uint16_t payload_type; | ||
2392 | |||
2393 | data_msg = (struct GNUNET_CADET_ChannelAppDataMessage *) message; | ||
2394 | data_id = ntohl (data_msg->mid); | ||
2395 | payload_msg = (struct GNUNET_MessageHeader *) &data_msg[1]; | ||
2396 | payload_type = ntohs (payload_msg->type); | ||
2397 | strncpy (info, GC_m2s (payload_type), 31); | ||
2398 | info[31] = '\0'; | ||
2399 | break; | ||
2400 | } | ||
2401 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK: | ||
2402 | { | ||
2403 | struct GNUNET_CADET_ChannelDataAckMessage *ack_msg; | ||
2404 | ack_msg = (struct GNUNET_CADET_ChannelDataAckMessage *) message; | ||
2405 | data_id = ntohl (ack_msg->mid); | ||
2406 | SPRINTF (info, "0x%010lX", | ||
2407 | (unsigned long int) ack_msg->futures); | ||
2408 | break; | ||
2409 | } | ||
2410 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN: | ||
2411 | { | ||
2412 | struct GNUNET_CADET_ChannelOpenMessage *cc_msg; | ||
2413 | cc_msg = (struct GNUNET_CADET_ChannelOpenMessage *) message; | ||
2414 | SPRINTF (info, " 0x%08X", ntohl (cc_msg->ctn.cn)); | ||
2415 | break; | ||
2416 | } | ||
2417 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK: | ||
2418 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED: | ||
2419 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
2420 | { | ||
2421 | struct GNUNET_CADET_ChannelManageMessage *m_msg; | ||
2422 | m_msg = (struct GNUNET_CADET_ChannelManageMessage *) message; | ||
2423 | SPRINTF (info, " 0x%08X", ntohl (m_msg->ctn.cn)); | ||
2424 | break; | ||
2425 | } | ||
2426 | default: | ||
2427 | info[0] = '\0'; | ||
2428 | } | ||
2429 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
2430 | "==> %s (%12s %4u) on chan %s (%p) %s [%5u]\n", | ||
2431 | GC_m2s (type), info, data_id, | ||
2432 | GCCH_2s (ch), ch, GC_f2s (fwd), size); | ||
2433 | 2059 | ||
2434 | if (GCT_is_loopback (ch->t)) | 2060 | if (NULL == ch) |
2435 | { | 2061 | { |
2436 | handle_loopback (ch, message, fwd); | 2062 | LOG2 (level, "CHN *** DEBUG NULL CHANNEL ***\n"); |
2437 | return; | 2063 | return; |
2438 | } | 2064 | } |
2439 | 2065 | LOG2 (level, | |
2440 | switch (type) | 2066 | "CHN %s:%X (%p)\n", |
2067 | GCT_2s (ch->t), | ||
2068 | ch->ctn, | ||
2069 | ch); | ||
2070 | if (NULL != ch->owner) | ||
2441 | { | 2071 | { |
2442 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA: | 2072 | LOG2 (level, |
2443 | if (GNUNET_YES == ch->reliable) | 2073 | "CHN origin %s ready %s local-id: %u\n", |
2444 | { | 2074 | GSC_2s (ch->owner->c), |
2445 | chq = GNUNET_new (struct CadetChannelQueue); | 2075 | ch->owner->client_ready ? "YES" : "NO", |
2446 | chq->type = type; | 2076 | ntohl (ch->owner->ccn.channel_of_client)); |
2447 | if (NULL == existing_copy) | ||
2448 | chq->copy = channel_save_copy (ch, message, fwd); | ||
2449 | else | ||
2450 | { | ||
2451 | chq->copy = (struct CadetReliableMessage *) existing_copy; | ||
2452 | if (NULL != chq->copy->chq) | ||
2453 | { | ||
2454 | /* Last retransmission was queued but not yet sent! | ||
2455 | * This retransmission was scheduled by a ch_message_sent which | ||
2456 | * followed a very fast RTT, so the tiny delay made the | ||
2457 | * retransmission function to execute before the previous | ||
2458 | * retransmitted message even had a chance to leave the peer. | ||
2459 | * Cancel this message and wait until the pending | ||
2460 | * retransmission leaves the peer and ch_message_sent starts | ||
2461 | * the timer for the next one. | ||
2462 | */ | ||
2463 | GNUNET_free (chq); | ||
2464 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2465 | " exisitng copy not yet transmitted!\n"); | ||
2466 | return; | ||
2467 | } | ||
2468 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2469 | " using existing copy: %p {r:%p q:%p t:%u}\n", | ||
2470 | existing_copy, | ||
2471 | chq->copy->rel, chq->copy->chq, chq->copy->type); | ||
2472 | } | ||
2473 | LOG (GNUNET_ERROR_TYPE_DEBUG, " new chq: %p\n", chq); | ||
2474 | chq->copy->chq = chq; | ||
2475 | chq->tq = GCT_send_prebuilt_message (message, ch->t, NULL, | ||
2476 | GNUNET_YES, | ||
2477 | &ch_message_sent, chq); | ||
2478 | /* q itself is stored in copy */ | ||
2479 | GNUNET_assert (NULL != chq->tq || GNUNET_NO != ch->destroy); | ||
2480 | } | ||
2481 | else | ||
2482 | { | ||
2483 | fire_and_forget (message, ch, GNUNET_NO); | ||
2484 | } | ||
2485 | break; | ||
2486 | |||
2487 | |||
2488 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK: | ||
2489 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN: | ||
2490 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK: | ||
2491 | chq = GNUNET_new (struct CadetChannelQueue); | ||
2492 | chq->type = type; | ||
2493 | chq->rel = fwd ? ch->root_rel : ch->dest_rel; | ||
2494 | if (NULL != chq->rel->uniq) | ||
2495 | { | ||
2496 | if (NULL != chq->rel->uniq->tq) | ||
2497 | { | ||
2498 | GCT_cancel (chq->rel->uniq->tq); | ||
2499 | /* ch_message_sent is called, freeing and NULLing uniq */ | ||
2500 | GNUNET_break (NULL == chq->rel->uniq); | ||
2501 | } | ||
2502 | else | ||
2503 | { | ||
2504 | GNUNET_break (0); | ||
2505 | GNUNET_free (chq->rel->uniq); | ||
2506 | } | ||
2507 | } | ||
2508 | |||
2509 | chq->rel->uniq = chq; | ||
2510 | chq->tq = GCT_send_prebuilt_message (message, ch->t, NULL, GNUNET_YES, | ||
2511 | &ch_message_sent, chq); | ||
2512 | if (NULL == chq->tq) | ||
2513 | { | ||
2514 | GNUNET_break (0); | ||
2515 | chq->rel->uniq = NULL; | ||
2516 | GCT_debug (ch->t, GNUNET_ERROR_TYPE_ERROR); | ||
2517 | GNUNET_free (chq); | ||
2518 | chq = NULL; | ||
2519 | return; | ||
2520 | } | ||
2521 | break; | ||
2522 | |||
2523 | |||
2524 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
2525 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED: | ||
2526 | fire_and_forget (message, ch, GNUNET_YES); | ||
2527 | break; | ||
2528 | |||
2529 | |||
2530 | default: | ||
2531 | GNUNET_break (0); | ||
2532 | LOG (GNUNET_ERROR_TYPE_WARNING, "type %s unknown!\n", GC_m2s (type)); | ||
2533 | fire_and_forget (message, ch, GNUNET_YES); | ||
2534 | } | 2077 | } |
2078 | if (NULL != ch->dest) | ||
2079 | { | ||
2080 | LOG2 (level, | ||
2081 | "CHN destination %s ready %s local-id: %u\n", | ||
2082 | GSC_2s (ch->dest->c), | ||
2083 | ch->dest->client_ready ? "YES" : "NO", | ||
2084 | ntohl (ch->dest->ccn.channel_of_client)); | ||
2085 | } | ||
2086 | LOG2 (level, | ||
2087 | "CHN Message IDs recv: %d (%LLX), send: %d\n", | ||
2088 | ntohl (ch->mid_recv.mid), | ||
2089 | (unsigned long long) ch->mid_futures, | ||
2090 | ntohl (ch->mid_send.mid)); | ||
2535 | } | 2091 | } |
2536 | 2092 | ||
2537 | 2093 | ||
2538 | /** | ||
2539 | * Get the static string for identification of the channel. | ||
2540 | * | ||
2541 | * @param ch Channel. | ||
2542 | * | ||
2543 | * @return Static string with the channel IDs. | ||
2544 | */ | ||
2545 | const char * | ||
2546 | GCCH_2s (const struct CadetChannel *ch) | ||
2547 | { | ||
2548 | static char buf[64]; | ||
2549 | |||
2550 | if (NULL == ch) | ||
2551 | return "(NULL Channel)"; | ||
2552 | 2094 | ||
2553 | SPRINTF (buf, | 2095 | /* end of gnunet-service-cadet-new_channel.c */ |
2554 | "%s:%s gid:%X (%X / %X)", | ||
2555 | GCT_2s (ch->t), | ||
2556 | GNUNET_h2s (&ch->port), | ||
2557 | ntohl (ch->gid.cn), | ||
2558 | ntohl (ch->lid_root.channel_of_client), | ||
2559 | ntohl (ch->lid_dest.channel_of_client)); | ||
2560 | |||
2561 | return buf; | ||
2562 | } | ||
diff --git a/src/cadet/gnunet-service-cadet_channel.h b/src/cadet/gnunet-service-cadet_channel.h index 9d4893269..16517c457 100644 --- a/src/cadet/gnunet-service-cadet_channel.h +++ b/src/cadet/gnunet-service-cadet_channel.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2013 GNUnet e.V. | 3 | Copyright (C) 2001-2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -20,344 +20,261 @@ | |||
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @file cadet/gnunet-service-cadet_channel.h | 22 | * @file cadet/gnunet-service-cadet_channel.h |
23 | * @brief cadet service; dealing with end-to-end channels | 23 | * @brief GNUnet CADET service with encryption |
24 | * @author Bartlomiej Polot | 24 | * @author Bartlomiej Polot |
25 | * | 25 | * @author Christian Grothoff |
26 | * All functions in this file should use the prefix GMCH (Gnunet Cadet CHannel) | ||
27 | */ | 26 | */ |
28 | |||
29 | #ifndef GNUNET_SERVICE_CADET_CHANNEL_H | 27 | #ifndef GNUNET_SERVICE_CADET_CHANNEL_H |
30 | #define GNUNET_SERVICE_CADET_CHANNEL_H | 28 | #define GNUNET_SERVICE_CADET_CHANNEL_H |
31 | 29 | ||
32 | #ifdef __cplusplus | 30 | #include "gnunet-service-cadet.h" |
33 | extern "C" | 31 | #include "gnunet-service-cadet_peer.h" |
34 | { | ||
35 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
36 | } | ||
37 | #endif | ||
38 | #endif | ||
39 | |||
40 | #include "platform.h" | ||
41 | #include "gnunet_util_lib.h" | ||
42 | |||
43 | #include "cadet_protocol.h" | 32 | #include "cadet_protocol.h" |
44 | #include "cadet.h" | 33 | |
45 | 34 | ||
46 | /** | 35 | /** |
47 | * Struct containing all information regarding a channel to a remote client. | 36 | * A channel is a bidirectional connection between two CADET |
37 | * clients. Communiation can be reliable, unreliable, in-order | ||
38 | * or out-of-order. One client is the "local" client, this | ||
39 | * one initiated the connection. The other client is the | ||
40 | * "incoming" client, this one listened on a port to accept | ||
41 | * the connection from the "local" client. | ||
48 | */ | 42 | */ |
49 | struct CadetChannel; | 43 | struct CadetChannel; |
50 | 44 | ||
51 | 45 | ||
52 | #include "gnunet-service-cadet_tunnel.h" | ||
53 | #include "gnunet-service-cadet_local.h" | ||
54 | |||
55 | |||
56 | /** | 46 | /** |
57 | * Destroy a channel and free all resources. | 47 | * Hash the @a port and @a initiator and @a listener to |
48 | * calculate the "challenge" @a h_port we send to the other | ||
49 | * peer on #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN. | ||
58 | * | 50 | * |
59 | * @param ch Channel to destroy. | 51 | * @param[out] h_port set to the hash of @a port, @a initiator and @a listener |
52 | * @param port cadet port, as seen by CADET clients | ||
53 | * @param listener peer that is listining on @a port | ||
60 | */ | 54 | */ |
61 | void | 55 | void |
62 | GCCH_destroy (struct CadetChannel *ch); | 56 | GCCH_hash_port (struct GNUNET_HashCode *h_port, |
57 | const struct GNUNET_HashCode *port, | ||
58 | const struct GNUNET_PeerIdentity *listener); | ||
63 | 59 | ||
64 | 60 | ||
65 | /** | 61 | /** |
66 | * Get the channel's public ID. | 62 | * Get the static string for identification of the channel. |
67 | * | 63 | * |
68 | * @param ch Channel. | 64 | * @param ch Channel. |
69 | * | 65 | * |
70 | * @return ID used to identify the channel with the remote peer. | 66 | * @return Static string with the channel IDs. |
71 | */ | ||
72 | struct GNUNET_CADET_ChannelTunnelNumber | ||
73 | GCCH_get_id (const struct CadetChannel *ch); | ||
74 | |||
75 | |||
76 | /** | ||
77 | * Get the channel tunnel. | ||
78 | * | ||
79 | * @param ch Channel to get the tunnel from. | ||
80 | * | ||
81 | * @return tunnel of the channel. | ||
82 | */ | 67 | */ |
83 | struct CadetTunnel * | 68 | const char * |
84 | GCCH_get_tunnel (const struct CadetChannel *ch); | 69 | GCCH_2s (const struct CadetChannel *ch); |
85 | 70 | ||
86 | 71 | ||
87 | /** | 72 | /** |
88 | * Get free buffer space towards the client on a specific channel. | 73 | * Log channel info. |
89 | * | 74 | * |
90 | * @param ch Channel. | 75 | * @param ch Channel. |
91 | * @param fwd Is query about FWD traffic? | 76 | * @param level Debug level to use. |
92 | * | ||
93 | * @return Free buffer space [0 - 64] | ||
94 | */ | 77 | */ |
95 | unsigned int | 78 | void |
96 | GCCH_get_buffer (struct CadetChannel *ch, int fwd); | 79 | GCCH_debug (struct CadetChannel *ch, |
80 | enum GNUNET_ErrorType level); | ||
97 | 81 | ||
98 | 82 | ||
99 | /** | 83 | /** |
100 | * Get flow control status of end point: is client allow to send? | 84 | * Get the channel's public ID. |
101 | * | 85 | * |
102 | * @param ch Channel. | 86 | * @param ch Channel. |
103 | * @param fwd Is query about FWD traffic? (Request root status). | ||
104 | * | 87 | * |
105 | * @return #GNUNET_YES if client is allowed to send us data. | 88 | * @return ID used to identify the channel with the remote peer. |
106 | */ | 89 | */ |
107 | int | 90 | struct GNUNET_CADET_ChannelTunnelNumber |
108 | GCCH_get_allowed (struct CadetChannel *ch, int fwd); | 91 | GCCH_get_id (const struct CadetChannel *ch); |
109 | 92 | ||
110 | 93 | ||
111 | /** | 94 | /** |
112 | * Is the root client for this channel on this peer? | 95 | * Create a new channel. |
113 | * | 96 | * |
114 | * @param ch Channel. | 97 | * @param owner local client owning the channel |
115 | * @param fwd Is this for fwd traffic? | 98 | * @param owner_id local chid of this channel at the @a owner |
116 | * | 99 | * @param destination peer to which we should build the channel |
117 | * @return #GNUNET_YES in case it is. | 100 | * @param port desired port at @a destination |
101 | * @param options options for the channel | ||
102 | * @return handle to the new channel | ||
118 | */ | 103 | */ |
119 | int | 104 | struct CadetChannel * |
120 | GCCH_is_origin (struct CadetChannel *ch, int fwd); | 105 | GCCH_channel_local_new (struct CadetClient *owner, |
106 | struct GNUNET_CADET_ClientChannelNumber owner_id, | ||
107 | struct CadetPeer *destination, | ||
108 | const struct GNUNET_HashCode *port, | ||
109 | uint32_t options); | ||
121 | 110 | ||
122 | /** | ||
123 | * Is the destination client for this channel on this peer? | ||
124 | * | ||
125 | * @param ch Channel. | ||
126 | * @param fwd Is this for fwd traffic? | ||
127 | * | ||
128 | * @return #GNUNET_YES in case it is. | ||
129 | */ | ||
130 | int | ||
131 | GCCH_is_terminal (struct CadetChannel *ch, int fwd); | ||
132 | 111 | ||
133 | /** | 112 | /** |
134 | * Send an end-to-end ACK message for the most recent in-sequence payload. | 113 | * A client is bound to the port that we have a channel |
135 | * | 114 | * open to. Send the acknowledgement for the connection |
136 | * If channel is not reliable, do nothing. | 115 | * request and establish the link with the client. |
137 | * | 116 | * |
138 | * @param ch Channel this is about. | 117 | * @param ch open incoming channel |
139 | * @param fwd Is for FWD traffic? (ACK dest->owner) | 118 | * @param c client listening on the respective @a port |
119 | * @param port port number @a c is listening on | ||
140 | */ | 120 | */ |
141 | void | 121 | void |
142 | GCCH_send_data_ack (struct CadetChannel *ch, int fwd); | 122 | GCCH_bind (struct CadetChannel *ch, |
123 | struct CadetClient *c, | ||
124 | const struct GNUNET_HashCode *port); | ||
143 | 125 | ||
144 | /** | ||
145 | * Notify the destination client that a new incoming channel was created. | ||
146 | * | ||
147 | * @param ch Channel that was created. | ||
148 | */ | ||
149 | void | ||
150 | GCCH_send_create (struct CadetChannel *ch); | ||
151 | 126 | ||
152 | /** | 127 | /** |
153 | * Allow a client to send us more data, in case it was choked. | 128 | * Destroy locally created channel. Called by the |
129 | * local client, so no need to tell the client. | ||
154 | * | 130 | * |
155 | * @param ch Channel. | 131 | * @param ch channel to destroy |
156 | * @param fwd Is this about FWD traffic? (Root client). | 132 | * @param c client that caused the destruction |
133 | * @param ccn client number of the client @a c | ||
157 | */ | 134 | */ |
158 | void | 135 | void |
159 | GCCH_allow_client (struct CadetChannel *ch, int fwd); | 136 | GCCH_channel_local_destroy (struct CadetChannel *ch, |
137 | struct CadetClient *c, | ||
138 | struct GNUNET_CADET_ClientChannelNumber ccn); | ||
160 | 139 | ||
161 | /** | ||
162 | * Log channel info. | ||
163 | * | ||
164 | * @param ch Channel. | ||
165 | * @param level Debug level to use. | ||
166 | */ | ||
167 | void | ||
168 | GCCH_debug (struct CadetChannel *ch, enum GNUNET_ErrorType level); | ||
169 | 140 | ||
170 | /** | 141 | /** |
171 | * Handle an ACK given by a client. | 142 | * Function called once and only once after a channel was bound |
172 | * | 143 | * to its tunnel via #GCT_add_channel() is ready for transmission. |
173 | * Mark client as ready and send him any buffered data we could have for him. | 144 | * Note that this is only the case for channels that this peer |
174 | * | 145 | * initiates, as for incoming channels we assume that they are |
175 | * @param ch Channel. | 146 | * ready for transmission immediately upon receiving the open |
176 | * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by root and go BCK) | 147 | * message. Used to bootstrap the #GCT_send() process. |
177 | */ | 148 | * |
178 | void | 149 | * @param ch the channel for which the tunnel is now ready |
179 | GCCH_handle_local_ack (struct CadetChannel *ch, int fwd); | ||
180 | |||
181 | /** | ||
182 | * Handle data given by a client. | ||
183 | * | ||
184 | * Check whether the client is allowed to send in this tunnel, save if channel | ||
185 | * is reliable and send an ACK to the client if there is still buffer space | ||
186 | * in the tunnel. | ||
187 | * | ||
188 | * @param ch Channel. | ||
189 | * @param c Client which sent the data. | ||
190 | * @param fwd Is this a FWD data? | ||
191 | * @param message Data message. | ||
192 | * @param size Size of data. | ||
193 | * | ||
194 | * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en error. | ||
195 | */ | ||
196 | int | ||
197 | GCCH_handle_local_data (struct CadetChannel *ch, | ||
198 | struct CadetClient *c, int fwd, | ||
199 | const struct GNUNET_MessageHeader *message, | ||
200 | size_t size); | ||
201 | |||
202 | /** | ||
203 | * Handle a channel destroy requested by a client. | ||
204 | * | ||
205 | * Destroy the channel and the tunnel in case this was the last channel. | ||
206 | * | ||
207 | * @param ch Channel. | ||
208 | * @param c Client that requested the destruction (to avoid notifying him). | ||
209 | * @param is_root Is the request coming from root? | ||
210 | */ | 150 | */ |
211 | void | 151 | void |
212 | GCCH_handle_local_destroy (struct CadetChannel *ch, | 152 | GCCH_tunnel_up (struct CadetChannel *ch); |
213 | struct CadetClient *c, | ||
214 | int is_root); | ||
215 | |||
216 | 153 | ||
217 | /** | ||
218 | * Handle a channel create requested by a client. | ||
219 | * | ||
220 | * Create the channel and the tunnel in case this was the first0 channel. | ||
221 | * | ||
222 | * @param c Client that requested the creation (will be the root). | ||
223 | * @param msg Create Channel message. | ||
224 | * | ||
225 | * @return #GNUNET_OK if everything went fine, #GNUNET_SYSERR otherwise. | ||
226 | */ | ||
227 | int | ||
228 | GCCH_handle_local_create (struct CadetClient *c, | ||
229 | struct GNUNET_CADET_LocalChannelCreateMessage *msg); | ||
230 | 154 | ||
231 | /** | 155 | /** |
232 | * Handler for cadet network payload traffic. | 156 | * Create a new channel based on a request coming in over the network. |
233 | * | 157 | * |
234 | * @param ch Channel for the message. | 158 | * @param t tunnel to the remote peer |
235 | * @param msg Unencryted data message. | 159 | * @param chid identifier of this channel in the tunnel |
236 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | 160 | * @param origin peer to who initiated the channel |
237 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | 161 | * @param h_port hash of desired local port |
238 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | 162 | * @param options options for the channel |
239 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | 163 | * @return handle to the new channel |
240 | */ | 164 | */ |
241 | void | 165 | struct CadetChannel * |
242 | GCCH_handle_data (struct CadetChannel *ch, | 166 | GCCH_channel_incoming_new (struct CadetTunnel *t, |
243 | const struct GNUNET_CADET_ChannelAppDataMessage *msg, | 167 | struct GNUNET_CADET_ChannelTunnelNumber chid, |
244 | int fwd); | 168 | const struct GNUNET_HashCode *h_port, |
169 | uint32_t options); | ||
245 | 170 | ||
246 | 171 | ||
247 | /** | 172 | /** |
248 | * Handler for cadet network traffic end-to-end ACKs. | 173 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for |
174 | * this channel. If the binding was successful, (re)transmit the | ||
175 | * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK. | ||
249 | * | 176 | * |
250 | * @param ch Channel on which we got this message. | 177 | * @param ch channel that got the duplicate open |
251 | * @param msg Data message. | 178 | * @param cti identifier of the connection that delivered the message |
252 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
253 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
254 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
255 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
256 | */ | 179 | */ |
257 | void | 180 | void |
258 | GCCH_handle_data_ack (struct CadetChannel *ch, | 181 | GCCH_handle_duplicate_open (struct CadetChannel *ch, |
259 | const struct GNUNET_CADET_ChannelDataAckMessage *msg, | 182 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti); |
260 | int fwd); | ||
261 | 183 | ||
262 | 184 | ||
263 | /** | ||
264 | * Handler for channel create messages. | ||
265 | * | ||
266 | * Does not have fwd parameter because it's always 'FWD': channel is incoming. | ||
267 | * | ||
268 | * @param t Tunnel this channel will be in. | ||
269 | * @param msg Channel crate message. | ||
270 | */ | ||
271 | struct CadetChannel * | ||
272 | GCCH_handle_create (struct CadetTunnel *t, | ||
273 | const struct GNUNET_CADET_ChannelOpenMessage *msg); | ||
274 | |||
275 | 185 | ||
276 | /** | 186 | /** |
277 | * Handler for channel NACK messages. | 187 | * We got payload data for a channel. Pass it on to the client. |
278 | * | ||
279 | * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter. | ||
280 | * | 188 | * |
281 | * @param ch Channel. | 189 | * @param ch channel that got data |
190 | * @param cti identifier of the connection that delivered the message | ||
191 | * @param msg message that was received | ||
282 | */ | 192 | */ |
283 | void | 193 | void |
284 | GCCH_handle_nack (struct CadetChannel *ch); | 194 | GCCH_handle_channel_plaintext_data (struct CadetChannel *ch, |
195 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, | ||
196 | const struct GNUNET_CADET_ChannelAppDataMessage *msg); | ||
285 | 197 | ||
286 | 198 | ||
287 | /** | 199 | /** |
288 | * Handler for channel ack messages. | 200 | * We got an acknowledgement for payload data for a channel. |
201 | * Possibly resume transmissions. | ||
289 | * | 202 | * |
290 | * @param ch Channel this channel is to be created in. | 203 | * @param ch channel that got the ack |
291 | * @param msg Message. | 204 | * @param cti identifier of the connection that delivered the message |
292 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | 205 | * @param ack details about what was received |
293 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
294 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
295 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
296 | */ | 206 | */ |
297 | void | 207 | void |
298 | GCCH_handle_ack (struct CadetChannel *ch, | 208 | GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch, |
299 | const struct GNUNET_CADET_ChannelManageMessage *msg, | 209 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, |
300 | int fwd); | 210 | const struct GNUNET_CADET_ChannelDataAckMessage *ack); |
301 | 211 | ||
302 | 212 | ||
303 | /** | 213 | /** |
304 | * Handler for channel destroy messages. | 214 | * We got an acknowledgement for the creation of the channel |
215 | * (the port is open on the other side). Begin transmissions. | ||
305 | * | 216 | * |
306 | * @param ch Channel this channel is to be destroyed of. | 217 | * @param ch channel to destroy |
307 | * @param msg Message. | 218 | * @param cti identifier of the connection that delivered the message, |
308 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | 219 | * NULL if the ACK was inferred because we got payload or are on loopback |
309 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | 220 | * @param port port number (needed to verify receiver knows the port) |
310 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
311 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
312 | */ | 221 | */ |
313 | void | 222 | void |
314 | GCCH_handle_destroy (struct CadetChannel *ch, | 223 | GCCH_handle_channel_open_ack (struct CadetChannel *ch, |
315 | const struct GNUNET_CADET_ChannelManageMessage *msg, | 224 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, |
316 | int fwd); | 225 | const struct GNUNET_HashCode *port); |
317 | 226 | ||
318 | 227 | ||
319 | /** | 228 | /** |
320 | * Sends an already built message on a channel. | 229 | * Destroy channel, based on the other peer closing the |
321 | * | 230 | * connection. Also needs to remove this channel from |
322 | * If the channel is on a loopback tunnel, notifies the appropriate destination | 231 | * the tunnel. |
323 | * client locally. | ||
324 | * | 232 | * |
325 | * On a normal channel passes the message to the tunnel for encryption and | 233 | * FIXME: need to make it possible to defer destruction until we have |
326 | * sending on a connection. | 234 | * received all messages up to the destroy, and right now the destroy |
235 | * message (and this API) fails to give is the information we need! | ||
327 | * | 236 | * |
328 | * This function DOES NOT save the message for retransmission. | 237 | * FIXME: also need to know if the other peer got a destroy from |
238 | * us before! | ||
329 | * | 239 | * |
330 | * @param message Message to send. Function makes a copy of it. | 240 | * @param ch channel to destroy |
331 | * @param ch Channel on which this message is transmitted. | 241 | * @param cti identifier of the connection that delivered the message, |
332 | * @param fwd Is this a fwd message? | 242 | * NULL during shutdown |
333 | * @param existing_copy This is a retransmission, don't save a copy. | ||
334 | */ | 243 | */ |
335 | void | 244 | void |
336 | GCCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | 245 | GCCH_handle_remote_destroy (struct CadetChannel *ch, |
337 | struct CadetChannel *ch, int fwd, | 246 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti); |
338 | void *existing_copy); | ||
339 | 247 | ||
340 | 248 | ||
341 | /** | 249 | /** |
342 | * Get the static string for identification of the channel. | 250 | * Handle data given by a client. |
343 | * | 251 | * |
344 | * @param ch Channel.i | 252 | * Check whether the client is allowed to send in this tunnel, save if |
253 | * channel is reliable and send an ACK to the client if there is still | ||
254 | * buffer space in the tunnel. | ||
345 | * | 255 | * |
346 | * @return Static string with the channel IDs. | 256 | * @param ch Channel. |
257 | * @param sender_ccn ccn of the sender | ||
258 | * @param buf payload to transmit. | ||
259 | * @param buf_len number of bytes in @a buf | ||
260 | * @return #GNUNET_OK if everything goes well, | ||
261 | * #GNUNET_SYSERR in case of an error. | ||
347 | */ | 262 | */ |
348 | const char * | 263 | int |
349 | GCCH_2s (const struct CadetChannel *ch); | 264 | GCCH_handle_local_data (struct CadetChannel *ch, |
350 | 265 | struct GNUNET_CADET_ClientChannelNumber sender_ccn, | |
351 | 266 | const char *buf, | |
267 | size_t buf_len); | ||
352 | 268 | ||
353 | 269 | ||
354 | #if 0 /* keep Emacsens' auto-indent happy */ | 270 | /** |
355 | { | 271 | * Handle ACK from client on local channel. |
356 | #endif | 272 | * |
357 | #ifdef __cplusplus | 273 | * @param ch channel to destroy |
358 | } | 274 | * @param client_ccn ccn of the client sending the ack |
359 | #endif | 275 | */ |
276 | void | ||
277 | GCCH_handle_local_ack (struct CadetChannel *ch, | ||
278 | struct GNUNET_CADET_ClientChannelNumber client_ccn); | ||
360 | 279 | ||
361 | /* ifndef GNUNET_SERVICE_CADET_CHANNEL_H */ | ||
362 | #endif | 280 | #endif |
363 | /* end of gnunet-service-cadet_channel.h */ | ||
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c index af27647b3..7b66f61a2 100644 --- a/src/cadet/gnunet-service-cadet_connection.c +++ b/src/cadet/gnunet-service-cadet_connection.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2001-2015 GNUnet e.V. | 3 | Copyright (C) 2001-2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -17,242 +17,126 @@ | |||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. | 18 | Boston, MA 02110-1301, USA. |
19 | */ | 19 | */ |
20 | |||
20 | /** | 21 | /** |
21 | * @file cadet/gnunet-service-cadet_connection.c | 22 | * @file cadet/gnunet-service-cadet_connection.c |
22 | * @brief GNUnet CADET service connection handling | 23 | * @brief management of CORE-level end-to-end connections; establishes |
24 | * end-to-end routes and transmits messages along the route | ||
23 | * @author Bartlomiej Polot | 25 | * @author Bartlomiej Polot |
26 | * @author Christian Grothoff | ||
24 | */ | 27 | */ |
25 | #include "platform.h" | 28 | #include "platform.h" |
26 | #include "gnunet_util_lib.h" | 29 | #include "gnunet-service-cadet_connection.h" |
30 | #include "gnunet-service-cadet_channel.h" | ||
31 | #include "gnunet-service-cadet_paths.h" | ||
32 | #include "gnunet-service-cadet_tunnels.h" | ||
33 | #include "gnunet_cadet_service.h" | ||
27 | #include "gnunet_statistics_service.h" | 34 | #include "gnunet_statistics_service.h" |
28 | #include "cadet_path.h" | ||
29 | #include "cadet_protocol.h" | 35 | #include "cadet_protocol.h" |
30 | #include "cadet.h" | ||
31 | #include "gnunet-service-cadet_connection.h" | ||
32 | #include "gnunet-service-cadet_peer.h" | ||
33 | #include "gnunet-service-cadet_tunnel.h" | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Should we run somewhat expensive checks on our invariants? | ||
38 | */ | ||
39 | #define CHECK_INVARIANTS 0 | ||
40 | |||
41 | |||
42 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-con",__VA_ARGS__) | ||
43 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__) | ||
44 | |||
45 | |||
46 | #define CADET_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\ | ||
47 | GNUNET_TIME_UNIT_MINUTES,\ | ||
48 | 10) | ||
49 | #define AVG_MSGS 32 | ||
50 | |||
51 | |||
52 | /******************************************************************************/ | ||
53 | /******************************** STRUCTS **********************************/ | ||
54 | /******************************************************************************/ | ||
55 | |||
56 | /** | ||
57 | * Handle for messages queued but not yet sent. | ||
58 | */ | ||
59 | struct CadetConnectionQueue | ||
60 | { | ||
61 | 36 | ||
62 | struct CadetConnectionQueue *next; | ||
63 | struct CadetConnectionQueue *prev; | ||
64 | 37 | ||
65 | /** | 38 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-con",__VA_ARGS__) |
66 | * Peer queue handle, to cancel if necessary. | ||
67 | */ | ||
68 | struct CadetPeerQueue *peer_q; | ||
69 | |||
70 | /** | ||
71 | * Continuation to call once sent. | ||
72 | */ | ||
73 | GCC_sent cont; | ||
74 | |||
75 | /** | ||
76 | * Closure for @e cont. | ||
77 | */ | ||
78 | void *cont_cls; | ||
79 | |||
80 | /** | ||
81 | * Was this a forced message? (Do not account for it) | ||
82 | */ | ||
83 | int forced; | ||
84 | }; | ||
85 | 39 | ||
86 | 40 | ||
87 | /** | 41 | /** |
88 | * Struct to encapsulate all the Flow Control information to a peer to which | 42 | * All the states a connection can be in. |
89 | * we are directly connected (on a core level). | ||
90 | */ | 43 | */ |
91 | struct CadetFlowControl | 44 | enum CadetConnectionState |
92 | { | 45 | { |
93 | /** | 46 | /** |
94 | * Connection this controls. | 47 | * Uninitialized status, we have not yet even gotten the message queue. |
95 | */ | ||
96 | struct CadetConnection *c; | ||
97 | |||
98 | struct CadetConnectionQueue *q_head; | ||
99 | struct CadetConnectionQueue *q_tail; | ||
100 | |||
101 | /** | ||
102 | * How many messages are in the queue on this connection. | ||
103 | */ | ||
104 | unsigned int queue_n; | ||
105 | |||
106 | /** | ||
107 | * How many messages do we accept in the queue. | ||
108 | * If 0, the connection is broken in this direction (next hop disconnected). | ||
109 | */ | ||
110 | unsigned int queue_max; | ||
111 | |||
112 | /** | ||
113 | * ID of the next packet to send. | ||
114 | */ | ||
115 | struct CadetEncryptedMessageIdentifier next_pid; | ||
116 | |||
117 | /** | ||
118 | * ID of the last packet sent towards the peer. | ||
119 | */ | ||
120 | struct CadetEncryptedMessageIdentifier last_pid_sent; | ||
121 | |||
122 | /** | ||
123 | * ID of the last packet received from the peer. | ||
124 | */ | ||
125 | struct CadetEncryptedMessageIdentifier last_pid_recv; | ||
126 | |||
127 | /** | ||
128 | * Bitmap of past 32 messages received: | ||
129 | * - LSB being @c last_pid_recv. | ||
130 | * - MSB being @c last_pid_recv - 31 (mod UINTMAX). | ||
131 | */ | ||
132 | uint32_t recv_bitmap; | ||
133 | |||
134 | /** | ||
135 | * Last ACK sent to the peer (peer is not allowed to send | ||
136 | * messages with PIDs higher than this value). | ||
137 | */ | 48 | */ |
138 | struct CadetEncryptedMessageIdentifier last_ack_sent; | 49 | CADET_CONNECTION_NEW, |
139 | 50 | ||
140 | /** | 51 | /** |
141 | * Last ACK sent towards the origin (for traffic towards leaf node). | 52 | * Connection create message in queue, awaiting transmission by CORE. |
142 | */ | 53 | */ |
143 | struct CadetEncryptedMessageIdentifier last_ack_recv; | 54 | CADET_CONNECTION_SENDING_CREATE, |
144 | 55 | ||
145 | /** | 56 | /** |
146 | * Task to poll the peer in case of a lost ACK causes stall. | 57 | * Connection create message sent, waiting for ACK. |
147 | */ | 58 | */ |
148 | struct GNUNET_SCHEDULER_Task *poll_task; | 59 | CADET_CONNECTION_SENT, |
149 | 60 | ||
150 | /** | 61 | /** |
151 | * How frequently to poll for ACKs. | 62 | * We are an inbound connection, and received a CREATE. Need to |
63 | * send an CREATE_ACK back. | ||
152 | */ | 64 | */ |
153 | struct GNUNET_TIME_Relative poll_time; | 65 | CADET_CONNECTION_CREATE_RECEIVED, |
154 | 66 | ||
155 | /** | 67 | /** |
156 | * Queued poll message, to cancel if not necessary anymore (got ACK). | 68 | * Connection confirmed, ready to carry traffic. |
157 | */ | 69 | */ |
158 | struct CadetConnectionQueue *poll_msg; | 70 | CADET_CONNECTION_READY |
159 | 71 | ||
160 | /** | ||
161 | * Queued poll message, to cancel if not necessary anymore (got ACK). | ||
162 | */ | ||
163 | struct CadetConnectionQueue *ack_msg; | ||
164 | }; | 72 | }; |
165 | 73 | ||
74 | |||
166 | /** | 75 | /** |
167 | * Keep a record of the last messages sent on this connection. | 76 | * Low-level connection to a destination. |
168 | */ | 77 | */ |
169 | struct CadetConnectionPerformance | 78 | struct CadetConnection |
170 | { | 79 | { |
171 | /** | ||
172 | * Circular buffer for storing measurements. | ||
173 | */ | ||
174 | double usecsperbyte[AVG_MSGS]; | ||
175 | 80 | ||
176 | /** | 81 | /** |
177 | * Running average of @c usecsperbyte. | 82 | * ID of the connection. |
178 | */ | ||
179 | double avg; | ||
180 | |||
181 | /** | ||
182 | * How many values of @c usecsperbyte are valid. | ||
183 | */ | ||
184 | uint16_t size; | ||
185 | |||
186 | /** | ||
187 | * Index of the next "free" position in @c usecsperbyte. | ||
188 | */ | 83 | */ |
189 | uint16_t idx; | 84 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; |
190 | }; | ||
191 | |||
192 | 85 | ||
193 | /** | ||
194 | * Struct containing all information regarding a connection to a peer. | ||
195 | */ | ||
196 | struct CadetConnection | ||
197 | { | ||
198 | /** | 86 | /** |
199 | * Tunnel this connection is part of. | 87 | * To which peer does this connection go? |
200 | */ | 88 | */ |
201 | struct CadetTunnel *t; | 89 | struct CadetPeer *destination; |
202 | 90 | ||
203 | /** | 91 | /** |
204 | * Flow control information for traffic fwd. | 92 | * Which tunnel is using this connection? |
205 | */ | 93 | */ |
206 | struct CadetFlowControl fwd_fc; | 94 | struct CadetTConnection *ct; |
207 | 95 | ||
208 | /** | 96 | /** |
209 | * Flow control information for traffic bck. | 97 | * Path we are using to our destination. |
210 | */ | 98 | */ |
211 | struct CadetFlowControl bck_fc; | 99 | struct CadetPeerPath *path; |
212 | 100 | ||
213 | /** | 101 | /** |
214 | * Measure connection performance on the endpoint. | 102 | * Pending message, NULL if we are ready to transmit. |
215 | */ | 103 | */ |
216 | struct CadetConnectionPerformance *perf; | 104 | struct GNUNET_MQ_Envelope *env; |
217 | 105 | ||
218 | /** | 106 | /** |
219 | * ID of the connection. | 107 | * Handle for calling #GCP_request_mq_cancel() once we are finished. |
220 | */ | 108 | */ |
221 | struct GNUNET_CADET_ConnectionTunnelIdentifier id; | 109 | struct GCP_MessageQueueManager *mq_man; |
222 | 110 | ||
223 | /** | 111 | /** |
224 | * Path being used for the tunnel. At the origin of the connection | 112 | * Task for connection maintenance. |
225 | * it's a pointer to the destination's path pool, otherwise just a copy. | ||
226 | */ | 113 | */ |
227 | struct CadetPeerPath *path; | 114 | struct GNUNET_SCHEDULER_Task *task; |
228 | 115 | ||
229 | /** | 116 | /** |
230 | * Task to keep the used paths alive at the owner, | 117 | * Queue entry for keepalive messages. |
231 | * time tunnel out on all the other peers. | ||
232 | */ | 118 | */ |
233 | struct GNUNET_SCHEDULER_Task *fwd_maintenance_task; | 119 | struct CadetTunnelQueueEntry *keepalive_qe; |
234 | 120 | ||
235 | /** | 121 | /** |
236 | * Task to keep the used paths alive at the destination, | 122 | * Function to call once we are ready to transmit. |
237 | * time tunnel out on all the other peers. | ||
238 | */ | 123 | */ |
239 | struct GNUNET_SCHEDULER_Task *bck_maintenance_task; | 124 | GCC_ReadyCallback ready_cb; |
240 | 125 | ||
241 | /** | 126 | /** |
242 | * Queue handle for maintainance traffic. One handle for FWD and BCK since | 127 | * Closure for @e ready_cb. |
243 | * one peer never needs to maintain both directions (no loopback connections). | ||
244 | */ | 128 | */ |
245 | struct CadetPeerQueue *maintenance_q; | 129 | void *ready_cb_cls; |
246 | 130 | ||
247 | /** | 131 | /** |
248 | * Should equal #get_next_hop(), or NULL if that peer disconnected. | 132 | * How long do we wait before we try again with a CREATE message? |
249 | */ | 133 | */ |
250 | struct CadetPeer *next_peer; | 134 | struct GNUNET_TIME_Relative retry_delay; |
251 | 135 | ||
252 | /** | 136 | /** |
253 | * Should equal #get_prev_hop(), or NULL if that peer disconnected. | 137 | * Performance metrics for this connection. |
254 | */ | 138 | */ |
255 | struct CadetPeer *prev_peer; | 139 | struct CadetConnectionMetrics metrics; |
256 | 140 | ||
257 | /** | 141 | /** |
258 | * State of the connection. | 142 | * State of the connection. |
@@ -260,221 +144,36 @@ struct CadetConnection | |||
260 | enum CadetConnectionState state; | 144 | enum CadetConnectionState state; |
261 | 145 | ||
262 | /** | 146 | /** |
263 | * Position of the local peer in the path. | 147 | * Options for the route, control buffering. |
264 | */ | 148 | */ |
265 | unsigned int own_pos; | 149 | enum GNUNET_CADET_ChannelOption options; |
266 | 150 | ||
267 | /** | 151 | /** |
268 | * Pending message count. | 152 | * How many latency observations did we make for this connection? |
269 | */ | 153 | */ |
270 | unsigned int pending_messages; | 154 | unsigned int latency_datapoints; |
271 | 155 | ||
272 | /** | 156 | /** |
273 | * Destroy flag: | 157 | * Offset of our @e destination in @e path. |
274 | * - if 0, connection in use. | ||
275 | * - if 1, destroy on last message. | ||
276 | * - if 2, connection is being destroyed don't re-enter. | ||
277 | */ | 158 | */ |
278 | int destroy; | 159 | unsigned int off; |
279 | 160 | ||
280 | /** | 161 | /** |
281 | * In-connection-map flag. Sometimes, when @e destroy is set but | 162 | * Are we ready to transmit via @e mq_man right now? |
282 | * actual destruction is delayed to enable us to finish processing | ||
283 | * queues (i.e. in the direction that is still working), we remove | ||
284 | * the connection from the map to prevent it from still being | ||
285 | * found (and used) by accident. This flag is set to #GNUNET_YES | ||
286 | * for a connection that is not in the #connections map. Should | ||
287 | * only be #GNUNET_YES if #destroy is also non-zero. | ||
288 | */ | 163 | */ |
289 | int was_removed; | 164 | int mqm_ready; |
290 | 165 | ||
291 | /** | ||
292 | * Counter to do exponential backoff when creating a connection (max 64). | ||
293 | */ | ||
294 | unsigned short create_retry; | ||
295 | |||
296 | /** | ||
297 | * Task to check if connection has duplicates. | ||
298 | */ | ||
299 | struct GNUNET_SCHEDULER_Task *check_duplicates_task; | ||
300 | }; | 166 | }; |
301 | 167 | ||
302 | 168 | ||
303 | /******************************************************************************/ | ||
304 | /******************************* GLOBALS ***********************************/ | ||
305 | /******************************************************************************/ | ||
306 | |||
307 | /** | ||
308 | * Global handle to the statistics service. | ||
309 | */ | ||
310 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
311 | |||
312 | /** | ||
313 | * Local peer own ID (memory efficient handle). | ||
314 | */ | ||
315 | extern GNUNET_PEER_Id myid; | ||
316 | |||
317 | /** | ||
318 | * Local peer own ID (full value). | ||
319 | */ | ||
320 | extern struct GNUNET_PeerIdentity my_full_id; | ||
321 | |||
322 | /** | ||
323 | * Connections known, indexed by cid (CadetConnection). | ||
324 | */ | ||
325 | static struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
326 | |||
327 | /** | ||
328 | * How many connections are we willing to maintain. | ||
329 | * Local connections are always allowed, | ||
330 | * even if there are more connections than max. | ||
331 | */ | ||
332 | static unsigned long long max_connections; | ||
333 | |||
334 | /** | ||
335 | * How many messages *in total* are we willing to queue, divide by number of | ||
336 | * connections to get connection queue size. | ||
337 | */ | ||
338 | static unsigned long long max_msgs_queue; | ||
339 | |||
340 | /** | ||
341 | * How often to send path keepalives. Paths timeout after 4 missed. | ||
342 | */ | ||
343 | static struct GNUNET_TIME_Relative refresh_connection_time; | ||
344 | |||
345 | /** | ||
346 | * How often to send path create / ACKs. | ||
347 | */ | ||
348 | static struct GNUNET_TIME_Relative create_connection_time; | ||
349 | |||
350 | |||
351 | /******************************************************************************/ | ||
352 | /******************************** STATIC ***********************************/ | ||
353 | /******************************************************************************/ | ||
354 | |||
355 | |||
356 | |||
357 | #if 0 // avoid compiler warning for unused static function | ||
358 | static void | ||
359 | fc_debug (struct CadetFlowControl *fc) | ||
360 | { | ||
361 | LOG (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n", | ||
362 | ntohl (fc->last_pid_recv.pid), | ||
363 | ntohl (fc->last_ack_sent.pid)); | ||
364 | LOG (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n", | ||
365 | fc->last_pid_sent, fc->last_ack_recv); | ||
366 | LOG (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n", | ||
367 | fc->queue_n, fc->queue_max); | ||
368 | } | ||
369 | |||
370 | static void | ||
371 | connection_debug (struct CadetConnection *c) | ||
372 | { | ||
373 | if (NULL == c) | ||
374 | { | ||
375 | LOG (GNUNET_ERROR_TYPE_INFO, "DEBUG NULL CONNECTION\n"); | ||
376 | return; | ||
377 | } | ||
378 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n", | ||
379 | peer2s (c->t->peer), GCC_2s (c)); | ||
380 | LOG (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n", | ||
381 | c->state, c->pending_messages); | ||
382 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n"); | ||
383 | fc_debug (&c->fwd_fc); | ||
384 | LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n"); | ||
385 | fc_debug (&c->bck_fc); | ||
386 | } | ||
387 | #endif | ||
388 | |||
389 | |||
390 | /** | ||
391 | * Schedule next keepalive task, taking in consideration | ||
392 | * the connection state and number of retries. | ||
393 | * | ||
394 | * @param c Connection for which to schedule the next keepalive. | ||
395 | * @param fwd Direction for the next keepalive. | ||
396 | */ | ||
397 | static void | ||
398 | schedule_next_keepalive (struct CadetConnection *c, int fwd); | ||
399 | |||
400 | |||
401 | /** | ||
402 | * Resets the connection timeout task, some other message has done the | ||
403 | * task's job. | ||
404 | * - For the first peer on the direction this means to send | ||
405 | * a keepalive or a path confirmation message (either create or ACK). | ||
406 | * - For all other peers, this means to destroy the connection, | ||
407 | * due to lack of activity. | ||
408 | * Starts the timeout if no timeout was running (connection just created). | ||
409 | * | ||
410 | * @param c Connection whose timeout to reset. | ||
411 | * @param fwd Is this forward? | ||
412 | */ | ||
413 | static void | ||
414 | connection_reset_timeout (struct CadetConnection *c, int fwd); | ||
415 | |||
416 | |||
417 | /** | ||
418 | * Get string description for tunnel state. Reentrant. | ||
419 | * | ||
420 | * @param s Tunnel state. | ||
421 | * | ||
422 | * @return String representation. | ||
423 | */ | ||
424 | static const char * | ||
425 | GCC_state2s (enum CadetConnectionState s) | ||
426 | { | ||
427 | switch (s) | ||
428 | { | ||
429 | case CADET_CONNECTION_NEW: | ||
430 | return "CADET_CONNECTION_NEW"; | ||
431 | case CADET_CONNECTION_SENT: | ||
432 | return "CADET_CONNECTION_SENT"; | ||
433 | case CADET_CONNECTION_ACK: | ||
434 | return "CADET_CONNECTION_ACK"; | ||
435 | case CADET_CONNECTION_READY: | ||
436 | return "CADET_CONNECTION_READY"; | ||
437 | case CADET_CONNECTION_DESTROYED: | ||
438 | return "CADET_CONNECTION_DESTROYED"; | ||
439 | case CADET_CONNECTION_BROKEN: | ||
440 | return "CADET_CONNECTION_BROKEN"; | ||
441 | default: | ||
442 | GNUNET_break (0); | ||
443 | LOG (GNUNET_ERROR_TYPE_ERROR, " conn state %u unknown!\n", s); | ||
444 | return "CADET_CONNECTION_STATE_ERROR"; | ||
445 | } | ||
446 | } | ||
447 | |||
448 | |||
449 | /** | 169 | /** |
450 | * Initialize a Flow Control structure to the initial state. | 170 | * Lookup a connection by its identifier. |
451 | * | 171 | * |
452 | * @param fc Flow Control structure to initialize. | 172 | * @param cid identifier to resolve |
173 | * @return NULL if connection was not found | ||
453 | */ | 174 | */ |
454 | static void | 175 | struct CadetConnection * |
455 | fc_init (struct CadetFlowControl *fc) | 176 | GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) |
456 | { | ||
457 | fc->next_pid.pid = 0; | ||
458 | fc->last_pid_sent.pid = htonl (UINT32_MAX); | ||
459 | fc->last_pid_recv.pid = htonl (UINT32_MAX); | ||
460 | fc->last_ack_sent.pid = (uint32_t) 0; | ||
461 | fc->last_ack_recv.pid = (uint32_t) 0; | ||
462 | fc->poll_task = NULL; | ||
463 | fc->poll_time = GNUNET_TIME_UNIT_SECONDS; | ||
464 | fc->queue_n = 0; | ||
465 | fc->queue_max = (max_msgs_queue / max_connections) + 1; | ||
466 | } | ||
467 | |||
468 | |||
469 | /** | ||
470 | * Find a connection. | ||
471 | * | ||
472 | * @param cid Connection ID. | ||
473 | * | ||
474 | * @return conntection with the given ID @cid or NULL if not found. | ||
475 | */ | ||
476 | static struct CadetConnection * | ||
477 | connection_get (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
478 | { | 177 | { |
479 | return GNUNET_CONTAINER_multishortmap_get (connections, | 178 | return GNUNET_CONTAINER_multishortmap_get (connections, |
480 | &cid->connection_of_tunnel); | 179 | &cid->connection_of_tunnel); |
@@ -482,3232 +181,911 @@ connection_get (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | |||
482 | 181 | ||
483 | 182 | ||
484 | /** | 183 | /** |
485 | * Change the connection state. Cannot change a connection marked as destroyed. | 184 | * Update the connection state. Also triggers the necessary |
185 | * MQM notifications. | ||
486 | * | 186 | * |
487 | * @param c Connection to change. | 187 | * @param cc connection to update the state for |
488 | * @param state New state to set. | 188 | * @param new_state new state for @a cc |
189 | * @param new_mqm_ready new `mqm_ready` state for @a cc | ||
489 | */ | 190 | */ |
490 | static void | 191 | static void |
491 | connection_change_state (struct CadetConnection* c, | 192 | update_state (struct CadetConnection *cc, |
492 | enum CadetConnectionState state) | 193 | enum CadetConnectionState new_state, |
194 | int new_mqm_ready) | ||
493 | { | 195 | { |
494 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 196 | int old_ready; |
495 | "Connection %s state %s -> %s\n", | 197 | int new_ready; |
496 | GCC_2s (c), GCC_state2s (c->state), GCC_state2s (state)); | ||
497 | if (CADET_CONNECTION_DESTROYED <= c->state) /* Destroyed or broken. */ | ||
498 | { | ||
499 | LOG (GNUNET_ERROR_TYPE_DEBUG, "state not changing anymore\n"); | ||
500 | return; | ||
501 | } | ||
502 | c->state = state; | ||
503 | if (CADET_CONNECTION_READY == state) | ||
504 | c->create_retry = 1; | ||
505 | } | ||
506 | |||
507 | 198 | ||
508 | /** | 199 | if ( (new_state == cc->state) && |
509 | * Mark a connection as "destroyed", to send all pending traffic and freeing | 200 | (new_mqm_ready == cc->mqm_ready) ) |
510 | * all associated resources, without accepting new status changes on it. | 201 | return; /* no change, nothing to do */ |
511 | * | 202 | old_ready = ( (CADET_CONNECTION_READY == cc->state) && |
512 | * @param c Connection to mark as destroyed. | 203 | (GNUNET_YES == cc->mqm_ready) ); |
513 | */ | 204 | new_ready = ( (CADET_CONNECTION_READY == new_state) && |
514 | static void | 205 | (GNUNET_YES == new_mqm_ready) ); |
515 | mark_destroyed (struct CadetConnection *c) | 206 | cc->state = new_state; |
516 | { | 207 | cc->mqm_ready = new_mqm_ready; |
517 | c->destroy = GNUNET_YES; | 208 | if (old_ready != new_ready) |
518 | connection_change_state (c, CADET_CONNECTION_DESTROYED); | 209 | cc->ready_cb (cc->ready_cb_cls, |
210 | new_ready); | ||
519 | } | 211 | } |
520 | 212 | ||
521 | 213 | ||
522 | /** | 214 | /** |
523 | * Function called if a connection has been stalled for a while, | 215 | * Destroy a connection, part of the internal implementation. Called |
524 | * possibly due to a missed ACK. Poll the neighbor about its ACK status. | 216 | * only from #GCC_destroy_from_core() or #GCC_destroy_from_tunnel(). |
525 | * | ||
526 | * @param cls Closure (poll ctx). | ||
527 | */ | ||
528 | static void | ||
529 | send_poll (void *cls); | ||
530 | |||
531 | |||
532 | /** | ||
533 | * Send an ACK on the connection, informing the predecessor about | ||
534 | * the available buffer space. Should not be called in case the peer | ||
535 | * is origin (no predecessor) in the @c fwd direction. | ||
536 | * | ||
537 | * Note that for fwd ack, the FWD mean forward *traffic* (root->dest), | ||
538 | * the ACK itself goes "back" (dest->root). | ||
539 | * | 217 | * |
540 | * @param c Connection on which to send the ACK. | 218 | * @param cc connection to destroy |
541 | * @param buffer How much space free to advertise? | ||
542 | * @param fwd Is this FWD ACK? (Going dest -> root) | ||
543 | * @param force Don't optimize out. | ||
544 | */ | 219 | */ |
545 | static void | 220 | static void |
546 | send_ack (struct CadetConnection *c, | 221 | GCC_destroy (struct CadetConnection *cc) |
547 | unsigned int buffer, | ||
548 | int fwd, | ||
549 | int force) | ||
550 | { | 222 | { |
551 | static struct CadetEncryptedMessageIdentifier zero; | ||
552 | struct CadetFlowControl *next_fc; | ||
553 | struct CadetFlowControl *prev_fc; | ||
554 | struct GNUNET_CADET_ConnectionEncryptedAckMessage msg; | ||
555 | struct CadetEncryptedMessageIdentifier ack_cemi; | ||
556 | int delta; | ||
557 | |||
558 | GCC_check_connections (); | ||
559 | GNUNET_assert (GNUNET_NO == GCC_is_origin (c, fwd)); | ||
560 | |||
561 | next_fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
562 | prev_fc = fwd ? &c->bck_fc : &c->fwd_fc; | ||
563 | |||
564 | LOG (GNUNET_ERROR_TYPE_DEBUG, "send %s ack on %s\n", | ||
565 | GC_f2s (fwd), GCC_2s (c)); | ||
566 | |||
567 | /* Check if we need to transmit the ACK. */ | ||
568 | delta = ntohl (prev_fc->last_ack_sent.pid) - ntohl (prev_fc->last_pid_recv.pid); | ||
569 | if (3 < delta && buffer < delta && GNUNET_NO == force) | ||
570 | { | ||
571 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, delta > 3\n"); | ||
572 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
573 | " last pid recv: %u, last ack sent: %u\n", | ||
574 | ntohl (prev_fc->last_pid_recv.pid), | ||
575 | ntohl (prev_fc->last_ack_sent.pid)); | ||
576 | GCC_check_connections (); | ||
577 | return; | ||
578 | } | ||
579 | |||
580 | /* Ok, ACK might be necessary, what PID to ACK? */ | ||
581 | ack_cemi.pid = htonl (ntohl (prev_fc->last_pid_recv.pid) + buffer); | ||
582 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 223 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
583 | " ACK %u, last PID %u, last ACK %u, qmax %u, q %u\n", | 224 | "Destroying %s\n", |
584 | ntohl (ack_cemi.pid), | 225 | GCC_2s (cc)); |
585 | ntohl (prev_fc->last_pid_recv.pid), | 226 | if (NULL != cc->mq_man) |
586 | ntohl (prev_fc->last_ack_sent.pid), | ||
587 | next_fc->queue_max, next_fc->queue_n); | ||
588 | if ( (ack_cemi.pid == prev_fc->last_ack_sent.pid) && | ||
589 | (GNUNET_NO == force) ) | ||
590 | { | ||
591 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n"); | ||
592 | GCC_check_connections (); | ||
593 | return; | ||
594 | } | ||
595 | |||
596 | /* Check if message is already in queue */ | ||
597 | if (NULL != prev_fc->ack_msg) | ||
598 | { | ||
599 | if (GC_is_pid_bigger (ntohl (ack_cemi.pid), | ||
600 | ntohl (prev_fc->last_ack_sent.pid))) | ||
601 | { | ||
602 | LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n"); | ||
603 | GCC_cancel (prev_fc->ack_msg); | ||
604 | /* GCC_cancel triggers ack_sent(), which clears fc->ack_msg */ | ||
605 | } | ||
606 | else | ||
607 | { | ||
608 | LOG (GNUNET_ERROR_TYPE_DEBUG, " same ACK already in queue\n"); | ||
609 | GCC_check_connections (); | ||
610 | return; | ||
611 | } | ||
612 | } | ||
613 | GNUNET_break (GC_is_pid_bigger (ntohl (ack_cemi.pid), | ||
614 | ntohl (prev_fc->last_ack_sent.pid))); | ||
615 | prev_fc->last_ack_sent = ack_cemi; | ||
616 | |||
617 | /* Build ACK message and send on conn */ | ||
618 | msg.header.size = htons (sizeof (msg)); | ||
619 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK); | ||
620 | msg.cemi_max = ack_cemi; | ||
621 | msg.cid = c->id; | ||
622 | |||
623 | prev_fc->ack_msg = GCC_send_prebuilt_message (&msg.header, | ||
624 | UINT16_MAX, | ||
625 | zero, | ||
626 | c, | ||
627 | !fwd, | ||
628 | GNUNET_YES, | ||
629 | NULL, NULL); | ||
630 | GNUNET_assert (NULL != prev_fc->ack_msg); | ||
631 | GCC_check_connections (); | ||
632 | } | ||
633 | |||
634 | |||
635 | /** | ||
636 | * Update performance information if we are a connection's endpoint. | ||
637 | * | ||
638 | * @param c Connection to update. | ||
639 | * @param wait How much time did we wait to send the last message. | ||
640 | * @param size Size of the last message. | ||
641 | */ | ||
642 | static void | ||
643 | update_perf (struct CadetConnection *c, | ||
644 | struct GNUNET_TIME_Relative wait, | ||
645 | uint16_t size) | ||
646 | { | ||
647 | struct CadetConnectionPerformance *p; | ||
648 | double usecsperbyte; | ||
649 | |||
650 | if (NULL == c->perf) | ||
651 | return; /* Only endpoints are interested in timing. */ | ||
652 | |||
653 | p = c->perf; | ||
654 | usecsperbyte = ((double) wait.rel_value_us) / size; | ||
655 | if (p->size == AVG_MSGS) | ||
656 | { | ||
657 | /* Array is full. Substract oldest value, add new one and store. */ | ||
658 | p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS); | ||
659 | p->usecsperbyte[p->idx] = usecsperbyte; | ||
660 | p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS); | ||
661 | } | ||
662 | else | ||
663 | { | ||
664 | /* Array not yet full. Add current value to avg and store. */ | ||
665 | p->usecsperbyte[p->idx] = usecsperbyte; | ||
666 | p->avg *= p->size; | ||
667 | p->avg += p->usecsperbyte[p->idx]; | ||
668 | p->size++; | ||
669 | p->avg /= p->size; | ||
670 | } | ||
671 | p->idx = (p->idx + 1) % AVG_MSGS; | ||
672 | } | ||
673 | |||
674 | |||
675 | /** | ||
676 | * Callback called when a connection queued message is sent. | ||
677 | * | ||
678 | * Calculates the average time and connection packet tracking. | ||
679 | * | ||
680 | * @param cls Closure (ConnectionQueue Handle), can be NULL. | ||
681 | * @param c Connection this message was on. | ||
682 | * @param fwd Was this a FWD going message? | ||
683 | * @param sent Was it really sent? (Could have been canceled) | ||
684 | * @param type Type of message sent. | ||
685 | * @param payload_type Type of payload, if applicable. | ||
686 | * @param pid Message ID, or 0 if not applicable (create, destroy, etc). | ||
687 | * @param size Size of the message. | ||
688 | * @param wait Time spent waiting for core (only the time for THIS message) | ||
689 | */ | ||
690 | static void | ||
691 | conn_message_sent (void *cls, | ||
692 | struct CadetConnection *c, | ||
693 | int fwd, | ||
694 | int sent, | ||
695 | uint16_t type, | ||
696 | uint16_t payload_type, | ||
697 | struct CadetEncryptedMessageIdentifier pid, | ||
698 | size_t size, | ||
699 | struct GNUNET_TIME_Relative wait) | ||
700 | { | ||
701 | struct CadetConnectionQueue *q = cls; | ||
702 | struct CadetFlowControl *fc; | ||
703 | int forced; | ||
704 | |||
705 | GCC_check_connections (); | ||
706 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
707 | ">>> %s (%s %4u) on conn %s (%p) %s [%5u] in queue %s\n", | ||
708 | GC_m2s (type), GC_m2s (payload_type), | ||
709 | ntohl (pid.pid), | ||
710 | GCC_2s (c), | ||
711 | c, | ||
712 | GC_f2s (fwd), size, | ||
713 | GNUNET_STRINGS_relative_time_to_string (wait, GNUNET_YES)); | ||
714 | |||
715 | /* If c is NULL, nothing to update. */ | ||
716 | if (NULL == c) | ||
717 | { | ||
718 | if (type != GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN | ||
719 | && type != GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY) | ||
720 | { | ||
721 | LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n", | ||
722 | GC_m2s (type)); | ||
723 | } | ||
724 | GCC_check_connections (); | ||
725 | return; | ||
726 | } | ||
727 | |||
728 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s pid %u\n", | ||
729 | sent ? "" : "not ", GC_f2s (fwd), | ||
730 | GC_m2s (type), GC_m2s (payload_type), | ||
731 | ntohl (pid.pid)); | ||
732 | GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG); | ||
733 | |||
734 | /* Update flow control info. */ | ||
735 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
736 | |||
737 | if (NULL != q) | ||
738 | { | 227 | { |
739 | GNUNET_CONTAINER_DLL_remove (fc->q_head, fc->q_tail, q); | 228 | GCP_request_mq_cancel (cc->mq_man, |
740 | forced = q->forced; | 229 | NULL); |
741 | if (NULL != q->cont) | 230 | cc->mq_man = NULL; |
742 | { | ||
743 | LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cont\n"); | ||
744 | q->cont (q->cont_cls, c, q, type, fwd, size); | ||
745 | } | ||
746 | GNUNET_free (q); | ||
747 | } | 231 | } |
748 | else /* CONN_CREATE or CONN_ACK */ | 232 | if (NULL != cc->task) |
749 | { | 233 | { |
750 | GNUNET_assert (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED != type); | 234 | GNUNET_SCHEDULER_cancel (cc->task); |
751 | forced = GNUNET_YES; | 235 | cc->task = NULL; |
752 | } | 236 | } |
753 | 237 | if (NULL != cc->keepalive_qe) | |
754 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages); | ||
755 | c->pending_messages--; | ||
756 | if ( (GNUNET_YES == c->destroy) && | ||
757 | (0 == c->pending_messages) ) | ||
758 | { | 238 | { |
759 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 239 | GCT_send_cancel (cc->keepalive_qe); |
760 | "! destroying connection!\n"); | 240 | cc->keepalive_qe = NULL; |
761 | GCC_destroy (c); | ||
762 | GCC_check_connections (); | ||
763 | return; | ||
764 | } | 241 | } |
765 | 242 | GCPP_del_connection (cc->path, | |
766 | /* Send ACK if needed, after accounting for sent ID in fc->queue_n */ | 243 | cc->off, |
767 | switch (type) | 244 | cc); |
768 | { | 245 | for (unsigned int i=0;i<cc->off;i++) |
769 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | 246 | GCP_remove_connection (GCPP_get_peer_at_offset (cc->path, |
770 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK: | 247 | i), |
771 | c->maintenance_q = NULL; | 248 | cc); |
772 | /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */ | 249 | GNUNET_assert (GNUNET_YES == |
773 | if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE == type || !fwd) | 250 | GNUNET_CONTAINER_multishortmap_remove (connections, |
774 | schedule_next_keepalive (c, fwd); | 251 | &GCC_get_id (cc)->connection_of_tunnel, |
775 | break; | 252 | cc)); |
776 | 253 | GNUNET_free (cc); | |
777 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED: | ||
778 | if (GNUNET_YES == sent) | ||
779 | { | ||
780 | fc->last_pid_sent = pid; | ||
781 | if (GC_is_pid_bigger (ntohl (fc->last_pid_sent.pid) + 1, | ||
782 | ntohl (fc->last_ack_recv.pid)) ) | ||
783 | GCC_start_poll (c, fwd); | ||
784 | GCC_send_ack (c, fwd, GNUNET_NO); | ||
785 | connection_reset_timeout (c, fwd); | ||
786 | } | ||
787 | |||
788 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! Q_N- %p %u\n", fc, fc->queue_n); | ||
789 | if (GNUNET_NO == forced) | ||
790 | { | ||
791 | fc->queue_n--; | ||
792 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
793 | "! accounting pid %u\n", | ||
794 | ntohl (fc->last_pid_sent.pid)); | ||
795 | } | ||
796 | else | ||
797 | { | ||
798 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
799 | "! forced, Q_N not accounting pid %u\n", | ||
800 | ntohl (fc->last_pid_sent.pid)); | ||
801 | } | ||
802 | break; | ||
803 | |||
804 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX: | ||
805 | if (GNUNET_YES == sent) | ||
806 | connection_reset_timeout (c, fwd); | ||
807 | break; | ||
808 | |||
809 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL: | ||
810 | fc->poll_msg = NULL; | ||
811 | if (2 == c->destroy) | ||
812 | { | ||
813 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL canceled on shutdown\n"); | ||
814 | return; | ||
815 | } | ||
816 | if (0 == fc->queue_max) | ||
817 | { | ||
818 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL cancelled: neighbor disconnected\n"); | ||
819 | return; | ||
820 | } | ||
821 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL sent for %s, scheduling new one!\n", | ||
822 | GCC_2s (c)); | ||
823 | GNUNET_assert (NULL == fc->poll_task); | ||
824 | fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time); | ||
825 | fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, | ||
826 | &send_poll, fc); | ||
827 | LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task); | ||
828 | break; | ||
829 | |||
830 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK: | ||
831 | fc->ack_msg = NULL; | ||
832 | break; | ||
833 | |||
834 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
835 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
836 | break; | ||
837 | |||
838 | default: | ||
839 | LOG (GNUNET_ERROR_TYPE_ERROR, "%s unknown\n", GC_m2s (type)); | ||
840 | GNUNET_break (0); | ||
841 | break; | ||
842 | } | ||
843 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n"); | ||
844 | |||
845 | update_perf (c, wait, size); | ||
846 | GCC_check_connections (); | ||
847 | } | ||
848 | |||
849 | |||
850 | /** | ||
851 | * Get the previous hop in a connection | ||
852 | * | ||
853 | * @param c Connection. | ||
854 | * | ||
855 | * @return Previous peer in the connection. | ||
856 | */ | ||
857 | static struct CadetPeer * | ||
858 | get_prev_hop (const struct CadetConnection *c) | ||
859 | { | ||
860 | GNUNET_PEER_Id id; | ||
861 | |||
862 | if (NULL == c->path) | ||
863 | return NULL; | ||
864 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
865 | " get prev hop %s [%u/%u]\n", | ||
866 | GCC_2s (c), c->own_pos, c->path->length); | ||
867 | if (0 == c->own_pos || c->path->length < 2) | ||
868 | id = c->path->peers[0]; | ||
869 | else | ||
870 | id = c->path->peers[c->own_pos - 1]; | ||
871 | |||
872 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", | ||
873 | GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); | ||
874 | |||
875 | return GCP_get_short (id, GNUNET_YES); | ||
876 | } | ||
877 | |||
878 | |||
879 | /** | ||
880 | * Get the next hop in a connection | ||
881 | * | ||
882 | * @param c Connection. | ||
883 | * | ||
884 | * @return Next peer in the connection. | ||
885 | */ | ||
886 | static struct CadetPeer * | ||
887 | get_next_hop (const struct CadetConnection *c) | ||
888 | { | ||
889 | GNUNET_PEER_Id id; | ||
890 | |||
891 | if (NULL == c->path) | ||
892 | return NULL; | ||
893 | |||
894 | LOG (GNUNET_ERROR_TYPE_DEBUG, " get next hop %s [%u/%u]\n", | ||
895 | GCC_2s (c), c->own_pos, c->path->length); | ||
896 | if ((c->path->length - 1) == c->own_pos || c->path->length < 2) | ||
897 | id = c->path->peers[c->path->length - 1]; | ||
898 | else | ||
899 | id = c->path->peers[c->own_pos + 1]; | ||
900 | |||
901 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", | ||
902 | GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); | ||
903 | |||
904 | return GCP_get_short (id, GNUNET_YES); | ||
905 | } | 254 | } |
906 | 255 | ||
907 | 256 | ||
908 | /** | ||
909 | * Check that the direct neighbours (previous and next hop) | ||
910 | * are properly associated with this connection. | ||
911 | * | ||
912 | * @param c connection to check | ||
913 | */ | ||
914 | static void | ||
915 | check_neighbours (const struct CadetConnection *c) | ||
916 | { | ||
917 | if (NULL == c->path) | ||
918 | return; /* nothing to check */ | ||
919 | GCP_check_connection (get_next_hop (c), c); | ||
920 | GCP_check_connection (get_prev_hop (c), c); | ||
921 | } | ||
922 | |||
923 | 257 | ||
924 | /** | 258 | /** |
925 | * Helper for #GCC_check_connections(). Calls #check_neighbours(). | 259 | * Destroy a connection, called when the CORE layer is already done |
260 | * (i.e. has received a BROKEN message), but if we still have to | ||
261 | * communicate the destruction of the connection to the tunnel (if one | ||
262 | * exists). | ||
926 | * | 263 | * |
927 | * @param cls NULL | 264 | * @param cc connection to destroy |
928 | * @param key ignored | ||
929 | * @param value the `struct CadetConnection` to check | ||
930 | * @return #GNUNET_OK (continue to iterate) | ||
931 | */ | ||
932 | static int | ||
933 | check_connection (void *cls, | ||
934 | const struct GNUNET_ShortHashCode *key, | ||
935 | void *value) | ||
936 | { | ||
937 | struct CadetConnection *c = value; | ||
938 | |||
939 | check_neighbours (c); | ||
940 | return GNUNET_OK; | ||
941 | } | ||
942 | |||
943 | |||
944 | /** | ||
945 | * Check invariants for all connections using #check_neighbours(). | ||
946 | */ | 265 | */ |
947 | void | 266 | void |
948 | GCC_check_connections () | 267 | GCC_destroy_without_core (struct CadetConnection *cc) |
949 | { | ||
950 | if (0 == CHECK_INVARIANTS) | ||
951 | return; | ||
952 | if (NULL == connections) | ||
953 | return; | ||
954 | GNUNET_CONTAINER_multishortmap_iterate (connections, | ||
955 | &check_connection, | ||
956 | NULL); | ||
957 | } | ||
958 | |||
959 | |||
960 | /** | ||
961 | * Get the hop in a connection. | ||
962 | * | ||
963 | * @param c Connection. | ||
964 | * @param fwd Next in the FWD direction? | ||
965 | * | ||
966 | * @return Next peer in the connection. | ||
967 | */ | ||
968 | static struct CadetPeer * | ||
969 | get_hop (struct CadetConnection *c, int fwd) | ||
970 | { | ||
971 | return (fwd) ? get_next_hop (c) : get_prev_hop (c); | ||
972 | } | ||
973 | |||
974 | |||
975 | /** | ||
976 | * Get a bit mask for a message received out-of-order. | ||
977 | * | ||
978 | * @param last_pid_recv Last PID we received prior to the out-of-order. | ||
979 | * @param ooo_pid PID of the out-of-order message. | ||
980 | */ | ||
981 | static uint32_t | ||
982 | get_recv_bitmask (struct CadetEncryptedMessageIdentifier last_pid_recv, | ||
983 | struct CadetEncryptedMessageIdentifier ooo_pid) | ||
984 | { | ||
985 | // FIXME: should assert that the delta is in range... | ||
986 | return 1 << (ntohl (last_pid_recv.pid) - ntohl (ooo_pid.pid)); | ||
987 | } | ||
988 | |||
989 | |||
990 | /** | ||
991 | * Check is an out-of-order message is ok: | ||
992 | * - at most 31 messages behind. | ||
993 | * - not duplicate. | ||
994 | * | ||
995 | * @param last_pid_recv Last in-order PID received. | ||
996 | */ | ||
997 | static int | ||
998 | is_ooo_ok (struct CadetEncryptedMessageIdentifier last_pid_recv, | ||
999 | struct CadetEncryptedMessageIdentifier ooo_pid, | ||
1000 | uint32_t ooo_bitmap) | ||
1001 | { | ||
1002 | uint32_t mask; | ||
1003 | |||
1004 | if (GC_is_pid_bigger (ntohl (last_pid_recv.pid) - 31, | ||
1005 | ntohl (ooo_pid.pid))) | ||
1006 | return GNUNET_NO; | ||
1007 | |||
1008 | mask = get_recv_bitmask (last_pid_recv, | ||
1009 | ooo_pid); | ||
1010 | if (0 != (ooo_bitmap & mask)) | ||
1011 | return GNUNET_NO; | ||
1012 | |||
1013 | return GNUNET_YES; | ||
1014 | } | ||
1015 | |||
1016 | |||
1017 | /** | ||
1018 | * Is traffic coming from this sender 'FWD' traffic? | ||
1019 | * | ||
1020 | * @param c Connection to check. | ||
1021 | * @param sender Short peer identity of neighbor. | ||
1022 | * | ||
1023 | * @return #GNUNET_YES in case the sender is the 'prev' hop and therefore | ||
1024 | * the traffic is 'FWD'. | ||
1025 | * #GNUNET_NO for BCK. | ||
1026 | * #GNUNET_SYSERR for errors (sender isn't a hop in the connection). | ||
1027 | */ | ||
1028 | static int | ||
1029 | is_fwd (const struct CadetConnection *c, | ||
1030 | const struct CadetPeer *sender) | ||
1031 | { | ||
1032 | GNUNET_PEER_Id id; | ||
1033 | |||
1034 | id = GCP_get_short_id (sender); | ||
1035 | if (GCP_get_short_id (get_prev_hop (c)) == id) | ||
1036 | return GNUNET_YES; | ||
1037 | |||
1038 | if (GCP_get_short_id (get_next_hop (c)) == id) | ||
1039 | return GNUNET_NO; | ||
1040 | |||
1041 | return GNUNET_SYSERR; | ||
1042 | } | ||
1043 | |||
1044 | |||
1045 | /** | ||
1046 | * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE | ||
1047 | * or a first CONNECTION_ACK directed to us. | ||
1048 | * | ||
1049 | * @param c Connection to confirm. | ||
1050 | * @param fwd Should we send it FWD? (root->dest) | ||
1051 | * (First (~SYNACK) goes BCK, second (~ACK) goes FWD) | ||
1052 | */ | ||
1053 | static void | ||
1054 | send_connection_ack (struct CadetConnection *c, int fwd) | ||
1055 | { | ||
1056 | static struct CadetEncryptedMessageIdentifier zero; | ||
1057 | struct GNUNET_CADET_ConnectionCreateAckMessage msg; | ||
1058 | struct CadetTunnel *t; | ||
1059 | const uint16_t size = sizeof (struct GNUNET_CADET_ConnectionCreateAckMessage); | ||
1060 | const uint16_t type = GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK; | ||
1061 | |||
1062 | GCC_check_connections (); | ||
1063 | t = c->t; | ||
1064 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1065 | "==> %s ({ C %s ACK} 0) on conn %s (%p) %s [%5u]\n", | ||
1066 | GC_m2s (type), GC_f2s (!fwd), GCC_2s (c), c, GC_f2s (fwd), size); | ||
1067 | |||
1068 | msg.header.size = htons (size); | ||
1069 | msg.header.type = htons (type); | ||
1070 | msg.reserved = htonl (0); | ||
1071 | msg.cid = c->id; | ||
1072 | |||
1073 | GNUNET_assert (NULL == c->maintenance_q); | ||
1074 | c->maintenance_q = GCP_send (get_hop (c, fwd), | ||
1075 | &msg.header, | ||
1076 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK, | ||
1077 | zero, | ||
1078 | c, | ||
1079 | fwd, | ||
1080 | &conn_message_sent, NULL); | ||
1081 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (conn`ACK)\n", | ||
1082 | c, c->pending_messages); | ||
1083 | c->pending_messages++; | ||
1084 | |||
1085 | if (CADET_TUNNEL_NEW == GCT_get_cstate (t)) | ||
1086 | GCT_change_cstate (t, CADET_TUNNEL_WAITING); | ||
1087 | if (CADET_CONNECTION_READY != c->state) | ||
1088 | connection_change_state (c, CADET_CONNECTION_SENT); | ||
1089 | GCC_check_connections (); | ||
1090 | } | ||
1091 | |||
1092 | |||
1093 | /** | ||
1094 | * Send a notification that a connection is broken. | ||
1095 | * | ||
1096 | * @param c Connection that is broken. | ||
1097 | * @param id1 Peer that has disconnected. | ||
1098 | * @param id2 Peer that has disconnected. | ||
1099 | * @param fwd Direction towards which to send it. | ||
1100 | */ | ||
1101 | static void | ||
1102 | send_broken (struct CadetConnection *c, | ||
1103 | const struct GNUNET_PeerIdentity *id1, | ||
1104 | const struct GNUNET_PeerIdentity *id2, | ||
1105 | int fwd) | ||
1106 | { | ||
1107 | static struct CadetEncryptedMessageIdentifier zero; | ||
1108 | struct GNUNET_CADET_ConnectionBrokenMessage msg; | ||
1109 | |||
1110 | GCC_check_connections (); | ||
1111 | msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage)); | ||
1112 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
1113 | msg.cid = c->id; | ||
1114 | msg.reserved = htonl (0); | ||
1115 | msg.peer1 = *id1; | ||
1116 | msg.peer2 = *id2; | ||
1117 | (void) GCC_send_prebuilt_message (&msg.header, | ||
1118 | UINT16_MAX, | ||
1119 | zero, | ||
1120 | c, | ||
1121 | fwd, | ||
1122 | GNUNET_YES, | ||
1123 | NULL, NULL); | ||
1124 | GCC_check_connections (); | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | /** | ||
1129 | * Send a notification that a connection is broken, when a connection | ||
1130 | * isn't even known to the local peer or soon to be destroyed. | ||
1131 | * | ||
1132 | * @param connection_id Connection ID. | ||
1133 | * @param id1 Peer that has disconnected, probably local peer. | ||
1134 | * @param id2 Peer that has disconnected can be NULL if unknown. | ||
1135 | * @param neighbor Peer to notify (neighbor who sent the connection). | ||
1136 | */ | ||
1137 | static void | ||
1138 | send_broken_unknown (const struct GNUNET_CADET_ConnectionTunnelIdentifier *connection_id, | ||
1139 | const struct GNUNET_PeerIdentity *id1, | ||
1140 | const struct GNUNET_PeerIdentity *id2, | ||
1141 | struct CadetPeer *neighbor) | ||
1142 | { | ||
1143 | static struct CadetEncryptedMessageIdentifier zero; | ||
1144 | struct GNUNET_CADET_ConnectionBrokenMessage msg; | ||
1145 | |||
1146 | GCC_check_connections (); | ||
1147 | LOG (GNUNET_ERROR_TYPE_INFO, "--> BROKEN on unknown connection %s\n", | ||
1148 | GNUNET_sh2s (&connection_id->connection_of_tunnel)); | ||
1149 | |||
1150 | msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBrokenMessage)); | ||
1151 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
1152 | msg.cid = *connection_id; | ||
1153 | msg.reserved = htonl (0); | ||
1154 | msg.peer1 = *id1; | ||
1155 | if (NULL != id2) | ||
1156 | msg.peer2 = *id2; | ||
1157 | else | ||
1158 | memset (&msg.peer2, 0, sizeof (msg.peer2)); | ||
1159 | GNUNET_assert (NULL != GCP_send (neighbor, | ||
1160 | &msg.header, | ||
1161 | UINT16_MAX, | ||
1162 | zero, | ||
1163 | NULL, | ||
1164 | GNUNET_SYSERR, /* connection, fwd */ | ||
1165 | NULL, NULL)); /* continuation */ | ||
1166 | GCC_check_connections (); | ||
1167 | } | ||
1168 | |||
1169 | |||
1170 | /** | ||
1171 | * Send keepalive packets for a connection. | ||
1172 | * | ||
1173 | * @param c Connection to keep alive.. | ||
1174 | * @param fwd Is this a FWD keepalive? (owner -> dest). | ||
1175 | */ | ||
1176 | static void | ||
1177 | send_connection_keepalive (struct CadetConnection *c, int fwd) | ||
1178 | { | 268 | { |
1179 | struct GNUNET_MessageHeader msg; | 269 | if (NULL != cc->ct) |
1180 | struct CadetFlowControl *fc; | ||
1181 | int tunnel_ready; | ||
1182 | |||
1183 | GCC_check_connections (); | ||
1184 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1185 | "keepalive %s for connection %s\n", | ||
1186 | GC_f2s (fwd), GCC_2s (c)); | ||
1187 | |||
1188 | GNUNET_assert (NULL != c->t); | ||
1189 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
1190 | tunnel_ready = GNUNET_YES == GCT_has_queued_traffic (c->t) | ||
1191 | && CADET_TUNNEL_KEY_OK <= GCT_get_estate (c->t); | ||
1192 | if (0 < fc->queue_n || tunnel_ready) | ||
1193 | { | 270 | { |
1194 | LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, traffic in queue\n"); | 271 | GCT_connection_lost (cc->ct); |
1195 | return; | 272 | cc->ct = NULL; |
1196 | } | 273 | } |
1197 | 274 | GCC_destroy (cc); | |
1198 | GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO); | ||
1199 | |||
1200 | GNUNET_assert (NULL != c->t); | ||
1201 | msg.size = htons (sizeof (msg)); | ||
1202 | msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE); | ||
1203 | |||
1204 | GNUNET_assert (NULL == | ||
1205 | GCT_send_prebuilt_message (&msg, c->t, c, | ||
1206 | GNUNET_NO, NULL, NULL)); | ||
1207 | GCC_check_connections (); | ||
1208 | } | ||
1209 | |||
1210 | |||
1211 | /** | ||
1212 | * Send CONNECTION_{CREATE/ACK} packets for a connection. | ||
1213 | * | ||
1214 | * @param c Connection for which to send the message. | ||
1215 | * @param fwd If #GNUNET_YES, send CREATE, otherwise send ACK. | ||
1216 | */ | ||
1217 | static void | ||
1218 | connection_recreate (struct CadetConnection *c, int fwd) | ||
1219 | { | ||
1220 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1221 | "sending connection recreate\n"); | ||
1222 | if (fwd) | ||
1223 | GCC_send_create (c); | ||
1224 | else | ||
1225 | send_connection_ack (c, GNUNET_NO); | ||
1226 | } | 275 | } |
1227 | 276 | ||
1228 | 277 | ||
1229 | /** | 278 | /** |
1230 | * Generic connection timer management. | 279 | * Destroy a connection, called if the tunnel association with the |
1231 | * Depending on the role of the peer in the connection will send the | 280 | * connection was already broken, but we still need to notify the CORE |
1232 | * appropriate message (build or keepalive) | 281 | * layer about the breakage. |
1233 | * | 282 | * |
1234 | * @param c Conncetion to maintain. | 283 | * @param cc connection to destroy |
1235 | * @param fwd Is FWD? | ||
1236 | */ | 284 | */ |
1237 | static void | 285 | void |
1238 | connection_maintain (struct CadetConnection *c, int fwd) | 286 | GCC_destroy_without_tunnel (struct CadetConnection *cc) |
1239 | { | 287 | { |
1240 | if (GNUNET_NO != c->destroy) | 288 | cc->ct = NULL; |
289 | if ( (CADET_CONNECTION_SENDING_CREATE != cc->state) && | ||
290 | (NULL != cc->mq_man) ) | ||
1241 | { | 291 | { |
1242 | LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, being destroyed\n"); | 292 | struct GNUNET_MQ_Envelope *env; |
1243 | return; | 293 | struct GNUNET_CADET_ConnectionDestroyMessage *destroy_msg; |
1244 | } | ||
1245 | |||
1246 | if (NULL == c->t) | ||
1247 | { | ||
1248 | GNUNET_break (0); | ||
1249 | GCC_debug (c, GNUNET_ERROR_TYPE_ERROR); | ||
1250 | return; | ||
1251 | } | ||
1252 | 294 | ||
1253 | if (CADET_TUNNEL_SEARCHING == GCT_get_cstate (c->t)) | 295 | /* Need to notify next hop that we are down. */ |
1254 | { | 296 | env = GNUNET_MQ_msg (destroy_msg, |
1255 | /* If status is SEARCHING, why is there a connection? Should be WAITING */ | 297 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); |
1256 | GNUNET_break (0); | 298 | destroy_msg->cid = cc->cid; |
1257 | GCT_debug (c->t, GNUNET_ERROR_TYPE_ERROR); | 299 | GCP_request_mq_cancel (cc->mq_man, |
1258 | LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, tunnel SEARCHING\n"); | 300 | env); |
1259 | schedule_next_keepalive (c, fwd); | 301 | cc->mq_man = NULL; |
1260 | return; | ||
1261 | } | ||
1262 | switch (c->state) | ||
1263 | { | ||
1264 | case CADET_CONNECTION_NEW: | ||
1265 | GNUNET_break (0); | ||
1266 | /* fall-through */ | ||
1267 | case CADET_CONNECTION_SENT: | ||
1268 | connection_recreate (c, fwd); | ||
1269 | break; | ||
1270 | case CADET_CONNECTION_READY: | ||
1271 | send_connection_keepalive (c, fwd); | ||
1272 | break; | ||
1273 | default: | ||
1274 | break; | ||
1275 | } | 302 | } |
303 | GCC_destroy (cc); | ||
1276 | } | 304 | } |
1277 | 305 | ||
1278 | 306 | ||
1279 | /** | 307 | /** |
1280 | * Keep the connection alive. | 308 | * Return the tunnel associated with this connection. |
1281 | * | 309 | * |
1282 | * @param c Connection to keep alive. | 310 | * @param cc connection to query |
1283 | * @param fwd Direction. | 311 | * @return corresponding entry in the tunnel's connection list |
1284 | */ | 312 | */ |
1285 | static void | 313 | struct CadetTConnection * |
1286 | connection_keepalive (struct CadetConnection *c, | 314 | GCC_get_ct (struct CadetConnection *cc) |
1287 | int fwd) | ||
1288 | { | 315 | { |
1289 | GCC_check_connections (); | 316 | return cc->ct; |
1290 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1291 | "%s keepalive for %s\n", | ||
1292 | GC_f2s (fwd), GCC_2s (c)); | ||
1293 | |||
1294 | if (fwd) | ||
1295 | c->fwd_maintenance_task = NULL; | ||
1296 | else | ||
1297 | c->bck_maintenance_task = NULL; | ||
1298 | connection_maintain (c, fwd); | ||
1299 | GCC_check_connections (); | ||
1300 | /* Next execution will be scheduled by message_sent or _maintain*/ | ||
1301 | } | 317 | } |
1302 | 318 | ||
1303 | 319 | ||
1304 | /** | 320 | /** |
1305 | * Keep the connection alive in the FWD direction. | 321 | * Obtain performance @a metrics from @a cc. |
1306 | * | 322 | * |
1307 | * @param cls Closure (connection to keepalive). | 323 | * @param cc connection to query |
324 | * @return the metrics | ||
1308 | */ | 325 | */ |
1309 | static void | 326 | const struct CadetConnectionMetrics * |
1310 | connection_fwd_keepalive (void *cls) | 327 | GCC_get_metrics (struct CadetConnection *cc) |
1311 | { | 328 | { |
1312 | struct CadetConnection *c = cls; | 329 | return &cc->metrics; |
1313 | |||
1314 | GCC_check_connections (); | ||
1315 | connection_keepalive (c, | ||
1316 | GNUNET_YES); | ||
1317 | GCC_check_connections (); | ||
1318 | } | 330 | } |
1319 | 331 | ||
1320 | 332 | ||
1321 | /** | 333 | /** |
1322 | * Keep the connection alive in the BCK direction. | 334 | * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the |
335 | * tunnel to prevent it from timing out. | ||
1323 | * | 336 | * |
1324 | * @param cls Closure (connection to keepalive). | 337 | * @param cls the `struct CadetConnection` to keep alive. |
1325 | */ | 338 | */ |
1326 | static void | 339 | static void |
1327 | connection_bck_keepalive (void *cls) | 340 | send_keepalive (void *cls); |
1328 | { | ||
1329 | struct CadetConnection *c = cls; | ||
1330 | |||
1331 | GCC_check_connections (); | ||
1332 | connection_keepalive (c, | ||
1333 | GNUNET_NO); | ||
1334 | GCC_check_connections (); | ||
1335 | } | ||
1336 | 341 | ||
1337 | 342 | ||
1338 | /** | 343 | /** |
1339 | * Schedule next keepalive task, taking in consideration | 344 | * Keepalive was transmitted. Remember this, and possibly |
1340 | * the connection state and number of retries. | 345 | * schedule the next one. |
1341 | * | 346 | * |
1342 | * If the peer is not the origin, do nothing. | 347 | * @param cls the `struct CadetConnection` to keep alive. |
1343 | * | 348 | * @param cid identifier of the connection within the tunnel, NULL |
1344 | * @param c Connection for which to schedule the next keepalive. | 349 | * if transmission failed |
1345 | * @param fwd Direction for the next keepalive. | ||
1346 | */ | 350 | */ |
1347 | static void | 351 | static void |
1348 | schedule_next_keepalive (struct CadetConnection *c, int fwd) | 352 | keepalive_done (void *cls, |
353 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | ||
1349 | { | 354 | { |
1350 | struct GNUNET_TIME_Relative delay; | 355 | struct CadetConnection *cc = cls; |
1351 | struct GNUNET_SCHEDULER_Task * *task_id; | ||
1352 | GNUNET_SCHEDULER_TaskCallback keepalive_task; | ||
1353 | |||
1354 | GCC_check_connections (); | ||
1355 | if (GNUNET_NO == GCC_is_origin (c, fwd)) | ||
1356 | return; | ||
1357 | |||
1358 | /* Calculate delay to use, depending on the state of the connection */ | ||
1359 | if (CADET_CONNECTION_READY == c->state) | ||
1360 | { | ||
1361 | delay = refresh_connection_time; | ||
1362 | } | ||
1363 | else | ||
1364 | { | ||
1365 | if (1 > c->create_retry) | ||
1366 | c->create_retry = 1; | ||
1367 | delay = GNUNET_TIME_relative_saturating_multiply (create_connection_time, | ||
1368 | c->create_retry); | ||
1369 | if (c->create_retry < 64) // TODO make configurable | ||
1370 | c->create_retry *= 2; | ||
1371 | } | ||
1372 | |||
1373 | /* Select direction-dependent parameters */ | ||
1374 | if (GNUNET_YES == fwd) | ||
1375 | { | ||
1376 | task_id = &c->fwd_maintenance_task; | ||
1377 | keepalive_task = &connection_fwd_keepalive; | ||
1378 | } | ||
1379 | else | ||
1380 | { | ||
1381 | task_id = &c->bck_maintenance_task; | ||
1382 | keepalive_task = &connection_bck_keepalive; | ||
1383 | } | ||
1384 | 356 | ||
1385 | /* Check that no one scheduled it before us */ | 357 | cc->keepalive_qe = NULL; |
1386 | if (NULL != *task_id) | 358 | if ( (GNUNET_YES == cc->mqm_ready) && |
1387 | { | 359 | (NULL == cc->task) ) |
1388 | /* No need for a _break. It can happen for instance when sending a SYNACK | 360 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, |
1389 | * for a duplicate SYN: the first SYNACK scheduled the task. */ | 361 | &send_keepalive, |
1390 | GNUNET_SCHEDULER_cancel (*task_id); | 362 | cc); |
1391 | } | ||
1392 | |||
1393 | /* Schedule the task */ | ||
1394 | *task_id = GNUNET_SCHEDULER_add_delayed (delay, | ||
1395 | keepalive_task, | ||
1396 | c); | ||
1397 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1398 | "next keepalive for %s in in %s\n", | ||
1399 | GCC_2s (c), GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); | ||
1400 | GCC_check_connections (); | ||
1401 | } | 363 | } |
1402 | 364 | ||
1403 | 365 | ||
1404 | /** | 366 | /** |
1405 | * Cancel all transmissions that belong to a certain connection. | 367 | * Send a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE through the |
368 | * tunnel to prevent it from timing out. | ||
1406 | * | 369 | * |
1407 | * If the connection is scheduled for destruction and no more messages are left, | 370 | * @param cls the `struct CadetConnection` to keep alive. |
1408 | * the connection will be destroyed by the continuation call. | ||
1409 | * | ||
1410 | * @param c Connection which to cancel. Might be destroyed during this call. | ||
1411 | * @param fwd Cancel fwd traffic? | ||
1412 | */ | 371 | */ |
1413 | static void | 372 | static void |
1414 | connection_cancel_queues (struct CadetConnection *c, | 373 | send_keepalive (void *cls) |
1415 | int fwd) | ||
1416 | { | 374 | { |
1417 | struct CadetFlowControl *fc; | 375 | struct CadetConnection *cc = cls; |
376 | struct GNUNET_MessageHeader msg; | ||
1418 | 377 | ||
1419 | GCC_check_connections (); | 378 | cc->task = NULL; |
1420 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 379 | if (CADET_TUNNEL_KEY_OK != GCT_get_estate (cc->ct->t)) |
1421 | "Cancel %s queues for connection %s\n", | ||
1422 | GC_f2s (fwd), GCC_2s (c)); | ||
1423 | if (NULL == c) | ||
1424 | { | 380 | { |
1425 | GNUNET_break (0); | 381 | /* Tunnel not yet ready, wait with keepalives... */ |
382 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, | ||
383 | &send_keepalive, | ||
384 | cc); | ||
1426 | return; | 385 | return; |
1427 | } | 386 | } |
1428 | 387 | GNUNET_assert (NULL != cc->ct); | |
1429 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | 388 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); |
1430 | if (NULL != fc->poll_task) | 389 | GNUNET_assert (NULL == cc->keepalive_qe); |
1431 | { | ||
1432 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
1433 | fc->poll_task = NULL; | ||
1434 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cancelled POLL task for fc %p\n", fc); | ||
1435 | } | ||
1436 | if (NULL != fc->poll_msg) | ||
1437 | { | ||
1438 | GCC_cancel (fc->poll_msg); | ||
1439 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cancelled POLL msg for fc %p\n", fc); | ||
1440 | } | ||
1441 | |||
1442 | while (NULL != fc->q_head) | ||
1443 | { | ||
1444 | GCC_cancel (fc->q_head); | ||
1445 | } | ||
1446 | GCC_check_connections (); | ||
1447 | } | ||
1448 | |||
1449 | |||
1450 | /** | ||
1451 | * Function called if a connection has been stalled for a while, | ||
1452 | * possibly due to a missed ACK. Poll the neighbor about its ACK status. | ||
1453 | * | ||
1454 | * @param cls Closure (poll ctx). | ||
1455 | */ | ||
1456 | static void | ||
1457 | send_poll (void *cls) | ||
1458 | { | ||
1459 | static struct CadetEncryptedMessageIdentifier zero; | ||
1460 | struct CadetFlowControl *fc = cls; | ||
1461 | struct GNUNET_CADET_ConnectionHopByHopPollMessage msg; | ||
1462 | struct CadetConnection *c; | ||
1463 | int fwd; | ||
1464 | |||
1465 | fc->poll_task = NULL; | ||
1466 | GCC_check_connections (); | ||
1467 | c = fc->c; | ||
1468 | fwd = fc == &c->fwd_fc; | ||
1469 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Polling connection %s %s\n", | ||
1470 | GCC_2s (c), GC_f2s (fwd)); | ||
1471 | |||
1472 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL); | ||
1473 | msg.header.size = htons (sizeof (msg)); | ||
1474 | msg.cid = c->id; | ||
1475 | msg.cemi = fc->last_pid_sent; | ||
1476 | LOG (GNUNET_ERROR_TYPE_DEBUG, " last pid sent: %u\n", ntohl (fc->last_pid_sent.pid)); | ||
1477 | fc->poll_msg | ||
1478 | = GCC_send_prebuilt_message (&msg.header, | ||
1479 | UINT16_MAX, | ||
1480 | zero, | ||
1481 | c, | ||
1482 | fc == &c->fwd_fc, | ||
1483 | GNUNET_YES, | ||
1484 | NULL, | ||
1485 | NULL); | ||
1486 | GNUNET_assert (NULL != fc->poll_msg); | ||
1487 | GCC_check_connections (); | ||
1488 | } | ||
1489 | |||
1490 | |||
1491 | /** | ||
1492 | * Generic connection timeout implementation. | ||
1493 | * | ||
1494 | * Timeout function due to lack of keepalive/traffic from an endpoint. | ||
1495 | * Destroys connection if called. | ||
1496 | * | ||
1497 | * @param c Connection to destroy. | ||
1498 | * @param fwd Was the timeout from the origin? (FWD timeout) | ||
1499 | */ | ||
1500 | static void | ||
1501 | connection_timeout (struct CadetConnection *c, int fwd) | ||
1502 | { | ||
1503 | GCC_check_connections (); | ||
1504 | |||
1505 | LOG (GNUNET_ERROR_TYPE_INFO, | 390 | LOG (GNUNET_ERROR_TYPE_INFO, |
1506 | "Connection %s %s timed out. Destroying.\n", | 391 | "Sending KEEPALIVE on behalf of %s via %s\n", |
1507 | GCC_2s (c), | 392 | GCC_2s (cc), |
1508 | GC_f2s (fwd)); | 393 | GCT_2s (cc->ct->t)); |
1509 | GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG); | 394 | GNUNET_STATISTICS_update (stats, |
1510 | 395 | "# keepalives sent", | |
1511 | if (GCC_is_origin (c, fwd)) /* Loopback? Something is wrong! */ | 396 | 1, |
1512 | { | 397 | GNUNET_NO); |
1513 | GNUNET_break (0); | 398 | msg.size = htons (sizeof (msg)); |
1514 | return; | 399 | msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE); |
1515 | } | ||
1516 | |||
1517 | /* If dest, send "broken" notification. */ | ||
1518 | if (GCC_is_terminal (c, fwd)) | ||
1519 | { | ||
1520 | struct CadetPeer *next_hop; | ||
1521 | |||
1522 | next_hop = fwd ? get_prev_hop (c) : get_next_hop (c); | ||
1523 | send_broken_unknown (&c->id, &my_full_id, NULL, next_hop); | ||
1524 | } | ||
1525 | |||
1526 | GCC_destroy (c); | ||
1527 | GCC_check_connections (); | ||
1528 | } | ||
1529 | |||
1530 | |||
1531 | /** | ||
1532 | * Timeout function due to lack of keepalive/traffic from the owner. | ||
1533 | * Destroys connection if called. | ||
1534 | * | ||
1535 | * @param cls Closure (connection to destroy). | ||
1536 | */ | ||
1537 | static void | ||
1538 | connection_fwd_timeout (void *cls) | ||
1539 | { | ||
1540 | struct CadetConnection *c = cls; | ||
1541 | |||
1542 | c->fwd_maintenance_task = NULL; | ||
1543 | GCC_check_connections (); | ||
1544 | connection_timeout (c, GNUNET_YES); | ||
1545 | GCC_check_connections (); | ||
1546 | } | ||
1547 | |||
1548 | |||
1549 | /** | ||
1550 | * Timeout function due to lack of keepalive/traffic from the destination. | ||
1551 | * Destroys connection if called. | ||
1552 | * | ||
1553 | * @param cls Closure (connection to destroy). | ||
1554 | */ | ||
1555 | static void | ||
1556 | connection_bck_timeout (void *cls) | ||
1557 | { | ||
1558 | struct CadetConnection *c = cls; | ||
1559 | 400 | ||
1560 | c->bck_maintenance_task = NULL; | 401 | cc->keepalive_qe |
1561 | GCC_check_connections (); | 402 | = GCT_send (cc->ct->t, |
1562 | connection_timeout (c, GNUNET_NO); | 403 | &msg, |
1563 | GCC_check_connections (); | 404 | &keepalive_done, |
405 | cc); | ||
1564 | } | 406 | } |
1565 | 407 | ||
1566 | 408 | ||
1567 | /** | 409 | /** |
1568 | * Resets the connection timeout task, some other message has done the | 410 | * We sent a message for which we expect to receive an ACK via |
1569 | * task's job. | 411 | * the connection identified by @a cti. |
1570 | * - For the first peer on the direction this means to send | ||
1571 | * a keepalive or a path confirmation message (either create or ACK). | ||
1572 | * - For all other peers, this means to destroy the connection, | ||
1573 | * due to lack of activity. | ||
1574 | * Starts the timeout if no timeout was running (connection just created). | ||
1575 | * | ||
1576 | * @param c Connection whose timeout to reset. | ||
1577 | * @param fwd Is this forward? | ||
1578 | * | 412 | * |
1579 | * TODO use heap to improve efficiency of scheduler. | 413 | * @param cid connection identifier where we expect an ACK |
1580 | */ | 414 | */ |
1581 | static void | 415 | void |
1582 | connection_reset_timeout (struct CadetConnection *c, int fwd) | 416 | GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) |
1583 | { | 417 | { |
1584 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s reset timeout\n", GC_f2s (fwd)); | 418 | struct CadetConnection *cc; |
1585 | if (GCC_is_origin (c, fwd)) /* Startpoint */ | ||
1586 | { | ||
1587 | schedule_next_keepalive (c, fwd); | ||
1588 | if (NULL != c->maintenance_q) | ||
1589 | { | ||
1590 | GCP_send_cancel (c->maintenance_q); | ||
1591 | c->maintenance_q = NULL; /* Is set to NULL by conn_message_sent anyway */ | ||
1592 | } | ||
1593 | } | ||
1594 | else /* Relay, endpoint. */ | ||
1595 | { | ||
1596 | struct GNUNET_TIME_Relative delay; | ||
1597 | struct GNUNET_SCHEDULER_Task * *ti; | ||
1598 | GNUNET_SCHEDULER_TaskCallback f; | ||
1599 | |||
1600 | ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task; | ||
1601 | 419 | ||
1602 | if (NULL != *ti) | 420 | cc = GCC_lookup (cid); |
1603 | GNUNET_SCHEDULER_cancel (*ti); | 421 | if (NULL == cc) |
1604 | delay = GNUNET_TIME_relative_saturating_multiply (refresh_connection_time, 4); | 422 | return; /* whopise, connection alredy down? */ |
1605 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 423 | cc->metrics.num_acked_transmissions++; |
1606 | " timing out in %s\n", | ||
1607 | GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_NO)); | ||
1608 | f = fwd ? &connection_fwd_timeout : &connection_bck_timeout; | ||
1609 | *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c); | ||
1610 | } | ||
1611 | } | 424 | } |
1612 | 425 | ||
1613 | 426 | ||
1614 | /** | 427 | /** |
1615 | * Iterator to compare each connection's path with the path of a new connection. | 428 | * We observed an ACK for a message that was originally sent via |
429 | * the connection identified by @a cti. | ||
1616 | * | 430 | * |
1617 | * If the connection coincides, the c member of path is set to the connection | 431 | * @param cti connection identifier where we got an ACK for a message |
1618 | * and the destroy flag of the connection is set. | 432 | * that was originally sent via this connection (the ACK |
1619 | * | 433 | * may have gotten back to us via a different connection). |
1620 | * @param cls Closure (new path). | ||
1621 | * @param c Connection in the tunnel to check. | ||
1622 | */ | 434 | */ |
1623 | static void | 435 | void |
1624 | check_path (void *cls, struct CadetConnection *c) | 436 | GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) |
1625 | { | 437 | { |
1626 | struct CadetConnection *new_conn = cls; | 438 | struct CadetConnection *cc; |
1627 | struct CadetPeerPath *path = new_conn->path; | ||
1628 | |||
1629 | LOG (GNUNET_ERROR_TYPE_DEBUG, " checking %s (%p), length %u\n", | ||
1630 | GCC_2s (c), c, c->path->length); | ||
1631 | 439 | ||
1632 | if (c != new_conn | 440 | cc = GCC_lookup (cid); |
1633 | && GNUNET_NO == c->destroy | 441 | if (NULL == cc) |
1634 | && CADET_CONNECTION_BROKEN != c->state | 442 | return; /* whopise, connection alredy down? */ |
1635 | && CADET_CONNECTION_DESTROYED != c->state | 443 | cc->metrics.num_successes++; |
1636 | && path_equivalent (path, c->path)) | ||
1637 | { | ||
1638 | new_conn->destroy = GNUNET_YES; /* Do not mark_destroyed, */ | ||
1639 | new_conn->path->c = c; /* this is only a flag for the Iterator. */ | ||
1640 | LOG (GNUNET_ERROR_TYPE_DEBUG, " MATCH!\n"); | ||
1641 | } | ||
1642 | } | 444 | } |
1643 | 445 | ||
1644 | 446 | ||
1645 | /** | 447 | /** |
1646 | * Finds out if this path is already being used by an existing connection. | 448 | * We observed some the given @a latency on the connection |
1647 | * | 449 | * identified by @a cti. (The same connection was taken |
1648 | * Checks the tunnel towards the destination to see if it contains | 450 | * in both directions.) |
1649 | * any connection with the same path. | ||
1650 | * | 451 | * |
1651 | * If the existing connection is ready, it is kept. | 452 | * @param cid connection identifier where we measured latency |
1652 | * Otherwise if the sender has a smaller ID that ours, we accept it (and | 453 | * @param latency the observed latency |
1653 | * the peer will eventually reject our attempt). | ||
1654 | * | ||
1655 | * @param path Path to check. | ||
1656 | * @return #GNUNET_YES if the tunnel has a connection with the same path, | ||
1657 | * #GNUNET_NO otherwise. | ||
1658 | */ | 454 | */ |
1659 | static int | 455 | void |
1660 | does_connection_exist (struct CadetConnection *conn) | 456 | GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, |
457 | struct GNUNET_TIME_Relative latency) | ||
1661 | { | 458 | { |
1662 | struct CadetPeer *p; | 459 | struct CadetConnection *cc; |
1663 | struct CadetTunnel *t; | 460 | double weight; |
1664 | struct CadetConnection *c; | 461 | double result; |
1665 | |||
1666 | p = GCP_get_short (conn->path->peers[0], GNUNET_NO); | ||
1667 | if (NULL == p) | ||
1668 | return GNUNET_NO; | ||
1669 | t = GCP_get_tunnel (p); | ||
1670 | if (NULL == t) | ||
1671 | return GNUNET_NO; | ||
1672 | |||
1673 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking for duplicates\n"); | ||
1674 | 462 | ||
1675 | GCT_iterate_connections (t, &check_path, conn); | 463 | cc = GCC_lookup (cid); |
1676 | 464 | if (NULL == cc) | |
1677 | if (GNUNET_YES == conn->destroy) | 465 | return; /* whopise, connection alredy down? */ |
1678 | { | 466 | GNUNET_STATISTICS_update (stats, |
1679 | c = conn->path->c; | 467 | "# latencies observed", |
1680 | conn->destroy = GNUNET_NO; | 468 | 1, |
1681 | conn->path->c = conn; | 469 | GNUNET_NO); |
1682 | LOG (GNUNET_ERROR_TYPE_DEBUG, " found duplicate of %s\n", GCC_2s (conn)); | 470 | cc->latency_datapoints++; |
1683 | LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate: %s\n", GCC_2s (c)); | 471 | if (cc->latency_datapoints >= 7) |
1684 | GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG); | 472 | weight = 7.0; |
1685 | if (CADET_CONNECTION_READY == c->state) | ||
1686 | { | ||
1687 | /* The other peer confirmed a live connection with this path, | ||
1688 | * why are they trying to duplicate it? */ | ||
1689 | GNUNET_STATISTICS_update (stats, "# duplicate connections", 1, GNUNET_NO); | ||
1690 | return GNUNET_YES; | ||
1691 | } | ||
1692 | LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate not ready, connection unique\n"); | ||
1693 | return GNUNET_NO; | ||
1694 | } | ||
1695 | else | 473 | else |
1696 | { | 474 | weight = cc->latency_datapoints; |
1697 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %s has no duplicates\n", GCC_2s (conn)); | 475 | /* Compute weighted average, giving at MOST weight 7 to the |
1698 | return GNUNET_NO; | 476 | existing values, or less if that value is based on fewer than 7 |
1699 | } | 477 | measurements. */ |
478 | result = (weight * cc->metrics.aged_latency.rel_value_us) + 1.0 * latency.rel_value_us; | ||
479 | result /= (weight + 1.0); | ||
480 | cc->metrics.aged_latency.rel_value_us = (uint64_t) result; | ||
1700 | } | 481 | } |
1701 | 482 | ||
1702 | 483 | ||
1703 | /** | 484 | /** |
1704 | * @brief Check if the tunnel this connection belongs to has any other | 485 | * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying |
1705 | * connection with the same path, and destroy one if so. | 486 | * that the end-to-end connection is up. Process it. |
1706 | * | 487 | * |
1707 | * @param cls Closure (connection to check). | 488 | * @param cc the connection that got the ACK. |
1708 | */ | ||
1709 | static void | ||
1710 | check_duplicates (void *cls) | ||
1711 | { | ||
1712 | struct CadetConnection *c = cls; | ||
1713 | |||
1714 | c->check_duplicates_task = NULL; | ||
1715 | if (GNUNET_YES == does_connection_exist (c)) | ||
1716 | { | ||
1717 | GCT_debug (c->t, GNUNET_ERROR_TYPE_DEBUG); | ||
1718 | send_broken (c, &my_full_id, &my_full_id, GCC_is_origin (c, GNUNET_YES)); | ||
1719 | GCC_destroy (c); | ||
1720 | } | ||
1721 | } | ||
1722 | |||
1723 | |||
1724 | /** | ||
1725 | * Wait for enough time to let any dead connections time out and check for | ||
1726 | * any remaining duplicates. | ||
1727 | * | ||
1728 | * @param c Connection that is a potential duplicate. | ||
1729 | */ | ||
1730 | static void | ||
1731 | schedule_check_duplicates (struct CadetConnection *c) | ||
1732 | { | ||
1733 | struct GNUNET_TIME_Relative delay; | ||
1734 | |||
1735 | if (NULL != c->check_duplicates_task) | ||
1736 | return; | ||
1737 | delay = GNUNET_TIME_relative_saturating_multiply (refresh_connection_time, 5); | ||
1738 | c->check_duplicates_task = GNUNET_SCHEDULER_add_delayed (delay, | ||
1739 | &check_duplicates, | ||
1740 | c); | ||
1741 | } | ||
1742 | |||
1743 | |||
1744 | /** | ||
1745 | * Add the connection to the list of both neighbors. | ||
1746 | * | ||
1747 | * @param c Connection. | ||
1748 | * | ||
1749 | * @return #GNUNET_OK if everything went fine | ||
1750 | * #GNUNET_SYSERR if the was an error and @c c is malformed. | ||
1751 | */ | ||
1752 | static int | ||
1753 | register_neighbors (struct CadetConnection *c) | ||
1754 | { | ||
1755 | c->next_peer = get_next_hop (c); | ||
1756 | c->prev_peer = get_prev_hop (c); | ||
1757 | GNUNET_assert (c->next_peer != c->prev_peer); | ||
1758 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1759 | "register neighbors for connection %s\n", | ||
1760 | GCC_2s (c)); | ||
1761 | path_debug (c->path); | ||
1762 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1763 | "own pos %u\n", c->own_pos); | ||
1764 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1765 | "putting connection %s to next peer %p\n", | ||
1766 | GCC_2s (c), | ||
1767 | c->next_peer); | ||
1768 | LOG (GNUNET_ERROR_TYPE_DEBUG, "next peer %p %s\n", | ||
1769 | c->next_peer, | ||
1770 | GCP_2s (c->next_peer)); | ||
1771 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1772 | "putting connection %s to prev peer %p\n", | ||
1773 | GCC_2s (c), | ||
1774 | c->prev_peer); | ||
1775 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1776 | "prev peer %p %s\n", | ||
1777 | c->prev_peer, | ||
1778 | GCP_2s (c->prev_peer)); | ||
1779 | |||
1780 | if ( (GNUNET_NO == GCP_is_neighbor (c->next_peer)) || | ||
1781 | (GNUNET_NO == GCP_is_neighbor (c->prev_peer)) ) | ||
1782 | { | ||
1783 | if (GCC_is_origin (c, GNUNET_YES)) | ||
1784 | GNUNET_STATISTICS_update (stats, "# local bad paths", 1, GNUNET_NO); | ||
1785 | GNUNET_STATISTICS_update (stats, "# bad paths", 1, GNUNET_NO); | ||
1786 | |||
1787 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1788 | " register neighbors failed\n"); | ||
1789 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1790 | " prev: %s, neighbor?: %d\n", | ||
1791 | GCP_2s (c->prev_peer), | ||
1792 | GCP_is_neighbor (c->prev_peer)); | ||
1793 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1794 | " next: %s, neighbor?: %d\n", | ||
1795 | GCP_2s (c->next_peer), | ||
1796 | GCP_is_neighbor (c->next_peer)); | ||
1797 | return GNUNET_SYSERR; | ||
1798 | } | ||
1799 | GCP_add_connection (c->next_peer, c, GNUNET_NO); | ||
1800 | GCP_add_connection (c->prev_peer, c, GNUNET_YES); | ||
1801 | |||
1802 | return GNUNET_OK; | ||
1803 | } | ||
1804 | |||
1805 | |||
1806 | /** | ||
1807 | * Remove the connection from the list of both neighbors. | ||
1808 | * | ||
1809 | * @param c Connection. | ||
1810 | */ | ||
1811 | static void | ||
1812 | unregister_neighbors (struct CadetConnection *c) | ||
1813 | { | ||
1814 | // struct CadetPeer *peer; FIXME dont use next_peer, prev_peer | ||
1815 | /* Either already unregistered or never got registered, it's ok either way. */ | ||
1816 | if (NULL == c->path) | ||
1817 | return; | ||
1818 | if (NULL != c->next_peer) | ||
1819 | { | ||
1820 | GCP_remove_connection (c->next_peer, c); | ||
1821 | c->next_peer = NULL; | ||
1822 | } | ||
1823 | if (NULL != c->prev_peer) | ||
1824 | { | ||
1825 | GCP_remove_connection (c->prev_peer, c); | ||
1826 | c->prev_peer = NULL; | ||
1827 | } | ||
1828 | } | ||
1829 | |||
1830 | |||
1831 | /** | ||
1832 | * Invalidates all paths towards all peers that comprise the connection which | ||
1833 | * rely on the disconnected peer. | ||
1834 | * | ||
1835 | * ~O(n^3) (peers in connection * paths/peer * links/path) | ||
1836 | * | ||
1837 | * @param c Connection whose peers' paths to clean. | ||
1838 | * @param disconnected Peer that disconnected. | ||
1839 | */ | ||
1840 | static void | ||
1841 | invalidate_paths (struct CadetConnection *c, | ||
1842 | struct CadetPeer *disconnected) | ||
1843 | { | ||
1844 | struct CadetPeer *peer; | ||
1845 | unsigned int i; | ||
1846 | |||
1847 | for (i = 0; i < c->path->length; i++) | ||
1848 | { | ||
1849 | peer = GCP_get_short (c->path->peers[i], GNUNET_NO); | ||
1850 | if (NULL != peer) | ||
1851 | GCP_notify_broken_link (peer, &my_full_id, GCP_get_id (disconnected)); | ||
1852 | } | ||
1853 | } | ||
1854 | |||
1855 | |||
1856 | /** | ||
1857 | * Bind the connection to the peer and the tunnel to that peer. | ||
1858 | * | ||
1859 | * If the peer has no tunnel, create one. Update tunnel and connection | ||
1860 | * data structres to reflect new status. | ||
1861 | * | ||
1862 | * @param c Connection. | ||
1863 | * @param peer Peer. | ||
1864 | */ | ||
1865 | static void | ||
1866 | add_to_peer (struct CadetConnection *c, | ||
1867 | struct CadetPeer *peer) | ||
1868 | { | ||
1869 | GCP_add_tunnel (peer); | ||
1870 | c->t = GCP_get_tunnel (peer); | ||
1871 | GCT_add_connection (c->t, c); | ||
1872 | } | ||
1873 | |||
1874 | |||
1875 | /** | ||
1876 | * Log receipt of message on stderr (INFO level). | ||
1877 | * | ||
1878 | * @param message Message received. | ||
1879 | * @param peer Peer who sent the message. | ||
1880 | * @param conn_id Connection ID of the message. | ||
1881 | */ | ||
1882 | static void | ||
1883 | log_message (const struct GNUNET_MessageHeader *message, | ||
1884 | const struct CadetPeer *peer, | ||
1885 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *conn_id) | ||
1886 | { | ||
1887 | uint16_t size; | ||
1888 | uint16_t type; | ||
1889 | char *arrow; | ||
1890 | |||
1891 | size = ntohs (message->size); | ||
1892 | type = ntohs (message->type); | ||
1893 | switch (type) | ||
1894 | { | ||
1895 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
1896 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK: | ||
1897 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
1898 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
1899 | arrow = "=="; | ||
1900 | break; | ||
1901 | default: | ||
1902 | arrow = "--"; | ||
1903 | } | ||
1904 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1905 | "<%s %s on conn %s from %s, %6u bytes\n", | ||
1906 | arrow, | ||
1907 | GC_m2s (type), | ||
1908 | GNUNET_sh2s (&conn_id->connection_of_tunnel), | ||
1909 | GCP_2s(peer), | ||
1910 | (unsigned int) size); | ||
1911 | } | ||
1912 | |||
1913 | /******************************************************************************/ | ||
1914 | /******************************** API ***********************************/ | ||
1915 | /******************************************************************************/ | ||
1916 | |||
1917 | /** | ||
1918 | * Handler for connection creation. | ||
1919 | * | ||
1920 | * @param peer Message sender (neighbor). | ||
1921 | * @param msg Message itself. | ||
1922 | */ | 489 | */ |
1923 | void | 490 | void |
1924 | GCC_handle_create (struct CadetPeer *peer, | 491 | GCC_handle_connection_create_ack (struct CadetConnection *cc) |
1925 | const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
1926 | { | 492 | { |
1927 | static struct CadetEncryptedMessageIdentifier zero; | 493 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1928 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid; | 494 | "Received CADET_CONNECTION_CREATE_ACK for %s in state %d (%s)\n", |
1929 | struct GNUNET_PeerIdentity *id; | 495 | GCC_2s (cc), |
1930 | struct CadetPeerPath *path; | 496 | cc->state, |
1931 | struct CadetPeer *dest_peer; | 497 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); |
1932 | struct CadetPeer *orig_peer; | 498 | if (CADET_CONNECTION_READY == cc->state) |
1933 | struct CadetConnection *c; | 499 | return; /* Duplicate ACK, ignore */ |
1934 | unsigned int own_pos; | 500 | if (NULL != cc->task) |
1935 | uint16_t size; | ||
1936 | |||
1937 | GCC_check_connections (); | ||
1938 | size = ntohs (msg->header.size); | ||
1939 | |||
1940 | /* Calculate hops */ | ||
1941 | size -= sizeof (struct GNUNET_CADET_ConnectionCreateMessage); | ||
1942 | if (0 != size % sizeof (struct GNUNET_PeerIdentity)) | ||
1943 | { | ||
1944 | GNUNET_break_op (0); | ||
1945 | return; | ||
1946 | } | ||
1947 | size /= sizeof (struct GNUNET_PeerIdentity); | ||
1948 | if (1 > size) | ||
1949 | { | ||
1950 | GNUNET_break_op (0); | ||
1951 | return; | ||
1952 | } | ||
1953 | LOG (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); | ||
1954 | |||
1955 | /* Get parameters */ | ||
1956 | cid = &msg->cid; | ||
1957 | log_message (&msg->header, peer, cid); | ||
1958 | id = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
1959 | LOG (GNUNET_ERROR_TYPE_DEBUG, " origin: %s\n", GNUNET_i2s (id)); | ||
1960 | |||
1961 | /* Create connection */ | ||
1962 | c = connection_get (cid); | ||
1963 | if (NULL == c) | ||
1964 | { | ||
1965 | path = path_build_from_peer_ids ((struct GNUNET_PeerIdentity *) &msg[1], | ||
1966 | size, myid, &own_pos); | ||
1967 | if (NULL == path) | ||
1968 | { | ||
1969 | /* Path was malformed, probably our own ID was not in it. */ | ||
1970 | GNUNET_STATISTICS_update (stats, "# malformed paths", 1, GNUNET_NO); | ||
1971 | GNUNET_break_op (0); | ||
1972 | return; | ||
1973 | } | ||
1974 | if (0 == own_pos) | ||
1975 | { | ||
1976 | /* We received this request from a neighbor, we cannot be origin */ | ||
1977 | GNUNET_STATISTICS_update (stats, "# fake paths", 1, GNUNET_NO); | ||
1978 | GNUNET_break_op (0); | ||
1979 | path_destroy (path); | ||
1980 | return; | ||
1981 | } | ||
1982 | |||
1983 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos); | ||
1984 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n"); | ||
1985 | c = GCC_new (cid, NULL, path, own_pos); | ||
1986 | if (NULL == c) | ||
1987 | { | ||
1988 | if (path->length - 1 == own_pos) | ||
1989 | { | ||
1990 | /* If we are destination, why did the creation fail? */ | ||
1991 | GNUNET_break (0); | ||
1992 | path_destroy (path); | ||
1993 | GCC_check_connections (); | ||
1994 | return; | ||
1995 | } | ||
1996 | send_broken_unknown (cid, &my_full_id, | ||
1997 | GNUNET_PEER_resolve2 (path->peers[own_pos + 1]), | ||
1998 | peer); | ||
1999 | path_destroy (path); | ||
2000 | GCC_check_connections (); | ||
2001 | return; | ||
2002 | } | ||
2003 | GCP_add_path_to_all (path, GNUNET_NO); | ||
2004 | connection_reset_timeout (c, GNUNET_YES); | ||
2005 | } | ||
2006 | else | ||
2007 | { | ||
2008 | path = path_duplicate (c->path); | ||
2009 | } | ||
2010 | if (CADET_CONNECTION_NEW == c->state) | ||
2011 | connection_change_state (c, CADET_CONNECTION_SENT); | ||
2012 | |||
2013 | /* Remember peers */ | ||
2014 | dest_peer = GCP_get (&id[size - 1], GNUNET_YES); | ||
2015 | orig_peer = GCP_get (&id[0], GNUNET_YES); | ||
2016 | |||
2017 | /* Is it a connection to us? */ | ||
2018 | if (c->own_pos == path->length - 1) | ||
2019 | { | ||
2020 | LOG (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); | ||
2021 | GCP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES); | ||
2022 | |||
2023 | add_to_peer (c, orig_peer); | ||
2024 | if (GNUNET_YES == does_connection_exist (c)) | ||
2025 | { | ||
2026 | /* Peer created a connection equal to one we think exists | ||
2027 | * and is fine. | ||
2028 | * Solution: Keep both and postpone disambiguation. In the meantime | ||
2029 | * the connection will time out or peer will inform us it is broken. | ||
2030 | * | ||
2031 | * Other options: | ||
2032 | * - Use explicit duplicate. | ||
2033 | * - Accept new conn and destroy the old. (interruption in higher level) | ||
2034 | * - Keep the one with higher ID / created by peer with higher ID. */ | ||
2035 | schedule_check_duplicates (c); | ||
2036 | } | ||
2037 | |||
2038 | if (CADET_TUNNEL_NEW == GCT_get_cstate (c->t)) | ||
2039 | GCT_change_cstate (c->t, CADET_TUNNEL_WAITING); | ||
2040 | if (NULL == c->maintenance_q) | ||
2041 | send_connection_ack (c, GNUNET_NO); | ||
2042 | if (CADET_CONNECTION_SENT == c->state) | ||
2043 | connection_change_state (c, CADET_CONNECTION_ACK); | ||
2044 | } | ||
2045 | else | ||
2046 | { | 501 | { |
2047 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | 502 | GNUNET_SCHEDULER_cancel (cc->task); |
2048 | GCP_add_path (dest_peer, path_duplicate (path), GNUNET_NO); | 503 | cc->task = NULL; |
2049 | GCP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO); | ||
2050 | (void) GCC_send_prebuilt_message (&msg->header, | ||
2051 | 0, | ||
2052 | zero, | ||
2053 | c, | ||
2054 | GNUNET_YES, GNUNET_YES, | ||
2055 | NULL, NULL); | ||
2056 | } | 504 | } |
2057 | path_destroy (path); | 505 | cc->metrics.age = GNUNET_TIME_absolute_get (); |
2058 | GCC_check_connections (); | 506 | update_state (cc, |
507 | CADET_CONNECTION_READY, | ||
508 | cc->mqm_ready); | ||
509 | if ( (NULL == cc->keepalive_qe) && | ||
510 | (GNUNET_YES == cc->mqm_ready) && | ||
511 | (NULL == cc->task) ) | ||
512 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, | ||
513 | &send_keepalive, | ||
514 | cc); | ||
2059 | } | 515 | } |
2060 | 516 | ||
2061 | 517 | ||
2062 | /** | 518 | /** |
2063 | * Handler for connection confirmations. | 519 | * Handle KX message. |
2064 | * | 520 | * |
2065 | * @param peer Message sender (neighbor). | 521 | * @param cc connection that received encrypted message |
2066 | * @param msg Message itself. | 522 | * @param msg the key exchange message |
2067 | */ | 523 | */ |
2068 | void | 524 | void |
2069 | GCC_handle_confirm (struct CadetPeer *peer, | 525 | GCC_handle_kx (struct CadetConnection *cc, |
2070 | const struct GNUNET_CADET_ConnectionCreateAckMessage *msg) | 526 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) |
2071 | { | 527 | { |
2072 | static struct CadetEncryptedMessageIdentifier zero; | 528 | if (CADET_CONNECTION_SENT == cc->state) |
2073 | struct CadetConnection *c; | ||
2074 | enum CadetConnectionState oldstate; | ||
2075 | int fwd; | ||
2076 | |||
2077 | GCC_check_connections (); | ||
2078 | log_message (&msg->header, peer, &msg->cid); | ||
2079 | c = connection_get (&msg->cid); | ||
2080 | if (NULL == c) | ||
2081 | { | ||
2082 | GNUNET_STATISTICS_update (stats, "# control on unknown connection", | ||
2083 | 1, GNUNET_NO); | ||
2084 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2085 | " don't know the connection!\n"); | ||
2086 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
2087 | GCC_check_connections (); | ||
2088 | return; | ||
2089 | } | ||
2090 | if (GNUNET_NO != c->destroy) | ||
2091 | { | 529 | { |
2092 | GNUNET_assert (CADET_CONNECTION_DESTROYED == c->state); | 530 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, |
2093 | GNUNET_STATISTICS_update (stats, "# control on dying connection", | 531 | clearly something is working, so pretend we got an ACK. */ |
2094 | 1, GNUNET_NO); | ||
2095 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 532 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2096 | "connection %s being destroyed, ignoring confirm\n", | 533 | "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n", |
2097 | GCC_2s (c)); | 534 | GCC_2s (cc)); |
2098 | GCC_check_connections (); | 535 | GCC_handle_connection_create_ack (cc); |
2099 | return; | ||
2100 | } | ||
2101 | |||
2102 | oldstate = c->state; | ||
2103 | LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", GCP_2s (peer)); | ||
2104 | if (get_next_hop (c) == peer) | ||
2105 | { | ||
2106 | LOG (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n"); | ||
2107 | fwd = GNUNET_NO; | ||
2108 | if (CADET_CONNECTION_SENT == oldstate) | ||
2109 | connection_change_state (c, CADET_CONNECTION_ACK); | ||
2110 | } | ||
2111 | else if (get_prev_hop (c) == peer) | ||
2112 | { | ||
2113 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FINAL ACK\n"); | ||
2114 | fwd = GNUNET_YES; | ||
2115 | connection_change_state (c, CADET_CONNECTION_READY); | ||
2116 | } | ||
2117 | else | ||
2118 | { | ||
2119 | GNUNET_STATISTICS_update (stats, "# control on connection from wrong peer", | ||
2120 | 1, GNUNET_NO); | ||
2121 | GNUNET_break_op (0); | ||
2122 | return; | ||
2123 | } | ||
2124 | |||
2125 | connection_reset_timeout (c, fwd); | ||
2126 | |||
2127 | GNUNET_assert (NULL != c->path); | ||
2128 | GCP_add_path_to_all (c->path, GNUNET_YES); | ||
2129 | |||
2130 | /* Message for us as creator? */ | ||
2131 | if (GNUNET_YES == GCC_is_origin (c, GNUNET_YES)) | ||
2132 | { | ||
2133 | if (GNUNET_NO != fwd) | ||
2134 | { | ||
2135 | GNUNET_break (0); | ||
2136 | return; | ||
2137 | } | ||
2138 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n"); | ||
2139 | |||
2140 | /* If just created, cancel the short timeout and start a long one */ | ||
2141 | if (CADET_CONNECTION_SENT == oldstate) | ||
2142 | { | ||
2143 | c->create_retry = 1; | ||
2144 | connection_reset_timeout (c, GNUNET_YES); | ||
2145 | } | ||
2146 | |||
2147 | /* Change connection state, send ACK */ | ||
2148 | connection_change_state (c, CADET_CONNECTION_READY); | ||
2149 | send_connection_ack (c, GNUNET_YES); | ||
2150 | |||
2151 | /* Change tunnel state, trigger KX */ | ||
2152 | if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t)) | ||
2153 | GCT_change_cstate (c->t, CADET_TUNNEL_READY); | ||
2154 | GCC_check_connections (); | ||
2155 | return; | ||
2156 | } | ||
2157 | |||
2158 | /* Message for us as destination? */ | ||
2159 | if (GCC_is_terminal (c, GNUNET_YES)) | ||
2160 | { | ||
2161 | if (GNUNET_YES != fwd) | ||
2162 | { | ||
2163 | GNUNET_break (0); | ||
2164 | return; | ||
2165 | } | ||
2166 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n"); | ||
2167 | |||
2168 | /* If just created, cancel the short timeout and start a long one */ | ||
2169 | if (CADET_CONNECTION_ACK == oldstate) | ||
2170 | connection_reset_timeout (c, GNUNET_NO); | ||
2171 | |||
2172 | /* Change tunnel state */ | ||
2173 | if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t)) | ||
2174 | GCT_change_cstate (c->t, CADET_TUNNEL_READY); | ||
2175 | GCC_check_connections (); | ||
2176 | } | 536 | } |
2177 | else | 537 | GCT_handle_kx (cc->ct, |
2178 | { | 538 | msg); |
2179 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
2180 | (void) GCC_send_prebuilt_message (&msg->header, 0, | ||
2181 | zero, | ||
2182 | c, | ||
2183 | fwd, | ||
2184 | GNUNET_YES, NULL, NULL); | ||
2185 | } | ||
2186 | GCC_check_connections (); | ||
2187 | } | 539 | } |
2188 | 540 | ||
2189 | 541 | ||
2190 | /** | 542 | /** |
2191 | * Handler for notifications of broken connections. | 543 | * Handle KX_AUTH message. |
2192 | * | 544 | * |
2193 | * @param peer Message sender (neighbor). | 545 | * @param cc connection that received encrypted message |
2194 | * @param msg Message itself. | 546 | * @param msg the key exchange message |
2195 | */ | 547 | */ |
2196 | void | 548 | void |
2197 | GCC_handle_broken (struct CadetPeer *peer, | 549 | GCC_handle_kx_auth (struct CadetConnection *cc, |
2198 | const struct GNUNET_CADET_ConnectionBrokenMessage *msg) | 550 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) |
2199 | { | 551 | { |
2200 | static struct CadetEncryptedMessageIdentifier zero; | 552 | if (CADET_CONNECTION_SENT == cc->state) |
2201 | struct CadetConnection *c; | ||
2202 | struct CadetTunnel *t; | ||
2203 | int fwd; | ||
2204 | |||
2205 | GCC_check_connections (); | ||
2206 | log_message (&msg->header, peer, &msg->cid); | ||
2207 | LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", GNUNET_i2s (&msg->peer1)); | ||
2208 | LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", GNUNET_i2s (&msg->peer2)); | ||
2209 | c = connection_get (&msg->cid); | ||
2210 | if (NULL == c) | ||
2211 | { | ||
2212 | LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate CONNECTION_BROKEN\n"); | ||
2213 | GNUNET_STATISTICS_update (stats, "# duplicate CONNECTION_BROKEN", | ||
2214 | 1, GNUNET_NO); | ||
2215 | GCC_check_connections (); | ||
2216 | return; | ||
2217 | } | ||
2218 | |||
2219 | t = c->t; | ||
2220 | |||
2221 | fwd = is_fwd (c, peer); | ||
2222 | if (GNUNET_SYSERR == fwd) | ||
2223 | { | ||
2224 | GNUNET_break_op (0); | ||
2225 | GCC_check_connections (); | ||
2226 | return; | ||
2227 | } | ||
2228 | mark_destroyed (c); | ||
2229 | if (GCC_is_terminal (c, fwd)) | ||
2230 | { | ||
2231 | struct CadetPeer *endpoint; | ||
2232 | |||
2233 | if (NULL == t) | ||
2234 | { | ||
2235 | /* A terminal connection should not have 't' set to NULL. */ | ||
2236 | GNUNET_break (0); | ||
2237 | GCC_debug (c, GNUNET_ERROR_TYPE_ERROR); | ||
2238 | return; | ||
2239 | } | ||
2240 | endpoint = GCP_get_short (c->path->peers[c->path->length - 1], GNUNET_YES); | ||
2241 | if (2 < c->path->length) | ||
2242 | path_invalidate (c->path); | ||
2243 | GCP_notify_broken_link (endpoint, &msg->peer1, &msg->peer2); | ||
2244 | |||
2245 | connection_change_state (c, CADET_CONNECTION_BROKEN); | ||
2246 | GCT_remove_connection (t, c); | ||
2247 | c->t = NULL; | ||
2248 | |||
2249 | GCC_destroy (c); | ||
2250 | } | ||
2251 | else | ||
2252 | { | 553 | { |
2253 | (void) GCC_send_prebuilt_message (&msg->header, 0, | 554 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, |
2254 | zero, c, fwd, | 555 | clearly something is working, so pretend we got an ACK. */ |
2255 | GNUNET_YES, NULL, NULL); | 556 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2256 | connection_cancel_queues (c, !fwd); | 557 | "Faking connection CADET_CONNECTION_CREATE_ACK for %s due to KX\n", |
558 | GCC_2s (cc)); | ||
559 | GCC_handle_connection_create_ack (cc); | ||
2257 | } | 560 | } |
2258 | GCC_check_connections (); | 561 | GCT_handle_kx_auth (cc->ct, |
2259 | return; | 562 | msg); |
2260 | } | 563 | } |
2261 | 564 | ||
2262 | 565 | ||
2263 | /** | 566 | /** |
2264 | * Handler for notifications of destroyed connections. | 567 | * Handle encrypted message. |
2265 | * | 568 | * |
2266 | * @param peer Message sender (neighbor). | 569 | * @param cc connection that received encrypted message |
2267 | * @param msg Message itself. | 570 | * @param msg the encrypted message to decrypt |
2268 | */ | 571 | */ |
2269 | void | 572 | void |
2270 | GCC_handle_destroy (struct CadetPeer *peer, | 573 | GCC_handle_encrypted (struct CadetConnection *cc, |
2271 | const struct GNUNET_CADET_ConnectionDestroyMessage *msg) | 574 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) |
2272 | { | 575 | { |
2273 | static struct CadetEncryptedMessageIdentifier zero; | 576 | if (CADET_CONNECTION_SENT == cc->state) |
2274 | struct CadetConnection *c; | ||
2275 | int fwd; | ||
2276 | |||
2277 | GCC_check_connections (); | ||
2278 | log_message (&msg->header, peer, &msg->cid); | ||
2279 | c = connection_get (&msg->cid); | ||
2280 | if (NULL == c) | ||
2281 | { | 577 | { |
2282 | /* Probably already got the message from another path, | 578 | /* We didn't get the CREATE_ACK, but instead got payload. That's fine, |
2283 | * destroyed the tunnel and retransmitted to children. | 579 | clearly something is working, so pretend we got an ACK. */ |
2284 | * Safe to ignore. | ||
2285 | */ | ||
2286 | GNUNET_STATISTICS_update (stats, | ||
2287 | "# control on unknown connection", | ||
2288 | 1, GNUNET_NO); | ||
2289 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 580 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2290 | " connection unknown destroyed: previously destroyed?\n"); | 581 | "Faking connection ACK for %s due to ENCRYPTED payload\n", |
2291 | GCC_check_connections (); | 582 | GCC_2s (cc)); |
2292 | return; | 583 | GCC_handle_connection_create_ack (cc); |
2293 | } | ||
2294 | |||
2295 | fwd = is_fwd (c, peer); | ||
2296 | if (GNUNET_SYSERR == fwd) | ||
2297 | { | ||
2298 | GNUNET_break_op (0); | ||
2299 | GCC_check_connections (); | ||
2300 | return; | ||
2301 | } | ||
2302 | |||
2303 | if (GNUNET_NO == GCC_is_terminal (c, fwd)) | ||
2304 | { | ||
2305 | (void) GCC_send_prebuilt_message (&msg->header, 0, | ||
2306 | zero, c, fwd, | ||
2307 | GNUNET_YES, NULL, NULL); | ||
2308 | } | 584 | } |
2309 | else if (0 == c->pending_messages) | 585 | cc->metrics.last_use = GNUNET_TIME_absolute_get (); |
2310 | { | 586 | GCT_handle_encrypted (cc->ct, |
2311 | LOG (GNUNET_ERROR_TYPE_DEBUG, " directly destroying connection!\n"); | 587 | msg); |
2312 | GCC_destroy (c); | ||
2313 | GCC_check_connections (); | ||
2314 | return; | ||
2315 | } | ||
2316 | mark_destroyed (c); | ||
2317 | if (NULL != c->t) | ||
2318 | { | ||
2319 | GCT_remove_connection (c->t, c); | ||
2320 | c->t = NULL; | ||
2321 | } | ||
2322 | GCC_check_connections (); | ||
2323 | return; | ||
2324 | } | 588 | } |
2325 | 589 | ||
2326 | 590 | ||
2327 | /** | 591 | /** |
2328 | * Handler for cadet network traffic hop-by-hop acks. | 592 | * Send a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE message to the |
593 | * first hop. | ||
2329 | * | 594 | * |
2330 | * @param peer Message sender (neighbor). | 595 | * @param cls the `struct CadetConnection` to initiate |
2331 | * @param msg Message itself. | ||
2332 | */ | 596 | */ |
2333 | void | 597 | static void |
2334 | GCC_handle_ack (struct CadetPeer *peer, | 598 | send_create (void *cls) |
2335 | const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg) | 599 | { |
2336 | { | 600 | struct CadetConnection *cc = cls; |
2337 | struct CadetConnection *c; | 601 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; |
2338 | struct CadetFlowControl *fc; | 602 | struct GNUNET_PeerIdentity *pids; |
2339 | struct CadetEncryptedMessageIdentifier ack; | 603 | struct GNUNET_MQ_Envelope *env; |
2340 | int fwd; | 604 | unsigned int path_length; |
2341 | 605 | ||
2342 | GCC_check_connections (); | 606 | cc->task = NULL; |
2343 | log_message (&msg->header, peer, &msg->cid); | 607 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); |
2344 | c = connection_get (&msg->cid); | 608 | path_length = GCPP_get_length (cc->path); |
2345 | if (NULL == c) | 609 | env = GNUNET_MQ_msg_extra (create_msg, |
2346 | { | 610 | (1 + path_length) * sizeof (struct GNUNET_PeerIdentity), |
2347 | GNUNET_STATISTICS_update (stats, | 611 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); |
2348 | "# ack on unknown connection", | 612 | create_msg->options = htonl ((uint32_t) cc->options); |
2349 | 1, | 613 | create_msg->cid = cc->cid; |
2350 | GNUNET_NO); | 614 | pids = (struct GNUNET_PeerIdentity *) &create_msg[1]; |
2351 | send_broken_unknown (&msg->cid, | 615 | pids[0] = my_full_id; |
2352 | &my_full_id, | 616 | for (unsigned int i=0;i<path_length;i++) |
2353 | NULL, | 617 | pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, |
2354 | peer); | 618 | i)); |
2355 | GCC_check_connections (); | 619 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2356 | return; | 620 | "Sending CADET_CONNECTION_CREATE message for %s\n", |
2357 | } | 621 | GCC_2s (cc)); |
2358 | 622 | cc->env = env; | |
2359 | /* Is this a forward or backward ACK? */ | 623 | update_state (cc, |
2360 | if (get_next_hop (c) == peer) | 624 | CADET_CONNECTION_SENT, |
2361 | { | 625 | GNUNET_NO); |
2362 | fc = &c->fwd_fc; | 626 | GCP_send (cc->mq_man, |
2363 | fwd = GNUNET_YES; | 627 | env); |
2364 | } | ||
2365 | else if (get_prev_hop (c) == peer) | ||
2366 | { | ||
2367 | fc = &c->bck_fc; | ||
2368 | fwd = GNUNET_NO; | ||
2369 | } | ||
2370 | else | ||
2371 | { | ||
2372 | GNUNET_break_op (0); | ||
2373 | return; | ||
2374 | } | ||
2375 | |||
2376 | ack = msg->cemi_max; | ||
2377 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %s ACK %u (was %u)\n", | ||
2378 | GC_f2s (fwd), | ||
2379 | ntohl (ack.pid), | ||
2380 | ntohl (fc->last_ack_recv.pid)); | ||
2381 | if (GC_is_pid_bigger (ntohl (ack.pid), | ||
2382 | ntohl (fc->last_ack_recv.pid))) | ||
2383 | fc->last_ack_recv = ack; | ||
2384 | |||
2385 | /* Cancel polling if the ACK is big enough. */ | ||
2386 | if ( (NULL != fc->poll_task) & | ||
2387 | GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid), | ||
2388 | ntohl (fc->last_pid_sent.pid))) | ||
2389 | { | ||
2390 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n"); | ||
2391 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
2392 | fc->poll_task = NULL; | ||
2393 | fc->poll_time = GNUNET_TIME_UNIT_SECONDS; | ||
2394 | } | ||
2395 | |||
2396 | GCC_check_connections (); | ||
2397 | } | 628 | } |
2398 | 629 | ||
2399 | 630 | ||
2400 | /** | 631 | /** |
2401 | * Handler for cadet network traffic hop-by-hop data counter polls. | 632 | * Send a CREATE_ACK message towards the origin. |
2402 | * | 633 | * |
2403 | * @param peer Message sender (neighbor). | 634 | * @param cls the `struct CadetConnection` to initiate |
2404 | * @param msg Message itself. | ||
2405 | */ | 635 | */ |
2406 | void | 636 | static void |
2407 | GCC_handle_poll (struct CadetPeer *peer, | 637 | send_create_ack (void *cls) |
2408 | const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg) | ||
2409 | { | 638 | { |
2410 | struct CadetConnection *c; | 639 | struct CadetConnection *cc = cls; |
2411 | struct CadetFlowControl *fc; | 640 | struct GNUNET_CADET_ConnectionCreateAckMessage *ack_msg; |
2412 | struct CadetEncryptedMessageIdentifier pid; | 641 | struct GNUNET_MQ_Envelope *env; |
2413 | int fwd; | ||
2414 | |||
2415 | GCC_check_connections (); | ||
2416 | log_message (&msg->header, peer, &msg->cid); | ||
2417 | c = connection_get (&msg->cid); | ||
2418 | if (NULL == c) | ||
2419 | { | ||
2420 | GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1, | ||
2421 | GNUNET_NO); | ||
2422 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2423 | "POLL message on unknown connection %s!\n", | ||
2424 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
2425 | send_broken_unknown (&msg->cid, | ||
2426 | &my_full_id, | ||
2427 | NULL, | ||
2428 | peer); | ||
2429 | GCC_check_connections (); | ||
2430 | return; | ||
2431 | } | ||
2432 | |||
2433 | /* Is this a forward or backward ACK? | ||
2434 | * Note: a poll should never be needed in a loopback case, | ||
2435 | * since there is no possiblility of packet loss there, so | ||
2436 | * this way of discerining FWD/BCK should not be a problem. | ||
2437 | */ | ||
2438 | if (get_next_hop (c) == peer) | ||
2439 | { | ||
2440 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n"); | ||
2441 | fc = &c->fwd_fc; | ||
2442 | } | ||
2443 | else if (get_prev_hop (c) == peer) | ||
2444 | { | ||
2445 | LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n"); | ||
2446 | fc = &c->bck_fc; | ||
2447 | } | ||
2448 | else | ||
2449 | { | ||
2450 | GNUNET_break_op (0); | ||
2451 | return; | ||
2452 | } | ||
2453 | 642 | ||
2454 | pid = msg->cemi; | 643 | cc->task = NULL; |
644 | GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state); | ||
2455 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 645 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2456 | " PID %u, OLD %u\n", | 646 | "Sending CONNECTION_CREATE_ACK message for %s\n", |
2457 | ntohl (pid.pid), | 647 | GCC_2s (cc)); |
2458 | ntohl (fc->last_pid_recv.pid)); | 648 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); |
2459 | fc->last_pid_recv = pid; | 649 | env = GNUNET_MQ_msg (ack_msg, |
2460 | fwd = fc == &c->bck_fc; | 650 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK); |
2461 | GCC_send_ack (c, fwd, GNUNET_YES); | 651 | ack_msg->cid = cc->cid; |
2462 | GCC_check_connections (); | 652 | cc->env = env; |
653 | update_state (cc, | ||
654 | CADET_CONNECTION_READY, | ||
655 | GNUNET_NO); | ||
656 | GCP_send (cc->mq_man, | ||
657 | env); | ||
2463 | } | 658 | } |
2464 | 659 | ||
2465 | 660 | ||
2466 | /** | 661 | /** |
2467 | * Check the message against internal state and test if it goes FWD or BCK. | 662 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a |
2468 | * | 663 | * connection that we already have. Either our ACK got lost |
2469 | * Updates the PID, state and timeout values for the connection. | 664 | * or something is fishy. Consider retransmitting the ACK. |
2470 | * | ||
2471 | * @param message Message to check. It must belong to an existing connection. | ||
2472 | * @param cid Connection ID (even if @a c is NULL, the ID is still needed). | ||
2473 | * @param c Connection this message should belong. If NULL, check fails. | ||
2474 | * @param sender Neighbor that sent the message. | ||
2475 | * | 665 | * |
2476 | * @return #GNUNET_YES if the message goes FWD. | 666 | * @param cc connection that got the duplicate CREATE |
2477 | * #GNUNET_NO if it goes BCK. | ||
2478 | * #GNUNET_SYSERR if there is an error (unauthorized sender, ...). | ||
2479 | */ | 667 | */ |
2480 | static int | 668 | void |
2481 | check_message (const struct GNUNET_MessageHeader *message, | 669 | GCC_handle_duplicate_create (struct CadetConnection *cc) |
2482 | const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid, | ||
2483 | struct CadetConnection *c, | ||
2484 | struct CadetPeer *sender, | ||
2485 | struct CadetEncryptedMessageIdentifier pid) | ||
2486 | { | 670 | { |
2487 | struct CadetFlowControl *fc; | 671 | if (GNUNET_YES == cc->mqm_ready) |
2488 | struct CadetPeer *hop; | ||
2489 | int fwd; | ||
2490 | uint16_t type; | ||
2491 | |||
2492 | /* Check connection */ | ||
2493 | if (NULL == c) | ||
2494 | { | 672 | { |
2495 | GNUNET_STATISTICS_update (stats, | ||
2496 | "# unknown connection", | ||
2497 | 1, GNUNET_NO); | ||
2498 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 673 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2499 | "%s on unknown connection %s\n", | 674 | "Got duplicate CREATE for %s, scheduling another ACK (%s)\n", |
2500 | GC_m2s (ntohs (message->type)), | 675 | GCC_2s (cc), |
2501 | GNUNET_sh2s (&cid->connection_of_tunnel)); | 676 | (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy"); |
2502 | GNUNET_break_op (0); | 677 | /* Revert back to the state of having only received the 'CREATE', |
2503 | send_broken_unknown (cid, | 678 | and immediately proceed to send the CREATE_ACK. */ |
2504 | &my_full_id, | 679 | update_state (cc, |
2505 | NULL, | 680 | CADET_CONNECTION_CREATE_RECEIVED, |
2506 | sender); | 681 | cc->mqm_ready); |
2507 | return GNUNET_SYSERR; | 682 | if (NULL != cc->task) |
2508 | } | 683 | GNUNET_SCHEDULER_cancel (cc->task); |
2509 | 684 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | |
2510 | /* Check if origin is as expected */ | 685 | cc); |
2511 | hop = get_prev_hop (c); | ||
2512 | if (sender == hop) | ||
2513 | { | ||
2514 | fwd = GNUNET_YES; | ||
2515 | } | 686 | } |
2516 | else | 687 | else |
2517 | { | 688 | { |
2518 | hop = get_next_hop (c); | 689 | /* We are currently sending something else back, which |
2519 | GNUNET_break (hop == c->next_peer); | 690 | can only be an ACK or payload, either of which would |
2520 | if (sender == hop) | 691 | do. So actually no need to do anything. */ |
2521 | { | 692 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2522 | fwd = GNUNET_NO; | 693 | "Got duplicate CREATE for %s. MQ is busy, not queueing another ACK\n", |
2523 | } | 694 | GCC_2s (cc)); |
2524 | else | ||
2525 | { | ||
2526 | /* Unexpected peer sending traffic on a connection. */ | ||
2527 | GNUNET_break_op (0); | ||
2528 | return GNUNET_SYSERR; | ||
2529 | } | ||
2530 | } | ||
2531 | |||
2532 | /* Check PID for payload messages */ | ||
2533 | type = ntohs (message->type); | ||
2534 | if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type) | ||
2535 | { | ||
2536 | fc = fwd ? &c->bck_fc : &c->fwd_fc; | ||
2537 | LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected in interval [%u,%u])\n", | ||
2538 | ntohl (pid.pid), | ||
2539 | ntohl (fc->last_pid_recv.pid) + 1, | ||
2540 | ntohl (fc->last_ack_sent.pid)); | ||
2541 | if (GC_is_pid_bigger (ntohl (pid.pid), | ||
2542 | ntohl (fc->last_ack_sent.pid))) | ||
2543 | { | ||
2544 | GNUNET_STATISTICS_update (stats, | ||
2545 | "# unsolicited message", | ||
2546 | 1, | ||
2547 | GNUNET_NO); | ||
2548 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2549 | "Received PID %u, (prev %u), ACK %u\n", | ||
2550 | pid, fc->last_pid_recv, fc->last_ack_sent); | ||
2551 | return GNUNET_SYSERR; | ||
2552 | } | ||
2553 | if (GC_is_pid_bigger (ntohl (pid.pid), | ||
2554 | ntohl (fc->last_pid_recv.pid))) | ||
2555 | { | ||
2556 | unsigned int delta; | ||
2557 | |||
2558 | delta = ntohl (pid.pid) - ntohl (fc->last_pid_recv.pid); | ||
2559 | fc->last_pid_recv = pid; | ||
2560 | fc->recv_bitmap <<= delta; | ||
2561 | fc->recv_bitmap |= 1; | ||
2562 | } | ||
2563 | else | ||
2564 | { | ||
2565 | GNUNET_STATISTICS_update (stats, | ||
2566 | "# out of order PID", | ||
2567 | 1, | ||
2568 | GNUNET_NO); | ||
2569 | if (GNUNET_NO == is_ooo_ok (fc->last_pid_recv, | ||
2570 | pid, | ||
2571 | fc->recv_bitmap)) | ||
2572 | { | ||
2573 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2574 | "PID %u unexpected (%u+), dropping!\n", | ||
2575 | ntohl (pid.pid), | ||
2576 | ntohl (fc->last_pid_recv.pid) - 31); | ||
2577 | return GNUNET_SYSERR; | ||
2578 | } | ||
2579 | fc->recv_bitmap |= get_recv_bitmask (fc->last_pid_recv, | ||
2580 | pid); | ||
2581 | } | ||
2582 | } | ||
2583 | |||
2584 | /* Count as connection confirmation. */ | ||
2585 | if ( (CADET_CONNECTION_SENT == c->state) || | ||
2586 | (CADET_CONNECTION_ACK == c->state) ) | ||
2587 | { | ||
2588 | connection_change_state (c, CADET_CONNECTION_READY); | ||
2589 | if (NULL != c->t) | ||
2590 | { | ||
2591 | if (CADET_TUNNEL_WAITING == GCT_get_cstate (c->t)) | ||
2592 | GCT_change_cstate (c->t, CADET_TUNNEL_READY); | ||
2593 | } | ||
2594 | } | 695 | } |
2595 | connection_reset_timeout (c, fwd); | ||
2596 | |||
2597 | return fwd; | ||
2598 | } | 696 | } |
2599 | 697 | ||
2600 | 698 | ||
2601 | /** | 699 | /** |
2602 | * Handler for key exchange traffic (Axolotl KX). | 700 | * There has been a change in the message queue existence for our |
701 | * peer at the first hop. Adjust accordingly. | ||
2603 | * | 702 | * |
2604 | * @param peer Message sender (neighbor). | 703 | * @param cls the `struct CadetConnection` |
2605 | * @param msg Message itself. | 704 | * @param available #GNUNET_YES if sending is now possible, |
705 | * #GNUNET_NO if sending is no longer possible | ||
706 | * #GNUNET_SYSERR if sending is no longer possible | ||
707 | * and the last envelope was discarded | ||
2606 | */ | 708 | */ |
2607 | void | 709 | static void |
2608 | GCC_handle_kx (struct CadetPeer *peer, | 710 | manage_first_hop_mq (void *cls, |
2609 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | 711 | int available) |
2610 | { | 712 | { |
2611 | static struct CadetEncryptedMessageIdentifier zero; | 713 | struct CadetConnection *cc = cls; |
2612 | const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid; | ||
2613 | struct CadetConnection *c; | ||
2614 | int fwd; | ||
2615 | |||
2616 | GCC_check_connections (); | ||
2617 | cid = &msg->cid; | ||
2618 | log_message (&msg->header, peer, cid); | ||
2619 | |||
2620 | c = connection_get (cid); | ||
2621 | fwd = check_message (&msg->header, | ||
2622 | cid, | ||
2623 | c, | ||
2624 | peer, | ||
2625 | zero); | ||
2626 | |||
2627 | /* If something went wrong, discard message. */ | ||
2628 | if (GNUNET_SYSERR == fwd) | ||
2629 | { | ||
2630 | GNUNET_break_op (0); | ||
2631 | GCC_check_connections (); | ||
2632 | return; | ||
2633 | } | ||
2634 | 714 | ||
2635 | /* Is this message for us? */ | 715 | if (GNUNET_YES != available) |
2636 | if (GCC_is_terminal (c, fwd)) | ||
2637 | { | 716 | { |
2638 | LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n"); | 717 | /* Connection is down, for now... */ |
2639 | GNUNET_STATISTICS_update (stats, "# received KX", 1, GNUNET_NO); | 718 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2640 | if (NULL == c->t) | 719 | "Core MQ for %s went down\n", |
720 | GCC_2s (cc)); | ||
721 | update_state (cc, | ||
722 | CADET_CONNECTION_NEW, | ||
723 | GNUNET_NO); | ||
724 | cc->retry_delay = GNUNET_TIME_UNIT_ZERO; | ||
725 | if (NULL != cc->task) | ||
2641 | { | 726 | { |
2642 | GNUNET_break (0); | 727 | GNUNET_SCHEDULER_cancel (cc->task); |
2643 | return; | 728 | cc->task = NULL; |
2644 | } | 729 | } |
2645 | GCT_handle_kx (c->t, msg); | ||
2646 | GCC_check_connections (); | ||
2647 | return; | ||
2648 | } | ||
2649 | |||
2650 | /* Message not for us: forward to next hop */ | ||
2651 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
2652 | GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); | ||
2653 | (void) GCC_send_prebuilt_message (&msg->header, 0, | ||
2654 | zero, c, fwd, | ||
2655 | GNUNET_NO, NULL, NULL); | ||
2656 | GCC_check_connections (); | ||
2657 | } | ||
2658 | |||
2659 | |||
2660 | /** | ||
2661 | * Handler for encrypted cadet network traffic (channel mgmt, data). | ||
2662 | * | ||
2663 | * @param peer Message sender (neighbor). | ||
2664 | * @param msg Message itself. | ||
2665 | */ | ||
2666 | void | ||
2667 | GCC_handle_encrypted (struct CadetPeer *peer, | ||
2668 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
2669 | { | ||
2670 | static struct CadetEncryptedMessageIdentifier zero; | ||
2671 | const struct GNUNET_CADET_ConnectionTunnelIdentifier* cid; | ||
2672 | struct CadetConnection *c; | ||
2673 | struct CadetEncryptedMessageIdentifier pid; | ||
2674 | int fwd; | ||
2675 | |||
2676 | GCC_check_connections (); | ||
2677 | cid = &msg->cid; | ||
2678 | pid = msg->cemi; | ||
2679 | log_message (&msg->header, peer, cid); | ||
2680 | |||
2681 | c = connection_get (cid); | ||
2682 | fwd = check_message (&msg->header, | ||
2683 | cid, | ||
2684 | c, | ||
2685 | peer, | ||
2686 | pid); | ||
2687 | |||
2688 | /* If something went wrong, discard message. */ | ||
2689 | if (GNUNET_SYSERR == fwd) | ||
2690 | { | ||
2691 | GCC_check_connections (); | ||
2692 | return; | 730 | return; |
2693 | } | 731 | } |
2694 | 732 | ||
2695 | /* Is this message for us? */ | 733 | update_state (cc, |
2696 | if (GCC_is_terminal (c, fwd)) | 734 | cc->state, |
2697 | { | 735 | GNUNET_YES); |
2698 | GNUNET_STATISTICS_update (stats, "# received encrypted", 1, GNUNET_NO); | 736 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2699 | 737 | "Core MQ for %s became available in state %d\n", | |
2700 | if (NULL == c->t) | 738 | GCC_2s (cc), |
739 | cc->state); | ||
740 | switch (cc->state) | ||
741 | { | ||
742 | case CADET_CONNECTION_NEW: | ||
743 | /* Transmit immediately */ | ||
744 | cc->task = GNUNET_SCHEDULER_add_now (&send_create, | ||
745 | cc); | ||
746 | break; | ||
747 | case CADET_CONNECTION_SENDING_CREATE: | ||
748 | /* Should not be possible to be called in this state. */ | ||
749 | GNUNET_assert (0); | ||
750 | break; | ||
751 | case CADET_CONNECTION_SENT: | ||
752 | /* Retry a bit later... */ | ||
753 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
754 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay, | ||
755 | &send_create, | ||
756 | cc); | ||
757 | break; | ||
758 | case CADET_CONNECTION_CREATE_RECEIVED: | ||
759 | /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */ | ||
760 | cc->metrics.age = GNUNET_TIME_absolute_get (); | ||
761 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | ||
762 | cc); | ||
763 | break; | ||
764 | case CADET_CONNECTION_READY: | ||
765 | if ( (NULL == cc->keepalive_qe) && | ||
766 | (GNUNET_YES == cc->mqm_ready) && | ||
767 | (NULL == cc->task) ) | ||
2701 | { | 768 | { |
2702 | GNUNET_break (GNUNET_NO != c->destroy); | 769 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2703 | return; | 770 | "Scheduling keepalive for %s in %s\n", |
771 | GCC_2s (cc), | ||
772 | GNUNET_STRINGS_relative_time_to_string (keepalive_period, | ||
773 | GNUNET_YES)); | ||
774 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, | ||
775 | &send_keepalive, | ||
776 | cc); | ||
2704 | } | 777 | } |
2705 | GCT_handle_encrypted (c->t, msg); | 778 | break; |
2706 | GCC_send_ack (c, fwd, GNUNET_NO); | ||
2707 | GCC_check_connections (); | ||
2708 | return; | ||
2709 | } | 779 | } |
2710 | |||
2711 | /* Message not for us: forward to next hop */ | ||
2712 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
2713 | GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); | ||
2714 | (void) GCC_send_prebuilt_message (&msg->header, 0, | ||
2715 | zero, c, fwd, | ||
2716 | GNUNET_NO, NULL, NULL); | ||
2717 | GCC_check_connections (); | ||
2718 | } | 780 | } |
2719 | 781 | ||
2720 | 782 | ||
2721 | /** | 783 | /** |
2722 | * Initialize the connections subsystem | 784 | * Create a connection to @a destination via @a path and notify @a cb |
785 | * whenever we are ready for more data. Shared logic independent of | ||
786 | * who is initiating the connection. | ||
2723 | * | 787 | * |
2724 | * @param c Configuration handle. | 788 | * @param destination where to go |
789 | * @param path which path to take (may not be the full path) | ||
790 | * @param off offset of @a destination on @a path | ||
791 | * @param options options for the connection | ||
792 | * @param ct which tunnel uses this connection | ||
793 | * @param init_state initial state for the connection | ||
794 | * @param ready_cb function to call when ready to transmit | ||
795 | * @param ready_cb_cls closure for @a cb | ||
796 | * @return handle to the connection | ||
2725 | */ | 797 | */ |
2726 | void | 798 | static struct CadetConnection * |
2727 | GCC_init (const struct GNUNET_CONFIGURATION_Handle *c) | 799 | connection_create (struct CadetPeer *destination, |
2728 | { | 800 | struct CadetPeerPath *path, |
2729 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | 801 | unsigned int off, |
2730 | if (GNUNET_OK != | 802 | enum GNUNET_CADET_ChannelOption options, |
2731 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_MSGS_QUEUE", | 803 | struct CadetTConnection *ct, |
2732 | &max_msgs_queue)) | 804 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, |
2733 | { | 805 | enum CadetConnectionState init_state, |
2734 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | 806 | GCC_ReadyCallback ready_cb, |
2735 | "CADET", "MAX_MSGS_QUEUE", "MISSING"); | 807 | void *ready_cb_cls) |
2736 | GNUNET_SCHEDULER_shutdown (); | 808 | { |
2737 | return; | 809 | struct CadetConnection *cc; |
2738 | } | 810 | struct CadetPeer *first_hop; |
2739 | 811 | ||
2740 | if (GNUNET_OK != | 812 | cc = GNUNET_new (struct CadetConnection); |
2741 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_CONNECTIONS", | 813 | cc->options = options; |
2742 | &max_connections)) | 814 | cc->state = init_state; |
2743 | { | 815 | cc->ct = ct; |
2744 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | 816 | cc->cid = *cid; |
2745 | "CADET", "MAX_CONNECTIONS", "MISSING"); | ||
2746 | GNUNET_SCHEDULER_shutdown (); | ||
2747 | return; | ||
2748 | } | ||
2749 | |||
2750 | if (GNUNET_OK != | ||
2751 | GNUNET_CONFIGURATION_get_value_time (c, "CADET", "REFRESH_CONNECTION_TIME", | ||
2752 | &refresh_connection_time)) | ||
2753 | { | ||
2754 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
2755 | "CADET", "REFRESH_CONNECTION_TIME", "MISSING"); | ||
2756 | GNUNET_SCHEDULER_shutdown (); | ||
2757 | return; | ||
2758 | } | ||
2759 | create_connection_time = GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, | ||
2760 | refresh_connection_time); | ||
2761 | connections = GNUNET_CONTAINER_multishortmap_create (1024, | ||
2762 | GNUNET_YES); | ||
2763 | } | ||
2764 | |||
2765 | |||
2766 | /** | ||
2767 | * Destroy each connection on shutdown. | ||
2768 | * | ||
2769 | * @param cls Closure (unused). | ||
2770 | * @param key Current key code (CID, unused). | ||
2771 | * @param value Value in the hash map (`struct CadetConnection`) | ||
2772 | * | ||
2773 | * @return #GNUNET_YES, because we should continue to iterate | ||
2774 | */ | ||
2775 | static int | ||
2776 | shutdown_iterator (void *cls, | ||
2777 | const struct GNUNET_ShortHashCode *key, | ||
2778 | void *value) | ||
2779 | { | ||
2780 | struct CadetConnection *c = value; | ||
2781 | |||
2782 | c->state = CADET_CONNECTION_DESTROYED; | ||
2783 | GCC_destroy (c); | ||
2784 | return GNUNET_YES; | ||
2785 | } | ||
2786 | |||
2787 | |||
2788 | /** | ||
2789 | * Shut down the connections subsystem. | ||
2790 | */ | ||
2791 | void | ||
2792 | GCC_shutdown (void) | ||
2793 | { | ||
2794 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connections\n"); | ||
2795 | GCC_check_connections (); | ||
2796 | GNUNET_CONTAINER_multishortmap_iterate (connections, | ||
2797 | &shutdown_iterator, | ||
2798 | NULL); | ||
2799 | GNUNET_CONTAINER_multishortmap_destroy (connections); | ||
2800 | connections = NULL; | ||
2801 | } | ||
2802 | |||
2803 | |||
2804 | /** | ||
2805 | * Create a connection. | ||
2806 | * | ||
2807 | * @param cid Connection ID (either created locally or imposed remotely). | ||
2808 | * @param t Tunnel this connection belongs to (or NULL for transit connections); | ||
2809 | * @param path Path this connection has to use (copy is made). | ||
2810 | * @param own_pos Own position in the @c path path. | ||
2811 | * | ||
2812 | * @return Newly created connection. | ||
2813 | * NULL in case of error: own id not in path, wrong neighbors, ... | ||
2814 | */ | ||
2815 | struct CadetConnection * | ||
2816 | GCC_new (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
2817 | struct CadetTunnel *t, | ||
2818 | struct CadetPeerPath *path, | ||
2819 | unsigned int own_pos) | ||
2820 | { | ||
2821 | struct CadetConnection *c; | ||
2822 | struct CadetPeerPath *cpath; | ||
2823 | |||
2824 | GCC_check_connections (); | ||
2825 | cpath = path_duplicate (path); | ||
2826 | GNUNET_assert (NULL != cpath); | ||
2827 | c = GNUNET_new (struct CadetConnection); | ||
2828 | c->id = *cid; | ||
2829 | GNUNET_assert (GNUNET_OK == | 817 | GNUNET_assert (GNUNET_OK == |
2830 | GNUNET_CONTAINER_multishortmap_put (connections, | 818 | GNUNET_CONTAINER_multishortmap_put (connections, |
2831 | &c->id.connection_of_tunnel, | 819 | &GCC_get_id (cc)->connection_of_tunnel, |
2832 | c, | 820 | cc, |
2833 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 821 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); |
2834 | fc_init (&c->fwd_fc); | 822 | cc->ready_cb = ready_cb; |
2835 | fc_init (&c->bck_fc); | 823 | cc->ready_cb_cls = ready_cb_cls; |
2836 | c->fwd_fc.c = c; | 824 | cc->path = path; |
2837 | c->bck_fc.c = c; | 825 | cc->off = off; |
2838 | |||
2839 | c->t = t; | ||
2840 | GNUNET_assert (own_pos <= cpath->length - 1); | ||
2841 | c->own_pos = own_pos; | ||
2842 | c->path = cpath; | ||
2843 | cpath->c = c; | ||
2844 | if (GNUNET_OK != register_neighbors (c)) | ||
2845 | { | ||
2846 | if (0 == own_pos) | ||
2847 | { | ||
2848 | /* We were the origin of this request, this means we have invalid | ||
2849 | * info about the paths to reach the destination. We must invalidate | ||
2850 | * the *original* path to avoid trying it again in the next minute. | ||
2851 | */ | ||
2852 | if (2 < path->length) | ||
2853 | path_invalidate (path); | ||
2854 | else | ||
2855 | { | ||
2856 | GNUNET_break (0); | ||
2857 | GCT_debug(t, GNUNET_ERROR_TYPE_WARNING); | ||
2858 | } | ||
2859 | c->t = NULL; | ||
2860 | } | ||
2861 | path_destroy (c->path); | ||
2862 | c->path = NULL; | ||
2863 | GCC_destroy (c); | ||
2864 | return NULL; | ||
2865 | } | ||
2866 | LOG (GNUNET_ERROR_TYPE_INFO, "New connection %s\n", GCC_2s (c)); | ||
2867 | GCC_check_connections (); | ||
2868 | return c; | ||
2869 | } | ||
2870 | |||
2871 | |||
2872 | /** | ||
2873 | * Connection is no longer needed: destroy it. | ||
2874 | * | ||
2875 | * Cancels all pending traffic (including possible DESTROY messages), all | ||
2876 | * maintenance tasks and removes the connection from neighbor peers and tunnel. | ||
2877 | * | ||
2878 | * @param c Connection to destroy. | ||
2879 | */ | ||
2880 | void | ||
2881 | GCC_destroy (struct CadetConnection *c) | ||
2882 | { | ||
2883 | GCC_check_connections (); | ||
2884 | if (NULL == c) | ||
2885 | { | ||
2886 | GNUNET_break (0); | ||
2887 | return; | ||
2888 | } | ||
2889 | |||
2890 | if (2 == c->destroy) /* cancel queues -> GCP_queue_cancel -> q_destroy -> */ | ||
2891 | return; /* -> message_sent -> GCC_destroy. Don't loop. */ | ||
2892 | c->destroy = 2; | ||
2893 | |||
2894 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2895 | "destroying connection %s\n", | ||
2896 | GCC_2s (c)); | ||
2897 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2898 | " fc's f: %p, b: %p\n", | ||
2899 | &c->fwd_fc, &c->bck_fc); | ||
2900 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2901 | " fc tasks f: %u, b: %u\n", | ||
2902 | c->fwd_fc.poll_task, | ||
2903 | c->bck_fc.poll_task); | ||
2904 | |||
2905 | /* Cancel all traffic */ | ||
2906 | if (NULL != c->path) | ||
2907 | { | ||
2908 | connection_cancel_queues (c, GNUNET_YES); | ||
2909 | connection_cancel_queues (c, GNUNET_NO); | ||
2910 | if (NULL != c->maintenance_q) | ||
2911 | { | ||
2912 | GCP_send_cancel (c->maintenance_q); | ||
2913 | c->maintenance_q = NULL; | ||
2914 | } | ||
2915 | } | ||
2916 | unregister_neighbors (c); | ||
2917 | path_destroy (c->path); | ||
2918 | c->path = NULL; | ||
2919 | |||
2920 | /* Delete from tunnel */ | ||
2921 | if (NULL != c->t) | ||
2922 | GCT_remove_connection (c->t, c); | ||
2923 | |||
2924 | if (NULL != c->check_duplicates_task) | ||
2925 | GNUNET_SCHEDULER_cancel (c->check_duplicates_task); | ||
2926 | if (NULL != c->fwd_maintenance_task) | ||
2927 | GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task); | ||
2928 | if (NULL != c->bck_maintenance_task) | ||
2929 | GNUNET_SCHEDULER_cancel (c->bck_maintenance_task); | ||
2930 | |||
2931 | if (GNUNET_NO == c->was_removed) | ||
2932 | { | ||
2933 | GNUNET_break (GNUNET_YES == | ||
2934 | GNUNET_CONTAINER_multishortmap_remove (connections, | ||
2935 | &c->id.connection_of_tunnel, | ||
2936 | c)); | ||
2937 | } | ||
2938 | GNUNET_STATISTICS_update (stats, | ||
2939 | "# connections", | ||
2940 | -1, | ||
2941 | GNUNET_NO); | ||
2942 | GNUNET_free (c); | ||
2943 | GCC_check_connections (); | ||
2944 | } | ||
2945 | |||
2946 | |||
2947 | /** | ||
2948 | * Get the connection ID. | ||
2949 | * | ||
2950 | * @param c Connection to get the ID from. | ||
2951 | * | ||
2952 | * @return ID of the connection. | ||
2953 | */ | ||
2954 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
2955 | GCC_get_id (const struct CadetConnection *c) | ||
2956 | { | ||
2957 | return &c->id; | ||
2958 | } | ||
2959 | |||
2960 | |||
2961 | /** | ||
2962 | * Get the connection path. | ||
2963 | * | ||
2964 | * @param c Connection to get the path from. | ||
2965 | * | ||
2966 | * @return path used by the connection. | ||
2967 | */ | ||
2968 | const struct CadetPeerPath * | ||
2969 | GCC_get_path (const struct CadetConnection *c) | ||
2970 | { | ||
2971 | if (GNUNET_NO == c->destroy) | ||
2972 | return c->path; | ||
2973 | return NULL; | ||
2974 | } | ||
2975 | |||
2976 | |||
2977 | /** | ||
2978 | * Get the connection state. | ||
2979 | * | ||
2980 | * @param c Connection to get the state from. | ||
2981 | * | ||
2982 | * @return state of the connection. | ||
2983 | */ | ||
2984 | enum CadetConnectionState | ||
2985 | GCC_get_state (const struct CadetConnection *c) | ||
2986 | { | ||
2987 | return c->state; | ||
2988 | } | ||
2989 | |||
2990 | /** | ||
2991 | * Get the connection tunnel. | ||
2992 | * | ||
2993 | * @param c Connection to get the tunnel from. | ||
2994 | * | ||
2995 | * @return tunnel of the connection. | ||
2996 | */ | ||
2997 | struct CadetTunnel * | ||
2998 | GCC_get_tunnel (const struct CadetConnection *c) | ||
2999 | { | ||
3000 | return c->t; | ||
3001 | } | ||
3002 | |||
3003 | |||
3004 | /** | ||
3005 | * Get free buffer space in a connection. | ||
3006 | * | ||
3007 | * @param c Connection. | ||
3008 | * @param fwd Is query about FWD traffic? | ||
3009 | * | ||
3010 | * @return Free buffer space [0 - max_msgs_queue/max_connections] | ||
3011 | */ | ||
3012 | unsigned int | ||
3013 | GCC_get_buffer (struct CadetConnection *c, int fwd) | ||
3014 | { | ||
3015 | struct CadetFlowControl *fc; | ||
3016 | |||
3017 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3018 | |||
3019 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Get %s buffer on %s: %u - %u\n", | ||
3020 | GC_f2s (fwd), GCC_2s (c), fc->queue_max, fc->queue_n); | ||
3021 | GCC_debug (c, GNUNET_ERROR_TYPE_DEBUG); | ||
3022 | |||
3023 | return (fc->queue_max - fc->queue_n); | ||
3024 | } | ||
3025 | |||
3026 | |||
3027 | /** | ||
3028 | * Get how many messages have we allowed to send to us from a direction. | ||
3029 | * | ||
3030 | * @param c Connection. | ||
3031 | * @param fwd Are we asking about traffic from FWD (BCK messages)? | ||
3032 | * | ||
3033 | * @return last_ack_sent - last_pid_recv | ||
3034 | */ | ||
3035 | unsigned int | ||
3036 | GCC_get_allowed (struct CadetConnection *c, int fwd) | ||
3037 | { | ||
3038 | struct CadetFlowControl *fc; | ||
3039 | |||
3040 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3041 | if ( (CADET_CONNECTION_READY != c->state) || | ||
3042 | GC_is_pid_bigger (ntohl (fc->last_pid_recv.pid), | ||
3043 | ntohl (fc->last_ack_sent.pid)) ) | ||
3044 | { | ||
3045 | return 0; | ||
3046 | } | ||
3047 | return (ntohl (fc->last_ack_sent.pid) - ntohl (fc->last_pid_recv.pid)); | ||
3048 | } | ||
3049 | |||
3050 | |||
3051 | /** | ||
3052 | * Get messages queued in a connection. | ||
3053 | * | ||
3054 | * @param c Connection. | ||
3055 | * @param fwd Is query about FWD traffic? | ||
3056 | * | ||
3057 | * @return Number of messages queued. | ||
3058 | */ | ||
3059 | unsigned int | ||
3060 | GCC_get_qn (struct CadetConnection *c, int fwd) | ||
3061 | { | ||
3062 | struct CadetFlowControl *fc; | ||
3063 | |||
3064 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3065 | |||
3066 | return fc->queue_n; | ||
3067 | } | ||
3068 | |||
3069 | |||
3070 | /** | ||
3071 | * Get next PID to use. | ||
3072 | * | ||
3073 | * @param c Connection. | ||
3074 | * @param fwd Is query about FWD traffic? | ||
3075 | * @return Next PID to use. | ||
3076 | */ | ||
3077 | struct CadetEncryptedMessageIdentifier | ||
3078 | GCC_get_pid (struct CadetConnection *c, int fwd) | ||
3079 | { | ||
3080 | struct CadetFlowControl *fc; | ||
3081 | struct CadetEncryptedMessageIdentifier pid; | ||
3082 | |||
3083 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3084 | pid = fc->next_pid; | ||
3085 | fc->next_pid.pid = htonl (1 + ntohl (pid.pid)); | ||
3086 | return pid; | ||
3087 | } | ||
3088 | |||
3089 | |||
3090 | /** | ||
3091 | * Allow the connection to advertise a buffer of the given size. | ||
3092 | * | ||
3093 | * The connection will send an @c fwd ACK message (so: in direction !fwd) | ||
3094 | * allowing up to last_pid_recv + buffer. | ||
3095 | * | ||
3096 | * @param c Connection. | ||
3097 | * @param buffer How many more messages the connection can accept. | ||
3098 | * @param fwd Is this about FWD traffic? (The ack will go dest->root). | ||
3099 | */ | ||
3100 | void | ||
3101 | GCC_allow (struct CadetConnection *c, unsigned int buffer, int fwd) | ||
3102 | { | ||
3103 | LOG (GNUNET_ERROR_TYPE_DEBUG, " allowing %s %u messages %s\n", | ||
3104 | GCC_2s (c), buffer, GC_f2s (fwd)); | ||
3105 | send_ack (c, buffer, fwd, GNUNET_NO); | ||
3106 | } | ||
3107 | |||
3108 | |||
3109 | /** | ||
3110 | * Notify other peers on a connection of a broken link. Mark connections | ||
3111 | * to destroy after all traffic has been sent. | ||
3112 | * | ||
3113 | * @param c Connection on which there has been a disconnection. | ||
3114 | * @param peer Peer that disconnected. | ||
3115 | */ | ||
3116 | void | ||
3117 | GCC_neighbor_disconnected (struct CadetConnection *c, struct CadetPeer *peer) | ||
3118 | { | ||
3119 | struct CadetFlowControl *fc; | ||
3120 | char peer_name[16]; | ||
3121 | int fwd; | ||
3122 | |||
3123 | GCC_check_connections (); | ||
3124 | strncpy (peer_name, GCP_2s (peer), 16); | ||
3125 | peer_name[15] = '\0'; | ||
3126 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 826 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
3127 | "shutting down %s, %s disconnected\n", | 827 | "Creating %s using path %s\n", |
3128 | GCC_2s (c), peer_name); | 828 | GCC_2s (cc), |
3129 | 829 | GCPP_2s (path)); | |
3130 | invalidate_paths (c, peer); | 830 | GCPP_add_connection (path, |
3131 | 831 | off, | |
3132 | fwd = is_fwd (c, peer); | 832 | cc); |
3133 | if (GNUNET_SYSERR == fwd) | 833 | for (unsigned int i=0;i<off;i++) |
3134 | { | 834 | GCP_add_connection (GCPP_get_peer_at_offset (path, |
3135 | GNUNET_break (0); | 835 | i), |
3136 | return; | 836 | cc); |
3137 | } | 837 | |
3138 | if ( (GNUNET_YES == GCC_is_terminal (c, fwd)) || | 838 | first_hop = GCPP_get_peer_at_offset (path, |
3139 | (GNUNET_NO != c->destroy) ) | 839 | 0); |
3140 | { | 840 | cc->mq_man = GCP_request_mq (first_hop, |
3141 | /* Local shutdown, or other peer already down (hence 'c->destroy'); | 841 | &manage_first_hop_mq, |
3142 | so there is no one to notify about this, just clean up. */ | 842 | cc); |
3143 | GCC_destroy (c); | 843 | return cc; |
3144 | GCC_check_connections (); | 844 | } |
3145 | return; | 845 | |
3146 | } | 846 | |
3147 | /* Mark FlowControl towards the peer as unavaliable. */ | 847 | /** |
3148 | fc = fwd ? &c->bck_fc : &c->fwd_fc; | 848 | * Create a connection to @a destination via @a path and |
3149 | fc->queue_max = 0; | 849 | * notify @a cb whenever we are ready for more data. This |
3150 | 850 | * is an inbound tunnel, so we must use the existing @a cid | |
3151 | send_broken (c, &my_full_id, GCP_get_id (peer), fwd); | 851 | * |
3152 | 852 | * @param destination where to go | |
3153 | /* Connection will have at least one pending message | 853 | * @param path which path to take (may not be the full path) |
3154 | * (the one we just scheduled), so delay destruction | 854 | * @param options options for the connection |
3155 | * and remove from map so we don't use accidentally. */ | 855 | * @param ct which tunnel uses this connection |
3156 | mark_destroyed (c); | 856 | * @param ready_cb function to call when ready to transmit |
3157 | GNUNET_assert (GNUNET_NO == c->was_removed); | 857 | * @param ready_cb_cls closure for @a cb |
3158 | c->was_removed = GNUNET_YES; | 858 | * @return handle to the connection, NULL if we already have |
3159 | GNUNET_break (GNUNET_YES == | 859 | * a connection that takes precedence on @a path |
3160 | GNUNET_CONTAINER_multishortmap_remove (connections, | ||
3161 | &c->id.connection_of_tunnel, | ||
3162 | c)); | ||
3163 | /* Cancel queue in the direction that just died. */ | ||
3164 | connection_cancel_queues (c, ! fwd); | ||
3165 | GCC_stop_poll (c, ! fwd); | ||
3166 | unregister_neighbors (c); | ||
3167 | GCC_check_connections (); | ||
3168 | } | ||
3169 | |||
3170 | |||
3171 | /** | ||
3172 | * Is this peer the first one on the connection? | ||
3173 | * | ||
3174 | * @param c Connection. | ||
3175 | * @param fwd Is this about fwd traffic? | ||
3176 | * | ||
3177 | * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal. | ||
3178 | */ | 860 | */ |
3179 | int | 861 | struct CadetConnection * |
3180 | GCC_is_origin (struct CadetConnection *c, int fwd) | 862 | GCC_create_inbound (struct CadetPeer *destination, |
3181 | { | 863 | struct CadetPeerPath *path, |
3182 | if (!fwd && c->path->length - 1 == c->own_pos ) | 864 | enum GNUNET_CADET_ChannelOption options, |
3183 | return GNUNET_YES; | 865 | struct CadetTConnection *ct, |
3184 | if (fwd && 0 == c->own_pos) | 866 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, |
3185 | return GNUNET_YES; | 867 | GCC_ReadyCallback ready_cb, |
3186 | return GNUNET_NO; | 868 | void *ready_cb_cls) |
3187 | } | 869 | { |
3188 | 870 | struct CadetConnection *cc; | |
3189 | 871 | unsigned int off; | |
3190 | /** | 872 | |
3191 | * Is this peer the last one on the connection? | 873 | off = GCPP_find_peer (path, |
3192 | * | 874 | destination); |
3193 | * @param c Connection. | 875 | GNUNET_assert (UINT_MAX != off); |
3194 | * @param fwd Is this about fwd traffic? | 876 | cc = GCPP_get_connection (path, |
3195 | * Note that the ROOT is the terminal for BCK traffic! | 877 | destination, |
3196 | * | 878 | off); |
3197 | * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin. | 879 | if (NULL != cc) |
3198 | */ | 880 | { |
3199 | int | 881 | int cmp; |
3200 | GCC_is_terminal (struct CadetConnection *c, int fwd) | 882 | |
3201 | { | 883 | cmp = memcmp (cid, |
3202 | return GCC_is_origin (c, ! fwd); | 884 | &cc->cid, |
3203 | } | 885 | sizeof (*cid)); |
3204 | 886 | if (0 == cmp) | |
3205 | 887 | { | |
3206 | /** | 888 | /* Two peers picked the SAME random connection identifier at the |
3207 | * See if we are allowed to send by the next hop in the given direction. | 889 | same time for the same path? Must be malicious. Drop |
3208 | * | 890 | connection (existing and inbound), even if it is the only |
3209 | * @param c Connection. | 891 | one. */ |
3210 | * @param fwd Is this about fwd traffic? | 892 | GNUNET_break_op (0); |
3211 | * | 893 | GCT_connection_lost (cc->ct); |
3212 | * @return #GNUNET_YES in case it's OK to send. | 894 | GCC_destroy_without_tunnel (cc); |
3213 | */ | ||
3214 | int | ||
3215 | GCC_is_sendable (struct CadetConnection *c, int fwd) | ||
3216 | { | ||
3217 | struct CadetFlowControl *fc; | ||
3218 | |||
3219 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3220 | " checking sendability of %s traffic on %s\n", | ||
3221 | GC_f2s (fwd), GCC_2s (c)); | ||
3222 | if (NULL == c) | ||
3223 | { | ||
3224 | GNUNET_break (0); | ||
3225 | return GNUNET_YES; | ||
3226 | } | ||
3227 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3228 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3229 | " last ack recv: %u, last pid sent: %u\n", | ||
3230 | ntohl (fc->last_ack_recv.pid), | ||
3231 | ntohl (fc->last_pid_sent.pid)); | ||
3232 | if (GC_is_pid_bigger (ntohl (fc->last_ack_recv.pid), | ||
3233 | ntohl (fc->last_pid_sent.pid))) | ||
3234 | { | ||
3235 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable\n"); | ||
3236 | return GNUNET_YES; | ||
3237 | } | ||
3238 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n"); | ||
3239 | return GNUNET_NO; | ||
3240 | } | ||
3241 | |||
3242 | |||
3243 | /** | ||
3244 | * Check if this connection is a direct one (never trim a direct connection). | ||
3245 | * | ||
3246 | * @param c Connection. | ||
3247 | * | ||
3248 | * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise. | ||
3249 | */ | ||
3250 | int | ||
3251 | GCC_is_direct (struct CadetConnection *c) | ||
3252 | { | ||
3253 | return (c->path->length == 2) ? GNUNET_YES : GNUNET_NO; | ||
3254 | } | ||
3255 | |||
3256 | |||
3257 | /** | ||
3258 | * Sends a completely built message on a connection, properly registering | ||
3259 | * all used resources. | ||
3260 | * | ||
3261 | * @param message Message to send. | ||
3262 | * @param payload_type Type of payload, in case the message is encrypted. | ||
3263 | * 0 for restransmissions (when type is no longer known) | ||
3264 | * UINT16_MAX when not applicable. | ||
3265 | * @param payload_id ID of the payload (PID, ACK, ...). | ||
3266 | * @param c Connection on which this message is transmitted. | ||
3267 | * @param fwd Is this a fwd message? | ||
3268 | * @param force Force the connection to accept the message (buffer overfill). | ||
3269 | * @param cont Continuation called once message is sent. Can be NULL. | ||
3270 | * @param cont_cls Closure for @c cont. | ||
3271 | * | ||
3272 | * @return Handle to cancel the message before it's sent. | ||
3273 | * NULL on error. | ||
3274 | * Invalid on @c cont call. | ||
3275 | */ | ||
3276 | struct CadetConnectionQueue * | ||
3277 | GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
3278 | uint16_t payload_type, | ||
3279 | struct CadetEncryptedMessageIdentifier payload_id, | ||
3280 | struct CadetConnection *c, int fwd, int force, | ||
3281 | GCC_sent cont, void *cont_cls) | ||
3282 | { | ||
3283 | struct CadetFlowControl *fc; | ||
3284 | struct CadetConnectionQueue *q; | ||
3285 | uint16_t size; | ||
3286 | uint16_t type; | ||
3287 | |||
3288 | size = ntohs (message->size); | ||
3289 | type = ntohs (message->type); | ||
3290 | |||
3291 | GCC_check_connections (); | ||
3292 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3293 | if (0 == fc->queue_max) | ||
3294 | { | ||
3295 | GNUNET_break (0); | ||
3296 | return NULL; | ||
3297 | } | ||
3298 | |||
3299 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
3300 | "--> %s (%s %4u) on conn %s (%p) %s [%5u]\n", | ||
3301 | GC_m2s (type), GC_m2s (payload_type), payload_id, GCC_2s (c), c, | ||
3302 | GC_f2s(fwd), size); | ||
3303 | switch (type) | ||
3304 | { | ||
3305 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED: | ||
3306 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u, PIDsnt: %u, ACKrcv: %u\n", | ||
3307 | fc, | ||
3308 | fc->queue_n, | ||
3309 | ntohl (fc->last_pid_sent.pid), | ||
3310 | ntohl (fc->last_ack_recv.pid)); | ||
3311 | if (GNUNET_NO == force) | ||
3312 | { | ||
3313 | fc->queue_n++; | ||
3314 | } | ||
3315 | break; | ||
3316 | |||
3317 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX: | ||
3318 | /* nothing to do here */ | ||
3319 | break; | ||
3320 | |||
3321 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
3322 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK: | ||
3323 | /* Should've only be used for restransmissions. */ | ||
3324 | GNUNET_break (0 == payload_type); | ||
3325 | break; | ||
3326 | |||
3327 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK: | ||
3328 | case GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL: | ||
3329 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
3330 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
3331 | GNUNET_assert (GNUNET_YES == force); | ||
3332 | break; | ||
3333 | |||
3334 | default: | ||
3335 | GNUNET_break (0); | ||
3336 | return NULL; | 895 | return NULL; |
3337 | } | 896 | } |
3338 | 897 | if (0 < cmp) | |
3339 | if (fc->queue_n > fc->queue_max && GNUNET_NO == force) | ||
3340 | { | ||
3341 | GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)", | ||
3342 | 1, GNUNET_NO); | ||
3343 | GNUNET_break (0); | ||
3344 | LOG (GNUNET_ERROR_TYPE_DEBUG, "queue full: %u/%u\n", | ||
3345 | fc->queue_n, fc->queue_max); | ||
3346 | if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == type) | ||
3347 | { | 898 | { |
3348 | fc->queue_n--; | 899 | /* drop existing */ |
900 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
901 | "Got two connections on %s, dropping my existing %s\n", | ||
902 | GCPP_2s (path), | ||
903 | GCC_2s (cc)); | ||
904 | GCT_connection_lost (cc->ct); | ||
905 | GCC_destroy_without_tunnel (cc); | ||
3349 | } | 906 | } |
3350 | return NULL; /* Drop this message */ | 907 | else |
3351 | } | ||
3352 | |||
3353 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %s %u\n", | ||
3354 | GCC_2s (c), c->pending_messages); | ||
3355 | c->pending_messages++; | ||
3356 | |||
3357 | q = GNUNET_new (struct CadetConnectionQueue); | ||
3358 | q->cont = cont; | ||
3359 | q->cont_cls = cont_cls; | ||
3360 | q->forced = force; | ||
3361 | GNUNET_CONTAINER_DLL_insert (fc->q_head, fc->q_tail, q); | ||
3362 | q->peer_q = GCP_send (get_hop (c, fwd), | ||
3363 | message, | ||
3364 | payload_type, | ||
3365 | payload_id, | ||
3366 | c, | ||
3367 | fwd, | ||
3368 | &conn_message_sent, q); | ||
3369 | if (NULL == q->peer_q) | ||
3370 | { | ||
3371 | LOG (GNUNET_ERROR_TYPE_DEBUG, "dropping msg on %s, NULL q\n", GCC_2s (c)); | ||
3372 | GNUNET_CONTAINER_DLL_remove (fc->q_head, fc->q_tail, q); | ||
3373 | GNUNET_free (q); | ||
3374 | GCC_check_connections (); | ||
3375 | return NULL; | ||
3376 | } | ||
3377 | GCC_check_connections (); | ||
3378 | return q; | ||
3379 | } | ||
3380 | |||
3381 | |||
3382 | /** | ||
3383 | * Cancel a previously sent message while it's in the queue. | ||
3384 | * | ||
3385 | * ONLY can be called before the continuation given to the send function | ||
3386 | * is called. Once the continuation is called, the message is no longer in the | ||
3387 | * queue. | ||
3388 | * | ||
3389 | * @param q Handle to the queue. | ||
3390 | */ | ||
3391 | void | ||
3392 | GCC_cancel (struct CadetConnectionQueue *q) | ||
3393 | { | ||
3394 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! GCC cancel message\n"); | ||
3395 | |||
3396 | /* send_cancel calls message_sent, which calls q->cont and frees q */ | ||
3397 | GCP_send_cancel (q->peer_q); | ||
3398 | GCC_check_connections (); | ||
3399 | } | ||
3400 | |||
3401 | |||
3402 | /** | ||
3403 | * Sends a CREATE CONNECTION message for a path to a peer. | ||
3404 | * Changes the connection and tunnel states if necessary. | ||
3405 | * | ||
3406 | * @param c Connection to create. | ||
3407 | */ | ||
3408 | void | ||
3409 | GCC_send_create (struct CadetConnection *c) | ||
3410 | { | ||
3411 | static struct CadetEncryptedMessageIdentifier zero; | ||
3412 | enum CadetTunnelCState state; | ||
3413 | size_t size; | ||
3414 | |||
3415 | GCC_check_connections (); | ||
3416 | size = sizeof (struct GNUNET_CADET_ConnectionCreateMessage); | ||
3417 | size += c->path->length * sizeof (struct GNUNET_PeerIdentity); | ||
3418 | { | ||
3419 | /* Allocate message on the stack */ | ||
3420 | unsigned char cbuf[size]; | ||
3421 | struct GNUNET_CADET_ConnectionCreateMessage *msg; | ||
3422 | struct GNUNET_PeerIdentity *peers; | ||
3423 | |||
3424 | |||
3425 | msg = (struct GNUNET_CADET_ConnectionCreateMessage *) cbuf; | ||
3426 | msg->header.size = htons (size); | ||
3427 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | ||
3428 | msg->reserved = htonl (0); | ||
3429 | msg->cid = *GCC_get_id (c); | ||
3430 | peers = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
3431 | for (int i = 0; i < c->path->length; i++) | ||
3432 | { | 908 | { |
3433 | GNUNET_PEER_resolve (c->path->peers[i], peers++); | 909 | /* keep existing */ |
910 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
911 | "Got two connections on %s, keeping my existing %s\n", | ||
912 | GCPP_2s (path), | ||
913 | GCC_2s (cc)); | ||
914 | return NULL; | ||
3434 | } | 915 | } |
3435 | GNUNET_assert (NULL == c->maintenance_q); | ||
3436 | c->maintenance_q = GCP_send (get_next_hop (c), | ||
3437 | &msg->header, | ||
3438 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, | ||
3439 | zero, | ||
3440 | c, GNUNET_YES, | ||
3441 | &conn_message_sent, NULL); | ||
3442 | } | 916 | } |
3443 | 917 | ||
3444 | LOG (GNUNET_ERROR_TYPE_INFO, "==> %s %19s on conn %s (%p) FWD [%5u]\n", | 918 | return connection_create (destination, |
3445 | GC_m2s (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE), "", | 919 | path, |
3446 | GCC_2s (c), c, size); | 920 | off, |
3447 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (create)\n", | 921 | options, |
3448 | c, c->pending_messages); | 922 | ct, |
3449 | c->pending_messages++; | 923 | cid, |
3450 | 924 | CADET_CONNECTION_CREATE_RECEIVED, | |
3451 | state = GCT_get_cstate (c->t); | 925 | ready_cb, |
3452 | if (CADET_TUNNEL_SEARCHING == state || CADET_TUNNEL_NEW == state) | 926 | ready_cb_cls); |
3453 | GCT_change_cstate (c->t, CADET_TUNNEL_WAITING); | ||
3454 | if (CADET_CONNECTION_NEW == c->state) | ||
3455 | connection_change_state (c, CADET_CONNECTION_SENT); | ||
3456 | GCC_check_connections (); | ||
3457 | } | 927 | } |
3458 | 928 | ||
3459 | 929 | ||
3460 | /** | 930 | /** |
3461 | * Send an ACK on the appropriate connection/channel, depending on | 931 | * Create a connection to @a destination via @a path and |
3462 | * the direction and the position of the peer. | 932 | * notify @a cb whenever we are ready for more data. |
3463 | * | 933 | * |
3464 | * @param c Which connection to send the hop-by-hop ACK. | 934 | * @param destination where to go |
3465 | * @param fwd Is this a fwd ACK? (will go dest->root). | 935 | * @param path which path to take (may not be the full path) |
3466 | * @param force Send the ACK even if suboptimal (e.g. requested by POLL). | 936 | * @param off offset of @a destination on @a path |
937 | * @param options options for the connection | ||
938 | * @param ct tunnel that uses the connection | ||
939 | * @param ready_cb function to call when ready to transmit | ||
940 | * @param ready_cb_cls closure for @a cb | ||
941 | * @return handle to the connection | ||
3467 | */ | 942 | */ |
3468 | void | 943 | struct CadetConnection * |
3469 | GCC_send_ack (struct CadetConnection *c, int fwd, int force) | 944 | GCC_create (struct CadetPeer *destination, |
945 | struct CadetPeerPath *path, | ||
946 | unsigned int off, | ||
947 | enum GNUNET_CADET_ChannelOption options, | ||
948 | struct CadetTConnection *ct, | ||
949 | GCC_ReadyCallback ready_cb, | ||
950 | void *ready_cb_cls) | ||
3470 | { | 951 | { |
3471 | unsigned int buffer; | 952 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; |
3472 | |||
3473 | GCC_check_connections (); | ||
3474 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GCC send %s ACK on %s\n", | ||
3475 | GC_f2s (fwd), GCC_2s (c)); | ||
3476 | |||
3477 | if (NULL == c) | ||
3478 | { | ||
3479 | GNUNET_break (0); | ||
3480 | return; | ||
3481 | } | ||
3482 | 953 | ||
3483 | if (GNUNET_NO != c->destroy) | 954 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, |
3484 | { | 955 | &cid, |
3485 | LOG (GNUNET_ERROR_TYPE_DEBUG, " being destroyed, why bother...\n"); | 956 | sizeof (cid)); |
3486 | GCC_check_connections (); | 957 | return connection_create (destination, |
3487 | return; | 958 | path, |
3488 | } | 959 | off, |
3489 | 960 | options, | |
3490 | /* Get available buffer space */ | 961 | ct, |
3491 | if (GCC_is_terminal (c, fwd)) | 962 | &cid, |
3492 | { | 963 | CADET_CONNECTION_NEW, |
3493 | LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from all channels\n"); | 964 | ready_cb, |
3494 | buffer = GCT_get_channels_buffer (c->t); | 965 | ready_cb_cls); |
3495 | } | ||
3496 | else | ||
3497 | { | ||
3498 | LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n"); | ||
3499 | buffer = GCC_get_buffer (c, fwd); | ||
3500 | } | ||
3501 | LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer); | ||
3502 | if (0 == buffer && GNUNET_NO == force) | ||
3503 | { | ||
3504 | GCC_check_connections (); | ||
3505 | return; | ||
3506 | } | ||
3507 | |||
3508 | /* Send available buffer space */ | ||
3509 | if (GNUNET_YES == GCC_is_origin (c, fwd)) | ||
3510 | { | ||
3511 | GNUNET_assert (NULL != c->t); | ||
3512 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channels...\n"); | ||
3513 | GCT_unchoke_channels (c->t); | ||
3514 | } | ||
3515 | else | ||
3516 | { | ||
3517 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n"); | ||
3518 | send_ack (c, buffer, fwd, force); | ||
3519 | } | ||
3520 | GCC_check_connections (); | ||
3521 | } | 966 | } |
3522 | 967 | ||
3523 | 968 | ||
3524 | /** | 969 | /** |
3525 | * Send a message to all peers in this connection that the connection | 970 | * Transmit message @a msg via connection @a cc. Must only be called |
3526 | * is no longer valid. | 971 | * (once) after the connection has signalled that it is ready via the |
972 | * `ready_cb`. Clients can also use #GCC_is_ready() to check if the | ||
973 | * connection is right now ready for transmission. | ||
3527 | * | 974 | * |
3528 | * If some peer should not receive the message, it should be zero'ed out | 975 | * @param cc connection identification |
3529 | * before calling this function. | 976 | * @param env envelope with message to transmit; must NOT |
3530 | * | 977 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it |
3531 | * @param c The connection whose peers to notify. | ||
3532 | */ | 978 | */ |
3533 | void | 979 | void |
3534 | GCC_send_destroy (struct CadetConnection *c) | 980 | GCC_transmit (struct CadetConnection *cc, |
981 | struct GNUNET_MQ_Envelope *env) | ||
3535 | { | 982 | { |
3536 | static struct CadetEncryptedMessageIdentifier zero; | ||
3537 | struct GNUNET_CADET_ConnectionDestroyMessage msg; | ||
3538 | |||
3539 | if (GNUNET_YES == c->destroy) | ||
3540 | return; | ||
3541 | GCC_check_connections (); | ||
3542 | msg.header.size = htons (sizeof (msg)); | ||
3543 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); | ||
3544 | msg.cid = c->id; | ||
3545 | msg.reserved = htonl (0); | ||
3546 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 983 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
3547 | " sending connection destroy for connection %s\n", | 984 | "Scheduling message for transmission on %s\n", |
3548 | GCC_2s (c)); | 985 | GCC_2s (cc)); |
3549 | 986 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | |
3550 | if (GNUNET_NO == GCC_is_terminal (c, GNUNET_YES)) | 987 | GNUNET_assert (CADET_CONNECTION_READY == cc->state); |
3551 | (void) GCC_send_prebuilt_message (&msg.header, | 988 | cc->metrics.last_use = GNUNET_TIME_absolute_get (); |
3552 | UINT16_MAX, | 989 | cc->mqm_ready = GNUNET_NO; |
3553 | zero, | 990 | if (NULL != cc->task) |
3554 | c, | 991 | { |
3555 | GNUNET_YES, GNUNET_YES, NULL, NULL); | 992 | GNUNET_SCHEDULER_cancel (cc->task); |
3556 | if (GNUNET_NO == GCC_is_terminal (c, GNUNET_NO)) | 993 | cc->task = NULL; |
3557 | (void) GCC_send_prebuilt_message (&msg.header, | 994 | } |
3558 | UINT16_MAX, | 995 | GCP_send (cc->mq_man, |
3559 | zero, | 996 | env); |
3560 | c, | ||
3561 | GNUNET_NO, GNUNET_YES, NULL, NULL); | ||
3562 | mark_destroyed (c); | ||
3563 | GCC_check_connections (); | ||
3564 | } | 997 | } |
3565 | 998 | ||
3566 | 999 | ||
3567 | /** | 1000 | /** |
3568 | * @brief Start a polling timer for the connection. | 1001 | * Obtain the path used by this connection. |
3569 | * | ||
3570 | * When a neighbor does not accept more traffic on the connection it could be | ||
3571 | * caused by a simple congestion or by a lost ACK. Polling enables to check | ||
3572 | * for the lastest ACK status for a connection. | ||
3573 | * | 1002 | * |
3574 | * @param c Connection. | 1003 | * @param cc connection |
3575 | * @param fwd Should we poll in the FWD direction? | 1004 | * @return path to @a cc |
3576 | */ | 1005 | */ |
3577 | void | 1006 | struct CadetPeerPath * |
3578 | GCC_start_poll (struct CadetConnection *c, int fwd) | 1007 | GCC_get_path (struct CadetConnection *cc) |
3579 | { | 1008 | { |
3580 | struct CadetFlowControl *fc; | 1009 | return cc->path; |
3581 | |||
3582 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3583 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL %s requested\n", | ||
3584 | GC_f2s (fwd)); | ||
3585 | if (NULL != fc->poll_task || NULL != fc->poll_msg) | ||
3586 | { | ||
3587 | LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL already in progress (t: %p, m: %p)\n", | ||
3588 | fc->poll_task, fc->poll_msg); | ||
3589 | return; | ||
3590 | } | ||
3591 | if (0 == fc->queue_max) | ||
3592 | { | ||
3593 | /* Should not be needed, traffic should've been cancelled. */ | ||
3594 | GNUNET_break (0); | ||
3595 | LOG (GNUNET_ERROR_TYPE_DEBUG, " POLL not possible, peer disconnected\n"); | ||
3596 | return; | ||
3597 | } | ||
3598 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL started on request\n"); | ||
3599 | fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, &send_poll, fc); | ||
3600 | } | 1010 | } |
3601 | 1011 | ||
3602 | 1012 | ||
3603 | /** | 1013 | /** |
3604 | * @brief Stop polling a connection for ACKs. | 1014 | * Obtain unique ID for the connection. |
3605 | * | 1015 | * |
3606 | * Once we have enough ACKs for future traffic, polls are no longer necessary. | 1016 | * @param cc connection. |
3607 | * | 1017 | * @return unique number of the connection |
3608 | * @param c Connection. | ||
3609 | * @param fwd Should we stop the poll in the FWD direction? | ||
3610 | */ | 1018 | */ |
3611 | void | 1019 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * |
3612 | GCC_stop_poll (struct CadetConnection *c, int fwd) | 1020 | GCC_get_id (struct CadetConnection *cc) |
3613 | { | 1021 | { |
3614 | struct CadetFlowControl *fc; | 1022 | return &cc->cid; |
3615 | |||
3616 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3617 | if (NULL != fc->poll_task) | ||
3618 | { | ||
3619 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
3620 | fc->poll_task = NULL; | ||
3621 | } | ||
3622 | if (NULL != fc->poll_msg) | ||
3623 | { | ||
3624 | GCC_cancel (fc->poll_msg); | ||
3625 | fc->poll_msg = NULL; | ||
3626 | } | ||
3627 | } | 1023 | } |
3628 | 1024 | ||
3629 | 1025 | ||
3630 | /** | 1026 | /** |
3631 | * Get a (static) string for a connection. | 1027 | * Get a (static) string for a connection. |
3632 | * | 1028 | * |
3633 | * @param c Connection. | 1029 | * @param cc Connection. |
3634 | */ | 1030 | */ |
3635 | const char * | 1031 | const char * |
3636 | GCC_2s (const struct CadetConnection *c) | 1032 | GCC_2s (const struct CadetConnection *cc) |
3637 | { | 1033 | { |
3638 | if (NULL == c) | 1034 | static char buf[128]; |
3639 | return "NULL"; | ||
3640 | 1035 | ||
3641 | if (NULL != c->t) | 1036 | if (NULL == cc) |
3642 | { | 1037 | return "Connection(NULL)"; |
3643 | static char buf[128]; | ||
3644 | 1038 | ||
3645 | SPRINTF (buf, "%s (->%s)", | 1039 | if (NULL != cc->ct) |
3646 | GNUNET_sh2s (&GCC_get_id (c)->connection_of_tunnel), | 1040 | { |
3647 | GCT_2s (c->t)); | 1041 | GNUNET_snprintf (buf, |
1042 | sizeof (buf), | ||
1043 | "Connection %s (%s)", | ||
1044 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
1045 | GCT_2s (cc->ct->t)); | ||
3648 | return buf; | 1046 | return buf; |
3649 | } | 1047 | } |
3650 | return GNUNET_sh2s (&c->id.connection_of_tunnel); | 1048 | GNUNET_snprintf (buf, |
1049 | sizeof (buf), | ||
1050 | "Connection %s", | ||
1051 | GNUNET_sh2s (&cc->cid.connection_of_tunnel)); | ||
1052 | return buf; | ||
3651 | } | 1053 | } |
3652 | 1054 | ||
3653 | 1055 | ||
1056 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-con",__VA_ARGS__) | ||
1057 | |||
1058 | |||
3654 | /** | 1059 | /** |
3655 | * Log all possible info about the connection state. | 1060 | * Log connection info. |
3656 | * | 1061 | * |
3657 | * @param c Connection to debug. | 1062 | * @param cc connection |
3658 | * @param level Debug level to use. | 1063 | * @param level Debug level to use. |
3659 | */ | 1064 | */ |
3660 | void | 1065 | void |
3661 | GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level) | 1066 | GCC_debug (struct CadetConnection *cc, |
1067 | enum GNUNET_ErrorType level) | ||
3662 | { | 1068 | { |
3663 | int do_log; | 1069 | int do_log; |
3664 | char *s; | ||
3665 | 1070 | ||
3666 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | 1071 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), |
3667 | "cadet-con", | 1072 | "cadet-con", |
3668 | __FILE__, __FUNCTION__, __LINE__); | 1073 | __FILE__, __FUNCTION__, __LINE__); |
3669 | if (0 == do_log) | 1074 | if (0 == do_log) |
3670 | return; | 1075 | return; |
3671 | 1076 | if (NULL == cc) | |
3672 | if (NULL == c) | ||
3673 | { | 1077 | { |
3674 | LOG2 (level, "CCC DEBUG NULL CONNECTION\n"); | 1078 | LOG2 (level, |
1079 | "Connection (NULL)\n"); | ||
3675 | return; | 1080 | return; |
3676 | } | 1081 | } |
3677 | 1082 | LOG2 (level, | |
3678 | LOG2 (level, "CCC DEBUG CONNECTION %s\n", GCC_2s (c)); | 1083 | "%s to %s via path %s in state %d is %s\n", |
3679 | s = path_2s (c->path); | 1084 | GCC_2s (cc), |
3680 | LOG2 (level, "CCC path %s, own pos: %u\n", s, c->own_pos); | 1085 | GCP_2s (cc->destination), |
3681 | GNUNET_free (s); | 1086 | GCPP_2s (cc->path), |
3682 | LOG2 (level, "CCC state: %s, destroy: %u\n", | 1087 | cc->state, |
3683 | GCC_state2s (c->state), c->destroy); | 1088 | (GNUNET_YES == cc->mqm_ready) ? "ready" : "busy"); |
3684 | LOG2 (level, "CCC pending messages: %u\n", c->pending_messages); | ||
3685 | if (NULL != c->perf) | ||
3686 | LOG2 (level, "CCC us/byte: %f\n", c->perf->avg); | ||
3687 | |||
3688 | LOG2 (level, "CCC FWD flow control:\n"); | ||
3689 | LOG2 (level, "CCC queue: %u/%u\n", c->fwd_fc.queue_n, c->fwd_fc.queue_max); | ||
3690 | LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n", | ||
3691 | ntohl (c->fwd_fc.last_pid_sent.pid), | ||
3692 | ntohl (c->fwd_fc.last_pid_recv.pid)); | ||
3693 | LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n", | ||
3694 | ntohl (c->fwd_fc.last_ack_sent.pid), | ||
3695 | ntohl (c->fwd_fc.last_ack_recv.pid)); | ||
3696 | LOG2 (level, "CCC recv PID bitmap: %X\n", c->fwd_fc.recv_bitmap); | ||
3697 | LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n", | ||
3698 | c->fwd_fc.poll_task, c->fwd_fc.poll_msg, c->fwd_fc.ack_msg); | ||
3699 | |||
3700 | LOG2 (level, "CCC BCK flow control:\n"); | ||
3701 | LOG2 (level, "CCC queue: %u/%u\n", c->bck_fc.queue_n, c->bck_fc.queue_max); | ||
3702 | LOG2 (level, "CCC last PID sent: %5u, recv: %5u\n", | ||
3703 | ntohl (c->bck_fc.last_pid_sent.pid), | ||
3704 | ntohl (c->bck_fc.last_pid_recv.pid)); | ||
3705 | LOG2 (level, "CCC last ACK sent: %5u, recv: %5u\n", | ||
3706 | ntohl (c->bck_fc.last_ack_sent.pid), | ||
3707 | ntohl (c->bck_fc.last_ack_recv.pid)); | ||
3708 | LOG2 (level, "CCC recv PID bitmap: %X\n", c->bck_fc.recv_bitmap); | ||
3709 | LOG2 (level, "CCC poll: task %d, msg %p, msg_ack %p)\n", | ||
3710 | c->bck_fc.poll_task, c->bck_fc.poll_msg, c->bck_fc.ack_msg); | ||
3711 | |||
3712 | LOG2 (level, "CCC DEBUG CONNECTION END\n"); | ||
3713 | } | 1089 | } |
1090 | |||
1091 | /* end of gnunet-service-cadet-new_connection.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet_connection.h b/src/cadet/gnunet-service-cadet_connection.h index 307cb42c2..fdb184366 100644 --- a/src/cadet/gnunet-service-cadet_connection.h +++ b/src/cadet/gnunet-service-cadet_connection.h | |||
@@ -1,6 +1,7 @@ | |||
1 | |||
1 | /* | 2 | /* |
2 | This file is part of GNUnet. | 3 | This file is part of GNUnet. |
3 | Copyright (C) 2013 GNUnet e.V. | 4 | Copyright (C) 2001-2017 GNUnet e.V. |
4 | 5 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 6 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 7 | it under the terms of the GNU General Public License as published |
@@ -20,557 +21,319 @@ | |||
20 | 21 | ||
21 | /** | 22 | /** |
22 | * @file cadet/gnunet-service-cadet_connection.h | 23 | * @file cadet/gnunet-service-cadet_connection.h |
23 | * @brief cadet service; dealing with connections | 24 | * @brief A connection is a live end-to-end messaging mechanism |
25 | * where the peers are identified by a path and know how | ||
26 | * to forward along the route using a connection identifier | ||
27 | * for routing the data. | ||
24 | * @author Bartlomiej Polot | 28 | * @author Bartlomiej Polot |
25 | * | 29 | * @author Christian Grothoff |
26 | * All functions in this file use the prefix GCC (GNUnet Cadet Connection) | ||
27 | */ | 30 | */ |
28 | |||
29 | #ifndef GNUNET_SERVICE_CADET_CONNECTION_H | 31 | #ifndef GNUNET_SERVICE_CADET_CONNECTION_H |
30 | #define GNUNET_SERVICE_CADET_CONNECTION_H | 32 | #define GNUNET_SERVICE_CADET_CONNECTION_H |
31 | 33 | ||
32 | #ifdef __cplusplus | ||
33 | extern "C" | ||
34 | { | ||
35 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
36 | } | ||
37 | #endif | ||
38 | #endif | ||
39 | |||
40 | #include "gnunet_util_lib.h" | 34 | #include "gnunet_util_lib.h" |
41 | 35 | #include "gnunet-service-cadet.h" | |
42 | |||
43 | /** | ||
44 | * All the states a connection can be in. | ||
45 | */ | ||
46 | enum CadetConnectionState | ||
47 | { | ||
48 | /** | ||
49 | * Uninitialized status, should never appear in operation. | ||
50 | */ | ||
51 | CADET_CONNECTION_NEW, | ||
52 | |||
53 | /** | ||
54 | * Connection create message sent, waiting for ACK. | ||
55 | */ | ||
56 | CADET_CONNECTION_SENT, | ||
57 | |||
58 | /** | ||
59 | * Connection ACK sent, waiting for ACK. | ||
60 | */ | ||
61 | CADET_CONNECTION_ACK, | ||
62 | |||
63 | /** | ||
64 | * Connection confirmed, ready to carry traffic. | ||
65 | */ | ||
66 | CADET_CONNECTION_READY, | ||
67 | |||
68 | /** | ||
69 | * Connection to be destroyed, just waiting to empty queues. | ||
70 | */ | ||
71 | CADET_CONNECTION_DESTROYED, | ||
72 | |||
73 | /** | ||
74 | * Connection to be destroyed because of a distant peer, same as DESTROYED. | ||
75 | */ | ||
76 | CADET_CONNECTION_BROKEN, | ||
77 | }; | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Struct containing all information regarding a connection to a peer. | ||
82 | */ | ||
83 | struct CadetConnection; | ||
84 | |||
85 | /** | ||
86 | * Handle for messages queued but not yet sent. | ||
87 | */ | ||
88 | struct CadetConnectionQueue; | ||
89 | |||
90 | #include "cadet_path.h" | ||
91 | #include "gnunet-service-cadet_channel.h" | ||
92 | #include "gnunet-service-cadet_peer.h" | 36 | #include "gnunet-service-cadet_peer.h" |
37 | #include "cadet_protocol.h" | ||
93 | 38 | ||
94 | 39 | ||
95 | /** | 40 | /** |
96 | * Check invariants for all connections using #check_neighbours(). | 41 | * Function called to notify tunnel about change in our readyness. |
97 | */ | ||
98 | void | ||
99 | GCC_check_connections (void); | ||
100 | |||
101 | |||
102 | /** | ||
103 | * Callback called when a queued message is sent. | ||
104 | * | 42 | * |
105 | * @param cls Closure. | 43 | * @param cls closure |
106 | * @param c Connection this message was on. | 44 | * @param is_ready #GNUNET_YES if the connection is now ready for transmission, |
107 | * @param type Type of message sent. | 45 | * #GNUNET_NO if the connection is no longer ready for transmission |
108 | * @param fwd Was this a FWD going message? | ||
109 | * @param size Size of the message. | ||
110 | */ | 46 | */ |
111 | typedef void | 47 | typedef void |
112 | (*GCC_sent) (void *cls, | 48 | (*GCC_ReadyCallback)(void *cls, |
113 | struct CadetConnection *c, | 49 | int is_ready); |
114 | struct CadetConnectionQueue *q, | ||
115 | uint16_t type, | ||
116 | int fwd, | ||
117 | size_t size); | ||
118 | 50 | ||
119 | 51 | ||
120 | /** | 52 | /** |
121 | * Handler for connection creation. | 53 | * Destroy a connection, called when the CORE layer is already done |
54 | * (i.e. has received a BROKEN message), but if we still have to | ||
55 | * communicate the destruction of the connection to the tunnel (if one | ||
56 | * exists). | ||
122 | * | 57 | * |
123 | * @param peer Message sender (neighbor). | 58 | * @param cc connection to destroy |
124 | * @param msg Message itself. | ||
125 | */ | 59 | */ |
126 | void | 60 | void |
127 | GCC_handle_create (struct CadetPeer *peer, | 61 | GCC_destroy_without_core (struct CadetConnection *cc); |
128 | const struct GNUNET_CADET_ConnectionCreateMessage *msg); | ||
129 | 62 | ||
130 | 63 | ||
131 | /** | 64 | /** |
132 | * Handler for connection confirmations. | 65 | * Destroy a connection, called if the tunnel association with the |
66 | * connection was already broken, but we still need to notify the CORE | ||
67 | * layer about the breakage. | ||
133 | * | 68 | * |
134 | * @param peer Message sender (neighbor). | 69 | * @param cc connection to destroy |
135 | * @param msg Message itself. | ||
136 | */ | 70 | */ |
137 | void | 71 | void |
138 | GCC_handle_confirm (struct CadetPeer *peer, | 72 | GCC_destroy_without_tunnel (struct CadetConnection *cc); |
139 | const struct GNUNET_CADET_ConnectionCreateAckMessage *msg); | ||
140 | 73 | ||
141 | 74 | ||
142 | /** | 75 | /** |
143 | * Handler for notifications of broken connections. | 76 | * Lookup a connection by its identifier. |
144 | * | 77 | * |
145 | * @param peer Message sender (neighbor). | 78 | * @param cid identifier to resolve |
146 | * @param msg Message itself. | 79 | * @return NULL if connection was not found |
147 | */ | 80 | */ |
148 | void | 81 | struct CadetConnection * |
149 | GCC_handle_broken (struct CadetPeer *peer, | 82 | GCC_lookup (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); |
150 | const struct GNUNET_CADET_ConnectionBrokenMessage *msg); | ||
151 | 83 | ||
152 | /** | ||
153 | * Handler for notifications of destroyed connections. | ||
154 | * | ||
155 | * @param peer Message sender (neighbor). | ||
156 | * @param msg Message itself. | ||
157 | */ | ||
158 | void | ||
159 | GCC_handle_destroy (struct CadetPeer *peer, | ||
160 | const struct GNUNET_CADET_ConnectionDestroyMessage *msg); | ||
161 | 84 | ||
162 | /** | 85 | /** |
163 | * Handler for cadet network traffic hop-by-hop acks. | 86 | * Create a connection to @a destination via @a path and |
87 | * notify @a cb whenever we are ready for more data. | ||
164 | * | 88 | * |
165 | * @param peer Message sender (neighbor). | 89 | * @param destination where to go |
166 | * @param msg Message itself. | 90 | * @param path which path to take (may not be the full path) |
91 | * @param off offset of @a destination on @a path | ||
92 | * @param options options for the connection | ||
93 | * @param ct which tunnel uses this connection | ||
94 | * @param ready_cb function to call when ready to transmit | ||
95 | * @param ready_cb_cls closure for @a cb | ||
96 | * @return handle to the connection | ||
167 | */ | 97 | */ |
168 | void | 98 | struct CadetConnection * |
169 | GCC_handle_ack (struct CadetPeer *peer, | 99 | GCC_create (struct CadetPeer *destination, |
170 | const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg); | 100 | struct CadetPeerPath *path, |
101 | unsigned int off, | ||
102 | enum GNUNET_CADET_ChannelOption options, | ||
103 | struct CadetTConnection *ct, | ||
104 | GCC_ReadyCallback ready_cb, | ||
105 | void *ready_cb_cls); | ||
171 | 106 | ||
172 | /** | ||
173 | * Handler for cadet network traffic hop-by-hop data counter polls. | ||
174 | * | ||
175 | * @param peer Message sender (neighbor). | ||
176 | * @param msg Message itself. | ||
177 | */ | ||
178 | void | ||
179 | GCC_handle_poll (struct CadetPeer *peer, | ||
180 | const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg); | ||
181 | 107 | ||
182 | /** | 108 | /** |
183 | * Handler for key exchange traffic (Axolotl KX). | 109 | * Create a connection to @a destination via @a path and |
110 | * notify @a cb whenever we are ready for more data. This | ||
111 | * is an inbound tunnel, so we must use the existing @a cid | ||
184 | * | 112 | * |
185 | * @param peer Message sender (neighbor). | 113 | * @param destination where to go |
186 | * @param msg Message itself. | 114 | * @param path which path to take (may not be the full path) |
115 | * @param options options for the connection | ||
116 | * @param ct which tunnel uses this connection | ||
117 | * @param ready_cb function to call when ready to transmit | ||
118 | * @param ready_cb_cls closure for @a cb | ||
119 | * @return handle to the connection, NULL if we already have | ||
120 | * a connection that takes precedence on @a path | ||
187 | */ | 121 | */ |
188 | void | 122 | struct CadetConnection * |
189 | GCC_handle_kx (struct CadetPeer *peer, | 123 | GCC_create_inbound (struct CadetPeer *destination, |
190 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg); | 124 | struct CadetPeerPath *path, |
125 | enum GNUNET_CADET_ChannelOption options, | ||
126 | struct CadetTConnection *ct, | ||
127 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
128 | GCC_ReadyCallback ready_cb, | ||
129 | void *ready_cb_cls); | ||
130 | |||
191 | 131 | ||
192 | /** | 132 | /** |
193 | * Handler for encrypted cadet network traffic (channel mgmt, data). | 133 | * Transmit message @a msg via connection @a cc. Must only be called |
134 | * (once) after the connection has signalled that it is ready via the | ||
135 | * `ready_cb`. Clients can also use #GCC_is_ready() to check if the | ||
136 | * connection is right now ready for transmission. | ||
194 | * | 137 | * |
195 | * @param peer Message sender (neighbor). | 138 | * @param cc connection identification |
196 | * @param msg Message itself. | 139 | * @param env envelope with message to transmit; |
140 | * the #GNUNET_MQ_notify_send() must not have yet been used | ||
141 | * for the envelope. Also, the message better match the | ||
142 | * connection identifier of this connection... | ||
197 | */ | 143 | */ |
198 | void | 144 | void |
199 | GCC_handle_encrypted (struct CadetPeer *peer, | 145 | GCC_transmit (struct CadetConnection *cc, |
200 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg); | 146 | struct GNUNET_MQ_Envelope *env); |
201 | 147 | ||
202 | /** | ||
203 | * Core handler for axolotl key exchange traffic. | ||
204 | * | ||
205 | * @param cls Closure (unused). | ||
206 | * @param message Message received. | ||
207 | * @param peer Neighbor who sent the message. | ||
208 | * | ||
209 | * @return GNUNET_OK, to keep the connection open. | ||
210 | */ | ||
211 | int | ||
212 | GCC_handle_ax_kx (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
213 | const struct GNUNET_MessageHeader *message); | ||
214 | 148 | ||
215 | /** | 149 | /** |
216 | * Core handler for axolotl encrypted cadet network traffic. | 150 | * A CREATE_ACK was received for this connection, process it. |
217 | * | 151 | * |
218 | * @param cls Closure (unused). | 152 | * @param cc the connection that got the ACK. |
219 | * @param message Message received. | ||
220 | * @param peer Neighbor who sent the message. | ||
221 | * | ||
222 | * @return GNUNET_OK, to keep the connection open. | ||
223 | */ | 153 | */ |
224 | int | 154 | void |
225 | GCC_handle_ax (void *cls, const struct GNUNET_PeerIdentity *peer, | 155 | GCC_handle_connection_create_ack (struct CadetConnection *cc); |
226 | struct GNUNET_MessageHeader *message); | ||
227 | 156 | ||
228 | /** | ||
229 | * Core handler for cadet keepalives. | ||
230 | * | ||
231 | * @param cls closure | ||
232 | * @param message message | ||
233 | * @param peer peer identity this notification is about | ||
234 | * @return GNUNET_OK to keep the connection open, | ||
235 | * GNUNET_SYSERR to close it (signal serious error) | ||
236 | * | ||
237 | * TODO: Check who we got this from, to validate route. | ||
238 | */ | ||
239 | int | ||
240 | GCC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
241 | const struct GNUNET_MessageHeader *message); | ||
242 | 157 | ||
243 | /** | 158 | /** |
244 | * Send an ACK on the appropriate connection/channel, depending on | 159 | * We got a #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE for a |
245 | * the direction and the position of the peer. | 160 | * connection that we already have. Either our ACK got lost |
161 | * or something is fishy. Consider retransmitting the ACK. | ||
246 | * | 162 | * |
247 | * @param c Which connection to send the hop-by-hop ACK. | 163 | * @param cc connection that got the duplicate CREATE |
248 | * @param fwd Is this a fwd ACK? (will go dest->root). | ||
249 | * @param force Send the ACK even if suboptimal (e.g. requested by POLL). | ||
250 | */ | 164 | */ |
251 | void | 165 | void |
252 | GCC_send_ack (struct CadetConnection *c, int fwd, int force); | 166 | GCC_handle_duplicate_create (struct CadetConnection *cc); |
253 | 167 | ||
254 | /** | ||
255 | * Initialize the connections subsystem | ||
256 | * | ||
257 | * @param c Configuration handle. | ||
258 | */ | ||
259 | void | ||
260 | GCC_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
261 | 168 | ||
262 | /** | 169 | /** |
263 | * Shut down the connections subsystem. | 170 | * Handle KX message. |
171 | * | ||
172 | * @param cc connection that received encrypted message | ||
173 | * @param msg the key exchange message | ||
264 | */ | 174 | */ |
265 | void | 175 | void |
266 | GCC_shutdown (void); | 176 | GCC_handle_kx (struct CadetConnection *cc, |
177 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg); | ||
267 | 178 | ||
268 | /** | ||
269 | * Create a connection. | ||
270 | * | ||
271 | * @param cid Connection ID (either created locally or imposed remotely). | ||
272 | * @param t Tunnel this connection belongs to (or NULL for transit connections); | ||
273 | * @param path Path this connection has to use (copy is made). | ||
274 | * @param own_pos Own position in the @c path path. | ||
275 | * | ||
276 | * @return Newly created connection. | ||
277 | * NULL in case of error: own id not in path, wrong neighbors, ... | ||
278 | */ | ||
279 | struct CadetConnection * | ||
280 | GCC_new (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
281 | struct CadetTunnel *t, | ||
282 | struct CadetPeerPath *path, | ||
283 | unsigned int own_pos); | ||
284 | 179 | ||
285 | /** | 180 | /** |
286 | * Connection is no longer needed: destroy it. | 181 | * Handle KX_AUTH message. |
287 | * | ||
288 | * Cancels all pending traffic (including possible DESTROY messages), all | ||
289 | * maintenance tasks and removes the connection from neighbor peers and tunnel. | ||
290 | * | 182 | * |
291 | * @param c Connection to destroy. | 183 | * @param cc connection that received encrypted message |
184 | * @param msg the key exchange message | ||
292 | */ | 185 | */ |
293 | void | 186 | void |
294 | GCC_destroy (struct CadetConnection *c); | 187 | GCC_handle_kx_auth (struct CadetConnection *cc, |
295 | 188 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg); | |
296 | /** | ||
297 | * Get the connection ID. | ||
298 | * | ||
299 | * @param c Connection to get the ID from. | ||
300 | * | ||
301 | * @return ID of the connection. | ||
302 | */ | ||
303 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * | ||
304 | GCC_get_id (const struct CadetConnection *c); | ||
305 | 189 | ||
306 | 190 | ||
307 | /** | 191 | /** |
308 | * Get the connection path. | 192 | * Performance metrics for a connection. |
309 | * | ||
310 | * @param c Connection to get the path from. | ||
311 | * | ||
312 | * @return path used by the connection. | ||
313 | */ | 193 | */ |
314 | const struct CadetPeerPath * | 194 | struct CadetConnectionMetrics |
315 | GCC_get_path (const struct CadetConnection *c); | 195 | { |
316 | 196 | ||
317 | /** | 197 | /** |
318 | * Get the connection state. | 198 | * Our current best estimate of the latency, based on a weighted |
319 | * | 199 | * average of at least @a latency_datapoints values. |
320 | * @param c Connection to get the state from. | 200 | */ |
321 | * | 201 | struct GNUNET_TIME_Relative aged_latency; |
322 | * @return state of the connection. | ||
323 | */ | ||
324 | enum CadetConnectionState | ||
325 | GCC_get_state (const struct CadetConnection *c); | ||
326 | 202 | ||
327 | /** | 203 | /** |
328 | * Get the connection tunnel. | 204 | * When was this connection first established? (by us sending or |
329 | * | 205 | * receiving the CREATE_ACK for the first time) |
330 | * @param c Connection to get the tunnel from. | 206 | */ |
331 | * | 207 | struct GNUNET_TIME_Absolute age; |
332 | * @return tunnel of the connection. | ||
333 | */ | ||
334 | struct CadetTunnel * | ||
335 | GCC_get_tunnel (const struct CadetConnection *c); | ||
336 | 208 | ||
337 | /** | 209 | /** |
338 | * Get free buffer space in a connection. | 210 | * When was this connection last used? (by us sending or |
339 | * | 211 | * receiving a PAYLOAD message on it) |
340 | * @param c Connection. | 212 | */ |
341 | * @param fwd Is query about FWD traffic? | 213 | struct GNUNET_TIME_Absolute last_use; |
342 | * | ||
343 | * @return Free buffer space [0 - max_msgs_queue/max_connections] | ||
344 | */ | ||
345 | unsigned int | ||
346 | GCC_get_buffer (struct CadetConnection *c, int fwd); | ||
347 | 214 | ||
348 | /** | 215 | /** |
349 | * Get how many messages have we allowed to send to us from a direction. | 216 | * How many packets that ought to generate an ACK did we send via |
350 | * | 217 | * this connection? |
351 | * @param c Connection. | 218 | */ |
352 | * @param fwd Are we asking about traffic from FWD (BCK messages)? | 219 | unsigned long long num_acked_transmissions; |
353 | * | ||
354 | * @return last_ack_sent - last_pid_recv | ||
355 | */ | ||
356 | unsigned int | ||
357 | GCC_get_allowed (struct CadetConnection *c, int fwd); | ||
358 | 220 | ||
359 | /** | 221 | /** |
360 | * Get messages queued in a connection. | 222 | * Number of packets that were sent via this connection did actually |
361 | * | 223 | * receive an ACK? (Note: ACKs may be transmitted and lost via |
362 | * @param c Connection. | 224 | * other connections, so this value should only be interpreted |
363 | * @param fwd Is query about FWD traffic? | 225 | * relative to @e num_acked_transmissions and in relation to other |
364 | * | 226 | * connections.) |
365 | * @return Number of messages queued. | 227 | */ |
366 | */ | 228 | unsigned long long num_successes; |
367 | unsigned int | ||
368 | GCC_get_qn (struct CadetConnection *c, int fwd); | ||
369 | 229 | ||
370 | /** | 230 | }; |
371 | * Get next PID to use. | ||
372 | * | ||
373 | * @param c Connection. | ||
374 | * @param fwd Is query about FWD traffic? | ||
375 | * @return Next PID to use. | ||
376 | */ | ||
377 | struct CadetEncryptedMessageIdentifier | ||
378 | GCC_get_pid (struct CadetConnection *c, int fwd); | ||
379 | 231 | ||
380 | /** | ||
381 | * Allow the connection to advertise a buffer of the given size. | ||
382 | * | ||
383 | * The connection will send an @c fwd ACK message (so: in direction !fwd) | ||
384 | * allowing up to last_pid_recv + buffer. | ||
385 | * | ||
386 | * @param c Connection. | ||
387 | * @param buffer How many more messages the connection can accept. | ||
388 | * @param fwd Is this about FWD traffic? (The ack will go dest->root). | ||
389 | */ | ||
390 | void | ||
391 | GCC_allow (struct CadetConnection *c, unsigned int buffer, int fwd); | ||
392 | 232 | ||
393 | /** | 233 | /** |
394 | * Send FWD keepalive packets for a connection. | 234 | * Obtain performance @a metrics from @a cc. |
395 | * | 235 | * |
396 | * @param cls Closure (connection for which to send the keepalive). | 236 | * @param cc connection to query |
397 | * @param tc Notification context. | 237 | * @return the metrics |
398 | */ | 238 | */ |
399 | void | 239 | const struct CadetConnectionMetrics * |
400 | GCC_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | 240 | GCC_get_metrics (struct CadetConnection *cc); |
241 | |||
401 | 242 | ||
402 | /** | 243 | /** |
403 | * Send BCK keepalive packets for a connection. | 244 | * Handle encrypted message. |
404 | * | 245 | * |
405 | * @param cls Closure (connection for which to send the keepalive). | 246 | * @param cc connection that received encrypted message |
406 | * @param tc Notification context. | 247 | * @param msg the encrypted message to decrypt |
407 | */ | 248 | */ |
408 | void | 249 | void |
409 | GCC_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | 250 | GCC_handle_encrypted (struct CadetConnection *cc, |
251 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg); | ||
410 | 252 | ||
411 | 253 | ||
412 | /** | 254 | /** |
413 | * Notify other peers on a connection of a broken link. Mark connections | 255 | * We sent a message for which we expect to receive an ACK via |
414 | * to destroy after all traffic has been sent. | 256 | * the connection identified by @a cti. |
415 | * | 257 | * |
416 | * @param c Connection on which there has been a disconnection. | 258 | * @param cid connection identifier where we expect an ACK |
417 | * @param peer Peer that disconnected. | ||
418 | */ | 259 | */ |
419 | void | 260 | void |
420 | GCC_neighbor_disconnected (struct CadetConnection *c, struct CadetPeer *peer); | 261 | GCC_ack_expected (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); |
421 | 262 | ||
422 | /** | ||
423 | * Is this peer the first one on the connection? | ||
424 | * | ||
425 | * @param c Connection. | ||
426 | * @param fwd Is this about fwd traffic? | ||
427 | * | ||
428 | * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal. | ||
429 | */ | ||
430 | int | ||
431 | GCC_is_origin (struct CadetConnection *c, int fwd); | ||
432 | 263 | ||
433 | /** | 264 | /** |
434 | * Is this peer the last one on the connection? | 265 | * We observed an ACK for a message that was originally sent via |
435 | * | 266 | * the connection identified by @a cti. |
436 | * @param c Connection. | ||
437 | * @param fwd Is this about fwd traffic? | ||
438 | * Note that the ROOT is the terminal for BCK traffic! | ||
439 | * | 267 | * |
440 | * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin. | 268 | * @param cid connection identifier where we got an ACK for a message |
269 | * that was originally sent via this connection (the ACK | ||
270 | * may have gotten back to us via a different connection). | ||
441 | */ | 271 | */ |
442 | int | 272 | void |
443 | GCC_is_terminal (struct CadetConnection *c, int fwd); | 273 | GCC_ack_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); |
444 | |||
445 | /** | ||
446 | * See if we are allowed to send by the next hop in the given direction. | ||
447 | * | ||
448 | * @param c Connection. | ||
449 | * @param fwd Is this about fwd traffic? | ||
450 | * | ||
451 | * @return #GNUNET_YES in case it's OK to send. | ||
452 | */ | ||
453 | int | ||
454 | GCC_is_sendable (struct CadetConnection *c, int fwd); | ||
455 | 274 | ||
456 | /** | ||
457 | * Check if this connection is a direct one (never trim a direct connection). | ||
458 | * | ||
459 | * @param c Connection. | ||
460 | * | ||
461 | * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise. | ||
462 | */ | ||
463 | int | ||
464 | GCC_is_direct (struct CadetConnection *c); | ||
465 | 275 | ||
466 | /** | 276 | /** |
467 | * Cancel a previously sent message while it's in the queue. | 277 | * We observed some the given @a latency on the connection |
278 | * identified by @a cti. (The same connection was taken | ||
279 | * in both directions.) | ||
468 | * | 280 | * |
469 | * ONLY can be called before the continuation given to the send function | 281 | * @param cti connection identifier where we measured latency |
470 | * is called. Once the continuation is called, the message is no longer in the | 282 | * @param latency the observed latency |
471 | * queue. | ||
472 | * | ||
473 | * @param q Handle to the queue. | ||
474 | */ | 283 | */ |
475 | void | 284 | void |
476 | GCC_cancel (struct CadetConnectionQueue *q); | 285 | GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti, |
286 | struct GNUNET_TIME_Relative latency); | ||
477 | 287 | ||
478 | /** | ||
479 | * Sends an already built message on a connection, properly registering | ||
480 | * all used resources. | ||
481 | * | ||
482 | * @param message Message to send. | ||
483 | * @param payload_type Type of payload, in case the message is encrypted. | ||
484 | * 0 for restransmissions (when type is no longer known) | ||
485 | * UINT16_MAX when not applicable. | ||
486 | * @param payload_id ID of the payload (PID, ACK, ...). | ||
487 | * @param c Connection on which this message is transmitted. | ||
488 | * @param fwd Is this a fwd message? | ||
489 | * @param force Force the connection to accept the message (buffer overfill). | ||
490 | * @param cont Continuation called once message is sent. Can be NULL. | ||
491 | * @param cont_cls Closure for @c cont. | ||
492 | * | ||
493 | * @return Handle to cancel the message before it's sent. | ||
494 | * NULL on error. | ||
495 | * Invalid on @c cont call. | ||
496 | */ | ||
497 | struct CadetConnectionQueue * | ||
498 | GCC_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
499 | uint16_t payload_type, | ||
500 | struct CadetEncryptedMessageIdentifier payload_id, | ||
501 | struct CadetConnection *c, int fwd, int force, | ||
502 | GCC_sent cont, void *cont_cls); | ||
503 | 288 | ||
504 | /** | 289 | /** |
505 | * Sends a CREATE CONNECTION message for a path to a peer. | 290 | * Return the tunnel associated with this connection. |
506 | * Changes the connection and tunnel states if necessary. | ||
507 | * | 291 | * |
508 | * @param connection Connection to create. | 292 | * @param cc connection to query |
293 | * @return corresponding entry in the tunnel's connection list | ||
509 | */ | 294 | */ |
510 | void | 295 | struct CadetTConnection * |
511 | GCC_send_create (struct CadetConnection *connection); | 296 | GCC_get_ct (struct CadetConnection *cc); |
512 | 297 | ||
513 | /** | ||
514 | * Send a message to all peers in this connection that the connection | ||
515 | * is no longer valid. | ||
516 | * | ||
517 | * If some peer should not receive the message, it should be zero'ed out | ||
518 | * before calling this function. | ||
519 | * | ||
520 | * @param c The connection whose peers to notify. | ||
521 | */ | ||
522 | void | ||
523 | GCC_send_destroy (struct CadetConnection *c); | ||
524 | 298 | ||
525 | /** | 299 | /** |
526 | * @brief Start a polling timer for the connection. | 300 | * Obtain the path used by this connection. |
527 | * | 301 | * |
528 | * When a neighbor does not accept more traffic on the connection it could be | 302 | * @param cc connection |
529 | * caused by a simple congestion or by a lost ACK. Polling enables to check | 303 | * @return path to @a cc |
530 | * for the lastest ACK status for a connection. | ||
531 | * | ||
532 | * @param c Connection. | ||
533 | * @param fwd Should we poll in the FWD direction? | ||
534 | */ | 304 | */ |
535 | void | 305 | struct CadetPeerPath * |
536 | GCC_start_poll (struct CadetConnection *c, int fwd); | 306 | GCC_get_path (struct CadetConnection *cc); |
537 | 307 | ||
538 | 308 | ||
539 | /** | 309 | /** |
540 | * @brief Stop polling a connection for ACKs. | 310 | * Obtain unique ID for the connection. |
541 | * | ||
542 | * Once we have enough ACKs for future traffic, polls are no longer necessary. | ||
543 | * | 311 | * |
544 | * @param c Connection. | 312 | * @param cc connection. |
545 | * @param fwd Should we stop the poll in the FWD direction? | 313 | * @return unique number of the connection |
546 | */ | 314 | */ |
547 | void | 315 | const struct GNUNET_CADET_ConnectionTunnelIdentifier * |
548 | GCC_stop_poll (struct CadetConnection *c, int fwd); | 316 | GCC_get_id (struct CadetConnection *cc); |
317 | |||
549 | 318 | ||
550 | /** | 319 | /** |
551 | * Get a (static) string for a connection. | 320 | * Get a (static) string for a connection. |
552 | * | 321 | * |
553 | * @param c Connection. | 322 | * @param cc Connection. |
554 | */ | 323 | */ |
555 | const char * | 324 | const char * |
556 | GCC_2s (const struct CadetConnection *c); | 325 | GCC_2s (const struct CadetConnection *cc); |
326 | |||
557 | 327 | ||
558 | /** | 328 | /** |
559 | * Log all possible info about the connection state. | 329 | * Log connection info. |
560 | * | 330 | * |
561 | * @param c Connection to debug. | 331 | * @param cc connection |
562 | * @param level Debug level to use. | 332 | * @param level Debug level to use. |
563 | */ | 333 | */ |
564 | void | 334 | void |
565 | GCC_debug (const struct CadetConnection *c, enum GNUNET_ErrorType level); | 335 | GCC_debug (struct CadetConnection *cc, |
336 | enum GNUNET_ErrorType level); | ||
566 | 337 | ||
567 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
568 | { | ||
569 | #endif | ||
570 | #ifdef __cplusplus | ||
571 | } | ||
572 | #endif | ||
573 | 338 | ||
574 | /* ifndef GNUNET_SERVICE_CADET_CONNECTION_H */ | ||
575 | #endif | 339 | #endif |
576 | /* end of gnunet-service-cadet_connection.h */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new_core.c b/src/cadet/gnunet-service-cadet_core.c index 4a4ead05b..ae03b4f35 100644 --- a/src/cadet/gnunet-service-cadet-new_core.c +++ b/src/cadet/gnunet-service-cadet_core.c | |||
@@ -30,22 +30,64 @@ | |||
30 | * - Optimization: given BROKEN messages, destroy paths (?) | 30 | * - Optimization: given BROKEN messages, destroy paths (?) |
31 | */ | 31 | */ |
32 | #include "platform.h" | 32 | #include "platform.h" |
33 | #include "gnunet-service-cadet-new_core.h" | 33 | #include "gnunet-service-cadet_core.h" |
34 | #include "gnunet-service-cadet-new_paths.h" | 34 | #include "gnunet-service-cadet_paths.h" |
35 | #include "gnunet-service-cadet-new_peer.h" | 35 | #include "gnunet-service-cadet_peer.h" |
36 | #include "gnunet-service-cadet-new_connection.h" | 36 | #include "gnunet-service-cadet_connection.h" |
37 | #include "gnunet-service-cadet-new_tunnels.h" | 37 | #include "gnunet-service-cadet_tunnels.h" |
38 | #include "gnunet_core_service.h" | 38 | #include "gnunet_core_service.h" |
39 | #include "gnunet_statistics_service.h" | ||
39 | #include "cadet_protocol.h" | 40 | #include "cadet_protocol.h" |
40 | 41 | ||
41 | 42 | ||
42 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-cor",__VA_ARGS__) | 43 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-cor",__VA_ARGS__) |
43 | 44 | ||
45 | /** | ||
46 | * Information we keep per direction for a route. | ||
47 | */ | ||
48 | struct RouteDirection; | ||
49 | |||
44 | 50 | ||
45 | /** | 51 | /** |
46 | * Number of messages we are willing to buffer per route. | 52 | * Set of CadetRoutes that have exactly the same number of messages |
53 | * in their buffer. Used so we can efficiently find all of those | ||
54 | * routes that have the current maximum of messages in the buffer (in | ||
55 | * case we have to purge). | ||
47 | */ | 56 | */ |
48 | #define ROUTE_BUFFER_SIZE 8 | 57 | struct Rung |
58 | { | ||
59 | |||
60 | /** | ||
61 | * Rung of RouteDirections with one more buffer entry each. | ||
62 | */ | ||
63 | struct Rung *next; | ||
64 | |||
65 | /** | ||
66 | * Rung of RouteDirections with one less buffer entry each. | ||
67 | */ | ||
68 | struct Rung *prev; | ||
69 | |||
70 | /** | ||
71 | * DLL of route directions with a number of buffer entries matching this rung. | ||
72 | */ | ||
73 | struct RouteDirection *rd_head; | ||
74 | |||
75 | /** | ||
76 | * DLL of route directions with a number of buffer entries matching this rung. | ||
77 | */ | ||
78 | struct RouteDirection *rd_tail; | ||
79 | |||
80 | /** | ||
81 | * Total number of route directions in this rung. | ||
82 | */ | ||
83 | unsigned int num_routes; | ||
84 | |||
85 | /** | ||
86 | * Number of messages route directions at this rung have | ||
87 | * in their buffer. | ||
88 | */ | ||
89 | unsigned int rung_off; | ||
90 | }; | ||
49 | 91 | ||
50 | 92 | ||
51 | /** | 93 | /** |
@@ -53,35 +95,46 @@ | |||
53 | */ | 95 | */ |
54 | struct RouteDirection | 96 | struct RouteDirection |
55 | { | 97 | { |
98 | |||
56 | /** | 99 | /** |
57 | * Target peer. | 100 | * DLL of other route directions within the same `struct Rung`. |
58 | */ | 101 | */ |
59 | struct CadetPeer *hop; | 102 | struct RouteDirection *prev; |
60 | 103 | ||
61 | /** | 104 | /** |
62 | * Route this direction is part of. | 105 | * DLL of other route directions within the same `struct Rung`. |
63 | */ | 106 | */ |
64 | struct CadetRoute *my_route; | 107 | struct RouteDirection *next; |
65 | 108 | ||
66 | /** | 109 | /** |
67 | * Message queue manager for @e hop. | 110 | * Rung of this route direction (matches length of the buffer DLL). |
68 | */ | 111 | */ |
69 | struct GCP_MessageQueueManager *mqm; | 112 | struct Rung *rung; |
113 | |||
114 | /** | ||
115 | * Head of DLL of envelopes we have in the buffer for this direction. | ||
116 | */ | ||
117 | struct GNUNET_MQ_Envelope *env_head; | ||
70 | 118 | ||
71 | /** | 119 | /** |
72 | * Cyclic message buffer to @e hop. | 120 | * Tail of DLL of envelopes we have in the buffer for this direction. |
73 | */ | 121 | */ |
74 | struct GNUNET_MQ_Envelope *out_buffer[ROUTE_BUFFER_SIZE]; | 122 | struct GNUNET_MQ_Envelope *env_tail; |
75 | 123 | ||
76 | /** | 124 | /** |
77 | * Next write offset to use to append messages to @e out_buffer. | 125 | * Target peer. |
126 | */ | ||
127 | struct CadetPeer *hop; | ||
128 | |||
129 | /** | ||
130 | * Route this direction is part of. | ||
78 | */ | 131 | */ |
79 | unsigned int out_wpos; | 132 | struct CadetRoute *my_route; |
80 | 133 | ||
81 | /** | 134 | /** |
82 | * Next read offset to use to retrieve messages from @e out_buffer. | 135 | * Message queue manager for @e hop. |
83 | */ | 136 | */ |
84 | unsigned int out_rpos; | 137 | struct GCP_MessageQueueManager *mqm; |
85 | 138 | ||
86 | /** | 139 | /** |
87 | * Is @e mqm currently ready for transmission? | 140 | * Is @e mqm currently ready for transmission? |
@@ -122,6 +175,15 @@ struct CadetRoute | |||
122 | */ | 175 | */ |
123 | struct GNUNET_TIME_Absolute last_use; | 176 | struct GNUNET_TIME_Absolute last_use; |
124 | 177 | ||
178 | /** | ||
179 | * Position of this route in the #route_heap. | ||
180 | */ | ||
181 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
182 | |||
183 | /** | ||
184 | * Options for the route, control buffering. | ||
185 | */ | ||
186 | enum GNUNET_CADET_ChannelOption options; | ||
125 | }; | 187 | }; |
126 | 188 | ||
127 | 189 | ||
@@ -135,6 +197,47 @@ static struct GNUNET_CORE_Handle *core; | |||
135 | */ | 197 | */ |
136 | static struct GNUNET_CONTAINER_MultiShortmap *routes; | 198 | static struct GNUNET_CONTAINER_MultiShortmap *routes; |
137 | 199 | ||
200 | /** | ||
201 | * Heap of routes, MIN-sorted by last activity. | ||
202 | */ | ||
203 | static struct GNUNET_CONTAINER_Heap *route_heap; | ||
204 | |||
205 | /** | ||
206 | * Rung zero (always pointed to by #rung_head). | ||
207 | */ | ||
208 | static struct Rung rung_zero; | ||
209 | |||
210 | /** | ||
211 | * DLL of rungs, with the head always point to a rung of | ||
212 | * route directions with no messages in the queue. | ||
213 | */ | ||
214 | static struct Rung *rung_head = &rung_zero; | ||
215 | |||
216 | /** | ||
217 | * Tail of the #rung_head DLL. | ||
218 | */ | ||
219 | static struct Rung *rung_tail = &rung_zero; | ||
220 | |||
221 | /** | ||
222 | * Maximum number of concurrent routes this peer will support. | ||
223 | */ | ||
224 | static unsigned long long max_routes; | ||
225 | |||
226 | /** | ||
227 | * Maximum number of envelopes we will buffer at this peer. | ||
228 | */ | ||
229 | static unsigned long long max_buffers; | ||
230 | |||
231 | /** | ||
232 | * Current number of envelopes we have buffered at this peer. | ||
233 | */ | ||
234 | static unsigned long long cur_buffers; | ||
235 | |||
236 | /** | ||
237 | * Task to timeout routes. | ||
238 | */ | ||
239 | static struct GNUNET_SCHEDULER_Task *timeout_task; | ||
240 | |||
138 | 241 | ||
139 | /** | 242 | /** |
140 | * Get the route corresponding to a hash. | 243 | * Get the route corresponding to a hash. |
@@ -150,6 +253,91 @@ get_route (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid) | |||
150 | 253 | ||
151 | 254 | ||
152 | /** | 255 | /** |
256 | * Lower the rung in which @a dir is by 1. | ||
257 | * | ||
258 | * @param dir direction to lower in rung. | ||
259 | */ | ||
260 | static void | ||
261 | lower_rung (struct RouteDirection *dir) | ||
262 | { | ||
263 | struct Rung *rung = dir->rung; | ||
264 | struct Rung *prev; | ||
265 | |||
266 | GNUNET_CONTAINER_DLL_remove (rung->rd_head, | ||
267 | rung->rd_tail, | ||
268 | dir); | ||
269 | prev = rung->prev; | ||
270 | GNUNET_assert (NULL != prev); | ||
271 | if (prev->rung_off != rung->rung_off - 1) | ||
272 | { | ||
273 | prev = GNUNET_new (struct Rung); | ||
274 | prev->rung_off = rung->rung_off - 1; | ||
275 | GNUNET_CONTAINER_DLL_insert_after (rung_head, | ||
276 | rung_tail, | ||
277 | rung->prev, | ||
278 | prev); | ||
279 | } | ||
280 | GNUNET_assert (NULL != prev); | ||
281 | GNUNET_CONTAINER_DLL_insert (prev->rd_head, | ||
282 | prev->rd_tail, | ||
283 | dir); | ||
284 | dir->rung = prev; | ||
285 | } | ||
286 | |||
287 | |||
288 | /** | ||
289 | * Discard the buffer @a env from the route direction @a dir and | ||
290 | * move @a dir down a rung. | ||
291 | * | ||
292 | * @param dir direction that contains the @a env in the buffer | ||
293 | * @param env envelope to discard | ||
294 | */ | ||
295 | static void | ||
296 | discard_buffer (struct RouteDirection *dir, | ||
297 | struct GNUNET_MQ_Envelope *env) | ||
298 | { | ||
299 | GNUNET_MQ_dll_remove (&dir->env_head, | ||
300 | &dir->env_tail, | ||
301 | env); | ||
302 | cur_buffers--; | ||
303 | GNUNET_MQ_discard (env); | ||
304 | lower_rung (dir); | ||
305 | GNUNET_STATISTICS_set (stats, | ||
306 | "# buffer use", | ||
307 | cur_buffers, | ||
308 | GNUNET_NO); | ||
309 | } | ||
310 | |||
311 | |||
312 | /** | ||
313 | * Discard all messages from the highest rung, to make space. | ||
314 | */ | ||
315 | static void | ||
316 | discard_all_from_rung_tail () | ||
317 | { | ||
318 | struct Rung *tail = rung_tail; | ||
319 | struct RouteDirection *dir; | ||
320 | |||
321 | while (NULL != (dir = tail->rd_head)) | ||
322 | { | ||
323 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
324 | "Queue full due new message %s on connection %s, dropping old message\n", | ||
325 | GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel)); | ||
326 | GNUNET_STATISTICS_update (stats, | ||
327 | "# messages dropped due to full buffer", | ||
328 | 1, | ||
329 | GNUNET_NO); | ||
330 | discard_buffer (dir, | ||
331 | dir->env_head); | ||
332 | } | ||
333 | GNUNET_CONTAINER_DLL_remove (rung_head, | ||
334 | rung_tail, | ||
335 | tail); | ||
336 | GNUNET_free (tail); | ||
337 | } | ||
338 | |||
339 | |||
340 | /** | ||
153 | * We message @a msg from @a prev. Find its route by @a cid and | 341 | * We message @a msg from @a prev. Find its route by @a cid and |
154 | * forward to the next hop. Drop and signal broken route if we do not | 342 | * forward to the next hop. Drop and signal broken route if we do not |
155 | * have a route. | 343 | * have a route. |
@@ -165,6 +353,8 @@ route_message (struct CadetPeer *prev, | |||
165 | { | 353 | { |
166 | struct CadetRoute *route; | 354 | struct CadetRoute *route; |
167 | struct RouteDirection *dir; | 355 | struct RouteDirection *dir; |
356 | struct Rung *rung; | ||
357 | struct Rung *nxt; | ||
168 | struct GNUNET_MQ_Envelope *env; | 358 | struct GNUNET_MQ_Envelope *env; |
169 | 359 | ||
170 | route = get_route (cid); | 360 | route = get_route (cid); |
@@ -178,6 +368,13 @@ route_message (struct CadetPeer *prev, | |||
178 | ntohs (msg->type), | 368 | ntohs (msg->type), |
179 | GCP_2s (prev), | 369 | GCP_2s (prev), |
180 | GNUNET_sh2s (&cid->connection_of_tunnel)); | 370 | GNUNET_sh2s (&cid->connection_of_tunnel)); |
371 | switch (ntohs (msg->type)) | ||
372 | { | ||
373 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
374 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
375 | /* No need to respond to these! */ | ||
376 | return; | ||
377 | } | ||
181 | env = GNUNET_MQ_msg (bm, | 378 | env = GNUNET_MQ_msg (bm, |
182 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | 379 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); |
183 | bm->cid = *cid; | 380 | bm->cid = *cid; |
@@ -186,6 +383,9 @@ route_message (struct CadetPeer *prev, | |||
186 | env); | 383 | env); |
187 | return; | 384 | return; |
188 | } | 385 | } |
386 | route->last_use = GNUNET_TIME_absolute_get (); | ||
387 | GNUNET_CONTAINER_heap_update_cost (route->hn, | ||
388 | route->last_use.abs_value_us); | ||
189 | dir = (prev == route->prev.hop) ? &route->next : &route->prev; | 389 | dir = (prev == route->prev.hop) ? &route->next : &route->prev; |
190 | if (GNUNET_YES == dir->is_ready) | 390 | if (GNUNET_YES == dir->is_ready) |
191 | { | 391 | { |
@@ -200,22 +400,59 @@ route_message (struct CadetPeer *prev, | |||
200 | GNUNET_MQ_msg_copy (msg)); | 400 | GNUNET_MQ_msg_copy (msg)); |
201 | return; | 401 | return; |
202 | } | 402 | } |
203 | env = dir->out_buffer[dir->out_wpos]; | 403 | /* Check if buffering is disallowed, and if so, make sure we only queue |
204 | if (NULL != env) | 404 | one message per direction. */ |
405 | if ( (0 != (route->options & GNUNET_CADET_OPTION_NOBUFFER)) && | ||
406 | (NULL != dir->env_head) ) | ||
407 | discard_buffer (dir, | ||
408 | dir->env_head); | ||
409 | rung = dir->rung; | ||
410 | if (cur_buffers == max_buffers) | ||
205 | { | 411 | { |
206 | /* Queue full, drop earliest message in queue */ | 412 | /* Need to make room. */ |
207 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 413 | if (NULL != rung->next) |
208 | "Queue full due to new message of type %u from %s to %s on connection %s, dropping old message\n", | 414 | { |
209 | ntohs (msg->type), | 415 | /* Easy case, drop messages from route directions in highest rung */ |
210 | GCP_2s (prev), | 416 | discard_all_from_rung_tail (); |
211 | GNUNET_i2s (GCP_get_id (dir->hop)), | 417 | } |
212 | GNUNET_sh2s (&cid->connection_of_tunnel)); | 418 | else |
213 | GNUNET_assert (dir->out_rpos == dir->out_wpos); | 419 | { |
214 | GNUNET_MQ_discard (env); | 420 | /* We are in the highest rung, drop our own! */ |
215 | dir->out_rpos++; | 421 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
216 | if (ROUTE_BUFFER_SIZE == dir->out_rpos) | 422 | "Queue full due new message %s on connection %s, dropping old message\n", |
217 | dir->out_rpos = 0; | 423 | GNUNET_sh2s (&dir->my_route->cid.connection_of_tunnel)); |
424 | GNUNET_STATISTICS_update (stats, | ||
425 | "# messages dropped due to full buffer", | ||
426 | 1, | ||
427 | GNUNET_NO); | ||
428 | discard_buffer (dir, | ||
429 | dir->env_head); | ||
430 | rung = dir->rung; | ||
431 | } | ||
432 | } | ||
433 | /* remove 'dir' from current rung */ | ||
434 | GNUNET_CONTAINER_DLL_remove (rung->rd_head, | ||
435 | rung->rd_tail, | ||
436 | dir); | ||
437 | /* make 'nxt' point to the next higher rung, creat if necessary */ | ||
438 | nxt = rung->next; | ||
439 | if ( (NULL == nxt) || | ||
440 | (rung->rung_off + 1 != nxt->rung_off) ) | ||
441 | { | ||
442 | nxt = GNUNET_new (struct Rung); | ||
443 | nxt->rung_off = rung->rung_off + 1; | ||
444 | GNUNET_CONTAINER_DLL_insert_after (rung_head, | ||
445 | rung_tail, | ||
446 | rung, | ||
447 | nxt); | ||
218 | } | 448 | } |
449 | /* insert 'dir' into next higher rung */ | ||
450 | GNUNET_CONTAINER_DLL_insert (nxt->rd_head, | ||
451 | nxt->rd_tail, | ||
452 | dir); | ||
453 | dir->rung = nxt; | ||
454 | |||
455 | /* add message into 'dir' buffer */ | ||
219 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 456 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
220 | "Queueing new message of type %u from %s to %s on connection %s\n", | 457 | "Queueing new message of type %u from %s to %s on connection %s\n", |
221 | ntohs (msg->type), | 458 | ntohs (msg->type), |
@@ -223,10 +460,23 @@ route_message (struct CadetPeer *prev, | |||
223 | GNUNET_i2s (GCP_get_id (dir->hop)), | 460 | GNUNET_i2s (GCP_get_id (dir->hop)), |
224 | GNUNET_sh2s (&cid->connection_of_tunnel)); | 461 | GNUNET_sh2s (&cid->connection_of_tunnel)); |
225 | env = GNUNET_MQ_msg_copy (msg); | 462 | env = GNUNET_MQ_msg_copy (msg); |
226 | dir->out_buffer[dir->out_wpos] = env; | 463 | GNUNET_MQ_dll_insert_tail (&dir->env_head, |
227 | dir->out_wpos++; | 464 | &dir->env_tail, |
228 | if (ROUTE_BUFFER_SIZE == dir->out_wpos) | 465 | env); |
229 | dir->out_wpos = 0; | 466 | cur_buffers++; |
467 | GNUNET_STATISTICS_set (stats, | ||
468 | "# buffer use", | ||
469 | cur_buffers, | ||
470 | GNUNET_NO); | ||
471 | /* Clean up 'rung' if now empty (and not head) */ | ||
472 | if ( (NULL == rung->rd_head) && | ||
473 | (rung != rung_head) ) | ||
474 | { | ||
475 | GNUNET_CONTAINER_DLL_remove (rung_head, | ||
476 | rung_tail, | ||
477 | rung); | ||
478 | GNUNET_free (rung); | ||
479 | } | ||
230 | } | 480 | } |
231 | 481 | ||
232 | 482 | ||
@@ -261,18 +511,26 @@ check_connection_create (void *cls, | |||
261 | static void | 511 | static void |
262 | destroy_direction (struct RouteDirection *dir) | 512 | destroy_direction (struct RouteDirection *dir) |
263 | { | 513 | { |
264 | for (unsigned int i=0;i<ROUTE_BUFFER_SIZE;i++) | 514 | struct GNUNET_MQ_Envelope *env; |
265 | if (NULL != dir->out_buffer[i]) | 515 | |
266 | { | 516 | while (NULL != (env = dir->env_head)) |
267 | GNUNET_MQ_discard (dir->out_buffer[i]); | 517 | { |
268 | dir->out_buffer[i] = NULL; | 518 | GNUNET_STATISTICS_update (stats, |
269 | } | 519 | "# messages dropped due to route destruction", |
520 | 1, | ||
521 | GNUNET_NO); | ||
522 | discard_buffer (dir, | ||
523 | env); | ||
524 | } | ||
270 | if (NULL != dir->mqm) | 525 | if (NULL != dir->mqm) |
271 | { | 526 | { |
272 | GCP_request_mq_cancel (dir->mqm, | 527 | GCP_request_mq_cancel (dir->mqm, |
273 | NULL); | 528 | NULL); |
274 | dir->mqm = NULL; | 529 | dir->mqm = NULL; |
275 | } | 530 | } |
531 | GNUNET_CONTAINER_DLL_remove (rung_head->rd_head, | ||
532 | rung_head->rd_tail, | ||
533 | dir); | ||
276 | } | 534 | } |
277 | 535 | ||
278 | 536 | ||
@@ -289,6 +547,16 @@ destroy_route (struct CadetRoute *route) | |||
289 | GNUNET_i2s (GCP_get_id (route->prev.hop)), | 547 | GNUNET_i2s (GCP_get_id (route->prev.hop)), |
290 | GNUNET_i2s2 (GCP_get_id (route->next.hop)), | 548 | GNUNET_i2s2 (GCP_get_id (route->next.hop)), |
291 | GNUNET_sh2s (&route->cid.connection_of_tunnel)); | 549 | GNUNET_sh2s (&route->cid.connection_of_tunnel)); |
550 | GNUNET_assert (route == | ||
551 | GNUNET_CONTAINER_heap_remove_node (route->hn)); | ||
552 | GNUNET_assert (GNUNET_YES == | ||
553 | GNUNET_CONTAINER_multishortmap_remove (routes, | ||
554 | &route->cid.connection_of_tunnel, | ||
555 | route)); | ||
556 | GNUNET_STATISTICS_set (stats, | ||
557 | "# routes", | ||
558 | GNUNET_CONTAINER_multishortmap_size (routes), | ||
559 | GNUNET_NO); | ||
292 | destroy_direction (&route->prev); | 560 | destroy_direction (&route->prev); |
293 | destroy_direction (&route->next); | 561 | destroy_direction (&route->next); |
294 | GNUNET_free (route); | 562 | GNUNET_free (route); |
@@ -328,7 +596,6 @@ send_broken (struct RouteDirection *target, | |||
328 | bm->peer1 = *peer1; | 596 | bm->peer1 = *peer1; |
329 | if (NULL != peer2) | 597 | if (NULL != peer2) |
330 | bm->peer2 = *peer2; | 598 | bm->peer2 = *peer2; |
331 | |||
332 | GCP_request_mq_cancel (target->mqm, | 599 | GCP_request_mq_cancel (target->mqm, |
333 | env); | 600 | env); |
334 | target->mqm = NULL; | 601 | target->mqm = NULL; |
@@ -336,6 +603,49 @@ send_broken (struct RouteDirection *target, | |||
336 | 603 | ||
337 | 604 | ||
338 | /** | 605 | /** |
606 | * Function called to check if any routes have timed out, and if | ||
607 | * so, to clean them up. Finally, schedules itself again at the | ||
608 | * earliest time where there might be more work. | ||
609 | * | ||
610 | * @param cls NULL | ||
611 | */ | ||
612 | static void | ||
613 | timeout_cb (void *cls) | ||
614 | { | ||
615 | struct CadetRoute *r; | ||
616 | struct GNUNET_TIME_Relative linger; | ||
617 | struct GNUNET_TIME_Absolute exp; | ||
618 | |||
619 | timeout_task = NULL; | ||
620 | linger = GNUNET_TIME_relative_multiply (keepalive_period, | ||
621 | 3); | ||
622 | while (NULL != (r = GNUNET_CONTAINER_heap_peek (route_heap))) | ||
623 | { | ||
624 | exp = GNUNET_TIME_absolute_add (r->last_use, | ||
625 | linger); | ||
626 | if (0 != GNUNET_TIME_absolute_get_duration (exp).rel_value_us) | ||
627 | { | ||
628 | /* Route not yet timed out, wait until it does. */ | ||
629 | timeout_task = GNUNET_SCHEDULER_add_at (exp, | ||
630 | &timeout_cb, | ||
631 | NULL); | ||
632 | return; | ||
633 | } | ||
634 | send_broken (&r->prev, | ||
635 | &r->cid, | ||
636 | NULL, | ||
637 | NULL); | ||
638 | send_broken (&r->next, | ||
639 | &r->cid, | ||
640 | NULL, | ||
641 | NULL); | ||
642 | destroy_route (r); | ||
643 | } | ||
644 | /* No more routes left, so no need for a #timeout_task */ | ||
645 | } | ||
646 | |||
647 | |||
648 | /** | ||
339 | * Function called when the message queue to the previous hop | 649 | * Function called when the message queue to the previous hop |
340 | * becomes available/unavailable. We expect this function to | 650 | * becomes available/unavailable. We expect this function to |
341 | * be called immediately when we register, and then again | 651 | * be called immediately when we register, and then again |
@@ -360,12 +670,17 @@ dir_ready_cb (void *cls, | |||
360 | struct GNUNET_MQ_Envelope *env; | 670 | struct GNUNET_MQ_Envelope *env; |
361 | 671 | ||
362 | dir->is_ready = GNUNET_YES; | 672 | dir->is_ready = GNUNET_YES; |
363 | if (NULL != (env = dir->out_buffer[dir->out_rpos])) | 673 | if (NULL != (env = dir->env_head)) |
364 | { | 674 | { |
365 | dir->out_buffer[dir->out_rpos] = NULL; | 675 | GNUNET_MQ_dll_remove (&dir->env_head, |
366 | dir->out_rpos++; | 676 | &dir->env_tail, |
367 | if (ROUTE_BUFFER_SIZE == dir->out_rpos) | 677 | env); |
368 | dir->out_rpos = 0; | 678 | cur_buffers--; |
679 | GNUNET_STATISTICS_set (stats, | ||
680 | "# buffer use", | ||
681 | cur_buffers, | ||
682 | GNUNET_NO); | ||
683 | lower_rung (dir); | ||
369 | dir->is_ready = GNUNET_NO; | 684 | dir->is_ready = GNUNET_NO; |
370 | GCP_send (dir->mqm, | 685 | GCP_send (dir->mqm, |
371 | env); | 686 | env); |
@@ -398,11 +713,44 @@ dir_init (struct RouteDirection *dir, | |||
398 | dir->mqm = GCP_request_mq (hop, | 713 | dir->mqm = GCP_request_mq (hop, |
399 | &dir_ready_cb, | 714 | &dir_ready_cb, |
400 | dir); | 715 | dir); |
716 | GNUNET_CONTAINER_DLL_insert (rung_head->rd_head, | ||
717 | rung_head->rd_tail, | ||
718 | dir); | ||
719 | dir->rung = rung_head; | ||
401 | GNUNET_assert (GNUNET_YES == dir->is_ready); | 720 | GNUNET_assert (GNUNET_YES == dir->is_ready); |
402 | } | 721 | } |
403 | 722 | ||
404 | 723 | ||
405 | /** | 724 | /** |
725 | * We could not create the desired route. Send a | ||
726 | * #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN | ||
727 | * message to @a target. | ||
728 | * | ||
729 | * @param target who should receive the message | ||
730 | * @param cid identifier of the connection/route that failed | ||
731 | * @param failure_at neighbour with which we failed to route, | ||
732 | * or NULL. | ||
733 | */ | ||
734 | static void | ||
735 | send_broken_without_mqm (struct CadetPeer *target, | ||
736 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | ||
737 | const struct GNUNET_PeerIdentity *failure_at) | ||
738 | { | ||
739 | struct GNUNET_MQ_Envelope *env; | ||
740 | struct GNUNET_CADET_ConnectionBrokenMessage *bm; | ||
741 | |||
742 | env = GNUNET_MQ_msg (bm, | ||
743 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
744 | bm->cid = *cid; | ||
745 | bm->peer1 = my_full_id; | ||
746 | if (NULL != failure_at) | ||
747 | bm->peer2 = *failure_at; | ||
748 | GCP_send_ooo (target, | ||
749 | env); | ||
750 | } | ||
751 | |||
752 | |||
753 | /** | ||
406 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE | 754 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE |
407 | * | 755 | * |
408 | * @param cls Closure (CadetPeer for neighbor that sent the message). | 756 | * @param cls Closure (CadetPeer for neighbor that sent the message). |
@@ -419,7 +767,9 @@ handle_connection_create (void *cls, | |||
419 | uint16_t size = ntohs (msg->header.size) - sizeof (*msg); | 767 | uint16_t size = ntohs (msg->header.size) - sizeof (*msg); |
420 | unsigned int path_length; | 768 | unsigned int path_length; |
421 | unsigned int off; | 769 | unsigned int off; |
770 | enum GNUNET_CADET_ChannelOption options; | ||
422 | 771 | ||
772 | options = (enum GNUNET_CADET_ChannelOption) ntohl (msg->options); | ||
423 | path_length = size / sizeof (struct GNUNET_PeerIdentity); | 773 | path_length = size / sizeof (struct GNUNET_PeerIdentity); |
424 | /* Initiator is at offset 0. */ | 774 | /* Initiator is at offset 0. */ |
425 | for (off=1;off<path_length;off++) | 775 | for (off=1;off<path_length;off++) |
@@ -460,8 +810,7 @@ handle_connection_create (void *cls, | |||
460 | struct CadetPeerPath *path; | 810 | struct CadetPeerPath *path; |
461 | struct CadetPeer *origin; | 811 | struct CadetPeer *origin; |
462 | 812 | ||
463 | cc = GNUNET_CONTAINER_multishortmap_get (connections, | 813 | cc = GCC_lookup (&msg->cid); |
464 | &msg->cid.connection_of_tunnel); | ||
465 | if (NULL != cc) | 814 | if (NULL != cc) |
466 | { | 815 | { |
467 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 816 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -479,10 +828,25 @@ handle_connection_create (void *cls, | |||
479 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | 828 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); |
480 | path = GCPP_get_path_from_route (path_length - 1, | 829 | path = GCPP_get_path_from_route (path_length - 1, |
481 | pids); | 830 | pids); |
482 | GCT_add_inbound_connection (GCP_get_tunnel (origin, | 831 | if (GNUNET_OK != |
483 | GNUNET_YES), | 832 | GCT_add_inbound_connection (GCP_get_tunnel (origin, |
484 | &msg->cid, | 833 | GNUNET_YES), |
485 | path); | 834 | &msg->cid, |
835 | (enum GNUNET_CADET_ChannelOption) ntohl (msg->options), | ||
836 | path)) | ||
837 | { | ||
838 | /* Send back BROKEN: duplicate connection on the same path, | ||
839 | we will use the other one. */ | ||
840 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
841 | "Received CADET_CONNECTION_CREATE from %s for %s, but %s already has a connection. Sending BROKEN\n", | ||
842 | GCP_2s (sender), | ||
843 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | ||
844 | GCPP_2s (path)); | ||
845 | send_broken_without_mqm (sender, | ||
846 | &msg->cid, | ||
847 | NULL); | ||
848 | return; | ||
849 | } | ||
486 | return; | 850 | return; |
487 | } | 851 | } |
488 | /* We are merely a hop on the way, check if we can support the route */ | 852 | /* We are merely a hop on the way, check if we can support the route */ |
@@ -492,22 +856,26 @@ handle_connection_create (void *cls, | |||
492 | (GNUNET_NO == GCP_has_core_connection (next)) ) | 856 | (GNUNET_NO == GCP_has_core_connection (next)) ) |
493 | { | 857 | { |
494 | /* unworkable, send back BROKEN notification */ | 858 | /* unworkable, send back BROKEN notification */ |
495 | struct GNUNET_MQ_Envelope *env; | ||
496 | struct GNUNET_CADET_ConnectionBrokenMessage *bm; | ||
497 | |||
498 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 859 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
499 | "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n", | 860 | "Received CADET_CONNECTION_CREATE from %s for %s. Next hop %s:%u is down. Sending BROKEN\n", |
500 | GCP_2s (sender), | 861 | GCP_2s (sender), |
501 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), | 862 | GNUNET_sh2s (&msg->cid.connection_of_tunnel), |
502 | GNUNET_i2s (&pids[off + 1]), | 863 | GNUNET_i2s (&pids[off + 1]), |
503 | off + 1); | 864 | off + 1); |
504 | env = GNUNET_MQ_msg (bm, | 865 | send_broken_without_mqm (sender, |
505 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | 866 | &msg->cid, |
506 | bm->cid = msg->cid; | 867 | &pids[off + 1]); |
507 | bm->peer1 = pids[off + 1]; | 868 | return; |
508 | bm->peer2 = my_full_id; | 869 | } |
509 | GCP_send_ooo (sender, | 870 | if (max_routes <= GNUNET_CONTAINER_multishortmap_size (routes)) |
510 | env); | 871 | { |
872 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
873 | "Received CADET_CONNECTION_CREATE from %s for %s. We have reached our route limit. Sending BROKEN\n", | ||
874 | GCP_2s (sender), | ||
875 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | ||
876 | send_broken_without_mqm (sender, | ||
877 | &msg->cid, | ||
878 | &pids[off - 1]); | ||
511 | return; | 879 | return; |
512 | } | 880 | } |
513 | 881 | ||
@@ -519,7 +887,9 @@ handle_connection_create (void *cls, | |||
519 | GNUNET_i2s (&pids[off + 1]), | 887 | GNUNET_i2s (&pids[off + 1]), |
520 | off + 1); | 888 | off + 1); |
521 | route = GNUNET_new (struct CadetRoute); | 889 | route = GNUNET_new (struct CadetRoute); |
890 | route->options = options; | ||
522 | route->cid = msg->cid; | 891 | route->cid = msg->cid; |
892 | route->last_use = GNUNET_TIME_absolute_get (); | ||
523 | dir_init (&route->prev, | 893 | dir_init (&route->prev, |
524 | route, | 894 | route, |
525 | sender); | 895 | sender); |
@@ -531,6 +901,18 @@ handle_connection_create (void *cls, | |||
531 | &route->cid.connection_of_tunnel, | 901 | &route->cid.connection_of_tunnel, |
532 | route, | 902 | route, |
533 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 903 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); |
904 | GNUNET_STATISTICS_set (stats, | ||
905 | "# routes", | ||
906 | GNUNET_CONTAINER_multishortmap_size (routes), | ||
907 | GNUNET_NO); | ||
908 | route->hn = GNUNET_CONTAINER_heap_insert (route_heap, | ||
909 | route, | ||
910 | route->last_use.abs_value_us); | ||
911 | if (NULL == timeout_task) | ||
912 | timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (keepalive_period, | ||
913 | 3), | ||
914 | &timeout_cb, | ||
915 | NULL); | ||
534 | } | 916 | } |
535 | 917 | ||
536 | 918 | ||
@@ -548,8 +930,7 @@ handle_connection_create_ack (void *cls, | |||
548 | struct CadetConnection *cc; | 930 | struct CadetConnection *cc; |
549 | 931 | ||
550 | /* First, check if ACK belongs to a connection that ends here. */ | 932 | /* First, check if ACK belongs to a connection that ends here. */ |
551 | cc = GNUNET_CONTAINER_multishortmap_get (connections, | 933 | cc = GCC_lookup (&msg->cid); |
552 | &msg->cid.connection_of_tunnel); | ||
553 | if (NULL != cc) | 934 | if (NULL != cc) |
554 | { | 935 | { |
555 | /* verify ACK came from the right direction */ | 936 | /* verify ACK came from the right direction */ |
@@ -593,8 +974,7 @@ handle_connection_broken (void *cls, | |||
593 | struct CadetRoute *route; | 974 | struct CadetRoute *route; |
594 | 975 | ||
595 | /* First, check if message belongs to a connection that ends here. */ | 976 | /* First, check if message belongs to a connection that ends here. */ |
596 | cc = GNUNET_CONTAINER_multishortmap_get (connections, | 977 | cc = GCC_lookup (&msg->cid); |
597 | &msg->cid.connection_of_tunnel); | ||
598 | if (NULL != cc) | 978 | if (NULL != cc) |
599 | { | 979 | { |
600 | /* verify message came from the right direction */ | 980 | /* verify message came from the right direction */ |
@@ -611,18 +991,19 @@ handle_connection_broken (void *cls, | |||
611 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 991 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
612 | "Received CONNECTION_BROKEN for connection %s. Destroying it.\n", | 992 | "Received CONNECTION_BROKEN for connection %s. Destroying it.\n", |
613 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | 993 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); |
614 | GCC_destroy (cc); | 994 | GCC_destroy_without_core (cc); |
615 | 995 | ||
616 | /* FIXME: also destroy the path up to the specified link! */ | 996 | /* FIXME: also destroy the path up to the specified link! */ |
617 | return; | 997 | return; |
618 | } | 998 | } |
619 | 999 | ||
620 | /* We're just an intermediary peer, route the message along its path */ | 1000 | /* We're just an intermediary peer, route the message along its path */ |
621 | route = get_route (&msg->cid); | ||
622 | route_message (peer, | 1001 | route_message (peer, |
623 | &msg->cid, | 1002 | &msg->cid, |
624 | &msg->header); | 1003 | &msg->header); |
625 | destroy_route (route); | 1004 | route = get_route (&msg->cid); |
1005 | if (NULL != route) | ||
1006 | destroy_route (route); | ||
626 | /* FIXME: also destroy paths we MAY have up to the specified link! */ | 1007 | /* FIXME: also destroy paths we MAY have up to the specified link! */ |
627 | } | 1008 | } |
628 | 1009 | ||
@@ -642,8 +1023,7 @@ handle_connection_destroy (void *cls, | |||
642 | struct CadetRoute *route; | 1023 | struct CadetRoute *route; |
643 | 1024 | ||
644 | /* First, check if message belongs to a connection that ends here. */ | 1025 | /* First, check if message belongs to a connection that ends here. */ |
645 | cc = GNUNET_CONTAINER_multishortmap_get (connections, | 1026 | cc = GCC_lookup (&msg->cid); |
646 | &msg->cid.connection_of_tunnel); | ||
647 | if (NULL != cc) | 1027 | if (NULL != cc) |
648 | { | 1028 | { |
649 | /* verify message came from the right direction */ | 1029 | /* verify message came from the right direction */ |
@@ -661,7 +1041,7 @@ handle_connection_destroy (void *cls, | |||
661 | "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n", | 1041 | "Received CONNECTION_DESTROY for connection %s. Destroying connection.\n", |
662 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | 1042 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); |
663 | 1043 | ||
664 | GCC_destroy (cc); | 1044 | GCC_destroy_without_core (cc); |
665 | return; | 1045 | return; |
666 | } | 1046 | } |
667 | 1047 | ||
@@ -669,11 +1049,12 @@ handle_connection_destroy (void *cls, | |||
669 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1049 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
670 | "Received CONNECTION_DESTROY for connection %s. Destroying route.\n", | 1050 | "Received CONNECTION_DESTROY for connection %s. Destroying route.\n", |
671 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); | 1051 | GNUNET_sh2s (&msg->cid.connection_of_tunnel)); |
672 | route = get_route (&msg->cid); | ||
673 | route_message (peer, | 1052 | route_message (peer, |
674 | &msg->cid, | 1053 | &msg->cid, |
675 | &msg->header); | 1054 | &msg->header); |
676 | destroy_route (route); | 1055 | route = get_route (&msg->cid); |
1056 | if (NULL != route) | ||
1057 | destroy_route (route); | ||
677 | } | 1058 | } |
678 | 1059 | ||
679 | 1060 | ||
@@ -691,8 +1072,7 @@ handle_tunnel_kx (void *cls, | |||
691 | struct CadetConnection *cc; | 1072 | struct CadetConnection *cc; |
692 | 1073 | ||
693 | /* First, check if message belongs to a connection that ends here. */ | 1074 | /* First, check if message belongs to a connection that ends here. */ |
694 | cc = GNUNET_CONTAINER_multishortmap_get (connections, | 1075 | cc = GCC_lookup (&msg->cid); |
695 | &msg->cid.connection_of_tunnel); | ||
696 | if (NULL != cc) | 1076 | if (NULL != cc) |
697 | { | 1077 | { |
698 | /* verify message came from the right direction */ | 1078 | /* verify message came from the right direction */ |
@@ -719,6 +1099,46 @@ handle_tunnel_kx (void *cls, | |||
719 | 1099 | ||
720 | 1100 | ||
721 | /** | 1101 | /** |
1102 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH | ||
1103 | * | ||
1104 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
1105 | * @param msg Message itself. | ||
1106 | */ | ||
1107 | static void | ||
1108 | handle_tunnel_kx_auth (void *cls, | ||
1109 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) | ||
1110 | { | ||
1111 | struct CadetPeer *peer = cls; | ||
1112 | struct CadetConnection *cc; | ||
1113 | |||
1114 | /* First, check if message belongs to a connection that ends here. */ | ||
1115 | cc = GCC_lookup (&msg->kx.cid); | ||
1116 | if (NULL != cc) | ||
1117 | { | ||
1118 | /* verify message came from the right direction */ | ||
1119 | struct CadetPeerPath *path = GCC_get_path (cc); | ||
1120 | |||
1121 | if (peer != | ||
1122 | GCPP_get_peer_at_offset (path, | ||
1123 | 0)) | ||
1124 | { | ||
1125 | /* received message from unexpected direction, ignore! */ | ||
1126 | GNUNET_break_op (0); | ||
1127 | return; | ||
1128 | } | ||
1129 | GCC_handle_kx_auth (cc, | ||
1130 | msg); | ||
1131 | return; | ||
1132 | } | ||
1133 | |||
1134 | /* We're just an intermediary peer, route the message along its path */ | ||
1135 | route_message (peer, | ||
1136 | &msg->kx.cid, | ||
1137 | &msg->kx.header); | ||
1138 | } | ||
1139 | |||
1140 | |||
1141 | /** | ||
722 | * Check if the encrypted message has the appropriate size. | 1142 | * Check if the encrypted message has the appropriate size. |
723 | * | 1143 | * |
724 | * @param cls Closure (unused). | 1144 | * @param cls Closure (unused). |
@@ -748,8 +1168,7 @@ handle_tunnel_encrypted (void *cls, | |||
748 | struct CadetConnection *cc; | 1168 | struct CadetConnection *cc; |
749 | 1169 | ||
750 | /* First, check if message belongs to a connection that ends here. */ | 1170 | /* First, check if message belongs to a connection that ends here. */ |
751 | cc = GNUNET_CONTAINER_multishortmap_get (connections, | 1171 | cc = GCC_lookup (&msg->cid); |
752 | &msg->cid.connection_of_tunnel); | ||
753 | if (NULL != cc) | 1172 | if (NULL != cc) |
754 | { | 1173 | { |
755 | /* verify message came from the right direction */ | 1174 | /* verify message came from the right direction */ |
@@ -876,6 +1295,10 @@ GCO_init (const struct GNUNET_CONFIGURATION_Handle *c) | |||
876 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX, | 1295 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX, |
877 | struct GNUNET_CADET_TunnelKeyExchangeMessage, | 1296 | struct GNUNET_CADET_TunnelKeyExchangeMessage, |
878 | NULL), | 1297 | NULL), |
1298 | GNUNET_MQ_hd_fixed_size (tunnel_kx_auth, | ||
1299 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH, | ||
1300 | struct GNUNET_CADET_TunnelKeyExchangeAuthMessage, | ||
1301 | NULL), | ||
879 | GNUNET_MQ_hd_var_size (tunnel_encrypted, | 1302 | GNUNET_MQ_hd_var_size (tunnel_encrypted, |
880 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED, | 1303 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED, |
881 | struct GNUNET_CADET_TunnelEncryptedMessage, | 1304 | struct GNUNET_CADET_TunnelEncryptedMessage, |
@@ -883,8 +1306,21 @@ GCO_init (const struct GNUNET_CONFIGURATION_Handle *c) | |||
883 | GNUNET_MQ_handler_end () | 1306 | GNUNET_MQ_handler_end () |
884 | }; | 1307 | }; |
885 | 1308 | ||
1309 | if (GNUNET_OK != | ||
1310 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1311 | "CADET", | ||
1312 | "MAX_ROUTES", | ||
1313 | &max_routes)) | ||
1314 | max_routes = 5000; | ||
1315 | if (GNUNET_OK != | ||
1316 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1317 | "CADET", | ||
1318 | "MAX_MSGS_QUEUE", | ||
1319 | &max_buffers)) | ||
1320 | max_buffers = 10000; | ||
886 | routes = GNUNET_CONTAINER_multishortmap_create (1024, | 1321 | routes = GNUNET_CONTAINER_multishortmap_create (1024, |
887 | GNUNET_NO); | 1322 | GNUNET_NO); |
1323 | route_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); | ||
888 | core = GNUNET_CORE_connect (c, | 1324 | core = GNUNET_CORE_connect (c, |
889 | NULL, | 1325 | NULL, |
890 | &core_init_cb, | 1326 | &core_init_cb, |
@@ -907,6 +1343,14 @@ GCO_shutdown () | |||
907 | } | 1343 | } |
908 | GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes)); | 1344 | GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (routes)); |
909 | GNUNET_CONTAINER_multishortmap_destroy (routes); | 1345 | GNUNET_CONTAINER_multishortmap_destroy (routes); |
1346 | routes = NULL; | ||
1347 | GNUNET_CONTAINER_heap_destroy (route_heap); | ||
1348 | route_heap = NULL; | ||
1349 | if (NULL != timeout_task) | ||
1350 | { | ||
1351 | GNUNET_SCHEDULER_cancel (timeout_task); | ||
1352 | timeout_task = NULL; | ||
1353 | } | ||
910 | } | 1354 | } |
911 | 1355 | ||
912 | /* end of gnunet-cadet-service_core.c */ | 1356 | /* end of gnunet-cadet-service_core.c */ |
diff --git a/src/cadet/gnunet-service-cadet-new_core.h b/src/cadet/gnunet-service-cadet_core.h index 65b0a6ba5..65b0a6ba5 100644 --- a/src/cadet/gnunet-service-cadet-new_core.h +++ b/src/cadet/gnunet-service-cadet_core.h | |||
diff --git a/src/cadet/gnunet-service-cadet_dht.c b/src/cadet/gnunet-service-cadet_dht.c index 22673b167..f00c0caf3 100644 --- a/src/cadet/gnunet-service-cadet_dht.c +++ b/src/cadet/gnunet-service-cadet_dht.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2013 GNUnet e.V. | 3 | Copyright (C) 2013, 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -17,25 +17,41 @@ | |||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. | 18 | Boston, MA 02110-1301, USA. |
19 | */ | 19 | */ |
20 | 20 | /** | |
21 | * @file cadet/gnunet-service-cadet_dht.c | ||
22 | * @brief Information we track per peer. | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
21 | 26 | ||
22 | #include "platform.h" | 27 | #include "platform.h" |
23 | #include "gnunet_util_lib.h" | 28 | #include "gnunet_util_lib.h" |
24 | |||
25 | #include "gnunet_dht_service.h" | 29 | #include "gnunet_dht_service.h" |
26 | #include "gnunet_statistics_service.h" | 30 | #include "gnunet_statistics_service.h" |
27 | 31 | #include "gnunet-service-cadet.h" | |
28 | #include "cadet_path.h" | ||
29 | #include "gnunet-service-cadet_dht.h" | 32 | #include "gnunet-service-cadet_dht.h" |
30 | #include "gnunet-service-cadet_peer.h" | ||
31 | #include "gnunet-service-cadet_hello.h" | 33 | #include "gnunet-service-cadet_hello.h" |
34 | #include "gnunet-service-cadet_peer.h" | ||
35 | #include "gnunet-service-cadet_paths.h" | ||
32 | 36 | ||
33 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__) | 37 | /** |
38 | * How long do we wait before first announcing our presence to the DHT. | ||
39 | * Used to wait for our HELLO to be available. Note that we also get | ||
40 | * notifications when our HELLO is ready, so this is just the maximum | ||
41 | * we wait for the first notification. | ||
42 | */ | ||
43 | #define STARTUP_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500) | ||
34 | 44 | ||
45 | /** | ||
46 | * How long do we wait after we get an updated HELLO before publishing? | ||
47 | * Allows for the HELLO to be updated again quickly, for example in | ||
48 | * case multiple addresses changed and we got a partial update. | ||
49 | */ | ||
50 | #define CHANGE_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100) | ||
51 | |||
52 | |||
53 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__) | ||
35 | 54 | ||
36 | /******************************************************************************/ | ||
37 | /******************************** STRUCTS **********************************/ | ||
38 | /******************************************************************************/ | ||
39 | 55 | ||
40 | /** | 56 | /** |
41 | * Handle for DHT searches. | 57 | * Handle for DHT searches. |
@@ -47,42 +63,9 @@ struct GCD_search_handle | |||
47 | */ | 63 | */ |
48 | struct GNUNET_DHT_GetHandle *dhtget; | 64 | struct GNUNET_DHT_GetHandle *dhtget; |
49 | 65 | ||
50 | /** | ||
51 | * Provided callback to call when a path is found. | ||
52 | */ | ||
53 | GCD_search_callback callback; | ||
54 | |||
55 | /** | ||
56 | * Provided closure. | ||
57 | */ | ||
58 | void *cls; | ||
59 | |||
60 | /** | ||
61 | * Peer ID searched for | ||
62 | */ | ||
63 | GNUNET_PEER_Id peer_id; | ||
64 | }; | 66 | }; |
65 | 67 | ||
66 | 68 | ||
67 | /******************************************************************************/ | ||
68 | /******************************* GLOBALS ***********************************/ | ||
69 | /******************************************************************************/ | ||
70 | |||
71 | /** | ||
72 | * Global handle to the statistics service. | ||
73 | */ | ||
74 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
75 | |||
76 | /** | ||
77 | * Own ID (short value). | ||
78 | */ | ||
79 | extern GNUNET_PEER_Id myid; | ||
80 | |||
81 | /** | ||
82 | * Own ID (full value). | ||
83 | */ | ||
84 | extern struct GNUNET_PeerIdentity my_full_id; | ||
85 | |||
86 | /** | 69 | /** |
87 | * Handle to use DHT. | 70 | * Handle to use DHT. |
88 | */ | 71 | */ |
@@ -94,69 +77,20 @@ static struct GNUNET_DHT_Handle *dht_handle; | |||
94 | static struct GNUNET_TIME_Relative id_announce_time; | 77 | static struct GNUNET_TIME_Relative id_announce_time; |
95 | 78 | ||
96 | /** | 79 | /** |
97 | * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put. | 80 | * DHT replication level, see DHT API: #GNUNET_DHT_get_start(), #GNUNET_DHT_put(). |
98 | */ | 81 | */ |
99 | static unsigned long long dht_replication_level; | 82 | static unsigned long long dht_replication_level; |
100 | 83 | ||
101 | /** | 84 | /** |
102 | * Task to periodically announce itself in the network. | 85 | * Task to periodically announce itself in the network. |
103 | */ | 86 | */ |
104 | static struct GNUNET_SCHEDULER_Task * announce_id_task; | 87 | static struct GNUNET_SCHEDULER_Task *announce_id_task; |
105 | 88 | ||
106 | /** | 89 | /** |
107 | * Delay for the next ID announce. | 90 | * Delay for the next ID announce. |
108 | */ | 91 | */ |
109 | static struct GNUNET_TIME_Relative announce_delay; | 92 | static struct GNUNET_TIME_Relative announce_delay; |
110 | 93 | ||
111 | /** | ||
112 | * GET requests to stop on shutdown. | ||
113 | */ | ||
114 | static struct GNUNET_CONTAINER_MultiHashMap32 *get_requests; | ||
115 | |||
116 | /******************************************************************************/ | ||
117 | /******************************** STATIC ***********************************/ | ||
118 | /******************************************************************************/ | ||
119 | |||
120 | |||
121 | /** | ||
122 | * Build a PeerPath from the paths returned from the DHT, reversing the paths | ||
123 | * to obtain a local peer -> destination path and interning the peer ids. | ||
124 | * | ||
125 | * @return Newly allocated and created path | ||
126 | * | ||
127 | * FIXME refactor and use build_path_from_peer_ids | ||
128 | */ | ||
129 | static struct CadetPeerPath * | ||
130 | path_build_from_dht (const struct GNUNET_PeerIdentity *get_path, | ||
131 | unsigned int get_path_length, | ||
132 | const struct GNUNET_PeerIdentity *put_path, | ||
133 | unsigned int put_path_length) | ||
134 | { | ||
135 | size_t size = get_path_length + put_path_length + 1; | ||
136 | struct GNUNET_PeerIdentity peers[size]; | ||
137 | const struct GNUNET_PeerIdentity *peer; | ||
138 | struct CadetPeerPath *p; | ||
139 | unsigned int own_pos; | ||
140 | int i; | ||
141 | |||
142 | peers[0] = my_full_id; | ||
143 | LOG (GNUNET_ERROR_TYPE_DEBUG, " GET has %d hops.\n", get_path_length); | ||
144 | for (i = 0 ; i < get_path_length; i++) | ||
145 | { | ||
146 | peer = &get_path[get_path_length - i - 1]; | ||
147 | LOG (GNUNET_ERROR_TYPE_DEBUG, " From GET: %s\n", GNUNET_i2s (peer)); | ||
148 | peers[i + 1] = *peer; | ||
149 | } | ||
150 | for (i = 0 ; i < put_path_length; i++) | ||
151 | { | ||
152 | peer = &put_path[put_path_length - i - 1]; | ||
153 | LOG (GNUNET_ERROR_TYPE_DEBUG, " From PUT: %s\n", GNUNET_i2s (peer)); | ||
154 | peers[i + get_path_length + 1] = *peer; | ||
155 | } | ||
156 | p = path_build_from_peer_ids (peers, size, myid, &own_pos); | ||
157 | return p; | ||
158 | } | ||
159 | |||
160 | 94 | ||
161 | /** | 95 | /** |
162 | * Function to process paths received for a new peer addition. The recorded | 96 | * Function to process paths received for a new peer addition. The recorded |
@@ -176,42 +110,34 @@ path_build_from_dht (const struct GNUNET_PeerIdentity *get_path, | |||
176 | */ | 110 | */ |
177 | static void | 111 | static void |
178 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | 112 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, |
179 | const struct GNUNET_HashCode * key, | 113 | const struct GNUNET_HashCode *key, |
180 | const struct GNUNET_PeerIdentity *get_path, | 114 | const struct GNUNET_PeerIdentity *get_path, |
181 | unsigned int get_path_length, | 115 | unsigned int get_path_length, |
182 | const struct GNUNET_PeerIdentity *put_path, | 116 | const struct GNUNET_PeerIdentity *put_path, |
183 | unsigned int put_path_length, enum GNUNET_BLOCK_Type type, | 117 | unsigned int put_path_length, |
184 | size_t size, const void *data) | 118 | enum GNUNET_BLOCK_Type type, |
119 | size_t size, | ||
120 | const void *data) | ||
185 | { | 121 | { |
186 | struct GCD_search_handle *h = cls; | 122 | const struct GNUNET_HELLO_Message *hello = data; |
187 | struct GNUNET_HELLO_Message *hello; | ||
188 | struct CadetPeerPath *p; | ||
189 | struct CadetPeer *peer; | 123 | struct CadetPeer *peer; |
190 | char *s; | ||
191 | 124 | ||
192 | p = path_build_from_dht (get_path, get_path_length, | 125 | GCPP_try_path_from_dht (get_path, |
193 | put_path, put_path_length); | 126 | get_path_length, |
194 | if (NULL == p) | 127 | put_path, |
128 | put_path_length); | ||
129 | if ( (size >= sizeof (struct GNUNET_HELLO_Message)) && | ||
130 | (ntohs (hello->header.size) == size) && | ||
131 | (size == GNUNET_HELLO_size (hello)) ) | ||
195 | { | 132 | { |
196 | GNUNET_break_op (0); | 133 | peer = GCP_get (&put_path[0], |
197 | return; | 134 | GNUNET_YES); |
135 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
136 | "Got HELLO for %s\n", | ||
137 | GCP_2s (peer)); | ||
138 | GCP_set_hello (peer, | ||
139 | hello); | ||
198 | } | 140 | } |
199 | |||
200 | s = path_2s (p); | ||
201 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
202 | "Got path from DHT: %s\n", | ||
203 | s); | ||
204 | GNUNET_free_non_null (s); | ||
205 | |||
206 | peer = GCP_get_short (p->peers[p->length - 1], GNUNET_YES); | ||
207 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
208 | "Got HELLO for %s\n", | ||
209 | GCP_2s (peer)); | ||
210 | h->callback (h->cls, p); | ||
211 | path_destroy (p); | ||
212 | hello = (struct GNUNET_HELLO_Message *) data; | ||
213 | GCP_set_hello (peer, hello); | ||
214 | GCP_try_connect (peer); | ||
215 | } | 141 | } |
216 | 142 | ||
217 | 143 | ||
@@ -229,19 +155,10 @@ announce_id (void *cls) | |||
229 | struct GNUNET_TIME_Absolute expiration; | 155 | struct GNUNET_TIME_Absolute expiration; |
230 | struct GNUNET_TIME_Relative next_put; | 156 | struct GNUNET_TIME_Relative next_put; |
231 | 157 | ||
232 | announce_id_task = NULL; | ||
233 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n"); | ||
234 | hello = GCH_get_mine (); | 158 | hello = GCH_get_mine (); |
235 | size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0; | 159 | size = (NULL != hello) ? GNUNET_HELLO_size (hello) : 0; |
236 | if ( (NULL == hello) || (0 == size) ) | 160 | if (0 == size) |
237 | { | 161 | { |
238 | /* Peerinfo gave us no hello yet, try again soon. */ | ||
239 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
240 | " no hello, waiting!\n"); | ||
241 | GNUNET_STATISTICS_update (stats, | ||
242 | "# DHT announce skipped (no hello)", | ||
243 | 1, | ||
244 | GNUNET_NO); | ||
245 | expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), | 162 | expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), |
246 | announce_delay); | 163 | announce_delay); |
247 | announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay); | 164 | announce_delay = GNUNET_TIME_STD_BACKOFF (announce_delay); |
@@ -252,71 +169,64 @@ announce_id (void *cls) | |||
252 | announce_delay = GNUNET_TIME_UNIT_SECONDS; | 169 | announce_delay = GNUNET_TIME_UNIT_SECONDS; |
253 | } | 170 | } |
254 | 171 | ||
255 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
256 | "Hello %p size: %u\n", | ||
257 | hello, | ||
258 | size); | ||
259 | if (NULL != hello) | ||
260 | { | ||
261 | GNUNET_STATISTICS_update (stats, | ||
262 | "# DHT announce", | ||
263 | 1, GNUNET_NO); | ||
264 | memset (&phash, | ||
265 | 0, | ||
266 | sizeof (phash)); | ||
267 | GNUNET_memcpy (&phash, | ||
268 | &my_full_id, | ||
269 | sizeof (my_full_id)); | ||
270 | GNUNET_DHT_put (dht_handle, /* DHT handle */ | ||
271 | &phash, /* Key to use */ | ||
272 | dht_replication_level, /* Replication level */ | ||
273 | GNUNET_DHT_RO_RECORD_ROUTE | ||
274 | | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ | ||
275 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */ | ||
276 | size, /* Size of the data */ | ||
277 | (const char *) hello, /* Data itself */ | ||
278 | expiration, /* Data expiration */ | ||
279 | NULL, /* Continuation */ | ||
280 | NULL); /* Continuation closure */ | ||
281 | } | ||
282 | /* Call again in id_announce_time, unless HELLO expires first, | 172 | /* Call again in id_announce_time, unless HELLO expires first, |
283 | * but wait at least 1s. */ | 173 | * but wait at least 1s. */ |
284 | next_put = GNUNET_TIME_absolute_get_remaining (expiration); | 174 | next_put |
285 | next_put = GNUNET_TIME_relative_min (next_put, | 175 | = GNUNET_TIME_absolute_get_remaining (expiration); |
286 | id_announce_time); | 176 | next_put |
287 | next_put = GNUNET_TIME_relative_max (next_put, | 177 | = GNUNET_TIME_relative_min (next_put, |
288 | GNUNET_TIME_UNIT_SECONDS); | 178 | id_announce_time); |
289 | announce_id_task = GNUNET_SCHEDULER_add_delayed (next_put, | 179 | next_put |
290 | &announce_id, | 180 | = GNUNET_TIME_relative_max (next_put, |
291 | cls); | 181 | GNUNET_TIME_UNIT_SECONDS); |
182 | announce_id_task | ||
183 | = GNUNET_SCHEDULER_add_delayed (next_put, | ||
184 | &announce_id, | ||
185 | cls); | ||
186 | GNUNET_STATISTICS_update (stats, | ||
187 | "# DHT announce", | ||
188 | 1, | ||
189 | GNUNET_NO); | ||
190 | memset (&phash, | ||
191 | 0, | ||
192 | sizeof (phash)); | ||
193 | GNUNET_memcpy (&phash, | ||
194 | &my_full_id, | ||
195 | sizeof (my_full_id)); | ||
196 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
197 | "Announcing my HELLO (%u bytes) in the DHT\n", | ||
198 | size); | ||
199 | GNUNET_DHT_put (dht_handle, /* DHT handle */ | ||
200 | &phash, /* Key to use */ | ||
201 | dht_replication_level, /* Replication level */ | ||
202 | GNUNET_DHT_RO_RECORD_ROUTE | ||
203 | | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ | ||
204 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */ | ||
205 | size, /* Size of the data */ | ||
206 | (const char *) hello, /* Data itself */ | ||
207 | expiration, /* Data expiration */ | ||
208 | NULL, /* Continuation */ | ||
209 | NULL); /* Continuation closure */ | ||
292 | } | 210 | } |
293 | 211 | ||
212 | |||
294 | /** | 213 | /** |
295 | * Iterator over hash map entries and stop GET requests before disconnecting | 214 | * Function called by the HELLO subsystem whenever OUR hello |
296 | * from the DHT. | 215 | * changes. Re-triggers the DHT PUT immediately. |
297 | * | ||
298 | * @param cls Closure (unused) | ||
299 | * @param key Current peer ID. | ||
300 | * @param value Value in the hash map (GCD_search_handle). | ||
301 | * | ||
302 | * @return #GNUNET_YES, we should continue to iterate, | ||
303 | */ | 216 | */ |
304 | int | 217 | void |
305 | stop_get (void *cls, | 218 | GCD_hello_update () |
306 | uint32_t key, | ||
307 | void *value) | ||
308 | { | 219 | { |
309 | struct GCD_search_handle *h = value; | 220 | if (NULL == announce_id_task) |
310 | 221 | return; /* too early */ | |
311 | GCD_search_stop (h); | 222 | GNUNET_SCHEDULER_cancel (announce_id_task); |
312 | return GNUNET_YES; | 223 | announce_id_task |
224 | = GNUNET_SCHEDULER_add_delayed (CHANGE_DELAY, | ||
225 | &announce_id, | ||
226 | NULL); | ||
313 | } | 227 | } |
314 | 228 | ||
315 | 229 | ||
316 | /******************************************************************************/ | ||
317 | /******************************** API ***********************************/ | ||
318 | /******************************************************************************/ | ||
319 | |||
320 | /** | 230 | /** |
321 | * Initialize the DHT subsystem. | 231 | * Initialize the DHT subsystem. |
322 | * | 232 | * |
@@ -325,36 +235,40 @@ stop_get (void *cls, | |||
325 | void | 235 | void |
326 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c) | 236 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c) |
327 | { | 237 | { |
328 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
329 | if (GNUNET_OK != | 238 | if (GNUNET_OK != |
330 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", | 239 | GNUNET_CONFIGURATION_get_value_number (c, |
240 | "CADET", | ||
331 | "DHT_REPLICATION_LEVEL", | 241 | "DHT_REPLICATION_LEVEL", |
332 | &dht_replication_level)) | 242 | &dht_replication_level)) |
333 | { | 243 | { |
334 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, "CADET", | 244 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, |
335 | "DHT_REPLICATION_LEVEL", "USING DEFAULT"); | 245 | "CADET", |
246 | "DHT_REPLICATION_LEVEL", | ||
247 | "USING DEFAULT"); | ||
336 | dht_replication_level = 3; | 248 | dht_replication_level = 3; |
337 | } | 249 | } |
338 | 250 | ||
339 | if (GNUNET_OK != | 251 | if (GNUNET_OK != |
340 | GNUNET_CONFIGURATION_get_value_time (c, "CADET", "ID_ANNOUNCE_TIME", | 252 | GNUNET_CONFIGURATION_get_value_time (c, |
253 | "CADET", | ||
254 | "ID_ANNOUNCE_TIME", | ||
341 | &id_announce_time)) | 255 | &id_announce_time)) |
342 | { | 256 | { |
343 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "CADET", | 257 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, |
344 | "ID_ANNOUNCE_TIME", "MISSING"); | 258 | "CADET", |
259 | "ID_ANNOUNCE_TIME", | ||
260 | "MISSING"); | ||
345 | GNUNET_SCHEDULER_shutdown (); | 261 | GNUNET_SCHEDULER_shutdown (); |
346 | return; | 262 | return; |
347 | } | 263 | } |
348 | 264 | ||
349 | dht_handle = GNUNET_DHT_connect (c, 64); | 265 | dht_handle = GNUNET_DHT_connect (c, |
350 | if (NULL == dht_handle) | 266 | 64); |
351 | { | 267 | GNUNET_break (NULL != dht_handle); |
352 | GNUNET_break (0); | ||
353 | } | ||
354 | |||
355 | announce_delay = GNUNET_TIME_UNIT_SECONDS; | 268 | announce_delay = GNUNET_TIME_UNIT_SECONDS; |
356 | announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, NULL); | 269 | announce_id_task = GNUNET_SCHEDULER_add_delayed (STARTUP_DELAY, |
357 | get_requests = GNUNET_CONTAINER_multihashmap32_create (32); | 270 | &announce_id, |
271 | NULL); | ||
358 | } | 272 | } |
359 | 273 | ||
360 | 274 | ||
@@ -364,10 +278,7 @@ GCD_init (const struct GNUNET_CONFIGURATION_Handle *c) | |||
364 | void | 278 | void |
365 | GCD_shutdown (void) | 279 | GCD_shutdown (void) |
366 | { | 280 | { |
367 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down DHT\n"); | 281 | if (NULL != dht_handle) |
368 | GNUNET_CONTAINER_multihashmap32_iterate (get_requests, &stop_get, NULL); | ||
369 | GNUNET_CONTAINER_multihashmap32_destroy (get_requests); | ||
370 | if (dht_handle != NULL) | ||
371 | { | 282 | { |
372 | GNUNET_DHT_disconnect (dht_handle); | 283 | GNUNET_DHT_disconnect (dht_handle); |
373 | dht_handle = NULL; | 284 | dht_handle = NULL; |
@@ -379,22 +290,31 @@ GCD_shutdown (void) | |||
379 | } | 290 | } |
380 | } | 291 | } |
381 | 292 | ||
293 | |||
294 | /** | ||
295 | * Search DHT for paths to @a peeR_id | ||
296 | * | ||
297 | * @param peer_id peer to search for | ||
298 | * @return handle to abort search | ||
299 | */ | ||
382 | struct GCD_search_handle * | 300 | struct GCD_search_handle * |
383 | GCD_search (const struct GNUNET_PeerIdentity *peer_id, | 301 | GCD_search (const struct GNUNET_PeerIdentity *peer_id) |
384 | GCD_search_callback callback, void *cls) | ||
385 | { | 302 | { |
386 | struct GNUNET_HashCode phash; | 303 | struct GNUNET_HashCode phash; |
387 | struct GCD_search_handle *h; | 304 | struct GCD_search_handle *h; |
388 | 305 | ||
389 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting DHT GET for peer %s\n", | 306 | GNUNET_STATISTICS_update (stats, |
390 | GNUNET_i2s (peer_id)); | 307 | "# DHT search", |
391 | GNUNET_STATISTICS_update (stats, "# DHT search", 1, GNUNET_NO); | 308 | 1, |
392 | memset (&phash, 0, sizeof (phash)); | 309 | GNUNET_NO); |
393 | GNUNET_memcpy (&phash, peer_id, sizeof (*peer_id)); | 310 | memset (&phash, |
311 | 0, | ||
312 | sizeof (phash)); | ||
313 | GNUNET_memcpy (&phash, | ||
314 | peer_id, | ||
315 | sizeof (*peer_id)); | ||
316 | |||
394 | h = GNUNET_new (struct GCD_search_handle); | 317 | h = GNUNET_new (struct GCD_search_handle); |
395 | h->peer_id = GNUNET_PEER_intern (peer_id); | ||
396 | h->callback = callback; | ||
397 | h->cls = cls; | ||
398 | h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ | 318 | h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ |
399 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */ | 319 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */ |
400 | &phash, /* key to search */ | 320 | &phash, /* key to search */ |
@@ -405,20 +325,27 @@ GCD_search (const struct GNUNET_PeerIdentity *peer_id, | |||
405 | 0, /* xquery bits */ | 325 | 0, /* xquery bits */ |
406 | &dht_get_id_handler, | 326 | &dht_get_id_handler, |
407 | h); | 327 | h); |
408 | GNUNET_CONTAINER_multihashmap32_put (get_requests, | 328 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
409 | h->peer_id, | 329 | "Starting DHT GET for peer %s (%p)\n", |
410 | h, | 330 | GNUNET_i2s (peer_id), |
411 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | 331 | h); |
412 | return h; | 332 | return h; |
413 | } | 333 | } |
414 | 334 | ||
415 | 335 | ||
336 | /** | ||
337 | * Stop DHT search started with #GCD_search(). | ||
338 | * | ||
339 | * @param h handle to search to stop | ||
340 | */ | ||
416 | void | 341 | void |
417 | GCD_search_stop (struct GCD_search_handle *h) | 342 | GCD_search_stop (struct GCD_search_handle *h) |
418 | { | 343 | { |
419 | GNUNET_break (GNUNET_OK == | 344 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
420 | GNUNET_CONTAINER_multihashmap32_remove (get_requests, | 345 | "Stopping DHT GET %p\n", |
421 | h->peer_id, h)); | 346 | h); |
422 | GNUNET_DHT_get_stop (h->dhtget); | 347 | GNUNET_DHT_get_stop (h->dhtget); |
423 | GNUNET_free (h); | 348 | GNUNET_free (h); |
424 | } | 349 | } |
350 | |||
351 | /* end of gnunet-service-cadet_dht.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet_dht.h b/src/cadet/gnunet-service-cadet_dht.h index b70dfe975..5d7ab29a0 100644 --- a/src/cadet/gnunet-service-cadet_dht.h +++ b/src/cadet/gnunet-service-cadet_dht.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2013 GNUnet e.V. | 3 | Copyright (C) 2013, 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -22,10 +22,10 @@ | |||
22 | * @file cadet/gnunet-service-cadet_dht.h | 22 | * @file cadet/gnunet-service-cadet_dht.h |
23 | * @brief cadet service; dealing with DHT requests and results | 23 | * @brief cadet service; dealing with DHT requests and results |
24 | * @author Bartlomiej Polot | 24 | * @author Bartlomiej Polot |
25 | * @author Christian Grothoff | ||
25 | * | 26 | * |
26 | * All functions in this file should use the prefix GMD (Gnunet Cadet Dht) | 27 | * All functions in this file should use the prefix GCD (Gnunet Cadet Dht) |
27 | */ | 28 | */ |
28 | |||
29 | #ifndef GNUNET_SERVICE_CADET_DHT_H | 29 | #ifndef GNUNET_SERVICE_CADET_DHT_H |
30 | #define GNUNET_SERVICE_CADET_DHT_H | 30 | #define GNUNET_SERVICE_CADET_DHT_H |
31 | 31 | ||
@@ -40,23 +40,11 @@ extern "C" | |||
40 | #include "platform.h" | 40 | #include "platform.h" |
41 | #include "gnunet_util_lib.h" | 41 | #include "gnunet_util_lib.h" |
42 | 42 | ||
43 | struct GCD_search_handle; | ||
44 | |||
45 | |||
46 | /** | 43 | /** |
47 | * Callback called on each path found over the DHT. | 44 | * Handle for DHT search operation. |
48 | * | ||
49 | * @param cls Closure. | ||
50 | * @param path An unchecked, unoptimized path to the target node. | ||
51 | * After callback will no longer be valid! | ||
52 | */ | 45 | */ |
53 | typedef void | 46 | struct GCD_search_handle; |
54 | (*GCD_search_callback) (void *cls, | ||
55 | const struct CadetPeerPath *path); | ||
56 | 47 | ||
57 | /******************************************************************************/ | ||
58 | /******************************** API ***********************************/ | ||
59 | /******************************************************************************/ | ||
60 | 48 | ||
61 | /** | 49 | /** |
62 | * Initialize the DHT subsystem. | 50 | * Initialize the DHT subsystem. |
@@ -66,6 +54,7 @@ typedef void | |||
66 | void | 54 | void |
67 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c); | 55 | GCD_init (const struct GNUNET_CONFIGURATION_Handle *c); |
68 | 56 | ||
57 | |||
69 | /** | 58 | /** |
70 | * Shut down the DHT subsystem. | 59 | * Shut down the DHT subsystem. |
71 | */ | 60 | */ |
@@ -73,14 +62,32 @@ void | |||
73 | GCD_shutdown (void); | 62 | GCD_shutdown (void); |
74 | 63 | ||
75 | 64 | ||
65 | /** | ||
66 | * Function called by the HELLO subsystem whenever OUR hello | ||
67 | * changes. Re-triggers the DHT PUT immediately. | ||
68 | */ | ||
69 | void | ||
70 | GCD_hello_update (void); | ||
71 | |||
72 | /** | ||
73 | * Search DHT for paths to @a peeR_id | ||
74 | * | ||
75 | * @param peer_id peer to search for | ||
76 | * @return handle to abort search | ||
77 | */ | ||
76 | struct GCD_search_handle * | 78 | struct GCD_search_handle * |
77 | GCD_search (const struct GNUNET_PeerIdentity *peer_id, | 79 | GCD_search (const struct GNUNET_PeerIdentity *peer_id); |
78 | GCD_search_callback callback, void *cls); | ||
79 | 80 | ||
80 | 81 | ||
82 | /** | ||
83 | * Stop DHT search started with #GCD_search(). | ||
84 | * | ||
85 | * @param h handle to search to stop | ||
86 | */ | ||
81 | void | 87 | void |
82 | GCD_search_stop (struct GCD_search_handle *h); | 88 | GCD_search_stop (struct GCD_search_handle *h); |
83 | 89 | ||
90 | |||
84 | #if 0 /* keep Emacsens' auto-indent happy */ | 91 | #if 0 /* keep Emacsens' auto-indent happy */ |
85 | { | 92 | { |
86 | #endif | 93 | #endif |
@@ -88,6 +95,6 @@ GCD_search_stop (struct GCD_search_handle *h); | |||
88 | } | 95 | } |
89 | #endif | 96 | #endif |
90 | 97 | ||
91 | /* ifndef GNUNET_CADET_SERVICE_LOCAL_H */ | 98 | /* ifndef GNUNET_CADET_SERVICE_DHT_H */ |
92 | #endif | 99 | #endif |
93 | /* end of gnunet-cadet-service_LOCAL.h */ | 100 | /* end of gnunet-service-cadet_dht.h */ |
diff --git a/src/cadet/gnunet-service-cadet_hello.c b/src/cadet/gnunet-service-cadet_hello.c index 3c63f3551..6d85de39f 100644 --- a/src/cadet/gnunet-service-cadet_hello.c +++ b/src/cadet/gnunet-service-cadet_hello.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2014 GNUnet e.V. | 3 | Copyright (C) 2014, 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -17,58 +17,33 @@ | |||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. | 18 | Boston, MA 02110-1301, USA. |
19 | */ | 19 | */ |
20 | 20 | /** | |
21 | * @file cadet/gnunet-service-cadet_hello.c | ||
22 | * @brief spread knowledge about how to contact other peers from PEERINFO | ||
23 | * @author Bartlomiej Polot | ||
24 | * @author Christian Grothoff | ||
25 | * | ||
26 | * TODO: | ||
27 | * - is most of this necessary/helpful? | ||
28 | * - should we not simply restrict this to OUR hello? | ||
29 | */ | ||
21 | #include "platform.h" | 30 | #include "platform.h" |
22 | #include "gnunet_util_lib.h" | 31 | #include "gnunet_util_lib.h" |
23 | 32 | ||
24 | #include "gnunet_statistics_service.h" | 33 | #include "gnunet_statistics_service.h" |
25 | #include "gnunet_peerinfo_service.h" | 34 | #include "gnunet_peerinfo_service.h" |
26 | |||
27 | #include "cadet_protocol.h" | 35 | #include "cadet_protocol.h" |
28 | #include "cadet_path.h" | 36 | #include "gnunet-service-cadet.h" |
29 | 37 | #include "gnunet-service-cadet_dht.h" | |
30 | #include "gnunet-service-cadet_hello.h" | 38 | #include "gnunet-service-cadet_hello.h" |
31 | #include "gnunet-service-cadet_peer.h" | 39 | #include "gnunet-service-cadet_peer.h" |
32 | 40 | ||
33 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__) | 41 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__) |
34 | 42 | ||
35 | |||
36 | /******************************************************************************/ | ||
37 | /******************************** STRUCTS **********************************/ | ||
38 | /******************************************************************************/ | ||
39 | |||
40 | |||
41 | |||
42 | /******************************************************************************/ | ||
43 | /******************************* GLOBALS ***********************************/ | ||
44 | /******************************************************************************/ | ||
45 | |||
46 | /** | ||
47 | * Global handle to the statistics service. | ||
48 | */ | ||
49 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
50 | |||
51 | /** | ||
52 | * Local peer own ID (memory efficient handle). | ||
53 | */ | ||
54 | extern GNUNET_PEER_Id myid; | ||
55 | |||
56 | /** | ||
57 | * Local peer own ID (full value). | ||
58 | */ | ||
59 | extern struct GNUNET_PeerIdentity my_full_id; | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Don't try to recover tunnels if shutting down. | ||
64 | */ | ||
65 | extern int shutting_down; | ||
66 | |||
67 | |||
68 | /** | 43 | /** |
69 | * Hello message of local peer. | 44 | * Hello message of local peer. |
70 | */ | 45 | */ |
71 | const struct GNUNET_HELLO_Message *mine; | 46 | static struct GNUNET_HELLO_Message *mine; |
72 | 47 | ||
73 | /** | 48 | /** |
74 | * Handle to peerinfo service. | 49 | * Handle to peerinfo service. |
@@ -78,13 +53,9 @@ static struct GNUNET_PEERINFO_Handle *peerinfo; | |||
78 | /** | 53 | /** |
79 | * Iterator context. | 54 | * Iterator context. |
80 | */ | 55 | */ |
81 | struct GNUNET_PEERINFO_NotifyContext* nc; | 56 | static struct GNUNET_PEERINFO_NotifyContext *nc; |
82 | 57 | ||
83 | 58 | ||
84 | /******************************************************************************/ | ||
85 | /******************************** STATIC ***********************************/ | ||
86 | /******************************************************************************/ | ||
87 | |||
88 | /** | 59 | /** |
89 | * Process each hello message received from peerinfo. | 60 | * Process each hello message received from peerinfo. |
90 | * | 61 | * |
@@ -94,31 +65,37 @@ struct GNUNET_PEERINFO_NotifyContext* nc; | |||
94 | * @param err_msg Error message. | 65 | * @param err_msg Error message. |
95 | */ | 66 | */ |
96 | static void | 67 | static void |
97 | got_hello (void *cls, const struct GNUNET_PeerIdentity *id, | 68 | got_hello (void *cls, |
69 | const struct GNUNET_PeerIdentity *id, | ||
98 | const struct GNUNET_HELLO_Message *hello, | 70 | const struct GNUNET_HELLO_Message *hello, |
99 | const char *err_msg) | 71 | const char *err_msg) |
100 | { | 72 | { |
101 | struct CadetPeer *peer; | 73 | struct CadetPeer *peer; |
102 | 74 | ||
103 | if (NULL == id || NULL == hello) | 75 | if ( (NULL == id) || |
76 | (NULL == hello) ) | ||
77 | return; | ||
78 | if (0 == memcmp (id, | ||
79 | &my_full_id, | ||
80 | sizeof (struct GNUNET_PeerIdentity))) | ||
104 | { | 81 | { |
105 | LOG (GNUNET_ERROR_TYPE_DEBUG, " hello with id %p and msg %p\n", id, hello); | 82 | GNUNET_free_non_null (mine); |
83 | mine = (struct GNUNET_HELLO_Message *) GNUNET_copy_message (&hello->header); | ||
84 | GCD_hello_update (); | ||
106 | return; | 85 | return; |
107 | } | 86 | } |
108 | LOG (GNUNET_ERROR_TYPE_DEBUG, " hello for %s (%d bytes), expires on %s\n", | ||
109 | GNUNET_i2s (id), GNUNET_HELLO_size (hello), | ||
110 | GNUNET_STRINGS_absolute_time_to_string (GNUNET_HELLO_get_last_expiration(hello))); | ||
111 | peer = GCP_get (id, GNUNET_YES); | ||
112 | GCP_set_hello (peer, hello); | ||
113 | |||
114 | if (GCP_get_short_id (peer) == myid) | ||
115 | mine = GCP_get_hello (peer); | ||
116 | } | ||
117 | 87 | ||
88 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
89 | "Hello for %s (%d bytes), expires on %s\n", | ||
90 | GNUNET_i2s (id), | ||
91 | GNUNET_HELLO_size (hello), | ||
92 | GNUNET_STRINGS_absolute_time_to_string (GNUNET_HELLO_get_last_expiration (hello))); | ||
93 | peer = GCP_get (id, | ||
94 | GNUNET_YES); | ||
95 | GCP_set_hello (peer, | ||
96 | hello); | ||
97 | } | ||
118 | 98 | ||
119 | /******************************************************************************/ | ||
120 | /******************************** API ***********************************/ | ||
121 | /******************************************************************************/ | ||
122 | 99 | ||
123 | /** | 100 | /** |
124 | * Initialize the hello subsystem. | 101 | * Initialize the hello subsystem. |
@@ -128,10 +105,12 @@ got_hello (void *cls, const struct GNUNET_PeerIdentity *id, | |||
128 | void | 105 | void |
129 | GCH_init (const struct GNUNET_CONFIGURATION_Handle *c) | 106 | GCH_init (const struct GNUNET_CONFIGURATION_Handle *c) |
130 | { | 107 | { |
131 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
132 | GNUNET_assert (NULL == nc); | 108 | GNUNET_assert (NULL == nc); |
133 | peerinfo = GNUNET_PEERINFO_connect (c); | 109 | peerinfo = GNUNET_PEERINFO_connect (c); |
134 | nc = GNUNET_PEERINFO_notify (c, GNUNET_NO, &got_hello, NULL); | 110 | nc = GNUNET_PEERINFO_notify (c, |
111 | GNUNET_NO, | ||
112 | &got_hello, | ||
113 | NULL); | ||
135 | } | 114 | } |
136 | 115 | ||
137 | 116 | ||
@@ -141,7 +120,6 @@ GCH_init (const struct GNUNET_CONFIGURATION_Handle *c) | |||
141 | void | 120 | void |
142 | GCH_shutdown () | 121 | GCH_shutdown () |
143 | { | 122 | { |
144 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down channels\n"); | ||
145 | if (NULL != nc) | 123 | if (NULL != nc) |
146 | { | 124 | { |
147 | GNUNET_PEERINFO_notify_cancel (nc); | 125 | GNUNET_PEERINFO_notify_cancel (nc); |
@@ -152,6 +130,11 @@ GCH_shutdown () | |||
152 | GNUNET_PEERINFO_disconnect (peerinfo); | 130 | GNUNET_PEERINFO_disconnect (peerinfo); |
153 | peerinfo = NULL; | 131 | peerinfo = NULL; |
154 | } | 132 | } |
133 | if (NULL != mine) | ||
134 | { | ||
135 | GNUNET_free (mine); | ||
136 | mine = NULL; | ||
137 | } | ||
155 | } | 138 | } |
156 | 139 | ||
157 | 140 | ||
@@ -166,35 +149,4 @@ GCH_get_mine (void) | |||
166 | return mine; | 149 | return mine; |
167 | } | 150 | } |
168 | 151 | ||
169 | 152 | /* end of gnunet-service-cadet-new_hello.c */ | |
170 | /** | ||
171 | * Get another peer's hello message. | ||
172 | * | ||
173 | * @param id ID of the peer whose hello message is requested. | ||
174 | * | ||
175 | * @return Hello message, if any (NULL possible). | ||
176 | */ | ||
177 | const struct GNUNET_HELLO_Message * | ||
178 | GCH_get (const struct GNUNET_PeerIdentity *id) | ||
179 | { | ||
180 | struct CadetPeer *p; | ||
181 | |||
182 | p = GCP_get (id, GNUNET_NO); | ||
183 | if (NULL == p) | ||
184 | return NULL; | ||
185 | return GCP_get_hello (p); | ||
186 | } | ||
187 | |||
188 | |||
189 | /** | ||
190 | * Convert a hello message to a string. | ||
191 | * | ||
192 | * @param h Hello message. | ||
193 | */ | ||
194 | char * | ||
195 | GCH_2s (const struct GNUNET_HELLO_Message *h) | ||
196 | { | ||
197 | return "hello (TODO)"; | ||
198 | } | ||
199 | |||
200 | |||
diff --git a/src/cadet/gnunet-service-cadet_hello.h b/src/cadet/gnunet-service-cadet_hello.h index 34121e1e0..4291ae985 100644 --- a/src/cadet/gnunet-service-cadet_hello.h +++ b/src/cadet/gnunet-service-cadet_hello.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2014 GNUnet e.V. | 3 | Copyright (C) 2014, 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -22,8 +22,9 @@ | |||
22 | * @file cadet/gnunet-service-cadet_hello.h | 22 | * @file cadet/gnunet-service-cadet_hello.h |
23 | * @brief cadet service; dealing with hello messages | 23 | * @brief cadet service; dealing with hello messages |
24 | * @author Bartlomiej Polot | 24 | * @author Bartlomiej Polot |
25 | * @author Christian Grothoff | ||
25 | * | 26 | * |
26 | * All functions in this file should use the prefix GMH (Gnunet Cadet Hello) | 27 | * All functions in this file should use the prefix GCH (Gnunet Cadet Hello) |
27 | */ | 28 | */ |
28 | 29 | ||
29 | #ifndef GNUNET_SERVICE_CADET_HELLO_H | 30 | #ifndef GNUNET_SERVICE_CADET_HELLO_H |
diff --git a/src/cadet/gnunet-service-cadet_local.c b/src/cadet/gnunet-service-cadet_local.c deleted file mode 100644 index dea6681df..000000000 --- a/src/cadet/gnunet-service-cadet_local.c +++ /dev/null | |||
@@ -1,1553 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | |||
22 | #include "platform.h" | ||
23 | #include "gnunet_util_lib.h" | ||
24 | |||
25 | #include "gnunet_statistics_service.h" | ||
26 | |||
27 | #include "cadet.h" | ||
28 | #include "cadet_protocol.h" /* GNUNET_CADET_Data is shared */ | ||
29 | |||
30 | #include "gnunet-service-cadet_local.h" | ||
31 | #include "gnunet-service-cadet_channel.h" | ||
32 | |||
33 | /* INFO DEBUG */ | ||
34 | #include "gnunet-service-cadet_tunnel.h" | ||
35 | #include "gnunet-service-cadet_peer.h" | ||
36 | |||
37 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-loc",__VA_ARGS__) | ||
38 | |||
39 | /******************************************************************************/ | ||
40 | /******************************** STRUCTS **********************************/ | ||
41 | /******************************************************************************/ | ||
42 | |||
43 | /** | ||
44 | * Struct containing information about a client of the service | ||
45 | * | ||
46 | * TODO: add a list of 'waiting' ports | ||
47 | */ | ||
48 | struct CadetClient | ||
49 | { | ||
50 | /** | ||
51 | * Linked list next | ||
52 | */ | ||
53 | struct CadetClient *next; | ||
54 | |||
55 | /** | ||
56 | * Linked list prev | ||
57 | */ | ||
58 | struct CadetClient *prev; | ||
59 | |||
60 | /** | ||
61 | * Tunnels that belong to this client, indexed by local id | ||
62 | */ | ||
63 | struct GNUNET_CONTAINER_MultiHashMap32 *own_channels; | ||
64 | |||
65 | /** | ||
66 | * Tunnels this client has accepted, indexed by incoming local id | ||
67 | */ | ||
68 | struct GNUNET_CONTAINER_MultiHashMap32 *incoming_channels; | ||
69 | |||
70 | /** | ||
71 | * Channel ID for the next incoming channel. | ||
72 | */ | ||
73 | struct GNUNET_CADET_ClientChannelNumber next_ccn; | ||
74 | |||
75 | /** | ||
76 | * Handle to communicate with the client | ||
77 | */ | ||
78 | struct GNUNET_SERVER_Client *handle; | ||
79 | |||
80 | /** | ||
81 | * Ports that this client has declared interest in. | ||
82 | * Indexed by port, contains *Client. | ||
83 | */ | ||
84 | struct GNUNET_CONTAINER_MultiHashMap *ports; | ||
85 | |||
86 | /** | ||
87 | * Whether the client is active or shutting down (don't send confirmations | ||
88 | * to a client that is shutting down. | ||
89 | */ | ||
90 | int shutting_down; | ||
91 | |||
92 | /** | ||
93 | * ID of the client, mainly for debug messages | ||
94 | */ | ||
95 | unsigned int id; | ||
96 | }; | ||
97 | |||
98 | /******************************************************************************/ | ||
99 | /******************************* GLOBALS ***********************************/ | ||
100 | /******************************************************************************/ | ||
101 | |||
102 | /** | ||
103 | * Global handle to the statistics service. | ||
104 | */ | ||
105 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
106 | |||
107 | /** | ||
108 | * Handle to server lib. | ||
109 | */ | ||
110 | static struct GNUNET_SERVER_Handle *server_handle; | ||
111 | |||
112 | /** | ||
113 | * DLL with all the clients, head. | ||
114 | */ | ||
115 | static struct CadetClient *clients_head; | ||
116 | |||
117 | /** | ||
118 | * DLL with all the clients, tail. | ||
119 | */ | ||
120 | static struct CadetClient *clients_tail; | ||
121 | |||
122 | /** | ||
123 | * Next ID to assign to a client. | ||
124 | */ | ||
125 | unsigned int next_client_id; | ||
126 | |||
127 | /** | ||
128 | * All ports clients of this peer have opened. | ||
129 | */ | ||
130 | static struct GNUNET_CONTAINER_MultiHashMap *ports; | ||
131 | |||
132 | /** | ||
133 | * Notification context, to send messages to local clients. | ||
134 | */ | ||
135 | static struct GNUNET_SERVER_NotificationContext *nc; | ||
136 | |||
137 | |||
138 | /******************************************************************************/ | ||
139 | /******************************** STATIC ***********************************/ | ||
140 | /******************************************************************************/ | ||
141 | |||
142 | /** | ||
143 | * Remove client's ports from the global hashmap on disconnect. | ||
144 | * | ||
145 | * @param cls Closure (unused). | ||
146 | * @param key Port. | ||
147 | * @param value Client structure. | ||
148 | * | ||
149 | * @return #GNUNET_OK, keep iterating. | ||
150 | */ | ||
151 | static int | ||
152 | client_release_ports (void *cls, | ||
153 | const struct GNUNET_HashCode *key, | ||
154 | void *value) | ||
155 | { | ||
156 | int res; | ||
157 | |||
158 | res = GNUNET_CONTAINER_multihashmap_remove (ports, key, value); | ||
159 | if (GNUNET_YES != res) | ||
160 | { | ||
161 | GNUNET_break (0); | ||
162 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
163 | "Port %s by client %p was not registered.\n", | ||
164 | GNUNET_h2s (key), value); | ||
165 | } | ||
166 | return GNUNET_OK; | ||
167 | } | ||
168 | |||
169 | |||
170 | /** | ||
171 | * Iterator for deleting each channel whose client endpoint disconnected. | ||
172 | * | ||
173 | * @param cls Closure (client that has disconnected). | ||
174 | * @param key The local channel id (used to access the hashmap). | ||
175 | * @param value The value stored at the key (channel to destroy). | ||
176 | * | ||
177 | * @return #GNUNET_OK, keep iterating. | ||
178 | */ | ||
179 | static int | ||
180 | channel_destroy_iterator (void *cls, | ||
181 | uint32_t key, | ||
182 | void *value) | ||
183 | { | ||
184 | struct CadetChannel *ch = value; | ||
185 | struct CadetClient *c = cls; | ||
186 | |||
187 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
188 | " Channel %s destroy, due to client %s shutdown.\n", | ||
189 | GCCH_2s (ch), GML_2s (c)); | ||
190 | |||
191 | GCCH_handle_local_destroy (ch, | ||
192 | c, | ||
193 | key < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
194 | return GNUNET_OK; | ||
195 | } | ||
196 | |||
197 | |||
198 | /** | ||
199 | * Unregister data and free memory for a client. | ||
200 | * | ||
201 | * @param c Client to destroy. No longer valid after call. | ||
202 | */ | ||
203 | static void | ||
204 | client_destroy (struct CadetClient *c) | ||
205 | { | ||
206 | LOG (GNUNET_ERROR_TYPE_DEBUG, " client destroy: %p/%u\n", c, c->id); | ||
207 | GNUNET_SERVER_client_drop (c->handle); | ||
208 | c->shutting_down = GNUNET_YES; | ||
209 | |||
210 | if (NULL != c->own_channels) | ||
211 | { | ||
212 | GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels, | ||
213 | &channel_destroy_iterator, c); | ||
214 | GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels); | ||
215 | } | ||
216 | if (NULL != c->incoming_channels) | ||
217 | { | ||
218 | GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels, | ||
219 | &channel_destroy_iterator, c); | ||
220 | GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels); | ||
221 | } | ||
222 | if (NULL != c->ports) | ||
223 | { | ||
224 | GNUNET_CONTAINER_multihashmap_iterate (c->ports, | ||
225 | &client_release_ports, c); | ||
226 | GNUNET_CONTAINER_multihashmap_destroy (c->ports); | ||
227 | } | ||
228 | |||
229 | GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c); | ||
230 | GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO); | ||
231 | GNUNET_SERVER_client_set_user_context (c->handle, NULL); | ||
232 | GNUNET_free (c); | ||
233 | } | ||
234 | |||
235 | |||
236 | /** | ||
237 | * Create a client record, register data and initialize memory. | ||
238 | * | ||
239 | * @param client Client's handle. | ||
240 | */ | ||
241 | static struct CadetClient * | ||
242 | client_new (struct GNUNET_SERVER_Client *client) | ||
243 | { | ||
244 | struct CadetClient *c; | ||
245 | |||
246 | GNUNET_SERVER_client_keep (client); | ||
247 | GNUNET_SERVER_notification_context_add (nc, client); | ||
248 | |||
249 | c = GNUNET_new (struct CadetClient); | ||
250 | c->handle = client; | ||
251 | c->id = next_client_id++; /* overflow not important: just for debug */ | ||
252 | |||
253 | c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32); | ||
254 | c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32); | ||
255 | |||
256 | GNUNET_SERVER_client_set_user_context (client, c); | ||
257 | GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c); | ||
258 | GNUNET_STATISTICS_update (stats, "# clients", +1, GNUNET_NO); | ||
259 | |||
260 | LOG (GNUNET_ERROR_TYPE_DEBUG, " client created: %p/%u\n", c, c->id); | ||
261 | |||
262 | return c; | ||
263 | } | ||
264 | |||
265 | |||
266 | /******************************************************************************/ | ||
267 | /******************************** HANDLES ***********************************/ | ||
268 | /******************************************************************************/ | ||
269 | |||
270 | /** | ||
271 | * Handler for client connection. | ||
272 | * | ||
273 | * @param cls Closure (unused). | ||
274 | * @param client Client handler. | ||
275 | */ | ||
276 | static void | ||
277 | handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client) | ||
278 | { | ||
279 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Client connected: %p\n", client); | ||
280 | if (NULL == client) | ||
281 | return; | ||
282 | |||
283 | (void) client_new (client); | ||
284 | } | ||
285 | |||
286 | |||
287 | /** | ||
288 | * Handler for client disconnection | ||
289 | * | ||
290 | * @param cls closure | ||
291 | * @param client identification of the client; NULL | ||
292 | * for the last call when the server is destroyed | ||
293 | */ | ||
294 | static void | ||
295 | handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | ||
296 | { | ||
297 | struct CadetClient *c; | ||
298 | |||
299 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Client disconnected: %p\n", client); | ||
300 | |||
301 | c = GML_client_get (client); | ||
302 | if (NULL != c) | ||
303 | { | ||
304 | LOG (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u, %p)\n", | ||
305 | c->id, c); | ||
306 | client_destroy (c); | ||
307 | } | ||
308 | else | ||
309 | { | ||
310 | LOG (GNUNET_ERROR_TYPE_DEBUG, " disconnecting client's context NULL\n"); | ||
311 | } | ||
312 | return; | ||
313 | } | ||
314 | |||
315 | |||
316 | /** | ||
317 | * Handler for port open requests. | ||
318 | * | ||
319 | * @param cls Closure. | ||
320 | * @param client Identification of the client. | ||
321 | * @param message The actual message. | ||
322 | */ | ||
323 | static void | ||
324 | handle_port_open (void *cls, struct GNUNET_SERVER_Client *client, | ||
325 | const struct GNUNET_MessageHeader *message) | ||
326 | { | ||
327 | struct CadetClient *c; | ||
328 | struct GNUNET_CADET_PortMessage *pmsg; | ||
329 | |||
330 | LOG (GNUNET_ERROR_TYPE_DEBUG, "open port requested\n"); | ||
331 | |||
332 | /* Sanity check for client registration */ | ||
333 | if (NULL == (c = GML_client_get (client))) | ||
334 | { | ||
335 | GNUNET_break (0); | ||
336 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
337 | return; | ||
338 | } | ||
339 | LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); | ||
340 | |||
341 | /* Message size sanity check */ | ||
342 | if (sizeof (struct GNUNET_CADET_PortMessage) != ntohs (message->size)) | ||
343 | { | ||
344 | GNUNET_break (0); | ||
345 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
346 | return; | ||
347 | } | ||
348 | |||
349 | pmsg = (struct GNUNET_CADET_PortMessage *) message; | ||
350 | if (NULL == c->ports) | ||
351 | { | ||
352 | c->ports = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO); | ||
353 | } | ||
354 | /* store in client's hashmap */ | ||
355 | if (GNUNET_OK != | ||
356 | GNUNET_CONTAINER_multihashmap_put (c->ports, &pmsg->port, c, | ||
357 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
358 | { | ||
359 | GNUNET_break (0); | ||
360 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
361 | return; | ||
362 | } | ||
363 | /* store in global hashmap */ | ||
364 | /* FIXME only allow one client to have the port open, | ||
365 | * have a backup hashmap with waiting clients */ | ||
366 | GNUNET_CONTAINER_multihashmap_put (ports, &pmsg->port, c, | ||
367 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
368 | |||
369 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
370 | } | ||
371 | |||
372 | |||
373 | /** | ||
374 | * Handler for port close requests. | ||
375 | * | ||
376 | * @param cls Closure. | ||
377 | * @param client Identification of the client. | ||
378 | * @param message The actual message. | ||
379 | */ | ||
380 | static void | ||
381 | handle_port_close (void *cls, struct GNUNET_SERVER_Client *client, | ||
382 | const struct GNUNET_MessageHeader *message) | ||
383 | { | ||
384 | struct CadetClient *c; | ||
385 | struct GNUNET_CADET_PortMessage *pmsg; | ||
386 | int removed; | ||
387 | |||
388 | LOG (GNUNET_ERROR_TYPE_DEBUG, "close port requested\n"); | ||
389 | |||
390 | /* Sanity check for client registration */ | ||
391 | if (NULL == (c = GML_client_get (client))) | ||
392 | { | ||
393 | GNUNET_break (0); | ||
394 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
395 | return; | ||
396 | } | ||
397 | LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); | ||
398 | |||
399 | /* Message size sanity check */ | ||
400 | if (sizeof (struct GNUNET_CADET_PortMessage) != ntohs (message->size)) | ||
401 | { | ||
402 | GNUNET_break (0); | ||
403 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
404 | return; | ||
405 | } | ||
406 | |||
407 | pmsg = (struct GNUNET_CADET_PortMessage *) message; | ||
408 | removed = GNUNET_CONTAINER_multihashmap_remove (c->ports, &pmsg->port, c); | ||
409 | GNUNET_break_op (GNUNET_YES == removed); | ||
410 | removed = GNUNET_CONTAINER_multihashmap_remove (ports, &pmsg->port, c); | ||
411 | GNUNET_break_op (GNUNET_YES == removed); | ||
412 | |||
413 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
414 | } | ||
415 | |||
416 | |||
417 | /** | ||
418 | * Handler for requests of new channels. | ||
419 | * | ||
420 | * @param cls Closure. | ||
421 | * @param client Identification of the client. | ||
422 | * @param message The actual message. | ||
423 | */ | ||
424 | static void | ||
425 | handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client, | ||
426 | const struct GNUNET_MessageHeader *message) | ||
427 | { | ||
428 | struct CadetClient *c; | ||
429 | |||
430 | LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); | ||
431 | LOG (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n"); | ||
432 | |||
433 | /* Sanity check for client registration */ | ||
434 | if (NULL == (c = GML_client_get (client))) | ||
435 | { | ||
436 | GNUNET_break (0); | ||
437 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
438 | return; | ||
439 | } | ||
440 | LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); | ||
441 | |||
442 | /* Message size sanity check */ | ||
443 | if (sizeof (struct GNUNET_CADET_LocalChannelCreateMessage) | ||
444 | != ntohs (message->size)) | ||
445 | { | ||
446 | GNUNET_break (0); | ||
447 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
448 | return; | ||
449 | } | ||
450 | |||
451 | if (GNUNET_OK != | ||
452 | GCCH_handle_local_create (c, | ||
453 | (struct GNUNET_CADET_LocalChannelCreateMessage *) | ||
454 | message)) | ||
455 | { | ||
456 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
457 | return; | ||
458 | } | ||
459 | |||
460 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
461 | } | ||
462 | |||
463 | |||
464 | /** | ||
465 | * Handler for requests of deleting tunnels | ||
466 | * | ||
467 | * @param cls closure | ||
468 | * @param client identification of the client | ||
469 | * @param message the actual message | ||
470 | */ | ||
471 | static void | ||
472 | handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client, | ||
473 | const struct GNUNET_MessageHeader *message) | ||
474 | { | ||
475 | const struct GNUNET_CADET_LocalChannelDestroyMessage *msg; | ||
476 | struct CadetClient *c; | ||
477 | struct CadetChannel *ch; | ||
478 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
479 | |||
480 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n"); | ||
481 | |||
482 | /* Sanity check for client registration */ | ||
483 | if (NULL == (c = GML_client_get (client))) | ||
484 | { | ||
485 | GNUNET_break (0); | ||
486 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
487 | return; | ||
488 | } | ||
489 | LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); | ||
490 | |||
491 | /* Message sanity check */ | ||
492 | if (sizeof (struct GNUNET_CADET_LocalChannelDestroyMessage) | ||
493 | != ntohs (message->size)) | ||
494 | { | ||
495 | GNUNET_break (0); | ||
496 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
497 | return; | ||
498 | } | ||
499 | |||
500 | msg = (const struct GNUNET_CADET_LocalChannelDestroyMessage *) message; | ||
501 | |||
502 | /* Retrieve tunnel */ | ||
503 | ccn = msg->ccn; | ||
504 | ch = GML_channel_get (c, ccn); | ||
505 | |||
506 | LOG (GNUNET_ERROR_TYPE_INFO, "Client %u is destroying channel %X\n", | ||
507 | c->id, ccn); | ||
508 | |||
509 | if (NULL == ch) | ||
510 | { | ||
511 | LOG (GNUNET_ERROR_TYPE_WARNING, " channel %X not found\n", ccn); | ||
512 | GNUNET_STATISTICS_update (stats, | ||
513 | "# client destroy messages on unknown channel", | ||
514 | 1, GNUNET_NO); | ||
515 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
516 | return; | ||
517 | } | ||
518 | |||
519 | GCCH_handle_local_destroy (ch, | ||
520 | c, | ||
521 | ntohl (ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
522 | |||
523 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
524 | } | ||
525 | |||
526 | |||
527 | /** | ||
528 | * Handler for client traffic | ||
529 | * | ||
530 | * @param cls closure | ||
531 | * @param client identification of the client | ||
532 | * @param message the actual message | ||
533 | */ | ||
534 | static void | ||
535 | handle_data (void *cls, struct GNUNET_SERVER_Client *client, | ||
536 | const struct GNUNET_MessageHeader *message) | ||
537 | { | ||
538 | const struct GNUNET_MessageHeader *payload; | ||
539 | struct GNUNET_CADET_LocalData *msg; | ||
540 | struct CadetClient *c; | ||
541 | struct CadetChannel *ch; | ||
542 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
543 | size_t message_size; | ||
544 | size_t payload_size; | ||
545 | size_t payload_claimed_size; | ||
546 | int fwd; | ||
547 | |||
548 | LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); | ||
549 | LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); | ||
550 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got data from a client\n"); | ||
551 | |||
552 | /* Sanity check for client registration */ | ||
553 | if (NULL == (c = GML_client_get (client))) | ||
554 | { | ||
555 | GNUNET_break (0); | ||
556 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
557 | return; | ||
558 | } | ||
559 | |||
560 | /* Sanity check for message size */ | ||
561 | message_size = ntohs (message->size); | ||
562 | if (sizeof (struct GNUNET_CADET_LocalData) | ||
563 | + sizeof (struct GNUNET_MessageHeader) > message_size | ||
564 | || GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < message_size) | ||
565 | { | ||
566 | GNUNET_break (0); | ||
567 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | /* Sanity check for payload size */ | ||
572 | payload_size = message_size - sizeof (struct GNUNET_CADET_LocalData); | ||
573 | msg = (struct GNUNET_CADET_LocalData *) message; | ||
574 | payload = (struct GNUNET_MessageHeader *) &msg[1]; | ||
575 | payload_claimed_size = ntohs (payload->size); | ||
576 | if (sizeof (struct GNUNET_MessageHeader) > payload_claimed_size | ||
577 | || GNUNET_CONSTANTS_MAX_CADET_MESSAGE_SIZE < payload_claimed_size | ||
578 | || payload_claimed_size > payload_size) | ||
579 | { | ||
580 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
581 | "client claims to send %u bytes in %u payload\n", | ||
582 | payload_claimed_size, payload_size); | ||
583 | GNUNET_break (0); | ||
584 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
585 | return; | ||
586 | } | ||
587 | |||
588 | ccn = msg->ccn; | ||
589 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %u bytes (%u payload) by client %u\n", | ||
590 | payload_size, payload_claimed_size, c->id); | ||
591 | |||
592 | /* Channel exists? */ | ||
593 | fwd = ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; | ||
594 | ch = GML_channel_get (c, ccn); | ||
595 | if (NULL == ch) | ||
596 | { | ||
597 | GNUNET_STATISTICS_update (stats, | ||
598 | "# client data messages on unknown channel", | ||
599 | 1, GNUNET_NO); | ||
600 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
601 | return; | ||
602 | } | ||
603 | |||
604 | if (GNUNET_OK != GCCH_handle_local_data (ch, c, fwd, payload, payload_size)) | ||
605 | { | ||
606 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
607 | return; | ||
608 | } | ||
609 | |||
610 | LOG (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n"); | ||
611 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
612 | |||
613 | return; | ||
614 | } | ||
615 | |||
616 | |||
617 | /** | ||
618 | * Handler for client's ACKs for payload traffic. | ||
619 | * | ||
620 | * @param cls Closure (unused). | ||
621 | * @param client Identification of the client. | ||
622 | * @param message The actual message. | ||
623 | */ | ||
624 | static void | ||
625 | handle_ack (void *cls, struct GNUNET_SERVER_Client *client, | ||
626 | const struct GNUNET_MessageHeader *message) | ||
627 | { | ||
628 | struct GNUNET_CADET_LocalAck *msg; | ||
629 | struct CadetChannel *ch; | ||
630 | struct CadetClient *c; | ||
631 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
632 | int fwd; | ||
633 | |||
634 | LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); | ||
635 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n"); | ||
636 | |||
637 | /* Sanity check for client registration */ | ||
638 | if (NULL == (c = GML_client_get (client))) | ||
639 | { | ||
640 | GNUNET_break (0); | ||
641 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
642 | return; | ||
643 | } | ||
644 | LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); | ||
645 | |||
646 | msg = (struct GNUNET_CADET_LocalAck *) message; | ||
647 | |||
648 | /* Channel exists? */ | ||
649 | ccn = msg->ccn; | ||
650 | LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", | ||
651 | ntohl (ccn.channel_of_client)); | ||
652 | ch = GML_channel_get (c, ccn); | ||
653 | LOG (GNUNET_ERROR_TYPE_DEBUG, " -- ch %p\n", ch); | ||
654 | if (NULL == ch) | ||
655 | { | ||
656 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
657 | "Channel %X unknown.\n", | ||
658 | ntohl (ccn.channel_of_client)); | ||
659 | LOG (GNUNET_ERROR_TYPE_DEBUG, " for client %u.\n", c->id); | ||
660 | GNUNET_STATISTICS_update (stats, | ||
661 | "# client ack messages on unknown channel", | ||
662 | 1, GNUNET_NO); | ||
663 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
664 | return; | ||
665 | } | ||
666 | |||
667 | /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */ | ||
668 | /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */ | ||
669 | fwd = ntohl (ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; | ||
670 | |||
671 | GCCH_handle_local_ack (ch, fwd); | ||
672 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
673 | } | ||
674 | |||
675 | |||
676 | /** | ||
677 | * Iterator over all peers to send a monitoring client info about each peer. | ||
678 | * | ||
679 | * @param cls Closure (). | ||
680 | * @param peer Peer ID (tunnel remote peer). | ||
681 | * @param value Peer info. | ||
682 | * | ||
683 | * @return #GNUNET_YES, to keep iterating. | ||
684 | */ | ||
685 | static int | ||
686 | get_all_peers_iterator (void *cls, | ||
687 | const struct GNUNET_PeerIdentity * peer, | ||
688 | void *value) | ||
689 | { | ||
690 | struct GNUNET_SERVER_Client *client = cls; | ||
691 | struct CadetPeer *p = value; | ||
692 | struct GNUNET_CADET_LocalInfoPeer msg; | ||
693 | |||
694 | msg.header.size = htons (sizeof (msg)); | ||
695 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
696 | msg.destination = *peer; | ||
697 | msg.paths = htons (GCP_count_paths (p)); | ||
698 | msg.tunnel = htons (NULL != GCP_get_tunnel (p)); | ||
699 | |||
700 | LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about peer %s\n", | ||
701 | GNUNET_i2s (peer)); | ||
702 | |||
703 | GNUNET_SERVER_notification_context_unicast (nc, client, | ||
704 | &msg.header, GNUNET_NO); | ||
705 | return GNUNET_YES; | ||
706 | } | ||
707 | |||
708 | |||
709 | /** | ||
710 | * Iterator over all peers to dump info for each peer. | ||
711 | * | ||
712 | * @param cls Closure (unused). | ||
713 | * @param peer Peer ID (tunnel remote peer). | ||
714 | * @param value Peer info. | ||
715 | * | ||
716 | * @return #GNUNET_YES, to keep iterating. | ||
717 | */ | ||
718 | static int | ||
719 | show_peer_iterator (void *cls, | ||
720 | const struct GNUNET_PeerIdentity * peer, | ||
721 | void *value) | ||
722 | { | ||
723 | struct CadetPeer *p = value; | ||
724 | struct CadetTunnel *t; | ||
725 | |||
726 | t = GCP_get_tunnel (p); | ||
727 | if (NULL != t) | ||
728 | GCT_debug (t, GNUNET_ERROR_TYPE_ERROR); | ||
729 | |||
730 | LOG (GNUNET_ERROR_TYPE_ERROR, "\n"); | ||
731 | |||
732 | return GNUNET_YES; | ||
733 | } | ||
734 | |||
735 | |||
736 | /** | ||
737 | * Iterator over all paths of a peer to build an InfoPeer message. | ||
738 | * | ||
739 | * Message contains blocks of peers, first not included. | ||
740 | * | ||
741 | * @param cls Closure (message to build). | ||
742 | * @param peer Peer this path is towards. | ||
743 | * @param path Path itself | ||
744 | * @return #GNUNET_YES if should keep iterating. | ||
745 | * #GNUNET_NO otherwise. | ||
746 | */ | ||
747 | static int | ||
748 | path_info_iterator (void *cls, | ||
749 | struct CadetPeer *peer, | ||
750 | struct CadetPeerPath *path) | ||
751 | { | ||
752 | struct GNUNET_CADET_LocalInfoPeer *resp = cls; | ||
753 | struct GNUNET_PeerIdentity *id; | ||
754 | uint16_t msg_size; | ||
755 | uint16_t path_size; | ||
756 | unsigned int i; | ||
757 | |||
758 | msg_size = ntohs (resp->header.size); | ||
759 | path_size = sizeof (struct GNUNET_PeerIdentity) * (path->length - 1); | ||
760 | |||
761 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Info Path %u\n", path->length); | ||
762 | if (msg_size + path_size > UINT16_MAX) | ||
763 | { | ||
764 | LOG (GNUNET_ERROR_TYPE_WARNING, "path too long for info message\n"); | ||
765 | return GNUNET_NO; | ||
766 | } | ||
767 | |||
768 | i = msg_size - sizeof (struct GNUNET_CADET_LocalInfoPeer); | ||
769 | i = i / sizeof (struct GNUNET_PeerIdentity); | ||
770 | |||
771 | /* Set id to the address of the first free peer slot. */ | ||
772 | id = (struct GNUNET_PeerIdentity *) &resp[1]; | ||
773 | id = &id[i]; | ||
774 | |||
775 | /* Don't copy first peers. | ||
776 | * First peer is always the local one. | ||
777 | * Last peer is always the destination (leave as 0, EOL). | ||
778 | */ | ||
779 | for (i = 0; i < path->length - 1; i++) | ||
780 | { | ||
781 | GNUNET_PEER_resolve (path->peers[i + 1], &id[i]); | ||
782 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %s\n", GNUNET_i2s (&id[i])); | ||
783 | } | ||
784 | |||
785 | resp->header.size = htons (msg_size + path_size); | ||
786 | |||
787 | return GNUNET_YES; | ||
788 | } | ||
789 | |||
790 | |||
791 | /** | ||
792 | * Handler for client's INFO PEERS request. | ||
793 | * | ||
794 | * @param cls Closure (unused). | ||
795 | * @param client Identification of the client. | ||
796 | * @param message The actual message. | ||
797 | */ | ||
798 | static void | ||
799 | handle_get_peers (void *cls, struct GNUNET_SERVER_Client *client, | ||
800 | const struct GNUNET_MessageHeader *message) | ||
801 | { | ||
802 | struct CadetClient *c; | ||
803 | struct GNUNET_MessageHeader reply; | ||
804 | |||
805 | /* Sanity check for client registration */ | ||
806 | if (NULL == (c = GML_client_get (client))) | ||
807 | { | ||
808 | GNUNET_break (0); | ||
809 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
810 | return; | ||
811 | } | ||
812 | |||
813 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
814 | "Received get peers request from client %u (%p)\n", | ||
815 | c->id, client); | ||
816 | |||
817 | GCP_iterate_all (get_all_peers_iterator, client); | ||
818 | reply.size = htons (sizeof (reply)); | ||
819 | reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
820 | GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO); | ||
821 | |||
822 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
823 | "Get peers request from client %u completed\n", c->id); | ||
824 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
825 | } | ||
826 | |||
827 | |||
828 | /** | ||
829 | * Handler for client's SHOW_PEER request. | ||
830 | * | ||
831 | * @param cls Closure (unused). | ||
832 | * @param client Identification of the client. | ||
833 | * @param message The actual message. | ||
834 | */ | ||
835 | void | ||
836 | handle_show_peer (void *cls, struct GNUNET_SERVER_Client *client, | ||
837 | const struct GNUNET_MessageHeader *message) | ||
838 | { | ||
839 | const struct GNUNET_CADET_LocalInfo *msg; | ||
840 | struct GNUNET_CADET_LocalInfoPeer *resp; | ||
841 | struct CadetPeer *p; | ||
842 | struct CadetClient *c; | ||
843 | unsigned char cbuf[64 * 1024]; | ||
844 | |||
845 | /* Sanity check for client registration */ | ||
846 | if (NULL == (c = GML_client_get (client))) | ||
847 | { | ||
848 | GNUNET_break (0); | ||
849 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
850 | return; | ||
851 | } | ||
852 | |||
853 | msg = (struct GNUNET_CADET_LocalInfo *) message; | ||
854 | resp = (struct GNUNET_CADET_LocalInfoPeer *) cbuf; | ||
855 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
856 | "Received peer info request from client %u for peer %s\n", | ||
857 | c->id, GNUNET_i2s_full (&msg->peer)); | ||
858 | |||
859 | resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); | ||
860 | resp->header.size = htons (sizeof (struct GNUNET_CADET_LocalInfoPeer)); | ||
861 | resp->destination = msg->peer; | ||
862 | p = GCP_get (&msg->peer, GNUNET_NO); | ||
863 | if (NULL == p) | ||
864 | { | ||
865 | /* We don't know the peer */ | ||
866 | |||
867 | LOG (GNUNET_ERROR_TYPE_INFO, "Peer %s unknown\n", | ||
868 | GNUNET_i2s_full (&msg->peer)); | ||
869 | resp->paths = htons (0); | ||
870 | resp->tunnel = htons (NULL != GCP_get_tunnel (p)); | ||
871 | |||
872 | GNUNET_SERVER_notification_context_unicast (nc, client, | ||
873 | &resp->header, | ||
874 | GNUNET_NO); | ||
875 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
876 | return; | ||
877 | } | ||
878 | |||
879 | resp->paths = htons (GCP_count_paths (p)); | ||
880 | resp->tunnel = htons (NULL != GCP_get_tunnel (p)); | ||
881 | GCP_iterate_paths (p, &path_info_iterator, resp); | ||
882 | |||
883 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, | ||
884 | &resp->header, GNUNET_NO); | ||
885 | |||
886 | LOG (GNUNET_ERROR_TYPE_INFO, "Show peer from client %u completed.\n", c->id); | ||
887 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
888 | } | ||
889 | |||
890 | |||
891 | /** | ||
892 | * Iterator over all tunnels to send a monitoring client info about each tunnel. | ||
893 | * | ||
894 | * @param cls Closure (). | ||
895 | * @param peer Peer ID (tunnel remote peer). | ||
896 | * @param value Tunnel info. | ||
897 | * | ||
898 | * @return #GNUNET_YES, to keep iterating. | ||
899 | */ | ||
900 | static int | ||
901 | get_all_tunnels_iterator (void *cls, | ||
902 | const struct GNUNET_PeerIdentity * peer, | ||
903 | void *value) | ||
904 | { | ||
905 | struct GNUNET_SERVER_Client *client = cls; | ||
906 | struct CadetTunnel *t = value; | ||
907 | struct GNUNET_CADET_LocalInfoTunnel msg; | ||
908 | |||
909 | msg.header.size = htons (sizeof (msg)); | ||
910 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
911 | msg.destination = *peer; | ||
912 | msg.channels = htonl (GCT_count_channels (t)); | ||
913 | msg.connections = htonl (GCT_count_any_connections (t)); | ||
914 | msg.cstate = htons ((uint16_t) GCT_get_cstate (t)); | ||
915 | msg.estate = htons ((uint16_t) GCT_get_estate (t)); | ||
916 | |||
917 | LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about tunnel ->%s\n", | ||
918 | GNUNET_i2s (peer)); | ||
919 | |||
920 | GNUNET_SERVER_notification_context_unicast (nc, client, | ||
921 | &msg.header, GNUNET_NO); | ||
922 | return GNUNET_YES; | ||
923 | } | ||
924 | |||
925 | |||
926 | /** | ||
927 | * Handler for client's INFO TUNNELS request. | ||
928 | * | ||
929 | * @param cls Closure (unused). | ||
930 | * @param client Identification of the client. | ||
931 | * @param message The actual message. | ||
932 | */ | ||
933 | static void | ||
934 | handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client, | ||
935 | const struct GNUNET_MessageHeader *message) | ||
936 | { | ||
937 | struct CadetClient *c; | ||
938 | struct GNUNET_MessageHeader reply; | ||
939 | |||
940 | /* Sanity check for client registration */ | ||
941 | if (NULL == (c = GML_client_get (client))) | ||
942 | { | ||
943 | GNUNET_break (0); | ||
944 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
945 | return; | ||
946 | } | ||
947 | |||
948 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
949 | "Received get tunnels request from client %u (%p)\n", | ||
950 | c->id, client); | ||
951 | |||
952 | GCT_iterate_all (get_all_tunnels_iterator, client); | ||
953 | reply.size = htons (sizeof (reply)); | ||
954 | reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
955 | GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO); | ||
956 | |||
957 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
958 | "Get tunnels request from client %u completed\n", c->id); | ||
959 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
960 | } | ||
961 | |||
962 | |||
963 | static void | ||
964 | iter_connection (void *cls, struct CadetConnection *c) | ||
965 | { | ||
966 | struct GNUNET_CADET_LocalInfoTunnel *msg = cls; | ||
967 | struct GNUNET_CADET_ConnectionTunnelIdentifier *h; | ||
968 | |||
969 | h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1]; | ||
970 | h[msg->connections] = *(GCC_get_id (c)); | ||
971 | msg->connections++; | ||
972 | } | ||
973 | |||
974 | static void | ||
975 | iter_channel (void *cls, struct CadetChannel *ch) | ||
976 | { | ||
977 | struct GNUNET_CADET_LocalInfoTunnel *msg = cls; | ||
978 | struct GNUNET_CADET_ConnectionTunnelIdentifier *h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1]; | ||
979 | struct GNUNET_CADET_ChannelTunnelNumber *chn = (struct GNUNET_CADET_ChannelTunnelNumber *) &h[msg->connections]; | ||
980 | |||
981 | chn[msg->channels] = GCCH_get_id (ch); | ||
982 | msg->channels++; | ||
983 | } | ||
984 | |||
985 | |||
986 | /** | ||
987 | * Handler for client's SHOW_TUNNEL request. | ||
988 | * | ||
989 | * @param cls Closure (unused). | ||
990 | * @param client Identification of the client. | ||
991 | * @param message The actual message. | ||
992 | */ | ||
993 | void | ||
994 | handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, | ||
995 | const struct GNUNET_MessageHeader *message) | ||
996 | { | ||
997 | const struct GNUNET_CADET_LocalInfo *msg; | ||
998 | struct GNUNET_CADET_LocalInfoTunnel *resp; | ||
999 | struct CadetClient *c; | ||
1000 | struct CadetTunnel *t; | ||
1001 | unsigned int ch_n; | ||
1002 | unsigned int c_n; | ||
1003 | size_t size; | ||
1004 | |||
1005 | /* Sanity check for client registration */ | ||
1006 | if (NULL == (c = GML_client_get (client))) | ||
1007 | { | ||
1008 | GNUNET_break (0); | ||
1009 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1010 | return; | ||
1011 | } | ||
1012 | |||
1013 | msg = (struct GNUNET_CADET_LocalInfo *) message; | ||
1014 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1015 | "Received tunnel info request from client %u for tunnel %s\n", | ||
1016 | c->id, GNUNET_i2s_full(&msg->peer)); | ||
1017 | |||
1018 | t = GCP_get_tunnel (GCP_get (&msg->peer, GNUNET_NO)); | ||
1019 | if (NULL == t) | ||
1020 | { | ||
1021 | /* We don't know the tunnel */ | ||
1022 | struct GNUNET_CADET_LocalInfoTunnel warn; | ||
1023 | |||
1024 | LOG (GNUNET_ERROR_TYPE_INFO, "Tunnel %s unknown %u\n", | ||
1025 | GNUNET_i2s_full(&msg->peer), sizeof (warn)); | ||
1026 | warn.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
1027 | warn.header.size = htons (sizeof (warn)); | ||
1028 | warn.destination = msg->peer; | ||
1029 | warn.channels = htonl (0); | ||
1030 | warn.connections = htonl (0); | ||
1031 | warn.cstate = htons (0); | ||
1032 | warn.estate = htons (0); | ||
1033 | |||
1034 | GNUNET_SERVER_notification_context_unicast (nc, client, | ||
1035 | &warn.header, | ||
1036 | GNUNET_NO); | ||
1037 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1038 | return; | ||
1039 | } | ||
1040 | |||
1041 | /* Initialize context */ | ||
1042 | ch_n = GCT_count_channels (t); | ||
1043 | c_n = GCT_count_any_connections (t); | ||
1044 | |||
1045 | size = sizeof (struct GNUNET_CADET_LocalInfoTunnel); | ||
1046 | size += c_n * sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier); | ||
1047 | size += ch_n * sizeof (struct GNUNET_CADET_ChannelTunnelNumber); | ||
1048 | |||
1049 | resp = GNUNET_malloc (size); | ||
1050 | resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
1051 | resp->header.size = htons (size); | ||
1052 | resp->destination = msg->peer; | ||
1053 | /* Do not interleave with iterators, iter_channel needs conn in HBO */ | ||
1054 | GCT_iterate_connections (t, &iter_connection, resp); | ||
1055 | GCT_iterate_channels (t, &iter_channel, resp); | ||
1056 | resp->connections = htonl (resp->connections); | ||
1057 | resp->channels = htonl (resp->channels); | ||
1058 | /* Do not interleave end */ | ||
1059 | resp->cstate = htons (GCT_get_cstate (t)); | ||
1060 | resp->estate = htons (GCT_get_estate (t)); | ||
1061 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, | ||
1062 | &resp->header, GNUNET_NO); | ||
1063 | GNUNET_free (resp); | ||
1064 | |||
1065 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1066 | "Show tunnel request from client %u completed. %u conn, %u ch\n", | ||
1067 | c->id, c_n, ch_n); | ||
1068 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1069 | } | ||
1070 | |||
1071 | |||
1072 | /** | ||
1073 | * Handler for client's INFO_DUMP request. | ||
1074 | * | ||
1075 | * @param cls Closure (unused). | ||
1076 | * @param client Identification of the client. | ||
1077 | * @param message The actual message. | ||
1078 | */ | ||
1079 | void | ||
1080 | handle_info_dump (void *cls, struct GNUNET_SERVER_Client *client, | ||
1081 | const struct GNUNET_MessageHeader *message) | ||
1082 | { | ||
1083 | struct CadetClient *c; | ||
1084 | |||
1085 | /* Sanity check for client registration */ | ||
1086 | if (NULL == (c = GML_client_get (client))) | ||
1087 | { | ||
1088 | GNUNET_break (0); | ||
1089 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1090 | return; | ||
1091 | } | ||
1092 | |||
1093 | LOG (GNUNET_ERROR_TYPE_INFO, "Received dump info request from client %u\n", | ||
1094 | c->id); | ||
1095 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1096 | "*************************** DUMP START ***************************\n"); | ||
1097 | |||
1098 | for (c = clients_head; NULL != c; c = c->next) | ||
1099 | { | ||
1100 | LOG (GNUNET_ERROR_TYPE_ERROR, "Client %u (%p), handle: %p\n", | ||
1101 | c->id, c, c->handle); | ||
1102 | if (NULL != c->ports) | ||
1103 | LOG (GNUNET_ERROR_TYPE_ERROR, "\t%3u ports registered\n", | ||
1104 | GNUNET_CONTAINER_multihashmap_size (c->ports)); | ||
1105 | else | ||
1106 | LOG (GNUNET_ERROR_TYPE_ERROR, "\t no ports registered\n"); | ||
1107 | LOG (GNUNET_ERROR_TYPE_ERROR, "\t%3u own channles\n", | ||
1108 | GNUNET_CONTAINER_multihashmap32_size (c->own_channels)); | ||
1109 | LOG (GNUNET_ERROR_TYPE_ERROR, "\t%3u incoming channles\n", | ||
1110 | GNUNET_CONTAINER_multihashmap32_size (c->incoming_channels)); | ||
1111 | } | ||
1112 | LOG (GNUNET_ERROR_TYPE_ERROR, "***************************\n"); | ||
1113 | GCP_iterate_all (&show_peer_iterator, NULL); | ||
1114 | |||
1115 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1116 | "**************************** DUMP END ****************************\n"); | ||
1117 | |||
1118 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1119 | } | ||
1120 | |||
1121 | |||
1122 | /** | ||
1123 | * Functions to handle messages from clients | ||
1124 | */ | ||
1125 | static struct GNUNET_SERVER_MessageHandler client_handlers[] = { | ||
1126 | {&handle_port_open, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_OPEN, | ||
1127 | sizeof (struct GNUNET_CADET_PortMessage)}, | ||
1128 | {&handle_port_close, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_PORT_CLOSE, | ||
1129 | sizeof (struct GNUNET_CADET_PortMessage)}, | ||
1130 | {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE, | ||
1131 | sizeof (struct GNUNET_CADET_LocalChannelCreateMessage)}, | ||
1132 | {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY, | ||
1133 | sizeof (struct GNUNET_CADET_LocalChannelDestroyMessage)}, | ||
1134 | {&handle_data, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, 0}, | ||
1135 | {&handle_ack, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, | ||
1136 | sizeof (struct GNUNET_CADET_LocalAck)}, | ||
1137 | {&handle_get_peers, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, | ||
1138 | sizeof (struct GNUNET_MessageHeader)}, | ||
1139 | {&handle_show_peer, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER, | ||
1140 | sizeof (struct GNUNET_CADET_LocalInfo)}, | ||
1141 | {&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS, | ||
1142 | sizeof (struct GNUNET_MessageHeader)}, | ||
1143 | {&handle_show_tunnel, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL, | ||
1144 | sizeof (struct GNUNET_CADET_LocalInfo)}, | ||
1145 | {&handle_info_dump, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_DUMP, | ||
1146 | sizeof (struct GNUNET_MessageHeader)}, | ||
1147 | {NULL, NULL, 0, 0} | ||
1148 | }; | ||
1149 | |||
1150 | |||
1151 | |||
1152 | /******************************************************************************/ | ||
1153 | /******************************** API ***********************************/ | ||
1154 | /******************************************************************************/ | ||
1155 | |||
1156 | /** | ||
1157 | * Initialize server subsystem. | ||
1158 | * | ||
1159 | * @param handle Server handle. | ||
1160 | */ | ||
1161 | void | ||
1162 | GML_init (struct GNUNET_SERVER_Handle *handle) | ||
1163 | { | ||
1164 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
1165 | server_handle = handle; | ||
1166 | GNUNET_SERVER_suspend (server_handle); | ||
1167 | ports = GNUNET_CONTAINER_multihashmap_create (16, GNUNET_NO); | ||
1168 | } | ||
1169 | |||
1170 | |||
1171 | /** | ||
1172 | * Install server (service) handlers and start listening to clients. | ||
1173 | */ | ||
1174 | void | ||
1175 | GML_start (void) | ||
1176 | { | ||
1177 | GNUNET_SERVER_add_handlers (server_handle, client_handlers); | ||
1178 | GNUNET_SERVER_connect_notify (server_handle, &handle_client_connect, NULL); | ||
1179 | GNUNET_SERVER_disconnect_notify (server_handle, &handle_client_disconnect, | ||
1180 | NULL); | ||
1181 | nc = GNUNET_SERVER_notification_context_create (server_handle, 1); | ||
1182 | |||
1183 | clients_head = NULL; | ||
1184 | clients_tail = NULL; | ||
1185 | next_client_id = 0; | ||
1186 | GNUNET_SERVER_resume (server_handle); | ||
1187 | } | ||
1188 | |||
1189 | |||
1190 | /** | ||
1191 | * Shutdown server. | ||
1192 | */ | ||
1193 | void | ||
1194 | GML_shutdown (void) | ||
1195 | { | ||
1196 | struct CadetClient *c; | ||
1197 | |||
1198 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down local\n"); | ||
1199 | |||
1200 | for (c = clients_head; NULL != clients_head; c = clients_head) | ||
1201 | client_destroy (c); | ||
1202 | |||
1203 | if (nc != NULL) | ||
1204 | { | ||
1205 | GNUNET_SERVER_notification_context_destroy (nc); | ||
1206 | nc = NULL; | ||
1207 | } | ||
1208 | |||
1209 | } | ||
1210 | |||
1211 | |||
1212 | /** | ||
1213 | * Get a channel from a client. | ||
1214 | * | ||
1215 | * @param c Client to check. | ||
1216 | * @param ccn Channel ID, must be local (> 0x800...). | ||
1217 | * | ||
1218 | * @return non-NULL if channel exists in the clients lists | ||
1219 | */ | ||
1220 | struct CadetChannel * | ||
1221 | GML_channel_get (struct CadetClient *c, | ||
1222 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
1223 | { | ||
1224 | struct GNUNET_CONTAINER_MultiHashMap32 *map; | ||
1225 | |||
1226 | if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
1227 | map = c->own_channels; | ||
1228 | else | ||
1229 | map = c->incoming_channels; | ||
1230 | |||
1231 | if (NULL == map) | ||
1232 | { | ||
1233 | GNUNET_break (0); | ||
1234 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1235 | "Client %s does no t have a valid map for CCN %X\n", | ||
1236 | GML_2s (c), ccn); | ||
1237 | return NULL; | ||
1238 | } | ||
1239 | return GNUNET_CONTAINER_multihashmap32_get (map, | ||
1240 | ccn.channel_of_client); | ||
1241 | } | ||
1242 | |||
1243 | |||
1244 | /** | ||
1245 | * Add a channel to a client | ||
1246 | * | ||
1247 | * @param client Client. | ||
1248 | * @param ccn Channel ID. | ||
1249 | * @param ch Channel. | ||
1250 | */ | ||
1251 | void | ||
1252 | GML_channel_add (struct CadetClient *client, | ||
1253 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
1254 | struct CadetChannel *ch) | ||
1255 | { | ||
1256 | if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
1257 | GNUNET_CONTAINER_multihashmap32_put (client->own_channels, | ||
1258 | ccn.channel_of_client, | ||
1259 | ch, | ||
1260 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
1261 | else | ||
1262 | GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels, | ||
1263 | ccn.channel_of_client, | ||
1264 | ch, | ||
1265 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
1266 | } | ||
1267 | |||
1268 | |||
1269 | /** | ||
1270 | * Remove a channel from a client. | ||
1271 | * | ||
1272 | * @param client Client. | ||
1273 | * @param ccn Channel ID. | ||
1274 | * @param ch Channel. | ||
1275 | */ | ||
1276 | void | ||
1277 | GML_channel_remove (struct CadetClient *client, | ||
1278 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
1279 | struct CadetChannel *ch) | ||
1280 | { | ||
1281 | if (ntohl (ccn.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
1282 | GNUNET_CONTAINER_multihashmap32_remove (client->own_channels, | ||
1283 | ccn.channel_of_client, | ||
1284 | ch); | ||
1285 | else | ||
1286 | GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels, | ||
1287 | ccn.channel_of_client, | ||
1288 | ch); | ||
1289 | } | ||
1290 | |||
1291 | |||
1292 | /** | ||
1293 | * Get the tunnel's next free local channel ID. | ||
1294 | * | ||
1295 | * @param c Client. | ||
1296 | * | ||
1297 | * @return LID of a channel free to use. | ||
1298 | */ | ||
1299 | struct GNUNET_CADET_ClientChannelNumber | ||
1300 | GML_get_next_ccn (struct CadetClient *c) | ||
1301 | { | ||
1302 | struct GNUNET_CADET_ClientChannelNumber ccn; | ||
1303 | |||
1304 | while (NULL != GML_channel_get (c, | ||
1305 | c->next_ccn)) | ||
1306 | { | ||
1307 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1308 | "Channel %u exists...\n", | ||
1309 | c->next_ccn); | ||
1310 | c->next_ccn.channel_of_client | ||
1311 | = htonl (1 + (ntohl (c->next_ccn.channel_of_client))); | ||
1312 | if (ntohl (c->next_ccn.channel_of_client) >= | ||
1313 | GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
1314 | c->next_ccn.channel_of_client = htonl (0); | ||
1315 | } | ||
1316 | ccn = c->next_ccn; | ||
1317 | c->next_ccn.channel_of_client | ||
1318 | = htonl (1 + (ntohl (c->next_ccn.channel_of_client))); | ||
1319 | |||
1320 | return ccn; | ||
1321 | } | ||
1322 | |||
1323 | |||
1324 | /** | ||
1325 | * Check if client has registered with the service and has not disconnected | ||
1326 | * | ||
1327 | * @param client the client to check | ||
1328 | * | ||
1329 | * @return non-NULL if client exists in the global DLL | ||
1330 | */ | ||
1331 | struct CadetClient * | ||
1332 | GML_client_get (struct GNUNET_SERVER_Client *client) | ||
1333 | { | ||
1334 | if (NULL == client) | ||
1335 | return NULL; | ||
1336 | return GNUNET_SERVER_client_get_user_context (client, | ||
1337 | struct CadetClient); | ||
1338 | } | ||
1339 | |||
1340 | |||
1341 | /** | ||
1342 | * Find a client that has opened a port | ||
1343 | * | ||
1344 | * @param port Port to check. | ||
1345 | * | ||
1346 | * @return non-NULL if a client has the port. | ||
1347 | */ | ||
1348 | struct CadetClient * | ||
1349 | GML_client_get_by_port (const struct GNUNET_HashCode *port) | ||
1350 | { | ||
1351 | return GNUNET_CONTAINER_multihashmap_get (ports, port); | ||
1352 | } | ||
1353 | |||
1354 | |||
1355 | /** | ||
1356 | * Deletes a channel from a client (either owner or destination). | ||
1357 | * | ||
1358 | * @param c Client whose tunnel to delete. | ||
1359 | * @param ch Channel which should be deleted. | ||
1360 | * @param id Channel ID. | ||
1361 | */ | ||
1362 | void | ||
1363 | GML_client_delete_channel (struct CadetClient *c, | ||
1364 | struct CadetChannel *ch, | ||
1365 | struct GNUNET_CADET_ClientChannelNumber id) | ||
1366 | { | ||
1367 | int res; | ||
1368 | |||
1369 | if (ntohl (id.channel_of_client) >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
1370 | { | ||
1371 | res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels, | ||
1372 | id.channel_of_client, | ||
1373 | ch); | ||
1374 | if (GNUNET_YES != res) | ||
1375 | LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n"); | ||
1376 | } | ||
1377 | else | ||
1378 | { | ||
1379 | res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels, | ||
1380 | id.channel_of_client, | ||
1381 | ch); | ||
1382 | if (GNUNET_YES != res) | ||
1383 | LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n"); | ||
1384 | } | ||
1385 | } | ||
1386 | |||
1387 | /** | ||
1388 | * Build a local ACK message and send it to a local client, if needed. | ||
1389 | * | ||
1390 | * If the client was already allowed to send data, do nothing. | ||
1391 | * | ||
1392 | * @param c Client to whom send the ACK. | ||
1393 | * @param ccn Channel ID to use | ||
1394 | */ | ||
1395 | void | ||
1396 | GML_send_ack (struct CadetClient *c, | ||
1397 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
1398 | { | ||
1399 | struct GNUNET_CADET_LocalAck msg; | ||
1400 | |||
1401 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1402 | "send local %s ack on %X towards %p\n", | ||
1403 | ntohl (ccn.channel_of_client) < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI | ||
1404 | ? "FWD" : "BCK", | ||
1405 | ntohl (ccn.channel_of_client), | ||
1406 | c); | ||
1407 | |||
1408 | msg.header.size = htons (sizeof (msg)); | ||
1409 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | ||
1410 | msg.ccn = ccn; | ||
1411 | GNUNET_SERVER_notification_context_unicast (nc, | ||
1412 | c->handle, | ||
1413 | &msg.header, | ||
1414 | GNUNET_NO); | ||
1415 | |||
1416 | } | ||
1417 | |||
1418 | |||
1419 | |||
1420 | /** | ||
1421 | * Notify the client that a new incoming channel was created. | ||
1422 | * | ||
1423 | * @param c Client to notify. | ||
1424 | * @param ccn Channel ID. | ||
1425 | * @param port Channel's destination port. | ||
1426 | * @param opt Options (bit array). | ||
1427 | * @param peer Origin peer. | ||
1428 | */ | ||
1429 | void | ||
1430 | GML_send_channel_create (struct CadetClient *c, | ||
1431 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
1432 | const struct GNUNET_HashCode *port, | ||
1433 | uint32_t opt, | ||
1434 | const struct GNUNET_PeerIdentity *peer) | ||
1435 | { | ||
1436 | struct GNUNET_CADET_LocalChannelCreateMessage msg; | ||
1437 | |||
1438 | msg.header.size = htons (sizeof (msg)); | ||
1439 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); | ||
1440 | msg.ccn = ccn; | ||
1441 | msg.port = *port; | ||
1442 | msg.opt = htonl (opt); | ||
1443 | msg.peer = *peer; | ||
1444 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, | ||
1445 | &msg.header, GNUNET_NO); | ||
1446 | } | ||
1447 | |||
1448 | |||
1449 | /** | ||
1450 | * Build a local channel NACK message and send it to a local client. | ||
1451 | * | ||
1452 | * @param c Client to whom send the NACK. | ||
1453 | * @param ccn Channel ID to use | ||
1454 | */ | ||
1455 | void | ||
1456 | GML_send_channel_nack (struct CadetClient *c, | ||
1457 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
1458 | { | ||
1459 | struct GNUNET_CADET_LocalAck msg; | ||
1460 | |||
1461 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1462 | "send local nack on %X towards %p\n", | ||
1463 | ntohl (ccn.channel_of_client), | ||
1464 | c); | ||
1465 | |||
1466 | msg.header.size = htons (sizeof (msg)); | ||
1467 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED); | ||
1468 | msg.ccn = ccn; | ||
1469 | GNUNET_SERVER_notification_context_unicast (nc, | ||
1470 | c->handle, | ||
1471 | &msg.header, | ||
1472 | GNUNET_NO); | ||
1473 | |||
1474 | } | ||
1475 | |||
1476 | /** | ||
1477 | * Notify a client that a channel is no longer valid. | ||
1478 | * | ||
1479 | * @param c Client. | ||
1480 | * @param ccn ID of the channel that is destroyed. | ||
1481 | */ | ||
1482 | void | ||
1483 | GML_send_channel_destroy (struct CadetClient *c, | ||
1484 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
1485 | { | ||
1486 | struct GNUNET_CADET_LocalChannelDestroyMessage msg; | ||
1487 | |||
1488 | if (NULL == c) | ||
1489 | { | ||
1490 | GNUNET_break (0); | ||
1491 | return; | ||
1492 | } | ||
1493 | if (GNUNET_YES == c->shutting_down) | ||
1494 | return; | ||
1495 | msg.header.size = htons (sizeof (msg)); | ||
1496 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY); | ||
1497 | msg.ccn = ccn; | ||
1498 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, | ||
1499 | &msg.header, GNUNET_NO); | ||
1500 | } | ||
1501 | |||
1502 | |||
1503 | /** | ||
1504 | * Modify the cadet message ID from global to local and send to client. | ||
1505 | * | ||
1506 | * @param c Client to send to. | ||
1507 | * @param msg Message to modify and send. | ||
1508 | * @param ccn Channel ID to use (c can be both owner and client). | ||
1509 | */ | ||
1510 | void | ||
1511 | GML_send_data (struct CadetClient *c, | ||
1512 | const struct GNUNET_CADET_ChannelAppDataMessage *msg, | ||
1513 | struct GNUNET_CADET_ClientChannelNumber ccn) | ||
1514 | { | ||
1515 | struct GNUNET_CADET_LocalData *copy; | ||
1516 | uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_CADET_ChannelAppDataMessage); | ||
1517 | char cbuf[size + sizeof (struct GNUNET_CADET_LocalData)]; | ||
1518 | |||
1519 | if (size < sizeof (struct GNUNET_MessageHeader)) | ||
1520 | { | ||
1521 | GNUNET_break_op (0); | ||
1522 | return; | ||
1523 | } | ||
1524 | if (NULL == c) | ||
1525 | { | ||
1526 | GNUNET_break (0); | ||
1527 | return; | ||
1528 | } | ||
1529 | copy = (struct GNUNET_CADET_LocalData *) cbuf; | ||
1530 | GNUNET_memcpy (©[1], &msg[1], size); | ||
1531 | copy->header.size = htons (sizeof (struct GNUNET_CADET_LocalData) + size); | ||
1532 | copy->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1533 | copy->ccn = ccn; | ||
1534 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, | ||
1535 | ©->header, GNUNET_NO); | ||
1536 | } | ||
1537 | |||
1538 | |||
1539 | /** | ||
1540 | * Get the static string to represent a client. | ||
1541 | * | ||
1542 | * @param c Client. | ||
1543 | * | ||
1544 | * @return Static string for the client. | ||
1545 | */ | ||
1546 | const char * | ||
1547 | GML_2s (const struct CadetClient *c) | ||
1548 | { | ||
1549 | static char buf[32]; | ||
1550 | |||
1551 | SPRINTF (buf, "%u", c->id); | ||
1552 | return buf; | ||
1553 | } | ||
diff --git a/src/cadet/gnunet-service-cadet_local.h b/src/cadet/gnunet-service-cadet_local.h deleted file mode 100644 index 113c2f489..000000000 --- a/src/cadet/gnunet-service-cadet_local.h +++ /dev/null | |||
@@ -1,234 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_local.h | ||
23 | * @brief cadet service; dealing with local clients | ||
24 | * @author Bartlomiej Polot | ||
25 | * | ||
26 | * All functions in this file should use the prefix GML (Gnunet Cadet Local) | ||
27 | */ | ||
28 | |||
29 | #ifndef GNUNET_SERVICE_CADET_LOCAL_H | ||
30 | #define GNUNET_SERVICE_CADET_LOCAL_H | ||
31 | |||
32 | #ifdef __cplusplus | ||
33 | extern "C" | ||
34 | { | ||
35 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
36 | } | ||
37 | #endif | ||
38 | #endif | ||
39 | |||
40 | #include "platform.h" | ||
41 | #include "gnunet_util_lib.h" | ||
42 | |||
43 | /** | ||
44 | * Struct containing information about a client of the service | ||
45 | */ | ||
46 | struct CadetClient; | ||
47 | |||
48 | #include "gnunet-service-cadet_channel.h" | ||
49 | |||
50 | /******************************************************************************/ | ||
51 | /******************************** API ***********************************/ | ||
52 | /******************************************************************************/ | ||
53 | |||
54 | /** | ||
55 | * Initialize server subsystem. | ||
56 | * | ||
57 | * @param handle Server handle. | ||
58 | */ | ||
59 | void | ||
60 | GML_init (struct GNUNET_SERVER_Handle *handle); | ||
61 | |||
62 | /** | ||
63 | * Install server (service) handlers and start listening to clients. | ||
64 | */ | ||
65 | void | ||
66 | GML_start (void); | ||
67 | |||
68 | /** | ||
69 | * Shutdown server. | ||
70 | */ | ||
71 | void | ||
72 | GML_shutdown (void); | ||
73 | |||
74 | /** | ||
75 | * Get a channel from a client. | ||
76 | * | ||
77 | * @param c Client to check. | ||
78 | * @param ccn Channel ID, must be local (> 0x800...). | ||
79 | * | ||
80 | * @return non-NULL if channel exists in the clients lists | ||
81 | */ | ||
82 | struct CadetChannel * | ||
83 | GML_channel_get (struct CadetClient *c, | ||
84 | struct GNUNET_CADET_ClientChannelNumber ccn); | ||
85 | |||
86 | /** | ||
87 | * Add a channel to a client | ||
88 | * | ||
89 | * @param client Client. | ||
90 | * @param ccn Channel ID. | ||
91 | * @param ch Channel. | ||
92 | */ | ||
93 | void | ||
94 | GML_channel_add (struct CadetClient *client, | ||
95 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
96 | struct CadetChannel *ch); | ||
97 | |||
98 | /** | ||
99 | * Remove a channel from a client | ||
100 | * | ||
101 | * @param client Client. | ||
102 | * @param ccn Channel ID. | ||
103 | * @param ch Channel. | ||
104 | */ | ||
105 | void | ||
106 | GML_channel_remove (struct CadetClient *client, | ||
107 | struct GNUNET_CADET_ClientChannelNumber ccn, | ||
108 | struct CadetChannel *ch); | ||
109 | |||
110 | /** | ||
111 | * Get the tunnel's next free local channel ID. | ||
112 | * | ||
113 | * @param c Client. | ||
114 | * | ||
115 | * @return LID of a channel free to use. | ||
116 | */ | ||
117 | struct GNUNET_CADET_ClientChannelNumber | ||
118 | GML_get_next_ccn (struct CadetClient *c); | ||
119 | |||
120 | /** | ||
121 | * Check if client has registered with the service and has not disconnected | ||
122 | * | ||
123 | * @param client the client to check | ||
124 | * | ||
125 | * @return non-NULL if client exists in the global DLL | ||
126 | */ | ||
127 | struct CadetClient * | ||
128 | GML_client_get (struct GNUNET_SERVER_Client *client); | ||
129 | |||
130 | /** | ||
131 | * Find a client that has opened a port | ||
132 | * | ||
133 | * @param port Port to check. | ||
134 | * | ||
135 | * @return non-NULL if a client has the port. | ||
136 | */ | ||
137 | struct CadetClient * | ||
138 | GML_client_get_by_port (const struct GNUNET_HashCode *port); | ||
139 | |||
140 | /** | ||
141 | * Deletes a tunnel from a client (either owner or destination). | ||
142 | * | ||
143 | * @param c Client whose tunnel to delete. | ||
144 | * @param ch Channel which should be deleted. | ||
145 | * @param id Channel ID. | ||
146 | */ | ||
147 | void | ||
148 | GML_client_delete_channel (struct CadetClient *c, | ||
149 | struct CadetChannel *ch, | ||
150 | struct GNUNET_CADET_ClientChannelNumber id); | ||
151 | |||
152 | /** | ||
153 | * Build a local ACK message and send it to a local client, if needed. | ||
154 | * | ||
155 | * If the client was already allowed to send data, do nothing. | ||
156 | * | ||
157 | * @param c Client to whom send the ACK. | ||
158 | * @param id Channel ID to use | ||
159 | */ | ||
160 | void | ||
161 | GML_send_ack (struct CadetClient *c, | ||
162 | struct GNUNET_CADET_ClientChannelNumber id); | ||
163 | |||
164 | /** | ||
165 | * Notify the appropriate client that a new incoming channel was created. | ||
166 | * | ||
167 | * @param c Client to notify. | ||
168 | * @param id Channel ID. | ||
169 | * @param port Channel's destination port. | ||
170 | * @param opt Options (bit array). | ||
171 | * @param peer Origin peer. | ||
172 | */ | ||
173 | void | ||
174 | GML_send_channel_create (struct CadetClient *c, | ||
175 | struct GNUNET_CADET_ClientChannelNumber id, | ||
176 | const struct GNUNET_HashCode *port, | ||
177 | uint32_t opt, | ||
178 | const struct GNUNET_PeerIdentity *peer); | ||
179 | |||
180 | /** | ||
181 | * Build a local channel NACK message and send it to a local client. | ||
182 | * | ||
183 | * @param c Client to whom send the NACK. | ||
184 | * @param id Channel ID to use | ||
185 | */ | ||
186 | void | ||
187 | GML_send_channel_nack (struct CadetClient *c, | ||
188 | struct GNUNET_CADET_ClientChannelNumber id); | ||
189 | |||
190 | |||
191 | /** | ||
192 | * Notify a client that a channel is no longer valid. | ||
193 | * | ||
194 | * @param c Client. | ||
195 | * @param id ID of the channel that is destroyed. | ||
196 | */ | ||
197 | void | ||
198 | GML_send_channel_destroy (struct CadetClient *c, | ||
199 | struct GNUNET_CADET_ClientChannelNumber id); | ||
200 | |||
201 | |||
202 | /** | ||
203 | * Modify the cadet message ID from global to local and send to client. | ||
204 | * | ||
205 | * @param c Client to send to. | ||
206 | * @param msg Message to modify and send. | ||
207 | * @param id Channel ID to use (c can be both owner and client). | ||
208 | */ | ||
209 | void | ||
210 | GML_send_data (struct CadetClient *c, | ||
211 | const struct GNUNET_CADET_ChannelAppDataMessage *msg, | ||
212 | struct GNUNET_CADET_ClientChannelNumber id); | ||
213 | |||
214 | /** | ||
215 | * Get the static string to represent a client. | ||
216 | * | ||
217 | * @param c Client. | ||
218 | * | ||
219 | * @return Static string for the client. | ||
220 | */ | ||
221 | const char * | ||
222 | GML_2s (const struct CadetClient *c); | ||
223 | |||
224 | |||
225 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
226 | { | ||
227 | #endif | ||
228 | #ifdef __cplusplus | ||
229 | } | ||
230 | #endif | ||
231 | |||
232 | /* ifndef GNUNET_CADET_SERVICE_LOCAL_H */ | ||
233 | #endif | ||
234 | /* end of gnunet-cadet-service_LOCAL.h */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new_paths.c b/src/cadet/gnunet-service-cadet_paths.c index 685656ec3..13752643c 100644 --- a/src/cadet/gnunet-service-cadet-new_paths.c +++ b/src/cadet/gnunet-service-cadet_paths.c | |||
@@ -18,18 +18,16 @@ | |||
18 | Boston, MA 02110-1301, USA. | 18 | Boston, MA 02110-1301, USA. |
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * @file cadet/gnunet-service-cadet-new_paths.c | 21 | * @file cadet/gnunet-service-cadet_paths.c |
22 | * @brief Information we track per path. | 22 | * @brief Information we track per path. |
23 | * @author Bartlomiej Polot | 23 | * @author Bartlomiej Polot |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * | ||
26 | * TODO: | ||
27 | * - path desirability score calculations are not done | ||
28 | */ | 25 | */ |
29 | #include "platform.h" | 26 | #include "platform.h" |
30 | #include "gnunet-service-cadet-new_connection.h" | 27 | #include "gnunet-service-cadet_connection.h" |
31 | #include "gnunet-service-cadet-new_peer.h" | 28 | #include "gnunet-service-cadet_tunnels.h" |
32 | #include "gnunet-service-cadet-new_paths.h" | 29 | #include "gnunet-service-cadet_peer.h" |
30 | #include "gnunet-service-cadet_paths.h" | ||
33 | 31 | ||
34 | 32 | ||
35 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-pat",__VA_ARGS__) | 33 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-pat",__VA_ARGS__) |
@@ -75,8 +73,16 @@ struct CadetPeerPath | |||
75 | static void | 73 | static void |
76 | recalculate_path_desirability (struct CadetPeerPath *path) | 74 | recalculate_path_desirability (struct CadetPeerPath *path) |
77 | { | 75 | { |
78 | /* FIXME: update path desirability! */ | 76 | double result = 0.0; |
79 | GNUNET_break (0); // not implemented | 77 | |
78 | for (unsigned int i=0;i<path->entries_length;i++) | ||
79 | { | ||
80 | struct CadetPeer *cp = path->entries[i]->peer; | ||
81 | |||
82 | result += GCP_get_desirability_of_path (cp, | ||
83 | i); | ||
84 | } | ||
85 | path->desirability = (GNUNET_CONTAINER_HeapCostType) result; | ||
80 | } | 86 | } |
81 | 87 | ||
82 | 88 | ||
@@ -147,6 +153,7 @@ GCPP_add_connection (struct CadetPeerPath *path, | |||
147 | GNUNET_assert (off < path->entries_length); | 153 | GNUNET_assert (off < path->entries_length); |
148 | entry = path->entries[off]; | 154 | entry = path->entries[off]; |
149 | GNUNET_assert (NULL == entry->cc); | 155 | GNUNET_assert (NULL == entry->cc); |
156 | GNUNET_assert (NULL != cc); | ||
150 | entry->cc = cc; | 157 | entry->cc = cc; |
151 | } | 158 | } |
152 | 159 | ||
@@ -191,7 +198,20 @@ path_destroy (struct CadetPeerPath *path) | |||
191 | "Destroying path %s\n", | 198 | "Destroying path %s\n", |
192 | GCPP_2s (path)); | 199 | GCPP_2s (path)); |
193 | for (unsigned int i=0;i<path->entries_length;i++) | 200 | for (unsigned int i=0;i<path->entries_length;i++) |
194 | GNUNET_free (path->entries[i]); | 201 | { |
202 | struct CadetPeerPathEntry *entry = path->entries[i]; | ||
203 | |||
204 | if (NULL != entry->cc) | ||
205 | { | ||
206 | struct CadetTConnection *ct; | ||
207 | |||
208 | ct = GCC_get_ct (entry->cc); | ||
209 | if (NULL != ct) | ||
210 | GCT_connection_lost (ct); | ||
211 | GCC_destroy_without_tunnel (entry->cc); | ||
212 | } | ||
213 | GNUNET_free (entry); | ||
214 | } | ||
195 | GNUNET_free (path->entries); | 215 | GNUNET_free (path->entries); |
196 | GNUNET_free (path); | 216 | GNUNET_free (path); |
197 | } | 217 | } |
@@ -208,15 +228,18 @@ void | |||
208 | GCPP_release (struct CadetPeerPath *path) | 228 | GCPP_release (struct CadetPeerPath *path) |
209 | { | 229 | { |
210 | struct CadetPeerPathEntry *entry; | 230 | struct CadetPeerPathEntry *entry; |
231 | int force; | ||
211 | 232 | ||
212 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 233 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
213 | "Owner releases path %s\n", | 234 | "Owner releases path %s\n", |
214 | GCPP_2s (path)); | 235 | GCPP_2s (path)); |
215 | path->hn = NULL; | 236 | path->hn = NULL; |
216 | entry = path->entries[path->entries_length - 1]; | 237 | entry = path->entries[path->entries_length - 1]; |
238 | GNUNET_assert (path == entry->path); | ||
217 | while (1) | 239 | while (1) |
218 | { | 240 | { |
219 | /* cut 'off' end of path */ | 241 | /* cut 'off' end of path */ |
242 | GNUNET_assert (NULL == entry->cc); | ||
220 | GCP_path_entry_remove (entry->peer, | 243 | GCP_path_entry_remove (entry->peer, |
221 | entry, | 244 | entry, |
222 | path->entries_length - 1); | 245 | path->entries_length - 1); |
@@ -228,12 +251,15 @@ GCPP_release (struct CadetPeerPath *path) | |||
228 | 251 | ||
229 | /* see if new peer at the end likes this path any better */ | 252 | /* see if new peer at the end likes this path any better */ |
230 | entry = path->entries[path->entries_length - 1]; | 253 | entry = path->entries[path->entries_length - 1]; |
254 | GNUNET_assert (path == entry->path); | ||
255 | force = (NULL == entry->cc) ? GNUNET_NO : GNUNET_YES; | ||
231 | path->hn = GCP_attach_path (entry->peer, | 256 | path->hn = GCP_attach_path (entry->peer, |
232 | path, | 257 | path, |
233 | path->entries_length - 1, | 258 | path->entries_length - 1, |
234 | GNUNET_NO); | 259 | force); |
235 | if (NULL != path->hn) | 260 | if (NULL != path->hn) |
236 | return; /* yep, got attached, we are done. */ | 261 | return; /* yep, got attached, we are done. */ |
262 | GNUNET_assert (GNUNET_NO == force); | ||
237 | } | 263 | } |
238 | 264 | ||
239 | /* nobody wants us, discard the path */ | 265 | /* nobody wants us, discard the path */ |
@@ -367,7 +393,6 @@ extend_path (struct CadetPeerPath *path, | |||
367 | int force) | 393 | int force) |
368 | { | 394 | { |
369 | unsigned int old_len = path->entries_length; | 395 | unsigned int old_len = path->entries_length; |
370 | struct GNUNET_CONTAINER_HeapNode *hn; | ||
371 | int i; | 396 | int i; |
372 | 397 | ||
373 | /* Expand path */ | 398 | /* Expand path */ |
@@ -393,38 +418,43 @@ extend_path (struct CadetPeerPath *path, | |||
393 | 418 | ||
394 | /* If we extend an existing path, detach it from the | 419 | /* If we extend an existing path, detach it from the |
395 | old owner and re-attach to the new one */ | 420 | old owner and re-attach to the new one */ |
396 | hn = NULL; | 421 | GCP_detach_path (path->entries[old_len-1]->peer, |
422 | path, | ||
423 | path->hn); | ||
424 | path->hn = NULL; | ||
397 | for (i=num_peers-1;i>=0;i--) | 425 | for (i=num_peers-1;i>=0;i--) |
398 | { | 426 | { |
399 | struct CadetPeerPathEntry *entry = path->entries[old_len + i]; | 427 | struct CadetPeerPathEntry *entry = path->entries[old_len + i]; |
400 | 428 | ||
401 | path->entries_length = old_len + i + 1; | 429 | path->entries_length = old_len + i + 1; |
402 | recalculate_path_desirability (path); | 430 | recalculate_path_desirability (path); |
403 | hn = GCP_attach_path (peers[i], | 431 | path->hn = GCP_attach_path (peers[i], |
404 | path, | 432 | path, |
405 | old_len + (unsigned int) i, | 433 | old_len + (unsigned int) i, |
406 | GNUNET_YES); | 434 | force); |
407 | if (NULL != hn) | 435 | if (NULL != path->hn) |
408 | break; | 436 | break; |
437 | GNUNET_assert (NULL == entry->cc); | ||
409 | GCP_path_entry_remove (entry->peer, | 438 | GCP_path_entry_remove (entry->peer, |
410 | entry, | 439 | entry, |
411 | old_len + i); | 440 | old_len + i); |
412 | GNUNET_free (entry); | 441 | GNUNET_free (entry); |
413 | path->entries[old_len + i] = NULL; | 442 | path->entries[old_len + i] = NULL; |
414 | } | 443 | } |
415 | if (NULL == hn) | 444 | if (NULL == path->hn) |
416 | { | 445 | { |
417 | /* none of the peers is interested in this path; | 446 | /* none of the peers is interested in this path; |
418 | shrink path back */ | 447 | shrink path back and re-attach. */ |
419 | GNUNET_array_grow (path->entries, | 448 | GNUNET_array_grow (path->entries, |
420 | path->entries_length, | 449 | path->entries_length, |
421 | old_len); | 450 | old_len); |
451 | path->hn = GCP_attach_path (path->entries[old_len - 1]->peer, | ||
452 | path, | ||
453 | old_len - 1, | ||
454 | GNUNET_YES); | ||
455 | GNUNET_assert (NULL != path->hn); | ||
422 | return; | 456 | return; |
423 | } | 457 | } |
424 | GCP_detach_path (path->entries[old_len-1]->peer, | ||
425 | path, | ||
426 | path->hn); | ||
427 | path->hn = hn; | ||
428 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 458 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
429 | "Extended path %s\n", | 459 | "Extended path %s\n", |
430 | GCPP_2s (path)); | 460 | GCPP_2s (path)); |
@@ -454,25 +484,42 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path, | |||
454 | struct CadetPeerPath *path; | 484 | struct CadetPeerPath *path; |
455 | struct GNUNET_CONTAINER_HeapNode *hn; | 485 | struct GNUNET_CONTAINER_HeapNode *hn; |
456 | int i; | 486 | int i; |
487 | unsigned int skip; | ||
488 | unsigned int total_len; | ||
457 | 489 | ||
458 | /* precompute 'cpath' so we can avoid doing the lookups lots of times */ | 490 | /* precompute 'cpath' so we can avoid doing the lookups lots of times */ |
459 | for (unsigned int off=0;off<get_path_length + put_path_length;off++) | 491 | skip = 0; |
492 | memset (cpath, | ||
493 | 0, | ||
494 | sizeof (cpath)); /* Just to trigger harder errors later. */ | ||
495 | total_len = get_path_length + put_path_length; | ||
496 | for (unsigned int off=0;off<total_len;off++) | ||
460 | { | 497 | { |
461 | const struct GNUNET_PeerIdentity *pid; | 498 | const struct GNUNET_PeerIdentity *pid; |
462 | 499 | ||
463 | pid = (off < get_path_length) | 500 | pid = (off < get_path_length) |
464 | ? &get_path[get_path_length - off] | 501 | ? &get_path[get_path_length - off] |
465 | : &put_path[get_path_length + put_path_length - off]; | 502 | : &put_path[get_path_length + put_path_length - off]; |
466 | cpath[off] = GCP_get (pid, | 503 | cpath[off - skip] = GCP_get (pid, |
467 | GNUNET_YES); | 504 | GNUNET_YES); |
505 | /* Check that no peer is twice on the path */ | ||
506 | for (unsigned int i=0;i<off - skip;i++) | ||
507 | { | ||
508 | if (cpath[i] == cpath[off - skip]) | ||
509 | { | ||
510 | skip = off - i; | ||
511 | break; | ||
512 | } | ||
513 | } | ||
468 | } | 514 | } |
515 | total_len -= skip; | ||
469 | 516 | ||
470 | /* First figure out if this path is a subset of an existing path, an | 517 | /* First figure out if this path is a subset of an existing path, an |
471 | extension of an existing path, or a new path. */ | 518 | extension of an existing path, or a new path. */ |
472 | cm_ctx.cpath_length = get_path_length + put_path_length; | 519 | cm_ctx.cpath_length = total_len; |
473 | cm_ctx.cpath = cpath; | 520 | cm_ctx.cpath = cpath; |
474 | cm_ctx.match = NULL; | 521 | cm_ctx.match = NULL; |
475 | for (i=get_path_length + put_path_length-1;i>=0;i--) | 522 | for (i=total_len-1;i>=0;i--) |
476 | { | 523 | { |
477 | GCP_iterate_paths_at (cpath[i], | 524 | GCP_iterate_paths_at (cpath[i], |
478 | (unsigned int) i, | 525 | (unsigned int) i, |
@@ -480,7 +527,7 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path, | |||
480 | &cm_ctx); | 527 | &cm_ctx); |
481 | if (NULL != cm_ctx.match) | 528 | if (NULL != cm_ctx.match) |
482 | { | 529 | { |
483 | if (i == get_path_length + put_path_length - 1) | 530 | if (i == total_len - 1) |
484 | { | 531 | { |
485 | /* Existing path includes this one, nothing to do! */ | 532 | /* Existing path includes this one, nothing to do! */ |
486 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 533 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
@@ -494,8 +541,8 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path, | |||
494 | "Trying to extend existing path %s by additional links discovered from DHT\n", | 541 | "Trying to extend existing path %s by additional links discovered from DHT\n", |
495 | GCPP_2s (cm_ctx.match)); | 542 | GCPP_2s (cm_ctx.match)); |
496 | extend_path (cm_ctx.match, | 543 | extend_path (cm_ctx.match, |
497 | &cpath[i], | 544 | &cpath[i + 1], |
498 | get_path_length + put_path_length - i, | 545 | total_len - i - 1, |
499 | GNUNET_NO); | 546 | GNUNET_NO); |
500 | return; | 547 | return; |
501 | } | 548 | } |
@@ -504,7 +551,7 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path, | |||
504 | 551 | ||
505 | /* No match at all, create completely new path */ | 552 | /* No match at all, create completely new path */ |
506 | path = GNUNET_new (struct CadetPeerPath); | 553 | path = GNUNET_new (struct CadetPeerPath); |
507 | path->entries_length = get_path_length + put_path_length; | 554 | path->entries_length = total_len; |
508 | path->entries = GNUNET_new_array (path->entries_length, | 555 | path->entries = GNUNET_new_array (path->entries_length, |
509 | struct CadetPeerPathEntry *); | 556 | struct CadetPeerPathEntry *); |
510 | for (i=path->entries_length-1;i>=0;i--) | 557 | for (i=path->entries_length-1;i>=0;i--) |
@@ -526,7 +573,7 @@ GCPP_try_path_from_dht (const struct GNUNET_PeerIdentity *get_path, | |||
526 | 573 | ||
527 | /* Finally, try to attach it */ | 574 | /* Finally, try to attach it */ |
528 | hn = NULL; | 575 | hn = NULL; |
529 | for (i=get_path_length + put_path_length-1;i>=0;i--) | 576 | for (i=total_len-1;i>=0;i--) |
530 | { | 577 | { |
531 | struct CadetPeerPathEntry *entry = path->entries[i]; | 578 | struct CadetPeerPathEntry *entry = path->entries[i]; |
532 | 579 | ||
@@ -613,8 +660,8 @@ GCPP_get_path_from_route (unsigned int path_length, | |||
613 | "Extending existing path %s to create inverse for incoming connection\n", | 660 | "Extending existing path %s to create inverse for incoming connection\n", |
614 | GCPP_2s (cm_ctx.match)); | 661 | GCPP_2s (cm_ctx.match)); |
615 | extend_path (cm_ctx.match, | 662 | extend_path (cm_ctx.match, |
616 | &cpath[i], | 663 | &cpath[i + 1], |
617 | path_length - i, | 664 | path_length - i - 1, |
618 | GNUNET_YES); | 665 | GNUNET_YES); |
619 | /* Check that extension was successful */ | 666 | /* Check that extension was successful */ |
620 | GNUNET_assert (cm_ctx.match->entries_length == path_length); | 667 | GNUNET_assert (cm_ctx.match->entries_length == path_length); |
diff --git a/src/cadet/gnunet-service-cadet-new_paths.h b/src/cadet/gnunet-service-cadet_paths.h index 7310d75e6..6b7bef640 100644 --- a/src/cadet/gnunet-service-cadet-new_paths.h +++ b/src/cadet/gnunet-service-cadet_paths.h | |||
@@ -29,7 +29,7 @@ | |||
29 | #define GNUNET_SERVICE_CADET_PATHS_H | 29 | #define GNUNET_SERVICE_CADET_PATHS_H |
30 | 30 | ||
31 | #include "gnunet_util_lib.h" | 31 | #include "gnunet_util_lib.h" |
32 | #include "gnunet-service-cadet-new.h" | 32 | #include "gnunet-service-cadet.h" |
33 | 33 | ||
34 | /** | 34 | /** |
35 | * Create a peer path based on the result of a DHT lookup. If we | 35 | * Create a peer path based on the result of a DHT lookup. If we |
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c index fa3f2be80..71c7c67d0 100644 --- a/src/cadet/gnunet-service-cadet_peer.c +++ b/src/cadet/gnunet-service-cadet_peer.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2013, 2015 GNUnet e.V. | 3 | Copyright (C) 2001-2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -17,2193 +17,1461 @@ | |||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. | 18 | Boston, MA 02110-1301, USA. |
19 | */ | 19 | */ |
20 | |||
20 | /** | 21 | /** |
21 | * @file cadet/gnunet-service-cadet_peer.c | 22 | * @file cadet/gnunet-service-cadet_peer.c |
22 | * @brief GNUnet CADET service connection handling | 23 | * @brief Information we track per peer. |
23 | * @author Bartlomiej Polot | 24 | * @author Bartlomiej Polot |
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * TODO: | ||
28 | * - optimize stopping/restarting DHT search to situations | ||
29 | * where we actually need it (i.e. not if we have a direct connection, | ||
30 | * or if we already have plenty of good short ones, or maybe even | ||
31 | * to take a break if we have some connections and have searched a lot (?)) | ||
24 | */ | 32 | */ |
25 | #include "platform.h" | 33 | #include "platform.h" |
26 | #include "gnunet_util_lib.h" | 34 | #include "gnunet_util_lib.h" |
35 | #include "gnunet_hello_lib.h" | ||
27 | #include "gnunet_signatures.h" | 36 | #include "gnunet_signatures.h" |
28 | #include "gnunet_transport_service.h" | 37 | #include "gnunet_transport_service.h" |
29 | #include "gnunet_ats_service.h" | 38 | #include "gnunet_ats_service.h" |
30 | #include "gnunet_core_service.h" | 39 | #include "gnunet_core_service.h" |
31 | #include "gnunet_statistics_service.h" | 40 | #include "gnunet_statistics_service.h" |
32 | #include "cadet_protocol.h" | 41 | #include "cadet_protocol.h" |
33 | #include "gnunet-service-cadet_peer.h" | ||
34 | #include "gnunet-service-cadet_dht.h" | ||
35 | #include "gnunet-service-cadet_connection.h" | 42 | #include "gnunet-service-cadet_connection.h" |
36 | #include "gnunet-service-cadet_tunnel.h" | 43 | #include "gnunet-service-cadet_dht.h" |
37 | #include "cadet_path.h" | 44 | #include "gnunet-service-cadet_peer.h" |
45 | #include "gnunet-service-cadet_paths.h" | ||
46 | #include "gnunet-service-cadet_tunnels.h" | ||
38 | 47 | ||
39 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-p2p",__VA_ARGS__) | ||
40 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-p2p",__VA_ARGS__) | ||
41 | 48 | ||
49 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-per",__VA_ARGS__) | ||
42 | 50 | ||
43 | /******************************************************************************/ | ||
44 | /******************************** STRUCTS **********************************/ | ||
45 | /******************************************************************************/ | ||
46 | 51 | ||
47 | /** | 52 | /** |
48 | * Information about a queued message on the peer level. | 53 | * How long do we wait until tearing down an idle peer? |
49 | */ | 54 | */ |
50 | struct CadetPeerQueue { | 55 | #define IDLE_PEER_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5) |
51 | |||
52 | struct CadetPeerQueue *next; | ||
53 | struct CadetPeerQueue *prev; | ||
54 | |||
55 | /** | ||
56 | * Envelope to cancel message before MQ sends it. | ||
57 | */ | ||
58 | struct GNUNET_MQ_Envelope *env; | ||
59 | |||
60 | /** | ||
61 | * Peer (neighbor) this message is being sent to. | ||
62 | */ | ||
63 | struct CadetPeer *peer; | ||
64 | |||
65 | /** | ||
66 | * Continuation to call to notify higher layers about message sent. | ||
67 | */ | ||
68 | GCP_sent cont; | ||
69 | |||
70 | /** | ||
71 | * Closure for @a cont. | ||
72 | */ | ||
73 | void *cont_cls; | ||
74 | |||
75 | /** | ||
76 | * Task to asynchronously run the drop continuation. | ||
77 | */ | ||
78 | struct GNUNET_SCHEDULER_Task *drop_task; | ||
79 | |||
80 | /** | ||
81 | * Time when message was queued for sending. | ||
82 | */ | ||
83 | struct GNUNET_TIME_Absolute queue_timestamp; | ||
84 | |||
85 | /** | ||
86 | * #GNUNET_YES if message was management traffic (POLL, ACK, ...). | ||
87 | */ | ||
88 | int management_traffic; | ||
89 | |||
90 | /** | ||
91 | * Message type. | ||
92 | */ | ||
93 | uint16_t type; | ||
94 | |||
95 | /** | ||
96 | * Message size. | ||
97 | */ | ||
98 | uint16_t size; | ||
99 | |||
100 | /** | ||
101 | * Type of the message's payload, if it was encrypted data. | ||
102 | */ | ||
103 | uint16_t payload_type; | ||
104 | |||
105 | /** | ||
106 | * ID of the payload (PID, ACK #, ...). | ||
107 | */ | ||
108 | struct CadetEncryptedMessageIdentifier payload_id; | ||
109 | |||
110 | /** | ||
111 | * Connection this message was sent on. | ||
112 | */ | ||
113 | struct CadetConnection *c; | ||
114 | |||
115 | /** | ||
116 | * Direction in @a c this message was send on (#GNUNET_YES = FWD). | ||
117 | */ | ||
118 | int c_fwd; | ||
119 | }; | ||
120 | |||
121 | 56 | ||
122 | /** | 57 | /** |
123 | * Struct containing all information regarding a given peer | 58 | * How long do we keep paths around if we no longer care about the peer? |
124 | */ | 59 | */ |
125 | struct CadetPeer | 60 | #define IDLE_PATH_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 2) |
126 | { | ||
127 | /** | ||
128 | * ID of the peer | ||
129 | */ | ||
130 | GNUNET_PEER_Id id; | ||
131 | |||
132 | struct CadetPeerQueue *q_head; | ||
133 | struct CadetPeerQueue *q_tail; | ||
134 | |||
135 | /** | ||
136 | * Last time we heard from this peer | ||
137 | */ | ||
138 | struct GNUNET_TIME_Absolute last_contact; | ||
139 | |||
140 | /** | ||
141 | * Paths to reach the peer, ordered by ascending hop count | ||
142 | */ | ||
143 | struct CadetPeerPath *path_head; | ||
144 | |||
145 | /** | ||
146 | * Paths to reach the peer, ordered by ascending hop count | ||
147 | */ | ||
148 | struct CadetPeerPath *path_tail; | ||
149 | |||
150 | /** | ||
151 | * Handle to stop the DHT search for paths to this peer | ||
152 | */ | ||
153 | struct GCD_search_handle *search_h; | ||
154 | |||
155 | /** | ||
156 | * Handle to stop the DHT search for paths to this peer | ||
157 | */ | ||
158 | struct GNUNET_SCHEDULER_Task *search_delayed; | ||
159 | |||
160 | /** | ||
161 | * Tunnel to this peer, if any. | ||
162 | */ | ||
163 | struct CadetTunnel *tunnel; | ||
164 | |||
165 | /** | ||
166 | * Connections that go through this peer; indexed by tid. | ||
167 | */ | ||
168 | struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
169 | |||
170 | /** | ||
171 | * Handle for core transmissions. | ||
172 | */ | ||
173 | struct GNUNET_MQ_Handle *core_mq; | ||
174 | |||
175 | /** | ||
176 | * How many messages are in the queue to this peer. | ||
177 | */ | ||
178 | unsigned int queue_n; | ||
179 | |||
180 | /** | ||
181 | * Hello message. | ||
182 | */ | ||
183 | struct GNUNET_HELLO_Message* hello; | ||
184 | |||
185 | /** | ||
186 | * Handle to us offering the HELLO to the transport. | ||
187 | */ | ||
188 | struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer; | ||
189 | |||
190 | /** | ||
191 | * Handle to our ATS request asking ATS to suggest an address | ||
192 | * to TRANSPORT for this peer (to establish a direct link). | ||
193 | */ | ||
194 | struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion; | ||
195 | 61 | ||
196 | }; | ||
197 | |||
198 | |||
199 | /******************************************************************************/ | ||
200 | /******************************* GLOBALS ***********************************/ | ||
201 | /******************************************************************************/ | ||
202 | |||
203 | /** | ||
204 | * Global handle to the statistics service. | ||
205 | */ | ||
206 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
207 | 62 | ||
208 | /** | ||
209 | * Local peer own ID (full value). | ||
210 | */ | ||
211 | extern struct GNUNET_PeerIdentity my_full_id; | ||
212 | 63 | ||
213 | /** | ||
214 | * Local peer own ID (short) | ||
215 | */ | ||
216 | extern GNUNET_PEER_Id myid; | ||
217 | 64 | ||
218 | /** | 65 | /** |
219 | * Peers known, indexed by PeerIdentity, values of type `struct CadetPeer`. | 66 | * Data structure used to track whom we have to notify about changes |
67 | * to our message queue. | ||
220 | */ | 68 | */ |
221 | static struct GNUNET_CONTAINER_MultiPeerMap *peers; | 69 | struct GCP_MessageQueueManager |
222 | 70 | { | |
223 | /** | ||
224 | * How many peers do we want to remember? | ||
225 | */ | ||
226 | static unsigned long long max_peers; | ||
227 | 71 | ||
228 | /** | 72 | /** |
229 | * Percentage of messages that will be dropped (for test purposes only). | 73 | * Kept in a DLL. |
230 | */ | 74 | */ |
231 | static unsigned long long drop_percent; | 75 | struct GCP_MessageQueueManager *next; |
232 | 76 | ||
233 | /** | 77 | /** |
234 | * Handle to communicate with CORE. | 78 | * Kept in a DLL. |
235 | */ | 79 | */ |
236 | static struct GNUNET_CORE_Handle *core_handle; | 80 | struct GCP_MessageQueueManager *prev; |
237 | 81 | ||
238 | /** | 82 | /** |
239 | * Our configuration; | 83 | * Function to call with updated message queue object. |
240 | */ | 84 | */ |
241 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | 85 | GCP_MessageQueueNotificationCallback cb; |
242 | 86 | ||
243 | /** | 87 | /** |
244 | * Handle to communicate with ATS. | 88 | * Closure for @e cb. |
245 | */ | 89 | */ |
246 | static struct GNUNET_ATS_ConnectivityHandle *ats_ch; | 90 | void *cb_cls; |
247 | 91 | ||
248 | /** | 92 | /** |
249 | * Shutdown falg. | 93 | * The peer this is for. |
250 | */ | 94 | */ |
251 | static int in_shutdown; | 95 | struct CadetPeer *cp; |
252 | 96 | ||
97 | /** | ||
98 | * Envelope this manager would like to transmit once it is its turn. | ||
99 | */ | ||
100 | struct GNUNET_MQ_Envelope *env; | ||
253 | 101 | ||
254 | /******************************************************************************/ | 102 | }; |
255 | /***************************** CORE HELPERS *********************************/ | ||
256 | /******************************************************************************/ | ||
257 | 103 | ||
258 | 104 | ||
259 | /** | 105 | /** |
260 | * Iterator to notify all connections of a broken link. Mark connections | 106 | * Struct containing all information regarding a given peer |
261 | * to destroy after all traffic has been sent. | ||
262 | * | ||
263 | * @param cls Closure (disconnected peer). | ||
264 | * @param key Current key code (peer id). | ||
265 | * @param value Value in the hash map (connection). | ||
266 | * | ||
267 | * @return #GNUNET_YES to continue to iterate. | ||
268 | */ | 107 | */ |
269 | static int | 108 | struct CadetPeer |
270 | notify_broken (void *cls, | ||
271 | const struct GNUNET_ShortHashCode *key, | ||
272 | void *value) | ||
273 | { | 109 | { |
274 | struct CadetPeer *peer = cls; | 110 | /** |
275 | struct CadetConnection *c = value; | 111 | * ID of the peer |
112 | */ | ||
113 | struct GNUNET_PeerIdentity pid; | ||
114 | |||
115 | /** | ||
116 | * Last time we heard from this peer (currently not used!) | ||
117 | */ | ||
118 | struct GNUNET_TIME_Absolute last_contactXXX; | ||
119 | |||
120 | /** | ||
121 | * Array of DLLs of paths traversing the peer, organized by the | ||
122 | * offset of the peer on the larger path. | ||
123 | */ | ||
124 | struct CadetPeerPathEntry **path_heads; | ||
125 | |||
126 | /** | ||
127 | * Array of DLL of paths traversing the peer, organized by the | ||
128 | * offset of the peer on the larger path. | ||
129 | */ | ||
130 | struct CadetPeerPathEntry **path_tails; | ||
131 | |||
132 | /** | ||
133 | * Notifications to call when @e core_mq changes. | ||
134 | */ | ||
135 | struct GCP_MessageQueueManager *mqm_head; | ||
136 | |||
137 | /** | ||
138 | * Notifications to call when @e core_mq changes. | ||
139 | */ | ||
140 | struct GCP_MessageQueueManager *mqm_tail; | ||
141 | |||
142 | /** | ||
143 | * Pointer to first "ready" entry in @e mqm_head. | ||
144 | */ | ||
145 | struct GCP_MessageQueueManager *mqm_ready_ptr; | ||
146 | |||
147 | /** | ||
148 | * MIN-heap of paths owned by this peer (they also end at this | ||
149 | * peer). Ordered by desirability. | ||
150 | */ | ||
151 | struct GNUNET_CONTAINER_Heap *path_heap; | ||
152 | |||
153 | /** | ||
154 | * Handle to stop the DHT search for paths to this peer | ||
155 | */ | ||
156 | struct GCD_search_handle *search_h; | ||
157 | |||
158 | /** | ||
159 | * Task to clean up @e path_heap asynchronously. | ||
160 | */ | ||
161 | struct GNUNET_SCHEDULER_Task *heap_cleanup_task; | ||
162 | |||
163 | /** | ||
164 | * Task to destroy this entry. | ||
165 | */ | ||
166 | struct GNUNET_SCHEDULER_Task *destroy_task; | ||
167 | |||
168 | /** | ||
169 | * Tunnel to this peer, if any. | ||
170 | */ | ||
171 | struct CadetTunnel *t; | ||
172 | |||
173 | /** | ||
174 | * Connections that go through this peer; indexed by tid. | ||
175 | */ | ||
176 | struct GNUNET_CONTAINER_MultiShortmap *connections; | ||
177 | |||
178 | /** | ||
179 | * Handle for core transmissions. | ||
180 | */ | ||
181 | struct GNUNET_MQ_Handle *core_mq; | ||
182 | |||
183 | /** | ||
184 | * Hello message of the peer. | ||
185 | */ | ||
186 | struct GNUNET_HELLO_Message *hello; | ||
187 | |||
188 | /** | ||
189 | * Handle to us offering the HELLO to the transport. | ||
190 | */ | ||
191 | struct GNUNET_TRANSPORT_OfferHelloHandle *hello_offer; | ||
192 | |||
193 | /** | ||
194 | * Handle to our ATS request asking ATS to suggest an address | ||
195 | * to TRANSPORT for this peer (to establish a direct link). | ||
196 | */ | ||
197 | struct GNUNET_ATS_ConnectivitySuggestHandle *connectivity_suggestion; | ||
198 | |||
199 | /** | ||
200 | * How many messages are in the queue to this peer. | ||
201 | */ | ||
202 | unsigned int queue_n; | ||
203 | |||
204 | /** | ||
205 | * How many paths do we have to this peer (in all @e path_heads DLLs combined). | ||
206 | */ | ||
207 | unsigned int num_paths; | ||
208 | |||
209 | /** | ||
210 | * Sum over all of the offsets of all of the paths in the @a path_heads DLLs. | ||
211 | * Used to speed-up @GCP_get_desirability_of_path() calculation. | ||
212 | */ | ||
213 | unsigned int off_sum; | ||
214 | |||
215 | /** | ||
216 | * Number of message queue managers of this peer that have a message in waiting. | ||
217 | * | ||
218 | * Used to quickly see if we need to bother scanning the @e msm_head DLL. | ||
219 | * TODO: could be replaced by another DLL that would then allow us to avoid | ||
220 | * the O(n)-scan of the DLL for ready entries! | ||
221 | */ | ||
222 | unsigned int mqm_ready_counter; | ||
223 | |||
224 | /** | ||
225 | * Current length of the @e path_heads and @path_tails arrays. | ||
226 | * The arrays should be grown as needed. | ||
227 | */ | ||
228 | unsigned int path_dll_length; | ||
276 | 229 | ||
277 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 230 | }; |
278 | "Notifying %s due to %s disconnect\n", | ||
279 | GCC_2s (c), GCP_2s (peer)); | ||
280 | GCC_neighbor_disconnected (c, peer); | ||
281 | return GNUNET_YES; | ||
282 | } | ||
283 | 231 | ||
284 | 232 | ||
285 | /** | 233 | /** |
286 | * Remove the direct path to the peer. | 234 | * Get the static string for a peer ID. |
287 | * | ||
288 | * @param peer Peer to remove the direct path from. | ||
289 | */ | ||
290 | static struct CadetPeerPath * | ||
291 | pop_direct_path (struct CadetPeer *peer) | ||
292 | { | ||
293 | struct CadetPeerPath *iter; | ||
294 | |||
295 | for (iter = peer->path_head; NULL != iter; iter = iter->next) | ||
296 | { | ||
297 | if (2 >= iter->length) | ||
298 | { | ||
299 | GNUNET_CONTAINER_DLL_remove (peer->path_head, | ||
300 | peer->path_tail, | ||
301 | iter); | ||
302 | return iter; | ||
303 | } | ||
304 | } | ||
305 | return NULL; | ||
306 | } | ||
307 | |||
308 | /** | ||
309 | * Call the continuation after a message has been sent or dropped. | ||
310 | * | ||
311 | * This funcion removes the message from the queue. | ||
312 | * | 235 | * |
313 | * @param q Queue handle. | 236 | * @param cp Peer. |
314 | * @param sent #GNUNET_YES if was sent to CORE, #GNUNET_NO if dropped. | 237 | * @return Static string for it's ID. |
315 | */ | 238 | */ |
316 | static void | 239 | const char * |
317 | call_peer_cont (struct CadetPeerQueue *q, int sent); | 240 | GCP_2s (const struct CadetPeer *cp) |
241 | { | ||
242 | static char buf[32]; | ||
243 | |||
244 | GNUNET_snprintf (buf, | ||
245 | sizeof (buf), | ||
246 | "P(%s)", | ||
247 | GNUNET_i2s (&cp->pid)); | ||
248 | return buf; | ||
249 | } | ||
250 | |||
251 | |||
252 | /** | ||
253 | * Calculate how desirable a path is for @a cp if @a cp | ||
254 | * is at offset @a off. | ||
255 | * | ||
256 | * The 'desirability_table.c' program can be used to compute a list of | ||
257 | * sample outputs for different scenarios. Basically, we score paths | ||
258 | * lower if there are many alternatives, and higher if they are | ||
259 | * shorter than average, and very high if they are much shorter than | ||
260 | * average and without many alternatives. | ||
261 | * | ||
262 | * @param cp a peer reachable via a path | ||
263 | * @param off offset of @a cp in the path | ||
264 | * @return score how useful a path is to reach @a cp, | ||
265 | * positive scores mean path is more desirable | ||
266 | */ | ||
267 | double | ||
268 | GCP_get_desirability_of_path (struct CadetPeer *cp, | ||
269 | unsigned int off) | ||
270 | { | ||
271 | unsigned int num_alts = cp->num_paths; | ||
272 | unsigned int off_sum; | ||
273 | double avg_sum; | ||
274 | double path_delta; | ||
275 | double weight_alts; | ||
276 | |||
277 | GNUNET_assert (num_alts >= 1); /* 'path' should be in there! */ | ||
278 | GNUNET_assert (0 != cp->path_dll_length); | ||
279 | |||
280 | /* We maintain 'off_sum' in 'peer' and thereby | ||
281 | avoid the SLOW recalculation each time. Kept here | ||
282 | just to document what is going on. */ | ||
283 | #if SLOW | ||
284 | off_sum = 0; | ||
285 | for (unsigned int j=0;j<cp->path_dll_length;j++) | ||
286 | for (struct CadetPeerPathEntry *pe = cp->path_heads[j]; | ||
287 | NULL != pe; | ||
288 | pe = pe->next) | ||
289 | off_sum += j; | ||
290 | GNUNET_assert (off_sum == cp->off_sum); | ||
291 | #else | ||
292 | off_sum = cp->off_sum; | ||
293 | #endif | ||
294 | avg_sum = off_sum * 1.0 / cp->path_dll_length; | ||
295 | path_delta = off - avg_sum; | ||
296 | /* path_delta positiv: path off of peer above average (bad path for peer), | ||
297 | path_delta negativ: path off of peer below average (good path for peer) */ | ||
298 | if (path_delta <= - 1.0) | ||
299 | weight_alts = - num_alts / path_delta; /* discount alternative paths */ | ||
300 | else if (path_delta >= 1.0) | ||
301 | weight_alts = num_alts * path_delta; /* overcount alternative paths */ | ||
302 | else | ||
303 | weight_alts = num_alts; /* count alternative paths normally */ | ||
318 | 304 | ||
319 | 305 | ||
320 | /******************************************************************************/ | 306 | /* off+1: long paths are generally harder to find and thus count |
321 | /***************************** CORE CALLBACKS *********************************/ | 307 | a bit more as they get longer. However, above-average paths |
322 | /******************************************************************************/ | 308 | still need to count less, hence the squaring of that factor. */ |
309 | return (off + 1.0) / (weight_alts * weight_alts); | ||
310 | } | ||
323 | 311 | ||
324 | 312 | ||
325 | /** | 313 | /** |
326 | * Method called whenever a given peer connects. | 314 | * This peer is no longer be needed, clean it up now. |
327 | * | 315 | * |
328 | * @param cls Core closure (unused). | 316 | * @param cls peer to clean up |
329 | * @param peer Peer identity this notification is about | ||
330 | * @param mq Message Queue to this peer. | ||
331 | * | ||
332 | * @return Internal closure for handlers (CadetPeer struct). | ||
333 | */ | 317 | */ |
334 | static void * | 318 | static void |
335 | core_connect_handler (void *cls, | 319 | destroy_peer (void *cls) |
336 | const struct GNUNET_PeerIdentity *peer, | 320 | { |
337 | struct GNUNET_MQ_Handle *mq) | 321 | struct CadetPeer *cp = cls; |
338 | { | 322 | |
339 | struct CadetPeer *neighbor; | 323 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
340 | struct CadetPeerPath *path; | 324 | "Destroying state about peer %s\n", |
341 | char own_id[16]; | 325 | GCP_2s (cp)); |
342 | 326 | cp->destroy_task = NULL; | |
343 | GCC_check_connections (); | 327 | GNUNET_assert (NULL == cp->t); |
344 | GNUNET_snprintf (own_id, | 328 | GNUNET_assert (NULL == cp->core_mq); |
345 | sizeof (own_id), | 329 | GNUNET_assert (0 == cp->num_paths); |
346 | "%s", | 330 | for (unsigned int i=0;i<cp->path_dll_length;i++) |
347 | GNUNET_i2s (&my_full_id)); | 331 | GNUNET_assert (NULL == cp->path_heads[i]); |
348 | 332 | GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)); | |
349 | /* Save a path to the neighbor */ | 333 | GNUNET_assert (GNUNET_YES == |
350 | neighbor = GCP_get (peer, GNUNET_YES); | 334 | GNUNET_CONTAINER_multipeermap_remove (peers, |
351 | if (myid == neighbor->id) | 335 | &cp->pid, |
352 | { | 336 | cp)); |
353 | LOG (GNUNET_ERROR_TYPE_INFO, | 337 | GNUNET_free_non_null (cp->path_heads); |
354 | "CONNECTED %s (self)\n", | 338 | GNUNET_free_non_null (cp->path_tails); |
355 | own_id); | 339 | cp->path_dll_length = 0; |
356 | path = path_new (1); | 340 | if (NULL != cp->search_h) |
357 | } | 341 | { |
358 | else | 342 | GCD_search_stop (cp->search_h); |
359 | { | 343 | cp->search_h = NULL; |
360 | LOG (GNUNET_ERROR_TYPE_INFO, | 344 | } |
361 | "CONNECTED %s <= %s\n", | 345 | /* FIXME: clean up search_delayedXXX! */ |
362 | own_id, | ||
363 | GNUNET_i2s (peer)); | ||
364 | path = path_new (2); | ||
365 | path->peers[1] = neighbor->id; | ||
366 | GNUNET_PEER_change_rc (neighbor->id, 1); | ||
367 | GNUNET_assert (NULL == neighbor->core_mq); | ||
368 | neighbor->core_mq = mq; | ||
369 | } | ||
370 | path->peers[0] = myid; | ||
371 | GNUNET_PEER_change_rc (myid, 1); | ||
372 | GCP_add_path (neighbor, path, GNUNET_YES); | ||
373 | |||
374 | /* Create the connections hashmap */ | ||
375 | GNUNET_assert (NULL == neighbor->connections); | ||
376 | neighbor->connections = GNUNET_CONTAINER_multishortmap_create (16, | ||
377 | GNUNET_YES); | ||
378 | GNUNET_STATISTICS_update (stats, | ||
379 | "# peers", | ||
380 | 1, | ||
381 | GNUNET_NO); | ||
382 | |||
383 | if ( (NULL != GCP_get_tunnel (neighbor)) && | ||
384 | (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, peer)) ) | ||
385 | { | ||
386 | GCP_connect (neighbor); | ||
387 | } | ||
388 | GCC_check_connections (); | ||
389 | 346 | ||
390 | return neighbor; | 347 | if (NULL != cp->hello_offer) |
348 | { | ||
349 | GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer); | ||
350 | cp->hello_offer = NULL; | ||
351 | } | ||
352 | if (NULL != cp->connectivity_suggestion) | ||
353 | { | ||
354 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); | ||
355 | cp->connectivity_suggestion = NULL; | ||
356 | } | ||
357 | GNUNET_CONTAINER_multishortmap_destroy (cp->connections); | ||
358 | if (NULL != cp->path_heap) | ||
359 | { | ||
360 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); | ||
361 | cp->path_heap = NULL; | ||
362 | } | ||
363 | if (NULL != cp->heap_cleanup_task) | ||
364 | { | ||
365 | GNUNET_SCHEDULER_cancel (cp->heap_cleanup_task); | ||
366 | cp->heap_cleanup_task = NULL; | ||
367 | } | ||
368 | GNUNET_free_non_null (cp->hello); | ||
369 | /* Peer should not be freed if paths exist; if there are no paths, | ||
370 | there ought to be no connections, and without connections, no | ||
371 | notifications. Thus we can assert that mqm_head is empty at this | ||
372 | point. */ | ||
373 | GNUNET_assert (NULL == cp->mqm_head); | ||
374 | GNUNET_assert (NULL == cp->mqm_ready_ptr); | ||
375 | GNUNET_free (cp); | ||
391 | } | 376 | } |
392 | 377 | ||
393 | 378 | ||
394 | /** | 379 | /** |
395 | * Method called whenever a peer disconnects. | 380 | * This peer is now on more "active" duty, activate processes related to it. |
396 | * | 381 | * |
397 | * @param cls Core closure (unused). | 382 | * @param cp the more-active peer |
398 | * @param peer Peer identity this notification is about. | ||
399 | * @param internal_cls Internal closure (CadetPeer struct). | ||
400 | */ | 383 | */ |
401 | static void | 384 | static void |
402 | core_disconnect_handler (void *cls, | 385 | consider_peer_activate (struct CadetPeer *cp) |
403 | const struct GNUNET_PeerIdentity *peer, | ||
404 | void *internal_cls) | ||
405 | { | 386 | { |
406 | struct CadetPeer *p = internal_cls; | 387 | uint32_t strength; |
407 | struct CadetPeerPath *direct_path; | 388 | |
408 | char own_id[16]; | 389 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
409 | 390 | "Updating peer %s activation state (%u connections)%s%s\n", | |
410 | GCC_check_connections (); | 391 | GCP_2s (cp), |
411 | strncpy (own_id, GNUNET_i2s (&my_full_id), 16); | 392 | GNUNET_CONTAINER_multishortmap_size (cp->connections), |
412 | own_id[15] = '\0'; | 393 | (NULL == cp->t) ? "" : " with tunnel", |
413 | if (myid == p->id) | 394 | (NULL == cp->core_mq) ? "" : " with CORE link"); |
414 | { | 395 | if (NULL != cp->destroy_task) |
415 | LOG (GNUNET_ERROR_TYPE_INFO, | 396 | { |
416 | "DISCONNECTED %s (self)\n", | 397 | /* It's active, do not destory! */ |
417 | own_id); | 398 | GNUNET_SCHEDULER_cancel (cp->destroy_task); |
418 | } | 399 | cp->destroy_task = NULL; |
419 | else | 400 | } |
401 | if ( (0 == GNUNET_CONTAINER_multishortmap_size (cp->connections)) && | ||
402 | (NULL == cp->t) ) | ||
403 | { | ||
404 | /* We're just on a path or directly connected; don't bother too much */ | ||
405 | if (NULL != cp->connectivity_suggestion) | ||
420 | { | 406 | { |
421 | LOG (GNUNET_ERROR_TYPE_INFO, | 407 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); |
422 | "DISCONNECTED %s <= %s\n", | 408 | cp->connectivity_suggestion = NULL; |
423 | own_id, GNUNET_i2s (peer)); | ||
424 | p->core_mq = NULL; | ||
425 | } | 409 | } |
426 | direct_path = pop_direct_path (p); | 410 | if (NULL != cp->search_h) |
427 | if (NULL != p->connections) | ||
428 | { | 411 | { |
429 | GNUNET_CONTAINER_multishortmap_iterate (p->connections, | 412 | GCD_search_stop (cp->search_h); |
430 | ¬ify_broken, | 413 | cp->search_h = NULL; |
431 | p); | ||
432 | GNUNET_CONTAINER_multishortmap_destroy (p->connections); | ||
433 | p->connections = NULL; | ||
434 | } | 414 | } |
435 | GNUNET_STATISTICS_update (stats, | 415 | return; |
436 | "# peers", | 416 | } |
437 | -1, | 417 | if (NULL == cp->core_mq) |
438 | GNUNET_NO); | 418 | { |
439 | path_destroy (direct_path); | 419 | /* Lacks direct connection, try to create one by querying the DHT */ |
440 | GCC_check_connections (); | 420 | if ( (NULL == cp->search_h) && |
441 | } | 421 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) ) |
442 | 422 | cp->search_h | |
443 | 423 | = GCD_search (&cp->pid); | |
444 | /******************************************************************************/ | 424 | } |
445 | /******************************************************************************/ | 425 | else |
446 | /******************************************************************************/ | 426 | { |
447 | /******************************************************************************/ | 427 | /* Have direct connection, stop DHT search if active */ |
448 | /******************************************************************************/ | 428 | if (NULL != cp->search_h) |
449 | |||
450 | /** | ||
451 | * Check if the create_connection message has the appropriate size. | ||
452 | * | ||
453 | * @param cls Closure (unused). | ||
454 | * @param msg Message to check. | ||
455 | * | ||
456 | * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise. | ||
457 | */ | ||
458 | static int | ||
459 | check_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
460 | { | ||
461 | uint16_t size; | ||
462 | |||
463 | size = ntohs (msg->header.size); | ||
464 | if (size < sizeof (*msg)) | ||
465 | { | 429 | { |
466 | GNUNET_break_op (0); | 430 | GCD_search_stop (cp->search_h); |
467 | return GNUNET_NO; | 431 | cp->search_h = NULL; |
468 | } | 432 | } |
469 | return GNUNET_YES; | 433 | } |
470 | } | ||
471 | |||
472 | /** | ||
473 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE | ||
474 | * | ||
475 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
476 | * @param msg Message itself. | ||
477 | */ | ||
478 | static void | ||
479 | handle_create (void *cls, const struct GNUNET_CADET_ConnectionCreateMessage *msg) | ||
480 | { | ||
481 | struct CadetPeer *peer = cls; | ||
482 | GCC_handle_create (peer, msg); | ||
483 | } | ||
484 | |||
485 | |||
486 | /** | ||
487 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK | ||
488 | * | ||
489 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
490 | * @param msg Message itself. | ||
491 | */ | ||
492 | static void | ||
493 | handle_confirm (void *cls, const struct GNUNET_CADET_ConnectionCreateAckMessage *msg) | ||
494 | { | ||
495 | struct CadetPeer *peer = cls; | ||
496 | GCC_handle_confirm (peer, msg); | ||
497 | } | ||
498 | |||
499 | 434 | ||
500 | /** | 435 | /* If we have a tunnel, our urge for connections is much bigger */ |
501 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN | 436 | strength = (NULL != cp->t) ? 32 : 1; |
502 | * | 437 | if (NULL != cp->connectivity_suggestion) |
503 | * @param cls Closure (CadetPeer for neighbor that sent the message). | 438 | GNUNET_ATS_connectivity_suggest_cancel (cp->connectivity_suggestion); |
504 | * @param msg Message itself. | 439 | cp->connectivity_suggestion |
505 | */ | 440 | = GNUNET_ATS_connectivity_suggest (ats_ch, |
506 | static void | 441 | &cp->pid, |
507 | handle_broken (void *cls, const struct GNUNET_CADET_ConnectionBrokenMessage *msg) | 442 | strength); |
508 | { | ||
509 | struct CadetPeer *peer = cls; | ||
510 | GCC_handle_broken (peer, msg); | ||
511 | } | 443 | } |
512 | 444 | ||
513 | 445 | ||
514 | /** | 446 | /** |
515 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY | 447 | * This peer may no longer be needed, consider cleaning it up. |
516 | * | 448 | * |
517 | * @param cls Closure (CadetPeer for neighbor that sent the message). | 449 | * @param cp peer to clean up |
518 | * @param msg Message itself. | ||
519 | */ | 450 | */ |
520 | static void | 451 | static void |
521 | handle_destroy (void *cls, const struct GNUNET_CADET_ConnectionDestroyMessage *msg) | 452 | consider_peer_destroy (struct CadetPeer *cp); |
522 | { | ||
523 | struct CadetPeer *peer = cls; | ||
524 | GCC_handle_destroy (peer, msg); | ||
525 | } | ||
526 | 453 | ||
527 | 454 | ||
528 | /** | 455 | /** |
529 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK | 456 | * We really no longere care about a peer, stop hogging memory with paths to it. |
457 | * Afterwards, see if there is more to be cleaned up about this peer. | ||
530 | * | 458 | * |
531 | * @param cls Closure (CadetPeer for neighbor that sent the message). | 459 | * @param cls a `struct CadetPeer`. |
532 | * @param msg Message itself. | ||
533 | */ | 460 | */ |
534 | static void | 461 | static void |
535 | handle_ack (void *cls, const struct GNUNET_CADET_ConnectionEncryptedAckMessage *msg) | 462 | drop_paths (void *cls) |
536 | { | 463 | { |
537 | struct CadetPeer *peer = cls; | 464 | struct CadetPeer *cp = cls; |
538 | GCC_handle_ack (peer, msg); | 465 | struct CadetPeerPath *path; |
539 | } | ||
540 | 466 | ||
541 | 467 | cp->destroy_task = NULL; | |
542 | /** | 468 | while (NULL != (path = GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) |
543 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL | 469 | GCPP_release (path); |
544 | * | 470 | consider_peer_destroy (cp); |
545 | * @param cls Closure (CadetPeer for neighbor that sent the message). | ||
546 | * @param msg Message itself. | ||
547 | */ | ||
548 | static void | ||
549 | handle_poll (void *cls, const struct GNUNET_CADET_ConnectionHopByHopPollMessage *msg) | ||
550 | { | ||
551 | struct CadetPeer *peer = cls; | ||
552 | GCC_handle_poll (peer, msg); | ||
553 | } | 471 | } |
554 | 472 | ||
555 | 473 | ||
556 | /** | 474 | /** |
557 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX | 475 | * This peer may no longer be needed, consider cleaning it up. |
558 | * | 476 | * |
559 | * @param cls Closure (CadetPeer for neighbor that sent the message). | 477 | * @param cp peer to clean up |
560 | * @param msg Message itself. | ||
561 | */ | 478 | */ |
562 | static void | 479 | static void |
563 | handle_kx (void *cls, const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | 480 | consider_peer_destroy (struct CadetPeer *cp) |
564 | { | ||
565 | struct CadetPeer *peer = cls; | ||
566 | GCC_handle_kx (peer, msg); | ||
567 | } | ||
568 | |||
569 | |||
570 | /** | ||
571 | * Check if the encrypted message has the appropriate size. | ||
572 | * | ||
573 | * @param cls Closure (unused). | ||
574 | * @param msg Message to check. | ||
575 | * | ||
576 | * @return #GNUNET_YES if size is correct, #GNUNET_NO otherwise. | ||
577 | */ | ||
578 | static int | ||
579 | check_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
580 | { | 481 | { |
581 | uint16_t size; | 482 | struct GNUNET_TIME_Relative exp; |
582 | uint16_t minimum_size; | ||
583 | |||
584 | size = ntohs (msg->header.size); | ||
585 | minimum_size = sizeof (struct GNUNET_CADET_TunnelEncryptedMessage) | ||
586 | + sizeof (struct GNUNET_MessageHeader); | ||
587 | |||
588 | if (size < minimum_size) | ||
589 | { | ||
590 | GNUNET_break_op (0); | ||
591 | return GNUNET_NO; | ||
592 | } | ||
593 | return GNUNET_YES; | ||
594 | } | ||
595 | 483 | ||
596 | /** | 484 | if (NULL != cp->destroy_task) |
597 | * Handle for #GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED. | 485 | { |
598 | * | 486 | GNUNET_SCHEDULER_cancel (cp->destroy_task); |
599 | * @param cls Closure (CadetPeer for neighbor that sent the message). | 487 | cp->destroy_task = NULL; |
600 | * @param msg Message itself. | 488 | } |
601 | */ | 489 | if (NULL != cp->t) |
602 | static void | 490 | return; /* still relevant! */ |
603 | handle_encrypted (void *cls, const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | 491 | if (NULL != cp->core_mq) |
604 | { | 492 | return; /* still relevant! */ |
605 | struct CadetPeer *peer = cls; | 493 | if (0 != GNUNET_CONTAINER_multishortmap_size (cp->connections)) |
606 | GCC_handle_encrypted (peer, msg); | 494 | return; /* still relevant! */ |
607 | } | 495 | if ( (NULL != cp->path_heap) && |
608 | 496 | (0 < GNUNET_CONTAINER_heap_get_size (cp->path_heap)) ) | |
609 | 497 | { | |
610 | /** | 498 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PATH_TIMEOUT, |
611 | * To be called on core init/fail. | 499 | &drop_paths, |
612 | * | 500 | cp); |
613 | * @param cls Closure (config) | 501 | return; |
614 | * @param identity The public identity of this peer. | 502 | } |
615 | */ | 503 | if (0 != cp->num_paths) |
616 | static void | 504 | return; /* still relevant! */ |
617 | core_init_notify (void *cls, | 505 | if (NULL != cp->hello) |
618 | const struct GNUNET_PeerIdentity *identity); | 506 | { |
619 | 507 | /* relevant only until HELLO expires */ | |
620 | 508 | exp = GNUNET_TIME_absolute_get_remaining (GNUNET_HELLO_get_last_expiration (cp->hello)); | |
621 | static void | 509 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (exp, |
622 | connect_to_core (const struct GNUNET_CONFIGURATION_Handle *c) | 510 | &destroy_peer, |
623 | { | 511 | cp); |
624 | struct GNUNET_MQ_MessageHandler core_handlers[] = { | 512 | return; |
625 | GNUNET_MQ_hd_var_size (create, | 513 | } |
626 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, | 514 | cp->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_PEER_TIMEOUT, |
627 | struct GNUNET_CADET_ConnectionCreateMessage, | 515 | &destroy_peer, |
628 | NULL), | 516 | cp); |
629 | GNUNET_MQ_hd_fixed_size (confirm, | ||
630 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK, | ||
631 | struct GNUNET_CADET_ConnectionCreateAckMessage, | ||
632 | NULL), | ||
633 | GNUNET_MQ_hd_fixed_size (broken, | ||
634 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, | ||
635 | struct GNUNET_CADET_ConnectionBrokenMessage, | ||
636 | NULL), | ||
637 | GNUNET_MQ_hd_fixed_size (destroy, | ||
638 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, | ||
639 | struct GNUNET_CADET_ConnectionDestroyMessage, | ||
640 | NULL), | ||
641 | GNUNET_MQ_hd_fixed_size (ack, | ||
642 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK, | ||
643 | struct GNUNET_CADET_ConnectionEncryptedAckMessage, | ||
644 | NULL), | ||
645 | GNUNET_MQ_hd_fixed_size (poll, | ||
646 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL, | ||
647 | struct GNUNET_CADET_ConnectionHopByHopPollMessage, | ||
648 | NULL), | ||
649 | GNUNET_MQ_hd_fixed_size (kx, | ||
650 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX, | ||
651 | struct GNUNET_CADET_TunnelKeyExchangeMessage, | ||
652 | NULL), | ||
653 | GNUNET_MQ_hd_var_size (encrypted, | ||
654 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED, | ||
655 | struct GNUNET_CADET_TunnelEncryptedMessage, | ||
656 | NULL), | ||
657 | GNUNET_MQ_handler_end () | ||
658 | }; | ||
659 | core_handle = GNUNET_CORE_connect (c, NULL, | ||
660 | &core_init_notify, | ||
661 | &core_connect_handler, | ||
662 | &core_disconnect_handler, | ||
663 | core_handlers); | ||
664 | } | ||
665 | |||
666 | /******************************************************************************/ | ||
667 | /******************************************************************************/ | ||
668 | /******************************************************************************/ | ||
669 | /******************************************************************************/ | ||
670 | /******************************************************************************/ | ||
671 | |||
672 | /** | ||
673 | * To be called on core init/fail. | ||
674 | * | ||
675 | * @param cls Closure (config) | ||
676 | * @param identity The public identity of this peer. | ||
677 | */ | ||
678 | static void | ||
679 | core_init_notify (void *cls, | ||
680 | const struct GNUNET_PeerIdentity *core_identity) | ||
681 | { | ||
682 | const struct GNUNET_CONFIGURATION_Handle *c = cls; | ||
683 | |||
684 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Core init\n"); | ||
685 | if (0 != memcmp (core_identity, &my_full_id, sizeof (my_full_id))) | ||
686 | { | ||
687 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n")); | ||
688 | LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (core_identity)); | ||
689 | LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id)); | ||
690 | GNUNET_CORE_disconnect (core_handle); | ||
691 | connect_to_core (c); | ||
692 | return; | ||
693 | } | ||
694 | GML_start (); | ||
695 | } | 517 | } |
696 | 518 | ||
697 | 519 | ||
698 | /******************************************************************************/ | ||
699 | /******************************** STATIC ***********************************/ | ||
700 | /******************************************************************************/ | ||
701 | |||
702 | |||
703 | /** | 520 | /** |
704 | * Get priority for a queued message. | 521 | * Set the message queue to @a mq for peer @a cp and notify watchers. |
705 | * | ||
706 | * @param q Queued message | ||
707 | * | ||
708 | * @return CORE priority to use. | ||
709 | * | 522 | * |
710 | * FIXME make static | 523 | * @param cp peer to modify |
711 | * FIXME use when sending | 524 | * @param mq message queue to set (can be NULL) |
712 | */ | 525 | */ |
713 | enum GNUNET_CORE_Priority | 526 | void |
714 | get_priority (struct CadetPeerQueue *q) | 527 | GCP_set_mq (struct CadetPeer *cp, |
715 | { | 528 | struct GNUNET_MQ_Handle *mq) |
716 | enum GNUNET_CORE_Priority low; | 529 | { |
717 | enum GNUNET_CORE_Priority high; | 530 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
718 | 531 | "Message queue for peer %s is now %p\n", | |
719 | if (NULL == q) | 532 | GCP_2s (cp), |
720 | { | 533 | mq); |
721 | GNUNET_break (0); | 534 | cp->core_mq = mq; |
722 | return GNUNET_CORE_PRIO_BACKGROUND; | 535 | for (struct GCP_MessageQueueManager *mqm = cp->mqm_head, *next; |
723 | } | 536 | NULL != mqm; |
724 | 537 | mqm = next) | |
725 | /* Relayed traffic has lower priority, our own traffic has higher */ | 538 | { |
726 | if (NULL == q->c || GNUNET_NO == GCC_is_origin (q->c, q->c_fwd)) | 539 | /* Save next pointer in case mqm gets freed by the callback */ |
540 | next = mqm->next; | ||
541 | if (NULL == mq) | ||
727 | { | 542 | { |
728 | low = GNUNET_CORE_PRIO_BEST_EFFORT; | 543 | if (NULL != mqm->env) |
729 | high = GNUNET_CORE_PRIO_URGENT; | 544 | { |
545 | GNUNET_MQ_discard (mqm->env); | ||
546 | mqm->env = NULL; | ||
547 | mqm->cb (mqm->cb_cls, | ||
548 | GNUNET_SYSERR); | ||
549 | } | ||
550 | else | ||
551 | { | ||
552 | mqm->cb (mqm->cb_cls, | ||
553 | GNUNET_NO); | ||
554 | } | ||
730 | } | 555 | } |
731 | else | 556 | else |
732 | { | 557 | { |
733 | low = GNUNET_CORE_PRIO_URGENT; | 558 | GNUNET_assert (NULL == mqm->env); |
734 | high = GNUNET_CORE_PRIO_CRITICAL_CONTROL; | 559 | mqm->cb (mqm->cb_cls, |
560 | GNUNET_YES); | ||
735 | } | 561 | } |
562 | } | ||
563 | if ( (NULL != mq) || | ||
564 | (NULL != cp->t) ) | ||
565 | consider_peer_activate (cp); | ||
566 | else | ||
567 | consider_peer_destroy (cp); | ||
736 | 568 | ||
737 | /* Bulky payload has lower priority, control traffic has higher. */ | 569 | if ( (NULL != mq) && |
738 | if (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED == q->type) | 570 | (NULL != cp->t) ) |
739 | return low; | 571 | { |
740 | return high; | 572 | /* have a new, direct path to the target, notify tunnel */ |
741 | } | 573 | struct CadetPeerPath *path; |
742 | |||
743 | |||
744 | /** | ||
745 | * Cancel all messages queued to CORE MQ towards this peer. | ||
746 | * | ||
747 | * @param peer Peer towards which to cancel all messages. | ||
748 | */ | ||
749 | static void | ||
750 | cancel_queued_messages (struct CadetPeer *peer) | ||
751 | { | ||
752 | while (NULL != peer->q_head) | ||
753 | { | ||
754 | struct CadetPeerQueue *q; | ||
755 | |||
756 | q = peer->q_head; | ||
757 | call_peer_cont (q, GNUNET_NO); | ||
758 | GNUNET_free (q); | ||
759 | } | ||
760 | } | ||
761 | |||
762 | |||
763 | /** | ||
764 | * Destroy the peer_info and free any allocated resources linked to it | ||
765 | * | ||
766 | * @param peer The peer_info to destroy. | ||
767 | * @return #GNUNET_OK on success | ||
768 | */ | ||
769 | static int | ||
770 | peer_destroy (struct CadetPeer *peer) | ||
771 | { | ||
772 | struct GNUNET_PeerIdentity id; | ||
773 | struct CadetPeerPath *p; | ||
774 | struct CadetPeerPath *nextp; | ||
775 | |||
776 | GNUNET_PEER_resolve (peer->id, &id); | ||
777 | GNUNET_PEER_change_rc (peer->id, -1); | ||
778 | |||
779 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
780 | "destroying peer %s\n", | ||
781 | GNUNET_i2s (&id)); | ||
782 | |||
783 | if (GNUNET_YES != | ||
784 | GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer)) | ||
785 | { | ||
786 | GNUNET_break (0); | ||
787 | LOG (GNUNET_ERROR_TYPE_WARNING, " peer not in peermap!!\n"); | ||
788 | } | ||
789 | GCP_stop_search (peer); | ||
790 | p = peer->path_head; | ||
791 | while (NULL != p) | ||
792 | { | ||
793 | nextp = p->next; | ||
794 | GNUNET_CONTAINER_DLL_remove (peer->path_head, | ||
795 | peer->path_tail, | ||
796 | p); | ||
797 | path_destroy (p); | ||
798 | p = nextp; | ||
799 | } | ||
800 | if (NULL != peer->tunnel) | ||
801 | GCT_destroy_empty (peer->tunnel); | ||
802 | if (NULL != peer->connections) | ||
803 | { | ||
804 | GNUNET_assert (0 == GNUNET_CONTAINER_multishortmap_size (peer->connections)); | ||
805 | GNUNET_CONTAINER_multishortmap_destroy (peer->connections); | ||
806 | peer->connections = NULL; | ||
807 | } | ||
808 | if (NULL != peer->hello_offer) | ||
809 | { | ||
810 | GNUNET_TRANSPORT_offer_hello_cancel (peer->hello_offer); | ||
811 | peer->hello_offer = NULL; | ||
812 | } | ||
813 | if (NULL != peer->connectivity_suggestion) | ||
814 | { | ||
815 | GNUNET_ATS_connectivity_suggest_cancel (peer->connectivity_suggestion); | ||
816 | peer->connectivity_suggestion = NULL; | ||
817 | } | ||
818 | cancel_queued_messages (peer); | ||
819 | 574 | ||
820 | GNUNET_free_non_null (peer->hello); | 575 | path = GCPP_get_path_from_route (1, |
821 | GNUNET_free (peer); | 576 | &cp->pid); |
822 | return GNUNET_OK; | 577 | GCT_consider_path (cp->t, |
578 | path, | ||
579 | 0); | ||
580 | } | ||
823 | } | 581 | } |
824 | 582 | ||
825 | 583 | ||
826 | /** | 584 | /** |
827 | * Iterator over peer hash map entries to destroy the peer during in_shutdown. | 585 | * Debug function should NEVER return true in production code, useful to |
586 | * simulate losses for testcases. | ||
828 | * | 587 | * |
829 | * @param cls closure | 588 | * @return #GNUNET_YES or #GNUNET_NO with the decision to drop. |
830 | * @param key current key code | ||
831 | * @param value value in the hash map | ||
832 | * @return #GNUNET_YES if we should continue to iterate, | ||
833 | * #GNUNET_NO if not. | ||
834 | */ | 589 | */ |
835 | static int | 590 | static int |
836 | shutdown_peer (void *cls, | 591 | should_I_drop (void) |
837 | const struct GNUNET_PeerIdentity *key, | ||
838 | void *value) | ||
839 | { | 592 | { |
840 | struct CadetPeer *p = value; | 593 | if (0 == drop_percent) |
841 | struct CadetTunnel *t = p->tunnel; | 594 | return GNUNET_NO; |
842 | 595 | if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | |
843 | LOG (GNUNET_ERROR_TYPE_DEBUG, " shutting down %s\n", GCP_2s (p)); | 596 | 101) < drop_percent) |
844 | if (NULL != t) | ||
845 | GCT_destroy (t); | ||
846 | p->tunnel = NULL; | ||
847 | peer_destroy (p); | ||
848 | return GNUNET_YES; | 597 | return GNUNET_YES; |
598 | return GNUNET_NO; | ||
849 | } | 599 | } |
850 | 600 | ||
851 | 601 | ||
852 | /** | 602 | /** |
853 | * Check if peer is searching for a path (either active or delayed search). | 603 | * Function called when CORE took one of the messages from |
854 | * | 604 | * a message queue manager and transmitted it. |
855 | * @param peer Peer to check | ||
856 | * @return #GNUNET_YES if there is a search active. | ||
857 | * #GNUNET_NO otherwise. | ||
858 | */ | ||
859 | static int | ||
860 | is_searching (const struct CadetPeer *peer) | ||
861 | { | ||
862 | return ( (NULL == peer->search_h) && | ||
863 | (NULL == peer->search_delayed) ) ? | ||
864 | GNUNET_NO : GNUNET_YES; | ||
865 | } | ||
866 | |||
867 | |||
868 | /** | ||
869 | * @brief Start a search for a peer. | ||
870 | * | 605 | * |
871 | * @param cls Closure (Peer to search for). | 606 | * @param cls the `struct CadetPeeer` where we made progress |
872 | */ | 607 | */ |
873 | static void | 608 | static void |
874 | delayed_search (void *cls) | 609 | mqm_send_done (void *cls); |
875 | { | ||
876 | struct CadetPeer *peer = cls; | ||
877 | |||
878 | peer->search_delayed = NULL; | ||
879 | GCC_check_connections (); | ||
880 | GCP_start_search (peer); | ||
881 | GCC_check_connections (); | ||
882 | } | ||
883 | 610 | ||
884 | 611 | ||
885 | /** | 612 | /** |
886 | * Returns if peer is used (has a tunnel or is neighbor). | 613 | * Transmit current envelope from this @a mqm. |
887 | * | 614 | * |
888 | * @param peer Peer to check. | 615 | * @param mqm mqm to transmit message for now |
889 | * @return #GNUNET_YES if peer is in use. | ||
890 | */ | 616 | */ |
891 | static int | 617 | static void |
892 | peer_is_used (struct CadetPeer *peer) | 618 | mqm_execute (struct GCP_MessageQueueManager *mqm) |
893 | { | ||
894 | struct CadetPeerPath *p; | ||
895 | |||
896 | if (NULL != peer->tunnel) | ||
897 | return GNUNET_YES; | ||
898 | |||
899 | for (p = peer->path_head; NULL != p; p = p->next) | ||
900 | { | ||
901 | if (p->length < 3) | ||
902 | return GNUNET_YES; | ||
903 | } | ||
904 | return GNUNET_NO; | ||
905 | } | ||
906 | |||
907 | |||
908 | /** | ||
909 | * Iterator over all the peers to get the oldest timestamp. | ||
910 | * | ||
911 | * @param cls Closure (unsued). | ||
912 | * @param key ID of the peer. | ||
913 | * @param value Peer_Info of the peer. | ||
914 | */ | ||
915 | static int | ||
916 | peer_get_oldest (void *cls, | ||
917 | const struct GNUNET_PeerIdentity *key, | ||
918 | void *value) | ||
919 | { | 619 | { |
920 | struct CadetPeer *p = value; | 620 | struct CadetPeer *cp = mqm->cp; |
921 | struct GNUNET_TIME_Absolute *abs = cls; | ||
922 | |||
923 | /* Don't count active peers */ | ||
924 | if (GNUNET_YES == peer_is_used (p)) | ||
925 | return GNUNET_YES; | ||
926 | 621 | ||
927 | if (abs->abs_value_us < p->last_contact.abs_value_us) | 622 | /* Move ready pointer to the next entry that might be ready. */ |
928 | abs->abs_value_us = p->last_contact.abs_value_us; | 623 | if ( (mqm == cp->mqm_ready_ptr) && |
929 | 624 | (NULL != mqm->next) ) | |
930 | return GNUNET_YES; | 625 | cp->mqm_ready_ptr = mqm->next; |
626 | /* Move entry to the end of the DLL, to be fair. */ | ||
627 | if (mqm != cp->mqm_tail) | ||
628 | { | ||
629 | GNUNET_CONTAINER_DLL_remove (cp->mqm_head, | ||
630 | cp->mqm_tail, | ||
631 | mqm); | ||
632 | GNUNET_CONTAINER_DLL_insert_tail (cp->mqm_head, | ||
633 | cp->mqm_tail, | ||
634 | mqm); | ||
635 | } | ||
636 | cp->mqm_ready_counter--; | ||
637 | if (GNUNET_YES == should_I_drop ()) | ||
638 | { | ||
639 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
640 | "DROPPING message to peer %s from MQM %p\n", | ||
641 | GCP_2s (cp), | ||
642 | mqm); | ||
643 | GNUNET_MQ_discard (mqm->env); | ||
644 | mqm->env = NULL; | ||
645 | mqm_send_done (cp); | ||
646 | } | ||
647 | else | ||
648 | { | ||
649 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
650 | "Sending to peer %s from MQM %p\n", | ||
651 | GCP_2s (cp), | ||
652 | mqm); | ||
653 | GNUNET_MQ_send (cp->core_mq, | ||
654 | mqm->env); | ||
655 | mqm->env = NULL; | ||
656 | } | ||
657 | mqm->cb (mqm->cb_cls, | ||
658 | GNUNET_YES); | ||
931 | } | 659 | } |
932 | 660 | ||
933 | 661 | ||
934 | /** | 662 | /** |
935 | * Iterator over all the peers to remove the oldest entry. | 663 | * Find the next ready message in the queue (starting |
664 | * the search from the `cp->mqm_ready_ptr`) and if possible | ||
665 | * execute the transmission. | ||
936 | * | 666 | * |
937 | * @param cls Closure (unsued). | 667 | * @param cp peer to try to send the next ready message to |
938 | * @param key ID of the peer. | ||
939 | * @param value Peer_Info of the peer. | ||
940 | */ | ||
941 | static int | ||
942 | peer_timeout (void *cls, | ||
943 | const struct GNUNET_PeerIdentity *key, | ||
944 | void *value) | ||
945 | { | ||
946 | struct CadetPeer *p = value; | ||
947 | struct GNUNET_TIME_Absolute *abs = cls; | ||
948 | |||
949 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
950 | "peer %s timeout\n", GNUNET_i2s (key)); | ||
951 | |||
952 | if (p->last_contact.abs_value_us == abs->abs_value_us && | ||
953 | GNUNET_NO == peer_is_used (p)) | ||
954 | { | ||
955 | peer_destroy (p); | ||
956 | return GNUNET_NO; | ||
957 | } | ||
958 | return GNUNET_YES; | ||
959 | } | ||
960 | |||
961 | |||
962 | /** | ||
963 | * Delete oldest unused peer. | ||
964 | */ | 668 | */ |
965 | static void | 669 | static void |
966 | peer_delete_oldest (void) | 670 | send_next_ready (struct CadetPeer *cp) |
967 | { | 671 | { |
968 | struct GNUNET_TIME_Absolute abs; | 672 | struct GCP_MessageQueueManager *mqm; |
969 | |||
970 | abs = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
971 | |||
972 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
973 | &peer_get_oldest, | ||
974 | &abs); | ||
975 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
976 | &peer_timeout, | ||
977 | &abs); | ||
978 | } | ||
979 | |||
980 | 673 | ||
981 | /** | 674 | if (0 == cp->mqm_ready_counter) |
982 | * Choose the best (yet unused) path towards a peer, | 675 | return; |
983 | * considering the tunnel properties. | 676 | while ( (NULL != (mqm = cp->mqm_ready_ptr)) && |
984 | * | 677 | (NULL == mqm->env) ) |
985 | * @param peer The destination peer. | 678 | cp->mqm_ready_ptr = mqm->next; |
986 | * @return Best current known path towards the peer, if any. | 679 | if (NULL == mqm) |
987 | */ | 680 | return; /* nothing to do */ |
988 | static struct CadetPeerPath * | 681 | mqm_execute (mqm); |
989 | peer_get_best_path (const struct CadetPeer *peer) | ||
990 | { | ||
991 | struct CadetPeerPath *best_p; | ||
992 | struct CadetPeerPath *p; | ||
993 | unsigned int best_cost; | ||
994 | unsigned int cost; | ||
995 | |||
996 | best_cost = UINT_MAX; | ||
997 | best_p = NULL; | ||
998 | for (p = peer->path_head; NULL != p; p = p->next) | ||
999 | { | ||
1000 | if (GNUNET_NO == path_is_valid (p)) | ||
1001 | continue; /* Don't use invalid paths. */ | ||
1002 | if (GNUNET_YES == GCT_is_path_used (peer->tunnel, p)) | ||
1003 | continue; /* If path is already in use, skip it. */ | ||
1004 | |||
1005 | if ((cost = GCT_get_path_cost (peer->tunnel, p)) < best_cost) | ||
1006 | { | ||
1007 | best_cost = cost; | ||
1008 | best_p = p; | ||
1009 | } | ||
1010 | } | ||
1011 | return best_p; | ||
1012 | } | 682 | } |
1013 | 683 | ||
1014 | 684 | ||
1015 | /** | 685 | /** |
1016 | * Function to process paths received for a new peer addition. The recorded | 686 | * Function called when CORE took one of the messages from |
1017 | * paths form the initial tunnel, which can be optimized later. | 687 | * a message queue manager and transmitted it. |
1018 | * Called on each result obtained for the DHT search. | ||
1019 | * | 688 | * |
1020 | * @param cls Closure (peer towards a path has been found). | 689 | * @param cls the `struct CadetPeeer` where we made progress |
1021 | * @param path Path created from the DHT query. Will be freed afterwards. | ||
1022 | */ | 690 | */ |
1023 | static void | 691 | static void |
1024 | search_handler (void *cls, const struct CadetPeerPath *path) | 692 | mqm_send_done (void *cls) |
1025 | { | 693 | { |
1026 | struct CadetPeer *peer = cls; | 694 | struct CadetPeer *cp = cls; |
1027 | unsigned int connection_count; | ||
1028 | |||
1029 | GCC_check_connections (); | ||
1030 | GCP_add_path_to_all (path, GNUNET_NO); | ||
1031 | |||
1032 | /* Count connections */ | ||
1033 | connection_count = GCT_count_connections (peer->tunnel); | ||
1034 | 695 | ||
1035 | /* If we already have our minimum (or more) connections, it's enough */ | 696 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1036 | if (CONNECTIONS_PER_TUNNEL <= connection_count) | 697 | "Sending to peer %s completed\n", |
1037 | { | 698 | GCP_2s (cp)); |
1038 | GCC_check_connections (); | 699 | send_next_ready (cp); |
1039 | return; | ||
1040 | } | ||
1041 | |||
1042 | if (CADET_TUNNEL_SEARCHING == GCT_get_cstate (peer->tunnel)) | ||
1043 | { | ||
1044 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n"); | ||
1045 | GCP_connect (peer); | ||
1046 | } | ||
1047 | GCC_check_connections (); | ||
1048 | } | ||
1049 | |||
1050 | |||
1051 | /** | ||
1052 | * Test if a message type is connection management traffic | ||
1053 | * or regular payload traffic. | ||
1054 | * | ||
1055 | * @param type Message type. | ||
1056 | * | ||
1057 | * @return #GNUNET_YES if connection management, #GNUNET_NO otherwise. | ||
1058 | */ | ||
1059 | static int | ||
1060 | is_connection_management (uint16_t type) | ||
1061 | { | ||
1062 | return type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_HOP_BY_HOP_ENCRYPTED_ACK || | ||
1063 | type == GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED_POLL; | ||
1064 | } | 700 | } |
1065 | 701 | ||
1066 | 702 | ||
1067 | /** | 703 | /** |
1068 | * Debug function should NEVER return true in production code, useful to | 704 | * Send the message in @a env to @a cp. |
1069 | * simulate losses for testcases. | ||
1070 | * | 705 | * |
1071 | * @return #GNUNET_YES or #GNUNET_NO with the decision to drop. | 706 | * @param mqm the message queue manager to use for transmission |
707 | * @param env envelope with the message to send; must NOT | ||
708 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it | ||
1072 | */ | 709 | */ |
1073 | static int | 710 | void |
1074 | should_I_drop (void) | 711 | GCP_send (struct GCP_MessageQueueManager *mqm, |
712 | struct GNUNET_MQ_Envelope *env) | ||
1075 | { | 713 | { |
1076 | if (0 == drop_percent) | 714 | struct CadetPeer *cp = mqm->cp; |
1077 | return GNUNET_NO; | ||
1078 | 715 | ||
1079 | if (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent) | 716 | GNUNET_assert (NULL != env); |
1080 | return GNUNET_YES; | 717 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1081 | 718 | "Queueing message to peer %s in MQM %p\n", | |
1082 | return GNUNET_NO; | 719 | GCP_2s (cp), |
720 | mqm); | ||
721 | GNUNET_assert (NULL != cp->core_mq); | ||
722 | GNUNET_assert (NULL == mqm->env); | ||
723 | GNUNET_MQ_notify_sent (env, | ||
724 | &mqm_send_done, | ||
725 | cp); | ||
726 | mqm->env = env; | ||
727 | cp->mqm_ready_counter++; | ||
728 | if (mqm != cp->mqm_ready_ptr) | ||
729 | cp->mqm_ready_ptr = cp->mqm_head; | ||
730 | if (1 == cp->mqm_ready_counter) | ||
731 | cp->mqm_ready_ptr = mqm; | ||
732 | if (0 != GNUNET_MQ_get_length (cp->core_mq)) | ||
733 | return; | ||
734 | send_next_ready (cp); | ||
1083 | } | 735 | } |
1084 | 736 | ||
1085 | 737 | ||
1086 | /******************************************************************************/ | ||
1087 | /******************************** API ***********************************/ | ||
1088 | /******************************************************************************/ | ||
1089 | |||
1090 | /** | 738 | /** |
1091 | * Call the continuation after a message has been sent or dropped. | 739 | * Function called to destroy a peer now. |
1092 | * | 740 | * |
1093 | * This funcion removes the message from the queue. | 741 | * @param cls NULL |
1094 | * | 742 | * @param pid identity of the peer (unused) |
1095 | * @param q Queue handle. | 743 | * @param value the `struct CadetPeer` to clean up |
1096 | * @param sent #GNUNET_YES if was sent to CORE, #GNUNET_NO if dropped. | 744 | * @return #GNUNET_OK (continue to iterate) |
1097 | */ | 745 | */ |
1098 | static void | 746 | static int |
1099 | call_peer_cont (struct CadetPeerQueue *q, int sent) | 747 | destroy_iterator_cb (void *cls, |
1100 | { | 748 | const struct GNUNET_PeerIdentity *pid, |
1101 | LOG (GNUNET_ERROR_TYPE_DEBUG, " core mq just sent %s\n", GC_m2s (q->type)); | 749 | void *value) |
1102 | if (NULL != q->cont) | ||
1103 | { | ||
1104 | struct GNUNET_TIME_Relative wait_time; | ||
1105 | |||
1106 | wait_time = GNUNET_TIME_absolute_get_duration (q->queue_timestamp); | ||
1107 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1108 | " calling callback on %s after %s\n", | ||
1109 | GCC_2s (q->c), | ||
1110 | GNUNET_STRINGS_relative_time_to_string (wait_time, GNUNET_NO)); | ||
1111 | q->cont (q->cont_cls, | ||
1112 | q->c, q->c_fwd, sent, | ||
1113 | q->type, | ||
1114 | q->payload_type, | ||
1115 | q->payload_id, | ||
1116 | q->size, wait_time); | ||
1117 | q->cont = NULL; | ||
1118 | } | ||
1119 | GNUNET_CONTAINER_DLL_remove (q->peer->q_head, q->peer->q_tail, q); | ||
1120 | } | ||
1121 | |||
1122 | |||
1123 | /** | ||
1124 | * Function called by MQ when a message is sent to CORE. | ||
1125 | * | ||
1126 | * @param cls Closure (queue handle). | ||
1127 | */ | ||
1128 | static void | ||
1129 | mq_sent (void *cls) | ||
1130 | { | 750 | { |
1131 | struct CadetPeerQueue *q = cls; | 751 | struct CadetPeer *cp = value; |
1132 | 752 | ||
1133 | if (GNUNET_NO == q->management_traffic) | 753 | if (NULL != cp->destroy_task) |
1134 | { | 754 | { |
1135 | q->peer->queue_n--; | 755 | GNUNET_SCHEDULER_cancel (cp->destroy_task); |
1136 | } | 756 | cp->destroy_task = NULL; |
1137 | call_peer_cont (q, GNUNET_YES); | 757 | } |
1138 | GNUNET_free (q); | 758 | destroy_peer (cp); |
759 | return GNUNET_OK; | ||
1139 | } | 760 | } |
1140 | 761 | ||
1141 | 762 | ||
1142 | /** | 763 | /** |
1143 | * Finish the drop operation. | 764 | * Clean up all entries about all peers. |
1144 | * | 765 | * Must only be called after all tunnels, CORE-connections and |
1145 | * @param cls queue entry to finish drop for | 766 | * connections are down. |
1146 | */ | 767 | */ |
1147 | static void | 768 | void |
1148 | drop_cb (void *cls) | 769 | GCP_destroy_all_peers () |
1149 | { | 770 | { |
1150 | struct CadetPeerQueue *q = cls; | 771 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1151 | 772 | "Destroying all peers now\n"); | |
1152 | GNUNET_MQ_discard (q->env); | 773 | GNUNET_CONTAINER_multipeermap_iterate (peers, |
1153 | call_peer_cont (q, GNUNET_YES); | 774 | &destroy_iterator_cb, |
1154 | GNUNET_free (q); | 775 | NULL); |
1155 | } | 776 | } |
1156 | 777 | ||
1157 | 778 | ||
1158 | /** | 779 | /** |
1159 | * @brief Send a message to another peer (using CORE). | 780 | * Drop all paths owned by this peer, and do not |
781 | * allow new ones to be added: We are shutting down. | ||
1160 | * | 782 | * |
1161 | * @param peer Peer towards which to queue the message. | 783 | * @param cp peer to drop paths to |
1162 | * @param message Message to send. | ||
1163 | * @param payload_type Type of the message's payload, for debug messages. | ||
1164 | * 0 if the message is a retransmission (unknown payload). | ||
1165 | * UINT16_MAX if the message does not have payload. | ||
1166 | * @param payload_id ID of the payload (MID, ACK #, etc) | ||
1167 | * @param c Connection this message belongs to (can be NULL). | ||
1168 | * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!) | ||
1169 | * @param cont Continuation to be called once CORE has sent the message. | ||
1170 | * @param cont_cls Closure for @c cont. | ||
1171 | * | ||
1172 | * @return A handle to the message in the queue or NULL (if dropped). | ||
1173 | */ | 784 | */ |
1174 | struct CadetPeerQueue * | 785 | void |
1175 | GCP_send (struct CadetPeer *peer, | 786 | GCP_drop_owned_paths (struct CadetPeer *cp) |
1176 | const struct GNUNET_MessageHeader *message, | ||
1177 | uint16_t payload_type, | ||
1178 | struct CadetEncryptedMessageIdentifier payload_id, | ||
1179 | struct CadetConnection *c, | ||
1180 | int fwd, | ||
1181 | GCP_sent cont, | ||
1182 | void *cont_cls) | ||
1183 | { | 787 | { |
1184 | struct CadetPeerQueue *q; | 788 | struct CadetPeerPath *path; |
1185 | uint16_t type; | ||
1186 | uint16_t size; | ||
1187 | |||
1188 | GCC_check_connections (); | ||
1189 | type = ntohs (message->type); | ||
1190 | size = ntohs (message->size); | ||
1191 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1192 | "que %s (%s %4u) on conn %s (%p) %s towards %s (size %u)\n", | ||
1193 | GC_m2s (type), GC_m2s (payload_type), | ||
1194 | ntohl (payload_id.pid), | ||
1195 | GCC_2s (c), c, GC_f2s (fwd), GCP_2s (peer), size); | ||
1196 | |||
1197 | if (NULL == peer->connections) | ||
1198 | { | ||
1199 | /* We are not connected to this peer, ignore request. */ | ||
1200 | GNUNET_break (0); | ||
1201 | LOG (GNUNET_ERROR_TYPE_INFO, "%s not a neighbor\n", GCP_2s (peer)); | ||
1202 | GNUNET_STATISTICS_update (stats, "# messages dropped due to wrong hop", 1, | ||
1203 | GNUNET_NO); | ||
1204 | return NULL; | ||
1205 | } | ||
1206 | 789 | ||
1207 | q = GNUNET_new (struct CadetPeerQueue); | 790 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1208 | q->env = GNUNET_MQ_msg_copy (message); | 791 | "Destroying all paths to %s\n", |
1209 | q->peer = peer; | 792 | GCP_2s (cp)); |
1210 | q->cont = cont; | 793 | while (NULL != (path = |
1211 | q->cont_cls = cont_cls; | 794 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap))) |
1212 | q->queue_timestamp = GNUNET_TIME_absolute_get (); | 795 | GCPP_release (path); |
1213 | q->management_traffic = is_connection_management (type); | 796 | GNUNET_CONTAINER_heap_destroy (cp->path_heap); |
1214 | q->type = type; | 797 | cp->path_heap = NULL; |
1215 | q->size = size; | ||
1216 | q->payload_type = payload_type; | ||
1217 | q->payload_id = payload_id; | ||
1218 | q->c = c; | ||
1219 | q->c_fwd = fwd; | ||
1220 | GNUNET_MQ_notify_sent (q->env, &mq_sent, q); | ||
1221 | GNUNET_CONTAINER_DLL_insert (peer->q_head, peer->q_tail, q); | ||
1222 | |||
1223 | if (GNUNET_YES == q->management_traffic) | ||
1224 | { | ||
1225 | GNUNET_MQ_send (peer->core_mq, q->env); // FIXME implement "_urgent", use | ||
1226 | } | ||
1227 | else | ||
1228 | { | ||
1229 | if (GNUNET_YES == should_I_drop ()) | ||
1230 | { | ||
1231 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1232 | "DD %s (%s %u) on conn %s %s (random drop for testing)\n", | ||
1233 | GC_m2s (q->type), | ||
1234 | GC_m2s (q->payload_type), | ||
1235 | ntohl (q->payload_id.pid), | ||
1236 | GCC_2s (c), | ||
1237 | GC_f2s (q->c_fwd)); | ||
1238 | q->drop_task = GNUNET_SCHEDULER_add_now (&drop_cb, | ||
1239 | q); | ||
1240 | return q; | ||
1241 | } | ||
1242 | GNUNET_MQ_send (peer->core_mq, q->env); | ||
1243 | peer->queue_n++; | ||
1244 | } | ||
1245 | |||
1246 | GCC_check_connections (); | ||
1247 | return q; | ||
1248 | } | 798 | } |
1249 | 799 | ||
1250 | 800 | ||
1251 | /** | 801 | /** |
1252 | * Cancel sending a message. Message must have been sent with | 802 | * Add an entry to the DLL of all of the paths that this peer is on. |
1253 | * #GCP_send before. May not be called after the notify sent | ||
1254 | * callback has been called. | ||
1255 | * | ||
1256 | * It DOES call the continuation given to #GCP_send. | ||
1257 | * | 803 | * |
1258 | * @param q Queue handle to cancel | 804 | * @param cp peer to modify |
805 | * @param entry an entry on a path | ||
806 | * @param off offset of this peer on the path | ||
1259 | */ | 807 | */ |
1260 | void | 808 | void |
1261 | GCP_send_cancel (struct CadetPeerQueue *q) | 809 | GCP_path_entry_add (struct CadetPeer *cp, |
1262 | { | 810 | struct CadetPeerPathEntry *entry, |
1263 | if (NULL != q->drop_task) | 811 | unsigned int off) |
812 | { | ||
813 | GNUNET_assert (cp == GCPP_get_peer_at_offset (entry->path, | ||
814 | off)); | ||
815 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
816 | "Discovered that peer %s is on path %s at offset %u\n", | ||
817 | GCP_2s (cp), | ||
818 | GCPP_2s (entry->path), | ||
819 | off); | ||
820 | if (off >= cp->path_dll_length) | ||
1264 | { | 821 | { |
1265 | GNUNET_SCHEDULER_cancel (q->drop_task); | 822 | unsigned int len = cp->path_dll_length; |
1266 | q->drop_task = NULL; | 823 | |
1267 | GNUNET_MQ_discard (q->env); | 824 | GNUNET_array_grow (cp->path_heads, |
825 | len, | ||
826 | off + 4); | ||
827 | GNUNET_array_grow (cp->path_tails, | ||
828 | cp->path_dll_length, | ||
829 | off + 4); | ||
1268 | } | 830 | } |
1269 | else | 831 | GNUNET_CONTAINER_DLL_insert (cp->path_heads[off], |
832 | cp->path_tails[off], | ||
833 | entry); | ||
834 | cp->off_sum += off; | ||
835 | cp->num_paths++; | ||
836 | |||
837 | /* If we have a tunnel to this peer, tell the tunnel that there is a | ||
838 | new path available. */ | ||
839 | if (NULL != cp->t) | ||
840 | GCT_consider_path (cp->t, | ||
841 | entry->path, | ||
842 | off); | ||
843 | |||
844 | if ( (NULL != cp->search_h) && | ||
845 | (DESIRED_CONNECTIONS_PER_TUNNEL <= cp->num_paths) ) | ||
1270 | { | 846 | { |
1271 | GNUNET_MQ_send_cancel (q->env); | 847 | /* Now I have enough paths, stop search */ |
848 | GCD_search_stop (cp->search_h); | ||
849 | cp->search_h = NULL; | ||
850 | } | ||
851 | if (NULL != cp->destroy_task) | ||
852 | { | ||
853 | /* paths changed, this resets the destroy timeout counter | ||
854 | and aborts a destroy task that may no longer be valid | ||
855 | to have (as we now have more paths via this peer). */ | ||
856 | consider_peer_destroy (cp); | ||
1272 | } | 857 | } |
1273 | call_peer_cont (q, GNUNET_NO); | ||
1274 | GNUNET_free (q); | ||
1275 | } | 858 | } |
1276 | 859 | ||
1277 | 860 | ||
1278 | /** | 861 | /** |
1279 | * Initialize the peer subsystem. | 862 | * Remove an entry from the DLL of all of the paths that this peer is on. |
1280 | * | 863 | * |
1281 | * @param c Configuration. | 864 | * @param cp peer to modify |
1282 | */ | 865 | * @param entry an entry on a path |
1283 | void | 866 | * @param off offset of this peer on the path |
1284 | GCP_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
1285 | { | ||
1286 | cfg = c; | ||
1287 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1288 | "GCP_init\n"); | ||
1289 | in_shutdown = GNUNET_NO; | ||
1290 | peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); | ||
1291 | if (GNUNET_OK != | ||
1292 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_PEERS", | ||
1293 | &max_peers)) | ||
1294 | { | ||
1295 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1296 | "CADET", "MAX_PEERS", "USING DEFAULT"); | ||
1297 | max_peers = 1000; | ||
1298 | } | ||
1299 | |||
1300 | if (GNUNET_OK != | ||
1301 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DROP_PERCENT", | ||
1302 | &drop_percent)) | ||
1303 | { | ||
1304 | drop_percent = 0; | ||
1305 | } | ||
1306 | else | ||
1307 | { | ||
1308 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1309 | LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n"); | ||
1310 | LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n"); | ||
1311 | LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n"); | ||
1312 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1313 | } | ||
1314 | ats_ch = GNUNET_ATS_connectivity_init (c); | ||
1315 | connect_to_core (c); | ||
1316 | if (NULL == core_handle) | ||
1317 | { | ||
1318 | GNUNET_break (0); | ||
1319 | GNUNET_SCHEDULER_shutdown (); | ||
1320 | } | ||
1321 | } | ||
1322 | |||
1323 | |||
1324 | /** | ||
1325 | * Shut down the peer subsystem. | ||
1326 | */ | 867 | */ |
1327 | void | 868 | void |
1328 | GCP_shutdown (void) | 869 | GCP_path_entry_remove (struct CadetPeer *cp, |
1329 | { | 870 | struct CadetPeerPathEntry *entry, |
1330 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 871 | unsigned int off) |
1331 | "Shutting down peer subsystem\n"); | 872 | { |
1332 | in_shutdown = GNUNET_YES; | 873 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1333 | if (NULL != core_handle) | 874 | "Removing knowledge about peer %s beging on path %s at offset %u\n", |
1334 | { | 875 | GCP_2s (cp), |
1335 | GNUNET_CORE_disconnect (core_handle); | 876 | GCPP_2s (entry->path), |
1336 | core_handle = NULL; | 877 | off); |
1337 | } | 878 | GNUNET_CONTAINER_DLL_remove (cp->path_heads[off], |
1338 | GNUNET_PEER_change_rc (myid, -1); | 879 | cp->path_tails[off], |
1339 | /* With MQ API, CORE calls the disconnect handler for every peer | 880 | entry); |
1340 | * after calling GNUNET_CORE_disconnect, shutdown must occur *after* that. | 881 | GNUNET_assert (0 < cp->num_paths); |
1341 | */ | 882 | cp->off_sum -= off; |
1342 | GNUNET_CONTAINER_multipeermap_iterate (peers, | 883 | cp->num_paths--; |
1343 | &shutdown_peer, | 884 | if ( (NULL == cp->core_mq) && |
1344 | NULL); | 885 | (NULL != cp->t) && |
1345 | if (NULL != ats_ch) | 886 | (NULL == cp->search_h) && |
1346 | { | 887 | (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) ) |
1347 | GNUNET_ATS_connectivity_done (ats_ch); | 888 | cp->search_h |
1348 | ats_ch = NULL; | 889 | = GCD_search (&cp->pid); |
1349 | } | 890 | if (NULL == cp->destroy_task) |
1350 | GNUNET_CONTAINER_multipeermap_destroy (peers); | 891 | { |
1351 | peers = NULL; | 892 | /* paths changed, we might now be ready for destruction, check again */ |
1352 | } | 893 | consider_peer_destroy (cp); |
1353 | 894 | } | |
1354 | |||
1355 | /** | ||
1356 | * Retrieve the CadetPeer stucture associated with the peer. Optionally create | ||
1357 | * one and insert it in the appropriate structures if the peer is not known yet. | ||
1358 | * | ||
1359 | * @param peer_id Full identity of the peer. | ||
1360 | * @param create #GNUNET_YES if a new peer should be created if unknown. | ||
1361 | * #GNUNET_NO otherwise. | ||
1362 | * | ||
1363 | * @return Existing or newly created peer structure. | ||
1364 | * NULL if unknown and not requested @a create | ||
1365 | */ | ||
1366 | struct CadetPeer * | ||
1367 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create) | ||
1368 | { | ||
1369 | struct CadetPeer *peer; | ||
1370 | |||
1371 | peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id); | ||
1372 | if (NULL == peer) | ||
1373 | { | ||
1374 | peer = GNUNET_new (struct CadetPeer); | ||
1375 | if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers) | ||
1376 | { | ||
1377 | peer_delete_oldest (); | ||
1378 | } | ||
1379 | GNUNET_assert (GNUNET_OK == | ||
1380 | GNUNET_CONTAINER_multipeermap_put (peers, | ||
1381 | peer_id, | ||
1382 | peer, | ||
1383 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1384 | peer->id = GNUNET_PEER_intern (peer_id); | ||
1385 | } | ||
1386 | peer->last_contact = GNUNET_TIME_absolute_get (); | ||
1387 | |||
1388 | return peer; | ||
1389 | } | ||
1390 | |||
1391 | |||
1392 | /** | ||
1393 | * Retrieve the CadetPeer stucture associated with the | ||
1394 | * peer. Optionally create one and insert it in the appropriate | ||
1395 | * structures if the peer is not known yet. | ||
1396 | * | ||
1397 | * @param peer Short identity of the peer. | ||
1398 | * @param create #GNUNET_YES if a new peer should be created if unknown. | ||
1399 | * #GNUNET_NO otherwise. | ||
1400 | * | ||
1401 | * @return Existing or newly created peer structure. | ||
1402 | * NULL if unknown and not requested @a create | ||
1403 | */ | ||
1404 | struct CadetPeer * | ||
1405 | GCP_get_short (const GNUNET_PEER_Id peer, int create) | ||
1406 | { | ||
1407 | return GCP_get (GNUNET_PEER_resolve2 (peer), create); | ||
1408 | } | 895 | } |
1409 | 896 | ||
1410 | 897 | ||
1411 | /** | 898 | /** |
1412 | * Function called once #GNUNET_TRANSPORT_offer_hello() is done. | 899 | * Prune down the number of paths to this peer, we seem to |
1413 | * Marks the operation as finished. | 900 | * have way too many. |
1414 | * | 901 | * |
1415 | * @param cls Closure (our `struct CadetPeer`). | 902 | * @param cls the `struct CadetPeer` to maintain the path heap for |
1416 | */ | 903 | */ |
1417 | static void | 904 | static void |
1418 | hello_offer_done (void *cls) | 905 | path_heap_cleanup (void *cls) |
1419 | { | 906 | { |
1420 | struct CadetPeer *peer = cls; | 907 | struct CadetPeer *cp = cls; |
908 | struct CadetPeerPath *root; | ||
1421 | 909 | ||
1422 | peer->hello_offer = NULL; | 910 | cp->heap_cleanup_task = NULL; |
911 | while (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= | ||
912 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) | ||
913 | { | ||
914 | /* Now we have way too many, drop least desirable UNLESS it is in use! | ||
915 | (Note that this intentionally keeps highly desireable, but currently | ||
916 | unused paths around in the hope that we might be able to switch, even | ||
917 | if the number of paths exceeds the threshold.) */ | ||
918 | root = GNUNET_CONTAINER_heap_peek (cp->path_heap); | ||
919 | GNUNET_assert (NULL != root); | ||
920 | if (NULL != | ||
921 | GCPP_get_connection (root, | ||
922 | cp, | ||
923 | GCPP_get_length (root) - 1)) | ||
924 | break; /* can't fix */ | ||
925 | /* Got plenty of paths to this destination, and this is a low-quality | ||
926 | one that we don't care about. Allow it to die. */ | ||
927 | GNUNET_assert (root == | ||
928 | GNUNET_CONTAINER_heap_remove_root (cp->path_heap)); | ||
929 | GCPP_release (root); | ||
930 | } | ||
1423 | } | 931 | } |
1424 | 932 | ||
1425 | 933 | ||
1426 | /** | 934 | /** |
1427 | * Try to establish a new connection to this peer (in its tunnel). | 935 | * Try adding a @a path to this @a peer. If the peer already |
1428 | * If the peer doesn't have any path to it yet, try to get one. | 936 | * has plenty of paths, return NULL. |
1429 | * If the peer already has some path, send a CREATE CONNECTION towards it. | ||
1430 | * | 937 | * |
1431 | * @param peer Peer to connect to. | 938 | * @param cp peer to which the @a path leads to |
939 | * @param path a path looking for an owner; may not be fully initialized yet! | ||
940 | * @param off offset of @a cp in @a path | ||
941 | * @param force force attaching the path | ||
942 | * @return NULL if this peer does not care to become a new owner, | ||
943 | * otherwise the node in the peer's path heap for the @a path. | ||
1432 | */ | 944 | */ |
1433 | void | 945 | struct GNUNET_CONTAINER_HeapNode * |
1434 | GCP_connect (struct CadetPeer *peer) | 946 | GCP_attach_path (struct CadetPeer *cp, |
947 | struct CadetPeerPath *path, | ||
948 | unsigned int off, | ||
949 | int force) | ||
1435 | { | 950 | { |
1436 | struct CadetTunnel *t; | 951 | GNUNET_CONTAINER_HeapCostType desirability; |
1437 | struct CadetPeerPath *path; | 952 | struct CadetPeerPath *root; |
1438 | struct CadetConnection *c; | 953 | GNUNET_CONTAINER_HeapCostType root_desirability; |
1439 | int rerun_search; | 954 | struct GNUNET_CONTAINER_HeapNode *hn; |
1440 | |||
1441 | GCC_check_connections (); | ||
1442 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1443 | "peer_connect towards %s\n", | ||
1444 | GCP_2s (peer)); | ||
1445 | /* If we have a current hello, try to connect using it. */ | ||
1446 | GCP_try_connect (peer); | ||
1447 | 955 | ||
1448 | t = peer->tunnel; | 956 | GNUNET_assert (off == GCPP_get_length (path) - 1); |
1449 | c = NULL; | 957 | GNUNET_assert (cp == GCPP_get_peer_at_offset (path, |
1450 | rerun_search = GNUNET_NO; | 958 | off)); |
1451 | 959 | if (NULL == cp->path_heap) | |
1452 | if (NULL != peer->path_head) | 960 | { |
961 | /* #GCP_drop_owned_paths() was already called, we cannot take new ones! */ | ||
962 | GNUNET_assert (GNUNET_NO == force); | ||
963 | return NULL; | ||
964 | } | ||
965 | desirability = GCPP_get_desirability (path); | ||
966 | if (GNUNET_NO == force) | ||
967 | { | ||
968 | /* FIXME: desirability is not yet initialized; tricky! */ | ||
969 | if (GNUNET_NO == | ||
970 | GNUNET_CONTAINER_heap_peek2 (cp->path_heap, | ||
971 | (void **) &root, | ||
972 | &root_desirability)) | ||
1453 | { | 973 | { |
1454 | LOG (GNUNET_ERROR_TYPE_DEBUG, " some path exists\n"); | 974 | root = NULL; |
1455 | path = peer_get_best_path (peer); | 975 | root_desirability = 0; |
1456 | if (NULL != path) | ||
1457 | { | ||
1458 | char *s; | ||
1459 | |||
1460 | s = path_2s (path); | ||
1461 | LOG (GNUNET_ERROR_TYPE_DEBUG, " path to use: %s\n", s); | ||
1462 | GNUNET_free (s); | ||
1463 | |||
1464 | c = GCT_use_path (t, path); | ||
1465 | if (NULL == c) | ||
1466 | { | ||
1467 | /* This case can happen when the path includes a first hop that is | ||
1468 | * not yet known to be connected. | ||
1469 | * | ||
1470 | * This happens quite often during testing when running cadet | ||
1471 | * under valgrind: core connect notifications come very late | ||
1472 | * and the DHT result has already come and created a valid | ||
1473 | * path. In this case, the peer->connections | ||
1474 | * hashmaps will be NULL and tunnel_use_path will not be able | ||
1475 | * to create a connection from that path. | ||
1476 | * | ||
1477 | * Re-running the DHT GET should give core time to callback. | ||
1478 | * | ||
1479 | * GCT_use_path -> GCC_new -> register_neighbors takes care of | ||
1480 | * updating statistics about this issue. | ||
1481 | */ | ||
1482 | rerun_search = GNUNET_YES; | ||
1483 | } | ||
1484 | else | ||
1485 | { | ||
1486 | GCC_send_create (c); | ||
1487 | return; | ||
1488 | } | ||
1489 | } | ||
1490 | else | ||
1491 | { | ||
1492 | LOG (GNUNET_ERROR_TYPE_DEBUG, " but is NULL, all paths are in use\n"); | ||
1493 | } | ||
1494 | } | 976 | } |
1495 | 977 | ||
1496 | if (GNUNET_YES == rerun_search) | 978 | if ( (DESIRED_CONNECTIONS_PER_TUNNEL > cp->num_paths) && |
979 | (desirability < root_desirability) ) | ||
1497 | { | 980 | { |
1498 | struct GNUNET_TIME_Relative delay; | 981 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1499 | 982 | "Decided to not attach path %p to peer %s due to undesirability\n", | |
1500 | GCP_stop_search (peer); | 983 | GCPP_2s (path), |
1501 | delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100); | 984 | GCP_2s (cp)); |
1502 | peer->search_delayed = GNUNET_SCHEDULER_add_delayed (delay, | 985 | return NULL; |
1503 | &delayed_search, | ||
1504 | peer); | ||
1505 | GCC_check_connections (); | ||
1506 | return; | ||
1507 | } | 986 | } |
987 | } | ||
1508 | 988 | ||
1509 | if (GNUNET_NO == is_searching (peer)) | 989 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1510 | GCP_start_search (peer); | 990 | "Attaching path %s to peer %s (%s)\n", |
1511 | GCC_check_connections (); | 991 | GCPP_2s (path), |
1512 | } | 992 | GCP_2s (cp), |
1513 | 993 | (GNUNET_NO == force) ? "desirable" : "forced"); | |
1514 | |||
1515 | /** | ||
1516 | * Chech whether there is a direct (core level) connection to peer. | ||
1517 | * | ||
1518 | * @param peer Peer to check. | ||
1519 | * | ||
1520 | * @return #GNUNET_YES if there is a direct connection. | ||
1521 | */ | ||
1522 | int | ||
1523 | GCP_is_neighbor (const struct CadetPeer *peer) | ||
1524 | { | ||
1525 | struct CadetPeerPath *path; | ||
1526 | |||
1527 | if (NULL == peer->connections) | ||
1528 | return GNUNET_NO; | ||
1529 | 994 | ||
1530 | for (path = peer->path_head; NULL != path; path = path->next) | 995 | /* Yes, we'd like to add this path, add to our heap */ |
1531 | { | 996 | hn = GNUNET_CONTAINER_heap_insert (cp->path_heap, |
1532 | if (3 > path->length) | 997 | path, |
1533 | return GNUNET_YES; | 998 | desirability); |
1534 | } | ||
1535 | 999 | ||
1536 | /* Is not a neighbor but connections is not NULL, probably disconnecting */ | 1000 | /* Consider maybe dropping other paths because of the new one */ |
1537 | return GNUNET_NO; | 1001 | if ( (GNUNET_CONTAINER_heap_get_size (cp->path_heap) >= |
1002 | 2 * DESIRED_CONNECTIONS_PER_TUNNEL) && | ||
1003 | (NULL != cp->heap_cleanup_task) ) | ||
1004 | cp->heap_cleanup_task = GNUNET_SCHEDULER_add_now (&path_heap_cleanup, | ||
1005 | cp); | ||
1006 | return hn; | ||
1538 | } | 1007 | } |
1539 | 1008 | ||
1540 | 1009 | ||
1541 | /** | 1010 | /** |
1542 | * Create and initialize a new tunnel towards a peer, in case it has none. | 1011 | * This peer can no longer own @a path as the path |
1543 | * In case the peer already has a tunnel, nothing is done. | 1012 | * has been extended and a peer further down the line |
1013 | * is now the new owner. | ||
1544 | * | 1014 | * |
1545 | * Does not generate any traffic, just creates the local data structures. | 1015 | * @param cp old owner of the @a path |
1546 | * | 1016 | * @param path path where the ownership is lost |
1547 | * @param peer Peer towards which to create the tunnel. | 1017 | * @param hn note in @a cp's path heap that must be deleted |
1548 | */ | 1018 | */ |
1549 | void | 1019 | void |
1550 | GCP_add_tunnel (struct CadetPeer *peer) | 1020 | GCP_detach_path (struct CadetPeer *cp, |
1021 | struct CadetPeerPath *path, | ||
1022 | struct GNUNET_CONTAINER_HeapNode *hn) | ||
1551 | { | 1023 | { |
1552 | GCC_check_connections (); | 1024 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1553 | if (NULL != peer->tunnel) | 1025 | "Detatching path %s from peer %s\n", |
1554 | return; | 1026 | GCPP_2s (path), |
1555 | peer->tunnel = GCT_new (peer); | 1027 | GCP_2s (cp)); |
1556 | GCC_check_connections (); | 1028 | GNUNET_assert (path == |
1029 | GNUNET_CONTAINER_heap_remove_node (hn)); | ||
1557 | } | 1030 | } |
1558 | 1031 | ||
1559 | 1032 | ||
1560 | /** | 1033 | /** |
1561 | * Add a connection to a neighboring peer. | 1034 | * Add a @a connection to this @a cp. |
1562 | * | ||
1563 | * Store that the peer is the first hop of the connection in one | ||
1564 | * direction and that on peer disconnect the connection must be | ||
1565 | * notified and destroyed, for it will no longer be valid. | ||
1566 | * | 1035 | * |
1567 | * @param peer Peer to add connection to. | 1036 | * @param cp peer via which the @a connection goes |
1568 | * @param c Connection to add. | 1037 | * @param cc the connection to add |
1569 | * @param pred #GNUNET_YES if we are predecessor, #GNUNET_NO if we are successor | ||
1570 | */ | 1038 | */ |
1571 | void | 1039 | void |
1572 | GCP_add_connection (struct CadetPeer *peer, | 1040 | GCP_add_connection (struct CadetPeer *cp, |
1573 | struct CadetConnection *c, | 1041 | struct CadetConnection *cc) |
1574 | int pred) | 1042 | { |
1575 | { | 1043 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1576 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1044 | "Adding connection %s to peer %s\n", |
1577 | "adding connection %s\n", | 1045 | GCC_2s (cc), |
1578 | GCC_2s (c)); | 1046 | GCP_2s (cp)); |
1579 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1047 | GNUNET_assert (GNUNET_OK == |
1580 | "to peer %s\n", | 1048 | GNUNET_CONTAINER_multishortmap_put (cp->connections, |
1581 | GCP_2s (peer)); | 1049 | &GCC_get_id (cc)->connection_of_tunnel, |
1582 | GNUNET_assert (NULL != peer->connections); | 1050 | cc, |
1583 | GNUNET_assert (GNUNET_OK == | 1051 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); |
1584 | GNUNET_CONTAINER_multishortmap_put (peer->connections, | 1052 | if (NULL != cp->destroy_task) |
1585 | &GCC_get_id (c)->connection_of_tunnel, | 1053 | { |
1586 | c, | 1054 | GNUNET_SCHEDULER_cancel (cp->destroy_task); |
1587 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 1055 | cp->destroy_task = NULL; |
1588 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1056 | } |
1589 | "Peer %s has now %u connections.\n", | ||
1590 | GCP_2s (peer), | ||
1591 | GNUNET_CONTAINER_multishortmap_size (peer->connections)); | ||
1592 | } | ||
1593 | |||
1594 | |||
1595 | /** | ||
1596 | * Add the path to the peer and update the path used to reach it in case this | ||
1597 | * is the shortest. | ||
1598 | * | ||
1599 | * @param peer Destination peer to add the path to. | ||
1600 | * @param path New path to add. Last peer must be @c peer. | ||
1601 | * Path will be either used of freed if already known. | ||
1602 | * @param trusted Do we trust that this path is real? | ||
1603 | * | ||
1604 | * @return path if path was taken, pointer to existing duplicate if exists | ||
1605 | * NULL on error. | ||
1606 | */ | ||
1607 | struct CadetPeerPath * | ||
1608 | GCP_add_path (struct CadetPeer *peer, | ||
1609 | struct CadetPeerPath *path, | ||
1610 | int trusted) | ||
1611 | { | ||
1612 | struct CadetPeerPath *aux; | ||
1613 | unsigned int l; | ||
1614 | unsigned int l2; | ||
1615 | |||
1616 | GCC_check_connections (); | ||
1617 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1618 | "adding path [%u] to peer %s\n", | ||
1619 | path->length, GCP_2s (peer)); | ||
1620 | |||
1621 | if (NULL == peer || NULL == path | ||
1622 | || path->peers[path->length - 1] != peer->id) | ||
1623 | { | ||
1624 | GNUNET_break (0); | ||
1625 | path_destroy (path); | ||
1626 | return NULL; | ||
1627 | } | ||
1628 | |||
1629 | for (l = 1; l < path->length; l++) | ||
1630 | { | ||
1631 | if (path->peers[l] == myid) | ||
1632 | { | ||
1633 | LOG (GNUNET_ERROR_TYPE_DEBUG, " shortening path by %u\n", l); | ||
1634 | for (l2 = 0; l2 < path->length - l; l2++) | ||
1635 | { | ||
1636 | path->peers[l2] = path->peers[l + l2]; | ||
1637 | } | ||
1638 | path->length -= l; | ||
1639 | l = 1; | ||
1640 | path->peers = GNUNET_realloc (path->peers, | ||
1641 | path->length * sizeof (GNUNET_PEER_Id)); | ||
1642 | } | ||
1643 | } | ||
1644 | |||
1645 | LOG (GNUNET_ERROR_TYPE_DEBUG, " final length: %u\n", path->length); | ||
1646 | |||
1647 | if (2 >= path->length && GNUNET_NO == trusted) | ||
1648 | { | ||
1649 | /* Only allow CORE to tell us about direct paths */ | ||
1650 | path_destroy (path); | ||
1651 | return NULL; | ||
1652 | } | ||
1653 | |||
1654 | l = path_get_length (path); | ||
1655 | if (0 == l) | ||
1656 | { | ||
1657 | path_destroy (path); | ||
1658 | return NULL; | ||
1659 | } | ||
1660 | |||
1661 | GNUNET_assert (peer->id == path->peers[path->length - 1]); | ||
1662 | for (aux = peer->path_head; aux != NULL; aux = aux->next) | ||
1663 | { | ||
1664 | l2 = path_get_length (aux); | ||
1665 | if (l2 > l) | ||
1666 | { | ||
1667 | LOG (GNUNET_ERROR_TYPE_DEBUG, " added\n"); | ||
1668 | GNUNET_CONTAINER_DLL_insert_before (peer->path_head, | ||
1669 | peer->path_tail, aux, path); | ||
1670 | goto finish; | ||
1671 | } | ||
1672 | else | ||
1673 | { | ||
1674 | if (l2 == l && memcmp (path->peers, aux->peers, l) == 0) | ||
1675 | { | ||
1676 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already known\n"); | ||
1677 | path_destroy (path); | ||
1678 | return aux; | ||
1679 | } | ||
1680 | } | ||
1681 | } | ||
1682 | GNUNET_CONTAINER_DLL_insert_tail (peer->path_head, | ||
1683 | peer->path_tail, | ||
1684 | path); | ||
1685 | LOG (GNUNET_ERROR_TYPE_DEBUG, " added last\n"); | ||
1686 | |||
1687 | finish: | ||
1688 | if (NULL != peer->tunnel | ||
1689 | && CONNECTIONS_PER_TUNNEL > GCT_count_connections (peer->tunnel) | ||
1690 | && 2 < path->length) /* Direct paths are handled by core_connect */ | ||
1691 | { | ||
1692 | GCP_connect (peer); | ||
1693 | } | ||
1694 | GCC_check_connections (); | ||
1695 | return path; | ||
1696 | } | 1057 | } |
1697 | 1058 | ||
1698 | 1059 | ||
1699 | /** | 1060 | /** |
1700 | * Add the path to the origin peer and update the path used to reach it in case | 1061 | * Remove a @a connection that went via this @a cp. |
1701 | * this is the shortest. | ||
1702 | * The path is given in peer_info -> destination, therefore we turn the path | ||
1703 | * upside down first. | ||
1704 | * | ||
1705 | * @param peer Peer to add the path to, being the origin of the path. | ||
1706 | * @param path New path to add after being inversed. | ||
1707 | * Path will be either used or freed. | ||
1708 | * @param trusted Do we trust that this path is real? | ||
1709 | * | 1062 | * |
1710 | * @return path if path was taken, pointer to existing duplicate if exists | 1063 | * @param cp peer via which the @a connection went |
1711 | * NULL on error. | 1064 | * @param cc the connection to remove |
1712 | */ | 1065 | */ |
1713 | struct CadetPeerPath * | 1066 | void |
1714 | GCP_add_path_to_origin (struct CadetPeer *peer, | 1067 | GCP_remove_connection (struct CadetPeer *cp, |
1715 | struct CadetPeerPath *path, | 1068 | struct CadetConnection *cc) |
1716 | int trusted) | ||
1717 | { | 1069 | { |
1718 | if (NULL == path) | 1070 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1719 | return NULL; | 1071 | "Removing connection %s from peer %s\n", |
1720 | path_invert (path); | 1072 | GCC_2s (cc), |
1721 | return GCP_add_path (peer, path, trusted); | 1073 | GCP_2s (cp)); |
1074 | GNUNET_assert (GNUNET_YES == | ||
1075 | GNUNET_CONTAINER_multishortmap_remove (cp->connections, | ||
1076 | &GCC_get_id (cc)->connection_of_tunnel, | ||
1077 | cc)); | ||
1078 | consider_peer_destroy (cp); | ||
1722 | } | 1079 | } |
1723 | 1080 | ||
1724 | 1081 | ||
1725 | /** | 1082 | /** |
1726 | * Adds a path to the info of all the peers in the path | 1083 | * Retrieve the CadetPeer stucture associated with the |
1084 | * peer. Optionally create one and insert it in the appropriate | ||
1085 | * structures if the peer is not known yet. | ||
1727 | * | 1086 | * |
1728 | * @param p Path to process. | 1087 | * @param peer_id Full identity of the peer. |
1729 | * @param confirmed Whether we know if the path works or not. | 1088 | * @param create #GNUNET_YES if a new peer should be created if unknown. |
1089 | * #GNUNET_NO to return NULL if peer is unknown. | ||
1090 | * @return Existing or newly created peer structure. | ||
1091 | * NULL if unknown and not requested @a create | ||
1730 | */ | 1092 | */ |
1731 | void | 1093 | struct CadetPeer * |
1732 | GCP_add_path_to_all (const struct CadetPeerPath *p, int confirmed) | 1094 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, |
1095 | int create) | ||
1733 | { | 1096 | { |
1734 | unsigned int i; | 1097 | struct CadetPeer *cp; |
1735 | 1098 | ||
1736 | /* TODO: invert and add to origin */ | 1099 | cp = GNUNET_CONTAINER_multipeermap_get (peers, |
1737 | /* TODO: replace all "GCP_add_path" with this, make the other one static */ | 1100 | peer_id); |
1738 | GCC_check_connections (); | 1101 | if (NULL != cp) |
1739 | for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ; | 1102 | return cp; |
1740 | for (i++; i < p->length; i++) | 1103 | if (GNUNET_NO == create) |
1741 | { | 1104 | return NULL; |
1742 | struct CadetPeer *peer; | 1105 | cp = GNUNET_new (struct CadetPeer); |
1743 | struct CadetPeerPath *copy; | 1106 | cp->pid = *peer_id; |
1744 | 1107 | cp->connections = GNUNET_CONTAINER_multishortmap_create (32, | |
1745 | peer = GCP_get_short (p->peers[i], GNUNET_YES); | 1108 | GNUNET_YES); |
1746 | copy = path_duplicate (p); | 1109 | cp->path_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); |
1747 | copy->length = i + 1; | 1110 | GNUNET_assert (GNUNET_YES == |
1748 | GCP_add_path (peer, copy, 3 > p->length ? GNUNET_NO : confirmed); | 1111 | GNUNET_CONTAINER_multipeermap_put (peers, |
1749 | } | 1112 | &cp->pid, |
1750 | GCC_check_connections (); | 1113 | cp, |
1114 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1115 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1116 | "Creating peer %s\n", | ||
1117 | GCP_2s (cp)); | ||
1118 | return cp; | ||
1751 | } | 1119 | } |
1752 | 1120 | ||
1753 | 1121 | ||
1754 | /** | 1122 | /** |
1755 | * Remove any path to the peer that has the exact same peers as the one given. | 1123 | * Obtain the peer identity for a `struct CadetPeer`. |
1756 | * | 1124 | * |
1757 | * @param peer Peer to remove the path from. | 1125 | * @param cp our peer handle |
1758 | * @param path Path to remove. Is always destroyed . | 1126 | * @return the peer identity |
1759 | */ | 1127 | */ |
1760 | void | 1128 | const struct GNUNET_PeerIdentity * |
1761 | GCP_remove_path (struct CadetPeer *peer, | 1129 | GCP_get_id (struct CadetPeer *cp) |
1762 | struct CadetPeerPath *path) | ||
1763 | { | 1130 | { |
1764 | struct CadetPeerPath *iter; | 1131 | return &cp->pid; |
1765 | struct CadetPeerPath *next; | ||
1766 | |||
1767 | GCC_check_connections (); | ||
1768 | GNUNET_assert (myid == path->peers[0]); | ||
1769 | GNUNET_assert (peer->id == path->peers[path->length - 1]); | ||
1770 | |||
1771 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1772 | "Removing path %p (%u) from %s\n", | ||
1773 | path, path->length, GCP_2s (peer)); | ||
1774 | |||
1775 | for (iter = peer->path_head; NULL != iter; iter = next) | ||
1776 | { | ||
1777 | next = iter->next; | ||
1778 | if (0 == path_cmp (path, iter)) | ||
1779 | { | ||
1780 | GNUNET_CONTAINER_DLL_remove (peer->path_head, | ||
1781 | peer->path_tail, | ||
1782 | iter); | ||
1783 | if (iter != path) | ||
1784 | path_destroy (iter); | ||
1785 | } | ||
1786 | } | ||
1787 | path_destroy (path); | ||
1788 | GCC_check_connections (); | ||
1789 | } | 1132 | } |
1790 | 1133 | ||
1791 | 1134 | ||
1792 | /** | 1135 | /** |
1793 | * Check that we are aware of a connection from a neighboring peer. | 1136 | * Iterate over all known peers. |
1794 | * | 1137 | * |
1795 | * @param peer Peer to the connection is with | 1138 | * @param iter Iterator. |
1796 | * @param c Connection that should be in the map with this peer. | 1139 | * @param cls Closure for @c iter. |
1797 | */ | 1140 | */ |
1798 | void | 1141 | void |
1799 | GCP_check_connection (const struct CadetPeer *peer, | 1142 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, |
1800 | const struct CadetConnection *c) | 1143 | void *cls) |
1801 | { | 1144 | { |
1802 | GNUNET_assert (NULL != peer); | 1145 | GNUNET_CONTAINER_multipeermap_iterate (peers, |
1803 | GNUNET_assert (NULL != peer->connections); | 1146 | iter, |
1804 | return; // ???? | 1147 | cls); |
1805 | GNUNET_assert (GNUNET_YES == | ||
1806 | GNUNET_CONTAINER_multishortmap_contains_value (peer->connections, | ||
1807 | &GCC_get_id (c)->connection_of_tunnel, | ||
1808 | c)); | ||
1809 | } | 1148 | } |
1810 | 1149 | ||
1811 | 1150 | ||
1812 | /** | 1151 | /** |
1813 | * Remove a connection from a neighboring peer. | 1152 | * Count the number of known paths toward the peer. |
1814 | * | 1153 | * |
1815 | * @param peer Peer to remove connection from. | 1154 | * @param cp Peer to get path info. |
1816 | * @param c Connection to remove. | 1155 | * @return Number of known paths. |
1817 | */ | 1156 | */ |
1818 | void | 1157 | unsigned int |
1819 | GCP_remove_connection (struct CadetPeer *peer, | 1158 | GCP_count_paths (const struct CadetPeer *cp) |
1820 | const struct CadetConnection *c) | ||
1821 | { | 1159 | { |
1822 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1160 | return cp->num_paths; |
1823 | "Removing connection %s\n", | ||
1824 | GCC_2s (c)); | ||
1825 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1826 | "from peer %s\n", | ||
1827 | GCP_2s (peer)); | ||
1828 | if ( (NULL == peer) || | ||
1829 | (NULL == peer->connections) ) | ||
1830 | return; | ||
1831 | GNUNET_assert (GNUNET_YES == | ||
1832 | GNUNET_CONTAINER_multishortmap_remove (peer->connections, | ||
1833 | &GCC_get_id (c)->connection_of_tunnel, | ||
1834 | c)); | ||
1835 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1836 | "Peer %s remains with %u connections.\n", | ||
1837 | GCP_2s (peer), | ||
1838 | GNUNET_CONTAINER_multishortmap_size (peer->connections)); | ||
1839 | } | 1161 | } |
1840 | 1162 | ||
1841 | 1163 | ||
1842 | /** | 1164 | /** |
1843 | * Start the DHT search for new paths towards the peer: we don't have | 1165 | * Iterate over the paths to a peer. |
1844 | * enough good connections. | ||
1845 | * | 1166 | * |
1846 | * @param peer Destination peer. | 1167 | * @param cp Peer to get path info. |
1168 | * @param callback Function to call for every path. | ||
1169 | * @param callback_cls Closure for @a callback. | ||
1170 | * @return Number of iterated paths. | ||
1847 | */ | 1171 | */ |
1848 | void | 1172 | unsigned int |
1849 | GCP_start_search (struct CadetPeer *peer) | 1173 | GCP_iterate_paths (struct CadetPeer *cp, |
1174 | GCP_PathIterator callback, | ||
1175 | void *callback_cls) | ||
1850 | { | 1176 | { |
1851 | const struct GNUNET_PeerIdentity *id; | 1177 | unsigned int ret = 0; |
1852 | struct CadetTunnel *t = peer->tunnel; | ||
1853 | |||
1854 | GCC_check_connections (); | ||
1855 | if (NULL != peer->search_h) | ||
1856 | { | ||
1857 | GNUNET_break (0); | ||
1858 | return; | ||
1859 | } | ||
1860 | |||
1861 | if (NULL != peer->search_delayed) | ||
1862 | GCP_stop_search (peer); | ||
1863 | |||
1864 | id = GNUNET_PEER_resolve2 (peer->id); | ||
1865 | peer->search_h = GCD_search (id, &search_handler, peer); | ||
1866 | |||
1867 | if (NULL == t) | ||
1868 | { | ||
1869 | /* Why would we search for a peer with no tunnel towards it? */ | ||
1870 | GNUNET_break (0); | ||
1871 | return; | ||
1872 | } | ||
1873 | |||
1874 | if (CADET_TUNNEL_NEW == GCT_get_cstate (t) | ||
1875 | || 0 == GCT_count_any_connections (t)) | ||
1876 | { | ||
1877 | GCT_change_cstate (t, CADET_TUNNEL_SEARCHING); | ||
1878 | } | ||
1879 | GCC_check_connections (); | ||
1880 | } | ||
1881 | 1178 | ||
1179 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1180 | "Iterating over paths to peer %s%s\n", | ||
1181 | GCP_2s (cp), | ||
1182 | (NULL == cp->core_mq) ? "" : " including direct link"); | ||
1183 | if (NULL != cp->core_mq) | ||
1184 | { | ||
1185 | struct CadetPeerPath *path; | ||
1882 | 1186 | ||
1883 | /** | 1187 | path = GCPP_get_path_from_route (1, |
1884 | * Stop the DHT search for new paths towards the peer: we already have | 1188 | &cp->pid); |
1885 | * enough good connections. | 1189 | ret++; |
1886 | * | 1190 | if (GNUNET_NO == |
1887 | * @param peer Destination peer. | 1191 | callback (callback_cls, |
1888 | */ | 1192 | path, |
1889 | void | 1193 | 0)) |
1890 | GCP_stop_search (struct CadetPeer *peer) | 1194 | return ret; |
1891 | { | 1195 | } |
1892 | GCC_check_connections (); | 1196 | for (unsigned int i=0;i<cp->path_dll_length;i++) |
1893 | if (NULL != peer->search_h) | 1197 | { |
1894 | { | 1198 | for (struct CadetPeerPathEntry *pe = cp->path_heads[i]; |
1895 | GCD_search_stop (peer->search_h); | 1199 | NULL != pe; |
1896 | peer->search_h = NULL; | 1200 | pe = pe->next) |
1897 | } | ||
1898 | if (NULL != peer->search_delayed) | ||
1899 | { | 1201 | { |
1900 | GNUNET_SCHEDULER_cancel (peer->search_delayed); | 1202 | ret++; |
1901 | peer->search_delayed = NULL; | 1203 | if (GNUNET_NO == |
1204 | callback (callback_cls, | ||
1205 | pe->path, | ||
1206 | i)) | ||
1207 | return ret; | ||
1902 | } | 1208 | } |
1903 | GCC_check_connections (); | 1209 | } |
1904 | } | 1210 | return ret; |
1905 | |||
1906 | |||
1907 | /** | ||
1908 | * Get the Full ID of a peer. | ||
1909 | * | ||
1910 | * @param peer Peer to get from. | ||
1911 | * | ||
1912 | * @return Full ID of peer. | ||
1913 | */ | ||
1914 | const struct GNUNET_PeerIdentity * | ||
1915 | GCP_get_id (const struct CadetPeer *peer) | ||
1916 | { | ||
1917 | return GNUNET_PEER_resolve2 (peer->id); | ||
1918 | } | 1211 | } |
1919 | 1212 | ||
1920 | 1213 | ||
1921 | /** | 1214 | /** |
1922 | * Get the Short ID of a peer. | 1215 | * Iterate over the paths to @a cp where |
1923 | * | 1216 | * @a cp is at distance @a dist from us. |
1924 | * @param peer Peer to get from. | ||
1925 | * | 1217 | * |
1926 | * @return Short ID of peer. | 1218 | * @param cp Peer to get path info. |
1219 | * @param dist desired distance of @a cp to us on the path | ||
1220 | * @param callback Function to call for every path. | ||
1221 | * @param callback_cls Closure for @a callback. | ||
1222 | * @return Number of iterated paths. | ||
1927 | */ | 1223 | */ |
1928 | GNUNET_PEER_Id | 1224 | unsigned int |
1929 | GCP_get_short_id (const struct CadetPeer *peer) | 1225 | GCP_iterate_paths_at (struct CadetPeer *cp, |
1226 | unsigned int dist, | ||
1227 | GCP_PathIterator callback, | ||
1228 | void *callback_cls) | ||
1930 | { | 1229 | { |
1931 | return peer->id; | 1230 | unsigned int ret = 0; |
1932 | } | ||
1933 | |||
1934 | 1231 | ||
1935 | /** | 1232 | if (dist >= cp->path_dll_length) |
1936 | * Set tunnel. | 1233 | { |
1937 | * | 1234 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1938 | * If tunnel is NULL and there was a search active, stop it, as it's useless. | 1235 | "Asked to look for paths at distance %u, but maximum for me is < %u\n", |
1939 | * | 1236 | dist, |
1940 | * @param peer Peer. | 1237 | cp->path_dll_length); |
1941 | * @param t Tunnel. | 1238 | return 0; |
1942 | */ | 1239 | } |
1943 | void | 1240 | for (struct CadetPeerPathEntry *pe = cp->path_heads[dist]; |
1944 | GCP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel *t) | 1241 | NULL != pe; |
1945 | { | 1242 | pe = pe->next) |
1946 | peer->tunnel = t; | 1243 | { |
1947 | if (NULL == t && GNUNET_YES == is_searching (peer)) | 1244 | if (GNUNET_NO == |
1948 | { | 1245 | callback (callback_cls, |
1949 | GCP_stop_search (peer); | 1246 | pe->path, |
1950 | } | 1247 | dist)) |
1248 | return ret; | ||
1249 | ret++; | ||
1250 | } | ||
1251 | return ret; | ||
1951 | } | 1252 | } |
1952 | 1253 | ||
1953 | 1254 | ||
1954 | /** | 1255 | /** |
1955 | * Get the tunnel towards a peer. | 1256 | * Get the tunnel towards a peer. |
1956 | * | 1257 | * |
1957 | * @param peer Peer to get from. | 1258 | * @param cp Peer to get from. |
1958 | * | 1259 | * @param create #GNUNET_YES to create a tunnel if we do not have one |
1959 | * @return Tunnel towards peer. | 1260 | * @return Tunnel towards peer. |
1960 | */ | 1261 | */ |
1961 | struct CadetTunnel * | 1262 | struct CadetTunnel * |
1962 | GCP_get_tunnel (const struct CadetPeer *peer) | 1263 | GCP_get_tunnel (struct CadetPeer *cp, |
1264 | int create) | ||
1963 | { | 1265 | { |
1964 | if (NULL == peer) | 1266 | if (NULL == cp) |
1965 | return NULL; | 1267 | return NULL; |
1966 | return peer->tunnel; | 1268 | if ( (NULL != cp->t) || |
1269 | (GNUNET_NO == create) ) | ||
1270 | return cp->t; | ||
1271 | cp->t = GCT_create_tunnel (cp); | ||
1272 | consider_peer_activate (cp); | ||
1273 | return cp->t; | ||
1967 | } | 1274 | } |
1968 | 1275 | ||
1969 | 1276 | ||
1970 | /** | 1277 | /** |
1971 | * Set the hello message. | 1278 | * Hello offer was passed to the transport service. Mark it |
1279 | * as done. | ||
1972 | * | 1280 | * |
1973 | * @param peer Peer whose message to set. | 1281 | * @param cls the `struct CadetPeer` where the offer completed |
1974 | * @param hello Hello message. | ||
1975 | */ | 1282 | */ |
1976 | void | 1283 | static void |
1977 | GCP_set_hello (struct CadetPeer *peer, | 1284 | hello_offer_done (void *cls) |
1978 | const struct GNUNET_HELLO_Message *hello) | ||
1979 | { | 1285 | { |
1980 | struct GNUNET_HELLO_Message *old; | 1286 | struct CadetPeer *cp = cls; |
1981 | size_t size; | ||
1982 | 1287 | ||
1983 | GCC_check_connections (); | 1288 | cp->hello_offer = NULL; |
1984 | LOG (GNUNET_ERROR_TYPE_DEBUG, "set hello for %s\n", GCP_2s (peer)); | ||
1985 | if (NULL == hello) | ||
1986 | return; | ||
1987 | |||
1988 | old = GCP_get_hello (peer); | ||
1989 | if (NULL == old) | ||
1990 | { | ||
1991 | size = GNUNET_HELLO_size (hello); | ||
1992 | peer->hello = GNUNET_malloc (size); | ||
1993 | GNUNET_memcpy (peer->hello, hello, size); | ||
1994 | } | ||
1995 | else | ||
1996 | { | ||
1997 | peer->hello = GNUNET_HELLO_merge (old, hello); | ||
1998 | GNUNET_free (old); | ||
1999 | } | ||
2000 | GCC_check_connections (); | ||
2001 | } | 1289 | } |
2002 | 1290 | ||
2003 | 1291 | ||
2004 | /** | 1292 | /** |
2005 | * Get the hello message. | 1293 | * We got a HELLO for a @a peer, remember it, and possibly |
2006 | * | 1294 | * trigger adequate actions (like trying to connect). |
2007 | * @param peer Peer whose message to get. | ||
2008 | * | 1295 | * |
2009 | * @return Hello message. | 1296 | * @param cp the peer we got a HELLO for |
1297 | * @param hello the HELLO to remember | ||
2010 | */ | 1298 | */ |
2011 | struct GNUNET_HELLO_Message * | 1299 | void |
2012 | GCP_get_hello (struct CadetPeer *peer) | 1300 | GCP_set_hello (struct CadetPeer *cp, |
1301 | const struct GNUNET_HELLO_Message *hello) | ||
2013 | { | 1302 | { |
2014 | struct GNUNET_TIME_Absolute expiration; | 1303 | struct GNUNET_HELLO_Message *mrg; |
2015 | struct GNUNET_TIME_Relative remaining; | ||
2016 | |||
2017 | if (NULL == peer->hello) | ||
2018 | return NULL; | ||
2019 | 1304 | ||
2020 | expiration = GNUNET_HELLO_get_last_expiration (peer->hello); | 1305 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2021 | remaining = GNUNET_TIME_absolute_get_remaining (expiration); | 1306 | "Got %u byte HELLO for peer %s\n", |
2022 | if (0 == remaining.rel_value_us) | 1307 | (unsigned int) GNUNET_HELLO_size (hello), |
2023 | { | 1308 | GCP_2s (cp)); |
2024 | LOG (GNUNET_ERROR_TYPE_DEBUG, " get - hello expired on %s\n", | 1309 | if (NULL != cp->hello_offer) |
2025 | GNUNET_STRINGS_absolute_time_to_string (expiration)); | 1310 | { |
2026 | GNUNET_free (peer->hello); | 1311 | GNUNET_TRANSPORT_offer_hello_cancel (cp->hello_offer); |
2027 | peer->hello = NULL; | 1312 | cp->hello_offer = NULL; |
2028 | } | 1313 | } |
2029 | return peer->hello; | 1314 | if (NULL != cp->hello) |
1315 | { | ||
1316 | mrg = GNUNET_HELLO_merge (hello, | ||
1317 | cp->hello); | ||
1318 | GNUNET_free (cp->hello); | ||
1319 | cp->hello = mrg; | ||
1320 | } | ||
1321 | else | ||
1322 | { | ||
1323 | cp->hello = GNUNET_memdup (hello, | ||
1324 | GNUNET_HELLO_size (hello)); | ||
1325 | } | ||
1326 | cp->hello_offer | ||
1327 | = GNUNET_TRANSPORT_offer_hello (cfg, | ||
1328 | GNUNET_HELLO_get_header (cp->hello) , | ||
1329 | &hello_offer_done, | ||
1330 | cp); | ||
1331 | /* New HELLO means cp's destruction time may change... */ | ||
1332 | consider_peer_destroy (cp); | ||
2030 | } | 1333 | } |
2031 | 1334 | ||
2032 | 1335 | ||
2033 | /** | 1336 | /** |
2034 | * Try to connect to a peer on TRANSPORT level. | 1337 | * The tunnel to the given peer no longer exists, remove it from our |
1338 | * data structures, and possibly clean up the peer itself. | ||
2035 | * | 1339 | * |
2036 | * @param peer Peer to whom to connect. | 1340 | * @param cp the peer affected |
1341 | * @param t the dead tunnel | ||
2037 | */ | 1342 | */ |
2038 | void | 1343 | void |
2039 | GCP_try_connect (struct CadetPeer *peer) | 1344 | GCP_drop_tunnel (struct CadetPeer *cp, |
1345 | struct CadetTunnel *t) | ||
2040 | { | 1346 | { |
2041 | struct GNUNET_HELLO_Message *hello; | 1347 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2042 | struct GNUNET_MessageHeader *mh; | 1348 | "Dropping tunnel %s to peer %s\n", |
2043 | 1349 | GCT_2s (t), | |
2044 | if (GNUNET_YES != | 1350 | GCP_2s (cp)); |
2045 | GNUNET_CONFIGURATION_get_value_yesno (cfg, | 1351 | GNUNET_assert (cp->t == t); |
2046 | "CADET", | 1352 | cp->t = NULL; |
2047 | "DISABLE_TRY_CONNECT")) | 1353 | consider_peer_destroy (cp); |
2048 | return; | ||
2049 | GCC_check_connections (); | ||
2050 | if (GNUNET_YES == GCP_is_neighbor (peer)) | ||
2051 | return; | ||
2052 | hello = GCP_get_hello (peer); | ||
2053 | if (NULL == hello) | ||
2054 | return; | ||
2055 | |||
2056 | mh = GNUNET_HELLO_get_header (hello); | ||
2057 | if (NULL != peer->hello_offer) | ||
2058 | { | ||
2059 | GNUNET_TRANSPORT_offer_hello_cancel (peer->hello_offer); | ||
2060 | peer->hello_offer = NULL; | ||
2061 | } | ||
2062 | peer->hello_offer = GNUNET_TRANSPORT_offer_hello (cfg, | ||
2063 | mh, | ||
2064 | &hello_offer_done, | ||
2065 | peer); | ||
2066 | if (NULL == peer->connectivity_suggestion) | ||
2067 | peer->connectivity_suggestion | ||
2068 | = GNUNET_ATS_connectivity_suggest (ats_ch, | ||
2069 | GCP_get_id (peer), | ||
2070 | 1); /* strength */ | ||
2071 | GCC_check_connections (); | ||
2072 | } | 1354 | } |
2073 | 1355 | ||
2074 | 1356 | ||
2075 | /** | 1357 | /** |
2076 | * Notify a peer that a link between two other peers is broken. If any path | 1358 | * Test if @a cp has a core-level connection |
2077 | * used that link, eliminate it. | ||
2078 | * | 1359 | * |
2079 | * @param peer Peer affected by the change. | 1360 | * @param cp peer to test |
2080 | * @param peer1 Peer whose link is broken. | 1361 | * @return #GNUNET_YES if @a cp has a core-level connection |
2081 | * @param peer2 Peer whose link is broken. | ||
2082 | */ | 1362 | */ |
2083 | void | 1363 | int |
2084 | GCP_notify_broken_link (struct CadetPeer *peer, | 1364 | GCP_has_core_connection (struct CadetPeer *cp) |
2085 | const struct GNUNET_PeerIdentity *peer1, | ||
2086 | const struct GNUNET_PeerIdentity *peer2) | ||
2087 | { | 1365 | { |
2088 | struct CadetPeerPath *iter; | 1366 | return (NULL != cp->core_mq) ? GNUNET_YES : GNUNET_NO; |
2089 | struct CadetPeerPath *next; | ||
2090 | unsigned int i; | ||
2091 | GNUNET_PEER_Id p1; | ||
2092 | GNUNET_PEER_Id p2; | ||
2093 | |||
2094 | GCC_check_connections (); | ||
2095 | p1 = GNUNET_PEER_search (peer1); | ||
2096 | p2 = GNUNET_PEER_search (peer2); | ||
2097 | |||
2098 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Link %u-%u broken\n", p1, p2); | ||
2099 | if (0 == p1 || 0 == p2) | ||
2100 | { | ||
2101 | /* We don't even know them */ | ||
2102 | return; | ||
2103 | } | ||
2104 | |||
2105 | for (iter = peer->path_head; NULL != iter; iter = next) | ||
2106 | { | ||
2107 | next = iter->next; | ||
2108 | for (i = 0; i < iter->length - 1; i++) | ||
2109 | { | ||
2110 | if ((iter->peers[i] == p1 && iter->peers[i + 1] == p2) | ||
2111 | || (iter->peers[i] == p2 && iter->peers[i + 1] == p1)) | ||
2112 | { | ||
2113 | char *s; | ||
2114 | |||
2115 | s = path_2s (iter); | ||
2116 | LOG (GNUNET_ERROR_TYPE_DEBUG, " - invalidating %s\n", s); | ||
2117 | GNUNET_free (s); | ||
2118 | |||
2119 | path_invalidate (iter); | ||
2120 | } | ||
2121 | } | ||
2122 | } | ||
2123 | GCC_check_connections (); | ||
2124 | } | 1367 | } |
2125 | 1368 | ||
2126 | 1369 | ||
2127 | /** | 1370 | /** |
2128 | * Count the number of known paths toward the peer. | 1371 | * Start message queue change notifications. |
2129 | * | ||
2130 | * @param peer Peer to get path info. | ||
2131 | * | 1372 | * |
2132 | * @return Number of known paths. | 1373 | * @param cp peer to notify for |
1374 | * @param cb function to call if mq becomes available or unavailable | ||
1375 | * @param cb_cls closure for @a cb | ||
1376 | * @return handle to cancel request | ||
2133 | */ | 1377 | */ |
2134 | unsigned int | 1378 | struct GCP_MessageQueueManager * |
2135 | GCP_count_paths (const struct CadetPeer *peer) | 1379 | GCP_request_mq (struct CadetPeer *cp, |
1380 | GCP_MessageQueueNotificationCallback cb, | ||
1381 | void *cb_cls) | ||
2136 | { | 1382 | { |
2137 | struct CadetPeerPath *iter; | 1383 | struct GCP_MessageQueueManager *mqm; |
2138 | unsigned int i; | ||
2139 | 1384 | ||
2140 | for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next) | 1385 | mqm = GNUNET_new (struct GCP_MessageQueueManager); |
2141 | i++; | 1386 | mqm->cb = cb; |
2142 | 1387 | mqm->cb_cls = cb_cls; | |
2143 | return i; | 1388 | mqm->cp = cp; |
1389 | GNUNET_CONTAINER_DLL_insert (cp->mqm_head, | ||
1390 | cp->mqm_tail, | ||
1391 | mqm); | ||
1392 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1393 | "Creating MQM %p for peer %s\n", | ||
1394 | mqm, | ||
1395 | GCP_2s (cp)); | ||
1396 | if (NULL != cp->core_mq) | ||
1397 | cb (cb_cls, | ||
1398 | GNUNET_YES); | ||
1399 | return mqm; | ||
2144 | } | 1400 | } |
2145 | 1401 | ||
2146 | 1402 | ||
2147 | /** | 1403 | /** |
2148 | * Iterate over the paths to a peer. | 1404 | * Stops message queue change notifications. |
2149 | * | 1405 | * |
2150 | * @param peer Peer to get path info. | 1406 | * @param mqm handle matching request to cancel |
2151 | * @param callback Function to call for every path. | 1407 | * @param last_env final message to transmit, or NULL |
2152 | * @param cls Closure for @a callback. | ||
2153 | * | ||
2154 | * @return Number of iterated paths. | ||
2155 | */ | 1408 | */ |
2156 | unsigned int | 1409 | void |
2157 | GCP_iterate_paths (struct CadetPeer *peer, | 1410 | GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm, |
2158 | GCP_path_iterator callback, | 1411 | struct GNUNET_MQ_Envelope *last_env) |
2159 | void *cls) | 1412 | { |
2160 | { | 1413 | struct CadetPeer *cp = mqm->cp; |
2161 | struct CadetPeerPath *iter; | 1414 | |
2162 | unsigned int i; | 1415 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2163 | 1416 | "Destroying MQM %p for peer %s%s\n", | |
2164 | for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next) | 1417 | mqm, |
1418 | GCP_2s (cp), | ||
1419 | (NULL == last_env) ? "" : " with last ditch transmission"); | ||
1420 | if (NULL != mqm->env) | ||
1421 | GNUNET_MQ_discard (mqm->env); | ||
1422 | if (NULL != last_env) | ||
1423 | { | ||
1424 | if (NULL != cp->core_mq) | ||
2165 | { | 1425 | { |
2166 | i++; | 1426 | GNUNET_MQ_notify_sent (last_env, |
2167 | if (GNUNET_YES != callback (cls, peer, iter)) | 1427 | &mqm_send_done, |
2168 | break; | 1428 | cp); |
1429 | GNUNET_MQ_send (cp->core_mq, | ||
1430 | last_env); | ||
2169 | } | 1431 | } |
2170 | 1432 | else | |
2171 | return i; | 1433 | { |
1434 | GNUNET_MQ_discard (last_env); | ||
1435 | } | ||
1436 | } | ||
1437 | if (cp->mqm_ready_ptr == mqm) | ||
1438 | cp->mqm_ready_ptr = mqm->next; | ||
1439 | GNUNET_CONTAINER_DLL_remove (cp->mqm_head, | ||
1440 | cp->mqm_tail, | ||
1441 | mqm); | ||
1442 | GNUNET_free (mqm); | ||
2172 | } | 1443 | } |
2173 | 1444 | ||
2174 | 1445 | ||
2175 | /** | 1446 | /** |
2176 | * Iterate all known peers. | 1447 | * Send the message in @a env to @a cp, overriding queueing logic. |
1448 | * This function should only be used to send error messages outside | ||
1449 | * of flow and congestion control, similar to ICMP. Note that | ||
1450 | * the envelope may be silently discarded as well. | ||
2177 | * | 1451 | * |
2178 | * @param iter Iterator. | 1452 | * @param cp peer to send the message to |
2179 | * @param cls Closure for @c iter. | 1453 | * @param env envelope with the message to send |
2180 | */ | 1454 | */ |
2181 | void | 1455 | void |
2182 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | 1456 | GCP_send_ooo (struct CadetPeer *cp, |
2183 | void *cls) | 1457 | struct GNUNET_MQ_Envelope *env) |
2184 | { | 1458 | { |
2185 | GCC_check_connections (); | 1459 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2186 | GNUNET_CONTAINER_multipeermap_iterate (peers, | 1460 | "Sending message to %s out of management\n", |
2187 | iter, | 1461 | GCP_2s (cp)); |
2188 | cls); | 1462 | if (NULL == cp->core_mq) |
2189 | GCC_check_connections (); | 1463 | { |
1464 | GNUNET_MQ_discard (env); | ||
1465 | return; | ||
1466 | } | ||
1467 | GNUNET_MQ_notify_sent (env, | ||
1468 | &mqm_send_done, | ||
1469 | cp); | ||
1470 | GNUNET_MQ_send (cp->core_mq, | ||
1471 | env); | ||
2190 | } | 1472 | } |
2191 | 1473 | ||
2192 | 1474 | ||
2193 | /** | ||
2194 | * Get the static string for a peer ID. | ||
2195 | * | ||
2196 | * @param peer Peer. | ||
2197 | * | ||
2198 | * @return Static string for it's ID. | ||
2199 | */ | ||
2200 | const char * | ||
2201 | GCP_2s (const struct CadetPeer *peer) | ||
2202 | { | ||
2203 | if (NULL == peer) | ||
2204 | return "(NULL)"; | ||
2205 | return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id)); | ||
2206 | } | ||
2207 | 1475 | ||
2208 | 1476 | ||
2209 | /* end of gnunet-service-cadet_peer.c */ | 1477 | /* end of gnunet-service-cadet-new_peer.c */ |
diff --git a/src/cadet/gnunet-service-cadet_peer.h b/src/cadet/gnunet-service-cadet_peer.h index 1e206e10f..baa87ea87 100644 --- a/src/cadet/gnunet-service-cadet_peer.h +++ b/src/cadet/gnunet-service-cadet_peer.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2013 GNUnet e.V. | 3 | Copyright (C) 2001-2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -20,464 +20,374 @@ | |||
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @file cadet/gnunet-service-cadet_peer.h | 22 | * @file cadet/gnunet-service-cadet_peer.h |
23 | * @brief cadet service; dealing with remote peers | 23 | * @brief Information we track per peer. |
24 | * @author Bartlomiej Polot | 24 | * @author Bartlomiej Polot |
25 | * | 25 | * @author Christian Grothoff |
26 | * All functions in this file should use the prefix GMP (Gnunet Cadet Peer) | ||
27 | */ | 26 | */ |
28 | |||
29 | #ifndef GNUNET_SERVICE_CADET_PEER_H | 27 | #ifndef GNUNET_SERVICE_CADET_PEER_H |
30 | #define GNUNET_SERVICE_CADET_PEER_H | 28 | #define GNUNET_SERVICE_CADET_PEER_H |
31 | 29 | ||
32 | #ifdef __cplusplus | 30 | #include "gnunet-service-cadet.h" |
33 | extern "C" | 31 | #include "gnunet_hello_lib.h" |
34 | { | ||
35 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
36 | } | ||
37 | #endif | ||
38 | #endif | ||
39 | |||
40 | #include "platform.h" | ||
41 | #include "gnunet_util_lib.h" | ||
42 | #include "cadet_path.h" | ||
43 | 32 | ||
44 | /** | ||
45 | * Struct containing all information regarding a given peer | ||
46 | */ | ||
47 | struct CadetPeer; | ||
48 | |||
49 | /** | ||
50 | * Handle to queued messages on a peer level. | ||
51 | */ | ||
52 | struct CadetPeerQueue; | ||
53 | |||
54 | #include "gnunet-service-cadet_connection.h" | ||
55 | |||
56 | |||
57 | /** | ||
58 | * Callback called when a queued message is sent. | ||
59 | * | ||
60 | * @param cls Closure. | ||
61 | * @param c Connection this message was on. | ||
62 | * @param fwd Was this a FWD going message? | ||
63 | * @param sent Was it really sent? (Could have been canceled) | ||
64 | * @param type Type of message sent. | ||
65 | * @param payload_type Type of payload, if applicable. | ||
66 | * @param pid Message ID, or 0 if not applicable (create, destroy, etc). | ||
67 | * @param size Size of the message. | ||
68 | * @param wait Time spent waiting for core (only the time for THIS message) | ||
69 | */ | ||
70 | typedef void | ||
71 | (*GCP_sent) (void *cls, | ||
72 | struct CadetConnection *c, | ||
73 | int fwd, | ||
74 | int sent, | ||
75 | uint16_t type, | ||
76 | uint16_t payload_type, | ||
77 | struct CadetEncryptedMessageIdentifier pid, | ||
78 | size_t size, | ||
79 | struct GNUNET_TIME_Relative wait); | ||
80 | 33 | ||
81 | /** | 34 | /** |
82 | * Peer path iterator. | 35 | * Get the static string for a peer ID. |
83 | * | 36 | * |
84 | * @param cls Closure. | 37 | * @param peer Peer. |
85 | * @param peer Peer this path is towards. | ||
86 | * @param path Path itself | ||
87 | * @return #GNUNET_YES if should keep iterating. | ||
88 | * #GNUNET_NO otherwise. | ||
89 | */ | ||
90 | typedef int | ||
91 | (*GCP_path_iterator) (void *cls, | ||
92 | struct CadetPeer *peer, | ||
93 | struct CadetPeerPath *path); | ||
94 | |||
95 | |||
96 | /******************************************************************************/ | ||
97 | /******************************** API ***********************************/ | ||
98 | /******************************************************************************/ | ||
99 | |||
100 | /** | ||
101 | * Initialize peer subsystem. | ||
102 | * | 38 | * |
103 | * @param c Configuration. | 39 | * @return Static string for it's ID. |
104 | */ | ||
105 | void | ||
106 | GCP_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
107 | |||
108 | /** | ||
109 | * Shut down the peer subsystem. | ||
110 | */ | 40 | */ |
111 | void | 41 | const char * |
112 | GCP_shutdown (void); | 42 | GCP_2s (const struct CadetPeer *peer); |
113 | 43 | ||
114 | 44 | ||
115 | /** | 45 | /** |
116 | * Retrieve the CadetPeer stucture associated with the peer. Optionally create | 46 | * Retrieve the CadetPeer stucture associated with the |
117 | * one and insert it in the appropriate structures if the peer is not known yet. | 47 | * peer. Optionally create one and insert it in the appropriate |
48 | * structures if the peer is not known yet. | ||
118 | * | 49 | * |
119 | * @param peer_id Full identity of the peer. | 50 | * @param peer_id Full identity of the peer. |
120 | * @param create #GNUNET_YES if a new peer should be created if unknown. | 51 | * @param create #GNUNET_YES if a new peer should be created if unknown. |
121 | * #GNUNET_NO otherwise. | 52 | * #GNUNET_NO to return NULL if peer is unknown. |
122 | * | ||
123 | * @return Existing or newly created peer structure. | 53 | * @return Existing or newly created peer structure. |
124 | * NULL if unknown and not requested @a create | 54 | * NULL if unknown and not requested @a create |
125 | */ | 55 | */ |
126 | struct CadetPeer * | 56 | struct CadetPeer * |
127 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, int create); | 57 | GCP_get (const struct GNUNET_PeerIdentity *peer_id, |
58 | int create); | ||
128 | 59 | ||
129 | 60 | ||
130 | /** | 61 | /** |
131 | * Retrieve the CadetPeer stucture associated with the peer. Optionally create | 62 | * Calculate how desirable a path is for @a cp if |
132 | * one and insert it in the appropriate structures if the peer is not known yet. | 63 | * @a cp is at offset @a off in the path. |
133 | * | ||
134 | * @param peer Short identity of the peer. | ||
135 | * @param create #GNUNET_YES if a new peer should be created if unknown. | ||
136 | * #GNUNET_NO otherwise. | ||
137 | * | 64 | * |
138 | * @return Existing or newly created peer structure. | 65 | * @param cp a peer reachable via a path |
139 | * NULL if unknown and not requested @a create | 66 | * @param off offset of @a cp in a path |
67 | * @return score how useful a path is to reach @a cp, | ||
68 | * positive scores mean path is more desirable | ||
140 | */ | 69 | */ |
141 | struct CadetPeer * | 70 | double |
142 | GCP_get_short (const GNUNET_PEER_Id peer, int create); | 71 | GCP_get_desirability_of_path (struct CadetPeer *cp, |
72 | unsigned int off); | ||
143 | 73 | ||
144 | 74 | ||
145 | /** | 75 | /** |
146 | * Try to establish a new connection to this peer (in its tunnel). | 76 | * Obtain the peer identity for a `struct CadetPeer`. |
147 | * If the peer doesn't have any path to it yet, try to get one. | ||
148 | * If the peer already has some path, send a CREATE CONNECTION towards it. | ||
149 | * | ||
150 | * @param peer Peer to connect to. | ||
151 | */ | ||
152 | void | ||
153 | GCP_connect (struct CadetPeer *peer); | ||
154 | |||
155 | /** | ||
156 | * @brief Send a message to another peer (using CORE). | ||
157 | * | 77 | * |
158 | * @param peer Peer towards which to queue the message. | 78 | * @param cp our peer handle |
159 | * @param message Message to send. | 79 | * @return the peer identity |
160 | * @param payload_type Type of the message's payload, for debug messages. | ||
161 | * 0 if the message is a retransmission (unknown payload). | ||
162 | * UINT16_MAX if the message does not have payload. | ||
163 | * @param payload_id ID of the payload (MID, ACK #, etc) | ||
164 | * @param c Connection this message belongs to (can be NULL). | ||
165 | * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!) | ||
166 | * @param cont Continuation to be called once CORE has sent the message. | ||
167 | * @param cont_cls Closure for @c cont. | ||
168 | */ | 80 | */ |
169 | struct CadetPeerQueue * | 81 | const struct GNUNET_PeerIdentity * |
170 | GCP_send (struct CadetPeer *peer, | 82 | GCP_get_id (struct CadetPeer *cp); |
171 | const struct GNUNET_MessageHeader *message, | ||
172 | uint16_t payload_type, | ||
173 | struct CadetEncryptedMessageIdentifier payload_id, | ||
174 | struct CadetConnection *c, | ||
175 | int fwd, | ||
176 | GCP_sent cont, | ||
177 | void *cont_cls); | ||
178 | 83 | ||
179 | /** | ||
180 | * Cancel sending a message. Message must have been sent with | ||
181 | * #GCP_send before. May not be called after the notify sent | ||
182 | * callback has been called. | ||
183 | * | ||
184 | * It does NOT call the continuation given to #GCP_send. | ||
185 | * | ||
186 | * @param q Queue handle to cancel | ||
187 | */ | ||
188 | void | ||
189 | GCP_send_cancel (struct CadetPeerQueue *q); | ||
190 | 84 | ||
191 | /** | 85 | /** |
192 | * Set tunnel. | 86 | * Iterate over all known peers. |
193 | * | 87 | * |
194 | * @param peer Peer. | 88 | * @param iter Iterator. |
195 | * @param t Tunnel. | 89 | * @param cls Closure for @c iter. |
196 | */ | 90 | */ |
197 | void | 91 | void |
198 | GCP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel *t); | 92 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, |
93 | void *cls); | ||
199 | 94 | ||
200 | 95 | ||
201 | /** | 96 | /** |
202 | * Check whether there is a direct (core level) connection to peer. | 97 | * Count the number of known paths toward the peer. |
203 | * | ||
204 | * @param peer Peer to check. | ||
205 | * | 98 | * |
206 | * @return #GNUNET_YES if there is a direct connection. | 99 | * @param cp Peer to get path info. |
100 | * @return Number of known paths. | ||
207 | */ | 101 | */ |
208 | int | 102 | unsigned int |
209 | GCP_is_neighbor (const struct CadetPeer *peer); | 103 | GCP_count_paths (const struct CadetPeer *cp); |
210 | 104 | ||
211 | 105 | ||
212 | /** | 106 | /** |
213 | * Create and initialize a new tunnel towards a peer, in case it has none. | 107 | * Drop all paths owned by this peer, and do not |
108 | * allow new ones to be added: We are shutting down. | ||
214 | * | 109 | * |
215 | * Does not generate any traffic, just creates the local data structures. | 110 | * @param cp peer to drop paths to |
216 | * | ||
217 | * @param peer Peer towards which to create the tunnel. | ||
218 | */ | 111 | */ |
219 | void | 112 | void |
220 | GCP_add_tunnel (struct CadetPeer *peer); | 113 | GCP_drop_owned_paths (struct CadetPeer *cp); |
221 | 114 | ||
222 | 115 | ||
223 | /** | 116 | /** |
224 | * Add a connection to a neighboring peer. | 117 | * Peer path iterator. |
225 | * | ||
226 | * Store that the peer is the first hop of the connection in one | ||
227 | * direction and that on peer disconnect the connection must be | ||
228 | * notified and destroyed, for it will no longer be valid. | ||
229 | * | 118 | * |
230 | * @param peer Peer to add connection to. | 119 | * @param cls Closure. |
231 | * @param c Connection to add. | 120 | * @param path Path itself |
232 | * @param pred #GNUNET_YES if we are predecessor, #GNUNET_NO if we are successor | 121 | * @param off offset of the target peer in @a path |
122 | * @return #GNUNET_YES if should keep iterating. | ||
123 | * #GNUNET_NO otherwise. | ||
233 | */ | 124 | */ |
234 | void | 125 | typedef int |
235 | GCP_add_connection (struct CadetPeer *peer, | 126 | (*GCP_PathIterator) (void *cls, |
236 | struct CadetConnection *c, | 127 | struct CadetPeerPath *path, |
237 | int pred); | 128 | unsigned int off); |
238 | 129 | ||
239 | 130 | ||
240 | /** | 131 | /** |
241 | * Add the path to the peer and update the path used to reach it in case this | 132 | * Iterate over the paths to a peer. |
242 | * is the shortest. | ||
243 | * | ||
244 | * @param peer Destination peer to add the path to. | ||
245 | * @param path New path to add. Last peer must be the peer in arg 1. | ||
246 | * Path will be either used of freed if already known. | ||
247 | * @param trusted Do we trust that this path is real? | ||
248 | * | 133 | * |
249 | * @return path if path was taken, pointer to existing duplicate if exists | 134 | * @param cp Peer to get path info. |
250 | * NULL on error. | 135 | * @param callback Function to call for every path. |
136 | * @param callback_cls Closure for @a callback. | ||
137 | * @return Number of iterated paths. | ||
251 | */ | 138 | */ |
252 | struct CadetPeerPath * | 139 | unsigned int |
253 | GCP_add_path (struct CadetPeer *peer, | 140 | GCP_iterate_paths (struct CadetPeer *cp, |
254 | struct CadetPeerPath *p, | 141 | GCP_PathIterator callback, |
255 | int trusted); | 142 | void *callback_cls); |
256 | 143 | ||
257 | 144 | ||
258 | /** | 145 | /** |
259 | * Add the path to the origin peer and update the path used to reach it in case | 146 | * Iterate over the paths to @a peer where |
260 | * this is the shortest. | 147 | * @a peer is at distance @a dist from us. |
261 | * The path is given in peer_info -> destination, therefore we turn the path | ||
262 | * upside down first. | ||
263 | * | ||
264 | * @param peer Peer to add the path to, being the origin of the path. | ||
265 | * @param path New path to add after being inversed. | ||
266 | * Path will be either used or freed. | ||
267 | * @param trusted Do we trust that this path is real? | ||
268 | * | 148 | * |
269 | * @return path if path was taken, pointer to existing duplicate if exists | 149 | * @param cp Peer to get path info. |
270 | * NULL on error. | 150 | * @param dist desired distance of @a peer to us on the path |
151 | * @param callback Function to call for every path. | ||
152 | * @param callback_cls Closure for @a callback. | ||
153 | * @return Number of iterated paths. | ||
271 | */ | 154 | */ |
272 | struct CadetPeerPath * | 155 | unsigned int |
273 | GCP_add_path_to_origin (struct CadetPeer *peer, | 156 | GCP_iterate_paths_at (struct CadetPeer *cp, |
274 | struct CadetPeerPath *path, | 157 | unsigned int dist, |
275 | int trusted); | 158 | GCP_PathIterator callback, |
159 | void *callback_cls); | ||
160 | |||
276 | 161 | ||
277 | /** | 162 | /** |
278 | * Adds a path to the info of all the peers in the path | 163 | * Remove an entry from the DLL of all of the paths that this peer is on. |
279 | * | 164 | * |
280 | * @param p Path to process. | 165 | * @param cp peer to modify |
281 | * @param confirmed Whether we know if the path works or not. | 166 | * @param entry an entry on a path |
167 | * @param off offset of this peer on the path | ||
282 | */ | 168 | */ |
283 | void | 169 | void |
284 | GCP_add_path_to_all (const struct CadetPeerPath *p, int confirmed); | 170 | GCP_path_entry_remove (struct CadetPeer *cp, |
171 | struct CadetPeerPathEntry *entry, | ||
172 | unsigned int off); | ||
285 | 173 | ||
286 | 174 | ||
287 | /** | 175 | /** |
288 | * Remove any path to the peer that has the extact same peers as the one given. | 176 | * Add an entry to the DLL of all of the paths that this peer is on. |
289 | * | 177 | * |
290 | * @param peer Peer to remove the path from. | 178 | * @param cp peer to modify |
291 | * @param path Path to remove. Is always destroyed . | 179 | * @param entry an entry on a path |
180 | * @param off offset of this peer on the path | ||
292 | */ | 181 | */ |
293 | void | 182 | void |
294 | GCP_remove_path (struct CadetPeer *peer, | 183 | GCP_path_entry_add (struct CadetPeer *cp, |
295 | struct CadetPeerPath *path); | 184 | struct CadetPeerPathEntry *entry, |
185 | unsigned int off); | ||
296 | 186 | ||
297 | 187 | ||
298 | /** | 188 | /** |
299 | * Check that we are aware of a connection from a neighboring peer. | 189 | * Get the tunnel towards a peer. |
300 | * | 190 | * |
301 | * @param peer Peer to the connection is with | 191 | * @param cp Peer to get from. |
302 | * @param c Connection that should be in the map with this peer. | 192 | * @param create #GNUNET_YES to create a tunnel if we do not have one |
193 | * @return Tunnel towards peer. | ||
303 | */ | 194 | */ |
304 | void | 195 | struct CadetTunnel * |
305 | GCP_check_connection (const struct CadetPeer *peer, | 196 | GCP_get_tunnel (struct CadetPeer *cp, |
306 | const struct CadetConnection *c); | 197 | int create); |
307 | 198 | ||
308 | 199 | ||
309 | /** | 200 | /** |
310 | * Remove a connection from a neighboring peer. | 201 | * The tunnel to the given peer no longer exists, remove it from our |
202 | * data structures, and possibly clean up the peer itself. | ||
311 | * | 203 | * |
312 | * @param peer Peer to remove connection from. | 204 | * @param cp the peer affected |
313 | * @param c Connection to remove. | 205 | * @param t the dead tunnel |
314 | */ | 206 | */ |
315 | void | 207 | void |
316 | GCP_remove_connection (struct CadetPeer *peer, | 208 | GCP_drop_tunnel (struct CadetPeer *cp, |
317 | const struct CadetConnection *c); | 209 | struct CadetTunnel *t); |
318 | 210 | ||
319 | 211 | ||
320 | /** | 212 | /** |
321 | * Start the DHT search for new paths towards the peer: we don't have | 213 | * Try adding a @a path to this @a cp. If the peer already |
322 | * enough good connections. | 214 | * has plenty of paths, return NULL. |
323 | * | 215 | * |
324 | * @param peer Destination peer. | 216 | * @param cp peer to which the @a path leads to |
217 | * @param path a path looking for an owner; may not be fully initialized yet! | ||
218 | * @param off offset of @a cp in @a path | ||
219 | * @param force for attaching the path | ||
220 | * @return NULL if this peer does not care to become a new owner, | ||
221 | * otherwise the node in the peer's path heap for the @a path. | ||
325 | */ | 222 | */ |
326 | void | 223 | struct GNUNET_CONTAINER_HeapNode * |
327 | GCP_start_search (struct CadetPeer *peer); | 224 | GCP_attach_path (struct CadetPeer *cp, |
225 | struct CadetPeerPath *path, | ||
226 | unsigned int off, | ||
227 | int force); | ||
328 | 228 | ||
329 | 229 | ||
330 | /** | 230 | /** |
331 | * Stop the DHT search for new paths towards the peer: we already have | 231 | * This peer can no longer own @a path as the path |
332 | * enough good connections. | 232 | * has been extended and a peer further down the line |
233 | * is now the new owner. | ||
333 | * | 234 | * |
334 | * @param peer Destination peer. | 235 | * @param cp old owner of the @a path |
236 | * @param path path where the ownership is lost | ||
237 | * @param hn note in @a cp's path heap that must be deleted | ||
335 | */ | 238 | */ |
336 | void | 239 | void |
337 | GCP_stop_search (struct CadetPeer *peer); | 240 | GCP_detach_path (struct CadetPeer *cp, |
241 | struct CadetPeerPath *path, | ||
242 | struct GNUNET_CONTAINER_HeapNode *hn); | ||
338 | 243 | ||
339 | 244 | ||
340 | /** | 245 | /** |
341 | * Get the Full ID of a peer. | 246 | * Add a @a connection to this @a cp. |
342 | * | 247 | * |
343 | * @param peer Peer to get from. | 248 | * @param cp peer via which the @a connection goes |
344 | * | 249 | * @param cc the connection to add |
345 | * @return Full ID of peer. | ||
346 | */ | 250 | */ |
347 | const struct GNUNET_PeerIdentity * | 251 | void |
348 | GCP_get_id (const struct CadetPeer *peer); | 252 | GCP_add_connection (struct CadetPeer *cp, |
253 | struct CadetConnection *cc); | ||
349 | 254 | ||
350 | 255 | ||
351 | /** | 256 | /** |
352 | * Get the Short ID of a peer. | 257 | * Remove a @a connection that went via this @a cp. |
353 | * | ||
354 | * @param peer Peer to get from. | ||
355 | * | 258 | * |
356 | * @return Short ID of peer. | 259 | * @param cp peer via which the @a connection went |
260 | * @param cc the connection to remove | ||
357 | */ | 261 | */ |
358 | GNUNET_PEER_Id | 262 | void |
359 | GCP_get_short_id (const struct CadetPeer *peer); | 263 | GCP_remove_connection (struct CadetPeer *cp, |
264 | struct CadetConnection *cc); | ||
360 | 265 | ||
361 | 266 | ||
362 | /** | 267 | /** |
363 | * Get the tunnel towards a peer. | 268 | * We got a HELLO for a @a cp, remember it, and possibly |
269 | * trigger adequate actions (like trying to connect). | ||
364 | * | 270 | * |
365 | * @param peer Peer to get from. | 271 | * @param cp the peer we got a HELLO for |
366 | * | 272 | * @param hello the HELLO to remember |
367 | * @return Tunnel towards peer. | ||
368 | */ | 273 | */ |
369 | struct CadetTunnel * | 274 | void |
370 | GCP_get_tunnel (const struct CadetPeer *peer); | 275 | GCP_set_hello (struct CadetPeer *cp, |
276 | const struct GNUNET_HELLO_Message *hello); | ||
371 | 277 | ||
372 | 278 | ||
373 | /** | 279 | /** |
374 | * Set the hello message. | 280 | * Clean up all entries about all peers. |
375 | * | 281 | * Must only be called after all tunnels, CORE-connections and |
376 | * @param peer Peer whose message to set. | 282 | * connections are down. |
377 | * @param hello Hello message. | ||
378 | */ | 283 | */ |
379 | void | 284 | void |
380 | GCP_set_hello (struct CadetPeer *peer, | 285 | GCP_destroy_all_peers (void); |
381 | const struct GNUNET_HELLO_Message *hello); | ||
382 | 286 | ||
383 | 287 | ||
384 | /** | 288 | /** |
385 | * Get the hello message. | 289 | * Data structure used to track whom we have to notify about changes |
386 | * | 290 | * in our ability to transmit to a given peer. |
387 | * @param peer Peer whose message to get. | ||
388 | * | 291 | * |
389 | * @return Hello message. | 292 | * All queue managers will be given equal chance for sending messages |
293 | * to @a cp. This construct this guarantees fairness for access to @a | ||
294 | * cp among the different message queues. Each connection or route | ||
295 | * will have its respective message queue managers for each direction. | ||
390 | */ | 296 | */ |
391 | struct GNUNET_HELLO_Message * | 297 | struct GCP_MessageQueueManager; |
392 | GCP_get_hello (struct CadetPeer *peer); | ||
393 | 298 | ||
394 | 299 | ||
395 | /** | 300 | /** |
396 | * Try to connect to a peer on TRANSPORT level. | 301 | * Function to call with updated message queue object. |
397 | * | 302 | * |
398 | * @param peer Peer to whom to connect. | 303 | * @param cls closure |
304 | * @param available #GNUNET_YES if sending is now possible, | ||
305 | * #GNUNET_NO if sending is no longer possible | ||
306 | * #GNUNET_SYSERR if sending is no longer possible | ||
307 | * and the last envelope was discarded | ||
399 | */ | 308 | */ |
400 | void | 309 | typedef void |
401 | GCP_try_connect (struct CadetPeer *peer); | 310 | (*GCP_MessageQueueNotificationCallback)(void *cls, |
311 | int available); | ||
312 | |||
402 | 313 | ||
403 | /** | 314 | /** |
404 | * Notify a peer that a link between two other peers is broken. If any path | 315 | * Start message queue change notifications. Will create a new slot |
405 | * used that link, eliminate it. | 316 | * to manage the message queue to the given @a cp. |
406 | * | 317 | * |
407 | * @param peer Peer affected by the change. | 318 | * @param cp peer to notify for |
408 | * @param peer1 Peer whose link is broken. | 319 | * @param cb function to call if mq becomes available or unavailable |
409 | * @param peer2 Peer whose link is broken. | 320 | * @param cb_cls closure for @a cb |
321 | * @return handle to cancel request | ||
410 | */ | 322 | */ |
411 | void | 323 | struct GCP_MessageQueueManager * |
412 | GCP_notify_broken_link (struct CadetPeer *peer, | 324 | GCP_request_mq (struct CadetPeer *cp, |
413 | const struct GNUNET_PeerIdentity *peer1, | 325 | GCP_MessageQueueNotificationCallback cb, |
414 | const struct GNUNET_PeerIdentity *peer2); | 326 | void *cb_cls); |
415 | 327 | ||
416 | 328 | ||
417 | /** | 329 | /** |
418 | * Count the number of known paths toward the peer. | 330 | * Test if @a cp has a core-level connection |
419 | * | 331 | * |
420 | * @param peer Peer to get path info. | 332 | * @param cp peer to test |
421 | * | 333 | * @return #GNUNET_YES if @a cp has a core-level connection |
422 | * @return Number of known paths. | ||
423 | */ | 334 | */ |
424 | unsigned int | 335 | int |
425 | GCP_count_paths (const struct CadetPeer *peer); | 336 | GCP_has_core_connection (struct CadetPeer *cp); |
337 | |||
426 | 338 | ||
427 | /** | 339 | /** |
428 | * Iterate over the paths to a peer. | 340 | * Send the message in @a env via a @a mqm. Must only be called at |
341 | * most once after the respective | ||
342 | * #GCP_MessageQueueNotificationCallback was called with `available` | ||
343 | * set to #GNUNET_YES, and not after the callback was called with | ||
344 | * `available` set to #GNUNET_NO or #GNUNET_SYSERR. | ||
429 | * | 345 | * |
430 | * @param peer Peer to get path info. | 346 | * @param mqm message queue manager for the transmission |
431 | * @param callback Function to call for every path. | 347 | * @param env envelope with the message to send; must NOT |
432 | * @param cls Closure for @a callback. | 348 | * yet have a #GNUNET_MQ_notify_sent() callback attached to it |
433 | * | ||
434 | * @return Number of iterated paths. | ||
435 | */ | 349 | */ |
436 | unsigned int | 350 | void |
437 | GCP_iterate_paths (struct CadetPeer *peer, | 351 | GCP_send (struct GCP_MessageQueueManager *mqm, |
438 | GCP_path_iterator callback, | 352 | struct GNUNET_MQ_Envelope *env); |
439 | void *cls); | ||
440 | 353 | ||
441 | 354 | ||
442 | /** | 355 | /** |
443 | * Iterate all known peers. | 356 | * Send the message in @a env to @a cp, overriding queueing logic. |
357 | * This function should only be used to send error messages outside | ||
358 | * of flow and congestion control, similar to ICMP. Note that | ||
359 | * the envelope may be silently discarded as well. | ||
444 | * | 360 | * |
445 | * @param iter Iterator. | 361 | * @param cp peer to send the message to |
446 | * @param cls Closure for @c iter. | 362 | * @param env envelope with the message to send |
447 | */ | 363 | */ |
448 | void | 364 | void |
449 | GCP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, | 365 | GCP_send_ooo (struct CadetPeer *cp, |
450 | void *cls); | 366 | struct GNUNET_MQ_Envelope *env); |
451 | 367 | ||
452 | 368 | ||
453 | /** | 369 | /** |
454 | * Get the static string for a peer ID. | 370 | * Stops message queue change notifications and sends a last message. |
455 | * | 371 | * In practice, this is implemented by sending that @a last_env |
456 | * @param peer Peer. | 372 | * message immediately (if any), ignoring queue order. |
457 | * | 373 | * |
458 | * @return Static string for it's ID. | 374 | * @param mqm handle matching request to cancel |
375 | * @param last_env final message to transmit, or NULL | ||
459 | */ | 376 | */ |
460 | const char * | 377 | void |
461 | GCP_2s (const struct CadetPeer *peer); | 378 | GCP_request_mq_cancel (struct GCP_MessageQueueManager *mqm, |
379 | struct GNUNET_MQ_Envelope *last_env); | ||
462 | 380 | ||
463 | 381 | ||
464 | /** | 382 | /** |
465 | * Log all kinds of info about a peer. | 383 | * Set the message queue to @a mq for peer @a cp and notify watchers. |
466 | * | 384 | * |
467 | * @param peer Peer. | 385 | * @param cp peer to modify |
386 | * @param mq message queue to set (can be NULL) | ||
468 | */ | 387 | */ |
469 | void | 388 | void |
470 | GCP_debug (const struct CadetPeer *p, | 389 | GCP_set_mq (struct CadetPeer *cp, |
471 | enum GNUNET_ErrorType level); | 390 | struct GNUNET_MQ_Handle *mq); |
472 | |||
473 | 391 | ||
474 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
475 | { | ||
476 | #endif | ||
477 | #ifdef __cplusplus | ||
478 | } | ||
479 | #endif | ||
480 | 392 | ||
481 | /* ifndef GNUNET_CADET_SERVICE_PEER_H */ | ||
482 | #endif | 393 | #endif |
483 | /* end of gnunet-cadet-service_peer.h */ | ||
diff --git a/src/cadet/gnunet-service-cadet_tunnel.c b/src/cadet/gnunet-service-cadet_tunnel.c deleted file mode 100644 index 3b21f4107..000000000 --- a/src/cadet/gnunet-service-cadet_tunnel.c +++ /dev/null | |||
@@ -1,3501 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-service-cadet_tunnel.c | ||
22 | * @brief logical links between CADET clients | ||
23 | * @author Bartlomiej Polot | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "gnunet_signatures.h" | ||
28 | #include "gnunet_statistics_service.h" | ||
29 | #include "cadet_protocol.h" | ||
30 | #include "cadet_path.h" | ||
31 | #include "gnunet-service-cadet_tunnel.h" | ||
32 | #include "gnunet-service-cadet_connection.h" | ||
33 | #include "gnunet-service-cadet_channel.h" | ||
34 | #include "gnunet-service-cadet_peer.h" | ||
35 | |||
36 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__) | ||
37 | #define LOG2(level, ...) GNUNET_log_from_nocheck(level,"cadet-tun",__VA_ARGS__) | ||
38 | |||
39 | #define REKEY_WAIT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5) | ||
40 | |||
41 | #if !defined(GNUNET_CULL_LOGGING) | ||
42 | #define DUMP_KEYS_TO_STDERR GNUNET_YES | ||
43 | #else | ||
44 | #define DUMP_KEYS_TO_STDERR GNUNET_NO | ||
45 | #endif | ||
46 | |||
47 | #define MIN_TUNNEL_BUFFER 8 | ||
48 | #define MAX_TUNNEL_BUFFER 64 | ||
49 | #define MAX_SKIPPED_KEYS 64 | ||
50 | #define MAX_KEY_GAP 256 | ||
51 | #define AX_HEADER_SIZE (sizeof (uint32_t) * 2\ | ||
52 | + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)) | ||
53 | |||
54 | /******************************************************************************/ | ||
55 | /******************************** STRUCTS **********************************/ | ||
56 | /******************************************************************************/ | ||
57 | |||
58 | struct CadetTChannel | ||
59 | { | ||
60 | struct CadetTChannel *next; | ||
61 | struct CadetTChannel *prev; | ||
62 | struct CadetChannel *ch; | ||
63 | }; | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Entry in list of connections used by tunnel, with metadata. | ||
68 | */ | ||
69 | struct CadetTConnection | ||
70 | { | ||
71 | /** | ||
72 | * Next in DLL. | ||
73 | */ | ||
74 | struct CadetTConnection *next; | ||
75 | |||
76 | /** | ||
77 | * Prev in DLL. | ||
78 | */ | ||
79 | struct CadetTConnection *prev; | ||
80 | |||
81 | /** | ||
82 | * Connection handle. | ||
83 | */ | ||
84 | struct CadetConnection *c; | ||
85 | |||
86 | /** | ||
87 | * Creation time, to keep oldest connection alive. | ||
88 | */ | ||
89 | struct GNUNET_TIME_Absolute created; | ||
90 | |||
91 | /** | ||
92 | * Connection throughput, to keep fastest connection alive. | ||
93 | */ | ||
94 | uint32_t throughput; | ||
95 | }; | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Struct to old keys for skipped messages while advancing the Axolotl ratchet. | ||
100 | */ | ||
101 | struct CadetTunnelSkippedKey | ||
102 | { | ||
103 | /** | ||
104 | * DLL next. | ||
105 | */ | ||
106 | struct CadetTunnelSkippedKey *next; | ||
107 | |||
108 | /** | ||
109 | * DLL prev. | ||
110 | */ | ||
111 | struct CadetTunnelSkippedKey *prev; | ||
112 | |||
113 | /** | ||
114 | * When was this key stored (for timeout). | ||
115 | */ | ||
116 | struct GNUNET_TIME_Absolute timestamp; | ||
117 | |||
118 | /** | ||
119 | * Header key. | ||
120 | */ | ||
121 | struct GNUNET_CRYPTO_SymmetricSessionKey HK; | ||
122 | |||
123 | /** | ||
124 | * Message key. | ||
125 | */ | ||
126 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | ||
127 | |||
128 | /** | ||
129 | * Key number for a given HK. | ||
130 | */ | ||
131 | unsigned int Kn; | ||
132 | }; | ||
133 | |||
134 | |||
135 | /** | ||
136 | * Axolotl data, according to https://github.com/trevp/axolotl/wiki . | ||
137 | */ | ||
138 | struct CadetTunnelAxolotl | ||
139 | { | ||
140 | /** | ||
141 | * A (double linked) list of stored message keys and associated header keys | ||
142 | * for "skipped" messages, i.e. messages that have not been | ||
143 | * received despite the reception of more recent messages, (head). | ||
144 | */ | ||
145 | struct CadetTunnelSkippedKey *skipped_head; | ||
146 | |||
147 | /** | ||
148 | * Skipped messages' keys DLL, tail. | ||
149 | */ | ||
150 | struct CadetTunnelSkippedKey *skipped_tail; | ||
151 | |||
152 | /** | ||
153 | * Elements in @a skipped_head <-> @a skipped_tail. | ||
154 | */ | ||
155 | unsigned int skipped; | ||
156 | |||
157 | /** | ||
158 | * 32-byte root key which gets updated by DH ratchet. | ||
159 | */ | ||
160 | struct GNUNET_CRYPTO_SymmetricSessionKey RK; | ||
161 | |||
162 | /** | ||
163 | * 32-byte header key (send). | ||
164 | */ | ||
165 | struct GNUNET_CRYPTO_SymmetricSessionKey HKs; | ||
166 | |||
167 | /** | ||
168 | * 32-byte header key (recv) | ||
169 | */ | ||
170 | struct GNUNET_CRYPTO_SymmetricSessionKey HKr; | ||
171 | |||
172 | /** | ||
173 | * 32-byte next header key (send). | ||
174 | */ | ||
175 | struct GNUNET_CRYPTO_SymmetricSessionKey NHKs; | ||
176 | |||
177 | /** | ||
178 | * 32-byte next header key (recv). | ||
179 | */ | ||
180 | struct GNUNET_CRYPTO_SymmetricSessionKey NHKr; | ||
181 | |||
182 | /** | ||
183 | * 32-byte chain keys (used for forward-secrecy updating, send). | ||
184 | */ | ||
185 | struct GNUNET_CRYPTO_SymmetricSessionKey CKs; | ||
186 | |||
187 | /** | ||
188 | * 32-byte chain keys (used for forward-secrecy updating, recv). | ||
189 | */ | ||
190 | struct GNUNET_CRYPTO_SymmetricSessionKey CKr; | ||
191 | |||
192 | /** | ||
193 | * ECDH for key exchange (A0 / B0). | ||
194 | */ | ||
195 | struct GNUNET_CRYPTO_EcdhePrivateKey *kx_0; | ||
196 | |||
197 | /** | ||
198 | * ECDH Ratchet key (send). | ||
199 | */ | ||
200 | struct GNUNET_CRYPTO_EcdhePrivateKey *DHRs; | ||
201 | |||
202 | /** | ||
203 | * ECDH Ratchet key (recv). | ||
204 | */ | ||
205 | struct GNUNET_CRYPTO_EcdhePublicKey DHRr; | ||
206 | |||
207 | /** | ||
208 | * Message number (reset to 0 with each new ratchet, next message to send). | ||
209 | */ | ||
210 | uint32_t Ns; | ||
211 | |||
212 | /** | ||
213 | * Message number (reset to 0 with each new ratchet, next message to recv). | ||
214 | */ | ||
215 | uint32_t Nr; | ||
216 | |||
217 | /** | ||
218 | * Previous message numbers (# of msgs sent under prev ratchet) | ||
219 | */ | ||
220 | uint32_t PNs; | ||
221 | |||
222 | /** | ||
223 | * True (#GNUNET_YES) if we have to send a new ratchet key in next msg. | ||
224 | */ | ||
225 | int ratchet_flag; | ||
226 | |||
227 | /** | ||
228 | * Number of messages recieved since our last ratchet advance. | ||
229 | * - If this counter = 0, we cannot send a new ratchet key in next msg. | ||
230 | * - If this counter > 0, we can (but don't yet have to) send a new key. | ||
231 | */ | ||
232 | unsigned int ratchet_allowed; | ||
233 | |||
234 | /** | ||
235 | * Number of messages recieved since our last ratchet advance. | ||
236 | * - If this counter = 0, we cannot send a new ratchet key in next msg. | ||
237 | * - If this counter > 0, we can (but don't yet have to) send a new key. | ||
238 | */ | ||
239 | unsigned int ratchet_counter; | ||
240 | |||
241 | /** | ||
242 | * When does this ratchet expire and a new one is triggered. | ||
243 | */ | ||
244 | struct GNUNET_TIME_Absolute ratchet_expiration; | ||
245 | }; | ||
246 | |||
247 | |||
248 | /** | ||
249 | * Struct containing all information regarding a tunnel to a peer. | ||
250 | */ | ||
251 | struct CadetTunnel | ||
252 | { | ||
253 | /** | ||
254 | * Endpoint of the tunnel. | ||
255 | */ | ||
256 | struct CadetPeer *peer; | ||
257 | |||
258 | /** | ||
259 | * Axolotl info. | ||
260 | */ | ||
261 | struct CadetTunnelAxolotl *ax; | ||
262 | |||
263 | /** | ||
264 | * State of the tunnel connectivity. | ||
265 | */ | ||
266 | enum CadetTunnelCState cstate; | ||
267 | |||
268 | /** | ||
269 | * State of the tunnel encryption. | ||
270 | */ | ||
271 | enum CadetTunnelEState estate; | ||
272 | |||
273 | /** | ||
274 | * Peer's ephemeral key, to recreate @c e_key and @c d_key when own ephemeral | ||
275 | * key changes. | ||
276 | */ | ||
277 | struct GNUNET_CRYPTO_EcdhePublicKey peers_ephemeral_key; | ||
278 | |||
279 | /** | ||
280 | * Encryption ("our") key. It is only "confirmed" if kx_ctx is NULL. | ||
281 | */ | ||
282 | struct GNUNET_CRYPTO_SymmetricSessionKey e_key; | ||
283 | |||
284 | /** | ||
285 | * Decryption ("their") key. It is only "confirmed" if kx_ctx is NULL. | ||
286 | */ | ||
287 | struct GNUNET_CRYPTO_SymmetricSessionKey d_key; | ||
288 | |||
289 | /** | ||
290 | * Task to start the rekey process. | ||
291 | */ | ||
292 | struct GNUNET_SCHEDULER_Task *rekey_task; | ||
293 | |||
294 | /** | ||
295 | * Paths that are actively used to reach the destination peer. | ||
296 | */ | ||
297 | struct CadetTConnection *connection_head; | ||
298 | struct CadetTConnection *connection_tail; | ||
299 | |||
300 | /** | ||
301 | * Next connection number. | ||
302 | */ | ||
303 | uint32_t next_cid; | ||
304 | |||
305 | /** | ||
306 | * Channels inside this tunnel. | ||
307 | */ | ||
308 | struct CadetTChannel *channel_head; | ||
309 | struct CadetTChannel *channel_tail; | ||
310 | |||
311 | /** | ||
312 | * Channel ID for the next created channel. | ||
313 | */ | ||
314 | struct GNUNET_CADET_ChannelTunnelNumber next_ctn; | ||
315 | |||
316 | /** | ||
317 | * Destroy flag: if true, destroy on last message. | ||
318 | */ | ||
319 | struct GNUNET_SCHEDULER_Task * destroy_task; | ||
320 | |||
321 | /** | ||
322 | * Queued messages, to transmit once tunnel gets connected. | ||
323 | */ | ||
324 | struct CadetTunnelDelayed *tq_head; | ||
325 | struct CadetTunnelDelayed *tq_tail; | ||
326 | |||
327 | /** | ||
328 | * Task to trim connections if too many are present. | ||
329 | */ | ||
330 | struct GNUNET_SCHEDULER_Task * trim_connections_task; | ||
331 | |||
332 | /** | ||
333 | * Ephemeral message in the queue (to avoid queueing more than one). | ||
334 | */ | ||
335 | struct CadetConnectionQueue *ephm_h; | ||
336 | |||
337 | /** | ||
338 | * Pong message in the queue. | ||
339 | */ | ||
340 | struct CadetConnectionQueue *pong_h; | ||
341 | }; | ||
342 | |||
343 | |||
344 | /** | ||
345 | * Struct used to save messages in a non-ready tunnel to send once connected. | ||
346 | */ | ||
347 | struct CadetTunnelDelayed | ||
348 | { | ||
349 | /** | ||
350 | * DLL | ||
351 | */ | ||
352 | struct CadetTunnelDelayed *next; | ||
353 | struct CadetTunnelDelayed *prev; | ||
354 | |||
355 | /** | ||
356 | * Tunnel. | ||
357 | */ | ||
358 | struct CadetTunnel *t; | ||
359 | |||
360 | /** | ||
361 | * Tunnel queue given to the channel to cancel request. Update on send_queued. | ||
362 | */ | ||
363 | struct CadetTunnelQueue *tq; | ||
364 | |||
365 | /** | ||
366 | * Message to send. | ||
367 | */ | ||
368 | /* struct GNUNET_MessageHeader *msg; */ | ||
369 | }; | ||
370 | |||
371 | |||
372 | /** | ||
373 | * Handle for messages queued but not yet sent. | ||
374 | */ | ||
375 | struct CadetTunnelQueue | ||
376 | { | ||
377 | /** | ||
378 | * Connection queue handle, to cancel if necessary. | ||
379 | */ | ||
380 | struct CadetConnectionQueue *cq; | ||
381 | |||
382 | /** | ||
383 | * Handle in case message hasn't been given to a connection yet. | ||
384 | */ | ||
385 | struct CadetTunnelDelayed *tqd; | ||
386 | |||
387 | /** | ||
388 | * Continuation to call once sent. | ||
389 | */ | ||
390 | GCT_sent cont; | ||
391 | |||
392 | /** | ||
393 | * Closure for @c cont. | ||
394 | */ | ||
395 | void *cont_cls; | ||
396 | }; | ||
397 | |||
398 | |||
399 | /******************************************************************************/ | ||
400 | /******************************* GLOBALS ***********************************/ | ||
401 | /******************************************************************************/ | ||
402 | |||
403 | /** | ||
404 | * Global handle to the statistics service. | ||
405 | */ | ||
406 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
407 | |||
408 | /** | ||
409 | * Local peer own ID (memory efficient handle). | ||
410 | */ | ||
411 | extern GNUNET_PEER_Id myid; | ||
412 | |||
413 | /** | ||
414 | * Local peer own ID (full value). | ||
415 | */ | ||
416 | extern struct GNUNET_PeerIdentity my_full_id; | ||
417 | |||
418 | |||
419 | /** | ||
420 | * Don't try to recover tunnels if shutting down. | ||
421 | */ | ||
422 | extern int shutting_down; | ||
423 | |||
424 | |||
425 | /** | ||
426 | * Set of all tunnels, in order to trigger a new exchange on rekey. | ||
427 | * Indexed by peer's ID. | ||
428 | */ | ||
429 | static struct GNUNET_CONTAINER_MultiPeerMap *tunnels; | ||
430 | |||
431 | /** | ||
432 | * Own Peer ID private key. | ||
433 | */ | ||
434 | const static struct GNUNET_CRYPTO_EddsaPrivateKey *id_key; | ||
435 | |||
436 | |||
437 | /******************************** AXOLOTL ************************************/ | ||
438 | |||
439 | /** | ||
440 | * How many messages are needed to trigger a ratchet advance. | ||
441 | */ | ||
442 | static unsigned long long ratchet_messages; | ||
443 | |||
444 | /** | ||
445 | * How long until we trigger a ratched advance. | ||
446 | */ | ||
447 | static struct GNUNET_TIME_Relative ratchet_time; | ||
448 | |||
449 | |||
450 | /******************************************************************************/ | ||
451 | /******************************** STATIC ***********************************/ | ||
452 | /******************************************************************************/ | ||
453 | |||
454 | /** | ||
455 | * Get string description for tunnel connectivity state. | ||
456 | * | ||
457 | * @param cs Tunnel state. | ||
458 | * | ||
459 | * @return String representation. | ||
460 | */ | ||
461 | static const char * | ||
462 | cstate2s (enum CadetTunnelCState cs) | ||
463 | { | ||
464 | static char buf[32]; | ||
465 | |||
466 | switch (cs) | ||
467 | { | ||
468 | case CADET_TUNNEL_NEW: | ||
469 | return "CADET_TUNNEL_NEW"; | ||
470 | case CADET_TUNNEL_SEARCHING: | ||
471 | return "CADET_TUNNEL_SEARCHING"; | ||
472 | case CADET_TUNNEL_WAITING: | ||
473 | return "CADET_TUNNEL_WAITING"; | ||
474 | case CADET_TUNNEL_READY: | ||
475 | return "CADET_TUNNEL_READY"; | ||
476 | case CADET_TUNNEL_SHUTDOWN: | ||
477 | return "CADET_TUNNEL_SHUTDOWN"; | ||
478 | default: | ||
479 | SPRINTF (buf, "%u (UNKNOWN STATE)", cs); | ||
480 | return buf; | ||
481 | } | ||
482 | return ""; | ||
483 | } | ||
484 | |||
485 | |||
486 | /** | ||
487 | * Get string description for tunnel encryption state. | ||
488 | * | ||
489 | * @param es Tunnel state. | ||
490 | * | ||
491 | * @return String representation. | ||
492 | */ | ||
493 | static const char * | ||
494 | estate2s (enum CadetTunnelEState es) | ||
495 | { | ||
496 | static char buf[32]; | ||
497 | |||
498 | switch (es) | ||
499 | { | ||
500 | case CADET_TUNNEL_KEY_UNINITIALIZED: | ||
501 | return "CADET_TUNNEL_KEY_UNINITIALIZED"; | ||
502 | case CADET_TUNNEL_KEY_SENT: | ||
503 | return "CADET_TUNNEL_KEY_SENT"; | ||
504 | case CADET_TUNNEL_KEY_PING: | ||
505 | return "CADET_TUNNEL_KEY_PING"; | ||
506 | case CADET_TUNNEL_KEY_OK: | ||
507 | return "CADET_TUNNEL_KEY_OK"; | ||
508 | case CADET_TUNNEL_KEY_REKEY: | ||
509 | return "CADET_TUNNEL_KEY_REKEY"; | ||
510 | default: | ||
511 | SPRINTF (buf, "%u (UNKNOWN STATE)", es); | ||
512 | return buf; | ||
513 | } | ||
514 | return ""; | ||
515 | } | ||
516 | |||
517 | |||
518 | /** | ||
519 | * @brief Check if tunnel is ready to send traffic. | ||
520 | * | ||
521 | * Tunnel must be connected and with encryption correctly set up. | ||
522 | * | ||
523 | * @param t Tunnel to check. | ||
524 | * | ||
525 | * @return #GNUNET_YES if ready, #GNUNET_NO otherwise | ||
526 | */ | ||
527 | static int | ||
528 | is_ready (struct CadetTunnel *t) | ||
529 | { | ||
530 | int ready; | ||
531 | int conn_ok; | ||
532 | int enc_ok; | ||
533 | |||
534 | conn_ok = CADET_TUNNEL_READY == t->cstate; | ||
535 | enc_ok = CADET_TUNNEL_KEY_OK == t->estate | ||
536 | || CADET_TUNNEL_KEY_REKEY == t->estate | ||
537 | || CADET_TUNNEL_KEY_PING == t->estate; | ||
538 | ready = conn_ok && enc_ok; | ||
539 | ready = ready || GCT_is_loopback (t); | ||
540 | return ready; | ||
541 | } | ||
542 | |||
543 | |||
544 | /** | ||
545 | * Get the channel's buffer. ONLY FOR NON-LOOPBACK CHANNELS!! | ||
546 | * | ||
547 | * @param tch Tunnel's channel handle. | ||
548 | * | ||
549 | * @return Amount of messages the channel can still buffer towards the client. | ||
550 | */ | ||
551 | static unsigned int | ||
552 | get_channel_buffer (const struct CadetTChannel *tch) | ||
553 | { | ||
554 | int fwd; | ||
555 | |||
556 | /* If channel is incoming, is terminal in the FWD direction and fwd is YES */ | ||
557 | fwd = GCCH_is_terminal (tch->ch, GNUNET_YES); | ||
558 | |||
559 | return GCCH_get_buffer (tch->ch, fwd); | ||
560 | } | ||
561 | |||
562 | |||
563 | /** | ||
564 | * Get the channel's allowance status. | ||
565 | * | ||
566 | * @param tch Tunnel's channel handle. | ||
567 | * | ||
568 | * @return #GNUNET_YES if we allowed the client to send data to us. | ||
569 | */ | ||
570 | static int | ||
571 | get_channel_allowed (const struct CadetTChannel *tch) | ||
572 | { | ||
573 | int fwd; | ||
574 | |||
575 | /* If channel is outgoing, is origin in the FWD direction and fwd is YES */ | ||
576 | fwd = GCCH_is_origin (tch->ch, GNUNET_YES); | ||
577 | |||
578 | return GCCH_get_allowed (tch->ch, fwd); | ||
579 | } | ||
580 | |||
581 | |||
582 | /** | ||
583 | * Get the connection's buffer. | ||
584 | * | ||
585 | * @param tc Tunnel's connection handle. | ||
586 | * | ||
587 | * @return Amount of messages the connection can still buffer. | ||
588 | */ | ||
589 | static unsigned int | ||
590 | get_connection_buffer (const struct CadetTConnection *tc) | ||
591 | { | ||
592 | int fwd; | ||
593 | |||
594 | /* If connection is outgoing, is origin in the FWD direction and fwd is YES */ | ||
595 | fwd = GCC_is_origin (tc->c, GNUNET_YES); | ||
596 | |||
597 | return GCC_get_buffer (tc->c, fwd); | ||
598 | } | ||
599 | |||
600 | |||
601 | /** | ||
602 | * Get the connection's allowance. | ||
603 | * | ||
604 | * @param tc Tunnel's connection handle. | ||
605 | * | ||
606 | * @return Amount of messages we have allowed the next peer to send us. | ||
607 | */ | ||
608 | static unsigned int | ||
609 | get_connection_allowed (const struct CadetTConnection *tc) | ||
610 | { | ||
611 | int fwd; | ||
612 | |||
613 | /* If connection is outgoing, is origin in the FWD direction and fwd is YES */ | ||
614 | fwd = GCC_is_origin (tc->c, GNUNET_YES); | ||
615 | |||
616 | return GCC_get_allowed (tc->c, fwd); | ||
617 | } | ||
618 | |||
619 | |||
620 | /** | ||
621 | * Create a new Axolotl ephemeral (ratchet) key. | ||
622 | * | ||
623 | * @param t Tunnel. | ||
624 | */ | ||
625 | static void | ||
626 | new_ephemeral (struct CadetTunnel *t) | ||
627 | { | ||
628 | GNUNET_free_non_null (t->ax->DHRs); | ||
629 | t->ax->DHRs = GNUNET_CRYPTO_ecdhe_key_create(); | ||
630 | #if DUMP_KEYS_TO_STDERR | ||
631 | { | ||
632 | struct GNUNET_CRYPTO_EcdhePublicKey pub; | ||
633 | GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &pub); | ||
634 | LOG (GNUNET_ERROR_TYPE_DEBUG, " new DHRs generated: pub %s\n", | ||
635 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &pub)); | ||
636 | } | ||
637 | #endif | ||
638 | } | ||
639 | |||
640 | |||
641 | /** | ||
642 | * Calculate HMAC. | ||
643 | * | ||
644 | * @param plaintext Content to HMAC. | ||
645 | * @param size Size of @c plaintext. | ||
646 | * @param iv Initialization vector for the message. | ||
647 | * @param key Key to use. | ||
648 | * @param hmac[out] Destination to store the HMAC. | ||
649 | */ | ||
650 | static void | ||
651 | t_hmac (const void *plaintext, size_t size, | ||
652 | uint32_t iv, const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
653 | struct GNUNET_ShortHashCode *hmac) | ||
654 | { | ||
655 | static const char ctx[] = "cadet authentication key"; | ||
656 | struct GNUNET_CRYPTO_AuthKey auth_key; | ||
657 | struct GNUNET_HashCode hash; | ||
658 | |||
659 | #if DUMP_KEYS_TO_STDERR | ||
660 | LOG (GNUNET_ERROR_TYPE_INFO, " HMAC %u bytes with key %s\n", size, | ||
661 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) key)); | ||
662 | #endif | ||
663 | GNUNET_CRYPTO_hmac_derive_key (&auth_key, key, | ||
664 | &iv, sizeof (iv), | ||
665 | key, sizeof (*key), | ||
666 | ctx, sizeof (ctx), | ||
667 | NULL); | ||
668 | /* Two step: CADET_Hash is only 256 bits, HashCode is 512. */ | ||
669 | GNUNET_CRYPTO_hmac (&auth_key, plaintext, size, &hash); | ||
670 | GNUNET_memcpy (hmac, &hash, sizeof (*hmac)); | ||
671 | } | ||
672 | |||
673 | |||
674 | /** | ||
675 | * Perform a HMAC. | ||
676 | * | ||
677 | * @param key Key to use. | ||
678 | * @param hash[out] Resulting HMAC. | ||
679 | * @param source Source key material (data to HMAC). | ||
680 | * @param len Length of @a source. | ||
681 | */ | ||
682 | static void | ||
683 | t_ax_hmac_hash (struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
684 | struct GNUNET_HashCode *hash, | ||
685 | void *source, unsigned int len) | ||
686 | { | ||
687 | static const char ctx[] = "axolotl HMAC-HASH"; | ||
688 | struct GNUNET_CRYPTO_AuthKey auth_key; | ||
689 | |||
690 | GNUNET_CRYPTO_hmac_derive_key (&auth_key, key, | ||
691 | ctx, sizeof (ctx), | ||
692 | NULL); | ||
693 | GNUNET_CRYPTO_hmac (&auth_key, source, len, hash); | ||
694 | } | ||
695 | |||
696 | |||
697 | /** | ||
698 | * Derive a key from a HMAC-HASH. | ||
699 | * | ||
700 | * @param key Key to use for the HMAC. | ||
701 | * @param out Key to generate. | ||
702 | * @param source Source key material (data to HMAC). | ||
703 | * @param len Length of @a source. | ||
704 | */ | ||
705 | static void | ||
706 | t_hmac_derive_key (struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
707 | struct GNUNET_CRYPTO_SymmetricSessionKey *out, | ||
708 | void *source, unsigned int len) | ||
709 | { | ||
710 | static const char ctx[] = "axolotl derive key"; | ||
711 | struct GNUNET_HashCode h; | ||
712 | |||
713 | t_ax_hmac_hash (key, &h, source, len); | ||
714 | GNUNET_CRYPTO_kdf (out, sizeof (*out), ctx, sizeof (ctx), | ||
715 | &h, sizeof (h), NULL); | ||
716 | } | ||
717 | |||
718 | |||
719 | /** | ||
720 | * Encrypt data with the axolotl tunnel key. | ||
721 | * | ||
722 | * @param t Tunnel whose key to use. | ||
723 | * @param dst Destination for the encrypted data. | ||
724 | * @param src Source of the plaintext. Can overlap with @c dst. | ||
725 | * @param size Size of the plaintext. | ||
726 | * | ||
727 | * @return Size of the encrypted data. | ||
728 | */ | ||
729 | static int | ||
730 | t_ax_encrypt (struct CadetTunnel *t, void *dst, const void *src, size_t size) | ||
731 | { | ||
732 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | ||
733 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
734 | struct CadetTunnelAxolotl *ax; | ||
735 | size_t out_size; | ||
736 | |||
737 | CADET_TIMING_START; | ||
738 | |||
739 | ax = t->ax; | ||
740 | ax->ratchet_counter++; | ||
741 | if (GNUNET_YES == ax->ratchet_allowed | ||
742 | && (ratchet_messages <= ax->ratchet_counter | ||
743 | || 0 == GNUNET_TIME_absolute_get_remaining (ax->ratchet_expiration).rel_value_us)) | ||
744 | { | ||
745 | ax->ratchet_flag = GNUNET_YES; | ||
746 | } | ||
747 | |||
748 | if (GNUNET_YES == ax->ratchet_flag) | ||
749 | { | ||
750 | /* Advance ratchet */ | ||
751 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; | ||
752 | struct GNUNET_HashCode dh; | ||
753 | struct GNUNET_HashCode hmac; | ||
754 | static const char ctx[] = "axolotl ratchet"; | ||
755 | |||
756 | new_ephemeral (t); | ||
757 | ax->HKs = ax->NHKs; | ||
758 | |||
759 | /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */ | ||
760 | GNUNET_CRYPTO_ecc_ecdh (ax->DHRs, &ax->DHRr, &dh); | ||
761 | t_ax_hmac_hash (&ax->RK, &hmac, &dh, sizeof (dh)); | ||
762 | GNUNET_CRYPTO_kdf (keys, sizeof (keys), ctx, sizeof (ctx), | ||
763 | &hmac, sizeof (hmac), NULL); | ||
764 | ax->RK = keys[0]; | ||
765 | ax->NHKs = keys[1]; | ||
766 | ax->CKs = keys[2]; | ||
767 | |||
768 | ax->PNs = ax->Ns; | ||
769 | ax->Ns = 0; | ||
770 | ax->ratchet_flag = GNUNET_NO; | ||
771 | ax->ratchet_allowed = GNUNET_NO; | ||
772 | ax->ratchet_counter = 0; | ||
773 | ax->ratchet_expiration = | ||
774 | GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), ratchet_time); | ||
775 | } | ||
776 | |||
777 | t_hmac_derive_key (&ax->CKs, &MK, "0", 1); | ||
778 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, &MK, NULL, 0, NULL); | ||
779 | |||
780 | #if DUMP_KEYS_TO_STDERR | ||
781 | LOG (GNUNET_ERROR_TYPE_DEBUG, " CKs: %s\n", | ||
782 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKs)); | ||
783 | LOG (GNUNET_ERROR_TYPE_INFO, " AX_ENC with key %u: %s\n", ax->Ns, | ||
784 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &MK)); | ||
785 | #endif | ||
786 | |||
787 | out_size = GNUNET_CRYPTO_symmetric_encrypt (src, size, &MK, &iv, dst); | ||
788 | t_hmac_derive_key (&ax->CKs, &ax->CKs, "1", 1); | ||
789 | |||
790 | CADET_TIMING_END; | ||
791 | |||
792 | return out_size; | ||
793 | } | ||
794 | |||
795 | |||
796 | /** | ||
797 | * Decrypt data with the axolotl tunnel key. | ||
798 | * | ||
799 | * @param t Tunnel whose key to use. | ||
800 | * @param dst Destination for the decrypted data. | ||
801 | * @param src Source of the ciphertext. Can overlap with @c dst. | ||
802 | * @param size Size of the ciphertext. | ||
803 | * | ||
804 | * @return Size of the decrypted data. | ||
805 | */ | ||
806 | static int | ||
807 | t_ax_decrypt (struct CadetTunnel *t, void *dst, const void *src, size_t size) | ||
808 | { | ||
809 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | ||
810 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
811 | struct CadetTunnelAxolotl *ax; | ||
812 | size_t out_size; | ||
813 | |||
814 | CADET_TIMING_START; | ||
815 | |||
816 | ax = t->ax; | ||
817 | |||
818 | t_hmac_derive_key (&ax->CKr, &MK, "0", 1); | ||
819 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, &MK, NULL, 0, NULL); | ||
820 | |||
821 | #if DUMP_KEYS_TO_STDERR | ||
822 | LOG (GNUNET_ERROR_TYPE_DEBUG, " CKr: %s\n", | ||
823 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKr)); | ||
824 | LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC with key %u: %s\n", ax->Nr, | ||
825 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &MK)); | ||
826 | #endif | ||
827 | |||
828 | GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); | ||
829 | out_size = GNUNET_CRYPTO_symmetric_decrypt (src, size, &MK, &iv, dst); | ||
830 | GNUNET_assert (out_size == size); | ||
831 | |||
832 | t_hmac_derive_key (&ax->CKr, &ax->CKr, "1", 1); | ||
833 | |||
834 | CADET_TIMING_END; | ||
835 | |||
836 | return out_size; | ||
837 | } | ||
838 | |||
839 | |||
840 | /** | ||
841 | * Encrypt header with the axolotl header key. | ||
842 | * | ||
843 | * @param t Tunnel whose key to use. | ||
844 | * @param msg Message whose header to encrypt. | ||
845 | */ | ||
846 | static void | ||
847 | t_h_encrypt (struct CadetTunnel *t, struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
848 | { | ||
849 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
850 | struct CadetTunnelAxolotl *ax; | ||
851 | size_t out_size; | ||
852 | |||
853 | CADET_TIMING_START; | ||
854 | ax = t->ax; | ||
855 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, &ax->HKs, NULL, 0, NULL); | ||
856 | |||
857 | #if DUMP_KEYS_TO_STDERR | ||
858 | LOG (GNUNET_ERROR_TYPE_INFO, " AX_ENC_H with key %s\n", | ||
859 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKs)); | ||
860 | #endif | ||
861 | |||
862 | out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->Ns, AX_HEADER_SIZE, | ||
863 | &ax->HKs, &iv, &msg->Ns); | ||
864 | |||
865 | GNUNET_assert (AX_HEADER_SIZE == out_size); | ||
866 | CADET_TIMING_END; | ||
867 | } | ||
868 | |||
869 | |||
870 | /** | ||
871 | * Decrypt header with the current axolotl header key. | ||
872 | * | ||
873 | * @param t Tunnel whose current ax HK to use. | ||
874 | * @param src Message whose header to decrypt. | ||
875 | * @param dst Where to decrypt header to. | ||
876 | */ | ||
877 | static void | ||
878 | t_h_decrypt (struct CadetTunnel *t, const struct GNUNET_CADET_TunnelEncryptedMessage *src, | ||
879 | struct GNUNET_CADET_TunnelEncryptedMessage *dst) | ||
880 | { | ||
881 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
882 | struct CadetTunnelAxolotl *ax; | ||
883 | size_t out_size; | ||
884 | |||
885 | CADET_TIMING_START; | ||
886 | |||
887 | ax = t->ax; | ||
888 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, &ax->HKr, NULL, 0, NULL); | ||
889 | |||
890 | #if DUMP_KEYS_TO_STDERR | ||
891 | LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC_H with key %s\n", | ||
892 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKr)); | ||
893 | #endif | ||
894 | |||
895 | out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, AX_HEADER_SIZE, | ||
896 | &ax->HKr, &iv, &dst->Ns); | ||
897 | |||
898 | GNUNET_assert (AX_HEADER_SIZE == out_size); | ||
899 | |||
900 | CADET_TIMING_END; | ||
901 | } | ||
902 | |||
903 | |||
904 | /** | ||
905 | * Decrypt and verify data with the appropriate tunnel key and verify that the | ||
906 | * data has not been altered since it was sent by the remote peer. | ||
907 | * | ||
908 | * @param t Tunnel whose key to use. | ||
909 | * @param dst Destination for the plaintext. | ||
910 | * @param src Source of the message. Can overlap with @c dst. | ||
911 | * @param size Size of the message. | ||
912 | * | ||
913 | * @return Size of the decrypted data, -1 if an error was encountered. | ||
914 | */ | ||
915 | static int | ||
916 | try_old_ax_keys (struct CadetTunnel *t, void *dst, | ||
917 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, size_t size) | ||
918 | { | ||
919 | struct CadetTunnelSkippedKey *key; | ||
920 | struct GNUNET_ShortHashCode *hmac; | ||
921 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
922 | struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header; | ||
923 | struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK; | ||
924 | size_t esize; | ||
925 | size_t res; | ||
926 | size_t len; | ||
927 | unsigned int N; | ||
928 | |||
929 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying old keys\n"); | ||
930 | hmac = &plaintext_header.hmac; | ||
931 | esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage); | ||
932 | |||
933 | /* Find a correct Header Key */ | ||
934 | for (key = t->ax->skipped_head; NULL != key; key = key->next) | ||
935 | { | ||
936 | #if DUMP_KEYS_TO_STDERR | ||
937 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Trying hmac with key %s\n", | ||
938 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->HK)); | ||
939 | #endif | ||
940 | t_hmac (&src->Ns, AX_HEADER_SIZE + esize, 0, &key->HK, hmac); | ||
941 | if (0 == memcmp (hmac, &src->hmac, sizeof (*hmac))) | ||
942 | { | ||
943 | LOG (GNUNET_ERROR_TYPE_DEBUG, " hmac correct\n"); | ||
944 | valid_HK = &key->HK; | ||
945 | break; | ||
946 | } | ||
947 | } | ||
948 | if (NULL == key) | ||
949 | return -1; | ||
950 | |||
951 | /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */ | ||
952 | GNUNET_assert (size > sizeof (struct GNUNET_CADET_TunnelEncryptedMessage)); | ||
953 | len = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage); | ||
954 | GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader)); | ||
955 | |||
956 | /* Decrypt header */ | ||
957 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, &key->HK, NULL, 0, NULL); | ||
958 | res = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, AX_HEADER_SIZE, | ||
959 | &key->HK, &iv, &plaintext_header.Ns); | ||
960 | GNUNET_assert (AX_HEADER_SIZE == res); | ||
961 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Message %u, previous: %u\n", | ||
962 | ntohl (plaintext_header.Ns), ntohl (plaintext_header.PNs)); | ||
963 | |||
964 | /* Find the correct Message Key */ | ||
965 | N = ntohl (plaintext_header.Ns); | ||
966 | while (NULL != key && N != key->Kn) | ||
967 | key = key->next; | ||
968 | if (NULL == key || 0 != memcmp (&key->HK, valid_HK, sizeof (*valid_HK))) | ||
969 | return -1; | ||
970 | |||
971 | #if DUMP_KEYS_TO_STDERR | ||
972 | LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC_H with skipped key %s\n", | ||
973 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->HK)); | ||
974 | LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC with skipped key %u: %s\n", | ||
975 | key->Kn, GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->MK)); | ||
976 | #endif | ||
977 | |||
978 | /* Decrypt payload */ | ||
979 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, &key->MK, NULL, 0, NULL); | ||
980 | res = GNUNET_CRYPTO_symmetric_decrypt (&src[1], len, &key->MK, &iv, dst); | ||
981 | |||
982 | /* Remove key */ | ||
983 | GNUNET_CONTAINER_DLL_remove (t->ax->skipped_head, t->ax->skipped_tail, key); | ||
984 | t->ax->skipped--; | ||
985 | GNUNET_free (key); /* GNUNET_free overwrites memory with 0xbaadf00d */ | ||
986 | |||
987 | return res; | ||
988 | } | ||
989 | |||
990 | |||
991 | /** | ||
992 | * Delete a key from the list of skipped keys. | ||
993 | * | ||
994 | * @param t Tunnel to delete from. | ||
995 | * @param HKr Header Key to use. | ||
996 | */ | ||
997 | static void | ||
998 | store_skipped_key (struct CadetTunnel *t, | ||
999 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr) | ||
1000 | { | ||
1001 | struct CadetTunnelSkippedKey *key; | ||
1002 | |||
1003 | key = GNUNET_new (struct CadetTunnelSkippedKey); | ||
1004 | key->timestamp = GNUNET_TIME_absolute_get (); | ||
1005 | key->Kn = t->ax->Nr; | ||
1006 | key->HK = t->ax->HKr; | ||
1007 | t_hmac_derive_key (&t->ax->CKr, &key->MK, "0", 1); | ||
1008 | #if DUMP_KEYS_TO_STDERR | ||
1009 | LOG (GNUNET_ERROR_TYPE_DEBUG, " storing MK for Nr %u: %s\n", | ||
1010 | key->Kn, GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->MK)); | ||
1011 | LOG (GNUNET_ERROR_TYPE_DEBUG, " for CKr: %s\n", | ||
1012 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &t->ax->CKr)); | ||
1013 | #endif | ||
1014 | t_hmac_derive_key (&t->ax->CKr, &t->ax->CKr, "1", 1); | ||
1015 | GNUNET_CONTAINER_DLL_insert (t->ax->skipped_head, t->ax->skipped_tail, key); | ||
1016 | t->ax->Nr++; | ||
1017 | t->ax->skipped++; | ||
1018 | } | ||
1019 | |||
1020 | |||
1021 | /** | ||
1022 | * Delete a key from the list of skipped keys. | ||
1023 | * | ||
1024 | * @param t Tunnel to delete from. | ||
1025 | * @param key Key to delete. | ||
1026 | */ | ||
1027 | static void | ||
1028 | delete_skipped_key (struct CadetTunnel *t, struct CadetTunnelSkippedKey *key) | ||
1029 | { | ||
1030 | GNUNET_CONTAINER_DLL_remove (t->ax->skipped_head, t->ax->skipped_tail, key); | ||
1031 | GNUNET_free (key); | ||
1032 | t->ax->skipped--; | ||
1033 | } | ||
1034 | |||
1035 | |||
1036 | /** | ||
1037 | * Stage skipped AX keys and calculate the message key. | ||
1038 | * | ||
1039 | * Stores each HK and MK for skipped messages. | ||
1040 | * | ||
1041 | * @param t Tunnel where to stage the keys. | ||
1042 | * @param HKr Header key. | ||
1043 | * @param Np Received meesage number. | ||
1044 | * | ||
1045 | * @return GNUNET_OK if keys were stored. | ||
1046 | * GNUNET_SYSERR if an error ocurred (Np not expected). | ||
1047 | */ | ||
1048 | static int | ||
1049 | store_ax_keys (struct CadetTunnel *t, | ||
1050 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr, | ||
1051 | uint32_t Np) | ||
1052 | { | ||
1053 | int gap; | ||
1054 | |||
1055 | |||
1056 | gap = Np - t->ax->Nr; | ||
1057 | LOG (GNUNET_ERROR_TYPE_INFO, "Storing keys [%u, %u)\n", t->ax->Nr, Np); | ||
1058 | if (MAX_KEY_GAP < gap) | ||
1059 | { | ||
1060 | /* Avoid DoS (forcing peer to do 2*33 chain HMAC operations) */ | ||
1061 | /* TODO: start new key exchange on return */ | ||
1062 | GNUNET_break_op (0); | ||
1063 | LOG (GNUNET_ERROR_TYPE_WARNING, "Got message %u, expected %u+\n", | ||
1064 | Np, t->ax->Nr); | ||
1065 | return GNUNET_SYSERR; | ||
1066 | } | ||
1067 | if (0 > gap) | ||
1068 | { | ||
1069 | /* Delayed message: don't store keys, flag to try old keys. */ | ||
1070 | return GNUNET_SYSERR; | ||
1071 | } | ||
1072 | |||
1073 | while (t->ax->Nr < Np) | ||
1074 | store_skipped_key (t, HKr); | ||
1075 | |||
1076 | while (t->ax->skipped > MAX_SKIPPED_KEYS) | ||
1077 | delete_skipped_key (t, t->ax->skipped_tail); | ||
1078 | |||
1079 | return GNUNET_OK; | ||
1080 | } | ||
1081 | |||
1082 | |||
1083 | /** | ||
1084 | * Decrypt and verify data with the appropriate tunnel key and verify that the | ||
1085 | * data has not been altered since it was sent by the remote peer. | ||
1086 | * | ||
1087 | * @param t Tunnel whose key to use. | ||
1088 | * @param dst Destination for the plaintext. | ||
1089 | * @param src Source of the message. Can overlap with @c dst. | ||
1090 | * @param size Size of the message. | ||
1091 | * | ||
1092 | * @return Size of the decrypted data, -1 if an error was encountered. | ||
1093 | */ | ||
1094 | static int | ||
1095 | t_ax_decrypt_and_validate (struct CadetTunnel *t, void *dst, | ||
1096 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, | ||
1097 | size_t size) | ||
1098 | { | ||
1099 | struct CadetTunnelAxolotl *ax; | ||
1100 | struct GNUNET_ShortHashCode msg_hmac; | ||
1101 | struct GNUNET_HashCode hmac; | ||
1102 | struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header; | ||
1103 | uint32_t Np; | ||
1104 | uint32_t PNp; | ||
1105 | size_t esize; /* Size of encryped payload */ | ||
1106 | size_t osize; /* Size of output (decrypted payload) */ | ||
1107 | |||
1108 | esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage); | ||
1109 | ax = t->ax; | ||
1110 | if (NULL == ax) | ||
1111 | return -1; | ||
1112 | |||
1113 | /* Try current HK */ | ||
1114 | t_hmac (&src->Ns, AX_HEADER_SIZE + esize, 0, &ax->HKr, &msg_hmac); | ||
1115 | if (0 != memcmp (&msg_hmac, &src->hmac, sizeof (msg_hmac))) | ||
1116 | { | ||
1117 | static const char ctx[] = "axolotl ratchet"; | ||
1118 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */ | ||
1119 | struct GNUNET_CRYPTO_SymmetricSessionKey HK; | ||
1120 | struct GNUNET_HashCode dh; | ||
1121 | struct GNUNET_CRYPTO_EcdhePublicKey *DHRp; | ||
1122 | |||
1123 | /* Try Next HK */ | ||
1124 | LOG (GNUNET_ERROR_TYPE_DEBUG, " trying next HK\n"); | ||
1125 | t_hmac (&src->Ns, AX_HEADER_SIZE + esize, 0, &ax->NHKr, &msg_hmac); | ||
1126 | if (0 != memcmp (&msg_hmac, &src->hmac, sizeof (msg_hmac))) | ||
1127 | { | ||
1128 | /* Try the skipped keys, if that fails, we're out of luck. */ | ||
1129 | return try_old_ax_keys (t, dst, src, size); | ||
1130 | } | ||
1131 | LOG (GNUNET_ERROR_TYPE_INFO, "next HK worked\n"); | ||
1132 | |||
1133 | HK = ax->HKr; | ||
1134 | ax->HKr = ax->NHKr; | ||
1135 | t_h_decrypt (t, src, &plaintext_header); | ||
1136 | Np = ntohl (plaintext_header.Ns); | ||
1137 | PNp = ntohl (plaintext_header.PNs); | ||
1138 | DHRp = &plaintext_header.DHRs; | ||
1139 | store_ax_keys (t, &HK, PNp); | ||
1140 | |||
1141 | /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */ | ||
1142 | GNUNET_CRYPTO_ecc_ecdh (ax->DHRs, DHRp, &dh); | ||
1143 | t_ax_hmac_hash (&ax->RK, &hmac, &dh, sizeof (dh)); | ||
1144 | GNUNET_CRYPTO_kdf (keys, sizeof (keys), ctx, sizeof (ctx), | ||
1145 | &hmac, sizeof (hmac), NULL); | ||
1146 | |||
1147 | /* Commit "purported" keys */ | ||
1148 | ax->RK = keys[0]; | ||
1149 | ax->NHKr = keys[1]; | ||
1150 | ax->CKr = keys[2]; | ||
1151 | ax->DHRr = *DHRp; | ||
1152 | ax->Nr = 0; | ||
1153 | ax->ratchet_allowed = GNUNET_YES; | ||
1154 | } | ||
1155 | else | ||
1156 | { | ||
1157 | LOG (GNUNET_ERROR_TYPE_DEBUG, "current HK\n"); | ||
1158 | t_h_decrypt (t, src, &plaintext_header); | ||
1159 | Np = ntohl (plaintext_header.Ns); | ||
1160 | PNp = ntohl (plaintext_header.PNs); | ||
1161 | } | ||
1162 | LOG (GNUNET_ERROR_TYPE_INFO, " got AX Nr %u\n", Np); | ||
1163 | if (Np != ax->Nr) | ||
1164 | if (GNUNET_OK != store_ax_keys (t, &ax->HKr, Np)) | ||
1165 | /* Try the skipped keys, if that fails, we're out of luck. */ | ||
1166 | return try_old_ax_keys (t, dst, src, size); | ||
1167 | |||
1168 | osize = t_ax_decrypt (t, dst, &src[1], esize); | ||
1169 | ax->Nr = Np + 1; | ||
1170 | |||
1171 | if (osize != esize) | ||
1172 | { | ||
1173 | GNUNET_break_op (0); | ||
1174 | return -1; | ||
1175 | } | ||
1176 | |||
1177 | return osize; | ||
1178 | } | ||
1179 | |||
1180 | |||
1181 | /** | ||
1182 | * Pick a connection on which send the next data message. | ||
1183 | * | ||
1184 | * @param t Tunnel on which to send the message. | ||
1185 | * | ||
1186 | * @return The connection on which to send the next message. | ||
1187 | */ | ||
1188 | static struct CadetConnection * | ||
1189 | tunnel_get_connection (struct CadetTunnel *t) | ||
1190 | { | ||
1191 | struct CadetTConnection *iter; | ||
1192 | struct CadetConnection *best; | ||
1193 | unsigned int qn; | ||
1194 | unsigned int lowest_q; | ||
1195 | |||
1196 | LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel_get_connection %s\n", GCT_2s (t)); | ||
1197 | best = NULL; | ||
1198 | lowest_q = UINT_MAX; | ||
1199 | for (iter = t->connection_head; NULL != iter; iter = iter->next) | ||
1200 | { | ||
1201 | LOG (GNUNET_ERROR_TYPE_DEBUG, " connection %s: %u\n", | ||
1202 | GCC_2s (iter->c), GCC_get_state (iter->c)); | ||
1203 | if (CADET_CONNECTION_READY == GCC_get_state (iter->c)) | ||
1204 | { | ||
1205 | qn = GCC_get_qn (iter->c, GCC_is_origin (iter->c, GNUNET_YES)); | ||
1206 | LOG (GNUNET_ERROR_TYPE_DEBUG, " q_n %u, \n", qn); | ||
1207 | if (qn < lowest_q) | ||
1208 | { | ||
1209 | best = iter->c; | ||
1210 | lowest_q = qn; | ||
1211 | } | ||
1212 | } | ||
1213 | } | ||
1214 | LOG (GNUNET_ERROR_TYPE_DEBUG, " selected: connection %s\n", GCC_2s (best)); | ||
1215 | return best; | ||
1216 | } | ||
1217 | |||
1218 | |||
1219 | /** | ||
1220 | * Callback called when a queued message is sent. | ||
1221 | * | ||
1222 | * Calculates the average time and connection packet tracking. | ||
1223 | * | ||
1224 | * @param cls Closure (TunnelQueue handle). | ||
1225 | * @param c Connection this message was on. | ||
1226 | * @param q Connection queue handle (unused). | ||
1227 | * @param type Type of message sent. | ||
1228 | * @param fwd Was this a FWD going message? | ||
1229 | * @param size Size of the message. | ||
1230 | */ | ||
1231 | static void | ||
1232 | tun_message_sent (void *cls, | ||
1233 | struct CadetConnection *c, | ||
1234 | struct CadetConnectionQueue *q, | ||
1235 | uint16_t type, int fwd, size_t size) | ||
1236 | { | ||
1237 | struct CadetTunnelQueue *qt = cls; | ||
1238 | struct CadetTunnel *t; | ||
1239 | |||
1240 | LOG (GNUNET_ERROR_TYPE_DEBUG, "tun_message_sent\n"); | ||
1241 | |||
1242 | GNUNET_assert (NULL != qt->cont); | ||
1243 | t = NULL == c ? NULL : GCC_get_tunnel (c); | ||
1244 | qt->cont (qt->cont_cls, t, qt, type, size); | ||
1245 | GNUNET_free (qt); | ||
1246 | } | ||
1247 | |||
1248 | |||
1249 | static unsigned int | ||
1250 | count_queued_data (const struct CadetTunnel *t) | ||
1251 | { | ||
1252 | struct CadetTunnelDelayed *iter; | ||
1253 | unsigned int count; | ||
1254 | |||
1255 | for (count = 0, iter = t->tq_head; iter != NULL; iter = iter->next) | ||
1256 | count++; | ||
1257 | |||
1258 | return count; | ||
1259 | } | ||
1260 | |||
1261 | /** | ||
1262 | * Delete a queued message: either was sent or the channel was destroyed | ||
1263 | * before the tunnel's key exchange had a chance to finish. | ||
1264 | * | ||
1265 | * @param tqd Delayed queue handle. | ||
1266 | */ | ||
1267 | static void | ||
1268 | unqueue_data (struct CadetTunnelDelayed *tqd) | ||
1269 | { | ||
1270 | GNUNET_CONTAINER_DLL_remove (tqd->t->tq_head, tqd->t->tq_tail, tqd); | ||
1271 | GNUNET_free (tqd); | ||
1272 | } | ||
1273 | |||
1274 | |||
1275 | /** | ||
1276 | * Cache a message to be sent once tunnel is online. | ||
1277 | * | ||
1278 | * @param t Tunnel to hold the message. | ||
1279 | * @param msg Message itself (copy will be made). | ||
1280 | */ | ||
1281 | static struct CadetTunnelDelayed * | ||
1282 | queue_data (struct CadetTunnel *t, const struct GNUNET_MessageHeader *msg) | ||
1283 | { | ||
1284 | struct CadetTunnelDelayed *tqd; | ||
1285 | uint16_t size = ntohs (msg->size); | ||
1286 | |||
1287 | LOG (GNUNET_ERROR_TYPE_DEBUG, "queue data on Tunnel %s\n", GCT_2s (t)); | ||
1288 | |||
1289 | GNUNET_assert (GNUNET_NO == is_ready (t)); | ||
1290 | |||
1291 | tqd = GNUNET_malloc (sizeof (struct CadetTunnelDelayed) + size); | ||
1292 | |||
1293 | tqd->t = t; | ||
1294 | GNUNET_memcpy (&tqd[1], msg, size); | ||
1295 | GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tqd); | ||
1296 | return tqd; | ||
1297 | } | ||
1298 | |||
1299 | |||
1300 | /** | ||
1301 | * Sends an already built message on a tunnel, encrypting it and | ||
1302 | * choosing the best connection. | ||
1303 | * | ||
1304 | * @param message Message to send. Function modifies it. | ||
1305 | * @param t Tunnel on which this message is transmitted. | ||
1306 | * @param c Connection to use (autoselect if NULL). | ||
1307 | * @param force Force the tunnel to take the message (buffer overfill). | ||
1308 | * @param cont Continuation to call once message is really sent. | ||
1309 | * @param cont_cls Closure for @c cont. | ||
1310 | * @param existing_q In case this a transmission of previously queued data, | ||
1311 | * this should be TunnelQueue given to the client. | ||
1312 | * Otherwise, NULL. | ||
1313 | * @return Handle to cancel message. | ||
1314 | * NULL if @c cont is NULL or an error happens and message is dropped. | ||
1315 | */ | ||
1316 | static struct CadetTunnelQueue * | ||
1317 | send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
1318 | struct CadetTunnel *t, | ||
1319 | struct CadetConnection *c, | ||
1320 | int force, | ||
1321 | GCT_sent cont, | ||
1322 | void *cont_cls, | ||
1323 | struct CadetTunnelQueue *existing_q) | ||
1324 | { | ||
1325 | struct GNUNET_MessageHeader *msg; | ||
1326 | struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg; | ||
1327 | struct CadetTunnelQueue *tq; | ||
1328 | size_t size = ntohs (message->size); | ||
1329 | char cbuf[sizeof (struct GNUNET_CADET_TunnelEncryptedMessage) + size] GNUNET_ALIGN; | ||
1330 | size_t esize; | ||
1331 | uint16_t type; | ||
1332 | int fwd; | ||
1333 | |||
1334 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GCT_2s (t)); | ||
1335 | |||
1336 | if (GNUNET_NO == is_ready (t)) | ||
1337 | { | ||
1338 | struct CadetTunnelDelayed *tqd; | ||
1339 | /* A non null existing_q indicates sending of queued data. | ||
1340 | * Should only happen after tunnel becomes ready. | ||
1341 | */ | ||
1342 | GNUNET_assert (NULL == existing_q); | ||
1343 | tqd = queue_data (t, message); | ||
1344 | if (NULL == cont) | ||
1345 | return NULL; | ||
1346 | tq = GNUNET_new (struct CadetTunnelQueue); | ||
1347 | tq->tqd = tqd; | ||
1348 | tqd->tq = tq; | ||
1349 | tq->cont = cont; | ||
1350 | tq->cont_cls = cont_cls; | ||
1351 | return tq; | ||
1352 | } | ||
1353 | |||
1354 | GNUNET_assert (GNUNET_NO == GCT_is_loopback (t)); | ||
1355 | |||
1356 | ax_msg = (struct GNUNET_CADET_TunnelEncryptedMessage *) cbuf; | ||
1357 | msg = &ax_msg->header; | ||
1358 | msg->size = htons (sizeof (struct GNUNET_CADET_TunnelEncryptedMessage) + size); | ||
1359 | msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED); | ||
1360 | esize = t_ax_encrypt (t, &ax_msg[1], message, size); | ||
1361 | ax_msg->Ns = htonl (t->ax->Ns++); | ||
1362 | ax_msg->PNs = htonl (t->ax->PNs); | ||
1363 | GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &ax_msg->DHRs); | ||
1364 | t_h_encrypt (t, ax_msg); | ||
1365 | t_hmac (&ax_msg->Ns, AX_HEADER_SIZE + esize, 0, &t->ax->HKs, &ax_msg->hmac); | ||
1366 | GNUNET_assert (esize == size); | ||
1367 | |||
1368 | if (NULL == c) | ||
1369 | c = tunnel_get_connection (t); | ||
1370 | if (NULL == c) | ||
1371 | { | ||
1372 | /* Why is tunnel 'ready'? Should have been queued! */ | ||
1373 | if (NULL != t->destroy_task) | ||
1374 | { | ||
1375 | GNUNET_break (0); | ||
1376 | GCT_debug (t, GNUNET_ERROR_TYPE_WARNING); | ||
1377 | } | ||
1378 | return NULL; /* Drop... */ | ||
1379 | } | ||
1380 | fwd = GCC_is_origin (c, GNUNET_YES); | ||
1381 | ax_msg->cid = *GCC_get_id (c); | ||
1382 | ax_msg->cemi = GCC_get_pid (c, fwd); | ||
1383 | |||
1384 | type = htons (message->type); | ||
1385 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1386 | "Sending message of type %s with CEMI %u and CID %s\n", | ||
1387 | GC_m2s (type), | ||
1388 | htonl (ax_msg->cemi.pid), | ||
1389 | GNUNET_sh2s (&ax_msg->cid.connection_of_tunnel)); | ||
1390 | |||
1391 | if (NULL == cont) | ||
1392 | { | ||
1393 | (void) GCC_send_prebuilt_message (msg, | ||
1394 | type, | ||
1395 | ax_msg->cemi, | ||
1396 | c, | ||
1397 | fwd, | ||
1398 | force, NULL, NULL); | ||
1399 | return NULL; | ||
1400 | } | ||
1401 | if (NULL == existing_q) | ||
1402 | { | ||
1403 | tq = GNUNET_new (struct CadetTunnelQueue); /* FIXME valgrind: leak*/ | ||
1404 | } | ||
1405 | else | ||
1406 | { | ||
1407 | tq = existing_q; | ||
1408 | tq->tqd = NULL; | ||
1409 | } | ||
1410 | tq->cont = cont; | ||
1411 | tq->cont_cls = cont_cls; | ||
1412 | tq->cq = GCC_send_prebuilt_message (msg, | ||
1413 | type, | ||
1414 | ax_msg->cemi, | ||
1415 | c, | ||
1416 | fwd, | ||
1417 | force, | ||
1418 | &tun_message_sent, tq); | ||
1419 | GNUNET_assert (NULL != tq->cq); | ||
1420 | |||
1421 | return tq; | ||
1422 | } | ||
1423 | |||
1424 | |||
1425 | /** | ||
1426 | * Send all cached messages that we can, tunnel is online. | ||
1427 | * | ||
1428 | * @param t Tunnel that holds the messages. Cannot be loopback. | ||
1429 | */ | ||
1430 | static void | ||
1431 | send_queued_data (struct CadetTunnel *t) | ||
1432 | { | ||
1433 | struct CadetTunnelDelayed *tqd; | ||
1434 | struct CadetTunnelDelayed *next; | ||
1435 | unsigned int room; | ||
1436 | |||
1437 | LOG (GNUNET_ERROR_TYPE_INFO, "Send queued data, tunnel %s\n", GCT_2s (t)); | ||
1438 | |||
1439 | if (GCT_is_loopback (t)) | ||
1440 | { | ||
1441 | GNUNET_break (0); | ||
1442 | return; | ||
1443 | } | ||
1444 | |||
1445 | if (GNUNET_NO == is_ready (t)) | ||
1446 | { | ||
1447 | LOG (GNUNET_ERROR_TYPE_WARNING, " not ready yet: %s/%s\n", | ||
1448 | estate2s (t->estate), cstate2s (t->cstate)); | ||
1449 | return; | ||
1450 | } | ||
1451 | |||
1452 | room = GCT_get_connections_buffer (t); | ||
1453 | LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room); | ||
1454 | LOG (GNUNET_ERROR_TYPE_DEBUG, " tq head: %p\n", t->tq_head); | ||
1455 | for (tqd = t->tq_head; NULL != tqd && room > 0; tqd = next) | ||
1456 | { | ||
1457 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending queued data\n"); | ||
1458 | next = tqd->next; | ||
1459 | room--; | ||
1460 | send_prebuilt_message ((struct GNUNET_MessageHeader *) &tqd[1], | ||
1461 | tqd->t, NULL, GNUNET_YES, | ||
1462 | NULL != tqd->tq ? tqd->tq->cont : NULL, | ||
1463 | NULL != tqd->tq ? tqd->tq->cont_cls : NULL, | ||
1464 | tqd->tq); | ||
1465 | unqueue_data (tqd); | ||
1466 | } | ||
1467 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GCT_send_queued_data end\n", GCP_2s (t->peer)); | ||
1468 | } | ||
1469 | |||
1470 | |||
1471 | /** | ||
1472 | * @brief Resend the KX until we complete the handshake. | ||
1473 | * | ||
1474 | * @param cls Closure (tunnel). | ||
1475 | */ | ||
1476 | static void | ||
1477 | kx_resend (void *cls) | ||
1478 | { | ||
1479 | struct CadetTunnel *t = cls; | ||
1480 | |||
1481 | t->rekey_task = NULL; | ||
1482 | if (CADET_TUNNEL_KEY_OK == t->estate) | ||
1483 | { | ||
1484 | /* Should have been canceled on estate change */ | ||
1485 | GNUNET_break (0); | ||
1486 | return; | ||
1487 | } | ||
1488 | |||
1489 | GCT_send_kx (t, CADET_TUNNEL_KEY_SENT >= t->estate); | ||
1490 | } | ||
1491 | |||
1492 | |||
1493 | /** | ||
1494 | * Callback called when a queued message is sent. | ||
1495 | * | ||
1496 | * @param cls Closure. | ||
1497 | * @param c Connection this message was on. | ||
1498 | * @param type Type of message sent. | ||
1499 | * @param fwd Was this a FWD going message? | ||
1500 | * @param size Size of the message. | ||
1501 | */ | ||
1502 | static void | ||
1503 | ephm_sent (void *cls, | ||
1504 | struct CadetConnection *c, | ||
1505 | struct CadetConnectionQueue *q, | ||
1506 | uint16_t type, int fwd, size_t size) | ||
1507 | { | ||
1508 | struct CadetTunnel *t = cls; | ||
1509 | LOG (GNUNET_ERROR_TYPE_DEBUG, "ephemeral sent %s\n", GC_m2s (type)); | ||
1510 | |||
1511 | t->ephm_h = NULL; | ||
1512 | |||
1513 | if (CADET_TUNNEL_KEY_OK == t->estate) | ||
1514 | return; | ||
1515 | |||
1516 | if (NULL != t->rekey_task) | ||
1517 | { | ||
1518 | GNUNET_break (0); | ||
1519 | GCT_debug (t, GNUNET_ERROR_TYPE_WARNING); | ||
1520 | GNUNET_SCHEDULER_cancel (t->rekey_task); | ||
1521 | } | ||
1522 | t->rekey_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
1523 | &kx_resend, t); | ||
1524 | |||
1525 | } | ||
1526 | |||
1527 | |||
1528 | /** | ||
1529 | * Called only on shutdown, destroy every tunnel. | ||
1530 | * | ||
1531 | * @param cls Closure (unused). | ||
1532 | * @param key Current public key. | ||
1533 | * @param value Value in the hash map (tunnel). | ||
1534 | * | ||
1535 | * @return #GNUNET_YES, so we should continue to iterate, | ||
1536 | */ | ||
1537 | static int | ||
1538 | destroy_iterator (void *cls, | ||
1539 | const struct GNUNET_PeerIdentity *key, | ||
1540 | void *value) | ||
1541 | { | ||
1542 | struct CadetTunnel *t = value; | ||
1543 | |||
1544 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1545 | "GCT_shutdown destroying tunnel at %p\n", t); | ||
1546 | GCT_destroy (t); | ||
1547 | return GNUNET_YES; | ||
1548 | } | ||
1549 | |||
1550 | |||
1551 | /** | ||
1552 | * Notify remote peer that we don't know a channel he is talking about, | ||
1553 | * probably CHANNEL_DESTROY was missed. | ||
1554 | * | ||
1555 | * @param t Tunnel on which to notify. | ||
1556 | * @param gid ID of the channel. | ||
1557 | */ | ||
1558 | static void | ||
1559 | send_channel_destroy (struct CadetTunnel *t, | ||
1560 | struct GNUNET_CADET_ChannelTunnelNumber gid) | ||
1561 | { | ||
1562 | struct GNUNET_CADET_ChannelManageMessage msg; | ||
1563 | |||
1564 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); | ||
1565 | msg.header.size = htons (sizeof (msg)); | ||
1566 | msg.ctn = gid; | ||
1567 | |||
1568 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1569 | "WARNING destroying unknown channel %u on tunnel %s\n", | ||
1570 | ntohl (gid.cn), | ||
1571 | GCT_2s (t)); | ||
1572 | send_prebuilt_message (&msg.header, t, NULL, GNUNET_YES, NULL, NULL, NULL); | ||
1573 | } | ||
1574 | |||
1575 | |||
1576 | /** | ||
1577 | * Demultiplex data per channel and call appropriate channel handler. | ||
1578 | * | ||
1579 | * @param t Tunnel on which the data came. | ||
1580 | * @param msg Data message. | ||
1581 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1582 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1583 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1584 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1585 | */ | ||
1586 | static void | ||
1587 | handle_data (struct CadetTunnel *t, | ||
1588 | const struct GNUNET_CADET_ChannelAppDataMessage *msg, | ||
1589 | int fwd) | ||
1590 | { | ||
1591 | struct CadetChannel *ch; | ||
1592 | char buf[128]; | ||
1593 | size_t size; | ||
1594 | uint16_t type; | ||
1595 | |||
1596 | /* Check size */ | ||
1597 | size = ntohs (msg->header.size); | ||
1598 | if (size < | ||
1599 | sizeof (struct GNUNET_CADET_ChannelAppDataMessage) + | ||
1600 | sizeof (struct GNUNET_MessageHeader)) | ||
1601 | { | ||
1602 | GNUNET_break (0); | ||
1603 | return; | ||
1604 | } | ||
1605 | type = ntohs (msg[1].header.type); | ||
1606 | LOG (GNUNET_ERROR_TYPE_DEBUG, " payload of type %s\n", GC_m2s (type)); | ||
1607 | SPRINTF (buf, "# received payload of type %hu", type); | ||
1608 | GNUNET_STATISTICS_update (stats, buf, 1, GNUNET_NO); | ||
1609 | |||
1610 | |||
1611 | /* Check channel */ | ||
1612 | ch = GCT_get_channel (t, msg->ctn); | ||
1613 | if (NULL == ch) | ||
1614 | { | ||
1615 | GNUNET_STATISTICS_update (stats, | ||
1616 | "# data on unknown channel", | ||
1617 | 1, | ||
1618 | GNUNET_NO); | ||
1619 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1620 | "channel 0x%X unknown\n", | ||
1621 | ntohl (msg->ctn.cn)); | ||
1622 | send_channel_destroy (t, msg->ctn); | ||
1623 | return; | ||
1624 | } | ||
1625 | |||
1626 | GCCH_handle_data (ch, msg, fwd); | ||
1627 | } | ||
1628 | |||
1629 | |||
1630 | /** | ||
1631 | * Demultiplex data ACKs per channel and update appropriate channel buffer info. | ||
1632 | * | ||
1633 | * @param t Tunnel on which the DATA ACK came. | ||
1634 | * @param msg DATA ACK message. | ||
1635 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1636 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1637 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1638 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1639 | */ | ||
1640 | static void | ||
1641 | handle_data_ack (struct CadetTunnel *t, | ||
1642 | const struct GNUNET_CADET_ChannelDataAckMessage *msg, | ||
1643 | int fwd) | ||
1644 | { | ||
1645 | struct CadetChannel *ch; | ||
1646 | size_t size; | ||
1647 | |||
1648 | /* Check size */ | ||
1649 | size = ntohs (msg->header.size); | ||
1650 | if (size != sizeof (struct GNUNET_CADET_ChannelDataAckMessage)) | ||
1651 | { | ||
1652 | GNUNET_break (0); | ||
1653 | return; | ||
1654 | } | ||
1655 | |||
1656 | /* Check channel */ | ||
1657 | ch = GCT_get_channel (t, msg->ctn); | ||
1658 | if (NULL == ch) | ||
1659 | { | ||
1660 | GNUNET_STATISTICS_update (stats, "# data ack on unknown channel", | ||
1661 | 1, GNUNET_NO); | ||
1662 | LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n", | ||
1663 | ntohl (msg->ctn.cn)); | ||
1664 | return; | ||
1665 | } | ||
1666 | |||
1667 | GCCH_handle_data_ack (ch, msg, fwd); | ||
1668 | } | ||
1669 | |||
1670 | |||
1671 | /** | ||
1672 | * Handle channel create. | ||
1673 | * | ||
1674 | * @param t Tunnel on which the message came. | ||
1675 | * @param msg ChannelCreate message. | ||
1676 | */ | ||
1677 | static void | ||
1678 | handle_ch_create (struct CadetTunnel *t, | ||
1679 | const struct GNUNET_CADET_ChannelOpenMessage *msg) | ||
1680 | { | ||
1681 | struct CadetChannel *ch; | ||
1682 | size_t size; | ||
1683 | |||
1684 | /* Check size */ | ||
1685 | size = ntohs (msg->header.size); | ||
1686 | if (size != sizeof (struct GNUNET_CADET_ChannelOpenMessage)) | ||
1687 | { | ||
1688 | GNUNET_break_op (0); | ||
1689 | return; | ||
1690 | } | ||
1691 | |||
1692 | /* Check channel */ | ||
1693 | ch = GCT_get_channel (t, msg->ctn); | ||
1694 | if (NULL != ch && ! GCT_is_loopback (t)) | ||
1695 | { | ||
1696 | /* Probably a retransmission, safe to ignore */ | ||
1697 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already exists...\n"); | ||
1698 | } | ||
1699 | ch = GCCH_handle_create (t, msg); | ||
1700 | if (NULL != ch) | ||
1701 | GCT_add_channel (t, ch); | ||
1702 | } | ||
1703 | |||
1704 | |||
1705 | |||
1706 | /** | ||
1707 | * Handle channel NACK: check correctness and call channel handler for NACKs. | ||
1708 | * | ||
1709 | * @param t Tunnel on which the NACK came. | ||
1710 | * @param msg NACK message. | ||
1711 | */ | ||
1712 | static void | ||
1713 | handle_ch_nack (struct CadetTunnel *t, | ||
1714 | const struct GNUNET_CADET_ChannelManageMessage *msg) | ||
1715 | { | ||
1716 | struct CadetChannel *ch; | ||
1717 | size_t size; | ||
1718 | |||
1719 | /* Check size */ | ||
1720 | size = ntohs (msg->header.size); | ||
1721 | if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage)) | ||
1722 | { | ||
1723 | GNUNET_break (0); | ||
1724 | return; | ||
1725 | } | ||
1726 | |||
1727 | /* Check channel */ | ||
1728 | ch = GCT_get_channel (t, msg->ctn); | ||
1729 | if (NULL == ch) | ||
1730 | { | ||
1731 | GNUNET_STATISTICS_update (stats, "# channel NACK on unknown channel", | ||
1732 | 1, GNUNET_NO); | ||
1733 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1734 | "WARNING channel %u unknown\n", | ||
1735 | ntohl (msg->ctn.cn)); | ||
1736 | return; | ||
1737 | } | ||
1738 | |||
1739 | GCCH_handle_nack (ch); | ||
1740 | } | ||
1741 | |||
1742 | |||
1743 | /** | ||
1744 | * Handle a CHANNEL ACK (SYNACK/ACK). | ||
1745 | * | ||
1746 | * @param t Tunnel on which the CHANNEL ACK came. | ||
1747 | * @param msg CHANNEL ACK message. | ||
1748 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1749 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1750 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1751 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1752 | */ | ||
1753 | static void | ||
1754 | handle_ch_ack (struct CadetTunnel *t, | ||
1755 | const struct GNUNET_CADET_ChannelManageMessage *msg, | ||
1756 | int fwd) | ||
1757 | { | ||
1758 | struct CadetChannel *ch; | ||
1759 | size_t size; | ||
1760 | |||
1761 | /* Check size */ | ||
1762 | size = ntohs (msg->header.size); | ||
1763 | if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage)) | ||
1764 | { | ||
1765 | GNUNET_break (0); | ||
1766 | return; | ||
1767 | } | ||
1768 | |||
1769 | /* Check channel */ | ||
1770 | ch = GCT_get_channel (t, msg->ctn); | ||
1771 | if (NULL == ch) | ||
1772 | { | ||
1773 | GNUNET_STATISTICS_update (stats, | ||
1774 | "# channel ack on unknown channel", | ||
1775 | 1, | ||
1776 | GNUNET_NO); | ||
1777 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1778 | "WARNING channel %u unknown\n", | ||
1779 | ntohl (msg->ctn.cn)); | ||
1780 | return; | ||
1781 | } | ||
1782 | |||
1783 | GCCH_handle_ack (ch, msg, fwd); | ||
1784 | } | ||
1785 | |||
1786 | |||
1787 | /** | ||
1788 | * Handle a channel destruction message. | ||
1789 | * | ||
1790 | * @param t Tunnel on which the message came. | ||
1791 | * @param msg Channel destroy message. | ||
1792 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1793 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1794 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1795 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1796 | */ | ||
1797 | static void | ||
1798 | handle_ch_destroy (struct CadetTunnel *t, | ||
1799 | const struct GNUNET_CADET_ChannelManageMessage *msg, | ||
1800 | int fwd) | ||
1801 | { | ||
1802 | struct CadetChannel *ch; | ||
1803 | size_t size; | ||
1804 | |||
1805 | /* Check size */ | ||
1806 | size = ntohs (msg->header.size); | ||
1807 | if (size != sizeof (struct GNUNET_CADET_ChannelManageMessage)) | ||
1808 | { | ||
1809 | GNUNET_break (0); | ||
1810 | return; | ||
1811 | } | ||
1812 | |||
1813 | /* Check channel */ | ||
1814 | ch = GCT_get_channel (t, msg->ctn); | ||
1815 | if (NULL == ch) | ||
1816 | { | ||
1817 | /* Probably a retransmission, safe to ignore */ | ||
1818 | return; | ||
1819 | } | ||
1820 | |||
1821 | GCCH_handle_destroy (ch, msg, fwd); | ||
1822 | } | ||
1823 | |||
1824 | |||
1825 | /** | ||
1826 | * Free Axolotl data. | ||
1827 | * | ||
1828 | * @param t Tunnel. | ||
1829 | */ | ||
1830 | static void | ||
1831 | destroy_ax (struct CadetTunnel *t) | ||
1832 | { | ||
1833 | if (NULL == t->ax) | ||
1834 | return; | ||
1835 | |||
1836 | GNUNET_free_non_null (t->ax->DHRs); | ||
1837 | GNUNET_free_non_null (t->ax->kx_0); | ||
1838 | while (NULL != t->ax->skipped_head) | ||
1839 | delete_skipped_key (t, t->ax->skipped_head); | ||
1840 | GNUNET_assert (0 == t->ax->skipped); | ||
1841 | |||
1842 | GNUNET_free (t->ax); | ||
1843 | t->ax = NULL; | ||
1844 | |||
1845 | if (NULL != t->rekey_task) | ||
1846 | { | ||
1847 | GNUNET_SCHEDULER_cancel (t->rekey_task); | ||
1848 | t->rekey_task = NULL; | ||
1849 | } | ||
1850 | if (NULL != t->ephm_h) | ||
1851 | { | ||
1852 | GCC_cancel (t->ephm_h); | ||
1853 | t->ephm_h = NULL; | ||
1854 | } | ||
1855 | } | ||
1856 | |||
1857 | |||
1858 | /** | ||
1859 | * Demultiplex by message type and call appropriate handler for a message | ||
1860 | * towards a channel of a local tunnel. | ||
1861 | * | ||
1862 | * @param t Tunnel this message came on. | ||
1863 | * @param msgh Message header. | ||
1864 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1865 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1866 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1867 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1868 | */ | ||
1869 | static void | ||
1870 | handle_decrypted (struct CadetTunnel *t, | ||
1871 | const struct GNUNET_MessageHeader *msgh, | ||
1872 | int fwd) | ||
1873 | { | ||
1874 | uint16_t type; | ||
1875 | char buf[256]; | ||
1876 | |||
1877 | type = ntohs (msgh->type); | ||
1878 | LOG (GNUNET_ERROR_TYPE_DEBUG, "<-- %s on %s\n", GC_m2s (type), GCT_2s (t)); | ||
1879 | SPRINTF (buf, "# received encrypted of type %hu (%s)", type, GC_m2s (type)); | ||
1880 | GNUNET_STATISTICS_update (stats, buf, 1, GNUNET_NO); | ||
1881 | |||
1882 | switch (type) | ||
1883 | { | ||
1884 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE: | ||
1885 | /* Do nothing, connection aleady got updated. */ | ||
1886 | GNUNET_STATISTICS_update (stats, "# keepalives received", 1, GNUNET_NO); | ||
1887 | break; | ||
1888 | |||
1889 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA: | ||
1890 | /* Don't send hop ACK, wait for client to ACK */ | ||
1891 | handle_data (t, (struct GNUNET_CADET_ChannelAppDataMessage *) msgh, fwd); | ||
1892 | break; | ||
1893 | |||
1894 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_APP_DATA_ACK: | ||
1895 | handle_data_ack (t, (struct GNUNET_CADET_ChannelDataAckMessage *) msgh, fwd); | ||
1896 | break; | ||
1897 | |||
1898 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN: | ||
1899 | handle_ch_create (t, (struct GNUNET_CADET_ChannelOpenMessage *) msgh); | ||
1900 | break; | ||
1901 | |||
1902 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_NACK_DEPRECATED: | ||
1903 | handle_ch_nack (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh); | ||
1904 | break; | ||
1905 | |||
1906 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK: | ||
1907 | handle_ch_ack (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh, fwd); | ||
1908 | break; | ||
1909 | |||
1910 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
1911 | handle_ch_destroy (t, (struct GNUNET_CADET_ChannelManageMessage *) msgh, fwd); | ||
1912 | break; | ||
1913 | |||
1914 | default: | ||
1915 | GNUNET_break_op (0); | ||
1916 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1917 | "end-to-end message not known (%u)\n", | ||
1918 | ntohs (msgh->type)); | ||
1919 | GCT_debug (t, GNUNET_ERROR_TYPE_WARNING); | ||
1920 | } | ||
1921 | } | ||
1922 | |||
1923 | |||
1924 | /******************************************************************************/ | ||
1925 | /******************************** API ***********************************/ | ||
1926 | /******************************************************************************/ | ||
1927 | |||
1928 | /** | ||
1929 | * Decrypt and process an encrypted message. | ||
1930 | * | ||
1931 | * Calls the appropriate handler for a message in a channel of a local tunnel. | ||
1932 | * | ||
1933 | * @param t Tunnel this message came on. | ||
1934 | * @param msg Message header. | ||
1935 | */ | ||
1936 | void | ||
1937 | GCT_handle_encrypted (struct CadetTunnel *t, | ||
1938 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg) | ||
1939 | { | ||
1940 | uint16_t size = ntohs (msg->header.size); | ||
1941 | char cbuf [size]; | ||
1942 | int decrypted_size; | ||
1943 | const struct GNUNET_MessageHeader *msgh; | ||
1944 | unsigned int off; | ||
1945 | |||
1946 | GNUNET_STATISTICS_update (stats, "# received encrypted", 1, GNUNET_NO); | ||
1947 | |||
1948 | decrypted_size = t_ax_decrypt_and_validate (t, cbuf, msg, size); | ||
1949 | |||
1950 | if (-1 == decrypted_size) | ||
1951 | { | ||
1952 | GNUNET_STATISTICS_update (stats, "# unable to decrypt", 1, GNUNET_NO); | ||
1953 | if (CADET_TUNNEL_KEY_PING <= t->estate) | ||
1954 | { | ||
1955 | GNUNET_break_op (0); | ||
1956 | LOG (GNUNET_ERROR_TYPE_WARNING, "Wrong crypto, tunnel %s\n", GCT_2s (t)); | ||
1957 | GCT_debug (t, GNUNET_ERROR_TYPE_WARNING); | ||
1958 | } | ||
1959 | return; | ||
1960 | } | ||
1961 | GCT_change_estate (t, CADET_TUNNEL_KEY_OK); | ||
1962 | |||
1963 | /* FIXME: this is bad, as the structs returned from | ||
1964 | this loop may be unaligned, see util's MST for | ||
1965 | how to do this right. */ | ||
1966 | off = 0; | ||
1967 | while (off + sizeof (struct GNUNET_MessageHeader) <= decrypted_size) | ||
1968 | { | ||
1969 | uint16_t msize; | ||
1970 | |||
1971 | msgh = (const struct GNUNET_MessageHeader *) &cbuf[off]; | ||
1972 | msize = ntohs (msgh->size); | ||
1973 | if (msize < sizeof (struct GNUNET_MessageHeader)) | ||
1974 | { | ||
1975 | GNUNET_break_op (0); | ||
1976 | return; | ||
1977 | } | ||
1978 | if (off + msize < decrypted_size) | ||
1979 | { | ||
1980 | GNUNET_break_op (0); | ||
1981 | return; | ||
1982 | } | ||
1983 | handle_decrypted (t, msgh, GNUNET_SYSERR); | ||
1984 | off += msize; | ||
1985 | } | ||
1986 | } | ||
1987 | |||
1988 | |||
1989 | /** | ||
1990 | * Handle a Key eXchange message. | ||
1991 | * | ||
1992 | * @param t Tunnel on which the message came. | ||
1993 | * @param msg KX message itself. | ||
1994 | */ | ||
1995 | void | ||
1996 | GCT_handle_kx (struct CadetTunnel *t, | ||
1997 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
1998 | { | ||
1999 | struct CadetTunnelAxolotl *ax; | ||
2000 | struct GNUNET_HashCode key_material[3]; | ||
2001 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[5]; | ||
2002 | const char salt[] = "CADET Axolotl salt"; | ||
2003 | const struct GNUNET_PeerIdentity *pid; | ||
2004 | int am_I_alice; | ||
2005 | |||
2006 | CADET_TIMING_START; | ||
2007 | |||
2008 | LOG (GNUNET_ERROR_TYPE_INFO, "<== { KX} on %s\n", GCT_2s (t)); | ||
2009 | |||
2010 | if (NULL == t->ax) | ||
2011 | { | ||
2012 | /* Something is wrong if ax is NULL. Whose fault it is? */ | ||
2013 | return; | ||
2014 | } | ||
2015 | ax = t->ax; | ||
2016 | |||
2017 | pid = GCT_get_destination (t); | ||
2018 | if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, pid)) | ||
2019 | am_I_alice = GNUNET_YES; | ||
2020 | else if (0 < GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, pid)) | ||
2021 | am_I_alice = GNUNET_NO; | ||
2022 | else | ||
2023 | { | ||
2024 | GNUNET_break_op (0); | ||
2025 | return; | ||
2026 | } | ||
2027 | |||
2028 | if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->flags))) | ||
2029 | { | ||
2030 | if (NULL != t->rekey_task) | ||
2031 | { | ||
2032 | GNUNET_SCHEDULER_cancel (t->rekey_task); | ||
2033 | t->rekey_task = NULL; | ||
2034 | } | ||
2035 | GCT_send_kx (t, GNUNET_NO); | ||
2036 | } | ||
2037 | |||
2038 | if (0 == memcmp (&ax->DHRr, &msg->ratchet_key, sizeof(msg->ratchet_key))) | ||
2039 | { | ||
2040 | LOG (GNUNET_ERROR_TYPE_INFO, " known ratchet key, exit\n"); | ||
2041 | return; | ||
2042 | } | ||
2043 | |||
2044 | LOG (GNUNET_ERROR_TYPE_INFO, " is Alice? %s\n", am_I_alice ? "YES" : "NO"); | ||
2045 | |||
2046 | ax->DHRr = msg->ratchet_key; | ||
2047 | |||
2048 | /* ECDH A B0 */ | ||
2049 | if (GNUNET_YES == am_I_alice) | ||
2050 | { | ||
2051 | GNUNET_CRYPTO_eddsa_ecdh (id_key, /* A */ | ||
2052 | &msg->ephemeral_key, /* B0 */ | ||
2053 | &key_material[0]); | ||
2054 | } | ||
2055 | else | ||
2056 | { | ||
2057 | GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* B0 */ | ||
2058 | &pid->public_key, /* A */ | ||
2059 | &key_material[0]); | ||
2060 | } | ||
2061 | |||
2062 | /* ECDH A0 B */ | ||
2063 | if (GNUNET_YES == am_I_alice) | ||
2064 | { | ||
2065 | GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* A0 */ | ||
2066 | &pid->public_key, /* B */ | ||
2067 | &key_material[1]); | ||
2068 | } | ||
2069 | else | ||
2070 | { | ||
2071 | GNUNET_CRYPTO_eddsa_ecdh (id_key, /* A */ | ||
2072 | &msg->ephemeral_key, /* B0 */ | ||
2073 | &key_material[1]); | ||
2074 | |||
2075 | |||
2076 | } | ||
2077 | |||
2078 | /* ECDH A0 B0 */ | ||
2079 | /* (This is the triple-DH, we could probably safely skip this, | ||
2080 | as A0/B0 are already in the key material.) */ | ||
2081 | GNUNET_CRYPTO_ecc_ecdh (ax->kx_0, /* A0 or B0 */ | ||
2082 | &msg->ephemeral_key, /* B0 or A0 */ | ||
2083 | &key_material[2]); | ||
2084 | |||
2085 | #if DUMP_KEYS_TO_STDERR | ||
2086 | { | ||
2087 | unsigned int i; | ||
2088 | for (i = 0; i < 3; i++) | ||
2089 | LOG (GNUNET_ERROR_TYPE_INFO, "km[%u]: %s\n", | ||
2090 | i, GNUNET_h2s (&key_material[i])); | ||
2091 | } | ||
2092 | #endif | ||
2093 | |||
2094 | /* KDF */ | ||
2095 | GNUNET_CRYPTO_kdf (keys, sizeof (keys), | ||
2096 | salt, sizeof (salt), | ||
2097 | &key_material, sizeof (key_material), NULL); | ||
2098 | |||
2099 | if (0 == memcmp (&ax->RK, &keys[0], sizeof(ax->RK))) | ||
2100 | { | ||
2101 | LOG (GNUNET_ERROR_TYPE_INFO, " known handshake key, exit\n"); | ||
2102 | return; | ||
2103 | } | ||
2104 | ax->RK = keys[0]; | ||
2105 | if (GNUNET_YES == am_I_alice) | ||
2106 | { | ||
2107 | ax->HKr = keys[1]; | ||
2108 | ax->NHKs = keys[2]; | ||
2109 | ax->NHKr = keys[3]; | ||
2110 | ax->CKr = keys[4]; | ||
2111 | ax->ratchet_flag = GNUNET_YES; | ||
2112 | } | ||
2113 | else | ||
2114 | { | ||
2115 | ax->HKs = keys[1]; | ||
2116 | ax->NHKr = keys[2]; | ||
2117 | ax->NHKs = keys[3]; | ||
2118 | ax->CKs = keys[4]; | ||
2119 | ax->ratchet_flag = GNUNET_NO; | ||
2120 | ax->ratchet_allowed = GNUNET_NO; | ||
2121 | ax->ratchet_counter = 0; | ||
2122 | ax->ratchet_expiration = | ||
2123 | GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), ratchet_time); | ||
2124 | } | ||
2125 | ax->PNs = 0; | ||
2126 | ax->Nr = 0; | ||
2127 | ax->Ns = 0; | ||
2128 | |||
2129 | GCT_change_estate (t, CADET_TUNNEL_KEY_PING); | ||
2130 | send_queued_data (t); | ||
2131 | |||
2132 | CADET_TIMING_END; | ||
2133 | } | ||
2134 | |||
2135 | /** | ||
2136 | * Initialize the tunnel subsystem. | ||
2137 | * | ||
2138 | * @param c Configuration handle. | ||
2139 | * @param key ECC private key, to derive all other keys and do crypto. | ||
2140 | */ | ||
2141 | void | ||
2142 | GCT_init (const struct GNUNET_CONFIGURATION_Handle *c, | ||
2143 | const struct GNUNET_CRYPTO_EddsaPrivateKey *key) | ||
2144 | { | ||
2145 | unsigned int expected_overhead; | ||
2146 | |||
2147 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
2148 | |||
2149 | expected_overhead = 0; | ||
2150 | expected_overhead += sizeof (struct GNUNET_CADET_TunnelEncryptedMessage); | ||
2151 | expected_overhead += sizeof (struct GNUNET_CADET_ChannelAppDataMessage); | ||
2152 | expected_overhead += sizeof (struct GNUNET_CADET_ConnectionEncryptedAckMessage); | ||
2153 | GNUNET_assert (GNUNET_CONSTANTS_CADET_P2P_OVERHEAD == expected_overhead); | ||
2154 | |||
2155 | if (GNUNET_OK != | ||
2156 | GNUNET_CONFIGURATION_get_value_number (c, | ||
2157 | "CADET", | ||
2158 | "RATCHET_MESSAGES", | ||
2159 | &ratchet_messages)) | ||
2160 | { | ||
2161 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
2162 | "CADET", | ||
2163 | "RATCHET_MESSAGES", | ||
2164 | "USING DEFAULT"); | ||
2165 | ratchet_messages = 64; | ||
2166 | } | ||
2167 | if (GNUNET_OK != | ||
2168 | GNUNET_CONFIGURATION_get_value_time (c, | ||
2169 | "CADET", | ||
2170 | "RATCHET_TIME", | ||
2171 | &ratchet_time)) | ||
2172 | { | ||
2173 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
2174 | "CADET", "RATCHET_TIME", "USING DEFAULT"); | ||
2175 | ratchet_time = GNUNET_TIME_UNIT_HOURS; | ||
2176 | } | ||
2177 | |||
2178 | |||
2179 | id_key = key; | ||
2180 | tunnels = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES); | ||
2181 | } | ||
2182 | |||
2183 | |||
2184 | /** | ||
2185 | * Shut down the tunnel subsystem. | ||
2186 | */ | ||
2187 | void | ||
2188 | GCT_shutdown (void) | ||
2189 | { | ||
2190 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down tunnels\n"); | ||
2191 | GNUNET_CONTAINER_multipeermap_iterate (tunnels, &destroy_iterator, NULL); | ||
2192 | GNUNET_CONTAINER_multipeermap_destroy (tunnels); | ||
2193 | } | ||
2194 | |||
2195 | |||
2196 | /** | ||
2197 | * Create a tunnel. | ||
2198 | * | ||
2199 | * @param destination Peer this tunnel is towards. | ||
2200 | */ | ||
2201 | struct CadetTunnel * | ||
2202 | GCT_new (struct CadetPeer *destination) | ||
2203 | { | ||
2204 | struct CadetTunnel *t; | ||
2205 | |||
2206 | t = GNUNET_new (struct CadetTunnel); | ||
2207 | t->next_ctn.cn = 0; | ||
2208 | t->peer = destination; | ||
2209 | |||
2210 | if (GNUNET_OK != | ||
2211 | GNUNET_CONTAINER_multipeermap_put (tunnels, GCP_get_id (destination), t, | ||
2212 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
2213 | { | ||
2214 | GNUNET_break (0); | ||
2215 | GNUNET_free (t); | ||
2216 | return NULL; | ||
2217 | } | ||
2218 | t->ax = GNUNET_new (struct CadetTunnelAxolotl); | ||
2219 | new_ephemeral (t); | ||
2220 | t->ax->kx_0 = GNUNET_CRYPTO_ecdhe_key_create (); | ||
2221 | return t; | ||
2222 | } | ||
2223 | |||
2224 | |||
2225 | /** | ||
2226 | * Change the tunnel's connection state. | ||
2227 | * | ||
2228 | * @param t Tunnel whose connection state to change. | ||
2229 | * @param cstate New connection state. | ||
2230 | */ | ||
2231 | void | ||
2232 | GCT_change_cstate (struct CadetTunnel* t, enum CadetTunnelCState cstate) | ||
2233 | { | ||
2234 | if (NULL == t) | ||
2235 | return; | ||
2236 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s cstate %s => %s\n", | ||
2237 | GCP_2s (t->peer), cstate2s (t->cstate), cstate2s (cstate)); | ||
2238 | if (myid != GCP_get_short_id (t->peer) && | ||
2239 | CADET_TUNNEL_READY != t->cstate && | ||
2240 | CADET_TUNNEL_READY == cstate) | ||
2241 | { | ||
2242 | t->cstate = cstate; | ||
2243 | if (CADET_TUNNEL_KEY_OK == t->estate) | ||
2244 | { | ||
2245 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered send queued data\n"); | ||
2246 | send_queued_data (t); | ||
2247 | } | ||
2248 | else if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) | ||
2249 | { | ||
2250 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered KX\n"); | ||
2251 | GCT_send_kx (t, GNUNET_NO); | ||
2252 | } | ||
2253 | else | ||
2254 | { | ||
2255 | LOG (GNUNET_ERROR_TYPE_DEBUG, "estate %s\n", estate2s (t->estate)); | ||
2256 | } | ||
2257 | } | ||
2258 | t->cstate = cstate; | ||
2259 | |||
2260 | if (CADET_TUNNEL_READY == cstate | ||
2261 | && CONNECTIONS_PER_TUNNEL <= GCT_count_connections (t)) | ||
2262 | { | ||
2263 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered stop dht\n"); | ||
2264 | GCP_stop_search (t->peer); | ||
2265 | } | ||
2266 | } | ||
2267 | |||
2268 | |||
2269 | /** | ||
2270 | * Change the tunnel encryption state. | ||
2271 | * | ||
2272 | * If the encryption state changes to OK, stop the rekey task. | ||
2273 | * | ||
2274 | * @param t Tunnel whose encryption state to change, or NULL. | ||
2275 | * @param state New encryption state. | ||
2276 | */ | ||
2277 | void | ||
2278 | GCT_change_estate (struct CadetTunnel* t, enum CadetTunnelEState state) | ||
2279 | { | ||
2280 | enum CadetTunnelEState old; | ||
2281 | |||
2282 | if (NULL == t) | ||
2283 | return; | ||
2284 | |||
2285 | old = t->estate; | ||
2286 | t->estate = state; | ||
2287 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s estate was %s\n", | ||
2288 | GCP_2s (t->peer), estate2s (old)); | ||
2289 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s estate is now %s\n", | ||
2290 | GCP_2s (t->peer), estate2s (t->estate)); | ||
2291 | |||
2292 | if (CADET_TUNNEL_KEY_OK != old && CADET_TUNNEL_KEY_OK == t->estate) | ||
2293 | { | ||
2294 | if (NULL != t->rekey_task) | ||
2295 | { | ||
2296 | GNUNET_SCHEDULER_cancel (t->rekey_task); | ||
2297 | t->rekey_task = NULL; | ||
2298 | } | ||
2299 | /* Send queued data if tunnel is not loopback */ | ||
2300 | if (myid != GCP_get_short_id (t->peer)) | ||
2301 | send_queued_data (t); | ||
2302 | } | ||
2303 | } | ||
2304 | |||
2305 | |||
2306 | /** | ||
2307 | * @brief Check if tunnel has too many connections, and remove one if necessary. | ||
2308 | * | ||
2309 | * Currently this means the newest connection, unless it is a direct one. | ||
2310 | * Implemented as a task to avoid freeing a connection that is in the middle | ||
2311 | * of being created/processed. | ||
2312 | * | ||
2313 | * @param cls Closure (Tunnel to check). | ||
2314 | */ | ||
2315 | static void | ||
2316 | trim_connections (void *cls) | ||
2317 | { | ||
2318 | struct CadetTunnel *t = cls; | ||
2319 | |||
2320 | t->trim_connections_task = NULL; | ||
2321 | if (GCT_count_connections (t) > 2 * CONNECTIONS_PER_TUNNEL) | ||
2322 | { | ||
2323 | struct CadetTConnection *iter; | ||
2324 | struct CadetTConnection *c; | ||
2325 | |||
2326 | for (c = iter = t->connection_head; NULL != iter; iter = iter->next) | ||
2327 | { | ||
2328 | if ((iter->created.abs_value_us > c->created.abs_value_us) | ||
2329 | && GNUNET_NO == GCC_is_direct (iter->c)) | ||
2330 | { | ||
2331 | c = iter; | ||
2332 | } | ||
2333 | } | ||
2334 | if (NULL != c) | ||
2335 | { | ||
2336 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Too many connections on tunnel %s\n", | ||
2337 | GCT_2s (t)); | ||
2338 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying connection %s\n", | ||
2339 | GCC_2s (c->c)); | ||
2340 | GCC_destroy (c->c); | ||
2341 | } | ||
2342 | else | ||
2343 | { | ||
2344 | GNUNET_break (0); | ||
2345 | } | ||
2346 | } | ||
2347 | } | ||
2348 | |||
2349 | |||
2350 | /** | ||
2351 | * Add a connection to a tunnel. | ||
2352 | * | ||
2353 | * @param t Tunnel. | ||
2354 | * @param c Connection. | ||
2355 | */ | ||
2356 | void | ||
2357 | GCT_add_connection (struct CadetTunnel *t, struct CadetConnection *c) | ||
2358 | { | ||
2359 | struct CadetTConnection *aux; | ||
2360 | |||
2361 | GNUNET_assert (NULL != c); | ||
2362 | |||
2363 | LOG (GNUNET_ERROR_TYPE_DEBUG, "add connection %s\n", GCC_2s (c)); | ||
2364 | LOG (GNUNET_ERROR_TYPE_DEBUG, " to tunnel %s\n", GCT_2s (t)); | ||
2365 | for (aux = t->connection_head; aux != NULL; aux = aux->next) | ||
2366 | if (aux->c == c) | ||
2367 | return; | ||
2368 | |||
2369 | aux = GNUNET_new (struct CadetTConnection); | ||
2370 | aux->c = c; | ||
2371 | aux->created = GNUNET_TIME_absolute_get (); | ||
2372 | |||
2373 | GNUNET_CONTAINER_DLL_insert (t->connection_head, t->connection_tail, aux); | ||
2374 | |||
2375 | if (CADET_TUNNEL_SEARCHING == t->cstate) | ||
2376 | GCT_change_cstate (t, CADET_TUNNEL_WAITING); | ||
2377 | |||
2378 | if (NULL != t->trim_connections_task) | ||
2379 | t->trim_connections_task = GNUNET_SCHEDULER_add_now (&trim_connections, t); | ||
2380 | } | ||
2381 | |||
2382 | |||
2383 | /** | ||
2384 | * Remove a connection from a tunnel. | ||
2385 | * | ||
2386 | * @param t Tunnel. | ||
2387 | * @param c Connection. | ||
2388 | */ | ||
2389 | void | ||
2390 | GCT_remove_connection (struct CadetTunnel *t, | ||
2391 | struct CadetConnection *c) | ||
2392 | { | ||
2393 | struct CadetTConnection *aux; | ||
2394 | struct CadetTConnection *next; | ||
2395 | unsigned int conns; | ||
2396 | |||
2397 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing connection %s from tunnel %s\n", | ||
2398 | GCC_2s (c), GCT_2s (t)); | ||
2399 | for (aux = t->connection_head; aux != NULL; aux = next) | ||
2400 | { | ||
2401 | next = aux->next; | ||
2402 | if (aux->c == c) | ||
2403 | { | ||
2404 | GNUNET_CONTAINER_DLL_remove (t->connection_head, t->connection_tail, aux); | ||
2405 | GNUNET_free (aux); | ||
2406 | } | ||
2407 | } | ||
2408 | |||
2409 | conns = GCT_count_connections (t); | ||
2410 | if (0 == conns | ||
2411 | && NULL == t->destroy_task | ||
2412 | && CADET_TUNNEL_SHUTDOWN != t->cstate | ||
2413 | && GNUNET_NO == shutting_down) | ||
2414 | { | ||
2415 | if (0 == GCT_count_any_connections (t)) | ||
2416 | GCT_change_cstate (t, CADET_TUNNEL_SEARCHING); | ||
2417 | else | ||
2418 | GCT_change_cstate (t, CADET_TUNNEL_WAITING); | ||
2419 | } | ||
2420 | |||
2421 | /* Start new connections if needed */ | ||
2422 | if (CONNECTIONS_PER_TUNNEL > conns | ||
2423 | && CADET_TUNNEL_SHUTDOWN != t->cstate | ||
2424 | && GNUNET_NO == shutting_down) | ||
2425 | { | ||
2426 | LOG (GNUNET_ERROR_TYPE_DEBUG, " too few connections, getting new ones\n"); | ||
2427 | GCP_connect (t->peer); /* Will change cstate to WAITING when possible */ | ||
2428 | return; | ||
2429 | } | ||
2430 | |||
2431 | /* If not marked as ready, no change is needed */ | ||
2432 | if (CADET_TUNNEL_READY != t->cstate) | ||
2433 | return; | ||
2434 | |||
2435 | /* Check if any connection is ready to maintain cstate */ | ||
2436 | for (aux = t->connection_head; aux != NULL; aux = aux->next) | ||
2437 | if (CADET_CONNECTION_READY == GCC_get_state (aux->c)) | ||
2438 | return; | ||
2439 | } | ||
2440 | |||
2441 | |||
2442 | /** | ||
2443 | * Add a channel to a tunnel. | ||
2444 | * | ||
2445 | * @param t Tunnel. | ||
2446 | * @param ch Channel. | ||
2447 | */ | ||
2448 | void | ||
2449 | GCT_add_channel (struct CadetTunnel *t, | ||
2450 | struct CadetChannel *ch) | ||
2451 | { | ||
2452 | struct CadetTChannel *aux; | ||
2453 | |||
2454 | GNUNET_assert (NULL != ch); | ||
2455 | |||
2456 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding channel %p to tunnel %p\n", ch, t); | ||
2457 | |||
2458 | for (aux = t->channel_head; aux != NULL; aux = aux->next) | ||
2459 | { | ||
2460 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already there %p\n", aux->ch); | ||
2461 | if (aux->ch == ch) | ||
2462 | return; | ||
2463 | } | ||
2464 | |||
2465 | aux = GNUNET_new (struct CadetTChannel); | ||
2466 | aux->ch = ch; | ||
2467 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2468 | " adding %p to %p\n", aux, t->channel_head); | ||
2469 | GNUNET_CONTAINER_DLL_insert_tail (t->channel_head, | ||
2470 | t->channel_tail, | ||
2471 | aux); | ||
2472 | |||
2473 | if (NULL != t->destroy_task) | ||
2474 | { | ||
2475 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
2476 | t->destroy_task = NULL; | ||
2477 | LOG (GNUNET_ERROR_TYPE_DEBUG, " undo destroy!\n"); | ||
2478 | } | ||
2479 | } | ||
2480 | |||
2481 | |||
2482 | /** | ||
2483 | * Remove a channel from a tunnel. | ||
2484 | * | ||
2485 | * @param t Tunnel. | ||
2486 | * @param ch Channel. | ||
2487 | */ | ||
2488 | void | ||
2489 | GCT_remove_channel (struct CadetTunnel *t, struct CadetChannel *ch) | ||
2490 | { | ||
2491 | struct CadetTChannel *aux; | ||
2492 | |||
2493 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing channel %p from tunnel %p\n", ch, t); | ||
2494 | for (aux = t->channel_head; aux != NULL; aux = aux->next) | ||
2495 | { | ||
2496 | if (aux->ch == ch) | ||
2497 | { | ||
2498 | LOG (GNUNET_ERROR_TYPE_DEBUG, " found! %s\n", GCCH_2s (ch)); | ||
2499 | GNUNET_CONTAINER_DLL_remove (t->channel_head, | ||
2500 | t->channel_tail, | ||
2501 | aux); | ||
2502 | GNUNET_free (aux); | ||
2503 | return; | ||
2504 | } | ||
2505 | } | ||
2506 | } | ||
2507 | |||
2508 | |||
2509 | /** | ||
2510 | * Search for a channel by global ID. | ||
2511 | * | ||
2512 | * @param t Tunnel containing the channel. | ||
2513 | * @param ctn Public channel number. | ||
2514 | * | ||
2515 | * @return channel handler, NULL if doesn't exist | ||
2516 | */ | ||
2517 | struct CadetChannel * | ||
2518 | GCT_get_channel (struct CadetTunnel *t, | ||
2519 | struct GNUNET_CADET_ChannelTunnelNumber ctn) | ||
2520 | { | ||
2521 | struct CadetTChannel *iter; | ||
2522 | |||
2523 | if (NULL == t) | ||
2524 | return NULL; | ||
2525 | |||
2526 | for (iter = t->channel_head; NULL != iter; iter = iter->next) | ||
2527 | { | ||
2528 | if (GCCH_get_id (iter->ch).cn == ctn.cn) | ||
2529 | break; | ||
2530 | } | ||
2531 | |||
2532 | return NULL == iter ? NULL : iter->ch; | ||
2533 | } | ||
2534 | |||
2535 | |||
2536 | /** | ||
2537 | * @brief Destroy a tunnel and free all resources. | ||
2538 | * | ||
2539 | * Should only be called a while after the tunnel has been marked as destroyed, | ||
2540 | * in case there is a new channel added to the same peer shortly after marking | ||
2541 | * the tunnel. This way we avoid a new public key handshake. | ||
2542 | * | ||
2543 | * @param cls Closure (tunnel to destroy). | ||
2544 | */ | ||
2545 | static void | ||
2546 | delayed_destroy (void *cls) | ||
2547 | { | ||
2548 | struct CadetTunnel *t = cls; | ||
2549 | struct CadetTConnection *iter; | ||
2550 | |||
2551 | t->destroy_task = NULL; | ||
2552 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2553 | "delayed destroying tunnel %p\n", | ||
2554 | t); | ||
2555 | t->cstate = CADET_TUNNEL_SHUTDOWN; | ||
2556 | for (iter = t->connection_head; NULL != iter; iter = iter->next) | ||
2557 | { | ||
2558 | GCC_send_destroy (iter->c); | ||
2559 | } | ||
2560 | GCT_destroy (t); | ||
2561 | } | ||
2562 | |||
2563 | |||
2564 | /** | ||
2565 | * Tunnel is empty: destroy it. | ||
2566 | * | ||
2567 | * Notifies all connections about the destruction. | ||
2568 | * | ||
2569 | * @param t Tunnel to destroy. | ||
2570 | */ | ||
2571 | void | ||
2572 | GCT_destroy_empty (struct CadetTunnel *t) | ||
2573 | { | ||
2574 | if (GNUNET_YES == shutting_down) | ||
2575 | return; /* Will be destroyed immediately anyway */ | ||
2576 | |||
2577 | if (NULL != t->destroy_task) | ||
2578 | { | ||
2579 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2580 | "Tunnel %s is already scheduled for destruction. Tunnel debug dump:\n", | ||
2581 | GCT_2s (t)); | ||
2582 | GCT_debug (t, GNUNET_ERROR_TYPE_WARNING); | ||
2583 | GNUNET_break (0); | ||
2584 | /* should never happen, tunnel can only become empty once, and the | ||
2585 | * task identifier should be NO_TASK (cleaned when the tunnel was created | ||
2586 | * or became un-empty) | ||
2587 | */ | ||
2588 | return; | ||
2589 | } | ||
2590 | |||
2591 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s empty: scheduling destruction\n", | ||
2592 | GCT_2s (t)); | ||
2593 | |||
2594 | // FIXME make delay a config option | ||
2595 | t->destroy_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, | ||
2596 | &delayed_destroy, t); | ||
2597 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduled destroy of %p as %p\n", | ||
2598 | t, t->destroy_task); | ||
2599 | } | ||
2600 | |||
2601 | |||
2602 | /** | ||
2603 | * Destroy tunnel if empty (no more channels). | ||
2604 | * | ||
2605 | * @param t Tunnel to destroy if empty. | ||
2606 | */ | ||
2607 | void | ||
2608 | GCT_destroy_if_empty (struct CadetTunnel *t) | ||
2609 | { | ||
2610 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s destroy if empty\n", GCT_2s (t)); | ||
2611 | if (0 < GCT_count_channels (t)) | ||
2612 | return; | ||
2613 | |||
2614 | GCT_destroy_empty (t); | ||
2615 | } | ||
2616 | |||
2617 | |||
2618 | /** | ||
2619 | * Destroy the tunnel. | ||
2620 | * | ||
2621 | * This function does not generate any warning traffic to clients or peers. | ||
2622 | * | ||
2623 | * Tasks: | ||
2624 | * Cancel messages belonging to this tunnel queued to neighbors. | ||
2625 | * Free any allocated resources linked to the tunnel. | ||
2626 | * | ||
2627 | * @param t The tunnel to destroy. | ||
2628 | */ | ||
2629 | void | ||
2630 | GCT_destroy (struct CadetTunnel *t) | ||
2631 | { | ||
2632 | struct CadetTConnection *iter_c; | ||
2633 | struct CadetTConnection *next_c; | ||
2634 | struct CadetTChannel *iter_ch; | ||
2635 | struct CadetTChannel *next_ch; | ||
2636 | unsigned int keepalives_queued; | ||
2637 | |||
2638 | if (NULL == t) | ||
2639 | return; | ||
2640 | |||
2641 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2642 | "destroying tunnel %s\n", | ||
2643 | GCP_2s (t->peer)); | ||
2644 | GNUNET_break (GNUNET_YES == | ||
2645 | GNUNET_CONTAINER_multipeermap_remove (tunnels, | ||
2646 | GCP_get_id (t->peer), t)); | ||
2647 | |||
2648 | for (iter_c = t->connection_head; NULL != iter_c; iter_c = next_c) | ||
2649 | { | ||
2650 | next_c = iter_c->next; | ||
2651 | GCC_destroy (iter_c->c); | ||
2652 | } | ||
2653 | for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = next_ch) | ||
2654 | { | ||
2655 | next_ch = iter_ch->next; | ||
2656 | GCCH_destroy (iter_ch->ch); | ||
2657 | /* Should only happen on shutdown, but it's ok. */ | ||
2658 | } | ||
2659 | keepalives_queued = 0; | ||
2660 | while (NULL != t->tq_head) | ||
2661 | { | ||
2662 | /* Should have been cleaned by destuction of channel. */ | ||
2663 | struct GNUNET_MessageHeader *mh; | ||
2664 | uint16_t type; | ||
2665 | |||
2666 | mh = (struct GNUNET_MessageHeader *) &t->tq_head[1]; | ||
2667 | type = ntohs (mh->type); | ||
2668 | if (0 == keepalives_queued && GNUNET_MESSAGE_TYPE_CADET_CHANNEL_KEEPALIVE == type) | ||
2669 | { | ||
2670 | keepalives_queued = 1; | ||
2671 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2672 | "one keepalive left behind on tunnel shutdown\n"); | ||
2673 | } | ||
2674 | else if (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY == type) | ||
2675 | { | ||
2676 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2677 | "tunnel destroyed before a CHANNEL_DESTROY was sent to peer\n"); | ||
2678 | } | ||
2679 | else | ||
2680 | { | ||
2681 | GNUNET_break (0); | ||
2682 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
2683 | "message left behind on tunnel shutdown: %s\n", | ||
2684 | GC_m2s (type)); | ||
2685 | } | ||
2686 | unqueue_data (t->tq_head); | ||
2687 | } | ||
2688 | |||
2689 | |||
2690 | if (NULL != t->destroy_task) | ||
2691 | { | ||
2692 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2693 | "cancelling dest: %p\n", | ||
2694 | t->destroy_task); | ||
2695 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
2696 | t->destroy_task = NULL; | ||
2697 | } | ||
2698 | |||
2699 | if (NULL != t->trim_connections_task) | ||
2700 | { | ||
2701 | LOG (GNUNET_ERROR_TYPE_DEBUG, "cancelling trim: %p\n", | ||
2702 | t->trim_connections_task); | ||
2703 | GNUNET_SCHEDULER_cancel (t->trim_connections_task); | ||
2704 | t->trim_connections_task = NULL; | ||
2705 | } | ||
2706 | |||
2707 | GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO); | ||
2708 | GCP_set_tunnel (t->peer, NULL); | ||
2709 | |||
2710 | if (NULL != t->rekey_task) | ||
2711 | { | ||
2712 | GNUNET_SCHEDULER_cancel (t->rekey_task); | ||
2713 | t->rekey_task = NULL; | ||
2714 | } | ||
2715 | if (NULL != t->ax) | ||
2716 | destroy_ax (t); | ||
2717 | |||
2718 | GNUNET_free (t); | ||
2719 | } | ||
2720 | |||
2721 | |||
2722 | /** | ||
2723 | * @brief Use the given path for the tunnel. | ||
2724 | * Update the next and prev hops (and RCs). | ||
2725 | * (Re)start the path refresh in case the tunnel is locally owned. | ||
2726 | * | ||
2727 | * @param t Tunnel to update. | ||
2728 | * @param p Path to use. | ||
2729 | * | ||
2730 | * @return Connection created. | ||
2731 | */ | ||
2732 | struct CadetConnection * | ||
2733 | GCT_use_path (struct CadetTunnel *t, struct CadetPeerPath *path) | ||
2734 | { | ||
2735 | struct CadetConnection *c; | ||
2736 | struct GNUNET_CADET_ConnectionTunnelIdentifier cid; | ||
2737 | unsigned int own_pos; | ||
2738 | |||
2739 | if (NULL == t || NULL == path) | ||
2740 | { | ||
2741 | GNUNET_break (0); | ||
2742 | return NULL; | ||
2743 | } | ||
2744 | |||
2745 | if (CADET_TUNNEL_SHUTDOWN == t->cstate) | ||
2746 | { | ||
2747 | GNUNET_break (0); | ||
2748 | return NULL; | ||
2749 | } | ||
2750 | |||
2751 | for (own_pos = 0; own_pos < path->length; own_pos++) | ||
2752 | { | ||
2753 | if (path->peers[own_pos] == myid) | ||
2754 | break; | ||
2755 | } | ||
2756 | if (own_pos >= path->length) | ||
2757 | { | ||
2758 | GNUNET_break_op (0); | ||
2759 | return NULL; | ||
2760 | } | ||
2761 | |||
2762 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof (cid)); | ||
2763 | c = GCC_new (&cid, t, path, own_pos); | ||
2764 | if (NULL == c) | ||
2765 | { | ||
2766 | /* Path was flawed */ | ||
2767 | return NULL; | ||
2768 | } | ||
2769 | GCT_add_connection (t, c); | ||
2770 | return c; | ||
2771 | } | ||
2772 | |||
2773 | |||
2774 | /** | ||
2775 | * Count all created connections of a tunnel. Not necessarily ready connections! | ||
2776 | * | ||
2777 | * @param t Tunnel on which to count. | ||
2778 | * | ||
2779 | * @return Number of connections created, either being established or ready. | ||
2780 | */ | ||
2781 | unsigned int | ||
2782 | GCT_count_any_connections (struct CadetTunnel *t) | ||
2783 | { | ||
2784 | struct CadetTConnection *iter; | ||
2785 | unsigned int count; | ||
2786 | |||
2787 | if (NULL == t) | ||
2788 | return 0; | ||
2789 | |||
2790 | for (count = 0, iter = t->connection_head; NULL != iter; iter = iter->next) | ||
2791 | count++; | ||
2792 | |||
2793 | return count; | ||
2794 | } | ||
2795 | |||
2796 | |||
2797 | /** | ||
2798 | * Count established (ready) connections of a tunnel. | ||
2799 | * | ||
2800 | * @param t Tunnel on which to count. | ||
2801 | * | ||
2802 | * @return Number of connections. | ||
2803 | */ | ||
2804 | unsigned int | ||
2805 | GCT_count_connections (struct CadetTunnel *t) | ||
2806 | { | ||
2807 | struct CadetTConnection *iter; | ||
2808 | unsigned int count; | ||
2809 | |||
2810 | if (NULL == t) | ||
2811 | return 0; | ||
2812 | |||
2813 | for (count = 0, iter = t->connection_head; NULL != iter; iter = iter->next) | ||
2814 | if (CADET_CONNECTION_READY == GCC_get_state (iter->c)) | ||
2815 | count++; | ||
2816 | |||
2817 | return count; | ||
2818 | } | ||
2819 | |||
2820 | |||
2821 | /** | ||
2822 | * Count channels of a tunnel. | ||
2823 | * | ||
2824 | * @param t Tunnel on which to count. | ||
2825 | * | ||
2826 | * @return Number of channels. | ||
2827 | */ | ||
2828 | unsigned int | ||
2829 | GCT_count_channels (struct CadetTunnel *t) | ||
2830 | { | ||
2831 | struct CadetTChannel *iter; | ||
2832 | unsigned int count; | ||
2833 | |||
2834 | for (count = 0, iter = t->channel_head; | ||
2835 | NULL != iter; | ||
2836 | iter = iter->next, count++) /* skip */; | ||
2837 | |||
2838 | return count; | ||
2839 | } | ||
2840 | |||
2841 | |||
2842 | /** | ||
2843 | * Get the connectivity state of a tunnel. | ||
2844 | * | ||
2845 | * @param t Tunnel. | ||
2846 | * | ||
2847 | * @return Tunnel's connectivity state. | ||
2848 | */ | ||
2849 | enum CadetTunnelCState | ||
2850 | GCT_get_cstate (struct CadetTunnel *t) | ||
2851 | { | ||
2852 | if (NULL == t) | ||
2853 | { | ||
2854 | GNUNET_assert (0); | ||
2855 | return (enum CadetTunnelCState) -1; | ||
2856 | } | ||
2857 | return t->cstate; | ||
2858 | } | ||
2859 | |||
2860 | |||
2861 | /** | ||
2862 | * Get the encryption state of a tunnel. | ||
2863 | * | ||
2864 | * @param t Tunnel. | ||
2865 | * | ||
2866 | * @return Tunnel's encryption state. | ||
2867 | */ | ||
2868 | enum CadetTunnelEState | ||
2869 | GCT_get_estate (struct CadetTunnel *t) | ||
2870 | { | ||
2871 | if (NULL == t) | ||
2872 | { | ||
2873 | GNUNET_break (0); | ||
2874 | return (enum CadetTunnelEState) -1; | ||
2875 | } | ||
2876 | return t->estate; | ||
2877 | } | ||
2878 | |||
2879 | /** | ||
2880 | * Get the maximum buffer space for a tunnel towards a local client. | ||
2881 | * | ||
2882 | * @param t Tunnel. | ||
2883 | * | ||
2884 | * @return Biggest buffer space offered by any channel in the tunnel. | ||
2885 | */ | ||
2886 | unsigned int | ||
2887 | GCT_get_channels_buffer (struct CadetTunnel *t) | ||
2888 | { | ||
2889 | struct CadetTChannel *iter; | ||
2890 | unsigned int buffer; | ||
2891 | unsigned int ch_buf; | ||
2892 | |||
2893 | if (NULL == t->channel_head) | ||
2894 | { | ||
2895 | /* Probably getting buffer for a channel create/handshake. */ | ||
2896 | LOG (GNUNET_ERROR_TYPE_DEBUG, " no channels, allow max\n"); | ||
2897 | return MIN_TUNNEL_BUFFER; | ||
2898 | } | ||
2899 | |||
2900 | buffer = 0; | ||
2901 | for (iter = t->channel_head; NULL != iter; iter = iter->next) | ||
2902 | { | ||
2903 | ch_buf = get_channel_buffer (iter); | ||
2904 | if (ch_buf > buffer) | ||
2905 | buffer = ch_buf; | ||
2906 | } | ||
2907 | if (MIN_TUNNEL_BUFFER > buffer) | ||
2908 | return MIN_TUNNEL_BUFFER; | ||
2909 | |||
2910 | if (MAX_TUNNEL_BUFFER < buffer) | ||
2911 | { | ||
2912 | GNUNET_break (0); | ||
2913 | return MAX_TUNNEL_BUFFER; | ||
2914 | } | ||
2915 | return buffer; | ||
2916 | } | ||
2917 | |||
2918 | |||
2919 | /** | ||
2920 | * Get the total buffer space for a tunnel for P2P traffic. | ||
2921 | * | ||
2922 | * @param t Tunnel. | ||
2923 | * | ||
2924 | * @return Buffer space offered by all connections in the tunnel. | ||
2925 | */ | ||
2926 | unsigned int | ||
2927 | GCT_get_connections_buffer (struct CadetTunnel *t) | ||
2928 | { | ||
2929 | struct CadetTConnection *iter; | ||
2930 | unsigned int buffer; | ||
2931 | |||
2932 | if (GNUNET_NO == is_ready (t)) | ||
2933 | { | ||
2934 | if (count_queued_data (t) >= 3) | ||
2935 | return 0; | ||
2936 | else | ||
2937 | return 1; | ||
2938 | } | ||
2939 | |||
2940 | buffer = 0; | ||
2941 | for (iter = t->connection_head; NULL != iter; iter = iter->next) | ||
2942 | { | ||
2943 | if (GCC_get_state (iter->c) != CADET_CONNECTION_READY) | ||
2944 | { | ||
2945 | continue; | ||
2946 | } | ||
2947 | buffer += get_connection_buffer (iter); | ||
2948 | } | ||
2949 | |||
2950 | return buffer; | ||
2951 | } | ||
2952 | |||
2953 | |||
2954 | /** | ||
2955 | * Get the tunnel's destination. | ||
2956 | * | ||
2957 | * @param t Tunnel. | ||
2958 | * | ||
2959 | * @return ID of the destination peer. | ||
2960 | */ | ||
2961 | const struct GNUNET_PeerIdentity * | ||
2962 | GCT_get_destination (struct CadetTunnel *t) | ||
2963 | { | ||
2964 | return GCP_get_id (t->peer); | ||
2965 | } | ||
2966 | |||
2967 | |||
2968 | /** | ||
2969 | * Get the tunnel's next free global channel ID. | ||
2970 | * | ||
2971 | * @param t Tunnel. | ||
2972 | * | ||
2973 | * @return GID of a channel free to use. | ||
2974 | */ | ||
2975 | struct GNUNET_CADET_ChannelTunnelNumber | ||
2976 | GCT_get_next_ctn (struct CadetTunnel *t) | ||
2977 | { | ||
2978 | struct GNUNET_CADET_ChannelTunnelNumber ctn; | ||
2979 | struct GNUNET_CADET_ChannelTunnelNumber mask; | ||
2980 | int result; | ||
2981 | |||
2982 | /* Set bit 30 depending on the ID relationship. Bit 31 is always 0 for GID. | ||
2983 | * If our ID is bigger or loopback tunnel, start at 0, bit 30 = 0 | ||
2984 | * If peer's ID is bigger, start at 0x4... bit 30 = 1 | ||
2985 | */ | ||
2986 | result = GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, GCP_get_id (t->peer)); | ||
2987 | if (0 > result) | ||
2988 | mask.cn = htonl (0x40000000); | ||
2989 | else | ||
2990 | mask.cn = 0x0; | ||
2991 | t->next_ctn.cn |= mask.cn; | ||
2992 | |||
2993 | while (NULL != GCT_get_channel (t, t->next_ctn)) | ||
2994 | { | ||
2995 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2996 | "Channel %u exists...\n", | ||
2997 | t->next_ctn.cn); | ||
2998 | t->next_ctn.cn = htonl ((ntohl (t->next_ctn.cn) + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI); | ||
2999 | t->next_ctn.cn |= mask.cn; | ||
3000 | } | ||
3001 | ctn = t->next_ctn; | ||
3002 | t->next_ctn.cn = (t->next_ctn.cn + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; | ||
3003 | t->next_ctn.cn |= mask.cn; | ||
3004 | |||
3005 | return ctn; | ||
3006 | } | ||
3007 | |||
3008 | |||
3009 | /** | ||
3010 | * Send ACK on one or more channels due to buffer in connections. | ||
3011 | * | ||
3012 | * @param t Channel which has some free buffer space. | ||
3013 | */ | ||
3014 | void | ||
3015 | GCT_unchoke_channels (struct CadetTunnel *t) | ||
3016 | { | ||
3017 | struct CadetTChannel *iter; | ||
3018 | unsigned int buffer; | ||
3019 | unsigned int channels = GCT_count_channels (t); | ||
3020 | unsigned int choked_n; | ||
3021 | struct CadetChannel *choked[channels]; | ||
3022 | |||
3023 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GCT_unchoke_channels on %s\n", GCT_2s (t)); | ||
3024 | LOG (GNUNET_ERROR_TYPE_DEBUG, " head: %p\n", t->channel_head); | ||
3025 | if (NULL != t->channel_head) | ||
3026 | LOG (GNUNET_ERROR_TYPE_DEBUG, " head ch: %p\n", t->channel_head->ch); | ||
3027 | |||
3028 | if (NULL != t->tq_head) | ||
3029 | send_queued_data (t); | ||
3030 | |||
3031 | /* Get buffer space */ | ||
3032 | buffer = GCT_get_connections_buffer (t); | ||
3033 | if (0 == buffer) | ||
3034 | { | ||
3035 | return; | ||
3036 | } | ||
3037 | |||
3038 | /* Count and remember choked channels */ | ||
3039 | choked_n = 0; | ||
3040 | for (iter = t->channel_head; NULL != iter; iter = iter->next) | ||
3041 | { | ||
3042 | if (GNUNET_NO == get_channel_allowed (iter)) | ||
3043 | { | ||
3044 | choked[choked_n++] = iter->ch; | ||
3045 | } | ||
3046 | } | ||
3047 | |||
3048 | /* Unchoke random channels */ | ||
3049 | while (0 < buffer && 0 < choked_n) | ||
3050 | { | ||
3051 | unsigned int r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
3052 | choked_n); | ||
3053 | GCCH_allow_client (choked[r], GCCH_is_origin (choked[r], GNUNET_YES)); | ||
3054 | choked_n--; | ||
3055 | buffer--; | ||
3056 | choked[r] = choked[choked_n]; | ||
3057 | } | ||
3058 | } | ||
3059 | |||
3060 | |||
3061 | /** | ||
3062 | * Send ACK on one or more connections due to buffer space to the client. | ||
3063 | * | ||
3064 | * Iterates all connections of the tunnel and sends ACKs appropriately. | ||
3065 | * | ||
3066 | * @param t Tunnel. | ||
3067 | */ | ||
3068 | void | ||
3069 | GCT_send_connection_acks (struct CadetTunnel *t) | ||
3070 | { | ||
3071 | struct CadetTConnection *iter; | ||
3072 | uint32_t allowed; | ||
3073 | uint32_t to_allow; | ||
3074 | uint32_t allow_per_connection; | ||
3075 | unsigned int cs; | ||
3076 | unsigned int buffer; | ||
3077 | |||
3078 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel send connection ACKs on %s\n", | ||
3079 | GCT_2s (t)); | ||
3080 | |||
3081 | if (NULL == t) | ||
3082 | { | ||
3083 | GNUNET_break (0); | ||
3084 | return; | ||
3085 | } | ||
3086 | |||
3087 | if (CADET_TUNNEL_READY != t->cstate) | ||
3088 | return; | ||
3089 | |||
3090 | buffer = GCT_get_channels_buffer (t); | ||
3091 | LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer %u\n", buffer); | ||
3092 | |||
3093 | /* Count connections, how many messages are already allowed */ | ||
3094 | cs = GCT_count_connections (t); | ||
3095 | for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next) | ||
3096 | { | ||
3097 | allowed += get_connection_allowed (iter); | ||
3098 | } | ||
3099 | LOG (GNUNET_ERROR_TYPE_DEBUG, " allowed %u\n", allowed); | ||
3100 | |||
3101 | /* Make sure there is no overflow */ | ||
3102 | if (allowed > buffer) | ||
3103 | return; | ||
3104 | |||
3105 | /* Authorize connections to send more data */ | ||
3106 | to_allow = buffer - allowed; | ||
3107 | |||
3108 | for (iter = t->connection_head; | ||
3109 | NULL != iter && to_allow > 0; | ||
3110 | iter = iter->next) | ||
3111 | { | ||
3112 | if (CADET_CONNECTION_READY != GCC_get_state (iter->c) | ||
3113 | || get_connection_allowed (iter) > 64 / 3) | ||
3114 | { | ||
3115 | continue; | ||
3116 | } | ||
3117 | GNUNET_assert(cs != 0); | ||
3118 | allow_per_connection = to_allow/cs; | ||
3119 | to_allow -= allow_per_connection; | ||
3120 | cs--; | ||
3121 | GCC_allow (iter->c, allow_per_connection, | ||
3122 | GCC_is_origin (iter->c, GNUNET_NO)); | ||
3123 | } | ||
3124 | |||
3125 | if (0 != to_allow) | ||
3126 | { | ||
3127 | /* Since we don't allow if it's allowed to send 64/3, this can happen. */ | ||
3128 | LOG (GNUNET_ERROR_TYPE_DEBUG, " reminding to_allow: %u\n", to_allow); | ||
3129 | } | ||
3130 | } | ||
3131 | |||
3132 | |||
3133 | /** | ||
3134 | * Cancel a previously sent message while it's in the queue. | ||
3135 | * | ||
3136 | * ONLY can be called before the continuation given to the send function | ||
3137 | * is called. Once the continuation is called, the message is no longer in the | ||
3138 | * queue. | ||
3139 | * | ||
3140 | * @param q Handle to the queue. | ||
3141 | */ | ||
3142 | void | ||
3143 | GCT_cancel (struct CadetTunnelQueue *q) | ||
3144 | { | ||
3145 | if (NULL != q->cq) | ||
3146 | { | ||
3147 | GNUNET_assert (NULL == q->tqd); | ||
3148 | GCC_cancel (q->cq); | ||
3149 | /* tun_message_sent() will be called and free q */ | ||
3150 | } | ||
3151 | else if (NULL != q->tqd) | ||
3152 | { | ||
3153 | unqueue_data (q->tqd); | ||
3154 | q->tqd = NULL; | ||
3155 | if (NULL != q->cont) | ||
3156 | q->cont (q->cont_cls, NULL, q, 0, 0); | ||
3157 | GNUNET_free (q); | ||
3158 | } | ||
3159 | else | ||
3160 | { | ||
3161 | GNUNET_break (0); | ||
3162 | } | ||
3163 | } | ||
3164 | |||
3165 | |||
3166 | /** | ||
3167 | * Check if the tunnel has queued traffic. | ||
3168 | * | ||
3169 | * @param t Tunnel to check. | ||
3170 | * | ||
3171 | * @return #GNUNET_YES if there is queued traffic | ||
3172 | * #GNUNET_NO otherwise | ||
3173 | */ | ||
3174 | int | ||
3175 | GCT_has_queued_traffic (struct CadetTunnel *t) | ||
3176 | { | ||
3177 | return (NULL != t->tq_head) ? GNUNET_YES : GNUNET_NO; | ||
3178 | } | ||
3179 | |||
3180 | |||
3181 | /** | ||
3182 | * Sends an already built message on a tunnel, encrypting it and | ||
3183 | * choosing the best connection if not provided. | ||
3184 | * | ||
3185 | * @param message Message to send. Function modifies it. | ||
3186 | * @param t Tunnel on which this message is transmitted. | ||
3187 | * @param c Connection to use (autoselect if NULL). | ||
3188 | * @param force Force the tunnel to take the message (buffer overfill). | ||
3189 | * @param cont Continuation to call once message is really sent. | ||
3190 | * @param cont_cls Closure for @c cont. | ||
3191 | * | ||
3192 | * @return Handle to cancel message. NULL if @c cont is NULL. | ||
3193 | */ | ||
3194 | struct CadetTunnelQueue * | ||
3195 | GCT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
3196 | struct CadetTunnel *t, | ||
3197 | struct CadetConnection *c, | ||
3198 | int force, GCT_sent cont, void *cont_cls) | ||
3199 | { | ||
3200 | return send_prebuilt_message (message, t, c, force, cont, cont_cls, NULL); | ||
3201 | } | ||
3202 | |||
3203 | |||
3204 | /** | ||
3205 | * Send a KX message. | ||
3206 | * | ||
3207 | * @param t Tunnel on which to send it. | ||
3208 | * @param force_reply Force the other peer to reply with a KX message. | ||
3209 | */ | ||
3210 | void | ||
3211 | GCT_send_kx (struct CadetTunnel *t, int force_reply) | ||
3212 | { | ||
3213 | static struct CadetEncryptedMessageIdentifier zero; | ||
3214 | struct CadetConnection *c; | ||
3215 | struct GNUNET_CADET_TunnelKeyExchangeMessage msg; | ||
3216 | enum GNUNET_CADET_KX_Flags flags; | ||
3217 | |||
3218 | LOG (GNUNET_ERROR_TYPE_INFO, "==> { KX} on %s\n", GCT_2s (t)); | ||
3219 | if (NULL != t->ephm_h) | ||
3220 | { | ||
3221 | LOG (GNUNET_ERROR_TYPE_INFO, " already queued, nop\n"); | ||
3222 | return; | ||
3223 | } | ||
3224 | GNUNET_assert (GNUNET_NO == GCT_is_loopback (t)); | ||
3225 | |||
3226 | c = tunnel_get_connection (t); | ||
3227 | if (NULL == c) | ||
3228 | { | ||
3229 | if (NULL == t->destroy_task && CADET_TUNNEL_READY == t->cstate) | ||
3230 | { | ||
3231 | GNUNET_break (0); | ||
3232 | GCT_debug (t, GNUNET_ERROR_TYPE_ERROR); | ||
3233 | } | ||
3234 | return; | ||
3235 | } | ||
3236 | |||
3237 | msg.header.size = htons (sizeof (msg)); | ||
3238 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX); | ||
3239 | flags = GNUNET_CADET_KX_FLAG_NONE; | ||
3240 | if (GNUNET_YES == force_reply) | ||
3241 | flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY; | ||
3242 | msg.flags = htonl (flags); | ||
3243 | msg.cid = *GCC_get_id (c); | ||
3244 | GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->kx_0, &msg.ephemeral_key); | ||
3245 | GNUNET_CRYPTO_ecdhe_key_get_public (t->ax->DHRs, &msg.ratchet_key); | ||
3246 | |||
3247 | t->ephm_h = GCC_send_prebuilt_message (&msg.header, | ||
3248 | UINT16_MAX, | ||
3249 | zero, | ||
3250 | c, | ||
3251 | GCC_is_origin (c, GNUNET_YES), | ||
3252 | GNUNET_YES, &ephm_sent, t); | ||
3253 | if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) | ||
3254 | GCT_change_estate (t, CADET_TUNNEL_KEY_SENT); | ||
3255 | } | ||
3256 | |||
3257 | |||
3258 | /** | ||
3259 | * Is the tunnel directed towards the local peer? | ||
3260 | * | ||
3261 | * @param t Tunnel. | ||
3262 | * | ||
3263 | * @return #GNUNET_YES if it is loopback. | ||
3264 | */ | ||
3265 | int | ||
3266 | GCT_is_loopback (const struct CadetTunnel *t) | ||
3267 | { | ||
3268 | return (myid == GCP_get_short_id (t->peer)); | ||
3269 | } | ||
3270 | |||
3271 | |||
3272 | /** | ||
3273 | * Is the tunnel this path already? | ||
3274 | * | ||
3275 | * @param t Tunnel. | ||
3276 | * @param p Path. | ||
3277 | * | ||
3278 | * @return #GNUNET_YES a connection uses this path. | ||
3279 | */ | ||
3280 | int | ||
3281 | GCT_is_path_used (const struct CadetTunnel *t, const struct CadetPeerPath *p) | ||
3282 | { | ||
3283 | struct CadetTConnection *iter; | ||
3284 | |||
3285 | for (iter = t->connection_head; NULL != iter; iter = iter->next) | ||
3286 | if (path_equivalent (GCC_get_path (iter->c), p)) | ||
3287 | return GNUNET_YES; | ||
3288 | |||
3289 | return GNUNET_NO; | ||
3290 | } | ||
3291 | |||
3292 | |||
3293 | /** | ||
3294 | * Get a cost of a path for a tunnel considering existing connections. | ||
3295 | * | ||
3296 | * @param t Tunnel. | ||
3297 | * @param path Candidate path. | ||
3298 | * | ||
3299 | * @return Cost of the path (path length + number of overlapping nodes) | ||
3300 | */ | ||
3301 | unsigned int | ||
3302 | GCT_get_path_cost (const struct CadetTunnel *t, | ||
3303 | const struct CadetPeerPath *path) | ||
3304 | { | ||
3305 | struct CadetTConnection *iter; | ||
3306 | const struct CadetPeerPath *aux; | ||
3307 | unsigned int overlap; | ||
3308 | unsigned int i; | ||
3309 | unsigned int j; | ||
3310 | |||
3311 | if (NULL == path) | ||
3312 | return 0; | ||
3313 | |||
3314 | overlap = 0; | ||
3315 | GNUNET_assert (NULL != t); | ||
3316 | |||
3317 | for (i = 0; i < path->length; i++) | ||
3318 | { | ||
3319 | for (iter = t->connection_head; NULL != iter; iter = iter->next) | ||
3320 | { | ||
3321 | aux = GCC_get_path (iter->c); | ||
3322 | if (NULL == aux) | ||
3323 | continue; | ||
3324 | |||
3325 | for (j = 0; j < aux->length; j++) | ||
3326 | { | ||
3327 | if (path->peers[i] == aux->peers[j]) | ||
3328 | { | ||
3329 | overlap++; | ||
3330 | break; | ||
3331 | } | ||
3332 | } | ||
3333 | } | ||
3334 | } | ||
3335 | return path->length + overlap; | ||
3336 | } | ||
3337 | |||
3338 | |||
3339 | /** | ||
3340 | * Get the static string for the peer this tunnel is directed. | ||
3341 | * | ||
3342 | * @param t Tunnel. | ||
3343 | * | ||
3344 | * @return Static string the destination peer's ID. | ||
3345 | */ | ||
3346 | const char * | ||
3347 | GCT_2s (const struct CadetTunnel *t) | ||
3348 | { | ||
3349 | if (NULL == t) | ||
3350 | return "(NULL)"; | ||
3351 | |||
3352 | return GCP_2s (t->peer); | ||
3353 | } | ||
3354 | |||
3355 | |||
3356 | /******************************************************************************/ | ||
3357 | /***************************** INFO/DEBUG *******************************/ | ||
3358 | /******************************************************************************/ | ||
3359 | |||
3360 | static void | ||
3361 | ax_debug (const struct CadetTunnelAxolotl *ax, enum GNUNET_ErrorType level) | ||
3362 | { | ||
3363 | struct GNUNET_CRYPTO_EcdhePublicKey pub; | ||
3364 | struct CadetTunnelSkippedKey *iter; | ||
3365 | |||
3366 | LOG2 (level, "TTT RK \t %s\n", | ||
3367 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->RK)); | ||
3368 | |||
3369 | LOG2 (level, "TTT HKs \t %s\n", | ||
3370 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKs)); | ||
3371 | LOG2 (level, "TTT HKr \t %s\n", | ||
3372 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->HKr)); | ||
3373 | LOG2 (level, "TTT NHKs\t %s\n", | ||
3374 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->NHKs)); | ||
3375 | LOG2 (level, "TTT NHKr\t %s\n", | ||
3376 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->NHKr)); | ||
3377 | |||
3378 | LOG2 (level, "TTT CKs \t %s\n", | ||
3379 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKs)); | ||
3380 | LOG2 (level, "TTT CKr \t %s\n", | ||
3381 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->CKr)); | ||
3382 | |||
3383 | GNUNET_CRYPTO_ecdhe_key_get_public (ax->DHRs, &pub); | ||
3384 | LOG2 (level, "TTT DHRs\t %s\n", | ||
3385 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &pub)); | ||
3386 | LOG2 (level, "TTT DHRr\t %s\n", | ||
3387 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &ax->DHRr)); | ||
3388 | |||
3389 | LOG2 (level, "TTT Nr\t %u\tNs\t%u\n", ax->Nr, ax->Ns); | ||
3390 | LOG2 (level, "TTT PNs\t %u\tSkipped\t%u\n", ax->PNs, ax->skipped); | ||
3391 | LOG2 (level, "TTT Ratchet\t%u\n", ax->ratchet_flag); | ||
3392 | |||
3393 | for (iter = ax->skipped_head; NULL != iter; iter = iter->next) | ||
3394 | { | ||
3395 | LOG2 (level, "TTT HK\t %s\n", | ||
3396 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &iter->HK)); | ||
3397 | LOG2 (level, "TTT MK\t %s\n", | ||
3398 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &iter->MK)); | ||
3399 | } | ||
3400 | } | ||
3401 | |||
3402 | /** | ||
3403 | * Log all possible info about the tunnel state. | ||
3404 | * | ||
3405 | * @param t Tunnel to debug. | ||
3406 | * @param level Debug level to use. | ||
3407 | */ | ||
3408 | void | ||
3409 | GCT_debug (const struct CadetTunnel *t, enum GNUNET_ErrorType level) | ||
3410 | { | ||
3411 | struct CadetTChannel *iter_ch; | ||
3412 | struct CadetTConnection *iter_c; | ||
3413 | int do_log; | ||
3414 | |||
3415 | do_log = GNUNET_get_log_call_status (level & (~GNUNET_ERROR_TYPE_BULK), | ||
3416 | "cadet-tun", | ||
3417 | __FILE__, __FUNCTION__, __LINE__); | ||
3418 | if (0 == do_log) | ||
3419 | return; | ||
3420 | |||
3421 | LOG2 (level, "TTT DEBUG TUNNEL TOWARDS %s\n", GCT_2s (t)); | ||
3422 | LOG2 (level, "TTT cstate %s, estate %s\n", | ||
3423 | cstate2s (t->cstate), estate2s (t->estate)); | ||
3424 | #if DUMP_KEYS_TO_STDERR | ||
3425 | ax_debug (t->ax, level); | ||
3426 | #endif | ||
3427 | LOG2 (level, "TTT tq_head %p, tq_tail %p\n", t->tq_head, t->tq_tail); | ||
3428 | LOG2 (level, "TTT destroy %p\n", t->destroy_task); | ||
3429 | LOG2 (level, "TTT channels:\n"); | ||
3430 | for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = iter_ch->next) | ||
3431 | { | ||
3432 | GCCH_debug (iter_ch->ch, level); | ||
3433 | } | ||
3434 | |||
3435 | LOG2 (level, "TTT connections:\n"); | ||
3436 | for (iter_c = t->connection_head; NULL != iter_c; iter_c = iter_c->next) | ||
3437 | { | ||
3438 | GCC_debug (iter_c->c, level); | ||
3439 | } | ||
3440 | |||
3441 | LOG2 (level, "TTT DEBUG TUNNEL END\n"); | ||
3442 | } | ||
3443 | |||
3444 | |||
3445 | /** | ||
3446 | * Iterate all tunnels. | ||
3447 | * | ||
3448 | * @param iter Iterator. | ||
3449 | * @param cls Closure for @c iter. | ||
3450 | */ | ||
3451 | void | ||
3452 | GCT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls) | ||
3453 | { | ||
3454 | GNUNET_CONTAINER_multipeermap_iterate (tunnels, iter, cls); | ||
3455 | } | ||
3456 | |||
3457 | |||
3458 | /** | ||
3459 | * Count all tunnels. | ||
3460 | * | ||
3461 | * @return Number of tunnels to remote peers kept by this peer. | ||
3462 | */ | ||
3463 | unsigned int | ||
3464 | GCT_count_all (void) | ||
3465 | { | ||
3466 | return GNUNET_CONTAINER_multipeermap_size (tunnels); | ||
3467 | } | ||
3468 | |||
3469 | |||
3470 | /** | ||
3471 | * Iterate all connections of a tunnel. | ||
3472 | * | ||
3473 | * @param t Tunnel whose connections to iterate. | ||
3474 | * @param iter Iterator. | ||
3475 | * @param cls Closure for @c iter. | ||
3476 | */ | ||
3477 | void | ||
3478 | GCT_iterate_connections (struct CadetTunnel *t, GCT_conn_iter iter, void *cls) | ||
3479 | { | ||
3480 | struct CadetTConnection *ct; | ||
3481 | |||
3482 | for (ct = t->connection_head; NULL != ct; ct = ct->next) | ||
3483 | iter (cls, ct->c); | ||
3484 | } | ||
3485 | |||
3486 | |||
3487 | /** | ||
3488 | * Iterate all channels of a tunnel. | ||
3489 | * | ||
3490 | * @param t Tunnel whose channels to iterate. | ||
3491 | * @param iter Iterator. | ||
3492 | * @param cls Closure for @c iter. | ||
3493 | */ | ||
3494 | void | ||
3495 | GCT_iterate_channels (struct CadetTunnel *t, GCT_chan_iter iter, void *cls) | ||
3496 | { | ||
3497 | struct CadetTChannel *cht; | ||
3498 | |||
3499 | for (cht = t->channel_head; NULL != cht; cht = cht->next) | ||
3500 | iter (cls, cht->ch); | ||
3501 | } | ||
diff --git a/src/cadet/gnunet-service-cadet_tunnel.h b/src/cadet/gnunet-service-cadet_tunnel.h deleted file mode 100644 index 0abdc02ce..000000000 --- a/src/cadet/gnunet-service-cadet_tunnel.h +++ /dev/null | |||
@@ -1,616 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_tunnel.h | ||
23 | * @brief cadet service; dealing with tunnels and crypto | ||
24 | * @author Bartlomiej Polot | ||
25 | * | ||
26 | * All functions in this file should use the prefix GMT (Gnunet Cadet Tunnel) | ||
27 | */ | ||
28 | |||
29 | #ifndef GNUNET_SERVICE_CADET_TUNNEL_H | ||
30 | #define GNUNET_SERVICE_CADET_TUNNEL_H | ||
31 | |||
32 | #ifdef __cplusplus | ||
33 | extern "C" | ||
34 | { | ||
35 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
36 | } | ||
37 | #endif | ||
38 | #endif | ||
39 | |||
40 | #include "platform.h" | ||
41 | #include "gnunet_util_lib.h" | ||
42 | |||
43 | #define CONNECTIONS_PER_TUNNEL 3 | ||
44 | |||
45 | /** | ||
46 | * All the connectivity states a tunnel can be in. | ||
47 | */ | ||
48 | enum CadetTunnelCState | ||
49 | { | ||
50 | /** | ||
51 | * Uninitialized status, should never appear in operation. | ||
52 | */ | ||
53 | CADET_TUNNEL_NEW, | ||
54 | |||
55 | /** | ||
56 | * No path to the peer known yet. | ||
57 | */ | ||
58 | CADET_TUNNEL_SEARCHING, | ||
59 | |||
60 | /** | ||
61 | * Request sent, not yet answered. | ||
62 | */ | ||
63 | CADET_TUNNEL_WAITING, | ||
64 | |||
65 | /** | ||
66 | * Peer connected and ready to accept data. | ||
67 | */ | ||
68 | CADET_TUNNEL_READY, | ||
69 | |||
70 | /** | ||
71 | * Tunnel being shut down, don't try to keep it alive. | ||
72 | */ | ||
73 | CADET_TUNNEL_SHUTDOWN | ||
74 | }; | ||
75 | |||
76 | |||
77 | /** | ||
78 | * All the encryption states a tunnel can be in. | ||
79 | */ | ||
80 | enum CadetTunnelEState | ||
81 | { | ||
82 | /** | ||
83 | * Uninitialized status, should never appear in operation. | ||
84 | */ | ||
85 | CADET_TUNNEL_KEY_UNINITIALIZED, | ||
86 | |||
87 | /** | ||
88 | * Ephemeral key sent, waiting for peer's key. | ||
89 | */ | ||
90 | CADET_TUNNEL_KEY_SENT, | ||
91 | |||
92 | /** | ||
93 | * In OTR: New ephemeral key and ping sent, waiting for pong. | ||
94 | * | ||
95 | * This means that we DO have the peer's ephemeral key, otherwise the | ||
96 | * state would be KEY_SENT. We DO NOT have a valid session key (either no | ||
97 | * previous key or previous key expired). | ||
98 | * | ||
99 | * | ||
100 | * In Axolotl: Key sent and received but no deciphered traffic yet. | ||
101 | * | ||
102 | * This means that we can send traffic (otherwise we would never complete | ||
103 | * the handshake), but we don't have complete confirmation. Since the first | ||
104 | * traffic MUST be a complete channel creation 3-way handshake, no payload | ||
105 | * will be sent before confirmation. | ||
106 | */ | ||
107 | CADET_TUNNEL_KEY_PING, | ||
108 | |||
109 | /** | ||
110 | * Handshake completed: session key available. | ||
111 | */ | ||
112 | CADET_TUNNEL_KEY_OK, | ||
113 | |||
114 | /** | ||
115 | * New ephemeral key and ping sent, waiting for pong. Unlike KEY_PING, | ||
116 | * we still have a valid session key and therefore we *can* still send | ||
117 | * traffic on the tunnel. | ||
118 | */ | ||
119 | CADET_TUNNEL_KEY_REKEY | ||
120 | }; | ||
121 | |||
122 | /** | ||
123 | * Struct containing all information regarding a given peer | ||
124 | */ | ||
125 | struct CadetTunnel; | ||
126 | |||
127 | |||
128 | #include "gnunet-service-cadet_channel.h" | ||
129 | #include "gnunet-service-cadet_connection.h" | ||
130 | #include "gnunet-service-cadet_peer.h" | ||
131 | |||
132 | /** | ||
133 | * Handle for messages queued but not yet sent. | ||
134 | */ | ||
135 | struct CadetTunnelQueue; | ||
136 | |||
137 | /** | ||
138 | * Callback called when a queued message is sent. | ||
139 | * | ||
140 | * @param cls Closure. | ||
141 | * @param t Tunnel this message was on. | ||
142 | * @param type Type of message sent. | ||
143 | * @param size Size of the message. | ||
144 | */ | ||
145 | typedef void | ||
146 | (*GCT_sent) (void *cls, | ||
147 | struct CadetTunnel *t, | ||
148 | struct CadetTunnelQueue *q, | ||
149 | uint16_t type, size_t size); | ||
150 | |||
151 | typedef void | ||
152 | (*GCT_conn_iter) (void *cls, struct CadetConnection *c); | ||
153 | |||
154 | |||
155 | typedef void | ||
156 | (*GCT_chan_iter) (void *cls, struct CadetChannel *ch); | ||
157 | |||
158 | |||
159 | /******************************************************************************/ | ||
160 | /******************************** API ***********************************/ | ||
161 | /******************************************************************************/ | ||
162 | |||
163 | /** | ||
164 | * Initialize tunnel subsystem. | ||
165 | * | ||
166 | * @param c Configuration handle. | ||
167 | * @param key ECC private key, to derive all other keys and do crypto. | ||
168 | */ | ||
169 | void | ||
170 | GCT_init (const struct GNUNET_CONFIGURATION_Handle *c, | ||
171 | const struct GNUNET_CRYPTO_EddsaPrivateKey *key); | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Shut down the tunnel subsystem. | ||
176 | */ | ||
177 | void | ||
178 | GCT_shutdown (void); | ||
179 | |||
180 | |||
181 | /** | ||
182 | * Create a tunnel. | ||
183 | * | ||
184 | * @param destination Peer this tunnel is towards. | ||
185 | */ | ||
186 | struct CadetTunnel * | ||
187 | GCT_new (struct CadetPeer *destination); | ||
188 | |||
189 | |||
190 | /** | ||
191 | * Tunnel is empty: destroy it. | ||
192 | * | ||
193 | * Notifies all connections about the destruction. | ||
194 | * | ||
195 | * @param t Tunnel to destroy. | ||
196 | */ | ||
197 | void | ||
198 | GCT_destroy_empty (struct CadetTunnel *t); | ||
199 | |||
200 | |||
201 | /** | ||
202 | * Destroy tunnel if empty (no more channels). | ||
203 | * | ||
204 | * @param t Tunnel to destroy if empty. | ||
205 | */ | ||
206 | void | ||
207 | GCT_destroy_if_empty (struct CadetTunnel *t); | ||
208 | |||
209 | |||
210 | /** | ||
211 | * Destroy the tunnel. | ||
212 | * | ||
213 | * This function does not generate any warning traffic to clients or peers. | ||
214 | * | ||
215 | * Tasks: | ||
216 | * Cancel messages belonging to this tunnel queued to neighbors. | ||
217 | * Free any allocated resources linked to the tunnel. | ||
218 | * | ||
219 | * @param t The tunnel to destroy. | ||
220 | */ | ||
221 | void | ||
222 | GCT_destroy (struct CadetTunnel *t); | ||
223 | |||
224 | |||
225 | /** | ||
226 | * Change the tunnel's connection state. | ||
227 | * | ||
228 | * @param t Tunnel whose connection state to change. | ||
229 | * @param cstate New connection state. | ||
230 | */ | ||
231 | void | ||
232 | GCT_change_cstate (struct CadetTunnel* t, enum CadetTunnelCState cstate); | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Change the tunnel encryption state. | ||
237 | * | ||
238 | * @param t Tunnel whose encryption state to change. | ||
239 | * @param state New encryption state. | ||
240 | */ | ||
241 | void | ||
242 | GCT_change_estate (struct CadetTunnel* t, enum CadetTunnelEState state); | ||
243 | |||
244 | |||
245 | /** | ||
246 | * Add a connection to a tunnel. | ||
247 | * | ||
248 | * @param t Tunnel. | ||
249 | * @param c Connection. | ||
250 | */ | ||
251 | void | ||
252 | GCT_add_connection (struct CadetTunnel *t, struct CadetConnection *c); | ||
253 | |||
254 | |||
255 | /** | ||
256 | * Remove a connection from a tunnel. | ||
257 | * | ||
258 | * @param t Tunnel. | ||
259 | * @param c Connection. | ||
260 | */ | ||
261 | void | ||
262 | GCT_remove_connection (struct CadetTunnel *t, struct CadetConnection *c); | ||
263 | |||
264 | |||
265 | /** | ||
266 | * Add a channel to a tunnel. | ||
267 | * | ||
268 | * @param t Tunnel. | ||
269 | * @param ch Channel. | ||
270 | */ | ||
271 | void | ||
272 | GCT_add_channel (struct CadetTunnel *t, struct CadetChannel *ch); | ||
273 | |||
274 | |||
275 | /** | ||
276 | * Remove a channel from a tunnel. | ||
277 | * | ||
278 | * @param t Tunnel. | ||
279 | * @param ch Channel. | ||
280 | */ | ||
281 | void | ||
282 | GCT_remove_channel (struct CadetTunnel *t, struct CadetChannel *ch); | ||
283 | |||
284 | |||
285 | /** | ||
286 | * Search for a channel by global ID. | ||
287 | * | ||
288 | * @param t Tunnel containing the channel. | ||
289 | * @param ctn Public channel number. | ||
290 | * | ||
291 | * @return channel handler, NULL if doesn't exist | ||
292 | */ | ||
293 | struct CadetChannel * | ||
294 | GCT_get_channel (struct CadetTunnel *t, struct GNUNET_CADET_ChannelTunnelNumber ctn); | ||
295 | |||
296 | |||
297 | /** | ||
298 | * Decrypt and process an encrypted message. | ||
299 | * | ||
300 | * Calls the appropriate handler for a message in a channel of a local tunnel. | ||
301 | * | ||
302 | * @param t Tunnel this message came on. | ||
303 | * @param msg Message header. | ||
304 | */ | ||
305 | void | ||
306 | GCT_handle_encrypted (struct CadetTunnel *t, | ||
307 | const struct GNUNET_CADET_TunnelEncryptedMessage *msg); | ||
308 | |||
309 | |||
310 | /** | ||
311 | * Handle a Key eXchange message. | ||
312 | * | ||
313 | * @param t Tunnel on which the message came. | ||
314 | * @param msg KX message itself. | ||
315 | */ | ||
316 | void | ||
317 | GCT_handle_kx (struct CadetTunnel *t, | ||
318 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg); | ||
319 | |||
320 | |||
321 | /** | ||
322 | * @brief Use the given path for the tunnel. | ||
323 | * Update the next and prev hops (and RCs). | ||
324 | * (Re)start the path refresh in case the tunnel is locally owned. | ||
325 | * | ||
326 | * @param t Tunnel to update. | ||
327 | * @param p Path to use. | ||
328 | * | ||
329 | * @return Connection created. | ||
330 | */ | ||
331 | struct CadetConnection * | ||
332 | GCT_use_path (struct CadetTunnel *t, struct CadetPeerPath *p); | ||
333 | |||
334 | |||
335 | /** | ||
336 | * Count all created connections of a tunnel. Not necessarily ready connections! | ||
337 | * | ||
338 | * @param t Tunnel on which to count. | ||
339 | * | ||
340 | * @return Number of connections created, either being established or ready. | ||
341 | */ | ||
342 | unsigned int | ||
343 | GCT_count_any_connections (struct CadetTunnel *t); | ||
344 | |||
345 | |||
346 | /** | ||
347 | * Count established (ready) connections of a tunnel. | ||
348 | * | ||
349 | * @param t Tunnel on which to count. | ||
350 | * | ||
351 | * @return Number of connections. | ||
352 | */ | ||
353 | unsigned int | ||
354 | GCT_count_connections (struct CadetTunnel *t); | ||
355 | |||
356 | |||
357 | /** | ||
358 | * Count channels of a tunnel. | ||
359 | * | ||
360 | * @param t Tunnel on which to count. | ||
361 | * | ||
362 | * @return Number of channels. | ||
363 | */ | ||
364 | unsigned int | ||
365 | GCT_count_channels (struct CadetTunnel *t); | ||
366 | |||
367 | |||
368 | /** | ||
369 | * Get the connectivity state of a tunnel. | ||
370 | * | ||
371 | * @param t Tunnel. | ||
372 | * | ||
373 | * @return Tunnel's connectivity state. | ||
374 | */ | ||
375 | enum CadetTunnelCState | ||
376 | GCT_get_cstate (struct CadetTunnel *t); | ||
377 | |||
378 | |||
379 | /** | ||
380 | * Get the encryption state of a tunnel. | ||
381 | * | ||
382 | * @param t Tunnel. | ||
383 | * | ||
384 | * @return Tunnel's encryption state. | ||
385 | */ | ||
386 | enum CadetTunnelEState | ||
387 | GCT_get_estate (struct CadetTunnel *t); | ||
388 | |||
389 | |||
390 | /** | ||
391 | * Get the maximum buffer space for a tunnel towards a local client. | ||
392 | * | ||
393 | * @param t Tunnel. | ||
394 | * | ||
395 | * @return Biggest buffer space offered by any channel in the tunnel. | ||
396 | */ | ||
397 | unsigned int | ||
398 | GCT_get_channels_buffer (struct CadetTunnel *t); | ||
399 | |||
400 | |||
401 | /** | ||
402 | * Get the total buffer space for a tunnel for P2P traffic. | ||
403 | * | ||
404 | * @param t Tunnel. | ||
405 | * | ||
406 | * @return Buffer space offered by all connections in the tunnel. | ||
407 | */ | ||
408 | unsigned int | ||
409 | GCT_get_connections_buffer (struct CadetTunnel *t); | ||
410 | |||
411 | |||
412 | /** | ||
413 | * Get the tunnel's destination. | ||
414 | * | ||
415 | * @param t Tunnel. | ||
416 | * | ||
417 | * @return ID of the destination peer. | ||
418 | */ | ||
419 | const struct GNUNET_PeerIdentity * | ||
420 | GCT_get_destination (struct CadetTunnel *t); | ||
421 | |||
422 | |||
423 | /** | ||
424 | * Get the tunnel's next free Channel ID. | ||
425 | * | ||
426 | * @param t Tunnel. | ||
427 | * | ||
428 | * @return ID of a channel free to use. | ||
429 | */ | ||
430 | struct GNUNET_CADET_ChannelTunnelNumber | ||
431 | GCT_get_next_ctn (struct CadetTunnel *t); | ||
432 | |||
433 | |||
434 | /** | ||
435 | * Send ACK on one or more channels due to buffer in connections. | ||
436 | * | ||
437 | * @param t Channel which has some free buffer space. | ||
438 | */ | ||
439 | void | ||
440 | GCT_unchoke_channels (struct CadetTunnel *t); | ||
441 | |||
442 | |||
443 | /** | ||
444 | * Send ACK on one or more connections due to buffer space to the client. | ||
445 | * | ||
446 | * Iterates all connections of the tunnel and sends ACKs appropriately. | ||
447 | * | ||
448 | * @param t Tunnel which has some free buffer space. | ||
449 | */ | ||
450 | void | ||
451 | GCT_send_connection_acks (struct CadetTunnel *t); | ||
452 | |||
453 | |||
454 | /** | ||
455 | * Cancel a previously sent message while it's in the queue. | ||
456 | * | ||
457 | * ONLY can be called before the continuation given to the send function | ||
458 | * is called. Once the continuation is called, the message is no longer in the | ||
459 | * queue. | ||
460 | * | ||
461 | * @param q Handle to the queue. | ||
462 | */ | ||
463 | void | ||
464 | GCT_cancel (struct CadetTunnelQueue *q); | ||
465 | |||
466 | |||
467 | /** | ||
468 | * Check if the tunnel has queued traffic. | ||
469 | * | ||
470 | * @param t Tunnel to check. | ||
471 | * | ||
472 | * @return #GNUNET_YES if there is queued traffic | ||
473 | * #GNUNET_NO otherwise | ||
474 | */ | ||
475 | int | ||
476 | GCT_has_queued_traffic (struct CadetTunnel *t); | ||
477 | |||
478 | /** | ||
479 | * Sends an already built message on a tunnel, encrypting it and | ||
480 | * choosing the best connection. | ||
481 | * | ||
482 | * @param message Message to send. Function modifies it. | ||
483 | * @param t Tunnel on which this message is transmitted. | ||
484 | * @param c Connection to use (autoselect if NULL). | ||
485 | * @param force Force the tunnel to take the message (buffer overfill). | ||
486 | * @param cont Continuation to call once message is really sent. | ||
487 | * @param cont_cls Closure for @c cont. | ||
488 | * | ||
489 | * @return Handle to cancel message. NULL if @c cont is NULL. | ||
490 | */ | ||
491 | struct CadetTunnelQueue * | ||
492 | GCT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
493 | struct CadetTunnel *t, struct CadetConnection *c, | ||
494 | int force, GCT_sent cont, void *cont_cls); | ||
495 | |||
496 | |||
497 | /** | ||
498 | * Send a KX message. | ||
499 | * | ||
500 | * @param t Tunnel on which to send it. | ||
501 | * @param force_reply Force the other peer to reply with a KX message. | ||
502 | */ | ||
503 | void | ||
504 | GCT_send_kx (struct CadetTunnel *t, int force_reply); | ||
505 | |||
506 | |||
507 | /** | ||
508 | * Is the tunnel directed towards the local peer? | ||
509 | * | ||
510 | * @param t Tunnel. | ||
511 | * | ||
512 | * @return #GNUNET_YES if it is loopback. | ||
513 | */ | ||
514 | int | ||
515 | GCT_is_loopback (const struct CadetTunnel *t); | ||
516 | |||
517 | |||
518 | /** | ||
519 | * Is the tunnel using this path already? | ||
520 | * | ||
521 | * @param t Tunnel. | ||
522 | * @param p Path. | ||
523 | * | ||
524 | * @return #GNUNET_YES a connection uses this path. | ||
525 | */ | ||
526 | int | ||
527 | GCT_is_path_used (const struct CadetTunnel *t, const struct CadetPeerPath *p); | ||
528 | |||
529 | |||
530 | /** | ||
531 | * Get a cost of a path for a tunnel considering existing connections. | ||
532 | * | ||
533 | * @param t Tunnel. | ||
534 | * @param path Candidate path. | ||
535 | * | ||
536 | * @return Cost of the path (path length + number of overlapping nodes) | ||
537 | */ | ||
538 | unsigned int | ||
539 | GCT_get_path_cost (const struct CadetTunnel *t, | ||
540 | const struct CadetPeerPath *path); | ||
541 | |||
542 | |||
543 | /** | ||
544 | * Get the static string for the peer this tunnel is directed. | ||
545 | * | ||
546 | * @param t Tunnel. | ||
547 | * | ||
548 | * @return Static string the destination peer's ID. | ||
549 | */ | ||
550 | const char * | ||
551 | GCT_2s (const struct CadetTunnel *t); | ||
552 | |||
553 | |||
554 | /** | ||
555 | * Log all possible info about the tunnel state. | ||
556 | * | ||
557 | * @param t Tunnel to debug. | ||
558 | * @param level Debug level to use. | ||
559 | */ | ||
560 | void | ||
561 | GCT_debug (const struct CadetTunnel *t, enum GNUNET_ErrorType level); | ||
562 | |||
563 | |||
564 | /** | ||
565 | * Iterate all tunnels. | ||
566 | * | ||
567 | * @param iter Iterator. | ||
568 | * @param cls Closure for @c iter. | ||
569 | */ | ||
570 | void | ||
571 | GCT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls); | ||
572 | |||
573 | |||
574 | /** | ||
575 | * Count all tunnels. | ||
576 | * | ||
577 | * @return Number of tunnels to remote peers kept by this peer. | ||
578 | */ | ||
579 | unsigned int | ||
580 | GCT_count_all (void); | ||
581 | |||
582 | |||
583 | /** | ||
584 | * Iterate all connections of a tunnel. | ||
585 | * | ||
586 | * @param t Tunnel whose connections to iterate. | ||
587 | * @param iter Iterator. | ||
588 | * @param cls Closure for @c iter. | ||
589 | */ | ||
590 | void | ||
591 | GCT_iterate_connections (struct CadetTunnel *t, GCT_conn_iter iter, void *cls); | ||
592 | |||
593 | |||
594 | /** | ||
595 | * Iterate all channels of a tunnel. | ||
596 | * | ||
597 | * @param t Tunnel whose channels to iterate. | ||
598 | * @param iter Iterator. | ||
599 | * @param cls Closure for @c iter. | ||
600 | */ | ||
601 | void | ||
602 | GCT_iterate_channels (struct CadetTunnel *t, | ||
603 | GCT_chan_iter iter, | ||
604 | void *cls); | ||
605 | |||
606 | |||
607 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
608 | { | ||
609 | #endif | ||
610 | #ifdef __cplusplus | ||
611 | } | ||
612 | #endif | ||
613 | |||
614 | /* ifndef GNUNET_CADET_SERVICE_TUNNEL_H */ | ||
615 | #endif | ||
616 | /* end of gnunet-cadet-service_tunnel.h */ | ||
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c index fd8335486..28004debc 100644 --- a/src/cadet/gnunet-service-cadet-new_tunnels.c +++ b/src/cadet/gnunet-service-cadet_tunnels.c | |||
@@ -18,35 +18,38 @@ | |||
18 | Boston, MA 02110-1301, USA. | 18 | Boston, MA 02110-1301, USA. |
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * @file cadet/gnunet-service-cadet-new_tunnels.c | 21 | * @file cadet/gnunet-service-cadet_tunnels.c |
22 | * @brief Information we track per tunnel. | 22 | * @brief Information we track per tunnel. |
23 | * @author Bartlomiej Polot | 23 | * @author Bartlomiej Polot |
24 | * @author Christian Grothoff | 24 | * @author Christian Grothoff |
25 | * | 25 | * |
26 | * FIXME: | 26 | * FIXME: |
27 | * - check KX estate machine -- make sure it is never stuck! | 27 | * - proper connection evaluation during connection management: |
28 | * - clean up KX logic, including adding sender authentication | 28 | * + consider quality (or quality spread?) of current connection set |
29 | * - implement connection management (evaluate, kill old ones, | 29 | * when deciding how often to do maintenance |
30 | * search for new ones) | 30 | * + interact with PEER to drive DHT GET/PUT operations based |
31 | * - when managing connections, distinguish those that | 31 | * on how much we like our connections |
32 | * have (recently) had traffic from those that were | ||
33 | * never ready (or not recently) | ||
34 | */ | 32 | */ |
35 | #include "platform.h" | 33 | #include "platform.h" |
36 | #include "gnunet_util_lib.h" | 34 | #include "gnunet_util_lib.h" |
37 | #include "gnunet_statistics_service.h" | 35 | #include "gnunet_statistics_service.h" |
38 | #include "gnunet_signatures.h" | 36 | #include "gnunet_signatures.h" |
39 | #include "gnunet-service-cadet-new.h" | ||
40 | #include "cadet_protocol.h" | 37 | #include "cadet_protocol.h" |
41 | #include "gnunet-service-cadet-new_channel.h" | 38 | #include "gnunet-service-cadet_channel.h" |
42 | #include "gnunet-service-cadet-new_connection.h" | 39 | #include "gnunet-service-cadet_connection.h" |
43 | #include "gnunet-service-cadet-new_tunnels.h" | 40 | #include "gnunet-service-cadet_tunnels.h" |
44 | #include "gnunet-service-cadet-new_peer.h" | 41 | #include "gnunet-service-cadet_peer.h" |
45 | #include "gnunet-service-cadet-new_paths.h" | 42 | #include "gnunet-service-cadet_paths.h" |
46 | 43 | ||
47 | 44 | ||
48 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__) | 45 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__) |
49 | 46 | ||
47 | /** | ||
48 | * How often do we try to decrypt payload with unverified key | ||
49 | * material? Used to limit CPU increase upon receiving bogus | ||
50 | * KX. | ||
51 | */ | ||
52 | #define MAX_UNVERIFIED_ATTEMPTS 16 | ||
50 | 53 | ||
51 | /** | 54 | /** |
52 | * How long do we wait until tearing down an idle tunnel? | 55 | * How long do we wait until tearing down an idle tunnel? |
@@ -54,12 +57,10 @@ | |||
54 | #define IDLE_DESTROY_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 90) | 57 | #define IDLE_DESTROY_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 90) |
55 | 58 | ||
56 | /** | 59 | /** |
57 | * Yuck, replace by 'offsetof' expression? | 60 | * How long do we wait initially before retransmitting the KX? |
58 | * FIXME. | 61 | * TODO: replace by 2 RTT if/once we have connection-level RTT data! |
59 | */ | 62 | */ |
60 | #define AX_HEADER_SIZE (sizeof (uint32_t) * 2\ | 63 | #define INITIAL_KX_RETRY_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 250) |
61 | + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)) | ||
62 | |||
63 | 64 | ||
64 | /** | 65 | /** |
65 | * Maximum number of skipped keys we keep in memory per tunnel. | 66 | * Maximum number of skipped keys we keep in memory per tunnel. |
@@ -133,52 +134,61 @@ struct CadetTunnelAxolotl | |||
133 | struct GNUNET_CRYPTO_SymmetricSessionKey RK; | 134 | struct GNUNET_CRYPTO_SymmetricSessionKey RK; |
134 | 135 | ||
135 | /** | 136 | /** |
136 | * 32-byte header key (send). | 137 | * 32-byte header key (currently used for sending). |
137 | */ | 138 | */ |
138 | struct GNUNET_CRYPTO_SymmetricSessionKey HKs; | 139 | struct GNUNET_CRYPTO_SymmetricSessionKey HKs; |
139 | 140 | ||
140 | /** | 141 | /** |
141 | * 32-byte header key (recv) | 142 | * 32-byte header key (currently used for receiving) |
142 | */ | 143 | */ |
143 | struct GNUNET_CRYPTO_SymmetricSessionKey HKr; | 144 | struct GNUNET_CRYPTO_SymmetricSessionKey HKr; |
144 | 145 | ||
145 | /** | 146 | /** |
146 | * 32-byte next header key (send). | 147 | * 32-byte next header key (for sending), used once the |
148 | * ratchet advances. We are sure that the sender has this | ||
149 | * key as well only after @e ratchet_allowed is #GNUNET_YES. | ||
147 | */ | 150 | */ |
148 | struct GNUNET_CRYPTO_SymmetricSessionKey NHKs; | 151 | struct GNUNET_CRYPTO_SymmetricSessionKey NHKs; |
149 | 152 | ||
150 | /** | 153 | /** |
151 | * 32-byte next header key (recv). | 154 | * 32-byte next header key (for receiving). To be tried |
155 | * when decrypting with @e HKr fails and thus the sender | ||
156 | * may have advanced the ratchet. | ||
152 | */ | 157 | */ |
153 | struct GNUNET_CRYPTO_SymmetricSessionKey NHKr; | 158 | struct GNUNET_CRYPTO_SymmetricSessionKey NHKr; |
154 | 159 | ||
155 | /** | 160 | /** |
156 | * 32-byte chain keys (used for forward-secrecy updating, send). | 161 | * 32-byte chain keys (used for forward-secrecy) for |
162 | * sending messages. Updated for every message. | ||
157 | */ | 163 | */ |
158 | struct GNUNET_CRYPTO_SymmetricSessionKey CKs; | 164 | struct GNUNET_CRYPTO_SymmetricSessionKey CKs; |
159 | 165 | ||
160 | /** | 166 | /** |
161 | * 32-byte chain keys (used for forward-secrecy updating, recv). | 167 | * 32-byte chain keys (used for forward-secrecy) for |
168 | * receiving messages. Updated for every message. If | ||
169 | * messages are skipped, the respective derived MKs | ||
170 | * (and the current @HKr) are kept in the @e skipped_head DLL. | ||
162 | */ | 171 | */ |
163 | struct GNUNET_CRYPTO_SymmetricSessionKey CKr; | 172 | struct GNUNET_CRYPTO_SymmetricSessionKey CKr; |
164 | 173 | ||
165 | /** | 174 | /** |
166 | * ECDH for key exchange (A0 / B0). | 175 | * ECDH for key exchange (A0 / B0). |
167 | */ | 176 | */ |
168 | struct GNUNET_CRYPTO_EcdhePrivateKey *kx_0; | 177 | struct GNUNET_CRYPTO_EcdhePrivateKey kx_0; |
169 | 178 | ||
170 | /** | 179 | /** |
171 | * ECDH Ratchet key (send). | 180 | * ECDH Ratchet key (our private key in the current DH). |
172 | */ | 181 | */ |
173 | struct GNUNET_CRYPTO_EcdhePrivateKey *DHRs; | 182 | struct GNUNET_CRYPTO_EcdhePrivateKey DHRs; |
174 | 183 | ||
175 | /** | 184 | /** |
176 | * ECDH Ratchet key (recv). | 185 | * ECDH Ratchet key (other peer's public key in the current DH). |
177 | */ | 186 | */ |
178 | struct GNUNET_CRYPTO_EcdhePublicKey DHRr; | 187 | struct GNUNET_CRYPTO_EcdhePublicKey DHRr; |
179 | 188 | ||
180 | /** | 189 | /** |
181 | * When does this ratchet expire and a new one is triggered. | 190 | * Time when the current ratchet expires and a new one is triggered |
191 | * (if @e ratchet_allowed is #GNUNET_YES). | ||
182 | */ | 192 | */ |
183 | struct GNUNET_TIME_Absolute ratchet_expiration; | 193 | struct GNUNET_TIME_Absolute ratchet_expiration; |
184 | 194 | ||
@@ -208,16 +218,28 @@ struct CadetTunnelAxolotl | |||
208 | int ratchet_flag; | 218 | int ratchet_flag; |
209 | 219 | ||
210 | /** | 220 | /** |
211 | * Number of messages recieved since our last ratchet advance. | 221 | * True (#GNUNET_YES) if we have received a message from the |
212 | * - If this counter = 0, we cannot send a new ratchet key in next msg. | 222 | * other peer that uses the keys from our last ratchet step. |
213 | * - If this counter > 0, we can (but don't yet have to) send a new key. | 223 | * This implies that we are again allowed to advance the ratchet, |
224 | * otherwise we have to wait until the other peer sees our current | ||
225 | * ephemeral key and advances first. | ||
226 | * | ||
227 | * #GNUNET_NO if we have advanced the ratched but lack any evidence | ||
228 | * that the other peer has noticed this. | ||
214 | */ | 229 | */ |
215 | unsigned int ratchet_allowed; | 230 | int ratchet_allowed; |
216 | 231 | ||
217 | /** | 232 | /** |
218 | * Number of messages recieved since our last ratchet advance. | 233 | * Number of messages recieved since our last ratchet advance. |
219 | * - If this counter = 0, we cannot send a new ratchet key in next msg. | 234 | * |
220 | * - If this counter > 0, we can (but don't yet have to) send a new key. | 235 | * If this counter = 0, we cannot send a new ratchet key in the next |
236 | * message. | ||
237 | * | ||
238 | * If this counter > 0, we could (but don't have to) send a new key. | ||
239 | * | ||
240 | * Once the @e ratchet_counter is larger than | ||
241 | * #ratchet_messages (or @e ratchet_expiration time has past), and | ||
242 | * @e ratchet_allowed is #GNUNET_YES, we advance the ratchet. | ||
221 | */ | 243 | */ |
222 | unsigned int ratchet_counter; | 244 | unsigned int ratchet_counter; |
223 | 245 | ||
@@ -247,7 +269,7 @@ struct CadetTunnelQueueEntry | |||
247 | /** | 269 | /** |
248 | * Continuation to call once sent (on the channel layer). | 270 | * Continuation to call once sent (on the channel layer). |
249 | */ | 271 | */ |
250 | GNUNET_SCHEDULER_TaskCallback cont; | 272 | GCT_SendContinuation cont; |
251 | 273 | ||
252 | /** | 274 | /** |
253 | * Closure for @c cont. | 275 | * Closure for @c cont. |
@@ -299,6 +321,15 @@ struct CadetTunnel | |||
299 | struct CadetTunnelAxolotl ax; | 321 | struct CadetTunnelAxolotl ax; |
300 | 322 | ||
301 | /** | 323 | /** |
324 | * Unverified Axolotl info, used only if we got a fresh KX (not a | ||
325 | * KX_AUTH) while our end of the tunnel was still up. In this case, | ||
326 | * we keep the fresh KX around but do not put it into action until | ||
327 | * we got encrypted payload that assures us of the authenticity of | ||
328 | * the KX. | ||
329 | */ | ||
330 | struct CadetTunnelAxolotl *unverified_ax; | ||
331 | |||
332 | /** | ||
302 | * Task scheduled if there are no more channels using the tunnel. | 333 | * Task scheduled if there are no more channels using the tunnel. |
303 | */ | 334 | */ |
304 | struct GNUNET_SCHEDULER_Task *destroy_task; | 335 | struct GNUNET_SCHEDULER_Task *destroy_task; |
@@ -329,14 +360,24 @@ struct CadetTunnel | |||
329 | struct GNUNET_MQ_Handle *mq; | 360 | struct GNUNET_MQ_Handle *mq; |
330 | 361 | ||
331 | /** | 362 | /** |
332 | * DLL of connections that are actively used to reach the destination peer. | 363 | * DLL of ready connections that are actively used to reach the destination peer. |
333 | */ | 364 | */ |
334 | struct CadetTConnection *connection_head; | 365 | struct CadetTConnection *connection_ready_head; |
335 | 366 | ||
336 | /** | 367 | /** |
337 | * DLL of connections that are actively used to reach the destination peer. | 368 | * DLL of ready connections that are actively used to reach the destination peer. |
338 | */ | 369 | */ |
339 | struct CadetTConnection *connection_tail; | 370 | struct CadetTConnection *connection_ready_tail; |
371 | |||
372 | /** | ||
373 | * DLL of connections that we maintain that might be used to reach the destination peer. | ||
374 | */ | ||
375 | struct CadetTConnection *connection_busy_head; | ||
376 | |||
377 | /** | ||
378 | * DLL of connections that we maintain that might be used to reach the destination peer. | ||
379 | */ | ||
380 | struct CadetTConnection *connection_busy_tail; | ||
340 | 381 | ||
341 | /** | 382 | /** |
342 | * Channels inside this tunnel. Maps | 383 | * Channels inside this tunnel. Maps |
@@ -359,16 +400,12 @@ struct CadetTunnel | |||
359 | */ | 400 | */ |
360 | struct CadetTunnelQueueEntry *tq_tail; | 401 | struct CadetTunnelQueueEntry *tq_tail; |
361 | 402 | ||
362 | |||
363 | /** | ||
364 | * Ephemeral message in the queue (to avoid queueing more than one). | ||
365 | */ | ||
366 | struct CadetConnectionQueue *ephm_hKILL; | ||
367 | |||
368 | /** | 403 | /** |
369 | * Pong message in the queue. | 404 | * Identification of the connection from which we are currently processing |
405 | * a message. Only valid (non-NULL) during #handle_decrypted() and the | ||
406 | * handle-*()-functions called from our @e mq during that function. | ||
370 | */ | 407 | */ |
371 | struct CadetConnectionQueue *pong_hKILL; | 408 | struct CadetTConnection *current_ct; |
372 | 409 | ||
373 | /** | 410 | /** |
374 | * How long do we wait until we retry the KX? | 411 | * How long do we wait until we retry the KX? |
@@ -381,9 +418,21 @@ struct CadetTunnel | |||
381 | struct GNUNET_TIME_Absolute next_kx_attempt; | 418 | struct GNUNET_TIME_Absolute next_kx_attempt; |
382 | 419 | ||
383 | /** | 420 | /** |
384 | * Number of connections in the @e connection_head DLL. | 421 | * Number of connections in the @e connection_ready_head DLL. |
385 | */ | 422 | */ |
386 | unsigned int num_connections; | 423 | unsigned int num_ready_connections; |
424 | |||
425 | /** | ||
426 | * Number of connections in the @e connection_busy_head DLL. | ||
427 | */ | ||
428 | unsigned int num_busy_connections; | ||
429 | |||
430 | /** | ||
431 | * How often have we tried and failed to decrypt a message using | ||
432 | * the unverified KX material from @e unverified_ax? Used to | ||
433 | * stop trying after #MAX_UNVERIFIED_ATTEMPTS. | ||
434 | */ | ||
435 | unsigned int unverified_attempts; | ||
387 | 436 | ||
388 | /** | 437 | /** |
389 | * Number of entries in the @e tq_head DLL. | 438 | * Number of entries in the @e tq_head DLL. |
@@ -395,10 +444,40 @@ struct CadetTunnel | |||
395 | */ | 444 | */ |
396 | enum CadetTunnelEState estate; | 445 | enum CadetTunnelEState estate; |
397 | 446 | ||
447 | /** | ||
448 | * Force triggering KX_AUTH independent of @e estate. | ||
449 | */ | ||
450 | int kx_auth_requested; | ||
451 | |||
398 | }; | 452 | }; |
399 | 453 | ||
400 | 454 | ||
401 | /** | 455 | /** |
456 | * Connection @a ct is now unready, clear it's ready flag | ||
457 | * and move it from the ready DLL to the busy DLL. | ||
458 | * | ||
459 | * @param ct connection to move to unready status | ||
460 | */ | ||
461 | static void | ||
462 | mark_connection_unready (struct CadetTConnection *ct) | ||
463 | { | ||
464 | struct CadetTunnel *t = ct->t; | ||
465 | |||
466 | GNUNET_assert (GNUNET_YES == ct->is_ready); | ||
467 | GNUNET_CONTAINER_DLL_remove (t->connection_ready_head, | ||
468 | t->connection_ready_tail, | ||
469 | ct); | ||
470 | GNUNET_assert (0 < t->num_ready_connections); | ||
471 | t->num_ready_connections--; | ||
472 | ct->is_ready = GNUNET_NO; | ||
473 | GNUNET_CONTAINER_DLL_insert (t->connection_busy_head, | ||
474 | t->connection_busy_tail, | ||
475 | ct); | ||
476 | t->num_busy_connections++; | ||
477 | } | ||
478 | |||
479 | |||
480 | /** | ||
402 | * Get the static string for the peer this tunnel is directed. | 481 | * Get the static string for the peer this tunnel is directed. |
403 | * | 482 | * |
404 | * @param t Tunnel. | 483 | * @param t Tunnel. |
@@ -434,19 +513,24 @@ estate2s (enum CadetTunnelEState es) | |||
434 | 513 | ||
435 | switch (es) | 514 | switch (es) |
436 | { | 515 | { |
437 | case CADET_TUNNEL_KEY_UNINITIALIZED: | 516 | case CADET_TUNNEL_KEY_UNINITIALIZED: |
438 | return "CADET_TUNNEL_KEY_UNINITIALIZED"; | 517 | return "CADET_TUNNEL_KEY_UNINITIALIZED"; |
439 | case CADET_TUNNEL_KEY_SENT: | 518 | case CADET_TUNNEL_KEY_AX_RECV: |
440 | return "CADET_TUNNEL_KEY_SENT"; | 519 | return "CADET_TUNNEL_KEY_AX_RECV"; |
441 | case CADET_TUNNEL_KEY_PING: | 520 | case CADET_TUNNEL_KEY_AX_SENT: |
442 | return "CADET_TUNNEL_KEY_PING"; | 521 | return "CADET_TUNNEL_KEY_AX_SENT"; |
443 | case CADET_TUNNEL_KEY_OK: | 522 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: |
444 | return "CADET_TUNNEL_KEY_OK"; | 523 | return "CADET_TUNNEL_KEY_AX_SENT_AND_RECV"; |
445 | case CADET_TUNNEL_KEY_REKEY: | 524 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: |
446 | return "CADET_TUNNEL_KEY_REKEY"; | 525 | return "CADET_TUNNEL_KEY_AX_AUTH_SENT"; |
447 | default: | 526 | case CADET_TUNNEL_KEY_OK: |
448 | SPRINTF (buf, "%u (UNKNOWN STATE)", es); | 527 | return "CADET_TUNNEL_KEY_OK"; |
449 | return buf; | 528 | default: |
529 | GNUNET_snprintf (buf, | ||
530 | sizeof (buf), | ||
531 | "%u (UNKNOWN STATE)", | ||
532 | es); | ||
533 | return buf; | ||
450 | } | 534 | } |
451 | } | 535 | } |
452 | 536 | ||
@@ -502,9 +586,9 @@ lookup_channel (struct CadetTunnel *t, | |||
502 | * @return Number of connections created, either being established or ready. | 586 | * @return Number of connections created, either being established or ready. |
503 | */ | 587 | */ |
504 | unsigned int | 588 | unsigned int |
505 | GCT_count_any_connections (struct CadetTunnel *t) | 589 | GCT_count_any_connections (const struct CadetTunnel *t) |
506 | { | 590 | { |
507 | return t->num_connections; | 591 | return t->num_ready_connections + t->num_busy_connections; |
508 | } | 592 | } |
509 | 593 | ||
510 | 594 | ||
@@ -518,25 +602,11 @@ GCT_count_any_connections (struct CadetTunnel *t) | |||
518 | static struct CadetTConnection * | 602 | static struct CadetTConnection * |
519 | get_ready_connection (struct CadetTunnel *t) | 603 | get_ready_connection (struct CadetTunnel *t) |
520 | { | 604 | { |
521 | for (struct CadetTConnection *pos = t->connection_head; | 605 | struct CadetTConnection *hd = t->connection_ready_head; |
522 | NULL != pos; | 606 | |
523 | pos = pos->next) | 607 | GNUNET_assert ( (NULL == hd) || |
524 | if (GNUNET_YES == pos->is_ready) | 608 | (GNUNET_YES == hd->is_ready) ); |
525 | { | 609 | return hd; |
526 | if (pos != t->connection_tail) | ||
527 | { | ||
528 | /* move 'pos' to the end, so we try other ready connections | ||
529 | first next time (round-robin, modulo availability) */ | ||
530 | GNUNET_CONTAINER_DLL_remove (t->connection_head, | ||
531 | t->connection_tail, | ||
532 | pos); | ||
533 | GNUNET_CONTAINER_DLL_insert_tail (t->connection_head, | ||
534 | t->connection_tail, | ||
535 | pos); | ||
536 | } | ||
537 | return pos; | ||
538 | } | ||
539 | return NULL; | ||
540 | } | 610 | } |
541 | 611 | ||
542 | 612 | ||
@@ -555,20 +625,6 @@ GCT_get_estate (struct CadetTunnel *t) | |||
555 | 625 | ||
556 | 626 | ||
557 | /** | 627 | /** |
558 | * Create a new Axolotl ephemeral (ratchet) key. | ||
559 | * | ||
560 | * @param t Tunnel. | ||
561 | */ | ||
562 | static void | ||
563 | new_ephemeral (struct CadetTunnel *t) | ||
564 | { | ||
565 | GNUNET_free_non_null (t->ax.DHRs); | ||
566 | t->ax.DHRs = GNUNET_CRYPTO_ecdhe_key_create (); | ||
567 | } | ||
568 | |||
569 | |||
570 | |||
571 | /** | ||
572 | * Called when either we have a new connection, or a new message in the | 628 | * Called when either we have a new connection, or a new message in the |
573 | * queue, or some existing connection has transmission capacity. Looks | 629 | * queue, or some existing connection has transmission capacity. Looks |
574 | * at our message queue and if there is a message, picks a connection | 630 | * at our message queue and if there is a message, picks a connection |
@@ -584,6 +640,21 @@ trigger_transmissions (void *cls); | |||
584 | 640 | ||
585 | 641 | ||
586 | /** | 642 | /** |
643 | * Create a new Axolotl ephemeral (ratchet) key. | ||
644 | * | ||
645 | * @param ax key material to update | ||
646 | */ | ||
647 | static void | ||
648 | new_ephemeral (struct CadetTunnelAxolotl *ax) | ||
649 | { | ||
650 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
651 | "Creating new ephemeral ratchet key (DHRs)\n"); | ||
652 | GNUNET_assert (GNUNET_OK == | ||
653 | GNUNET_CRYPTO_ecdhe_key_create2 (&ax->DHRs)); | ||
654 | } | ||
655 | |||
656 | |||
657 | /** | ||
587 | * Calculate HMAC. | 658 | * Calculate HMAC. |
588 | * | 659 | * |
589 | * @param plaintext Content to HMAC. | 660 | * @param plaintext Content to HMAC. |
@@ -609,7 +680,8 @@ t_hmac (const void *plaintext, | |||
609 | key, sizeof (*key), | 680 | key, sizeof (*key), |
610 | ctx, sizeof (ctx), | 681 | ctx, sizeof (ctx), |
611 | NULL); | 682 | NULL); |
612 | /* Two step: CADET_Hash is only 256 bits, HashCode is 512. */ | 683 | /* Two step: GNUNET_ShortHash is only 256 bits, |
684 | GNUNET_HashCode is 512, so we truncate. */ | ||
613 | GNUNET_CRYPTO_hmac (&auth_key, | 685 | GNUNET_CRYPTO_hmac (&auth_key, |
614 | plaintext, | 686 | plaintext, |
615 | size, | 687 | size, |
@@ -624,7 +696,7 @@ t_hmac (const void *plaintext, | |||
624 | * Perform a HMAC. | 696 | * Perform a HMAC. |
625 | * | 697 | * |
626 | * @param key Key to use. | 698 | * @param key Key to use. |
627 | * @param hash[out] Resulting HMAC. | 699 | * @param[out] hash Resulting HMAC. |
628 | * @param source Source key material (data to HMAC). | 700 | * @param source Source key material (data to HMAC). |
629 | * @param len Length of @a source. | 701 | * @param len Length of @a source. |
630 | */ | 702 | */ |
@@ -679,23 +751,21 @@ t_hmac_derive_key (const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | |||
679 | /** | 751 | /** |
680 | * Encrypt data with the axolotl tunnel key. | 752 | * Encrypt data with the axolotl tunnel key. |
681 | * | 753 | * |
682 | * @param t Tunnel whose key to use. | 754 | * @param ax key material to use. |
683 | * @param dst Destination with @a size bytes for the encrypted data. | 755 | * @param dst Destination with @a size bytes for the encrypted data. |
684 | * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes | 756 | * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes |
685 | * @param size Size of the buffers at @a src and @a dst | 757 | * @param size Size of the buffers at @a src and @a dst |
686 | */ | 758 | */ |
687 | static void | 759 | static void |
688 | t_ax_encrypt (struct CadetTunnel *t, | 760 | t_ax_encrypt (struct CadetTunnelAxolotl *ax, |
689 | void *dst, | 761 | void *dst, |
690 | const void *src, | 762 | const void *src, |
691 | size_t size) | 763 | size_t size) |
692 | { | 764 | { |
693 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | 765 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; |
694 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | 766 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; |
695 | struct CadetTunnelAxolotl *ax; | ||
696 | size_t out_size; | 767 | size_t out_size; |
697 | 768 | ||
698 | ax = &t->ax; | ||
699 | ax->ratchet_counter++; | 769 | ax->ratchet_counter++; |
700 | if ( (GNUNET_YES == ax->ratchet_allowed) && | 770 | if ( (GNUNET_YES == ax->ratchet_allowed) && |
701 | ( (ratchet_messages <= ax->ratchet_counter) || | 771 | ( (ratchet_messages <= ax->ratchet_counter) || |
@@ -711,11 +781,11 @@ t_ax_encrypt (struct CadetTunnel *t, | |||
711 | struct GNUNET_HashCode hmac; | 781 | struct GNUNET_HashCode hmac; |
712 | static const char ctx[] = "axolotl ratchet"; | 782 | static const char ctx[] = "axolotl ratchet"; |
713 | 783 | ||
714 | new_ephemeral (t); | 784 | new_ephemeral (ax); |
715 | ax->HKs = ax->NHKs; | 785 | ax->HKs = ax->NHKs; |
716 | 786 | ||
717 | /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */ | 787 | /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */ |
718 | GNUNET_CRYPTO_ecc_ecdh (ax->DHRs, | 788 | GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs, |
719 | &ax->DHRr, | 789 | &ax->DHRr, |
720 | &dh); | 790 | &dh); |
721 | t_ax_hmac_hash (&ax->RK, | 791 | t_ax_hmac_hash (&ax->RK, |
@@ -765,23 +835,21 @@ t_ax_encrypt (struct CadetTunnel *t, | |||
765 | /** | 835 | /** |
766 | * Decrypt data with the axolotl tunnel key. | 836 | * Decrypt data with the axolotl tunnel key. |
767 | * | 837 | * |
768 | * @param t Tunnel whose key to use. | 838 | * @param ax key material to use. |
769 | * @param dst Destination for the decrypted data, must contain @a size bytes. | 839 | * @param dst Destination for the decrypted data, must contain @a size bytes. |
770 | * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes. | 840 | * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes. |
771 | * @param size Size of the @a src and @a dst buffers | 841 | * @param size Size of the @a src and @a dst buffers |
772 | */ | 842 | */ |
773 | static void | 843 | static void |
774 | t_ax_decrypt (struct CadetTunnel *t, | 844 | t_ax_decrypt (struct CadetTunnelAxolotl *ax, |
775 | void *dst, | 845 | void *dst, |
776 | const void *src, | 846 | const void *src, |
777 | size_t size) | 847 | size_t size) |
778 | { | 848 | { |
779 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | 849 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; |
780 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | 850 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; |
781 | struct CadetTunnelAxolotl *ax; | ||
782 | size_t out_size; | 851 | size_t out_size; |
783 | 852 | ||
784 | ax = &t->ax; | ||
785 | t_hmac_derive_key (&ax->CKr, | 853 | t_hmac_derive_key (&ax->CKr, |
786 | &MK, | 854 | &MK, |
787 | "0", | 855 | "0", |
@@ -807,76 +875,72 @@ t_ax_decrypt (struct CadetTunnel *t, | |||
807 | /** | 875 | /** |
808 | * Encrypt header with the axolotl header key. | 876 | * Encrypt header with the axolotl header key. |
809 | * | 877 | * |
810 | * @param t Tunnel whose key to use. | 878 | * @param ax key material to use. |
811 | * @param msg Message whose header to encrypt. | 879 | * @param[in|out] msg Message whose header to encrypt. |
812 | */ | 880 | */ |
813 | static void | 881 | static void |
814 | t_h_encrypt (struct CadetTunnel *t, | 882 | t_h_encrypt (struct CadetTunnelAxolotl *ax, |
815 | struct GNUNET_CADET_TunnelEncryptedMessage *msg) | 883 | struct GNUNET_CADET_TunnelEncryptedMessage *msg) |
816 | { | 884 | { |
817 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | 885 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; |
818 | struct CadetTunnelAxolotl *ax; | ||
819 | size_t out_size; | 886 | size_t out_size; |
820 | 887 | ||
821 | ax = &t->ax; | ||
822 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | 888 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, |
823 | &ax->HKs, | 889 | &ax->HKs, |
824 | NULL, 0, | 890 | NULL, 0, |
825 | NULL); | 891 | NULL); |
826 | out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->Ns, | 892 | out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->ax_header, |
827 | AX_HEADER_SIZE, | 893 | sizeof (struct GNUNET_CADET_AxHeader), |
828 | &ax->HKs, | 894 | &ax->HKs, |
829 | &iv, | 895 | &iv, |
830 | &msg->Ns); | 896 | &msg->ax_header); |
831 | GNUNET_assert (AX_HEADER_SIZE == out_size); | 897 | GNUNET_assert (sizeof (struct GNUNET_CADET_AxHeader) == out_size); |
832 | } | 898 | } |
833 | 899 | ||
834 | 900 | ||
835 | /** | 901 | /** |
836 | * Decrypt header with the current axolotl header key. | 902 | * Decrypt header with the current axolotl header key. |
837 | * | 903 | * |
838 | * @param t Tunnel whose current ax HK to use. | 904 | * @param ax key material to use. |
839 | * @param src Message whose header to decrypt. | 905 | * @param src Message whose header to decrypt. |
840 | * @param dst Where to decrypt header to. | 906 | * @param dst Where to decrypt header to. |
841 | */ | 907 | */ |
842 | static void | 908 | static void |
843 | t_h_decrypt (struct CadetTunnel *t, | 909 | t_h_decrypt (struct CadetTunnelAxolotl *ax, |
844 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, | 910 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, |
845 | struct GNUNET_CADET_TunnelEncryptedMessage *dst) | 911 | struct GNUNET_CADET_TunnelEncryptedMessage *dst) |
846 | { | 912 | { |
847 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | 913 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; |
848 | struct CadetTunnelAxolotl *ax; | ||
849 | size_t out_size; | 914 | size_t out_size; |
850 | 915 | ||
851 | ax = &t->ax; | ||
852 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | 916 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, |
853 | &ax->HKr, | 917 | &ax->HKr, |
854 | NULL, 0, | 918 | NULL, 0, |
855 | NULL); | 919 | NULL); |
856 | out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, | 920 | out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns, |
857 | AX_HEADER_SIZE, | 921 | sizeof (struct GNUNET_CADET_AxHeader), |
858 | &ax->HKr, | 922 | &ax->HKr, |
859 | &iv, | 923 | &iv, |
860 | &dst->Ns); | 924 | &dst->ax_header.Ns); |
861 | GNUNET_assert (AX_HEADER_SIZE == out_size); | 925 | GNUNET_assert (sizeof (struct GNUNET_CADET_AxHeader) == out_size); |
862 | } | 926 | } |
863 | 927 | ||
864 | 928 | ||
865 | /** | 929 | /** |
866 | * Delete a key from the list of skipped keys. | 930 | * Delete a key from the list of skipped keys. |
867 | * | 931 | * |
868 | * @param t Tunnel to delete from. | 932 | * @param ax key material to delete @a key from. |
869 | * @param key Key to delete. | 933 | * @param key Key to delete. |
870 | */ | 934 | */ |
871 | static void | 935 | static void |
872 | delete_skipped_key (struct CadetTunnel *t, | 936 | delete_skipped_key (struct CadetTunnelAxolotl *ax, |
873 | struct CadetTunnelSkippedKey *key) | 937 | struct CadetTunnelSkippedKey *key) |
874 | { | 938 | { |
875 | GNUNET_CONTAINER_DLL_remove (t->ax.skipped_head, | 939 | GNUNET_CONTAINER_DLL_remove (ax->skipped_head, |
876 | t->ax.skipped_tail, | 940 | ax->skipped_tail, |
877 | key); | 941 | key); |
878 | GNUNET_free (key); | 942 | GNUNET_free (key); |
879 | t->ax.skipped--; | 943 | ax->skipped--; |
880 | } | 944 | } |
881 | 945 | ||
882 | 946 | ||
@@ -884,14 +948,14 @@ delete_skipped_key (struct CadetTunnel *t, | |||
884 | * Decrypt and verify data with the appropriate tunnel key and verify that the | 948 | * Decrypt and verify data with the appropriate tunnel key and verify that the |
885 | * data has not been altered since it was sent by the remote peer. | 949 | * data has not been altered since it was sent by the remote peer. |
886 | * | 950 | * |
887 | * @param t Tunnel whose key to use. | 951 | * @param ax key material to use. |
888 | * @param dst Destination for the plaintext. | 952 | * @param dst Destination for the plaintext. |
889 | * @param src Source of the message. Can overlap with @c dst. | 953 | * @param src Source of the message. Can overlap with @c dst. |
890 | * @param size Size of the message. | 954 | * @param size Size of the message. |
891 | * @return Size of the decrypted data, -1 if an error was encountered. | 955 | * @return Size of the decrypted data, -1 if an error was encountered. |
892 | */ | 956 | */ |
893 | static ssize_t | 957 | static ssize_t |
894 | try_old_ax_keys (struct CadetTunnel *t, | 958 | try_old_ax_keys (struct CadetTunnelAxolotl *ax, |
895 | void *dst, | 959 | void *dst, |
896 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, | 960 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, |
897 | size_t size) | 961 | size_t size) |
@@ -913,10 +977,10 @@ try_old_ax_keys (struct CadetTunnel *t, | |||
913 | 977 | ||
914 | /* Find a correct Header Key */ | 978 | /* Find a correct Header Key */ |
915 | valid_HK = NULL; | 979 | valid_HK = NULL; |
916 | for (key = t->ax.skipped_head; NULL != key; key = key->next) | 980 | for (key = ax->skipped_head; NULL != key; key = key->next) |
917 | { | 981 | { |
918 | t_hmac (&src->Ns, | 982 | t_hmac (&src->ax_header, |
919 | AX_HEADER_SIZE + esize, | 983 | sizeof (struct GNUNET_CADET_AxHeader) + esize, |
920 | 0, | 984 | 0, |
921 | &key->HK, | 985 | &key->HK, |
922 | hmac); | 986 | hmac); |
@@ -941,15 +1005,15 @@ try_old_ax_keys (struct CadetTunnel *t, | |||
941 | &key->HK, | 1005 | &key->HK, |
942 | NULL, 0, | 1006 | NULL, 0, |
943 | NULL); | 1007 | NULL); |
944 | res = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, | 1008 | res = GNUNET_CRYPTO_symmetric_decrypt (&src->ax_header.Ns, |
945 | AX_HEADER_SIZE, | 1009 | sizeof (struct GNUNET_CADET_AxHeader), |
946 | &key->HK, | 1010 | &key->HK, |
947 | &iv, | 1011 | &iv, |
948 | &plaintext_header.Ns); | 1012 | &plaintext_header.ax_header.Ns); |
949 | GNUNET_assert (AX_HEADER_SIZE == res); | 1013 | GNUNET_assert (sizeof (struct GNUNET_CADET_AxHeader) == res); |
950 | 1014 | ||
951 | /* Find the correct message key */ | 1015 | /* Find the correct message key */ |
952 | N = ntohl (plaintext_header.Ns); | 1016 | N = ntohl (plaintext_header.ax_header.Ns); |
953 | while ( (NULL != key) && | 1017 | while ( (NULL != key) && |
954 | (N != key->Kn) ) | 1018 | (N != key->Kn) ) |
955 | key = key->next; | 1019 | key = key->next; |
@@ -970,7 +1034,7 @@ try_old_ax_keys (struct CadetTunnel *t, | |||
970 | &key->MK, | 1034 | &key->MK, |
971 | &iv, | 1035 | &iv, |
972 | dst); | 1036 | dst); |
973 | delete_skipped_key (t, | 1037 | delete_skipped_key (ax, |
974 | key); | 1038 | key); |
975 | return res; | 1039 | return res; |
976 | } | 1040 | } |
@@ -979,32 +1043,32 @@ try_old_ax_keys (struct CadetTunnel *t, | |||
979 | /** | 1043 | /** |
980 | * Delete a key from the list of skipped keys. | 1044 | * Delete a key from the list of skipped keys. |
981 | * | 1045 | * |
982 | * @param t Tunnel to delete from. | 1046 | * @param ax key material to delete from. |
983 | * @param HKr Header Key to use. | 1047 | * @param HKr Header Key to use. |
984 | */ | 1048 | */ |
985 | static void | 1049 | static void |
986 | store_skipped_key (struct CadetTunnel *t, | 1050 | store_skipped_key (struct CadetTunnelAxolotl *ax, |
987 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr) | 1051 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr) |
988 | { | 1052 | { |
989 | struct CadetTunnelSkippedKey *key; | 1053 | struct CadetTunnelSkippedKey *key; |
990 | 1054 | ||
991 | key = GNUNET_new (struct CadetTunnelSkippedKey); | 1055 | key = GNUNET_new (struct CadetTunnelSkippedKey); |
992 | key->timestamp = GNUNET_TIME_absolute_get (); | 1056 | key->timestamp = GNUNET_TIME_absolute_get (); |
993 | key->Kn = t->ax.Nr; | 1057 | key->Kn = ax->Nr; |
994 | key->HK = t->ax.HKr; | 1058 | key->HK = ax->HKr; |
995 | t_hmac_derive_key (&t->ax.CKr, | 1059 | t_hmac_derive_key (&ax->CKr, |
996 | &key->MK, | 1060 | &key->MK, |
997 | "0", | 1061 | "0", |
998 | 1); | 1062 | 1); |
999 | t_hmac_derive_key (&t->ax.CKr, | 1063 | t_hmac_derive_key (&ax->CKr, |
1000 | &t->ax.CKr, | 1064 | &ax->CKr, |
1001 | "1", | 1065 | "1", |
1002 | 1); | 1066 | 1); |
1003 | GNUNET_CONTAINER_DLL_insert (t->ax.skipped_head, | 1067 | GNUNET_CONTAINER_DLL_insert (ax->skipped_head, |
1004 | t->ax.skipped_tail, | 1068 | ax->skipped_tail, |
1005 | key); | 1069 | key); |
1006 | t->ax.skipped++; | 1070 | ax->skipped++; |
1007 | t->ax.Nr++; | 1071 | ax->Nr++; |
1008 | } | 1072 | } |
1009 | 1073 | ||
1010 | 1074 | ||
@@ -1012,33 +1076,33 @@ store_skipped_key (struct CadetTunnel *t, | |||
1012 | * Stage skipped AX keys and calculate the message key. | 1076 | * Stage skipped AX keys and calculate the message key. |
1013 | * Stores each HK and MK for skipped messages. | 1077 | * Stores each HK and MK for skipped messages. |
1014 | * | 1078 | * |
1015 | * @param t Tunnel where to stage the keys. | 1079 | * @param ax key material to use |
1016 | * @param HKr Header key. | 1080 | * @param HKr Header key. |
1017 | * @param Np Received meesage number. | 1081 | * @param Np Received meesage number. |
1018 | * @return #GNUNET_OK if keys were stored. | 1082 | * @return #GNUNET_OK if keys were stored. |
1019 | * #GNUNET_SYSERR if an error ocurred (Np not expected). | 1083 | * #GNUNET_SYSERR if an error ocurred (@a Np not expected). |
1020 | */ | 1084 | */ |
1021 | static int | 1085 | static int |
1022 | store_ax_keys (struct CadetTunnel *t, | 1086 | store_ax_keys (struct CadetTunnelAxolotl *ax, |
1023 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr, | 1087 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr, |
1024 | uint32_t Np) | 1088 | uint32_t Np) |
1025 | { | 1089 | { |
1026 | int gap; | 1090 | int gap; |
1027 | 1091 | ||
1028 | gap = Np - t->ax.Nr; | 1092 | gap = Np - ax->Nr; |
1029 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1093 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1030 | "Storing skipped keys [%u, %u)\n", | 1094 | "Storing skipped keys [%u, %u)\n", |
1031 | t->ax.Nr, | 1095 | ax->Nr, |
1032 | Np); | 1096 | Np); |
1033 | if (MAX_KEY_GAP < gap) | 1097 | if (MAX_KEY_GAP < gap) |
1034 | { | 1098 | { |
1035 | /* Avoid DoS (forcing peer to do 2^33 chain HMAC operations) */ | 1099 | /* Avoid DoS (forcing peer to do more than #MAX_KEY_GAP HMAC operations) */ |
1036 | /* TODO: start new key exchange on return */ | 1100 | /* TODO: start new key exchange on return */ |
1037 | GNUNET_break_op (0); | 1101 | GNUNET_break_op (0); |
1038 | LOG (GNUNET_ERROR_TYPE_WARNING, | 1102 | LOG (GNUNET_ERROR_TYPE_WARNING, |
1039 | "Got message %u, expected %u+\n", | 1103 | "Got message %u, expected %u+\n", |
1040 | Np, | 1104 | Np, |
1041 | t->ax.Nr); | 1105 | ax->Nr); |
1042 | return GNUNET_SYSERR; | 1106 | return GNUNET_SYSERR; |
1043 | } | 1107 | } |
1044 | if (0 > gap) | 1108 | if (0 > gap) |
@@ -1047,13 +1111,13 @@ store_ax_keys (struct CadetTunnel *t, | |||
1047 | return GNUNET_SYSERR; | 1111 | return GNUNET_SYSERR; |
1048 | } | 1112 | } |
1049 | 1113 | ||
1050 | while (t->ax.Nr < Np) | 1114 | while (ax->Nr < Np) |
1051 | store_skipped_key (t, | 1115 | store_skipped_key (ax, |
1052 | HKr); | 1116 | HKr); |
1053 | 1117 | ||
1054 | while (t->ax.skipped > MAX_SKIPPED_KEYS) | 1118 | while (ax->skipped > MAX_SKIPPED_KEYS) |
1055 | delete_skipped_key (t, | 1119 | delete_skipped_key (ax, |
1056 | t->ax.skipped_tail); | 1120 | ax->skipped_tail); |
1057 | return GNUNET_OK; | 1121 | return GNUNET_OK; |
1058 | } | 1122 | } |
1059 | 1123 | ||
@@ -1062,19 +1126,18 @@ store_ax_keys (struct CadetTunnel *t, | |||
1062 | * Decrypt and verify data with the appropriate tunnel key and verify that the | 1126 | * Decrypt and verify data with the appropriate tunnel key and verify that the |
1063 | * data has not been altered since it was sent by the remote peer. | 1127 | * data has not been altered since it was sent by the remote peer. |
1064 | * | 1128 | * |
1065 | * @param t Tunnel whose key to use. | 1129 | * @param ax key material to use |
1066 | * @param dst Destination for the plaintext. | 1130 | * @param dst Destination for the plaintext. |
1067 | * @param src Source of the message. Can overlap with @c dst. | 1131 | * @param src Source of the message. Can overlap with @c dst. |
1068 | * @param size Size of the message. | 1132 | * @param size Size of the message. |
1069 | * @return Size of the decrypted data, -1 if an error was encountered. | 1133 | * @return Size of the decrypted data, -1 if an error was encountered. |
1070 | */ | 1134 | */ |
1071 | static ssize_t | 1135 | static ssize_t |
1072 | t_ax_decrypt_and_validate (struct CadetTunnel *t, | 1136 | t_ax_decrypt_and_validate (struct CadetTunnelAxolotl *ax, |
1073 | void *dst, | 1137 | void *dst, |
1074 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, | 1138 | const struct GNUNET_CADET_TunnelEncryptedMessage *src, |
1075 | size_t size) | 1139 | size_t size) |
1076 | { | 1140 | { |
1077 | struct CadetTunnelAxolotl *ax; | ||
1078 | struct GNUNET_ShortHashCode msg_hmac; | 1141 | struct GNUNET_ShortHashCode msg_hmac; |
1079 | struct GNUNET_HashCode hmac; | 1142 | struct GNUNET_HashCode hmac; |
1080 | struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header; | 1143 | struct GNUNET_CADET_TunnelEncryptedMessage plaintext_header; |
@@ -1083,11 +1146,10 @@ t_ax_decrypt_and_validate (struct CadetTunnel *t, | |||
1083 | size_t esize; /* Size of encryped payload */ | 1146 | size_t esize; /* Size of encryped payload */ |
1084 | 1147 | ||
1085 | esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage); | 1148 | esize = size - sizeof (struct GNUNET_CADET_TunnelEncryptedMessage); |
1086 | ax = &t->ax; | ||
1087 | 1149 | ||
1088 | /* Try current HK */ | 1150 | /* Try current HK */ |
1089 | t_hmac (&src->Ns, | 1151 | t_hmac (&src->ax_header, |
1090 | AX_HEADER_SIZE + esize, | 1152 | sizeof (struct GNUNET_CADET_AxHeader) + esize, |
1091 | 0, &ax->HKr, | 1153 | 0, &ax->HKr, |
1092 | &msg_hmac); | 1154 | &msg_hmac); |
1093 | if (0 != memcmp (&msg_hmac, | 1155 | if (0 != memcmp (&msg_hmac, |
@@ -1101,8 +1163,8 @@ t_ax_decrypt_and_validate (struct CadetTunnel *t, | |||
1101 | struct GNUNET_CRYPTO_EcdhePublicKey *DHRp; | 1163 | struct GNUNET_CRYPTO_EcdhePublicKey *DHRp; |
1102 | 1164 | ||
1103 | /* Try Next HK */ | 1165 | /* Try Next HK */ |
1104 | t_hmac (&src->Ns, | 1166 | t_hmac (&src->ax_header, |
1105 | AX_HEADER_SIZE + esize, | 1167 | sizeof (struct GNUNET_CADET_AxHeader) + esize, |
1106 | 0, | 1168 | 0, |
1107 | &ax->NHKr, | 1169 | &ax->NHKr, |
1108 | &msg_hmac); | 1170 | &msg_hmac); |
@@ -1111,25 +1173,25 @@ t_ax_decrypt_and_validate (struct CadetTunnel *t, | |||
1111 | sizeof (msg_hmac))) | 1173 | sizeof (msg_hmac))) |
1112 | { | 1174 | { |
1113 | /* Try the skipped keys, if that fails, we're out of luck. */ | 1175 | /* Try the skipped keys, if that fails, we're out of luck. */ |
1114 | return try_old_ax_keys (t, | 1176 | return try_old_ax_keys (ax, |
1115 | dst, | 1177 | dst, |
1116 | src, | 1178 | src, |
1117 | size); | 1179 | size); |
1118 | } | 1180 | } |
1119 | HK = ax->HKr; | 1181 | HK = ax->HKr; |
1120 | ax->HKr = ax->NHKr; | 1182 | ax->HKr = ax->NHKr; |
1121 | t_h_decrypt (t, | 1183 | t_h_decrypt (ax, |
1122 | src, | 1184 | src, |
1123 | &plaintext_header); | 1185 | &plaintext_header); |
1124 | Np = ntohl (plaintext_header.Ns); | 1186 | Np = ntohl (plaintext_header.ax_header.Ns); |
1125 | PNp = ntohl (plaintext_header.PNs); | 1187 | PNp = ntohl (plaintext_header.ax_header.PNs); |
1126 | DHRp = &plaintext_header.DHRs; | 1188 | DHRp = &plaintext_header.ax_header.DHRs; |
1127 | store_ax_keys (t, | 1189 | store_ax_keys (ax, |
1128 | &HK, | 1190 | &HK, |
1129 | PNp); | 1191 | PNp); |
1130 | 1192 | ||
1131 | /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */ | 1193 | /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */ |
1132 | GNUNET_CRYPTO_ecc_ecdh (ax->DHRs, | 1194 | GNUNET_CRYPTO_ecc_ecdh (&ax->DHRs, |
1133 | DHRp, | 1195 | DHRp, |
1134 | &dh); | 1196 | &dh); |
1135 | t_ax_hmac_hash (&ax->RK, | 1197 | t_ax_hmac_hash (&ax->RK, |
@@ -1150,25 +1212,25 @@ t_ax_decrypt_and_validate (struct CadetTunnel *t, | |||
1150 | } | 1212 | } |
1151 | else | 1213 | else |
1152 | { | 1214 | { |
1153 | t_h_decrypt (t, | 1215 | t_h_decrypt (ax, |
1154 | src, | 1216 | src, |
1155 | &plaintext_header); | 1217 | &plaintext_header); |
1156 | Np = ntohl (plaintext_header.Ns); | 1218 | Np = ntohl (plaintext_header.ax_header.Ns); |
1157 | PNp = ntohl (plaintext_header.PNs); | 1219 | PNp = ntohl (plaintext_header.ax_header.PNs); |
1158 | } | 1220 | } |
1159 | if ( (Np != ax->Nr) && | 1221 | if ( (Np != ax->Nr) && |
1160 | (GNUNET_OK != store_ax_keys (t, | 1222 | (GNUNET_OK != store_ax_keys (ax, |
1161 | &ax->HKr, | 1223 | &ax->HKr, |
1162 | Np)) ) | 1224 | Np)) ) |
1163 | { | 1225 | { |
1164 | /* Try the skipped keys, if that fails, we're out of luck. */ | 1226 | /* Try the skipped keys, if that fails, we're out of luck. */ |
1165 | return try_old_ax_keys (t, | 1227 | return try_old_ax_keys (ax, |
1166 | dst, | 1228 | dst, |
1167 | src, | 1229 | src, |
1168 | size); | 1230 | size); |
1169 | } | 1231 | } |
1170 | 1232 | ||
1171 | t_ax_decrypt (t, | 1233 | t_ax_decrypt (ax, |
1172 | dst, | 1234 | dst, |
1173 | &src[1], | 1235 | &src[1], |
1174 | esize); | 1236 | esize); |
@@ -1213,10 +1275,10 @@ GCT_change_estate (struct CadetTunnel *t, | |||
1213 | 1275 | ||
1214 | t->estate = state; | 1276 | t->estate = state; |
1215 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1277 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1216 | "Tunnel %s estate changed from %d to %d\n", | 1278 | "%s estate changed from %s to %s\n", |
1217 | GCT_2s (t), | 1279 | GCT_2s (t), |
1218 | old, | 1280 | estate2s (old), |
1219 | state); | 1281 | estate2s (state)); |
1220 | 1282 | ||
1221 | if ( (CADET_TUNNEL_KEY_OK != old) && | 1283 | if ( (CADET_TUNNEL_KEY_OK != old) && |
1222 | (CADET_TUNNEL_KEY_OK == t->estate) ) | 1284 | (CADET_TUNNEL_KEY_OK == t->estate) ) |
@@ -1226,15 +1288,14 @@ GCT_change_estate (struct CadetTunnel *t, | |||
1226 | GNUNET_SCHEDULER_cancel (t->kx_task); | 1288 | GNUNET_SCHEDULER_cancel (t->kx_task); |
1227 | t->kx_task = NULL; | 1289 | t->kx_task = NULL; |
1228 | } | 1290 | } |
1229 | if (CADET_TUNNEL_KEY_REKEY != old) | 1291 | /* notify all channels that have been waiting */ |
1230 | { | 1292 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, |
1231 | /* notify all channels that have been waiting */ | 1293 | ¬ify_tunnel_up_cb, |
1232 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, | 1294 | t); |
1233 | ¬ify_tunnel_up_cb, | 1295 | if (NULL != t->send_task) |
1234 | t); | 1296 | GNUNET_SCHEDULER_cancel (t->send_task); |
1235 | } | 1297 | t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions, |
1236 | 1298 | t); | |
1237 | /* FIXME: schedule rekey task! */ | ||
1238 | } | 1299 | } |
1239 | } | 1300 | } |
1240 | 1301 | ||
@@ -1242,80 +1303,179 @@ GCT_change_estate (struct CadetTunnel *t, | |||
1242 | /** | 1303 | /** |
1243 | * Send a KX message. | 1304 | * Send a KX message. |
1244 | * | 1305 | * |
1245 | * FIXME: does not take care of sender-authentication yet! | 1306 | * @param t tunnel on which to send the KX_AUTH |
1246 | * | 1307 | * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if |
1247 | * @param t Tunnel on which to send it. | 1308 | * we are to find one that is ready. |
1248 | * @param force_reply Force the other peer to reply with a KX message. | 1309 | * @param ax axolotl key context to use |
1249 | */ | 1310 | */ |
1250 | static void | 1311 | static void |
1251 | send_kx (struct CadetTunnel *t, | 1312 | send_kx (struct CadetTunnel *t, |
1252 | int force_reply) | 1313 | struct CadetTConnection *ct, |
1314 | struct CadetTunnelAxolotl *ax) | ||
1253 | { | 1315 | { |
1254 | struct CadetTunnelAxolotl *ax = &t->ax; | ||
1255 | struct CadetTConnection *ct; | ||
1256 | struct CadetConnection *cc; | 1316 | struct CadetConnection *cc; |
1257 | struct GNUNET_MQ_Envelope *env; | 1317 | struct GNUNET_MQ_Envelope *env; |
1258 | struct GNUNET_CADET_TunnelKeyExchangeMessage *msg; | 1318 | struct GNUNET_CADET_TunnelKeyExchangeMessage *msg; |
1259 | enum GNUNET_CADET_KX_Flags flags; | 1319 | enum GNUNET_CADET_KX_Flags flags; |
1260 | 1320 | ||
1261 | ct = get_ready_connection (t); | 1321 | if ( (NULL == ct) || |
1322 | (GNUNET_NO == ct->is_ready) ) | ||
1323 | ct = get_ready_connection (t); | ||
1262 | if (NULL == ct) | 1324 | if (NULL == ct) |
1263 | { | 1325 | { |
1264 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1326 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1265 | "Wanted to send KX on tunnel %s, but no connection is ready, deferring\n", | 1327 | "Wanted to send %s in state %s, but no connection is ready, deferring\n", |
1266 | GCT_2s (t)); | 1328 | GCT_2s (t), |
1329 | estate2s (t->estate)); | ||
1330 | t->next_kx_attempt = GNUNET_TIME_absolute_get (); | ||
1267 | return; | 1331 | return; |
1268 | } | 1332 | } |
1269 | cc = ct->cc; | 1333 | cc = ct->cc; |
1270 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1334 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1271 | "Sending KX on tunnel %s using connection %s\n", | 1335 | "Sending KX on %s via %s in state %s\n", |
1272 | GCT_2s (t), | 1336 | GCT_2s (t), |
1273 | GCC_2s (ct->cc)); | 1337 | GCC_2s (cc), |
1274 | 1338 | estate2s (t->estate)); | |
1275 | // GNUNET_assert (GNUNET_NO == GCT_is_loopback (t)); | ||
1276 | env = GNUNET_MQ_msg (msg, | 1339 | env = GNUNET_MQ_msg (msg, |
1277 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX); | 1340 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX); |
1278 | flags = GNUNET_CADET_KX_FLAG_NONE; | 1341 | flags = GNUNET_CADET_KX_FLAG_FORCE_REPLY; /* always for KX */ |
1279 | if (GNUNET_YES == force_reply) | ||
1280 | flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY; | ||
1281 | msg->flags = htonl (flags); | 1342 | msg->flags = htonl (flags); |
1282 | msg->cid = *GCC_get_id (cc); | 1343 | msg->cid = *GCC_get_id (cc); |
1283 | GNUNET_CRYPTO_ecdhe_key_get_public (ax->kx_0, | 1344 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0, |
1284 | &msg->ephemeral_key); | 1345 | &msg->ephemeral_key); |
1285 | GNUNET_CRYPTO_ecdhe_key_get_public (ax->DHRs, | 1346 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs, |
1286 | &msg->ratchet_key); | 1347 | &msg->ratchet_key); |
1287 | ct->is_ready = GNUNET_NO; | 1348 | mark_connection_unready (ct); |
1288 | GCC_transmit (cc, | ||
1289 | env); | ||
1290 | t->kx_retry_delay = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay); | 1349 | t->kx_retry_delay = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay); |
1291 | t->next_kx_attempt = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay); | 1350 | t->next_kx_attempt = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay); |
1292 | if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) | 1351 | if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) |
1293 | GCT_change_estate (t, | 1352 | GCT_change_estate (t, |
1294 | CADET_TUNNEL_KEY_SENT); | 1353 | CADET_TUNNEL_KEY_AX_SENT); |
1354 | else if (CADET_TUNNEL_KEY_AX_RECV == t->estate) | ||
1355 | GCT_change_estate (t, | ||
1356 | CADET_TUNNEL_KEY_AX_SENT_AND_RECV); | ||
1357 | GCC_transmit (cc, | ||
1358 | env); | ||
1359 | } | ||
1360 | |||
1361 | |||
1362 | /** | ||
1363 | * Send a KX_AUTH message. | ||
1364 | * | ||
1365 | * @param t tunnel on which to send the KX_AUTH | ||
1366 | * @param ct Tunnel and connection on which to send the KX_AUTH, NULL if | ||
1367 | * we are to find one that is ready. | ||
1368 | * @param ax axolotl key context to use | ||
1369 | * @param force_reply Force the other peer to reply with a KX_AUTH message | ||
1370 | * (set if we would like to transmit right now, but cannot) | ||
1371 | */ | ||
1372 | static void | ||
1373 | send_kx_auth (struct CadetTunnel *t, | ||
1374 | struct CadetTConnection *ct, | ||
1375 | struct CadetTunnelAxolotl *ax, | ||
1376 | int force_reply) | ||
1377 | { | ||
1378 | struct CadetConnection *cc; | ||
1379 | struct GNUNET_MQ_Envelope *env; | ||
1380 | struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg; | ||
1381 | enum GNUNET_CADET_KX_Flags flags; | ||
1382 | |||
1383 | if ( (NULL == ct) || | ||
1384 | (GNUNET_NO == ct->is_ready) ) | ||
1385 | ct = get_ready_connection (t); | ||
1386 | if (NULL == ct) | ||
1387 | { | ||
1388 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1389 | "Wanted to send KX_AUTH on %s, but no connection is ready, deferring\n", | ||
1390 | GCT_2s (t)); | ||
1391 | t->next_kx_attempt = GNUNET_TIME_absolute_get (); | ||
1392 | t->kx_auth_requested = GNUNET_YES; /* queue KX_AUTH independent of estate */ | ||
1393 | return; | ||
1394 | } | ||
1395 | t->kx_auth_requested = GNUNET_NO; /* clear flag */ | ||
1396 | cc = ct->cc; | ||
1397 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1398 | "Sending KX_AUTH on %s using %s\n", | ||
1399 | GCT_2s (t), | ||
1400 | GCC_2s (ct->cc)); | ||
1401 | |||
1402 | env = GNUNET_MQ_msg (msg, | ||
1403 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_KX_AUTH); | ||
1404 | flags = GNUNET_CADET_KX_FLAG_NONE; | ||
1405 | if (GNUNET_YES == force_reply) | ||
1406 | flags |= GNUNET_CADET_KX_FLAG_FORCE_REPLY; | ||
1407 | msg->kx.flags = htonl (flags); | ||
1408 | msg->kx.cid = *GCC_get_id (cc); | ||
1409 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->kx_0, | ||
1410 | &msg->kx.ephemeral_key); | ||
1411 | GNUNET_CRYPTO_ecdhe_key_get_public (&ax->DHRs, | ||
1412 | &msg->kx.ratchet_key); | ||
1413 | /* Compute authenticator (this is the main difference to #send_kx()) */ | ||
1414 | GNUNET_CRYPTO_hash (&ax->RK, | ||
1415 | sizeof (ax->RK), | ||
1416 | &msg->auth); | ||
1417 | |||
1418 | /* Compute when to be triggered again; actual job will | ||
1419 | be scheduled via #connection_ready_cb() */ | ||
1420 | t->kx_retry_delay | ||
1421 | = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay); | ||
1422 | t->next_kx_attempt | ||
1423 | = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay); | ||
1424 | |||
1425 | /* Send via cc, mark it as unready */ | ||
1426 | mark_connection_unready (ct); | ||
1427 | |||
1428 | /* Update state machine, unless we are already OK */ | ||
1429 | if (CADET_TUNNEL_KEY_OK != t->estate) | ||
1430 | GCT_change_estate (t, | ||
1431 | CADET_TUNNEL_KEY_AX_AUTH_SENT); | ||
1432 | |||
1433 | GCC_transmit (cc, | ||
1434 | env); | ||
1295 | } | 1435 | } |
1296 | 1436 | ||
1297 | 1437 | ||
1298 | /** | 1438 | /** |
1299 | * Handle KX message. | 1439 | * Cleanup state used by @a ax. |
1300 | * | 1440 | * |
1301 | * FIXME: sender-authentication in KX is missing! | 1441 | * @param ax state to free, but not memory of @a ax itself |
1442 | */ | ||
1443 | static void | ||
1444 | cleanup_ax (struct CadetTunnelAxolotl *ax) | ||
1445 | { | ||
1446 | while (NULL != ax->skipped_head) | ||
1447 | delete_skipped_key (ax, | ||
1448 | ax->skipped_head); | ||
1449 | GNUNET_assert (0 == ax->skipped); | ||
1450 | GNUNET_CRYPTO_ecdhe_key_clear (&ax->kx_0); | ||
1451 | GNUNET_CRYPTO_ecdhe_key_clear (&ax->DHRs); | ||
1452 | } | ||
1453 | |||
1454 | |||
1455 | /** | ||
1456 | * Update our Axolotl key state based on the KX data we received. | ||
1457 | * Computes the new chain keys, and root keys, etc, and also checks | ||
1458 | * wether this is a replay of the current chain. | ||
1302 | * | 1459 | * |
1303 | * @param ct connection/tunnel combo that received encrypted message | 1460 | * @param[in|out] axolotl chain key state to recompute |
1304 | * @param msg the key exchange message | 1461 | * @param pid peer identity of the other peer |
1462 | * @param ephemeral_key ephemeral public key of the other peer | ||
1463 | * @param ratchet_key senders next ephemeral public key | ||
1464 | * @return #GNUNET_OK on success, #GNUNET_NO if the resulting | ||
1465 | * root key is already in @a ax and thus the KX is useless; | ||
1466 | * #GNUNET_SYSERR on hard errors (i.e. @a pid is #my_full_id) | ||
1305 | */ | 1467 | */ |
1306 | void | 1468 | static int |
1307 | GCT_handle_kx (struct CadetTConnection *ct, | 1469 | update_ax_by_kx (struct CadetTunnelAxolotl *ax, |
1308 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | 1470 | const struct GNUNET_PeerIdentity *pid, |
1471 | const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key, | ||
1472 | const struct GNUNET_CRYPTO_EcdhePublicKey *ratchet_key) | ||
1309 | { | 1473 | { |
1310 | struct CadetTunnel *t = ct->t; | ||
1311 | struct CadetTunnelAxolotl *ax = &t->ax; | ||
1312 | struct GNUNET_HashCode key_material[3]; | 1474 | struct GNUNET_HashCode key_material[3]; |
1313 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[5]; | 1475 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[5]; |
1314 | const char salt[] = "CADET Axolotl salt"; | 1476 | const char salt[] = "CADET Axolotl salt"; |
1315 | const struct GNUNET_PeerIdentity *pid; | ||
1316 | int am_I_alice; | 1477 | int am_I_alice; |
1317 | 1478 | ||
1318 | pid = GCP_get_id (t->destination); | ||
1319 | if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, | 1479 | if (0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, |
1320 | pid)) | 1480 | pid)) |
1321 | am_I_alice = GNUNET_YES; | 1481 | am_I_alice = GNUNET_YES; |
@@ -1325,41 +1485,30 @@ GCT_handle_kx (struct CadetTConnection *ct, | |||
1325 | else | 1485 | else |
1326 | { | 1486 | { |
1327 | GNUNET_break_op (0); | 1487 | GNUNET_break_op (0); |
1328 | return; | 1488 | return GNUNET_SYSERR; |
1329 | } | ||
1330 | |||
1331 | if (0 != (GNUNET_CADET_KX_FLAG_FORCE_REPLY & ntohl (msg->flags))) | ||
1332 | { | ||
1333 | if (NULL != t->kx_task) | ||
1334 | { | ||
1335 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
1336 | t->kx_task = NULL; | ||
1337 | } | ||
1338 | send_kx (t, | ||
1339 | GNUNET_NO); | ||
1340 | } | 1489 | } |
1341 | 1490 | ||
1342 | if (0 == memcmp (&ax->DHRr, | 1491 | if (0 == memcmp (&ax->DHRr, |
1343 | &msg->ratchet_key, | 1492 | ratchet_key, |
1344 | sizeof (msg->ratchet_key))) | 1493 | sizeof (*ratchet_key))) |
1345 | { | 1494 | { |
1346 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1495 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1347 | " known ratchet key, exit\n"); | 1496 | "Ratchet key already known. Ignoring KX.\n"); |
1348 | return; | 1497 | return GNUNET_NO; |
1349 | } | 1498 | } |
1350 | 1499 | ||
1351 | ax->DHRr = msg->ratchet_key; | 1500 | ax->DHRr = *ratchet_key; |
1352 | 1501 | ||
1353 | /* ECDH A B0 */ | 1502 | /* ECDH A B0 */ |
1354 | if (GNUNET_YES == am_I_alice) | 1503 | if (GNUNET_YES == am_I_alice) |
1355 | { | 1504 | { |
1356 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* A */ | 1505 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* A */ |
1357 | &msg->ephemeral_key, /* B0 */ | 1506 | ephemeral_key, /* B0 */ |
1358 | &key_material[0]); | 1507 | &key_material[0]); |
1359 | } | 1508 | } |
1360 | else | 1509 | else |
1361 | { | 1510 | { |
1362 | GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* B0 */ | 1511 | GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* B0 */ |
1363 | &pid->public_key, /* A */ | 1512 | &pid->public_key, /* A */ |
1364 | &key_material[0]); | 1513 | &key_material[0]); |
1365 | } | 1514 | } |
@@ -1367,14 +1516,14 @@ GCT_handle_kx (struct CadetTConnection *ct, | |||
1367 | /* ECDH A0 B */ | 1516 | /* ECDH A0 B */ |
1368 | if (GNUNET_YES == am_I_alice) | 1517 | if (GNUNET_YES == am_I_alice) |
1369 | { | 1518 | { |
1370 | GNUNET_CRYPTO_ecdh_eddsa (ax->kx_0, /* A0 */ | 1519 | GNUNET_CRYPTO_ecdh_eddsa (&ax->kx_0, /* A0 */ |
1371 | &pid->public_key, /* B */ | 1520 | &pid->public_key, /* B */ |
1372 | &key_material[1]); | 1521 | &key_material[1]); |
1373 | } | 1522 | } |
1374 | else | 1523 | else |
1375 | { | 1524 | { |
1376 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* A */ | 1525 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, /* A */ |
1377 | &msg->ephemeral_key, /* B0 */ | 1526 | ephemeral_key, /* B0 */ |
1378 | &key_material[1]); | 1527 | &key_material[1]); |
1379 | 1528 | ||
1380 | 1529 | ||
@@ -1383,8 +1532,8 @@ GCT_handle_kx (struct CadetTConnection *ct, | |||
1383 | /* ECDH A0 B0 */ | 1532 | /* ECDH A0 B0 */ |
1384 | /* (This is the triple-DH, we could probably safely skip this, | 1533 | /* (This is the triple-DH, we could probably safely skip this, |
1385 | as A0/B0 are already in the key material.) */ | 1534 | as A0/B0 are already in the key material.) */ |
1386 | GNUNET_CRYPTO_ecc_ecdh (ax->kx_0, /* A0 or B0 */ | 1535 | GNUNET_CRYPTO_ecc_ecdh (&ax->kx_0, /* A0 or B0 */ |
1387 | &msg->ephemeral_key, /* B0 or A0 */ | 1536 | ephemeral_key, /* B0 or A0 */ |
1388 | &key_material[2]); | 1537 | &key_material[2]); |
1389 | 1538 | ||
1390 | /* KDF */ | 1539 | /* KDF */ |
@@ -1397,13 +1546,10 @@ GCT_handle_kx (struct CadetTConnection *ct, | |||
1397 | &keys[0], | 1546 | &keys[0], |
1398 | sizeof (ax->RK))) | 1547 | sizeof (ax->RK))) |
1399 | { | 1548 | { |
1400 | LOG (GNUNET_ERROR_TYPE_INFO, | 1549 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1401 | " known handshake key, exit\n"); | 1550 | "Root key of handshake already known. Ignoring KX.\n"); |
1402 | return; | 1551 | return GNUNET_NO; |
1403 | } | 1552 | } |
1404 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1405 | "Handling KX message for tunnel %s\n", | ||
1406 | GCT_2s (t)); | ||
1407 | 1553 | ||
1408 | ax->RK = keys[0]; | 1554 | ax->RK = keys[0]; |
1409 | if (GNUNET_YES == am_I_alice) | 1555 | if (GNUNET_YES == am_I_alice) |
@@ -1421,45 +1567,305 @@ GCT_handle_kx (struct CadetTConnection *ct, | |||
1421 | ax->NHKs = keys[3]; | 1567 | ax->NHKs = keys[3]; |
1422 | ax->CKs = keys[4]; | 1568 | ax->CKs = keys[4]; |
1423 | ax->ratchet_flag = GNUNET_NO; | 1569 | ax->ratchet_flag = GNUNET_NO; |
1424 | ax->ratchet_allowed = GNUNET_NO; | ||
1425 | ax->ratchet_counter = 0; | ||
1426 | ax->ratchet_expiration | 1570 | ax->ratchet_expiration |
1427 | = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), | 1571 | = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), |
1428 | ratchet_time); | 1572 | ratchet_time); |
1429 | } | 1573 | } |
1430 | ax->PNs = 0; | 1574 | return GNUNET_OK; |
1431 | ax->Nr = 0; | 1575 | } |
1432 | ax->Ns = 0; | ||
1433 | 1576 | ||
1577 | |||
1578 | /** | ||
1579 | * Try to redo the KX or KX_AUTH handshake, if we can. | ||
1580 | * | ||
1581 | * @param cls the `struct CadetTunnel` to do KX for. | ||
1582 | */ | ||
1583 | static void | ||
1584 | retry_kx (void *cls) | ||
1585 | { | ||
1586 | struct CadetTunnel *t = cls; | ||
1587 | struct CadetTunnelAxolotl *ax; | ||
1588 | |||
1589 | t->kx_task = NULL; | ||
1590 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1591 | "Trying to make KX progress on %s in state %s\n", | ||
1592 | GCT_2s (t), | ||
1593 | estate2s (t->estate)); | ||
1434 | switch (t->estate) | 1594 | switch (t->estate) |
1435 | { | 1595 | { |
1436 | case CADET_TUNNEL_KEY_UNINITIALIZED: | 1596 | case CADET_TUNNEL_KEY_UNINITIALIZED: /* first attempt */ |
1597 | case CADET_TUNNEL_KEY_AX_SENT: /* trying again */ | ||
1598 | send_kx (t, | ||
1599 | NULL, | ||
1600 | &t->ax); | ||
1601 | break; | ||
1602 | case CADET_TUNNEL_KEY_AX_RECV: | ||
1603 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
1604 | /* We are responding, so only require reply | ||
1605 | if WE have a channel waiting. */ | ||
1606 | if (NULL != t->unverified_ax) | ||
1607 | { | ||
1608 | /* Send AX_AUTH so we might get this one verified */ | ||
1609 | ax = t->unverified_ax; | ||
1610 | } | ||
1611 | else | ||
1612 | { | ||
1613 | /* How can this be? */ | ||
1614 | GNUNET_break (0); | ||
1615 | ax = &t->ax; | ||
1616 | } | ||
1617 | send_kx_auth (t, | ||
1618 | NULL, | ||
1619 | ax, | ||
1620 | (0 == GCT_count_channels (t)) | ||
1621 | ? GNUNET_NO | ||
1622 | : GNUNET_YES); | ||
1623 | break; | ||
1624 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
1625 | /* We are responding, so only require reply | ||
1626 | if WE have a channel waiting. */ | ||
1627 | if (NULL != t->unverified_ax) | ||
1628 | { | ||
1629 | /* Send AX_AUTH so we might get this one verified */ | ||
1630 | ax = t->unverified_ax; | ||
1631 | } | ||
1632 | else | ||
1633 | { | ||
1634 | /* How can this be? */ | ||
1635 | GNUNET_break (0); | ||
1636 | ax = &t->ax; | ||
1637 | } | ||
1638 | send_kx_auth (t, | ||
1639 | NULL, | ||
1640 | ax, | ||
1641 | (0 == GCT_count_channels (t)) | ||
1642 | ? GNUNET_NO | ||
1643 | : GNUNET_YES); | ||
1644 | break; | ||
1645 | case CADET_TUNNEL_KEY_OK: | ||
1646 | /* Must have been the *other* peer asking us to | ||
1647 | respond with a KX_AUTH. */ | ||
1648 | if (NULL != t->unverified_ax) | ||
1649 | { | ||
1650 | /* Sending AX_AUTH in response to AX so we might get this one verified */ | ||
1651 | ax = t->unverified_ax; | ||
1652 | } | ||
1653 | else | ||
1654 | { | ||
1655 | /* Sending AX_AUTH in response to AX_AUTH */ | ||
1656 | ax = &t->ax; | ||
1657 | } | ||
1658 | send_kx_auth (t, | ||
1659 | NULL, | ||
1660 | ax, | ||
1661 | GNUNET_NO); | ||
1662 | break; | ||
1663 | } | ||
1664 | } | ||
1665 | |||
1666 | |||
1667 | /** | ||
1668 | * Handle KX message that lacks authentication (and which will thus | ||
1669 | * only be considered authenticated after we respond with our own | ||
1670 | * KX_AUTH and finally successfully decrypt payload). | ||
1671 | * | ||
1672 | * @param ct connection/tunnel combo that received encrypted message | ||
1673 | * @param msg the key exchange message | ||
1674 | */ | ||
1675 | void | ||
1676 | GCT_handle_kx (struct CadetTConnection *ct, | ||
1677 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | ||
1678 | { | ||
1679 | struct CadetTunnel *t = ct->t; | ||
1680 | struct CadetTunnelAxolotl *ax; | ||
1681 | int ret; | ||
1682 | |||
1683 | if (0 == | ||
1684 | memcmp (&t->ax.DHRr, | ||
1685 | &msg->ratchet_key, | ||
1686 | sizeof (msg->ratchet_key))) | ||
1687 | { | ||
1688 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1689 | "Got duplicate KX. Firing back KX_AUTH.\n"); | ||
1690 | send_kx_auth (t, | ||
1691 | ct, | ||
1692 | &t->ax, | ||
1693 | GNUNET_NO); | ||
1694 | return; | ||
1695 | } | ||
1696 | |||
1697 | /* We only keep ONE unverified KX around, so if there is an existing one, | ||
1698 | clean it up. */ | ||
1699 | if (NULL != t->unverified_ax) | ||
1700 | { | ||
1701 | if (0 == | ||
1702 | memcmp (&t->unverified_ax->DHRr, | ||
1703 | &msg->ratchet_key, | ||
1704 | sizeof (msg->ratchet_key))) | ||
1705 | { | ||
1706 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1707 | "Got duplicate unverified KX on %s. Fire back KX_AUTH again.\n", | ||
1708 | GCT_2s (t)); | ||
1709 | send_kx_auth (t, | ||
1710 | ct, | ||
1711 | t->unverified_ax, | ||
1712 | GNUNET_NO); | ||
1713 | return; | ||
1714 | } | ||
1715 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1716 | "Dropping old unverified KX state. Got a fresh KX for %s.\n", | ||
1717 | GCT_2s (t)); | ||
1718 | memset (t->unverified_ax, | ||
1719 | 0, | ||
1720 | sizeof (struct CadetTunnelAxolotl)); | ||
1721 | t->unverified_ax->DHRs = t->ax.DHRs; | ||
1722 | t->unverified_ax->kx_0 = t->ax.kx_0; | ||
1723 | } | ||
1724 | else | ||
1725 | { | ||
1726 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1727 | "Creating fresh unverified KX for %s.\n", | ||
1728 | GCT_2s (t)); | ||
1729 | t->unverified_ax = GNUNET_new (struct CadetTunnelAxolotl); | ||
1730 | t->unverified_ax->DHRs = t->ax.DHRs; | ||
1731 | t->unverified_ax->kx_0 = t->ax.kx_0; | ||
1732 | } | ||
1733 | /* Set as the 'current' RK/DHRr the one we are currently using, | ||
1734 | so that the duplicate-detection logic of | ||
1735 | #update_ax_by_kx can work. */ | ||
1736 | t->unverified_ax->RK = t->ax.RK; | ||
1737 | t->unverified_ax->DHRr = t->ax.DHRr; | ||
1738 | t->unverified_attempts = 0; | ||
1739 | ax = t->unverified_ax; | ||
1740 | |||
1741 | /* Update 'ax' by the new key material */ | ||
1742 | ret = update_ax_by_kx (ax, | ||
1743 | GCP_get_id (t->destination), | ||
1744 | &msg->ephemeral_key, | ||
1745 | &msg->ratchet_key); | ||
1746 | GNUNET_break (GNUNET_SYSERR != ret); | ||
1747 | if (GNUNET_OK != ret) | ||
1748 | return; /* duplicate KX, nothing to do */ | ||
1749 | |||
1750 | /* move ahead in our state machine */ | ||
1751 | if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) | ||
1752 | GCT_change_estate (t, | ||
1753 | CADET_TUNNEL_KEY_AX_RECV); | ||
1754 | else if (CADET_TUNNEL_KEY_AX_SENT == t->estate) | ||
1437 | GCT_change_estate (t, | 1755 | GCT_change_estate (t, |
1438 | CADET_TUNNEL_KEY_PING); | 1756 | CADET_TUNNEL_KEY_AX_SENT_AND_RECV); |
1757 | |||
1758 | /* KX is still not done, try again our end. */ | ||
1759 | if (CADET_TUNNEL_KEY_OK != t->estate) | ||
1760 | { | ||
1761 | if (NULL != t->kx_task) | ||
1762 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
1763 | t->kx_task | ||
1764 | = GNUNET_SCHEDULER_add_now (&retry_kx, | ||
1765 | t); | ||
1766 | } | ||
1767 | } | ||
1768 | |||
1769 | |||
1770 | /** | ||
1771 | * Handle KX_AUTH message. | ||
1772 | * | ||
1773 | * @param ct connection/tunnel combo that received encrypted message | ||
1774 | * @param msg the key exchange message | ||
1775 | */ | ||
1776 | void | ||
1777 | GCT_handle_kx_auth (struct CadetTConnection *ct, | ||
1778 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) | ||
1779 | { | ||
1780 | struct CadetTunnel *t = ct->t; | ||
1781 | struct CadetTunnelAxolotl ax_tmp; | ||
1782 | struct GNUNET_HashCode kx_auth; | ||
1783 | int ret; | ||
1784 | |||
1785 | if ( (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) || | ||
1786 | (CADET_TUNNEL_KEY_AX_RECV == t->estate) ) | ||
1787 | { | ||
1788 | /* Confusing, we got a KX_AUTH before we even send our own | ||
1789 | KX. This should not happen. We'll send our own KX ASAP anyway, | ||
1790 | so let's ignore this here. */ | ||
1791 | GNUNET_break_op (0); | ||
1792 | return; | ||
1793 | } | ||
1794 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1795 | "Handling KX_AUTH message for %s\n", | ||
1796 | GCT_2s (t)); | ||
1797 | |||
1798 | /* We do everything in ax_tmp until we've checked the authentication | ||
1799 | so we don't clobber anything we care about by accident. */ | ||
1800 | ax_tmp = t->ax; | ||
1801 | |||
1802 | /* Update 'ax' by the new key material */ | ||
1803 | ret = update_ax_by_kx (&ax_tmp, | ||
1804 | GCP_get_id (t->destination), | ||
1805 | &msg->kx.ephemeral_key, | ||
1806 | &msg->kx.ratchet_key); | ||
1807 | if (GNUNET_OK != ret) | ||
1808 | { | ||
1809 | if (GNUNET_NO == ret) | ||
1810 | GNUNET_STATISTICS_update (stats, | ||
1811 | "# redundant KX_AUTH received", | ||
1812 | 1, | ||
1813 | GNUNET_NO); | ||
1814 | else | ||
1815 | GNUNET_break (0); /* connect to self!? */ | ||
1816 | return; | ||
1817 | } | ||
1818 | GNUNET_CRYPTO_hash (&ax_tmp.RK, | ||
1819 | sizeof (ax_tmp.RK), | ||
1820 | &kx_auth); | ||
1821 | if (0 != memcmp (&kx_auth, | ||
1822 | &msg->auth, | ||
1823 | sizeof (kx_auth))) | ||
1824 | { | ||
1825 | /* This KX_AUTH is not using the latest KX/KX_AUTH data | ||
1826 | we transmitted to the sender, refuse it, try KX again. */ | ||
1827 | GNUNET_STATISTICS_update (stats, | ||
1828 | "# KX_AUTH not using our last KX received (auth failure)", | ||
1829 | 1, | ||
1830 | GNUNET_NO); | ||
1831 | send_kx (t, | ||
1832 | ct, | ||
1833 | &t->ax); | ||
1834 | return; | ||
1835 | } | ||
1836 | /* Yep, we're good. */ | ||
1837 | t->ax = ax_tmp; | ||
1838 | if (NULL != t->unverified_ax) | ||
1839 | { | ||
1840 | /* We got some "stale" KX before, drop that. */ | ||
1841 | cleanup_ax (t->unverified_ax); | ||
1842 | GNUNET_free (t->unverified_ax); | ||
1843 | t->unverified_ax = NULL; | ||
1844 | } | ||
1845 | |||
1846 | /* move ahead in our state machine */ | ||
1847 | switch (t->estate) | ||
1848 | { | ||
1849 | case CADET_TUNNEL_KEY_UNINITIALIZED: | ||
1850 | case CADET_TUNNEL_KEY_AX_RECV: | ||
1851 | /* Checked above, this is impossible. */ | ||
1852 | GNUNET_assert (0); | ||
1439 | break; | 1853 | break; |
1440 | case CADET_TUNNEL_KEY_SENT: | 1854 | case CADET_TUNNEL_KEY_AX_SENT: /* This is the normal case */ |
1441 | /* Got a response to us sending our key; now | 1855 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: /* both peers started KX */ |
1442 | we can start transmitting! */ | 1856 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: /* both peers now did KX_AUTH */ |
1443 | GCT_change_estate (t, | 1857 | GCT_change_estate (t, |
1444 | CADET_TUNNEL_KEY_OK); | 1858 | CADET_TUNNEL_KEY_OK); |
1445 | if (NULL != t->send_task) | ||
1446 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
1447 | t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions, | ||
1448 | t); | ||
1449 | break; | ||
1450 | case CADET_TUNNEL_KEY_PING: | ||
1451 | /* Got a key yet again; need encrypted payload to advance */ | ||
1452 | break; | 1859 | break; |
1453 | case CADET_TUNNEL_KEY_OK: | 1860 | case CADET_TUNNEL_KEY_OK: |
1454 | /* Did not expect a key, but so what. */ | 1861 | /* Did not expect another KX_AUTH, but so what, still acceptable. |
1455 | break; | 1862 | Nothing to do here. */ |
1456 | case CADET_TUNNEL_KEY_REKEY: | ||
1457 | /* Got a key yet again; need encrypted payload to advance */ | ||
1458 | break; | 1863 | break; |
1459 | } | 1864 | } |
1460 | } | 1865 | } |
1461 | 1866 | ||
1462 | 1867 | ||
1868 | |||
1463 | /* ************************************** end core crypto ***************************** */ | 1869 | /* ************************************** end core crypto ***************************** */ |
1464 | 1870 | ||
1465 | 1871 | ||
@@ -1489,12 +1895,12 @@ get_next_free_ctn (struct CadetTunnel *t) | |||
1489 | ctn = ntohl (t->next_ctn.cn); | 1895 | ctn = ntohl (t->next_ctn.cn); |
1490 | while (NULL != | 1896 | while (NULL != |
1491 | GNUNET_CONTAINER_multihashmap32_get (t->channels, | 1897 | GNUNET_CONTAINER_multihashmap32_get (t->channels, |
1492 | ctn)) | 1898 | ctn | highbit)) |
1493 | { | 1899 | { |
1494 | ctn = ((ctn + 1) & (~ HIGH_BIT)) | highbit; | 1900 | ctn = ((ctn + 1) & (~ HIGH_BIT)); |
1495 | } | 1901 | } |
1496 | t->next_ctn.cn = htonl (((ctn + 1) & (~ HIGH_BIT)) | highbit); | 1902 | t->next_ctn.cn = htonl ((ctn + 1) & (~ HIGH_BIT)); |
1497 | ret.cn = ntohl (ctn); | 1903 | ret.cn = htonl (ctn | highbit); |
1498 | return ret; | 1904 | return ret; |
1499 | } | 1905 | } |
1500 | 1906 | ||
@@ -1515,23 +1921,97 @@ GCT_add_channel (struct CadetTunnel *t, | |||
1515 | struct GNUNET_CADET_ChannelTunnelNumber ctn; | 1921 | struct GNUNET_CADET_ChannelTunnelNumber ctn; |
1516 | 1922 | ||
1517 | ctn = get_next_free_ctn (t); | 1923 | ctn = get_next_free_ctn (t); |
1924 | if (NULL != t->destroy_task) | ||
1925 | { | ||
1926 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
1927 | t->destroy_task = NULL; | ||
1928 | } | ||
1518 | GNUNET_assert (GNUNET_YES == | 1929 | GNUNET_assert (GNUNET_YES == |
1519 | GNUNET_CONTAINER_multihashmap32_put (t->channels, | 1930 | GNUNET_CONTAINER_multihashmap32_put (t->channels, |
1520 | ntohl (ctn.cn), | 1931 | ntohl (ctn.cn), |
1521 | ch, | 1932 | ch, |
1522 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 1933 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); |
1523 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1934 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1524 | "Adding channel %s to tunnel %s\n", | 1935 | "Adding %s to %s\n", |
1525 | GCCH_2s (ch), | 1936 | GCCH_2s (ch), |
1526 | GCT_2s (t)); | 1937 | GCT_2s (t)); |
1527 | if ( (CADET_TUNNEL_KEY_OK == t->estate) || | 1938 | switch (t->estate) |
1528 | (CADET_TUNNEL_KEY_REKEY == t->estate) ) | 1939 | { |
1940 | case CADET_TUNNEL_KEY_UNINITIALIZED: | ||
1941 | /* waiting for connection to start KX */ | ||
1942 | break; | ||
1943 | case CADET_TUNNEL_KEY_AX_RECV: | ||
1944 | case CADET_TUNNEL_KEY_AX_SENT: | ||
1945 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: | ||
1946 | /* we're currently waiting for KX to complete */ | ||
1947 | break; | ||
1948 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
1949 | /* waiting for OTHER peer to send us data, | ||
1950 | we might need to prompt more aggressively! */ | ||
1951 | if (NULL == t->kx_task) | ||
1952 | t->kx_task | ||
1953 | = GNUNET_SCHEDULER_add_at (t->next_kx_attempt, | ||
1954 | &retry_kx, | ||
1955 | t); | ||
1956 | break; | ||
1957 | case CADET_TUNNEL_KEY_OK: | ||
1958 | /* We are ready. Tell the new channel that we are up. */ | ||
1529 | GCCH_tunnel_up (ch); | 1959 | GCCH_tunnel_up (ch); |
1960 | break; | ||
1961 | } | ||
1530 | return ctn; | 1962 | return ctn; |
1531 | } | 1963 | } |
1532 | 1964 | ||
1533 | 1965 | ||
1534 | /** | 1966 | /** |
1967 | * We lost a connection, remove it from our list and clean up | ||
1968 | * the connection object itself. | ||
1969 | * | ||
1970 | * @param ct binding of connection to tunnel of the connection that was lost. | ||
1971 | */ | ||
1972 | void | ||
1973 | GCT_connection_lost (struct CadetTConnection *ct) | ||
1974 | { | ||
1975 | struct CadetTunnel *t = ct->t; | ||
1976 | |||
1977 | if (GNUNET_YES == ct->is_ready) | ||
1978 | { | ||
1979 | GNUNET_CONTAINER_DLL_remove (t->connection_ready_head, | ||
1980 | t->connection_ready_tail, | ||
1981 | ct); | ||
1982 | t->num_ready_connections--; | ||
1983 | } | ||
1984 | else | ||
1985 | { | ||
1986 | GNUNET_CONTAINER_DLL_remove (t->connection_busy_head, | ||
1987 | t->connection_busy_tail, | ||
1988 | ct); | ||
1989 | t->num_busy_connections--; | ||
1990 | } | ||
1991 | GNUNET_free (ct); | ||
1992 | } | ||
1993 | |||
1994 | |||
1995 | /** | ||
1996 | * Clean up connection @a ct of a tunnel. | ||
1997 | * | ||
1998 | * @param cls the `struct CadetTunnel` | ||
1999 | * @param ct connection to clean up | ||
2000 | */ | ||
2001 | static void | ||
2002 | destroy_t_connection (void *cls, | ||
2003 | struct CadetTConnection *ct) | ||
2004 | { | ||
2005 | struct CadetTunnel *t = cls; | ||
2006 | struct CadetConnection *cc = ct->cc; | ||
2007 | |||
2008 | GNUNET_assert (ct->t == t); | ||
2009 | GCT_connection_lost (ct); | ||
2010 | GCC_destroy_without_tunnel (cc); | ||
2011 | } | ||
2012 | |||
2013 | |||
2014 | /** | ||
1535 | * This tunnel is no longer used, destroy it. | 2015 | * This tunnel is no longer used, destroy it. |
1536 | * | 2016 | * |
1537 | * @param cls the idle tunnel | 2017 | * @param cls the idle tunnel |
@@ -1540,27 +2020,23 @@ static void | |||
1540 | destroy_tunnel (void *cls) | 2020 | destroy_tunnel (void *cls) |
1541 | { | 2021 | { |
1542 | struct CadetTunnel *t = cls; | 2022 | struct CadetTunnel *t = cls; |
1543 | struct CadetTConnection *ct; | ||
1544 | struct CadetTunnelQueueEntry *tq; | 2023 | struct CadetTunnelQueueEntry *tq; |
1545 | 2024 | ||
1546 | t->destroy_task = NULL; | 2025 | t->destroy_task = NULL; |
1547 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2026 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1548 | "Destroying idle tunnel %s\n", | 2027 | "Destroying idle %s\n", |
1549 | GCT_2s (t)); | 2028 | GCT_2s (t)); |
1550 | GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (t->channels)); | 2029 | GNUNET_assert (0 == GCT_count_channels (t)); |
1551 | while (NULL != (ct = t->connection_head)) | 2030 | GCT_iterate_connections (t, |
1552 | { | 2031 | &destroy_t_connection, |
1553 | GNUNET_assert (ct->t == t); | 2032 | t); |
1554 | GNUNET_CONTAINER_DLL_remove (t->connection_head, | 2033 | GNUNET_assert (NULL == t->connection_ready_head); |
1555 | t->connection_tail, | 2034 | GNUNET_assert (NULL == t->connection_busy_head); |
1556 | ct); | ||
1557 | GCC_destroy (ct->cc); | ||
1558 | GNUNET_free (ct); | ||
1559 | } | ||
1560 | while (NULL != (tq = t->tq_head)) | 2035 | while (NULL != (tq = t->tq_head)) |
1561 | { | 2036 | { |
1562 | if (NULL != tq->cont) | 2037 | if (NULL != tq->cont) |
1563 | tq->cont (tq->cont_cls); | 2038 | tq->cont (tq->cont_cls, |
2039 | NULL); | ||
1564 | GCT_send_cancel (tq); | 2040 | GCT_send_cancel (tq); |
1565 | } | 2041 | } |
1566 | GCP_drop_tunnel (t->destination, | 2042 | GCP_drop_tunnel (t->destination, |
@@ -1583,12 +2059,13 @@ destroy_tunnel (void *cls) | |||
1583 | } | 2059 | } |
1584 | GNUNET_MST_destroy (t->mst); | 2060 | GNUNET_MST_destroy (t->mst); |
1585 | GNUNET_MQ_destroy (t->mq); | 2061 | GNUNET_MQ_destroy (t->mq); |
1586 | while (NULL != t->ax.skipped_head) | 2062 | if (NULL != t->unverified_ax) |
1587 | delete_skipped_key (t, | 2063 | { |
1588 | t->ax.skipped_head); | 2064 | cleanup_ax (t->unverified_ax); |
1589 | GNUNET_assert (0 == t->ax.skipped); | 2065 | GNUNET_free (t->unverified_ax); |
1590 | GNUNET_free_non_null (t->ax.kx_0); | 2066 | } |
1591 | GNUNET_free_non_null (t->ax.DHRs); | 2067 | cleanup_ax (&t->ax); |
2068 | GNUNET_assert (NULL == t->destroy_task); | ||
1592 | GNUNET_free (t); | 2069 | GNUNET_free (t); |
1593 | } | 2070 | } |
1594 | 2071 | ||
@@ -1606,19 +2083,21 @@ GCT_remove_channel (struct CadetTunnel *t, | |||
1606 | struct GNUNET_CADET_ChannelTunnelNumber ctn) | 2083 | struct GNUNET_CADET_ChannelTunnelNumber ctn) |
1607 | { | 2084 | { |
1608 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2085 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1609 | "Removing channel %s from tunnel %s\n", | 2086 | "Removing %s from %s\n", |
1610 | GCCH_2s (ch), | 2087 | GCCH_2s (ch), |
1611 | GCT_2s (t)); | 2088 | GCT_2s (t)); |
1612 | GNUNET_assert (GNUNET_YES == | 2089 | GNUNET_assert (GNUNET_YES == |
1613 | GNUNET_CONTAINER_multihashmap32_remove (t->channels, | 2090 | GNUNET_CONTAINER_multihashmap32_remove (t->channels, |
1614 | ntohl (ctn.cn), | 2091 | ntohl (ctn.cn), |
1615 | ch)); | 2092 | ch)); |
1616 | if (0 == | 2093 | if ( (0 == |
1617 | GNUNET_CONTAINER_multihashmap32_size (t->channels)) | 2094 | GCT_count_channels (t)) && |
2095 | (NULL == t->destroy_task) ) | ||
1618 | { | 2096 | { |
1619 | t->destroy_task = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY, | 2097 | t->destroy_task |
1620 | &destroy_tunnel, | 2098 | = GNUNET_SCHEDULER_add_delayed (IDLE_DESTROY_DELAY, |
1621 | t); | 2099 | &destroy_tunnel, |
2100 | t); | ||
1622 | } | 2101 | } |
1623 | } | 2102 | } |
1624 | 2103 | ||
@@ -1638,7 +2117,8 @@ destroy_remaining_channels (void *cls, | |||
1638 | { | 2117 | { |
1639 | struct CadetChannel *ch = value; | 2118 | struct CadetChannel *ch = value; |
1640 | 2119 | ||
1641 | GCCH_handle_remote_destroy (ch); | 2120 | GCCH_handle_remote_destroy (ch, |
2121 | NULL); | ||
1642 | return GNUNET_OK; | 2122 | return GNUNET_OK; |
1643 | } | 2123 | } |
1644 | 2124 | ||
@@ -1656,7 +2136,7 @@ GCT_destroy_tunnel_now (struct CadetTunnel *t) | |||
1656 | &destroy_remaining_channels, | 2136 | &destroy_remaining_channels, |
1657 | t); | 2137 | t); |
1658 | GNUNET_assert (0 == | 2138 | GNUNET_assert (0 == |
1659 | GNUNET_CONTAINER_multihashmap32_size (t->channels)); | 2139 | GCT_count_channels (t)); |
1660 | if (NULL != t->destroy_task) | 2140 | if (NULL != t->destroy_task) |
1661 | { | 2141 | { |
1662 | GNUNET_SCHEDULER_cancel (t->destroy_task); | 2142 | GNUNET_SCHEDULER_cancel (t->destroy_task); |
@@ -1667,25 +2147,6 @@ GCT_destroy_tunnel_now (struct CadetTunnel *t) | |||
1667 | 2147 | ||
1668 | 2148 | ||
1669 | /** | 2149 | /** |
1670 | * It's been a while, we should try to redo the KX, if we can. | ||
1671 | * | ||
1672 | * @param cls the `struct CadetTunnel` to do KX for. | ||
1673 | */ | ||
1674 | static void | ||
1675 | retry_kx (void *cls) | ||
1676 | { | ||
1677 | struct CadetTunnel *t = cls; | ||
1678 | |||
1679 | t->kx_task = NULL; | ||
1680 | send_kx (t, | ||
1681 | ( (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate) || | ||
1682 | (CADET_TUNNEL_KEY_SENT == t->estate) ) | ||
1683 | ? GNUNET_YES | ||
1684 | : GNUNET_NO); | ||
1685 | } | ||
1686 | |||
1687 | |||
1688 | /** | ||
1689 | * Send normal payload from queue in @a t via connection @a ct. | 2150 | * Send normal payload from queue in @a t via connection @a ct. |
1690 | * Does nothing if our payload queue is empty. | 2151 | * Does nothing if our payload queue is empty. |
1691 | * | 2152 | * |
@@ -1716,7 +2177,7 @@ try_send_normal_payload (struct CadetTunnel *t, | |||
1716 | tq); | 2177 | tq); |
1717 | if (NULL != tq->cid) | 2178 | if (NULL != tq->cid) |
1718 | *tq->cid = *GCC_get_id (ct->cc); | 2179 | *tq->cid = *GCC_get_id (ct->cc); |
1719 | ct->is_ready = GNUNET_NO; | 2180 | mark_connection_unready (ct); |
1720 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2181 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1721 | "Sending payload of %s on %s\n", | 2182 | "Sending payload of %s on %s\n", |
1722 | GCT_2s (t), | 2183 | GCT_2s (t), |
@@ -1724,7 +2185,8 @@ try_send_normal_payload (struct CadetTunnel *t, | |||
1724 | GCC_transmit (ct->cc, | 2185 | GCC_transmit (ct->cc, |
1725 | tq->env); | 2186 | tq->env); |
1726 | if (NULL != tq->cont) | 2187 | if (NULL != tq->cont) |
1727 | tq->cont (tq->cont_cls); | 2188 | tq->cont (tq->cont_cls, |
2189 | GCC_get_id (ct->cc)); | ||
1728 | GNUNET_free (tq); | 2190 | GNUNET_free (tq); |
1729 | } | 2191 | } |
1730 | 2192 | ||
@@ -1747,44 +2209,74 @@ connection_ready_cb (void *cls, | |||
1747 | if (GNUNET_NO == is_ready) | 2209 | if (GNUNET_NO == is_ready) |
1748 | { | 2210 | { |
1749 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2211 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1750 | "Connection %s no longer ready for tunnel %s\n", | 2212 | "%s no longer ready for %s\n", |
1751 | GCC_2s (ct->cc), | 2213 | GCC_2s (ct->cc), |
1752 | GCT_2s (t)); | 2214 | GCT_2s (t)); |
1753 | ct->is_ready = GNUNET_NO; | 2215 | mark_connection_unready (ct); |
1754 | return; | 2216 | return; |
1755 | } | 2217 | } |
2218 | GNUNET_assert (GNUNET_NO == ct->is_ready); | ||
2219 | GNUNET_CONTAINER_DLL_remove (t->connection_busy_head, | ||
2220 | t->connection_busy_tail, | ||
2221 | ct); | ||
2222 | GNUNET_assert (0 < t->num_busy_connections); | ||
2223 | t->num_busy_connections--; | ||
1756 | ct->is_ready = GNUNET_YES; | 2224 | ct->is_ready = GNUNET_YES; |
2225 | GNUNET_CONTAINER_DLL_insert_tail (t->connection_ready_head, | ||
2226 | t->connection_ready_tail, | ||
2227 | ct); | ||
2228 | t->num_ready_connections++; | ||
2229 | |||
1757 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2230 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1758 | "Connection %s now ready for tunnel %s in state %s\n", | 2231 | "%s now ready for %s in state %s\n", |
1759 | GCC_2s (ct->cc), | 2232 | GCC_2s (ct->cc), |
1760 | GCT_2s (t), | 2233 | GCT_2s (t), |
1761 | estate2s (t->estate)); | 2234 | estate2s (t->estate)); |
1762 | switch (t->estate) | 2235 | switch (t->estate) |
1763 | { | 2236 | { |
1764 | case CADET_TUNNEL_KEY_UNINITIALIZED: | 2237 | case CADET_TUNNEL_KEY_UNINITIALIZED: |
2238 | /* Do not begin KX if WE have no channels waiting! */ | ||
2239 | if (0 == GCT_count_channels (t)) | ||
2240 | return; | ||
2241 | /* We are uninitialized, just transmit immediately, | ||
2242 | without undue delay. */ | ||
2243 | if (NULL != t->kx_task) | ||
2244 | { | ||
2245 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
2246 | t->kx_task = NULL; | ||
2247 | } | ||
1765 | send_kx (t, | 2248 | send_kx (t, |
1766 | GNUNET_YES); | 2249 | ct, |
2250 | &t->ax); | ||
1767 | break; | 2251 | break; |
1768 | case CADET_TUNNEL_KEY_SENT: | 2252 | case CADET_TUNNEL_KEY_AX_RECV: |
1769 | case CADET_TUNNEL_KEY_PING: | 2253 | case CADET_TUNNEL_KEY_AX_SENT: |
1770 | /* opportunity to #retry_kx() starts now, schedule job */ | 2254 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: |
2255 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: | ||
2256 | /* we're currently waiting for KX to complete, schedule job */ | ||
1771 | if (NULL == t->kx_task) | 2257 | if (NULL == t->kx_task) |
1772 | { | ||
1773 | t->kx_task | 2258 | t->kx_task |
1774 | = GNUNET_SCHEDULER_add_at (t->next_kx_attempt, | 2259 | = GNUNET_SCHEDULER_add_at (t->next_kx_attempt, |
1775 | &retry_kx, | 2260 | &retry_kx, |
1776 | t); | 2261 | t); |
1777 | } | ||
1778 | break; | 2262 | break; |
1779 | case CADET_TUNNEL_KEY_OK: | 2263 | case CADET_TUNNEL_KEY_OK: |
2264 | if (GNUNET_YES == t->kx_auth_requested) | ||
2265 | { | ||
2266 | if (NULL != t->kx_task) | ||
2267 | { | ||
2268 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
2269 | t->kx_task = NULL; | ||
2270 | } | ||
2271 | send_kx_auth (t, | ||
2272 | ct, | ||
2273 | &t->ax, | ||
2274 | GNUNET_NO); | ||
2275 | return; | ||
2276 | } | ||
1780 | try_send_normal_payload (t, | 2277 | try_send_normal_payload (t, |
1781 | ct); | 2278 | ct); |
1782 | break; | 2279 | break; |
1783 | case CADET_TUNNEL_KEY_REKEY: | ||
1784 | send_kx (t, | ||
1785 | GNUNET_NO); | ||
1786 | t->estate = CADET_TUNNEL_KEY_OK; | ||
1787 | break; | ||
1788 | } | 2280 | } |
1789 | } | 2281 | } |
1790 | 2282 | ||
@@ -1815,6 +2307,118 @@ trigger_transmissions (void *cls) | |||
1815 | 2307 | ||
1816 | 2308 | ||
1817 | /** | 2309 | /** |
2310 | * Closure for #evaluate_connection. Used to assemble summary information | ||
2311 | * about the existing connections so we can evaluate a new path. | ||
2312 | */ | ||
2313 | struct EvaluationSummary | ||
2314 | { | ||
2315 | |||
2316 | /** | ||
2317 | * Minimum length of any of our connections, `UINT_MAX` if we have none. | ||
2318 | */ | ||
2319 | unsigned int min_length; | ||
2320 | |||
2321 | /** | ||
2322 | * Maximum length of any of our connections, 0 if we have none. | ||
2323 | */ | ||
2324 | unsigned int max_length; | ||
2325 | |||
2326 | /** | ||
2327 | * Minimum desirability of any of our connections, UINT64_MAX if we have none. | ||
2328 | */ | ||
2329 | GNUNET_CONTAINER_HeapCostType min_desire; | ||
2330 | |||
2331 | /** | ||
2332 | * Maximum desirability of any of our connections, 0 if we have none. | ||
2333 | */ | ||
2334 | GNUNET_CONTAINER_HeapCostType max_desire; | ||
2335 | |||
2336 | /** | ||
2337 | * Path we are comparing against for #evaluate_connection, can be NULL. | ||
2338 | */ | ||
2339 | struct CadetPeerPath *path; | ||
2340 | |||
2341 | /** | ||
2342 | * Connection deemed the "worst" so far encountered by #evaluate_connection, | ||
2343 | * NULL if we did not yet encounter any connections. | ||
2344 | */ | ||
2345 | struct CadetTConnection *worst; | ||
2346 | |||
2347 | /** | ||
2348 | * Numeric score of @e worst, only set if @e worst is non-NULL. | ||
2349 | */ | ||
2350 | double worst_score; | ||
2351 | |||
2352 | /** | ||
2353 | * Set to #GNUNET_YES if we have a connection over @e path already. | ||
2354 | */ | ||
2355 | int duplicate; | ||
2356 | |||
2357 | }; | ||
2358 | |||
2359 | |||
2360 | /** | ||
2361 | * Evaluate a connection, updating our summary information in @a cls about | ||
2362 | * what kinds of connections we have. | ||
2363 | * | ||
2364 | * @param cls the `struct EvaluationSummary *` to update | ||
2365 | * @param ct a connection to include in the summary | ||
2366 | */ | ||
2367 | static void | ||
2368 | evaluate_connection (void *cls, | ||
2369 | struct CadetTConnection *ct) | ||
2370 | { | ||
2371 | struct EvaluationSummary *es = cls; | ||
2372 | struct CadetConnection *cc = ct->cc; | ||
2373 | struct CadetPeerPath *ps = GCC_get_path (cc); | ||
2374 | const struct CadetConnectionMetrics *metrics; | ||
2375 | GNUNET_CONTAINER_HeapCostType ct_desirability; | ||
2376 | struct GNUNET_TIME_Relative uptime; | ||
2377 | struct GNUNET_TIME_Relative last_use; | ||
2378 | uint32_t ct_length; | ||
2379 | double score; | ||
2380 | double success_rate; | ||
2381 | |||
2382 | if (ps == es->path) | ||
2383 | { | ||
2384 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2385 | "Ignoring duplicate path %s.\n", | ||
2386 | GCPP_2s (es->path)); | ||
2387 | es->duplicate = GNUNET_YES; | ||
2388 | return; | ||
2389 | } | ||
2390 | ct_desirability = GCPP_get_desirability (ps); | ||
2391 | ct_length = GCPP_get_length (ps); | ||
2392 | metrics = GCC_get_metrics (cc); | ||
2393 | uptime = GNUNET_TIME_absolute_get_duration (metrics->age); | ||
2394 | last_use = GNUNET_TIME_absolute_get_duration (metrics->last_use); | ||
2395 | /* We add 1.0 here to avoid division by zero. */ | ||
2396 | success_rate = (metrics->num_acked_transmissions + 1.0) / (metrics->num_successes + 1.0); | ||
2397 | score | ||
2398 | = ct_desirability | ||
2399 | + 100.0 / (1.0 + ct_length) /* longer paths = better */ | ||
2400 | + sqrt (uptime.rel_value_us / 60000000LL) /* larger uptime = better */ | ||
2401 | - last_use.rel_value_us / 1000L; /* longer idle = worse */ | ||
2402 | score *= success_rate; /* weigh overall by success rate */ | ||
2403 | |||
2404 | if ( (NULL == es->worst) || | ||
2405 | (score < es->worst_score) ) | ||
2406 | { | ||
2407 | es->worst = ct; | ||
2408 | es->worst_score = score; | ||
2409 | } | ||
2410 | es->min_length = GNUNET_MIN (es->min_length, | ||
2411 | ct_length); | ||
2412 | es->max_length = GNUNET_MAX (es->max_length, | ||
2413 | ct_length); | ||
2414 | es->min_desire = GNUNET_MIN (es->min_desire, | ||
2415 | ct_desirability); | ||
2416 | es->max_desire = GNUNET_MAX (es->max_desire, | ||
2417 | ct_desirability); | ||
2418 | } | ||
2419 | |||
2420 | |||
2421 | /** | ||
1818 | * Consider using the path @a p for the tunnel @a t. | 2422 | * Consider using the path @a p for the tunnel @a t. |
1819 | * The tunnel destination is at offset @a off in path @a p. | 2423 | * The tunnel destination is at offset @a off in path @a p. |
1820 | * | 2424 | * |
@@ -1829,31 +2433,24 @@ consider_path_cb (void *cls, | |||
1829 | unsigned int off) | 2433 | unsigned int off) |
1830 | { | 2434 | { |
1831 | struct CadetTunnel *t = cls; | 2435 | struct CadetTunnel *t = cls; |
1832 | unsigned int min_length = UINT_MAX; | 2436 | struct EvaluationSummary es; |
1833 | GNUNET_CONTAINER_HeapCostType max_desire = 0; | ||
1834 | struct CadetTConnection *ct; | 2437 | struct CadetTConnection *ct; |
1835 | 2438 | ||
1836 | /* Check if we care about the new path. */ | 2439 | GNUNET_assert (off < GCPP_get_length (path)); |
1837 | for (ct = t->connection_head; | 2440 | es.min_length = UINT_MAX; |
1838 | NULL != ct; | 2441 | es.max_length = 0; |
1839 | ct = ct->next) | 2442 | es.max_desire = 0; |
1840 | { | 2443 | es.min_desire = UINT64_MAX; |
1841 | struct CadetPeerPath *ps; | 2444 | es.path = path; |
1842 | 2445 | es.duplicate = GNUNET_NO; | |
1843 | ps = GCC_get_path (ct->cc); | 2446 | es.worst = NULL; |
1844 | if (ps == path) | 2447 | |
1845 | { | 2448 | /* Compute evaluation summary over existing connections. */ |
1846 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2449 | GCT_iterate_connections (t, |
1847 | "Ignoring duplicate path %s for tunnel %s.\n", | 2450 | &evaluate_connection, |
1848 | GCPP_2s (path), | 2451 | &es); |
1849 | GCT_2s (t)); | 2452 | if (GNUNET_YES == es.duplicate) |
1850 | return GNUNET_YES; /* duplicate */ | 2453 | return GNUNET_YES; |
1851 | } | ||
1852 | min_length = GNUNET_MIN (min_length, | ||
1853 | GCPP_get_length (ps)); | ||
1854 | max_desire = GNUNET_MAX (max_desire, | ||
1855 | GCPP_get_desirability (ps)); | ||
1856 | } | ||
1857 | 2454 | ||
1858 | /* FIXME: not sure we should really just count | 2455 | /* FIXME: not sure we should really just count |
1859 | 'num_connections' here, as they may all have | 2456 | 'num_connections' here, as they may all have |
@@ -1862,18 +2459,20 @@ consider_path_cb (void *cls, | |||
1862 | /* We iterate by increasing path length; if we have enough paths and | 2459 | /* We iterate by increasing path length; if we have enough paths and |
1863 | this one is more than twice as long than what we are currently | 2460 | this one is more than twice as long than what we are currently |
1864 | using, then ignore all of these super-long ones! */ | 2461 | using, then ignore all of these super-long ones! */ |
1865 | if ( (t->num_connections > DESIRED_CONNECTIONS_PER_TUNNEL) && | 2462 | if ( (GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL) && |
1866 | (min_length * 2 < off) ) | 2463 | (es.min_length * 2 < off) && |
2464 | (es.max_length < off) ) | ||
1867 | { | 2465 | { |
1868 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2466 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1869 | "Ignoring paths of length %u, they are way too long.\n", | 2467 | "Ignoring paths of length %u, they are way too long.\n", |
1870 | min_length * 2); | 2468 | es.min_length * 2); |
1871 | return GNUNET_NO; | 2469 | return GNUNET_NO; |
1872 | } | 2470 | } |
1873 | /* If we have enough paths and this one looks no better, ignore it. */ | 2471 | /* If we have enough paths and this one looks no better, ignore it. */ |
1874 | if ( (t->num_connections >= DESIRED_CONNECTIONS_PER_TUNNEL) && | 2472 | if ( (GCT_count_any_connections (t) >= DESIRED_CONNECTIONS_PER_TUNNEL) && |
1875 | (min_length < GCPP_get_length (path)) && | 2473 | (es.min_length < GCPP_get_length (path)) && |
1876 | (max_desire > GCPP_get_desirability (path)) ) | 2474 | (es.min_desire > GCPP_get_desirability (path)) && |
2475 | (es.max_length < off) ) | ||
1877 | { | 2476 | { |
1878 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2477 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1879 | "Ignoring path (%u/%llu) to %s, got something better already.\n", | 2478 | "Ignoring path (%u/%llu) to %s, got something better already.\n", |
@@ -1890,19 +2489,22 @@ consider_path_cb (void *cls, | |||
1890 | ct->t = t; | 2489 | ct->t = t; |
1891 | ct->cc = GCC_create (t->destination, | 2490 | ct->cc = GCC_create (t->destination, |
1892 | path, | 2491 | path, |
2492 | off, | ||
2493 | GNUNET_CADET_OPTION_DEFAULT, /* FIXME: set based on what channels want/need! */ | ||
1893 | ct, | 2494 | ct, |
1894 | &connection_ready_cb, | 2495 | &connection_ready_cb, |
1895 | ct); | 2496 | ct); |
2497 | |||
1896 | /* FIXME: schedule job to kill connection (and path?) if it takes | 2498 | /* FIXME: schedule job to kill connection (and path?) if it takes |
1897 | too long to get ready! (And track performance data on how long | 2499 | too long to get ready! (And track performance data on how long |
1898 | other connections took with the tunnel!) | 2500 | other connections took with the tunnel!) |
1899 | => Note: to be done within 'connection'-logic! */ | 2501 | => Note: to be done within 'connection'-logic! */ |
1900 | GNUNET_CONTAINER_DLL_insert (t->connection_head, | 2502 | GNUNET_CONTAINER_DLL_insert (t->connection_busy_head, |
1901 | t->connection_tail, | 2503 | t->connection_busy_tail, |
1902 | ct); | 2504 | ct); |
1903 | t->num_connections++; | 2505 | t->num_busy_connections++; |
1904 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2506 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1905 | "Found interesting path %s for tunnel %s, created connection %s\n", | 2507 | "Found interesting path %s for %s, created %s\n", |
1906 | GCPP_2s (path), | 2508 | GCPP_2s (path), |
1907 | GCT_2s (t), | 2509 | GCT_2s (t), |
1908 | GCC_2s (ct->cc)); | 2510 | GCC_2s (ct->cc)); |
@@ -1927,17 +2529,50 @@ static void | |||
1927 | maintain_connections_cb (void *cls) | 2529 | maintain_connections_cb (void *cls) |
1928 | { | 2530 | { |
1929 | struct CadetTunnel *t = cls; | 2531 | struct CadetTunnel *t = cls; |
2532 | struct GNUNET_TIME_Relative delay; | ||
2533 | struct EvaluationSummary es; | ||
1930 | 2534 | ||
1931 | t->maintain_connections_task = NULL; | 2535 | t->maintain_connections_task = NULL; |
1932 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2536 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1933 | "Performing connection maintenance for tunnel %s.\n", | 2537 | "Performing connection maintenance for %s.\n", |
1934 | GCT_2s (t)); | 2538 | GCT_2s (t)); |
1935 | 2539 | ||
2540 | es.min_length = UINT_MAX; | ||
2541 | es.max_length = 0; | ||
2542 | es.max_desire = 0; | ||
2543 | es.min_desire = UINT64_MAX; | ||
2544 | es.path = NULL; | ||
2545 | es.worst = NULL; | ||
2546 | es.duplicate = GNUNET_NO; | ||
2547 | GCT_iterate_connections (t, | ||
2548 | &evaluate_connection, | ||
2549 | &es); | ||
2550 | if ( (NULL != es.worst) && | ||
2551 | (GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL) ) | ||
2552 | { | ||
2553 | /* Clear out worst-performing connection 'es.worst'. */ | ||
2554 | destroy_t_connection (t, | ||
2555 | es.worst); | ||
2556 | } | ||
2557 | |||
2558 | /* Consider additional paths */ | ||
1936 | (void) GCP_iterate_paths (t->destination, | 2559 | (void) GCP_iterate_paths (t->destination, |
1937 | &consider_path_cb, | 2560 | &consider_path_cb, |
1938 | t); | 2561 | t); |
1939 | 2562 | ||
1940 | GNUNET_break (0); // FIXME: implement! | 2563 | /* FIXME: calculate when to try again based on how well we are doing; |
2564 | in particular, if we have to few connections, we might be able | ||
2565 | to do without this (as PATHS should tell us whenever a new path | ||
2566 | is available instantly; however, need to make sure this job is | ||
2567 | restarted after that happens). | ||
2568 | Furthermore, if the paths we do know are in a reasonably narrow | ||
2569 | quality band and are plentyful, we might also consider us stabilized | ||
2570 | and then reduce the frequency accordingly. */ | ||
2571 | delay = GNUNET_TIME_UNIT_MINUTES; | ||
2572 | t->maintain_connections_task | ||
2573 | = GNUNET_SCHEDULER_add_delayed (delay, | ||
2574 | &maintain_connections_cb, | ||
2575 | t); | ||
1941 | } | 2576 | } |
1942 | 2577 | ||
1943 | 2578 | ||
@@ -1954,6 +2589,10 @@ GCT_consider_path (struct CadetTunnel *t, | |||
1954 | struct CadetPeerPath *p, | 2589 | struct CadetPeerPath *p, |
1955 | unsigned int off) | 2590 | unsigned int off) |
1956 | { | 2591 | { |
2592 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2593 | "Considering %s for %s\n", | ||
2594 | GCPP_2s (p), | ||
2595 | GCT_2s (t)); | ||
1957 | (void) consider_path_cb (t, | 2596 | (void) consider_path_cb (t, |
1958 | p, | 2597 | p, |
1959 | off); | 2598 | off); |
@@ -1961,7 +2600,7 @@ GCT_consider_path (struct CadetTunnel *t, | |||
1961 | 2600 | ||
1962 | 2601 | ||
1963 | /** | 2602 | /** |
1964 | * NOT IMPLEMENTED. | 2603 | * We got a keepalive. Track in statistics. |
1965 | * | 2604 | * |
1966 | * @param cls the `struct CadetTunnel` for which we decrypted the message | 2605 | * @param cls the `struct CadetTunnel` for which we decrypted the message |
1967 | * @param msg the message we received on the tunnel | 2606 | * @param msg the message we received on the tunnel |
@@ -1972,7 +2611,13 @@ handle_plaintext_keepalive (void *cls, | |||
1972 | { | 2611 | { |
1973 | struct CadetTunnel *t = cls; | 2612 | struct CadetTunnel *t = cls; |
1974 | 2613 | ||
1975 | GNUNET_break (0); // FIXME | 2614 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2615 | "Received KEEPALIVE on %s\n", | ||
2616 | GCT_2s (t)); | ||
2617 | GNUNET_STATISTICS_update (stats, | ||
2618 | "# keepalives received", | ||
2619 | 1, | ||
2620 | GNUNET_NO); | ||
1976 | } | 2621 | } |
1977 | 2622 | ||
1978 | 2623 | ||
@@ -2012,7 +2657,7 @@ handle_plaintext_data (void *cls, | |||
2012 | /* We don't know about such a channel, might have been destroyed on our | 2657 | /* We don't know about such a channel, might have been destroyed on our |
2013 | end in the meantime, or never existed. Send back a DESTROY. */ | 2658 | end in the meantime, or never existed. Send back a DESTROY. */ |
2014 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2659 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2015 | "Receicved %u bytes of application data for unknown channel %u, sending DESTROY\n", | 2660 | "Received %u bytes of application data for unknown channel %u, sending DESTROY\n", |
2016 | (unsigned int) (ntohs (msg->header.size) - sizeof (*msg)), | 2661 | (unsigned int) (ntohs (msg->header.size) - sizeof (*msg)), |
2017 | ntohl (msg->ctn.cn)); | 2662 | ntohl (msg->ctn.cn)); |
2018 | GCT_send_channel_destroy (t, | 2663 | GCT_send_channel_destroy (t, |
@@ -2020,6 +2665,7 @@ handle_plaintext_data (void *cls, | |||
2020 | return; | 2665 | return; |
2021 | } | 2666 | } |
2022 | GCCH_handle_channel_plaintext_data (ch, | 2667 | GCCH_handle_channel_plaintext_data (ch, |
2668 | GCC_get_id (t->current_ct->cc), | ||
2023 | msg); | 2669 | msg); |
2024 | } | 2670 | } |
2025 | 2671 | ||
@@ -2046,13 +2692,14 @@ handle_plaintext_data_ack (void *cls, | |||
2046 | /* We don't know about such a channel, might have been destroyed on our | 2692 | /* We don't know about such a channel, might have been destroyed on our |
2047 | end in the meantime, or never existed. Send back a DESTROY. */ | 2693 | end in the meantime, or never existed. Send back a DESTROY. */ |
2048 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2694 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2049 | "Receicved DATA_ACK for unknown channel %u, sending DESTROY\n", | 2695 | "Received DATA_ACK for unknown channel %u, sending DESTROY\n", |
2050 | ntohl (ack->ctn.cn)); | 2696 | ntohl (ack->ctn.cn)); |
2051 | GCT_send_channel_destroy (t, | 2697 | GCT_send_channel_destroy (t, |
2052 | ack->ctn); | 2698 | ack->ctn); |
2053 | return; | 2699 | return; |
2054 | } | 2700 | } |
2055 | GCCH_handle_channel_plaintext_data_ack (ch, | 2701 | GCCH_handle_channel_plaintext_data_ack (ch, |
2702 | GCC_get_id (t->current_ct->cc), | ||
2056 | ack); | 2703 | ack); |
2057 | } | 2704 | } |
2058 | 2705 | ||
@@ -2076,21 +2723,27 @@ handle_plaintext_channel_open (void *cls, | |||
2076 | if (NULL != ch) | 2723 | if (NULL != ch) |
2077 | { | 2724 | { |
2078 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2725 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2079 | "Receicved duplicate channel OPEN on port %s from %s (%s), resending ACK\n", | 2726 | "Received duplicate channel CHANNEL_OPEN on h_port %s from %s (%s), resending ACK\n", |
2080 | GNUNET_h2s (&copen->port), | 2727 | GNUNET_h2s (&copen->h_port), |
2081 | GCT_2s (t), | 2728 | GCT_2s (t), |
2082 | GCCH_2s (ch)); | 2729 | GCCH_2s (ch)); |
2083 | GCCH_handle_duplicate_open (ch); | 2730 | GCCH_handle_duplicate_open (ch, |
2731 | GCC_get_id (t->current_ct->cc)); | ||
2084 | return; | 2732 | return; |
2085 | } | 2733 | } |
2086 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2734 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2087 | "Receicved channel OPEN on port %s from %s\n", | 2735 | "Received CHANNEL_OPEN on h_port %s from %s\n", |
2088 | GNUNET_h2s (&copen->port), | 2736 | GNUNET_h2s (&copen->h_port), |
2089 | GCT_2s (t)); | 2737 | GCT_2s (t)); |
2090 | ch = GCCH_channel_incoming_new (t, | 2738 | ch = GCCH_channel_incoming_new (t, |
2091 | copen->ctn, | 2739 | copen->ctn, |
2092 | &copen->port, | 2740 | &copen->h_port, |
2093 | ntohl (copen->opt)); | 2741 | ntohl (copen->opt)); |
2742 | if (NULL != t->destroy_task) | ||
2743 | { | ||
2744 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
2745 | t->destroy_task = NULL; | ||
2746 | } | ||
2094 | GNUNET_assert (GNUNET_OK == | 2747 | GNUNET_assert (GNUNET_OK == |
2095 | GNUNET_CONTAINER_multihashmap32_put (t->channels, | 2748 | GNUNET_CONTAINER_multihashmap32_put (t->channels, |
2096 | ntohl (copen->ctn.cn), | 2749 | ntohl (copen->ctn.cn), |
@@ -2109,7 +2762,7 @@ void | |||
2109 | GCT_send_channel_destroy (struct CadetTunnel *t, | 2762 | GCT_send_channel_destroy (struct CadetTunnel *t, |
2110 | struct GNUNET_CADET_ChannelTunnelNumber ctn) | 2763 | struct GNUNET_CADET_ChannelTunnelNumber ctn) |
2111 | { | 2764 | { |
2112 | struct GNUNET_CADET_ChannelManageMessage msg; | 2765 | struct GNUNET_CADET_ChannelDestroyMessage msg; |
2113 | 2766 | ||
2114 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2767 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2115 | "Sending DESTORY message for channel ID %u\n", | 2768 | "Sending DESTORY message for channel ID %u\n", |
@@ -2135,7 +2788,7 @@ GCT_send_channel_destroy (struct CadetTunnel *t, | |||
2135 | */ | 2788 | */ |
2136 | static void | 2789 | static void |
2137 | handle_plaintext_channel_open_ack (void *cls, | 2790 | handle_plaintext_channel_open_ack (void *cls, |
2138 | const struct GNUNET_CADET_ChannelManageMessage *cm) | 2791 | const struct GNUNET_CADET_ChannelOpenAckMessage *cm) |
2139 | { | 2792 | { |
2140 | struct CadetTunnel *t = cls; | 2793 | struct CadetTunnel *t = cls; |
2141 | struct CadetChannel *ch; | 2794 | struct CadetChannel *ch; |
@@ -2157,7 +2810,9 @@ handle_plaintext_channel_open_ack (void *cls, | |||
2157 | "Received channel OPEN_ACK on channel %s from %s\n", | 2810 | "Received channel OPEN_ACK on channel %s from %s\n", |
2158 | GCCH_2s (ch), | 2811 | GCCH_2s (ch), |
2159 | GCT_2s (t)); | 2812 | GCT_2s (t)); |
2160 | GCCH_handle_channel_open_ack (ch); | 2813 | GCCH_handle_channel_open_ack (ch, |
2814 | GCC_get_id (t->current_ct->cc), | ||
2815 | &cm->port); | ||
2161 | } | 2816 | } |
2162 | 2817 | ||
2163 | 2818 | ||
@@ -2170,7 +2825,7 @@ handle_plaintext_channel_open_ack (void *cls, | |||
2170 | */ | 2825 | */ |
2171 | static void | 2826 | static void |
2172 | handle_plaintext_channel_destroy (void *cls, | 2827 | handle_plaintext_channel_destroy (void *cls, |
2173 | const struct GNUNET_CADET_ChannelManageMessage *cm) | 2828 | const struct GNUNET_CADET_ChannelDestroyMessage *cm) |
2174 | { | 2829 | { |
2175 | struct CadetTunnel *t = cls; | 2830 | struct CadetTunnel *t = cls; |
2176 | struct CadetChannel *ch; | 2831 | struct CadetChannel *ch; |
@@ -2187,10 +2842,11 @@ handle_plaintext_channel_destroy (void *cls, | |||
2187 | return; | 2842 | return; |
2188 | } | 2843 | } |
2189 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2844 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2190 | "Receicved channel DESTROY on %s from %s\n", | 2845 | "Received channel DESTROY on %s from %s\n", |
2191 | GCCH_2s (ch), | 2846 | GCCH_2s (ch), |
2192 | GCT_2s (t)); | 2847 | GCT_2s (t)); |
2193 | GCCH_handle_remote_destroy (ch); | 2848 | GCCH_handle_remote_destroy (ch, |
2849 | GCC_get_id (t->current_ct->cc)); | ||
2194 | } | 2850 | } |
2195 | 2851 | ||
2196 | 2852 | ||
@@ -2208,6 +2864,7 @@ handle_decrypted (void *cls, | |||
2208 | { | 2864 | { |
2209 | struct CadetTunnel *t = cls; | 2865 | struct CadetTunnel *t = cls; |
2210 | 2866 | ||
2867 | GNUNET_assert (NULL != t->current_ct); | ||
2211 | GNUNET_MQ_inject_message (t->mq, | 2868 | GNUNET_MQ_inject_message (t->mq, |
2212 | msg); | 2869 | msg); |
2213 | return GNUNET_OK; | 2870 | return GNUNET_OK; |
@@ -2259,17 +2916,19 @@ GCT_create_tunnel (struct CadetPeer *destination) | |||
2259 | t), | 2916 | t), |
2260 | GNUNET_MQ_hd_fixed_size (plaintext_channel_open_ack, | 2917 | GNUNET_MQ_hd_fixed_size (plaintext_channel_open_ack, |
2261 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK, | 2918 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK, |
2262 | struct GNUNET_CADET_ChannelManageMessage, | 2919 | struct GNUNET_CADET_ChannelOpenAckMessage, |
2263 | t), | 2920 | t), |
2264 | GNUNET_MQ_hd_fixed_size (plaintext_channel_destroy, | 2921 | GNUNET_MQ_hd_fixed_size (plaintext_channel_destroy, |
2265 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY, | 2922 | GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY, |
2266 | struct GNUNET_CADET_ChannelManageMessage, | 2923 | struct GNUNET_CADET_ChannelDestroyMessage, |
2267 | t), | 2924 | t), |
2268 | GNUNET_MQ_handler_end () | 2925 | GNUNET_MQ_handler_end () |
2269 | }; | 2926 | }; |
2270 | 2927 | ||
2271 | new_ephemeral (t); | 2928 | t->kx_retry_delay = INITIAL_KX_RETRY_DELAY; |
2272 | t->ax.kx_0 = GNUNET_CRYPTO_ecdhe_key_create (); | 2929 | new_ephemeral (&t->ax); |
2930 | GNUNET_assert (GNUNET_OK == | ||
2931 | GNUNET_CRYPTO_ecdhe_key_create2 (&t->ax.kx_0)); | ||
2273 | t->destination = destination; | 2932 | t->destination = destination; |
2274 | t->channels = GNUNET_CONTAINER_multihashmap32_create (8); | 2933 | t->channels = GNUNET_CONTAINER_multihashmap32_create (8); |
2275 | t->maintain_connections_task | 2934 | t->maintain_connections_task |
@@ -2293,11 +2952,15 @@ GCT_create_tunnel (struct CadetPeer *destination) | |||
2293 | * | 2952 | * |
2294 | * @param t a tunnel | 2953 | * @param t a tunnel |
2295 | * @param cid connection identifer to use for the connection | 2954 | * @param cid connection identifer to use for the connection |
2955 | * @param options options for the connection | ||
2296 | * @param path path to use for the connection | 2956 | * @param path path to use for the connection |
2957 | * @return #GNUNET_OK on success, | ||
2958 | * #GNUNET_SYSERR on failure (duplicate connection) | ||
2297 | */ | 2959 | */ |
2298 | void | 2960 | int |
2299 | GCT_add_inbound_connection (struct CadetTunnel *t, | 2961 | GCT_add_inbound_connection (struct CadetTunnel *t, |
2300 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | 2962 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, |
2963 | enum GNUNET_CADET_ChannelOption options, | ||
2301 | struct CadetPeerPath *path) | 2964 | struct CadetPeerPath *path) |
2302 | { | 2965 | { |
2303 | struct CadetTConnection *ct; | 2966 | struct CadetTConnection *ct; |
@@ -2307,22 +2970,33 @@ GCT_add_inbound_connection (struct CadetTunnel *t, | |||
2307 | ct->t = t; | 2970 | ct->t = t; |
2308 | ct->cc = GCC_create_inbound (t->destination, | 2971 | ct->cc = GCC_create_inbound (t->destination, |
2309 | path, | 2972 | path, |
2973 | options, | ||
2310 | ct, | 2974 | ct, |
2311 | cid, | 2975 | cid, |
2312 | &connection_ready_cb, | 2976 | &connection_ready_cb, |
2313 | ct); | 2977 | ct); |
2978 | if (NULL == ct->cc) | ||
2979 | { | ||
2980 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2981 | "%s refused inbound %s (duplicate)\n", | ||
2982 | GCT_2s (t), | ||
2983 | GCC_2s (ct->cc)); | ||
2984 | GNUNET_free (ct); | ||
2985 | return GNUNET_SYSERR; | ||
2986 | } | ||
2314 | /* FIXME: schedule job to kill connection (and path?) if it takes | 2987 | /* FIXME: schedule job to kill connection (and path?) if it takes |
2315 | too long to get ready! (And track performance data on how long | 2988 | too long to get ready! (And track performance data on how long |
2316 | other connections took with the tunnel!) | 2989 | other connections took with the tunnel!) |
2317 | => Note: to be done within 'connection'-logic! */ | 2990 | => Note: to be done within 'connection'-logic! */ |
2318 | GNUNET_CONTAINER_DLL_insert (t->connection_head, | 2991 | GNUNET_CONTAINER_DLL_insert (t->connection_busy_head, |
2319 | t->connection_tail, | 2992 | t->connection_busy_tail, |
2320 | ct); | 2993 | ct); |
2321 | t->num_connections++; | 2994 | t->num_busy_connections++; |
2322 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 2995 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2323 | "Tunnel %s has new connection %s\n", | 2996 | "%s has new %s\n", |
2324 | GCT_2s (t), | 2997 | GCT_2s (t), |
2325 | GCC_2s (ct->cc)); | 2998 | GCC_2s (ct->cc)); |
2999 | return GNUNET_OK; | ||
2326 | } | 3000 | } |
2327 | 3001 | ||
2328 | 3002 | ||
@@ -2342,7 +3016,7 @@ GCT_handle_encrypted (struct CadetTConnection *ct, | |||
2342 | ssize_t decrypted_size; | 3016 | ssize_t decrypted_size; |
2343 | 3017 | ||
2344 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 3018 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2345 | "Tunnel %s received %u bytes of encrypted data in state %d\n", | 3019 | "%s received %u bytes of encrypted data in state %d\n", |
2346 | GCT_2s (t), | 3020 | GCT_2s (t), |
2347 | (unsigned int) size, | 3021 | (unsigned int) size, |
2348 | t->estate); | 3022 | t->estate); |
@@ -2350,66 +3024,158 @@ GCT_handle_encrypted (struct CadetTConnection *ct, | |||
2350 | switch (t->estate) | 3024 | switch (t->estate) |
2351 | { | 3025 | { |
2352 | case CADET_TUNNEL_KEY_UNINITIALIZED: | 3026 | case CADET_TUNNEL_KEY_UNINITIALIZED: |
3027 | case CADET_TUNNEL_KEY_AX_RECV: | ||
2353 | /* We did not even SEND our KX, how can the other peer | 3028 | /* We did not even SEND our KX, how can the other peer |
2354 | send us encrypted data? */ | 3029 | send us encrypted data? Must have been that we went |
2355 | GNUNET_break_op (0); | 3030 | down and the other peer still things we are up. |
3031 | Let's send it KX back. */ | ||
3032 | GNUNET_STATISTICS_update (stats, | ||
3033 | "# received encrypted without any KX", | ||
3034 | 1, | ||
3035 | GNUNET_NO); | ||
3036 | if (NULL != t->kx_task) | ||
3037 | { | ||
3038 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
3039 | t->kx_task = NULL; | ||
3040 | } | ||
3041 | send_kx (t, | ||
3042 | ct, | ||
3043 | &t->ax); | ||
2356 | return; | 3044 | return; |
2357 | case CADET_TUNNEL_KEY_SENT: | 3045 | case CADET_TUNNEL_KEY_AX_SENT_AND_RECV: |
3046 | /* We send KX, and other peer send KX to us at the same time. | ||
3047 | Neither KX is AUTH'ed, so let's try KX_AUTH this time. */ | ||
3048 | GNUNET_STATISTICS_update (stats, | ||
3049 | "# received encrypted without KX_AUTH", | ||
3050 | 1, | ||
3051 | GNUNET_NO); | ||
3052 | if (NULL != t->kx_task) | ||
3053 | { | ||
3054 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
3055 | t->kx_task = NULL; | ||
3056 | } | ||
3057 | send_kx_auth (t, | ||
3058 | ct, | ||
3059 | &t->ax, | ||
3060 | GNUNET_YES); | ||
3061 | return; | ||
3062 | case CADET_TUNNEL_KEY_AX_SENT: | ||
2358 | /* We did not get the KX of the other peer, but that | 3063 | /* We did not get the KX of the other peer, but that |
2359 | might have been lost. Ask for KX again. */ | 3064 | might have been lost. Send our KX again immediately. */ |
2360 | GNUNET_STATISTICS_update (stats, | 3065 | GNUNET_STATISTICS_update (stats, |
2361 | "# received encrypted without KX", | 3066 | "# received encrypted without KX", |
2362 | 1, | 3067 | 1, |
2363 | GNUNET_NO); | 3068 | GNUNET_NO); |
2364 | if (NULL != t->kx_task) | 3069 | if (NULL != t->kx_task) |
3070 | { | ||
2365 | GNUNET_SCHEDULER_cancel (t->kx_task); | 3071 | GNUNET_SCHEDULER_cancel (t->kx_task); |
2366 | t->kx_task = GNUNET_SCHEDULER_add_now (&retry_kx, | 3072 | t->kx_task = NULL; |
2367 | t); | 3073 | } |
3074 | send_kx (t, | ||
3075 | ct, | ||
3076 | &t->ax); | ||
2368 | return; | 3077 | return; |
2369 | case CADET_TUNNEL_KEY_PING: | 3078 | case CADET_TUNNEL_KEY_AX_AUTH_SENT: |
2370 | /* Great, first payload, we might graduate to OK */ | 3079 | /* Great, first payload, we might graduate to OK! */ |
2371 | case CADET_TUNNEL_KEY_OK: | 3080 | case CADET_TUNNEL_KEY_OK: |
2372 | case CADET_TUNNEL_KEY_REKEY: | 3081 | /* We are up and running, all good. */ |
2373 | break; | 3082 | break; |
2374 | } | 3083 | } |
2375 | 3084 | ||
2376 | GNUNET_STATISTICS_update (stats, | 3085 | decrypted_size = -1; |
2377 | "# received encrypted", | 3086 | if (CADET_TUNNEL_KEY_OK == t->estate) |
2378 | 1, | 3087 | { |
2379 | GNUNET_NO); | 3088 | /* We have well-established key material available, |
2380 | decrypted_size = t_ax_decrypt_and_validate (t, | 3089 | try that. (This is the common case.) */ |
2381 | cbuf, | 3090 | decrypted_size = t_ax_decrypt_and_validate (&t->ax, |
2382 | msg, | 3091 | cbuf, |
2383 | size); | 3092 | msg, |
3093 | size); | ||
3094 | } | ||
3095 | |||
3096 | if ( (-1 == decrypted_size) && | ||
3097 | (NULL != t->unverified_ax) ) | ||
3098 | { | ||
3099 | /* We have un-authenticated KX material available. We should try | ||
3100 | this as a back-up option, in case the sender crashed and | ||
3101 | switched keys. */ | ||
3102 | decrypted_size = t_ax_decrypt_and_validate (t->unverified_ax, | ||
3103 | cbuf, | ||
3104 | msg, | ||
3105 | size); | ||
3106 | if (-1 != decrypted_size) | ||
3107 | { | ||
3108 | /* It worked! Treat this as authentication of the AX data! */ | ||
3109 | cleanup_ax (&t->ax); | ||
3110 | t->ax = *t->unverified_ax; | ||
3111 | GNUNET_free (t->unverified_ax); | ||
3112 | t->unverified_ax = NULL; | ||
3113 | } | ||
3114 | if (CADET_TUNNEL_KEY_AX_AUTH_SENT == t->estate) | ||
3115 | { | ||
3116 | /* First time it worked, move tunnel into production! */ | ||
3117 | GCT_change_estate (t, | ||
3118 | CADET_TUNNEL_KEY_OK); | ||
3119 | if (NULL != t->send_task) | ||
3120 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
3121 | t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions, | ||
3122 | t); | ||
3123 | } | ||
3124 | } | ||
3125 | if (NULL != t->unverified_ax) | ||
3126 | { | ||
3127 | /* We had unverified KX material that was useless; so increment | ||
3128 | counter and eventually move to ignore it. Note that we even do | ||
3129 | this increment if we successfully decrypted with the old KX | ||
3130 | material and thus didn't even both with the new one. This is | ||
3131 | the ideal case, as a malicious injection of bogus KX data | ||
3132 | basically only causes us to increment a counter a few times. */ | ||
3133 | t->unverified_attempts++; | ||
3134 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3135 | "Failed to decrypt message with unverified KX data %u times\n", | ||
3136 | t->unverified_attempts); | ||
3137 | if (t->unverified_attempts > MAX_UNVERIFIED_ATTEMPTS) | ||
3138 | { | ||
3139 | cleanup_ax (t->unverified_ax); | ||
3140 | GNUNET_free (t->unverified_ax); | ||
3141 | t->unverified_ax = NULL; | ||
3142 | } | ||
3143 | } | ||
2384 | 3144 | ||
2385 | if (-1 == decrypted_size) | 3145 | if (-1 == decrypted_size) |
2386 | { | 3146 | { |
2387 | GNUNET_break_op (0); | 3147 | /* Decryption failed for good, complain. */ |
2388 | LOG (GNUNET_ERROR_TYPE_WARNING, | 3148 | LOG (GNUNET_ERROR_TYPE_WARNING, |
2389 | "Tunnel %s failed to decrypt and validate encrypted data\n", | 3149 | "%s failed to decrypt and validate encrypted data, retrying KX\n", |
2390 | GCT_2s (t)); | 3150 | GCT_2s (t)); |
2391 | GNUNET_STATISTICS_update (stats, | 3151 | GNUNET_STATISTICS_update (stats, |
2392 | "# unable to decrypt", | 3152 | "# unable to decrypt", |
2393 | 1, | 3153 | 1, |
2394 | GNUNET_NO); | 3154 | GNUNET_NO); |
3155 | if (NULL != t->kx_task) | ||
3156 | { | ||
3157 | GNUNET_SCHEDULER_cancel (t->kx_task); | ||
3158 | t->kx_task = NULL; | ||
3159 | } | ||
3160 | send_kx (t, | ||
3161 | ct, | ||
3162 | &t->ax); | ||
2395 | return; | 3163 | return; |
2396 | } | 3164 | } |
2397 | if (CADET_TUNNEL_KEY_PING == t->estate) | 3165 | GNUNET_STATISTICS_update (stats, |
2398 | { | 3166 | "# decrypted bytes", |
2399 | GCT_change_estate (t, | 3167 | decrypted_size, |
2400 | CADET_TUNNEL_KEY_OK); | 3168 | GNUNET_NO); |
2401 | if (NULL != t->send_task) | 3169 | |
2402 | GNUNET_SCHEDULER_cancel (t->send_task); | ||
2403 | t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions, | ||
2404 | t); | ||
2405 | } | ||
2406 | /* The MST will ultimately call #handle_decrypted() on each message. */ | 3170 | /* The MST will ultimately call #handle_decrypted() on each message. */ |
3171 | t->current_ct = ct; | ||
2407 | GNUNET_break_op (GNUNET_OK == | 3172 | GNUNET_break_op (GNUNET_OK == |
2408 | GNUNET_MST_from_buffer (t->mst, | 3173 | GNUNET_MST_from_buffer (t->mst, |
2409 | cbuf, | 3174 | cbuf, |
2410 | decrypted_size, | 3175 | decrypted_size, |
2411 | GNUNET_YES, | 3176 | GNUNET_YES, |
2412 | GNUNET_NO)); | 3177 | GNUNET_NO)); |
3178 | t->current_ct = NULL; | ||
2413 | } | 3179 | } |
2414 | 3180 | ||
2415 | 3181 | ||
@@ -2421,12 +3187,12 @@ GCT_handle_encrypted (struct CadetTConnection *ct, | |||
2421 | * @param t Tunnel on which this message is transmitted. | 3187 | * @param t Tunnel on which this message is transmitted. |
2422 | * @param cont Continuation to call once message is really sent. | 3188 | * @param cont Continuation to call once message is really sent. |
2423 | * @param cont_cls Closure for @c cont. | 3189 | * @param cont_cls Closure for @c cont. |
2424 | * @return Handle to cancel message. NULL if @c cont is NULL. | 3190 | * @return Handle to cancel message |
2425 | */ | 3191 | */ |
2426 | struct CadetTunnelQueueEntry * | 3192 | struct CadetTunnelQueueEntry * |
2427 | GCT_send (struct CadetTunnel *t, | 3193 | GCT_send (struct CadetTunnel *t, |
2428 | const struct GNUNET_MessageHeader *message, | 3194 | const struct GNUNET_MessageHeader *message, |
2429 | GNUNET_SCHEDULER_TaskCallback cont, | 3195 | GCT_SendContinuation cont, |
2430 | void *cont_cls) | 3196 | void *cont_cls) |
2431 | { | 3197 | { |
2432 | struct CadetTunnelQueueEntry *tq; | 3198 | struct CadetTunnelQueueEntry *tq; |
@@ -2434,26 +3200,38 @@ GCT_send (struct CadetTunnel *t, | |||
2434 | struct GNUNET_MQ_Envelope *env; | 3200 | struct GNUNET_MQ_Envelope *env; |
2435 | struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg; | 3201 | struct GNUNET_CADET_TunnelEncryptedMessage *ax_msg; |
2436 | 3202 | ||
3203 | if (CADET_TUNNEL_KEY_OK != t->estate) | ||
3204 | { | ||
3205 | GNUNET_break (0); | ||
3206 | return NULL; | ||
3207 | } | ||
2437 | payload_size = ntohs (message->size); | 3208 | payload_size = ntohs (message->size); |
2438 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 3209 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
2439 | "Encrypting %u bytes for tunnel %s\n", | 3210 | "Encrypting %u bytes for %s\n", |
2440 | (unsigned int) payload_size, | 3211 | (unsigned int) payload_size, |
2441 | GCT_2s (t)); | 3212 | GCT_2s (t)); |
2442 | env = GNUNET_MQ_msg_extra (ax_msg, | 3213 | env = GNUNET_MQ_msg_extra (ax_msg, |
2443 | payload_size, | 3214 | payload_size, |
2444 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED); | 3215 | GNUNET_MESSAGE_TYPE_CADET_TUNNEL_ENCRYPTED); |
2445 | t_ax_encrypt (t, | 3216 | t_ax_encrypt (&t->ax, |
2446 | &ax_msg[1], | 3217 | &ax_msg[1], |
2447 | message, | 3218 | message, |
2448 | payload_size); | 3219 | payload_size); |
2449 | ax_msg->Ns = htonl (t->ax.Ns++); | 3220 | GNUNET_STATISTICS_update (stats, |
2450 | ax_msg->PNs = htonl (t->ax.PNs); | 3221 | "# encrypted bytes", |
2451 | GNUNET_CRYPTO_ecdhe_key_get_public (t->ax.DHRs, | 3222 | payload_size, |
2452 | &ax_msg->DHRs); | 3223 | GNUNET_NO); |
2453 | t_h_encrypt (t, | 3224 | ax_msg->ax_header.Ns = htonl (t->ax.Ns++); |
3225 | ax_msg->ax_header.PNs = htonl (t->ax.PNs); | ||
3226 | /* FIXME: we should do this once, not once per message; | ||
3227 | this is a point multiplication, and DHRs does not | ||
3228 | change all the time. */ | ||
3229 | GNUNET_CRYPTO_ecdhe_key_get_public (&t->ax.DHRs, | ||
3230 | &ax_msg->ax_header.DHRs); | ||
3231 | t_h_encrypt (&t->ax, | ||
2454 | ax_msg); | 3232 | ax_msg); |
2455 | t_hmac (&ax_msg->Ns, | 3233 | t_hmac (&ax_msg->ax_header, |
2456 | AX_HEADER_SIZE + payload_size, | 3234 | sizeof (struct GNUNET_CADET_AxHeader) + payload_size, |
2457 | 0, | 3235 | 0, |
2458 | &t->ax.HKs, | 3236 | &t->ax.HKs, |
2459 | &ax_msg->hmac); | 3237 | &ax_msg->hmac); |
@@ -2510,11 +3288,23 @@ GCT_iterate_connections (struct CadetTunnel *t, | |||
2510 | GCT_ConnectionIterator iter, | 3288 | GCT_ConnectionIterator iter, |
2511 | void *iter_cls) | 3289 | void *iter_cls) |
2512 | { | 3290 | { |
2513 | for (struct CadetTConnection *ct = t->connection_head; | 3291 | struct CadetTConnection *n; |
3292 | for (struct CadetTConnection *ct = t->connection_ready_head; | ||
2514 | NULL != ct; | 3293 | NULL != ct; |
2515 | ct = ct->next) | 3294 | ct = n) |
3295 | { | ||
3296 | n = ct->next; | ||
3297 | iter (iter_cls, | ||
3298 | ct); | ||
3299 | } | ||
3300 | for (struct CadetTConnection *ct = t->connection_busy_head; | ||
3301 | NULL != ct; | ||
3302 | ct = n) | ||
3303 | { | ||
3304 | n = ct->next; | ||
2516 | iter (iter_cls, | 3305 | iter (iter_cls, |
2517 | ct->cc); | 3306 | ct); |
3307 | } | ||
2518 | } | 3308 | } |
2519 | 3309 | ||
2520 | 3310 | ||
@@ -2628,10 +3418,7 @@ GCT_debug (const struct CadetTunnel *t, | |||
2628 | GCT_2s (t), | 3418 | GCT_2s (t), |
2629 | estate2s (t->estate), | 3419 | estate2s (t->estate), |
2630 | t->tq_len, | 3420 | t->tq_len, |
2631 | t->num_connections); | 3421 | GCT_count_any_connections (t)); |
2632 | #if DUMP_KEYS_TO_STDERR | ||
2633 | ax_debug (t->ax, level); | ||
2634 | #endif | ||
2635 | LOG2 (level, | 3422 | LOG2 (level, |
2636 | "TTT channels:\n"); | 3423 | "TTT channels:\n"); |
2637 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, | 3424 | GNUNET_CONTAINER_multihashmap32_iterate (t->channels, |
@@ -2639,7 +3426,10 @@ GCT_debug (const struct CadetTunnel *t, | |||
2639 | &level); | 3426 | &level); |
2640 | LOG2 (level, | 3427 | LOG2 (level, |
2641 | "TTT connections:\n"); | 3428 | "TTT connections:\n"); |
2642 | for (iter_c = t->connection_head; NULL != iter_c; iter_c = iter_c->next) | 3429 | for (iter_c = t->connection_ready_head; NULL != iter_c; iter_c = iter_c->next) |
3430 | GCC_debug (iter_c->cc, | ||
3431 | level); | ||
3432 | for (iter_c = t->connection_busy_head; NULL != iter_c; iter_c = iter_c->next) | ||
2643 | GCC_debug (iter_c->cc, | 3433 | GCC_debug (iter_c->cc, |
2644 | level); | 3434 | level); |
2645 | 3435 | ||
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.h b/src/cadet/gnunet-service-cadet_tunnels.h index c867a9e82..4a3619ab6 100644 --- a/src/cadet/gnunet-service-cadet-new_tunnels.h +++ b/src/cadet/gnunet-service-cadet_tunnels.h | |||
@@ -20,7 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * @file cadet/gnunet-service-cadet-new_tunnels.h | 23 | * @file cadet/gnunet-service-cadet_tunnels.h |
24 | * @brief Information we track per tunnel. | 24 | * @brief Information we track per tunnel. |
25 | * @author Bartlomiej Polot | 25 | * @author Bartlomiej Polot |
26 | * @author Christian Grothoff | 26 | * @author Christian Grothoff |
@@ -28,7 +28,7 @@ | |||
28 | #ifndef GNUNET_SERVICE_CADET_TUNNELS_H | 28 | #ifndef GNUNET_SERVICE_CADET_TUNNELS_H |
29 | #define GNUNET_SERVICE_CADET_TUNNELS_H | 29 | #define GNUNET_SERVICE_CADET_TUNNELS_H |
30 | 30 | ||
31 | #include "gnunet-service-cadet-new.h" | 31 | #include "gnunet-service-cadet.h" |
32 | #include "cadet_protocol.h" | 32 | #include "cadet_protocol.h" |
33 | 33 | ||
34 | 34 | ||
@@ -50,29 +50,36 @@ enum CadetTunnelEState | |||
50 | CADET_TUNNEL_KEY_UNINITIALIZED, | 50 | CADET_TUNNEL_KEY_UNINITIALIZED, |
51 | 51 | ||
52 | /** | 52 | /** |
53 | * Ephemeral key sent, waiting for peer's key. | 53 | * KX message sent, waiting for other peer's KX_AUTH. |
54 | */ | 54 | */ |
55 | CADET_TUNNEL_KEY_SENT, | 55 | CADET_TUNNEL_KEY_AX_SENT, |
56 | 56 | ||
57 | /** | 57 | /** |
58 | * Key received and we sent ours back, but we got no traffic yet. | 58 | * KX message received, trying to send back KX_AUTH. |
59 | */ | ||
60 | CADET_TUNNEL_KEY_AX_RECV, | ||
61 | |||
62 | /** | ||
63 | * KX message sent and received, trying to send back KX_AUTH. | ||
64 | */ | ||
65 | CADET_TUNNEL_KEY_AX_SENT_AND_RECV, | ||
66 | |||
67 | /** | ||
68 | * KX received and we sent KX_AUTH back, but we got no traffic yet, | ||
69 | * so we're waiting for either KX_AUTH or ENCRYPED traffic from | ||
70 | * the other peer. | ||
71 | * | ||
59 | * We will not yet send traffic, as this might have been a replay. | 72 | * We will not yet send traffic, as this might have been a replay. |
60 | * The other (initiating) peer should send a CHANNEL_OPEN next | 73 | * The other (initiating) peer should send a CHANNEL_OPEN next |
61 | * anyway. | 74 | * anyway, and then we are in business! |
62 | */ | 75 | */ |
63 | CADET_TUNNEL_KEY_PING, | 76 | CADET_TUNNEL_KEY_AX_AUTH_SENT, |
64 | 77 | ||
65 | /** | 78 | /** |
66 | * Handshake completed: session key available. | 79 | * Handshake completed: session key available. |
67 | */ | 80 | */ |
68 | CADET_TUNNEL_KEY_OK, | 81 | CADET_TUNNEL_KEY_OK |
69 | 82 | ||
70 | /** | ||
71 | * New ephemeral key and ping sent, waiting for pong. Unlike KEY_PING, | ||
72 | * we still have a valid session key and therefore we *can* still send | ||
73 | * traffic on the tunnel. | ||
74 | */ | ||
75 | CADET_TUNNEL_KEY_REKEY | ||
76 | }; | 83 | }; |
77 | 84 | ||
78 | 85 | ||
@@ -112,15 +119,29 @@ GCT_destroy_tunnel_now (struct CadetTunnel *t); | |||
112 | * | 119 | * |
113 | * @param t a tunnel | 120 | * @param t a tunnel |
114 | * @param cid connection identifer to use for the connection | 121 | * @param cid connection identifer to use for the connection |
122 | * @param options options for the connection | ||
115 | * @param path path to use for the connection | 123 | * @param path path to use for the connection |
124 | * @return #GNUNET_OK on success, | ||
125 | * #GNUNET_SYSERR on failure (duplicate connection) | ||
116 | */ | 126 | */ |
117 | void | 127 | int |
118 | GCT_add_inbound_connection (struct CadetTunnel *t, | 128 | GCT_add_inbound_connection (struct CadetTunnel *t, |
119 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | 129 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, |
130 | enum GNUNET_CADET_ChannelOption options, | ||
120 | struct CadetPeerPath *path); | 131 | struct CadetPeerPath *path); |
121 | 132 | ||
122 | 133 | ||
123 | /** | 134 | /** |
135 | * We lost a connection, remove it from our list and clean up | ||
136 | * the connection object itself. | ||
137 | * | ||
138 | * @param ct binding of connection to tunnel of the connection that was lost. | ||
139 | */ | ||
140 | void | ||
141 | GCT_connection_lost (struct CadetTConnection *ct); | ||
142 | |||
143 | |||
144 | /** | ||
124 | * Return the peer to which this tunnel goes. | 145 | * Return the peer to which this tunnel goes. |
125 | * | 146 | * |
126 | * @param t a tunnel | 147 | * @param t a tunnel |
@@ -181,6 +202,19 @@ GCT_send_channel_destroy (struct CadetTunnel *t, | |||
181 | 202 | ||
182 | 203 | ||
183 | /** | 204 | /** |
205 | * Function called when a transmission requested using #GCT_send is done. | ||
206 | * | ||
207 | * @param cls closure | ||
208 | * @param ctn identifier of the connection used for transmission, NULL if | ||
209 | * the transmission failed (to be used to match ACKs to the | ||
210 | * respective connection for connection performance evaluation) | ||
211 | */ | ||
212 | typedef void | ||
213 | (*GCT_SendContinuation)(void *cls, | ||
214 | const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid); | ||
215 | |||
216 | |||
217 | /** | ||
184 | * Sends an already built message on a tunnel, encrypting it and | 218 | * Sends an already built message on a tunnel, encrypting it and |
185 | * choosing the best connection if not provided. | 219 | * choosing the best connection if not provided. |
186 | * | 220 | * |
@@ -188,12 +222,12 @@ GCT_send_channel_destroy (struct CadetTunnel *t, | |||
188 | * @param t Tunnel on which this message is transmitted. | 222 | * @param t Tunnel on which this message is transmitted. |
189 | * @param cont Continuation to call once message is really sent. | 223 | * @param cont Continuation to call once message is really sent. |
190 | * @param cont_cls Closure for @c cont. | 224 | * @param cont_cls Closure for @c cont. |
191 | * @return Handle to cancel message. NULL if @c cont is NULL. | 225 | * @return Handle to cancel message. |
192 | */ | 226 | */ |
193 | struct CadetTunnelQueueEntry * | 227 | struct CadetTunnelQueueEntry * |
194 | GCT_send (struct CadetTunnel *t, | 228 | GCT_send (struct CadetTunnel *t, |
195 | const struct GNUNET_MessageHeader *message, | 229 | const struct GNUNET_MessageHeader *message, |
196 | GNUNET_SCHEDULER_TaskCallback cont, | 230 | GCT_SendContinuation cont, |
197 | void *cont_cls); | 231 | void *cont_cls); |
198 | 232 | ||
199 | 233 | ||
@@ -227,18 +261,18 @@ GCT_count_channels (struct CadetTunnel *t); | |||
227 | * @return number of connections available for the tunnel | 261 | * @return number of connections available for the tunnel |
228 | */ | 262 | */ |
229 | unsigned int | 263 | unsigned int |
230 | GCT_count_any_connections (struct CadetTunnel *t); | 264 | GCT_count_any_connections (const struct CadetTunnel *t); |
231 | 265 | ||
232 | 266 | ||
233 | /** | 267 | /** |
234 | * Iterator over connections. | 268 | * Iterator over connections. |
235 | * | 269 | * |
236 | * @param cls closure | 270 | * @param cls closure |
237 | * @param c one of the connections | 271 | * @param ct one of the connections |
238 | */ | 272 | */ |
239 | typedef void | 273 | typedef void |
240 | (*GCT_ConnectionIterator) (void *cls, | 274 | (*GCT_ConnectionIterator) (void *cls, |
241 | struct CadetConnection *c); | 275 | struct CadetTConnection *ct); |
242 | 276 | ||
243 | 277 | ||
244 | /** | 278 | /** |
@@ -301,6 +335,17 @@ GCT_handle_kx (struct CadetTConnection *ct, | |||
301 | 335 | ||
302 | 336 | ||
303 | /** | 337 | /** |
338 | * Handle KX_AUTH message. | ||
339 | * | ||
340 | * @param ct connection/tunnel combo that received encrypted message | ||
341 | * @param msg the key exchange message | ||
342 | */ | ||
343 | void | ||
344 | GCT_handle_kx_auth (struct CadetTConnection *ct, | ||
345 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg); | ||
346 | |||
347 | |||
348 | /** | ||
304 | * Handle encrypted message. | 349 | * Handle encrypted message. |
305 | * | 350 | * |
306 | * @param ct connection/tunnel combo that received encrypted message | 351 | * @param ct connection/tunnel combo that received encrypted message |
diff --git a/src/cadet/test_cadet.c b/src/cadet/test_cadet.c index 3a1042eba..72df2203c 100644 --- a/src/cadet/test_cadet.c +++ b/src/cadet/test_cadet.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2011 GNUnet e.V. | 3 | Copyright (C) 2011, 2017 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -19,8 +19,9 @@ | |||
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * @file cadet/test_cadet.c | 21 | * @file cadet/test_cadet.c |
22 | * | 22 | * @author Bart Polot |
23 | * @brief Test for the cadet service: retransmission of traffic. | 23 | * @author Christian Grothoff |
24 | * @brief Test for the cadet service using mq API. | ||
24 | */ | 25 | */ |
25 | #include <stdio.h> | 26 | #include <stdio.h> |
26 | #include "platform.h" | 27 | #include "platform.h" |
@@ -31,9 +32,20 @@ | |||
31 | 32 | ||
32 | 33 | ||
33 | /** | 34 | /** |
34 | * How many messages to send | 35 | * Ugly workaround to unify data handlers on incoming and outgoing channels. |
36 | */ | ||
37 | struct CadetTestChannelWrapper | ||
38 | { | ||
39 | /** | ||
40 | * Channel pointer. | ||
41 | */ | ||
42 | struct GNUNET_CADET_Channel *ch; | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * How many messages to send by default. | ||
35 | */ | 47 | */ |
36 | #define TOTAL_PACKETS 500 /* Cannot exceed 64k! */ | 48 | #define TOTAL_PACKETS 500 /* Cannot exceed 64k! */ |
37 | 49 | ||
38 | /** | 50 | /** |
39 | * How long until we give up on connecting the peers? | 51 | * How long until we give up on connecting the peers? |
@@ -41,7 +53,7 @@ | |||
41 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) | 53 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) |
42 | 54 | ||
43 | /** | 55 | /** |
44 | * Time to wait for stuff that should be rather fast | 56 | * Time to wait by default for stuff that should be rather fast. |
45 | */ | 57 | */ |
46 | #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) | 58 | #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20) |
47 | 59 | ||
@@ -64,7 +76,7 @@ static int test; | |||
64 | /** | 76 | /** |
65 | * String with test name | 77 | * String with test name |
66 | */ | 78 | */ |
67 | char *test_name; | 79 | static char *test_name; |
68 | 80 | ||
69 | /** | 81 | /** |
70 | * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic. | 82 | * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic. |
@@ -72,6 +84,16 @@ char *test_name; | |||
72 | static int test_backwards = GNUNET_NO; | 84 | static int test_backwards = GNUNET_NO; |
73 | 85 | ||
74 | /** | 86 | /** |
87 | * How many packets to send. | ||
88 | */ | ||
89 | static unsigned int total_packets; | ||
90 | |||
91 | /** | ||
92 | * Time to wait for fast operations. | ||
93 | */ | ||
94 | static struct GNUNET_TIME_Relative short_time; | ||
95 | |||
96 | /** | ||
75 | * How many events have happened | 97 | * How many events have happened |
76 | */ | 98 | */ |
77 | static int ok; | 99 | static int ok; |
@@ -79,32 +101,32 @@ static int ok; | |||
79 | /** | 101 | /** |
80 | * Number of events expected to conclude the test successfully. | 102 | * Number of events expected to conclude the test successfully. |
81 | */ | 103 | */ |
82 | int ok_goal; | 104 | static int ok_goal; |
83 | 105 | ||
84 | /** | 106 | /** |
85 | * Size of each test packet | 107 | * Size of each test packet's payload |
86 | */ | 108 | */ |
87 | size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t); | 109 | static size_t size_payload = sizeof (uint32_t); |
88 | 110 | ||
89 | /** | 111 | /** |
90 | * Operation to get peer ids. | 112 | * Operation to get peer ids. |
91 | */ | 113 | */ |
92 | struct GNUNET_TESTBED_Operation *t_op[2]; | 114 | static struct GNUNET_TESTBED_Operation *t_op[2]; |
93 | 115 | ||
94 | /** | 116 | /** |
95 | * Peer ids. | 117 | * Peer ids. |
96 | */ | 118 | */ |
97 | struct GNUNET_PeerIdentity *p_id[2]; | 119 | static struct GNUNET_PeerIdentity *p_id[2]; |
98 | 120 | ||
99 | /** | 121 | /** |
100 | * Port ID | 122 | * Port ID |
101 | */ | 123 | */ |
102 | struct GNUNET_HashCode port; | 124 | static struct GNUNET_HashCode port; |
103 | 125 | ||
104 | /** | 126 | /** |
105 | * Peer ids counter. | 127 | * Peer ids counter. |
106 | */ | 128 | */ |
107 | unsigned int p_ids; | 129 | static unsigned int p_ids; |
108 | 130 | ||
109 | /** | 131 | /** |
110 | * Is the setup initialized? | 132 | * Is the setup initialized? |
@@ -157,9 +179,9 @@ static struct GNUNET_SCHEDULER_Task *disconnect_task; | |||
157 | static struct GNUNET_SCHEDULER_Task *test_task; | 179 | static struct GNUNET_SCHEDULER_Task *test_task; |
158 | 180 | ||
159 | /** | 181 | /** |
160 | * Task runnining #data_task(). | 182 | * Task runnining #send_next_msg(). |
161 | */ | 183 | */ |
162 | static struct GNUNET_SCHEDULER_Task *data_job; | 184 | static struct GNUNET_SCHEDULER_Task *send_next_msg_task; |
163 | 185 | ||
164 | /** | 186 | /** |
165 | * Cadet handle for the root peer | 187 | * Cadet handle for the root peer |
@@ -174,7 +196,7 @@ static struct GNUNET_CADET_Handle *h2; | |||
174 | /** | 196 | /** |
175 | * Channel handle for the root peer | 197 | * Channel handle for the root peer |
176 | */ | 198 | */ |
177 | static struct GNUNET_CADET_Channel *ch; | 199 | static struct GNUNET_CADET_Channel *outgoing_ch; |
178 | 200 | ||
179 | /** | 201 | /** |
180 | * Channel handle for the dest peer | 202 | * Channel handle for the dest peer |
@@ -182,17 +204,6 @@ static struct GNUNET_CADET_Channel *ch; | |||
182 | static struct GNUNET_CADET_Channel *incoming_ch; | 204 | static struct GNUNET_CADET_Channel *incoming_ch; |
183 | 205 | ||
184 | /** | 206 | /** |
185 | * Transmit handle for root data calls | ||
186 | */ | ||
187 | static struct GNUNET_CADET_TransmitHandle *th; | ||
188 | |||
189 | /** | ||
190 | * Transmit handle for root data calls | ||
191 | */ | ||
192 | static struct GNUNET_CADET_TransmitHandle *incoming_th; | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Time we started the data transmission (after channel has been established | 207 | * Time we started the data transmission (after channel has been established |
197 | * and initilized). | 208 | * and initilized). |
198 | */ | 209 | */ |
@@ -218,21 +229,32 @@ static unsigned int ka_sent; | |||
218 | */ | 229 | */ |
219 | static unsigned int ka_received; | 230 | static unsigned int ka_received; |
220 | 231 | ||
232 | /** | ||
233 | * How many messages were dropped by CADET because of full buffers? | ||
234 | */ | ||
235 | static unsigned int msg_dropped; | ||
236 | |||
237 | |||
238 | /******************************************************************************/ | ||
239 | |||
240 | |||
241 | /******************************************************************************/ | ||
242 | |||
221 | 243 | ||
222 | /** | 244 | /** |
223 | * Get the client number considered as the "target" or "receiver", depending on | 245 | * Get the channel considered as the "target" or "receiver", depending on |
224 | * the test type and size. | 246 | * the test type and size. |
225 | * | 247 | * |
226 | * @return Peer # of the target client, either 0 (for backward tests) or | 248 | * @return Channel handle of the target client, either 0 (for backward tests) |
227 | * the last peer in the line (for other tests). | 249 | * or the last peer in the line (for other tests). |
228 | */ | 250 | */ |
229 | static unsigned int | 251 | static struct GNUNET_CADET_Channel * |
230 | get_expected_target () | 252 | get_target_channel () |
231 | { | 253 | { |
232 | if (SPEED == test && GNUNET_YES == test_backwards) | 254 | if (SPEED == test && GNUNET_YES == test_backwards) |
233 | return 0; | 255 | return outgoing_ch; |
234 | else | 256 | else |
235 | return peers_requested - 1; | 257 | return incoming_ch; |
236 | } | 258 | } |
237 | 259 | ||
238 | 260 | ||
@@ -245,18 +267,15 @@ show_end_data (void) | |||
245 | static struct GNUNET_TIME_Absolute end_time; | 267 | static struct GNUNET_TIME_Absolute end_time; |
246 | static struct GNUNET_TIME_Relative total_time; | 268 | static struct GNUNET_TIME_Relative total_time; |
247 | 269 | ||
248 | end_time = GNUNET_TIME_absolute_get(); | 270 | end_time = GNUNET_TIME_absolute_get (); |
249 | total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time); | 271 | total_time = GNUNET_TIME_absolute_get_difference (start_time, end_time); |
250 | FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name); | 272 | FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name); |
251 | FPRINTF (stderr, "Test time %s\n", | 273 | FPRINTF (stderr, "Test time %s\n", |
252 | GNUNET_STRINGS_relative_time_to_string (total_time, | 274 | GNUNET_STRINGS_relative_time_to_string (total_time, GNUNET_YES)); |
253 | GNUNET_YES)); | 275 | FPRINTF (stderr, "Test bandwidth: %f kb/s\n", 4 * total_packets * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms |
254 | FPRINTF (stderr, "Test bandwidth: %f kb/s\n", | 276 | FPRINTF (stderr, "Test throughput: %f packets/s\n\n", total_packets * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms |
255 | 4 * TOTAL_PACKETS * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms | ||
256 | FPRINTF (stderr, "Test throughput: %f packets/s\n\n", | ||
257 | TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms | ||
258 | GAUGER ("CADET", test_name, | 277 | GAUGER ("CADET", test_name, |
259 | TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000), | 278 | total_packets * 1000.0 / (total_time.rel_value_us / 1000), |
260 | "packets/s"); | 279 | "packets/s"); |
261 | } | 280 | } |
262 | 281 | ||
@@ -275,29 +294,19 @@ disconnect_cadet_peers (void *cls) | |||
275 | 294 | ||
276 | disconnect_task = NULL; | 295 | disconnect_task = NULL; |
277 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 296 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
278 | "disconnecting cadet service of peers, called from line %ld\n", | 297 | "disconnecting cadet service of peers, called from line %ld\n", |
279 | line); | 298 | line); |
280 | for (i = 0; i < 2; i++) | 299 | for (i = 0; i < 2; i++) |
281 | { | 300 | { |
282 | GNUNET_TESTBED_operation_done (t_op[i]); | 301 | GNUNET_TESTBED_operation_done (t_op[i]); |
283 | } | 302 | } |
284 | if (NULL != ch) | 303 | if (NULL != outgoing_ch) |
285 | { | 304 | { |
286 | if (NULL != th) | 305 | GNUNET_CADET_channel_destroy (outgoing_ch); |
287 | { | 306 | outgoing_ch = NULL; |
288 | GNUNET_CADET_notify_transmit_ready_cancel (th); | ||
289 | th = NULL; | ||
290 | } | ||
291 | GNUNET_CADET_channel_destroy (ch); | ||
292 | ch = NULL; | ||
293 | } | 307 | } |
294 | if (NULL != incoming_ch) | 308 | if (NULL != incoming_ch) |
295 | { | 309 | { |
296 | if (NULL != incoming_th) | ||
297 | { | ||
298 | GNUNET_CADET_notify_transmit_ready_cancel (incoming_th); | ||
299 | incoming_th = NULL; | ||
300 | } | ||
301 | GNUNET_CADET_channel_destroy (incoming_ch); | 310 | GNUNET_CADET_channel_destroy (incoming_ch); |
302 | incoming_ch = NULL; | 311 | incoming_ch = NULL; |
303 | } | 312 | } |
@@ -316,10 +325,10 @@ static void | |||
316 | shutdown_task (void *cls) | 325 | shutdown_task (void *cls) |
317 | { | 326 | { |
318 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); | 327 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); |
319 | if (NULL != data_job) | 328 | if (NULL != send_next_msg_task) |
320 | { | 329 | { |
321 | GNUNET_SCHEDULER_cancel (data_job); | 330 | GNUNET_SCHEDULER_cancel (send_next_msg_task); |
322 | data_job = NULL; | 331 | send_next_msg_task = NULL; |
323 | } | 332 | } |
324 | if (NULL != test_task) | 333 | if (NULL != test_task) |
325 | { | 334 | { |
@@ -329,8 +338,8 @@ shutdown_task (void *cls) | |||
329 | if (NULL != disconnect_task) | 338 | if (NULL != disconnect_task) |
330 | { | 339 | { |
331 | GNUNET_SCHEDULER_cancel (disconnect_task); | 340 | GNUNET_SCHEDULER_cancel (disconnect_task); |
332 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, | 341 | disconnect_task = |
333 | (void *) __LINE__); | 342 | GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) __LINE__); |
334 | } | 343 | } |
335 | } | 344 | } |
336 | 345 | ||
@@ -349,14 +358,16 @@ stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) | |||
349 | { | 358 | { |
350 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " KA sent: %u, KA received: %u\n", | 359 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " KA sent: %u, KA received: %u\n", |
351 | ka_sent, ka_received); | 360 | ka_sent, ka_received); |
352 | if (KEEPALIVE == test && (ka_sent < 2 || ka_sent > ka_received + 1)) | 361 | if ((KEEPALIVE == test) && ((ka_sent < 2) || (ka_sent > ka_received + 1))) |
362 | { | ||
363 | GNUNET_break (0); | ||
353 | ok--; | 364 | ok--; |
365 | } | ||
354 | GNUNET_TESTBED_operation_done (stats_op); | 366 | GNUNET_TESTBED_operation_done (stats_op); |
355 | 367 | ||
356 | if (NULL != disconnect_task) | 368 | if (NULL != disconnect_task) |
357 | GNUNET_SCHEDULER_cancel (disconnect_task); | 369 | GNUNET_SCHEDULER_cancel (disconnect_task); |
358 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, | 370 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, cls); |
359 | cls); | ||
360 | } | 371 | } |
361 | 372 | ||
362 | 373 | ||
@@ -372,29 +383,27 @@ stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) | |||
372 | * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration | 383 | * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration |
373 | */ | 384 | */ |
374 | static int | 385 | static int |
375 | stats_iterator (void *cls, | 386 | stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer, |
376 | const struct GNUNET_TESTBED_Peer *peer, | 387 | const char *subsystem, const char *name, uint64_t value, |
377 | const char *subsystem, | ||
378 | const char *name, | ||
379 | uint64_t value, | ||
380 | int is_persistent) | 388 | int is_persistent) |
381 | { | 389 | { |
382 | static const char *s_sent = "# keepalives sent"; | 390 | static const char *s_sent = "# keepalives sent"; |
383 | static const char *s_recv = "# keepalives received"; | 391 | static const char *s_recv = "# keepalives received"; |
392 | static const char *rdrops = "# messages dropped due to full buffer"; | ||
393 | static const char *cdrops = "# messages dropped due to slow client"; | ||
384 | uint32_t i; | 394 | uint32_t i; |
385 | 395 | ||
386 | i = GNUNET_TESTBED_get_index (peer); | 396 | i = GNUNET_TESTBED_get_index (peer); |
387 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 397 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "STATS PEER %u - %s [%s]: %llu\n", i, |
388 | "STATS PEER %u - %s [%s]: %llu\n", | 398 | subsystem, name, (unsigned long long) value); |
389 | i, | ||
390 | subsystem, | ||
391 | name, | ||
392 | (unsigned long long) value); | ||
393 | if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i) | 399 | if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i) |
394 | ka_sent = value; | 400 | ka_sent = value; |
395 | 401 | if (0 == strncmp (s_recv, name, strlen (s_recv)) && peers_requested - 1 == i) | |
396 | if (0 == strncmp(s_recv, name, strlen (s_recv)) && peers_requested - 1 == i) | ||
397 | ka_received = value; | 402 | ka_received = value; |
403 | if (0 == strncmp (rdrops, name, strlen (rdrops))) | ||
404 | msg_dropped += value; | ||
405 | if (0 == strncmp (cdrops, name, strlen (cdrops))) | ||
406 | msg_dropped += value; | ||
398 | 407 | ||
399 | return GNUNET_OK; | 408 | return GNUNET_OK; |
400 | } | 409 | } |
@@ -403,7 +412,7 @@ stats_iterator (void *cls, | |||
403 | /** | 412 | /** |
404 | * Task to gather all statistics. | 413 | * Task to gather all statistics. |
405 | * | 414 | * |
406 | * @param cls Closure (NULL). | 415 | * @param cls Closure (line from which the task was scheduled). |
407 | */ | 416 | */ |
408 | static void | 417 | static void |
409 | gather_stats_and_exit (void *cls) | 418 | gather_stats_and_exit (void *cls) |
@@ -412,21 +421,20 @@ gather_stats_and_exit (void *cls) | |||
412 | 421 | ||
413 | disconnect_task = NULL; | 422 | disconnect_task = NULL; |
414 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 423 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
415 | "gathering statistics from line %d\n", | 424 | "gathering statistics from line %ld\n", |
416 | (int) l); | 425 | l); |
417 | if (NULL != ch) | 426 | if (NULL != outgoing_ch) |
418 | { | 427 | { |
419 | if (NULL != th) | 428 | GNUNET_CADET_channel_destroy (outgoing_ch); |
420 | { | 429 | outgoing_ch = NULL; |
421 | GNUNET_CADET_notify_transmit_ready_cancel (th); | ||
422 | th = NULL; | ||
423 | } | ||
424 | GNUNET_CADET_channel_destroy (ch); | ||
425 | ch = NULL; | ||
426 | } | 430 | } |
427 | stats_op = GNUNET_TESTBED_get_statistics (peers_running, testbed_peers, | 431 | stats_op = GNUNET_TESTBED_get_statistics (peers_running, |
428 | "cadet", NULL, | 432 | testbed_peers, |
429 | stats_iterator, stats_cont, cls); | 433 | "cadet", |
434 | NULL, | ||
435 | &stats_iterator, | ||
436 | stats_cont, | ||
437 | cls); | ||
430 | } | 438 | } |
431 | 439 | ||
432 | 440 | ||
@@ -439,165 +447,154 @@ gather_stats_and_exit (void *cls) | |||
439 | static void | 447 | static void |
440 | abort_test (long line) | 448 | abort_test (long line) |
441 | { | 449 | { |
442 | if (disconnect_task != NULL) | 450 | if (NULL != disconnect_task) |
443 | { | 451 | { |
444 | GNUNET_SCHEDULER_cancel (disconnect_task); | 452 | GNUNET_SCHEDULER_cancel (disconnect_task); |
445 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting test from %ld\n", line); | 453 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Aborting test from %ld\n", line); |
446 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, | 454 | disconnect_task = |
447 | (void *) line); | 455 | GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, (void *) line); |
448 | } | 456 | } |
449 | } | 457 | } |
450 | 458 | ||
451 | /** | ||
452 | * Transmit ready callback. | ||
453 | * | ||
454 | * @param cls Closure (message type). | ||
455 | * @param size Size of the tranmist buffer. | ||
456 | * @param buf Pointer to the beginning of the buffer. | ||
457 | * | ||
458 | * @return Number of bytes written to buf. | ||
459 | */ | ||
460 | static size_t | ||
461 | tmt_rdy (void *cls, size_t size, void *buf); | ||
462 | |||
463 | 459 | ||
464 | /** | 460 | /** |
465 | * Task to request a new data transmission. | 461 | * Send a message on the channel with the appropriate size and payload. |
462 | * | ||
463 | * Update the appropriate *_sent counter. | ||
466 | * | 464 | * |
467 | * @param cls Closure (peer #). | 465 | * @param channel Channel to send the message on. |
468 | */ | 466 | */ |
469 | static void | 467 | static void |
470 | data_task (void *cls) | 468 | send_test_message (struct GNUNET_CADET_Channel *channel) |
471 | { | 469 | { |
472 | struct GNUNET_CADET_Channel *channel; | 470 | struct GNUNET_MQ_Envelope *env; |
473 | static struct GNUNET_CADET_TransmitHandle **pth; | 471 | struct GNUNET_MessageHeader *msg; |
474 | long src; | 472 | uint32_t *data; |
473 | int payload; | ||
474 | int size; | ||
475 | 475 | ||
476 | data_job = NULL; | 476 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
477 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n"); | 477 | "Sending test message on channel %p\n", |
478 | if (GNUNET_YES == test_backwards) | 478 | channel); |
479 | { | 479 | size = size_payload; |
480 | channel = incoming_ch; | 480 | if (GNUNET_NO == initialized) |
481 | pth = &incoming_th; | ||
482 | src = peers_requested - 1; | ||
483 | } | ||
484 | else | ||
485 | { | 481 | { |
486 | channel = ch; | 482 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending INITIALIZER\n"); |
487 | pth = &th; | 483 | size += 1000; |
488 | src = 0; | 484 | payload = data_sent; |
485 | if (SPEED_ACK == test) // FIXME unify SPEED_ACK with an initializer | ||
486 | data_sent++; | ||
489 | } | 487 | } |
490 | 488 | else if (SPEED == test || SPEED_ACK == test) | |
491 | GNUNET_assert (NULL != channel); | ||
492 | GNUNET_assert (NULL == *pth); | ||
493 | |||
494 | *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, | ||
495 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
496 | size_payload + data_sent, | ||
497 | &tmt_rdy, (void *) src); | ||
498 | if (NULL == *pth) | ||
499 | { | 489 | { |
500 | unsigned long i = (unsigned long) cls; | 490 | if (get_target_channel() == channel) |
501 | |||
502 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Retransmission\n"); | ||
503 | if (0 == i) | ||
504 | { | 491 | { |
505 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " in 1 ms\n"); | 492 | payload = ack_sent; |
506 | data_job = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, | 493 | size += ack_sent; |
507 | &data_task, (void *) 1L); | 494 | ack_sent++; |
495 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
496 | "Sending ACK %u [%d bytes]\n", | ||
497 | payload, size); | ||
508 | } | 498 | } |
509 | else | 499 | else |
510 | { | 500 | { |
511 | i++; | 501 | payload = data_sent; |
512 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 502 | size += data_sent; |
513 | "in %llu ms\n", | 503 | data_sent++; |
514 | (unsigned long long) i); | 504 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
515 | data_job = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, | 505 | "Sending DATA %u [%d bytes]\n", |
516 | i), | 506 | data_sent, size); |
517 | &data_task, (void *) i); | ||
518 | } | 507 | } |
519 | } | 508 | } |
520 | } | 509 | else if (FORWARD == test) |
510 | { | ||
511 | payload = ack_sent; | ||
512 | } | ||
513 | else if (P2P_SIGNAL == test) | ||
514 | { | ||
515 | payload = data_sent; | ||
516 | } | ||
517 | else | ||
518 | { | ||
519 | GNUNET_assert (0); | ||
520 | } | ||
521 | env = GNUNET_MQ_msg_extra (msg, size, GNUNET_MESSAGE_TYPE_DUMMY); | ||
521 | 522 | ||
523 | data = (uint32_t *) &msg[1]; | ||
524 | *data = htonl (payload); | ||
525 | GNUNET_MQ_send (GNUNET_CADET_get_mq (channel), env); | ||
526 | } | ||
522 | 527 | ||
523 | /** | 528 | /** |
524 | * Transmit ready callback | 529 | * Task to request a new data transmission in a SPEED test, without waiting |
530 | * for previous messages to be sent/arrrive. | ||
525 | * | 531 | * |
526 | * @param cls Closure (peer # which is sending the data). | 532 | * @param cls Closure (unused). |
527 | * @param size Size of the buffer we have. | ||
528 | * @param buf Buffer to copy data to. | ||
529 | */ | 533 | */ |
530 | static size_t | 534 | static void |
531 | tmt_rdy (void *cls, size_t size, void *buf) | 535 | send_next_msg (void *cls) |
532 | { | 536 | { |
533 | struct GNUNET_MessageHeader *msg = buf; | 537 | struct GNUNET_CADET_Channel *channel; |
534 | size_t msg_size; | ||
535 | uint32_t *data; | ||
536 | long id = (long) cls; | ||
537 | unsigned int counter; | ||
538 | 538 | ||
539 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 539 | send_next_msg_task = NULL; |
540 | "tmt_rdy on %ld, filling buffer\n", | 540 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending next message: %d\n", data_sent); |
541 | id); | 541 | |
542 | if (0 == id) | 542 | channel = GNUNET_YES == test_backwards ? incoming_ch : outgoing_ch; |
543 | th = NULL; | 543 | GNUNET_assert (NULL != channel); |
544 | else if ((peers_requested - 1) == id) | 544 | GNUNET_assert (SPEED == test); |
545 | incoming_th = NULL; | 545 | send_test_message (channel); |
546 | else | 546 | if (data_sent < total_packets) |
547 | GNUNET_assert (0); | ||
548 | counter = get_expected_target () == id ? ack_sent : data_sent; | ||
549 | msg_size = size_payload + counter; | ||
550 | GNUNET_assert (msg_size > sizeof (struct GNUNET_MessageHeader)); | ||
551 | if ( (size < msg_size) || | ||
552 | (NULL == buf) ) | ||
553 | { | ||
554 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
555 | "size %u, buf %p, data_sent %u, ack_received %u\n", | ||
556 | (unsigned int) size, | ||
557 | buf, | ||
558 | data_sent, | ||
559 | ack_received); | ||
560 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ok %u, ok goal %u\n", ok, ok_goal); | ||
561 | GNUNET_break (ok >= ok_goal - 2); | ||
562 | |||
563 | return 0; | ||
564 | } | ||
565 | msg->size = htons (msg_size); | ||
566 | msg->type = htons (GNUNET_MESSAGE_TYPE_DUMMY); | ||
567 | data = (uint32_t *) &msg[1]; | ||
568 | *data = htonl (counter); | ||
569 | if (GNUNET_NO == initialized) | ||
570 | { | 547 | { |
548 | /* SPEED test: Send all messages as soon as possible */ | ||
571 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 549 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
572 | "sending initializer\n"); | 550 | "Scheduling message %d\n", |
573 | msg_size = size_payload + 1000; | 551 | data_sent + 1); |
574 | msg->size = htons (msg_size); | 552 | send_next_msg_task = |
575 | if (SPEED_ACK == test) | 553 | GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS, |
576 | data_sent++; | 554 | &send_next_msg, |
555 | NULL); | ||
577 | } | 556 | } |
578 | else if ( (SPEED == test) || | 557 | } |
579 | (SPEED_ACK == test) ) | 558 | |
559 | |||
560 | /** | ||
561 | * Every few messages cancel the timeout task and re-schedule it again, to | ||
562 | * avoid timing out when traffic keeps coming. | ||
563 | * | ||
564 | * @param line Code line number to log if a timeout occurs. | ||
565 | */ | ||
566 | static void | ||
567 | reschedule_timeout_task (long line) | ||
568 | { | ||
569 | if ((ok % 10) == 0) | ||
580 | { | 570 | { |
581 | if (get_expected_target() == id) | 571 | if (NULL != disconnect_task) |
582 | ack_sent++; | ||
583 | else | ||
584 | data_sent++; | ||
585 | counter++; | ||
586 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
587 | " Sent message %u size %u\n", | ||
588 | counter, | ||
589 | (unsigned int) msg_size); | ||
590 | if ( (data_sent < TOTAL_PACKETS) && | ||
591 | (SPEED == test) ) | ||
592 | { | 572 | { |
593 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 573 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
594 | " Scheduling message %d\n", | 574 | " reschedule timeout every 10 messages\n"); |
595 | counter + 1); | 575 | GNUNET_SCHEDULER_cancel (disconnect_task); |
596 | data_job = GNUNET_SCHEDULER_add_now (&data_task, NULL); | 576 | disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time, |
577 | &gather_stats_and_exit, | ||
578 | (void *) line); | ||
597 | } | 579 | } |
598 | } | 580 | } |
581 | } | ||
599 | 582 | ||
600 | return msg_size; | 583 | |
584 | /** | ||
585 | * Check if payload is sane (size contains payload). | ||
586 | * | ||
587 | * @param cls should match #ch | ||
588 | * @param message The actual message. | ||
589 | * @return #GNUNET_OK to keep the channel open, | ||
590 | * #GNUNET_SYSERR to close it (signal serious error). | ||
591 | */ | ||
592 | static int | ||
593 | check_data (void *cls, const struct GNUNET_MessageHeader *message) | ||
594 | { | ||
595 | if (sizeof (struct GNUNET_MessageHeader) >= ntohs (message->size)) | ||
596 | return GNUNET_SYSERR; | ||
597 | return GNUNET_OK; /* all is well-formed */ | ||
601 | } | 598 | } |
602 | 599 | ||
603 | 600 | ||
@@ -605,75 +602,50 @@ tmt_rdy (void *cls, size_t size, void *buf) | |||
605 | * Function is called whenever a message is received. | 602 | * Function is called whenever a message is received. |
606 | * | 603 | * |
607 | * @param cls closure (set from GNUNET_CADET_connect(), peer number) | 604 | * @param cls closure (set from GNUNET_CADET_connect(), peer number) |
608 | * @param channel connection to the other end | ||
609 | * @param channel_ctx place to store local state associated with the channel | ||
610 | * @param message the actual message | 605 | * @param message the actual message |
611 | * @return #GNUNET_OK to keep the connection open, | ||
612 | * #GNUNET_SYSERR to close it (signal serious error) | ||
613 | */ | 606 | */ |
614 | static int | 607 | static void |
615 | data_callback (void *cls, | 608 | handle_data (void *cls, const struct GNUNET_MessageHeader *message) |
616 | struct GNUNET_CADET_Channel *channel, | ||
617 | void **channel_ctx, | ||
618 | const struct GNUNET_MessageHeader *message) | ||
619 | { | 609 | { |
620 | struct GNUNET_CADET_TransmitHandle **pth; | 610 | struct CadetTestChannelWrapper *ch = cls; |
621 | long client = (long) cls; | 611 | struct GNUNET_CADET_Channel *channel = ch->ch; |
622 | long expected_target_client; | ||
623 | uint32_t *data; | 612 | uint32_t *data; |
624 | uint32_t payload; | 613 | uint32_t payload; |
625 | unsigned int counter; | 614 | int *counter; |
626 | 615 | ||
627 | ok++; | 616 | ok++; |
628 | counter = get_expected_target () == client ? data_received : ack_received; | ||
629 | |||
630 | GNUNET_CADET_receive_done (channel); | 617 | GNUNET_CADET_receive_done (channel); |
618 | counter = get_target_channel () == channel ? &data_received : &ack_received; | ||
631 | 619 | ||
632 | if ((ok % 10) == 0) | 620 | reschedule_timeout_task ((long) __LINE__); |
621 | |||
622 | if (channel == outgoing_ch) | ||
633 | { | 623 | { |
634 | if (NULL != disconnect_task) | 624 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message.\n"); |
635 | { | ||
636 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
637 | " reschedule timeout\n"); | ||
638 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
639 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
640 | &gather_stats_and_exit, | ||
641 | (void *) __LINE__); | ||
642 | } | ||
643 | } | 625 | } |
644 | 626 | else if (channel == incoming_ch) | |
645 | switch (client) | 627 | { |
628 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client got a message.\n"); | ||
629 | } | ||
630 | else | ||
646 | { | 631 | { |
647 | case 0L: | 632 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unknown channel %p.\n", channel); |
648 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n"); | ||
649 | GNUNET_assert (channel == ch); | ||
650 | pth = &th; | ||
651 | break; | ||
652 | case 1L: | ||
653 | case 4L: | ||
654 | GNUNET_assert (client == peers_requested - 1); | ||
655 | GNUNET_assert (channel == incoming_ch); | ||
656 | pth = &incoming_th; | ||
657 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client %ld got a message.\n", | ||
658 | client); | ||
659 | break; | ||
660 | default: | ||
661 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Client %ld not valid.\n", client); | ||
662 | GNUNET_assert (0); | 633 | GNUNET_assert (0); |
663 | } | 634 | } |
635 | |||
664 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal); | 636 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal); |
665 | data = (uint32_t *) &message[1]; | 637 | data = (uint32_t *) &message[1]; |
666 | payload = ntohl (*data); | 638 | payload = ntohl (*data); |
667 | if (payload == counter) | 639 | if (payload == *counter) |
668 | { | 640 | { |
669 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload); | 641 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload); |
670 | } | 642 | } |
671 | else | 643 | else |
672 | { | 644 | { |
673 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " payload %u, expected: %u\n", | 645 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
674 | payload, counter); | 646 | " payload %u, expected: %u\n", |
647 | payload, *counter); | ||
675 | } | 648 | } |
676 | expected_target_client = get_expected_target (); | ||
677 | 649 | ||
678 | if (GNUNET_NO == initialized) | 650 | if (GNUNET_NO == initialized) |
679 | { | 651 | { |
@@ -681,188 +653,152 @@ data_callback (void *cls, | |||
681 | start_time = GNUNET_TIME_absolute_get (); | 653 | start_time = GNUNET_TIME_absolute_get (); |
682 | if (SPEED == test) | 654 | if (SPEED == test) |
683 | { | 655 | { |
684 | GNUNET_assert (peers_requested - 1 == client); | 656 | GNUNET_assert (incoming_ch == channel); |
685 | data_job = GNUNET_SCHEDULER_add_now (&data_task, NULL); | 657 | send_next_msg_task = GNUNET_SCHEDULER_add_now (&send_next_msg, NULL); |
686 | return GNUNET_OK; | 658 | return; |
687 | } | 659 | } |
688 | } | 660 | } |
689 | 661 | ||
690 | counter++; | 662 | (*counter)++; |
691 | if (client == expected_target_client) /* Normally 4 */ | 663 | if (get_target_channel () == channel) /* Got "data" */ |
692 | { | 664 | { |
693 | data_received++; | ||
694 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received); | 665 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received); |
695 | if (SPEED != test || (ok_goal - 2) == ok) | 666 | if (SPEED != test || (ok_goal - 2) == ok) |
696 | { | 667 | { |
697 | /* Send ACK */ | 668 | /* Send ACK */ |
698 | GNUNET_assert (NULL == *pth); | 669 | send_test_message (channel); |
699 | *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, | 670 | return; |
700 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
701 | size_payload + ack_sent, | ||
702 | &tmt_rdy, (void *) client); | ||
703 | return GNUNET_OK; | ||
704 | } | 671 | } |
705 | else | 672 | else |
706 | { | 673 | { |
707 | if (data_received < TOTAL_PACKETS) | 674 | if (data_received < total_packets) |
708 | return GNUNET_OK; | 675 | return; |
709 | } | 676 | } |
710 | } | 677 | } |
711 | else /* Normally 0 */ | 678 | else /* Got "ack" */ |
712 | { | 679 | { |
713 | if (SPEED_ACK == test || SPEED == test) | 680 | if (SPEED_ACK == test || SPEED == test) |
714 | { | 681 | { |
715 | ack_received++; | ||
716 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received); | 682 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received); |
717 | /* send more data */ | 683 | /* Send more data */ |
718 | GNUNET_assert (NULL == *pth); | 684 | send_test_message (channel); |
719 | *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, | 685 | if (ack_received < total_packets && SPEED != test) |
720 | GNUNET_TIME_UNIT_FOREVER_REL, | 686 | return; |
721 | size_payload + data_sent, | ||
722 | &tmt_rdy, (void *) client); | ||
723 | if (ack_received < TOTAL_PACKETS && SPEED != test) | ||
724 | return GNUNET_OK; | ||
725 | if (ok == 2 && SPEED == test) | 687 | if (ok == 2 && SPEED == test) |
726 | return GNUNET_OK; | 688 | return; |
727 | show_end_data(); | 689 | show_end_data (); |
728 | } | 690 | } |
729 | if (test == P2P_SIGNAL) | 691 | if (test == P2P_SIGNAL) |
730 | { | 692 | { |
731 | if (NULL != incoming_th) | ||
732 | { | ||
733 | GNUNET_CADET_notify_transmit_ready_cancel (incoming_th); | ||
734 | incoming_th = NULL; | ||
735 | } | ||
736 | GNUNET_CADET_channel_destroy (incoming_ch); | 693 | GNUNET_CADET_channel_destroy (incoming_ch); |
737 | incoming_ch = NULL; | 694 | incoming_ch = NULL; |
738 | } | 695 | } |
739 | else | 696 | else |
740 | { | 697 | { |
741 | if (NULL != th) | 698 | GNUNET_CADET_channel_destroy (outgoing_ch); |
742 | { | 699 | outgoing_ch = NULL; |
743 | GNUNET_CADET_notify_transmit_ready_cancel (th); | ||
744 | th = NULL; | ||
745 | } | ||
746 | GNUNET_CADET_channel_destroy (ch); | ||
747 | ch = NULL; | ||
748 | } | 700 | } |
749 | } | 701 | } |
750 | |||
751 | return GNUNET_OK; | ||
752 | } | 702 | } |
753 | 703 | ||
754 | 704 | ||
755 | /** | 705 | /** |
756 | * Data handlers for every message type of CADET's payload. | 706 | * Method called whenever a peer connects to a port in MQ-based CADET. |
757 | * {callback_function, message_type, size_expected} | ||
758 | */ | ||
759 | static struct GNUNET_CADET_MessageHandler handlers[] = { | ||
760 | {&data_callback, | ||
761 | GNUNET_MESSAGE_TYPE_DUMMY, | ||
762 | sizeof (struct GNUNET_MessageHeader)}, | ||
763 | {NULL, 0, 0} | ||
764 | }; | ||
765 | |||
766 | |||
767 | /** | ||
768 | * Method called whenever another peer has added us to a channel | ||
769 | * the other peer initiated. | ||
770 | * | 707 | * |
771 | * @param cls Closure. | 708 | * @param cls Closure from #GNUNET_CADET_open_port (peer # as long). |
772 | * @param channel New handle to the channel. | 709 | * @param channel New handle to the channel. |
773 | * @param initiator Peer that started the channel. | 710 | * @param source Peer that started this channel. |
774 | * @param port Port this channel is connected to. | 711 | * @return Closure for the incoming @a channel. It's given to: |
775 | * @param options channel option flags | 712 | * - The #GNUNET_CADET_DisconnectEventHandler (given to |
776 | * @return Initial channel context for the channel | 713 | * #GNUNET_CADET_open_port) when the channel dies. |
777 | * (can be NULL -- that's not an error). | 714 | * - Each the #GNUNET_MQ_MessageCallback handlers for each message |
715 | * received on the @a channel. | ||
778 | */ | 716 | */ |
779 | static void * | 717 | static void * |
780 | incoming_channel (void *cls, | 718 | connect_handler (void *cls, struct GNUNET_CADET_Channel *channel, |
781 | struct GNUNET_CADET_Channel *channel, | 719 | const struct GNUNET_PeerIdentity *source) |
782 | const struct GNUNET_PeerIdentity *initiator, | ||
783 | const struct GNUNET_HashCode *port, | ||
784 | enum GNUNET_CADET_ChannelOption options) | ||
785 | { | 720 | { |
721 | struct CadetTestChannelWrapper *ch; | ||
722 | long peer = (long) cls; | ||
723 | |||
786 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 724 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, |
787 | "Incoming channel from %s to peer %d:%s\n", | 725 | "Incoming channel from %s to %ld: %p\n", |
788 | GNUNET_i2s (initiator), | 726 | GNUNET_i2s (source), peer, channel); |
789 | (int) (long) cls, GNUNET_h2s (port)); | ||
790 | ok++; | 727 | ok++; |
791 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); | 728 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); |
792 | if ((long) cls == peers_requested - 1) | 729 | if (peer == peers_requested - 1) |
793 | { | 730 | { |
794 | if (NULL != incoming_ch) | 731 | if (NULL != incoming_ch) |
795 | { | 732 | { |
796 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 733 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
797 | "Duplicate incoming channel for client %lu\n", | 734 | "Duplicate incoming channel for client %lu\n", (long) cls); |
798 | (long) cls); | 735 | GNUNET_assert (0); |
799 | GNUNET_break(0); | ||
800 | } | 736 | } |
801 | incoming_ch = channel; | 737 | incoming_ch = channel; |
802 | } | 738 | } |
803 | else | 739 | else |
804 | { | 740 | { |
805 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 741 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
806 | "Incoming channel for unknown client %lu\n", (long) cls); | 742 | "Incoming channel for unexpected peer #%lu\n", (long) cls); |
807 | GNUNET_break(0); | 743 | GNUNET_assert (0); |
808 | } | 744 | } |
809 | if (NULL != disconnect_task) | 745 | if (NULL != disconnect_task) |
810 | { | 746 | { |
811 | GNUNET_SCHEDULER_cancel (disconnect_task); | 747 | GNUNET_SCHEDULER_cancel (disconnect_task); |
812 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | 748 | disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time, |
813 | &gather_stats_and_exit, | 749 | &gather_stats_and_exit, |
814 | (void *) __LINE__); | 750 | (void *) __LINE__); |
815 | } | 751 | } |
816 | 752 | ||
817 | return NULL; | 753 | /* TODO: cannot return channel as-is, in order to unify the data handlers */ |
754 | ch = GNUNET_new (struct CadetTestChannelWrapper); | ||
755 | ch->ch = channel; | ||
756 | |||
757 | return ch; | ||
818 | } | 758 | } |
819 | 759 | ||
820 | 760 | ||
821 | /** | 761 | /** |
822 | * Function called whenever an inbound channel is destroyed. Should clean up | 762 | * Function called whenever an MQ-channel is destroyed, even if the destruction |
823 | * any associated state. | 763 | * was requested by #GNUNET_CADET_channel_destroy. |
764 | * It must NOT call #GNUNET_CADET_channel_destroy on the channel. | ||
824 | * | 765 | * |
825 | * @param cls closure (set from GNUNET_CADET_connect, peer number) | 766 | * It should clean up any associated state, including cancelling any pending |
826 | * @param channel connection to the other end (henceforth invalid) | 767 | * transmission on this channel. |
827 | * @param channel_ctx place where local state associated | 768 | * |
828 | * with the channel is stored | 769 | * @param cls Channel closure (channel wrapper). |
770 | * @param channel Connection to the other end (henceforth invalid). | ||
829 | */ | 771 | */ |
830 | static void | 772 | static void |
831 | channel_cleaner (void *cls, | 773 | disconnect_handler (void *cls, const struct GNUNET_CADET_Channel *channel) |
832 | const struct GNUNET_CADET_Channel *channel, | ||
833 | void *channel_ctx) | ||
834 | { | 774 | { |
835 | long i = (long) cls; | 775 | struct CadetTestChannelWrapper *ch_w = cls; |
836 | 776 | ||
837 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 777 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Channel disconnected\n"); |
838 | "Incoming channel disconnected at peer %ld\n", | 778 | GNUNET_assert (ch_w->ch == channel); |
839 | i); | 779 | if (channel == incoming_ch) |
840 | if (peers_running - 1 == i) | ||
841 | { | 780 | { |
842 | ok++; | 781 | ok++; |
843 | GNUNET_break (channel == incoming_ch); | ||
844 | incoming_ch = NULL; | 782 | incoming_ch = NULL; |
845 | } | 783 | } |
846 | else if (0L == i) | 784 | else if (outgoing_ch == channel |
785 | ) | ||
847 | { | 786 | { |
848 | if (P2P_SIGNAL == test) | 787 | if (P2P_SIGNAL == test) |
849 | { | 788 | { |
850 | ok++; | 789 | ok++; |
851 | } | 790 | } |
852 | GNUNET_break (channel == ch); | 791 | outgoing_ch = NULL; |
853 | ch = NULL; | ||
854 | } | 792 | } |
855 | else | 793 | else |
856 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 794 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown channel! %p\n", channel); |
857 | "Unknown peer! %d\n", | ||
858 | (int) i); | ||
859 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); | 795 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); |
860 | 796 | ||
861 | if (NULL != disconnect_task) | 797 | if (NULL != disconnect_task) |
862 | { | 798 | { |
863 | GNUNET_SCHEDULER_cancel (disconnect_task); | 799 | GNUNET_SCHEDULER_cancel (disconnect_task); |
864 | disconnect_task = GNUNET_SCHEDULER_add_now (&gather_stats_and_exit, | 800 | disconnect_task = |
865 | (void *) __LINE__); | 801 | GNUNET_SCHEDULER_add_now (&gather_stats_and_exit, (void *) __LINE__); |
866 | } | 802 | } |
867 | } | 803 | } |
868 | 804 | ||
@@ -876,13 +812,20 @@ channel_cleaner (void *cls, | |||
876 | * @param cls Closure (unused). | 812 | * @param cls Closure (unused). |
877 | */ | 813 | */ |
878 | static void | 814 | static void |
879 | do_test (void *cls) | 815 | start_test (void *cls) |
880 | { | 816 | { |
817 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
818 | GNUNET_MQ_hd_var_size (data, | ||
819 | GNUNET_MESSAGE_TYPE_DUMMY, | ||
820 | struct GNUNET_MessageHeader, | ||
821 | NULL), | ||
822 | GNUNET_MQ_handler_end () | ||
823 | }; | ||
824 | struct CadetTestChannelWrapper *ch; | ||
881 | enum GNUNET_CADET_ChannelOption flags; | 825 | enum GNUNET_CADET_ChannelOption flags; |
882 | 826 | ||
883 | test_task = NULL; | 827 | test_task = NULL; |
884 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 828 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "start_test\n"); |
885 | "do_test\n"); | ||
886 | if (NULL != disconnect_task) | 829 | if (NULL != disconnect_task) |
887 | { | 830 | { |
888 | GNUNET_SCHEDULER_cancel (disconnect_task); | 831 | GNUNET_SCHEDULER_cancel (disconnect_task); |
@@ -896,30 +839,33 @@ do_test (void *cls) | |||
896 | flags |= GNUNET_CADET_OPTION_RELIABLE; | 839 | flags |= GNUNET_CADET_OPTION_RELIABLE; |
897 | } | 840 | } |
898 | 841 | ||
899 | ch = GNUNET_CADET_channel_create (h1, | 842 | ch = GNUNET_new (struct CadetTestChannelWrapper); |
900 | NULL, | 843 | outgoing_ch = GNUNET_CADET_channel_create (h1, |
901 | p_id[1], | 844 | ch, |
902 | &port, | 845 | p_id[1], |
903 | flags); | 846 | &port, |
847 | flags, | ||
848 | NULL, | ||
849 | &disconnect_handler, | ||
850 | handlers); | ||
904 | 851 | ||
905 | disconnect_task | 852 | ch->ch = outgoing_ch; |
906 | = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | 853 | |
907 | &gather_stats_and_exit, | 854 | disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time, |
908 | (void *) __LINE__); | 855 | &gather_stats_and_exit, |
856 | (void *) __LINE__); | ||
909 | if (KEEPALIVE == test) | 857 | if (KEEPALIVE == test) |
910 | return; /* Don't send any data. */ | 858 | return; /* Don't send any data. */ |
859 | |||
911 | 860 | ||
912 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
913 | "Sending data initializer...\n"); | ||
914 | data_received = 0; | 861 | data_received = 0; |
915 | data_sent = 0; | 862 | data_sent = 0; |
916 | ack_received = 0; | 863 | ack_received = 0; |
917 | ack_sent = 0; | 864 | ack_sent = 0; |
918 | th = GNUNET_CADET_notify_transmit_ready (ch, | 865 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
919 | GNUNET_NO, | 866 | "Sending data initializer on channel %p...\n", |
920 | GNUNET_TIME_UNIT_FOREVER_REL, | 867 | outgoing_ch); |
921 | size_payload + 1000, | 868 | send_test_message (outgoing_ch); |
922 | &tmt_rdy, (void *) 0L); | ||
923 | } | 869 | } |
924 | 870 | ||
925 | 871 | ||
@@ -933,35 +879,26 @@ do_test (void *cls) | |||
933 | * NULL if the operation is successfull | 879 | * NULL if the operation is successfull |
934 | */ | 880 | */ |
935 | static void | 881 | static void |
936 | pi_cb (void *cls, | 882 | pi_cb (void *cls, struct GNUNET_TESTBED_Operation *op, |
937 | struct GNUNET_TESTBED_Operation *op, | 883 | const struct GNUNET_TESTBED_PeerInformation *pinfo, const char *emsg) |
938 | const struct GNUNET_TESTBED_PeerInformation *pinfo, | ||
939 | const char *emsg) | ||
940 | { | 884 | { |
941 | long i = (long) cls; | 885 | long i = (long) cls; |
942 | 886 | ||
943 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 887 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ID callback for %ld\n", i); |
944 | "id callback for %ld\n", i); | ||
945 | 888 | ||
946 | if ( (NULL == pinfo) || | 889 | if ((NULL == pinfo) || (NULL != emsg)) |
947 | (NULL != emsg) ) | ||
948 | { | 890 | { |
949 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 891 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); |
950 | "pi_cb: %s\n", emsg); | ||
951 | abort_test (__LINE__); | 892 | abort_test (__LINE__); |
952 | return; | 893 | return; |
953 | } | 894 | } |
954 | p_id[i] = pinfo->result.id; | 895 | p_id[i] = pinfo->result.id; |
955 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 896 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i])); |
956 | " id: %s\n", GNUNET_i2s (p_id[i])); | ||
957 | p_ids++; | 897 | p_ids++; |
958 | if (p_ids < 2) | 898 | if (p_ids < 2) |
959 | return; | 899 | return; |
960 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 900 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n"); |
961 | "Got all IDs, starting test\n"); | 901 | test_task = GNUNET_SCHEDULER_add_now (&start_test, NULL); |
962 | test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
963 | &do_test, | ||
964 | NULL); | ||
965 | } | 902 | } |
966 | 903 | ||
967 | 904 | ||
@@ -972,7 +909,7 @@ pi_cb (void *cls, | |||
972 | * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. | 909 | * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. |
973 | * @param num_peers Number of peers that are running. | 910 | * @param num_peers Number of peers that are running. |
974 | * @param peers Array of peers. | 911 | * @param peers Array of peers. |
975 | * @param cadetes Handle to each of the CADETs of the peers. | 912 | * @param cadets Handle to each of the CADETs of the peers. |
976 | */ | 913 | */ |
977 | static void | 914 | static void |
978 | tmain (void *cls, | 915 | tmain (void *cls, |
@@ -989,16 +926,18 @@ tmain (void *cls, | |||
989 | testbed_peers = peers; | 926 | testbed_peers = peers; |
990 | h1 = cadets[0]; | 927 | h1 = cadets[0]; |
991 | h2 = cadets[num_peers - 1]; | 928 | h2 = cadets[num_peers - 1]; |
992 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | 929 | disconnect_task = GNUNET_SCHEDULER_add_delayed (short_time, |
993 | &disconnect_cadet_peers, | 930 | &disconnect_cadet_peers, |
994 | (void *) __LINE__); | 931 | (void *) __LINE__); |
995 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | 932 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); |
996 | t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], | 933 | t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], |
997 | GNUNET_TESTBED_PIT_IDENTITY, | 934 | GNUNET_TESTBED_PIT_IDENTITY, |
998 | &pi_cb, (void *) 0L); | 935 | &pi_cb, |
936 | (void *) 0L); | ||
999 | t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], | 937 | t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], |
1000 | GNUNET_TESTBED_PIT_IDENTITY, | 938 | GNUNET_TESTBED_PIT_IDENTITY, |
1001 | &pi_cb, (void *) 1L); | 939 | &pi_cb, |
940 | (void *) 1L); | ||
1002 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n"); | 941 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n"); |
1003 | } | 942 | } |
1004 | 943 | ||
@@ -1009,16 +948,46 @@ tmain (void *cls, | |||
1009 | int | 948 | int |
1010 | main (int argc, char *argv[]) | 949 | main (int argc, char *argv[]) |
1011 | { | 950 | { |
1012 | initialized = GNUNET_NO; | ||
1013 | static const struct GNUNET_HashCode *ports[2]; | 951 | static const struct GNUNET_HashCode *ports[2]; |
952 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
953 | GNUNET_MQ_hd_var_size (data, | ||
954 | GNUNET_MESSAGE_TYPE_DUMMY, | ||
955 | struct GNUNET_MessageHeader, | ||
956 | NULL), | ||
957 | GNUNET_MQ_handler_end () | ||
958 | }; | ||
1014 | const char *config_file; | 959 | const char *config_file; |
1015 | char port_id[] = "test port"; | 960 | char port_id[] = "test port"; |
1016 | GNUNET_CRYPTO_hash (port_id, sizeof (port_id), &port); | 961 | struct GNUNET_GETOPT_CommandLineOption options[] = { |
962 | GNUNET_GETOPT_option_relative_time ('t', | ||
963 | "time", | ||
964 | "short_time", | ||
965 | gettext_noop ("set short timeout"), | ||
966 | &short_time), | ||
967 | |||
968 | GNUNET_GETOPT_option_uint ('m', | ||
969 | "messages", | ||
970 | "NUM_MESSAGES", | ||
971 | gettext_noop ("set number of messages to send"), | ||
972 | &total_packets), | ||
1017 | 973 | ||
974 | GNUNET_GETOPT_OPTION_END | ||
975 | }; | ||
976 | |||
977 | |||
978 | initialized = GNUNET_NO; | ||
1018 | GNUNET_log_setup ("test", "DEBUG", NULL); | 979 | GNUNET_log_setup ("test", "DEBUG", NULL); |
1019 | config_file = "test_cadet.conf"; | ||
1020 | 980 | ||
1021 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n"); | 981 | total_packets = TOTAL_PACKETS; |
982 | short_time = SHORT_TIME; | ||
983 | if (-1 == GNUNET_GETOPT_run (argv[0], options, argc, argv)) | ||
984 | { | ||
985 | FPRINTF (stderr, "test failed: problem with CLI parameters\n"); | ||
986 | exit (1); | ||
987 | } | ||
988 | |||
989 | config_file = "test_cadet.conf"; | ||
990 | GNUNET_CRYPTO_hash (port_id, sizeof (port_id), &port); | ||
1022 | 991 | ||
1023 | /* Find out requested size */ | 992 | /* Find out requested size */ |
1024 | if (strstr (argv[0], "_2_") != NULL) | 993 | if (strstr (argv[0], "_2_") != NULL) |
@@ -1056,11 +1025,11 @@ main (int argc, char *argv[]) | |||
1056 | { | 1025 | { |
1057 | /* Test is supposed to generate the following callbacks: | 1026 | /* Test is supposed to generate the following callbacks: |
1058 | * 1 incoming channel (@dest) | 1027 | * 1 incoming channel (@dest) |
1059 | * TOTAL_PACKETS received data packet (@dest) | 1028 | * total_packets received data packet (@dest) |
1060 | * TOTAL_PACKETS received data packet (@orig) | 1029 | * total_packets received data packet (@orig) |
1061 | * 1 received channel destroy (@dest) | 1030 | * 1 received channel destroy (@dest) |
1062 | */ | 1031 | */ |
1063 | ok_goal = TOTAL_PACKETS * 2 + 2; | 1032 | ok_goal = total_packets * 2 + 2; |
1064 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); | 1033 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); |
1065 | test = SPEED_ACK; | 1034 | test = SPEED_ACK; |
1066 | test_name = "speed ack"; | 1035 | test_name = "speed ack"; |
@@ -1070,11 +1039,11 @@ main (int argc, char *argv[]) | |||
1070 | /* Test is supposed to generate the following callbacks: | 1039 | /* Test is supposed to generate the following callbacks: |
1071 | * 1 incoming channel (@dest) | 1040 | * 1 incoming channel (@dest) |
1072 | * 1 initial packet (@dest) | 1041 | * 1 initial packet (@dest) |
1073 | * TOTAL_PACKETS received data packet (@dest) | 1042 | * total_packets received data packet (@dest) |
1074 | * 1 received data packet (@orig) | 1043 | * 1 received data packet (@orig) |
1075 | * 1 received channel destroy (@dest) | 1044 | * 1 received channel destroy (@dest) |
1076 | */ | 1045 | */ |
1077 | ok_goal = TOTAL_PACKETS + 4; | 1046 | ok_goal = total_packets + 4; |
1078 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); | 1047 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); |
1079 | if (strstr (argv[0], "_reliable") != NULL) | 1048 | if (strstr (argv[0], "_reliable") != NULL) |
1080 | { | 1049 | { |
@@ -1115,20 +1084,22 @@ main (int argc, char *argv[]) | |||
1115 | p_ids = 0; | 1084 | p_ids = 0; |
1116 | ports[0] = &port; | 1085 | ports[0] = &port; |
1117 | ports[1] = NULL; | 1086 | ports[1] = NULL; |
1118 | GNUNET_CADET_TEST_run ("test_cadet_small", | 1087 | GNUNET_CADET_TEST_ruN ("test_cadet_small", |
1119 | config_file, | 1088 | config_file, |
1120 | peers_requested, | 1089 | peers_requested, |
1121 | &tmain, | 1090 | &tmain, |
1122 | NULL, /* tmain cls */ | 1091 | NULL, /* tmain cls */ |
1123 | &incoming_channel, | 1092 | &connect_handler, |
1124 | &channel_cleaner, | 1093 | NULL, |
1125 | handlers, | 1094 | &disconnect_handler, |
1126 | ports); | 1095 | handlers, |
1127 | 1096 | ports); | |
1128 | if (ok_goal > ok) | 1097 | if (NULL != strstr (argv[0], "_reliable")) |
1098 | msg_dropped = 0; /* dropped should be retransmitted */ | ||
1099 | |||
1100 | if (ok_goal > ok - msg_dropped) | ||
1129 | { | 1101 | { |
1130 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1102 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "FAILED! (%d/%d)\n", ok, ok_goal); |
1131 | "FAILED! (%d/%d)\n", ok, ok_goal); | ||
1132 | return 1; | 1103 | return 1; |
1133 | } | 1104 | } |
1134 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n"); | 1105 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n"); |
diff --git a/src/cadet/test_cadet_local.c b/src/cadet/test_cadet_local.c deleted file mode 100644 index 2b915ab81..000000000 --- a/src/cadet/test_cadet_local.c +++ /dev/null | |||
@@ -1,351 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/test_cadet_local.c | ||
23 | * @brief test cadet local: test of cadet channels with just one peer | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_dht_service.h" | ||
30 | #include "gnunet_testing_lib.h" | ||
31 | #include "gnunet_cadet_service.h" | ||
32 | |||
33 | struct GNUNET_TESTING_Peer *me; | ||
34 | |||
35 | static struct GNUNET_CADET_Handle *cadet_peer_1; | ||
36 | |||
37 | static struct GNUNET_CADET_Handle *cadet_peer_2; | ||
38 | |||
39 | static struct GNUNET_CADET_Channel *ch; | ||
40 | |||
41 | static int result = GNUNET_OK; | ||
42 | |||
43 | static int got_data = GNUNET_NO; | ||
44 | |||
45 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
46 | |||
47 | static struct GNUNET_SCHEDULER_Task *connect_task; | ||
48 | |||
49 | static struct GNUNET_CADET_TransmitHandle *mth; | ||
50 | |||
51 | |||
52 | /** | ||
53 | * Connect to other client and send data | ||
54 | * | ||
55 | * @param cls Closue (unused). | ||
56 | */ | ||
57 | static void | ||
58 | do_connect (void *cls); | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Shutdown nicely | ||
63 | */ | ||
64 | static void | ||
65 | do_shutdown (void *cls) | ||
66 | { | ||
67 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
68 | "shutdown\n"); | ||
69 | if (NULL != abort_task) | ||
70 | { | ||
71 | GNUNET_SCHEDULER_cancel (abort_task); | ||
72 | abort_task = NULL; | ||
73 | } | ||
74 | if (NULL != ch) | ||
75 | { | ||
76 | GNUNET_CADET_channel_destroy (ch); | ||
77 | ch = NULL; | ||
78 | } | ||
79 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
80 | "Disconnect client 1\n"); | ||
81 | if (NULL != cadet_peer_1) | ||
82 | { | ||
83 | GNUNET_CADET_disconnect (cadet_peer_1); | ||
84 | cadet_peer_1 = NULL; | ||
85 | } | ||
86 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
87 | "Disconnect client 2\n"); | ||
88 | if (NULL != cadet_peer_2) | ||
89 | { | ||
90 | GNUNET_CADET_disconnect (cadet_peer_2); | ||
91 | cadet_peer_2 = NULL; | ||
92 | } | ||
93 | if (NULL != connect_task) | ||
94 | { | ||
95 | GNUNET_SCHEDULER_cancel (connect_task); | ||
96 | connect_task = NULL; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | |||
101 | /** | ||
102 | * Something went wrong and timed out. Kill everything and set error flag | ||
103 | */ | ||
104 | static void | ||
105 | do_abort (void *cls) | ||
106 | { | ||
107 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n"); | ||
108 | result = GNUNET_SYSERR; | ||
109 | abort_task = NULL; | ||
110 | GNUNET_SCHEDULER_shutdown (); | ||
111 | } | ||
112 | |||
113 | |||
114 | /** | ||
115 | * Function is called whenever a message is received. | ||
116 | * | ||
117 | * @param cls closure (set from GNUNET_CADET_connect) | ||
118 | * @param channel connection to the other end | ||
119 | * @param channel_ctx place to store local state associated with the channel | ||
120 | * @param message the actual message | ||
121 | * @return #GNUNET_OK to keep the connection open, | ||
122 | * #GNUNET_SYSERR to close it (signal serious error) | ||
123 | */ | ||
124 | static int | ||
125 | data_callback (void *cls, | ||
126 | struct GNUNET_CADET_Channel *channel, | ||
127 | void **channel_ctx, | ||
128 | const struct GNUNET_MessageHeader *message) | ||
129 | { | ||
130 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
131 | "Data callback! Shutting down.\n"); | ||
132 | got_data = GNUNET_YES; | ||
133 | GNUNET_SCHEDULER_shutdown (); | ||
134 | GNUNET_CADET_receive_done (channel); | ||
135 | return GNUNET_OK; | ||
136 | } | ||
137 | |||
138 | |||
139 | /** | ||
140 | * Method called whenever another peer has added us to a channel | ||
141 | * the other peer initiated. | ||
142 | * | ||
143 | * @param cls closure | ||
144 | * @param channel new handle to the channel | ||
145 | * @param initiator peer that started the channel | ||
146 | * @param port port number | ||
147 | * @param options channel options | ||
148 | * @return initial channel context for the channel | ||
149 | * (can be NULL -- that's not an error) | ||
150 | */ | ||
151 | static void * | ||
152 | inbound_channel (void *cls, | ||
153 | struct GNUNET_CADET_Channel *channel, | ||
154 | const struct GNUNET_PeerIdentity *initiator, | ||
155 | const struct GNUNET_HashCode *port, | ||
156 | enum GNUNET_CADET_ChannelOption options) | ||
157 | { | ||
158 | long id = (long) cls; | ||
159 | |||
160 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
161 | "received incoming channel on peer %d, port %s\n", | ||
162 | (int) id, | ||
163 | GNUNET_h2s (port)); | ||
164 | if (id != 2L) | ||
165 | { | ||
166 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
167 | "wrong peer\n"); | ||
168 | result = GNUNET_SYSERR; | ||
169 | } | ||
170 | return NULL; | ||
171 | } | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Function called whenever an channel is destroyed. Should clean up | ||
176 | * any associated state. | ||
177 | * | ||
178 | * @param cls closure (set from GNUNET_CADET_connect) | ||
179 | * @param channel connection to the other end (henceforth invalid) | ||
180 | * @param channel_ctx place where local state associated | ||
181 | * with the channel is stored | ||
182 | */ | ||
183 | static void | ||
184 | channel_end (void *cls, | ||
185 | const struct GNUNET_CADET_Channel *channel, | ||
186 | void *channel_ctx) | ||
187 | { | ||
188 | long id = (long) cls; | ||
189 | |||
190 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
191 | "incoming channel closed at peer %ld\n", | ||
192 | id); | ||
193 | if (NULL != mth) | ||
194 | { | ||
195 | GNUNET_CADET_notify_transmit_ready_cancel (mth); | ||
196 | mth = NULL; | ||
197 | } | ||
198 | if (channel == ch) | ||
199 | ch = NULL; | ||
200 | if (GNUNET_NO == got_data) | ||
201 | { | ||
202 | if (NULL == connect_task) | ||
203 | connect_task | ||
204 | = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, | ||
205 | 2), | ||
206 | &do_connect, | ||
207 | NULL); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | |||
212 | /** | ||
213 | * Handler array for traffic received on peer1 | ||
214 | */ | ||
215 | static struct GNUNET_CADET_MessageHandler handlers1[] = { | ||
216 | {&data_callback, 1, 0}, | ||
217 | {NULL, 0, 0} | ||
218 | }; | ||
219 | |||
220 | |||
221 | /** | ||
222 | * Handler array for traffic received on peer2 (none expected) | ||
223 | */ | ||
224 | static struct GNUNET_CADET_MessageHandler handlers2[] = { | ||
225 | {&data_callback, 1, 0}, | ||
226 | {NULL, 0, 0} | ||
227 | }; | ||
228 | |||
229 | |||
230 | /** | ||
231 | * Data send callback: fillbuffer with test packet. | ||
232 | * | ||
233 | * @param cls Closure (unused). | ||
234 | * @param size Buffer size. | ||
235 | * @param buf Buffer to fill. | ||
236 | * | ||
237 | * @return size of test packet. | ||
238 | */ | ||
239 | static size_t | ||
240 | do_send (void *cls, size_t size, void *buf) | ||
241 | { | ||
242 | struct GNUNET_MessageHeader *m = buf; | ||
243 | |||
244 | mth = NULL; | ||
245 | if (NULL == buf) | ||
246 | { | ||
247 | GNUNET_break (0); | ||
248 | result = GNUNET_SYSERR; | ||
249 | return 0; | ||
250 | } | ||
251 | m->size = htons (sizeof (struct GNUNET_MessageHeader)); | ||
252 | m->type = htons (1); | ||
253 | GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); | ||
254 | return sizeof (struct GNUNET_MessageHeader); | ||
255 | } | ||
256 | |||
257 | |||
258 | /** | ||
259 | * Connect to other client and send data | ||
260 | * | ||
261 | * @param cls Closue (unused). | ||
262 | */ | ||
263 | static void | ||
264 | do_connect (void *cls) | ||
265 | { | ||
266 | struct GNUNET_PeerIdentity id; | ||
267 | |||
268 | connect_task = NULL; | ||
269 | GNUNET_TESTING_peer_get_identity (me, &id); | ||
270 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
271 | "CONNECT BY PORT\n"); | ||
272 | ch = GNUNET_CADET_channel_create (cadet_peer_1, | ||
273 | NULL, | ||
274 | &id, GC_u2h (1), | ||
275 | GNUNET_CADET_OPTION_DEFAULT); | ||
276 | mth = GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO, | ||
277 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
278 | sizeof (struct GNUNET_MessageHeader), | ||
279 | &do_send, NULL); | ||
280 | } | ||
281 | |||
282 | |||
283 | /** | ||
284 | * Initialize framework and start test | ||
285 | * | ||
286 | * @param cls Closure (unused). | ||
287 | * @param cfg Configuration handle. | ||
288 | * @param peer Testing peer handle. | ||
289 | */ | ||
290 | static void | ||
291 | run (void *cls, | ||
292 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
293 | struct GNUNET_TESTING_Peer *peer) | ||
294 | { | ||
295 | me = peer; | ||
296 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, | ||
297 | NULL); | ||
298 | abort_task = | ||
299 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
300 | (GNUNET_TIME_UNIT_SECONDS, 15), | ||
301 | &do_abort, | ||
302 | NULL); | ||
303 | cadet_peer_1 = GNUNET_CADET_connect (cfg, /* configuration */ | ||
304 | (void *) 1L, /* cls */ | ||
305 | &channel_end, /* channel end hndlr */ | ||
306 | handlers1); /* traffic handlers */ | ||
307 | cadet_peer_2 = GNUNET_CADET_connect (cfg, /* configuration */ | ||
308 | (void *) 2L, /* cls */ | ||
309 | &channel_end, /* channel end hndlr */ | ||
310 | handlers2); /* traffic handlers */ | ||
311 | |||
312 | if ( (NULL == cadet_peer_1) || | ||
313 | (NULL == cadet_peer_2) ) | ||
314 | { | ||
315 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
316 | "Couldn't connect to cadet :(\n"); | ||
317 | result = GNUNET_SYSERR; | ||
318 | GNUNET_SCHEDULER_shutdown (); | ||
319 | return; | ||
320 | } | ||
321 | GNUNET_CADET_open_port (cadet_peer_2, | ||
322 | GC_u2h (1), | ||
323 | &inbound_channel, | ||
324 | (void *) 2L); | ||
325 | if (NULL == connect_task) | ||
326 | connect_task | ||
327 | = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, | ||
328 | 2), | ||
329 | &do_connect, | ||
330 | NULL); | ||
331 | } | ||
332 | |||
333 | |||
334 | /** | ||
335 | * Main | ||
336 | */ | ||
337 | int | ||
338 | main (int argc, char *argv[]) | ||
339 | { | ||
340 | if (0 != GNUNET_TESTING_peer_run ("test-cadet-local", | ||
341 | "test_cadet.conf", | ||
342 | &run, NULL)) | ||
343 | { | ||
344 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n"); | ||
345 | return 2; | ||
346 | } | ||
347 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result); | ||
348 | return (result == GNUNET_OK) ? 0 : 1; | ||
349 | } | ||
350 | |||
351 | /* end of test_cadet_local_1.c */ | ||
diff --git a/src/cadet/test_cadet_local_mq.c b/src/cadet/test_cadet_local_mq.c new file mode 100644 index 000000000..3089c7fbb --- /dev/null +++ b/src/cadet/test_cadet_local_mq.c | |||
@@ -0,0 +1,332 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/test_cadet_local.c | ||
23 | * @brief test cadet local: test of cadet channels with just one peer | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_dht_service.h" | ||
30 | #include "gnunet_testing_lib.h" | ||
31 | #include "gnunet_cadet_service.h" | ||
32 | |||
33 | #define TEST_MESSAGE_TYPE 1 | ||
34 | #define TEST_PORT_ID 1 | ||
35 | |||
36 | /** | ||
37 | * Test message structure. | ||
38 | */ | ||
39 | struct GNUNET_CADET_TestMsg | ||
40 | { | ||
41 | /** | ||
42 | * Type: #TEST_MESSAGE_TYPE | ||
43 | * | ||
44 | * Size: sizeof(struct GNUNET_CADET_TestMsg) | ||
45 | */ | ||
46 | struct GNUNET_MessageHeader header; | ||
47 | |||
48 | /** | ||
49 | * Test payload. | ||
50 | */ | ||
51 | uint64_t payload; | ||
52 | }; | ||
53 | |||
54 | struct GNUNET_TESTING_Peer *me; | ||
55 | |||
56 | static struct GNUNET_CADET_Handle *cadet_peer_1; | ||
57 | |||
58 | static struct GNUNET_CADET_Handle *cadet_peer_2; | ||
59 | |||
60 | static struct GNUNET_CADET_Channel *ch; | ||
61 | |||
62 | static int result = GNUNET_OK; | ||
63 | |||
64 | static int got_data = GNUNET_NO; | ||
65 | |||
66 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
67 | |||
68 | static struct GNUNET_SCHEDULER_Task *connect_task; | ||
69 | |||
70 | |||
71 | /** | ||
72 | * Connect to other client and send data | ||
73 | * | ||
74 | * @param cls Closue (unused). | ||
75 | */ | ||
76 | static void | ||
77 | do_connect (void *cls); | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Shutdown nicely | ||
82 | */ | ||
83 | static void | ||
84 | do_shutdown (void *cls) | ||
85 | { | ||
86 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
87 | "shutdown\n"); | ||
88 | if (NULL != abort_task) | ||
89 | { | ||
90 | GNUNET_SCHEDULER_cancel (abort_task); | ||
91 | abort_task = NULL; | ||
92 | } | ||
93 | if (NULL != ch) | ||
94 | { | ||
95 | GNUNET_CADET_channel_destroy (ch); | ||
96 | ch = NULL; | ||
97 | } | ||
98 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
99 | "Disconnect client 1\n"); | ||
100 | if (NULL != cadet_peer_1) | ||
101 | { | ||
102 | GNUNET_CADET_disconnect (cadet_peer_1); | ||
103 | cadet_peer_1 = NULL; | ||
104 | } | ||
105 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
106 | "Disconnect client 2\n"); | ||
107 | if (NULL != cadet_peer_2) | ||
108 | { | ||
109 | GNUNET_CADET_disconnect (cadet_peer_2); | ||
110 | cadet_peer_2 = NULL; | ||
111 | } | ||
112 | if (NULL != connect_task) | ||
113 | { | ||
114 | GNUNET_SCHEDULER_cancel (connect_task); | ||
115 | connect_task = NULL; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | |||
120 | /** | ||
121 | * Something went wrong and timed out. Kill everything and set error flag | ||
122 | */ | ||
123 | static void | ||
124 | do_abort (void *cls) | ||
125 | { | ||
126 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ABORT from line %ld\n", (long) cls); | ||
127 | result = GNUNET_SYSERR; | ||
128 | abort_task = NULL; | ||
129 | GNUNET_SCHEDULER_shutdown (); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * Method called whenever a peer connects to a port in MQ-based CADET. | ||
134 | * | ||
135 | * @param cls Closure from #GNUNET_CADET_open_port. | ||
136 | * @param channel New handle to the channel. | ||
137 | * @param source Peer that started this channel. | ||
138 | * @return Closure for the incoming @a channel. It's given to: | ||
139 | * - The #GNUNET_CADET_DisconnectEventHandler (given to | ||
140 | * #GNUNET_CADET_open_port) when the channel dies. | ||
141 | * - Each the #GNUNET_MQ_MessageCallback handlers for each message | ||
142 | * received on the @a channel. | ||
143 | */ | ||
144 | static void * | ||
145 | connected (void *cls, | ||
146 | struct GNUNET_CADET_Channel *channel, | ||
147 | const struct GNUNET_PeerIdentity *source) | ||
148 | { | ||
149 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
150 | "connected %s, cls: %p\n", | ||
151 | GNUNET_i2s(source), cls); | ||
152 | return channel; | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * Function called whenever an MQ-channel is destroyed, even if the destruction | ||
157 | * was requested by #GNUNET_CADET_channel_destroy. | ||
158 | * It must NOT call #GNUNET_CADET_channel_destroy on the channel. | ||
159 | * | ||
160 | * It should clean up any associated state, including cancelling any pending | ||
161 | * transmission on this channel. | ||
162 | * | ||
163 | * @param cls Channel closure. | ||
164 | * @param channel Connection to the other end (henceforth invalid). | ||
165 | */ | ||
166 | static void | ||
167 | disconnected (void *cls, | ||
168 | const struct GNUNET_CADET_Channel *channel) | ||
169 | { | ||
170 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
171 | "disconnected channel %p, cls: %p\n", | ||
172 | channel, cls); | ||
173 | if (channel == ch) | ||
174 | ch = NULL; | ||
175 | } | ||
176 | |||
177 | |||
178 | /** | ||
179 | * Handle test data | ||
180 | * | ||
181 | * @param h The cadet handle | ||
182 | * @param msg A message with the details of the new incoming channel | ||
183 | */ | ||
184 | static void | ||
185 | handle_data_received (void *cls, | ||
186 | const struct GNUNET_CADET_TestMsg *msg) | ||
187 | { | ||
188 | uint64_t payload; | ||
189 | |||
190 | payload = GNUNET_ntohll (msg->payload); | ||
191 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
192 | "Data callback payload %llu with cls: %p! Shutting down.\n", | ||
193 | (unsigned long long) payload, | ||
194 | cls); | ||
195 | GNUNET_assert (42 == payload); | ||
196 | got_data = GNUNET_YES; | ||
197 | GNUNET_SCHEDULER_shutdown (); | ||
198 | } | ||
199 | |||
200 | |||
201 | /** | ||
202 | * Signature of the main function of a task. | ||
203 | * | ||
204 | * @param cls Closure (unused). | ||
205 | */ | ||
206 | static void | ||
207 | message_sent (void *cls) | ||
208 | { | ||
209 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "message sent\n"); | ||
210 | } | ||
211 | |||
212 | |||
213 | /** | ||
214 | * Connect to other client and send data | ||
215 | * | ||
216 | * @param cls Closure (unused). | ||
217 | */ | ||
218 | static void | ||
219 | do_connect (void *cls) | ||
220 | { | ||
221 | struct GNUNET_PeerIdentity id; | ||
222 | struct GNUNET_MQ_Handle *mq; | ||
223 | struct GNUNET_MQ_Envelope *env; | ||
224 | struct GNUNET_CADET_TestMsg *msg; | ||
225 | |||
226 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
227 | GNUNET_MQ_hd_fixed_size (data_received, | ||
228 | TEST_MESSAGE_TYPE, | ||
229 | struct GNUNET_CADET_TestMsg, | ||
230 | cadet_peer_1), | ||
231 | GNUNET_MQ_handler_end () | ||
232 | }; | ||
233 | |||
234 | connect_task = NULL; | ||
235 | GNUNET_TESTING_peer_get_identity (me, &id); | ||
236 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
237 | "creating channel\n"); | ||
238 | ch = GNUNET_CADET_channel_create (cadet_peer_1, /* cadet handle */ | ||
239 | NULL, /* channel cls */ | ||
240 | &id, /* destination */ | ||
241 | GC_u2h (TEST_MESSAGE_TYPE), /* port */ | ||
242 | GNUNET_CADET_OPTION_DEFAULT, /* opt */ | ||
243 | NULL, /* window change */ | ||
244 | &disconnected, /* disconnect handler */ | ||
245 | handlers /* traffic handlers */ | ||
246 | ); | ||
247 | env = GNUNET_MQ_msg (msg, TEST_MESSAGE_TYPE); | ||
248 | msg->payload = GNUNET_htonll (42); | ||
249 | mq = GNUNET_CADET_get_mq (ch); | ||
250 | GNUNET_MQ_notify_sent (env, &message_sent, NULL); | ||
251 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
252 | "sending message\n"); | ||
253 | GNUNET_MQ_send (mq, env); | ||
254 | } | ||
255 | |||
256 | |||
257 | /** | ||
258 | * Initialize framework and start test | ||
259 | * | ||
260 | * @param cls Closure (unused). | ||
261 | * @param cfg Configuration handle. | ||
262 | * @param peer Testing peer handle. | ||
263 | */ | ||
264 | static void | ||
265 | run (void *cls, | ||
266 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
267 | struct GNUNET_TESTING_Peer *peer) | ||
268 | { | ||
269 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
270 | GNUNET_MQ_hd_fixed_size (data_received, | ||
271 | TEST_MESSAGE_TYPE, | ||
272 | struct GNUNET_CADET_TestMsg, | ||
273 | cadet_peer_2), | ||
274 | GNUNET_MQ_handler_end () | ||
275 | }; | ||
276 | struct GNUNET_TIME_Relative delay; | ||
277 | |||
278 | me = peer; | ||
279 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, | ||
280 | NULL); | ||
281 | delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15); | ||
282 | abort_task = GNUNET_SCHEDULER_add_delayed (delay, | ||
283 | &do_abort, | ||
284 | (void *) (long) __LINE__); | ||
285 | cadet_peer_1 = GNUNET_CADET_connect (cfg); | ||
286 | cadet_peer_2 = GNUNET_CADET_connect (cfg); | ||
287 | |||
288 | if ( (NULL == cadet_peer_1) || | ||
289 | (NULL == cadet_peer_2) ) | ||
290 | { | ||
291 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
292 | "Couldn't connect to cadet\n"); | ||
293 | result = GNUNET_SYSERR; | ||
294 | GNUNET_SCHEDULER_shutdown (); | ||
295 | return; | ||
296 | } | ||
297 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CADET 1: %p\n", cadet_peer_1); | ||
298 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CADET 2: %p\n", cadet_peer_2); | ||
299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handlers 2: %p\n", handlers); | ||
300 | GNUNET_CADET_open_port (cadet_peer_2, /* cadet handle */ | ||
301 | GC_u2h (TEST_PORT_ID), /* port id */ | ||
302 | &connected, /* connect handler */ | ||
303 | (void *) 2L, /* handle for #connected */ | ||
304 | NULL, /* window size handler */ | ||
305 | &disconnected, /* disconnect handler */ | ||
306 | handlers); /* traffic handlers */ | ||
307 | delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2); | ||
308 | if (NULL == connect_task) | ||
309 | connect_task = GNUNET_SCHEDULER_add_delayed (delay, | ||
310 | &do_connect, | ||
311 | NULL); | ||
312 | } | ||
313 | |||
314 | |||
315 | /** | ||
316 | * Main | ||
317 | */ | ||
318 | int | ||
319 | main (int argc, char *argv[]) | ||
320 | { | ||
321 | if (0 != GNUNET_TESTING_peer_run ("test-cadet-local", | ||
322 | "test_cadet.conf", | ||
323 | &run, NULL)) | ||
324 | { | ||
325 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n"); | ||
326 | return 2; | ||
327 | } | ||
328 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result); | ||
329 | return (result == GNUNET_OK) ? 0 : 1; | ||
330 | } | ||
331 | |||
332 | /* end of test_cadet_local_1.c */ | ||
diff --git a/src/cadet/test_cadet_single.c b/src/cadet/test_cadet_single.c deleted file mode 100644 index b45b0af5d..000000000 --- a/src/cadet/test_cadet_single.c +++ /dev/null | |||
@@ -1,354 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2011 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/test_cadet_single.c | ||
23 | * @brief test cadet single: test of cadet channels with just one client | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_dht_service.h" | ||
30 | #include "gnunet_testing_lib.h" | ||
31 | #include "gnunet_cadet_service.h" | ||
32 | |||
33 | #define REPETITIONS 5 | ||
34 | #define DATA_SIZE 35000 | ||
35 | |||
36 | struct GNUNET_TESTING_Peer *me; | ||
37 | |||
38 | static struct GNUNET_CADET_Handle *cadet; | ||
39 | |||
40 | static struct GNUNET_CADET_Channel *ch1; | ||
41 | |||
42 | static struct GNUNET_CADET_Channel *ch2; | ||
43 | |||
44 | static int result; | ||
45 | |||
46 | static struct GNUNET_SCHEDULER_Task *abort_task; | ||
47 | |||
48 | static struct GNUNET_SCHEDULER_Task *connect_task; | ||
49 | |||
50 | static unsigned int repetition; | ||
51 | |||
52 | static struct GNUNET_CADET_TransmitHandle *nth; | ||
53 | |||
54 | static struct GNUNET_CADET_Port *port; | ||
55 | |||
56 | |||
57 | /* forward declaration */ | ||
58 | static size_t | ||
59 | do_send (void *cls, size_t size, void *buf); | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Shutdown nicely | ||
64 | */ | ||
65 | static void | ||
66 | do_shutdown (void *cls) | ||
67 | { | ||
68 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
69 | "shutdown\n"); | ||
70 | if (NULL != port) | ||
71 | { | ||
72 | GNUNET_CADET_close_port (port); | ||
73 | port = NULL; | ||
74 | } | ||
75 | if (NULL != nth) | ||
76 | { | ||
77 | GNUNET_CADET_notify_transmit_ready_cancel (nth); | ||
78 | nth = NULL; | ||
79 | } | ||
80 | if (NULL != abort_task) | ||
81 | { | ||
82 | GNUNET_SCHEDULER_cancel (abort_task); | ||
83 | abort_task = NULL; | ||
84 | } | ||
85 | if (NULL != connect_task) | ||
86 | { | ||
87 | GNUNET_SCHEDULER_cancel (connect_task); | ||
88 | connect_task = NULL; | ||
89 | } | ||
90 | if (NULL != ch1) | ||
91 | { | ||
92 | GNUNET_CADET_channel_destroy (ch1); | ||
93 | ch1 = NULL; | ||
94 | } | ||
95 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
96 | "Disconnect clients\n"); | ||
97 | if (NULL != cadet) | ||
98 | { | ||
99 | GNUNET_CADET_disconnect (cadet); | ||
100 | cadet = NULL; | ||
101 | } | ||
102 | else | ||
103 | { | ||
104 | GNUNET_break (0); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | |||
109 | /** | ||
110 | * Something went wrong and timed out. Kill everything and set error flag | ||
111 | */ | ||
112 | static void | ||
113 | do_abort (void *cls) | ||
114 | { | ||
115 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n"); | ||
116 | result = GNUNET_SYSERR; | ||
117 | abort_task = NULL; | ||
118 | GNUNET_SCHEDULER_shutdown (); | ||
119 | } | ||
120 | |||
121 | |||
122 | /** | ||
123 | * Function is called whenever a message is received. | ||
124 | * | ||
125 | * @param cls closure (set from GNUNET_CADET_connect) | ||
126 | * @param channel connection to the other end | ||
127 | * @param channel_ctx place to store local state associated with the channel | ||
128 | * @param message the actual message | ||
129 | * @return #GNUNET_OK to keep the connection open, | ||
130 | * #GNUNET_SYSERR to close it (signal serious error) | ||
131 | */ | ||
132 | static int | ||
133 | data_callback (void *cls, | ||
134 | struct GNUNET_CADET_Channel *channel, | ||
135 | void **channel_ctx, | ||
136 | const struct GNUNET_MessageHeader *message) | ||
137 | { | ||
138 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
139 | "Data callback! Repetition %u/%u\n", | ||
140 | repetition, REPETITIONS); | ||
141 | repetition++; | ||
142 | if (repetition < REPETITIONS) | ||
143 | { | ||
144 | struct GNUNET_CADET_Channel *my_channel; | ||
145 | if (0 == repetition % 2) | ||
146 | my_channel = ch1; | ||
147 | else | ||
148 | my_channel = ch2; | ||
149 | nth = GNUNET_CADET_notify_transmit_ready (my_channel, | ||
150 | GNUNET_NO, | ||
151 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
152 | sizeof (struct GNUNET_MessageHeader) | ||
153 | + DATA_SIZE, | ||
154 | &do_send, NULL); | ||
155 | GNUNET_CADET_receive_done (channel); | ||
156 | return GNUNET_OK; | ||
157 | } | ||
158 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
159 | "All data OK. Destroying channel.\n"); | ||
160 | GNUNET_assert (NULL == nth); | ||
161 | GNUNET_CADET_channel_destroy (ch1); | ||
162 | ch1 = NULL; | ||
163 | return GNUNET_OK; | ||
164 | } | ||
165 | |||
166 | |||
167 | /** | ||
168 | * Method called whenever another peer has added us to a channel | ||
169 | * the other peer initiated. | ||
170 | * | ||
171 | * @param cls closure | ||
172 | * @param channel new handle to the channel | ||
173 | * @param initiator peer that started the channel | ||
174 | * @param port port number | ||
175 | * @param options channel option flags | ||
176 | * @return initial channel context for the channel | ||
177 | * (can be NULL -- that's not an error) | ||
178 | */ | ||
179 | static void * | ||
180 | inbound_channel (void *cls, | ||
181 | struct GNUNET_CADET_Channel *channel, | ||
182 | const struct GNUNET_PeerIdentity *initiator, | ||
183 | const struct GNUNET_HashCode *port, | ||
184 | enum GNUNET_CADET_ChannelOption options) | ||
185 | { | ||
186 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
187 | "received incoming channel on port %s\n", | ||
188 | GNUNET_h2s (port)); | ||
189 | ch2 = channel; | ||
190 | return NULL; | ||
191 | } | ||
192 | |||
193 | |||
194 | /** | ||
195 | * Function called whenever an inbound channel is destroyed. Should clean up | ||
196 | * any associated state. | ||
197 | * | ||
198 | * @param cls closure (set from GNUNET_CADET_connect) | ||
199 | * @param channel connection to the other end (henceforth invalid) | ||
200 | * @param channel_ctx place where local state associated | ||
201 | * with the channel is stored | ||
202 | */ | ||
203 | static void | ||
204 | channel_end (void *cls, | ||
205 | const struct GNUNET_CADET_Channel *channel, | ||
206 | void *channel_ctx) | ||
207 | { | ||
208 | long id = (long) cls; | ||
209 | |||
210 | nth = NULL; | ||
211 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
212 | "incoming channel closed at peer %ld\n", | ||
213 | id); | ||
214 | if ( (REPETITIONS == repetition) && | ||
215 | (channel == ch2) ) | ||
216 | { | ||
217 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
218 | "everything fine! finishing!\n"); | ||
219 | result = GNUNET_OK; | ||
220 | GNUNET_SCHEDULER_shutdown (); | ||
221 | } | ||
222 | if (channel == ch2) | ||
223 | ch2 = NULL; | ||
224 | if (channel == ch1) | ||
225 | ch1 = NULL; | ||
226 | } | ||
227 | |||
228 | |||
229 | /** | ||
230 | * Handler array for traffic received on peer1 | ||
231 | */ | ||
232 | static struct GNUNET_CADET_MessageHandler handlers1[] = { | ||
233 | {&data_callback, 1, 0}, | ||
234 | {NULL, 0, 0} | ||
235 | }; | ||
236 | |||
237 | |||
238 | /** | ||
239 | * Data send callback: fillbuffer with test packet. | ||
240 | * | ||
241 | * @param cls Closure (unused). | ||
242 | * @param size Buffer size. | ||
243 | * @param buf Buffer to fill. | ||
244 | * @return size of test packet. | ||
245 | */ | ||
246 | static size_t | ||
247 | do_send (void *cls, size_t size, void *buf) | ||
248 | { | ||
249 | struct GNUNET_MessageHeader *m = buf; | ||
250 | |||
251 | nth = NULL; | ||
252 | if (NULL == buf) | ||
253 | { | ||
254 | GNUNET_break (0); | ||
255 | result = GNUNET_SYSERR; | ||
256 | return 0; | ||
257 | } | ||
258 | m->size = htons (sizeof (struct GNUNET_MessageHeader) + DATA_SIZE); | ||
259 | m->type = htons (1); | ||
260 | memset (&m[1], 0, DATA_SIZE); | ||
261 | GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader) + DATA_SIZE); | ||
262 | return sizeof (struct GNUNET_MessageHeader) + DATA_SIZE; | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * Connect to other client and send data | ||
267 | * | ||
268 | * @param cls Closue (unused). | ||
269 | */ | ||
270 | static void | ||
271 | do_connect (void *cls) | ||
272 | { | ||
273 | struct GNUNET_PeerIdentity id; | ||
274 | size_t size = sizeof (struct GNUNET_MessageHeader) + DATA_SIZE; | ||
275 | |||
276 | connect_task = NULL; | ||
277 | GNUNET_TESTING_peer_get_identity (me, &id); | ||
278 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECT BY PORT\n"); | ||
279 | ch1 = GNUNET_CADET_channel_create (cadet, NULL, &id, GC_u2h (1), | ||
280 | GNUNET_CADET_OPTION_DEFAULT); | ||
281 | nth = GNUNET_CADET_notify_transmit_ready (ch1, | ||
282 | GNUNET_NO, | ||
283 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
284 | size, | ||
285 | &do_send, | ||
286 | NULL); | ||
287 | } | ||
288 | |||
289 | |||
290 | /** | ||
291 | * Initialize framework and start test | ||
292 | * | ||
293 | * @param cls Closure (unused). | ||
294 | * @param cfg Configuration handle. | ||
295 | * @param peer Testing peer handle. | ||
296 | */ | ||
297 | static void | ||
298 | run (void *cls, | ||
299 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
300 | struct GNUNET_TESTING_Peer *peer) | ||
301 | { | ||
302 | me = peer; | ||
303 | GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); | ||
304 | abort_task = | ||
305 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
306 | (GNUNET_TIME_UNIT_SECONDS, 15), &do_abort, | ||
307 | NULL); | ||
308 | cadet = GNUNET_CADET_connect (cfg, /* configuration */ | ||
309 | (void *) 1L, /* cls */ | ||
310 | &channel_end, /* inbound end hndlr */ | ||
311 | handlers1); /* traffic handlers */ | ||
312 | port = GNUNET_CADET_open_port (cadet, | ||
313 | GC_u2h (1), | ||
314 | &inbound_channel, | ||
315 | (void *) 1L); | ||
316 | |||
317 | |||
318 | if (NULL == cadet) | ||
319 | { | ||
320 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
321 | "Couldn't connect to cadet :(\n"); | ||
322 | result = GNUNET_SYSERR; | ||
323 | return; | ||
324 | } | ||
325 | connect_task | ||
326 | = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
327 | &do_connect, | ||
328 | NULL); | ||
329 | } | ||
330 | |||
331 | |||
332 | /** | ||
333 | * Main | ||
334 | */ | ||
335 | int | ||
336 | main (int argc, | ||
337 | char *argv[]) | ||
338 | { | ||
339 | result = GNUNET_NO; | ||
340 | if (0 != GNUNET_TESTING_peer_run ("test-cadet-local", | ||
341 | "test_cadet.conf", | ||
342 | &run, NULL)) | ||
343 | { | ||
344 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
345 | "run failed\n"); | ||
346 | return 2; | ||
347 | } | ||
348 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
349 | "Final result: %d\n", | ||
350 | result); | ||
351 | return (result == GNUNET_OK) ? 0 : 1; | ||
352 | } | ||
353 | |||
354 | /* end of test_cadet_single.c */ | ||