diff options
Diffstat (limited to 'src/topology')
-rw-r--r-- | src/topology/.gitignore | 2 | ||||
-rw-r--r-- | src/topology/Makefile.am | 61 | ||||
-rw-r--r-- | src/topology/friends.c | 246 | ||||
-rw-r--r-- | src/topology/gnunet-daemon-topology.c | 1155 | ||||
-rw-r--r-- | src/topology/test_gnunet_daemon_topology.c | 298 | ||||
-rw-r--r-- | src/topology/test_gnunet_daemon_topology_data.conf | 34 | ||||
-rw-r--r-- | src/topology/topology.conf | 8 |
7 files changed, 0 insertions, 1804 deletions
diff --git a/src/topology/.gitignore b/src/topology/.gitignore deleted file mode 100644 index cfa95ec7e..000000000 --- a/src/topology/.gitignore +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | gnunet-daemon-topology | ||
2 | test_gnunet_daemon_topology | ||
diff --git a/src/topology/Makefile.am b/src/topology/Makefile.am deleted file mode 100644 index e5920116b..000000000 --- a/src/topology/Makefile.am +++ /dev/null | |||
@@ -1,61 +0,0 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | if USE_COVERAGE | ||
5 | AM_CFLAGS = --coverage -O0 | ||
6 | endif | ||
7 | |||
8 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
9 | |||
10 | libexecdir= $(pkglibdir)/libexec/ | ||
11 | |||
12 | dist_pkgcfg_DATA = \ | ||
13 | topology.conf | ||
14 | |||
15 | |||
16 | lib_LTLIBRARIES = libgnunetfriends.la | ||
17 | |||
18 | libgnunetfriends_la_SOURCES = \ | ||
19 | friends.c | ||
20 | libgnunetfriends_la_LIBADD = \ | ||
21 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
22 | $(GN_LIBINTL) $(XLIB) | ||
23 | libgnunetfriends_la_LDFLAGS = \ | ||
24 | $(GN_LIB_LDFLAGS) \ | ||
25 | -version-info 0:0:0 | ||
26 | |||
27 | |||
28 | libexec_PROGRAMS = \ | ||
29 | gnunet-daemon-topology | ||
30 | |||
31 | gnunet_daemon_topology_SOURCES = \ | ||
32 | gnunet-daemon-topology.c | ||
33 | gnunet_daemon_topology_LDADD = \ | ||
34 | libgnunetfriends.la \ | ||
35 | $(top_builddir)/src/core/libgnunetcore.la \ | ||
36 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ | ||
37 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
38 | $(top_builddir)/src/transport/libgnunettransport.la \ | ||
39 | $(top_builddir)/src/ats/libgnunetats.la \ | ||
40 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
41 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
42 | $(GN_LIBINTL) | ||
43 | |||
44 | |||
45 | check_PROGRAMS = \ | ||
46 | test_gnunet_daemon_topology | ||
47 | |||
48 | if ENABLE_TEST_RUN | ||
49 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
50 | TESTS = $(check_PROGRAMS) | ||
51 | endif | ||
52 | |||
53 | test_gnunet_daemon_topology_SOURCES = \ | ||
54 | test_gnunet_daemon_topology.c | ||
55 | test_gnunet_daemon_topology_LDADD = \ | ||
56 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
57 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
58 | $(top_builddir)/src/util/libgnunetutil.la | ||
59 | |||
60 | EXTRA_DIST = \ | ||
61 | test_gnunet_daemon_topology_data.conf | ||
diff --git a/src/topology/friends.c b/src/topology/friends.c deleted file mode 100644 index 65c7e81d7..000000000 --- a/src/topology/friends.c +++ /dev/null | |||
@@ -1,246 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2013 Christian Grothoff | ||
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 topology/friends.c | ||
23 | * @brief library to read and write the FRIENDS file | ||
24 | * @author Christian Grothoff | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_friends_lib.h" | ||
28 | |||
29 | |||
30 | /** | ||
31 | * Parse the FRIENDS file. | ||
32 | * | ||
33 | * @param cfg our configuration | ||
34 | * @param cb function to call on each friend found | ||
35 | * @param cb_cls closure for @a cb | ||
36 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on parsing errors | ||
37 | */ | ||
38 | int | ||
39 | GNUNET_FRIENDS_parse (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
40 | GNUNET_FRIENDS_Callback cb, | ||
41 | void *cb_cls) | ||
42 | { | ||
43 | char *fn; | ||
44 | char *data; | ||
45 | size_t pos; | ||
46 | size_t start; | ||
47 | struct GNUNET_PeerIdentity pid; | ||
48 | uint64_t fsize; | ||
49 | ssize_t ssize; | ||
50 | |||
51 | if (GNUNET_OK != | ||
52 | GNUNET_CONFIGURATION_get_value_filename (cfg, | ||
53 | "TOPOLOGY", | ||
54 | "FRIENDS", | ||
55 | &fn)) | ||
56 | { | ||
57 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
58 | "topology", | ||
59 | "FRIENDS"); | ||
60 | return GNUNET_SYSERR; | ||
61 | } | ||
62 | if ((GNUNET_OK != | ||
63 | GNUNET_DISK_file_test (fn)) && | ||
64 | (GNUNET_OK != | ||
65 | GNUNET_DISK_fn_write (fn, | ||
66 | NULL, | ||
67 | 0, | ||
68 | GNUNET_DISK_PERM_USER_READ | ||
69 | | GNUNET_DISK_PERM_USER_WRITE | ||
70 | | GNUNET_DISK_OPEN_CREATE))) | ||
71 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, | ||
72 | "write", | ||
73 | fn); | ||
74 | if ((GNUNET_OK != | ||
75 | GNUNET_DISK_file_size (fn, | ||
76 | &fsize, | ||
77 | GNUNET_NO, | ||
78 | GNUNET_YES)) || | ||
79 | (0 == fsize)) | ||
80 | { | ||
81 | GNUNET_free (fn); | ||
82 | return GNUNET_OK; | ||
83 | } | ||
84 | data = GNUNET_malloc_large (fsize); | ||
85 | if (NULL == data) | ||
86 | { | ||
87 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "malloc"); | ||
88 | GNUNET_free (fn); | ||
89 | return GNUNET_SYSERR; | ||
90 | } | ||
91 | ssize = GNUNET_DISK_fn_read (fn, | ||
92 | data, | ||
93 | fsize); | ||
94 | if ((ssize < 0) || | ||
95 | (fsize != (uint64_t) ssize)) | ||
96 | { | ||
97 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, | ||
98 | "read", | ||
99 | "fn"); | ||
100 | GNUNET_free (fn); | ||
101 | GNUNET_free (data); | ||
102 | return GNUNET_SYSERR; | ||
103 | } | ||
104 | start = 0; | ||
105 | pos = 0; | ||
106 | while (pos < fsize) | ||
107 | { | ||
108 | while ((pos < fsize) && | ||
109 | (! isspace ((unsigned char) data[pos]))) | ||
110 | pos++; | ||
111 | if (GNUNET_OK != | ||
112 | GNUNET_CRYPTO_eddsa_public_key_from_string (&data[start], | ||
113 | pos - start, | ||
114 | &pid.public_key)) | ||
115 | { | ||
116 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
117 | _ ( | ||
118 | "Syntax error in FRIENDS file at offset %llu, skipping bytes `%.*s'.\n"), | ||
119 | (unsigned long long) pos, | ||
120 | (int) (pos - start), | ||
121 | &data[start]); | ||
122 | pos++; | ||
123 | start = pos; | ||
124 | continue; | ||
125 | } | ||
126 | pos++; | ||
127 | start = pos; | ||
128 | cb (cb_cls, &pid); | ||
129 | } | ||
130 | GNUNET_free (data); | ||
131 | GNUNET_free (fn); | ||
132 | return GNUNET_OK; | ||
133 | } | ||
134 | |||
135 | |||
136 | /** | ||
137 | * Handle for writing a friends file. | ||
138 | */ | ||
139 | struct GNUNET_FRIENDS_Writer | ||
140 | { | ||
141 | /** | ||
142 | * Handle to the file. | ||
143 | */ | ||
144 | struct GNUNET_DISK_FileHandle *fh; | ||
145 | }; | ||
146 | |||
147 | |||
148 | /** | ||
149 | * Start writing a fresh FRIENDS file. Will make a backup of the | ||
150 | * old one. | ||
151 | * | ||
152 | * @param cfg configuration to use. | ||
153 | * @return NULL on error | ||
154 | */ | ||
155 | struct GNUNET_FRIENDS_Writer * | ||
156 | GNUNET_FRIENDS_write_start (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
157 | { | ||
158 | struct GNUNET_FRIENDS_Writer *w; | ||
159 | char *fn; | ||
160 | |||
161 | if (GNUNET_OK != | ||
162 | GNUNET_CONFIGURATION_get_value_filename (cfg, "TOPOLOGY", "FRIENDS", &fn)) | ||
163 | { | ||
164 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
165 | "topology", "FRIENDS"); | ||
166 | return NULL; | ||
167 | } | ||
168 | if (GNUNET_OK != | ||
169 | GNUNET_DISK_directory_create_for_file (fn)) | ||
170 | { | ||
171 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
172 | _ ("Directory for file `%s' does not seem to be writable.\n"), | ||
173 | fn); | ||
174 | GNUNET_free (fn); | ||
175 | return NULL; | ||
176 | } | ||
177 | if (GNUNET_OK == GNUNET_DISK_file_test (fn)) | ||
178 | GNUNET_DISK_file_backup (fn); | ||
179 | w = GNUNET_new (struct GNUNET_FRIENDS_Writer); | ||
180 | w->fh = GNUNET_DISK_file_open (fn, | ||
181 | GNUNET_DISK_OPEN_CREATE | ||
182 | | GNUNET_DISK_OPEN_WRITE | ||
183 | | GNUNET_DISK_OPEN_FAILIFEXISTS, | ||
184 | GNUNET_DISK_PERM_USER_READ); | ||
185 | GNUNET_free (fn); | ||
186 | if (NULL == w->fh) | ||
187 | { | ||
188 | GNUNET_free (w); | ||
189 | return NULL; | ||
190 | } | ||
191 | return w; | ||
192 | } | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Finish writing out the friends file. | ||
197 | * | ||
198 | * @param w write handle | ||
199 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
200 | */ | ||
201 | int | ||
202 | GNUNET_FRIENDS_write_stop (struct GNUNET_FRIENDS_Writer *w) | ||
203 | { | ||
204 | int ret; | ||
205 | |||
206 | ret = GNUNET_DISK_file_close (w->fh); | ||
207 | GNUNET_free (w); | ||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | |||
212 | /** | ||
213 | * Add a friend to the friends file. | ||
214 | * | ||
215 | * @param w write handle | ||
216 | * @param friend_id friend to add | ||
217 | * @return #GNUNET_OK on success, #GNUNET_SYSERR on error | ||
218 | */ | ||
219 | int | ||
220 | GNUNET_FRIENDS_write (struct GNUNET_FRIENDS_Writer *w, | ||
221 | const struct GNUNET_PeerIdentity *friend_id) | ||
222 | { | ||
223 | char *buf; | ||
224 | char *ret; | ||
225 | size_t slen; | ||
226 | |||
227 | ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&friend_id->public_key); | ||
228 | GNUNET_asprintf (&buf, | ||
229 | "%s\n", | ||
230 | ret); | ||
231 | GNUNET_free (ret); | ||
232 | slen = strlen (buf); | ||
233 | if (slen != | ||
234 | GNUNET_DISK_file_write (w->fh, | ||
235 | buf, | ||
236 | slen)) | ||
237 | { | ||
238 | GNUNET_free (buf); | ||
239 | return GNUNET_SYSERR; | ||
240 | } | ||
241 | GNUNET_free (buf); | ||
242 | return GNUNET_OK; | ||
243 | } | ||
244 | |||
245 | |||
246 | /* end of friends.c */ | ||
diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c deleted file mode 100644 index b380c0bd4..000000000 --- a/src/topology/gnunet-daemon-topology.c +++ /dev/null | |||
@@ -1,1155 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2007-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 topology/gnunet-daemon-topology.c | ||
23 | * @brief code for maintaining the overlay topology | ||
24 | * @author Christian Grothoff | ||
25 | * | ||
26 | * This daemon combines three functions: | ||
27 | * - suggesting to ATS which peers we might want to connect to | ||
28 | * - enforcing the F2F restrictions (by blacklisting) | ||
29 | * - gossping HELLOs | ||
30 | * | ||
31 | * All three require similar information (who are our friends | ||
32 | * impacts connectivity suggestions; connectivity suggestions | ||
33 | * should consider blacklisting; connectivity suggestions | ||
34 | * should consider available/known HELLOs; gossip requires | ||
35 | * connectivity data; connectivity suggestions require | ||
36 | * connectivity data), which is why they are combined in this | ||
37 | * program. | ||
38 | */ | ||
39 | #include "platform.h" | ||
40 | #include "gnunet_util_lib.h" | ||
41 | #include "gnunet_friends_lib.h" | ||
42 | #include "gnunet_constants.h" | ||
43 | #include "gnunet_core_service.h" | ||
44 | #include "gnunet_protocols.h" | ||
45 | #include "gnunet_peerinfo_service.h" | ||
46 | #include "gnunet_statistics_service.h" | ||
47 | #include "gnunet_transport_service.h" | ||
48 | #include "gnunet_ats_service.h" | ||
49 | |||
50 | |||
51 | /** | ||
52 | * At what frequency do we sent HELLOs to a peer? | ||
53 | */ | ||
54 | #define HELLO_ADVERTISEMENT_MIN_FREQUENCY \ | ||
55 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) | ||
56 | |||
57 | /** | ||
58 | * After what time period do we expire the HELLO Bloom filter? | ||
59 | */ | ||
60 | #define HELLO_ADVERTISEMENT_MIN_REPEAT_FREQUENCY \ | ||
61 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 4) | ||
62 | |||
63 | |||
64 | /** | ||
65 | * Record for neighbours, friends and blacklisted peers. | ||
66 | */ | ||
67 | struct Peer | ||
68 | { | ||
69 | /** | ||
70 | * Which peer is this entry about? | ||
71 | */ | ||
72 | struct GNUNET_PeerIdentity pid; | ||
73 | |||
74 | /** | ||
75 | * Our handle for transmitting to this peer; NULL | ||
76 | * if peer is not connected. | ||
77 | */ | ||
78 | struct GNUNET_MQ_Handle *mq; | ||
79 | |||
80 | /** | ||
81 | * Pointer to the HELLO message of this peer; can be NULL. | ||
82 | */ | ||
83 | struct GNUNET_HELLO_Message *hello; | ||
84 | |||
85 | /** | ||
86 | * Bloom filter used to mark which peers already got the HELLO | ||
87 | * from this peer. | ||
88 | */ | ||
89 | struct GNUNET_CONTAINER_BloomFilter *filter; | ||
90 | |||
91 | /** | ||
92 | * Next time we are allowed to transmit a HELLO to this peer? | ||
93 | */ | ||
94 | struct GNUNET_TIME_Absolute next_hello_allowed; | ||
95 | |||
96 | /** | ||
97 | * When should we reset the bloom filter of this entry? | ||
98 | */ | ||
99 | struct GNUNET_TIME_Absolute filter_expiration; | ||
100 | |||
101 | /** | ||
102 | * ID of task we use to wait for the time to send the next HELLO | ||
103 | * to this peer. | ||
104 | */ | ||
105 | struct GNUNET_SCHEDULER_Task *hello_delay_task; | ||
106 | |||
107 | /** | ||
108 | * Handle for our connectivity suggestion for this peer. | ||
109 | */ | ||
110 | struct GNUNET_ATS_ConnectivitySuggestHandle *sh; | ||
111 | |||
112 | /** | ||
113 | * How much would we like to connect to this peer? | ||
114 | */ | ||
115 | uint32_t strength; | ||
116 | |||
117 | /** | ||
118 | * Is this peer listed here because it is a friend? | ||
119 | */ | ||
120 | int is_friend; | ||
121 | }; | ||
122 | |||
123 | |||
124 | /** | ||
125 | * Our peerinfo notification context. We use notification | ||
126 | * to instantly learn about new peers as they are discovered. | ||
127 | */ | ||
128 | static struct GNUNET_PEERINFO_NotifyContext *peerinfo_notify; | ||
129 | |||
130 | /** | ||
131 | * Our configuration. | ||
132 | */ | ||
133 | static const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
134 | |||
135 | /** | ||
136 | * Handle to the CORE service. | ||
137 | */ | ||
138 | static struct GNUNET_CORE_Handle *handle; | ||
139 | |||
140 | /** | ||
141 | * Handle to the PEERINFO service. | ||
142 | */ | ||
143 | static struct GNUNET_PEERINFO_Handle *pi; | ||
144 | |||
145 | /** | ||
146 | * Handle to the ATS service. | ||
147 | */ | ||
148 | static struct GNUNET_ATS_ConnectivityHandle *ats; | ||
149 | |||
150 | /** | ||
151 | * Identity of this peer. | ||
152 | */ | ||
153 | static struct GNUNET_PeerIdentity my_identity; | ||
154 | |||
155 | /** | ||
156 | * All of our friends, all of our current neighbours and all peers for | ||
157 | * which we have HELLOs. So pretty much everyone. Maps peer identities | ||
158 | * to `struct Peer *` values. | ||
159 | */ | ||
160 | static struct GNUNET_CONTAINER_MultiPeerMap *peers; | ||
161 | |||
162 | /** | ||
163 | * Handle for reporting statistics. | ||
164 | */ | ||
165 | static struct GNUNET_STATISTICS_Handle *stats; | ||
166 | |||
167 | /** | ||
168 | * Blacklist (NULL if we have none). | ||
169 | */ | ||
170 | static struct GNUNET_TRANSPORT_Blacklist *blacklist; | ||
171 | |||
172 | /** | ||
173 | * Task scheduled to asynchronously reconsider adding/removing | ||
174 | * peer connectivity suggestions. | ||
175 | */ | ||
176 | static struct GNUNET_SCHEDULER_Task *add_task; | ||
177 | |||
178 | /** | ||
179 | * Active HELLO offering to transport service. | ||
180 | */ | ||
181 | static struct GNUNET_TRANSPORT_OfferHelloHandle *oh; | ||
182 | |||
183 | /** | ||
184 | * Flag to disallow non-friend connections (pure F2F mode). | ||
185 | */ | ||
186 | static int friends_only; | ||
187 | |||
188 | /** | ||
189 | * Minimum number of friends to have in the | ||
190 | * connection set before we allow non-friends. | ||
191 | */ | ||
192 | static unsigned int minimum_friend_count; | ||
193 | |||
194 | /** | ||
195 | * Number of peers (friends and others) that we are currently connected to. | ||
196 | */ | ||
197 | static unsigned int connection_count; | ||
198 | |||
199 | /** | ||
200 | * Target number of connections. | ||
201 | */ | ||
202 | static unsigned int target_connection_count; | ||
203 | |||
204 | /** | ||
205 | * Number of friends that we are currently connected to. | ||
206 | */ | ||
207 | static unsigned int friend_count; | ||
208 | |||
209 | |||
210 | /** | ||
211 | * Function that decides if a connection is acceptable or not. | ||
212 | * If we have a blacklist, only friends are allowed, so the check | ||
213 | * is rather simple. | ||
214 | * | ||
215 | * @param cls closure | ||
216 | * @param pid peer to approve or disapprove | ||
217 | * @return #GNUNET_OK if the connection is allowed | ||
218 | */ | ||
219 | static int | ||
220 | blacklist_check (void *cls, const struct GNUNET_PeerIdentity *pid) | ||
221 | { | ||
222 | struct Peer *pos; | ||
223 | |||
224 | pos = GNUNET_CONTAINER_multipeermap_get (peers, pid); | ||
225 | if ((NULL != pos) && (GNUNET_YES == pos->is_friend)) | ||
226 | return GNUNET_OK; | ||
227 | GNUNET_STATISTICS_update (stats, | ||
228 | gettext_noop ("# peers blacklisted"), | ||
229 | 1, | ||
230 | GNUNET_NO); | ||
231 | return GNUNET_SYSERR; | ||
232 | } | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Whitelist all peers that we blacklisted; we've passed | ||
237 | * the minimum number of friends. | ||
238 | */ | ||
239 | static void | ||
240 | whitelist_peers () | ||
241 | { | ||
242 | if (NULL != blacklist) | ||
243 | { | ||
244 | GNUNET_TRANSPORT_blacklist_cancel (blacklist); | ||
245 | blacklist = NULL; | ||
246 | } | ||
247 | } | ||
248 | |||
249 | |||
250 | /** | ||
251 | * Free all resources associated with the given peer. | ||
252 | * | ||
253 | * @param cls closure (not used) | ||
254 | * @param pid identity of the peer | ||
255 | * @param value peer to free | ||
256 | * @return #GNUNET_YES (always: continue to iterate) | ||
257 | */ | ||
258 | static int | ||
259 | free_peer (void *cls, const struct GNUNET_PeerIdentity *pid, void *value) | ||
260 | { | ||
261 | struct Peer *pos = value; | ||
262 | |||
263 | GNUNET_break (NULL == pos->mq); | ||
264 | GNUNET_break (GNUNET_OK == | ||
265 | GNUNET_CONTAINER_multipeermap_remove (peers, pid, pos)); | ||
266 | if (NULL != pos->hello_delay_task) | ||
267 | { | ||
268 | GNUNET_SCHEDULER_cancel (pos->hello_delay_task); | ||
269 | pos->hello_delay_task = NULL; | ||
270 | } | ||
271 | if (NULL != pos->sh) | ||
272 | { | ||
273 | GNUNET_ATS_connectivity_suggest_cancel (pos->sh); | ||
274 | pos->sh = NULL; | ||
275 | } | ||
276 | if (NULL != pos->hello) | ||
277 | { | ||
278 | GNUNET_free (pos->hello); | ||
279 | pos->hello = NULL; | ||
280 | } | ||
281 | if (NULL != pos->filter) | ||
282 | { | ||
283 | GNUNET_CONTAINER_bloomfilter_free (pos->filter); | ||
284 | pos->filter = NULL; | ||
285 | } | ||
286 | GNUNET_free (pos); | ||
287 | return GNUNET_YES; | ||
288 | } | ||
289 | |||
290 | |||
291 | /** | ||
292 | * Recalculate how much we want to be connected to the specified peer | ||
293 | * and let ATS know about the result. | ||
294 | * | ||
295 | * @param pos peer to consider connecting to | ||
296 | */ | ||
297 | static void | ||
298 | attempt_connect (struct Peer *pos) | ||
299 | { | ||
300 | uint32_t strength; | ||
301 | |||
302 | if (0 == GNUNET_memcmp (&my_identity, &pos->pid)) | ||
303 | return; /* This is myself, nothing to do. */ | ||
304 | if (connection_count < target_connection_count) | ||
305 | strength = 1; | ||
306 | else | ||
307 | strength = 0; | ||
308 | if ((friend_count < minimum_friend_count) || (GNUNET_YES == friends_only)) | ||
309 | { | ||
310 | if (pos->is_friend) | ||
311 | strength += 10; /* urgently needed */ | ||
312 | else | ||
313 | strength = 0; /* disallowed */ | ||
314 | } | ||
315 | if (pos->is_friend) | ||
316 | strength *= 2; /* friends always count more */ | ||
317 | if (NULL != pos->mq) | ||
318 | strength *= 2; /* existing connections preferred */ | ||
319 | if (strength == pos->strength) | ||
320 | return; /* nothing to do */ | ||
321 | if (NULL != pos->sh) | ||
322 | { | ||
323 | GNUNET_ATS_connectivity_suggest_cancel (pos->sh); | ||
324 | pos->sh = NULL; | ||
325 | } | ||
326 | pos->strength = strength; | ||
327 | if (0 != strength) | ||
328 | { | ||
329 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
330 | "Asking to connect to `%s' with strength %u\n", | ||
331 | GNUNET_i2s (&pos->pid), | ||
332 | (unsigned int) strength); | ||
333 | GNUNET_STATISTICS_update (stats, | ||
334 | gettext_noop ("# connect requests issued to ATS"), | ||
335 | 1, | ||
336 | GNUNET_NO); | ||
337 | pos->sh = GNUNET_ATS_connectivity_suggest (ats, &pos->pid, strength); | ||
338 | } | ||
339 | } | ||
340 | |||
341 | |||
342 | /** | ||
343 | * Create a new entry in the peer list. | ||
344 | * | ||
345 | * @param peer identity of the new entry | ||
346 | * @param hello hello message, can be NULL | ||
347 | * @param is_friend is the new entry for a friend? | ||
348 | * @return the new entry | ||
349 | */ | ||
350 | static struct Peer * | ||
351 | make_peer (const struct GNUNET_PeerIdentity *peer, | ||
352 | const struct GNUNET_HELLO_Message *hello, | ||
353 | int is_friend) | ||
354 | { | ||
355 | struct Peer *ret; | ||
356 | |||
357 | ret = GNUNET_new (struct Peer); | ||
358 | ret->pid = *peer; | ||
359 | ret->is_friend = is_friend; | ||
360 | if (NULL != hello) | ||
361 | { | ||
362 | ret->hello = GNUNET_malloc (GNUNET_HELLO_size (hello)); | ||
363 | GNUNET_memcpy (ret->hello, hello, GNUNET_HELLO_size (hello)); | ||
364 | } | ||
365 | GNUNET_break (GNUNET_OK == | ||
366 | GNUNET_CONTAINER_multipeermap_put ( | ||
367 | peers, | ||
368 | peer, | ||
369 | ret, | ||
370 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | ||
371 | return ret; | ||
372 | } | ||
373 | |||
374 | |||
375 | /** | ||
376 | * Setup bloom filter for the given peer entry. | ||
377 | * | ||
378 | * @param peer entry to initialize | ||
379 | */ | ||
380 | static void | ||
381 | setup_filter (struct Peer *peer) | ||
382 | { | ||
383 | struct GNUNET_HashCode hc; | ||
384 | |||
385 | /* 2^{-5} chance of not sending a HELLO to a peer is | ||
386 | * acceptably small (if the filter is 50% full); | ||
387 | * 64 bytes of memory are small compared to the rest | ||
388 | * of the data structure and would only really become | ||
389 | * "useless" once a HELLO has been passed on to ~100 | ||
390 | * other peers, which is likely more than enough in | ||
391 | * any case; hence 64, 5 as bloomfilter parameters. */peer->filter = GNUNET_CONTAINER_bloomfilter_init (NULL, 64, 5); | ||
392 | peer->filter_expiration = | ||
393 | GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_REPEAT_FREQUENCY); | ||
394 | /* never send a peer its own HELLO */ | ||
395 | GNUNET_CRYPTO_hash (&peer->pid, sizeof(struct GNUNET_PeerIdentity), &hc); | ||
396 | GNUNET_CONTAINER_bloomfilter_add (peer->filter, &hc); | ||
397 | } | ||
398 | |||
399 | |||
400 | /** | ||
401 | * Closure for #find_advertisable_hello(). | ||
402 | */ | ||
403 | struct FindAdvHelloContext | ||
404 | { | ||
405 | /** | ||
406 | * Peer we want to advertise to. | ||
407 | */ | ||
408 | struct Peer *peer; | ||
409 | |||
410 | /** | ||
411 | * Where to store the result (peer selected for advertising). | ||
412 | */ | ||
413 | struct Peer *result; | ||
414 | |||
415 | /** | ||
416 | * Maximum HELLO size we can use right now. | ||
417 | */ | ||
418 | size_t max_size; | ||
419 | |||
420 | struct GNUNET_TIME_Relative next_adv; | ||
421 | }; | ||
422 | |||
423 | |||
424 | /** | ||
425 | * Find a peer that would be reasonable for advertising. | ||
426 | * | ||
427 | * @param cls closure | ||
428 | * @param pid identity of a peer | ||
429 | * @param value 'struct Peer*' for the peer we are considering | ||
430 | * @return #GNUNET_YES (continue iteration) | ||
431 | */ | ||
432 | static int | ||
433 | find_advertisable_hello (void *cls, | ||
434 | const struct GNUNET_PeerIdentity *pid, | ||
435 | void *value) | ||
436 | { | ||
437 | struct FindAdvHelloContext *fah = cls; | ||
438 | struct Peer *pos = value; | ||
439 | struct GNUNET_TIME_Relative rst_time; | ||
440 | struct GNUNET_HashCode hc; | ||
441 | size_t hs; | ||
442 | |||
443 | if (pos == fah->peer) | ||
444 | return GNUNET_YES; | ||
445 | if (pos->hello == NULL) | ||
446 | return GNUNET_YES; | ||
447 | rst_time = GNUNET_TIME_absolute_get_remaining (pos->filter_expiration); | ||
448 | if (0 == rst_time.rel_value_us) | ||
449 | { | ||
450 | /* time to discard... */ | ||
451 | GNUNET_CONTAINER_bloomfilter_free (pos->filter); | ||
452 | setup_filter (pos); | ||
453 | } | ||
454 | fah->next_adv = GNUNET_TIME_relative_min (rst_time, fah->next_adv); | ||
455 | hs = GNUNET_HELLO_size (pos->hello); | ||
456 | if (hs > fah->max_size) | ||
457 | return GNUNET_YES; | ||
458 | GNUNET_CRYPTO_hash (&fah->peer->pid, | ||
459 | sizeof(struct GNUNET_PeerIdentity), | ||
460 | &hc); | ||
461 | if (GNUNET_NO == GNUNET_CONTAINER_bloomfilter_test (pos->filter, &hc)) | ||
462 | fah->result = pos; | ||
463 | return GNUNET_YES; | ||
464 | } | ||
465 | |||
466 | |||
467 | /** | ||
468 | * Calculate when we would like to send the next HELLO to this | ||
469 | * peer and ask for it. | ||
470 | * | ||
471 | * @param cls for which peer to schedule the HELLO | ||
472 | */ | ||
473 | static void | ||
474 | schedule_next_hello (void *cls) | ||
475 | { | ||
476 | struct Peer *pl = cls; | ||
477 | struct FindAdvHelloContext fah; | ||
478 | struct GNUNET_MQ_Envelope *env; | ||
479 | size_t want; | ||
480 | struct GNUNET_TIME_Relative delay; | ||
481 | struct GNUNET_HashCode hc; | ||
482 | |||
483 | pl->hello_delay_task = NULL; | ||
484 | GNUNET_assert (NULL != pl->mq); | ||
485 | /* find applicable HELLOs */ | ||
486 | fah.peer = pl; | ||
487 | fah.result = NULL; | ||
488 | fah.max_size = GNUNET_MAX_MESSAGE_SIZE - 1; | ||
489 | fah.next_adv = GNUNET_TIME_UNIT_FOREVER_REL; | ||
490 | GNUNET_CONTAINER_multipeermap_iterate (peers, &find_advertisable_hello, &fah); | ||
491 | pl->hello_delay_task = | ||
492 | GNUNET_SCHEDULER_add_delayed (fah.next_adv, &schedule_next_hello, pl); | ||
493 | if (NULL == fah.result) | ||
494 | return; | ||
495 | delay = GNUNET_TIME_absolute_get_remaining (pl->next_hello_allowed); | ||
496 | if (0 != delay.rel_value_us) | ||
497 | return; | ||
498 | |||
499 | want = GNUNET_HELLO_size (fah.result->hello); | ||
500 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
501 | "Sending HELLO with %u bytes", | ||
502 | (unsigned int) want); | ||
503 | env = GNUNET_MQ_msg_copy (&fah.result->hello->header); | ||
504 | GNUNET_MQ_send (pl->mq, env); | ||
505 | |||
506 | /* avoid sending this one again soon */ | ||
507 | GNUNET_CRYPTO_hash (&pl->pid, sizeof(struct GNUNET_PeerIdentity), &hc); | ||
508 | GNUNET_CONTAINER_bloomfilter_add (fah.result->filter, &hc); | ||
509 | |||
510 | GNUNET_STATISTICS_update (stats, | ||
511 | gettext_noop ("# HELLO messages gossipped"), | ||
512 | 1, | ||
513 | GNUNET_NO); | ||
514 | /* prepare to send the next one */ | ||
515 | pl->next_hello_allowed = | ||
516 | GNUNET_TIME_relative_to_absolute (HELLO_ADVERTISEMENT_MIN_FREQUENCY); | ||
517 | if (NULL != pl->hello_delay_task) | ||
518 | GNUNET_SCHEDULER_cancel (pl->hello_delay_task); | ||
519 | pl->hello_delay_task = GNUNET_SCHEDULER_add_now (&schedule_next_hello, pl); | ||
520 | } | ||
521 | |||
522 | |||
523 | /** | ||
524 | * Cancel existing requests for sending HELLOs to this peer | ||
525 | * and recalculate when we should send HELLOs to it based | ||
526 | * on our current state (something changed!). | ||
527 | * | ||
528 | * @param cls closure `struct Peer` to skip, or NULL | ||
529 | * @param pid identity of a peer | ||
530 | * @param value `struct Peer *` for the peer | ||
531 | * @return #GNUNET_YES (always) | ||
532 | */ | ||
533 | static int | ||
534 | reschedule_hellos (void *cls, | ||
535 | const struct GNUNET_PeerIdentity *pid, | ||
536 | void *value) | ||
537 | { | ||
538 | struct Peer *peer = value; | ||
539 | struct Peer *skip = cls; | ||
540 | |||
541 | if (skip == peer) | ||
542 | return GNUNET_YES; | ||
543 | if (NULL == peer->mq) | ||
544 | return GNUNET_YES; | ||
545 | if (NULL != peer->hello_delay_task) | ||
546 | { | ||
547 | GNUNET_SCHEDULER_cancel (peer->hello_delay_task); | ||
548 | peer->hello_delay_task = NULL; | ||
549 | } | ||
550 | peer->hello_delay_task = | ||
551 | GNUNET_SCHEDULER_add_now (&schedule_next_hello, peer); | ||
552 | return GNUNET_YES; | ||
553 | } | ||
554 | |||
555 | |||
556 | /** | ||
557 | * Method called whenever a peer connects. | ||
558 | * | ||
559 | * @param cls closure | ||
560 | * @param peer peer identity this notification is about | ||
561 | * @param mq message queue for communicating with @a peer | ||
562 | * @return our `struct Peer` for @a peer | ||
563 | */ | ||
564 | static void * | ||
565 | connect_notify (void *cls, | ||
566 | const struct GNUNET_PeerIdentity *peer, | ||
567 | struct GNUNET_MQ_Handle *mq) | ||
568 | { | ||
569 | struct Peer *pos; | ||
570 | |||
571 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
572 | "Core told us that we are connecting to `%s'\n", | ||
573 | GNUNET_i2s (peer)); | ||
574 | if (0 == GNUNET_memcmp (&my_identity, peer)) | ||
575 | return NULL; | ||
576 | GNUNET_MQ_set_options (mq, GNUNET_MQ_PRIO_BEST_EFFORT); | ||
577 | connection_count++; | ||
578 | GNUNET_STATISTICS_set (stats, | ||
579 | gettext_noop ("# peers connected"), | ||
580 | connection_count, | ||
581 | GNUNET_NO); | ||
582 | pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); | ||
583 | if (NULL == pos) | ||
584 | { | ||
585 | pos = make_peer (peer, NULL, GNUNET_NO); | ||
586 | } | ||
587 | else | ||
588 | { | ||
589 | GNUNET_assert (NULL == pos->mq); | ||
590 | } | ||
591 | pos->mq = mq; | ||
592 | if (pos->is_friend) | ||
593 | { | ||
594 | friend_count++; | ||
595 | if ((friend_count == minimum_friend_count) && (GNUNET_YES != friends_only)) | ||
596 | whitelist_peers (); | ||
597 | GNUNET_STATISTICS_set (stats, | ||
598 | gettext_noop ("# friends connected"), | ||
599 | friend_count, | ||
600 | GNUNET_NO); | ||
601 | } | ||
602 | reschedule_hellos (NULL, peer, pos); | ||
603 | return pos; | ||
604 | } | ||
605 | |||
606 | |||
607 | /** | ||
608 | * Try to add more peers to our connection set. | ||
609 | * | ||
610 | * @param cls closure, not used | ||
611 | * @param pid identity of a peer | ||
612 | * @param value `struct Peer *` for the peer | ||
613 | * @return #GNUNET_YES (continue to iterate) | ||
614 | */ | ||
615 | static int | ||
616 | try_add_peers (void *cls, const struct GNUNET_PeerIdentity *pid, void *value) | ||
617 | { | ||
618 | struct Peer *pos = value; | ||
619 | |||
620 | attempt_connect (pos); | ||
621 | return GNUNET_YES; | ||
622 | } | ||
623 | |||
624 | |||
625 | /** | ||
626 | * Add peers and schedule connection attempt | ||
627 | * | ||
628 | * @param cls unused, NULL | ||
629 | */ | ||
630 | static void | ||
631 | add_peer_task (void *cls) | ||
632 | { | ||
633 | add_task = NULL; | ||
634 | |||
635 | GNUNET_CONTAINER_multipeermap_iterate (peers, &try_add_peers, NULL); | ||
636 | } | ||
637 | |||
638 | |||
639 | /** | ||
640 | * Method called whenever a peer disconnects. | ||
641 | * | ||
642 | * @param cls closure | ||
643 | * @param peer peer identity this notification is about | ||
644 | * @param internal_cls the `struct Peer` for this peer | ||
645 | */ | ||
646 | static void | ||
647 | disconnect_notify (void *cls, | ||
648 | const struct GNUNET_PeerIdentity *peer, | ||
649 | void *internal_cls) | ||
650 | { | ||
651 | struct Peer *pos = internal_cls; | ||
652 | |||
653 | if (NULL == pos) | ||
654 | return; /* myself, we're shutting down */ | ||
655 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
656 | "Core told us that we disconnected from `%s'\n", | ||
657 | GNUNET_i2s (peer)); | ||
658 | if (NULL == pos->mq) | ||
659 | { | ||
660 | GNUNET_break (0); | ||
661 | return; | ||
662 | } | ||
663 | pos->mq = NULL; | ||
664 | connection_count--; | ||
665 | if (NULL != pos->hello_delay_task) | ||
666 | { | ||
667 | GNUNET_SCHEDULER_cancel (pos->hello_delay_task); | ||
668 | pos->hello_delay_task = NULL; | ||
669 | } | ||
670 | GNUNET_STATISTICS_set (stats, | ||
671 | gettext_noop ("# peers connected"), | ||
672 | connection_count, | ||
673 | GNUNET_NO); | ||
674 | if (pos->is_friend) | ||
675 | { | ||
676 | friend_count--; | ||
677 | GNUNET_STATISTICS_set (stats, | ||
678 | gettext_noop ("# friends connected"), | ||
679 | friend_count, | ||
680 | GNUNET_NO); | ||
681 | } | ||
682 | if (((connection_count < target_connection_count) || | ||
683 | (friend_count < minimum_friend_count)) && | ||
684 | (NULL == add_task)) | ||
685 | add_task = GNUNET_SCHEDULER_add_now (&add_peer_task, NULL); | ||
686 | if ((friend_count < minimum_friend_count) && (NULL == blacklist)) | ||
687 | blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_check, NULL); | ||
688 | } | ||
689 | |||
690 | |||
691 | /** | ||
692 | * Iterator called on each address. | ||
693 | * | ||
694 | * @param cls flag that we will set if we see any addresses | ||
695 | * @param address the address of the peer | ||
696 | * @param expiration when will the given address expire | ||
697 | * @return #GNUNET_SYSERR always, to terminate iteration | ||
698 | */ | ||
699 | static int | ||
700 | address_iterator (void *cls, | ||
701 | const struct GNUNET_HELLO_Address *address, | ||
702 | struct GNUNET_TIME_Absolute expiration) | ||
703 | { | ||
704 | int *flag = cls; | ||
705 | |||
706 | *flag = GNUNET_YES; | ||
707 | return GNUNET_SYSERR; | ||
708 | } | ||
709 | |||
710 | |||
711 | /** | ||
712 | * We've gotten a HELLO from another peer. Consider it for | ||
713 | * advertising. | ||
714 | * | ||
715 | * @param hello the HELLO we got | ||
716 | */ | ||
717 | static void | ||
718 | consider_for_advertising (const struct GNUNET_HELLO_Message *hello) | ||
719 | { | ||
720 | int have_address; | ||
721 | struct GNUNET_PeerIdentity pid; | ||
722 | struct GNUNET_TIME_Absolute dt; | ||
723 | struct GNUNET_HELLO_Message *nh; | ||
724 | struct Peer *peer; | ||
725 | uint16_t size; | ||
726 | |||
727 | if (GNUNET_OK != GNUNET_HELLO_get_id (hello, &pid)) | ||
728 | { | ||
729 | GNUNET_break (0); | ||
730 | return; | ||
731 | } | ||
732 | if (0 == GNUNET_memcmp (&pid, &my_identity)) | ||
733 | return; /* that's me! */ | ||
734 | have_address = GNUNET_NO; | ||
735 | GNUNET_HELLO_iterate_addresses (hello, | ||
736 | GNUNET_NO, | ||
737 | &address_iterator, | ||
738 | &have_address); | ||
739 | if (GNUNET_NO == have_address) | ||
740 | return; /* no point in advertising this one... */ | ||
741 | peer = GNUNET_CONTAINER_multipeermap_get (peers, &pid); | ||
742 | if (NULL == peer) | ||
743 | { | ||
744 | peer = make_peer (&pid, hello, GNUNET_NO); | ||
745 | } | ||
746 | else if (NULL != peer->hello) | ||
747 | { | ||
748 | dt = GNUNET_HELLO_equals (peer->hello, hello, GNUNET_TIME_absolute_get ()); | ||
749 | if (dt.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us) | ||
750 | return; /* nothing new here */ | ||
751 | } | ||
752 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
753 | "Found HELLO from peer `%s' for advertising\n", | ||
754 | GNUNET_i2s (&pid)); | ||
755 | if (NULL != peer->hello) | ||
756 | { | ||
757 | nh = GNUNET_HELLO_merge (peer->hello, hello); | ||
758 | GNUNET_free (peer->hello); | ||
759 | peer->hello = nh; | ||
760 | } | ||
761 | else | ||
762 | { | ||
763 | size = GNUNET_HELLO_size (hello); | ||
764 | peer->hello = GNUNET_malloc (size); | ||
765 | GNUNET_memcpy (peer->hello, hello, size); | ||
766 | } | ||
767 | if (NULL != peer->filter) | ||
768 | { | ||
769 | GNUNET_CONTAINER_bloomfilter_free (peer->filter); | ||
770 | peer->filter = NULL; | ||
771 | } | ||
772 | setup_filter (peer); | ||
773 | /* since we have a new HELLO to pick from, re-schedule all | ||
774 | * HELLO requests that are not bound by the HELLO send rate! */ | ||
775 | GNUNET_CONTAINER_multipeermap_iterate (peers, &reschedule_hellos, peer); | ||
776 | } | ||
777 | |||
778 | |||
779 | /** | ||
780 | * PEERINFO calls this function to let us know about a possible peer | ||
781 | * that we might want to connect to. | ||
782 | * | ||
783 | * @param cls closure (not used) | ||
784 | * @param peer potential peer to connect to | ||
785 | * @param hello HELLO for this peer (or NULL) | ||
786 | * @param err_msg NULL if successful, otherwise contains error message | ||
787 | */ | ||
788 | static void | ||
789 | process_peer (void *cls, | ||
790 | const struct GNUNET_PeerIdentity *peer, | ||
791 | const struct GNUNET_HELLO_Message *hello, | ||
792 | const char *err_msg) | ||
793 | { | ||
794 | struct Peer *pos; | ||
795 | |||
796 | if (NULL != err_msg) | ||
797 | { | ||
798 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
799 | _ ("Error in communication with PEERINFO service: %s\n"), | ||
800 | err_msg); | ||
801 | GNUNET_PEERINFO_notify_cancel (peerinfo_notify); | ||
802 | peerinfo_notify = | ||
803 | GNUNET_PEERINFO_notify (cfg, GNUNET_NO, &process_peer, NULL); | ||
804 | return; | ||
805 | } | ||
806 | GNUNET_assert (NULL != peer); | ||
807 | if (0 == GNUNET_memcmp (&my_identity, peer)) | ||
808 | return; /* that's me! */ | ||
809 | if (NULL == hello) | ||
810 | { | ||
811 | /* free existing HELLO, if any */ | ||
812 | pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); | ||
813 | if (NULL != pos) | ||
814 | { | ||
815 | GNUNET_free (pos->hello); | ||
816 | pos->hello = NULL; | ||
817 | if (NULL != pos->filter) | ||
818 | { | ||
819 | GNUNET_CONTAINER_bloomfilter_free (pos->filter); | ||
820 | pos->filter = NULL; | ||
821 | } | ||
822 | if ((NULL == pos->mq) && (GNUNET_NO == pos->is_friend)) | ||
823 | free_peer (NULL, &pos->pid, pos); | ||
824 | } | ||
825 | return; | ||
826 | } | ||
827 | consider_for_advertising (hello); | ||
828 | pos = GNUNET_CONTAINER_multipeermap_get (peers, peer); | ||
829 | if (NULL == pos) | ||
830 | pos = make_peer (peer, hello, GNUNET_NO); | ||
831 | attempt_connect (pos); | ||
832 | } | ||
833 | |||
834 | |||
835 | /** | ||
836 | * Function called after #GNUNET_CORE_connect has succeeded | ||
837 | * (or failed for good). | ||
838 | * | ||
839 | * @param cls closure | ||
840 | * @param my_id ID of this peer, NULL if we failed | ||
841 | */ | ||
842 | static void | ||
843 | core_init (void *cls, const struct GNUNET_PeerIdentity *my_id) | ||
844 | { | ||
845 | if (NULL == my_id) | ||
846 | { | ||
847 | GNUNET_log ( | ||
848 | GNUNET_ERROR_TYPE_ERROR, | ||
849 | _ ("Failed to connect to core service, can not manage topology!\n")); | ||
850 | GNUNET_SCHEDULER_shutdown (); | ||
851 | return; | ||
852 | } | ||
853 | my_identity = *my_id; | ||
854 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "I am peer `%s'\n", GNUNET_i2s (my_id)); | ||
855 | peerinfo_notify = | ||
856 | GNUNET_PEERINFO_notify (cfg, GNUNET_NO, &process_peer, NULL); | ||
857 | } | ||
858 | |||
859 | |||
860 | /** | ||
861 | * Process friend found in FRIENDS file. | ||
862 | * | ||
863 | * @param cls pointer to an `unsigned int` to be incremented per friend found | ||
864 | * @param pid identity of the friend | ||
865 | */ | ||
866 | static void | ||
867 | handle_friend (void *cls, const struct GNUNET_PeerIdentity *pid) | ||
868 | { | ||
869 | unsigned int *entries_found = cls; | ||
870 | struct Peer *fl; | ||
871 | |||
872 | if (0 == GNUNET_memcmp (pid, &my_identity)) | ||
873 | { | ||
874 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
875 | _ ("Found myself `%s' in friend list (useless, ignored)\n"), | ||
876 | GNUNET_i2s (pid)); | ||
877 | return; | ||
878 | } | ||
879 | (*entries_found)++; | ||
880 | fl = make_peer (pid, NULL, GNUNET_YES); | ||
881 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
882 | _ ("Found friend `%s' in configuration\n"), | ||
883 | GNUNET_i2s (&fl->pid)); | ||
884 | } | ||
885 | |||
886 | |||
887 | /** | ||
888 | * Read the friends file. | ||
889 | */ | ||
890 | static void | ||
891 | read_friends_file (const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
892 | { | ||
893 | unsigned int entries_found; | ||
894 | |||
895 | entries_found = 0; | ||
896 | if (GNUNET_OK != GNUNET_FRIENDS_parse (cfg, &handle_friend, &entries_found)) | ||
897 | { | ||
898 | if ((GNUNET_YES == friends_only) || (minimum_friend_count > 0)) | ||
899 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
900 | _ ("Encountered errors parsing friends list!\n")); | ||
901 | } | ||
902 | GNUNET_STATISTICS_update (stats, | ||
903 | gettext_noop ("# friends in configuration"), | ||
904 | entries_found, | ||
905 | GNUNET_NO); | ||
906 | if ((minimum_friend_count > entries_found) && (GNUNET_NO == friends_only)) | ||
907 | { | ||
908 | GNUNET_log ( | ||
909 | GNUNET_ERROR_TYPE_WARNING, | ||
910 | _ ( | ||
911 | "Fewer friends specified than required by minimum friend count. Will only connect to friends.\n")); | ||
912 | } | ||
913 | if ((minimum_friend_count > target_connection_count) && | ||
914 | (GNUNET_NO == friends_only)) | ||
915 | { | ||
916 | GNUNET_log ( | ||
917 | GNUNET_ERROR_TYPE_WARNING, | ||
918 | _ ( | ||
919 | "More friendly connections required than target total number of connections.\n")); | ||
920 | } | ||
921 | } | ||
922 | |||
923 | |||
924 | /** | ||
925 | * This function is called whenever an encrypted HELLO message is | ||
926 | * received. | ||
927 | * | ||
928 | * @param cls closure with the peer identity of the sender | ||
929 | * @param message the actual HELLO message | ||
930 | * @return #GNUNET_OK if @a message is well-formed | ||
931 | * #GNUNET_SYSERR if @a message is invalid | ||
932 | */ | ||
933 | static int | ||
934 | check_hello (void *cls, const struct GNUNET_HELLO_Message *message) | ||
935 | { | ||
936 | struct GNUNET_PeerIdentity pid; | ||
937 | |||
938 | if (GNUNET_OK != GNUNET_HELLO_get_id (message, &pid)) | ||
939 | { | ||
940 | GNUNET_break_op (0); | ||
941 | return GNUNET_SYSERR; | ||
942 | } | ||
943 | return GNUNET_OK; | ||
944 | } | ||
945 | |||
946 | |||
947 | /** | ||
948 | * This function is called whenever an encrypted HELLO message is | ||
949 | * received. | ||
950 | * | ||
951 | * @param cls closure with the peer identity of the sender | ||
952 | * @param message the actual HELLO message | ||
953 | */ | ||
954 | static void | ||
955 | handle_hello (void *cls, const struct GNUNET_HELLO_Message *message) | ||
956 | { | ||
957 | const struct GNUNET_PeerIdentity *other = cls; | ||
958 | struct Peer *peer; | ||
959 | struct GNUNET_PeerIdentity pid; | ||
960 | |||
961 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
962 | "Received encrypted HELLO from peer `%s'", | ||
963 | GNUNET_i2s (other)); | ||
964 | GNUNET_assert (GNUNET_OK == GNUNET_HELLO_get_id (message, &pid)); | ||
965 | GNUNET_STATISTICS_update (stats, | ||
966 | gettext_noop ("# HELLO messages received"), | ||
967 | 1, | ||
968 | GNUNET_NO); | ||
969 | peer = GNUNET_CONTAINER_multipeermap_get (peers, &pid); | ||
970 | if (NULL == peer) | ||
971 | { | ||
972 | if ((GNUNET_YES == friends_only) || (friend_count < minimum_friend_count)) | ||
973 | return; | ||
974 | } | ||
975 | else | ||
976 | { | ||
977 | if ((GNUNET_YES != peer->is_friend) && (GNUNET_YES == friends_only)) | ||
978 | return; | ||
979 | if ((GNUNET_YES != peer->is_friend) && | ||
980 | (friend_count < minimum_friend_count)) | ||
981 | return; | ||
982 | } | ||
983 | (void) GNUNET_PEERINFO_add_peer (pi, message, NULL, NULL); | ||
984 | } | ||
985 | |||
986 | |||
987 | /** | ||
988 | * Last task run during shutdown. Disconnects us from | ||
989 | * the transport and core. | ||
990 | * | ||
991 | * @param cls unused, NULL | ||
992 | */ | ||
993 | static void | ||
994 | cleaning_task (void *cls) | ||
995 | { | ||
996 | if (NULL != peerinfo_notify) | ||
997 | { | ||
998 | GNUNET_PEERINFO_notify_cancel (peerinfo_notify); | ||
999 | peerinfo_notify = NULL; | ||
1000 | } | ||
1001 | if (NULL != handle) | ||
1002 | { | ||
1003 | GNUNET_CORE_disconnect (handle); | ||
1004 | handle = NULL; | ||
1005 | } | ||
1006 | whitelist_peers (); | ||
1007 | if (NULL != add_task) | ||
1008 | { | ||
1009 | GNUNET_SCHEDULER_cancel (add_task); | ||
1010 | add_task = NULL; | ||
1011 | } | ||
1012 | if (NULL != oh) | ||
1013 | { | ||
1014 | GNUNET_TRANSPORT_offer_hello_cancel (oh); | ||
1015 | oh = NULL; | ||
1016 | } | ||
1017 | GNUNET_CONTAINER_multipeermap_iterate (peers, &free_peer, NULL); | ||
1018 | GNUNET_CONTAINER_multipeermap_destroy (peers); | ||
1019 | peers = NULL; | ||
1020 | if (NULL != ats) | ||
1021 | { | ||
1022 | GNUNET_ATS_connectivity_done (ats); | ||
1023 | ats = NULL; | ||
1024 | } | ||
1025 | if (NULL != pi) | ||
1026 | { | ||
1027 | GNUNET_PEERINFO_disconnect (pi); | ||
1028 | pi = NULL; | ||
1029 | } | ||
1030 | if (NULL != stats) | ||
1031 | { | ||
1032 | GNUNET_STATISTICS_destroy (stats, GNUNET_NO); | ||
1033 | stats = NULL; | ||
1034 | } | ||
1035 | } | ||
1036 | |||
1037 | |||
1038 | /** | ||
1039 | * Main function that will be run. | ||
1040 | * | ||
1041 | * @param cls closure | ||
1042 | * @param args remaining command-line arguments | ||
1043 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
1044 | * @param c configuration | ||
1045 | */ | ||
1046 | static void | ||
1047 | run (void *cls, | ||
1048 | char *const *args, | ||
1049 | const char *cfgfile, | ||
1050 | const struct GNUNET_CONFIGURATION_Handle *c) | ||
1051 | { | ||
1052 | struct GNUNET_MQ_MessageHandler handlers[] = | ||
1053 | { GNUNET_MQ_hd_var_size (hello, | ||
1054 | GNUNET_MESSAGE_TYPE_HELLO, | ||
1055 | struct GNUNET_HELLO_Message, | ||
1056 | NULL), | ||
1057 | GNUNET_MQ_handler_end () }; | ||
1058 | unsigned long long opt; | ||
1059 | |||
1060 | cfg = c; | ||
1061 | stats = GNUNET_STATISTICS_create ("topology", cfg); | ||
1062 | friends_only = | ||
1063 | GNUNET_CONFIGURATION_get_value_yesno (cfg, "TOPOLOGY", "FRIENDS-ONLY"); | ||
1064 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, | ||
1065 | "TOPOLOGY", | ||
1066 | "MINIMUM-FRIENDS", | ||
1067 | &opt)) | ||
1068 | opt = 0; | ||
1069 | minimum_friend_count = (unsigned int) opt; | ||
1070 | if (GNUNET_OK != | ||
1071 | GNUNET_CONFIGURATION_get_value_number (cfg, | ||
1072 | "TOPOLOGY", | ||
1073 | "TARGET-CONNECTION-COUNT", | ||
1074 | &opt)) | ||
1075 | opt = 16; | ||
1076 | target_connection_count = (unsigned int) opt; | ||
1077 | peers = GNUNET_CONTAINER_multipeermap_create (target_connection_count * 2, | ||
1078 | GNUNET_NO); | ||
1079 | read_friends_file (cfg); | ||
1080 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1081 | "Topology would like %u connections with at least %u friends\n", | ||
1082 | target_connection_count, | ||
1083 | minimum_friend_count); | ||
1084 | if ((GNUNET_YES == friends_only) || (minimum_friend_count > 0)) | ||
1085 | blacklist = GNUNET_TRANSPORT_blacklist (cfg, &blacklist_check, NULL); | ||
1086 | ats = GNUNET_ATS_connectivity_init (cfg); | ||
1087 | pi = GNUNET_PEERINFO_connect (cfg); | ||
1088 | handle = GNUNET_CORE_connect (cfg, | ||
1089 | NULL, | ||
1090 | &core_init, | ||
1091 | &connect_notify, | ||
1092 | &disconnect_notify, | ||
1093 | handlers); | ||
1094 | GNUNET_SCHEDULER_add_shutdown (&cleaning_task, NULL); | ||
1095 | if (NULL == handle) | ||
1096 | { | ||
1097 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1098 | _ ("Failed to connect to `%s' service.\n"), | ||
1099 | "core"); | ||
1100 | GNUNET_SCHEDULER_shutdown (); | ||
1101 | return; | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | |||
1106 | /** | ||
1107 | * The main function for the topology daemon. | ||
1108 | * | ||
1109 | * @param argc number of arguments from the command line | ||
1110 | * @param argv command line arguments | ||
1111 | * @return 0 ok, 1 on error | ||
1112 | */ | ||
1113 | int | ||
1114 | main (int argc, char *const *argv) | ||
1115 | { | ||
1116 | static const struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
1117 | GNUNET_GETOPT_OPTION_END | ||
1118 | }; | ||
1119 | int ret; | ||
1120 | |||
1121 | if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv)) | ||
1122 | return 2; | ||
1123 | |||
1124 | ret = (GNUNET_OK == GNUNET_PROGRAM_run (argc, | ||
1125 | argv, | ||
1126 | "gnunet-daemon-topology", | ||
1127 | _ ("GNUnet topology control"), | ||
1128 | options, | ||
1129 | &run, | ||
1130 | NULL)) | ||
1131 | ? 0 | ||
1132 | : 1; | ||
1133 | GNUNET_free_nz ((void *) argv); | ||
1134 | return ret; | ||
1135 | } | ||
1136 | |||
1137 | |||
1138 | #if defined(__linux__) && defined(__GLIBC__) | ||
1139 | #include <malloc.h> | ||
1140 | |||
1141 | /** | ||
1142 | * MINIMIZE heap size (way below 128k) since this process doesn't need much. | ||
1143 | */ | ||
1144 | void __attribute__ ((constructor)) | ||
1145 | GNUNET_ARM_memory_init () | ||
1146 | { | ||
1147 | mallopt (M_TRIM_THRESHOLD, 4 * 1024); | ||
1148 | mallopt (M_TOP_PAD, 1 * 1024); | ||
1149 | malloc_trim (0); | ||
1150 | } | ||
1151 | |||
1152 | |||
1153 | #endif | ||
1154 | |||
1155 | /* end of gnunet-daemon-topology.c */ | ||
diff --git a/src/topology/test_gnunet_daemon_topology.c b/src/topology/test_gnunet_daemon_topology.c deleted file mode 100644 index d1081515c..000000000 --- a/src/topology/test_gnunet_daemon_topology.c +++ /dev/null | |||
@@ -1,298 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2009, 2012 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 topology/test_gnunet_daemon_topology.c | ||
22 | * @brief testcase for topology maintenance code | ||
23 | * @author Christian Grothoff | ||
24 | * @author xrs | ||
25 | */ | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_testbed_service.h" | ||
28 | #include "gnunet_statistics_service.h" | ||
29 | |||
30 | |||
31 | #define NUM_PEERS 8 | ||
32 | |||
33 | /* | ||
34 | * The threshold defines the number of connection that are needed | ||
35 | * for one peer to pass the test. Be aware that setting NUM_PEERS | ||
36 | * too high can cause bandwidth problems for the testing peers. | ||
37 | * Normal should be 5KB/s per peer. See gnunet-config -s ats. | ||
38 | * schanzen 12/2019: This _only_ makes sense if we connect to the | ||
39 | * actual network as in the test we do not connect to more than 1 peer. | ||
40 | * => reducing to 1 for now, was NUM_PEERS / 2 | ||
41 | */ | ||
42 | #define THRESHOLD 1 | ||
43 | |||
44 | /** | ||
45 | * How long until we give up on connecting the peers? | ||
46 | */ | ||
47 | #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60) | ||
48 | |||
49 | /* | ||
50 | * Store manual connections. | ||
51 | */ | ||
52 | static unsigned int connect_left; | ||
53 | |||
54 | /* | ||
55 | * Result of the testcase. | ||
56 | */ | ||
57 | static int result; | ||
58 | |||
59 | /* | ||
60 | * Peers that reached the threshold of connections. | ||
61 | */ | ||
62 | static int checked_peers; | ||
63 | |||
64 | /* | ||
65 | * Testbed operations. | ||
66 | */ | ||
67 | struct GNUNET_TESTBED_Operation *op[NUM_PEERS]; | ||
68 | |||
69 | /* | ||
70 | * Timeout for testcase. | ||
71 | */ | ||
72 | static struct GNUNET_SCHEDULER_Task *timeout_tid; | ||
73 | |||
74 | /* | ||
75 | * Peer context for every testbed peer. | ||
76 | */ | ||
77 | struct peerctx | ||
78 | { | ||
79 | int index; | ||
80 | struct GNUNET_STATISTICS_Handle *statistics; | ||
81 | int connections; | ||
82 | int reported; /* GNUNET_NO | GNUNET_YES */ | ||
83 | }; | ||
84 | |||
85 | |||
86 | static void | ||
87 | shutdown_task (void *cls) | ||
88 | { | ||
89 | unsigned int i; | ||
90 | |||
91 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
92 | "Shutting down testcase\n"); | ||
93 | |||
94 | for (i = 0; i < NUM_PEERS; i++) | ||
95 | { | ||
96 | if (NULL != op[i]) | ||
97 | GNUNET_TESTBED_operation_done (op[i]); | ||
98 | } | ||
99 | |||
100 | if (NULL != timeout_tid) | ||
101 | GNUNET_SCHEDULER_cancel (timeout_tid); | ||
102 | } | ||
103 | |||
104 | |||
105 | static void | ||
106 | timeout_task (void *cls) | ||
107 | { | ||
108 | timeout_tid = NULL; | ||
109 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
110 | "Testcase timeout\n"); | ||
111 | |||
112 | result = GNUNET_SYSERR; | ||
113 | GNUNET_SCHEDULER_shutdown (); | ||
114 | } | ||
115 | |||
116 | |||
117 | /* | ||
118 | * The function is called every time the topology of connected | ||
119 | * peers to a peer changes. | ||
120 | */ | ||
121 | int | ||
122 | statistics_iterator (void *cls, | ||
123 | const char *subsystem, | ||
124 | const char *name, | ||
125 | uint64_t value, | ||
126 | int is_persistent) | ||
127 | { | ||
128 | struct peerctx *p_ctx = (struct peerctx*) cls; | ||
129 | |||
130 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
131 | "Peer %d: %s = %llu\n", | ||
132 | p_ctx->index, | ||
133 | name, | ||
134 | (unsigned long long) value); | ||
135 | |||
136 | if (p_ctx->connections < value) | ||
137 | p_ctx->connections = value; | ||
138 | |||
139 | if ((THRESHOLD <= value) && (GNUNET_NO == p_ctx->reported)) | ||
140 | { | ||
141 | p_ctx->reported = GNUNET_YES; | ||
142 | checked_peers++; | ||
143 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
144 | "Peer %d successfully connected to at least %d peers once.\n", | ||
145 | p_ctx->index, | ||
146 | THRESHOLD); | ||
147 | |||
148 | if (checked_peers == NUM_PEERS) | ||
149 | { | ||
150 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
151 | "Test OK: All peers have connected to %d peers once.\n", | ||
152 | THRESHOLD); | ||
153 | result = GNUNET_YES; | ||
154 | GNUNET_SCHEDULER_shutdown (); | ||
155 | } | ||
156 | } | ||
157 | |||
158 | return GNUNET_YES; | ||
159 | } | ||
160 | |||
161 | |||
162 | static void * | ||
163 | ca_statistics (void *cls, | ||
164 | const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
165 | { | ||
166 | return GNUNET_STATISTICS_create ("topology", cfg); | ||
167 | } | ||
168 | |||
169 | |||
170 | void | ||
171 | da_statistics (void *cls, | ||
172 | void *op_result) | ||
173 | { | ||
174 | struct peerctx *p_ctx = (struct peerctx *) cls; | ||
175 | |||
176 | GNUNET_break (GNUNET_OK == GNUNET_STATISTICS_watch_cancel | ||
177 | (p_ctx->statistics, "topology", "# peers connected", | ||
178 | statistics_iterator, p_ctx)); | ||
179 | |||
180 | GNUNET_STATISTICS_destroy (p_ctx->statistics, GNUNET_NO); | ||
181 | p_ctx->statistics = NULL; | ||
182 | |||
183 | GNUNET_free (p_ctx); | ||
184 | } | ||
185 | |||
186 | |||
187 | static void | ||
188 | service_connect_complete (void *cls, | ||
189 | struct GNUNET_TESTBED_Operation *op, | ||
190 | void *ca_result, | ||
191 | const char *emsg) | ||
192 | { | ||
193 | int ret; | ||
194 | struct peerctx *p_ctx = (struct peerctx*) cls; | ||
195 | |||
196 | if (NULL == ca_result) | ||
197 | GNUNET_SCHEDULER_shutdown (); | ||
198 | |||
199 | p_ctx->statistics = ca_result; | ||
200 | |||
201 | ret = GNUNET_STATISTICS_watch (ca_result, | ||
202 | "topology", | ||
203 | "# peers connected", | ||
204 | statistics_iterator, | ||
205 | p_ctx); | ||
206 | |||
207 | if (GNUNET_NO == ret) | ||
208 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
209 | "call to GNUNET_STATISTICS_watch() failed\n"); | ||
210 | } | ||
211 | |||
212 | |||
213 | static void | ||
214 | notify_connect_complete (void *cls, | ||
215 | struct GNUNET_TESTBED_Operation *op, | ||
216 | const char *emsg) | ||
217 | { | ||
218 | GNUNET_TESTBED_operation_done (op); | ||
219 | if (NULL != emsg) | ||
220 | { | ||
221 | fprintf (stderr, "Failed to connect two peers: %s\n", emsg); | ||
222 | result = GNUNET_SYSERR; | ||
223 | GNUNET_SCHEDULER_shutdown (); | ||
224 | return; | ||
225 | } | ||
226 | connect_left--; | ||
227 | } | ||
228 | |||
229 | |||
230 | static void | ||
231 | do_connect (void *cls, | ||
232 | struct GNUNET_TESTBED_RunHandle *h, | ||
233 | unsigned int num_peers, | ||
234 | struct GNUNET_TESTBED_Peer **peers, | ||
235 | unsigned int links_succeeded, | ||
236 | unsigned int links_failed) | ||
237 | { | ||
238 | unsigned int i; | ||
239 | struct peerctx *p_ctx; | ||
240 | |||
241 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
242 | "Threshold is set to %d.\n", | ||
243 | THRESHOLD); | ||
244 | |||
245 | GNUNET_assert (NUM_PEERS == num_peers); | ||
246 | |||
247 | for (i = 0; i < NUM_PEERS; i++) | ||
248 | { | ||
249 | p_ctx = GNUNET_new (struct peerctx); | ||
250 | p_ctx->index = i; | ||
251 | p_ctx->connections = 0; | ||
252 | p_ctx->reported = GNUNET_NO; | ||
253 | |||
254 | if (i < NUM_PEERS - 1) | ||
255 | { | ||
256 | connect_left++; | ||
257 | GNUNET_TESTBED_overlay_connect (NULL, | ||
258 | ¬ify_connect_complete, NULL, | ||
259 | peers[i], peers[i + 1]); | ||
260 | } | ||
261 | |||
262 | op[i] = | ||
263 | GNUNET_TESTBED_service_connect (cls, | ||
264 | peers[i], | ||
265 | "statistics", | ||
266 | service_connect_complete, | ||
267 | p_ctx, /* cls of completion cb */ | ||
268 | ca_statistics, /* connect adapter */ | ||
269 | da_statistics, /* disconnect adapter */ | ||
270 | p_ctx); | ||
271 | } | ||
272 | |||
273 | GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); | ||
274 | timeout_tid = | ||
275 | GNUNET_SCHEDULER_add_delayed (TIMEOUT, | ||
276 | &timeout_task, | ||
277 | NULL); | ||
278 | } | ||
279 | |||
280 | |||
281 | int | ||
282 | main (int argc, char *argv[]) | ||
283 | { | ||
284 | result = GNUNET_SYSERR; | ||
285 | checked_peers = 0; | ||
286 | |||
287 | (void) GNUNET_TESTBED_test_run ("test-gnunet-daemon-topology", | ||
288 | "test_gnunet_daemon_topology_data.conf", | ||
289 | NUM_PEERS, | ||
290 | 0, NULL, NULL, | ||
291 | &do_connect, NULL); | ||
292 | GNUNET_DISK_directory_remove ("/tmp/test-gnunet-topology"); | ||
293 | |||
294 | return (GNUNET_OK != result) ? 1 : 0; | ||
295 | } | ||
296 | |||
297 | |||
298 | /* end of test_gnunet_daemon_topology.c */ | ||
diff --git a/src/topology/test_gnunet_daemon_topology_data.conf b/src/topology/test_gnunet_daemon_topology_data.conf deleted file mode 100644 index b1b3e9b88..000000000 --- a/src/topology/test_gnunet_daemon_topology_data.conf +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | [PATHS] | ||
2 | GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-topology/ | ||
3 | |||
4 | [transport] | ||
5 | PLUGINS = tcp | ||
6 | #PREFIX = xterm -e xterm -T transport -e gdb -x cmd --args | ||
7 | #PREFIX = valgrind --tool=memcheck --log-file=logs%p | ||
8 | |||
9 | [testbed] | ||
10 | OVERLAY_TOPOLOGY=LINE | ||
11 | |||
12 | [transport-tcp] | ||
13 | BINDTO = 127.0.0.1 | ||
14 | |||
15 | # Do not try to connect to external network | ||
16 | [hostlist] | ||
17 | OPTIONS = | ||
18 | |||
19 | [nat] | ||
20 | DISABLEV6 = YES | ||
21 | ENABLE_UPNP = NO | ||
22 | BEHIND_NAT = NO | ||
23 | ALLOW_NAT = NO | ||
24 | INTERNAL_ADDRESS = 127.0.0.1 | ||
25 | EXTERNAL_ADDRESS = 127.0.0.1 | ||
26 | USE_LOCALADDR = NO | ||
27 | USE_HOSTNAME = NO | ||
28 | |||
29 | [nse] | ||
30 | WORKBITS = 0 | ||
31 | |||
32 | [rps] | ||
33 | START_ON_DEMAND = NO | ||
34 | IMMEDIATE_START = NO | ||
diff --git a/src/topology/topology.conf b/src/topology/topology.conf deleted file mode 100644 index 45d8dd0c7..000000000 --- a/src/topology/topology.conf +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | [topology] | ||
2 | IMMEDIATE_START = YES | ||
3 | NOARMBIND = YES | ||
4 | MINIMUM-FRIENDS = 0 | ||
5 | FRIENDS-ONLY = NO | ||
6 | TARGET-CONNECTION-COUNT = 16 | ||
7 | FRIENDS = $GNUNET_CONFIG_HOME/topology/friends.txt | ||
8 | BINARY = gnunet-daemon-topology | ||