aboutsummaryrefslogtreecommitdiff
path: root/src/cadet
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2014-05-07 12:07:16 +0000
committerBart Polot <bart@net.in.tum.de>2014-05-07 12:07:16 +0000
commit41716952f1d0508fb621cb5fec31406d3bd96192 (patch)
tree0ea8e1a1397babe96db05d17cb7618fc69bb88c7 /src/cadet
parent74794f20cec6fbbd007e0921e7a347655050c024 (diff)
downloadgnunet-41716952f1d0508fb621cb5fec31406d3bd96192.tar.gz
gnunet-41716952f1d0508fb621cb5fec31406d3bd96192.zip
Renamed directory
Diffstat (limited to 'src/cadet')
-rw-r--r--src/cadet/Makefile.am194
-rwxr-xr-xsrc/cadet/beautify_log.sh18
-rw-r--r--src/cadet/cadet.h351
-rw-r--r--src/cadet/cadet_api.c2141
-rw-r--r--src/cadet/cadet_common.c348
-rw-r--r--src/cadet/cadet_path.c213
-rw-r--r--src/cadet/cadet_path.h185
-rw-r--r--src/cadet/cadet_protocol.h459
-rw-r--r--src/cadet/cadet_test_lib.c295
-rw-r--r--src/cadet/cadet_test_lib.h106
-rw-r--r--src/cadet/cadet_tunnel_tree.c1174
-rw-r--r--src/cadet/cadet_tunnel_tree.h382
-rw-r--r--src/cadet/gnunet-cadet-profiler.c1092
-rw-r--r--src/cadet/gnunet-cadet.c851
-rw-r--r--src/cadet/gnunet-service-cadet.c181
-rw-r--r--src/cadet/gnunet-service-cadet_channel.c2432
-rw-r--r--src/cadet/gnunet-service-cadet_channel.h349
-rw-r--r--src/cadet/gnunet-service-cadet_connection.c3176
-rw-r--r--src/cadet/gnunet-service-cadet_connection.h566
-rw-r--r--src/cadet/gnunet-service-cadet_dht.c423
-rw-r--r--src/cadet/gnunet-service-cadet_dht.h92
-rw-r--r--src/cadet/gnunet-service-cadet_hello.c198
-rw-r--r--src/cadet/gnunet-service-cadet_hello.h76
-rw-r--r--src/cadet/gnunet-service-cadet_local.c1242
-rw-r--r--src/cadet/gnunet-service-cadet_local.h226
-rw-r--r--src/cadet/gnunet-service-cadet_peer.c2219
-rw-r--r--src/cadet/gnunet-service-cadet_peer.h418
-rw-r--r--src/cadet/gnunet-service-cadet_tunnel.c2887
-rw-r--r--src/cadet/gnunet-service-cadet_tunnel.h531
-rwxr-xr-xsrc/cadet/loopcheck.sh8
-rw-r--r--src/cadet/mesh.conf.in21
-rw-r--r--src/cadet/profiler.conf19
-rwxr-xr-xsrc/cadet/run_profiler.sh25
-rw-r--r--src/cadet/small.dat21
-rw-r--r--src/cadet/test_cadet.c953
-rw-r--r--src/cadet/test_cadet.conf100
-rw-r--r--src/cadet/test_cadet_drop.conf4
-rw-r--r--src/cadet/test_cadet_local.c337
-rw-r--r--src/cadet/test_cadet_single.c329
-rw-r--r--src/cadet/valgrind-mesh.supp116
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 @@
1AM_CPPFLAGS = -I$(top_srcdir)/src/include
2
3if MINGW
4 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
5endif
6
7if USE_COVERAGE
8 AM_CFLAGS = --coverage -O0
9 XLIB = -lgcov
10endif
11
12pkgcfgdir= $(pkgdatadir)/config.d/
13
14libexecdir= $(pkglibdir)/libexec/
15
16pkgcfg_DATA = \
17 cadet.conf
18
19plugindir = $(libdir)/gnunet
20
21AM_CLFAGS = -g
22
23libexec_PROGRAMS = \
24 gnunet-service-cadet $(EXP_LIBEXEC)
25
26bin_PROGRAMS = \
27 gnunet-cadet
28
29lib_LTLIBRARIES = \
30 libgnunetcadet.la $(EXP_LIB)
31
32libgnunetcadet_la_SOURCES = \
33 cadet_api.c cadet_common.c
34libgnunetcadet_la_LIBADD = \
35 $(top_builddir)/src/util/libgnunetutil.la \
36 $(XLIB) \
37 $(LTLIBINTL)
38libgnunetcadet_la_LDFLAGS = \
39 $(GN_LIB_LDFLAGS) $(WINFLAGS) \
40 -version-info 5:0:0
41
42gnunet_cadet_SOURCES = \
43 gnunet-cadet.c
44gnunet_cadet_LDADD = \
45 $(top_builddir)/src/cadet/libgnunetcadet.la \
46 $(top_builddir)/src/util/libgnunetutil.la
47gnunet_cadet_DEPENDENCIES = \
48 libgnunetcadet.la
49
50gnunet_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
61gnunet_service_cadet_CFLAGS = $(AM_CFLAGS)
62gnunet_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
71gnunet_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
80if LINUX
81 gnunet_service_cadet_LDFLAGS = -lrt
82endif
83
84
85if HAVE_TESTING
86 noinst_LIBRARIES = libgnunetcadettest.a $(noinst_LIB_EXP)
87 noinst_PROGRAMS = gnunet-cadet-profiler
88endif
89
90libgnunetcadettest_a_SOURCES = \
91 cadet_test_lib.c cadet_test_lib.h
92libgnunetcadettest_a_LIBADD = \
93 $(top_builddir)/src/util/libgnunetutil.la \
94 $(top_builddir)/src/testbed/libgnunettestbed.la \
95 $(top_builddir)/src/cadet/libgnunetcadet.la
96libgnunetcadettest_a_DEPENDENCIES = \
97 libgnunetcadet.la
98
99if HAVE_TESTING
100check_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
111endif
112
113ld_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
121dep_cadet_test_lib = \
122 libgnunetcadet.la \
123 libgnunetcadettest.a \
124 $(top_builddir)/src/statistics/libgnunetstatistics.la
125
126
127gnunet_cadet_profiler_SOURCES = \
128 gnunet-cadet-profiler.c
129gnunet_cadet_profiler_LDADD = $(ld_cadet_test_lib)
130gnunet_cadet_profiler_DEPENDENCIES = $(dep_cadet_test_lib)
131
132
133test_cadet_single_SOURCES = \
134 test_cadet_single.c
135test_cadet_single_LDADD = $(ld_cadet_test_lib)
136test_cadet_single_DEPENDENCIES = $(dep_cadet_test_lib)
137
138test_cadet_local_SOURCES = \
139 test_cadet_local.c
140test_cadet_local_LDADD = $(ld_cadet_test_lib)
141test_cadet_local_DEPENDENCIES = $(dep_cadet_test_lib)
142
143test_cadet_forward_SOURCES = \
144 test_cadet.c
145test_cadet_forward_LDADD = $(ld_cadet_test_lib)
146test_cadet_forward_DEPENDENCIES = $(dep_cadet_test_lib)
147
148test_cadet_signal_SOURCES = \
149 test_cadet.c
150test_cadet_signal_LDADD = $(ld_cadet_test_lib)
151test_cadet_signal_DEPENDENCIES = $(dep_cadet_test_lib)
152
153test_cadet_keepalive_SOURCES = \
154 test_cadet.c
155test_cadet_keepalive_LDADD = $(ld_cadet_test_lib)
156test_cadet_keepalive_DEPENDENCIES = $(dep_cadet_test_lib)
157
158test_cadet_speed_SOURCES = \
159 test_cadet.c
160test_cadet_speed_LDADD = $(ld_cadet_test_lib)
161test_cadet_speed_DEPENDENCIES = $(dep_cadet_test_lib)
162
163test_cadet_speed_ack_SOURCES = \
164 test_cadet.c
165test_cadet_speed_ack_LDADD = $(ld_cadet_test_lib)
166test_cadet_speed_ack_DEPENDENCIES = $(dep_cadet_test_lib)
167
168test_cadet_speed_backwards_SOURCES = \
169 test_cadet.c
170test_cadet_speed_backwards_LDADD = $(ld_cadet_test_lib)
171test_cadet_speed_backwards_DEPENDENCIES = $(dep_cadet_test_lib)
172
173test_cadet_speed_reliable_SOURCES = \
174 test_cadet.c
175test_cadet_speed_reliable_LDADD = $(ld_cadet_test_lib)
176test_cadet_speed_reliable_DEPENDENCIES = $(dep_cadet_test_lib)
177
178test_cadet_speed_reliable_backwards_SOURCES = \
179 test_cadet.c
180test_cadet_speed_reliable_backwards_LDADD = $(ld_cadet_test_lib)
181test_cadet_speed_reliable_backwards_DEPENDENCIES = $(dep_cadet_test_lib)
182
183
184if ENABLE_TEST_RUN
185AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;
186TESTS = \
187 $(check_PROGRAMS)
188endif
189
190EXTRA_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
2grep "STARTING SERVICE " log > __tmp_peers
3SED_EXPR=""
4while 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/;"
10done < __tmp_peers
11rm __tmp_peers
12
13SED_EXPR="${SED_EXPR}s/mesh-api-/mesh-api- /g"
14sed -e "$SED_EXPR" log > .log
15
16if [[ "`ps aux | grep "kwrite .lo[g]"`" = "" ]]; then
17 kwrite .log --geometry 960x1140-960 &
18fi
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
30extern "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
64GNUNET_NETWORK_STRUCT_BEGIN
65
66/**
67 * Message for a client to register to the service
68 */
69struct 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 */
89typedef uint32_t CADET_ChannelNumber;
90
91
92/**
93 * Message for a client to create and destroy channels.
94 */
95struct 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 */
129struct 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 */
151struct 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 */
169struct 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 */
196struct 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 */
225struct 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
262GNUNET_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 */
273char *
274GM_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 */
285int
286GM_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 */
297uint32_t
298GM_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 */
309uint32_t
310GM_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 */
321const struct GNUNET_HashCode *
322GM_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 */
328const char *
329GM_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 */
341const char *
342GM_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 */
39struct 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
89union 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 */
121struct 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 */
230struct 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 */
247struct 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 */
306struct 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 */
335static size_t
336send_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 */
351static int
352th_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 */
366static size_t
367message_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 */
396static struct GNUNET_CADET_Channel *
397retrieve_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 */
420static struct GNUNET_CADET_Channel *
421create_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 */
459static void
460destroy_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 */
525static void
526timeout_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 */
553static void
554add_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 */
575static void
576send_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 */
586static void
587send_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 */
608static void
609reconnect_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 */
619static void
620send_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 */
659static int
660do_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 */
709static void
710reconnect_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 */
729static void
730reconnect (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 */
759static void
760process_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 */
818static void
819process_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 */
845static void
846process_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 */
915static void
916process_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 */
1036static void
1037process_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 */
1074static void
1075process_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 */
1138static void
1139process_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 */
1176static void
1177process_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
1228clean_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 */
1240static void
1241msg_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 */
1329static size_t
1330send_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 */
1451static void
1452send_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
1483struct GNUNET_CADET_Handle *
1484GNUNET_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
1537void
1538GNUNET_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 */
1623struct GNUNET_CADET_Channel *
1624GNUNET_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
1653void
1654GNUNET_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 */
1701const union GNUNET_CADET_ChannelInfo *
1702GNUNET_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
1730struct GNUNET_CADET_TransmitHandle *
1731GNUNET_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
1774void
1775GNUNET_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
1794void
1795GNUNET_CADET_receive_done (struct GNUNET_CADET_Channel *channel)
1796{
1797 send_ack (channel);
1798}
1799
1800
1801static void
1802send_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 */
1826int
1827GNUNET_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 */
1852void *
1853GNUNET_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 */
1878int
1879GNUNET_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 */
1916int
1917GNUNET_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 */
1940void *
1941GNUNET_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 */
1968int
1969GNUNET_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 */
2007int
2008GNUNET_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 */
2045static size_t
2046cadet_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 */
2076static void
2077cadet_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 */
2103static void
2104cadet_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 */
2123struct GNUNET_MQ_Handle *
2124GNUNET_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 */
36char *
37GM_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
54int
55GM_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
62uint32_t
63GM_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
71uint32_t
72GM_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
80const struct GNUNET_HashCode *
81GM_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
90const char *
91GM_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)
103const char *
104GM_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
343const char *
344GM_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 */
39static void
40path_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 */
58struct CadetPeerPath *
59path_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 */
78void
79path_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 */
98struct CadetPeerPath *
99path_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 */
120unsigned int
121path_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 */
138void
139path_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 */
157int
158path_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 */
171int
172path_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
185char *
186path_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
203void
204path_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
33extern "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 */
47struct 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 */
95struct CadetPeerPath *
96path_new (unsigned int length);
97
98
99/**
100 * Invert the path.
101 *
102 * @param path The path to invert.
103 */
104void
105path_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 */
113struct CadetPeerPath *
114path_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 */
125unsigned int
126path_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 */
136void
137path_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 */
147int
148path_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 */
157int
158path_destroy (struct CadetPeerPath *p);
159
160/**
161 * Path -> allocated one line string. Caller must free.
162 *
163 * @param p Path.
164 */
165char *
166path_2s (struct CadetPeerPath *p);
167
168/**
169 * Print info about the path for debug.
170 *
171 * @param p Path to debug.
172 */
173void
174path_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
35struct GNUNET_CADET_TunnelMessage;
36extern "C"
37{
38#if 0
39 /* keep Emacsens' auto-indent happy */
40}
41#endif
42#endif
43
44/******************************************************************************/
45/******************** CADET NETWORK MESSAGES **************************/
46/******************************************************************************/
47
48GNUNET_NETWORK_STRUCT_BEGIN
49
50/**
51 * Message for cadet connection creation.
52 */
53struct 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 */
78struct 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 */
96struct 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 */
118struct 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 */
170struct 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 */
198struct 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 */
220struct 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 */
262struct 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 */
289struct 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 */
306struct 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 */
333struct 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 */
362struct 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 */
384struct 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 */
407struct 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 */
434struct 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
448GNUNET_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 */
33struct 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 */
91struct 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 */
115static void *
116cadet_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 */
140static void
141cadet_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 */
162static void
163cadet_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
196void
197GNUNET_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 */
227static void
228cadet_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
265void
266GNUNET_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
29extern "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 */
42struct 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 */
54typedef 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 */
76void
77GNUNET_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 */
93void
94GNUNET_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 */
36struct 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 */
78struct 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 */
117struct CadetPeerPath *
118path_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 */
137void
138path_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 */
157struct CadetPeerPath *
158path_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 */
179static void
180tree_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 */
193unsigned int
194path_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 */
209int
210path_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 */
231static struct CadetTunnelTreeNode *
232tree_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 */
256static struct CadetTunnelTreeNode *
257tree_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 */
282static void
283tree_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 = &pi;
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
339static void
340tree_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 */
376static void
377tree_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 */
415struct CadetTunnelTree *
416tree_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 */
441void
442tree_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 */
462enum CadetPeerState
463tree_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 */
481GNUNET_PEER_Id
482tree_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 */
502struct GNUNET_PeerIdentity *
503tree_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 */
541struct CadetTunnelTreeNode *
542tree_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 */
556static void
557tree_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 */
592void
593tree_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 */
610struct 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 */
638void
639tree_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 */
676static void
677count_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 */
690unsigned int
691tree_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 */
709void
710tree_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 */
730struct CadetTunnelTreeNode *
731tree_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 */
803struct CadetPeerPath *
804tree_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 */
861int
862tree_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 */
1012GNUNET_PEER_Id
1013tree_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 */
1059int
1060tree_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 */
1096unsigned int
1097tree_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 */
1133void
1134tree_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 */
1151static int
1152iterate_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 */
1164void
1165tree_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 */
36struct 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 */
61struct CadetTunnelTreeNode;
62
63
64/**
65 * Tree to reach all peers in the tunnel
66 */
67struct 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 */
81struct CadetPeerPath *
82path_new (unsigned int length);
83
84
85/**
86 * Invert the path.
87 *
88 * @param path The path to invert.
89 */
90void
91path_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 */
99struct CadetPeerPath *
100path_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 */
111unsigned int
112path_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 */
122int
123path_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 */
134typedef 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 */
144typedef 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 */
155struct CadetTunnelTree *
156tree_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 */
166void
167tree_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 */
179enum CadetPeerState
180tree_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 */
190GNUNET_PEER_Id
191tree_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 */
203struct GNUNET_PeerIdentity *
204tree_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 */
215struct CadetTunnelTreeNode *
216tree_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 */
226void
227tree_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 */
241void
242tree_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 */
251unsigned int
252tree_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 */
263void
264tree_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 */
281struct CadetTunnelTreeNode *
282tree_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 */
296struct CadetPeerPath *
297tree_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 */
311int
312tree_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 */
328GNUNET_PEER_Id
329tree_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 */
349int
350tree_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 */
363unsigned int
364tree_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 */
372void
373tree_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 */
381void
382tree_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 */
59static 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 */
64struct 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 */
90struct 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 */
162static struct GNUNET_TIME_Relative round_time;
163
164/**
165 * GNUNET_PeerIdentity -> CadetPeer
166 */
167static struct GNUNET_CONTAINER_MultiPeerMap *ids;
168
169/**
170 * Testbed peer handles.
171 */
172static struct GNUNET_TESTBED_Peer **testbed_handles;
173
174/**
175 * Testbed Operation (to get stats).
176 */
177static struct GNUNET_TESTBED_Operation *stats_op;
178
179/**
180 * Operation to get peer ids.
181 */
182struct CadetPeer *peers;
183
184/**
185 * Peer ids counter.
186 */
187static unsigned int p_ids;
188
189/**
190 * Total number of peers.
191 */
192static unsigned long long peers_total;
193
194/**
195 * Number of currently running peers.
196 */
197static unsigned long long peers_running;
198
199/**
200 * Number of peers doing pings.
201 */
202static unsigned long long peers_pinging;
203
204/**
205 * Test context (to shut down).
206 */
207static struct GNUNET_CADET_TEST_Context *test_ctx;
208
209/**
210 * Task called to shutdown test.
211 */
212static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
213
214/**
215 * Task called to disconnect peers, before shutdown.
216 */
217static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
218
219/**
220 * Task to perform tests
221 */
222static GNUNET_SCHEDULER_TaskIdentifier test_task;
223
224/**
225 * Round number.
226 */
227static unsigned int current_round;
228
229/**
230 * Do preconnect? (Each peer creates a tunnel to one other peer).
231 */
232static int do_warmup;
233
234/**
235 * Warmup progress.
236 */
237static unsigned int peers_warmup;
238
239/**
240 * Flag to notify callbacks not to generate any new traffic anymore.
241 */
242static 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 */
254static void
255start_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 */
265static struct GNUNET_TIME_Relative
266delay_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 */
282static unsigned int
283get_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 */
292static void
293show_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 */
319static void
320shutdown_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 */
333static void
334disconnect_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 */
382static void
383abort_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 */
402static void
403stats_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 */
427static int
428stats_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 */
448static void
449collect_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 */
467static void
468finish_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 */
483static void
484adjust_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 */
547static void
548next_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 */
576static size_t
577tmt_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 */
587static size_t
588tmt_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 */
613static void
614ping (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 */
639static void
640pong (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 */
660static size_t
661tmt_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 */
700int
701ping_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 */
726int
727pong_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 */
764static 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 */
783static void *
784incoming_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 */
826static void
827channel_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 */
847static struct CadetPeer *
848select_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 */
870static void
871start_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 */
915static void
916warmup (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 */
947static void
948peer_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 */
999static void
1000tmain (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 */
1036int
1037main (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 */
35static int monitor_connections;
36
37/**
38 * Option -P.
39 */
40static int request_peers;
41
42/**
43 * Option --peer
44 */
45static char *peer_id;
46
47/**
48 * Option -T.
49 */
50static int request_tunnels;
51
52/**
53 * Option --tunnel
54 */
55static char *tunnel_id;
56
57/**
58 * Option --connection
59 */
60static char *conn_id;
61
62/**
63 * Option --channel
64 */
65static char *channel_id;
66
67/**
68 * Port to listen on (-p).
69 */
70static uint32_t listen_port;
71
72/**
73 * Request echo service
74 */
75int echo;
76
77/**
78 * Time of last echo request.
79 */
80struct GNUNET_TIME_Absolute echo_time;
81
82/**
83 * Task for next echo request.
84 */
85GNUNET_SCHEDULER_TaskIdentifier echo_task;
86
87/**
88 * Peer to connect to.
89 */
90static char *target_id;
91
92/**
93 * Port to connect to
94 */
95static uint32_t target_port;
96
97/**
98 * Data pending in netcat mode.
99 */
100size_t data_size;
101
102
103/**
104 * Cadet handle.
105 */
106static struct GNUNET_CADET_Handle *mh;
107
108/**
109 * Channel handle.
110 */
111static struct GNUNET_CADET_Channel *ch;
112
113/**
114 * Shutdown task handle.
115 */
116GNUNET_SCHEDULER_TaskIdentifier sd;
117
118
119
120static void
121listen_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 */
132static void
133shutdown_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 */
163size_t
164data_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 */
203static void
204read_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 */
232static void
233listen_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 */
258static void
259channel_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 */
288static void *
289channel_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 */
323static void
324send_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 */
343static void
344create_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 */
386static int
387data_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 */
455static void
456peers_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 */
484void
485peer_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 */
505void
506tunnels_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 */
539void
540tunnel_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 */
578static void
579get_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 */
596static void
597show_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 */
621static void
622get_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 */
639static void
640show_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 */
665static void
666show_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 */
678static void
679show_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 */
693static void
694run (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 */
797int
798main (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 */
67struct GNUNET_STATISTICS_Handle *stats;
68
69/**
70 * Local peer own ID (memory efficient handle).
71 */
72GNUNET_PEER_Id myid;
73
74/**
75 * Local peer own ID (full value).
76 */
77struct GNUNET_PeerIdentity my_full_id;
78
79
80/**
81 * Signal that shutdown is happening: prevent recover measures.
82 */
83int shutting_down;
84
85/*************************** Static global variables **************************/
86
87/**
88 * Own private key.
89 */
90static 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 */
103static void
104shutdown_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 */
130static void
131run (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 */
168int
169main (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 */
45enum 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 */
67struct 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 */
94struct 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 */
134struct 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 */
203struct 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 */
296extern struct GNUNET_STATISTICS_Handle *stats;
297
298/**
299 * Local peer own ID (memory efficient handle).
300 */
301extern 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 */
319static int
320rel_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 */
327static void
328send_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 */
337static void
338send_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 */
349static int
350is_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 */
366static struct CadetReliableMessage *
367copy_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 (&copy[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 */
391static void
392add_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 */
438static void
439add_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 */
469static void
470channel_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 */
486static uint32_t
487channel_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 */
507static void
508send_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 */
538static void
539send_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 */
565static void
566send_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 */
595static void
596send_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 *) &copy[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 */
659static void
660send_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 */
696static void
697send_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 */
714static void
715channel_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 *) &copy[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 */
753static void
754channel_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 */
790static void
791ch_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 */
877static void
878send_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 */
899static void
900send_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 */
922static void
923fire_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 */
937static void
938send_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 */
960static void
961channel_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 */
1017static void
1018channel_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 */
1096static int
1097rel_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 */
1150static void
1151channel_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 */
1211static struct CadetReliableMessage *
1212channel_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 (&copy[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 */
1250static struct CadetChannel *
1251channel_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 */
1282void
1283handle_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 */
1347void
1348GMCH_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 */
1394CADET_ChannelNumber
1395GMCH_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 */
1408struct CadetTunnel3 *
1409GMCH_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 */
1423unsigned int
1424GMCH_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 */
1449int
1450GMCH_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 */
1475int
1476GMCH_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 */
1493int
1494GMCH_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 */
1511void
1512GMCH_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 */
1572void
1573GMCH_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 */
1632void
1633GMCH_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 */
1671void
1672GMCH_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 */
1719int
1720GMCH_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 */
1789void
1790GMCH_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 */
1825int
1826GMCH_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 */
1893void
1894GMCH_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 */
1998void
1999GMCH_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 */
2098struct CadetChannel *
2099GMCH_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 */
2185void
2186GMCH_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 */
2203void
2204GMCH_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 */
2234void
2235GMCH_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 */
2289void
2290GMCH_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 */
2420const char *
2421GMCH_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
33extern "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 */
49struct 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 */
61void
62GMCH_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 */
72CADET_ChannelNumber
73GMCH_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 */
82struct CadetTunnel3 *
83GMCH_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 */
93unsigned int
94GMCH_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 */
105int
106GMCH_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 */
117int
118GMCH_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 */
128int
129GMCH_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 */
139void
140GMCH_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 */
147void
148GMCH_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 */
156void
157GMCH_allow_client (struct CadetChannel *ch, int fwd);
158
159/**
160 * Log channel info.
161 *
162 * @param ch Channel.
163 */
164void
165GMCH_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 */
175void
176GMCH_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 */
192int
193GMCH_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 */
207void
208GMCH_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 */
222int
223GMCH_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 */
236void
237GMCH_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 */
251void
252GMCH_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 */
264struct CadetChannel *
265GMCH_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 */
275void
276GMCH_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 */
288void
289GMCH_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 */
303void
304GMCH_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 */
324void
325GMCH_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 */
336const char *
337GMCH_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 */
56struct 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 */
117struct 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 */
144struct 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 */
224struct 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 */
254extern struct GNUNET_STATISTICS_Handle *stats;
255
256/**
257 * Local peer own ID (memory efficient handle).
258 */
259extern GNUNET_PEER_Id myid;
260
261/**
262 * Local peer own ID (full value).
263 */
264extern struct GNUNET_PeerIdentity my_full_id;
265
266/**
267 * Connections known, indexed by cid (CadetConnection).
268 */
269static 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 */
275static 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 */
281static unsigned long long max_msgs_queue;
282
283/**
284 * How often to send path keepalives. Paths timeout after 4 missed.
285 */
286static struct GNUNET_TIME_Relative refresh_connection_time;
287
288/**
289 * How often to send path create / ACKs.
290 */
291static struct GNUNET_TIME_Relative create_connection_time;
292
293
294/******************************************************************************/
295/******************************** STATIC ***********************************/
296/******************************************************************************/
297
298#if 0 // avoid compiler warning for unused static function
299static void
300fc_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
310static void
311connection_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 */
337static void
338schedule_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 */
353static void
354connection_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 */
364static const char *
365GMC_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 */
390static void
391fc_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 */
409static struct CadetConnection *
410connection_get (const struct GNUNET_CADET_Hash *cid)
411{
412 return GNUNET_CONTAINER_multihashmap_get (connections, GM_h2hc (cid));
413}
414
415
416static void
417connection_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 */
444static void
445ack_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 */
469static void
470send_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 */
562static void
563conn_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 */
700static struct CadetPeer *
701get_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 */
726static struct CadetPeer *
727get_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 */
753static struct CadetPeer *
754get_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 */
773static int
774is_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 */
799static void
800send_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 */
828static void
829send_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 */
856static void
857send_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 */
893static void
894send_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 */
927static void
928connection_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 */
946static void
947connection_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 */
983static void
984connection_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 */
1009static void
1010connection_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 */
1025static void
1026connection_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 */
1044static void
1045schedule_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 */
1106static void
1107connection_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 */
1135static void
1136connection_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 */
1169static void
1170connection_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 */
1183static void
1184poll_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 */
1213static void
1214connection_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 */
1250static void
1251connection_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 */
1279static void
1280connection_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 */
1316static void
1317connection_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 */
1350static int
1351register_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 */
1397static void
1398unregister_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 */
1431static void
1432add_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 */
1449static struct CadetPeerPath *
1450build_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 */
1508static void
1509log_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 */
1532int
1533GMC_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 */
1661int
1662GMC_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 */
1789int
1790GMC_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 */
1856int
1857GMC_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 */
1914static int
1915handle_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 */
2047static int
2048handle_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 */
2149int
2150GMC_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 */
2168int
2169GMC_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 */
2187int
2188GMC_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 */
2261int
2262GMC_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 */
2325void
2326GMC_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 */
2381void
2382GMC_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 */
2428static int
2429shutdown_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 */
2443void
2444GMC_shutdown (void)
2445{
2446 GNUNET_CONTAINER_multihashmap_iterate (connections, &shutdown_iterator, NULL);
2447 GNUNET_CONTAINER_multihashmap_destroy (connections);
2448 connections = NULL;
2449}
2450
2451
2452struct CadetConnection *
2453GMC_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
2493void
2494GMC_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 */
2571const struct GNUNET_CADET_Hash *
2572GMC_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 */
2585const struct GNUNET_HashCode *
2586GMC_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 */
2599const struct CadetPeerPath *
2600GMC_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 */
2615enum CadetConnectionState
2616GMC_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 */
2628struct CadetTunnel3 *
2629GMC_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 */
2643unsigned int
2644GMC_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 */
2661unsigned int
2662GMC_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 */
2682unsigned int
2683GMC_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 */
2701unsigned int
2702GMC_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 */
2722void
2723GMC_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 */
2738void
2739GMC_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 */
2782int
2783GMC_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 */
2802int
2803GMC_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 */
2817int
2818GMC_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 */
2850int
2851GMC_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 */
2873struct CadetConnectionQueue *
2874GMC_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 */
3021void
3022GMC_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 */
3037void
3038GMC_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 */
3076void
3077GMC_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 */
3114void
3115GMC_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 */
3143void
3144GMC_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 */
3161const char *
3162GMC_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
33extern "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 */
46enum 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 */
78struct CadetConnection;
79
80/**
81 * Handle for messages queued but not yet sent.
82 */
83struct 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 */
100typedef 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 */
115int
116GMC_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 */
129int
130GMC_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 */
143int
144GMC_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 */
158int
159GMC_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 */
172int
173GMC_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 */
186int
187GMC_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 */
200int
201GMC_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 */
214int
215GMC_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 */
229int
230GMC_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 */
241void
242GMC_send_ack (struct CadetConnection *c, int fwd, int force);
243
244/**
245 * Initialize the connections subsystem
246 *
247 * @param c Configuration handle.
248 */
249void
250GMC_init (const struct GNUNET_CONFIGURATION_Handle *c);
251
252/**
253 * Shut down the connections subsystem.
254 */
255void
256GMC_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 */
268struct CadetConnection *
269GMC_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 */
282void
283GMC_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 */
292const struct GNUNET_CADET_Hash *
293GMC_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 */
303const struct GNUNET_HashCode *
304GMC_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 */
314const struct CadetPeerPath *
315GMC_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 */
324enum CadetConnectionState
325GMC_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 */
334struct CadetTunnel3 *
335GMC_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 */
345unsigned int
346GMC_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 */
356unsigned int
357GMC_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 */
367unsigned int
368GMC_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 */
378unsigned int
379GMC_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 */
391void
392GMC_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 */
400void
401GMC_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 */
409void
410GMC_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 */
420void
421GMC_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 */
432int
433GMC_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 */
444int
445GMC_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 */
455int
456GMC_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 */
465int
466GMC_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 */
477void
478GMC_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 */
497struct CadetConnectionQueue *
498GMC_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 */
509void
510GMC_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 */
521void
522GMC_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 */
534void
535GMC_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 */
546void
547GMC_stop_poll (struct CadetConnection *c, int fwd);
548
549/**
550 * Get a (static) string for a connection.
551 *
552 * @param c Connection.
553 */
554const char *
555GMC_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 */
43struct 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 */
66extern struct GNUNET_STATISTICS_Handle *stats;
67
68/**
69 * Own ID (short value).
70 */
71extern GNUNET_PEER_Id myid;
72
73/**
74 * Own ID (full value).
75 */
76extern struct GNUNET_PeerIdentity my_full_id;
77
78/**
79 * Handle to use DHT.
80 */
81static struct GNUNET_DHT_Handle *dht_handle;
82
83/**
84 * How often to PUT own ID in the DHT.
85 */
86static struct GNUNET_TIME_Relative id_announce_time;
87
88/**
89 * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put.
90 */
91static unsigned long long dht_replication_level;
92
93/**
94 * Task to periodically announce itself in the network.
95 */
96static GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
97
98/**
99 * GET requests to stop on shutdown.
100 */
101static 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 */
116static struct CadetPeerPath *
117path_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 */
213static void
214dht_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 */
250static void
251announce_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 */
311int
312stop_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 */
332void
333GMD_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 */
369void
370GMD_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
386struct GMD_search_handle *
387GMD_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
415void
416GMD_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
33extern "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
43struct 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 */
53typedef 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 */
65void
66GMD_init (const struct GNUNET_CONFIGURATION_Handle *c);
67
68/**
69 * Shut down the DHT subsystem.
70 */
71void
72GMD_shutdown (void);
73
74
75struct GMD_search_handle *
76GMD_search (const struct GNUNET_PeerIdentity *peer_id,
77 GMD_search_callback callback, void *cls);
78
79
80void
81GMD_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 */
49extern struct GNUNET_STATISTICS_Handle *stats;
50
51/**
52 * Local peer own ID (memory efficient handle).
53 */
54extern GNUNET_PEER_Id myid;
55
56/**
57 * Local peer own ID (full value).
58 */
59extern struct GNUNET_PeerIdentity my_full_id;
60
61
62/**
63 * Don't try to recover tunnels if shutting down.
64 */
65extern int shutting_down;
66
67
68/**
69 * Hello message of local peer.
70 */
71const struct GNUNET_HELLO_Message *mine;
72
73/**
74 * Handle to peerinfo service.
75 */
76static struct GNUNET_PEERINFO_Handle *peerinfo;
77
78/**
79 * Iterator context.
80 */
81struct 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 */
96static void
97got_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 */
131void
132GMH_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 */
144void
145GMH_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 */
165const struct GNUNET_HELLO_Message *
166GMH_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 */
180const struct GNUNET_HELLO_Message *
181GMH_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 */
192char *
193GMH_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
33extern "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 */
50void
51GMH_init (const struct GNUNET_CONFIGURATION_Handle *c);
52
53/**
54 * Shut down the hello subsystem.
55 */
56void
57GMH_shutdown ();
58
59/**
60 * Get own hello message.
61 *
62 * @return Own hello message.
63 */
64const struct GNUNET_HELLO_Message *
65GMH_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 */
48struct 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 */
105extern struct GNUNET_STATISTICS_Handle *stats;
106
107/**
108 * Handle to server lib.
109 */
110static struct GNUNET_SERVER_Handle *server_handle;
111
112/**
113 * DLL with all the clients, head.
114 */
115static struct CadetClient *clients_head;
116
117/**
118 * DLL with all the clients, tail.
119 */
120static struct CadetClient *clients_tail;
121
122/**
123 * Next ID to assign to a client.
124 */
125unsigned int next_client_id;
126
127/**
128 * All ports clients of this peer have opened.
129 */
130static struct GNUNET_CONTAINER_MultiHashMap32 *ports;
131
132/**
133 * Notification context, to send messages to local clients.
134 */
135static 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 */
151static int
152client_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 */
182static void
183handle_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 */
209static int
210channel_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 */
232static void
233handle_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 */
292static void
293handle_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 */
359static void
360handle_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 */
405static void
406handle_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 */
463static void
464handle_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 */
532static void
533handle_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 */
593static int
594get_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 */
624static void
625handle_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 */
663static int
664get_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 */
696static void
697handle_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
726static void
727iter_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
736static void
737iter_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 */
755void
756handle_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 */
836static 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 */
865void
866GML_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 */
878void
879GML_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 */
897void
898GML_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 */
916struct CadetChannel *
917GML_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 */
956void
957GML_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 */
979void
980GML_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 */
1004CADET_ChannelNumber
1005GML_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 */
1028struct CadetClient *
1029GML_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 */
1041struct CadetClient *
1042GML_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 */
1055void
1056GML_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 */
1090void
1091GML_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 */
1120void
1121GML_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 */
1144void
1145GML_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 */
1169void
1170GML_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 */
1199void
1200GML_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 (&copy[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 &copy->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 */
1235const char *
1236GML_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
33extern "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 */
46struct 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 */
59void
60GML_init (struct GNUNET_SERVER_Handle *handle);
61
62/**
63 * Install server (service) handlers and start listening to clients.
64 */
65void
66GML_start (void);
67
68/**
69 * Shutdown server.
70 */
71void
72GML_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 */
82struct CadetChannel *
83GML_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 */
92void
93GML_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 */
104void
105GML_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 */
116CADET_ChannelNumber
117GML_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 */
126struct CadetClient *
127GML_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 */
136struct CadetClient *
137GML_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 */
146void
147GML_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 */
159void
160GML_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 */
171void
172GML_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 */
182void
183GML_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 */
191void
192GML_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 */
201void
202GML_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 */
213const char *
214GML_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 */
46struct 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 */
117struct 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 */
188extern struct GNUNET_STATISTICS_Handle *stats;
189
190/**
191 * Local peer own ID (full value).
192 */
193extern struct GNUNET_PeerIdentity my_full_id;
194
195/**
196 * Local peer own ID (short)
197 */
198extern GNUNET_PEER_Id myid;
199
200/**
201 * Peers known, indexed by PeerIdentity (CadetPeer).
202 */
203static struct GNUNET_CONTAINER_MultiPeerMap *peers;
204
205/**
206 * How many peers do we want to remember?
207 */
208static unsigned long long max_peers;
209
210/**
211 * Percentage of messages that will be dropped (for test purposes only).
212 */
213static unsigned long long drop_percent;
214
215/**
216 * Handle to communicate with core.
217 */
218static struct GNUNET_CORE_Handle *core_handle;
219
220/**
221 * Handle to try to start new connections.
222 */
223static struct GNUNET_TRANSPORT_Handle *transport_handle;
224
225
226/******************************************************************************/
227/***************************** DEBUG *********************************/
228/******************************************************************************/
229
230static void
231queue_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 */
263static int
264notify_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 */
285static struct CadetPeerPath *
286pop_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 */
312static void
313core_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 */
357static void
358core_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, &notify_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 */
395static 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 */
419static void
420core_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 */
460static size_t
461send_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 */
488static size_t
489send_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 */
537static size_t
538send_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 */
569static enum GNUNET_CORE_Priority
570get_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 */
610static int
611shutdown_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 */
631static int
632peer_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 */
674static int
675peer_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 */
698static int
699peer_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 */
724static int
725peer_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 */
748static void
749peer_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 */
772static struct CadetPeerPath *
773peer_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 */
809static int
810queue_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 */
842static struct CadetPeerQueue *
843peer_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 */
866static void
867search_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 */
900static size_t
901queue_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 */
1062void
1063GMP_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 */
1139struct CadetPeerQueue *
1140GMP_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 */
1235void
1236GMP_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 */
1289static struct CadetPeerQueue *
1290connection_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 */
1318struct GNUNET_MessageHeader *
1319GMP_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
1357void
1358GMP_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 */
1393void
1394GMP_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 */
1462void
1463GMP_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 */
1488struct CadetPeer *
1489GMP_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 */
1519struct CadetPeer *
1520GMP_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 */
1532static void
1533try_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 */
1552void
1553GMP_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 */
1643int
1644GMP_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 */
1670void
1671GMP_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 */
1691int
1692GMP_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 */
1735struct CadetPeerPath *
1736GMP_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 */
1841struct CadetPeerPath *
1842GMP_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 */
1859void
1860GMP_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 */
1885void
1886GMP_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 */
1917int
1918GMP_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 */
1946void
1947GMP_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 */
1965void
1966GMP_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 */
1985const struct GNUNET_PeerIdentity *
1986GMP_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 */
1999GNUNET_PEER_Id
2000GMP_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 */
2012void
2013GMP_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 */
2030struct CadetTunnel3 *
2031GMP_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 */
2043void
2044GMP_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 */
2078struct GNUNET_HELLO_Message *
2079GMP_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 */
2105void
2106GMP_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 */
2131void
2132GMP_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 */
2180unsigned int
2181GMP_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 */
2199void
2200GMP_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 */
2213const char *
2214GMP_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
33extern "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 */
46struct CadetPeer;
47
48/**
49 * Struct containing info about a queued transmission to this peer
50 */
51struct 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 */
67typedef 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 */
81void
82GMP_init (const struct GNUNET_CONFIGURATION_Handle *c);
83
84/**
85 * Shut down the peer subsystem.
86 */
87void
88GMP_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 */
99struct CadetPeer *
100GMP_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 */
111struct CadetPeer *
112GMP_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 */
121void
122GMP_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 */
133void
134GMP_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 */
153struct CadetPeerQueue *
154GMP_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 */
166void
167GMP_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 */
177struct GNUNET_MessageHeader *
178GMP_connection_pop (struct CadetPeer *peer, struct CadetConnection *c);
179
180void
181GMP_queue_unlock (struct CadetPeer *peer, struct CadetConnection *c);
182
183/**
184 * Set tunnel.
185 *
186 * @param peer Peer.
187 * @param t Tunnel.
188 */
189void
190GMP_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 */
199int
200GMP_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 */
209void
210GMP_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 */
224int
225GMP_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 */
239struct CadetPeerPath *
240GMP_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 */
256struct CadetPeerPath *
257GMP_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 */
267void
268GMP_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 */
276void
277GMP_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 */
287int
288GMP_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 */
296void
297GMP_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 */
305void
306GMP_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 */
315const struct GNUNET_PeerIdentity *
316GMP_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 */
325GNUNET_PEER_Id
326GMP_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 */
335struct CadetTunnel3 *
336GMP_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 */
344void
345GMP_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 */
354struct GNUNET_HELLO_Message *
355GMP_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 */
363void
364GMP_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 */
374void
375GMP_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 */
386unsigned int
387GMP_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 */
395void
396GMP_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 */
405const char *
406GMP_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
45struct CadetTChannel
46{
47 struct CadetTChannel *next;
48 struct CadetTChannel *prev;
49 struct CadetChannel *ch;
50};
51
52
53/**
54 * Connection list and metadata.
55 */
56struct 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 */
87struct 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 */
104struct 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 */
179struct 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 */
207struct 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 */
238extern struct GNUNET_STATISTICS_Handle *stats;
239
240/**
241 * Local peer own ID (memory efficient handle).
242 */
243extern GNUNET_PEER_Id myid;
244
245/**
246 * Local peer own ID (full value).
247 */
248extern struct GNUNET_PeerIdentity my_full_id;
249
250
251/**
252 * Don't try to recover tunnels if shutting down.
253 */
254extern 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 */
261static struct GNUNET_CONTAINER_MultiPeerMap *tunnels;
262
263/**
264 * Default TTL for payload packets.
265 */
266static unsigned long long default_ttl;
267
268/**
269 * Own private key.
270 */
271const static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
272
273/**
274 * Own ephemeral private key.
275 */
276static struct GNUNET_CRYPTO_EcdhePrivateKey *my_ephemeral_key;
277
278/**
279 * Cached message used to perform a key exchange.
280 */
281static struct GNUNET_CADET_KX_Ephemeral kx_msg;
282
283/**
284 * Task to generate a new ephemeral key.
285 */
286static GNUNET_SCHEDULER_TaskIdentifier rekey_task;
287
288/**
289 * Rekey period.
290 */
291static 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 */
304static const char *
305cstate2s (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 */
335static const char *
336estate2s (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 */
368static int
369is_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 */
385size_t
386ephemeral_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 */
401size_t
402ping_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 */
415static unsigned int
416get_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 */
434static int
435get_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 */
453static unsigned int
454get_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 */
472static unsigned int
473get_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 */
492int
493check_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 */
531static int
532t_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 */
558static int
559t_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 */
602void
603derive_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 */
624void
625derive_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 */
647static struct CadetConnection *
648tunnel_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 */
690static void
691tun_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 */
714static void
715unqueue_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 */
728static struct CadetTunnelDelayed *
729queue_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 */
761static void
762t_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 */
797static struct CadetTunnel3Queue *
798send_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 */
911static void
912send_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 */
961static void
962send_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 */
1033static void
1034send_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 */
1047static void
1048send_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 */
1075static void
1076send_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 */
1099static void
1100rekey_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 */
1152static int
1153rekey_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 */
1182static void
1183rekey (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 */
1224static int
1225destroy_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 */
1244static void
1245send_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 */
1270static void
1271handle_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 */
1316static void
1317handle_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 */
1353static void
1354handle_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 */
1388static void
1389handle_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 */
1428static void
1429handle_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 */
1470static void
1471handle_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 */
1504static void
1505handle_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 */
1536static void
1537handle_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 */
1574static void
1575handle_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 */
1615static void
1616handle_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 */
1683void
1684GMT_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 */
1722void
1723GMT_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 */
1757void
1758GMT_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 */
1792void
1793GMT_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 */
1810struct CadetTunnel3 *
1811GMT_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 */
1837void
1838GMT_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 */
1876void
1877GMT_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 */
1908static void
1909trim_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 */
1951void
1952GMT_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 */
1980void
1981GMT_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 */
1993void
1994GMT_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 */
2043void
2044GMT_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 */
2079void
2080GMT_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 */
2106struct CadetChannel *
2107GMT_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 */
2134static void
2135delayed_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 */
2166void
2167GMT_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 */
2200void
2201GMT_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 */
2222void
2223GMT_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 */
2285struct CadetConnection *
2286GMT_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 */
2334unsigned int
2335GMT_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 */
2357unsigned int
2358GMT_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 */
2378enum CadetTunnel3CState
2379GMT_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 */
2397enum CadetTunnel3EState
2398GMT_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 */
2415unsigned int
2416GMT_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 */
2446unsigned int
2447GMT_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 */
2473const struct GNUNET_PeerIdentity *
2474GMT_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 */
2487CADET_ChannelNumber
2488GMT_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 */
2524void
2525GMT_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 */
2575void
2576GMT_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 */
2642void
2643GMT_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 */
2678struct CadetTunnel3Queue *
2679GMT_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 */
2694int
2695GMT_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 */
2709int
2710GMT_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 */
2730unsigned int
2731GMT_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 */
2775const char *
2776GMT_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 */
2795void
2796GMT_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 */
2837void
2838GMT_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 */
2849unsigned int
2850GMT_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 */
2863void
2864GMT_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 */
2880void
2881GMT_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
33extern "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 */
46enum 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 */
78enum 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 */
106struct 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 */
116struct 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 */
126typedef void (*GMT_sent) (void *cls,
127 struct CadetTunnel3 *t,
128 struct CadetTunnel3Queue *q,
129 uint16_t type, size_t size);
130
131typedef void (*GMT_conn_iter) (void *cls, struct CadetConnection *c);
132typedef 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 */
145void
146GMT_init (const struct GNUNET_CONFIGURATION_Handle *c,
147 const struct GNUNET_CRYPTO_EddsaPrivateKey *key);
148
149/**
150 * Shut down the tunnel subsystem.
151 */
152void
153GMT_shutdown (void);
154
155/**
156 * Create a tunnel.
157 *
158 * @param destination Peer this tunnel is towards.
159 */
160struct CadetTunnel3 *
161GMT_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 */
170void
171GMT_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 */
178void
179GMT_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 */
192void
193GMT_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 */
202void
203GMT_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 */
212void
213GMT_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 */
221void
222GMT_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 */
230void
231GMT_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 */
239void
240GMT_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 */
248void
249GMT_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 */
257void
258GMT_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 */
268struct CadetChannel *
269GMT_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 */
279void
280GMT_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 */
289void
290GMT_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 */
303struct CadetConnection *
304GMT_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 */
313unsigned int
314GMT_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 */
323unsigned int
324GMT_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 */
333enum CadetTunnel3CState
334GMT_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 */
343enum CadetTunnel3EState
344GMT_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 */
353unsigned int
354GMT_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 */
363unsigned int
364GMT_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 */
373const struct GNUNET_PeerIdentity *
374GMT_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 */
383CADET_ChannelNumber
384GMT_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 */
391void
392GMT_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 */
401void
402GMT_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 */
413void
414GMT_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 */
429struct CadetTunnel3Queue *
430GMT_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 */
441int
442GMT_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 */
452int
453GMT_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 */
463unsigned int
464GMT_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 */
474const char *
475GMT_2s (const struct CadetTunnel3 *t);
476
477/**
478 * Log all possible info about the tunnel state.
479 *
480 * @param t Tunnel to debug.
481 */
482void
483GMT_debug (const struct CadetTunnel3 *t);
484
485/**
486 * Iterate all tunnels.
487 *
488 * @param iter Iterator.
489 * @param cls Closure for @c iter.
490 */
491void
492GMT_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 */
499unsigned int
500GMT_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 */
509void
510GMT_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 */
519void
520GMT_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
3while true; do
4 date;
5 taskset 1 make check || break;
6 grep -B 10 Assert *log && break
7 ls core* &> /dev/null && break
8done
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]
2AUTOSTART = @AUTOSTART@
3@JAVAPORT@PORT = 2096
4HOSTNAME = localhost
5BINARY = gnunet-service-mesh
6ACCEPT_FROM = 127.0.0.1;
7ACCEPT_FROM6 = ::1;
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-mesh.sock
9UNIX_MATCH_UID = YES
10UNIX_MATCH_GID = YES
11REFRESH_CONNECTION_TIME = 5 min
12ID_ANNOUNCE_TIME = 1 h
13APP_ANNOUNCE_TIME = 1 h
14CONNECT_TIMEOUT = 30 s
15DEFAULT_TTL = 64
16DHT_REPLICATION_LEVEL = 3
17MAX_TUNNELS = 1000
18# MAX_TUNNELS deprecated
19MAX_CONNECTIONS = 1000
20MAX_MSGS_QUEUE = 10000
21MAX_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]
4OVERLAY_TOPOLOGY = RANDOM
5OVERLAY_RANDOM_LINKS = %LINKS%
6MAX_PARALLEL_SERVICE_CONNECTIONS=4000
7SETUP_TIMEOUT = 60 m
8
9[transport]
10#MANIPULATE_DELAY_IN = 50 ms
11MANIPULATE_DELAY_OUT = 10 ms
12
13[mesh]
14REFRESH_CONNECTION_TIME = 1 h
15DISABLE_TRY_CONNECT = YES
16ID_ANNOUNCE_TIME = 240 s
17
18[dht]
19FORCE_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
3if [ "$#" -lt "3" ]; then
4 echo "usage: $0 ROUND_TIME PEERS PINGING_PEERS";
5 echo "example: $0 30s 16 1";
6 exit 1;
7fi
8
9ROUNDTIME=$1
10PEERS=$2
11PINGS=$3
12
13if [ $PEERS -eq 1 ]; then
14 echo "cannot run 1 peer";
15 exit 1;
16fi
17
18LINKS=`echo "l($PEERS)/l(2) * $PEERS" | bc -l`
19LINKS=`printf "%.0f" $LINKS`
20NSE=`echo "l($PEERS)/l(2)" | bc -l`
21echo "using $PEERS peers, $LINKS links";
22
23sed -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 @@
116
21:2
31:9
42:3
53:4
63:11
74:5
85:6
95:13
106:7
117:8
127:15
138:9
149:10
1510:11
1611:12
1712:13
1813:14
1914:15
2015:16
2116: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 */
62static int test;
63
64/**
65 * String with test name
66 */
67char *test_name;
68
69/**
70 * Flag to send traffic leaf->root in speed tests to test BCK_ACK logic.
71 */
72static int test_backwards = GNUNET_NO;
73
74/**
75 * How many events have happened
76 */
77static int ok;
78
79/**
80 * Number of events expected to conclude the test successfully.
81 */
82int ok_goal;
83
84/**
85 * Size of each test packet
86 */
87size_t size_payload = sizeof (struct GNUNET_MessageHeader) + sizeof (uint32_t);
88
89/**
90 * Operation to get peer ids.
91 */
92struct GNUNET_TESTBED_Operation *t_op[2];
93
94/**
95 * Peer ids.
96 */
97struct GNUNET_PeerIdentity *p_id[2];
98
99/**
100 * Peer ids counter.
101 */
102unsigned int p_ids;
103
104/**
105 * Is the setup initialized?
106 */
107static int initialized;
108
109/**
110 * Number of payload packes sent
111 */
112static int data_sent;
113
114/**
115 * Number of payload packets received
116 */
117static int data_received;
118
119/**
120 * Number of payload packed explicitly (app level) acknowledged
121 */
122static int data_ack;
123
124/**
125 * Total number of currently running peers.
126 */
127static unsigned long long peers_running;
128
129/**
130 * Test context (to shut down).
131 */
132struct GNUNET_CADET_TEST_Context *test_ctx;
133
134/**
135 * Task called to disconnect peers.
136 */
137static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
138
139/**
140 * Task To perform tests
141 */
142static GNUNET_SCHEDULER_TaskIdentifier test_task;
143
144/**
145 * Task called to shutdown test.
146 */
147static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
148
149/**
150 * Cadet handle for the root peer
151 */
152static struct GNUNET_CADET_Handle *h1;
153
154/**
155 * Cadet handle for the first leaf peer
156 */
157static struct GNUNET_CADET_Handle *h2;
158
159/**
160 * Channel handle for the root peer
161 */
162static struct GNUNET_CADET_Channel *ch;
163
164/**
165 * Channel handle for the dest peer
166 */
167static struct GNUNET_CADET_Channel *incoming_ch;
168
169/**
170 * Time we started the data transmission (after channel has been established
171 * and initilized).
172 */
173static struct GNUNET_TIME_Absolute start_time;
174
175/**
176 * Peers handle.
177 */
178static struct GNUNET_TESTBED_Peer **testbed_peers;
179
180/**
181 * Statistics operation handle.
182 */
183static struct GNUNET_TESTBED_Operation *stats_op;
184
185/**
186 * Keepalives sent.
187 */
188static unsigned int ka_sent;
189
190/**
191 * Keepalives received.
192 */
193static unsigned int ka_received;
194
195
196/**
197 * Show the results of the test (banwidth acheived) and log them to GAUGER
198 */
199static void
200show_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 */
227static void
228shutdown_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 */
241static void
242disconnect_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 */
279static void
280abort_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 */
299static size_t
300tmt_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 */
309static void
310data_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 */
361size_t
362tmt_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 */
415int
416data_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 */
542static void
543stats_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 */
571static int
572stats_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 */
599static void
600check_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 */
617static 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 */
635static void *
636incoming_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 */
681static void
682channel_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 */
729static void
730do_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 */
777static void
778pi_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 */
812static void
813tmain (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 */
844int
845main (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]
2AUTOSTART = NO
3PORT = 12113
4ACCEPT_FROM = 127.0.0.1;
5HOSTNAME = localhost
6OVERLAY_TOPOLOGY = LINE
7#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args
8
9[fs]
10AUTOSTART = NO
11
12[resolver]
13AUTOSTART = 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
19AUTOSTART = NO
20ACCEPT_FROM = 127.0.0.1;
21REFRESH_CONNECTION_TIME = 2 s
22ID_ANNOUNCE_TIME = 5 s
23CONNECT_TIMEOUT = 30 s
24DEFAULT_TTL = 16
25DHT_REPLICATION_LEVEL = 10
26MAX_TUNNELS = 10
27MAX_CONNECTIONS = 10
28MAX_MSGS_QUEUE = 20
29DISABLE_TRY_CONNECT = YES
30
31[dht]
32AUTOSTART = NO
33DISABLE_TRY_CONNECT = YES
34FORCE_NSE = 3
35
36[dhtcache]
37QUOTA = 1 MB
38DATABASE = heap
39
40[transport]
41PLUGINS = udp
42ACCEPT_FROM6 = ::1;
43ACCEPT_FROM = 127.0.0.1;
44NEIGHBOUR_LIMIT = 50
45PORT = 12365
46#MANIPULATE_DELAY_IN = 10 ms
47#MANIPULATE_DELAY_OUT = 10 ms
48
49
50[ats]
51WAN_QUOTA_OUT = 3932160
52WAN_QUOTA_IN = 3932160
53
54[core]
55PORT = 12092
56AUTOSTART = YES
57USE_EPHEMERAL_KEYS = NO
58
59[arm]
60DEFAULTSERVICES = core transport dht mesh statistics
61PORT = 12366
62
63[transport-udp]
64TIMEOUT = 300 s
65PORT = 12368
66
67[gnunetd]
68HOSTKEY = $GNUNET_TEST_HOME/.hostkey
69
70[PATHS]
71GNUNET_TEST_HOME = /tmp/test-mesh/
72
73[dns]
74AUTOSTART = NO
75
76[nse]
77AUTOSTART = NO
78
79[vpn]
80AUTOSTART = NO
81
82[nat]
83RETURN_LOCAL_ADDRESSES = YES
84DISABLEV6 = YES
85USE_LOCALADDR = YES
86
87[gns-helper-service-w32]
88AUTOSTART = NO
89
90[consensus]
91AUTOSTART = NO
92
93[gns]
94AUTOSTART = NO
95
96[statistics]
97AUTOSTART = NO
98
99[peerinfo]
100NO_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]
4DROP_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
33struct GNUNET_TESTING_Peer *me;
34
35static struct GNUNET_CADET_Handle *cadet_peer_1;
36
37static struct GNUNET_CADET_Handle *cadet_peer_2;
38
39static struct GNUNET_CADET_Channel *ch;
40
41static int result = GNUNET_OK;
42
43static int got_data = GNUNET_NO;
44
45static GNUNET_SCHEDULER_TaskIdentifier abort_task;
46
47static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
48
49static 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 */
58static void
59do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
60
61
62/**
63 * Shutdown nicely
64 */
65static void
66do_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 */
93static void
94do_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 */
119static int
120data_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 */
148static void *
149inbound_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 */
177static void
178channel_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 */
204static 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 */
213static 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 */
228static size_t
229do_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 */
252static void
253do_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 */
278static void
279run (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 */
323int
324main (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
36struct GNUNET_TESTING_Peer *me;
37
38static struct GNUNET_CADET_Handle *cadet;
39
40static struct GNUNET_CADET_Channel *ch1;
41
42static struct GNUNET_CADET_Channel *ch2;
43
44static int result;
45
46static GNUNET_SCHEDULER_TaskIdentifier abort_task;
47
48static GNUNET_SCHEDULER_TaskIdentifier shutdown_task;
49
50static unsigned int repetition;
51
52
53/* forward declaration */
54static size_t
55do_send (void *cls, size_t size, void *buf);
56
57
58/**
59 * Shutdown nicely
60 */
61static void
62do_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 */
90static void
91do_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
105static void
106finish (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 */
126static int
127data_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 */
169static void *
170inbound_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 */
191static void
192channel_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 */
213static 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 */
228static size_t
229do_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 */
252static void
253do_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 */
278static void
279run (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 */
314int
315main (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