aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/gnunet-service-messenger_tunnel.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/gnunet-service-messenger_tunnel.c')
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.c300
1 files changed, 300 insertions, 0 deletions
diff --git a/src/messenger/gnunet-service-messenger_tunnel.c b/src/messenger/gnunet-service-messenger_tunnel.c
new file mode 100644
index 000000000..df9e5c4c7
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_tunnel.c
@@ -0,0 +1,300 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 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_util.h"
30
31struct GNUNET_MESSENGER_SrvTunnel*
32create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *door)
33{
34 GNUNET_assert((room) && (door));
35
36 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_new(struct GNUNET_MESSENGER_SrvTunnel);
37
38 tunnel->room = room;
39 tunnel->channel = NULL;
40
41 tunnel->peer = GNUNET_PEER_intern (door);
42 tunnel->contact_id = NULL;
43
44 tunnel->peer_message = NULL;
45 tunnel->last_message = NULL;
46
47 return tunnel;
48}
49
50void
51destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
52{
53 GNUNET_assert(tunnel);
54
55 if (tunnel->channel)
56 GNUNET_CADET_channel_destroy (tunnel->channel);
57
58 GNUNET_PEER_change_rc (tunnel->peer, -1);
59
60 if (tunnel->contact_id)
61 GNUNET_free(tunnel->contact_id);
62
63 if (tunnel->peer_message)
64 GNUNET_free(tunnel->peer_message);
65
66 if (tunnel->last_message)
67 GNUNET_free(tunnel->last_message);
68
69 GNUNET_free(tunnel);
70}
71
72int
73bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel)
74{
75 GNUNET_assert(tunnel);
76
77 if (tunnel->channel)
78 {
79 if (tunnel->contact_id)
80 return GNUNET_NO;
81
82 delayed_disconnect_channel (tunnel->channel);
83 }
84
85 tunnel->channel = channel;
86
87 return GNUNET_YES;
88}
89
90extern void
91callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls);
92
93void
94callback_tunnel_disconnect (void *cls, const struct GNUNET_CADET_Channel *channel)
95{
96 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
97
98 if (tunnel)
99 {
100 tunnel->channel = NULL;
101
102 callback_room_disconnect (tunnel->room, cls);
103 }
104}
105
106extern int
107callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls,
108 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash);
109
110int
111check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
112{
113 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
114
115 if (!tunnel)
116 return GNUNET_NO;
117
118 const uint16_t length = ntohs (header->size) - sizeof(*header);
119 const char *buffer = (const char*) &header[1];
120
121 struct GNUNET_MESSENGER_Message message;
122
123 if (length < sizeof(message.header))
124 return GNUNET_NO;
125
126 if (GNUNET_YES != decode_message (&message, length, buffer))
127 return GNUNET_NO;
128
129 struct GNUNET_HashCode hash;
130 hash_message (length, buffer, &hash);
131
132 int result = callback_verify_room_message (tunnel->room, cls, &message, &hash);
133
134 if (GNUNET_MESSENGER_KIND_PEER == message.header.kind)
135 {
136 struct GNUNET_PeerIdentity identity;
137
138 GNUNET_PEER_resolve (tunnel->peer, &identity);
139
140 if (0 == GNUNET_memcmp(&(message.body.peer.peer), &(identity)))
141 {
142 if (tunnel->contact_id)
143 {
144 if (0 != GNUNET_memcmp(tunnel->contact_id, &(message.header.sender_id)))
145 result = GNUNET_SYSERR;
146 }
147 else
148 {
149 tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
150
151 GNUNET_memcpy(tunnel->contact_id, &(message.header.sender_id), sizeof(struct GNUNET_ShortHashCode));
152 }
153 }
154 }
155
156 return (result == GNUNET_YES ? GNUNET_OK : GNUNET_NO);
157}
158
159extern void
160callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message,
161 const struct GNUNET_HashCode *hash);
162
163void
164handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
165{
166 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
167
168 const uint16_t length = ntohs (header->size) - sizeof(*header);
169 const char *buffer = (const char*) &header[1];
170
171 struct GNUNET_MESSENGER_Message message;
172 struct GNUNET_HashCode hash;
173
174 decode_message (&message, length, buffer);
175 hash_message (length, buffer, &hash);
176
177 if (tunnel)
178 {
179 if (!tunnel->last_message)
180 tunnel->last_message = GNUNET_new(struct GNUNET_HashCode);
181
182 GNUNET_memcpy(tunnel->last_message, &hash, sizeof(struct GNUNET_HashCode));
183
184 callback_room_recv (tunnel->room, cls, copy_message (&message), &hash);
185 }
186
187 GNUNET_CADET_receive_done (tunnel->channel);
188}
189
190int
191connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
192{
193 GNUNET_assert(tunnel);
194
195 if (tunnel->channel)
196 return GNUNET_NO;
197
198 const struct GNUNET_PeerIdentity *door = GNUNET_PEER_resolve2 (tunnel->peer);
199
200 struct GNUNET_CADET_Handle *cadet = get_room_cadet (tunnel->room);
201 struct GNUNET_HashCode *key = get_room_key (tunnel->room);
202
203 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
204 struct GNUNET_MessageHeader, NULL),
205 GNUNET_MQ_handler_end() };
206
207 tunnel->channel = GNUNET_CADET_channel_create (cadet, tunnel, door, key, NULL, callback_tunnel_disconnect, handlers);
208
209 return GNUNET_YES;
210}
211
212void
213disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
214{
215 if (tunnel->channel)
216 {
217 delayed_disconnect_channel (tunnel->channel);
218
219 tunnel->channel = NULL;
220 }
221}
222
223int
224is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
225{
226 return (tunnel->channel ? GNUNET_YES : GNUNET_NO);
227}
228
229struct GNUNET_MESSENGER_MessageSent
230{
231 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
232 struct GNUNET_HashCode hash;
233};
234
235extern void
236callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls,
237 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
238
239static void
240callback_tunnel_sent (void *cls)
241{
242 struct GNUNET_MESSENGER_MessageSent *sent = cls;
243
244 if (sent->tunnel)
245 {
246 if (!sent->tunnel->last_message)
247 sent->tunnel->last_message = GNUNET_new(struct GNUNET_HashCode);
248
249 GNUNET_memcpy(sent->tunnel->last_message, &(sent->hash), sizeof(struct GNUNET_HashCode));
250 }
251
252 GNUNET_free(sent);
253}
254
255void
256send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MQ_Envelope *env,
257 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
258{
259 struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (tunnel->channel);
260
261 struct GNUNET_MESSENGER_MessageSent *sent = GNUNET_new(struct GNUNET_MESSENGER_MessageSent);
262
263 GNUNET_memcpy(&(sent->hash), hash, sizeof(struct GNUNET_HashCode));
264
265 sent->tunnel = tunnel;
266
267 GNUNET_MQ_notify_sent (env, callback_tunnel_sent, sent);
268 GNUNET_MQ_send (mq, env);
269
270 callback_room_sent (tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle, tunnel, message, hash);
271}
272
273void
274send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message,
275 struct GNUNET_HashCode *hash)
276{
277 struct GNUNET_MQ_Envelope *env = pack_room_message (tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle,
278 message, hash,
279 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
280
281 if (env)
282 send_tunnel_envelope (tunnel, handle, env, copy_message (message), hash);
283}
284
285void
286forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message,
287 const struct GNUNET_HashCode *hash)
288{
289 struct GNUNET_MESSENGER_Message *clone = copy_message (message);
290 struct GNUNET_MQ_Envelope *env = pack_message (clone, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
291
292 if (env)
293 send_tunnel_envelope (tunnel, NULL, env, clone, hash);
294}
295
296const struct GNUNET_HashCode*
297get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
298{
299 return tunnel->peer_message;
300}