aboutsummaryrefslogtreecommitdiff
path: root/src/service/messenger/gnunet-service-messenger_tunnel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/messenger/gnunet-service-messenger_tunnel.c')
-rw-r--r--src/service/messenger/gnunet-service-messenger_tunnel.c441
1 files changed, 441 insertions, 0 deletions
diff --git a/src/service/messenger/gnunet-service-messenger_tunnel.c b/src/service/messenger/gnunet-service-messenger_tunnel.c
new file mode 100644
index 000000000..98d0ab1ce
--- /dev/null
+++ b/src/service/messenger/gnunet-service-messenger_tunnel.c
@@ -0,0 +1,441 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2024 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 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_tunnel.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_tunnel.h"
27
28#include "gnunet-service-messenger_handle.h"
29#include "gnunet-service-messenger_message_recv.h"
30#include "gnunet-service-messenger_message_store.h"
31#include "gnunet-service-messenger_operation_store.h"
32#include "gnunet-service-messenger_operation.h"
33
34#include "messenger_api_util.h"
35
36struct GNUNET_MESSENGER_SrvTunnel*
37create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room,
38 const struct GNUNET_PeerIdentity *door)
39{
40 GNUNET_assert ((room) && (door));
41
42 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_new (struct
43 GNUNET_MESSENGER_SrvTunnel);
44
45 tunnel->room = room;
46 tunnel->channel = NULL;
47
48 tunnel->peer = GNUNET_PEER_intern (door);
49
50 tunnel->messenger_version = 0;
51
52 tunnel->peer_message = NULL;
53
54 init_message_state (&(tunnel->state));
55
56 return tunnel;
57}
58
59
60void
61destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
62{
63 GNUNET_assert (tunnel);
64
65 if (tunnel->channel)
66 GNUNET_CADET_channel_destroy (tunnel->channel);
67
68 GNUNET_PEER_change_rc (tunnel->peer, -1);
69
70 if (tunnel->peer_message)
71 GNUNET_free (tunnel->peer_message);
72
73 clear_message_state (&(tunnel->state));
74
75 GNUNET_free (tunnel);
76}
77
78
79void
80bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
81 struct GNUNET_CADET_Channel *channel)
82{
83 GNUNET_assert (tunnel);
84
85 if (tunnel->channel)
86 delayed_disconnect_channel (tunnel->channel);
87
88 tunnel->channel = channel;
89}
90
91
92extern void
93callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room,
94 void *cls);
95
96void
97callback_tunnel_disconnect (void *cls,
98 const struct GNUNET_CADET_Channel *channel)
99{
100 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
101
102 if (tunnel)
103 {
104 tunnel->channel = NULL;
105
106 callback_room_disconnect (tunnel->room, cls);
107 }
108}
109
110
111extern enum GNUNET_GenericReturnValue
112callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
113 void *cls,
114 struct GNUNET_MESSENGER_Message *message,
115 struct GNUNET_HashCode *hash);
116
117enum GNUNET_GenericReturnValue
118check_tunnel_message (void *cls,
119 const struct GNUNET_MessageHeader *header)
120{
121 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
122
123 if (! tunnel)
124 return GNUNET_SYSERR;
125
126 const uint16_t length = ntohs (header->size) - sizeof(*header);
127 const char *buffer = (const char*) &header[1];
128
129 struct GNUNET_MESSENGER_Message message;
130
131 if (length < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN,
132 GNUNET_YES))
133 {
134 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
135 "Tunnel error: Message too short! (%d)\n", length);
136 return GNUNET_SYSERR;
137 }
138
139 uint16_t padding = 0;
140
141 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES,
142 &padding))
143 {
144 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Tunnel error: Decoding failed!\n");
145 return GNUNET_SYSERR;
146 }
147
148 struct GNUNET_HashCode hash;
149 hash_message (&message, length - padding, buffer, &hash);
150
151 return callback_verify_room_message (tunnel->room, cls, &message, &hash);
152}
153
154
155extern enum GNUNET_GenericReturnValue
156update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
157 struct GNUNET_MESSENGER_Message *message,
158 const struct GNUNET_HashCode *hash);
159
160extern void
161callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
162 const struct GNUNET_MESSENGER_Message *message,
163 const struct GNUNET_HashCode *hash);
164
165static void
166update_tunnel_last_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
167 const struct GNUNET_HashCode *hash)
168{
169 struct GNUNET_MESSENGER_OperationStore *operation_store =
170 get_srv_room_operation_store (tunnel->room);
171
172 enum GNUNET_GenericReturnValue requested;
173 requested = (GNUNET_MESSENGER_OP_REQUEST ==
174 get_store_operation_type (operation_store, hash)?
175 GNUNET_YES : GNUNET_NO);
176
177 struct GNUNET_MESSENGER_MessageStore *message_store =
178 get_srv_room_message_store (tunnel->room);
179
180 const struct GNUNET_MESSENGER_Message *message = get_store_message (
181 message_store, hash);
182
183 if (message)
184 update_message_state (&(tunnel->state), requested, message, hash);
185}
186
187
188void
189handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
190{
191 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
192
193 if (! tunnel)
194 return;
195
196 const uint16_t length = ntohs (header->size) - sizeof(*header);
197 const char *buffer = (const char*) &header[1];
198
199 struct GNUNET_MESSENGER_Message message;
200 struct GNUNET_HashCode hash;
201
202 uint16_t padding = 0;
203
204 decode_message (&message, length, buffer, GNUNET_YES, &padding);
205 hash_message (&message, length - padding, buffer, &hash);
206
207 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got message of kind: %s!\n",
208 GNUNET_MESSENGER_name_of_kind (message.header.kind));
209
210 enum GNUNET_GenericReturnValue new_message;
211 new_message = update_room_message (tunnel->room,
212 copy_message (&message),
213 &hash);
214
215 if (GNUNET_YES != new_message)
216 goto receive_done;
217
218 update_tunnel_last_message (tunnel, &hash);
219
220 enum GNUNET_GenericReturnValue forward_message = GNUNET_YES;
221
222 switch (message.header.kind)
223 {
224 case GNUNET_MESSENGER_KIND_INFO:
225 forward_message = recv_message_info (tunnel->room, tunnel, &message, &hash);
226 break;
227 case GNUNET_MESSENGER_KIND_PEER:
228 forward_message = recv_message_peer (tunnel->room, tunnel, &message, &hash);
229 break;
230 case GNUNET_MESSENGER_KIND_MISS:
231 forward_message = recv_message_miss (tunnel->room, tunnel, &message, &hash);
232 break;
233 case GNUNET_MESSENGER_KIND_REQUEST:
234 forward_message = recv_message_request (tunnel->room, tunnel, &message,
235 &hash);
236 break;
237 default:
238 break;
239 }
240
241 if (GNUNET_YES == forward_message)
242 {
243 forward_srv_room_message (tunnel->room, tunnel, &message, &hash);
244 callback_room_handle_message (tunnel->room, &message, &hash);
245 }
246
247receive_done:
248 cleanup_message (&message);
249
250 GNUNET_CADET_receive_done (tunnel->channel);
251}
252
253
254enum GNUNET_GenericReturnValue
255connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
256{
257 GNUNET_assert (tunnel);
258
259 if (tunnel->channel)
260 return GNUNET_NO;
261
262 const struct GNUNET_PeerIdentity *door = GNUNET_PEER_resolve2 (tunnel->peer);
263
264 struct GNUNET_CADET_Handle *cadet = get_srv_room_cadet (tunnel->room);
265 const struct GNUNET_HashCode *key = get_srv_room_key (tunnel->room);
266
267 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size (
268 tunnel_message,
269 GNUNET_MESSAGE_TYPE_CADET_CLI,
270 struct
271 GNUNET_MessageHeader, NULL),
272 GNUNET_MQ_handler_end () };
273
274 struct GNUNET_HashCode port;
275 convert_messenger_key_to_port (key, &port);
276 tunnel->channel = GNUNET_CADET_channel_create (cadet, tunnel, door, &port,
277 NULL,
278 callback_tunnel_disconnect,
279 handlers);
280
281 return GNUNET_YES;
282}
283
284
285void
286disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
287{
288 GNUNET_assert (tunnel);
289
290 if (tunnel->channel)
291 {
292 delayed_disconnect_channel (tunnel->channel);
293
294 tunnel->channel = NULL;
295 }
296}
297
298
299enum GNUNET_GenericReturnValue
300is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
301{
302 GNUNET_assert (tunnel);
303
304 return (tunnel->channel ? GNUNET_YES : GNUNET_NO);
305}
306
307
308struct GNUNET_MESSENGER_MessageSent
309{
310 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
311 struct GNUNET_HashCode hash;
312};
313
314static void
315callback_tunnel_sent (void *cls)
316{
317 struct GNUNET_MESSENGER_MessageSent *sent = cls;
318
319 if (sent->tunnel)
320 update_tunnel_last_message (sent->tunnel, &(sent->hash));
321
322 GNUNET_free (sent);
323}
324
325
326void
327send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
328 struct GNUNET_MQ_Envelope *env,
329 const struct GNUNET_HashCode *hash)
330{
331 GNUNET_assert ((tunnel) && (env) && (hash));
332
333 struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (tunnel->channel);
334
335 struct GNUNET_MESSENGER_MessageSent *sent = GNUNET_new (struct
336 GNUNET_MESSENGER_MessageSent);
337
338 GNUNET_memcpy (&(sent->hash), hash, sizeof(struct GNUNET_HashCode));
339
340 sent->tunnel = tunnel;
341
342 GNUNET_MQ_notify_sent (env, callback_tunnel_sent, sent);
343 GNUNET_MQ_send (mq, env);
344}
345
346
347enum GNUNET_GenericReturnValue
348send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
349 void *handle,
350 struct GNUNET_MESSENGER_Message *message)
351{
352 GNUNET_assert ((tunnel) && (handle));
353
354 if (! message)
355 return GNUNET_NO;
356
357 struct GNUNET_HashCode hash;
358 struct GNUNET_MQ_Envelope *env = pack_srv_room_message (
359 tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle,
360 message, &hash, GNUNET_MESSENGER_PACK_MODE_ENVELOPE
361 );
362
363 destroy_message (message);
364
365 if (! env)
366 return GNUNET_NO;
367
368 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending tunnel message: %s\n",
369 GNUNET_h2s (&hash));
370
371 send_tunnel_envelope (tunnel, env, &hash);
372 return GNUNET_YES;
373}
374
375
376void
377forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
378 const struct GNUNET_MESSENGER_Message *message,
379 const struct GNUNET_HashCode *hash)
380{
381 GNUNET_assert ((tunnel) && (message) && (hash));
382
383 struct GNUNET_MESSENGER_Message *copy = copy_message (message);
384 struct GNUNET_MQ_Envelope *env = pack_message (copy, NULL, NULL,
385 GNUNET_MESSENGER_PACK_MODE_ENVELOPE,
386 NULL);
387
388 destroy_message (copy);
389
390 if (! env)
391 return;
392
393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Forwarding tunnel message: %s\n",
394 GNUNET_h2s (hash));
395
396 send_tunnel_envelope (tunnel, env, hash);
397}
398
399
400const struct GNUNET_HashCode*
401get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
402{
403 GNUNET_assert (tunnel);
404
405 return tunnel->peer_message;
406}
407
408
409void
410get_tunnel_peer_identity (const struct GNUNET_MESSENGER_SrvTunnel *tunnel,
411 struct GNUNET_PeerIdentity *peer)
412{
413 GNUNET_assert (tunnel);
414
415 GNUNET_PEER_resolve (tunnel->peer, peer);
416}
417
418
419uint32_t
420get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
421{
422 GNUNET_assert (tunnel);
423
424 return tunnel->messenger_version;
425}
426
427
428enum GNUNET_GenericReturnValue
429update_tunnel_messenger_version (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
430 uint32_t version)
431{
432 GNUNET_assert (tunnel);
433
434 if (version != GNUNET_MESSENGER_VERSION)
435 return GNUNET_SYSERR;
436
437 if (version > tunnel->messenger_version)
438 tunnel->messenger_version = version;
439
440 return GNUNET_OK;
441}