diff options
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | pkgconfig/Makefile.am | 1 | ||||
-rw-r--r-- | pkgconfig/gnunetdv.pc.in | 12 | ||||
-rw-r--r-- | src/ats/Makefile.am | 2 | ||||
-rw-r--r-- | src/dv/.gitignore | 2 | ||||
-rw-r--r-- | src/dv/Makefile.am | 100 | ||||
-rw-r--r-- | src/dv/dv.conf.in | 15 | ||||
-rw-r--r-- | src/dv/dv.h | 172 | ||||
-rw-r--r-- | src/dv/dv_api.c | 467 | ||||
-rw-r--r-- | src/dv/gnunet-dv.c | 185 | ||||
-rw-r--r-- | src/dv/gnunet-service-dv.c | 2146 | ||||
-rw-r--r-- | src/dv/plugin_transport_dv.c | 910 | ||||
-rw-r--r-- | src/dv/template_dv.conf | 33 | ||||
-rw-r--r-- | src/dv/test_transport_blacklist.c | 69 | ||||
-rw-r--r-- | src/dv/test_transport_blacklist_data.conf | 5 | ||||
-rw-r--r-- | src/dv/test_transport_dv.c | 131 | ||||
-rw-r--r-- | src/dv/test_transport_dv_data.conf | 19 | ||||
-rw-r--r-- | src/gns/test_gns_nick_shorten.conf | 24 | ||||
-rw-r--r-- | src/peerstore/Makefile.am | 4 | ||||
-rw-r--r-- | src/testing/Makefile.am | 3 |
20 files changed, 7 insertions, 4294 deletions
diff --git a/configure.ac b/configure.ac index 14360284a..f53d65006 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -1833,7 +1833,6 @@ pkgconfig/gnunetdatacache.pc | |||
1833 | pkgconfig/gnunetdatastore.pc | 1833 | pkgconfig/gnunetdatastore.pc |
1834 | pkgconfig/gnunetdht.pc | 1834 | pkgconfig/gnunetdht.pc |
1835 | pkgconfig/gnunetdns.pc | 1835 | pkgconfig/gnunetdns.pc |
1836 | pkgconfig/gnunetdv.pc | ||
1837 | pkgconfig/gnunetenv.pc | 1836 | pkgconfig/gnunetenv.pc |
1838 | pkgconfig/gnunetfragmentation.pc | 1837 | pkgconfig/gnunetfragmentation.pc |
1839 | pkgconfig/gnunetfs.pc | 1838 | pkgconfig/gnunetfs.pc |
diff --git a/pkgconfig/Makefile.am b/pkgconfig/Makefile.am index 755d680df..9ff682bd8 100644 --- a/pkgconfig/Makefile.am +++ b/pkgconfig/Makefile.am | |||
@@ -10,7 +10,6 @@ pcfiles = \ | |||
10 | gnunetdatastore.pc \ | 10 | gnunetdatastore.pc \ |
11 | gnunetdht.pc \ | 11 | gnunetdht.pc \ |
12 | gnunetdns.pc \ | 12 | gnunetdns.pc \ |
13 | gnunetdv.pc \ | ||
14 | gnunetenv.pc \ | 13 | gnunetenv.pc \ |
15 | gnunetfragmentation.pc \ | 14 | gnunetfragmentation.pc \ |
16 | gnunetfs.pc \ | 15 | gnunetfs.pc \ |
diff --git a/pkgconfig/gnunetdv.pc.in b/pkgconfig/gnunetdv.pc.in deleted file mode 100644 index bd5bd4278..000000000 --- a/pkgconfig/gnunetdv.pc.in +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | prefix=@prefix@ | ||
2 | exec_prefix=@exec_prefix@ | ||
3 | libdir=@libdir@ | ||
4 | includedir=@includedir@ | ||
5 | |||
6 | Name: GNUnet dv | ||
7 | Description: Library to access GNUnet DV service | ||
8 | URL: http://gnunet.org | ||
9 | Version: @VERSION@ | ||
10 | Requires: | ||
11 | Libs: -L${libdir} -lgnunetdv | ||
12 | Cflags: -I${includedir} | ||
diff --git a/src/ats/Makefile.am b/src/ats/Makefile.am index 2a62d71bd..1200aac09 100644 --- a/src/ats/Makefile.am +++ b/src/ats/Makefile.am | |||
@@ -214,6 +214,8 @@ EXTRA_DIST = \ | |||
214 | ats.h ats2.h \ | 214 | ats.h ats2.h \ |
215 | plugin_ats2_common.c \ | 215 | plugin_ats2_common.c \ |
216 | test_delay \ | 216 | test_delay \ |
217 | test_ats2_lib.conf \ | ||
218 | test_ats_api.conf \ | ||
217 | test_ats_api_mlp.conf \ | 219 | test_ats_api_mlp.conf \ |
218 | test_ats_api_ril.conf \ | 220 | test_ats_api_ril.conf \ |
219 | test_ats_api_proportional.conf | 221 | test_ats_api_proportional.conf |
diff --git a/src/dv/.gitignore b/src/dv/.gitignore deleted file mode 100644 index b3068b1c4..000000000 --- a/src/dv/.gitignore +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | gnunet-service-dv | ||
2 | gnunet-dv | ||
diff --git a/src/dv/Makefile.am b/src/dv/Makefile.am deleted file mode 100644 index c44321151..000000000 --- a/src/dv/Makefile.am +++ /dev/null | |||
@@ -1,100 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | endif | ||
7 | |||
8 | if USE_COVERAGE | ||
9 | AM_CFLAGS = --coverage -O0 | ||
10 | XLIB = -lgcov | ||
11 | endif | ||
12 | |||
13 | plugindir = $(libdir)/gnunet | ||
14 | |||
15 | libexecdir= $(pkglibdir)/libexec/ | ||
16 | |||
17 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
18 | |||
19 | pkgcfg_DATA = \ | ||
20 | dv.conf | ||
21 | |||
22 | lib_LTLIBRARIES = libgnunetdv.la | ||
23 | |||
24 | plugin_LTLIBRARIES = libgnunet_plugin_transport_dv.la | ||
25 | |||
26 | libgnunetdv_la_SOURCES = \ | ||
27 | dv_api.c dv.h | ||
28 | libgnunetdv_la_LIBADD = \ | ||
29 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
30 | $(GN_LIBINTL) $(XLIB) | ||
31 | libgnunetdv_la_LDFLAGS = \ | ||
32 | $(GN_LIB_LDFLAGS) $(WINFLAGS) \ | ||
33 | -version-info 0:0:0 | ||
34 | |||
35 | |||
36 | noinst_PROGRAMS = \ | ||
37 | gnunet-dv | ||
38 | |||
39 | libexec_PROGRAMS = \ | ||
40 | gnunet-service-dv | ||
41 | |||
42 | gnunet_service_dv_SOURCES = \ | ||
43 | gnunet-service-dv.c dv.h | ||
44 | gnunet_service_dv_LDADD = \ | ||
45 | $(top_builddir)/src/ats/libgnunetats.la \ | ||
46 | $(top_builddir)/src/set/libgnunetset.la \ | ||
47 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
48 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
49 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
50 | $(GN_LIBINTL) | ||
51 | |||
52 | gnunet_dv_SOURCES = \ | ||
53 | gnunet-dv.c dv.h | ||
54 | gnunet_dv_LDADD = \ | ||
55 | libgnunetdv.la \ | ||
56 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
57 | $(GN_LIBINTL) | ||
58 | |||
59 | libgnunet_plugin_transport_dv_la_SOURCES = \ | ||
60 | plugin_transport_dv.c | ||
61 | libgnunet_plugin_transport_dv_la_LIBADD = \ | ||
62 | libgnunetdv.la \ | ||
63 | $(top_builddir)/src/ats/libgnunetats.la \ | ||
64 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
65 | $(top_builddir)/src/util/libgnunetutil.la | ||
66 | libgnunet_plugin_transport_dv_la_LDFLAGS = \ | ||
67 | $(GN_PLUGIN_LDFLAGS) | ||
68 | |||
69 | if HAVE_TESTING | ||
70 | check_PROGRAMS = \ | ||
71 | test_transport_blacklist \ | ||
72 | test_transport_dv | ||
73 | endif | ||
74 | |||
75 | if ENABLE_TEST_RUN | ||
76 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
77 | TESTS = $(check_PROGRAMS) | ||
78 | endif | ||
79 | |||
80 | test_transport_dv_SOURCES = \ | ||
81 | test_transport_dv.c | ||
82 | test_transport_dv_LDADD = \ | ||
83 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
84 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
85 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
86 | $(top_builddir)/src/util/libgnunetutil.la | ||
87 | |||
88 | test_transport_blacklist_SOURCES = \ | ||
89 | test_transport_blacklist.c | ||
90 | test_transport_blacklist_LDADD = \ | ||
91 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
92 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
93 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
94 | $(top_builddir)/src/util/libgnunetutil.la | ||
95 | |||
96 | EXTRA_DIST = \ | ||
97 | test_transport_dv_data.conf \ | ||
98 | test_transport_blacklist_data.conf \ | ||
99 | template_dv.conf | ||
100 | |||
diff --git a/src/dv/dv.conf.in b/src/dv/dv.conf.in deleted file mode 100644 index 145c58be6..000000000 --- a/src/dv/dv.conf.in +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | [dv] | ||
2 | START_ON_DEMAND = @START_ON_DEMAND@ | ||
3 | ACCEPT_FROM6 = ::1; | ||
4 | ACCEPT_FROM = 127.0.0.1; | ||
5 | BINARY = gnunet-service-dv | ||
6 | HOSTNAME = localhost | ||
7 | @UNIXONLY@ PORT = 2571 | ||
8 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-dv.sock | ||
9 | UNIX_MATCH_UID = YES | ||
10 | UNIX_MATCH_GID = YES | ||
11 | # ACCEPT_FROM = | ||
12 | # ACCEPT_FROM6 = | ||
13 | # REJECT_FROM = | ||
14 | # REJECT_FROM6 = | ||
15 | # BINDTO = | ||
diff --git a/src/dv/dv.h b/src/dv/dv.h deleted file mode 100644 index b85d9c33f..000000000 --- a/src/dv/dv.h +++ /dev/null | |||
@@ -1,172 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @author Christian Grothoff | ||
23 | * @file dv/dv.h | ||
24 | * @brief IPC messages between DV service and DV plugin | ||
25 | */ | ||
26 | #ifndef DV_H | ||
27 | #define DV_H | ||
28 | |||
29 | #include "gnunet_common.h" | ||
30 | |||
31 | GNUNET_NETWORK_STRUCT_BEGIN | ||
32 | |||
33 | /** | ||
34 | * DV service tells plugin about a DV-connection being | ||
35 | * now available. | ||
36 | */ | ||
37 | struct GNUNET_DV_ConnectMessage | ||
38 | { | ||
39 | /** | ||
40 | * Type: #GNUNET_MESSAGE_TYPE_DV_CONNECT | ||
41 | */ | ||
42 | struct GNUNET_MessageHeader header; | ||
43 | |||
44 | /** | ||
45 | * The distance to the peer that we are now connected to | ||
46 | */ | ||
47 | uint32_t distance GNUNET_PACKED; | ||
48 | |||
49 | /** | ||
50 | * The other peer (at the given distance). | ||
51 | */ | ||
52 | struct GNUNET_PeerIdentity peer; | ||
53 | |||
54 | /** | ||
55 | * The network the peer is in | ||
56 | */ | ||
57 | uint32_t network GNUNET_PACKED; | ||
58 | |||
59 | }; | ||
60 | |||
61 | |||
62 | /** | ||
63 | * DV service tells plugin about a DV-connection being | ||
64 | * no longer available. | ||
65 | * | ||
66 | * Sender address is copied to the end of this struct, | ||
67 | * followed by the actual message received. | ||
68 | */ | ||
69 | struct GNUNET_DV_DisconnectMessage | ||
70 | { | ||
71 | /** | ||
72 | * Type: #GNUNET_MESSAGE_TYPE_DV_DISCONNECT | ||
73 | */ | ||
74 | struct GNUNET_MessageHeader header; | ||
75 | |||
76 | /** | ||
77 | * Always zero. | ||
78 | */ | ||
79 | uint32_t reserved GNUNET_PACKED; | ||
80 | |||
81 | /** | ||
82 | * The peer that is no longer available. | ||
83 | */ | ||
84 | struct GNUNET_PeerIdentity peer; | ||
85 | |||
86 | }; | ||
87 | |||
88 | |||
89 | /** | ||
90 | * DV Message, contains a message that was received via DV for this | ||
91 | * peer. Send from the DV service to the DV plugin. | ||
92 | * | ||
93 | * Sender address is copied to the end of this struct, | ||
94 | * followed by the actual message received. | ||
95 | */ | ||
96 | struct GNUNET_DV_ReceivedMessage | ||
97 | { | ||
98 | /** | ||
99 | * Type: #GNUNET_MESSAGE_TYPE_DV_RECV | ||
100 | */ | ||
101 | struct GNUNET_MessageHeader header; | ||
102 | |||
103 | /** | ||
104 | * The distance to the peer that we received the message from | ||
105 | */ | ||
106 | uint32_t distance GNUNET_PACKED; | ||
107 | |||
108 | /** | ||
109 | * The (actual) sender of the message | ||
110 | */ | ||
111 | struct GNUNET_PeerIdentity sender; | ||
112 | |||
113 | /* payload follows */ | ||
114 | }; | ||
115 | |||
116 | |||
117 | /** | ||
118 | * Message from plugin to DV service, requesting a | ||
119 | * message to be routed. | ||
120 | */ | ||
121 | struct GNUNET_DV_SendMessage | ||
122 | { | ||
123 | /** | ||
124 | * Type: #GNUNET_MESSAGE_TYPE_DV_SEND | ||
125 | */ | ||
126 | struct GNUNET_MessageHeader header; | ||
127 | |||
128 | /** | ||
129 | * Reserved for alignment. 0. | ||
130 | */ | ||
131 | uint32_t reserved GNUNET_PACKED; | ||
132 | |||
133 | /** | ||
134 | * The (actual) target of the message | ||
135 | */ | ||
136 | struct GNUNET_PeerIdentity target; | ||
137 | |||
138 | }; | ||
139 | |||
140 | |||
141 | /** | ||
142 | * Message from service to DV plugin, saying that our | ||
143 | * distance to another peer changed. | ||
144 | */ | ||
145 | struct GNUNET_DV_DistanceUpdateMessage | ||
146 | { | ||
147 | /** | ||
148 | * Type: #GNUNET_MESSAGE_TYPE_DV_DISTANCE_CHANGED. | ||
149 | */ | ||
150 | struct GNUNET_MessageHeader header; | ||
151 | |||
152 | /** | ||
153 | * What is the new distance? | ||
154 | */ | ||
155 | uint32_t distance GNUNET_PACKED; | ||
156 | |||
157 | /** | ||
158 | * The peer for which the distance changed. | ||
159 | */ | ||
160 | struct GNUNET_PeerIdentity peer; | ||
161 | |||
162 | /** | ||
163 | * The network the peer is in | ||
164 | */ | ||
165 | uint32_t network GNUNET_PACKED; | ||
166 | |||
167 | }; | ||
168 | |||
169 | |||
170 | GNUNET_NETWORK_STRUCT_END | ||
171 | |||
172 | #endif | ||
diff --git a/src/dv/dv_api.c b/src/dv/dv_api.c deleted file mode 100644 index dd46ce9f5..000000000 --- a/src/dv/dv_api.c +++ /dev/null | |||
@@ -1,467 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009--2013, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file dv/dv_api.c | ||
23 | * @brief library to access the DV service | ||
24 | * @author Christian Grothoff | ||
25 | * @author Nathan Evans | ||
26 | */ | ||
27 | #include "platform.h" | ||
28 | #include "gnunet_util_lib.h" | ||
29 | #include "gnunet_dv_service.h" | ||
30 | #include "gnunet_protocols.h" | ||
31 | #include "dv.h" | ||
32 | #include "gnunet_transport_plugin.h" | ||
33 | |||
34 | #define LOG(kind,...) GNUNET_log_from (kind, "dv-api",__VA_ARGS__) | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Information we track for each peer. | ||
39 | */ | ||
40 | struct ConnectedPeer | ||
41 | { | ||
42 | |||
43 | /** | ||
44 | * Identity of the peer. | ||
45 | */ | ||
46 | struct GNUNET_PeerIdentity pid; | ||
47 | |||
48 | }; | ||
49 | |||
50 | |||
51 | /** | ||
52 | * Handle to the DV service. | ||
53 | */ | ||
54 | struct GNUNET_DV_ServiceHandle | ||
55 | { | ||
56 | |||
57 | /** | ||
58 | * Connection to DV service. | ||
59 | */ | ||
60 | struct GNUNET_MQ_Handle *mq; | ||
61 | |||
62 | /** | ||
63 | * Our configuration. | ||
64 | */ | ||
65 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
66 | |||
67 | /** | ||
68 | * Closure for the callbacks. | ||
69 | */ | ||
70 | void *cls; | ||
71 | |||
72 | /** | ||
73 | * Function to call on connect events. | ||
74 | */ | ||
75 | GNUNET_DV_ConnectCallback connect_cb; | ||
76 | |||
77 | /** | ||
78 | * Function to call on distance change events. | ||
79 | */ | ||
80 | GNUNET_DV_DistanceChangedCallback distance_cb; | ||
81 | |||
82 | /** | ||
83 | * Function to call on disconnect events. | ||
84 | */ | ||
85 | GNUNET_DV_DisconnectCallback disconnect_cb; | ||
86 | |||
87 | /** | ||
88 | * Function to call on receiving messages events. | ||
89 | */ | ||
90 | GNUNET_DV_MessageReceivedCallback message_cb; | ||
91 | |||
92 | /** | ||
93 | * Information tracked per connected peer. Maps peer | ||
94 | * identities to `struct ConnectedPeer` entries. | ||
95 | */ | ||
96 | struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
97 | |||
98 | }; | ||
99 | |||
100 | |||
101 | /** | ||
102 | * Disconnect and then reconnect to the DV service. | ||
103 | * | ||
104 | * @param sh service handle | ||
105 | */ | ||
106 | static void | ||
107 | reconnect (struct GNUNET_DV_ServiceHandle *sh); | ||
108 | |||
109 | |||
110 | /** | ||
111 | * We got disconnected from the service and thus all of the | ||
112 | * connections need to be torn down. | ||
113 | * | ||
114 | * @param cls the `struct GNUNET_DV_ServiceHandle` | ||
115 | * @param key a peer identity | ||
116 | * @param value a `struct ConnectedPeer` to clean up | ||
117 | * @return #GNUNET_OK (continue to iterate) | ||
118 | */ | ||
119 | static int | ||
120 | cleanup_send_cb (void *cls, | ||
121 | const struct GNUNET_PeerIdentity *key, | ||
122 | void *value) | ||
123 | { | ||
124 | struct GNUNET_DV_ServiceHandle *sh = cls; | ||
125 | struct ConnectedPeer *peer = value; | ||
126 | |||
127 | GNUNET_assert (GNUNET_YES == | ||
128 | GNUNET_CONTAINER_multipeermap_remove (sh->peers, | ||
129 | key, | ||
130 | peer)); | ||
131 | sh->disconnect_cb (sh->cls, | ||
132 | key); | ||
133 | GNUNET_free (peer); | ||
134 | return GNUNET_OK; | ||
135 | } | ||
136 | |||
137 | |||
138 | /** | ||
139 | * Handles a message sent from the DV service to us. | ||
140 | * Parse it out and give it to the plugin. | ||
141 | * | ||
142 | * @param cls the handle to the DV API | ||
143 | * @param cm the message that was received | ||
144 | */ | ||
145 | static void | ||
146 | handle_connect (void *cls, | ||
147 | const struct GNUNET_DV_ConnectMessage *cm) | ||
148 | { | ||
149 | struct GNUNET_DV_ServiceHandle *sh = cls; | ||
150 | struct ConnectedPeer *peer; | ||
151 | |||
152 | peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, | ||
153 | &cm->peer); | ||
154 | if (NULL != peer) | ||
155 | { | ||
156 | GNUNET_break (0); | ||
157 | reconnect (sh); | ||
158 | return; | ||
159 | } | ||
160 | peer = GNUNET_new (struct ConnectedPeer); | ||
161 | peer->pid = cm->peer; | ||
162 | GNUNET_assert (GNUNET_OK == | ||
163 | GNUNET_CONTAINER_multipeermap_put (sh->peers, | ||
164 | &peer->pid, | ||
165 | peer, | ||
166 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
167 | sh->connect_cb (sh->cls, | ||
168 | &cm->peer, | ||
169 | ntohl (cm->distance), | ||
170 | (enum GNUNET_NetworkType) ntohl (cm->network)); | ||
171 | } | ||
172 | |||
173 | |||
174 | /** | ||
175 | * Handles a message sent from the DV service to us. | ||
176 | * Parse it out and give it to the plugin. | ||
177 | * | ||
178 | * @param cls the handle to the DV API | ||
179 | * @param dm the message that was received | ||
180 | */ | ||
181 | static void | ||
182 | handle_disconnect (void *cls, | ||
183 | const struct GNUNET_DV_DisconnectMessage *dm) | ||
184 | { | ||
185 | struct GNUNET_DV_ServiceHandle *sh = cls; | ||
186 | struct ConnectedPeer *peer; | ||
187 | |||
188 | peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, | ||
189 | &dm->peer); | ||
190 | if (NULL == peer) | ||
191 | { | ||
192 | GNUNET_break (0); | ||
193 | reconnect (sh); | ||
194 | return; | ||
195 | } | ||
196 | cleanup_send_cb (sh, | ||
197 | &dm->peer, | ||
198 | peer); | ||
199 | } | ||
200 | |||
201 | |||
202 | /** | ||
203 | * Handles a message sent from the DV service to us. | ||
204 | * Parse it out and give it to the plugin. | ||
205 | * | ||
206 | * @param cls the handle to the DV API | ||
207 | * @param msg the message that was received | ||
208 | */ | ||
209 | static void | ||
210 | handle_distance_update (void *cls, | ||
211 | const struct GNUNET_DV_DistanceUpdateMessage *dum) | ||
212 | { | ||
213 | struct GNUNET_DV_ServiceHandle *sh = cls; | ||
214 | struct ConnectedPeer *peer; | ||
215 | |||
216 | peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, | ||
217 | &dum->peer); | ||
218 | if (NULL == peer) | ||
219 | { | ||
220 | GNUNET_break (0); | ||
221 | reconnect (sh); | ||
222 | return; | ||
223 | } | ||
224 | sh->distance_cb (sh->cls, | ||
225 | &dum->peer, | ||
226 | ntohl (dum->distance), | ||
227 | (enum GNUNET_NetworkType) ntohl (dum->network)); | ||
228 | } | ||
229 | |||
230 | |||
231 | /** | ||
232 | * Handles a message sent from the DV service to us. | ||
233 | * Parse it out and give it to the plugin. | ||
234 | * | ||
235 | * @param cls the handle to the DV API | ||
236 | * @param rm the message that was received | ||
237 | */ | ||
238 | static int | ||
239 | check_received (void *cls, | ||
240 | const struct GNUNET_DV_ReceivedMessage *rm) | ||
241 | { | ||
242 | struct GNUNET_DV_ServiceHandle *sh = cls; | ||
243 | const struct GNUNET_MessageHeader *payload; | ||
244 | |||
245 | if (NULL == | ||
246 | GNUNET_CONTAINER_multipeermap_get (sh->peers, | ||
247 | &rm->sender)) | ||
248 | { | ||
249 | GNUNET_break (0); | ||
250 | return GNUNET_SYSERR; | ||
251 | } | ||
252 | if (ntohs (rm->header.size) - sizeof (struct GNUNET_DV_ReceivedMessage) < | ||
253 | sizeof (*payload)) | ||
254 | { | ||
255 | GNUNET_break (0); | ||
256 | return GNUNET_SYSERR; | ||
257 | } | ||
258 | payload = (const struct GNUNET_MessageHeader *) &rm[1]; | ||
259 | if (ntohs (rm->header.size) != | ||
260 | sizeof (struct GNUNET_DV_ReceivedMessage) + ntohs (payload->size)) | ||
261 | { | ||
262 | GNUNET_break (0); | ||
263 | return GNUNET_SYSERR; | ||
264 | } | ||
265 | return GNUNET_OK; | ||
266 | } | ||
267 | |||
268 | |||
269 | /** | ||
270 | * Handles a message sent from the DV service to us. | ||
271 | * Parse it out and give it to the plugin. | ||
272 | * | ||
273 | * @param cls the handle to the DV API | ||
274 | * @param rm the message that was received | ||
275 | */ | ||
276 | static void | ||
277 | handle_received (void *cls, | ||
278 | const struct GNUNET_DV_ReceivedMessage *rm) | ||
279 | { | ||
280 | struct GNUNET_DV_ServiceHandle *sh = cls; | ||
281 | const struct GNUNET_MessageHeader *payload; | ||
282 | |||
283 | payload = (const struct GNUNET_MessageHeader *) &rm[1]; | ||
284 | sh->message_cb (sh->cls, | ||
285 | &rm->sender, | ||
286 | ntohl (rm->distance), | ||
287 | payload); | ||
288 | } | ||
289 | |||
290 | |||
291 | /** | ||
292 | * Generic error handler, called with the appropriate error code and | ||
293 | * the same closure specified at the creation of the message queue. | ||
294 | * Not every message queue implementation supports an error handler. | ||
295 | * | ||
296 | * @param cls closure with the `struct GNUNET_DV_ServiceHandle *` | ||
297 | * @param error error code | ||
298 | */ | ||
299 | static void | ||
300 | mq_error_handler (void *cls, | ||
301 | enum GNUNET_MQ_Error error) | ||
302 | { | ||
303 | struct GNUNET_DV_ServiceHandle *sh = cls; | ||
304 | |||
305 | reconnect (sh); | ||
306 | } | ||
307 | |||
308 | |||
309 | /** | ||
310 | * Disconnect and then reconnect to the DV service. | ||
311 | * | ||
312 | * @param sh service handle | ||
313 | */ | ||
314 | static void | ||
315 | reconnect (struct GNUNET_DV_ServiceHandle *sh) | ||
316 | { | ||
317 | struct GNUNET_MQ_MessageHandler handlers[] = { | ||
318 | GNUNET_MQ_hd_fixed_size (connect, | ||
319 | GNUNET_MESSAGE_TYPE_DV_CONNECT, | ||
320 | struct GNUNET_DV_ConnectMessage, | ||
321 | sh), | ||
322 | GNUNET_MQ_hd_fixed_size (disconnect, | ||
323 | GNUNET_MESSAGE_TYPE_DV_DISCONNECT, | ||
324 | struct GNUNET_DV_DisconnectMessage, | ||
325 | sh), | ||
326 | GNUNET_MQ_hd_fixed_size (distance_update, | ||
327 | GNUNET_MESSAGE_TYPE_DV_DISTANCE_CHANGED, | ||
328 | struct GNUNET_DV_DistanceUpdateMessage, | ||
329 | sh), | ||
330 | GNUNET_MQ_hd_var_size (received, | ||
331 | GNUNET_MESSAGE_TYPE_DV_RECV, | ||
332 | struct GNUNET_DV_ReceivedMessage, | ||
333 | sh), | ||
334 | GNUNET_MQ_handler_end () | ||
335 | }; | ||
336 | struct GNUNET_MessageHeader *sm; | ||
337 | struct GNUNET_MQ_Envelope *env; | ||
338 | |||
339 | if (NULL != sh->mq) | ||
340 | { | ||
341 | GNUNET_MQ_destroy (sh->mq); | ||
342 | sh->mq = NULL; | ||
343 | } | ||
344 | GNUNET_CONTAINER_multipeermap_iterate (sh->peers, | ||
345 | &cleanup_send_cb, | ||
346 | sh); | ||
347 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
348 | "Connecting to DV service\n"); | ||
349 | sh->mq = GNUNET_CLIENT_connect (sh->cfg, | ||
350 | "dv", | ||
351 | handlers, | ||
352 | &mq_error_handler, | ||
353 | sh); | ||
354 | if (NULL == sh->mq) | ||
355 | { | ||
356 | GNUNET_break (0); | ||
357 | return; | ||
358 | } | ||
359 | env = GNUNET_MQ_msg (sm, | ||
360 | GNUNET_MESSAGE_TYPE_DV_START); | ||
361 | GNUNET_MQ_send (sh->mq, | ||
362 | env); | ||
363 | } | ||
364 | |||
365 | |||
366 | /** | ||
367 | * Connect to the DV service. | ||
368 | * | ||
369 | * @param cfg configuration | ||
370 | * @param cls closure for callbacks | ||
371 | * @param connect_cb function to call on connects | ||
372 | * @param distance_cb function to call if distances change | ||
373 | * @param disconnect_cb function to call on disconnects | ||
374 | * @param message_cb function to call if we receive messages | ||
375 | * @return handle to access the service | ||
376 | */ | ||
377 | struct GNUNET_DV_ServiceHandle * | ||
378 | GNUNET_DV_service_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
379 | void *cls, | ||
380 | GNUNET_DV_ConnectCallback connect_cb, | ||
381 | GNUNET_DV_DistanceChangedCallback distance_cb, | ||
382 | GNUNET_DV_DisconnectCallback disconnect_cb, | ||
383 | GNUNET_DV_MessageReceivedCallback message_cb) | ||
384 | { | ||
385 | struct GNUNET_DV_ServiceHandle *sh; | ||
386 | |||
387 | sh = GNUNET_new (struct GNUNET_DV_ServiceHandle); | ||
388 | sh->cfg = cfg; | ||
389 | sh->cls = cls; | ||
390 | sh->connect_cb = connect_cb; | ||
391 | sh->distance_cb = distance_cb; | ||
392 | sh->disconnect_cb = disconnect_cb; | ||
393 | sh->message_cb = message_cb; | ||
394 | sh->peers = GNUNET_CONTAINER_multipeermap_create (128, | ||
395 | GNUNET_YES); | ||
396 | reconnect (sh); | ||
397 | return sh; | ||
398 | } | ||
399 | |||
400 | |||
401 | /** | ||
402 | * Disconnect from DV service. | ||
403 | * | ||
404 | * @param sh service handle | ||
405 | */ | ||
406 | void | ||
407 | GNUNET_DV_service_disconnect (struct GNUNET_DV_ServiceHandle *sh) | ||
408 | { | ||
409 | if (NULL == sh) | ||
410 | return; | ||
411 | if (NULL != sh->mq) | ||
412 | { | ||
413 | GNUNET_MQ_destroy (sh->mq); | ||
414 | sh->mq = NULL; | ||
415 | } | ||
416 | GNUNET_CONTAINER_multipeermap_iterate (sh->peers, | ||
417 | &cleanup_send_cb, | ||
418 | sh); | ||
419 | GNUNET_CONTAINER_multipeermap_destroy (sh->peers); | ||
420 | GNUNET_free (sh); | ||
421 | } | ||
422 | |||
423 | |||
424 | /** | ||
425 | * Send a message via DV service. | ||
426 | * | ||
427 | * @param sh service handle | ||
428 | * @param target intended recpient | ||
429 | * @param msg message payload | ||
430 | */ | ||
431 | void | ||
432 | GNUNET_DV_send (struct GNUNET_DV_ServiceHandle *sh, | ||
433 | const struct GNUNET_PeerIdentity *target, | ||
434 | const struct GNUNET_MessageHeader *msg) | ||
435 | { | ||
436 | struct GNUNET_DV_SendMessage *sm; | ||
437 | struct ConnectedPeer *peer; | ||
438 | struct GNUNET_MQ_Envelope *env; | ||
439 | |||
440 | if (ntohs (msg->size) + sizeof (*sm) >= GNUNET_MAX_MESSAGE_SIZE) | ||
441 | { | ||
442 | GNUNET_break (0); | ||
443 | return; | ||
444 | } | ||
445 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
446 | "Asked to send %u bytes of type %u to %s\n", | ||
447 | (unsigned int) ntohs (msg->size), | ||
448 | (unsigned int) ntohs (msg->type), | ||
449 | GNUNET_i2s (target)); | ||
450 | peer = GNUNET_CONTAINER_multipeermap_get (sh->peers, | ||
451 | target); | ||
452 | if (NULL == peer) | ||
453 | { | ||
454 | GNUNET_break (0); | ||
455 | return; | ||
456 | } | ||
457 | GNUNET_assert (NULL != sh->mq); | ||
458 | env = GNUNET_MQ_msg_nested_mh (sm, | ||
459 | GNUNET_MESSAGE_TYPE_DV_SEND, | ||
460 | msg); | ||
461 | sm->target = *target; | ||
462 | GNUNET_MQ_send (sh->mq, | ||
463 | env); | ||
464 | } | ||
465 | |||
466 | |||
467 | /* end of dv_api.c */ | ||
diff --git a/src/dv/gnunet-dv.c b/src/dv/gnunet-dv.c deleted file mode 100644 index 90d8144e5..000000000 --- a/src/dv/gnunet-dv.c +++ /dev/null | |||
@@ -1,185 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file dv/gnunet-dv.c | ||
22 | * @brief DV monitoring command line tool | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "gnunet_dv_service.h" | ||
28 | |||
29 | /** | ||
30 | * Handle to DV service. | ||
31 | */ | ||
32 | static struct GNUNET_DV_ServiceHandle *sh; | ||
33 | |||
34 | /** | ||
35 | * Was verbose specified? | ||
36 | */ | ||
37 | static unsigned int verbose; | ||
38 | |||
39 | |||
40 | /** | ||
41 | * Function called if DV starts to be able to talk to a peer. | ||
42 | * | ||
43 | * @param cls closure | ||
44 | * @param peer newly connected peer | ||
45 | * @param distance distance to the peer | ||
46 | * @param network the network the next hop is located in | ||
47 | */ | ||
48 | static void | ||
49 | connect_cb (void *cls, | ||
50 | const struct GNUNET_PeerIdentity *peer, | ||
51 | uint32_t distance, | ||
52 | enum GNUNET_NetworkType network) | ||
53 | { | ||
54 | fprintf (stderr, "Connect: %s at %u\n", | ||
55 | GNUNET_i2s (peer), | ||
56 | (unsigned int) distance); | ||
57 | } | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Function called if DV distance to a peer is changed. | ||
62 | * | ||
63 | * @param cls closure | ||
64 | * @param peer connected peer | ||
65 | * @param distance new distance to the peer | ||
66 | * @param network network used on first hop to peer | ||
67 | */ | ||
68 | static void | ||
69 | change_cb (void *cls, | ||
70 | const struct GNUNET_PeerIdentity *peer, | ||
71 | uint32_t distance, | ||
72 | enum GNUNET_NetworkType network) | ||
73 | { | ||
74 | fprintf (stderr, "Change: %s at %u\n", | ||
75 | GNUNET_i2s (peer), | ||
76 | (unsigned int) distance); | ||
77 | } | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Function called if DV is no longer able to talk to a peer. | ||
82 | * | ||
83 | * @param cls closure | ||
84 | * @param peer peer that disconnected | ||
85 | */ | ||
86 | static void | ||
87 | disconnect_cb (void *cls, | ||
88 | const struct GNUNET_PeerIdentity *peer) | ||
89 | { | ||
90 | fprintf (stderr, "Disconnect: %s\n", | ||
91 | GNUNET_i2s (peer)); | ||
92 | } | ||
93 | |||
94 | |||
95 | /** | ||
96 | * Function called if DV receives a message for this peer. | ||
97 | * | ||
98 | * @param cls closure | ||
99 | * @param sender sender of the message | ||
100 | * @param distance how far did the message travel | ||
101 | * @param msg actual message payload | ||
102 | */ | ||
103 | static void | ||
104 | message_cb (void *cls, | ||
105 | const struct GNUNET_PeerIdentity *sender, | ||
106 | uint32_t distance, | ||
107 | const struct GNUNET_MessageHeader *msg) | ||
108 | { | ||
109 | if (verbose) | ||
110 | fprintf (stderr, "Message: %s at %u sends %u bytes of type %u\n", | ||
111 | GNUNET_i2s (sender), | ||
112 | (unsigned int) distance, | ||
113 | (unsigned int) ntohs (msg->size), | ||
114 | (unsigned int) ntohs (msg->type)); | ||
115 | } | ||
116 | |||
117 | |||
118 | /** | ||
119 | * Task run on shutdown. | ||
120 | * | ||
121 | * @param cls NULL | ||
122 | */ | ||
123 | static void | ||
124 | shutdown_task (void *cls) | ||
125 | { | ||
126 | GNUNET_DV_service_disconnect (sh); | ||
127 | sh = NULL; | ||
128 | } | ||
129 | |||
130 | |||
131 | /** | ||
132 | * Main function that will be run by the scheduler. | ||
133 | * | ||
134 | * @param cls closure | ||
135 | * @param args remaining command-line arguments | ||
136 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
137 | * @param cfg configuration | ||
138 | */ | ||
139 | static void | ||
140 | run (void *cls, char *const *args, const char *cfgfile, | ||
141 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
142 | { | ||
143 | sh = GNUNET_DV_service_connect (cfg, NULL, | ||
144 | &connect_cb, | ||
145 | &change_cb, | ||
146 | &disconnect_cb, | ||
147 | &message_cb); | ||
148 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
149 | } | ||
150 | |||
151 | |||
152 | /** | ||
153 | * The main function. | ||
154 | * | ||
155 | * @param argc number of arguments from the command line | ||
156 | * @param argv command line arguments | ||
157 | * @return 0 ok, 1 on error | ||
158 | */ | ||
159 | int | ||
160 | main (int argc, char *const *argv) | ||
161 | { | ||
162 | int res; | ||
163 | |||
164 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
165 | |||
166 | GNUNET_GETOPT_option_verbose (&verbose), | ||
167 | |||
168 | GNUNET_GETOPT_OPTION_END | ||
169 | }; | ||
170 | |||
171 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
172 | return 2; | ||
173 | |||
174 | res = GNUNET_PROGRAM_run (argc, argv, "gnunet-dv", | ||
175 | gettext_noop ("Print information about DV state"), | ||
176 | options, &run, | ||
177 | NULL); | ||
178 | GNUNET_free ((void *) argv); | ||
179 | |||
180 | if (GNUNET_OK != res) | ||
181 | return 1; | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | /* end of gnunet-dv.c */ | ||
diff --git a/src/dv/gnunet-service-dv.c b/src/dv/gnunet-service-dv.c deleted file mode 100644 index dd2ff9c12..000000000 --- a/src/dv/gnunet-service-dv.c +++ /dev/null | |||
@@ -1,2146 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013, 2016 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file dv/gnunet-service-dv.c | ||
23 | * @brief the distance vector service, primarily handles gossip of nearby | ||
24 | * peers and sending/receiving DV messages from core and decapsulating | ||
25 | * them | ||
26 | * | ||
27 | * @author Christian Grothoff | ||
28 | * @author Nathan Evans | ||
29 | */ | ||
30 | #include "platform.h" | ||
31 | #include "gnunet_util_lib.h" | ||
32 | #include "gnunet_protocols.h" | ||
33 | #include "gnunet_core_service.h" | ||
34 | #include "gnunet_hello_lib.h" | ||
35 | #include "gnunet_peerinfo_service.h" | ||
36 | #include "gnunet_statistics_service.h" | ||
37 | #include "gnunet_set_service.h" | ||
38 | #include "gnunet_ats_service.h" | ||
39 | #include "dv.h" | ||
40 | #include <gcrypt.h> | ||
41 | |||
42 | |||
43 | /** | ||
44 | * How often do we establish the consensu? | ||
45 | */ | ||
46 | #define GNUNET_DV_CONSENSUS_FREQUENCY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5) | ||
47 | |||
48 | /** | ||
49 | * Maximum number of messages we queue per peer. | ||
50 | */ | ||
51 | #define MAX_QUEUE_SIZE 16 | ||
52 | |||
53 | /** | ||
54 | * Maximum number of messages we queue towards the clients/plugin. | ||
55 | */ | ||
56 | #define MAX_QUEUE_SIZE_PLUGIN 1024 | ||
57 | |||
58 | /** | ||
59 | * The default fisheye depth, from how many hops away will | ||
60 | * we keep peers? | ||
61 | */ | ||
62 | #define DEFAULT_FISHEYE_DEPTH 3 | ||
63 | |||
64 | /** | ||
65 | * How many hops is a direct neighbor away? | ||
66 | */ | ||
67 | #define DIRECT_NEIGHBOR_COST 1 | ||
68 | |||
69 | |||
70 | GNUNET_NETWORK_STRUCT_BEGIN | ||
71 | |||
72 | /** | ||
73 | * Information about a peer DV can route to. These entries are what | ||
74 | * we use as the binary format to establish consensus to create our | ||
75 | * routing table and as the address format in the HELLOs. | ||
76 | */ | ||
77 | struct Target | ||
78 | { | ||
79 | |||
80 | /** | ||
81 | * Identity of the peer we can reach. | ||
82 | */ | ||
83 | struct GNUNET_PeerIdentity peer; | ||
84 | |||
85 | /** | ||
86 | * How many hops (1-3) is this peer away? in network byte order | ||
87 | */ | ||
88 | uint32_t distance GNUNET_PACKED; | ||
89 | |||
90 | }; | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Message exchanged between DV services (via core), requesting a | ||
95 | * message to be routed. | ||
96 | */ | ||
97 | struct RouteMessage | ||
98 | { | ||
99 | /** | ||
100 | * Type: #GNUNET_MESSAGE_TYPE_DV_ROUTE | ||
101 | */ | ||
102 | struct GNUNET_MessageHeader header; | ||
103 | |||
104 | /** | ||
105 | * Expected (remaining) distance. Must be always smaller than | ||
106 | * #DEFAULT_FISHEYE_DEPTH, should be zero at the target. Must | ||
107 | * be decremented by one at each hop. Peers must not forward | ||
108 | * these messages further once the counter has reached zero. | ||
109 | */ | ||
110 | uint32_t distance GNUNET_PACKED; | ||
111 | |||
112 | /** | ||
113 | * The (actual) target of the message (this peer, if distance is zero). | ||
114 | */ | ||
115 | struct GNUNET_PeerIdentity target; | ||
116 | |||
117 | /** | ||
118 | * The (actual) sender of the message. | ||
119 | */ | ||
120 | struct GNUNET_PeerIdentity sender; | ||
121 | |||
122 | }; | ||
123 | |||
124 | GNUNET_NETWORK_STRUCT_END | ||
125 | |||
126 | |||
127 | /** | ||
128 | * Information about a direct neighbor (core-level, excluding | ||
129 | * DV-links, only DV-enabled peers). | ||
130 | */ | ||
131 | struct DirectNeighbor | ||
132 | { | ||
133 | |||
134 | /** | ||
135 | * Identity of the peer. | ||
136 | */ | ||
137 | struct GNUNET_PeerIdentity peer; | ||
138 | |||
139 | /** | ||
140 | * Session ID we use whenever we create a set union with | ||
141 | * this neighbor; constructed from the XOR of our peer | ||
142 | * IDs and then salted with "DV-SALT" to avoid conflicts | ||
143 | * with other applications. | ||
144 | */ | ||
145 | struct GNUNET_HashCode real_session_id; | ||
146 | |||
147 | /** | ||
148 | * Transmit handle to core service. | ||
149 | */ | ||
150 | struct GNUNET_MQ_Handle *mq; | ||
151 | |||
152 | /** | ||
153 | * Routing table of the neighbor, NULL if not yet established. | ||
154 | * Keys are peer identities, values are 'struct Target' entries. | ||
155 | * Note that the distances in the targets are from the point-of-view | ||
156 | * of the peer, not from us! | ||
157 | */ | ||
158 | struct GNUNET_CONTAINER_MultiPeerMap *neighbor_table; | ||
159 | |||
160 | /** | ||
161 | * Updated routing table of the neighbor, under construction, | ||
162 | * NULL if we are not currently building it. | ||
163 | * Keys are peer identities, values are 'struct Target' entries. | ||
164 | * Note that the distances in the targets are from the point-of-view | ||
165 | * of the other peer, not from us! | ||
166 | */ | ||
167 | struct GNUNET_CONTAINER_MultiPeerMap *neighbor_table_consensus; | ||
168 | |||
169 | /** | ||
170 | * Our current (exposed) routing table as a set. | ||
171 | */ | ||
172 | struct GNUNET_SET_Handle *my_set; | ||
173 | |||
174 | /** | ||
175 | * Handle for our current active set union operation. | ||
176 | */ | ||
177 | struct GNUNET_SET_OperationHandle *set_op; | ||
178 | |||
179 | /** | ||
180 | * Handle used if we are listening for this peer, waiting for the | ||
181 | * other peer to initiate construction of the set union. NULL if | ||
182 | * we ar the initiating peer. | ||
183 | */ | ||
184 | struct GNUNET_SET_ListenHandle *listen_handle; | ||
185 | |||
186 | /** | ||
187 | * ID of the task we use to (periodically) update our consensus | ||
188 | * with this peer. Used if we are the initiating peer. | ||
189 | */ | ||
190 | struct GNUNET_SCHEDULER_Task *initiate_task; | ||
191 | |||
192 | /** | ||
193 | * At what offset are we, with respect to inserting our own routes | ||
194 | * into the consensus? | ||
195 | */ | ||
196 | unsigned int consensus_insertion_offset; | ||
197 | |||
198 | /** | ||
199 | * At what distance are we, with respect to inserting our own routes | ||
200 | * into the consensus? | ||
201 | */ | ||
202 | unsigned int consensus_insertion_distance; | ||
203 | |||
204 | /** | ||
205 | * Elements in consensus | ||
206 | */ | ||
207 | unsigned int consensus_elements; | ||
208 | |||
209 | /** | ||
210 | * Direct one hop route | ||
211 | */ | ||
212 | struct Route *direct_route; | ||
213 | |||
214 | /** | ||
215 | * Flag set within 'check_target_removed' to trigger full global route refresh. | ||
216 | */ | ||
217 | int target_removed; | ||
218 | |||
219 | /** | ||
220 | * Our distance to this peer, 0 for unknown. | ||
221 | */ | ||
222 | uint32_t distance; | ||
223 | |||
224 | /** | ||
225 | * The network this peer is in | ||
226 | */ | ||
227 | enum GNUNET_NetworkType network; | ||
228 | |||
229 | /** | ||
230 | * Is this neighbor connected at the core level? | ||
231 | */ | ||
232 | int connected; | ||
233 | |||
234 | }; | ||
235 | |||
236 | |||
237 | /** | ||
238 | * A route includes information about the next hop, | ||
239 | * the target, and the ultimate distance to the | ||
240 | * target. | ||
241 | */ | ||
242 | struct Route | ||
243 | { | ||
244 | |||
245 | /** | ||
246 | * Which peer do we need to forward the message to? | ||
247 | */ | ||
248 | struct DirectNeighbor *next_hop; | ||
249 | |||
250 | /** | ||
251 | * What would be the target, and how far is it away? | ||
252 | */ | ||
253 | struct Target target; | ||
254 | |||
255 | /** | ||
256 | * Offset of this target in the respective consensus set. | ||
257 | */ | ||
258 | unsigned int set_offset; | ||
259 | |||
260 | }; | ||
261 | |||
262 | |||
263 | /** | ||
264 | * Set of targets we bring to a consensus; all targets in a set have a | ||
265 | * distance equal to the sets distance (which is implied by the array | ||
266 | * index of the set). | ||
267 | */ | ||
268 | struct ConsensusSet | ||
269 | { | ||
270 | |||
271 | /** | ||
272 | * Array of targets in the set, may include NULL entries if a | ||
273 | * neighbor has disconnected; the targets are allocated with the | ||
274 | * respective container (all_routes), not here. | ||
275 | */ | ||
276 | struct Route **targets; | ||
277 | |||
278 | /** | ||
279 | * Size of the @e targets array. | ||
280 | */ | ||
281 | unsigned int array_length; | ||
282 | |||
283 | }; | ||
284 | |||
285 | |||
286 | /** | ||
287 | * Peermap of all of our neighbors; processing these usually requires | ||
288 | * first checking to see if the peer is core-connected and if the | ||
289 | * distance is 1, in which case they are direct neighbors. | ||
290 | */ | ||
291 | static struct GNUNET_CONTAINER_MultiPeerMap *direct_neighbors; | ||
292 | |||
293 | /** | ||
294 | * Hashmap with all routes that we currently support; contains | ||
295 | * routing information for all peers from distance 2 | ||
296 | * up to distance #DEFAULT_FISHEYE_DEPTH. | ||
297 | */ | ||
298 | static struct GNUNET_CONTAINER_MultiPeerMap *all_routes; | ||
299 | |||
300 | /** | ||
301 | * Array of consensus sets we expose to the outside world. Sets | ||
302 | * are structured by the distance to the target. | ||
303 | */ | ||
304 | static struct ConsensusSet consensi[DEFAULT_FISHEYE_DEPTH]; | ||
305 | |||
306 | /** | ||
307 | * Handle to the core service api. | ||
308 | */ | ||
309 | static struct GNUNET_CORE_Handle *core_api; | ||
310 | |||
311 | /** | ||
312 | * The identity of our peer. | ||
313 | */ | ||
314 | static struct GNUNET_PeerIdentity my_identity; | ||
315 | |||
316 | /** | ||
317 | * The configuration for this service. | ||
318 | */ | ||
319 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
320 | |||
321 | /** | ||
322 | * The client, the DV plugin connected to us (or an event monitor). | ||
323 | * Hopefully this client will never change, although if the plugin | ||
324 | * dies and returns for some reason it may happen. | ||
325 | */ | ||
326 | static struct GNUNET_NotificationContext *nc; | ||
327 | |||
328 | /** | ||
329 | * Handle for the statistics service. | ||
330 | */ | ||
331 | static struct GNUNET_STATISTICS_Handle *stats; | ||
332 | |||
333 | /** | ||
334 | * Handle to ATS service. | ||
335 | */ | ||
336 | static struct GNUNET_ATS_PerformanceHandle *ats; | ||
337 | |||
338 | /** | ||
339 | * Task scheduled to refresh routes based on direct neighbours. | ||
340 | */ | ||
341 | static struct GNUNET_SCHEDULER_Task *rr_task; | ||
342 | |||
343 | /** | ||
344 | * #GNUNET_YES if we are shutting down. | ||
345 | */ | ||
346 | static int in_shutdown; | ||
347 | |||
348 | /** | ||
349 | * Start creating a new DV set union by initiating the connection. | ||
350 | * | ||
351 | * @param cls the 'struct DirectNeighbor' of the peer we're building | ||
352 | * a routing consensus with | ||
353 | */ | ||
354 | static void | ||
355 | initiate_set_union (void *cls); | ||
356 | |||
357 | |||
358 | /** | ||
359 | * Start creating a new DV set union construction, our neighbour has | ||
360 | * asked for it (callback for listening peer). | ||
361 | * | ||
362 | * @param cls the 'struct DirectNeighbor' of the peer we're building | ||
363 | * a routing consensus with | ||
364 | * @param other_peer the other peer | ||
365 | * @param context_msg message with application specific information from | ||
366 | * the other peer | ||
367 | * @param request request from the other peer, use GNUNET_SET_accept | ||
368 | * to accept it, otherwise the request will be refused | ||
369 | * Note that we don't use a return value here, as it is also | ||
370 | * necessary to specify the set we want to do the operation with, | ||
371 | * whith sometimes can be derived from the context message. | ||
372 | * Also necessary to specify the timeout. | ||
373 | */ | ||
374 | static void | ||
375 | listen_set_union (void *cls, | ||
376 | const struct GNUNET_PeerIdentity *other_peer, | ||
377 | const struct GNUNET_MessageHeader *context_msg, | ||
378 | struct GNUNET_SET_Request *request); | ||
379 | |||
380 | |||
381 | /** | ||
382 | * Forward a message from another peer to the plugin. | ||
383 | * | ||
384 | * @param message the message to send to the plugin | ||
385 | * @param origin the original sender of the message | ||
386 | * @param distance distance to the original sender of the message | ||
387 | */ | ||
388 | static void | ||
389 | send_data_to_plugin (const struct GNUNET_MessageHeader *message, | ||
390 | const struct GNUNET_PeerIdentity *origin, | ||
391 | uint32_t distance) | ||
392 | { | ||
393 | struct GNUNET_DV_ReceivedMessage *received_msg; | ||
394 | size_t size; | ||
395 | |||
396 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
397 | "Delivering message from peer `%s' at distance %u\n", | ||
398 | GNUNET_i2s (origin), | ||
399 | (unsigned int) distance); | ||
400 | size = sizeof (struct GNUNET_DV_ReceivedMessage) + | ||
401 | ntohs (message->size); | ||
402 | if (size >= GNUNET_MAX_MESSAGE_SIZE) | ||
403 | { | ||
404 | GNUNET_break (0); /* too big */ | ||
405 | return; | ||
406 | } | ||
407 | received_msg = GNUNET_malloc (size); | ||
408 | received_msg->header.size = htons (size); | ||
409 | received_msg->header.type = htons (GNUNET_MESSAGE_TYPE_DV_RECV); | ||
410 | received_msg->distance = htonl (distance); | ||
411 | received_msg->sender = *origin; | ||
412 | GNUNET_memcpy (&received_msg[1], message, ntohs (message->size)); | ||
413 | GNUNET_notification_context_broadcast (nc, | ||
414 | &received_msg->header, | ||
415 | GNUNET_YES); | ||
416 | GNUNET_free (received_msg); | ||
417 | } | ||
418 | |||
419 | |||
420 | /** | ||
421 | * Forward a control message to the plugin. | ||
422 | * | ||
423 | * @param message the message to send to the plugin | ||
424 | */ | ||
425 | static void | ||
426 | send_control_to_plugin (const struct GNUNET_MessageHeader *message) | ||
427 | { | ||
428 | GNUNET_notification_context_broadcast (nc, | ||
429 | message, | ||
430 | GNUNET_NO); | ||
431 | } | ||
432 | |||
433 | |||
434 | /** | ||
435 | * Send a DISTANCE_CHANGED message to the plugin. | ||
436 | * | ||
437 | * @param peer peer with a changed distance | ||
438 | * @param distance new distance to the peer | ||
439 | * @param network network used by the neighbor | ||
440 | */ | ||
441 | static void | ||
442 | send_distance_change_to_plugin (const struct GNUNET_PeerIdentity *peer, | ||
443 | uint32_t distance, | ||
444 | enum GNUNET_NetworkType network) | ||
445 | { | ||
446 | struct GNUNET_DV_DistanceUpdateMessage du_msg; | ||
447 | |||
448 | GNUNET_break (GNUNET_NT_UNSPECIFIED != network); | ||
449 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
450 | "Delivering DISTANCE_CHANGED for message about peer `%s'\n", | ||
451 | GNUNET_i2s (peer)); | ||
452 | du_msg.header.size = htons (sizeof (du_msg)); | ||
453 | du_msg.header.type = htons (GNUNET_MESSAGE_TYPE_DV_DISTANCE_CHANGED); | ||
454 | du_msg.distance = htonl (distance); | ||
455 | du_msg.peer = *peer; | ||
456 | du_msg.network = htonl ((uint32_t) network); | ||
457 | send_control_to_plugin (&du_msg.header); | ||
458 | } | ||
459 | |||
460 | |||
461 | /** | ||
462 | * Give a CONNECT message to the plugin. | ||
463 | * | ||
464 | * @param target peer that connected | ||
465 | * @param distance distance to the target | ||
466 | * @param network the network the next hop is located in | ||
467 | */ | ||
468 | static void | ||
469 | send_connect_to_plugin (const struct GNUNET_PeerIdentity *target, | ||
470 | uint32_t distance, | ||
471 | enum GNUNET_NetworkType network) | ||
472 | { | ||
473 | struct GNUNET_DV_ConnectMessage cm; | ||
474 | |||
475 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
476 | "Delivering CONNECT about peer %s with distance %u\n", | ||
477 | GNUNET_i2s (target), distance); | ||
478 | cm.header.size = htons (sizeof (cm)); | ||
479 | cm.header.type = htons (GNUNET_MESSAGE_TYPE_DV_CONNECT); | ||
480 | cm.distance = htonl (distance); | ||
481 | cm.network = htonl ((uint32_t) network); | ||
482 | cm.peer = *target; | ||
483 | send_control_to_plugin (&cm.header); | ||
484 | } | ||
485 | |||
486 | |||
487 | /** | ||
488 | * Give a DISCONNECT message to the plugin. | ||
489 | * | ||
490 | * @param target peer that disconnected | ||
491 | */ | ||
492 | static void | ||
493 | send_disconnect_to_plugin (const struct GNUNET_PeerIdentity *target) | ||
494 | { | ||
495 | struct GNUNET_DV_DisconnectMessage dm; | ||
496 | |||
497 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
498 | "Delivering DISCONNECT about peer `%s'\n", | ||
499 | GNUNET_i2s (target)); | ||
500 | dm.header.size = htons (sizeof (dm)); | ||
501 | dm.header.type = htons (GNUNET_MESSAGE_TYPE_DV_DISCONNECT); | ||
502 | dm.reserved = htonl (0); | ||
503 | dm.peer = *target; | ||
504 | send_control_to_plugin (&dm.header); | ||
505 | } | ||
506 | |||
507 | |||
508 | /** | ||
509 | * Forward the given payload to the given target. | ||
510 | * | ||
511 | * @param target where to send the message | ||
512 | * @param distance distance to the @a sender | ||
513 | * @param sender original sender of the message | ||
514 | * @param actual_target ultimate recipient for the message | ||
515 | * @param payload payload of the message | ||
516 | */ | ||
517 | static void | ||
518 | forward_payload (struct DirectNeighbor *target, | ||
519 | uint32_t distance, | ||
520 | const struct GNUNET_PeerIdentity *sender, | ||
521 | const struct GNUNET_PeerIdentity *actual_target, | ||
522 | const struct GNUNET_MessageHeader *payload) | ||
523 | { | ||
524 | struct GNUNET_MQ_Envelope *env; | ||
525 | struct RouteMessage *rm; | ||
526 | |||
527 | if ( (GNUNET_MQ_get_length (target->mq) >= MAX_QUEUE_SIZE) && | ||
528 | (0 != memcmp (sender, | ||
529 | &my_identity, | ||
530 | sizeof (struct GNUNET_PeerIdentity))) ) | ||
531 | { | ||
532 | /* not _our_ client and queue is full, drop */ | ||
533 | GNUNET_STATISTICS_update (stats, | ||
534 | "# messages dropped", | ||
535 | 1, | ||
536 | GNUNET_NO); | ||
537 | return; | ||
538 | } | ||
539 | if (sizeof (struct RouteMessage) + ntohs (payload->size) | ||
540 | >= GNUNET_MAX_MESSAGE_SIZE) | ||
541 | { | ||
542 | GNUNET_break (0); | ||
543 | return; | ||
544 | } | ||
545 | env = GNUNET_MQ_msg_nested_mh (rm, | ||
546 | GNUNET_MESSAGE_TYPE_DV_ROUTE, | ||
547 | payload); | ||
548 | rm->distance = htonl (distance); | ||
549 | rm->target = *actual_target; | ||
550 | rm->sender = *sender; | ||
551 | GNUNET_MQ_send (target->mq, | ||
552 | env); | ||
553 | } | ||
554 | |||
555 | |||
556 | /** | ||
557 | * Find a free slot for storing a 'route' in the 'consensi' | ||
558 | * set at the given distance. | ||
559 | * | ||
560 | * @param distance distance to use for the set slot | ||
561 | */ | ||
562 | static unsigned int | ||
563 | get_consensus_slot (uint32_t distance) | ||
564 | { | ||
565 | struct ConsensusSet *cs; | ||
566 | unsigned int i; | ||
567 | |||
568 | GNUNET_assert (distance < DEFAULT_FISHEYE_DEPTH); | ||
569 | cs = &consensi[distance]; | ||
570 | i = 0; | ||
571 | while ( (i < cs->array_length) && | ||
572 | (NULL != cs->targets[i]) ) i++; | ||
573 | if (i == cs->array_length) | ||
574 | { | ||
575 | GNUNET_array_grow (cs->targets, | ||
576 | cs->array_length, | ||
577 | cs->array_length * 2 + 2); | ||
578 | } | ||
579 | return i; | ||
580 | } | ||
581 | |||
582 | |||
583 | /** | ||
584 | * Allocate a slot in the consensus set for a route. | ||
585 | * | ||
586 | * @param route route to initialize | ||
587 | * @param distance which consensus set to use | ||
588 | */ | ||
589 | static void | ||
590 | allocate_route (struct Route *route, | ||
591 | uint32_t distance) | ||
592 | { | ||
593 | unsigned int i; | ||
594 | |||
595 | if (distance >= DEFAULT_FISHEYE_DEPTH) | ||
596 | { | ||
597 | route->target.distance = htonl (distance); | ||
598 | route->set_offset = UINT_MAX; /* invalid slot */ | ||
599 | return; | ||
600 | } | ||
601 | i = get_consensus_slot (distance); | ||
602 | route->set_offset = i; | ||
603 | consensi[distance].targets[i] = route; | ||
604 | route->target.distance = htonl (distance); | ||
605 | } | ||
606 | |||
607 | |||
608 | /** | ||
609 | * Release a slot in the consensus set for a route. | ||
610 | * | ||
611 | * @param route route to release the slot from | ||
612 | */ | ||
613 | static void | ||
614 | release_route (struct Route *route) | ||
615 | { | ||
616 | if (UINT_MAX == route->set_offset) | ||
617 | return; | ||
618 | GNUNET_assert (ntohl (route->target.distance) < DEFAULT_FISHEYE_DEPTH); | ||
619 | consensi[ntohl (route->target.distance)].targets[route->set_offset] = NULL; | ||
620 | route->set_offset = UINT_MAX; /* indicate invalid slot */ | ||
621 | } | ||
622 | |||
623 | |||
624 | /** | ||
625 | * Move a route from one consensus set to another. | ||
626 | * | ||
627 | * @param route route to move | ||
628 | * @param new_distance new distance for the route (destination set) | ||
629 | */ | ||
630 | static void | ||
631 | move_route (struct Route *route, | ||
632 | uint32_t new_distance) | ||
633 | { | ||
634 | release_route (route); | ||
635 | allocate_route (route, new_distance); | ||
636 | } | ||
637 | |||
638 | |||
639 | /** | ||
640 | * Initialize this neighbors 'my_set' and when done give | ||
641 | * it to the pending set operation for execution. | ||
642 | * | ||
643 | * Add a single element to the set per call: | ||
644 | * | ||
645 | * If we reached the last element of a consensus element: increase distance | ||
646 | * | ||
647 | * | ||
648 | * @param cls the neighbor for which we are building the set | ||
649 | */ | ||
650 | static void | ||
651 | build_set (void *cls) | ||
652 | { | ||
653 | struct DirectNeighbor *neighbor = cls; | ||
654 | struct GNUNET_SET_Element element; | ||
655 | struct Target *target; | ||
656 | struct Route *route; | ||
657 | |||
658 | target = NULL; | ||
659 | /* skip over NULL entries */ | ||
660 | while ( (DEFAULT_FISHEYE_DEPTH > neighbor->consensus_insertion_distance) && | ||
661 | (consensi[neighbor->consensus_insertion_distance].array_length > neighbor->consensus_insertion_offset) && | ||
662 | (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) | ||
663 | neighbor->consensus_insertion_offset++; | ||
664 | while ( (DEFAULT_FISHEYE_DEPTH > neighbor->consensus_insertion_distance) && | ||
665 | (consensi[neighbor->consensus_insertion_distance].array_length == neighbor->consensus_insertion_offset) ) | ||
666 | { | ||
667 | /* If we reached the last element of a consensus array element: increase distance and start with next array */ | ||
668 | neighbor->consensus_insertion_offset = 0; | ||
669 | neighbor->consensus_insertion_distance++; | ||
670 | /* skip over NULL entries */ | ||
671 | while ( (DEFAULT_FISHEYE_DEPTH > neighbor->consensus_insertion_distance) && | ||
672 | (consensi[neighbor->consensus_insertion_distance].array_length > neighbor->consensus_insertion_offset) && | ||
673 | (NULL == consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]) ) | ||
674 | neighbor->consensus_insertion_offset++; | ||
675 | } | ||
676 | if (DEFAULT_FISHEYE_DEPTH == neighbor->consensus_insertion_distance) | ||
677 | { | ||
678 | /* we have added all elements to the set, run the operation */ | ||
679 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
680 | "Finished building my SET for peer `%s' with %u elements, committing\n", | ||
681 | GNUNET_i2s (&neighbor->peer), | ||
682 | neighbor->consensus_elements); | ||
683 | GNUNET_SET_commit (neighbor->set_op, | ||
684 | neighbor->my_set); | ||
685 | GNUNET_SET_destroy (neighbor->my_set); | ||
686 | neighbor->my_set = NULL; | ||
687 | return; | ||
688 | } | ||
689 | |||
690 | route = consensi[neighbor->consensus_insertion_distance].targets[neighbor->consensus_insertion_offset]; | ||
691 | GNUNET_assert (NULL != route); | ||
692 | target = &route->target; | ||
693 | GNUNET_assert (ntohl (target->distance) < DEFAULT_FISHEYE_DEPTH); | ||
694 | element.size = sizeof (struct Target); | ||
695 | element.element_type = htons (0); | ||
696 | element.data = target; | ||
697 | |||
698 | /* Find next non-NULL entry */ | ||
699 | neighbor->consensus_insertion_offset++; | ||
700 | if ( (0 != memcmp (&target->peer, | ||
701 | &my_identity, | ||
702 | sizeof (my_identity))) && | ||
703 | (0 != memcmp (&target->peer, | ||
704 | &neighbor->peer, | ||
705 | sizeof (struct GNUNET_PeerIdentity))) ) | ||
706 | { | ||
707 | /* Add target if it is not the neighbor or this peer */ | ||
708 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
709 | "Adding peer `%s' with distance %u to SET\n", | ||
710 | GNUNET_i2s (&target->peer), | ||
711 | ntohl (target->distance) + 1); | ||
712 | GNUNET_SET_add_element (neighbor->my_set, | ||
713 | &element, | ||
714 | &build_set, neighbor); | ||
715 | neighbor->consensus_elements++; | ||
716 | } | ||
717 | else | ||
718 | build_set (neighbor); | ||
719 | } | ||
720 | |||
721 | |||
722 | /** | ||
723 | * A peer is now connected to us at distance 1. Initiate DV exchange. | ||
724 | * | ||
725 | * @param neighbor entry for the neighbor at distance 1 | ||
726 | */ | ||
727 | static void | ||
728 | handle_direct_connect (struct DirectNeighbor *neighbor) | ||
729 | { | ||
730 | struct Route *route; | ||
731 | struct GNUNET_HashCode h1; | ||
732 | struct GNUNET_HashCode h2; | ||
733 | struct GNUNET_HashCode session_id; | ||
734 | |||
735 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
736 | "Direct connection to %s established, routing table exchange begins.\n", | ||
737 | GNUNET_i2s (&neighbor->peer)); | ||
738 | GNUNET_STATISTICS_update (stats, | ||
739 | "# peers connected (1-hop)", | ||
740 | 1, GNUNET_NO); | ||
741 | route = GNUNET_CONTAINER_multipeermap_get (all_routes, | ||
742 | &neighbor->peer); | ||
743 | if (NULL != route) | ||
744 | { | ||
745 | GNUNET_assert (GNUNET_YES == | ||
746 | GNUNET_CONTAINER_multipeermap_remove (all_routes, | ||
747 | &neighbor->peer, | ||
748 | route)); | ||
749 | send_disconnect_to_plugin (&neighbor->peer); | ||
750 | release_route (route); | ||
751 | GNUNET_free (route); | ||
752 | } | ||
753 | |||
754 | neighbor->direct_route = GNUNET_new (struct Route); | ||
755 | neighbor->direct_route->next_hop = neighbor; | ||
756 | neighbor->direct_route->target.peer = neighbor->peer; | ||
757 | allocate_route (neighbor->direct_route, DIRECT_NEIGHBOR_COST); | ||
758 | |||
759 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
760 | "Adding direct route to %s\n", | ||
761 | GNUNET_i2s (&neighbor->direct_route->target.peer)); | ||
762 | |||
763 | |||
764 | /* construct session ID seed as XOR of both peer's identities */ | ||
765 | GNUNET_CRYPTO_hash (&my_identity, | ||
766 | sizeof (my_identity), | ||
767 | &h1); | ||
768 | GNUNET_CRYPTO_hash (&neighbor->peer, | ||
769 | sizeof (struct GNUNET_PeerIdentity), | ||
770 | &h2); | ||
771 | GNUNET_CRYPTO_hash_xor (&h1, | ||
772 | &h2, | ||
773 | &session_id); | ||
774 | /* make sure session ID is unique across applications by salting it with 'DV' */ | ||
775 | GNUNET_CRYPTO_hkdf (&neighbor->real_session_id, sizeof (struct GNUNET_HashCode), | ||
776 | GCRY_MD_SHA512, GCRY_MD_SHA256, | ||
777 | "DV-SALT", 2, | ||
778 | &session_id, sizeof (session_id), | ||
779 | NULL, 0); | ||
780 | if (0 < memcmp (&neighbor->peer, | ||
781 | &my_identity, | ||
782 | sizeof (struct GNUNET_PeerIdentity))) | ||
783 | { | ||
784 | if (NULL != neighbor->listen_handle) | ||
785 | { | ||
786 | GNUNET_break (0); | ||
787 | } | ||
788 | else | ||
789 | neighbor->initiate_task = GNUNET_SCHEDULER_add_now (&initiate_set_union, | ||
790 | neighbor); | ||
791 | } | ||
792 | else | ||
793 | { | ||
794 | if (NULL != neighbor->listen_handle) | ||
795 | { | ||
796 | GNUNET_break (0); | ||
797 | } | ||
798 | else | ||
799 | { | ||
800 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
801 | "Starting SET listen operation with peer `%s'\n", | ||
802 | GNUNET_i2s (&neighbor->peer)); | ||
803 | neighbor->listen_handle = GNUNET_SET_listen (cfg, | ||
804 | GNUNET_SET_OPERATION_UNION, | ||
805 | &neighbor->real_session_id, | ||
806 | &listen_set_union, | ||
807 | neighbor); | ||
808 | } | ||
809 | } | ||
810 | } | ||
811 | |||
812 | |||
813 | /** | ||
814 | * Method called whenever a peer connects. | ||
815 | * | ||
816 | * @param cls closure | ||
817 | * @param peer peer identity this notification is about | ||
818 | * @param mq message queue for sending data to @a peer | ||
819 | * @return our `struct DirectNeighbour` for this peer | ||
820 | */ | ||
821 | static void * | ||
822 | handle_core_connect (void *cls, | ||
823 | const struct GNUNET_PeerIdentity *peer, | ||
824 | struct GNUNET_MQ_Handle *mq) | ||
825 | { | ||
826 | struct DirectNeighbor *neighbor; | ||
827 | |||
828 | /* Check for connect to self message */ | ||
829 | if (0 == memcmp (&my_identity, | ||
830 | peer, | ||
831 | sizeof (struct GNUNET_PeerIdentity))) | ||
832 | return NULL; | ||
833 | /* check if entry exists */ | ||
834 | neighbor = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, | ||
835 | peer); | ||
836 | if (NULL != neighbor) | ||
837 | { | ||
838 | GNUNET_break (GNUNET_NT_UNSPECIFIED != neighbor->network); | ||
839 | GNUNET_break (GNUNET_YES != neighbor->connected); | ||
840 | neighbor->connected = GNUNET_YES; | ||
841 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
842 | "Core connected to %s (distance %u)\n", | ||
843 | GNUNET_i2s (peer), | ||
844 | (unsigned int) neighbor->distance); | ||
845 | if (DIRECT_NEIGHBOR_COST != neighbor->distance) | ||
846 | return NULL; | ||
847 | handle_direct_connect (neighbor); | ||
848 | return NULL; | ||
849 | } | ||
850 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
851 | "Core connected to %s (distance unknown)\n", | ||
852 | GNUNET_i2s (peer)); | ||
853 | neighbor = GNUNET_new (struct DirectNeighbor); | ||
854 | neighbor->peer = *peer; | ||
855 | GNUNET_assert (GNUNET_YES == | ||
856 | GNUNET_CONTAINER_multipeermap_put (direct_neighbors, | ||
857 | &neighbor->peer, | ||
858 | neighbor, | ||
859 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
860 | neighbor->connected = GNUNET_YES; | ||
861 | neighbor->distance = 0; /* unknown */ | ||
862 | neighbor->network = GNUNET_NT_UNSPECIFIED; | ||
863 | return neighbor; | ||
864 | } | ||
865 | |||
866 | |||
867 | /** | ||
868 | * Called for each 'target' in a neighbor table to free the associated memory. | ||
869 | * | ||
870 | * @param cls NULL | ||
871 | * @param key key of the value | ||
872 | * @param value value to free | ||
873 | * @return #GNUNET_OK to continue to iterate | ||
874 | */ | ||
875 | static int | ||
876 | free_targets (void *cls, | ||
877 | const struct GNUNET_PeerIdentity *key, | ||
878 | void *value) | ||
879 | { | ||
880 | GNUNET_free (value); | ||
881 | return GNUNET_OK; | ||
882 | } | ||
883 | |||
884 | |||
885 | /** | ||
886 | * Add a new route to the given @a target via the given @a neighbor. | ||
887 | * | ||
888 | * @param target the target of the route | ||
889 | * @param neighbor the next hop for communicating with the @a target | ||
890 | */ | ||
891 | static void | ||
892 | add_new_route (struct Target *target, | ||
893 | struct DirectNeighbor *neighbor) | ||
894 | { | ||
895 | struct Route *route; | ||
896 | |||
897 | route = GNUNET_new (struct Route); | ||
898 | route->next_hop = neighbor; | ||
899 | route->target.peer = target->peer; | ||
900 | allocate_route (route, ntohl (target->distance) + 1); | ||
901 | GNUNET_assert (GNUNET_YES == | ||
902 | GNUNET_CONTAINER_multipeermap_put (all_routes, | ||
903 | &route->target.peer, | ||
904 | route, | ||
905 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
906 | send_connect_to_plugin (&route->target.peer, | ||
907 | ntohl (route->target.distance), | ||
908 | neighbor->network); | ||
909 | } | ||
910 | |||
911 | |||
912 | /** | ||
913 | * Multipeerhmap iterator for checking if a given route is | ||
914 | * (now) useful to this peer. | ||
915 | * | ||
916 | * @param cls the direct neighbor for the given route | ||
917 | * @param key key value stored under | ||
918 | * @param value a 'struct Target' that may or may not be useful; not that | ||
919 | * the distance in 'target' does not include the first hop yet | ||
920 | * @return #GNUNET_YES to continue iteration, #GNUNET_NO to stop | ||
921 | */ | ||
922 | static int | ||
923 | check_possible_route (void *cls, | ||
924 | const struct GNUNET_PeerIdentity *key, | ||
925 | void *value) | ||
926 | { | ||
927 | struct DirectNeighbor *neighbor = cls; | ||
928 | struct Target *target = value; | ||
929 | struct Route *route; | ||
930 | |||
931 | if (GNUNET_YES == | ||
932 | GNUNET_CONTAINER_multipeermap_contains (direct_neighbors, | ||
933 | key)) | ||
934 | return GNUNET_YES; /* direct route, do not care about alternatives */ | ||
935 | route = GNUNET_CONTAINER_multipeermap_get (all_routes, | ||
936 | key); | ||
937 | if (NULL != route) | ||
938 | { | ||
939 | /* we have an existing route, check how it compares with going via 'target' */ | ||
940 | if (ntohl (route->target.distance) > ntohl (target->distance) + 1) | ||
941 | { | ||
942 | /* via 'target' is cheaper than the existing route; switch to alternative route! */ | ||
943 | move_route (route, ntohl (target->distance) + 1); | ||
944 | route->next_hop = neighbor; | ||
945 | send_distance_change_to_plugin (&target->peer, | ||
946 | ntohl (target->distance) + 1, | ||
947 | neighbor->network); | ||
948 | } | ||
949 | return GNUNET_YES; /* got a route to this target already */ | ||
950 | } | ||
951 | if (ntohl (target->distance) >= DEFAULT_FISHEYE_DEPTH) | ||
952 | return GNUNET_YES; /* distance is too large to be interesting */ | ||
953 | add_new_route (target, neighbor); | ||
954 | return GNUNET_YES; | ||
955 | } | ||
956 | |||
957 | |||
958 | /** | ||
959 | * Multipeermap iterator for finding routes that were previously | ||
960 | * "hidden" due to a better route (called after a disconnect event). | ||
961 | * | ||
962 | * @param cls NULL | ||
963 | * @param key peer identity of the given direct neighbor | ||
964 | * @param value a `struct DirectNeighbor` to check for additional routes | ||
965 | * @return #GNUNET_YES to continue iteration | ||
966 | */ | ||
967 | static int | ||
968 | refresh_routes (void *cls, | ||
969 | const struct GNUNET_PeerIdentity *key, | ||
970 | void *value) | ||
971 | { | ||
972 | struct DirectNeighbor *neighbor = value; | ||
973 | |||
974 | if ( (GNUNET_YES != neighbor->connected) || | ||
975 | (DIRECT_NEIGHBOR_COST != neighbor->distance) ) | ||
976 | return GNUNET_YES; | ||
977 | if (NULL != neighbor->neighbor_table) | ||
978 | GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, | ||
979 | &check_possible_route, | ||
980 | neighbor); | ||
981 | return GNUNET_YES; | ||
982 | } | ||
983 | |||
984 | |||
985 | /** | ||
986 | * Task to run #refresh_routes() on all direct neighbours. | ||
987 | * | ||
988 | * @param cls NULL | ||
989 | */ | ||
990 | static void | ||
991 | refresh_routes_task (void *cls) | ||
992 | { | ||
993 | rr_task = NULL; | ||
994 | GNUNET_CONTAINER_multipeermap_iterate (direct_neighbors, | ||
995 | &refresh_routes, | ||
996 | NULL); | ||
997 | } | ||
998 | |||
999 | |||
1000 | /** | ||
1001 | * Asynchronously run #refresh_routes() at the next opportunity | ||
1002 | * on all direct neighbours. | ||
1003 | */ | ||
1004 | static void | ||
1005 | schedule_refresh_routes () | ||
1006 | { | ||
1007 | if (NULL == rr_task) | ||
1008 | rr_task = GNUNET_SCHEDULER_add_now (&refresh_routes_task, | ||
1009 | NULL); | ||
1010 | } | ||
1011 | |||
1012 | |||
1013 | /** | ||
1014 | * Multipeermap iterator for freeing routes that go via a particular | ||
1015 | * neighbor that disconnected and is thus no longer available. | ||
1016 | * | ||
1017 | * @param cls the direct neighbor that is now unavailable | ||
1018 | * @param key key value stored under | ||
1019 | * @param value a `struct Route` that may or may not go via neighbor | ||
1020 | * | ||
1021 | * @return #GNUNET_YES to continue iteration, #GNUNET_NO to stop | ||
1022 | */ | ||
1023 | static int | ||
1024 | cull_routes (void *cls, | ||
1025 | const struct GNUNET_PeerIdentity *key, | ||
1026 | void *value) | ||
1027 | { | ||
1028 | struct DirectNeighbor *neighbor = cls; | ||
1029 | struct Route *route = value; | ||
1030 | |||
1031 | if (route->next_hop != neighbor) | ||
1032 | return GNUNET_YES; /* not affected */ | ||
1033 | GNUNET_assert (GNUNET_YES == | ||
1034 | GNUNET_CONTAINER_multipeermap_remove (all_routes, key, value)); | ||
1035 | release_route (route); | ||
1036 | send_disconnect_to_plugin (&route->target.peer); | ||
1037 | GNUNET_free (route); | ||
1038 | return GNUNET_YES; | ||
1039 | } | ||
1040 | |||
1041 | |||
1042 | /** | ||
1043 | * Handle the case that a direct connection to a peer is | ||
1044 | * disrupted. Remove all routes via that peer and | ||
1045 | * stop the consensus with it. | ||
1046 | * | ||
1047 | * @param neighbor peer that was disconnected (or at least is no | ||
1048 | * longer at distance 1) | ||
1049 | */ | ||
1050 | static void | ||
1051 | handle_direct_disconnect (struct DirectNeighbor *neighbor) | ||
1052 | { | ||
1053 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1054 | "Culling routes via %s due to direct disconnect\n", | ||
1055 | GNUNET_i2s (&neighbor->peer)); | ||
1056 | GNUNET_CONTAINER_multipeermap_iterate (all_routes, | ||
1057 | &cull_routes, | ||
1058 | neighbor); | ||
1059 | if (NULL != neighbor->direct_route) | ||
1060 | { | ||
1061 | release_route (neighbor->direct_route); | ||
1062 | GNUNET_free (neighbor->direct_route); | ||
1063 | neighbor->direct_route = NULL; | ||
1064 | } | ||
1065 | if (NULL != neighbor->neighbor_table_consensus) | ||
1066 | { | ||
1067 | GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table_consensus, | ||
1068 | &free_targets, | ||
1069 | NULL); | ||
1070 | GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table_consensus); | ||
1071 | neighbor->neighbor_table_consensus = NULL; | ||
1072 | } | ||
1073 | if (NULL != neighbor->neighbor_table) | ||
1074 | { | ||
1075 | GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, | ||
1076 | &free_targets, | ||
1077 | NULL); | ||
1078 | GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table); | ||
1079 | neighbor->neighbor_table = NULL; | ||
1080 | } | ||
1081 | if (NULL != neighbor->set_op) | ||
1082 | { | ||
1083 | GNUNET_SET_operation_cancel (neighbor->set_op); | ||
1084 | neighbor->set_op = NULL; | ||
1085 | } | ||
1086 | if (NULL != neighbor->my_set) | ||
1087 | { | ||
1088 | GNUNET_SET_destroy (neighbor->my_set); | ||
1089 | neighbor->my_set = NULL; | ||
1090 | } | ||
1091 | if (NULL != neighbor->listen_handle) | ||
1092 | { | ||
1093 | GNUNET_SET_listen_cancel (neighbor->listen_handle); | ||
1094 | neighbor->listen_handle = NULL; | ||
1095 | } | ||
1096 | if (NULL != neighbor->initiate_task) | ||
1097 | { | ||
1098 | GNUNET_SCHEDULER_cancel (neighbor->initiate_task); | ||
1099 | neighbor->initiate_task = NULL; | ||
1100 | } | ||
1101 | } | ||
1102 | |||
1103 | |||
1104 | /** | ||
1105 | * Function that is called with QoS information about an address; used | ||
1106 | * to update our current distance to another peer. | ||
1107 | * | ||
1108 | * @param cls closure | ||
1109 | * @param address the address | ||
1110 | * @param active #GNUNET_YES if this address is actively used | ||
1111 | * to maintain a connection to a peer; | ||
1112 | * #GNUNET_NO if the address is not actively used; | ||
1113 | * #GNUNET_SYSERR if this address is no longer available for ATS | ||
1114 | * @param bandwidth_out assigned outbound bandwidth for the connection | ||
1115 | * @param bandwidth_in assigned inbound bandwidth for the connection | ||
1116 | * @param prop performance data for the address (as far as known) | ||
1117 | */ | ||
1118 | static void | ||
1119 | handle_ats_update (void *cls, | ||
1120 | const struct GNUNET_HELLO_Address *address, | ||
1121 | int active, | ||
1122 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out, | ||
1123 | struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in, | ||
1124 | const struct GNUNET_ATS_Properties *prop) | ||
1125 | { | ||
1126 | struct DirectNeighbor *neighbor; | ||
1127 | uint32_t distance; | ||
1128 | enum GNUNET_NetworkType network; | ||
1129 | |||
1130 | if (NULL == address) | ||
1131 | { | ||
1132 | /* ATS service temporarily disconnected */ | ||
1133 | return; | ||
1134 | } | ||
1135 | |||
1136 | if (GNUNET_YES != active) | ||
1137 | { | ||
1138 | // FIXME: handle disconnect/inactive case too! | ||
1139 | return; | ||
1140 | } | ||
1141 | distance = prop->distance; | ||
1142 | network = prop->scope; | ||
1143 | GNUNET_break (GNUNET_NT_UNSPECIFIED != network); | ||
1144 | /* check if entry exists */ | ||
1145 | neighbor = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, | ||
1146 | &address->peer); | ||
1147 | if (NULL != neighbor) | ||
1148 | { | ||
1149 | neighbor->network = network; | ||
1150 | if (neighbor->distance == distance) | ||
1151 | return; /* nothing new to see here, move along */ | ||
1152 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1153 | "ATS says distance to %s is now %u\n", | ||
1154 | GNUNET_i2s (&address->peer), | ||
1155 | (unsigned int) distance); | ||
1156 | if ( (DIRECT_NEIGHBOR_COST == neighbor->distance) && | ||
1157 | (DIRECT_NEIGHBOR_COST == distance) ) | ||
1158 | return; /* no change */ | ||
1159 | if (DIRECT_NEIGHBOR_COST == neighbor->distance) | ||
1160 | { | ||
1161 | neighbor->distance = distance; | ||
1162 | GNUNET_STATISTICS_update (stats, | ||
1163 | "# peers connected (1-hop)", | ||
1164 | -1, GNUNET_NO); | ||
1165 | handle_direct_disconnect (neighbor); | ||
1166 | schedule_refresh_routes (); | ||
1167 | return; | ||
1168 | } | ||
1169 | neighbor->distance = distance; | ||
1170 | if (DIRECT_NEIGHBOR_COST != neighbor->distance) | ||
1171 | return; | ||
1172 | if (GNUNET_YES != neighbor->connected) | ||
1173 | return; | ||
1174 | handle_direct_connect (neighbor); | ||
1175 | return; | ||
1176 | } | ||
1177 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1178 | "ATS says distance to %s is now %u\n", | ||
1179 | GNUNET_i2s (&address->peer), | ||
1180 | (unsigned int) distance); | ||
1181 | neighbor = GNUNET_new (struct DirectNeighbor); | ||
1182 | neighbor->peer = address->peer; | ||
1183 | GNUNET_assert (GNUNET_YES == | ||
1184 | GNUNET_CONTAINER_multipeermap_put (direct_neighbors, | ||
1185 | &neighbor->peer, | ||
1186 | neighbor, | ||
1187 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1188 | neighbor->connected = GNUNET_NO; /* not yet */ | ||
1189 | neighbor->distance = distance; | ||
1190 | neighbor->network = network; | ||
1191 | } | ||
1192 | |||
1193 | |||
1194 | /** | ||
1195 | * Check if a target was removed from the set of the other peer; if so, | ||
1196 | * if we also used it for our route, we need to remove it from our | ||
1197 | * 'all_routes' set (and later check if an alternative path now exists). | ||
1198 | * | ||
1199 | * @param cls the `struct DirectNeighbor` | ||
1200 | * @param key peer identity for the target | ||
1201 | * @param value a `struct Target` previously reachable via the given neighbor | ||
1202 | */ | ||
1203 | static int | ||
1204 | check_target_removed (void *cls, | ||
1205 | const struct GNUNET_PeerIdentity *key, | ||
1206 | void *value) | ||
1207 | { | ||
1208 | struct DirectNeighbor *neighbor = cls; | ||
1209 | struct Target *new_target; | ||
1210 | struct Route *current_route; | ||
1211 | |||
1212 | new_target = GNUNET_CONTAINER_multipeermap_get (neighbor->neighbor_table_consensus, | ||
1213 | key); | ||
1214 | current_route = GNUNET_CONTAINER_multipeermap_get (all_routes, | ||
1215 | key); | ||
1216 | if (NULL != new_target) | ||
1217 | { | ||
1218 | /* target was in old set, is in new set */ | ||
1219 | if ( (NULL != current_route) && | ||
1220 | (current_route->next_hop == neighbor) && | ||
1221 | (current_route->target.distance != new_target->distance) ) | ||
1222 | { | ||
1223 | /* need to recalculate routes due to distance change */ | ||
1224 | neighbor->target_removed = GNUNET_YES; | ||
1225 | } | ||
1226 | return GNUNET_OK; | ||
1227 | } | ||
1228 | /* target was revoked, check if it was used */ | ||
1229 | if ( (NULL == current_route) || | ||
1230 | (current_route->next_hop != neighbor) ) | ||
1231 | { | ||
1232 | /* didn't matter, wasn't used */ | ||
1233 | return GNUNET_OK; | ||
1234 | } | ||
1235 | /* remove existing route */ | ||
1236 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1237 | "Lost route to %s\n", | ||
1238 | GNUNET_i2s (¤t_route->target.peer)); | ||
1239 | GNUNET_assert (GNUNET_YES == | ||
1240 | GNUNET_CONTAINER_multipeermap_remove (all_routes, key, current_route)); | ||
1241 | send_disconnect_to_plugin (¤t_route->target.peer); | ||
1242 | release_route (current_route); | ||
1243 | GNUNET_free (current_route); | ||
1244 | neighbor->target_removed = GNUNET_YES; | ||
1245 | return GNUNET_OK; | ||
1246 | } | ||
1247 | |||
1248 | |||
1249 | /** | ||
1250 | * Check if a target was added to the set of the other peer; if it | ||
1251 | * was added or impoves the existing route, do the needed updates. | ||
1252 | * | ||
1253 | * @param cls the `struct DirectNeighbor` | ||
1254 | * @param key peer identity for the target | ||
1255 | * @param value a `struct Target` now reachable via the given neighbor | ||
1256 | */ | ||
1257 | static int | ||
1258 | check_target_added (void *cls, | ||
1259 | const struct GNUNET_PeerIdentity *key, | ||
1260 | void *value) | ||
1261 | { | ||
1262 | struct DirectNeighbor *neighbor = cls; | ||
1263 | struct Target *target = value; | ||
1264 | struct Route *current_route; | ||
1265 | |||
1266 | /* target was revoked, check if it was used */ | ||
1267 | current_route = GNUNET_CONTAINER_multipeermap_get (all_routes, | ||
1268 | key); | ||
1269 | if (NULL != current_route) | ||
1270 | { | ||
1271 | /* route exists */ | ||
1272 | if (current_route->next_hop == neighbor) | ||
1273 | { | ||
1274 | /* we had the same route before, no change in target */ | ||
1275 | if (ntohl (target->distance) + 1 != ntohl (current_route->target.distance)) | ||
1276 | { | ||
1277 | /* but distance changed! */ | ||
1278 | if (ntohl (target->distance) + 1 > DEFAULT_FISHEYE_DEPTH) | ||
1279 | { | ||
1280 | /* distance increased beyond what is allowed, kill route */ | ||
1281 | GNUNET_assert (GNUNET_YES == | ||
1282 | GNUNET_CONTAINER_multipeermap_remove (all_routes, | ||
1283 | key, | ||
1284 | current_route)); | ||
1285 | send_disconnect_to_plugin (key); | ||
1286 | release_route (current_route); | ||
1287 | GNUNET_free (current_route); | ||
1288 | } | ||
1289 | else | ||
1290 | { | ||
1291 | /* distance decreased, update route */ | ||
1292 | move_route (current_route, | ||
1293 | ntohl (target->distance) + 1); | ||
1294 | send_distance_change_to_plugin (&target->peer, | ||
1295 | ntohl (target->distance) + 1, | ||
1296 | neighbor->network); | ||
1297 | } | ||
1298 | } | ||
1299 | return GNUNET_OK; | ||
1300 | } | ||
1301 | if (ntohl (current_route->target.distance) <= ntohl (target->distance) + 1) | ||
1302 | { | ||
1303 | /* alternative, shorter route exists, ignore */ | ||
1304 | return GNUNET_OK; | ||
1305 | } | ||
1306 | /* new route is better than the existing one, take over! */ | ||
1307 | /* NOTE: minor security issue: malicious peers may advertise | ||
1308 | very short routes to take over longer paths; as we don't | ||
1309 | check that the shorter routes actually work, a malicious | ||
1310 | direct neighbor can use this to DoS our long routes */ | ||
1311 | |||
1312 | move_route (current_route, ntohl (target->distance) + 1); | ||
1313 | current_route->next_hop = neighbor; | ||
1314 | send_distance_change_to_plugin (&target->peer, | ||
1315 | ntohl (target->distance) + 1, | ||
1316 | neighbor->network); | ||
1317 | return GNUNET_OK; | ||
1318 | } | ||
1319 | /* new route */ | ||
1320 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1321 | "Discovered new route to %s using %u hops\n", | ||
1322 | GNUNET_i2s (&target->peer), | ||
1323 | (unsigned int) (ntohl (target->distance) + 1)); | ||
1324 | current_route = GNUNET_new (struct Route); | ||
1325 | current_route->next_hop = neighbor; | ||
1326 | current_route->target.peer = target->peer; | ||
1327 | allocate_route (current_route, ntohl (target->distance) + 1); | ||
1328 | GNUNET_assert (GNUNET_YES == | ||
1329 | GNUNET_CONTAINER_multipeermap_put (all_routes, | ||
1330 | ¤t_route->target.peer, | ||
1331 | current_route, | ||
1332 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
1333 | |||
1334 | send_connect_to_plugin (¤t_route->target.peer, | ||
1335 | ntohl (current_route->target.distance), | ||
1336 | neighbor->network); | ||
1337 | return GNUNET_OK; | ||
1338 | } | ||
1339 | |||
1340 | |||
1341 | /** | ||
1342 | * Callback for set operation results. Called for each element | ||
1343 | * in the result set. | ||
1344 | * We have learned a new route from the other peer. Add it to the | ||
1345 | * route set we're building. | ||
1346 | * | ||
1347 | * @param cls the `struct DirectNeighbor` we're building the consensus with | ||
1348 | * @param element a result element, only valid if status is #GNUNET_SET_STATUS_OK | ||
1349 | * @param current_size current set size | ||
1350 | * @param status see `enum GNUNET_SET_Status` | ||
1351 | */ | ||
1352 | static void | ||
1353 | handle_set_union_result (void *cls, | ||
1354 | const struct GNUNET_SET_Element *element, | ||
1355 | uint64_t current_size, | ||
1356 | enum GNUNET_SET_Status status) | ||
1357 | { | ||
1358 | struct DirectNeighbor *neighbor = cls; | ||
1359 | struct DirectNeighbor *dn; | ||
1360 | struct Target *target; | ||
1361 | const struct Target *ctarget; | ||
1362 | char *status_str; | ||
1363 | |||
1364 | switch (status) | ||
1365 | { | ||
1366 | case GNUNET_SET_STATUS_OK: | ||
1367 | status_str = "GNUNET_SET_STATUS_OK"; | ||
1368 | break; | ||
1369 | case GNUNET_SET_STATUS_FAILURE: | ||
1370 | status_str = "GNUNET_SET_STATUS_FAILURE"; | ||
1371 | break; | ||
1372 | case GNUNET_SET_STATUS_HALF_DONE: | ||
1373 | status_str = "GNUNET_SET_STATUS_HALF_DONE"; | ||
1374 | break; | ||
1375 | case GNUNET_SET_STATUS_DONE: | ||
1376 | status_str = "GNUNET_SET_STATUS_DONE"; | ||
1377 | break; | ||
1378 | default: | ||
1379 | status_str = "UNDEFINED"; | ||
1380 | break; | ||
1381 | } | ||
1382 | |||
1383 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1384 | "Got SET union result: %s\n", | ||
1385 | status_str); | ||
1386 | switch (status) | ||
1387 | { | ||
1388 | case GNUNET_SET_STATUS_OK: | ||
1389 | if (sizeof (struct Target) != element->size) | ||
1390 | { | ||
1391 | GNUNET_break_op (0); | ||
1392 | return; | ||
1393 | } | ||
1394 | ctarget = element->data; | ||
1395 | if ( (NULL != | ||
1396 | (dn = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, | ||
1397 | &ctarget->peer))) && | ||
1398 | (DIRECT_NEIGHBOR_COST == dn->distance) ) | ||
1399 | { | ||
1400 | /* this is a direct neighbor of ours, we do not care about routes | ||
1401 | to this peer */ | ||
1402 | return; | ||
1403 | } | ||
1404 | target = GNUNET_new (struct Target); | ||
1405 | GNUNET_memcpy (target, element->data, sizeof (struct Target)); | ||
1406 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1407 | "Received information about peer `%s' with distance %u from SET\n", | ||
1408 | GNUNET_i2s (&target->peer), | ||
1409 | ntohl (target->distance) + 1); | ||
1410 | |||
1411 | if (NULL == neighbor->neighbor_table_consensus) | ||
1412 | neighbor->neighbor_table_consensus | ||
1413 | = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | ||
1414 | if (GNUNET_YES != | ||
1415 | GNUNET_CONTAINER_multipeermap_put (neighbor->neighbor_table_consensus, | ||
1416 | &target->peer, | ||
1417 | target, | ||
1418 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
1419 | { | ||
1420 | GNUNET_break_op (0); | ||
1421 | GNUNET_free (target); | ||
1422 | } | ||
1423 | break; | ||
1424 | case GNUNET_SET_STATUS_FAILURE: | ||
1425 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1426 | "Failed to establish DV union, will try again later\n"); | ||
1427 | neighbor->set_op = NULL; | ||
1428 | if (NULL != neighbor->neighbor_table_consensus) | ||
1429 | { | ||
1430 | GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table_consensus, | ||
1431 | &free_targets, | ||
1432 | NULL); | ||
1433 | GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table_consensus); | ||
1434 | neighbor->neighbor_table_consensus = NULL; | ||
1435 | } | ||
1436 | if (0 < memcmp (&neighbor->peer, | ||
1437 | &my_identity, | ||
1438 | sizeof (struct GNUNET_PeerIdentity))) | ||
1439 | neighbor->initiate_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, | ||
1440 | &initiate_set_union, | ||
1441 | neighbor); | ||
1442 | break; | ||
1443 | case GNUNET_SET_STATUS_HALF_DONE: | ||
1444 | break; | ||
1445 | case GNUNET_SET_STATUS_DONE: | ||
1446 | /* we got all of our updates; integrate routing table! */ | ||
1447 | neighbor->target_removed = GNUNET_NO; | ||
1448 | if (NULL == neighbor->neighbor_table_consensus) | ||
1449 | neighbor->neighbor_table_consensus = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | ||
1450 | if (NULL != neighbor->neighbor_table) | ||
1451 | GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, | ||
1452 | &check_target_removed, | ||
1453 | neighbor); | ||
1454 | if (GNUNET_YES == neighbor->target_removed) | ||
1455 | { | ||
1456 | /* check if we got an alternative for the removed routes */ | ||
1457 | schedule_refresh_routes (); | ||
1458 | } | ||
1459 | /* add targets that appeared (and check for improved routes) */ | ||
1460 | GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table_consensus, | ||
1461 | &check_target_added, | ||
1462 | neighbor); | ||
1463 | if (NULL != neighbor->neighbor_table) | ||
1464 | { | ||
1465 | GNUNET_CONTAINER_multipeermap_iterate (neighbor->neighbor_table, | ||
1466 | &free_targets, | ||
1467 | NULL); | ||
1468 | GNUNET_CONTAINER_multipeermap_destroy (neighbor->neighbor_table); | ||
1469 | neighbor->neighbor_table = NULL; | ||
1470 | } | ||
1471 | neighbor->neighbor_table = neighbor->neighbor_table_consensus; | ||
1472 | neighbor->neighbor_table_consensus = NULL; | ||
1473 | |||
1474 | /* operation done, schedule next run! */ | ||
1475 | neighbor->set_op = NULL; | ||
1476 | if (0 < memcmp (&neighbor->peer, | ||
1477 | &my_identity, | ||
1478 | sizeof (struct GNUNET_PeerIdentity))) | ||
1479 | neighbor->initiate_task = GNUNET_SCHEDULER_add_delayed (GNUNET_DV_CONSENSUS_FREQUENCY, | ||
1480 | &initiate_set_union, | ||
1481 | neighbor); | ||
1482 | break; | ||
1483 | default: | ||
1484 | GNUNET_break (0); | ||
1485 | return; | ||
1486 | } | ||
1487 | } | ||
1488 | |||
1489 | |||
1490 | /** | ||
1491 | * Start creating a new DV set union construction, our neighbour has | ||
1492 | * asked for it (callback for listening peer). | ||
1493 | * | ||
1494 | * @param cls the 'struct DirectNeighbor' of the peer we're building | ||
1495 | * a routing consensus with | ||
1496 | * @param other_peer the other peer | ||
1497 | * @param context_msg message with application specific information from | ||
1498 | * the other peer | ||
1499 | * @param request request from the other peer, use GNUNET_SET_accept | ||
1500 | * to accept it, otherwise the request will be refused | ||
1501 | * Note that we don't use a return value here, as it is also | ||
1502 | * necessary to specify the set we want to do the operation with, | ||
1503 | * whith sometimes can be derived from the context message. | ||
1504 | * Also necessary to specify the timeout. | ||
1505 | */ | ||
1506 | static void | ||
1507 | listen_set_union (void *cls, | ||
1508 | const struct GNUNET_PeerIdentity *other_peer, | ||
1509 | const struct GNUNET_MessageHeader *context_msg, | ||
1510 | struct GNUNET_SET_Request *request) | ||
1511 | { | ||
1512 | struct DirectNeighbor *neighbor = cls; | ||
1513 | |||
1514 | if (NULL == request) | ||
1515 | return; /* why??? */ | ||
1516 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1517 | "Starting to create consensus with %s\n", | ||
1518 | GNUNET_i2s (&neighbor->peer)); | ||
1519 | if (NULL != neighbor->set_op) | ||
1520 | { | ||
1521 | GNUNET_SET_operation_cancel (neighbor->set_op); | ||
1522 | neighbor->set_op = NULL; | ||
1523 | } | ||
1524 | if (NULL != neighbor->my_set) | ||
1525 | { | ||
1526 | GNUNET_SET_destroy (neighbor->my_set); | ||
1527 | neighbor->my_set = NULL; | ||
1528 | } | ||
1529 | neighbor->my_set = GNUNET_SET_create (cfg, | ||
1530 | GNUNET_SET_OPERATION_UNION); | ||
1531 | neighbor->set_op = GNUNET_SET_accept (request, | ||
1532 | GNUNET_SET_RESULT_ADDED, | ||
1533 | (struct GNUNET_SET_Option[]) {{ 0 }}, | ||
1534 | &handle_set_union_result, | ||
1535 | neighbor); | ||
1536 | neighbor->consensus_insertion_offset = 0; | ||
1537 | neighbor->consensus_insertion_distance = 0; | ||
1538 | neighbor->consensus_elements = 0; | ||
1539 | build_set (neighbor); | ||
1540 | } | ||
1541 | |||
1542 | |||
1543 | /** | ||
1544 | * Start creating a new DV set union by initiating the connection. | ||
1545 | * | ||
1546 | * @param cls the `struct DirectNeighbor *` of the peer we're building | ||
1547 | * a routing consensus with | ||
1548 | */ | ||
1549 | static void | ||
1550 | initiate_set_union (void *cls) | ||
1551 | { | ||
1552 | struct DirectNeighbor *neighbor = cls; | ||
1553 | |||
1554 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1555 | "Initiating SET union with peer `%s'\n", | ||
1556 | GNUNET_i2s (&neighbor->peer)); | ||
1557 | neighbor->initiate_task = NULL; | ||
1558 | neighbor->my_set = GNUNET_SET_create (cfg, | ||
1559 | GNUNET_SET_OPERATION_UNION); | ||
1560 | neighbor->set_op = GNUNET_SET_prepare (&neighbor->peer, | ||
1561 | &neighbor->real_session_id, | ||
1562 | NULL, | ||
1563 | GNUNET_SET_RESULT_ADDED, | ||
1564 | (struct GNUNET_SET_Option[]) {{ 0 }}, | ||
1565 | &handle_set_union_result, | ||
1566 | neighbor); | ||
1567 | neighbor->consensus_insertion_offset = 0; | ||
1568 | neighbor->consensus_insertion_distance = 0; | ||
1569 | neighbor->consensus_elements = 0; | ||
1570 | build_set (neighbor); | ||
1571 | } | ||
1572 | |||
1573 | |||
1574 | /** | ||
1575 | * Check that @a rm is well-formed. | ||
1576 | * | ||
1577 | * @param cls closure | ||
1578 | * @param rm the message | ||
1579 | * @return #GNUNET_OK if @a rm is well-formed. | ||
1580 | */ | ||
1581 | static int | ||
1582 | check_dv_route_message (void *cls, | ||
1583 | const struct RouteMessage *rm) | ||
1584 | { | ||
1585 | const struct GNUNET_MessageHeader *payload; | ||
1586 | |||
1587 | if (ntohs (rm->header.size) < sizeof (struct RouteMessage) + sizeof (struct GNUNET_MessageHeader)) | ||
1588 | { | ||
1589 | GNUNET_break_op (0); | ||
1590 | return GNUNET_SYSERR; | ||
1591 | } | ||
1592 | payload = (const struct GNUNET_MessageHeader *) &rm[1]; | ||
1593 | if (ntohs (rm->header.size) != sizeof (struct RouteMessage) + ntohs (payload->size)) | ||
1594 | { | ||
1595 | GNUNET_break_op (0); | ||
1596 | return GNUNET_SYSERR; | ||
1597 | } | ||
1598 | return GNUNET_OK; | ||
1599 | } | ||
1600 | |||
1601 | |||
1602 | /** | ||
1603 | * Core handler for DV data messages. Whatever this message | ||
1604 | * contains all we really have to do is rip it out of its | ||
1605 | * DV layering and give it to our pal the DV plugin to report | ||
1606 | * in with. | ||
1607 | * | ||
1608 | * @param cls closure | ||
1609 | * @param rm the message | ||
1610 | */ | ||
1611 | static void | ||
1612 | handle_dv_route_message (void *cls, | ||
1613 | const struct RouteMessage *rm) | ||
1614 | { | ||
1615 | struct DirectNeighbor *neighbor = cls; | ||
1616 | const struct GNUNET_MessageHeader *payload; | ||
1617 | struct Route *route; | ||
1618 | struct DirectNeighbor *nneighbor; | ||
1619 | struct DirectNeighbor *dn; | ||
1620 | struct Target *target; | ||
1621 | uint32_t distance; | ||
1622 | char me[5]; | ||
1623 | char src[5]; | ||
1624 | char prev[5]; | ||
1625 | char dst[5]; | ||
1626 | |||
1627 | distance = ntohl (rm->distance); | ||
1628 | payload = (const struct GNUNET_MessageHeader *) &rm[1]; | ||
1629 | strncpy (prev, GNUNET_i2s (&neighbor->peer), 4); | ||
1630 | strncpy (me, GNUNET_i2s (&my_identity), 4); | ||
1631 | strncpy (src, GNUNET_i2s (&rm->sender), 4); | ||
1632 | strncpy (dst, GNUNET_i2s (&rm->target), 4); | ||
1633 | prev[4] = me[4] = src[4] = dst[4] = '\0'; | ||
1634 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1635 | "Handling DV message with %u bytes payload of type %u from %s to %s routed by %s to me (%s @ hop %u)\n", | ||
1636 | (unsigned int) (ntohs (rm->header.size) - sizeof (struct RouteMessage)), | ||
1637 | ntohs (payload->type), | ||
1638 | src, | ||
1639 | dst, | ||
1640 | prev, | ||
1641 | me, | ||
1642 | (unsigned int) distance + 1); | ||
1643 | |||
1644 | if (0 == memcmp (&rm->target, | ||
1645 | &my_identity, | ||
1646 | sizeof (struct GNUNET_PeerIdentity))) | ||
1647 | { | ||
1648 | if ((NULL != | ||
1649 | (dn = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, | ||
1650 | &rm->sender))) && | ||
1651 | (DIRECT_NEIGHBOR_COST == dn->distance)) | ||
1652 | { | ||
1653 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1654 | "Discarding DV message, as %s is a direct neighbor\n", | ||
1655 | GNUNET_i2s (&rm->sender)); | ||
1656 | GNUNET_STATISTICS_update (stats, | ||
1657 | "# messages discarded (direct neighbor)", | ||
1658 | 1, GNUNET_NO); | ||
1659 | return; | ||
1660 | } | ||
1661 | /* message is for me, check reverse route! */ | ||
1662 | route = GNUNET_CONTAINER_multipeermap_get (all_routes, | ||
1663 | &rm->sender); | ||
1664 | if ( (NULL == route) && | ||
1665 | (distance < DEFAULT_FISHEYE_DEPTH) ) | ||
1666 | { | ||
1667 | /* don't have reverse route yet, learn it! */ | ||
1668 | target = GNUNET_new (struct Target); | ||
1669 | target->peer = rm->sender; | ||
1670 | target->distance = htonl (distance); | ||
1671 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1672 | "Learning sender %s at distance %u from delivery!\n", | ||
1673 | GNUNET_i2s (&rm->sender), | ||
1674 | (unsigned int) distance + 1); | ||
1675 | if (NULL == neighbor->neighbor_table) | ||
1676 | neighbor->neighbor_table = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | ||
1677 | if (GNUNET_YES != | ||
1678 | GNUNET_CONTAINER_multipeermap_put (neighbor->neighbor_table, | ||
1679 | &target->peer, | ||
1680 | target, | ||
1681 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
1682 | { | ||
1683 | GNUNET_break_op (0); | ||
1684 | GNUNET_free (target); | ||
1685 | return; | ||
1686 | } | ||
1687 | add_new_route (target, neighbor); | ||
1688 | } | ||
1689 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1690 | "Delivering %u bytes from %s to myself!\n", | ||
1691 | ntohs (payload->size), | ||
1692 | GNUNET_i2s (&rm->sender)); | ||
1693 | send_data_to_plugin (payload, | ||
1694 | &rm->sender, | ||
1695 | 1 + distance); | ||
1696 | return; | ||
1697 | } | ||
1698 | if ( (NULL == GNUNET_CONTAINER_multipeermap_get (direct_neighbors, | ||
1699 | &rm->sender)) && | ||
1700 | (NULL == GNUNET_CONTAINER_multipeermap_get (all_routes, | ||
1701 | &rm->sender)) ) | ||
1702 | { | ||
1703 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1704 | "Learning sender %s at distance %u from forwarding!\n", | ||
1705 | GNUNET_i2s (&rm->sender), | ||
1706 | 1 + distance); | ||
1707 | target = GNUNET_new (struct Target); | ||
1708 | target->peer = rm->sender; | ||
1709 | target->distance = htonl (distance); | ||
1710 | if (NULL == neighbor->neighbor_table) | ||
1711 | neighbor->neighbor_table = GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO); | ||
1712 | if (GNUNET_YES != | ||
1713 | GNUNET_CONTAINER_multipeermap_put (neighbor->neighbor_table, | ||
1714 | &target->peer, | ||
1715 | target, | ||
1716 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
1717 | { | ||
1718 | GNUNET_break_op (0); | ||
1719 | GNUNET_free (target); | ||
1720 | return; | ||
1721 | } | ||
1722 | add_new_route (target, neighbor); | ||
1723 | } | ||
1724 | |||
1725 | route = GNUNET_CONTAINER_multipeermap_get (all_routes, | ||
1726 | &rm->target); | ||
1727 | if (NULL == route) | ||
1728 | { | ||
1729 | nneighbor = GNUNET_CONTAINER_multipeermap_get (direct_neighbors, | ||
1730 | &rm->target); | ||
1731 | if (NULL == nneighbor) | ||
1732 | { | ||
1733 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1734 | "No route to %s, not routing %u bytes!\n", | ||
1735 | GNUNET_i2s (&rm->target), | ||
1736 | ntohs (payload->size)); | ||
1737 | GNUNET_STATISTICS_update (stats, | ||
1738 | "# messages discarded (no route)", | ||
1739 | 1, GNUNET_NO); | ||
1740 | return; | ||
1741 | } | ||
1742 | } | ||
1743 | else | ||
1744 | { | ||
1745 | nneighbor = route->next_hop; | ||
1746 | } | ||
1747 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1748 | "Forwarding message to %s\n", | ||
1749 | GNUNET_i2s (&nneighbor->peer)); | ||
1750 | forward_payload (nneighbor, | ||
1751 | distance + 1, | ||
1752 | &rm->sender, | ||
1753 | &rm->target, | ||
1754 | payload); | ||
1755 | } | ||
1756 | |||
1757 | |||
1758 | /** | ||
1759 | * Check that @a msg is well-formed | ||
1760 | * | ||
1761 | * @param cls identification of the client | ||
1762 | * @param message the actual message | ||
1763 | * @return #GNUNET_OK if @a msg is well-formed | ||
1764 | */ | ||
1765 | static int | ||
1766 | check_dv_send_message (void *cls, | ||
1767 | const struct GNUNET_DV_SendMessage *msg) | ||
1768 | { | ||
1769 | const struct GNUNET_MessageHeader *payload; | ||
1770 | |||
1771 | if (ntohs (msg->header.size) < sizeof (struct GNUNET_DV_SendMessage) + | ||
1772 | sizeof (struct GNUNET_MessageHeader)) | ||
1773 | { | ||
1774 | GNUNET_break (0); | ||
1775 | return GNUNET_SYSERR; | ||
1776 | } | ||
1777 | payload = (const struct GNUNET_MessageHeader *) &msg[1]; | ||
1778 | if (ntohs (msg->header.size) != sizeof (struct GNUNET_DV_SendMessage) + ntohs (payload->size)) | ||
1779 | { | ||
1780 | GNUNET_break (0); | ||
1781 | return GNUNET_SYSERR; | ||
1782 | } | ||
1783 | return GNUNET_OK; | ||
1784 | } | ||
1785 | |||
1786 | |||
1787 | /** | ||
1788 | * Service server's handler for message send requests (which come | ||
1789 | * bubbling up to us through the DV plugin). | ||
1790 | * | ||
1791 | * @param cls identification of the client | ||
1792 | * @param message the actual message | ||
1793 | */ | ||
1794 | static void | ||
1795 | handle_dv_send_message (void *cls, | ||
1796 | const struct GNUNET_DV_SendMessage *msg) | ||
1797 | { | ||
1798 | struct GNUNET_SERVICE_Client *client = cls; | ||
1799 | struct Route *route; | ||
1800 | const struct GNUNET_MessageHeader *payload; | ||
1801 | |||
1802 | payload = (const struct GNUNET_MessageHeader *) &msg[1]; | ||
1803 | route = GNUNET_CONTAINER_multipeermap_get (all_routes, | ||
1804 | &msg->target); | ||
1805 | if (NULL == route) | ||
1806 | { | ||
1807 | /* got disconnected */ | ||
1808 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1809 | "No route to %s, dropping local message of type %u\n", | ||
1810 | GNUNET_i2s (&msg->target), | ||
1811 | ntohs (payload->type)); | ||
1812 | GNUNET_STATISTICS_update (stats, | ||
1813 | "# local messages discarded (no route)", | ||
1814 | 1, GNUNET_NO); | ||
1815 | GNUNET_SERVICE_client_continue (client); | ||
1816 | return; | ||
1817 | } | ||
1818 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1819 | "Forwarding %u bytes of type %u to %s\n", | ||
1820 | ntohs (payload->size), | ||
1821 | ntohs (payload->type), | ||
1822 | GNUNET_i2s (&msg->target)); | ||
1823 | |||
1824 | forward_payload (route->next_hop, | ||
1825 | 0 /* first hop, distance is zero */, | ||
1826 | &my_identity, | ||
1827 | &msg->target, | ||
1828 | payload); | ||
1829 | GNUNET_SERVICE_client_continue (client); | ||
1830 | } | ||
1831 | |||
1832 | |||
1833 | /** | ||
1834 | * Cleanup all of the data structures associated with a given neighbor. | ||
1835 | * | ||
1836 | * @param neighbor neighbor to clean up | ||
1837 | */ | ||
1838 | static void | ||
1839 | cleanup_neighbor (struct DirectNeighbor *neighbor) | ||
1840 | { | ||
1841 | handle_direct_disconnect (neighbor); | ||
1842 | GNUNET_assert (GNUNET_YES == | ||
1843 | GNUNET_CONTAINER_multipeermap_remove (direct_neighbors, | ||
1844 | &neighbor->peer, | ||
1845 | neighbor)); | ||
1846 | GNUNET_free (neighbor); | ||
1847 | } | ||
1848 | |||
1849 | |||
1850 | /** | ||
1851 | * Method called whenever a given peer disconnects. | ||
1852 | * | ||
1853 | * @param cls closure | ||
1854 | * @param peer peer identity this notification is about | ||
1855 | * @param internal_cls the corresponding `struct DirectNeighbor` | ||
1856 | */ | ||
1857 | static void | ||
1858 | handle_core_disconnect (void *cls, | ||
1859 | const struct GNUNET_PeerIdentity *peer, | ||
1860 | void *internal_cls) | ||
1861 | { | ||
1862 | struct DirectNeighbor *neighbor = internal_cls; | ||
1863 | |||
1864 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1865 | "Received core peer disconnect message for peer `%s'!\n", | ||
1866 | GNUNET_i2s (peer)); | ||
1867 | /* Check for disconnect from self message */ | ||
1868 | if (NULL == neighbor) | ||
1869 | return; | ||
1870 | GNUNET_break (GNUNET_YES == neighbor->connected); | ||
1871 | neighbor->connected = GNUNET_NO; | ||
1872 | if (DIRECT_NEIGHBOR_COST == neighbor->distance) | ||
1873 | { | ||
1874 | GNUNET_STATISTICS_update (stats, | ||
1875 | "# peers connected (1-hop)", | ||
1876 | -1, | ||
1877 | GNUNET_NO); | ||
1878 | } | ||
1879 | cleanup_neighbor (neighbor); | ||
1880 | if (GNUNET_YES == in_shutdown) | ||
1881 | return; | ||
1882 | schedule_refresh_routes (); | ||
1883 | } | ||
1884 | |||
1885 | |||
1886 | /** | ||
1887 | * Multipeermap iterator for freeing routes. Should never be called. | ||
1888 | * | ||
1889 | * @param cls NULL | ||
1890 | * @param key key value stored under | ||
1891 | * @param value the route to be freed | ||
1892 | * @return #GNUNET_YES to continue iteration, #GNUNET_NO to stop | ||
1893 | */ | ||
1894 | static int | ||
1895 | free_route (void *cls, | ||
1896 | const struct GNUNET_PeerIdentity *key, | ||
1897 | void *value) | ||
1898 | { | ||
1899 | struct Route *route = value; | ||
1900 | |||
1901 | GNUNET_break (0); | ||
1902 | GNUNET_assert (GNUNET_YES == | ||
1903 | GNUNET_CONTAINER_multipeermap_remove (all_routes, key, value)); | ||
1904 | release_route (route); | ||
1905 | send_disconnect_to_plugin (&route->target.peer); | ||
1906 | GNUNET_free (route); | ||
1907 | return GNUNET_YES; | ||
1908 | } | ||
1909 | |||
1910 | |||
1911 | /** | ||
1912 | * Multipeermap iterator for freeing direct neighbors. Should never be called. | ||
1913 | * | ||
1914 | * @param cls NULL | ||
1915 | * @param key key value stored under | ||
1916 | * @param value the direct neighbor to be freed | ||
1917 | * @return #GNUNET_YES to continue iteration, #GNUNET_NO to stop | ||
1918 | */ | ||
1919 | static int | ||
1920 | free_direct_neighbors (void *cls, | ||
1921 | const struct GNUNET_PeerIdentity *key, | ||
1922 | void *value) | ||
1923 | { | ||
1924 | struct DirectNeighbor *neighbor = value; | ||
1925 | |||
1926 | cleanup_neighbor (neighbor); | ||
1927 | return GNUNET_YES; | ||
1928 | } | ||
1929 | |||
1930 | |||
1931 | /** | ||
1932 | * Task run during shutdown. | ||
1933 | * | ||
1934 | * @param cls unused | ||
1935 | */ | ||
1936 | static void | ||
1937 | shutdown_task (void *cls) | ||
1938 | { | ||
1939 | unsigned int i; | ||
1940 | |||
1941 | in_shutdown = GNUNET_YES; | ||
1942 | GNUNET_assert (NULL != core_api); | ||
1943 | GNUNET_CORE_disconnect (core_api); | ||
1944 | core_api = NULL; | ||
1945 | GNUNET_ATS_performance_done (ats); | ||
1946 | ats = NULL; | ||
1947 | GNUNET_CONTAINER_multipeermap_iterate (direct_neighbors, | ||
1948 | &free_direct_neighbors, | ||
1949 | NULL); | ||
1950 | GNUNET_CONTAINER_multipeermap_iterate (all_routes, | ||
1951 | &free_route, | ||
1952 | NULL); | ||
1953 | GNUNET_CONTAINER_multipeermap_destroy (direct_neighbors); | ||
1954 | GNUNET_CONTAINER_multipeermap_destroy (all_routes); | ||
1955 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
1956 | stats = NULL; | ||
1957 | GNUNET_notification_context_destroy (nc); | ||
1958 | nc = NULL; | ||
1959 | for (i=0;i<DEFAULT_FISHEYE_DEPTH;i++) | ||
1960 | { | ||
1961 | GNUNET_array_grow (consensi[i].targets, | ||
1962 | consensi[i].array_length, | ||
1963 | 0); | ||
1964 | } | ||
1965 | if (NULL != rr_task) | ||
1966 | { | ||
1967 | GNUNET_SCHEDULER_cancel (rr_task); | ||
1968 | rr_task = NULL; | ||
1969 | } | ||
1970 | } | ||
1971 | |||
1972 | |||
1973 | /** | ||
1974 | * Notify newly connected client about an existing route. | ||
1975 | * | ||
1976 | * @param cls the `struct GNUNET_SERVICE_Client *` | ||
1977 | * @param key peer identity | ||
1978 | * @param value the `struct Route *` | ||
1979 | * @return #GNUNET_OK (continue to iterate) | ||
1980 | */ | ||
1981 | static int | ||
1982 | notify_client_about_route (void *cls, | ||
1983 | const struct GNUNET_PeerIdentity *key, | ||
1984 | void *value) | ||
1985 | { | ||
1986 | struct GNUNET_SERVICE_Client *client = cls; | ||
1987 | struct Route *route = value; | ||
1988 | struct GNUNET_MQ_Envelope *env; | ||
1989 | struct GNUNET_DV_ConnectMessage *cm; | ||
1990 | |||
1991 | env = GNUNET_MQ_msg (cm, | ||
1992 | GNUNET_MESSAGE_TYPE_DV_CONNECT); | ||
1993 | cm->distance = htonl (route->target.distance); | ||
1994 | cm->peer = route->target.peer; | ||
1995 | GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), | ||
1996 | env); | ||
1997 | return GNUNET_OK; | ||
1998 | } | ||
1999 | |||
2000 | |||
2001 | /** | ||
2002 | * Handle START-message. This is the first message sent to us | ||
2003 | * by the client (can only be one!). | ||
2004 | * | ||
2005 | * @param cls closure (always NULL) | ||
2006 | * @param client identification of the client | ||
2007 | * @param message the actual message | ||
2008 | */ | ||
2009 | static void | ||
2010 | handle_start (void *cls, | ||
2011 | const struct GNUNET_MessageHeader *message) | ||
2012 | { | ||
2013 | struct GNUNET_SERVICE_Client *client = cls; | ||
2014 | |||
2015 | GNUNET_notification_context_add (nc, | ||
2016 | GNUNET_SERVICE_client_get_mq (client)); | ||
2017 | GNUNET_SERVICE_client_continue (client); | ||
2018 | GNUNET_CONTAINER_multipeermap_iterate (all_routes, | ||
2019 | ¬ify_client_about_route, | ||
2020 | client); | ||
2021 | } | ||
2022 | |||
2023 | |||
2024 | /** | ||
2025 | * Called on core init. | ||
2026 | * | ||
2027 | * @param cls unused | ||
2028 | * @param identity this peer's identity | ||
2029 | */ | ||
2030 | static void | ||
2031 | core_init (void *cls, | ||
2032 | const struct GNUNET_PeerIdentity *identity) | ||
2033 | { | ||
2034 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2035 | "I am peer: %s\n", | ||
2036 | GNUNET_i2s (identity)); | ||
2037 | my_identity = *identity; | ||
2038 | } | ||
2039 | |||
2040 | |||
2041 | /** | ||
2042 | * Process dv requests. | ||
2043 | * | ||
2044 | * @param cls closure | ||
2045 | * @param c configuration to use | ||
2046 | * @param service the initialized service | ||
2047 | */ | ||
2048 | static void | ||
2049 | run (void *cls, | ||
2050 | const struct GNUNET_CONFIGURATION_Handle *c, | ||
2051 | struct GNUNET_SERVICE_Handle *service) | ||
2052 | { | ||
2053 | struct GNUNET_MQ_MessageHandler core_handlers[] = { | ||
2054 | GNUNET_MQ_hd_var_size (dv_route_message, | ||
2055 | GNUNET_MESSAGE_TYPE_DV_ROUTE, | ||
2056 | struct RouteMessage, | ||
2057 | NULL), | ||
2058 | GNUNET_MQ_handler_end () | ||
2059 | }; | ||
2060 | in_shutdown = GNUNET_NO; | ||
2061 | cfg = c; | ||
2062 | direct_neighbors = GNUNET_CONTAINER_multipeermap_create (128, | ||
2063 | GNUNET_NO); | ||
2064 | all_routes = GNUNET_CONTAINER_multipeermap_create (65536, | ||
2065 | GNUNET_NO); | ||
2066 | core_api = GNUNET_CORE_connect (cfg, | ||
2067 | NULL, | ||
2068 | &core_init, | ||
2069 | &handle_core_connect, | ||
2070 | &handle_core_disconnect, | ||
2071 | core_handlers); | ||
2072 | |||
2073 | if (NULL == core_api) | ||
2074 | return; | ||
2075 | ats = GNUNET_ATS_performance_init (cfg, | ||
2076 | &handle_ats_update, | ||
2077 | NULL); | ||
2078 | if (NULL == ats) | ||
2079 | { | ||
2080 | GNUNET_CORE_disconnect (core_api); | ||
2081 | core_api = NULL; | ||
2082 | return; | ||
2083 | } | ||
2084 | nc = GNUNET_notification_context_create (MAX_QUEUE_SIZE_PLUGIN); | ||
2085 | stats = GNUNET_STATISTICS_create ("dv", | ||
2086 | cfg); | ||
2087 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, | ||
2088 | NULL); | ||
2089 | } | ||
2090 | |||
2091 | |||
2092 | /** | ||
2093 | * Callback called when a client connects to the service. | ||
2094 | * | ||
2095 | * @param cls closure for the service | ||
2096 | * @param c the new client that connected to the service | ||
2097 | * @param mq the message queue used to send messages to the client | ||
2098 | * @return @a c | ||
2099 | */ | ||
2100 | static void * | ||
2101 | client_connect_cb (void *cls, | ||
2102 | struct GNUNET_SERVICE_Client *c, | ||
2103 | struct GNUNET_MQ_Handle *mq) | ||
2104 | { | ||
2105 | return c; | ||
2106 | } | ||
2107 | |||
2108 | |||
2109 | /** | ||
2110 | * Callback called when a client disconnected from the service | ||
2111 | * | ||
2112 | * @param cls closure for the service | ||
2113 | * @param c the client that disconnected | ||
2114 | * @param internal_cls should be equal to @a c | ||
2115 | */ | ||
2116 | static void | ||
2117 | client_disconnect_cb (void *cls, | ||
2118 | struct GNUNET_SERVICE_Client *c, | ||
2119 | void *internal_cls) | ||
2120 | { | ||
2121 | GNUNET_assert (c == internal_cls); | ||
2122 | } | ||
2123 | |||
2124 | |||
2125 | /** | ||
2126 | * Define "main" method using service macro. | ||
2127 | */ | ||
2128 | GNUNET_SERVICE_MAIN | ||
2129 | ("dv", | ||
2130 | GNUNET_SERVICE_OPTION_NONE, | ||
2131 | &run, | ||
2132 | &client_connect_cb, | ||
2133 | &client_disconnect_cb, | ||
2134 | NULL, | ||
2135 | GNUNET_MQ_hd_fixed_size (start, | ||
2136 | GNUNET_MESSAGE_TYPE_DV_START, | ||
2137 | struct GNUNET_MessageHeader, | ||
2138 | NULL), | ||
2139 | GNUNET_MQ_hd_var_size (dv_send_message, | ||
2140 | GNUNET_MESSAGE_TYPE_DV_SEND, | ||
2141 | struct GNUNET_DV_SendMessage, | ||
2142 | NULL), | ||
2143 | GNUNET_MQ_handler_end ()); | ||
2144 | |||
2145 | |||
2146 | /* end of gnunet-service-dv.c */ | ||
diff --git a/src/dv/plugin_transport_dv.c b/src/dv/plugin_transport_dv.c deleted file mode 100644 index a99c170d7..000000000 --- a/src/dv/plugin_transport_dv.c +++ /dev/null | |||
@@ -1,910 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2002--2014 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file dv/plugin_transport_dv.c | ||
23 | * @brief DV transport service, takes incoming DV requests and deals with | ||
24 | * the DV service | ||
25 | * @author Nathan Evans | ||
26 | * @author Christian Grothoff | ||
27 | */ | ||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_protocols.h" | ||
31 | #include "gnunet_statistics_service.h" | ||
32 | #include "gnunet_dv_service.h" | ||
33 | #include "gnunet_transport_service.h" | ||
34 | #include "gnunet_transport_plugin.h" | ||
35 | #include "dv.h" | ||
36 | |||
37 | |||
38 | #define LOG(kind,...) GNUNET_log_from (kind, "transport-dv",__VA_ARGS__) | ||
39 | |||
40 | |||
41 | /** | ||
42 | * Encapsulation of all of the state of the plugin. | ||
43 | */ | ||
44 | struct Plugin; | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Session handle for connections. | ||
49 | */ | ||
50 | struct GNUNET_ATS_Session | ||
51 | { | ||
52 | /** | ||
53 | * Pointer to the global plugin struct. | ||
54 | */ | ||
55 | struct Plugin *plugin; | ||
56 | |||
57 | /** | ||
58 | * Address we use for the other peer. | ||
59 | */ | ||
60 | struct GNUNET_HELLO_Address *address; | ||
61 | |||
62 | /** | ||
63 | * To whom are we talking to. | ||
64 | */ | ||
65 | struct GNUNET_PeerIdentity sender; | ||
66 | |||
67 | /** | ||
68 | * Number of bytes waiting for transmission to this peer. | ||
69 | * FIXME: not set yet. | ||
70 | */ | ||
71 | unsigned long long bytes_in_queue; | ||
72 | |||
73 | /** | ||
74 | * Number of messages waiting for transmission to this peer. | ||
75 | * FIXME: not set yet. | ||
76 | */ | ||
77 | unsigned int msgs_in_queue; | ||
78 | |||
79 | /** | ||
80 | * Current distance to the given peer. | ||
81 | */ | ||
82 | uint32_t distance; | ||
83 | |||
84 | /** | ||
85 | * Current network the next hop peer is located in | ||
86 | */ | ||
87 | enum GNUNET_NetworkType network; | ||
88 | |||
89 | /** | ||
90 | * Does the transport service know about this session (and we thus | ||
91 | * need to call `session_end` when it is released?) | ||
92 | */ | ||
93 | int active; | ||
94 | |||
95 | }; | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Encapsulation of all of the state of the plugin. | ||
100 | */ | ||
101 | struct Plugin | ||
102 | { | ||
103 | /** | ||
104 | * Our environment. | ||
105 | */ | ||
106 | struct GNUNET_TRANSPORT_PluginEnvironment *env; | ||
107 | |||
108 | /** | ||
109 | * Hash map of sessions (active and inactive). | ||
110 | */ | ||
111 | struct GNUNET_CONTAINER_MultiPeerMap *sessions; | ||
112 | |||
113 | /** | ||
114 | * Copy of the handler array where the closures are | ||
115 | * set to this struct's instance. | ||
116 | */ | ||
117 | struct GNUNET_SERVER_MessageHandler *handlers; | ||
118 | |||
119 | /** | ||
120 | * Handle to the DV service | ||
121 | */ | ||
122 | struct GNUNET_DV_ServiceHandle *dvh; | ||
123 | |||
124 | /** | ||
125 | * Tokenizer for boxed messages. | ||
126 | */ | ||
127 | struct GNUNET_SERVER_MessageStreamTokenizer *mst; | ||
128 | |||
129 | /** | ||
130 | * Function to call about session status changes. | ||
131 | */ | ||
132 | GNUNET_TRANSPORT_SessionInfoCallback sic; | ||
133 | |||
134 | /** | ||
135 | * Closure for @e sic. | ||
136 | */ | ||
137 | void *sic_cls; | ||
138 | }; | ||
139 | |||
140 | |||
141 | /** | ||
142 | * If a session monitor is attached, notify it about the new | ||
143 | * session state. | ||
144 | * | ||
145 | * @param plugin our plugin | ||
146 | * @param session session that changed state | ||
147 | * @param state new state of the session | ||
148 | */ | ||
149 | static void | ||
150 | notify_session_monitor (struct Plugin *plugin, | ||
151 | struct GNUNET_ATS_Session *session, | ||
152 | enum GNUNET_TRANSPORT_SessionState state) | ||
153 | { | ||
154 | struct GNUNET_TRANSPORT_SessionInfo info; | ||
155 | |||
156 | if (NULL == plugin->sic) | ||
157 | return; | ||
158 | memset (&info, 0, sizeof (info)); | ||
159 | info.state = state; | ||
160 | info.is_inbound = GNUNET_SYSERR; /* hard to say */ | ||
161 | info.num_msg_pending = session->msgs_in_queue; | ||
162 | info.num_bytes_pending = session->bytes_in_queue; | ||
163 | /* info.receive_delay remains zero as this is not supported by DV | ||
164 | (cannot selectively not receive from 'core') */ | ||
165 | info.session_timeout = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
166 | info.address = session->address; | ||
167 | plugin->sic (plugin->sic_cls, | ||
168 | session, | ||
169 | &info); | ||
170 | } | ||
171 | |||
172 | |||
173 | /** | ||
174 | * Notify transport service about the change in distance. | ||
175 | * | ||
176 | * @param session session where the distance changed | ||
177 | */ | ||
178 | static void | ||
179 | notify_distance_change (struct GNUNET_ATS_Session *session) | ||
180 | { | ||
181 | struct Plugin *plugin = session->plugin; | ||
182 | |||
183 | if (GNUNET_YES != session->active) | ||
184 | return; | ||
185 | plugin->env->update_address_distance (plugin->env->cls, | ||
186 | session->address, | ||
187 | session->distance); | ||
188 | } | ||
189 | |||
190 | |||
191 | /** | ||
192 | * Function called by MST on each message from the box. | ||
193 | * | ||
194 | * @param cls closure with the `struct Plugin *` | ||
195 | * @param client identification of the client (with the 'struct GNUNET_ATS_Session') | ||
196 | * @param message the actual message | ||
197 | * @return #GNUNET_OK on success | ||
198 | */ | ||
199 | static int | ||
200 | unbox_cb (void *cls, | ||
201 | void *client, | ||
202 | const struct GNUNET_MessageHeader *message) | ||
203 | { | ||
204 | struct Plugin *plugin = cls; | ||
205 | struct GNUNET_ATS_Session *session = client; | ||
206 | |||
207 | session->active = GNUNET_YES; | ||
208 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
209 | "Delivering message of type %u with %u bytes from peer `%s'\n", | ||
210 | ntohs (message->type), | ||
211 | ntohs (message->size), | ||
212 | GNUNET_i2s (&session->sender)); | ||
213 | plugin->env->receive (plugin->env->cls, | ||
214 | session->address, | ||
215 | session, | ||
216 | message); | ||
217 | plugin->env->update_address_distance (plugin->env->cls, | ||
218 | session->address, | ||
219 | session->distance); | ||
220 | return GNUNET_OK; | ||
221 | } | ||
222 | |||
223 | |||
224 | /** | ||
225 | * Handler for messages received from the DV service. | ||
226 | * | ||
227 | * @param cls closure with the plugin | ||
228 | * @param sender sender of the message | ||
229 | * @param distance how far did the message travel | ||
230 | * @param msg actual message payload | ||
231 | */ | ||
232 | static void | ||
233 | handle_dv_message_received (void *cls, | ||
234 | const struct GNUNET_PeerIdentity *sender, | ||
235 | uint32_t distance, | ||
236 | const struct GNUNET_MessageHeader *msg) | ||
237 | { | ||
238 | struct Plugin *plugin = cls; | ||
239 | struct GNUNET_ATS_Session *session; | ||
240 | |||
241 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
242 | "Received DV_MESSAGE_RECEIVED message for peer `%s': new distance %u\n", | ||
243 | GNUNET_i2s (sender), | ||
244 | distance); | ||
245 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
246 | sender); | ||
247 | if (NULL == session) | ||
248 | { | ||
249 | GNUNET_break (0); | ||
250 | return; | ||
251 | } | ||
252 | if (GNUNET_MESSAGE_TYPE_DV_BOX == ntohs (msg->type)) | ||
253 | { | ||
254 | /* need to unbox using MST */ | ||
255 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
256 | "Unboxing DV message using MST\n"); | ||
257 | GNUNET_SERVER_mst_receive (plugin->mst, | ||
258 | session, | ||
259 | (const char *) &msg[1], | ||
260 | ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader), | ||
261 | GNUNET_YES, | ||
262 | GNUNET_NO); | ||
263 | return; | ||
264 | } | ||
265 | session->active = GNUNET_YES; | ||
266 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
267 | "Delivering message of type %u with %u bytes from peer `%s'\n", | ||
268 | ntohs (msg->type), | ||
269 | ntohs (msg->size), | ||
270 | GNUNET_i2s (sender)); | ||
271 | plugin->env->receive (plugin->env->cls, | ||
272 | session->address, | ||
273 | session, | ||
274 | msg); | ||
275 | plugin->env->update_address_distance (plugin->env->cls, | ||
276 | session->address, | ||
277 | session->distance); | ||
278 | } | ||
279 | |||
280 | |||
281 | /** | ||
282 | * Function called if DV starts to be able to talk to a peer. | ||
283 | * | ||
284 | * @param cls closure with `struct Plugin *` | ||
285 | * @param peer newly connected peer | ||
286 | * @param distance distance to the peer | ||
287 | * @param network the network the next hop is located in | ||
288 | */ | ||
289 | static void | ||
290 | handle_dv_connect (void *cls, | ||
291 | const struct GNUNET_PeerIdentity *peer, | ||
292 | uint32_t distance, | ||
293 | enum GNUNET_NetworkType network) | ||
294 | { | ||
295 | struct Plugin *plugin = cls; | ||
296 | struct GNUNET_ATS_Session *session; | ||
297 | |||
298 | GNUNET_break (GNUNET_NT_UNSPECIFIED != network); | ||
299 | /** | ||
300 | * This requires transport plugin to be linked to libgnunetats. | ||
301 | * If you remove it, also remove libgnunetats linkage from Makefile.am | ||
302 | */ | ||
303 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
304 | "Received DV_CONNECT message for peer `%s' with next hop in network %s\n", | ||
305 | GNUNET_i2s (peer), | ||
306 | GNUNET_NT_to_string (network)); | ||
307 | |||
308 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
309 | peer); | ||
310 | if (NULL != session) | ||
311 | { | ||
312 | GNUNET_break (0); | ||
313 | session->distance = distance; | ||
314 | notify_distance_change (session); | ||
315 | return; /* nothing to do */ | ||
316 | } | ||
317 | |||
318 | session = GNUNET_new (struct GNUNET_ATS_Session); | ||
319 | session->address = GNUNET_HELLO_address_allocate (peer, "dv", | ||
320 | NULL, 0, | ||
321 | GNUNET_HELLO_ADDRESS_INFO_NONE); | ||
322 | session->sender = *peer; | ||
323 | session->plugin = plugin; | ||
324 | session->distance = distance; | ||
325 | session->network = network; | ||
326 | GNUNET_assert(GNUNET_YES == | ||
327 | GNUNET_CONTAINER_multipeermap_put (plugin->sessions, | ||
328 | &session->sender, session, | ||
329 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
330 | |||
331 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
332 | "Creating new DV session %p for peer `%s' at distance %u\n", | ||
333 | session, | ||
334 | GNUNET_i2s (peer), | ||
335 | distance); | ||
336 | |||
337 | session->active = GNUNET_YES; | ||
338 | plugin->env->session_start (plugin->env->cls, | ||
339 | session->address, | ||
340 | session, | ||
341 | network); | ||
342 | plugin->env->update_address_distance (plugin->env->cls, | ||
343 | session->address, | ||
344 | session->distance); | ||
345 | |||
346 | notify_session_monitor (session->plugin, | ||
347 | session, | ||
348 | GNUNET_TRANSPORT_SS_UP); | ||
349 | } | ||
350 | |||
351 | |||
352 | /** | ||
353 | * Function called if DV distance to a peer is changed. | ||
354 | * | ||
355 | * @param cls closure with `struct Plugin *` | ||
356 | * @param peer connected peer | ||
357 | * @param distance new distance to the peer | ||
358 | * @param network network type used for the connection | ||
359 | */ | ||
360 | static void | ||
361 | handle_dv_distance_changed (void *cls, | ||
362 | const struct GNUNET_PeerIdentity *peer, | ||
363 | uint32_t distance, | ||
364 | enum GNUNET_NetworkType network) | ||
365 | { | ||
366 | struct Plugin *plugin = cls; | ||
367 | struct GNUNET_ATS_Session *session; | ||
368 | |||
369 | GNUNET_break (GNUNET_NT_UNSPECIFIED != network); | ||
370 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
371 | "Received `%s' message for peer `%s': new distance %u\n", | ||
372 | "DV_DISTANCE_CHANGED", | ||
373 | GNUNET_i2s (peer), | ||
374 | distance); | ||
375 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
376 | peer); | ||
377 | if (NULL == session) | ||
378 | { | ||
379 | GNUNET_break (0); | ||
380 | handle_dv_connect (plugin, peer, distance, network); | ||
381 | return; | ||
382 | } | ||
383 | session->distance = distance; | ||
384 | notify_distance_change (session); | ||
385 | } | ||
386 | |||
387 | |||
388 | /** | ||
389 | * Release session object and clean up associated resources. | ||
390 | * | ||
391 | * @param session session to clean up | ||
392 | */ | ||
393 | static void | ||
394 | free_session (struct GNUNET_ATS_Session *session) | ||
395 | { | ||
396 | struct Plugin *plugin = session->plugin; | ||
397 | |||
398 | GNUNET_assert (GNUNET_YES == | ||
399 | GNUNET_CONTAINER_multipeermap_remove (plugin->sessions, | ||
400 | &session->sender, | ||
401 | session)); | ||
402 | |||
403 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
404 | "Freeing session %p for peer `%s'\n", | ||
405 | session, | ||
406 | GNUNET_i2s (&session->sender)); | ||
407 | if (GNUNET_YES == session->active) | ||
408 | { | ||
409 | notify_session_monitor (session->plugin, | ||
410 | session, | ||
411 | GNUNET_TRANSPORT_SS_DONE); | ||
412 | plugin->env->session_end (plugin->env->cls, | ||
413 | session->address, | ||
414 | session); | ||
415 | session->active = GNUNET_NO; | ||
416 | } | ||
417 | GNUNET_HELLO_address_free (session->address); | ||
418 | GNUNET_free (session); | ||
419 | } | ||
420 | |||
421 | |||
422 | /** | ||
423 | * Function called if DV is no longer able to talk to a peer. | ||
424 | * | ||
425 | * @param cls closure with `struct Plugin *` | ||
426 | * @param peer peer that disconnected | ||
427 | */ | ||
428 | static void | ||
429 | handle_dv_disconnect (void *cls, | ||
430 | const struct GNUNET_PeerIdentity *peer) | ||
431 | { | ||
432 | struct Plugin *plugin = cls; | ||
433 | struct GNUNET_ATS_Session *session; | ||
434 | |||
435 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
436 | "Received `%s' message for peer `%s'\n", | ||
437 | "DV_DISCONNECT", | ||
438 | GNUNET_i2s (peer)); | ||
439 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
440 | peer); | ||
441 | if (NULL == session) | ||
442 | return; /* nothing to do */ | ||
443 | free_session (session); | ||
444 | } | ||
445 | |||
446 | |||
447 | /** | ||
448 | * Function that can be used by the transport service to transmit | ||
449 | * a message using the plugin. | ||
450 | * | ||
451 | * @param cls closure | ||
452 | * @param session the session used | ||
453 | * @param priority how important is the message | ||
454 | * @param msgbuf the message to transmit | ||
455 | * @param msgbuf_size number of bytes in 'msgbuf' | ||
456 | * @param timeout when should we time out | ||
457 | * @param cont continuation to call once the message has | ||
458 | * been transmitted (or if the transport is ready | ||
459 | * for the next transmission call; or if the | ||
460 | * peer disconnected...) | ||
461 | * @param cont_cls closure for @a cont | ||
462 | * @return number of bytes used (on the physical network, with overheads); | ||
463 | * -1 on hard errors (i.e. address invalid); 0 is a legal value | ||
464 | * and does NOT mean that the message was not transmitted (DV) | ||
465 | */ | ||
466 | static ssize_t | ||
467 | dv_plugin_send (void *cls, | ||
468 | struct GNUNET_ATS_Session *session, | ||
469 | const char *msgbuf, | ||
470 | size_t msgbuf_size, | ||
471 | unsigned int priority, | ||
472 | struct GNUNET_TIME_Relative timeout, | ||
473 | GNUNET_TRANSPORT_TransmitContinuation cont, | ||
474 | void *cont_cls) | ||
475 | { | ||
476 | struct Plugin *plugin = cls; | ||
477 | const struct GNUNET_MessageHeader *msg; | ||
478 | struct GNUNET_MessageHeader *box; | ||
479 | |||
480 | box = NULL; | ||
481 | msg = (const struct GNUNET_MessageHeader *) msgbuf; | ||
482 | if (ntohs (msg->size) != msgbuf_size) | ||
483 | { | ||
484 | /* need to box */ | ||
485 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
486 | "Boxing DV message\n"); | ||
487 | box = GNUNET_malloc (sizeof (struct GNUNET_MessageHeader) + msgbuf_size); | ||
488 | box->type = htons (GNUNET_MESSAGE_TYPE_DV_BOX); | ||
489 | box->size = htons (sizeof (struct GNUNET_MessageHeader) + msgbuf_size); | ||
490 | GNUNET_memcpy (&box[1], msgbuf, msgbuf_size); | ||
491 | msg = box; | ||
492 | } | ||
493 | GNUNET_DV_send (plugin->dvh, | ||
494 | &session->sender, | ||
495 | msg); | ||
496 | cont (cont_cls, | ||
497 | &session->sender, | ||
498 | GNUNET_OK, | ||
499 | msgbuf_size, 0); | ||
500 | GNUNET_free_non_null (box); | ||
501 | return 0; /* DV */ | ||
502 | } | ||
503 | |||
504 | |||
505 | /** | ||
506 | * Function that can be used to force the plugin to disconnect | ||
507 | * from the given peer and cancel all previous transmissions | ||
508 | * (and their continuations). | ||
509 | * | ||
510 | * @param cls closure with the `struct Plugin *` | ||
511 | * @param target peer from which to disconnect | ||
512 | */ | ||
513 | static void | ||
514 | dv_plugin_disconnect_peer (void *cls, | ||
515 | const struct GNUNET_PeerIdentity *target) | ||
516 | { | ||
517 | struct Plugin *plugin = cls; | ||
518 | struct GNUNET_ATS_Session *session; | ||
519 | |||
520 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
521 | target); | ||
522 | if (NULL == session) | ||
523 | return; /* nothing to do */ | ||
524 | session->active = GNUNET_NO; | ||
525 | } | ||
526 | |||
527 | |||
528 | /** | ||
529 | * Function that can be used to force the plugin to disconnect | ||
530 | * from the given peer and cancel all previous transmissions | ||
531 | * (and their continuations). | ||
532 | * | ||
533 | * @param cls closure with the `struct Plugin *` | ||
534 | * @param session which session to disconnect | ||
535 | * @return #GNUNET_OK | ||
536 | */ | ||
537 | static int | ||
538 | dv_plugin_disconnect_session (void *cls, | ||
539 | struct GNUNET_ATS_Session *session) | ||
540 | { | ||
541 | session->active = GNUNET_NO; | ||
542 | return GNUNET_OK; | ||
543 | } | ||
544 | |||
545 | |||
546 | /** | ||
547 | * Convert the transports address to a nice, human-readable | ||
548 | * format. | ||
549 | * | ||
550 | * @param cls closure | ||
551 | * @param type name of the transport that generated the address | ||
552 | * @param addr one of the addresses of the host, NULL for the last address | ||
553 | * the specific address format depends on the transport | ||
554 | * @param addrlen length of the address | ||
555 | * @param numeric should (IP) addresses be displayed in numeric form? | ||
556 | * @param timeout after how long should we give up? | ||
557 | * @param asc function to call on each string | ||
558 | * @param asc_cls closure for @a asc | ||
559 | */ | ||
560 | static void | ||
561 | dv_plugin_address_pretty_printer (void *cls, | ||
562 | const char *type, | ||
563 | const void *addr, | ||
564 | size_t addrlen, | ||
565 | int numeric, | ||
566 | struct GNUNET_TIME_Relative timeout, | ||
567 | GNUNET_TRANSPORT_AddressStringCallback asc, | ||
568 | void *asc_cls) | ||
569 | { | ||
570 | if ( (0 == addrlen) && | ||
571 | (0 == strcmp (type, "dv")) ) | ||
572 | asc (asc_cls, | ||
573 | "dv", | ||
574 | GNUNET_OK); | ||
575 | else | ||
576 | asc (asc_cls, | ||
577 | NULL, | ||
578 | GNUNET_SYSERR); | ||
579 | asc (asc_cls, | ||
580 | NULL, | ||
581 | GNUNET_OK); | ||
582 | } | ||
583 | |||
584 | |||
585 | /** | ||
586 | * Convert the DV address to a pretty string. | ||
587 | * | ||
588 | * @param cls closure | ||
589 | * @param addr the (hopefully) DV address | ||
590 | * @param addrlen the length of the @a addr | ||
591 | * @return string representing the DV address | ||
592 | */ | ||
593 | static const char * | ||
594 | dv_plugin_address_to_string (void *cls, | ||
595 | const void *addr, | ||
596 | size_t addrlen) | ||
597 | { | ||
598 | if (0 != addrlen) | ||
599 | { | ||
600 | GNUNET_break (0); /* malformed */ | ||
601 | return NULL; | ||
602 | } | ||
603 | return "dv"; | ||
604 | } | ||
605 | |||
606 | |||
607 | /** | ||
608 | * Another peer has suggested an address for this peer and transport | ||
609 | * plugin. Check that this could be a valid address. This function | ||
610 | * is not expected to 'validate' the address in the sense of trying to | ||
611 | * connect to it but simply to see if the binary format is technically | ||
612 | * legal for establishing a connection to this peer (and make sure that | ||
613 | * the address really corresponds to our network connection/settings | ||
614 | * and not some potential man-in-the-middle). | ||
615 | * | ||
616 | * @param cls closure | ||
617 | * @param addr pointer to the address | ||
618 | * @param addrlen length of @a addr | ||
619 | * @return #GNUNET_OK if this is a plausible address for this peer | ||
620 | * and transport, #GNUNET_SYSERR if not | ||
621 | * | ||
622 | */ | ||
623 | static int | ||
624 | dv_plugin_check_address (void *cls, | ||
625 | const void *addr, | ||
626 | size_t addrlen) | ||
627 | { | ||
628 | if (0 != addrlen) | ||
629 | return GNUNET_SYSERR; | ||
630 | return GNUNET_OK; | ||
631 | } | ||
632 | |||
633 | |||
634 | /** | ||
635 | * Create a new session to transmit data to the target | ||
636 | * This session will used to send data to this peer and the plugin will | ||
637 | * notify us by calling the env->session_end function | ||
638 | * | ||
639 | * @param cls the plugin | ||
640 | * @param address the address | ||
641 | * @return the session if the address is valid, NULL otherwise | ||
642 | */ | ||
643 | static struct GNUNET_ATS_Session * | ||
644 | dv_get_session (void *cls, | ||
645 | const struct GNUNET_HELLO_Address *address) | ||
646 | { | ||
647 | struct Plugin *plugin = cls; | ||
648 | struct GNUNET_ATS_Session *session; | ||
649 | |||
650 | if (0 != address->address_length) | ||
651 | return NULL; | ||
652 | session = GNUNET_CONTAINER_multipeermap_get (plugin->sessions, | ||
653 | &address->peer); | ||
654 | if (NULL == session) | ||
655 | return NULL; /* not valid right now */ | ||
656 | session->active = GNUNET_YES; | ||
657 | return session; | ||
658 | } | ||
659 | |||
660 | |||
661 | /** | ||
662 | * Function called to convert a string address to | ||
663 | * a binary address. | ||
664 | * | ||
665 | * @param cls closure ('struct Plugin*') | ||
666 | * @param addr string address | ||
667 | * @param addrlen length of the @a addr including \0 termination | ||
668 | * @param buf location to store the buffer | ||
669 | * If the function returns #GNUNET_SYSERR, its contents are undefined. | ||
670 | * @param added length of created address | ||
671 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure | ||
672 | */ | ||
673 | static int | ||
674 | dv_plugin_string_to_address (void *cls, | ||
675 | const char *addr, | ||
676 | uint16_t addrlen, | ||
677 | void **buf, | ||
678 | size_t *added) | ||
679 | { | ||
680 | if ( (addrlen == 3) && | ||
681 | (0 == strcmp ("dv", addr)) ) | ||
682 | { | ||
683 | *added = 0; | ||
684 | return GNUNET_OK; | ||
685 | } | ||
686 | return GNUNET_SYSERR; | ||
687 | } | ||
688 | |||
689 | |||
690 | /** | ||
691 | * Function that will be called whenever the transport service wants to | ||
692 | * notify the plugin that a session is still active and in use and | ||
693 | * therefore the session timeout for this session has to be updated | ||
694 | * | ||
695 | * @param cls closure (`struct Plugin *`) | ||
696 | * @param peer which peer was the session for | ||
697 | * @param session which session is being updated | ||
698 | */ | ||
699 | static void | ||
700 | dv_plugin_update_session_timeout (void *cls, | ||
701 | const struct GNUNET_PeerIdentity *peer, | ||
702 | struct GNUNET_ATS_Session *session) | ||
703 | { | ||
704 | /* DV currently doesn't time out like "normal" plugins, | ||
705 | so it should be safe to do nothing, right? | ||
706 | (or should we add an internal timeout?) */ | ||
707 | } | ||
708 | |||
709 | |||
710 | /** | ||
711 | * Function to obtain the network type for a session | ||
712 | * FIXME: we should probably look at the network type | ||
713 | * used by the next hop here. Or find some other way | ||
714 | * to properly allow ATS-DV resource allocation. | ||
715 | * | ||
716 | * @param cls closure (`struct Plugin *`) | ||
717 | * @param session the session | ||
718 | * @return the network type | ||
719 | */ | ||
720 | static enum GNUNET_NetworkType | ||
721 | dv_get_network (void *cls, | ||
722 | struct GNUNET_ATS_Session *session) | ||
723 | { | ||
724 | GNUNET_assert (NULL != session); | ||
725 | return session->network; | ||
726 | } | ||
727 | |||
728 | |||
729 | /** | ||
730 | * Function obtain the network type for an address. | ||
731 | * | ||
732 | * @param cls closure (`struct Plugin *`) | ||
733 | * @param address the address | ||
734 | * @return the network type | ||
735 | */ | ||
736 | static enum GNUNET_NetworkType | ||
737 | dv_plugin_get_network_for_address (void *cls, | ||
738 | const struct GNUNET_HELLO_Address *address) | ||
739 | { | ||
740 | return GNUNET_NT_WAN; /* FOR NOW */ | ||
741 | } | ||
742 | |||
743 | |||
744 | /** | ||
745 | * Function that is called to get the keepalive factor. | ||
746 | * #GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT is divided by this number to | ||
747 | * calculate the interval between keepalive packets. | ||
748 | * | ||
749 | * @param cls closure with the `struct Plugin` | ||
750 | * @return keepalive factor | ||
751 | */ | ||
752 | static unsigned int | ||
753 | dv_plugin_query_keepalive_factor (void *cls) | ||
754 | { | ||
755 | return 3; | ||
756 | } | ||
757 | |||
758 | |||
759 | /** | ||
760 | * Return information about the given session to the | ||
761 | * monitor callback. | ||
762 | * | ||
763 | * @param cls the `struct Plugin` with the monitor callback (`sic`) | ||
764 | * @param peer peer we send information about | ||
765 | * @param value our `struct GNUNET_ATS_Session` to send information about | ||
766 | * @return #GNUNET_OK (continue to iterate) | ||
767 | */ | ||
768 | static int | ||
769 | send_session_info_iter (void *cls, | ||
770 | const struct GNUNET_PeerIdentity *peer, | ||
771 | void *value) | ||
772 | { | ||
773 | struct Plugin *plugin = cls; | ||
774 | struct GNUNET_ATS_Session *session = value; | ||
775 | |||
776 | if (GNUNET_YES != session->active) | ||
777 | return GNUNET_OK; | ||
778 | notify_session_monitor (plugin, | ||
779 | session, | ||
780 | GNUNET_TRANSPORT_SS_UP); | ||
781 | return GNUNET_OK; | ||
782 | } | ||
783 | |||
784 | |||
785 | /** | ||
786 | * Begin monitoring sessions of a plugin. There can only | ||
787 | * be one active monitor per plugin (i.e. if there are | ||
788 | * multiple monitors, the transport service needs to | ||
789 | * multiplex the generated events over all of them). | ||
790 | * | ||
791 | * @param cls closure of the plugin | ||
792 | * @param sic callback to invoke, NULL to disable monitor; | ||
793 | * plugin will being by iterating over all active | ||
794 | * sessions immediately and then enter monitor mode | ||
795 | * @param sic_cls closure for @a sic | ||
796 | */ | ||
797 | static void | ||
798 | dv_plugin_setup_monitor (void *cls, | ||
799 | GNUNET_TRANSPORT_SessionInfoCallback sic, | ||
800 | void *sic_cls) | ||
801 | { | ||
802 | struct Plugin *plugin = cls; | ||
803 | |||
804 | plugin->sic = sic; | ||
805 | plugin->sic_cls = sic_cls; | ||
806 | if (NULL != sic) | ||
807 | { | ||
808 | GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions, | ||
809 | &send_session_info_iter, | ||
810 | plugin); | ||
811 | /* signal end of first iteration */ | ||
812 | sic (sic_cls, NULL, NULL); | ||
813 | } | ||
814 | } | ||
815 | |||
816 | |||
817 | /** | ||
818 | * Entry point for the plugin. | ||
819 | * | ||
820 | * @param cls closure with the plugin environment | ||
821 | * @return plugin API | ||
822 | */ | ||
823 | void * | ||
824 | libgnunet_plugin_transport_dv_init (void *cls) | ||
825 | { | ||
826 | struct GNUNET_TRANSPORT_PluginEnvironment *env = cls; | ||
827 | struct GNUNET_TRANSPORT_PluginFunctions *api; | ||
828 | struct Plugin *plugin; | ||
829 | |||
830 | plugin = GNUNET_new (struct Plugin); | ||
831 | plugin->env = env; | ||
832 | plugin->sessions = GNUNET_CONTAINER_multipeermap_create (1024 * 8, GNUNET_YES); | ||
833 | plugin->mst = GNUNET_SERVER_mst_create (&unbox_cb, | ||
834 | plugin); | ||
835 | plugin->dvh = GNUNET_DV_service_connect (env->cfg, | ||
836 | plugin, | ||
837 | &handle_dv_connect, | ||
838 | &handle_dv_distance_changed, | ||
839 | &handle_dv_disconnect, | ||
840 | &handle_dv_message_received); | ||
841 | if (NULL == plugin->dvh) | ||
842 | { | ||
843 | GNUNET_CONTAINER_multipeermap_destroy (plugin->sessions); | ||
844 | GNUNET_SERVER_mst_destroy (plugin->mst); | ||
845 | GNUNET_free (plugin); | ||
846 | return NULL; | ||
847 | } | ||
848 | api = GNUNET_new (struct GNUNET_TRANSPORT_PluginFunctions); | ||
849 | api->cls = plugin; | ||
850 | api->send = &dv_plugin_send; | ||
851 | api->disconnect_peer = &dv_plugin_disconnect_peer; | ||
852 | api->disconnect_session = &dv_plugin_disconnect_session; | ||
853 | api->address_pretty_printer = &dv_plugin_address_pretty_printer; | ||
854 | api->check_address = &dv_plugin_check_address; | ||
855 | api->address_to_string = &dv_plugin_address_to_string; | ||
856 | api->string_to_address = &dv_plugin_string_to_address; | ||
857 | api->query_keepalive_factor = &dv_plugin_query_keepalive_factor; | ||
858 | api->get_session = &dv_get_session; | ||
859 | api->get_network = &dv_get_network; | ||
860 | api->get_network_for_address = &dv_plugin_get_network_for_address; | ||
861 | api->update_session_timeout = &dv_plugin_update_session_timeout; | ||
862 | api->setup_monitor = &dv_plugin_setup_monitor; | ||
863 | return api; | ||
864 | } | ||
865 | |||
866 | |||
867 | /** | ||
868 | * Function called to free a session. | ||
869 | * | ||
870 | * @param cls NULL | ||
871 | * @param key unused | ||
872 | * @param value session to free | ||
873 | * @return #GNUNET_OK (continue to iterate) | ||
874 | */ | ||
875 | static int | ||
876 | free_session_iterator (void *cls, | ||
877 | const struct GNUNET_PeerIdentity *key, | ||
878 | void *value) | ||
879 | { | ||
880 | struct GNUNET_ATS_Session *session = value; | ||
881 | |||
882 | free_session (session); | ||
883 | return GNUNET_OK; | ||
884 | } | ||
885 | |||
886 | |||
887 | /** | ||
888 | * Exit point from the plugin. | ||
889 | * | ||
890 | * @param cls plugin API | ||
891 | * @return NULL | ||
892 | */ | ||
893 | void * | ||
894 | libgnunet_plugin_transport_dv_done (void *cls) | ||
895 | { | ||
896 | struct GNUNET_TRANSPORT_PluginFunctions *api = cls; | ||
897 | struct Plugin *plugin = api->cls; | ||
898 | |||
899 | GNUNET_DV_service_disconnect (plugin->dvh); | ||
900 | GNUNET_CONTAINER_multipeermap_iterate (plugin->sessions, | ||
901 | &free_session_iterator, | ||
902 | NULL); | ||
903 | GNUNET_CONTAINER_multipeermap_destroy (plugin->sessions); | ||
904 | GNUNET_SERVER_mst_destroy (plugin->mst); | ||
905 | GNUNET_free (plugin); | ||
906 | GNUNET_free (api); | ||
907 | return NULL; | ||
908 | } | ||
909 | |||
910 | /* end of plugin_transport_dv.c */ | ||
diff --git a/src/dv/template_dv.conf b/src/dv/template_dv.conf deleted file mode 100644 index d37154261..000000000 --- a/src/dv/template_dv.conf +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | # Peers: | ||
2 | # | ||
3 | # `G3FK2T8AMPJ0H556QXEYVTEW409BP3KHPCG99TV66V8NYAS1KEWG' | ||
4 | # `6DEVS8Y51AT0TGNNHR7A75H47XXYJEFRZXX5RVQ9Q6S7Z49SYXT0' | ||
5 | # `6YNBKM6TTK64FAG9DF0292AW5JA9CCAC04JTY0HF8XHP635HPBBG' | ||
6 | # `DK5WZKKDHH06BH1H0DE0Z8CPBTG9AD8P85SF02WW3285AT3V0V50' | ||
7 | # | ||
8 | |||
9 | [testbed] | ||
10 | OVERLAY_TOPOLOGY = CLIQUE | ||
11 | SETUP_TIMEOUT = 3 m | ||
12 | OPERATION_TIMEOUT = 30 s | ||
13 | CACHE_SIZE = 0 | ||
14 | |||
15 | [transport-blacklist-G3FK2T8AMPJ0H556QXEYVTEW409BP3KHPCG99TV66V8NYAS1KEWG] | ||
16 | 6DEVS8Y51AT0TGNNHR7A75H47XXYJEFRZXX5RVQ9Q6S7Z49SYXT0 = tcp | ||
17 | |||
18 | [transport-blacklist-6DEVS8Y51AT0TGNNHR7A75H47XXYJEFRZXX5RVQ9Q6S7Z49SYXT0] | ||
19 | G3FK2T8AMPJ0H556QXEYVTEW409BP3KHPCG99TV66V8NYAS1KEWG = tcp | ||
20 | |||
21 | [transport-blacklist-6YNBKM6TTK64FAG9DF0292AW5JA9CCAC04JTY0HF8XHP635HPBBG] | ||
22 | |||
23 | [transport-blacklist-DK5WZKKDHH06BH1H0DE0Z8CPBTG9AD8P85SF02WW3285AT3V0V50] | ||
24 | |||
25 | [PATHS] | ||
26 | GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-dv-testing/ | ||
27 | |||
28 | [peerinfo] | ||
29 | USE_INCLUDED_HELLOS = NO | ||
30 | |||
31 | [nat] | ||
32 | RETURN_LOCAL_ADDRESSES = YES | ||
33 | |||
diff --git a/src/dv/test_transport_blacklist.c b/src/dv/test_transport_blacklist.c deleted file mode 100644 index 4fc9b4908..000000000 --- a/src/dv/test_transport_blacklist.c +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009, 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file dv/test_transport_blacklist.c | ||
22 | * @brief base testcase for testing blacklist | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_core_service.h" | ||
26 | #include "gnunet_testbed_service.h" | ||
27 | |||
28 | /** | ||
29 | * Return value from main, set to 0 on success. | ||
30 | */ | ||
31 | static int ok; | ||
32 | |||
33 | |||
34 | static void | ||
35 | test_connection (void *cls, | ||
36 | struct GNUNET_TESTBED_RunHandle *h, | ||
37 | unsigned int num_peers, | ||
38 | struct GNUNET_TESTBED_Peer **peers, | ||
39 | unsigned int links_succeeded, | ||
40 | unsigned int links_failed) | ||
41 | { | ||
42 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Links successful %u / %u failed\n", links_succeeded, links_failed); | ||
43 | if ( (4 == num_peers) && (0 == links_failed) ) | ||
44 | { | ||
45 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
46 | "Testbed connect peers despite blacklist!\n"); | ||
47 | ok = 1; | ||
48 | } | ||
49 | else | ||
50 | { | ||
51 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
52 | "Note that getting a message about a timeout during setup is expected for this test.\n"); | ||
53 | } | ||
54 | GNUNET_SCHEDULER_shutdown (); | ||
55 | } | ||
56 | |||
57 | |||
58 | int | ||
59 | main (int argc, char *argv[]) | ||
60 | { | ||
61 | (void) GNUNET_TESTBED_test_run ("test-transport-blacklist", | ||
62 | "test_transport_blacklist_data.conf", | ||
63 | 4, | ||
64 | 0, NULL, NULL, | ||
65 | &test_connection, NULL); | ||
66 | return ok; | ||
67 | } | ||
68 | |||
69 | /* end of test_transport_blacklist.c */ | ||
diff --git a/src/dv/test_transport_blacklist_data.conf b/src/dv/test_transport_blacklist_data.conf deleted file mode 100644 index ea55a196b..000000000 --- a/src/dv/test_transport_blacklist_data.conf +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | @INLINE@ template_dv.conf | ||
2 | |||
3 | [transport] | ||
4 | PORT = 52565 | ||
5 | PLUGINS = tcp | ||
diff --git a/src/dv/test_transport_dv.c b/src/dv/test_transport_dv.c deleted file mode 100644 index 03b6087d5..000000000 --- a/src/dv/test_transport_dv.c +++ /dev/null | |||
@@ -1,131 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009, 2013 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your 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 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file dv/test_transport_dv.c | ||
22 | * @brief base testcase for testing distance vector transport | ||
23 | */ | ||
24 | #include "platform.h" | ||
25 | #include "gnunet_core_service.h" | ||
26 | #include "gnunet_testbed_service.h" | ||
27 | |||
28 | /** | ||
29 | * Return value from main, set to 0 on success. | ||
30 | */ | ||
31 | static int ok; | ||
32 | |||
33 | struct GNUNET_TESTBED_Operation *topology_op; | ||
34 | |||
35 | static struct GNUNET_SCHEDULER_Task * shutdown_task; | ||
36 | |||
37 | |||
38 | static void | ||
39 | do_shutdown (void *cls) | ||
40 | { | ||
41 | shutdown_task = NULL; | ||
42 | if (NULL != topology_op) | ||
43 | { | ||
44 | GNUNET_TESTBED_operation_done (topology_op); | ||
45 | topology_op = NULL; | ||
46 | } | ||
47 | } | ||
48 | |||
49 | |||
50 | static void | ||
51 | topology_completed (void *cls, | ||
52 | unsigned int nsuccess, | ||
53 | unsigned int nfailures) | ||
54 | { | ||
55 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
56 | "Links successful %u / %u failed\n", | ||
57 | nsuccess, | ||
58 | nfailures); | ||
59 | GNUNET_TESTBED_operation_done (topology_op); | ||
60 | topology_op = NULL; | ||
61 | |||
62 | if (nfailures > 0) | ||
63 | { | ||
64 | fprintf (stderr, | ||
65 | "Error: links successful %u but %u failed\n", | ||
66 | nsuccess, | ||
67 | nfailures); | ||
68 | ok = 1; | ||
69 | } | ||
70 | else | ||
71 | ok = 0; | ||
72 | |||
73 | GNUNET_SCHEDULER_shutdown (); | ||
74 | } | ||
75 | |||
76 | |||
77 | static void | ||
78 | test_connection (void *cls, | ||
79 | struct GNUNET_TESTBED_RunHandle *h, | ||
80 | unsigned int num_peers, | ||
81 | struct GNUNET_TESTBED_Peer **peers, | ||
82 | unsigned int links_succeeded, | ||
83 | unsigned int links_failed) | ||
84 | { | ||
85 | shutdown_task = GNUNET_SCHEDULER_add_shutdown (&do_shutdown, | ||
86 | NULL); | ||
87 | if (4 != num_peers) | ||
88 | { | ||
89 | ok = 1; | ||
90 | fprintf (stderr, | ||
91 | "Only %u out of 4 peers were started ...\n", | ||
92 | num_peers); | ||
93 | } | ||
94 | |||
95 | if (0 != links_failed) | ||
96 | { | ||
97 | /* All peers except DV peers are connected */ | ||
98 | fprintf (stderr, | ||
99 | "Testbed failed to connect peers (%u links OK, %u links failed)\n", | ||
100 | links_succeeded, | ||
101 | links_failed); | ||
102 | |||
103 | topology_op = GNUNET_TESTBED_overlay_configure_topology | ||
104 | (NULL, num_peers, peers, NULL, | ||
105 | &topology_completed, NULL, | ||
106 | GNUNET_TESTBED_TOPOLOGY_CLIQUE, | ||
107 | GNUNET_TESTBED_TOPOLOGY_OPTION_END); | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | ok = 1; | ||
112 | fprintf (stderr, | ||
113 | "Testbed connected peers, should not happen...\n"); | ||
114 | GNUNET_SCHEDULER_shutdown (); | ||
115 | } | ||
116 | |||
117 | |||
118 | int | ||
119 | main (int argc, char *argv[]) | ||
120 | { | ||
121 | ok = 1; | ||
122 | /* Connecting initial topology */ | ||
123 | (void) GNUNET_TESTBED_test_run ("test-transport-dv", | ||
124 | "test_transport_dv_data.conf", | ||
125 | 4, | ||
126 | 0, NULL, NULL, | ||
127 | &test_connection, NULL); | ||
128 | return ok; | ||
129 | } | ||
130 | |||
131 | /* end of test_transport_dv.c */ | ||
diff --git a/src/dv/test_transport_dv_data.conf b/src/dv/test_transport_dv_data.conf deleted file mode 100644 index a21fba8a7..000000000 --- a/src/dv/test_transport_dv_data.conf +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | @INLINE@ template_dv.conf | ||
2 | |||
3 | [transport] | ||
4 | PORT = 52565 | ||
5 | PLUGINS = tcp dv | ||
6 | #PREFIX = valgrind --leak-check=full --track-fds=yes --leak-resolution=high | ||
7 | |||
8 | [dv] | ||
9 | START_ON_DEMAND = YES | ||
10 | # PREFIX = valgrind --leak-check=full --track-fds=yes --leak-resolution=high | ||
11 | |||
12 | [set] | ||
13 | START_ON_DEMAND = YES | ||
14 | # PREFIX = valgrind --leak-check=full --track-fds=yes --leak-resolution=high | ||
15 | |||
16 | [core] | ||
17 | # PREFIX = valgrind --leak-check=full --track-fds=yes --leak-resolution=high | ||
18 | |||
19 | |||
diff --git a/src/gns/test_gns_nick_shorten.conf b/src/gns/test_gns_nick_shorten.conf deleted file mode 100644 index 317477c80..000000000 --- a/src/gns/test_gns_nick_shorten.conf +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | @INLINE@ test_gns_defaults.conf | ||
2 | |||
3 | [PATHS] | ||
4 | GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-gns-peer-1/ | ||
5 | |||
6 | [dht] | ||
7 | START_ON_DEMAND = YES | ||
8 | |||
9 | [transport] | ||
10 | PLUGINS = | ||
11 | |||
12 | [gns] | ||
13 | #PREFIX = valgrind --leak-check=full --track-origins=yes | ||
14 | START_ON_DEMAND = YES | ||
15 | AUTO_IMPORT_PKEY = YES | ||
16 | MAX_PARALLEL_BACKGROUND_QUERIES = 10 | ||
17 | DEFAULT_LOOKUP_TIMEOUT = 15 s | ||
18 | RECORD_PUT_INTERVAL = 1 h | ||
19 | ZONE_PUBLISH_TIME_WINDOW = 1 h | ||
20 | DNS_ROOT=PD67SGHF3E0447TU9HADIVU9OM7V4QHTOG0EBU69TFRI2LG63DR0 | ||
21 | #USE_CACHE = NO | ||
22 | |||
23 | [revocation] | ||
24 | WORKBITS = 1 | ||
diff --git a/src/peerstore/Makefile.am b/src/peerstore/Makefile.am index 3aef05769..c6acdce56 100644 --- a/src/peerstore/Makefile.am +++ b/src/peerstore/Makefile.am | |||
@@ -107,7 +107,9 @@ check_PROGRAMS = \ | |||
107 | $(FLAT_TESTS) | 107 | $(FLAT_TESTS) |
108 | 108 | ||
109 | EXTRA_DIST = \ | 109 | EXTRA_DIST = \ |
110 | test_peerstore_api_data.conf | 110 | test_peerstore_api_data.conf \ |
111 | test_plugin_peerstore_flat.conf \ | ||
112 | test_plugin_peerstore_sqlite.conf | ||
111 | 113 | ||
112 | if ENABLE_TEST_RUN | 114 | if ENABLE_TEST_RUN |
113 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | 115 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; |
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am index 727bfb134..39e5f1574 100644 --- a/src/testing/Makefile.am +++ b/src/testing/Makefile.am | |||
@@ -95,4 +95,5 @@ test_testing_sharedservices_LDADD = \ | |||
95 | $(top_builddir)/src/util/libgnunetutil.la | 95 | $(top_builddir)/src/util/libgnunetutil.la |
96 | 96 | ||
97 | EXTRA_DIST = \ | 97 | EXTRA_DIST = \ |
98 | test_testing_defaults.conf | 98 | test_testing_defaults.conf \ |
99 | test_testing_sharedservices.conf | ||