aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/.gitignore9
-rw-r--r--src/core/Makefile.am143
-rw-r--r--src/core/core.conf.in23
-rw-r--r--src/core/core.h328
-rw-r--r--src/core/core_api.c773
-rw-r--r--src/core/core_api_monitor_peers.c196
-rw-r--r--src/core/gnunet-core.c208
-rw-r--r--src/core/gnunet-service-core.c987
-rw-r--r--src/core/gnunet-service-core.h198
-rw-r--r--src/core/gnunet-service-core_kx.c1945
-rw-r--r--src/core/gnunet-service-core_kx.h103
-rw-r--r--src/core/gnunet-service-core_sessions.c1043
-rw-r--r--src/core/gnunet-service-core_sessions.h183
-rw-r--r--src/core/gnunet-service-core_typemap.c377
-rw-r--r--src/core/gnunet-service-core_typemap.h163
-rw-r--r--src/core/test_core_api.c344
-rw-r--r--src/core/test_core_api_data.conf11
-rw-r--r--src/core/test_core_api_peer1.conf42
-rw-r--r--src/core/test_core_api_peer2.conf43
-rw-r--r--src/core/test_core_api_reliability.c535
-rw-r--r--src/core/test_core_api_send_to_self.c195
-rw-r--r--src/core/test_core_api_send_to_self.conf19
-rw-r--r--src/core/test_core_api_start_only.c250
-rw-r--r--src/core/test_core_defaults.conf22
-rw-r--r--src/core/test_core_quota_asymmetric_recv_limited_peer1.conf54
-rw-r--r--src/core/test_core_quota_asymmetric_recv_limited_peer2.conf57
-rw-r--r--src/core/test_core_quota_asymmetric_send_limit_peer1.conf52
-rw-r--r--src/core/test_core_quota_asymmetric_send_limit_peer2.conf61
-rw-r--r--src/core/test_core_quota_compliance.c779
-rw-r--r--src/core/test_core_quota_peer1.conf58
-rw-r--r--src/core/test_core_quota_peer2.conf59
31 files changed, 0 insertions, 9260 deletions
diff --git a/src/core/.gitignore b/src/core/.gitignore
deleted file mode 100644
index cdd1f93c2..000000000
--- a/src/core/.gitignore
+++ /dev/null
@@ -1,9 +0,0 @@
1gnunet-service-core
2gnunet-core
3test_core_api
4test_core_api_reliability
5test_core_api_send_to_self
6test_core_api_start_only
7test_core_quota_compliance_asymmetric_recv_limited
8test_core_quota_compliance_asymmetric_send_limited
9test_core_quota_compliance_symmetric
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
deleted file mode 100644
index e51247e18..000000000
--- a/src/core/Makefile.am
+++ /dev/null
@@ -1,143 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4pkgcfgdir= $(pkgdatadir)/config.d/
5
6libexecdir= $(pkglibdir)/libexec/
7
8pkgcfg_DATA = \
9 core.conf
10
11if USE_COVERAGE
12 AM_CFLAGS = --coverage -O0
13 XLIB = -lgcov
14endif
15
16
17lib_LTLIBRARIES = \
18 libgnunetcore.la
19
20libgnunetcore_la_SOURCES = \
21 core_api.c core.h \
22 core_api_monitor_peers.c
23libgnunetcore_la_LIBADD = \
24 $(top_builddir)/src/util/libgnunetutil.la \
25 $(GN_LIBINTL) $(XLIB)
26libgnunetcore_la_LDFLAGS = \
27 $(GN_LIB_LDFLAGS) \
28 -version-info 0:1:0
29
30
31libexec_PROGRAMS = \
32 gnunet-service-core
33
34bin_PROGRAMS = \
35 gnunet-core
36
37gnunet_service_core_SOURCES = \
38 gnunet-service-core.c gnunet-service-core.h \
39 gnunet-service-core_kx.c gnunet-service-core_kx.h \
40 gnunet-service-core_sessions.c gnunet-service-core_sessions.h \
41 gnunet-service-core_typemap.c gnunet-service-core_typemap.h
42gnunet_service_core_LDADD = \
43 $(top_builddir)/src/statistics/libgnunetstatistics.la \
44 $(top_builddir)/src/transport/libgnunettransport.la \
45 $(top_builddir)/src/util/libgnunetutil.la \
46 $(GN_LIBINTL) $(Z_LIBS)
47
48
49gnunet_core_SOURCES = \
50 gnunet-core.c
51gnunet_core_LDADD = \
52 libgnunetcore.la \
53 $(top_builddir)/src/util/libgnunetutil.la
54gnunet_core_LDFLAGS = \
55 $(GN_LIBINTL)
56
57TESTING_TESTS = \
58 test_core_api_send_to_self
59
60check_PROGRAMS = \
61 test_core_api_start_only \
62 test_core_api \
63 test_core_api_reliability \
64 test_core_quota_compliance_symmetric \
65 test_core_quota_compliance_asymmetric_send_limited \
66 test_core_quota_compliance_asymmetric_recv_limited \
67 $(TESTING_TESTS)
68
69if ENABLE_TEST_RUN
70AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
71TESTS = $(check_PROGRAMS)
72endif
73
74test_core_api_SOURCES = \
75 test_core_api.c
76test_core_api_LDADD = \
77 libgnunetcore.la \
78 $(top_builddir)/src/transport/libgnunettransport.la \
79 $(top_builddir)/src/ats/libgnunetats.la \
80 $(top_builddir)/src/util/libgnunetutil.la
81
82test_core_api_reliability_SOURCES = \
83 test_core_api_reliability.c
84test_core_api_reliability_LDADD = \
85 libgnunetcore.la \
86 $(top_builddir)/src/transport/libgnunettransport.la \
87 $(top_builddir)/src/ats/libgnunetats.la \
88 $(top_builddir)/src/util/libgnunetutil.la
89
90test_core_api_send_to_self_SOURCES = \
91 test_core_api_send_to_self.c
92test_core_api_send_to_self_LDADD = \
93 libgnunetcore.la \
94 $(top_builddir)/src/testing/libgnunettesting.la \
95 $(top_builddir)/src/transport/libgnunettransport.la \
96 $(top_builddir)/src/util/libgnunetutil.la
97
98test_core_api_start_only_SOURCES = \
99 test_core_api_start_only.c
100test_core_api_start_only_LDADD = \
101 $(top_builddir)/src/testing/libgnunettesting.la \
102 libgnunetcore.la \
103 $(top_builddir)/src/util/libgnunetutil.la
104
105test_core_quota_compliance_symmetric_SOURCES = \
106 test_core_quota_compliance.c
107test_core_quota_compliance_symmetric_LDADD = \
108 libgnunetcore.la \
109 $(top_builddir)/src/transport/libgnunettransport.la \
110 $(top_builddir)/src/ats/libgnunetats.la \
111 $(top_builddir)/src/util/libgnunetutil.la \
112 $(top_builddir)/src/statistics/libgnunetstatistics.la
113
114test_core_quota_compliance_asymmetric_send_limited_SOURCES = \
115 test_core_quota_compliance.c
116test_core_quota_compliance_asymmetric_send_limited_LDADD = \
117 libgnunetcore.la \
118 $(top_builddir)/src/transport/libgnunettransport.la \
119 $(top_builddir)/src/ats/libgnunetats.la \
120 $(top_builddir)/src/util/libgnunetutil.la \
121 $(top_builddir)/src/statistics/libgnunetstatistics.la
122
123test_core_quota_compliance_asymmetric_recv_limited_SOURCES = \
124 test_core_quota_compliance.c
125test_core_quota_compliance_asymmetric_recv_limited_LDADD = \
126 libgnunetcore.la \
127 $(top_builddir)/src/transport/libgnunettransport.la \
128 $(top_builddir)/src/ats/libgnunetats.la \
129 $(top_builddir)/src/util/libgnunetutil.la \
130 $(top_builddir)/src/statistics/libgnunetstatistics.la
131
132EXTRA_DIST = \
133 test_core_defaults.conf \
134 test_core_api_data.conf \
135 test_core_api_peer1.conf \
136 test_core_api_peer2.conf \
137 test_core_api_send_to_self.conf \
138 test_core_quota_asymmetric_recv_limited_peer1.conf \
139 test_core_quota_asymmetric_recv_limited_peer2.conf \
140 test_core_quota_asymmetric_send_limit_peer1.conf \
141 test_core_quota_asymmetric_send_limit_peer2.conf \
142 test_core_quota_peer1.conf \
143 test_core_quota_peer2.conf
diff --git a/src/core/core.conf.in b/src/core/core.conf.in
deleted file mode 100644
index 00faf6079..000000000
--- a/src/core/core.conf.in
+++ /dev/null
@@ -1,23 +0,0 @@
1[core]
2START_ON_DEMAND = @START_ON_DEMAND@
3@JAVAPORT@PORT = 2092
4HOSTNAME = localhost
5BINARY = gnunet-service-core
6ACCEPT_FROM = 127.0.0.1;
7ACCEPT_FROM6 = ::1;
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-core.sock
9UNIX_MATCH_UID = NO
10UNIX_MATCH_GID = YES
11# DISABLE_SOCKET_FORWARDING = NO
12# USERNAME =
13# MAXBUF =
14# TIMEOUT =
15# DISABLEV6 =
16# BINDTO =
17# REJECT_FROM =
18# REJECT_FROM6 =
19# PREFIX =
20
21# Note: this MUST be set to YES in production, only set to NO for testing
22# for performance (testbed/cluster-scale use!).
23USE_EPHEMERAL_KEYS = YES
diff --git a/src/core/core.h b/src/core/core.h
deleted file mode 100644
index 4d8619a29..000000000
--- a/src/core/core.h
+++ /dev/null
@@ -1,328 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-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 core/core.h
23 * @brief common internal definitions for core service
24 * @author Christian Grothoff
25 */
26#ifndef CORE_H
27#define CORE_H
28
29#include "gnunet_bandwidth_lib.h"
30#include "gnunet_transport_service.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_time_lib.h"
33
34/**
35 * General core debugging.
36 */
37#define DEBUG_CORE GNUNET_EXTRA_LOGGING
38
39/**
40 * Definition of bits in the InitMessage's options field that specify
41 * which events this client cares about. Note that inbound messages
42 * for handlers that were specifically registered are always
43 * transmitted to the client.
44 */
45#define GNUNET_CORE_OPTION_NOTHING 0
46
47/**
48 * Client cares about connectivity changes.
49 */
50#define GNUNET_CORE_OPTION_SEND_STATUS_CHANGE 4
51
52/**
53 * Client wants all inbound messages in full.
54 */
55#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND 8
56
57/**
58 * Client just wants the 4-byte message headers of
59 * all inbound messages.
60 */
61#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND 16
62
63/**
64 * Client wants all outbound messages in full.
65 */
66#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 32
67
68/**
69 * Client just wants the 4-byte message headers of
70 * all outbound messages.
71 */
72#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND 64
73
74
75GNUNET_NETWORK_STRUCT_BEGIN
76
77/**
78 * Message transmitted core clients to gnunet-service-core
79 * to start the interaction. This header is followed by
80 * uint16_t type values specifying which messages this
81 * client is interested in.
82 */
83struct InitMessage
84{
85 /**
86 * Header with type #GNUNET_MESSAGE_TYPE_CORE_INIT.
87 */
88 struct GNUNET_MessageHeader header;
89
90 /**
91 * Options, see GNUNET_CORE_OPTION_ values.
92 */
93 uint32_t options GNUNET_PACKED;
94};
95
96
97/**
98 * Message transmitted by the gnunet-service-core process
99 * to its clients in response to an INIT message.
100 */
101struct InitReplyMessage
102{
103 /**
104 * Header with type #GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY
105 */
106 struct GNUNET_MessageHeader header;
107
108 /**
109 * Always zero.
110 */
111 uint32_t reserved GNUNET_PACKED;
112
113 /**
114 * Public key of the local peer.
115 */
116 struct GNUNET_PeerIdentity my_identity;
117};
118
119
120/**
121 * Message sent by the service to clients to notify them
122 * about a peer connecting.
123 */
124struct ConnectNotifyMessage
125{
126 /**
127 * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT
128 */
129 struct GNUNET_MessageHeader header;
130
131 /**
132 * Always zero.
133 */
134 uint32_t reserved GNUNET_PACKED;
135
136 /**
137 * Identity of the connecting peer.
138 */
139 struct GNUNET_PeerIdentity peer;
140};
141
142
143/**
144 * Message sent by the service to clients to notify them
145 * about a peer disconnecting.
146 */
147struct DisconnectNotifyMessage
148{
149 /**
150 * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT.
151 */
152 struct GNUNET_MessageHeader header;
153
154 /**
155 * Always zero.
156 */
157 uint32_t reserved GNUNET_PACKED;
158
159 /**
160 * Identity of the connecting peer.
161 */
162 struct GNUNET_PeerIdentity peer;
163};
164
165
166/**
167 * Message sent by the service to clients to notify them about
168 * messages being received or transmitted. This overall message is
169 * followed by the real message, or just the header of the real
170 * message (depending on the client's preferences). The receiver can
171 * tell if it got the full message or only a partial message by
172 * looking at the size field in the header of NotifyTrafficMessage and
173 * checking it with the size field in the message that follows.
174 */
175struct NotifyTrafficMessage
176{
177 /**
178 * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND
179 * or #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND.
180 */
181 struct GNUNET_MessageHeader header;
182
183 /**
184 * Identity of the receiver or sender.
185 */
186 struct GNUNET_PeerIdentity peer;
187
188 /* Followed by payload (message or just header), variable size */
189};
190
191
192/**
193 * Client notifying core about the maximum-priority
194 * message it has in the queue for a particular target.
195 */
196struct SendMessageRequest
197{
198 /**
199 * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST
200 */
201 struct GNUNET_MessageHeader header;
202
203 /**
204 * How important is this message?
205 */
206 uint32_t priority GNUNET_PACKED;
207
208 /**
209 * By what time would the sender really like to see this
210 * message transmitted?
211 */
212 struct GNUNET_TIME_AbsoluteNBO deadline;
213
214 /**
215 * Identity of the intended target.
216 */
217 struct GNUNET_PeerIdentity peer;
218
219 /**
220 * Always zero.
221 */
222 uint32_t reserved GNUNET_PACKED;
223
224 /**
225 * How large is the message?
226 */
227 uint16_t size GNUNET_PACKED;
228
229 /**
230 * Counter for this peer to match SMRs to replies.
231 */
232 uint16_t smr_id GNUNET_PACKED;
233};
234
235
236/**
237 * Core notifying client that it is allowed to now
238 * transmit a message to the given target
239 * (response to #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST).
240 */
241struct SendMessageReady
242{
243 /**
244 * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND_READY
245 */
246 struct GNUNET_MessageHeader header;
247
248 /**
249 * How many bytes are allowed for transmission?
250 * Guaranteed to be at least as big as the requested size,
251 * or ZERO if the request is rejected (will timeout,
252 * peer disconnected, queue full, etc.).
253 */
254 uint16_t size GNUNET_PACKED;
255
256 /**
257 * smr_id from the request.
258 */
259 uint16_t smr_id GNUNET_PACKED;
260
261 /**
262 * Identity of the intended target.
263 */
264 struct GNUNET_PeerIdentity peer;
265};
266
267
268/**
269 * Client asking core to transmit a particular message to a particular
270 * target (response to #GNUNET_MESSAGE_TYPE_CORE_SEND_READY).
271 */
272struct SendMessage
273{
274 /**
275 * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND
276 */
277 struct GNUNET_MessageHeader header;
278
279 /**
280 * How important is this message? Contains a
281 * `enum GNUNET_MQ_PriorityPreferences` in NBO.
282 */
283 uint32_t priority GNUNET_PACKED;
284
285 /**
286 * By what time would the sender really like to see this
287 * message transmitted?
288 */
289 struct GNUNET_TIME_AbsoluteNBO deadline;
290
291 /**
292 * Identity of the intended receiver.
293 */
294 struct GNUNET_PeerIdentity peer;
295};
296
297
298/**
299 * Message sent by the service to monitor clients to notify them
300 * about a peer changing status.
301 */
302struct MonitorNotifyMessage
303{
304 /**
305 * Header with type #GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY
306 */
307 struct GNUNET_MessageHeader header;
308
309 /**
310 * New peer state, an `enum GNUNET_CORE_KxState` in NBO.
311 */
312 uint32_t state GNUNET_PACKED;
313
314 /**
315 * Identity of the peer.
316 */
317 struct GNUNET_PeerIdentity peer;
318
319 /**
320 * How long will we stay in this state (if nothing else happens)?
321 */
322 struct GNUNET_TIME_AbsoluteNBO timeout;
323};
324
325
326GNUNET_NETWORK_STRUCT_END
327#endif
328/* end of core.h */
diff --git a/src/core/core_api.c b/src/core/core_api.c
deleted file mode 100644
index 81118693d..000000000
--- a/src/core/core_api.c
+++ /dev/null
@@ -1,773 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-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 * @file core/core_api.c
22 * @brief core service; this is the main API for encrypted P2P
23 * communications
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_constants.h"
29#include "gnunet_core_service.h"
30#include "core.h"
31
32#define LOG(kind, ...) GNUNET_log_from (kind, "core-api", __VA_ARGS__)
33
34
35/**
36 * Information we track for each peer.
37 */
38struct PeerRecord
39{
40 /**
41 * Corresponding CORE handle.
42 */
43 struct GNUNET_CORE_Handle *h;
44
45 /**
46 * Message queue for the peer.
47 */
48 struct GNUNET_MQ_Handle *mq;
49
50 /**
51 * Message we are currently trying to pass to the CORE service
52 * for this peer (from @e mq).
53 */
54 struct GNUNET_MQ_Envelope *env;
55
56 /**
57 * Value the client returned when we connected, used
58 * as the closure in various places.
59 */
60 void *client_cls;
61
62 /**
63 * Peer the record is about.
64 */
65 struct GNUNET_PeerIdentity peer;
66
67 /**
68 * SendMessageRequest ID generator for this peer.
69 */
70 uint16_t smr_id_gen;
71};
72
73
74/**
75 * Context for the core service connection.
76 */
77struct GNUNET_CORE_Handle
78{
79 /**
80 * Configuration we're using.
81 */
82 const struct GNUNET_CONFIGURATION_Handle *cfg;
83
84 /**
85 * Closure for the various callbacks.
86 */
87 void *cls;
88
89 /**
90 * Function to call once we've handshaked with the core service.
91 */
92 GNUNET_CORE_StartupCallback init;
93
94 /**
95 * Function to call whenever we're notified about a peer connecting.
96 */
97 GNUNET_CORE_ConnectEventHandler connects;
98
99 /**
100 * Function to call whenever we're notified about a peer disconnecting.
101 */
102 GNUNET_CORE_DisconnectEventHandler disconnects;
103
104 /**
105 * Function handlers for messages of particular type.
106 */
107 struct GNUNET_MQ_MessageHandler *handlers;
108
109 /**
110 * Our message queue for transmissions to the service.
111 */
112 struct GNUNET_MQ_Handle *mq;
113
114 /**
115 * Hash map listing all of the peers that we are currently
116 * connected to.
117 */
118 struct GNUNET_CONTAINER_MultiPeerMap *peers;
119
120 /**
121 * Identity of this peer.
122 */
123 struct GNUNET_PeerIdentity me;
124
125 /**
126 * ID of reconnect task (if any).
127 */
128 struct GNUNET_SCHEDULER_Task *reconnect_task;
129
130 /**
131 * Current delay we use for re-trying to connect to core.
132 */
133 struct GNUNET_TIME_Relative retry_backoff;
134
135 /**
136 * Number of entries in the handlers array.
137 */
138 unsigned int hcnt;
139
140 /**
141 * Did we ever get INIT?
142 */
143 int have_init;
144};
145
146
147/**
148 * Our current client connection went down. Clean it up
149 * and try to reconnect!
150 *
151 * @param h our handle to the core service
152 */
153static void
154reconnect (struct GNUNET_CORE_Handle *h);
155
156
157/**
158 * Task schedule to try to re-connect to core.
159 *
160 * @param cls the `struct GNUNET_CORE_Handle`
161 * @param tc task context
162 */
163static void
164reconnect_task (void *cls)
165{
166 struct GNUNET_CORE_Handle *h = cls;
167
168 h->reconnect_task = NULL;
169 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CORE service after delay\n");
170 reconnect (h);
171}
172
173
174/**
175 * Notify clients about disconnect and free the entry for connected
176 * peer.
177 *
178 * @param cls the `struct GNUNET_CORE_Handle *`
179 * @param key the peer identity (not used)
180 * @param value the `struct PeerRecord` to free.
181 * @return #GNUNET_YES (continue)
182 */
183static int
184disconnect_and_free_peer_entry (void *cls,
185 const struct GNUNET_PeerIdentity *key,
186 void *value)
187{
188 struct GNUNET_CORE_Handle *h = cls;
189 struct PeerRecord *pr = value;
190
191 GNUNET_assert (pr->h == h);
192 if (NULL != h->disconnects)
193 h->disconnects (h->cls, &pr->peer, pr->client_cls);
194 GNUNET_assert (GNUNET_YES ==
195 GNUNET_CONTAINER_multipeermap_remove (h->peers, key, pr));
196 GNUNET_MQ_destroy (pr->mq);
197 GNUNET_assert (NULL == pr->mq);
198 if (NULL != pr->env)
199 {
200 GNUNET_MQ_discard (pr->env);
201 pr->env = NULL;
202 }
203 GNUNET_free (pr);
204 return GNUNET_YES;
205}
206
207
208/**
209 * Close down any existing connection to the CORE service and
210 * try re-establishing it later.
211 *
212 * @param h our handle
213 */
214static void
215reconnect_later (struct GNUNET_CORE_Handle *h)
216{
217 GNUNET_assert (NULL == h->reconnect_task);
218 if (NULL != h->mq)
219 {
220 GNUNET_MQ_destroy (h->mq);
221 h->mq = NULL;
222 }
223 GNUNET_assert (NULL == h->reconnect_task);
224 h->reconnect_task =
225 GNUNET_SCHEDULER_add_delayed (h->retry_backoff, &reconnect_task, h);
226 GNUNET_CONTAINER_multipeermap_iterate (h->peers,
227 &disconnect_and_free_peer_entry,
228 h);
229 h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff);
230}
231
232
233/**
234 * Error handler for the message queue to the CORE service.
235 * On errors, we reconnect.
236 *
237 * @param cls closure, a `struct GNUNET_CORE_Handle *`
238 * @param error error code
239 */
240static void
241handle_mq_error (void *cls, enum GNUNET_MQ_Error error)
242{
243 struct GNUNET_CORE_Handle *h = cls;
244
245 LOG (GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %d\n", error);
246 reconnect_later (h);
247}
248
249
250/**
251 * Implement sending functionality of a message queue for
252 * us sending messages to a peer.
253 *
254 * @param mq the message queue
255 * @param msg the message to send
256 * @param impl_state state of the implementation
257 */
258static void
259core_mq_send_impl (struct GNUNET_MQ_Handle *mq,
260 const struct GNUNET_MessageHeader *msg,
261 void *impl_state)
262{
263 struct PeerRecord *pr = impl_state;
264 struct GNUNET_CORE_Handle *h = pr->h;
265 struct SendMessageRequest *smr;
266 struct SendMessage *sm;
267 struct GNUNET_MQ_Envelope *env;
268 uint16_t msize;
269 enum GNUNET_MQ_PriorityPreferences flags;
270
271 if (NULL == h->mq)
272 {
273 /* We're currently reconnecting, pretend this worked */
274 GNUNET_MQ_impl_send_continue (mq);
275 return;
276 }
277 GNUNET_assert (NULL == pr->env);
278 /* extract options from envelope */
279 env = GNUNET_MQ_get_current_envelope (mq);
280 flags = GNUNET_MQ_env_get_options (env);
281
282 /* check message size for sanity */
283 msize = ntohs (msg->size);
284 if (msize >= GNUNET_MAX_MESSAGE_SIZE - sizeof(struct SendMessage))
285 {
286 GNUNET_break (0);
287 GNUNET_MQ_impl_send_continue (mq);
288 return;
289 }
290
291 /* ask core for transmission */
292 LOG (GNUNET_ERROR_TYPE_DEBUG,
293 "Asking core for transmission of %u bytes to `%s'\n",
294 (unsigned int) msize,
295 GNUNET_i2s (&pr->peer));
296 env = GNUNET_MQ_msg (smr, GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST);
297 smr->priority = htonl ((uint32_t) flags);
298 smr->peer = pr->peer;
299 smr->size = htons (msize);
300 smr->smr_id = htons (++pr->smr_id_gen);
301 GNUNET_MQ_send (h->mq, env);
302
303 /* prepare message with actual transmission data */
304 pr->env = GNUNET_MQ_msg_nested_mh (sm, GNUNET_MESSAGE_TYPE_CORE_SEND, msg);
305 sm->priority = htonl ((uint32_t) flags);
306 sm->peer = pr->peer;
307 LOG (GNUNET_ERROR_TYPE_DEBUG,
308 "Calling get_message with buffer of %u bytes\n",
309 (unsigned int) msize);
310}
311
312
313/**
314 * Handle destruction of a message queue. Implementations must not
315 * free @a mq, but should take care of @a impl_state.
316 *
317 * @param mq the message queue to destroy
318 * @param impl_state state of the implementation
319 */
320static void
321core_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
322{
323 struct PeerRecord *pr = impl_state;
324
325 GNUNET_assert (mq == pr->mq);
326 pr->mq = NULL;
327}
328
329
330/**
331 * Implementation function that cancels the currently sent message.
332 * Should basically undo whatever #mq_send_impl() did.
333 *
334 * @param mq message queue
335 * @param impl_state state specific to the implementation
336 */
337static void
338core_mq_cancel_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
339{
340 struct PeerRecord *pr = impl_state;
341
342 (void) mq;
343 GNUNET_assert (NULL != pr->env);
344 GNUNET_MQ_discard (pr->env);
345 pr->env = NULL;
346}
347
348
349/**
350 * We had an error processing a message we forwarded from a peer to
351 * the CORE service. We should just complain about it but otherwise
352 * continue processing.
353 *
354 * @param cls closure
355 * @param error error code
356 */
357static void
358core_mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
359{
360 /* struct PeerRecord *pr = cls; */
361 (void) cls;
362 (void) error;
363 GNUNET_break_op (0);
364}
365
366
367/**
368 * Add the given peer to the list of our connected peers
369 * and create the respective data structures and notify
370 * the application.
371 *
372 * @param h the core handle
373 * @param peer the peer that is connecting to us
374 */
375static void
376connect_peer (struct GNUNET_CORE_Handle *h,
377 const struct GNUNET_PeerIdentity *peer)
378{
379 struct PeerRecord *pr;
380
381 pr = GNUNET_new (struct PeerRecord);
382 pr->peer = *peer;
383 pr->h = h;
384 GNUNET_assert (GNUNET_YES ==
385 GNUNET_CONTAINER_multipeermap_put (
386 h->peers,
387 &pr->peer,
388 pr,
389 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
390 pr->mq = GNUNET_MQ_queue_for_callbacks (&core_mq_send_impl,
391 &core_mq_destroy_impl,
392 &core_mq_cancel_impl,
393 pr,
394 h->handlers,
395 &core_mq_error_handler,
396 pr);
397 if (NULL != h->connects)
398 {
399 pr->client_cls = h->connects (h->cls, &pr->peer, pr->mq);
400 GNUNET_MQ_set_handlers_closure (pr->mq, pr->client_cls);
401 }
402}
403
404
405/**
406 * Handle init reply message received from CORE service. Notify
407 * application that we are now connected to the CORE. Also fake
408 * loopback connection.
409 *
410 * @param cls the `struct GNUNET_CORE_Handle`
411 * @param m the init reply
412 */
413static void
414handle_init_reply (void *cls, const struct InitReplyMessage *m)
415{
416 struct GNUNET_CORE_Handle *h = cls;
417 GNUNET_CORE_StartupCallback init;
418
419 GNUNET_break (0 == ntohl (m->reserved));
420 h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
421 if (NULL != (init = h->init))
422 {
423 /* mark so we don't call init on reconnect */
424 h->init = NULL;
425 h->me = m->my_identity;
426 LOG (GNUNET_ERROR_TYPE_DEBUG,
427 "Connected to core service of peer `%s'.\n",
428 GNUNET_i2s (&h->me));
429 h->have_init = GNUNET_YES;
430 init (h->cls, &h->me);
431 }
432 else
433 {
434 LOG (GNUNET_ERROR_TYPE_DEBUG,
435 "Successfully reconnected to core service.\n");
436 if (GNUNET_NO == h->have_init)
437 {
438 h->me = m->my_identity;
439 h->have_init = GNUNET_YES;
440 }
441 else
442 {
443 GNUNET_break (0 == memcmp (&h->me,
444 &m->my_identity,
445 sizeof(struct GNUNET_PeerIdentity)));
446 }
447 }
448 /* fake 'connect to self' */
449 connect_peer (h, &h->me);
450}
451
452
453/**
454 * Handle connect message received from CORE service.
455 * Notify the application about the new connection.
456 *
457 * @param cls the `struct GNUNET_CORE_Handle`
458 * @param cnm the connect message
459 */
460static void
461handle_connect_notify (void *cls, const struct ConnectNotifyMessage *cnm)
462{
463 struct GNUNET_CORE_Handle *h = cls;
464 struct PeerRecord *pr;
465
466 LOG (GNUNET_ERROR_TYPE_DEBUG,
467 "Received notification about connection from `%s'.\n",
468 GNUNET_i2s (&cnm->peer));
469 if (0 == memcmp (&h->me, &cnm->peer, sizeof(struct GNUNET_PeerIdentity)))
470 {
471 /* connect to self!? */
472 GNUNET_break (0);
473 return;
474 }
475 pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &cnm->peer);
476 if (NULL != pr)
477 {
478 GNUNET_break (0);
479 reconnect_later (h);
480 return;
481 }
482 connect_peer (h, &cnm->peer);
483}
484
485
486/**
487 * Handle disconnect message received from CORE service.
488 * Notify the application about the lost connection.
489 *
490 * @param cls the `struct GNUNET_CORE_Handle`
491 * @param dnm message about the disconnect event
492 */
493static void
494handle_disconnect_notify (void *cls, const struct DisconnectNotifyMessage *dnm)
495{
496 struct GNUNET_CORE_Handle *h = cls;
497 struct PeerRecord *pr;
498
499 if (0 == memcmp (&h->me, &dnm->peer, sizeof(struct GNUNET_PeerIdentity)))
500 {
501 /* disconnect from self!? */
502 GNUNET_break (0);
503 return;
504 }
505 GNUNET_break (0 == ntohl (dnm->reserved));
506 LOG (GNUNET_ERROR_TYPE_DEBUG,
507 "Received notification about disconnect from `%s'.\n",
508 GNUNET_i2s (&dnm->peer));
509 pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &dnm->peer);
510 if (NULL == pr)
511 {
512 GNUNET_break (0);
513 reconnect_later (h);
514 return;
515 }
516 disconnect_and_free_peer_entry (h, &pr->peer, pr);
517}
518
519
520/**
521 * Check that message received from CORE service is well-formed.
522 *
523 * @param cls the `struct GNUNET_CORE_Handle`
524 * @param ntm the message we got
525 * @return #GNUNET_OK if the message is well-formed
526 */
527static int
528check_notify_inbound (void *cls, const struct NotifyTrafficMessage *ntm)
529{
530 uint16_t msize;
531 const struct GNUNET_MessageHeader *em;
532
533 (void) cls;
534 msize = ntohs (ntm->header.size) - sizeof(struct NotifyTrafficMessage);
535 if (msize < sizeof(struct GNUNET_MessageHeader))
536 {
537 GNUNET_break (0);
538 return GNUNET_SYSERR;
539 }
540 em = (const struct GNUNET_MessageHeader *) &ntm[1];
541 if (msize != ntohs (em->size))
542 {
543 GNUNET_break (0);
544 return GNUNET_SYSERR;
545 }
546 return GNUNET_OK;
547}
548
549
550/**
551 * Handle inbound message received from CORE service. If applicable,
552 * notify the application.
553 *
554 * @param cls the `struct GNUNET_CORE_Handle`
555 * @param ntm the message we got from CORE.
556 */
557static void
558handle_notify_inbound (void *cls, const struct NotifyTrafficMessage *ntm)
559{
560 struct GNUNET_CORE_Handle *h = cls;
561 const struct GNUNET_MessageHeader *em;
562 struct PeerRecord *pr;
563
564 LOG (GNUNET_ERROR_TYPE_DEBUG,
565 "Received inbound message from `%s'.\n",
566 GNUNET_i2s (&ntm->peer));
567 em = (const struct GNUNET_MessageHeader *) &ntm[1];
568 pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &ntm->peer);
569 if (NULL == pr)
570 {
571 GNUNET_break (0);
572 reconnect_later (h);
573 return;
574 }
575 GNUNET_MQ_inject_message (pr->mq, em);
576}
577
578
579/**
580 * Handle message received from CORE service notifying us that we are
581 * now allowed to send a message to a peer. If that message is still
582 * pending, put it into the queue to be transmitted.
583 *
584 * @param cls the `struct GNUNET_CORE_Handle`
585 * @param smr the message we got
586 */
587static void
588handle_send_ready (void *cls, const struct SendMessageReady *smr)
589{
590 struct GNUNET_CORE_Handle *h = cls;
591 struct PeerRecord *pr;
592
593 pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &smr->peer);
594 if (NULL == pr)
595 {
596 GNUNET_break (0);
597 reconnect_later (h);
598 return;
599 }
600 LOG (GNUNET_ERROR_TYPE_DEBUG,
601 "Received notification about transmission readiness to `%s'.\n",
602 GNUNET_i2s (&smr->peer));
603 if (NULL == pr->env)
604 {
605 /* request must have been cancelled between the original request
606 * and the response from CORE, ignore CORE's readiness */
607 return;
608 }
609 if (ntohs (smr->smr_id) != pr->smr_id_gen)
610 {
611 /* READY message is for expired or cancelled message,
612 * ignore! (we should have already sent another request) */
613 return;
614 }
615
616 /* ok, all good, send message out! */
617 GNUNET_MQ_send (h->mq, pr->env);
618 pr->env = NULL;
619 GNUNET_MQ_impl_send_continue (pr->mq);
620}
621
622
623/**
624 * Our current client connection went down. Clean it up and try to
625 * reconnect!
626 *
627 * @param h our handle to the core service
628 */
629static void
630reconnect (struct GNUNET_CORE_Handle *h)
631{
632 struct GNUNET_MQ_MessageHandler handlers[] =
633 { GNUNET_MQ_hd_fixed_size (init_reply,
634 GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY,
635 struct InitReplyMessage,
636 h),
637 GNUNET_MQ_hd_fixed_size (connect_notify,
638 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT,
639 struct ConnectNotifyMessage,
640 h),
641 GNUNET_MQ_hd_fixed_size (disconnect_notify,
642 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT,
643 struct DisconnectNotifyMessage,
644 h),
645 GNUNET_MQ_hd_var_size (notify_inbound,
646 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND,
647 struct NotifyTrafficMessage,
648 h),
649 GNUNET_MQ_hd_fixed_size (send_ready,
650 GNUNET_MESSAGE_TYPE_CORE_SEND_READY,
651 struct SendMessageReady,
652 h),
653 GNUNET_MQ_handler_end () };
654 struct InitMessage *init;
655 struct GNUNET_MQ_Envelope *env;
656 uint16_t *ts;
657
658 GNUNET_assert (NULL == h->mq);
659 h->mq = GNUNET_CLIENT_connect (h->cfg, "core", handlers, &handle_mq_error, h);
660 if (NULL == h->mq)
661 {
662 reconnect_later (h);
663 return;
664 }
665 env = GNUNET_MQ_msg_extra (init,
666 sizeof(uint16_t) * h->hcnt,
667 GNUNET_MESSAGE_TYPE_CORE_INIT);
668 LOG (GNUNET_ERROR_TYPE_INFO, "(Re)connecting to CORE service\n");
669 init->options = htonl (0);
670 ts = (uint16_t *) &init[1];
671 for (unsigned int hpos = 0; hpos < h->hcnt; hpos++)
672 ts[hpos] = htons (h->handlers[hpos].type);
673 GNUNET_MQ_send (h->mq, env);
674}
675
676
677/**
678 * Connect to the core service. Note that the connection may complete
679 * (or fail) asynchronously.
680 *
681 * @param cfg configuration to use
682 * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
683 * @param init callback to call once we have successfully
684 * connected to the core service
685 * @param connects function to call on peer connect, can be NULL
686 * @param disconnects function to call on peer disconnect / timeout, can be NULL
687 * @param handlers callbacks for messages we care about, NULL-terminated
688 * @return handle to the core service (only useful for disconnect until @a init is called);
689 * NULL on error (in this case, init is never called)
690 */
691struct GNUNET_CORE_Handle *
692GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
693 void *cls,
694 GNUNET_CORE_StartupCallback init,
695 GNUNET_CORE_ConnectEventHandler connects,
696 GNUNET_CORE_DisconnectEventHandler disconnects,
697 const struct GNUNET_MQ_MessageHandler *handlers)
698{
699 struct GNUNET_CORE_Handle *h;
700
701 h = GNUNET_new (struct GNUNET_CORE_Handle);
702 h->cfg = cfg;
703 h->cls = cls;
704 h->init = init;
705 h->connects = connects;
706 h->disconnects = disconnects;
707 h->peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
708 h->handlers = GNUNET_MQ_copy_handlers (handlers);
709 h->hcnt = GNUNET_MQ_count_handlers (handlers);
710 GNUNET_assert (h->hcnt <
711 (GNUNET_MAX_MESSAGE_SIZE - sizeof(struct InitMessage))
712 / sizeof(uint16_t));
713 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CORE service\n");
714 reconnect (h);
715 if (NULL == h->mq)
716 {
717 GNUNET_CORE_disconnect (h);
718 return NULL;
719 }
720 return h;
721}
722
723
724/**
725 * Disconnect from the core service.
726 *
727 * @param handle connection to core to disconnect
728 */
729void
730GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle)
731{
732 LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from CORE service\n");
733 GNUNET_CONTAINER_multipeermap_iterate (handle->peers,
734 &disconnect_and_free_peer_entry,
735 handle);
736 GNUNET_CONTAINER_multipeermap_destroy (handle->peers);
737 handle->peers = NULL;
738 if (NULL != handle->reconnect_task)
739 {
740 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
741 handle->reconnect_task = NULL;
742 }
743 if (NULL != handle->mq)
744 {
745 GNUNET_MQ_destroy (handle->mq);
746 handle->mq = NULL;
747 }
748 GNUNET_free (handle->handlers);
749 GNUNET_free (handle);
750}
751
752
753/**
754 * Obtain the message queue for a connected peer.
755 *
756 * @param h the core handle
757 * @param pid the identity of the peer to check if it has been connected to us
758 * @return NULL if peer is not connected
759 */
760struct GNUNET_MQ_Handle *
761GNUNET_CORE_get_mq (const struct GNUNET_CORE_Handle *h,
762 const struct GNUNET_PeerIdentity *pid)
763{
764 struct PeerRecord *pr;
765
766 pr = GNUNET_CONTAINER_multipeermap_get (h->peers, pid);
767 if (NULL == pr)
768 return NULL;
769 return pr->mq;
770}
771
772
773/* end of core_api.c */
diff --git a/src/core/core_api_monitor_peers.c b/src/core/core_api_monitor_peers.c
deleted file mode 100644
index 3be8e3859..000000000
--- a/src/core/core_api_monitor_peers.c
+++ /dev/null
@@ -1,196 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2014, 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 core/core_api_monitor_peers.c
23 * @brief implementation of the peer_iterate function
24 * @author Christian Grothoff
25 * @author Nathan Evans
26 */
27#include "platform.h"
28#include "gnunet_core_service.h"
29#include "core.h"
30
31
32/**
33 * Handle to a CORE monitoring operation.
34 */
35struct GNUNET_CORE_MonitorHandle
36{
37 /**
38 * Our configuration.
39 */
40 const struct GNUNET_CONFIGURATION_Handle *cfg;
41
42 /**
43 * Our connection to the service.
44 */
45 struct GNUNET_MQ_Handle *mq;
46
47 /**
48 * Function called with the peer.
49 */
50 GNUNET_CORE_MonitorCallback peer_cb;
51
52 /**
53 * Closure for @e peer_cb.
54 */
55 void *peer_cb_cls;
56};
57
58
59/**
60 * Protocol error, reconnect to CORE service and notify
61 * client.
62 *
63 * @param mh monitoring session to reconnect to CORE
64 */
65static void
66reconnect (struct GNUNET_CORE_MonitorHandle *mh);
67
68
69/**
70 * Generic error handler, called with the appropriate error code and
71 * the same closure specified at the creation of the message queue.
72 * Not every message queue implementation supports an error handler.
73 *
74 * @param cls closure, a `struct GNUNET_CORE_MonitorHandle *`
75 * @param error error code
76 */
77static void
78handle_mq_error (void *cls, enum GNUNET_MQ_Error error)
79{
80 struct GNUNET_CORE_MonitorHandle *mh = cls;
81
82 (void) error;
83 reconnect (mh);
84}
85
86
87/**
88 * Receive reply from CORE service with information about a peer.
89 *
90 * @param cls our `struct GNUNET_CORE_MonitorHandle *`
91 * @param mon_message monitor message
92 */
93static void
94handle_receive_info (void *cls, const struct MonitorNotifyMessage *mon_message)
95{
96 struct GNUNET_CORE_MonitorHandle *mh = cls;
97
98 mh->peer_cb (mh->peer_cb_cls,
99 &mon_message->peer,
100 (enum GNUNET_CORE_KxState) ntohl (mon_message->state),
101 GNUNET_TIME_absolute_ntoh (mon_message->timeout));
102}
103
104
105/**
106 * Protocol error, reconnect to CORE service and notify
107 * client.
108 *
109 * @param mh monitoring session to reconnect to CORE
110 */
111static void
112reconnect (struct GNUNET_CORE_MonitorHandle *mh)
113{
114 struct GNUNET_MQ_MessageHandler handlers[] =
115 { GNUNET_MQ_hd_fixed_size (receive_info,
116 GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY,
117 struct MonitorNotifyMessage,
118 mh),
119 GNUNET_MQ_handler_end () };
120 struct GNUNET_MQ_Envelope *env;
121 struct GNUNET_MessageHeader *msg;
122
123 if (NULL != mh->mq)
124 GNUNET_MQ_destroy (mh->mq);
125 /* FIXME: use backoff? */
126 mh->mq =
127 GNUNET_CLIENT_connect (mh->cfg, "core", handlers, &handle_mq_error, mh);
128 if (NULL == mh->mq)
129 return;
130 /* notify callback about reconnect */
131 if (NULL != mh->peer_cb)
132 mh->peer_cb (mh->peer_cb_cls,
133 NULL,
134 GNUNET_CORE_KX_CORE_DISCONNECT,
135 GNUNET_TIME_UNIT_FOREVER_ABS);
136 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS);
137 GNUNET_MQ_send (mh->mq, env);
138}
139
140
141/**
142 * Monitor connectivity and KX status of all peers known to CORE.
143 * Calls @a peer_cb with the current status for each connected peer,
144 * and then once with NULL to indicate that all peers that are
145 * currently active have been handled. After that, the iteration
146 * continues until it is cancelled. Normal users of the CORE API are
147 * not expected to use this function. It is different in that it
148 * truly lists all connections (including those where the KX is in
149 * progress), not just those relevant to the application. This
150 * function is used by special applications for diagnostics.
151 *
152 * @param cfg configuration handle
153 * @param peer_cb function to call with the peer information
154 * @param peer_cb_cls closure for @a peer_cb
155 * @return NULL on error
156 */
157struct GNUNET_CORE_MonitorHandle *
158GNUNET_CORE_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
159 GNUNET_CORE_MonitorCallback peer_cb,
160 void *peer_cb_cls)
161{
162 struct GNUNET_CORE_MonitorHandle *mh;
163
164 GNUNET_assert (NULL != peer_cb);
165 mh = GNUNET_new (struct GNUNET_CORE_MonitorHandle);
166 mh->cfg = cfg;
167 reconnect (mh);
168 mh->peer_cb = peer_cb;
169 mh->peer_cb_cls = peer_cb_cls;
170 if (NULL == mh->mq)
171 {
172 GNUNET_free (mh);
173 return NULL;
174 }
175 return mh;
176}
177
178
179/**
180 * Stop monitoring CORE activity.
181 *
182 * @param mh monitor to stop
183 */
184void
185GNUNET_CORE_monitor_stop (struct GNUNET_CORE_MonitorHandle *mh)
186{
187 if (NULL != mh->mq)
188 {
189 GNUNET_MQ_destroy (mh->mq);
190 mh->mq = NULL;
191 }
192 GNUNET_free (mh);
193}
194
195
196/* end of core_api_monitor_peers.c */
diff --git a/src/core/gnunet-core.c b/src/core/gnunet-core.c
deleted file mode 100644
index d90c8e1f5..000000000
--- a/src/core/gnunet-core.c
+++ /dev/null
@@ -1,208 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011, 2012, 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 core/gnunet-core.c
23 * @brief Print information about other peers known to CORE.
24 * @author Nathan Evans
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_core_service.h"
29
30
31/**
32 * Option -m.
33 */
34static int monitor_connections;
35
36/**
37 * Handle to the CORE monitor.
38 */
39static struct GNUNET_CORE_MonitorHandle *mh;
40
41
42/**
43 * Task run in monitor mode when the user presses CTRL-C to abort.
44 * Stops monitoring activity.
45 *
46 * @param cls NULL
47 */
48static void
49shutdown_task (void *cls)
50{
51 (void) cls;
52 if (NULL != mh)
53 {
54 GNUNET_CORE_monitor_stop (mh);
55 mh = NULL;
56 }
57}
58
59
60/**
61 * Function called to notify core users that another
62 * peer changed its state with us.
63 *
64 * @param cls closure
65 * @param peer the peer that changed state
66 * @param state new state of the peer
67 * @param timeout timeout for the new state
68 */
69static void
70monitor_cb (void *cls,
71 const struct GNUNET_PeerIdentity *peer,
72 enum GNUNET_CORE_KxState state,
73 struct GNUNET_TIME_Absolute timeout)
74{
75 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
76 const char *now_str;
77 const char *state_str;
78
79 (void) cls;
80 if (((NULL == peer) || (GNUNET_CORE_KX_ITERATION_FINISHED == state)) &&
81 (GNUNET_NO == monitor_connections))
82 {
83 GNUNET_SCHEDULER_shutdown ();
84 return;
85 }
86
87 switch (state)
88 {
89 case GNUNET_CORE_KX_STATE_DOWN:
90 /* should never happen, as we immediately send the key */
91 state_str = _ ("fresh connection");
92 break;
93
94 case GNUNET_CORE_KX_STATE_KEY_SENT:
95 state_str = _ ("key sent");
96 break;
97
98 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
99 state_str = _ ("key received");
100 break;
101
102 case GNUNET_CORE_KX_STATE_UP:
103 state_str = _ ("connection established");
104 break;
105
106 case GNUNET_CORE_KX_STATE_REKEY_SENT:
107 state_str = _ ("rekeying");
108 break;
109
110 case GNUNET_CORE_KX_PEER_DISCONNECT:
111 state_str = _ ("disconnected");
112 break;
113
114 case GNUNET_CORE_KX_ITERATION_FINISHED:
115 return;
116
117 case GNUNET_CORE_KX_CORE_DISCONNECT:
118 fprintf (stderr,
119 "%s\n",
120 _ ("Connection to CORE service lost (reconnecting)"));
121 return;
122
123 default:
124 state_str = _ ("unknown state");
125 break;
126 }
127 now_str = GNUNET_STRINGS_absolute_time_to_string (now);
128 fprintf (stdout,
129 _ ("%24s: %-30s %4s (timeout in %6s)\n"),
130 now_str,
131 state_str,
132 GNUNET_i2s (peer),
133 GNUNET_STRINGS_relative_time_to_string (
134 GNUNET_TIME_absolute_get_remaining (timeout),
135 GNUNET_YES));
136}
137
138
139/**
140 * Main function that will be run by the scheduler.
141 *
142 * @param cls closure
143 * @param args remaining command-line arguments
144 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
145 * @param cfg configuration
146 */
147static void
148run (void *cls,
149 char *const *args,
150 const char *cfgfile,
151 const struct GNUNET_CONFIGURATION_Handle *cfg)
152{
153 (void) cls;
154 (void) cfgfile;
155 if (NULL != args[0])
156 {
157 fprintf (stderr, _ ("Invalid command line argument `%s'\n"), args[0]);
158 return;
159 }
160 mh = GNUNET_CORE_monitor_start (cfg, &monitor_cb, NULL);
161 if (NULL == mh)
162 {
163 fprintf (stderr, "%s", _ ("Failed to connect to CORE service!\n"));
164 return;
165 }
166 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
167}
168
169
170/**
171 * The main function to obtain peer information from CORE.
172 *
173 * @param argc number of arguments from the command line
174 * @param argv command line arguments
175 * @return 0 ok, 1 on error
176 */
177int
178main (int argc, char *const *argv)
179{
180 int res;
181 struct GNUNET_GETOPT_CommandLineOption options[] =
182 { GNUNET_GETOPT_option_flag (
183 'm',
184 "monitor",
185 gettext_noop (
186 "provide information about all current connections (continuously)"),
187 &monitor_connections),
188 GNUNET_GETOPT_OPTION_END };
189
190 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
191 return 2;
192 res = GNUNET_PROGRAM_run (argc,
193 argv,
194 "gnunet-core",
195 gettext_noop (
196 "Print information about connected peers."),
197 options,
198 &run,
199 NULL);
200
201 GNUNET_free_nz ((void *) argv);
202 if (GNUNET_OK == res)
203 return 0;
204 return 1;
205}
206
207
208/* end of gnunet-core.c */
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c
deleted file mode 100644
index c9c3e3ff5..000000000
--- a/src/core/gnunet-service-core.c
+++ /dev/null
@@ -1,987 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011, 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 core/gnunet-service-core.c
23 * @brief high-level P2P messaging
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include <gcrypt.h>
28#include "gnunet_util_lib.h"
29#include "gnunet-service-core.h"
30#include "gnunet-service-core_kx.h"
31#include "gnunet-service-core_sessions.h"
32#include "gnunet-service-core_typemap.h"
33
34/**
35 * How many messages do we queue up at most for any client? This can
36 * cause messages to be dropped if clients do not process them fast
37 * enough! Note that this is a soft limit; we try
38 * to keep a few larger messages above the limit.
39 */
40#define SOFT_MAX_QUEUE 128
41
42/**
43 * How many messages do we queue up at most for any client? This can
44 * cause messages to be dropped if clients do not process them fast
45 * enough! Note that this is the hard limit.
46 */
47#define HARD_MAX_QUEUE 256
48
49
50/**
51 * Data structure for each client connected to the CORE service.
52 */
53struct GSC_Client
54{
55 /**
56 * Clients are kept in a linked list.
57 */
58 struct GSC_Client *next;
59
60 /**
61 * Clients are kept in a linked list.
62 */
63 struct GSC_Client *prev;
64
65 /**
66 * Handle for the client with the server API.
67 */
68 struct GNUNET_SERVICE_Client *client;
69
70 /**
71 * Message queue to talk to @e client.
72 */
73 struct GNUNET_MQ_Handle *mq;
74
75 /**
76 * Array of the types of messages this peer cares
77 * about (with @e tcnt entries). Allocated as part
78 * of this client struct, do not free!
79 */
80 uint16_t *types;
81
82 /**
83 * Map of peer identities to active transmission requests of this
84 * client to the peer (of type `struct GSC_ClientActiveRequest`).
85 */
86 struct GNUNET_CONTAINER_MultiPeerMap *requests;
87
88 /**
89 * Map containing all peers that this client knows we're connected to.
90 */
91 struct GNUNET_CONTAINER_MultiPeerMap *connectmap;
92
93 /**
94 * Options for messages this client cares about,
95 * see GNUNET_CORE_OPTION_ values.
96 */
97 uint32_t options;
98
99 /**
100 * Have we gotten the #GNUNET_MESSAGE_TYPE_CORE_INIT message
101 * from this client already?
102 */
103 int got_init;
104
105 /**
106 * Number of types of incoming messages this client
107 * specifically cares about. Size of the @e types array.
108 */
109 unsigned int tcnt;
110};
111
112
113/**
114 * Our identity.
115 */
116struct GNUNET_PeerIdentity GSC_my_identity;
117
118/**
119 * Our configuration.
120 */
121const struct GNUNET_CONFIGURATION_Handle *GSC_cfg;
122
123/**
124 * For creating statistics.
125 */
126struct GNUNET_STATISTICS_Handle *GSC_stats;
127
128/**
129 * Big "or" of all client options.
130 */
131static uint32_t all_client_options;
132
133/**
134 * Head of linked list of our clients.
135 */
136static struct GSC_Client *client_head;
137
138/**
139 * Tail of linked list of our clients.
140 */
141static struct GSC_Client *client_tail;
142
143
144/**
145 * Test if the client is interested in messages of the given type.
146 *
147 * @param type message type
148 * @param c client to test
149 * @return #GNUNET_YES if @a c is interested, #GNUNET_NO if not.
150 */
151static int
152type_match (uint16_t type, struct GSC_Client *c)
153{
154 if ((0 == c->tcnt) && (0 != c->options))
155 return GNUNET_YES; /* peer without handlers and inbound/outbond
156 callbacks matches ALL */
157 if (NULL == c->types)
158 return GNUNET_NO;
159 for (unsigned int i = 0; i < c->tcnt; i++)
160 if (type == c->types[i])
161 return GNUNET_YES;
162 return GNUNET_NO;
163}
164
165
166/**
167 * Check #GNUNET_MESSAGE_TYPE_CORE_INIT request.
168 *
169 * @param cls client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT
170 * @param im the `struct InitMessage`
171 * @return #GNUNET_OK if @a im is well-formed
172 */
173static int
174check_client_init (void *cls, const struct InitMessage *im)
175{
176 return GNUNET_OK;
177}
178
179
180/**
181 * Handle #GNUNET_MESSAGE_TYPE_CORE_INIT request.
182 *
183 * @param cls client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT
184 * @param im the `struct InitMessage`
185 */
186static void
187handle_client_init (void *cls, const struct InitMessage *im)
188{
189 struct GSC_Client *c = cls;
190 struct GNUNET_MQ_Envelope *env;
191 struct InitReplyMessage *irm;
192 uint16_t msize;
193 const uint16_t *types;
194
195 /* check that we don't have an entry already */
196 msize = ntohs (im->header.size) - sizeof(struct InitMessage);
197 types = (const uint16_t *) &im[1];
198 c->tcnt = msize / sizeof(uint16_t);
199 c->options = ntohl (im->options);
200 c->got_init = GNUNET_YES;
201 all_client_options |= c->options;
202 c->types = GNUNET_malloc (msize);
203 GNUNET_assert (GNUNET_YES ==
204 GNUNET_CONTAINER_multipeermap_put (
205 c->connectmap,
206 &GSC_my_identity,
207 NULL,
208 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
209 for (unsigned int i = 0; i < c->tcnt; i++)
210 c->types[i] = ntohs (types[i]);
211 GSC_TYPEMAP_add (c->types, c->tcnt);
212 GNUNET_log (
213 GNUNET_ERROR_TYPE_DEBUG,
214 "Client connecting to core service is interested in %u message types\n",
215 (unsigned int) c->tcnt);
216 /* send init reply message */
217 env = GNUNET_MQ_msg (irm, GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY);
218 irm->reserved = htonl (0);
219 irm->my_identity = GSC_my_identity;
220 GNUNET_MQ_send (c->mq, env);
221 GSC_SESSIONS_notify_client_about_sessions (c);
222 GNUNET_SERVICE_client_continue (c->client);
223}
224
225
226/**
227 * We will never be ready to transmit the given message in (disconnect
228 * or invalid request). Frees resources associated with @a car. We
229 * don't explicitly tell the client, it'll learn with the disconnect
230 * (or violated the protocol).
231 *
232 * @param car request that now permanently failed; the
233 * responsibility for the handle is now returned
234 * to CLIENTS (SESSIONS is done with it).
235 * @param drop_client #GNUNET_YES if the client violated the protocol
236 * and we should thus drop the connection
237 */
238void
239GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car,
240 int drop_client)
241{
242 GNUNET_assert (
243 GNUNET_YES ==
244 GNUNET_CONTAINER_multipeermap_remove (car->client_handle->requests,
245 &car->target,
246 car));
247 if (GNUNET_YES == drop_client)
248 GNUNET_SERVICE_client_drop (car->client_handle->client);
249 GNUNET_free (car);
250}
251
252
253/**
254 * Tell a client that we are ready to receive the message.
255 *
256 * @param car request that is now ready; the responsibility
257 * for the handle remains shared between CLIENTS
258 * and SESSIONS after this call.
259 */
260void
261GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car)
262{
263 struct GSC_Client *c;
264 struct GNUNET_MQ_Envelope *env;
265 struct SendMessageReady *smr;
266 struct GNUNET_TIME_Relative delay;
267 struct GNUNET_TIME_Relative left;
268
269 c = car->client_handle;
270 if (GNUNET_YES !=
271 GNUNET_CONTAINER_multipeermap_contains (c->connectmap, &car->target))
272 {
273 /* connection has gone down since, drop request */
274 GNUNET_assert (0 !=
275 GNUNET_memcmp (&car->target,
276 &GSC_my_identity));
277 GSC_SESSIONS_dequeue_request (car);
278 GSC_CLIENTS_reject_request (car, GNUNET_NO);
279 return;
280 }
281 delay = GNUNET_TIME_absolute_get_duration (car->received_time);
282 left = GNUNET_TIME_absolute_get_duration (car->deadline);
283 if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
284 GNUNET_log (
285 GNUNET_ERROR_TYPE_WARNING,
286 "Client waited %s for permission to transmit to `%s'%s (priority %u)\n",
287 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES),
288 GNUNET_i2s (&car->target),
289 (0 == left.rel_value_us) ? " (past deadline)" : "",
290 car->priority);
291 env = GNUNET_MQ_msg (smr, GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
292 smr->size = htons (car->msize);
293 smr->smr_id = car->smr_id;
294 smr->peer = car->target;
295 GNUNET_MQ_send (c->mq, env);
296}
297
298
299/**
300 * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST message.
301 *
302 * @param cls client that sent a #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST
303 * @param req the `struct SendMessageRequest`
304 */
305static void
306handle_client_send_request (void *cls, const struct SendMessageRequest *req)
307{
308 struct GSC_Client *c = cls;
309 struct GSC_ClientActiveRequest *car;
310 int is_loopback;
311
312 if (NULL == c->requests)
313 c->requests = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_NO);
314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
315 "Client asked for transmission to `%s'\n",
316 GNUNET_i2s (&req->peer));
317 is_loopback = (0 == GNUNET_memcmp (&req->peer,
318 &GSC_my_identity));
319 if ((! is_loopback) &&
320 (GNUNET_YES !=
321 GNUNET_CONTAINER_multipeermap_contains (c->connectmap, &req->peer)))
322 {
323 /* neighbour must have disconnected since request was issued,
324 * ignore (client will realize it once it processes the
325 * disconnect notification) */
326 GNUNET_STATISTICS_update (GSC_stats,
327 gettext_noop (
328 "# send requests dropped (disconnected)"),
329 1,
330 GNUNET_NO);
331 GNUNET_SERVICE_client_continue (c->client);
332 return;
333 }
334
335 car = GNUNET_CONTAINER_multipeermap_get (c->requests, &req->peer);
336 if (NULL == car)
337 {
338 /* create new entry */
339 car = GNUNET_new (struct GSC_ClientActiveRequest);
340 GNUNET_assert (GNUNET_OK ==
341 GNUNET_CONTAINER_multipeermap_put (
342 c->requests,
343 &req->peer,
344 car,
345 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
346 car->client_handle = c;
347 }
348 else
349 {
350 /* dequeue and recycle memory from pending request, there can only
351 be at most one per client and peer */
352 GNUNET_STATISTICS_update (GSC_stats,
353 gettext_noop (
354 "# dequeuing CAR (duplicate request)"),
355 1,
356 GNUNET_NO);
357 GSC_SESSIONS_dequeue_request (car);
358 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
359 "Transmission request to `%s' was a duplicate!\n",
360 GNUNET_i2s (&req->peer));
361 }
362 car->target = req->peer;
363 car->received_time = GNUNET_TIME_absolute_get ();
364 car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline);
365 car->priority = (enum GNUNET_MQ_PriorityPreferences) ntohl (req->priority);
366 car->msize = ntohs (req->size);
367 car->smr_id = req->smr_id;
368 car->was_solicited = GNUNET_NO;
369 GNUNET_SERVICE_client_continue (c->client);
370 if (is_loopback)
371 {
372 /* loopback, satisfy immediately */
373 GSC_CLIENTS_solicit_request (car);
374 return;
375 }
376 GSC_SESSIONS_queue_request (car);
377}
378
379
380/**
381 * Closure for the #client_tokenizer_callback().
382 */
383struct TokenizerContext
384{
385 /**
386 * Active request handle for the message.
387 */
388 struct GSC_ClientActiveRequest *car;
389
390 /**
391 * How important is this message.
392 */
393 enum GNUNET_MQ_PriorityPreferences priority;
394};
395
396
397/**
398 * Functions with this signature are called whenever a complete
399 * message is received by the tokenizer. Used by
400 * #handle_client_send() for dispatching messages from clients to
401 * either the SESSION subsystem or other CLIENT (for loopback).
402 *
403 * @param cls reservation request (`struct TokenizerContext`)
404 * @param message the actual message
405 * @return #GNUNET_OK on success,
406 * #GNUNET_NO to stop further processing (no error)
407 * #GNUNET_SYSERR to stop further processing with error
408 */
409static int
410tokenized_cb (void *cls, const struct GNUNET_MessageHeader *message)
411{
412 struct TokenizerContext *tc = cls;
413 struct GSC_ClientActiveRequest *car = tc->car;
414 char buf[92];
415
416 GNUNET_snprintf (buf,
417 sizeof(buf),
418 gettext_noop ("# bytes of messages of type %u received"),
419 (unsigned int) ntohs (message->type));
420 GNUNET_STATISTICS_update (GSC_stats, buf, ntohs (message->size), GNUNET_NO);
421 if (0 == GNUNET_memcmp (&car->target,
422 &GSC_my_identity))
423 {
424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
425 "Delivering message of type %u to myself\n",
426 ntohs (message->type));
427 GSC_CLIENTS_deliver_message (&GSC_my_identity,
428 message,
429 ntohs (message->size),
430 GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
431 GSC_CLIENTS_deliver_message (&GSC_my_identity,
432 message,
433 sizeof(struct GNUNET_MessageHeader),
434 GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
435 GSC_CLIENTS_deliver_message (&GSC_my_identity,
436 message,
437 ntohs (message->size),
438 GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
439 GSC_CLIENTS_deliver_message (&GSC_my_identity,
440 message,
441 sizeof(struct GNUNET_MessageHeader),
442 GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
443 }
444 else
445 {
446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
447 "Delivering message of type %u and size %u to %s\n",
448 ntohs (message->type),
449 ntohs (message->size),
450 GNUNET_i2s (&car->target));
451 GSC_CLIENTS_deliver_message (&car->target,
452 message,
453 ntohs (message->size),
454 GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
455 GSC_CLIENTS_deliver_message (&car->target,
456 message,
457 sizeof(struct GNUNET_MessageHeader),
458 GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
459 GSC_SESSIONS_transmit (car, message, tc->priority);
460 }
461 return GNUNET_OK;
462}
463
464
465/**
466 * Check #GNUNET_MESSAGE_TYPE_CORE_SEND request.
467 *
468 * @param cls the `struct GSC_Client`
469 * @param sm the `struct SendMessage`
470 * @return #GNUNET_OK if @a sm is well-formed
471 */
472static int
473check_client_send (void *cls, const struct SendMessage *sm)
474{
475 return GNUNET_OK;
476}
477
478
479/**
480 * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND request.
481 *
482 * @param cls the `struct GSC_Client`
483 * @param sm the `struct SendMessage`
484 */
485static void
486handle_client_send (void *cls, const struct SendMessage *sm)
487{
488 struct GSC_Client *c = cls;
489 struct TokenizerContext tc;
490 uint16_t msize;
491 struct GNUNET_TIME_Relative delay;
492 struct GNUNET_MessageStreamTokenizer *mst;
493
494 msize = ntohs (sm->header.size) - sizeof(struct SendMessage);
495 tc.car = GNUNET_CONTAINER_multipeermap_get (c->requests, &sm->peer);
496 if (NULL == tc.car)
497 {
498 /* Must have been that we first approved the request, then got disconnected
499 * (which triggered removal of the 'car') and now the client gives us a message
500 * just *before* the client learns about the disconnect. Theoretically, we
501 * might also now be *again* connected. So this can happen (but should be
502 * rare). If it does happen, the message is discarded. */GNUNET_STATISTICS_update (GSC_stats,
503 gettext_noop (
504 "# messages discarded (session disconnected)"),
505 1,
506 GNUNET_NO);
507 GNUNET_SERVICE_client_continue (c->client);
508 return;
509 }
510 delay = GNUNET_TIME_absolute_get_duration (tc.car->received_time);
511 tc.priority = (enum GNUNET_MQ_PriorityPreferences) ntohl (sm->priority);
512 if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
513 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
514 "Client waited %s for transmission of %u bytes to `%s'\n",
515 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES),
516 msize,
517 GNUNET_i2s (&sm->peer));
518 else
519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
520 "Client waited %s for transmission of %u bytes to `%s'\n",
521 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES),
522 msize,
523 GNUNET_i2s (&sm->peer));
524
525 GNUNET_assert (
526 GNUNET_YES ==
527 GNUNET_CONTAINER_multipeermap_remove (c->requests, &sm->peer, tc.car));
528 mst = GNUNET_MST_create (&tokenized_cb, &tc);
529 GNUNET_MST_from_buffer (mst,
530 (const char *) &sm[1],
531 msize,
532 GNUNET_YES,
533 GNUNET_NO);
534 GNUNET_MST_destroy (mst);
535 GSC_SESSIONS_dequeue_request (tc.car);
536 GNUNET_free (tc.car);
537 GNUNET_SERVICE_client_continue (c->client);
538}
539
540
541/**
542 * Free client request records.
543 *
544 * @param cls NULL
545 * @param key identity of peer for which this is an active request
546 * @param value the `struct GSC_ClientActiveRequest` to free
547 * @return #GNUNET_YES (continue iteration)
548 */
549static int
550destroy_active_client_request (void *cls,
551 const struct GNUNET_PeerIdentity *key,
552 void *value)
553{
554 struct GSC_ClientActiveRequest *car = value;
555
556 GNUNET_assert (
557 GNUNET_YES ==
558 GNUNET_CONTAINER_multipeermap_remove (car->client_handle->requests,
559 &car->target,
560 car));
561 GSC_SESSIONS_dequeue_request (car);
562 GNUNET_free (car);
563 return GNUNET_YES;
564}
565
566
567/**
568 * A client connected, set up.
569 *
570 * @param cls closure
571 * @param client identification of the client
572 * @param mq message queue to talk to @a client
573 * @return our client handle
574 */
575static void *
576client_connect_cb (void *cls,
577 struct GNUNET_SERVICE_Client *client,
578 struct GNUNET_MQ_Handle *mq)
579{
580 struct GSC_Client *c;
581
582 c = GNUNET_new (struct GSC_Client);
583 c->client = client;
584 c->mq = mq;
585 c->connectmap = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_NO);
586 GNUNET_CONTAINER_DLL_insert (client_head, client_tail, c);
587 return c;
588}
589
590
591/**
592 * A client disconnected, clean up.
593 *
594 * @param cls closure
595 * @param client identification of the client
596 * @param app_ctx our `struct GST_Client` for @a client
597 */
598static void
599client_disconnect_cb (void *cls,
600 struct GNUNET_SERVICE_Client *client,
601 void *app_ctx)
602{
603 struct GSC_Client *c = app_ctx;
604
605 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
606 "Client %p has disconnected from core service.\n",
607 client);
608 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, c);
609 if (NULL != c->requests)
610 {
611 GNUNET_CONTAINER_multipeermap_iterate (c->requests,
612 &destroy_active_client_request,
613 NULL);
614 GNUNET_CONTAINER_multipeermap_destroy (c->requests);
615 }
616 GNUNET_CONTAINER_multipeermap_destroy (c->connectmap);
617 c->connectmap = NULL;
618 if (NULL != c->types)
619 {
620 GSC_TYPEMAP_remove (c->types, c->tcnt);
621 GNUNET_free (c->types);
622 }
623 GNUNET_free (c);
624
625 /* recalculate 'all_client_options' */
626 all_client_options = 0;
627 for (c = client_head; NULL != c; c = c->next)
628 all_client_options |= c->options;
629}
630
631
632/**
633 * Notify a particular client about a change to existing connection to
634 * one of our neighbours (check if the client is interested). Called
635 * from #GSC_SESSIONS_notify_client_about_sessions().
636 *
637 * @param client client to notify
638 * @param neighbour identity of the neighbour that changed status
639 * @param tmap_old previous type map for the neighbour, NULL for connect
640 * @param tmap_new updated type map for the neighbour, NULL for disconnect
641 */
642void
643GSC_CLIENTS_notify_client_about_neighbour (
644 struct GSC_Client *client,
645 const struct GNUNET_PeerIdentity *neighbour,
646 const struct GSC_TypeMap *tmap_old,
647 const struct GSC_TypeMap *tmap_new)
648{
649 struct GNUNET_MQ_Envelope *env;
650 int old_match;
651 int new_match;
652
653 if (GNUNET_YES != client->got_init)
654 return;
655 old_match = GSC_TYPEMAP_test_match (tmap_old, client->types, client->tcnt);
656 new_match = GSC_TYPEMAP_test_match (tmap_new, client->types, client->tcnt);
657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
658 "Notifying client about neighbour %s (%d/%d)\n",
659 GNUNET_i2s (neighbour),
660 old_match,
661 new_match);
662 if (old_match == new_match)
663 {
664 GNUNET_assert (
665 old_match ==
666 GNUNET_CONTAINER_multipeermap_contains (client->connectmap, neighbour));
667 return; /* no change */
668 }
669 if (GNUNET_NO == old_match)
670 {
671 struct ConnectNotifyMessage *cnm;
672
673 /* send connect */
674 GNUNET_assert (
675 GNUNET_NO ==
676 GNUNET_CONTAINER_multipeermap_contains (client->connectmap, neighbour));
677 GNUNET_assert (GNUNET_YES ==
678 GNUNET_CONTAINER_multipeermap_put (
679 client->connectmap,
680 neighbour,
681 NULL,
682 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
683 env = GNUNET_MQ_msg (cnm, GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
684 cnm->reserved = htonl (0);
685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
686 "Sending NOTIFY_CONNECT message about peer %s to client.\n",
687 GNUNET_i2s (neighbour));
688 cnm->peer = *neighbour;
689 GNUNET_MQ_send (client->mq, env);
690 }
691 else
692 {
693 struct DisconnectNotifyMessage *dcm;
694
695 /* send disconnect */
696 GNUNET_assert (
697 GNUNET_YES ==
698 GNUNET_CONTAINER_multipeermap_contains (client->connectmap, neighbour));
699 GNUNET_assert (GNUNET_YES ==
700 GNUNET_CONTAINER_multipeermap_remove (client->connectmap,
701 neighbour,
702 NULL));
703 env = GNUNET_MQ_msg (dcm, GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
704 dcm->reserved = htonl (0);
705 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
706 "Sending NOTIFY_DISCONNECT message about peer %s to client.\n",
707 GNUNET_i2s (neighbour));
708 dcm->peer = *neighbour;
709 GNUNET_MQ_send (client->mq, env);
710 }
711}
712
713
714/**
715 * Notify all clients about a change to existing session.
716 * Called from SESSIONS whenever there is a change in sessions
717 * or types processed by the respective peer.
718 *
719 * @param neighbour identity of the neighbour that changed status
720 * @param tmap_old previous type map for the neighbour, NULL for connect
721 * @param tmap_new updated type map for the neighbour, NULL for disconnect
722 */
723void
724GSC_CLIENTS_notify_clients_about_neighbour (
725 const struct GNUNET_PeerIdentity *neighbour,
726 const struct GSC_TypeMap *tmap_old,
727 const struct GSC_TypeMap *tmap_new)
728{
729 struct GSC_Client *c;
730
731 for (c = client_head; NULL != c; c = c->next)
732 GSC_CLIENTS_notify_client_about_neighbour (c,
733 neighbour,
734 tmap_old,
735 tmap_new);
736}
737
738
739/**
740 * Deliver P2P message to interested clients. Caller must have checked
741 * that the sending peer actually lists the given message type as one
742 * of its types.
743 *
744 * @param sender peer who sent us the message
745 * @param msg the message
746 * @param msize number of bytes to transmit
747 * @param options options for checking which clients should
748 * receive the message
749 */
750void
751GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender,
752 const struct GNUNET_MessageHeader *msg,
753 uint16_t msize,
754 uint32_t options)
755{
756 size_t size = msize + sizeof(struct NotifyTrafficMessage);
757
758 if (size >= GNUNET_MAX_MESSAGE_SIZE)
759 {
760 GNUNET_break (0);
761 return;
762 }
763 if (! ((0 != (all_client_options & options)) ||
764 (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND))))
765 return; /* no client cares about this message notification */
766 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
767 "Core service passes message from `%s' of type %u to client.\n",
768 GNUNET_i2s (sender),
769 (unsigned int) ntohs (msg->type));
770 GSC_SESSIONS_add_to_typemap (sender, ntohs (msg->type));
771
772 for (struct GSC_Client *c = client_head; NULL != c; c = c->next)
773 {
774 struct GNUNET_MQ_Envelope *env;
775 struct NotifyTrafficMessage *ntm;
776 uint16_t mtype;
777 unsigned int qlen;
778 int tm;
779
780 tm = type_match (ntohs (msg->type), c);
781 if (! ((0 != (c->options & options)) ||
782 ((0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) &&
783 (GNUNET_YES == tm))))
784 continue; /* neither options nor type match permit the message */
785 if ((0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) &&
786 ((0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
787 (GNUNET_YES == tm)))
788 continue;
789 if ((0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) &&
790 (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)))
791 continue;
792
793 /* Drop messages if:
794 1) We are above the hard limit, or
795 2) We are above the soft limit, and a coin toss limited
796 to the message size (giving larger messages a
797 proportionally higher chance of being queued) falls
798 below the threshold. The threshold is based on where
799 we are between the soft and the hard limit, scaled
800 to match the range of message sizes we usually encounter
801 (i.e. up to 32k); so a 64k message has a 50% chance of
802 being kept if we are just barely below the hard max,
803 and a 99% chance of being kept if we are at the soft max.
804 The reason is to make it more likely to drop control traffic
805 (ACK, queries) which may be cumulative or highly redundant,
806 and cheap to drop than data traffic. */qlen = GNUNET_MQ_get_length (c->mq);
807 if ((qlen >= HARD_MAX_QUEUE) ||
808 ((qlen > SOFT_MAX_QUEUE) &&
809 ((GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
810 ntohs (msg->size))) <
811 (qlen - SOFT_MAX_QUEUE) * 0x8000
812 / (HARD_MAX_QUEUE - SOFT_MAX_QUEUE))))
813 {
814 char buf[1024];
815
816 GNUNET_log (
817 GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
818 "Dropping decrypted message of type %u as client is too busy (queue full)\n",
819 (unsigned int) ntohs (msg->type));
820 GNUNET_snprintf (buf,
821 sizeof(buf),
822 gettext_noop (
823 "# messages of type %u discarded (client busy)"),
824 (unsigned int) ntohs (msg->type));
825 GNUNET_STATISTICS_update (GSC_stats, buf, 1, GNUNET_NO);
826 continue;
827 }
828
829 GNUNET_log (
830 GNUNET_ERROR_TYPE_DEBUG,
831 "Sending %u message with %u bytes to client interested in messages of type %u.\n",
832 options,
833 ntohs (msg->size),
834 (unsigned int) ntohs (msg->type));
835
836 if (0 != (options & (GNUNET_CORE_OPTION_SEND_FULL_INBOUND
837 | GNUNET_CORE_OPTION_SEND_HDR_INBOUND)))
838 mtype = GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND;
839 else
840 mtype = GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND;
841 env = GNUNET_MQ_msg_extra (ntm, msize, mtype);
842 ntm->peer = *sender;
843 GNUNET_memcpy (&ntm[1], msg, msize);
844
845 GNUNET_assert (
846 (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
847 (GNUNET_YES != tm) ||
848 (GNUNET_YES ==
849 GNUNET_CONTAINER_multipeermap_contains (c->connectmap, sender)));
850 GNUNET_MQ_send (c->mq, env);
851 }
852}
853
854
855/**
856 * Last task run during shutdown. Disconnects us from
857 * the transport.
858 *
859 * @param cls NULL, unused
860 */
861static void
862shutdown_task (void *cls)
863{
864 struct GSC_Client *c;
865
866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service shutting down.\n");
867 while (NULL != (c = client_head))
868 GNUNET_SERVICE_client_drop (c->client);
869 GSC_SESSIONS_done ();
870 GSC_KX_done ();
871 GSC_TYPEMAP_done ();
872 if (NULL != GSC_stats)
873 {
874 GNUNET_STATISTICS_destroy (GSC_stats, GNUNET_NO);
875 GSC_stats = NULL;
876 }
877 GSC_cfg = NULL;
878}
879
880
881/**
882 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
883 * request type, the client does not have to have transmitted an INIT
884 * request. All current peers are returned, regardless of which
885 * message types they accept.
886 *
887 * @param cls client sending the iteration request
888 * @param message iteration request message
889 */
890static void
891handle_client_monitor_peers (void *cls,
892 const struct GNUNET_MessageHeader *message)
893{
894 struct GSC_Client *c = cls;
895
896 GNUNET_SERVICE_client_continue (c->client);
897 GSC_KX_handle_client_monitor_peers (c->mq);
898}
899
900
901/**
902 * Initiate core service.
903 *
904 * @param cls closure
905 * @param c configuration to use
906 * @param service the initialized service
907 */
908static void
909run (void *cls,
910 const struct GNUNET_CONFIGURATION_Handle *c,
911 struct GNUNET_SERVICE_Handle *service)
912{
913 struct GNUNET_CRYPTO_EddsaPrivateKey pk;
914 char *keyfile;
915
916 GSC_cfg = c;
917 if (GNUNET_OK !=
918 GNUNET_CONFIGURATION_get_value_filename (GSC_cfg,
919 "PEER",
920 "PRIVATE_KEY",
921 &keyfile))
922 {
923 GNUNET_log (
924 GNUNET_ERROR_TYPE_ERROR,
925 _ ("Core service is lacking HOSTKEY configuration setting. Exiting.\n"));
926 GNUNET_SCHEDULER_shutdown ();
927 return;
928 }
929 GSC_stats = GNUNET_STATISTICS_create ("core", GSC_cfg);
930 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
931 GNUNET_SERVICE_suspend (service);
932 GSC_TYPEMAP_init ();
933 if (GNUNET_SYSERR ==
934 GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
935 GNUNET_YES,
936 &pk))
937 {
938 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
939 "Failed to setup peer's private key\n");
940 GNUNET_SCHEDULER_shutdown ();
941 GNUNET_free (keyfile);
942 return;
943 }
944 GNUNET_free (keyfile);
945 if (GNUNET_OK != GSC_KX_init (&pk))
946 {
947 GNUNET_SCHEDULER_shutdown ();
948 return;
949 }
950 GSC_SESSIONS_init ();
951 GNUNET_SERVICE_resume (service);
952 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
953 _ ("Core service of `%s' ready.\n"),
954 GNUNET_i2s (&GSC_my_identity));
955}
956
957
958/**
959 * Define "main" method using service macro.
960 */
961GNUNET_SERVICE_MAIN (
962 "core",
963 GNUNET_SERVICE_OPTION_NONE,
964 &run,
965 &client_connect_cb,
966 &client_disconnect_cb,
967 NULL,
968 GNUNET_MQ_hd_var_size (client_init,
969 GNUNET_MESSAGE_TYPE_CORE_INIT,
970 struct InitMessage,
971 NULL),
972 GNUNET_MQ_hd_fixed_size (client_monitor_peers,
973 GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS,
974 struct GNUNET_MessageHeader,
975 NULL),
976 GNUNET_MQ_hd_fixed_size (client_send_request,
977 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
978 struct SendMessageRequest,
979 NULL),
980 GNUNET_MQ_hd_var_size (client_send,
981 GNUNET_MESSAGE_TYPE_CORE_SEND,
982 struct SendMessage,
983 NULL),
984 GNUNET_MQ_handler_end ());
985
986
987/* end of gnunet-service-core.c */
diff --git a/src/core/gnunet-service-core.h b/src/core/gnunet-service-core.h
deleted file mode 100644
index 0f71f221a..000000000
--- a/src/core/gnunet-service-core.h
+++ /dev/null
@@ -1,198 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 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 core/gnunet-service-core.h
23 * @brief Globals for gnunet-service-core
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_CORE_H
27#define GNUNET_SERVICE_CORE_H
28
29#include "gnunet_statistics_service.h"
30#include "gnunet_core_service.h"
31#include "core.h"
32#include "gnunet-service-core_typemap.h"
33
34
35/**
36 * Opaque handle to a client.
37 */
38struct GSC_Client;
39
40
41/**
42 * Record kept for each request for transmission issued by a
43 * client that is still pending. (This struct is used by
44 * both the 'CLIENTS' and 'SESSIONS' subsystems.)
45 */
46struct GSC_ClientActiveRequest
47{
48 /**
49 * Active requests are kept in a doubly-linked list of
50 * the respective target peer.
51 */
52 struct GSC_ClientActiveRequest *next;
53
54 /**
55 * Active requests are kept in a doubly-linked list of
56 * the respective target peer.
57 */
58 struct GSC_ClientActiveRequest *prev;
59
60 /**
61 * Handle to the client.
62 */
63 struct GSC_Client *client_handle;
64
65 /**
66 * Which peer is the message going to be for?
67 */
68 struct GNUNET_PeerIdentity target;
69
70 /**
71 * At what time did we first see this request?
72 */
73 struct GNUNET_TIME_Absolute received_time;
74
75 /**
76 * By what time would the client want to see this message out?
77 */
78 struct GNUNET_TIME_Absolute deadline;
79
80 /**
81 * How important is this request.
82 */
83 enum GNUNET_MQ_PriorityPreferences priority;
84
85 /**
86 * Has this request been solicited yet?
87 */
88 int was_solicited;
89
90 /**
91 * How many bytes does the client intend to send?
92 */
93 uint16_t msize;
94
95 /**
96 * Unique request ID (in big endian).
97 */
98 uint16_t smr_id;
99};
100
101
102/**
103 * Tell a client that we are ready to receive the message.
104 *
105 * @param car request that is now ready; the responsibility
106 * for the handle remains shared between CLIENTS
107 * and SESSIONS after this call.
108 */
109void
110GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car);
111
112
113/**
114 * We will never be ready to transmit the given message in (disconnect
115 * or invalid request). Frees resources associated with @a car. We
116 * don't explicitly tell the client, it'll learn with the disconnect
117 * (or violated the protocol).
118 *
119 * @param car request that now permanently failed; the
120 * responsibility for the handle is now returned
121 * to CLIENTS (SESSIONS is done with it).
122 * @param drop_client #GNUNET_YES if the client violated the protocol
123 * and we should thus drop the connection
124 */
125void
126GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car,
127 int drop_client);
128
129
130/**
131 * Notify a particular client about a change to existing connection to
132 * one of our neighbours (check if the client is interested). Called
133 * from #GSC_SESSIONS_notify_client_about_sessions().
134 *
135 * @param client client to notify
136 * @param neighbour identity of the neighbour that changed status
137 * @param tmap_old previous type map for the neighbour, NULL for connect
138 * @param tmap_new updated type map for the neighbour, NULL for disconnect
139 */
140void
141GSC_CLIENTS_notify_client_about_neighbour (
142 struct GSC_Client *client,
143 const struct GNUNET_PeerIdentity *neighbour,
144 const struct GSC_TypeMap *tmap_old,
145 const struct GSC_TypeMap *tmap_new);
146
147
148/**
149 * Deliver P2P message to interested clients. Caller must have checked
150 * that the sending peer actually lists the given message type as one
151 * of its types.
152 *
153 * @param sender peer who sent us the message
154 * @param msg the message
155 * @param msize number of bytes to transmit
156 * @param options options for checking which clients should
157 * receive the message
158 */
159void
160GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender,
161 const struct GNUNET_MessageHeader *msg,
162 uint16_t msize,
163 uint32_t options);
164
165
166/**
167 * Notify all clients about a change to existing session.
168 * Called from SESSIONS whenever there is a change in sessions
169 * or types processed by the respective peer.
170 *
171 * @param neighbour identity of the neighbour that changed status
172 * @param tmap_old previous type map for the neighbour, NULL for connect
173 * @param tmap_new updated type map for the neighbour, NULL for disconnect
174 */
175void
176GSC_CLIENTS_notify_clients_about_neighbour (
177 const struct GNUNET_PeerIdentity *neighbour,
178 const struct GSC_TypeMap *tmap_old,
179 const struct GSC_TypeMap *tmap_new);
180
181
182/**
183 * Our configuration.
184 */
185extern const struct GNUNET_CONFIGURATION_Handle *GSC_cfg;
186
187/**
188 * For creating statistics.
189 */
190extern struct GNUNET_STATISTICS_Handle *GSC_stats;
191
192/**
193 * Our identity.
194 */
195extern struct GNUNET_PeerIdentity GSC_my_identity;
196
197
198#endif
diff --git a/src/core/gnunet-service-core_kx.c b/src/core/gnunet-service-core_kx.c
deleted file mode 100644
index 07c346485..000000000
--- a/src/core/gnunet-service-core_kx.c
+++ /dev/null
@@ -1,1945 +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 core/gnunet-service-core_kx.c
23 * @brief code for managing the key exchange (SET_KEY, PING, PONG) with other
24 * peers
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet-service-core_kx.h"
29#include "gnunet-service-core.h"
30#include "gnunet-service-core_sessions.h"
31#include "gnunet_statistics_service.h"
32#include "gnunet_transport_service.h"
33#include "gnunet_constants.h"
34#include "gnunet_signatures.h"
35#include "gnunet_protocols.h"
36#include "core.h"
37
38/**
39 * Enable expensive (and possibly problematic for privacy!) logging of KX.
40 */
41#define DEBUG_KX 0
42
43/**
44 * How long do we wait for SET_KEY confirmation initially?
45 */
46#define INITIAL_SET_KEY_RETRY_FREQUENCY \
47 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
48
49/**
50 * What is the minimum frequency for a PING message?
51 */
52#define MIN_PING_FREQUENCY \
53 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
54
55/**
56 * How often do we rekey?
57 */
58#define REKEY_FREQUENCY \
59 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
60
61/**
62 * What time difference do we tolerate?
63 */
64#define REKEY_TOLERANCE \
65 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
66
67/**
68 * What is the maximum age of a message for us to consider processing
69 * it? Note that this looks at the timestamp used by the other peer,
70 * so clock skew between machines does come into play here. So this
71 * should be picked high enough so that a little bit of clock skew
72 * does not prevent peers from connecting to us.
73 */
74#define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS
75
76
77GNUNET_NETWORK_STRUCT_BEGIN
78
79/**
80 * Encapsulation for encrypted messages exchanged between
81 * peers. Followed by the actual encrypted data.
82 */
83struct EncryptedMessage
84{
85 /**
86 * Message type is #GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE.
87 */
88 struct GNUNET_MessageHeader header;
89
90 /**
91 * Random value used for IV generation.
92 */
93 uint32_t iv_seed GNUNET_PACKED;
94
95 /**
96 * MAC of the encrypted message (starting at @e sequence_number),
97 * used to verify message integrity. Everything after this value
98 * (excluding this value itself) will be encrypted and
99 * authenticated. #ENCRYPTED_HEADER_SIZE must be set to the offset
100 * of the *next* field.
101 */
102 struct GNUNET_HashCode hmac;
103
104 /**
105 * Sequence number, in network byte order. This field
106 * must be the first encrypted/decrypted field
107 */
108 uint32_t sequence_number GNUNET_PACKED;
109
110 /**
111 * Reserved, always zero.
112 */
113 uint32_t reserved GNUNET_PACKED;
114
115 /**
116 * Timestamp. Used to prevent replay of ancient messages
117 * (recent messages are caught with the sequence number).
118 */
119 struct GNUNET_TIME_AbsoluteNBO timestamp;
120};
121GNUNET_NETWORK_STRUCT_END
122
123
124/**
125 * Number of bytes (at the beginning) of `struct EncryptedMessage`
126 * that are NOT encrypted.
127 */
128#define ENCRYPTED_HEADER_SIZE \
129 (offsetof (struct EncryptedMessage, sequence_number))
130
131
132/**
133 * Information about the status of a key exchange with another peer.
134 */
135struct GSC_KeyExchangeInfo
136{
137 /**
138 * DLL.
139 */
140 struct GSC_KeyExchangeInfo *next;
141
142 /**
143 * DLL.
144 */
145 struct GSC_KeyExchangeInfo *prev;
146
147 /**
148 * Identity of the peer.
149 */
150 const struct GNUNET_PeerIdentity *peer;
151
152 /**
153 * Message queue for sending messages to @a peer.
154 */
155 struct GNUNET_MQ_Handle *mq;
156
157 /**
158 * Our message stream tokenizer (for encrypted payload).
159 */
160 struct GNUNET_MessageStreamTokenizer *mst;
161
162 /**
163 * PING message we transmit to the other peer.
164 */
165 struct PingMessage ping;
166
167 /**
168 * Ephemeral public ECC key of the other peer.
169 */
170 struct GNUNET_CRYPTO_EcdhePublicKey other_ephemeral_key;
171
172 /**
173 * Key we use to encrypt our messages for the other peer
174 * (initialized by us when we do the handshake).
175 */
176 struct GNUNET_CRYPTO_SymmetricSessionKey encrypt_key;
177
178 /**
179 * Key we use to decrypt messages from the other peer
180 * (given to us by the other peer during the handshake).
181 */
182 struct GNUNET_CRYPTO_SymmetricSessionKey decrypt_key;
183
184 /**
185 * At what time did the other peer generate the decryption key?
186 */
187 struct GNUNET_TIME_Absolute foreign_key_expires;
188
189 /**
190 * When should the session time out (if there are no PONGs)?
191 */
192 struct GNUNET_TIME_Absolute timeout;
193
194 /**
195 * What was the last timeout we informed our monitors about?
196 */
197 struct GNUNET_TIME_Absolute last_notify_timeout;
198
199 /**
200 * At what frequency are we currently re-trying SET_KEY messages?
201 */
202 struct GNUNET_TIME_Relative set_key_retry_frequency;
203
204 /**
205 * ID of task used for re-trying SET_KEY and PING message.
206 */
207 struct GNUNET_SCHEDULER_Task *retry_set_key_task;
208
209 /**
210 * ID of task used for sending keep-alive pings.
211 */
212 struct GNUNET_SCHEDULER_Task *keep_alive_task;
213
214 /**
215 * Bit map indicating which of the 32 sequence numbers before the
216 * last were received (good for accepting out-of-order packets and
217 * estimating reliability of the connection)
218 */
219 uint32_t last_packets_bitmap;
220
221 /**
222 * last sequence number received on this connection (highest)
223 */
224 uint32_t last_sequence_number_received;
225
226 /**
227 * last sequence number transmitted
228 */
229 uint32_t last_sequence_number_sent;
230
231 /**
232 * What was our PING challenge number (for this peer)?
233 */
234 uint32_t ping_challenge;
235
236 /**
237 * #GNUNET_YES if this peer currently has excess bandwidth.
238 */
239 int has_excess_bandwidth;
240
241 /**
242 * What is our connection status?
243 */
244 enum GNUNET_CORE_KxState status;
245};
246
247
248/**
249 * Transport service.
250 */
251static struct GNUNET_TRANSPORT_CoreHandle *transport;
252
253/**
254 * Our private key.
255 */
256static struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key;
257
258/**
259 * Our ephemeral private key.
260 */
261static struct GNUNET_CRYPTO_EcdhePrivateKey my_ephemeral_key;
262
263/**
264 * Current message we send for a key exchange.
265 */
266static struct EphemeralKeyMessage current_ekm;
267
268/**
269 * DLL head.
270 */
271static struct GSC_KeyExchangeInfo *kx_head;
272
273/**
274 * DLL tail.
275 */
276static struct GSC_KeyExchangeInfo *kx_tail;
277
278/**
279 * Task scheduled for periodic re-generation (and thus rekeying) of our
280 * ephemeral key.
281 */
282static struct GNUNET_SCHEDULER_Task *rekey_task;
283
284/**
285 * Notification context for broadcasting to monitors.
286 */
287static struct GNUNET_NotificationContext *nc;
288
289
290/**
291 * Calculate seed value we should use for a message.
292 *
293 * @param kx key exchange context
294 */
295static uint32_t
296calculate_seed (struct GSC_KeyExchangeInfo *kx)
297{
298 /* Note: may want to make this non-random and instead
299 derive from key material to avoid having an undetectable
300 side-channel */
301 return htonl (
302 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
303}
304
305
306/**
307 * Inform all monitors about the KX state of the given peer.
308 *
309 * @param kx key exchange state to inform about
310 */
311static void
312monitor_notify_all (struct GSC_KeyExchangeInfo *kx)
313{
314 struct MonitorNotifyMessage msg;
315
316 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
317 msg.header.size = htons (sizeof(msg));
318 msg.state = htonl ((uint32_t) kx->status);
319 msg.peer = *kx->peer;
320 msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
321 GNUNET_notification_context_broadcast (nc, &msg.header, GNUNET_NO);
322 kx->last_notify_timeout = kx->timeout;
323}
324
325
326/**
327 * Derive an authentication key from "set key" information
328 *
329 * @param akey authentication key to derive
330 * @param skey session key to use
331 * @param seed seed to use
332 */
333static void
334derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey,
335 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
336 uint32_t seed)
337{
338 static const char ctx[] = "authentication key";
339
340#if DEBUG_KX
341 struct GNUNET_HashCode sh;
342
343 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
345 "Deriving Auth key from SKEY %s and seed %u\n",
346 GNUNET_h2s (&sh),
347 (unsigned int) seed);
348#endif
349 GNUNET_CRYPTO_hmac_derive_key (akey,
350 skey,
351 &seed,
352 sizeof(seed),
353 skey,
354 sizeof(
355 struct GNUNET_CRYPTO_SymmetricSessionKey),
356 ctx,
357 sizeof(ctx),
358 NULL);
359}
360
361
362/**
363 * Derive an IV from packet information
364 *
365 * @param iv initialization vector to initialize
366 * @param skey session key to use
367 * @param seed seed to use
368 * @param identity identity of the other peer to use
369 */
370static void
371derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
372 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
373 uint32_t seed,
374 const struct GNUNET_PeerIdentity *identity)
375{
376 static const char ctx[] = "initialization vector";
377
378#if DEBUG_KX
379 struct GNUNET_HashCode sh;
380
381 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
382 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
383 "Deriving IV from SKEY %s and seed %u for peer %s\n",
384 GNUNET_h2s (&sh),
385 (unsigned int) seed,
386 GNUNET_i2s (identity));
387#endif
388 GNUNET_CRYPTO_symmetric_derive_iv (iv,
389 skey,
390 &seed,
391 sizeof(seed),
392 identity,
393 sizeof(struct GNUNET_PeerIdentity),
394 ctx,
395 sizeof(ctx),
396 NULL);
397}
398
399
400/**
401 * Derive an IV from pong packet information
402 *
403 * @param iv initialization vector to initialize
404 * @param skey session key to use
405 * @param seed seed to use
406 * @param challenge nonce to use
407 * @param identity identity of the other peer to use
408 */
409static void
410derive_pong_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
411 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
412 uint32_t seed,
413 uint32_t challenge,
414 const struct GNUNET_PeerIdentity *identity)
415{
416 static const char ctx[] = "pong initialization vector";
417
418#if DEBUG_KX
419 struct GNUNET_HashCode sh;
420
421 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
422 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
423 "Deriving PONG IV from SKEY %s and seed %u/%u for %s\n",
424 GNUNET_h2s (&sh),
425 (unsigned int) seed,
426 (unsigned int) challenge,
427 GNUNET_i2s (identity));
428#endif
429 GNUNET_CRYPTO_symmetric_derive_iv (iv,
430 skey,
431 &seed,
432 sizeof(seed),
433 identity,
434 sizeof(struct GNUNET_PeerIdentity),
435 &challenge,
436 sizeof(challenge),
437 ctx,
438 sizeof(ctx),
439 NULL);
440}
441
442
443/**
444 * Derive an AES key from key material
445 *
446 * @param sender peer identity of the sender
447 * @param receiver peer identity of the sender
448 * @param key_material high entropy key material to use
449 * @param skey set to derived session key
450 */
451static void
452derive_aes_key (const struct GNUNET_PeerIdentity *sender,
453 const struct GNUNET_PeerIdentity *receiver,
454 const struct GNUNET_HashCode *key_material,
455 struct GNUNET_CRYPTO_SymmetricSessionKey *skey)
456{
457 static const char ctx[] = "aes key generation vector";
458
459#if DEBUG_KX
460 struct GNUNET_HashCode sh;
461
462 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
464 "Deriving AES Keys for %s to %s from %s\n",
465 GNUNET_i2s (sender),
466 GNUNET_i2s2 (receiver),
467 GNUNET_h2s (key_material));
468#endif
469 GNUNET_CRYPTO_kdf (skey,
470 sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey),
471 ctx,
472 sizeof(ctx),
473 key_material,
474 sizeof(struct GNUNET_HashCode),
475 sender,
476 sizeof(struct GNUNET_PeerIdentity),
477 receiver,
478 sizeof(struct GNUNET_PeerIdentity),
479 NULL);
480}
481
482
483/**
484 * Encrypt size bytes from @a in and write the result to @a out. Use the
485 * @a kx key for outbound traffic of the given neighbour.
486 *
487 * @param kx key information context
488 * @param iv initialization vector to use
489 * @param in ciphertext
490 * @param out plaintext
491 * @param size size of @a in/@a out
492 * @return #GNUNET_OK on success
493 */
494static int
495do_encrypt (struct GSC_KeyExchangeInfo *kx,
496 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
497 const void *in,
498 void *out,
499 size_t size)
500{
501 if (size != (uint16_t) size)
502 {
503 GNUNET_break (0);
504 return GNUNET_NO;
505 }
506 GNUNET_assert (size == GNUNET_CRYPTO_symmetric_encrypt (in,
507 (uint16_t) size,
508 &kx->encrypt_key,
509 iv,
510 out));
511 GNUNET_STATISTICS_update (GSC_stats,
512 gettext_noop ("# bytes encrypted"),
513 size,
514 GNUNET_NO);
515 /* the following is too sensitive to write to log files by accident,
516 so we require manual intervention to get this one... */
517#if DEBUG_KX
518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
519 "Encrypted %u bytes for `%s' using key %u, IV %u\n",
520 (unsigned int) size,
521 GNUNET_i2s (kx->peer),
522 (unsigned int) kx->encrypt_key.crc32,
523 GNUNET_CRYPTO_crc32_n (iv, sizeof(iv)));
524#endif
525 return GNUNET_OK;
526}
527
528
529/**
530 * Decrypt size bytes from @a in and write the result to @a out. Use
531 * the @a kx key for inbound traffic of the given neighbour. This
532 * function does NOT do any integrity-checks on the result.
533 *
534 * @param kx key information context
535 * @param iv initialization vector to use
536 * @param in ciphertext
537 * @param out plaintext
538 * @param size size of @a in / @a out
539 * @return #GNUNET_OK on success
540 */
541static int
542do_decrypt (struct GSC_KeyExchangeInfo *kx,
543 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
544 const void *in,
545 void *out,
546 size_t size)
547{
548 if (size != (uint16_t) size)
549 {
550 GNUNET_break (0);
551 return GNUNET_NO;
552 }
553 if ((kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
554 (kx->status != GNUNET_CORE_KX_STATE_UP) &&
555 (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT))
556 {
557 GNUNET_break_op (0);
558 return GNUNET_SYSERR;
559 }
560 if (size != GNUNET_CRYPTO_symmetric_decrypt (in,
561 (uint16_t) size,
562 &kx->decrypt_key,
563 iv,
564 out))
565 {
566 GNUNET_break (0);
567 return GNUNET_SYSERR;
568 }
569 GNUNET_STATISTICS_update (GSC_stats,
570 gettext_noop ("# bytes decrypted"),
571 size,
572 GNUNET_NO);
573 /* the following is too sensitive to write to log files by accident,
574 so we require manual intervention to get this one... */
575#if DEBUG_KX
576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
577 "Decrypted %u bytes from `%s' using key %u, IV %u\n",
578 (unsigned int) size,
579 GNUNET_i2s (kx->peer),
580 (unsigned int) kx->decrypt_key.crc32,
581 GNUNET_CRYPTO_crc32_n (iv, sizeof(*iv)));
582#endif
583 return GNUNET_OK;
584}
585
586
587/**
588 * Send our key (and encrypted PING) to the other peer.
589 *
590 * @param kx key exchange context
591 */
592static void
593send_key (struct GSC_KeyExchangeInfo *kx);
594
595
596/**
597 * Task that will retry #send_key() if our previous attempt failed.
598 *
599 * @param cls our `struct GSC_KeyExchangeInfo`
600 */
601static void
602set_key_retry_task (void *cls)
603{
604 struct GSC_KeyExchangeInfo *kx = cls;
605
606 kx->retry_set_key_task = NULL;
607 kx->set_key_retry_frequency =
608 GNUNET_TIME_STD_BACKOFF (kx->set_key_retry_frequency);
609 GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
610 send_key (kx);
611}
612
613
614/**
615 * Create a fresh PING message for transmission to the other peer.
616 *
617 * @param kx key exchange context to create PING for
618 */
619static void
620setup_fresh_ping (struct GSC_KeyExchangeInfo *kx)
621{
622 struct PingMessage pp;
623 struct PingMessage *pm;
624 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
625
626 pm = &kx->ping;
627 kx->ping_challenge =
628 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
629 pm->header.size = htons (sizeof(struct PingMessage));
630 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
631 pm->iv_seed = calculate_seed (kx);
632 derive_iv (&iv, &kx->encrypt_key, pm->iv_seed, kx->peer);
633 pp.challenge = kx->ping_challenge;
634 pp.target = *kx->peer;
635 do_encrypt (kx,
636 &iv,
637 &pp.target,
638 &pm->target,
639 sizeof(struct PingMessage)
640 - ((void *) &pm->target - (void *) pm));
641}
642
643
644/**
645 * Deliver P2P message to interested clients. Invokes send twice,
646 * once for clients that want the full message, and once for clients
647 * that only want the header
648 *
649 * @param cls the `struct GSC_KeyExchangeInfo`
650 * @param m the message
651 * @return #GNUNET_OK on success,
652 * #GNUNET_NO to stop further processing (no error)
653 * #GNUNET_SYSERR to stop further processing with error
654 */
655static int
656deliver_message (void *cls, const struct GNUNET_MessageHeader *m)
657{
658 struct GSC_KeyExchangeInfo *kx = cls;
659
660 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
661 "Decrypted message of type %d from %s\n",
662 ntohs (m->type),
663 GNUNET_i2s (kx->peer));
664 if (GNUNET_CORE_KX_STATE_UP != kx->status)
665 {
666 GNUNET_STATISTICS_update (GSC_stats,
667 gettext_noop ("# PAYLOAD dropped (out of order)"),
668 1,
669 GNUNET_NO);
670 return GNUNET_OK;
671 }
672 switch (ntohs (m->type))
673 {
674 case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP:
675 case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
676 GSC_SESSIONS_set_typemap (kx->peer, m);
677 return GNUNET_OK;
678
679 case GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP:
680 GSC_SESSIONS_confirm_typemap (kx->peer, m);
681 return GNUNET_OK;
682
683 default:
684 GSC_CLIENTS_deliver_message (kx->peer,
685 m,
686 ntohs (m->size),
687 GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
688 GSC_CLIENTS_deliver_message (kx->peer,
689 m,
690 sizeof(struct GNUNET_MessageHeader),
691 GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
692 }
693 return GNUNET_OK;
694}
695
696
697/**
698 * Function called by transport to notify us that
699 * a peer connected to us (on the network level).
700 * Starts the key exchange with the given peer.
701 *
702 * @param cls closure (NULL)
703 * @param pid identity of the peer to do a key exchange with
704 * @return key exchange information context
705 */
706static void *
707handle_transport_notify_connect (void *cls,
708 const struct GNUNET_PeerIdentity *pid,
709 struct GNUNET_MQ_Handle *mq)
710{
711 struct GSC_KeyExchangeInfo *kx;
712 struct GNUNET_HashCode h1;
713 struct GNUNET_HashCode h2;
714
715 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
716 "Initiating key exchange with `%s'\n",
717 GNUNET_i2s (pid));
718 GNUNET_STATISTICS_update (GSC_stats,
719 gettext_noop ("# key exchanges initiated"),
720 1,
721 GNUNET_NO);
722 kx = GNUNET_new (struct GSC_KeyExchangeInfo);
723 kx->mst = GNUNET_MST_create (&deliver_message, kx);
724 kx->mq = mq;
725 kx->peer = pid;
726 kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
727 GNUNET_CONTAINER_DLL_insert (kx_head, kx_tail, kx);
728 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
729 monitor_notify_all (kx);
730 GNUNET_CRYPTO_hash (pid, sizeof(struct GNUNET_PeerIdentity), &h1);
731 GNUNET_CRYPTO_hash (&GSC_my_identity,
732 sizeof(struct GNUNET_PeerIdentity),
733 &h2);
734 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, &h2))
735 {
736 /* peer with "lower" identity starts KX, otherwise we typically end up
737 with both peers starting the exchange and transmit the 'set key'
738 message twice */
739 send_key (kx);
740 }
741 else
742 {
743 /* peer with "higher" identity starts a delayed KX, if the "lower" peer
744 * does not start a KX since it sees no reasons to do so */
745 kx->retry_set_key_task =
746 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
747 &set_key_retry_task,
748 kx);
749 }
750 return kx;
751}
752
753
754/**
755 * Function called by transport telling us that a peer
756 * disconnected.
757 * Stop key exchange with the given peer. Clean up key material.
758 *
759 * @param cls closure
760 * @param peer the peer that disconnected
761 * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer
762 */
763static void
764handle_transport_notify_disconnect (void *cls,
765 const struct GNUNET_PeerIdentity *peer,
766 void *handler_cls)
767{
768 struct GSC_KeyExchangeInfo *kx = handler_cls;
769
770 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
771 "Peer `%s' disconnected from us.\n",
772 GNUNET_i2s (peer));
773 GSC_SESSIONS_end (kx->peer);
774 GNUNET_STATISTICS_update (GSC_stats,
775 gettext_noop ("# key exchanges stopped"),
776 1,
777 GNUNET_NO);
778 if (NULL != kx->retry_set_key_task)
779 {
780 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
781 kx->retry_set_key_task = NULL;
782 }
783 if (NULL != kx->keep_alive_task)
784 {
785 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
786 kx->keep_alive_task = NULL;
787 }
788 kx->status = GNUNET_CORE_KX_PEER_DISCONNECT;
789 monitor_notify_all (kx);
790 GNUNET_CONTAINER_DLL_remove (kx_head, kx_tail, kx);
791 GNUNET_MST_destroy (kx->mst);
792 GNUNET_free (kx);
793}
794
795
796/**
797 * Send our PING to the other peer.
798 *
799 * @param kx key exchange context
800 */
801static void
802send_ping (struct GSC_KeyExchangeInfo *kx)
803{
804 struct GNUNET_MQ_Envelope *env;
805
806 GNUNET_STATISTICS_update (GSC_stats,
807 gettext_noop ("# PING messages transmitted"),
808 1,
809 GNUNET_NO);
810 env = GNUNET_MQ_msg_copy (&kx->ping.header);
811 GNUNET_MQ_send (kx->mq, env);
812}
813
814
815/**
816 * Derive fresh session keys from the current ephemeral keys.
817 *
818 * @param kx session to derive keys for
819 */
820static void
821derive_session_keys (struct GSC_KeyExchangeInfo *kx)
822{
823 struct GNUNET_HashCode key_material;
824
825 if (GNUNET_OK !=
826 GNUNET_CRYPTO_ecc_ecdh (&my_ephemeral_key,
827 &kx->other_ephemeral_key,
828 &key_material))
829 {
830 GNUNET_break (0);
831 return;
832 }
833 derive_aes_key (&GSC_my_identity, kx->peer, &key_material, &kx->encrypt_key);
834 derive_aes_key (kx->peer, &GSC_my_identity, &key_material, &kx->decrypt_key);
835 memset (&key_material, 0, sizeof(key_material));
836 /* fresh key, reset sequence numbers */
837 kx->last_sequence_number_received = 0;
838 kx->last_packets_bitmap = 0;
839 setup_fresh_ping (kx);
840}
841
842
843/**
844 * We received a #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY message.
845 * Validate and update our key material and status.
846 *
847 * @param cls key exchange status for the corresponding peer
848 * @param m the set key message we received
849 */
850static void
851handle_ephemeral_key (void *cls, const struct EphemeralKeyMessage *m)
852{
853 struct GSC_KeyExchangeInfo *kx = cls;
854 struct GNUNET_TIME_Absolute start_t;
855 struct GNUNET_TIME_Absolute end_t;
856 struct GNUNET_TIME_Absolute now;
857 enum GNUNET_CORE_KxState sender_status;
858
859 end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time);
860 if (((GNUNET_CORE_KX_STATE_KEY_RECEIVED == kx->status) ||
861 (GNUNET_CORE_KX_STATE_UP == kx->status) ||
862 (GNUNET_CORE_KX_STATE_REKEY_SENT == kx->status)) &&
863 (end_t.abs_value_us < kx->foreign_key_expires.abs_value_us))
864 {
865 GNUNET_STATISTICS_update (GSC_stats,
866 gettext_noop ("# old ephemeral keys ignored"),
867 1,
868 GNUNET_NO);
869 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
870 "Received expired EPHEMERAL_KEY from %s\n",
871 GNUNET_i2s (&m->origin_identity));
872 return;
873 }
874 if (0 == memcmp (&m->ephemeral_key,
875 &kx->other_ephemeral_key,
876 sizeof(m->ephemeral_key)))
877 {
878 GNUNET_STATISTICS_update (GSC_stats,
879 gettext_noop (
880 "# duplicate ephemeral keys ignored"),
881 1,
882 GNUNET_NO);
883 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
884 "Ignoring duplicate EPHEMERAL_KEY from %s\n",
885 GNUNET_i2s (&m->origin_identity));
886 return;
887 }
888 if (0 != memcmp (&m->origin_identity,
889 kx->peer,
890 sizeof(struct GNUNET_PeerIdentity)))
891 {
892 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
893 "Received EPHEMERAL_KEY from %s, but expected %s\n",
894 GNUNET_i2s (&m->origin_identity),
895 GNUNET_i2s_full (kx->peer));
896 GNUNET_break_op (0);
897 return;
898 }
899 if ((ntohl (m->purpose.size) !=
900 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
901 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
902 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
903 + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
904 + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) ||
905 (GNUNET_OK !=
906 GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY,
907 &m->purpose,
908 &m->signature,
909 &m->origin_identity.public_key)))
910 {
911 /* invalid signature */
912 GNUNET_break_op (0);
913 GNUNET_STATISTICS_update (GSC_stats,
914 gettext_noop (
915 "# EPHEMERAL_KEYs rejected (bad signature)"),
916 1,
917 GNUNET_NO);
918 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
919 "Received EPHEMERAL_KEY from %s with bad signature\n",
920 GNUNET_i2s (&m->origin_identity));
921 return;
922 }
923 now = GNUNET_TIME_absolute_get ();
924 start_t = GNUNET_TIME_absolute_ntoh (m->creation_time);
925 if ((end_t.abs_value_us <
926 GNUNET_TIME_absolute_subtract (now, REKEY_TOLERANCE).abs_value_us) ||
927 (start_t.abs_value_us >
928 GNUNET_TIME_absolute_add (now, REKEY_TOLERANCE).abs_value_us))
929 {
930 GNUNET_log (
931 GNUNET_ERROR_TYPE_WARNING,
932 _ (
933 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match our system time (%llu not in [%llu,%llu]).\n"),
934 GNUNET_i2s (kx->peer),
935 (unsigned long long) now.abs_value_us,
936 (unsigned long long) start_t.abs_value_us,
937 (unsigned long long) end_t.abs_value_us);
938 GNUNET_STATISTICS_update (GSC_stats,
939 gettext_noop (
940 "# EPHEMERAL_KEY messages rejected due to time"),
941 1,
942 GNUNET_NO);
943 return;
944 }
945#if DEBUG_KX
946 {
947 struct GNUNET_HashCode eh;
948
949 GNUNET_CRYPTO_hash (&m->ephemeral_key, sizeof(m->ephemeral_key), &eh);
950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
951 "Received valid EPHEMERAL_KEY `%s' from `%s' in state %d.\n",
952 GNUNET_h2s (&eh),
953 GNUNET_i2s (kx->peer),
954 kx->status);
955 }
956#endif
957 GNUNET_STATISTICS_update (GSC_stats,
958 gettext_noop ("# valid ephemeral keys received"),
959 1,
960 GNUNET_NO);
961 kx->other_ephemeral_key = m->ephemeral_key;
962 kx->foreign_key_expires = end_t;
963 derive_session_keys (kx);
964
965 /* check if we still need to send the sender our key */
966 sender_status = (enum GNUNET_CORE_KxState) ntohl (m->sender_status);
967 switch (sender_status)
968 {
969 case GNUNET_CORE_KX_STATE_DOWN:
970 GNUNET_break_op (0);
971 break;
972
973 case GNUNET_CORE_KX_STATE_KEY_SENT:
974 /* fine, need to send our key after updating our status, see below */
975 GSC_SESSIONS_reinit (kx->peer);
976 break;
977
978 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
979 /* other peer already got our key, but typemap did go down */
980 GSC_SESSIONS_reinit (kx->peer);
981 break;
982
983 case GNUNET_CORE_KX_STATE_UP:
984 /* other peer already got our key, typemap NOT down */
985 break;
986
987 case GNUNET_CORE_KX_STATE_REKEY_SENT:
988 /* other peer already got our key, typemap NOT down */
989 break;
990
991 default:
992 GNUNET_break (0);
993 break;
994 }
995 /* check if we need to confirm everything is fine via PING + PONG */
996 switch (kx->status)
997 {
998 case GNUNET_CORE_KX_STATE_DOWN:
999 GNUNET_assert (NULL == kx->keep_alive_task);
1000 kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
1001 monitor_notify_all (kx);
1002 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1003 send_key (kx);
1004 else
1005 send_ping (kx);
1006 break;
1007
1008 case GNUNET_CORE_KX_STATE_KEY_SENT:
1009 GNUNET_assert (NULL == kx->keep_alive_task);
1010 kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
1011 monitor_notify_all (kx);
1012 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1013 send_key (kx);
1014 else
1015 send_ping (kx);
1016 break;
1017
1018 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1019 GNUNET_assert (NULL == kx->keep_alive_task);
1020 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1021 send_key (kx);
1022 else
1023 send_ping (kx);
1024 break;
1025
1026 case GNUNET_CORE_KX_STATE_UP:
1027 kx->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1028 monitor_notify_all (kx);
1029 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1030 send_key (kx);
1031 else
1032 send_ping (kx);
1033 break;
1034
1035 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1036 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1037 send_key (kx);
1038 else
1039 send_ping (kx);
1040 break;
1041
1042 default:
1043 GNUNET_break (0);
1044 break;
1045 }
1046}
1047
1048
1049/**
1050 * We received a PING message. Validate and transmit
1051 * a PONG message.
1052 *
1053 * @param cls key exchange status for the corresponding peer
1054 * @param m the encrypted PING message itself
1055 */
1056static void
1057handle_ping (void *cls, const struct PingMessage *m)
1058{
1059 struct GSC_KeyExchangeInfo *kx = cls;
1060 struct PingMessage t;
1061 struct PongMessage tx;
1062 struct PongMessage *tp;
1063 struct GNUNET_MQ_Envelope *env;
1064 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1065
1066 GNUNET_STATISTICS_update (GSC_stats,
1067 gettext_noop ("# PING messages received"),
1068 1,
1069 GNUNET_NO);
1070 if ((kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
1071 (kx->status != GNUNET_CORE_KX_STATE_UP) &&
1072 (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT))
1073 {
1074 /* ignore */
1075 GNUNET_STATISTICS_update (GSC_stats,
1076 gettext_noop (
1077 "# PING messages dropped (out of order)"),
1078 1,
1079 GNUNET_NO);
1080 return;
1081 }
1082 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1083 "Core service receives PING request from `%s'.\n",
1084 GNUNET_i2s (kx->peer));
1085 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1086 if (GNUNET_OK != do_decrypt (kx,
1087 &iv,
1088 &m->target,
1089 &t.target,
1090 sizeof(struct PingMessage)
1091 - ((void *) &m->target - (void *) m)))
1092 {
1093 GNUNET_break_op (0);
1094 return;
1095 }
1096 if (0 !=
1097 memcmp (&t.target, &GSC_my_identity, sizeof(struct GNUNET_PeerIdentity)))
1098 {
1099 if (GNUNET_CORE_KX_STATE_REKEY_SENT != kx->status)
1100 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1101 "Decryption of PING from peer `%s' failed, PING for `%s'?\n",
1102 GNUNET_i2s (kx->peer),
1103 GNUNET_i2s2 (&t.target));
1104 else
1105 GNUNET_log (
1106 GNUNET_ERROR_TYPE_DEBUG,
1107 "Decryption of PING from peer `%s' failed after rekey (harmless)\n",
1108 GNUNET_i2s (kx->peer));
1109 GNUNET_break_op (0);
1110 return;
1111 }
1112 /* construct PONG */
1113 tx.reserved = 0;
1114 tx.challenge = t.challenge;
1115 tx.target = t.target;
1116 env = GNUNET_MQ_msg (tp, GNUNET_MESSAGE_TYPE_CORE_PONG);
1117 tp->iv_seed = calculate_seed (kx);
1118 derive_pong_iv (&iv, &kx->encrypt_key, tp->iv_seed, t.challenge, kx->peer);
1119 do_encrypt (kx,
1120 &iv,
1121 &tx.challenge,
1122 &tp->challenge,
1123 sizeof(struct PongMessage)
1124 - ((void *) &tp->challenge - (void *) tp));
1125 GNUNET_STATISTICS_update (GSC_stats,
1126 gettext_noop ("# PONG messages created"),
1127 1,
1128 GNUNET_NO);
1129 GNUNET_MQ_send (kx->mq, env);
1130}
1131
1132
1133/**
1134 * Task triggered when a neighbour entry is about to time out
1135 * (and we should prevent this by sending a PING).
1136 *
1137 * @param cls the `struct GSC_KeyExchangeInfo`
1138 */
1139static void
1140send_keep_alive (void *cls)
1141{
1142 struct GSC_KeyExchangeInfo *kx = cls;
1143 struct GNUNET_TIME_Relative retry;
1144 struct GNUNET_TIME_Relative left;
1145
1146 kx->keep_alive_task = NULL;
1147 left = GNUNET_TIME_absolute_get_remaining (kx->timeout);
1148 if (0 == left.rel_value_us)
1149 {
1150 GNUNET_STATISTICS_update (GSC_stats,
1151 gettext_noop ("# sessions terminated by timeout"),
1152 1,
1153 GNUNET_NO);
1154 GSC_SESSIONS_end (kx->peer);
1155 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1156 monitor_notify_all (kx);
1157 send_key (kx);
1158 return;
1159 }
1160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1161 "Sending KEEPALIVE to `%s'\n",
1162 GNUNET_i2s (kx->peer));
1163 GNUNET_STATISTICS_update (GSC_stats,
1164 gettext_noop ("# keepalive messages sent"),
1165 1,
1166 GNUNET_NO);
1167 setup_fresh_ping (kx);
1168 send_ping (kx);
1169 retry = GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
1170 MIN_PING_FREQUENCY);
1171 kx->keep_alive_task =
1172 GNUNET_SCHEDULER_add_delayed (retry, &send_keep_alive, kx);
1173}
1174
1175
1176/**
1177 * We've seen a valid message from the other peer.
1178 * Update the time when the session would time out
1179 * and delay sending our keep alive message further.
1180 *
1181 * @param kx key exchange where we saw activity
1182 */
1183static void
1184update_timeout (struct GSC_KeyExchangeInfo *kx)
1185{
1186 struct GNUNET_TIME_Relative delta;
1187
1188 kx->timeout =
1189 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1190 delta =
1191 GNUNET_TIME_absolute_get_difference (kx->last_notify_timeout, kx->timeout);
1192 if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
1193 {
1194 /* we only notify monitors about timeout changes if those
1195 are bigger than the threshold (5s) */
1196 monitor_notify_all (kx);
1197 }
1198 if (NULL != kx->keep_alive_task)
1199 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1200 kx->keep_alive_task = GNUNET_SCHEDULER_add_delayed (
1201 GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
1202 &send_keep_alive,
1203 kx);
1204}
1205
1206
1207/**
1208 * We received a PONG message. Validate and update our status.
1209 *
1210 * @param kx key exchange context for the the PONG
1211 * @param m the encrypted PONG message itself
1212 */
1213static void
1214handle_pong (void *cls, const struct PongMessage *m)
1215{
1216 struct GSC_KeyExchangeInfo *kx = cls;
1217 struct PongMessage t;
1218 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1219
1220 GNUNET_STATISTICS_update (GSC_stats,
1221 gettext_noop ("# PONG messages received"),
1222 1,
1223 GNUNET_NO);
1224 switch (kx->status)
1225 {
1226 case GNUNET_CORE_KX_STATE_DOWN:
1227 GNUNET_STATISTICS_update (GSC_stats,
1228 gettext_noop (
1229 "# PONG messages dropped (connection down)"),
1230 1,
1231 GNUNET_NO);
1232 return;
1233
1234 case GNUNET_CORE_KX_STATE_KEY_SENT:
1235 GNUNET_STATISTICS_update (GSC_stats,
1236 gettext_noop (
1237 "# PONG messages dropped (out of order)"),
1238 1,
1239 GNUNET_NO);
1240 return;
1241
1242 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1243 break;
1244
1245 case GNUNET_CORE_KX_STATE_UP:
1246 break;
1247
1248 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1249 break;
1250
1251 default:
1252 GNUNET_break (0);
1253 return;
1254 }
1255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1256 "Core service receives PONG response from `%s'.\n",
1257 GNUNET_i2s (kx->peer));
1258 /* mark as garbage, just to be sure */
1259 memset (&t, 255, sizeof(t));
1260 derive_pong_iv (&iv,
1261 &kx->decrypt_key,
1262 m->iv_seed,
1263 kx->ping_challenge,
1264 &GSC_my_identity);
1265 if (GNUNET_OK != do_decrypt (kx,
1266 &iv,
1267 &m->challenge,
1268 &t.challenge,
1269 sizeof(struct PongMessage)
1270 - ((void *) &m->challenge - (void *) m)))
1271 {
1272 GNUNET_break_op (0);
1273 return;
1274 }
1275 GNUNET_STATISTICS_update (GSC_stats,
1276 gettext_noop ("# PONG messages decrypted"),
1277 1,
1278 GNUNET_NO);
1279 if ((0 !=
1280 memcmp (&t.target, kx->peer, sizeof(struct GNUNET_PeerIdentity))) ||
1281 (kx->ping_challenge != t.challenge))
1282 {
1283 /* PONG malformed */
1284 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1285 "Received malformed PONG wanted sender `%s' with challenge %u\n",
1286 GNUNET_i2s (kx->peer),
1287 (unsigned int) kx->ping_challenge);
1288 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1289 "Received malformed PONG received from `%s' with challenge %u\n",
1290 GNUNET_i2s (&t.target),
1291 (unsigned int) t.challenge);
1292 return;
1293 }
1294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1295 "Received valid PONG from `%s'\n",
1296 GNUNET_i2s (kx->peer));
1297 /* no need to resend key any longer */
1298 if (NULL != kx->retry_set_key_task)
1299 {
1300 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1301 kx->retry_set_key_task = NULL;
1302 }
1303 switch (kx->status)
1304 {
1305 case GNUNET_CORE_KX_STATE_DOWN:
1306 GNUNET_assert (0); /* should be impossible */
1307 return;
1308
1309 case GNUNET_CORE_KX_STATE_KEY_SENT:
1310 GNUNET_assert (0); /* should be impossible */
1311 return;
1312
1313 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1314 GNUNET_STATISTICS_update (GSC_stats,
1315 gettext_noop (
1316 "# session keys confirmed via PONG"),
1317 1,
1318 GNUNET_NO);
1319 kx->status = GNUNET_CORE_KX_STATE_UP;
1320 monitor_notify_all (kx);
1321 GSC_SESSIONS_create (kx->peer, kx);
1322 GNUNET_assert (NULL == kx->keep_alive_task);
1323 update_timeout (kx);
1324 break;
1325
1326 case GNUNET_CORE_KX_STATE_UP:
1327 GNUNET_STATISTICS_update (GSC_stats,
1328 gettext_noop ("# timeouts prevented via PONG"),
1329 1,
1330 GNUNET_NO);
1331 update_timeout (kx);
1332 break;
1333
1334 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1335 GNUNET_STATISTICS_update (GSC_stats,
1336 gettext_noop (
1337 "# rekey operations confirmed via PONG"),
1338 1,
1339 GNUNET_NO);
1340 kx->status = GNUNET_CORE_KX_STATE_UP;
1341 monitor_notify_all (kx);
1342 update_timeout (kx);
1343 break;
1344
1345 default:
1346 GNUNET_break (0);
1347 break;
1348 }
1349}
1350
1351
1352/**
1353 * Send our key to the other peer.
1354 *
1355 * @param kx key exchange context
1356 */
1357static void
1358send_key (struct GSC_KeyExchangeInfo *kx)
1359{
1360 struct GNUNET_MQ_Envelope *env;
1361
1362 GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
1363 if (NULL != kx->retry_set_key_task)
1364 {
1365 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1366 kx->retry_set_key_task = NULL;
1367 }
1368 /* always update sender status in SET KEY message */
1369#if DEBUG_KX
1370 {
1371 struct GNUNET_HashCode hc;
1372
1373 GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1374 sizeof(current_ekm.ephemeral_key),
1375 &hc);
1376 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1377 "Sending EPHEMERAL_KEY %s to `%s' (my status: %d)\n",
1378 GNUNET_h2s (&hc),
1379 GNUNET_i2s (kx->peer),
1380 kx->status);
1381 }
1382#endif
1383 current_ekm.sender_status = htonl ((int32_t) (kx->status));
1384 env = GNUNET_MQ_msg_copy (&current_ekm.header);
1385 GNUNET_MQ_send (kx->mq, env);
1386 if (GNUNET_CORE_KX_STATE_KEY_SENT != kx->status)
1387 send_ping (kx);
1388 kx->retry_set_key_task =
1389 GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency,
1390 &set_key_retry_task,
1391 kx);
1392}
1393
1394
1395/**
1396 * Encrypt and transmit a message with the given payload.
1397 *
1398 * @param kx key exchange context
1399 * @param payload payload of the message
1400 * @param payload_size number of bytes in @a payload
1401 */
1402void
1403GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
1404 const void *payload,
1405 size_t payload_size)
1406{
1407 size_t used = payload_size + sizeof(struct EncryptedMessage);
1408 char pbuf[used]; /* plaintext */
1409 struct EncryptedMessage *em; /* encrypted message */
1410 struct EncryptedMessage *ph; /* plaintext header */
1411 struct GNUNET_MQ_Envelope *env;
1412 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1413 struct GNUNET_CRYPTO_AuthKey auth_key;
1414
1415 ph = (struct EncryptedMessage *) pbuf;
1416 ph->sequence_number = htonl (++kx->last_sequence_number_sent);
1417 ph->iv_seed = calculate_seed (kx);
1418 ph->reserved = 0;
1419 ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1420 GNUNET_memcpy (&ph[1], payload, payload_size);
1421 env = GNUNET_MQ_msg_extra (em,
1422 payload_size,
1423 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
1424 em->iv_seed = ph->iv_seed;
1425 derive_iv (&iv, &kx->encrypt_key, ph->iv_seed, kx->peer);
1426 GNUNET_assert (GNUNET_OK == do_encrypt (kx,
1427 &iv,
1428 &ph->sequence_number,
1429 &em->sequence_number,
1430 used - ENCRYPTED_HEADER_SIZE));
1431#if DEBUG_KX
1432 {
1433 struct GNUNET_HashCode hc;
1434
1435 GNUNET_CRYPTO_hash (&ph->sequence_number,
1436 used - ENCRYPTED_HEADER_SIZE,
1437 &hc);
1438 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1439 "Encrypted payload `%s' of %u bytes for %s\n",
1440 GNUNET_h2s (&hc),
1441 (unsigned int) (used - ENCRYPTED_HEADER_SIZE),
1442 GNUNET_i2s (kx->peer));
1443 }
1444#endif
1445 derive_auth_key (&auth_key, &kx->encrypt_key, ph->iv_seed);
1446 GNUNET_CRYPTO_hmac (&auth_key,
1447 &em->sequence_number,
1448 used - ENCRYPTED_HEADER_SIZE,
1449 &em->hmac);
1450#if DEBUG_KX
1451 {
1452 struct GNUNET_HashCode hc;
1453
1454 GNUNET_CRYPTO_hash (&auth_key, sizeof(auth_key), &hc);
1455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1456 "For peer %s, used AC %s to create hmac %s\n",
1457 GNUNET_i2s (kx->peer),
1458 GNUNET_h2s (&hc),
1459 GNUNET_h2s2 (&em->hmac));
1460 }
1461#endif
1462 kx->has_excess_bandwidth = GNUNET_NO;
1463 GNUNET_MQ_send (kx->mq, env);
1464}
1465
1466
1467/**
1468 * We received an encrypted message. Check that it is
1469 * well-formed (size-wise).
1470 *
1471 * @param cls key exchange context for encrypting the message
1472 * @param m encrypted message
1473 * @return #GNUNET_OK if @a msg is well-formed (size-wise)
1474 */
1475static int
1476check_encrypted (void *cls, const struct EncryptedMessage *m)
1477{
1478 uint16_t size = ntohs (m->header.size) - sizeof(*m);
1479
1480 if (size < sizeof(struct GNUNET_MessageHeader))
1481 {
1482 GNUNET_break_op (0);
1483 return GNUNET_SYSERR;
1484 }
1485 return GNUNET_OK;
1486}
1487
1488
1489/**
1490 * We received an encrypted message. Decrypt, validate and
1491 * pass on to the appropriate clients.
1492 *
1493 * @param cls key exchange context for encrypting the message
1494 * @param m encrypted message
1495 */
1496static void
1497handle_encrypted (void *cls, const struct EncryptedMessage *m)
1498{
1499 struct GSC_KeyExchangeInfo *kx = cls;
1500 struct EncryptedMessage *pt; /* plaintext */
1501 struct GNUNET_HashCode ph;
1502 uint32_t snum;
1503 struct GNUNET_TIME_Absolute t;
1504 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1505 struct GNUNET_CRYPTO_AuthKey auth_key;
1506 uint16_t size = ntohs (m->header.size);
1507 char buf[size] GNUNET_ALIGN;
1508
1509 if (GNUNET_CORE_KX_STATE_UP != kx->status)
1510 {
1511 GNUNET_STATISTICS_update (GSC_stats,
1512 gettext_noop (
1513 "# DATA message dropped (out of order)"),
1514 1,
1515 GNUNET_NO);
1516 return;
1517 }
1518 if (0 ==
1519 GNUNET_TIME_absolute_get_remaining (kx->foreign_key_expires).rel_value_us)
1520 {
1521 GNUNET_log (
1522 GNUNET_ERROR_TYPE_WARNING,
1523 _ (
1524 "Session to peer `%s' went down due to key expiration (should not happen)\n"),
1525 GNUNET_i2s (kx->peer));
1526 GNUNET_STATISTICS_update (GSC_stats,
1527 gettext_noop (
1528 "# sessions terminated by key expiration"),
1529 1,
1530 GNUNET_NO);
1531 GSC_SESSIONS_end (kx->peer);
1532 if (NULL != kx->keep_alive_task)
1533 {
1534 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1535 kx->keep_alive_task = NULL;
1536 }
1537 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1538 monitor_notify_all (kx);
1539 send_key (kx);
1540 return;
1541 }
1542
1543 /* validate hash */
1544#if DEBUG_KX
1545 {
1546 struct GNUNET_HashCode hc;
1547
1548 GNUNET_CRYPTO_hash (&m->sequence_number, size - ENCRYPTED_HEADER_SIZE, &hc);
1549 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1550 "Received encrypted payload `%s' of %u bytes from %s\n",
1551 GNUNET_h2s (&hc),
1552 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1553 GNUNET_i2s (kx->peer));
1554 }
1555#endif
1556 derive_auth_key (&auth_key, &kx->decrypt_key, m->iv_seed);
1557 GNUNET_CRYPTO_hmac (&auth_key,
1558 &m->sequence_number,
1559 size - ENCRYPTED_HEADER_SIZE,
1560 &ph);
1561#if DEBUG_KX
1562 {
1563 struct GNUNET_HashCode hc;
1564
1565 GNUNET_CRYPTO_hash (&auth_key, sizeof(auth_key), &hc);
1566 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1567 "For peer %s, used AC %s to verify hmac %s\n",
1568 GNUNET_i2s (kx->peer),
1569 GNUNET_h2s (&hc),
1570 GNUNET_h2s2 (&m->hmac));
1571 }
1572#endif
1573 if (0 != memcmp (&ph, &m->hmac, sizeof(struct GNUNET_HashCode)))
1574 {
1575 /* checksum failed */
1576 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1577 "Failed checksum validation for a message from `%s'\n",
1578 GNUNET_i2s (kx->peer));
1579 return;
1580 }
1581 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1582 /* decrypt */
1583 if (GNUNET_OK != do_decrypt (kx,
1584 &iv,
1585 &m->sequence_number,
1586 &buf[ENCRYPTED_HEADER_SIZE],
1587 size - ENCRYPTED_HEADER_SIZE))
1588 {
1589 GNUNET_break_op (0);
1590 return;
1591 }
1592 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1593 "Decrypted %u bytes from %s\n",
1594 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1595 GNUNET_i2s (kx->peer));
1596 pt = (struct EncryptedMessage *) buf;
1597
1598 /* validate sequence number */
1599 snum = ntohl (pt->sequence_number);
1600 if (kx->last_sequence_number_received == snum)
1601 {
1602 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1603 "Received duplicate message, ignoring.\n");
1604 /* duplicate, ignore */
1605 GNUNET_STATISTICS_update (GSC_stats,
1606 gettext_noop ("# bytes dropped (duplicates)"),
1607 size,
1608 GNUNET_NO);
1609 return;
1610 }
1611 if ((kx->last_sequence_number_received > snum) &&
1612 (kx->last_sequence_number_received - snum > 32))
1613 {
1614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1615 "Received ancient out of sequence message, ignoring.\n");
1616 /* ancient out of sequence, ignore */
1617 GNUNET_STATISTICS_update (GSC_stats,
1618 gettext_noop (
1619 "# bytes dropped (out of sequence)"),
1620 size,
1621 GNUNET_NO);
1622 return;
1623 }
1624 if (kx->last_sequence_number_received > snum)
1625 {
1626 uint32_t rotbit = 1U << (kx->last_sequence_number_received - snum - 1);
1627
1628 if ((kx->last_packets_bitmap & rotbit) != 0)
1629 {
1630 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1631 "Received duplicate message, ignoring.\n");
1632 GNUNET_STATISTICS_update (GSC_stats,
1633 gettext_noop ("# bytes dropped (duplicates)"),
1634 size,
1635 GNUNET_NO);
1636 /* duplicate, ignore */
1637 return;
1638 }
1639 kx->last_packets_bitmap |= rotbit;
1640 }
1641 if (kx->last_sequence_number_received < snum)
1642 {
1643 unsigned int shift = (snum - kx->last_sequence_number_received);
1644
1645 if (shift >= 8 * sizeof(kx->last_packets_bitmap))
1646 kx->last_packets_bitmap = 0;
1647 else
1648 kx->last_packets_bitmap <<= shift;
1649 kx->last_sequence_number_received = snum;
1650 }
1651
1652 /* check timestamp */
1653 t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
1654 if (GNUNET_TIME_absolute_get_duration (t).rel_value_us >
1655 MAX_MESSAGE_AGE.rel_value_us)
1656 {
1657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1658 "Message received far too old (%s). Content ignored.\n",
1659 GNUNET_STRINGS_relative_time_to_string (
1660 GNUNET_TIME_absolute_get_duration (t),
1661 GNUNET_YES));
1662 GNUNET_STATISTICS_update (GSC_stats,
1663 gettext_noop (
1664 "# bytes dropped (ancient message)"),
1665 size,
1666 GNUNET_NO);
1667 return;
1668 }
1669
1670 /* process decrypted message(s) */
1671 update_timeout (kx);
1672 GNUNET_STATISTICS_update (GSC_stats,
1673 gettext_noop ("# bytes of payload decrypted"),
1674 size - sizeof(struct EncryptedMessage),
1675 GNUNET_NO);
1676 if (GNUNET_OK !=
1677 GNUNET_MST_from_buffer (kx->mst,
1678 &buf[sizeof(struct EncryptedMessage)],
1679 size - sizeof(struct EncryptedMessage),
1680 GNUNET_YES,
1681 GNUNET_NO))
1682 GNUNET_break_op (0);
1683}
1684
1685
1686/**
1687 * One of our neighbours has excess bandwidth, remember this.
1688 *
1689 * @param cls NULL
1690 * @param pid identity of the peer with excess bandwidth
1691 * @param connect_cls the `struct Neighbour`
1692 */
1693static void
1694handle_transport_notify_excess_bw (void *cls,
1695 const struct GNUNET_PeerIdentity *pid,
1696 void *connect_cls)
1697{
1698 struct GSC_KeyExchangeInfo *kx = connect_cls;
1699
1700 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1701 "Peer %s has excess bandwidth available\n",
1702 GNUNET_i2s (pid));
1703 kx->has_excess_bandwidth = GNUNET_YES;
1704 GSC_SESSIONS_solicit (pid);
1705}
1706
1707
1708/**
1709 * Setup the message that links the ephemeral key to our persistent
1710 * public key and generate the appropriate signature.
1711 */
1712static void
1713sign_ephemeral_key ()
1714{
1715 current_ekm.header.size = htons (sizeof(struct EphemeralKeyMessage));
1716 current_ekm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY);
1717 current_ekm.sender_status = 0; /* to be set later */
1718 current_ekm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY);
1719 current_ekm.purpose.size =
1720 htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
1721 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1722 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1723 + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
1724 + sizeof(struct GNUNET_PeerIdentity));
1725 current_ekm.creation_time =
1726 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1727 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (GSC_cfg,
1728 "core",
1729 "USE_EPHEMERAL_KEYS"))
1730 {
1731 current_ekm.expiration_time =
1732 GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (
1733 GNUNET_TIME_relative_add (REKEY_FREQUENCY,
1734 REKEY_TOLERANCE)));
1735 }
1736 else
1737 {
1738 current_ekm.expiration_time =
1739 GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
1740 }
1741 GNUNET_CRYPTO_ecdhe_key_get_public (&my_ephemeral_key,
1742 &current_ekm.ephemeral_key);
1743 current_ekm.origin_identity = GSC_my_identity;
1744 GNUNET_assert (GNUNET_OK ==
1745 GNUNET_CRYPTO_eddsa_sign_ (&my_private_key,
1746 &current_ekm.purpose,
1747 &current_ekm.signature));
1748}
1749
1750
1751/**
1752 * Task run to trigger rekeying.
1753 *
1754 * @param cls closure, NULL
1755 */
1756static void
1757do_rekey (void *cls)
1758{
1759 struct GSC_KeyExchangeInfo *pos;
1760
1761 rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, &do_rekey, NULL);
1762 GNUNET_CRYPTO_ecdhe_key_create (&my_ephemeral_key);
1763 sign_ephemeral_key ();
1764 {
1765 struct GNUNET_HashCode eh;
1766
1767 GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1768 sizeof(current_ekm.ephemeral_key),
1769 &eh);
1770 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Rekeying to %s\n", GNUNET_h2s (&eh));
1771 }
1772 for (pos = kx_head; NULL != pos; pos = pos->next)
1773 {
1774 if (GNUNET_CORE_KX_STATE_UP == pos->status)
1775 {
1776 pos->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1777 monitor_notify_all (pos);
1778 derive_session_keys (pos);
1779 }
1780 if (GNUNET_CORE_KX_STATE_DOWN == pos->status)
1781 {
1782 pos->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1783 monitor_notify_all (pos);
1784 }
1785 monitor_notify_all (pos);
1786 send_key (pos);
1787 }
1788}
1789
1790
1791/**
1792 * Initialize KX subsystem.
1793 *
1794 * @param pk private key to use for the peer
1795 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1796 */
1797int
1798GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
1799{
1800 struct GNUNET_MQ_MessageHandler handlers[] = {
1801 GNUNET_MQ_hd_fixed_size (ephemeral_key,
1802 GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY,
1803 struct EphemeralKeyMessage,
1804 NULL),
1805 GNUNET_MQ_hd_fixed_size (ping,
1806 GNUNET_MESSAGE_TYPE_CORE_PING,
1807 struct PingMessage,
1808 NULL),
1809 GNUNET_MQ_hd_fixed_size (pong,
1810 GNUNET_MESSAGE_TYPE_CORE_PONG,
1811 struct PongMessage,
1812 NULL),
1813 GNUNET_MQ_hd_var_size (encrypted,
1814 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE,
1815 struct EncryptedMessage,
1816 NULL),
1817 GNUNET_MQ_handler_end ()
1818 };
1819
1820 my_private_key = *pk;
1821 GNUNET_CRYPTO_eddsa_key_get_public (&my_private_key,
1822 &GSC_my_identity.public_key);
1823 GNUNET_CRYPTO_ecdhe_key_create (&my_ephemeral_key);
1824 sign_ephemeral_key ();
1825 {
1826 struct GNUNET_HashCode eh;
1827
1828 GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1829 sizeof(current_ekm.ephemeral_key),
1830 &eh);
1831 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1832 "Starting with ephemeral key %s\n",
1833 GNUNET_h2s (&eh));
1834 }
1835
1836 nc = GNUNET_notification_context_create (1);
1837 rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, &do_rekey, NULL);
1838 transport =
1839 GNUNET_TRANSPORT_core_connect (GSC_cfg,
1840 &GSC_my_identity,
1841 handlers,
1842 NULL,
1843 &handle_transport_notify_connect,
1844 &handle_transport_notify_disconnect,
1845 &handle_transport_notify_excess_bw);
1846 if (NULL == transport)
1847 {
1848 GSC_KX_done ();
1849 return GNUNET_SYSERR;
1850 }
1851 return GNUNET_OK;
1852}
1853
1854
1855/**
1856 * Shutdown KX subsystem.
1857 */
1858void
1859GSC_KX_done ()
1860{
1861 if (NULL != transport)
1862 {
1863 GNUNET_TRANSPORT_core_disconnect (transport);
1864 transport = NULL;
1865 }
1866 if (NULL != rekey_task)
1867 {
1868 GNUNET_SCHEDULER_cancel (rekey_task);
1869 rekey_task = NULL;
1870 }
1871 memset (&my_ephemeral_key,
1872 0,
1873 sizeof (my_ephemeral_key));
1874 memset (&my_private_key,
1875 0,
1876 sizeof (my_private_key));
1877 if (NULL != nc)
1878 {
1879 GNUNET_notification_context_destroy (nc);
1880 nc = NULL;
1881 }
1882}
1883
1884
1885/**
1886 * Check how many messages are queued for the given neighbour.
1887 *
1888 * @param kxinfo data about neighbour to check
1889 * @return number of items in the message queue
1890 */
1891unsigned int
1892GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo)
1893{
1894 return GNUNET_MQ_get_length (kxinfo->mq);
1895}
1896
1897
1898/**
1899 * Check if the given neighbour has excess bandwidth available.
1900 *
1901 * @param target neighbour to check
1902 * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not
1903 */
1904int
1905GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo)
1906{
1907 return kxinfo->has_excess_bandwidth;
1908}
1909
1910
1911/**
1912 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
1913 * request type, the client does not have to have transmitted an INIT
1914 * request. All current peers are returned, regardless of which
1915 * message types they accept.
1916 *
1917 * @param mq message queue to add for monitoring
1918 */
1919void
1920GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq)
1921{
1922 struct GNUNET_MQ_Envelope *env;
1923 struct MonitorNotifyMessage *done_msg;
1924 struct GSC_KeyExchangeInfo *kx;
1925
1926 GNUNET_notification_context_add (nc, mq);
1927 for (kx = kx_head; NULL != kx; kx = kx->next)
1928 {
1929 struct GNUNET_MQ_Envelope *env;
1930 struct MonitorNotifyMessage *msg;
1931
1932 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
1933 msg->state = htonl ((uint32_t) kx->status);
1934 msg->peer = *kx->peer;
1935 msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
1936 GNUNET_MQ_send (mq, env);
1937 }
1938 env = GNUNET_MQ_msg (done_msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
1939 done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
1940 done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
1941 GNUNET_MQ_send (mq, env);
1942}
1943
1944
1945/* end of gnunet-service-core_kx.c */
diff --git a/src/core/gnunet-service-core_kx.h b/src/core/gnunet-service-core_kx.h
deleted file mode 100644
index 77f3e43b6..000000000
--- a/src/core/gnunet-service-core_kx.h
+++ /dev/null
@@ -1,103 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2011 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 core/gnunet-service-core_kx.h
23 * @brief code for managing the key exchange (SET_KEY, PING, PONG) with other peers
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_CORE_KX_H
27#define GNUNET_SERVICE_CORE_KX_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_transport_service.h"
31
32
33/**
34 * Information about the status of a key exchange with another peer.
35 */
36struct GSC_KeyExchangeInfo;
37
38
39/**
40 * Encrypt and transmit a message with the given payload.
41 *
42 * @param kx key exchange context
43 * @param payload payload of the message
44 * @param payload_size number of bytes in 'payload'
45 */
46void
47GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
48 const void *payload,
49 size_t payload_size);
50
51
52/**
53 * Initialize KX subsystem.
54 *
55 * @param pk private key to use for the peer
56 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
57 */
58int
59GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk);
60
61
62/**
63 * Shutdown KX subsystem.
64 */
65void
66GSC_KX_done (void);
67
68
69/**
70 * Check if the given neighbour has excess bandwidth available.
71 *
72 * @param target neighbour to check
73 * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not
74 */
75int
76GSC_NEIGHBOURS_check_excess_bandwidth (const struct
77 GSC_KeyExchangeInfo *target);
78
79
80/**
81 * Check how many messages are queued for the given neighbour.
82 *
83 * @param target neighbour to check
84 * @return number of items in the message queue
85 */
86unsigned int
87GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *target);
88
89
90/**
91 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
92 * request type, the client does not have to have transmitted an INIT
93 * request. All current peers are returned, regardless of which
94 * message types they accept.
95 *
96 * @param mq message queue to add for monitoring
97 */
98void
99GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq);
100
101
102#endif
103/* end of gnunet-service-core_kx.h */
diff --git a/src/core/gnunet-service-core_sessions.c b/src/core/gnunet-service-core_sessions.c
deleted file mode 100644
index d40b3bfad..000000000
--- a/src/core/gnunet-service-core_sessions.c
+++ /dev/null
@@ -1,1043 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2014, 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 core/gnunet-service-core_sessions.c
23 * @brief code for managing of 'encrypted' sessions (key exchange done)
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet-service-core.h"
28#include "gnunet-service-core_kx.h"
29#include "gnunet-service-core_typemap.h"
30#include "gnunet-service-core_sessions.h"
31#include "gnunet_constants.h"
32#include "core.h"
33
34
35/**
36 * How many encrypted messages do we queue at most?
37 * Needed to bound memory consumption.
38 */
39#define MAX_ENCRYPTED_MESSAGE_QUEUE_SIZE 4
40
41
42/**
43 * Message ready for encryption. This struct is followed by the
44 * actual content of the message.
45 */
46struct SessionMessageEntry
47{
48 /**
49 * We keep messages in a doubly linked list.
50 */
51 struct SessionMessageEntry *next;
52
53 /**
54 * We keep messages in a doubly linked list.
55 */
56 struct SessionMessageEntry *prev;
57
58 /**
59 * How important is this message.
60 */
61 enum GNUNET_MQ_PriorityPreferences priority;
62
63 /**
64 * Flag set to #GNUNET_YES if this is a typemap message.
65 */
66 int is_typemap;
67
68 /**
69 * Flag set to #GNUNET_YES if this is a typemap confirmation message.
70 */
71 int is_typemap_confirm;
72
73 /**
74 * Deadline for transmission, 1s after we received it (if we
75 * are not corking), otherwise "now". Note that this message
76 * does NOT expire past its deadline.
77 */
78 struct GNUNET_TIME_Absolute deadline;
79
80 /**
81 * How long is the message? (number of bytes following the `struct
82 * MessageEntry`, but not including the size of `struct
83 * MessageEntry` itself!)
84 */
85 size_t size;
86};
87
88
89/**
90 * Data kept per session.
91 */
92struct Session
93{
94 /**
95 * Identity of the other peer.
96 */
97 const struct GNUNET_PeerIdentity *peer;
98
99 /**
100 * Key exchange state for this peer.
101 */
102 struct GSC_KeyExchangeInfo *kx;
103
104 /**
105 * Head of list of requests from clients for transmission to
106 * this peer.
107 */
108 struct GSC_ClientActiveRequest *active_client_request_head;
109
110 /**
111 * Tail of list of requests from clients for transmission to
112 * this peer.
113 */
114 struct GSC_ClientActiveRequest *active_client_request_tail;
115
116 /**
117 * Head of list of messages ready for encryption.
118 */
119 struct SessionMessageEntry *sme_head;
120
121 /**
122 * Tail of list of messages ready for encryption.
123 */
124 struct SessionMessageEntry *sme_tail;
125
126 /**
127 * Current type map for this peer.
128 */
129 struct GSC_TypeMap *tmap;
130
131 /**
132 * Task to transmit corked messages with a delay.
133 */
134 struct GNUNET_SCHEDULER_Task *cork_task;
135
136 /**
137 * Task to transmit our type map.
138 */
139 struct GNUNET_SCHEDULER_Task *typemap_task;
140
141 /**
142 * Retransmission delay we currently use for the typemap
143 * transmissions (if not confirmed).
144 */
145 struct GNUNET_TIME_Relative typemap_delay;
146
147 /**
148 * Is this the first time we're sending the typemap? If so,
149 * we want to send it a bit faster the second time. 0 if
150 * we are sending for the first time, 1 if not.
151 */
152 int first_typemap;
153};
154
155
156GNUNET_NETWORK_STRUCT_BEGIN
157
158/**
159 * Message sent to confirm that a typemap was received.
160 */
161struct TypeMapConfirmationMessage
162{
163 /**
164 * Header with type #GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP.
165 */
166 struct GNUNET_MessageHeader header;
167
168 /**
169 * Reserved, always zero.
170 */
171 uint32_t reserved GNUNET_PACKED;
172
173 /**
174 * Hash of the (decompressed) type map that was received.
175 */
176 struct GNUNET_HashCode tm_hash;
177};
178
179GNUNET_NETWORK_STRUCT_END
180
181
182/**
183 * Map of peer identities to `struct Session`.
184 */
185static struct GNUNET_CONTAINER_MultiPeerMap *sessions;
186
187
188/**
189 * Find the session for the given peer.
190 *
191 * @param peer identity of the peer
192 * @return NULL if we are not connected, otherwise the
193 * session handle
194 */
195static struct Session *
196find_session (const struct GNUNET_PeerIdentity *peer)
197{
198 if (NULL == sessions)
199 return NULL;
200 return GNUNET_CONTAINER_multipeermap_get (sessions, peer);
201}
202
203
204/**
205 * End the session with the given peer (we are no longer
206 * connected).
207 *
208 * @param pid identity of peer to kill session with
209 */
210void
211GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid)
212{
213 struct Session *session;
214 struct GSC_ClientActiveRequest *car;
215 struct SessionMessageEntry *sme;
216
217 session = find_session (pid);
218 if (NULL == session)
219 return;
220 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
221 "Destroying session for peer `%s'\n",
222 GNUNET_i2s (session->peer));
223 if (NULL != session->cork_task)
224 {
225 GNUNET_SCHEDULER_cancel (session->cork_task);
226 session->cork_task = NULL;
227 }
228 while (NULL != (car = session->active_client_request_head))
229 {
230 GNUNET_CONTAINER_DLL_remove (session->active_client_request_head,
231 session->active_client_request_tail,
232 car);
233 GSC_CLIENTS_reject_request (car, GNUNET_NO);
234 }
235 while (NULL != (sme = session->sme_head))
236 {
237 GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, sme);
238 GNUNET_free (sme);
239 }
240 if (NULL != session->typemap_task)
241 {
242 GNUNET_SCHEDULER_cancel (session->typemap_task);
243 session->typemap_task = NULL;
244 }
245 GSC_CLIENTS_notify_clients_about_neighbour (session->peer,
246 session->tmap,
247 NULL);
248 GNUNET_assert (
249 GNUNET_YES ==
250 GNUNET_CONTAINER_multipeermap_remove (sessions, session->peer, session));
251 GNUNET_STATISTICS_set (GSC_stats,
252 gettext_noop ("# peers connected"),
253 GNUNET_CONTAINER_multipeermap_size (sessions),
254 GNUNET_NO);
255 GSC_TYPEMAP_destroy (session->tmap);
256 session->tmap = NULL;
257 GNUNET_free (session);
258}
259
260
261/**
262 * Transmit our current typemap message to the other peer.
263 * (Done periodically until the typemap is confirmed).
264 *
265 * @param cls the `struct Session *`
266 */
267static void
268transmit_typemap_task (void *cls)
269{
270 struct Session *session = cls;
271 struct GNUNET_MessageHeader *hdr;
272 struct GNUNET_TIME_Relative delay;
273
274 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
275 "Sending TYPEMAP to %s\n",
276 GNUNET_i2s (session->peer));
277 session->typemap_delay = GNUNET_TIME_STD_BACKOFF (session->typemap_delay);
278 delay = session->typemap_delay;
279 /* randomize a bit to avoid spont. sync */
280 delay.rel_value_us +=
281 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1000 * 1000);
282 session->typemap_task =
283 GNUNET_SCHEDULER_add_delayed (delay, &transmit_typemap_task, session);
284 GNUNET_STATISTICS_update (GSC_stats,
285 gettext_noop ("# type map refreshes sent"),
286 1,
287 GNUNET_NO);
288 hdr = GSC_TYPEMAP_compute_type_map_message ();
289 GSC_KX_encrypt_and_transmit (session->kx, hdr, ntohs (hdr->size));
290 GNUNET_free (hdr);
291}
292
293
294/**
295 * Restart the typemap task for the given session.
296 *
297 * @param session session to restart typemap transmission for
298 */
299static void
300start_typemap_task (struct Session *session)
301{
302 if (NULL != session->typemap_task)
303 GNUNET_SCHEDULER_cancel (session->typemap_task);
304 session->typemap_delay = GNUNET_TIME_UNIT_SECONDS;
305 session->typemap_task = GNUNET_SCHEDULER_add_delayed (session->typemap_delay,
306 &transmit_typemap_task,
307 session);
308}
309
310
311/**
312 * Create a session, a key exchange was just completed.
313 *
314 * @param peer peer that is now connected
315 * @param kx key exchange that completed
316 */
317void
318GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer,
319 struct GSC_KeyExchangeInfo *kx)
320{
321 struct Session *session;
322
323 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
324 "Creating session for peer `%s'\n",
325 GNUNET_i2s (peer));
326 session = GNUNET_new (struct Session);
327 session->tmap = GSC_TYPEMAP_create ();
328 session->peer = peer;
329 session->kx = kx;
330 GNUNET_assert (GNUNET_OK ==
331 GNUNET_CONTAINER_multipeermap_put (
332 sessions,
333 session->peer,
334 session,
335 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
336 GNUNET_STATISTICS_set (GSC_stats,
337 gettext_noop ("# peers connected"),
338 GNUNET_CONTAINER_multipeermap_size (sessions),
339 GNUNET_NO);
340 GSC_CLIENTS_notify_clients_about_neighbour (peer, NULL, session->tmap);
341 start_typemap_task (session);
342}
343
344
345/**
346 * The other peer has indicated that it 'lost' the session
347 * (KX down), reinitialize the session on our end, in particular
348 * this means to restart the typemap transmission.
349 *
350 * @param peer peer that is now connected
351 */
352void
353GSC_SESSIONS_reinit (const struct GNUNET_PeerIdentity *peer)
354{
355 struct Session *session;
356
357 session = find_session (peer);
358 if (NULL == session)
359 {
360 /* KX/session is new for both sides; thus no need to restart what
361 has not yet begun */
362 return;
363 }
364 start_typemap_task (session);
365}
366
367
368/**
369 * The other peer has confirmed receiving our type map,
370 * check if it is current and if so, stop retransmitting it.
371 *
372 * @param peer peer that confirmed the type map
373 * @param msg confirmation message we received
374 */
375void
376GSC_SESSIONS_confirm_typemap (const struct GNUNET_PeerIdentity *peer,
377 const struct GNUNET_MessageHeader *msg)
378{
379 const struct TypeMapConfirmationMessage *cmsg;
380 struct Session *session;
381
382 session = find_session (peer);
383 if (NULL == session)
384 {
385 GNUNET_break (0);
386 return;
387 }
388 if (ntohs (msg->size) != sizeof(struct TypeMapConfirmationMessage))
389 {
390 GNUNET_break_op (0);
391 return;
392 }
393 cmsg = (const struct TypeMapConfirmationMessage *) msg;
394 if (GNUNET_YES != GSC_TYPEMAP_check_hash (&cmsg->tm_hash))
395 {
396 /* our typemap has changed in the meantime, do not
397 accept confirmation */
398 GNUNET_STATISTICS_update (GSC_stats,
399 gettext_noop (
400 "# outdated typemap confirmations received"),
401 1,
402 GNUNET_NO);
403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
404 "Got outdated typemap confirmated from peer `%s'\n",
405 GNUNET_i2s (session->peer));
406 return;
407 }
408 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
409 "Got typemap confirmation from peer `%s'\n",
410 GNUNET_i2s (session->peer));
411 if (NULL != session->typemap_task)
412 {
413 GNUNET_SCHEDULER_cancel (session->typemap_task);
414 session->typemap_task = NULL;
415 }
416 GNUNET_STATISTICS_update (GSC_stats,
417 gettext_noop (
418 "# valid typemap confirmations received"),
419 1,
420 GNUNET_NO);
421}
422
423
424/**
425 * Notify the given client about the session (client is new).
426 *
427 * @param cls the `struct GSC_Client`
428 * @param key peer identity
429 * @param value the `struct Session`
430 * @return #GNUNET_OK (continue to iterate)
431 */
432static int
433notify_client_about_session (void *cls,
434 const struct GNUNET_PeerIdentity *key,
435 void *value)
436{
437 struct GSC_Client *client = cls;
438 struct Session *session = value;
439
440 GSC_CLIENTS_notify_client_about_neighbour (client,
441 session->peer,
442 NULL, /* old TMAP: none */
443 session->tmap);
444 return GNUNET_OK;
445}
446
447
448/**
449 * We have a new client, notify it about all current sessions.
450 *
451 * @param client the new client
452 */
453void
454GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client)
455{
456 /* notify new client about existing sessions */
457 GNUNET_CONTAINER_multipeermap_iterate (sessions,
458 &notify_client_about_session,
459 client);
460}
461
462
463/**
464 * Try to perform a transmission on the given session. Will solicit
465 * additional messages if the 'sme' queue is not full enough.
466 *
467 * @param session session to transmit messages from
468 */
469static void
470try_transmission (struct Session *session);
471
472
473/**
474 * Queue a request from a client for transmission to a particular peer.
475 *
476 * @param car request to queue; this handle is then shared between
477 * the caller (CLIENTS subsystem) and SESSIONS and must not
478 * be released by either until either #GSC_SESSIONS_dequeue(),
479 * #GSC_SESSIONS_transmit() or #GSC_CLIENTS_failed()
480 * have been invoked on it
481 */
482void
483GSC_SESSIONS_queue_request (struct GSC_ClientActiveRequest *car)
484{
485 struct Session *session;
486
487 session = find_session (&car->target);
488 if (NULL == session)
489 {
490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
491 "Dropped client request for transmission (am disconnected)\n");
492 GNUNET_break (0); /* should have been rejected earlier */
493 GSC_CLIENTS_reject_request (car, GNUNET_NO);
494 return;
495 }
496 if (car->msize > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
497 {
498 GNUNET_break (0);
499 GSC_CLIENTS_reject_request (car, GNUNET_YES);
500 return;
501 }
502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
503 "Received client transmission request. queueing\n");
504 GNUNET_CONTAINER_DLL_insert_tail (session->active_client_request_head,
505 session->active_client_request_tail,
506 car);
507 try_transmission (session);
508}
509
510
511/**
512 * Dequeue a request from a client from transmission to a particular peer.
513 *
514 * @param car request to dequeue; this handle will then be 'owned' by
515 * the caller (CLIENTS sysbsystem)
516 */
517void
518GSC_SESSIONS_dequeue_request (struct GSC_ClientActiveRequest *car)
519{
520 struct Session *session;
521
522 if (0 == memcmp (&car->target,
523 &GSC_my_identity,
524 sizeof(struct GNUNET_PeerIdentity)))
525 return;
526 session = find_session (&car->target);
527 GNUNET_assert (NULL != session);
528 GNUNET_CONTAINER_DLL_remove (session->active_client_request_head,
529 session->active_client_request_tail,
530 car);
531 /* dequeueing of 'high' priority messages may unblock
532 transmission for lower-priority messages, so we also
533 need to try in this case. */
534 try_transmission (session);
535}
536
537
538/**
539 * Solicit messages for transmission, starting with those of the highest
540 * priority.
541 *
542 * @param session session to solict messages for
543 * @param msize how many bytes do we have already
544 */
545static void
546solicit_messages (struct Session *session, size_t msize)
547{
548 struct GSC_ClientActiveRequest *car;
549 struct GSC_ClientActiveRequest *nxt;
550 size_t so_size;
551 enum GNUNET_MQ_PriorityPreferences pmax;
552
553 so_size = msize;
554 pmax = GNUNET_MQ_PRIO_BACKGROUND;
555 for (car = session->active_client_request_head; NULL != car; car = car->next)
556 {
557 if (GNUNET_YES == car->was_solicited)
558 continue;
559 pmax = GNUNET_MAX (pmax, car->priority & GNUNET_MQ_PRIORITY_MASK);
560 }
561 nxt = session->active_client_request_head;
562 while (NULL != (car = nxt))
563 {
564 nxt = car->next;
565 if (car->priority < pmax)
566 continue;
567 if (so_size + car->msize > GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE)
568 break;
569 so_size += car->msize;
570 if (GNUNET_YES == car->was_solicited)
571 continue;
572 car->was_solicited = GNUNET_YES;
573 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
574 "Soliciting message with priority %u\n",
575 car->priority);
576 GSC_CLIENTS_solicit_request (car);
577 /* The above call may *dequeue* requests and thereby
578 clobber 'nxt'. Hence we need to restart from the
579 head of the list. */
580 nxt = session->active_client_request_head;
581 so_size = msize;
582 }
583}
584
585
586/**
587 * Some messages were delayed (corked), but the timeout has now expired.
588 * Send them now.
589 *
590 * @param cls `struct Session` with the messages to transmit now
591 */
592static void
593pop_cork_task (void *cls)
594{
595 struct Session *session = cls;
596
597 session->cork_task = NULL;
598 try_transmission (session);
599}
600
601
602/**
603 * Try to perform a transmission on the given session. Will solicit
604 * additional messages if the 'sme' queue is not full enough or has
605 * only low-priority messages.
606 *
607 * @param session session to transmit messages from
608 */
609static void
610try_transmission (struct Session *session)
611{
612 struct SessionMessageEntry *pos;
613 size_t msize;
614 struct GNUNET_TIME_Absolute now;
615 struct GNUNET_TIME_Absolute min_deadline;
616 enum GNUNET_MQ_PriorityPreferences maxp;
617 enum GNUNET_MQ_PriorityPreferences maxpc;
618 struct GSC_ClientActiveRequest *car;
619 int excess;
620
621 msize = 0;
622 min_deadline = GNUNET_TIME_UNIT_FOREVER_ABS;
623 /* if the peer has excess bandwidth, background traffic is allowed,
624 otherwise not */
625 if (MAX_ENCRYPTED_MESSAGE_QUEUE_SIZE <=
626 GSC_NEIGHBOURS_get_queue_length (session->kx))
627 {
628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
629 "Transmission queue already very long, waiting...\n");
630 return; /* queue already too long */
631 }
632 excess = GSC_NEIGHBOURS_check_excess_bandwidth (session->kx);
633 if (GNUNET_YES == excess)
634 maxp = GNUNET_MQ_PRIO_BACKGROUND;
635 else
636 maxp = GNUNET_MQ_PRIO_BEST_EFFORT;
637 /* determine highest priority of 'ready' messages we already solicited from clients */
638 pos = session->sme_head;
639 while ((NULL != pos) &&
640 (msize + pos->size <= GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE))
641 {
642 GNUNET_assert (pos->size < GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE);
643 msize += pos->size;
644 maxp = GNUNET_MAX (maxp, pos->priority & GNUNET_MQ_PRIORITY_MASK);
645 min_deadline = GNUNET_TIME_absolute_min (min_deadline, pos->deadline);
646 pos = pos->next;
647 }
648 GNUNET_log (
649 GNUNET_ERROR_TYPE_DEBUG,
650 "Calculating transmission set with %u priority (%s) and %s earliest deadline\n",
651 maxp,
652 (GNUNET_YES == excess) ? "excess bandwidth" : "limited bandwidth",
653 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_remaining (
654 min_deadline),
655 GNUNET_YES));
656
657 if (maxp < GNUNET_MQ_PRIO_CRITICAL_CONTROL)
658 {
659 /* if highest already solicited priority from clients is not critical,
660 check if there are higher-priority messages to be solicited from clients */
661 if (GNUNET_YES == excess)
662 maxpc = GNUNET_MQ_PRIO_BACKGROUND;
663 else
664 maxpc = GNUNET_MQ_PRIO_BEST_EFFORT;
665 for (car = session->active_client_request_head; NULL != car;
666 car = car->next)
667 {
668 if (GNUNET_YES == car->was_solicited)
669 continue;
670 maxpc = GNUNET_MAX (maxpc, car->priority & GNUNET_MQ_PRIORITY_MASK);
671 }
672 if (maxpc > maxp)
673 {
674 /* we have messages waiting for solicitation that have a higher
675 priority than those that we already accepted; solicit the
676 high-priority messages first */
677 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
678 "Soliciting messages based on priority (%u > %u)\n",
679 maxpc,
680 maxp);
681 solicit_messages (session, 0);
682 return;
683 }
684 }
685 else
686 {
687 /* never solicit more, we have critical messages to process */
688 excess = GNUNET_NO;
689 maxpc = GNUNET_MQ_PRIO_BACKGROUND;
690 }
691 now = GNUNET_TIME_absolute_get ();
692 if (((GNUNET_YES == excess) || (maxpc >= GNUNET_MQ_PRIO_BEST_EFFORT)) &&
693 ((0 == msize) ||
694 ((msize < GNUNET_CONSTANTS_MAX_ENCRYPTED_MESSAGE_SIZE / 2) &&
695 (min_deadline.abs_value_us > now.abs_value_us))))
696 {
697 /* not enough ready yet (tiny message & cork possible), or no messages at all,
698 and either excess bandwidth or best-effort or higher message waiting at
699 client; in this case, we try to solicit more */
700 GNUNET_log (
701 GNUNET_ERROR_TYPE_DEBUG,
702 "Soliciting messages (excess %d, maxpc %d, message size %u, deadline %s)\n",
703 excess,
704 maxpc,
705 (unsigned int) msize,
706 GNUNET_STRINGS_relative_time_to_string (
707 GNUNET_TIME_absolute_get_remaining (
708 min_deadline),
709 GNUNET_YES));
710 solicit_messages (session, msize);
711 if (msize > 0)
712 {
713 /* if there is data to send, just not yet, make sure we do transmit
714 * it once the deadline is reached */
715 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
716 "Corking until %s\n",
717 GNUNET_STRINGS_relative_time_to_string (
718 GNUNET_TIME_absolute_get_remaining (min_deadline),
719 GNUNET_YES));
720 if (NULL != session->cork_task)
721 GNUNET_SCHEDULER_cancel (session->cork_task);
722 session->cork_task =
723 GNUNET_SCHEDULER_add_at (min_deadline, &pop_cork_task, session);
724 }
725 else
726 {
727 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
728 "Queue empty, waiting for solicitations\n");
729 }
730 return;
731 }
732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
733 "Building combined plaintext buffer to transmit message!\n");
734 /* create plaintext buffer of all messages (that fit), encrypt and
735 transmit */
736 {
737 static unsigned long long total_bytes;
738 static unsigned int total_msgs;
739 char pbuf[msize]; /* plaintext */
740 size_t used;
741
742 used = 0;
743 while ((NULL != (pos = session->sme_head)) && (used + pos->size <= msize))
744 {
745 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
746 "Adding message of type %d (%d/%d) to payload for %s\n",
747 ntohs (((const struct GNUNET_MessageHeader *) &pos[1])->type),
748 pos->is_typemap,
749 pos->is_typemap_confirm,
750 GNUNET_i2s (session->peer));
751 GNUNET_memcpy (&pbuf[used], &pos[1], pos->size);
752 used += pos->size;
753 GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, pos);
754 GNUNET_free (pos);
755 }
756 /* compute average payload size */
757 total_bytes += used;
758 total_msgs++;
759 if (0 == total_msgs)
760 {
761 /* 2^32 messages, wrap around... */
762 total_msgs = 1;
763 total_bytes = used;
764 }
765 GNUNET_STATISTICS_set (GSC_stats,
766 "# avg payload per encrypted message",
767 total_bytes / total_msgs,
768 GNUNET_NO);
769 /* now actually transmit... */
770 GSC_KX_encrypt_and_transmit (session->kx, pbuf, used);
771 }
772}
773
774
775/**
776 * Send an updated typemap message to the neighbour now,
777 * and restart typemap transmissions.
778 *
779 * @param cls the message
780 * @param key neighbour's identity
781 * @param value `struct Neighbour` of the target
782 * @return always #GNUNET_OK
783 */
784static int
785do_restart_typemap_message (void *cls,
786 const struct GNUNET_PeerIdentity *key,
787 void *value)
788{
789 const struct GNUNET_MessageHeader *hdr = cls;
790 struct Session *session = value;
791 struct SessionMessageEntry *sme;
792 uint16_t size;
793
794 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
795 "Restarting sending TYPEMAP to %s\n",
796 GNUNET_i2s (session->peer));
797 size = ntohs (hdr->size);
798 for (sme = session->sme_head; NULL != sme; sme = sme->next)
799 {
800 if (GNUNET_YES == sme->is_typemap)
801 {
802 GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, sme);
803 GNUNET_free (sme);
804 break;
805 }
806 }
807 sme = GNUNET_malloc (sizeof(struct SessionMessageEntry) + size);
808 sme->is_typemap = GNUNET_YES;
809 GNUNET_memcpy (&sme[1], hdr, size);
810 sme->size = size;
811 sme->priority = GNUNET_MQ_PRIO_CRITICAL_CONTROL;
812 GNUNET_CONTAINER_DLL_insert (session->sme_head, session->sme_tail, sme);
813 try_transmission (session);
814 start_typemap_task (session);
815 return GNUNET_OK;
816}
817
818
819/**
820 * Broadcast an updated typemap message to all neighbours.
821 * Restarts the retransmissions until the typemaps are confirmed.
822 *
823 * @param msg message to transmit
824 */
825void
826GSC_SESSIONS_broadcast_typemap (const struct GNUNET_MessageHeader *msg)
827{
828 if (NULL == sessions)
829 return;
830 GNUNET_CONTAINER_multipeermap_iterate (sessions,
831 &do_restart_typemap_message,
832 (void *) msg);
833}
834
835
836/**
837 * Traffic is being solicited for the given peer. This means that the
838 * message queue on the transport-level (NEIGHBOURS subsystem) is now
839 * empty and it is now OK to transmit another (non-control) message.
840 *
841 * @param pid identity of peer ready to receive data
842 */
843void
844GSC_SESSIONS_solicit (const struct GNUNET_PeerIdentity *pid)
845{
846 struct Session *session;
847
848 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
849 "Transport solicits for %s\n",
850 GNUNET_i2s (pid));
851 session = find_session (pid);
852 if (NULL == session)
853 return;
854 try_transmission (session);
855}
856
857
858/**
859 * Transmit a message to a particular peer.
860 *
861 * @param car original request that was queued and then solicited;
862 * this handle will now be 'owned' by the SESSIONS subsystem
863 * @param msg message to transmit
864 * @param priority how important is this message
865 */
866void
867GSC_SESSIONS_transmit (struct GSC_ClientActiveRequest *car,
868 const struct GNUNET_MessageHeader *msg,
869 enum GNUNET_MQ_PriorityPreferences priority)
870{
871 struct Session *session;
872 struct SessionMessageEntry *sme;
873 struct SessionMessageEntry *pos;
874 size_t msize;
875
876 session = find_session (&car->target);
877 if (NULL == session)
878 return;
879 msize = ntohs (msg->size);
880 sme = GNUNET_malloc (sizeof(struct SessionMessageEntry) + msize);
881 GNUNET_memcpy (&sme[1], msg, msize);
882 sme->size = msize;
883 sme->priority = priority;
884 if (0 != (GNUNET_MQ_PREF_CORK_ALLOWED & priority))
885 {
886 sme->deadline =
887 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_MAX_CORK_DELAY);
888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
889 "Message corked, delaying transmission\n");
890 }
891 pos = session->sme_head;
892 while ((NULL != pos) && (pos->priority >= sme->priority))
893 pos = pos->next;
894 if (NULL == pos)
895 GNUNET_CONTAINER_DLL_insert_tail (session->sme_head,
896 session->sme_tail,
897 sme);
898 else
899 GNUNET_CONTAINER_DLL_insert_after (session->sme_head,
900 session->sme_tail,
901 pos->prev,
902 sme);
903 try_transmission (session);
904}
905
906
907/**
908 * We have received a typemap message from a peer, update ours.
909 * Notifies clients about the session.
910 *
911 * @param peer peer this is about
912 * @param msg typemap update message
913 */
914void
915GSC_SESSIONS_set_typemap (const struct GNUNET_PeerIdentity *peer,
916 const struct GNUNET_MessageHeader *msg)
917{
918 struct Session *session;
919 struct GSC_TypeMap *nmap;
920 struct SessionMessageEntry *sme;
921 struct TypeMapConfirmationMessage *tmc;
922
923 nmap = GSC_TYPEMAP_get_from_message (msg);
924 if (NULL == nmap)
925 {
926 GNUNET_break_op (0);
927 return; /* malformed */
928 }
929 session = find_session (peer);
930 if (NULL == session)
931 {
932 GSC_TYPEMAP_destroy (nmap);
933 GNUNET_break (0);
934 return;
935 }
936 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
937 "Received TYPEMAP from %s\n",
938 GNUNET_i2s (session->peer));
939 for (sme = session->sme_head; NULL != sme; sme = sme->next)
940 {
941 if (GNUNET_YES == sme->is_typemap_confirm)
942 {
943 GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, sme);
944 GNUNET_free (sme);
945 break;
946 }
947 }
948 sme = GNUNET_malloc (sizeof(struct SessionMessageEntry)
949 + sizeof(struct TypeMapConfirmationMessage));
950 sme->deadline = GNUNET_TIME_absolute_get ();
951 sme->size = sizeof(struct TypeMapConfirmationMessage);
952 sme->priority = GNUNET_MQ_PRIO_CRITICAL_CONTROL;
953 sme->is_typemap_confirm = GNUNET_YES;
954 tmc = (struct TypeMapConfirmationMessage *) &sme[1];
955 tmc->header.size = htons (sizeof(struct TypeMapConfirmationMessage));
956 tmc->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP);
957 tmc->reserved = htonl (0);
958 GSC_TYPEMAP_hash (nmap, &tmc->tm_hash);
959 GNUNET_CONTAINER_DLL_insert (session->sme_head, session->sme_tail, sme);
960 try_transmission (session);
961 GSC_CLIENTS_notify_clients_about_neighbour (peer, session->tmap, nmap);
962 GSC_TYPEMAP_destroy (session->tmap);
963 session->tmap = nmap;
964}
965
966
967/**
968 * The given peer send a message of the specified type. Make sure the
969 * respective bit is set in its type-map and that clients are notified
970 * about the session.
971 *
972 * @param peer peer this is about
973 * @param type type of the message
974 */
975void
976GSC_SESSIONS_add_to_typemap (const struct GNUNET_PeerIdentity *peer,
977 uint16_t type)
978{
979 struct Session *session;
980 struct GSC_TypeMap *nmap;
981
982 if (0 == memcmp (peer, &GSC_my_identity, sizeof(struct GNUNET_PeerIdentity)))
983 return;
984 session = find_session (peer);
985 GNUNET_assert (NULL != session);
986 if (GNUNET_YES == GSC_TYPEMAP_test_match (session->tmap, &type, 1))
987 return; /* already in it */
988 nmap = GSC_TYPEMAP_extend (session->tmap, &type, 1);
989 GSC_CLIENTS_notify_clients_about_neighbour (peer, session->tmap, nmap);
990 GSC_TYPEMAP_destroy (session->tmap);
991 session->tmap = nmap;
992}
993
994
995/**
996 * Initialize sessions subsystem.
997 */
998void
999GSC_SESSIONS_init ()
1000{
1001 sessions = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES);
1002}
1003
1004
1005/**
1006 * Helper function for #GSC_SESSIONS_done() to free all
1007 * active sessions.
1008 *
1009 * @param cls NULL
1010 * @param key identity of the connected peer
1011 * @param value the `struct Session` for the peer
1012 * @return #GNUNET_OK (continue to iterate)
1013 */
1014static int
1015free_session_helper (void *cls,
1016 const struct GNUNET_PeerIdentity *key,
1017 void *value)
1018{
1019 /* struct Session *session = value; */
1020
1021 GSC_SESSIONS_end (key);
1022 return GNUNET_OK;
1023}
1024
1025
1026/**
1027 * Shutdown sessions subsystem.
1028 */
1029void
1030GSC_SESSIONS_done ()
1031{
1032 if (NULL != sessions)
1033 {
1034 GNUNET_CONTAINER_multipeermap_iterate (sessions,
1035 &free_session_helper,
1036 NULL);
1037 GNUNET_CONTAINER_multipeermap_destroy (sessions);
1038 sessions = NULL;
1039 }
1040}
1041
1042
1043/* end of gnunet-service-core_sessions.c */
diff --git a/src/core/gnunet-service-core_sessions.h b/src/core/gnunet-service-core_sessions.h
deleted file mode 100644
index fda2cc32c..000000000
--- a/src/core/gnunet-service-core_sessions.h
+++ /dev/null
@@ -1,183 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-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 core/gnunet-service-core_neighbours.h
23 * @brief code for managing of 'encrypted' sessions (key exchange done)
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_CORE_SESSIONS_H
27#define GNUNET_SERVICE_CORE_SESSIONS_H
28
29#include "gnunet-service-core.h"
30#include "gnunet-service-core_kx.h"
31
32
33/**
34 * Create a session, a key exchange was just completed.
35 *
36 * @param peer peer that is now connected
37 * @param kx key exchange that completed
38 */
39void
40GSC_SESSIONS_create (const struct GNUNET_PeerIdentity *peer,
41 struct GSC_KeyExchangeInfo *kx);
42
43
44/**
45 * The other peer has indicated that it 'lost' the session
46 * (KX down), reinitialize the session on our end, in particular
47 * this means to restart the typemap transmission.
48 *
49 * @param peer peer that is now connected
50 */
51void
52GSC_SESSIONS_reinit (const struct GNUNET_PeerIdentity *peer);
53
54
55/**
56 * The other peer has confirmed receiving our type map,
57 * check if it is current and if so, stop retransmitting it.
58 *
59 * @param peer peer that confirmed the type map
60 * @param msg confirmation message we received
61 */
62void
63GSC_SESSIONS_confirm_typemap (const struct GNUNET_PeerIdentity *peer,
64 const struct GNUNET_MessageHeader *msg);
65
66
67/**
68 * End the session with the given peer (we are no longer
69 * connected).
70 *
71 * @param pid identity of peer to kill session with
72 */
73void
74GSC_SESSIONS_end (const struct GNUNET_PeerIdentity *pid);
75
76
77/**
78 * Traffic is being solicited for the given peer. This means that the
79 * message queue on the transport-level (NEIGHBOURS subsystem) is now
80 * empty and it is now OK to transmit another (non-control) message.
81 *
82 * @param pid identity of peer ready to receive data
83 */
84void
85GSC_SESSIONS_solicit (const struct GNUNET_PeerIdentity *pid);
86
87
88/**
89 * Queue a request from a client for transmission to a particular peer.
90 *
91 * @param car request to queue; this handle is then shared between
92 * the caller (CLIENTS subsystem) and SESSIONS and must not
93 * be released by either until either 'GNUNET_SESSIONS_dequeue',
94 * or 'GNUNET_CLIENTS_failed'
95 * have been invoked on it
96 */
97void
98GSC_SESSIONS_queue_request (struct GSC_ClientActiveRequest *car);
99
100
101/**
102 * Dequeue a request from a client from transmission to a particular peer.
103 *
104 * @param car request to dequeue; this handle will then be 'owned' by
105 * the caller (CLIENTS sysbsystem)
106 */
107void
108GSC_SESSIONS_dequeue_request (struct GSC_ClientActiveRequest *car);
109
110
111/**
112 * Transmit a message to a particular peer.
113 *
114 * @param car original request that was queued and then solicited,
115 * ownership does not change (dequeue will be called soon).
116 * @param msg message to transmit
117 * @param priority how important is this message
118 */
119void
120GSC_SESSIONS_transmit (struct GSC_ClientActiveRequest *car,
121 const struct GNUNET_MessageHeader *msg,
122 enum GNUNET_MQ_PriorityPreferences priority);
123
124
125/**
126 * Broadcast an updated typemap message to all neighbours.
127 * Restarts the retransmissions until the typemaps are confirmed.
128 *
129 * @param msg message to transmit
130 */
131void
132GSC_SESSIONS_broadcast_typemap (const struct GNUNET_MessageHeader *msg);
133
134
135/**
136 * We have a new client, notify it about all current sessions.
137 *
138 * @param client the new client
139 */
140void
141GSC_SESSIONS_notify_client_about_sessions (struct GSC_Client *client);
142
143
144/**
145 * We've received a typemap message from a peer, update ours.
146 * Notifies clients about the session.
147 *
148 * @param peer peer this is about
149 * @param msg typemap update message
150 */
151void
152GSC_SESSIONS_set_typemap (const struct GNUNET_PeerIdentity *peer,
153 const struct GNUNET_MessageHeader *msg);
154
155
156/**
157 * The given peer send a message of the specified type. Make sure the
158 * respective bit is set in its type-map and that clients are notified
159 * about the session.
160 *
161 * @param peer peer this is about
162 * @param type type of the message
163 */
164void
165GSC_SESSIONS_add_to_typemap (const struct GNUNET_PeerIdentity *peer,
166 uint16_t type);
167
168
169/**
170 * Initialize sessions subsystem.
171 */
172void
173GSC_SESSIONS_init (void);
174
175
176/**
177 * Shutdown sessions subsystem.
178 */
179void
180GSC_SESSIONS_done (void);
181
182
183#endif
diff --git a/src/core/gnunet-service-core_typemap.c b/src/core/gnunet-service-core_typemap.c
deleted file mode 100644
index 47235501c..000000000
--- a/src/core/gnunet-service-core_typemap.c
+++ /dev/null
@@ -1,377 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-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 core/gnunet-service-core_typemap.c
23 * @brief management of map that specifies which message types this peer supports
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_transport_service.h"
29#include "gnunet-service-core.h"
30#include "gnunet-service-core_sessions.h"
31#include "gnunet-service-core_typemap.h"
32#include <zlib.h>
33
34
35/**
36 * A type map describing which messages a given neighbour is able
37 * to process.
38 */
39struct GSC_TypeMap
40{
41 uint32_t bits[(UINT16_MAX + 1) / 32];
42};
43
44/**
45 * Bitmap of message types this peer is able to handle.
46 */
47static struct GSC_TypeMap my_type_map;
48
49/**
50 * Counters for message types this peer is able to handle.
51 */
52static uint8_t map_counters[UINT16_MAX + 1];
53
54/**
55 * Current hash of our (uncompressed) type map.
56 * Lazily computed when needed.
57 */
58static struct GNUNET_HashCode my_tm_hash;
59
60/**
61 * Is #my_tm_hash() current with respect to our type map?
62 */
63static int hash_current;
64
65
66/**
67 * Our type map changed, recompute its hash.
68 */
69static void
70rehash_typemap ()
71{
72 hash_current = GNUNET_NO;
73}
74
75
76/**
77 * Hash the contents of a type map.
78 *
79 * @param tm map to hash
80 * @param hc where to store the hash code
81 */
82void
83GSC_TYPEMAP_hash (const struct GSC_TypeMap *tm, struct GNUNET_HashCode *hc)
84{
85 GNUNET_CRYPTO_hash (tm, sizeof(struct GSC_TypeMap), hc);
86}
87
88
89/**
90 * Check if the given hash matches our current type map.
91 *
92 * @param hc hash code to check if it matches our type map
93 * @return #GNUNET_YES if the hash matches, #GNUNET_NO if not
94 */
95int
96GSC_TYPEMAP_check_hash (const struct GNUNET_HashCode *hc)
97{
98 if (GNUNET_NO == hash_current)
99 {
100 GSC_TYPEMAP_hash (&my_type_map, &my_tm_hash);
101 hash_current = GNUNET_YES;
102 }
103 return (0 == memcmp (hc, &my_tm_hash, sizeof(struct GNUNET_HashCode)))
104 ? GNUNET_YES
105 : GNUNET_NO;
106}
107
108
109/**
110 * Compute a type map message for this peer.
111 *
112 * @return this peers current type map message.
113 */
114struct GNUNET_MessageHeader *
115GSC_TYPEMAP_compute_type_map_message ()
116{
117 char *tmp;
118 uLongf dlen;
119 struct GNUNET_MessageHeader *hdr;
120
121#ifdef compressBound
122 dlen = compressBound (sizeof(my_type_map));
123#else
124 dlen = sizeof(my_type_map) + (sizeof(my_type_map) / 100) + 20;
125 /* documentation says 100.1% oldSize + 12 bytes, but we
126 * should be able to overshoot by more to be safe */
127#endif
128 hdr = GNUNET_malloc (dlen + sizeof(struct GNUNET_MessageHeader));
129 tmp = (char *) &hdr[1];
130 if ((Z_OK != compress2 ((Bytef *) tmp,
131 &dlen,
132 (const Bytef *) &my_type_map,
133 sizeof(my_type_map),
134 9)) ||
135 (dlen >= sizeof(my_type_map)))
136 {
137 /* compression failed, use uncompressed map */
138 dlen = sizeof(my_type_map);
139 GNUNET_memcpy (tmp, &my_type_map, sizeof(my_type_map));
140 hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP);
141 }
142 else
143 {
144 /* compression worked, use compressed map */
145 hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP);
146 }
147 hdr->size = htons ((uint16_t) dlen + sizeof(struct GNUNET_MessageHeader));
148 return hdr;
149}
150
151
152/**
153 * Extract a type map from a TYPE_MAP message.
154 *
155 * @param msg a type map message
156 * @return NULL on error
157 */
158struct GSC_TypeMap *
159GSC_TYPEMAP_get_from_message (const struct GNUNET_MessageHeader *msg)
160{
161 struct GSC_TypeMap *ret;
162 uint16_t size;
163 uLongf dlen;
164
165 size = ntohs (msg->size);
166 switch (ntohs (msg->type))
167 {
168 case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP:
169 GNUNET_STATISTICS_update (GSC_stats,
170 gettext_noop ("# type maps received"),
171 1,
172 GNUNET_NO);
173 if (size != sizeof(struct GSC_TypeMap))
174 {
175 GNUNET_break_op (0);
176 return NULL;
177 }
178 ret = GNUNET_new (struct GSC_TypeMap);
179 GNUNET_memcpy (ret, &msg[1], sizeof(struct GSC_TypeMap));
180 return ret;
181
182 case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
183 GNUNET_STATISTICS_update (GSC_stats,
184 gettext_noop ("# type maps received"),
185 1,
186 GNUNET_NO);
187 ret = GNUNET_new (struct GSC_TypeMap);
188 dlen = sizeof(struct GSC_TypeMap);
189 if ((Z_OK != uncompress ((Bytef *) ret,
190 &dlen,
191 (const Bytef *) &msg[1],
192 (uLong) size)) ||
193 (dlen != sizeof(struct GSC_TypeMap)))
194 {
195 GNUNET_break_op (0);
196 GNUNET_free (ret);
197 return NULL;
198 }
199 return ret;
200
201 default:
202 GNUNET_break (0);
203 return NULL;
204 }
205}
206
207
208/**
209 * Send my type map to all connected peers (it got changed).
210 */
211static void
212broadcast_my_type_map ()
213{
214 struct GNUNET_MessageHeader *hdr;
215
216 hdr = GSC_TYPEMAP_compute_type_map_message ();
217 GNUNET_STATISTICS_update (GSC_stats,
218 gettext_noop ("# updates to my type map"),
219 1,
220 GNUNET_NO);
221 GSC_SESSIONS_broadcast_typemap (hdr);
222 GNUNET_free (hdr);
223}
224
225
226/**
227 * Add a set of types to our type map.
228 *
229 * @param types array of message types supported by this peer
230 * @param tlen number of entries in @a types
231 */
232void
233GSC_TYPEMAP_add (const uint16_t *types, unsigned int tlen)
234{
235 unsigned int i;
236 int changed;
237
238 changed = GNUNET_NO;
239 for (i = 0; i < tlen; i++)
240 {
241 if (0 == map_counters[types[i]]++)
242 {
243 my_type_map.bits[types[i] / 32] |= (1 << (types[i] % 32));
244 changed = GNUNET_YES;
245 }
246 }
247 if (GNUNET_YES == changed)
248 {
249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Typemap changed, broadcasting!\n");
250 rehash_typemap ();
251 broadcast_my_type_map ();
252 }
253}
254
255
256/**
257 * Remove a set of types from our type map.
258 *
259 * @param types array of types to remove
260 * @param tlen length of the @a types array
261 */
262void
263GSC_TYPEMAP_remove (const uint16_t *types, unsigned int tlen)
264{
265 int changed;
266
267 changed = GNUNET_NO;
268 for (unsigned int i = 0; i < tlen; i++)
269 {
270 if (0 == --map_counters[types[i]])
271 {
272 my_type_map.bits[types[i] / 32] &= ~(1 << (types[i] % 32));
273 changed = GNUNET_YES;
274 }
275 }
276 if (GNUNET_YES == changed)
277 {
278 rehash_typemap ();
279 broadcast_my_type_map ();
280 }
281}
282
283
284/**
285 * Test if any of the types from the types array is in the
286 * given type map.
287 *
288 * @param tmap map to test
289 * @param types array of types
290 * @param tcnt number of entries in @a types
291 * @return #GNUNET_YES if a type is in the map, #GNUNET_NO if not
292 */
293int
294GSC_TYPEMAP_test_match (const struct GSC_TypeMap *tmap,
295 const uint16_t *types,
296 unsigned int tcnt)
297{
298 if (NULL == tmap)
299 return GNUNET_NO;
300 if (0 == tcnt)
301 return GNUNET_YES; /* matches all */
302 for (unsigned int i = 0; i < tcnt; i++)
303 if (0 != (tmap->bits[types[i] / 32] & (1 << (types[i] % 32))))
304 return GNUNET_YES;
305 return GNUNET_NO;
306}
307
308
309/**
310 * Add additional types to a given typemap.
311 *
312 * @param tmap map to extend (not changed)
313 * @param types array of types to add
314 * @param tcnt number of entries in @a types
315 * @return updated type map (fresh copy)
316 */
317struct GSC_TypeMap *
318GSC_TYPEMAP_extend (const struct GSC_TypeMap *tmap,
319 const uint16_t *types,
320 unsigned int tcnt)
321{
322 struct GSC_TypeMap *ret;
323
324 ret = GNUNET_new (struct GSC_TypeMap);
325 if (NULL != tmap)
326 GNUNET_memcpy (ret, tmap, sizeof(struct GSC_TypeMap));
327 for (unsigned int i = 0; i < tcnt; i++)
328 ret->bits[types[i] / 32] |= (1 << (types[i] % 32));
329 return ret;
330}
331
332
333/**
334 * Create an empty type map.
335 *
336 * @return an empty type map
337 */
338struct GSC_TypeMap *
339GSC_TYPEMAP_create ()
340{
341 return GNUNET_new (struct GSC_TypeMap);
342}
343
344
345/**
346 * Free the given type map.
347 *
348 * @param tmap a type map
349 */
350void
351GSC_TYPEMAP_destroy (struct GSC_TypeMap *tmap)
352{
353 GNUNET_free (tmap);
354}
355
356
357/**
358 * Initialize typemap subsystem.
359 */
360void
361GSC_TYPEMAP_init ()
362{
363 /* nothing to do */
364}
365
366
367/**
368 * Shutdown typemap subsystem.
369 */
370void
371GSC_TYPEMAP_done ()
372{
373 /* nothing to do */
374}
375
376
377/* end of gnunet-service-core_typemap.c */
diff --git a/src/core/gnunet-service-core_typemap.h b/src/core/gnunet-service-core_typemap.h
deleted file mode 100644
index 7acdec53b..000000000
--- a/src/core/gnunet-service-core_typemap.h
+++ /dev/null
@@ -1,163 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify 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 core/gnunet-service-core_typemap.h
23 * @brief management of map that specifies which message types this peer supports
24 * @author Christian Grothoff
25 */
26#ifndef GNUNET_SERVICE_CORE_TYPEMAP_H
27#define GNUNET_SERVICE_CORE_TYPEMAP_H
28
29#include "gnunet_util_lib.h"
30#include "gnunet_transport_service.h"
31
32/**
33 * Map specifying which message types a peer supports.
34 */
35struct GSC_TypeMap;
36
37
38/**
39 * Add a set of types to our type map.
40 *
41 * @param types array of message types supported by this peer
42 * @param tlen number of entries in @a types
43 */
44void
45GSC_TYPEMAP_add (const uint16_t *types,
46 unsigned int tlen);
47
48
49/**
50 * Remove a set of message types from our type map.
51 *
52 * @param types array of message types no longer supported by this peer
53 * @param tlen number of entries in @a types
54 */
55void
56GSC_TYPEMAP_remove (const uint16_t *types,
57 unsigned int tlen);
58
59
60/**
61 * Compute a type map message for this peer.
62 *
63 * @return this peers current type map message.
64 */
65struct GNUNET_MessageHeader *
66GSC_TYPEMAP_compute_type_map_message (void);
67
68
69/**
70 * Check if the given hash matches our current type map.
71 *
72 * @param hc hash code to check if it matches our type map
73 * @return #GNUNET_YES if the hash matches, #GNUNET_NO if not
74 */
75int
76GSC_TYPEMAP_check_hash (const struct GNUNET_HashCode *hc);
77
78
79/**
80 * Hash the contents of a type map.
81 *
82 * @param tm map to hash
83 * @param hc where to store the hash code
84 */
85void
86GSC_TYPEMAP_hash (const struct GSC_TypeMap *tm,
87 struct GNUNET_HashCode *hc);
88
89
90/**
91 * Extract a type map from a
92 * #GNUNET_MESSAGE_TYPE_CORE_COMRESSED_TYPE_MAP or
93 * #GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP message.
94 *
95 * @param msg a type map message
96 * @return NULL on error
97 */
98struct GSC_TypeMap *
99GSC_TYPEMAP_get_from_message (const struct GNUNET_MessageHeader *msg);
100
101
102/**
103 * Test if any of the types from the types array is in the
104 * given type map.
105 *
106 * @param tmap map to test
107 * @param types array of types
108 * @param tcnt number of entries in @a types
109 * @return #GNUNET_YES if a type is in the map, #GNUNET_NO if not
110 */
111int
112GSC_TYPEMAP_test_match (const struct GSC_TypeMap *tmap,
113 const uint16_t *types,
114 unsigned int tcnt);
115
116
117/**
118 * Add additional types to a given typemap.
119 *
120 * @param tmap map to extend (not changed)
121 * @param types array of types to add
122 * @param tcnt number of entries in @a types
123 * @return updated type map (fresh copy)
124 */
125struct GSC_TypeMap *
126GSC_TYPEMAP_extend (const struct GSC_TypeMap *tmap,
127 const uint16_t *types,
128 unsigned int tcnt);
129
130
131/**
132 * Create an empty type map.
133 *
134 * @return an empty type map
135 */
136struct GSC_TypeMap *
137GSC_TYPEMAP_create (void);
138
139
140/**
141 * Free the given type map.
142 *
143 * @param tmap a type map
144 */
145void
146GSC_TYPEMAP_destroy (struct GSC_TypeMap *tmap);
147
148
149/**
150 * Initialize typemap subsystem.
151 */
152void
153GSC_TYPEMAP_init (void);
154
155
156/**
157 * Shutdown typemap subsystem.
158 */
159void
160GSC_TYPEMAP_done (void);
161
162#endif
163/* end of gnunet-service-core_typemap.h */
diff --git a/src/core/test_core_api.c b/src/core/test_core_api.c
deleted file mode 100644
index 064964292..000000000
--- a/src/core/test_core_api.c
+++ /dev/null
@@ -1,344 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2015, 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 * @file core/test_core_api.c
22 * @brief testcase for core_api.c
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_arm_service.h"
27#include "gnunet_core_service.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_transport_service.h"
30#include "gnunet_transport_hello_service.h"
31#include "gnunet_ats_service.h"
32
33#define MTYPE 12345
34
35struct PeerContext
36{
37 struct GNUNET_CONFIGURATION_Handle *cfg;
38 struct GNUNET_CORE_Handle *ch;
39 struct GNUNET_PeerIdentity id;
40 struct GNUNET_TRANSPORT_OfferHelloHandle *oh;
41 struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
42 struct GNUNET_ATS_ConnectivityHandle *ats;
43 struct GNUNET_ATS_ConnectivitySuggestHandle *ats_sh;
44 struct GNUNET_MessageHeader *hello;
45 int connect_status;
46 struct GNUNET_OS_Process *arm_proc;
47};
48
49static struct PeerContext p1;
50
51static struct PeerContext p2;
52
53static struct GNUNET_SCHEDULER_Task *err_task;
54
55static int ok;
56
57#define OKPP \
58 do \
59 { \
60 ok++; \
61 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, \
62 "Now at stage %u at %s:%u\n", \
63 ok, \
64 __FILE__, \
65 __LINE__); \
66 } while (0)
67
68
69static void
70offer_hello_done (void *cls)
71{
72 struct PeerContext *p = cls;
73
74 p->oh = NULL;
75}
76
77
78static void
79process_hello (void *cls, const struct GNUNET_MessageHeader *message)
80{
81 struct PeerContext *p = cls;
82
83 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
84 "Received (my) HELLO from transport service\n");
85 GNUNET_assert (message != NULL);
86 if ((p == &p1) && (NULL == p2.oh))
87 p2.oh =
88 GNUNET_TRANSPORT_offer_hello (p2.cfg, message, &offer_hello_done, &p2);
89 if ((p == &p2) && (NULL == p1.oh))
90 p1.oh =
91 GNUNET_TRANSPORT_offer_hello (p1.cfg, message, &offer_hello_done, &p1);
92}
93
94
95static void
96terminate_peer (struct PeerContext *p)
97{
98 if (NULL != p->ch)
99 {
100 GNUNET_CORE_disconnect (p->ch);
101 p->ch = NULL;
102 }
103 if (NULL != p->ghh)
104 {
105 GNUNET_TRANSPORT_hello_get_cancel (p->ghh);
106 p->ghh = NULL;
107 }
108 if (NULL != p->oh)
109 {
110 GNUNET_TRANSPORT_offer_hello_cancel (p->oh);
111 p->oh = NULL;
112 }
113 if (NULL != p->ats_sh)
114 {
115 GNUNET_ATS_connectivity_suggest_cancel (p->ats_sh);
116 p->ats_sh = NULL;
117 }
118 if (NULL != p->ats)
119 {
120 GNUNET_ATS_connectivity_done (p->ats);
121 p->ats = NULL;
122 }
123}
124
125
126static void
127terminate_task (void *cls)
128{
129 GNUNET_assert (ok == 6);
130 terminate_peer (&p1);
131 terminate_peer (&p2);
132 ok = 0;
133}
134
135
136static void
137terminate_task_error (void *cls)
138{
139 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ENDING ANGRILY %u\n", ok);
140 GNUNET_break (0);
141 terminate_peer (&p1);
142 terminate_peer (&p2);
143 ok = 42;
144}
145
146
147static void *
148connect_notify (void *cls,
149 const struct GNUNET_PeerIdentity *peer,
150 struct GNUNET_MQ_Handle *mq)
151{
152 struct PeerContext *pc = cls;
153 struct GNUNET_MQ_Envelope *env;
154 struct GNUNET_MessageHeader *msg;
155
156 if (0 == memcmp (&pc->id, peer, sizeof(struct GNUNET_PeerIdentity)))
157 return (void *) peer;
158 GNUNET_assert (pc->connect_status == 0);
159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
160 "Encrypted connection established to peer `%s'\n",
161 GNUNET_i2s (peer));
162 pc->connect_status = 1;
163 if (pc == &p1)
164 {
165 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
166 "Asking core (1) for transmission to peer `%s'\n",
167 GNUNET_i2s (&p2.id));
168 env = GNUNET_MQ_msg (msg, MTYPE);
169 /* enable corking for this test */
170 GNUNET_MQ_env_set_options (env,
171 GNUNET_MQ_PRIO_BEST_EFFORT
172 | GNUNET_MQ_PREF_CORK_ALLOWED);
173 /* now actually transmit message */
174 GNUNET_assert (ok == 4);
175 OKPP;
176 GNUNET_MQ_send (mq, env);
177 }
178 return (void *) peer;
179}
180
181
182static void
183disconnect_notify (void *cls,
184 const struct GNUNET_PeerIdentity *peer,
185 void *internal_cls)
186{
187 struct PeerContext *pc = cls;
188
189 if (0 == memcmp (&pc->id, peer, sizeof(struct GNUNET_PeerIdentity)))
190 return;
191 pc->connect_status = 0;
192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
193 "Encrypted connection to `%s' cut\n",
194 GNUNET_i2s (peer));
195}
196
197
198static void
199handle_test (void *cls, const struct GNUNET_MessageHeader *message)
200{
201 const struct GNUNET_PeerIdentity *peer = cls;
202
203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
204 "Receiving message from `%s'.\n",
205 GNUNET_i2s (peer));
206 GNUNET_assert (ok == 5);
207 OKPP;
208 GNUNET_SCHEDULER_cancel (err_task);
209 err_task = GNUNET_SCHEDULER_add_now (&terminate_task, NULL);
210}
211
212
213static void
214init_notify (void *cls, const struct GNUNET_PeerIdentity *my_identity)
215{
216 struct PeerContext *p = cls;
217 struct GNUNET_MQ_MessageHandler handlers[] =
218 { GNUNET_MQ_hd_fixed_size (test, MTYPE, struct GNUNET_MessageHeader, NULL),
219 GNUNET_MQ_handler_end () };
220
221 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
222 "Core connection to `%s' established\n",
223 GNUNET_i2s (my_identity));
224 p->id = *my_identity;
225 if (cls == &p1)
226 {
227 GNUNET_assert (ok == 2);
228 OKPP;
229 /* connect p2 */
230 p2.ch = GNUNET_CORE_connect (p2.cfg,
231 &p2,
232 &init_notify,
233 &connect_notify,
234 &disconnect_notify,
235 handlers);
236 }
237 else
238 {
239 GNUNET_assert (ok == 3);
240 OKPP;
241 GNUNET_assert (cls == &p2);
242 p1.ats_sh = GNUNET_ATS_connectivity_suggest (p1.ats, &p2.id, 1);
243 }
244}
245
246
247static void
248setup_peer (struct PeerContext *p, const char *cfgname)
249{
250 char *binary;
251
252 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
253 p->cfg = GNUNET_CONFIGURATION_create ();
254 p->arm_proc = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
255 | GNUNET_OS_USE_PIPE_CONTROL,
256 NULL,
257 NULL,
258 NULL,
259 binary,
260 "gnunet-service-arm",
261 "-c",
262 cfgname,
263 NULL);
264 GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
265 p->ats = GNUNET_ATS_connectivity_init (p->cfg);
266 GNUNET_assert (NULL != p->ats);
267 p->ghh = GNUNET_TRANSPORT_hello_get (p->cfg,
268 GNUNET_TRANSPORT_AC_ANY,
269 &process_hello,
270 p);
271 GNUNET_free (binary);
272}
273
274
275static void
276run (void *cls,
277 char *const *args,
278 const char *cfgfile,
279 const struct GNUNET_CONFIGURATION_Handle *cfg)
280{
281 struct GNUNET_MQ_MessageHandler handlers[] =
282 { GNUNET_MQ_hd_fixed_size (test, MTYPE, struct GNUNET_MessageHeader, NULL),
283 GNUNET_MQ_handler_end () };
284
285 GNUNET_assert (ok == 1);
286 OKPP;
287 setup_peer (&p1, "test_core_api_peer1.conf");
288 setup_peer (&p2, "test_core_api_peer2.conf");
289 err_task = GNUNET_SCHEDULER_add_delayed (
290 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300),
291 &terminate_task_error,
292 NULL);
293 p1.ch = GNUNET_CORE_connect (p1.cfg,
294 &p1,
295 &init_notify,
296 &connect_notify,
297 &disconnect_notify,
298 handlers);
299}
300
301
302static void
303stop_arm (struct PeerContext *p)
304{
305 if (0 != GNUNET_OS_process_kill (p->arm_proc, GNUNET_TERM_SIG))
306 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
307 if (GNUNET_OK != GNUNET_OS_process_wait (p->arm_proc))
308 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
310 "ARM process %u stopped\n",
311 GNUNET_OS_process_get_pid (p->arm_proc));
312 GNUNET_OS_process_destroy (p->arm_proc);
313 p->arm_proc = NULL;
314 GNUNET_CONFIGURATION_destroy (p->cfg);
315}
316
317
318int
319main (int argc, char *argv1[])
320{
321 char *const argv[] = { "test-core-api", "-c", "test_core_api_data.conf",
322 NULL };
323 struct GNUNET_GETOPT_CommandLineOption options[] =
324 { GNUNET_GETOPT_OPTION_END };
325
326 ok = 1;
327 GNUNET_log_setup ("test-core-api", "WARNING", NULL);
328 GNUNET_PROGRAM_run ((sizeof(argv) / sizeof(char *)) - 1,
329 argv,
330 "test-core-api",
331 "nohelp",
332 options,
333 &run,
334 &ok);
335 stop_arm (&p1);
336 stop_arm (&p2);
337 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-1");
338 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-2");
339
340 return ok;
341}
342
343
344/* end of test_core_api.c */
diff --git a/src/core/test_core_api_data.conf b/src/core/test_core_api_data.conf
deleted file mode 100644
index 420849ba9..000000000
--- a/src/core/test_core_api_data.conf
+++ /dev/null
@@ -1,11 +0,0 @@
1@INLINE@ test_core_defaults.conf
2[PATHS]
3
4[ats]
5WAN_QUOTA_IN = 64 kiB
6WAN_QUOTA_OUT = 64 kiB
7
8[core]
9PORT = 52092
10UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-core.sock
11
diff --git a/src/core/test_core_api_peer1.conf b/src/core/test_core_api_peer1.conf
deleted file mode 100644
index 28463effe..000000000
--- a/src/core/test_core_api_peer1.conf
+++ /dev/null
@@ -1,42 +0,0 @@
1@INLINE@ test_core_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-core-peer-1/
4
5[arm]
6PORT = 12460
7UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
8
9[statistics]
10PORT = 12461
11
12[resolver]
13PORT = 12462
14UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
15
16[peerinfo]
17PORT = 12463
18UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
19
20[transport]
21PORT = 12464
22UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
23
24[core]
25PORT = 12475
26UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-core.sock
27
28[ats]
29PORT = 12476
30UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-ats.sock
31
32[transport-tcp]
33PORT = 12467
34
35[transport-udp]
36PORT = 12468
37
38[transport-unix]
39PORT = 12469
40
41[transport-http]
42PORT = 12470
diff --git a/src/core/test_core_api_peer2.conf b/src/core/test_core_api_peer2.conf
deleted file mode 100644
index 819d58d17..000000000
--- a/src/core/test_core_api_peer2.conf
+++ /dev/null
@@ -1,43 +0,0 @@
1@INLINE@ test_core_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-core-peer-2/
4
5[arm]
6PORT = 22460
7UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
8
9[statistics]
10PORT = 22461
11UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
12
13[resolver]
14PORT = 22462
15UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
16
17[peerinfo]
18PORT = 22463
19UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
20
21[transport]
22PORT = 22464
23UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
24
25[core]
26PORT = 22475
27UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-core.sock
28
29[ats]
30PORT = 22476
31UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-ats.sock
32
33[transport-tcp]
34PORT = 22467
35
36[transport-udp]
37PORT = 22468
38
39[transport-unix]
40PORT = 22469
41
42[transport-http]
43PORT = 22470
diff --git a/src/core/test_core_api_reliability.c b/src/core/test_core_api_reliability.c
deleted file mode 100644
index debf808ca..000000000
--- a/src/core/test_core_api_reliability.c
+++ /dev/null
@@ -1,535 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2015, 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 * @file core/test_core_api_reliability.c
22 * @brief testcase for core_api.c focusing on reliable transmission (with TCP)
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_arm_service.h"
27#include "gnunet_core_service.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_ats_service.h"
30#include "gnunet_transport_service.h"
31#include "gnunet_transport_hello_service.h"
32#include <gauger.h>
33
34/**
35 * Note that this value must not significantly exceed
36 * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise
37 * messages may be dropped even for a reliable transport.
38 */
39#define TOTAL_MSGS (600 * 10)
40
41/**
42 * How long until we give up on transmitting the message?
43 */
44#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
45
46#define MTYPE 12345
47
48
49static unsigned long long total_bytes;
50
51static struct GNUNET_TIME_Absolute start_time;
52
53static struct GNUNET_SCHEDULER_Task *err_task;
54
55
56struct PeerContext
57{
58 struct GNUNET_CONFIGURATION_Handle *cfg;
59 struct GNUNET_CORE_Handle *ch;
60 struct GNUNET_MQ_Handle *mq;
61 struct GNUNET_PeerIdentity id;
62 struct GNUNET_TRANSPORT_OfferHelloHandle *oh;
63 struct GNUNET_MessageHeader *hello;
64 struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
65 struct GNUNET_ATS_ConnectivityHandle *ats;
66 struct GNUNET_ATS_ConnectivitySuggestHandle *ats_sh;
67 int connect_status;
68 struct GNUNET_OS_Process *arm_proc;
69};
70
71static struct PeerContext p1;
72
73static struct PeerContext p2;
74
75static int ok;
76
77static int32_t tr_n;
78
79
80#define OKPP do { ok++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, \
81 "Now at stage %u at %s:%u\n", ok, __FILE__, \
82 __LINE__); } while (0)
83
84struct TestMessage
85{
86 struct GNUNET_MessageHeader header;
87 uint32_t num GNUNET_PACKED;
88};
89
90
91static unsigned int
92get_size (unsigned int iter)
93{
94 unsigned int ret;
95
96 if (iter < 60000)
97 return iter + sizeof(struct TestMessage);
98 ret = (iter * iter * iter);
99 return sizeof(struct TestMessage) + (ret % 60000);
100}
101
102
103static void
104terminate_peer (struct PeerContext *p)
105{
106 if (NULL != p->ch)
107 {
108 GNUNET_CORE_disconnect (p->ch);
109 p->ch = NULL;
110 }
111 if (NULL != p->ghh)
112 {
113 GNUNET_TRANSPORT_hello_get_cancel (p->ghh);
114 p->ghh = NULL;
115 }
116 if (NULL != p->oh)
117 {
118 GNUNET_TRANSPORT_offer_hello_cancel (p->oh);
119 p->oh = NULL;
120 }
121 if (NULL != p->ats_sh)
122 {
123 GNUNET_ATS_connectivity_suggest_cancel (p->ats_sh);
124 p->ats_sh = NULL;
125 }
126 if (NULL != p->ats)
127 {
128 GNUNET_ATS_connectivity_done (p->ats);
129 p->ats = NULL;
130 }
131}
132
133
134static void
135terminate_task_error (void *cls)
136{
137 err_task = NULL;
138 GNUNET_break (0);
139 GNUNET_SCHEDULER_shutdown ();
140 ok = 42;
141}
142
143
144static void
145do_shutdown (void *cls)
146{
147 unsigned long long delta;
148
149 delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us;
150 if (0 == delta)
151 delta = 1;
152 fprintf (stderr,
153 "\nThroughput was %llu kb/s\n",
154 total_bytes * 1000000LL / 1024 / delta);
155 GAUGER ("CORE",
156 "Core throughput/s",
157 total_bytes * 1000000LL / 1024 / delta,
158 "kb/s");
159 if (NULL != err_task)
160 {
161 GNUNET_SCHEDULER_cancel (err_task);
162 err_task = NULL;
163 }
164 terminate_peer (&p1);
165 terminate_peer (&p2);
166}
167
168
169static void
170send_message (struct GNUNET_MQ_Handle *mq,
171 int32_t num)
172{
173 struct GNUNET_MQ_Envelope *env;
174 struct TestMessage *hdr;
175 unsigned int s;
176
177 GNUNET_assert (NULL != mq);
178 GNUNET_assert (tr_n < TOTAL_MSGS);
179 s = get_size (tr_n);
180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
181 "Sending message %u of size %u\n",
182 tr_n,
183 s);
184 env = GNUNET_MQ_msg_extra (hdr,
185 s - sizeof(struct TestMessage),
186 MTYPE);
187 hdr->num = htonl (tr_n);
188 memset (&hdr[1],
189 tr_n,
190 s - sizeof(struct TestMessage));
191 tr_n++;
192 GNUNET_SCHEDULER_cancel (err_task);
193 err_task =
194 GNUNET_SCHEDULER_add_delayed (TIMEOUT,
195 &terminate_task_error,
196 NULL);
197 total_bytes += s;
198 GNUNET_MQ_send (mq,
199 env);
200}
201
202
203static void *
204connect_notify (void *cls,
205 const struct GNUNET_PeerIdentity *peer,
206 struct GNUNET_MQ_Handle *mq)
207{
208 struct PeerContext *pc = cls;
209
210 if (0 == memcmp (&pc->id,
211 peer,
212 sizeof(struct GNUNET_PeerIdentity)))
213 return (void *) peer;
214 pc->mq = mq;
215 GNUNET_assert (0 == pc->connect_status);
216 pc->connect_status = 1;
217 if (pc == &p1)
218 {
219 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
220 "Encrypted connection established to peer `%s'\n",
221 GNUNET_i2s (peer));
222 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
223 "Asking core (1) for transmission to peer `%s'\n",
224 GNUNET_i2s (&p2.id));
225 GNUNET_SCHEDULER_cancel (err_task);
226 err_task =
227 GNUNET_SCHEDULER_add_delayed (TIMEOUT,
228 &terminate_task_error,
229 NULL);
230 start_time = GNUNET_TIME_absolute_get ();
231 send_message (mq,
232 0);
233 }
234 return (void *) peer;
235}
236
237
238static void
239disconnect_notify (void *cls,
240 const struct GNUNET_PeerIdentity *peer,
241 void *internal_cls)
242{
243 struct PeerContext *pc = cls;
244
245 if (0 == memcmp (&pc->id,
246 peer,
247 sizeof(struct GNUNET_PeerIdentity)))
248 return;
249 pc->mq = NULL;
250 pc->connect_status = 0;
251 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
252 "Encrypted connection to `%s' cut\n",
253 GNUNET_i2s (peer));
254}
255
256
257static int
258check_test (void *cls,
259 const struct TestMessage *hdr)
260{
261 return GNUNET_OK; /* accept all */
262}
263
264
265static void
266handle_test (void *cls,
267 const struct TestMessage *hdr)
268{
269 static int n;
270 unsigned int s;
271
272 s = get_size (n);
273 if (ntohs (hdr->header.size) != s)
274 {
275 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
276 "Expected message %u of size %u, got %u bytes of message %u\n",
277 n,
278 s,
279 ntohs (hdr->header.size),
280 ntohl (hdr->num));
281 GNUNET_SCHEDULER_cancel (err_task);
282 err_task = GNUNET_SCHEDULER_add_now (&terminate_task_error,
283 NULL);
284 return;
285 }
286 if (ntohl (hdr->num) != n)
287 {
288 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
289 "Expected message %u of size %u, got %u bytes of message %u\n",
290 n,
291 s,
292 (unsigned int) ntohs (hdr->header.size),
293 (unsigned int) ntohl (hdr->num));
294 GNUNET_SCHEDULER_cancel (err_task);
295 err_task = GNUNET_SCHEDULER_add_now (&terminate_task_error,
296 NULL);
297 return;
298 }
299 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
300 "Got message %u of size %u\n",
301 (unsigned int) ntohl (hdr->num),
302 (unsigned int) ntohs (hdr->header.size));
303 n++;
304 if (0 == (n % (TOTAL_MSGS / 100)))
305 fprintf (stderr,
306 "%s",
307 ".");
308 if (n == TOTAL_MSGS)
309 {
310 ok = 0;
311 GNUNET_SCHEDULER_shutdown ();
312 }
313 else
314 {
315 if (n == tr_n)
316 {
317 send_message (p1.mq,
318 tr_n);
319 }
320 }
321}
322
323
324static void
325init_notify (void *cls,
326 const struct GNUNET_PeerIdentity *my_identity)
327{
328 struct PeerContext *p = cls;
329 struct GNUNET_MQ_MessageHandler handlers[] = {
330 GNUNET_MQ_hd_var_size (test,
331 MTYPE,
332 struct TestMessage,
333 NULL),
334 GNUNET_MQ_handler_end ()
335 };
336
337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
338 "Connection to CORE service of `%s' established\n",
339 GNUNET_i2s (my_identity));
340 p->id = *my_identity;
341 if (cls == &p1)
342 {
343 GNUNET_assert (ok == 2);
344 OKPP;
345 /* connect p2 */
346 GNUNET_assert (NULL !=
347 (p2.ch = GNUNET_CORE_connect (p2.cfg,
348 &p2,
349 &init_notify,
350 &connect_notify,
351 &disconnect_notify,
352 handlers)));
353 }
354 else
355 {
356 GNUNET_assert (ok == 3);
357 OKPP;
358 GNUNET_assert (cls == &p2);
359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
360 "Asking transport (1) to connect to peer `%s'\n",
361 GNUNET_i2s (&p2.id));
362 p1.ats_sh = GNUNET_ATS_connectivity_suggest (p1.ats,
363 &p2.id,
364 1);
365 }
366}
367
368
369static void
370offer_hello_done (void *cls)
371{
372 struct PeerContext *p = cls;
373
374 p->oh = NULL;
375}
376
377
378static void
379process_hello (void *cls,
380 const struct GNUNET_MessageHeader *message)
381{
382 struct PeerContext *p = cls;
383
384 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
385 "Received (my) `%s' from transport service\n", "HELLO");
386 GNUNET_assert (message != NULL);
387 GNUNET_free (p->hello);
388 p->hello = GNUNET_copy_message (message);
389 if ((p == &p1) && (NULL == p2.oh))
390 p2.oh = GNUNET_TRANSPORT_offer_hello (p2.cfg,
391 message,
392 &offer_hello_done,
393 &p2);
394 if ((p == &p2) && (NULL == p1.oh))
395 p1.oh = GNUNET_TRANSPORT_offer_hello (p1.cfg,
396 message,
397 &offer_hello_done,
398 &p1);
399
400 if ((p == &p1) && (p2.hello != NULL) && (NULL == p1.oh))
401 p1.oh = GNUNET_TRANSPORT_offer_hello (p1.cfg,
402 p2.hello,
403 &offer_hello_done,
404 &p1);
405 if ((p == &p2) && (p1.hello != NULL) && (NULL == p2.oh))
406 p2.oh = GNUNET_TRANSPORT_offer_hello (p2.cfg,
407 p1.hello,
408 &offer_hello_done,
409 &p2);
410}
411
412
413static void
414setup_peer (struct PeerContext *p,
415 const char *cfgname)
416{
417 char *binary;
418
419 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
420 p->cfg = GNUNET_CONFIGURATION_create ();
421 p->arm_proc
422 = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
423 | GNUNET_OS_USE_PIPE_CONTROL,
424 NULL, NULL, NULL,
425 binary,
426 "gnunet-service-arm",
427 "-c",
428 cfgname,
429 NULL);
430 GNUNET_assert (GNUNET_OK ==
431 GNUNET_CONFIGURATION_load (p->cfg,
432 cfgname));
433 p->ats = GNUNET_ATS_connectivity_init (p->cfg);
434 GNUNET_assert (NULL != p->ats);
435 p->ghh = GNUNET_TRANSPORT_hello_get (p->cfg,
436 GNUNET_TRANSPORT_AC_ANY,
437 &process_hello,
438 p);
439 GNUNET_free (binary);
440}
441
442
443static void
444run (void *cls,
445 char *const *args,
446 const char *cfgfile,
447 const struct GNUNET_CONFIGURATION_Handle *cfg)
448{
449 struct GNUNET_MQ_MessageHandler handlers[] = {
450 GNUNET_MQ_hd_fixed_size (test,
451 MTYPE,
452 struct TestMessage,
453 NULL),
454 GNUNET_MQ_handler_end ()
455 };
456
457 GNUNET_assert (ok == 1);
458 OKPP;
459 setup_peer (&p1,
460 "test_core_api_peer1.conf");
461 setup_peer (&p2,
462 "test_core_api_peer2.conf");
463 err_task =
464 GNUNET_SCHEDULER_add_delayed (TIMEOUT,
465 &terminate_task_error,
466 NULL);
467 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
468 NULL);
469
470 GNUNET_assert (NULL !=
471 (p1.ch = GNUNET_CORE_connect (p1.cfg,
472 &p1,
473 &init_notify,
474 &connect_notify,
475 &disconnect_notify,
476 handlers)));
477}
478
479
480static void
481stop_arm (struct PeerContext *p)
482{
483 if (0 != GNUNET_OS_process_kill (p->arm_proc,
484 GNUNET_TERM_SIG))
485 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
486 "kill");
487 if (GNUNET_OK != GNUNET_OS_process_wait (p->arm_proc))
488 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
489 "waitpid");
490 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
491 "ARM process %u stopped\n",
492 GNUNET_OS_process_get_pid (p->arm_proc));
493 GNUNET_OS_process_destroy (p->arm_proc);
494 p->arm_proc = NULL;
495 GNUNET_CONFIGURATION_destroy (p->cfg);
496}
497
498
499int
500main (int argc,
501 char *argv1[])
502{
503 char *const argv[] = {
504 "test-core-api-reliability",
505 "-c",
506 "test_core_api_data.conf",
507 NULL
508 };
509 struct GNUNET_GETOPT_CommandLineOption options[] = {
510 GNUNET_GETOPT_OPTION_END
511 };
512
513 ok = 1;
514 GNUNET_log_setup ("test-core-api-reliability",
515 "WARNING",
516 NULL);
517 GNUNET_PROGRAM_run ((sizeof(argv) / sizeof(char *)) - 1,
518 argv,
519 "test-core-api-reliability",
520 "nohelp",
521 options,
522 &run,
523 &ok);
524 stop_arm (&p1);
525 stop_arm (&p2);
526 GNUNET_free (p1.hello);
527 GNUNET_free (p2.hello);
528 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-1");
529 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-2");
530
531 return ok;
532}
533
534
535/* end of test_core_api_reliability.c */
diff --git a/src/core/test_core_api_send_to_self.c b/src/core/test_core_api_send_to_self.c
deleted file mode 100644
index c2e39cd26..000000000
--- a/src/core/test_core_api_send_to_self.c
+++ /dev/null
@@ -1,195 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010, 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 core/test_core_api_send_to_self.c
23 * @brief test that sending a message to ourselves via CORE works
24 * @author Philipp Toelke
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_testing_lib.h"
30#include "gnunet_protocols.h"
31#include "gnunet_core_service.h"
32#include "gnunet_constants.h"
33
34/**
35 * Final status code.
36 */
37static int ret;
38
39/**
40 * Handle to the cleanup task.
41 */
42static struct GNUNET_SCHEDULER_Task *die_task;
43
44/**
45 * Identity of this peer.
46 */
47static struct GNUNET_PeerIdentity myself;
48
49/**
50 * The handle to core
51 */
52static struct GNUNET_CORE_Handle *core;
53
54
55/**
56 * Function scheduled as very last function, cleans up after us
57 */
58static void
59cleanup (void *cls)
60{
61 if (NULL != die_task)
62 {
63 GNUNET_SCHEDULER_cancel (die_task);
64 die_task = NULL;
65 }
66 if (NULL != core)
67 {
68 GNUNET_CORE_disconnect (core);
69 core = NULL;
70 }
71 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
72 "Ending test.\n");
73}
74
75
76/**
77 * Function scheduled as very last function, cleans up after us
78 */
79static void
80do_timeout (void *cls)
81{
82 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
83 "Test timeout.\n");
84 die_task = NULL;
85 GNUNET_SCHEDULER_shutdown ();
86}
87
88
89static void
90handle_test (void *cls,
91 const struct GNUNET_MessageHeader *message)
92{
93 GNUNET_SCHEDULER_shutdown ();
94 ret = 0;
95}
96
97
98static void
99init (void *cls,
100 const struct GNUNET_PeerIdentity *my_identity)
101{
102 if (NULL == my_identity)
103 {
104 GNUNET_break (0);
105 return;
106 }
107 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
108 "Correctly connected to CORE; we are the peer %s.\n",
109 GNUNET_i2s (my_identity));
110 GNUNET_memcpy (&myself,
111 my_identity,
112 sizeof(struct GNUNET_PeerIdentity));
113}
114
115
116static void *
117connect_cb (void *cls,
118 const struct GNUNET_PeerIdentity *peer,
119 struct GNUNET_MQ_Handle *mq)
120{
121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
122 "Connected to peer %s.\n",
123 GNUNET_i2s (peer));
124 if (0 == memcmp (peer,
125 &myself,
126 sizeof(struct GNUNET_PeerIdentity)))
127 {
128 struct GNUNET_MQ_Envelope *env;
129 struct GNUNET_MessageHeader *msg;
130
131 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
132 "Connected to myself; sending message!\n");
133 env = GNUNET_MQ_msg (msg,
134 GNUNET_MESSAGE_TYPE_DUMMY);
135 GNUNET_MQ_send (mq,
136 env);
137 }
138 return NULL;
139}
140
141
142/**
143 * Main function that will be run by the scheduler.
144 *
145 * @param cls closure
146 * @param cfg configuration
147 */
148static void
149run (void *cls,
150 const struct GNUNET_CONFIGURATION_Handle *cfg,
151 struct GNUNET_TESTING_Peer *peer)
152{
153 struct GNUNET_MQ_MessageHandler handlers[] = {
154 GNUNET_MQ_hd_fixed_size (test,
155 GNUNET_MESSAGE_TYPE_DUMMY,
156 struct GNUNET_MessageHeader,
157 NULL),
158 GNUNET_MQ_handler_end ()
159 };
160
161 core =
162 GNUNET_CORE_connect (cfg,
163 NULL,
164 &init,
165 &connect_cb,
166 NULL,
167 handlers);
168 GNUNET_SCHEDULER_add_shutdown (&cleanup,
169 NULL);
170 die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
171 &do_timeout,
172 NULL);
173}
174
175
176/**
177 * The main function to test sending a message to the local peer via core
178 *
179 * @param argc number of arguments from the command line
180 * @param argv command line arguments
181 * @return 0 ok, 1 on error
182 */
183int
184main (int argc, char *argv[])
185{
186 ret = 1;
187 if (0 != GNUNET_TESTING_peer_run ("test-core-api-send-to-self",
188 "test_core_api_peer1.conf",
189 &run, NULL))
190 return 1;
191 return ret;
192}
193
194
195/* end of test_core_api_send_to_self.c */
diff --git a/src/core/test_core_api_send_to_self.conf b/src/core/test_core_api_send_to_self.conf
deleted file mode 100644
index c2a459bb9..000000000
--- a/src/core/test_core_api_send_to_self.conf
+++ /dev/null
@@ -1,19 +0,0 @@
1@INLINE@ test_core_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = ~/.gnunet/
4
5[ats]
6WAN_QUOTA_IN = 104857600
7WAN_QUOTA_OUT = 104757600
8
9[test-sts]
10IMMEDIATE_START = YES
11PORT = 59252
12HOSTNAME = localhost
13BINARY = test_core_api_send_to_self
14ACCEPT_FROM = 127.0.0.1;
15ACCEPT_FROM6 = ::1;
16TOTAL_QUOTA_IN = 65536
17TOTAL_QUOTA_OUT = 65536
18UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-sts.sock
19
diff --git a/src/core/test_core_api_start_only.c b/src/core/test_core_api_start_only.c
deleted file mode 100644
index 007131134..000000000
--- a/src/core/test_core_api_start_only.c
+++ /dev/null
@@ -1,250 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 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 * @file transport/test_core_api_start_only.c
22 * @brief testcase for core_api.c that only starts two peers,
23 * connects to the core service and shuts down again
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_arm_service.h"
28#include "gnunet_core_service.h"
29#include "gnunet_util_lib.h"
30
31#define TIMEOUT 5
32
33#define MTYPE 12345
34
35struct PeerContext
36{
37 struct GNUNET_CONFIGURATION_Handle *cfg;
38 struct GNUNET_CORE_Handle *ch;
39 struct GNUNET_PeerIdentity id;
40 struct GNUNET_OS_Process *arm_proc;
41};
42
43static struct PeerContext p1;
44
45static struct PeerContext p2;
46
47static struct GNUNET_SCHEDULER_Task *timeout_task_id;
48
49static int ok;
50
51
52static void *
53connect_notify (void *cls,
54 const struct GNUNET_PeerIdentity *peer,
55 struct GNUNET_MQ_Handle *mq)
56{
57 return NULL;
58}
59
60
61static void
62disconnect_notify (void *cls,
63 const struct GNUNET_PeerIdentity *peer,
64 void *internal_cls)
65{
66}
67
68
69static struct GNUNET_MQ_MessageHandler handlers[] = {
70 GNUNET_MQ_handler_end ()
71};
72
73
74static void
75shutdown_task (void *cls)
76{
77 GNUNET_CORE_disconnect (p1.ch);
78 p1.ch = NULL;
79 GNUNET_CORE_disconnect (p2.ch);
80 p2.ch = NULL;
81 ok = 0;
82}
83
84
85static void
86init_notify (void *cls,
87 const struct GNUNET_PeerIdentity *my_identity)
88{
89 struct PeerContext *p = cls;
90
91 if (p == &p1)
92 {
93 /* connect p2 */
94 p2.ch = GNUNET_CORE_connect (p2.cfg,
95 &p2,
96 &init_notify,
97 &connect_notify,
98 &disconnect_notify,
99 handlers);
100 }
101 else
102 {
103 GNUNET_assert (p == &p2);
104 GNUNET_SCHEDULER_cancel (timeout_task_id);
105 timeout_task_id = NULL;
106 GNUNET_SCHEDULER_add_now (&shutdown_task,
107 NULL);
108 }
109}
110
111
112static void
113setup_peer (struct PeerContext *p,
114 const char *cfgname)
115{
116 char *binary;
117
118 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
119 p->cfg = GNUNET_CONFIGURATION_create ();
120 p->arm_proc =
121 GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
122 | GNUNET_OS_USE_PIPE_CONTROL,
123 NULL, NULL, NULL,
124 binary,
125 "gnunet-service-arm",
126 "-c", cfgname,
127 NULL);
128 GNUNET_assert (GNUNET_OK ==
129 GNUNET_CONFIGURATION_load (p->cfg,
130 cfgname));
131 GNUNET_free (binary);
132}
133
134
135static void
136timeout_task (void *cls)
137{
138 fprintf (stderr,
139 "%s",
140 "Timeout.\n");
141 if (NULL != p1.ch)
142 {
143 GNUNET_CORE_disconnect (p1.ch);
144 p1.ch = NULL;
145 }
146 if (NULL != p2.ch)
147 {
148 GNUNET_CORE_disconnect (p2.ch);
149 p2.ch = NULL;
150 }
151 ok = 42;
152}
153
154
155static void
156run (void *cls,
157 char *const *args,
158 const char *cfgfile,
159 const struct GNUNET_CONFIGURATION_Handle *cfg)
160{
161 GNUNET_assert (ok == 1);
162 ok++;
163 setup_peer (&p1, "test_core_api_peer1.conf");
164 setup_peer (&p2, "test_core_api_peer2.conf");
165 timeout_task_id =
166 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
167 (GNUNET_TIME_UNIT_MINUTES,
168 TIMEOUT),
169 &timeout_task,
170 NULL);
171 p1.ch = GNUNET_CORE_connect (p1.cfg,
172 &p1,
173 &init_notify,
174 &connect_notify,
175 &disconnect_notify,
176 handlers);
177}
178
179
180static void
181stop_arm (struct PeerContext *p)
182{
183 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
184 "Stopping peer\n");
185 if (0 != GNUNET_OS_process_kill (p->arm_proc,
186 GNUNET_TERM_SIG))
187 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
188 "kill");
189 if (GNUNET_OK !=
190 GNUNET_OS_process_wait (p->arm_proc))
191 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
192 "waitpid");
193 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
194 "ARM process %u stopped\n",
195 (unsigned int) GNUNET_OS_process_get_pid (p->arm_proc));
196 GNUNET_OS_process_destroy (p->arm_proc);
197 p->arm_proc = NULL;
198 GNUNET_CONFIGURATION_destroy (p->cfg);
199}
200
201
202static int
203check ()
204{
205 char *const argv[] = {
206 "test-core-api-start-only",
207 "-c",
208 "test_core_api_data.conf",
209 NULL
210 };
211 struct GNUNET_GETOPT_CommandLineOption options[] = {
212 GNUNET_GETOPT_OPTION_END
213 };
214
215 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-1");
216 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-2");
217
218 ok = 1;
219 GNUNET_PROGRAM_run ((sizeof(argv) / sizeof(char *)) - 1,
220 argv,
221 "test-core-api-start-only",
222 "nohelp",
223 options,
224 &run,
225 &ok);
226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
227 "Test finished\n");
228 stop_arm (&p1);
229 stop_arm (&p2);
230 return ok;
231}
232
233
234int
235main (int argc,
236 char *argv[])
237{
238 int ret;
239
240 GNUNET_log_setup ("test-core-api-start-only",
241 "WARNING",
242 NULL);
243 ret = check ();
244 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-1");
245 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-peer-2");
246 return ret;
247}
248
249
250/* end of test_core_api_start_only.c */
diff --git a/src/core/test_core_defaults.conf b/src/core/test_core_defaults.conf
deleted file mode 100644
index 7c7dad99e..000000000
--- a/src/core/test_core_defaults.conf
+++ /dev/null
@@ -1,22 +0,0 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2@INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf
3
4[PATHS]
5GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-core/
6
7[nat]
8ENABLE_UPNP = NO
9
10[ats]
11WAN_QUOTA_IN = 1 GB
12WAN_QUOTA_OUT = 1 GB
13
14[transport-tcp]
15BINDTO = 127.0.0.1
16
17[transport-udp]
18BROADCAST = NO
19
20[peerinfo]
21NO_IO = YES
22
diff --git a/src/core/test_core_quota_asymmetric_recv_limited_peer1.conf b/src/core/test_core_quota_asymmetric_recv_limited_peer1.conf
deleted file mode 100644
index 766a2e73b..000000000
--- a/src/core/test_core_quota_asymmetric_recv_limited_peer1.conf
+++ /dev/null
@@ -1,54 +0,0 @@
1@INLINE@ test_core_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-core-quota-asym-recv-lim-peer-1/
4
5[transport-tcp]
6PORT = 12488
7
8[arm]
9PORT = 12486
10UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-arm.sock
11
12[statistics]
13PORT = 12487
14UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-statistics.sock
15
16[resolver]
17PORT = 12484
18UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-1-service-resolver.sock
19
20[peerinfo]
21PORT = 12489
22UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-peerinfo.sock
23
24[transport]
25PORT = 12485
26UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-transport.sock
27
28[transport-udp]
29PORT = 12489
30
31[ats]
32PORT = 12491
33UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-ats.sock
34# UNSPECIFIED
35UNSPECIFIED_QUOTA_IN = 100 MiB
36UNSPECIFIED_QUOTA_OUT = 100 MiB
37# LOOPBACK
38LOOPBACK_QUOTA_IN = 100 MiB
39LOOPBACK_QUOTA_OUT = 100 MiB
40# LAN
41LAN_QUOTA_IN = 100 MiB
42LAN_QUOTA_OUT = 100 MiB
43# WAN
44WAN_QUOTA_IN = 100 MiB
45WAN_QUOTA_OUT = 100 MiB
46# WLAN
47WLAN_QUOTA_IN = 100 MiB
48WLAN_QUOTA_OUT = 100 MiB
49
50
51[core]
52PORT = 12490
53UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p1-service-core.sock
54
diff --git a/src/core/test_core_quota_asymmetric_recv_limited_peer2.conf b/src/core/test_core_quota_asymmetric_recv_limited_peer2.conf
deleted file mode 100644
index 30c0bb81f..000000000
--- a/src/core/test_core_quota_asymmetric_recv_limited_peer2.conf
+++ /dev/null
@@ -1,57 +0,0 @@
1@INLINE@ test_core_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-core-quota-asym-recv-lim-peer-2/
4
5
6[arm]
7PORT = 22486
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-arm.sock
9
10[statistics]
11PORT = 22487
12UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-statistics.sock
13
14[resolver]
15PORT = 22484
16UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-resolver.sock
17
18[peerinfo]
19PORT = 22489
20UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-peerinfo.sock
21
22[transport]
23PORT = 22485
24UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-transport.sock
25
26[core]
27PORT = 22490
28UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-core.sock
29
30[ats]
31PORT = 22491
32UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-recv-p2-service-ats.sock
33# UNSPECIFIED
34UNSPECIFIED_QUOTA_IN = 10 MiB
35UNSPECIFIED_QUOTA_OUT = 10 MiB
36# LOOPBACK
37LOOPBACK_QUOTA_IN = 10 MiB
38LOOPBACK_QUOTA_OUT = 10 MiB
39# LAN
40LAN_QUOTA_IN = 10 MiB
41LAN_QUOTA_OUT = 10 MiB
42# WAN
43WAN_QUOTA_IN = 10 MiB
44WAN_QUOTA_OUT = 10 MiB
45# WLAN
46WLAN_QUOTA_IN = 10 MiB
47WLAN_QUOTA_OUT = 10 MiB
48
49[transport-tcp]
50PORT = 22467
51
52[transport-http]
53PORT = 22469
54
55[transport-tcp]
56PORT = 22468
57
diff --git a/src/core/test_core_quota_asymmetric_send_limit_peer1.conf b/src/core/test_core_quota_asymmetric_send_limit_peer1.conf
deleted file mode 100644
index 4a9f483d6..000000000
--- a/src/core/test_core_quota_asymmetric_send_limit_peer1.conf
+++ /dev/null
@@ -1,52 +0,0 @@
1@INLINE@ test_core_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-core-quota-asym-send-lim-peer-1/
4
5[transport-tcp]
6PORT = 12488
7
8[transport-udp]
9PORT = 12492
10
11[arm]
12PORT = 12486
13UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-arm.sock
14
15[statistics]
16PORT = 12487
17UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-statistics.sock
18
19[resolver]
20PORT = 12484
21UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-1-service-resolver.sock
22
23[peerinfo]
24PORT = 12489
25UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-peerinfo.sock
26
27[transport]
28PORT = 12485
29UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-transport.sock
30
31[ats]
32PORT = 12491
33UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-ats.sock
34# UNSPECIFIED
35UNSPECIFIED_QUOTA_IN = 10 MiB
36UNSPECIFIED_QUOTA_OUT = 10 MiB
37# LOOPBACK
38LOOPBACK_QUOTA_IN = 10 MiB
39LOOPBACK_QUOTA_OUT = 10 MiB
40# LAN
41LAN_QUOTA_IN = 10 MiB
42LAN_QUOTA_OUT = 10 MiB
43# WAN
44WAN_QUOTA_IN = 10 MiB
45WAN_QUOTA_OUT = 10 MiB
46# WLAN
47WLAN_QUOTA_IN = 10 MiB
48WLAN_QUOTA_OUT = 10 MiB
49
50[core]
51PORT = 12490
52UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p1-service-core.sock
diff --git a/src/core/test_core_quota_asymmetric_send_limit_peer2.conf b/src/core/test_core_quota_asymmetric_send_limit_peer2.conf
deleted file mode 100644
index 36434461c..000000000
--- a/src/core/test_core_quota_asymmetric_send_limit_peer2.conf
+++ /dev/null
@@ -1,61 +0,0 @@
1@INLINE@ test_core_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-core-quota-asym-send-lim-peer-2/
4
5[arm]
6PORT = 22486
7UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-arm.sock
8
9[statistics]
10PORT = 22487
11UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-statistics.sock
12
13[resolver]
14PORT = 22484
15UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-resolver.sock
16
17[peerinfo]
18PORT = 22489
19UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-peerinfo.sock
20
21[transport]
22PORT = 22485
23UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-transport.sock
24
25[core]
26PORT = 22490
27UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-core.sock
28
29[ats]
30PORT = 22491
31UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-asym-send-p2-service-ats.sock
32WAN_QUOTA_IN = 100 MiB
33WAN_QUOTA_OUT = 100 MiB
34
35[ats]
36PORT = 12471
37UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-core-sym-p1-service-ats.sock
38# UNSPECIFIED
39UNSPECIFIED_QUOTA_IN = 100 MiB
40UNSPECIFIED_QUOTA_OUT = 100 MiB
41# LOOPBACK
42LOOPBACK_QUOTA_IN = 100 MiB
43LOOPBACK_QUOTA_OUT = 100 MiB
44# LAN
45LAN_QUOTA_IN = 100 MiB
46LAN_QUOTA_OUT = 100 MiB
47# WAN
48WAN_QUOTA_IN = 100 MiB
49WAN_QUOTA_OUT = 100 MiB
50# WLAN
51WLAN_QUOTA_IN = 100 MiB
52WLAN_QUOTA_OUT = 100 MiB
53
54[transport-tcp]
55PORT = 22467
56
57[transport-udp]
58PORT = 22468
59
60[transport-http]
61PORT = 22469
diff --git a/src/core/test_core_quota_compliance.c b/src/core/test_core_quota_compliance.c
deleted file mode 100644
index cf2da3d97..000000000
--- a/src/core/test_core_quota_compliance.c
+++ /dev/null
@@ -1,779 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009, 2010, 2015, 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 * @file core/test_core_quota_compliance.c
22 * @brief testcase for core_api.c focusing quota compliance on core level
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_arm_service.h"
27#include "gnunet_core_service.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_ats_service.h"
30#include "gnunet_transport_service.h"
31#include "gnunet_transport_hello_service.h"
32#include "gnunet_statistics_service.h"
33
34
35#define SYMMETRIC 0
36#define ASYMMETRIC_SEND_LIMITED 1
37#define ASYMMETRIC_RECV_LIMITED 2
38
39/**
40 * Note that this value must not significantly exceed
41 * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise
42 * messages may be dropped even for a reliable transport.
43 */
44#define TOTAL_MSGS (60000 * 10)
45
46/**
47 * How long until we give up on transmitting the message?
48 */
49#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
50
51/**
52 * What delay do we request from the core service for transmission?
53 */
54#define FAST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, \
55 150)
56
57#define MTYPE 12345
58#define MESSAGESIZE (1024 - 8)
59#define MEASUREMENT_LENGTH GNUNET_TIME_relative_multiply ( \
60 GNUNET_TIME_UNIT_SECONDS, 30)
61
62static unsigned long long total_bytes_sent;
63static unsigned long long total_bytes_recv;
64
65static struct GNUNET_TIME_Absolute start_time;
66
67static struct GNUNET_SCHEDULER_Task *err_task;
68
69static struct GNUNET_SCHEDULER_Task *measure_task;
70
71
72struct PeerContext
73{
74 struct GNUNET_CONFIGURATION_Handle *cfg;
75 struct GNUNET_CORE_Handle *ch;
76 struct GNUNET_MQ_Handle *mq;
77 struct GNUNET_TRANSPORT_OfferHelloHandle *oh;
78 struct GNUNET_PeerIdentity id;
79 struct GNUNET_MessageHeader *hello;
80 struct GNUNET_STATISTICS_Handle *stats;
81 struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
82 struct GNUNET_ATS_ConnectivityHandle *ats;
83 struct GNUNET_ATS_ConnectivitySuggestHandle *ats_sh;
84 int connect_status;
85 struct GNUNET_OS_Process *arm_proc;
86};
87
88static struct PeerContext p1;
89static struct PeerContext p2;
90
91static unsigned long long current_quota_p1_in;
92static unsigned long long current_quota_p1_out;
93static unsigned long long current_quota_p2_in;
94static unsigned long long current_quota_p2_out;
95
96static int ok;
97static int test;
98static int32_t tr_n;
99
100static int running;
101
102
103#if VERBOSE
104#define OKPP do { ok++; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, \
105 "Now at stage %u at %s:%u\n", ok, __FILE__, \
106 __LINE__); } while (0)
107#else
108#define OKPP do { ok++; } while (0)
109#endif
110
111struct TestMessage
112{
113 struct GNUNET_MessageHeader header;
114 uint32_t num GNUNET_PACKED;
115 uint8_t pad[MESSAGESIZE];
116};
117
118
119static void
120terminate_peer (struct PeerContext *p)
121{
122 if (NULL != p->ch)
123 {
124 GNUNET_CORE_disconnect (p->ch);
125 p->ch = NULL;
126 }
127 if (NULL != p->ghh)
128 {
129 GNUNET_TRANSPORT_hello_get_cancel (p->ghh);
130 p->ghh = NULL;
131 }
132 if (NULL != p->oh)
133 {
134 GNUNET_TRANSPORT_offer_hello_cancel (p->oh);
135 p->oh = NULL;
136 }
137 if (NULL != p->ats_sh)
138 {
139 GNUNET_ATS_connectivity_suggest_cancel (p->ats_sh);
140 p->ats_sh = NULL;
141 }
142 if (NULL != p->ats)
143 {
144 GNUNET_ATS_connectivity_done (p->ats);
145 p->ats = NULL;
146 }
147 if (NULL != p->stats)
148 {
149 GNUNET_STATISTICS_destroy (p->stats, GNUNET_NO);
150 p->stats = NULL;
151 }
152 if (NULL != p->hello)
153 {
154 GNUNET_free (p->hello);
155 p->hello = NULL;
156 }
157}
158
159
160static void
161shutdown_task (void *cls)
162{
163 if (NULL != err_task)
164 {
165 GNUNET_SCHEDULER_cancel (err_task);
166 err_task = NULL;
167 }
168 if (NULL != measure_task)
169 {
170 GNUNET_SCHEDULER_cancel (measure_task);
171 measure_task = NULL;
172 }
173 terminate_peer (&p1);
174 terminate_peer (&p2);
175}
176
177
178static void
179terminate_task_error (void *cls)
180{
181 err_task = NULL;
182 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
183 "Testcase failed (timeout)!\n");
184 GNUNET_SCHEDULER_shutdown ();
185 ok = 42;
186}
187
188
189/**
190 * Callback function to process statistic values.
191 *
192 * @param cls closure
193 * @param subsystem name of subsystem that created the statistic
194 * @param name the name of the datum
195 * @param value the current value
196 * @param is_persistent #GNUNET_YES if the value is persistent, #GNUNET_NO if not
197 * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
198 */
199static int
200print_stat (void *cls,
201 const char *subsystem,
202 const char *name,
203 uint64_t value,
204 int is_persistent)
205{
206 if (cls == &p1)
207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
208 "Peer1 %50s = %12llu\n",
209 name,
210 (unsigned long long) value);
211 if (cls == &p2)
212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
213 "Peer2 %50s = %12llu\n",
214 name,
215 (unsigned long long) value);
216 return GNUNET_OK;
217}
218
219
220static void
221measurement_stop (void *cls)
222{
223 unsigned long long delta;
224 unsigned long long throughput_out;
225 unsigned long long throughput_in;
226 unsigned long long max_quota_in;
227 unsigned long long max_quota_out;
228 unsigned long long quota_delta;
229 enum GNUNET_ErrorType kind = GNUNET_ERROR_TYPE_DEBUG;
230
231 measure_task = NULL;
232 fprintf (stdout, "%s", "\n");
233 running = GNUNET_NO;
234
235 delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us;
236 if (0 == delta)
237 delta = 1;
238 throughput_out = total_bytes_sent * 1000000LL / delta; /* convert to bytes/s */
239 throughput_in = total_bytes_recv * 1000000LL / delta; /* convert to bytes/s */
240
241 max_quota_in = GNUNET_MIN (current_quota_p1_in, current_quota_p2_in);
242 max_quota_out = GNUNET_MIN (current_quota_p1_out, current_quota_p2_out);
243 if (max_quota_out < max_quota_in)
244 quota_delta = max_quota_in / 3;
245 else
246 quota_delta = max_quota_out / 3;
247
248 if ((throughput_out > (max_quota_out + quota_delta)) ||
249 (throughput_in > (max_quota_in + quota_delta)))
250 ok = 1; /* fail */
251 else
252 ok = 0; /* pass */
253 GNUNET_STATISTICS_get (p1.stats,
254 "core",
255 "# discarded CORE_SEND requests",
256 NULL,
257 &print_stat,
258 &p1);
259 GNUNET_STATISTICS_get (p1.stats,
260 "core",
261 "# discarded CORE_SEND request bytes",
262 NULL,
263 &print_stat,
264 &p1);
265 GNUNET_STATISTICS_get (p1.stats,
266 "core",
267 "# discarded lower priority CORE_SEND requests",
268 NULL,
269 &print_stat,
270 NULL);
271 GNUNET_STATISTICS_get (p1.stats,
272 "core",
273 "# discarded lower priority CORE_SEND request bytes",
274 NULL,
275 &print_stat,
276 &p1);
277 GNUNET_STATISTICS_get (p2.stats,
278 "core",
279 "# discarded CORE_SEND requests",
280 NULL,
281 &print_stat,
282 &p2);
283
284 GNUNET_STATISTICS_get (p2.stats,
285 "core",
286 "# discarded CORE_SEND request bytes",
287 NULL,
288 &print_stat,
289 &p2);
290 GNUNET_STATISTICS_get (p2.stats,
291 "core",
292 "# discarded lower priority CORE_SEND requests",
293 NULL,
294 &print_stat,
295 &p2);
296 GNUNET_STATISTICS_get (p2.stats,
297 "core",
298 "# discarded lower priority CORE_SEND request bytes",
299 NULL,
300 &print_stat,
301 &p2);
302
303 if (ok != 0)
304 kind = GNUNET_ERROR_TYPE_ERROR;
305 switch (test)
306 {
307 case SYMMETRIC:
308 GNUNET_log (kind,
309 "Core quota compliance test with symmetric quotas: %s\n",
310 (0 == ok) ? "PASSED" : "FAILED");
311 break;
312
313 case ASYMMETRIC_SEND_LIMITED:
314 GNUNET_log (kind,
315 "Core quota compliance test with limited sender quota: %s\n",
316 (0 == ok) ? "PASSED" : "FAILED");
317 break;
318
319 case ASYMMETRIC_RECV_LIMITED:
320 GNUNET_log (kind,
321 "Core quota compliance test with limited receiver quota: %s\n",
322 (0 == ok) ? "PASSED" : "FAILED");
323 break;
324 }
325 ;
326 GNUNET_log (kind,
327 "Peer 1 send rate: %llu b/s (%llu bytes in %llu ms)\n",
328 throughput_out,
329 total_bytes_sent,
330 delta);
331 GNUNET_log (kind,
332 "Peer 1 send quota: %llu b/s\n",
333 current_quota_p1_out);
334 GNUNET_log (kind,
335 "Peer 2 receive rate: %llu b/s (%llu bytes in %llu ms)\n",
336 throughput_in,
337 total_bytes_recv,
338 delta);
339 GNUNET_log (kind,
340 "Peer 2 receive quota: %llu b/s\n",
341 current_quota_p2_in);
342/*
343 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Max. inbound quota allowed: %llu b/s\n",max_quota_in );
344 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Max. outbound quota allowed: %llu b/s\n",max_quota_out);
345 */
346 GNUNET_SCHEDULER_shutdown ();
347}
348
349
350static void
351do_transmit (void *cls)
352{
353 struct TestMessage *hdr;
354 struct GNUNET_MQ_Envelope *env;
355
356 env = GNUNET_MQ_msg (hdr,
357 MTYPE);
358 hdr->num = htonl (tr_n);
359 memset (&hdr->pad,
360 tr_n,
361 MESSAGESIZE);
362 tr_n++;
363 GNUNET_SCHEDULER_cancel (err_task);
364 err_task =
365 GNUNET_SCHEDULER_add_delayed (TIMEOUT,
366 &terminate_task_error,
367 NULL);
368 total_bytes_sent += sizeof(struct TestMessage);
369 GNUNET_MQ_send (p1.mq,
370 env);
371}
372
373
374static void *
375connect_notify (void *cls,
376 const struct GNUNET_PeerIdentity *peer,
377 struct GNUNET_MQ_Handle *mq)
378{
379 struct PeerContext *pc = cls;
380
381 if (0 == memcmp (&pc->id,
382 peer,
383 sizeof(struct GNUNET_PeerIdentity)))
384 return NULL; /* loopback */
385 GNUNET_assert (0 == pc->connect_status);
386 pc->connect_status = 1;
387 pc->mq = mq;
388 if (pc == &p1)
389 {
390 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
391 "Encrypted connection established to peer `%s'\n",
392 GNUNET_i2s (peer));
393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
394 "Asking core (1) for transmission to peer `%s'\n",
395 GNUNET_i2s (&p2.id));
396 GNUNET_SCHEDULER_cancel (err_task);
397 err_task =
398 GNUNET_SCHEDULER_add_delayed (TIMEOUT,
399 &terminate_task_error,
400 NULL);
401 start_time = GNUNET_TIME_absolute_get ();
402 running = GNUNET_YES;
403 measure_task =
404 GNUNET_SCHEDULER_add_delayed (MEASUREMENT_LENGTH,
405 &measurement_stop,
406 NULL);
407 do_transmit (NULL);
408 }
409 return pc;
410}
411
412
413static void
414disconnect_notify (void *cls,
415 const struct GNUNET_PeerIdentity *peer,
416 void *internal_cls)
417{
418 struct PeerContext *pc = cls;
419
420 if (NULL == internal_cls)
421 return; /* loopback */
422 pc->connect_status = 0;
423 pc->mq = NULL;
424 if (NULL != measure_task)
425 {
426 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
427 "Measurement aborted due to disconnect!\n");
428 GNUNET_SCHEDULER_cancel (measure_task);
429 measure_task = NULL;
430 }
431 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
432 "Encrypted connection to `%s' cut\n",
433 GNUNET_i2s (peer));
434}
435
436
437static void
438handle_test (void *cls,
439 const struct TestMessage *hdr)
440{
441 static int n;
442
443 total_bytes_recv += sizeof(struct TestMessage);
444 if (ntohl (hdr->num) != n)
445 {
446 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
447 "Expected message %u, got message %u\n",
448 n,
449 ntohl (hdr->num));
450 GNUNET_SCHEDULER_cancel (err_task);
451 err_task = GNUNET_SCHEDULER_add_now (&terminate_task_error,
452 NULL);
453 return;
454 }
455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
456 "Got message %u\n",
457 ntohl (hdr->num));
458 n++;
459 if (0 == (n % 10))
460 fprintf (stderr, "%s", ".");
461
462 if (GNUNET_YES == running)
463 do_transmit (NULL);
464}
465
466
467static void
468init_notify (void *cls,
469 const struct GNUNET_PeerIdentity *my_identity)
470{
471 struct PeerContext *p = cls;
472 struct GNUNET_MQ_MessageHandler handlers[] = {
473 GNUNET_MQ_hd_fixed_size (test,
474 MTYPE,
475 struct TestMessage,
476 NULL),
477 GNUNET_MQ_handler_end ()
478 };
479
480 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
481 "Connection to CORE service of `%s' established\n",
482 GNUNET_i2s (my_identity));
483 GNUNET_assert (NULL != my_identity);
484 p->id = *my_identity;
485 if (cls == &p1)
486 {
487 GNUNET_assert (ok == 2);
488 OKPP;
489 /* connect p2 */
490 p2.ch = GNUNET_CORE_connect (p2.cfg,
491 &p2,
492 &init_notify,
493 &connect_notify,
494 &disconnect_notify,
495 handlers);
496 }
497 else
498 {
499 GNUNET_assert (ok == 3);
500 OKPP;
501 GNUNET_assert (cls == &p2);
502 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
503 "Asking core (1) to connect to peer `%s' and vice-versa\n",
504 GNUNET_i2s (&p2.id));
505 p1.ats_sh = GNUNET_ATS_connectivity_suggest (p1.ats,
506 &p2.id,
507 1);
508 p2.ats_sh = GNUNET_ATS_connectivity_suggest (p2.ats,
509 &p1.id,
510 1);
511 }
512}
513
514
515static void
516offer_hello_done (void *cls)
517{
518 struct PeerContext *p = cls;
519
520 p->oh = NULL;
521}
522
523
524static void
525process_hello (void *cls,
526 const struct GNUNET_MessageHeader *message)
527{
528 struct PeerContext *p = cls;
529
530 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
531 "Received (my) HELLO from transport service\n");
532 GNUNET_assert (message != NULL);
533 p->hello = GNUNET_malloc (ntohs (message->size));
534 GNUNET_memcpy (p->hello, message, ntohs (message->size));
535 if ((p == &p1) &&
536 (NULL == p2.oh))
537 p2.oh = GNUNET_TRANSPORT_offer_hello (p2.cfg,
538 message,
539 &offer_hello_done,
540 &p2);
541 if ((p == &p2) &&
542 (NULL == p1.oh))
543 p1.oh = GNUNET_TRANSPORT_offer_hello (p1.cfg, message,
544 &offer_hello_done,
545 &p1);
546
547 if ((p == &p1) &&
548 (NULL != p2.hello) &&
549 (NULL == p1.oh))
550 p1.oh = GNUNET_TRANSPORT_offer_hello (p1.cfg,
551 p2.hello,
552 &offer_hello_done,
553 &p1);
554 if ((p == &p2) &&
555 (NULL != p1.hello) &&
556 (NULL == p2.oh))
557 p2.oh = GNUNET_TRANSPORT_offer_hello (p2.cfg,
558 p1.hello,
559 &offer_hello_done,
560 &p2);
561}
562
563
564static void
565setup_peer (struct PeerContext *p,
566 const char *cfgname)
567{
568 char *binary;
569
570 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
571 p->cfg = GNUNET_CONFIGURATION_create ();
572 p->arm_proc =
573 GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
574 | GNUNET_OS_USE_PIPE_CONTROL,
575 NULL, NULL, NULL,
576 binary,
577 "gnunet-service-arm",
578 "-c",
579 cfgname,
580 NULL);
581 GNUNET_assert (GNUNET_OK ==
582 GNUNET_CONFIGURATION_load (p->cfg,
583 cfgname));
584 p->stats = GNUNET_STATISTICS_create ("core",
585 p->cfg);
586 GNUNET_assert (NULL != p->stats);
587 p->ats = GNUNET_ATS_connectivity_init (p->cfg);
588 GNUNET_assert (NULL != p->ats);
589 p->ghh = GNUNET_TRANSPORT_hello_get (p->cfg,
590 GNUNET_TRANSPORT_AC_ANY,
591 &process_hello,
592 p);
593 GNUNET_free (binary);
594}
595
596
597static void
598run (void *cls,
599 char *const *args,
600 const char *cfgfile,
601 const struct GNUNET_CONFIGURATION_Handle *cfg)
602{
603 struct GNUNET_MQ_MessageHandler handlers[] = {
604 GNUNET_MQ_hd_fixed_size (test,
605 MTYPE,
606 struct TestMessage,
607 NULL),
608 GNUNET_MQ_handler_end ()
609 };
610
611 GNUNET_assert (ok == 1);
612 OKPP;
613 err_task =
614 GNUNET_SCHEDULER_add_delayed (TIMEOUT,
615 &terminate_task_error,
616 NULL);
617 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
618 NULL);
619 if (test == SYMMETRIC)
620 {
621 setup_peer (&p1,
622 "test_core_quota_peer1.conf");
623 setup_peer (&p2,
624 "test_core_quota_peer2.conf");
625 }
626 else if (test == ASYMMETRIC_SEND_LIMITED)
627 {
628 setup_peer (&p1,
629 "test_core_quota_asymmetric_send_limit_peer1.conf");
630 setup_peer (&p2,
631 "test_core_quota_asymmetric_send_limit_peer2.conf");
632 }
633 else if (test == ASYMMETRIC_RECV_LIMITED)
634 {
635 setup_peer (&p1,
636 "test_core_quota_asymmetric_recv_limited_peer1.conf");
637 setup_peer (&p2,
638 "test_core_quota_asymmetric_recv_limited_peer2.conf");
639 }
640
641 GNUNET_assert (test != -1);
642 GNUNET_assert (GNUNET_SYSERR !=
643 GNUNET_CONFIGURATION_get_value_size (p1.cfg,
644 "ATS",
645 "WAN_QUOTA_IN",
646 &current_quota_p1_in));
647 GNUNET_assert (GNUNET_SYSERR !=
648 GNUNET_CONFIGURATION_get_value_size (p2.cfg,
649 "ATS",
650 "WAN_QUOTA_IN",
651 &current_quota_p2_in));
652 GNUNET_assert (GNUNET_SYSERR !=
653 GNUNET_CONFIGURATION_get_value_size (p1.cfg,
654 "ATS",
655 "WAN_QUOTA_OUT",
656 &current_quota_p1_out));
657 GNUNET_assert (GNUNET_SYSERR !=
658 GNUNET_CONFIGURATION_get_value_size (p2.cfg,
659 "ATS",
660 "WAN_QUOTA_OUT",
661 &current_quota_p2_out));
662
663 p1.ch = GNUNET_CORE_connect (p1.cfg,
664 &p1,
665 &init_notify,
666 &connect_notify,
667 &disconnect_notify,
668 handlers);
669}
670
671
672static void
673stop_arm (struct PeerContext *p)
674{
675 if (0 != GNUNET_OS_process_kill (p->arm_proc,
676 GNUNET_TERM_SIG))
677 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
678 "kill");
679 if (GNUNET_OK !=
680 GNUNET_OS_process_wait (p->arm_proc))
681 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
682 "waitpid");
683 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
684 "ARM process %u stopped\n",
685 GNUNET_OS_process_get_pid (p->arm_proc));
686 GNUNET_OS_process_destroy (p->arm_proc);
687 p->arm_proc = NULL;
688 GNUNET_CONFIGURATION_destroy (p->cfg);
689}
690
691
692static int
693check ()
694{
695 char *const argv[] = {
696 "test-core-quota-compliance",
697 "-c",
698 "test_core_api_data.conf",
699 NULL
700 };
701 struct GNUNET_GETOPT_CommandLineOption options[] = {
702 GNUNET_GETOPT_OPTION_END
703 };
704
705 ok = 1;
706 GNUNET_PROGRAM_run ((sizeof(argv) / sizeof(char *)) - 1,
707 argv,
708 "test-core-quota-compliance",
709 "nohelp",
710 options,
711 &run,
712 &ok);
713 stop_arm (&p1);
714 stop_arm (&p2);
715 return ok;
716}
717
718
719static void
720cleanup_directory (int test)
721{
722 switch (test)
723 {
724 case SYMMETRIC:
725 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-sym-peer-1/");
726 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-core-quota-sym-peer-2/");
727 break;
728
729 case ASYMMETRIC_SEND_LIMITED:
730 GNUNET_DISK_directory_remove
731 ("/tmp/test-gnunet-core-quota-asym-send-lim-peer-1/");
732 GNUNET_DISK_directory_remove
733 ("/tmp/test-gnunet-core-quota-asym-send-lim-peer-2/");
734 break;
735
736 case ASYMMETRIC_RECV_LIMITED:
737 GNUNET_DISK_directory_remove
738 ("/tmp/test-gnunet-core-quota-asym-recv-lim-peer-1/");
739 GNUNET_DISK_directory_remove
740 ("/tmp/test-gnunet-core-quota-asym-recv-lim-peer-2/");
741 break;
742 }
743}
744
745
746int
747main (int argc,
748 char *argv[])
749{
750 int ret;
751
752 test = -1;
753 if (NULL != strstr (argv[0],
754 "_symmetric"))
755 {
756 test = SYMMETRIC;
757 }
758 else if (NULL != strstr (argv[0],
759 "_asymmetric_send"))
760 {
761 test = ASYMMETRIC_SEND_LIMITED;
762 }
763 else if (NULL != strstr (argv[0],
764 "_asymmetric_recv"))
765 {
766 test = ASYMMETRIC_RECV_LIMITED;
767 }
768 GNUNET_assert (test != -1);
769 cleanup_directory (test);
770 GNUNET_log_setup ("test-core-quota-compliance",
771 "WARNING",
772 NULL);
773 ret = check ();
774 cleanup_directory (test);
775 return ret;
776}
777
778
779/* end of test_core_quota_compliance.c */
diff --git a/src/core/test_core_quota_peer1.conf b/src/core/test_core_quota_peer1.conf
deleted file mode 100644
index ec592f778..000000000
--- a/src/core/test_core_quota_peer1.conf
+++ /dev/null
@@ -1,58 +0,0 @@
1@INLINE@ test_core_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-core-peer-1/
4
5[arm]
6PORT = 12460
7UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-arm.sock
8
9[statistics]
10PORT = 12461
11
12[resolver]
13PORT = 12462
14UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-resolver.sock
15
16[peerinfo]
17PORT = 12463
18UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-peerinfo.sock
19
20[transport]
21PORT = 12464
22UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-transport.sock
23
24[core]
25PORT = 12475
26UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-core.sock
27
28[ats]
29PORT = 12476
30UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p1-service-ats.sock
31# UNSPECIFIED
32UNSPECIFIED_QUOTA_IN = 10 MiB
33UNSPECIFIED_QUOTA_OUT = 10 MiB
34# LOOPBACK
35LOOPBACK_QUOTA_IN = 10 MiB
36LOOPBACK_QUOTA_OUT = 10 MiB
37# LAN
38LAN_QUOTA_IN = 10 MiB
39LAN_QUOTA_OUT = 10 MiB
40# WAN
41WAN_QUOTA_IN = 10 MiB
42WAN_QUOTA_OUT = 10 MiB
43# WLAN
44WLAN_QUOTA_IN = 10 MiB
45WLAN_QUOTA_OUT = 10 MiB
46
47
48[transport-tcp]
49PORT = 12467
50
51[transport-udp]
52PORT = 12468
53
54[transport-unix]
55PORT = 12469
56
57[transport-http]
58PORT = 12470
diff --git a/src/core/test_core_quota_peer2.conf b/src/core/test_core_quota_peer2.conf
deleted file mode 100644
index 65d0710bb..000000000
--- a/src/core/test_core_quota_peer2.conf
+++ /dev/null
@@ -1,59 +0,0 @@
1@INLINE@ test_core_defaults.conf
2[PATHS]
3GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-core-peer-2/
4
5[arm]
6PORT = 22460
7UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-arm.sock
8
9[statistics]
10PORT = 22461
11UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-statistics.sock
12
13[resolver]
14PORT = 22462
15UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-resolver.sock
16
17[peerinfo]
18PORT = 22463
19UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-peerinfo.sock
20
21[transport]
22PORT = 22464
23UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-transport.sock
24
25[core]
26PORT = 22475
27UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-core.sock
28
29[ats]
30PORT = 22476
31UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-p2-service-ats.sock
32# UNSPECIFIED
33UNSPECIFIED_QUOTA_IN = 10 MiB
34UNSPECIFIED_QUOTA_OUT = 10 MiB
35# LOOPBACK
36LOOPBACK_QUOTA_IN = 10 MiB
37LOOPBACK_QUOTA_OUT = 10 MiB
38# LAN
39LAN_QUOTA_IN = 10 MiB
40LAN_QUOTA_OUT = 10 MiB
41# WAN
42WAN_QUOTA_IN = 10 MiB
43WAN_QUOTA_OUT = 10 MiB
44# WLAN
45WLAN_QUOTA_IN = 10 MiB
46WLAN_QUOTA_OUT = 10 MiB
47
48
49[transport-tcp]
50PORT = 22467
51
52[transport-udp]
53PORT = 22468
54
55[transport-unix]
56PORT = 22469
57
58[transport-http]
59PORT = 22470