diff options
author | Bart Polot <bart@net.in.tum.de> | 2014-05-07 12:07:16 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2014-05-07 12:07:16 +0000 |
commit | 41716952f1d0508fb621cb5fec31406d3bd96192 (patch) | |
tree | 0ea8e1a1397babe96db05d17cb7618fc69bb88c7 /src/cadet | |
parent | 74794f20cec6fbbd007e0921e7a347655050c024 (diff) | |
download | gnunet-41716952f1d0508fb621cb5fec31406d3bd96192.tar.gz gnunet-41716952f1d0508fb621cb5fec31406d3bd96192.zip |
Renamed directory
Diffstat (limited to 'src/cadet')
40 files changed, 24758 insertions, 0 deletions
diff --git a/src/cadet/Makefile.am b/src/cadet/Makefile.am new file mode 100644 index 000000000..e9aaec402 --- /dev/null +++ b/src/cadet/Makefile.am | |||
@@ -0,0 +1,194 @@ | |||
1 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
2 | |||
3 | if MINGW | ||
4 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
5 | endif | ||
6 | |||
7 | if USE_COVERAGE | ||
8 | AM_CFLAGS = --coverage -O0 | ||
9 | XLIB = -lgcov | ||
10 | endif | ||
11 | |||
12 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
13 | |||
14 | libexecdir= $(pkglibdir)/libexec/ | ||
15 | |||
16 | pkgcfg_DATA = \ | ||
17 | cadet.conf | ||
18 | |||
19 | plugindir = $(libdir)/gnunet | ||
20 | |||
21 | AM_CLFAGS = -g | ||
22 | |||
23 | libexec_PROGRAMS = \ | ||
24 | gnunet-service-cadet $(EXP_LIBEXEC) | ||
25 | |||
26 | bin_PROGRAMS = \ | ||
27 | gnunet-cadet | ||
28 | |||
29 | lib_LTLIBRARIES = \ | ||
30 | libgnunetcadet.la $(EXP_LIB) | ||
31 | |||
32 | libgnunetcadet_la_SOURCES = \ | ||
33 | cadet_api.c cadet_common.c | ||
34 | libgnunetcadet_la_LIBADD = \ | ||
35 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
36 | $(XLIB) \ | ||
37 | $(LTLIBINTL) | ||
38 | libgnunetcadet_la_LDFLAGS = \ | ||
39 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
40 | -version-info 5:0:0 | ||
41 | |||
42 | gnunet_cadet_SOURCES = \ | ||
43 | gnunet-cadet.c | ||
44 | gnunet_cadet_LDADD = \ | ||
45 | $(top_builddir)/src/cadet/libgnunetcadet.la \ | ||
46 | $(top_builddir)/src/util/libgnunetutil.la | ||
47 | gnunet_cadet_DEPENDENCIES = \ | ||
48 | libgnunetcadet.la | ||
49 | |||
50 | gnunet_service_cadet_SOURCES = \ | ||
51 | gnunet-service-cadet_tunnel.c gnunet-service-cadet_tunnel.h \ | ||
52 | gnunet-service-cadet_connection.c gnunet-service-cadet_connection.h \ | ||
53 | gnunet-service-cadet_channel.c gnunet-service-cadet_channel.h \ | ||
54 | gnunet-service-cadet_local.c gnunet-service-cadet_local.h \ | ||
55 | gnunet-service-cadet_peer.c gnunet-service-cadet_peer.h \ | ||
56 | gnunet-service-cadet_dht.c gnunet-service-cadet_dht.h \ | ||
57 | gnunet-service-cadet_hello.c gnunet-service-cadet_hello.h \ | ||
58 | cadet_path.c cadet_path.h \ | ||
59 | cadet_common.c \ | ||
60 | gnunet-service-cadet.c | ||
61 | gnunet_service_cadet_CFLAGS = $(AM_CFLAGS) | ||
62 | gnunet_service_cadet_LDADD = \ | ||
63 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
64 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
65 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
66 | $(top_builddir)/src/dht/libgnunetdht.la \ | ||
67 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
68 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ | ||
69 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
70 | $(top_builddir)/src/block/libgnunetblock.la | ||
71 | gnunet_service_cadet_DEPENDENCIES = \ | ||
72 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
73 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
74 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
75 | $(top_builddir)/src/dht/libgnunetdht.la \ | ||
76 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
77 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ | ||
78 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
79 | $(top_builddir)/src/block/libgnunetblock.la | ||
80 | if LINUX | ||
81 | gnunet_service_cadet_LDFLAGS = -lrt | ||
82 | endif | ||
83 | |||
84 | |||
85 | if HAVE_TESTING | ||
86 | noinst_LIBRARIES = libgnunetcadettest.a $(noinst_LIB_EXP) | ||
87 | noinst_PROGRAMS = gnunet-cadet-profiler | ||
88 | endif | ||
89 | |||
90 | libgnunetcadettest_a_SOURCES = \ | ||
91 | cadet_test_lib.c cadet_test_lib.h | ||
92 | libgnunetcadettest_a_LIBADD = \ | ||
93 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
94 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
95 | $(top_builddir)/src/cadet/libgnunetcadet.la | ||
96 | libgnunetcadettest_a_DEPENDENCIES = \ | ||
97 | libgnunetcadet.la | ||
98 | |||
99 | if HAVE_TESTING | ||
100 | check_PROGRAMS = \ | ||
101 | test_cadet_single \ | ||
102 | test_cadet_local \ | ||
103 | test_cadet_forward \ | ||
104 | test_cadet_signal \ | ||
105 | test_cadet_keepalive \ | ||
106 | test_cadet_speed \ | ||
107 | test_cadet_speed_ack \ | ||
108 | test_cadet_speed_backwards \ | ||
109 | test_cadet_speed_reliable \ | ||
110 | test_cadet_speed_reliable_backwards | ||
111 | endif | ||
112 | |||
113 | ld_cadet_test_lib = \ | ||
114 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
115 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
116 | $(top_builddir)/src/cadet/libgnunetcadettest.a \ | ||
117 | $(top_builddir)/src/cadet/libgnunetcadet.la \ | ||
118 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
119 | $(top_builddir)/src/statistics/libgnunetstatistics.la | ||
120 | |||
121 | dep_cadet_test_lib = \ | ||
122 | libgnunetcadet.la \ | ||
123 | libgnunetcadettest.a \ | ||
124 | $(top_builddir)/src/statistics/libgnunetstatistics.la | ||
125 | |||
126 | |||
127 | gnunet_cadet_profiler_SOURCES = \ | ||
128 | gnunet-cadet-profiler.c | ||
129 | gnunet_cadet_profiler_LDADD = $(ld_cadet_test_lib) | ||
130 | gnunet_cadet_profiler_DEPENDENCIES = $(dep_cadet_test_lib) | ||
131 | |||
132 | |||
133 | test_cadet_single_SOURCES = \ | ||
134 | test_cadet_single.c | ||
135 | test_cadet_single_LDADD = $(ld_cadet_test_lib) | ||
136 | test_cadet_single_DEPENDENCIES = $(dep_cadet_test_lib) | ||
137 | |||
138 | test_cadet_local_SOURCES = \ | ||
139 | test_cadet_local.c | ||
140 | test_cadet_local_LDADD = $(ld_cadet_test_lib) | ||
141 | test_cadet_local_DEPENDENCIES = $(dep_cadet_test_lib) | ||
142 | |||
143 | test_cadet_forward_SOURCES = \ | ||
144 | test_cadet.c | ||
145 | test_cadet_forward_LDADD = $(ld_cadet_test_lib) | ||
146 | test_cadet_forward_DEPENDENCIES = $(dep_cadet_test_lib) | ||
147 | |||
148 | test_cadet_signal_SOURCES = \ | ||
149 | test_cadet.c | ||
150 | test_cadet_signal_LDADD = $(ld_cadet_test_lib) | ||
151 | test_cadet_signal_DEPENDENCIES = $(dep_cadet_test_lib) | ||
152 | |||
153 | test_cadet_keepalive_SOURCES = \ | ||
154 | test_cadet.c | ||
155 | test_cadet_keepalive_LDADD = $(ld_cadet_test_lib) | ||
156 | test_cadet_keepalive_DEPENDENCIES = $(dep_cadet_test_lib) | ||
157 | |||
158 | test_cadet_speed_SOURCES = \ | ||
159 | test_cadet.c | ||
160 | test_cadet_speed_LDADD = $(ld_cadet_test_lib) | ||
161 | test_cadet_speed_DEPENDENCIES = $(dep_cadet_test_lib) | ||
162 | |||
163 | test_cadet_speed_ack_SOURCES = \ | ||
164 | test_cadet.c | ||
165 | test_cadet_speed_ack_LDADD = $(ld_cadet_test_lib) | ||
166 | test_cadet_speed_ack_DEPENDENCIES = $(dep_cadet_test_lib) | ||
167 | |||
168 | test_cadet_speed_backwards_SOURCES = \ | ||
169 | test_cadet.c | ||
170 | test_cadet_speed_backwards_LDADD = $(ld_cadet_test_lib) | ||
171 | test_cadet_speed_backwards_DEPENDENCIES = $(dep_cadet_test_lib) | ||
172 | |||
173 | test_cadet_speed_reliable_SOURCES = \ | ||
174 | test_cadet.c | ||
175 | test_cadet_speed_reliable_LDADD = $(ld_cadet_test_lib) | ||
176 | test_cadet_speed_reliable_DEPENDENCIES = $(dep_cadet_test_lib) | ||
177 | |||
178 | test_cadet_speed_reliable_backwards_SOURCES = \ | ||
179 | test_cadet.c | ||
180 | test_cadet_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib) | ||
181 | test_cadet_speed_reliable_backwards_DEPENDENCIES = $(dep_cadet_test_lib) | ||
182 | |||
183 | |||
184 | if ENABLE_TEST_RUN | ||
185 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH; | ||
186 | TESTS = \ | ||
187 | $(check_PROGRAMS) | ||
188 | endif | ||
189 | |||
190 | EXTRA_DIST = \ | ||
191 | cadet.h cadet_protocol.h \ | ||
192 | test_cadet.conf \ | ||
193 | test_cadet_drop.conf | ||
194 | |||
diff --git a/src/cadet/beautify_log.sh b/src/cadet/beautify_log.sh new file mode 100755 index 000000000..b12f20380 --- /dev/null +++ b/src/cadet/beautify_log.sh | |||
@@ -0,0 +1,18 @@ | |||
1 | #!/bin/sh | ||
2 | grep "STARTING SERVICE " log > __tmp_peers | ||
3 | SED_EXPR="" | ||
4 | while read -r line; do | ||
5 | PEER=`echo $line | sed -e 's/.*\[\(....\)\].*/\1/'` | ||
6 | PID=`echo $line | sed -e 's/.*mesh-\([0-9]*\).*/\1/'` | ||
7 | echo "$PID => $PEER" | ||
8 | SED_EXPR="${SED_EXPR}s/mesh-\([a-z2]*\)-$PID/MESH \1 $PEER/;" | ||
9 | SED_EXPR="${SED_EXPR}s/mesh-$PID/MESH XXX $PEER/;" | ||
10 | done < __tmp_peers | ||
11 | rm __tmp_peers | ||
12 | |||
13 | SED_EXPR="${SED_EXPR}s/mesh-api-/mesh-api- /g" | ||
14 | sed -e "$SED_EXPR" log > .log | ||
15 | |||
16 | if [[ "`ps aux | grep "kwrite .lo[g]"`" = "" ]]; then | ||
17 | kwrite .log --geometry 960x1140-960 & | ||
18 | fi | ||
diff --git a/src/cadet/cadet.h b/src/cadet/cadet.h new file mode 100644 index 000000000..757f8c501 --- /dev/null +++ b/src/cadet/cadet.h | |||
@@ -0,0 +1,351 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2001 - 2011 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @author Bartlomiej Polot | ||
23 | * @file cadet/cadet.h | ||
24 | */ | ||
25 | |||
26 | #ifndef CADET_H_ | ||
27 | #define CADET_H_ | ||
28 | |||
29 | #ifdef __cplusplus | ||
30 | extern "C" | ||
31 | { | ||
32 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
33 | } | ||
34 | #endif | ||
35 | #endif | ||
36 | |||
37 | #include <stdint.h> | ||
38 | |||
39 | #define CADET_DEBUG GNUNET_YES | ||
40 | |||
41 | #include "platform.h" | ||
42 | #include "gnunet_util_lib.h" | ||
43 | #include "gnunet_peer_lib.h" | ||
44 | #include "gnunet_core_service.h" | ||
45 | #include "gnunet_protocols.h" | ||
46 | #include <gnunet_cadet_service.h> | ||
47 | |||
48 | /******************************************************************************/ | ||
49 | /************************** CONSTANTS ******************************/ | ||
50 | /******************************************************************************/ | ||
51 | |||
52 | #define GNUNET_CADET_LOCAL_CHANNEL_ID_CLI 0x80000000 | ||
53 | #define GNUNET_CADET_LOCAL_CHANNEL_ID_SERV 0xB0000000 | ||
54 | |||
55 | #define HIGH_PID 0xFFFF0000 | ||
56 | #define LOW_PID 0x0000FFFF | ||
57 | |||
58 | #define PID_OVERFLOW(pid, max) (pid > HIGH_PID && max < LOW_PID) | ||
59 | |||
60 | /******************************************************************************/ | ||
61 | /************************** MESSAGES ******************************/ | ||
62 | /******************************************************************************/ | ||
63 | |||
64 | GNUNET_NETWORK_STRUCT_BEGIN | ||
65 | |||
66 | /** | ||
67 | * Message for a client to register to the service | ||
68 | */ | ||
69 | struct GNUNET_CADET_ClientConnect | ||
70 | { | ||
71 | /** | ||
72 | * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT | ||
73 | * | ||
74 | * Size: sizeof(struct GNUNET_CADET_ClientConnect) + | ||
75 | * sizeof(CADET_ApplicationType) * applications + | ||
76 | * sizeof(uint16_t) * types | ||
77 | */ | ||
78 | struct GNUNET_MessageHeader header; | ||
79 | /* uint32_t list_ports[] */ | ||
80 | }; | ||
81 | |||
82 | |||
83 | /** | ||
84 | * Type for channel numbering. | ||
85 | * - Local channel numbers given by the service (incoming) are >= 0xB0000000 | ||
86 | * - Local channel numbers given by the client (created) are >= 0x80000000 | ||
87 | * - Global channel numbers are < 0x80000000 | ||
88 | */ | ||
89 | typedef uint32_t CADET_ChannelNumber; | ||
90 | |||
91 | |||
92 | /** | ||
93 | * Message for a client to create and destroy channels. | ||
94 | */ | ||
95 | struct GNUNET_CADET_ChannelMessage | ||
96 | { | ||
97 | /** | ||
98 | * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_TUNNEL_[CREATE|DESTROY] | ||
99 | * | ||
100 | * Size: sizeof(struct GNUNET_CADET_ChannelMessage) | ||
101 | */ | ||
102 | struct GNUNET_MessageHeader header; | ||
103 | |||
104 | /** | ||
105 | * ID of a channel controlled by this client. | ||
106 | */ | ||
107 | CADET_ChannelNumber channel_id GNUNET_PACKED; | ||
108 | |||
109 | /** | ||
110 | * Channel's peer | ||
111 | */ | ||
112 | struct GNUNET_PeerIdentity peer; | ||
113 | |||
114 | /** | ||
115 | * Port of the channel. | ||
116 | */ | ||
117 | uint32_t port GNUNET_PACKED; | ||
118 | |||
119 | /** | ||
120 | * Options. | ||
121 | */ | ||
122 | uint32_t opt GNUNET_PACKED; | ||
123 | }; | ||
124 | |||
125 | |||
126 | /** | ||
127 | * Message for cadet data traffic. | ||
128 | */ | ||
129 | struct GNUNET_CADET_LocalData | ||
130 | { | ||
131 | /** | ||
132 | * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA | ||
133 | */ | ||
134 | struct GNUNET_MessageHeader header; | ||
135 | |||
136 | /** | ||
137 | * ID of the channel | ||
138 | */ | ||
139 | uint32_t id GNUNET_PACKED; | ||
140 | |||
141 | /** | ||
142 | * Payload follows | ||
143 | */ | ||
144 | }; | ||
145 | |||
146 | |||
147 | /** | ||
148 | * Message to allow the client send more data to the service | ||
149 | * (always service -> client). | ||
150 | */ | ||
151 | struct GNUNET_CADET_LocalAck | ||
152 | { | ||
153 | /** | ||
154 | * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK | ||
155 | */ | ||
156 | struct GNUNET_MessageHeader header; | ||
157 | |||
158 | /** | ||
159 | * ID of the channel allowed to send more data. | ||
160 | */ | ||
161 | CADET_ChannelNumber channel_id GNUNET_PACKED; | ||
162 | |||
163 | }; | ||
164 | |||
165 | |||
166 | /** | ||
167 | * Message to inform the client about channels in the service. | ||
168 | */ | ||
169 | struct GNUNET_CADET_LocalInfo | ||
170 | { | ||
171 | /** | ||
172 | * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO[_TUNNEL,_PEER] | ||
173 | */ | ||
174 | struct GNUNET_MessageHeader header; | ||
175 | |||
176 | /** | ||
177 | * ID of the channel allowed to send more data. | ||
178 | */ | ||
179 | CADET_ChannelNumber channel_id GNUNET_PACKED; | ||
180 | |||
181 | /** | ||
182 | * ID of the owner of the channel (can be local peer). | ||
183 | */ | ||
184 | // struct GNUNET_PeerIdentity owner; | ||
185 | |||
186 | /** | ||
187 | * ID of the destination of the channel (can be local peer). | ||
188 | */ | ||
189 | struct GNUNET_PeerIdentity peer; | ||
190 | }; | ||
191 | |||
192 | |||
193 | /** | ||
194 | * Message to inform the client about one of the peers in the service. | ||
195 | */ | ||
196 | struct GNUNET_CADET_LocalInfoPeer | ||
197 | { | ||
198 | /** | ||
199 | * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER[S] | ||
200 | */ | ||
201 | struct GNUNET_MessageHeader header; | ||
202 | |||
203 | /** | ||
204 | * Number of paths. | ||
205 | */ | ||
206 | uint16_t paths GNUNET_PACKED; | ||
207 | |||
208 | /** | ||
209 | * Do we have a tunnel toward this peer? | ||
210 | */ | ||
211 | int16_t tunnel GNUNET_PACKED; | ||
212 | |||
213 | /** | ||
214 | * ID of the destination of the tunnel (can be local peer). | ||
215 | */ | ||
216 | struct GNUNET_PeerIdentity destination; | ||
217 | |||
218 | /* If type == PEER (no 'S'): GNUNET_PeerIdentity paths[] | ||
219 | * (each path ends in destination) */ | ||
220 | }; | ||
221 | |||
222 | /** | ||
223 | * Message to inform the client about one of the tunnels in the service. | ||
224 | */ | ||
225 | struct GNUNET_CADET_LocalInfoTunnel | ||
226 | { | ||
227 | /** | ||
228 | * Type: GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL[S] | ||
229 | */ | ||
230 | struct GNUNET_MessageHeader header; | ||
231 | |||
232 | /** | ||
233 | * Number of channels. | ||
234 | */ | ||
235 | uint32_t channels GNUNET_PACKED; | ||
236 | |||
237 | /** | ||
238 | * ID of the destination of the tunnel (can be local peer). | ||
239 | */ | ||
240 | struct GNUNET_PeerIdentity destination; | ||
241 | |||
242 | /** | ||
243 | * Number of connections. | ||
244 | */ | ||
245 | uint32_t connections GNUNET_PACKED; | ||
246 | |||
247 | /** | ||
248 | * Encryption state. | ||
249 | */ | ||
250 | uint16_t estate GNUNET_PACKED; | ||
251 | |||
252 | /** | ||
253 | * Connection state. | ||
254 | */ | ||
255 | uint16_t cstate GNUNET_PACKED; | ||
256 | |||
257 | /* If TUNNEL (no 'S'): GNUNET_PeerIdentity connection_ids[connections] */ | ||
258 | /* If TUNNEL (no 'S'): uint32_t channel_ids[channels] */ | ||
259 | }; | ||
260 | |||
261 | |||
262 | GNUNET_NETWORK_STRUCT_END | ||
263 | |||
264 | |||
265 | |||
266 | /** | ||
267 | * @brief Translate a fwd variable into a string representation, for logging. | ||
268 | * | ||
269 | * @param fwd Is FWD? (#GNUNET_YES or #GNUNET_NO) | ||
270 | * | ||
271 | * @return String representing FWD or BCK. | ||
272 | */ | ||
273 | char * | ||
274 | GM_f2s (int fwd); | ||
275 | |||
276 | |||
277 | /** | ||
278 | * Check if one pid is bigger than other, accounting for overflow. | ||
279 | * | ||
280 | * @param bigger Argument that should be bigger. | ||
281 | * @param smaller Argument that should be smaller. | ||
282 | * | ||
283 | * @return True if bigger (arg1) has a higher value than smaller (arg 2). | ||
284 | */ | ||
285 | int | ||
286 | GM_is_pid_bigger (uint32_t bigger, uint32_t smaller); | ||
287 | |||
288 | |||
289 | /** | ||
290 | * Get the higher ACK value out of two values, taking in account overflow. | ||
291 | * | ||
292 | * @param a First ACK value. | ||
293 | * @param b Second ACK value. | ||
294 | * | ||
295 | * @return Highest ACK value from the two. | ||
296 | */ | ||
297 | uint32_t | ||
298 | GM_max_pid (uint32_t a, uint32_t b); | ||
299 | |||
300 | |||
301 | /** | ||
302 | * Get the lower ACK value out of two values, taking in account overflow. | ||
303 | * | ||
304 | * @param a First ACK value. | ||
305 | * @param b Second ACK value. | ||
306 | * | ||
307 | * @return Lowest ACK value from the two. | ||
308 | */ | ||
309 | uint32_t | ||
310 | GM_min_pid (uint32_t a, uint32_t b); | ||
311 | |||
312 | |||
313 | /** | ||
314 | * Convert a 256 bit CadetHash into a 512 HashCode to use in GNUNET_h2s, | ||
315 | * multihashmap, and other HashCode-based functions. | ||
316 | * | ||
317 | * @param id A 256 bit hash to expand. | ||
318 | * | ||
319 | * @return A HashCode containing the original 256 bit hash right-padded with 0. | ||
320 | */ | ||
321 | const struct GNUNET_HashCode * | ||
322 | GM_h2hc (const struct GNUNET_CADET_Hash *id); | ||
323 | |||
324 | /** | ||
325 | * Get a string from a Cadet Hash (256 bits). | ||
326 | * WARNING: Not reentrant (based on GNUNET_h2s). | ||
327 | */ | ||
328 | const char * | ||
329 | GM_h2s (const struct GNUNET_CADET_Hash *id); | ||
330 | |||
331 | /** | ||
332 | * Convert a message type into a string to help debug | ||
333 | * Generated with: | ||
334 | * FIND: "#define ([^ ]+)[ ]*([0-9]+)" | ||
335 | * REPLACE: " case \2: return "\1"; break;" | ||
336 | * | ||
337 | * @param m Message type. | ||
338 | * | ||
339 | * @return Human readable string description. | ||
340 | */ | ||
341 | const char * | ||
342 | GM_m2s (uint16_t m); | ||
343 | |||
344 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
345 | { | ||
346 | #endif | ||
347 | #ifdef __cplusplus | ||
348 | } | ||
349 | #endif | ||
350 | |||
351 | #endif | ||
diff --git a/src/cadet/cadet_api.c b/src/cadet/cadet_api.c new file mode 100644 index 000000000..aa5c67329 --- /dev/null +++ b/src/cadet/cadet_api.c | |||
@@ -0,0 +1,2141 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2011 Christian Grothoff (and other contributing authors) | ||
4 | GNUnet is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published | ||
6 | by the Free Software Foundation; either version 3, or (at your | ||
7 | option) any later version. | ||
8 | GNUnet is distributed in the hope that it will be useful, but | ||
9 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
11 | General Public License for more details. | ||
12 | You should have received a copy of the GNU General Public License | ||
13 | along with GNUnet; see the file COPYING. If not, write to the | ||
14 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
15 | Boston, MA 02111-1307, USA. | ||
16 | */ | ||
17 | |||
18 | /** | ||
19 | * @file cadet/cadet_api.c | ||
20 | * @brief cadet api: client implementation of new cadet service | ||
21 | * @author Bartlomiej Polot | ||
22 | */ | ||
23 | |||
24 | #include "platform.h" | ||
25 | #include "gnunet_util_lib.h" | ||
26 | #include "gnunet_cadet_service.h" | ||
27 | #include "cadet.h" | ||
28 | #include "cadet_protocol.h" | ||
29 | |||
30 | #define LOG(kind,...) GNUNET_log_from (kind, "cadet-api",__VA_ARGS__) | ||
31 | |||
32 | /******************************************************************************/ | ||
33 | /************************ DATA STRUCTURES ****************************/ | ||
34 | /******************************************************************************/ | ||
35 | |||
36 | /** | ||
37 | * Transmission queue to the service | ||
38 | */ | ||
39 | struct GNUNET_CADET_TransmitHandle | ||
40 | { | ||
41 | |||
42 | /** | ||
43 | * Double Linked list | ||
44 | */ | ||
45 | struct GNUNET_CADET_TransmitHandle *next; | ||
46 | |||
47 | /** | ||
48 | * Double Linked list | ||
49 | */ | ||
50 | struct GNUNET_CADET_TransmitHandle *prev; | ||
51 | |||
52 | /** | ||
53 | * Channel this message is sent on / for (may be NULL for control messages). | ||
54 | */ | ||
55 | struct GNUNET_CADET_Channel *channel; | ||
56 | |||
57 | /** | ||
58 | * Callback to obtain the message to transmit, or NULL if we | ||
59 | * got the message in 'data'. Notice that messages built | ||
60 | * by 'notify' need to be encapsulated with information about | ||
61 | * the 'target'. | ||
62 | */ | ||
63 | GNUNET_CONNECTION_TransmitReadyNotify notify; | ||
64 | |||
65 | /** | ||
66 | * Closure for 'notify' | ||
67 | */ | ||
68 | void *notify_cls; | ||
69 | |||
70 | /** | ||
71 | * How long is this message valid. Once the timeout has been | ||
72 | * reached, the message must no longer be sent. If this | ||
73 | * is a message with a 'notify' callback set, the 'notify' | ||
74 | * function should be called with 'buf' NULL and size 0. | ||
75 | */ | ||
76 | struct GNUNET_TIME_Absolute timeout; | ||
77 | |||
78 | /** | ||
79 | * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER. | ||
80 | */ | ||
81 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | ||
82 | |||
83 | /** | ||
84 | * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL. | ||
85 | */ | ||
86 | size_t size; | ||
87 | }; | ||
88 | |||
89 | union CadetInfoCB { | ||
90 | |||
91 | /** | ||
92 | * Channel callback. | ||
93 | */ | ||
94 | GNUNET_CADET_ChannelCB channel_cb; | ||
95 | |||
96 | /** | ||
97 | * Monitor callback | ||
98 | */ | ||
99 | GNUNET_CADET_PeersCB peers_cb; | ||
100 | |||
101 | /** | ||
102 | * Monitor callback | ||
103 | */ | ||
104 | GNUNET_CADET_PeerCB peer_cb; | ||
105 | |||
106 | /** | ||
107 | * Monitor callback | ||
108 | */ | ||
109 | GNUNET_CADET_TunnelsCB tunnels_cb; | ||
110 | |||
111 | /** | ||
112 | * Tunnel callback. | ||
113 | */ | ||
114 | GNUNET_CADET_TunnelCB tunnel_cb; | ||
115 | }; | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Opaque handle to the service. | ||
120 | */ | ||
121 | struct GNUNET_CADET_Handle | ||
122 | { | ||
123 | |||
124 | /** | ||
125 | * Handle to the server connection, to send messages later | ||
126 | */ | ||
127 | struct GNUNET_CLIENT_Connection *client; | ||
128 | |||
129 | /** | ||
130 | * Set of handlers used for processing incoming messages in the channels | ||
131 | */ | ||
132 | const struct GNUNET_CADET_MessageHandler *message_handlers; | ||
133 | |||
134 | /** | ||
135 | * Number of handlers in the handlers array. | ||
136 | */ | ||
137 | unsigned int n_handlers; | ||
138 | |||
139 | /** | ||
140 | * Ports open. | ||
141 | */ | ||
142 | const uint32_t *ports; | ||
143 | |||
144 | /** | ||
145 | * Number of ports. | ||
146 | */ | ||
147 | unsigned int n_ports; | ||
148 | |||
149 | /** | ||
150 | * Double linked list of the channels this client is connected to, head. | ||
151 | */ | ||
152 | struct GNUNET_CADET_Channel *channels_head; | ||
153 | |||
154 | /** | ||
155 | * Double linked list of the channels this client is connected to, tail. | ||
156 | */ | ||
157 | struct GNUNET_CADET_Channel *channels_tail; | ||
158 | |||
159 | /** | ||
160 | * Callback for inbound channel creation | ||
161 | */ | ||
162 | GNUNET_CADET_InboundChannelNotificationHandler *new_channel; | ||
163 | |||
164 | /** | ||
165 | * Callback for inbound channel disconnection | ||
166 | */ | ||
167 | GNUNET_CADET_ChannelEndHandler *cleaner; | ||
168 | |||
169 | /** | ||
170 | * Handle to cancel pending transmissions in case of disconnection | ||
171 | */ | ||
172 | struct GNUNET_CLIENT_TransmitHandle *th; | ||
173 | |||
174 | /** | ||
175 | * Closure for all the handlers given by the client | ||
176 | */ | ||
177 | void *cls; | ||
178 | |||
179 | /** | ||
180 | * Messages to send to the service, head. | ||
181 | */ | ||
182 | struct GNUNET_CADET_TransmitHandle *th_head; | ||
183 | |||
184 | /** | ||
185 | * Messages to send to the service, tail. | ||
186 | */ | ||
187 | struct GNUNET_CADET_TransmitHandle *th_tail; | ||
188 | |||
189 | /** | ||
190 | * chid of the next channel to create (to avoid reusing IDs often) | ||
191 | */ | ||
192 | CADET_ChannelNumber next_chid; | ||
193 | |||
194 | /** | ||
195 | * Have we started the task to receive messages from the service | ||
196 | * yet? We do this after we send the 'CADET_LOCAL_CONNECT' message. | ||
197 | */ | ||
198 | int in_receive; | ||
199 | |||
200 | /** | ||
201 | * Configuration given by the client, in case of reconnection | ||
202 | */ | ||
203 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
204 | |||
205 | /** | ||
206 | * Time to the next reconnect in case one reconnect fails | ||
207 | */ | ||
208 | struct GNUNET_TIME_Relative reconnect_time; | ||
209 | |||
210 | /** | ||
211 | * Task for trying to reconnect. | ||
212 | */ | ||
213 | GNUNET_SCHEDULER_TaskIdentifier reconnect_task; | ||
214 | |||
215 | /** | ||
216 | * Callback for an info task (only one active at a time). | ||
217 | */ | ||
218 | union CadetInfoCB info_cb; | ||
219 | |||
220 | /** | ||
221 | * Info callback closure for @c info_cb. | ||
222 | */ | ||
223 | void *info_cls; | ||
224 | }; | ||
225 | |||
226 | |||
227 | /** | ||
228 | * Description of a peer | ||
229 | */ | ||
230 | struct GNUNET_CADET_Peer | ||
231 | { | ||
232 | /** | ||
233 | * ID of the peer in short form | ||
234 | */ | ||
235 | GNUNET_PEER_Id id; | ||
236 | |||
237 | /** | ||
238 | * Channel this peer belongs to | ||
239 | */ | ||
240 | struct GNUNET_CADET_Channel *t; | ||
241 | }; | ||
242 | |||
243 | |||
244 | /** | ||
245 | * Opaque handle to a channel. | ||
246 | */ | ||
247 | struct GNUNET_CADET_Channel | ||
248 | { | ||
249 | |||
250 | /** | ||
251 | * DLL next | ||
252 | */ | ||
253 | struct GNUNET_CADET_Channel *next; | ||
254 | |||
255 | /** | ||
256 | * DLL prev | ||
257 | */ | ||
258 | struct GNUNET_CADET_Channel *prev; | ||
259 | |||
260 | /** | ||
261 | * Handle to the cadet this channel belongs to | ||
262 | */ | ||
263 | struct GNUNET_CADET_Handle *cadet; | ||
264 | |||
265 | /** | ||
266 | * Local ID of the channel | ||
267 | */ | ||
268 | CADET_ChannelNumber chid; | ||
269 | |||
270 | /** | ||
271 | * Port number. | ||
272 | */ | ||
273 | uint32_t port; | ||
274 | |||
275 | /** | ||
276 | * Other end of the channel. | ||
277 | */ | ||
278 | GNUNET_PEER_Id peer; | ||
279 | |||
280 | /** | ||
281 | * Any data the caller wants to put in here | ||
282 | */ | ||
283 | void *ctx; | ||
284 | |||
285 | /** | ||
286 | * Size of packet queued in this channel | ||
287 | */ | ||
288 | unsigned int packet_size; | ||
289 | |||
290 | /** | ||
291 | * Channel options: reliability, etc. | ||
292 | */ | ||
293 | enum GNUNET_CADET_ChannelOption options; | ||
294 | |||
295 | /** | ||
296 | * Are we allowed to send to the service? | ||
297 | */ | ||
298 | int allow_send; | ||
299 | |||
300 | }; | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Implementation state for cadet's message queue. | ||
305 | */ | ||
306 | struct CadetMQState | ||
307 | { | ||
308 | /** | ||
309 | * The current transmit handle, or NULL | ||
310 | * if no transmit is active. | ||
311 | */ | ||
312 | struct GNUNET_CADET_TransmitHandle *th; | ||
313 | |||
314 | /** | ||
315 | * Channel to send the data over. | ||
316 | */ | ||
317 | struct GNUNET_CADET_Channel *channel; | ||
318 | }; | ||
319 | |||
320 | |||
321 | /******************************************************************************/ | ||
322 | /*********************** DECLARATIONS *************************/ | ||
323 | /******************************************************************************/ | ||
324 | |||
325 | /** | ||
326 | * Function called to send a message to the service. | ||
327 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | ||
328 | * the meantime. | ||
329 | * | ||
330 | * @param cls closure, the cadet handle | ||
331 | * @param size number of bytes available in buf | ||
332 | * @param buf where the callee should write the connect message | ||
333 | * @return number of bytes written to buf | ||
334 | */ | ||
335 | static size_t | ||
336 | send_callback (void *cls, size_t size, void *buf); | ||
337 | |||
338 | |||
339 | /******************************************************************************/ | ||
340 | /*********************** AUXILIARY FUNCTIONS *************************/ | ||
341 | /******************************************************************************/ | ||
342 | |||
343 | /** | ||
344 | * Check if transmission is a payload packet. | ||
345 | * | ||
346 | * @param th Transmission handle. | ||
347 | * | ||
348 | * @return GNUNET_YES if it is a payload packet, | ||
349 | * GNUNET_NO if it is a cadet management packet. | ||
350 | */ | ||
351 | static int | ||
352 | th_is_payload (struct GNUNET_CADET_TransmitHandle *th) | ||
353 | { | ||
354 | return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO; | ||
355 | } | ||
356 | |||
357 | |||
358 | /** | ||
359 | * Check whether there is any message ready in the queue and find the size. | ||
360 | * | ||
361 | * @param h Cadet handle. | ||
362 | * | ||
363 | * @return The size of the first ready message in the queue, | ||
364 | * 0 if there is none. | ||
365 | */ | ||
366 | static size_t | ||
367 | message_ready_size (struct GNUNET_CADET_Handle *h) | ||
368 | { | ||
369 | struct GNUNET_CADET_TransmitHandle *th; | ||
370 | struct GNUNET_CADET_Channel *ch; | ||
371 | |||
372 | for (th = h->th_head; NULL != th; th = th->next) | ||
373 | { | ||
374 | ch = th->channel; | ||
375 | if (GNUNET_NO == th_is_payload (th)) | ||
376 | { | ||
377 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# message internal\n"); | ||
378 | return th->size; | ||
379 | } | ||
380 | if (GNUNET_YES == ch->allow_send) | ||
381 | { | ||
382 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# message payload ok\n"); | ||
383 | return th->size; | ||
384 | } | ||
385 | } | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | |||
390 | /** | ||
391 | * Get the channel handler for the channel specified by id from the given handle | ||
392 | * @param h Cadet handle | ||
393 | * @param chid ID of the wanted channel | ||
394 | * @return handle to the required channel or NULL if not found | ||
395 | */ | ||
396 | static struct GNUNET_CADET_Channel * | ||
397 | retrieve_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid) | ||
398 | { | ||
399 | struct GNUNET_CADET_Channel *ch; | ||
400 | |||
401 | ch = h->channels_head; | ||
402 | while (ch != NULL) | ||
403 | { | ||
404 | if (ch->chid == chid) | ||
405 | return ch; | ||
406 | ch = ch->next; | ||
407 | } | ||
408 | return NULL; | ||
409 | } | ||
410 | |||
411 | |||
412 | /** | ||
413 | * Create a new channel and insert it in the channel list of the cadet handle | ||
414 | * | ||
415 | * @param h Cadet handle | ||
416 | * @param chid Desired chid of the channel, 0 to assign one automatically. | ||
417 | * | ||
418 | * @return Handle to the created channel. | ||
419 | */ | ||
420 | static struct GNUNET_CADET_Channel * | ||
421 | create_channel (struct GNUNET_CADET_Handle *h, CADET_ChannelNumber chid) | ||
422 | { | ||
423 | struct GNUNET_CADET_Channel *ch; | ||
424 | |||
425 | ch = GNUNET_new (struct GNUNET_CADET_Channel); | ||
426 | GNUNET_CONTAINER_DLL_insert (h->channels_head, h->channels_tail, ch); | ||
427 | ch->cadet = h; | ||
428 | if (0 == chid) | ||
429 | { | ||
430 | ch->chid = h->next_chid; | ||
431 | while (NULL != retrieve_channel (h, h->next_chid)) | ||
432 | { | ||
433 | h->next_chid++; | ||
434 | h->next_chid &= ~GNUNET_CADET_LOCAL_CHANNEL_ID_SERV; | ||
435 | h->next_chid |= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; | ||
436 | } | ||
437 | } | ||
438 | else | ||
439 | { | ||
440 | ch->chid = chid; | ||
441 | } | ||
442 | ch->allow_send = GNUNET_NO; | ||
443 | return ch; | ||
444 | } | ||
445 | |||
446 | |||
447 | /** | ||
448 | * Destroy the specified channel. | ||
449 | * - Destroys all peers, calling the disconnect callback on each if needed | ||
450 | * - Cancels all outgoing traffic for that channel, calling respective notifys | ||
451 | * - Calls cleaner if channel was inbound | ||
452 | * - Frees all memory used | ||
453 | * | ||
454 | * @param ch Pointer to the channel. | ||
455 | * @param call_cleaner Whether to call the cleaner handler. | ||
456 | * | ||
457 | * @return Handle to the required channel or NULL if not found. | ||
458 | */ | ||
459 | static void | ||
460 | destroy_channel (struct GNUNET_CADET_Channel *ch, int call_cleaner) | ||
461 | { | ||
462 | struct GNUNET_CADET_Handle *h; | ||
463 | struct GNUNET_CADET_TransmitHandle *th; | ||
464 | struct GNUNET_CADET_TransmitHandle *next; | ||
465 | |||
466 | LOG (GNUNET_ERROR_TYPE_DEBUG, " destroy_channel %X\n", ch->chid); | ||
467 | |||
468 | if (NULL == ch) | ||
469 | { | ||
470 | GNUNET_break (0); | ||
471 | return; | ||
472 | } | ||
473 | h = ch->cadet; | ||
474 | |||
475 | GNUNET_CONTAINER_DLL_remove (h->channels_head, h->channels_tail, ch); | ||
476 | |||
477 | /* signal channel destruction */ | ||
478 | if ( (NULL != h->cleaner) && (0 != ch->peer) && (GNUNET_YES == call_cleaner) ) | ||
479 | { | ||
480 | LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cleaner\n"); | ||
481 | h->cleaner (h->cls, ch, ch->ctx); | ||
482 | } | ||
483 | |||
484 | /* check that clients did not leave messages behind in the queue */ | ||
485 | for (th = h->th_head; NULL != th; th = next) | ||
486 | { | ||
487 | next = th->next; | ||
488 | if (th->channel != ch) | ||
489 | continue; | ||
490 | /* Clients should have aborted their requests already. | ||
491 | * Management traffic should be ok, as clients can't cancel that. | ||
492 | * If the service crashed and we are reconnecting, it's ok. | ||
493 | */ | ||
494 | GNUNET_break (GNUNET_NO == th_is_payload (th) | ||
495 | || GNUNET_NO == h->in_receive); | ||
496 | GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); | ||
497 | |||
498 | /* clean up request */ | ||
499 | if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task) | ||
500 | GNUNET_SCHEDULER_cancel (th->timeout_task); | ||
501 | GNUNET_free (th); | ||
502 | } | ||
503 | |||
504 | /* if there are no more pending requests with cadet service, cancel active request */ | ||
505 | /* Note: this should be unnecessary... */ | ||
506 | if ((0 == message_ready_size (h)) && (NULL != h->th)) | ||
507 | { | ||
508 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); | ||
509 | h->th = NULL; | ||
510 | } | ||
511 | |||
512 | if (0 != ch->peer) | ||
513 | GNUNET_PEER_change_rc (ch->peer, -1); | ||
514 | GNUNET_free (ch); | ||
515 | return; | ||
516 | } | ||
517 | |||
518 | |||
519 | /** | ||
520 | * Notify client that the transmission has timed out | ||
521 | * | ||
522 | * @param cls closure | ||
523 | * @param tc task context | ||
524 | */ | ||
525 | static void | ||
526 | timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
527 | { | ||
528 | struct GNUNET_CADET_TransmitHandle *th = cls; | ||
529 | struct GNUNET_CADET_Handle *cadet; | ||
530 | |||
531 | cadet = th->channel->cadet; | ||
532 | GNUNET_CONTAINER_DLL_remove (cadet->th_head, cadet->th_tail, th); | ||
533 | th->channel->packet_size = 0; | ||
534 | if (GNUNET_YES == th_is_payload (th)) | ||
535 | th->notify (th->notify_cls, 0, NULL); | ||
536 | GNUNET_free (th); | ||
537 | if ((0 == message_ready_size (cadet)) && (NULL != cadet->th)) | ||
538 | { | ||
539 | /* nothing ready to transmit, no point in asking for transmission */ | ||
540 | GNUNET_CLIENT_notify_transmit_ready_cancel (cadet->th); | ||
541 | cadet->th = NULL; | ||
542 | } | ||
543 | } | ||
544 | |||
545 | |||
546 | /** | ||
547 | * Add a transmit handle to the transmission queue and set the | ||
548 | * timeout if needed. | ||
549 | * | ||
550 | * @param h cadet handle with the queue head and tail | ||
551 | * @param th handle to the packet to be transmitted | ||
552 | */ | ||
553 | static void | ||
554 | add_to_queue (struct GNUNET_CADET_Handle *h, | ||
555 | struct GNUNET_CADET_TransmitHandle *th) | ||
556 | { | ||
557 | GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th); | ||
558 | if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us == th->timeout.abs_value_us) | ||
559 | return; | ||
560 | th->timeout_task = | ||
561 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining | ||
562 | (th->timeout), &timeout_transmission, th); | ||
563 | } | ||
564 | |||
565 | |||
566 | /** | ||
567 | * Auxiliary function to send an already constructed packet to the service. | ||
568 | * Takes care of creating a new queue element, copying the message and | ||
569 | * calling the tmt_rdy function if necessary. | ||
570 | * | ||
571 | * @param h cadet handle | ||
572 | * @param msg message to transmit | ||
573 | * @param channel channel this send is related to (NULL if N/A) | ||
574 | */ | ||
575 | static void | ||
576 | send_packet (struct GNUNET_CADET_Handle *h, | ||
577 | const struct GNUNET_MessageHeader *msg, | ||
578 | struct GNUNET_CADET_Channel *channel); | ||
579 | |||
580 | |||
581 | /** | ||
582 | * Send an ack on the channel to confirm the processing of a message. | ||
583 | * | ||
584 | * @param ch Channel on which to send the ACK. | ||
585 | */ | ||
586 | static void | ||
587 | send_ack (struct GNUNET_CADET_Channel *ch) | ||
588 | { | ||
589 | struct GNUNET_CADET_LocalAck msg; | ||
590 | |||
591 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ACK on channel %X\n", ch->chid); | ||
592 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | ||
593 | msg.header.size = htons (sizeof (msg)); | ||
594 | msg.channel_id = htonl (ch->chid); | ||
595 | |||
596 | send_packet (ch->cadet, &msg.header, ch); | ||
597 | return; | ||
598 | } | ||
599 | |||
600 | |||
601 | |||
602 | /** | ||
603 | * Reconnect callback: tries to reconnect again after a failer previous | ||
604 | * reconnecttion | ||
605 | * @param cls closure (cadet handle) | ||
606 | * @param tc task context | ||
607 | */ | ||
608 | static void | ||
609 | reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
610 | |||
611 | |||
612 | /** | ||
613 | * Send a connect packet to the service with the applications and types | ||
614 | * requested by the user. | ||
615 | * | ||
616 | * @param h The cadet handle. | ||
617 | * | ||
618 | */ | ||
619 | static void | ||
620 | send_connect (struct GNUNET_CADET_Handle *h) | ||
621 | { | ||
622 | size_t size; | ||
623 | |||
624 | size = sizeof (struct GNUNET_CADET_ClientConnect); | ||
625 | size += h->n_ports * sizeof (uint32_t); | ||
626 | { | ||
627 | char buf[size] GNUNET_ALIGN; | ||
628 | struct GNUNET_CADET_ClientConnect *msg; | ||
629 | uint32_t *ports; | ||
630 | uint16_t i; | ||
631 | |||
632 | /* build connection packet */ | ||
633 | msg = (struct GNUNET_CADET_ClientConnect *) buf; | ||
634 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT); | ||
635 | msg->header.size = htons (size); | ||
636 | ports = (uint32_t *) &msg[1]; | ||
637 | for (i = 0; i < h->n_ports; i++) | ||
638 | { | ||
639 | ports[i] = htonl (h->ports[i]); | ||
640 | LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n", | ||
641 | h->ports[i]); | ||
642 | } | ||
643 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
644 | "Sending %lu bytes long message with %u ports\n", | ||
645 | ntohs (msg->header.size), h->n_ports); | ||
646 | send_packet (h, &msg->header, NULL); | ||
647 | } | ||
648 | } | ||
649 | |||
650 | |||
651 | /** | ||
652 | * Reconnect to the service, retransmit all infomation to try to restore the | ||
653 | * original state. | ||
654 | * | ||
655 | * @param h handle to the cadet | ||
656 | * | ||
657 | * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...) | ||
658 | */ | ||
659 | static int | ||
660 | do_reconnect (struct GNUNET_CADET_Handle *h) | ||
661 | { | ||
662 | LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); | ||
663 | LOG (GNUNET_ERROR_TYPE_DEBUG, "******* RECONNECT *******\n"); | ||
664 | LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); | ||
665 | LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h); | ||
666 | LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n"); | ||
667 | |||
668 | /* disconnect */ | ||
669 | if (NULL != h->th) | ||
670 | { | ||
671 | GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); | ||
672 | h->th = NULL; | ||
673 | } | ||
674 | if (NULL != h->client) | ||
675 | { | ||
676 | GNUNET_CLIENT_disconnect (h->client); | ||
677 | } | ||
678 | |||
679 | /* connect again */ | ||
680 | h->client = GNUNET_CLIENT_connect ("cadet", h->cfg); | ||
681 | if (h->client == NULL) | ||
682 | { | ||
683 | h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, | ||
684 | &reconnect_cbk, h); | ||
685 | h->reconnect_time = | ||
686 | GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS, | ||
687 | GNUNET_TIME_relative_multiply | ||
688 | (h->reconnect_time, 2)); | ||
689 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Next retry in %s\n", | ||
690 | GNUNET_STRINGS_relative_time_to_string (h->reconnect_time, | ||
691 | GNUNET_NO)); | ||
692 | GNUNET_break (0); | ||
693 | return GNUNET_NO; | ||
694 | } | ||
695 | else | ||
696 | { | ||
697 | h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; | ||
698 | } | ||
699 | send_connect (h); | ||
700 | return GNUNET_YES; | ||
701 | } | ||
702 | |||
703 | /** | ||
704 | * Reconnect callback: tries to reconnect again after a failer previous | ||
705 | * reconnecttion | ||
706 | * @param cls closure (cadet handle) | ||
707 | * @param tc task context | ||
708 | */ | ||
709 | static void | ||
710 | reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
711 | { | ||
712 | struct GNUNET_CADET_Handle *h = cls; | ||
713 | |||
714 | h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
715 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
716 | return; | ||
717 | do_reconnect (h); | ||
718 | } | ||
719 | |||
720 | |||
721 | /** | ||
722 | * Reconnect to the service, retransmit all infomation to try to restore the | ||
723 | * original state. | ||
724 | * | ||
725 | * @param h handle to the cadet | ||
726 | * | ||
727 | * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...) | ||
728 | */ | ||
729 | static void | ||
730 | reconnect (struct GNUNET_CADET_Handle *h) | ||
731 | { | ||
732 | struct GNUNET_CADET_Channel *ch; | ||
733 | struct GNUNET_CADET_Channel *next; | ||
734 | |||
735 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
736 | "Requested RECONNECT, destroying all channels\n"); | ||
737 | h->in_receive = GNUNET_NO; | ||
738 | for (ch = h->channels_head; NULL != ch; ch = next) | ||
739 | { | ||
740 | next = ch->next; | ||
741 | destroy_channel (ch, GNUNET_YES); | ||
742 | } | ||
743 | if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task) | ||
744 | h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time, | ||
745 | &reconnect_cbk, h); | ||
746 | } | ||
747 | |||
748 | |||
749 | /******************************************************************************/ | ||
750 | /*********************** RECEIVE HANDLERS ****************************/ | ||
751 | /******************************************************************************/ | ||
752 | |||
753 | /** | ||
754 | * Process the new channel notification and add it to the channels in the handle | ||
755 | * | ||
756 | * @param h The cadet handle | ||
757 | * @param msg A message with the details of the new incoming channel | ||
758 | */ | ||
759 | static void | ||
760 | process_channel_created (struct GNUNET_CADET_Handle *h, | ||
761 | const struct GNUNET_CADET_ChannelMessage *msg) | ||
762 | { | ||
763 | struct GNUNET_CADET_Channel *ch; | ||
764 | CADET_ChannelNumber chid; | ||
765 | uint32_t port; | ||
766 | |||
767 | chid = ntohl (msg->channel_id); | ||
768 | port = ntohl (msg->port); | ||
769 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming channel %X:%u\n", chid, port); | ||
770 | if (chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV) | ||
771 | { | ||
772 | GNUNET_break (0); | ||
773 | return; | ||
774 | } | ||
775 | if (NULL != h->new_channel) | ||
776 | { | ||
777 | void *ctx; | ||
778 | |||
779 | ch = create_channel (h, chid); | ||
780 | ch->allow_send = GNUNET_NO; | ||
781 | ch->peer = GNUNET_PEER_intern (&msg->peer); | ||
782 | ch->cadet = h; | ||
783 | ch->chid = chid; | ||
784 | ch->port = port; | ||
785 | ch->options = ntohl (msg->opt); | ||
786 | |||
787 | LOG (GNUNET_ERROR_TYPE_DEBUG, " created channel %p\n", ch); | ||
788 | ctx = h->new_channel (h->cls, ch, &msg->peer, ch->port, ch->options); | ||
789 | if (NULL != ctx) | ||
790 | ch->ctx = ctx; | ||
791 | LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n"); | ||
792 | } | ||
793 | else | ||
794 | { | ||
795 | struct GNUNET_CADET_ChannelMessage d_msg; | ||
796 | |||
797 | LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming channels\n"); | ||
798 | |||
799 | d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); | ||
800 | d_msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage)); | ||
801 | d_msg.channel_id = msg->channel_id; | ||
802 | memset (&d_msg.peer, 0, sizeof (struct GNUNET_PeerIdentity)); | ||
803 | d_msg.port = 0; | ||
804 | d_msg.opt = 0; | ||
805 | |||
806 | send_packet (h, &d_msg.header, NULL); | ||
807 | } | ||
808 | return; | ||
809 | } | ||
810 | |||
811 | |||
812 | /** | ||
813 | * Process the channel destroy notification and free associated resources | ||
814 | * | ||
815 | * @param h The cadet handle | ||
816 | * @param msg A message with the details of the channel being destroyed | ||
817 | */ | ||
818 | static void | ||
819 | process_channel_destroy (struct GNUNET_CADET_Handle *h, | ||
820 | const struct GNUNET_CADET_ChannelMessage *msg) | ||
821 | { | ||
822 | struct GNUNET_CADET_Channel *ch; | ||
823 | CADET_ChannelNumber chid; | ||
824 | |||
825 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel Destroy received from service\n"); | ||
826 | chid = ntohl (msg->channel_id); | ||
827 | ch = retrieve_channel (h, chid); | ||
828 | |||
829 | if (NULL == ch) | ||
830 | { | ||
831 | LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X unknown\n", chid); | ||
832 | return; | ||
833 | } | ||
834 | LOG (GNUNET_ERROR_TYPE_DEBUG, " destroying channel %X\n", ch->chid); | ||
835 | destroy_channel (ch, GNUNET_YES); | ||
836 | } | ||
837 | |||
838 | |||
839 | /** | ||
840 | * Process the incoming data packets, call appropriate handlers. | ||
841 | * | ||
842 | * @param h The cadet handle | ||
843 | * @param message A message encapsulating the data | ||
844 | */ | ||
845 | static void | ||
846 | process_incoming_data (struct GNUNET_CADET_Handle *h, | ||
847 | const struct GNUNET_MessageHeader *message) | ||
848 | { | ||
849 | const struct GNUNET_MessageHeader *payload; | ||
850 | const struct GNUNET_CADET_MessageHandler *handler; | ||
851 | struct GNUNET_CADET_LocalData *dmsg; | ||
852 | struct GNUNET_CADET_Channel *ch; | ||
853 | size_t size; | ||
854 | unsigned int i; | ||
855 | uint16_t type; | ||
856 | |||
857 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n"); | ||
858 | dmsg = (struct GNUNET_CADET_LocalData *) message; | ||
859 | ch = retrieve_channel (h, ntohl (dmsg->id)); | ||
860 | if (NULL == ch) | ||
861 | { | ||
862 | GNUNET_break (0); | ||
863 | return; | ||
864 | } | ||
865 | |||
866 | payload = (struct GNUNET_MessageHeader *) &dmsg[1]; | ||
867 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %s data on channel %s [%X]\n", | ||
868 | GM_f2s (ch->chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV), | ||
869 | GNUNET_i2s (GNUNET_PEER_resolve2 (ch->peer)), ntohl (dmsg->id)); | ||
870 | |||
871 | size = ntohs (message->size); | ||
872 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %u bytes\n", size); | ||
873 | |||
874 | if (NULL == ch) | ||
875 | { | ||
876 | /* Channel was ignored/destroyed, probably service didn't get it yet */ | ||
877 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ignored!\n"); | ||
878 | return; | ||
879 | } | ||
880 | type = ntohs (payload->type); | ||
881 | size = ntohs (payload->size); | ||
882 | LOG (GNUNET_ERROR_TYPE_DEBUG, " payload type %s\n", GM_m2s (type)); | ||
883 | for (i = 0; i < h->n_handlers; i++) | ||
884 | { | ||
885 | handler = &h->message_handlers[i]; | ||
886 | LOG (GNUNET_ERROR_TYPE_DEBUG, " checking handler for type %u\n", | ||
887 | handler->type); | ||
888 | if (handler->type == type) | ||
889 | { | ||
890 | if (GNUNET_OK != | ||
891 | handler->callback (h->cls, ch, &ch->ctx, payload)) | ||
892 | { | ||
893 | LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n"); | ||
894 | GNUNET_CADET_channel_destroy (ch); | ||
895 | return; | ||
896 | } | ||
897 | else | ||
898 | { | ||
899 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
900 | "callback completed successfully\n"); | ||
901 | return; | ||
902 | } | ||
903 | } | ||
904 | } | ||
905 | } | ||
906 | |||
907 | |||
908 | /** | ||
909 | * Process a local ACK message, enabling the client to send | ||
910 | * more data to the service. | ||
911 | * | ||
912 | * @param h Cadet handle. | ||
913 | * @param message Message itself. | ||
914 | */ | ||
915 | static void | ||
916 | process_ack (struct GNUNET_CADET_Handle *h, | ||
917 | const struct GNUNET_MessageHeader *message) | ||
918 | { | ||
919 | struct GNUNET_CADET_LocalAck *msg; | ||
920 | struct GNUNET_CADET_Channel *ch; | ||
921 | CADET_ChannelNumber chid; | ||
922 | |||
923 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n"); | ||
924 | msg = (struct GNUNET_CADET_LocalAck *) message; | ||
925 | chid = ntohl (msg->channel_id); | ||
926 | ch = retrieve_channel (h, chid); | ||
927 | if (NULL == ch) | ||
928 | { | ||
929 | LOG (GNUNET_ERROR_TYPE_DEBUG, "ACK on unknown channel %X\n", chid); | ||
930 | return; | ||
931 | } | ||
932 | LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X!\n", ch->chid); | ||
933 | ch->allow_send = GNUNET_YES; | ||
934 | if (NULL == h->th && 0 < ch->packet_size) | ||
935 | { | ||
936 | LOG (GNUNET_ERROR_TYPE_DEBUG, " tmt rdy was NULL, requesting!\n"); | ||
937 | h->th = GNUNET_CLIENT_notify_transmit_ready (h->client, ch->packet_size, | ||
938 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
939 | GNUNET_YES, &send_callback, h); | ||
940 | } | ||
941 | } | ||
942 | |||
943 | |||
944 | /* | ||
945 | * Process a local reply about info on all channels, pass info to the user. | ||
946 | * | ||
947 | * @param h Cadet handle. | ||
948 | * @param message Message itself. | ||
949 | */ | ||
950 | // static void | ||
951 | // process_get_channels (struct GNUNET_CADET_Handle *h, | ||
952 | // const struct GNUNET_MessageHeader *message) | ||
953 | // { | ||
954 | // struct GNUNET_CADET_LocalInfo *msg; | ||
955 | // | ||
956 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Channels messasge received\n"); | ||
957 | // | ||
958 | // if (NULL == h->channels_cb) | ||
959 | // { | ||
960 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); | ||
961 | // return; | ||
962 | // } | ||
963 | // | ||
964 | // msg = (struct GNUNET_CADET_LocalInfo *) message; | ||
965 | // if (ntohs (message->size) != | ||
966 | // (sizeof (struct GNUNET_CADET_LocalInfo) + | ||
967 | // sizeof (struct GNUNET_PeerIdentity))) | ||
968 | // { | ||
969 | // GNUNET_break_op (0); | ||
970 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
971 | // "Get channels message: size %hu - expected %u\n", | ||
972 | // ntohs (message->size), | ||
973 | // sizeof (struct GNUNET_CADET_LocalInfo)); | ||
974 | // return; | ||
975 | // } | ||
976 | // h->channels_cb (h->channels_cls, | ||
977 | // ntohl (msg->channel_id), | ||
978 | // &msg->owner, | ||
979 | // &msg->destination); | ||
980 | // } | ||
981 | |||
982 | |||
983 | |||
984 | /* | ||
985 | * Process a local monitor_channel reply, pass info to the user. | ||
986 | * | ||
987 | * @param h Cadet handle. | ||
988 | * @param message Message itself. | ||
989 | */ | ||
990 | // static void | ||
991 | // process_show_channel (struct GNUNET_CADET_Handle *h, | ||
992 | // const struct GNUNET_MessageHeader *message) | ||
993 | // { | ||
994 | // struct GNUNET_CADET_LocalInfo *msg; | ||
995 | // size_t esize; | ||
996 | // | ||
997 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Channel messasge received\n"); | ||
998 | // | ||
999 | // if (NULL == h->channel_cb) | ||
1000 | // { | ||
1001 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n"); | ||
1002 | // return; | ||
1003 | // } | ||
1004 | // | ||
1005 | // /* Verify message sanity */ | ||
1006 | // msg = (struct GNUNET_CADET_LocalInfo *) message; | ||
1007 | // esize = sizeof (struct GNUNET_CADET_LocalInfo); | ||
1008 | // if (ntohs (message->size) != esize) | ||
1009 | // { | ||
1010 | // GNUNET_break_op (0); | ||
1011 | // GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1012 | // "Show channel message: size %hu - expected %u\n", | ||
1013 | // ntohs (message->size), | ||
1014 | // esize); | ||
1015 | // | ||
1016 | // h->channel_cb (h->channel_cls, NULL, NULL); | ||
1017 | // h->channel_cb = NULL; | ||
1018 | // h->channel_cls = NULL; | ||
1019 | // | ||
1020 | // return; | ||
1021 | // } | ||
1022 | // | ||
1023 | // h->channel_cb (h->channel_cls, | ||
1024 | // &msg->destination, | ||
1025 | // &msg->owner); | ||
1026 | // } | ||
1027 | |||
1028 | |||
1029 | |||
1030 | /** | ||
1031 | * Process a local reply about info on all tunnels, pass info to the user. | ||
1032 | * | ||
1033 | * @param h Cadet handle. | ||
1034 | * @param message Message itself. | ||
1035 | */ | ||
1036 | static void | ||
1037 | process_get_peers (struct GNUNET_CADET_Handle *h, | ||
1038 | const struct GNUNET_MessageHeader *message) | ||
1039 | { | ||
1040 | struct GNUNET_CADET_LocalInfoPeer *msg; | ||
1041 | uint16_t size; | ||
1042 | |||
1043 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Peer messasge received\n"); | ||
1044 | |||
1045 | if (NULL == h->info_cb.peers_cb) | ||
1046 | { | ||
1047 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ignored\n"); | ||
1048 | return; | ||
1049 | } | ||
1050 | |||
1051 | size = ntohs (message->size); | ||
1052 | if (sizeof (struct GNUNET_CADET_LocalInfoPeer) > size) | ||
1053 | { | ||
1054 | h->info_cb.peers_cb (h->info_cls, NULL, -1, 0, 0); | ||
1055 | h->info_cb.peers_cb = NULL; | ||
1056 | h->info_cls = NULL; | ||
1057 | return; | ||
1058 | } | ||
1059 | |||
1060 | msg = (struct GNUNET_CADET_LocalInfoPeer *) message; | ||
1061 | h->info_cb.peers_cb (h->info_cls, &msg->destination, | ||
1062 | (int) ntohs (msg->tunnel), | ||
1063 | (unsigned int ) ntohs (msg->paths), | ||
1064 | 0); | ||
1065 | } | ||
1066 | |||
1067 | |||
1068 | /** | ||
1069 | * Process a local peer info reply, pass info to the user. | ||
1070 | * | ||
1071 | * @param h Cadet handle. | ||
1072 | * @param message Message itself. | ||
1073 | */ | ||
1074 | static void | ||
1075 | process_get_peer (struct GNUNET_CADET_Handle *h, | ||
1076 | const struct GNUNET_MessageHeader *message) | ||
1077 | { | ||
1078 | struct GNUNET_CADET_LocalInfoTunnel *msg; | ||
1079 | size_t esize; | ||
1080 | size_t msize; | ||
1081 | unsigned int ch_n; | ||
1082 | unsigned int c_n; | ||
1083 | struct GNUNET_CADET_Hash *conns; | ||
1084 | CADET_ChannelNumber *chns; | ||
1085 | |||
1086 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnel messasge received\n"); | ||
1087 | if (NULL == h->info_cb.tunnel_cb) | ||
1088 | { | ||
1089 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ignored\n"); | ||
1090 | return; | ||
1091 | } | ||
1092 | |||
1093 | /* Verify message sanity */ | ||
1094 | msg = (struct GNUNET_CADET_LocalInfoTunnel *) message; | ||
1095 | msize = ntohs (message->size); | ||
1096 | esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel); | ||
1097 | if (esize > msize) | ||
1098 | { | ||
1099 | GNUNET_break_op (0); | ||
1100 | h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0); | ||
1101 | goto clean_cls; | ||
1102 | } | ||
1103 | ch_n = ntohl (msg->channels); | ||
1104 | c_n = ntohl (msg->connections); | ||
1105 | esize += ch_n * sizeof (CADET_ChannelNumber); | ||
1106 | esize += c_n * sizeof (struct GNUNET_CADET_Hash); | ||
1107 | if (msize != esize) | ||
1108 | { | ||
1109 | GNUNET_break_op (0); | ||
1110 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "m:%u, e: %u (%u ch, %u conn)\n", | ||
1111 | msize, esize, ch_n, c_n); | ||
1112 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u (%u ch, %u conn)\n", | ||
1113 | sizeof (struct GNUNET_CADET_LocalInfoTunnel), | ||
1114 | sizeof (CADET_ChannelNumber), sizeof (struct GNUNET_HashCode)); | ||
1115 | h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0); | ||
1116 | goto clean_cls; | ||
1117 | } | ||
1118 | |||
1119 | /* Call Callback with tunnel info. */ | ||
1120 | conns = (struct GNUNET_CADET_Hash *) &msg[1]; | ||
1121 | chns = (CADET_ChannelNumber *) &conns[c_n]; | ||
1122 | h->info_cb.tunnel_cb (h->info_cls, &msg->destination, | ||
1123 | ch_n, c_n, chns, conns, | ||
1124 | ntohs (msg->estate), ntohs (msg->cstate)); | ||
1125 | |||
1126 | clean_cls: | ||
1127 | h->info_cb.tunnel_cb = NULL; | ||
1128 | h->info_cls = NULL; | ||
1129 | } | ||
1130 | |||
1131 | |||
1132 | /** | ||
1133 | * Process a local reply about info on all tunnels, pass info to the user. | ||
1134 | * | ||
1135 | * @param h Cadet handle. | ||
1136 | * @param message Message itself. | ||
1137 | */ | ||
1138 | static void | ||
1139 | process_get_tunnels (struct GNUNET_CADET_Handle *h, | ||
1140 | const struct GNUNET_MessageHeader *message) | ||
1141 | { | ||
1142 | struct GNUNET_CADET_LocalInfoTunnel *msg; | ||
1143 | uint16_t size; | ||
1144 | |||
1145 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnels messasge received\n"); | ||
1146 | |||
1147 | if (NULL == h->info_cb.tunnels_cb) | ||
1148 | { | ||
1149 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ignored\n"); | ||
1150 | return; | ||
1151 | } | ||
1152 | |||
1153 | size = ntohs (message->size); | ||
1154 | if (sizeof (struct GNUNET_CADET_LocalInfoTunnel) > size) | ||
1155 | { | ||
1156 | h->info_cb.tunnels_cb (h->info_cls, NULL, 0, 0, 0, 0); | ||
1157 | h->info_cb.tunnels_cb = NULL; | ||
1158 | h->info_cls = NULL; | ||
1159 | return; | ||
1160 | } | ||
1161 | |||
1162 | msg = (struct GNUNET_CADET_LocalInfoTunnel *) message; | ||
1163 | h->info_cb.tunnels_cb (h->info_cls, &msg->destination, | ||
1164 | ntohl (msg->channels), ntohl (msg->connections), | ||
1165 | ntohs (msg->estate), ntohs (msg->cstate)); | ||
1166 | |||
1167 | } | ||
1168 | |||
1169 | |||
1170 | /** | ||
1171 | * Process a local tunnel info reply, pass info to the user. | ||
1172 | * | ||
1173 | * @param h Cadet handle. | ||
1174 | * @param message Message itself. | ||
1175 | */ | ||
1176 | static void | ||
1177 | process_get_tunnel (struct GNUNET_CADET_Handle *h, | ||
1178 | const struct GNUNET_MessageHeader *message) | ||
1179 | { | ||
1180 | struct GNUNET_CADET_LocalInfoTunnel *msg; | ||
1181 | size_t esize; | ||
1182 | size_t msize; | ||
1183 | unsigned int ch_n; | ||
1184 | unsigned int c_n; | ||
1185 | struct GNUNET_CADET_Hash *conns; | ||
1186 | CADET_ChannelNumber *chns; | ||
1187 | |||
1188 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Get Tunnel messasge received\n"); | ||
1189 | if (NULL == h->info_cb.tunnel_cb) | ||
1190 | { | ||
1191 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ignored\n"); | ||
1192 | return; | ||
1193 | } | ||
1194 | |||
1195 | /* Verify message sanity */ | ||
1196 | msg = (struct GNUNET_CADET_LocalInfoTunnel *) message; | ||
1197 | msize = ntohs (message->size); | ||
1198 | esize = sizeof (struct GNUNET_CADET_LocalInfoTunnel); | ||
1199 | if (esize > msize) | ||
1200 | { | ||
1201 | GNUNET_break_op (0); | ||
1202 | h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0); | ||
1203 | goto clean_cls; | ||
1204 | } | ||
1205 | ch_n = ntohl (msg->channels); | ||
1206 | c_n = ntohl (msg->connections); | ||
1207 | esize += ch_n * sizeof (CADET_ChannelNumber); | ||
1208 | esize += c_n * sizeof (struct GNUNET_CADET_Hash); | ||
1209 | if (msize != esize) | ||
1210 | { | ||
1211 | GNUNET_break_op (0); | ||
1212 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "m:%u, e: %u (%u ch, %u conn)\n", | ||
1213 | msize, esize, ch_n, c_n); | ||
1214 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u (%u ch, %u conn)\n", | ||
1215 | sizeof (struct GNUNET_CADET_LocalInfoTunnel), | ||
1216 | sizeof (CADET_ChannelNumber), sizeof (struct GNUNET_HashCode)); | ||
1217 | h->info_cb.tunnel_cb (h->info_cls, NULL, 0, 0, NULL, NULL, 0, 0); | ||
1218 | goto clean_cls; | ||
1219 | } | ||
1220 | |||
1221 | /* Call Callback with tunnel info. */ | ||
1222 | conns = (struct GNUNET_CADET_Hash *) &msg[1]; | ||
1223 | chns = (CADET_ChannelNumber *) &conns[c_n]; | ||
1224 | h->info_cb.tunnel_cb (h->info_cls, &msg->destination, | ||
1225 | ch_n, c_n, chns, conns, | ||
1226 | ntohs (msg->estate), ntohs (msg->cstate)); | ||
1227 | |||
1228 | clean_cls: | ||
1229 | h->info_cb.tunnel_cb = NULL; | ||
1230 | h->info_cls = NULL; | ||
1231 | } | ||
1232 | |||
1233 | |||
1234 | /** | ||
1235 | * Function to process all messages received from the service | ||
1236 | * | ||
1237 | * @param cls closure | ||
1238 | * @param msg message received, NULL on timeout or fatal error | ||
1239 | */ | ||
1240 | static void | ||
1241 | msg_received (void *cls, const struct GNUNET_MessageHeader *msg) | ||
1242 | { | ||
1243 | struct GNUNET_CADET_Handle *h = cls; | ||
1244 | uint16_t type; | ||
1245 | |||
1246 | if (msg == NULL) | ||
1247 | { | ||
1248 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1249 | "Cadet service disconnected, reconnecting\n", h); | ||
1250 | reconnect (h); | ||
1251 | return; | ||
1252 | } | ||
1253 | type = ntohs (msg->type); | ||
1254 | LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); | ||
1255 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n", | ||
1256 | GM_m2s (type)); | ||
1257 | switch (type) | ||
1258 | { | ||
1259 | /* Notify of a new incoming channel */ | ||
1260 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
1261 | process_channel_created (h, (struct GNUNET_CADET_ChannelMessage *) msg); | ||
1262 | break; | ||
1263 | /* Notify of a channel disconnection */ | ||
1264 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: /* TODO separate(gid problem)*/ | ||
1265 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: | ||
1266 | process_channel_destroy (h, (struct GNUNET_CADET_ChannelMessage *) msg); | ||
1267 | break; | ||
1268 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA: | ||
1269 | process_incoming_data (h, msg); | ||
1270 | break; | ||
1271 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK: | ||
1272 | process_ack (h, msg); | ||
1273 | break; | ||
1274 | // case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS: | ||
1275 | // process_get_channels (h, msg); | ||
1276 | // break; | ||
1277 | // case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL: | ||
1278 | // process_show_channel (h, msg); | ||
1279 | // break; | ||
1280 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS: | ||
1281 | process_get_peers (h, msg); | ||
1282 | break; | ||
1283 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER: | ||
1284 | process_get_peer (h, msg); | ||
1285 | break; | ||
1286 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS: | ||
1287 | process_get_tunnels (h, msg); | ||
1288 | break; | ||
1289 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL: | ||
1290 | process_get_tunnel (h, msg); | ||
1291 | break; | ||
1292 | // case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL: | ||
1293 | // process_show_channel (h, msg); | ||
1294 | // break; | ||
1295 | default: | ||
1296 | /* We shouldn't get any other packages, log and ignore */ | ||
1297 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1298 | "unsolicited message form service (type %s)\n", | ||
1299 | GM_m2s (ntohs (msg->type))); | ||
1300 | } | ||
1301 | LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n"); | ||
1302 | if (GNUNET_YES == h->in_receive) | ||
1303 | { | ||
1304 | GNUNET_CLIENT_receive (h->client, &msg_received, h, | ||
1305 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
1306 | } | ||
1307 | else | ||
1308 | { | ||
1309 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1310 | "in receive off, not calling CLIENT_receive\n"); | ||
1311 | } | ||
1312 | } | ||
1313 | |||
1314 | |||
1315 | /******************************************************************************/ | ||
1316 | /************************ SEND FUNCTIONS ****************************/ | ||
1317 | /******************************************************************************/ | ||
1318 | |||
1319 | /** | ||
1320 | * Function called to send a message to the service. | ||
1321 | * "buf" will be NULL and "size" zero if the socket was closed for writing in | ||
1322 | * the meantime. | ||
1323 | * | ||
1324 | * @param cls closure, the cadet handle | ||
1325 | * @param size number of bytes available in buf | ||
1326 | * @param buf where the callee should write the connect message | ||
1327 | * @return number of bytes written to buf | ||
1328 | */ | ||
1329 | static size_t | ||
1330 | send_callback (void *cls, size_t size, void *buf) | ||
1331 | { | ||
1332 | struct GNUNET_CADET_Handle *h = cls; | ||
1333 | struct GNUNET_CADET_TransmitHandle *th; | ||
1334 | struct GNUNET_CADET_TransmitHandle *next; | ||
1335 | struct GNUNET_CADET_Channel *ch; | ||
1336 | char *cbuf = buf; | ||
1337 | size_t tsize; | ||
1338 | size_t psize; | ||
1339 | size_t nsize; | ||
1340 | |||
1341 | LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); | ||
1342 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() Buffer %u\n", size); | ||
1343 | if ((0 == size) || (NULL == buf)) | ||
1344 | { | ||
1345 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# Received NULL send callback on %p\n", h); | ||
1346 | reconnect (h); | ||
1347 | h->th = NULL; | ||
1348 | return 0; | ||
1349 | } | ||
1350 | tsize = 0; | ||
1351 | next = h->th_head; | ||
1352 | nsize = message_ready_size (h); | ||
1353 | while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize)) | ||
1354 | { | ||
1355 | ch = th->channel; | ||
1356 | if (GNUNET_YES == th_is_payload (th)) | ||
1357 | { | ||
1358 | struct GNUNET_CADET_LocalData *dmsg; | ||
1359 | struct GNUNET_MessageHeader *mh; | ||
1360 | |||
1361 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload\n"); | ||
1362 | if (GNUNET_NO == ch->allow_send) | ||
1363 | { | ||
1364 | /* This channel is not ready to transmit yet, try next message */ | ||
1365 | next = th->next; | ||
1366 | continue; | ||
1367 | } | ||
1368 | ch->packet_size = 0; | ||
1369 | GNUNET_assert (size >= th->size); | ||
1370 | dmsg = (struct GNUNET_CADET_LocalData *) cbuf; | ||
1371 | mh = (struct GNUNET_MessageHeader *) &dmsg[1]; | ||
1372 | psize = th->notify (th->notify_cls, | ||
1373 | size - sizeof (struct GNUNET_CADET_LocalData), | ||
1374 | mh); | ||
1375 | if (psize > 0) | ||
1376 | { | ||
1377 | psize += sizeof (struct GNUNET_CADET_LocalData); | ||
1378 | GNUNET_assert (size >= psize); | ||
1379 | dmsg->header.size = htons (psize); | ||
1380 | dmsg->id = htonl (ch->chid); | ||
1381 | dmsg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1382 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# payload type %s\n", | ||
1383 | GM_m2s (ntohs (mh->type))); | ||
1384 | ch->allow_send = GNUNET_NO; | ||
1385 | } | ||
1386 | else | ||
1387 | { | ||
1388 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1389 | "# callback returned size 0, " | ||
1390 | "application canceled transmission\n"); | ||
1391 | } | ||
1392 | } | ||
1393 | else | ||
1394 | { | ||
1395 | struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1]; | ||
1396 | |||
1397 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# cadet internal traffic, type %s\n", | ||
1398 | GM_m2s (ntohs (mh->type))); | ||
1399 | memcpy (cbuf, &th[1], th->size); | ||
1400 | psize = th->size; | ||
1401 | } | ||
1402 | if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK) | ||
1403 | GNUNET_SCHEDULER_cancel (th->timeout_task); | ||
1404 | GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); | ||
1405 | GNUNET_free (th); | ||
1406 | next = h->th_head; | ||
1407 | nsize = message_ready_size (h); | ||
1408 | cbuf += psize; | ||
1409 | size -= psize; | ||
1410 | tsize += psize; | ||
1411 | } | ||
1412 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# total size: %u\n", tsize); | ||
1413 | h->th = NULL; | ||
1414 | size = message_ready_size (h); | ||
1415 | if (0 != size) | ||
1416 | { | ||
1417 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# next size: %u\n", size); | ||
1418 | h->th = | ||
1419 | GNUNET_CLIENT_notify_transmit_ready (h->client, size, | ||
1420 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1421 | GNUNET_YES, &send_callback, h); | ||
1422 | } | ||
1423 | else | ||
1424 | { | ||
1425 | if (NULL != h->th_head) | ||
1426 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# can't transmit any more\n"); | ||
1427 | else | ||
1428 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# nothing left to transmit\n"); | ||
1429 | } | ||
1430 | if (GNUNET_NO == h->in_receive) | ||
1431 | { | ||
1432 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# start receiving from service\n"); | ||
1433 | h->in_receive = GNUNET_YES; | ||
1434 | GNUNET_CLIENT_receive (h->client, &msg_received, h, | ||
1435 | GNUNET_TIME_UNIT_FOREVER_REL); | ||
1436 | } | ||
1437 | LOG (GNUNET_ERROR_TYPE_DEBUG, "# Send packet() END\n"); | ||
1438 | return tsize; | ||
1439 | } | ||
1440 | |||
1441 | |||
1442 | /** | ||
1443 | * Auxiliary function to send an already constructed packet to the service. | ||
1444 | * Takes care of creating a new queue element, copying the message and | ||
1445 | * calling the tmt_rdy function if necessary. | ||
1446 | * | ||
1447 | * @param h cadet handle | ||
1448 | * @param msg message to transmit | ||
1449 | * @param channel channel this send is related to (NULL if N/A) | ||
1450 | */ | ||
1451 | static void | ||
1452 | send_packet (struct GNUNET_CADET_Handle *h, | ||
1453 | const struct GNUNET_MessageHeader *msg, | ||
1454 | struct GNUNET_CADET_Channel *channel) | ||
1455 | { | ||
1456 | struct GNUNET_CADET_TransmitHandle *th; | ||
1457 | size_t msize; | ||
1458 | |||
1459 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n", | ||
1460 | GM_m2s(ntohs(msg->type))); | ||
1461 | msize = ntohs (msg->size); | ||
1462 | th = GNUNET_malloc (sizeof (struct GNUNET_CADET_TransmitHandle) + msize); | ||
1463 | th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
1464 | th->size = msize; | ||
1465 | th->channel = channel; | ||
1466 | memcpy (&th[1], msg, msize); | ||
1467 | add_to_queue (h, th); | ||
1468 | LOG (GNUNET_ERROR_TYPE_DEBUG, " queued\n"); | ||
1469 | if (NULL != h->th) | ||
1470 | return; | ||
1471 | LOG (GNUNET_ERROR_TYPE_DEBUG, " calling ntfy tmt rdy for %u bytes\n", msize); | ||
1472 | h->th = | ||
1473 | GNUNET_CLIENT_notify_transmit_ready (h->client, msize, | ||
1474 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1475 | GNUNET_YES, &send_callback, h); | ||
1476 | } | ||
1477 | |||
1478 | |||
1479 | /******************************************************************************/ | ||
1480 | /********************** API CALL DEFINITIONS *************************/ | ||
1481 | /******************************************************************************/ | ||
1482 | |||
1483 | struct GNUNET_CADET_Handle * | ||
1484 | GNUNET_CADET_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls, | ||
1485 | GNUNET_CADET_InboundChannelNotificationHandler new_channel, | ||
1486 | GNUNET_CADET_ChannelEndHandler cleaner, | ||
1487 | const struct GNUNET_CADET_MessageHandler *handlers, | ||
1488 | const uint32_t *ports) | ||
1489 | { | ||
1490 | struct GNUNET_CADET_Handle *h; | ||
1491 | |||
1492 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect()\n"); | ||
1493 | h = GNUNET_new (struct GNUNET_CADET_Handle); | ||
1494 | LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h); | ||
1495 | h->cfg = cfg; | ||
1496 | h->new_channel = new_channel; | ||
1497 | h->cleaner = cleaner; | ||
1498 | h->client = GNUNET_CLIENT_connect ("cadet", cfg); | ||
1499 | if (h->client == NULL) | ||
1500 | { | ||
1501 | GNUNET_break (0); | ||
1502 | GNUNET_free (h); | ||
1503 | return NULL; | ||
1504 | } | ||
1505 | h->cls = cls; | ||
1506 | h->message_handlers = handlers; | ||
1507 | h->ports = ports; | ||
1508 | h->next_chid = GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; | ||
1509 | h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS; | ||
1510 | h->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
1511 | |||
1512 | if (NULL != ports && ports[0] != 0 && NULL == new_channel) | ||
1513 | { | ||
1514 | GNUNET_break (0); | ||
1515 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1516 | "no new channel handler given, ports parameter is useless!!\n"); | ||
1517 | } | ||
1518 | if ((NULL == ports || ports[0] == 0) && NULL != new_channel) | ||
1519 | { | ||
1520 | GNUNET_break (0); | ||
1521 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1522 | "no ports given, new channel handler will never be called!!\n"); | ||
1523 | } | ||
1524 | /* count handlers */ | ||
1525 | for (h->n_handlers = 0; | ||
1526 | handlers && handlers[h->n_handlers].type; | ||
1527 | h->n_handlers++) ; | ||
1528 | for (h->n_ports = 0; | ||
1529 | ports && ports[h->n_ports]; | ||
1530 | h->n_ports++) ; | ||
1531 | send_connect (h); | ||
1532 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_CADET_connect() END\n"); | ||
1533 | return h; | ||
1534 | } | ||
1535 | |||
1536 | |||
1537 | void | ||
1538 | GNUNET_CADET_disconnect (struct GNUNET_CADET_Handle *handle) | ||
1539 | { | ||
1540 | struct GNUNET_CADET_Channel *ch; | ||
1541 | struct GNUNET_CADET_Channel *aux; | ||
1542 | struct GNUNET_CADET_TransmitHandle *th; | ||
1543 | |||
1544 | LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET DISCONNECT\n"); | ||
1545 | |||
1546 | ch = handle->channels_head; | ||
1547 | while (NULL != ch) | ||
1548 | { | ||
1549 | aux = ch->next; | ||
1550 | if (ch->chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV) | ||
1551 | { | ||
1552 | GNUNET_break (0); | ||
1553 | LOG (GNUNET_ERROR_TYPE_DEBUG, "channel %X not destroyed\n", ch->chid); | ||
1554 | } | ||
1555 | destroy_channel (ch, GNUNET_YES); | ||
1556 | ch = aux; | ||
1557 | } | ||
1558 | while ( (th = handle->th_head) != NULL) | ||
1559 | { | ||
1560 | struct GNUNET_MessageHeader *msg; | ||
1561 | |||
1562 | /* Make sure it is an allowed packet (everything else should have been | ||
1563 | * already canceled). | ||
1564 | */ | ||
1565 | GNUNET_break (GNUNET_NO == th_is_payload (th)); | ||
1566 | msg = (struct GNUNET_MessageHeader *) &th[1]; | ||
1567 | switch (ntohs(msg->type)) | ||
1568 | { | ||
1569 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT: | ||
1570 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
1571 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
1572 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS: | ||
1573 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL: | ||
1574 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER: | ||
1575 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS: | ||
1576 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL: | ||
1577 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS: | ||
1578 | break; | ||
1579 | default: | ||
1580 | GNUNET_break (0); | ||
1581 | LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n", | ||
1582 | ntohs(msg->type)); | ||
1583 | } | ||
1584 | |||
1585 | GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th); | ||
1586 | GNUNET_free (th); | ||
1587 | } | ||
1588 | |||
1589 | if (NULL != handle->th) | ||
1590 | { | ||
1591 | GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th); | ||
1592 | handle->th = NULL; | ||
1593 | } | ||
1594 | if (NULL != handle->client) | ||
1595 | { | ||
1596 | GNUNET_CLIENT_disconnect (handle->client); | ||
1597 | handle->client = NULL; | ||
1598 | } | ||
1599 | if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task) | ||
1600 | { | ||
1601 | GNUNET_SCHEDULER_cancel(handle->reconnect_task); | ||
1602 | handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
1603 | } | ||
1604 | GNUNET_free (handle); | ||
1605 | } | ||
1606 | |||
1607 | |||
1608 | /** | ||
1609 | * Create a new channel towards a remote peer. | ||
1610 | * | ||
1611 | * If the destination port is not open by any peer or the destination peer | ||
1612 | * does not accept the channel, #GNUNET_CADET_ChannelEndHandler will be called | ||
1613 | * for this channel. | ||
1614 | * | ||
1615 | * @param h cadet handle | ||
1616 | * @param channel_ctx client's channel context to associate with the channel | ||
1617 | * @param peer peer identity the channel should go to | ||
1618 | * @param port Port number. | ||
1619 | * @param options CadetOption flag field, with all desired option bits set to 1. | ||
1620 | * | ||
1621 | * @return handle to the channel | ||
1622 | */ | ||
1623 | struct GNUNET_CADET_Channel * | ||
1624 | GNUNET_CADET_channel_create (struct GNUNET_CADET_Handle *h, | ||
1625 | void *channel_ctx, | ||
1626 | const struct GNUNET_PeerIdentity *peer, | ||
1627 | uint32_t port, | ||
1628 | enum GNUNET_CADET_ChannelOption options) | ||
1629 | { | ||
1630 | struct GNUNET_CADET_Channel *ch; | ||
1631 | struct GNUNET_CADET_ChannelMessage msg; | ||
1632 | |||
1633 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1634 | "Creating new channel to %s:%u\n", | ||
1635 | GNUNET_i2s (peer), port); | ||
1636 | ch = create_channel (h, 0); | ||
1637 | LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", ch); | ||
1638 | LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", ch->chid); | ||
1639 | ch->ctx = channel_ctx; | ||
1640 | ch->peer = GNUNET_PEER_intern (peer); | ||
1641 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE); | ||
1642 | msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage)); | ||
1643 | msg.channel_id = htonl (ch->chid); | ||
1644 | msg.port = htonl (port); | ||
1645 | msg.peer = *peer; | ||
1646 | msg.opt = htonl (options); | ||
1647 | ch->allow_send = 0; | ||
1648 | send_packet (h, &msg.header, ch); | ||
1649 | return ch; | ||
1650 | } | ||
1651 | |||
1652 | |||
1653 | void | ||
1654 | GNUNET_CADET_channel_destroy (struct GNUNET_CADET_Channel *channel) | ||
1655 | { | ||
1656 | struct GNUNET_CADET_Handle *h; | ||
1657 | struct GNUNET_CADET_ChannelMessage msg; | ||
1658 | struct GNUNET_CADET_TransmitHandle *th; | ||
1659 | |||
1660 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying channel\n"); | ||
1661 | h = channel->cadet; | ||
1662 | |||
1663 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); | ||
1664 | msg.header.size = htons (sizeof (struct GNUNET_CADET_ChannelMessage)); | ||
1665 | msg.channel_id = htonl (channel->chid); | ||
1666 | memset (&msg.peer, 0, sizeof (struct GNUNET_PeerIdentity)); | ||
1667 | msg.port = 0; | ||
1668 | msg.opt = 0; | ||
1669 | th = h->th_head; | ||
1670 | while (th != NULL) | ||
1671 | { | ||
1672 | struct GNUNET_CADET_TransmitHandle *aux; | ||
1673 | if (th->channel == channel) | ||
1674 | { | ||
1675 | aux = th->next; | ||
1676 | /* FIXME call the handler? */ | ||
1677 | if (GNUNET_YES == th_is_payload (th)) | ||
1678 | th->notify (th->notify_cls, 0, NULL); | ||
1679 | GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th); | ||
1680 | GNUNET_free (th); | ||
1681 | th = aux; | ||
1682 | } | ||
1683 | else | ||
1684 | th = th->next; | ||
1685 | } | ||
1686 | |||
1687 | destroy_channel (channel, GNUNET_YES); | ||
1688 | send_packet (h, &msg.header, NULL); | ||
1689 | } | ||
1690 | |||
1691 | |||
1692 | /** | ||
1693 | * Get information about a channel. | ||
1694 | * | ||
1695 | * @param channel Channel handle. | ||
1696 | * @param option Query (GNUNET_CADET_OPTION_*). | ||
1697 | * @param ... dependant on option, currently not used | ||
1698 | * | ||
1699 | * @return Union with an answer to the query. | ||
1700 | */ | ||
1701 | const union GNUNET_CADET_ChannelInfo * | ||
1702 | GNUNET_CADET_channel_get_info (struct GNUNET_CADET_Channel *channel, | ||
1703 | enum GNUNET_CADET_ChannelOption option, ...) | ||
1704 | { | ||
1705 | static int bool_flag; | ||
1706 | const union GNUNET_CADET_ChannelInfo *ret; | ||
1707 | |||
1708 | switch (option) | ||
1709 | { | ||
1710 | case GNUNET_CADET_OPTION_NOBUFFER: | ||
1711 | case GNUNET_CADET_OPTION_RELIABLE: | ||
1712 | case GNUNET_CADET_OPTION_OOORDER: | ||
1713 | if (0 != (option & channel->options)) | ||
1714 | bool_flag = GNUNET_YES; | ||
1715 | else | ||
1716 | bool_flag = GNUNET_NO; | ||
1717 | ret = (const union GNUNET_CADET_ChannelInfo *) &bool_flag; | ||
1718 | break; | ||
1719 | case GNUNET_CADET_OPTION_PEER: | ||
1720 | ret = (const union GNUNET_CADET_ChannelInfo *) GNUNET_PEER_resolve2 (channel->peer); | ||
1721 | break; | ||
1722 | default: | ||
1723 | GNUNET_break (0); | ||
1724 | return NULL; | ||
1725 | } | ||
1726 | |||
1727 | return ret; | ||
1728 | } | ||
1729 | |||
1730 | struct GNUNET_CADET_TransmitHandle * | ||
1731 | GNUNET_CADET_notify_transmit_ready (struct GNUNET_CADET_Channel *channel, int cork, | ||
1732 | struct GNUNET_TIME_Relative maxdelay, | ||
1733 | size_t notify_size, | ||
1734 | GNUNET_CONNECTION_TransmitReadyNotify notify, | ||
1735 | void *notify_cls) | ||
1736 | { | ||
1737 | struct GNUNET_CADET_TransmitHandle *th; | ||
1738 | |||
1739 | GNUNET_assert (NULL != channel); | ||
1740 | LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET NOTIFY TRANSMIT READY\n"); | ||
1741 | LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", channel->chid); | ||
1742 | LOG (GNUNET_ERROR_TYPE_DEBUG, " allow_send %d\n", channel->allow_send); | ||
1743 | if (channel->chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV) | ||
1744 | LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n"); | ||
1745 | else | ||
1746 | LOG (GNUNET_ERROR_TYPE_DEBUG, " to destination\n"); | ||
1747 | LOG (GNUNET_ERROR_TYPE_DEBUG, " payload size %u\n", notify_size); | ||
1748 | GNUNET_assert (NULL != notify); | ||
1749 | GNUNET_assert (0 == channel->packet_size); // Only one data packet allowed | ||
1750 | th = GNUNET_new (struct GNUNET_CADET_TransmitHandle); | ||
1751 | th->channel = channel; | ||
1752 | th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay); | ||
1753 | th->size = notify_size + sizeof (struct GNUNET_CADET_LocalData); | ||
1754 | channel->packet_size = th->size; | ||
1755 | LOG (GNUNET_ERROR_TYPE_DEBUG, " total size %u\n", th->size); | ||
1756 | th->notify = notify; | ||
1757 | th->notify_cls = notify_cls; | ||
1758 | add_to_queue (channel->cadet, th); | ||
1759 | if (NULL != channel->cadet->th) | ||
1760 | return th; | ||
1761 | if (GNUNET_NO == channel->allow_send) | ||
1762 | return th; | ||
1763 | LOG (GNUNET_ERROR_TYPE_DEBUG, " call client notify tmt rdy\n"); | ||
1764 | channel->cadet->th = | ||
1765 | GNUNET_CLIENT_notify_transmit_ready (channel->cadet->client, th->size, | ||
1766 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1767 | GNUNET_YES, &send_callback, | ||
1768 | channel->cadet); | ||
1769 | LOG (GNUNET_ERROR_TYPE_DEBUG, "CADET NOTIFY TRANSMIT READY END\n"); | ||
1770 | return th; | ||
1771 | } | ||
1772 | |||
1773 | |||
1774 | void | ||
1775 | GNUNET_CADET_notify_transmit_ready_cancel (struct GNUNET_CADET_TransmitHandle *th) | ||
1776 | { | ||
1777 | struct GNUNET_CADET_Handle *cadet; | ||
1778 | |||
1779 | th->channel->packet_size = 0; | ||
1780 | cadet = th->channel->cadet; | ||
1781 | if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK) | ||
1782 | GNUNET_SCHEDULER_cancel (th->timeout_task); | ||
1783 | GNUNET_CONTAINER_DLL_remove (cadet->th_head, cadet->th_tail, th); | ||
1784 | GNUNET_free (th); | ||
1785 | if ((0 == message_ready_size (cadet)) && (NULL != cadet->th)) | ||
1786 | { | ||
1787 | /* queue empty, no point in asking for transmission */ | ||
1788 | GNUNET_CLIENT_notify_transmit_ready_cancel (cadet->th); | ||
1789 | cadet->th = NULL; | ||
1790 | } | ||
1791 | } | ||
1792 | |||
1793 | |||
1794 | void | ||
1795 | GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel) | ||
1796 | { | ||
1797 | send_ack (channel); | ||
1798 | } | ||
1799 | |||
1800 | |||
1801 | static void | ||
1802 | send_info_request (struct GNUNET_CADET_Handle *h, uint16_t type) | ||
1803 | { | ||
1804 | struct GNUNET_MessageHeader msg; | ||
1805 | |||
1806 | msg.size = htons (sizeof (msg)); | ||
1807 | msg.type = htons (type); | ||
1808 | send_packet (h, &msg, NULL); | ||
1809 | } | ||
1810 | |||
1811 | |||
1812 | /** | ||
1813 | * Request information about peers known to the running cadet service. | ||
1814 | * The callback will be called for every peer known to the service. | ||
1815 | * Only one info request (of any kind) can be active at once. | ||
1816 | * | ||
1817 | * | ||
1818 | * WARNING: unstable API, likely to change in the future! | ||
1819 | * | ||
1820 | * @param h Handle to the cadet peer. | ||
1821 | * @param callback Function to call with the requested data. | ||
1822 | * @param callback_cls Closure for @c callback. | ||
1823 | * | ||
1824 | * @return #GNUNET_OK / #GNUNET_SYSERR | ||
1825 | */ | ||
1826 | int | ||
1827 | GNUNET_CADET_get_peers (struct GNUNET_CADET_Handle *h, | ||
1828 | GNUNET_CADET_PeersCB callback, | ||
1829 | void *callback_cls) | ||
1830 | { | ||
1831 | if (NULL != h->info_cb.peers_cb) | ||
1832 | { | ||
1833 | GNUNET_break (0); | ||
1834 | return GNUNET_SYSERR; | ||
1835 | } | ||
1836 | send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
1837 | h->info_cb.peers_cb = callback; | ||
1838 | h->info_cls = callback_cls; | ||
1839 | return GNUNET_OK; | ||
1840 | } | ||
1841 | |||
1842 | |||
1843 | /** | ||
1844 | * Cancel a peer info request. The callback will not be called (anymore). | ||
1845 | * | ||
1846 | * WARNING: unstable API, likely to change in the future! | ||
1847 | * | ||
1848 | * @param h Cadet handle. | ||
1849 | * | ||
1850 | * @return Closure given to GNUNET_CADET_get_peers. | ||
1851 | */ | ||
1852 | void * | ||
1853 | GNUNET_CADET_get_peers_cancel (struct GNUNET_CADET_Handle *h) | ||
1854 | { | ||
1855 | void *cls; | ||
1856 | |||
1857 | cls = h->info_cls; | ||
1858 | h->info_cb.peers_cb = NULL; | ||
1859 | h->info_cls = NULL; | ||
1860 | return cls; | ||
1861 | } | ||
1862 | |||
1863 | |||
1864 | /** | ||
1865 | * Request information about a peer known to the running cadet peer. | ||
1866 | * The callback will be called for the tunnel once. | ||
1867 | * Only one info request (of any kind) can be active at once. | ||
1868 | * | ||
1869 | * WARNING: unstable API, likely to change in the future! | ||
1870 | * | ||
1871 | * @param h Handle to the cadet peer. | ||
1872 | * @param id Peer whose tunnel to examine. | ||
1873 | * @param callback Function to call with the requested data. | ||
1874 | * @param callback_cls Closure for @c callback. | ||
1875 | * | ||
1876 | * @return #GNUNET_OK / #GNUNET_SYSERR | ||
1877 | */ | ||
1878 | int | ||
1879 | GNUNET_CADET_get_peer (struct GNUNET_CADET_Handle *h, | ||
1880 | const struct GNUNET_PeerIdentity *id, | ||
1881 | GNUNET_CADET_PeerCB callback, | ||
1882 | void *callback_cls) | ||
1883 | { | ||
1884 | struct GNUNET_CADET_LocalInfo msg; | ||
1885 | |||
1886 | if (NULL != h->info_cb.peer_cb) | ||
1887 | { | ||
1888 | GNUNET_break (0); | ||
1889 | return GNUNET_SYSERR; | ||
1890 | } | ||
1891 | |||
1892 | memset (&msg, 0, sizeof (msg)); | ||
1893 | msg.header.size = htons (sizeof (msg)); | ||
1894 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER); | ||
1895 | msg.peer = *id; | ||
1896 | send_packet (h, &msg.header, NULL); | ||
1897 | h->info_cb.peer_cb = callback; | ||
1898 | h->info_cls = callback_cls; | ||
1899 | return GNUNET_OK; | ||
1900 | } | ||
1901 | |||
1902 | |||
1903 | /** | ||
1904 | * Request information about tunnels of the running cadet peer. | ||
1905 | * The callback will be called for every tunnel of the service. | ||
1906 | * Only one info request (of any kind) can be active at once. | ||
1907 | * | ||
1908 | * WARNING: unstable API, likely to change in the future! | ||
1909 | * | ||
1910 | * @param h Handle to the cadet peer. | ||
1911 | * @param callback Function to call with the requested data. | ||
1912 | * @param callback_cls Closure for @c callback. | ||
1913 | * | ||
1914 | * @return #GNUNET_OK / #GNUNET_SYSERR | ||
1915 | */ | ||
1916 | int | ||
1917 | GNUNET_CADET_get_tunnels (struct GNUNET_CADET_Handle *h, | ||
1918 | GNUNET_CADET_TunnelsCB callback, | ||
1919 | void *callback_cls) | ||
1920 | { | ||
1921 | if (NULL != h->info_cb.tunnels_cb) | ||
1922 | { | ||
1923 | GNUNET_break (0); | ||
1924 | return GNUNET_SYSERR; | ||
1925 | } | ||
1926 | send_info_request (h, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
1927 | h->info_cb.tunnels_cb = callback; | ||
1928 | h->info_cls = callback_cls; | ||
1929 | return GNUNET_OK; | ||
1930 | } | ||
1931 | |||
1932 | |||
1933 | /** | ||
1934 | * Cancel a monitor request. The monitor callback will not be called. | ||
1935 | * | ||
1936 | * @param h Cadet handle. | ||
1937 | * | ||
1938 | * @return Closure given to GNUNET_CADET_get_tunnels. | ||
1939 | */ | ||
1940 | void * | ||
1941 | GNUNET_CADET_get_tunnels_cancel (struct GNUNET_CADET_Handle *h) | ||
1942 | { | ||
1943 | void *cls; | ||
1944 | |||
1945 | h->info_cb.tunnels_cb = NULL; | ||
1946 | cls = h->info_cls; | ||
1947 | h->info_cls = NULL; | ||
1948 | |||
1949 | return cls; | ||
1950 | } | ||
1951 | |||
1952 | |||
1953 | |||
1954 | /** | ||
1955 | * Request information about a tunnel of the running cadet peer. | ||
1956 | * The callback will be called for the tunnel once. | ||
1957 | * Only one info request (of any kind) can be active at once. | ||
1958 | * | ||
1959 | * WARNING: unstable API, likely to change in the future! | ||
1960 | * | ||
1961 | * @param h Handle to the cadet peer. | ||
1962 | * @param id Peer whose tunnel to examine. | ||
1963 | * @param callback Function to call with the requested data. | ||
1964 | * @param callback_cls Closure for @c callback. | ||
1965 | * | ||
1966 | * @return #GNUNET_OK / #GNUNET_SYSERR | ||
1967 | */ | ||
1968 | int | ||
1969 | GNUNET_CADET_get_tunnel (struct GNUNET_CADET_Handle *h, | ||
1970 | const struct GNUNET_PeerIdentity *id, | ||
1971 | GNUNET_CADET_TunnelCB callback, | ||
1972 | void *callback_cls) | ||
1973 | { | ||
1974 | struct GNUNET_CADET_LocalInfo msg; | ||
1975 | |||
1976 | if (NULL != h->info_cb.tunnel_cb) | ||
1977 | { | ||
1978 | GNUNET_break (0); | ||
1979 | return GNUNET_SYSERR; | ||
1980 | } | ||
1981 | |||
1982 | memset (&msg, 0, sizeof (msg)); | ||
1983 | msg.header.size = htons (sizeof (msg)); | ||
1984 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
1985 | msg.peer = *id; | ||
1986 | send_packet (h, &msg.header, NULL); | ||
1987 | h->info_cb.tunnel_cb = callback; | ||
1988 | h->info_cls = callback_cls; | ||
1989 | return GNUNET_OK; | ||
1990 | } | ||
1991 | |||
1992 | |||
1993 | /** | ||
1994 | * Request information about a specific channel of the running cadet peer. | ||
1995 | * | ||
1996 | * WARNING: unstable API, likely to change in the future! | ||
1997 | * FIXME Add destination option. | ||
1998 | * | ||
1999 | * @param h Handle to the cadet peer. | ||
2000 | * @param initiator ID of the owner of the channel. | ||
2001 | * @param channel_number Channel number. | ||
2002 | * @param callback Function to call with the requested data. | ||
2003 | * @param callback_cls Closure for @c callback. | ||
2004 | * | ||
2005 | * @return #GNUNET_OK / #GNUNET_SYSERR | ||
2006 | */ | ||
2007 | int | ||
2008 | GNUNET_CADET_show_channel (struct GNUNET_CADET_Handle *h, | ||
2009 | struct GNUNET_PeerIdentity *initiator, | ||
2010 | unsigned int channel_number, | ||
2011 | GNUNET_CADET_ChannelCB callback, | ||
2012 | void *callback_cls) | ||
2013 | { | ||
2014 | struct GNUNET_CADET_LocalInfo msg; | ||
2015 | |||
2016 | if (NULL != h->info_cb.channel_cb) | ||
2017 | { | ||
2018 | GNUNET_break (0); | ||
2019 | return GNUNET_SYSERR; | ||
2020 | } | ||
2021 | |||
2022 | msg.header.size = htons (sizeof (msg)); | ||
2023 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL); | ||
2024 | msg.peer = *initiator; | ||
2025 | msg.channel_id = htonl (channel_number); | ||
2026 | // msg.reserved = 0; | ||
2027 | send_packet (h, &msg.header, NULL); | ||
2028 | h->info_cb.channel_cb = callback; | ||
2029 | h->info_cls = callback_cls; | ||
2030 | return GNUNET_OK; | ||
2031 | } | ||
2032 | |||
2033 | |||
2034 | /** | ||
2035 | * Function called to notify a client about the connection | ||
2036 | * begin ready to queue more data. "buf" will be | ||
2037 | * NULL and "size" zero if the connection was closed for | ||
2038 | * writing in the meantime. | ||
2039 | * | ||
2040 | * @param cls closure | ||
2041 | * @param size number of bytes available in buf | ||
2042 | * @param buf where the callee should write the message | ||
2043 | * @return number of bytes written to buf | ||
2044 | */ | ||
2045 | static size_t | ||
2046 | cadet_mq_ntr (void *cls, size_t size, | ||
2047 | void *buf) | ||
2048 | { | ||
2049 | struct GNUNET_MQ_Handle *mq = cls; | ||
2050 | struct CadetMQState *state = GNUNET_MQ_impl_state (mq); | ||
2051 | const struct GNUNET_MessageHeader *msg = GNUNET_MQ_impl_current (mq); | ||
2052 | uint16_t msize; | ||
2053 | |||
2054 | state->th = NULL; | ||
2055 | if (NULL == buf) | ||
2056 | { | ||
2057 | GNUNET_MQ_inject_error (mq, GNUNET_MQ_ERROR_WRITE); | ||
2058 | return 0; | ||
2059 | } | ||
2060 | msize = ntohs (msg->size); | ||
2061 | GNUNET_assert (msize <= size); | ||
2062 | memcpy (buf, msg, msize); | ||
2063 | GNUNET_MQ_impl_send_continue (mq); | ||
2064 | return msize; | ||
2065 | } | ||
2066 | |||
2067 | |||
2068 | /** | ||
2069 | * Signature of functions implementing the | ||
2070 | * sending functionality of a message queue. | ||
2071 | * | ||
2072 | * @param mq the message queue | ||
2073 | * @param msg the message to send | ||
2074 | * @param impl_state state of the implementation | ||
2075 | */ | ||
2076 | static void | ||
2077 | cadet_mq_send_impl (struct GNUNET_MQ_Handle *mq, | ||
2078 | const struct GNUNET_MessageHeader *msg, void *impl_state) | ||
2079 | { | ||
2080 | struct CadetMQState *state = impl_state; | ||
2081 | |||
2082 | GNUNET_assert (NULL == state->th); | ||
2083 | state->th = | ||
2084 | GNUNET_CADET_notify_transmit_ready (state->channel, | ||
2085 | /* FIXME: add option for corking */ | ||
2086 | GNUNET_NO, | ||
2087 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
2088 | ntohs (msg->size), | ||
2089 | cadet_mq_ntr, mq); | ||
2090 | |||
2091 | } | ||
2092 | |||
2093 | |||
2094 | /** | ||
2095 | * Signature of functions implementing the | ||
2096 | * destruction of a message queue. | ||
2097 | * Implementations must not free 'mq', but should | ||
2098 | * take care of 'impl_state'. | ||
2099 | * | ||
2100 | * @param mq the message queue to destroy | ||
2101 | * @param impl_state state of the implementation | ||
2102 | */ | ||
2103 | static void | ||
2104 | cadet_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state) | ||
2105 | { | ||
2106 | struct CadetMQState *state = impl_state; | ||
2107 | |||
2108 | if (NULL != state->th) | ||
2109 | GNUNET_CADET_notify_transmit_ready_cancel (state->th); | ||
2110 | |||
2111 | GNUNET_free (state); | ||
2112 | } | ||
2113 | |||
2114 | |||
2115 | /** | ||
2116 | * Create a message queue for a cadet channel. | ||
2117 | * The message queue can only be used to transmit messages, | ||
2118 | * not to receive them. | ||
2119 | * | ||
2120 | * @param channel the channel to create the message qeue for | ||
2121 | * @return a message queue to messages over the channel | ||
2122 | */ | ||
2123 | struct GNUNET_MQ_Handle * | ||
2124 | GNUNET_CADET_mq_create (struct GNUNET_CADET_Channel *channel) | ||
2125 | { | ||
2126 | struct GNUNET_MQ_Handle *mq; | ||
2127 | struct CadetMQState *state; | ||
2128 | |||
2129 | state = GNUNET_new (struct CadetMQState); | ||
2130 | state->channel = channel; | ||
2131 | |||
2132 | mq = GNUNET_MQ_queue_for_callbacks (cadet_mq_send_impl, | ||
2133 | cadet_mq_destroy_impl, | ||
2134 | NULL, /* FIXME: cancel impl. */ | ||
2135 | state, | ||
2136 | NULL, /* no msg handlers */ | ||
2137 | NULL, /* no err handlers */ | ||
2138 | NULL); /* no handler cls */ | ||
2139 | return mq; | ||
2140 | } | ||
2141 | |||
diff --git a/src/cadet/cadet_common.c b/src/cadet/cadet_common.c new file mode 100644 index 000000000..855e9e20c --- /dev/null +++ b/src/cadet/cadet_common.c | |||
@@ -0,0 +1,348 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2012 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, 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 | GM_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 | int | ||
55 | GM_is_pid_bigger (uint32_t bigger, uint32_t smaller) | ||
56 | { | ||
57 | return (GNUNET_YES == PID_OVERFLOW (smaller, bigger) || | ||
58 | (bigger > smaller && GNUNET_NO == PID_OVERFLOW (bigger, smaller))); | ||
59 | } | ||
60 | |||
61 | |||
62 | uint32_t | ||
63 | GM_max_pid (uint32_t a, uint32_t b) | ||
64 | { | ||
65 | if (GM_is_pid_bigger(a, b)) | ||
66 | return a; | ||
67 | return b; | ||
68 | } | ||
69 | |||
70 | |||
71 | uint32_t | ||
72 | GM_min_pid (uint32_t a, uint32_t b) | ||
73 | { | ||
74 | if (GM_is_pid_bigger(a, b)) | ||
75 | return b; | ||
76 | return a; | ||
77 | } | ||
78 | |||
79 | |||
80 | const struct GNUNET_HashCode * | ||
81 | GM_h2hc (const struct GNUNET_CADET_Hash *id) | ||
82 | { | ||
83 | static struct GNUNET_HashCode hc; | ||
84 | memcpy (&hc, id, sizeof (*id)); | ||
85 | |||
86 | return &hc; | ||
87 | } | ||
88 | |||
89 | |||
90 | const char * | ||
91 | GM_h2s (const struct GNUNET_CADET_Hash *id) | ||
92 | { | ||
93 | static char s[53]; | ||
94 | |||
95 | memcpy (s, GNUNET_h2s_full (GM_h2hc (id)), 52); | ||
96 | s[52] = '\0'; | ||
97 | |||
98 | return s; | ||
99 | } | ||
100 | |||
101 | |||
102 | #if !defined(GNUNET_CULL_LOGGING) | ||
103 | const char * | ||
104 | GM_m2s (uint16_t m) | ||
105 | { | ||
106 | static char buf[32]; | ||
107 | const char *t; | ||
108 | |||
109 | switch (m) | ||
110 | { | ||
111 | /** | ||
112 | * Request the creation of a path | ||
113 | */ | ||
114 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
115 | t = "CONNECTION_CREATE"; | ||
116 | break; | ||
117 | |||
118 | /** | ||
119 | * Request the modification of an existing path | ||
120 | */ | ||
121 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
122 | t = "CONNECTION_ACK"; | ||
123 | break; | ||
124 | |||
125 | /** | ||
126 | * Notify that a connection of a path is no longer valid | ||
127 | */ | ||
128 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
129 | t = "CONNECTION_BROKEN"; | ||
130 | break; | ||
131 | |||
132 | /** | ||
133 | * At some point, the route will spontaneously change | ||
134 | */ | ||
135 | case GNUNET_MESSAGE_TYPE_CADET_PATH_CHANGED: | ||
136 | t = "PATH_CHANGED"; | ||
137 | break; | ||
138 | |||
139 | /** | ||
140 | * Transport payload data. | ||
141 | */ | ||
142 | case GNUNET_MESSAGE_TYPE_CADET_DATA: | ||
143 | t = "DATA"; | ||
144 | break; | ||
145 | |||
146 | /** | ||
147 | * Confirm receipt of payload data. | ||
148 | */ | ||
149 | case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: | ||
150 | t = "DATA_ACK"; | ||
151 | break; | ||
152 | |||
153 | /** | ||
154 | * Key exchange encapsulation. | ||
155 | */ | ||
156 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
157 | t = "KX"; | ||
158 | break; | ||
159 | |||
160 | /** | ||
161 | * New ephemeral key. | ||
162 | */ | ||
163 | case GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL: | ||
164 | t = "KX_EPHEMERAL"; | ||
165 | break; | ||
166 | |||
167 | /** | ||
168 | * Challenge to test peer's session key. | ||
169 | */ | ||
170 | case GNUNET_MESSAGE_TYPE_CADET_KX_PING: | ||
171 | t = "KX_PING"; | ||
172 | break; | ||
173 | |||
174 | /** | ||
175 | * Answer to session key challenge. | ||
176 | */ | ||
177 | case GNUNET_MESSAGE_TYPE_CADET_KX_PONG: | ||
178 | t = "KX_PONG"; | ||
179 | break; | ||
180 | |||
181 | /** | ||
182 | * Request the destuction of a path | ||
183 | */ | ||
184 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
185 | t = "CONNECTION_DESTROY"; | ||
186 | break; | ||
187 | |||
188 | /** | ||
189 | * ACK for a data packet. | ||
190 | */ | ||
191 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
192 | t = "ACK"; | ||
193 | break; | ||
194 | |||
195 | /** | ||
196 | * POLL for ACK. | ||
197 | */ | ||
198 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
199 | t = "POLL"; | ||
200 | break; | ||
201 | |||
202 | /** | ||
203 | * Announce origin is still alive. | ||
204 | */ | ||
205 | case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE: | ||
206 | t = "KEEPALIVE"; | ||
207 | break; | ||
208 | |||
209 | /** | ||
210 | * Connect to the cadet service, specifying subscriptions | ||
211 | */ | ||
212 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT: | ||
213 | t = "LOCAL_CONNECT"; | ||
214 | break; | ||
215 | |||
216 | /** | ||
217 | * Ask the cadet service to create a new tunnel | ||
218 | */ | ||
219 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
220 | t = "CHANNEL_CREATE"; | ||
221 | break; | ||
222 | |||
223 | /** | ||
224 | * Ask the cadet service to destroy a tunnel | ||
225 | */ | ||
226 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
227 | t = "CHANNEL_DESTROY"; | ||
228 | break; | ||
229 | |||
230 | /** | ||
231 | * Confirm the creation of a channel. | ||
232 | */ | ||
233 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: | ||
234 | t = "CHANNEL_ACK"; | ||
235 | break; | ||
236 | |||
237 | /** | ||
238 | * Confirm the creation of a channel. | ||
239 | */ | ||
240 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: | ||
241 | t = "CHANNEL_NACK"; | ||
242 | break; | ||
243 | |||
244 | /** | ||
245 | * Encrypted payload. | ||
246 | */ | ||
247 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
248 | t = "ENCRYPTED"; | ||
249 | break; | ||
250 | |||
251 | /** | ||
252 | * Local payload traffic | ||
253 | */ | ||
254 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA: | ||
255 | t = "LOCAL_DATA"; | ||
256 | break; | ||
257 | |||
258 | /** | ||
259 | * Local ACK for data. | ||
260 | */ | ||
261 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK: | ||
262 | t = "LOCAL_ACK"; | ||
263 | break; | ||
264 | |||
265 | /** | ||
266 | * Local monitoring of channels. | ||
267 | */ | ||
268 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNELS: | ||
269 | t = "LOCAL_INFO_CHANNELS"; | ||
270 | break; | ||
271 | |||
272 | /** | ||
273 | * Local monitoring of a channel. | ||
274 | */ | ||
275 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CHANNEL: | ||
276 | t = "LOCAL_INFO_CHANNEL"; | ||
277 | break; | ||
278 | |||
279 | /** | ||
280 | * Local monitoring of service. | ||
281 | */ | ||
282 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS: | ||
283 | t = "LOCAL_INFO_TUNNELS"; | ||
284 | break; | ||
285 | |||
286 | /** | ||
287 | * Local monitoring of service. | ||
288 | */ | ||
289 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL: | ||
290 | t = "LOCAL_INFO_TUNNEL"; | ||
291 | break; | ||
292 | |||
293 | /** | ||
294 | * Local information about all connections of service. | ||
295 | */ | ||
296 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CONNECTIONS: | ||
297 | t = "LOCAL_INFO_CONNECTIONS"; | ||
298 | break; | ||
299 | |||
300 | /** | ||
301 | * Local information of service about a specific connection. | ||
302 | */ | ||
303 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_CONNECTION: | ||
304 | t = "LOCAL_INFO_CONNECTION"; | ||
305 | break; | ||
306 | |||
307 | /** | ||
308 | * Local information about all peers known to the service. | ||
309 | */ | ||
310 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS: | ||
311 | t = "LOCAL_INFO_PEERS"; | ||
312 | break; | ||
313 | |||
314 | /** | ||
315 | * Local information of service about a specific peer. | ||
316 | */ | ||
317 | case GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEER: | ||
318 | t = "LOCAL_INFO_PEER"; | ||
319 | break; | ||
320 | |||
321 | /** | ||
322 | * Traffic (net-cat style) used by the Command Line Interface. | ||
323 | */ | ||
324 | case GNUNET_MESSAGE_TYPE_CADET_CLI: | ||
325 | t = "CLI"; | ||
326 | break; | ||
327 | |||
328 | /** | ||
329 | * 640kb should be enough for everybody | ||
330 | */ | ||
331 | case 299: | ||
332 | t = "RESERVE_END"; | ||
333 | break; | ||
334 | |||
335 | default: | ||
336 | sprintf(buf, "%u (UNKNOWN TYPE)", m); | ||
337 | return buf; | ||
338 | } | ||
339 | sprintf(buf, "{%18s}", t); | ||
340 | return buf; | ||
341 | } | ||
342 | #else | ||
343 | const char * | ||
344 | GM_m2s (uint16_t m) | ||
345 | { | ||
346 | return ""; | ||
347 | } | ||
348 | #endif | ||
diff --git a/src/cadet/cadet_path.c b/src/cadet/cadet_path.c new file mode 100644 index 000000000..0a97e73ef --- /dev/null +++ b/src/cadet/cadet_path.c | |||
@@ -0,0 +1,213 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2001 - 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, 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 | /** | ||
32 | * @brief Destroy a path after some time has past. | ||
33 | * | ||
34 | * If the path is returned from DHT again after a while, try again. | ||
35 | * | ||
36 | * @param cls Closure (path to destroy). | ||
37 | * @param tc Task context. | ||
38 | */ | ||
39 | static void | ||
40 | path_destroy_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
41 | { | ||
42 | struct CadetPeerPath *path = cls; | ||
43 | struct CadetPeer *peer; | ||
44 | |||
45 | path->path_delete = GNUNET_SCHEDULER_NO_TASK; | ||
46 | peer = GMP_get_short (path->peers[path->length - 1]); | ||
47 | GMP_remove_path (peer, path); | ||
48 | } | ||
49 | |||
50 | |||
51 | /** | ||
52 | * Create a new path | ||
53 | * | ||
54 | * @param length How many hops will the path have. | ||
55 | * | ||
56 | * @return A newly allocated path with a peer array of the specified length. | ||
57 | */ | ||
58 | struct CadetPeerPath * | ||
59 | path_new (unsigned int length) | ||
60 | { | ||
61 | struct CadetPeerPath *p; | ||
62 | |||
63 | p = GNUNET_new (struct CadetPeerPath); | ||
64 | if (length > 0) | ||
65 | { | ||
66 | p->length = length; | ||
67 | p->peers = GNUNET_malloc (length * sizeof (GNUNET_PEER_Id)); | ||
68 | } | ||
69 | return p; | ||
70 | } | ||
71 | |||
72 | |||
73 | /** | ||
74 | * Invert the path | ||
75 | * | ||
76 | * @param path the path to invert | ||
77 | */ | ||
78 | void | ||
79 | path_invert (struct CadetPeerPath *path) | ||
80 | { | ||
81 | GNUNET_PEER_Id aux; | ||
82 | unsigned int i; | ||
83 | |||
84 | for (i = 0; i < path->length / 2; i++) | ||
85 | { | ||
86 | aux = path->peers[i]; | ||
87 | path->peers[i] = path->peers[path->length - i - 1]; | ||
88 | path->peers[path->length - i - 1] = aux; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Duplicate a path, incrementing short peer's rc. | ||
95 | * | ||
96 | * @param path The path to duplicate. | ||
97 | */ | ||
98 | struct CadetPeerPath * | ||
99 | path_duplicate (const struct CadetPeerPath *path) | ||
100 | { | ||
101 | struct CadetPeerPath *aux; | ||
102 | unsigned int i; | ||
103 | |||
104 | aux = path_new (path->length); | ||
105 | memcpy (aux->peers, path->peers, path->length * sizeof (GNUNET_PEER_Id)); | ||
106 | for (i = 0; i < aux->length; i++) | ||
107 | GNUNET_PEER_change_rc (aux->peers[i], 1); | ||
108 | return aux; | ||
109 | } | ||
110 | |||
111 | |||
112 | /** | ||
113 | * Get the length of a path. | ||
114 | * | ||
115 | * @param path The path to measure, with the local peer at any point of it. | ||
116 | * | ||
117 | * @return Number of hops to reach destination. | ||
118 | * UINT_MAX in case the peer is not in the path. | ||
119 | */ | ||
120 | unsigned int | ||
121 | path_get_length (struct CadetPeerPath *path) | ||
122 | { | ||
123 | if (NULL == path) | ||
124 | return UINT_MAX; | ||
125 | return path->length; | ||
126 | } | ||
127 | |||
128 | |||
129 | |||
130 | /** | ||
131 | * Mark path as invalid: keep it aroud for a while to avoid trying it in a loop. | ||
132 | * | ||
133 | * DHT_get sometimes returns bad cached results, for instance, on a locally | ||
134 | * cached result where the PUT followed a path that is no longer current. | ||
135 | * | ||
136 | * @param p Path to invalidate. | ||
137 | */ | ||
138 | void | ||
139 | path_invalidate (struct CadetPeerPath *p) | ||
140 | { | ||
141 | if (GNUNET_SCHEDULER_NO_TASK != p->path_delete) | ||
142 | return; | ||
143 | |||
144 | p->path_delete = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, | ||
145 | &path_destroy_delayed, p); | ||
146 | } | ||
147 | |||
148 | |||
149 | /** | ||
150 | * Test if a path is valid (or at least not known to be invalid). | ||
151 | * | ||
152 | * @param path Path to test. | ||
153 | * | ||
154 | * @return #GNUNET_YES If the path is valid or unknown, | ||
155 | * #GNUNET_NO If the path is known to be invalid. | ||
156 | */ | ||
157 | int | ||
158 | path_is_valid (const struct CadetPeerPath *path) | ||
159 | { | ||
160 | return (GNUNET_SCHEDULER_NO_TASK == path->path_delete); | ||
161 | } | ||
162 | |||
163 | |||
164 | /** | ||
165 | * Destroy the path and free any allocated resources linked to it | ||
166 | * | ||
167 | * @param p the path to destroy | ||
168 | * | ||
169 | * @return GNUNET_OK on success | ||
170 | */ | ||
171 | int | ||
172 | path_destroy (struct CadetPeerPath *p) | ||
173 | { | ||
174 | if (NULL == p) | ||
175 | return GNUNET_OK; | ||
176 | |||
177 | GNUNET_PEER_decrement_rcs (p->peers, p->length); | ||
178 | GNUNET_free_non_null (p->peers); | ||
179 | if (GNUNET_SCHEDULER_NO_TASK != p->path_delete) | ||
180 | GNUNET_SCHEDULER_cancel (p->path_delete); | ||
181 | GNUNET_free (p); | ||
182 | return GNUNET_OK; | ||
183 | } | ||
184 | |||
185 | char * | ||
186 | path_2s (struct CadetPeerPath *p) | ||
187 | { | ||
188 | char *s; | ||
189 | char *old; | ||
190 | unsigned int i; | ||
191 | |||
192 | old = GNUNET_strdup (""); | ||
193 | for (i = 0; i < p->length; i++) | ||
194 | { | ||
195 | GNUNET_asprintf (&s, "%s %s", | ||
196 | old, GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i]))); | ||
197 | GNUNET_free_non_null (old); | ||
198 | old = s; | ||
199 | } | ||
200 | return s; | ||
201 | } | ||
202 | |||
203 | void | ||
204 | path_debug (struct CadetPeerPath *p) | ||
205 | { | ||
206 | unsigned int i; | ||
207 | |||
208 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PATH:\n"); | ||
209 | for (i = 0; i < p->length; i++) | ||
210 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %s\n", | ||
211 | GNUNET_i2s (GNUNET_PEER_resolve2 (p->peers[i]))); | ||
212 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "END\n"); | ||
213 | } | ||
diff --git a/src/cadet/cadet_path.h b/src/cadet/cadet_path.h new file mode 100644 index 000000000..36bcfa5ae --- /dev/null +++ b/src/cadet/cadet_path.h | |||
@@ -0,0 +1,185 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2001 - 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/cadet_path.h | ||
23 | * @brief Path handling functions | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "gnunet-service-cadet_connection.h" | ||
28 | |||
29 | #ifndef CADET_PATH_H_ | ||
30 | #define CADET_PATH_H_ | ||
31 | |||
32 | #ifdef __cplusplus | ||
33 | extern "C" | ||
34 | { | ||
35 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
36 | } | ||
37 | #endif | ||
38 | #endif | ||
39 | |||
40 | /******************************************************************************/ | ||
41 | /************************ DATA STRUCTURES ****************************/ | ||
42 | /******************************************************************************/ | ||
43 | |||
44 | /** | ||
45 | * Information regarding a possible path to reach a single peer | ||
46 | */ | ||
47 | struct CadetPeerPath | ||
48 | { | ||
49 | |||
50 | /** | ||
51 | * Linked list | ||
52 | */ | ||
53 | struct CadetPeerPath *next; | ||
54 | struct CadetPeerPath *prev; | ||
55 | |||
56 | /** | ||
57 | * List of all the peers that form the path from origin to target. | ||
58 | */ | ||
59 | GNUNET_PEER_Id *peers; | ||
60 | |||
61 | /** | ||
62 | * Number of peers (hops) in the path | ||
63 | */ | ||
64 | unsigned int length; | ||
65 | |||
66 | /** | ||
67 | * User defined data store. | ||
68 | */ | ||
69 | struct CadetConnection *c; | ||
70 | |||
71 | /** | ||
72 | * Path's score, how reliable is the path. | ||
73 | */ | ||
74 | // int score; | ||
75 | |||
76 | /** | ||
77 | * Task to delete the path. | ||
78 | * We tried it, it didn't work, don't try again in a while. | ||
79 | */ | ||
80 | GNUNET_SCHEDULER_TaskIdentifier path_delete; | ||
81 | |||
82 | }; | ||
83 | |||
84 | /******************************************************************************/ | ||
85 | /************************* FUNCTIONS *****************************/ | ||
86 | /******************************************************************************/ | ||
87 | |||
88 | /** | ||
89 | * Create a new path. | ||
90 | * | ||
91 | * @param length How many hops will the path have. | ||
92 | * | ||
93 | * @return A newly allocated path with a peer array of the specified length. | ||
94 | */ | ||
95 | struct CadetPeerPath * | ||
96 | path_new (unsigned int length); | ||
97 | |||
98 | |||
99 | /** | ||
100 | * Invert the path. | ||
101 | * | ||
102 | * @param path The path to invert. | ||
103 | */ | ||
104 | void | ||
105 | path_invert (struct CadetPeerPath *path); | ||
106 | |||
107 | |||
108 | /** | ||
109 | * Duplicate a path, incrementing short peer's rc. | ||
110 | * | ||
111 | * @param path The path to duplicate. | ||
112 | */ | ||
113 | struct CadetPeerPath * | ||
114 | path_duplicate (const struct CadetPeerPath *path); | ||
115 | |||
116 | |||
117 | /** | ||
118 | * Get the length of a path. | ||
119 | * | ||
120 | * @param path The path to measure, with the local peer at any point of it. | ||
121 | * | ||
122 | * @return Number of hops to reach destination. | ||
123 | * UINT_MAX in case the peer is not in the path. | ||
124 | */ | ||
125 | unsigned int | ||
126 | path_get_length (struct CadetPeerPath *path); | ||
127 | |||
128 | /** | ||
129 | * Mark path as invalid: keep it aroud for a while to avoid trying it in a loop. | ||
130 | * | ||
131 | * DHT_get sometimes returns bad cached results, for instance, on a locally | ||
132 | * cached result where the PUT followed a path that is no longer current. | ||
133 | * | ||
134 | * @param p Path to invalidate. | ||
135 | */ | ||
136 | void | ||
137 | path_invalidate (struct CadetPeerPath *p); | ||
138 | |||
139 | /** | ||
140 | * Test if a path is valid (or at least not known to be invalid). | ||
141 | * | ||
142 | * @param path Path to test. | ||
143 | * | ||
144 | * @return #GNUNET_YES If the path is valid or unknown, | ||
145 | * #GNUNET_NO If the path is known to be invalid. | ||
146 | */ | ||
147 | int | ||
148 | path_is_valid (const struct CadetPeerPath *path); | ||
149 | |||
150 | /** | ||
151 | * Destroy the path and free any allocated resources linked to it | ||
152 | * | ||
153 | * @param p the path to destroy | ||
154 | * | ||
155 | * @return GNUNET_OK on success | ||
156 | */ | ||
157 | int | ||
158 | path_destroy (struct CadetPeerPath *p); | ||
159 | |||
160 | /** | ||
161 | * Path -> allocated one line string. Caller must free. | ||
162 | * | ||
163 | * @param p Path. | ||
164 | */ | ||
165 | char * | ||
166 | path_2s (struct CadetPeerPath *p); | ||
167 | |||
168 | /** | ||
169 | * Print info about the path for debug. | ||
170 | * | ||
171 | * @param p Path to debug. | ||
172 | */ | ||
173 | void | ||
174 | path_debug (struct CadetPeerPath *p); | ||
175 | |||
176 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
177 | { | ||
178 | #endif | ||
179 | #ifdef __cplusplus | ||
180 | } | ||
181 | #endif | ||
182 | |||
183 | |||
184 | /* ifndef CADET_PATH_H */ | ||
185 | #endif | ||
diff --git a/src/cadet/cadet_protocol.h b/src/cadet/cadet_protocol.h new file mode 100644 index 000000000..19cdfe4a0 --- /dev/null +++ b/src/cadet/cadet_protocol.h | |||
@@ -0,0 +1,459 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2001 - 2011 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @author Bartlomiej Polot | ||
23 | * @file cadet/cadet_protocol.h | ||
24 | */ | ||
25 | |||
26 | #ifndef CADET_PROTOCOL_H_ | ||
27 | #define CADET_PROTOCOL_H_ | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_util_lib.h" | ||
31 | #include "cadet.h" | ||
32 | |||
33 | #ifdef __cplusplus | ||
34 | |||
35 | struct GNUNET_CADET_TunnelMessage; | ||
36 | extern "C" | ||
37 | { | ||
38 | #if 0 | ||
39 | /* keep Emacsens' auto-indent happy */ | ||
40 | } | ||
41 | #endif | ||
42 | #endif | ||
43 | |||
44 | /******************************************************************************/ | ||
45 | /******************** CADET NETWORK MESSAGES **************************/ | ||
46 | /******************************************************************************/ | ||
47 | |||
48 | GNUNET_NETWORK_STRUCT_BEGIN | ||
49 | |||
50 | /** | ||
51 | * Message for cadet connection creation. | ||
52 | */ | ||
53 | struct GNUNET_CADET_ConnectionCreate | ||
54 | { | ||
55 | /** | ||
56 | * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE | ||
57 | * | ||
58 | * Size: sizeof (struct GNUNET_CADET_ConnectionCreate) + | ||
59 | * path_length * sizeof (struct GNUNET_PeerIdentity) | ||
60 | */ | ||
61 | struct GNUNET_MessageHeader header; | ||
62 | |||
63 | /** | ||
64 | * ID of the connection | ||
65 | */ | ||
66 | struct GNUNET_CADET_Hash cid; | ||
67 | |||
68 | /** | ||
69 | * path_length structs defining the *whole* path from the origin [0] to the | ||
70 | * final destination [path_length-1]. | ||
71 | */ | ||
72 | /* struct GNUNET_PeerIdentity peers[path_length]; */ | ||
73 | }; | ||
74 | |||
75 | /** | ||
76 | * Message for ack'ing a connection | ||
77 | */ | ||
78 | struct GNUNET_CADET_ConnectionACK | ||
79 | { | ||
80 | /** | ||
81 | * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK | ||
82 | */ | ||
83 | struct GNUNET_MessageHeader header; | ||
84 | |||
85 | /** | ||
86 | * ID of the connection. | ||
87 | */ | ||
88 | struct GNUNET_CADET_Hash cid; | ||
89 | |||
90 | }; | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Message for encapsulation of a Key eXchange message in a connection. | ||
95 | */ | ||
96 | struct GNUNET_CADET_KX | ||
97 | { | ||
98 | /** | ||
99 | * Type: GNUNET_MESSAGE_TYPE_CADET_KX. | ||
100 | */ | ||
101 | struct GNUNET_MessageHeader header; | ||
102 | |||
103 | /** | ||
104 | * ID of the connection. | ||
105 | */ | ||
106 | struct GNUNET_CADET_Hash cid; | ||
107 | |||
108 | /* Specific KX message follows. */ | ||
109 | }; | ||
110 | |||
111 | |||
112 | /** | ||
113 | * Message transmitted with the signed ephemeral key of a peer. The | ||
114 | * session key is then derived from the two ephemeral keys (ECDHE). | ||
115 | * | ||
116 | * As far as possible, same as CORE's EphemeralKeyMessage. | ||
117 | */ | ||
118 | struct GNUNET_CADET_KX_Ephemeral | ||
119 | { | ||
120 | |||
121 | /** | ||
122 | * Message type is GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL. | ||
123 | */ | ||
124 | struct GNUNET_MessageHeader header; | ||
125 | |||
126 | /** | ||
127 | * Status of the sender (should be in "enum PeerStateMachine"), nbo. | ||
128 | */ | ||
129 | int32_t sender_status GNUNET_PACKED; | ||
130 | |||
131 | /** | ||
132 | * An ECC signature of the 'origin' asserting the validity of | ||
133 | * the given ephemeral key. | ||
134 | */ | ||
135 | struct GNUNET_CRYPTO_EddsaSignature signature; | ||
136 | |||
137 | /** | ||
138 | * Information about what is being signed. | ||
139 | */ | ||
140 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
141 | |||
142 | /** | ||
143 | * At what time was this key created (beginning of validity). | ||
144 | */ | ||
145 | struct GNUNET_TIME_AbsoluteNBO creation_time; | ||
146 | |||
147 | /** | ||
148 | * When does the given ephemeral key expire (end of validity). | ||
149 | */ | ||
150 | struct GNUNET_TIME_AbsoluteNBO expiration_time; | ||
151 | |||
152 | /** | ||
153 | * Ephemeral public ECC key (always for NIST P-521) encoded in a format suitable | ||
154 | * for network transmission as created using 'gcry_sexp_sprint'. | ||
155 | */ | ||
156 | struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; | ||
157 | |||
158 | /** | ||
159 | * Public key of the signing peer (persistent version, not the ephemeral public key). | ||
160 | */ | ||
161 | struct GNUNET_PeerIdentity origin_identity; | ||
162 | }; | ||
163 | |||
164 | |||
165 | /** | ||
166 | * We're sending an (encrypted) PING to the other peer to check if he | ||
167 | * can decrypt. The other peer should respond with a PONG with the | ||
168 | * same content, except this time encrypted with the receiver's key. | ||
169 | */ | ||
170 | struct GNUNET_CADET_KX_Ping | ||
171 | { | ||
172 | /** | ||
173 | * Message type is GNUNET_MESSAGE_TYPE_CADET_KX_PING. | ||
174 | */ | ||
175 | struct GNUNET_MessageHeader header; | ||
176 | |||
177 | /** | ||
178 | * Seed for the IV | ||
179 | */ | ||
180 | uint32_t iv GNUNET_PACKED; | ||
181 | |||
182 | /** | ||
183 | * Intended target of the PING, used primarily to check | ||
184 | * that decryption actually worked. | ||
185 | */ | ||
186 | struct GNUNET_PeerIdentity target; | ||
187 | |||
188 | /** | ||
189 | * Random number chosen to make reply harder. | ||
190 | */ | ||
191 | uint32_t nonce GNUNET_PACKED; | ||
192 | }; | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Response to a PING. Includes data from the original PING. | ||
197 | */ | ||
198 | struct GNUNET_CADET_KX_Pong | ||
199 | { | ||
200 | /** | ||
201 | * Message type is GNUNET_MESSAGE_TYPE_CADET_KX_PONG. | ||
202 | */ | ||
203 | struct GNUNET_MessageHeader header; | ||
204 | |||
205 | /** | ||
206 | * Seed for the IV | ||
207 | */ | ||
208 | uint32_t iv GNUNET_PACKED; | ||
209 | |||
210 | /** | ||
211 | * Same nonce as in the reve. | ||
212 | */ | ||
213 | uint32_t nonce GNUNET_PACKED; | ||
214 | }; | ||
215 | |||
216 | |||
217 | /** | ||
218 | * Tunnel(ed) message. | ||
219 | */ | ||
220 | struct GNUNET_CADET_Encrypted | ||
221 | { | ||
222 | /** | ||
223 | * Type: GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED | ||
224 | */ | ||
225 | struct GNUNET_MessageHeader header; | ||
226 | |||
227 | /** | ||
228 | * ID of the connection. | ||
229 | */ | ||
230 | struct GNUNET_CADET_Hash cid; | ||
231 | |||
232 | /** | ||
233 | * ID of the packet (hop by hop). | ||
234 | */ | ||
235 | uint32_t pid GNUNET_PACKED; | ||
236 | |||
237 | /** | ||
238 | * Number of hops to live. | ||
239 | */ | ||
240 | uint32_t ttl GNUNET_PACKED; | ||
241 | |||
242 | /** | ||
243 | * Initialization Vector for payload encryption. | ||
244 | */ | ||
245 | uint32_t iv GNUNET_PACKED; | ||
246 | |||
247 | /** | ||
248 | * MAC of the encrypted message, used to verify message integrity. | ||
249 | * Everything after this value will be encrypted and authenticated. | ||
250 | */ | ||
251 | struct GNUNET_CADET_Hash hmac; | ||
252 | |||
253 | /** | ||
254 | * Encrypted content follows. | ||
255 | */ | ||
256 | }; | ||
257 | |||
258 | |||
259 | /** | ||
260 | * Message to create a Channel. | ||
261 | */ | ||
262 | struct GNUNET_CADET_ChannelCreate | ||
263 | { | ||
264 | /** | ||
265 | * Type: GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE | ||
266 | */ | ||
267 | struct GNUNET_MessageHeader header; | ||
268 | |||
269 | /** | ||
270 | * ID of the channel | ||
271 | */ | ||
272 | CADET_ChannelNumber chid GNUNET_PACKED; | ||
273 | |||
274 | /** | ||
275 | * Destination port. | ||
276 | */ | ||
277 | uint32_t port GNUNET_PACKED; | ||
278 | |||
279 | /** | ||
280 | * Channel options. | ||
281 | */ | ||
282 | uint32_t opt GNUNET_PACKED; | ||
283 | }; | ||
284 | |||
285 | |||
286 | /** | ||
287 | * Message to manage a Channel (ACK, NACK, Destroy). | ||
288 | */ | ||
289 | struct GNUNET_CADET_ChannelManage | ||
290 | { | ||
291 | /** | ||
292 | * Type: GNUNET_MESSAGE_TYPE_CADET_CHANNEL_{ACK|NACK|DESTROY} | ||
293 | */ | ||
294 | struct GNUNET_MessageHeader header; | ||
295 | |||
296 | /** | ||
297 | * ID of the channel | ||
298 | */ | ||
299 | CADET_ChannelNumber chid GNUNET_PACKED; | ||
300 | }; | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Message for cadet data traffic. | ||
305 | */ | ||
306 | struct GNUNET_CADET_Data | ||
307 | { | ||
308 | /** | ||
309 | * Type: GNUNET_MESSAGE_TYPE_CADET_UNICAST, | ||
310 | * GNUNET_MESSAGE_TYPE_CADET_TO_ORIGIN | ||
311 | */ | ||
312 | struct GNUNET_MessageHeader header; | ||
313 | |||
314 | /** | ||
315 | * Unique ID of the payload message | ||
316 | */ | ||
317 | uint32_t mid GNUNET_PACKED; | ||
318 | |||
319 | /** | ||
320 | * ID of the channel | ||
321 | */ | ||
322 | CADET_ChannelNumber chid GNUNET_PACKED; | ||
323 | |||
324 | /** | ||
325 | * Payload follows | ||
326 | */ | ||
327 | }; | ||
328 | |||
329 | |||
330 | /** | ||
331 | * Message to acknowledge end-to-end data. | ||
332 | */ | ||
333 | struct GNUNET_CADET_DataACK | ||
334 | { | ||
335 | /** | ||
336 | * Type: GNUNET_MESSAGE_TYPE_CADET_DATA_ACK | ||
337 | */ | ||
338 | struct GNUNET_MessageHeader header; | ||
339 | |||
340 | /** | ||
341 | * ID of the channel | ||
342 | */ | ||
343 | CADET_ChannelNumber chid GNUNET_PACKED; | ||
344 | |||
345 | /** | ||
346 | * Bitfield of already-received newer messages | ||
347 | * pid + 1 @ LSB | ||
348 | * pid + 64 @ MSB | ||
349 | */ | ||
350 | uint64_t futures GNUNET_PACKED; | ||
351 | |||
352 | /** | ||
353 | * Last message ID received. | ||
354 | */ | ||
355 | uint32_t mid GNUNET_PACKED; | ||
356 | }; | ||
357 | |||
358 | |||
359 | /** | ||
360 | * Message to acknowledge cadet encrypted traffic. | ||
361 | */ | ||
362 | struct GNUNET_CADET_ACK | ||
363 | { | ||
364 | /** | ||
365 | * Type: GNUNET_MESSAGE_TYPE_CADET_ACK | ||
366 | */ | ||
367 | struct GNUNET_MessageHeader header; | ||
368 | |||
369 | /** | ||
370 | * Maximum packet ID authorized. | ||
371 | */ | ||
372 | uint32_t ack GNUNET_PACKED; | ||
373 | |||
374 | /** | ||
375 | * ID of the connection. | ||
376 | */ | ||
377 | struct GNUNET_CADET_Hash cid; | ||
378 | }; | ||
379 | |||
380 | |||
381 | /** | ||
382 | * Message to query a peer about its Flow Control status regarding a tunnel. | ||
383 | */ | ||
384 | struct GNUNET_CADET_Poll | ||
385 | { | ||
386 | /** | ||
387 | * Type: GNUNET_MESSAGE_TYPE_CADET_POLL | ||
388 | */ | ||
389 | struct GNUNET_MessageHeader header; | ||
390 | |||
391 | /** | ||
392 | * Last packet sent. | ||
393 | */ | ||
394 | uint32_t pid GNUNET_PACKED; | ||
395 | |||
396 | /** | ||
397 | * ID of the connection. | ||
398 | */ | ||
399 | struct GNUNET_CADET_Hash cid; | ||
400 | |||
401 | }; | ||
402 | |||
403 | |||
404 | /** | ||
405 | * Message for notifying a disconnection in a path | ||
406 | */ | ||
407 | struct GNUNET_CADET_ConnectionBroken | ||
408 | { | ||
409 | /** | ||
410 | * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN | ||
411 | */ | ||
412 | struct GNUNET_MessageHeader header; | ||
413 | |||
414 | /** | ||
415 | * ID of the connection. | ||
416 | */ | ||
417 | struct GNUNET_CADET_Hash cid; | ||
418 | |||
419 | /** | ||
420 | * ID of the endpoint | ||
421 | */ | ||
422 | struct GNUNET_PeerIdentity peer1; | ||
423 | |||
424 | /** | ||
425 | * ID of the endpoint | ||
426 | */ | ||
427 | struct GNUNET_PeerIdentity peer2; | ||
428 | }; | ||
429 | |||
430 | |||
431 | /** | ||
432 | * Message to destroy a connection. | ||
433 | */ | ||
434 | struct GNUNET_CADET_ConnectionDestroy | ||
435 | { | ||
436 | /** | ||
437 | * Type: GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY | ||
438 | */ | ||
439 | struct GNUNET_MessageHeader header; | ||
440 | |||
441 | /** | ||
442 | * ID of the connection. | ||
443 | */ | ||
444 | struct GNUNET_CADET_Hash cid; | ||
445 | }; | ||
446 | |||
447 | |||
448 | GNUNET_NETWORK_STRUCT_END | ||
449 | |||
450 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
451 | { | ||
452 | #endif | ||
453 | #ifdef __cplusplus | ||
454 | } | ||
455 | #endif | ||
456 | |||
457 | /* ifndef CADET_PROTOCOL_H */ | ||
458 | #endif | ||
459 | /* end of cadet_protocol.h */ | ||
diff --git a/src/cadet/cadet_test_lib.c b/src/cadet/cadet_test_lib.c new file mode 100644 index 000000000..663972cad --- /dev/null +++ b/src/cadet/cadet_test_lib.c | |||
@@ -0,0 +1,295 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2012 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_test_lib.c | ||
22 | * @author Bartlomiej Polot | ||
23 | * @brief library for writing CADET tests | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "cadet_test_lib.h" | ||
28 | #include "gnunet_cadet_service.h" | ||
29 | |||
30 | /** | ||
31 | * Test context for a CADET Test. | ||
32 | */ | ||
33 | struct GNUNET_CADET_TEST_Context | ||
34 | { | ||
35 | /** | ||
36 | * Array of running peers. | ||
37 | */ | ||
38 | struct GNUNET_TESTBED_Peer **peers; | ||
39 | |||
40 | /** | ||
41 | * Array of handles to the CADET for each peer. | ||
42 | */ | ||
43 | struct GNUNET_CADET_Handle **cadetes; | ||
44 | |||
45 | /** | ||
46 | * Operation associated with the connection to the CADET. | ||
47 | */ | ||
48 | struct GNUNET_TESTBED_Operation **ops; | ||
49 | |||
50 | /** | ||
51 | * Main function of the test to run once all CADETs are available. | ||
52 | */ | ||
53 | GNUNET_CADET_TEST_AppMain app_main; | ||
54 | |||
55 | /** | ||
56 | * Closure for 'app_main'. | ||
57 | */ | ||
58 | void *app_main_cls; | ||
59 | |||
60 | /** | ||
61 | * Number of peers running, size of the arrays above. | ||
62 | */ | ||
63 | unsigned int num_peers; | ||
64 | |||
65 | /** | ||
66 | * Handler for incoming tunnels. | ||
67 | */ | ||
68 | GNUNET_CADET_InboundChannelNotificationHandler *new_channel; | ||
69 | |||
70 | /** | ||
71 | * Cleaner for destroyed incoming tunnels. | ||
72 | */ | ||
73 | GNUNET_CADET_ChannelEndHandler *cleaner; | ||
74 | |||
75 | /** | ||
76 | * Message handlers. | ||
77 | */ | ||
78 | struct GNUNET_CADET_MessageHandler* handlers; | ||
79 | |||
80 | /** | ||
81 | * Application ports. | ||
82 | */ | ||
83 | const uint32_t *ports; | ||
84 | |||
85 | }; | ||
86 | |||
87 | |||
88 | /** | ||
89 | * Context for a cadet adapter callback. | ||
90 | */ | ||
91 | struct GNUNET_CADET_TEST_AdapterContext | ||
92 | { | ||
93 | /** | ||
94 | * Peer number for the particular peer. | ||
95 | */ | ||
96 | unsigned int peer; | ||
97 | |||
98 | /** | ||
99 | * General context. | ||
100 | */ | ||
101 | struct GNUNET_CADET_TEST_Context *ctx; | ||
102 | }; | ||
103 | |||
104 | |||
105 | /** | ||
106 | * Adapter function called to establish a connection to | ||
107 | * the CADET service. | ||
108 | * | ||
109 | * @param cls closure | ||
110 | * @param cfg configuration of the peer to connect to; will be available until | ||
111 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
112 | * from GNUNET_TESTBED_service_connect() | ||
113 | * @return service handle to return in 'op_result', NULL on error | ||
114 | */ | ||
115 | static void * | ||
116 | cadet_connect_adapter (void *cls, | ||
117 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
118 | { | ||
119 | struct GNUNET_CADET_TEST_AdapterContext *actx = cls; | ||
120 | struct GNUNET_CADET_TEST_Context *ctx = actx->ctx; | ||
121 | struct GNUNET_CADET_Handle *h; | ||
122 | |||
123 | h = GNUNET_CADET_connect (cfg, | ||
124 | (void *) (long) actx->peer, | ||
125 | ctx->new_channel, | ||
126 | ctx->cleaner, | ||
127 | ctx->handlers, | ||
128 | ctx->ports); | ||
129 | return h; | ||
130 | } | ||
131 | |||
132 | |||
133 | /** | ||
134 | * Adapter function called to destroy a connection to | ||
135 | * the CADET service. | ||
136 | * | ||
137 | * @param cls closure | ||
138 | * @param op_result service handle returned from the connect adapter | ||
139 | */ | ||
140 | static void | ||
141 | cadet_disconnect_adapter (void *cls, | ||
142 | void *op_result) | ||
143 | { | ||
144 | struct GNUNET_CADET_Handle *cadet = op_result; | ||
145 | struct GNUNET_CADET_TEST_AdapterContext *actx = cls; | ||
146 | |||
147 | GNUNET_free (actx); | ||
148 | GNUNET_CADET_disconnect (cadet); | ||
149 | } | ||
150 | |||
151 | |||
152 | /** | ||
153 | * Callback to be called when a service connect operation is completed. | ||
154 | * | ||
155 | * @param cls The callback closure from functions generating an operation. | ||
156 | * @param op The operation that has been finished. | ||
157 | * @param ca_result The service handle returned from | ||
158 | * GNUNET_TESTBED_ConnectAdapter() (cadet handle). | ||
159 | * @param emsg Error message in case the operation has failed. | ||
160 | * NULL if operation has executed successfully. | ||
161 | */ | ||
162 | static void | ||
163 | cadet_connect_cb (void *cls, | ||
164 | struct GNUNET_TESTBED_Operation *op, | ||
165 | void *ca_result, | ||
166 | const char *emsg) | ||
167 | { | ||
168 | struct GNUNET_CADET_TEST_Context *ctx = cls; | ||
169 | unsigned int i; | ||
170 | |||
171 | if (NULL != emsg) | ||
172 | { | ||
173 | fprintf (stderr, "Failed to connect to CADET service: %s\n", | ||
174 | emsg); | ||
175 | GNUNET_SCHEDULER_shutdown (); | ||
176 | return; | ||
177 | } | ||
178 | for (i = 0; i < ctx->num_peers; i++) | ||
179 | if (op == ctx->ops[i]) | ||
180 | { | ||
181 | ctx->cadetes[i] = ca_result; | ||
182 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...cadet %u connected\n", i); | ||
183 | } | ||
184 | for (i = 0; i < ctx->num_peers; i++) | ||
185 | if (NULL == ctx->cadetes[i]) | ||
186 | return; /* still some CADET connections missing */ | ||
187 | /* all CADET connections ready! */ | ||
188 | ctx->app_main (ctx->app_main_cls, | ||
189 | ctx, | ||
190 | ctx->num_peers, | ||
191 | ctx->peers, | ||
192 | ctx->cadetes); | ||
193 | } | ||
194 | |||
195 | |||
196 | void | ||
197 | GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx) | ||
198 | { | ||
199 | unsigned int i; | ||
200 | |||
201 | for (i = 0; i < ctx->num_peers; i++) | ||
202 | { | ||
203 | GNUNET_assert (NULL != ctx->ops[i]); | ||
204 | GNUNET_TESTBED_operation_done (ctx->ops[i]); | ||
205 | ctx->ops[i] = NULL; | ||
206 | } | ||
207 | GNUNET_free (ctx->ops); | ||
208 | GNUNET_free (ctx->cadetes); | ||
209 | GNUNET_free (ctx); | ||
210 | GNUNET_SCHEDULER_shutdown (); | ||
211 | } | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Callback run when the testbed is ready (peers running and connected to | ||
216 | * each other) | ||
217 | * | ||
218 | * @param cls Closure (context). | ||
219 | * @param h the run handle | ||
220 | * @param num_peers Number of peers that are running. | ||
221 | * @param peers Handles to each one of the @c num_peers peers. | ||
222 | * @param links_succeeded the number of overlay link connection attempts that | ||
223 | * succeeded | ||
224 | * @param links_failed the number of overlay link connection attempts that | ||
225 | * failed | ||
226 | */ | ||
227 | static void | ||
228 | cadet_test_run (void *cls, | ||
229 | struct GNUNET_TESTBED_RunHandle *h, | ||
230 | unsigned int num_peers, | ||
231 | struct GNUNET_TESTBED_Peer **peers, | ||
232 | unsigned int links_succeeded, | ||
233 | unsigned int links_failed) | ||
234 | { | ||
235 | struct GNUNET_CADET_TEST_Context *ctx = cls; | ||
236 | unsigned int i; | ||
237 | |||
238 | if (num_peers != ctx->num_peers) | ||
239 | { | ||
240 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n", | ||
241 | num_peers, ctx->num_peers); | ||
242 | exit (1); | ||
243 | } | ||
244 | ctx->peers = peers; | ||
245 | for (i = 0; i < num_peers; i++) | ||
246 | { | ||
247 | struct GNUNET_CADET_TEST_AdapterContext *newctx; | ||
248 | newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext); | ||
249 | newctx->peer = i; | ||
250 | newctx->ctx = ctx; | ||
251 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to cadet %u\n", i); | ||
252 | ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx, | ||
253 | peers[i], | ||
254 | "cadet", | ||
255 | &cadet_connect_cb, | ||
256 | ctx, | ||
257 | &cadet_connect_adapter, | ||
258 | &cadet_disconnect_adapter, | ||
259 | newctx); | ||
260 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "op handle %p\n", ctx->ops[i]); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | |||
265 | void | ||
266 | GNUNET_CADET_TEST_run (const char *testname, | ||
267 | const char *cfgname, | ||
268 | unsigned int num_peers, | ||
269 | GNUNET_CADET_TEST_AppMain tmain, | ||
270 | void *tmain_cls, | ||
271 | GNUNET_CADET_InboundChannelNotificationHandler new_channel, | ||
272 | GNUNET_CADET_ChannelEndHandler cleaner, | ||
273 | struct GNUNET_CADET_MessageHandler* handlers, | ||
274 | const uint32_t *ports) | ||
275 | { | ||
276 | struct GNUNET_CADET_TEST_Context *ctx; | ||
277 | |||
278 | ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context); | ||
279 | ctx->num_peers = num_peers; | ||
280 | ctx->ops = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *)); | ||
281 | ctx->cadetes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_CADET_Handle *)); | ||
282 | ctx->app_main = tmain; | ||
283 | ctx->app_main_cls = tmain_cls; | ||
284 | ctx->new_channel = new_channel; | ||
285 | ctx->cleaner = cleaner; | ||
286 | ctx->handlers = handlers; | ||
287 | ctx->ports = ports; | ||
288 | GNUNET_TESTBED_test_run (testname, | ||
289 | cfgname, | ||
290 | num_peers, | ||
291 | 0LL, NULL, NULL, | ||
292 | &cadet_test_run, ctx); | ||
293 | } | ||
294 | |||
295 | /* end of cadet_test_lib.c */ | ||
diff --git a/src/cadet/cadet_test_lib.h b/src/cadet/cadet_test_lib.h new file mode 100644 index 000000000..f2ed426b0 --- /dev/null +++ b/src/cadet/cadet_test_lib.h | |||
@@ -0,0 +1,106 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2012 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/cadet_test_lib.h | ||
22 | * @author Bartlomiej Polot | ||
23 | * @brief library for writing CADET tests | ||
24 | */ | ||
25 | #ifndef CADET_TEST_LIB_H | ||
26 | #define CADET_TEST_LIB_H | ||
27 | |||
28 | #ifdef __cplusplus | ||
29 | extern "C" | ||
30 | { | ||
31 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
32 | } | ||
33 | #endif | ||
34 | #endif | ||
35 | |||
36 | #include "gnunet_testbed_service.h" | ||
37 | #include "gnunet_cadet_service.h" | ||
38 | |||
39 | /** | ||
40 | * Test context for a CADET Test. | ||
41 | */ | ||
42 | struct GNUNET_CADET_TEST_Context; | ||
43 | |||
44 | |||
45 | /** | ||
46 | * Main function of a CADET test. | ||
47 | * | ||
48 | * @param cls Closure. | ||
49 | * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. | ||
50 | * @param num_peers Number of peers that are running. | ||
51 | * @param peers Array of peers. | ||
52 | * @param cadetes Handle to each of the CADETs of the peers. | ||
53 | */ | ||
54 | typedef void (*GNUNET_CADET_TEST_AppMain) (void *cls, | ||
55 | struct GNUNET_CADET_TEST_Context *ctx, | ||
56 | unsigned int num_peers, | ||
57 | struct GNUNET_TESTBED_Peer **peers, | ||
58 | struct GNUNET_CADET_Handle **cadetes); | ||
59 | |||
60 | |||
61 | /** | ||
62 | * Run a test using the given name, configuration file and number of | ||
63 | * peers. | ||
64 | * All cadet callbacks will receive the peer number as the closure. | ||
65 | * | ||
66 | * @param testname Name of the test (for logging). | ||
67 | * @param cfgname Name of the configuration file. | ||
68 | * @param num_peers Number of peers to start. | ||
69 | * @param tmain Main function to run once the testbed is ready. | ||
70 | * @param tmain_cls Closure for 'tmain'. | ||
71 | * @param new_channel Handler for incoming tunnels. | ||
72 | * @param cleaner Cleaner for destroyed incoming tunnels. | ||
73 | * @param handlers Message handlers. | ||
74 | * @param ports Ports the peers offer. | ||
75 | */ | ||
76 | void | ||
77 | GNUNET_CADET_TEST_run (const char *testname, | ||
78 | const char *cfgname, | ||
79 | unsigned int num_peers, | ||
80 | GNUNET_CADET_TEST_AppMain tmain, | ||
81 | void *tmain_cls, | ||
82 | GNUNET_CADET_InboundChannelNotificationHandler new_channel, | ||
83 | GNUNET_CADET_ChannelEndHandler cleaner, | ||
84 | struct GNUNET_CADET_MessageHandler* handlers, | ||
85 | const uint32_t* ports); | ||
86 | |||
87 | |||
88 | /** | ||
89 | * Clean up the testbed. | ||
90 | * | ||
91 | * @param ctx handle for the testbed | ||
92 | */ | ||
93 | void | ||
94 | GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx); | ||
95 | |||
96 | |||
97 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
98 | { | ||
99 | #endif | ||
100 | #ifdef __cplusplus | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | |||
105 | /* ifndef CADET_TEST_LIB_H */ | ||
106 | #endif | ||
diff --git a/src/cadet/cadet_tunnel_tree.c b/src/cadet/cadet_tunnel_tree.c new file mode 100644 index 000000000..dd3f3dae1 --- /dev/null +++ b/src/cadet/cadet_tunnel_tree.c | |||
@@ -0,0 +1,1174 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2001 - 2011 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/cadet_tunnel_tree.c | ||
23 | * @brief Tunnel tree handling functions | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "cadet.h" | ||
28 | #include "cadet_tunnel_tree.h" | ||
29 | |||
30 | #define CADET_TREE_DEBUG GNUNET_YES | ||
31 | |||
32 | |||
33 | /** | ||
34 | * Node of path tree for a tunnel | ||
35 | */ | ||
36 | struct CadetTunnelTreeNode | ||
37 | { | ||
38 | /** | ||
39 | * Peer this node describes | ||
40 | */ | ||
41 | GNUNET_PEER_Id peer; | ||
42 | |||
43 | /** | ||
44 | * Parent node in the tree | ||
45 | */ | ||
46 | struct CadetTunnelTreeNode *parent; | ||
47 | |||
48 | /** | ||
49 | * DLL of siblings | ||
50 | */ | ||
51 | struct CadetTunnelTreeNode *next; | ||
52 | |||
53 | /** | ||
54 | * DLL of siblings | ||
55 | */ | ||
56 | struct CadetTunnelTreeNode *prev; | ||
57 | |||
58 | /** | ||
59 | * DLL of children | ||
60 | */ | ||
61 | struct CadetTunnelTreeNode *children_head; | ||
62 | |||
63 | /** | ||
64 | * DLL of children | ||
65 | */ | ||
66 | struct CadetTunnelTreeNode *children_tail; | ||
67 | |||
68 | /** | ||
69 | * Status of the peer in the tunnel | ||
70 | */ | ||
71 | enum CadetPeerState status; | ||
72 | }; | ||
73 | |||
74 | |||
75 | /** | ||
76 | * Tree to reach all peers in the tunnel | ||
77 | */ | ||
78 | struct CadetTunnelTree | ||
79 | { | ||
80 | /** | ||
81 | * Root node of peer tree | ||
82 | */ | ||
83 | struct CadetTunnelTreeNode *root; | ||
84 | |||
85 | /** | ||
86 | * Node that represents our position in the tree (for non local tunnels) | ||
87 | */ | ||
88 | struct CadetTunnelTreeNode *me; | ||
89 | |||
90 | /** | ||
91 | * DLL of disconneted nodes | ||
92 | */ | ||
93 | struct CadetTunnelTreeNode *disconnected_head; | ||
94 | |||
95 | /** | ||
96 | * DLL of disconneted nodes | ||
97 | */ | ||
98 | struct CadetTunnelTreeNode *disconnected_tail; | ||
99 | |||
100 | /** | ||
101 | * Cache of all peers and the first hop to them. | ||
102 | * Indexed by PeerIdentity, contains a pointer to the PeerIdentity | ||
103 | * of 1st hop. | ||
104 | */ | ||
105 | struct GNUNET_CONTAINER_MultiHashMap *first_hops; | ||
106 | |||
107 | }; | ||
108 | |||
109 | |||
110 | /** | ||
111 | * Create a new path | ||
112 | * | ||
113 | * @param length How many hops will the path have. | ||
114 | * | ||
115 | * @return A newly allocated path with a peer array of the specified length. | ||
116 | */ | ||
117 | struct CadetPeerPath * | ||
118 | path_new (unsigned int length) | ||
119 | { | ||
120 | struct CadetPeerPath *p; | ||
121 | |||
122 | p = GNUNET_new (struct CadetPeerPath); | ||
123 | if (length > 0) | ||
124 | { | ||
125 | p->length = length; | ||
126 | p->peers = GNUNET_malloc (length * sizeof (GNUNET_PEER_Id)); | ||
127 | } | ||
128 | return p; | ||
129 | } | ||
130 | |||
131 | |||
132 | /** | ||
133 | * Invert the path | ||
134 | * | ||
135 | * @param path the path to invert | ||
136 | */ | ||
137 | void | ||
138 | path_invert (struct CadetPeerPath *path) | ||
139 | { | ||
140 | GNUNET_PEER_Id aux; | ||
141 | unsigned int i; | ||
142 | |||
143 | for (i = 0; i < path->length / 2; i++) | ||
144 | { | ||
145 | aux = path->peers[i]; | ||
146 | path->peers[i] = path->peers[path->length - i - 1]; | ||
147 | path->peers[path->length - i - 1] = aux; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | |||
152 | /** | ||
153 | * Duplicate a path, incrementing short peer's rc. | ||
154 | * | ||
155 | * @param path The path to duplicate. | ||
156 | */ | ||
157 | struct CadetPeerPath * | ||
158 | path_duplicate (struct CadetPeerPath *path) | ||
159 | { | ||
160 | struct CadetPeerPath *aux; | ||
161 | unsigned int i; | ||
162 | |||
163 | aux = path_new (path->length); | ||
164 | memcpy (aux->peers, path->peers, path->length * sizeof (GNUNET_PEER_Id)); | ||
165 | for (i = 0; i < path->length; i++) | ||
166 | GNUNET_PEER_change_rc (path->peers[i], 1); | ||
167 | return aux; | ||
168 | } | ||
169 | |||
170 | |||
171 | /** | ||
172 | * Recusively update the info about what is the first hop to reach the node | ||
173 | * | ||
174 | * @param tree Tree this nodes belongs to. | ||
175 | * @param parent The node form which to start updating. | ||
176 | * @param hop If known, ID of the first hop. | ||
177 | * If not known, NULL to find out and pass on children. | ||
178 | */ | ||
179 | static void | ||
180 | tree_node_update_first_hops (struct CadetTunnelTree *tree, | ||
181 | struct CadetTunnelTreeNode *parent, | ||
182 | struct GNUNET_PeerIdentity *hop); | ||
183 | |||
184 | |||
185 | /** | ||
186 | * Get the length of a path. | ||
187 | * | ||
188 | * @param path The path to measure, with the local peer at any point of it. | ||
189 | * | ||
190 | * @return Number of hops to reach destination. | ||
191 | * UINT_MAX in case the peer is not in the path. | ||
192 | */ | ||
193 | unsigned int | ||
194 | path_get_length (struct CadetPeerPath *path) | ||
195 | { | ||
196 | if (NULL == path) | ||
197 | return UINT_MAX; | ||
198 | return path->length; | ||
199 | } | ||
200 | |||
201 | |||
202 | /** | ||
203 | * Destroy the path and free any allocated resources linked to it | ||
204 | * | ||
205 | * @param p the path to destroy | ||
206 | * | ||
207 | * @return GNUNET_OK on success | ||
208 | */ | ||
209 | int | ||
210 | path_destroy (struct CadetPeerPath *p) | ||
211 | { | ||
212 | if (NULL == p) | ||
213 | return GNUNET_OK; | ||
214 | GNUNET_PEER_decrement_rcs (p->peers, p->length); | ||
215 | GNUNET_free_non_null (p->peers); | ||
216 | GNUNET_free (p); | ||
217 | return GNUNET_OK; | ||
218 | } | ||
219 | |||
220 | |||
221 | |||
222 | /** | ||
223 | * Allocates and initializes a new node. | ||
224 | * Sets ID and parent of the new node and inserts it in the DLL of the parent | ||
225 | * | ||
226 | * @param parent Node that will be the parent from the new node, NULL for root | ||
227 | * @param peer Short Id of the new node | ||
228 | * | ||
229 | * @return Newly allocated node | ||
230 | */ | ||
231 | static struct CadetTunnelTreeNode * | ||
232 | tree_node_new (struct CadetTunnelTreeNode *parent, GNUNET_PEER_Id peer) | ||
233 | { | ||
234 | struct CadetTunnelTreeNode *node; | ||
235 | |||
236 | node = GNUNET_new (struct CadetTunnelTreeNode); | ||
237 | node->peer = peer; | ||
238 | GNUNET_PEER_change_rc (peer, 1); | ||
239 | node->parent = parent; | ||
240 | if (NULL != parent) | ||
241 | GNUNET_CONTAINER_DLL_insert (parent->children_head, parent->children_tail, | ||
242 | node); | ||
243 | |||
244 | return node; | ||
245 | } | ||
246 | |||
247 | |||
248 | /** | ||
249 | * Recursively find the given peer. | ||
250 | * | ||
251 | * @param parent Node where to start looking. | ||
252 | * @param peer_id Short ID of the peer to find. | ||
253 | * | ||
254 | * @return Pointer to the node of the peer. NULL if not found. | ||
255 | */ | ||
256 | static struct CadetTunnelTreeNode * | ||
257 | tree_node_find_peer (struct CadetTunnelTreeNode *parent, GNUNET_PEER_Id peer_id) | ||
258 | { | ||
259 | struct CadetTunnelTreeNode *n; | ||
260 | struct CadetTunnelTreeNode *r; | ||
261 | |||
262 | if (parent->peer == peer_id) | ||
263 | return parent; | ||
264 | for (n = parent->children_head; NULL != n; n = n->next) | ||
265 | { | ||
266 | r = tree_node_find_peer (n, peer_id); | ||
267 | if (NULL != r) | ||
268 | return r; | ||
269 | } | ||
270 | return NULL; | ||
271 | } | ||
272 | |||
273 | |||
274 | /** | ||
275 | * Recusively update the info about what is the first hop to reach the node | ||
276 | * | ||
277 | * @param tree Tree this nodes belongs to. | ||
278 | * @param parent ID from node form which to start updating. | ||
279 | * @param hop If known, ID of the first hop. | ||
280 | * If not known, NULL to find out and pass on children. | ||
281 | */ | ||
282 | static void | ||
283 | tree_node_update_first_hops (struct CadetTunnelTree *tree, | ||
284 | struct CadetTunnelTreeNode *parent, | ||
285 | struct GNUNET_PeerIdentity *hop) | ||
286 | { | ||
287 | struct GNUNET_PeerIdentity pi; | ||
288 | struct GNUNET_PeerIdentity *copy; | ||
289 | struct GNUNET_PeerIdentity id; | ||
290 | struct CadetTunnelTreeNode *n; | ||
291 | |||
292 | #if CADET_TREE_DEBUG | ||
293 | GNUNET_PEER_resolve (parent->peer, &id); | ||
294 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Finding first hop for %s.\n", | ||
295 | GNUNET_i2s (&id)); | ||
296 | #endif | ||
297 | if (NULL == hop) | ||
298 | { | ||
299 | struct CadetTunnelTreeNode *aux; | ||
300 | struct CadetTunnelTreeNode *old; | ||
301 | |||
302 | aux = old = parent; | ||
303 | while (aux != tree->me) | ||
304 | { | ||
305 | #if CADET_TREE_DEBUG | ||
306 | GNUNET_PEER_resolve (aux->peer, &id); | ||
307 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: ... checking %s.\n", | ||
308 | GNUNET_i2s (&id)); | ||
309 | #endif | ||
310 | old = aux; | ||
311 | aux = aux->parent; | ||
312 | GNUNET_assert (NULL != aux); | ||
313 | } | ||
314 | #if CADET_TREE_DEBUG | ||
315 | GNUNET_PEER_resolve (old->peer, &id); | ||
316 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: It's %s!\n", | ||
317 | GNUNET_i2s (&id)); | ||
318 | #endif | ||
319 | hop = π | ||
320 | GNUNET_PEER_resolve (old->peer, hop); | ||
321 | } | ||
322 | GNUNET_PEER_resolve (parent->peer, &id); | ||
323 | copy = GNUNET_CONTAINER_multihashmap_get (tree->first_hops, &id.hashPubKey); | ||
324 | if (NULL == copy) | ||
325 | copy = GNUNET_new (struct GNUNET_PeerIdentity); | ||
326 | *copy = *hop; | ||
327 | |||
328 | (void) GNUNET_CONTAINER_multihashmap_put (tree->first_hops, &id.hashPubKey, | ||
329 | copy, | ||
330 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE); | ||
331 | |||
332 | for (n = parent->children_head; NULL != n; n = n->next) | ||
333 | { | ||
334 | tree_node_update_first_hops (tree, n, hop); | ||
335 | } | ||
336 | } | ||
337 | |||
338 | |||
339 | static void | ||
340 | tree_node_debug (struct CadetTunnelTreeNode *n, uint16_t level) | ||
341 | { | ||
342 | struct CadetTunnelTreeNode *c; | ||
343 | struct GNUNET_PeerIdentity id;; | ||
344 | uint16_t i; | ||
345 | |||
346 | for (i = 0; i < level; i++) | ||
347 | FPRINTF (stderr, "%s", " "); | ||
348 | if (n->status == CADET_PEER_READY) | ||
349 | FPRINTF (stderr, "%s", "#"); | ||
350 | if (n->status == CADET_PEER_SEARCHING) | ||
351 | FPRINTF (stderr, "%s", "+"); | ||
352 | if (n->status == CADET_PEER_RELAY) | ||
353 | FPRINTF (stderr, "%s", "-"); | ||
354 | if (n->status == CADET_PEER_RECONNECTING) | ||
355 | FPRINTF (stderr, "%s", "*"); | ||
356 | |||
357 | GNUNET_PEER_resolve (n->peer, &id); | ||
358 | FPRINTF (stderr, "%s, [%u, %p] ", GNUNET_i2s (&id), n->peer, n); | ||
359 | if (NULL != n->parent) | ||
360 | { | ||
361 | GNUNET_PEER_resolve (n->parent->peer, &id); | ||
362 | FPRINTF (stderr, "(-> %s [%u])\n", GNUNET_i2s (&id), n->parent->peer); | ||
363 | } | ||
364 | else | ||
365 | FPRINTF (stderr, "%s", "(root)\n"); | ||
366 | for (c = n->children_head; NULL != c; c = c->next) | ||
367 | tree_node_debug (c, level + 1); | ||
368 | } | ||
369 | |||
370 | |||
371 | /** | ||
372 | * Destroys and frees the node and all children | ||
373 | * | ||
374 | * @param parent Parent node to be destroyed | ||
375 | */ | ||
376 | static void | ||
377 | tree_node_destroy (struct CadetTunnelTreeNode *parent) | ||
378 | { | ||
379 | struct CadetTunnelTreeNode *n; | ||
380 | struct CadetTunnelTreeNode *next; | ||
381 | |||
382 | if (NULL == parent) | ||
383 | return; | ||
384 | #if CADET_TREE_DEBUG | ||
385 | struct GNUNET_PeerIdentity id; | ||
386 | |||
387 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Destroying node %u\n", | ||
388 | parent->peer); | ||
389 | GNUNET_PEER_resolve (parent->peer, &id); | ||
390 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: (%s)\n", GNUNET_i2s (&id)); | ||
391 | #endif | ||
392 | n = parent->children_head; | ||
393 | while (NULL != n) | ||
394 | { | ||
395 | next = n->next; | ||
396 | tree_node_destroy (n); | ||
397 | n = next; | ||
398 | } | ||
399 | GNUNET_PEER_change_rc (parent->peer, -1); | ||
400 | if (NULL != parent->parent) | ||
401 | GNUNET_CONTAINER_DLL_remove (parent->parent->children_head, | ||
402 | parent->parent->children_tail, parent); | ||
403 | GNUNET_free (parent); | ||
404 | } | ||
405 | |||
406 | |||
407 | |||
408 | /** | ||
409 | * Create a new tree. | ||
410 | * | ||
411 | * @param peer A short peer id of the root of the tree. | ||
412 | * | ||
413 | * @return A newly allocated and initialized tunnel tree. | ||
414 | */ | ||
415 | struct CadetTunnelTree * | ||
416 | tree_new (GNUNET_PEER_Id peer) | ||
417 | { | ||
418 | struct CadetTunnelTree *tree; | ||
419 | |||
420 | tree = GNUNET_new (struct CadetTunnelTree); | ||
421 | tree->first_hops = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); | ||
422 | tree->root = tree_node_new (NULL, peer); | ||
423 | tree->root->status = CADET_PEER_ROOT; | ||
424 | |||
425 | if (1 == peer) | ||
426 | { | ||
427 | tree->me = tree->root; | ||
428 | } | ||
429 | |||
430 | return tree; | ||
431 | } | ||
432 | |||
433 | |||
434 | /** | ||
435 | * Set the status of a node. | ||
436 | * | ||
437 | * @param tree Tree. | ||
438 | * @param peer A short peer id of the node. | ||
439 | * @param status New status to set. | ||
440 | */ | ||
441 | void | ||
442 | tree_set_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer, | ||
443 | enum CadetPeerState status) | ||
444 | { | ||
445 | struct CadetTunnelTreeNode *n; | ||
446 | |||
447 | n = tree_find_peer (tree, peer); | ||
448 | if (NULL == n) | ||
449 | return; | ||
450 | n->status = status; | ||
451 | } | ||
452 | |||
453 | |||
454 | /** | ||
455 | * Get the status of a node. | ||
456 | * | ||
457 | * @param tree Tree whose node's status we want to now. | ||
458 | * @param peer A short peer id of the node. | ||
459 | * | ||
460 | * @return Status of the peer. | ||
461 | */ | ||
462 | enum CadetPeerState | ||
463 | tree_get_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer) | ||
464 | { | ||
465 | struct CadetTunnelTreeNode *n; | ||
466 | |||
467 | n = tree_find_peer (tree, peer); | ||
468 | if (NULL == n) | ||
469 | return CADET_PEER_INVALID; | ||
470 | return n->status; | ||
471 | } | ||
472 | |||
473 | |||
474 | /** | ||
475 | * Get the id of the predecessor of the local node. | ||
476 | * | ||
477 | * @param tree Tree whose local id we want to now. | ||
478 | * | ||
479 | * @return Short peer id of local peer. | ||
480 | */ | ||
481 | GNUNET_PEER_Id | ||
482 | tree_get_predecessor (struct CadetTunnelTree *tree) | ||
483 | { | ||
484 | if (NULL != tree->me && NULL != tree->me->parent) | ||
485 | return tree->me->parent->peer; | ||
486 | else | ||
487 | return (GNUNET_PEER_Id) 0; | ||
488 | } | ||
489 | |||
490 | |||
491 | /** | ||
492 | * Find the first peer whom to send a packet to go down this path | ||
493 | * | ||
494 | * @param t The tunnel tree to use | ||
495 | * @param peer The peerinfo of the peer we are trying to reach | ||
496 | * | ||
497 | * @return peerinfo of the peer who is the first hop in the tunnel | ||
498 | * NULL on error | ||
499 | * | ||
500 | * FIXME use PEER_Id | ||
501 | */ | ||
502 | struct GNUNET_PeerIdentity * | ||
503 | tree_get_first_hop (struct CadetTunnelTree *t, GNUNET_PEER_Id peer) | ||
504 | { | ||
505 | struct GNUNET_PeerIdentity id; | ||
506 | struct GNUNET_PeerIdentity *r; | ||
507 | |||
508 | GNUNET_PEER_resolve (peer, &id); | ||
509 | r = GNUNET_CONTAINER_multihashmap_get (t->first_hops, &id.hashPubKey); | ||
510 | if (NULL == r) | ||
511 | { | ||
512 | struct CadetTunnelTreeNode *n; | ||
513 | |||
514 | n = tree_find_peer (t, peer); | ||
515 | if (NULL != t->me && NULL != n) | ||
516 | { | ||
517 | tree_node_update_first_hops (t, n, NULL); | ||
518 | r = GNUNET_CONTAINER_multihashmap_get (t->first_hops, &id.hashPubKey); | ||
519 | GNUNET_assert (NULL != r); | ||
520 | } | ||
521 | else | ||
522 | { | ||
523 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
524 | "Tree structure inconsistent! me: %p, n: %p", t->me, n); | ||
525 | GNUNET_break (0); | ||
526 | } | ||
527 | } | ||
528 | |||
529 | return r; | ||
530 | } | ||
531 | |||
532 | |||
533 | /** | ||
534 | * Find the given peer in the tree. | ||
535 | * | ||
536 | * @param tree Tree where to look for the peer. | ||
537 | * @param peer_id Short ID of the peer to find. | ||
538 | * | ||
539 | * @return Pointer to the node of the peer. NULL if not found. | ||
540 | */ | ||
541 | struct CadetTunnelTreeNode * | ||
542 | tree_find_peer (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer_id) | ||
543 | { | ||
544 | return tree_node_find_peer (tree->root, peer_id); | ||
545 | } | ||
546 | |||
547 | |||
548 | /** | ||
549 | * Recusively mark peer and children as disconnected, notify client | ||
550 | * | ||
551 | * @param tree Tree this node belongs to | ||
552 | * @param parent Node to be clean, potentially with children | ||
553 | * @param cb Callback to use to notify about disconnected peers. | ||
554 | * @param cbcls Closure for cb. | ||
555 | */ | ||
556 | static void | ||
557 | tree_mark_peers_disconnected (struct CadetTunnelTree *tree, | ||
558 | struct CadetTunnelTreeNode *parent, | ||
559 | CadetTreeCallback cb, void *cbcls) | ||
560 | { | ||
561 | struct GNUNET_PeerIdentity *pi; | ||
562 | struct GNUNET_PeerIdentity id; | ||
563 | struct CadetTunnelTreeNode *n; | ||
564 | |||
565 | for (n = parent->children_head; NULL != n; n = n->next) | ||
566 | { | ||
567 | tree_mark_peers_disconnected (tree, n, cb, cbcls); | ||
568 | } | ||
569 | if (CADET_PEER_READY == parent->status) | ||
570 | { | ||
571 | if (NULL != cb) | ||
572 | cb (cbcls, parent->peer); | ||
573 | parent->status = CADET_PEER_RECONNECTING; | ||
574 | } | ||
575 | |||
576 | /* Remove and free info about first hop */ | ||
577 | GNUNET_PEER_resolve (parent->peer, &id); | ||
578 | pi = GNUNET_CONTAINER_multihashmap_get (tree->first_hops, &id.hashPubKey); | ||
579 | GNUNET_CONTAINER_multihashmap_remove_all (tree->first_hops, &id.hashPubKey); | ||
580 | if (NULL != pi) | ||
581 | GNUNET_free (pi); | ||
582 | } | ||
583 | |||
584 | |||
585 | /** | ||
586 | * Iterate over all children of the local node. | ||
587 | * | ||
588 | * @param tree Tree to use. Must have "me" set. | ||
589 | * @param cb Callback to call over each child. | ||
590 | * @param cb_cls Closure for @c cb. | ||
591 | */ | ||
592 | void | ||
593 | tree_iterate_children (struct CadetTunnelTree *tree, CadetTreeCallback cb, | ||
594 | void *cb_cls) | ||
595 | { | ||
596 | struct CadetTunnelTreeNode *n; | ||
597 | |||
598 | if (NULL == tree->me) | ||
599 | return; | ||
600 | for (n = tree->me->children_head; NULL != n; n = n->next) | ||
601 | { | ||
602 | cb (cb_cls, n->peer); | ||
603 | } | ||
604 | } | ||
605 | |||
606 | |||
607 | /** | ||
608 | * Struct to contain a list of pending nodes when iterating a tree. | ||
609 | */ | ||
610 | struct CadetTreePendingNode { | ||
611 | |||
612 | /** | ||
613 | * DLL next. | ||
614 | */ | ||
615 | struct CadetTreePendingNode *next; | ||
616 | |||
617 | /** | ||
618 | * DLL prev. | ||
619 | */ | ||
620 | struct CadetTreePendingNode *prev; | ||
621 | |||
622 | /** | ||
623 | * Pending node. | ||
624 | */ | ||
625 | struct CadetTunnelTreeNode *node; | ||
626 | }; | ||
627 | |||
628 | |||
629 | /** | ||
630 | * Iterate over all nodes in the tree. | ||
631 | * | ||
632 | * @param tree Tree to use.. | ||
633 | * @param cb Callback to call over each child. | ||
634 | * @param cb_cls Closure for @c cb. | ||
635 | * | ||
636 | * TODO: recursive implementation? (s/heap/stack/g) | ||
637 | */ | ||
638 | void | ||
639 | tree_iterate_all (struct CadetTunnelTree *tree, | ||
640 | CadetWholeTreeCallback cb, | ||
641 | void *cb_cls) | ||
642 | { | ||
643 | struct CadetTunnelTreeNode *parent; | ||
644 | struct CadetTunnelTreeNode *n; | ||
645 | struct CadetTreePendingNode *head; | ||
646 | struct CadetTreePendingNode *tail; | ||
647 | struct CadetTreePendingNode *pending; | ||
648 | |||
649 | cb (cb_cls, tree->root->peer, 0); | ||
650 | pending = GNUNET_new (struct CadetTreePendingNode); | ||
651 | pending->node = tree->root; | ||
652 | head = tail = NULL; | ||
653 | GNUNET_CONTAINER_DLL_insert (head, tail, pending); | ||
654 | |||
655 | while (NULL != head) | ||
656 | { | ||
657 | pending = head; | ||
658 | parent = pending->node; | ||
659 | GNUNET_CONTAINER_DLL_remove (head, tail, pending); | ||
660 | GNUNET_free (pending); | ||
661 | for (n = parent->children_head; NULL != n; n = n->next) | ||
662 | { | ||
663 | cb (cb_cls, n->peer, parent->peer); | ||
664 | pending = GNUNET_new (struct CadetTreePendingNode); | ||
665 | pending->node = n; | ||
666 | /* Insert_tail: breadth first, Insert: depth first */ | ||
667 | GNUNET_CONTAINER_DLL_insert (head, tail, pending); | ||
668 | } | ||
669 | } | ||
670 | } | ||
671 | |||
672 | |||
673 | /** | ||
674 | * Iterator to count the children in a tree. | ||
675 | */ | ||
676 | static void | ||
677 | count_children_cb (void *cls, GNUNET_PEER_Id peer) | ||
678 | { | ||
679 | unsigned int *i = cls; | ||
680 | |||
681 | (*i)++; | ||
682 | } | ||
683 | |||
684 | |||
685 | /** | ||
686 | * Count how many children does the local node have in the tree. | ||
687 | * | ||
688 | * @param tree Tree to use. Must have "me" set. | ||
689 | */ | ||
690 | unsigned int | ||
691 | tree_count_children (struct CadetTunnelTree *tree) | ||
692 | { | ||
693 | unsigned int i; | ||
694 | |||
695 | i = 0; | ||
696 | tree_iterate_children(tree, &count_children_cb, &i); | ||
697 | return i; | ||
698 | } | ||
699 | |||
700 | |||
701 | /** | ||
702 | * Recusively update the info about what is the first hop to reach the node | ||
703 | * | ||
704 | * @param tree Tree this nodes belongs to. | ||
705 | * @param parent_id Short ID from node form which to start updating. | ||
706 | * @param hop If known, ID of the first hop. | ||
707 | * If not known, NULL to find out and pass on children. | ||
708 | */ | ||
709 | void | ||
710 | tree_update_first_hops (struct CadetTunnelTree *tree, GNUNET_PEER_Id parent_id, | ||
711 | struct GNUNET_PeerIdentity *hop) | ||
712 | { | ||
713 | tree_node_update_first_hops (tree, tree_find_peer (tree, parent_id), hop); | ||
714 | } | ||
715 | |||
716 | |||
717 | /** | ||
718 | * Delete the current path to the peer, including all now unused relays. | ||
719 | * The destination peer is NOT destroyed, it is returned in order to either set | ||
720 | * a new path to it or destroy it explicitly, taking care of it's child nodes. | ||
721 | * | ||
722 | * @param t Tunnel tree where to delete the path from. | ||
723 | * @param peer_id Short ID of the destination peer whose path we want to remove. | ||
724 | * @param cb Callback to use to notify about disconnected peers. | ||
725 | * @param cbcls Closure for cb. | ||
726 | * | ||
727 | * @return pointer to the pathless node. | ||
728 | * NULL when not found | ||
729 | */ | ||
730 | struct CadetTunnelTreeNode * | ||
731 | tree_del_path (struct CadetTunnelTree *t, GNUNET_PEER_Id peer_id, | ||
732 | CadetTreeCallback cb, void *cbcls) | ||
733 | { | ||
734 | struct CadetTunnelTreeNode *parent; | ||
735 | struct CadetTunnelTreeNode *node; | ||
736 | struct CadetTunnelTreeNode *n; | ||
737 | |||
738 | #if CADET_TREE_DEBUG | ||
739 | struct GNUNET_PeerIdentity id; | ||
740 | |||
741 | GNUNET_PEER_resolve (peer_id, &id); | ||
742 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Deleting path to %s.\n", | ||
743 | GNUNET_i2s (&id)); | ||
744 | #endif | ||
745 | if (NULL == t->root || peer_id == t->root->peer) | ||
746 | return NULL; | ||
747 | |||
748 | for (n = t->disconnected_head; NULL != n; n = n->next) | ||
749 | { | ||
750 | if (n->peer == peer_id) | ||
751 | { | ||
752 | /* Was already pathless, waiting for reconnection */ | ||
753 | GNUNET_CONTAINER_DLL_remove (t->disconnected_head, t->disconnected_tail, | ||
754 | n); | ||
755 | return n; | ||
756 | } | ||
757 | } | ||
758 | n = tree_find_peer (t, peer_id); | ||
759 | if (NULL == n) | ||
760 | return NULL; | ||
761 | node = n; | ||
762 | |||
763 | parent = n->parent; | ||
764 | GNUNET_CONTAINER_DLL_remove (parent->children_head, parent->children_tail, n); | ||
765 | n->parent = NULL; | ||
766 | |||
767 | while (CADET_PEER_RELAY == parent->status && | ||
768 | NULL == parent->children_head) | ||
769 | { | ||
770 | #if CADET_TREE_DEBUG | ||
771 | GNUNET_PEER_resolve (parent->peer, &id); | ||
772 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Deleting node %s.\n", | ||
773 | GNUNET_i2s (&id)); | ||
774 | #endif | ||
775 | n = parent->parent; | ||
776 | if (parent == t->me) | ||
777 | t->me = NULL; | ||
778 | tree_node_destroy (parent); | ||
779 | parent = n; | ||
780 | } | ||
781 | #if CADET_TREE_DEBUG | ||
782 | GNUNET_PEER_resolve (parent->peer, &id); | ||
783 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Not deleted peer %s.\n", | ||
784 | GNUNET_i2s (&id)); | ||
785 | #endif | ||
786 | |||
787 | tree_mark_peers_disconnected (t, node, cb, cbcls); | ||
788 | |||
789 | return node; | ||
790 | } | ||
791 | |||
792 | |||
793 | /** | ||
794 | * Return a newly allocated individual path to reach a peer from the local peer, | ||
795 | * according to the path tree of some tunnel. | ||
796 | * | ||
797 | * @param t Tunnel from which to read the path tree. | ||
798 | * @param peer Short ID of the destination peer to whom we want a path. | ||
799 | * | ||
800 | * @return A newly allocated individual path to reach the destination peer. | ||
801 | * Path must be destroyed afterwards. | ||
802 | */ | ||
803 | struct CadetPeerPath * | ||
804 | tree_get_path_to_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer) | ||
805 | { | ||
806 | struct CadetTunnelTreeNode *n; | ||
807 | struct CadetPeerPath *p; | ||
808 | |||
809 | n = tree_find_peer (t, peer); | ||
810 | if (NULL == n) | ||
811 | { | ||
812 | GNUNET_break (0); | ||
813 | return NULL; | ||
814 | } | ||
815 | p = path_new (0); | ||
816 | |||
817 | /* Building the path (inverted!) */ | ||
818 | while (n->peer != 1) | ||
819 | { | ||
820 | GNUNET_array_append (p->peers, p->length, n->peer); | ||
821 | GNUNET_PEER_change_rc (n->peer, 1); | ||
822 | n = n->parent; | ||
823 | if (NULL == n) | ||
824 | { | ||
825 | GNUNET_break (0); | ||
826 | path_destroy (p); | ||
827 | return NULL; | ||
828 | } | ||
829 | } | ||
830 | GNUNET_array_append (p->peers, p->length, 1); | ||
831 | GNUNET_PEER_change_rc (1, 1); | ||
832 | |||
833 | path_invert (p); | ||
834 | |||
835 | return p; | ||
836 | } | ||
837 | |||
838 | |||
839 | |||
840 | /** | ||
841 | * Integrate a stand alone path into the tunnel tree. | ||
842 | * If the peer toward which the new path is already in the tree, the peer | ||
843 | * and its children will be maked as disconnected and the callback | ||
844 | * will be called on each one of them. They will be maked as online only after | ||
845 | * receiving a PATH ACK for the new path for each one of them, so the caller | ||
846 | * should take care of sending a new CREATE PATH message for each disconnected | ||
847 | * peer. | ||
848 | * | ||
849 | * @param t Tunnel where to add the new path. | ||
850 | * @param p Path to be integrated. | ||
851 | * @param cb Callback to use to notify about peers temporarily disconnecting. | ||
852 | * @param cbcls Closure for cb. | ||
853 | * | ||
854 | * @return GNUNET_OK in case of success. | ||
855 | * GNUNET_SYSERR in case of error. | ||
856 | * | ||
857 | * TODO: optimize | ||
858 | * - go backwards on path looking for each peer in the present tree | ||
859 | * - do not disconnect peers until new path is created & connected | ||
860 | */ | ||
861 | int | ||
862 | tree_add_path (struct CadetTunnelTree *t, const struct CadetPeerPath *p, | ||
863 | CadetTreeCallback cb, void *cbcls) | ||
864 | { | ||
865 | struct CadetTunnelTreeNode *parent; | ||
866 | struct CadetTunnelTreeNode *oldnode; | ||
867 | struct CadetTunnelTreeNode *n; | ||
868 | struct CadetTunnelTreeNode *c; | ||
869 | struct GNUNET_PeerIdentity id; | ||
870 | int me; | ||
871 | unsigned int i; | ||
872 | |||
873 | #if CADET_TREE_DEBUG | ||
874 | GNUNET_PEER_resolve (p->peers[p->length - 1], &id); | ||
875 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
876 | "tree: Adding path [%u] towards peer %s.\n", p->length, | ||
877 | GNUNET_i2s (&id)); | ||
878 | #endif | ||
879 | |||
880 | GNUNET_assert (0 != p->length); | ||
881 | parent = n = t->root; | ||
882 | if (n->peer != p->peers[0]) | ||
883 | { | ||
884 | GNUNET_break (0); | ||
885 | return GNUNET_SYSERR; | ||
886 | } | ||
887 | if (1 == p->length) | ||
888 | return GNUNET_OK; | ||
889 | oldnode = tree_del_path (t, p->peers[p->length - 1], cb, cbcls); | ||
890 | /* Look for the first node that is not already present in the tree | ||
891 | * | ||
892 | * Assuming that the tree is somewhat balanced, O(log n * log N). | ||
893 | * - Length of the path is expected to be log N (size of whole network). | ||
894 | * - Each level of the tree is expected to have log n children (size of tree). | ||
895 | */ | ||
896 | me = t->root->peer == 1 ? 0 : -1; | ||
897 | for (i = 1; i < p->length; i++) | ||
898 | { | ||
899 | #if CADET_TREE_DEBUG | ||
900 | GNUNET_PEER_resolve (p->peers[i], &id); | ||
901 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Looking for peer %s.\n", | ||
902 | GNUNET_i2s (&id)); | ||
903 | #endif | ||
904 | parent = n; | ||
905 | if (p->peers[i] == 1) | ||
906 | me = i; | ||
907 | for (c = n->children_head; NULL != c; c = c->next) | ||
908 | { | ||
909 | if (c->peer == p->peers[i]) | ||
910 | { | ||
911 | #if CADET_TREE_DEBUG | ||
912 | GNUNET_PEER_resolve (parent->peer, &id); | ||
913 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
914 | "tree: Found in children of %s.\n", GNUNET_i2s (&id)); | ||
915 | #endif | ||
916 | n = c; | ||
917 | break; | ||
918 | } | ||
919 | } | ||
920 | /* If we couldn't find a child equal to path[i], we have reached the end | ||
921 | * of the common path. */ | ||
922 | if (parent == n) | ||
923 | break; | ||
924 | } | ||
925 | #if CADET_TREE_DEBUG | ||
926 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: All childen visited.\n"); | ||
927 | #endif | ||
928 | /* Add the rest of the path as a branch from parent. */ | ||
929 | while (i < p->length) | ||
930 | { | ||
931 | #if CADET_TREE_DEBUG | ||
932 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Adding peer %u to %u.\n", | ||
933 | p->peers[i], parent->peer); | ||
934 | GNUNET_PEER_resolve (p->peers[i], &id); | ||
935 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Adding peer %s.\n", | ||
936 | GNUNET_i2s (&id)); | ||
937 | GNUNET_PEER_resolve (parent->peer, &id); | ||
938 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: to %s.\n", | ||
939 | GNUNET_i2s (&id)); | ||
940 | #endif | ||
941 | |||
942 | if (i == p->length - 1 && NULL != oldnode) | ||
943 | { | ||
944 | #if CADET_TREE_DEBUG | ||
945 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
946 | "tree: Putting old node into place.\n"); | ||
947 | #endif | ||
948 | oldnode->parent = parent; | ||
949 | GNUNET_CONTAINER_DLL_insert (parent->children_head, parent->children_tail, | ||
950 | oldnode); | ||
951 | tree_node_update_first_hops (t, oldnode, NULL); | ||
952 | n = oldnode; | ||
953 | } | ||
954 | else | ||
955 | { | ||
956 | #if CADET_TREE_DEBUG | ||
957 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Creating new node.\n"); | ||
958 | #endif | ||
959 | n = tree_node_new (parent, p->peers[i]); | ||
960 | n->status = CADET_PEER_RELAY; | ||
961 | } | ||
962 | if (n->peer == 1) | ||
963 | { | ||
964 | t->me = n; | ||
965 | me = i; | ||
966 | } | ||
967 | i++; | ||
968 | parent = n; | ||
969 | } | ||
970 | n->status = CADET_PEER_SEARCHING; | ||
971 | |||
972 | GNUNET_break (-1 != me); | ||
973 | |||
974 | /* Add info about first hop into hashmap. */ | ||
975 | if (-1 != me && me < p->length - 1) | ||
976 | { | ||
977 | #if CADET_TREE_DEBUG | ||
978 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
979 | "CADET: finding first hop (own pos %d/%u)\n", me, | ||
980 | p->length - 1); | ||
981 | #endif | ||
982 | GNUNET_PEER_resolve (p->peers[me + 1], &id); | ||
983 | tree_update_first_hops (t, p->peers[me + 1], &id); | ||
984 | } | ||
985 | #if CADET_TREE_DEBUG | ||
986 | else | ||
987 | { | ||
988 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
989 | "CADET: was last in path, not updating first hops (%d/%u)\n", | ||
990 | me, p->length - 1); | ||
991 | } | ||
992 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: New node added.\n"); | ||
993 | #endif | ||
994 | if (NULL == t->me) | ||
995 | t->me = tree_find_peer (t, 1); | ||
996 | return GNUNET_OK; | ||
997 | } | ||
998 | |||
999 | |||
1000 | /** | ||
1001 | * Notifies a tree that a connection it might be using is broken. | ||
1002 | * Marks all peers down the paths as disconnected and notifies the client. | ||
1003 | * | ||
1004 | * @param t Tree to use. | ||
1005 | * @param p1 Short id of one of the peers (order unimportant) | ||
1006 | * @param p2 Short id of one of the peers (order unimportant) | ||
1007 | * @param cb Function to call for every peer that is marked as disconnected. | ||
1008 | * @param cbcls Closure for cb. | ||
1009 | * | ||
1010 | * @return Short ID of the first disconnected peer in the tree. | ||
1011 | */ | ||
1012 | GNUNET_PEER_Id | ||
1013 | tree_notify_connection_broken (struct CadetTunnelTree *t, GNUNET_PEER_Id p1, | ||
1014 | GNUNET_PEER_Id p2, CadetTreeCallback cb, | ||
1015 | void *cbcls) | ||
1016 | { | ||
1017 | struct CadetTunnelTreeNode *n; | ||
1018 | struct CadetTunnelTreeNode *c; | ||
1019 | |||
1020 | n = tree_find_peer (t, p1); | ||
1021 | if (NULL == n) | ||
1022 | return 0; | ||
1023 | if (NULL != n->parent && n->parent->peer == p2) | ||
1024 | { | ||
1025 | tree_mark_peers_disconnected (t, n, cb, cbcls); | ||
1026 | GNUNET_CONTAINER_DLL_remove (n->parent->children_head, | ||
1027 | n->parent->children_tail, n); | ||
1028 | GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail, n); | ||
1029 | return p1; | ||
1030 | } | ||
1031 | for (c = n->children_head; NULL != c; c = c->next) | ||
1032 | { | ||
1033 | if (c->peer == p2) | ||
1034 | { | ||
1035 | tree_mark_peers_disconnected (t, c, cb, cbcls); | ||
1036 | GNUNET_CONTAINER_DLL_remove (n->children_head, n->children_tail, c); | ||
1037 | GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail, | ||
1038 | c); | ||
1039 | return p2; | ||
1040 | } | ||
1041 | } | ||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | |||
1046 | /** | ||
1047 | * Deletes a peer from a tunnel, liberating all unused resources on the path to | ||
1048 | * it. It shouldn't have children, if it has they will be destroyed as well. | ||
1049 | * If the tree is not local and no longer has any paths, the root node will be | ||
1050 | * destroyed and marked as NULL. | ||
1051 | * | ||
1052 | * @param t Tunnel tree to use. | ||
1053 | * @param peer Short ID of the peer to remove from the tunnel tree. | ||
1054 | * @param cb Callback to notify client of disconnected peers. | ||
1055 | * @param cbcls Closure for cb. | ||
1056 | * | ||
1057 | * @return GNUNET_OK or GNUNET_SYSERR | ||
1058 | */ | ||
1059 | int | ||
1060 | tree_del_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer, | ||
1061 | CadetTreeCallback cb, void *cbcls) | ||
1062 | { | ||
1063 | struct CadetTunnelTreeNode *n; | ||
1064 | |||
1065 | n = tree_del_path (t, peer, cb, cbcls); | ||
1066 | if (NULL == n) | ||
1067 | { | ||
1068 | GNUNET_break (0); | ||
1069 | return GNUNET_YES; | ||
1070 | } | ||
1071 | tree_node_destroy (n); | ||
1072 | if (NULL == t->root->children_head && t->me != t->root) | ||
1073 | { | ||
1074 | tree_node_destroy (t->root); | ||
1075 | t->root = NULL; | ||
1076 | return GNUNET_NO; | ||
1077 | } | ||
1078 | return GNUNET_YES; | ||
1079 | } | ||
1080 | |||
1081 | |||
1082 | |||
1083 | /** | ||
1084 | * Get the cost of the path relative to the already built tunnel tree. | ||
1085 | * | ||
1086 | * @param t The tunnel tree to which compare. | ||
1087 | * @param path The individual path to reach a peer. It has to start at the | ||
1088 | * root of the tree to be comparable. | ||
1089 | * | ||
1090 | * @return Number of hops to reach destination, UINT_MAX in case the peer is not | ||
1091 | * in the path. | ||
1092 | * | ||
1093 | * TODO: adapt to allow any start / root combination | ||
1094 | * TODO: take in account state of the nodes | ||
1095 | */ | ||
1096 | unsigned int | ||
1097 | tree_get_path_cost (struct CadetTunnelTree *t, struct CadetPeerPath *path) | ||
1098 | { | ||
1099 | struct CadetTunnelTreeNode *n; | ||
1100 | struct CadetTunnelTreeNode *p; | ||
1101 | unsigned int i; | ||
1102 | unsigned int l; | ||
1103 | |||
1104 | l = path_get_length (path); | ||
1105 | p = t->root; | ||
1106 | if (t->root->peer != path->peers[0]) | ||
1107 | { | ||
1108 | GNUNET_break (0); | ||
1109 | return UINT_MAX; | ||
1110 | } | ||
1111 | for (i = 1; i < l; i++) | ||
1112 | { | ||
1113 | for (n = p->children_head; NULL != n; n = n->next) | ||
1114 | { | ||
1115 | if (path->peers[i] == n->peer) | ||
1116 | { | ||
1117 | break; | ||
1118 | } | ||
1119 | } | ||
1120 | if (NULL == n) | ||
1121 | return l - i; | ||
1122 | p = n; | ||
1123 | } | ||
1124 | return l - i; | ||
1125 | } | ||
1126 | |||
1127 | |||
1128 | /** | ||
1129 | * Print the tree on stderr | ||
1130 | * | ||
1131 | * @param t The tree | ||
1132 | */ | ||
1133 | void | ||
1134 | tree_debug (struct CadetTunnelTree *t) | ||
1135 | { | ||
1136 | tree_node_debug (t->root, 0); | ||
1137 | FPRINTF (stderr, "root: %p\n", t->root); | ||
1138 | FPRINTF (stderr, "me: %p\n", t->me); | ||
1139 | } | ||
1140 | |||
1141 | |||
1142 | /** | ||
1143 | * Iterator over hash map peer entries and frees all data in it. | ||
1144 | * Used prior to destroying a hashmap. Makes you miss anonymous functions in C. | ||
1145 | * | ||
1146 | * @param cls closure | ||
1147 | * @param key current key code (will no longer contain valid data!!) | ||
1148 | * @param value value in the hash map (treated as void *) | ||
1149 | * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not. | ||
1150 | */ | ||
1151 | static int | ||
1152 | iterate_free (void *cls, const struct GNUNET_HashCode * key, void *value) | ||
1153 | { | ||
1154 | GNUNET_free (value); | ||
1155 | return GNUNET_YES; | ||
1156 | } | ||
1157 | |||
1158 | |||
1159 | /** | ||
1160 | * Destroy the whole tree and free all used memory and Peer_Ids | ||
1161 | * | ||
1162 | * @param t Tree to be destroyed | ||
1163 | */ | ||
1164 | void | ||
1165 | tree_destroy (struct CadetTunnelTree *t) | ||
1166 | { | ||
1167 | #if CADET_TREE_DEBUG | ||
1168 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Destroying tree\n"); | ||
1169 | #endif | ||
1170 | tree_node_destroy (t->root); | ||
1171 | GNUNET_CONTAINER_multihashmap_iterate (t->first_hops, &iterate_free, NULL); | ||
1172 | GNUNET_CONTAINER_multihashmap_destroy (t->first_hops); | ||
1173 | GNUNET_free (t); | ||
1174 | } | ||
diff --git a/src/cadet/cadet_tunnel_tree.h b/src/cadet/cadet_tunnel_tree.h new file mode 100644 index 000000000..779d330e7 --- /dev/null +++ b/src/cadet/cadet_tunnel_tree.h | |||
@@ -0,0 +1,382 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2001 - 2011 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/cadet_tunnel_tree.h | ||
23 | * @brief Tunnel tree handling functions | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "cadet.h" | ||
28 | |||
29 | /******************************************************************************/ | ||
30 | /************************ DATA STRUCTURES ****************************/ | ||
31 | /******************************************************************************/ | ||
32 | |||
33 | /** | ||
34 | * Information regarding a possible path to reach a single peer | ||
35 | */ | ||
36 | struct CadetPeerPath | ||
37 | { | ||
38 | |||
39 | /** | ||
40 | * Linked list | ||
41 | */ | ||
42 | struct CadetPeerPath *next; | ||
43 | struct CadetPeerPath *prev; | ||
44 | |||
45 | /** | ||
46 | * List of all the peers that form the path from origin to target. | ||
47 | */ | ||
48 | GNUNET_PEER_Id *peers; | ||
49 | |||
50 | /** | ||
51 | * Number of peers (hops) in the path | ||
52 | */ | ||
53 | unsigned int length; | ||
54 | |||
55 | }; | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Node of path tree for a tunnel | ||
60 | */ | ||
61 | struct CadetTunnelTreeNode; | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Tree to reach all peers in the tunnel | ||
66 | */ | ||
67 | struct CadetTunnelTree; | ||
68 | |||
69 | |||
70 | /******************************************************************************/ | ||
71 | /************************* FUNCTIONS *****************************/ | ||
72 | /******************************************************************************/ | ||
73 | |||
74 | /** | ||
75 | * Create a new path. | ||
76 | * | ||
77 | * @param length How many hops will the path have. | ||
78 | * | ||
79 | * @return A newly allocated path with a peer array of the specified length. | ||
80 | */ | ||
81 | struct CadetPeerPath * | ||
82 | path_new (unsigned int length); | ||
83 | |||
84 | |||
85 | /** | ||
86 | * Invert the path. | ||
87 | * | ||
88 | * @param path The path to invert. | ||
89 | */ | ||
90 | void | ||
91 | path_invert (struct CadetPeerPath *path); | ||
92 | |||
93 | |||
94 | /** | ||
95 | * Duplicate a path, incrementing short peer's rc. | ||
96 | * | ||
97 | * @param path The path to duplicate. | ||
98 | */ | ||
99 | struct CadetPeerPath * | ||
100 | path_duplicate (struct CadetPeerPath *path); | ||
101 | |||
102 | |||
103 | /** | ||
104 | * Get the length of a path. | ||
105 | * | ||
106 | * @param path The path to measure, with the local peer at any point of it. | ||
107 | * | ||
108 | * @return Number of hops to reach destination. | ||
109 | * UINT_MAX in case the peer is not in the path. | ||
110 | */ | ||
111 | unsigned int | ||
112 | path_get_length (struct CadetPeerPath *path); | ||
113 | |||
114 | |||
115 | /** | ||
116 | * Destroy the path and free any allocated resources linked to it | ||
117 | * | ||
118 | * @param p the path to destroy | ||
119 | * | ||
120 | * @return GNUNET_OK on success | ||
121 | */ | ||
122 | int | ||
123 | path_destroy (struct CadetPeerPath *p); | ||
124 | |||
125 | |||
126 | /******************************************************************************/ | ||
127 | |||
128 | /** | ||
129 | * Iterator over all children of a node. | ||
130 | * | ||
131 | * @param cls Closure. | ||
132 | * @param peer_id Short ID of the peer. | ||
133 | */ | ||
134 | typedef void (*CadetTreeCallback) (void *cls, GNUNET_PEER_Id peer_id); | ||
135 | |||
136 | |||
137 | /** | ||
138 | * Iterator over all nodes in a tree. | ||
139 | * | ||
140 | * @param cls Closure. | ||
141 | * @param peer_id Short ID of the peer. | ||
142 | * @param peer_id Short ID of the parent of the peer. | ||
143 | */ | ||
144 | typedef void (*CadetWholeTreeCallback) (void *cls, | ||
145 | GNUNET_PEER_Id peer_id, | ||
146 | GNUNET_PEER_Id parent_id); | ||
147 | |||
148 | /** | ||
149 | * Create a new tunnel tree associated to a tunnel | ||
150 | * | ||
151 | * @param peer A short peer id of the root of the tree | ||
152 | * | ||
153 | * @return A newly allocated and initialized tunnel tree | ||
154 | */ | ||
155 | struct CadetTunnelTree * | ||
156 | tree_new (GNUNET_PEER_Id peer); | ||
157 | |||
158 | |||
159 | /** | ||
160 | * Set the status of a node. | ||
161 | * | ||
162 | * @param tree Tree. | ||
163 | * @param peer A short peer id of the node. | ||
164 | * @param status New status to set. | ||
165 | */ | ||
166 | void | ||
167 | tree_set_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer, | ||
168 | enum CadetPeerState status); | ||
169 | |||
170 | |||
171 | /** | ||
172 | * Get the status of a node. | ||
173 | * | ||
174 | * @param tree Tree whose local id we want to now. | ||
175 | * @param peer A short peer id of the node. | ||
176 | * | ||
177 | * @return Short peer id of local peer. | ||
178 | */ | ||
179 | enum CadetPeerState | ||
180 | tree_get_status (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer); | ||
181 | |||
182 | |||
183 | /** | ||
184 | * Get the id of the predecessor of the local node. | ||
185 | * | ||
186 | * @param tree Tree whose local id we want to now. | ||
187 | * | ||
188 | * @return Short peer id of local peer. | ||
189 | */ | ||
190 | GNUNET_PEER_Id | ||
191 | tree_get_predecessor (struct CadetTunnelTree *tree); | ||
192 | |||
193 | |||
194 | /** | ||
195 | * Find the first peer whom to send a packet to go down this path | ||
196 | * | ||
197 | * @param t The tunnel tree to use | ||
198 | * @param peer The peerinfo of the peer we are trying to reach | ||
199 | * | ||
200 | * @return peerinfo of the peer who is the first hop in the tunnel | ||
201 | * NULL on error | ||
202 | */ | ||
203 | struct GNUNET_PeerIdentity * | ||
204 | tree_get_first_hop (struct CadetTunnelTree *t, GNUNET_PEER_Id peer); | ||
205 | |||
206 | |||
207 | /** | ||
208 | * Find the given peer in the tree. | ||
209 | * | ||
210 | * @param tree Tree where to look for the peer. | ||
211 | * @param peer_id Peer to find. | ||
212 | * | ||
213 | * @return Pointer to the node of the peer. NULL if not found. | ||
214 | */ | ||
215 | struct CadetTunnelTreeNode * | ||
216 | tree_find_peer (struct CadetTunnelTree *tree, GNUNET_PEER_Id peer_id); | ||
217 | |||
218 | |||
219 | /** | ||
220 | * Iterate over all children of the local node. | ||
221 | * | ||
222 | * @param tree Tree to use. Must have "me" set. | ||
223 | * @param cb Callback to call over each child. | ||
224 | * @param cb_cls Closure for @c cb. | ||
225 | */ | ||
226 | void | ||
227 | tree_iterate_children (struct CadetTunnelTree *tree, | ||
228 | CadetTreeCallback cb, | ||
229 | void *cb_cls); | ||
230 | |||
231 | |||
232 | /** | ||
233 | * Iterate over all nodes in the tree. | ||
234 | * | ||
235 | * @param tree Tree to use.. | ||
236 | * @param cb Callback to call over each child. | ||
237 | * @param cb_cls Closure for @c cb. | ||
238 | * | ||
239 | * TODO: recursive implementation? (s/heap/stack/g) | ||
240 | */ | ||
241 | void | ||
242 | tree_iterate_all (struct CadetTunnelTree *tree, | ||
243 | CadetWholeTreeCallback cb, | ||
244 | void *cb_cls); | ||
245 | |||
246 | /** | ||
247 | * Count how many children does the local node have in the tree. | ||
248 | * | ||
249 | * @param tree Tree to use. Must have "me" set. | ||
250 | */ | ||
251 | unsigned int | ||
252 | tree_count_children (struct CadetTunnelTree *tree); | ||
253 | |||
254 | |||
255 | /** | ||
256 | * Recusively update the info about what is the first hop to reach the node | ||
257 | * | ||
258 | * @param tree Tree this nodes belongs to. | ||
259 | * @param parent_id Short ID from node form which to start updating. | ||
260 | * @param hop If known, ID of the first hop. | ||
261 | * If not known, NULL to find out and pass on children. | ||
262 | */ | ||
263 | void | ||
264 | tree_update_first_hops (struct CadetTunnelTree *tree, GNUNET_PEER_Id parent_id, | ||
265 | struct GNUNET_PeerIdentity *hop); | ||
266 | |||
267 | /** | ||
268 | * Delete the current path to the peer, including all now unused relays. | ||
269 | * The destination peer is NOT destroyed, it is returned in order to either set | ||
270 | * a new path to it or destroy it explicitly, taking care of it's child nodes. | ||
271 | * | ||
272 | * @param t Tunnel tree where to delete the path from. | ||
273 | * @param peer_id Short ID of the destination peer whose path we want to remove. | ||
274 | * @param cb Callback to use to notify about which peers are going to be | ||
275 | * disconnected. | ||
276 | * @param cbcls Closure for cb. | ||
277 | * | ||
278 | * @return pointer to the pathless node. | ||
279 | * NULL when not found | ||
280 | */ | ||
281 | struct CadetTunnelTreeNode * | ||
282 | tree_del_path (struct CadetTunnelTree *t, GNUNET_PEER_Id peer_id, | ||
283 | CadetTreeCallback cb, void *cbcls); | ||
284 | |||
285 | |||
286 | /** | ||
287 | * Return a newly allocated individual path to reach a peer from the local peer, | ||
288 | * according to the path tree of some tunnel. | ||
289 | * | ||
290 | * @param t Tunnel from which to read the path tree | ||
291 | * @param peer Destination peer to whom we want a path | ||
292 | * | ||
293 | * @return A newly allocated individual path to reach the destination peer. | ||
294 | * Path must be destroyed afterwards. | ||
295 | */ | ||
296 | struct CadetPeerPath * | ||
297 | tree_get_path_to_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer); | ||
298 | |||
299 | |||
300 | /** | ||
301 | * Integrate a stand alone path into the tunnel tree. | ||
302 | * | ||
303 | * @param t Tunnel where to add the new path. | ||
304 | * @param p Path to be integrated. | ||
305 | * @param cb Callback to use to notify about peers temporarily disconnecting. | ||
306 | * @param cbcls Closure for cb. | ||
307 | * | ||
308 | * @return GNUNET_OK in case of success. | ||
309 | * GNUNET_SYSERR in case of error. | ||
310 | */ | ||
311 | int | ||
312 | tree_add_path (struct CadetTunnelTree *t, const struct CadetPeerPath *p, | ||
313 | CadetTreeCallback cb, void *cbcls); | ||
314 | |||
315 | |||
316 | /** | ||
317 | * Notifies a tree that a connection it might be using is broken. | ||
318 | * Marks all peers down the paths as disconnected and notifies the client. | ||
319 | * | ||
320 | * @param t Tree to use. | ||
321 | * @param p1 Short id of one of the peers (order unimportant) | ||
322 | * @param p2 Short id of one of the peers (order unimportant) | ||
323 | * @param cb Function to call for every peer that is marked as disconnected. | ||
324 | * @param cbcls Closure for cb. | ||
325 | * | ||
326 | * @return Short ID of the first disconnected peer in the tree. | ||
327 | */ | ||
328 | GNUNET_PEER_Id | ||
329 | tree_notify_connection_broken (struct CadetTunnelTree *t, GNUNET_PEER_Id p1, | ||
330 | GNUNET_PEER_Id p2, CadetTreeCallback cb, | ||
331 | void *cbcls); | ||
332 | |||
333 | |||
334 | /** | ||
335 | * Deletes a peer from a tunnel, liberating all unused resources on the path to | ||
336 | * it. It shouldn't have children, if it has they will be destroyed as well. | ||
337 | * If the tree is not local and no longer has any paths, the root node will be | ||
338 | * destroyed and marked as NULL. | ||
339 | * | ||
340 | * FIXME: dont destroy the root | ||
341 | * | ||
342 | * @param t Tunnel tree to use. | ||
343 | * @param peer Short ID of the peer to remove from the tunnel tree. | ||
344 | * @param cb Callback to notify client of disconnected peers. | ||
345 | * @param cbcls Closure for cb. | ||
346 | * | ||
347 | * @return GNUNET_YES if the tunnel still has nodes | ||
348 | */ | ||
349 | int | ||
350 | tree_del_peer (struct CadetTunnelTree *t, GNUNET_PEER_Id peer, | ||
351 | CadetTreeCallback cb, void *cbcls); | ||
352 | |||
353 | |||
354 | /** | ||
355 | * Get the cost of the path relative to the already built tunnel tree | ||
356 | * | ||
357 | * @param t The tunnel tree to which compare | ||
358 | * @param path The individual path to reach a peer | ||
359 | * | ||
360 | * @return Number of hops to reach destination, UINT_MAX in case the peer is not | ||
361 | * in the path | ||
362 | */ | ||
363 | unsigned int | ||
364 | tree_get_path_cost (struct CadetTunnelTree *t, struct CadetPeerPath *path); | ||
365 | |||
366 | |||
367 | /** | ||
368 | * Print the tree on stderr | ||
369 | * | ||
370 | * @param t The tree | ||
371 | */ | ||
372 | void | ||
373 | tree_debug (struct CadetTunnelTree *t); | ||
374 | |||
375 | |||
376 | /** | ||
377 | * Destroy the whole tree and free all used memory and Peer_Ids | ||
378 | * | ||
379 | * @param t Tree to be destroyed | ||
380 | */ | ||
381 | void | ||
382 | tree_destroy (struct CadetTunnelTree *t); | ||
diff --git a/src/cadet/gnunet-cadet-profiler.c b/src/cadet/gnunet-cadet-profiler.c new file mode 100644 index 000000000..c944caa75 --- /dev/null +++ b/src/cadet/gnunet-cadet-profiler.c | |||
@@ -0,0 +1,1092 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2011 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/gnunet-cadet-profiler.c | ||
22 | * | ||
23 | * @brief Profiler for cadet experiments. | ||
24 | */ | ||
25 | #include <stdio.h> | ||
26 | #include "platform.h" | ||
27 | #include "cadet_test_lib.h" | ||
28 | #include "gnunet_cadet_service.h" | ||
29 | #include "gnunet_statistics_service.h" | ||
30 | |||
31 | |||
32 | #define PING 1 | ||
33 | #define PONG 2 | ||
34 | |||
35 | |||
36 | /** | ||
37 | * Paximum ping period in milliseconds. Real period = rand (0, PING_PERIOD) | ||
38 | */ | ||
39 | #define PING_PERIOD 1000 | ||
40 | |||
41 | /** | ||
42 | * How long until we give up on connecting the peers? | ||
43 | */ | ||
44 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) | ||
45 | |||
46 | /** | ||
47 | * Time to wait for stuff that should be rather fast | ||
48 | */ | ||
49 | #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300) | ||
50 | |||
51 | /** | ||
52 | * Total number of rounds. | ||
53 | */ | ||
54 | #define number_rounds sizeof(rounds)/sizeof(rounds[0]) | ||
55 | |||
56 | /** | ||
57 | * Ratio of peers active. First round always is 1.0. | ||
58 | */ | ||
59 | static float rounds[] = {0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.0}; | ||
60 | |||
61 | /** | ||
62 | * Message type for pings. | ||
63 | */ | ||
64 | struct CadetPingMessage | ||
65 | { | ||
66 | /** | ||
67 | * Header. Type PING/PONG. | ||
68 | */ | ||
69 | struct GNUNET_MessageHeader header; | ||
70 | |||
71 | /** | ||
72 | * Message number. | ||
73 | */ | ||
74 | uint32_t counter; | ||
75 | |||
76 | /** | ||
77 | * Time the message was sent. | ||
78 | */ | ||
79 | struct GNUNET_TIME_AbsoluteNBO timestamp; | ||
80 | |||
81 | /** | ||
82 | * Round number. | ||
83 | */ | ||
84 | uint32_t round_number; | ||
85 | }; | ||
86 | |||
87 | /** | ||
88 | * Peer description. | ||
89 | */ | ||
90 | struct CadetPeer | ||
91 | { | ||
92 | /** | ||
93 | * Testbed Operation (to get peer id, etc). | ||
94 | */ | ||
95 | struct GNUNET_TESTBED_Operation *op; | ||
96 | |||
97 | /** | ||
98 | * Peer ID. | ||
99 | */ | ||
100 | struct GNUNET_PeerIdentity id; | ||
101 | |||
102 | /** | ||
103 | * Cadet handle for the root peer | ||
104 | */ | ||
105 | struct GNUNET_CADET_Handle *cadet; | ||
106 | |||
107 | /** | ||
108 | * Channel handle for the root peer | ||
109 | */ | ||
110 | struct GNUNET_CADET_Channel *ch; | ||
111 | |||
112 | /** | ||
113 | * Channel handle for the dest peer | ||
114 | */ | ||
115 | struct GNUNET_CADET_Channel *incoming_ch; | ||
116 | |||
117 | /** | ||
118 | * Channel handle for a warmup channel. | ||
119 | */ | ||
120 | struct GNUNET_CADET_Channel *warmup_ch; | ||
121 | |||
122 | /** | ||
123 | * Number of payload packes sent | ||
124 | */ | ||
125 | int data_sent; | ||
126 | |||
127 | /** | ||
128 | * Number of payload packets received | ||
129 | */ | ||
130 | int data_received; | ||
131 | |||
132 | /** | ||
133 | * Is peer up? | ||
134 | */ | ||
135 | int up; | ||
136 | |||
137 | /** | ||
138 | * Destinaton to ping. | ||
139 | */ | ||
140 | struct CadetPeer *dest; | ||
141 | |||
142 | /** | ||
143 | * Incoming channel for pings. | ||
144 | */ | ||
145 | struct CadetPeer *incoming; | ||
146 | |||
147 | /** | ||
148 | * Task to do the next ping. | ||
149 | */ | ||
150 | GNUNET_SCHEDULER_TaskIdentifier ping_task; | ||
151 | |||
152 | float mean[number_rounds]; | ||
153 | float var[number_rounds]; | ||
154 | unsigned int pongs[number_rounds]; | ||
155 | unsigned int pings[number_rounds]; | ||
156 | |||
157 | }; | ||
158 | |||
159 | /** | ||
160 | * Duration of each round. | ||
161 | */ | ||
162 | static struct GNUNET_TIME_Relative round_time; | ||
163 | |||
164 | /** | ||
165 | * GNUNET_PeerIdentity -> CadetPeer | ||
166 | */ | ||
167 | static struct GNUNET_CONTAINER_MultiPeerMap *ids; | ||
168 | |||
169 | /** | ||
170 | * Testbed peer handles. | ||
171 | */ | ||
172 | static struct GNUNET_TESTBED_Peer **testbed_handles; | ||
173 | |||
174 | /** | ||
175 | * Testbed Operation (to get stats). | ||
176 | */ | ||
177 | static struct GNUNET_TESTBED_Operation *stats_op; | ||
178 | |||
179 | /** | ||
180 | * Operation to get peer ids. | ||
181 | */ | ||
182 | struct CadetPeer *peers; | ||
183 | |||
184 | /** | ||
185 | * Peer ids counter. | ||
186 | */ | ||
187 | static unsigned int p_ids; | ||
188 | |||
189 | /** | ||
190 | * Total number of peers. | ||
191 | */ | ||
192 | static unsigned long long peers_total; | ||
193 | |||
194 | /** | ||
195 | * Number of currently running peers. | ||
196 | */ | ||
197 | static unsigned long long peers_running; | ||
198 | |||
199 | /** | ||
200 | * Number of peers doing pings. | ||
201 | */ | ||
202 | static unsigned long long peers_pinging; | ||
203 | |||
204 | /** | ||
205 | * Test context (to shut down). | ||
206 | */ | ||
207 | static struct GNUNET_CADET_TEST_Context *test_ctx; | ||
208 | |||
209 | /** | ||
210 | * Task called to shutdown test. | ||
211 | */ | ||
212 | static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; | ||
213 | |||
214 | /** | ||
215 | * Task called to disconnect peers, before shutdown. | ||
216 | */ | ||
217 | static GNUNET_SCHEDULER_TaskIdentifier disconnect_task; | ||
218 | |||
219 | /** | ||
220 | * Task to perform tests | ||
221 | */ | ||
222 | static GNUNET_SCHEDULER_TaskIdentifier test_task; | ||
223 | |||
224 | /** | ||
225 | * Round number. | ||
226 | */ | ||
227 | static unsigned int current_round; | ||
228 | |||
229 | /** | ||
230 | * Do preconnect? (Each peer creates a tunnel to one other peer). | ||
231 | */ | ||
232 | static int do_warmup; | ||
233 | |||
234 | /** | ||
235 | * Warmup progress. | ||
236 | */ | ||
237 | static unsigned int peers_warmup; | ||
238 | |||
239 | /** | ||
240 | * Flag to notify callbacks not to generate any new traffic anymore. | ||
241 | */ | ||
242 | static int test_finished; | ||
243 | |||
244 | |||
245 | /** | ||
246 | * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES. | ||
247 | * | ||
248 | * Testcase continues when the root receives confirmation of connected peers, | ||
249 | * on callback funtion ch. | ||
250 | * | ||
251 | * @param cls Closure (unsued). | ||
252 | * @param tc Task Context. | ||
253 | */ | ||
254 | static void | ||
255 | start_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
256 | |||
257 | |||
258 | /** | ||
259 | * Calculate a random delay. | ||
260 | * | ||
261 | * @param max Exclusive maximum, in ms. | ||
262 | * | ||
263 | * @return A time between 0 a max-1 ms. | ||
264 | */ | ||
265 | static struct GNUNET_TIME_Relative | ||
266 | delay_ms_rnd (unsigned int max) | ||
267 | { | ||
268 | unsigned int rnd; | ||
269 | |||
270 | rnd = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, max); | ||
271 | return GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, rnd); | ||
272 | } | ||
273 | |||
274 | |||
275 | /** | ||
276 | * Get the index of a peer in the peers array. | ||
277 | * | ||
278 | * @param peer Peer whose index to get. | ||
279 | * | ||
280 | * @return Index of peer in peers. | ||
281 | */ | ||
282 | static unsigned int | ||
283 | get_index (struct CadetPeer *peer) | ||
284 | { | ||
285 | return peer - peers; | ||
286 | } | ||
287 | |||
288 | |||
289 | /** | ||
290 | * Show the results of the test (banwidth acheived) and log them to GAUGER | ||
291 | */ | ||
292 | static void | ||
293 | show_end_data (void) | ||
294 | { | ||
295 | struct CadetPeer *peer; | ||
296 | unsigned int i; | ||
297 | unsigned int j; | ||
298 | |||
299 | for (i = 0; i < number_rounds; i++) | ||
300 | { | ||
301 | for (j = 0; j < peers_pinging; j++) | ||
302 | { | ||
303 | peer = &peers[j]; | ||
304 | FPRINTF (stdout, | ||
305 | "ROUND %3u PEER %3u: %10.2f / %10.2f, PINGS: %3u, PONGS: %3u\n", | ||
306 | i, j, peer->mean[i], sqrt (peer->var[i] / (peer->pongs[i] - 1)), | ||
307 | peer->pings[i], peer->pongs[i]); | ||
308 | } | ||
309 | } | ||
310 | } | ||
311 | |||
312 | |||
313 | /** | ||
314 | * Shut down peergroup, clean up. | ||
315 | * | ||
316 | * @param cls Closure (unused). | ||
317 | * @param tc Task Context. | ||
318 | */ | ||
319 | static void | ||
320 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
321 | { | ||
322 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Ending test.\n"); | ||
323 | shutdown_handle = GNUNET_SCHEDULER_NO_TASK; | ||
324 | } | ||
325 | |||
326 | |||
327 | /** | ||
328 | * Disconnect from cadet services af all peers, call shutdown. | ||
329 | * | ||
330 | * @param cls Closure (unused). | ||
331 | * @param tc Task Context. | ||
332 | */ | ||
333 | static void | ||
334 | disconnect_cadet_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
335 | { | ||
336 | long line = (long) cls; | ||
337 | unsigned int i; | ||
338 | |||
339 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
340 | "disconnecting cadet service, called from line %ld\n", line); | ||
341 | disconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
342 | for (i = 0; i < peers_total; i++) | ||
343 | { | ||
344 | if (NULL != peers[i].op) | ||
345 | GNUNET_TESTBED_operation_done (peers[i].op); | ||
346 | |||
347 | if (peers[i].up != GNUNET_YES) | ||
348 | continue; | ||
349 | |||
350 | if (NULL != peers[i].ch) | ||
351 | { | ||
352 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: channel %p\n", i, peers[i].ch); | ||
353 | GNUNET_CADET_channel_destroy (peers[i].ch); | ||
354 | } | ||
355 | if (NULL != peers[i].warmup_ch) | ||
356 | { | ||
357 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: warmup channel %p\n", | ||
358 | i, peers[i].warmup_ch); | ||
359 | GNUNET_CADET_channel_destroy (peers[i].warmup_ch); | ||
360 | } | ||
361 | if (NULL != peers[i].incoming_ch) | ||
362 | { | ||
363 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u: incoming channel %p\n", | ||
364 | i, peers[i].incoming_ch); | ||
365 | GNUNET_CADET_channel_destroy (peers[i].incoming_ch); | ||
366 | } | ||
367 | } | ||
368 | GNUNET_CADET_TEST_cleanup (test_ctx); | ||
369 | if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle) | ||
370 | { | ||
371 | GNUNET_SCHEDULER_cancel (shutdown_handle); | ||
372 | } | ||
373 | shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
374 | } | ||
375 | |||
376 | |||
377 | /** | ||
378 | * Finish test normally: schedule disconnect and shutdown | ||
379 | * | ||
380 | * @param line Line in the code the abort is requested from (__LINE__). | ||
381 | */ | ||
382 | static void | ||
383 | abort_test (long line) | ||
384 | { | ||
385 | if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) | ||
386 | { | ||
387 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
388 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, | ||
389 | (void *) line); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | /** | ||
394 | * Stats callback. Finish the stats testbed operation and when all stats have | ||
395 | * been iterated, shutdown the test. | ||
396 | * | ||
397 | * @param cls closure | ||
398 | * @param op the operation that has been finished | ||
399 | * @param emsg error message in case the operation has failed; will be NULL if | ||
400 | * operation has executed successfully. | ||
401 | */ | ||
402 | static void | ||
403 | stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) | ||
404 | { | ||
405 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "... collecting statistics done.\n"); | ||
406 | GNUNET_TESTBED_operation_done (stats_op); | ||
407 | |||
408 | if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) | ||
409 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
410 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, | ||
411 | (void *) __LINE__); | ||
412 | |||
413 | } | ||
414 | |||
415 | |||
416 | /** | ||
417 | * Process statistic values. | ||
418 | * | ||
419 | * @param cls closure | ||
420 | * @param peer the peer the statistic belong to | ||
421 | * @param subsystem name of subsystem that created the statistic | ||
422 | * @param name the name of the datum | ||
423 | * @param value the current value | ||
424 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
425 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
426 | */ | ||
427 | static int | ||
428 | stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer, | ||
429 | const char *subsystem, const char *name, | ||
430 | uint64_t value, int is_persistent) | ||
431 | { | ||
432 | uint32_t i; | ||
433 | |||
434 | i = GNUNET_TESTBED_get_index (peer); | ||
435 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " STATS %u - %s [%s]: %llu\n", | ||
436 | i, subsystem, name, value); | ||
437 | |||
438 | return GNUNET_OK; | ||
439 | } | ||
440 | |||
441 | |||
442 | /** | ||
443 | * Task check that keepalives were sent and received. | ||
444 | * | ||
445 | * @param cls Closure (NULL). | ||
446 | * @param tc Task Context. | ||
447 | */ | ||
448 | static void | ||
449 | collect_stats (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
450 | { | ||
451 | if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) | ||
452 | return; | ||
453 | |||
454 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start collecting statistics...\n"); | ||
455 | stats_op = GNUNET_TESTBED_get_statistics (peers_total, testbed_handles, | ||
456 | NULL, NULL, | ||
457 | stats_iterator, stats_cont, NULL); | ||
458 | } | ||
459 | |||
460 | |||
461 | /** | ||
462 | * @brief Finish profiler normally. Signal finish and start collecting stats. | ||
463 | * | ||
464 | * @param cls Closure (unused). | ||
465 | * @param tc Task context. | ||
466 | */ | ||
467 | static void | ||
468 | finish_profiler (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
469 | { | ||
470 | if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) | ||
471 | return; | ||
472 | |||
473 | test_finished = GNUNET_YES; | ||
474 | show_end_data(); | ||
475 | GNUNET_SCHEDULER_add_now (&collect_stats, NULL); | ||
476 | } | ||
477 | |||
478 | /** | ||
479 | * Set the total number of running peers. | ||
480 | * | ||
481 | * @param target Desired number of running peers. | ||
482 | */ | ||
483 | static void | ||
484 | adjust_running_peers (unsigned int target) | ||
485 | { | ||
486 | struct GNUNET_TESTBED_Operation *op; | ||
487 | unsigned int delta; | ||
488 | unsigned int run; | ||
489 | unsigned int i; | ||
490 | unsigned int r; | ||
491 | |||
492 | GNUNET_assert (target <= peers_total); | ||
493 | |||
494 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "adjust peers to %u\n", target); | ||
495 | if (target > peers_running) | ||
496 | { | ||
497 | delta = target - peers_running; | ||
498 | run = GNUNET_YES; | ||
499 | } | ||
500 | else | ||
501 | { | ||
502 | delta = peers_running - target; | ||
503 | run = GNUNET_NO; | ||
504 | } | ||
505 | |||
506 | for (i = 0; i < delta; i++) | ||
507 | { | ||
508 | do { | ||
509 | r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
510 | peers_total - peers_pinging); | ||
511 | r += peers_pinging; | ||
512 | } while (peers[r].up == run || NULL != peers[r].incoming); | ||
513 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "St%s peer %u: %s\n", | ||
514 | run ? "arting" : "opping", r, GNUNET_i2s (&peers[r].id)); | ||
515 | |||
516 | if (GNUNET_SCHEDULER_NO_TASK != peers[r].ping_task) | ||
517 | GNUNET_SCHEDULER_cancel (peers[r].ping_task); | ||
518 | peers[r].ping_task = GNUNET_SCHEDULER_NO_TASK; | ||
519 | |||
520 | peers[r].up = run; | ||
521 | |||
522 | if (NULL != peers[r].ch) | ||
523 | GNUNET_CADET_channel_destroy (peers[r].ch); | ||
524 | peers[r].ch = NULL; | ||
525 | if (NULL != peers[r].dest) | ||
526 | { | ||
527 | if (NULL != peers[r].dest->incoming_ch) | ||
528 | GNUNET_CADET_channel_destroy (peers[r].dest->incoming_ch); | ||
529 | peers[r].dest->incoming_ch = NULL; | ||
530 | } | ||
531 | |||
532 | op = GNUNET_TESTBED_peer_manage_service (&peers[r], testbed_handles[r], | ||
533 | "cadet", NULL, NULL, run); | ||
534 | GNUNET_break (NULL != op); | ||
535 | peers_running += run ? 1 : -1; | ||
536 | GNUNET_assert (peers_running > 0); | ||
537 | } | ||
538 | } | ||
539 | |||
540 | |||
541 | /** | ||
542 | * @brief Move to next round. | ||
543 | * | ||
544 | * @param cls Closure (round #). | ||
545 | * @param tc Task context. | ||
546 | */ | ||
547 | static void | ||
548 | next_rnd (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
549 | { | ||
550 | if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) | ||
551 | return; | ||
552 | |||
553 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "ROUND %ld\n", current_round); | ||
554 | if (0.0 == rounds[current_round]) | ||
555 | { | ||
556 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Finishing\n"); | ||
557 | GNUNET_SCHEDULER_add_now (&finish_profiler, NULL); | ||
558 | return; | ||
559 | } | ||
560 | adjust_running_peers (rounds[current_round] * peers_total); | ||
561 | current_round++; | ||
562 | |||
563 | GNUNET_SCHEDULER_add_delayed (round_time, &next_rnd, NULL); | ||
564 | } | ||
565 | |||
566 | |||
567 | /** | ||
568 | * Transmit ping callback. | ||
569 | * | ||
570 | * @param cls Closure (peer for PING, NULL for PONG). | ||
571 | * @param size Size of the tranmist buffer. | ||
572 | * @param buf Pointer to the beginning of the buffer. | ||
573 | * | ||
574 | * @return Number of bytes written to buf. | ||
575 | */ | ||
576 | static size_t | ||
577 | tmt_rdy_ping (void *cls, size_t size, void *buf); | ||
578 | |||
579 | |||
580 | /** | ||
581 | * Transmit pong callback. | ||
582 | * | ||
583 | * @param cls Closure (copy of PING message, to be freed). | ||
584 | * @param size Size of the buffer we have. | ||
585 | * @param buf Buffer to copy data to. | ||
586 | */ | ||
587 | static size_t | ||
588 | tmt_rdy_pong (void *cls, size_t size, void *buf) | ||
589 | { | ||
590 | struct CadetPingMessage *ping = cls; | ||
591 | struct CadetPingMessage *pong; | ||
592 | |||
593 | if (0 == size || NULL == buf) | ||
594 | { | ||
595 | GNUNET_free (ping); | ||
596 | return 0; | ||
597 | } | ||
598 | pong = (struct CadetPingMessage *) buf; | ||
599 | memcpy (pong, ping, sizeof (*ping)); | ||
600 | pong->header.type = htons (PONG); | ||
601 | |||
602 | GNUNET_free (ping); | ||
603 | return sizeof (*ping); | ||
604 | } | ||
605 | |||
606 | |||
607 | /** | ||
608 | * @brief Send a ping to destination | ||
609 | * | ||
610 | * @param cls Closure (peer). | ||
611 | * @param tc Task context. | ||
612 | */ | ||
613 | static void | ||
614 | ping (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
615 | { | ||
616 | struct CadetPeer *peer = (struct CadetPeer *) cls; | ||
617 | |||
618 | peer->ping_task = GNUNET_SCHEDULER_NO_TASK; | ||
619 | |||
620 | if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0 | ||
621 | || GNUNET_YES == test_finished) | ||
622 | return; | ||
623 | |||
624 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u -> %u (%u)\n", | ||
625 | get_index (peer), get_index (peer->dest), peer->data_sent); | ||
626 | |||
627 | GNUNET_CADET_notify_transmit_ready (peer->ch, GNUNET_NO, | ||
628 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
629 | sizeof (struct CadetPingMessage), | ||
630 | &tmt_rdy_ping, peer); | ||
631 | } | ||
632 | |||
633 | /** | ||
634 | * @brief Reply with a pong to origin. | ||
635 | * | ||
636 | * @param cls Closure (peer). | ||
637 | * @param tc Task context. | ||
638 | */ | ||
639 | static void | ||
640 | pong (struct GNUNET_CADET_Channel *channel, const struct CadetPingMessage *ping) | ||
641 | { | ||
642 | struct CadetPingMessage *copy; | ||
643 | |||
644 | copy = GNUNET_new (struct CadetPingMessage); | ||
645 | memcpy (copy, ping, sizeof (*ping)); | ||
646 | GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, | ||
647 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
648 | sizeof (struct CadetPingMessage), | ||
649 | &tmt_rdy_pong, copy); | ||
650 | } | ||
651 | |||
652 | |||
653 | /** | ||
654 | * Transmit ping callback | ||
655 | * | ||
656 | * @param cls Closure (peer). | ||
657 | * @param size Size of the buffer we have. | ||
658 | * @param buf Buffer to copy data to. | ||
659 | */ | ||
660 | static size_t | ||
661 | tmt_rdy_ping (void *cls, size_t size, void *buf) | ||
662 | { | ||
663 | struct CadetPeer *peer = (struct CadetPeer *) cls; | ||
664 | struct CadetPingMessage *msg = buf; | ||
665 | |||
666 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tmt_rdy called, filling buffer\n"); | ||
667 | if (size < sizeof (struct CadetPingMessage) || NULL == buf) | ||
668 | { | ||
669 | GNUNET_break (GNUNET_YES == test_finished); | ||
670 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
671 | "size %u, buf %p, data_sent %u, data_received %u\n", | ||
672 | size, buf, peer->data_sent, peer->data_received); | ||
673 | |||
674 | return 0; | ||
675 | } | ||
676 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending: msg %d\n", peer->data_sent); | ||
677 | msg->header.size = htons (size); | ||
678 | msg->header.type = htons (PING); | ||
679 | msg->counter = htonl (peer->data_sent++); | ||
680 | msg->round_number = htonl (current_round); | ||
681 | msg->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); | ||
682 | peer->pings[current_round]++; | ||
683 | peer->ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (PING_PERIOD), | ||
684 | &ping, peer); | ||
685 | |||
686 | return sizeof (struct CadetPingMessage); | ||
687 | } | ||
688 | |||
689 | |||
690 | /** | ||
691 | * Function is called whenever a PING message is received. | ||
692 | * | ||
693 | * @param cls closure (peer #, set from GNUNET_CADET_connect) | ||
694 | * @param channel connection to the other end | ||
695 | * @param channel_ctx place to store local state associated with the channel | ||
696 | * @param message the actual message | ||
697 | * @return GNUNET_OK to keep the connection open, | ||
698 | * GNUNET_SYSERR to close it (signal serious error) | ||
699 | */ | ||
700 | int | ||
701 | ping_handler (void *cls, struct GNUNET_CADET_Channel *channel, | ||
702 | void **channel_ctx, | ||
703 | const struct GNUNET_MessageHeader *message) | ||
704 | { | ||
705 | long n = (long) cls; | ||
706 | |||
707 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%u got PING\n", n); | ||
708 | GNUNET_CADET_receive_done (channel); | ||
709 | if (GNUNET_NO == test_finished) | ||
710 | pong (channel, (struct CadetPingMessage *) message); | ||
711 | |||
712 | return GNUNET_OK; | ||
713 | } | ||
714 | |||
715 | |||
716 | /** | ||
717 | * Function is called whenever a PONG message is received. | ||
718 | * | ||
719 | * @param cls closure (peer #, set from GNUNET_CADET_connect) | ||
720 | * @param channel connection to the other end | ||
721 | * @param channel_ctx place to store local state associated with the channel | ||
722 | * @param message the actual message | ||
723 | * @return GNUNET_OK to keep the connection open, | ||
724 | * GNUNET_SYSERR to close it (signal serious error) | ||
725 | */ | ||
726 | int | ||
727 | pong_handler (void *cls, struct GNUNET_CADET_Channel *channel, | ||
728 | void **channel_ctx, | ||
729 | const struct GNUNET_MessageHeader *message) | ||
730 | { | ||
731 | long n = (long) cls; | ||
732 | struct CadetPeer *peer; | ||
733 | struct CadetPingMessage *msg; | ||
734 | struct GNUNET_TIME_Absolute send_time; | ||
735 | struct GNUNET_TIME_Relative latency; | ||
736 | unsigned int r /* Ping round */; | ||
737 | float delta; | ||
738 | |||
739 | GNUNET_CADET_receive_done (channel); | ||
740 | peer = &peers[n]; | ||
741 | |||
742 | msg = (struct CadetPingMessage *) message; | ||
743 | |||
744 | send_time = GNUNET_TIME_absolute_ntoh (msg->timestamp); | ||
745 | latency = GNUNET_TIME_absolute_get_duration (send_time); | ||
746 | r = ntohl (msg->round_number); | ||
747 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <- %u (%u) latency: %s\n", | ||
748 | get_index (peer), get_index (peer->dest), ntohl (msg->counter), | ||
749 | GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO)); | ||
750 | |||
751 | /* Online variance calculation */ | ||
752 | peer->pongs[r]++; | ||
753 | delta = latency.rel_value_us - peer->mean[r]; | ||
754 | peer->mean[r] = peer->mean[r] + delta/peer->pongs[r]; | ||
755 | peer->var[r] += delta * (latency.rel_value_us - peer->mean[r]); | ||
756 | |||
757 | return GNUNET_OK; | ||
758 | } | ||
759 | |||
760 | |||
761 | /** | ||
762 | * Handlers, for diverse services | ||
763 | */ | ||
764 | static struct GNUNET_CADET_MessageHandler handlers[] = { | ||
765 | {&ping_handler, PING, sizeof (struct CadetPingMessage)}, | ||
766 | {&pong_handler, PONG, sizeof (struct CadetPingMessage)}, | ||
767 | {NULL, 0, 0} | ||
768 | }; | ||
769 | |||
770 | |||
771 | /** | ||
772 | * Method called whenever another peer has added us to a channel | ||
773 | * the other peer initiated. | ||
774 | * | ||
775 | * @param cls Closure. | ||
776 | * @param channel New handle to the channel. | ||
777 | * @param initiator Peer that started the channel. | ||
778 | * @param port Port this channel is connected to. | ||
779 | * @param options channel option flags | ||
780 | * @return Initial channel context for the channel | ||
781 | * (can be NULL -- that's not an error). | ||
782 | */ | ||
783 | static void * | ||
784 | incoming_channel (void *cls, struct GNUNET_CADET_Channel *channel, | ||
785 | const struct GNUNET_PeerIdentity *initiator, | ||
786 | uint32_t port, enum GNUNET_CADET_ChannelOption options) | ||
787 | { | ||
788 | long n = (long) cls; | ||
789 | struct CadetPeer *peer; | ||
790 | |||
791 | peer = GNUNET_CONTAINER_multipeermap_get (ids, initiator); | ||
792 | GNUNET_assert (NULL != peer); | ||
793 | if (NULL == peers[n].incoming) | ||
794 | { | ||
795 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "WARMUP %3u: %u <= %u\n", | ||
796 | peers_warmup, n, get_index (peer)); | ||
797 | peers_warmup++; | ||
798 | if (peers_warmup < peers_total) | ||
799 | return NULL; | ||
800 | if (GNUNET_SCHEDULER_NO_TASK != test_task) | ||
801 | { | ||
802 | GNUNET_SCHEDULER_cancel (test_task); | ||
803 | test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
804 | &start_test, NULL); | ||
805 | } | ||
806 | return NULL; | ||
807 | } | ||
808 | GNUNET_assert (peer == peers[n].incoming); | ||
809 | GNUNET_assert (peer->dest == &peers[n]); | ||
810 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u <= %u %p\n", | ||
811 | n, get_index (peer), channel); | ||
812 | peers[n].incoming_ch = channel; | ||
813 | |||
814 | return NULL; | ||
815 | } | ||
816 | |||
817 | /** | ||
818 | * Function called whenever an inbound channel is destroyed. Should clean up | ||
819 | * any associated state. | ||
820 | * | ||
821 | * @param cls closure (set from GNUNET_CADET_connect) | ||
822 | * @param channel connection to the other end (henceforth invalid) | ||
823 | * @param channel_ctx place where local state associated | ||
824 | * with the channel is stored | ||
825 | */ | ||
826 | static void | ||
827 | channel_cleaner (void *cls, const struct GNUNET_CADET_Channel *channel, | ||
828 | void *channel_ctx) | ||
829 | { | ||
830 | long n = (long) cls; | ||
831 | struct CadetPeer *peer = &peers[n]; | ||
832 | |||
833 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
834 | "Channel %p disconnected at peer %ld\n", channel, n); | ||
835 | if (peer->ch == channel) | ||
836 | peer->ch = NULL; | ||
837 | } | ||
838 | |||
839 | |||
840 | /** | ||
841 | * Select a random peer that has no incoming channel | ||
842 | * | ||
843 | * @param peer ID of the peer connecting. NULL if irrelevant (warmup). | ||
844 | * | ||
845 | * @return Random peer not yet connected to. | ||
846 | */ | ||
847 | static struct CadetPeer * | ||
848 | select_random_peer (struct CadetPeer *peer) | ||
849 | { | ||
850 | unsigned int r; | ||
851 | |||
852 | do | ||
853 | { | ||
854 | r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, peers_total); | ||
855 | } while (NULL != peers[r].incoming); | ||
856 | peers[r].incoming = peer; | ||
857 | |||
858 | return &peers[r]; | ||
859 | } | ||
860 | |||
861 | /** | ||
862 | * START THE TEST ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES. | ||
863 | * | ||
864 | * Testcase continues when the root receives confirmation of connected peers, | ||
865 | * on callback funtion ch. | ||
866 | * | ||
867 | * @param cls Closure (unsued). | ||
868 | * @param tc Task Context. | ||
869 | */ | ||
870 | static void | ||
871 | start_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
872 | { | ||
873 | enum GNUNET_CADET_ChannelOption flags; | ||
874 | unsigned long i; | ||
875 | |||
876 | test_task = GNUNET_SCHEDULER_NO_TASK; | ||
877 | if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) | ||
878 | return; | ||
879 | |||
880 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Start profiler\n"); | ||
881 | |||
882 | flags = GNUNET_CADET_OPTION_DEFAULT; | ||
883 | for (i = 0; i < peers_pinging; i++) | ||
884 | { | ||
885 | peers[i].dest = select_random_peer (&peers[i]); | ||
886 | peers[i].ch = GNUNET_CADET_channel_create (peers[i].cadet, NULL, | ||
887 | &peers[i].dest->id, | ||
888 | 1, flags); | ||
889 | if (NULL == peers[i].ch) | ||
890 | { | ||
891 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Channel %lu failed\n", i); | ||
892 | GNUNET_CADET_TEST_cleanup (test_ctx); | ||
893 | return; | ||
894 | } | ||
895 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "%u => %u %p\n", | ||
896 | i, get_index (peers[i].dest), peers[i].ch); | ||
897 | peers[i].ping_task = GNUNET_SCHEDULER_add_delayed (delay_ms_rnd (2000), | ||
898 | &ping, &peers[i]); | ||
899 | } | ||
900 | peers_running = peers_total; | ||
901 | if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) | ||
902 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
903 | disconnect_task = | ||
904 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(round_time, | ||
905 | number_rounds + 1), | ||
906 | &disconnect_cadet_peers, | ||
907 | (void *) __LINE__); | ||
908 | GNUNET_SCHEDULER_add_delayed (round_time, &next_rnd, NULL); | ||
909 | } | ||
910 | |||
911 | |||
912 | /** | ||
913 | * Do warmup: create some channels to spread information about the topology. | ||
914 | */ | ||
915 | static void | ||
916 | warmup (void) | ||
917 | { | ||
918 | struct CadetPeer *peer; | ||
919 | unsigned int i; | ||
920 | |||
921 | for (i = 0; i < peers_total; i++) | ||
922 | { | ||
923 | peer = select_random_peer (NULL); | ||
924 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "WARMUP %u => %u\n", | ||
925 | i, get_index (peer)); | ||
926 | peers[i].warmup_ch = | ||
927 | GNUNET_CADET_channel_create (peers[i].cadet, NULL, &peer->id, | ||
928 | 1, GNUNET_CADET_OPTION_DEFAULT); | ||
929 | if (NULL == peers[i].warmup_ch) | ||
930 | { | ||
931 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Warmup %u failed\n", i); | ||
932 | GNUNET_CADET_TEST_cleanup (test_ctx); | ||
933 | return; | ||
934 | } | ||
935 | } | ||
936 | } | ||
937 | |||
938 | /** | ||
939 | * Callback to be called when the requested peer information is available | ||
940 | * | ||
941 | * @param cls the closure from GNUNET_TESTBED_peer_get_information() | ||
942 | * @param op the operation this callback corresponds to | ||
943 | * @param pinfo the result; will be NULL if the operation has failed | ||
944 | * @param emsg error message if the operation has failed; | ||
945 | * NULL if the operation is successfull | ||
946 | */ | ||
947 | static void | ||
948 | peer_id_cb (void *cls, | ||
949 | struct GNUNET_TESTBED_Operation *op, | ||
950 | const struct GNUNET_TESTBED_PeerInformation *pinfo, | ||
951 | const char *emsg) | ||
952 | { | ||
953 | long n = (long) cls; | ||
954 | |||
955 | if (NULL == pinfo || NULL != emsg) | ||
956 | { | ||
957 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); | ||
958 | abort_test (__LINE__); | ||
959 | return; | ||
960 | } | ||
961 | peers[n].id = *(pinfo->result.id); | ||
962 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " %u id: %s\n", | ||
963 | n, GNUNET_i2s (&peers[n].id)); | ||
964 | GNUNET_break (GNUNET_OK == | ||
965 | GNUNET_CONTAINER_multipeermap_put (ids, &peers[n].id, &peers[n], | ||
966 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)); | ||
967 | |||
968 | GNUNET_TESTBED_operation_done (peers[n].op); | ||
969 | peers[n].op = NULL; | ||
970 | |||
971 | p_ids++; | ||
972 | if (p_ids < peers_total) | ||
973 | return; | ||
974 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got all IDs, starting profiler\n"); | ||
975 | if (do_warmup) | ||
976 | { | ||
977 | struct GNUNET_TIME_Relative delay; | ||
978 | |||
979 | warmup(); | ||
980 | delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, | ||
981 | 100 * peers_total); | ||
982 | test_task = GNUNET_SCHEDULER_add_delayed (delay, &start_test, NULL); | ||
983 | return; /* start_test from incoming_channel */ | ||
984 | } | ||
985 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting in a second...\n"); | ||
986 | test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
987 | &start_test, NULL); | ||
988 | } | ||
989 | |||
990 | /** | ||
991 | * test main: start test when all peers are connected | ||
992 | * | ||
993 | * @param cls Closure. | ||
994 | * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. | ||
995 | * @param num_peers Number of peers that are running. | ||
996 | * @param testbed_peers Array of peers. | ||
997 | * @param cadetes Handle to each of the CADETs of the peers. | ||
998 | */ | ||
999 | static void | ||
1000 | tmain (void *cls, | ||
1001 | struct GNUNET_CADET_TEST_Context *ctx, | ||
1002 | unsigned int num_peers, | ||
1003 | struct GNUNET_TESTBED_Peer **testbed_peers, | ||
1004 | struct GNUNET_CADET_Handle **cadetes) | ||
1005 | { | ||
1006 | unsigned long i; | ||
1007 | |||
1008 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n"); | ||
1009 | test_ctx = ctx; | ||
1010 | GNUNET_assert (peers_total == num_peers); | ||
1011 | peers_running = num_peers; | ||
1012 | testbed_handles = testbed_peers; | ||
1013 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
1014 | &disconnect_cadet_peers, | ||
1015 | (void *) __LINE__); | ||
1016 | shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | ||
1017 | &shutdown_task, NULL); | ||
1018 | for (i = 0; i < peers_total; i++) | ||
1019 | { | ||
1020 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requesting id %ld\n", i); | ||
1021 | peers[i].up = GNUNET_YES; | ||
1022 | peers[i].cadet = cadetes[i]; | ||
1023 | peers[i].op = | ||
1024 | GNUNET_TESTBED_peer_get_information (testbed_handles[i], | ||
1025 | GNUNET_TESTBED_PIT_IDENTITY, | ||
1026 | &peer_id_cb, (void *) i); | ||
1027 | } | ||
1028 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "requested peer ids\n"); | ||
1029 | /* Continues from pi_cb -> do_test */ | ||
1030 | } | ||
1031 | |||
1032 | |||
1033 | /** | ||
1034 | * Main: start profiler. | ||
1035 | */ | ||
1036 | int | ||
1037 | main (int argc, char *argv[]) | ||
1038 | { | ||
1039 | static uint32_t ports[2]; | ||
1040 | const char *config_file; | ||
1041 | |||
1042 | config_file = ".profiler.conf"; | ||
1043 | |||
1044 | if (4 > argc) | ||
1045 | { | ||
1046 | fprintf (stderr, "usage: %s ROUND_TIME PEERS PINGS [DO_WARMUP]\n", argv[0]); | ||
1047 | fprintf (stderr, "example: %s 30s 16 1 Y\n", argv[0]); | ||
1048 | return 1; | ||
1049 | } | ||
1050 | |||
1051 | if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_relative (argv[1], &round_time)) | ||
1052 | { | ||
1053 | fprintf (stderr, "%s is not a valid time\n", argv[1]); | ||
1054 | return 1; | ||
1055 | } | ||
1056 | |||
1057 | peers_total = atoll (argv[2]); | ||
1058 | if (2 > peers_total) | ||
1059 | { | ||
1060 | fprintf (stderr, "%s peers is not valid (> 2)\n", argv[1]); | ||
1061 | return 1; | ||
1062 | } | ||
1063 | peers = GNUNET_malloc (sizeof (struct CadetPeer) * peers_total); | ||
1064 | |||
1065 | peers_pinging = atoll (argv[3]); | ||
1066 | |||
1067 | if (peers_total < 2 * peers_pinging) | ||
1068 | { | ||
1069 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1070 | "not enough peers, total should be > 2 * peers_pinging\n"); | ||
1071 | return 1; | ||
1072 | } | ||
1073 | |||
1074 | do_warmup = (5 > argc || argv[4][0] != 'N'); | ||
1075 | |||
1076 | ids = GNUNET_CONTAINER_multipeermap_create (2 * peers_total, GNUNET_YES); | ||
1077 | GNUNET_assert (NULL != ids); | ||
1078 | p_ids = 0; | ||
1079 | test_finished = GNUNET_NO; | ||
1080 | ports[0] = 1; | ||
1081 | ports[1] = 0; | ||
1082 | GNUNET_CADET_TEST_run ("cadet-profiler", config_file, peers_total, | ||
1083 | &tmain, NULL, /* tmain cls */ | ||
1084 | &incoming_channel, &channel_cleaner, | ||
1085 | handlers, ports); | ||
1086 | GNUNET_free (peers); | ||
1087 | |||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | /* end of gnunet-cadet-profiler.c */ | ||
1092 | |||
diff --git a/src/cadet/gnunet-cadet.c b/src/cadet/gnunet-cadet.c new file mode 100644 index 000000000..840c6d0ac --- /dev/null +++ b/src/cadet/gnunet-cadet.c | |||
@@ -0,0 +1,851 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2012 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-cadet.c | ||
23 | * @brief Print information about cadet tunnels and peers. | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_cadet_service.h" | ||
29 | #include "cadet.h" | ||
30 | |||
31 | |||
32 | /** | ||
33 | * Option -m. | ||
34 | */ | ||
35 | static int monitor_connections; | ||
36 | |||
37 | /** | ||
38 | * Option -P. | ||
39 | */ | ||
40 | static int request_peers; | ||
41 | |||
42 | /** | ||
43 | * Option --peer | ||
44 | */ | ||
45 | static char *peer_id; | ||
46 | |||
47 | /** | ||
48 | * Option -T. | ||
49 | */ | ||
50 | static int request_tunnels; | ||
51 | |||
52 | /** | ||
53 | * Option --tunnel | ||
54 | */ | ||
55 | static char *tunnel_id; | ||
56 | |||
57 | /** | ||
58 | * Option --connection | ||
59 | */ | ||
60 | static char *conn_id; | ||
61 | |||
62 | /** | ||
63 | * Option --channel | ||
64 | */ | ||
65 | static char *channel_id; | ||
66 | |||
67 | /** | ||
68 | * Port to listen on (-p). | ||
69 | */ | ||
70 | static uint32_t listen_port; | ||
71 | |||
72 | /** | ||
73 | * Request echo service | ||
74 | */ | ||
75 | int echo; | ||
76 | |||
77 | /** | ||
78 | * Time of last echo request. | ||
79 | */ | ||
80 | struct GNUNET_TIME_Absolute echo_time; | ||
81 | |||
82 | /** | ||
83 | * Task for next echo request. | ||
84 | */ | ||
85 | GNUNET_SCHEDULER_TaskIdentifier echo_task; | ||
86 | |||
87 | /** | ||
88 | * Peer to connect to. | ||
89 | */ | ||
90 | static char *target_id; | ||
91 | |||
92 | /** | ||
93 | * Port to connect to | ||
94 | */ | ||
95 | static uint32_t target_port; | ||
96 | |||
97 | /** | ||
98 | * Data pending in netcat mode. | ||
99 | */ | ||
100 | size_t data_size; | ||
101 | |||
102 | |||
103 | /** | ||
104 | * Cadet handle. | ||
105 | */ | ||
106 | static struct GNUNET_CADET_Handle *mh; | ||
107 | |||
108 | /** | ||
109 | * Channel handle. | ||
110 | */ | ||
111 | static struct GNUNET_CADET_Channel *ch; | ||
112 | |||
113 | /** | ||
114 | * Shutdown task handle. | ||
115 | */ | ||
116 | GNUNET_SCHEDULER_TaskIdentifier sd; | ||
117 | |||
118 | |||
119 | |||
120 | static void | ||
121 | listen_stdio (void); | ||
122 | |||
123 | |||
124 | |||
125 | /** | ||
126 | * Task run in monitor mode when the user presses CTRL-C to abort. | ||
127 | * Stops monitoring activity. | ||
128 | * | ||
129 | * @param cls Closure (unused). | ||
130 | * @param tc scheduler context | ||
131 | */ | ||
132 | static void | ||
133 | shutdown_task (void *cls, | ||
134 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
135 | { | ||
136 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); | ||
137 | if (NULL != ch) | ||
138 | { | ||
139 | GNUNET_CADET_channel_destroy (ch); | ||
140 | ch = NULL; | ||
141 | } | ||
142 | if (NULL != mh) | ||
143 | { | ||
144 | GNUNET_CADET_disconnect (mh); | ||
145 | mh = NULL; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | |||
150 | /** | ||
151 | * Function called to notify a client about the connection | ||
152 | * begin ready to queue more data. "buf" will be | ||
153 | * NULL and "size" zero if the connection was closed for | ||
154 | * writing in the meantime. | ||
155 | * | ||
156 | * FIXME | ||
157 | * | ||
158 | * @param cls closure | ||
159 | * @param size number of bytes available in buf | ||
160 | * @param buf where the callee should write the message | ||
161 | * @return number of bytes written to buf | ||
162 | */ | ||
163 | size_t | ||
164 | data_ready (void *cls, size_t size, void *buf) | ||
165 | { | ||
166 | struct GNUNET_MessageHeader *msg; | ||
167 | size_t total_size; | ||
168 | |||
169 | if (NULL == buf || 0 == size) | ||
170 | { | ||
171 | GNUNET_SCHEDULER_shutdown(); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | total_size = data_size + sizeof (struct GNUNET_MessageHeader); | ||
176 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending %u bytes\n", data_size); | ||
177 | GNUNET_assert (size >= total_size); | ||
178 | |||
179 | msg = buf; | ||
180 | msg->size = htons (total_size); | ||
181 | msg->type = htons (GNUNET_MESSAGE_TYPE_CADET_CLI); | ||
182 | memcpy (&msg[1], cls, data_size); | ||
183 | if (GNUNET_NO == echo) | ||
184 | { | ||
185 | listen_stdio (); | ||
186 | } | ||
187 | else | ||
188 | { | ||
189 | echo_time = GNUNET_TIME_absolute_get (); | ||
190 | } | ||
191 | |||
192 | return total_size; | ||
193 | } | ||
194 | |||
195 | |||
196 | /** | ||
197 | * Task run in monitor mode when the user presses CTRL-C to abort. | ||
198 | * Stops monitoring activity. | ||
199 | * | ||
200 | * @param cls Closure (unused). | ||
201 | * @param tc scheduler context | ||
202 | */ | ||
203 | static void | ||
204 | read_stdio (void *cls, | ||
205 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
206 | { | ||
207 | static char buf[60000]; | ||
208 | |||
209 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
210 | { | ||
211 | return; | ||
212 | } | ||
213 | |||
214 | data_size = read (0, buf, 60000); | ||
215 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stdio read %u bytes\n", data_size); | ||
216 | if (data_size < 1) | ||
217 | { | ||
218 | GNUNET_SCHEDULER_shutdown(); | ||
219 | return; | ||
220 | } | ||
221 | GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO, | ||
222 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
223 | data_size | ||
224 | + sizeof (struct GNUNET_MessageHeader), | ||
225 | &data_ready, buf); | ||
226 | } | ||
227 | |||
228 | |||
229 | /** | ||
230 | * Start listening to stdin | ||
231 | */ | ||
232 | static void | ||
233 | listen_stdio (void) | ||
234 | { | ||
235 | struct GNUNET_NETWORK_FDSet *rs; | ||
236 | |||
237 | rs = GNUNET_NETWORK_fdset_create (); | ||
238 | GNUNET_NETWORK_fdset_set_native (rs, 0); | ||
239 | GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
240 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
241 | rs, NULL, | ||
242 | &read_stdio, NULL); | ||
243 | GNUNET_NETWORK_fdset_destroy (rs); | ||
244 | } | ||
245 | |||
246 | |||
247 | /** | ||
248 | * Function called whenever a channel is destroyed. Should clean up | ||
249 | * any associated state. | ||
250 | * | ||
251 | * It must NOT call #GNUNET_CADET_channel_destroy on the channel. | ||
252 | * | ||
253 | * @param cls closure (set from #GNUNET_CADET_connect) | ||
254 | * @param channel connection to the other end (henceforth invalid) | ||
255 | * @param channel_ctx place where local state associated | ||
256 | * with the channel is stored | ||
257 | */ | ||
258 | static void | ||
259 | channel_ended (void *cls, | ||
260 | const struct GNUNET_CADET_Channel *channel, | ||
261 | void *channel_ctx) | ||
262 | { | ||
263 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Channel ended!\n"); | ||
264 | GNUNET_break (channel == ch); | ||
265 | ch = NULL; | ||
266 | GNUNET_SCHEDULER_shutdown (); | ||
267 | } | ||
268 | |||
269 | |||
270 | /** | ||
271 | * Method called whenever another peer has added us to a channel | ||
272 | * the other peer initiated. | ||
273 | * Only called (once) upon reception of data with a message type which was | ||
274 | * subscribed to in #GNUNET_CADET_connect. | ||
275 | * | ||
276 | * A call to #GNUNET_CADET_channel_destroy causes te channel to be ignored. In | ||
277 | * this case the handler MUST return NULL. | ||
278 | * | ||
279 | * @param cls closure | ||
280 | * @param channel new handle to the channel | ||
281 | * @param initiator peer that started the channel | ||
282 | * @param port Port this channel is for. | ||
283 | * @param options CadetOption flag field, with all active option bits set to 1. | ||
284 | * | ||
285 | * @return initial channel context for the channel | ||
286 | * (can be NULL -- that's not an error) | ||
287 | */ | ||
288 | static void * | ||
289 | channel_incoming (void *cls, | ||
290 | struct GNUNET_CADET_Channel * channel, | ||
291 | const struct GNUNET_PeerIdentity * initiator, | ||
292 | uint32_t port, enum GNUNET_CADET_ChannelOption options) | ||
293 | { | ||
294 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
295 | "Incoming channel %p on port %u\n", | ||
296 | channel, port); | ||
297 | if (NULL != ch) | ||
298 | { | ||
299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "A channel already exists\n"); | ||
300 | return NULL; | ||
301 | } | ||
302 | if (0 == listen_port) | ||
303 | { | ||
304 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not listening to channels\n"); | ||
305 | return NULL; | ||
306 | } | ||
307 | ch = channel; | ||
308 | if (GNUNET_NO == echo) | ||
309 | { | ||
310 | listen_stdio (); | ||
311 | return NULL; | ||
312 | } | ||
313 | data_size = 0; | ||
314 | return NULL; | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * @brief Send an echo request to the remote peer. | ||
319 | * | ||
320 | * @param cls Closure (NULL). | ||
321 | * @param tc Task context. | ||
322 | */ | ||
323 | static void | ||
324 | send_echo (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
325 | { | ||
326 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) || NULL == ch) | ||
327 | return; | ||
328 | |||
329 | GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO, | ||
330 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
331 | sizeof (struct GNUNET_MessageHeader), | ||
332 | &data_ready, NULL); | ||
333 | } | ||
334 | |||
335 | |||
336 | |||
337 | /** | ||
338 | * Call CADET's monitor API, get info of one connection. | ||
339 | * | ||
340 | * @param cls Closure (unused). | ||
341 | * @param tc TaskContext | ||
342 | */ | ||
343 | static void | ||
344 | create_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
345 | { | ||
346 | struct GNUNET_PeerIdentity pid; | ||
347 | enum GNUNET_CADET_ChannelOption opt; | ||
348 | |||
349 | GNUNET_assert (NULL == ch); | ||
350 | |||
351 | if (GNUNET_OK != | ||
352 | GNUNET_CRYPTO_eddsa_public_key_from_string (target_id, | ||
353 | strlen (target_id), | ||
354 | &pid.public_key)) | ||
355 | { | ||
356 | FPRINTF (stderr, | ||
357 | _("Invalid target `%s'\n"), | ||
358 | target_id); | ||
359 | GNUNET_SCHEDULER_shutdown (); | ||
360 | return; | ||
361 | } | ||
362 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to `%s'\n", target_id); | ||
363 | opt = GNUNET_CADET_OPTION_DEFAULT | GNUNET_CADET_OPTION_RELIABLE; | ||
364 | ch = GNUNET_CADET_channel_create (mh, NULL, &pid, target_port, opt); | ||
365 | if (GNUNET_NO == echo) | ||
366 | listen_stdio (); | ||
367 | else | ||
368 | GNUNET_SCHEDULER_add_now (send_echo, NULL); | ||
369 | } | ||
370 | |||
371 | |||
372 | /** | ||
373 | * Function called whenever a message is received. | ||
374 | * | ||
375 | * Each time the function must call #GNUNET_CADET_receive_done on the channel | ||
376 | * in order to receive the next message. This doesn't need to be immediate: | ||
377 | * can be delayed if some processing is done on the message. | ||
378 | * | ||
379 | * @param cls Closure (set from #GNUNET_CADET_connect). | ||
380 | * @param channel Connection to the other end. | ||
381 | * @param channel_ctx Place to store local state associated with the channel. | ||
382 | * @param message The actual message. | ||
383 | * @return #GNUNET_OK to keep the channel open, | ||
384 | * #GNUNET_SYSERR to close it (signal serious error). | ||
385 | */ | ||
386 | static int | ||
387 | data_callback (void *cls, | ||
388 | struct GNUNET_CADET_Channel *channel, | ||
389 | void **channel_ctx, | ||
390 | const struct GNUNET_MessageHeader *message) | ||
391 | { | ||
392 | uint16_t len; | ||
393 | ssize_t done; | ||
394 | uint16_t off; | ||
395 | const char *buf; | ||
396 | GNUNET_break (ch == channel); | ||
397 | |||
398 | if (GNUNET_YES == echo) | ||
399 | { | ||
400 | if (0 != listen_port) | ||
401 | { | ||
402 | /* Just listening to echo incoming messages*/ | ||
403 | GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, | ||
404 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
405 | sizeof (struct GNUNET_MessageHeader), | ||
406 | &data_ready, NULL); | ||
407 | return GNUNET_OK; | ||
408 | } | ||
409 | else | ||
410 | { | ||
411 | struct GNUNET_TIME_Relative latency; | ||
412 | |||
413 | latency = GNUNET_TIME_absolute_get_duration (echo_time); | ||
414 | echo_time = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
415 | FPRINTF (stdout, "time: %s\n", | ||
416 | GNUNET_STRINGS_relative_time_to_string (latency, GNUNET_NO)); | ||
417 | echo_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
418 | &send_echo, NULL); | ||
419 | } | ||
420 | } | ||
421 | |||
422 | len = ntohs (message->size) - sizeof (*message); | ||
423 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u bytes\n", len); | ||
424 | buf = (const char *) &message[1]; | ||
425 | off = 0; | ||
426 | while (off < len) | ||
427 | { | ||
428 | done = write (1, &buf[off], len - off); | ||
429 | if (done <= 0) | ||
430 | { | ||
431 | if (-1 == done) | ||
432 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, | ||
433 | "write"); | ||
434 | return GNUNET_SYSERR; | ||
435 | } | ||
436 | off += done; | ||
437 | } | ||
438 | return GNUNET_OK; | ||
439 | } | ||
440 | |||
441 | |||
442 | /** | ||
443 | * Method called to retrieve information about all peers in CADET, called | ||
444 | * once per peer. | ||
445 | * | ||
446 | * After last peer has been reported, an additional call with NULL is done. | ||
447 | * | ||
448 | * @param cls Closure. | ||
449 | * @param peer Peer, or NULL on "EOF". | ||
450 | * @param tunnel Do we have a tunnel towards this peer? | ||
451 | * @param n_paths Number of known paths towards this peer. | ||
452 | * @param best_path How long is the best path? | ||
453 | * (0 = unknown, 1 = ourselves, 2 = neighbor) | ||
454 | */ | ||
455 | static void | ||
456 | peers_callback (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
457 | int tunnel, unsigned int n_paths, unsigned int best_path) | ||
458 | { | ||
459 | if (NULL == peer) | ||
460 | { | ||
461 | if (GNUNET_YES != monitor_connections) | ||
462 | { | ||
463 | GNUNET_SCHEDULER_shutdown(); | ||
464 | } | ||
465 | return; | ||
466 | } | ||
467 | FPRINTF (stdout, "%s tunnel: %c, paths: %u\n", | ||
468 | GNUNET_i2s_full (peer), tunnel ? 'Y' : 'N', n_paths); | ||
469 | } | ||
470 | |||
471 | /** | ||
472 | * Method called to retrieve information about a specific peer | ||
473 | * known to the service. | ||
474 | * | ||
475 | * @param cls Closure. | ||
476 | * @param peer Peer ID. | ||
477 | * @param tunnel Do we have a tunnel towards this peer? #GNUNET_YES/#GNUNET_NO | ||
478 | * @param neighbor Is this a direct neighbor? #GNUNET_YES/#GNUNET_NO | ||
479 | * @param n_paths Number of paths known towards peer. | ||
480 | * @param paths Array of PEER_IDs representing all paths to reach the peer. | ||
481 | * Each path starts with the local peer. | ||
482 | * Each path ends with the destination peer (given in @c peer). | ||
483 | */ | ||
484 | void | ||
485 | peer_callback (void *cls, | ||
486 | const struct GNUNET_PeerIdentity *peer, | ||
487 | int tunnel, | ||
488 | int neighbor, | ||
489 | unsigned int n_paths, | ||
490 | struct GNUNET_PeerIdentity *paths) | ||
491 | { | ||
492 | } | ||
493 | |||
494 | |||
495 | /** | ||
496 | * Method called to retrieve information about all tunnels in CADET. | ||
497 | * | ||
498 | * @param cls Closure. | ||
499 | * @param peer Destination peer. | ||
500 | * @param channels Number of channels. | ||
501 | * @param connections Number of connections. | ||
502 | * @param estate Encryption state. | ||
503 | * @param cstate Connectivity state. | ||
504 | */ | ||
505 | void | ||
506 | tunnels_callback (void *cls, | ||
507 | const struct GNUNET_PeerIdentity *peer, | ||
508 | unsigned int channels, | ||
509 | unsigned int connections, | ||
510 | uint16_t estate, | ||
511 | uint16_t cstate) | ||
512 | { | ||
513 | if (NULL == peer) | ||
514 | { | ||
515 | if (GNUNET_YES != monitor_connections) | ||
516 | { | ||
517 | GNUNET_SCHEDULER_shutdown(); | ||
518 | } | ||
519 | return; | ||
520 | } | ||
521 | FPRINTF (stdout, "%s [ENC: %u, CON: %u] CHs: %u, CONNs: %u\n", | ||
522 | GNUNET_i2s_full (peer), estate, cstate, channels, connections); | ||
523 | } | ||
524 | |||
525 | |||
526 | /** | ||
527 | * Method called to retrieve information about a specific tunnel the cadet peer | ||
528 | * has established, o`r is trying to establish. | ||
529 | * | ||
530 | * @param cls Closure. | ||
531 | * @param peer Peer towards whom the tunnel is directed. | ||
532 | * @param n_channels Number of channels. | ||
533 | * @param n_connections Number of connections. | ||
534 | * @param channels Channels. | ||
535 | * @param connections Connections. | ||
536 | * @param estate Encryption status. | ||
537 | * @param cstate Connectivity status. | ||
538 | */ | ||
539 | void | ||
540 | tunnel_callback (void *cls, | ||
541 | const struct GNUNET_PeerIdentity *peer, | ||
542 | unsigned int n_channels, | ||
543 | unsigned int n_connections, | ||
544 | uint32_t *channels, | ||
545 | struct GNUNET_CADET_Hash *connections, | ||
546 | unsigned int estate, | ||
547 | unsigned int cstate) | ||
548 | { | ||
549 | unsigned int i; | ||
550 | |||
551 | if (NULL != peer) | ||
552 | { | ||
553 | FPRINTF (stdout, "Tunnel %s\n", GNUNET_i2s_full (peer)); | ||
554 | FPRINTF (stdout, "- %u channels\n", n_channels); | ||
555 | for (i = 0; i < n_channels; i++) | ||
556 | FPRINTF (stdout, " %u\n", channels[i]); | ||
557 | FPRINTF (stdout, "- %u connections\n", n_connections); | ||
558 | for (i = 0; i < n_connections; i++) | ||
559 | FPRINTF (stdout, " %s\n", GM_h2s (&connections[i])); | ||
560 | FPRINTF (stdout, "- enc state: %u\n", estate); | ||
561 | FPRINTF (stdout, "- con state: %u\n", cstate); | ||
562 | } | ||
563 | if (GNUNET_YES != monitor_connections) | ||
564 | { | ||
565 | GNUNET_SCHEDULER_shutdown(); | ||
566 | } | ||
567 | return; | ||
568 | |||
569 | } | ||
570 | |||
571 | |||
572 | /** | ||
573 | * Call CADET's meta API, get all peers known to a peer. | ||
574 | * | ||
575 | * @param cls Closure (unused). | ||
576 | * @param tc TaskContext | ||
577 | */ | ||
578 | static void | ||
579 | get_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
580 | { | ||
581 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
582 | { | ||
583 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); | ||
584 | return; | ||
585 | } | ||
586 | GNUNET_CADET_get_peers (mh, &peers_callback, NULL); | ||
587 | } | ||
588 | |||
589 | |||
590 | /** | ||
591 | * Call CADET's monitor API, get info of one peer. | ||
592 | * | ||
593 | * @param cls Closure (unused). | ||
594 | * @param tc TaskContext | ||
595 | */ | ||
596 | static void | ||
597 | show_peer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
598 | { | ||
599 | struct GNUNET_PeerIdentity pid; | ||
600 | |||
601 | if (GNUNET_OK != | ||
602 | GNUNET_CRYPTO_eddsa_public_key_from_string (peer_id, | ||
603 | strlen (peer_id), | ||
604 | &pid.public_key)) | ||
605 | { | ||
606 | fprintf (stderr, | ||
607 | _("Invalid peer ID `%s'\n"), | ||
608 | peer_id); | ||
609 | GNUNET_SCHEDULER_shutdown(); | ||
610 | return; | ||
611 | } | ||
612 | GNUNET_CADET_get_peer (mh, &pid, peer_callback, NULL); | ||
613 | } | ||
614 | |||
615 | /** | ||
616 | * Call CADET's meta API, get all tunnels known to a peer. | ||
617 | * | ||
618 | * @param cls Closure (unused). | ||
619 | * @param tc TaskContext | ||
620 | */ | ||
621 | static void | ||
622 | get_tunnels (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
623 | { | ||
624 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
625 | { | ||
626 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown\n"); | ||
627 | return; | ||
628 | } | ||
629 | GNUNET_CADET_get_tunnels (mh, &tunnels_callback, NULL); | ||
630 | } | ||
631 | |||
632 | |||
633 | /** | ||
634 | * Call CADET's monitor API, get info of one tunnel. | ||
635 | * | ||
636 | * @param cls Closure (unused). | ||
637 | * @param tc TaskContext | ||
638 | */ | ||
639 | static void | ||
640 | show_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
641 | { | ||
642 | struct GNUNET_PeerIdentity pid; | ||
643 | |||
644 | if (GNUNET_OK != | ||
645 | GNUNET_CRYPTO_eddsa_public_key_from_string (tunnel_id, | ||
646 | strlen (tunnel_id), | ||
647 | &pid.public_key)) | ||
648 | { | ||
649 | fprintf (stderr, | ||
650 | _("Invalid tunnel owner `%s'\n"), | ||
651 | tunnel_id); | ||
652 | GNUNET_SCHEDULER_shutdown(); | ||
653 | return; | ||
654 | } | ||
655 | GNUNET_CADET_get_tunnel (mh, &pid, tunnel_callback, NULL); | ||
656 | } | ||
657 | |||
658 | |||
659 | /** | ||
660 | * Call CADET's monitor API, get info of one channel. | ||
661 | * | ||
662 | * @param cls Closure (unused). | ||
663 | * @param tc TaskContext | ||
664 | */ | ||
665 | static void | ||
666 | show_channel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
667 | { | ||
668 | |||
669 | } | ||
670 | |||
671 | |||
672 | /** | ||
673 | * Call CADET's monitor API, get info of one connection. | ||
674 | * | ||
675 | * @param cls Closure (unused). | ||
676 | * @param tc TaskContext | ||
677 | */ | ||
678 | static void | ||
679 | show_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
680 | { | ||
681 | |||
682 | } | ||
683 | |||
684 | |||
685 | /** | ||
686 | * Main function that will be run by the scheduler. | ||
687 | * | ||
688 | * @param cls closure | ||
689 | * @param args remaining command-line arguments | ||
690 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
691 | * @param cfg configuration | ||
692 | */ | ||
693 | static void | ||
694 | run (void *cls, char *const *args, const char *cfgfile, | ||
695 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
696 | { | ||
697 | GNUNET_CADET_InboundChannelNotificationHandler *newch = NULL; | ||
698 | GNUNET_CADET_ChannelEndHandler *endch = NULL; | ||
699 | static const struct GNUNET_CADET_MessageHandler handlers[] = { | ||
700 | {&data_callback, GNUNET_MESSAGE_TYPE_CADET_CLI, 0}, | ||
701 | {NULL, 0, 0} /* FIXME add option to monitor msg types */ | ||
702 | }; | ||
703 | static uint32_t *ports = NULL; | ||
704 | /* FIXME add option to monitor apps */ | ||
705 | |||
706 | target_id = args[0]; | ||
707 | target_port = args[0] && args[1] ? atoi(args[1]) : 0; | ||
708 | if ( (0 != (request_peers | request_tunnels) | ||
709 | || 0 != monitor_connections | ||
710 | || NULL != tunnel_id | ||
711 | || NULL != conn_id | ||
712 | || NULL != channel_id) | ||
713 | && target_id != NULL) | ||
714 | { | ||
715 | FPRINTF (stderr, | ||
716 | _("You must NOT give a TARGET" | ||
717 | "when using 'request all' options\n")); | ||
718 | return; | ||
719 | } | ||
720 | |||
721 | if (NULL != target_id) | ||
722 | { | ||
723 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
724 | "Creating channel to %s\n", | ||
725 | target_id); | ||
726 | GNUNET_SCHEDULER_add_now (&create_channel, NULL); | ||
727 | endch = &channel_ended; | ||
728 | } | ||
729 | else if (0 != listen_port) | ||
730 | { | ||
731 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Listen\n"); | ||
732 | newch = &channel_incoming; | ||
733 | endch = &channel_ended; | ||
734 | ports = GNUNET_malloc (sizeof (uint32_t) * 2); | ||
735 | ports[0] = listen_port; | ||
736 | } | ||
737 | else if (NULL != peer_id) | ||
738 | { | ||
739 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show peer\n"); | ||
740 | GNUNET_SCHEDULER_add_now (&show_peer, NULL); | ||
741 | } | ||
742 | else if (NULL != tunnel_id) | ||
743 | { | ||
744 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show tunnel\n"); | ||
745 | GNUNET_SCHEDULER_add_now (&show_tunnel, NULL); | ||
746 | } | ||
747 | else if (NULL != channel_id) | ||
748 | { | ||
749 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show channel\n"); | ||
750 | GNUNET_SCHEDULER_add_now (&show_channel, NULL); | ||
751 | } | ||
752 | else if (NULL != conn_id) | ||
753 | { | ||
754 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show connection\n"); | ||
755 | GNUNET_SCHEDULER_add_now (&show_connection, NULL); | ||
756 | } | ||
757 | else if (GNUNET_YES == request_peers) | ||
758 | { | ||
759 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all peers\n"); | ||
760 | GNUNET_SCHEDULER_add_now (&get_peers, NULL); | ||
761 | } | ||
762 | else if (GNUNET_YES == request_tunnels) | ||
763 | { | ||
764 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Show all tunnels\n"); | ||
765 | GNUNET_SCHEDULER_add_now (&get_tunnels, NULL); | ||
766 | } | ||
767 | else | ||
768 | { | ||
769 | FPRINTF (stderr, "No action requested\n"); | ||
770 | return; | ||
771 | } | ||
772 | |||
773 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to cadet\n"); | ||
774 | mh = GNUNET_CADET_connect (cfg, | ||
775 | NULL, /* cls */ | ||
776 | newch, /* new channel */ | ||
777 | endch, /* cleaner */ | ||
778 | handlers, | ||
779 | ports); | ||
780 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done\n"); | ||
781 | if (NULL == mh) | ||
782 | GNUNET_SCHEDULER_add_now (shutdown_task, NULL); | ||
783 | else | ||
784 | sd = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | ||
785 | shutdown_task, NULL); | ||
786 | |||
787 | } | ||
788 | |||
789 | |||
790 | /** | ||
791 | * The main function to obtain peer information. | ||
792 | * | ||
793 | * @param argc number of arguments from the command line | ||
794 | * @param argv command line arguments | ||
795 | * @return 0 ok, 1 on error | ||
796 | */ | ||
797 | int | ||
798 | main (int argc, char *const *argv) | ||
799 | { | ||
800 | int res; | ||
801 | const char helpstr[] = "Create channels and retreive info about cadets status."; | ||
802 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
803 | // {'a', "channel", "TUNNEL_ID:CHANNEL_ID", | ||
804 | // gettext_noop ("provide information about a particular channel"), | ||
805 | // GNUNET_YES, &GNUNET_GETOPT_set_string, &channel_id}, | ||
806 | {'C', "connection", "CONNECTION_ID", | ||
807 | gettext_noop ("provide information about a particular connection"), | ||
808 | GNUNET_YES, &GNUNET_GETOPT_set_string, &conn_id}, | ||
809 | {'e', "echo", NULL, | ||
810 | gettext_noop ("activate echo mode"), | ||
811 | GNUNET_NO, &GNUNET_GETOPT_set_one, &echo}, | ||
812 | // {'m', "monitor", NULL, | ||
813 | // gettext_noop ("provide information about all events (continuously)"), | ||
814 | // GNUNET_NO, &GNUNET_GETOPT_set_one, &monitor_mode}, | ||
815 | {'o', "open-port", NULL, | ||
816 | gettext_noop ("port to listen to (default; 0)"), | ||
817 | GNUNET_YES, &GNUNET_GETOPT_set_uint, &listen_port}, | ||
818 | {'p', "peer", "PEER_ID", | ||
819 | gettext_noop ("provide information about a patricular peer"), | ||
820 | GNUNET_YES, &GNUNET_GETOPT_set_string, &peer_id}, | ||
821 | {'P', "peers", NULL, | ||
822 | gettext_noop ("provide information about all peers"), | ||
823 | GNUNET_NO, &GNUNET_GETOPT_set_one, &request_peers}, | ||
824 | {'t', "tunnel", "TUNNEL_ID", | ||
825 | gettext_noop ("provide information about a particular tunnel"), | ||
826 | GNUNET_YES, &GNUNET_GETOPT_set_string, &tunnel_id}, | ||
827 | {'T', "tunnels", NULL, | ||
828 | gettext_noop ("provide information about all tunnels"), | ||
829 | GNUNET_NO, &GNUNET_GETOPT_set_one, &request_tunnels}, | ||
830 | |||
831 | GNUNET_GETOPT_OPTION_END | ||
832 | }; | ||
833 | |||
834 | monitor_connections = GNUNET_NO; | ||
835 | |||
836 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
837 | return 2; | ||
838 | |||
839 | res = GNUNET_PROGRAM_run (argc, argv, "gnunet-cadet (OPTIONS | TARGET PORT)", | ||
840 | gettext_noop (helpstr), | ||
841 | options, &run, NULL); | ||
842 | |||
843 | GNUNET_free ((void *) argv); | ||
844 | |||
845 | if (GNUNET_OK == res) | ||
846 | return 0; | ||
847 | else | ||
848 | return 1; | ||
849 | } | ||
850 | |||
851 | /* end of gnunet-cadet.c */ | ||
diff --git a/src/cadet/gnunet-service-cadet.c b/src/cadet/gnunet-service-cadet.c new file mode 100644 index 000000000..de9aaf7a5 --- /dev/null +++ b/src/cadet/gnunet-service-cadet.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2001-2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet.c | ||
23 | * @brief GNUnet CADET service with encryption | ||
24 | * @author Bartlomiej Polot | ||
25 | * | ||
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 | * | ||
35 | * Dictionary: | ||
36 | * - 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. | ||
41 | * - connection: path which is being used in a tunnel. | ||
42 | */ | ||
43 | |||
44 | #include "platform.h" | ||
45 | #include "gnunet_util_lib.h" | ||
46 | #include "cadet.h" | ||
47 | #include "gnunet_statistics_service.h" | ||
48 | |||
49 | #include "gnunet-service-cadet_local.h" | ||
50 | #include "gnunet-service-cadet_channel.h" | ||
51 | #include "gnunet-service-cadet_connection.h" | ||
52 | #include "gnunet-service-cadet_tunnel.h" | ||
53 | #include "gnunet-service-cadet_dht.h" | ||
54 | #include "gnunet-service-cadet_peer.h" | ||
55 | #include "gnunet-service-cadet_hello.h" | ||
56 | |||
57 | |||
58 | /******************************************************************************/ | ||
59 | /*********************** GLOBAL VARIABLES ****************************/ | ||
60 | /******************************************************************************/ | ||
61 | |||
62 | /****************************** Global variables ******************************/ | ||
63 | |||
64 | /** | ||
65 | * Handle to the statistics service. | ||
66 | */ | ||
67 | struct GNUNET_STATISTICS_Handle *stats; | ||
68 | |||
69 | /** | ||
70 | * Local peer own ID (memory efficient handle). | ||
71 | */ | ||
72 | GNUNET_PEER_Id myid; | ||
73 | |||
74 | /** | ||
75 | * Local peer own ID (full value). | ||
76 | */ | ||
77 | struct GNUNET_PeerIdentity my_full_id; | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Signal that shutdown is happening: prevent recover measures. | ||
82 | */ | ||
83 | int shutting_down; | ||
84 | |||
85 | /*************************** Static global variables **************************/ | ||
86 | |||
87 | /** | ||
88 | * Own private key. | ||
89 | */ | ||
90 | static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | ||
91 | |||
92 | |||
93 | /******************************************************************************/ | ||
94 | /************************ MAIN FUNCTIONS ****************************/ | ||
95 | /******************************************************************************/ | ||
96 | |||
97 | /** | ||
98 | * Task run during shutdown. | ||
99 | * | ||
100 | * @param cls unused | ||
101 | * @param tc unused | ||
102 | */ | ||
103 | static void | ||
104 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
105 | { | ||
106 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n"); | ||
107 | |||
108 | shutting_down = GNUNET_YES; | ||
109 | |||
110 | GML_shutdown (); | ||
111 | GMH_shutdown (); | ||
112 | GMC_shutdown (); | ||
113 | GMT_shutdown (); | ||
114 | GMD_shutdown (); | ||
115 | GMP_shutdown (); | ||
116 | |||
117 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
118 | stats = NULL; | ||
119 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n"); | ||
120 | } | ||
121 | |||
122 | |||
123 | /** | ||
124 | * Process cadet requests. | ||
125 | * | ||
126 | * @param cls closure | ||
127 | * @param server the initialized server | ||
128 | * @param c configuration to use | ||
129 | */ | ||
130 | static void | ||
131 | run (void *cls, struct GNUNET_SERVER_Handle *server, | ||
132 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
133 | { | ||
134 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n"); | ||
135 | |||
136 | stats = GNUNET_STATISTICS_create ("cadet", c); | ||
137 | |||
138 | /* Scheduled the task to clean up when shutdown is called */ | ||
139 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task, | ||
140 | NULL); | ||
141 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "reading key\n"); | ||
142 | my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c); | ||
143 | GNUNET_assert (NULL != my_private_key); | ||
144 | GNUNET_CRYPTO_eddsa_key_get_public (my_private_key, &my_full_id.public_key); | ||
145 | myid = GNUNET_PEER_intern (&my_full_id); | ||
146 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
147 | "STARTING SERVICE (CADET) for peer [%s]\n", | ||
148 | GNUNET_i2s (&my_full_id)); | ||
149 | |||
150 | GML_init (server); /* Local clients */ | ||
151 | GMH_init (c); /* Hellos */ | ||
152 | GMC_init (c); /* Connections */ | ||
153 | GMP_init (c); /* Peers */ | ||
154 | GMD_init (c); /* DHT */ | ||
155 | GMT_init (c, my_private_key); /* Tunnels */ | ||
156 | |||
157 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cadet service running\n"); | ||
158 | } | ||
159 | |||
160 | |||
161 | /** | ||
162 | * The main function for the cadet service. | ||
163 | * | ||
164 | * @param argc number of arguments from the command line | ||
165 | * @param argv command line arguments | ||
166 | * @return 0 ok, 1 on error | ||
167 | */ | ||
168 | int | ||
169 | main (int argc, char *const *argv) | ||
170 | { | ||
171 | int ret; | ||
172 | int r; | ||
173 | |||
174 | shutting_down = GNUNET_NO; | ||
175 | r = GNUNET_SERVICE_run (argc, argv, "cadet", GNUNET_SERVICE_OPTION_NONE, &run, | ||
176 | NULL); | ||
177 | GNUNET_free (my_private_key); | ||
178 | ret = (GNUNET_OK == r) ? 0 : 1; | ||
179 | |||
180 | return ret; | ||
181 | } | ||
diff --git a/src/cadet/gnunet-service-cadet_channel.c b/src/cadet/gnunet-service-cadet_channel.c new file mode 100644 index 000000000..91338d5c0 --- /dev/null +++ b/src/cadet/gnunet-service-cadet_channel.c | |||
@@ -0,0 +1,2432 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, 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" | ||
29 | |||
30 | #include "gnunet-service-cadet_channel.h" | ||
31 | #include "gnunet-service-cadet_local.h" | ||
32 | #include "gnunet-service-cadet_tunnel.h" | ||
33 | #include "gnunet-service-cadet_peer.h" | ||
34 | |||
35 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-chn",__VA_ARGS__) | ||
36 | |||
37 | #define CADET_RETRANSMIT_TIME GNUNET_TIME_relative_multiply(\ | ||
38 | GNUNET_TIME_UNIT_MILLISECONDS, 250) | ||
39 | #define CADET_RETRANSMIT_MARGIN 4 | ||
40 | |||
41 | |||
42 | /** | ||
43 | * All the states a connection can be in. | ||
44 | */ | ||
45 | enum CadetChannelState | ||
46 | { | ||
47 | /** | ||
48 | * Uninitialized status, should never appear in operation. | ||
49 | */ | ||
50 | CADET_CHANNEL_NEW, | ||
51 | |||
52 | /** | ||
53 | * Connection create message sent, waiting for ACK. | ||
54 | */ | ||
55 | CADET_CHANNEL_SENT, | ||
56 | |||
57 | /** | ||
58 | * Connection confirmed, ready to carry traffic. | ||
59 | */ | ||
60 | CADET_CHANNEL_READY, | ||
61 | }; | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Info holder for channel messages in queues. | ||
66 | */ | ||
67 | struct CadetChannelQueue | ||
68 | { | ||
69 | /** | ||
70 | * Tunnel Queue. | ||
71 | */ | ||
72 | struct CadetTunnel3Queue *tq; | ||
73 | |||
74 | /** | ||
75 | * Message type (DATA/DATA_ACK) | ||
76 | */ | ||
77 | uint16_t type; | ||
78 | |||
79 | /** | ||
80 | * Message copy (for DATAs, to start retransmission timer) | ||
81 | */ | ||
82 | struct CadetReliableMessage *copy; | ||
83 | |||
84 | /** | ||
85 | * Reliability (for DATA_ACKs, to access rel->ack_q) | ||
86 | */ | ||
87 | struct CadetChannelReliability *rel; | ||
88 | }; | ||
89 | |||
90 | |||
91 | /** | ||
92 | * Info needed to retry a message in case it gets lost. | ||
93 | */ | ||
94 | struct CadetReliableMessage | ||
95 | { | ||
96 | /** | ||
97 | * Double linked list, FIFO style | ||
98 | */ | ||
99 | struct CadetReliableMessage *next; | ||
100 | struct CadetReliableMessage *prev; | ||
101 | |||
102 | /** | ||
103 | * Type of message (payload, channel management). | ||
104 | */ | ||
105 | int16_t type; | ||
106 | |||
107 | /** | ||
108 | * Tunnel Reliability queue this message is in. | ||
109 | */ | ||
110 | struct CadetChannelReliability *rel; | ||
111 | |||
112 | /** | ||
113 | * ID of the message (ACK needed to free) | ||
114 | */ | ||
115 | uint32_t mid; | ||
116 | |||
117 | /** | ||
118 | * Tunnel Queue. | ||
119 | */ | ||
120 | struct CadetChannelQueue *chq; | ||
121 | |||
122 | /** | ||
123 | * When was this message issued (to calculate ACK delay) | ||
124 | */ | ||
125 | struct GNUNET_TIME_Absolute timestamp; | ||
126 | |||
127 | /* struct GNUNET_CADET_Data with payload */ | ||
128 | }; | ||
129 | |||
130 | |||
131 | /** | ||
132 | * Info about the traffic state for a client in a channel. | ||
133 | */ | ||
134 | struct CadetChannelReliability | ||
135 | { | ||
136 | /** | ||
137 | * Channel this is about. | ||
138 | */ | ||
139 | struct CadetChannel *ch; | ||
140 | |||
141 | /** | ||
142 | * DLL of messages sent and not yet ACK'd. | ||
143 | */ | ||
144 | struct CadetReliableMessage *head_sent; | ||
145 | struct CadetReliableMessage *tail_sent; | ||
146 | |||
147 | /** | ||
148 | * DLL of messages received out of order. | ||
149 | */ | ||
150 | struct CadetReliableMessage *head_recv; | ||
151 | struct CadetReliableMessage *tail_recv; | ||
152 | |||
153 | /** | ||
154 | * Messages received. | ||
155 | */ | ||
156 | unsigned int n_recv; | ||
157 | |||
158 | /** | ||
159 | * Next MID to use for outgoing traffic. | ||
160 | */ | ||
161 | uint32_t mid_send; | ||
162 | |||
163 | /** | ||
164 | * Next MID expected for incoming traffic. | ||
165 | */ | ||
166 | uint32_t mid_recv; | ||
167 | |||
168 | /** | ||
169 | * Handle for queued unique data CREATE, DATA_ACK. | ||
170 | */ | ||
171 | struct CadetChannelQueue *uniq; | ||
172 | |||
173 | /** | ||
174 | * Can we send data to the client? | ||
175 | */ | ||
176 | int client_ready; | ||
177 | |||
178 | /** | ||
179 | * Can the client send data to us? | ||
180 | */ | ||
181 | int client_allowed; | ||
182 | |||
183 | /** | ||
184 | * Task to resend/poll in case no ACK is received. | ||
185 | */ | ||
186 | GNUNET_SCHEDULER_TaskIdentifier retry_task; | ||
187 | |||
188 | /** | ||
189 | * Counter for exponential backoff. | ||
190 | */ | ||
191 | struct GNUNET_TIME_Relative retry_timer; | ||
192 | |||
193 | /** | ||
194 | * How long does it usually take to get an ACK. | ||
195 | */ | ||
196 | struct GNUNET_TIME_Relative expected_delay; | ||
197 | }; | ||
198 | |||
199 | |||
200 | /** | ||
201 | * Struct containing all information regarding a channel to a remote client. | ||
202 | */ | ||
203 | struct CadetChannel | ||
204 | { | ||
205 | /** | ||
206 | * Tunnel this channel is in. | ||
207 | */ | ||
208 | struct CadetTunnel3 *t; | ||
209 | |||
210 | /** | ||
211 | * Destination port of the channel. | ||
212 | */ | ||
213 | uint32_t port; | ||
214 | |||
215 | /** | ||
216 | * Global channel number ( < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
217 | */ | ||
218 | CADET_ChannelNumber gid; | ||
219 | |||
220 | /** | ||
221 | * Local tunnel number for root (owner) client. | ||
222 | * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI or 0 ) | ||
223 | */ | ||
224 | CADET_ChannelNumber lid_root; | ||
225 | |||
226 | /** | ||
227 | * Local tunnel number for local destination clients (incoming number) | ||
228 | * ( >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV or 0). | ||
229 | */ | ||
230 | CADET_ChannelNumber lid_dest; | ||
231 | |||
232 | /** | ||
233 | * Channel state. | ||
234 | */ | ||
235 | enum CadetChannelState state; | ||
236 | |||
237 | /** | ||
238 | * Is the tunnel bufferless (minimum latency)? | ||
239 | */ | ||
240 | int nobuffer; | ||
241 | |||
242 | /** | ||
243 | * Is the tunnel reliable? | ||
244 | */ | ||
245 | int reliable; | ||
246 | |||
247 | /** | ||
248 | * Last time the channel was used | ||
249 | */ | ||
250 | struct GNUNET_TIME_Absolute timestamp; | ||
251 | |||
252 | /** | ||
253 | * Client owner of the tunnel, if any | ||
254 | */ | ||
255 | struct CadetClient *root; | ||
256 | |||
257 | /** | ||
258 | * Client destination of the tunnel, if any. | ||
259 | */ | ||
260 | struct CadetClient *dest; | ||
261 | |||
262 | /** | ||
263 | * Flag to signal the destruction of the channel. | ||
264 | * If this is set GNUNET_YES the channel will be destroyed | ||
265 | * when the queue is empty. | ||
266 | */ | ||
267 | int destroy; | ||
268 | |||
269 | /** | ||
270 | * Total (reliable) messages pending ACK for this channel. | ||
271 | */ | ||
272 | unsigned int pending_messages; | ||
273 | |||
274 | /** | ||
275 | * Reliability data. | ||
276 | * Only present (non-NULL) at the owner of a tunnel. | ||
277 | */ | ||
278 | struct CadetChannelReliability *root_rel; | ||
279 | |||
280 | /** | ||
281 | * Reliability data. | ||
282 | * Only present (non-NULL) at the destination of a tunnel. | ||
283 | */ | ||
284 | struct CadetChannelReliability *dest_rel; | ||
285 | |||
286 | }; | ||
287 | |||
288 | |||
289 | /******************************************************************************/ | ||
290 | /******************************* GLOBALS ***********************************/ | ||
291 | /******************************************************************************/ | ||
292 | |||
293 | /** | ||
294 | * Global handle to the statistics service. | ||
295 | */ | ||
296 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
297 | |||
298 | /** | ||
299 | * Local peer own ID (memory efficient handle). | ||
300 | */ | ||
301 | extern GNUNET_PEER_Id myid; | ||
302 | |||
303 | |||
304 | /******************************************************************************/ | ||
305 | /******************************** STATIC ***********************************/ | ||
306 | /******************************************************************************/ | ||
307 | |||
308 | /** | ||
309 | * Destroy a reliable message after it has been acknowledged, either by | ||
310 | * direct mid ACK or bitfield. Updates the appropriate data structures and | ||
311 | * timers and frees all memory. | ||
312 | * | ||
313 | * @param copy Message that is no longer needed: remote peer got it. | ||
314 | * @param update_time Is the timing information relevant? | ||
315 | * If this message is ACK in a batch the timing information | ||
316 | * is skewed by the retransmission, count only for the | ||
317 | * retransmitted message. | ||
318 | */ | ||
319 | static int | ||
320 | rel_message_free (struct CadetReliableMessage *copy, int update_time); | ||
321 | |||
322 | /** | ||
323 | * send a channel create message. | ||
324 | * | ||
325 | * @param ch Channel for which to send. | ||
326 | */ | ||
327 | static void | ||
328 | send_create (struct CadetChannel *ch); | ||
329 | |||
330 | /** | ||
331 | * Confirm we got a channel create, FWD ack. | ||
332 | * | ||
333 | * @param ch The channel to confirm. | ||
334 | * @param fwd Should we send a FWD ACK? (going dest->root) | ||
335 | * @param reaction This ACK is a reaction to a duplicate CREATE, don't save. | ||
336 | */ | ||
337 | static void | ||
338 | send_ack (struct CadetChannel *ch, int fwd, int reaction); | ||
339 | |||
340 | |||
341 | |||
342 | /** | ||
343 | * Test if the channel is loopback: both root and dest are on the local peer. | ||
344 | * | ||
345 | * @param ch Channel to test. | ||
346 | * | ||
347 | * @return #GNUNET_YES if channel is loopback, #GNUNET_NO otherwise. | ||
348 | */ | ||
349 | static int | ||
350 | is_loopback (const struct CadetChannel *ch) | ||
351 | { | ||
352 | if (NULL != ch->t) | ||
353 | return GMT_is_loopback (ch->t); | ||
354 | |||
355 | return (NULL != ch->root && NULL != ch->dest); | ||
356 | } | ||
357 | |||
358 | |||
359 | /** | ||
360 | * Save a copy of the data message for later retransmission. | ||
361 | * | ||
362 | * @param msg Message to copy. | ||
363 | * @param mid Message ID. | ||
364 | * @param rel Reliability data for retransmission. | ||
365 | */ | ||
366 | static struct CadetReliableMessage * | ||
367 | copy_message (const struct GNUNET_CADET_Data *msg, uint32_t mid, | ||
368 | struct CadetChannelReliability *rel) | ||
369 | { | ||
370 | struct CadetReliableMessage *copy; | ||
371 | uint16_t size; | ||
372 | |||
373 | size = ntohs (msg->header.size); | ||
374 | copy = GNUNET_malloc (sizeof (*copy) + size); | ||
375 | copy->mid = mid; | ||
376 | copy->rel = rel; | ||
377 | copy->type = GNUNET_MESSAGE_TYPE_CADET_DATA; | ||
378 | memcpy (©[1], msg, size); | ||
379 | |||
380 | return copy; | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * We have received a message out of order, or the client is not ready. | ||
385 | * Buffer it until we receive an ACK from the client or the missing | ||
386 | * message from the channel. | ||
387 | * | ||
388 | * @param msg Message to buffer (MUST be of type CADET_DATA). | ||
389 | * @param rel Reliability data to the corresponding direction. | ||
390 | */ | ||
391 | static void | ||
392 | add_buffered_data (const struct GNUNET_CADET_Data *msg, | ||
393 | struct CadetChannelReliability *rel) | ||
394 | { | ||
395 | struct CadetReliableMessage *copy; | ||
396 | struct CadetReliableMessage *prev; | ||
397 | uint32_t mid; | ||
398 | |||
399 | mid = ntohl (msg->mid); | ||
400 | |||
401 | LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data %u\n", mid); | ||
402 | |||
403 | rel->n_recv++; | ||
404 | |||
405 | // FIXME do something better than O(n), although n < 64... | ||
406 | // FIXME start from the end (most messages are the latest ones) | ||
407 | for (prev = rel->head_recv; NULL != prev; prev = prev->next) | ||
408 | { | ||
409 | LOG (GNUNET_ERROR_TYPE_DEBUG, " prev %u\n", prev->mid); | ||
410 | if (prev->mid == mid) | ||
411 | { | ||
412 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already there!\n"); | ||
413 | return; | ||
414 | } | ||
415 | else if (GM_is_pid_bigger (prev->mid, mid)) | ||
416 | { | ||
417 | LOG (GNUNET_ERROR_TYPE_DEBUG, " bingo!\n"); | ||
418 | copy = copy_message (msg, mid, rel); | ||
419 | GNUNET_CONTAINER_DLL_insert_before (rel->head_recv, rel->tail_recv, | ||
420 | prev, copy); | ||
421 | return; | ||
422 | } | ||
423 | } | ||
424 | copy = copy_message (msg, mid, rel); | ||
425 | LOG (GNUNET_ERROR_TYPE_DEBUG, " insert at tail!\n"); | ||
426 | GNUNET_CONTAINER_DLL_insert_tail (rel->head_recv, rel->tail_recv, copy); | ||
427 | LOG (GNUNET_ERROR_TYPE_DEBUG, "add_buffered_data END\n"); | ||
428 | } | ||
429 | |||
430 | |||
431 | /** | ||
432 | * Add a destination client to a channel, initializing all data structures | ||
433 | * in the channel and the client. | ||
434 | * | ||
435 | * @param ch Channel to which add the destination. | ||
436 | * @param c Client which to add to the channel. | ||
437 | */ | ||
438 | static void | ||
439 | add_destination (struct CadetChannel *ch, struct CadetClient *c) | ||
440 | { | ||
441 | if (NULL != ch->dest) | ||
442 | { | ||
443 | GNUNET_break (0); | ||
444 | return; | ||
445 | } | ||
446 | |||
447 | /* Assign local id as destination */ | ||
448 | ch->lid_dest = GML_get_next_chid (c); | ||
449 | |||
450 | /* Store in client's hashmap */ | ||
451 | GML_channel_add (c, ch->lid_dest, ch); | ||
452 | |||
453 | GNUNET_break (NULL == ch->dest_rel); | ||
454 | ch->dest_rel = GNUNET_new (struct CadetChannelReliability); | ||
455 | ch->dest_rel->ch = ch; | ||
456 | ch->dest_rel->expected_delay.rel_value_us = 0; | ||
457 | ch->dest_rel->retry_timer = CADET_RETRANSMIT_TIME; | ||
458 | |||
459 | ch->dest = c; | ||
460 | } | ||
461 | |||
462 | |||
463 | /** | ||
464 | * Set options in a channel, extracted from a bit flag field. | ||
465 | * | ||
466 | * @param ch Channel to set options to. | ||
467 | * @param options Bit array in host byte order. | ||
468 | */ | ||
469 | static void | ||
470 | channel_set_options (struct CadetChannel *ch, uint32_t options) | ||
471 | { | ||
472 | ch->nobuffer = (options & GNUNET_CADET_OPTION_NOBUFFER) != 0 ? | ||
473 | GNUNET_YES : GNUNET_NO; | ||
474 | ch->reliable = (options & GNUNET_CADET_OPTION_RELIABLE) != 0 ? | ||
475 | GNUNET_YES : GNUNET_NO; | ||
476 | } | ||
477 | |||
478 | |||
479 | /** | ||
480 | * Get a bit flag field with the options of a channel. | ||
481 | * | ||
482 | * @param ch Channel to get options from. | ||
483 | * | ||
484 | * @return Bit array in host byte order. | ||
485 | */ | ||
486 | static uint32_t | ||
487 | channel_get_options (struct CadetChannel *ch) | ||
488 | { | ||
489 | uint32_t options; | ||
490 | |||
491 | options = 0; | ||
492 | if (ch->nobuffer) | ||
493 | options |= GNUNET_CADET_OPTION_NOBUFFER; | ||
494 | if (ch->reliable) | ||
495 | options |= GNUNET_CADET_OPTION_RELIABLE; | ||
496 | |||
497 | return options; | ||
498 | } | ||
499 | |||
500 | |||
501 | /** | ||
502 | * Notify a client that the channel is no longer valid. | ||
503 | * | ||
504 | * @param ch Channel that is destroyed. | ||
505 | * @param local_only Should we avoid sending it to other peers? | ||
506 | */ | ||
507 | static void | ||
508 | send_destroy (struct CadetChannel *ch, int local_only) | ||
509 | { | ||
510 | struct GNUNET_CADET_ChannelManage msg; | ||
511 | |||
512 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); | ||
513 | msg.header.size = htons (sizeof (msg)); | ||
514 | msg.chid = htonl (ch->gid); | ||
515 | |||
516 | /* If root is not NULL, notify. | ||
517 | * If it's NULL, check lid_root. When a local destroy comes in, root | ||
518 | * is set to NULL but lid_root is left untouched. In this case, do nothing, | ||
519 | * the client is the one who requested the channel to be destroyed. | ||
520 | */ | ||
521 | if (NULL != ch->root) | ||
522 | GML_send_channel_destroy (ch->root, ch->lid_root); | ||
523 | else if (0 == ch->lid_root && GNUNET_NO == local_only) | ||
524 | GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL); | ||
525 | |||
526 | if (NULL != ch->dest) | ||
527 | GML_send_channel_destroy (ch->dest, ch->lid_dest); | ||
528 | else if (0 == ch->lid_dest && GNUNET_NO == local_only) | ||
529 | GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_YES, NULL); | ||
530 | } | ||
531 | |||
532 | |||
533 | /** | ||
534 | * Notify the destination client that a new incoming channel was created. | ||
535 | * | ||
536 | * @param ch Channel that was created. | ||
537 | */ | ||
538 | static void | ||
539 | send_client_create (struct CadetChannel *ch) | ||
540 | { | ||
541 | uint32_t opt; | ||
542 | |||
543 | if (NULL == ch->dest) | ||
544 | return; | ||
545 | |||
546 | opt = 0; | ||
547 | opt |= GNUNET_YES == ch->reliable ? GNUNET_CADET_OPTION_RELIABLE : 0; | ||
548 | opt |= GNUNET_YES == ch->nobuffer ? GNUNET_CADET_OPTION_NOBUFFER : 0; | ||
549 | GML_send_channel_create (ch->dest, ch->lid_dest, ch->port, opt, | ||
550 | GMT_get_destination (ch->t)); | ||
551 | |||
552 | } | ||
553 | |||
554 | |||
555 | /** | ||
556 | * Send data to a client. | ||
557 | * | ||
558 | * If the client is ready, send directly, otherwise buffer while listening | ||
559 | * for a local ACK. | ||
560 | * | ||
561 | * @param ch Channel | ||
562 | * @param msg Message. | ||
563 | * @param fwd Is this a fwd (root->dest) message? | ||
564 | */ | ||
565 | static void | ||
566 | send_client_data (struct CadetChannel *ch, | ||
567 | const struct GNUNET_CADET_Data *msg, | ||
568 | int fwd) | ||
569 | { | ||
570 | if (fwd) | ||
571 | { | ||
572 | if (ch->dest_rel->client_ready) | ||
573 | GML_send_data (ch->dest, msg, ch->lid_dest); | ||
574 | else | ||
575 | add_buffered_data (msg, ch->dest_rel); | ||
576 | } | ||
577 | else | ||
578 | { | ||
579 | if (ch->root_rel->client_ready) | ||
580 | GML_send_data (ch->root, msg, ch->lid_root); | ||
581 | else | ||
582 | add_buffered_data (msg, ch->root_rel); | ||
583 | } | ||
584 | } | ||
585 | |||
586 | |||
587 | /** | ||
588 | * Send a buffered message to the client, for in order delivery or | ||
589 | * as result of client ACK. | ||
590 | * | ||
591 | * @param ch Channel on which to empty the message buffer. | ||
592 | * @param c Client to send to. | ||
593 | * @param fwd Is this to send FWD data?. | ||
594 | */ | ||
595 | static void | ||
596 | send_client_buffered_data (struct CadetChannel *ch, | ||
597 | struct CadetClient *c, | ||
598 | int fwd) | ||
599 | { | ||
600 | struct CadetReliableMessage *copy; | ||
601 | struct CadetChannelReliability *rel; | ||
602 | |||
603 | LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data\n"); | ||
604 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
605 | if (GNUNET_NO == rel->client_ready) | ||
606 | { | ||
607 | LOG (GNUNET_ERROR_TYPE_DEBUG, "client not ready\n"); | ||
608 | return; | ||
609 | } | ||
610 | |||
611 | copy = rel->head_recv; | ||
612 | /* We never buffer channel management messages */ | ||
613 | if (NULL != copy) | ||
614 | { | ||
615 | if (copy->mid == rel->mid_recv || GNUNET_NO == ch->reliable) | ||
616 | { | ||
617 | struct GNUNET_CADET_Data *msg = (struct GNUNET_CADET_Data *) ©[1]; | ||
618 | |||
619 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
620 | " have %u! now expecting %u\n", | ||
621 | copy->mid, rel->mid_recv + 1); | ||
622 | send_client_data (ch, msg, fwd); | ||
623 | rel->n_recv--; | ||
624 | rel->mid_recv++; | ||
625 | GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy); | ||
626 | LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE RECV %p\n", copy); | ||
627 | GNUNET_free (copy); | ||
628 | } | ||
629 | else | ||
630 | { | ||
631 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
632 | " reliable && don't have %u, next is %u\n", | ||
633 | rel->mid_recv, | ||
634 | copy->mid); | ||
635 | if (GNUNET_YES == ch->destroy) | ||
636 | { | ||
637 | /* We don't have the next data piece and the remote peer has closed the | ||
638 | * channel. We won't receive it anymore, so just destroy the channel. | ||
639 | * FIXME: wait some time to allow other connections to | ||
640 | * deliver missing messages | ||
641 | */ | ||
642 | send_destroy (ch, GNUNET_YES); | ||
643 | GMCH_destroy (ch); | ||
644 | } | ||
645 | } | ||
646 | } | ||
647 | LOG (GNUNET_ERROR_TYPE_DEBUG, "send_buffered_data END\n"); | ||
648 | } | ||
649 | |||
650 | |||
651 | /** | ||
652 | * Allow a client to send more data. | ||
653 | * | ||
654 | * In case the client was already allowed to send data, do nothing. | ||
655 | * | ||
656 | * @param ch Channel. | ||
657 | * @param fwd Is this a FWD ACK? (FWD ACKs are sent to root) | ||
658 | */ | ||
659 | static void | ||
660 | send_client_ack (struct CadetChannel *ch, int fwd) | ||
661 | { | ||
662 | struct CadetChannelReliability *rel = fwd ? ch->root_rel : ch->dest_rel; | ||
663 | struct CadetClient *c = fwd ? ch->root : ch->dest; | ||
664 | |||
665 | if (NULL == c) | ||
666 | { | ||
667 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
668 | return; | ||
669 | } | ||
670 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
671 | " sending %s ack to client on channel %s\n", | ||
672 | GM_f2s (fwd), GMCH_2s (ch)); | ||
673 | |||
674 | if (NULL == rel) | ||
675 | { | ||
676 | GNUNET_break (0); | ||
677 | return; | ||
678 | } | ||
679 | |||
680 | if (GNUNET_YES == rel->client_allowed) | ||
681 | { | ||
682 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already allowed\n"); | ||
683 | return; | ||
684 | } | ||
685 | rel->client_allowed = GNUNET_YES; | ||
686 | |||
687 | GML_send_ack (c, fwd ? ch->lid_root : ch->lid_dest); | ||
688 | } | ||
689 | |||
690 | |||
691 | /** | ||
692 | * Notify the root that the destination rejected the channel. | ||
693 | * | ||
694 | * @param ch Rejected channel. | ||
695 | */ | ||
696 | static void | ||
697 | send_client_nack (struct CadetChannel *ch) | ||
698 | { | ||
699 | if (NULL == ch->root) | ||
700 | { | ||
701 | GNUNET_break (0); | ||
702 | return; | ||
703 | } | ||
704 | GML_send_channel_nack (ch->root, ch->lid_root); | ||
705 | } | ||
706 | |||
707 | |||
708 | /** | ||
709 | * We haven't received an ACK after a certain time: restransmit the message. | ||
710 | * | ||
711 | * @param cls Closure (CadetChannelReliability with the message to restransmit) | ||
712 | * @param tc TaskContext. | ||
713 | */ | ||
714 | static void | ||
715 | channel_retransmit_message (void *cls, | ||
716 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
717 | { | ||
718 | struct CadetChannelReliability *rel = cls; | ||
719 | struct CadetReliableMessage *copy; | ||
720 | struct CadetChannel *ch; | ||
721 | struct GNUNET_CADET_Data *payload; | ||
722 | int fwd; | ||
723 | |||
724 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
725 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
726 | return; | ||
727 | |||
728 | ch = rel->ch; | ||
729 | copy = rel->head_sent; | ||
730 | if (NULL == copy) | ||
731 | { | ||
732 | GNUNET_break (0); | ||
733 | return; | ||
734 | } | ||
735 | |||
736 | payload = (struct GNUNET_CADET_Data *) ©[1]; | ||
737 | fwd = (rel == ch->root_rel); | ||
738 | |||
739 | /* Message not found in the queue that we are going to use. */ | ||
740 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RETRANSMIT %u\n", copy->mid); | ||
741 | |||
742 | GMCH_send_prebuilt_message (&payload->header, ch, fwd, copy); | ||
743 | GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO); | ||
744 | } | ||
745 | |||
746 | |||
747 | /** | ||
748 | * We haven't received an Channel ACK after a certain time: resend the CREATE. | ||
749 | * | ||
750 | * @param cls Closure (CadetChannelReliability of the channel to recreate) | ||
751 | * @param tc TaskContext. | ||
752 | */ | ||
753 | static void | ||
754 | channel_recreate (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
755 | { | ||
756 | struct CadetChannelReliability *rel = cls; | ||
757 | |||
758 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
759 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
760 | return; | ||
761 | |||
762 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! RE-CREATE\n"); | ||
763 | GNUNET_STATISTICS_update (stats, "# data retransmitted", 1, GNUNET_NO); | ||
764 | |||
765 | if (rel == rel->ch->root_rel) | ||
766 | { | ||
767 | send_create (rel->ch); | ||
768 | } | ||
769 | else if (rel == rel->ch->dest_rel) | ||
770 | { | ||
771 | send_ack (rel->ch, GNUNET_YES, GNUNET_NO); | ||
772 | } | ||
773 | else | ||
774 | { | ||
775 | GNUNET_break (0); | ||
776 | } | ||
777 | |||
778 | } | ||
779 | |||
780 | |||
781 | /** | ||
782 | * Message has been sent: start retransmission timer. | ||
783 | * | ||
784 | * @param cls Closure (queue structure). | ||
785 | * @param t Tunnel. | ||
786 | * @param q Queue handler (no longer valid). | ||
787 | * @param type Type of message. | ||
788 | * @param size Size of the message. | ||
789 | */ | ||
790 | static void | ||
791 | ch_message_sent (void *cls, | ||
792 | struct CadetTunnel3 *t, | ||
793 | struct CadetTunnel3Queue *q, | ||
794 | uint16_t type, size_t size) | ||
795 | { | ||
796 | struct CadetChannelQueue *chq = cls; | ||
797 | struct CadetReliableMessage *copy = chq->copy; | ||
798 | struct CadetChannelReliability *rel; | ||
799 | |||
800 | LOG (GNUNET_ERROR_TYPE_DEBUG, "channel message sent callback %s\n", | ||
801 | GM_m2s (chq->type)); | ||
802 | |||
803 | switch (chq->type) | ||
804 | { | ||
805 | case GNUNET_MESSAGE_TYPE_CADET_DATA: | ||
806 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SENT DATA MID %u\n", copy->mid); | ||
807 | GNUNET_assert (chq == copy->chq); | ||
808 | copy->timestamp = GNUNET_TIME_absolute_get (); | ||
809 | rel = copy->rel; | ||
810 | if (GNUNET_SCHEDULER_NO_TASK == rel->retry_task) | ||
811 | { | ||
812 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!! scheduling retry in 4 * %s\n", | ||
813 | GNUNET_STRINGS_relative_time_to_string (rel->expected_delay, | ||
814 | GNUNET_YES)); | ||
815 | if (0 != rel->expected_delay.rel_value_us) | ||
816 | { | ||
817 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!! delay != 0\n"); | ||
818 | rel->retry_timer = | ||
819 | GNUNET_TIME_relative_multiply (rel->expected_delay, | ||
820 | CADET_RETRANSMIT_MARGIN); | ||
821 | } | ||
822 | else | ||
823 | { | ||
824 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!! delay reset\n"); | ||
825 | rel->retry_timer = CADET_RETRANSMIT_TIME; | ||
826 | } | ||
827 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!! using delay %s\n", | ||
828 | GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, | ||
829 | GNUNET_NO)); | ||
830 | rel->retry_task = | ||
831 | GNUNET_SCHEDULER_add_delayed (rel->retry_timer, | ||
832 | &channel_retransmit_message, rel); | ||
833 | } | ||
834 | else | ||
835 | { | ||
836 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!! retry task %u\n", rel->retry_task); | ||
837 | } | ||
838 | copy->chq = NULL; | ||
839 | break; | ||
840 | |||
841 | |||
842 | case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: | ||
843 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
844 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: | ||
845 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SENT %s\n", GM_m2s (chq->type)); | ||
846 | rel = chq->rel; | ||
847 | GNUNET_assert (rel->uniq == chq); | ||
848 | rel->uniq = NULL; | ||
849 | |||
850 | if (CADET_CHANNEL_READY != rel->ch->state | ||
851 | && GNUNET_MESSAGE_TYPE_CADET_DATA_ACK != type | ||
852 | && GNUNET_NO == rel->ch->destroy) | ||
853 | { | ||
854 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rel->retry_task); | ||
855 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! STD BACKOFF %s\n", | ||
856 | GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, | ||
857 | GNUNET_NO)); | ||
858 | rel->retry_timer = GNUNET_TIME_STD_BACKOFF (rel->retry_timer); | ||
859 | rel->retry_task = GNUNET_SCHEDULER_add_delayed (rel->retry_timer, | ||
860 | &channel_recreate, rel); | ||
861 | } | ||
862 | break; | ||
863 | |||
864 | default: | ||
865 | GNUNET_break (0); | ||
866 | } | ||
867 | |||
868 | GNUNET_free (chq); | ||
869 | } | ||
870 | |||
871 | |||
872 | /** | ||
873 | * send a channel create message. | ||
874 | * | ||
875 | * @param ch Channel for which to send. | ||
876 | */ | ||
877 | static void | ||
878 | send_create (struct CadetChannel *ch) | ||
879 | { | ||
880 | struct GNUNET_CADET_ChannelCreate msgcc; | ||
881 | |||
882 | msgcc.header.size = htons (sizeof (msgcc)); | ||
883 | msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE); | ||
884 | msgcc.chid = htonl (ch->gid); | ||
885 | msgcc.port = htonl (ch->port); | ||
886 | msgcc.opt = htonl (channel_get_options (ch)); | ||
887 | |||
888 | GMCH_send_prebuilt_message (&msgcc.header, ch, GNUNET_YES, NULL); | ||
889 | } | ||
890 | |||
891 | |||
892 | /** | ||
893 | * Confirm we got a channel create or FWD ack. | ||
894 | * | ||
895 | * @param ch The channel to confirm. | ||
896 | * @param fwd Should we send a FWD ACK? (going dest->root) | ||
897 | * @param reaction This ACK is a reaction to a duplicate CREATE, don't save. | ||
898 | */ | ||
899 | static void | ||
900 | send_ack (struct CadetChannel *ch, int fwd, int reaction) | ||
901 | { | ||
902 | struct GNUNET_CADET_ChannelManage msg; | ||
903 | |||
904 | msg.header.size = htons (sizeof (msg)); | ||
905 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK); | ||
906 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending channel %s ack for channel %s\n", | ||
907 | GM_f2s (fwd), GMCH_2s (ch)); | ||
908 | |||
909 | msg.chid = htonl (ch->gid); | ||
910 | GMCH_send_prebuilt_message (&msg.header, ch, !fwd, reaction ? &msg : NULL); | ||
911 | } | ||
912 | |||
913 | |||
914 | /** | ||
915 | * Send a message and don't keep any info about it: we won't need to cancel it | ||
916 | * or resend it. | ||
917 | * | ||
918 | * @param msg Header of the message to fire away. | ||
919 | * @param ch Channel on which the message should go. | ||
920 | * @param force Is this a forced (undroppable) message? | ||
921 | */ | ||
922 | static void | ||
923 | fire_and_forget (const struct GNUNET_MessageHeader *msg, | ||
924 | struct CadetChannel *ch, | ||
925 | int force) | ||
926 | { | ||
927 | GNUNET_break (NULL == GMT_send_prebuilt_message (msg, ch->t, NULL, | ||
928 | force, NULL, NULL)); | ||
929 | } | ||
930 | |||
931 | |||
932 | /** | ||
933 | * Notify that a channel create didn't succeed. | ||
934 | * | ||
935 | * @param ch The channel to reject. | ||
936 | */ | ||
937 | static void | ||
938 | send_nack (struct CadetChannel *ch) | ||
939 | { | ||
940 | struct GNUNET_CADET_ChannelManage msg; | ||
941 | |||
942 | msg.header.size = htons (sizeof (msg)); | ||
943 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK); | ||
944 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
945 | " sending channel NACK for channel %s\n", | ||
946 | GMCH_2s (ch)); | ||
947 | |||
948 | msg.chid = htonl (ch->gid); | ||
949 | GMCH_send_prebuilt_message (&msg.header, ch, GNUNET_NO, NULL); | ||
950 | } | ||
951 | |||
952 | |||
953 | /** | ||
954 | * Destroy all reliable messages queued for a channel, | ||
955 | * during a channel destruction. | ||
956 | * Frees the reliability structure itself. | ||
957 | * | ||
958 | * @param rel Reliability data for a channel. | ||
959 | */ | ||
960 | static void | ||
961 | channel_rel_free_all (struct CadetChannelReliability *rel) | ||
962 | { | ||
963 | struct CadetReliableMessage *copy; | ||
964 | struct CadetReliableMessage *next; | ||
965 | |||
966 | if (NULL == rel) | ||
967 | return; | ||
968 | |||
969 | for (copy = rel->head_recv; NULL != copy; copy = next) | ||
970 | { | ||
971 | next = copy->next; | ||
972 | GNUNET_CONTAINER_DLL_remove (rel->head_recv, rel->tail_recv, copy); | ||
973 | LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE BATCH RECV %p\n", copy); | ||
974 | GNUNET_break (NULL == copy->chq); | ||
975 | GNUNET_free (copy); | ||
976 | } | ||
977 | for (copy = rel->head_sent; NULL != copy; copy = next) | ||
978 | { | ||
979 | next = copy->next; | ||
980 | GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy); | ||
981 | LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE BATCH %p\n", copy); | ||
982 | if (NULL != copy->chq) | ||
983 | { | ||
984 | if (NULL != copy->chq->tq) | ||
985 | { | ||
986 | GMT_cancel (copy->chq->tq); | ||
987 | /* ch_message_sent will free copy->q */ | ||
988 | } | ||
989 | else | ||
990 | { | ||
991 | GNUNET_free (copy->chq); | ||
992 | GNUNET_break (0); | ||
993 | } | ||
994 | } | ||
995 | GNUNET_free (copy); | ||
996 | } | ||
997 | if (NULL != rel->uniq && NULL != rel->uniq->tq) | ||
998 | { | ||
999 | GMT_cancel (rel->uniq->tq); | ||
1000 | /* ch_message_sent is called freeing uniq */ | ||
1001 | } | ||
1002 | if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task) | ||
1003 | { | ||
1004 | GNUNET_SCHEDULER_cancel (rel->retry_task); | ||
1005 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
1006 | } | ||
1007 | GNUNET_free (rel); | ||
1008 | } | ||
1009 | |||
1010 | |||
1011 | /** | ||
1012 | * Mark future messages as ACK'd. | ||
1013 | * | ||
1014 | * @param rel Reliability data. | ||
1015 | * @param msg DataACK message with a bitfield of future ACK'd messages. | ||
1016 | */ | ||
1017 | static void | ||
1018 | channel_rel_free_sent (struct CadetChannelReliability *rel, | ||
1019 | const struct GNUNET_CADET_DataACK *msg) | ||
1020 | { | ||
1021 | struct CadetReliableMessage *copy; | ||
1022 | struct CadetReliableMessage *next; | ||
1023 | uint64_t bitfield; | ||
1024 | uint64_t mask; | ||
1025 | uint32_t mid; | ||
1026 | uint32_t target; | ||
1027 | unsigned int i; | ||
1028 | |||
1029 | bitfield = msg->futures; | ||
1030 | mid = ntohl (msg->mid); | ||
1031 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1032 | "!!! free_sent_reliable %u %llX\n", | ||
1033 | mid, bitfield); | ||
1034 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1035 | " rel %p, head %p\n", | ||
1036 | rel, rel->head_sent); | ||
1037 | for (i = 0, copy = rel->head_sent; | ||
1038 | i < 64 && NULL != copy && 0 != bitfield; | ||
1039 | i++) | ||
1040 | { | ||
1041 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1042 | " trying bit %u (mid %u)\n", | ||
1043 | i, mid + i + 1); | ||
1044 | mask = 0x1LL << i; | ||
1045 | if (0 == (bitfield & mask)) | ||
1046 | continue; | ||
1047 | |||
1048 | LOG (GNUNET_ERROR_TYPE_DEBUG, " set!\n"); | ||
1049 | /* Bit was set, clear the bit from the bitfield */ | ||
1050 | bitfield &= ~mask; | ||
1051 | |||
1052 | /* The i-th bit was set. Do we have that copy? */ | ||
1053 | /* Skip copies with mid < target */ | ||
1054 | target = mid + i + 1; | ||
1055 | LOG (GNUNET_ERROR_TYPE_DEBUG, " target %u\n", target); | ||
1056 | while (NULL != copy && GM_is_pid_bigger (target, copy->mid)) | ||
1057 | copy = copy->next; | ||
1058 | |||
1059 | /* Did we run out of copies? (previously freed, it's ok) */ | ||
1060 | if (NULL == copy) | ||
1061 | { | ||
1062 | LOG (GNUNET_ERROR_TYPE_DEBUG, "run out of copies...\n"); | ||
1063 | return; | ||
1064 | } | ||
1065 | |||
1066 | /* Did we overshoot the target? (previously freed, it's ok) */ | ||
1067 | if (GM_is_pid_bigger (copy->mid, target)) | ||
1068 | { | ||
1069 | LOG (GNUNET_ERROR_TYPE_DEBUG, " next copy %u\n", copy->mid); | ||
1070 | continue; | ||
1071 | } | ||
1072 | |||
1073 | /* Now copy->mid == target, free it */ | ||
1074 | next = copy->next; | ||
1075 | GNUNET_break (GNUNET_YES != rel_message_free (copy, GNUNET_YES)); | ||
1076 | copy = next; | ||
1077 | } | ||
1078 | LOG (GNUNET_ERROR_TYPE_DEBUG, "free_sent_reliable END\n"); | ||
1079 | } | ||
1080 | |||
1081 | |||
1082 | /** | ||
1083 | * Destroy a reliable message after it has been acknowledged, either by | ||
1084 | * direct mid ACK or bitfield. Updates the appropriate data structures and | ||
1085 | * timers and frees all memory. | ||
1086 | * | ||
1087 | * @param copy Message that is no longer needed: remote peer got it. | ||
1088 | * @param update_time Is the timing information relevant? | ||
1089 | * If this message is ACK in a batch the timing information | ||
1090 | * is skewed by the retransmission, count only for the | ||
1091 | * retransmitted message. | ||
1092 | * | ||
1093 | * @return #GNUNET_YES if channel was destroyed as a result of the call, | ||
1094 | * #GNUNET_NO otherwise. | ||
1095 | */ | ||
1096 | static int | ||
1097 | rel_message_free (struct CadetReliableMessage *copy, int update_time) | ||
1098 | { | ||
1099 | struct CadetChannelReliability *rel; | ||
1100 | struct GNUNET_TIME_Relative time; | ||
1101 | |||
1102 | rel = copy->rel; | ||
1103 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Freeing %u\n", copy->mid); | ||
1104 | if (update_time) | ||
1105 | { | ||
1106 | time = GNUNET_TIME_absolute_get_duration (copy->timestamp); | ||
1107 | if (0 == rel->expected_delay.rel_value_us) | ||
1108 | rel->expected_delay = time; | ||
1109 | else | ||
1110 | { | ||
1111 | rel->expected_delay.rel_value_us *= 7; | ||
1112 | rel->expected_delay.rel_value_us += time.rel_value_us; | ||
1113 | rel->expected_delay.rel_value_us /= 8; | ||
1114 | } | ||
1115 | LOG (GNUNET_ERROR_TYPE_INFO, "!!! took %s, new delay %s\n", | ||
1116 | GNUNET_STRINGS_relative_time_to_string (time, GNUNET_NO), | ||
1117 | GNUNET_STRINGS_relative_time_to_string (rel->expected_delay, | ||
1118 | GNUNET_NO)); | ||
1119 | rel->retry_timer = rel->expected_delay; | ||
1120 | } | ||
1121 | else | ||
1122 | { | ||
1123 | LOG (GNUNET_ERROR_TYPE_INFO, "!!! batch free, ignoring timing\n"); | ||
1124 | } | ||
1125 | rel->ch->pending_messages--; | ||
1126 | if (NULL != copy->chq) | ||
1127 | { | ||
1128 | GMT_cancel (copy->chq->tq); | ||
1129 | /* copy->q is set to NULL by ch_message_sent */ | ||
1130 | } | ||
1131 | GNUNET_CONTAINER_DLL_remove (rel->head_sent, rel->tail_sent, copy); | ||
1132 | LOG (GNUNET_ERROR_TYPE_DEBUG, " COPYFREE %p\n", copy); | ||
1133 | GNUNET_free (copy); | ||
1134 | |||
1135 | if (GNUNET_NO != rel->ch->destroy && 0 == rel->ch->pending_messages) | ||
1136 | { | ||
1137 | GMCH_destroy (rel->ch); | ||
1138 | return GNUNET_YES; | ||
1139 | } | ||
1140 | return GNUNET_NO; | ||
1141 | } | ||
1142 | |||
1143 | |||
1144 | /** | ||
1145 | * Channel was ACK'd by remote peer, mark as ready and cancel retransmission. | ||
1146 | * | ||
1147 | * @param ch Channel to mark as ready. | ||
1148 | * @param fwd Was the ACK message a FWD ACK? (dest->root, SYNACK) | ||
1149 | */ | ||
1150 | static void | ||
1151 | channel_confirm (struct CadetChannel *ch, int fwd) | ||
1152 | { | ||
1153 | struct CadetChannelReliability *rel; | ||
1154 | enum CadetChannelState oldstate; | ||
1155 | |||
1156 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1157 | if (NULL == rel) | ||
1158 | { | ||
1159 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
1160 | return; | ||
1161 | } | ||
1162 | LOG (GNUNET_ERROR_TYPE_DEBUG, " channel confirm %s %s\n", | ||
1163 | GM_f2s (fwd), GMCH_2s (ch)); | ||
1164 | oldstate = ch->state; | ||
1165 | ch->state = CADET_CHANNEL_READY; | ||
1166 | |||
1167 | if (CADET_CHANNEL_READY != oldstate || GNUNET_YES == is_loopback (ch)) | ||
1168 | { | ||
1169 | rel->client_ready = GNUNET_YES; | ||
1170 | rel->expected_delay = rel->retry_timer; | ||
1171 | LOG (GNUNET_ERROR_TYPE_DEBUG, " !! retry timer confirm %s\n", | ||
1172 | GNUNET_STRINGS_relative_time_to_string (rel->retry_timer, GNUNET_NO)); | ||
1173 | if (GMT_get_connections_buffer (ch->t) > 0 || GMT_is_loopback (ch->t)) | ||
1174 | send_client_ack (ch, fwd); | ||
1175 | |||
1176 | if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task) | ||
1177 | { | ||
1178 | GNUNET_SCHEDULER_cancel (rel->retry_task); | ||
1179 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
1180 | } | ||
1181 | else if (NULL != rel->uniq) | ||
1182 | { | ||
1183 | GMT_cancel (rel->uniq->tq); | ||
1184 | /* ch_message_sent will free and NULL uniq */ | ||
1185 | } | ||
1186 | else | ||
1187 | { | ||
1188 | if (GNUNET_NO == is_loopback (ch)) | ||
1189 | { | ||
1190 | /* We SHOULD have been trying to retransmit this! */ | ||
1191 | GNUNET_break (0); | ||
1192 | } | ||
1193 | } | ||
1194 | } | ||
1195 | |||
1196 | /* In case of a FWD ACK (SYNACK) send a BCK ACK (ACK). */ | ||
1197 | if (GNUNET_YES == fwd) | ||
1198 | send_ack (ch, GNUNET_NO, GNUNET_NO); | ||
1199 | } | ||
1200 | |||
1201 | |||
1202 | /** | ||
1203 | * Save a copy to retransmit in case it gets lost. | ||
1204 | * | ||
1205 | * Initializes all needed callbacks and timers. | ||
1206 | * | ||
1207 | * @param ch Channel this message goes on. | ||
1208 | * @param msg Message to copy. | ||
1209 | * @param fwd Is this fwd traffic? | ||
1210 | */ | ||
1211 | static struct CadetReliableMessage * | ||
1212 | channel_save_copy (struct CadetChannel *ch, | ||
1213 | const struct GNUNET_MessageHeader *msg, | ||
1214 | int fwd) | ||
1215 | { | ||
1216 | struct CadetChannelReliability *rel; | ||
1217 | struct CadetReliableMessage *copy; | ||
1218 | uint32_t mid; | ||
1219 | uint16_t type; | ||
1220 | uint16_t size; | ||
1221 | |||
1222 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1223 | mid = rel->mid_send - 1; | ||
1224 | type = ntohs (msg->type); | ||
1225 | size = ntohs (msg->size); | ||
1226 | |||
1227 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SAVE %u %s\n", mid, GM_m2s (type)); | ||
1228 | copy = GNUNET_malloc (sizeof (struct CadetReliableMessage) + size); | ||
1229 | LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", copy); | ||
1230 | copy->mid = mid; | ||
1231 | copy->rel = rel; | ||
1232 | copy->type = type; | ||
1233 | memcpy (©[1], msg, size); | ||
1234 | GNUNET_CONTAINER_DLL_insert_tail (rel->head_sent, rel->tail_sent, copy); | ||
1235 | ch->pending_messages++; | ||
1236 | |||
1237 | return copy; | ||
1238 | } | ||
1239 | |||
1240 | |||
1241 | /** | ||
1242 | * Create a new channel. | ||
1243 | * | ||
1244 | * @param t Tunnel this channel is in. | ||
1245 | * @param owner Client that owns the channel, NULL for foreign channels. | ||
1246 | * @param lid_root Local ID for root client. | ||
1247 | * | ||
1248 | * @return A new initialized channel. NULL on error. | ||
1249 | */ | ||
1250 | static struct CadetChannel * | ||
1251 | channel_new (struct CadetTunnel3 *t, | ||
1252 | struct CadetClient *owner, | ||
1253 | CADET_ChannelNumber lid_root) | ||
1254 | { | ||
1255 | struct CadetChannel *ch; | ||
1256 | |||
1257 | ch = GNUNET_new (struct CadetChannel); | ||
1258 | ch->root = owner; | ||
1259 | ch->lid_root = lid_root; | ||
1260 | ch->t = t; | ||
1261 | |||
1262 | GNUNET_STATISTICS_update (stats, "# channels", 1, GNUNET_NO); | ||
1263 | |||
1264 | if (NULL != owner) | ||
1265 | { | ||
1266 | ch->gid = GMT_get_next_chid (t); | ||
1267 | GML_channel_add (owner, lid_root, ch); | ||
1268 | } | ||
1269 | GMT_add_channel (t, ch); | ||
1270 | |||
1271 | return ch; | ||
1272 | } | ||
1273 | |||
1274 | |||
1275 | /** | ||
1276 | * Handle a loopback message: call the appropriate handler for the message type. | ||
1277 | * | ||
1278 | * @param ch Channel this message is on. | ||
1279 | * @param msgh Message header. | ||
1280 | * @param fwd Is this FWD traffic? | ||
1281 | */ | ||
1282 | void | ||
1283 | handle_loopback (struct CadetChannel *ch, | ||
1284 | const struct GNUNET_MessageHeader *msgh, | ||
1285 | int fwd) | ||
1286 | { | ||
1287 | uint16_t type; | ||
1288 | |||
1289 | type = ntohs (msgh->type); | ||
1290 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1291 | "Loopback %s %s message!\n", | ||
1292 | GM_f2s (fwd), GM_m2s (type)); | ||
1293 | |||
1294 | switch (type) | ||
1295 | { | ||
1296 | case GNUNET_MESSAGE_TYPE_CADET_DATA: | ||
1297 | /* Don't send hop ACK, wait for client to ACK */ | ||
1298 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! SEND loopback %u (%u)\n", | ||
1299 | ntohl (((struct GNUNET_CADET_Data *) msgh)->mid), ntohs (msgh->size)); | ||
1300 | GMCH_handle_data (ch, (struct GNUNET_CADET_Data *) msgh, fwd); | ||
1301 | break; | ||
1302 | |||
1303 | case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: | ||
1304 | GMCH_handle_data_ack (ch, (struct GNUNET_CADET_DataACK *) msgh, fwd); | ||
1305 | break; | ||
1306 | |||
1307 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
1308 | GMCH_handle_create (ch->t, | ||
1309 | (struct GNUNET_CADET_ChannelCreate *) msgh); | ||
1310 | break; | ||
1311 | |||
1312 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: | ||
1313 | GMCH_handle_ack (ch, | ||
1314 | (struct GNUNET_CADET_ChannelManage *) msgh, | ||
1315 | fwd); | ||
1316 | break; | ||
1317 | |||
1318 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: | ||
1319 | GMCH_handle_nack (ch); | ||
1320 | break; | ||
1321 | |||
1322 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
1323 | GMCH_handle_destroy (ch, | ||
1324 | (struct GNUNET_CADET_ChannelManage *) msgh, | ||
1325 | fwd); | ||
1326 | break; | ||
1327 | |||
1328 | default: | ||
1329 | GNUNET_break_op (0); | ||
1330 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1331 | "end-to-end message not known (%u)\n", | ||
1332 | ntohs (msgh->type)); | ||
1333 | } | ||
1334 | } | ||
1335 | |||
1336 | |||
1337 | |||
1338 | /******************************************************************************/ | ||
1339 | /******************************** API ***********************************/ | ||
1340 | /******************************************************************************/ | ||
1341 | |||
1342 | /** | ||
1343 | * Destroy a channel and free all resources. | ||
1344 | * | ||
1345 | * @param ch Channel to destroy. | ||
1346 | */ | ||
1347 | void | ||
1348 | GMCH_destroy (struct CadetChannel *ch) | ||
1349 | { | ||
1350 | struct CadetClient *c; | ||
1351 | struct CadetTunnel3 *t; | ||
1352 | |||
1353 | if (NULL == ch) | ||
1354 | return; | ||
1355 | if (2 == ch->destroy) | ||
1356 | return; /* recursive call */ | ||
1357 | ch->destroy = 2; | ||
1358 | |||
1359 | LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying channel %s:%u\n", | ||
1360 | GMT_2s (ch->t), ch->gid); | ||
1361 | GMCH_debug (ch); | ||
1362 | |||
1363 | c = ch->root; | ||
1364 | if (NULL != c) | ||
1365 | { | ||
1366 | GML_channel_remove (c, ch->lid_root, ch); | ||
1367 | } | ||
1368 | |||
1369 | c = ch->dest; | ||
1370 | if (NULL != c) | ||
1371 | { | ||
1372 | GML_channel_remove (c, ch->lid_dest, ch); | ||
1373 | } | ||
1374 | |||
1375 | channel_rel_free_all (ch->root_rel); | ||
1376 | channel_rel_free_all (ch->dest_rel); | ||
1377 | |||
1378 | t = ch->t; | ||
1379 | GMT_remove_channel (t, ch); | ||
1380 | GNUNET_STATISTICS_update (stats, "# channels", -1, GNUNET_NO); | ||
1381 | |||
1382 | GNUNET_free (ch); | ||
1383 | GMT_destroy_if_empty (t); | ||
1384 | } | ||
1385 | |||
1386 | |||
1387 | /** | ||
1388 | * Get the channel's public ID. | ||
1389 | * | ||
1390 | * @param ch Channel. | ||
1391 | * | ||
1392 | * @return ID used to identify the channel with the remote peer. | ||
1393 | */ | ||
1394 | CADET_ChannelNumber | ||
1395 | GMCH_get_id (const struct CadetChannel *ch) | ||
1396 | { | ||
1397 | return ch->gid; | ||
1398 | } | ||
1399 | |||
1400 | |||
1401 | /** | ||
1402 | * Get the channel tunnel. | ||
1403 | * | ||
1404 | * @param ch Channel to get the tunnel from. | ||
1405 | * | ||
1406 | * @return tunnel of the channel. | ||
1407 | */ | ||
1408 | struct CadetTunnel3 * | ||
1409 | GMCH_get_tunnel (const struct CadetChannel *ch) | ||
1410 | { | ||
1411 | return ch->t; | ||
1412 | } | ||
1413 | |||
1414 | |||
1415 | /** | ||
1416 | * Get free buffer space towards the client on a specific channel. | ||
1417 | * | ||
1418 | * @param ch Channel. | ||
1419 | * @param fwd Is query about FWD traffic? | ||
1420 | * | ||
1421 | * @return Free buffer space [0 - 64] | ||
1422 | */ | ||
1423 | unsigned int | ||
1424 | GMCH_get_buffer (struct CadetChannel *ch, int fwd) | ||
1425 | { | ||
1426 | struct CadetChannelReliability *rel; | ||
1427 | |||
1428 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
1429 | |||
1430 | /* If rel is NULL it means that the end is not yet created, | ||
1431 | * most probably is a loopback channel at the point of sending | ||
1432 | * the ChannelCreate to itself. | ||
1433 | */ | ||
1434 | if (NULL == rel) | ||
1435 | return 64; | ||
1436 | |||
1437 | return (64 - rel->n_recv); | ||
1438 | } | ||
1439 | |||
1440 | |||
1441 | /** | ||
1442 | * Get flow control status of end point: is client allow to send? | ||
1443 | * | ||
1444 | * @param ch Channel. | ||
1445 | * @param fwd Is query about FWD traffic? (Request root status). | ||
1446 | * | ||
1447 | * @return #GNUNET_YES if client is allowed to send us data. | ||
1448 | */ | ||
1449 | int | ||
1450 | GMCH_get_allowed (struct CadetChannel *ch, int fwd) | ||
1451 | { | ||
1452 | struct CadetChannelReliability *rel; | ||
1453 | |||
1454 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1455 | |||
1456 | if (NULL == rel) | ||
1457 | { | ||
1458 | /* Probably shutting down: root/dest NULL'ed to mark disconnection */ | ||
1459 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
1460 | return 0; | ||
1461 | } | ||
1462 | |||
1463 | return rel->client_allowed; | ||
1464 | } | ||
1465 | |||
1466 | |||
1467 | /** | ||
1468 | * Is the root client for this channel on this peer? | ||
1469 | * | ||
1470 | * @param ch Channel. | ||
1471 | * @param fwd Is this for fwd traffic? | ||
1472 | * | ||
1473 | * @return #GNUNET_YES in case it is. | ||
1474 | */ | ||
1475 | int | ||
1476 | GMCH_is_origin (struct CadetChannel *ch, int fwd) | ||
1477 | { | ||
1478 | struct CadetClient *c; | ||
1479 | |||
1480 | c = fwd ? ch->root : ch->dest; | ||
1481 | return NULL != c; | ||
1482 | } | ||
1483 | |||
1484 | |||
1485 | /** | ||
1486 | * Is the destination client for this channel on this peer? | ||
1487 | * | ||
1488 | * @param ch Channel. | ||
1489 | * @param fwd Is this for fwd traffic? | ||
1490 | * | ||
1491 | * @return #GNUNET_YES in case it is. | ||
1492 | */ | ||
1493 | int | ||
1494 | GMCH_is_terminal (struct CadetChannel *ch, int fwd) | ||
1495 | { | ||
1496 | struct CadetClient *c; | ||
1497 | |||
1498 | c = fwd ? ch->dest : ch->root; | ||
1499 | return NULL != c; | ||
1500 | } | ||
1501 | |||
1502 | |||
1503 | /** | ||
1504 | * Send an end-to-end ACK message for the most recent in-sequence payload. | ||
1505 | * | ||
1506 | * If channel is not reliable, do nothing. | ||
1507 | * | ||
1508 | * @param ch Channel this is about. | ||
1509 | * @param fwd Is for FWD traffic? (ACK dest->owner) | ||
1510 | */ | ||
1511 | void | ||
1512 | GMCH_send_data_ack (struct CadetChannel *ch, int fwd) | ||
1513 | { | ||
1514 | struct GNUNET_CADET_DataACK msg; | ||
1515 | struct CadetChannelReliability *rel; | ||
1516 | struct CadetReliableMessage *copy; | ||
1517 | unsigned int delta; | ||
1518 | uint64_t mask; | ||
1519 | uint32_t ack; | ||
1520 | |||
1521 | if (GNUNET_NO == ch->reliable) | ||
1522 | { | ||
1523 | return; | ||
1524 | } | ||
1525 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
1526 | ack = rel->mid_recv - 1; | ||
1527 | LOG (GNUNET_ERROR_TYPE_INFO, "===> DATA_ACK for %u\n", ack); | ||
1528 | |||
1529 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA_ACK); | ||
1530 | msg.header.size = htons (sizeof (msg)); | ||
1531 | msg.chid = htonl (ch->gid); | ||
1532 | msg.futures = 0; | ||
1533 | for (copy = rel->head_recv; NULL != copy; copy = copy->next) | ||
1534 | { | ||
1535 | if (copy->type != GNUNET_MESSAGE_TYPE_CADET_DATA) | ||
1536 | { | ||
1537 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1538 | "!! Type %s, expected DATA\n", | ||
1539 | GM_m2s (copy->type)); | ||
1540 | continue; | ||
1541 | } | ||
1542 | if (copy->mid == ack + 1) | ||
1543 | { | ||
1544 | ack++; | ||
1545 | continue; | ||
1546 | } | ||
1547 | delta = copy->mid - (ack + 1); | ||
1548 | if (63 < delta) | ||
1549 | break; | ||
1550 | mask = 0x1LL << delta; | ||
1551 | msg.futures |= mask; | ||
1552 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1553 | " !! setting bit for %u (delta %u) (%llX) -> %llX\n", | ||
1554 | copy->mid, delta, mask, msg.futures); | ||
1555 | } | ||
1556 | msg.mid = htonl (ack); | ||
1557 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1558 | "!!! ACK for %u, futures %llX\n", | ||
1559 | ack, msg.futures); | ||
1560 | |||
1561 | GMCH_send_prebuilt_message (&msg.header, ch, !fwd, NULL); | ||
1562 | LOG (GNUNET_ERROR_TYPE_DEBUG, "send_data_ack END\n"); | ||
1563 | } | ||
1564 | |||
1565 | |||
1566 | /** | ||
1567 | * Allow a client to send us more data, in case it was choked. | ||
1568 | * | ||
1569 | * @param ch Channel. | ||
1570 | * @param fwd Is this about FWD traffic? (Root client). | ||
1571 | */ | ||
1572 | void | ||
1573 | GMCH_allow_client (struct CadetChannel *ch, int fwd) | ||
1574 | { | ||
1575 | struct CadetChannelReliability *rel; | ||
1576 | unsigned int buffer; | ||
1577 | |||
1578 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMCH allow\n"); | ||
1579 | |||
1580 | if (CADET_CHANNEL_READY != ch->state) | ||
1581 | { | ||
1582 | LOG (GNUNET_ERROR_TYPE_DEBUG, " channel not ready yet!\n"); | ||
1583 | return; | ||
1584 | } | ||
1585 | |||
1586 | if (GNUNET_YES == ch->reliable) | ||
1587 | { | ||
1588 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1589 | if (NULL == rel) | ||
1590 | { | ||
1591 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
1592 | return; | ||
1593 | } | ||
1594 | if (NULL != rel->head_sent) | ||
1595 | { | ||
1596 | if (64 <= rel->mid_send - rel->head_sent->mid) | ||
1597 | { | ||
1598 | LOG (GNUNET_ERROR_TYPE_DEBUG, " too big MID gap! Wait for ACK.\n"); | ||
1599 | return; | ||
1600 | } | ||
1601 | else | ||
1602 | LOG (GNUNET_ERROR_TYPE_DEBUG, " gap ok: %u - %u\n", | ||
1603 | rel->head_sent->mid, rel->mid_send); | ||
1604 | } | ||
1605 | else | ||
1606 | { | ||
1607 | LOG (GNUNET_ERROR_TYPE_DEBUG, " head sent is NULL\n"); | ||
1608 | } | ||
1609 | } | ||
1610 | |||
1611 | if (is_loopback (ch)) | ||
1612 | buffer = GMCH_get_buffer (ch, fwd); | ||
1613 | else | ||
1614 | buffer = GMT_get_connections_buffer (ch->t); | ||
1615 | |||
1616 | if (0 == buffer) | ||
1617 | { | ||
1618 | LOG (GNUNET_ERROR_TYPE_DEBUG, " no buffer space.\n"); | ||
1619 | return; | ||
1620 | } | ||
1621 | |||
1622 | LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space %u, allowing\n", buffer); | ||
1623 | send_client_ack (ch, fwd); | ||
1624 | } | ||
1625 | |||
1626 | |||
1627 | /** | ||
1628 | * Log channel info. | ||
1629 | * | ||
1630 | * @param ch Channel. | ||
1631 | */ | ||
1632 | void | ||
1633 | GMCH_debug (struct CadetChannel *ch) | ||
1634 | { | ||
1635 | if (NULL == ch) | ||
1636 | { | ||
1637 | LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CHANNEL ***\n"); | ||
1638 | return; | ||
1639 | } | ||
1640 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %s:%X (%p)\n", | ||
1641 | GMT_2s (ch->t), ch->gid, ch); | ||
1642 | LOG (GNUNET_ERROR_TYPE_DEBUG, " root %p/%p\n", | ||
1643 | ch->root, ch->root_rel); | ||
1644 | if (NULL != ch->root) | ||
1645 | { | ||
1646 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cli %s\n", GML_2s (ch->root)); | ||
1647 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ready %s\n", | ||
1648 | ch->root_rel->client_ready ? "YES" : "NO"); | ||
1649 | LOG (GNUNET_ERROR_TYPE_DEBUG, " id %X\n", ch->lid_root); | ||
1650 | } | ||
1651 | LOG (GNUNET_ERROR_TYPE_DEBUG, " dest %p/%p\n", | ||
1652 | ch->dest, ch->dest_rel); | ||
1653 | if (NULL != ch->dest) | ||
1654 | { | ||
1655 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cli %s\n", GML_2s (ch->dest)); | ||
1656 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ready %s\n", | ||
1657 | ch->dest_rel->client_ready ? "YES" : "NO"); | ||
1658 | LOG (GNUNET_ERROR_TYPE_DEBUG, " id %X\n", ch->lid_dest); | ||
1659 | } | ||
1660 | } | ||
1661 | |||
1662 | |||
1663 | /** | ||
1664 | * Handle an ACK given by a client. | ||
1665 | * | ||
1666 | * Mark client as ready and send him any buffered data we could have for him. | ||
1667 | * | ||
1668 | * @param ch Channel. | ||
1669 | * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by dest and go BCK) | ||
1670 | */ | ||
1671 | void | ||
1672 | GMCH_handle_local_ack (struct CadetChannel *ch, int fwd) | ||
1673 | { | ||
1674 | struct CadetChannelReliability *rel; | ||
1675 | struct CadetClient *c; | ||
1676 | |||
1677 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
1678 | c = fwd ? ch->dest : ch->root; | ||
1679 | |||
1680 | rel->client_ready = GNUNET_YES; | ||
1681 | send_client_buffered_data (ch, c, fwd); | ||
1682 | |||
1683 | if (GNUNET_YES == ch->destroy && 0 == rel->n_recv) | ||
1684 | { | ||
1685 | send_destroy (ch, GNUNET_YES); | ||
1686 | GMCH_destroy (ch); | ||
1687 | } | ||
1688 | /* if loopback is marked for destruction, no need to ACK to the other peer, | ||
1689 | * it requested the destruction and is already gone, therefore, else if. | ||
1690 | */ | ||
1691 | else if (is_loopback (ch)) | ||
1692 | { | ||
1693 | unsigned int buffer; | ||
1694 | |||
1695 | buffer = GMCH_get_buffer (ch, fwd); | ||
1696 | if (0 < buffer) | ||
1697 | GMCH_allow_client (ch, fwd); | ||
1698 | |||
1699 | return; | ||
1700 | } | ||
1701 | GMT_send_connection_acks (ch->t); | ||
1702 | } | ||
1703 | |||
1704 | |||
1705 | /** | ||
1706 | * Handle data given by a client. | ||
1707 | * | ||
1708 | * Check whether the client is allowed to send in this tunnel, save if channel | ||
1709 | * is reliable and send an ACK to the client if there is still buffer space | ||
1710 | * in the tunnel. | ||
1711 | * | ||
1712 | * @param ch Channel. | ||
1713 | * @param c Client which sent the data. | ||
1714 | * @param message Message. | ||
1715 | * @param fwd Is this a FWD data? | ||
1716 | * | ||
1717 | * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en error. | ||
1718 | */ | ||
1719 | int | ||
1720 | GMCH_handle_local_data (struct CadetChannel *ch, | ||
1721 | struct CadetClient *c, | ||
1722 | struct GNUNET_MessageHeader *message, | ||
1723 | int fwd) | ||
1724 | { | ||
1725 | struct CadetChannelReliability *rel; | ||
1726 | struct GNUNET_CADET_Data *payload; | ||
1727 | size_t size = ntohs (message->size); | ||
1728 | uint16_t p2p_size = sizeof(struct GNUNET_CADET_Data) + size; | ||
1729 | unsigned char cbuf[p2p_size]; | ||
1730 | |||
1731 | /* Is the client in the channel? */ | ||
1732 | if ( !( (fwd && | ||
1733 | ch->root == c) | ||
1734 | || | ||
1735 | (!fwd && | ||
1736 | ch->dest == c) ) ) | ||
1737 | { | ||
1738 | GNUNET_break_op (0); | ||
1739 | return GNUNET_SYSERR; | ||
1740 | } | ||
1741 | |||
1742 | rel = fwd ? ch->root_rel : ch->dest_rel; | ||
1743 | |||
1744 | if (GNUNET_NO == rel->client_allowed) | ||
1745 | { | ||
1746 | GNUNET_break_op (0); | ||
1747 | return GNUNET_SYSERR; | ||
1748 | } | ||
1749 | |||
1750 | rel->client_allowed = GNUNET_NO; | ||
1751 | |||
1752 | /* Ok, everything is correct, send the message. */ | ||
1753 | payload = (struct GNUNET_CADET_Data *) cbuf; | ||
1754 | payload->mid = htonl (rel->mid_send); | ||
1755 | rel->mid_send++; | ||
1756 | memcpy (&payload[1], message, size); | ||
1757 | payload->header.size = htons (p2p_size); | ||
1758 | payload->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_DATA); | ||
1759 | payload->chid = htonl (ch->gid); | ||
1760 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n"); | ||
1761 | GMCH_send_prebuilt_message (&payload->header, ch, fwd, NULL); | ||
1762 | |||
1763 | if (is_loopback (ch)) | ||
1764 | { | ||
1765 | if (GMCH_get_buffer (ch, fwd) > 0) | ||
1766 | GMCH_allow_client (ch, fwd); | ||
1767 | |||
1768 | return GNUNET_OK; | ||
1769 | } | ||
1770 | |||
1771 | if (GMT_get_connections_buffer (ch->t) > 0) | ||
1772 | { | ||
1773 | GMCH_allow_client (ch, fwd); | ||
1774 | } | ||
1775 | |||
1776 | return GNUNET_OK; | ||
1777 | } | ||
1778 | |||
1779 | |||
1780 | /** | ||
1781 | * Handle a channel destroy requested by a client. | ||
1782 | * | ||
1783 | * Destroy the channel and the tunnel in case this was the last channel. | ||
1784 | * | ||
1785 | * @param ch Channel. | ||
1786 | * @param c Client that requested the destruction (to avoid notifying him). | ||
1787 | * @param is_root Is the request coming from root? | ||
1788 | */ | ||
1789 | void | ||
1790 | GMCH_handle_local_destroy (struct CadetChannel *ch, | ||
1791 | struct CadetClient *c, | ||
1792 | int is_root) | ||
1793 | { | ||
1794 | ch->destroy = GNUNET_YES; | ||
1795 | /* Cleanup after the tunnel */ | ||
1796 | if (GNUNET_NO == is_root && c == ch->dest) | ||
1797 | { | ||
1798 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is destination.\n", GML_2s (c)); | ||
1799 | GML_client_delete_channel (c, ch, ch->lid_dest); | ||
1800 | ch->dest = NULL; | ||
1801 | } | ||
1802 | if (GNUNET_YES == is_root && c == ch->root) | ||
1803 | { | ||
1804 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Client %s is owner.\n", GML_2s (c)); | ||
1805 | GML_client_delete_channel (c, ch, ch->lid_root); | ||
1806 | ch->root = NULL; | ||
1807 | } | ||
1808 | |||
1809 | send_destroy (ch, GNUNET_NO); | ||
1810 | if (0 == ch->pending_messages) | ||
1811 | GMCH_destroy (ch); | ||
1812 | } | ||
1813 | |||
1814 | |||
1815 | /** | ||
1816 | * Handle a channel create requested by a client. | ||
1817 | * | ||
1818 | * Create the channel and the tunnel in case this was the first0 channel. | ||
1819 | * | ||
1820 | * @param c Client that requested the creation (will be the root). | ||
1821 | * @param msg Create Channel message. | ||
1822 | * | ||
1823 | * @return GNUNET_OK if everything went fine, GNUNET_SYSERR otherwise. | ||
1824 | */ | ||
1825 | int | ||
1826 | GMCH_handle_local_create (struct CadetClient *c, | ||
1827 | struct GNUNET_CADET_ChannelMessage *msg) | ||
1828 | { | ||
1829 | struct CadetChannel *ch; | ||
1830 | struct CadetTunnel3 *t; | ||
1831 | struct CadetPeer *peer; | ||
1832 | CADET_ChannelNumber chid; | ||
1833 | |||
1834 | LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s:%u\n", | ||
1835 | GNUNET_i2s (&msg->peer), ntohl (msg->port)); | ||
1836 | chid = ntohl (msg->channel_id); | ||
1837 | |||
1838 | /* Sanity check for duplicate channel IDs */ | ||
1839 | if (NULL != GML_channel_get (c, chid)) | ||
1840 | { | ||
1841 | GNUNET_break (0); | ||
1842 | return GNUNET_SYSERR; | ||
1843 | } | ||
1844 | |||
1845 | peer = GMP_get (&msg->peer); | ||
1846 | GMP_add_tunnel (peer); | ||
1847 | t = GMP_get_tunnel (peer); | ||
1848 | |||
1849 | if (GMP_get_short_id (peer) == myid) | ||
1850 | { | ||
1851 | GMT_change_cstate (t, CADET_TUNNEL3_READY); | ||
1852 | } | ||
1853 | else | ||
1854 | { | ||
1855 | /* FIXME change to a tunnel API, eliminate ch <-> peer connection */ | ||
1856 | GMP_connect (peer); | ||
1857 | } | ||
1858 | |||
1859 | /* Create channel */ | ||
1860 | ch = channel_new (t, c, chid); | ||
1861 | if (NULL == ch) | ||
1862 | { | ||
1863 | GNUNET_break (0); | ||
1864 | return GNUNET_SYSERR; | ||
1865 | } | ||
1866 | ch->port = ntohl (msg->port); | ||
1867 | channel_set_options (ch, ntohl (msg->opt)); | ||
1868 | |||
1869 | /* In unreliable channels, we'll use the DLL to buffer BCK data */ | ||
1870 | ch->root_rel = GNUNET_new (struct CadetChannelReliability); | ||
1871 | ch->root_rel->ch = ch; | ||
1872 | ch->root_rel->retry_timer = CADET_RETRANSMIT_TIME; | ||
1873 | ch->root_rel->expected_delay.rel_value_us = 0; | ||
1874 | |||
1875 | LOG (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s\n", GMCH_2s (ch)); | ||
1876 | |||
1877 | send_create (ch); | ||
1878 | |||
1879 | return GNUNET_OK; | ||
1880 | } | ||
1881 | |||
1882 | |||
1883 | /** | ||
1884 | * Handler for cadet network payload traffic. | ||
1885 | * | ||
1886 | * @param ch Channel for the message. | ||
1887 | * @param msg Unencryted data message. | ||
1888 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1889 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1890 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1891 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1892 | */ | ||
1893 | void | ||
1894 | GMCH_handle_data (struct CadetChannel *ch, | ||
1895 | const struct GNUNET_CADET_Data *msg, | ||
1896 | int fwd) | ||
1897 | { | ||
1898 | struct CadetChannelReliability *rel; | ||
1899 | struct CadetClient *c; | ||
1900 | uint32_t mid; | ||
1901 | |||
1902 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | ||
1903 | if (GNUNET_SYSERR == fwd) | ||
1904 | { | ||
1905 | if (is_loopback (ch)) | ||
1906 | { | ||
1907 | /* It is a loopback channel after all... */ | ||
1908 | GNUNET_break (0); | ||
1909 | return; | ||
1910 | } | ||
1911 | fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; | ||
1912 | } | ||
1913 | |||
1914 | /* Initialize FWD/BCK data */ | ||
1915 | c = fwd ? ch->dest : ch->root; | ||
1916 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
1917 | |||
1918 | if (NULL == c) | ||
1919 | { | ||
1920 | GNUNET_break (GNUNET_NO != ch->destroy); | ||
1921 | return; | ||
1922 | } | ||
1923 | |||
1924 | if (CADET_CHANNEL_READY != ch->state) | ||
1925 | { | ||
1926 | if (GNUNET_NO == fwd) | ||
1927 | { | ||
1928 | /* If we are the root, this means the other peer has sent traffic before | ||
1929 | * receiving our ACK. Even if the SYNACK goes missing, no traffic should | ||
1930 | * be sent before the ACK. | ||
1931 | */ | ||
1932 | GNUNET_break_op (0); | ||
1933 | return; | ||
1934 | } | ||
1935 | /* If we are the dest, this means that the SYNACK got to the root but | ||
1936 | * the ACK went missing. Treat this as an ACK. | ||
1937 | */ | ||
1938 | channel_confirm (ch, GNUNET_NO); | ||
1939 | } | ||
1940 | |||
1941 | GNUNET_STATISTICS_update (stats, "# data received", 1, GNUNET_NO); | ||
1942 | |||
1943 | mid = ntohl (msg->mid); | ||
1944 | LOG (GNUNET_ERROR_TYPE_INFO, "<=== DATA %u %s on channel %s\n", | ||
1945 | mid, GM_f2s (fwd), GMCH_2s (ch)); | ||
1946 | |||
1947 | if (GNUNET_NO == ch->reliable || | ||
1948 | ( !GM_is_pid_bigger (rel->mid_recv, mid) && | ||
1949 | GM_is_pid_bigger (rel->mid_recv + 64, mid) ) ) | ||
1950 | { | ||
1951 | LOG (GNUNET_ERROR_TYPE_DEBUG, "RECV %u (%u)\n", | ||
1952 | mid, ntohs (msg->header.size)); | ||
1953 | if (GNUNET_YES == ch->reliable) | ||
1954 | { | ||
1955 | /* Is this the exact next expected messasge? */ | ||
1956 | if (mid == rel->mid_recv) | ||
1957 | { | ||
1958 | LOG (GNUNET_ERROR_TYPE_DEBUG, "as expected\n"); | ||
1959 | rel->mid_recv++; | ||
1960 | send_client_data (ch, msg, fwd); | ||
1961 | } | ||
1962 | else | ||
1963 | { | ||
1964 | LOG (GNUNET_ERROR_TYPE_DEBUG, "save for later\n"); | ||
1965 | add_buffered_data (msg, rel); | ||
1966 | } | ||
1967 | } | ||
1968 | else | ||
1969 | { | ||
1970 | /* Tunnel is unreliable: send to clients directly */ | ||
1971 | /* FIXME: accept Out Of Order traffic */ | ||
1972 | rel->mid_recv = mid + 1; | ||
1973 | send_client_data (ch, msg, fwd); | ||
1974 | } | ||
1975 | } | ||
1976 | else | ||
1977 | { | ||
1978 | GNUNET_break_op (GM_is_pid_bigger (rel->mid_recv, mid)); | ||
1979 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1980 | "MID %u not expected (%u - %u), dropping!\n", | ||
1981 | mid, rel->mid_recv, rel->mid_recv + 63); | ||
1982 | } | ||
1983 | |||
1984 | GMCH_send_data_ack (ch, fwd); | ||
1985 | } | ||
1986 | |||
1987 | |||
1988 | /** | ||
1989 | * Handler for cadet network traffic end-to-end ACKs. | ||
1990 | * | ||
1991 | * @param ch Channel on which we got this message. | ||
1992 | * @param msg Data message. | ||
1993 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1994 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1995 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1996 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1997 | */ | ||
1998 | void | ||
1999 | GMCH_handle_data_ack (struct CadetChannel *ch, | ||
2000 | const struct GNUNET_CADET_DataACK *msg, | ||
2001 | int fwd) | ||
2002 | { | ||
2003 | struct CadetChannelReliability *rel; | ||
2004 | struct CadetReliableMessage *copy; | ||
2005 | struct CadetReliableMessage *next; | ||
2006 | uint32_t ack; | ||
2007 | int work; | ||
2008 | |||
2009 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | ||
2010 | if (GNUNET_SYSERR == fwd) | ||
2011 | { | ||
2012 | if (is_loopback (ch)) | ||
2013 | { | ||
2014 | /* It is a loopback channel after all... */ | ||
2015 | GNUNET_break (0); | ||
2016 | return; | ||
2017 | } | ||
2018 | /* Inverted: if message came 'FWD' is a 'BCK ACK'. */ | ||
2019 | fwd = (NULL != ch->dest) ? GNUNET_NO : GNUNET_YES; | ||
2020 | } | ||
2021 | |||
2022 | ack = ntohl (msg->mid); | ||
2023 | LOG (GNUNET_ERROR_TYPE_INFO, "<=== %s ACK %u\n", GM_f2s (fwd), ack); | ||
2024 | |||
2025 | if (GNUNET_YES == fwd) | ||
2026 | { | ||
2027 | rel = ch->root_rel; | ||
2028 | } | ||
2029 | else | ||
2030 | { | ||
2031 | rel = ch->dest_rel; | ||
2032 | } | ||
2033 | if (NULL == rel) | ||
2034 | { | ||
2035 | GNUNET_break_op (GNUNET_NO != ch->destroy); | ||
2036 | return; | ||
2037 | } | ||
2038 | |||
2039 | /* Free ACK'd copies: no need to retransmit those anymore FIXME refactor */ | ||
2040 | for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next) | ||
2041 | { | ||
2042 | if (GM_is_pid_bigger (copy->mid, ack)) | ||
2043 | { | ||
2044 | LOG (GNUNET_ERROR_TYPE_DEBUG, " head %u, out!\n", copy->mid); | ||
2045 | channel_rel_free_sent (rel, msg); | ||
2046 | break; | ||
2047 | } | ||
2048 | work = GNUNET_YES; | ||
2049 | LOG (GNUNET_ERROR_TYPE_DEBUG, " id %u\n", copy->mid); | ||
2050 | next = copy->next; | ||
2051 | if (GNUNET_YES == rel_message_free (copy, GNUNET_YES)) | ||
2052 | return; | ||
2053 | } | ||
2054 | |||
2055 | /* ACK client if needed and possible */ | ||
2056 | GMCH_allow_client (ch, fwd); | ||
2057 | |||
2058 | /* If some message was free'd, update the retransmission delay */ | ||
2059 | if (GNUNET_YES == work) | ||
2060 | { | ||
2061 | if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task) | ||
2062 | { | ||
2063 | GNUNET_SCHEDULER_cancel (rel->retry_task); | ||
2064 | rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
2065 | if (NULL != rel->head_sent && NULL == rel->head_sent->chq) | ||
2066 | { | ||
2067 | struct GNUNET_TIME_Absolute new_target; | ||
2068 | struct GNUNET_TIME_Relative delay; | ||
2069 | |||
2070 | delay = GNUNET_TIME_relative_multiply (rel->retry_timer, | ||
2071 | CADET_RETRANSMIT_MARGIN); | ||
2072 | new_target = GNUNET_TIME_absolute_add (rel->head_sent->timestamp, | ||
2073 | delay); | ||
2074 | delay = GNUNET_TIME_absolute_get_remaining (new_target); | ||
2075 | rel->retry_task = | ||
2076 | GNUNET_SCHEDULER_add_delayed (delay, | ||
2077 | &channel_retransmit_message, | ||
2078 | rel); | ||
2079 | } | ||
2080 | } | ||
2081 | else | ||
2082 | { | ||
2083 | /* Work was done but no task was pending? Shouldn't happen! */ | ||
2084 | GNUNET_break (0); | ||
2085 | } | ||
2086 | } | ||
2087 | } | ||
2088 | |||
2089 | |||
2090 | /** | ||
2091 | * Handler for channel create messages. | ||
2092 | * | ||
2093 | * Does not have fwd parameter because it's always 'FWD': channel is incoming. | ||
2094 | * | ||
2095 | * @param t Tunnel this channel will be in. | ||
2096 | * @param msg Channel crate message. | ||
2097 | */ | ||
2098 | struct CadetChannel * | ||
2099 | GMCH_handle_create (struct CadetTunnel3 *t, | ||
2100 | const struct GNUNET_CADET_ChannelCreate *msg) | ||
2101 | { | ||
2102 | CADET_ChannelNumber chid; | ||
2103 | struct CadetChannel *ch; | ||
2104 | struct CadetClient *c; | ||
2105 | int new_channel; | ||
2106 | int reaction; | ||
2107 | |||
2108 | reaction = GNUNET_NO; | ||
2109 | chid = ntohl (msg->chid); | ||
2110 | ch = GMT_get_channel (t, chid); | ||
2111 | if (NULL == ch) | ||
2112 | { | ||
2113 | /* Create channel */ | ||
2114 | ch = channel_new (t, NULL, 0); | ||
2115 | ch->gid = chid; | ||
2116 | channel_set_options (ch, ntohl (msg->opt)); | ||
2117 | new_channel = GNUNET_YES; | ||
2118 | } | ||
2119 | else | ||
2120 | { | ||
2121 | new_channel = GNUNET_NO; | ||
2122 | } | ||
2123 | |||
2124 | if (GNUNET_YES == new_channel || GMT_is_loopback (t)) | ||
2125 | { | ||
2126 | /* Find a destination client */ | ||
2127 | ch->port = ntohl (msg->port); | ||
2128 | LOG (GNUNET_ERROR_TYPE_DEBUG, " port %u\n", ch->port); | ||
2129 | c = GML_client_get_by_port (ch->port); | ||
2130 | if (NULL == c) | ||
2131 | { | ||
2132 | LOG (GNUNET_ERROR_TYPE_DEBUG, " no client has port registered\n"); | ||
2133 | if (is_loopback (ch)) | ||
2134 | { | ||
2135 | LOG (GNUNET_ERROR_TYPE_DEBUG, " loopback: destroy on handler\n"); | ||
2136 | send_nack (ch); | ||
2137 | } | ||
2138 | else | ||
2139 | { | ||
2140 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not loopback: destroy now\n"); | ||
2141 | send_nack (ch); | ||
2142 | GMCH_destroy (ch); | ||
2143 | } | ||
2144 | return NULL; | ||
2145 | } | ||
2146 | else | ||
2147 | { | ||
2148 | LOG (GNUNET_ERROR_TYPE_DEBUG, " client %p has port registered\n", c); | ||
2149 | } | ||
2150 | |||
2151 | add_destination (ch, c); | ||
2152 | if (GNUNET_YES == ch->reliable) | ||
2153 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n"); | ||
2154 | else | ||
2155 | LOG (GNUNET_ERROR_TYPE_DEBUG, "!!! Not Reliable\n"); | ||
2156 | |||
2157 | send_client_create (ch); | ||
2158 | ch->state = CADET_CHANNEL_SENT; | ||
2159 | } | ||
2160 | else | ||
2161 | { | ||
2162 | LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate create channel\n"); | ||
2163 | reaction = GNUNET_YES; | ||
2164 | if (GNUNET_SCHEDULER_NO_TASK != ch->dest_rel->retry_task) | ||
2165 | { | ||
2166 | LOG (GNUNET_ERROR_TYPE_DEBUG, " clearing retry task\n"); | ||
2167 | /* we were waiting to re-send our 'SYNACK', wait no more! */ | ||
2168 | GNUNET_SCHEDULER_cancel (ch->dest_rel->retry_task); | ||
2169 | ch->dest_rel->retry_task = GNUNET_SCHEDULER_NO_TASK; | ||
2170 | } | ||
2171 | } | ||
2172 | send_ack (ch, GNUNET_YES, reaction); | ||
2173 | |||
2174 | return ch; | ||
2175 | } | ||
2176 | |||
2177 | |||
2178 | /** | ||
2179 | * Handler for channel NACK messages. | ||
2180 | * | ||
2181 | * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter. | ||
2182 | * | ||
2183 | * @param ch Channel. | ||
2184 | */ | ||
2185 | void | ||
2186 | GMCH_handle_nack (struct CadetChannel *ch) | ||
2187 | { | ||
2188 | send_client_nack (ch); | ||
2189 | GMCH_destroy (ch); | ||
2190 | } | ||
2191 | |||
2192 | |||
2193 | /** | ||
2194 | * Handler for channel ack messages. | ||
2195 | * | ||
2196 | * @param ch Channel. | ||
2197 | * @param msg Message. | ||
2198 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
2199 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
2200 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
2201 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
2202 | */ | ||
2203 | void | ||
2204 | GMCH_handle_ack (struct CadetChannel *ch, | ||
2205 | const struct GNUNET_CADET_ChannelManage *msg, | ||
2206 | int fwd) | ||
2207 | { | ||
2208 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | ||
2209 | if (GNUNET_SYSERR == fwd) | ||
2210 | { | ||
2211 | if (is_loopback (ch)) | ||
2212 | { | ||
2213 | /* It is a loopback channel after all... */ | ||
2214 | GNUNET_break (0); | ||
2215 | return; | ||
2216 | } | ||
2217 | fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; | ||
2218 | } | ||
2219 | |||
2220 | channel_confirm (ch, !fwd); | ||
2221 | } | ||
2222 | |||
2223 | |||
2224 | /** | ||
2225 | * Handler for channel destroy messages. | ||
2226 | * | ||
2227 | * @param ch Channel to be destroyed of. | ||
2228 | * @param msg Message. | ||
2229 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
2230 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
2231 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
2232 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
2233 | */ | ||
2234 | void | ||
2235 | GMCH_handle_destroy (struct CadetChannel *ch, | ||
2236 | const struct GNUNET_CADET_ChannelManage *msg, | ||
2237 | int fwd) | ||
2238 | { | ||
2239 | struct CadetChannelReliability *rel; | ||
2240 | |||
2241 | /* If this is a remote (non-loopback) channel, find 'fwd'. */ | ||
2242 | if (GNUNET_SYSERR == fwd) | ||
2243 | { | ||
2244 | if (is_loopback (ch)) | ||
2245 | { | ||
2246 | /* It is a loopback channel after all... */ | ||
2247 | GNUNET_break (0); | ||
2248 | return; | ||
2249 | } | ||
2250 | fwd = (NULL != ch->dest) ? GNUNET_YES : GNUNET_NO; | ||
2251 | } | ||
2252 | |||
2253 | GMCH_debug (ch); | ||
2254 | if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) ) | ||
2255 | { | ||
2256 | /* Not for us (don't destroy twice a half-open loopback channel) */ | ||
2257 | return; | ||
2258 | } | ||
2259 | |||
2260 | rel = fwd ? ch->dest_rel : ch->root_rel; | ||
2261 | if (0 == rel->n_recv) | ||
2262 | { | ||
2263 | send_destroy (ch, GNUNET_YES); | ||
2264 | GMCH_destroy (ch); | ||
2265 | } | ||
2266 | else | ||
2267 | { | ||
2268 | ch->destroy = GNUNET_YES; | ||
2269 | } | ||
2270 | } | ||
2271 | |||
2272 | |||
2273 | /** | ||
2274 | * Sends an already built message on a channel. | ||
2275 | * | ||
2276 | * If the channel is on a loopback tunnel, notifies the appropriate destination | ||
2277 | * client locally. | ||
2278 | * | ||
2279 | * On a normal channel passes the message to the tunnel for encryption and | ||
2280 | * sending on a connection. | ||
2281 | * | ||
2282 | * This function DOES NOT save the message for retransmission. | ||
2283 | * | ||
2284 | * @param message Message to send. Function makes a copy of it. | ||
2285 | * @param ch Channel on which this message is transmitted. | ||
2286 | * @param fwd Is this a fwd message? | ||
2287 | * @param existing_copy This is a retransmission, don't save a copy. | ||
2288 | */ | ||
2289 | void | ||
2290 | GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
2291 | struct CadetChannel *ch, int fwd, | ||
2292 | void *existing_copy) | ||
2293 | { | ||
2294 | struct CadetChannelQueue *chq; | ||
2295 | uint16_t type; | ||
2296 | |||
2297 | type = ntohs (message->type); | ||
2298 | LOG (GNUNET_ERROR_TYPE_INFO, "===> %s %s on channel %s\n", | ||
2299 | GM_m2s (type), GM_f2s (fwd), GMCH_2s (ch)); | ||
2300 | |||
2301 | if (GMT_is_loopback (ch->t)) | ||
2302 | { | ||
2303 | handle_loopback (ch, message, fwd); | ||
2304 | return; | ||
2305 | } | ||
2306 | |||
2307 | switch (type) | ||
2308 | { | ||
2309 | struct GNUNET_CADET_Data *payload; | ||
2310 | case GNUNET_MESSAGE_TYPE_CADET_DATA: | ||
2311 | |||
2312 | payload = (struct GNUNET_CADET_Data *) message; | ||
2313 | LOG (GNUNET_ERROR_TYPE_INFO, "===> %s %u\n", | ||
2314 | GM_m2s (type), ntohl (payload->mid)); | ||
2315 | if (GNUNET_YES == ch->reliable) | ||
2316 | { | ||
2317 | chq = GNUNET_new (struct CadetChannelQueue); | ||
2318 | chq->type = type; | ||
2319 | if (NULL == existing_copy) | ||
2320 | chq->copy = channel_save_copy (ch, message, fwd); | ||
2321 | else | ||
2322 | { | ||
2323 | chq->copy = (struct CadetReliableMessage *) existing_copy; | ||
2324 | if (NULL != chq->copy->chq) | ||
2325 | { | ||
2326 | /* Last retransmission was queued but not yet sent! | ||
2327 | * This retransmission was scheduled by a ch_message_sent which | ||
2328 | * followed a very fast RTT, so the tiny delay made the | ||
2329 | * retransmission function to execute before the previous | ||
2330 | * retransmitted message even had a chance to leave the peer. | ||
2331 | * Cancel this message and wait until the pending | ||
2332 | * retransmission leaves the peer and ch_message_sent starts | ||
2333 | * the timer for the next one. | ||
2334 | */ | ||
2335 | GNUNET_free (chq); | ||
2336 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2337 | " exisitng copy not yet transmitted!\n"); | ||
2338 | return; | ||
2339 | } | ||
2340 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2341 | " using existing copy: %p {r:%p q:%p t:%u}\n", | ||
2342 | existing_copy, | ||
2343 | chq->copy->rel, chq->copy->chq, chq->copy->type); | ||
2344 | } | ||
2345 | LOG (GNUNET_ERROR_TYPE_DEBUG, " new chq: %p\n", chq); | ||
2346 | chq->copy->chq = chq; | ||
2347 | chq->tq = GMT_send_prebuilt_message (message, ch->t, NULL, | ||
2348 | NULL != existing_copy, | ||
2349 | &ch_message_sent, chq); | ||
2350 | /* q itself is stored in copy */ | ||
2351 | GNUNET_assert (NULL != chq->tq || GNUNET_NO != ch->destroy); | ||
2352 | } | ||
2353 | else | ||
2354 | { | ||
2355 | fire_and_forget (message, ch, GNUNET_NO); | ||
2356 | } | ||
2357 | break; | ||
2358 | |||
2359 | |||
2360 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: | ||
2361 | if (GNUNET_YES == fwd || NULL != existing_copy) | ||
2362 | { | ||
2363 | /* BCK ACK (going FWD) is just a response for a SYNACK, don't keep*/ | ||
2364 | fire_and_forget (message, ch, GNUNET_YES); | ||
2365 | return; | ||
2366 | } | ||
2367 | /* fall-trough */ | ||
2368 | case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: | ||
2369 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
2370 | chq = GNUNET_new (struct CadetChannelQueue); | ||
2371 | chq->type = type; | ||
2372 | chq->rel = fwd ? ch->root_rel : ch->dest_rel; | ||
2373 | if (NULL != chq->rel->uniq) | ||
2374 | { | ||
2375 | if (NULL != chq->rel->uniq->tq) | ||
2376 | { | ||
2377 | GMT_cancel (chq->rel->uniq->tq); | ||
2378 | /* ch_message_sent is called, freeing and NULLing uniq */ | ||
2379 | } | ||
2380 | else | ||
2381 | { | ||
2382 | GNUNET_break (0); | ||
2383 | GNUNET_free (chq->rel->uniq); | ||
2384 | } | ||
2385 | } | ||
2386 | chq->tq = GMT_send_prebuilt_message (message, ch->t, NULL, GNUNET_YES, | ||
2387 | &ch_message_sent, chq); | ||
2388 | if (NULL == chq->tq) | ||
2389 | { | ||
2390 | GNUNET_break (0); | ||
2391 | GNUNET_free (chq); | ||
2392 | chq = NULL; | ||
2393 | return; | ||
2394 | } | ||
2395 | chq->rel->uniq = chq; | ||
2396 | break; | ||
2397 | |||
2398 | |||
2399 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
2400 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: | ||
2401 | fire_and_forget (message, ch, GNUNET_YES); | ||
2402 | break; | ||
2403 | |||
2404 | |||
2405 | default: | ||
2406 | GNUNET_break (0); | ||
2407 | LOG (GNUNET_ERROR_TYPE_DEBUG, "type %s unknown!\n", GM_m2s (type)); | ||
2408 | fire_and_forget (message, ch, GNUNET_YES); | ||
2409 | } | ||
2410 | } | ||
2411 | |||
2412 | |||
2413 | /** | ||
2414 | * Get the static string for identification of the channel. | ||
2415 | * | ||
2416 | * @param ch Channel. | ||
2417 | * | ||
2418 | * @return Static string with the channel IDs. | ||
2419 | */ | ||
2420 | const char * | ||
2421 | GMCH_2s (const struct CadetChannel *ch) | ||
2422 | { | ||
2423 | static char buf[64]; | ||
2424 | |||
2425 | if (NULL == ch) | ||
2426 | return "(NULL Channel)"; | ||
2427 | |||
2428 | sprintf (buf, "%s:%u gid:%X (%X / %X)", | ||
2429 | GMT_2s (ch->t), ch->port, ch->gid, ch->lid_root, ch->lid_dest); | ||
2430 | |||
2431 | return buf; | ||
2432 | } | ||
diff --git a/src/cadet/gnunet-service-cadet_channel.h b/src/cadet/gnunet-service-cadet_channel.h new file mode 100644 index 000000000..f5a89a423 --- /dev/null +++ b/src/cadet/gnunet-service-cadet_channel.h | |||
@@ -0,0 +1,349 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_channel.h | ||
23 | * @brief cadet service; dealing with end-to-end channels | ||
24 | * @author Bartlomiej Polot | ||
25 | * | ||
26 | * All functions in this file should use the prefix GMCH (Gnunet Cadet CHannel) | ||
27 | */ | ||
28 | |||
29 | #ifndef GNUNET_SERVICE_CADET_CHANNEL_H | ||
30 | #define GNUNET_SERVICE_CADET_CHANNEL_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 | #include "cadet_protocol.h" | ||
44 | #include "cadet.h" | ||
45 | |||
46 | /** | ||
47 | * Struct containing all information regarding a channel to a remote client. | ||
48 | */ | ||
49 | struct CadetChannel; | ||
50 | |||
51 | |||
52 | #include "gnunet-service-cadet_tunnel.h" | ||
53 | #include "gnunet-service-cadet_local.h" | ||
54 | |||
55 | |||
56 | /** | ||
57 | * Destroy a channel and free all resources. | ||
58 | * | ||
59 | * @param ch Channel to destroy. | ||
60 | */ | ||
61 | void | ||
62 | GMCH_destroy (struct CadetChannel *ch); | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Get the channel's public ID. | ||
67 | * | ||
68 | * @param ch Channel. | ||
69 | * | ||
70 | * @return ID used to identify the channel with the remote peer. | ||
71 | */ | ||
72 | CADET_ChannelNumber | ||
73 | GMCH_get_id (const struct CadetChannel *ch); | ||
74 | |||
75 | /** | ||
76 | * Get the channel tunnel. | ||
77 | * | ||
78 | * @param ch Channel to get the tunnel from. | ||
79 | * | ||
80 | * @return tunnel of the channel. | ||
81 | */ | ||
82 | struct CadetTunnel3 * | ||
83 | GMCH_get_tunnel (const struct CadetChannel *ch); | ||
84 | |||
85 | /** | ||
86 | * Get free buffer space towards the client on a specific channel. | ||
87 | * | ||
88 | * @param ch Channel. | ||
89 | * @param fwd Is query about FWD traffic? | ||
90 | * | ||
91 | * @return Free buffer space [0 - 64] | ||
92 | */ | ||
93 | unsigned int | ||
94 | GMCH_get_buffer (struct CadetChannel *ch, int fwd); | ||
95 | |||
96 | |||
97 | /** | ||
98 | * Get flow control status of end point: is client allow to send? | ||
99 | * | ||
100 | * @param ch Channel. | ||
101 | * @param fwd Is query about FWD traffic? (Request root status). | ||
102 | * | ||
103 | * @return #GNUNET_YES if client is allowed to send us data. | ||
104 | */ | ||
105 | int | ||
106 | GMCH_get_allowed (struct CadetChannel *ch, int fwd); | ||
107 | |||
108 | |||
109 | /** | ||
110 | * Is the root client for this channel on this peer? | ||
111 | * | ||
112 | * @param ch Channel. | ||
113 | * @param fwd Is this for fwd traffic? | ||
114 | * | ||
115 | * @return #GNUNET_YES in case it is. | ||
116 | */ | ||
117 | int | ||
118 | GMCH_is_origin (struct CadetChannel *ch, int fwd); | ||
119 | |||
120 | /** | ||
121 | * Is the destination client for this channel on this peer? | ||
122 | * | ||
123 | * @param ch Channel. | ||
124 | * @param fwd Is this for fwd traffic? | ||
125 | * | ||
126 | * @return #GNUNET_YES in case it is. | ||
127 | */ | ||
128 | int | ||
129 | GMCH_is_terminal (struct CadetChannel *ch, int fwd); | ||
130 | |||
131 | /** | ||
132 | * Send an end-to-end ACK message for the most recent in-sequence payload. | ||
133 | * | ||
134 | * If channel is not reliable, do nothing. | ||
135 | * | ||
136 | * @param ch Channel this is about. | ||
137 | * @param fwd Is for FWD traffic? (ACK dest->owner) | ||
138 | */ | ||
139 | void | ||
140 | GMCH_send_data_ack (struct CadetChannel *ch, int fwd); | ||
141 | |||
142 | /** | ||
143 | * Notify the destination client that a new incoming channel was created. | ||
144 | * | ||
145 | * @param ch Channel that was created. | ||
146 | */ | ||
147 | void | ||
148 | GMCH_send_create (struct CadetChannel *ch); | ||
149 | |||
150 | /** | ||
151 | * Allow a client to send us more data, in case it was choked. | ||
152 | * | ||
153 | * @param ch Channel. | ||
154 | * @param fwd Is this about FWD traffic? (Root client). | ||
155 | */ | ||
156 | void | ||
157 | GMCH_allow_client (struct CadetChannel *ch, int fwd); | ||
158 | |||
159 | /** | ||
160 | * Log channel info. | ||
161 | * | ||
162 | * @param ch Channel. | ||
163 | */ | ||
164 | void | ||
165 | GMCH_debug (struct CadetChannel *ch); | ||
166 | |||
167 | /** | ||
168 | * Handle an ACK given by a client. | ||
169 | * | ||
170 | * Mark client as ready and send him any buffered data we could have for him. | ||
171 | * | ||
172 | * @param ch Channel. | ||
173 | * @param fwd Is this a "FWD ACK"? (FWD ACKs are sent by root and go BCK) | ||
174 | */ | ||
175 | void | ||
176 | GMCH_handle_local_ack (struct CadetChannel *ch, int fwd); | ||
177 | |||
178 | /** | ||
179 | * Handle data given by a client. | ||
180 | * | ||
181 | * Check whether the client is allowed to send in this tunnel, save if channel | ||
182 | * is reliable and send an ACK to the client if there is still buffer space | ||
183 | * in the tunnel. | ||
184 | * | ||
185 | * @param ch Channel. | ||
186 | * @param c Client which sent the data. | ||
187 | * @param message Message. | ||
188 | * @param fwd Is this a FWD data? | ||
189 | * | ||
190 | * @return GNUNET_OK if everything goes well, GNUNET_SYSERR in case of en error. | ||
191 | */ | ||
192 | int | ||
193 | GMCH_handle_local_data (struct CadetChannel *ch, | ||
194 | struct CadetClient *c, | ||
195 | struct GNUNET_MessageHeader *message, | ||
196 | int fwd); | ||
197 | |||
198 | /** | ||
199 | * Handle a channel destroy requested by a client. | ||
200 | * | ||
201 | * Destroy the channel and the tunnel in case this was the last channel. | ||
202 | * | ||
203 | * @param ch Channel. | ||
204 | * @param c Client that requested the destruction (to avoid notifying him). | ||
205 | * @param is_root Is the request coming from root? | ||
206 | */ | ||
207 | void | ||
208 | GMCH_handle_local_destroy (struct CadetChannel *ch, | ||
209 | struct CadetClient *c, | ||
210 | int is_root); | ||
211 | |||
212 | /** | ||
213 | * Handle a channel create requested by a client. | ||
214 | * | ||
215 | * Create the channel and the tunnel in case this was the first0 channel. | ||
216 | * | ||
217 | * @param c Client that requested the creation (will be the root). | ||
218 | * @param msg Create Channel message. | ||
219 | * | ||
220 | * @return GNUNET_OK if everything went fine, GNUNET_SYSERR otherwise. | ||
221 | */ | ||
222 | int | ||
223 | GMCH_handle_local_create (struct CadetClient *c, | ||
224 | struct GNUNET_CADET_ChannelMessage *msg); | ||
225 | |||
226 | /** | ||
227 | * Handler for cadet network payload traffic. | ||
228 | * | ||
229 | * @param ch Channel for the message. | ||
230 | * @param msg Unencryted data message. | ||
231 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
232 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
233 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
234 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
235 | */ | ||
236 | void | ||
237 | GMCH_handle_data (struct CadetChannel *ch, | ||
238 | const struct GNUNET_CADET_Data *msg, | ||
239 | int fwd); | ||
240 | |||
241 | /** | ||
242 | * Handler for cadet network traffic end-to-end ACKs. | ||
243 | * | ||
244 | * @param ch Channel on which we got this message. | ||
245 | * @param msg Data message. | ||
246 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
247 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
248 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
249 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
250 | */ | ||
251 | void | ||
252 | GMCH_handle_data_ack (struct CadetChannel *ch, | ||
253 | const struct GNUNET_CADET_DataACK *msg, | ||
254 | int fwd); | ||
255 | |||
256 | /** | ||
257 | * Handler for channel create messages. | ||
258 | * | ||
259 | * Does not have fwd parameter because it's always 'FWD': channel is incoming. | ||
260 | * | ||
261 | * @param t Tunnel this channel will be in. | ||
262 | * @param msg Channel crate message. | ||
263 | */ | ||
264 | struct CadetChannel * | ||
265 | GMCH_handle_create (struct CadetTunnel3 *t, | ||
266 | const struct GNUNET_CADET_ChannelCreate *msg); | ||
267 | |||
268 | /** | ||
269 | * Handler for channel NACK messages. | ||
270 | * | ||
271 | * NACK messages always go dest -> root, no need for 'fwd' or 'msg' parameter. | ||
272 | * | ||
273 | * @param ch Channel. | ||
274 | */ | ||
275 | void | ||
276 | GMCH_handle_nack (struct CadetChannel *ch); | ||
277 | |||
278 | /** | ||
279 | * Handler for channel ack messages. | ||
280 | * | ||
281 | * @param ch Channel this channel is to be created in. | ||
282 | * @param msg Message. | ||
283 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
284 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
285 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
286 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
287 | */ | ||
288 | void | ||
289 | GMCH_handle_ack (struct CadetChannel *ch, | ||
290 | const struct GNUNET_CADET_ChannelManage *msg, | ||
291 | int fwd); | ||
292 | |||
293 | /** | ||
294 | * Handler for channel destroy messages. | ||
295 | * | ||
296 | * @param ch Channel this channel is to be destroyed of. | ||
297 | * @param msg Message. | ||
298 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
299 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
300 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
301 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
302 | */ | ||
303 | void | ||
304 | GMCH_handle_destroy (struct CadetChannel *ch, | ||
305 | const struct GNUNET_CADET_ChannelManage *msg, | ||
306 | int fwd); | ||
307 | |||
308 | /** | ||
309 | * Sends an already built message on a channel. | ||
310 | * | ||
311 | * If the channel is on a loopback tunnel, notifies the appropriate destination | ||
312 | * client locally. | ||
313 | * | ||
314 | * On a normal channel passes the message to the tunnel for encryption and | ||
315 | * sending on a connection. | ||
316 | * | ||
317 | * This function DOES NOT save the message for retransmission. | ||
318 | * | ||
319 | * @param message Message to send. Function makes a copy of it. | ||
320 | * @param ch Channel on which this message is transmitted. | ||
321 | * @param fwd Is this a fwd message? | ||
322 | * @param existing_copy This is a retransmission, don't save a copy. | ||
323 | */ | ||
324 | void | ||
325 | GMCH_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
326 | struct CadetChannel *ch, int fwd, | ||
327 | void *existing_copy); | ||
328 | |||
329 | /** | ||
330 | * Get the static string for identification of the channel. | ||
331 | * | ||
332 | * @param ch Channel.i | ||
333 | * | ||
334 | * @return Static string with the channel IDs. | ||
335 | */ | ||
336 | const char * | ||
337 | GMCH_2s (const struct CadetChannel *ch); | ||
338 | |||
339 | |||
340 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
341 | { | ||
342 | #endif | ||
343 | #ifdef __cplusplus | ||
344 | } | ||
345 | #endif | ||
346 | |||
347 | /* ifndef GNUNET_SERVICE_CADET_CHANNEL_H */ | ||
348 | #endif | ||
349 | /* 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 new file mode 100644 index 000000000..9c07e006b --- /dev/null +++ b/src/cadet/gnunet-service-cadet_connection.c | |||
@@ -0,0 +1,3176 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2001-2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_connection.c | ||
23 | * @brief GNUnet CADET service connection handling | ||
24 | * @author Bartlomiej Polot | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | |||
30 | #include "gnunet_statistics_service.h" | ||
31 | |||
32 | #include "cadet_path.h" | ||
33 | #include "cadet_protocol.h" | ||
34 | #include "cadet.h" | ||
35 | #include "gnunet-service-cadet_connection.h" | ||
36 | #include "gnunet-service-cadet_peer.h" | ||
37 | #include "gnunet-service-cadet_tunnel.h" | ||
38 | |||
39 | |||
40 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-con",__VA_ARGS__) | ||
41 | |||
42 | #define CADET_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\ | ||
43 | GNUNET_TIME_UNIT_MINUTES,\ | ||
44 | 10) | ||
45 | #define AVG_MSGS 32 | ||
46 | |||
47 | |||
48 | /******************************************************************************/ | ||
49 | /******************************** STRUCTS **********************************/ | ||
50 | /******************************************************************************/ | ||
51 | |||
52 | /** | ||
53 | * Struct to encapsulate all the Flow Control information to a peer to which | ||
54 | * we are directly connected (on a core level). | ||
55 | */ | ||
56 | struct CadetFlowControl | ||
57 | { | ||
58 | /** | ||
59 | * Connection this controls. | ||
60 | */ | ||
61 | struct CadetConnection *c; | ||
62 | |||
63 | /** | ||
64 | * How many messages are in the queue on this connection. | ||
65 | */ | ||
66 | unsigned int queue_n; | ||
67 | |||
68 | /** | ||
69 | * How many messages do we accept in the queue. | ||
70 | */ | ||
71 | unsigned int queue_max; | ||
72 | |||
73 | /** | ||
74 | * ID of the last packet sent towards the peer. | ||
75 | */ | ||
76 | uint32_t last_pid_sent; | ||
77 | |||
78 | /** | ||
79 | * ID of the last packet received from the peer. | ||
80 | */ | ||
81 | uint32_t last_pid_recv; | ||
82 | |||
83 | /** | ||
84 | * Last ACK sent to the peer (peer can't send more than this PID). | ||
85 | */ | ||
86 | uint32_t last_ack_sent; | ||
87 | |||
88 | /** | ||
89 | * Last ACK sent towards the origin (for traffic towards leaf node). | ||
90 | */ | ||
91 | uint32_t last_ack_recv; | ||
92 | |||
93 | /** | ||
94 | * Task to poll the peer in case of a lost ACK causes stall. | ||
95 | */ | ||
96 | GNUNET_SCHEDULER_TaskIdentifier poll_task; | ||
97 | |||
98 | /** | ||
99 | * How frequently to poll for ACKs. | ||
100 | */ | ||
101 | struct GNUNET_TIME_Relative poll_time; | ||
102 | |||
103 | /** | ||
104 | * Queued poll message, to cancel if not necessary anymore (got ACK). | ||
105 | */ | ||
106 | struct CadetConnectionQueue *poll_msg; | ||
107 | |||
108 | /** | ||
109 | * Queued poll message, to cancel if not necessary anymore (got ACK). | ||
110 | */ | ||
111 | struct CadetConnectionQueue *ack_msg; | ||
112 | }; | ||
113 | |||
114 | /** | ||
115 | * Keep a record of the last messages sent on this connection. | ||
116 | */ | ||
117 | struct CadetConnectionPerformance | ||
118 | { | ||
119 | /** | ||
120 | * Circular buffer for storing measurements. | ||
121 | */ | ||
122 | double usecsperbyte[AVG_MSGS]; | ||
123 | |||
124 | /** | ||
125 | * Running average of @c usecsperbyte. | ||
126 | */ | ||
127 | double avg; | ||
128 | |||
129 | /** | ||
130 | * How many values of @c usecsperbyte are valid. | ||
131 | */ | ||
132 | uint16_t size; | ||
133 | |||
134 | /** | ||
135 | * Index of the next "free" position in @c usecsperbyte. | ||
136 | */ | ||
137 | uint16_t idx; | ||
138 | }; | ||
139 | |||
140 | |||
141 | /** | ||
142 | * Struct containing all information regarding a connection to a peer. | ||
143 | */ | ||
144 | struct CadetConnection | ||
145 | { | ||
146 | /** | ||
147 | * Tunnel this connection is part of. | ||
148 | */ | ||
149 | struct CadetTunnel3 *t; | ||
150 | |||
151 | /** | ||
152 | * Flow control information for traffic fwd. | ||
153 | */ | ||
154 | struct CadetFlowControl fwd_fc; | ||
155 | |||
156 | /** | ||
157 | * Flow control information for traffic bck. | ||
158 | */ | ||
159 | struct CadetFlowControl bck_fc; | ||
160 | |||
161 | /** | ||
162 | * Measure connection performance on the endpoint. | ||
163 | */ | ||
164 | struct CadetConnectionPerformance *perf; | ||
165 | |||
166 | /** | ||
167 | * ID of the connection. | ||
168 | */ | ||
169 | struct GNUNET_CADET_Hash id; | ||
170 | |||
171 | /** | ||
172 | * State of the connection. | ||
173 | */ | ||
174 | enum CadetConnectionState state; | ||
175 | |||
176 | /** | ||
177 | * Path being used for the tunnel. At the origin of the connection | ||
178 | * it's a pointer to the destination's path pool, otherwise just a copy. | ||
179 | */ | ||
180 | struct CadetPeerPath *path; | ||
181 | |||
182 | /** | ||
183 | * Position of the local peer in the path. | ||
184 | */ | ||
185 | unsigned int own_pos; | ||
186 | |||
187 | /** | ||
188 | * Task to keep the used paths alive at the owner, | ||
189 | * time tunnel out on all the other peers. | ||
190 | */ | ||
191 | GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task; | ||
192 | |||
193 | /** | ||
194 | * Task to keep the used paths alive at the destination, | ||
195 | * time tunnel out on all the other peers. | ||
196 | */ | ||
197 | GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task; | ||
198 | |||
199 | /** | ||
200 | * Queue handle for maintainance traffic. One handle for FWD and BCK since | ||
201 | * one peer never needs to maintain both directions (no loopback connections). | ||
202 | */ | ||
203 | struct CadetPeerQueue *maintenance_q; | ||
204 | |||
205 | /** | ||
206 | * Counter to do exponential backoff when creating a connection (max 64). | ||
207 | */ | ||
208 | unsigned short create_retry; | ||
209 | |||
210 | /** | ||
211 | * Pending message count. | ||
212 | */ | ||
213 | int pending_messages; | ||
214 | |||
215 | /** | ||
216 | * Destroy flag: if true, destroy on last message. | ||
217 | */ | ||
218 | int destroy; | ||
219 | }; | ||
220 | |||
221 | /** | ||
222 | * Handle for messages queued but not yet sent. | ||
223 | */ | ||
224 | struct CadetConnectionQueue | ||
225 | { | ||
226 | /** | ||
227 | * Peer queue handle, to cancel if necessary. | ||
228 | */ | ||
229 | struct CadetPeerQueue *q; | ||
230 | |||
231 | /** | ||
232 | * Was this a forced message? (Do not account for it) | ||
233 | */ | ||
234 | int forced; | ||
235 | |||
236 | /** | ||
237 | * Continuation to call once sent. | ||
238 | */ | ||
239 | GMC_sent cont; | ||
240 | |||
241 | /** | ||
242 | * Closure for @c cont. | ||
243 | */ | ||
244 | void *cont_cls; | ||
245 | }; | ||
246 | |||
247 | /******************************************************************************/ | ||
248 | /******************************* GLOBALS ***********************************/ | ||
249 | /******************************************************************************/ | ||
250 | |||
251 | /** | ||
252 | * Global handle to the statistics service. | ||
253 | */ | ||
254 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
255 | |||
256 | /** | ||
257 | * Local peer own ID (memory efficient handle). | ||
258 | */ | ||
259 | extern GNUNET_PEER_Id myid; | ||
260 | |||
261 | /** | ||
262 | * Local peer own ID (full value). | ||
263 | */ | ||
264 | extern struct GNUNET_PeerIdentity my_full_id; | ||
265 | |||
266 | /** | ||
267 | * Connections known, indexed by cid (CadetConnection). | ||
268 | */ | ||
269 | static struct GNUNET_CONTAINER_MultiHashMap *connections; | ||
270 | |||
271 | /** | ||
272 | * How many connections are we willing to maintain. | ||
273 | * Local connections are always allowed, even if there are more connections than max. | ||
274 | */ | ||
275 | static unsigned long long max_connections; | ||
276 | |||
277 | /** | ||
278 | * How many messages *in total* are we willing to queue, divide by number of | ||
279 | * connections to get connection queue size. | ||
280 | */ | ||
281 | static unsigned long long max_msgs_queue; | ||
282 | |||
283 | /** | ||
284 | * How often to send path keepalives. Paths timeout after 4 missed. | ||
285 | */ | ||
286 | static struct GNUNET_TIME_Relative refresh_connection_time; | ||
287 | |||
288 | /** | ||
289 | * How often to send path create / ACKs. | ||
290 | */ | ||
291 | static struct GNUNET_TIME_Relative create_connection_time; | ||
292 | |||
293 | |||
294 | /******************************************************************************/ | ||
295 | /******************************** STATIC ***********************************/ | ||
296 | /******************************************************************************/ | ||
297 | |||
298 | #if 0 // avoid compiler warning for unused static function | ||
299 | static void | ||
300 | fc_debug (struct CadetFlowControl *fc) | ||
301 | { | ||
302 | LOG (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n", | ||
303 | fc->last_pid_recv, fc->last_ack_sent); | ||
304 | LOG (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n", | ||
305 | fc->last_pid_sent, fc->last_ack_recv); | ||
306 | LOG (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n", | ||
307 | fc->queue_n, fc->queue_max); | ||
308 | } | ||
309 | |||
310 | static void | ||
311 | connection_debug (struct CadetConnection *c) | ||
312 | { | ||
313 | if (NULL == c) | ||
314 | { | ||
315 | LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n"); | ||
316 | return; | ||
317 | } | ||
318 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n", | ||
319 | peer2s (c->t->peer), GMC_2s (c)); | ||
320 | LOG (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n", | ||
321 | c->state, c->pending_messages); | ||
322 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n"); | ||
323 | fc_debug (&c->fwd_fc); | ||
324 | LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n"); | ||
325 | fc_debug (&c->bck_fc); | ||
326 | } | ||
327 | #endif | ||
328 | |||
329 | |||
330 | /** | ||
331 | * Schedule next keepalive task, taking in consideration | ||
332 | * the connection state and number of retries. | ||
333 | * | ||
334 | * @param c Connection for which to schedule the next keepalive. | ||
335 | * @param fwd Direction for the next keepalive. | ||
336 | */ | ||
337 | static void | ||
338 | schedule_next_keepalive (struct CadetConnection *c, int fwd); | ||
339 | |||
340 | |||
341 | /** | ||
342 | * Resets the connection timeout task, some other message has done the | ||
343 | * task's job. | ||
344 | * - For the first peer on the direction this means to send | ||
345 | * a keepalive or a path confirmation message (either create or ACK). | ||
346 | * - For all other peers, this means to destroy the connection, | ||
347 | * due to lack of activity. | ||
348 | * Starts the timeout if no timeout was running (connection just created). | ||
349 | * | ||
350 | * @param c Connection whose timeout to reset. | ||
351 | * @param fwd Is this forward? | ||
352 | */ | ||
353 | static void | ||
354 | connection_reset_timeout (struct CadetConnection *c, int fwd); | ||
355 | |||
356 | |||
357 | /** | ||
358 | * Get string description for tunnel state. Reentrant. | ||
359 | * | ||
360 | * @param s Tunnel state. | ||
361 | * | ||
362 | * @return String representation. | ||
363 | */ | ||
364 | static const char * | ||
365 | GMC_state2s (enum CadetConnectionState s) | ||
366 | { | ||
367 | switch (s) | ||
368 | { | ||
369 | case CADET_CONNECTION_NEW: | ||
370 | return "CADET_CONNECTION_NEW"; | ||
371 | case CADET_CONNECTION_SENT: | ||
372 | return "CADET_CONNECTION_SENT"; | ||
373 | case CADET_CONNECTION_ACK: | ||
374 | return "CADET_CONNECTION_ACK"; | ||
375 | case CADET_CONNECTION_READY: | ||
376 | return "CADET_CONNECTION_READY"; | ||
377 | case CADET_CONNECTION_DESTROYED: | ||
378 | return "CADET_CONNECTION_DESTROYED"; | ||
379 | default: | ||
380 | return "CADET_CONNECTION_STATE_ERROR"; | ||
381 | } | ||
382 | } | ||
383 | |||
384 | |||
385 | /** | ||
386 | * Initialize a Flow Control structure to the initial state. | ||
387 | * | ||
388 | * @param fc Flow Control structure to initialize. | ||
389 | */ | ||
390 | static void | ||
391 | fc_init (struct CadetFlowControl *fc) | ||
392 | { | ||
393 | fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */ | ||
394 | fc->last_pid_recv = (uint32_t) -1; | ||
395 | fc->last_ack_sent = (uint32_t) 0; | ||
396 | fc->last_ack_recv = (uint32_t) 0; | ||
397 | fc->poll_task = GNUNET_SCHEDULER_NO_TASK; | ||
398 | fc->poll_time = GNUNET_TIME_UNIT_SECONDS; | ||
399 | fc->queue_n = 0; | ||
400 | fc->queue_max = (max_msgs_queue / max_connections) + 1; | ||
401 | } | ||
402 | |||
403 | |||
404 | /** | ||
405 | * Find a connection. | ||
406 | * | ||
407 | * @param cid Connection ID. | ||
408 | */ | ||
409 | static struct CadetConnection * | ||
410 | connection_get (const struct GNUNET_CADET_Hash *cid) | ||
411 | { | ||
412 | return GNUNET_CONTAINER_multihashmap_get (connections, GM_h2hc (cid)); | ||
413 | } | ||
414 | |||
415 | |||
416 | static void | ||
417 | connection_change_state (struct CadetConnection* c, | ||
418 | enum CadetConnectionState state) | ||
419 | { | ||
420 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
421 | "Connection %s state %s -> %s\n", | ||
422 | GMC_2s (c), GMC_state2s (c->state), GMC_state2s (state)); | ||
423 | if (CADET_CONNECTION_DESTROYED == c->state) | ||
424 | { | ||
425 | LOG (GNUNET_ERROR_TYPE_DEBUG, "state not changing anymore\n"); | ||
426 | return; | ||
427 | } | ||
428 | c->state = state; | ||
429 | if (CADET_CONNECTION_READY == state) | ||
430 | c->create_retry = 1; | ||
431 | } | ||
432 | |||
433 | |||
434 | /** | ||
435 | * Callback called when a queued ACK message is sent. | ||
436 | * | ||
437 | * @param cls Closure (FC). | ||
438 | * @param c Connection this message was on. | ||
439 | * @param q Queue handler this call invalidates. | ||
440 | * @param type Type of message sent. | ||
441 | * @param fwd Was this a FWD going message? | ||
442 | * @param size Size of the message. | ||
443 | */ | ||
444 | static void | ||
445 | ack_sent (void *cls, | ||
446 | struct CadetConnection *c, | ||
447 | struct CadetConnectionQueue *q, | ||
448 | uint16_t type, int fwd, size_t size) | ||
449 | { | ||
450 | struct CadetFlowControl *fc = cls; | ||
451 | |||
452 | fc->ack_msg = NULL; | ||
453 | } | ||
454 | |||
455 | |||
456 | /** | ||
457 | * Send an ACK on the connection, informing the predecessor about | ||
458 | * the available buffer space. Should not be called in case the peer | ||
459 | * is origin (no predecessor) in the @c fwd direction. | ||
460 | * | ||
461 | * Note that for fwd ack, the FWD mean forward *traffic* (root->dest), | ||
462 | * the ACK itself goes "back" (dest->root). | ||
463 | * | ||
464 | * @param c Connection on which to send the ACK. | ||
465 | * @param buffer How much space free to advertise? | ||
466 | * @param fwd Is this FWD ACK? (Going dest -> root) | ||
467 | * @param force Don't optimize out. | ||
468 | */ | ||
469 | static void | ||
470 | send_ack (struct CadetConnection *c, unsigned int buffer, int fwd, int force) | ||
471 | { | ||
472 | struct CadetFlowControl *next_fc; | ||
473 | struct CadetFlowControl *prev_fc; | ||
474 | struct GNUNET_CADET_ACK msg; | ||
475 | uint32_t ack; | ||
476 | int delta; | ||
477 | |||
478 | /* If origin, there is no connection to send ACKs. Wrong function! */ | ||
479 | if (GMC_is_origin (c, fwd)) | ||
480 | { | ||
481 | LOG (GNUNET_ERROR_TYPE_DEBUG, "connection %s is origin in %s\n", | ||
482 | GMC_2s (c), GM_f2s (fwd)); | ||
483 | GNUNET_break (0); | ||
484 | return; | ||
485 | } | ||
486 | |||
487 | next_fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
488 | prev_fc = fwd ? &c->bck_fc : &c->fwd_fc; | ||
489 | |||
490 | LOG (GNUNET_ERROR_TYPE_DEBUG, "connection send %s ack on %s\n", | ||
491 | GM_f2s (fwd), GMC_2s (c)); | ||
492 | |||
493 | /* Check if we need to transmit the ACK. */ | ||
494 | delta = prev_fc->last_ack_sent - prev_fc->last_pid_recv; | ||
495 | if (3 < delta && buffer < delta && GNUNET_NO == force) | ||
496 | { | ||
497 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n"); | ||
498 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
499 | " last pid recv: %u, last ack sent: %u\n", | ||
500 | prev_fc->last_pid_recv, prev_fc->last_ack_sent); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | /* Ok, ACK might be necessary, what PID to ACK? */ | ||
505 | ack = prev_fc->last_pid_recv + buffer; | ||
506 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack); | ||
507 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
508 | " last pid %u, last ack %u, qmax %u, q %u\n", | ||
509 | prev_fc->last_pid_recv, prev_fc->last_ack_sent, | ||
510 | next_fc->queue_max, next_fc->queue_n); | ||
511 | if (ack == prev_fc->last_ack_sent && GNUNET_NO == force) | ||
512 | { | ||
513 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n"); | ||
514 | return; | ||
515 | } | ||
516 | |||
517 | /* Check if message is already in queue */ | ||
518 | if (NULL != prev_fc->ack_msg) | ||
519 | { | ||
520 | if (GM_is_pid_bigger (ack, prev_fc->last_ack_sent)) | ||
521 | { | ||
522 | LOG (GNUNET_ERROR_TYPE_DEBUG, " canceling old ACK\n"); | ||
523 | GMC_cancel (prev_fc->ack_msg); | ||
524 | /* GMC_cancel triggers ack_sent(), which clears fc->ack_msg */ | ||
525 | } | ||
526 | else | ||
527 | { | ||
528 | LOG (GNUNET_ERROR_TYPE_DEBUG, " same ACK already in queue\n"); | ||
529 | return; | ||
530 | } | ||
531 | } | ||
532 | |||
533 | prev_fc->last_ack_sent = ack; | ||
534 | |||
535 | /* Build ACK message and send on connection */ | ||
536 | msg.header.size = htons (sizeof (msg)); | ||
537 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_ACK); | ||
538 | msg.ack = htonl (ack); | ||
539 | msg.cid = c->id; | ||
540 | |||
541 | prev_fc->ack_msg = GMC_send_prebuilt_message (&msg.header, | ||
542 | GNUNET_MESSAGE_TYPE_CADET_ACK, | ||
543 | ack, c, !fwd, GNUNET_YES, | ||
544 | &ack_sent, prev_fc); | ||
545 | } | ||
546 | |||
547 | |||
548 | /** | ||
549 | * Callback called when a connection queued message is sent. | ||
550 | * | ||
551 | * Calculates the average time and connection packet tracking. | ||
552 | * | ||
553 | * @param cls Closure (ConnectionQueue Handle). | ||
554 | * @param c Connection this message was on. | ||
555 | * @param sent Was it really sent? (Could have been canceled) | ||
556 | * @param type Type of message sent. | ||
557 | * @param pid Packet ID, or 0 if not applicable (create, destroy, etc). | ||
558 | * @param fwd Was this a FWD going message? | ||
559 | * @param size Size of the message. | ||
560 | * @param wait Time spent waiting for core (only the time for THIS message) | ||
561 | */ | ||
562 | static void | ||
563 | conn_message_sent (void *cls, | ||
564 | struct CadetConnection *c, int sent, | ||
565 | uint16_t type, uint32_t pid, int fwd, size_t size, | ||
566 | struct GNUNET_TIME_Relative wait) | ||
567 | { | ||
568 | struct CadetConnectionPerformance *p; | ||
569 | struct CadetFlowControl *fc; | ||
570 | struct CadetConnectionQueue *q = cls; | ||
571 | double usecsperbyte; | ||
572 | int forced; | ||
573 | |||
574 | LOG (GNUNET_ERROR_TYPE_DEBUG, "connection message_sent\n"); | ||
575 | |||
576 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
577 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %ssent %s %s\n", | ||
578 | sent ? "" : "not ", GM_f2s (fwd), GM_m2s (type)); | ||
579 | if (NULL != q) | ||
580 | { | ||
581 | forced = q->forced; | ||
582 | if (NULL != q->cont) | ||
583 | { | ||
584 | LOG (GNUNET_ERROR_TYPE_DEBUG, " calling cont\n"); | ||
585 | q->cont (q->cont_cls, c, q, type, fwd, size); | ||
586 | } | ||
587 | GNUNET_free (q); | ||
588 | } | ||
589 | else if (type == GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED) | ||
590 | { | ||
591 | /* If NULL == q and ENCRYPTED == type, message must have been ch_mngmnt */ | ||
592 | forced = GNUNET_YES; | ||
593 | } | ||
594 | else | ||
595 | { | ||
596 | forced = GNUNET_NO; | ||
597 | } | ||
598 | if (NULL == c) | ||
599 | { | ||
600 | GNUNET_break (type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN || | ||
601 | type == GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY); | ||
602 | LOG (GNUNET_ERROR_TYPE_ERROR, "Message %s sent on NULL connection!\n", | ||
603 | GM_m2s (type)); | ||
604 | return; | ||
605 | } | ||
606 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P- %p %u\n", c, c->pending_messages); | ||
607 | c->pending_messages--; | ||
608 | if (GNUNET_YES == c->destroy && 0 == c->pending_messages) | ||
609 | { | ||
610 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! destroying connection!\n"); | ||
611 | GMC_destroy (c); | ||
612 | return; | ||
613 | } | ||
614 | /* Send ACK if needed, after accounting for sent ID in fc->queue_n */ | ||
615 | switch (type) | ||
616 | { | ||
617 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
618 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
619 | c->maintenance_q = NULL; | ||
620 | /* Don't trigger a keepalive for sent ACKs, only SYN and SYNACKs */ | ||
621 | if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE == type || !fwd) | ||
622 | schedule_next_keepalive (c, fwd); | ||
623 | break; | ||
624 | |||
625 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
626 | if (GNUNET_YES == sent) | ||
627 | { | ||
628 | GNUNET_assert (NULL != q); | ||
629 | fc->last_pid_sent = pid; // FIXME | ||
630 | GMC_send_ack (c, fwd, GNUNET_NO); | ||
631 | connection_reset_timeout (c, fwd); | ||
632 | } | ||
633 | |||
634 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! Q_N- %p %u\n", fc, fc->queue_n); | ||
635 | if (GNUNET_NO == forced) | ||
636 | { | ||
637 | fc->queue_n--; | ||
638 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
639 | "! accounting pid %u\n", | ||
640 | fc->last_pid_sent); | ||
641 | } | ||
642 | else | ||
643 | { | ||
644 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
645 | "! forced, Q_N not accounting pid %u\n", | ||
646 | fc->last_pid_sent); | ||
647 | } | ||
648 | break; | ||
649 | |||
650 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
651 | if (GNUNET_YES == sent) | ||
652 | connection_reset_timeout (c, fwd); | ||
653 | break; | ||
654 | |||
655 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
656 | fc->poll_msg = NULL; | ||
657 | break; | ||
658 | |||
659 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
660 | fc->ack_msg = NULL; | ||
661 | break; | ||
662 | |||
663 | default: | ||
664 | break; | ||
665 | } | ||
666 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n"); | ||
667 | |||
668 | if (NULL == c->perf) | ||
669 | return; /* Only endpoints are interested in timing. */ | ||
670 | |||
671 | p = c->perf; | ||
672 | usecsperbyte = ((double) wait.rel_value_us) / size; | ||
673 | if (p->size == AVG_MSGS) | ||
674 | { | ||
675 | /* Array is full. Substract oldest value, add new one and store. */ | ||
676 | p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS); | ||
677 | p->usecsperbyte[p->idx] = usecsperbyte; | ||
678 | p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS); | ||
679 | } | ||
680 | else | ||
681 | { | ||
682 | /* Array not yet full. Add current value to avg and store. */ | ||
683 | p->usecsperbyte[p->idx] = usecsperbyte; | ||
684 | p->avg *= p->size; | ||
685 | p->avg += p->usecsperbyte[p->idx]; | ||
686 | p->size++; | ||
687 | p->avg /= p->size; | ||
688 | } | ||
689 | p->idx = (p->idx + 1) % AVG_MSGS; | ||
690 | } | ||
691 | |||
692 | |||
693 | /** | ||
694 | * Get the previous hop in a connection | ||
695 | * | ||
696 | * @param c Connection. | ||
697 | * | ||
698 | * @return Previous peer in the connection. | ||
699 | */ | ||
700 | static struct CadetPeer * | ||
701 | get_prev_hop (const struct CadetConnection *c) | ||
702 | { | ||
703 | GNUNET_PEER_Id id; | ||
704 | |||
705 | LOG (GNUNET_ERROR_TYPE_DEBUG, " get prev hop %s [%u/%u]\n", | ||
706 | GMC_2s (c), c->own_pos, c->path->length); | ||
707 | if (0 == c->own_pos || c->path->length < 2) | ||
708 | id = c->path->peers[0]; | ||
709 | else | ||
710 | id = c->path->peers[c->own_pos - 1]; | ||
711 | |||
712 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", | ||
713 | GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); | ||
714 | |||
715 | return GMP_get_short (id); | ||
716 | } | ||
717 | |||
718 | |||
719 | /** | ||
720 | * Get the next hop in a connection | ||
721 | * | ||
722 | * @param c Connection. | ||
723 | * | ||
724 | * @return Next peer in the connection. | ||
725 | */ | ||
726 | static struct CadetPeer * | ||
727 | get_next_hop (const struct CadetConnection *c) | ||
728 | { | ||
729 | GNUNET_PEER_Id id; | ||
730 | |||
731 | LOG (GNUNET_ERROR_TYPE_DEBUG, " get next hop %s [%u/%u]\n", | ||
732 | GMC_2s (c), c->own_pos, c->path->length); | ||
733 | if ((c->path->length - 1) == c->own_pos || c->path->length < 2) | ||
734 | id = c->path->peers[c->path->length - 1]; | ||
735 | else | ||
736 | id = c->path->peers[c->own_pos + 1]; | ||
737 | |||
738 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ID: %s (%u)\n", | ||
739 | GNUNET_i2s (GNUNET_PEER_resolve2 (id)), id); | ||
740 | |||
741 | return GMP_get_short (id); | ||
742 | } | ||
743 | |||
744 | |||
745 | /** | ||
746 | * Get the hop in a connection. | ||
747 | * | ||
748 | * @param c Connection. | ||
749 | * @param fwd Next hop? | ||
750 | * | ||
751 | * @return Next peer in the connection. | ||
752 | */ | ||
753 | static struct CadetPeer * | ||
754 | get_hop (struct CadetConnection *c, int fwd) | ||
755 | { | ||
756 | if (fwd) | ||
757 | return get_next_hop (c); | ||
758 | return get_prev_hop (c); | ||
759 | } | ||
760 | |||
761 | |||
762 | /** | ||
763 | * Is traffic coming from this sender 'FWD' traffic? | ||
764 | * | ||
765 | * @param c Connection to check. | ||
766 | * @param sender Peer identity of neighbor. | ||
767 | * | ||
768 | * @return #GNUNET_YES in case the sender is the 'prev' hop and therefore | ||
769 | * the traffic is 'FWD'. | ||
770 | * #GNUNET_NO for BCK. | ||
771 | * #GNUNET_SYSERR for errors. | ||
772 | */ | ||
773 | static int | ||
774 | is_fwd (const struct CadetConnection *c, | ||
775 | const struct GNUNET_PeerIdentity *sender) | ||
776 | { | ||
777 | GNUNET_PEER_Id id; | ||
778 | |||
779 | id = GNUNET_PEER_search (sender); | ||
780 | if (GMP_get_short_id (get_prev_hop (c)) == id) | ||
781 | return GNUNET_YES; | ||
782 | |||
783 | if (GMP_get_short_id (get_next_hop (c)) == id) | ||
784 | return GNUNET_NO; | ||
785 | |||
786 | GNUNET_break (0); | ||
787 | return GNUNET_SYSERR; | ||
788 | } | ||
789 | |||
790 | |||
791 | /** | ||
792 | * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE | ||
793 | * or a first CONNECTION_ACK directed to us. | ||
794 | * | ||
795 | * @param connection Connection to confirm. | ||
796 | * @param fwd Should we send it FWD? (root->dest) | ||
797 | * (First (~SYNACK) goes BCK, second (~ACK) goes FWD) | ||
798 | */ | ||
799 | static void | ||
800 | send_connection_ack (struct CadetConnection *connection, int fwd) | ||
801 | { | ||
802 | struct CadetTunnel3 *t; | ||
803 | |||
804 | t = connection->t; | ||
805 | LOG (GNUNET_ERROR_TYPE_INFO, "===> {%14s ACK} on connection %s\n", | ||
806 | GM_f2s (!fwd), GMC_2s (connection)); | ||
807 | GMP_queue_add (get_hop (connection, fwd), NULL, | ||
808 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, | ||
809 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, 0, | ||
810 | sizeof (struct GNUNET_CADET_ConnectionACK), | ||
811 | connection, fwd, &conn_message_sent, NULL); | ||
812 | connection->pending_messages++; | ||
813 | if (CADET_TUNNEL3_NEW == GMT_get_cstate (t)) | ||
814 | GMT_change_cstate (t, CADET_TUNNEL3_WAITING); | ||
815 | if (CADET_CONNECTION_READY != connection->state) | ||
816 | connection_change_state (connection, CADET_CONNECTION_SENT); | ||
817 | } | ||
818 | |||
819 | |||
820 | /** | ||
821 | * Send a notification that a connection is broken. | ||
822 | * | ||
823 | * @param c Connection that is broken. | ||
824 | * @param id1 Peer that has disconnected. | ||
825 | * @param id2 Peer that has disconnected. | ||
826 | * @param fwd Direction towards which to send it. | ||
827 | */ | ||
828 | static void | ||
829 | send_broken (struct CadetConnection *c, | ||
830 | const struct GNUNET_PeerIdentity *id1, | ||
831 | const struct GNUNET_PeerIdentity *id2, | ||
832 | int fwd) | ||
833 | { | ||
834 | struct GNUNET_CADET_ConnectionBroken msg; | ||
835 | |||
836 | msg.header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken)); | ||
837 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
838 | msg.cid = c->id; | ||
839 | msg.peer1 = *id1; | ||
840 | msg.peer2 = *id2; | ||
841 | GMC_send_prebuilt_message (&msg.header, | ||
842 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 0, | ||
843 | c, fwd, GNUNET_YES, NULL, NULL); | ||
844 | } | ||
845 | |||
846 | |||
847 | /** | ||
848 | * Send a notification that a connection is broken, when a connection | ||
849 | * isn't even known to the local peer. | ||
850 | * | ||
851 | * @param connection_id Connection ID. | ||
852 | * @param id1 Peer that has disconnected, probably local peer. | ||
853 | * @param id2 Peer that has disconnected can be NULL if unknown. | ||
854 | * @param peer Peer to notify (neighbor who sent the connection). | ||
855 | */ | ||
856 | static void | ||
857 | send_broken_unknown (const struct GNUNET_CADET_Hash *connection_id, | ||
858 | const struct GNUNET_PeerIdentity *id1, | ||
859 | const struct GNUNET_PeerIdentity *id2, | ||
860 | const struct GNUNET_PeerIdentity *peer_id) | ||
861 | { | ||
862 | struct GNUNET_CADET_ConnectionBroken *msg; | ||
863 | struct CadetPeer *neighbor; | ||
864 | |||
865 | LOG (GNUNET_ERROR_TYPE_INFO, "===> BROKEN on unknown connection %s\n", | ||
866 | GNUNET_h2s (GM_h2hc (connection_id))); | ||
867 | |||
868 | msg = GNUNET_new (struct GNUNET_CADET_ConnectionBroken); | ||
869 | msg->header.size = htons (sizeof (struct GNUNET_CADET_ConnectionBroken)); | ||
870 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN); | ||
871 | msg->cid = *connection_id; | ||
872 | msg->peer1 = *id1; | ||
873 | if (NULL != id2) | ||
874 | msg->peer2 = *id2; | ||
875 | else | ||
876 | memset (&msg->peer2, 0, sizeof (msg->peer2)); | ||
877 | neighbor = GMP_get (peer_id); | ||
878 | GMP_queue_add (neighbor, msg, | ||
879 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, | ||
880 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 2, | ||
881 | sizeof (struct GNUNET_CADET_ConnectionBroken), | ||
882 | NULL, GNUNET_SYSERR, /* connection, fwd */ | ||
883 | NULL, NULL); /* continuation */ | ||
884 | } | ||
885 | |||
886 | |||
887 | /** | ||
888 | * Send keepalive packets for a connection. | ||
889 | * | ||
890 | * @param c Connection to keep alive.. | ||
891 | * @param fwd Is this a FWD keepalive? (owner -> dest). | ||
892 | */ | ||
893 | static void | ||
894 | send_connection_keepalive (struct CadetConnection *c, int fwd) | ||
895 | { | ||
896 | struct GNUNET_MessageHeader msg; | ||
897 | struct CadetFlowControl *fc; | ||
898 | |||
899 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
900 | "keepalive %s for connection %s\n", | ||
901 | GM_f2s (fwd), GMC_2s (c)); | ||
902 | |||
903 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
904 | if (0 < fc->queue_n) | ||
905 | { | ||
906 | LOG (GNUNET_ERROR_TYPE_INFO, "not sending keepalive, traffic in queue\n"); | ||
907 | } | ||
908 | |||
909 | GNUNET_STATISTICS_update (stats, "# keepalives sent", 1, GNUNET_NO); | ||
910 | |||
911 | GNUNET_assert (NULL != c->t); | ||
912 | msg.size = htons (sizeof (msg)); | ||
913 | msg.type = htons (GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE); | ||
914 | |||
915 | GNUNET_assert (NULL == | ||
916 | GMT_send_prebuilt_message (&msg, c->t, c, | ||
917 | GNUNET_NO, NULL, NULL)); | ||
918 | } | ||
919 | |||
920 | |||
921 | /** | ||
922 | * Send CONNECTION_{CREATE/ACK} packets for a connection. | ||
923 | * | ||
924 | * @param c Connection for which to send the message. | ||
925 | * @param fwd If #GNUNET_YES, send CREATE, otherwise send ACK. | ||
926 | */ | ||
927 | static void | ||
928 | connection_recreate (struct CadetConnection *c, int fwd) | ||
929 | { | ||
930 | LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n"); | ||
931 | if (fwd) | ||
932 | GMC_send_create (c); | ||
933 | else | ||
934 | send_connection_ack (c, GNUNET_NO); | ||
935 | } | ||
936 | |||
937 | |||
938 | /** | ||
939 | * Generic connection timer management. | ||
940 | * Depending on the role of the peer in the connection will send the | ||
941 | * appropriate message (build or keepalive) | ||
942 | * | ||
943 | * @param c Conncetion to maintain. | ||
944 | * @param fwd Is FWD? | ||
945 | */ | ||
946 | static void | ||
947 | connection_maintain (struct CadetConnection *c, int fwd) | ||
948 | { | ||
949 | if (GNUNET_NO != c->destroy) | ||
950 | return; | ||
951 | |||
952 | if (CADET_TUNNEL3_SEARCHING == GMT_get_cstate (c->t)) | ||
953 | { | ||
954 | /* TODO DHT GET with RO_BART */ | ||
955 | return; | ||
956 | } | ||
957 | switch (c->state) | ||
958 | { | ||
959 | case CADET_CONNECTION_NEW: | ||
960 | GNUNET_break (0); | ||
961 | /* fall-through */ | ||
962 | case CADET_CONNECTION_SENT: | ||
963 | connection_recreate (c, fwd); | ||
964 | break; | ||
965 | case CADET_CONNECTION_READY: | ||
966 | send_connection_keepalive (c, fwd); | ||
967 | break; | ||
968 | default: | ||
969 | break; | ||
970 | } | ||
971 | } | ||
972 | |||
973 | |||
974 | |||
975 | /** | ||
976 | * Keep the connection alive. | ||
977 | * | ||
978 | * @param c Connection to keep alive. | ||
979 | * @param fwd Direction. | ||
980 | * @param shutdown Are we shutting down? (Don't send traffic) | ||
981 | * Non-zero value for true, not necessarily GNUNET_YES. | ||
982 | */ | ||
983 | static void | ||
984 | connection_keepalive (struct CadetConnection *c, int fwd, int shutdown) | ||
985 | { | ||
986 | LOG (GNUNET_ERROR_TYPE_DEBUG, "%s keepalive for %s\n", | ||
987 | GM_f2s (fwd), GMC_2s (c)); | ||
988 | |||
989 | if (fwd) | ||
990 | c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK; | ||
991 | else | ||
992 | c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK; | ||
993 | |||
994 | if (GNUNET_NO != shutdown) | ||
995 | return; | ||
996 | |||
997 | connection_maintain (c, fwd); | ||
998 | |||
999 | /* Next execution will be scheduled by message_sent */ | ||
1000 | } | ||
1001 | |||
1002 | |||
1003 | /** | ||
1004 | * Keep the connection alive in the FWD direction. | ||
1005 | * | ||
1006 | * @param cls Closure (connection to keepalive). | ||
1007 | * @param tc TaskContext. | ||
1008 | */ | ||
1009 | static void | ||
1010 | connection_fwd_keepalive (void *cls, | ||
1011 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1012 | { | ||
1013 | connection_keepalive ((struct CadetConnection *) cls, | ||
1014 | GNUNET_YES, | ||
1015 | tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN); | ||
1016 | } | ||
1017 | |||
1018 | |||
1019 | /** | ||
1020 | * Keep the connection alive in the BCK direction. | ||
1021 | * | ||
1022 | * @param cls Closure (connection to keepalive). | ||
1023 | * @param tc TaskContext. | ||
1024 | */ | ||
1025 | static void | ||
1026 | connection_bck_keepalive (void *cls, | ||
1027 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1028 | { | ||
1029 | connection_keepalive ((struct CadetConnection *) cls, | ||
1030 | GNUNET_NO, | ||
1031 | tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN); | ||
1032 | } | ||
1033 | |||
1034 | |||
1035 | /** | ||
1036 | * Schedule next keepalive task, taking in consideration | ||
1037 | * the connection state and number of retries. | ||
1038 | * | ||
1039 | * If the peer is not the origin, do nothing. | ||
1040 | * | ||
1041 | * @param c Connection for which to schedule the next keepalive. | ||
1042 | * @param fwd Direction for the next keepalive. | ||
1043 | */ | ||
1044 | static void | ||
1045 | schedule_next_keepalive (struct CadetConnection *c, int fwd) | ||
1046 | { | ||
1047 | struct GNUNET_TIME_Relative delay; | ||
1048 | GNUNET_SCHEDULER_TaskIdentifier *task_id; | ||
1049 | GNUNET_SCHEDULER_Task keepalive_task; | ||
1050 | |||
1051 | if (GNUNET_NO == GMC_is_origin (c, fwd)) | ||
1052 | return; | ||
1053 | |||
1054 | /* Calculate delay to use, depending on the state of the connection */ | ||
1055 | if (CADET_CONNECTION_READY == c->state) | ||
1056 | { | ||
1057 | delay = refresh_connection_time; | ||
1058 | } | ||
1059 | else | ||
1060 | { | ||
1061 | if (1 > c->create_retry) | ||
1062 | c->create_retry = 1; | ||
1063 | delay = GNUNET_TIME_relative_multiply (create_connection_time, | ||
1064 | c->create_retry); | ||
1065 | if (c->create_retry < 64) | ||
1066 | c->create_retry *= 2; | ||
1067 | } | ||
1068 | |||
1069 | /* Select direction-dependent parameters */ | ||
1070 | if (GNUNET_YES == fwd) | ||
1071 | { | ||
1072 | task_id = &c->fwd_maintenance_task; | ||
1073 | keepalive_task = &connection_fwd_keepalive; | ||
1074 | } | ||
1075 | else | ||
1076 | { | ||
1077 | task_id = &c->bck_maintenance_task; | ||
1078 | keepalive_task = &connection_bck_keepalive; | ||
1079 | } | ||
1080 | |||
1081 | /* Check that no one scheduled it before us */ | ||
1082 | if (GNUNET_SCHEDULER_NO_TASK != *task_id) | ||
1083 | { | ||
1084 | /* No need for a _break. It can happen for instance when sending a SYNACK | ||
1085 | * for a duplicate SYN: the first SYNACK scheduled the task. */ | ||
1086 | GNUNET_SCHEDULER_cancel (*task_id); | ||
1087 | } | ||
1088 | |||
1089 | /* Schedule the task */ | ||
1090 | *task_id = GNUNET_SCHEDULER_add_delayed (delay, keepalive_task, c); | ||
1091 | LOG (GNUNET_ERROR_TYPE_DEBUG, "next keepalive in %s\n", | ||
1092 | GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES)); | ||
1093 | } | ||
1094 | |||
1095 | |||
1096 | /** | ||
1097 | * @brief Re-initiate traffic on this connection if necessary. | ||
1098 | * | ||
1099 | * Check if there is traffic queued towards this peer | ||
1100 | * and the core transmit handle is NULL (traffic was stalled). | ||
1101 | * If so, call core tmt rdy. | ||
1102 | * | ||
1103 | * @param c Connection on which initiate traffic. | ||
1104 | * @param fwd Is this about fwd traffic? | ||
1105 | */ | ||
1106 | static void | ||
1107 | connection_unlock_queue (struct CadetConnection *c, int fwd) | ||
1108 | { | ||
1109 | struct CadetPeer *peer; | ||
1110 | |||
1111 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1112 | "connection_unlock_queue %s on %s\n", | ||
1113 | GM_f2s (fwd), GMC_2s (c)); | ||
1114 | |||
1115 | if (GMC_is_terminal (c, fwd)) | ||
1116 | { | ||
1117 | LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n"); | ||
1118 | return; | ||
1119 | } | ||
1120 | |||
1121 | peer = get_hop (c, fwd); | ||
1122 | GMP_queue_unlock (peer, c); | ||
1123 | } | ||
1124 | |||
1125 | |||
1126 | /** | ||
1127 | * Cancel all transmissions that belong to a certain connection. | ||
1128 | * | ||
1129 | * If the connection is scheduled for destruction and no more messages are left, | ||
1130 | * the connection will be destroyed by the continuation call. | ||
1131 | * | ||
1132 | * @param c Connection which to cancel. Might be destroyed during this call. | ||
1133 | * @param fwd Cancel fwd traffic? | ||
1134 | */ | ||
1135 | static void | ||
1136 | connection_cancel_queues (struct CadetConnection *c, int fwd) | ||
1137 | { | ||
1138 | struct CadetFlowControl *fc; | ||
1139 | struct CadetPeer *peer; | ||
1140 | |||
1141 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1142 | " *** Cancel %s queues for connection %s\n", | ||
1143 | GM_f2s (fwd), GMC_2s (c)); | ||
1144 | if (NULL == c) | ||
1145 | { | ||
1146 | GNUNET_break (0); | ||
1147 | return; | ||
1148 | } | ||
1149 | |||
1150 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
1151 | if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task) | ||
1152 | { | ||
1153 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
1154 | fc->poll_task = GNUNET_SCHEDULER_NO_TASK; | ||
1155 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Cancel POLL in ccq for fc %p\n", fc); | ||
1156 | } | ||
1157 | peer = get_hop (c, fwd); | ||
1158 | GMP_queue_cancel (peer, c); | ||
1159 | } | ||
1160 | |||
1161 | |||
1162 | /** | ||
1163 | * Function called if a connection has been stalled for a while, | ||
1164 | * possibly due to a missed ACK. Poll the neighbor about its ACK status. | ||
1165 | * | ||
1166 | * @param cls Closure (poll ctx). | ||
1167 | * @param tc TaskContext. | ||
1168 | */ | ||
1169 | static void | ||
1170 | connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
1171 | |||
1172 | |||
1173 | /** | ||
1174 | * Callback called when a queued POLL message is sent. | ||
1175 | * | ||
1176 | * @param cls Closure (FC). | ||
1177 | * @param c Connection this message was on. | ||
1178 | * @param q Queue handler this call invalidates. | ||
1179 | * @param type Type of message sent. | ||
1180 | * @param fwd Was this a FWD going message? | ||
1181 | * @param size Size of the message. | ||
1182 | */ | ||
1183 | static void | ||
1184 | poll_sent (void *cls, | ||
1185 | struct CadetConnection *c, | ||
1186 | struct CadetConnectionQueue *q, | ||
1187 | uint16_t type, int fwd, size_t size) | ||
1188 | { | ||
1189 | struct CadetFlowControl *fc = cls; | ||
1190 | |||
1191 | if (2 == c->destroy) | ||
1192 | { | ||
1193 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL canceled on shutdown\n"); | ||
1194 | return; | ||
1195 | } | ||
1196 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1197 | " *** POLL sent for , scheduling new one!\n"); | ||
1198 | fc->poll_msg = NULL; | ||
1199 | fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time); | ||
1200 | fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, | ||
1201 | &connection_poll, fc); | ||
1202 | LOG (GNUNET_ERROR_TYPE_DEBUG, " task %u\n", fc->poll_task); | ||
1203 | |||
1204 | } | ||
1205 | |||
1206 | /** | ||
1207 | * Function called if a connection has been stalled for a while, | ||
1208 | * possibly due to a missed ACK. Poll the neighbor about its ACK status. | ||
1209 | * | ||
1210 | * @param cls Closure (poll ctx). | ||
1211 | * @param tc TaskContext. | ||
1212 | */ | ||
1213 | static void | ||
1214 | connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1215 | { | ||
1216 | struct CadetFlowControl *fc = cls; | ||
1217 | struct GNUNET_CADET_Poll msg; | ||
1218 | struct CadetConnection *c; | ||
1219 | |||
1220 | fc->poll_task = GNUNET_SCHEDULER_NO_TASK; | ||
1221 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1222 | { | ||
1223 | return; | ||
1224 | } | ||
1225 | |||
1226 | c = fc->c; | ||
1227 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling connection %s %s\n", | ||
1228 | GMC_2s (c), fc == &c->fwd_fc ? "FWD" : "BCK"); | ||
1229 | |||
1230 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_POLL); | ||
1231 | msg.header.size = htons (sizeof (msg)); | ||
1232 | msg.pid = htonl (fc->last_pid_sent); | ||
1233 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** last pid sent: %u!\n", fc->last_pid_sent); | ||
1234 | fc->poll_msg = | ||
1235 | GMC_send_prebuilt_message (&msg.header, | ||
1236 | GNUNET_MESSAGE_TYPE_CADET_POLL, | ||
1237 | fc->last_pid_sent, | ||
1238 | c, fc == &c->fwd_fc, GNUNET_YES, | ||
1239 | &poll_sent, fc); | ||
1240 | } | ||
1241 | |||
1242 | |||
1243 | /** | ||
1244 | * Timeout function due to lack of keepalive/traffic from the owner. | ||
1245 | * Destroys connection if called. | ||
1246 | * | ||
1247 | * @param cls Closure (connection to destroy). | ||
1248 | * @param tc TaskContext. | ||
1249 | */ | ||
1250 | static void | ||
1251 | connection_fwd_timeout (void *cls, | ||
1252 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1253 | { | ||
1254 | struct CadetConnection *c = cls; | ||
1255 | |||
1256 | c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK; | ||
1257 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1258 | return; | ||
1259 | |||
1260 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s FWD timed out. Destroying.\n", | ||
1261 | GMC_2s (c)); | ||
1262 | if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */ | ||
1263 | { | ||
1264 | GNUNET_break (0); | ||
1265 | return; | ||
1266 | } | ||
1267 | |||
1268 | GMC_destroy (c); | ||
1269 | } | ||
1270 | |||
1271 | |||
1272 | /** | ||
1273 | * Timeout function due to lack of keepalive/traffic from the destination. | ||
1274 | * Destroys connection if called. | ||
1275 | * | ||
1276 | * @param cls Closure (connection to destroy). | ||
1277 | * @param tc TaskContext | ||
1278 | */ | ||
1279 | static void | ||
1280 | connection_bck_timeout (void *cls, | ||
1281 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1282 | { | ||
1283 | struct CadetConnection *c = cls; | ||
1284 | |||
1285 | c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK; | ||
1286 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1287 | return; | ||
1288 | |||
1289 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s BCK timed out. Destroying.\n", | ||
1290 | GMC_2s (c)); | ||
1291 | |||
1292 | if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */ | ||
1293 | { | ||
1294 | GNUNET_break (0); | ||
1295 | return; | ||
1296 | } | ||
1297 | |||
1298 | GMC_destroy (c); | ||
1299 | } | ||
1300 | |||
1301 | |||
1302 | /** | ||
1303 | * Resets the connection timeout task, some other message has done the | ||
1304 | * task's job. | ||
1305 | * - For the first peer on the direction this means to send | ||
1306 | * a keepalive or a path confirmation message (either create or ACK). | ||
1307 | * - For all other peers, this means to destroy the connection, | ||
1308 | * due to lack of activity. | ||
1309 | * Starts the timeout if no timeout was running (connection just created). | ||
1310 | * | ||
1311 | * @param c Connection whose timeout to reset. | ||
1312 | * @param fwd Is this forward? | ||
1313 | * | ||
1314 | * TODO use heap to improve efficiency of scheduler. | ||
1315 | */ | ||
1316 | static void | ||
1317 | connection_reset_timeout (struct CadetConnection *c, int fwd) | ||
1318 | { | ||
1319 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s reset timeout\n", GM_f2s (fwd)); | ||
1320 | |||
1321 | if (GMC_is_origin (c, fwd)) /* Startpoint */ | ||
1322 | { | ||
1323 | schedule_next_keepalive (c, fwd); | ||
1324 | } | ||
1325 | else /* Relay, endpoint. */ | ||
1326 | { | ||
1327 | struct GNUNET_TIME_Relative delay; | ||
1328 | GNUNET_SCHEDULER_TaskIdentifier *ti; | ||
1329 | GNUNET_SCHEDULER_Task f; | ||
1330 | |||
1331 | ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task; | ||
1332 | |||
1333 | if (GNUNET_SCHEDULER_NO_TASK != *ti) | ||
1334 | GNUNET_SCHEDULER_cancel (*ti); | ||
1335 | delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4); | ||
1336 | f = fwd ? &connection_fwd_timeout : &connection_bck_timeout; | ||
1337 | *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c); | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | |||
1342 | /** | ||
1343 | * Add the connection to the list of both neighbors. | ||
1344 | * | ||
1345 | * @param c Connection. | ||
1346 | * | ||
1347 | * @return #GNUNET_OK if everything went fine | ||
1348 | * #GNUNET_SYSERR if the was an error and @c c is malformed. | ||
1349 | */ | ||
1350 | static int | ||
1351 | register_neighbors (struct CadetConnection *c) | ||
1352 | { | ||
1353 | struct CadetPeer *next_peer; | ||
1354 | struct CadetPeer *prev_peer; | ||
1355 | |||
1356 | next_peer = get_next_hop (c); | ||
1357 | prev_peer = get_prev_hop (c); | ||
1358 | |||
1359 | LOG (GNUNET_ERROR_TYPE_DEBUG, "register neighbors for connection %s\n", | ||
1360 | GMC_2s (c)); | ||
1361 | path_debug (c->path); | ||
1362 | LOG (GNUNET_ERROR_TYPE_DEBUG, "own pos %u\n", c->own_pos); | ||
1363 | LOG (GNUNET_ERROR_TYPE_DEBUG, "putting connection %s to next peer %p\n", | ||
1364 | GMC_2s (c), next_peer); | ||
1365 | LOG (GNUNET_ERROR_TYPE_DEBUG, "next peer %p %s\n", next_peer, GMP_2s (next_peer)); | ||
1366 | LOG (GNUNET_ERROR_TYPE_DEBUG, "putting connection %s to prev peer %p\n", | ||
1367 | GMC_2s (c), prev_peer); | ||
1368 | LOG (GNUNET_ERROR_TYPE_DEBUG, "prev peer %p %s\n", prev_peer, GMP_2s (prev_peer)); | ||
1369 | |||
1370 | if (GNUNET_NO == GMP_is_neighbor (next_peer) | ||
1371 | || GNUNET_NO == GMP_is_neighbor (prev_peer)) | ||
1372 | { | ||
1373 | if (GMC_is_origin (c, GNUNET_YES)) | ||
1374 | GNUNET_STATISTICS_update (stats, "# local bad paths", 1, GNUNET_NO); | ||
1375 | GNUNET_STATISTICS_update (stats, "# bad paths", 1, GNUNET_NO); | ||
1376 | |||
1377 | LOG (GNUNET_ERROR_TYPE_DEBUG, " register neighbors failed\n"); | ||
1378 | LOG (GNUNET_ERROR_TYPE_DEBUG, " prev: %s, neighbor?: %d\n", | ||
1379 | GMP_2s (prev_peer), GMP_is_neighbor (prev_peer)); | ||
1380 | LOG (GNUNET_ERROR_TYPE_DEBUG, " next: %s, neighbor?: %d\n", | ||
1381 | GMP_2s (next_peer), GMP_is_neighbor (next_peer)); | ||
1382 | return GNUNET_SYSERR; | ||
1383 | } | ||
1384 | |||
1385 | GMP_add_connection (next_peer, c); | ||
1386 | GMP_add_connection (prev_peer, c); | ||
1387 | |||
1388 | return GNUNET_OK; | ||
1389 | } | ||
1390 | |||
1391 | |||
1392 | /** | ||
1393 | * Remove the connection from the list of both neighbors. | ||
1394 | * | ||
1395 | * @param c Connection. | ||
1396 | */ | ||
1397 | static void | ||
1398 | unregister_neighbors (struct CadetConnection *c) | ||
1399 | { | ||
1400 | struct CadetPeer *peer; | ||
1401 | |||
1402 | peer = get_next_hop (c); | ||
1403 | if (GNUNET_OK != GMP_remove_connection (peer, c)) | ||
1404 | { | ||
1405 | GNUNET_assert (CADET_CONNECTION_NEW == c->state | ||
1406 | || CADET_CONNECTION_DESTROYED == c->state); | ||
1407 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate: %u\n", c->state); | ||
1408 | if (NULL != c->t) GMT_debug (c->t); | ||
1409 | } | ||
1410 | |||
1411 | peer = get_prev_hop (c); | ||
1412 | if (GNUNET_OK != GMP_remove_connection (peer, c)) | ||
1413 | { | ||
1414 | GNUNET_assert (CADET_CONNECTION_NEW == c->state | ||
1415 | || CADET_CONNECTION_DESTROYED == c->state); | ||
1416 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate: %u\n", c->state); | ||
1417 | if (NULL != c->t) GMT_debug (c->t); | ||
1418 | } | ||
1419 | } | ||
1420 | |||
1421 | |||
1422 | /** | ||
1423 | * Bind the connection to the peer and the tunnel to that peer. | ||
1424 | * | ||
1425 | * If the peer has no tunnel, create one. Update tunnel and connection | ||
1426 | * data structres to reflect new status. | ||
1427 | * | ||
1428 | * @param c Connection. | ||
1429 | * @param peer Peer. | ||
1430 | */ | ||
1431 | static void | ||
1432 | add_to_peer (struct CadetConnection *c, struct CadetPeer *peer) | ||
1433 | { | ||
1434 | GMP_add_tunnel (peer); | ||
1435 | c->t = GMP_get_tunnel (peer); | ||
1436 | GMT_add_connection (c->t, c); | ||
1437 | } | ||
1438 | |||
1439 | |||
1440 | /** | ||
1441 | * Builds a path from a PeerIdentity array. | ||
1442 | * | ||
1443 | * @param peers PeerIdentity array. | ||
1444 | * @param size Size of the @c peers array. | ||
1445 | * @param own_pos Output parameter: own position in the path. | ||
1446 | * | ||
1447 | * @return Fixed and shortened path. | ||
1448 | */ | ||
1449 | static struct CadetPeerPath * | ||
1450 | build_path_from_peer_ids (struct GNUNET_PeerIdentity *peers, | ||
1451 | unsigned int size, | ||
1452 | unsigned int *own_pos) | ||
1453 | { | ||
1454 | struct CadetPeerPath *path; | ||
1455 | GNUNET_PEER_Id shortid; | ||
1456 | unsigned int i; | ||
1457 | unsigned int j; | ||
1458 | unsigned int offset; | ||
1459 | |||
1460 | /* Create path */ | ||
1461 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n"); | ||
1462 | path = path_new (size); | ||
1463 | *own_pos = 0; | ||
1464 | offset = 0; | ||
1465 | for (i = 0; i < size; i++) | ||
1466 | { | ||
1467 | LOG (GNUNET_ERROR_TYPE_DEBUG, " - %u: taking %s\n", | ||
1468 | i, GNUNET_i2s (&peers[i])); | ||
1469 | shortid = GNUNET_PEER_intern (&peers[i]); | ||
1470 | |||
1471 | /* Check for loops / duplicates */ | ||
1472 | for (j = 0; j < i - offset; j++) | ||
1473 | { | ||
1474 | if (path->peers[j] == shortid) | ||
1475 | { | ||
1476 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already exists at pos %u\n", j); | ||
1477 | offset = i - j; | ||
1478 | LOG (GNUNET_ERROR_TYPE_DEBUG, " offset now %u\n", offset); | ||
1479 | GNUNET_PEER_change_rc (shortid, -1); | ||
1480 | } | ||
1481 | } | ||
1482 | LOG (GNUNET_ERROR_TYPE_DEBUG, " storing at %u\n", i - offset); | ||
1483 | path->peers[i - offset] = shortid; | ||
1484 | if (path->peers[i - offset] == myid) | ||
1485 | *own_pos = i - offset; | ||
1486 | } | ||
1487 | path->length -= offset; | ||
1488 | |||
1489 | if (path->peers[*own_pos] != myid) | ||
1490 | { | ||
1491 | /* create path: self not found in path through self */ | ||
1492 | GNUNET_break_op (0); | ||
1493 | path_destroy (path); | ||
1494 | return NULL; | ||
1495 | } | ||
1496 | |||
1497 | return path; | ||
1498 | } | ||
1499 | |||
1500 | |||
1501 | /** | ||
1502 | * Log receipt of message on stderr (INFO level). | ||
1503 | * | ||
1504 | * @param message Message received. | ||
1505 | * @param peer Peer who sent the message. | ||
1506 | * @param hash Connection ID. | ||
1507 | */ | ||
1508 | static void | ||
1509 | log_message (const struct GNUNET_MessageHeader *message, | ||
1510 | const struct GNUNET_PeerIdentity *peer, | ||
1511 | const struct GNUNET_CADET_Hash *hash) | ||
1512 | { | ||
1513 | LOG (GNUNET_ERROR_TYPE_INFO, "<-- %s on connection %s from %s\n", | ||
1514 | GM_m2s (ntohs (message->type)), GNUNET_h2s (GM_h2hc (hash)), | ||
1515 | GNUNET_i2s (peer)); | ||
1516 | } | ||
1517 | |||
1518 | /******************************************************************************/ | ||
1519 | /******************************** API ***********************************/ | ||
1520 | /******************************************************************************/ | ||
1521 | |||
1522 | /** | ||
1523 | * Core handler for connection creation. | ||
1524 | * | ||
1525 | * @param cls Closure (unused). | ||
1526 | * @param peer Sender (neighbor). | ||
1527 | * @param message Message. | ||
1528 | * | ||
1529 | * @return GNUNET_OK to keep the connection open, | ||
1530 | * GNUNET_SYSERR to close it (signal serious error) | ||
1531 | */ | ||
1532 | int | ||
1533 | GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
1534 | const struct GNUNET_MessageHeader *message) | ||
1535 | { | ||
1536 | struct GNUNET_CADET_ConnectionCreate *msg; | ||
1537 | struct GNUNET_PeerIdentity *id; | ||
1538 | struct GNUNET_CADET_Hash *cid; | ||
1539 | struct CadetPeerPath *path; | ||
1540 | struct CadetPeer *dest_peer; | ||
1541 | struct CadetPeer *orig_peer; | ||
1542 | struct CadetConnection *c; | ||
1543 | unsigned int own_pos; | ||
1544 | uint16_t size; | ||
1545 | |||
1546 | /* Check size */ | ||
1547 | size = ntohs (message->size); | ||
1548 | if (size < sizeof (struct GNUNET_CADET_ConnectionCreate)) | ||
1549 | { | ||
1550 | GNUNET_break_op (0); | ||
1551 | return GNUNET_OK; | ||
1552 | } | ||
1553 | |||
1554 | /* Calculate hops */ | ||
1555 | size -= sizeof (struct GNUNET_CADET_ConnectionCreate); | ||
1556 | if (size % sizeof (struct GNUNET_PeerIdentity)) | ||
1557 | { | ||
1558 | GNUNET_break_op (0); | ||
1559 | return GNUNET_OK; | ||
1560 | } | ||
1561 | size /= sizeof (struct GNUNET_PeerIdentity); | ||
1562 | if (1 > size) | ||
1563 | { | ||
1564 | GNUNET_break_op (0); | ||
1565 | return GNUNET_OK; | ||
1566 | } | ||
1567 | LOG (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size); | ||
1568 | |||
1569 | /* Get parameters */ | ||
1570 | msg = (struct GNUNET_CADET_ConnectionCreate *) message; | ||
1571 | cid = &msg->cid; | ||
1572 | log_message (message, peer, cid); | ||
1573 | id = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
1574 | LOG (GNUNET_ERROR_TYPE_DEBUG, " origin: %s\n", GNUNET_i2s (id)); | ||
1575 | |||
1576 | /* Create connection */ | ||
1577 | c = connection_get (cid); | ||
1578 | if (NULL == c) | ||
1579 | { | ||
1580 | path = build_path_from_peer_ids ((struct GNUNET_PeerIdentity *) &msg[1], | ||
1581 | size, &own_pos); | ||
1582 | if (NULL == path) | ||
1583 | return GNUNET_OK; | ||
1584 | if (0 == own_pos) | ||
1585 | { | ||
1586 | GNUNET_break_op (0); | ||
1587 | path_destroy (path); | ||
1588 | return GNUNET_OK; | ||
1589 | } | ||
1590 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos); | ||
1591 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n"); | ||
1592 | c = GMC_new (cid, NULL, path_duplicate (path), own_pos); | ||
1593 | if (NULL == c) | ||
1594 | { | ||
1595 | if (path->length - 1 == own_pos) | ||
1596 | { | ||
1597 | /* If we are destination, why did the creation fail? */ | ||
1598 | GNUNET_break (0); | ||
1599 | return GNUNET_OK; | ||
1600 | } | ||
1601 | send_broken_unknown (cid, &my_full_id, | ||
1602 | GNUNET_PEER_resolve2 (path->peers[own_pos + 1]), | ||
1603 | peer); | ||
1604 | path_destroy (path); | ||
1605 | return GNUNET_OK; | ||
1606 | } | ||
1607 | GMP_add_path_to_all (path, GNUNET_NO); | ||
1608 | connection_reset_timeout (c, GNUNET_YES); | ||
1609 | } | ||
1610 | else | ||
1611 | { | ||
1612 | path = path_duplicate (c->path); | ||
1613 | } | ||
1614 | if (CADET_CONNECTION_NEW == c->state) | ||
1615 | connection_change_state (c, CADET_CONNECTION_SENT); | ||
1616 | |||
1617 | /* Remember peers */ | ||
1618 | dest_peer = GMP_get (&id[size - 1]); | ||
1619 | orig_peer = GMP_get (&id[0]); | ||
1620 | |||
1621 | /* Is it a connection to us? */ | ||
1622 | if (c->own_pos == path->length - 1) | ||
1623 | { | ||
1624 | LOG (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n"); | ||
1625 | GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES); | ||
1626 | |||
1627 | add_to_peer (c, orig_peer); | ||
1628 | if (CADET_TUNNEL3_NEW == GMT_get_cstate (c->t)) | ||
1629 | GMT_change_cstate (c->t, CADET_TUNNEL3_WAITING); | ||
1630 | |||
1631 | send_connection_ack (c, GNUNET_NO); | ||
1632 | if (CADET_CONNECTION_SENT == c->state) | ||
1633 | connection_change_state (c, CADET_CONNECTION_ACK); | ||
1634 | } | ||
1635 | else | ||
1636 | { | ||
1637 | /* It's for somebody else! Retransmit. */ | ||
1638 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n"); | ||
1639 | GMP_add_path (dest_peer, path_duplicate (path), GNUNET_NO); | ||
1640 | GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_NO); | ||
1641 | GMC_send_prebuilt_message (message, | ||
1642 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0, | ||
1643 | c, GNUNET_YES, GNUNET_YES, | ||
1644 | NULL, NULL); | ||
1645 | } | ||
1646 | path_destroy (path); | ||
1647 | return GNUNET_OK; | ||
1648 | } | ||
1649 | |||
1650 | |||
1651 | /** | ||
1652 | * Core handler for path confirmations. | ||
1653 | * | ||
1654 | * @param cls closure | ||
1655 | * @param message message | ||
1656 | * @param peer peer identity this notification is about | ||
1657 | * | ||
1658 | * @return GNUNET_OK to keep the connection open, | ||
1659 | * GNUNET_SYSERR to close it (signal serious error) | ||
1660 | */ | ||
1661 | int | ||
1662 | GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
1663 | const struct GNUNET_MessageHeader *message) | ||
1664 | { | ||
1665 | struct GNUNET_CADET_ConnectionACK *msg; | ||
1666 | struct CadetConnection *c; | ||
1667 | struct CadetPeerPath *p; | ||
1668 | struct CadetPeer *pi; | ||
1669 | enum CadetConnectionState oldstate; | ||
1670 | int fwd; | ||
1671 | |||
1672 | msg = (struct GNUNET_CADET_ConnectionACK *) message; | ||
1673 | log_message (message, peer, &msg->cid); | ||
1674 | c = connection_get (&msg->cid); | ||
1675 | if (NULL == c) | ||
1676 | { | ||
1677 | GNUNET_STATISTICS_update (stats, "# control on unknown connection", | ||
1678 | 1, GNUNET_NO); | ||
1679 | LOG (GNUNET_ERROR_TYPE_DEBUG, " don't know the connection!\n"); | ||
1680 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
1681 | return GNUNET_OK; | ||
1682 | } | ||
1683 | |||
1684 | if (GNUNET_NO != c->destroy) | ||
1685 | { | ||
1686 | LOG (GNUNET_ERROR_TYPE_DEBUG, " connection being destroyed\n"); | ||
1687 | return GNUNET_OK; | ||
1688 | } | ||
1689 | |||
1690 | oldstate = c->state; | ||
1691 | LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n", GNUNET_i2s (peer)); | ||
1692 | pi = GMP_get (peer); | ||
1693 | if (get_next_hop (c) == pi) | ||
1694 | { | ||
1695 | LOG (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n"); | ||
1696 | fwd = GNUNET_NO; | ||
1697 | if (CADET_CONNECTION_SENT == oldstate) | ||
1698 | connection_change_state (c, CADET_CONNECTION_ACK); | ||
1699 | } | ||
1700 | else if (get_prev_hop (c) == pi) | ||
1701 | { | ||
1702 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK\n"); | ||
1703 | fwd = GNUNET_YES; | ||
1704 | connection_change_state (c, CADET_CONNECTION_READY); | ||
1705 | } | ||
1706 | else | ||
1707 | { | ||
1708 | GNUNET_break_op (0); | ||
1709 | return GNUNET_OK; | ||
1710 | } | ||
1711 | |||
1712 | connection_reset_timeout (c, fwd); | ||
1713 | |||
1714 | /* Add path to peers? */ | ||
1715 | p = c->path; | ||
1716 | if (NULL != p) | ||
1717 | { | ||
1718 | GMP_add_path_to_all (p, GNUNET_YES); | ||
1719 | } | ||
1720 | else | ||
1721 | { | ||
1722 | GNUNET_break (0); | ||
1723 | } | ||
1724 | |||
1725 | /* Message for us as creator? */ | ||
1726 | if (GMC_is_origin (c, GNUNET_YES)) | ||
1727 | { | ||
1728 | if (GNUNET_NO != fwd) | ||
1729 | { | ||
1730 | GNUNET_break_op (0); | ||
1731 | return GNUNET_OK; | ||
1732 | } | ||
1733 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n"); | ||
1734 | |||
1735 | /* If just created, cancel the short timeout and start a long one */ | ||
1736 | if (CADET_CONNECTION_SENT == oldstate) | ||
1737 | connection_reset_timeout (c, GNUNET_YES); | ||
1738 | |||
1739 | /* Change connection state */ | ||
1740 | connection_change_state (c, CADET_CONNECTION_READY); | ||
1741 | send_connection_ack (c, GNUNET_YES); | ||
1742 | |||
1743 | /* Change tunnel state, trigger KX */ | ||
1744 | if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t)) | ||
1745 | GMT_change_cstate (c->t, CADET_TUNNEL3_READY); | ||
1746 | |||
1747 | return GNUNET_OK; | ||
1748 | } | ||
1749 | |||
1750 | /* Message for us as destination? */ | ||
1751 | if (GMC_is_terminal (c, GNUNET_YES)) | ||
1752 | { | ||
1753 | if (GNUNET_YES != fwd) | ||
1754 | { | ||
1755 | GNUNET_break_op (0); | ||
1756 | return GNUNET_OK; | ||
1757 | } | ||
1758 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n"); | ||
1759 | |||
1760 | /* If just created, cancel the short timeout and start a long one */ | ||
1761 | if (CADET_CONNECTION_ACK == oldstate) | ||
1762 | connection_reset_timeout (c, GNUNET_NO); | ||
1763 | |||
1764 | /* Change tunnel state */ | ||
1765 | if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t)) | ||
1766 | GMT_change_cstate (c->t, CADET_TUNNEL3_READY); | ||
1767 | |||
1768 | return GNUNET_OK; | ||
1769 | } | ||
1770 | |||
1771 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
1772 | GMC_send_prebuilt_message (message, | ||
1773 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, 0, | ||
1774 | c, fwd, GNUNET_YES, NULL, NULL); | ||
1775 | return GNUNET_OK; | ||
1776 | } | ||
1777 | |||
1778 | |||
1779 | /** | ||
1780 | * Core handler for notifications of broken connections. | ||
1781 | * | ||
1782 | * @param cls Closure (unused). | ||
1783 | * @param id Peer identity of sending neighbor. | ||
1784 | * @param message Message. | ||
1785 | * | ||
1786 | * @return GNUNET_OK to keep the connection open, | ||
1787 | * GNUNET_SYSERR to close it (signal serious error) | ||
1788 | */ | ||
1789 | int | ||
1790 | GMC_handle_broken (void* cls, | ||
1791 | const struct GNUNET_PeerIdentity* id, | ||
1792 | const struct GNUNET_MessageHeader* message) | ||
1793 | { | ||
1794 | struct GNUNET_CADET_ConnectionBroken *msg; | ||
1795 | struct CadetConnection *c; | ||
1796 | int fwd; | ||
1797 | |||
1798 | msg = (struct GNUNET_CADET_ConnectionBroken *) message; | ||
1799 | log_message (message, id, &msg->cid); | ||
1800 | LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", | ||
1801 | GNUNET_i2s (&msg->peer1)); | ||
1802 | LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n", | ||
1803 | GNUNET_i2s (&msg->peer2)); | ||
1804 | c = connection_get (&msg->cid); | ||
1805 | if (NULL == c) | ||
1806 | { | ||
1807 | LOG (GNUNET_ERROR_TYPE_DEBUG, " duplicate CONNECTION_BROKEN\n"); | ||
1808 | return GNUNET_OK; | ||
1809 | } | ||
1810 | |||
1811 | fwd = is_fwd (c, id); | ||
1812 | if (GMC_is_terminal (c, fwd)) | ||
1813 | { | ||
1814 | struct GNUNET_MessageHeader *out_msg; | ||
1815 | struct CadetPeer *neighbor; | ||
1816 | struct CadetPeer *endpoint; | ||
1817 | |||
1818 | neighbor = get_hop (c, !fwd); | ||
1819 | endpoint = GMP_get_short (c->path->peers[c->path->length - 1]); | ||
1820 | path_invalidate (c->path); | ||
1821 | GMP_notify_broken_link (endpoint, &msg->peer1, &msg->peer2); | ||
1822 | c->state = CADET_CONNECTION_DESTROYED; | ||
1823 | while (NULL != (out_msg = GMP_connection_pop (neighbor, c))) | ||
1824 | { | ||
1825 | GNUNET_assert (NULL == | ||
1826 | GMT_send_prebuilt_message (out_msg, c->t, NULL, GNUNET_YES, | ||
1827 | NULL, NULL)); | ||
1828 | } | ||
1829 | |||
1830 | GMC_destroy (c); | ||
1831 | } | ||
1832 | else | ||
1833 | { | ||
1834 | GMC_send_prebuilt_message (message, | ||
1835 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, 0, | ||
1836 | c, fwd, GNUNET_YES, NULL, NULL); | ||
1837 | c->destroy = GNUNET_YES; | ||
1838 | connection_cancel_queues (c, !fwd); | ||
1839 | } | ||
1840 | |||
1841 | return GNUNET_OK; | ||
1842 | |||
1843 | } | ||
1844 | |||
1845 | |||
1846 | /** | ||
1847 | * Core handler for tunnel destruction | ||
1848 | * | ||
1849 | * @param cls Closure (unused). | ||
1850 | * @param peer Peer identity of sending neighbor. | ||
1851 | * @param message Message. | ||
1852 | * | ||
1853 | * @return GNUNET_OK to keep the connection open, | ||
1854 | * GNUNET_SYSERR to close it (signal serious error) | ||
1855 | */ | ||
1856 | int | ||
1857 | GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
1858 | const struct GNUNET_MessageHeader *message) | ||
1859 | { | ||
1860 | struct GNUNET_CADET_ConnectionDestroy *msg; | ||
1861 | struct CadetConnection *c; | ||
1862 | int fwd; | ||
1863 | |||
1864 | msg = (struct GNUNET_CADET_ConnectionDestroy *) message; | ||
1865 | log_message (message, peer, &msg->cid); | ||
1866 | c = connection_get (&msg->cid); | ||
1867 | if (NULL == c) | ||
1868 | { | ||
1869 | /* Probably already got the message from another path, | ||
1870 | * destroyed the tunnel and retransmitted to children. | ||
1871 | * Safe to ignore. | ||
1872 | */ | ||
1873 | GNUNET_STATISTICS_update (stats, "# control on unknown connection", | ||
1874 | 1, GNUNET_NO); | ||
1875 | LOG (GNUNET_ERROR_TYPE_DEBUG, " connection unknown: already destroyed?\n"); | ||
1876 | return GNUNET_OK; | ||
1877 | } | ||
1878 | fwd = is_fwd (c, peer); | ||
1879 | if (GNUNET_SYSERR == fwd) | ||
1880 | { | ||
1881 | GNUNET_break_op (0); /* FIXME */ | ||
1882 | return GNUNET_OK; | ||
1883 | } | ||
1884 | if (GNUNET_NO == GMC_is_terminal (c, fwd)) | ||
1885 | GMC_send_prebuilt_message (message, | ||
1886 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0, | ||
1887 | c, fwd, GNUNET_YES, NULL, NULL); | ||
1888 | else if (0 == c->pending_messages) | ||
1889 | { | ||
1890 | LOG (GNUNET_ERROR_TYPE_DEBUG, " directly destroying connection!\n"); | ||
1891 | GMC_destroy (c); | ||
1892 | return GNUNET_OK; | ||
1893 | } | ||
1894 | c->destroy = GNUNET_YES; | ||
1895 | c->state = CADET_CONNECTION_DESTROYED; | ||
1896 | if (NULL != c->t) | ||
1897 | { | ||
1898 | GMT_remove_connection (c->t, c); | ||
1899 | c->t = NULL; | ||
1900 | } | ||
1901 | |||
1902 | return GNUNET_OK; | ||
1903 | } | ||
1904 | |||
1905 | /** | ||
1906 | * Generic handler for cadet network encrypted traffic. | ||
1907 | * | ||
1908 | * @param peer Peer identity this notification is about. | ||
1909 | * @param msg Encrypted message. | ||
1910 | * | ||
1911 | * @return GNUNET_OK to keep the connection open, | ||
1912 | * GNUNET_SYSERR to close it (signal serious error) | ||
1913 | */ | ||
1914 | static int | ||
1915 | handle_cadet_encrypted (const struct GNUNET_PeerIdentity *peer, | ||
1916 | const struct GNUNET_CADET_Encrypted *msg) | ||
1917 | { | ||
1918 | struct CadetConnection *c; | ||
1919 | struct CadetPeer *neighbor; | ||
1920 | struct CadetFlowControl *fc; | ||
1921 | GNUNET_PEER_Id peer_id; | ||
1922 | uint32_t pid; | ||
1923 | uint32_t ttl; | ||
1924 | size_t size; | ||
1925 | int fwd; | ||
1926 | |||
1927 | log_message (&msg->header, peer, &msg->cid); | ||
1928 | |||
1929 | /* Check size */ | ||
1930 | size = ntohs (msg->header.size); | ||
1931 | if (size < | ||
1932 | sizeof (struct GNUNET_CADET_Encrypted) + | ||
1933 | sizeof (struct GNUNET_MessageHeader)) | ||
1934 | { | ||
1935 | GNUNET_break_op (0); | ||
1936 | return GNUNET_OK; | ||
1937 | } | ||
1938 | |||
1939 | /* Check connection */ | ||
1940 | c = connection_get (&msg->cid); | ||
1941 | if (NULL == c) | ||
1942 | { | ||
1943 | GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO); | ||
1944 | LOG (GNUNET_ERROR_TYPE_DEBUG, "enc on unknown connection %s\n", | ||
1945 | GNUNET_h2s (GM_h2hc (&msg->cid))); | ||
1946 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
1947 | return GNUNET_OK; | ||
1948 | } | ||
1949 | |||
1950 | LOG (GNUNET_ERROR_TYPE_DEBUG, " connection %s\n", GMC_2s (c)); | ||
1951 | |||
1952 | /* Check if origin is as expected */ | ||
1953 | neighbor = get_prev_hop (c); | ||
1954 | peer_id = GNUNET_PEER_search (peer); | ||
1955 | if (peer_id == GMP_get_short_id (neighbor)) | ||
1956 | { | ||
1957 | fwd = GNUNET_YES; | ||
1958 | } | ||
1959 | else | ||
1960 | { | ||
1961 | neighbor = get_next_hop (c); | ||
1962 | if (peer_id == GMP_get_short_id (neighbor)) | ||
1963 | { | ||
1964 | fwd = GNUNET_NO; | ||
1965 | } | ||
1966 | else | ||
1967 | { | ||
1968 | /* Unexpected peer sending traffic on a connection. */ | ||
1969 | GNUNET_break_op (0); | ||
1970 | return GNUNET_OK; | ||
1971 | } | ||
1972 | } | ||
1973 | |||
1974 | /* Check PID */ | ||
1975 | fc = fwd ? &c->bck_fc : &c->fwd_fc; | ||
1976 | pid = ntohl (msg->pid); | ||
1977 | LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u (expected %u+)\n", | ||
1978 | pid, fc->last_pid_recv + 1); | ||
1979 | if (GM_is_pid_bigger (pid, fc->last_ack_sent)) | ||
1980 | { | ||
1981 | GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO); | ||
1982 | GNUNET_break_op (0); | ||
1983 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1984 | "Received PID %u, (prev %u), ACK %u\n", | ||
1985 | pid, fc->last_pid_recv, fc->last_ack_sent); | ||
1986 | return GNUNET_OK; | ||
1987 | } | ||
1988 | if (GNUNET_NO == GM_is_pid_bigger (pid, fc->last_pid_recv)) | ||
1989 | { | ||
1990 | GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO); | ||
1991 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1992 | " PID %u not expected (%u+), dropping!\n", | ||
1993 | pid, fc->last_pid_recv + 1); | ||
1994 | return GNUNET_OK; | ||
1995 | } | ||
1996 | if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state) | ||
1997 | connection_change_state (c, CADET_CONNECTION_READY); | ||
1998 | connection_reset_timeout (c, fwd); | ||
1999 | fc->last_pid_recv = pid; | ||
2000 | |||
2001 | /* Is this message for us? */ | ||
2002 | if (GMC_is_terminal (c, fwd)) | ||
2003 | { | ||
2004 | LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n"); | ||
2005 | GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO); | ||
2006 | |||
2007 | if (NULL == c->t) | ||
2008 | { | ||
2009 | GNUNET_break (GNUNET_NO != c->destroy); | ||
2010 | return GNUNET_OK; | ||
2011 | } | ||
2012 | fc->last_pid_recv = pid; | ||
2013 | GMT_handle_encrypted (c->t, msg); | ||
2014 | GMC_send_ack (c, fwd, GNUNET_NO); | ||
2015 | return GNUNET_OK; | ||
2016 | } | ||
2017 | |||
2018 | /* Message not for us: forward to next hop */ | ||
2019 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
2020 | ttl = ntohl (msg->ttl); | ||
2021 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl); | ||
2022 | if (ttl == 0) | ||
2023 | { | ||
2024 | GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO); | ||
2025 | LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n"); | ||
2026 | GMC_send_ack (c, fwd, GNUNET_NO); | ||
2027 | return GNUNET_OK; | ||
2028 | } | ||
2029 | |||
2030 | GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); | ||
2031 | GMC_send_prebuilt_message (&msg->header, | ||
2032 | GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED, 0, | ||
2033 | c, fwd, GNUNET_NO, NULL, NULL); | ||
2034 | |||
2035 | return GNUNET_OK; | ||
2036 | } | ||
2037 | |||
2038 | /** | ||
2039 | * Generic handler for cadet network encrypted traffic. | ||
2040 | * | ||
2041 | * @param peer Peer identity this notification is about. | ||
2042 | * @param msg Encrypted message. | ||
2043 | * | ||
2044 | * @return GNUNET_OK to keep the connection open, | ||
2045 | * GNUNET_SYSERR to close it (signal serious error) | ||
2046 | */ | ||
2047 | static int | ||
2048 | handle_cadet_kx (const struct GNUNET_PeerIdentity *peer, | ||
2049 | const struct GNUNET_CADET_KX *msg) | ||
2050 | { | ||
2051 | struct CadetConnection *c; | ||
2052 | struct CadetPeer *neighbor; | ||
2053 | GNUNET_PEER_Id peer_id; | ||
2054 | size_t size; | ||
2055 | int fwd; | ||
2056 | |||
2057 | log_message (&msg->header, peer, &msg->cid); | ||
2058 | |||
2059 | /* Check size */ | ||
2060 | size = ntohs (msg->header.size); | ||
2061 | if (size < | ||
2062 | sizeof (struct GNUNET_CADET_KX) + | ||
2063 | sizeof (struct GNUNET_MessageHeader)) | ||
2064 | { | ||
2065 | GNUNET_break_op (0); | ||
2066 | return GNUNET_OK; | ||
2067 | } | ||
2068 | |||
2069 | /* Check connection */ | ||
2070 | c = connection_get (&msg->cid); | ||
2071 | if (NULL == c) | ||
2072 | { | ||
2073 | GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO); | ||
2074 | LOG (GNUNET_ERROR_TYPE_DEBUG, "kx on unknown connection %s\n", | ||
2075 | GNUNET_h2s (GM_h2hc (&msg->cid))); | ||
2076 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
2077 | return GNUNET_OK; | ||
2078 | } | ||
2079 | LOG (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n", GMC_2s (c)); | ||
2080 | |||
2081 | /* Check if origin is as expected */ | ||
2082 | neighbor = get_prev_hop (c); | ||
2083 | peer_id = GNUNET_PEER_search (peer); | ||
2084 | if (peer_id == GMP_get_short_id (neighbor)) | ||
2085 | { | ||
2086 | fwd = GNUNET_YES; | ||
2087 | } | ||
2088 | else | ||
2089 | { | ||
2090 | neighbor = get_next_hop (c); | ||
2091 | if (peer_id == GMP_get_short_id (neighbor)) | ||
2092 | { | ||
2093 | fwd = GNUNET_NO; | ||
2094 | } | ||
2095 | else | ||
2096 | { | ||
2097 | /* Unexpected peer sending traffic on a connection. */ | ||
2098 | GNUNET_break_op (0); | ||
2099 | return GNUNET_OK; | ||
2100 | } | ||
2101 | } | ||
2102 | |||
2103 | /* Count as connection confirmation. */ | ||
2104 | if (CADET_CONNECTION_SENT == c->state || CADET_CONNECTION_ACK == c->state) | ||
2105 | { | ||
2106 | connection_change_state (c, CADET_CONNECTION_READY); | ||
2107 | if (NULL != c->t) | ||
2108 | { | ||
2109 | if (CADET_TUNNEL3_WAITING == GMT_get_cstate (c->t)) | ||
2110 | GMT_change_cstate (c->t, CADET_TUNNEL3_READY); | ||
2111 | } | ||
2112 | } | ||
2113 | connection_reset_timeout (c, fwd); | ||
2114 | |||
2115 | /* Is this message for us? */ | ||
2116 | if (GMC_is_terminal (c, fwd)) | ||
2117 | { | ||
2118 | LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n"); | ||
2119 | GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO); | ||
2120 | if (NULL == c->t) | ||
2121 | { | ||
2122 | GNUNET_break (0); | ||
2123 | return GNUNET_OK; | ||
2124 | } | ||
2125 | GMT_handle_kx (c->t, &msg[1].header); | ||
2126 | return GNUNET_OK; | ||
2127 | } | ||
2128 | |||
2129 | /* Message not for us: forward to next hop */ | ||
2130 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n"); | ||
2131 | GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO); | ||
2132 | GMC_send_prebuilt_message (&msg->header, GNUNET_MESSAGE_TYPE_CADET_KX, 0, | ||
2133 | c, fwd, GNUNET_NO, NULL, NULL); | ||
2134 | |||
2135 | return GNUNET_OK; | ||
2136 | } | ||
2137 | |||
2138 | |||
2139 | /** | ||
2140 | * Core handler for encrypted cadet network traffic (channel mgmt, data). | ||
2141 | * | ||
2142 | * @param cls Closure (unused). | ||
2143 | * @param message Message received. | ||
2144 | * @param peer Peer who sent the message. | ||
2145 | * | ||
2146 | * @return GNUNET_OK to keep the connection open, | ||
2147 | * GNUNET_SYSERR to close it (signal serious error) | ||
2148 | */ | ||
2149 | int | ||
2150 | GMC_handle_encrypted (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
2151 | const struct GNUNET_MessageHeader *message) | ||
2152 | { | ||
2153 | return handle_cadet_encrypted (peer, | ||
2154 | (struct GNUNET_CADET_Encrypted *)message); | ||
2155 | } | ||
2156 | |||
2157 | |||
2158 | /** | ||
2159 | * Core handler for key exchange traffic (ephemeral key, ping, pong). | ||
2160 | * | ||
2161 | * @param cls Closure (unused). | ||
2162 | * @param message Message received. | ||
2163 | * @param peer Peer who sent the message. | ||
2164 | * | ||
2165 | * @return GNUNET_OK to keep the connection open, | ||
2166 | * GNUNET_SYSERR to close it (signal serious error) | ||
2167 | */ | ||
2168 | int | ||
2169 | GMC_handle_kx (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
2170 | const struct GNUNET_MessageHeader *message) | ||
2171 | { | ||
2172 | return handle_cadet_kx (peer, | ||
2173 | (struct GNUNET_CADET_KX *) message); | ||
2174 | } | ||
2175 | |||
2176 | |||
2177 | /** | ||
2178 | * Core handler for cadet network traffic point-to-point acks. | ||
2179 | * | ||
2180 | * @param cls closure | ||
2181 | * @param message message | ||
2182 | * @param peer peer identity this notification is about | ||
2183 | * | ||
2184 | * @return GNUNET_OK to keep the connection open, | ||
2185 | * GNUNET_SYSERR to close it (signal serious error) | ||
2186 | */ | ||
2187 | int | ||
2188 | GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
2189 | const struct GNUNET_MessageHeader *message) | ||
2190 | { | ||
2191 | struct GNUNET_CADET_ACK *msg; | ||
2192 | struct CadetConnection *c; | ||
2193 | struct CadetFlowControl *fc; | ||
2194 | GNUNET_PEER_Id id; | ||
2195 | uint32_t ack; | ||
2196 | int fwd; | ||
2197 | |||
2198 | msg = (struct GNUNET_CADET_ACK *) message; | ||
2199 | log_message (message, peer, &msg->cid); | ||
2200 | c = connection_get (&msg->cid); | ||
2201 | if (NULL == c) | ||
2202 | { | ||
2203 | GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1, | ||
2204 | GNUNET_NO); | ||
2205 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
2206 | return GNUNET_OK; | ||
2207 | } | ||
2208 | |||
2209 | /* Is this a forward or backward ACK? */ | ||
2210 | id = GNUNET_PEER_search (peer); | ||
2211 | if (GMP_get_short_id (get_next_hop (c)) == id) | ||
2212 | { | ||
2213 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n"); | ||
2214 | fc = &c->fwd_fc; | ||
2215 | fwd = GNUNET_YES; | ||
2216 | } | ||
2217 | else if (GMP_get_short_id (get_prev_hop (c)) == id) | ||
2218 | { | ||
2219 | LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n"); | ||
2220 | fc = &c->bck_fc; | ||
2221 | fwd = GNUNET_NO; | ||
2222 | } | ||
2223 | else | ||
2224 | { | ||
2225 | GNUNET_break_op (0); | ||
2226 | return GNUNET_OK; | ||
2227 | } | ||
2228 | |||
2229 | ack = ntohl (msg->ack); | ||
2230 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n", | ||
2231 | ack, fc->last_ack_recv); | ||
2232 | if (GM_is_pid_bigger (ack, fc->last_ack_recv)) | ||
2233 | fc->last_ack_recv = ack; | ||
2234 | |||
2235 | /* Cancel polling if the ACK is big enough. */ | ||
2236 | if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task && | ||
2237 | GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent)) | ||
2238 | { | ||
2239 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n"); | ||
2240 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
2241 | fc->poll_task = GNUNET_SCHEDULER_NO_TASK; | ||
2242 | fc->poll_time = GNUNET_TIME_UNIT_SECONDS; | ||
2243 | } | ||
2244 | |||
2245 | connection_unlock_queue (c, fwd); | ||
2246 | |||
2247 | return GNUNET_OK; | ||
2248 | } | ||
2249 | |||
2250 | |||
2251 | /** | ||
2252 | * Core handler for cadet network traffic point-to-point ack polls. | ||
2253 | * | ||
2254 | * @param cls closure | ||
2255 | * @param message message | ||
2256 | * @param peer peer identity this notification is about | ||
2257 | * | ||
2258 | * @return GNUNET_OK to keep the connection open, | ||
2259 | * GNUNET_SYSERR to close it (signal serious error) | ||
2260 | */ | ||
2261 | int | ||
2262 | GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
2263 | const struct GNUNET_MessageHeader *message) | ||
2264 | { | ||
2265 | struct GNUNET_CADET_Poll *msg; | ||
2266 | struct CadetConnection *c; | ||
2267 | struct CadetFlowControl *fc; | ||
2268 | GNUNET_PEER_Id id; | ||
2269 | uint32_t pid; | ||
2270 | int fwd; | ||
2271 | |||
2272 | msg = (struct GNUNET_CADET_Poll *) message; | ||
2273 | log_message (message, peer, &msg->cid); | ||
2274 | c = connection_get (&msg->cid); | ||
2275 | if (NULL == c) | ||
2276 | { | ||
2277 | GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1, | ||
2278 | GNUNET_NO); | ||
2279 | LOG (GNUNET_ERROR_TYPE_DEBUG, "POLL message on unknown connection %s!\n", | ||
2280 | GNUNET_h2s (GM_h2hc (&msg->cid))); | ||
2281 | send_broken_unknown (&msg->cid, &my_full_id, NULL, peer); | ||
2282 | return GNUNET_OK; | ||
2283 | } | ||
2284 | |||
2285 | /* Is this a forward or backward ACK? | ||
2286 | * Note: a poll should never be needed in a loopback case, | ||
2287 | * since there is no possiblility of packet loss there, so | ||
2288 | * this way of discerining FWD/BCK should not be a problem. | ||
2289 | */ | ||
2290 | id = GNUNET_PEER_search (peer); | ||
2291 | if (GMP_get_short_id (get_next_hop (c)) == id) | ||
2292 | { | ||
2293 | LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n"); | ||
2294 | fc = &c->fwd_fc; | ||
2295 | } | ||
2296 | else if (GMP_get_short_id (get_prev_hop (c)) == id) | ||
2297 | { | ||
2298 | LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n"); | ||
2299 | fc = &c->bck_fc; | ||
2300 | } | ||
2301 | else | ||
2302 | { | ||
2303 | GNUNET_break_op (0); | ||
2304 | return GNUNET_OK; | ||
2305 | } | ||
2306 | |||
2307 | pid = ntohl (msg->pid); | ||
2308 | LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n", pid, fc->last_pid_recv); | ||
2309 | fc->last_pid_recv = pid; | ||
2310 | fwd = fc == &c->bck_fc; | ||
2311 | GMC_send_ack (c, fwd, GNUNET_YES); | ||
2312 | |||
2313 | return GNUNET_OK; | ||
2314 | } | ||
2315 | |||
2316 | |||
2317 | /** | ||
2318 | * Send an ACK on the appropriate connection/channel, depending on | ||
2319 | * the direction and the position of the peer. | ||
2320 | * | ||
2321 | * @param c Which connection to send the hop-by-hop ACK. | ||
2322 | * @param fwd Is this a fwd ACK? (will go dest->root). | ||
2323 | * @param force Send the ACK even if suboptimal (e.g. requested by POLL). | ||
2324 | */ | ||
2325 | void | ||
2326 | GMC_send_ack (struct CadetConnection *c, int fwd, int force) | ||
2327 | { | ||
2328 | unsigned int buffer; | ||
2329 | |||
2330 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2331 | "GMC send %s ACK on %s\n", | ||
2332 | GM_f2s (fwd), GMC_2s (c)); | ||
2333 | |||
2334 | if (NULL == c) | ||
2335 | { | ||
2336 | GNUNET_break (0); | ||
2337 | return; | ||
2338 | } | ||
2339 | |||
2340 | if (GNUNET_NO != c->destroy) | ||
2341 | { | ||
2342 | LOG (GNUNET_ERROR_TYPE_DEBUG, " being destroyed, why bother...\n"); | ||
2343 | return; | ||
2344 | } | ||
2345 | |||
2346 | /* Get available buffer space */ | ||
2347 | if (GMC_is_terminal (c, fwd)) | ||
2348 | { | ||
2349 | LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from all channels\n"); | ||
2350 | buffer = GMT_get_channels_buffer (c->t); | ||
2351 | } | ||
2352 | else | ||
2353 | { | ||
2354 | LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n"); | ||
2355 | buffer = GMC_get_buffer (c, fwd); | ||
2356 | } | ||
2357 | LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer); | ||
2358 | if (0 == buffer && GNUNET_NO == force) | ||
2359 | return; | ||
2360 | |||
2361 | /* Send available buffer space */ | ||
2362 | if (GMC_is_origin (c, fwd)) | ||
2363 | { | ||
2364 | GNUNET_assert (NULL != c->t); | ||
2365 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channels...\n"); | ||
2366 | GMT_unchoke_channels (c->t); | ||
2367 | } | ||
2368 | else | ||
2369 | { | ||
2370 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n"); | ||
2371 | send_ack (c, buffer, fwd, force); | ||
2372 | } | ||
2373 | } | ||
2374 | |||
2375 | |||
2376 | /** | ||
2377 | * Initialize the connections subsystem | ||
2378 | * | ||
2379 | * @param c Configuration handle. | ||
2380 | */ | ||
2381 | void | ||
2382 | GMC_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
2383 | { | ||
2384 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
2385 | if (GNUNET_OK != | ||
2386 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_MSGS_QUEUE", | ||
2387 | &max_msgs_queue)) | ||
2388 | { | ||
2389 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
2390 | "CADET", "MAX_MSGS_QUEUE", "MISSING"); | ||
2391 | GNUNET_SCHEDULER_shutdown (); | ||
2392 | return; | ||
2393 | } | ||
2394 | |||
2395 | if (GNUNET_OK != | ||
2396 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_CONNECTIONS", | ||
2397 | &max_connections)) | ||
2398 | { | ||
2399 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
2400 | "CADET", "MAX_CONNECTIONS", "MISSING"); | ||
2401 | GNUNET_SCHEDULER_shutdown (); | ||
2402 | return; | ||
2403 | } | ||
2404 | |||
2405 | if (GNUNET_OK != | ||
2406 | GNUNET_CONFIGURATION_get_value_time (c, "CADET", "REFRESH_CONNECTION_TIME", | ||
2407 | &refresh_connection_time)) | ||
2408 | { | ||
2409 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
2410 | "CADET", "REFRESH_CONNECTION_TIME", "MISSING"); | ||
2411 | GNUNET_SCHEDULER_shutdown (); | ||
2412 | return; | ||
2413 | } | ||
2414 | create_connection_time = GNUNET_TIME_UNIT_SECONDS; | ||
2415 | connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_NO); | ||
2416 | } | ||
2417 | |||
2418 | |||
2419 | /** | ||
2420 | * Destroy each connection on shutdown. | ||
2421 | * | ||
2422 | * @param cls Closure (unused). | ||
2423 | * @param key Current key code (CID, unused). | ||
2424 | * @param value Value in the hash map (connection) | ||
2425 | * | ||
2426 | * @return #GNUNET_YES, because we should continue to iterate, | ||
2427 | */ | ||
2428 | static int | ||
2429 | shutdown_iterator (void *cls, | ||
2430 | const struct GNUNET_HashCode *key, | ||
2431 | void *value) | ||
2432 | { | ||
2433 | struct CadetConnection *c = value; | ||
2434 | |||
2435 | GMC_destroy (c); | ||
2436 | return GNUNET_YES; | ||
2437 | } | ||
2438 | |||
2439 | |||
2440 | /** | ||
2441 | * Shut down the connections subsystem. | ||
2442 | */ | ||
2443 | void | ||
2444 | GMC_shutdown (void) | ||
2445 | { | ||
2446 | GNUNET_CONTAINER_multihashmap_iterate (connections, &shutdown_iterator, NULL); | ||
2447 | GNUNET_CONTAINER_multihashmap_destroy (connections); | ||
2448 | connections = NULL; | ||
2449 | } | ||
2450 | |||
2451 | |||
2452 | struct CadetConnection * | ||
2453 | GMC_new (const struct GNUNET_CADET_Hash *cid, | ||
2454 | struct CadetTunnel3 *t, | ||
2455 | struct CadetPeerPath *p, | ||
2456 | unsigned int own_pos) | ||
2457 | { | ||
2458 | struct CadetConnection *c; | ||
2459 | |||
2460 | c = GNUNET_new (struct CadetConnection); | ||
2461 | c->id = *cid; | ||
2462 | GNUNET_assert (GNUNET_OK == | ||
2463 | GNUNET_CONTAINER_multihashmap_put (connections, | ||
2464 | GMC_get_h (c), c, | ||
2465 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
2466 | fc_init (&c->fwd_fc); | ||
2467 | fc_init (&c->bck_fc); | ||
2468 | c->fwd_fc.c = c; | ||
2469 | c->bck_fc.c = c; | ||
2470 | |||
2471 | c->t = t; | ||
2472 | GNUNET_assert (own_pos <= p->length - 1); | ||
2473 | c->own_pos = own_pos; | ||
2474 | c->path = p; | ||
2475 | p->c = c; | ||
2476 | |||
2477 | if (GNUNET_OK != register_neighbors (c)) | ||
2478 | { | ||
2479 | if (0 == own_pos) | ||
2480 | { | ||
2481 | path_invalidate (c->path); | ||
2482 | c->t = NULL; | ||
2483 | c->path = NULL; | ||
2484 | } | ||
2485 | GMC_destroy (c); | ||
2486 | return NULL; | ||
2487 | } | ||
2488 | |||
2489 | return c; | ||
2490 | } | ||
2491 | |||
2492 | |||
2493 | void | ||
2494 | GMC_destroy (struct CadetConnection *c) | ||
2495 | { | ||
2496 | if (NULL == c) | ||
2497 | { | ||
2498 | GNUNET_break (0); | ||
2499 | return; | ||
2500 | } | ||
2501 | |||
2502 | if (2 == c->destroy) /* cancel queues -> GMP_queue_cancel -> q_destroy -> */ | ||
2503 | return; /* -> message_sent -> GMC_destroy. Don't loop. */ | ||
2504 | c->destroy = 2; | ||
2505 | |||
2506 | LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n", GMC_2s (c)); | ||
2507 | LOG (GNUNET_ERROR_TYPE_DEBUG, " fc's f: %p, b: %p\n", | ||
2508 | &c->fwd_fc, &c->bck_fc); | ||
2509 | LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n", | ||
2510 | c->fwd_fc.poll_task, c->bck_fc.poll_task); | ||
2511 | |||
2512 | /* Cancel all traffic */ | ||
2513 | if (NULL != c->path) | ||
2514 | { | ||
2515 | connection_cancel_queues (c, GNUNET_YES); | ||
2516 | connection_cancel_queues (c, GNUNET_NO); | ||
2517 | unregister_neighbors (c); | ||
2518 | } | ||
2519 | |||
2520 | LOG (GNUNET_ERROR_TYPE_DEBUG, " fc tasks f: %u, b: %u\n", | ||
2521 | c->fwd_fc.poll_task, c->bck_fc.poll_task); | ||
2522 | |||
2523 | /* Cancel maintainance task (keepalive/timeout) */ | ||
2524 | if (NULL != c->fwd_fc.poll_msg) | ||
2525 | { | ||
2526 | GMC_cancel (c->fwd_fc.poll_msg); | ||
2527 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg FWD canceled\n"); | ||
2528 | } | ||
2529 | if (NULL != c->bck_fc.poll_msg) | ||
2530 | { | ||
2531 | GMC_cancel (c->bck_fc.poll_msg); | ||
2532 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL msg BCK canceled\n"); | ||
2533 | } | ||
2534 | |||
2535 | /* Delete from tunnel */ | ||
2536 | if (NULL != c->t) | ||
2537 | GMT_remove_connection (c->t, c); | ||
2538 | |||
2539 | if (GNUNET_NO == GMC_is_origin (c, GNUNET_YES) && NULL != c->path) | ||
2540 | path_destroy (c->path); | ||
2541 | if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task) | ||
2542 | GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task); | ||
2543 | if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task) | ||
2544 | GNUNET_SCHEDULER_cancel (c->bck_maintenance_task); | ||
2545 | if (GNUNET_SCHEDULER_NO_TASK != c->fwd_fc.poll_task) | ||
2546 | { | ||
2547 | GNUNET_SCHEDULER_cancel (c->fwd_fc.poll_task); | ||
2548 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL FWD canceled\n"); | ||
2549 | } | ||
2550 | if (GNUNET_SCHEDULER_NO_TASK != c->bck_fc.poll_task) | ||
2551 | { | ||
2552 | GNUNET_SCHEDULER_cancel (c->bck_fc.poll_task); | ||
2553 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL BCK canceled\n"); | ||
2554 | } | ||
2555 | |||
2556 | GNUNET_break (GNUNET_YES == | ||
2557 | GNUNET_CONTAINER_multihashmap_remove (connections, | ||
2558 | GMC_get_h (c), c)); | ||
2559 | |||
2560 | GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO); | ||
2561 | GNUNET_free (c); | ||
2562 | } | ||
2563 | |||
2564 | /** | ||
2565 | * Get the connection ID. | ||
2566 | * | ||
2567 | * @param c Connection to get the ID from. | ||
2568 | * | ||
2569 | * @return ID of the connection. | ||
2570 | */ | ||
2571 | const struct GNUNET_CADET_Hash * | ||
2572 | GMC_get_id (const struct CadetConnection *c) | ||
2573 | { | ||
2574 | return &c->id; | ||
2575 | } | ||
2576 | |||
2577 | |||
2578 | /** | ||
2579 | * Get the connection ID. | ||
2580 | * | ||
2581 | * @param c Connection to get the ID from. | ||
2582 | * | ||
2583 | * @return ID of the connection. | ||
2584 | */ | ||
2585 | const struct GNUNET_HashCode * | ||
2586 | GMC_get_h (const struct CadetConnection *c) | ||
2587 | { | ||
2588 | return GM_h2hc (&c->id); | ||
2589 | } | ||
2590 | |||
2591 | |||
2592 | /** | ||
2593 | * Get the connection path. | ||
2594 | * | ||
2595 | * @param c Connection to get the path from. | ||
2596 | * | ||
2597 | * @return path used by the connection. | ||
2598 | */ | ||
2599 | const struct CadetPeerPath * | ||
2600 | GMC_get_path (const struct CadetConnection *c) | ||
2601 | { | ||
2602 | if (GNUNET_NO == c->destroy) | ||
2603 | return c->path; | ||
2604 | return NULL; | ||
2605 | } | ||
2606 | |||
2607 | |||
2608 | /** | ||
2609 | * Get the connection state. | ||
2610 | * | ||
2611 | * @param c Connection to get the state from. | ||
2612 | * | ||
2613 | * @return state of the connection. | ||
2614 | */ | ||
2615 | enum CadetConnectionState | ||
2616 | GMC_get_state (const struct CadetConnection *c) | ||
2617 | { | ||
2618 | return c->state; | ||
2619 | } | ||
2620 | |||
2621 | /** | ||
2622 | * Get the connection tunnel. | ||
2623 | * | ||
2624 | * @param c Connection to get the tunnel from. | ||
2625 | * | ||
2626 | * @return tunnel of the connection. | ||
2627 | */ | ||
2628 | struct CadetTunnel3 * | ||
2629 | GMC_get_tunnel (const struct CadetConnection *c) | ||
2630 | { | ||
2631 | return c->t; | ||
2632 | } | ||
2633 | |||
2634 | |||
2635 | /** | ||
2636 | * Get free buffer space in a connection. | ||
2637 | * | ||
2638 | * @param c Connection. | ||
2639 | * @param fwd Is query about FWD traffic? | ||
2640 | * | ||
2641 | * @return Free buffer space [0 - max_msgs_queue/max_connections] | ||
2642 | */ | ||
2643 | unsigned int | ||
2644 | GMC_get_buffer (struct CadetConnection *c, int fwd) | ||
2645 | { | ||
2646 | struct CadetFlowControl *fc; | ||
2647 | |||
2648 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2649 | |||
2650 | return (fc->queue_max - fc->queue_n); | ||
2651 | } | ||
2652 | |||
2653 | /** | ||
2654 | * Get how many messages have we allowed to send to us from a direction. | ||
2655 | * | ||
2656 | * @param c Connection. | ||
2657 | * @param fwd Are we asking about traffic from FWD (BCK messages)? | ||
2658 | * | ||
2659 | * @return last_ack_sent - last_pid_recv | ||
2660 | */ | ||
2661 | unsigned int | ||
2662 | GMC_get_allowed (struct CadetConnection *c, int fwd) | ||
2663 | { | ||
2664 | struct CadetFlowControl *fc; | ||
2665 | |||
2666 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2667 | if (GM_is_pid_bigger(fc->last_pid_recv, fc->last_ack_sent)) | ||
2668 | { | ||
2669 | return 0; | ||
2670 | } | ||
2671 | return (fc->last_ack_sent - fc->last_pid_recv); | ||
2672 | } | ||
2673 | |||
2674 | /** | ||
2675 | * Get messages queued in a connection. | ||
2676 | * | ||
2677 | * @param c Connection. | ||
2678 | * @param fwd Is query about FWD traffic? | ||
2679 | * | ||
2680 | * @return Number of messages queued. | ||
2681 | */ | ||
2682 | unsigned int | ||
2683 | GMC_get_qn (struct CadetConnection *c, int fwd) | ||
2684 | { | ||
2685 | struct CadetFlowControl *fc; | ||
2686 | |||
2687 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2688 | |||
2689 | return fc->queue_n; | ||
2690 | } | ||
2691 | |||
2692 | |||
2693 | /** | ||
2694 | * Get next PID to use. | ||
2695 | * | ||
2696 | * @param c Connection. | ||
2697 | * @param fwd Is query about FWD traffic? | ||
2698 | * | ||
2699 | * @return Last PID used + 1. | ||
2700 | */ | ||
2701 | unsigned int | ||
2702 | GMC_get_pid (struct CadetConnection *c, int fwd) | ||
2703 | { | ||
2704 | struct CadetFlowControl *fc; | ||
2705 | |||
2706 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2707 | |||
2708 | return fc->last_pid_sent + 1; | ||
2709 | } | ||
2710 | |||
2711 | |||
2712 | /** | ||
2713 | * Allow the connection to advertise a buffer of the given size. | ||
2714 | * | ||
2715 | * The connection will send an @c fwd ACK message (so: in direction !fwd) | ||
2716 | * allowing up to last_pid_recv + buffer. | ||
2717 | * | ||
2718 | * @param c Connection. | ||
2719 | * @param buffer How many more messages the connection can accept. | ||
2720 | * @param fwd Is this about FWD traffic? (The ack will go dest->root). | ||
2721 | */ | ||
2722 | void | ||
2723 | GMC_allow (struct CadetConnection *c, unsigned int buffer, int fwd) | ||
2724 | { | ||
2725 | LOG (GNUNET_ERROR_TYPE_DEBUG, " allowing %s %u messages %s\n", | ||
2726 | GMC_2s (c), buffer, GM_f2s (fwd)); | ||
2727 | send_ack (c, buffer, fwd, GNUNET_NO); | ||
2728 | } | ||
2729 | |||
2730 | |||
2731 | /** | ||
2732 | * Notify other peers on a connection of a broken link. Mark connections | ||
2733 | * to destroy after all traffic has been sent. | ||
2734 | * | ||
2735 | * @param c Connection on which there has been a disconnection. | ||
2736 | * @param peer Peer that disconnected. | ||
2737 | */ | ||
2738 | void | ||
2739 | GMC_notify_broken (struct CadetConnection *c, | ||
2740 | struct CadetPeer *peer) | ||
2741 | { | ||
2742 | int fwd; | ||
2743 | |||
2744 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2745 | " notify broken on %s due to %s disconnect\n", | ||
2746 | GMC_2s (c), GMP_2s (peer)); | ||
2747 | |||
2748 | fwd = peer == get_prev_hop (c); | ||
2749 | |||
2750 | if (GNUNET_YES == GMC_is_terminal (c, fwd)) | ||
2751 | { | ||
2752 | /* Local shutdown, no one to notify about this. */ | ||
2753 | GMC_destroy (c); | ||
2754 | return; | ||
2755 | } | ||
2756 | if (GNUNET_NO == c->destroy) | ||
2757 | send_broken (c, &my_full_id, GMP_get_id (peer), fwd); | ||
2758 | |||
2759 | /* Connection will have at least one pending message | ||
2760 | * (the one we just scheduled), so no point in checking whether to | ||
2761 | * destroy immediately. */ | ||
2762 | c->destroy = GNUNET_YES; | ||
2763 | c->state = CADET_CONNECTION_DESTROYED; | ||
2764 | |||
2765 | /** | ||
2766 | * Cancel all queues, if no message is left, connection will be destroyed. | ||
2767 | */ | ||
2768 | connection_cancel_queues (c, !fwd); | ||
2769 | |||
2770 | return; | ||
2771 | } | ||
2772 | |||
2773 | |||
2774 | /** | ||
2775 | * Is this peer the first one on the connection? | ||
2776 | * | ||
2777 | * @param c Connection. | ||
2778 | * @param fwd Is this about fwd traffic? | ||
2779 | * | ||
2780 | * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal. | ||
2781 | */ | ||
2782 | int | ||
2783 | GMC_is_origin (struct CadetConnection *c, int fwd) | ||
2784 | { | ||
2785 | if (!fwd && c->path->length - 1 == c->own_pos ) | ||
2786 | return GNUNET_YES; | ||
2787 | if (fwd && 0 == c->own_pos) | ||
2788 | return GNUNET_YES; | ||
2789 | return GNUNET_NO; | ||
2790 | } | ||
2791 | |||
2792 | |||
2793 | /** | ||
2794 | * Is this peer the last one on the connection? | ||
2795 | * | ||
2796 | * @param c Connection. | ||
2797 | * @param fwd Is this about fwd traffic? | ||
2798 | * Note that the ROOT is the terminal for BCK traffic! | ||
2799 | * | ||
2800 | * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin. | ||
2801 | */ | ||
2802 | int | ||
2803 | GMC_is_terminal (struct CadetConnection *c, int fwd) | ||
2804 | { | ||
2805 | return GMC_is_origin (c, !fwd); | ||
2806 | } | ||
2807 | |||
2808 | |||
2809 | /** | ||
2810 | * See if we are allowed to send by the next hop in the given direction. | ||
2811 | * | ||
2812 | * @param c Connection. | ||
2813 | * @param fwd Is this about fwd traffic? | ||
2814 | * | ||
2815 | * @return #GNUNET_YES in case it's OK to send. | ||
2816 | */ | ||
2817 | int | ||
2818 | GMC_is_sendable (struct CadetConnection *c, int fwd) | ||
2819 | { | ||
2820 | struct CadetFlowControl *fc; | ||
2821 | |||
2822 | LOG (GNUNET_ERROR_TYPE_DEBUG, " checking sendability of %s traffic on %s\n", | ||
2823 | GM_f2s (fwd), GMC_2s (c)); | ||
2824 | if (NULL == c) | ||
2825 | { | ||
2826 | GNUNET_break (0); | ||
2827 | return GNUNET_YES; | ||
2828 | } | ||
2829 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2830 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2831 | " last ack recv: %u, last pid sent: %u\n", | ||
2832 | fc->last_ack_recv, fc->last_pid_sent); | ||
2833 | if (GM_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent)) | ||
2834 | { | ||
2835 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable\n"); | ||
2836 | return GNUNET_YES; | ||
2837 | } | ||
2838 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n"); | ||
2839 | return GNUNET_NO; | ||
2840 | } | ||
2841 | |||
2842 | |||
2843 | /** | ||
2844 | * Check if this connection is a direct one (never trim a direct connection). | ||
2845 | * | ||
2846 | * @param c Connection. | ||
2847 | * | ||
2848 | * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise. | ||
2849 | */ | ||
2850 | int | ||
2851 | GMC_is_direct (struct CadetConnection *c) | ||
2852 | { | ||
2853 | return (c->path->length == 2) ? GNUNET_YES : GNUNET_NO; | ||
2854 | } | ||
2855 | |||
2856 | /** | ||
2857 | * Sends an already built message on a connection, properly registering | ||
2858 | * all used resources. | ||
2859 | * | ||
2860 | * @param message Message to send. Function makes a copy of it. | ||
2861 | * If message is not hop-by-hop, decrements TTL of copy. | ||
2862 | * @param payload_type Type of payload, in case the message is encrypted. | ||
2863 | * @param c Connection on which this message is transmitted. | ||
2864 | * @param fwd Is this a fwd message? | ||
2865 | * @param force Force the connection to accept the message (buffer overfill). | ||
2866 | * @param cont Continuation called once message is sent. Can be NULL. | ||
2867 | * @param cont_cls Closure for @c cont. | ||
2868 | * | ||
2869 | * @return Handle to cancel the message before it's sent. | ||
2870 | * NULL on error or if @c cont is NULL. | ||
2871 | * Invalid on @c cont call. | ||
2872 | */ | ||
2873 | struct CadetConnectionQueue * | ||
2874 | GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
2875 | uint16_t payload_type, uint32_t payload_id, | ||
2876 | struct CadetConnection *c, int fwd, int force, | ||
2877 | GMC_sent cont, void *cont_cls) | ||
2878 | { | ||
2879 | struct CadetFlowControl *fc; | ||
2880 | struct CadetConnectionQueue *q; | ||
2881 | void *data; | ||
2882 | size_t size; | ||
2883 | uint16_t type; | ||
2884 | int droppable; | ||
2885 | |||
2886 | size = ntohs (message->size); | ||
2887 | data = GNUNET_malloc (size); | ||
2888 | memcpy (data, message, size); | ||
2889 | type = ntohs (message->type); | ||
2890 | LOG (GNUNET_ERROR_TYPE_INFO, "--> %s (%s %u) on connection %s (%u bytes)\n", | ||
2891 | GM_m2s (type), GM_m2s (payload_type), payload_id, GMC_2s (c), size); | ||
2892 | |||
2893 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
2894 | droppable = GNUNET_NO == force; | ||
2895 | switch (type) | ||
2896 | { | ||
2897 | struct GNUNET_CADET_Encrypted *emsg; | ||
2898 | struct GNUNET_CADET_KX *kmsg; | ||
2899 | struct GNUNET_CADET_ACK *amsg; | ||
2900 | struct GNUNET_CADET_Poll *pmsg; | ||
2901 | struct GNUNET_CADET_ConnectionDestroy *dmsg; | ||
2902 | struct GNUNET_CADET_ConnectionBroken *bmsg; | ||
2903 | uint32_t ttl; | ||
2904 | |||
2905 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
2906 | emsg = (struct GNUNET_CADET_Encrypted *) data; | ||
2907 | ttl = ntohl (emsg->ttl); | ||
2908 | if (0 == ttl) | ||
2909 | { | ||
2910 | GNUNET_break_op (0); | ||
2911 | GNUNET_free (data); | ||
2912 | return NULL; | ||
2913 | } | ||
2914 | emsg->cid = c->id; | ||
2915 | emsg->ttl = htonl (ttl - 1); | ||
2916 | emsg->pid = htonl (0); | ||
2917 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u\n", fc, fc->queue_n); | ||
2918 | LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid sent %u\n", fc->last_pid_sent); | ||
2919 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ack recv %u\n", fc->last_ack_recv); | ||
2920 | if (GNUNET_YES == droppable) | ||
2921 | { | ||
2922 | fc->queue_n++; | ||
2923 | } | ||
2924 | else | ||
2925 | { | ||
2926 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not droppable, Q_N stays the same\n"); | ||
2927 | } | ||
2928 | if (GM_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv)) | ||
2929 | { | ||
2930 | GMC_start_poll (c, fwd); | ||
2931 | } | ||
2932 | break; | ||
2933 | |||
2934 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
2935 | kmsg = (struct GNUNET_CADET_KX *) data; | ||
2936 | kmsg->cid = c->id; | ||
2937 | break; | ||
2938 | |||
2939 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
2940 | amsg = (struct GNUNET_CADET_ACK *) data; | ||
2941 | amsg->cid = c->id; | ||
2942 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack)); | ||
2943 | droppable = GNUNET_NO; | ||
2944 | break; | ||
2945 | |||
2946 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
2947 | pmsg = (struct GNUNET_CADET_Poll *) data; | ||
2948 | pmsg->cid = c->id; | ||
2949 | LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid)); | ||
2950 | droppable = GNUNET_NO; | ||
2951 | break; | ||
2952 | |||
2953 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
2954 | dmsg = (struct GNUNET_CADET_ConnectionDestroy *) data; | ||
2955 | dmsg->cid = c->id; | ||
2956 | break; | ||
2957 | |||
2958 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
2959 | bmsg = (struct GNUNET_CADET_ConnectionBroken *) data; | ||
2960 | bmsg->cid = c->id; | ||
2961 | break; | ||
2962 | |||
2963 | case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE: | ||
2964 | GNUNET_break (0); | ||
2965 | /* falltrough */ | ||
2966 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
2967 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
2968 | break; | ||
2969 | |||
2970 | default: | ||
2971 | GNUNET_break (0); | ||
2972 | GNUNET_free (data); | ||
2973 | return NULL; | ||
2974 | } | ||
2975 | |||
2976 | if (fc->queue_n > fc->queue_max && droppable) | ||
2977 | { | ||
2978 | GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)", | ||
2979 | 1, GNUNET_NO); | ||
2980 | GNUNET_break (0); | ||
2981 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2982 | "queue full: %u/%u\n", | ||
2983 | fc->queue_n, fc->queue_max); | ||
2984 | if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == type) | ||
2985 | { | ||
2986 | fc->queue_n--; | ||
2987 | } | ||
2988 | GNUNET_free (data); | ||
2989 | return NULL; /* Drop this message */ | ||
2990 | } | ||
2991 | |||
2992 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u\n", c, c->pending_messages); | ||
2993 | // c->pending_messages++; | ||
2994 | |||
2995 | q = GNUNET_new (struct CadetConnectionQueue); | ||
2996 | q->forced = !droppable; | ||
2997 | q->q = GMP_queue_add (get_hop (c, fwd), data, type, payload_type, payload_id, | ||
2998 | size, c, fwd, &conn_message_sent, q); | ||
2999 | if (NULL == q->q) | ||
3000 | { | ||
3001 | LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING dropping msg on %s\n", GMC_2s (c)); | ||
3002 | GNUNET_free (data); | ||
3003 | GNUNET_free (q); | ||
3004 | return NULL; | ||
3005 | } | ||
3006 | q->cont = cont; | ||
3007 | q->cont_cls = cont_cls; | ||
3008 | return (NULL == cont) ? NULL : q; | ||
3009 | } | ||
3010 | |||
3011 | |||
3012 | /** | ||
3013 | * Cancel a previously sent message while it's in the queue. | ||
3014 | * | ||
3015 | * ONLY can be called before the continuation given to the send function | ||
3016 | * is called. Once the continuation is called, the message is no longer in the | ||
3017 | * queue. | ||
3018 | * | ||
3019 | * @param q Handle to the queue. | ||
3020 | */ | ||
3021 | void | ||
3022 | GMC_cancel (struct CadetConnectionQueue *q) | ||
3023 | { | ||
3024 | LOG (GNUNET_ERROR_TYPE_DEBUG, "! GMC cancel message\n"); | ||
3025 | |||
3026 | /* queue destroy calls message_sent, which calls q->cont and frees q */ | ||
3027 | GMP_queue_destroy (q->q, GNUNET_YES, GNUNET_NO, 0); | ||
3028 | } | ||
3029 | |||
3030 | |||
3031 | /** | ||
3032 | * Sends a CREATE CONNECTION message for a path to a peer. | ||
3033 | * Changes the connection and tunnel states if necessary. | ||
3034 | * | ||
3035 | * @param connection Connection to create. | ||
3036 | */ | ||
3037 | void | ||
3038 | GMC_send_create (struct CadetConnection *connection) | ||
3039 | { | ||
3040 | enum CadetTunnel3CState state; | ||
3041 | size_t size; | ||
3042 | |||
3043 | size = sizeof (struct GNUNET_CADET_ConnectionCreate); | ||
3044 | size += connection->path->length * sizeof (struct GNUNET_PeerIdentity); | ||
3045 | |||
3046 | LOG (GNUNET_ERROR_TYPE_INFO, "===> %s on connection %s (%u bytes)\n", | ||
3047 | GM_m2s (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE), | ||
3048 | GMC_2s (connection), size); | ||
3049 | LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (create)\n", | ||
3050 | connection, connection->pending_messages); | ||
3051 | connection->pending_messages++; | ||
3052 | |||
3053 | connection->maintenance_q = | ||
3054 | GMP_queue_add (get_next_hop (connection), NULL, | ||
3055 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, | ||
3056 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0, | ||
3057 | size, connection, GNUNET_YES, &conn_message_sent, NULL); | ||
3058 | |||
3059 | state = GMT_get_cstate (connection->t); | ||
3060 | if (CADET_TUNNEL3_SEARCHING == state || CADET_TUNNEL3_NEW == state) | ||
3061 | GMT_change_cstate (connection->t, CADET_TUNNEL3_WAITING); | ||
3062 | if (CADET_CONNECTION_NEW == connection->state) | ||
3063 | connection_change_state (connection, CADET_CONNECTION_SENT); | ||
3064 | } | ||
3065 | |||
3066 | |||
3067 | /** | ||
3068 | * Send a message to all peers in this connection that the connection | ||
3069 | * is no longer valid. | ||
3070 | * | ||
3071 | * If some peer should not receive the message, it should be zero'ed out | ||
3072 | * before calling this function. | ||
3073 | * | ||
3074 | * @param c The connection whose peers to notify. | ||
3075 | */ | ||
3076 | void | ||
3077 | GMC_send_destroy (struct CadetConnection *c) | ||
3078 | { | ||
3079 | struct GNUNET_CADET_ConnectionDestroy msg; | ||
3080 | |||
3081 | if (GNUNET_YES == c->destroy) | ||
3082 | return; | ||
3083 | |||
3084 | msg.header.size = htons (sizeof (msg)); | ||
3085 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY);; | ||
3086 | msg.cid = c->id; | ||
3087 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
3088 | " sending connection destroy for connection %s\n", | ||
3089 | GMC_2s (c)); | ||
3090 | |||
3091 | if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES)) | ||
3092 | GMC_send_prebuilt_message (&msg.header, | ||
3093 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0, | ||
3094 | c, GNUNET_YES, GNUNET_YES, NULL, NULL); | ||
3095 | if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO)) | ||
3096 | GMC_send_prebuilt_message (&msg.header, | ||
3097 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, 0, | ||
3098 | c, GNUNET_NO, GNUNET_YES, NULL, NULL); | ||
3099 | c->destroy = GNUNET_YES; | ||
3100 | c->state = CADET_CONNECTION_DESTROYED; | ||
3101 | } | ||
3102 | |||
3103 | |||
3104 | /** | ||
3105 | * @brief Start a polling timer for the connection. | ||
3106 | * | ||
3107 | * When a neighbor does not accept more traffic on the connection it could be | ||
3108 | * caused by a simple congestion or by a lost ACK. Polling enables to check | ||
3109 | * for the lastest ACK status for a connection. | ||
3110 | * | ||
3111 | * @param c Connection. | ||
3112 | * @param fwd Should we poll in the FWD direction? | ||
3113 | */ | ||
3114 | void | ||
3115 | GMC_start_poll (struct CadetConnection *c, int fwd) | ||
3116 | { | ||
3117 | struct CadetFlowControl *fc; | ||
3118 | |||
3119 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3120 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL %s requested\n", | ||
3121 | GM_f2s (fwd)); | ||
3122 | if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task || NULL != fc->poll_msg) | ||
3123 | { | ||
3124 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** not needed (%u, %p)\n", | ||
3125 | fc->poll_task, fc->poll_msg); | ||
3126 | return; | ||
3127 | } | ||
3128 | LOG (GNUNET_ERROR_TYPE_DEBUG, " *** POLL started on request\n"); | ||
3129 | fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time, | ||
3130 | &connection_poll, | ||
3131 | fc); | ||
3132 | } | ||
3133 | |||
3134 | |||
3135 | /** | ||
3136 | * @brief Stop polling a connection for ACKs. | ||
3137 | * | ||
3138 | * Once we have enough ACKs for future traffic, polls are no longer necessary. | ||
3139 | * | ||
3140 | * @param c Connection. | ||
3141 | * @param fwd Should we stop the poll in the FWD direction? | ||
3142 | */ | ||
3143 | void | ||
3144 | GMC_stop_poll (struct CadetConnection *c, int fwd) | ||
3145 | { | ||
3146 | struct CadetFlowControl *fc; | ||
3147 | |||
3148 | fc = fwd ? &c->fwd_fc : &c->bck_fc; | ||
3149 | if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task) | ||
3150 | { | ||
3151 | GNUNET_SCHEDULER_cancel (fc->poll_task); | ||
3152 | fc->poll_task = GNUNET_SCHEDULER_NO_TASK; | ||
3153 | } | ||
3154 | } | ||
3155 | |||
3156 | /** | ||
3157 | * Get a (static) string for a connection. | ||
3158 | * | ||
3159 | * @param c Connection. | ||
3160 | */ | ||
3161 | const char * | ||
3162 | GMC_2s (const struct CadetConnection *c) | ||
3163 | { | ||
3164 | if (NULL == c) | ||
3165 | return "NULL"; | ||
3166 | |||
3167 | if (NULL != c->t) | ||
3168 | { | ||
3169 | static char buf[128]; | ||
3170 | |||
3171 | sprintf (buf, "%s (->%s)", | ||
3172 | GNUNET_h2s (GM_h2hc (GMC_get_id (c))), GMT_2s (c->t)); | ||
3173 | return buf; | ||
3174 | } | ||
3175 | return GNUNET_h2s (GM_h2hc (&c->id)); | ||
3176 | } | ||
diff --git a/src/cadet/gnunet-service-cadet_connection.h b/src/cadet/gnunet-service-cadet_connection.h new file mode 100644 index 000000000..4e1104c2b --- /dev/null +++ b/src/cadet/gnunet-service-cadet_connection.h | |||
@@ -0,0 +1,566 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_connection.h | ||
23 | * @brief cadet service; dealing with connections | ||
24 | * @author Bartlomiej Polot | ||
25 | * | ||
26 | * All functions in this file should use the prefix GMC (Gnunet Cadet Connection) | ||
27 | */ | ||
28 | |||
29 | #ifndef GNUNET_SERVICE_CADET_CONNECTION_H | ||
30 | #define GNUNET_SERVICE_CADET_CONNECTION_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 "gnunet_util_lib.h" | ||
41 | |||
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 | |||
75 | /** | ||
76 | * Struct containing all information regarding a connection to a peer. | ||
77 | */ | ||
78 | struct CadetConnection; | ||
79 | |||
80 | /** | ||
81 | * Handle for messages queued but not yet sent. | ||
82 | */ | ||
83 | struct CadetConnectionQueue; | ||
84 | |||
85 | #include "cadet_path.h" | ||
86 | #include "gnunet-service-cadet_channel.h" | ||
87 | #include "gnunet-service-cadet_peer.h" | ||
88 | |||
89 | |||
90 | |||
91 | /** | ||
92 | * Callback called when a queued message is sent. | ||
93 | * | ||
94 | * @param cls Closure. | ||
95 | * @param c Connection this message was on. | ||
96 | * @param type Type of message sent. | ||
97 | * @param fwd Was this a FWD going message? | ||
98 | * @param size Size of the message. | ||
99 | */ | ||
100 | typedef void (*GMC_sent) (void *cls, | ||
101 | struct CadetConnection *c, | ||
102 | struct CadetConnectionQueue *q, | ||
103 | uint16_t type, int fwd, size_t size); | ||
104 | |||
105 | /** | ||
106 | * Core handler for connection creation. | ||
107 | * | ||
108 | * @param cls Closure (unused). | ||
109 | * @param peer Sender (neighbor). | ||
110 | * @param message Message. | ||
111 | * | ||
112 | * @return GNUNET_OK to keep the connection open, | ||
113 | * GNUNET_SYSERR to close it (signal serious error) | ||
114 | */ | ||
115 | int | ||
116 | GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
117 | const struct GNUNET_MessageHeader *message); | ||
118 | |||
119 | /** | ||
120 | * Core handler for path confirmations. | ||
121 | * | ||
122 | * @param cls closure | ||
123 | * @param message message | ||
124 | * @param peer peer identity this notification is about | ||
125 | * | ||
126 | * @return GNUNET_OK to keep the connection open, | ||
127 | * GNUNET_SYSERR to close it (signal serious error) | ||
128 | */ | ||
129 | int | ||
130 | GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
131 | const struct GNUNET_MessageHeader *message); | ||
132 | |||
133 | /** | ||
134 | * Core handler for notifications of broken paths | ||
135 | * | ||
136 | * @param cls Closure (unused). | ||
137 | * @param id Peer identity of sending neighbor. | ||
138 | * @param message Message. | ||
139 | * | ||
140 | * @return GNUNET_OK to keep the connection open, | ||
141 | * GNUNET_SYSERR to close it (signal serious error) | ||
142 | */ | ||
143 | int | ||
144 | GMC_handle_broken (void* cls, | ||
145 | const struct GNUNET_PeerIdentity* id, | ||
146 | const struct GNUNET_MessageHeader* message); | ||
147 | |||
148 | /** | ||
149 | * Core handler for tunnel destruction | ||
150 | * | ||
151 | * @param cls Closure (unused). | ||
152 | * @param peer Peer identity of sending neighbor. | ||
153 | * @param message Message. | ||
154 | * | ||
155 | * @return GNUNET_OK to keep the connection open, | ||
156 | * GNUNET_SYSERR to close it (signal serious error) | ||
157 | */ | ||
158 | int | ||
159 | GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
160 | const struct GNUNET_MessageHeader *message); | ||
161 | |||
162 | /** | ||
163 | * Core handler for encrypted cadet network traffic (channel mgmt, data). | ||
164 | * | ||
165 | * @param cls Closure (unused). | ||
166 | * @param message Message received. | ||
167 | * @param peer Peer who sent the message. | ||
168 | * | ||
169 | * @return GNUNET_OK to keep the connection open, | ||
170 | * GNUNET_SYSERR to close it (signal serious error) | ||
171 | */ | ||
172 | int | ||
173 | GMC_handle_encrypted (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
174 | const struct GNUNET_MessageHeader *message); | ||
175 | |||
176 | /** | ||
177 | * Core handler for key exchange traffic (ephemeral key, ping, pong). | ||
178 | * | ||
179 | * @param cls Closure (unused). | ||
180 | * @param message Message received. | ||
181 | * @param peer Peer who sent the message. | ||
182 | * | ||
183 | * @return GNUNET_OK to keep the connection open, | ||
184 | * GNUNET_SYSERR to close it (signal serious error) | ||
185 | */ | ||
186 | int | ||
187 | GMC_handle_kx (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
188 | const struct GNUNET_MessageHeader *message); | ||
189 | |||
190 | /** | ||
191 | * Core handler for cadet network traffic point-to-point acks. | ||
192 | * | ||
193 | * @param cls closure | ||
194 | * @param message message | ||
195 | * @param peer peer identity this notification is about | ||
196 | * | ||
197 | * @return GNUNET_OK to keep the connection open, | ||
198 | * GNUNET_SYSERR to close it (signal serious error) | ||
199 | */ | ||
200 | int | ||
201 | GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
202 | const struct GNUNET_MessageHeader *message); | ||
203 | |||
204 | /** | ||
205 | * Core handler for cadet network traffic point-to-point ack polls. | ||
206 | * | ||
207 | * @param cls closure | ||
208 | * @param message message | ||
209 | * @param peer peer identity this notification is about | ||
210 | * | ||
211 | * @return GNUNET_OK to keep the connection open, | ||
212 | * GNUNET_SYSERR to close it (signal serious error) | ||
213 | */ | ||
214 | int | ||
215 | GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
216 | const struct GNUNET_MessageHeader *message); | ||
217 | |||
218 | /** | ||
219 | * Core handler for cadet keepalives. | ||
220 | * | ||
221 | * @param cls closure | ||
222 | * @param message message | ||
223 | * @param peer peer identity this notification is about | ||
224 | * @return GNUNET_OK to keep the connection open, | ||
225 | * GNUNET_SYSERR to close it (signal serious error) | ||
226 | * | ||
227 | * TODO: Check who we got this from, to validate route. | ||
228 | */ | ||
229 | int | ||
230 | GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer, | ||
231 | const struct GNUNET_MessageHeader *message); | ||
232 | |||
233 | /** | ||
234 | * Send an ACK on the appropriate connection/channel, depending on | ||
235 | * the direction and the position of the peer. | ||
236 | * | ||
237 | * @param c Which connection to send the hop-by-hop ACK. | ||
238 | * @param fwd Is this a fwd ACK? (will go dest->root). | ||
239 | * @param force Send the ACK even if suboptimal (e.g. requested by POLL). | ||
240 | */ | ||
241 | void | ||
242 | GMC_send_ack (struct CadetConnection *c, int fwd, int force); | ||
243 | |||
244 | /** | ||
245 | * Initialize the connections subsystem | ||
246 | * | ||
247 | * @param c Configuration handle. | ||
248 | */ | ||
249 | void | ||
250 | GMC_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
251 | |||
252 | /** | ||
253 | * Shut down the connections subsystem. | ||
254 | */ | ||
255 | void | ||
256 | GMC_shutdown (void); | ||
257 | |||
258 | /** | ||
259 | * Create a connection. | ||
260 | * | ||
261 | * @param cid Connection ID (either created locally or imposed remotely). | ||
262 | * @param t Tunnel this connection belongs to (or NULL); | ||
263 | * @param p Path this connection has to use. | ||
264 | * @param own_pos Own position in the @c p path. | ||
265 | * | ||
266 | * @return Newly created connection, NULL in case of error (own id not in path). | ||
267 | */ | ||
268 | struct CadetConnection * | ||
269 | GMC_new (const struct GNUNET_CADET_Hash *cid, | ||
270 | struct CadetTunnel3 *t, | ||
271 | struct CadetPeerPath *p, | ||
272 | unsigned int own_pos); | ||
273 | |||
274 | /** | ||
275 | * Connection is no longer needed: destroy it. | ||
276 | * | ||
277 | * Cancels all pending traffic (including possible DESTROY messages), all | ||
278 | * maintenance tasks and removes the connection from neighbor peers and tunnel. | ||
279 | * | ||
280 | * @param c Connection to destroy. | ||
281 | */ | ||
282 | void | ||
283 | GMC_destroy (struct CadetConnection *c); | ||
284 | |||
285 | /** | ||
286 | * Get the connection ID. | ||
287 | * | ||
288 | * @param c Connection to get the ID from. | ||
289 | * | ||
290 | * @return ID of the connection. | ||
291 | */ | ||
292 | const struct GNUNET_CADET_Hash * | ||
293 | GMC_get_id (const struct CadetConnection *c); | ||
294 | |||
295 | |||
296 | /** | ||
297 | * Get a hash for the connection ID. | ||
298 | * | ||
299 | * @param c Connection to get the hash. | ||
300 | * | ||
301 | * @return Hash expanded from the ID of the connection. | ||
302 | */ | ||
303 | const struct GNUNET_HashCode * | ||
304 | GMC_get_h (const struct CadetConnection *c); | ||
305 | |||
306 | |||
307 | /** | ||
308 | * Get the connection path. | ||
309 | * | ||
310 | * @param c Connection to get the path from. | ||
311 | * | ||
312 | * @return path used by the connection. | ||
313 | */ | ||
314 | const struct CadetPeerPath * | ||
315 | GMC_get_path (const struct CadetConnection *c); | ||
316 | |||
317 | /** | ||
318 | * Get the connection state. | ||
319 | * | ||
320 | * @param c Connection to get the state from. | ||
321 | * | ||
322 | * @return state of the connection. | ||
323 | */ | ||
324 | enum CadetConnectionState | ||
325 | GMC_get_state (const struct CadetConnection *c); | ||
326 | |||
327 | /** | ||
328 | * Get the connection tunnel. | ||
329 | * | ||
330 | * @param c Connection to get the tunnel from. | ||
331 | * | ||
332 | * @return tunnel of the connection. | ||
333 | */ | ||
334 | struct CadetTunnel3 * | ||
335 | GMC_get_tunnel (const struct CadetConnection *c); | ||
336 | |||
337 | /** | ||
338 | * Get free buffer space in a connection. | ||
339 | * | ||
340 | * @param c Connection. | ||
341 | * @param fwd Is query about FWD traffic? | ||
342 | * | ||
343 | * @return Free buffer space [0 - max_msgs_queue/max_connections] | ||
344 | */ | ||
345 | unsigned int | ||
346 | GMC_get_buffer (struct CadetConnection *c, int fwd); | ||
347 | |||
348 | /** | ||
349 | * Get how many messages have we allowed to send to us from a direction. | ||
350 | * | ||
351 | * @param c Connection. | ||
352 | * @param fwd Are we asking about traffic from FWD (BCK messages)? | ||
353 | * | ||
354 | * @return last_ack_sent - last_pid_recv | ||
355 | */ | ||
356 | unsigned int | ||
357 | GMC_get_allowed (struct CadetConnection *c, int fwd); | ||
358 | |||
359 | /** | ||
360 | * Get messages queued in a connection. | ||
361 | * | ||
362 | * @param c Connection. | ||
363 | * @param fwd Is query about FWD traffic? | ||
364 | * | ||
365 | * @return Number of messages queued. | ||
366 | */ | ||
367 | unsigned int | ||
368 | GMC_get_qn (struct CadetConnection *c, int fwd); | ||
369 | |||
370 | /** | ||
371 | * Get next PID to use. | ||
372 | * | ||
373 | * @param c Connection. | ||
374 | * @param fwd Is query about FWD traffic? | ||
375 | * | ||
376 | * @return Last PID used + 1. | ||
377 | */ | ||
378 | unsigned int | ||
379 | GMC_get_pid (struct CadetConnection *c, int fwd); | ||
380 | |||
381 | /** | ||
382 | * Allow the connection to advertise a buffer of the given size. | ||
383 | * | ||
384 | * The connection will send an @c fwd ACK message (so: in direction !fwd) | ||
385 | * allowing up to last_pid_recv + buffer. | ||
386 | * | ||
387 | * @param c Connection. | ||
388 | * @param buffer How many more messages the connection can accept. | ||
389 | * @param fwd Is this about FWD traffic? (The ack will go dest->root). | ||
390 | */ | ||
391 | void | ||
392 | GMC_allow (struct CadetConnection *c, unsigned int buffer, int fwd); | ||
393 | |||
394 | /** | ||
395 | * Send FWD keepalive packets for a connection. | ||
396 | * | ||
397 | * @param cls Closure (connection for which to send the keepalive). | ||
398 | * @param tc Notification context. | ||
399 | */ | ||
400 | void | ||
401 | GMC_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
402 | |||
403 | /** | ||
404 | * Send BCK keepalive packets for a connection. | ||
405 | * | ||
406 | * @param cls Closure (connection for which to send the keepalive). | ||
407 | * @param tc Notification context. | ||
408 | */ | ||
409 | void | ||
410 | GMC_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
411 | |||
412 | |||
413 | /** | ||
414 | * Notify other peers on a connection of a broken link. Mark connections | ||
415 | * to destroy after all traffic has been sent. | ||
416 | * | ||
417 | * @param c Connection on which there has been a disconnection. | ||
418 | * @param peer Peer that disconnected. | ||
419 | */ | ||
420 | void | ||
421 | GMC_notify_broken (struct CadetConnection *c, | ||
422 | struct CadetPeer *peer); | ||
423 | |||
424 | /** | ||
425 | * Is this peer the first one on the connection? | ||
426 | * | ||
427 | * @param c Connection. | ||
428 | * @param fwd Is this about fwd traffic? | ||
429 | * | ||
430 | * @return #GNUNET_YES if origin, #GNUNET_NO if relay/terminal. | ||
431 | */ | ||
432 | int | ||
433 | GMC_is_origin (struct CadetConnection *c, int fwd); | ||
434 | |||
435 | /** | ||
436 | * Is this peer the last one on the connection? | ||
437 | * | ||
438 | * @param c Connection. | ||
439 | * @param fwd Is this about fwd traffic? | ||
440 | * Note that the ROOT is the terminal for BCK traffic! | ||
441 | * | ||
442 | * @return #GNUNET_YES if terminal, #GNUNET_NO if relay/origin. | ||
443 | */ | ||
444 | int | ||
445 | GMC_is_terminal (struct CadetConnection *c, int fwd); | ||
446 | |||
447 | /** | ||
448 | * See if we are allowed to send by the next hop in the given direction. | ||
449 | * | ||
450 | * @param c Connection. | ||
451 | * @param fwd Is this about fwd traffic? | ||
452 | * | ||
453 | * @return #GNUNET_YES in case it's OK to send. | ||
454 | */ | ||
455 | int | ||
456 | GMC_is_sendable (struct CadetConnection *c, int fwd); | ||
457 | |||
458 | /** | ||
459 | * Check if this connection is a direct one (never trim a direct connection). | ||
460 | * | ||
461 | * @param c Connection. | ||
462 | * | ||
463 | * @return #GNUNET_YES in case it's a direct connection, #GNUNET_NO otherwise. | ||
464 | */ | ||
465 | int | ||
466 | GMC_is_direct (struct CadetConnection *c); | ||
467 | |||
468 | /** | ||
469 | * Cancel a previously sent message while it's in the queue. | ||
470 | * | ||
471 | * ONLY can be called before the continuation given to the send function | ||
472 | * is called. Once the continuation is called, the message is no longer in the | ||
473 | * queue. | ||
474 | * | ||
475 | * @param q Handle to the queue. | ||
476 | */ | ||
477 | void | ||
478 | GMC_cancel (struct CadetConnectionQueue *q); | ||
479 | |||
480 | /** | ||
481 | * Sends an already built message on a connection, properly registering | ||
482 | * all used resources. | ||
483 | * | ||
484 | * @param message Message to send. Function makes a copy of it. | ||
485 | * If message is not hop-by-hop, decrements TTL of copy. | ||
486 | * @param payload_type Type of payload, in case the message is encrypted. | ||
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 or if @c cont is NULL. | ||
495 | * Invalid on @c cont call. | ||
496 | */ | ||
497 | struct CadetConnectionQueue * | ||
498 | GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
499 | uint16_t payload_type, uint32_t payload_id, | ||
500 | struct CadetConnection *c, int fwd, int force, | ||
501 | GMC_sent cont, void *cont_cls); | ||
502 | |||
503 | /** | ||
504 | * Sends a CREATE CONNECTION message for a path to a peer. | ||
505 | * Changes the connection and tunnel states if necessary. | ||
506 | * | ||
507 | * @param connection Connection to create. | ||
508 | */ | ||
509 | void | ||
510 | GMC_send_create (struct CadetConnection *connection); | ||
511 | |||
512 | /** | ||
513 | * Send a message to all peers in this connection that the connection | ||
514 | * is no longer valid. | ||
515 | * | ||
516 | * If some peer should not receive the message, it should be zero'ed out | ||
517 | * before calling this function. | ||
518 | * | ||
519 | * @param c The connection whose peers to notify. | ||
520 | */ | ||
521 | void | ||
522 | GMC_send_destroy (struct CadetConnection *c); | ||
523 | |||
524 | /** | ||
525 | * @brief Start a polling timer for the connection. | ||
526 | * | ||
527 | * When a neighbor does not accept more traffic on the connection it could be | ||
528 | * caused by a simple congestion or by a lost ACK. Polling enables to check | ||
529 | * for the lastest ACK status for a connection. | ||
530 | * | ||
531 | * @param c Connection. | ||
532 | * @param fwd Should we poll in the FWD direction? | ||
533 | */ | ||
534 | void | ||
535 | GMC_start_poll (struct CadetConnection *c, int fwd); | ||
536 | |||
537 | |||
538 | /** | ||
539 | * @brief Stop polling a connection for ACKs. | ||
540 | * | ||
541 | * Once we have enough ACKs for future traffic, polls are no longer necessary. | ||
542 | * | ||
543 | * @param c Connection. | ||
544 | * @param fwd Should we stop the poll in the FWD direction? | ||
545 | */ | ||
546 | void | ||
547 | GMC_stop_poll (struct CadetConnection *c, int fwd); | ||
548 | |||
549 | /** | ||
550 | * Get a (static) string for a connection. | ||
551 | * | ||
552 | * @param c Connection. | ||
553 | */ | ||
554 | const char * | ||
555 | GMC_2s (const struct CadetConnection *c); | ||
556 | |||
557 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
558 | { | ||
559 | #endif | ||
560 | #ifdef __cplusplus | ||
561 | } | ||
562 | #endif | ||
563 | |||
564 | /* ifndef GNUNET_SERVICE_CADET_CONNECTION_H */ | ||
565 | #endif | ||
566 | /* end of gnunet-service-cadet_connection.h */ | ||
diff --git a/src/cadet/gnunet-service-cadet_dht.c b/src/cadet/gnunet-service-cadet_dht.c new file mode 100644 index 000000000..b187e3cd9 --- /dev/null +++ b/src/cadet/gnunet-service-cadet_dht.c | |||
@@ -0,0 +1,423 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | |||
22 | #include "platform.h" | ||
23 | #include "gnunet_util_lib.h" | ||
24 | |||
25 | #include "gnunet_dht_service.h" | ||
26 | #include "gnunet_statistics_service.h" | ||
27 | |||
28 | #include "cadet_path.h" | ||
29 | #include "gnunet-service-cadet_dht.h" | ||
30 | #include "gnunet-service-cadet_peer.h" | ||
31 | #include "gnunet-service-cadet_hello.h" | ||
32 | |||
33 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-dht",__VA_ARGS__) | ||
34 | |||
35 | |||
36 | /******************************************************************************/ | ||
37 | /******************************** STRUCTS **********************************/ | ||
38 | /******************************************************************************/ | ||
39 | |||
40 | /** | ||
41 | * Handle for DHT searches. | ||
42 | */ | ||
43 | struct GMD_search_handle | ||
44 | { | ||
45 | /** DHT_GET handle. */ | ||
46 | struct GNUNET_DHT_GetHandle *dhtget; | ||
47 | |||
48 | /** Provided callback to call when a path is found. */ | ||
49 | GMD_search_callback callback; | ||
50 | |||
51 | /** Provided closure. */ | ||
52 | void *cls; | ||
53 | |||
54 | /** Peer ID searched for */ | ||
55 | GNUNET_PEER_Id peer_id; | ||
56 | }; | ||
57 | |||
58 | |||
59 | /******************************************************************************/ | ||
60 | /******************************* GLOBALS ***********************************/ | ||
61 | /******************************************************************************/ | ||
62 | |||
63 | /** | ||
64 | * Global handle to the statistics service. | ||
65 | */ | ||
66 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
67 | |||
68 | /** | ||
69 | * Own ID (short value). | ||
70 | */ | ||
71 | extern GNUNET_PEER_Id myid; | ||
72 | |||
73 | /** | ||
74 | * Own ID (full value). | ||
75 | */ | ||
76 | extern struct GNUNET_PeerIdentity my_full_id; | ||
77 | |||
78 | /** | ||
79 | * Handle to use DHT. | ||
80 | */ | ||
81 | static struct GNUNET_DHT_Handle *dht_handle; | ||
82 | |||
83 | /** | ||
84 | * How often to PUT own ID in the DHT. | ||
85 | */ | ||
86 | static struct GNUNET_TIME_Relative id_announce_time; | ||
87 | |||
88 | /** | ||
89 | * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put. | ||
90 | */ | ||
91 | static unsigned long long dht_replication_level; | ||
92 | |||
93 | /** | ||
94 | * Task to periodically announce itself in the network. | ||
95 | */ | ||
96 | static GNUNET_SCHEDULER_TaskIdentifier announce_id_task; | ||
97 | |||
98 | /** | ||
99 | * GET requests to stop on shutdown. | ||
100 | */ | ||
101 | static struct GNUNET_CONTAINER_MultiHashMap32 *get_requests; | ||
102 | |||
103 | /******************************************************************************/ | ||
104 | /******************************** STATIC ***********************************/ | ||
105 | /******************************************************************************/ | ||
106 | |||
107 | |||
108 | /** | ||
109 | * Build a PeerPath from the paths returned from the DHT, reversing the paths | ||
110 | * to obtain a local peer -> destination path and interning the peer ids. | ||
111 | * | ||
112 | * @return Newly allocated and created path | ||
113 | * | ||
114 | * FIXME refactor and use build_path_from_peer_ids | ||
115 | */ | ||
116 | static struct CadetPeerPath * | ||
117 | path_build_from_dht (const struct GNUNET_PeerIdentity *get_path, | ||
118 | unsigned int get_path_length, | ||
119 | const struct GNUNET_PeerIdentity *put_path, | ||
120 | unsigned int put_path_length) | ||
121 | { | ||
122 | struct CadetPeerPath *p; | ||
123 | GNUNET_PEER_Id id; | ||
124 | int i; | ||
125 | |||
126 | p = path_new (1); | ||
127 | p->peers[0] = myid; | ||
128 | GNUNET_PEER_change_rc (myid, 1); | ||
129 | i = get_path_length; | ||
130 | LOG (GNUNET_ERROR_TYPE_DEBUG, " GET has %d hops.\n", i); | ||
131 | for (i--; i >= 0; i--) | ||
132 | { | ||
133 | id = GNUNET_PEER_intern (&get_path[i]); | ||
134 | if (p->length > 0 && id == p->peers[p->length - 1]) | ||
135 | { | ||
136 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n"); | ||
137 | GNUNET_PEER_change_rc (id, -1); | ||
138 | } | ||
139 | else | ||
140 | { | ||
141 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Adding from GET: %s.\n", | ||
142 | GNUNET_i2s (&get_path[i])); | ||
143 | p->length++; | ||
144 | p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length); | ||
145 | p->peers[p->length - 1] = id; | ||
146 | } | ||
147 | } | ||
148 | i = put_path_length; | ||
149 | LOG (GNUNET_ERROR_TYPE_DEBUG, " PUT has %d hops.\n", i); | ||
150 | for (i--; i >= 0; i--) | ||
151 | { | ||
152 | id = GNUNET_PEER_intern (&put_path[i]); | ||
153 | if (id == myid) | ||
154 | { | ||
155 | /* PUT path went through us, so discard the path up until now and start | ||
156 | * from here to get a much shorter (and loop-free) path. | ||
157 | */ | ||
158 | path_destroy (p); | ||
159 | p = path_new (0); | ||
160 | } | ||
161 | if (p->length > 0 && id == p->peers[p->length - 1]) | ||
162 | { | ||
163 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n"); | ||
164 | GNUNET_PEER_change_rc (id, -1); | ||
165 | } | ||
166 | else | ||
167 | { | ||
168 | LOG (GNUNET_ERROR_TYPE_DEBUG, " Adding from PUT: %s.\n", | ||
169 | GNUNET_i2s (&put_path[i])); | ||
170 | p->length++; | ||
171 | p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length); | ||
172 | p->peers[p->length - 1] = id; | ||
173 | } | ||
174 | } | ||
175 | #if CADET_DEBUG | ||
176 | if (get_path_length > 0) | ||
177 | LOG (GNUNET_ERROR_TYPE_DEBUG, " (first of GET: %s)\n", | ||
178 | GNUNET_i2s (&get_path[0])); | ||
179 | if (put_path_length > 0) | ||
180 | LOG (GNUNET_ERROR_TYPE_DEBUG, " (first of PUT: %s)\n", | ||
181 | GNUNET_i2s (&put_path[0])); | ||
182 | LOG (GNUNET_ERROR_TYPE_DEBUG, " In total: %d hops\n", | ||
183 | p->length); | ||
184 | for (i = 0; i < p->length; i++) | ||
185 | { | ||
186 | struct GNUNET_PeerIdentity peer_id; | ||
187 | |||
188 | GNUNET_PEER_resolve (p->peers[i], &peer_id); | ||
189 | LOG (GNUNET_ERROR_TYPE_DEBUG, " %u: %s\n", p->peers[i], | ||
190 | GNUNET_i2s (&peer_id)); | ||
191 | } | ||
192 | #endif | ||
193 | return p; | ||
194 | } | ||
195 | |||
196 | |||
197 | /** | ||
198 | * Function to process paths received for a new peer addition. The recorded | ||
199 | * paths form the initial tunnel, which can be optimized later. | ||
200 | * Called on each result obtained for the DHT search. | ||
201 | * | ||
202 | * @param cls closure | ||
203 | * @param exp when will this value expire | ||
204 | * @param key key of the result | ||
205 | * @param get_path path of the get request | ||
206 | * @param get_path_length lenght of get_path | ||
207 | * @param put_path path of the put request | ||
208 | * @param put_path_length length of the put_path | ||
209 | * @param type type of the result | ||
210 | * @param size number of bytes in data | ||
211 | * @param data pointer to the result data | ||
212 | */ | ||
213 | static void | ||
214 | dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp, | ||
215 | const struct GNUNET_HashCode * key, | ||
216 | const struct GNUNET_PeerIdentity *get_path, | ||
217 | unsigned int get_path_length, | ||
218 | const struct GNUNET_PeerIdentity *put_path, | ||
219 | unsigned int put_path_length, enum GNUNET_BLOCK_Type type, | ||
220 | size_t size, const void *data) | ||
221 | { | ||
222 | struct GMD_search_handle *h = cls; | ||
223 | struct GNUNET_HELLO_Message *hello; | ||
224 | struct CadetPeerPath *p; | ||
225 | struct CadetPeer *peer; | ||
226 | char *s; | ||
227 | |||
228 | p = path_build_from_dht (get_path, get_path_length, | ||
229 | put_path, put_path_length); | ||
230 | s = path_2s (p); | ||
231 | LOG (GNUNET_ERROR_TYPE_INFO, "Got path from DHT: %s\n", s); | ||
232 | GNUNET_free_non_null (s); | ||
233 | peer = GMP_get_short (p->peers[p->length - 1]); | ||
234 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got HELLO for %s\n", GMP_2s (peer)); | ||
235 | h->callback (h->cls, p); | ||
236 | path_destroy (p); | ||
237 | hello = (struct GNUNET_HELLO_Message *) data; | ||
238 | GMP_set_hello (peer, hello); | ||
239 | GMP_try_connect (peer); | ||
240 | return; | ||
241 | } | ||
242 | |||
243 | |||
244 | /** | ||
245 | * Periodically announce self id in the DHT | ||
246 | * | ||
247 | * @param cls closure | ||
248 | * @param tc task context | ||
249 | */ | ||
250 | static void | ||
251 | announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
252 | { | ||
253 | struct GNUNET_HashCode phash; | ||
254 | const struct GNUNET_HELLO_Message *hello; | ||
255 | size_t size; | ||
256 | struct GNUNET_TIME_Absolute expiration; | ||
257 | struct GNUNET_TIME_Relative retry_time; | ||
258 | |||
259 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
260 | { | ||
261 | announce_id_task = GNUNET_SCHEDULER_NO_TASK; | ||
262 | return; | ||
263 | } | ||
264 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Announce ID\n"); | ||
265 | |||
266 | /* TODO | ||
267 | * - Set data expiration in function of X | ||
268 | * - Adapt X to churn | ||
269 | */ | ||
270 | hello = GMH_get_mine (); | ||
271 | if (NULL == hello || (size = GNUNET_HELLO_size (hello)) == 0) | ||
272 | { | ||
273 | /* Peerinfo gave us no hello yet, try again in a second. */ | ||
274 | announce_id_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
275 | &announce_id, cls); | ||
276 | LOG (GNUNET_ERROR_TYPE_DEBUG, " no hello, waiting!\n"); | ||
277 | return; | ||
278 | } | ||
279 | expiration = GNUNET_HELLO_get_last_expiration (hello); | ||
280 | retry_time = GNUNET_TIME_absolute_get_remaining (expiration); | ||
281 | |||
282 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Hello %p size: %u\n", hello, size); | ||
283 | memset (&phash, 0, sizeof (phash)); | ||
284 | memcpy (&phash, &my_full_id, sizeof (my_full_id)); | ||
285 | GNUNET_DHT_put (dht_handle, /* DHT handle */ | ||
286 | &phash, /* Key to use */ | ||
287 | dht_replication_level, /* Replication level */ | ||
288 | GNUNET_DHT_RO_RECORD_ROUTE | ||
289 | | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */ | ||
290 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* Block type */ | ||
291 | size, /* Size of the data */ | ||
292 | (const char *) hello, /* Data itself */ | ||
293 | expiration, /* Data expiration */ | ||
294 | retry_time, /* Retry time */ | ||
295 | NULL, /* Continuation */ | ||
296 | NULL); /* Continuation closure */ | ||
297 | announce_id_task = | ||
298 | GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls); | ||
299 | } | ||
300 | |||
301 | /** | ||
302 | * Iterator over hash map entries and stop GET requests before disconnecting | ||
303 | * from the DHT. | ||
304 | * | ||
305 | * @param cls Closure (unused) | ||
306 | * @param key Current peer ID. | ||
307 | * @param value Value in the hash map (GMD_search_handle). | ||
308 | * | ||
309 | * @return #GNUNET_YES, we should continue to iterate, | ||
310 | */ | ||
311 | int | ||
312 | stop_get (void *cls, | ||
313 | uint32_t key, | ||
314 | void *value) | ||
315 | { | ||
316 | struct GMD_search_handle *h = value; | ||
317 | |||
318 | GMD_search_stop (h); | ||
319 | return GNUNET_YES; | ||
320 | } | ||
321 | |||
322 | |||
323 | /******************************************************************************/ | ||
324 | /******************************** API ***********************************/ | ||
325 | /******************************************************************************/ | ||
326 | |||
327 | /** | ||
328 | * Initialize the DHT subsystem. | ||
329 | * | ||
330 | * @param c Configuration. | ||
331 | */ | ||
332 | void | ||
333 | GMD_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
334 | { | ||
335 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
336 | if (GNUNET_OK != | ||
337 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DHT_REPLICATION_LEVEL", | ||
338 | &dht_replication_level)) | ||
339 | { | ||
340 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
341 | "CADET", "DHT_REPLICATION_LEVEL", "USING DEFAULT"); | ||
342 | dht_replication_level = 3; | ||
343 | } | ||
344 | |||
345 | if (GNUNET_OK != | ||
346 | GNUNET_CONFIGURATION_get_value_time (c, "CADET", "ID_ANNOUNCE_TIME", | ||
347 | &id_announce_time)) | ||
348 | { | ||
349 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, | ||
350 | "CADET", "ID_ANNOUNCE_TIME", "MISSING"); | ||
351 | GNUNET_SCHEDULER_shutdown (); | ||
352 | return; | ||
353 | } | ||
354 | |||
355 | dht_handle = GNUNET_DHT_connect (c, 64); | ||
356 | if (NULL == dht_handle) | ||
357 | { | ||
358 | GNUNET_break (0); | ||
359 | } | ||
360 | |||
361 | announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, NULL); | ||
362 | get_requests = GNUNET_CONTAINER_multihashmap32_create (32); | ||
363 | } | ||
364 | |||
365 | |||
366 | /** | ||
367 | * Shut down the DHT subsystem. | ||
368 | */ | ||
369 | void | ||
370 | GMD_shutdown (void) | ||
371 | { | ||
372 | GNUNET_CONTAINER_multihashmap32_iterate (get_requests, &stop_get, NULL); | ||
373 | GNUNET_CONTAINER_multihashmap32_destroy (get_requests); | ||
374 | if (dht_handle != NULL) | ||
375 | { | ||
376 | GNUNET_DHT_disconnect (dht_handle); | ||
377 | dht_handle = NULL; | ||
378 | } | ||
379 | if (GNUNET_SCHEDULER_NO_TASK != announce_id_task) | ||
380 | { | ||
381 | GNUNET_SCHEDULER_cancel (announce_id_task); | ||
382 | announce_id_task = GNUNET_SCHEDULER_NO_TASK; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | struct GMD_search_handle * | ||
387 | GMD_search (const struct GNUNET_PeerIdentity *peer_id, | ||
388 | GMD_search_callback callback, void *cls) | ||
389 | { | ||
390 | struct GNUNET_HashCode phash; | ||
391 | struct GMD_search_handle *h; | ||
392 | |||
393 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
394 | " Starting DHT GET for peer %s\n", GNUNET_i2s (peer_id)); | ||
395 | memset (&phash, 0, sizeof (phash)); | ||
396 | memcpy (&phash, peer_id, sizeof (*peer_id)); | ||
397 | h = GNUNET_new (struct GMD_search_handle); | ||
398 | h->peer_id = GNUNET_PEER_intern (peer_id); | ||
399 | h->callback = callback; | ||
400 | h->cls = cls; | ||
401 | h->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */ | ||
402 | GNUNET_BLOCK_TYPE_DHT_HELLO, /* type */ | ||
403 | &phash, /* key to search */ | ||
404 | dht_replication_level, /* replication level */ | ||
405 | GNUNET_DHT_RO_RECORD_ROUTE | | ||
406 | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, | ||
407 | NULL, /* xquery */ | ||
408 | 0, /* xquery bits */ | ||
409 | &dht_get_id_handler, h); | ||
410 | GNUNET_CONTAINER_multihashmap32_put (get_requests, h->peer_id, h, | ||
411 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
412 | return h; | ||
413 | } | ||
414 | |||
415 | void | ||
416 | GMD_search_stop (struct GMD_search_handle *h) | ||
417 | { | ||
418 | GNUNET_break (GNUNET_OK == | ||
419 | GNUNET_CONTAINER_multihashmap32_remove (get_requests, | ||
420 | h->peer_id, h)); | ||
421 | GNUNET_DHT_get_stop (h->dhtget); | ||
422 | GNUNET_free (h); | ||
423 | } | ||
diff --git a/src/cadet/gnunet-service-cadet_dht.h b/src/cadet/gnunet-service-cadet_dht.h new file mode 100644 index 000000000..6cac531ff --- /dev/null +++ b/src/cadet/gnunet-service-cadet_dht.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, 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 | * | ||
26 | * All functions in this file should use the prefix GMD (Gnunet Cadet Dht) | ||
27 | */ | ||
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 | struct GMD_search_handle; | ||
44 | |||
45 | |||
46 | /** | ||
47 | * Callback called on each path found over the DHT. | ||
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 | */ | ||
53 | typedef void (*GMD_search_callback) (void *cls, | ||
54 | const struct CadetPeerPath *path); | ||
55 | |||
56 | /******************************************************************************/ | ||
57 | /******************************** API ***********************************/ | ||
58 | /******************************************************************************/ | ||
59 | |||
60 | /** | ||
61 | * Initialize the DHT subsystem. | ||
62 | * | ||
63 | * @param c Configuration. | ||
64 | */ | ||
65 | void | ||
66 | GMD_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
67 | |||
68 | /** | ||
69 | * Shut down the DHT subsystem. | ||
70 | */ | ||
71 | void | ||
72 | GMD_shutdown (void); | ||
73 | |||
74 | |||
75 | struct GMD_search_handle * | ||
76 | GMD_search (const struct GNUNET_PeerIdentity *peer_id, | ||
77 | GMD_search_callback callback, void *cls); | ||
78 | |||
79 | |||
80 | void | ||
81 | GMD_search_stop (struct GMD_search_handle *h); | ||
82 | |||
83 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
84 | { | ||
85 | #endif | ||
86 | #ifdef __cplusplus | ||
87 | } | ||
88 | #endif | ||
89 | |||
90 | /* ifndef GNUNET_CADET_SERVICE_LOCAL_H */ | ||
91 | #endif | ||
92 | /* end of gnunet-cadet-service_LOCAL.h */ \ No newline at end of file | ||
diff --git a/src/cadet/gnunet-service-cadet_hello.c b/src/cadet/gnunet-service-cadet_hello.c new file mode 100644 index 000000000..7eda3f507 --- /dev/null +++ b/src/cadet/gnunet-service-cadet_hello.c | |||
@@ -0,0 +1,198 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2014 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #include "platform.h" | ||
22 | #include "gnunet_util_lib.h" | ||
23 | |||
24 | #include "gnunet_statistics_service.h" | ||
25 | #include "gnunet_peerinfo_service.h" | ||
26 | |||
27 | #include "cadet_protocol.h" | ||
28 | #include "cadet_path.h" | ||
29 | |||
30 | #include "gnunet-service-cadet_hello.h" | ||
31 | #include "gnunet-service-cadet_peer.h" | ||
32 | |||
33 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-hll",__VA_ARGS__) | ||
34 | |||
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 | /** | ||
69 | * Hello message of local peer. | ||
70 | */ | ||
71 | const struct GNUNET_HELLO_Message *mine; | ||
72 | |||
73 | /** | ||
74 | * Handle to peerinfo service. | ||
75 | */ | ||
76 | static struct GNUNET_PEERINFO_Handle *peerinfo; | ||
77 | |||
78 | /** | ||
79 | * Iterator context. | ||
80 | */ | ||
81 | struct GNUNET_PEERINFO_NotifyContext* nc; | ||
82 | |||
83 | |||
84 | /******************************************************************************/ | ||
85 | /******************************** STATIC ***********************************/ | ||
86 | /******************************************************************************/ | ||
87 | |||
88 | /** | ||
89 | * Process each hello message received from peerinfo. | ||
90 | * | ||
91 | * @param cls Closure (unused). | ||
92 | * @param peer Identity of the peer. | ||
93 | * @param hello Hello of the peer. | ||
94 | * @param err_msg Error message. | ||
95 | */ | ||
96 | static void | ||
97 | got_hello (void *cls, const struct GNUNET_PeerIdentity *id, | ||
98 | const struct GNUNET_HELLO_Message *hello, | ||
99 | const char *err_msg) | ||
100 | { | ||
101 | struct CadetPeer *peer; | ||
102 | |||
103 | if (NULL == id || NULL == hello) | ||
104 | { | ||
105 | LOG (GNUNET_ERROR_TYPE_DEBUG, " hello with id %p and msg %p\n", id, hello); | ||
106 | return; | ||
107 | } | ||
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 = GMP_get (id); | ||
112 | GMP_set_hello (peer, hello); | ||
113 | |||
114 | if (GMP_get_short_id (peer) == myid) | ||
115 | { | ||
116 | mine = GMP_get_hello (peer); | ||
117 | LOG (GNUNET_ERROR_TYPE_DEBUG, " updated mine to %p\n", mine); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | |||
122 | /******************************************************************************/ | ||
123 | /******************************** API ***********************************/ | ||
124 | /******************************************************************************/ | ||
125 | |||
126 | /** | ||
127 | * Initialize the hello subsystem. | ||
128 | * | ||
129 | * @param c Configuration. | ||
130 | */ | ||
131 | void | ||
132 | GMH_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
133 | { | ||
134 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
135 | GNUNET_assert (NULL == nc); | ||
136 | peerinfo = GNUNET_PEERINFO_connect (c); | ||
137 | nc = GNUNET_PEERINFO_notify (c, GNUNET_NO, &got_hello, NULL); | ||
138 | } | ||
139 | |||
140 | |||
141 | /** | ||
142 | * Shut down the hello subsystem. | ||
143 | */ | ||
144 | void | ||
145 | GMH_shutdown () | ||
146 | { | ||
147 | if (NULL != nc) | ||
148 | { | ||
149 | GNUNET_PEERINFO_notify_cancel (nc); | ||
150 | nc = NULL; | ||
151 | } | ||
152 | if (NULL != peerinfo) | ||
153 | { | ||
154 | GNUNET_PEERINFO_disconnect (peerinfo); | ||
155 | peerinfo = NULL; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | |||
160 | /** | ||
161 | * Get own hello message. | ||
162 | * | ||
163 | * @return Own hello message. | ||
164 | */ | ||
165 | const struct GNUNET_HELLO_Message * | ||
166 | GMH_get_mine (void) | ||
167 | { | ||
168 | LOG (GNUNET_ERROR_TYPE_DEBUG, " mine is %p\n", mine); | ||
169 | return mine; | ||
170 | } | ||
171 | |||
172 | |||
173 | /** | ||
174 | * Get another peer's hello message. | ||
175 | * | ||
176 | * @param id ID of the peer whose hello message is requested. | ||
177 | * | ||
178 | * @return Hello message, if any (NULL possible). | ||
179 | */ | ||
180 | const struct GNUNET_HELLO_Message * | ||
181 | GMH_get (const struct GNUNET_PeerIdentity *id) | ||
182 | { | ||
183 | return GMP_get_hello (GMP_get (id)); | ||
184 | } | ||
185 | |||
186 | |||
187 | /** | ||
188 | * Convert a hello message to a string. | ||
189 | * | ||
190 | * @param h Hello message. | ||
191 | */ | ||
192 | char * | ||
193 | GMH_2s (const struct GNUNET_HELLO_Message *h) | ||
194 | { | ||
195 | return "hello (TODO)"; | ||
196 | } | ||
197 | |||
198 | |||
diff --git a/src/cadet/gnunet-service-cadet_hello.h b/src/cadet/gnunet-service-cadet_hello.h new file mode 100644 index 000000000..8e978ea9d --- /dev/null +++ b/src/cadet/gnunet-service-cadet_hello.h | |||
@@ -0,0 +1,76 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2014 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, 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 | * | ||
26 | * All functions in this file should use the prefix GMH (Gnunet Cadet Hello) | ||
27 | */ | ||
28 | |||
29 | #ifndef GNUNET_SERVICE_CADET_HELLO_H | ||
30 | #define GNUNET_SERVICE_CADET_HELLO_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 | #include "gnunet_hello_lib.h" | ||
43 | |||
44 | |||
45 | /** | ||
46 | * Initialize the hello subsystem. | ||
47 | * | ||
48 | * @param c Configuration. | ||
49 | */ | ||
50 | void | ||
51 | GMH_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
52 | |||
53 | /** | ||
54 | * Shut down the hello subsystem. | ||
55 | */ | ||
56 | void | ||
57 | GMH_shutdown (); | ||
58 | |||
59 | /** | ||
60 | * Get own hello message. | ||
61 | * | ||
62 | * @return Own hello message. | ||
63 | */ | ||
64 | const struct GNUNET_HELLO_Message * | ||
65 | GMH_get_mine (void); | ||
66 | |||
67 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
68 | { | ||
69 | #endif | ||
70 | #ifdef __cplusplus | ||
71 | } | ||
72 | #endif | ||
73 | |||
74 | /* ifndef GNUNET_CADET_SERVICE_HELLO_H */ | ||
75 | #endif | ||
76 | /* end of gnunet-cadet-service_hello.h */ | ||
diff --git a/src/cadet/gnunet-service-cadet_local.c b/src/cadet/gnunet-service-cadet_local.c new file mode 100644 index 000000000..96596ce68 --- /dev/null +++ b/src/cadet/gnunet-service-cadet_local.c | |||
@@ -0,0 +1,1242 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, 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 | CADET_ChannelNumber next_chid; | ||
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_MultiHashMap32 *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_MultiHashMap32 *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 | uint32_t key, | ||
154 | void *value) | ||
155 | { | ||
156 | int res; | ||
157 | |||
158 | res = GNUNET_CONTAINER_multihashmap32_remove (ports, key, value); | ||
159 | if (GNUNET_YES != res) | ||
160 | { | ||
161 | GNUNET_break (0); | ||
162 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
163 | "Port %u by client %p was not registered.\n", | ||
164 | key, value); | ||
165 | } | ||
166 | return GNUNET_OK; | ||
167 | } | ||
168 | |||
169 | |||
170 | |||
171 | /******************************************************************************/ | ||
172 | /******************************** HANDLES ***********************************/ | ||
173 | /******************************************************************************/ | ||
174 | |||
175 | |||
176 | /** | ||
177 | * Handler for client connection. | ||
178 | * | ||
179 | * @param cls Closure (unused). | ||
180 | * @param client Client handler. | ||
181 | */ | ||
182 | static void | ||
183 | handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client) | ||
184 | { | ||
185 | struct CadetClient *c; | ||
186 | |||
187 | LOG (GNUNET_ERROR_TYPE_DEBUG, "client connected: %p\n", client); | ||
188 | if (NULL == client) | ||
189 | return; | ||
190 | c = GNUNET_new (struct CadetClient); | ||
191 | c->handle = client; | ||
192 | c->id = next_client_id++; /* overflow not important: just for debug */ | ||
193 | c->next_chid = GNUNET_CADET_LOCAL_CHANNEL_ID_SERV; | ||
194 | GNUNET_SERVER_client_keep (client); | ||
195 | GNUNET_SERVER_client_set_user_context (client, c); | ||
196 | GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c); | ||
197 | } | ||
198 | |||
199 | |||
200 | /** | ||
201 | * Iterator for deleting each channel whose client endpoint disconnected. | ||
202 | * | ||
203 | * @param cls Closure (client that has disconnected). | ||
204 | * @param key The local channel id (used to access the hashmap). | ||
205 | * @param value The value stored at the key (channel to destroy). | ||
206 | * | ||
207 | * @return GNUNET_OK, keep iterating. | ||
208 | */ | ||
209 | static int | ||
210 | channel_destroy_iterator (void *cls, | ||
211 | uint32_t key, | ||
212 | void *value) | ||
213 | { | ||
214 | struct CadetChannel *ch = value; | ||
215 | struct CadetClient *c = cls; | ||
216 | |||
217 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
218 | " Channel %s destroy, due to client %s shutdown.\n", | ||
219 | GMCH_2s (ch), GML_2s (c)); | ||
220 | |||
221 | GMCH_handle_local_destroy (ch, c, key < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV); | ||
222 | return GNUNET_OK; | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * Handler for client disconnection | ||
227 | * | ||
228 | * @param cls closure | ||
229 | * @param client identification of the client; NULL | ||
230 | * for the last call when the server is destroyed | ||
231 | */ | ||
232 | static void | ||
233 | handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | ||
234 | { | ||
235 | struct CadetClient *c; | ||
236 | |||
237 | LOG (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client); | ||
238 | if (client == NULL) | ||
239 | { | ||
240 | LOG (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n"); | ||
241 | return; | ||
242 | } | ||
243 | |||
244 | c = GML_client_get (client); | ||
245 | if (NULL != c) | ||
246 | { | ||
247 | LOG (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u, %p)\n", | ||
248 | c->id, c); | ||
249 | GNUNET_SERVER_client_drop (c->handle); | ||
250 | c->shutting_down = GNUNET_YES; | ||
251 | if (NULL != c->own_channels) | ||
252 | { | ||
253 | GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels, | ||
254 | &channel_destroy_iterator, c); | ||
255 | GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels); | ||
256 | } | ||
257 | |||
258 | if (NULL != c->incoming_channels) | ||
259 | { | ||
260 | GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels, | ||
261 | &channel_destroy_iterator, c); | ||
262 | GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels); | ||
263 | } | ||
264 | |||
265 | if (NULL != c->ports) | ||
266 | { | ||
267 | GNUNET_CONTAINER_multihashmap32_iterate (c->ports, | ||
268 | &client_release_ports, c); | ||
269 | GNUNET_CONTAINER_multihashmap32_destroy (c->ports); | ||
270 | } | ||
271 | GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c); | ||
272 | GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO); | ||
273 | LOG (GNUNET_ERROR_TYPE_DEBUG, " client free (%p)\n", c); | ||
274 | GNUNET_free (c); | ||
275 | } | ||
276 | else | ||
277 | { | ||
278 | LOG (GNUNET_ERROR_TYPE_WARNING, " context NULL!\n"); | ||
279 | } | ||
280 | LOG (GNUNET_ERROR_TYPE_DEBUG, "done!\n"); | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | |||
285 | /** | ||
286 | * Handler for new clients | ||
287 | * | ||
288 | * @param cls closure | ||
289 | * @param client identification of the client | ||
290 | * @param message the actual message, which includes messages the client wants | ||
291 | */ | ||
292 | static void | ||
293 | handle_new_client (void *cls, struct GNUNET_SERVER_Client *client, | ||
294 | const struct GNUNET_MessageHeader *message) | ||
295 | { | ||
296 | struct GNUNET_CADET_ClientConnect *cc_msg; | ||
297 | struct CadetClient *c; | ||
298 | unsigned int size; | ||
299 | uint32_t *p; | ||
300 | unsigned int i; | ||
301 | |||
302 | LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); | ||
303 | LOG (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client); | ||
304 | |||
305 | /* Check data sanity */ | ||
306 | size = ntohs (message->size) - sizeof (struct GNUNET_CADET_ClientConnect); | ||
307 | cc_msg = (struct GNUNET_CADET_ClientConnect *) message; | ||
308 | if (0 != (size % sizeof (uint32_t))) | ||
309 | { | ||
310 | GNUNET_break (0); | ||
311 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
312 | return; | ||
313 | } | ||
314 | size /= sizeof (uint32_t); | ||
315 | |||
316 | /* Initialize new client structure */ | ||
317 | c = GNUNET_SERVER_client_get_user_context (client, struct CadetClient); | ||
318 | LOG (GNUNET_ERROR_TYPE_DEBUG, " client id %u\n", c->id); | ||
319 | LOG (GNUNET_ERROR_TYPE_DEBUG, " client has %u ports\n", size); | ||
320 | if (size > 0) | ||
321 | { | ||
322 | uint32_t u32; | ||
323 | |||
324 | p = (uint32_t *) &cc_msg[1]; | ||
325 | c->ports = GNUNET_CONTAINER_multihashmap32_create (size); | ||
326 | for (i = 0; i < size; i++) | ||
327 | { | ||
328 | u32 = ntohl (p[i]); | ||
329 | LOG (GNUNET_ERROR_TYPE_DEBUG, " port: %u\n", u32); | ||
330 | |||
331 | /* store in client's hashmap */ | ||
332 | GNUNET_CONTAINER_multihashmap32_put (c->ports, u32, c, | ||
333 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
334 | /* store in global hashmap */ | ||
335 | /* FIXME only allow one client to have the port open, | ||
336 | * have a backup hashmap with waiting clients */ | ||
337 | GNUNET_CONTAINER_multihashmap32_put (ports, u32, c, | ||
338 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32); | ||
343 | c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32); | ||
344 | GNUNET_SERVER_notification_context_add (nc, client); | ||
345 | GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO); | ||
346 | |||
347 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
348 | LOG (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n"); | ||
349 | } | ||
350 | |||
351 | |||
352 | /** | ||
353 | * Handler for requests of new tunnels | ||
354 | * | ||
355 | * @param cls Closure. | ||
356 | * @param client Identification of the client. | ||
357 | * @param message The actual message. | ||
358 | */ | ||
359 | static void | ||
360 | handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client, | ||
361 | const struct GNUNET_MessageHeader *message) | ||
362 | { | ||
363 | struct CadetClient *c; | ||
364 | |||
365 | LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); | ||
366 | LOG (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n"); | ||
367 | |||
368 | /* Sanity check for client registration */ | ||
369 | if (NULL == (c = GML_client_get (client))) | ||
370 | { | ||
371 | GNUNET_break (0); | ||
372 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
373 | return; | ||
374 | } | ||
375 | LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); | ||
376 | |||
377 | /* Message size sanity check */ | ||
378 | if (sizeof (struct GNUNET_CADET_ChannelMessage) != ntohs (message->size)) | ||
379 | { | ||
380 | GNUNET_break (0); | ||
381 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
382 | return; | ||
383 | } | ||
384 | |||
385 | if (GNUNET_OK != | ||
386 | GMCH_handle_local_create (c, | ||
387 | (struct GNUNET_CADET_ChannelMessage *) message)) | ||
388 | { | ||
389 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
390 | return; | ||
391 | } | ||
392 | |||
393 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
394 | return; | ||
395 | } | ||
396 | |||
397 | |||
398 | /** | ||
399 | * Handler for requests of deleting tunnels | ||
400 | * | ||
401 | * @param cls closure | ||
402 | * @param client identification of the client | ||
403 | * @param message the actual message | ||
404 | */ | ||
405 | static void | ||
406 | handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client, | ||
407 | const struct GNUNET_MessageHeader *message) | ||
408 | { | ||
409 | struct GNUNET_CADET_ChannelMessage *msg; | ||
410 | struct CadetClient *c; | ||
411 | struct CadetChannel *ch; | ||
412 | CADET_ChannelNumber chid; | ||
413 | |||
414 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a DESTROY CHANNEL from client!\n"); | ||
415 | |||
416 | /* Sanity check for client registration */ | ||
417 | if (NULL == (c = GML_client_get (client))) | ||
418 | { | ||
419 | GNUNET_break (0); | ||
420 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
421 | return; | ||
422 | } | ||
423 | LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); | ||
424 | |||
425 | /* Message sanity check */ | ||
426 | if (sizeof (struct GNUNET_CADET_ChannelMessage) != ntohs (message->size)) | ||
427 | { | ||
428 | GNUNET_break (0); | ||
429 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | msg = (struct GNUNET_CADET_ChannelMessage *) message; | ||
434 | |||
435 | /* Retrieve tunnel */ | ||
436 | chid = ntohl (msg->channel_id); | ||
437 | LOG (GNUNET_ERROR_TYPE_DEBUG, " for channel %X\n", chid); | ||
438 | ch = GML_channel_get (c, chid); | ||
439 | if (NULL == ch) | ||
440 | { | ||
441 | LOG (GNUNET_ERROR_TYPE_DEBUG, " channel %X not found\n", chid); | ||
442 | GNUNET_STATISTICS_update (stats, | ||
443 | "# client destroy messages on unknown channel", | ||
444 | 1, GNUNET_NO); | ||
445 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
446 | return; | ||
447 | } | ||
448 | |||
449 | GMCH_handle_local_destroy (ch, c, chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV); | ||
450 | |||
451 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
452 | return; | ||
453 | } | ||
454 | |||
455 | |||
456 | /** | ||
457 | * Handler for client traffic | ||
458 | * | ||
459 | * @param cls closure | ||
460 | * @param client identification of the client | ||
461 | * @param message the actual message | ||
462 | */ | ||
463 | static void | ||
464 | handle_data (void *cls, struct GNUNET_SERVER_Client *client, | ||
465 | const struct GNUNET_MessageHeader *message) | ||
466 | { | ||
467 | struct GNUNET_CADET_LocalData *msg; | ||
468 | struct CadetClient *c; | ||
469 | struct CadetChannel *ch; | ||
470 | CADET_ChannelNumber chid; | ||
471 | size_t size; | ||
472 | int fwd; | ||
473 | |||
474 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got data from a client!\n"); | ||
475 | |||
476 | /* Sanity check for client registration */ | ||
477 | if (NULL == (c = GML_client_get (client))) | ||
478 | { | ||
479 | GNUNET_break (0); | ||
480 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
481 | return; | ||
482 | } | ||
483 | LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); | ||
484 | |||
485 | msg = (struct GNUNET_CADET_LocalData *) message; | ||
486 | |||
487 | /* Sanity check for message size */ | ||
488 | size = ntohs (message->size) - sizeof (struct GNUNET_CADET_LocalData); | ||
489 | if (size < sizeof (struct GNUNET_MessageHeader)) | ||
490 | { | ||
491 | GNUNET_break (0); | ||
492 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
493 | return; | ||
494 | } | ||
495 | |||
496 | /* Channel exists? */ | ||
497 | chid = ntohl (msg->id); | ||
498 | LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", chid); | ||
499 | fwd = chid < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV; | ||
500 | ch = GML_channel_get (c, chid); | ||
501 | if (NULL == ch) | ||
502 | { | ||
503 | GNUNET_STATISTICS_update (stats, | ||
504 | "# client data messages on unknown channel", | ||
505 | 1, GNUNET_NO); | ||
506 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
507 | return; | ||
508 | } | ||
509 | |||
510 | if (GNUNET_OK != | ||
511 | GMCH_handle_local_data (ch, c, | ||
512 | (struct GNUNET_MessageHeader *)&msg[1], fwd)) | ||
513 | { | ||
514 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
515 | return; | ||
516 | } | ||
517 | |||
518 | LOG (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n"); | ||
519 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
520 | |||
521 | return; | ||
522 | } | ||
523 | |||
524 | |||
525 | /** | ||
526 | * Handler for client's ACKs for payload traffic. | ||
527 | * | ||
528 | * @param cls Closure (unused). | ||
529 | * @param client Identification of the client. | ||
530 | * @param message The actual message. | ||
531 | */ | ||
532 | static void | ||
533 | handle_ack (void *cls, struct GNUNET_SERVER_Client *client, | ||
534 | const struct GNUNET_MessageHeader *message) | ||
535 | { | ||
536 | struct GNUNET_CADET_LocalAck *msg; | ||
537 | struct CadetChannel *ch; | ||
538 | struct CadetClient *c; | ||
539 | CADET_ChannelNumber chid; | ||
540 | int fwd; | ||
541 | |||
542 | LOG (GNUNET_ERROR_TYPE_DEBUG, "\n"); | ||
543 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n"); | ||
544 | |||
545 | /* Sanity check for client registration */ | ||
546 | if (NULL == (c = GML_client_get (client))) | ||
547 | { | ||
548 | GNUNET_break (0); | ||
549 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
550 | return; | ||
551 | } | ||
552 | LOG (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id); | ||
553 | |||
554 | msg = (struct GNUNET_CADET_LocalAck *) message; | ||
555 | |||
556 | /* Channel exists? */ | ||
557 | chid = ntohl (msg->channel_id); | ||
558 | LOG (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", chid); | ||
559 | ch = GML_channel_get (c, chid); | ||
560 | LOG (GNUNET_ERROR_TYPE_DEBUG, " -- ch %p\n", ch); | ||
561 | if (NULL == ch) | ||
562 | { | ||
563 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %X unknown.\n", chid); | ||
564 | LOG (GNUNET_ERROR_TYPE_DEBUG, " for client %u.\n", c->id); | ||
565 | GNUNET_STATISTICS_update (stats, | ||
566 | "# client ack messages on unknown channel", | ||
567 | 1, GNUNET_NO); | ||
568 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
569 | return; | ||
570 | } | ||
571 | |||
572 | /* If client is root, the ACK is going FWD, therefore this is "BCK ACK". */ | ||
573 | /* If client is dest, the ACK is going BCK, therefore this is "FWD ACK" */ | ||
574 | fwd = chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV; | ||
575 | |||
576 | GMCH_handle_local_ack (ch, fwd); | ||
577 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
578 | |||
579 | return; | ||
580 | } | ||
581 | |||
582 | |||
583 | |||
584 | /** | ||
585 | * Iterator over all peers to send a monitoring client info about each peer. | ||
586 | * | ||
587 | * @param cls Closure (). | ||
588 | * @param peer Peer ID (tunnel remote peer). | ||
589 | * @param value Peer info. | ||
590 | * | ||
591 | * @return #GNUNET_YES, to keep iterating. | ||
592 | */ | ||
593 | static int | ||
594 | get_all_peers_iterator (void *cls, | ||
595 | const struct GNUNET_PeerIdentity * peer, | ||
596 | void *value) | ||
597 | { | ||
598 | struct GNUNET_SERVER_Client *client = cls; | ||
599 | struct CadetPeer *p = value; | ||
600 | struct GNUNET_CADET_LocalInfoPeer msg; | ||
601 | |||
602 | msg.header.size = htons (sizeof (msg)); | ||
603 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
604 | msg.destination = *peer; | ||
605 | msg.paths = htons (GMP_count_paths (p)); | ||
606 | msg.tunnel = htons (NULL != GMP_get_tunnel (p)); | ||
607 | |||
608 | LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about peer %s\n", | ||
609 | GNUNET_i2s (peer)); | ||
610 | |||
611 | GNUNET_SERVER_notification_context_unicast (nc, client, | ||
612 | &msg.header, GNUNET_NO); | ||
613 | return GNUNET_YES; | ||
614 | } | ||
615 | |||
616 | |||
617 | /** | ||
618 | * Handler for client's INFO PEERS request. | ||
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_get_peers (void *cls, struct GNUNET_SERVER_Client *client, | ||
626 | const struct GNUNET_MessageHeader *message) | ||
627 | { | ||
628 | struct CadetClient *c; | ||
629 | struct GNUNET_MessageHeader reply; | ||
630 | |||
631 | /* Sanity check for client registration */ | ||
632 | if (NULL == (c = GML_client_get (client))) | ||
633 | { | ||
634 | GNUNET_break (0); | ||
635 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
636 | return; | ||
637 | } | ||
638 | |||
639 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
640 | "Received get peers request from client %u (%p)\n", | ||
641 | c->id, client); | ||
642 | |||
643 | GMP_iterate_all (get_all_peers_iterator, client); | ||
644 | reply.size = htons (sizeof (reply)); | ||
645 | reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS); | ||
646 | GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO); | ||
647 | |||
648 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
649 | "Get peers request from client %u completed\n", c->id); | ||
650 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
651 | } | ||
652 | |||
653 | |||
654 | /** | ||
655 | * Iterator over all tunnels to send a monitoring client info about each tunnel. | ||
656 | * | ||
657 | * @param cls Closure (). | ||
658 | * @param peer Peer ID (tunnel remote peer). | ||
659 | * @param value Tunnel info. | ||
660 | * | ||
661 | * @return #GNUNET_YES, to keep iterating. | ||
662 | */ | ||
663 | static int | ||
664 | get_all_tunnels_iterator (void *cls, | ||
665 | const struct GNUNET_PeerIdentity * peer, | ||
666 | void *value) | ||
667 | { | ||
668 | struct GNUNET_SERVER_Client *client = cls; | ||
669 | struct CadetTunnel3 *t = value; | ||
670 | struct GNUNET_CADET_LocalInfoTunnel msg; | ||
671 | |||
672 | msg.header.size = htons (sizeof (msg)); | ||
673 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
674 | msg.destination = *peer; | ||
675 | msg.channels = htonl (GMT_count_channels (t)); | ||
676 | msg.connections = htonl (GMT_count_connections (t)); | ||
677 | msg.cstate = htons ((uint16_t) GMT_get_cstate (t)); | ||
678 | msg.estate = htons ((uint16_t) GMT_get_estate (t)); | ||
679 | |||
680 | LOG (GNUNET_ERROR_TYPE_DEBUG, "sending info about tunnel ->%s\n", | ||
681 | GNUNET_i2s (peer)); | ||
682 | |||
683 | GNUNET_SERVER_notification_context_unicast (nc, client, | ||
684 | &msg.header, GNUNET_NO); | ||
685 | return GNUNET_YES; | ||
686 | } | ||
687 | |||
688 | |||
689 | /** | ||
690 | * Handler for client's INFO TUNNELS request. | ||
691 | * | ||
692 | * @param cls Closure (unused). | ||
693 | * @param client Identification of the client. | ||
694 | * @param message The actual message. | ||
695 | */ | ||
696 | static void | ||
697 | handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client, | ||
698 | const struct GNUNET_MessageHeader *message) | ||
699 | { | ||
700 | struct CadetClient *c; | ||
701 | struct GNUNET_MessageHeader reply; | ||
702 | |||
703 | /* Sanity check for client registration */ | ||
704 | if (NULL == (c = GML_client_get (client))) | ||
705 | { | ||
706 | GNUNET_break (0); | ||
707 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
708 | return; | ||
709 | } | ||
710 | |||
711 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
712 | "Received get tunnels request from client %u (%p)\n", | ||
713 | c->id, client); | ||
714 | |||
715 | GMT_iterate_all (get_all_tunnels_iterator, client); | ||
716 | reply.size = htons (sizeof (reply)); | ||
717 | reply.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS); | ||
718 | GNUNET_SERVER_notification_context_unicast (nc, client, &reply, GNUNET_NO); | ||
719 | |||
720 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
721 | "Get tunnels request from client %u completed\n", c->id); | ||
722 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
723 | } | ||
724 | |||
725 | |||
726 | static void | ||
727 | iter_connection (void *cls, struct CadetConnection *c) | ||
728 | { | ||
729 | struct GNUNET_CADET_LocalInfoTunnel *msg = cls; | ||
730 | struct GNUNET_CADET_Hash *h = (struct GNUNET_CADET_Hash *) &msg[1]; | ||
731 | |||
732 | h[msg->connections] = *(GMC_get_id (c)); | ||
733 | msg->connections++; | ||
734 | } | ||
735 | |||
736 | static void | ||
737 | iter_channel (void *cls, struct CadetChannel *ch) | ||
738 | { | ||
739 | struct GNUNET_CADET_LocalInfoTunnel *msg = cls; | ||
740 | struct GNUNET_HashCode *h = (struct GNUNET_HashCode *) &msg[1]; | ||
741 | CADET_ChannelNumber *chn = (CADET_ChannelNumber *) &h[msg->connections]; | ||
742 | |||
743 | chn[msg->channels] = GMCH_get_id (ch); | ||
744 | msg->channels++; | ||
745 | } | ||
746 | |||
747 | |||
748 | /** | ||
749 | * Handler for client's SHOW_TUNNEL request. | ||
750 | * | ||
751 | * @param cls Closure (unused). | ||
752 | * @param client Identification of the client. | ||
753 | * @param message The actual message. | ||
754 | */ | ||
755 | void | ||
756 | handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client, | ||
757 | const struct GNUNET_MessageHeader *message) | ||
758 | { | ||
759 | const struct GNUNET_CADET_LocalInfo *msg; | ||
760 | struct GNUNET_CADET_LocalInfoTunnel *resp; | ||
761 | struct CadetClient *c; | ||
762 | struct CadetTunnel3 *t; | ||
763 | unsigned int ch_n; | ||
764 | unsigned int c_n; | ||
765 | size_t size; | ||
766 | |||
767 | /* Sanity check for client registration */ | ||
768 | if (NULL == (c = GML_client_get (client))) | ||
769 | { | ||
770 | GNUNET_break (0); | ||
771 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
772 | return; | ||
773 | } | ||
774 | |||
775 | msg = (struct GNUNET_CADET_LocalInfo *) message; | ||
776 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
777 | "Received tunnel info request from client %u for tunnel %s\n", | ||
778 | c->id, GNUNET_i2s_full(&msg->peer)); | ||
779 | |||
780 | t = GMP_get_tunnel (GMP_get (&msg->peer)); | ||
781 | if (NULL == t) | ||
782 | { | ||
783 | /* We don't know the tunnel */ | ||
784 | struct GNUNET_CADET_LocalInfoTunnel warn; | ||
785 | |||
786 | LOG (GNUNET_ERROR_TYPE_INFO, "Tunnel %s unknown %u\n", | ||
787 | GNUNET_i2s_full(&msg->peer), sizeof (warn)); | ||
788 | warn.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
789 | warn.header.size = htons (sizeof (warn)); | ||
790 | warn.destination = msg->peer; | ||
791 | warn.channels = htonl (0); | ||
792 | warn.connections = htonl (0); | ||
793 | warn.cstate = htons (0); | ||
794 | warn.estate = htons (0); | ||
795 | |||
796 | GNUNET_SERVER_notification_context_unicast (nc, client, | ||
797 | &warn.header, | ||
798 | GNUNET_NO); | ||
799 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
800 | return; | ||
801 | } | ||
802 | |||
803 | /* Initialize context */ | ||
804 | ch_n = GMT_count_channels (t); | ||
805 | c_n = GMT_count_connections (t); | ||
806 | |||
807 | size = sizeof (struct GNUNET_CADET_LocalInfoTunnel); | ||
808 | size += c_n * sizeof (struct GNUNET_CADET_Hash); | ||
809 | size += ch_n * sizeof (CADET_ChannelNumber); | ||
810 | |||
811 | resp = GNUNET_malloc (size); | ||
812 | resp->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL); | ||
813 | resp->header.size = htons (size); | ||
814 | GMT_iterate_connections (t, &iter_connection, resp); | ||
815 | GMT_iterate_channels (t, &iter_channel, resp); | ||
816 | /* Do not interleave with iterators, iter_channel needs conn in HBO */ | ||
817 | resp->destination = msg->peer; | ||
818 | resp->connections = htonl (resp->connections); | ||
819 | resp->channels = htonl (resp->channels); | ||
820 | resp->cstate = htons (GMT_get_cstate (t)); | ||
821 | resp->estate = htons (GMT_get_estate (t)); | ||
822 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, | ||
823 | &resp->header, GNUNET_NO); | ||
824 | GNUNET_free (resp); | ||
825 | |||
826 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
827 | "Show tunnel request from client %u completed. %u conn, %u ch\n", | ||
828 | c->id, c_n, ch_n); | ||
829 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
830 | } | ||
831 | |||
832 | |||
833 | /** | ||
834 | * Functions to handle messages from clients | ||
835 | */ | ||
836 | static struct GNUNET_SERVER_MessageHandler client_handlers[] = { | ||
837 | {&handle_new_client, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_CONNECT, 0}, | ||
838 | {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE, | ||
839 | sizeof (struct GNUNET_CADET_ChannelMessage)}, | ||
840 | {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY, | ||
841 | sizeof (struct GNUNET_CADET_ChannelMessage)}, | ||
842 | {&handle_data, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA, 0}, | ||
843 | {&handle_ack, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK, | ||
844 | sizeof (struct GNUNET_CADET_LocalAck)}, | ||
845 | {&handle_get_peers, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_PEERS, | ||
846 | sizeof (struct GNUNET_MessageHeader)}, | ||
847 | {&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNELS, | ||
848 | sizeof (struct GNUNET_MessageHeader)}, | ||
849 | {&handle_show_tunnel, NULL, GNUNET_MESSAGE_TYPE_CADET_LOCAL_INFO_TUNNEL, | ||
850 | sizeof (struct GNUNET_CADET_LocalInfo)}, | ||
851 | {NULL, NULL, 0, 0} | ||
852 | }; | ||
853 | |||
854 | |||
855 | |||
856 | /******************************************************************************/ | ||
857 | /******************************** API ***********************************/ | ||
858 | /******************************************************************************/ | ||
859 | |||
860 | /** | ||
861 | * Initialize server subsystem. | ||
862 | * | ||
863 | * @param handle Server handle. | ||
864 | */ | ||
865 | void | ||
866 | GML_init (struct GNUNET_SERVER_Handle *handle) | ||
867 | { | ||
868 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
869 | server_handle = handle; | ||
870 | GNUNET_SERVER_suspend (server_handle); | ||
871 | ports = GNUNET_CONTAINER_multihashmap32_create (32); | ||
872 | } | ||
873 | |||
874 | |||
875 | /** | ||
876 | * Install server (service) handlers and start listening to clients. | ||
877 | */ | ||
878 | void | ||
879 | GML_start (void) | ||
880 | { | ||
881 | GNUNET_SERVER_add_handlers (server_handle, client_handlers); | ||
882 | GNUNET_SERVER_connect_notify (server_handle, &handle_client_connect, NULL); | ||
883 | GNUNET_SERVER_disconnect_notify (server_handle, &handle_client_disconnect, | ||
884 | NULL); | ||
885 | nc = GNUNET_SERVER_notification_context_create (server_handle, 1); | ||
886 | |||
887 | clients_head = NULL; | ||
888 | clients_tail = NULL; | ||
889 | next_client_id = 0; | ||
890 | GNUNET_SERVER_resume (server_handle); | ||
891 | } | ||
892 | |||
893 | |||
894 | /** | ||
895 | * Shutdown server. | ||
896 | */ | ||
897 | void | ||
898 | GML_shutdown (void) | ||
899 | { | ||
900 | if (nc != NULL) | ||
901 | { | ||
902 | GNUNET_SERVER_notification_context_destroy (nc); | ||
903 | nc = NULL; | ||
904 | } | ||
905 | } | ||
906 | |||
907 | |||
908 | /** | ||
909 | * Get a channel from a client. | ||
910 | * | ||
911 | * @param c Client to check. | ||
912 | * @param chid Channel ID, must be local (> 0x800...). | ||
913 | * | ||
914 | * @return non-NULL if channel exists in the clients lists | ||
915 | */ | ||
916 | struct CadetChannel * | ||
917 | GML_channel_get (struct CadetClient *c, CADET_ChannelNumber chid) | ||
918 | { | ||
919 | struct GNUNET_CONTAINER_MultiHashMap32 *map; | ||
920 | |||
921 | if (0 == (chid & GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)) | ||
922 | { | ||
923 | GNUNET_break_op (0); | ||
924 | LOG (GNUNET_ERROR_TYPE_DEBUG, "CHID %X not a local chid\n", chid); | ||
925 | return NULL; | ||
926 | } | ||
927 | |||
928 | if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV) | ||
929 | map = c->incoming_channels; | ||
930 | else if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
931 | map = c->own_channels; | ||
932 | else | ||
933 | { | ||
934 | GNUNET_break (0); | ||
935 | map = NULL; | ||
936 | } | ||
937 | if (NULL == map) | ||
938 | { | ||
939 | GNUNET_break (0); | ||
940 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
941 | "Client %s does no t have a valid map for CHID %X\n", | ||
942 | GML_2s (c), chid); | ||
943 | return NULL; | ||
944 | } | ||
945 | return GNUNET_CONTAINER_multihashmap32_get (map, chid); | ||
946 | } | ||
947 | |||
948 | |||
949 | /** | ||
950 | * Add a channel to a client | ||
951 | * | ||
952 | * @param client Client. | ||
953 | * @param chid Channel ID. | ||
954 | * @param ch Channel. | ||
955 | */ | ||
956 | void | ||
957 | GML_channel_add (struct CadetClient *client, | ||
958 | uint32_t chid, | ||
959 | struct CadetChannel *ch) | ||
960 | { | ||
961 | if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_SERV) | ||
962 | GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels, chid, ch, | ||
963 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
964 | else if (chid >= GNUNET_CADET_LOCAL_CHANNEL_ID_CLI) | ||
965 | GNUNET_CONTAINER_multihashmap32_put (client->own_channels, chid, ch, | ||
966 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
967 | else | ||
968 | GNUNET_break (0); | ||
969 | } | ||
970 | |||
971 | |||
972 | /** | ||
973 | * Remove a channel from a client. | ||
974 | * | ||
975 | * @param client Client. | ||
976 | * @param chid Channel ID. | ||
977 | * @param ch Channel. | ||
978 | */ | ||
979 | void | ||
980 | GML_channel_remove (struct CadetClient *client, | ||
981 | uint32_t chid, | ||
982 | struct CadetChannel *ch) | ||
983 | { | ||
984 | if (GNUNET_CADET_LOCAL_CHANNEL_ID_SERV <= chid) | ||
985 | GNUNET_break (GNUNET_YES == | ||
986 | GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels, | ||
987 | chid, ch)); | ||
988 | else if (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI <= chid) | ||
989 | GNUNET_break (GNUNET_YES == | ||
990 | GNUNET_CONTAINER_multihashmap32_remove (client->own_channels, | ||
991 | chid, ch)); | ||
992 | else | ||
993 | GNUNET_break (0); | ||
994 | } | ||
995 | |||
996 | |||
997 | /** | ||
998 | * Get the tunnel's next free local channel ID. | ||
999 | * | ||
1000 | * @param c Client. | ||
1001 | * | ||
1002 | * @return LID of a channel free to use. | ||
1003 | */ | ||
1004 | CADET_ChannelNumber | ||
1005 | GML_get_next_chid (struct CadetClient *c) | ||
1006 | { | ||
1007 | CADET_ChannelNumber chid; | ||
1008 | |||
1009 | while (NULL != GML_channel_get (c, c->next_chid)) | ||
1010 | { | ||
1011 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", c->next_chid); | ||
1012 | c->next_chid = (c->next_chid + 1) | GNUNET_CADET_LOCAL_CHANNEL_ID_SERV; | ||
1013 | } | ||
1014 | chid = c->next_chid; | ||
1015 | c->next_chid = (c->next_chid + 1) | GNUNET_CADET_LOCAL_CHANNEL_ID_SERV; | ||
1016 | |||
1017 | return chid; | ||
1018 | } | ||
1019 | |||
1020 | |||
1021 | /** | ||
1022 | * Check if client has registered with the service and has not disconnected | ||
1023 | * | ||
1024 | * @param client the client to check | ||
1025 | * | ||
1026 | * @return non-NULL if client exists in the global DLL | ||
1027 | */ | ||
1028 | struct CadetClient * | ||
1029 | GML_client_get (struct GNUNET_SERVER_Client *client) | ||
1030 | { | ||
1031 | return GNUNET_SERVER_client_get_user_context (client, struct CadetClient); | ||
1032 | } | ||
1033 | |||
1034 | /** | ||
1035 | * Find a client that has opened a port | ||
1036 | * | ||
1037 | * @param port Port to check. | ||
1038 | * | ||
1039 | * @return non-NULL if a client has the port. | ||
1040 | */ | ||
1041 | struct CadetClient * | ||
1042 | GML_client_get_by_port (uint32_t port) | ||
1043 | { | ||
1044 | return GNUNET_CONTAINER_multihashmap32_get (ports, port); | ||
1045 | } | ||
1046 | |||
1047 | |||
1048 | /** | ||
1049 | * Deletes a channel from a client (either owner or destination). | ||
1050 | * | ||
1051 | * @param c Client whose tunnel to delete. | ||
1052 | * @param ch Channel which should be deleted. | ||
1053 | * @param id Channel ID. | ||
1054 | */ | ||
1055 | void | ||
1056 | GML_client_delete_channel (struct CadetClient *c, | ||
1057 | struct CadetChannel *ch, | ||
1058 | CADET_ChannelNumber id) | ||
1059 | { | ||
1060 | int res; | ||
1061 | |||
1062 | if (GNUNET_CADET_LOCAL_CHANNEL_ID_SERV <= id) | ||
1063 | { | ||
1064 | res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels, | ||
1065 | id, ch); | ||
1066 | if (GNUNET_YES != res) | ||
1067 | LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n"); | ||
1068 | } | ||
1069 | else if (GNUNET_CADET_LOCAL_CHANNEL_ID_CLI <= id) | ||
1070 | { | ||
1071 | res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels, | ||
1072 | id, ch); | ||
1073 | if (GNUNET_YES != res) | ||
1074 | LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n"); | ||
1075 | } | ||
1076 | else | ||
1077 | { | ||
1078 | GNUNET_break (0); | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1082 | /** | ||
1083 | * Build a local ACK message and send it to a local client, if needed. | ||
1084 | * | ||
1085 | * If the client was already allowed to send data, do nothing. | ||
1086 | * | ||
1087 | * @param c Client to whom send the ACK. | ||
1088 | * @param id Channel ID to use | ||
1089 | */ | ||
1090 | void | ||
1091 | GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id) | ||
1092 | { | ||
1093 | struct GNUNET_CADET_LocalAck msg; | ||
1094 | |||
1095 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1096 | "send local %s ack on %X towards %p\n", | ||
1097 | id < GNUNET_CADET_LOCAL_CHANNEL_ID_SERV ? "FWD" : "BCK", id, c); | ||
1098 | |||
1099 | msg.header.size = htons (sizeof (msg)); | ||
1100 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_ACK); | ||
1101 | msg.channel_id = htonl (id); | ||
1102 | GNUNET_SERVER_notification_context_unicast (nc, | ||
1103 | c->handle, | ||
1104 | &msg.header, | ||
1105 | GNUNET_NO); | ||
1106 | |||
1107 | } | ||
1108 | |||
1109 | |||
1110 | |||
1111 | /** | ||
1112 | * Notify the client that a new incoming channel was created. | ||
1113 | * | ||
1114 | * @param c Client to notify. | ||
1115 | * @param id Channel ID. | ||
1116 | * @param port Channel's destination port. | ||
1117 | * @param opt Options (bit array). | ||
1118 | * @param peer Origin peer. | ||
1119 | */ | ||
1120 | void | ||
1121 | GML_send_channel_create (struct CadetClient *c, | ||
1122 | uint32_t id, uint32_t port, uint32_t opt, | ||
1123 | const struct GNUNET_PeerIdentity *peer) | ||
1124 | { | ||
1125 | struct GNUNET_CADET_ChannelMessage msg; | ||
1126 | |||
1127 | msg.header.size = htons (sizeof (msg)); | ||
1128 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE); | ||
1129 | msg.channel_id = htonl (id); | ||
1130 | msg.port = htonl (port); | ||
1131 | msg.opt = htonl (opt); | ||
1132 | msg.peer = *peer; | ||
1133 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, | ||
1134 | &msg.header, GNUNET_NO); | ||
1135 | } | ||
1136 | |||
1137 | |||
1138 | /** | ||
1139 | * Build a local channel NACK message and send it to a local client. | ||
1140 | * | ||
1141 | * @param c Client to whom send the NACK. | ||
1142 | * @param id Channel ID to use | ||
1143 | */ | ||
1144 | void | ||
1145 | GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id) | ||
1146 | { | ||
1147 | struct GNUNET_CADET_LocalAck msg; | ||
1148 | |||
1149 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1150 | "send local nack on %X towards %p\n", | ||
1151 | id, c); | ||
1152 | |||
1153 | msg.header.size = htons (sizeof (msg)); | ||
1154 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK); | ||
1155 | msg.channel_id = htonl (id); | ||
1156 | GNUNET_SERVER_notification_context_unicast (nc, | ||
1157 | c->handle, | ||
1158 | &msg.header, | ||
1159 | GNUNET_NO); | ||
1160 | |||
1161 | } | ||
1162 | |||
1163 | /** | ||
1164 | * Notify a client that a channel is no longer valid. | ||
1165 | * | ||
1166 | * @param c Client. | ||
1167 | * @param id ID of the channel that is destroyed. | ||
1168 | */ | ||
1169 | void | ||
1170 | GML_send_channel_destroy (struct CadetClient *c, uint32_t id) | ||
1171 | { | ||
1172 | struct GNUNET_CADET_ChannelMessage msg; | ||
1173 | |||
1174 | if (NULL == c) | ||
1175 | { | ||
1176 | GNUNET_break (0); | ||
1177 | return; | ||
1178 | } | ||
1179 | if (GNUNET_YES == c->shutting_down) | ||
1180 | return; | ||
1181 | msg.header.size = htons (sizeof (msg)); | ||
1182 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); | ||
1183 | msg.channel_id = htonl (id); | ||
1184 | msg.port = htonl (0); | ||
1185 | memset (&msg.peer, 0, sizeof (msg.peer)); | ||
1186 | msg.opt = htonl (0); | ||
1187 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, | ||
1188 | &msg.header, GNUNET_NO); | ||
1189 | } | ||
1190 | |||
1191 | |||
1192 | /** | ||
1193 | * Modify the cadet message ID from global to local and send to client. | ||
1194 | * | ||
1195 | * @param c Client to send to. | ||
1196 | * @param msg Message to modify and send. | ||
1197 | * @param id Channel ID to use (c can be both owner and client). | ||
1198 | */ | ||
1199 | void | ||
1200 | GML_send_data (struct CadetClient *c, | ||
1201 | const struct GNUNET_CADET_Data *msg, | ||
1202 | CADET_ChannelNumber id) | ||
1203 | { | ||
1204 | struct GNUNET_CADET_LocalData *copy; | ||
1205 | uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_CADET_Data); | ||
1206 | char cbuf[size + sizeof (struct GNUNET_CADET_LocalData)]; | ||
1207 | |||
1208 | if (size < sizeof (struct GNUNET_MessageHeader)) | ||
1209 | { | ||
1210 | GNUNET_break_op (0); | ||
1211 | return; | ||
1212 | } | ||
1213 | if (NULL == c) | ||
1214 | { | ||
1215 | GNUNET_break (0); | ||
1216 | return; | ||
1217 | } | ||
1218 | copy = (struct GNUNET_CADET_LocalData *) cbuf; | ||
1219 | memcpy (©[1], &msg[1], size); | ||
1220 | copy->header.size = htons (sizeof (struct GNUNET_CADET_LocalData) + size); | ||
1221 | copy->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | ||
1222 | copy->id = htonl (id); | ||
1223 | GNUNET_SERVER_notification_context_unicast (nc, c->handle, | ||
1224 | ©->header, GNUNET_NO); | ||
1225 | } | ||
1226 | |||
1227 | |||
1228 | /** | ||
1229 | * Get the static string to represent a client. | ||
1230 | * | ||
1231 | * @param c Client. | ||
1232 | * | ||
1233 | * @return Static string for the client. | ||
1234 | */ | ||
1235 | const char * | ||
1236 | GML_2s (const struct CadetClient *c) | ||
1237 | { | ||
1238 | static char buf[32]; | ||
1239 | |||
1240 | sprintf (buf, "%u", c->id); | ||
1241 | return buf; | ||
1242 | } | ||
diff --git a/src/cadet/gnunet-service-cadet_local.h b/src/cadet/gnunet-service-cadet_local.h new file mode 100644 index 000000000..b78b3c5da --- /dev/null +++ b/src/cadet/gnunet-service-cadet_local.h | |||
@@ -0,0 +1,226 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, 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 chid 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, uint32_t chid); | ||
84 | |||
85 | /** | ||
86 | * Add a channel to a client | ||
87 | * | ||
88 | * @param client Client. | ||
89 | * @param chid Channel ID. | ||
90 | * @param ch Channel. | ||
91 | */ | ||
92 | void | ||
93 | GML_channel_add (struct CadetClient *client, | ||
94 | uint32_t chid, | ||
95 | struct CadetChannel *ch); | ||
96 | |||
97 | /** | ||
98 | * Remove a channel from a client | ||
99 | * | ||
100 | * @param client Client. | ||
101 | * @param chid Channel ID. | ||
102 | * @param ch Channel. | ||
103 | */ | ||
104 | void | ||
105 | GML_channel_remove (struct CadetClient *client, | ||
106 | uint32_t chid, | ||
107 | struct CadetChannel *ch); | ||
108 | |||
109 | /** | ||
110 | * Get the tunnel's next free local channel ID. | ||
111 | * | ||
112 | * @param c Client. | ||
113 | * | ||
114 | * @return LID of a channel free to use. | ||
115 | */ | ||
116 | CADET_ChannelNumber | ||
117 | GML_get_next_chid (struct CadetClient *c); | ||
118 | |||
119 | /** | ||
120 | * Check if client has registered with the service and has not disconnected | ||
121 | * | ||
122 | * @param client the client to check | ||
123 | * | ||
124 | * @return non-NULL if client exists in the global DLL | ||
125 | */ | ||
126 | struct CadetClient * | ||
127 | GML_client_get (struct GNUNET_SERVER_Client *client); | ||
128 | |||
129 | /** | ||
130 | * Find a client that has opened a port | ||
131 | * | ||
132 | * @param port Port to check. | ||
133 | * | ||
134 | * @return non-NULL if a client has the port. | ||
135 | */ | ||
136 | struct CadetClient * | ||
137 | GML_client_get_by_port (uint32_t port); | ||
138 | |||
139 | /** | ||
140 | * Deletes a tunnel from a client (either owner or destination). | ||
141 | * | ||
142 | * @param c Client whose tunnel to delete. | ||
143 | * @param ch Channel which should be deleted. | ||
144 | * @param id Channel ID. | ||
145 | */ | ||
146 | void | ||
147 | GML_client_delete_channel (struct CadetClient *c, | ||
148 | struct CadetChannel *ch, | ||
149 | CADET_ChannelNumber id); | ||
150 | |||
151 | /** | ||
152 | * Build a local ACK message and send it to a local client, if needed. | ||
153 | * | ||
154 | * If the client was already allowed to send data, do nothing. | ||
155 | * | ||
156 | * @param c Client to whom send the ACK. | ||
157 | * @param id Channel ID to use | ||
158 | */ | ||
159 | void | ||
160 | GML_send_ack (struct CadetClient *c, CADET_ChannelNumber id); | ||
161 | |||
162 | /** | ||
163 | * Notify the appropriate client that a new incoming channel was created. | ||
164 | * | ||
165 | * @param c Client to notify. | ||
166 | * @param id Channel ID. | ||
167 | * @param port Channel's destination port. | ||
168 | * @param opt Options (bit array). | ||
169 | * @param peer Origin peer. | ||
170 | */ | ||
171 | void | ||
172 | GML_send_channel_create (struct CadetClient *c, | ||
173 | uint32_t id, uint32_t port, uint32_t opt, | ||
174 | const struct GNUNET_PeerIdentity *peer); | ||
175 | |||
176 | /** | ||
177 | * Build a local channel NACK message and send it to a local client. | ||
178 | * | ||
179 | * @param c Client to whom send the NACK. | ||
180 | * @param id Channel ID to use | ||
181 | */ | ||
182 | void | ||
183 | GML_send_channel_nack (struct CadetClient *c, CADET_ChannelNumber id); | ||
184 | |||
185 | /** | ||
186 | * Notify a client that a channel is no longer valid. | ||
187 | * | ||
188 | * @param c Client. | ||
189 | * @param id ID of the channel that is destroyed. | ||
190 | */ | ||
191 | void | ||
192 | GML_send_channel_destroy (struct CadetClient *c, uint32_t id); | ||
193 | |||
194 | /** | ||
195 | * Modify the cadet message ID from global to local and send to client. | ||
196 | * | ||
197 | * @param c Client to send to. | ||
198 | * @param msg Message to modify and send. | ||
199 | * @param id Channel ID to use (c can be both owner and client). | ||
200 | */ | ||
201 | void | ||
202 | GML_send_data (struct CadetClient *c, | ||
203 | const struct GNUNET_CADET_Data *msg, | ||
204 | CADET_ChannelNumber id); | ||
205 | |||
206 | /** | ||
207 | * Get the static string to represent a client. | ||
208 | * | ||
209 | * @param c Client. | ||
210 | * | ||
211 | * @return Static string for the client. | ||
212 | */ | ||
213 | const char * | ||
214 | GML_2s (const struct CadetClient *c); | ||
215 | |||
216 | |||
217 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
218 | { | ||
219 | #endif | ||
220 | #ifdef __cplusplus | ||
221 | } | ||
222 | #endif | ||
223 | |||
224 | /* ifndef GNUNET_CADET_SERVICE_LOCAL_H */ | ||
225 | #endif | ||
226 | /* end of gnunet-cadet-service_LOCAL.h */ | ||
diff --git a/src/cadet/gnunet-service-cadet_peer.c b/src/cadet/gnunet-service-cadet_peer.c new file mode 100644 index 000000000..287d42efe --- /dev/null +++ b/src/cadet/gnunet-service-cadet_peer.c | |||
@@ -0,0 +1,2219 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | |||
22 | #include "platform.h" | ||
23 | #include "gnunet_util_lib.h" | ||
24 | |||
25 | #include "gnunet_transport_service.h" | ||
26 | #include "gnunet_core_service.h" | ||
27 | #include "gnunet_statistics_service.h" | ||
28 | |||
29 | #include "cadet_protocol.h" | ||
30 | |||
31 | #include "gnunet-service-cadet_peer.h" | ||
32 | #include "gnunet-service-cadet_dht.h" | ||
33 | #include "gnunet-service-cadet_connection.h" | ||
34 | #include "gnunet-service-cadet_tunnel.h" | ||
35 | #include "cadet_path.h" | ||
36 | |||
37 | #define LOG(level, ...) GNUNET_log_from (level,"cadet-p2p",__VA_ARGS__) | ||
38 | |||
39 | /******************************************************************************/ | ||
40 | /******************************** STRUCTS **********************************/ | ||
41 | /******************************************************************************/ | ||
42 | |||
43 | /** | ||
44 | * Struct containing info about a queued transmission to this peer | ||
45 | */ | ||
46 | struct CadetPeerQueue | ||
47 | { | ||
48 | /** | ||
49 | * DLL next | ||
50 | */ | ||
51 | struct CadetPeerQueue *next; | ||
52 | |||
53 | /** | ||
54 | * DLL previous | ||
55 | */ | ||
56 | struct CadetPeerQueue *prev; | ||
57 | |||
58 | /** | ||
59 | * Peer this transmission is directed to. | ||
60 | */ | ||
61 | struct CadetPeer *peer; | ||
62 | |||
63 | /** | ||
64 | * Connection this message belongs to. | ||
65 | */ | ||
66 | struct CadetConnection *c; | ||
67 | |||
68 | /** | ||
69 | * Is FWD in c? | ||
70 | */ | ||
71 | int fwd; | ||
72 | |||
73 | /** | ||
74 | * Pointer to info stucture used as cls. | ||
75 | */ | ||
76 | void *cls; | ||
77 | |||
78 | /** | ||
79 | * Type of message | ||
80 | */ | ||
81 | uint16_t type; | ||
82 | |||
83 | /** | ||
84 | * Type of message | ||
85 | */ | ||
86 | uint16_t payload_type; | ||
87 | |||
88 | /** | ||
89 | * Type of message | ||
90 | */ | ||
91 | uint32_t payload_id; | ||
92 | |||
93 | /** | ||
94 | * Size of the message | ||
95 | */ | ||
96 | size_t size; | ||
97 | |||
98 | /** | ||
99 | * Set when this message starts waiting for CORE. | ||
100 | */ | ||
101 | struct GNUNET_TIME_Absolute start_waiting; | ||
102 | |||
103 | /** | ||
104 | * Function to call on sending. | ||
105 | */ | ||
106 | GMP_sent callback; | ||
107 | |||
108 | /** | ||
109 | * Closure for callback. | ||
110 | */ | ||
111 | void *callback_cls; | ||
112 | }; | ||
113 | |||
114 | /** | ||
115 | * Struct containing all information regarding a given peer | ||
116 | */ | ||
117 | struct CadetPeer | ||
118 | { | ||
119 | /** | ||
120 | * ID of the peer | ||
121 | */ | ||
122 | GNUNET_PEER_Id id; | ||
123 | |||
124 | /** | ||
125 | * Last time we heard from this peer | ||
126 | */ | ||
127 | struct GNUNET_TIME_Absolute last_contact; | ||
128 | |||
129 | /** | ||
130 | * Paths to reach the peer, ordered by ascending hop count | ||
131 | */ | ||
132 | struct CadetPeerPath *path_head; | ||
133 | |||
134 | /** | ||
135 | * Paths to reach the peer, ordered by ascending hop count | ||
136 | */ | ||
137 | struct CadetPeerPath *path_tail; | ||
138 | |||
139 | /** | ||
140 | * Handle to stop the DHT search for paths to this peer | ||
141 | */ | ||
142 | struct GMD_search_handle *search_h; | ||
143 | |||
144 | /** | ||
145 | * Tunnel to this peer, if any. | ||
146 | */ | ||
147 | struct CadetTunnel3 *tunnel; | ||
148 | |||
149 | /** | ||
150 | * Connections that go through this peer, indexed by tid; | ||
151 | */ | ||
152 | struct GNUNET_CONTAINER_MultiHashMap *connections; | ||
153 | |||
154 | /** | ||
155 | * Handle for queued transmissions | ||
156 | */ | ||
157 | struct GNUNET_CORE_TransmitHandle *core_transmit; | ||
158 | |||
159 | /** | ||
160 | * Transmission queue to core DLL head | ||
161 | */ | ||
162 | struct CadetPeerQueue *queue_head; | ||
163 | |||
164 | /** | ||
165 | * Transmission queue to core DLL tail | ||
166 | */ | ||
167 | struct CadetPeerQueue *queue_tail; | ||
168 | |||
169 | /** | ||
170 | * How many messages are in the queue to this peer. | ||
171 | */ | ||
172 | unsigned int queue_n; | ||
173 | |||
174 | /** | ||
175 | * Hello message. | ||
176 | */ | ||
177 | struct GNUNET_HELLO_Message* hello; | ||
178 | }; | ||
179 | |||
180 | |||
181 | /******************************************************************************/ | ||
182 | /******************************* GLOBALS ***********************************/ | ||
183 | /******************************************************************************/ | ||
184 | |||
185 | /** | ||
186 | * Global handle to the statistics service. | ||
187 | */ | ||
188 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
189 | |||
190 | /** | ||
191 | * Local peer own ID (full value). | ||
192 | */ | ||
193 | extern struct GNUNET_PeerIdentity my_full_id; | ||
194 | |||
195 | /** | ||
196 | * Local peer own ID (short) | ||
197 | */ | ||
198 | extern GNUNET_PEER_Id myid; | ||
199 | |||
200 | /** | ||
201 | * Peers known, indexed by PeerIdentity (CadetPeer). | ||
202 | */ | ||
203 | static struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
204 | |||
205 | /** | ||
206 | * How many peers do we want to remember? | ||
207 | */ | ||
208 | static unsigned long long max_peers; | ||
209 | |||
210 | /** | ||
211 | * Percentage of messages that will be dropped (for test purposes only). | ||
212 | */ | ||
213 | static unsigned long long drop_percent; | ||
214 | |||
215 | /** | ||
216 | * Handle to communicate with core. | ||
217 | */ | ||
218 | static struct GNUNET_CORE_Handle *core_handle; | ||
219 | |||
220 | /** | ||
221 | * Handle to try to start new connections. | ||
222 | */ | ||
223 | static struct GNUNET_TRANSPORT_Handle *transport_handle; | ||
224 | |||
225 | |||
226 | /******************************************************************************/ | ||
227 | /***************************** DEBUG *********************************/ | ||
228 | /******************************************************************************/ | ||
229 | |||
230 | static void | ||
231 | queue_debug (struct CadetPeer *peer) | ||
232 | { | ||
233 | struct CadetPeerQueue *q; | ||
234 | |||
235 | LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ Messages queued towards %s\n", GMP_2s (peer)); | ||
236 | LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ core tmt rdy: %p\n", peer->core_transmit); | ||
237 | |||
238 | for (q = peer->queue_head; NULL != q; q = q->next) | ||
239 | { | ||
240 | LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ - %s %s on %s\n", | ||
241 | GM_m2s (q->type), GM_f2s (q->fwd), GMC_2s (q->c)); | ||
242 | } | ||
243 | |||
244 | LOG (GNUNET_ERROR_TYPE_DEBUG, "QQQ End queued towards %s\n", GMP_2s (peer)); | ||
245 | } | ||
246 | |||
247 | |||
248 | /******************************************************************************/ | ||
249 | /***************************** CORE HELPERS *********************************/ | ||
250 | /******************************************************************************/ | ||
251 | |||
252 | |||
253 | /** | ||
254 | * Iterator to notify all connections of a broken link. Mark connections | ||
255 | * to destroy after all traffic has been sent. | ||
256 | * | ||
257 | * @param cls Closure (peer disconnected). | ||
258 | * @param key Current key code (peer id). | ||
259 | * @param value Value in the hash map (connection). | ||
260 | * | ||
261 | * @return #GNUNET_YES to continue to iterate. | ||
262 | */ | ||
263 | static int | ||
264 | notify_broken (void *cls, | ||
265 | const struct GNUNET_HashCode *key, | ||
266 | void *value) | ||
267 | { | ||
268 | struct CadetPeer *peer = cls; | ||
269 | struct CadetConnection *c = value; | ||
270 | |||
271 | LOG (GNUNET_ERROR_TYPE_DEBUG, " notifying %s due to %s\n", | ||
272 | GMC_2s (c), GMP_2s (peer)); | ||
273 | GMC_notify_broken (c, peer); | ||
274 | |||
275 | return GNUNET_YES; | ||
276 | } | ||
277 | |||
278 | |||
279 | /** | ||
280 | * Remove the direct path to the peer. | ||
281 | * | ||
282 | * @param peer Peer to remove the direct path from. | ||
283 | * | ||
284 | */ | ||
285 | static struct CadetPeerPath * | ||
286 | pop_direct_path (struct CadetPeer *peer) | ||
287 | { | ||
288 | struct CadetPeerPath *iter; | ||
289 | |||
290 | for (iter = peer->path_head; NULL != iter; iter = iter->next) | ||
291 | { | ||
292 | if (2 <= iter->length) | ||
293 | { | ||
294 | GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, iter); | ||
295 | return iter; | ||
296 | } | ||
297 | } | ||
298 | return NULL; | ||
299 | } | ||
300 | |||
301 | |||
302 | /******************************************************************************/ | ||
303 | /***************************** CORE CALLBACKS *********************************/ | ||
304 | /******************************************************************************/ | ||
305 | |||
306 | /** | ||
307 | * Method called whenever a given peer connects. | ||
308 | * | ||
309 | * @param cls closure | ||
310 | * @param peer peer identity this notification is about | ||
311 | */ | ||
312 | static void | ||
313 | core_connect (void *cls, const struct GNUNET_PeerIdentity *peer) | ||
314 | { | ||
315 | struct CadetPeer *mp; | ||
316 | struct CadetPeerPath *path; | ||
317 | char own_id[16]; | ||
318 | |||
319 | strncpy (own_id, GNUNET_i2s (&my_full_id), 15); | ||
320 | mp = GMP_get (peer); | ||
321 | if (myid == mp->id) | ||
322 | { | ||
323 | LOG (GNUNET_ERROR_TYPE_INFO, "CONNECTED %s (self)\n", own_id); | ||
324 | path = path_new (1); | ||
325 | } | ||
326 | else | ||
327 | { | ||
328 | LOG (GNUNET_ERROR_TYPE_INFO, "CONNECTED %s <= %s\n", | ||
329 | own_id, GNUNET_i2s (peer)); | ||
330 | path = path_new (2); | ||
331 | path->peers[1] = mp->id; | ||
332 | GNUNET_PEER_change_rc (mp->id, 1); | ||
333 | GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO); | ||
334 | } | ||
335 | path->peers[0] = myid; | ||
336 | GNUNET_PEER_change_rc (myid, 1); | ||
337 | GMP_add_path (mp, path, GNUNET_YES); | ||
338 | |||
339 | mp->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES); | ||
340 | |||
341 | if (NULL != GMP_get_tunnel (mp) && | ||
342 | 0 > GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, peer)) | ||
343 | { | ||
344 | GMP_connect (mp); | ||
345 | } | ||
346 | |||
347 | return; | ||
348 | } | ||
349 | |||
350 | |||
351 | /** | ||
352 | * Method called whenever a peer disconnects. | ||
353 | * | ||
354 | * @param cls closure | ||
355 | * @param peer peer identity this notification is about | ||
356 | */ | ||
357 | static void | ||
358 | core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer) | ||
359 | { | ||
360 | struct CadetPeer *p; | ||
361 | struct CadetPeerPath *direct_path; | ||
362 | char own_id[16]; | ||
363 | |||
364 | strncpy (own_id, GNUNET_i2s (&my_full_id), 15); | ||
365 | p = GNUNET_CONTAINER_multipeermap_get (peers, peer); | ||
366 | if (NULL == p) | ||
367 | { | ||
368 | GNUNET_break (0); | ||
369 | return; | ||
370 | } | ||
371 | if (myid == p->id) | ||
372 | LOG (GNUNET_ERROR_TYPE_INFO, "DISCONNECTED %s (self)\n", own_id); | ||
373 | else | ||
374 | LOG (GNUNET_ERROR_TYPE_DEBUG, "DISCONNECTED %s <= %s\n", | ||
375 | own_id, GNUNET_i2s (peer)); | ||
376 | direct_path = pop_direct_path (p); | ||
377 | GNUNET_CONTAINER_multihashmap_iterate (p->connections, ¬ify_broken, p); | ||
378 | GNUNET_CONTAINER_multihashmap_destroy (p->connections); | ||
379 | p->connections = NULL; | ||
380 | if (NULL != p->core_transmit) | ||
381 | { | ||
382 | GNUNET_CORE_notify_transmit_ready_cancel (p->core_transmit); | ||
383 | p->core_transmit = NULL; | ||
384 | } | ||
385 | GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO); | ||
386 | |||
387 | path_destroy (direct_path); | ||
388 | return; | ||
389 | } | ||
390 | |||
391 | |||
392 | /** | ||
393 | * Functions to handle messages from core | ||
394 | */ | ||
395 | static struct GNUNET_CORE_MessageHandler core_handlers[] = { | ||
396 | {&GMC_handle_create, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE, 0}, | ||
397 | {&GMC_handle_confirm, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK, | ||
398 | sizeof (struct GNUNET_CADET_ConnectionACK)}, | ||
399 | {&GMC_handle_broken, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN, | ||
400 | sizeof (struct GNUNET_CADET_ConnectionBroken)}, | ||
401 | {&GMC_handle_destroy, GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY, | ||
402 | sizeof (struct GNUNET_CADET_ConnectionDestroy)}, | ||
403 | {&GMC_handle_ack, GNUNET_MESSAGE_TYPE_CADET_ACK, | ||
404 | sizeof (struct GNUNET_CADET_ACK)}, | ||
405 | {&GMC_handle_poll, GNUNET_MESSAGE_TYPE_CADET_POLL, | ||
406 | sizeof (struct GNUNET_CADET_Poll)}, | ||
407 | {&GMC_handle_encrypted, GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED, 0}, | ||
408 | {&GMC_handle_kx, GNUNET_MESSAGE_TYPE_CADET_KX, 0}, | ||
409 | {NULL, 0, 0} | ||
410 | }; | ||
411 | |||
412 | |||
413 | /** | ||
414 | * To be called on core init/fail. | ||
415 | * | ||
416 | * @param cls Closure (config) | ||
417 | * @param identity the public identity of this peer | ||
418 | */ | ||
419 | static void | ||
420 | core_init (void *cls, | ||
421 | const struct GNUNET_PeerIdentity *identity) | ||
422 | { | ||
423 | const struct GNUNET_CONFIGURATION_Handle *c = cls; | ||
424 | static int i = 0; | ||
425 | |||
426 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Core init\n"); | ||
427 | if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id))) | ||
428 | { | ||
429 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n")); | ||
430 | LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (identity)); | ||
431 | LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id)); | ||
432 | GNUNET_CORE_disconnect (core_handle); | ||
433 | core_handle = GNUNET_CORE_connect (c, /* Main configuration */ | ||
434 | NULL, /* Closure passed to CADET functions */ | ||
435 | &core_init, /* Call core_init once connected */ | ||
436 | &core_connect, /* Handle connects */ | ||
437 | &core_disconnect, /* remove peers on disconnects */ | ||
438 | NULL, /* Don't notify about all incoming messages */ | ||
439 | GNUNET_NO, /* For header only in notification */ | ||
440 | NULL, /* Don't notify about all outbound messages */ | ||
441 | GNUNET_NO, /* For header-only out notification */ | ||
442 | core_handlers); /* Register these handlers */ | ||
443 | if (10 < i++) | ||
444 | GNUNET_abort(); | ||
445 | } | ||
446 | GML_start (); | ||
447 | return; | ||
448 | } | ||
449 | |||
450 | |||
451 | /** | ||
452 | * Core callback to write a pre-constructed data packet to core buffer | ||
453 | * | ||
454 | * @param cls Closure (CadetTransmissionDescriptor with data in "data" member). | ||
455 | * @param size Number of bytes available in buf. | ||
456 | * @param buf Where the to write the message. | ||
457 | * | ||
458 | * @return number of bytes written to buf | ||
459 | */ | ||
460 | static size_t | ||
461 | send_core_data_raw (void *cls, size_t size, void *buf) | ||
462 | { | ||
463 | struct GNUNET_MessageHeader *msg = cls; | ||
464 | size_t total_size; | ||
465 | |||
466 | GNUNET_assert (NULL != msg); | ||
467 | total_size = ntohs (msg->size); | ||
468 | |||
469 | if (total_size > size) | ||
470 | { | ||
471 | GNUNET_break (0); | ||
472 | return 0; | ||
473 | } | ||
474 | memcpy (buf, msg, total_size); | ||
475 | GNUNET_free (cls); | ||
476 | return total_size; | ||
477 | } | ||
478 | |||
479 | |||
480 | /** | ||
481 | * Function to send a create connection message to a peer. | ||
482 | * | ||
483 | * @param c Connection to create. | ||
484 | * @param size number of bytes available in buf | ||
485 | * @param buf where the callee should write the message | ||
486 | * @return number of bytes written to buf | ||
487 | */ | ||
488 | static size_t | ||
489 | send_core_connection_create (struct CadetConnection *c, size_t size, void *buf) | ||
490 | { | ||
491 | struct GNUNET_CADET_ConnectionCreate *msg; | ||
492 | struct GNUNET_PeerIdentity *peer_ptr; | ||
493 | const struct CadetPeerPath *p = GMC_get_path (c); | ||
494 | size_t size_needed; | ||
495 | int i; | ||
496 | |||
497 | if (NULL == p) | ||
498 | return 0; | ||
499 | |||
500 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION CREATE...\n"); | ||
501 | size_needed = | ||
502 | sizeof (struct GNUNET_CADET_ConnectionCreate) + | ||
503 | p->length * sizeof (struct GNUNET_PeerIdentity); | ||
504 | |||
505 | if (size < size_needed || NULL == buf) | ||
506 | { | ||
507 | GNUNET_break (0); | ||
508 | return 0; | ||
509 | } | ||
510 | msg = (struct GNUNET_CADET_ConnectionCreate *) buf; | ||
511 | msg->header.size = htons (size_needed); | ||
512 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | ||
513 | msg->cid = *GMC_get_id (c); | ||
514 | |||
515 | peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1]; | ||
516 | for (i = 0; i < p->length; i++) | ||
517 | { | ||
518 | GNUNET_PEER_resolve (p->peers[i], peer_ptr++); | ||
519 | } | ||
520 | |||
521 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
522 | "CONNECTION CREATE (%u bytes long) sent!\n", | ||
523 | size_needed); | ||
524 | return size_needed; | ||
525 | } | ||
526 | |||
527 | |||
528 | /** | ||
529 | * Creates a path ack message in buf and frees all unused resources. | ||
530 | * | ||
531 | * @param c Connection to send an ACK on. | ||
532 | * @param size number of bytes available in buf | ||
533 | * @param buf where the callee should write the message | ||
534 | * | ||
535 | * @return number of bytes written to buf | ||
536 | */ | ||
537 | static size_t | ||
538 | send_core_connection_ack (struct CadetConnection *c, size_t size, void *buf) | ||
539 | { | ||
540 | struct GNUNET_CADET_ConnectionACK *msg = buf; | ||
541 | |||
542 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION ACK...\n"); | ||
543 | if (sizeof (struct GNUNET_CADET_ConnectionACK) > size) | ||
544 | { | ||
545 | GNUNET_break (0); | ||
546 | return 0; | ||
547 | } | ||
548 | msg->header.size = htons (sizeof (struct GNUNET_CADET_ConnectionACK)); | ||
549 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK); | ||
550 | msg->cid = *GMC_get_id (c); | ||
551 | |||
552 | LOG (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION ACK sent!\n"); | ||
553 | return sizeof (struct GNUNET_CADET_ConnectionACK); | ||
554 | } | ||
555 | |||
556 | |||
557 | /******************************************************************************/ | ||
558 | /******************************** STATIC ***********************************/ | ||
559 | /******************************************************************************/ | ||
560 | |||
561 | |||
562 | /** | ||
563 | * Get priority for a queued message. | ||
564 | * | ||
565 | * @param q Queued message | ||
566 | * | ||
567 | * @return CORE priority to use. | ||
568 | */ | ||
569 | static enum GNUNET_CORE_Priority | ||
570 | get_priority (struct CadetPeerQueue *q) | ||
571 | { | ||
572 | enum GNUNET_CORE_Priority low; | ||
573 | enum GNUNET_CORE_Priority high; | ||
574 | |||
575 | if (NULL == q) | ||
576 | { | ||
577 | GNUNET_break (0); | ||
578 | return GNUNET_CORE_PRIO_BACKGROUND; | ||
579 | } | ||
580 | |||
581 | /* Relayed traffic has lower priority, our own traffic has higher */ | ||
582 | if (NULL == q->c || GNUNET_NO == GMC_is_origin (q->c, q->fwd)) | ||
583 | { | ||
584 | low = GNUNET_CORE_PRIO_BEST_EFFORT; | ||
585 | high = GNUNET_CORE_PRIO_URGENT; | ||
586 | } | ||
587 | else | ||
588 | { | ||
589 | low = GNUNET_CORE_PRIO_URGENT; | ||
590 | high = GNUNET_CORE_PRIO_CRITICAL_CONTROL; | ||
591 | } | ||
592 | |||
593 | /* Bulky payload has lower priority, control traffic has higher. */ | ||
594 | if (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED == q->type) | ||
595 | return low; | ||
596 | else | ||
597 | return high; | ||
598 | } | ||
599 | |||
600 | |||
601 | /** | ||
602 | * Iterator over tunnel hash map entries to destroy the tunnel during shutdown. | ||
603 | * | ||
604 | * @param cls closure | ||
605 | * @param key current key code | ||
606 | * @param value value in the hash map | ||
607 | * @return #GNUNET_YES if we should continue to iterate, | ||
608 | * #GNUNET_NO if not. | ||
609 | */ | ||
610 | static int | ||
611 | shutdown_tunnel (void *cls, | ||
612 | const struct GNUNET_PeerIdentity *key, | ||
613 | void *value) | ||
614 | { | ||
615 | struct CadetPeer *p = value; | ||
616 | struct CadetTunnel3 *t = p->tunnel; | ||
617 | |||
618 | if (NULL != t) | ||
619 | GMT_destroy (t); | ||
620 | return GNUNET_YES; | ||
621 | } | ||
622 | |||
623 | |||
624 | /** | ||
625 | * Destroy the peer_info and free any allocated resources linked to it | ||
626 | * | ||
627 | * @param peer The peer_info to destroy. | ||
628 | * | ||
629 | * @return GNUNET_OK on success | ||
630 | */ | ||
631 | static int | ||
632 | peer_destroy (struct CadetPeer *peer) | ||
633 | { | ||
634 | struct GNUNET_PeerIdentity id; | ||
635 | struct CadetPeerPath *p; | ||
636 | struct CadetPeerPath *nextp; | ||
637 | |||
638 | GNUNET_PEER_resolve (peer->id, &id); | ||
639 | GNUNET_PEER_change_rc (peer->id, -1); | ||
640 | |||
641 | LOG (GNUNET_ERROR_TYPE_WARNING, "destroying peer %s\n", GNUNET_i2s (&id)); | ||
642 | |||
643 | if (GNUNET_YES != | ||
644 | GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer)) | ||
645 | { | ||
646 | GNUNET_break (0); | ||
647 | LOG (GNUNET_ERROR_TYPE_WARNING, " not in peermap!!\n"); | ||
648 | } | ||
649 | if (NULL != peer->search_h) | ||
650 | { | ||
651 | GMD_search_stop (peer->search_h); | ||
652 | } | ||
653 | p = peer->path_head; | ||
654 | while (NULL != p) | ||
655 | { | ||
656 | nextp = p->next; | ||
657 | GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p); | ||
658 | path_destroy (p); | ||
659 | p = nextp; | ||
660 | } | ||
661 | GMT_destroy_empty (peer->tunnel); | ||
662 | GNUNET_free (peer); | ||
663 | return GNUNET_OK; | ||
664 | } | ||
665 | |||
666 | |||
667 | /** | ||
668 | * Returns if peer is used (has a tunnel or is neighbor). | ||
669 | * | ||
670 | * @param peer Peer to check. | ||
671 | * | ||
672 | * @return #GNUNET_YES if peer is in use. | ||
673 | */ | ||
674 | static int | ||
675 | peer_is_used (struct CadetPeer *peer) | ||
676 | { | ||
677 | struct CadetPeerPath *p; | ||
678 | |||
679 | if (NULL != peer->tunnel) | ||
680 | return GNUNET_YES; | ||
681 | |||
682 | for (p = peer->path_head; NULL != p; p = p->next) | ||
683 | { | ||
684 | if (p->length < 3) | ||
685 | return GNUNET_YES; | ||
686 | } | ||
687 | return GNUNET_NO; | ||
688 | } | ||
689 | |||
690 | |||
691 | /** | ||
692 | * Iterator over all the peers to get the oldest timestamp. | ||
693 | * | ||
694 | * @param cls Closure (unsued). | ||
695 | * @param key ID of the peer. | ||
696 | * @param value Peer_Info of the peer. | ||
697 | */ | ||
698 | static int | ||
699 | peer_get_oldest (void *cls, | ||
700 | const struct GNUNET_PeerIdentity *key, | ||
701 | void *value) | ||
702 | { | ||
703 | struct CadetPeer *p = value; | ||
704 | struct GNUNET_TIME_Absolute *abs = cls; | ||
705 | |||
706 | /* Don't count active peers */ | ||
707 | if (GNUNET_YES == peer_is_used (p)) | ||
708 | return GNUNET_YES; | ||
709 | |||
710 | if (abs->abs_value_us < p->last_contact.abs_value_us) | ||
711 | abs->abs_value_us = p->last_contact.abs_value_us; | ||
712 | |||
713 | return GNUNET_YES; | ||
714 | } | ||
715 | |||
716 | |||
717 | /** | ||
718 | * Iterator over all the peers to remove the oldest entry. | ||
719 | * | ||
720 | * @param cls Closure (unsued). | ||
721 | * @param key ID of the peer. | ||
722 | * @param value Peer_Info of the peer. | ||
723 | */ | ||
724 | static int | ||
725 | peer_timeout (void *cls, | ||
726 | const struct GNUNET_PeerIdentity *key, | ||
727 | void *value) | ||
728 | { | ||
729 | struct CadetPeer *p = value; | ||
730 | struct GNUNET_TIME_Absolute *abs = cls; | ||
731 | |||
732 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
733 | "peer %s timeout\n", GNUNET_i2s (key)); | ||
734 | |||
735 | if (p->last_contact.abs_value_us == abs->abs_value_us && | ||
736 | GNUNET_NO == peer_is_used (p)) | ||
737 | { | ||
738 | peer_destroy (p); | ||
739 | return GNUNET_NO; | ||
740 | } | ||
741 | return GNUNET_YES; | ||
742 | } | ||
743 | |||
744 | |||
745 | /** | ||
746 | * Delete oldest unused peer. | ||
747 | */ | ||
748 | static void | ||
749 | peer_delete_oldest (void) | ||
750 | { | ||
751 | struct GNUNET_TIME_Absolute abs; | ||
752 | |||
753 | abs = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
754 | |||
755 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
756 | &peer_get_oldest, | ||
757 | &abs); | ||
758 | GNUNET_CONTAINER_multipeermap_iterate (peers, | ||
759 | &peer_timeout, | ||
760 | &abs); | ||
761 | } | ||
762 | |||
763 | |||
764 | /** | ||
765 | * Choose the best (yet unused) path towards a peer, | ||
766 | * considering the tunnel properties. | ||
767 | * | ||
768 | * @param peer The destination peer. | ||
769 | * | ||
770 | * @return Best current known path towards the peer, if any. | ||
771 | */ | ||
772 | static struct CadetPeerPath * | ||
773 | peer_get_best_path (const struct CadetPeer *peer) | ||
774 | { | ||
775 | struct CadetPeerPath *best_p; | ||
776 | struct CadetPeerPath *p; | ||
777 | unsigned int best_cost; | ||
778 | unsigned int cost; | ||
779 | |||
780 | best_cost = UINT_MAX; | ||
781 | best_p = NULL; | ||
782 | for (p = peer->path_head; NULL != p; p = p->next) | ||
783 | { | ||
784 | if (GNUNET_NO == path_is_valid (p)) | ||
785 | continue; /* Don't use invalid paths. */ | ||
786 | if (GNUNET_YES == GMT_is_path_used (peer->tunnel, p)) | ||
787 | continue; /* If path is already in use, skip it. */ | ||
788 | |||
789 | if ((cost = GMT_get_path_cost (peer->tunnel, p)) < best_cost) | ||
790 | { | ||
791 | best_cost = cost; | ||
792 | best_p = p; | ||
793 | } | ||
794 | } | ||
795 | return best_p; | ||
796 | } | ||
797 | |||
798 | |||
799 | /** | ||
800 | * Is this queue element sendable? | ||
801 | * | ||
802 | * - All management traffic is always sendable. | ||
803 | * - For payload traffic, check the connection flow control. | ||
804 | * | ||
805 | * @param q Queue element to inspect. | ||
806 | * | ||
807 | * @return #GNUNET_YES if it is sendable, #GNUNET_NO otherwise. | ||
808 | */ | ||
809 | static int | ||
810 | queue_is_sendable (struct CadetPeerQueue *q) | ||
811 | { | ||
812 | /* Is PID-independent? */ | ||
813 | switch (q->type) | ||
814 | { | ||
815 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
816 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
817 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
818 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
819 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
820 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
821 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
822 | return GNUNET_YES; | ||
823 | |||
824 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
825 | break; | ||
826 | |||
827 | default: | ||
828 | GNUNET_break (0); | ||
829 | } | ||
830 | |||
831 | return GMC_is_sendable (q->c, q->fwd); | ||
832 | } | ||
833 | |||
834 | |||
835 | /** | ||
836 | * Get first sendable message. | ||
837 | * | ||
838 | * @param peer The destination peer. | ||
839 | * | ||
840 | * @return First transmittable message, if any. Otherwise, NULL. | ||
841 | */ | ||
842 | static struct CadetPeerQueue * | ||
843 | peer_get_first_message (const struct CadetPeer *peer) | ||
844 | { | ||
845 | struct CadetPeerQueue *q; | ||
846 | |||
847 | for (q = peer->queue_head; NULL != q; q = q->next) | ||
848 | { | ||
849 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking %p towards %s\n", q, GMC_2s (q->c)); | ||
850 | if (queue_is_sendable (q)) | ||
851 | return q; | ||
852 | } | ||
853 | |||
854 | return NULL; | ||
855 | } | ||
856 | |||
857 | |||
858 | /** | ||
859 | * Function to process paths received for a new peer addition. The recorded | ||
860 | * paths form the initial tunnel, which can be optimized later. | ||
861 | * Called on each result obtained for the DHT search. | ||
862 | * | ||
863 | * @param cls closure | ||
864 | * @param path | ||
865 | */ | ||
866 | static void | ||
867 | search_handler (void *cls, const struct CadetPeerPath *path) | ||
868 | { | ||
869 | struct CadetPeer *peer = cls; | ||
870 | unsigned int connection_count; | ||
871 | |||
872 | GMP_add_path_to_all (path, GNUNET_NO); | ||
873 | |||
874 | /* Count connections */ | ||
875 | connection_count = GMT_count_connections (peer->tunnel); | ||
876 | |||
877 | /* If we already have 3 (or more (?!)) connections, it's enough */ | ||
878 | if (3 <= connection_count) | ||
879 | return; | ||
880 | |||
881 | if (CADET_TUNNEL3_SEARCHING == GMT_get_cstate (peer->tunnel)) | ||
882 | { | ||
883 | LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n"); | ||
884 | GMP_connect (peer); | ||
885 | } | ||
886 | return; | ||
887 | } | ||
888 | |||
889 | |||
890 | |||
891 | /** | ||
892 | * Core callback to write a queued packet to core buffer | ||
893 | * | ||
894 | * @param cls Closure (peer info). | ||
895 | * @param size Number of bytes available in buf. | ||
896 | * @param buf Where the to write the message. | ||
897 | * | ||
898 | * @return number of bytes written to buf | ||
899 | */ | ||
900 | static size_t | ||
901 | queue_send (void *cls, size_t size, void *buf) | ||
902 | { | ||
903 | struct CadetPeer *peer = cls; | ||
904 | struct CadetConnection *c; | ||
905 | struct CadetPeerQueue *queue; | ||
906 | const struct GNUNET_PeerIdentity *dst_id; | ||
907 | size_t data_size; | ||
908 | uint32_t pid; | ||
909 | |||
910 | pid = 0; | ||
911 | peer->core_transmit = NULL; | ||
912 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Queue send towards %s (max %u)\n", | ||
913 | GMP_2s (peer), size); | ||
914 | |||
915 | if (NULL == buf || 0 == size) | ||
916 | { | ||
917 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Buffer size 0.\n"); | ||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | /* Initialize */ | ||
922 | queue = peer_get_first_message (peer); | ||
923 | if (NULL == queue) | ||
924 | { | ||
925 | GNUNET_assert (0); /* Core tmt_rdy should've been canceled */ | ||
926 | return 0; | ||
927 | } | ||
928 | c = queue->c; | ||
929 | |||
930 | dst_id = GNUNET_PEER_resolve2 (peer->id); | ||
931 | LOG (GNUNET_ERROR_TYPE_DEBUG, " on connection %s %s\n", | ||
932 | GMC_2s (c), GM_f2s(queue->fwd)); | ||
933 | /* Check if buffer size is enough for the message */ | ||
934 | if (queue->size > size) | ||
935 | { | ||
936 | LOG (GNUNET_ERROR_TYPE_WARNING, "not enough room (%u vs %u), reissue\n", | ||
937 | queue->size, size); | ||
938 | peer->core_transmit = | ||
939 | GNUNET_CORE_notify_transmit_ready (core_handle, | ||
940 | GNUNET_NO, get_priority (queue), | ||
941 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
942 | dst_id, | ||
943 | queue->size, | ||
944 | &queue_send, | ||
945 | peer); | ||
946 | return 0; | ||
947 | } | ||
948 | LOG (GNUNET_ERROR_TYPE_DEBUG, " size %u ok\n", queue->size); | ||
949 | |||
950 | /* Fill buf */ | ||
951 | switch (queue->type) | ||
952 | { | ||
953 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
954 | pid = GMC_get_pid (queue->c, queue->fwd); | ||
955 | LOG (GNUNET_ERROR_TYPE_DEBUG, " payload ID %u\n", pid); | ||
956 | data_size = send_core_data_raw (queue->cls, size, buf); | ||
957 | ((struct GNUNET_CADET_Encrypted *) buf)->pid = htonl (pid); | ||
958 | break; | ||
959 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
960 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
961 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
962 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
963 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
964 | LOG (GNUNET_ERROR_TYPE_DEBUG, " raw %s\n", GM_m2s (queue->type)); | ||
965 | data_size = send_core_data_raw (queue->cls, size, buf); | ||
966 | break; | ||
967 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
968 | LOG (GNUNET_ERROR_TYPE_DEBUG, " path create\n"); | ||
969 | if (GMC_is_origin (c, GNUNET_YES)) | ||
970 | data_size = send_core_connection_create (queue->c, size, buf); | ||
971 | else | ||
972 | data_size = send_core_data_raw (queue->cls, size, buf); | ||
973 | break; | ||
974 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
975 | LOG (GNUNET_ERROR_TYPE_DEBUG, " path ack\n"); | ||
976 | if (GMC_is_origin (c, GNUNET_NO) || | ||
977 | GMC_is_origin (c, GNUNET_YES)) | ||
978 | data_size = send_core_connection_ack (queue->c, size, buf); | ||
979 | else | ||
980 | data_size = send_core_data_raw (queue->cls, size, buf); | ||
981 | break; | ||
982 | case GNUNET_MESSAGE_TYPE_CADET_DATA: | ||
983 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
984 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
985 | /* This should be encapsulted */ | ||
986 | GNUNET_break (0); | ||
987 | data_size = 0; | ||
988 | break; | ||
989 | default: | ||
990 | GNUNET_break (0); | ||
991 | LOG (GNUNET_ERROR_TYPE_WARNING, " type unknown: %u\n", queue->type); | ||
992 | data_size = 0; | ||
993 | } | ||
994 | |||
995 | if (0 < drop_percent && | ||
996 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent) | ||
997 | { | ||
998 | LOG (GNUNET_ERROR_TYPE_WARNING, "DD %s on connection %s\n", | ||
999 | GM_m2s (queue->type), GMC_2s (c)); | ||
1000 | data_size = 0; | ||
1001 | } | ||
1002 | else | ||
1003 | { | ||
1004 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1005 | "snd %s (%s %u) on connection %s (%p) %s (size %u)\n", | ||
1006 | GM_m2s (queue->type), GM_m2s (queue->payload_type), | ||
1007 | queue->payload_type, GMC_2s (c), c, GM_f2s (queue->fwd), data_size); | ||
1008 | } | ||
1009 | |||
1010 | /* Free queue, but cls was freed by send_core_* */ | ||
1011 | GMP_queue_destroy (queue, GNUNET_NO, GNUNET_YES, pid); | ||
1012 | |||
1013 | /* If more data in queue, send next */ | ||
1014 | queue = peer_get_first_message (peer); | ||
1015 | if (NULL != queue) | ||
1016 | { | ||
1017 | LOG (GNUNET_ERROR_TYPE_DEBUG, " more data!\n"); | ||
1018 | if (NULL == peer->core_transmit) | ||
1019 | { | ||
1020 | peer->core_transmit = | ||
1021 | GNUNET_CORE_notify_transmit_ready (core_handle, | ||
1022 | GNUNET_NO, get_priority (queue), | ||
1023 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1024 | dst_id, | ||
1025 | queue->size, | ||
1026 | &queue_send, | ||
1027 | peer); | ||
1028 | queue->start_waiting = GNUNET_TIME_absolute_get (); | ||
1029 | } | ||
1030 | else | ||
1031 | { | ||
1032 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1033 | "* tmt rdy called somewhere else\n"); | ||
1034 | } | ||
1035 | // GMC_start_poll (); FIXME needed? | ||
1036 | } | ||
1037 | else | ||
1038 | { | ||
1039 | // GMC_stop_poll(); FIXME needed? | ||
1040 | } | ||
1041 | |||
1042 | LOG (GNUNET_ERROR_TYPE_DEBUG, " return %d\n", data_size); | ||
1043 | queue_debug (peer); | ||
1044 | return data_size; | ||
1045 | } | ||
1046 | |||
1047 | |||
1048 | /******************************************************************************/ | ||
1049 | /******************************** API ***********************************/ | ||
1050 | /******************************************************************************/ | ||
1051 | |||
1052 | |||
1053 | /** | ||
1054 | * Free a transmission that was already queued with all resources | ||
1055 | * associated to the request. | ||
1056 | * | ||
1057 | * @param queue Queue handler to cancel. | ||
1058 | * @param clear_cls Is it necessary to free associated cls? | ||
1059 | * @param sent Was it really sent? (Could have been canceled) | ||
1060 | * @param pid PID, if relevant (was sent and was a payload message). | ||
1061 | */ | ||
1062 | void | ||
1063 | GMP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls, | ||
1064 | int sent, uint32_t pid) | ||
1065 | { | ||
1066 | struct CadetPeer *peer; | ||
1067 | |||
1068 | peer = queue->peer; | ||
1069 | |||
1070 | if (GNUNET_YES == clear_cls) | ||
1071 | { | ||
1072 | LOG (GNUNET_ERROR_TYPE_DEBUG, "queue destroy type %s\n", | ||
1073 | GM_m2s (queue->type)); | ||
1074 | switch (queue->type) | ||
1075 | { | ||
1076 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
1077 | LOG (GNUNET_ERROR_TYPE_INFO, "destroying a DESTROY message\n"); | ||
1078 | /* fall through */ | ||
1079 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
1080 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
1081 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
1082 | case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE: | ||
1083 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
1084 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
1085 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
1086 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
1087 | GNUNET_free_non_null (queue->cls); | ||
1088 | break; | ||
1089 | |||
1090 | default: | ||
1091 | GNUNET_break (0); | ||
1092 | LOG (GNUNET_ERROR_TYPE_ERROR, " type %s unknown!\n", | ||
1093 | GM_m2s (queue->type)); | ||
1094 | } | ||
1095 | } | ||
1096 | GNUNET_CONTAINER_DLL_remove (peer->queue_head, peer->queue_tail, queue); | ||
1097 | |||
1098 | if (queue->type != GNUNET_MESSAGE_TYPE_CADET_ACK && | ||
1099 | queue->type != GNUNET_MESSAGE_TYPE_CADET_POLL) | ||
1100 | { | ||
1101 | peer->queue_n--; | ||
1102 | } | ||
1103 | |||
1104 | if (NULL != queue->callback) | ||
1105 | { | ||
1106 | LOG (GNUNET_ERROR_TYPE_DEBUG, " calling callback\n"); | ||
1107 | queue->callback (queue->callback_cls, | ||
1108 | queue->c, sent, queue->type, pid, | ||
1109 | queue->fwd, queue->size, | ||
1110 | GNUNET_TIME_absolute_get_duration (queue->start_waiting)); | ||
1111 | } | ||
1112 | |||
1113 | if (NULL == peer_get_first_message (peer) && NULL != peer->core_transmit) | ||
1114 | { | ||
1115 | GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit); | ||
1116 | peer->core_transmit = NULL; | ||
1117 | } | ||
1118 | |||
1119 | GNUNET_free (queue); | ||
1120 | } | ||
1121 | |||
1122 | |||
1123 | /** | ||
1124 | * @brief Queue and pass message to core when possible. | ||
1125 | * | ||
1126 | * @param peer Peer towards which to queue the message. | ||
1127 | * @param cls Closure (@c type dependant). It will be used by queue_send to | ||
1128 | * build the message to be sent if not already prebuilt. | ||
1129 | * @param type Type of the message, 0 for a raw message. | ||
1130 | * @param size Size of the message. | ||
1131 | * @param c Connection this message belongs to (can be NULL). | ||
1132 | * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!) | ||
1133 | * @param cont Continuation to be called once CORE has taken the message. | ||
1134 | * @param cont_cls Closure for @c cont. | ||
1135 | * | ||
1136 | * @return Handle to cancel the message before it is sent. Once cont is called | ||
1137 | * message has been sent and therefore the handle is no longer valid. | ||
1138 | */ | ||
1139 | struct CadetPeerQueue * | ||
1140 | GMP_queue_add (struct CadetPeer *peer, void *cls, uint16_t type, | ||
1141 | uint16_t payload_type, uint32_t payload_id, size_t size, | ||
1142 | struct CadetConnection *c, int fwd, | ||
1143 | GMP_sent cont, void *cont_cls) | ||
1144 | { | ||
1145 | struct CadetPeerQueue *queue; | ||
1146 | int priority; | ||
1147 | int call_core; | ||
1148 | |||
1149 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
1150 | "que %s (%s %u) on connection %s (%p) %s towards %s (size %u)\n", | ||
1151 | GM_m2s (type), GM_m2s (payload_type), payload_id, | ||
1152 | GMC_2s (c), c, GM_f2s (fwd), GMP_2s (peer), size); | ||
1153 | |||
1154 | if (NULL == peer->connections) | ||
1155 | { | ||
1156 | /* We are not connected to this peer, ignore request. */ | ||
1157 | LOG (GNUNET_ERROR_TYPE_WARNING, "%s not a neighbor\n", GMP_2s (peer)); | ||
1158 | GNUNET_STATISTICS_update (stats, "# messages dropped due to wrong hop", 1, | ||
1159 | GNUNET_NO); | ||
1160 | return NULL; | ||
1161 | } | ||
1162 | |||
1163 | priority = 0; | ||
1164 | |||
1165 | if (GNUNET_MESSAGE_TYPE_CADET_POLL == type || | ||
1166 | GNUNET_MESSAGE_TYPE_CADET_ACK == type) | ||
1167 | { | ||
1168 | priority = 100; | ||
1169 | } | ||
1170 | |||
1171 | LOG (GNUNET_ERROR_TYPE_DEBUG, "priority %d\n", priority); | ||
1172 | |||
1173 | call_core = NULL == c ? GNUNET_YES : GMC_is_sendable (c, fwd); | ||
1174 | queue = GNUNET_new (struct CadetPeerQueue); | ||
1175 | queue->cls = cls; | ||
1176 | queue->type = type; | ||
1177 | queue->payload_type = payload_type; | ||
1178 | queue->payload_id = payload_id; | ||
1179 | queue->size = size; | ||
1180 | queue->peer = peer; | ||
1181 | queue->c = c; | ||
1182 | queue->fwd = fwd; | ||
1183 | queue->callback = cont; | ||
1184 | queue->callback_cls = cont_cls; | ||
1185 | if (100 > priority) | ||
1186 | { | ||
1187 | GNUNET_CONTAINER_DLL_insert_tail (peer->queue_head, peer->queue_tail, queue); | ||
1188 | peer->queue_n++; | ||
1189 | } | ||
1190 | else | ||
1191 | { | ||
1192 | GNUNET_CONTAINER_DLL_insert (peer->queue_head, peer->queue_tail, queue); | ||
1193 | call_core = GNUNET_YES; | ||
1194 | } | ||
1195 | |||
1196 | if (NULL == peer->core_transmit && GNUNET_YES == call_core) | ||
1197 | { | ||
1198 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1199 | "calling core tmt rdy towards %s for %u bytes\n", | ||
1200 | GMP_2s (peer), size); | ||
1201 | peer->core_transmit = | ||
1202 | GNUNET_CORE_notify_transmit_ready (core_handle, | ||
1203 | GNUNET_NO, get_priority (queue), | ||
1204 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1205 | GNUNET_PEER_resolve2 (peer->id), | ||
1206 | size, | ||
1207 | &queue_send, | ||
1208 | peer); | ||
1209 | queue->start_waiting = GNUNET_TIME_absolute_get (); | ||
1210 | } | ||
1211 | else if (GNUNET_NO == call_core) | ||
1212 | { | ||
1213 | LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s not needed\n", | ||
1214 | GMP_2s (peer)); | ||
1215 | |||
1216 | } | ||
1217 | else | ||
1218 | { | ||
1219 | LOG (GNUNET_ERROR_TYPE_DEBUG, "core tmt rdy towards %s already called\n", | ||
1220 | GMP_2s (peer)); | ||
1221 | |||
1222 | } | ||
1223 | queue_debug (peer); | ||
1224 | return queue; | ||
1225 | } | ||
1226 | |||
1227 | |||
1228 | /** | ||
1229 | * Cancel all queued messages to a peer that belong to a certain connection. | ||
1230 | * | ||
1231 | * @param peer Peer towards whom to cancel. | ||
1232 | * @param c Connection whose queued messages to cancel. Might be destroyed by | ||
1233 | * the sent continuation call. | ||
1234 | */ | ||
1235 | void | ||
1236 | GMP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c) | ||
1237 | { | ||
1238 | struct CadetPeerQueue *q; | ||
1239 | struct CadetPeerQueue *next; | ||
1240 | struct CadetPeerQueue *prev; | ||
1241 | |||
1242 | for (q = peer->queue_head; NULL != q; q = next) | ||
1243 | { | ||
1244 | prev = q->prev; | ||
1245 | if (q->c == c) | ||
1246 | { | ||
1247 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMP queue cancel %s\n", GM_m2s (q->type)); | ||
1248 | if (GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY != q->type) | ||
1249 | { | ||
1250 | q->c = NULL; | ||
1251 | } | ||
1252 | else | ||
1253 | { | ||
1254 | GMP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0); | ||
1255 | } | ||
1256 | |||
1257 | /* Get next from prev, q->next might be already freed: | ||
1258 | * queue destroy -> callback -> GMC_destroy -> cancel_queues -> here | ||
1259 | */ | ||
1260 | if (NULL == prev) | ||
1261 | next = peer->queue_head; | ||
1262 | else | ||
1263 | next = prev->next; | ||
1264 | } | ||
1265 | else | ||
1266 | { | ||
1267 | next = q->next; | ||
1268 | } | ||
1269 | } | ||
1270 | if (NULL == peer->queue_head) | ||
1271 | { | ||
1272 | if (NULL != peer->core_transmit) | ||
1273 | { | ||
1274 | GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit); | ||
1275 | peer->core_transmit = NULL; | ||
1276 | } | ||
1277 | } | ||
1278 | } | ||
1279 | |||
1280 | |||
1281 | /** | ||
1282 | * Get the first transmittable message for a connection. | ||
1283 | * | ||
1284 | * @param peer Neighboring peer. | ||
1285 | * @param c Connection. | ||
1286 | * | ||
1287 | * @return First transmittable message. | ||
1288 | */ | ||
1289 | static struct CadetPeerQueue * | ||
1290 | connection_get_first_message (struct CadetPeer *peer, struct CadetConnection *c) | ||
1291 | { | ||
1292 | struct CadetPeerQueue *q; | ||
1293 | |||
1294 | for (q = peer->queue_head; NULL != q; q = q->next) | ||
1295 | { | ||
1296 | if (q->c != c) | ||
1297 | continue; | ||
1298 | if (queue_is_sendable (q)) | ||
1299 | { | ||
1300 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sendable!!\n"); | ||
1301 | return q; | ||
1302 | } | ||
1303 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not sendable\n"); | ||
1304 | } | ||
1305 | |||
1306 | return NULL; | ||
1307 | } | ||
1308 | |||
1309 | |||
1310 | /** | ||
1311 | * Get the first message for a connection and unqueue it. | ||
1312 | * | ||
1313 | * @param peer Neighboring peer. | ||
1314 | * @param c Connection. | ||
1315 | * | ||
1316 | * @return First message for this connection. | ||
1317 | */ | ||
1318 | struct GNUNET_MessageHeader * | ||
1319 | GMP_connection_pop (struct CadetPeer *peer, struct CadetConnection *c) | ||
1320 | { | ||
1321 | struct CadetPeerQueue *q; | ||
1322 | struct CadetPeerQueue *next; | ||
1323 | struct GNUNET_MessageHeader *msg; | ||
1324 | |||
1325 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection pop on %s\n", GMC_2s (c)); | ||
1326 | for (q = peer->queue_head; NULL != q; q = next) | ||
1327 | { | ||
1328 | next = q->next; | ||
1329 | if (q->c != c) | ||
1330 | continue; | ||
1331 | switch (q->type) | ||
1332 | { | ||
1333 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE: | ||
1334 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_ACK: | ||
1335 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_DESTROY: | ||
1336 | case GNUNET_MESSAGE_TYPE_CADET_CONNECTION_BROKEN: | ||
1337 | case GNUNET_MESSAGE_TYPE_CADET_ACK: | ||
1338 | case GNUNET_MESSAGE_TYPE_CADET_POLL: | ||
1339 | GMP_queue_destroy (q, GNUNET_YES, GNUNET_NO, 0); | ||
1340 | continue; | ||
1341 | |||
1342 | case GNUNET_MESSAGE_TYPE_CADET_KX: | ||
1343 | case GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED: | ||
1344 | msg = (struct GNUNET_MessageHeader *) q->cls; | ||
1345 | GMP_queue_destroy (q, GNUNET_NO, GNUNET_NO, 0); | ||
1346 | return msg; | ||
1347 | |||
1348 | default: | ||
1349 | GNUNET_break (0); | ||
1350 | } | ||
1351 | } | ||
1352 | |||
1353 | return NULL; | ||
1354 | } | ||
1355 | |||
1356 | |||
1357 | void | ||
1358 | GMP_queue_unlock (struct CadetPeer *peer, struct CadetConnection *c) | ||
1359 | { | ||
1360 | struct CadetPeerQueue *q; | ||
1361 | size_t size; | ||
1362 | |||
1363 | if (NULL != peer->core_transmit) | ||
1364 | { | ||
1365 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already unlocked!\n"); | ||
1366 | return; /* Already unlocked */ | ||
1367 | } | ||
1368 | |||
1369 | q = connection_get_first_message (peer, c); | ||
1370 | if (NULL == q) | ||
1371 | { | ||
1372 | LOG (GNUNET_ERROR_TYPE_DEBUG, " queue empty!\n"); | ||
1373 | return; /* Nothing to transmit */ | ||
1374 | } | ||
1375 | |||
1376 | size = q->size; | ||
1377 | peer->core_transmit = | ||
1378 | GNUNET_CORE_notify_transmit_ready (core_handle, | ||
1379 | GNUNET_NO, get_priority (q), | ||
1380 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
1381 | GNUNET_PEER_resolve2 (peer->id), | ||
1382 | size, | ||
1383 | &queue_send, | ||
1384 | peer); | ||
1385 | } | ||
1386 | |||
1387 | |||
1388 | /** | ||
1389 | * Initialize the peer subsystem. | ||
1390 | * | ||
1391 | * @param c Configuration. | ||
1392 | */ | ||
1393 | void | ||
1394 | GMP_init (const struct GNUNET_CONFIGURATION_Handle *c) | ||
1395 | { | ||
1396 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
1397 | peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO); | ||
1398 | if (GNUNET_OK != | ||
1399 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "MAX_PEERS", | ||
1400 | &max_peers)) | ||
1401 | { | ||
1402 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1403 | "CADET", "MAX_PEERS", "USING DEFAULT"); | ||
1404 | max_peers = 1000; | ||
1405 | } | ||
1406 | |||
1407 | if (GNUNET_OK != | ||
1408 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DROP_PERCENT", | ||
1409 | &drop_percent)) | ||
1410 | { | ||
1411 | drop_percent = 0; | ||
1412 | } | ||
1413 | else | ||
1414 | { | ||
1415 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1416 | LOG (GNUNET_ERROR_TYPE_WARNING, "Cadet is running with DROP enabled.\n"); | ||
1417 | LOG (GNUNET_ERROR_TYPE_WARNING, "This is NOT a good idea!\n"); | ||
1418 | LOG (GNUNET_ERROR_TYPE_WARNING, "Remove DROP_PERCENT from config file.\n"); | ||
1419 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1420 | } | ||
1421 | |||
1422 | core_handle = GNUNET_CORE_connect (c, /* Main configuration */ | ||
1423 | NULL, /* Closure passed to CADET functions */ | ||
1424 | &core_init, /* Call core_init once connected */ | ||
1425 | &core_connect, /* Handle connects */ | ||
1426 | &core_disconnect, /* remove peers on disconnects */ | ||
1427 | NULL, /* Don't notify about all incoming messages */ | ||
1428 | GNUNET_NO, /* For header only in notification */ | ||
1429 | NULL, /* Don't notify about all outbound messages */ | ||
1430 | GNUNET_NO, /* For header-only out notification */ | ||
1431 | core_handlers); /* Register these handlers */ | ||
1432 | if (GNUNET_YES != | ||
1433 | GNUNET_CONFIGURATION_get_value_yesno (c, "CADET", "DISABLE_TRY_CONNECT")) | ||
1434 | { | ||
1435 | transport_handle = GNUNET_TRANSPORT_connect (c, &my_full_id, NULL, /* cls */ | ||
1436 | /* Notify callbacks */ | ||
1437 | NULL, NULL, NULL); | ||
1438 | } | ||
1439 | else | ||
1440 | { | ||
1441 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1442 | LOG (GNUNET_ERROR_TYPE_WARNING, "* DISABLE TRYING CONNECT in config *\n"); | ||
1443 | LOG (GNUNET_ERROR_TYPE_WARNING, "* Use this only for test purposes. *\n"); | ||
1444 | LOG (GNUNET_ERROR_TYPE_WARNING, "**************************************\n"); | ||
1445 | transport_handle = NULL; | ||
1446 | } | ||
1447 | |||
1448 | |||
1449 | |||
1450 | if (NULL == core_handle) | ||
1451 | { | ||
1452 | GNUNET_break (0); | ||
1453 | GNUNET_SCHEDULER_shutdown (); | ||
1454 | return; | ||
1455 | } | ||
1456 | |||
1457 | } | ||
1458 | |||
1459 | /** | ||
1460 | * Shut down the peer subsystem. | ||
1461 | */ | ||
1462 | void | ||
1463 | GMP_shutdown (void) | ||
1464 | { | ||
1465 | GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL); | ||
1466 | |||
1467 | if (core_handle != NULL) | ||
1468 | { | ||
1469 | GNUNET_CORE_disconnect (core_handle); | ||
1470 | core_handle = NULL; | ||
1471 | } | ||
1472 | if (transport_handle != NULL) | ||
1473 | { | ||
1474 | GNUNET_TRANSPORT_disconnect (transport_handle); | ||
1475 | transport_handle = NULL; | ||
1476 | } | ||
1477 | GNUNET_PEER_change_rc (myid, -1); | ||
1478 | } | ||
1479 | |||
1480 | /** | ||
1481 | * Retrieve the CadetPeer stucture associated with the peer, create one | ||
1482 | * and insert it in the appropriate structures if the peer is not known yet. | ||
1483 | * | ||
1484 | * @param peer_id Full identity of the peer. | ||
1485 | * | ||
1486 | * @return Existing or newly created peer structure. | ||
1487 | */ | ||
1488 | struct CadetPeer * | ||
1489 | GMP_get (const struct GNUNET_PeerIdentity *peer_id) | ||
1490 | { | ||
1491 | struct CadetPeer *peer; | ||
1492 | |||
1493 | peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id); | ||
1494 | if (NULL == peer) | ||
1495 | { | ||
1496 | peer = GNUNET_new (struct CadetPeer); | ||
1497 | if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers) | ||
1498 | { | ||
1499 | peer_delete_oldest (); | ||
1500 | } | ||
1501 | GNUNET_CONTAINER_multipeermap_put (peers, peer_id, peer, | ||
1502 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1503 | peer->id = GNUNET_PEER_intern (peer_id); | ||
1504 | } | ||
1505 | peer->last_contact = GNUNET_TIME_absolute_get(); | ||
1506 | |||
1507 | return peer; | ||
1508 | } | ||
1509 | |||
1510 | |||
1511 | /** | ||
1512 | * Retrieve the CadetPeer stucture associated with the peer, create one | ||
1513 | * and insert it in the appropriate structures if the peer is not known yet. | ||
1514 | * | ||
1515 | * @param peer Short identity of the peer. | ||
1516 | * | ||
1517 | * @return Existing or newly created peer structure. | ||
1518 | */ | ||
1519 | struct CadetPeer * | ||
1520 | GMP_get_short (const GNUNET_PEER_Id peer) | ||
1521 | { | ||
1522 | return GMP_get (GNUNET_PEER_resolve2 (peer)); | ||
1523 | } | ||
1524 | |||
1525 | |||
1526 | /** | ||
1527 | * Try to connect to a peer on transport level. | ||
1528 | * | ||
1529 | * @param cls Closure (peer). | ||
1530 | * @param tc TaskContext. | ||
1531 | */ | ||
1532 | static void | ||
1533 | try_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1534 | { | ||
1535 | struct CadetPeer *peer = cls; | ||
1536 | |||
1537 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | ||
1538 | return; | ||
1539 | |||
1540 | GNUNET_TRANSPORT_try_connect (transport_handle, | ||
1541 | GNUNET_PEER_resolve2 (peer->id), NULL, NULL); | ||
1542 | } | ||
1543 | |||
1544 | |||
1545 | /** | ||
1546 | * Try to establish a new connection to this peer (in its tunnel). | ||
1547 | * If the peer doesn't have any path to it yet, try to get one. | ||
1548 | * If the peer already has some path, send a CREATE CONNECTION towards it. | ||
1549 | * | ||
1550 | * @param peer Peer to connect to. | ||
1551 | */ | ||
1552 | void | ||
1553 | GMP_connect (struct CadetPeer *peer) | ||
1554 | { | ||
1555 | struct CadetTunnel3 *t; | ||
1556 | struct CadetPeerPath *p; | ||
1557 | struct CadetConnection *c; | ||
1558 | int rerun_search; | ||
1559 | |||
1560 | LOG (GNUNET_ERROR_TYPE_DEBUG, "peer_connect towards %s\n", GMP_2s (peer)); | ||
1561 | |||
1562 | /* If we have a current hello, try to connect using it. */ | ||
1563 | GMP_try_connect (peer); | ||
1564 | |||
1565 | t = peer->tunnel; | ||
1566 | c = NULL; | ||
1567 | rerun_search = GNUNET_NO; | ||
1568 | |||
1569 | if (NULL != peer->path_head) | ||
1570 | { | ||
1571 | LOG (GNUNET_ERROR_TYPE_DEBUG, " some path exists\n"); | ||
1572 | p = peer_get_best_path (peer); | ||
1573 | if (NULL != p) | ||
1574 | { | ||
1575 | char *s; | ||
1576 | |||
1577 | s = path_2s (p); | ||
1578 | LOG (GNUNET_ERROR_TYPE_DEBUG, " path to use: %s\n", s); | ||
1579 | GNUNET_free (s); | ||
1580 | |||
1581 | c = GMT_use_path (t, p); | ||
1582 | if (NULL == c) | ||
1583 | { | ||
1584 | /* This case can happen when the path includes a first hop that is | ||
1585 | * not yet known to be connected. | ||
1586 | * | ||
1587 | * This happens quite often during testing when running cadet | ||
1588 | * under valgrind: core connect notifications come very late and the | ||
1589 | * DHT result has already come and created a valid path. | ||
1590 | * In this case, the peer->connections hashmap will be NULL and | ||
1591 | * tunnel_use_path will not be able to create a connection from that | ||
1592 | * path. | ||
1593 | * | ||
1594 | * Re-running the DHT GET should give core time to callback. | ||
1595 | * | ||
1596 | * GMT_use_path -> GMC_new -> register_neighbors takes care of | ||
1597 | * updating statistics about this issue. | ||
1598 | */ | ||
1599 | rerun_search = GNUNET_YES; | ||
1600 | } | ||
1601 | else | ||
1602 | { | ||
1603 | GMC_send_create (c); | ||
1604 | return; | ||
1605 | } | ||
1606 | } | ||
1607 | else | ||
1608 | { | ||
1609 | LOG (GNUNET_ERROR_TYPE_DEBUG, " but is NULL, all paths are in use\n"); | ||
1610 | } | ||
1611 | } | ||
1612 | |||
1613 | if (NULL != peer->search_h && GNUNET_YES == rerun_search) | ||
1614 | { | ||
1615 | GMD_search_stop (peer->search_h); | ||
1616 | peer->search_h = NULL; | ||
1617 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1618 | " Stopping DHT GET for peer %s\n", | ||
1619 | GMP_2s (peer)); | ||
1620 | } | ||
1621 | |||
1622 | if (NULL == peer->search_h) | ||
1623 | { | ||
1624 | const struct GNUNET_PeerIdentity *id; | ||
1625 | |||
1626 | id = GNUNET_PEER_resolve2 (peer->id); | ||
1627 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1628 | " Starting DHT GET for peer %s\n", GMP_2s (peer)); | ||
1629 | peer->search_h = GMD_search (id, &search_handler, peer); | ||
1630 | if (CADET_TUNNEL3_NEW == GMT_get_cstate (t)) | ||
1631 | GMT_change_cstate (t, CADET_TUNNEL3_SEARCHING); | ||
1632 | } | ||
1633 | } | ||
1634 | |||
1635 | |||
1636 | /** | ||
1637 | * Chech whether there is a direct (core level) connection to peer. | ||
1638 | * | ||
1639 | * @param peer Peer to check. | ||
1640 | * | ||
1641 | * @return #GNUNET_YES if there is a direct connection. | ||
1642 | */ | ||
1643 | int | ||
1644 | GMP_is_neighbor (const struct CadetPeer *peer) | ||
1645 | { | ||
1646 | struct CadetPeerPath *path; | ||
1647 | |||
1648 | if (NULL == peer->connections) | ||
1649 | return GNUNET_NO; | ||
1650 | |||
1651 | for (path = peer->path_head; NULL != path; path = path->next) | ||
1652 | { | ||
1653 | if (3 > path->length) | ||
1654 | return GNUNET_YES; | ||
1655 | } | ||
1656 | |||
1657 | /* Is not a neighbor but connections is not NULL, probably disconnecting */ | ||
1658 | return GNUNET_NO; | ||
1659 | } | ||
1660 | |||
1661 | |||
1662 | /** | ||
1663 | * Create and initialize a new tunnel towards a peer, in case it has none. | ||
1664 | * In case the peer already has a tunnel, nothing is done. | ||
1665 | * | ||
1666 | * Does not generate any traffic, just creates the local data structures. | ||
1667 | * | ||
1668 | * @param peer Peer towards which to create the tunnel. | ||
1669 | */ | ||
1670 | void | ||
1671 | GMP_add_tunnel (struct CadetPeer *peer) | ||
1672 | { | ||
1673 | if (NULL != peer->tunnel) | ||
1674 | return; | ||
1675 | peer->tunnel = GMT_new (peer); | ||
1676 | } | ||
1677 | |||
1678 | |||
1679 | /** | ||
1680 | * Add a connection to a neighboring peer. | ||
1681 | * | ||
1682 | * Store that the peer is the first hop of the connection in one | ||
1683 | * direction and that on peer disconnect the connection must be | ||
1684 | * notified and destroyed, for it will no longer be valid. | ||
1685 | * | ||
1686 | * @param peer Peer to add connection to. | ||
1687 | * @param c Connection to add. | ||
1688 | * | ||
1689 | * @return GNUNET_OK on success. | ||
1690 | */ | ||
1691 | int | ||
1692 | GMP_add_connection (struct CadetPeer *peer, | ||
1693 | struct CadetConnection *c) | ||
1694 | { | ||
1695 | int result; | ||
1696 | LOG (GNUNET_ERROR_TYPE_DEBUG, "adding connection %s\n", GMC_2s (c)); | ||
1697 | LOG (GNUNET_ERROR_TYPE_DEBUG, "to peer %s\n", GMP_2s (peer)); | ||
1698 | |||
1699 | if (NULL == peer->connections) | ||
1700 | { | ||
1701 | GNUNET_break (0); | ||
1702 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1703 | "Peer %s is not a neighbor!\n", | ||
1704 | GMP_2s (peer)); | ||
1705 | return GNUNET_SYSERR; | ||
1706 | } | ||
1707 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1708 | "peer %s ok, has %u connections.\n", | ||
1709 | GMP_2s (peer), GNUNET_CONTAINER_multihashmap_size (peer->connections)); | ||
1710 | result = GNUNET_CONTAINER_multihashmap_put (peer->connections, | ||
1711 | GMC_get_h (c), | ||
1712 | c, | ||
1713 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
1714 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1715 | " now has %u connections.\n", | ||
1716 | GNUNET_CONTAINER_multihashmap_size (peer->connections)); | ||
1717 | LOG (GNUNET_ERROR_TYPE_DEBUG, "result %u\n", result); | ||
1718 | |||
1719 | return result; | ||
1720 | } | ||
1721 | |||
1722 | |||
1723 | /** | ||
1724 | * Add the path to the peer and update the path used to reach it in case this | ||
1725 | * is the shortest. | ||
1726 | * | ||
1727 | * @param peer Destination peer to add the path to. | ||
1728 | * @param path New path to add. Last peer must be the peer in arg 1. | ||
1729 | * Path will be either used of freed if already known. | ||
1730 | * @param trusted Do we trust that this path is real? | ||
1731 | * | ||
1732 | * @return path if path was taken, pointer to existing duplicate if exists | ||
1733 | * NULL on error. | ||
1734 | */ | ||
1735 | struct CadetPeerPath * | ||
1736 | GMP_add_path (struct CadetPeer *peer, struct CadetPeerPath *path, | ||
1737 | int trusted) | ||
1738 | { | ||
1739 | struct CadetPeerPath *aux; | ||
1740 | unsigned int l; | ||
1741 | unsigned int l2; | ||
1742 | |||
1743 | LOG (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n", | ||
1744 | path->length, GMP_2s (peer)); | ||
1745 | |||
1746 | if ((NULL == peer) || (NULL == path)) | ||
1747 | { | ||
1748 | GNUNET_break (0); | ||
1749 | path_destroy (path); | ||
1750 | return NULL; | ||
1751 | } | ||
1752 | if (path->peers[path->length - 1] != peer->id) | ||
1753 | { | ||
1754 | GNUNET_break (0); | ||
1755 | path_destroy (path); | ||
1756 | return NULL; | ||
1757 | } | ||
1758 | |||
1759 | for (l = 1; l < path->length; l++) | ||
1760 | { | ||
1761 | if (path->peers[l] == myid) | ||
1762 | { | ||
1763 | LOG (GNUNET_ERROR_TYPE_DEBUG, " shortening path by %u\n", l); | ||
1764 | for (l2 = 0; l2 < path->length - l; l2++) | ||
1765 | { | ||
1766 | path->peers[l2] = path->peers[l + l2]; | ||
1767 | } | ||
1768 | path->length -= l; | ||
1769 | l = 1; | ||
1770 | path->peers = GNUNET_realloc (path->peers, | ||
1771 | path->length * sizeof (GNUNET_PEER_Id)); | ||
1772 | } | ||
1773 | } | ||
1774 | |||
1775 | LOG (GNUNET_ERROR_TYPE_DEBUG, " final length: %u\n", path->length); | ||
1776 | |||
1777 | if (2 >= path->length && GNUNET_NO == trusted) | ||
1778 | { | ||
1779 | /* Only allow CORE to tell us about direct paths */ | ||
1780 | path_destroy (path); | ||
1781 | return NULL; | ||
1782 | } | ||
1783 | |||
1784 | l = path_get_length (path); | ||
1785 | if (0 == l) | ||
1786 | { | ||
1787 | path_destroy (path); | ||
1788 | return NULL; | ||
1789 | } | ||
1790 | |||
1791 | GNUNET_assert (peer->id == path->peers[path->length - 1]); | ||
1792 | for (aux = peer->path_head; aux != NULL; aux = aux->next) | ||
1793 | { | ||
1794 | l2 = path_get_length (aux); | ||
1795 | if (l2 > l) | ||
1796 | { | ||
1797 | LOG (GNUNET_ERROR_TYPE_DEBUG, " added\n"); | ||
1798 | GNUNET_CONTAINER_DLL_insert_before (peer->path_head, | ||
1799 | peer->path_tail, aux, path); | ||
1800 | if (NULL != peer->tunnel && 3 < GMT_count_connections (peer->tunnel)) | ||
1801 | { | ||
1802 | GMP_connect (peer); | ||
1803 | } | ||
1804 | return path; | ||
1805 | } | ||
1806 | else | ||
1807 | { | ||
1808 | if (l2 == l && memcmp (path->peers, aux->peers, l) == 0) | ||
1809 | { | ||
1810 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already known\n"); | ||
1811 | path_destroy (path); | ||
1812 | return aux; | ||
1813 | } | ||
1814 | } | ||
1815 | } | ||
1816 | GNUNET_CONTAINER_DLL_insert_tail (peer->path_head, peer->path_tail, | ||
1817 | path); | ||
1818 | LOG (GNUNET_ERROR_TYPE_DEBUG, " added last\n"); | ||
1819 | if (NULL != peer->tunnel && 3 < GMT_count_connections (peer->tunnel)) | ||
1820 | { | ||
1821 | GMP_connect (peer); | ||
1822 | } | ||
1823 | return path; | ||
1824 | } | ||
1825 | |||
1826 | |||
1827 | /** | ||
1828 | * Add the path to the origin peer and update the path used to reach it in case | ||
1829 | * this is the shortest. | ||
1830 | * The path is given in peer_info -> destination, therefore we turn the path | ||
1831 | * upside down first. | ||
1832 | * | ||
1833 | * @param peer Peer to add the path to, being the origin of the path. | ||
1834 | * @param path New path to add after being inversed. | ||
1835 | * Path will be either used or freed. | ||
1836 | * @param trusted Do we trust that this path is real? | ||
1837 | * | ||
1838 | * @return path if path was taken, pointer to existing duplicate if exists | ||
1839 | * NULL on error. | ||
1840 | */ | ||
1841 | struct CadetPeerPath * | ||
1842 | GMP_add_path_to_origin (struct CadetPeer *peer, | ||
1843 | struct CadetPeerPath *path, | ||
1844 | int trusted) | ||
1845 | { | ||
1846 | if (NULL == path) | ||
1847 | return NULL; | ||
1848 | path_invert (path); | ||
1849 | return GMP_add_path (peer, path, trusted); | ||
1850 | } | ||
1851 | |||
1852 | |||
1853 | /** | ||
1854 | * Adds a path to the info of all the peers in the path | ||
1855 | * | ||
1856 | * @param p Path to process. | ||
1857 | * @param confirmed Whether we know if the path works or not. | ||
1858 | */ | ||
1859 | void | ||
1860 | GMP_add_path_to_all (const struct CadetPeerPath *p, int confirmed) | ||
1861 | { | ||
1862 | unsigned int i; | ||
1863 | |||
1864 | /* TODO: invert and add */ | ||
1865 | for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ; | ||
1866 | for (i++; i < p->length; i++) | ||
1867 | { | ||
1868 | struct CadetPeer *aux; | ||
1869 | struct CadetPeerPath *copy; | ||
1870 | |||
1871 | aux = GMP_get_short (p->peers[i]); | ||
1872 | copy = path_duplicate (p); | ||
1873 | copy->length = i + 1; | ||
1874 | GMP_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed); | ||
1875 | } | ||
1876 | } | ||
1877 | |||
1878 | |||
1879 | /** | ||
1880 | * Remove any path to the peer that has the extact same peers as the one given. | ||
1881 | * | ||
1882 | * @param peer Peer to remove the path from. | ||
1883 | * @param path Path to remove. Is always destroyed . | ||
1884 | */ | ||
1885 | void | ||
1886 | GMP_remove_path (struct CadetPeer *peer, struct CadetPeerPath *path) | ||
1887 | { | ||
1888 | struct CadetPeerPath *iter; | ||
1889 | struct CadetPeerPath *next; | ||
1890 | |||
1891 | GNUNET_assert (myid == path->peers[0]); | ||
1892 | GNUNET_assert (peer->id == path->peers[path->length - 1]); | ||
1893 | |||
1894 | for (iter = peer->path_head; NULL != iter; iter = next) | ||
1895 | { | ||
1896 | next = iter->next; | ||
1897 | if (0 == memcmp (path->peers, iter->peers, | ||
1898 | sizeof (GNUNET_PEER_Id) * path->length)) | ||
1899 | { | ||
1900 | GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, iter); | ||
1901 | if (iter != path) | ||
1902 | path_destroy (iter); | ||
1903 | } | ||
1904 | } | ||
1905 | path_destroy (path); | ||
1906 | } | ||
1907 | |||
1908 | |||
1909 | /** | ||
1910 | * Remove a connection from a neighboring peer. | ||
1911 | * | ||
1912 | * @param peer Peer to remove connection from. | ||
1913 | * @param c Connection to remove. | ||
1914 | * | ||
1915 | * @return GNUNET_OK on success. | ||
1916 | */ | ||
1917 | int | ||
1918 | GMP_remove_connection (struct CadetPeer *peer, | ||
1919 | const struct CadetConnection *c) | ||
1920 | { | ||
1921 | LOG (GNUNET_ERROR_TYPE_DEBUG, "removing connection %s\n", GMC_2s (c)); | ||
1922 | LOG (GNUNET_ERROR_TYPE_DEBUG, "from peer %s\n", GMP_2s (peer)); | ||
1923 | |||
1924 | if (NULL == peer || NULL == peer->connections) | ||
1925 | { | ||
1926 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1927 | "Peer %s is not a neighbor!\n", | ||
1928 | GMP_2s (peer)); | ||
1929 | return GNUNET_SYSERR; | ||
1930 | } | ||
1931 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1932 | "peer %s ok, has %u connections.\n", | ||
1933 | GMP_2s (peer), GNUNET_CONTAINER_multihashmap_size (peer->connections)); | ||
1934 | |||
1935 | return GNUNET_CONTAINER_multihashmap_remove (peer->connections, | ||
1936 | GMC_get_h (c), | ||
1937 | c); | ||
1938 | } | ||
1939 | |||
1940 | /** | ||
1941 | * Start the DHT search for new paths towards the peer: we don't have | ||
1942 | * enough good connections. | ||
1943 | * | ||
1944 | * @param peer Destination peer. | ||
1945 | */ | ||
1946 | void | ||
1947 | GMP_start_search (struct CadetPeer *peer) | ||
1948 | { | ||
1949 | if (NULL != peer->search_h) | ||
1950 | { | ||
1951 | GNUNET_break (0); | ||
1952 | return; | ||
1953 | } | ||
1954 | |||
1955 | peer->search_h = GMD_search (GMP_get_id (peer), &search_handler, peer); | ||
1956 | } | ||
1957 | |||
1958 | |||
1959 | /** | ||
1960 | * Stop the DHT search for new paths towards the peer: we already have | ||
1961 | * enough good connections. | ||
1962 | * | ||
1963 | * @param peer Destination peer. | ||
1964 | */ | ||
1965 | void | ||
1966 | GMP_stop_search (struct CadetPeer *peer) | ||
1967 | { | ||
1968 | if (NULL == peer->search_h) | ||
1969 | { | ||
1970 | return; | ||
1971 | } | ||
1972 | |||
1973 | GMD_search_stop (peer->search_h); | ||
1974 | peer->search_h = NULL; | ||
1975 | } | ||
1976 | |||
1977 | |||
1978 | /** | ||
1979 | * Get the Full ID of a peer. | ||
1980 | * | ||
1981 | * @param peer Peer to get from. | ||
1982 | * | ||
1983 | * @return Full ID of peer. | ||
1984 | */ | ||
1985 | const struct GNUNET_PeerIdentity * | ||
1986 | GMP_get_id (const struct CadetPeer *peer) | ||
1987 | { | ||
1988 | return GNUNET_PEER_resolve2 (peer->id); | ||
1989 | } | ||
1990 | |||
1991 | |||
1992 | /** | ||
1993 | * Get the Short ID of a peer. | ||
1994 | * | ||
1995 | * @param peer Peer to get from. | ||
1996 | * | ||
1997 | * @return Short ID of peer. | ||
1998 | */ | ||
1999 | GNUNET_PEER_Id | ||
2000 | GMP_get_short_id (const struct CadetPeer *peer) | ||
2001 | { | ||
2002 | return peer->id; | ||
2003 | } | ||
2004 | |||
2005 | |||
2006 | /** | ||
2007 | * Set tunnel. | ||
2008 | * | ||
2009 | * @param peer Peer. | ||
2010 | * @param t Tunnel. | ||
2011 | */ | ||
2012 | void | ||
2013 | GMP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel3 *t) | ||
2014 | { | ||
2015 | peer->tunnel = t; | ||
2016 | if (NULL == t && NULL != peer->search_h) | ||
2017 | { | ||
2018 | GMP_stop_search (peer); | ||
2019 | } | ||
2020 | } | ||
2021 | |||
2022 | |||
2023 | /** | ||
2024 | * Get the tunnel towards a peer. | ||
2025 | * | ||
2026 | * @param peer Peer to get from. | ||
2027 | * | ||
2028 | * @return Tunnel towards peer. | ||
2029 | */ | ||
2030 | struct CadetTunnel3 * | ||
2031 | GMP_get_tunnel (const struct CadetPeer *peer) | ||
2032 | { | ||
2033 | return peer->tunnel; | ||
2034 | } | ||
2035 | |||
2036 | |||
2037 | /** | ||
2038 | * Set the hello message. | ||
2039 | * | ||
2040 | * @param peer Peer whose message to set. | ||
2041 | * @param hello Hello message. | ||
2042 | */ | ||
2043 | void | ||
2044 | GMP_set_hello (struct CadetPeer *peer, const struct GNUNET_HELLO_Message *hello) | ||
2045 | { | ||
2046 | struct GNUNET_HELLO_Message *old; | ||
2047 | size_t size; | ||
2048 | |||
2049 | LOG (GNUNET_ERROR_TYPE_DEBUG, "set hello for %s\n", GMP_2s (peer)); | ||
2050 | if (NULL == hello) | ||
2051 | return; | ||
2052 | |||
2053 | old = GMP_get_hello (peer); | ||
2054 | if (NULL == old) | ||
2055 | { | ||
2056 | size = GNUNET_HELLO_size (hello); | ||
2057 | LOG (GNUNET_ERROR_TYPE_DEBUG, " new (%u bytes)\n", size); | ||
2058 | peer->hello = GNUNET_malloc (size); | ||
2059 | memcpy (peer->hello, hello, size); | ||
2060 | } | ||
2061 | else | ||
2062 | { | ||
2063 | peer->hello = GNUNET_HELLO_merge (old, hello); | ||
2064 | LOG (GNUNET_ERROR_TYPE_DEBUG, " merge into %p (%u bytes)\n", | ||
2065 | peer->hello, GNUNET_HELLO_size (hello)); | ||
2066 | GNUNET_free (old); | ||
2067 | } | ||
2068 | } | ||
2069 | |||
2070 | |||
2071 | /** | ||
2072 | * Get the hello message. | ||
2073 | * | ||
2074 | * @param peer Peer whose message to get. | ||
2075 | * | ||
2076 | * @return Hello message. | ||
2077 | */ | ||
2078 | struct GNUNET_HELLO_Message * | ||
2079 | GMP_get_hello (struct CadetPeer *peer) | ||
2080 | { | ||
2081 | struct GNUNET_TIME_Absolute expiration; | ||
2082 | struct GNUNET_TIME_Relative remaining; | ||
2083 | |||
2084 | if (NULL == peer->hello) | ||
2085 | return NULL; | ||
2086 | |||
2087 | expiration = GNUNET_HELLO_get_last_expiration (peer->hello); | ||
2088 | remaining = GNUNET_TIME_absolute_get_remaining (expiration); | ||
2089 | if (0 == remaining.rel_value_us) | ||
2090 | { | ||
2091 | LOG (GNUNET_ERROR_TYPE_DEBUG, " get - hello expired on %s\n", | ||
2092 | GNUNET_STRINGS_absolute_time_to_string (expiration)); | ||
2093 | GNUNET_free (peer->hello); | ||
2094 | peer->hello = NULL; | ||
2095 | } | ||
2096 | return peer->hello; | ||
2097 | } | ||
2098 | |||
2099 | |||
2100 | /** | ||
2101 | * Try to connect to a peer on TRANSPORT level. | ||
2102 | * | ||
2103 | * @param peer Peer to whom to connect. | ||
2104 | */ | ||
2105 | void | ||
2106 | GMP_try_connect (struct CadetPeer *peer) | ||
2107 | { | ||
2108 | struct GNUNET_HELLO_Message *hello; | ||
2109 | struct GNUNET_MessageHeader *mh; | ||
2110 | |||
2111 | if (NULL == transport_handle) | ||
2112 | return; | ||
2113 | |||
2114 | hello = GMP_get_hello (peer); | ||
2115 | if (NULL == hello) | ||
2116 | return; | ||
2117 | |||
2118 | mh = GNUNET_HELLO_get_header (hello); | ||
2119 | GNUNET_TRANSPORT_offer_hello (transport_handle, mh, try_connect, peer); | ||
2120 | } | ||
2121 | |||
2122 | |||
2123 | /** | ||
2124 | * Notify a peer that a link between two other peers is broken. If any path | ||
2125 | * used that link, eliminate it. | ||
2126 | * | ||
2127 | * @param peer Peer affected by the change. | ||
2128 | * @param peer1 Peer whose link is broken. | ||
2129 | * @param peer2 Peer whose link is broken. | ||
2130 | */ | ||
2131 | void | ||
2132 | GMP_notify_broken_link (struct CadetPeer *peer, | ||
2133 | struct GNUNET_PeerIdentity *peer1, | ||
2134 | struct GNUNET_PeerIdentity *peer2) | ||
2135 | { | ||
2136 | struct CadetPeerPath *iter; | ||
2137 | struct CadetPeerPath *next; | ||
2138 | unsigned int i; | ||
2139 | GNUNET_PEER_Id p1; | ||
2140 | GNUNET_PEER_Id p2; | ||
2141 | |||
2142 | p1 = GNUNET_PEER_search (peer1); | ||
2143 | p2 = GNUNET_PEER_search (peer2); | ||
2144 | |||
2145 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Link %u-%u broken\n", p1, p2); | ||
2146 | if (0 == p1 || 0 == p2) | ||
2147 | { | ||
2148 | /* We don't even know them */ | ||
2149 | return; | ||
2150 | } | ||
2151 | |||
2152 | for (iter = peer->path_head; NULL != iter; iter = next) | ||
2153 | { | ||
2154 | next = iter->next; | ||
2155 | for (i = 0; i < iter->length - 1; i++) | ||
2156 | { | ||
2157 | if ((iter->peers[i] == p1 && iter->peers[i + 1] == p2) | ||
2158 | || (iter->peers[i] == p2 && iter->peers[i + 1] == p1)) | ||
2159 | { | ||
2160 | char *s; | ||
2161 | |||
2162 | s = path_2s (iter); | ||
2163 | LOG (GNUNET_ERROR_TYPE_DEBUG, " - invalidating %s\n", s); | ||
2164 | GNUNET_free (s); | ||
2165 | |||
2166 | path_invalidate (iter); | ||
2167 | } | ||
2168 | } | ||
2169 | } | ||
2170 | } | ||
2171 | |||
2172 | |||
2173 | /** | ||
2174 | * Count the number of known paths toward the peer. | ||
2175 | * | ||
2176 | * @param peer Peer to get path info. | ||
2177 | * | ||
2178 | * @return Number of known paths. | ||
2179 | */ | ||
2180 | unsigned int | ||
2181 | GMP_count_paths (const struct CadetPeer *peer) | ||
2182 | { | ||
2183 | struct CadetPeerPath *iter; | ||
2184 | unsigned int i; | ||
2185 | |||
2186 | for (iter = peer->path_head, i = 0; NULL != iter; iter = iter->next) | ||
2187 | i++; | ||
2188 | |||
2189 | return i; | ||
2190 | } | ||
2191 | |||
2192 | |||
2193 | /** | ||
2194 | * Iterate all known peers. | ||
2195 | * | ||
2196 | * @param iter Iterator. | ||
2197 | * @param cls Closure for @c iter. | ||
2198 | */ | ||
2199 | void | ||
2200 | GMP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls) | ||
2201 | { | ||
2202 | GNUNET_CONTAINER_multipeermap_iterate (peers, iter, cls); | ||
2203 | } | ||
2204 | |||
2205 | |||
2206 | /** | ||
2207 | * Get the static string for a peer ID. | ||
2208 | * | ||
2209 | * @param peer Peer. | ||
2210 | * | ||
2211 | * @return Static string for it's ID. | ||
2212 | */ | ||
2213 | const char * | ||
2214 | GMP_2s (const struct CadetPeer *peer) | ||
2215 | { | ||
2216 | if (NULL == peer) | ||
2217 | return "(NULL)"; | ||
2218 | return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id)); | ||
2219 | } | ||
diff --git a/src/cadet/gnunet-service-cadet_peer.h b/src/cadet/gnunet-service-cadet_peer.h new file mode 100644 index 000000000..9f1146e9f --- /dev/null +++ b/src/cadet/gnunet-service-cadet_peer.h | |||
@@ -0,0 +1,418 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file cadet/gnunet-service-cadet_peer.h | ||
23 | * @brief cadet service; dealing with remote peers | ||
24 | * @author Bartlomiej Polot | ||
25 | * | ||
26 | * All functions in this file should use the prefix GMP (Gnunet Cadet Peer) | ||
27 | */ | ||
28 | |||
29 | #ifndef GNUNET_SERVICE_CADET_PEER_H | ||
30 | #define GNUNET_SERVICE_CADET_PEER_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 all information regarding a given peer | ||
45 | */ | ||
46 | struct CadetPeer; | ||
47 | |||
48 | /** | ||
49 | * Struct containing info about a queued transmission to this peer | ||
50 | */ | ||
51 | struct CadetPeerQueue; | ||
52 | |||
53 | #include "gnunet-service-cadet_connection.h" | ||
54 | |||
55 | /** | ||
56 | * Callback called when a queued message is sent. | ||
57 | * | ||
58 | * @param cls Closure. | ||
59 | * @param c Connection this message was on. | ||
60 | * @param sent Was it really sent? (Could have been canceled) | ||
61 | * @param type Type of message sent. | ||
62 | * @param pid Packet ID, or 0 if not applicable (create, destroy, etc). | ||
63 | * @param fwd Was this a FWD going message? | ||
64 | * @param size Size of the message. | ||
65 | * @param wait Time spent waiting for core (only the time for THIS message) | ||
66 | */ | ||
67 | typedef void (*GMP_sent) (void *cls, | ||
68 | struct CadetConnection *c, int sent, | ||
69 | uint16_t type, uint32_t pid, int fwd, size_t size, | ||
70 | struct GNUNET_TIME_Relative wait); | ||
71 | |||
72 | /******************************************************************************/ | ||
73 | /******************************** API ***********************************/ | ||
74 | /******************************************************************************/ | ||
75 | |||
76 | /** | ||
77 | * Initialize peer subsystem. | ||
78 | * | ||
79 | * @param c Configuration. | ||
80 | */ | ||
81 | void | ||
82 | GMP_init (const struct GNUNET_CONFIGURATION_Handle *c); | ||
83 | |||
84 | /** | ||
85 | * Shut down the peer subsystem. | ||
86 | */ | ||
87 | void | ||
88 | GMP_shutdown (void); | ||
89 | |||
90 | |||
91 | /** | ||
92 | * Retrieve the CadetPeer stucture associated with the peer, create one | ||
93 | * and insert it in the appropriate structures if the peer is not known yet. | ||
94 | * | ||
95 | * @param peer_id Full identity of the peer. | ||
96 | * | ||
97 | * @return Existing or newly created peer structure. | ||
98 | */ | ||
99 | struct CadetPeer * | ||
100 | GMP_get (const struct GNUNET_PeerIdentity *peer_id); | ||
101 | |||
102 | |||
103 | /** | ||
104 | * Retrieve the CadetPeer stucture associated with the peer, create one | ||
105 | * and insert it in the appropriate structures if the peer is not known yet. | ||
106 | * | ||
107 | * @param peer Short identity of the peer. | ||
108 | * | ||
109 | * @return Existing or newly created peer structure. | ||
110 | */ | ||
111 | struct CadetPeer * | ||
112 | GMP_get_short (const GNUNET_PEER_Id peer); | ||
113 | |||
114 | /** | ||
115 | * Try to establish a new connection to this peer (in its tunnel). | ||
116 | * If the peer doesn't have any path to it yet, try to get one. | ||
117 | * If the peer already has some path, send a CREATE CONNECTION towards it. | ||
118 | * | ||
119 | * @param peer Peer to connect to. | ||
120 | */ | ||
121 | void | ||
122 | GMP_connect (struct CadetPeer *peer); | ||
123 | |||
124 | /** | ||
125 | * Free a transmission that was already queued with all resources | ||
126 | * associated to the request. | ||
127 | * | ||
128 | * @param queue Queue handler to cancel. | ||
129 | * @param clear_cls Is it necessary to free associated cls? | ||
130 | * @param sent Was it really sent? (Could have been canceled) | ||
131 | * @param pid PID, if relevant (was sent and was a payload message). | ||
132 | */ | ||
133 | void | ||
134 | GMP_queue_destroy (struct CadetPeerQueue *queue, int clear_cls, | ||
135 | int sent, uint32_t pid); | ||
136 | |||
137 | /** | ||
138 | * @brief Queue and pass message to core when possible. | ||
139 | * | ||
140 | * @param peer Peer towards which to queue the message. | ||
141 | * @param cls Closure (@c type dependant). It will be used by queue_send to | ||
142 | * build the message to be sent if not already prebuilt. | ||
143 | * @param type Type of the message, 0 for a raw message. | ||
144 | * @param size Size of the message. | ||
145 | * @param c Connection this message belongs to (cannot be NULL). | ||
146 | * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!) | ||
147 | * @param cont Continuation to be called once CORE has taken the message. | ||
148 | * @param cont_cls Closure for @c cont. | ||
149 | * | ||
150 | * @return Handle to cancel the message before it is sent. Once cont is called | ||
151 | * message has been sent and therefore the handle is no longer valid. | ||
152 | */ | ||
153 | struct CadetPeerQueue * | ||
154 | GMP_queue_add (struct CadetPeer *peer, void *cls, uint16_t type, | ||
155 | uint16_t payload_type, uint32_t payload_id, | ||
156 | size_t size, struct CadetConnection *c, int fwd, | ||
157 | GMP_sent cont, void *cont_cls); | ||
158 | |||
159 | /** | ||
160 | * Cancel all queued messages to a peer that belong to a certain connection. | ||
161 | * | ||
162 | * @param peer Peer towards whom to cancel. | ||
163 | * @param c Connection whose queued messages to cancel. Might be destroyed by | ||
164 | * the sent continuation call. | ||
165 | */ | ||
166 | void | ||
167 | GMP_queue_cancel (struct CadetPeer *peer, struct CadetConnection *c); | ||
168 | |||
169 | /** | ||
170 | * Get the first message for a connection and unqueue it. | ||
171 | * | ||
172 | * @param peer Neighboring peer. | ||
173 | * @param c Connection. | ||
174 | * | ||
175 | * @return First message for this connection. | ||
176 | */ | ||
177 | struct GNUNET_MessageHeader * | ||
178 | GMP_connection_pop (struct CadetPeer *peer, struct CadetConnection *c); | ||
179 | |||
180 | void | ||
181 | GMP_queue_unlock (struct CadetPeer *peer, struct CadetConnection *c); | ||
182 | |||
183 | /** | ||
184 | * Set tunnel. | ||
185 | * | ||
186 | * @param peer Peer. | ||
187 | * @param t Tunnel. | ||
188 | */ | ||
189 | void | ||
190 | GMP_set_tunnel (struct CadetPeer *peer, struct CadetTunnel3 *t); | ||
191 | |||
192 | /** | ||
193 | * Check whether there is a direct (core level) connection to peer. | ||
194 | * | ||
195 | * @param peer Peer to check. | ||
196 | * | ||
197 | * @return #GNUNET_YES if there is a direct connection. | ||
198 | */ | ||
199 | int | ||
200 | GMP_is_neighbor (const struct CadetPeer *peer); | ||
201 | |||
202 | /** | ||
203 | * Create and initialize a new tunnel towards a peer, in case it has none. | ||
204 | * | ||
205 | * Does not generate any traffic, just creates the local data structures. | ||
206 | * | ||
207 | * @param peer Peer towards which to create the tunnel. | ||
208 | */ | ||
209 | void | ||
210 | GMP_add_tunnel (struct CadetPeer *peer); | ||
211 | |||
212 | /** | ||
213 | * Add a connection to a neighboring peer. | ||
214 | * | ||
215 | * Store that the peer is the first hop of the connection in one | ||
216 | * direction and that on peer disconnect the connection must be | ||
217 | * notified and destroyed, for it will no longer be valid. | ||
218 | * | ||
219 | * @param peer Peer to add connection to. | ||
220 | * @param c Connection to add. | ||
221 | * | ||
222 | * @return GNUNET_OK on success. | ||
223 | */ | ||
224 | int | ||
225 | GMP_add_connection (struct CadetPeer *peer, struct CadetConnection *c); | ||
226 | |||
227 | /** | ||
228 | * Add the path to the peer and update the path used to reach it in case this | ||
229 | * is the shortest. | ||
230 | * | ||
231 | * @param peer Destination peer to add the path to. | ||
232 | * @param path New path to add. Last peer must be the peer in arg 1. | ||
233 | * Path will be either used of freed if already known. | ||
234 | * @param trusted Do we trust that this path is real? | ||
235 | * | ||
236 | * @return path if path was taken, pointer to existing duplicate if exists | ||
237 | * NULL on error. | ||
238 | */ | ||
239 | struct CadetPeerPath * | ||
240 | GMP_add_path (struct CadetPeer *peer, struct CadetPeerPath *p, int trusted); | ||
241 | |||
242 | /** | ||
243 | * Add the path to the origin peer and update the path used to reach it in case | ||
244 | * this is the shortest. | ||
245 | * The path is given in peer_info -> destination, therefore we turn the path | ||
246 | * upside down first. | ||
247 | * | ||
248 | * @param peer Peer to add the path to, being the origin of the path. | ||
249 | * @param path New path to add after being inversed. | ||
250 | * Path will be either used or freed. | ||
251 | * @param trusted Do we trust that this path is real? | ||
252 | * | ||
253 | * @return path if path was taken, pointer to existing duplicate if exists | ||
254 | * NULL on error. | ||
255 | */ | ||
256 | struct CadetPeerPath * | ||
257 | GMP_add_path_to_origin (struct CadetPeer *peer, | ||
258 | struct CadetPeerPath *path, | ||
259 | int trusted); | ||
260 | |||
261 | /** | ||
262 | * Adds a path to the info of all the peers in the path | ||
263 | * | ||
264 | * @param p Path to process. | ||
265 | * @param confirmed Whether we know if the path works or not. | ||
266 | */ | ||
267 | void | ||
268 | GMP_add_path_to_all (const struct CadetPeerPath *p, int confirmed); | ||
269 | |||
270 | /** | ||
271 | * Remove any path to the peer that has the extact same peers as the one given. | ||
272 | * | ||
273 | * @param peer Peer to remove the path from. | ||
274 | * @param path Path to remove. Is always destroyed . | ||
275 | */ | ||
276 | void | ||
277 | GMP_remove_path (struct CadetPeer *peer, struct CadetPeerPath *path); | ||
278 | |||
279 | /** | ||
280 | * Remove a connection from a neighboring peer. | ||
281 | * | ||
282 | * @param peer Peer to remove connection from. | ||
283 | * @param c Connection to remove. | ||
284 | * | ||
285 | * @return GNUNET_OK on success. | ||
286 | */ | ||
287 | int | ||
288 | GMP_remove_connection (struct CadetPeer *peer, const struct CadetConnection *c); | ||
289 | |||
290 | /** | ||
291 | * Start the DHT search for new paths towards the peer: we don't have | ||
292 | * enough good connections. | ||
293 | * | ||
294 | * @param peer Destination peer. | ||
295 | */ | ||
296 | void | ||
297 | GMP_start_search (struct CadetPeer *peer); | ||
298 | |||
299 | /** | ||
300 | * Stop the DHT search for new paths towards the peer: we already have | ||
301 | * enough good connections. | ||
302 | * | ||
303 | * @param peer Destination peer. | ||
304 | */ | ||
305 | void | ||
306 | GMP_stop_search (struct CadetPeer *peer); | ||
307 | |||
308 | /** | ||
309 | * Get the Full ID of a peer. | ||
310 | * | ||
311 | * @param peer Peer to get from. | ||
312 | * | ||
313 | * @return Full ID of peer. | ||
314 | */ | ||
315 | const struct GNUNET_PeerIdentity * | ||
316 | GMP_get_id (const struct CadetPeer *peer); | ||
317 | |||
318 | /** | ||
319 | * Get the Short ID of a peer. | ||
320 | * | ||
321 | * @param peer Peer to get from. | ||
322 | * | ||
323 | * @return Short ID of peer. | ||
324 | */ | ||
325 | GNUNET_PEER_Id | ||
326 | GMP_get_short_id (const struct CadetPeer *peer); | ||
327 | |||
328 | /** | ||
329 | * Get the tunnel towards a peer. | ||
330 | * | ||
331 | * @param peer Peer to get from. | ||
332 | * | ||
333 | * @return Tunnel towards peer. | ||
334 | */ | ||
335 | struct CadetTunnel3 * | ||
336 | GMP_get_tunnel (const struct CadetPeer *peer); | ||
337 | |||
338 | /** | ||
339 | * Set the hello message. | ||
340 | * | ||
341 | * @param peer Peer whose message to set. | ||
342 | * @param hello Hello message. | ||
343 | */ | ||
344 | void | ||
345 | GMP_set_hello (struct CadetPeer *peer, const struct GNUNET_HELLO_Message *hello); | ||
346 | |||
347 | /** | ||
348 | * Get the hello message. | ||
349 | * | ||
350 | * @param peer Peer whose message to get. | ||
351 | * | ||
352 | * @return Hello message. | ||
353 | */ | ||
354 | struct GNUNET_HELLO_Message * | ||
355 | GMP_get_hello (struct CadetPeer *peer); | ||
356 | |||
357 | |||
358 | /** | ||
359 | * Try to connect to a peer on TRANSPORT level. | ||
360 | * | ||
361 | * @param peer Peer to whom to connect. | ||
362 | */ | ||
363 | void | ||
364 | GMP_try_connect (struct CadetPeer *peer); | ||
365 | |||
366 | /** | ||
367 | * Notify a peer that a link between two other peers is broken. If any path | ||
368 | * used that link, eliminate it. | ||
369 | * | ||
370 | * @param peer Peer affected by the change. | ||
371 | * @param peer1 Peer whose link is broken. | ||
372 | * @param peer2 Peer whose link is broken. | ||
373 | */ | ||
374 | void | ||
375 | GMP_notify_broken_link (struct CadetPeer *peer, | ||
376 | struct GNUNET_PeerIdentity *peer1, | ||
377 | struct GNUNET_PeerIdentity *peer2); | ||
378 | |||
379 | /** | ||
380 | * Count the number of known paths toward the peer. | ||
381 | * | ||
382 | * @param peer Peer to get path info. | ||
383 | * | ||
384 | * @return Number of known paths. | ||
385 | */ | ||
386 | unsigned int | ||
387 | GMP_count_paths (const struct CadetPeer *peer); | ||
388 | |||
389 | /** | ||
390 | * Iterate all known peers. | ||
391 | * | ||
392 | * @param iter Iterator. | ||
393 | * @param cls Closure for @c iter. | ||
394 | */ | ||
395 | void | ||
396 | GMP_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls); | ||
397 | |||
398 | /** | ||
399 | * Get the static string for a peer ID. | ||
400 | * | ||
401 | * @param peer Peer. | ||
402 | * | ||
403 | * @return Static string for it's ID. | ||
404 | */ | ||
405 | const char * | ||
406 | GMP_2s (const struct CadetPeer *peer); | ||
407 | |||
408 | |||
409 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
410 | { | ||
411 | #endif | ||
412 | #ifdef __cplusplus | ||
413 | } | ||
414 | #endif | ||
415 | |||
416 | /* ifndef GNUNET_CADET_SERVICE_PEER_H */ | ||
417 | #endif | ||
418 | /* 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 new file mode 100644 index 000000000..f2be27bf5 --- /dev/null +++ b/src/cadet/gnunet-service-cadet_tunnel.c | |||
@@ -0,0 +1,2887 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #include "platform.h" | ||
22 | #include "gnunet_util_lib.h" | ||
23 | |||
24 | #include "gnunet_signatures.h" | ||
25 | #include "gnunet_statistics_service.h" | ||
26 | |||
27 | #include "cadet_protocol.h" | ||
28 | #include "cadet_path.h" | ||
29 | |||
30 | #include "gnunet-service-cadet_tunnel.h" | ||
31 | #include "gnunet-service-cadet_connection.h" | ||
32 | #include "gnunet-service-cadet_channel.h" | ||
33 | #include "gnunet-service-cadet_peer.h" | ||
34 | |||
35 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__) | ||
36 | |||
37 | #define REKEY_WAIT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5) | ||
38 | |||
39 | #define CONNECTIONS_PER_TUNNEL 3 | ||
40 | |||
41 | /******************************************************************************/ | ||
42 | /******************************** STRUCTS **********************************/ | ||
43 | /******************************************************************************/ | ||
44 | |||
45 | struct CadetTChannel | ||
46 | { | ||
47 | struct CadetTChannel *next; | ||
48 | struct CadetTChannel *prev; | ||
49 | struct CadetChannel *ch; | ||
50 | }; | ||
51 | |||
52 | |||
53 | /** | ||
54 | * Connection list and metadata. | ||
55 | */ | ||
56 | struct CadetTConnection | ||
57 | { | ||
58 | /** | ||
59 | * Next in DLL. | ||
60 | */ | ||
61 | struct CadetTConnection *next; | ||
62 | |||
63 | /** | ||
64 | * Prev in DLL. | ||
65 | */ | ||
66 | struct CadetTConnection *prev; | ||
67 | |||
68 | /** | ||
69 | * Connection handle. | ||
70 | */ | ||
71 | struct CadetConnection *c; | ||
72 | |||
73 | /** | ||
74 | * Creation time, to keep oldest connection alive. | ||
75 | */ | ||
76 | struct GNUNET_TIME_Absolute created; | ||
77 | |||
78 | /** | ||
79 | * Connection throughput, to keep fastest connection alive. | ||
80 | */ | ||
81 | uint32_t throughput; | ||
82 | }; | ||
83 | |||
84 | /** | ||
85 | * Structure used during a Key eXchange. | ||
86 | */ | ||
87 | struct CadetTunnelKXCtx | ||
88 | { | ||
89 | /** | ||
90 | * Decryption ("their") old key, for decrypting traffic sent by the | ||
91 | * other end before the key exchange started. | ||
92 | */ | ||
93 | struct GNUNET_CRYPTO_SymmetricSessionKey d_key_old; | ||
94 | |||
95 | /** | ||
96 | * Challenge to send in a ping and expect in the pong. | ||
97 | */ | ||
98 | uint32_t challenge; | ||
99 | }; | ||
100 | |||
101 | /** | ||
102 | * Struct containing all information regarding a tunnel to a peer. | ||
103 | */ | ||
104 | struct CadetTunnel3 | ||
105 | { | ||
106 | /** | ||
107 | * Endpoint of the tunnel. | ||
108 | */ | ||
109 | struct CadetPeer *peer; | ||
110 | |||
111 | /** | ||
112 | * State of the tunnel connectivity. | ||
113 | */ | ||
114 | enum CadetTunnel3CState cstate; | ||
115 | |||
116 | /** | ||
117 | * State of the tunnel encryption. | ||
118 | */ | ||
119 | enum CadetTunnel3EState estate; | ||
120 | |||
121 | /** | ||
122 | * Key eXchange context. | ||
123 | */ | ||
124 | struct CadetTunnelKXCtx *kx_ctx; | ||
125 | |||
126 | /** | ||
127 | * Encryption ("our") key. | ||
128 | */ | ||
129 | struct GNUNET_CRYPTO_SymmetricSessionKey e_key; | ||
130 | |||
131 | /** | ||
132 | * Decryption ("their") key. | ||
133 | */ | ||
134 | struct GNUNET_CRYPTO_SymmetricSessionKey d_key; | ||
135 | |||
136 | /** | ||
137 | * Task to start the rekey process. | ||
138 | */ | ||
139 | GNUNET_SCHEDULER_TaskIdentifier rekey_task; | ||
140 | |||
141 | /** | ||
142 | * Paths that are actively used to reach the destination peer. | ||
143 | */ | ||
144 | struct CadetTConnection *connection_head; | ||
145 | struct CadetTConnection *connection_tail; | ||
146 | |||
147 | /** | ||
148 | * Next connection number. | ||
149 | */ | ||
150 | uint32_t next_cid; | ||
151 | |||
152 | /** | ||
153 | * Channels inside this tunnel. | ||
154 | */ | ||
155 | struct CadetTChannel *channel_head; | ||
156 | struct CadetTChannel *channel_tail; | ||
157 | |||
158 | /** | ||
159 | * Channel ID for the next created channel. | ||
160 | */ | ||
161 | CADET_ChannelNumber next_chid; | ||
162 | |||
163 | /** | ||
164 | * Destroy flag: if true, destroy on last message. | ||
165 | */ | ||
166 | GNUNET_SCHEDULER_TaskIdentifier destroy_task; | ||
167 | |||
168 | /** | ||
169 | * Queued messages, to transmit once tunnel gets connected. | ||
170 | */ | ||
171 | struct CadetTunnelDelayed *tq_head; | ||
172 | struct CadetTunnelDelayed *tq_tail; | ||
173 | }; | ||
174 | |||
175 | |||
176 | /** | ||
177 | * Struct used to save messages in a non-ready tunnel to send once connected. | ||
178 | */ | ||
179 | struct CadetTunnelDelayed | ||
180 | { | ||
181 | /** | ||
182 | * DLL | ||
183 | */ | ||
184 | struct CadetTunnelDelayed *next; | ||
185 | struct CadetTunnelDelayed *prev; | ||
186 | |||
187 | /** | ||
188 | * Tunnel. | ||
189 | */ | ||
190 | struct CadetTunnel3 *t; | ||
191 | |||
192 | /** | ||
193 | * Tunnel queue given to the channel to cancel request. Update on send_queued. | ||
194 | */ | ||
195 | struct CadetTunnel3Queue *tq; | ||
196 | |||
197 | /** | ||
198 | * Message to send. | ||
199 | */ | ||
200 | /* struct GNUNET_MessageHeader *msg; */ | ||
201 | }; | ||
202 | |||
203 | |||
204 | /** | ||
205 | * Handle for messages queued but not yet sent. | ||
206 | */ | ||
207 | struct CadetTunnel3Queue | ||
208 | { | ||
209 | /** | ||
210 | * Connection queue handle, to cancel if necessary. | ||
211 | */ | ||
212 | struct CadetConnectionQueue *cq; | ||
213 | |||
214 | /** | ||
215 | * Handle in case message hasn't been given to a connection yet. | ||
216 | */ | ||
217 | struct CadetTunnelDelayed *tqd; | ||
218 | |||
219 | /** | ||
220 | * Continuation to call once sent. | ||
221 | */ | ||
222 | GMT_sent cont; | ||
223 | |||
224 | /** | ||
225 | * Closure for @c cont. | ||
226 | */ | ||
227 | void *cont_cls; | ||
228 | }; | ||
229 | |||
230 | |||
231 | /******************************************************************************/ | ||
232 | /******************************* GLOBALS ***********************************/ | ||
233 | /******************************************************************************/ | ||
234 | |||
235 | /** | ||
236 | * Global handle to the statistics service. | ||
237 | */ | ||
238 | extern struct GNUNET_STATISTICS_Handle *stats; | ||
239 | |||
240 | /** | ||
241 | * Local peer own ID (memory efficient handle). | ||
242 | */ | ||
243 | extern GNUNET_PEER_Id myid; | ||
244 | |||
245 | /** | ||
246 | * Local peer own ID (full value). | ||
247 | */ | ||
248 | extern struct GNUNET_PeerIdentity my_full_id; | ||
249 | |||
250 | |||
251 | /** | ||
252 | * Don't try to recover tunnels if shutting down. | ||
253 | */ | ||
254 | extern int shutting_down; | ||
255 | |||
256 | |||
257 | /** | ||
258 | * Set of all tunnels, in order to trigger a new exchange on rekey. | ||
259 | * Indexed by peer's ID. | ||
260 | */ | ||
261 | static struct GNUNET_CONTAINER_MultiPeerMap *tunnels; | ||
262 | |||
263 | /** | ||
264 | * Default TTL for payload packets. | ||
265 | */ | ||
266 | static unsigned long long default_ttl; | ||
267 | |||
268 | /** | ||
269 | * Own private key. | ||
270 | */ | ||
271 | const static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key; | ||
272 | |||
273 | /** | ||
274 | * Own ephemeral private key. | ||
275 | */ | ||
276 | static struct GNUNET_CRYPTO_EcdhePrivateKey *my_ephemeral_key; | ||
277 | |||
278 | /** | ||
279 | * Cached message used to perform a key exchange. | ||
280 | */ | ||
281 | static struct GNUNET_CADET_KX_Ephemeral kx_msg; | ||
282 | |||
283 | /** | ||
284 | * Task to generate a new ephemeral key. | ||
285 | */ | ||
286 | static GNUNET_SCHEDULER_TaskIdentifier rekey_task; | ||
287 | |||
288 | /** | ||
289 | * Rekey period. | ||
290 | */ | ||
291 | static struct GNUNET_TIME_Relative rekey_period; | ||
292 | |||
293 | /******************************************************************************/ | ||
294 | /******************************** STATIC ***********************************/ | ||
295 | /******************************************************************************/ | ||
296 | |||
297 | /** | ||
298 | * Get string description for tunnel connectivity state. | ||
299 | * | ||
300 | * @param cs Tunnel state. | ||
301 | * | ||
302 | * @return String representation. | ||
303 | */ | ||
304 | static const char * | ||
305 | cstate2s (enum CadetTunnel3CState cs) | ||
306 | { | ||
307 | static char buf[128]; | ||
308 | |||
309 | switch (cs) | ||
310 | { | ||
311 | case CADET_TUNNEL3_NEW: | ||
312 | return "CADET_TUNNEL3_NEW"; | ||
313 | case CADET_TUNNEL3_SEARCHING: | ||
314 | return "CADET_TUNNEL3_SEARCHING"; | ||
315 | case CADET_TUNNEL3_WAITING: | ||
316 | return "CADET_TUNNEL3_WAITING"; | ||
317 | case CADET_TUNNEL3_READY: | ||
318 | return "CADET_TUNNEL3_READY"; | ||
319 | |||
320 | default: | ||
321 | sprintf (buf, "%u (UNKNOWN STATE)", cs); | ||
322 | return buf; | ||
323 | } | ||
324 | return ""; | ||
325 | } | ||
326 | |||
327 | |||
328 | /** | ||
329 | * Get string description for tunnel encryption state. | ||
330 | * | ||
331 | * @param es Tunnel state. | ||
332 | * | ||
333 | * @return String representation. | ||
334 | */ | ||
335 | static const char * | ||
336 | estate2s (enum CadetTunnel3EState es) | ||
337 | { | ||
338 | static char buf[128]; | ||
339 | |||
340 | switch (es) | ||
341 | { | ||
342 | case CADET_TUNNEL3_KEY_UNINITIALIZED: | ||
343 | return "CADET_TUNNEL3_KEY_UNINITIALIZED"; | ||
344 | case CADET_TUNNEL3_KEY_SENT: | ||
345 | return "CADET_TUNNEL3_KEY_SENT"; | ||
346 | case CADET_TUNNEL3_KEY_PING: | ||
347 | return "CADET_TUNNEL3_KEY_PING"; | ||
348 | case CADET_TUNNEL3_KEY_OK: | ||
349 | return "CADET_TUNNEL3_KEY_OK"; | ||
350 | |||
351 | default: | ||
352 | sprintf (buf, "%u (UNKNOWN STATE)", es); | ||
353 | return buf; | ||
354 | } | ||
355 | return ""; | ||
356 | } | ||
357 | |||
358 | |||
359 | /** | ||
360 | * @brief Check if tunnel is ready to send traffic. | ||
361 | * | ||
362 | * Tunnel must be connected and with encryption correctly set up. | ||
363 | * | ||
364 | * @param t Tunnel to check. | ||
365 | * | ||
366 | * @return #GNUNET_YES if ready, #GNUNET_NO otherwise | ||
367 | */ | ||
368 | static int | ||
369 | is_ready (struct CadetTunnel3 *t) | ||
370 | { | ||
371 | int ready; | ||
372 | |||
373 | GMT_debug (t); | ||
374 | ready = (CADET_TUNNEL3_READY == t->cstate && CADET_TUNNEL3_KEY_OK == t->estate); | ||
375 | ready = ready || GMT_is_loopback (t); | ||
376 | return ready; | ||
377 | } | ||
378 | |||
379 | |||
380 | /** | ||
381 | * Ephemeral key message purpose size. | ||
382 | * | ||
383 | * @return Size of the part of the ephemeral key message that must be signed. | ||
384 | */ | ||
385 | size_t | ||
386 | ephemeral_purpose_size (void) | ||
387 | { | ||
388 | return sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
389 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + | ||
390 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + | ||
391 | sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + | ||
392 | sizeof (struct GNUNET_PeerIdentity); | ||
393 | } | ||
394 | |||
395 | |||
396 | /** | ||
397 | * Size of the encrypted part of a ping message. | ||
398 | * | ||
399 | * @return Size of the encrypted part of a ping message. | ||
400 | */ | ||
401 | size_t | ||
402 | ping_encryption_size (void) | ||
403 | { | ||
404 | return sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t); | ||
405 | } | ||
406 | |||
407 | |||
408 | /** | ||
409 | * Get the channel's buffer. ONLY FOR NON-LOOPBACK CHANNELS!! | ||
410 | * | ||
411 | * @param tch Tunnel's channel handle. | ||
412 | * | ||
413 | * @return Amount of messages the channel can still buffer towards the client. | ||
414 | */ | ||
415 | static unsigned int | ||
416 | get_channel_buffer (const struct CadetTChannel *tch) | ||
417 | { | ||
418 | int fwd; | ||
419 | |||
420 | /* If channel is outgoing, is origin in the FWD direction and fwd is YES */ | ||
421 | fwd = GMCH_is_origin (tch->ch, GNUNET_YES); | ||
422 | |||
423 | return GMCH_get_buffer (tch->ch, fwd); | ||
424 | } | ||
425 | |||
426 | |||
427 | /** | ||
428 | * Get the channel's allowance status. | ||
429 | * | ||
430 | * @param tch Tunnel's channel handle. | ||
431 | * | ||
432 | * @return #GNUNET_YES if we allowed the client to send data to us. | ||
433 | */ | ||
434 | static int | ||
435 | get_channel_allowed (const struct CadetTChannel *tch) | ||
436 | { | ||
437 | int fwd; | ||
438 | |||
439 | /* If channel is outgoing, is origin in the FWD direction and fwd is YES */ | ||
440 | fwd = GMCH_is_origin (tch->ch, GNUNET_YES); | ||
441 | |||
442 | return GMCH_get_allowed (tch->ch, fwd); | ||
443 | } | ||
444 | |||
445 | |||
446 | /** | ||
447 | * Get the connection's buffer. | ||
448 | * | ||
449 | * @param tc Tunnel's connection handle. | ||
450 | * | ||
451 | * @return Amount of messages the connection can still buffer. | ||
452 | */ | ||
453 | static unsigned int | ||
454 | get_connection_buffer (const struct CadetTConnection *tc) | ||
455 | { | ||
456 | int fwd; | ||
457 | |||
458 | /* If connection is outgoing, is origin in the FWD direction and fwd is YES */ | ||
459 | fwd = GMC_is_origin (tc->c, GNUNET_YES); | ||
460 | |||
461 | return GMC_get_buffer (tc->c, fwd); | ||
462 | } | ||
463 | |||
464 | |||
465 | /** | ||
466 | * Get the connection's allowance. | ||
467 | * | ||
468 | * @param tc Tunnel's connection handle. | ||
469 | * | ||
470 | * @return Amount of messages we have allowed the next peer to send us. | ||
471 | */ | ||
472 | static unsigned int | ||
473 | get_connection_allowed (const struct CadetTConnection *tc) | ||
474 | { | ||
475 | int fwd; | ||
476 | |||
477 | /* If connection is outgoing, is origin in the FWD direction and fwd is YES */ | ||
478 | fwd = GMC_is_origin (tc->c, GNUNET_YES); | ||
479 | |||
480 | return GMC_get_allowed (tc->c, fwd); | ||
481 | } | ||
482 | |||
483 | |||
484 | /** | ||
485 | * Check that a ephemeral key message s well formed and correctly signed. | ||
486 | * | ||
487 | * @param t Tunnel on which the message came. | ||
488 | * @param msg The ephemeral key message. | ||
489 | * | ||
490 | * @return GNUNET_OK if message is fine, GNUNET_SYSERR otherwise. | ||
491 | */ | ||
492 | int | ||
493 | check_ephemeral (struct CadetTunnel3 *t, | ||
494 | const struct GNUNET_CADET_KX_Ephemeral *msg) | ||
495 | { | ||
496 | /* Check message size */ | ||
497 | if (ntohs (msg->header.size) != sizeof (struct GNUNET_CADET_KX_Ephemeral)) | ||
498 | return GNUNET_SYSERR; | ||
499 | |||
500 | /* Check signature size */ | ||
501 | if (ntohl (msg->purpose.size) != ephemeral_purpose_size ()) | ||
502 | return GNUNET_SYSERR; | ||
503 | |||
504 | /* Check origin */ | ||
505 | if (0 != memcmp (&msg->origin_identity, | ||
506 | GMP_get_id (t->peer), | ||
507 | sizeof (struct GNUNET_PeerIdentity))) | ||
508 | return GNUNET_SYSERR; | ||
509 | |||
510 | /* Check signature */ | ||
511 | if (GNUNET_OK != | ||
512 | GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_CADET_KX, | ||
513 | &msg->purpose, | ||
514 | &msg->signature, | ||
515 | &msg->origin_identity.public_key)) | ||
516 | return GNUNET_SYSERR; | ||
517 | |||
518 | return GNUNET_OK; | ||
519 | } | ||
520 | |||
521 | |||
522 | /** | ||
523 | * Encrypt data with the tunnel key. | ||
524 | * | ||
525 | * @param t Tunnel whose key to use. | ||
526 | * @param dst Destination for the encrypted data. | ||
527 | * @param src Source of the plaintext. Can overlap with @c dst. | ||
528 | * @param size Size of the plaintext. | ||
529 | * @param iv Initialization Vector to use. | ||
530 | */ | ||
531 | static int | ||
532 | t_encrypt (struct CadetTunnel3 *t, | ||
533 | void *dst, const void *src, | ||
534 | size_t size, uint32_t iv) | ||
535 | { | ||
536 | struct GNUNET_CRYPTO_SymmetricInitializationVector siv; | ||
537 | size_t out_size; | ||
538 | |||
539 | LOG (GNUNET_ERROR_TYPE_DEBUG, " t_encrypt start\n"); | ||
540 | GNUNET_CRYPTO_symmetric_derive_iv (&siv, &t->e_key, &iv, sizeof (iv), NULL); | ||
541 | LOG (GNUNET_ERROR_TYPE_DEBUG, " t_encrypt IV derived\n"); | ||
542 | out_size = GNUNET_CRYPTO_symmetric_encrypt (src, size, &t->e_key, &siv, dst); | ||
543 | LOG (GNUNET_ERROR_TYPE_DEBUG, " t_encrypt end\n"); | ||
544 | |||
545 | return out_size; | ||
546 | } | ||
547 | |||
548 | |||
549 | /** | ||
550 | * Decrypt data with the tunnel key. | ||
551 | * | ||
552 | * @param t Tunnel whose key to use. | ||
553 | * @param dst Destination for the plaintext. | ||
554 | * @param src Source of the encrypted data. Can overlap with @c dst. | ||
555 | * @param size Size of the encrypted data. | ||
556 | * @param iv Initialization Vector to use. | ||
557 | */ | ||
558 | static int | ||
559 | t_decrypt (struct CadetTunnel3 *t, | ||
560 | void *dst, const void *src, | ||
561 | size_t size, uint32_t iv) | ||
562 | { | ||
563 | struct GNUNET_CRYPTO_SymmetricInitializationVector siv; | ||
564 | struct GNUNET_CRYPTO_SymmetricSessionKey *key; | ||
565 | size_t out_size; | ||
566 | |||
567 | LOG (GNUNET_ERROR_TYPE_DEBUG, " t_decrypt start\n"); | ||
568 | if (t->estate == CADET_TUNNEL3_KEY_OK || t->estate == CADET_TUNNEL3_KEY_PING) | ||
569 | { | ||
570 | key = &t->d_key; | ||
571 | } | ||
572 | else if (NULL != t->kx_ctx) | ||
573 | { | ||
574 | key = &t->kx_ctx->d_key_old; | ||
575 | } | ||
576 | else | ||
577 | { | ||
578 | GNUNET_STATISTICS_update (stats, "# non decryptable data", 1, GNUNET_NO); | ||
579 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
580 | "WARNING got data on %s without a valid key\n", | ||
581 | GMT_2s (t)); | ||
582 | GMT_debug (t); | ||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | LOG (GNUNET_ERROR_TYPE_DEBUG, " t_decrypt iv\n"); | ||
587 | GNUNET_CRYPTO_symmetric_derive_iv (&siv, key, &iv, sizeof (iv), NULL); | ||
588 | LOG (GNUNET_ERROR_TYPE_DEBUG, " t_decrypt iv done\n"); | ||
589 | out_size = GNUNET_CRYPTO_symmetric_decrypt (src, size, key, &siv, dst); | ||
590 | LOG (GNUNET_ERROR_TYPE_DEBUG, " t_decrypt end\n"); | ||
591 | |||
592 | return out_size; | ||
593 | } | ||
594 | |||
595 | |||
596 | /** | ||
597 | * Create key material by doing ECDH on the local and remote ephemeral keys. | ||
598 | * | ||
599 | * @param key_material Where to store the key material. | ||
600 | * @param ephemeral_key Peer's public ephemeral key. | ||
601 | */ | ||
602 | void | ||
603 | derive_key_material (struct GNUNET_HashCode *key_material, | ||
604 | const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_key) | ||
605 | { | ||
606 | if (GNUNET_OK != | ||
607 | GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key, | ||
608 | ephemeral_key, | ||
609 | key_material)) | ||
610 | { | ||
611 | GNUNET_break (0); | ||
612 | } | ||
613 | } | ||
614 | |||
615 | /** | ||
616 | * Create a symmetic key from the identities of both ends and the key material | ||
617 | * from ECDH. | ||
618 | * | ||
619 | * @param key Destination for the generated key. | ||
620 | * @param sender ID of the peer that will encrypt with @c key. | ||
621 | * @param receiver ID of the peer that will decrypt with @c key. | ||
622 | * @param key_material Hash created with ECDH with the ephemeral keys. | ||
623 | */ | ||
624 | void | ||
625 | derive_symmertic (struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
626 | const struct GNUNET_PeerIdentity *sender, | ||
627 | const struct GNUNET_PeerIdentity *receiver, | ||
628 | const struct GNUNET_HashCode *key_material) | ||
629 | { | ||
630 | const char salt[] = "CADET kx salt"; | ||
631 | |||
632 | GNUNET_CRYPTO_kdf (key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), | ||
633 | salt, sizeof (salt), | ||
634 | key_material, sizeof (struct GNUNET_HashCode), | ||
635 | sender, sizeof (struct GNUNET_PeerIdentity), | ||
636 | receiver, sizeof (struct GNUNET_PeerIdentity), | ||
637 | NULL); | ||
638 | } | ||
639 | |||
640 | /** | ||
641 | * Pick a connection on which send the next data message. | ||
642 | * | ||
643 | * @param t Tunnel on which to send the message. | ||
644 | * | ||
645 | * @return The connection on which to send the next message. | ||
646 | */ | ||
647 | static struct CadetConnection * | ||
648 | tunnel_get_connection (struct CadetTunnel3 *t) | ||
649 | { | ||
650 | struct CadetTConnection *iter; | ||
651 | struct CadetConnection *best; | ||
652 | unsigned int qn; | ||
653 | unsigned int lowest_q; | ||
654 | |||
655 | LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel_get_connection %s\n", GMT_2s (t)); | ||
656 | best = NULL; | ||
657 | lowest_q = UINT_MAX; | ||
658 | for (iter = t->connection_head; NULL != iter; iter = iter->next) | ||
659 | { | ||
660 | LOG (GNUNET_ERROR_TYPE_DEBUG, " connection %s: %u\n", | ||
661 | GMC_2s (iter->c), GMC_get_state (iter->c)); | ||
662 | if (CADET_CONNECTION_READY == GMC_get_state (iter->c)) | ||
663 | { | ||
664 | qn = GMC_get_qn (iter->c, GMC_is_origin (iter->c, GNUNET_YES)); | ||
665 | LOG (GNUNET_ERROR_TYPE_DEBUG, " q_n %u, \n", qn); | ||
666 | if (qn < lowest_q) | ||
667 | { | ||
668 | best = iter->c; | ||
669 | lowest_q = qn; | ||
670 | } | ||
671 | } | ||
672 | } | ||
673 | LOG (GNUNET_ERROR_TYPE_DEBUG, " selected: connection %s\n", GMC_2s (best)); | ||
674 | return best; | ||
675 | } | ||
676 | |||
677 | |||
678 | /** | ||
679 | * Callback called when a queued message is sent. | ||
680 | * | ||
681 | * Calculates the average time and connection packet tracking. | ||
682 | * | ||
683 | * @param cls Closure (TunnelQueue handle). | ||
684 | * @param c Connection this message was on. | ||
685 | * @param q Connection queue handle (unused). | ||
686 | * @param type Type of message sent. | ||
687 | * @param fwd Was this a FWD going message? | ||
688 | * @param size Size of the message. | ||
689 | */ | ||
690 | static void | ||
691 | tun_message_sent (void *cls, | ||
692 | struct CadetConnection *c, | ||
693 | struct CadetConnectionQueue *q, | ||
694 | uint16_t type, int fwd, size_t size) | ||
695 | { | ||
696 | struct CadetTunnel3Queue *qt = cls; | ||
697 | struct CadetTunnel3 *t; | ||
698 | |||
699 | LOG (GNUNET_ERROR_TYPE_DEBUG, "tun_message_sent\n"); | ||
700 | |||
701 | GNUNET_assert (NULL != qt->cont); | ||
702 | t = NULL == c ? NULL : GMC_get_tunnel (c); | ||
703 | qt->cont (qt->cont_cls, t, qt, type, size); | ||
704 | GNUNET_free (qt); | ||
705 | } | ||
706 | |||
707 | |||
708 | /** | ||
709 | * Delete a queued message: either was sent or the channel was destroyed | ||
710 | * before the tunnel's key exchange had a chance to finish. | ||
711 | * | ||
712 | * @param tqd Delayed queue handle. | ||
713 | */ | ||
714 | static void | ||
715 | unqueue_data (struct CadetTunnelDelayed *tqd) | ||
716 | { | ||
717 | GNUNET_CONTAINER_DLL_remove (tqd->t->tq_head, tqd->t->tq_tail, tqd); | ||
718 | GNUNET_free (tqd); | ||
719 | } | ||
720 | |||
721 | |||
722 | /** | ||
723 | * Cache a message to be sent once tunnel is online. | ||
724 | * | ||
725 | * @param t Tunnel to hold the message. | ||
726 | * @param msg Message itself (copy will be made). | ||
727 | */ | ||
728 | static struct CadetTunnelDelayed * | ||
729 | queue_data (struct CadetTunnel3 *t, const struct GNUNET_MessageHeader *msg) | ||
730 | { | ||
731 | struct CadetTunnelDelayed *tqd; | ||
732 | uint16_t size = ntohs (msg->size); | ||
733 | |||
734 | LOG (GNUNET_ERROR_TYPE_DEBUG, "queue data on Tunnel %s\n", GMT_2s (t)); | ||
735 | |||
736 | if (GNUNET_YES == is_ready (t)) | ||
737 | { | ||
738 | GNUNET_break (0); | ||
739 | return NULL; | ||
740 | } | ||
741 | |||
742 | tqd = GNUNET_malloc (sizeof (struct CadetTunnelDelayed) + size); | ||
743 | |||
744 | tqd->t = t; | ||
745 | memcpy (&tqd[1], msg, size); | ||
746 | GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tqd); | ||
747 | return tqd; | ||
748 | } | ||
749 | |||
750 | |||
751 | /** | ||
752 | * Calculate HMAC. | ||
753 | * | ||
754 | * @param t Tunnel to get keys from. | ||
755 | * @param plaintext Content to HMAC. | ||
756 | * @param size Size of @c plaintext. | ||
757 | * @param iv Initialization vector for the message. | ||
758 | * @param outgoing Is this an outgoing message that we encrypted? | ||
759 | * @param hmac Destination to store the HMAC. | ||
760 | */ | ||
761 | static void | ||
762 | t_hmac (struct CadetTunnel3 *t, const void *plaintext, size_t size, uint32_t iv, | ||
763 | int outgoing, struct GNUNET_CADET_Hash *hmac) | ||
764 | { | ||
765 | struct GNUNET_CRYPTO_AuthKey auth_key; | ||
766 | static const char ctx[] = "cadet authentication key"; | ||
767 | struct GNUNET_CRYPTO_SymmetricSessionKey *key; | ||
768 | struct GNUNET_HashCode hash; | ||
769 | |||
770 | key = outgoing ? &t->e_key : &t->d_key; | ||
771 | GNUNET_CRYPTO_hmac_derive_key (&auth_key, key, | ||
772 | &iv, sizeof (iv), | ||
773 | key, sizeof (*key), | ||
774 | ctx, sizeof (ctx), | ||
775 | NULL); | ||
776 | GNUNET_CRYPTO_hmac (&auth_key, plaintext, size, &hash); | ||
777 | memcpy (hmac, &hash, sizeof (*hmac)); | ||
778 | } | ||
779 | |||
780 | |||
781 | /** | ||
782 | * Sends an already built message on a tunnel, encrypting it and | ||
783 | * choosing the best connection. | ||
784 | * | ||
785 | * @param message Message to send. Function modifies it. | ||
786 | * @param t Tunnel on which this message is transmitted. | ||
787 | * @param c Connection to use (autoselect if NULL). | ||
788 | * @param force Force the tunnel to take the message (buffer overfill). | ||
789 | * @param cont Continuation to call once message is really sent. | ||
790 | * @param cont_cls Closure for @c cont. | ||
791 | * @param existing_q In case this a transmission of previously queued data, | ||
792 | * this should be TunnelQueue given to the client. | ||
793 | * Otherwise, NULL. | ||
794 | * | ||
795 | * @return Handle to cancel message. NULL if @c cont is NULL. | ||
796 | */ | ||
797 | static struct CadetTunnel3Queue * | ||
798 | send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
799 | struct CadetTunnel3 *t, struct CadetConnection *c, | ||
800 | int force, GMT_sent cont, void *cont_cls, | ||
801 | struct CadetTunnel3Queue *existing_q) | ||
802 | { | ||
803 | struct CadetTunnel3Queue *tq; | ||
804 | struct GNUNET_CADET_Encrypted *msg; | ||
805 | size_t size = ntohs (message->size); | ||
806 | char cbuf[sizeof (struct GNUNET_CADET_Encrypted) + size]; | ||
807 | uint32_t mid; | ||
808 | uint32_t iv; | ||
809 | uint16_t type; | ||
810 | int fwd; | ||
811 | |||
812 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GMT_2s (t)); | ||
813 | |||
814 | if (GNUNET_NO == is_ready (t)) | ||
815 | { | ||
816 | struct CadetTunnelDelayed *tqd; | ||
817 | /* A non null existing_q indicates sending of queued data. | ||
818 | * Should only happen after tunnel becomes ready. | ||
819 | */ | ||
820 | GNUNET_assert (NULL == existing_q); | ||
821 | tqd = queue_data (t, message); | ||
822 | if (NULL == cont) | ||
823 | return NULL; | ||
824 | tq = GNUNET_new (struct CadetTunnel3Queue); | ||
825 | tq->tqd = tqd; | ||
826 | tqd->tq = tq; | ||
827 | tq->cont = cont; | ||
828 | tq->cont_cls = cont_cls; | ||
829 | return tq; | ||
830 | } | ||
831 | |||
832 | GNUNET_assert (GNUNET_NO == GMT_is_loopback (t)); | ||
833 | |||
834 | iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); | ||
835 | msg = (struct GNUNET_CADET_Encrypted *) cbuf; | ||
836 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED); | ||
837 | msg->iv = iv; | ||
838 | GNUNET_assert (t_encrypt (t, &msg[1], message, size, iv) == size); | ||
839 | t_hmac (t, &msg[1], size, iv, GNUNET_YES, &msg->hmac); | ||
840 | msg->header.size = htons (sizeof (struct GNUNET_CADET_Encrypted) + size); | ||
841 | |||
842 | if (NULL == c) | ||
843 | c = tunnel_get_connection (t); | ||
844 | if (NULL == c) | ||
845 | { | ||
846 | if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task | ||
847 | || CADET_TUNNEL3_SEARCHING != t->cstate) | ||
848 | { | ||
849 | GNUNET_break (0); | ||
850 | GMT_debug (t); | ||
851 | } | ||
852 | return NULL; | ||
853 | } | ||
854 | |||
855 | mid = 0; | ||
856 | type = ntohs (message->type); | ||
857 | switch (type) | ||
858 | { | ||
859 | case GNUNET_MESSAGE_TYPE_CADET_DATA: | ||
860 | case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: | ||
861 | if (GNUNET_MESSAGE_TYPE_CADET_DATA == type) | ||
862 | mid = ntohl (((struct GNUNET_CADET_Data *) message)->mid); | ||
863 | else | ||
864 | mid = ntohl (((struct GNUNET_CADET_DataACK *) message)->mid); | ||
865 | /* Fall thru */ | ||
866 | case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE: | ||
867 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
868 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
869 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: | ||
870 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: | ||
871 | msg->cid = *GMC_get_id (c); | ||
872 | msg->ttl = htonl (default_ttl); | ||
873 | break; | ||
874 | default: | ||
875 | GNUNET_break (0); | ||
876 | } | ||
877 | LOG (GNUNET_ERROR_TYPE_DEBUG, "type %s\n", GM_m2s (type)); | ||
878 | |||
879 | fwd = GMC_is_origin (c, GNUNET_YES); | ||
880 | |||
881 | if (NULL == cont) | ||
882 | { | ||
883 | GNUNET_break (NULL == | ||
884 | GMC_send_prebuilt_message (&msg->header, type, mid, | ||
885 | c, fwd, force, NULL, NULL)); | ||
886 | return NULL; | ||
887 | } | ||
888 | if (NULL == existing_q) | ||
889 | { | ||
890 | tq = GNUNET_new (struct CadetTunnel3Queue); /* FIXME valgrind: leak*/ | ||
891 | } | ||
892 | else | ||
893 | { | ||
894 | tq = existing_q; | ||
895 | tq->tqd = NULL; | ||
896 | } | ||
897 | tq->cq = GMC_send_prebuilt_message (&msg->header, type, mid, c, fwd, force, | ||
898 | &tun_message_sent, tq); | ||
899 | tq->cont = cont; | ||
900 | tq->cont_cls = cont_cls; | ||
901 | |||
902 | return tq; | ||
903 | } | ||
904 | |||
905 | |||
906 | /** | ||
907 | * Send all cached messages that we can, tunnel is online. | ||
908 | * | ||
909 | * @param t Tunnel that holds the messages. Cannot be loopback. | ||
910 | */ | ||
911 | static void | ||
912 | send_queued_data (struct CadetTunnel3 *t) | ||
913 | { | ||
914 | struct CadetTunnelDelayed *tqd; | ||
915 | struct CadetTunnelDelayed *next; | ||
916 | unsigned int room; | ||
917 | |||
918 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
919 | "GMT_send_queued_data on tunnel %s\n", | ||
920 | GMT_2s (t)); | ||
921 | |||
922 | if (GMT_is_loopback (t)) | ||
923 | { | ||
924 | GNUNET_break (0); | ||
925 | return; | ||
926 | } | ||
927 | |||
928 | if (GNUNET_NO == is_ready (t)) | ||
929 | { | ||
930 | LOG (GNUNET_ERROR_TYPE_DEBUG, " not ready yet: %s/%s\n", | ||
931 | estate2s (t->estate), cstate2s (t->cstate)); | ||
932 | return; | ||
933 | } | ||
934 | |||
935 | room = GMT_get_connections_buffer (t); | ||
936 | LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room); | ||
937 | LOG (GNUNET_ERROR_TYPE_DEBUG, " tq head: %p\n", t->tq_head); | ||
938 | for (tqd = t->tq_head; NULL != tqd && room > 0; tqd = next) | ||
939 | { | ||
940 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending queued data\n"); | ||
941 | next = tqd->next; | ||
942 | room--; | ||
943 | send_prebuilt_message ((struct GNUNET_MessageHeader *) &tqd[1], | ||
944 | tqd->t, NULL, GNUNET_YES, | ||
945 | NULL != tqd->tq ? tqd->tq->cont : NULL, | ||
946 | NULL != tqd->tq ? tqd->tq->cont_cls : NULL, | ||
947 | tqd->tq); | ||
948 | unqueue_data (tqd); | ||
949 | } | ||
950 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_send_queued_data end\n", GMP_2s (t->peer)); | ||
951 | } | ||
952 | |||
953 | |||
954 | /** | ||
955 | * Sends key exchange message on a tunnel, choosing the best connection. | ||
956 | * Should not be called on loopback tunnels. | ||
957 | * | ||
958 | * @param t Tunnel on which this message is transmitted. | ||
959 | * @param message Message to send. Function modifies it. | ||
960 | */ | ||
961 | static void | ||
962 | send_kx (struct CadetTunnel3 *t, | ||
963 | const struct GNUNET_MessageHeader *message) | ||
964 | { | ||
965 | struct CadetConnection *c; | ||
966 | struct GNUNET_CADET_KX *msg; | ||
967 | size_t size = ntohs (message->size); | ||
968 | char cbuf[sizeof (struct GNUNET_CADET_KX) + size]; | ||
969 | uint16_t type; | ||
970 | int fwd; | ||
971 | |||
972 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT KX on Tunnel %s\n", GMT_2s (t)); | ||
973 | |||
974 | /* Avoid loopback. */ | ||
975 | if (GMT_is_loopback (t)) | ||
976 | { | ||
977 | LOG (GNUNET_ERROR_TYPE_DEBUG, " loopback!\n"); | ||
978 | GNUNET_break (0); | ||
979 | return; | ||
980 | } | ||
981 | |||
982 | if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task) | ||
983 | { | ||
984 | LOG (GNUNET_ERROR_TYPE_DEBUG, " being destroyed, why bother\n"); | ||
985 | return; | ||
986 | } | ||
987 | |||
988 | /* Must have a connection. */ | ||
989 | if (NULL == t->connection_head) | ||
990 | { | ||
991 | GNUNET_break (CADET_TUNNEL3_SEARCHING == t->cstate); | ||
992 | GMT_debug (t); | ||
993 | return; | ||
994 | } | ||
995 | |||
996 | msg = (struct GNUNET_CADET_KX *) cbuf; | ||
997 | msg->header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX); | ||
998 | msg->header.size = htons (sizeof (struct GNUNET_CADET_KX) + size); | ||
999 | c = tunnel_get_connection (t); | ||
1000 | if (NULL == c) | ||
1001 | { | ||
1002 | GNUNET_break (GNUNET_SCHEDULER_NO_TASK != t->destroy_task | ||
1003 | || CADET_TUNNEL3_READY != t->cstate); | ||
1004 | GMT_debug (t); | ||
1005 | return; | ||
1006 | } | ||
1007 | type = ntohs (message->type); | ||
1008 | switch (type) | ||
1009 | { | ||
1010 | case GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL: | ||
1011 | case GNUNET_MESSAGE_TYPE_CADET_KX_PING: | ||
1012 | case GNUNET_MESSAGE_TYPE_CADET_KX_PONG: | ||
1013 | memcpy (&msg[1], message, size); | ||
1014 | break; | ||
1015 | default: | ||
1016 | LOG (GNUNET_ERROR_TYPE_DEBUG, "unkown type %s\n", | ||
1017 | GM_m2s (type)); | ||
1018 | GNUNET_break (0); | ||
1019 | } | ||
1020 | |||
1021 | fwd = GMC_is_origin (t->connection_head->c, GNUNET_YES); | ||
1022 | /* TODO save handle and cancel in case of a unneeded retransmission */ | ||
1023 | GMC_send_prebuilt_message (&msg->header, GNUNET_MESSAGE_TYPE_CADET_KX, | ||
1024 | message->type, c, fwd, GNUNET_YES, NULL, NULL); | ||
1025 | } | ||
1026 | |||
1027 | |||
1028 | /** | ||
1029 | * Send the ephemeral key on a tunnel. | ||
1030 | * | ||
1031 | * @param t Tunnel on which to send the key. | ||
1032 | */ | ||
1033 | static void | ||
1034 | send_ephemeral (struct CadetTunnel3 *t) | ||
1035 | { | ||
1036 | LOG (GNUNET_ERROR_TYPE_INFO, "=> EPHM for %s\n", GMT_2s (t)); | ||
1037 | |||
1038 | kx_msg.sender_status = htonl (t->estate); | ||
1039 | send_kx (t, &kx_msg.header); | ||
1040 | } | ||
1041 | |||
1042 | /** | ||
1043 | * Send a ping message on a tunnel. | ||
1044 | * | ||
1045 | * @param t Tunnel on which to send the ping. | ||
1046 | */ | ||
1047 | static void | ||
1048 | send_ping (struct CadetTunnel3 *t) | ||
1049 | { | ||
1050 | struct GNUNET_CADET_KX_Ping msg; | ||
1051 | |||
1052 | LOG (GNUNET_ERROR_TYPE_INFO, "=> PING for %s\n", GMT_2s (t)); | ||
1053 | msg.header.size = htons (sizeof (msg)); | ||
1054 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX_PING); | ||
1055 | msg.iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); | ||
1056 | msg.target = *GMP_get_id (t->peer); | ||
1057 | msg.nonce = t->kx_ctx->challenge; | ||
1058 | |||
1059 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending %u\n", msg.nonce); | ||
1060 | LOG (GNUNET_ERROR_TYPE_DEBUG, " towards %s\n", GNUNET_i2s (&msg.target)); | ||
1061 | t_encrypt (t, &msg.target, &msg.target, ping_encryption_size(), msg.iv); | ||
1062 | LOG (GNUNET_ERROR_TYPE_DEBUG, " e sending %u\n", msg.nonce); | ||
1063 | LOG (GNUNET_ERROR_TYPE_DEBUG, " e towards %s\n", GNUNET_i2s (&msg.target)); | ||
1064 | |||
1065 | send_kx (t, &msg.header); | ||
1066 | } | ||
1067 | |||
1068 | |||
1069 | /** | ||
1070 | * Send a pong message on a tunnel. | ||
1071 | * | ||
1072 | * @param t Tunnel on which to send the pong. | ||
1073 | * @param challenge Value sent in the ping that we have to send back. | ||
1074 | */ | ||
1075 | static void | ||
1076 | send_pong (struct CadetTunnel3 *t, uint32_t challenge) | ||
1077 | { | ||
1078 | struct GNUNET_CADET_KX_Pong msg; | ||
1079 | |||
1080 | LOG (GNUNET_ERROR_TYPE_INFO, "=> PONG for %s\n", GMT_2s (t)); | ||
1081 | msg.header.size = htons (sizeof (msg)); | ||
1082 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX_PONG); | ||
1083 | msg.iv = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); | ||
1084 | msg.nonce = challenge; | ||
1085 | LOG (GNUNET_ERROR_TYPE_DEBUG, " sending %u\n", msg.nonce); | ||
1086 | t_encrypt (t, &msg.nonce, &msg.nonce, sizeof (msg.nonce), msg.iv); | ||
1087 | LOG (GNUNET_ERROR_TYPE_DEBUG, " e sending %u\n", msg.nonce); | ||
1088 | |||
1089 | send_kx (t, &msg.header); | ||
1090 | } | ||
1091 | |||
1092 | |||
1093 | /** | ||
1094 | * Initiate a rekey with the remote peer. | ||
1095 | * | ||
1096 | * @param cls Closure (tunnel). | ||
1097 | * @param tc TaskContext. | ||
1098 | */ | ||
1099 | static void | ||
1100 | rekey_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1101 | { | ||
1102 | struct CadetTunnel3 *t = cls; | ||
1103 | |||
1104 | t->rekey_task = GNUNET_SCHEDULER_NO_TASK; | ||
1105 | |||
1106 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Re-key Tunnel %s\n", GMT_2s (t)); | ||
1107 | if (NULL != tc && 0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | ||
1108 | return; | ||
1109 | |||
1110 | if (NULL == t->kx_ctx) | ||
1111 | { | ||
1112 | LOG (GNUNET_ERROR_TYPE_DEBUG, " new kx ctx\n"); | ||
1113 | t->kx_ctx = GNUNET_new (struct CadetTunnelKXCtx); | ||
1114 | t->kx_ctx->challenge = | ||
1115 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); | ||
1116 | t->kx_ctx->d_key_old = t->d_key; | ||
1117 | LOG (GNUNET_ERROR_TYPE_DEBUG, " new challenge for %s: %u\n", | ||
1118 | GMT_2s (t), t->kx_ctx->challenge); | ||
1119 | } | ||
1120 | send_ephemeral (t); | ||
1121 | switch (t->estate) | ||
1122 | { | ||
1123 | case CADET_TUNNEL3_KEY_UNINITIALIZED: | ||
1124 | t->estate = CADET_TUNNEL3_KEY_SENT; | ||
1125 | break; | ||
1126 | case CADET_TUNNEL3_KEY_SENT: | ||
1127 | break; | ||
1128 | case CADET_TUNNEL3_KEY_PING: | ||
1129 | case CADET_TUNNEL3_KEY_OK: | ||
1130 | send_ping (t); | ||
1131 | t->estate = CADET_TUNNEL3_KEY_PING; | ||
1132 | break; | ||
1133 | default: | ||
1134 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Unexpected state %u\n", t->estate); | ||
1135 | } | ||
1136 | |||
1137 | LOG (GNUNET_ERROR_TYPE_DEBUG, " next call in %s\n", | ||
1138 | GNUNET_STRINGS_relative_time_to_string (REKEY_WAIT, GNUNET_YES)); | ||
1139 | t->rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_WAIT, &rekey_tunnel, t); | ||
1140 | } | ||
1141 | |||
1142 | |||
1143 | /** | ||
1144 | * Out ephemeral key has changed, create new session key on all tunnels. | ||
1145 | * | ||
1146 | * @param cls Closure (size of the hashmap). | ||
1147 | * @param key Current public key. | ||
1148 | * @param value Value in the hash map (tunnel). | ||
1149 | * | ||
1150 | * @return #GNUNET_YES, so we should continue to iterate, | ||
1151 | */ | ||
1152 | static int | ||
1153 | rekey_iterator (void *cls, | ||
1154 | const struct GNUNET_PeerIdentity *key, | ||
1155 | void *value) | ||
1156 | { | ||
1157 | struct CadetTunnel3 *t = value; | ||
1158 | struct GNUNET_TIME_Relative delay; | ||
1159 | long n = (long) cls; | ||
1160 | uint32_t r; | ||
1161 | |||
1162 | if (GNUNET_SCHEDULER_NO_TASK != t->rekey_task) | ||
1163 | return GNUNET_YES; | ||
1164 | |||
1165 | if (GNUNET_YES == GMT_is_loopback (t)) | ||
1166 | return GNUNET_YES; | ||
1167 | |||
1168 | r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, (uint32_t) n * 100); | ||
1169 | delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, r); | ||
1170 | t->rekey_task = GNUNET_SCHEDULER_add_delayed (delay, &rekey_tunnel, t); | ||
1171 | |||
1172 | return GNUNET_YES; | ||
1173 | } | ||
1174 | |||
1175 | |||
1176 | /** | ||
1177 | * Create a new ephemeral key and key message, schedule next rekeying. | ||
1178 | * | ||
1179 | * @param cls Closure (unused). | ||
1180 | * @param tc TaskContext. | ||
1181 | */ | ||
1182 | static void | ||
1183 | rekey (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1184 | { | ||
1185 | struct GNUNET_TIME_Absolute time; | ||
1186 | long n; | ||
1187 | |||
1188 | rekey_task = GNUNET_SCHEDULER_NO_TASK; | ||
1189 | |||
1190 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | ||
1191 | return; | ||
1192 | |||
1193 | GNUNET_free_non_null (my_ephemeral_key); | ||
1194 | my_ephemeral_key = GNUNET_CRYPTO_ecdhe_key_create (); | ||
1195 | |||
1196 | time = GNUNET_TIME_absolute_get (); | ||
1197 | kx_msg.creation_time = GNUNET_TIME_absolute_hton (time); | ||
1198 | time = GNUNET_TIME_absolute_add (time, rekey_period); | ||
1199 | time = GNUNET_TIME_absolute_add (time, GNUNET_TIME_UNIT_MINUTES); | ||
1200 | kx_msg.expiration_time = GNUNET_TIME_absolute_hton (time); | ||
1201 | GNUNET_CRYPTO_ecdhe_key_get_public (my_ephemeral_key, &kx_msg.ephemeral_key); | ||
1202 | |||
1203 | GNUNET_assert (GNUNET_OK == | ||
1204 | GNUNET_CRYPTO_eddsa_sign (my_private_key, | ||
1205 | &kx_msg.purpose, | ||
1206 | &kx_msg.signature)); | ||
1207 | |||
1208 | n = (long) GNUNET_CONTAINER_multipeermap_size (tunnels); | ||
1209 | GNUNET_CONTAINER_multipeermap_iterate (tunnels, &rekey_iterator, (void *) n); | ||
1210 | |||
1211 | rekey_task = GNUNET_SCHEDULER_add_delayed (rekey_period, &rekey, NULL); | ||
1212 | } | ||
1213 | |||
1214 | |||
1215 | /** | ||
1216 | * Called only on shutdown, destroy every tunnel. | ||
1217 | * | ||
1218 | * @param cls Closure (unused). | ||
1219 | * @param key Current public key. | ||
1220 | * @param value Value in the hash map (tunnel). | ||
1221 | * | ||
1222 | * @return #GNUNET_YES, so we should continue to iterate, | ||
1223 | */ | ||
1224 | static int | ||
1225 | destroy_iterator (void *cls, | ||
1226 | const struct GNUNET_PeerIdentity *key, | ||
1227 | void *value) | ||
1228 | { | ||
1229 | struct CadetTunnel3 *t = value; | ||
1230 | |||
1231 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_shutdown destroying tunnel at %p\n", t); | ||
1232 | GMT_destroy (t); | ||
1233 | return GNUNET_YES; | ||
1234 | } | ||
1235 | |||
1236 | |||
1237 | /** | ||
1238 | * Notify remote peer that we don't know a channel he is talking about, | ||
1239 | * probably CHANNEL_DESTROY was missed. | ||
1240 | * | ||
1241 | * @param t Tunnel on which to notify. | ||
1242 | * @param gid ID of the channel. | ||
1243 | */ | ||
1244 | static void | ||
1245 | send_channel_destroy (struct CadetTunnel3 *t, unsigned int gid) | ||
1246 | { | ||
1247 | struct GNUNET_CADET_ChannelManage msg; | ||
1248 | |||
1249 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY); | ||
1250 | msg.header.size = htons (sizeof (msg)); | ||
1251 | msg.chid = htonl (gid); | ||
1252 | |||
1253 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1254 | "WARNING destroying unknown channel %u on tunnel %s\n", | ||
1255 | gid, GMT_2s (t)); | ||
1256 | send_prebuilt_message (&msg.header, t, NULL, GNUNET_YES, NULL, NULL, NULL); | ||
1257 | } | ||
1258 | |||
1259 | |||
1260 | /** | ||
1261 | * Demultiplex data per channel and call appropriate channel handler. | ||
1262 | * | ||
1263 | * @param t Tunnel on which the data came. | ||
1264 | * @param msg Data message. | ||
1265 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1266 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1267 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1268 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1269 | */ | ||
1270 | static void | ||
1271 | handle_data (struct CadetTunnel3 *t, | ||
1272 | const struct GNUNET_CADET_Data *msg, | ||
1273 | int fwd) | ||
1274 | { | ||
1275 | struct CadetChannel *ch; | ||
1276 | size_t size; | ||
1277 | |||
1278 | /* Check size */ | ||
1279 | size = ntohs (msg->header.size); | ||
1280 | if (size < | ||
1281 | sizeof (struct GNUNET_CADET_Data) + | ||
1282 | sizeof (struct GNUNET_MessageHeader)) | ||
1283 | { | ||
1284 | GNUNET_break (0); | ||
1285 | return; | ||
1286 | } | ||
1287 | LOG (GNUNET_ERROR_TYPE_DEBUG, " payload of type %s\n", | ||
1288 | GM_m2s (ntohs (msg[1].header.type))); | ||
1289 | |||
1290 | /* Check channel */ | ||
1291 | ch = GMT_get_channel (t, ntohl (msg->chid)); | ||
1292 | if (NULL == ch) | ||
1293 | { | ||
1294 | GNUNET_STATISTICS_update (stats, "# data on unknown channel", | ||
1295 | 1, GNUNET_NO); | ||
1296 | LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel 0x%X unknown\n", | ||
1297 | ntohl (msg->chid)); | ||
1298 | send_channel_destroy (t, ntohl (msg->chid)); | ||
1299 | return; | ||
1300 | } | ||
1301 | |||
1302 | GMCH_handle_data (ch, msg, fwd); | ||
1303 | } | ||
1304 | |||
1305 | |||
1306 | /** | ||
1307 | * Demultiplex data ACKs per channel and update appropriate channel buffer info. | ||
1308 | * | ||
1309 | * @param t Tunnel on which the DATA ACK came. | ||
1310 | * @param msg DATA ACK message. | ||
1311 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1312 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1313 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1314 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1315 | */ | ||
1316 | static void | ||
1317 | handle_data_ack (struct CadetTunnel3 *t, | ||
1318 | const struct GNUNET_CADET_DataACK *msg, | ||
1319 | int fwd) | ||
1320 | { | ||
1321 | struct CadetChannel *ch; | ||
1322 | size_t size; | ||
1323 | |||
1324 | /* Check size */ | ||
1325 | size = ntohs (msg->header.size); | ||
1326 | if (size != sizeof (struct GNUNET_CADET_DataACK)) | ||
1327 | { | ||
1328 | GNUNET_break (0); | ||
1329 | return; | ||
1330 | } | ||
1331 | |||
1332 | /* Check channel */ | ||
1333 | ch = GMT_get_channel (t, ntohl (msg->chid)); | ||
1334 | if (NULL == ch) | ||
1335 | { | ||
1336 | GNUNET_STATISTICS_update (stats, "# data ack on unknown channel", | ||
1337 | 1, GNUNET_NO); | ||
1338 | LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n", | ||
1339 | ntohl (msg->chid)); | ||
1340 | return; | ||
1341 | } | ||
1342 | |||
1343 | GMCH_handle_data_ack (ch, msg, fwd); | ||
1344 | } | ||
1345 | |||
1346 | |||
1347 | /** | ||
1348 | * Handle channel create. | ||
1349 | * | ||
1350 | * @param t Tunnel on which the data came. | ||
1351 | * @param msg Data message. | ||
1352 | */ | ||
1353 | static void | ||
1354 | handle_ch_create (struct CadetTunnel3 *t, | ||
1355 | const struct GNUNET_CADET_ChannelCreate *msg) | ||
1356 | { | ||
1357 | struct CadetChannel *ch; | ||
1358 | size_t size; | ||
1359 | |||
1360 | /* Check size */ | ||
1361 | size = ntohs (msg->header.size); | ||
1362 | if (size != sizeof (struct GNUNET_CADET_ChannelCreate)) | ||
1363 | { | ||
1364 | GNUNET_break (0); | ||
1365 | return; | ||
1366 | } | ||
1367 | |||
1368 | /* Check channel */ | ||
1369 | ch = GMT_get_channel (t, ntohl (msg->chid)); | ||
1370 | if (NULL != ch && ! GMT_is_loopback (t)) | ||
1371 | { | ||
1372 | /* Probably a retransmission, safe to ignore */ | ||
1373 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already exists...\n"); | ||
1374 | } | ||
1375 | ch = GMCH_handle_create (t, msg); | ||
1376 | if (NULL != ch) | ||
1377 | GMT_add_channel (t, ch); | ||
1378 | } | ||
1379 | |||
1380 | |||
1381 | |||
1382 | /** | ||
1383 | * Handle channel NACK: check correctness and call channel handler for NACKs. | ||
1384 | * | ||
1385 | * @param t Tunnel on which the NACK came. | ||
1386 | * @param msg NACK message. | ||
1387 | */ | ||
1388 | static void | ||
1389 | handle_ch_nack (struct CadetTunnel3 *t, | ||
1390 | const struct GNUNET_CADET_ChannelManage *msg) | ||
1391 | { | ||
1392 | struct CadetChannel *ch; | ||
1393 | size_t size; | ||
1394 | |||
1395 | /* Check size */ | ||
1396 | size = ntohs (msg->header.size); | ||
1397 | if (size != sizeof (struct GNUNET_CADET_ChannelManage)) | ||
1398 | { | ||
1399 | GNUNET_break (0); | ||
1400 | return; | ||
1401 | } | ||
1402 | |||
1403 | /* Check channel */ | ||
1404 | ch = GMT_get_channel (t, ntohl (msg->chid)); | ||
1405 | if (NULL == ch) | ||
1406 | { | ||
1407 | GNUNET_STATISTICS_update (stats, "# channel NACK on unknown channel", | ||
1408 | 1, GNUNET_NO); | ||
1409 | LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n", | ||
1410 | ntohl (msg->chid)); | ||
1411 | return; | ||
1412 | } | ||
1413 | |||
1414 | GMCH_handle_nack (ch); | ||
1415 | } | ||
1416 | |||
1417 | |||
1418 | /** | ||
1419 | * Handle a CHANNEL ACK (SYNACK/ACK). | ||
1420 | * | ||
1421 | * @param t Tunnel on which the CHANNEL ACK came. | ||
1422 | * @param msg CHANNEL ACK message. | ||
1423 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1424 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1425 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1426 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1427 | */ | ||
1428 | static void | ||
1429 | handle_ch_ack (struct CadetTunnel3 *t, | ||
1430 | const struct GNUNET_CADET_ChannelManage *msg, | ||
1431 | int fwd) | ||
1432 | { | ||
1433 | struct CadetChannel *ch; | ||
1434 | size_t size; | ||
1435 | |||
1436 | /* Check size */ | ||
1437 | size = ntohs (msg->header.size); | ||
1438 | if (size != sizeof (struct GNUNET_CADET_ChannelManage)) | ||
1439 | { | ||
1440 | GNUNET_break (0); | ||
1441 | return; | ||
1442 | } | ||
1443 | |||
1444 | /* Check channel */ | ||
1445 | ch = GMT_get_channel (t, ntohl (msg->chid)); | ||
1446 | if (NULL == ch) | ||
1447 | { | ||
1448 | GNUNET_STATISTICS_update (stats, "# channel ack on unknown channel", | ||
1449 | 1, GNUNET_NO); | ||
1450 | LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n", | ||
1451 | ntohl (msg->chid)); | ||
1452 | return; | ||
1453 | } | ||
1454 | |||
1455 | GMCH_handle_ack (ch, msg, fwd); | ||
1456 | } | ||
1457 | |||
1458 | |||
1459 | |||
1460 | /** | ||
1461 | * Handle a channel destruction message. | ||
1462 | * | ||
1463 | * @param t Tunnel on which the message came. | ||
1464 | * @param msg Channel destroy message. | ||
1465 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1466 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1467 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1468 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1469 | */ | ||
1470 | static void | ||
1471 | handle_ch_destroy (struct CadetTunnel3 *t, | ||
1472 | const struct GNUNET_CADET_ChannelManage *msg, | ||
1473 | int fwd) | ||
1474 | { | ||
1475 | struct CadetChannel *ch; | ||
1476 | size_t size; | ||
1477 | |||
1478 | /* Check size */ | ||
1479 | size = ntohs (msg->header.size); | ||
1480 | if (size != sizeof (struct GNUNET_CADET_ChannelManage)) | ||
1481 | { | ||
1482 | GNUNET_break (0); | ||
1483 | return; | ||
1484 | } | ||
1485 | |||
1486 | /* Check channel */ | ||
1487 | ch = GMT_get_channel (t, ntohl (msg->chid)); | ||
1488 | if (NULL == ch) | ||
1489 | { | ||
1490 | /* Probably a retransmission, safe to ignore */ | ||
1491 | return; | ||
1492 | } | ||
1493 | |||
1494 | GMCH_handle_destroy (ch, msg, fwd); | ||
1495 | } | ||
1496 | |||
1497 | |||
1498 | /** | ||
1499 | * The peer's ephemeral key has changed: update the symmetrical keys. | ||
1500 | * | ||
1501 | * @param t Tunnel this message came on. | ||
1502 | * @param msg Key eXchange message. | ||
1503 | */ | ||
1504 | static void | ||
1505 | handle_ephemeral (struct CadetTunnel3 *t, | ||
1506 | const struct GNUNET_CADET_KX_Ephemeral *msg) | ||
1507 | { | ||
1508 | struct GNUNET_HashCode km; | ||
1509 | LOG (GNUNET_ERROR_TYPE_INFO, "<=== EPHM for %s\n", GMT_2s (t)); | ||
1510 | |||
1511 | if (GNUNET_OK != check_ephemeral (t, msg)) | ||
1512 | { | ||
1513 | GNUNET_break_op (0); | ||
1514 | return; | ||
1515 | } | ||
1516 | derive_key_material (&km, &msg->ephemeral_key); | ||
1517 | LOG (GNUNET_ERROR_TYPE_DEBUG, " km is %s\n", GNUNET_h2s (&km)); | ||
1518 | derive_symmertic (&t->e_key, &my_full_id, GMP_get_id (t->peer), &km); | ||
1519 | derive_symmertic (&t->d_key, GMP_get_id (t->peer), &my_full_id, &km); | ||
1520 | if (CADET_TUNNEL3_KEY_SENT == t->estate) | ||
1521 | { | ||
1522 | LOG (GNUNET_ERROR_TYPE_DEBUG, " our key was sent, send ping\n"); | ||
1523 | send_ping (t); | ||
1524 | t->estate = CADET_TUNNEL3_KEY_PING; | ||
1525 | } | ||
1526 | } | ||
1527 | |||
1528 | |||
1529 | /** | ||
1530 | * Peer wants to check our symmetrical keys by sending an encrypted challenge. | ||
1531 | * Answer with by retransmitting the challenge with the "opposite" key. | ||
1532 | * | ||
1533 | * @param t Tunnel this message came on. | ||
1534 | * @param msg Key eXchange Ping message. | ||
1535 | */ | ||
1536 | static void | ||
1537 | handle_ping (struct CadetTunnel3 *t, | ||
1538 | const struct GNUNET_CADET_KX_Ping *msg) | ||
1539 | { | ||
1540 | struct GNUNET_CADET_KX_Ping res; | ||
1541 | |||
1542 | if (ntohs (msg->header.size) != sizeof (res)) | ||
1543 | { | ||
1544 | GNUNET_break_op (0); | ||
1545 | return; | ||
1546 | } | ||
1547 | |||
1548 | LOG (GNUNET_ERROR_TYPE_INFO, "<=== PING for %s\n", GMT_2s (t)); | ||
1549 | t_decrypt (t, &res.target, &msg->target, ping_encryption_size (), msg->iv); | ||
1550 | if (0 != memcmp (&my_full_id, &res.target, sizeof (my_full_id))) | ||
1551 | { | ||
1552 | // FIXME: move to debug | ||
1553 | GNUNET_STATISTICS_update (stats, "# malformed PINGs", 1, GNUNET_NO); | ||
1554 | LOG (GNUNET_ERROR_TYPE_WARNING, " malformed PING on %s\n", GMT_2s (t)); | ||
1555 | LOG (GNUNET_ERROR_TYPE_WARNING, " e got %u\n", msg->nonce); | ||
1556 | LOG (GNUNET_ERROR_TYPE_WARNING, " e towards %s\n", GNUNET_i2s (&msg->target)); | ||
1557 | LOG (GNUNET_ERROR_TYPE_WARNING, " got %u\n", res.nonce); | ||
1558 | LOG (GNUNET_ERROR_TYPE_WARNING, " towards %s\n", GNUNET_i2s (&res.target)); | ||
1559 | return; | ||
1560 | } | ||
1561 | |||
1562 | send_pong (t, res.nonce); | ||
1563 | } | ||
1564 | |||
1565 | |||
1566 | /** | ||
1567 | * Peer has answer to our challenge. | ||
1568 | * If answer is successful, consider the key exchange finished and clean | ||
1569 | * up all related state. | ||
1570 | * | ||
1571 | * @param t Tunnel this message came on. | ||
1572 | * @param msg Key eXchange Pong message. | ||
1573 | */ | ||
1574 | static void | ||
1575 | handle_pong (struct CadetTunnel3 *t, | ||
1576 | const struct GNUNET_CADET_KX_Pong *msg) | ||
1577 | { | ||
1578 | uint32_t challenge; | ||
1579 | |||
1580 | LOG (GNUNET_ERROR_TYPE_INFO, "<=== PONG for %s\n", GMT_2s (t)); | ||
1581 | if (GNUNET_SCHEDULER_NO_TASK == t->rekey_task) | ||
1582 | { | ||
1583 | GNUNET_STATISTICS_update (stats, "# duplicate PONG messages", 1, GNUNET_NO); | ||
1584 | return; | ||
1585 | } | ||
1586 | t_decrypt (t, &challenge, &msg->nonce, sizeof (uint32_t), msg->iv); | ||
1587 | |||
1588 | if (challenge != t->kx_ctx->challenge) | ||
1589 | { | ||
1590 | LOG (GNUNET_ERROR_TYPE_WARNING, "Wrong PONG challenge\n"); | ||
1591 | LOG (GNUNET_ERROR_TYPE_DEBUG, "PONG: %u (e: %u). Expected: %u.\n", | ||
1592 | challenge, msg->nonce, t->kx_ctx->challenge); | ||
1593 | GNUNET_break_op (0); | ||
1594 | return; | ||
1595 | } | ||
1596 | GNUNET_SCHEDULER_cancel (t->rekey_task); | ||
1597 | t->rekey_task = GNUNET_SCHEDULER_NO_TASK; | ||
1598 | GNUNET_free (t->kx_ctx); | ||
1599 | t->kx_ctx = NULL; | ||
1600 | GMT_change_estate (t, CADET_TUNNEL3_KEY_OK); | ||
1601 | } | ||
1602 | |||
1603 | |||
1604 | /** | ||
1605 | * Demultiplex by message type and call appropriate handler for a message | ||
1606 | * towards a channel of a local tunnel. | ||
1607 | * | ||
1608 | * @param t Tunnel this message came on. | ||
1609 | * @param msgh Message header. | ||
1610 | * @param fwd Is this message fwd? This only is meaningful in loopback channels. | ||
1611 | * #GNUNET_YES if message is FWD on the respective channel (loopback) | ||
1612 | * #GNUNET_NO if message is BCK on the respective channel (loopback) | ||
1613 | * #GNUNET_SYSERR if message on a one-ended channel (remote) | ||
1614 | */ | ||
1615 | static void | ||
1616 | handle_decrypted (struct CadetTunnel3 *t, | ||
1617 | const struct GNUNET_MessageHeader *msgh, | ||
1618 | int fwd) | ||
1619 | { | ||
1620 | uint16_t type; | ||
1621 | |||
1622 | type = ntohs (msgh->type); | ||
1623 | LOG (GNUNET_ERROR_TYPE_INFO, "<=== %s on %s\n", GM_m2s (type), GMT_2s (t)); | ||
1624 | |||
1625 | switch (type) | ||
1626 | { | ||
1627 | case GNUNET_MESSAGE_TYPE_CADET_KEEPALIVE: | ||
1628 | /* Do nothing, connection aleady got updated. */ | ||
1629 | GNUNET_STATISTICS_update (stats, "# keepalives received", 1, GNUNET_NO); | ||
1630 | break; | ||
1631 | |||
1632 | case GNUNET_MESSAGE_TYPE_CADET_DATA: | ||
1633 | /* Don't send hop ACK, wait for client to ACK */ | ||
1634 | handle_data (t, (struct GNUNET_CADET_Data *) msgh, fwd); | ||
1635 | break; | ||
1636 | |||
1637 | case GNUNET_MESSAGE_TYPE_CADET_DATA_ACK: | ||
1638 | handle_data_ack (t, (struct GNUNET_CADET_DataACK *) msgh, fwd); | ||
1639 | break; | ||
1640 | |||
1641 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_CREATE: | ||
1642 | handle_ch_create (t, | ||
1643 | (struct GNUNET_CADET_ChannelCreate *) msgh); | ||
1644 | break; | ||
1645 | |||
1646 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_NACK: | ||
1647 | handle_ch_nack (t, | ||
1648 | (struct GNUNET_CADET_ChannelManage *) msgh); | ||
1649 | break; | ||
1650 | |||
1651 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_ACK: | ||
1652 | handle_ch_ack (t, | ||
1653 | (struct GNUNET_CADET_ChannelManage *) msgh, | ||
1654 | fwd); | ||
1655 | break; | ||
1656 | |||
1657 | case GNUNET_MESSAGE_TYPE_CADET_CHANNEL_DESTROY: | ||
1658 | handle_ch_destroy (t, | ||
1659 | (struct GNUNET_CADET_ChannelManage *) msgh, | ||
1660 | fwd); | ||
1661 | break; | ||
1662 | |||
1663 | default: | ||
1664 | GNUNET_break_op (0); | ||
1665 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1666 | "end-to-end message not known (%u)\n", | ||
1667 | ntohs (msgh->type)); | ||
1668 | GMT_debug (t); | ||
1669 | } | ||
1670 | } | ||
1671 | |||
1672 | /******************************************************************************/ | ||
1673 | /******************************** API ***********************************/ | ||
1674 | /******************************************************************************/ | ||
1675 | |||
1676 | /** | ||
1677 | * Decrypt and demultiplex by message type. Call appropriate handler | ||
1678 | * for every message. | ||
1679 | * | ||
1680 | * @param t Tunnel this message came on. | ||
1681 | * @param msg Encrypted message. | ||
1682 | */ | ||
1683 | void | ||
1684 | GMT_handle_encrypted (struct CadetTunnel3 *t, | ||
1685 | const struct GNUNET_CADET_Encrypted *msg) | ||
1686 | { | ||
1687 | size_t size = ntohs (msg->header.size); | ||
1688 | size_t payload_size = size - sizeof (struct GNUNET_CADET_Encrypted); | ||
1689 | size_t decrypted_size; | ||
1690 | char cbuf [payload_size]; | ||
1691 | struct GNUNET_MessageHeader *msgh; | ||
1692 | unsigned int off; | ||
1693 | struct GNUNET_CADET_Hash hmac; | ||
1694 | |||
1695 | decrypted_size = t_decrypt (t, cbuf, &msg[1], payload_size, msg->iv); | ||
1696 | t_hmac (t, &msg[1], payload_size, msg->iv, GNUNET_NO, &hmac); | ||
1697 | if (0 != memcmp (&hmac, &msg->hmac, sizeof (hmac))) | ||
1698 | { | ||
1699 | /* checksum failed */ | ||
1700 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1701 | "Failed checksum validation for a message on tunnel `%s'\n", | ||
1702 | GMT_2s (t)); | ||
1703 | GNUNET_STATISTICS_update (stats, "# wrong HMAC", 1, GNUNET_NO); | ||
1704 | return; | ||
1705 | } | ||
1706 | off = 0; | ||
1707 | while (off < decrypted_size) | ||
1708 | { | ||
1709 | msgh = (struct GNUNET_MessageHeader *) &cbuf[off]; | ||
1710 | handle_decrypted (t, msgh, GNUNET_SYSERR); | ||
1711 | off += ntohs (msgh->size); | ||
1712 | } | ||
1713 | } | ||
1714 | |||
1715 | |||
1716 | /** | ||
1717 | * Demultiplex an encapsulated KX message by message type. | ||
1718 | * | ||
1719 | * @param t Tunnel on which the message came. | ||
1720 | * @param message Payload of KX message. | ||
1721 | */ | ||
1722 | void | ||
1723 | GMT_handle_kx (struct CadetTunnel3 *t, | ||
1724 | const struct GNUNET_MessageHeader *message) | ||
1725 | { | ||
1726 | uint16_t type; | ||
1727 | |||
1728 | type = ntohs (message->type); | ||
1729 | LOG (GNUNET_ERROR_TYPE_DEBUG, "kx message received\n", type); | ||
1730 | switch (type) | ||
1731 | { | ||
1732 | case GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL: | ||
1733 | handle_ephemeral (t, (struct GNUNET_CADET_KX_Ephemeral *) message); | ||
1734 | break; | ||
1735 | |||
1736 | case GNUNET_MESSAGE_TYPE_CADET_KX_PING: | ||
1737 | handle_ping (t, (struct GNUNET_CADET_KX_Ping *) message); | ||
1738 | break; | ||
1739 | |||
1740 | case GNUNET_MESSAGE_TYPE_CADET_KX_PONG: | ||
1741 | handle_pong (t, (struct GNUNET_CADET_KX_Pong *) message); | ||
1742 | break; | ||
1743 | |||
1744 | default: | ||
1745 | GNUNET_break_op (0); | ||
1746 | LOG (GNUNET_ERROR_TYPE_DEBUG, "kx message not known (%u)\n", type); | ||
1747 | } | ||
1748 | } | ||
1749 | |||
1750 | |||
1751 | /** | ||
1752 | * Initialize the tunnel subsystem. | ||
1753 | * | ||
1754 | * @param c Configuration handle. | ||
1755 | * @param key ECC private key, to derive all other keys and do crypto. | ||
1756 | */ | ||
1757 | void | ||
1758 | GMT_init (const struct GNUNET_CONFIGURATION_Handle *c, | ||
1759 | const struct GNUNET_CRYPTO_EddsaPrivateKey *key) | ||
1760 | { | ||
1761 | LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); | ||
1762 | if (GNUNET_OK != | ||
1763 | GNUNET_CONFIGURATION_get_value_number (c, "CADET", "DEFAULT_TTL", | ||
1764 | &default_ttl)) | ||
1765 | { | ||
1766 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1767 | "CADET", "DEFAULT_TTL", "USING DEFAULT"); | ||
1768 | default_ttl = 64; | ||
1769 | } | ||
1770 | if (GNUNET_OK != | ||
1771 | GNUNET_CONFIGURATION_get_value_time (c, "CADET", "REKEY_PERIOD", | ||
1772 | &rekey_period)) | ||
1773 | { | ||
1774 | rekey_period = GNUNET_TIME_UNIT_DAYS; | ||
1775 | } | ||
1776 | |||
1777 | my_private_key = key; | ||
1778 | kx_msg.header.size = htons (sizeof (kx_msg)); | ||
1779 | kx_msg.header.type = htons (GNUNET_MESSAGE_TYPE_CADET_KX_EPHEMERAL); | ||
1780 | kx_msg.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CADET_KX); | ||
1781 | kx_msg.purpose.size = htonl (ephemeral_purpose_size ()); | ||
1782 | kx_msg.origin_identity = my_full_id; | ||
1783 | rekey_task = GNUNET_SCHEDULER_add_now (&rekey, NULL); | ||
1784 | |||
1785 | tunnels = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES); | ||
1786 | } | ||
1787 | |||
1788 | |||
1789 | /** | ||
1790 | * Shut down the tunnel subsystem. | ||
1791 | */ | ||
1792 | void | ||
1793 | GMT_shutdown (void) | ||
1794 | { | ||
1795 | if (GNUNET_SCHEDULER_NO_TASK != rekey_task) | ||
1796 | { | ||
1797 | GNUNET_SCHEDULER_cancel (rekey_task); | ||
1798 | rekey_task = GNUNET_SCHEDULER_NO_TASK; | ||
1799 | } | ||
1800 | GNUNET_CONTAINER_multipeermap_iterate (tunnels, &destroy_iterator, NULL); | ||
1801 | GNUNET_CONTAINER_multipeermap_destroy (tunnels); | ||
1802 | } | ||
1803 | |||
1804 | |||
1805 | /** | ||
1806 | * Create a tunnel. | ||
1807 | * | ||
1808 | * @param destination Peer this tunnel is towards. | ||
1809 | */ | ||
1810 | struct CadetTunnel3 * | ||
1811 | GMT_new (struct CadetPeer *destination) | ||
1812 | { | ||
1813 | struct CadetTunnel3 *t; | ||
1814 | |||
1815 | t = GNUNET_new (struct CadetTunnel3); | ||
1816 | t->next_chid = 0; | ||
1817 | t->peer = destination; | ||
1818 | |||
1819 | if (GNUNET_OK != | ||
1820 | GNUNET_CONTAINER_multipeermap_put (tunnels, GMP_get_id (destination), t, | ||
1821 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
1822 | { | ||
1823 | GNUNET_break (0); | ||
1824 | GNUNET_free (t); | ||
1825 | return NULL; | ||
1826 | } | ||
1827 | return t; | ||
1828 | } | ||
1829 | |||
1830 | |||
1831 | /** | ||
1832 | * Change the tunnel's connection state. | ||
1833 | * | ||
1834 | * @param t Tunnel whose connection state to change. | ||
1835 | * @param cstate New connection state. | ||
1836 | */ | ||
1837 | void | ||
1838 | GMT_change_cstate (struct CadetTunnel3* t, enum CadetTunnel3CState cstate) | ||
1839 | { | ||
1840 | if (NULL == t) | ||
1841 | return; | ||
1842 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s cstate %s => %s\n", | ||
1843 | GMP_2s (t->peer), cstate2s (t->cstate), cstate2s (cstate)); | ||
1844 | if (myid != GMP_get_short_id (t->peer) && | ||
1845 | CADET_TUNNEL3_READY != t->cstate && | ||
1846 | CADET_TUNNEL3_READY == cstate) | ||
1847 | { | ||
1848 | t->cstate = cstate; | ||
1849 | if (CADET_TUNNEL3_KEY_OK == t->estate) | ||
1850 | { | ||
1851 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered send queued data\n"); | ||
1852 | send_queued_data (t); | ||
1853 | } | ||
1854 | else if (CADET_TUNNEL3_KEY_UNINITIALIZED == t->estate) | ||
1855 | { | ||
1856 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered rekey\n"); | ||
1857 | rekey_tunnel (t, NULL); | ||
1858 | } | ||
1859 | } | ||
1860 | t->cstate = cstate; | ||
1861 | |||
1862 | if (CADET_TUNNEL3_READY == cstate | ||
1863 | && CONNECTIONS_PER_TUNNEL <= GMT_count_connections (t)) | ||
1864 | { | ||
1865 | LOG (GNUNET_ERROR_TYPE_DEBUG, " cstate triggered stop dht\n"); | ||
1866 | GMP_stop_search (t->peer); | ||
1867 | } | ||
1868 | } | ||
1869 | |||
1870 | /** | ||
1871 | * Change the tunnel encryption state. | ||
1872 | * | ||
1873 | * @param t Tunnel whose encryption state to change. | ||
1874 | * @param state New encryption state. | ||
1875 | */ | ||
1876 | void | ||
1877 | GMT_change_estate (struct CadetTunnel3* t, enum CadetTunnel3EState state) | ||
1878 | { | ||
1879 | if (NULL == t) | ||
1880 | return; | ||
1881 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1882 | "Tunnel %s estate was %s\n", | ||
1883 | GMP_2s (t->peer), estate2s (t->estate)); | ||
1884 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1885 | "Tunnel %s estate is now %s\n", | ||
1886 | GMP_2s (t->peer), estate2s (state)); | ||
1887 | if (myid != GMP_get_short_id (t->peer) && | ||
1888 | CADET_TUNNEL3_KEY_OK != t->estate && CADET_TUNNEL3_KEY_OK == state) | ||
1889 | { | ||
1890 | t->estate = state; | ||
1891 | send_queued_data (t); | ||
1892 | return; | ||
1893 | } | ||
1894 | t->estate = state; | ||
1895 | } | ||
1896 | |||
1897 | |||
1898 | /** | ||
1899 | * @brief Check if tunnel has too many connections, and remove one if necessary. | ||
1900 | * | ||
1901 | * Currently this means the newest connection, unless it is a direct one. | ||
1902 | * Implemented as a task to avoid freeing a connection that is in the middle | ||
1903 | * of being created/processed. | ||
1904 | * | ||
1905 | * @param cls Closure (Tunnel to check). | ||
1906 | * @param tc Task context. | ||
1907 | */ | ||
1908 | static void | ||
1909 | trim_connections (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1910 | { | ||
1911 | struct CadetTunnel3 *t = cls; | ||
1912 | |||
1913 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
1914 | return; | ||
1915 | |||
1916 | if (GMT_count_connections (t) > 2 * CONNECTIONS_PER_TUNNEL) | ||
1917 | { | ||
1918 | struct CadetTConnection *iter; | ||
1919 | struct CadetTConnection *c; | ||
1920 | |||
1921 | for (c = iter = t->connection_head; NULL != iter; iter = iter->next) | ||
1922 | { | ||
1923 | if ((NULL == c || iter->created.abs_value_us > c->created.abs_value_us) | ||
1924 | && GNUNET_NO == GMC_is_direct (iter->c)) | ||
1925 | { | ||
1926 | c = iter; | ||
1927 | } | ||
1928 | } | ||
1929 | if (NULL != c) | ||
1930 | { | ||
1931 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Too many connections on tunnel %s\n", | ||
1932 | GMT_2s (t)); | ||
1933 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying connection %s\n", | ||
1934 | GMC_2s (c->c)); | ||
1935 | GMC_destroy (c->c); | ||
1936 | } | ||
1937 | else | ||
1938 | { | ||
1939 | GNUNET_break (0); | ||
1940 | } | ||
1941 | } | ||
1942 | } | ||
1943 | |||
1944 | |||
1945 | /** | ||
1946 | * Add a connection to a tunnel. | ||
1947 | * | ||
1948 | * @param t Tunnel. | ||
1949 | * @param c Connection. | ||
1950 | */ | ||
1951 | void | ||
1952 | GMT_add_connection (struct CadetTunnel3 *t, struct CadetConnection *c) | ||
1953 | { | ||
1954 | struct CadetTConnection *aux; | ||
1955 | |||
1956 | GNUNET_assert (NULL != c); | ||
1957 | |||
1958 | LOG (GNUNET_ERROR_TYPE_DEBUG, "add connection %s\n", GMC_2s (c)); | ||
1959 | LOG (GNUNET_ERROR_TYPE_DEBUG, " to tunnel %s\n", GMT_2s (t)); | ||
1960 | for (aux = t->connection_head; aux != NULL; aux = aux->next) | ||
1961 | if (aux->c == c) | ||
1962 | return; | ||
1963 | |||
1964 | aux = GNUNET_new (struct CadetTConnection); | ||
1965 | aux->c = c; | ||
1966 | aux->created = GNUNET_TIME_absolute_get (); | ||
1967 | |||
1968 | GNUNET_CONTAINER_DLL_insert (t->connection_head, t->connection_tail, aux); | ||
1969 | |||
1970 | GNUNET_SCHEDULER_add_now (&trim_connections, t); | ||
1971 | } | ||
1972 | |||
1973 | |||
1974 | /** | ||
1975 | * Mark a path as no longer valid for this tunnel: has been tried and failed. | ||
1976 | * | ||
1977 | * @param t Tunnel to update. | ||
1978 | * @param path Invalid path to remove. Is destroyed after removal. | ||
1979 | */ | ||
1980 | void | ||
1981 | GMT_remove_path (struct CadetTunnel3 *t, struct CadetPeerPath *path) | ||
1982 | { | ||
1983 | GMP_remove_path (t->peer, path); | ||
1984 | } | ||
1985 | |||
1986 | |||
1987 | /** | ||
1988 | * Remove a connection from a tunnel. | ||
1989 | * | ||
1990 | * @param t Tunnel. | ||
1991 | * @param c Connection. | ||
1992 | */ | ||
1993 | void | ||
1994 | GMT_remove_connection (struct CadetTunnel3 *t, | ||
1995 | struct CadetConnection *c) | ||
1996 | { | ||
1997 | struct CadetTConnection *aux; | ||
1998 | struct CadetTConnection *next; | ||
1999 | |||
2000 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing connection %s from tunnel %s\n", | ||
2001 | GMC_2s (c), GMT_2s (t)); | ||
2002 | for (aux = t->connection_head; aux != NULL; aux = next) | ||
2003 | { | ||
2004 | next = aux->next; | ||
2005 | if (aux->c == c) | ||
2006 | { | ||
2007 | GNUNET_CONTAINER_DLL_remove (t->connection_head, t->connection_tail, aux); | ||
2008 | GNUNET_free (aux); | ||
2009 | } | ||
2010 | } | ||
2011 | |||
2012 | /* Start new connections if needed */ | ||
2013 | if (CONNECTIONS_PER_TUNNEL < GMT_count_connections (t) | ||
2014 | && GNUNET_SCHEDULER_NO_TASK == t->destroy_task | ||
2015 | && CADET_TUNNEL3_SHUTDOWN != t->cstate | ||
2016 | && GNUNET_NO == shutting_down) | ||
2017 | { | ||
2018 | LOG (GNUNET_ERROR_TYPE_DEBUG, " no more connections, getting new ones\n"); | ||
2019 | t->cstate = CADET_TUNNEL3_SEARCHING; | ||
2020 | GMP_connect (t->peer); | ||
2021 | return; | ||
2022 | } | ||
2023 | |||
2024 | /* If not marked as ready, no change is needed */ | ||
2025 | if (CADET_TUNNEL3_READY != t->cstate) | ||
2026 | return; | ||
2027 | |||
2028 | /* Check if any connection is ready to maintaing cstate */ | ||
2029 | for (aux = t->connection_head; aux != NULL; aux = aux->next) | ||
2030 | if (CADET_CONNECTION_READY == GMC_get_state (aux->c)) | ||
2031 | return; | ||
2032 | |||
2033 | t->cstate = CADET_TUNNEL3_WAITING; | ||
2034 | } | ||
2035 | |||
2036 | |||
2037 | /** | ||
2038 | * Add a channel to a tunnel. | ||
2039 | * | ||
2040 | * @param t Tunnel. | ||
2041 | * @param ch Channel. | ||
2042 | */ | ||
2043 | void | ||
2044 | GMT_add_channel (struct CadetTunnel3 *t, struct CadetChannel *ch) | ||
2045 | { | ||
2046 | struct CadetTChannel *aux; | ||
2047 | |||
2048 | GNUNET_assert (NULL != ch); | ||
2049 | |||
2050 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Adding channel %p to tunnel %p\n", ch, t); | ||
2051 | |||
2052 | for (aux = t->channel_head; aux != NULL; aux = aux->next) | ||
2053 | { | ||
2054 | LOG (GNUNET_ERROR_TYPE_DEBUG, " already there %p\n", aux->ch); | ||
2055 | if (aux->ch == ch) | ||
2056 | return; | ||
2057 | } | ||
2058 | |||
2059 | aux = GNUNET_new (struct CadetTChannel); | ||
2060 | aux->ch = ch; | ||
2061 | LOG (GNUNET_ERROR_TYPE_DEBUG, " adding %p to %p\n", aux, t->channel_head); | ||
2062 | GNUNET_CONTAINER_DLL_insert_tail (t->channel_head, t->channel_tail, aux); | ||
2063 | |||
2064 | if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task) | ||
2065 | { | ||
2066 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
2067 | t->destroy_task = GNUNET_SCHEDULER_NO_TASK; | ||
2068 | LOG (GNUNET_ERROR_TYPE_DEBUG, " undo destroy!\n"); | ||
2069 | } | ||
2070 | } | ||
2071 | |||
2072 | |||
2073 | /** | ||
2074 | * Remove a channel from a tunnel. | ||
2075 | * | ||
2076 | * @param t Tunnel. | ||
2077 | * @param ch Channel. | ||
2078 | */ | ||
2079 | void | ||
2080 | GMT_remove_channel (struct CadetTunnel3 *t, struct CadetChannel *ch) | ||
2081 | { | ||
2082 | struct CadetTChannel *aux; | ||
2083 | |||
2084 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Removing channel %p from tunnel %p\n", ch, t); | ||
2085 | for (aux = t->channel_head; aux != NULL; aux = aux->next) | ||
2086 | { | ||
2087 | if (aux->ch == ch) | ||
2088 | { | ||
2089 | LOG (GNUNET_ERROR_TYPE_DEBUG, " found! %s\n", GMCH_2s (ch)); | ||
2090 | GNUNET_CONTAINER_DLL_remove (t->channel_head, t->channel_tail, aux); | ||
2091 | GNUNET_free (aux); | ||
2092 | return; | ||
2093 | } | ||
2094 | } | ||
2095 | } | ||
2096 | |||
2097 | |||
2098 | /** | ||
2099 | * Search for a channel by global ID. | ||
2100 | * | ||
2101 | * @param t Tunnel containing the channel. | ||
2102 | * @param chid Public channel number. | ||
2103 | * | ||
2104 | * @return channel handler, NULL if doesn't exist | ||
2105 | */ | ||
2106 | struct CadetChannel * | ||
2107 | GMT_get_channel (struct CadetTunnel3 *t, CADET_ChannelNumber chid) | ||
2108 | { | ||
2109 | struct CadetTChannel *iter; | ||
2110 | |||
2111 | if (NULL == t) | ||
2112 | return NULL; | ||
2113 | |||
2114 | for (iter = t->channel_head; NULL != iter; iter = iter->next) | ||
2115 | { | ||
2116 | if (GMCH_get_id (iter->ch) == chid) | ||
2117 | break; | ||
2118 | } | ||
2119 | |||
2120 | return NULL == iter ? NULL : iter->ch; | ||
2121 | } | ||
2122 | |||
2123 | |||
2124 | /** | ||
2125 | * @brief Destroy a tunnel and free all resources. | ||
2126 | * | ||
2127 | * Should only be called a while after the tunnel has been marked as destroyed, | ||
2128 | * in case there is a new channel added to the same peer shortly after marking | ||
2129 | * the tunnel. This way we avoid a new public key handshake. | ||
2130 | * | ||
2131 | * @param cls Closure (tunnel to destroy). | ||
2132 | * @param tc Task context. | ||
2133 | */ | ||
2134 | static void | ||
2135 | delayed_destroy (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
2136 | { | ||
2137 | struct CadetTunnel3 *t = cls; | ||
2138 | struct CadetTConnection *iter; | ||
2139 | |||
2140 | LOG (GNUNET_ERROR_TYPE_DEBUG, "delayed destroying tunnel %p\n", t); | ||
2141 | if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | ||
2142 | { | ||
2143 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
2144 | "Not destroying tunnel, due to shutdown. " | ||
2145 | "Tunnel at %p should have been freed by GMT_shutdown\n", t); | ||
2146 | return; | ||
2147 | } | ||
2148 | t->destroy_task = GNUNET_SCHEDULER_NO_TASK; | ||
2149 | t->cstate = CADET_TUNNEL3_SHUTDOWN; | ||
2150 | |||
2151 | for (iter = t->connection_head; NULL != iter; iter = iter->next) | ||
2152 | { | ||
2153 | GMC_send_destroy (iter->c); | ||
2154 | } | ||
2155 | GMT_destroy (t); | ||
2156 | } | ||
2157 | |||
2158 | |||
2159 | /** | ||
2160 | * Tunnel is empty: destroy it. | ||
2161 | * | ||
2162 | * Notifies all connections about the destruction. | ||
2163 | * | ||
2164 | * @param t Tunnel to destroy. | ||
2165 | */ | ||
2166 | void | ||
2167 | GMT_destroy_empty (struct CadetTunnel3 *t) | ||
2168 | { | ||
2169 | if (GNUNET_YES == shutting_down) | ||
2170 | return; /* Will be destroyed immediately anyway */ | ||
2171 | |||
2172 | if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task) | ||
2173 | { | ||
2174 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
2175 | "Tunnel %s is already scheduled for destruction\n", | ||
2176 | GMT_2s (t)); | ||
2177 | GNUNET_break (0); | ||
2178 | /* should never happen, tunnel can only become empty once, and the | ||
2179 | * task identifier should be NO_TASK (cleaned when the tunnel was created | ||
2180 | * or became un-empty) | ||
2181 | */ | ||
2182 | return; | ||
2183 | } | ||
2184 | |||
2185 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s empty: destroying scheduled\n", | ||
2186 | GMT_2s (t)); | ||
2187 | |||
2188 | t->destroy_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, | ||
2189 | &delayed_destroy, t); | ||
2190 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduled destroy of %p as %llX\n", | ||
2191 | t, t->destroy_task); | ||
2192 | } | ||
2193 | |||
2194 | |||
2195 | /** | ||
2196 | * Destroy tunnel if empty (no more channels). | ||
2197 | * | ||
2198 | * @param t Tunnel to destroy if empty. | ||
2199 | */ | ||
2200 | void | ||
2201 | GMT_destroy_if_empty (struct CadetTunnel3 *t) | ||
2202 | { | ||
2203 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel %s destroy if empty\n", GMT_2s (t)); | ||
2204 | if (1 < GMT_count_channels (t)) | ||
2205 | return; | ||
2206 | |||
2207 | GMT_destroy_empty (t); | ||
2208 | } | ||
2209 | |||
2210 | |||
2211 | /** | ||
2212 | * Destroy the tunnel. | ||
2213 | * | ||
2214 | * This function does not generate any warning traffic to clients or peers. | ||
2215 | * | ||
2216 | * Tasks: | ||
2217 | * Cancel messages belonging to this tunnel queued to neighbors. | ||
2218 | * Free any allocated resources linked to the tunnel. | ||
2219 | * | ||
2220 | * @param t The tunnel to destroy. | ||
2221 | */ | ||
2222 | void | ||
2223 | GMT_destroy (struct CadetTunnel3 *t) | ||
2224 | { | ||
2225 | struct CadetTConnection *iter_c; | ||
2226 | struct CadetTConnection *next_c; | ||
2227 | struct CadetTChannel *iter_ch; | ||
2228 | struct CadetTChannel *next_ch; | ||
2229 | |||
2230 | if (NULL == t) | ||
2231 | return; | ||
2232 | |||
2233 | LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s\n", GMP_2s (t->peer)); | ||
2234 | |||
2235 | GNUNET_break (GNUNET_YES == | ||
2236 | GNUNET_CONTAINER_multipeermap_remove (tunnels, | ||
2237 | GMP_get_id (t->peer), t)); | ||
2238 | |||
2239 | for (iter_c = t->connection_head; NULL != iter_c; iter_c = next_c) | ||
2240 | { | ||
2241 | next_c = iter_c->next; | ||
2242 | GMC_destroy (iter_c->c); | ||
2243 | } | ||
2244 | for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = next_ch) | ||
2245 | { | ||
2246 | next_ch = iter_ch->next; | ||
2247 | GMCH_destroy (iter_ch->ch); | ||
2248 | /* Should only happen on shutdown, but it's ok. */ | ||
2249 | } | ||
2250 | |||
2251 | if (GNUNET_SCHEDULER_NO_TASK != t->destroy_task) | ||
2252 | { | ||
2253 | LOG (GNUNET_ERROR_TYPE_DEBUG, "cancelling %llX\n", t->destroy_task); | ||
2254 | GNUNET_SCHEDULER_cancel (t->destroy_task); | ||
2255 | t->destroy_task = GNUNET_SCHEDULER_NO_TASK; | ||
2256 | } | ||
2257 | |||
2258 | GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO); | ||
2259 | GMP_set_tunnel (t->peer, NULL); | ||
2260 | |||
2261 | if (GNUNET_SCHEDULER_NO_TASK != t->rekey_task) | ||
2262 | { | ||
2263 | GNUNET_SCHEDULER_cancel (t->rekey_task); | ||
2264 | t->rekey_task = GNUNET_SCHEDULER_NO_TASK; | ||
2265 | if (NULL != t->kx_ctx) | ||
2266 | GNUNET_free (t->kx_ctx); | ||
2267 | else | ||
2268 | GNUNET_break (0); | ||
2269 | } | ||
2270 | |||
2271 | GNUNET_free (t); | ||
2272 | } | ||
2273 | |||
2274 | |||
2275 | /** | ||
2276 | * @brief Use the given path for the tunnel. | ||
2277 | * Update the next and prev hops (and RCs). | ||
2278 | * (Re)start the path refresh in case the tunnel is locally owned. | ||
2279 | * | ||
2280 | * @param t Tunnel to update. | ||
2281 | * @param p Path to use. | ||
2282 | * | ||
2283 | * @return Connection created. | ||
2284 | */ | ||
2285 | struct CadetConnection * | ||
2286 | GMT_use_path (struct CadetTunnel3 *t, struct CadetPeerPath *p) | ||
2287 | { | ||
2288 | struct CadetConnection *c; | ||
2289 | struct GNUNET_CADET_Hash cid; | ||
2290 | unsigned int own_pos; | ||
2291 | |||
2292 | if (NULL == t || NULL == p) | ||
2293 | { | ||
2294 | GNUNET_break (0); | ||
2295 | return NULL; | ||
2296 | } | ||
2297 | |||
2298 | if (CADET_TUNNEL3_SHUTDOWN == t->cstate) | ||
2299 | { | ||
2300 | GNUNET_break (0); | ||
2301 | return NULL; | ||
2302 | } | ||
2303 | |||
2304 | for (own_pos = 0; own_pos < p->length; own_pos++) | ||
2305 | { | ||
2306 | if (p->peers[own_pos] == myid) | ||
2307 | break; | ||
2308 | } | ||
2309 | if (own_pos >= p->length) | ||
2310 | { | ||
2311 | GNUNET_break_op (0); | ||
2312 | return NULL; | ||
2313 | } | ||
2314 | |||
2315 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, &cid, sizeof (cid)); | ||
2316 | c = GMC_new (&cid, t, p, own_pos); | ||
2317 | if (NULL == c) | ||
2318 | { | ||
2319 | /* Path was flawed */ | ||
2320 | return NULL; | ||
2321 | } | ||
2322 | GMT_add_connection (t, c); | ||
2323 | return c; | ||
2324 | } | ||
2325 | |||
2326 | |||
2327 | /** | ||
2328 | * Count established (ready) connections of a tunnel. | ||
2329 | * | ||
2330 | * @param t Tunnel on which to count. | ||
2331 | * | ||
2332 | * @return Number of connections. | ||
2333 | */ | ||
2334 | unsigned int | ||
2335 | GMT_count_connections (struct CadetTunnel3 *t) | ||
2336 | { | ||
2337 | struct CadetTConnection *iter; | ||
2338 | unsigned int count; | ||
2339 | |||
2340 | if (NULL == t) | ||
2341 | return 0; | ||
2342 | |||
2343 | for (count = 0, iter = t->connection_head; NULL != iter; iter = iter->next) | ||
2344 | if (CADET_CONNECTION_DESTROYED != GMC_get_state (iter->c)) | ||
2345 | count++; | ||
2346 | |||
2347 | return count; | ||
2348 | } | ||
2349 | |||
2350 | /** | ||
2351 | * Count channels of a tunnel. | ||
2352 | * | ||
2353 | * @param t Tunnel on which to count. | ||
2354 | * | ||
2355 | * @return Number of channels. | ||
2356 | */ | ||
2357 | unsigned int | ||
2358 | GMT_count_channels (struct CadetTunnel3 *t) | ||
2359 | { | ||
2360 | struct CadetTChannel *iter; | ||
2361 | unsigned int count; | ||
2362 | |||
2363 | for (count = 0, iter = t->channel_head; | ||
2364 | NULL != iter; | ||
2365 | iter = iter->next, count++) /* skip */; | ||
2366 | |||
2367 | return count; | ||
2368 | } | ||
2369 | |||
2370 | |||
2371 | /** | ||
2372 | * Get the connectivity state of a tunnel. | ||
2373 | * | ||
2374 | * @param t Tunnel. | ||
2375 | * | ||
2376 | * @return Tunnel's connectivity state. | ||
2377 | */ | ||
2378 | enum CadetTunnel3CState | ||
2379 | GMT_get_cstate (struct CadetTunnel3 *t) | ||
2380 | { | ||
2381 | if (NULL == t) | ||
2382 | { | ||
2383 | GNUNET_assert (0); | ||
2384 | return (enum CadetTunnel3CState) -1; | ||
2385 | } | ||
2386 | return t->cstate; | ||
2387 | } | ||
2388 | |||
2389 | |||
2390 | /** | ||
2391 | * Get the encryption state of a tunnel. | ||
2392 | * | ||
2393 | * @param t Tunnel. | ||
2394 | * | ||
2395 | * @return Tunnel's encryption state. | ||
2396 | */ | ||
2397 | enum CadetTunnel3EState | ||
2398 | GMT_get_estate (struct CadetTunnel3 *t) | ||
2399 | { | ||
2400 | if (NULL == t) | ||
2401 | { | ||
2402 | GNUNET_assert (0); | ||
2403 | return (enum CadetTunnel3EState) -1; | ||
2404 | } | ||
2405 | return t->estate; | ||
2406 | } | ||
2407 | |||
2408 | /** | ||
2409 | * Get the maximum buffer space for a tunnel towards a local client. | ||
2410 | * | ||
2411 | * @param t Tunnel. | ||
2412 | * | ||
2413 | * @return Biggest buffer space offered by any channel in the tunnel. | ||
2414 | */ | ||
2415 | unsigned int | ||
2416 | GMT_get_channels_buffer (struct CadetTunnel3 *t) | ||
2417 | { | ||
2418 | struct CadetTChannel *iter; | ||
2419 | unsigned int buffer; | ||
2420 | unsigned int ch_buf; | ||
2421 | |||
2422 | if (NULL == t->channel_head) | ||
2423 | { | ||
2424 | /* Probably getting buffer for a channel create/handshake. */ | ||
2425 | return 64; | ||
2426 | } | ||
2427 | |||
2428 | buffer = 0; | ||
2429 | for (iter = t->channel_head; NULL != iter; iter = iter->next) | ||
2430 | { | ||
2431 | ch_buf = get_channel_buffer (iter); | ||
2432 | if (ch_buf > buffer) | ||
2433 | buffer = ch_buf; | ||
2434 | } | ||
2435 | return buffer; | ||
2436 | } | ||
2437 | |||
2438 | |||
2439 | /** | ||
2440 | * Get the total buffer space for a tunnel for P2P traffic. | ||
2441 | * | ||
2442 | * @param t Tunnel. | ||
2443 | * | ||
2444 | * @return Buffer space offered by all connections in the tunnel. | ||
2445 | */ | ||
2446 | unsigned int | ||
2447 | GMT_get_connections_buffer (struct CadetTunnel3 *t) | ||
2448 | { | ||
2449 | struct CadetTConnection *iter; | ||
2450 | unsigned int buffer; | ||
2451 | |||
2452 | buffer = 0; | ||
2453 | for (iter = t->connection_head; NULL != iter; iter = iter->next) | ||
2454 | { | ||
2455 | if (GMC_get_state (iter->c) != CADET_CONNECTION_READY) | ||
2456 | { | ||
2457 | continue; | ||
2458 | } | ||
2459 | buffer += get_connection_buffer (iter); | ||
2460 | } | ||
2461 | |||
2462 | return buffer; | ||
2463 | } | ||
2464 | |||
2465 | |||
2466 | /** | ||
2467 | * Get the tunnel's destination. | ||
2468 | * | ||
2469 | * @param t Tunnel. | ||
2470 | * | ||
2471 | * @return ID of the destination peer. | ||
2472 | */ | ||
2473 | const struct GNUNET_PeerIdentity * | ||
2474 | GMT_get_destination (struct CadetTunnel3 *t) | ||
2475 | { | ||
2476 | return GMP_get_id (t->peer); | ||
2477 | } | ||
2478 | |||
2479 | |||
2480 | /** | ||
2481 | * Get the tunnel's next free global channel ID. | ||
2482 | * | ||
2483 | * @param t Tunnel. | ||
2484 | * | ||
2485 | * @return GID of a channel free to use. | ||
2486 | */ | ||
2487 | CADET_ChannelNumber | ||
2488 | GMT_get_next_chid (struct CadetTunnel3 *t) | ||
2489 | { | ||
2490 | CADET_ChannelNumber chid; | ||
2491 | CADET_ChannelNumber mask; | ||
2492 | int result; | ||
2493 | |||
2494 | /* Set bit 30 depending on the ID relationship. Bit 31 is always 0 for GID. | ||
2495 | * If our ID is bigger or loopback tunnel, start at 0, bit 30 = 0 | ||
2496 | * If peer's ID is bigger, start at 0x4... bit 30 = 1 | ||
2497 | */ | ||
2498 | result = GNUNET_CRYPTO_cmp_peer_identity (&my_full_id, GMP_get_id (t->peer)); | ||
2499 | if (0 > result) | ||
2500 | mask = 0x40000000; | ||
2501 | else | ||
2502 | mask = 0x0; | ||
2503 | t->next_chid |= mask; | ||
2504 | |||
2505 | while (NULL != GMT_get_channel (t, t->next_chid)) | ||
2506 | { | ||
2507 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", t->next_chid); | ||
2508 | t->next_chid = (t->next_chid + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; | ||
2509 | t->next_chid |= mask; | ||
2510 | } | ||
2511 | chid = t->next_chid; | ||
2512 | t->next_chid = (t->next_chid + 1) & ~GNUNET_CADET_LOCAL_CHANNEL_ID_CLI; | ||
2513 | t->next_chid |= mask; | ||
2514 | |||
2515 | return chid; | ||
2516 | } | ||
2517 | |||
2518 | |||
2519 | /** | ||
2520 | * Send ACK on one or more channels due to buffer in connections. | ||
2521 | * | ||
2522 | * @param t Channel which has some free buffer space. | ||
2523 | */ | ||
2524 | void | ||
2525 | GMT_unchoke_channels (struct CadetTunnel3 *t) | ||
2526 | { | ||
2527 | struct CadetTChannel *iter; | ||
2528 | unsigned int buffer; | ||
2529 | unsigned int channels = GMT_count_channels (t); | ||
2530 | unsigned int choked_n; | ||
2531 | struct CadetChannel *choked[channels]; | ||
2532 | |||
2533 | LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_unchoke_channels on %s\n", GMT_2s (t)); | ||
2534 | LOG (GNUNET_ERROR_TYPE_DEBUG, " head: %p\n", t->channel_head); | ||
2535 | if (NULL != t->channel_head) | ||
2536 | LOG (GNUNET_ERROR_TYPE_DEBUG, " head ch: %p\n", t->channel_head->ch); | ||
2537 | |||
2538 | /* Get buffer space */ | ||
2539 | buffer = GMT_get_connections_buffer (t); | ||
2540 | if (0 == buffer) | ||
2541 | { | ||
2542 | return; | ||
2543 | } | ||
2544 | |||
2545 | /* Count and remember choked channels */ | ||
2546 | choked_n = 0; | ||
2547 | for (iter = t->channel_head; NULL != iter; iter = iter->next) | ||
2548 | { | ||
2549 | if (GNUNET_NO == get_channel_allowed (iter)) | ||
2550 | { | ||
2551 | choked[choked_n++] = iter->ch; | ||
2552 | } | ||
2553 | } | ||
2554 | |||
2555 | /* Unchoke random channels */ | ||
2556 | while (0 < buffer && 0 < choked_n) | ||
2557 | { | ||
2558 | unsigned int r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
2559 | choked_n); | ||
2560 | GMCH_allow_client (choked[r], GMCH_is_origin (choked[r], GNUNET_YES)); | ||
2561 | choked_n--; | ||
2562 | buffer--; | ||
2563 | choked[r] = choked[choked_n]; | ||
2564 | } | ||
2565 | } | ||
2566 | |||
2567 | |||
2568 | /** | ||
2569 | * Send ACK on one or more connections due to buffer space to the client. | ||
2570 | * | ||
2571 | * Iterates all connections of the tunnel and sends ACKs appropriately. | ||
2572 | * | ||
2573 | * @param t Tunnel. | ||
2574 | */ | ||
2575 | void | ||
2576 | GMT_send_connection_acks (struct CadetTunnel3 *t) | ||
2577 | { | ||
2578 | struct CadetTConnection *iter; | ||
2579 | uint32_t allowed; | ||
2580 | uint32_t to_allow; | ||
2581 | uint32_t allow_per_connection; | ||
2582 | unsigned int cs; | ||
2583 | unsigned int buffer; | ||
2584 | |||
2585 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Tunnel send connection ACKs on %s\n", | ||
2586 | GMT_2s (t)); | ||
2587 | |||
2588 | if (NULL == t) | ||
2589 | { | ||
2590 | GNUNET_break (0); | ||
2591 | return; | ||
2592 | } | ||
2593 | |||
2594 | buffer = GMT_get_channels_buffer (t); | ||
2595 | LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer %u\n", buffer); | ||
2596 | |||
2597 | /* Count connections, how many messages are already allowed */ | ||
2598 | cs = GMT_count_connections (t); | ||
2599 | for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next) | ||
2600 | { | ||
2601 | allowed += get_connection_allowed (iter); | ||
2602 | } | ||
2603 | LOG (GNUNET_ERROR_TYPE_DEBUG, " allowed %u\n", allowed); | ||
2604 | |||
2605 | /* Make sure there is no overflow */ | ||
2606 | if (allowed > buffer) | ||
2607 | { | ||
2608 | return; | ||
2609 | } | ||
2610 | |||
2611 | /* Authorize connections to send more data */ | ||
2612 | to_allow = buffer; /* - allowed; */ | ||
2613 | |||
2614 | for (iter = t->connection_head; | ||
2615 | NULL != iter && to_allow > 0; | ||
2616 | iter = iter->next) | ||
2617 | { | ||
2618 | allow_per_connection = to_allow/cs; | ||
2619 | to_allow -= allow_per_connection; | ||
2620 | cs--; | ||
2621 | if (get_connection_allowed (iter) > 64 / 3) | ||
2622 | { | ||
2623 | continue; | ||
2624 | } | ||
2625 | GMC_allow (iter->c, allow_per_connection, | ||
2626 | GMC_is_origin (iter->c, GNUNET_NO)); | ||
2627 | } | ||
2628 | |||
2629 | GNUNET_break (to_allow == 0); | ||
2630 | } | ||
2631 | |||
2632 | |||
2633 | /** | ||
2634 | * Cancel a previously sent message while it's in the queue. | ||
2635 | * | ||
2636 | * ONLY can be called before the continuation given to the send function | ||
2637 | * is called. Once the continuation is called, the message is no longer in the | ||
2638 | * queue. | ||
2639 | * | ||
2640 | * @param q Handle to the queue. | ||
2641 | */ | ||
2642 | void | ||
2643 | GMT_cancel (struct CadetTunnel3Queue *q) | ||
2644 | { | ||
2645 | if (NULL != q->cq) | ||
2646 | { | ||
2647 | GMC_cancel (q->cq); | ||
2648 | /* tun_message_sent() will be called and free q */ | ||
2649 | } | ||
2650 | else if (NULL != q->tqd) | ||
2651 | { | ||
2652 | unqueue_data (q->tqd); | ||
2653 | q->tqd = NULL; | ||
2654 | if (NULL != q->cont) | ||
2655 | q->cont (q->cont_cls, NULL, q, 0, 0); | ||
2656 | GNUNET_free (q); | ||
2657 | } | ||
2658 | else | ||
2659 | { | ||
2660 | GNUNET_break (0); | ||
2661 | } | ||
2662 | } | ||
2663 | |||
2664 | |||
2665 | /** | ||
2666 | * Sends an already built message on a tunnel, encrypting it and | ||
2667 | * choosing the best connection if not provided. | ||
2668 | * | ||
2669 | * @param message Message to send. Function modifies it. | ||
2670 | * @param t Tunnel on which this message is transmitted. | ||
2671 | * @param c Connection to use (autoselect if NULL). | ||
2672 | * @param force Force the tunnel to take the message (buffer overfill). | ||
2673 | * @param cont Continuation to call once message is really sent. | ||
2674 | * @param cont_cls Closure for @c cont. | ||
2675 | * | ||
2676 | * @return Handle to cancel message. NULL if @c cont is NULL. | ||
2677 | */ | ||
2678 | struct CadetTunnel3Queue * | ||
2679 | GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
2680 | struct CadetTunnel3 *t, struct CadetConnection *c, | ||
2681 | int force, GMT_sent cont, void *cont_cls) | ||
2682 | { | ||
2683 | return send_prebuilt_message (message, t, c, force, cont, cont_cls, NULL); | ||
2684 | } | ||
2685 | |||
2686 | |||
2687 | /** | ||
2688 | * Is the tunnel directed towards the local peer? | ||
2689 | * | ||
2690 | * @param t Tunnel. | ||
2691 | * | ||
2692 | * @return #GNUNET_YES if it is loopback. | ||
2693 | */ | ||
2694 | int | ||
2695 | GMT_is_loopback (const struct CadetTunnel3 *t) | ||
2696 | { | ||
2697 | return (myid == GMP_get_short_id (t->peer)); | ||
2698 | } | ||
2699 | |||
2700 | |||
2701 | /** | ||
2702 | * Is the tunnel this path already? | ||
2703 | * | ||
2704 | * @param t Tunnel. | ||
2705 | * @param p Path. | ||
2706 | * | ||
2707 | * @return #GNUNET_YES a connection uses this path. | ||
2708 | */ | ||
2709 | int | ||
2710 | GMT_is_path_used (const struct CadetTunnel3 *t, const struct CadetPeerPath *p) | ||
2711 | { | ||
2712 | struct CadetTConnection *iter; | ||
2713 | |||
2714 | for (iter = t->connection_head; NULL != iter; iter = iter->next) | ||
2715 | if (GMC_get_path (iter->c) == p) | ||
2716 | return GNUNET_YES; | ||
2717 | |||
2718 | return GNUNET_NO; | ||
2719 | } | ||
2720 | |||
2721 | |||
2722 | /** | ||
2723 | * Get a cost of a path for a tunnel considering existing connections. | ||
2724 | * | ||
2725 | * @param t Tunnel. | ||
2726 | * @param path Candidate path. | ||
2727 | * | ||
2728 | * @return Cost of the path (path length + number of overlapping nodes) | ||
2729 | */ | ||
2730 | unsigned int | ||
2731 | GMT_get_path_cost (const struct CadetTunnel3 *t, | ||
2732 | const struct CadetPeerPath *path) | ||
2733 | { | ||
2734 | struct CadetTConnection *iter; | ||
2735 | const struct CadetPeerPath *aux; | ||
2736 | unsigned int overlap; | ||
2737 | unsigned int i; | ||
2738 | unsigned int j; | ||
2739 | |||
2740 | if (NULL == path) | ||
2741 | return 0; | ||
2742 | |||
2743 | overlap = 0; | ||
2744 | GNUNET_assert (NULL != t); | ||
2745 | |||
2746 | for (i = 0; i < path->length; i++) | ||
2747 | { | ||
2748 | for (iter = t->connection_head; NULL != iter; iter = iter->next) | ||
2749 | { | ||
2750 | aux = GMC_get_path (iter->c); | ||
2751 | if (NULL == aux) | ||
2752 | continue; | ||
2753 | |||
2754 | for (j = 0; j < aux->length; j++) | ||
2755 | { | ||
2756 | if (path->peers[i] == aux->peers[j]) | ||
2757 | { | ||
2758 | overlap++; | ||
2759 | break; | ||
2760 | } | ||
2761 | } | ||
2762 | } | ||
2763 | } | ||
2764 | return path->length + overlap; | ||
2765 | } | ||
2766 | |||
2767 | |||
2768 | /** | ||
2769 | * Get the static string for the peer this tunnel is directed. | ||
2770 | * | ||
2771 | * @param t Tunnel. | ||
2772 | * | ||
2773 | * @return Static string the destination peer's ID. | ||
2774 | */ | ||
2775 | const char * | ||
2776 | GMT_2s (const struct CadetTunnel3 *t) | ||
2777 | { | ||
2778 | if (NULL == t) | ||
2779 | return "(NULL)"; | ||
2780 | |||
2781 | return GMP_2s (t->peer); | ||
2782 | } | ||
2783 | |||
2784 | |||
2785 | /******************************************************************************/ | ||
2786 | /***************************** INFO/DEBUG *******************************/ | ||
2787 | /******************************************************************************/ | ||
2788 | |||
2789 | |||
2790 | /** | ||
2791 | * Log all possible info about the tunnel state to stderr. | ||
2792 | * | ||
2793 | * @param t Tunnel to debug. | ||
2794 | */ | ||
2795 | void | ||
2796 | GMT_debug (const struct CadetTunnel3 *t) | ||
2797 | { | ||
2798 | struct CadetTChannel *iterch; | ||
2799 | struct CadetTConnection *iterc; | ||
2800 | |||
2801 | LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT DEBUG TUNNEL TOWARDS %s\n", GMT_2s (t)); | ||
2802 | LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT cstate %s, estate %s\n", | ||
2803 | cstate2s (t->cstate), estate2s (t->estate)); | ||
2804 | LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT kx_ctx %p, rekey_task %u\n", | ||
2805 | t->kx_ctx, t->rekey_task); | ||
2806 | LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT tq_head %p, tq_tail %p\n", | ||
2807 | t->tq_head, t->tq_tail); | ||
2808 | LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT destroy %u\n", t->destroy_task); | ||
2809 | |||
2810 | LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT channels:\n"); | ||
2811 | for (iterch = t->channel_head; NULL != iterch; iterch = iterch->next) | ||
2812 | { | ||
2813 | LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT - %s\n", GMCH_2s (iterch->ch)); | ||
2814 | } | ||
2815 | |||
2816 | LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT connections:\n"); | ||
2817 | for (iterc = t->connection_head; NULL != iterc; iterc = iterc->next) | ||
2818 | { | ||
2819 | LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT - %s [%u] buf: %u/%u (qn %u/%u)\n", | ||
2820 | GMC_2s (iterc->c), GMC_get_state (iterc->c), | ||
2821 | GMC_get_buffer (iterc->c, GNUNET_YES), | ||
2822 | GMC_get_buffer (iterc->c, GNUNET_NO), | ||
2823 | GMC_get_qn (iterc->c, GNUNET_YES), | ||
2824 | GMC_get_qn (iterc->c, GNUNET_NO)); | ||
2825 | } | ||
2826 | |||
2827 | LOG (GNUNET_ERROR_TYPE_DEBUG, "TTT DEBUG TUNNEL END\n"); | ||
2828 | } | ||
2829 | |||
2830 | |||
2831 | /** | ||
2832 | * Iterate all tunnels. | ||
2833 | * | ||
2834 | * @param iter Iterator. | ||
2835 | * @param cls Closure for @c iter. | ||
2836 | */ | ||
2837 | void | ||
2838 | GMT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls) | ||
2839 | { | ||
2840 | GNUNET_CONTAINER_multipeermap_iterate (tunnels, iter, cls); | ||
2841 | } | ||
2842 | |||
2843 | |||
2844 | /** | ||
2845 | * Count all tunnels. | ||
2846 | * | ||
2847 | * @return Number of tunnels to remote peers kept by this peer. | ||
2848 | */ | ||
2849 | unsigned int | ||
2850 | GMT_count_all (void) | ||
2851 | { | ||
2852 | return GNUNET_CONTAINER_multipeermap_size (tunnels); | ||
2853 | } | ||
2854 | |||
2855 | |||
2856 | /** | ||
2857 | * Iterate all connections of a tunnel. | ||
2858 | * | ||
2859 | * @param t Tunnel whose connections to iterate. | ||
2860 | * @param iter Iterator. | ||
2861 | * @param cls Closure for @c iter. | ||
2862 | */ | ||
2863 | void | ||
2864 | GMT_iterate_connections (struct CadetTunnel3 *t, GMT_conn_iter iter, void *cls) | ||
2865 | { | ||
2866 | struct CadetTConnection *ct; | ||
2867 | |||
2868 | for (ct = t->connection_head; NULL != ct; ct = ct->next) | ||
2869 | iter (cls, ct->c); | ||
2870 | } | ||
2871 | |||
2872 | |||
2873 | /** | ||
2874 | * Iterate all channels of a tunnel. | ||
2875 | * | ||
2876 | * @param t Tunnel whose channels to iterate. | ||
2877 | * @param iter Iterator. | ||
2878 | * @param cls Closure for @c iter. | ||
2879 | */ | ||
2880 | void | ||
2881 | GMT_iterate_channels (struct CadetTunnel3 *t, GMT_chan_iter iter, void *cls) | ||
2882 | { | ||
2883 | struct CadetTChannel *cht; | ||
2884 | |||
2885 | for (cht = t->channel_head; NULL != cht; cht = cht->next) | ||
2886 | iter (cls, cht->ch); | ||
2887 | } | ||
diff --git a/src/cadet/gnunet-service-cadet_tunnel.h b/src/cadet/gnunet-service-cadet_tunnel.h new file mode 100644 index 000000000..16616de59 --- /dev/null +++ b/src/cadet/gnunet-service-cadet_tunnel.h | |||
@@ -0,0 +1,531 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, 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 | /** | ||
44 | * All the connectivity states a tunnel can be in. | ||
45 | */ | ||
46 | enum CadetTunnel3CState | ||
47 | { | ||
48 | /** | ||
49 | * Uninitialized status, should never appear in operation. | ||
50 | */ | ||
51 | CADET_TUNNEL3_NEW, | ||
52 | |||
53 | /** | ||
54 | * Path to the peer not known yet. | ||
55 | */ | ||
56 | CADET_TUNNEL3_SEARCHING, | ||
57 | |||
58 | /** | ||
59 | * Request sent, not yet answered. | ||
60 | */ | ||
61 | CADET_TUNNEL3_WAITING, | ||
62 | |||
63 | /** | ||
64 | * Peer connected and ready to accept data. | ||
65 | */ | ||
66 | CADET_TUNNEL3_READY, | ||
67 | |||
68 | /** | ||
69 | * Tunnel being shut down, don't try to keep it alive. | ||
70 | */ | ||
71 | CADET_TUNNEL3_SHUTDOWN | ||
72 | }; | ||
73 | |||
74 | |||
75 | /** | ||
76 | * All the encryption states a tunnel can be in. | ||
77 | */ | ||
78 | enum CadetTunnel3EState | ||
79 | { | ||
80 | /** | ||
81 | * Uninitialized status, should never appear in operation. | ||
82 | */ | ||
83 | CADET_TUNNEL3_KEY_UNINITIALIZED, | ||
84 | |||
85 | /** | ||
86 | * Ephemeral key sent, waiting for peer's key. | ||
87 | */ | ||
88 | CADET_TUNNEL3_KEY_SENT, | ||
89 | |||
90 | /** | ||
91 | * New ephemeral key and ping sent, waiting for pong. | ||
92 | * This means that we DO have the peer's ephemeral key, otherwise the | ||
93 | * state would be KEY_SENT. | ||
94 | */ | ||
95 | CADET_TUNNEL3_KEY_PING, | ||
96 | |||
97 | /** | ||
98 | * Handshake completed: session key available. | ||
99 | */ | ||
100 | CADET_TUNNEL3_KEY_OK, | ||
101 | }; | ||
102 | |||
103 | /** | ||
104 | * Struct containing all information regarding a given peer | ||
105 | */ | ||
106 | struct CadetTunnel3; | ||
107 | |||
108 | |||
109 | #include "gnunet-service-cadet_channel.h" | ||
110 | #include "gnunet-service-cadet_connection.h" | ||
111 | #include "gnunet-service-cadet_peer.h" | ||
112 | |||
113 | /** | ||
114 | * Handle for messages queued but not yet sent. | ||
115 | */ | ||
116 | struct CadetTunnel3Queue; | ||
117 | |||
118 | /** | ||
119 | * Callback called when a queued message is sent. | ||
120 | * | ||
121 | * @param cls Closure. | ||
122 | * @param t Tunnel this message was on. | ||
123 | * @param type Type of message sent. | ||
124 | * @param size Size of the message. | ||
125 | */ | ||
126 | typedef void (*GMT_sent) (void *cls, | ||
127 | struct CadetTunnel3 *t, | ||
128 | struct CadetTunnel3Queue *q, | ||
129 | uint16_t type, size_t size); | ||
130 | |||
131 | typedef void (*GMT_conn_iter) (void *cls, struct CadetConnection *c); | ||
132 | typedef void (*GMT_chan_iter) (void *cls, struct CadetChannel *ch); | ||
133 | |||
134 | |||
135 | /******************************************************************************/ | ||
136 | /******************************** API ***********************************/ | ||
137 | /******************************************************************************/ | ||
138 | |||
139 | /** | ||
140 | * Initialize tunnel subsystem. | ||
141 | * | ||
142 | * @param c Configuration handle. | ||
143 | * @param key ECC private key, to derive all other keys and do crypto. | ||
144 | */ | ||
145 | void | ||
146 | GMT_init (const struct GNUNET_CONFIGURATION_Handle *c, | ||
147 | const struct GNUNET_CRYPTO_EddsaPrivateKey *key); | ||
148 | |||
149 | /** | ||
150 | * Shut down the tunnel subsystem. | ||
151 | */ | ||
152 | void | ||
153 | GMT_shutdown (void); | ||
154 | |||
155 | /** | ||
156 | * Create a tunnel. | ||
157 | * | ||
158 | * @param destination Peer this tunnel is towards. | ||
159 | */ | ||
160 | struct CadetTunnel3 * | ||
161 | GMT_new (struct CadetPeer *destination); | ||
162 | |||
163 | /** | ||
164 | * Tunnel is empty: destroy it. | ||
165 | * | ||
166 | * Notifies all connections about the destruction. | ||
167 | * | ||
168 | * @param t Tunnel to destroy. | ||
169 | */ | ||
170 | void | ||
171 | GMT_destroy_empty (struct CadetTunnel3 *t); | ||
172 | |||
173 | /** | ||
174 | * Destroy tunnel if empty (no more channels). | ||
175 | * | ||
176 | * @param t Tunnel to destroy if empty. | ||
177 | */ | ||
178 | void | ||
179 | GMT_destroy_if_empty (struct CadetTunnel3 *t); | ||
180 | |||
181 | /** | ||
182 | * Destroy the tunnel. | ||
183 | * | ||
184 | * This function does not generate any warning traffic to clients or peers. | ||
185 | * | ||
186 | * Tasks: | ||
187 | * Cancel messages belonging to this tunnel queued to neighbors. | ||
188 | * Free any allocated resources linked to the tunnel. | ||
189 | * | ||
190 | * @param t The tunnel to destroy. | ||
191 | */ | ||
192 | void | ||
193 | GMT_destroy (struct CadetTunnel3 *t); | ||
194 | |||
195 | |||
196 | /** | ||
197 | * Change the tunnel's connection state. | ||
198 | * | ||
199 | * @param t Tunnel whose connection state to change. | ||
200 | * @param cstate New connection state. | ||
201 | */ | ||
202 | void | ||
203 | GMT_change_cstate (struct CadetTunnel3* t, enum CadetTunnel3CState cstate); | ||
204 | |||
205 | |||
206 | /** | ||
207 | * Change the tunnel encryption state. | ||
208 | * | ||
209 | * @param t Tunnel whose encryption state to change. | ||
210 | * @param state New encryption state. | ||
211 | */ | ||
212 | void | ||
213 | GMT_change_estate (struct CadetTunnel3* t, enum CadetTunnel3EState state); | ||
214 | |||
215 | /** | ||
216 | * Add a connection to a tunnel. | ||
217 | * | ||
218 | * @param t Tunnel. | ||
219 | * @param c Connection. | ||
220 | */ | ||
221 | void | ||
222 | GMT_add_connection (struct CadetTunnel3 *t, struct CadetConnection *c); | ||
223 | |||
224 | /** | ||
225 | * Mark a path as no longer valid for this tunnel: has been tried and failed. | ||
226 | * | ||
227 | * @param t Tunnel to update. | ||
228 | * @param path Invalid path to remove. Is destroyed after removal. | ||
229 | */ | ||
230 | void | ||
231 | GMT_remove_path (struct CadetTunnel3 *t, struct CadetPeerPath *path); | ||
232 | |||
233 | /** | ||
234 | * Remove a connection from a tunnel. | ||
235 | * | ||
236 | * @param t Tunnel. | ||
237 | * @param c Connection. | ||
238 | */ | ||
239 | void | ||
240 | GMT_remove_connection (struct CadetTunnel3 *t, struct CadetConnection *c); | ||
241 | |||
242 | /** | ||
243 | * Add a channel to a tunnel. | ||
244 | * | ||
245 | * @param t Tunnel. | ||
246 | * @param ch Channel. | ||
247 | */ | ||
248 | void | ||
249 | GMT_add_channel (struct CadetTunnel3 *t, struct CadetChannel *ch); | ||
250 | |||
251 | /** | ||
252 | * Remove a channel from a tunnel. | ||
253 | * | ||
254 | * @param t Tunnel. | ||
255 | * @param ch Channel. | ||
256 | */ | ||
257 | void | ||
258 | GMT_remove_channel (struct CadetTunnel3 *t, struct CadetChannel *ch); | ||
259 | |||
260 | /** | ||
261 | * Search for a channel by global ID. | ||
262 | * | ||
263 | * @param t Tunnel containing the channel. | ||
264 | * @param chid Public channel number. | ||
265 | * | ||
266 | * @return channel handler, NULL if doesn't exist | ||
267 | */ | ||
268 | struct CadetChannel * | ||
269 | GMT_get_channel (struct CadetTunnel3 *t, CADET_ChannelNumber chid); | ||
270 | |||
271 | /** | ||
272 | * Decrypt and demultiplex by message type. Call appropriate handler | ||
273 | * for a message | ||
274 | * towards a channel of a local tunnel. | ||
275 | * | ||
276 | * @param t Tunnel this message came on. | ||
277 | * @param msg Message header. | ||
278 | */ | ||
279 | void | ||
280 | GMT_handle_encrypted (struct CadetTunnel3 *t, | ||
281 | const struct GNUNET_CADET_Encrypted *msg); | ||
282 | |||
283 | /** | ||
284 | * Demultiplex an encapsulated KX message by message type. | ||
285 | * | ||
286 | * @param t Tunnel on which the message came. | ||
287 | * @param message KX message itself. | ||
288 | */ | ||
289 | void | ||
290 | GMT_handle_kx (struct CadetTunnel3 *t, | ||
291 | const struct GNUNET_MessageHeader *message); | ||
292 | |||
293 | /** | ||
294 | * @brief Use the given path for the tunnel. | ||
295 | * Update the next and prev hops (and RCs). | ||
296 | * (Re)start the path refresh in case the tunnel is locally owned. | ||
297 | * | ||
298 | * @param t Tunnel to update. | ||
299 | * @param p Path to use. | ||
300 | * | ||
301 | * @return Connection created. | ||
302 | */ | ||
303 | struct CadetConnection * | ||
304 | GMT_use_path (struct CadetTunnel3 *t, struct CadetPeerPath *p); | ||
305 | |||
306 | /** | ||
307 | * Count established (ready) connections of a tunnel. | ||
308 | * | ||
309 | * @param t Tunnel on which to count. | ||
310 | * | ||
311 | * @return Number of connections. | ||
312 | */ | ||
313 | unsigned int | ||
314 | GMT_count_connections (struct CadetTunnel3 *t); | ||
315 | |||
316 | /** | ||
317 | * Count channels of a tunnel. | ||
318 | * | ||
319 | * @param t Tunnel on which to count. | ||
320 | * | ||
321 | * @return Number of channels. | ||
322 | */ | ||
323 | unsigned int | ||
324 | GMT_count_channels (struct CadetTunnel3 *t); | ||
325 | |||
326 | /** | ||
327 | * Get the connectivity state of a tunnel. | ||
328 | * | ||
329 | * @param t Tunnel. | ||
330 | * | ||
331 | * @return Tunnel's connectivity state. | ||
332 | */ | ||
333 | enum CadetTunnel3CState | ||
334 | GMT_get_cstate (struct CadetTunnel3 *t); | ||
335 | |||
336 | /** | ||
337 | * Get the encryption state of a tunnel. | ||
338 | * | ||
339 | * @param t Tunnel. | ||
340 | * | ||
341 | * @return Tunnel's encryption state. | ||
342 | */ | ||
343 | enum CadetTunnel3EState | ||
344 | GMT_get_estate (struct CadetTunnel3 *t); | ||
345 | |||
346 | /** | ||
347 | * Get the maximum buffer space for a tunnel towards a local client. | ||
348 | * | ||
349 | * @param t Tunnel. | ||
350 | * | ||
351 | * @return Biggest buffer space offered by any channel in the tunnel. | ||
352 | */ | ||
353 | unsigned int | ||
354 | GMT_get_channels_buffer (struct CadetTunnel3 *t); | ||
355 | |||
356 | /** | ||
357 | * Get the total buffer space for a tunnel for P2P traffic. | ||
358 | * | ||
359 | * @param t Tunnel. | ||
360 | * | ||
361 | * @return Buffer space offered by all connections in the tunnel. | ||
362 | */ | ||
363 | unsigned int | ||
364 | GMT_get_connections_buffer (struct CadetTunnel3 *t); | ||
365 | |||
366 | /** | ||
367 | * Get the tunnel's destination. | ||
368 | * | ||
369 | * @param t Tunnel. | ||
370 | * | ||
371 | * @return ID of the destination peer. | ||
372 | */ | ||
373 | const struct GNUNET_PeerIdentity * | ||
374 | GMT_get_destination (struct CadetTunnel3 *t); | ||
375 | |||
376 | /** | ||
377 | * Get the tunnel's next free Channel ID. | ||
378 | * | ||
379 | * @param t Tunnel. | ||
380 | * | ||
381 | * @return ID of a channel free to use. | ||
382 | */ | ||
383 | CADET_ChannelNumber | ||
384 | GMT_get_next_chid (struct CadetTunnel3 *t); | ||
385 | |||
386 | /** | ||
387 | * Send ACK on one or more channels due to buffer in connections. | ||
388 | * | ||
389 | * @param t Channel which has some free buffer space. | ||
390 | */ | ||
391 | void | ||
392 | GMT_unchoke_channels (struct CadetTunnel3 *t); | ||
393 | |||
394 | /** | ||
395 | * Send ACK on one or more connections due to buffer space to the client. | ||
396 | * | ||
397 | * Iterates all connections of the tunnel and sends ACKs appropriately. | ||
398 | * | ||
399 | * @param t Tunnel which has some free buffer space. | ||
400 | */ | ||
401 | void | ||
402 | GMT_send_connection_acks (struct CadetTunnel3 *t); | ||
403 | |||
404 | /** | ||
405 | * Cancel a previously sent message while it's in the queue. | ||
406 | * | ||
407 | * ONLY can be called before the continuation given to the send function | ||
408 | * is called. Once the continuation is called, the message is no longer in the | ||
409 | * queue. | ||
410 | * | ||
411 | * @param q Handle to the queue. | ||
412 | */ | ||
413 | void | ||
414 | GMT_cancel (struct CadetTunnel3Queue *q); | ||
415 | |||
416 | /** | ||
417 | * Sends an already built message on a tunnel, encrypting it and | ||
418 | * choosing the best connection. | ||
419 | * | ||
420 | * @param message Message to send. Function modifies it. | ||
421 | * @param t Tunnel on which this message is transmitted. | ||
422 | * @param c Connection to use (autoselect if NULL). | ||
423 | * @param force Force the tunnel to take the message (buffer overfill). | ||
424 | * @param cont Continuation to call once message is really sent. | ||
425 | * @param cont_cls Closure for @c cont. | ||
426 | * | ||
427 | * @return Handle to cancel message. NULL if @c cont is NULL. | ||
428 | */ | ||
429 | struct CadetTunnel3Queue * | ||
430 | GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, | ||
431 | struct CadetTunnel3 *t, struct CadetConnection *c, | ||
432 | int force, GMT_sent cont, void *cont_cls); | ||
433 | |||
434 | /** | ||
435 | * Is the tunnel directed towards the local peer? | ||
436 | * | ||
437 | * @param t Tunnel. | ||
438 | * | ||
439 | * @return #GNUNET_YES if it is loopback. | ||
440 | */ | ||
441 | int | ||
442 | GMT_is_loopback (const struct CadetTunnel3 *t); | ||
443 | |||
444 | /** | ||
445 | * Is the tunnel using this path already? | ||
446 | * | ||
447 | * @param t Tunnel. | ||
448 | * @param p Path. | ||
449 | * | ||
450 | * @return #GNUNET_YES a connection uses this path. | ||
451 | */ | ||
452 | int | ||
453 | GMT_is_path_used (const struct CadetTunnel3 *t, const struct CadetPeerPath *p); | ||
454 | |||
455 | /** | ||
456 | * Get a cost of a path for a tunnel considering existing connections. | ||
457 | * | ||
458 | * @param t Tunnel. | ||
459 | * @param path Candidate path. | ||
460 | * | ||
461 | * @return Cost of the path (path length + number of overlapping nodes) | ||
462 | */ | ||
463 | unsigned int | ||
464 | GMT_get_path_cost (const struct CadetTunnel3 *t, | ||
465 | const struct CadetPeerPath *path); | ||
466 | |||
467 | /** | ||
468 | * Get the static string for the peer this tunnel is directed. | ||
469 | * | ||
470 | * @param t Tunnel. | ||
471 | * | ||
472 | * @return Static string the destination peer's ID. | ||
473 | */ | ||
474 | const char * | ||
475 | GMT_2s (const struct CadetTunnel3 *t); | ||
476 | |||
477 | /** | ||
478 | * Log all possible info about the tunnel state. | ||
479 | * | ||
480 | * @param t Tunnel to debug. | ||
481 | */ | ||
482 | void | ||
483 | GMT_debug (const struct CadetTunnel3 *t); | ||
484 | |||
485 | /** | ||
486 | * Iterate all tunnels. | ||
487 | * | ||
488 | * @param iter Iterator. | ||
489 | * @param cls Closure for @c iter. | ||
490 | */ | ||
491 | void | ||
492 | GMT_iterate_all (GNUNET_CONTAINER_PeerMapIterator iter, void *cls); | ||
493 | |||
494 | /** | ||
495 | * Count all tunnels. | ||
496 | * | ||
497 | * @return Number of tunnels to remote peers kept by this peer. | ||
498 | */ | ||
499 | unsigned int | ||
500 | GMT_count_all (void); | ||
501 | |||
502 | /** | ||
503 | * Iterate all connections of a tunnel. | ||
504 | * | ||
505 | * @param t Tunnel whose connections to iterate. | ||
506 | * @param iter Iterator. | ||
507 | * @param cls Closure for @c iter. | ||
508 | */ | ||
509 | void | ||
510 | GMT_iterate_connections (struct CadetTunnel3 *t, GMT_conn_iter iter, void *cls); | ||
511 | |||
512 | /** | ||
513 | * Iterate all channels of a tunnel. | ||
514 | * | ||
515 | * @param t Tunnel whose channels to iterate. | ||
516 | * @param iter Iterator. | ||
517 | * @param cls Closure for @c iter. | ||
518 | */ | ||
519 | void | ||
520 | GMT_iterate_channels (struct CadetTunnel3 *t, GMT_chan_iter iter, void *cls); | ||
521 | |||
522 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
523 | { | ||
524 | #endif | ||
525 | #ifdef __cplusplus | ||
526 | } | ||
527 | #endif | ||
528 | |||
529 | /* ifndef GNUNET_CADET_SERVICE_TUNNEL_H */ | ||
530 | #endif | ||
531 | /* end of gnunet-cadet-service_tunnel.h */ | ||
diff --git a/src/cadet/loopcheck.sh b/src/cadet/loopcheck.sh new file mode 100755 index 000000000..2ea737ecb --- /dev/null +++ b/src/cadet/loopcheck.sh | |||
@@ -0,0 +1,8 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | while true; do | ||
4 | date; | ||
5 | taskset 1 make check || break; | ||
6 | grep -B 10 Assert *log && break | ||
7 | ls core* &> /dev/null && break | ||
8 | done | ||
diff --git a/src/cadet/mesh.conf.in b/src/cadet/mesh.conf.in new file mode 100644 index 000000000..c6bb09dd7 --- /dev/null +++ b/src/cadet/mesh.conf.in | |||
@@ -0,0 +1,21 @@ | |||
1 | [mesh] | ||
2 | AUTOSTART = @AUTOSTART@ | ||
3 | @JAVAPORT@PORT = 2096 | ||
4 | HOSTNAME = localhost | ||
5 | BINARY = gnunet-service-mesh | ||
6 | ACCEPT_FROM = 127.0.0.1; | ||
7 | ACCEPT_FROM6 = ::1; | ||
8 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-mesh.sock | ||
9 | UNIX_MATCH_UID = YES | ||
10 | UNIX_MATCH_GID = YES | ||
11 | REFRESH_CONNECTION_TIME = 5 min | ||
12 | ID_ANNOUNCE_TIME = 1 h | ||
13 | APP_ANNOUNCE_TIME = 1 h | ||
14 | CONNECT_TIMEOUT = 30 s | ||
15 | DEFAULT_TTL = 64 | ||
16 | DHT_REPLICATION_LEVEL = 3 | ||
17 | MAX_TUNNELS = 1000 | ||
18 | # MAX_TUNNELS deprecated | ||
19 | MAX_CONNECTIONS = 1000 | ||
20 | MAX_MSGS_QUEUE = 10000 | ||
21 | MAX_PEERS = 1000 | ||
diff --git a/src/cadet/profiler.conf b/src/cadet/profiler.conf new file mode 100644 index 000000000..8817802d1 --- /dev/null +++ b/src/cadet/profiler.conf | |||
@@ -0,0 +1,19 @@ | |||
1 | @INLINE@ test_mesh.conf | ||
2 | |||
3 | [testbed] | ||
4 | OVERLAY_TOPOLOGY = RANDOM | ||
5 | OVERLAY_RANDOM_LINKS = %LINKS% | ||
6 | MAX_PARALLEL_SERVICE_CONNECTIONS=4000 | ||
7 | SETUP_TIMEOUT = 60 m | ||
8 | |||
9 | [transport] | ||
10 | #MANIPULATE_DELAY_IN = 50 ms | ||
11 | MANIPULATE_DELAY_OUT = 10 ms | ||
12 | |||
13 | [mesh] | ||
14 | REFRESH_CONNECTION_TIME = 1 h | ||
15 | DISABLE_TRY_CONNECT = YES | ||
16 | ID_ANNOUNCE_TIME = 240 s | ||
17 | |||
18 | [dht] | ||
19 | FORCE_NSE = %NSE% | ||
diff --git a/src/cadet/run_profiler.sh b/src/cadet/run_profiler.sh new file mode 100755 index 000000000..aba6ce4d4 --- /dev/null +++ b/src/cadet/run_profiler.sh | |||
@@ -0,0 +1,25 @@ | |||
1 | #!/bin/sh | ||
2 | |||
3 | if [ "$#" -lt "3" ]; then | ||
4 | echo "usage: $0 ROUND_TIME PEERS PINGING_PEERS"; | ||
5 | echo "example: $0 30s 16 1"; | ||
6 | exit 1; | ||
7 | fi | ||
8 | |||
9 | ROUNDTIME=$1 | ||
10 | PEERS=$2 | ||
11 | PINGS=$3 | ||
12 | |||
13 | if [ $PEERS -eq 1 ]; then | ||
14 | echo "cannot run 1 peer"; | ||
15 | exit 1; | ||
16 | fi | ||
17 | |||
18 | LINKS=`echo "l($PEERS)/l(2) * $PEERS" | bc -l` | ||
19 | LINKS=`printf "%.0f" $LINKS` | ||
20 | NSE=`echo "l($PEERS)/l(2)" | bc -l` | ||
21 | echo "using $PEERS peers, $LINKS links"; | ||
22 | |||
23 | sed -e "s/%LINKS%/$LINKS/;s/%NSE%/$NSE/" profiler.conf > .profiler.conf | ||
24 | |||
25 | ./gnunet-mesh-profiler $ROUNDTIME $PEERS $PINGS $4 |& tee log | grep -v DEBUG | ||
diff --git a/src/cadet/small.dat b/src/cadet/small.dat new file mode 100644 index 000000000..c3805ee80 --- /dev/null +++ b/src/cadet/small.dat | |||
@@ -0,0 +1,21 @@ | |||
1 | 16 | ||
2 | 1:2 | ||
3 | 1:9 | ||
4 | 2:3 | ||
5 | 3:4 | ||
6 | 3:11 | ||
7 | 4:5 | ||
8 | 5:6 | ||
9 | 5:13 | ||
10 | 6:7 | ||
11 | 7:8 | ||
12 | 7:15 | ||
13 | 8:9 | ||
14 | 9:10 | ||
15 | 10:11 | ||
16 | 11:12 | ||
17 | 12:13 | ||
18 | 13:14 | ||
19 | 14:15 | ||
20 | 15:16 | ||
21 | 16:1 | ||
diff --git a/src/cadet/test_cadet.c b/src/cadet/test_cadet.c new file mode 100644 index 000000000..ac2661a86 --- /dev/null +++ b/src/cadet/test_cadet.c | |||
@@ -0,0 +1,953 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2011 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | /** | ||
21 | * @file cadet/test_cadet.c | ||
22 | * | ||
23 | * @brief Test for the cadet service: retransmission of traffic. | ||
24 | */ | ||
25 | #include <stdio.h> | ||
26 | #include "platform.h" | ||
27 | #include "cadet_test_lib.h" | ||
28 | #include "gnunet_cadet_service.h" | ||
29 | #include "gnunet_statistics_service.h" | ||
30 | #include <gauger.h> | ||
31 | |||
32 | |||
33 | /** | ||
34 | * How namy messages to send | ||
35 | */ | ||
36 | #define TOTAL_PACKETS 100 | ||
37 | |||
38 | /** | ||
39 | * How long until we give up on connecting the peers? | ||
40 | */ | ||
41 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120) | ||
42 | |||
43 | /** | ||
44 | * Time to wait for stuff that should be rather fast | ||
45 | */ | ||
46 | #define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) | ||
47 | |||
48 | /** | ||
49 | * DIFFERENT TESTS TO RUN | ||
50 | */ | ||
51 | #define SETUP 0 | ||
52 | #define FORWARD 1 | ||
53 | #define KEEPALIVE 2 | ||
54 | #define SPEED 3 | ||
55 | #define SPEED_ACK 4 | ||
56 | #define SPEED_REL 8 | ||
57 | #define P2P_SIGNAL 10 | ||
58 | |||
59 | /** | ||
60 | * Which test are we running? | ||
61 | */ | ||
62 | static int test; | ||
63 | |||
64 | /** | ||
65 | * String with test name | ||
66 | */ | ||
67 | char *test_name; | ||
68 | |||
69 | /** | ||
70 | * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic. | ||
71 | */ | ||
72 | static int test_backwards = GNUNET_NO; | ||
73 | |||
74 | /** | ||
75 | * How many events have happened | ||
76 | */ | ||
77 | static int ok; | ||
78 | |||
79 | /** | ||
80 | * Number of events expected to conclude the test successfully. | ||
81 | */ | ||
82 | int ok_goal; | ||
83 | |||
84 | /** | ||
85 | * Size of each test packet | ||
86 | */ | ||
87 | size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t); | ||
88 | |||
89 | /** | ||
90 | * Operation to get peer ids. | ||
91 | */ | ||
92 | struct GNUNET_TESTBED_Operation *t_op[2]; | ||
93 | |||
94 | /** | ||
95 | * Peer ids. | ||
96 | */ | ||
97 | struct GNUNET_PeerIdentity *p_id[2]; | ||
98 | |||
99 | /** | ||
100 | * Peer ids counter. | ||
101 | */ | ||
102 | unsigned int p_ids; | ||
103 | |||
104 | /** | ||
105 | * Is the setup initialized? | ||
106 | */ | ||
107 | static int initialized; | ||
108 | |||
109 | /** | ||
110 | * Number of payload packes sent | ||
111 | */ | ||
112 | static int data_sent; | ||
113 | |||
114 | /** | ||
115 | * Number of payload packets received | ||
116 | */ | ||
117 | static int data_received; | ||
118 | |||
119 | /** | ||
120 | * Number of payload packed explicitly (app level) acknowledged | ||
121 | */ | ||
122 | static int data_ack; | ||
123 | |||
124 | /** | ||
125 | * Total number of currently running peers. | ||
126 | */ | ||
127 | static unsigned long long peers_running; | ||
128 | |||
129 | /** | ||
130 | * Test context (to shut down). | ||
131 | */ | ||
132 | struct GNUNET_CADET_TEST_Context *test_ctx; | ||
133 | |||
134 | /** | ||
135 | * Task called to disconnect peers. | ||
136 | */ | ||
137 | static GNUNET_SCHEDULER_TaskIdentifier disconnect_task; | ||
138 | |||
139 | /** | ||
140 | * Task To perform tests | ||
141 | */ | ||
142 | static GNUNET_SCHEDULER_TaskIdentifier test_task; | ||
143 | |||
144 | /** | ||
145 | * Task called to shutdown test. | ||
146 | */ | ||
147 | static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle; | ||
148 | |||
149 | /** | ||
150 | * Cadet handle for the root peer | ||
151 | */ | ||
152 | static struct GNUNET_CADET_Handle *h1; | ||
153 | |||
154 | /** | ||
155 | * Cadet handle for the first leaf peer | ||
156 | */ | ||
157 | static struct GNUNET_CADET_Handle *h2; | ||
158 | |||
159 | /** | ||
160 | * Channel handle for the root peer | ||
161 | */ | ||
162 | static struct GNUNET_CADET_Channel *ch; | ||
163 | |||
164 | /** | ||
165 | * Channel handle for the dest peer | ||
166 | */ | ||
167 | static struct GNUNET_CADET_Channel *incoming_ch; | ||
168 | |||
169 | /** | ||
170 | * Time we started the data transmission (after channel has been established | ||
171 | * and initilized). | ||
172 | */ | ||
173 | static struct GNUNET_TIME_Absolute start_time; | ||
174 | |||
175 | /** | ||
176 | * Peers handle. | ||
177 | */ | ||
178 | static struct GNUNET_TESTBED_Peer **testbed_peers; | ||
179 | |||
180 | /** | ||
181 | * Statistics operation handle. | ||
182 | */ | ||
183 | static struct GNUNET_TESTBED_Operation *stats_op; | ||
184 | |||
185 | /** | ||
186 | * Keepalives sent. | ||
187 | */ | ||
188 | static unsigned int ka_sent; | ||
189 | |||
190 | /** | ||
191 | * Keepalives received. | ||
192 | */ | ||
193 | static unsigned int ka_received; | ||
194 | |||
195 | |||
196 | /** | ||
197 | * Show the results of the test (banwidth acheived) and log them to GAUGER | ||
198 | */ | ||
199 | static void | ||
200 | show_end_data (void) | ||
201 | { | ||
202 | static struct GNUNET_TIME_Absolute end_time; | ||
203 | static struct GNUNET_TIME_Relative total_time; | ||
204 | |||
205 | end_time = GNUNET_TIME_absolute_get(); | ||
206 | total_time = GNUNET_TIME_absolute_get_difference(start_time, end_time); | ||
207 | FPRINTF (stderr, "\nResults of test \"%s\"\n", test_name); | ||
208 | FPRINTF (stderr, "Test time %s\n", | ||
209 | GNUNET_STRINGS_relative_time_to_string (total_time, | ||
210 | GNUNET_YES)); | ||
211 | FPRINTF (stderr, "Test bandwidth: %f kb/s\n", | ||
212 | 4 * TOTAL_PACKETS * 1.0 / (total_time.rel_value_us / 1000)); // 4bytes * ms | ||
213 | FPRINTF (stderr, "Test throughput: %f packets/s\n\n", | ||
214 | TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000)); // packets * ms | ||
215 | GAUGER ("CADET", test_name, | ||
216 | TOTAL_PACKETS * 1000.0 / (total_time.rel_value_us / 1000), | ||
217 | "packets/s"); | ||
218 | } | ||
219 | |||
220 | |||
221 | /** | ||
222 | * Shut down peergroup, clean up. | ||
223 | * | ||
224 | * @param cls Closure (unused). | ||
225 | * @param tc Task Context. | ||
226 | */ | ||
227 | static void | ||
228 | shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
229 | { | ||
230 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending test.\n"); | ||
231 | shutdown_handle = GNUNET_SCHEDULER_NO_TASK; | ||
232 | } | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Disconnect from cadet services af all peers, call shutdown. | ||
237 | * | ||
238 | * @param cls Closure (unused). | ||
239 | * @param tc Task Context. | ||
240 | */ | ||
241 | static void | ||
242 | disconnect_cadet_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
243 | { | ||
244 | long line = (long) cls; | ||
245 | unsigned int i; | ||
246 | |||
247 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
248 | "disconnecting cadet service of peers, called from line %ld\n", | ||
249 | line); | ||
250 | disconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
251 | for (i = 0; i < 2; i++) | ||
252 | { | ||
253 | GNUNET_TESTBED_operation_done (t_op[i]); | ||
254 | } | ||
255 | if (NULL != ch) | ||
256 | { | ||
257 | GNUNET_CADET_channel_destroy (ch); | ||
258 | ch = NULL; | ||
259 | } | ||
260 | if (NULL != incoming_ch) | ||
261 | { | ||
262 | GNUNET_CADET_channel_destroy (incoming_ch); | ||
263 | incoming_ch = NULL; | ||
264 | } | ||
265 | GNUNET_CADET_TEST_cleanup (test_ctx); | ||
266 | if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle) | ||
267 | { | ||
268 | GNUNET_SCHEDULER_cancel (shutdown_handle); | ||
269 | } | ||
270 | shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL); | ||
271 | } | ||
272 | |||
273 | |||
274 | /** | ||
275 | * Abort test: schedule disconnect and shutdown immediately | ||
276 | * | ||
277 | * @param line Line in the code the abort is requested from (__LINE__). | ||
278 | */ | ||
279 | static void | ||
280 | abort_test (long line) | ||
281 | { | ||
282 | if (disconnect_task != GNUNET_SCHEDULER_NO_TASK) | ||
283 | { | ||
284 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
285 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, | ||
286 | (void *) line); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | /** | ||
291 | * Transmit ready callback. | ||
292 | * | ||
293 | * @param cls Closure (message type). | ||
294 | * @param size Size of the tranmist buffer. | ||
295 | * @param buf Pointer to the beginning of the buffer. | ||
296 | * | ||
297 | * @return Number of bytes written to buf. | ||
298 | */ | ||
299 | static size_t | ||
300 | tmt_rdy (void *cls, size_t size, void *buf); | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Task to schedule a new data transmission. | ||
305 | * | ||
306 | * @param cls Closure (peer #). | ||
307 | * @param tc Task Context. | ||
308 | */ | ||
309 | static void | ||
310 | data_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
311 | { | ||
312 | struct GNUNET_CADET_TransmitHandle *th; | ||
313 | struct GNUNET_CADET_Channel *channel; | ||
314 | |||
315 | if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) | ||
316 | return; | ||
317 | |||
318 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n"); | ||
319 | if (GNUNET_YES == test_backwards) | ||
320 | { | ||
321 | channel = incoming_ch; | ||
322 | } | ||
323 | else | ||
324 | { | ||
325 | channel = ch; | ||
326 | } | ||
327 | th = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, | ||
328 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
329 | size_payload, &tmt_rdy, (void *) 1L); | ||
330 | if (NULL == th) | ||
331 | { | ||
332 | unsigned long i = (unsigned long) cls; | ||
333 | |||
334 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Retransmission\n"); | ||
335 | if (0 == i) | ||
336 | { | ||
337 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " in 1 ms\n"); | ||
338 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, | ||
339 | &data_task, (void *)1UL); | ||
340 | } | ||
341 | else | ||
342 | { | ||
343 | i++; | ||
344 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "in %u ms\n", i); | ||
345 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply( | ||
346 | GNUNET_TIME_UNIT_MILLISECONDS, | ||
347 | i), | ||
348 | &data_task, (void *)i); | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | |||
353 | |||
354 | /** | ||
355 | * Transmit ready callback | ||
356 | * | ||
357 | * @param cls Closure (message type). | ||
358 | * @param size Size of the buffer we have. | ||
359 | * @param buf Buffer to copy data to. | ||
360 | */ | ||
361 | size_t | ||
362 | tmt_rdy (void *cls, size_t size, void *buf) | ||
363 | { | ||
364 | struct GNUNET_MessageHeader *msg = buf; | ||
365 | uint32_t *data; | ||
366 | |||
367 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
368 | "tmt_rdy called, filling buffer\n"); | ||
369 | if (size < size_payload || NULL == buf) | ||
370 | { | ||
371 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
372 | "size %u, buf %p, data_sent %u, data_received %u\n", | ||
373 | size, buf, data_sent, data_received); | ||
374 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ok %u, ok goal %u\n", ok, ok_goal); | ||
375 | GNUNET_break (ok >= ok_goal - 2); | ||
376 | |||
377 | return 0; | ||
378 | } | ||
379 | msg->size = htons (size); | ||
380 | msg->type = htons ((long) cls); | ||
381 | data = (uint32_t *) &msg[1]; | ||
382 | *data = htonl (data_sent); | ||
383 | if (GNUNET_NO == initialized) | ||
384 | { | ||
385 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
386 | "sending initializer\n"); | ||
387 | } | ||
388 | else if (SPEED == test) | ||
389 | { | ||
390 | data_sent++; | ||
391 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
392 | " Sent packet %d\n", data_sent); | ||
393 | if (data_sent < TOTAL_PACKETS) | ||
394 | { | ||
395 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
396 | " Scheduling packet %d\n", data_sent + 1); | ||
397 | GNUNET_SCHEDULER_add_now (&data_task, NULL); | ||
398 | } | ||
399 | } | ||
400 | |||
401 | return size_payload; | ||
402 | } | ||
403 | |||
404 | |||
405 | /** | ||
406 | * Function is called whenever a message is received. | ||
407 | * | ||
408 | * @param cls closure (set from GNUNET_CADET_connect) | ||
409 | * @param channel connection to the other end | ||
410 | * @param channel_ctx place to store local state associated with the channel | ||
411 | * @param message the actual message | ||
412 | * @return GNUNET_OK to keep the connection open, | ||
413 | * GNUNET_SYSERR to close it (signal serious error) | ||
414 | */ | ||
415 | int | ||
416 | data_callback (void *cls, struct GNUNET_CADET_Channel *channel, | ||
417 | void **channel_ctx, | ||
418 | const struct GNUNET_MessageHeader *message) | ||
419 | { | ||
420 | long client = (long) cls; | ||
421 | long expected_target_client; | ||
422 | uint32_t *data; | ||
423 | |||
424 | ok++; | ||
425 | |||
426 | GNUNET_CADET_receive_done (channel); | ||
427 | |||
428 | if ((ok % 20) == 0) | ||
429 | { | ||
430 | if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) | ||
431 | { | ||
432 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
433 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
434 | &disconnect_cadet_peers, | ||
435 | (void *) __LINE__); | ||
436 | } | ||
437 | } | ||
438 | |||
439 | switch (client) | ||
440 | { | ||
441 | case 0L: | ||
442 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n"); | ||
443 | break; | ||
444 | case 4L: | ||
445 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
446 | "Leaf client %li got a message.\n", | ||
447 | client); | ||
448 | break; | ||
449 | default: | ||
450 | GNUNET_assert (0); | ||
451 | break; | ||
452 | } | ||
453 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal); | ||
454 | data = (uint32_t *) &message[1]; | ||
455 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload: (%u)\n", ntohl (*data)); | ||
456 | if (SPEED == test && GNUNET_YES == test_backwards) | ||
457 | { | ||
458 | expected_target_client = 0L; | ||
459 | } | ||
460 | else | ||
461 | { | ||
462 | expected_target_client = 4L; | ||
463 | } | ||
464 | |||
465 | if (GNUNET_NO == initialized) | ||
466 | { | ||
467 | initialized = GNUNET_YES; | ||
468 | start_time = GNUNET_TIME_absolute_get (); | ||
469 | if (SPEED == test) | ||
470 | { | ||
471 | GNUNET_assert (4L == client); | ||
472 | GNUNET_SCHEDULER_add_now (&data_task, NULL); | ||
473 | return GNUNET_OK; | ||
474 | } | ||
475 | } | ||
476 | |||
477 | if (client == expected_target_client) // Normally 4 | ||
478 | { | ||
479 | data_received++; | ||
480 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received); | ||
481 | if (SPEED != test || (ok_goal - 2) == ok) | ||
482 | { | ||
483 | GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, | ||
484 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
485 | size_payload, &tmt_rdy, (void *) 1L); | ||
486 | return GNUNET_OK; | ||
487 | } | ||
488 | else | ||
489 | { | ||
490 | if (data_received < TOTAL_PACKETS) | ||
491 | return GNUNET_OK; | ||
492 | } | ||
493 | } | ||
494 | else // Normally 0 | ||
495 | { | ||
496 | if (test == SPEED_ACK || test == SPEED) | ||
497 | { | ||
498 | data_ack++; | ||
499 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", data_ack); | ||
500 | GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, | ||
501 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
502 | size_payload, &tmt_rdy, (void *) 1L); | ||
503 | if (data_ack < TOTAL_PACKETS && SPEED != test) | ||
504 | return GNUNET_OK; | ||
505 | if (ok == 2 && SPEED == test) | ||
506 | return GNUNET_OK; | ||
507 | show_end_data(); | ||
508 | } | ||
509 | if (test == P2P_SIGNAL) | ||
510 | { | ||
511 | GNUNET_CADET_channel_destroy (incoming_ch); | ||
512 | incoming_ch = NULL; | ||
513 | } | ||
514 | else | ||
515 | { | ||
516 | GNUNET_CADET_channel_destroy (ch); | ||
517 | ch = NULL; | ||
518 | } | ||
519 | } | ||
520 | |||
521 | if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) | ||
522 | { | ||
523 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
524 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
525 | &disconnect_cadet_peers, | ||
526 | (void *) __LINE__); | ||
527 | } | ||
528 | |||
529 | return GNUNET_OK; | ||
530 | } | ||
531 | |||
532 | |||
533 | /** | ||
534 | * Stats callback. Finish the stats testbed operation and when all stats have | ||
535 | * been iterated, shutdown the test. | ||
536 | * | ||
537 | * @param cls closure | ||
538 | * @param op the operation that has been finished | ||
539 | * @param emsg error message in case the operation has failed; will be NULL if | ||
540 | * operation has executed successfully. | ||
541 | */ | ||
542 | static void | ||
543 | stats_cont (void *cls, struct GNUNET_TESTBED_Operation *op, const char *emsg) | ||
544 | { | ||
545 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "stats_cont for peer %u\n", cls); | ||
546 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " sent: %u, received: %u\n", | ||
547 | ka_sent, ka_received); | ||
548 | if (ka_sent < 2 || ka_sent > ka_received + 1) | ||
549 | ok--; | ||
550 | GNUNET_TESTBED_operation_done (stats_op); | ||
551 | |||
552 | if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) | ||
553 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
554 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, | ||
555 | (void *) __LINE__); | ||
556 | |||
557 | } | ||
558 | |||
559 | |||
560 | /** | ||
561 | * Process statistic values. | ||
562 | * | ||
563 | * @param cls closure | ||
564 | * @param peer the peer the statistic belong to | ||
565 | * @param subsystem name of subsystem that created the statistic | ||
566 | * @param name the name of the datum | ||
567 | * @param value the current value | ||
568 | * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not | ||
569 | * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration | ||
570 | */ | ||
571 | static int | ||
572 | stats_iterator (void *cls, const struct GNUNET_TESTBED_Peer *peer, | ||
573 | const char *subsystem, const char *name, | ||
574 | uint64_t value, int is_persistent) | ||
575 | { | ||
576 | static const char *s_sent = "# keepalives sent"; | ||
577 | static const char *s_recv = "# keepalives received"; | ||
578 | uint32_t i; | ||
579 | |||
580 | i = GNUNET_TESTBED_get_index (peer); | ||
581 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %u - %s [%s]: %llu\n", | ||
582 | i, subsystem, name, value); | ||
583 | if (0 == strncmp (s_sent, name, strlen (s_sent)) && 0 == i) | ||
584 | ka_sent = value; | ||
585 | |||
586 | if (0 == strncmp(s_recv, name, strlen (s_recv)) && 4 == i) | ||
587 | ka_received = value; | ||
588 | |||
589 | return GNUNET_OK; | ||
590 | } | ||
591 | |||
592 | |||
593 | /** | ||
594 | * Task check that keepalives were sent and received. | ||
595 | * | ||
596 | * @param cls Closure (NULL). | ||
597 | * @param tc Task Context. | ||
598 | */ | ||
599 | static void | ||
600 | check_keepalives (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
601 | { | ||
602 | if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) | ||
603 | return; | ||
604 | |||
605 | disconnect_task = GNUNET_SCHEDULER_NO_TASK; | ||
606 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "check keepalives\n"); | ||
607 | GNUNET_CADET_channel_destroy (ch); | ||
608 | stats_op = GNUNET_TESTBED_get_statistics (5, testbed_peers, | ||
609 | "cadet", NULL, | ||
610 | stats_iterator, stats_cont, NULL); | ||
611 | } | ||
612 | |||
613 | |||
614 | /** | ||
615 | * Handlers, for diverse services | ||
616 | */ | ||
617 | static struct GNUNET_CADET_MessageHandler handlers[] = { | ||
618 | {&data_callback, 1, sizeof (struct GNUNET_MessageHeader)}, | ||
619 | {NULL, 0, 0} | ||
620 | }; | ||
621 | |||
622 | |||
623 | /** | ||
624 | * Method called whenever another peer has added us to a channel | ||
625 | * the other peer initiated. | ||
626 | * | ||
627 | * @param cls Closure. | ||
628 | * @param channel New handle to the channel. | ||
629 | * @param initiator Peer that started the channel. | ||
630 | * @param port Port this channel is connected to. | ||
631 | * @param options channel option flags | ||
632 | * @return Initial channel context for the channel | ||
633 | * (can be NULL -- that's not an error). | ||
634 | */ | ||
635 | static void * | ||
636 | incoming_channel (void *cls, struct GNUNET_CADET_Channel *channel, | ||
637 | const struct GNUNET_PeerIdentity *initiator, | ||
638 | uint32_t port, enum GNUNET_CADET_ChannelOption options) | ||
639 | { | ||
640 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
641 | "Incoming channel from %s to peer %d\n", | ||
642 | GNUNET_i2s (initiator), (long) cls); | ||
643 | ok++; | ||
644 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); | ||
645 | if ((long) cls == 4L) | ||
646 | incoming_ch = channel; | ||
647 | else | ||
648 | { | ||
649 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
650 | "Incoming channel for unknown client %lu\n", (long) cls); | ||
651 | GNUNET_break(0); | ||
652 | } | ||
653 | if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) | ||
654 | { | ||
655 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
656 | if (KEEPALIVE == test) | ||
657 | { | ||
658 | struct GNUNET_TIME_Relative delay; | ||
659 | delay = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS , 5); | ||
660 | disconnect_task = | ||
661 | GNUNET_SCHEDULER_add_delayed (delay, &check_keepalives, NULL); | ||
662 | } | ||
663 | else | ||
664 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
665 | &disconnect_cadet_peers, | ||
666 | (void *) __LINE__); | ||
667 | } | ||
668 | |||
669 | return NULL; | ||
670 | } | ||
671 | |||
672 | /** | ||
673 | * Function called whenever an inbound channel is destroyed. Should clean up | ||
674 | * any associated state. | ||
675 | * | ||
676 | * @param cls closure (set from GNUNET_CADET_connect) | ||
677 | * @param channel connection to the other end (henceforth invalid) | ||
678 | * @param channel_ctx place where local state associated | ||
679 | * with the channel is stored | ||
680 | */ | ||
681 | static void | ||
682 | channel_cleaner (void *cls, const struct GNUNET_CADET_Channel *channel, | ||
683 | void *channel_ctx) | ||
684 | { | ||
685 | long i = (long) cls; | ||
686 | |||
687 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
688 | "Incoming channel disconnected at peer %ld\n", i); | ||
689 | if (4L == i) | ||
690 | { | ||
691 | ok++; | ||
692 | GNUNET_break (channel == incoming_ch); | ||
693 | incoming_ch = NULL; | ||
694 | } | ||
695 | else if (0L == i) | ||
696 | { | ||
697 | if (P2P_SIGNAL == test) | ||
698 | { | ||
699 | ok ++; | ||
700 | } | ||
701 | GNUNET_break (channel == ch); | ||
702 | ch = NULL; | ||
703 | } | ||
704 | else | ||
705 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
706 | "Unknown peer! %d\n", i); | ||
707 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: %d\n", ok); | ||
708 | |||
709 | if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) | ||
710 | { | ||
711 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
712 | disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cadet_peers, | ||
713 | (void *) __LINE__); | ||
714 | } | ||
715 | |||
716 | return; | ||
717 | } | ||
718 | |||
719 | |||
720 | /** | ||
721 | * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES. | ||
722 | * | ||
723 | * Testcase continues when the root receives confirmation of connected peers, | ||
724 | * on callback funtion ch. | ||
725 | * | ||
726 | * @param cls Closure (unsued). | ||
727 | * @param tc Task Context. | ||
728 | */ | ||
729 | static void | ||
730 | do_test (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
731 | { | ||
732 | enum GNUNET_CADET_ChannelOption flags; | ||
733 | |||
734 | if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) | ||
735 | return; | ||
736 | |||
737 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test_task\n"); | ||
738 | |||
739 | if (GNUNET_SCHEDULER_NO_TASK != disconnect_task) | ||
740 | { | ||
741 | GNUNET_SCHEDULER_cancel (disconnect_task); | ||
742 | } | ||
743 | |||
744 | flags = GNUNET_CADET_OPTION_DEFAULT; | ||
745 | if (SPEED_REL == test) | ||
746 | { | ||
747 | test = SPEED; | ||
748 | flags |= GNUNET_CADET_OPTION_RELIABLE; | ||
749 | } | ||
750 | ch = GNUNET_CADET_channel_create (h1, NULL, p_id[1], 1, flags); | ||
751 | |||
752 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
753 | &disconnect_cadet_peers, | ||
754 | (void *) __LINE__); | ||
755 | if (KEEPALIVE == test) | ||
756 | return; /* Don't send any data. */ | ||
757 | |||
758 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
759 | "Sending data initializer...\n"); | ||
760 | data_ack = 0; | ||
761 | data_received = 0; | ||
762 | data_sent = 0; | ||
763 | GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO, | ||
764 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
765 | size_payload, &tmt_rdy, (void *) 1L); | ||
766 | } | ||
767 | |||
768 | /** | ||
769 | * Callback to be called when the requested peer information is available | ||
770 | * | ||
771 | * @param cls the closure from GNUNET_TESTBED_peer_get_information() | ||
772 | * @param op the operation this callback corresponds to | ||
773 | * @param pinfo the result; will be NULL if the operation has failed | ||
774 | * @param emsg error message if the operation has failed; | ||
775 | * NULL if the operation is successfull | ||
776 | */ | ||
777 | static void | ||
778 | pi_cb (void *cls, | ||
779 | struct GNUNET_TESTBED_Operation *op, | ||
780 | const struct GNUNET_TESTBED_PeerInformation *pinfo, | ||
781 | const char *emsg) | ||
782 | { | ||
783 | long i = (long) cls; | ||
784 | |||
785 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "id callback for %ld\n", i); | ||
786 | |||
787 | if (NULL == pinfo || NULL != emsg) | ||
788 | { | ||
789 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "pi_cb: %s\n", emsg); | ||
790 | abort_test (__LINE__); | ||
791 | return; | ||
792 | } | ||
793 | p_id[i] = pinfo->result.id; | ||
794 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " id: %s\n", GNUNET_i2s (p_id[i])); | ||
795 | p_ids++; | ||
796 | if (p_ids < 2) | ||
797 | return; | ||
798 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got all IDs, starting test\n"); | ||
799 | test_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
800 | &do_test, NULL); | ||
801 | } | ||
802 | |||
803 | /** | ||
804 | * test main: start test when all peers are connected | ||
805 | * | ||
806 | * @param cls Closure. | ||
807 | * @param ctx Argument to give to GNUNET_CADET_TEST_cleanup on test end. | ||
808 | * @param num_peers Number of peers that are running. | ||
809 | * @param peers Array of peers. | ||
810 | * @param cadetes Handle to each of the CADETs of the peers. | ||
811 | */ | ||
812 | static void | ||
813 | tmain (void *cls, | ||
814 | struct GNUNET_CADET_TEST_Context *ctx, | ||
815 | unsigned int num_peers, | ||
816 | struct GNUNET_TESTBED_Peer **peers, | ||
817 | struct GNUNET_CADET_Handle **cadetes) | ||
818 | { | ||
819 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test main\n"); | ||
820 | ok = 0; | ||
821 | test_ctx = ctx; | ||
822 | peers_running = num_peers; | ||
823 | testbed_peers = peers; | ||
824 | h1 = cadetes[0]; | ||
825 | h2 = cadetes[num_peers - 1]; | ||
826 | disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, | ||
827 | &disconnect_cadet_peers, | ||
828 | (void *) __LINE__); | ||
829 | shutdown_handle = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, | ||
830 | &shutdown_task, NULL); | ||
831 | t_op[0] = GNUNET_TESTBED_peer_get_information (peers[0], | ||
832 | GNUNET_TESTBED_PIT_IDENTITY, | ||
833 | &pi_cb, (void *) 0L); | ||
834 | t_op[1] = GNUNET_TESTBED_peer_get_information (peers[num_peers - 1], | ||
835 | GNUNET_TESTBED_PIT_IDENTITY, | ||
836 | &pi_cb, (void *) 1L); | ||
837 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "requested peer ids\n"); | ||
838 | } | ||
839 | |||
840 | |||
841 | /** | ||
842 | * Main: start test | ||
843 | */ | ||
844 | int | ||
845 | main (int argc, char *argv[]) | ||
846 | { | ||
847 | initialized = GNUNET_NO; | ||
848 | static uint32_t ports[2]; | ||
849 | const char *config_file; | ||
850 | |||
851 | GNUNET_log_setup ("test", "DEBUG", NULL); | ||
852 | config_file = "test_cadet.conf"; | ||
853 | |||
854 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Start\n"); | ||
855 | if (strstr (argv[0], "_cadet_forward") != NULL) | ||
856 | { | ||
857 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "FORWARD\n"); | ||
858 | test = FORWARD; | ||
859 | test_name = "unicast"; | ||
860 | ok_goal = 4; | ||
861 | } | ||
862 | else if (strstr (argv[0], "_cadet_signal") != NULL) | ||
863 | { | ||
864 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SIGNAL\n"); | ||
865 | test = P2P_SIGNAL; | ||
866 | test_name = "signal"; | ||
867 | ok_goal = 4; | ||
868 | } | ||
869 | else if (strstr (argv[0], "_cadet_speed_ack") != NULL) | ||
870 | { | ||
871 | /* Test is supposed to generate the following callbacks: | ||
872 | * 1 incoming channel (@dest) | ||
873 | * TOTAL_PACKETS received data packet (@dest) | ||
874 | * TOTAL_PACKETS received data packet (@orig) | ||
875 | * 1 received channel destroy (@dest) | ||
876 | */ | ||
877 | ok_goal = TOTAL_PACKETS * 2 + 2; | ||
878 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED_ACK\n"); | ||
879 | test = SPEED_ACK; | ||
880 | test_name = "speed ack"; | ||
881 | } | ||
882 | else if (strstr (argv[0], "_cadet_speed") != NULL) | ||
883 | { | ||
884 | /* Test is supposed to generate the following callbacks: | ||
885 | * 1 incoming channel (@dest) | ||
886 | * 1 initial packet (@dest) | ||
887 | * TOTAL_PACKETS received data packet (@dest) | ||
888 | * 1 received data packet (@orig) | ||
889 | * 1 received channel destroy (@dest) | ||
890 | */ | ||
891 | ok_goal = TOTAL_PACKETS + 4; | ||
892 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "SPEED\n"); | ||
893 | if (strstr (argv[0], "_reliable") != NULL) | ||
894 | { | ||
895 | test = SPEED_REL; | ||
896 | test_name = "speed reliable"; | ||
897 | config_file = "test_cadet_drop.conf"; | ||
898 | } | ||
899 | else | ||
900 | { | ||
901 | test = SPEED; | ||
902 | test_name = "speed"; | ||
903 | } | ||
904 | } | ||
905 | else if (strstr (argv[0], "_keepalive") != NULL) | ||
906 | { | ||
907 | test = KEEPALIVE; | ||
908 | /* Test is supposed to generate the following callbacks: | ||
909 | * 1 incoming channel (@dest) | ||
910 | * [wait] | ||
911 | * 1 received channel destroy (@dest) | ||
912 | */ | ||
913 | ok_goal = 2; | ||
914 | } | ||
915 | else | ||
916 | { | ||
917 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "UNKNOWN\n"); | ||
918 | test = SETUP; | ||
919 | ok_goal = 0; | ||
920 | } | ||
921 | |||
922 | if (strstr (argv[0], "backwards") != NULL) | ||
923 | { | ||
924 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "BACKWARDS (LEAF TO ROOT)\n"); | ||
925 | test_backwards = GNUNET_YES; | ||
926 | GNUNET_asprintf (&test_name, "backwards %s", test_name); | ||
927 | } | ||
928 | |||
929 | p_ids = 0; | ||
930 | ports[0] = 1; | ||
931 | ports[1] = 0; | ||
932 | GNUNET_CADET_TEST_run ("test_cadet_small", | ||
933 | config_file, | ||
934 | 5, | ||
935 | &tmain, | ||
936 | NULL, /* tmain cls */ | ||
937 | &incoming_channel, | ||
938 | &channel_cleaner, | ||
939 | handlers, | ||
940 | ports); | ||
941 | |||
942 | if (ok_goal > ok) | ||
943 | { | ||
944 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
945 | "FAILED! (%d/%d)\n", ok, ok_goal); | ||
946 | return 1; | ||
947 | } | ||
948 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "success\n"); | ||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | /* end of test_cadet.c */ | ||
953 | |||
diff --git a/src/cadet/test_cadet.conf b/src/cadet/test_cadet.conf new file mode 100644 index 000000000..5a2f03dd0 --- /dev/null +++ b/src/cadet/test_cadet.conf | |||
@@ -0,0 +1,100 @@ | |||
1 | [testbed] | ||
2 | AUTOSTART = NO | ||
3 | PORT = 12113 | ||
4 | ACCEPT_FROM = 127.0.0.1; | ||
5 | HOSTNAME = localhost | ||
6 | OVERLAY_TOPOLOGY = LINE | ||
7 | #PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args | ||
8 | |||
9 | [fs] | ||
10 | AUTOSTART = NO | ||
11 | |||
12 | [resolver] | ||
13 | AUTOSTART = NO | ||
14 | |||
15 | [mesh] | ||
16 | #BINARY = gnunet-service-mesh-enc | ||
17 | #PREFIX = valgrind --leak-check=full | ||
18 | #PREFIX = xterm -geometry 100x85 -T peer1 -e gdb --args | ||
19 | AUTOSTART = NO | ||
20 | ACCEPT_FROM = 127.0.0.1; | ||
21 | REFRESH_CONNECTION_TIME = 2 s | ||
22 | ID_ANNOUNCE_TIME = 5 s | ||
23 | CONNECT_TIMEOUT = 30 s | ||
24 | DEFAULT_TTL = 16 | ||
25 | DHT_REPLICATION_LEVEL = 10 | ||
26 | MAX_TUNNELS = 10 | ||
27 | MAX_CONNECTIONS = 10 | ||
28 | MAX_MSGS_QUEUE = 20 | ||
29 | DISABLE_TRY_CONNECT = YES | ||
30 | |||
31 | [dht] | ||
32 | AUTOSTART = NO | ||
33 | DISABLE_TRY_CONNECT = YES | ||
34 | FORCE_NSE = 3 | ||
35 | |||
36 | [dhtcache] | ||
37 | QUOTA = 1 MB | ||
38 | DATABASE = heap | ||
39 | |||
40 | [transport] | ||
41 | PLUGINS = udp | ||
42 | ACCEPT_FROM6 = ::1; | ||
43 | ACCEPT_FROM = 127.0.0.1; | ||
44 | NEIGHBOUR_LIMIT = 50 | ||
45 | PORT = 12365 | ||
46 | #MANIPULATE_DELAY_IN = 10 ms | ||
47 | #MANIPULATE_DELAY_OUT = 10 ms | ||
48 | |||
49 | |||
50 | [ats] | ||
51 | WAN_QUOTA_OUT = 3932160 | ||
52 | WAN_QUOTA_IN = 3932160 | ||
53 | |||
54 | [core] | ||
55 | PORT = 12092 | ||
56 | AUTOSTART = YES | ||
57 | USE_EPHEMERAL_KEYS = NO | ||
58 | |||
59 | [arm] | ||
60 | DEFAULTSERVICES = core transport dht mesh statistics | ||
61 | PORT = 12366 | ||
62 | |||
63 | [transport-udp] | ||
64 | TIMEOUT = 300 s | ||
65 | PORT = 12368 | ||
66 | |||
67 | [gnunetd] | ||
68 | HOSTKEY = $GNUNET_TEST_HOME/.hostkey | ||
69 | |||
70 | [PATHS] | ||
71 | GNUNET_TEST_HOME = /tmp/test-mesh/ | ||
72 | |||
73 | [dns] | ||
74 | AUTOSTART = NO | ||
75 | |||
76 | [nse] | ||
77 | AUTOSTART = NO | ||
78 | |||
79 | [vpn] | ||
80 | AUTOSTART = NO | ||
81 | |||
82 | [nat] | ||
83 | RETURN_LOCAL_ADDRESSES = YES | ||
84 | DISABLEV6 = YES | ||
85 | USE_LOCALADDR = YES | ||
86 | |||
87 | [gns-helper-service-w32] | ||
88 | AUTOSTART = NO | ||
89 | |||
90 | [consensus] | ||
91 | AUTOSTART = NO | ||
92 | |||
93 | [gns] | ||
94 | AUTOSTART = NO | ||
95 | |||
96 | [statistics] | ||
97 | AUTOSTART = NO | ||
98 | |||
99 | [peerinfo] | ||
100 | NO_IO = YES | ||
diff --git a/src/cadet/test_cadet_drop.conf b/src/cadet/test_cadet_drop.conf new file mode 100644 index 000000000..4df0e3f34 --- /dev/null +++ b/src/cadet/test_cadet_drop.conf | |||
@@ -0,0 +1,4 @@ | |||
1 | @INLINE@ test_mesh.conf | ||
2 | |||
3 | [mesh] | ||
4 | DROP_PERCENT = 1 | ||
diff --git a/src/cadet/test_cadet_local.c b/src/cadet/test_cadet_local.c new file mode 100644 index 000000000..0796aaf12 --- /dev/null +++ b/src/cadet/test_cadet_local.c | |||
@@ -0,0 +1,337 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2011 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, 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 GNUNET_SCHEDULER_TaskIdentifier abort_task; | ||
46 | |||
47 | static GNUNET_SCHEDULER_TaskIdentifier shutdown_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 | * @param tc TaskContext. | ||
57 | */ | ||
58 | static void | ||
59 | do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
60 | |||
61 | |||
62 | /** | ||
63 | * Shutdown nicely | ||
64 | */ | ||
65 | static void | ||
66 | do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
67 | { | ||
68 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n"); | ||
69 | if (GNUNET_SCHEDULER_NO_TASK != abort_task) | ||
70 | { | ||
71 | GNUNET_SCHEDULER_cancel (abort_task); | ||
72 | } | ||
73 | if (NULL != ch) | ||
74 | { | ||
75 | GNUNET_CADET_channel_destroy (ch); | ||
76 | } | ||
77 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 1\n"); | ||
78 | if (NULL != cadet_peer_1) | ||
79 | { | ||
80 | GNUNET_CADET_disconnect (cadet_peer_1); | ||
81 | } | ||
82 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 2\n"); | ||
83 | if (NULL != cadet_peer_2) | ||
84 | { | ||
85 | GNUNET_CADET_disconnect (cadet_peer_2); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | |||
90 | /** | ||
91 | * Something went wrong and timed out. Kill everything and set error flag | ||
92 | */ | ||
93 | static void | ||
94 | do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
95 | { | ||
96 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n"); | ||
97 | result = GNUNET_SYSERR; | ||
98 | abort_task = GNUNET_SCHEDULER_NO_TASK; | ||
99 | if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) | ||
100 | { | ||
101 | GNUNET_SCHEDULER_cancel (shutdown_task); | ||
102 | shutdown_task = GNUNET_SCHEDULER_NO_TASK; | ||
103 | } | ||
104 | do_shutdown (cls, tc); | ||
105 | } | ||
106 | |||
107 | |||
108 | /** | ||
109 | * Function is called whenever a message is received. | ||
110 | * | ||
111 | * @param cls closure (set from GNUNET_CADET_connect) | ||
112 | * @param channel connection to the other end | ||
113 | * @param channel_ctx place to store local state associated with the channel | ||
114 | * @param message the actual message | ||
115 | * | ||
116 | * @return GNUNET_OK to keep the connection open, | ||
117 | * GNUNET_SYSERR to close it (signal serious error) | ||
118 | */ | ||
119 | static int | ||
120 | data_callback (void *cls, struct GNUNET_CADET_Channel *channel, | ||
121 | void **channel_ctx, | ||
122 | const struct GNUNET_MessageHeader *message) | ||
123 | { | ||
124 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data callback! Shutting down.\n"); | ||
125 | got_data = GNUNET_YES; | ||
126 | if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) | ||
127 | GNUNET_SCHEDULER_cancel (shutdown_task); | ||
128 | shutdown_task = | ||
129 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, | ||
130 | NULL); | ||
131 | GNUNET_CADET_receive_done (channel); | ||
132 | return GNUNET_OK; | ||
133 | } | ||
134 | |||
135 | |||
136 | /** | ||
137 | * Method called whenever another peer has added us to a channel | ||
138 | * the other peer initiated. | ||
139 | * | ||
140 | * @param cls closure | ||
141 | * @param channel new handle to the channel | ||
142 | * @param initiator peer that started the channel | ||
143 | * @param port port number | ||
144 | * @param options channel options | ||
145 | * @return initial channel context for the channel | ||
146 | * (can be NULL -- that's not an error) | ||
147 | */ | ||
148 | static void * | ||
149 | inbound_channel (void *cls, struct GNUNET_CADET_Channel *channel, | ||
150 | const struct GNUNET_PeerIdentity *initiator, | ||
151 | uint32_t port, enum GNUNET_CADET_ChannelOption options) | ||
152 | { | ||
153 | long id = (long) cls; | ||
154 | |||
155 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
156 | "received incoming channel on peer %d, port %u\n", | ||
157 | id, port); | ||
158 | if (id != 2L) | ||
159 | { | ||
160 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
161 | "wrong peer\n"); | ||
162 | result = GNUNET_SYSERR; | ||
163 | } | ||
164 | return NULL; | ||
165 | } | ||
166 | |||
167 | |||
168 | /** | ||
169 | * Function called whenever an channel is destroyed. Should clean up | ||
170 | * any associated state. | ||
171 | * | ||
172 | * @param cls closure (set from GNUNET_CADET_connect) | ||
173 | * @param channel connection to the other end (henceforth invalid) | ||
174 | * @param channel_ctx place where local state associated | ||
175 | * with the channel is stored | ||
176 | */ | ||
177 | static void | ||
178 | channel_end (void *cls, const struct GNUNET_CADET_Channel *channel, | ||
179 | void *channel_ctx) | ||
180 | { | ||
181 | long id = (long) cls; | ||
182 | |||
183 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
184 | "incoming channel closed at peer %ld\n", | ||
185 | id); | ||
186 | if (NULL != mth) | ||
187 | { | ||
188 | GNUNET_CADET_notify_transmit_ready_cancel (mth); | ||
189 | mth = NULL; | ||
190 | } | ||
191 | if (GNUNET_NO == got_data) | ||
192 | { | ||
193 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( | ||
194 | GNUNET_TIME_UNIT_SECONDS, | ||
195 | 2), | ||
196 | &do_connect, NULL); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | |||
201 | /** | ||
202 | * Handler array for traffic received on peer1 | ||
203 | */ | ||
204 | static struct GNUNET_CADET_MessageHandler handlers1[] = { | ||
205 | {&data_callback, 1, 0}, | ||
206 | {NULL, 0, 0} | ||
207 | }; | ||
208 | |||
209 | |||
210 | /** | ||
211 | * Handler array for traffic received on peer2 (none expected) | ||
212 | */ | ||
213 | static struct GNUNET_CADET_MessageHandler handlers2[] = { | ||
214 | {&data_callback, 1, 0}, | ||
215 | {NULL, 0, 0} | ||
216 | }; | ||
217 | |||
218 | |||
219 | /** | ||
220 | * Data send callback: fillbuffer with test packet. | ||
221 | * | ||
222 | * @param cls Closure (unused). | ||
223 | * @param size Buffer size. | ||
224 | * @param buf Buffer to fill. | ||
225 | * | ||
226 | * @return size of test packet. | ||
227 | */ | ||
228 | static size_t | ||
229 | do_send (void *cls, size_t size, void *buf) | ||
230 | { | ||
231 | struct GNUNET_MessageHeader *m = buf; | ||
232 | |||
233 | mth = NULL; | ||
234 | if (NULL == buf) | ||
235 | { | ||
236 | GNUNET_break (0); | ||
237 | result = GNUNET_SYSERR; | ||
238 | return 0; | ||
239 | } | ||
240 | m->size = htons (sizeof (struct GNUNET_MessageHeader)); | ||
241 | m->type = htons (1); | ||
242 | GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); | ||
243 | return sizeof (struct GNUNET_MessageHeader); | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * Connect to other client and send data | ||
248 | * | ||
249 | * @param cls Closue (unused). | ||
250 | * @param tc TaskContext. | ||
251 | */ | ||
252 | static void | ||
253 | do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
254 | { | ||
255 | struct GNUNET_PeerIdentity id; | ||
256 | |||
257 | if (NULL != tc && 0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) | ||
258 | return; | ||
259 | |||
260 | GNUNET_TESTING_peer_get_identity (me, &id); | ||
261 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECT BY PORT\n"); | ||
262 | ch = GNUNET_CADET_channel_create (cadet_peer_1, NULL, &id, 1, | ||
263 | GNUNET_CADET_OPTION_DEFAULT); | ||
264 | mth = GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO, | ||
265 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
266 | sizeof (struct GNUNET_MessageHeader), | ||
267 | &do_send, NULL); | ||
268 | } | ||
269 | |||
270 | |||
271 | /** | ||
272 | * Initialize framework and start test | ||
273 | * | ||
274 | * @param cls Closure (unused). | ||
275 | * @param cfg Configuration handle. | ||
276 | * @param peer Testing peer handle. | ||
277 | */ | ||
278 | static void | ||
279 | run (void *cls, | ||
280 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
281 | struct GNUNET_TESTING_Peer *peer) | ||
282 | { | ||
283 | static uint32_t ports[] = {1, 0}; | ||
284 | |||
285 | me = peer; | ||
286 | abort_task = | ||
287 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
288 | (GNUNET_TIME_UNIT_SECONDS, 15), &do_abort, | ||
289 | NULL); | ||
290 | cadet_peer_1 = GNUNET_CADET_connect (cfg, /* configuration */ | ||
291 | (void *) 1L, /* cls */ | ||
292 | NULL, /* inbound new hndlr */ | ||
293 | &channel_end, /* channel end hndlr */ | ||
294 | handlers1, /* traffic handlers */ | ||
295 | NULL); /* ports offered */ | ||
296 | |||
297 | cadet_peer_2 = GNUNET_CADET_connect (cfg, /* configuration */ | ||
298 | (void *) 2L, /* cls */ | ||
299 | &inbound_channel, /* inbound new hndlr */ | ||
300 | &channel_end, /* channel end hndlr */ | ||
301 | handlers2, /* traffic handlers */ | ||
302 | ports); /* ports offered */ | ||
303 | if (NULL == cadet_peer_1 || NULL == cadet_peer_2) | ||
304 | { | ||
305 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to cadet :(\n"); | ||
306 | result = GNUNET_SYSERR; | ||
307 | return; | ||
308 | } | ||
309 | else | ||
310 | { | ||
311 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "YAY! CONNECTED TO CADET :D\n"); | ||
312 | } | ||
313 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( | ||
314 | GNUNET_TIME_UNIT_SECONDS, | ||
315 | 2), | ||
316 | &do_connect, NULL); | ||
317 | } | ||
318 | |||
319 | |||
320 | /** | ||
321 | * Main | ||
322 | */ | ||
323 | int | ||
324 | main (int argc, char *argv[]) | ||
325 | { | ||
326 | if (0 != GNUNET_TESTING_peer_run ("test-cadet-local", | ||
327 | "test_cadet.conf", | ||
328 | &run, NULL)) | ||
329 | { | ||
330 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n"); | ||
331 | return 2; | ||
332 | } | ||
333 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result); | ||
334 | return (result == GNUNET_OK) ? 0 : 1; | ||
335 | } | ||
336 | |||
337 | /* end of test_cadet_local_1.c */ | ||
diff --git a/src/cadet/test_cadet_single.c b/src/cadet/test_cadet_single.c new file mode 100644 index 000000000..3780c745c --- /dev/null +++ b/src/cadet/test_cadet_single.c | |||
@@ -0,0 +1,329 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2011 Christian Grothoff (and other contributing authors) | ||
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., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, 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 GNUNET_SCHEDULER_TaskIdentifier abort_task; | ||
47 | |||
48 | static GNUNET_SCHEDULER_TaskIdentifier shutdown_task; | ||
49 | |||
50 | static unsigned int repetition; | ||
51 | |||
52 | |||
53 | /* forward declaration */ | ||
54 | static size_t | ||
55 | do_send (void *cls, size_t size, void *buf); | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Shutdown nicely | ||
60 | */ | ||
61 | static void | ||
62 | do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
63 | { | ||
64 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutdown\n"); | ||
65 | if (GNUNET_SCHEDULER_NO_TASK != abort_task) | ||
66 | { | ||
67 | GNUNET_SCHEDULER_cancel (abort_task); | ||
68 | } | ||
69 | if (NULL != ch1) | ||
70 | { | ||
71 | GNUNET_CADET_channel_destroy (ch1); | ||
72 | } | ||
73 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 1\n"); | ||
74 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect client 2\n"); | ||
75 | if (NULL != cadet) | ||
76 | { | ||
77 | GNUNET_CADET_disconnect (cadet); | ||
78 | cadet = NULL; | ||
79 | } | ||
80 | else | ||
81 | { | ||
82 | GNUNET_break (0); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | |||
87 | /** | ||
88 | * Something went wrong and timed out. Kill everything and set error flag | ||
89 | */ | ||
90 | static void | ||
91 | do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
92 | { | ||
93 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ABORT\n"); | ||
94 | result = GNUNET_SYSERR; | ||
95 | abort_task = GNUNET_SCHEDULER_NO_TASK; | ||
96 | if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) | ||
97 | { | ||
98 | GNUNET_SCHEDULER_cancel (shutdown_task); | ||
99 | shutdown_task = GNUNET_SCHEDULER_NO_TASK; | ||
100 | } | ||
101 | do_shutdown (cls, tc); | ||
102 | } | ||
103 | |||
104 | |||
105 | static void | ||
106 | finish (void) | ||
107 | { | ||
108 | if (GNUNET_SCHEDULER_NO_TASK != shutdown_task) | ||
109 | GNUNET_SCHEDULER_cancel (shutdown_task); | ||
110 | shutdown_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, | ||
111 | &do_shutdown, NULL); | ||
112 | } | ||
113 | |||
114 | |||
115 | /** | ||
116 | * Function is called whenever a message is received. | ||
117 | * | ||
118 | * @param cls closure (set from GNUNET_CADET_connect) | ||
119 | * @param channel connection to the other end | ||
120 | * @param channel_ctx place to store local state associated with the channel | ||
121 | * @param message the actual message | ||
122 | * | ||
123 | * @return GNUNET_OK to keep the connection open, | ||
124 | * GNUNET_SYSERR to close it (signal serious error) | ||
125 | */ | ||
126 | static int | ||
127 | data_callback (void *cls, struct GNUNET_CADET_Channel *channel, | ||
128 | void **channel_ctx, | ||
129 | const struct GNUNET_MessageHeader *message) | ||
130 | { | ||
131 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
132 | "Data callback! Repetition %u/%u\n", | ||
133 | repetition, REPETITIONS); | ||
134 | repetition = repetition + 1; | ||
135 | if (repetition < REPETITIONS) | ||
136 | { | ||
137 | struct GNUNET_CADET_Channel *my_channel; | ||
138 | if (repetition % 2 == 0) | ||
139 | my_channel = ch1; | ||
140 | else | ||
141 | my_channel = ch2; | ||
142 | GNUNET_CADET_notify_transmit_ready (my_channel, GNUNET_NO, | ||
143 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
144 | sizeof (struct GNUNET_MessageHeader) | ||
145 | + DATA_SIZE, | ||
146 | &do_send, NULL); | ||
147 | GNUNET_CADET_receive_done (channel); | ||
148 | return GNUNET_OK; | ||
149 | } | ||
150 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All data OK. Destroying channel.\n"); | ||
151 | GNUNET_CADET_channel_destroy (ch1); | ||
152 | ch1 = NULL; | ||
153 | return GNUNET_OK; | ||
154 | } | ||
155 | |||
156 | |||
157 | /** | ||
158 | * Method called whenever another peer has added us to a channel | ||
159 | * the other peer initiated. | ||
160 | * | ||
161 | * @param cls closure | ||
162 | * @param channel new handle to the channel | ||
163 | * @param initiator peer that started the channel | ||
164 | * @param port port number | ||
165 | * @param options channel option flags | ||
166 | * @return initial channel context for the channel | ||
167 | * (can be NULL -- that's not an error) | ||
168 | */ | ||
169 | static void * | ||
170 | inbound_channel (void *cls, struct GNUNET_CADET_Channel *channel, | ||
171 | const struct GNUNET_PeerIdentity *initiator, | ||
172 | uint32_t port, enum GNUNET_CADET_ChannelOption options) | ||
173 | { | ||
174 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
175 | "received incoming channel on port %u\n", | ||
176 | port); | ||
177 | ch2 = channel; | ||
178 | return NULL; | ||
179 | } | ||
180 | |||
181 | |||
182 | /** | ||
183 | * Function called whenever an inbound channel is destroyed. Should clean up | ||
184 | * any associated state. | ||
185 | * | ||
186 | * @param cls closure (set from GNUNET_CADET_connect) | ||
187 | * @param channel connection to the other end (henceforth invalid) | ||
188 | * @param channel_ctx place where local state associated | ||
189 | * with the channel is stored | ||
190 | */ | ||
191 | static void | ||
192 | channel_end (void *cls, const struct GNUNET_CADET_Channel *channel, | ||
193 | void *channel_ctx) | ||
194 | { | ||
195 | long id = (long) cls; | ||
196 | |||
197 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
198 | "incoming channel closed at peer %ld\n", | ||
199 | id); | ||
200 | if (REPETITIONS == repetition && channel == ch2) | ||
201 | { | ||
202 | ch2 = NULL; | ||
203 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "everything fine! finishing!\n"); | ||
204 | result = GNUNET_OK; | ||
205 | finish (); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | |||
210 | /** | ||
211 | * Handler array for traffic received on peer1 | ||
212 | */ | ||
213 | static struct GNUNET_CADET_MessageHandler handlers1[] = { | ||
214 | {&data_callback, 1, 0}, | ||
215 | {NULL, 0, 0} | ||
216 | }; | ||
217 | |||
218 | |||
219 | /** | ||
220 | * Data send callback: fillbuffer with test packet. | ||
221 | * | ||
222 | * @param cls Closure (unused). | ||
223 | * @param size Buffer size. | ||
224 | * @param buf Buffer to fill. | ||
225 | * | ||
226 | * @return size of test packet. | ||
227 | */ | ||
228 | static size_t | ||
229 | do_send (void *cls, size_t size, void *buf) | ||
230 | { | ||
231 | struct GNUNET_MessageHeader *m = buf; | ||
232 | |||
233 | if (NULL == buf) | ||
234 | { | ||
235 | GNUNET_break (0); | ||
236 | result = GNUNET_SYSERR; | ||
237 | return 0; | ||
238 | } | ||
239 | m->size = htons (sizeof (struct GNUNET_MessageHeader)); | ||
240 | m->type = htons (1); | ||
241 | memset (&m[1], 0, DATA_SIZE); | ||
242 | GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader) + DATA_SIZE); | ||
243 | return sizeof (struct GNUNET_MessageHeader) + DATA_SIZE; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * Connect to other client and send data | ||
248 | * | ||
249 | * @param cls Closue (unused). | ||
250 | * @param tc TaskContext. | ||
251 | */ | ||
252 | static void | ||
253 | do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
254 | { | ||
255 | struct GNUNET_PeerIdentity id; | ||
256 | size_t size = sizeof (struct GNUNET_MessageHeader) + DATA_SIZE; | ||
257 | |||
258 | if ((GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason) != 0) | ||
259 | return; | ||
260 | |||
261 | GNUNET_TESTING_peer_get_identity (me, &id); | ||
262 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECT BY PORT\n"); | ||
263 | ch1 = GNUNET_CADET_channel_create (cadet, NULL, &id, 1, | ||
264 | GNUNET_CADET_OPTION_DEFAULT); | ||
265 | GNUNET_CADET_notify_transmit_ready (ch1, GNUNET_NO, | ||
266 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
267 | size, &do_send, NULL); | ||
268 | } | ||
269 | |||
270 | |||
271 | /** | ||
272 | * Initialize framework and start test | ||
273 | * | ||
274 | * @param cls Closure (unused). | ||
275 | * @param cfg Configuration handle. | ||
276 | * @param peer Testing peer handle. | ||
277 | */ | ||
278 | static void | ||
279 | run (void *cls, | ||
280 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
281 | struct GNUNET_TESTING_Peer *peer) | ||
282 | { | ||
283 | static uint32_t ports[] = {1, 0}; | ||
284 | |||
285 | me = peer; | ||
286 | abort_task = | ||
287 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
288 | (GNUNET_TIME_UNIT_SECONDS, 15), &do_abort, | ||
289 | NULL); | ||
290 | cadet = GNUNET_CADET_connect (cfg, /* configuration */ | ||
291 | (void *) 1L, /* cls */ | ||
292 | &inbound_channel, /* inbound new hndlr */ | ||
293 | &channel_end, /* inbound end hndlr */ | ||
294 | handlers1, /* traffic handlers */ | ||
295 | ports); /* ports offered */ | ||
296 | |||
297 | if (NULL == cadet) | ||
298 | { | ||
299 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Couldn't connect to cadet :(\n"); | ||
300 | result = GNUNET_SYSERR; | ||
301 | return; | ||
302 | } | ||
303 | else | ||
304 | { | ||
305 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "YAY! CONNECTED TO CADET :D\n"); | ||
306 | } | ||
307 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_connect, NULL); | ||
308 | } | ||
309 | |||
310 | |||
311 | /** | ||
312 | * Main | ||
313 | */ | ||
314 | int | ||
315 | main (int argc, char *argv[]) | ||
316 | { | ||
317 | result = GNUNET_NO; | ||
318 | if (0 != GNUNET_TESTING_peer_run ("test-cadet-local", | ||
319 | "test_cadet.conf", | ||
320 | &run, NULL)) | ||
321 | { | ||
322 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "run failed\n"); | ||
323 | return 2; | ||
324 | } | ||
325 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Final result: %d\n", result); | ||
326 | return (result == GNUNET_OK) ? 0 : 1; | ||
327 | } | ||
328 | |||
329 | /* end of test_cadet_single.c */ | ||
diff --git a/src/cadet/valgrind-mesh.supp b/src/cadet/valgrind-mesh.supp new file mode 100644 index 000000000..fecd5185b --- /dev/null +++ b/src/cadet/valgrind-mesh.supp | |||
@@ -0,0 +1,116 @@ | |||
1 | { | ||
2 | logsetup_addr | ||
3 | Memcheck:Addr8 | ||
4 | obj:/lib/libc-2.14.1.so | ||
5 | ... | ||
6 | fun:get_type | ||
7 | fun:GNUNET_log_setup | ||
8 | fun:GNUNET_SERVICE_run | ||
9 | fun:main | ||
10 | } | ||
11 | |||
12 | { | ||
13 | scanf_addr | ||
14 | Memcheck:Addr8 | ||
15 | obj:/lib/libc-2.14.1.so | ||
16 | ... | ||
17 | fun:vsscanf | ||
18 | fun:sscanf | ||
19 | fun:GNUNET_CONFIGURATION_get_value_number | ||
20 | fun:GNUNET_SERVICE_get_server_addresses | ||
21 | fun:setup_service | ||
22 | fun:GNUNET_SERVICE_run | ||
23 | fun:main | ||
24 | } | ||
25 | |||
26 | { | ||
27 | mylog_addr | ||
28 | Memcheck:Addr8 | ||
29 | obj:/lib/libc-2.14.1.so | ||
30 | ... | ||
31 | fun:service_task | ||
32 | fun:GNUNET_SCHEDULER_run | ||
33 | fun:GNUNET_SERVICE_run | ||
34 | fun:main | ||
35 | } | ||
36 | |||
37 | { | ||
38 | mylog_uninit | ||
39 | Memcheck:Value8 | ||
40 | obj:/lib/libc-2.14.1.so | ||
41 | ... | ||
42 | fun:mylog | ||
43 | fun:GNUNET_log_from_nocheck | ||
44 | fun:service_task | ||
45 | ... | ||
46 | fun:GNUNET_SCHEDULER_run | ||
47 | fun:GNUNET_SERVICE_run | ||
48 | fun:main | ||
49 | } | ||
50 | |||
51 | { | ||
52 | mylog_from_cond | ||
53 | Memcheck:Cond | ||
54 | obj:/lib/libc-2.14.1.so | ||
55 | ... | ||
56 | fun:mylog | ||
57 | fun:GNUNET_log_from_nocheck | ||
58 | ... | ||
59 | fun:service_task | ||
60 | fun:GNUNET_SCHEDULER_run | ||
61 | fun:GNUNET_SERVICE_run | ||
62 | fun:main | ||
63 | } | ||
64 | |||
65 | { | ||
66 | mylog_cond | ||
67 | Memcheck:Cond | ||
68 | obj:/lib/libc-2.14.1.so | ||
69 | ... | ||
70 | fun:mylog | ||
71 | fun:GNUNET_log_nocheck | ||
72 | ... | ||
73 | fun:service_task | ||
74 | fun:GNUNET_SCHEDULER_run | ||
75 | fun:GNUNET_SERVICE_run | ||
76 | fun:main | ||
77 | } | ||
78 | |||
79 | { | ||
80 | inet_ntop_cond | ||
81 | Memcheck:Cond | ||
82 | obj:/lib/libc-2.14.1.so | ||
83 | ... | ||
84 | fun:inet_ntop | ||
85 | fun:GNUNET_a2s | ||
86 | ... | ||
87 | fun:service_task | ||
88 | fun:GNUNET_SCHEDULER_run | ||
89 | fun:GNUNET_SERVICE_run | ||
90 | fun:main | ||
91 | } | ||
92 | |||
93 | { | ||
94 | create_key_from_file | ||
95 | Memcheck:Addr8 | ||
96 | obj:/lib/libc-2.14.1.so | ||
97 | ... | ||
98 | fun:GNUNET_CRYPTO_rsa_key_create_from_file | ||
99 | fun:run | ||
100 | fun:service_task | ||
101 | fun:GNUNET_SCHEDULER_run | ||
102 | fun:GNUNET_SERVICE_run | ||
103 | fun:main | ||
104 | } | ||
105 | |||
106 | { | ||
107 | main_notify_handler | ||
108 | Memcheck:Addr8 | ||
109 | obj:/lib/libc-2.14.1.so | ||
110 | ... | ||
111 | fun:main_notify_handler | ||
112 | fun:receive_ready | ||
113 | fun:GNUNET_SCHEDULER_run | ||
114 | fun:GNUNET_SERVICE_run | ||
115 | fun:main | ||
116 | } \ No newline at end of file | ||