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.am138
-rw-r--r--src/core/core.conf.in23
-rw-r--r--src/core/core.h326
-rw-r--r--src/core/core_api.c772
-rw-r--r--src/core/core_api_cmd_connecting_peers.c275
-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.c988
-rw-r--r--src/core/gnunet-service-core.h198
-rw-r--r--src/core/gnunet-service-core_kx.c1934
-rw-r--r--src/core/gnunet-service-core_kx.h102
-rw-r--r--src/core/gnunet-service-core_sessions.c1028
-rw-r--r--src/core/gnunet-service-core_sessions.h183
-rw-r--r--src/core/gnunet-service-core_typemap.c370
-rw-r--r--src/core/gnunet-service-core_typemap.h162
-rw-r--r--src/core/meson.build119
-rw-r--r--src/core/test_core_api.c348
-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.c537
-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.c258
-rw-r--r--src/core/test_core_defaults.conf22
-rw-r--r--src/core/test_core_plugin_cmd_just_run.c512
-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.c788
-rw-r--r--src/core/test_core_quota_peer1.conf58
-rw-r--r--src/core/test_core_quota_peer2.conf59
-rwxr-xr-xsrc/core/test_core_start_testcase.sh15
35 files changed, 0 insertions, 10162 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 b1d932ace..000000000
--- a/src/core/Makefile.am
+++ /dev/null
@@ -1,138 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4pkgcfgdir= $(pkgdatadir)/config.d/
5
6plugindir = $(libdir)/gnunet
7
8libexecdir= $(pkglibdir)/libexec/
9
10pkgcfg_DATA = \
11 core.conf
12
13if USE_COVERAGE
14 AM_CFLAGS = --coverage -O0
15 XLIB = -lgcov
16endif
17
18plugin_LTLIBRARIES = \
19 libgnunet_test_core_plugin_cmd_just_run.la
20
21TESTING_LIBS = \
22 libgnunetcoretesting.la
23
24lib_LTLIBRARIES = \
25 libgnunetcore.la \
26 $(TESTING_LIBS)
27
28libgnunetcore_la_SOURCES = \
29 core_api.c core.h \
30 core_api_monitor_peers.c
31libgnunetcore_la_LIBADD = \
32 $(top_builddir)/src/lib/util/libgnunetutil.la \
33 $(GN_LIBINTL) $(XLIB)
34libgnunetcore_la_LDFLAGS = \
35 $(GN_LIB_LDFLAGS) \
36 -version-info 0:1:0
37
38libgnunet_test_core_plugin_cmd_just_run_la_SOURCES = \
39 test_core_plugin_cmd_just_run.c
40libgnunet_test_core_plugin_cmd_just_run_la_LIBADD = \
41 libgnunetcoretesting.la \
42 $(top_builddir)/src/transport/libgnunettransportapplication.la \
43 $(top_builddir)/src/transport/libgnunettransportcore.la \
44 $(top_builddir)/src/lib/testing/libgnunettesting.la \
45 $(top_builddir)/src/peerstore/libgnunetpeerstore.la \
46 $(top_builddir)/src/statistics/libgnunetstatistics.la \
47 $(top_builddir)/src/lib/hello/libgnunethello.la \
48 $(top_builddir)/src/service/arm/libgnunetarm.la \
49 $(top_builddir)/src/lib/util/libgnunetutil.la \
50 $(LTLIBINTL)
51libgnunet_test_core_plugin_cmd_just_run_la_LDFLAGS = \
52 $(GN_PLUGIN_LDFLAGS)
53
54libgnunetcoretesting_la_SOURCES = \
55 core_api_cmd_connecting_peers.c
56libgnunetcoretesting_la_LIBADD = \
57 $(top_builddir)/src/lib/testing/libgnunettesting.la \
58 $(top_builddir)/src/service/arm/libgnunetarm.la \
59 $(top_builddir)/src/transport/libgnunettransportapplication.la \
60 $(top_builddir)/src/transport/libgnunettransportcore.la \
61 $(top_builddir)/src/lib/util/libgnunetutil.la
62libgnunetcoretesting_la_LDFLAGS = \
63 $(GN_LIBINTL) \
64 $(GN_LIB_LDFLAGS) \
65 -version-info 0:0:0
66
67
68libexec_PROGRAMS = \
69 gnunet-service-core
70
71bin_PROGRAMS = \
72 gnunet-core
73
74gnunet_service_core_SOURCES = \
75 gnunet-service-core.c gnunet-service-core.h \
76 gnunet-service-core_kx.c gnunet-service-core_kx.h \
77 gnunet-service-core_sessions.c gnunet-service-core_sessions.h \
78 gnunet-service-core_typemap.c gnunet-service-core_typemap.h
79gnunet_service_core_LDADD = \
80 $(top_builddir)/src/statistics/libgnunetstatistics.la \
81 $(top_builddir)/src/transport/libgnunettransportapplication.la \
82 $(top_builddir)/src/transport/libgnunettransportcore.la \
83 $(top_builddir)/src/lib/util/libgnunetutil.la \
84 $(GN_LIBINTL) $(Z_LIBS)
85
86
87gnunet_core_SOURCES = \
88 gnunet-core.c
89gnunet_core_LDADD = \
90 libgnunetcore.la \
91 $(top_builddir)/src/lib/util/libgnunetutil.la
92gnunet_core_LDFLAGS = \
93 $(GN_LIBINTL)
94
95TESTING_TESTS = \
96 test_core_api_send_to_self
97
98check_PROGRAMS = \
99 test_core_api_start_only \
100 $(TESTING_TESTS)
101
102# Only test TNG if we run experimental
103check_SCRIPTS= \
104 test_core_start_testcase.sh
105
106if ENABLE_TEST_RUN
107AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
108TESTS = $(check_PROGRAMS) \
109 $(check_SCRIPTS)
110endif
111
112test_core_api_send_to_self_SOURCES = \
113 test_core_api_send_to_self.c
114test_core_api_send_to_self_LDADD = \
115 libgnunetcore.la \
116 $(top_builddir)/src/lib/testing/libgnunettesting.la \
117 $(top_builddir)/src/lib/util/libgnunetutil.la
118
119test_core_api_start_only_SOURCES = \
120 test_core_api_start_only.c
121test_core_api_start_only_LDADD = \
122 $(top_builddir)/src/lib/testing/libgnunettesting.la \
123 libgnunetcore.la \
124 $(top_builddir)/src/lib/util/libgnunetutil.la
125
126EXTRA_DIST = \
127 test_core_start_testcase.sh \
128 test_core_defaults.conf \
129 test_core_api_data.conf \
130 test_core_api_peer1.conf \
131 test_core_api_peer2.conf \
132 test_core_api_send_to_self.conf \
133 test_core_quota_asymmetric_recv_limited_peer1.conf \
134 test_core_quota_asymmetric_recv_limited_peer2.conf \
135 test_core_quota_asymmetric_send_limit_peer1.conf \
136 test_core_quota_asymmetric_send_limit_peer2.conf \
137 test_core_quota_peer1.conf \
138 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 d4596f038..000000000
--- a/src/core/core.h
+++ /dev/null
@@ -1,326 +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_util_lib.h"
30#include "gnunet_time_lib.h"
31
32/**
33 * General core debugging.
34 */
35#define DEBUG_CORE GNUNET_EXTRA_LOGGING
36
37/**
38 * Definition of bits in the InitMessage's options field that specify
39 * which events this client cares about. Note that inbound messages
40 * for handlers that were specifically registered are always
41 * transmitted to the client.
42 */
43#define GNUNET_CORE_OPTION_NOTHING 0
44
45/**
46 * Client cares about connectivity changes.
47 */
48#define GNUNET_CORE_OPTION_SEND_STATUS_CHANGE 4
49
50/**
51 * Client wants all inbound messages in full.
52 */
53#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND 8
54
55/**
56 * Client just wants the 4-byte message headers of
57 * all inbound messages.
58 */
59#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND 16
60
61/**
62 * Client wants all outbound messages in full.
63 */
64#define GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND 32
65
66/**
67 * Client just wants the 4-byte message headers of
68 * all outbound messages.
69 */
70#define GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND 64
71
72
73GNUNET_NETWORK_STRUCT_BEGIN
74
75/**
76 * Message transmitted core clients to gnunet-service-core
77 * to start the interaction. This header is followed by
78 * uint16_t type values specifying which messages this
79 * client is interested in.
80 */
81struct InitMessage
82{
83 /**
84 * Header with type #GNUNET_MESSAGE_TYPE_CORE_INIT.
85 */
86 struct GNUNET_MessageHeader header;
87
88 /**
89 * Options, see GNUNET_CORE_OPTION_ values.
90 */
91 uint32_t options GNUNET_PACKED;
92};
93
94
95/**
96 * Message transmitted by the gnunet-service-core process
97 * to its clients in response to an INIT message.
98 */
99struct InitReplyMessage
100{
101 /**
102 * Header with type #GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY
103 */
104 struct GNUNET_MessageHeader header;
105
106 /**
107 * Always zero.
108 */
109 uint32_t reserved GNUNET_PACKED;
110
111 /**
112 * Public key of the local peer.
113 */
114 struct GNUNET_PeerIdentity my_identity;
115};
116
117
118/**
119 * Message sent by the service to clients to notify them
120 * about a peer connecting.
121 */
122struct ConnectNotifyMessage
123{
124 /**
125 * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT
126 */
127 struct GNUNET_MessageHeader header;
128
129 /**
130 * Always zero.
131 */
132 uint32_t reserved GNUNET_PACKED;
133
134 /**
135 * Identity of the connecting peer.
136 */
137 struct GNUNET_PeerIdentity peer;
138};
139
140
141/**
142 * Message sent by the service to clients to notify them
143 * about a peer disconnecting.
144 */
145struct DisconnectNotifyMessage
146{
147 /**
148 * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT.
149 */
150 struct GNUNET_MessageHeader header;
151
152 /**
153 * Always zero.
154 */
155 uint32_t reserved GNUNET_PACKED;
156
157 /**
158 * Identity of the connecting peer.
159 */
160 struct GNUNET_PeerIdentity peer;
161};
162
163
164/**
165 * Message sent by the service to clients to notify them about
166 * messages being received or transmitted. This overall message is
167 * followed by the real message, or just the header of the real
168 * message (depending on the client's preferences). The receiver can
169 * tell if it got the full message or only a partial message by
170 * looking at the size field in the header of NotifyTrafficMessage and
171 * checking it with the size field in the message that follows.
172 */
173struct NotifyTrafficMessage
174{
175 /**
176 * Header with type #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND
177 * or #GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND.
178 */
179 struct GNUNET_MessageHeader header;
180
181 /**
182 * Identity of the receiver or sender.
183 */
184 struct GNUNET_PeerIdentity peer;
185
186 /* Followed by payload (message or just header), variable size */
187};
188
189
190/**
191 * Client notifying core about the maximum-priority
192 * message it has in the queue for a particular target.
193 */
194struct SendMessageRequest
195{
196 /**
197 * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST
198 */
199 struct GNUNET_MessageHeader header;
200
201 /**
202 * How important is this message?
203 */
204 uint32_t priority GNUNET_PACKED;
205
206 /**
207 * By what time would the sender really like to see this
208 * message transmitted?
209 */
210 struct GNUNET_TIME_AbsoluteNBO deadline;
211
212 /**
213 * Identity of the intended target.
214 */
215 struct GNUNET_PeerIdentity peer;
216
217 /**
218 * Always zero.
219 */
220 uint32_t reserved GNUNET_PACKED;
221
222 /**
223 * How large is the message?
224 */
225 uint16_t size GNUNET_PACKED;
226
227 /**
228 * Counter for this peer to match SMRs to replies.
229 */
230 uint16_t smr_id GNUNET_PACKED;
231};
232
233
234/**
235 * Core notifying client that it is allowed to now
236 * transmit a message to the given target
237 * (response to #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST).
238 */
239struct SendMessageReady
240{
241 /**
242 * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND_READY
243 */
244 struct GNUNET_MessageHeader header;
245
246 /**
247 * How many bytes are allowed for transmission?
248 * Guaranteed to be at least as big as the requested size,
249 * or ZERO if the request is rejected (will timeout,
250 * peer disconnected, queue full, etc.).
251 */
252 uint16_t size GNUNET_PACKED;
253
254 /**
255 * smr_id from the request.
256 */
257 uint16_t smr_id GNUNET_PACKED;
258
259 /**
260 * Identity of the intended target.
261 */
262 struct GNUNET_PeerIdentity peer;
263};
264
265
266/**
267 * Client asking core to transmit a particular message to a particular
268 * target (response to #GNUNET_MESSAGE_TYPE_CORE_SEND_READY).
269 */
270struct SendMessage
271{
272 /**
273 * Header with type #GNUNET_MESSAGE_TYPE_CORE_SEND
274 */
275 struct GNUNET_MessageHeader header;
276
277 /**
278 * How important is this message? Contains a
279 * `enum GNUNET_MQ_PriorityPreferences` in NBO.
280 */
281 uint32_t priority GNUNET_PACKED;
282
283 /**
284 * By what time would the sender really like to see this
285 * message transmitted?
286 */
287 struct GNUNET_TIME_AbsoluteNBO deadline;
288
289 /**
290 * Identity of the intended receiver.
291 */
292 struct GNUNET_PeerIdentity peer;
293};
294
295
296/**
297 * Message sent by the service to monitor clients to notify them
298 * about a peer changing status.
299 */
300struct MonitorNotifyMessage
301{
302 /**
303 * Header with type #GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY
304 */
305 struct GNUNET_MessageHeader header;
306
307 /**
308 * New peer state, an `enum GNUNET_CORE_KxState` in NBO.
309 */
310 uint32_t state GNUNET_PACKED;
311
312 /**
313 * Identity of the peer.
314 */
315 struct GNUNET_PeerIdentity peer;
316
317 /**
318 * How long will we stay in this state (if nothing else happens)?
319 */
320 struct GNUNET_TIME_AbsoluteNBO timeout;
321};
322
323
324GNUNET_NETWORK_STRUCT_END
325#endif
326/* end of core.h */
diff --git a/src/core/core_api.c b/src/core/core_api.c
deleted file mode 100644
index 2e0bb1785..000000000
--- a/src/core/core_api.c
+++ /dev/null
@@ -1,772 +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 */
162static void
163reconnect_task (void *cls)
164{
165 struct GNUNET_CORE_Handle *h = cls;
166
167 h->reconnect_task = NULL;
168 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CORE service after delay\n");
169 reconnect (h);
170}
171
172
173/**
174 * Notify clients about disconnect and free the entry for connected
175 * peer.
176 *
177 * @param cls the `struct GNUNET_CORE_Handle *`
178 * @param key the peer identity (not used)
179 * @param value the `struct PeerRecord` to free.
180 * @return #GNUNET_YES (continue)
181 */
182static int
183disconnect_and_free_peer_entry (void *cls,
184 const struct GNUNET_PeerIdentity *key,
185 void *value)
186{
187 struct GNUNET_CORE_Handle *h = cls;
188 struct PeerRecord *pr = value;
189
190 GNUNET_assert (pr->h == h);
191 if (NULL != h->disconnects)
192 h->disconnects (h->cls, &pr->peer, pr->client_cls);
193 GNUNET_assert (GNUNET_YES ==
194 GNUNET_CONTAINER_multipeermap_remove (h->peers, key, pr));
195 GNUNET_MQ_destroy (pr->mq);
196 GNUNET_assert (NULL == pr->mq);
197 if (NULL != pr->env)
198 {
199 GNUNET_MQ_discard (pr->env);
200 pr->env = NULL;
201 }
202 GNUNET_free (pr);
203 return GNUNET_YES;
204}
205
206
207/**
208 * Close down any existing connection to the CORE service and
209 * try re-establishing it later.
210 *
211 * @param h our handle
212 */
213static void
214reconnect_later (struct GNUNET_CORE_Handle *h)
215{
216 GNUNET_assert (NULL == h->reconnect_task);
217 if (NULL != h->mq)
218 {
219 GNUNET_MQ_destroy (h->mq);
220 h->mq = NULL;
221 }
222 GNUNET_assert (NULL == h->reconnect_task);
223 h->reconnect_task =
224 GNUNET_SCHEDULER_add_delayed (h->retry_backoff, &reconnect_task, h);
225 GNUNET_CONTAINER_multipeermap_iterate (h->peers,
226 &disconnect_and_free_peer_entry,
227 h);
228 h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff);
229}
230
231
232/**
233 * Error handler for the message queue to the CORE service.
234 * On errors, we reconnect.
235 *
236 * @param cls closure, a `struct GNUNET_CORE_Handle *`
237 * @param error error code
238 */
239static void
240handle_mq_error (void *cls, enum GNUNET_MQ_Error error)
241{
242 struct GNUNET_CORE_Handle *h = cls;
243
244 LOG (GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %d\n", error);
245 reconnect_later (h);
246}
247
248
249/**
250 * Implement sending functionality of a message queue for
251 * us sending messages to a peer.
252 *
253 * @param mq the message queue
254 * @param msg the message to send
255 * @param impl_state state of the implementation
256 */
257static void
258core_mq_send_impl (struct GNUNET_MQ_Handle *mq,
259 const struct GNUNET_MessageHeader *msg,
260 void *impl_state)
261{
262 struct PeerRecord *pr = impl_state;
263 struct GNUNET_CORE_Handle *h = pr->h;
264 struct SendMessageRequest *smr;
265 struct SendMessage *sm;
266 struct GNUNET_MQ_Envelope *env;
267 uint16_t msize;
268 enum GNUNET_MQ_PriorityPreferences flags;
269
270 if (NULL == h->mq)
271 {
272 /* We're currently reconnecting, pretend this worked */
273 GNUNET_MQ_impl_send_continue (mq);
274 return;
275 }
276 GNUNET_assert (NULL == pr->env);
277 /* extract options from envelope */
278 env = GNUNET_MQ_get_current_envelope (mq);
279 flags = GNUNET_MQ_env_get_options (env);
280
281 /* check message size for sanity */
282 msize = ntohs (msg->size);
283 if (msize >= GNUNET_MAX_MESSAGE_SIZE - sizeof(struct SendMessage))
284 {
285 GNUNET_break (0);
286 GNUNET_MQ_impl_send_continue (mq);
287 return;
288 }
289
290 /* ask core for transmission */
291 LOG (GNUNET_ERROR_TYPE_DEBUG,
292 "Asking core for transmission of %u bytes to `%s'\n",
293 (unsigned int) msize,
294 GNUNET_i2s (&pr->peer));
295 env = GNUNET_MQ_msg (smr, GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST);
296 smr->priority = htonl ((uint32_t) flags);
297 smr->peer = pr->peer;
298 smr->size = htons (msize);
299 smr->smr_id = htons (++pr->smr_id_gen);
300 GNUNET_MQ_send (h->mq, env);
301
302 /* prepare message with actual transmission data */
303 pr->env = GNUNET_MQ_msg_nested_mh (sm, GNUNET_MESSAGE_TYPE_CORE_SEND, msg);
304 sm->priority = htonl ((uint32_t) flags);
305 sm->peer = pr->peer;
306 LOG (GNUNET_ERROR_TYPE_DEBUG,
307 "Calling get_message with buffer of %u bytes\n",
308 (unsigned int) msize);
309}
310
311
312/**
313 * Handle destruction of a message queue. Implementations must not
314 * free @a mq, but should take care of @a impl_state.
315 *
316 * @param mq the message queue to destroy
317 * @param impl_state state of the implementation
318 */
319static void
320core_mq_destroy_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
321{
322 struct PeerRecord *pr = impl_state;
323
324 GNUNET_assert (mq == pr->mq);
325 pr->mq = NULL;
326}
327
328
329/**
330 * Implementation function that cancels the currently sent message.
331 * Should basically undo whatever #mq_send_impl() did.
332 *
333 * @param mq message queue
334 * @param impl_state state specific to the implementation
335 */
336static void
337core_mq_cancel_impl (struct GNUNET_MQ_Handle *mq, void *impl_state)
338{
339 struct PeerRecord *pr = impl_state;
340
341 (void) mq;
342 GNUNET_assert (NULL != pr->env);
343 GNUNET_MQ_discard (pr->env);
344 pr->env = NULL;
345}
346
347
348/**
349 * We had an error processing a message we forwarded from a peer to
350 * the CORE service. We should just complain about it but otherwise
351 * continue processing.
352 *
353 * @param cls closure
354 * @param error error code
355 */
356static void
357core_mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
358{
359 /* struct PeerRecord *pr = cls; */
360 (void) cls;
361 (void) error;
362 GNUNET_break_op (0);
363}
364
365
366/**
367 * Add the given peer to the list of our connected peers
368 * and create the respective data structures and notify
369 * the application.
370 *
371 * @param h the core handle
372 * @param peer the peer that is connecting to us
373 */
374static void
375connect_peer (struct GNUNET_CORE_Handle *h,
376 const struct GNUNET_PeerIdentity *peer)
377{
378 struct PeerRecord *pr;
379
380 pr = GNUNET_new (struct PeerRecord);
381 pr->peer = *peer;
382 pr->h = h;
383 GNUNET_assert (GNUNET_YES ==
384 GNUNET_CONTAINER_multipeermap_put (
385 h->peers,
386 &pr->peer,
387 pr,
388 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
389 pr->mq = GNUNET_MQ_queue_for_callbacks (&core_mq_send_impl,
390 &core_mq_destroy_impl,
391 &core_mq_cancel_impl,
392 pr,
393 h->handlers,
394 &core_mq_error_handler,
395 pr);
396 if (NULL != h->connects)
397 {
398 pr->client_cls = h->connects (h->cls, &pr->peer, pr->mq);
399 GNUNET_MQ_set_handlers_closure (pr->mq, pr->client_cls);
400 }
401}
402
403
404/**
405 * Handle init reply message received from CORE service. Notify
406 * application that we are now connected to the CORE. Also fake
407 * loopback connection.
408 *
409 * @param cls the `struct GNUNET_CORE_Handle`
410 * @param m the init reply
411 */
412static void
413handle_init_reply (void *cls, const struct InitReplyMessage *m)
414{
415 struct GNUNET_CORE_Handle *h = cls;
416 GNUNET_CORE_StartupCallback init;
417
418 GNUNET_break (0 == ntohl (m->reserved));
419 h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
420 if (NULL != (init = h->init))
421 {
422 /* mark so we don't call init on reconnect */
423 h->init = NULL;
424 h->me = m->my_identity;
425 LOG (GNUNET_ERROR_TYPE_DEBUG,
426 "Connected to core service of peer `%s'.\n",
427 GNUNET_i2s (&h->me));
428 h->have_init = GNUNET_YES;
429 init (h->cls, &h->me);
430 }
431 else
432 {
433 LOG (GNUNET_ERROR_TYPE_DEBUG,
434 "Successfully reconnected to core service.\n");
435 if (GNUNET_NO == h->have_init)
436 {
437 h->me = m->my_identity;
438 h->have_init = GNUNET_YES;
439 }
440 else
441 {
442 GNUNET_break (0 == memcmp (&h->me,
443 &m->my_identity,
444 sizeof(struct GNUNET_PeerIdentity)));
445 }
446 }
447 /* fake 'connect to self' */
448 connect_peer (h, &h->me);
449}
450
451
452/**
453 * Handle connect message received from CORE service.
454 * Notify the application about the new connection.
455 *
456 * @param cls the `struct GNUNET_CORE_Handle`
457 * @param cnm the connect message
458 */
459static void
460handle_connect_notify (void *cls, const struct ConnectNotifyMessage *cnm)
461{
462 struct GNUNET_CORE_Handle *h = cls;
463 struct PeerRecord *pr;
464
465 LOG (GNUNET_ERROR_TYPE_DEBUG,
466 "Received notification about connection from `%s'.\n",
467 GNUNET_i2s (&cnm->peer));
468 if (0 == memcmp (&h->me, &cnm->peer, sizeof(struct GNUNET_PeerIdentity)))
469 {
470 /* connect to self!? */
471 GNUNET_break (0);
472 return;
473 }
474 pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &cnm->peer);
475 if (NULL != pr)
476 {
477 GNUNET_break (0);
478 reconnect_later (h);
479 return;
480 }
481 connect_peer (h, &cnm->peer);
482}
483
484
485/**
486 * Handle disconnect message received from CORE service.
487 * Notify the application about the lost connection.
488 *
489 * @param cls the `struct GNUNET_CORE_Handle`
490 * @param dnm message about the disconnect event
491 */
492static void
493handle_disconnect_notify (void *cls, const struct DisconnectNotifyMessage *dnm)
494{
495 struct GNUNET_CORE_Handle *h = cls;
496 struct PeerRecord *pr;
497
498 if (0 == memcmp (&h->me, &dnm->peer, sizeof(struct GNUNET_PeerIdentity)))
499 {
500 /* disconnect from self!? */
501 GNUNET_break (0);
502 return;
503 }
504 GNUNET_break (0 == ntohl (dnm->reserved));
505 LOG (GNUNET_ERROR_TYPE_DEBUG,
506 "Received notification about disconnect from `%s'.\n",
507 GNUNET_i2s (&dnm->peer));
508 pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &dnm->peer);
509 if (NULL == pr)
510 {
511 GNUNET_break (0);
512 reconnect_later (h);
513 return;
514 }
515 disconnect_and_free_peer_entry (h, &pr->peer, pr);
516}
517
518
519/**
520 * Check that message received from CORE service is well-formed.
521 *
522 * @param cls the `struct GNUNET_CORE_Handle`
523 * @param ntm the message we got
524 * @return #GNUNET_OK if the message is well-formed
525 */
526static int
527check_notify_inbound (void *cls, const struct NotifyTrafficMessage *ntm)
528{
529 uint16_t msize;
530 const struct GNUNET_MessageHeader *em;
531
532 (void) cls;
533 msize = ntohs (ntm->header.size) - sizeof(struct NotifyTrafficMessage);
534 if (msize < sizeof(struct GNUNET_MessageHeader))
535 {
536 GNUNET_break (0);
537 return GNUNET_SYSERR;
538 }
539 em = (const struct GNUNET_MessageHeader *) &ntm[1];
540 if (msize != ntohs (em->size))
541 {
542 GNUNET_break (0);
543 return GNUNET_SYSERR;
544 }
545 return GNUNET_OK;
546}
547
548
549/**
550 * Handle inbound message received from CORE service. If applicable,
551 * notify the application.
552 *
553 * @param cls the `struct GNUNET_CORE_Handle`
554 * @param ntm the message we got from CORE.
555 */
556static void
557handle_notify_inbound (void *cls, const struct NotifyTrafficMessage *ntm)
558{
559 struct GNUNET_CORE_Handle *h = cls;
560 const struct GNUNET_MessageHeader *em;
561 struct PeerRecord *pr;
562
563 LOG (GNUNET_ERROR_TYPE_DEBUG,
564 "Received inbound message from `%s'.\n",
565 GNUNET_i2s (&ntm->peer));
566 em = (const struct GNUNET_MessageHeader *) &ntm[1];
567 pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &ntm->peer);
568 if (NULL == pr)
569 {
570 GNUNET_break (0);
571 reconnect_later (h);
572 return;
573 }
574 GNUNET_MQ_inject_message (pr->mq, em);
575}
576
577
578/**
579 * Handle message received from CORE service notifying us that we are
580 * now allowed to send a message to a peer. If that message is still
581 * pending, put it into the queue to be transmitted.
582 *
583 * @param cls the `struct GNUNET_CORE_Handle`
584 * @param smr the message we got
585 */
586static void
587handle_send_ready (void *cls, const struct SendMessageReady *smr)
588{
589 struct GNUNET_CORE_Handle *h = cls;
590 struct PeerRecord *pr;
591
592 pr = GNUNET_CONTAINER_multipeermap_get (h->peers, &smr->peer);
593 if (NULL == pr)
594 {
595 GNUNET_break (0);
596 reconnect_later (h);
597 return;
598 }
599 LOG (GNUNET_ERROR_TYPE_DEBUG,
600 "Received notification about transmission readiness to `%s'.\n",
601 GNUNET_i2s (&smr->peer));
602 if (NULL == pr->env)
603 {
604 /* request must have been cancelled between the original request
605 * and the response from CORE, ignore CORE's readiness */
606 return;
607 }
608 if (ntohs (smr->smr_id) != pr->smr_id_gen)
609 {
610 /* READY message is for expired or cancelled message,
611 * ignore! (we should have already sent another request) */
612 return;
613 }
614
615 /* ok, all good, send message out! */
616 GNUNET_MQ_send (h->mq, pr->env);
617 pr->env = NULL;
618 GNUNET_MQ_impl_send_continue (pr->mq);
619}
620
621
622/**
623 * Our current client connection went down. Clean it up and try to
624 * reconnect!
625 *
626 * @param h our handle to the core service
627 */
628static void
629reconnect (struct GNUNET_CORE_Handle *h)
630{
631 struct GNUNET_MQ_MessageHandler handlers[] =
632 { GNUNET_MQ_hd_fixed_size (init_reply,
633 GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY,
634 struct InitReplyMessage,
635 h),
636 GNUNET_MQ_hd_fixed_size (connect_notify,
637 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT,
638 struct ConnectNotifyMessage,
639 h),
640 GNUNET_MQ_hd_fixed_size (disconnect_notify,
641 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT,
642 struct DisconnectNotifyMessage,
643 h),
644 GNUNET_MQ_hd_var_size (notify_inbound,
645 GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND,
646 struct NotifyTrafficMessage,
647 h),
648 GNUNET_MQ_hd_fixed_size (send_ready,
649 GNUNET_MESSAGE_TYPE_CORE_SEND_READY,
650 struct SendMessageReady,
651 h),
652 GNUNET_MQ_handler_end () };
653 struct InitMessage *init;
654 struct GNUNET_MQ_Envelope *env;
655 uint16_t *ts;
656
657 GNUNET_assert (NULL == h->mq);
658 h->mq = GNUNET_CLIENT_connect (h->cfg, "core", handlers, &handle_mq_error, h);
659 if (NULL == h->mq)
660 {
661 reconnect_later (h);
662 return;
663 }
664 env = GNUNET_MQ_msg_extra (init,
665 sizeof(uint16_t) * h->hcnt,
666 GNUNET_MESSAGE_TYPE_CORE_INIT);
667 LOG (GNUNET_ERROR_TYPE_INFO, "(Re)connecting to CORE service\n");
668 init->options = htonl (0);
669 ts = (uint16_t *) &init[1];
670 for (unsigned int hpos = 0; hpos < h->hcnt; hpos++)
671 ts[hpos] = htons (h->handlers[hpos].type);
672 GNUNET_MQ_send (h->mq, env);
673}
674
675
676/**
677 * Connect to the core service. Note that the connection may complete
678 * (or fail) asynchronously.
679 *
680 * @param cfg configuration to use
681 * @param cls closure for the various callbacks that follow (including handlers in the handlers array)
682 * @param init callback to call once we have successfully
683 * connected to the core service
684 * @param connects function to call on peer connect, can be NULL
685 * @param disconnects function to call on peer disconnect / timeout, can be NULL
686 * @param handlers callbacks for messages we care about, NULL-terminated
687 * @return handle to the core service (only useful for disconnect until @a init is called);
688 * NULL on error (in this case, init is never called)
689 */
690struct GNUNET_CORE_Handle *
691GNUNET_CORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
692 void *cls,
693 GNUNET_CORE_StartupCallback init,
694 GNUNET_CORE_ConnectEventHandler connects,
695 GNUNET_CORE_DisconnectEventHandler disconnects,
696 const struct GNUNET_MQ_MessageHandler *handlers)
697{
698 struct GNUNET_CORE_Handle *h;
699
700 h = GNUNET_new (struct GNUNET_CORE_Handle);
701 h->cfg = cfg;
702 h->cls = cls;
703 h->init = init;
704 h->connects = connects;
705 h->disconnects = disconnects;
706 h->peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
707 h->handlers = GNUNET_MQ_copy_handlers (handlers);
708 h->hcnt = GNUNET_MQ_count_handlers (handlers);
709 GNUNET_assert (h->hcnt <
710 (GNUNET_MAX_MESSAGE_SIZE - sizeof(struct InitMessage))
711 / sizeof(uint16_t));
712 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connecting to CORE service\n");
713 reconnect (h);
714 if (NULL == h->mq)
715 {
716 GNUNET_CORE_disconnect (h);
717 return NULL;
718 }
719 return h;
720}
721
722
723/**
724 * Disconnect from the core service.
725 *
726 * @param handle connection to core to disconnect
727 */
728void
729GNUNET_CORE_disconnect (struct GNUNET_CORE_Handle *handle)
730{
731 LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from CORE service\n");
732 GNUNET_CONTAINER_multipeermap_iterate (handle->peers,
733 &disconnect_and_free_peer_entry,
734 handle);
735 GNUNET_CONTAINER_multipeermap_destroy (handle->peers);
736 handle->peers = NULL;
737 if (NULL != handle->reconnect_task)
738 {
739 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
740 handle->reconnect_task = NULL;
741 }
742 if (NULL != handle->mq)
743 {
744 GNUNET_MQ_destroy (handle->mq);
745 handle->mq = NULL;
746 }
747 GNUNET_free (handle->handlers);
748 GNUNET_free (handle);
749}
750
751
752/**
753 * Obtain the message queue for a connected peer.
754 *
755 * @param h the core handle
756 * @param pid the identity of the peer to check if it has been connected to us
757 * @return NULL if peer is not connected
758 */
759struct GNUNET_MQ_Handle *
760GNUNET_CORE_get_mq (const struct GNUNET_CORE_Handle *h,
761 const struct GNUNET_PeerIdentity *pid)
762{
763 struct PeerRecord *pr;
764
765 pr = GNUNET_CONTAINER_multipeermap_get (h->peers, pid);
766 if (NULL == pr)
767 return NULL;
768 return pr->mq;
769}
770
771
772/* end of core_api.c */
diff --git a/src/core/core_api_cmd_connecting_peers.c b/src/core/core_api_cmd_connecting_peers.c
deleted file mode 100644
index ce2184a3c..000000000
--- a/src/core/core_api_cmd_connecting_peers.c
+++ /dev/null
@@ -1,275 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 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 testing_api_cmd_start_peer.c
23 * @brief cmd to start a peer.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_ng_lib.h"
29#include "gnunet_testing_netjail_lib.h"
30#include "gnunet_transport_application_service.h"
31#include "gnunet_hello_lib.h"
32#include "gnunet_transport_core_service.h"
33
34/**
35 * Generic logging shortcut
36 */
37#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
38
39
40/**
41 * The run method of this cmd will connect to peers.
42 *
43 */
44static void
45connect_peers_run (void *cls,
46 struct GNUNET_TESTING_Interpreter *is)
47{
48 struct GNUNET_TESTING_ConnectPeersState *cps = cls;
49 const struct GNUNET_TESTING_StartPeerState *sps;
50 const struct GNUNET_TESTING_Command *system_cmd;
51 const struct GNUNET_TESTING_System *tl_system;
52 const struct GNUNET_TESTING_Command *peer1_cmd;
53 struct GNUNET_PeerIdentity *peer;
54 enum GNUNET_NetworkType nt = 0;
55 struct GNUNET_TESTING_NodeConnection *pos_connection;
56 struct GNUNET_TESTING_AddressPrefix *pos_prefix;
57 const enum GNUNET_GenericReturnValue *broadcast;
58 unsigned int con_num = 0;
59 uint32_t num;
60 char *addr;
61 char *addr_and_port;
62 char *emsg = NULL;
63
64 cps->is = is;
65 peer1_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
66 cps->start_peer_label);
67 GNUNET_TESTING_get_trait_broadcast (peer1_cmd,
68 &broadcast);
69 GNUNET_TESTING_get_trait_state (peer1_cmd,
70 &sps);
71
72 system_cmd = GNUNET_TESTING_interpreter_lookup_command (is,
73 cps->create_label);
74 GNUNET_TESTING_get_trait_test_system (system_cmd,
75 &tl_system);
76
77 cps->tl_system = tl_system;
78
79 LOG (GNUNET_ERROR_TYPE_DEBUG,
80 "cps->num: %u \n",
81 cps->num);
82
83
84 cps->ah = GNUNET_TRANSPORT_application_init (sps->cfg);
85 if (NULL == cps->ah)
86 {
87 LOG (GNUNET_ERROR_TYPE_ERROR,
88 "Failed to initialize the TRANSPORT application suggestion client handle for peer `%s': `%s'\n",
89 sps->cfgname,
90 emsg);
91 GNUNET_free (emsg);
92 GNUNET_TESTING_interpreter_fail (is);
93 return;
94 }
95
96 cps->node_connections_head = GNUNET_TESTING_get_connections (cps->num,
97 cps->topology);
98
99 for (pos_connection = cps->node_connections_head; NULL != pos_connection;
100 pos_connection = pos_connection->next)
101 {
102 con_num++;
103 num = GNUNET_TESTING_calculate_num (pos_connection, cps->topology);
104 for (pos_prefix = pos_connection->address_prefixes_head; NULL != pos_prefix;
105 pos_prefix =
106 pos_prefix->next)
107 {
108 addr = GNUNET_TESTING_get_address (pos_connection,
109 pos_prefix->address_prefix);
110 if (NULL != addr)
111 {
112 char *natted_p = strstr (pos_prefix->address_prefix, "_");
113
114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
115 "0 validating peer number %s %s %s\n",
116 natted_p,
117 pos_prefix->address_prefix,
118 addr);
119 if (0 == GNUNET_memcmp (pos_prefix->address_prefix, "udp"))
120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
121 "validating memcmp\n");
122 if (GNUNET_YES == *broadcast)
123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
124 "validating broadcast\n");
125 if ((0 == GNUNET_memcmp (pos_prefix->address_prefix, "udp")) &&
126 (GNUNET_YES == *broadcast) )
127 GNUNET_asprintf (&addr_and_port,
128 "%s:2086",
129 addr);
130 else if (NULL == natted_p)
131 GNUNET_asprintf (&addr_and_port,
132 "%s:60002",
133 addr);
134 else if (NULL != natted_p)
135 {
136 char *prefix;
137 char *rest;
138 char *rest2;
139 char *address;
140
141 prefix = strtok (addr, "_");
142 rest = strtok (NULL, "_");
143 rest2 = strtok (rest, "-");
144 address = strtok (NULL, "-");
145
146 GNUNET_asprintf (&addr_and_port,
147 "%s-%s:0",
148 prefix,
149 address);
150
151 }
152 peer = GNUNET_TESTING_get_peer (num, tl_system);
153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
154 "validating peer number %u with identity %s and address %s %u %s and handle %p\n",
155 num,
156 GNUNET_i2s (peer),
157 addr_and_port,
158 *broadcast,
159 pos_prefix->address_prefix,
160 cps->ah);
161 GNUNET_TRANSPORT_application_validate ((struct
162 GNUNET_TRANSPORT_ApplicationHandle
163 *) cps->ah,
164 peer,
165 nt,
166 addr_and_port);
167 GNUNET_free (peer);
168 GNUNET_free (addr);
169 GNUNET_free (addr_and_port);
170 }
171 }
172 }
173 cps->con_num = con_num;
174}
175
176
177/**
178 * The cleanup function of this cmd frees resources the cmd allocated.
179 *
180 */
181static void
182connect_peers_cleanup (void *cls)
183{
184 struct GNUNET_TESTING_ConnectPeersState *cps = cls;
185
186 GNUNET_free (cps->connected_peers_map);
187 GNUNET_free (cps);
188}
189
190
191/**
192 * This function prepares an array with traits.
193 *
194 */
195enum GNUNET_GenericReturnValue
196connect_peers_traits (void *cls,
197 const void **ret,
198 const char *trait,
199 unsigned int index)
200{
201 struct GNUNET_TESTING_ConnectPeersState *cps = cls;
202 struct GNUNET_TESTING_Trait traits[] = {
203 GNUNET_TESTING_make_trait_connect_peer_state ((const void *) cps),
204 GNUNET_TESTING_trait_end ()
205 };
206 return GNUNET_TESTING_get_trait (traits,
207 ret,
208 trait,
209 index);
210}
211
212
213struct GNUNET_TESTING_Command
214GNUNET_CORE_cmd_connect_peers (const char *label,
215 const char *start_peer_label,
216 const char *create_label,
217 uint32_t num,
218 struct GNUNET_TESTING_NetjailTopology *
219 topology,
220 unsigned int additional_connects,
221 unsigned int wait_for_connect,
222 struct GNUNET_MQ_MessageHandler *handlers)
223{
224 struct GNUNET_TESTING_ConnectPeersState *cps;
225 unsigned int node_additional_connects;
226 struct GNUNET_CONTAINER_MultiShortmap *connected_peers_map =
227 GNUNET_CONTAINER_multishortmap_create (1,GNUNET_NO);
228 unsigned int i;
229
230 node_additional_connects = GNUNET_TESTING_get_additional_connects (num,
231 topology);
232
233 LOG (GNUNET_ERROR_TYPE_DEBUG,
234 "global: %u and local: %u additional_connects\n",
235 additional_connects,
236 node_additional_connects);
237
238 if (0 != node_additional_connects)
239 additional_connects = node_additional_connects;
240
241 cps = GNUNET_new (struct GNUNET_TESTING_ConnectPeersState);
242 cps->start_peer_label = start_peer_label;
243 cps->num = num;
244 cps->create_label = create_label;
245 cps->topology = topology;
246 cps->additional_connects = additional_connects;
247 cps->wait_for_connect = wait_for_connect;
248 cps->connected_peers_map = connected_peers_map;
249
250 if (NULL != handlers)
251 {
252 for (i = 0; NULL != handlers[i].cb; i++)
253 ;
254 cps->handlers = GNUNET_new_array (i + 1,
255 struct GNUNET_MQ_MessageHandler);
256 GNUNET_memcpy (cps->handlers,
257 handlers,
258 i * sizeof(struct GNUNET_MQ_MessageHandler));
259 }
260
261 if (GNUNET_YES == wait_for_connect)
262 return GNUNET_TESTING_command_new (cps,
263 label,
264 &connect_peers_run,
265 &connect_peers_cleanup,
266 &connect_peers_traits,
267 &cps->ac);
268 else
269 return GNUNET_TESTING_command_new (cps,
270 label,
271 &connect_peers_run,
272 &connect_peers_cleanup,
273 &connect_peers_traits,
274 NULL);
275}
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 e387fecc9..000000000
--- a/src/core/gnunet-service-core.c
+++ /dev/null
@@ -1,988 +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#include "gnunet_constants.h"
34
35/**
36 * How many messages do we queue up at most for any client? This can
37 * cause messages to be dropped if clients do not process them fast
38 * enough! Note that this is a soft limit; we try
39 * to keep a few larger messages above the limit.
40 */
41#define SOFT_MAX_QUEUE 128
42
43/**
44 * How many messages do we queue up at most for any client? This can
45 * cause messages to be dropped if clients do not process them fast
46 * enough! Note that this is the hard limit.
47 */
48#define HARD_MAX_QUEUE 256
49
50
51/**
52 * Data structure for each client connected to the CORE service.
53 */
54struct GSC_Client
55{
56 /**
57 * Clients are kept in a linked list.
58 */
59 struct GSC_Client *next;
60
61 /**
62 * Clients are kept in a linked list.
63 */
64 struct GSC_Client *prev;
65
66 /**
67 * Handle for the client with the server API.
68 */
69 struct GNUNET_SERVICE_Client *client;
70
71 /**
72 * Message queue to talk to @e client.
73 */
74 struct GNUNET_MQ_Handle *mq;
75
76 /**
77 * Array of the types of messages this peer cares
78 * about (with @e tcnt entries). Allocated as part
79 * of this client struct, do not free!
80 */
81 uint16_t *types;
82
83 /**
84 * Map of peer identities to active transmission requests of this
85 * client to the peer (of type `struct GSC_ClientActiveRequest`).
86 */
87 struct GNUNET_CONTAINER_MultiPeerMap *requests;
88
89 /**
90 * Map containing all peers that this client knows we're connected to.
91 */
92 struct GNUNET_CONTAINER_MultiPeerMap *connectmap;
93
94 /**
95 * Options for messages this client cares about,
96 * see GNUNET_CORE_OPTION_ values.
97 */
98 uint32_t options;
99
100 /**
101 * Have we gotten the #GNUNET_MESSAGE_TYPE_CORE_INIT message
102 * from this client already?
103 */
104 int got_init;
105
106 /**
107 * Number of types of incoming messages this client
108 * specifically cares about. Size of the @e types array.
109 */
110 unsigned int tcnt;
111};
112
113
114/**
115 * Our identity.
116 */
117struct GNUNET_PeerIdentity GSC_my_identity;
118
119/**
120 * Our configuration.
121 */
122const struct GNUNET_CONFIGURATION_Handle *GSC_cfg;
123
124/**
125 * For creating statistics.
126 */
127struct GNUNET_STATISTICS_Handle *GSC_stats;
128
129/**
130 * Big "or" of all client options.
131 */
132static uint32_t all_client_options;
133
134/**
135 * Head of linked list of our clients.
136 */
137static struct GSC_Client *client_head;
138
139/**
140 * Tail of linked list of our clients.
141 */
142static struct GSC_Client *client_tail;
143
144
145/**
146 * Test if the client is interested in messages of the given type.
147 *
148 * @param type message type
149 * @param c client to test
150 * @return #GNUNET_YES if @a c is interested, #GNUNET_NO if not.
151 */
152static int
153type_match (uint16_t type, struct GSC_Client *c)
154{
155 if ((0 == c->tcnt) && (0 != c->options))
156 return GNUNET_YES; /* peer without handlers and inbound/outbond
157 callbacks matches ALL */
158 if (NULL == c->types)
159 return GNUNET_NO;
160 for (unsigned int i = 0; i < c->tcnt; i++)
161 if (type == c->types[i])
162 return GNUNET_YES;
163 return GNUNET_NO;
164}
165
166
167/**
168 * Check #GNUNET_MESSAGE_TYPE_CORE_INIT request.
169 *
170 * @param cls client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT
171 * @param im the `struct InitMessage`
172 * @return #GNUNET_OK if @a im is well-formed
173 */
174static int
175check_client_init (void *cls, const struct InitMessage *im)
176{
177 return GNUNET_OK;
178}
179
180
181/**
182 * Handle #GNUNET_MESSAGE_TYPE_CORE_INIT request.
183 *
184 * @param cls client that sent #GNUNET_MESSAGE_TYPE_CORE_INIT
185 * @param im the `struct InitMessage`
186 */
187static void
188handle_client_init (void *cls, const struct InitMessage *im)
189{
190 struct GSC_Client *c = cls;
191 struct GNUNET_MQ_Envelope *env;
192 struct InitReplyMessage *irm;
193 uint16_t msize;
194 const uint16_t *types;
195
196 /* check that we don't have an entry already */
197 msize = ntohs (im->header.size) - sizeof(struct InitMessage);
198 types = (const uint16_t *) &im[1];
199 c->tcnt = msize / sizeof(uint16_t);
200 c->options = ntohl (im->options);
201 c->got_init = GNUNET_YES;
202 all_client_options |= c->options;
203 c->types = GNUNET_malloc (msize);
204 GNUNET_assert (GNUNET_YES ==
205 GNUNET_CONTAINER_multipeermap_put (
206 c->connectmap,
207 &GSC_my_identity,
208 NULL,
209 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
210 for (unsigned int i = 0; i < c->tcnt; i++)
211 c->types[i] = ntohs (types[i]);
212 GSC_TYPEMAP_add (c->types, c->tcnt);
213 GNUNET_log (
214 GNUNET_ERROR_TYPE_DEBUG,
215 "Client connecting to core service is interested in %u message types\n",
216 (unsigned int) c->tcnt);
217 /* send init reply message */
218 env = GNUNET_MQ_msg (irm, GNUNET_MESSAGE_TYPE_CORE_INIT_REPLY);
219 irm->reserved = htonl (0);
220 irm->my_identity = GSC_my_identity;
221 GNUNET_MQ_send (c->mq, env);
222 GSC_SESSIONS_notify_client_about_sessions (c);
223 GNUNET_SERVICE_client_continue (c->client);
224}
225
226
227/**
228 * We will never be ready to transmit the given message in (disconnect
229 * or invalid request). Frees resources associated with @a car. We
230 * don't explicitly tell the client, it'll learn with the disconnect
231 * (or violated the protocol).
232 *
233 * @param car request that now permanently failed; the
234 * responsibility for the handle is now returned
235 * to CLIENTS (SESSIONS is done with it).
236 * @param drop_client #GNUNET_YES if the client violated the protocol
237 * and we should thus drop the connection
238 */
239void
240GSC_CLIENTS_reject_request (struct GSC_ClientActiveRequest *car,
241 int drop_client)
242{
243 GNUNET_assert (
244 GNUNET_YES ==
245 GNUNET_CONTAINER_multipeermap_remove (car->client_handle->requests,
246 &car->target,
247 car));
248 if (GNUNET_YES == drop_client)
249 GNUNET_SERVICE_client_drop (car->client_handle->client);
250 GNUNET_free (car);
251}
252
253
254/**
255 * Tell a client that we are ready to receive the message.
256 *
257 * @param car request that is now ready; the responsibility
258 * for the handle remains shared between CLIENTS
259 * and SESSIONS after this call.
260 */
261void
262GSC_CLIENTS_solicit_request (struct GSC_ClientActiveRequest *car)
263{
264 struct GSC_Client *c;
265 struct GNUNET_MQ_Envelope *env;
266 struct SendMessageReady *smr;
267 struct GNUNET_TIME_Relative delay;
268 struct GNUNET_TIME_Relative left;
269
270 c = car->client_handle;
271 if (GNUNET_YES !=
272 GNUNET_CONTAINER_multipeermap_contains (c->connectmap, &car->target))
273 {
274 /* connection has gone down since, drop request */
275 GNUNET_assert (0 !=
276 GNUNET_memcmp (&car->target,
277 &GSC_my_identity));
278 GSC_SESSIONS_dequeue_request (car);
279 GSC_CLIENTS_reject_request (car, GNUNET_NO);
280 return;
281 }
282 delay = GNUNET_TIME_absolute_get_duration (car->received_time);
283 left = GNUNET_TIME_absolute_get_duration (car->deadline);
284 if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
285 GNUNET_log (
286 GNUNET_ERROR_TYPE_WARNING,
287 "Client waited %s for permission to transmit to `%s'%s (priority %u)\n",
288 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES),
289 GNUNET_i2s (&car->target),
290 (0 == left.rel_value_us) ? " (past deadline)" : "",
291 car->priority);
292 env = GNUNET_MQ_msg (smr, GNUNET_MESSAGE_TYPE_CORE_SEND_READY);
293 smr->size = htons (car->msize);
294 smr->smr_id = car->smr_id;
295 smr->peer = car->target;
296 GNUNET_MQ_send (c->mq, env);
297}
298
299
300/**
301 * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST message.
302 *
303 * @param cls client that sent a #GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST
304 * @param req the `struct SendMessageRequest`
305 */
306static void
307handle_client_send_request (void *cls, const struct SendMessageRequest *req)
308{
309 struct GSC_Client *c = cls;
310 struct GSC_ClientActiveRequest *car;
311 int is_loopback;
312
313 if (NULL == c->requests)
314 c->requests = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_NO);
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
316 "Client asked for transmission to `%s'\n",
317 GNUNET_i2s (&req->peer));
318 is_loopback = (0 == GNUNET_memcmp (&req->peer,
319 &GSC_my_identity));
320 if ((! is_loopback) &&
321 (GNUNET_YES !=
322 GNUNET_CONTAINER_multipeermap_contains (c->connectmap, &req->peer)))
323 {
324 /* neighbour must have disconnected since request was issued,
325 * ignore (client will realize it once it processes the
326 * disconnect notification) */
327 GNUNET_STATISTICS_update (GSC_stats,
328 gettext_noop (
329 "# send requests dropped (disconnected)"),
330 1,
331 GNUNET_NO);
332 GNUNET_SERVICE_client_continue (c->client);
333 return;
334 }
335
336 car = GNUNET_CONTAINER_multipeermap_get (c->requests, &req->peer);
337 if (NULL == car)
338 {
339 /* create new entry */
340 car = GNUNET_new (struct GSC_ClientActiveRequest);
341 GNUNET_assert (GNUNET_OK ==
342 GNUNET_CONTAINER_multipeermap_put (
343 c->requests,
344 &req->peer,
345 car,
346 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
347 car->client_handle = c;
348 }
349 else
350 {
351 /* dequeue and recycle memory from pending request, there can only
352 be at most one per client and peer */
353 GNUNET_STATISTICS_update (GSC_stats,
354 gettext_noop (
355 "# dequeuing CAR (duplicate request)"),
356 1,
357 GNUNET_NO);
358 GSC_SESSIONS_dequeue_request (car);
359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
360 "Transmission request to `%s' was a duplicate!\n",
361 GNUNET_i2s (&req->peer));
362 }
363 car->target = req->peer;
364 car->received_time = GNUNET_TIME_absolute_get ();
365 car->deadline = GNUNET_TIME_absolute_ntoh (req->deadline);
366 car->priority = (enum GNUNET_MQ_PriorityPreferences) ntohl (req->priority);
367 car->msize = ntohs (req->size);
368 car->smr_id = req->smr_id;
369 car->was_solicited = GNUNET_NO;
370 GNUNET_SERVICE_client_continue (c->client);
371 if (is_loopback)
372 {
373 /* loopback, satisfy immediately */
374 GSC_CLIENTS_solicit_request (car);
375 return;
376 }
377 GSC_SESSIONS_queue_request (car);
378}
379
380
381/**
382 * Closure for the #client_tokenizer_callback().
383 */
384struct TokenizerContext
385{
386 /**
387 * Active request handle for the message.
388 */
389 struct GSC_ClientActiveRequest *car;
390
391 /**
392 * How important is this message.
393 */
394 enum GNUNET_MQ_PriorityPreferences priority;
395};
396
397
398/**
399 * Functions with this signature are called whenever a complete
400 * message is received by the tokenizer. Used by
401 * #handle_client_send() for dispatching messages from clients to
402 * either the SESSION subsystem or other CLIENT (for loopback).
403 *
404 * @param cls reservation request (`struct TokenizerContext`)
405 * @param message the actual message
406 * @return #GNUNET_OK on success,
407 * #GNUNET_NO to stop further processing (no error)
408 * #GNUNET_SYSERR to stop further processing with error
409 */
410static int
411tokenized_cb (void *cls, const struct GNUNET_MessageHeader *message)
412{
413 struct TokenizerContext *tc = cls;
414 struct GSC_ClientActiveRequest *car = tc->car;
415 char buf[92];
416
417 GNUNET_snprintf (buf,
418 sizeof(buf),
419 gettext_noop ("# bytes of messages of type %u received"),
420 (unsigned int) ntohs (message->type));
421 GNUNET_STATISTICS_update (GSC_stats, buf, ntohs (message->size), GNUNET_NO);
422 if (0 == GNUNET_memcmp (&car->target,
423 &GSC_my_identity))
424 {
425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
426 "Delivering message of type %u to myself\n",
427 ntohs (message->type));
428 GSC_CLIENTS_deliver_message (&GSC_my_identity,
429 message,
430 ntohs (message->size),
431 GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
432 GSC_CLIENTS_deliver_message (&GSC_my_identity,
433 message,
434 sizeof(struct GNUNET_MessageHeader),
435 GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
436 GSC_CLIENTS_deliver_message (&GSC_my_identity,
437 message,
438 ntohs (message->size),
439 GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
440 GSC_CLIENTS_deliver_message (&GSC_my_identity,
441 message,
442 sizeof(struct GNUNET_MessageHeader),
443 GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
444 }
445 else
446 {
447 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
448 "Delivering message of type %u and size %u to %s\n",
449 ntohs (message->type),
450 ntohs (message->size),
451 GNUNET_i2s (&car->target));
452 GSC_CLIENTS_deliver_message (&car->target,
453 message,
454 ntohs (message->size),
455 GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND);
456 GSC_CLIENTS_deliver_message (&car->target,
457 message,
458 sizeof(struct GNUNET_MessageHeader),
459 GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND);
460 GSC_SESSIONS_transmit (car, message, tc->priority);
461 }
462 return GNUNET_OK;
463}
464
465
466/**
467 * Check #GNUNET_MESSAGE_TYPE_CORE_SEND request.
468 *
469 * @param cls the `struct GSC_Client`
470 * @param sm the `struct SendMessage`
471 * @return #GNUNET_OK if @a sm is well-formed
472 */
473static int
474check_client_send (void *cls, const struct SendMessage *sm)
475{
476 return GNUNET_OK;
477}
478
479
480/**
481 * Handle #GNUNET_MESSAGE_TYPE_CORE_SEND request.
482 *
483 * @param cls the `struct GSC_Client`
484 * @param sm the `struct SendMessage`
485 */
486static void
487handle_client_send (void *cls, const struct SendMessage *sm)
488{
489 struct GSC_Client *c = cls;
490 struct TokenizerContext tc;
491 uint16_t msize;
492 struct GNUNET_TIME_Relative delay;
493 struct GNUNET_MessageStreamTokenizer *mst;
494
495 msize = ntohs (sm->header.size) - sizeof(struct SendMessage);
496 tc.car = GNUNET_CONTAINER_multipeermap_get (c->requests, &sm->peer);
497 if (NULL == tc.car)
498 {
499 /* Must have been that we first approved the request, then got disconnected
500 * (which triggered removal of the 'car') and now the client gives us a message
501 * just *before* the client learns about the disconnect. Theoretically, we
502 * might also now be *again* connected. So this can happen (but should be
503 * rare). If it does happen, the message is discarded. */GNUNET_STATISTICS_update (GSC_stats,
504 gettext_noop (
505 "# messages discarded (session disconnected)"),
506 1,
507 GNUNET_NO);
508 GNUNET_SERVICE_client_continue (c->client);
509 return;
510 }
511 delay = GNUNET_TIME_absolute_get_duration (tc.car->received_time);
512 tc.priority = (enum GNUNET_MQ_PriorityPreferences) ntohl (sm->priority);
513 if (delay.rel_value_us > GNUNET_CONSTANTS_LATENCY_WARN.rel_value_us)
514 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
515 "Client waited %s for transmission of %u bytes to `%s'\n",
516 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES),
517 msize,
518 GNUNET_i2s (&sm->peer));
519 else
520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
521 "Client waited %s for transmission of %u bytes to `%s'\n",
522 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES),
523 msize,
524 GNUNET_i2s (&sm->peer));
525
526 GNUNET_assert (
527 GNUNET_YES ==
528 GNUNET_CONTAINER_multipeermap_remove (c->requests, &sm->peer, tc.car));
529 mst = GNUNET_MST_create (&tokenized_cb, &tc);
530 GNUNET_MST_from_buffer (mst,
531 (const char *) &sm[1],
532 msize,
533 GNUNET_YES,
534 GNUNET_NO);
535 GNUNET_MST_destroy (mst);
536 GSC_SESSIONS_dequeue_request (tc.car);
537 GNUNET_free (tc.car);
538 GNUNET_SERVICE_client_continue (c->client);
539}
540
541
542/**
543 * Free client request records.
544 *
545 * @param cls NULL
546 * @param key identity of peer for which this is an active request
547 * @param value the `struct GSC_ClientActiveRequest` to free
548 * @return #GNUNET_YES (continue iteration)
549 */
550static int
551destroy_active_client_request (void *cls,
552 const struct GNUNET_PeerIdentity *key,
553 void *value)
554{
555 struct GSC_ClientActiveRequest *car = value;
556
557 GNUNET_assert (
558 GNUNET_YES ==
559 GNUNET_CONTAINER_multipeermap_remove (car->client_handle->requests,
560 &car->target,
561 car));
562 GSC_SESSIONS_dequeue_request (car);
563 GNUNET_free (car);
564 return GNUNET_YES;
565}
566
567
568/**
569 * A client connected, set up.
570 *
571 * @param cls closure
572 * @param client identification of the client
573 * @param mq message queue to talk to @a client
574 * @return our client handle
575 */
576static void *
577client_connect_cb (void *cls,
578 struct GNUNET_SERVICE_Client *client,
579 struct GNUNET_MQ_Handle *mq)
580{
581 struct GSC_Client *c;
582
583 c = GNUNET_new (struct GSC_Client);
584 c->client = client;
585 c->mq = mq;
586 c->connectmap = GNUNET_CONTAINER_multipeermap_create (16, GNUNET_NO);
587 GNUNET_CONTAINER_DLL_insert (client_head, client_tail, c);
588 return c;
589}
590
591
592/**
593 * A client disconnected, clean up.
594 *
595 * @param cls closure
596 * @param client identification of the client
597 * @param app_ctx our `struct GST_Client` for @a client
598 */
599static void
600client_disconnect_cb (void *cls,
601 struct GNUNET_SERVICE_Client *client,
602 void *app_ctx)
603{
604 struct GSC_Client *c = app_ctx;
605
606 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
607 "Client %p has disconnected from core service.\n",
608 client);
609 GNUNET_CONTAINER_DLL_remove (client_head, client_tail, c);
610 if (NULL != c->requests)
611 {
612 GNUNET_CONTAINER_multipeermap_iterate (c->requests,
613 &destroy_active_client_request,
614 NULL);
615 GNUNET_CONTAINER_multipeermap_destroy (c->requests);
616 }
617 GNUNET_CONTAINER_multipeermap_destroy (c->connectmap);
618 c->connectmap = NULL;
619 if (NULL != c->types)
620 {
621 GSC_TYPEMAP_remove (c->types, c->tcnt);
622 GNUNET_free (c->types);
623 }
624 GNUNET_free (c);
625
626 /* recalculate 'all_client_options' */
627 all_client_options = 0;
628 for (c = client_head; NULL != c; c = c->next)
629 all_client_options |= c->options;
630}
631
632
633/**
634 * Notify a particular client about a change to existing connection to
635 * one of our neighbours (check if the client is interested). Called
636 * from #GSC_SESSIONS_notify_client_about_sessions().
637 *
638 * @param client client to notify
639 * @param neighbour identity of the neighbour that changed status
640 * @param tmap_old previous type map for the neighbour, NULL for connect
641 * @param tmap_new updated type map for the neighbour, NULL for disconnect
642 */
643void
644GSC_CLIENTS_notify_client_about_neighbour (
645 struct GSC_Client *client,
646 const struct GNUNET_PeerIdentity *neighbour,
647 const struct GSC_TypeMap *tmap_old,
648 const struct GSC_TypeMap *tmap_new)
649{
650 struct GNUNET_MQ_Envelope *env;
651 int old_match;
652 int new_match;
653
654 if (GNUNET_YES != client->got_init)
655 return;
656 old_match = GSC_TYPEMAP_test_match (tmap_old, client->types, client->tcnt);
657 new_match = GSC_TYPEMAP_test_match (tmap_new, client->types, client->tcnt);
658 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
659 "Notifying client about neighbour %s (%d/%d)\n",
660 GNUNET_i2s (neighbour),
661 old_match,
662 new_match);
663 if (old_match == new_match)
664 {
665 GNUNET_assert (
666 old_match ==
667 GNUNET_CONTAINER_multipeermap_contains (client->connectmap, neighbour));
668 return; /* no change */
669 }
670 if (GNUNET_NO == old_match)
671 {
672 struct ConnectNotifyMessage *cnm;
673
674 /* send connect */
675 GNUNET_assert (
676 GNUNET_NO ==
677 GNUNET_CONTAINER_multipeermap_contains (client->connectmap, neighbour));
678 GNUNET_assert (GNUNET_YES ==
679 GNUNET_CONTAINER_multipeermap_put (
680 client->connectmap,
681 neighbour,
682 NULL,
683 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
684 env = GNUNET_MQ_msg (cnm, GNUNET_MESSAGE_TYPE_CORE_NOTIFY_CONNECT);
685 cnm->reserved = htonl (0);
686 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
687 "Sending NOTIFY_CONNECT message about peer %s to client.\n",
688 GNUNET_i2s (neighbour));
689 cnm->peer = *neighbour;
690 GNUNET_MQ_send (client->mq, env);
691 }
692 else
693 {
694 struct DisconnectNotifyMessage *dcm;
695
696 /* send disconnect */
697 GNUNET_assert (
698 GNUNET_YES ==
699 GNUNET_CONTAINER_multipeermap_contains (client->connectmap, neighbour));
700 GNUNET_assert (GNUNET_YES ==
701 GNUNET_CONTAINER_multipeermap_remove (client->connectmap,
702 neighbour,
703 NULL));
704 env = GNUNET_MQ_msg (dcm, GNUNET_MESSAGE_TYPE_CORE_NOTIFY_DISCONNECT);
705 dcm->reserved = htonl (0);
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
707 "Sending NOTIFY_DISCONNECT message about peer %s to client.\n",
708 GNUNET_i2s (neighbour));
709 dcm->peer = *neighbour;
710 GNUNET_MQ_send (client->mq, env);
711 }
712}
713
714
715/**
716 * Notify all clients about a change to existing session.
717 * Called from SESSIONS whenever there is a change in sessions
718 * or types processed by the respective peer.
719 *
720 * @param neighbour identity of the neighbour that changed status
721 * @param tmap_old previous type map for the neighbour, NULL for connect
722 * @param tmap_new updated type map for the neighbour, NULL for disconnect
723 */
724void
725GSC_CLIENTS_notify_clients_about_neighbour (
726 const struct GNUNET_PeerIdentity *neighbour,
727 const struct GSC_TypeMap *tmap_old,
728 const struct GSC_TypeMap *tmap_new)
729{
730 struct GSC_Client *c;
731
732 for (c = client_head; NULL != c; c = c->next)
733 GSC_CLIENTS_notify_client_about_neighbour (c,
734 neighbour,
735 tmap_old,
736 tmap_new);
737}
738
739
740/**
741 * Deliver P2P message to interested clients. Caller must have checked
742 * that the sending peer actually lists the given message type as one
743 * of its types.
744 *
745 * @param sender peer who sent us the message
746 * @param msg the message
747 * @param msize number of bytes to transmit
748 * @param options options for checking which clients should
749 * receive the message
750 */
751void
752GSC_CLIENTS_deliver_message (const struct GNUNET_PeerIdentity *sender,
753 const struct GNUNET_MessageHeader *msg,
754 uint16_t msize,
755 uint32_t options)
756{
757 size_t size = msize + sizeof(struct NotifyTrafficMessage);
758
759 if (size >= GNUNET_MAX_MESSAGE_SIZE)
760 {
761 GNUNET_break (0);
762 return;
763 }
764 if (! ((0 != (all_client_options & options)) ||
765 (0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND))))
766 return; /* no client cares about this message notification */
767 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
768 "Core service passes message from `%s' of type %u to client.\n",
769 GNUNET_i2s (sender),
770 (unsigned int) ntohs (msg->type));
771 GSC_SESSIONS_add_to_typemap (sender, ntohs (msg->type));
772
773 for (struct GSC_Client *c = client_head; NULL != c; c = c->next)
774 {
775 struct GNUNET_MQ_Envelope *env;
776 struct NotifyTrafficMessage *ntm;
777 uint16_t mtype;
778 unsigned int qlen;
779 int tm;
780
781 tm = type_match (ntohs (msg->type), c);
782 if (! ((0 != (c->options & options)) ||
783 ((0 != (options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) &&
784 (GNUNET_YES == tm))))
785 continue; /* neither options nor type match permit the message */
786 if ((0 != (options & GNUNET_CORE_OPTION_SEND_HDR_INBOUND)) &&
787 ((0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
788 (GNUNET_YES == tm)))
789 continue;
790 if ((0 != (options & GNUNET_CORE_OPTION_SEND_HDR_OUTBOUND)) &&
791 (0 != (c->options & GNUNET_CORE_OPTION_SEND_FULL_OUTBOUND)))
792 continue;
793
794 /* Drop messages if:
795 1) We are above the hard limit, or
796 2) We are above the soft limit, and a coin toss limited
797 to the message size (giving larger messages a
798 proportionally higher chance of being queued) falls
799 below the threshold. The threshold is based on where
800 we are between the soft and the hard limit, scaled
801 to match the range of message sizes we usually encounter
802 (i.e. up to 32k); so a 64k message has a 50% chance of
803 being kept if we are just barely below the hard max,
804 and a 99% chance of being kept if we are at the soft max.
805 The reason is to make it more likely to drop control traffic
806 (ACK, queries) which may be cumulative or highly redundant,
807 and cheap to drop than data traffic. */qlen = GNUNET_MQ_get_length (c->mq);
808 if ((qlen >= HARD_MAX_QUEUE) ||
809 ((qlen > SOFT_MAX_QUEUE) &&
810 ((GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
811 ntohs (msg->size))) <
812 (qlen - SOFT_MAX_QUEUE) * 0x8000
813 / (HARD_MAX_QUEUE - SOFT_MAX_QUEUE))))
814 {
815 char buf[1024];
816
817 GNUNET_log (
818 GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
819 "Dropping decrypted message of type %u as client is too busy (queue full)\n",
820 (unsigned int) ntohs (msg->type));
821 GNUNET_snprintf (buf,
822 sizeof(buf),
823 gettext_noop (
824 "# messages of type %u discarded (client busy)"),
825 (unsigned int) ntohs (msg->type));
826 GNUNET_STATISTICS_update (GSC_stats, buf, 1, GNUNET_NO);
827 continue;
828 }
829
830 GNUNET_log (
831 GNUNET_ERROR_TYPE_DEBUG,
832 "Sending %u message with %u bytes to client interested in messages of type %u.\n",
833 options,
834 ntohs (msg->size),
835 (unsigned int) ntohs (msg->type));
836
837 if (0 != (options & (GNUNET_CORE_OPTION_SEND_FULL_INBOUND
838 | GNUNET_CORE_OPTION_SEND_HDR_INBOUND)))
839 mtype = GNUNET_MESSAGE_TYPE_CORE_NOTIFY_INBOUND;
840 else
841 mtype = GNUNET_MESSAGE_TYPE_CORE_NOTIFY_OUTBOUND;
842 env = GNUNET_MQ_msg_extra (ntm, msize, mtype);
843 ntm->peer = *sender;
844 GNUNET_memcpy (&ntm[1], msg, msize);
845
846 GNUNET_assert (
847 (0 == (c->options & GNUNET_CORE_OPTION_SEND_FULL_INBOUND)) ||
848 (GNUNET_YES != tm) ||
849 (GNUNET_YES ==
850 GNUNET_CONTAINER_multipeermap_contains (c->connectmap, sender)));
851 GNUNET_MQ_send (c->mq, env);
852 }
853}
854
855
856/**
857 * Last task run during shutdown. Disconnects us from
858 * the transport.
859 *
860 * @param cls NULL, unused
861 */
862static void
863shutdown_task (void *cls)
864{
865 struct GSC_Client *c;
866
867 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service shutting down.\n");
868 while (NULL != (c = client_head))
869 GNUNET_SERVICE_client_drop (c->client);
870 GSC_SESSIONS_done ();
871 GSC_KX_done ();
872 GSC_TYPEMAP_done ();
873 if (NULL != GSC_stats)
874 {
875 GNUNET_STATISTICS_destroy (GSC_stats, GNUNET_NO);
876 GSC_stats = NULL;
877 }
878 GSC_cfg = NULL;
879}
880
881
882/**
883 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
884 * request type, the client does not have to have transmitted an INIT
885 * request. All current peers are returned, regardless of which
886 * message types they accept.
887 *
888 * @param cls client sending the iteration request
889 * @param message iteration request message
890 */
891static void
892handle_client_monitor_peers (void *cls,
893 const struct GNUNET_MessageHeader *message)
894{
895 struct GSC_Client *c = cls;
896
897 GNUNET_SERVICE_client_continue (c->client);
898 GSC_KX_handle_client_monitor_peers (c->mq);
899}
900
901
902/**
903 * Initiate core service.
904 *
905 * @param cls closure
906 * @param c configuration to use
907 * @param service the initialized service
908 */
909static void
910run (void *cls,
911 const struct GNUNET_CONFIGURATION_Handle *c,
912 struct GNUNET_SERVICE_Handle *service)
913{
914 struct GNUNET_CRYPTO_EddsaPrivateKey pk;
915 char *keyfile;
916
917 GSC_cfg = c;
918 if (GNUNET_OK !=
919 GNUNET_CONFIGURATION_get_value_filename (GSC_cfg,
920 "PEER",
921 "PRIVATE_KEY",
922 &keyfile))
923 {
924 GNUNET_log (
925 GNUNET_ERROR_TYPE_ERROR,
926 _ ("Core service is lacking HOSTKEY configuration setting. Exiting.\n"));
927 GNUNET_SCHEDULER_shutdown ();
928 return;
929 }
930 GSC_stats = GNUNET_STATISTICS_create ("core", GSC_cfg);
931 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
932 GNUNET_SERVICE_suspend (service);
933 GSC_TYPEMAP_init ();
934 if (GNUNET_SYSERR ==
935 GNUNET_CRYPTO_eddsa_key_from_file (keyfile,
936 GNUNET_YES,
937 &pk))
938 {
939 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
940 "Failed to setup peer's private key\n");
941 GNUNET_SCHEDULER_shutdown ();
942 GNUNET_free (keyfile);
943 return;
944 }
945 GNUNET_free (keyfile);
946 if (GNUNET_OK != GSC_KX_init (&pk))
947 {
948 GNUNET_SCHEDULER_shutdown ();
949 return;
950 }
951 GSC_SESSIONS_init ();
952 GNUNET_SERVICE_resume (service);
953 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
954 _ ("Core service of `%s' ready.\n"),
955 GNUNET_i2s (&GSC_my_identity));
956}
957
958
959/**
960 * Define "main" method using service macro.
961 */
962GNUNET_SERVICE_MAIN (
963 "core",
964 GNUNET_SERVICE_OPTION_NONE,
965 &run,
966 &client_connect_cb,
967 &client_disconnect_cb,
968 NULL,
969 GNUNET_MQ_hd_var_size (client_init,
970 GNUNET_MESSAGE_TYPE_CORE_INIT,
971 struct InitMessage,
972 NULL),
973 GNUNET_MQ_hd_fixed_size (client_monitor_peers,
974 GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS,
975 struct GNUNET_MessageHeader,
976 NULL),
977 GNUNET_MQ_hd_fixed_size (client_send_request,
978 GNUNET_MESSAGE_TYPE_CORE_SEND_REQUEST,
979 struct SendMessageRequest,
980 NULL),
981 GNUNET_MQ_hd_var_size (client_send,
982 GNUNET_MESSAGE_TYPE_CORE_SEND,
983 struct SendMessage,
984 NULL),
985 GNUNET_MQ_handler_end ());
986
987
988/* 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 ca7bccbd9..000000000
--- a/src/core/gnunet-service-core_kx.c
+++ /dev/null
@@ -1,1934 +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_transport_core_service.h"
30#include "gnunet-service-core_sessions.h"
31#include "gnunet-service-core.h"
32#include "gnunet_constants.h"
33#include "gnunet_signatures.h"
34#include "gnunet_protocols.h"
35
36/**
37 * Enable expensive (and possibly problematic for privacy!) logging of KX.
38 */
39#define DEBUG_KX 0
40
41/**
42 * How long do we wait for SET_KEY confirmation initially?
43 */
44#define INITIAL_SET_KEY_RETRY_FREQUENCY \
45 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
46
47/**
48 * What is the minimum frequency for a PING message?
49 */
50#define MIN_PING_FREQUENCY \
51 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
52
53/**
54 * How often do we rekey?
55 */
56#define REKEY_FREQUENCY \
57 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
58
59/**
60 * What time difference do we tolerate?
61 */
62#define REKEY_TOLERANCE \
63 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
64
65/**
66 * What is the maximum age of a message for us to consider processing
67 * it? Note that this looks at the timestamp used by the other peer,
68 * so clock skew between machines does come into play here. So this
69 * should be picked high enough so that a little bit of clock skew
70 * does not prevent peers from connecting to us.
71 */
72#define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS
73
74
75GNUNET_NETWORK_STRUCT_BEGIN
76
77/**
78 * Encapsulation for encrypted messages exchanged between
79 * peers. Followed by the actual encrypted data.
80 */
81struct EncryptedMessage
82{
83 /**
84 * Message type is #GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE.
85 */
86 struct GNUNET_MessageHeader header;
87
88 /**
89 * Random value used for IV generation.
90 */
91 uint32_t iv_seed GNUNET_PACKED;
92
93 /**
94 * MAC of the encrypted message (starting at @e sequence_number),
95 * used to verify message integrity. Everything after this value
96 * (excluding this value itself) will be encrypted and
97 * authenticated. #ENCRYPTED_HEADER_SIZE must be set to the offset
98 * of the *next* field.
99 */
100 struct GNUNET_HashCode hmac;
101
102 /**
103 * Sequence number, in network byte order. This field
104 * must be the first encrypted/decrypted field
105 */
106 uint32_t sequence_number GNUNET_PACKED;
107
108 /**
109 * Reserved, always zero.
110 */
111 uint32_t reserved GNUNET_PACKED;
112
113 /**
114 * Timestamp. Used to prevent replay of ancient messages
115 * (recent messages are caught with the sequence number).
116 */
117 struct GNUNET_TIME_AbsoluteNBO timestamp;
118};
119GNUNET_NETWORK_STRUCT_END
120
121
122/**
123 * Number of bytes (at the beginning) of `struct EncryptedMessage`
124 * that are NOT encrypted.
125 */
126#define ENCRYPTED_HEADER_SIZE \
127 (offsetof (struct EncryptedMessage, sequence_number))
128
129
130/**
131 * Information about the status of a key exchange with another peer.
132 */
133struct GSC_KeyExchangeInfo
134{
135 /**
136 * DLL.
137 */
138 struct GSC_KeyExchangeInfo *next;
139
140 /**
141 * DLL.
142 */
143 struct GSC_KeyExchangeInfo *prev;
144
145 /**
146 * Identity of the peer.
147 */
148 const struct GNUNET_PeerIdentity *peer;
149
150 /**
151 * Message queue for sending messages to @a peer.
152 */
153 struct GNUNET_MQ_Handle *mq;
154
155 /**
156 * Our message stream tokenizer (for encrypted payload).
157 */
158 struct GNUNET_MessageStreamTokenizer *mst;
159
160 /**
161 * PING message we transmit to the other peer.
162 */
163 struct PingMessage ping;
164
165 /**
166 * Ephemeral public ECC key of the other peer.
167 */
168 struct GNUNET_CRYPTO_EcdhePublicKey other_ephemeral_key;
169
170 /**
171 * Key we use to encrypt our messages for the other peer
172 * (initialized by us when we do the handshake).
173 */
174 struct GNUNET_CRYPTO_SymmetricSessionKey encrypt_key;
175
176 /**
177 * Key we use to decrypt messages from the other peer
178 * (given to us by the other peer during the handshake).
179 */
180 struct GNUNET_CRYPTO_SymmetricSessionKey decrypt_key;
181
182 /**
183 * At what time did the other peer generate the decryption key?
184 */
185 struct GNUNET_TIME_Absolute foreign_key_expires;
186
187 /**
188 * When should the session time out (if there are no PONGs)?
189 */
190 struct GNUNET_TIME_Absolute timeout;
191
192 /**
193 * What was the last timeout we informed our monitors about?
194 */
195 struct GNUNET_TIME_Absolute last_notify_timeout;
196
197 /**
198 * At what frequency are we currently re-trying SET_KEY messages?
199 */
200 struct GNUNET_TIME_Relative set_key_retry_frequency;
201
202 /**
203 * ID of task used for re-trying SET_KEY and PING message.
204 */
205 struct GNUNET_SCHEDULER_Task *retry_set_key_task;
206
207 /**
208 * ID of task used for sending keep-alive pings.
209 */
210 struct GNUNET_SCHEDULER_Task *keep_alive_task;
211
212 /**
213 * Bit map indicating which of the 32 sequence numbers before the
214 * last were received (good for accepting out-of-order packets and
215 * estimating reliability of the connection)
216 */
217 uint32_t last_packets_bitmap;
218
219 /**
220 * last sequence number received on this connection (highest)
221 */
222 uint32_t last_sequence_number_received;
223
224 /**
225 * last sequence number transmitted
226 */
227 uint32_t last_sequence_number_sent;
228
229 /**
230 * What was our PING challenge number (for this peer)?
231 */
232 uint32_t ping_challenge;
233
234 /**
235 * #GNUNET_YES if this peer currently has excess bandwidth.
236 */
237 int has_excess_bandwidth;
238
239 /**
240 * What is our connection status?
241 */
242 enum GNUNET_CORE_KxState status;
243};
244
245
246/**
247 * Transport service.
248 */
249static struct GNUNET_TRANSPORT_CoreHandle *transport;
250
251/**
252 * Our private key.
253 */
254static struct GNUNET_CRYPTO_EddsaPrivateKey my_private_key;
255
256/**
257 * Our ephemeral private key.
258 */
259static struct GNUNET_CRYPTO_EcdhePrivateKey my_ephemeral_key;
260
261/**
262 * Current message we send for a key exchange.
263 */
264static struct EphemeralKeyMessage current_ekm;
265
266/**
267 * DLL head.
268 */
269static struct GSC_KeyExchangeInfo *kx_head;
270
271/**
272 * DLL tail.
273 */
274static struct GSC_KeyExchangeInfo *kx_tail;
275
276/**
277 * Task scheduled for periodic re-generation (and thus rekeying) of our
278 * ephemeral key.
279 */
280static struct GNUNET_SCHEDULER_Task *rekey_task;
281
282/**
283 * Notification context for broadcasting to monitors.
284 */
285static struct GNUNET_NotificationContext *nc;
286
287
288/**
289 * Calculate seed value we should use for a message.
290 *
291 * @param kx key exchange context
292 */
293static uint32_t
294calculate_seed (struct GSC_KeyExchangeInfo *kx)
295{
296 /* Note: may want to make this non-random and instead
297 derive from key material to avoid having an undetectable
298 side-channel */
299 return htonl (
300 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX));
301}
302
303
304/**
305 * Inform all monitors about the KX state of the given peer.
306 *
307 * @param kx key exchange state to inform about
308 */
309static void
310monitor_notify_all (struct GSC_KeyExchangeInfo *kx)
311{
312 struct MonitorNotifyMessage msg;
313
314 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
315 msg.header.size = htons (sizeof(msg));
316 msg.state = htonl ((uint32_t) kx->status);
317 msg.peer = *kx->peer;
318 msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
319 GNUNET_notification_context_broadcast (nc, &msg.header, GNUNET_NO);
320 kx->last_notify_timeout = kx->timeout;
321}
322
323
324/**
325 * Derive an authentication key from "set key" information
326 *
327 * @param akey authentication key to derive
328 * @param skey session key to use
329 * @param seed seed to use
330 */
331static void
332derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey,
333 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
334 uint32_t seed)
335{
336 static const char ctx[] = "authentication key";
337
338#if DEBUG_KX
339 struct GNUNET_HashCode sh;
340
341 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343 "Deriving Auth key from SKEY %s and seed %u\n",
344 GNUNET_h2s (&sh),
345 (unsigned int) seed);
346#endif
347 GNUNET_CRYPTO_hmac_derive_key (akey,
348 skey,
349 &seed,
350 sizeof(seed),
351 skey,
352 sizeof(
353 struct GNUNET_CRYPTO_SymmetricSessionKey),
354 ctx,
355 sizeof(ctx),
356 NULL);
357}
358
359
360/**
361 * Derive an IV from packet information
362 *
363 * @param iv initialization vector to initialize
364 * @param skey session key to use
365 * @param seed seed to use
366 * @param identity identity of the other peer to use
367 */
368static void
369derive_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
370 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
371 uint32_t seed,
372 const struct GNUNET_PeerIdentity *identity)
373{
374 static const char ctx[] = "initialization vector";
375
376#if DEBUG_KX
377 struct GNUNET_HashCode sh;
378
379 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
380 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
381 "Deriving IV from SKEY %s and seed %u for peer %s\n",
382 GNUNET_h2s (&sh),
383 (unsigned int) seed,
384 GNUNET_i2s (identity));
385#endif
386 GNUNET_CRYPTO_symmetric_derive_iv (iv,
387 skey,
388 &seed,
389 sizeof(seed),
390 identity,
391 sizeof(struct GNUNET_PeerIdentity),
392 ctx,
393 sizeof(ctx),
394 NULL);
395}
396
397
398/**
399 * Derive an IV from pong packet information
400 *
401 * @param iv initialization vector to initialize
402 * @param skey session key to use
403 * @param seed seed to use
404 * @param challenge nonce to use
405 * @param identity identity of the other peer to use
406 */
407static void
408derive_pong_iv (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
409 const struct GNUNET_CRYPTO_SymmetricSessionKey *skey,
410 uint32_t seed,
411 uint32_t challenge,
412 const struct GNUNET_PeerIdentity *identity)
413{
414 static const char ctx[] = "pong initialization vector";
415
416#if DEBUG_KX
417 struct GNUNET_HashCode sh;
418
419 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
420 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
421 "Deriving PONG IV from SKEY %s and seed %u/%u for %s\n",
422 GNUNET_h2s (&sh),
423 (unsigned int) seed,
424 (unsigned int) challenge,
425 GNUNET_i2s (identity));
426#endif
427 GNUNET_CRYPTO_symmetric_derive_iv (iv,
428 skey,
429 &seed,
430 sizeof(seed),
431 identity,
432 sizeof(struct GNUNET_PeerIdentity),
433 &challenge,
434 sizeof(challenge),
435 ctx,
436 sizeof(ctx),
437 NULL);
438}
439
440
441/**
442 * Derive an AES key from key material
443 *
444 * @param sender peer identity of the sender
445 * @param receiver peer identity of the sender
446 * @param key_material high entropy key material to use
447 * @param skey set to derived session key
448 */
449static void
450derive_aes_key (const struct GNUNET_PeerIdentity *sender,
451 const struct GNUNET_PeerIdentity *receiver,
452 const struct GNUNET_HashCode *key_material,
453 struct GNUNET_CRYPTO_SymmetricSessionKey *skey)
454{
455 static const char ctx[] = "aes key generation vector";
456
457#if DEBUG_KX
458 struct GNUNET_HashCode sh;
459
460 GNUNET_CRYPTO_hash (skey, sizeof(*skey), &sh);
461 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
462 "Deriving AES Keys for %s to %s from %s\n",
463 GNUNET_i2s (sender),
464 GNUNET_i2s2 (receiver),
465 GNUNET_h2s (key_material));
466#endif
467 GNUNET_CRYPTO_kdf (skey,
468 sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey),
469 ctx,
470 sizeof(ctx),
471 key_material,
472 sizeof(struct GNUNET_HashCode),
473 sender,
474 sizeof(struct GNUNET_PeerIdentity),
475 receiver,
476 sizeof(struct GNUNET_PeerIdentity),
477 NULL);
478}
479
480
481/**
482 * Encrypt size bytes from @a in and write the result to @a out. Use the
483 * @a kx key for outbound traffic of the given neighbour.
484 *
485 * @param kx key information context
486 * @param iv initialization vector to use
487 * @param in ciphertext
488 * @param out plaintext
489 * @param size size of @a in / @a out
490 *
491 * @return #GNUNET_OK on success
492 */
493static int
494do_encrypt (struct GSC_KeyExchangeInfo *kx,
495 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
496 const void *in,
497 void *out,
498 size_t size)
499{
500 if (size != (uint16_t) size)
501 {
502 GNUNET_break (0);
503 return GNUNET_NO;
504 }
505 GNUNET_assert (size == GNUNET_CRYPTO_symmetric_encrypt (in,
506 (uint16_t) size,
507 &kx->encrypt_key,
508 iv,
509 out));
510 GNUNET_STATISTICS_update (GSC_stats,
511 gettext_noop ("# bytes encrypted"),
512 size,
513 GNUNET_NO);
514 /* the following is too sensitive to write to log files by accident,
515 so we require manual intervention to get this one... */
516#if DEBUG_KX
517 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
518 "Encrypted %u bytes for `%s' using key %s, IV %u\n",
519 (unsigned int) size,
520 GNUNET_i2s (kx->peer),
521 kx->encrypt_key.aes_key,
522 GNUNET_CRYPTO_crc32_n (iv, sizeof(iv)));
523#endif
524 return GNUNET_OK;
525}
526
527
528/**
529 * Decrypt size bytes from @a in and write the result to @a out. Use
530 * the @a kx key for inbound traffic of the given neighbour. This
531 * function does NOT do any integrity-checks on the result.
532 *
533 * @param kx key information context
534 * @param iv initialization vector to use
535 * @param in ciphertext
536 * @param out plaintext
537 * @param size size of @a in / @a out
538 * @return #GNUNET_OK on success
539 */
540static int
541do_decrypt (struct GSC_KeyExchangeInfo *kx,
542 const struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
543 const void *in,
544 void *out,
545 size_t size)
546{
547 if (size != (uint16_t) size)
548 {
549 GNUNET_break (0);
550 return GNUNET_NO;
551 }
552 if ((kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
553 (kx->status != GNUNET_CORE_KX_STATE_UP) &&
554 (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT))
555 {
556 GNUNET_break_op (0);
557 return GNUNET_SYSERR;
558 }
559 if (size != GNUNET_CRYPTO_symmetric_decrypt (in,
560 (uint16_t) size,
561 &kx->decrypt_key,
562 iv,
563 out))
564 {
565 GNUNET_break (0);
566 return GNUNET_SYSERR;
567 }
568 GNUNET_STATISTICS_update (GSC_stats,
569 gettext_noop ("# bytes decrypted"),
570 size,
571 GNUNET_NO);
572 /* the following is too sensitive to write to log files by accident,
573 so we require manual intervention to get this one... */
574#if DEBUG_KX
575 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
576 "Decrypted %u bytes from `%s' using key %s, IV %u\n",
577 (unsigned int) size,
578 GNUNET_i2s (kx->peer),
579 kx->decrypt_key.aes_key,
580 GNUNET_CRYPTO_crc32_n (iv, sizeof(*iv)));
581#endif
582 return GNUNET_OK;
583}
584
585
586/**
587 * Send our key (and encrypted PING) to the other peer.
588 *
589 * @param kx key exchange context
590 */
591static void
592send_key (struct GSC_KeyExchangeInfo *kx);
593
594
595/**
596 * Task that will retry #send_key() if our previous attempt failed.
597 *
598 * @param cls our `struct GSC_KeyExchangeInfo`
599 */
600static void
601set_key_retry_task (void *cls)
602{
603 struct GSC_KeyExchangeInfo *kx = cls;
604
605 kx->retry_set_key_task = NULL;
606 kx->set_key_retry_frequency =
607 GNUNET_TIME_STD_BACKOFF (kx->set_key_retry_frequency);
608 GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
609 send_key (kx);
610}
611
612
613/**
614 * Create a fresh PING message for transmission to the other peer.
615 *
616 * @param kx key exchange context to create PING for
617 */
618static void
619setup_fresh_ping (struct GSC_KeyExchangeInfo *kx)
620{
621 struct PingMessage pp;
622 struct PingMessage *pm;
623 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
624
625 pm = &kx->ping;
626 kx->ping_challenge =
627 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX);
628 pm->header.size = htons (sizeof(struct PingMessage));
629 pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING);
630 pm->iv_seed = calculate_seed (kx);
631 derive_iv (&iv, &kx->encrypt_key, pm->iv_seed, kx->peer);
632 pp.challenge = kx->ping_challenge;
633 pp.target = *kx->peer;
634 do_encrypt (kx,
635 &iv,
636 &pp.target,
637 &pm->target,
638 sizeof(struct PingMessage)
639 - ((void *) &pm->target - (void *) pm));
640}
641
642
643/**
644 * Deliver P2P message to interested clients. Invokes send twice,
645 * once for clients that want the full message, and once for clients
646 * that only want the header
647 *
648 * @param cls the `struct GSC_KeyExchangeInfo`
649 * @param m the message
650 * @return #GNUNET_OK on success,
651 * #GNUNET_NO to stop further processing (no error)
652 * #GNUNET_SYSERR to stop further processing with error
653 */
654static int
655deliver_message (void *cls, const struct GNUNET_MessageHeader *m)
656{
657 struct GSC_KeyExchangeInfo *kx = cls;
658
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
660 "Decrypted message of type %d from %s\n",
661 ntohs (m->type),
662 GNUNET_i2s (kx->peer));
663 if (GNUNET_CORE_KX_STATE_UP != kx->status)
664 {
665 GNUNET_STATISTICS_update (GSC_stats,
666 gettext_noop ("# PAYLOAD dropped (out of order)"),
667 1,
668 GNUNET_NO);
669 return GNUNET_OK;
670 }
671 switch (ntohs (m->type))
672 {
673 case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP:
674 case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
675 GSC_SESSIONS_set_typemap (kx->peer, m);
676 return GNUNET_OK;
677
678 case GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP:
679 GSC_SESSIONS_confirm_typemap (kx->peer, m);
680 return GNUNET_OK;
681
682 default:
683 GSC_CLIENTS_deliver_message (kx->peer,
684 m,
685 ntohs (m->size),
686 GNUNET_CORE_OPTION_SEND_FULL_INBOUND);
687 GSC_CLIENTS_deliver_message (kx->peer,
688 m,
689 sizeof(struct GNUNET_MessageHeader),
690 GNUNET_CORE_OPTION_SEND_HDR_INBOUND);
691 }
692 return GNUNET_OK;
693}
694
695
696/**
697 * Function called by transport to notify us that
698 * a peer connected to us (on the network level).
699 * Starts the key exchange with the given peer.
700 *
701 * @param cls closure (NULL)
702 * @param pid identity of the peer to do a key exchange with
703 * @return key exchange information context
704 */
705static void *
706handle_transport_notify_connect (void *cls,
707 const struct GNUNET_PeerIdentity *pid,
708 struct GNUNET_MQ_Handle *mq)
709{
710 struct GSC_KeyExchangeInfo *kx;
711 struct GNUNET_HashCode h1;
712 struct GNUNET_HashCode h2;
713
714 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
715 "Initiating key exchange with `%s'\n",
716 GNUNET_i2s (pid));
717 GNUNET_STATISTICS_update (GSC_stats,
718 gettext_noop ("# key exchanges initiated"),
719 1,
720 GNUNET_NO);
721 kx = GNUNET_new (struct GSC_KeyExchangeInfo);
722 kx->mst = GNUNET_MST_create (&deliver_message, kx);
723 kx->mq = mq;
724 kx->peer = pid;
725 kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY;
726 GNUNET_CONTAINER_DLL_insert (kx_head, kx_tail, kx);
727 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
728 monitor_notify_all (kx);
729 GNUNET_CRYPTO_hash (pid, sizeof(struct GNUNET_PeerIdentity), &h1);
730 GNUNET_CRYPTO_hash (&GSC_my_identity,
731 sizeof(struct GNUNET_PeerIdentity),
732 &h2);
733 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, &h2))
734 {
735 /* peer with "lower" identity starts KX, otherwise we typically end up
736 with both peers starting the exchange and transmit the 'set key'
737 message twice */
738 send_key (kx);
739 }
740 else
741 {
742 /* peer with "higher" identity starts a delayed KX, if the "lower" peer
743 * does not start a KX since it sees no reasons to do so */
744 kx->retry_set_key_task =
745 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
746 &set_key_retry_task,
747 kx);
748 }
749 return kx;
750}
751
752
753/**
754 * Function called by transport telling us that a peer
755 * disconnected.
756 * Stop key exchange with the given peer. Clean up key material.
757 *
758 * @param cls closure
759 * @param peer the peer that disconnected
760 * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer
761 */
762static void
763handle_transport_notify_disconnect (void *cls,
764 const struct GNUNET_PeerIdentity *peer,
765 void *handler_cls)
766{
767 struct GSC_KeyExchangeInfo *kx = handler_cls;
768
769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
770 "Peer `%s' disconnected from us.\n",
771 GNUNET_i2s (peer));
772 GSC_SESSIONS_end (kx->peer);
773 GNUNET_STATISTICS_update (GSC_stats,
774 gettext_noop ("# key exchanges stopped"),
775 1,
776 GNUNET_NO);
777 if (NULL != kx->retry_set_key_task)
778 {
779 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
780 kx->retry_set_key_task = NULL;
781 }
782 if (NULL != kx->keep_alive_task)
783 {
784 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
785 kx->keep_alive_task = NULL;
786 }
787 kx->status = GNUNET_CORE_KX_PEER_DISCONNECT;
788 monitor_notify_all (kx);
789 GNUNET_CONTAINER_DLL_remove (kx_head, kx_tail, kx);
790 GNUNET_MST_destroy (kx->mst);
791 GNUNET_free (kx);
792}
793
794
795/**
796 * Send our PING to the other peer.
797 *
798 * @param kx key exchange context
799 */
800static void
801send_ping (struct GSC_KeyExchangeInfo *kx)
802{
803 struct GNUNET_MQ_Envelope *env;
804
805 GNUNET_STATISTICS_update (GSC_stats,
806 gettext_noop ("# PING messages transmitted"),
807 1,
808 GNUNET_NO);
809 env = GNUNET_MQ_msg_copy (&kx->ping.header);
810 GNUNET_MQ_send (kx->mq, env);
811}
812
813
814/**
815 * Derive fresh session keys from the current ephemeral keys.
816 *
817 * @param kx session to derive keys for
818 */
819static void
820derive_session_keys (struct GSC_KeyExchangeInfo *kx)
821{
822 struct GNUNET_HashCode key_material;
823
824 if (GNUNET_OK !=
825 GNUNET_CRYPTO_ecc_ecdh (&my_ephemeral_key,
826 &kx->other_ephemeral_key,
827 &key_material))
828 {
829 GNUNET_break (0);
830 return;
831 }
832 derive_aes_key (&GSC_my_identity, kx->peer, &key_material, &kx->encrypt_key);
833 derive_aes_key (kx->peer, &GSC_my_identity, &key_material, &kx->decrypt_key);
834 memset (&key_material, 0, sizeof(key_material));
835 /* fresh key, reset sequence numbers */
836 kx->last_sequence_number_received = 0;
837 kx->last_packets_bitmap = 0;
838 setup_fresh_ping (kx);
839}
840
841
842/**
843 * We received a #GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY message.
844 * Validate and update our key material and status.
845 *
846 * @param cls key exchange status for the corresponding peer
847 * @param m the set key message we received
848 */
849static void
850handle_ephemeral_key (void *cls, const struct EphemeralKeyMessage *m)
851{
852 struct GSC_KeyExchangeInfo *kx = cls;
853 struct GNUNET_TIME_Absolute start_t;
854 struct GNUNET_TIME_Absolute end_t;
855 struct GNUNET_TIME_Absolute now;
856 enum GNUNET_CORE_KxState sender_status;
857
858 end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time);
859 if (((GNUNET_CORE_KX_STATE_KEY_RECEIVED == kx->status) ||
860 (GNUNET_CORE_KX_STATE_UP == kx->status) ||
861 (GNUNET_CORE_KX_STATE_REKEY_SENT == kx->status)) &&
862 (end_t.abs_value_us < kx->foreign_key_expires.abs_value_us))
863 {
864 GNUNET_STATISTICS_update (GSC_stats,
865 gettext_noop ("# old ephemeral keys ignored"),
866 1,
867 GNUNET_NO);
868 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
869 "Received expired EPHEMERAL_KEY from %s\n",
870 GNUNET_i2s (&m->origin_identity));
871 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
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 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
887 return;
888 }
889 if (0 != memcmp (&m->origin_identity,
890 kx->peer,
891 sizeof(struct GNUNET_PeerIdentity)))
892 {
893 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
894 "Received EPHEMERAL_KEY from %s, but expected %s\n",
895 GNUNET_i2s (&m->origin_identity),
896 GNUNET_i2s_full (kx->peer));
897 GNUNET_break_op (0);
898 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
899 return;
900 }
901 if ((ntohl (m->purpose.size) !=
902 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
903 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
904 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
905 + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)
906 + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) ||
907 (GNUNET_OK !=
908 GNUNET_CRYPTO_eddsa_verify_ (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY,
909 &m->purpose,
910 &m->signature,
911 &m->origin_identity.public_key)))
912 {
913 /* invalid signature */
914 GNUNET_break_op (0);
915 GNUNET_STATISTICS_update (GSC_stats,
916 gettext_noop (
917 "# EPHEMERAL_KEYs rejected (bad signature)"),
918 1,
919 GNUNET_NO);
920 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
921 "Received EPHEMERAL_KEY from %s with bad signature\n",
922 GNUNET_i2s (&m->origin_identity));
923 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
924 return;
925 }
926 now = GNUNET_TIME_absolute_get ();
927 start_t = GNUNET_TIME_absolute_ntoh (m->creation_time);
928 if ((end_t.abs_value_us <
929 GNUNET_TIME_absolute_subtract (now, REKEY_TOLERANCE).abs_value_us) ||
930 (start_t.abs_value_us >
931 GNUNET_TIME_absolute_add (now, REKEY_TOLERANCE).abs_value_us))
932 {
933 GNUNET_log (
934 GNUNET_ERROR_TYPE_WARNING,
935 _ (
936 "EPHEMERAL_KEY from peer `%s' rejected as its validity range does not match our system time (%llu not in [%llu,%llu]).\n"),
937 GNUNET_i2s (kx->peer),
938 (unsigned long long) now.abs_value_us,
939 (unsigned long long) start_t.abs_value_us,
940 (unsigned long long) end_t.abs_value_us);
941 GNUNET_STATISTICS_update (GSC_stats,
942 gettext_noop (
943 "# EPHEMERAL_KEY messages rejected due to time"),
944 1,
945 GNUNET_NO);
946 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
947 return;
948 }
949#if DEBUG_KX
950 {
951 struct GNUNET_HashCode eh;
952
953 GNUNET_CRYPTO_hash (&m->ephemeral_key, sizeof(m->ephemeral_key), &eh);
954 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
955 "Received valid EPHEMERAL_KEY `%s' from `%s' in state %d.\n",
956 GNUNET_h2s (&eh),
957 GNUNET_i2s (kx->peer),
958 kx->status);
959 }
960#endif
961 GNUNET_STATISTICS_update (GSC_stats,
962 gettext_noop ("# valid ephemeral keys received"),
963 1,
964 GNUNET_NO);
965 kx->other_ephemeral_key = m->ephemeral_key;
966 kx->foreign_key_expires = end_t;
967 derive_session_keys (kx);
968
969 /* check if we still need to send the sender our key */
970 sender_status = (enum GNUNET_CORE_KxState) ntohl (m->sender_status);
971 switch (sender_status)
972 {
973 case GNUNET_CORE_KX_STATE_DOWN:
974 GNUNET_break_op (0);
975 break;
976
977 case GNUNET_CORE_KX_STATE_KEY_SENT:
978 /* fine, need to send our key after updating our status, see below */
979 GSC_SESSIONS_reinit (kx->peer);
980 break;
981
982 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
983 /* other peer already got our key, but typemap did go down */
984 GSC_SESSIONS_reinit (kx->peer);
985 break;
986
987 case GNUNET_CORE_KX_STATE_UP:
988 /* other peer already got our key, typemap NOT down */
989 break;
990
991 case GNUNET_CORE_KX_STATE_REKEY_SENT:
992 /* other peer already got our key, typemap NOT down */
993 break;
994
995 default:
996 GNUNET_break (0);
997 break;
998 }
999 /* check if we need to confirm everything is fine via PING + PONG */
1000 switch (kx->status)
1001 {
1002 case GNUNET_CORE_KX_STATE_DOWN:
1003 GNUNET_assert (NULL == kx->keep_alive_task);
1004 kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
1005 monitor_notify_all (kx);
1006 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1007 send_key (kx);
1008 else
1009 send_ping (kx);
1010 break;
1011
1012 case GNUNET_CORE_KX_STATE_KEY_SENT:
1013 GNUNET_assert (NULL == kx->keep_alive_task);
1014 kx->status = GNUNET_CORE_KX_STATE_KEY_RECEIVED;
1015 monitor_notify_all (kx);
1016 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1017 send_key (kx);
1018 else
1019 send_ping (kx);
1020 break;
1021
1022 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1023 GNUNET_assert (NULL == kx->keep_alive_task);
1024 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1025 send_key (kx);
1026 else
1027 send_ping (kx);
1028 break;
1029
1030 case GNUNET_CORE_KX_STATE_UP:
1031 kx->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1032 monitor_notify_all (kx);
1033 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1034 send_key (kx);
1035 else
1036 send_ping (kx);
1037 break;
1038
1039 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1040 if (GNUNET_CORE_KX_STATE_KEY_SENT == sender_status)
1041 send_key (kx);
1042 else
1043 send_ping (kx);
1044 break;
1045
1046 default:
1047 GNUNET_break (0);
1048 break;
1049 }
1050 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1051}
1052
1053
1054/**
1055 * We received a PING message. Validate and transmit
1056 * a PONG message.
1057 *
1058 * @param cls key exchange status for the corresponding peer
1059 * @param m the encrypted PING message itself
1060 */
1061static void
1062handle_ping (void *cls, const struct PingMessage *m)
1063{
1064 struct GSC_KeyExchangeInfo *kx = cls;
1065 struct PingMessage t;
1066 struct PongMessage tx;
1067 struct PongMessage *tp;
1068 struct GNUNET_MQ_Envelope *env;
1069 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1070
1071 GNUNET_STATISTICS_update (GSC_stats,
1072 gettext_noop ("# PING messages received"),
1073 1,
1074 GNUNET_NO);
1075 if ((kx->status != GNUNET_CORE_KX_STATE_KEY_RECEIVED) &&
1076 (kx->status != GNUNET_CORE_KX_STATE_UP) &&
1077 (kx->status != GNUNET_CORE_KX_STATE_REKEY_SENT))
1078 {
1079 /* ignore */
1080 GNUNET_STATISTICS_update (GSC_stats,
1081 gettext_noop (
1082 "# PING messages dropped (out of order)"),
1083 1,
1084 GNUNET_NO);
1085 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1086 return;
1087 }
1088 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1089 "Core service receives PING request from `%s'.\n",
1090 GNUNET_i2s (kx->peer));
1091 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1092 if (GNUNET_OK != do_decrypt (kx,
1093 &iv,
1094 &m->target,
1095 &t.target,
1096 sizeof(struct PingMessage)
1097 - ((void *) &m->target - (void *) m)))
1098 {
1099 GNUNET_break_op (0);
1100 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1101 return;
1102 }
1103 if (0 !=
1104 memcmp (&t.target, &GSC_my_identity, sizeof(struct GNUNET_PeerIdentity)))
1105 {
1106 if (GNUNET_CORE_KX_STATE_REKEY_SENT != kx->status)
1107 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1108 "Decryption of PING from peer `%s' failed, PING for `%s'?\n",
1109 GNUNET_i2s (kx->peer),
1110 GNUNET_i2s2 (&t.target));
1111 else
1112 GNUNET_log (
1113 GNUNET_ERROR_TYPE_DEBUG,
1114 "Decryption of PING from peer `%s' failed after rekey (harmless)\n",
1115 GNUNET_i2s (kx->peer));
1116 GNUNET_break_op (0);
1117 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1118 return;
1119 }
1120 /* construct PONG */
1121 tx.reserved = 0;
1122 tx.challenge = t.challenge;
1123 tx.target = t.target;
1124 env = GNUNET_MQ_msg (tp, GNUNET_MESSAGE_TYPE_CORE_PONG);
1125 tp->iv_seed = calculate_seed (kx);
1126 derive_pong_iv (&iv, &kx->encrypt_key, tp->iv_seed, t.challenge, kx->peer);
1127 do_encrypt (kx,
1128 &iv,
1129 &tx.challenge,
1130 &tp->challenge,
1131 sizeof(struct PongMessage)
1132 - ((void *) &tp->challenge - (void *) tp));
1133 GNUNET_STATISTICS_update (GSC_stats,
1134 gettext_noop ("# PONG messages created"),
1135 1,
1136 GNUNET_NO);
1137 GNUNET_MQ_send (kx->mq, env);
1138}
1139
1140
1141/**
1142 * Task triggered when a neighbour entry is about to time out
1143 * (and we should prevent this by sending a PING).
1144 *
1145 * @param cls the `struct GSC_KeyExchangeInfo`
1146 */
1147static void
1148send_keep_alive (void *cls)
1149{
1150 struct GSC_KeyExchangeInfo *kx = cls;
1151 struct GNUNET_TIME_Relative retry;
1152 struct GNUNET_TIME_Relative left;
1153
1154 kx->keep_alive_task = NULL;
1155 left = GNUNET_TIME_absolute_get_remaining (kx->timeout);
1156 if (0 == left.rel_value_us)
1157 {
1158 GNUNET_STATISTICS_update (GSC_stats,
1159 gettext_noop ("# sessions terminated by timeout"),
1160 1,
1161 GNUNET_NO);
1162 GSC_SESSIONS_end (kx->peer);
1163 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1164 monitor_notify_all (kx);
1165 send_key (kx);
1166 return;
1167 }
1168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1169 "Sending KEEPALIVE to `%s'\n",
1170 GNUNET_i2s (kx->peer));
1171 GNUNET_STATISTICS_update (GSC_stats,
1172 gettext_noop ("# keepalive messages sent"),
1173 1,
1174 GNUNET_NO);
1175 setup_fresh_ping (kx);
1176 send_ping (kx);
1177 retry = GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2),
1178 MIN_PING_FREQUENCY);
1179 kx->keep_alive_task =
1180 GNUNET_SCHEDULER_add_delayed (retry, &send_keep_alive, kx);
1181}
1182
1183
1184/**
1185 * We've seen a valid message from the other peer.
1186 * Update the time when the session would time out
1187 * and delay sending our keep alive message further.
1188 *
1189 * @param kx key exchange where we saw activity
1190 */
1191static void
1192update_timeout (struct GSC_KeyExchangeInfo *kx)
1193{
1194 struct GNUNET_TIME_Relative delta;
1195
1196 kx->timeout =
1197 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
1198 delta =
1199 GNUNET_TIME_absolute_get_difference (kx->last_notify_timeout, kx->timeout);
1200 if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
1201 {
1202 /* we only notify monitors about timeout changes if those
1203 are bigger than the threshold (5s) */
1204 monitor_notify_all (kx);
1205 }
1206 if (NULL != kx->keep_alive_task)
1207 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1208 kx->keep_alive_task = GNUNET_SCHEDULER_add_delayed (
1209 GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2),
1210 &send_keep_alive,
1211 kx);
1212}
1213
1214
1215/**
1216 * We received a PONG message. Validate and update our status.
1217 *
1218 * @param kx key exchange context for the the PONG
1219 * @param m the encrypted PONG message itself
1220 */
1221static void
1222handle_pong (void *cls, const struct PongMessage *m)
1223{
1224 struct GSC_KeyExchangeInfo *kx = cls;
1225 struct PongMessage t;
1226 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1227
1228 GNUNET_STATISTICS_update (GSC_stats,
1229 gettext_noop ("# PONG messages received"),
1230 1,
1231 GNUNET_NO);
1232 switch (kx->status)
1233 {
1234 case GNUNET_CORE_KX_STATE_DOWN:
1235 GNUNET_STATISTICS_update (GSC_stats,
1236 gettext_noop (
1237 "# PONG messages dropped (connection down)"),
1238 1,
1239 GNUNET_NO);
1240 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1241 return;
1242
1243 case GNUNET_CORE_KX_STATE_KEY_SENT:
1244 GNUNET_STATISTICS_update (GSC_stats,
1245 gettext_noop (
1246 "# PONG messages dropped (out of order)"),
1247 1,
1248 GNUNET_NO);
1249 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1250 return;
1251
1252 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1253 break;
1254
1255 case GNUNET_CORE_KX_STATE_UP:
1256 break;
1257
1258 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1259 break;
1260
1261 default:
1262 GNUNET_break (0);
1263 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1264 return;
1265 }
1266 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1267 "Core service receives PONG response from `%s'.\n",
1268 GNUNET_i2s (kx->peer));
1269 /* mark as garbage, just to be sure */
1270 memset (&t, 255, sizeof(t));
1271 derive_pong_iv (&iv,
1272 &kx->decrypt_key,
1273 m->iv_seed,
1274 kx->ping_challenge,
1275 &GSC_my_identity);
1276 if (GNUNET_OK != do_decrypt (kx,
1277 &iv,
1278 &m->challenge,
1279 &t.challenge,
1280 sizeof(struct PongMessage)
1281 - ((void *) &m->challenge - (void *) m)))
1282 {
1283 GNUNET_break_op (0);
1284 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1285 return;
1286 }
1287 GNUNET_STATISTICS_update (GSC_stats,
1288 gettext_noop ("# PONG messages decrypted"),
1289 1,
1290 GNUNET_NO);
1291 if ((0 !=
1292 memcmp (&t.target, kx->peer, sizeof(struct GNUNET_PeerIdentity))) ||
1293 (kx->ping_challenge != t.challenge))
1294 {
1295 /* PONG malformed */
1296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1297 "Received malformed PONG wanted sender `%s' with challenge %u\n",
1298 GNUNET_i2s (kx->peer),
1299 (unsigned int) kx->ping_challenge);
1300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1301 "Received malformed PONG received from `%s' with challenge %u\n",
1302 GNUNET_i2s (&t.target),
1303 (unsigned int) t.challenge);
1304 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1305 return;
1306 }
1307 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1308 "Received valid PONG from `%s'\n",
1309 GNUNET_i2s (kx->peer));
1310 /* no need to resend key any longer */
1311 if (NULL != kx->retry_set_key_task)
1312 {
1313 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1314 kx->retry_set_key_task = NULL;
1315 }
1316 switch (kx->status)
1317 {
1318 case GNUNET_CORE_KX_STATE_DOWN:
1319 GNUNET_assert (0); /* should be impossible */
1320 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1321 return;
1322
1323 case GNUNET_CORE_KX_STATE_KEY_SENT:
1324 GNUNET_assert (0); /* should be impossible */
1325 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1326 return;
1327
1328 case GNUNET_CORE_KX_STATE_KEY_RECEIVED:
1329 GNUNET_STATISTICS_update (GSC_stats,
1330 gettext_noop (
1331 "# session keys confirmed via PONG"),
1332 1,
1333 GNUNET_NO);
1334 kx->status = GNUNET_CORE_KX_STATE_UP;
1335 monitor_notify_all (kx);
1336 GSC_SESSIONS_create (kx->peer, kx);
1337 GNUNET_assert (NULL == kx->keep_alive_task);
1338 update_timeout (kx);
1339 break;
1340
1341 case GNUNET_CORE_KX_STATE_UP:
1342 GNUNET_STATISTICS_update (GSC_stats,
1343 gettext_noop ("# timeouts prevented via PONG"),
1344 1,
1345 GNUNET_NO);
1346 update_timeout (kx);
1347 break;
1348
1349 case GNUNET_CORE_KX_STATE_REKEY_SENT:
1350 GNUNET_STATISTICS_update (GSC_stats,
1351 gettext_noop (
1352 "# rekey operations confirmed via PONG"),
1353 1,
1354 GNUNET_NO);
1355 kx->status = GNUNET_CORE_KX_STATE_UP;
1356 monitor_notify_all (kx);
1357 update_timeout (kx);
1358 break;
1359
1360 default:
1361 GNUNET_break (0);
1362 break;
1363 }
1364}
1365
1366
1367/**
1368 * Send our key to the other peer.
1369 *
1370 * @param kx key exchange context
1371 */
1372static void
1373send_key (struct GSC_KeyExchangeInfo *kx)
1374{
1375 struct GNUNET_MQ_Envelope *env;
1376
1377 GNUNET_assert (GNUNET_CORE_KX_STATE_DOWN != kx->status);
1378 if (NULL != kx->retry_set_key_task)
1379 {
1380 GNUNET_SCHEDULER_cancel (kx->retry_set_key_task);
1381 kx->retry_set_key_task = NULL;
1382 }
1383 /* always update sender status in SET KEY message */
1384#if DEBUG_KX
1385 {
1386 struct GNUNET_HashCode hc;
1387
1388 GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1389 sizeof(current_ekm.ephemeral_key),
1390 &hc);
1391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1392 "Sending EPHEMERAL_KEY %s to `%s' (my status: %d)\n",
1393 GNUNET_h2s (&hc),
1394 GNUNET_i2s (kx->peer),
1395 kx->status);
1396 }
1397#endif
1398 current_ekm.sender_status = htonl ((int32_t) (kx->status));
1399 env = GNUNET_MQ_msg_copy (&current_ekm.header);
1400 GNUNET_MQ_send (kx->mq, env);
1401 if (GNUNET_CORE_KX_STATE_KEY_SENT != kx->status)
1402 send_ping (kx);
1403 kx->retry_set_key_task =
1404 GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency,
1405 &set_key_retry_task,
1406 kx);
1407}
1408
1409
1410void
1411GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
1412 const void *payload,
1413 size_t payload_size)
1414{
1415 size_t used = payload_size + sizeof(struct EncryptedMessage);
1416 char pbuf[used]; /* plaintext */
1417 struct EncryptedMessage *em; /* encrypted message */
1418 struct EncryptedMessage *ph; /* plaintext header */
1419 struct GNUNET_MQ_Envelope *env;
1420 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1421 struct GNUNET_CRYPTO_AuthKey auth_key;
1422
1423 ph = (struct EncryptedMessage *) pbuf;
1424 ph->sequence_number = htonl (++kx->last_sequence_number_sent);
1425 ph->iv_seed = calculate_seed (kx);
1426 ph->reserved = 0;
1427 ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1428 GNUNET_memcpy (&ph[1], payload, payload_size);
1429 env = GNUNET_MQ_msg_extra (em,
1430 payload_size,
1431 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE);
1432 em->iv_seed = ph->iv_seed;
1433 derive_iv (&iv, &kx->encrypt_key, ph->iv_seed, kx->peer);
1434 GNUNET_assert (GNUNET_OK == do_encrypt (kx,
1435 &iv,
1436 &ph->sequence_number,
1437 &em->sequence_number,
1438 used - ENCRYPTED_HEADER_SIZE));
1439#if DEBUG_KX
1440 {
1441 struct GNUNET_HashCode hc;
1442
1443 GNUNET_CRYPTO_hash (&ph->sequence_number,
1444 used - ENCRYPTED_HEADER_SIZE,
1445 &hc);
1446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1447 "Encrypted payload `%s' of %u bytes for %s\n",
1448 GNUNET_h2s (&hc),
1449 (unsigned int) (used - ENCRYPTED_HEADER_SIZE),
1450 GNUNET_i2s (kx->peer));
1451 }
1452#endif
1453 derive_auth_key (&auth_key, &kx->encrypt_key, ph->iv_seed);
1454 GNUNET_CRYPTO_hmac (&auth_key,
1455 &em->sequence_number,
1456 used - ENCRYPTED_HEADER_SIZE,
1457 &em->hmac);
1458#if DEBUG_KX
1459 {
1460 struct GNUNET_HashCode hc;
1461
1462 GNUNET_CRYPTO_hash (&auth_key, sizeof(auth_key), &hc);
1463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1464 "For peer %s, used AC %s to create hmac %s\n",
1465 GNUNET_i2s (kx->peer),
1466 GNUNET_h2s (&hc),
1467 GNUNET_h2s2 (&em->hmac));
1468 }
1469#endif
1470 kx->has_excess_bandwidth = GNUNET_NO;
1471 GNUNET_MQ_send (kx->mq, env);
1472}
1473
1474
1475/**
1476 * We received an encrypted message. Check that it is
1477 * well-formed (size-wise).
1478 *
1479 * @param cls key exchange context for encrypting the message
1480 * @param m encrypted message
1481 * @return #GNUNET_OK if @a msg is well-formed (size-wise)
1482 */
1483static int
1484check_encrypted (void *cls, const struct EncryptedMessage *m)
1485{
1486 uint16_t size = ntohs (m->header.size) - sizeof(*m);
1487
1488 if (size < sizeof(struct GNUNET_MessageHeader))
1489 {
1490 GNUNET_break_op (0);
1491 return GNUNET_SYSERR;
1492 }
1493 return GNUNET_OK;
1494}
1495
1496
1497/**
1498 * We received an encrypted message. Decrypt, validate and
1499 * pass on to the appropriate clients.
1500 *
1501 * @param cls key exchange context for encrypting the message
1502 * @param m encrypted message
1503 */
1504static void
1505handle_encrypted (void *cls, const struct EncryptedMessage *m)
1506{
1507 struct GSC_KeyExchangeInfo *kx = cls;
1508 struct EncryptedMessage *pt; /* plaintext */
1509 struct GNUNET_HashCode ph;
1510 uint32_t snum;
1511 struct GNUNET_TIME_Absolute t;
1512 struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
1513 struct GNUNET_CRYPTO_AuthKey auth_key;
1514 uint16_t size = ntohs (m->header.size);
1515 char buf[size] GNUNET_ALIGN;
1516
1517 if (GNUNET_CORE_KX_STATE_UP != kx->status)
1518 {
1519 GNUNET_STATISTICS_update (GSC_stats,
1520 gettext_noop (
1521 "# DATA message dropped (out of order)"),
1522 1,
1523 GNUNET_NO);
1524 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1525 return;
1526 }
1527 if (0 ==
1528 GNUNET_TIME_absolute_get_remaining (kx->foreign_key_expires).rel_value_us)
1529 {
1530 GNUNET_log (
1531 GNUNET_ERROR_TYPE_WARNING,
1532 _ (
1533 "Session to peer `%s' went down due to key expiration (should not happen)\n"),
1534 GNUNET_i2s (kx->peer));
1535 GNUNET_STATISTICS_update (GSC_stats,
1536 gettext_noop (
1537 "# sessions terminated by key expiration"),
1538 1,
1539 GNUNET_NO);
1540 GSC_SESSIONS_end (kx->peer);
1541 if (NULL != kx->keep_alive_task)
1542 {
1543 GNUNET_SCHEDULER_cancel (kx->keep_alive_task);
1544 kx->keep_alive_task = NULL;
1545 }
1546 kx->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1547 monitor_notify_all (kx);
1548 send_key (kx);
1549 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1550 return;
1551 }
1552
1553 /* validate hash */
1554#if DEBUG_KX
1555 {
1556 struct GNUNET_HashCode hc;
1557
1558 GNUNET_CRYPTO_hash (&m->sequence_number, size - ENCRYPTED_HEADER_SIZE, &hc);
1559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1560 "Received encrypted payload `%s' of %u bytes from %s\n",
1561 GNUNET_h2s (&hc),
1562 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1563 GNUNET_i2s (kx->peer));
1564 }
1565#endif
1566 derive_auth_key (&auth_key, &kx->decrypt_key, m->iv_seed);
1567 GNUNET_CRYPTO_hmac (&auth_key,
1568 &m->sequence_number,
1569 size - ENCRYPTED_HEADER_SIZE,
1570 &ph);
1571#if DEBUG_KX
1572 {
1573 struct GNUNET_HashCode hc;
1574
1575 GNUNET_CRYPTO_hash (&auth_key, sizeof(auth_key), &hc);
1576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1577 "For peer %s, used AC %s to verify hmac %s\n",
1578 GNUNET_i2s (kx->peer),
1579 GNUNET_h2s (&hc),
1580 GNUNET_h2s2 (&m->hmac));
1581 }
1582#endif
1583 if (0 != memcmp (&ph, &m->hmac, sizeof(struct GNUNET_HashCode)))
1584 {
1585 /* checksum failed */
1586 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1587 "Failed checksum validation for a message from `%s'\n",
1588 GNUNET_i2s (kx->peer));
1589 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1590 return;
1591 }
1592 derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity);
1593 /* decrypt */
1594 if (GNUNET_OK != do_decrypt (kx,
1595 &iv,
1596 &m->sequence_number,
1597 &buf[ENCRYPTED_HEADER_SIZE],
1598 size - ENCRYPTED_HEADER_SIZE))
1599 {
1600 GNUNET_break_op (0);
1601 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1602 return;
1603 }
1604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1605 "Decrypted %u bytes from %s\n",
1606 (unsigned int) (size - ENCRYPTED_HEADER_SIZE),
1607 GNUNET_i2s (kx->peer));
1608 pt = (struct EncryptedMessage *) buf;
1609
1610 /* validate sequence number */
1611 snum = ntohl (pt->sequence_number);
1612 if (kx->last_sequence_number_received == snum)
1613 {
1614 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1615 "Received duplicate message, ignoring.\n");
1616 /* duplicate, ignore */
1617 GNUNET_STATISTICS_update (GSC_stats,
1618 gettext_noop ("# bytes dropped (duplicates)"),
1619 size,
1620 GNUNET_NO);
1621 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1622 return;
1623 }
1624 if ((kx->last_sequence_number_received > snum) &&
1625 (kx->last_sequence_number_received - snum > 32))
1626 {
1627 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1628 "Received ancient out of sequence message, ignoring.\n");
1629 /* ancient out of sequence, ignore */
1630 GNUNET_STATISTICS_update (GSC_stats,
1631 gettext_noop (
1632 "# bytes dropped (out of sequence)"),
1633 size,
1634 GNUNET_NO);
1635 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1636 return;
1637 }
1638 if (kx->last_sequence_number_received > snum)
1639 {
1640 uint32_t rotbit = 1U << (kx->last_sequence_number_received - snum - 1);
1641
1642 if ((kx->last_packets_bitmap & rotbit) != 0)
1643 {
1644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1645 "Received duplicate message, ignoring.\n");
1646 GNUNET_STATISTICS_update (GSC_stats,
1647 gettext_noop ("# bytes dropped (duplicates)"),
1648 size,
1649 GNUNET_NO);
1650 /* duplicate, ignore */
1651 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1652 return;
1653 }
1654 kx->last_packets_bitmap |= rotbit;
1655 }
1656 if (kx->last_sequence_number_received < snum)
1657 {
1658 unsigned int shift = (snum - kx->last_sequence_number_received);
1659
1660 if (shift >= 8 * sizeof(kx->last_packets_bitmap))
1661 kx->last_packets_bitmap = 0;
1662 else
1663 kx->last_packets_bitmap <<= shift;
1664 kx->last_sequence_number_received = snum;
1665 }
1666
1667 /* check timestamp */
1668 t = GNUNET_TIME_absolute_ntoh (pt->timestamp);
1669 if (GNUNET_TIME_absolute_get_duration (t).rel_value_us >
1670 MAX_MESSAGE_AGE.rel_value_us)
1671 {
1672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1673 "Message received far too old (%s). Content ignored.\n",
1674 GNUNET_STRINGS_relative_time_to_string (
1675 GNUNET_TIME_absolute_get_duration (t),
1676 GNUNET_YES));
1677 GNUNET_STATISTICS_update (GSC_stats,
1678 gettext_noop (
1679 "# bytes dropped (ancient message)"),
1680 size,
1681 GNUNET_NO);
1682 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1683 return;
1684 }
1685
1686 /* process decrypted message(s) */
1687 update_timeout (kx);
1688 GNUNET_STATISTICS_update (GSC_stats,
1689 gettext_noop ("# bytes of payload decrypted"),
1690 size - sizeof(struct EncryptedMessage),
1691 GNUNET_NO);
1692 if (GNUNET_OK !=
1693 GNUNET_MST_from_buffer (kx->mst,
1694 &buf[sizeof(struct EncryptedMessage)],
1695 size - sizeof(struct EncryptedMessage),
1696 GNUNET_YES,
1697 GNUNET_NO))
1698 GNUNET_break_op (0);
1699
1700 GNUNET_TRANSPORT_core_receive_continue (transport, kx->peer);
1701}
1702
1703
1704/**
1705 * Setup the message that links the ephemeral key to our persistent
1706 * public key and generate the appropriate signature.
1707 */
1708static void
1709sign_ephemeral_key ()
1710{
1711 current_ekm.header.size = htons (sizeof(struct EphemeralKeyMessage));
1712 current_ekm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY);
1713 current_ekm.sender_status = 0; /* to be set later */
1714 current_ekm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY);
1715 current_ekm.purpose.size =
1716 htonl (sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
1717 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1718 + sizeof(struct GNUNET_TIME_AbsoluteNBO)
1719 + sizeof(struct GNUNET_CRYPTO_EcdhePublicKey)
1720 + sizeof(struct GNUNET_PeerIdentity));
1721 current_ekm.creation_time =
1722 GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
1723 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (GSC_cfg,
1724 "core",
1725 "USE_EPHEMERAL_KEYS"))
1726 {
1727 current_ekm.expiration_time =
1728 GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (
1729 GNUNET_TIME_relative_add (REKEY_FREQUENCY,
1730 REKEY_TOLERANCE)));
1731 }
1732 else
1733 {
1734 current_ekm.expiration_time =
1735 GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
1736 }
1737 GNUNET_CRYPTO_ecdhe_key_get_public (&my_ephemeral_key,
1738 &current_ekm.ephemeral_key);
1739 current_ekm.origin_identity = GSC_my_identity;
1740 GNUNET_assert (GNUNET_OK ==
1741 GNUNET_CRYPTO_eddsa_sign_ (&my_private_key,
1742 &current_ekm.purpose,
1743 &current_ekm.signature));
1744}
1745
1746
1747/**
1748 * Task run to trigger rekeying.
1749 *
1750 * @param cls closure, NULL
1751 */
1752static void
1753do_rekey (void *cls)
1754{
1755 struct GSC_KeyExchangeInfo *pos;
1756
1757 rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, &do_rekey, NULL);
1758 GNUNET_CRYPTO_ecdhe_key_create (&my_ephemeral_key);
1759 sign_ephemeral_key ();
1760 {
1761 struct GNUNET_HashCode eh;
1762
1763 GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1764 sizeof(current_ekm.ephemeral_key),
1765 &eh);
1766 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Rekeying to %s\n", GNUNET_h2s (&eh));
1767 }
1768 for (pos = kx_head; NULL != pos; pos = pos->next)
1769 {
1770 if (GNUNET_CORE_KX_STATE_UP == pos->status)
1771 {
1772 pos->status = GNUNET_CORE_KX_STATE_REKEY_SENT;
1773 monitor_notify_all (pos);
1774 derive_session_keys (pos);
1775 }
1776 if (GNUNET_CORE_KX_STATE_DOWN == pos->status)
1777 {
1778 pos->status = GNUNET_CORE_KX_STATE_KEY_SENT;
1779 monitor_notify_all (pos);
1780 }
1781 monitor_notify_all (pos);
1782 send_key (pos);
1783 }
1784}
1785
1786
1787/**
1788 * Initialize KX subsystem.
1789 *
1790 * @param pk private key to use for the peer
1791 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
1792 */
1793int
1794GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
1795{
1796 struct GNUNET_MQ_MessageHandler handlers[] = {
1797 GNUNET_MQ_hd_fixed_size (ephemeral_key,
1798 GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY,
1799 struct EphemeralKeyMessage,
1800 NULL),
1801 GNUNET_MQ_hd_fixed_size (ping,
1802 GNUNET_MESSAGE_TYPE_CORE_PING,
1803 struct PingMessage,
1804 NULL),
1805 GNUNET_MQ_hd_fixed_size (pong,
1806 GNUNET_MESSAGE_TYPE_CORE_PONG,
1807 struct PongMessage,
1808 NULL),
1809 GNUNET_MQ_hd_var_size (encrypted,
1810 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE,
1811 struct EncryptedMessage,
1812 NULL),
1813 GNUNET_MQ_handler_end ()
1814 };
1815
1816 my_private_key = *pk;
1817 GNUNET_CRYPTO_eddsa_key_get_public (&my_private_key,
1818 &GSC_my_identity.public_key);
1819 GNUNET_CRYPTO_ecdhe_key_create (&my_ephemeral_key);
1820 sign_ephemeral_key ();
1821 {
1822 struct GNUNET_HashCode eh;
1823
1824 GNUNET_CRYPTO_hash (&current_ekm.ephemeral_key,
1825 sizeof(current_ekm.ephemeral_key),
1826 &eh);
1827 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1828 "Starting with ephemeral key %s\n",
1829 GNUNET_h2s (&eh));
1830 }
1831
1832 nc = GNUNET_notification_context_create (1);
1833 rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, &do_rekey, NULL);
1834 transport =
1835 GNUNET_TRANSPORT_core_connect (GSC_cfg,
1836 &GSC_my_identity,
1837 handlers,
1838 NULL,
1839 &handle_transport_notify_connect,
1840 &handle_transport_notify_disconnect);
1841 if (NULL == transport)
1842 {
1843 GSC_KX_done ();
1844 return GNUNET_SYSERR;
1845 }
1846 return GNUNET_OK;
1847}
1848
1849
1850/**
1851 * Shutdown KX subsystem.
1852 */
1853void
1854GSC_KX_done ()
1855{
1856 if (NULL != transport)
1857 {
1858 GNUNET_TRANSPORT_core_disconnect (transport);
1859 transport = NULL;
1860 }
1861 if (NULL != rekey_task)
1862 {
1863 GNUNET_SCHEDULER_cancel (rekey_task);
1864 rekey_task = NULL;
1865 }
1866 memset (&my_ephemeral_key,
1867 0,
1868 sizeof (my_ephemeral_key));
1869 memset (&my_private_key,
1870 0,
1871 sizeof (my_private_key));
1872 if (NULL != nc)
1873 {
1874 GNUNET_notification_context_destroy (nc);
1875 nc = NULL;
1876 }
1877}
1878
1879
1880/**
1881 * Check how many messages are queued for the given neighbour.
1882 *
1883 * @param kxinfo data about neighbour to check
1884 * @return number of items in the message queue
1885 */
1886unsigned int
1887GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo)
1888{
1889 return GNUNET_MQ_get_length (kxinfo->mq);
1890}
1891
1892
1893int
1894GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo)
1895{
1896 return kxinfo->has_excess_bandwidth;
1897}
1898
1899
1900/**
1901 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
1902 * request type, the client does not have to have transmitted an INIT
1903 * request. All current peers are returned, regardless of which
1904 * message types they accept.
1905 *
1906 * @param mq message queue to add for monitoring
1907 */
1908void
1909GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq)
1910{
1911 struct GNUNET_MQ_Envelope *env;
1912 struct MonitorNotifyMessage *done_msg;
1913 struct GSC_KeyExchangeInfo *kx;
1914
1915 GNUNET_notification_context_add (nc, mq);
1916 for (kx = kx_head; NULL != kx; kx = kx->next)
1917 {
1918 struct GNUNET_MQ_Envelope *env;
1919 struct MonitorNotifyMessage *msg;
1920
1921 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
1922 msg->state = htonl ((uint32_t) kx->status);
1923 msg->peer = *kx->peer;
1924 msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
1925 GNUNET_MQ_send (mq, env);
1926 }
1927 env = GNUNET_MQ_msg (done_msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY);
1928 done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
1929 done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS);
1930 GNUNET_MQ_send (mq, env);
1931}
1932
1933
1934/* 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 8bcac3f68..000000000
--- a/src/core/gnunet-service-core_kx.h
+++ /dev/null
@@ -1,102 +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
31
32/**
33 * Information about the status of a key exchange with another peer.
34 */
35struct GSC_KeyExchangeInfo;
36
37
38/**
39 * Encrypt and transmit a message with the given payload.
40 *
41 * @param kx key exchange context
42 * @param payload payload of the message
43 * @param payload_size number of bytes in 'payload'
44 */
45void
46GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx,
47 const void *payload,
48 size_t payload_size);
49
50
51/**
52 * Initialize KX subsystem.
53 *
54 * @param pk private key to use for the peer
55 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
56 */
57int
58GSC_KX_init (struct GNUNET_CRYPTO_EddsaPrivateKey *pk);
59
60
61/**
62 * Shutdown KX subsystem.
63 */
64void
65GSC_KX_done (void);
66
67
68/**
69 * Check if the given neighbour has excess bandwidth available.
70 *
71 * @param target neighbour to check
72 * @return #GNUNET_YES if excess bandwidth is available, #GNUNET_NO if not
73 */
74int
75GSC_NEIGHBOURS_check_excess_bandwidth (const struct
76 GSC_KeyExchangeInfo *target);
77
78
79/**
80 * Check how many messages are queued for the given neighbour.
81 *
82 * @param target neighbour to check
83 * @return number of items in the message queue
84 */
85unsigned int
86GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *target);
87
88
89/**
90 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this
91 * request type, the client does not have to have transmitted an INIT
92 * request. All current peers are returned, regardless of which
93 * message types they accept.
94 *
95 * @param mq message queue to add for monitoring
96 */
97void
98GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq);
99
100
101#endif
102/* 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 e103c89f5..000000000
--- a/src/core/gnunet-service-core_sessions.c
+++ /dev/null
@@ -1,1028 +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
858void
859GSC_SESSIONS_transmit (struct GSC_ClientActiveRequest *car,
860 const struct GNUNET_MessageHeader *msg,
861 enum GNUNET_MQ_PriorityPreferences priority)
862{
863 struct Session *session;
864 struct SessionMessageEntry *sme;
865 struct SessionMessageEntry *pos;
866 size_t msize;
867
868 session = find_session (&car->target);
869 if (NULL == session)
870 return;
871 msize = ntohs (msg->size);
872 sme = GNUNET_malloc (sizeof(struct SessionMessageEntry) + msize);
873 GNUNET_memcpy (&sme[1], msg, msize);
874 sme->size = msize;
875 sme->priority = priority;
876 if (0 != (GNUNET_MQ_PREF_CORK_ALLOWED & priority))
877 {
878 sme->deadline =
879 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_MAX_CORK_DELAY);
880 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
881 "Message corked, delaying transmission\n");
882 }
883 pos = session->sme_head;
884 while ((NULL != pos) && (pos->priority >= sme->priority))
885 pos = pos->next;
886 if (NULL == pos)
887 GNUNET_CONTAINER_DLL_insert_tail (session->sme_head,
888 session->sme_tail,
889 sme);
890 else
891 GNUNET_CONTAINER_DLL_insert_after (session->sme_head,
892 session->sme_tail,
893 pos->prev,
894 sme);
895 try_transmission (session);
896}
897
898
899void
900GSC_SESSIONS_set_typemap (const struct GNUNET_PeerIdentity *peer,
901 const struct GNUNET_MessageHeader *msg)
902{
903 struct Session *session;
904 struct GSC_TypeMap *nmap;
905 struct SessionMessageEntry *sme;
906 struct TypeMapConfirmationMessage *tmc;
907
908 nmap = GSC_TYPEMAP_get_from_message (msg);
909 if (NULL == nmap)
910 {
911 GNUNET_break_op (0);
912 return; /* malformed */
913 }
914 session = find_session (peer);
915 if (NULL == session)
916 {
917 GSC_TYPEMAP_destroy (nmap);
918 GNUNET_break (0);
919 return;
920 }
921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
922 "Received TYPEMAP from %s\n",
923 GNUNET_i2s (session->peer));
924 for (sme = session->sme_head; NULL != sme; sme = sme->next)
925 {
926 if (GNUNET_YES == sme->is_typemap_confirm)
927 {
928 GNUNET_CONTAINER_DLL_remove (session->sme_head, session->sme_tail, sme);
929 GNUNET_free (sme);
930 break;
931 }
932 }
933 sme = GNUNET_malloc (sizeof(struct SessionMessageEntry)
934 + sizeof(struct TypeMapConfirmationMessage));
935 sme->deadline = GNUNET_TIME_absolute_get ();
936 sme->size = sizeof(struct TypeMapConfirmationMessage);
937 sme->priority = GNUNET_MQ_PRIO_CRITICAL_CONTROL;
938 sme->is_typemap_confirm = GNUNET_YES;
939 tmc = (struct TypeMapConfirmationMessage *) &sme[1];
940 tmc->header.size = htons (sizeof(struct TypeMapConfirmationMessage));
941 tmc->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_CONFIRM_TYPE_MAP);
942 tmc->reserved = htonl (0);
943 GSC_TYPEMAP_hash (nmap, &tmc->tm_hash);
944 GNUNET_CONTAINER_DLL_insert (session->sme_head, session->sme_tail, sme);
945 try_transmission (session);
946 GSC_CLIENTS_notify_clients_about_neighbour (peer, session->tmap, nmap);
947 GSC_TYPEMAP_destroy (session->tmap);
948 session->tmap = nmap;
949}
950
951
952/**
953 * The given peer send a message of the specified type. Make sure the
954 * respective bit is set in its type-map and that clients are notified
955 * about the session.
956 *
957 * @param peer peer this is about
958 * @param type type of the message
959 */
960void
961GSC_SESSIONS_add_to_typemap (const struct GNUNET_PeerIdentity *peer,
962 uint16_t type)
963{
964 struct Session *session;
965 struct GSC_TypeMap *nmap;
966
967 if (0 == memcmp (peer, &GSC_my_identity, sizeof(struct GNUNET_PeerIdentity)))
968 return;
969 session = find_session (peer);
970 GNUNET_assert (NULL != session);
971 if (GNUNET_YES == GSC_TYPEMAP_test_match (session->tmap, &type, 1))
972 return; /* already in it */
973 nmap = GSC_TYPEMAP_extend (session->tmap, &type, 1);
974 GSC_CLIENTS_notify_clients_about_neighbour (peer, session->tmap, nmap);
975 GSC_TYPEMAP_destroy (session->tmap);
976 session->tmap = nmap;
977}
978
979
980/**
981 * Initialize sessions subsystem.
982 */
983void
984GSC_SESSIONS_init ()
985{
986 sessions = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_YES);
987}
988
989
990/**
991 * Helper function for #GSC_SESSIONS_done() to free all
992 * active sessions.
993 *
994 * @param cls NULL
995 * @param key identity of the connected peer
996 * @param value the `struct Session` for the peer
997 * @return #GNUNET_OK (continue to iterate)
998 */
999static int
1000free_session_helper (void *cls,
1001 const struct GNUNET_PeerIdentity *key,
1002 void *value)
1003{
1004 /* struct Session *session = value; */
1005
1006 GSC_SESSIONS_end (key);
1007 return GNUNET_OK;
1008}
1009
1010
1011/**
1012 * Shutdown sessions subsystem.
1013 */
1014void
1015GSC_SESSIONS_done ()
1016{
1017 if (NULL != sessions)
1018 {
1019 GNUNET_CONTAINER_multipeermap_iterate (sessions,
1020 &free_session_helper,
1021 NULL);
1022 GNUNET_CONTAINER_multipeermap_destroy (sessions);
1023 sessions = NULL;
1024 }
1025}
1026
1027
1028/* 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 200a84b23..000000000
--- a/src/core/gnunet-service-core_typemap.c
+++ /dev/null
@@ -1,370 +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-service-core.h"
29#include "gnunet-service-core_sessions.h"
30#include "gnunet-service-core_typemap.h"
31#include <zlib.h>
32
33
34/**
35 * A type map describing which messages a given neighbour is able
36 * to process.
37 */
38struct GSC_TypeMap
39{
40 uint32_t bits[(UINT16_MAX + 1) / 32];
41};
42
43/**
44 * Bitmap of message types this peer is able to handle.
45 */
46static struct GSC_TypeMap my_type_map;
47
48/**
49 * Counters for message types this peer is able to handle.
50 */
51static uint8_t map_counters[UINT16_MAX + 1];
52
53/**
54 * Current hash of our (uncompressed) type map.
55 * Lazily computed when needed.
56 */
57static struct GNUNET_HashCode my_tm_hash;
58
59/**
60 * Is #my_tm_hash() current with respect to our type map?
61 */
62static int hash_current;
63
64
65/**
66 * Our type map changed, recompute its hash.
67 */
68static void
69rehash_typemap ()
70{
71 hash_current = GNUNET_NO;
72}
73
74
75/**
76 * Hash the contents of a type map.
77 *
78 * @param tm map to hash
79 * @param hc where to store the hash code
80 */
81void
82GSC_TYPEMAP_hash (const struct GSC_TypeMap *tm, struct GNUNET_HashCode *hc)
83{
84 GNUNET_CRYPTO_hash (tm, sizeof(struct GSC_TypeMap), hc);
85}
86
87
88/**
89 * Check if the given hash matches our current type map.
90 *
91 * @param hc hash code to check if it matches our type map
92 * @return #GNUNET_YES if the hash matches, #GNUNET_NO if not
93 */
94int
95GSC_TYPEMAP_check_hash (const struct GNUNET_HashCode *hc)
96{
97 if (GNUNET_NO == hash_current)
98 {
99 GSC_TYPEMAP_hash (&my_type_map, &my_tm_hash);
100 hash_current = GNUNET_YES;
101 }
102 return (0 == memcmp (hc, &my_tm_hash, sizeof(struct GNUNET_HashCode)))
103 ? GNUNET_YES
104 : GNUNET_NO;
105}
106
107
108/**
109 * Compute a type map message for this peer.
110 *
111 * @return this peers current type map message.
112 */
113struct GNUNET_MessageHeader *
114GSC_TYPEMAP_compute_type_map_message ()
115{
116 char *tmp;
117 uLongf dlen;
118 struct GNUNET_MessageHeader *hdr;
119
120#ifdef compressBound
121 dlen = compressBound (sizeof(my_type_map));
122#else
123 dlen = sizeof(my_type_map) + (sizeof(my_type_map) / 100) + 20;
124 /* documentation says 100.1% oldSize + 12 bytes, but we
125 * should be able to overshoot by more to be safe */
126#endif
127 hdr = GNUNET_malloc (dlen + sizeof(struct GNUNET_MessageHeader));
128 tmp = (char *) &hdr[1];
129 if ((Z_OK != compress2 ((Bytef *) tmp,
130 &dlen,
131 (const Bytef *) &my_type_map,
132 sizeof(my_type_map),
133 9)) ||
134 (dlen >= sizeof(my_type_map)))
135 {
136 /* compression failed, use uncompressed map */
137 dlen = sizeof(my_type_map);
138 GNUNET_memcpy (tmp, &my_type_map, sizeof(my_type_map));
139 hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP);
140 }
141 else
142 {
143 /* compression worked, use compressed map */
144 hdr->type = htons (GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP);
145 }
146 hdr->size = htons ((uint16_t) dlen + sizeof(struct GNUNET_MessageHeader));
147 return hdr;
148}
149
150
151/**
152 * Extract a type map from a TYPE_MAP message.
153 *
154 * @param msg a type map message
155 * @return NULL on error
156 */
157struct GSC_TypeMap *
158GSC_TYPEMAP_get_from_message (const struct GNUNET_MessageHeader *msg)
159{
160 struct GSC_TypeMap *ret;
161 uint16_t size;
162 uLongf dlen;
163
164 size = ntohs (msg->size);
165 switch (ntohs (msg->type))
166 {
167 case GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP:
168 GNUNET_STATISTICS_update (GSC_stats,
169 gettext_noop ("# type maps received"),
170 1,
171 GNUNET_NO);
172 if (size != sizeof(struct GSC_TypeMap))
173 {
174 GNUNET_break_op (0);
175 return NULL;
176 }
177 ret = GNUNET_new (struct GSC_TypeMap);
178 GNUNET_memcpy (ret, &msg[1], sizeof(struct GSC_TypeMap));
179 return ret;
180
181 case GNUNET_MESSAGE_TYPE_CORE_COMPRESSED_TYPE_MAP:
182 GNUNET_STATISTICS_update (GSC_stats,
183 gettext_noop ("# type maps received"),
184 1,
185 GNUNET_NO);
186 ret = GNUNET_new (struct GSC_TypeMap);
187 dlen = sizeof(struct GSC_TypeMap);
188 if ((Z_OK != uncompress ((Bytef *) ret,
189 &dlen,
190 (const Bytef *) &msg[1],
191 (uLong) size)) ||
192 (dlen != sizeof(struct GSC_TypeMap)))
193 {
194 GNUNET_break_op (0);
195 GNUNET_free (ret);
196 return NULL;
197 }
198 return ret;
199
200 default:
201 GNUNET_break (0);
202 return NULL;
203 }
204}
205
206
207/**
208 * Send my type map to all connected peers (it got changed).
209 */
210static void
211broadcast_my_type_map ()
212{
213 struct GNUNET_MessageHeader *hdr;
214
215 hdr = GSC_TYPEMAP_compute_type_map_message ();
216 GNUNET_STATISTICS_update (GSC_stats,
217 gettext_noop ("# updates to my type map"),
218 1,
219 GNUNET_NO);
220 GSC_SESSIONS_broadcast_typemap (hdr);
221 GNUNET_free (hdr);
222}
223
224
225/**
226 * Add a set of types to our type map.
227 *
228 * @param types array of message types supported by this peer
229 * @param tlen number of entries in @a types
230 */
231void
232GSC_TYPEMAP_add (const uint16_t *types, unsigned int tlen)
233{
234 unsigned int i;
235 int changed;
236
237 changed = GNUNET_NO;
238 for (i = 0; i < tlen; i++)
239 {
240 if (0 == map_counters[types[i]]++)
241 {
242 my_type_map.bits[types[i] / 32] |= (1 << (types[i] % 32));
243 changed = GNUNET_YES;
244 }
245 }
246 if (GNUNET_YES == changed)
247 {
248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Typemap changed, broadcasting!\n");
249 rehash_typemap ();
250 broadcast_my_type_map ();
251 }
252}
253
254
255void
256GSC_TYPEMAP_remove (const uint16_t *types, unsigned int tlen)
257{
258 int changed;
259
260 changed = GNUNET_NO;
261 for (unsigned int i = 0; i < tlen; i++)
262 {
263 if (0 == --map_counters[types[i]])
264 {
265 my_type_map.bits[types[i] / 32] &= ~(1 << (types[i] % 32));
266 changed = GNUNET_YES;
267 }
268 }
269 if (GNUNET_YES == changed)
270 {
271 rehash_typemap ();
272 broadcast_my_type_map ();
273 }
274}
275
276
277/**
278 * Test if any of the types from the types array is in the
279 * given type map.
280 *
281 * @param tmap map to test
282 * @param types array of types
283 * @param tcnt number of entries in @a types
284 * @return #GNUNET_YES if a type is in the map, #GNUNET_NO if not
285 */
286int
287GSC_TYPEMAP_test_match (const struct GSC_TypeMap *tmap,
288 const uint16_t *types,
289 unsigned int tcnt)
290{
291 if (NULL == tmap)
292 return GNUNET_NO;
293 if (0 == tcnt)
294 return GNUNET_YES; /* matches all */
295 for (unsigned int i = 0; i < tcnt; i++)
296 if (0 != (tmap->bits[types[i] / 32] & (1 << (types[i] % 32))))
297 return GNUNET_YES;
298 return GNUNET_NO;
299}
300
301
302/**
303 * Add additional types to a given typemap.
304 *
305 * @param tmap map to extend (not changed)
306 * @param types array of types to add
307 * @param tcnt number of entries in @a types
308 * @return updated type map (fresh copy)
309 */
310struct GSC_TypeMap *
311GSC_TYPEMAP_extend (const struct GSC_TypeMap *tmap,
312 const uint16_t *types,
313 unsigned int tcnt)
314{
315 struct GSC_TypeMap *ret;
316
317 ret = GNUNET_new (struct GSC_TypeMap);
318 if (NULL != tmap)
319 GNUNET_memcpy (ret, tmap, sizeof(struct GSC_TypeMap));
320 for (unsigned int i = 0; i < tcnt; i++)
321 ret->bits[types[i] / 32] |= (1 << (types[i] % 32));
322 return ret;
323}
324
325
326/**
327 * Create an empty type map.
328 *
329 * @return an empty type map
330 */
331struct GSC_TypeMap *
332GSC_TYPEMAP_create ()
333{
334 return GNUNET_new (struct GSC_TypeMap);
335}
336
337
338/**
339 * Free the given type map.
340 *
341 * @param tmap a type map
342 */
343void
344GSC_TYPEMAP_destroy (struct GSC_TypeMap *tmap)
345{
346 GNUNET_free (tmap);
347}
348
349
350/**
351 * Initialize typemap subsystem.
352 */
353void
354GSC_TYPEMAP_init ()
355{
356 /* nothing to do */
357}
358
359
360/**
361 * Shutdown typemap subsystem.
362 */
363void
364GSC_TYPEMAP_done ()
365{
366 /* nothing to do */
367}
368
369
370/* 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 de41f4220..000000000
--- a/src/core/gnunet-service-core_typemap.h
+++ /dev/null
@@ -1,162 +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
31/**
32 * Map specifying which message types a peer supports.
33 */
34struct GSC_TypeMap;
35
36
37/**
38 * Add a set of types to our type map.
39 *
40 * @param types array of message types supported by this peer
41 * @param tlen number of entries in @a types
42 */
43void
44GSC_TYPEMAP_add (const uint16_t *types,
45 unsigned int tlen);
46
47
48/**
49 * Remove a set of message types from our type map.
50 *
51 * @param types array of message types no longer supported by this peer
52 * @param tlen number of entries in @a types
53 */
54void
55GSC_TYPEMAP_remove (const uint16_t *types,
56 unsigned int tlen);
57
58
59/**
60 * Compute a type map message for this peer.
61 *
62 * @return this peers current type map message.
63 */
64struct GNUNET_MessageHeader *
65GSC_TYPEMAP_compute_type_map_message (void);
66
67
68/**
69 * Check if the given hash matches our current type map.
70 *
71 * @param hc hash code to check if it matches our type map
72 * @return #GNUNET_YES if the hash matches, #GNUNET_NO if not
73 */
74int
75GSC_TYPEMAP_check_hash (const struct GNUNET_HashCode *hc);
76
77
78/**
79 * Hash the contents of a type map.
80 *
81 * @param tm map to hash
82 * @param hc where to store the hash code
83 */
84void
85GSC_TYPEMAP_hash (const struct GSC_TypeMap *tm,
86 struct GNUNET_HashCode *hc);
87
88
89/**
90 * Extract a type map from a
91 * #GNUNET_MESSAGE_TYPE_CORE_COMRESSED_TYPE_MAP or
92 * #GNUNET_MESSAGE_TYPE_CORE_BINARY_TYPE_MAP message.
93 *
94 * @param msg a type map message
95 * @return NULL on error
96 */
97struct GSC_TypeMap *
98GSC_TYPEMAP_get_from_message (const struct GNUNET_MessageHeader *msg);
99
100
101/**
102 * Test if any of the types from the types array is in the
103 * given type map.
104 *
105 * @param tmap map to test
106 * @param types array of types
107 * @param tcnt number of entries in @a types
108 * @return #GNUNET_YES if a type is in the map, #GNUNET_NO if not
109 */
110int
111GSC_TYPEMAP_test_match (const struct GSC_TypeMap *tmap,
112 const uint16_t *types,
113 unsigned int tcnt);
114
115
116/**
117 * Add additional types to a given typemap.
118 *
119 * @param tmap map to extend (not changed)
120 * @param types array of types to add
121 * @param tcnt number of entries in @a types
122 * @return updated type map (fresh copy)
123 */
124struct GSC_TypeMap *
125GSC_TYPEMAP_extend (const struct GSC_TypeMap *tmap,
126 const uint16_t *types,
127 unsigned int tcnt);
128
129
130/**
131 * Create an empty type map.
132 *
133 * @return an empty type map
134 */
135struct GSC_TypeMap *
136GSC_TYPEMAP_create (void);
137
138
139/**
140 * Free the given type map.
141 *
142 * @param tmap a type map
143 */
144void
145GSC_TYPEMAP_destroy (struct GSC_TypeMap *tmap);
146
147
148/**
149 * Initialize typemap subsystem.
150 */
151void
152GSC_TYPEMAP_init (void);
153
154
155/**
156 * Shutdown typemap subsystem.
157 */
158void
159GSC_TYPEMAP_done (void);
160
161#endif
162/* end of gnunet-service-core_typemap.h */
diff --git a/src/core/meson.build b/src/core/meson.build
deleted file mode 100644
index 2e3e958af..000000000
--- a/src/core/meson.build
+++ /dev/null
@@ -1,119 +0,0 @@
1libgnunetcore_src = ['core_api.c',
2 'core_api_monitor_peers.c']
3
4gnunetservicecore_src = ['gnunet-service-core.c',
5 'gnunet-service-core_kx.c',
6 'gnunet-service-core_sessions.c',
7 'gnunet-service-core_typemap.c']
8
9configure_file(input : 'core.conf.in',
10 output : 'core.conf',
11 configuration : cdata,
12 install: true,
13 install_dir: pkgcfgdir)
14
15
16if get_option('monolith')
17 foreach p : libgnunetcore_src + gnunetservicecore_src
18 gnunet_src += 'core/' + p
19 endforeach
20 subdir_done()
21endif
22
23libgnunetcore = library('gnunetcore',
24 libgnunetcore_src,
25 dependencies: libgnunetutil_dep,
26 include_directories: [incdir, configuration_inc],
27 install: true,
28 soversion: '0',
29 version: '0.0.1',
30 install_dir: get_option('libdir'))
31libgnunetcore_dep = declare_dependency(link_with : libgnunetcore)
32pkg.generate(libgnunetcore, url: 'https://www.gnunet.org',
33 description : 'Provides API for (encrypted) P2P communication')
34
35libgnunetcoretesting = library('gnunetcoretesting',
36 ['core_api_cmd_connecting_peers.c'],
37 dependencies: [
38 libgnunetutil_dep,
39 libgnunettesting_dep,
40 libgnunetarm_dep,
41 libgnunettransportapplication_dep,
42 libgnunettransportcore_dep,
43 ],
44 include_directories: [incdir, configuration_inc],
45 install: true,
46 soversion: '0',
47 version: '0.0.0',
48 install_dir: get_option('libdir'))
49libgnunetcoretesting_dep = declare_dependency(link_with : libgnunetcoretesting)
50
51shared_module('gnunet_test_core_plugin_cmd_just_run',
52 ['test_core_plugin_cmd_just_run.c'],
53 dependencies: [libgnunetutil_dep,
54 libgnunetcoretesting_dep,
55 libgnunettransportcore_dep,
56 libgnunettransportapplication_dep,
57 libgnunettesting_dep,
58 libgnunetpeerstore_dep,
59 libgnunetstatistics_dep,
60 libgnunethello_dep,
61 libgnunetarm_dep
62 ],
63 include_directories: [incdir, configuration_inc],
64 install: true,
65 install_dir: get_option('libdir')/'gnunet')
66
67executable ('gnunet-core',
68 ['gnunet-core.c'],
69 dependencies: [libgnunetcore_dep, libgnunetutil_dep],
70 include_directories: [incdir, configuration_inc],
71 install: true,
72 install_dir: get_option('bindir'))
73
74executable ('gnunet-service-core',
75 gnunetservicecore_src,
76 dependencies: [libgnunetcore_dep, libgnunetutil_dep,
77 libgnunetstatistics_dep,
78 libgnunettransportcore_dep,
79 zlib_dep],
80 include_directories: [incdir, configuration_inc],
81 install: true,
82 install_dir: get_option('libdir') / 'gnunet' / 'libexec')
83
84configure_file(input : 'test_core_defaults.conf',
85 output : 'test_core_defaults.conf',
86 copy: true)
87
88configure_file(input : 'test_core_api_send_to_self.conf',
89 output : 'test_core_api_send_to_self.conf',
90 copy: true)
91
92configure_file(input : 'test_core_api_peer1.conf',
93 output : 'test_core_api_peer1.conf',
94 copy: true)
95
96testcore_api_send_self = executable ('test_core_api_send_to_self',
97 ['test_core_api_send_to_self.c'],
98 dependencies: [
99 libgnunetcore_dep,
100 libgnunetutil_dep,
101 libgnunettesting_dep
102 ],
103 include_directories: [incdir, configuration_inc],
104 install: false)
105
106testcore_api_start = executable ('test_core_api_start_only',
107 ['test_core_api_send_to_self.c'],
108 dependencies: [
109 libgnunetcore_dep,
110 libgnunetutil_dep,
111 libgnunettesting_dep
112 ],
113 include_directories: [incdir, configuration_inc],
114 install: false)
115
116test('test_core_api_send_to_self', testcore_api_send_self,
117 suite: 'core', workdir: meson.current_build_dir())
118test('test_core_api_start_only', testcore_api_start,
119 suite: 'core', workdir: meson.current_build_dir())
diff --git a/src/core/test_core_api.c b/src/core/test_core_api.c
deleted file mode 100644
index 653ce1aa0..000000000
--- a/src/core/test_core_api.c
+++ /dev/null
@@ -1,348 +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_purge_cfg_dir
338 ("test_core_api_peer1.conf",
339 "GNUNET_TEST_HOME");
340 GNUNET_DISK_purge_cfg_dir
341 ("test_core_api_peer2.conf",
342 "GNUNET_TEST_HOME");
343
344 return ok;
345}
346
347
348/* 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 d4b55a6b8..000000000
--- a/src/core/test_core_api_reliability.c
+++ /dev/null
@@ -1,537 +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_purge_cfg_dir ("test_core_api_peer1.conf",
529 "GNUNET_TEST_HOME");
530 GNUNET_DISK_purge_cfg_dir ("test_core_api_peer2.conf",
531 "GNUNET_TEST_HOME");
532
533 return ok;
534}
535
536
537/* 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 fe8e69999..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_TMP/test-core-api-send-to-self/
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 e50d3b2ec..000000000
--- a/src/core/test_core_api_start_only.c
+++ /dev/null
@@ -1,258 +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_purge_cfg_dir
216 ("test_core_api_peer1.conf",
217 "GNUNET_TEST_HOME");
218 GNUNET_DISK_purge_cfg_dir
219 ("test_core_api_peer2.conf",
220 "GNUNET_TEST_HOME");
221
222 ok = 1;
223 GNUNET_PROGRAM_run ((sizeof(argv) / sizeof(char *)) - 1,
224 argv,
225 "test-core-api-start-only",
226 "nohelp",
227 options,
228 &run,
229 &ok);
230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
231 "Test finished\n");
232 stop_arm (&p1);
233 stop_arm (&p2);
234 return ok;
235}
236
237
238int
239main (int argc,
240 char *argv[])
241{
242 int ret;
243
244 GNUNET_log_setup ("test-core-api-start-only",
245 "WARNING",
246 NULL);
247 ret = check ();
248 GNUNET_DISK_purge_cfg_dir
249 ("test_core_api_peer1.conf",
250 "GNUNET_TEST_HOME");
251 GNUNET_DISK_purge_cfg_dir
252 ("test_core_api_peer2.conf",
253 "GNUNET_TEST_HOME");
254 return ret;
255}
256
257
258/* 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_plugin_cmd_just_run.c b/src/core/test_core_plugin_cmd_just_run.c
deleted file mode 100644
index 176d055c8..000000000
--- a/src/core/test_core_plugin_cmd_just_run.c
+++ /dev/null
@@ -1,512 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 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 testbed/plugin_cmd_simple_send.c
23 * @brief a plugin to provide the API for running test cases.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_barrier.h"
28#include "gnunet_testing_netjail_lib.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_transport_application_service.h"
31#include "gnunet_transport_core_service.h"
32#include "gnunet_testing_barrier.h"
33#include "gnunet_core_service.h"
34#include "gnunet_transport_testing_ng_lib.h"
35
36/**
37 * Generic logging shortcut
38 */
39#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
40
41#define BASE_DIR "testdir"
42
43#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
44
45#define MAX_RECEIVED 1000
46
47#define MESSAGE_SIZE 65000
48
49static struct GNUNET_TESTING_Command block_script;
50
51static struct GNUNET_TESTING_Command connect_peers;
52
53static struct GNUNET_TESTING_Command local_prepared;
54
55static struct GNUNET_TESTING_Command start_peer;
56
57static struct GNUNET_TESTING_Interpreter *is;
58
59static struct GNUNET_CONTAINER_MultiPeerMap *senders;
60
61struct TestState
62{
63 /**
64 * Callback to write messages to the master loop.
65 *
66 */
67 GNUNET_TESTING_cmd_helper_write_cb write_message;
68
69 /**
70 * Callback to notify the helper test case has finished.
71 */
72 GNUNET_TESTING_cmd_helper_finish_cb finished_cb;
73
74 /**
75 * The name for a specific test environment directory.
76 *
77 */
78 char *testdir;
79
80 /**
81 * The name for the configuration file of the specific node.
82 *
83 */
84 char *cfgname;
85
86 /**
87 * The complete topology information.
88 */
89 struct GNUNET_TESTING_NetjailTopology *topology;
90};
91
92struct Sender
93{
94 /**
95 * Number of received messages from sender.
96 */
97 unsigned long long num_received;
98
99 /**
100 * Sample mean time the message traveled.
101 */
102 struct GNUNET_TIME_Relative mean_time;
103
104 /**
105 * Time the first message was send.
106 */
107 struct GNUNET_TIME_Absolute time_first;
108};
109
110
111struct GNUNET_TESTING_BarrierList*
112get_waiting_for_barriers ()
113{
114 struct GNUNET_TESTING_BarrierList*barriers;
115 struct GNUNET_TESTING_BarrierListEntry *ble;
116
117 barriers = GNUNET_new (struct GNUNET_TESTING_BarrierList);
118 ble = GNUNET_new (struct GNUNET_TESTING_BarrierListEntry);
119 ble->barrier_name = "ready-to-connect";
120 ble->expected_reaches = 1;
121 GNUNET_CONTAINER_DLL_insert (barriers->head,
122 barriers->tail,
123 ble);
124
125 ble = GNUNET_new (struct GNUNET_TESTING_BarrierListEntry);
126 ble->barrier_name = "test-case-finished";
127 ble->expected_reaches = 1;
128 GNUNET_CONTAINER_DLL_insert (barriers->head,
129 barriers->tail,
130 ble);
131 return barriers;
132}
133
134
135/**
136 * Callback to set the flag indicating all peers started. Will be called via the plugin api.
137 *
138 */
139static void
140all_peers_started ()
141{
142}
143
144
145/**
146 * Function called with the final result of the test.
147 *
148 * @param cls the `struct MainParams`
149 * @param rv #GNUNET_OK if the test passed
150 */
151static void
152handle_result (void *cls,
153 enum GNUNET_GenericReturnValue rv)
154{
155 struct TestState *ts = cls;
156
157 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
158 "Local test exits with status %d\n",
159 rv);
160
161 ts->finished_cb (rv);
162 GNUNET_free (ts->testdir);
163 GNUNET_free (ts->cfgname);
164 GNUNET_TESTING_free_topology (ts->topology);
165 GNUNET_free (ts);
166}
167
168
169/**
170 * Callback from start peer cmd for signaling a peer got connected.
171 *
172 *
173static void *
174notify_connect (struct GNUNET_TESTING_Interpreter *is,
175 const struct GNUNET_PeerIdentity *peer)
176{
177 const struct ConnectPeersState *cps;
178 const struct GNUNET_TESTING_Command *cmd;
179
180 cmd = GNUNET_TESTING_interpreter_lookup_command (is,
181 "connect-peers");
182 GNUNET_TRANSPORT_get_trait_connect_peer_state (cmd,
183 &cps);
184 void *ret = NULL;
185
186 cps->notify_connect (is,
187 peer);
188 return ret;
189 }*/
190
191
192/**
193 * Callback to set the flag indicating all peers are prepared to finish. Will be called via the plugin api.
194 */
195static void
196all_local_tests_prepared ()
197{
198 const struct GNUNET_TESTING_LocalPreparedState *lfs;
199
200 GNUNET_TESTING_get_trait_local_prepared_state (&local_prepared,
201 &lfs);
202 GNUNET_assert (NULL != &lfs->ac);
203 if (NULL == lfs->ac.cont)
204 GNUNET_TESTING_async_fail ((struct GNUNET_TESTING_AsyncContext *) &lfs->ac);
205 else
206 GNUNET_TESTING_async_finish ((struct
207 GNUNET_TESTING_AsyncContext *) &lfs->ac);
208}
209
210
211static void
212child_completed_callback (void *cls,
213 enum GNUNET_OS_ProcessStatusType type,
214 long unsigned int exit_code)
215{
216
217}
218
219
220/**
221 * Function called to check a message being
222 * received.
223 *
224 */
225static int
226check_encrypted (void *cls, struct GNUNET_MessageHeader *header)
227{
228 return GNUNET_OK;
229}
230
231
232static void
233core_receive_continue (struct GNUNET_PeerIdentity *peer)
234{
235 const struct GNUNET_TESTING_StartPeerState *sps;
236
237 GNUNET_TESTING_get_trait_state (&start_peer,
238 &sps);
239
240 LOG (GNUNET_ERROR_TYPE_DEBUG,
241 "Executing core receive continue\n");
242
243 GNUNET_TRANSPORT_core_receive_continue (sps->th, peer);
244}
245
246
247/*static void
248handle_core (void *cls, struct GNUNET_MessageHeader *header)
249{
250 struct GNUNET_PeerIdentity *peer = cls;
251
252 core_receive_continue (peer);
253 }*/
254
255
256/**
257 * Function called to handle a message being received.
258 *
259 */
260static void
261handle_encrypted (void *cls, struct GNUNET_MessageHeader *header)
262{
263 struct GNUNET_PeerIdentity *peer = cls;
264
265 core_receive_continue (peer);
266}
267
268
269static void
270handle_ephemeral_key (void *cls, struct GNUNET_MessageHeader *header)
271{
272 struct GNUNET_PeerIdentity *peer = cls;
273
274 core_receive_continue (peer);
275}
276
277
278static void
279handle_ping (void *cls, struct GNUNET_MessageHeader *header)
280{
281 struct GNUNET_PeerIdentity *peer = cls;
282
283 core_receive_continue (peer);
284}
285
286
287static void
288handle_pong (void *cls, struct GNUNET_MessageHeader *header)
289{
290 struct GNUNET_PeerIdentity *peer = cls;
291
292 core_receive_continue (peer);
293}
294
295
296/**
297 * Function to start a local test case.
298 *
299 * @param write_message Callback to send a message to the master loop.
300 * @param router_ip Global address of the network namespace.
301 * @param node_ip The IP address of the node.
302 * @param m The number of the node in a network namespace.
303 * @param n The number of the network namespace.
304 * @param local_m The number of nodes in a network namespace.
305 * @param topology_data A file name for the file containing the topology configuration, or a string containing
306 * the topology configuration.
307 * @param read_file If read_file is GNUNET_YES this string is the filename for the topology configuration,
308 * if read_file is GNUNET_NO the string contains the topology configuration.
309 * @param finish_cb Callback function which writes a message from the helper process running on a netjail
310 * node to the master process * signaling that the test case running on the netjail node finished.
311 * @return Returns the struct GNUNET_TESTING_Interpreter of the command loop running on this netjail node.
312 */
313static struct GNUNET_TESTING_Interpreter *
314start_testcase (GNUNET_TESTING_cmd_helper_write_cb write_message,
315 const char *router_ip,
316 const char *node_ip,
317 const char *m,
318 const char *n,
319 const char *local_m,
320 const char *topology_data,
321 unsigned int *read_file,
322 GNUNET_TESTING_cmd_helper_finish_cb finished_cb)
323{
324
325 unsigned int n_int;
326 unsigned int m_int;
327 unsigned int local_m_int;
328 unsigned int num;
329 struct TestState *ts = GNUNET_new (struct TestState);
330 struct GNUNET_TESTING_NetjailTopology *topology;
331 unsigned int sscanf_ret = 0;
332 char **argv = NULL;
333 int argc = 0;
334
335 ts->finished_cb = finished_cb;
336 LOG (GNUNET_ERROR_TYPE_ERROR,
337 "n %s m %s\n",
338 n,
339 m);
340
341 if (GNUNET_YES == *read_file)
342 {
343 LOG (GNUNET_ERROR_TYPE_DEBUG,
344 "read from file\n");
345 topology = GNUNET_TESTING_get_topo_from_file (topology_data);
346 }
347 else
348 topology = GNUNET_TESTING_get_topo_from_string (topology_data);
349
350 ts->topology = topology;
351
352 errno = 0;
353 sscanf_ret = sscanf (m, "%u", &m_int);
354 if (errno != 0)
355 {
356 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
357 }
358 GNUNET_assert (0 < sscanf_ret);
359 errno = 0;
360 sscanf_ret = sscanf (n, "%u", &n_int);
361 if (errno != 0)
362 {
363 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
364 }
365 GNUNET_assert (0 < sscanf_ret);
366 errno = 0;
367 sscanf_ret = sscanf (local_m, "%u", &local_m_int);
368 if (errno != 0)
369 {
370 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "sscanf");
371 }
372 GNUNET_assert (0 < sscanf_ret);
373
374 if (0 == n_int)
375 num = m_int;
376 else
377 num = (n_int - 1) * local_m_int + m_int + topology->nodes_x;
378
379 block_script = GNUNET_TESTING_cmd_block_until_external_trigger (
380 "block-script");
381 connect_peers = GNUNET_CORE_cmd_connect_peers ("connect-peers",
382 "start-peer",
383 "system-create",
384 num,
385 topology,
386 0,
387 GNUNET_NO,
388 NULL);
389 local_prepared = GNUNET_TESTING_cmd_local_test_prepared (
390 "local-test-prepared",
391 write_message);
392
393
394 GNUNET_asprintf (&ts->cfgname,
395 "test_core_just_run.conf");
396
397 LOG (GNUNET_ERROR_TYPE_DEBUG,
398 "plugin cfgname: %s\n",
399 ts->cfgname);
400
401 LOG (GNUNET_ERROR_TYPE_DEBUG,
402 "node ip: %s\n",
403 node_ip);
404
405 GNUNET_asprintf (&ts->testdir,
406 "%s%s%s",
407 BASE_DIR,
408 m,
409 n);
410
411 /*struct GNUNET_MQ_MessageHandler handlers[] = {
412 GNUNET_MQ_hd_fixed_size (ephemeral_key,
413 GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY,
414 struct EphemeralKeyMessage,
415 NULL),
416 GNUNET_MQ_hd_fixed_size (ping,
417 GNUNET_MESSAGE_TYPE_CORE_PING,
418 struct PingMessage,
419 NULL),
420 GNUNET_MQ_hd_fixed_size (pong,
421 GNUNET_MESSAGE_TYPE_CORE_PONG,
422 struct PongMessage,
423 NULL),
424 GNUNET_MQ_handler_end ()
425 };*/
426
427 start_peer = GNUNET_TESTING_cmd_start_peer ("start-peer",
428 "system-create",
429 num,
430 node_ip,
431 ts->cfgname,
432 GNUNET_NO);
433
434 struct GNUNET_TESTING_Command commands[] = {
435 GNUNET_TESTING_cmd_system_create ("system-create",
436 ts->testdir),
437 start_peer,
438 GNUNET_TESTING_cmd_barrier_reached ("ready-to-connect-reached",
439 "ready-to-connect",
440 GNUNET_NO,
441 num,
442 GNUNET_NO,
443 write_message),
444 connect_peers,
445 GNUNET_TESTING_cmd_exec_bash_script ("script",
446 "block.sh",
447 argv,
448 argc,
449 &child_completed_callback),
450 block_script,
451 GNUNET_TESTING_cmd_barrier_reached ("test-case-finished-reached",
452 "test-case-finished",
453 GNUNET_NO,
454 num,
455 GNUNET_NO,
456 write_message),
457 GNUNET_TESTING_cmd_stop_peer ("stop-peer",
458 "start-peer"),
459 GNUNET_TESTING_cmd_system_destroy ("system-destroy",
460 "system-create"),
461 GNUNET_TESTING_cmd_end ()
462 };
463
464 ts->write_message = write_message;
465
466 is = GNUNET_TESTING_run (commands,
467 TIMEOUT,
468 &handle_result,
469 ts);
470 return is;
471}
472
473
474/**
475 * Entry point for the plugin.
476 *
477 * @param cls NULL
478 * @return the exported block API
479 */
480void *
481libgnunet_test_core_plugin_cmd_just_run_init (void *cls)
482{
483 struct GNUNET_TESTING_PluginFunctions *api;
484
485 GNUNET_log_setup ("simple-send",
486 "DEBUG",
487 NULL);
488
489 api = GNUNET_new (struct GNUNET_TESTING_PluginFunctions);
490 api->start_testcase = &start_testcase;
491 api->get_waiting_for_barriers = get_waiting_for_barriers;
492 return api;
493}
494
495
496/**
497 * Exit point from the plugin.
498 *
499 * @param cls the return value from #libgnunet_test_transport_plugin_just_run_init
500 * @return NULL
501 */
502void *
503libgnunet_test_core_plugin_cmd_just_run_done (void *cls)
504{
505 struct GNUNET_TESTING_PluginFunctions *api = cls;
506
507 GNUNET_free (api);
508 return NULL;
509}
510
511
512/* end of plugin_cmd_simple_send.c */
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 099c6fa3b..000000000
--- a/src/core/test_core_quota_compliance.c
+++ /dev/null
@@ -1,788 +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 if (NULL != p->hello) GNUNET_free (p->hello);
534 p->hello = GNUNET_malloc (ntohs (message->size));
535 GNUNET_memcpy (p->hello, message, ntohs (message->size));
536 if ((p == &p1) &&
537 (NULL == p2.oh))
538 p2.oh = GNUNET_TRANSPORT_offer_hello (p2.cfg,
539 message,
540 &offer_hello_done,
541 &p2);
542 if ((p == &p2) &&
543 (NULL == p1.oh))
544 p1.oh = GNUNET_TRANSPORT_offer_hello (p1.cfg, message,
545 &offer_hello_done,
546 &p1);
547
548 if ((p == &p1) &&
549 (NULL != p2.hello) &&
550 (NULL == p1.oh))
551 p1.oh = GNUNET_TRANSPORT_offer_hello (p1.cfg,
552 p2.hello,
553 &offer_hello_done,
554 &p1);
555 if ((p == &p2) &&
556 (NULL != p1.hello) &&
557 (NULL == p2.oh))
558 p2.oh = GNUNET_TRANSPORT_offer_hello (p2.cfg,
559 p1.hello,
560 &offer_hello_done,
561 &p2);
562}
563
564
565static void
566setup_peer (struct PeerContext *p,
567 const char *cfgname)
568{
569 char *binary;
570
571 binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
572 p->cfg = GNUNET_CONFIGURATION_create ();
573 p->arm_proc =
574 GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_OUT_AND_ERR
575 | GNUNET_OS_USE_PIPE_CONTROL,
576 NULL, NULL, NULL,
577 binary,
578 "gnunet-service-arm",
579 "-c",
580 cfgname,
581 NULL);
582 GNUNET_assert (GNUNET_OK ==
583 GNUNET_CONFIGURATION_load (p->cfg,
584 cfgname));
585 p->stats = GNUNET_STATISTICS_create ("core",
586 p->cfg);
587 GNUNET_assert (NULL != p->stats);
588 p->ats = GNUNET_ATS_connectivity_init (p->cfg);
589 GNUNET_assert (NULL != p->ats);
590 p->ghh = GNUNET_TRANSPORT_hello_get (p->cfg,
591 GNUNET_TRANSPORT_AC_ANY,
592 &process_hello,
593 p);
594 GNUNET_free (binary);
595}
596
597
598static void
599run (void *cls,
600 char *const *args,
601 const char *cfgfile,
602 const struct GNUNET_CONFIGURATION_Handle *cfg)
603{
604 struct GNUNET_MQ_MessageHandler handlers[] = {
605 GNUNET_MQ_hd_fixed_size (test,
606 MTYPE,
607 struct TestMessage,
608 NULL),
609 GNUNET_MQ_handler_end ()
610 };
611
612 GNUNET_assert (ok == 1);
613 OKPP;
614 err_task =
615 GNUNET_SCHEDULER_add_delayed (TIMEOUT,
616 &terminate_task_error,
617 NULL);
618 GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
619 NULL);
620 if (test == SYMMETRIC)
621 {
622 setup_peer (&p1,
623 "test_core_quota_peer1.conf");
624 setup_peer (&p2,
625 "test_core_quota_peer2.conf");
626 }
627 else if (test == ASYMMETRIC_SEND_LIMITED)
628 {
629 setup_peer (&p1,
630 "test_core_quota_asymmetric_send_limit_peer1.conf");
631 setup_peer (&p2,
632 "test_core_quota_asymmetric_send_limit_peer2.conf");
633 }
634 else if (test == ASYMMETRIC_RECV_LIMITED)
635 {
636 setup_peer (&p1,
637 "test_core_quota_asymmetric_recv_limited_peer1.conf");
638 setup_peer (&p2,
639 "test_core_quota_asymmetric_recv_limited_peer2.conf");
640 }
641
642 GNUNET_assert (test != -1);
643 GNUNET_assert (GNUNET_SYSERR !=
644 GNUNET_CONFIGURATION_get_value_size (p1.cfg,
645 "ATS",
646 "WAN_QUOTA_IN",
647 &current_quota_p1_in));
648 GNUNET_assert (GNUNET_SYSERR !=
649 GNUNET_CONFIGURATION_get_value_size (p2.cfg,
650 "ATS",
651 "WAN_QUOTA_IN",
652 &current_quota_p2_in));
653 GNUNET_assert (GNUNET_SYSERR !=
654 GNUNET_CONFIGURATION_get_value_size (p1.cfg,
655 "ATS",
656 "WAN_QUOTA_OUT",
657 &current_quota_p1_out));
658 GNUNET_assert (GNUNET_SYSERR !=
659 GNUNET_CONFIGURATION_get_value_size (p2.cfg,
660 "ATS",
661 "WAN_QUOTA_OUT",
662 &current_quota_p2_out));
663
664 p1.ch = GNUNET_CORE_connect (p1.cfg,
665 &p1,
666 &init_notify,
667 &connect_notify,
668 &disconnect_notify,
669 handlers);
670}
671
672
673static void
674stop_arm (struct PeerContext *p)
675{
676 if (0 != GNUNET_OS_process_kill (p->arm_proc,
677 GNUNET_TERM_SIG))
678 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
679 "kill");
680 if (GNUNET_OK !=
681 GNUNET_OS_process_wait (p->arm_proc))
682 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
683 "waitpid");
684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
685 "ARM process %u stopped\n",
686 GNUNET_OS_process_get_pid (p->arm_proc));
687 GNUNET_OS_process_destroy (p->arm_proc);
688 p->arm_proc = NULL;
689 GNUNET_CONFIGURATION_destroy (p->cfg);
690}
691
692
693static int
694check ()
695{
696 char *const argv[] = {
697 "test-core-quota-compliance",
698 "-c",
699 "test_core_api_data.conf",
700 NULL
701 };
702 struct GNUNET_GETOPT_CommandLineOption options[] = {
703 GNUNET_GETOPT_OPTION_END
704 };
705
706 ok = 1;
707 GNUNET_PROGRAM_run ((sizeof(argv) / sizeof(char *)) - 1,
708 argv,
709 "test-core-quota-compliance",
710 "nohelp",
711 options,
712 &run,
713 &ok);
714 stop_arm (&p1);
715 stop_arm (&p2);
716 return ok;
717}
718
719
720static void
721cleanup_directory (int test)
722{
723 switch (test)
724 {
725 case SYMMETRIC:
726 GNUNET_DISK_purge_cfg_dir
727 ("test_core_quota_peer1.conf",
728 "GNUNET_TEST_HOME");
729 GNUNET_DISK_purge_cfg_dir
730 ("test_core_quota_peer2.conf",
731 "GNUNET_TEST_HOME");
732 break;
733
734 case ASYMMETRIC_SEND_LIMITED:
735 GNUNET_DISK_purge_cfg_dir
736 ("test_core_quota_asymmetric_send_limit_peer1.conf",
737 "GNUNET_TEST_HOME");
738 GNUNET_DISK_purge_cfg_dir
739 ("test_core_quota_asymmetric_send_limit_peer2.conf",
740 "GNUNET_TEST_HOME");
741 break;
742
743 case ASYMMETRIC_RECV_LIMITED:
744 GNUNET_DISK_purge_cfg_dir
745 ("test_core_quota_asymmetric_recv_limited_peer1.conf",
746 "GNUNET_TEST_HOME");
747 GNUNET_DISK_purge_cfg_dir
748 ("test_core_quota_asymmetric_recv_limited_peer2.conf",
749 "GNUNET_TEST_HOME");
750 break;
751 }
752}
753
754
755int
756main (int argc,
757 char *argv[])
758{
759 int ret;
760
761 test = -1;
762 if (NULL != strstr (argv[0],
763 "_symmetric"))
764 {
765 test = SYMMETRIC;
766 }
767 else if (NULL != strstr (argv[0],
768 "_asymmetric_send"))
769 {
770 test = ASYMMETRIC_SEND_LIMITED;
771 }
772 else if (NULL != strstr (argv[0],
773 "_asymmetric_recv"))
774 {
775 test = ASYMMETRIC_RECV_LIMITED;
776 }
777 GNUNET_assert (test != -1);
778 cleanup_directory (test);
779 GNUNET_log_setup ("test-core-quota-compliance",
780 "WARNING",
781 NULL);
782 ret = check ();
783 cleanup_directory (test);
784 return ret;
785}
786
787
788/* 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
diff --git a/src/core/test_core_start_testcase.sh b/src/core/test_core_start_testcase.sh
deleted file mode 100755
index 78e67dbf5..000000000
--- a/src/core/test_core_start_testcase.sh
+++ /dev/null
@@ -1,15 +0,0 @@
1#!/bin/bash
2echo gaga1 > gaga.txt
3read -p "Test case configuration to use:" conf
4if ! [ -d "/run/netns" ]; then
5 echo You have to create the directory /run/netns.
6fi
7if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then
8 if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" != 1 ]; then
9 echo -e "Error during test setup: The kernel parameter kernel.unprivileged_userns_clone has to be set to 1! One has to execute\n\n sysctl kernel.unprivileged_userns_clone=1\n"
10 exit 78
11 fi
12fi
13echo gaga2 >> gaga.txt
14exec unshare -r -nmU bash -c "mount -t tmpfs --make-rshared tmpfs /run/netns; /usr/local/lib/gnunet/libexec/test_testing_start_with_config $conf"
15echo gaga3 >> gaga.txt