diff options
author | TheJackiMonster <thejackimonster@gmail.com> | 2020-11-12 20:58:07 +0100 |
---|---|---|
committer | TheJackiMonster <thejackimonster@gmail.com> | 2020-11-12 20:58:07 +0100 |
commit | ca912f85dae6b61dd80ab02d0e3f0b20a556da7c (patch) | |
tree | 788ebaf2ce0870bad875a7d910b6cd1b536a99c7 /src | |
parent | 5bdfe2001fbc68b06293b79dd6426156719d33c0 (diff) | |
download | gnunet-ca912f85dae6b61dd80ab02d0e3f0b20a556da7c.tar.gz gnunet-ca912f85dae6b61dd80ab02d0e3f0b20a556da7c.zip |
-remerge branch 'jacki/messenger'
This reverts commit e11d1e59e4ae5f7d89c33df3ae9ca8f1ece990cf.
Diffstat (limited to 'src')
54 files changed, 10277 insertions, 14 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index f98cb96df..d8a869acb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am | |||
@@ -11,7 +11,8 @@ endif | |||
11 | 11 | ||
12 | if HAVE_EXPERIMENTAL | 12 | if HAVE_EXPERIMENTAL |
13 | EXP_DIR = \ | 13 | EXP_DIR = \ |
14 | rps | 14 | rps \ |
15 | messenger | ||
15 | #abd FTBFS | 16 | #abd FTBFS |
16 | if HAVE_ABE | 17 | if HAVE_ABE |
17 | EXP_DIR += \ | 18 | EXP_DIR += \ |
diff --git a/src/identity/identity_api.c b/src/identity/identity_api.c index d44e8da96..64c088923 100644 --- a/src/identity/identity_api.c +++ b/src/identity/identity_api.c | |||
@@ -1138,11 +1138,11 @@ GNUNET_IDENTITY_signature_verify_ (uint32_t purpose, | |||
1138 | 1138 | ||
1139 | 1139 | ||
1140 | ssize_t | 1140 | ssize_t |
1141 | GNUNET_IDENTITY_public_key_encrypt (const void *block, | 1141 | GNUNET_IDENTITY_encrypt (const void *block, |
1142 | size_t size, | 1142 | size_t size, |
1143 | const struct GNUNET_IDENTITY_PublicKey *pub, | 1143 | const struct GNUNET_IDENTITY_PublicKey *pub, |
1144 | struct GNUNET_CRYPTO_EcdhePublicKey *ecc, | 1144 | struct GNUNET_CRYPTO_EcdhePublicKey *ecc, |
1145 | void *result) | 1145 | void *result) |
1146 | { | 1146 | { |
1147 | struct GNUNET_CRYPTO_EcdhePrivateKey pk; | 1147 | struct GNUNET_CRYPTO_EcdhePrivateKey pk; |
1148 | GNUNET_CRYPTO_ecdhe_key_create (&pk); | 1148 | GNUNET_CRYPTO_ecdhe_key_create (&pk); |
@@ -1177,13 +1177,11 @@ GNUNET_IDENTITY_public_key_encrypt (const void *block, | |||
1177 | 1177 | ||
1178 | 1178 | ||
1179 | ssize_t | 1179 | ssize_t |
1180 | GNUNET_IDENTITY_private_key_decrypt (const void *block, | 1180 | GNUNET_IDENTITY_decrypt (const void *block, |
1181 | size_t size, | 1181 | size_t size, |
1182 | const struct | 1182 | const struct GNUNET_IDENTITY_PrivateKey *priv, |
1183 | GNUNET_IDENTITY_PrivateKey *priv, | 1183 | const struct GNUNET_CRYPTO_EcdhePublicKey *ecc, |
1184 | const struct | 1184 | void *result) |
1185 | GNUNET_CRYPTO_EcdhePublicKey *ecc, | ||
1186 | void *result) | ||
1187 | { | 1185 | { |
1188 | struct GNUNET_HashCode hash; | 1186 | struct GNUNET_HashCode hash; |
1189 | switch (ntohl (priv->type)) | 1187 | switch (ntohl (priv->type)) |
diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 202abb7ac..fc3d745a6 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am | |||
@@ -62,6 +62,7 @@ gnunetinclude_HEADERS = \ | |||
62 | gnunet_json_lib.h \ | 62 | gnunet_json_lib.h \ |
63 | gnunet_load_lib.h \ | 63 | gnunet_load_lib.h \ |
64 | gnunet_cadet_service.h \ | 64 | gnunet_cadet_service.h \ |
65 | gnunet_messenger_service.h \ | ||
65 | gnunet_mhd_compat.h \ | 66 | gnunet_mhd_compat.h \ |
66 | gnunet_microphone_lib.h \ | 67 | gnunet_microphone_lib.h \ |
67 | gnunet_mst_lib.h \ | 68 | gnunet_mst_lib.h \ |
diff --git a/src/include/gnunet_messenger_service.h b/src/include/gnunet_messenger_service.h new file mode 100644 index 000000000..8f5315c30 --- /dev/null +++ b/src/include/gnunet_messenger_service.h | |||
@@ -0,0 +1,436 @@ | |||
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 | * | ||
23 | * @file | ||
24 | * MESSENGER service; manages decentralized chat groups | ||
25 | * | ||
26 | * @defgroup messenger MESSENGER service | ||
27 | * Instant messaging based on the CADET subsystem | ||
28 | * | ||
29 | * @{ | ||
30 | */ | ||
31 | |||
32 | #ifndef GNUNET_MESSENGER_SERVICE_H | ||
33 | #define GNUNET_MESSENGER_SERVICE_H | ||
34 | |||
35 | #ifdef __cplusplus | ||
36 | extern "C" { | ||
37 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
38 | } | ||
39 | #endif | ||
40 | #endif | ||
41 | |||
42 | #include "platform.h" | ||
43 | #include "gnunet_configuration_lib.h" | ||
44 | #include "gnunet_crypto_lib.h" | ||
45 | #include "gnunet_identity_service.h" | ||
46 | #include "gnunet_mq_lib.h" | ||
47 | #include "gnunet_protocols.h" | ||
48 | #include "gnunet_scheduler_lib.h" | ||
49 | #include "gnunet_time_lib.h" | ||
50 | |||
51 | #define GNUNET_MESSENGER_SERVICE_NAME "messenger" | ||
52 | |||
53 | /** | ||
54 | * Opaque handle to the messenger | ||
55 | */ | ||
56 | struct GNUNET_MESSENGER_Handle; | ||
57 | |||
58 | /** | ||
59 | * Opaque handle to a room | ||
60 | */ | ||
61 | struct GNUNET_MESSENGER_Room; | ||
62 | |||
63 | /** | ||
64 | * Opaque handle to a contact | ||
65 | */ | ||
66 | struct GNUNET_MESSENGER_Contact; | ||
67 | |||
68 | /** | ||
69 | * Enum for the different supported kinds of messages | ||
70 | */ | ||
71 | enum GNUNET_MESSENGER_MessageKind | ||
72 | { | ||
73 | GNUNET_MESSENGER_KIND_INFO = 1, | ||
74 | |||
75 | GNUNET_MESSENGER_KIND_JOIN = 2, | ||
76 | GNUNET_MESSENGER_KIND_LEAVE = 3, | ||
77 | |||
78 | GNUNET_MESSENGER_KIND_NAME = 4, | ||
79 | GNUNET_MESSENGER_KIND_KEY = 5, | ||
80 | GNUNET_MESSENGER_KIND_PEER = 6, | ||
81 | GNUNET_MESSENGER_KIND_ID = 7, | ||
82 | |||
83 | GNUNET_MESSENGER_KIND_MISS = 8, | ||
84 | GNUNET_MESSENGER_KIND_MERGE = 9, | ||
85 | GNUNET_MESSENGER_KIND_REQUEST = 10, | ||
86 | |||
87 | GNUNET_MESSENGER_KIND_INVITE = 11, | ||
88 | GNUNET_MESSENGER_KIND_TEXT = 12, | ||
89 | GNUNET_MESSENGER_KIND_FILE = 13, | ||
90 | |||
91 | GNUNET_MESSENGER_KIND_PRIVATE = 14, | ||
92 | |||
93 | GNUNET_MESSENGER_KIND_UNKNOWN = 0 | ||
94 | }__attribute__((__packed__)); | ||
95 | |||
96 | /** | ||
97 | * Get the name of a message <i>kind</i>. | ||
98 | * | ||
99 | * @param kind Kind of a message | ||
100 | * @return Name of that kind | ||
101 | */ | ||
102 | const char* | ||
103 | GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind); | ||
104 | |||
105 | struct GNUNET_MESSENGER_MessageHeader | ||
106 | { | ||
107 | struct GNUNET_IDENTITY_Signature signature; | ||
108 | |||
109 | struct GNUNET_TIME_AbsoluteNBO timestamp; | ||
110 | |||
111 | struct GNUNET_ShortHashCode sender_id; | ||
112 | struct GNUNET_HashCode previous; | ||
113 | |||
114 | enum GNUNET_MESSENGER_MessageKind kind; | ||
115 | }; | ||
116 | |||
117 | struct GNUNET_MESSENGER_MessageInfo | ||
118 | { | ||
119 | struct GNUNET_IDENTITY_PublicKey host_key; | ||
120 | struct GNUNET_ShortHashCode unique_id; | ||
121 | }; | ||
122 | |||
123 | struct GNUNET_MESSENGER_MessageJoin | ||
124 | { | ||
125 | struct GNUNET_IDENTITY_PublicKey key; | ||
126 | }; | ||
127 | |||
128 | struct GNUNET_MESSENGER_MessageLeave | ||
129 | { | ||
130 | }; | ||
131 | |||
132 | struct GNUNET_MESSENGER_MessageName | ||
133 | { | ||
134 | char *name; | ||
135 | }; | ||
136 | |||
137 | struct GNUNET_MESSENGER_MessageKey | ||
138 | { | ||
139 | struct GNUNET_IDENTITY_PublicKey key; | ||
140 | }; | ||
141 | |||
142 | struct GNUNET_MESSENGER_MessagePeer | ||
143 | { | ||
144 | struct GNUNET_PeerIdentity peer; | ||
145 | }; | ||
146 | |||
147 | struct GNUNET_MESSENGER_MessageId | ||
148 | { | ||
149 | struct GNUNET_ShortHashCode id; | ||
150 | }; | ||
151 | |||
152 | struct GNUNET_MESSENGER_MessageMiss | ||
153 | { | ||
154 | struct GNUNET_PeerIdentity peer; | ||
155 | }; | ||
156 | |||
157 | struct GNUNET_MESSENGER_MessageMerge | ||
158 | { | ||
159 | struct GNUNET_HashCode previous; | ||
160 | }; | ||
161 | |||
162 | struct GNUNET_MESSENGER_MessageRequest | ||
163 | { | ||
164 | struct GNUNET_HashCode hash; | ||
165 | }; | ||
166 | |||
167 | struct GNUNET_MESSENGER_MessageInvite | ||
168 | { | ||
169 | struct GNUNET_PeerIdentity door; | ||
170 | struct GNUNET_HashCode key; | ||
171 | }; | ||
172 | |||
173 | struct GNUNET_MESSENGER_MessageText | ||
174 | { | ||
175 | char *text; | ||
176 | }; | ||
177 | |||
178 | struct GNUNET_MESSENGER_MessageFile | ||
179 | { | ||
180 | struct GNUNET_CRYPTO_SymmetricSessionKey key; | ||
181 | struct GNUNET_HashCode hash; | ||
182 | char name[NAME_MAX]; | ||
183 | char *uri; | ||
184 | }; | ||
185 | |||
186 | struct GNUNET_MESSENGER_MessagePrivate | ||
187 | { | ||
188 | struct GNUNET_CRYPTO_EcdhePublicKey key; | ||
189 | |||
190 | uint16_t length; | ||
191 | char *data; | ||
192 | }; | ||
193 | |||
194 | struct GNUNET_MESSENGER_MessageBody | ||
195 | { | ||
196 | union | ||
197 | { | ||
198 | struct GNUNET_MESSENGER_MessageInfo info; | ||
199 | |||
200 | struct GNUNET_MESSENGER_MessageJoin join; | ||
201 | struct GNUNET_MESSENGER_MessageLeave leave; | ||
202 | |||
203 | struct GNUNET_MESSENGER_MessageName name; | ||
204 | struct GNUNET_MESSENGER_MessageKey key; | ||
205 | struct GNUNET_MESSENGER_MessagePeer peer; | ||
206 | struct GNUNET_MESSENGER_MessageId id; | ||
207 | |||
208 | struct GNUNET_MESSENGER_MessageMiss miss; | ||
209 | struct GNUNET_MESSENGER_MessageMerge merge; | ||
210 | struct GNUNET_MESSENGER_MessageRequest request; | ||
211 | |||
212 | struct GNUNET_MESSENGER_MessageInvite invite; | ||
213 | struct GNUNET_MESSENGER_MessageText text; | ||
214 | struct GNUNET_MESSENGER_MessageFile file; | ||
215 | |||
216 | struct GNUNET_MESSENGER_MessagePrivate private; | ||
217 | }; | ||
218 | }; | ||
219 | |||
220 | /** | ||
221 | * Struct to a message | ||
222 | */ | ||
223 | struct GNUNET_MESSENGER_Message | ||
224 | { | ||
225 | struct GNUNET_MESSENGER_MessageHeader header; | ||
226 | struct GNUNET_MESSENGER_MessageBody body; | ||
227 | }; | ||
228 | |||
229 | /** | ||
230 | * Method called whenever the EGO of a <i>handle</i> changes or if the first connection fails | ||
231 | * to load a valid EGO and the anonymous keypair will be used instead. | ||
232 | * | ||
233 | * @param cls Closure from <i>GNUNET_MESSENGER_connect</i> | ||
234 | * @param handle Messenger handle | ||
235 | */ | ||
236 | typedef void | ||
237 | (*GNUNET_MESSENGER_IdentityCallback) (void *cls, struct GNUNET_MESSENGER_Handle *handle); | ||
238 | |||
239 | /** | ||
240 | * Method called whenever a message is sent or received from a <i>room</i>. | ||
241 | * | ||
242 | * @param cls Closure from <i>GNUNET_MESSENGER_connect</i> | ||
243 | * @param room Room handle | ||
244 | * @param message Newly received or sent message | ||
245 | * @param hash Hash identifying the message | ||
246 | */ | ||
247 | typedef void | ||
248 | (*GNUNET_MESSENGER_MessageCallback) (void *cls, const struct GNUNET_MESSENGER_Room *room, | ||
249 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
250 | |||
251 | /** | ||
252 | * Set up a handle for the messenger related functions and connects to all necessary services. It will look up the ego | ||
253 | * key identified by its <i>name</i> and use it for signing all messages from the handle. | ||
254 | * | ||
255 | * @param cfg Configuration to use | ||
256 | * @param name Name to look up an ego or NULL to stay anonymous | ||
257 | * @param identity_callback Function called when the EGO of the handle changes | ||
258 | * @param identity_cls Closure for the <i>identity_callback</i> handler | ||
259 | * @param msg_callback Function called when a new message is sent or received | ||
260 | * @param msg_cls Closure for the <i>msg_callback</i> handler | ||
261 | * @return Messenger handle to use, NULL on error | ||
262 | */ | ||
263 | struct GNUNET_MESSENGER_Handle* | ||
264 | GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *name, | ||
265 | GNUNET_MESSENGER_IdentityCallback identity_callback, void *identity_cls, | ||
266 | GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls); | ||
267 | |||
268 | /** | ||
269 | * Update a handle of the messenger to use a different ego key and replace the old one with a newly generated one. All | ||
270 | * participated rooms get informed about the key renewal. The handle requires a set name for this function to work and | ||
271 | * it needs to be unused by other egos. | ||
272 | * | ||
273 | * Keep in mind that this will fully delete the old ego key (if any is used) even if any other service wants to use it | ||
274 | * as default. | ||
275 | * | ||
276 | * @param handle Messenger handle to use | ||
277 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure | ||
278 | */ | ||
279 | int | ||
280 | GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle); | ||
281 | |||
282 | /** | ||
283 | * Disconnect all of the messengers used services and clears up its used memory. | ||
284 | * | ||
285 | * @param handle Messenger handle to use | ||
286 | */ | ||
287 | void | ||
288 | GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle); | ||
289 | |||
290 | /** | ||
291 | * Get the name (if specified, otherwise NULL) used by the messenger. | ||
292 | * | ||
293 | * @param handle Messenger handle to use | ||
294 | * @return Name used by the messenger or NULL | ||
295 | */ | ||
296 | const char* | ||
297 | GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle); | ||
298 | |||
299 | /** | ||
300 | * Set the name for the messenger. This will rename the currently used ego and move all stored files related to the current | ||
301 | * name to its new directory. If anything fails during this process the function returns GNUNET_NO and the name for | ||
302 | * the messenger won't change as specified. | ||
303 | * | ||
304 | * @param handle Messenger handle to use | ||
305 | * @param name Name for the messenger to change to | ||
306 | * @return GNUNET_YES on success, GNUNET_NO on failure and GNUNET_SYSERR if <i>handle</i> is NULL | ||
307 | */ | ||
308 | int | ||
309 | GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle, const char *name); | ||
310 | |||
311 | /** | ||
312 | * Get the public key used by the messenger. | ||
313 | * | ||
314 | * @param handle Messenger handle to use | ||
315 | * @return Used ego's public key | ||
316 | */ | ||
317 | const struct GNUNET_IDENTITY_PublicKey* | ||
318 | GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle); | ||
319 | |||
320 | /** | ||
321 | * Open a room to send and receive messages. The room will use the specified <i>key</i> as port for the underlying cadet | ||
322 | * service. Opening a room results in opening the port for incoming connections as possible <b>door</b>. | ||
323 | * | ||
324 | * Notice that there can only be one room related to a specific <i>key</i>. So trying to open two rooms with the same | ||
325 | * <i>key</i> will result in opening the room once but returning the handle both times because the room stays open. | ||
326 | * | ||
327 | * You can also open a room after entering it through a <b>door</b> using <i>GNUNET_MESSENGER_entry_room(...)</i>. This | ||
328 | * will notify all entered <b>doors</b> to list you as new <b>door</b>. | ||
329 | * | ||
330 | * ( All <b>doors</b> form a ring structured network to shorten the latency sending and receiving messages. ) | ||
331 | * | ||
332 | * @param handle Messenger handle to use | ||
333 | * @param key Hash identifying the port | ||
334 | * @return Room handle, NULL on error | ||
335 | */ | ||
336 | struct GNUNET_MESSENGER_Room* | ||
337 | GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); | ||
338 | |||
339 | /** | ||
340 | * Enter a room to send and receive messages through a <b>door</b> opened using <i>GNUNET_MESSENGER_open_room(...)</i>. | ||
341 | * | ||
342 | * Notice that there can only be one room related to a specific <i>key</i>. So trying to enter two rooms with the same | ||
343 | * <i>key</i> will result in entering the room once but returning the handle both times because the room stays entered. | ||
344 | * You can however enter a room through multiple <b>doors</b> in parallel which results in connecting both ends. But | ||
345 | * entering the room through the same <b>door</b> won't have any effect after the first time. | ||
346 | * | ||
347 | * You can also enter a room through a <b>door</b> after opening it using <i>GNUNET_MESSENGER_open_room(...)</i>. But the | ||
348 | * <b>door</b> may not be your own peer identity. | ||
349 | * | ||
350 | * ( All <b>doors</b> form a ring structured network to shorten the latency sending and receiving messages. ) | ||
351 | * | ||
352 | * @param handle Messenger handle to use | ||
353 | * @param door Peer identity of an open <b>door</b> | ||
354 | * @param key Hash identifying the port | ||
355 | * @return Room handle, NULL on error | ||
356 | */ | ||
357 | struct GNUNET_MESSENGER_Room* | ||
358 | GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, | ||
359 | const struct GNUNET_HashCode *key); | ||
360 | |||
361 | /** | ||
362 | * Close a room which was entered, opened or both in various order and variety. Closing a room will destroy all connections | ||
363 | * from your peer to another and the other way around. | ||
364 | * | ||
365 | * ( After a member closes a <b>door</b>, all members entered through that specific <b>door</b> have to use another one | ||
366 | * or open the room on their own. ) | ||
367 | * | ||
368 | * @param room Room handle | ||
369 | */ | ||
370 | void | ||
371 | GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room); | ||
372 | |||
373 | /** | ||
374 | * Get the contact of a member in a <i>room</i> identified by their <i>id</i>. | ||
375 | * | ||
376 | * Notice that contacts are independent of rooms but will be removed if all rooms containing these contacts get closed. | ||
377 | * | ||
378 | * @param room Room handle | ||
379 | * @param id Hash identifying a member | ||
380 | * @return Contact handle, NULL if <i>id</i> is not in use | ||
381 | */ | ||
382 | struct GNUNET_MESSENGER_Contact* | ||
383 | GNUNET_MESSENGER_get_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_ShortHashCode *id); | ||
384 | |||
385 | /** | ||
386 | * Get the name used by the <i>contact</i>. | ||
387 | * | ||
388 | * @param contact Contact handle | ||
389 | * @return Name of <i>contact</i> or NULL | ||
390 | */ | ||
391 | const char* | ||
392 | GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact); | ||
393 | |||
394 | /** | ||
395 | * Get the public key used by the <i>contact</i>. | ||
396 | * | ||
397 | * @param contact Contact handle | ||
398 | * @return Public key of the ego used by <i>contact</i> | ||
399 | */ | ||
400 | const struct GNUNET_IDENTITY_PublicKey* | ||
401 | GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact); | ||
402 | |||
403 | /** | ||
404 | * Send a <i>message</i> into a </i>room</i>. If you opened the <i>room</i> all entered members will receive the | ||
405 | * <i>message</i>. If you entered the <i>room</i> through a <b>door</b> all so entered <b>doors</b> will receive the | ||
406 | * <i>message</i> as well. All members receiving the <i>message</i> will also propagate this <i>message</i> recursively | ||
407 | * as long as the <i>message</i> is unknown to them. | ||
408 | * | ||
409 | * Notice that all messages sent and received are also stored and can be propagated to new members entering the room. | ||
410 | * | ||
411 | * @param room Room handle | ||
412 | * @param message New message to send | ||
413 | */ | ||
414 | void | ||
415 | GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message); | ||
416 | |||
417 | /** | ||
418 | * Get the message in a <i>room</i> identified by its <i>hash</i>. | ||
419 | * | ||
420 | * @param room Room handle | ||
421 | * @param hash Hash identifying a message | ||
422 | * @return Message struct or NULL if no message with that hash is known | ||
423 | */ | ||
424 | const struct GNUNET_MESSENGER_Message* | ||
425 | GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash); | ||
426 | |||
427 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
428 | { | ||
429 | #endif | ||
430 | #ifdef __cplusplus | ||
431 | } | ||
432 | #endif | ||
433 | |||
434 | #endif //GNUNET_MESSENGER_SERVICE_H | ||
435 | |||
436 | /** @} *//* end of group */ | ||
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index e9b81a654..9aa029e9d 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | Copyright (C) 2001--2018 GNUnet e.V. | 3 | Copyright (C) 2001--2020 GNUnet e.V. |
4 | 4 | ||
5 | GNUnet is free software: you can redistribute it and/or modify it | 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 | 6 | under the terms of the GNU Affero General Public License as published |
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | /** | 21 | /** |
22 | * @author Christian Grothoff | 22 | * @author Christian Grothoff |
23 | * @author Tobias Frisch | ||
23 | * | 24 | * |
24 | * @file | 25 | * @file |
25 | * Constants for network protocols | 26 | * Constants for network protocols |
@@ -3508,6 +3509,46 @@ extern "C" { | |||
3508 | #define GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT 1501 | 3509 | #define GNUNET_MESSAGE_TYPE_RECLAIM_REFERENCE_RESULT 1501 |
3509 | 3510 | ||
3510 | 3511 | ||
3512 | /*********************************************************************************/ | ||
3513 | /********************************** MESSENGER **********************************/ | ||
3514 | /*********************************************************************************/ | ||
3515 | /* MESSENGER: message types 1600-1629 | ||
3516 | * 1600-1609 Connection-level Messages | ||
3517 | * 1610-1619 Room-level Messages | ||
3518 | */ | ||
3519 | |||
3520 | /********************************* Connection **********************************/ | ||
3521 | |||
3522 | #define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE 1600 | ||
3523 | |||
3524 | #define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE 1601 | ||
3525 | |||
3526 | #define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY 1602 | ||
3527 | |||
3528 | #define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME 1603 | ||
3529 | |||
3530 | #define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME 1604 | ||
3531 | |||
3532 | #define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY 1605 | ||
3533 | |||
3534 | #define GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID 1606 | ||
3535 | |||
3536 | /************************************ Room *************************************/ | ||
3537 | |||
3538 | #define GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN 1610 | ||
3539 | |||
3540 | #define GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY 1611 | ||
3541 | |||
3542 | #define GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE 1612 | ||
3543 | |||
3544 | #define GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE 1614 | ||
3545 | |||
3546 | #define GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE 1615 | ||
3547 | |||
3548 | #define GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE 1616 | ||
3549 | |||
3550 | /*********************************************************************************/ | ||
3551 | |||
3511 | /** | 3552 | /** |
3512 | * Type used to match 'all' message types. | 3553 | * Type used to match 'all' message types. |
3513 | */ | 3554 | */ |
diff --git a/src/messenger/.gitignore b/src/messenger/.gitignore new file mode 100644 index 000000000..9de3fb304 --- /dev/null +++ b/src/messenger/.gitignore | |||
@@ -0,0 +1,4 @@ | |||
1 | gnunet-service-messenger | ||
2 | gnunet-messenger | ||
3 | test_messenger_api | ||
4 | test_messenger_anonymous | ||
diff --git a/src/messenger/Makefile.am b/src/messenger/Makefile.am new file mode 100644 index 000000000..ebe08290e --- /dev/null +++ b/src/messenger/Makefile.am | |||
@@ -0,0 +1,131 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | if USE_COVERAGE | ||
5 | AM_CFLAGS = --coverage -O0 | ||
6 | XLIB = -lgcov | ||
7 | endif | ||
8 | |||
9 | pkgcfgdir= $(pkgdatadir)/config.d/ | ||
10 | |||
11 | libexecdir= $(pkglibdir)/libexec/ | ||
12 | |||
13 | pkgcfg_DATA = \ | ||
14 | messenger.conf | ||
15 | |||
16 | plugindir = $(libdir)/gnunet | ||
17 | |||
18 | AM_CLFAGS = -g | ||
19 | |||
20 | libexec_PROGRAMS = \ | ||
21 | gnunet-service-messenger \ | ||
22 | $(EXP_LIBEXEC) | ||
23 | |||
24 | bin_PROGRAMS = \ | ||
25 | gnunet-messenger | ||
26 | |||
27 | lib_LTLIBRARIES = \ | ||
28 | libgnunetmessenger_common.la \ | ||
29 | libgnunetmessenger.la \ | ||
30 | $(EXP_LIB) | ||
31 | |||
32 | libgnunetmessenger_common_la_SOURCES = \ | ||
33 | messenger_api_ego.h \ | ||
34 | messenger_api_message.c messenger_api_message.h \ | ||
35 | messenger_api_list_tunnels.c messenger_api_list_tunnels.h | ||
36 | libgnunetmessenger_common_la_LIBADD = \ | ||
37 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
38 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
39 | $(XLIB) \ | ||
40 | $(LTLIBINTL) | ||
41 | libgnunetmessenger_common_la_LDFLAGS = \ | ||
42 | $(GN_LIB_LDFLAGS) \ | ||
43 | -version-info 0:0:0 | ||
44 | |||
45 | libgnunetmessenger_la_SOURCES = \ | ||
46 | messenger_api.c \ | ||
47 | messenger_api_contact.c messenger_api_contact.h \ | ||
48 | messenger_api_handle.c messenger_api_handle.h \ | ||
49 | messenger_api_room.c messenger_api_room.h | ||
50 | libgnunetmessenger_la_LIBADD = \ | ||
51 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
52 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
53 | libgnunetmessenger_common.la \ | ||
54 | $(XLIB) \ | ||
55 | $(LTLIBINTL) | ||
56 | libgnunetmessenger_la_LDFLAGS = \ | ||
57 | $(GN_LIB_LDFLAGS) \ | ||
58 | -version-info 0:0:0 | ||
59 | |||
60 | gnunet_messenger_SOURCES = \ | ||
61 | gnunet-messenger.c | ||
62 | gnunet_messenger_LDADD = \ | ||
63 | libgnunetmessenger_common.la \ | ||
64 | libgnunetmessenger.la \ | ||
65 | $(top_builddir)/src/util/libgnunetutil.la | ||
66 | gnunet_messenger_LDFLAGS = \ | ||
67 | $(GN_LIBINTL) | ||
68 | |||
69 | gnunet_service_messenger_SOURCES = \ | ||
70 | gnunet-service-messenger.c gnunet-service-messenger.h \ | ||
71 | gnunet-service-messenger_service.c gnunet-service-messenger_service.h \ | ||
72 | gnunet-service-messenger_list_handles.c gnunet-service-messenger_list_handles.h \ | ||
73 | gnunet-service-messenger_list_messages.c gnunet-service-messenger_list_messages.h \ | ||
74 | gnunet-service-messenger_message_handle.c gnunet-service-messenger_message_handle.h \ | ||
75 | gnunet-service-messenger_message_kind.c gnunet-service-messenger_message_kind.h \ | ||
76 | gnunet-service-messenger_message_recv.c gnunet-service-messenger_message_recv.h \ | ||
77 | gnunet-service-messenger_message_send.c gnunet-service-messenger_message_send.h \ | ||
78 | gnunet-service-messenger_message_store.c gnunet-service-messenger_message_store.h \ | ||
79 | gnunet-service-messenger_basement.c gnunet-service-messenger_basement.h \ | ||
80 | gnunet-service-messenger_contact.c gnunet-service-messenger_contact.h \ | ||
81 | gnunet-service-messenger_handle.c gnunet-service-messenger_handle.h \ | ||
82 | gnunet-service-messenger_room.c gnunet-service-messenger_room.h \ | ||
83 | gnunet-service-messenger_tunnel.c gnunet-service-messenger_tunnel.h \ | ||
84 | gnunet-service-messenger_util.c gnunet-service-messenger_util.h | ||
85 | gnunet_service_messenger_LDADD = \ | ||
86 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
87 | $(top_builddir)/src/cadet/libgnunetcadet.la \ | ||
88 | $(top_builddir)/src/identity/libgnunetidentity.la \ | ||
89 | libgnunetmessenger_common.la \ | ||
90 | libgnunetmessenger.la \ | ||
91 | $(GN_LIBINTL) | ||
92 | |||
93 | check_PROGRAMS = \ | ||
94 | test_messenger_api \ | ||
95 | test_messenger_anonymous \ | ||
96 | test_messenger_comm0 | ||
97 | |||
98 | if ENABLE_TEST_RUN | ||
99 | AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; | ||
100 | TESTS = \ | ||
101 | $(check_PROGRAMS) | ||
102 | endif | ||
103 | |||
104 | test_messenger_api_SOURCES = \ | ||
105 | test_messenger.c | ||
106 | test_messenger_api_LDADD = \ | ||
107 | libgnunetmessenger_common.la \ | ||
108 | libgnunetmessenger.la \ | ||
109 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
110 | $(top_builddir)/src/util/libgnunetutil.la | ||
111 | |||
112 | test_messenger_anonymous_SOURCES = \ | ||
113 | test_messenger_anonymous.c | ||
114 | test_messenger_anonymous_LDADD = \ | ||
115 | libgnunetmessenger_common.la \ | ||
116 | libgnunetmessenger.la \ | ||
117 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
118 | $(top_builddir)/src/util/libgnunetutil.la | ||
119 | |||
120 | test_messenger_comm0_SOURCES = \ | ||
121 | test_messenger_comm0.c | ||
122 | test_messenger_comm0_LDADD = \ | ||
123 | libgnunetmessenger_common.la \ | ||
124 | libgnunetmessenger.la \ | ||
125 | $(top_builddir)/src/testbed/libgnunettestbed.la \ | ||
126 | $(top_builddir)/src/testbed-logger/libgnunettestbedlogger.la \ | ||
127 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
128 | $(top_builddir)/src/util/libgnunetutil.la | ||
129 | |||
130 | EXTRA_DIST = \ | ||
131 | test_messenger_api.conf | ||
diff --git a/src/messenger/gnunet-messenger.c b/src/messenger/gnunet-messenger.c new file mode 100644 index 000000000..579e5c3ad --- /dev/null +++ b/src/messenger/gnunet-messenger.c | |||
@@ -0,0 +1,306 @@ | |||
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-messenger.c | ||
23 | * @brief Print information about messenger groups. | ||
24 | */ | ||
25 | |||
26 | #include <stdio.h> | ||
27 | |||
28 | #include "platform.h" | ||
29 | #include "gnunet_util_lib.h" | ||
30 | #include "gnunet_messenger_service.h" | ||
31 | |||
32 | struct GNUNET_MESSENGER_Handle *messenger; | ||
33 | |||
34 | /** | ||
35 | * Function called whenever a message is received or sent. | ||
36 | * | ||
37 | * @param cls Closure | ||
38 | * @param room Room | ||
39 | * @param message Message | ||
40 | * @param hash Hash of message | ||
41 | */ | ||
42 | void | ||
43 | on_message (void *cls, const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | ||
44 | const struct GNUNET_HashCode *hash) | ||
45 | { | ||
46 | struct GNUNET_MESSENGER_Contact *sender = GNUNET_MESSENGER_get_member (room, &(message->header.sender_id)); | ||
47 | |||
48 | const char *sender_name = GNUNET_MESSENGER_contact_get_name (sender); | ||
49 | |||
50 | if (!sender_name) | ||
51 | sender_name = "anonymous"; | ||
52 | |||
53 | switch (message->header.kind) | ||
54 | { | ||
55 | case GNUNET_MESSENGER_KIND_JOIN: | ||
56 | { | ||
57 | printf ("* '%s' joined the room! [ %u %u %u %u ]\n", sender_name, message->body.join.key.ecdsa_key.q_y[0], | ||
58 | message->body.join.key.ecdsa_key.q_y[1], message->body.join.key.ecdsa_key.q_y[2], | ||
59 | message->body.join.key.ecdsa_key.q_y[3]); | ||
60 | break; | ||
61 | } | ||
62 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
63 | { | ||
64 | printf ("* '%s' leaves the room!\n", sender_name); | ||
65 | break; | ||
66 | } | ||
67 | case GNUNET_MESSENGER_KIND_PEER: | ||
68 | { | ||
69 | printf ("* '%s' opened the room on: %s\n", sender_name, GNUNET_i2s_full (&(message->body.peer.peer))); | ||
70 | break; | ||
71 | } | ||
72 | case GNUNET_MESSENGER_KIND_TEXT: | ||
73 | { | ||
74 | printf ("* '%s' says: \"%s\"\n", sender_name, message->body.text.text); | ||
75 | break; | ||
76 | } | ||
77 | default: | ||
78 | { | ||
79 | break; | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||
84 | struct GNUNET_SCHEDULER_Task *read_task; | ||
85 | |||
86 | /** | ||
87 | * Task to shut down this application. | ||
88 | * | ||
89 | * @param cls Closure | ||
90 | */ | ||
91 | static void | ||
92 | shutdown_hook (void *cls) | ||
93 | { | ||
94 | struct GNUNET_MESSENGER_Room *room = cls; | ||
95 | |||
96 | if (read_task) | ||
97 | GNUNET_SCHEDULER_cancel (read_task); | ||
98 | |||
99 | if (room) | ||
100 | GNUNET_MESSENGER_close_room (room); | ||
101 | |||
102 | if (messenger) | ||
103 | GNUNET_MESSENGER_disconnect (messenger); | ||
104 | } | ||
105 | |||
106 | static void | ||
107 | listen_stdio (void *cls); | ||
108 | |||
109 | #define MAX_BUFFER_SIZE 60000 | ||
110 | |||
111 | /** | ||
112 | * Task run in stdio mode, after some data is available at stdin. | ||
113 | * | ||
114 | * @param cls Closure | ||
115 | */ | ||
116 | static void | ||
117 | read_stdio (void *cls) | ||
118 | { | ||
119 | read_task = NULL; | ||
120 | |||
121 | char buffer[MAX_BUFFER_SIZE]; | ||
122 | ssize_t length; | ||
123 | |||
124 | length = read (0, buffer, MAX_BUFFER_SIZE); | ||
125 | |||
126 | if ((length <= 0) || (length >= MAX_BUFFER_SIZE)) | ||
127 | { | ||
128 | GNUNET_SCHEDULER_shutdown (); | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | if (buffer[length - 1] == '\n') | ||
133 | buffer[length - 1] = '\0'; | ||
134 | else | ||
135 | buffer[length] = '\0'; | ||
136 | |||
137 | struct GNUNET_MESSENGER_Room *room = cls; | ||
138 | |||
139 | struct GNUNET_MESSENGER_Message message; | ||
140 | message.header.kind = GNUNET_MESSENGER_KIND_TEXT; | ||
141 | message.body.text.text = buffer; | ||
142 | |||
143 | GNUNET_MESSENGER_send_message (room, &message); | ||
144 | |||
145 | read_task = GNUNET_SCHEDULER_add_now (listen_stdio, cls); | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * Wait for input on STDIO and send it out over the #ch. | ||
150 | * | ||
151 | * @param cls Closure | ||
152 | */ | ||
153 | static void | ||
154 | listen_stdio (void *cls) | ||
155 | { | ||
156 | read_task = NULL; | ||
157 | |||
158 | struct GNUNET_NETWORK_FDSet *rs = GNUNET_NETWORK_fdset_create (); | ||
159 | |||
160 | GNUNET_NETWORK_fdset_set_native (rs, 0); | ||
161 | |||
162 | read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, | ||
163 | GNUNET_TIME_UNIT_FOREVER_REL, | ||
164 | rs, | ||
165 | NULL, | ||
166 | &read_stdio, cls); | ||
167 | |||
168 | GNUNET_NETWORK_fdset_destroy (rs); | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * Initial task to startup application. | ||
173 | * | ||
174 | * @param cls Closure | ||
175 | */ | ||
176 | static void | ||
177 | idle (void *cls) | ||
178 | { | ||
179 | struct GNUNET_MESSENGER_Room *room = cls; | ||
180 | |||
181 | printf ("* You joined the room.\n"); | ||
182 | |||
183 | read_task = GNUNET_SCHEDULER_add_now (listen_stdio, room); | ||
184 | } | ||
185 | |||
186 | char *door_id; | ||
187 | char *ego_name; | ||
188 | char *room_key; | ||
189 | |||
190 | struct GNUNET_SCHEDULER_Task *shutdown_task; | ||
191 | |||
192 | /** | ||
193 | * Function called when an identity is retrieved. | ||
194 | * | ||
195 | * @param cls Closure | ||
196 | * @param handle Handle of messenger service | ||
197 | */ | ||
198 | static void | ||
199 | on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle) | ||
200 | { | ||
201 | struct GNUNET_HashCode key; | ||
202 | memset (&key, 0, sizeof(key)); | ||
203 | |||
204 | if (room_key) | ||
205 | GNUNET_CRYPTO_hash (room_key, strlen (room_key), &key); | ||
206 | |||
207 | struct GNUNET_PeerIdentity *door = NULL; | ||
208 | |||
209 | if (door_id) | ||
210 | { | ||
211 | door = GNUNET_new(struct GNUNET_PeerIdentity); | ||
212 | |||
213 | if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (door_id, strlen (door_id), &(door->public_key))) | ||
214 | { | ||
215 | GNUNET_free(door); | ||
216 | door = NULL; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | const char *name = GNUNET_MESSENGER_get_name (handle); | ||
221 | |||
222 | if (!name) | ||
223 | name = "anonymous"; | ||
224 | |||
225 | printf ("* Welcome to the messenger, '%s'!\n", name); | ||
226 | |||
227 | struct GNUNET_MESSENGER_Room *room; | ||
228 | |||
229 | if (door) | ||
230 | { | ||
231 | printf ("* You try to entry a room...\n"); | ||
232 | |||
233 | room = GNUNET_MESSENGER_entry_room (messenger, door, &key); | ||
234 | } | ||
235 | else | ||
236 | { | ||
237 | printf ("* You try to open a room...\n"); | ||
238 | |||
239 | room = GNUNET_MESSENGER_open_room (messenger, &key); | ||
240 | } | ||
241 | |||
242 | GNUNET_SCHEDULER_cancel (shutdown_task); | ||
243 | |||
244 | shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, room); | ||
245 | |||
246 | if (!room) | ||
247 | GNUNET_SCHEDULER_shutdown (); | ||
248 | else | ||
249 | GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (), GNUNET_SCHEDULER_PRIORITY_IDLE, idle, | ||
250 | room); | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * Main function that will be run by the scheduler. | ||
255 | * | ||
256 | * @param cls closure | ||
257 | * @param args remaining command-line arguments | ||
258 | * @param cfgfile name of the configuration file used (for saving, can be NULL!) | ||
259 | * @param cfg configuration | ||
260 | */ | ||
261 | static void | ||
262 | run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
263 | { | ||
264 | messenger = GNUNET_MESSENGER_connect (cfg, ego_name, &on_identity, NULL, &on_message, NULL); | ||
265 | |||
266 | shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, NULL); | ||
267 | } | ||
268 | |||
269 | /** | ||
270 | * The main function to obtain messenger information. | ||
271 | * | ||
272 | * @param argc number of arguments from the command line | ||
273 | * @param argv command line arguments | ||
274 | * @return 0 ok, 1 on error | ||
275 | */ | ||
276 | int | ||
277 | main (int argc, char **argv) | ||
278 | { | ||
279 | const char *description = "Open and connect to rooms using the MESSENGER to chat."; | ||
280 | |||
281 | struct GNUNET_GETOPT_CommandLineOption options[] = { | ||
282 | GNUNET_GETOPT_option_string ('d', | ||
283 | "door", | ||
284 | "PEERIDENTITY", | ||
285 | "peer identity to entry into the room", | ||
286 | &door_id), | ||
287 | GNUNET_GETOPT_option_string ('e', | ||
288 | "ego", | ||
289 | "IDENTITY", | ||
290 | "identity to use for messaging", | ||
291 | &ego_name), | ||
292 | GNUNET_GETOPT_option_string ('r', | ||
293 | "room", | ||
294 | "ROOMKEY", | ||
295 | "key of the room to connect to", | ||
296 | &room_key), | ||
297 | GNUNET_GETOPT_OPTION_END }; | ||
298 | |||
299 | return (GNUNET_OK == GNUNET_PROGRAM_run (argc, | ||
300 | argv, | ||
301 | "gnunet-messenger\0", | ||
302 | gettext_noop(description), | ||
303 | options, | ||
304 | &run, | ||
305 | NULL) ? EXIT_SUCCESS : EXIT_FAILURE); | ||
306 | } | ||
diff --git a/src/messenger/gnunet-service-messenger.c b/src/messenger/gnunet-service-messenger.c new file mode 100644 index 000000000..2c92305c4 --- /dev/null +++ b/src/messenger/gnunet-service-messenger.c | |||
@@ -0,0 +1,306 @@ | |||
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.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger.h" | ||
27 | |||
28 | #include "gnunet-service-messenger_service.h" | ||
29 | #include "messenger_api_message.h" | ||
30 | |||
31 | struct GNUNET_MESSENGER_Client | ||
32 | { | ||
33 | struct GNUNET_SERVICE_Client *client; | ||
34 | struct GNUNET_MESSENGER_SrvHandle *handle; | ||
35 | }; | ||
36 | |||
37 | struct GNUNET_MESSENGER_Service *messenger; | ||
38 | |||
39 | static int | ||
40 | check_create (void *cls, const struct GNUNET_MESSENGER_CreateMessage *msg) | ||
41 | { | ||
42 | GNUNET_MQ_check_zero_termination(msg); | ||
43 | return GNUNET_OK; | ||
44 | } | ||
45 | |||
46 | static void | ||
47 | handle_create (void *cls, const struct GNUNET_MESSENGER_CreateMessage *msg) | ||
48 | { | ||
49 | struct GNUNET_MESSENGER_Client *msg_client = cls; | ||
50 | |||
51 | const char *name = ((const char*) msg) + sizeof(*msg); | ||
52 | |||
53 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle created with name: %s\n", name); | ||
54 | |||
55 | setup_handle_name (msg_client->handle, strlen (name) > 0? name : NULL); | ||
56 | |||
57 | GNUNET_SERVICE_client_continue (msg_client->client); | ||
58 | } | ||
59 | |||
60 | static void | ||
61 | handle_update (void *cls, const struct GNUNET_MESSENGER_UpdateMessage *msg) | ||
62 | { | ||
63 | struct GNUNET_MESSENGER_Client *msg_client = cls; | ||
64 | |||
65 | if (GNUNET_OK != update_handle (msg_client->handle)) | ||
66 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Name is required to update key!\n"); | ||
67 | |||
68 | GNUNET_SERVICE_client_continue (msg_client->client); | ||
69 | } | ||
70 | |||
71 | static void | ||
72 | handle_destroy (void *cls, const struct GNUNET_MESSENGER_DestroyMessage *msg) | ||
73 | { | ||
74 | struct GNUNET_MESSENGER_Client *msg_client = cls; | ||
75 | |||
76 | GNUNET_SERVICE_client_drop (msg_client->client); | ||
77 | } | ||
78 | |||
79 | static int | ||
80 | check_set_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg) | ||
81 | { | ||
82 | GNUNET_MQ_check_zero_termination(msg); | ||
83 | return GNUNET_OK; | ||
84 | } | ||
85 | |||
86 | static void | ||
87 | handle_set_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg) | ||
88 | { | ||
89 | struct GNUNET_MESSENGER_Client *msg_client = cls; | ||
90 | |||
91 | const char *name = ((const char*) msg) + sizeof(*msg); | ||
92 | |||
93 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handles name is now: %s\n", name); | ||
94 | |||
95 | if (GNUNET_YES != set_handle_name (msg_client->handle, name)) | ||
96 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "No valid name: %s\n", name); | ||
97 | |||
98 | GNUNET_SERVICE_client_continue (msg_client->client); | ||
99 | } | ||
100 | |||
101 | static void | ||
102 | handle_room_open (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg) | ||
103 | { | ||
104 | struct GNUNET_MESSENGER_Client *msg_client = cls; | ||
105 | |||
106 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room: %s\n", | ||
107 | GNUNET_h2s (&(msg->key))); | ||
108 | |||
109 | if (GNUNET_YES == open_handle_room (msg_client->handle, &(msg->key))) | ||
110 | { | ||
111 | const struct GNUNET_ShortHashCode* member_id = get_handle_member_id(msg_client->handle, &(msg->key)); | ||
112 | |||
113 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room with member id: %s\n", | ||
114 | GNUNET_sh2s (member_id)); | ||
115 | |||
116 | struct GNUNET_MESSENGER_RoomMessage *response; | ||
117 | struct GNUNET_MQ_Envelope *env; | ||
118 | |||
119 | env = GNUNET_MQ_msg(response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN); | ||
120 | GNUNET_memcpy(&(response->key), &(msg->key), sizeof(msg->key)); | ||
121 | GNUNET_MQ_send (msg_client->handle->mq, env); | ||
122 | } | ||
123 | else | ||
124 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Opening room failed: %s\n", | ||
125 | GNUNET_h2s (&(msg->key))); | ||
126 | |||
127 | GNUNET_SERVICE_client_continue (msg_client->client); | ||
128 | } | ||
129 | |||
130 | static void | ||
131 | handle_room_entry (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg) | ||
132 | { | ||
133 | struct GNUNET_MESSENGER_Client *msg_client = cls; | ||
134 | |||
135 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room: %s, %s\n", | ||
136 | GNUNET_h2s (&(msg->key)), GNUNET_i2s (&(msg->door))); | ||
137 | |||
138 | if (GNUNET_YES == entry_handle_room (msg_client->handle, &(msg->door), &(msg->key))) | ||
139 | { | ||
140 | const struct GNUNET_ShortHashCode* member_id = get_handle_member_id(msg_client->handle, &(msg->key)); | ||
141 | |||
142 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room with member id: %s\n", | ||
143 | GNUNET_sh2s (member_id)); | ||
144 | |||
145 | struct GNUNET_MESSENGER_RoomMessage *response; | ||
146 | struct GNUNET_MQ_Envelope *env; | ||
147 | |||
148 | env = GNUNET_MQ_msg(response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY); | ||
149 | GNUNET_memcpy(&(response->door), &(msg->door), sizeof(msg->door)); | ||
150 | GNUNET_memcpy(&(response->key), &(msg->key), sizeof(msg->key)); | ||
151 | GNUNET_MQ_send (msg_client->handle->mq, env); | ||
152 | } | ||
153 | else | ||
154 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Entrance into room failed: %s, %s\n", | ||
155 | GNUNET_h2s (&(msg->key)), GNUNET_i2s (&(msg->door))); | ||
156 | |||
157 | GNUNET_SERVICE_client_continue (msg_client->client); | ||
158 | } | ||
159 | |||
160 | static void | ||
161 | handle_room_close (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg) | ||
162 | { | ||
163 | struct GNUNET_MESSENGER_Client *msg_client = cls; | ||
164 | |||
165 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room: %s\n", GNUNET_h2s (&(msg->key))); | ||
166 | |||
167 | if (GNUNET_YES == close_handle_room (msg_client->handle, &(msg->key))) | ||
168 | { | ||
169 | const struct GNUNET_ShortHashCode* member_id = get_handle_member_id(msg_client->handle, &(msg->key)); | ||
170 | |||
171 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room with member id: %s\n", | ||
172 | GNUNET_sh2s (member_id)); | ||
173 | |||
174 | struct GNUNET_MESSENGER_RoomMessage *response; | ||
175 | struct GNUNET_MQ_Envelope *env; | ||
176 | |||
177 | env = GNUNET_MQ_msg(response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE); | ||
178 | GNUNET_memcpy(&(response->key), &(msg->key), sizeof(msg->key)); | ||
179 | GNUNET_MQ_send (msg_client->handle->mq, env); | ||
180 | } | ||
181 | else | ||
182 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Closing room failed: %s\n", GNUNET_h2s (&(msg->key))); | ||
183 | |||
184 | GNUNET_SERVICE_client_continue (msg_client->client); | ||
185 | } | ||
186 | |||
187 | static int | ||
188 | check_send_message (void *cls, const struct GNUNET_MESSENGER_SendMessage *msg) | ||
189 | { | ||
190 | const uint16_t full_length = ntohs (msg->header.size) - sizeof(msg->header); | ||
191 | |||
192 | if (full_length < sizeof(msg->key)) | ||
193 | return GNUNET_NO; | ||
194 | |||
195 | const uint16_t length = full_length - sizeof(msg->key); | ||
196 | const char *buffer = ((const char*) msg) + sizeof(*msg); | ||
197 | |||
198 | struct GNUNET_MESSENGER_Message message; | ||
199 | |||
200 | if (GNUNET_YES != decode_message (&message, length, buffer)) | ||
201 | return GNUNET_NO; | ||
202 | |||
203 | return GNUNET_OK; | ||
204 | } | ||
205 | |||
206 | static void | ||
207 | handle_send_message (void *cls, const struct GNUNET_MESSENGER_SendMessage *msg) | ||
208 | { | ||
209 | struct GNUNET_MESSENGER_Client *msg_client = cls; | ||
210 | |||
211 | const struct GNUNET_HashCode *key = &(msg->key); | ||
212 | const char *buffer = ((const char*) msg) + sizeof(*msg); | ||
213 | |||
214 | const uint16_t length = ntohs (msg->header.size) - sizeof(*msg); | ||
215 | |||
216 | struct GNUNET_MESSENGER_Message message; | ||
217 | decode_message (&message, length, buffer); | ||
218 | |||
219 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending message: %s to %s\n", | ||
220 | GNUNET_MESSENGER_name_of_kind (message.header.kind), | ||
221 | GNUNET_h2s (key)); | ||
222 | |||
223 | if (GNUNET_YES != send_handle_message (msg_client->handle, key, &message)) | ||
224 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message failed: %s to %s\n", | ||
225 | GNUNET_MESSENGER_name_of_kind (message.header.kind), | ||
226 | GNUNET_h2s (key)); | ||
227 | |||
228 | GNUNET_SERVICE_client_continue (msg_client->client); | ||
229 | } | ||
230 | |||
231 | static void | ||
232 | handle_get_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg) | ||
233 | { | ||
234 | struct GNUNET_MESSENGER_Client *msg_client = cls; | ||
235 | |||
236 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Requesting message from room: %s\n", | ||
237 | GNUNET_h2s (&(msg->key))); | ||
238 | |||
239 | struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (messenger, &(msg->key)); | ||
240 | |||
241 | if (room) | ||
242 | get_room_message (room, msg_client->handle, &(msg->hash), GNUNET_YES); | ||
243 | else | ||
244 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Room not found: %s\n", | ||
245 | GNUNET_h2s (&(msg->key))); | ||
246 | |||
247 | GNUNET_SERVICE_client_continue (msg_client->client); | ||
248 | } | ||
249 | |||
250 | static void* | ||
251 | callback_client_connect (void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq) | ||
252 | { | ||
253 | struct GNUNET_MESSENGER_Client *msg_client = GNUNET_new(struct GNUNET_MESSENGER_Client); | ||
254 | |||
255 | msg_client->client = client; | ||
256 | msg_client->handle = add_service_handle (messenger, mq); | ||
257 | |||
258 | return msg_client; | ||
259 | } | ||
260 | |||
261 | static void | ||
262 | callback_client_disconnect (void *cls, struct GNUNET_SERVICE_Client *client, void *internal_cls) | ||
263 | { | ||
264 | struct GNUNET_MESSENGER_Client *msg_client = internal_cls; | ||
265 | |||
266 | remove_service_handle (messenger, msg_client->handle); | ||
267 | |||
268 | GNUNET_free(msg_client); | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * Setup MESSENGER internals. | ||
273 | * | ||
274 | * @param cls closure | ||
275 | * @param config configuration to use | ||
276 | * @param service the initialized service | ||
277 | */ | ||
278 | static void | ||
279 | run (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service) | ||
280 | { | ||
281 | messenger = create_service (config, service); | ||
282 | |||
283 | if ((!messenger) || (!messenger->cadet) || (!messenger->identity)) | ||
284 | GNUNET_SCHEDULER_shutdown (); | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * Define "main" method using service macro. | ||
289 | */ | ||
290 | GNUNET_SERVICE_MAIN( | ||
291 | GNUNET_MESSENGER_SERVICE_NAME, | ||
292 | GNUNET_SERVICE_OPTION_NONE, | ||
293 | &run, | ||
294 | &callback_client_connect, | ||
295 | &callback_client_disconnect, | ||
296 | NULL, | ||
297 | GNUNET_MQ_hd_var_size( create, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE, struct GNUNET_MESSENGER_CreateMessage, NULL ), | ||
298 | GNUNET_MQ_hd_fixed_size( update, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE, struct GNUNET_MESSENGER_UpdateMessage, NULL ), | ||
299 | GNUNET_MQ_hd_fixed_size( destroy, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY, struct GNUNET_MESSENGER_DestroyMessage, NULL ), | ||
300 | GNUNET_MQ_hd_var_size( set_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME, struct GNUNET_MESSENGER_NameMessage, NULL ), | ||
301 | GNUNET_MQ_hd_fixed_size( room_open, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN, struct GNUNET_MESSENGER_RoomMessage, NULL ), | ||
302 | GNUNET_MQ_hd_fixed_size( room_entry, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY, struct GNUNET_MESSENGER_RoomMessage, NULL ), | ||
303 | GNUNET_MQ_hd_fixed_size( room_close, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE, struct GNUNET_MESSENGER_RoomMessage, NULL ), | ||
304 | GNUNET_MQ_hd_var_size( send_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE, struct GNUNET_MESSENGER_SendMessage, NULL ), | ||
305 | GNUNET_MQ_hd_fixed_size( get_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE, struct GNUNET_MESSENGER_RecvMessage, NULL ), | ||
306 | GNUNET_MQ_handler_end()); | ||
diff --git a/src/messenger/gnunet-service-messenger.h b/src/messenger/gnunet-service-messenger.h new file mode 100644 index 000000000..85a1d2549 --- /dev/null +++ b/src/messenger/gnunet-service-messenger.h | |||
@@ -0,0 +1,121 @@ | |||
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.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_cadet_service.h" | ||
31 | #include "gnunet_container_lib.h" | ||
32 | #include "gnunet_crypto_lib.h" | ||
33 | #include "gnunet_identity_service.h" | ||
34 | #include "gnunet_mq_lib.h" | ||
35 | #include "gnunet_peer_lib.h" | ||
36 | #include "gnunet_protocols.h" | ||
37 | #include "gnunet_util_lib.h" | ||
38 | |||
39 | /** | ||
40 | * Message to create a handle for a client | ||
41 | */ | ||
42 | struct GNUNET_MESSENGER_CreateMessage | ||
43 | { | ||
44 | struct GNUNET_MessageHeader header; | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * Message to update the handle (its EGO key) for a client | ||
49 | */ | ||
50 | struct GNUNET_MESSENGER_UpdateMessage | ||
51 | { | ||
52 | struct GNUNET_MessageHeader header; | ||
53 | }; | ||
54 | |||
55 | /** | ||
56 | * Message to destroy the handle for a client | ||
57 | */ | ||
58 | struct GNUNET_MESSENGER_DestroyMessage | ||
59 | { | ||
60 | struct GNUNET_MessageHeader header; | ||
61 | }; | ||
62 | |||
63 | /** | ||
64 | * Message to receive the current name of a handle | ||
65 | */ | ||
66 | struct GNUNET_MESSENGER_NameMessage | ||
67 | { | ||
68 | struct GNUNET_MessageHeader header; | ||
69 | }; | ||
70 | |||
71 | /** | ||
72 | * Message to receive the current public key of a handle | ||
73 | */ | ||
74 | struct GNUNET_MESSENGER_KeyMessage | ||
75 | { | ||
76 | struct GNUNET_MessageHeader header; | ||
77 | struct GNUNET_IDENTITY_PublicKey pubkey; | ||
78 | }; | ||
79 | |||
80 | /** | ||
81 | * General message to confirm interaction with a room | ||
82 | */ | ||
83 | struct GNUNET_MESSENGER_RoomMessage | ||
84 | { | ||
85 | struct GNUNET_MessageHeader header; | ||
86 | |||
87 | struct GNUNET_PeerIdentity door; | ||
88 | struct GNUNET_HashCode key; | ||
89 | }; | ||
90 | |||
91 | /** | ||
92 | * Message to receive the current member id of a handle in room | ||
93 | */ | ||
94 | struct GNUNET_MESSENGER_MemberMessage | ||
95 | { | ||
96 | struct GNUNET_MessageHeader header; | ||
97 | |||
98 | struct GNUNET_HashCode key; | ||
99 | struct GNUNET_ShortHashCode id; | ||
100 | }; | ||
101 | |||
102 | /** | ||
103 | * Message to send something into a room | ||
104 | */ | ||
105 | struct GNUNET_MESSENGER_SendMessage | ||
106 | { | ||
107 | struct GNUNET_MessageHeader header; | ||
108 | struct GNUNET_HashCode key; | ||
109 | }; | ||
110 | |||
111 | /** | ||
112 | * Message to receive something from a room | ||
113 | */ | ||
114 | struct GNUNET_MESSENGER_RecvMessage | ||
115 | { | ||
116 | struct GNUNET_MessageHeader header; | ||
117 | struct GNUNET_HashCode key; | ||
118 | struct GNUNET_HashCode hash; | ||
119 | }; | ||
120 | |||
121 | #endif //GNUNET_SERVICE_MESSENGER_H | ||
diff --git a/src/messenger/gnunet-service-messenger_basement.c b/src/messenger/gnunet-service-messenger_basement.c new file mode 100644 index 000000000..190cf2de5 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_basement.c | |||
@@ -0,0 +1,58 @@ | |||
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_basement.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_basement.h" | ||
27 | |||
28 | size_t | ||
29 | count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels) | ||
30 | { | ||
31 | const struct GNUNET_MESSENGER_ListTunnel *element; | ||
32 | size_t count = 0; | ||
33 | |||
34 | for (element = tunnels->head; element; element = element->next) | ||
35 | count++; | ||
36 | |||
37 | return count; | ||
38 | } | ||
39 | |||
40 | int | ||
41 | should_connect_tunnel_to (size_t count, size_t src, size_t dst) | ||
42 | { | ||
43 | if ((src + 1) % count == dst % count) | ||
44 | return GNUNET_YES; | ||
45 | |||
46 | return GNUNET_NO; | ||
47 | } | ||
48 | |||
49 | int | ||
50 | required_connection_between (size_t count, size_t src, size_t dst) | ||
51 | { | ||
52 | if (GNUNET_YES == should_connect_tunnel_to (count, src, dst)) | ||
53 | return GNUNET_YES; | ||
54 | if (GNUNET_YES == should_connect_tunnel_to (count, dst, src)) | ||
55 | return GNUNET_YES; | ||
56 | |||
57 | return GNUNET_NO; | ||
58 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_basement.h b/src/messenger/gnunet-service-messenger_basement.h new file mode 100644 index 000000000..0a1a9b126 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_basement.h | |||
@@ -0,0 +1,66 @@ | |||
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_basement.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_BASEMENT_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_BASEMENT_H | ||
28 | |||
29 | #include "messenger_api_list_tunnels.h" | ||
30 | |||
31 | /** | ||
32 | * Returns the count of peers in a list (typically from the basement of a room). | ||
33 | * | ||
34 | * @param tunnels List of peer identities | ||
35 | * @return Count of the entries in the list | ||
36 | */ | ||
37 | size_t | ||
38 | count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels); | ||
39 | |||
40 | /** | ||
41 | * Returns GNUNET_YES or GNUNET_NO to determine if the peer at index <i>src</i> should | ||
42 | * or should not connect outgoing to the peer at index <i>dst</i> to construct a complete | ||
43 | * basement with a given <i>count</i> of peers. | ||
44 | * | ||
45 | * @param count Count of peers | ||
46 | * @param src Source index | ||
47 | * @param dst Destination index | ||
48 | * @return GNUNET_YES or GNUNET_NO based on topologic requirement | ||
49 | */ | ||
50 | int | ||
51 | should_connect_tunnel_to (size_t count, size_t src, size_t dst); | ||
52 | |||
53 | /** | ||
54 | * Returns GNUNET_YES or GNUNET_NO to determine if the peers of index <i>src</i> and | ||
55 | * index <i>dst</i> should be connected in any direction to construct a complete | ||
56 | * basement with a given <i>count</i> of peers. | ||
57 | * | ||
58 | * @param count Count of peers | ||
59 | * @param src Source index | ||
60 | * @param dst Destination index | ||
61 | * @return GNUNET_YES or GNUNET_NO based on topologic requirement | ||
62 | */ | ||
63 | int | ||
64 | required_connection_between (size_t count, size_t src, size_t dst); | ||
65 | |||
66 | #endif //GNUNET_SERVICE_MESSENGER_BASEMENT_H | ||
diff --git a/src/messenger/gnunet-service-messenger_contact.c b/src/messenger/gnunet-service-messenger_contact.c new file mode 100644 index 000000000..1ec125402 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_contact.c | |||
@@ -0,0 +1,96 @@ | |||
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_contact.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_contact.h" | ||
27 | |||
28 | struct GNUNET_MESSENGER_SrvContact* | ||
29 | create_contact (const struct GNUNET_IDENTITY_PublicKey *key) | ||
30 | { | ||
31 | struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_new(struct GNUNET_MESSENGER_SrvContact); | ||
32 | |||
33 | contact->name = NULL; | ||
34 | contact->rc = 0; | ||
35 | |||
36 | GNUNET_memcpy(&(contact->public_key), key, sizeof(contact->public_key)); | ||
37 | |||
38 | return contact; | ||
39 | } | ||
40 | |||
41 | void | ||
42 | destroy_contact (struct GNUNET_MESSENGER_SrvContact *contact) | ||
43 | { | ||
44 | if (contact->name) | ||
45 | GNUNET_free(contact->name); | ||
46 | |||
47 | GNUNET_free(contact); | ||
48 | } | ||
49 | |||
50 | const char* | ||
51 | get_contact_name (const struct GNUNET_MESSENGER_SrvContact *contact) | ||
52 | { | ||
53 | return contact->name; | ||
54 | } | ||
55 | |||
56 | void | ||
57 | set_contact_name (struct GNUNET_MESSENGER_SrvContact *contact, const char *name) | ||
58 | { | ||
59 | GNUNET_assert(name); | ||
60 | |||
61 | if (contact->name) | ||
62 | GNUNET_free(contact->name); | ||
63 | |||
64 | contact->name = GNUNET_strdup(name); | ||
65 | } | ||
66 | |||
67 | const struct GNUNET_IDENTITY_PublicKey* | ||
68 | get_contact_key (const struct GNUNET_MESSENGER_SrvContact *contact) | ||
69 | { | ||
70 | return &(contact->public_key); | ||
71 | } | ||
72 | |||
73 | void | ||
74 | increase_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact) | ||
75 | { | ||
76 | contact->rc++; | ||
77 | } | ||
78 | |||
79 | int | ||
80 | decrease_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact) | ||
81 | { | ||
82 | if (contact->rc > 0) | ||
83 | contact->rc--; | ||
84 | |||
85 | return contact->rc ? GNUNET_NO : GNUNET_YES; | ||
86 | } | ||
87 | |||
88 | const struct GNUNET_HashCode* | ||
89 | get_contact_id_from_key (const struct GNUNET_MESSENGER_SrvContact *contact) | ||
90 | { | ||
91 | static struct GNUNET_HashCode id; | ||
92 | |||
93 | GNUNET_CRYPTO_hash (&(contact->public_key), sizeof(contact->public_key), &id); | ||
94 | |||
95 | return &id; | ||
96 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_contact.h b/src/messenger/gnunet-service-messenger_contact.h new file mode 100644 index 000000000..4a4f8bf0f --- /dev/null +++ b/src/messenger/gnunet-service-messenger_contact.h | |||
@@ -0,0 +1,112 @@ | |||
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_contact.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_CONTACT_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_CONTACT_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_crypto_lib.h" | ||
31 | #include "gnunet_identity_service.h" | ||
32 | |||
33 | struct GNUNET_MESSENGER_SrvContact | ||
34 | { | ||
35 | char *name; | ||
36 | size_t rc; | ||
37 | |||
38 | struct GNUNET_IDENTITY_PublicKey public_key; | ||
39 | }; | ||
40 | |||
41 | /** | ||
42 | * Creates and allocates a new contact with a given public <i>key</i> from an EGO. | ||
43 | * | ||
44 | * @param key Public key | ||
45 | * @return New contact | ||
46 | */ | ||
47 | struct GNUNET_MESSENGER_SrvContact* | ||
48 | create_contact (const struct GNUNET_IDENTITY_PublicKey *key); | ||
49 | |||
50 | /** | ||
51 | * Destroys a contact and frees its memory fully. | ||
52 | * | ||
53 | * @param contact Contact | ||
54 | */ | ||
55 | void | ||
56 | destroy_contact (struct GNUNET_MESSENGER_SrvContact *contact); | ||
57 | |||
58 | /** | ||
59 | * Returns the current name of a given <i>contact</i> or NULL if no valid name was assigned yet. | ||
60 | * | ||
61 | * @param contact Contact | ||
62 | * @return Name of the contact or NULL | ||
63 | */ | ||
64 | const char* | ||
65 | get_contact_name (const struct GNUNET_MESSENGER_SrvContact *contact); | ||
66 | |||
67 | /** | ||
68 | * Changes the current name of a given <i>contact</i> by copying it from the parameter <i>name</i>. | ||
69 | * | ||
70 | * @param contact Contact | ||
71 | * @param name Valid name (may not be NULL!) | ||
72 | */ | ||
73 | void | ||
74 | set_contact_name (struct GNUNET_MESSENGER_SrvContact *contact, const char *name); | ||
75 | |||
76 | /** | ||
77 | * Returns the public key of a given <i>contact</i>. | ||
78 | * | ||
79 | * @param contact Contact | ||
80 | * @return Public key of the contact | ||
81 | */ | ||
82 | const struct GNUNET_IDENTITY_PublicKey* | ||
83 | get_contact_key (const struct GNUNET_MESSENGER_SrvContact *contact); | ||
84 | |||
85 | /** | ||
86 | * Increases the reference counter of a given <i>contact</i> which is zero as default. | ||
87 | * | ||
88 | * @param contact Contact | ||
89 | */ | ||
90 | void | ||
91 | increase_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact); | ||
92 | |||
93 | /** | ||
94 | * Decreases the reference counter if possible (can not underflow!) of a given <i>contact</i> | ||
95 | * and returns GNUNET_YES if the counter is equal to zero, otherwise GNUNET_NO. | ||
96 | * | ||
97 | * @param contact Contact | ||
98 | * @return GNUNET_YES or GNUNET_NO depending on the reference counter | ||
99 | */ | ||
100 | int | ||
101 | decrease_contact_rc (struct GNUNET_MESSENGER_SrvContact *contact); | ||
102 | |||
103 | /** | ||
104 | * Returns the resulting hashcode of the public key from a given <i>contact</i>. | ||
105 | * | ||
106 | * @param contact Contact | ||
107 | * @return Hash of the contacts public key | ||
108 | */ | ||
109 | const struct GNUNET_HashCode* | ||
110 | get_contact_id_from_key (const struct GNUNET_MESSENGER_SrvContact *contact); | ||
111 | |||
112 | #endif //GNUNET_SERVICE_MESSENGER_CONTACT_H | ||
diff --git a/src/messenger/gnunet-service-messenger_handle.c b/src/messenger/gnunet-service-messenger_handle.c new file mode 100644 index 000000000..38ad6fbb4 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_handle.c | |||
@@ -0,0 +1,503 @@ | |||
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_handle.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_handle.h" | ||
27 | |||
28 | #include "gnunet-service-messenger.h" | ||
29 | #include "gnunet-service-messenger_message_kind.h" | ||
30 | |||
31 | struct GNUNET_MESSENGER_SrvHandle* | ||
32 | create_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq) | ||
33 | { | ||
34 | struct GNUNET_MESSENGER_SrvHandle *handle = GNUNET_new(struct GNUNET_MESSENGER_SrvHandle); | ||
35 | |||
36 | handle->service = service; | ||
37 | handle->mq = mq; | ||
38 | |||
39 | handle->name = NULL; | ||
40 | |||
41 | handle->operation = NULL; | ||
42 | |||
43 | handle->ego = NULL; | ||
44 | |||
45 | handle->member_ids = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | ||
46 | |||
47 | return handle; | ||
48 | } | ||
49 | |||
50 | int | ||
51 | iterate_free_member_ids (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
52 | { | ||
53 | GNUNET_free(value); | ||
54 | |||
55 | return GNUNET_YES; | ||
56 | } | ||
57 | |||
58 | void | ||
59 | destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle) | ||
60 | { | ||
61 | if (handle->service->dir) | ||
62 | save_handle_configuration(handle); | ||
63 | |||
64 | if (handle->operation) | ||
65 | GNUNET_IDENTITY_cancel (handle->operation); | ||
66 | |||
67 | if (handle->name) | ||
68 | GNUNET_free(handle->name); | ||
69 | |||
70 | GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_free_member_ids, NULL); | ||
71 | GNUNET_CONTAINER_multihashmap_destroy (handle->member_ids); | ||
72 | |||
73 | GNUNET_free(handle); | ||
74 | } | ||
75 | |||
76 | void | ||
77 | get_handle_data_subdir (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir) | ||
78 | { | ||
79 | if (name) | ||
80 | GNUNET_asprintf (dir, "%s%s%c%s%c", handle->service->dir, "identities", | ||
81 | DIR_SEPARATOR, name, DIR_SEPARATOR); | ||
82 | else | ||
83 | GNUNET_asprintf (dir, "%s%s%c", handle->service->dir, "anonymous", | ||
84 | DIR_SEPARATOR); | ||
85 | } | ||
86 | |||
87 | static int | ||
88 | create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) | ||
89 | { | ||
90 | struct GNUNET_ShortHashCode *random_id = generate_service_new_member_id (handle->service, key); | ||
91 | |||
92 | if (!random_id) | ||
93 | return GNUNET_NO; | ||
94 | |||
95 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, random_id, | ||
96 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
97 | { | ||
98 | GNUNET_free(random_id); | ||
99 | return GNUNET_NO; | ||
100 | } | ||
101 | |||
102 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Created a new member id (%s) for room: %s\n", | ||
103 | GNUNET_sh2s(random_id), GNUNET_h2s(key)); | ||
104 | |||
105 | return GNUNET_YES; | ||
106 | } | ||
107 | |||
108 | const struct GNUNET_ShortHashCode* | ||
109 | get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) | ||
110 | { | ||
111 | return GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key); | ||
112 | } | ||
113 | |||
114 | void | ||
115 | change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, | ||
116 | const struct GNUNET_ShortHashCode *unique_id) | ||
117 | { | ||
118 | struct GNUNET_ShortHashCode *member_id = GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key); | ||
119 | |||
120 | if (member_id) | ||
121 | { | ||
122 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Changed a member id (%s) for room (%s) ", | ||
123 | GNUNET_sh2s(member_id), GNUNET_h2s(key)); | ||
124 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, "into (%s).\n", | ||
125 | GNUNET_sh2s(unique_id)); | ||
126 | |||
127 | GNUNET_memcpy(member_id, unique_id, sizeof(*unique_id)); | ||
128 | |||
129 | struct GNUNET_MESSENGER_MemberMessage *msg; | ||
130 | struct GNUNET_MQ_Envelope *env; | ||
131 | |||
132 | env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID); | ||
133 | |||
134 | GNUNET_memcpy(&(msg->key), key, sizeof(*key)); | ||
135 | GNUNET_memcpy(&(msg->id), member_id, sizeof(*member_id)); | ||
136 | |||
137 | GNUNET_MQ_send (handle->mq, env); | ||
138 | } | ||
139 | else | ||
140 | { | ||
141 | member_id = GNUNET_new(struct GNUNET_ShortHashCode); | ||
142 | GNUNET_memcpy(member_id, unique_id, sizeof(*member_id)); | ||
143 | |||
144 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, member_id, | ||
145 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
146 | GNUNET_free(member_id); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static void | ||
151 | change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) | ||
152 | { | ||
153 | if (handle->name) | ||
154 | GNUNET_free(handle->name); | ||
155 | |||
156 | handle->name = name ? GNUNET_strdup(name) : NULL; | ||
157 | |||
158 | const uint16_t name_len = handle->name ? strlen (handle->name) : 0; | ||
159 | |||
160 | struct GNUNET_MESSENGER_NameMessage *msg; | ||
161 | struct GNUNET_MQ_Envelope *env; | ||
162 | |||
163 | env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME); | ||
164 | |||
165 | char *extra = ((char*) msg) + sizeof(*msg); | ||
166 | |||
167 | if (name_len) | ||
168 | GNUNET_memcpy(extra, handle->name, name_len); | ||
169 | |||
170 | extra[name_len] = '\0'; | ||
171 | |||
172 | GNUNET_MQ_send (handle->mq, env); | ||
173 | } | ||
174 | |||
175 | static void | ||
176 | change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, struct GNUNET_MESSENGER_Ego *ego) | ||
177 | { | ||
178 | handle->ego = ego; | ||
179 | |||
180 | ego = get_handle_ego(handle); | ||
181 | |||
182 | struct GNUNET_MESSENGER_KeyMessage *msg; | ||
183 | struct GNUNET_MQ_Envelope *env; | ||
184 | |||
185 | env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY); | ||
186 | |||
187 | GNUNET_memcpy(&(msg->pubkey), &(ego->pub), sizeof(ego->pub)); | ||
188 | |||
189 | GNUNET_MQ_send (handle->mq, env); | ||
190 | } | ||
191 | |||
192 | struct GNUNET_MESSENGER_Ego* | ||
193 | get_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle) | ||
194 | { | ||
195 | static struct GNUNET_MESSENGER_Ego anonymous; | ||
196 | static int read_keys = 0; | ||
197 | |||
198 | if (handle->ego) | ||
199 | return handle->ego; | ||
200 | |||
201 | if (!read_keys) | ||
202 | { | ||
203 | struct GNUNET_IDENTITY_Ego* ego = GNUNET_IDENTITY_ego_get_anonymous (); | ||
204 | GNUNET_memcpy(&(anonymous.priv), GNUNET_IDENTITY_ego_get_private_key(ego), sizeof(anonymous.priv)); | ||
205 | GNUNET_IDENTITY_ego_get_public_key(ego, &(anonymous.pub)); | ||
206 | read_keys = 1; | ||
207 | } | ||
208 | |||
209 | return &anonymous; | ||
210 | } | ||
211 | |||
212 | void | ||
213 | setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) | ||
214 | { | ||
215 | change_handle_name (handle, name); | ||
216 | change_handle_ego (handle, handle->name? lookup_service_ego(handle->service, handle->name) : NULL); | ||
217 | |||
218 | if (handle->service->dir) | ||
219 | load_handle_configuration(handle); | ||
220 | } | ||
221 | |||
222 | struct GNUNET_MESSENGER_MessageHandle | ||
223 | { | ||
224 | struct GNUNET_MESSENGER_SrvHandle *handle; | ||
225 | struct GNUNET_MESSENGER_Message *message; | ||
226 | }; | ||
227 | |||
228 | static int | ||
229 | iterate_send_message (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
230 | { | ||
231 | struct GNUNET_MESSENGER_MessageHandle *msg_handle = cls; | ||
232 | |||
233 | send_handle_message (msg_handle->handle, key, msg_handle->message); | ||
234 | |||
235 | return GNUNET_YES; | ||
236 | } | ||
237 | |||
238 | static void | ||
239 | callback_ego_create (void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *emsg) | ||
240 | { | ||
241 | struct GNUNET_MESSENGER_SrvHandle *handle = cls; | ||
242 | |||
243 | handle->operation = NULL; | ||
244 | |||
245 | if (emsg) | ||
246 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg); | ||
247 | |||
248 | if (key) | ||
249 | { | ||
250 | struct GNUNET_MESSENGER_MessageHandle msg_handle; | ||
251 | |||
252 | msg_handle.handle = handle; | ||
253 | msg_handle.message = create_message_key (key); | ||
254 | |||
255 | GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle); | ||
256 | |||
257 | destroy_message (msg_handle.message); | ||
258 | |||
259 | update_service_ego(handle->service, handle->name, key); | ||
260 | |||
261 | change_handle_ego (handle, lookup_service_ego(handle->service, handle->name)); | ||
262 | } | ||
263 | } | ||
264 | |||
265 | int | ||
266 | update_handle (struct GNUNET_MESSENGER_SrvHandle *handle) | ||
267 | { | ||
268 | GNUNET_assert(handle); | ||
269 | |||
270 | if (!handle->name) | ||
271 | return GNUNET_SYSERR; | ||
272 | |||
273 | struct GNUNET_MESSENGER_Ego *ego = lookup_service_ego(handle->service, handle->name); | ||
274 | |||
275 | if (!ego) | ||
276 | handle->operation = GNUNET_IDENTITY_create (handle->service->identity, handle->name, NULL, | ||
277 | GNUNET_IDENTITY_TYPE_ECDSA, callback_ego_create, handle); | ||
278 | else | ||
279 | change_handle_ego (handle, ego); | ||
280 | |||
281 | return GNUNET_OK; | ||
282 | } | ||
283 | |||
284 | int | ||
285 | set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name) | ||
286 | { | ||
287 | GNUNET_assert(handle); | ||
288 | |||
289 | if ((name) && (lookup_service_ego(handle->service, name))) | ||
290 | return GNUNET_NO; | ||
291 | |||
292 | struct GNUNET_IDENTITY_Operation *operation = handle->operation; | ||
293 | |||
294 | if (handle->name) | ||
295 | handle->operation = GNUNET_IDENTITY_rename (handle->service->identity, handle->name, name, NULL, NULL); | ||
296 | |||
297 | char *old_dir; | ||
298 | get_handle_data_subdir (handle, handle->name, &old_dir); | ||
299 | |||
300 | char *new_dir; | ||
301 | get_handle_data_subdir (handle, name, &new_dir); | ||
302 | |||
303 | int result = 0; | ||
304 | |||
305 | if (GNUNET_YES == GNUNET_DISK_directory_test (old_dir, GNUNET_YES)) | ||
306 | { | ||
307 | GNUNET_DISK_directory_create_for_file (new_dir); | ||
308 | |||
309 | result = rename (old_dir, new_dir); | ||
310 | } | ||
311 | else if (GNUNET_YES == GNUNET_DISK_directory_test (new_dir, GNUNET_NO)) | ||
312 | result = -1; | ||
313 | |||
314 | if (0 == result) | ||
315 | { | ||
316 | struct GNUNET_MESSENGER_MessageHandle msg_handle; | ||
317 | |||
318 | msg_handle.handle = handle; | ||
319 | msg_handle.message = create_message_name (name); | ||
320 | |||
321 | GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle); | ||
322 | |||
323 | destroy_message (msg_handle.message); | ||
324 | |||
325 | change_handle_name (handle, name); | ||
326 | |||
327 | if (operation) | ||
328 | GNUNET_IDENTITY_cancel (operation); | ||
329 | } | ||
330 | else | ||
331 | { | ||
332 | if (handle->operation) | ||
333 | { | ||
334 | GNUNET_IDENTITY_cancel (handle->operation); | ||
335 | |||
336 | handle->operation = operation; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | GNUNET_free(old_dir); | ||
341 | GNUNET_free(new_dir); | ||
342 | |||
343 | return (result == 0 ? GNUNET_OK : GNUNET_NO); | ||
344 | } | ||
345 | |||
346 | int | ||
347 | open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) | ||
348 | { | ||
349 | if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key))) | ||
350 | return GNUNET_NO; | ||
351 | |||
352 | return open_service_room (handle->service, handle, key); | ||
353 | } | ||
354 | |||
355 | int | ||
356 | entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door, | ||
357 | const struct GNUNET_HashCode *key) | ||
358 | { | ||
359 | if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key))) | ||
360 | return GNUNET_NO; | ||
361 | |||
362 | return entry_service_room (handle->service, handle, door, key); | ||
363 | } | ||
364 | |||
365 | int | ||
366 | close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) | ||
367 | { | ||
368 | if (!get_handle_member_id (handle, key)) | ||
369 | return GNUNET_NO; | ||
370 | |||
371 | return close_service_room (handle->service, handle, key); | ||
372 | } | ||
373 | |||
374 | int | ||
375 | send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, | ||
376 | struct GNUNET_MESSENGER_Message *message) | ||
377 | { | ||
378 | const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key); | ||
379 | |||
380 | if (!id) | ||
381 | { | ||
382 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "It is required to be a member of a room to send messages!\n"); | ||
383 | return GNUNET_NO; | ||
384 | } | ||
385 | |||
386 | struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (handle->service, key); | ||
387 | |||
388 | if (!room) | ||
389 | { | ||
390 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "The room (%s) is unknown!\n", GNUNET_h2s (key)); | ||
391 | return GNUNET_NO; | ||
392 | } | ||
393 | |||
394 | struct GNUNET_HashCode hash; | ||
395 | |||
396 | GNUNET_memcpy(&(message->header.sender_id), id, sizeof(*id)); | ||
397 | |||
398 | send_room_message (room, handle, message, &hash); | ||
399 | return GNUNET_YES; | ||
400 | } | ||
401 | |||
402 | static int callback_scan_for_rooms(void* cls, const char *filename) { | ||
403 | struct GNUNET_MESSENGER_SrvHandle* handle = cls; | ||
404 | |||
405 | struct GNUNET_CONFIGURATION_Handle* cfg = GNUNET_CONFIGURATION_create(); | ||
406 | |||
407 | if ((GNUNET_YES == GNUNET_DISK_file_test(filename)) && | ||
408 | (GNUNET_OK == GNUNET_CONFIGURATION_parse(cfg, filename))) | ||
409 | { | ||
410 | struct GNUNET_HashCode key; | ||
411 | struct GNUNET_ShortHashCode member_id; | ||
412 | |||
413 | if ((GNUNET_OK == GNUNET_CONFIGURATION_get_data(cfg, "room", "key", &key, sizeof(key))) && | ||
414 | (GNUNET_OK == GNUNET_CONFIGURATION_get_data(cfg, "room", "member_id", &member_id, sizeof(member_id)))) | ||
415 | change_handle_member_id(handle, &key, &member_id); | ||
416 | } | ||
417 | |||
418 | GNUNET_CONFIGURATION_destroy(cfg); | ||
419 | return GNUNET_OK; | ||
420 | } | ||
421 | |||
422 | void load_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle) { | ||
423 | char* id_dir; | ||
424 | get_handle_data_subdir(handle, handle->name, &id_dir); | ||
425 | |||
426 | if (GNUNET_YES == GNUNET_DISK_directory_test(id_dir, GNUNET_YES)) | ||
427 | { | ||
428 | char* scan_dir; | ||
429 | GNUNET_asprintf(&scan_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR); | ||
430 | |||
431 | if (GNUNET_OK == GNUNET_DISK_directory_test(scan_dir, GNUNET_YES)) | ||
432 | GNUNET_DISK_directory_scan(scan_dir, callback_scan_for_rooms, handle); | ||
433 | |||
434 | GNUNET_free(scan_dir); | ||
435 | } | ||
436 | |||
437 | GNUNET_free(id_dir); | ||
438 | } | ||
439 | |||
440 | static int | ||
441 | iterate_save_rooms(void* cls, const struct GNUNET_HashCode* key, void* value) | ||
442 | { | ||
443 | struct GNUNET_MESSENGER_SrvHandle* handle = cls; | ||
444 | struct GNUNET_ShortHashCode* member_id = value; | ||
445 | |||
446 | char* id_dir; | ||
447 | get_handle_data_subdir(handle, handle->name, &id_dir); | ||
448 | |||
449 | char* filename; | ||
450 | GNUNET_asprintf(&filename, "%s%s%c%s.cfg", | ||
451 | id_dir, "rooms", DIR_SEPARATOR, | ||
452 | GNUNET_h2s(key)); | ||
453 | |||
454 | GNUNET_free(id_dir); | ||
455 | |||
456 | struct GNUNET_CONFIGURATION_Handle* cfg = GNUNET_CONFIGURATION_create(); | ||
457 | |||
458 | char* key_data = GNUNET_STRINGS_data_to_string_alloc(key, sizeof(*key)); | ||
459 | |||
460 | if (key_data) | ||
461 | { | ||
462 | GNUNET_CONFIGURATION_set_value_string(cfg, "room", "key", key_data); | ||
463 | |||
464 | GNUNET_free(key_data); | ||
465 | } | ||
466 | |||
467 | char* member_id_data = GNUNET_STRINGS_data_to_string_alloc(member_id, sizeof(*member_id)); | ||
468 | |||
469 | if (member_id_data) | ||
470 | { | ||
471 | GNUNET_CONFIGURATION_set_value_string(cfg, "room", "member_id", member_id_data); | ||
472 | |||
473 | GNUNET_free(member_id_data); | ||
474 | } | ||
475 | |||
476 | GNUNET_CONFIGURATION_write(cfg, filename); | ||
477 | GNUNET_CONFIGURATION_destroy(cfg); | ||
478 | |||
479 | GNUNET_free(filename); | ||
480 | |||
481 | return GNUNET_YES; | ||
482 | } | ||
483 | |||
484 | void save_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle) | ||
485 | { | ||
486 | char* id_dir; | ||
487 | get_handle_data_subdir(handle, handle->name, &id_dir); | ||
488 | |||
489 | if ((GNUNET_YES == GNUNET_DISK_directory_test(id_dir, GNUNET_NO)) || | ||
490 | (GNUNET_OK == GNUNET_DISK_directory_create(id_dir))) | ||
491 | { | ||
492 | char* save_dir; | ||
493 | GNUNET_asprintf(&save_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR); | ||
494 | |||
495 | if ((GNUNET_YES == GNUNET_DISK_directory_test(save_dir, GNUNET_NO)) || | ||
496 | (GNUNET_OK == GNUNET_DISK_directory_create(save_dir))) | ||
497 | GNUNET_CONTAINER_multihashmap_iterate(handle->member_ids, iterate_save_rooms, handle); | ||
498 | |||
499 | GNUNET_free(save_dir); | ||
500 | } | ||
501 | |||
502 | GNUNET_free(id_dir); | ||
503 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_handle.h b/src/messenger/gnunet-service-messenger_handle.h new file mode 100644 index 000000000..81cf377a8 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_handle.h | |||
@@ -0,0 +1,216 @@ | |||
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_handle.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_HANDLE_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_HANDLE_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_cadet_service.h" | ||
31 | #include "gnunet_container_lib.h" | ||
32 | #include "gnunet_crypto_lib.h" | ||
33 | #include "gnunet_identity_service.h" | ||
34 | #include "gnunet_peer_lib.h" | ||
35 | #include "gnunet_mq_lib.h" | ||
36 | |||
37 | #include "gnunet-service-messenger_service.h" | ||
38 | |||
39 | #include "messenger_api_ego.h" | ||
40 | #include "messenger_api_message.h" | ||
41 | |||
42 | struct GNUNET_MESSENGER_SrvHandle | ||
43 | { | ||
44 | struct GNUNET_MESSENGER_Service *service; | ||
45 | struct GNUNET_MQ_Handle *mq; | ||
46 | |||
47 | char *name; | ||
48 | |||
49 | struct GNUNET_IDENTITY_Operation *operation; | ||
50 | |||
51 | struct GNUNET_MESSENGER_Ego *ego; | ||
52 | |||
53 | struct GNUNET_CONTAINER_MultiHashMap *member_ids; | ||
54 | }; | ||
55 | |||
56 | /** | ||
57 | * Creates and allocates a new handle related to a <i>service</i> and using a given <i>mq</i> (message queue). | ||
58 | * | ||
59 | * @param service MESSENGER Service | ||
60 | * @param mq Message queue | ||
61 | * @return New handle | ||
62 | */ | ||
63 | struct GNUNET_MESSENGER_SrvHandle* | ||
64 | create_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq); | ||
65 | |||
66 | /** | ||
67 | * Destroys a handle and frees its memory fully. | ||
68 | * | ||
69 | * @param handle Handle | ||
70 | */ | ||
71 | void | ||
72 | destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle); | ||
73 | |||
74 | /** | ||
75 | * Writes the path of the directory for a given <i>handle</i> using a specific <i>name</i> to the parameter | ||
76 | * <i>dir</i>. This directory will be used to store data regarding the handle and its messages. | ||
77 | * | ||
78 | * @param handle Handle | ||
79 | * @param name Potential name of the handle | ||
80 | * @param dir[out] Path to store data | ||
81 | */ | ||
82 | void | ||
83 | get_handle_data_subdir (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir); | ||
84 | |||
85 | /** | ||
86 | * Returns the member id of a given <i>handle</i> in a specific <i>room</i>. | ||
87 | * | ||
88 | * If the handle is not a member of the specific <i>room</i>, NULL gets returned. | ||
89 | * | ||
90 | * @param handle Handle | ||
91 | * @param key Key of a room | ||
92 | * @return Member id or NULL | ||
93 | */ | ||
94 | const struct GNUNET_ShortHashCode* | ||
95 | get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); | ||
96 | |||
97 | /** | ||
98 | * Changes the member id of a given <i>handle</i> in a specific <i>room</i> to match a <i>unique_id</i>. | ||
99 | * | ||
100 | * The client connected to the <i>handle</i> will be informed afterwards automatically. | ||
101 | * | ||
102 | * @param handle Handle | ||
103 | * @param key Key of a room | ||
104 | * @param unique_id Unique member id | ||
105 | */ | ||
106 | void | ||
107 | change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, | ||
108 | const struct GNUNET_ShortHashCode *unique_id); | ||
109 | |||
110 | /** | ||
111 | * Returns the EGO used by a given <i>handle</i>. | ||
112 | * | ||
113 | * @param handle Handle | ||
114 | * @return EGO keypair | ||
115 | */ | ||
116 | struct GNUNET_MESSENGER_Ego* | ||
117 | get_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle); | ||
118 | |||
119 | /** | ||
120 | * Tries to set the name and EGO key of a <i>handle</i> initially by looking up a specific <i>name</i>. | ||
121 | * | ||
122 | * @param handle Handle | ||
123 | * @param name Name (optionally: valid EGO name) | ||
124 | */ | ||
125 | void | ||
126 | setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name); | ||
127 | |||
128 | /** | ||
129 | * Tries to change the keypair of an EGO of a <i>handle</i> under the same name and informs all rooms | ||
130 | * about the change automatically. | ||
131 | * | ||
132 | * @param handle Handle | ||
133 | * @return GNUNET_OK on success, otherwise GNUNET_SYSERR | ||
134 | */ | ||
135 | int | ||
136 | update_handle (struct GNUNET_MESSENGER_SrvHandle *handle); | ||
137 | |||
138 | /** | ||
139 | * Tries to rename the handle which implies renaming the EGO its using and moving all related data into | ||
140 | * the directory fitting to the changed <i>name</i>. | ||
141 | * | ||
142 | * The client connected to the <i>handle</i> will be informed afterwards automatically. | ||
143 | * | ||
144 | * @param handle Handle | ||
145 | * @param name New name | ||
146 | * @return GNUNET_OK on success, otherwise GNUNET_NO | ||
147 | */ | ||
148 | int | ||
149 | set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name); | ||
150 | |||
151 | /** | ||
152 | * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and opens the | ||
153 | * room from the handles service. | ||
154 | * | ||
155 | * @param handle Handle | ||
156 | * @param key Key of a room | ||
157 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
158 | */ | ||
159 | int | ||
160 | open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); | ||
161 | |||
162 | /** | ||
163 | * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and enters the room | ||
164 | * through a tunnel to a peer identified by a given <i>door</i> (peer identity). | ||
165 | * | ||
166 | * @param handle Handle | ||
167 | * @param door Peer identity | ||
168 | * @param key Key of a room | ||
169 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
170 | */ | ||
171 | int | ||
172 | entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door, | ||
173 | const struct GNUNET_HashCode *key); | ||
174 | |||
175 | /** | ||
176 | * Removes the membership of the room using a specific <i>key</i> and closes it if no other handle | ||
177 | * from this service is still a member of it. | ||
178 | * | ||
179 | * @param handle Handle | ||
180 | * @param key Key of a room | ||
181 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
182 | */ | ||
183 | int | ||
184 | close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); | ||
185 | |||
186 | /** | ||
187 | * Sends a <i>message</i> from a given <i>handle</i> to the room using a specific <i>key</i>. | ||
188 | * | ||
189 | * @param handle Handle | ||
190 | * @param key Key of a room | ||
191 | * @param message Message | ||
192 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
193 | */ | ||
194 | int | ||
195 | send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key, | ||
196 | struct GNUNET_MESSENGER_Message *message); | ||
197 | |||
198 | /** | ||
199 | * Loads member ids and other potential configuration from a given <i>handle</i> which | ||
200 | * depends on the given name the <i>handle</i> uses. | ||
201 | * | ||
202 | * @param handle Handle | ||
203 | */ | ||
204 | void | ||
205 | load_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle); | ||
206 | |||
207 | /** | ||
208 | * Saves member ids and other potential configuration from a given <i>handle</i> which | ||
209 | * depends on the given name the <i>handle</i> uses. | ||
210 | * | ||
211 | * @param handle Handle | ||
212 | */ | ||
213 | void | ||
214 | save_handle_configuration(struct GNUNET_MESSENGER_SrvHandle *handle); | ||
215 | |||
216 | #endif //GNUNET_SERVICE_MESSENGER_HANDLE_H | ||
diff --git a/src/messenger/gnunet-service-messenger_list_handles.c b/src/messenger/gnunet-service-messenger_list_handles.c new file mode 100644 index 000000000..16a160dea --- /dev/null +++ b/src/messenger/gnunet-service-messenger_list_handles.c | |||
@@ -0,0 +1,95 @@ | |||
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_list_handles.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_list_handles.h" | ||
27 | |||
28 | #include "gnunet-service-messenger_handle.h" | ||
29 | |||
30 | void | ||
31 | init_list_handles (struct GNUNET_MESSENGER_ListHandles *handles) | ||
32 | { | ||
33 | GNUNET_assert(handles); | ||
34 | |||
35 | handles->head = NULL; | ||
36 | handles->tail = NULL; | ||
37 | } | ||
38 | |||
39 | void | ||
40 | clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles) | ||
41 | { | ||
42 | GNUNET_assert(handles); | ||
43 | |||
44 | while (handles->head) | ||
45 | { | ||
46 | struct GNUNET_MESSENGER_ListHandle *element = handles->head; | ||
47 | |||
48 | GNUNET_CONTAINER_DLL_remove(handles->head, handles->tail, element); | ||
49 | destroy_handle (element->handle); | ||
50 | GNUNET_free(element); | ||
51 | } | ||
52 | |||
53 | handles->head = NULL; | ||
54 | handles->tail = NULL; | ||
55 | } | ||
56 | |||
57 | void | ||
58 | add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle) | ||
59 | { | ||
60 | struct GNUNET_MESSENGER_ListHandle *element = GNUNET_new(struct GNUNET_MESSENGER_ListHandle); | ||
61 | |||
62 | element->handle = handle; | ||
63 | |||
64 | GNUNET_CONTAINER_DLL_insert_tail(handles->head, handles->tail, element); | ||
65 | } | ||
66 | |||
67 | int | ||
68 | remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle) | ||
69 | { | ||
70 | struct GNUNET_MESSENGER_ListHandle *element; | ||
71 | |||
72 | for (element = handles->head; element; element = element->next) | ||
73 | if (element->handle == handle) | ||
74 | break; | ||
75 | |||
76 | if (!element) | ||
77 | return GNUNET_NO; | ||
78 | |||
79 | GNUNET_CONTAINER_DLL_remove(handles->head, handles->tail, element); | ||
80 | GNUNET_free(element); | ||
81 | |||
82 | return GNUNET_YES; | ||
83 | } | ||
84 | |||
85 | void* | ||
86 | find_list_handle_by_member (struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key) | ||
87 | { | ||
88 | struct GNUNET_MESSENGER_ListHandle *element; | ||
89 | |||
90 | for (element = handles->head; element; element = element->next) | ||
91 | if (get_handle_member_id ((struct GNUNET_MESSENGER_SrvHandle*) element->handle, key)) | ||
92 | return element->handle; | ||
93 | |||
94 | return NULL; | ||
95 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_list_handles.h b/src/messenger/gnunet-service-messenger_list_handles.h new file mode 100644 index 000000000..fe92cc58a --- /dev/null +++ b/src/messenger/gnunet-service-messenger_list_handles.h | |||
@@ -0,0 +1,96 @@ | |||
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_list_handles.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_LIST_HANDLES_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_LIST_HANDLES_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_crypto_lib.h" | ||
31 | #include "gnunet_container_lib.h" | ||
32 | |||
33 | struct GNUNET_MESSENGER_ListHandle | ||
34 | { | ||
35 | struct GNUNET_MESSENGER_ListHandle *prev; | ||
36 | struct GNUNET_MESSENGER_ListHandle *next; | ||
37 | |||
38 | void *handle; | ||
39 | }; | ||
40 | |||
41 | struct GNUNET_MESSENGER_ListHandles | ||
42 | { | ||
43 | struct GNUNET_MESSENGER_ListHandle *head; | ||
44 | struct GNUNET_MESSENGER_ListHandle *tail; | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * Initializes list of handles as empty list. | ||
49 | * | ||
50 | * @param handles List of handles | ||
51 | */ | ||
52 | void | ||
53 | init_list_handles (struct GNUNET_MESSENGER_ListHandles *handles); | ||
54 | |||
55 | /** | ||
56 | * Destroys remaining handles and clears the list. | ||
57 | * | ||
58 | * @param handles List of handles | ||
59 | */ | ||
60 | void | ||
61 | clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles); | ||
62 | |||
63 | /** | ||
64 | * Adds a specific <i>handle</i> to the end of the list. | ||
65 | * | ||
66 | * @param handles List of handles | ||
67 | * @param handle Handle | ||
68 | */ | ||
69 | void | ||
70 | add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle); | ||
71 | |||
72 | /** | ||
73 | * Removes the first entry matching with a specific <i>handle</i> from the list and | ||
74 | * returns GNUNET_YES on success or GNUNET_NO on failure. | ||
75 | * | ||
76 | * @param handles List of handles | ||
77 | * @param handle Handle | ||
78 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
79 | */ | ||
80 | int | ||
81 | remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, void *handle); | ||
82 | |||
83 | /** | ||
84 | * Searches linearly through the list of handles for members of a specific room | ||
85 | * which is identified by a given <i>key</i>. | ||
86 | * | ||
87 | * If no handle is found which is a current member, NULL gets returned. | ||
88 | * | ||
89 | * @param handles List of handles | ||
90 | * @param key Common key of a room | ||
91 | * @return First handle which is a current member | ||
92 | */ | ||
93 | void* | ||
94 | find_list_handle_by_member (struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key); | ||
95 | |||
96 | #endif //GNUNET_SERVICE_MESSENGER_LIST_HANDLES_H | ||
diff --git a/src/messenger/gnunet-service-messenger_list_messages.c b/src/messenger/gnunet-service-messenger_list_messages.c new file mode 100644 index 000000000..c4f1f7043 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_list_messages.c | |||
@@ -0,0 +1,76 @@ | |||
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_list_messages.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_list_messages.h" | ||
27 | |||
28 | void | ||
29 | init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages) | ||
30 | { | ||
31 | GNUNET_assert(messages); | ||
32 | |||
33 | messages->head = NULL; | ||
34 | messages->tail = NULL; | ||
35 | } | ||
36 | |||
37 | void | ||
38 | clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages) | ||
39 | { | ||
40 | GNUNET_assert(messages); | ||
41 | |||
42 | while (messages->head) | ||
43 | { | ||
44 | struct GNUNET_MESSENGER_ListMessage *element = messages->head; | ||
45 | |||
46 | GNUNET_CONTAINER_DLL_remove(messages->head, messages->tail, element); | ||
47 | GNUNET_free(element); | ||
48 | } | ||
49 | |||
50 | messages->head = NULL; | ||
51 | messages->tail = NULL; | ||
52 | } | ||
53 | |||
54 | void | ||
55 | add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash) | ||
56 | { | ||
57 | struct GNUNET_MESSENGER_ListMessage *element = GNUNET_new(struct GNUNET_MESSENGER_ListMessage); | ||
58 | |||
59 | GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode)); | ||
60 | |||
61 | GNUNET_CONTAINER_DLL_insert_tail(messages->head, messages->tail, element); | ||
62 | } | ||
63 | |||
64 | void | ||
65 | remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash) | ||
66 | { | ||
67 | struct GNUNET_MESSENGER_ListMessage *element; | ||
68 | |||
69 | for (element = messages->head; element; element = element->next) | ||
70 | if (0 == GNUNET_CRYPTO_hash_cmp (&(element->hash), hash)) | ||
71 | { | ||
72 | GNUNET_CONTAINER_DLL_remove(messages->head, messages->tail, element); | ||
73 | GNUNET_free(element); | ||
74 | break; | ||
75 | } | ||
76 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_list_messages.h b/src/messenger/gnunet-service-messenger_list_messages.h new file mode 100644 index 000000000..266c30ec6 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_list_messages.h | |||
@@ -0,0 +1,81 @@ | |||
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_list_messages.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_LIST_MESSAGES_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_LIST_MESSAGES_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_crypto_lib.h" | ||
31 | #include "gnunet_container_lib.h" | ||
32 | |||
33 | struct GNUNET_MESSENGER_ListMessage | ||
34 | { | ||
35 | struct GNUNET_MESSENGER_ListMessage *prev; | ||
36 | struct GNUNET_MESSENGER_ListMessage *next; | ||
37 | |||
38 | struct GNUNET_HashCode hash; | ||
39 | }; | ||
40 | |||
41 | struct GNUNET_MESSENGER_ListMessages | ||
42 | { | ||
43 | struct GNUNET_MESSENGER_ListMessage *head; | ||
44 | struct GNUNET_MESSENGER_ListMessage *tail; | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * Initializes list of message hashes as empty list. | ||
49 | * | ||
50 | * @param messages List of hashes | ||
51 | */ | ||
52 | void | ||
53 | init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages); | ||
54 | |||
55 | /** | ||
56 | * Clears the list of message hashes. | ||
57 | * | ||
58 | * @param messages List of hashes | ||
59 | */ | ||
60 | void | ||
61 | clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages); | ||
62 | |||
63 | /** | ||
64 | * Adds a specific <i>hash</i> from a message to the end of the list. | ||
65 | * | ||
66 | * @param messages List of hashes | ||
67 | * @param hash Hash of message | ||
68 | */ | ||
69 | void | ||
70 | add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash); | ||
71 | |||
72 | /** | ||
73 | * Removes the first entry with a matching <i>hash</i> from the list. | ||
74 | * | ||
75 | * @param messages List of hashes | ||
76 | * @param hash Hash of message | ||
77 | */ | ||
78 | void | ||
79 | remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash); | ||
80 | |||
81 | #endif //GNUNET_SERVICE_MESSENGER_LIST_MESSAGES_H | ||
diff --git a/src/messenger/gnunet-service-messenger_message_handle.c b/src/messenger/gnunet-service-messenger_message_handle.c new file mode 100644 index 000000000..1652435c8 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_message_handle.c | |||
@@ -0,0 +1,130 @@ | |||
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_message_handle.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_message_handle.h" | ||
27 | |||
28 | void | ||
29 | handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
30 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
31 | { | ||
32 | struct GNUNET_MESSENGER_SrvContact *contact = get_room_contact (room, &(message->header.sender_id)); | ||
33 | |||
34 | if (!contact) | ||
35 | add_room_contact (room, &(message->header.sender_id), &(message->body.join.key)); | ||
36 | |||
37 | struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id)); | ||
38 | |||
39 | if (!info) | ||
40 | { | ||
41 | info = GNUNET_new(struct GNUNET_MESSENGER_MemberInfo); | ||
42 | |||
43 | info->access = GNUNET_MESSENGER_MEMBER_UNKNOWN; | ||
44 | init_list_messages (&(info->session_messages)); | ||
45 | } | ||
46 | else | ||
47 | clear_list_messages (&(info->session_messages)); | ||
48 | |||
49 | if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_put (room->member_infos, &(message->header.sender_id), info, | ||
50 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
51 | add_to_list_messages (&(info->session_messages), hash); | ||
52 | } | ||
53 | |||
54 | void | ||
55 | handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
56 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
57 | { | ||
58 | struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id)); | ||
59 | |||
60 | if (info) | ||
61 | clear_list_messages (&(info->session_messages)); | ||
62 | } | ||
63 | |||
64 | void | ||
65 | handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
66 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
67 | { | ||
68 | struct GNUNET_MESSENGER_SrvContact *contact = get_room_contact (room, &(message->header.sender_id)); | ||
69 | |||
70 | if (contact) | ||
71 | set_contact_name (contact, message->body.name.name); | ||
72 | |||
73 | struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id)); | ||
74 | |||
75 | if (info) | ||
76 | add_to_list_messages (&(info->session_messages), hash); | ||
77 | } | ||
78 | |||
79 | void | ||
80 | handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
81 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
82 | { | ||
83 | struct GNUNET_MESSENGER_SrvContact *contact = get_room_contact (room, &(message->header.sender_id)); | ||
84 | |||
85 | if (contact) | ||
86 | swap_service_contact_by_pubkey (room->service, contact, &(message->body.key.key)); | ||
87 | |||
88 | struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id)); | ||
89 | |||
90 | if (info) | ||
91 | add_to_list_messages (&(info->session_messages), hash); | ||
92 | } | ||
93 | |||
94 | void | ||
95 | handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
96 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
97 | { | ||
98 | if (GNUNET_NO == contains_list_tunnels (&(room->basement), &(message->body.peer.peer))) | ||
99 | add_to_list_tunnels (&(room->basement), &(message->body.peer.peer)); | ||
100 | |||
101 | if (room->peer_message) | ||
102 | rebuild_room_basement_structure (room); | ||
103 | } | ||
104 | |||
105 | void | ||
106 | handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
107 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
108 | { | ||
109 | struct GNUNET_MESSENGER_MemberInfo *info = get_room_member_info (room, &(message->header.sender_id)); | ||
110 | |||
111 | if (info) | ||
112 | add_to_list_messages (&(info->session_messages), hash); | ||
113 | |||
114 | switch_room_member_id (room, &(message->header.sender_id), &(message->body.id.id), hash); | ||
115 | } | ||
116 | |||
117 | void | ||
118 | handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
119 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
120 | { | ||
121 | struct GNUNET_MESSENGER_ListTunnel *element = find_list_tunnels (&(room->basement), &(message->body.peer.peer), NULL); | ||
122 | |||
123 | if (!element) | ||
124 | return; | ||
125 | |||
126 | remove_from_list_tunnels (&(room->basement), element); | ||
127 | |||
128 | if (room->peer_message) | ||
129 | rebuild_room_basement_structure (room); | ||
130 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_message_handle.h b/src/messenger/gnunet-service-messenger_message_handle.h new file mode 100644 index 000000000..d091e1d11 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_message_handle.h | |||
@@ -0,0 +1,128 @@ | |||
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_message_handle.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_HANDLE_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_MESSAGE_HANDLE_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_crypto_lib.h" | ||
31 | |||
32 | #include "gnunet-service-messenger_message_kind.h" | ||
33 | |||
34 | #include "gnunet-service-messenger_tunnel.h" | ||
35 | #include "messenger_api_message.h" | ||
36 | |||
37 | /** | ||
38 | * Handles a received or sent join message to make changes of current member information. | ||
39 | * (add matching member and clear member info) | ||
40 | * | ||
41 | * @param room Room of the message | ||
42 | * @param tunnel Receiving/sending connection (may be NULL) | ||
43 | * @param message JOIN-Message | ||
44 | * @param hash Hash of the message | ||
45 | */ | ||
46 | void | ||
47 | handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
48 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
49 | |||
50 | /** | ||
51 | * Handles a received or sent leave message to make changes of current member information. | ||
52 | * (remove matching member and clear member info) | ||
53 | * | ||
54 | * @param room Room of the message | ||
55 | * @param tunnel Receiving/sending connection (may be NULL) | ||
56 | * @param message LEAVE-Message | ||
57 | * @param hash Hash of the message | ||
58 | */ | ||
59 | void | ||
60 | handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
61 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
62 | |||
63 | /** | ||
64 | * Handles a received or sent name message to rename a current member. | ||
65 | * (change name of matching member) | ||
66 | * | ||
67 | * @param room Room of the message | ||
68 | * @param tunnel Receiving/sending connection (may be NULL) | ||
69 | * @param message NAME-Message | ||
70 | * @param hash Hash of the message | ||
71 | */ | ||
72 | void | ||
73 | handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
74 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
75 | |||
76 | /** | ||
77 | * Handles a received or sent key message to change the key of a member and rearrange the contacts accordingly. | ||
78 | * (move the member in the contacts and change its key) | ||
79 | * | ||
80 | * @param room Room of the message | ||
81 | * @param tunnel Receiving/sending connection (may be NULL) | ||
82 | * @param message KEY-Message | ||
83 | * @param hash Hash of the message | ||
84 | */ | ||
85 | void | ||
86 | handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
87 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
88 | |||
89 | /** | ||
90 | * Handles a received or sent peer message to make changes of the basement in the room. | ||
91 | * (add a new peer to the basement and restructure connections based on updated list of peers) | ||
92 | * | ||
93 | * @param room Room of the message | ||
94 | * @param tunnel Receiving/sending connection (may be NULL) | ||
95 | * @param message PEER-Message | ||
96 | * @param hash Hash of the message | ||
97 | */ | ||
98 | void | ||
99 | handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
100 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
101 | |||
102 | /** | ||
103 | * Handles a received or sent id message to change a members id. | ||
104 | * (change id of matching member) | ||
105 | * | ||
106 | * @param room Room of the message | ||
107 | * @param tunnel Receiving/sending connection (may be NULL) | ||
108 | * @param message ID-Message | ||
109 | * @param hash Hash of the message | ||
110 | */ | ||
111 | void | ||
112 | handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
113 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
114 | |||
115 | /** | ||
116 | * Handles a received or sent miss message to drop a peer from the basement in the room. | ||
117 | * (remove a peer from the basement and restructure connections based on updated list of peers) | ||
118 | * | ||
119 | * @param room Room of the message | ||
120 | * @param tunnel Receiving/sending connection (may be NULL) | ||
121 | * @param message MISS-Message | ||
122 | * @param hash Hash of the message | ||
123 | */ | ||
124 | void | ||
125 | handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
126 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
127 | |||
128 | #endif //GNUNET_SERVICE_MESSENGER_MESSAGE_HANDLE_H | ||
diff --git a/src/messenger/gnunet-service-messenger_message_kind.c b/src/messenger/gnunet-service-messenger_message_kind.c new file mode 100644 index 000000000..9c829fe09 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_message_kind.c | |||
@@ -0,0 +1,192 @@ | |||
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_message_kind.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_message_kind.h" | ||
27 | #include "gnunet-service-messenger_util.h" | ||
28 | |||
29 | struct GNUNET_MESSENGER_Message* | ||
30 | create_message_info (struct GNUNET_MESSENGER_Ego *ego, struct GNUNET_CONTAINER_MultiShortmap *members) | ||
31 | { | ||
32 | struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INFO); | ||
33 | |||
34 | if (!message) | ||
35 | return NULL; | ||
36 | |||
37 | GNUNET_memcpy(&(message->body.info.host_key), &(ego->pub), sizeof(ego->pub)); | ||
38 | |||
39 | if (GNUNET_YES == generate_free_member_id (&(message->body.info.unique_id), members)) | ||
40 | return message; | ||
41 | else | ||
42 | { | ||
43 | destroy_message (message); | ||
44 | return NULL; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | struct GNUNET_MESSENGER_Message* | ||
49 | create_message_join (struct GNUNET_MESSENGER_Ego *ego) | ||
50 | { | ||
51 | struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_JOIN); | ||
52 | |||
53 | if (!message) | ||
54 | return NULL; | ||
55 | |||
56 | GNUNET_memcpy(&(message->body.join.key), &(ego->pub), sizeof(ego->pub)); | ||
57 | |||
58 | return message; | ||
59 | } | ||
60 | |||
61 | struct GNUNET_MESSENGER_Message* | ||
62 | create_message_leave () | ||
63 | { | ||
64 | return create_message (GNUNET_MESSENGER_KIND_LEAVE); | ||
65 | } | ||
66 | |||
67 | struct GNUNET_MESSENGER_Message* | ||
68 | create_message_name (const char *name) | ||
69 | { | ||
70 | struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_NAME); | ||
71 | |||
72 | if (!message) | ||
73 | return NULL; | ||
74 | |||
75 | message->body.name.name = GNUNET_strdup(name); | ||
76 | return message; | ||
77 | } | ||
78 | |||
79 | struct GNUNET_MESSENGER_Message* | ||
80 | create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key) | ||
81 | { | ||
82 | struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_KEY); | ||
83 | |||
84 | if (!message) | ||
85 | return NULL; | ||
86 | |||
87 | GNUNET_IDENTITY_key_get_public (key, &(message->body.key.key)); | ||
88 | return message; | ||
89 | } | ||
90 | |||
91 | struct GNUNET_MESSENGER_Message* | ||
92 | create_message_peer (const struct GNUNET_MESSENGER_Service *service) | ||
93 | { | ||
94 | struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_PEER); | ||
95 | |||
96 | if (!message) | ||
97 | return NULL; | ||
98 | |||
99 | if (GNUNET_OK == get_service_peer_identity (service, &(message->body.peer.peer))) | ||
100 | return message; | ||
101 | else | ||
102 | { | ||
103 | destroy_message (message); | ||
104 | return NULL; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | struct GNUNET_MESSENGER_Message* | ||
109 | create_message_id (const struct GNUNET_ShortHashCode *unique_id) | ||
110 | { | ||
111 | struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_ID); | ||
112 | |||
113 | if (!message) | ||
114 | return NULL; | ||
115 | |||
116 | GNUNET_memcpy(&(message->body.id.id), unique_id, sizeof(struct GNUNET_ShortHashCode)); | ||
117 | |||
118 | return message; | ||
119 | } | ||
120 | |||
121 | struct GNUNET_MESSENGER_Message* | ||
122 | create_message_miss (const struct GNUNET_PeerIdentity *peer) | ||
123 | { | ||
124 | struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MISS); | ||
125 | |||
126 | if (!message) | ||
127 | { | ||
128 | return NULL; | ||
129 | } | ||
130 | |||
131 | GNUNET_memcpy(&(message->body.miss.peer), peer, sizeof(struct GNUNET_PeerIdentity)); | ||
132 | |||
133 | return message; | ||
134 | } | ||
135 | |||
136 | struct GNUNET_MESSENGER_Message* | ||
137 | create_message_merge (const struct GNUNET_HashCode *previous) | ||
138 | { | ||
139 | struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MERGE); | ||
140 | |||
141 | if (!message) | ||
142 | return NULL; | ||
143 | |||
144 | GNUNET_memcpy(&(message->body.merge.previous), previous, sizeof(struct GNUNET_HashCode)); | ||
145 | |||
146 | return message; | ||
147 | } | ||
148 | |||
149 | struct GNUNET_MESSENGER_Message* | ||
150 | create_message_request (const struct GNUNET_HashCode *hash) | ||
151 | { | ||
152 | struct GNUNET_HashCode zero; | ||
153 | memset (&zero, 0, sizeof(zero)); | ||
154 | |||
155 | if (0 == GNUNET_CRYPTO_hash_cmp (hash, &zero)) | ||
156 | return NULL; | ||
157 | |||
158 | struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_REQUEST); | ||
159 | |||
160 | if (!message) | ||
161 | return NULL; | ||
162 | |||
163 | GNUNET_memcpy(&(message->body.request.hash), hash, sizeof(struct GNUNET_HashCode)); | ||
164 | |||
165 | return message; | ||
166 | } | ||
167 | |||
168 | struct GNUNET_MESSENGER_Message* | ||
169 | create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key) | ||
170 | { | ||
171 | struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INVITE); | ||
172 | |||
173 | if (!message) | ||
174 | return NULL; | ||
175 | |||
176 | GNUNET_memcpy(&(message->body.invite.door), door, sizeof(struct GNUNET_PeerIdentity)); | ||
177 | GNUNET_memcpy(&(message->body.invite.key), key, sizeof(struct GNUNET_HashCode)); | ||
178 | |||
179 | return message; | ||
180 | } | ||
181 | |||
182 | struct GNUNET_MESSENGER_Message* | ||
183 | create_message_text (const char *text) | ||
184 | { | ||
185 | struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_TEXT); | ||
186 | |||
187 | if (!message) | ||
188 | return NULL; | ||
189 | |||
190 | message->body.text.text = GNUNET_strdup(text); | ||
191 | return message; | ||
192 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_message_kind.h b/src/messenger/gnunet-service-messenger_message_kind.h new file mode 100644 index 000000000..dd89d0b2f --- /dev/null +++ b/src/messenger/gnunet-service-messenger_message_kind.h | |||
@@ -0,0 +1,160 @@ | |||
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_message_kind.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_KIND_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_MESSAGE_KIND_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_container_lib.h" | ||
31 | #include "gnunet_crypto_lib.h" | ||
32 | #include "gnunet_identity_service.h" | ||
33 | |||
34 | #include "messenger_api_message.h" | ||
35 | #include "gnunet-service-messenger_service.h" | ||
36 | #include "messenger_api_ego.h" | ||
37 | |||
38 | /** | ||
39 | * Creates and allocates a new info message containing the hosts public key and a newly generated unique member id. | ||
40 | * (all values are stored as copy) | ||
41 | * | ||
42 | * @param ego EGO of the host | ||
43 | * @param members Map of all assigned member ids | ||
44 | * @return New message | ||
45 | */ | ||
46 | struct GNUNET_MESSENGER_Message* | ||
47 | create_message_info (struct GNUNET_MESSENGER_Ego *ego, struct GNUNET_CONTAINER_MultiShortmap *members); | ||
48 | |||
49 | /** | ||
50 | * Creates and allocates a new join message containing the clients public key. | ||
51 | * (all values are stored as copy) | ||
52 | * | ||
53 | * @param ego EGO of the client | ||
54 | * @return New message | ||
55 | */ | ||
56 | struct GNUNET_MESSENGER_Message* | ||
57 | create_message_join (struct GNUNET_MESSENGER_Ego *ego); | ||
58 | |||
59 | /** | ||
60 | * Creates and allocates a new leave message. | ||
61 | * | ||
62 | * @return New message | ||
63 | */ | ||
64 | struct GNUNET_MESSENGER_Message* | ||
65 | create_message_leave (); | ||
66 | |||
67 | /** | ||
68 | * Creates and allocates a new name message containing the <i>name</i> to change to. | ||
69 | * (all values are stored as copy) | ||
70 | * | ||
71 | * @param name New name | ||
72 | * @return New message | ||
73 | */ | ||
74 | struct GNUNET_MESSENGER_Message* | ||
75 | create_message_name (const char *name); | ||
76 | |||
77 | /** | ||
78 | * Creates and allocates a new key message containing the public key to change to derived | ||
79 | * from its private counterpart. (all values are stored as copy) | ||
80 | * | ||
81 | * @param key Private key of EGO | ||
82 | * @return New message | ||
83 | */ | ||
84 | struct GNUNET_MESSENGER_Message* | ||
85 | create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key); | ||
86 | |||
87 | /** | ||
88 | * Creates and allocates a new peer message containing a services peer identity. | ||
89 | * (all values are stored as copy) | ||
90 | * | ||
91 | * @param service Service | ||
92 | * @return New message | ||
93 | */ | ||
94 | struct GNUNET_MESSENGER_Message* | ||
95 | create_message_peer (const struct GNUNET_MESSENGER_Service *service); | ||
96 | |||
97 | /** | ||
98 | * Creates and allocates a new id message containing the unique member id to change to. | ||
99 | * (all values are stored as copy) | ||
100 | * | ||
101 | * @param unique_id Unique member id | ||
102 | * @return New message | ||
103 | */ | ||
104 | struct GNUNET_MESSENGER_Message* | ||
105 | create_message_id (const struct GNUNET_ShortHashCode *unique_id); | ||
106 | |||
107 | /** | ||
108 | * Creates and allocates a new miss message containing the missing peer identity. | ||
109 | * (all values are stored as copy) | ||
110 | * | ||
111 | * @param peer Missing peer identity | ||
112 | * @return New message | ||
113 | */ | ||
114 | struct GNUNET_MESSENGER_Message* | ||
115 | create_message_miss (const struct GNUNET_PeerIdentity *peer); | ||
116 | |||
117 | /** | ||
118 | * Creates and allocates a new merge message containing the hash of a second previous message | ||
119 | * besides the regular previous message mentioned in a messages header. | ||
120 | * (all values are stored as copy) | ||
121 | * | ||
122 | * @param previous Hash of message | ||
123 | * @return New message | ||
124 | */ | ||
125 | struct GNUNET_MESSENGER_Message* | ||
126 | create_message_merge (const struct GNUNET_HashCode *previous); | ||
127 | |||
128 | /** | ||
129 | * Creates and allocates a new request message containing the hash of a missing message. | ||
130 | * (all values are stored as copy) | ||
131 | * | ||
132 | * @param hash Hash of message | ||
133 | * @return New message | ||
134 | */ | ||
135 | struct GNUNET_MESSENGER_Message* | ||
136 | create_message_request (const struct GNUNET_HashCode *hash); | ||
137 | |||
138 | /** | ||
139 | * Creates and allocates a new invite message containing the peer identity of an entrance peer | ||
140 | * to a room using a given <i>key</i> as shared secret for communication. | ||
141 | * (all values are stored as copy) | ||
142 | * | ||
143 | * @param door Peer identity | ||
144 | * @param key Shared secret of a room | ||
145 | * @return New message | ||
146 | */ | ||
147 | struct GNUNET_MESSENGER_Message* | ||
148 | create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key); | ||
149 | |||
150 | /** | ||
151 | * Creates and allocates a new text message containing a string representing text. | ||
152 | * (all values are stored as copy) | ||
153 | * | ||
154 | * @param text Text | ||
155 | * @return New message | ||
156 | */ | ||
157 | struct GNUNET_MESSENGER_Message* | ||
158 | create_message_text (const char *text); | ||
159 | |||
160 | #endif //GNUNET_SERVICE_MESSENGER_MESSAGE_KIND_H | ||
diff --git a/src/messenger/gnunet-service-messenger_message_recv.c b/src/messenger/gnunet-service-messenger_message_recv.c new file mode 100644 index 000000000..aa28a36ea --- /dev/null +++ b/src/messenger/gnunet-service-messenger_message_recv.c | |||
@@ -0,0 +1,204 @@ | |||
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_message_recv.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_message_recv.h" | ||
27 | #include "gnunet-service-messenger_message_handle.h" | ||
28 | |||
29 | void | ||
30 | recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
31 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
32 | { | ||
33 | int conflict = GNUNET_CONTAINER_multishortmap_contains (room->members, &(message->body.info.unique_id)); | ||
34 | |||
35 | if (GNUNET_NO == conflict) | ||
36 | { | ||
37 | struct GNUNET_MESSENGER_Message *sync_message = create_message_id (&(message->body.info.unique_id)); | ||
38 | struct GNUNET_HashCode sync_hash; | ||
39 | |||
40 | send_room_message_ext (room, room->host, sync_message, &sync_hash, tunnel); | ||
41 | destroy_message (sync_message); | ||
42 | |||
43 | switch_room_member_id (room, get_room_host_id (room), &(message->body.info.unique_id), NULL); | ||
44 | |||
45 | change_room_host_id (room, &(message->body.info.unique_id)); | ||
46 | } | ||
47 | |||
48 | if (!tunnel->contact_id) | ||
49 | tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode); | ||
50 | |||
51 | GNUNET_memcpy(tunnel->contact_id, &(message->header.sender_id), sizeof(struct GNUNET_ShortHashCode)); | ||
52 | |||
53 | struct GNUNET_ShortHashCode original_id; | ||
54 | |||
55 | if (GNUNET_YES == conflict) | ||
56 | { | ||
57 | GNUNET_memcpy(&original_id, get_room_host_id (room), sizeof(struct GNUNET_ShortHashCode)); | ||
58 | |||
59 | change_room_host_id (room, &(message->body.info.unique_id)); | ||
60 | } | ||
61 | |||
62 | { | ||
63 | struct GNUNET_MESSENGER_Message *join_message = create_message_join (room->host->ego); | ||
64 | struct GNUNET_HashCode join_hash; | ||
65 | |||
66 | send_tunnel_message (tunnel, room->host, join_message, &join_hash); | ||
67 | destroy_message (join_message); | ||
68 | } | ||
69 | |||
70 | if ((GNUNET_YES == conflict) && (0 != GNUNET_memcmp(&original_id, get_room_host_id (room)))) | ||
71 | { | ||
72 | struct GNUNET_MESSENGER_Message *sync_message = create_message_id (&original_id); | ||
73 | struct GNUNET_HashCode sync_hash; | ||
74 | |||
75 | send_tunnel_message (tunnel, room->host, sync_message, &sync_hash); | ||
76 | destroy_message (sync_message); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | struct GNUNET_MESSENGER_MemberInfoSpread | ||
81 | { | ||
82 | struct GNUNET_MESSENGER_SrvRoom *room; | ||
83 | struct GNUNET_MESSENGER_SrvTunnel *tunnel; | ||
84 | }; | ||
85 | |||
86 | static int | ||
87 | iterate_send_member_infos (void *cls, const struct GNUNET_ShortHashCode *key, void *value) | ||
88 | { | ||
89 | struct GNUNET_MESSENGER_MemberInfo *info = value; | ||
90 | struct GNUNET_MESSENGER_MemberInfoSpread *spread = cls; | ||
91 | |||
92 | struct GNUNET_MESSENGER_ListMessage *element = info->session_messages.head; | ||
93 | |||
94 | while (element) | ||
95 | { | ||
96 | const struct GNUNET_MESSENGER_Message *message = get_room_message (spread->room, spread->room->host, | ||
97 | &(element->hash), GNUNET_NO); | ||
98 | |||
99 | if (message) | ||
100 | forward_tunnel_message (spread->tunnel, message, &(element->hash)); | ||
101 | |||
102 | element = element->next; | ||
103 | } | ||
104 | |||
105 | return GNUNET_YES; | ||
106 | } | ||
107 | |||
108 | void | ||
109 | recv_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
110 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
111 | { | ||
112 | const struct GNUNET_MESSENGER_Message *info_msg = get_room_message (room, room->host, &(message->header.previous), | ||
113 | GNUNET_NO); | ||
114 | |||
115 | if ((info_msg) && (0 == GNUNET_memcmp(&(info_msg->header.sender_id), get_room_host_id (room))) | ||
116 | && (GNUNET_MESSENGER_KIND_INFO == info_msg->header.kind)) | ||
117 | { | ||
118 | struct GNUNET_MESSENGER_MemberInfoSpread spread; | ||
119 | |||
120 | spread.room = room; | ||
121 | |||
122 | if ((tunnel) && (tunnel->contact_id) && (0 == GNUNET_memcmp(tunnel->contact_id, &(message->header.sender_id)))) | ||
123 | spread.tunnel = tunnel; | ||
124 | else | ||
125 | spread.tunnel = find_room_tunnel_to (room, &(message->header.sender_id)); | ||
126 | |||
127 | if (spread.tunnel) | ||
128 | GNUNET_CONTAINER_multishortmap_iterate (room->member_infos, iterate_send_member_infos, &spread); | ||
129 | } | ||
130 | |||
131 | handle_message_join (room, tunnel, message, hash); | ||
132 | } | ||
133 | |||
134 | void | ||
135 | recv_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
136 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
137 | { | ||
138 | handle_message_leave (room, tunnel, message, hash); | ||
139 | } | ||
140 | |||
141 | void | ||
142 | recv_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
143 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
144 | { | ||
145 | handle_message_name (room, tunnel, message, hash); | ||
146 | } | ||
147 | |||
148 | void | ||
149 | recv_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
150 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
151 | { | ||
152 | handle_message_key (room, tunnel, message, hash); | ||
153 | } | ||
154 | |||
155 | void | ||
156 | recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
157 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
158 | { | ||
159 | struct GNUNET_PeerIdentity peer; | ||
160 | GNUNET_PEER_resolve (tunnel->peer, &peer); | ||
161 | |||
162 | if (0 == GNUNET_memcmp(&peer, &(message->body.peer.peer))) | ||
163 | { | ||
164 | if (!tunnel->peer_message) | ||
165 | tunnel->peer_message = GNUNET_new(struct GNUNET_HashCode); | ||
166 | |||
167 | GNUNET_memcpy(tunnel->peer_message, hash, sizeof(struct GNUNET_HashCode)); | ||
168 | |||
169 | if (!tunnel->contact_id) | ||
170 | tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode); | ||
171 | |||
172 | GNUNET_memcpy(tunnel->contact_id, &(message->header.sender_id), sizeof(struct GNUNET_ShortHashCode)); | ||
173 | } | ||
174 | |||
175 | handle_message_peer (room, tunnel, message, hash); | ||
176 | } | ||
177 | |||
178 | void | ||
179 | recv_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
180 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
181 | { | ||
182 | if ((tunnel->contact_id) && (0 == GNUNET_memcmp(tunnel->contact_id, &(message->header.sender_id)))) | ||
183 | GNUNET_memcpy(tunnel->contact_id, &(message->body.id.id), sizeof(struct GNUNET_ShortHashCode)); | ||
184 | |||
185 | handle_message_id (room, tunnel, message, hash); | ||
186 | } | ||
187 | |||
188 | void | ||
189 | recv_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
190 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
191 | { | ||
192 | handle_message_miss (room, tunnel, message, hash); | ||
193 | } | ||
194 | |||
195 | void | ||
196 | recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
197 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
198 | { | ||
199 | const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, room->host, &(message->body.request.hash), | ||
200 | GNUNET_NO); | ||
201 | |||
202 | if (msg) | ||
203 | forward_tunnel_message (tunnel, msg, &(message->body.request.hash)); | ||
204 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_message_recv.h b/src/messenger/gnunet-service-messenger_message_recv.h new file mode 100644 index 000000000..245612cb0 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_message_recv.h | |||
@@ -0,0 +1,159 @@ | |||
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_message_recv.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_RECV_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_MESSAGE_RECV_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_crypto_lib.h" | ||
31 | |||
32 | #include "gnunet-service-messenger_tunnel.h" | ||
33 | #include "messenger_api_message.h" | ||
34 | |||
35 | /** | ||
36 | * Handles a received info message to change the current member id to the one generated by | ||
37 | * the host connected to. (all current tunnels will be informed about the id change) | ||
38 | * | ||
39 | * @param room Room of the message | ||
40 | * @param tunnel Receiving connection | ||
41 | * @param message INFO-Message | ||
42 | * @param hash Hash of the message | ||
43 | */ | ||
44 | void | ||
45 | recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
46 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
47 | |||
48 | /** | ||
49 | * Handles a received join message to forward all member information to the new member if the message was | ||
50 | * the direct reaction to a previous info message from this peer. | ||
51 | * | ||
52 | * @param room Room of the message | ||
53 | * @param tunnel Receiving connection | ||
54 | * @param message JOIN-Message | ||
55 | * @param hash Hash of the message | ||
56 | */ | ||
57 | void | ||
58 | recv_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
59 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
60 | |||
61 | /** | ||
62 | * Handles a received leave message. | ||
63 | * @see handle_message_leave() | ||
64 | * | ||
65 | * @param room Room of the message | ||
66 | * @param tunnel Receiving connection | ||
67 | * @param message LEAVE-Message | ||
68 | * @param hash Hash of the message | ||
69 | */ | ||
70 | void | ||
71 | recv_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
72 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
73 | |||
74 | /** | ||
75 | * Handles a received name message. | ||
76 | * @see handle_message_name() | ||
77 | * | ||
78 | * @param room Room of the message | ||
79 | * @param tunnel Receiving connection | ||
80 | * @param message NAME-Message | ||
81 | * @param hash Hash of the message | ||
82 | */ | ||
83 | void | ||
84 | recv_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
85 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
86 | |||
87 | /** | ||
88 | * Handles a received key message. | ||
89 | * @see handle_message_key() | ||
90 | * | ||
91 | * @param room Room of the message | ||
92 | * @param tunnel Receiving connection | ||
93 | * @param message KEY-Message | ||
94 | * @param hash Hash of the message | ||
95 | */ | ||
96 | void | ||
97 | recv_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
98 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
99 | |||
100 | /** | ||
101 | * Handles a received peer message to link it to its origin tunnel if the peer identity matches. | ||
102 | * (the peer message and the member id can potentially be linked to the tunnel) | ||
103 | * | ||
104 | * TODO: This handling will only check the one given tunnel! | ||
105 | * | ||
106 | * @param room Room of the message | ||
107 | * @param tunnel Receiving connection | ||
108 | * @param message PEER-Message | ||
109 | * @param hash Hash of the message | ||
110 | */ | ||
111 | void | ||
112 | recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
113 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
114 | |||
115 | /** | ||
116 | * Handles a received id message to change the tunnels linked member id if necessary. | ||
117 | * (the tunnels linked member id will be changed if the sender id is matching) | ||
118 | * | ||
119 | * TODO: This handling will only check the one given tunnel! | ||
120 | * | ||
121 | * @param room Room of the message | ||
122 | * @param tunnel Receiving connection | ||
123 | * @param message ID-Message | ||
124 | * @param hash Hash of the message | ||
125 | */ | ||
126 | void | ||
127 | recv_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
128 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
129 | |||
130 | /** | ||
131 | * Handles a received miss message. | ||
132 | * @see handle_message_miss() | ||
133 | * | ||
134 | * @param room Room of the message | ||
135 | * @param tunnel Receiving connection | ||
136 | * @param message MISS-Message | ||
137 | * @param hash Hash of the message | ||
138 | */ | ||
139 | void | ||
140 | recv_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
141 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
142 | |||
143 | /** | ||
144 | * Handles a received request message by checking for the requested message and forwarding it back | ||
145 | * if the message was found. | ||
146 | * (this can also cause this peer to send a new request instead of only forwarding the received one) | ||
147 | * | ||
148 | * TODO: Requests can cause exponentially more requests! | ||
149 | * | ||
150 | * @param room Room of the message | ||
151 | * @param tunnel Receiving connection | ||
152 | * @param message REQUEST-Message | ||
153 | * @param hash Hash of the message | ||
154 | */ | ||
155 | void | ||
156 | recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
157 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
158 | |||
159 | #endif //GNUNET_SERVICE_MESSENGER_MESSAGE_RECV_H | ||
diff --git a/src/messenger/gnunet-service-messenger_message_send.c b/src/messenger/gnunet-service-messenger_message_send.c new file mode 100644 index 000000000..86cf9b888 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_message_send.c | |||
@@ -0,0 +1,118 @@ | |||
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_message_send.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_message_send.h" | ||
27 | #include "gnunet-service-messenger_message_handle.h" | ||
28 | |||
29 | void | ||
30 | send_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
31 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
32 | const struct GNUNET_HashCode *hash) | ||
33 | { | ||
34 | if (!tunnel->contact_id) | ||
35 | { | ||
36 | tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode); | ||
37 | |||
38 | GNUNET_memcpy(tunnel->contact_id, &(message->body.info.unique_id), sizeof(struct GNUNET_ShortHashCode)); | ||
39 | } | ||
40 | else | ||
41 | { | ||
42 | disconnect_tunnel (tunnel); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | void | ||
47 | send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
48 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
49 | const struct GNUNET_HashCode *hash) | ||
50 | { | ||
51 | handle_message_join (room, tunnel, message, hash); | ||
52 | |||
53 | if (room->peer_message) | ||
54 | { | ||
55 | const struct GNUNET_MESSENGER_Message *peer_message = get_room_message (room, handle, room->peer_message, | ||
56 | GNUNET_NO); | ||
57 | |||
58 | if ((peer_message) && (tunnel)) | ||
59 | { | ||
60 | forward_tunnel_message (tunnel, peer_message, room->peer_message); | ||
61 | } | ||
62 | } | ||
63 | } | ||
64 | |||
65 | void | ||
66 | send_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
67 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
68 | const struct GNUNET_HashCode *hash) | ||
69 | { | ||
70 | handle_message_leave (room, tunnel, message, hash); | ||
71 | } | ||
72 | |||
73 | void | ||
74 | send_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
75 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
76 | const struct GNUNET_HashCode *hash) | ||
77 | { | ||
78 | handle_message_name (room, tunnel, message, hash); | ||
79 | } | ||
80 | |||
81 | void | ||
82 | send_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
83 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
84 | const struct GNUNET_HashCode *hash) | ||
85 | { | ||
86 | handle_message_key (room, tunnel, message, hash); | ||
87 | } | ||
88 | |||
89 | void | ||
90 | send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
91 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
92 | const struct GNUNET_HashCode *hash) | ||
93 | { | ||
94 | if (!room->peer_message) | ||
95 | { | ||
96 | room->peer_message = GNUNET_new(struct GNUNET_HashCode); | ||
97 | } | ||
98 | |||
99 | GNUNET_memcpy(room->peer_message, hash, sizeof(struct GNUNET_HashCode)); | ||
100 | |||
101 | handle_message_peer (room, tunnel, message, hash); | ||
102 | } | ||
103 | |||
104 | void | ||
105 | send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
106 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
107 | const struct GNUNET_HashCode *hash) | ||
108 | { | ||
109 | handle_message_id (room, tunnel, message, hash); | ||
110 | } | ||
111 | |||
112 | void | ||
113 | send_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
114 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
115 | const struct GNUNET_HashCode *hash) | ||
116 | { | ||
117 | handle_message_miss (room, tunnel, message, hash); | ||
118 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_message_send.h b/src/messenger/gnunet-service-messenger_message_send.h new file mode 100644 index 000000000..c1096205a --- /dev/null +++ b/src/messenger/gnunet-service-messenger_message_send.h | |||
@@ -0,0 +1,155 @@ | |||
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_message_send.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_SEND_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_MESSAGE_SEND_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_crypto_lib.h" | ||
31 | |||
32 | #include "gnunet-service-messenger_tunnel.h" | ||
33 | #include "messenger_api_message.h" | ||
34 | |||
35 | /** | ||
36 | * Handles a sent info message to setup a tunnels linked member id. | ||
37 | * (if a tunnel has already got a member id linked to it, the connection will be closed) | ||
38 | * | ||
39 | * @param room Room of the message | ||
40 | * @param handle Sending handle | ||
41 | * @param tunnel Sending connection (may be NULL) | ||
42 | * @param message INFO-Message | ||
43 | * @param hash Hash of the message | ||
44 | */ | ||
45 | void | ||
46 | send_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
47 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
48 | const struct GNUNET_HashCode *hash); | ||
49 | |||
50 | /** | ||
51 | * Handles a sent join message to ensure growth of the decentralized room structure. | ||
52 | * (if the service provides a peer message for this room currently, it will be forwarded) | ||
53 | * | ||
54 | * @param room Room of the message | ||
55 | * @param handle Sending handle | ||
56 | * @param tunnel Sending connection (may be NULL) | ||
57 | * @param message JOIN-Message | ||
58 | * @param hash Hash of the message | ||
59 | */ | ||
60 | void | ||
61 | send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
62 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
63 | const struct GNUNET_HashCode *hash); | ||
64 | |||
65 | /** | ||
66 | * Handles a sent leave message. | ||
67 | * @see handle_message_leave() | ||
68 | * | ||
69 | * @param room Room of the message | ||
70 | * @param handle Sending handle | ||
71 | * @param tunnel Sending connection (may be NULL) | ||
72 | * @param message LEAVE-Message | ||
73 | * @param hash Hash of the message | ||
74 | */ | ||
75 | void | ||
76 | send_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
77 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
78 | const struct GNUNET_HashCode *hash); | ||
79 | |||
80 | /** | ||
81 | * Handles a sent name message. | ||
82 | * @see handle_message_name() | ||
83 | * | ||
84 | * @param room Room of the message | ||
85 | * @param handle Sending handle | ||
86 | * @param tunnel Sending connection (may be NULL) | ||
87 | * @param message NAME-Message | ||
88 | * @param hash Hash of the message | ||
89 | */ | ||
90 | void | ||
91 | send_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
92 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
93 | const struct GNUNET_HashCode *hash); | ||
94 | |||
95 | /** | ||
96 | * Handles a sent key message. | ||
97 | * @see handle_message_key() | ||
98 | * | ||
99 | * @param room Room of the message | ||
100 | * @param handle Sending handle | ||
101 | * @param tunnel Sending connection (may be NULL) | ||
102 | * @param message KEY-Message | ||
103 | * @param hash Hash of the message | ||
104 | */ | ||
105 | void | ||
106 | send_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
107 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
108 | const struct GNUNET_HashCode *hash); | ||
109 | |||
110 | /** | ||
111 | * Handles a sent peer message to update the rooms peer message of this service. | ||
112 | * (a set peer message indicates this service being a part of the decentralized room structure) | ||
113 | * | ||
114 | * @param room Room of the message | ||
115 | * @param handle Sending handle | ||
116 | * @param tunnel Sending connection (may be NULL) | ||
117 | * @param message PEER-Message | ||
118 | * @param hash Hash of the message | ||
119 | */ | ||
120 | void | ||
121 | send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
122 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
123 | const struct GNUNET_HashCode *hash); | ||
124 | |||
125 | /** | ||
126 | * Handles a sent id message. | ||
127 | * @see handle_message_id() | ||
128 | * | ||
129 | * @param room Room of the message | ||
130 | * @param handle Sending handle | ||
131 | * @param tunnel Sending connection (may be NULL) | ||
132 | * @param message ID-Message | ||
133 | * @param hash Hash of the message | ||
134 | */ | ||
135 | void | ||
136 | send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
137 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
138 | const struct GNUNET_HashCode *hash); | ||
139 | |||
140 | /** | ||
141 | * Handles a sent miss message. | ||
142 | * @see handle_message_miss() | ||
143 | * | ||
144 | * @param room Room of the message | ||
145 | * @param handle Sending handle | ||
146 | * @param tunnel Sending connection (may be NULL) | ||
147 | * @param message MISS-Message | ||
148 | * @param hash Hash of the message | ||
149 | */ | ||
150 | void | ||
151 | send_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
152 | struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MESSENGER_Message *message, | ||
153 | const struct GNUNET_HashCode *hash); | ||
154 | |||
155 | #endif //GNUNET_SERVICE_MESSENGER_MESSAGE_SEND_H | ||
diff --git a/src/messenger/gnunet-service-messenger_message_store.c b/src/messenger/gnunet-service-messenger_message_store.c new file mode 100644 index 000000000..5933d6390 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_message_store.c | |||
@@ -0,0 +1,282 @@ | |||
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_message_store.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_message_store.h" | ||
27 | #include "messenger_api_message.h" | ||
28 | |||
29 | void | ||
30 | init_message_store (struct GNUNET_MESSENGER_MessageStore *store) | ||
31 | { | ||
32 | store->storage_messages = NULL; | ||
33 | |||
34 | store->entries = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | ||
35 | store->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | ||
36 | } | ||
37 | |||
38 | static int | ||
39 | iterate_destroy_entries (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
40 | { | ||
41 | struct GNUNET_MESSENGER_MessageEntry *entry = value; | ||
42 | |||
43 | GNUNET_free(entry); | ||
44 | |||
45 | return GNUNET_YES; | ||
46 | } | ||
47 | |||
48 | static int | ||
49 | iterate_destroy_messages (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
50 | { | ||
51 | struct GNUNET_MESSENGER_Message *message = value; | ||
52 | |||
53 | destroy_message (message); | ||
54 | |||
55 | return GNUNET_YES; | ||
56 | } | ||
57 | |||
58 | void | ||
59 | clear_message_store (struct GNUNET_MESSENGER_MessageStore *store) | ||
60 | { | ||
61 | if (store->storage_messages) | ||
62 | { | ||
63 | GNUNET_DISK_file_close (store->storage_messages); | ||
64 | |||
65 | store->storage_messages = NULL; | ||
66 | } | ||
67 | |||
68 | GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_destroy_entries, NULL); | ||
69 | GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_destroy_messages, NULL); | ||
70 | |||
71 | GNUNET_CONTAINER_multihashmap_destroy (store->entries); | ||
72 | GNUNET_CONTAINER_multihashmap_destroy (store->messages); | ||
73 | } | ||
74 | |||
75 | struct GNUNET_MESSENGER_MessageEntryStorage | ||
76 | { | ||
77 | struct GNUNET_HashCode hash; | ||
78 | struct GNUNET_MESSENGER_MessageEntry entry; | ||
79 | }; | ||
80 | |||
81 | void | ||
82 | load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory) | ||
83 | { | ||
84 | enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); | ||
85 | |||
86 | if (store->storage_messages) | ||
87 | GNUNET_DISK_file_close (store->storage_messages); | ||
88 | |||
89 | char *filename; | ||
90 | GNUNET_asprintf (&filename, "%s%s", directory, "messages.store"); | ||
91 | |||
92 | if (GNUNET_YES == GNUNET_DISK_file_test (filename)) | ||
93 | store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission); | ||
94 | else | ||
95 | store->storage_messages = NULL; | ||
96 | |||
97 | GNUNET_free(filename); | ||
98 | |||
99 | if (!store->storage_messages) | ||
100 | return; | ||
101 | |||
102 | GNUNET_asprintf (&filename, "%s%s", directory, "entries.store"); | ||
103 | |||
104 | if (GNUNET_YES != GNUNET_DISK_file_test (filename)) | ||
105 | goto free_filename; | ||
106 | |||
107 | struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission); | ||
108 | |||
109 | if (!entries) | ||
110 | goto free_filename; | ||
111 | |||
112 | struct GNUNET_MESSENGER_MessageEntryStorage storage; | ||
113 | struct GNUNET_MESSENGER_MessageEntry *entry; | ||
114 | |||
115 | do | ||
116 | { | ||
117 | entry = GNUNET_new(struct GNUNET_MESSENGER_MessageEntry); | ||
118 | |||
119 | if (GNUNET_DISK_file_read (entries, &storage, sizeof(storage)) == sizeof(storage)) | ||
120 | { | ||
121 | GNUNET_memcpy(entry, &(storage.entry), sizeof(*entry)); | ||
122 | |||
123 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->entries, &(storage.hash), entry, | ||
124 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
125 | GNUNET_free(entry); | ||
126 | } | ||
127 | else | ||
128 | { | ||
129 | GNUNET_free(entry); | ||
130 | |||
131 | entry = NULL; | ||
132 | } | ||
133 | } | ||
134 | while (entry); | ||
135 | |||
136 | GNUNET_DISK_file_close (entries); | ||
137 | |||
138 | free_filename: | ||
139 | GNUNET_free(filename); | ||
140 | } | ||
141 | |||
142 | struct GNUNET_MESSENGER_MessageSave | ||
143 | { | ||
144 | struct GNUNET_MESSENGER_MessageStore *store; | ||
145 | |||
146 | struct GNUNET_DISK_FileHandle *storage_entries; | ||
147 | }; | ||
148 | |||
149 | static int | ||
150 | iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
151 | { | ||
152 | struct GNUNET_MESSENGER_MessageSave *save = cls; | ||
153 | |||
154 | if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (save->store->entries, key)) | ||
155 | return GNUNET_YES; | ||
156 | |||
157 | struct GNUNET_MESSENGER_Message *message = value; | ||
158 | struct GNUNET_MESSENGER_MessageEntryStorage storage; | ||
159 | |||
160 | GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash)); | ||
161 | |||
162 | storage.entry.length = get_message_size (message); | ||
163 | storage.entry.offset = GNUNET_DISK_file_seek (save->store->storage_messages, 0, GNUNET_DISK_SEEK_END); | ||
164 | |||
165 | if ((GNUNET_SYSERR == storage.entry.offset) || | ||
166 | (sizeof(storage) != GNUNET_DISK_file_write (save->storage_entries, &storage, sizeof(storage)))) | ||
167 | return GNUNET_YES; | ||
168 | |||
169 | char *buffer = GNUNET_malloc(storage.entry.length); | ||
170 | |||
171 | encode_message (message, storage.entry.length, buffer); | ||
172 | |||
173 | GNUNET_DISK_file_write (save->store->storage_messages, buffer, storage.entry.length); | ||
174 | |||
175 | GNUNET_free(buffer); | ||
176 | |||
177 | return GNUNET_YES; | ||
178 | } | ||
179 | |||
180 | void | ||
181 | save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory) | ||
182 | { | ||
183 | struct GNUNET_MESSENGER_MessageSave save; | ||
184 | |||
185 | enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); | ||
186 | |||
187 | char *filename; | ||
188 | GNUNET_asprintf (&filename, "%s%s", directory, "entries.store"); | ||
189 | |||
190 | save.store = store; | ||
191 | save.storage_entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission); | ||
192 | |||
193 | GNUNET_free(filename); | ||
194 | |||
195 | if (!save.storage_entries) | ||
196 | return; | ||
197 | |||
198 | if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage_entries, 0, GNUNET_DISK_SEEK_END)) | ||
199 | goto close_entries; | ||
200 | |||
201 | if (store->storage_messages) | ||
202 | GNUNET_DISK_file_close (store->storage_messages); | ||
203 | |||
204 | GNUNET_asprintf (&filename, "%s%s", directory, "messages.store"); | ||
205 | |||
206 | store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE, | ||
207 | permission); | ||
208 | |||
209 | GNUNET_free(filename); | ||
210 | |||
211 | if (store->storage_messages) | ||
212 | { | ||
213 | GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_save_messages, &save); | ||
214 | |||
215 | GNUNET_DISK_file_sync (store->storage_messages); | ||
216 | GNUNET_DISK_file_sync (save.storage_entries); | ||
217 | } | ||
218 | |||
219 | close_entries: | ||
220 | GNUNET_DISK_file_close (save.storage_entries); | ||
221 | } | ||
222 | |||
223 | int | ||
224 | contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash) | ||
225 | { | ||
226 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->messages, hash)) | ||
227 | return GNUNET_YES; | ||
228 | |||
229 | return GNUNET_CONTAINER_multihashmap_contains (store->entries, hash); | ||
230 | } | ||
231 | |||
232 | const struct GNUNET_MESSENGER_Message* | ||
233 | get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash) | ||
234 | { | ||
235 | struct GNUNET_MESSENGER_Message *message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash); | ||
236 | |||
237 | if (message) | ||
238 | return message; | ||
239 | |||
240 | if (!store->storage_messages) | ||
241 | return NULL; | ||
242 | |||
243 | const struct GNUNET_MESSENGER_MessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash); | ||
244 | |||
245 | if (!entry) | ||
246 | return NULL; | ||
247 | |||
248 | if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages, entry->offset, GNUNET_DISK_SEEK_SET)) | ||
249 | return message; | ||
250 | |||
251 | char *buffer = GNUNET_malloc(entry->length); | ||
252 | |||
253 | if (GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length) | ||
254 | goto free_buffer; | ||
255 | |||
256 | |||
257 | message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN); | ||
258 | |||
259 | if ((GNUNET_YES != decode_message (message, entry->length, buffer)) || (GNUNET_OK | ||
260 | != GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message, | ||
261 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) | ||
262 | { | ||
263 | destroy_message (message); | ||
264 | |||
265 | message = NULL; | ||
266 | |||
267 | GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry); | ||
268 | } | ||
269 | |||
270 | free_buffer: | ||
271 | GNUNET_free(buffer); | ||
272 | |||
273 | return message; | ||
274 | } | ||
275 | |||
276 | int | ||
277 | put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, | ||
278 | struct GNUNET_MESSENGER_Message *message) | ||
279 | { | ||
280 | return GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message, | ||
281 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
282 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_message_store.h b/src/messenger/gnunet-service-messenger_message_store.h new file mode 100644 index 000000000..e58459b21 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_message_store.h | |||
@@ -0,0 +1,120 @@ | |||
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_message_store.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_STORE_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_MESSAGE_STORE_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_container_lib.h" | ||
31 | #include "gnunet_disk_lib.h" | ||
32 | |||
33 | struct GNUNET_MESSENGER_MessageEntry | ||
34 | { | ||
35 | off_t offset; | ||
36 | uint16_t length; | ||
37 | }; | ||
38 | |||
39 | struct GNUNET_MESSENGER_MessageStore | ||
40 | { | ||
41 | struct GNUNET_DISK_FileHandle *storage_messages; | ||
42 | |||
43 | struct GNUNET_CONTAINER_MultiHashMap *entries; | ||
44 | struct GNUNET_CONTAINER_MultiHashMap *messages; | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * Initializes a message store as fully empty. | ||
49 | * | ||
50 | * @param store Message store | ||
51 | */ | ||
52 | void | ||
53 | init_message_store (struct GNUNET_MESSENGER_MessageStore *store); | ||
54 | |||
55 | /** | ||
56 | * Clears a message store, wipes its content and deallocates its memory. | ||
57 | * | ||
58 | * @param store Message store | ||
59 | */ | ||
60 | void | ||
61 | clear_message_store (struct GNUNET_MESSENGER_MessageStore *store); | ||
62 | |||
63 | /** | ||
64 | * Loads messages from a directory into a message store. | ||
65 | * | ||
66 | * @param store Message store | ||
67 | * @param directory Path to a directory | ||
68 | */ | ||
69 | void | ||
70 | load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory); | ||
71 | |||
72 | /** | ||
73 | * Saves messages from a message store into a directory. | ||
74 | * | ||
75 | * @param store Message store | ||
76 | * @param directory Path to a directory | ||
77 | */ | ||
78 | void | ||
79 | save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory); | ||
80 | |||
81 | /** | ||
82 | * Checks if a message matching a given <i>hash</i> is stored in a message store. The function returns | ||
83 | * GNUNET_YES if a match is found, GNUNET_NO otherwise. | ||
84 | * | ||
85 | * The message has not to be loaded from disk into memory for this check! | ||
86 | * | ||
87 | * @param store Message store | ||
88 | * @param hash Hash of message | ||
89 | * @return GNUNET_YES on match, otherwise GNUNET_NO | ||
90 | */ | ||
91 | int | ||
92 | contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash); | ||
93 | |||
94 | /** | ||
95 | * Returns the message from a message store matching a given <i>hash</i>. If no matching message is found, | ||
96 | * NULL gets returned. | ||
97 | * | ||
98 | * This function requires the message to be loaded into memory! | ||
99 | * @see contains_store_message() | ||
100 | * | ||
101 | * @param store Message store | ||
102 | * @param hash Hash of message | ||
103 | * @return Message or NULL | ||
104 | */ | ||
105 | const struct GNUNET_MESSENGER_Message* | ||
106 | get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash); | ||
107 | |||
108 | /** | ||
109 | * Stores a message into the message store. The result indicates if the operation was successful. | ||
110 | * | ||
111 | * @param store Message store | ||
112 | * @param hash Hash of message | ||
113 | * @param message Message | ||
114 | * @return GNUNET_OK on success, otherwise GNUNET_NO | ||
115 | */ | ||
116 | int | ||
117 | put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, | ||
118 | struct GNUNET_MESSENGER_Message *message); | ||
119 | |||
120 | #endif //GNUNET_SERVICE_MESSENGER_MESSAGE_STORE_H | ||
diff --git a/src/messenger/gnunet-service-messenger_room.c b/src/messenger/gnunet-service-messenger_room.c new file mode 100644 index 000000000..7383e1d20 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_room.c | |||
@@ -0,0 +1,1051 @@ | |||
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_room.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_room.h" | ||
27 | |||
28 | #include "gnunet-service-messenger_message_kind.h" | ||
29 | |||
30 | #include "gnunet-service-messenger_service.h" | ||
31 | #include "gnunet-service-messenger_util.h" | ||
32 | |||
33 | static void | ||
34 | idle_request_room_messages (void *cls); | ||
35 | |||
36 | struct GNUNET_MESSENGER_SrvRoom* | ||
37 | create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key) | ||
38 | { | ||
39 | GNUNET_assert((handle) && (key)); | ||
40 | |||
41 | struct GNUNET_MESSENGER_SrvRoom *room = GNUNET_new(struct GNUNET_MESSENGER_SrvRoom); | ||
42 | |||
43 | room->service = handle->service; | ||
44 | room->host = handle; | ||
45 | room->port = NULL; | ||
46 | |||
47 | GNUNET_memcpy(&(room->key), key, sizeof(struct GNUNET_HashCode)); | ||
48 | |||
49 | room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO); | ||
50 | room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO); | ||
51 | room->member_infos = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO); | ||
52 | |||
53 | init_message_store (&(room->store)); | ||
54 | room->requested = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | ||
55 | |||
56 | init_list_tunnels (&(room->basement)); | ||
57 | init_list_messages (&(room->last_messages)); | ||
58 | |||
59 | room->peer_message = NULL; | ||
60 | |||
61 | init_list_messages (&(room->handling)); | ||
62 | room->idle = NULL; | ||
63 | |||
64 | room->strict_access = GNUNET_NO; | ||
65 | |||
66 | if (room->service->dir) | ||
67 | load_service_room_and_messages (room->service, room); | ||
68 | |||
69 | room->idle = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room); | ||
70 | |||
71 | return room; | ||
72 | } | ||
73 | |||
74 | static int | ||
75 | iterate_destroy_tunnels (void *cls, const struct GNUNET_PeerIdentity *key, void *value) | ||
76 | { | ||
77 | struct GNUNET_MESSENGER_SrvTunnel *tunnel = value; | ||
78 | destroy_tunnel (tunnel); | ||
79 | return GNUNET_YES; | ||
80 | } | ||
81 | |||
82 | static int | ||
83 | iterate_clear_members (void *cls, const struct GNUNET_ShortHashCode *key, void *value) | ||
84 | { | ||
85 | struct GNUNET_MESSENGER_SrvContact *contact = value; | ||
86 | |||
87 | if (GNUNET_YES == decrease_contact_rc (contact)) | ||
88 | { | ||
89 | struct GNUNET_MESSENGER_SrvRoom *room = cls; | ||
90 | |||
91 | const struct GNUNET_HashCode *id = get_contact_id_from_key (contact); | ||
92 | |||
93 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->service->contacts, id, contact)) | ||
94 | destroy_contact (contact); | ||
95 | } | ||
96 | |||
97 | return GNUNET_YES; | ||
98 | } | ||
99 | |||
100 | static int | ||
101 | iterate_destroy_member_infos (void *cls, const struct GNUNET_ShortHashCode *key, void *value) | ||
102 | { | ||
103 | struct GNUNET_MESSENGER_MemberInfo *info = value; | ||
104 | |||
105 | clear_list_messages (&(info->session_messages)); | ||
106 | |||
107 | GNUNET_free(info); | ||
108 | return GNUNET_YES; | ||
109 | } | ||
110 | |||
111 | void | ||
112 | destroy_room (struct GNUNET_MESSENGER_SrvRoom *room) | ||
113 | { | ||
114 | GNUNET_assert(room); | ||
115 | |||
116 | if (room->idle) | ||
117 | { | ||
118 | GNUNET_SCHEDULER_cancel (room->idle); | ||
119 | |||
120 | room->idle = NULL; | ||
121 | } | ||
122 | |||
123 | if (room->port) | ||
124 | GNUNET_CADET_close_port (room->port); | ||
125 | |||
126 | merge_room_last_messages (room, room->host); | ||
127 | |||
128 | GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels, | ||
129 | NULL); | ||
130 | |||
131 | handle_room_messages (room); | ||
132 | |||
133 | if (room->service->dir) | ||
134 | save_service_room_and_messages (room->service, room); | ||
135 | |||
136 | GNUNET_CONTAINER_multishortmap_iterate (room->members, iterate_clear_members, room); | ||
137 | GNUNET_CONTAINER_multishortmap_iterate (room->member_infos, iterate_destroy_member_infos, NULL); | ||
138 | |||
139 | clear_message_store (&(room->store)); | ||
140 | |||
141 | GNUNET_CONTAINER_multihashmap_destroy (room->requested); | ||
142 | |||
143 | GNUNET_CONTAINER_multipeermap_destroy (room->tunnels); | ||
144 | GNUNET_CONTAINER_multishortmap_destroy (room->members); | ||
145 | GNUNET_CONTAINER_multishortmap_destroy (room->member_infos); | ||
146 | |||
147 | clear_list_tunnels (&(room->basement)); | ||
148 | clear_list_messages (&(room->last_messages)); | ||
149 | |||
150 | if (room->peer_message) | ||
151 | GNUNET_free(room->peer_message); | ||
152 | |||
153 | GNUNET_free(room); | ||
154 | } | ||
155 | |||
156 | struct GNUNET_MESSENGER_SrvContact* | ||
157 | get_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id) | ||
158 | { | ||
159 | GNUNET_assert((room) && (room->members)); | ||
160 | |||
161 | return GNUNET_CONTAINER_multishortmap_get (room->members, id); | ||
162 | } | ||
163 | |||
164 | void | ||
165 | add_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id, | ||
166 | const struct GNUNET_IDENTITY_PublicKey *pubkey) | ||
167 | { | ||
168 | struct GNUNET_MESSENGER_SrvContact *contact = get_service_contact_by_pubkey (room->service, pubkey); | ||
169 | |||
170 | if (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put (room->members, id, contact, | ||
171 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
172 | increase_contact_rc (contact); | ||
173 | } | ||
174 | |||
175 | struct GNUNET_MESSENGER_MemberInfo* | ||
176 | get_room_member_info (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id) | ||
177 | { | ||
178 | GNUNET_assert((room) && (room->member_infos)); | ||
179 | |||
180 | return GNUNET_CONTAINER_multishortmap_get (room->member_infos, id); | ||
181 | } | ||
182 | |||
183 | struct GNUNET_ShortHashCode* | ||
184 | generate_room_member_id (const struct GNUNET_MESSENGER_SrvRoom *room) | ||
185 | { | ||
186 | struct GNUNET_ShortHashCode *unique_id = GNUNET_new(struct GNUNET_ShortHashCode); | ||
187 | |||
188 | GNUNET_assert(room); | ||
189 | |||
190 | if (GNUNET_YES == generate_free_member_id (unique_id, room->members)) | ||
191 | return unique_id; | ||
192 | else | ||
193 | { | ||
194 | GNUNET_free(unique_id); | ||
195 | return NULL; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | const struct GNUNET_ShortHashCode* | ||
200 | get_room_host_id (const struct GNUNET_MESSENGER_SrvRoom *room) | ||
201 | { | ||
202 | GNUNET_assert(room); | ||
203 | |||
204 | return get_handle_member_id (room->host, &(room->key)); | ||
205 | } | ||
206 | |||
207 | void | ||
208 | change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *unique_id) | ||
209 | { | ||
210 | GNUNET_assert(room); | ||
211 | |||
212 | change_handle_member_id (room->host, &(room->key), unique_id); | ||
213 | } | ||
214 | |||
215 | static int | ||
216 | send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
217 | struct GNUNET_MESSENGER_SrvTunnel *tunnel) | ||
218 | { | ||
219 | if (!handle) | ||
220 | return GNUNET_NO; | ||
221 | |||
222 | merge_room_last_messages (room, handle); | ||
223 | |||
224 | if (!is_tunnel_connected (tunnel)) | ||
225 | return GNUNET_NO; | ||
226 | |||
227 | struct GNUNET_MESSENGER_Message *message = create_message_info (get_handle_ego(handle), room->members); | ||
228 | |||
229 | if (!message) | ||
230 | return GNUNET_NO; | ||
231 | |||
232 | if ((tunnel->peer_message) && (tunnel->contact_id)) | ||
233 | { | ||
234 | GNUNET_memcpy(&(message->body.info.unique_id), &(tunnel->contact_id), sizeof(struct GNUNET_ShortHashCode)); | ||
235 | GNUNET_free(tunnel->contact_id); | ||
236 | |||
237 | tunnel->contact_id = NULL; | ||
238 | } | ||
239 | |||
240 | struct GNUNET_HashCode hash; | ||
241 | |||
242 | send_tunnel_message (tunnel, handle, message, &hash); | ||
243 | destroy_message (message); | ||
244 | |||
245 | if (tunnel->contact_id) | ||
246 | { | ||
247 | GNUNET_free(tunnel->contact_id); | ||
248 | |||
249 | tunnel->contact_id = NULL; | ||
250 | } | ||
251 | |||
252 | return GNUNET_YES; | ||
253 | } | ||
254 | |||
255 | static void* | ||
256 | callback_room_connect (void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *source) | ||
257 | { | ||
258 | struct GNUNET_MESSENGER_SrvRoom *room = cls; | ||
259 | |||
260 | struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, source); | ||
261 | |||
262 | if (tunnel) | ||
263 | { | ||
264 | if (GNUNET_YES == bind_tunnel (tunnel, channel)) | ||
265 | { | ||
266 | if (GNUNET_YES == send_room_info (room, room->host, tunnel)) | ||
267 | return tunnel; | ||
268 | else | ||
269 | { | ||
270 | disconnect_tunnel (tunnel); | ||
271 | return NULL; | ||
272 | } | ||
273 | } | ||
274 | else | ||
275 | { | ||
276 | delayed_disconnect_channel (channel); | ||
277 | return NULL; | ||
278 | } | ||
279 | } | ||
280 | else | ||
281 | { | ||
282 | tunnel = create_tunnel (room, source); | ||
283 | |||
284 | if ((GNUNET_YES == bind_tunnel (tunnel, channel)) && (GNUNET_OK | ||
285 | == GNUNET_CONTAINER_multipeermap_put (room->tunnels, source, tunnel, | ||
286 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) | ||
287 | { | ||
288 | if (GNUNET_YES == send_room_info (room, room->host, tunnel)) | ||
289 | return tunnel; | ||
290 | else | ||
291 | { | ||
292 | GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source, tunnel); | ||
293 | |||
294 | disconnect_tunnel (tunnel); | ||
295 | destroy_tunnel (tunnel); | ||
296 | return NULL; | ||
297 | } | ||
298 | } | ||
299 | else | ||
300 | { | ||
301 | tunnel->channel = NULL; | ||
302 | destroy_tunnel (tunnel); | ||
303 | |||
304 | delayed_disconnect_channel (channel); | ||
305 | return NULL; | ||
306 | } | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static int | ||
311 | join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
312 | const struct GNUNET_ShortHashCode *member_id) | ||
313 | { | ||
314 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s(get_room_key(room)), GNUNET_sh2s(member_id)); | ||
315 | |||
316 | struct GNUNET_MESSENGER_Message *message = create_message_join (get_handle_ego(handle)); | ||
317 | |||
318 | if (!message) | ||
319 | { | ||
320 | GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Your join message could not be created!\n"); | ||
321 | |||
322 | return GNUNET_NO; | ||
323 | } | ||
324 | |||
325 | struct GNUNET_HashCode hash; | ||
326 | |||
327 | send_room_message (room, handle, message, &hash); | ||
328 | destroy_message (message); | ||
329 | |||
330 | struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_new(struct GNUNET_MESSENGER_MemberInfo); | ||
331 | |||
332 | info->access = GNUNET_MESSENGER_MEMBER_ALLOWED; | ||
333 | init_list_messages (&(info->session_messages)); | ||
334 | |||
335 | if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_put (room->member_infos, member_id, info, | ||
336 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
337 | { | ||
338 | change_handle_member_id (handle, &(room->key), member_id); | ||
339 | |||
340 | add_to_list_messages (&(info->session_messages), &hash); | ||
341 | return GNUNET_YES; | ||
342 | } | ||
343 | else | ||
344 | { | ||
345 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Your member information could not be registered!\n"); | ||
346 | |||
347 | GNUNET_free(info); | ||
348 | return GNUNET_NO; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | static int | ||
353 | join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) | ||
354 | { | ||
355 | const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, &(room->key)); | ||
356 | |||
357 | struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, member_id); | ||
358 | |||
359 | if ((!info) && (GNUNET_NO == join_room (room, handle, member_id))) | ||
360 | return GNUNET_NO; | ||
361 | |||
362 | return GNUNET_YES; | ||
363 | } | ||
364 | |||
365 | extern int | ||
366 | check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header); | ||
367 | extern void | ||
368 | handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header); | ||
369 | |||
370 | extern void | ||
371 | callback_tunnel_disconnect (void *cls, const struct GNUNET_CADET_Channel *channel); | ||
372 | |||
373 | int | ||
374 | open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) | ||
375 | { | ||
376 | if (room->port) | ||
377 | return join_room_locally (room, handle); | ||
378 | |||
379 | struct GNUNET_CADET_Handle *cadet = get_room_cadet (room); | ||
380 | struct GNUNET_HashCode *key = get_room_key (room); | ||
381 | |||
382 | struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI, | ||
383 | struct GNUNET_MessageHeader, NULL), | ||
384 | GNUNET_MQ_handler_end() }; | ||
385 | |||
386 | room->port = GNUNET_CADET_open_port (cadet, key, callback_room_connect, room, NULL, | ||
387 | callback_tunnel_disconnect, handlers); | ||
388 | |||
389 | const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, &(room->key)); | ||
390 | |||
391 | struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, member_id); | ||
392 | |||
393 | if ((!info) && (GNUNET_NO == join_room (room, handle, member_id)) && (room->port)) | ||
394 | { | ||
395 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not join the room, therefore it keeps closed!\n"); | ||
396 | |||
397 | GNUNET_CADET_close_port (room->port); | ||
398 | room->port = NULL; | ||
399 | |||
400 | return GNUNET_NO; | ||
401 | } | ||
402 | |||
403 | struct GNUNET_MESSENGER_Message *message = create_message_peer (room->service); | ||
404 | |||
405 | if (message) | ||
406 | { | ||
407 | struct GNUNET_HashCode hash; | ||
408 | |||
409 | send_room_message (room, handle, message, &hash); | ||
410 | destroy_message (message); | ||
411 | } | ||
412 | |||
413 | return (room->port ? GNUNET_YES : GNUNET_NO); | ||
414 | } | ||
415 | |||
416 | int | ||
417 | entry_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
418 | const struct GNUNET_PeerIdentity *door) | ||
419 | { | ||
420 | if (room->peer_message) | ||
421 | { | ||
422 | const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, handle, room->peer_message, GNUNET_NO); | ||
423 | |||
424 | if (0 == GNUNET_memcmp(&(msg->body.peer.peer), door)) | ||
425 | return join_room_locally (room, handle); | ||
426 | } | ||
427 | |||
428 | struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, door); | ||
429 | |||
430 | if (tunnel) | ||
431 | { | ||
432 | switch (connect_tunnel (tunnel)) | ||
433 | { | ||
434 | case GNUNET_YES: | ||
435 | return GNUNET_YES; | ||
436 | case GNUNET_NO: | ||
437 | return join_room_locally (room, handle); | ||
438 | default: | ||
439 | return GNUNET_NO; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | tunnel = create_tunnel (room, door); | ||
444 | |||
445 | if ((GNUNET_YES == connect_tunnel (tunnel)) && | ||
446 | (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (room->tunnels, door, tunnel, | ||
447 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) | ||
448 | return GNUNET_YES; | ||
449 | else | ||
450 | { | ||
451 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not connect to that door!\n"); | ||
452 | |||
453 | destroy_tunnel (tunnel); | ||
454 | return GNUNET_NO; | ||
455 | } | ||
456 | } | ||
457 | |||
458 | struct GNUNET_MESSENGER_SrvTunnelFinder | ||
459 | { | ||
460 | const struct GNUNET_ShortHashCode *needle; | ||
461 | struct GNUNET_MESSENGER_SrvTunnel *tunnel; | ||
462 | }; | ||
463 | |||
464 | static int | ||
465 | iterate_find_tunnel (void *cls, const struct GNUNET_PeerIdentity *peer, void *value) | ||
466 | { | ||
467 | struct GNUNET_MESSENGER_SrvTunnel *tunnel = value; | ||
468 | struct GNUNET_MESSENGER_SrvTunnelFinder *finder = cls; | ||
469 | |||
470 | if ((tunnel->contact_id) && (0 == GNUNET_memcmp(tunnel->contact_id, finder->needle))) | ||
471 | { | ||
472 | finder->tunnel = tunnel; | ||
473 | return GNUNET_NO; | ||
474 | } | ||
475 | |||
476 | return GNUNET_YES; | ||
477 | } | ||
478 | |||
479 | struct GNUNET_MESSENGER_SrvTunnel* | ||
480 | find_room_tunnel_to (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *contact_id) | ||
481 | { | ||
482 | struct GNUNET_MESSENGER_SrvTunnelFinder finder; | ||
483 | |||
484 | finder.needle = contact_id; | ||
485 | finder.tunnel = NULL; | ||
486 | |||
487 | GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_find_tunnel, &finder); | ||
488 | |||
489 | return finder.tunnel; | ||
490 | } | ||
491 | |||
492 | struct GNUNET_MQ_Envelope* | ||
493 | pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
494 | struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode) | ||
495 | { | ||
496 | message->header.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); | ||
497 | |||
498 | const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, &(room->key)); | ||
499 | |||
500 | GNUNET_assert(id); | ||
501 | |||
502 | GNUNET_memcpy(&(message->header.sender_id), id, sizeof(struct GNUNET_ShortHashCode)); | ||
503 | |||
504 | if (room->last_messages.head) | ||
505 | GNUNET_memcpy(&(message->header.previous), &(room->last_messages.head->hash), sizeof(struct GNUNET_HashCode)); | ||
506 | else | ||
507 | memset (&(message->header.previous), 0, sizeof(struct GNUNET_HashCode)); | ||
508 | |||
509 | return pack_message (message, hash, get_handle_ego (handle), mode); | ||
510 | } | ||
511 | |||
512 | struct GNUNET_MESSENGER_ClosureSendRoom | ||
513 | { | ||
514 | struct GNUNET_MESSENGER_SrvRoom *room; | ||
515 | struct GNUNET_MESSENGER_SrvHandle *handle; | ||
516 | struct GNUNET_MESSENGER_SrvTunnel *exclude; | ||
517 | struct GNUNET_MESSENGER_Message *message; | ||
518 | struct GNUNET_HashCode *hash; | ||
519 | int packed; | ||
520 | }; | ||
521 | |||
522 | static int | ||
523 | iterate_send_room_message (void *cls, const struct GNUNET_PeerIdentity *key, void *value) | ||
524 | { | ||
525 | struct GNUNET_MESSENGER_SrvTunnel *tunnel = value; | ||
526 | |||
527 | if ((!is_tunnel_connected (tunnel)) || (!tunnel->contact_id)) | ||
528 | return GNUNET_YES; | ||
529 | |||
530 | struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls; | ||
531 | |||
532 | if (tunnel == closure->exclude) | ||
533 | return GNUNET_YES; | ||
534 | |||
535 | struct GNUNET_MQ_Envelope *env = NULL; | ||
536 | |||
537 | if (closure->packed == GNUNET_NO) | ||
538 | { | ||
539 | env = pack_room_message (closure->room, closure->handle, closure->message, closure->hash, | ||
540 | GNUNET_MESSENGER_PACK_MODE_ENVELOPE); | ||
541 | |||
542 | if (env) | ||
543 | { | ||
544 | closure->message = copy_message (closure->message); | ||
545 | closure->packed = GNUNET_YES; | ||
546 | } | ||
547 | } | ||
548 | else | ||
549 | { | ||
550 | env = pack_message (closure->message, NULL, NULL, | ||
551 | GNUNET_MESSENGER_PACK_MODE_ENVELOPE); | ||
552 | } | ||
553 | |||
554 | if (env) | ||
555 | send_tunnel_envelope (tunnel, closure->handle, env, closure->message, closure->hash); | ||
556 | |||
557 | return GNUNET_YES; | ||
558 | } | ||
559 | |||
560 | void | ||
561 | callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls, | ||
562 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
563 | |||
564 | void | ||
565 | send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
566 | struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash) | ||
567 | { | ||
568 | struct GNUNET_MESSENGER_ClosureSendRoom closure; | ||
569 | |||
570 | closure.room = room; | ||
571 | closure.handle = handle; | ||
572 | closure.exclude = NULL; | ||
573 | closure.message = message; | ||
574 | closure.hash = hash; | ||
575 | closure.packed = GNUNET_NO; | ||
576 | |||
577 | GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure); | ||
578 | |||
579 | if ((GNUNET_NO == closure.packed) && (closure.message == message)) | ||
580 | { | ||
581 | pack_room_message (room, handle, message, hash, | ||
582 | GNUNET_MESSENGER_PACK_MODE_UNKNOWN); | ||
583 | |||
584 | callback_room_sent (room, handle, NULL, copy_message (message), hash); | ||
585 | } | ||
586 | } | ||
587 | |||
588 | void | ||
589 | send_room_message_ext (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
590 | struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, | ||
591 | struct GNUNET_MESSENGER_SrvTunnel *tunnel) | ||
592 | { | ||
593 | struct GNUNET_MESSENGER_ClosureSendRoom closure; | ||
594 | |||
595 | closure.room = room; | ||
596 | closure.handle = handle; | ||
597 | closure.exclude = tunnel; | ||
598 | closure.message = message; | ||
599 | closure.hash = hash; | ||
600 | closure.packed = GNUNET_NO; | ||
601 | |||
602 | GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure); | ||
603 | |||
604 | if ((GNUNET_NO == closure.packed) && (closure.message == message)) | ||
605 | { | ||
606 | pack_room_message (room, handle, message, hash, | ||
607 | GNUNET_MESSENGER_PACK_MODE_UNKNOWN); | ||
608 | |||
609 | callback_room_sent (room, handle, NULL, copy_message (message), hash); | ||
610 | } | ||
611 | } | ||
612 | |||
613 | void | ||
614 | forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
615 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
616 | { | ||
617 | struct GNUNET_MESSENGER_ClosureSendRoom closure; | ||
618 | struct GNUNET_HashCode message_hash; | ||
619 | |||
620 | GNUNET_memcpy(&message_hash, hash, sizeof(struct GNUNET_HashCode)); | ||
621 | |||
622 | closure.room = room; | ||
623 | closure.handle = NULL; | ||
624 | closure.exclude = tunnel; | ||
625 | closure.message = copy_message (message); | ||
626 | closure.hash = &message_hash; | ||
627 | closure.packed = GNUNET_YES; | ||
628 | |||
629 | GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure); | ||
630 | } | ||
631 | |||
632 | void | ||
633 | merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) | ||
634 | { | ||
635 | if (!handle) | ||
636 | return; | ||
637 | |||
638 | if (!room->last_messages.head) | ||
639 | return; | ||
640 | |||
641 | while (room->last_messages.head != room->last_messages.tail) | ||
642 | { | ||
643 | struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.tail; | ||
644 | |||
645 | struct GNUNET_MESSENGER_Message *message = create_message_merge (&(element->hash)); | ||
646 | |||
647 | if (message) | ||
648 | { | ||
649 | struct GNUNET_HashCode hash; | ||
650 | |||
651 | send_room_message (room, handle, message, &hash); | ||
652 | destroy_message (message); | ||
653 | } | ||
654 | |||
655 | if (element->prev) | ||
656 | GNUNET_CONTAINER_DLL_remove(room->last_messages.head, room->last_messages.tail, element); | ||
657 | } | ||
658 | } | ||
659 | |||
660 | struct GNUNET_CADET_Handle* | ||
661 | get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room) | ||
662 | { | ||
663 | return room->service->cadet; | ||
664 | } | ||
665 | |||
666 | struct GNUNET_HashCode* | ||
667 | get_room_key (struct GNUNET_MESSENGER_SrvRoom *room) | ||
668 | { | ||
669 | return &(room->key); | ||
670 | } | ||
671 | |||
672 | const struct GNUNET_MESSENGER_SrvTunnel* | ||
673 | get_room_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer) | ||
674 | { | ||
675 | return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer); | ||
676 | } | ||
677 | |||
678 | const struct GNUNET_MESSENGER_Message* | ||
679 | get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
680 | const struct GNUNET_HashCode *hash, int request) | ||
681 | { | ||
682 | const struct GNUNET_MESSENGER_Message *message = get_store_message (&(room->store), hash); | ||
683 | |||
684 | if ((message) || (!handle) || (GNUNET_YES != request) | ||
685 | || (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->requested, hash))) | ||
686 | return message; | ||
687 | |||
688 | struct GNUNET_MESSENGER_Message *request_msg = create_message_request (hash); | ||
689 | |||
690 | if (request_msg) | ||
691 | { | ||
692 | if (GNUNET_CONTAINER_multihashmap_put (room->requested, hash, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST) == GNUNET_OK) | ||
693 | { | ||
694 | struct GNUNET_HashCode request_hash; | ||
695 | |||
696 | send_room_message (room, handle, request_msg, &request_hash); | ||
697 | } | ||
698 | |||
699 | destroy_message (request_msg); | ||
700 | } | ||
701 | |||
702 | return message; | ||
703 | } | ||
704 | |||
705 | void | ||
706 | callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls) | ||
707 | { | ||
708 | struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; | ||
709 | |||
710 | if (!room->host) | ||
711 | return; | ||
712 | |||
713 | struct GNUNET_PeerIdentity identity; | ||
714 | |||
715 | GNUNET_PEER_resolve (tunnel->peer, &identity); | ||
716 | |||
717 | if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity)) | ||
718 | { | ||
719 | struct GNUNET_MESSENGER_Message *message = create_message_miss (&identity); | ||
720 | |||
721 | if (message) | ||
722 | { | ||
723 | struct GNUNET_HashCode hash; | ||
724 | |||
725 | send_room_message (room, room->host, message, &hash); | ||
726 | destroy_message (message); | ||
727 | } | ||
728 | } | ||
729 | } | ||
730 | |||
731 | int | ||
732 | callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, | ||
733 | struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash) | ||
734 | { | ||
735 | if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind) | ||
736 | return GNUNET_SYSERR; | ||
737 | |||
738 | struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, | ||
739 | &(message->header.sender_id)); | ||
740 | |||
741 | if (!contact) | ||
742 | { | ||
743 | if (GNUNET_MESSENGER_KIND_INFO == message->header.kind) | ||
744 | contact = get_service_contact_by_pubkey (room->service, &(message->body.info.host_key)); | ||
745 | else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind) | ||
746 | contact = get_service_contact_by_pubkey (room->service, &(message->body.join.key)); | ||
747 | } | ||
748 | |||
749 | if ((!contact) || (GNUNET_SYSERR == verify_message (message, hash, get_contact_key (contact)))) | ||
750 | return GNUNET_SYSERR; | ||
751 | |||
752 | if (GNUNET_YES == room->strict_access) | ||
753 | { | ||
754 | struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, | ||
755 | &(message->header.sender_id)); | ||
756 | |||
757 | if ((info) && (GNUNET_MESSENGER_MEMBER_BLOCKED == info->access)) | ||
758 | return GNUNET_SYSERR; | ||
759 | } | ||
760 | |||
761 | if (GNUNET_YES == contains_store_message (&(room->store), hash)) | ||
762 | return GNUNET_NO; | ||
763 | |||
764 | return GNUNET_YES; | ||
765 | } | ||
766 | |||
767 | static void | ||
768 | search_room_for_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash) | ||
769 | { | ||
770 | const struct GNUNET_MESSENGER_Message *message = get_room_message (room, room->host, hash, GNUNET_YES); | ||
771 | |||
772 | if (!message) | ||
773 | return; | ||
774 | |||
775 | if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind) | ||
776 | search_room_for_message (room, &(message->body.merge.previous)); | ||
777 | |||
778 | search_room_for_message (room, &(message->header.previous)); | ||
779 | } | ||
780 | |||
781 | static void | ||
782 | idle_request_room_messages (void *cls) | ||
783 | { | ||
784 | struct GNUNET_MESSENGER_SrvRoom *room = cls; | ||
785 | |||
786 | room->idle = NULL; | ||
787 | |||
788 | struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.head; | ||
789 | |||
790 | while (element) | ||
791 | { | ||
792 | search_room_for_message (room, &(element->hash)); | ||
793 | |||
794 | element = element->next; | ||
795 | } | ||
796 | |||
797 | merge_room_last_messages (room, room->host); | ||
798 | |||
799 | room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_second_ (), | ||
800 | GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, | ||
801 | cls); | ||
802 | } | ||
803 | |||
804 | void | ||
805 | update_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_Message *message, | ||
806 | const struct GNUNET_HashCode *hash) | ||
807 | { | ||
808 | struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.head; | ||
809 | struct GNUNET_MESSENGER_ListMessage *merging = NULL; | ||
810 | |||
811 | if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind) | ||
812 | { | ||
813 | merging = room->last_messages.head; | ||
814 | |||
815 | while (merging) | ||
816 | { | ||
817 | if (0 == GNUNET_CRYPTO_hash_cmp (&(merging->hash), &(message->body.merge.previous))) | ||
818 | break; | ||
819 | |||
820 | merging = merging->next; | ||
821 | } | ||
822 | |||
823 | if (merging) | ||
824 | element = merging->next; | ||
825 | } | ||
826 | |||
827 | while (element) | ||
828 | { | ||
829 | if (0 == GNUNET_CRYPTO_hash_cmp (&(element->hash), &(message->header.previous))) | ||
830 | break; | ||
831 | |||
832 | element = element->next; | ||
833 | } | ||
834 | |||
835 | if ((merging) && (!element)) | ||
836 | { | ||
837 | element = merging; | ||
838 | merging = NULL; | ||
839 | } | ||
840 | |||
841 | if (element) | ||
842 | { | ||
843 | GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode)); | ||
844 | |||
845 | if (merging) | ||
846 | GNUNET_CONTAINER_DLL_remove(room->last_messages.head, room->last_messages.tail, merging); | ||
847 | } | ||
848 | else | ||
849 | add_to_list_messages (&(room->last_messages), hash); | ||
850 | |||
851 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (room->requested, hash)) | ||
852 | GNUNET_CONTAINER_multihashmap_remove_all (room->requested, hash); | ||
853 | } | ||
854 | |||
855 | void | ||
856 | switch_room_member_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *old_id, | ||
857 | const struct GNUNET_ShortHashCode *new_id, const struct GNUNET_HashCode *hash) | ||
858 | { | ||
859 | struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, old_id); | ||
860 | |||
861 | if ((contact) && (GNUNET_YES == GNUNET_CONTAINER_multishortmap_remove (room->members, old_id, contact))) | ||
862 | GNUNET_CONTAINER_multishortmap_put (room->members, new_id, contact, | ||
863 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
864 | |||
865 | struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, old_id); | ||
866 | |||
867 | if ((!info) || (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove (room->member_infos, old_id, contact)) | ||
868 | || (GNUNET_YES != GNUNET_CONTAINER_multishortmap_put (room->member_infos, new_id, contact, | ||
869 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) | ||
870 | return; | ||
871 | |||
872 | if (hash) | ||
873 | add_to_list_messages (&(info->session_messages), hash); | ||
874 | } | ||
875 | |||
876 | void | ||
877 | rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room) | ||
878 | { | ||
879 | struct GNUNET_PeerIdentity peer; | ||
880 | size_t src; | ||
881 | |||
882 | if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) || (!find_list_tunnels (&(room->basement), &peer, | ||
883 | &src))) | ||
884 | return; | ||
885 | |||
886 | size_t count = count_of_tunnels (&(room->basement)); | ||
887 | |||
888 | struct GNUNET_MESSENGER_ListTunnel *element = room->basement.head; | ||
889 | struct GNUNET_MESSENGER_SrvTunnel *tunnel; | ||
890 | |||
891 | size_t dst = 0; | ||
892 | |||
893 | while (element) | ||
894 | { | ||
895 | GNUNET_PEER_resolve (element->peer, &peer); | ||
896 | |||
897 | tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, &peer); | ||
898 | |||
899 | if (!tunnel) | ||
900 | { | ||
901 | element = remove_from_list_tunnels (&(room->basement), element); | ||
902 | continue; | ||
903 | } | ||
904 | |||
905 | if (GNUNET_YES == required_connection_between (count, src, dst)) | ||
906 | { | ||
907 | if (GNUNET_SYSERR == connect_tunnel (tunnel)) | ||
908 | { | ||
909 | element = remove_from_list_tunnels (&(room->basement), element); | ||
910 | continue; | ||
911 | } | ||
912 | } | ||
913 | else | ||
914 | disconnect_tunnel (tunnel); | ||
915 | |||
916 | element = element->next; | ||
917 | dst++; | ||
918 | } | ||
919 | } | ||
920 | |||
921 | void | ||
922 | handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room) | ||
923 | { | ||
924 | while (room->handling.head) | ||
925 | { | ||
926 | struct GNUNET_MESSENGER_ListMessage *element = room->handling.head; | ||
927 | |||
928 | const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, room->host, &(element->hash), GNUNET_NO); | ||
929 | |||
930 | if (msg) | ||
931 | handle_service_message (room->service, room, msg, &(element->hash)); | ||
932 | |||
933 | GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element); | ||
934 | GNUNET_free(element); | ||
935 | } | ||
936 | } | ||
937 | |||
938 | #include "gnunet-service-messenger_message_recv.h" | ||
939 | |||
940 | void | ||
941 | callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message, | ||
942 | const struct GNUNET_HashCode *hash) | ||
943 | { | ||
944 | struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; | ||
945 | |||
946 | if (GNUNET_OK != put_store_message (&(room->store), hash, message)) | ||
947 | return; | ||
948 | |||
949 | update_room_last_messages (room, message, hash); | ||
950 | |||
951 | if (GNUNET_MESSENGER_KIND_INFO != message->header.kind) | ||
952 | forward_room_message (room, tunnel, message, hash); | ||
953 | |||
954 | const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES; | ||
955 | |||
956 | add_to_list_messages (&(room->handling), hash); | ||
957 | |||
958 | switch (message->header.kind) | ||
959 | { | ||
960 | case GNUNET_MESSENGER_KIND_INFO: | ||
961 | recv_message_info (room, tunnel, message, hash); | ||
962 | break; | ||
963 | case GNUNET_MESSENGER_KIND_JOIN: | ||
964 | recv_message_join (room, tunnel, message, hash); | ||
965 | break; | ||
966 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
967 | recv_message_leave (room, tunnel, message, hash); | ||
968 | break; | ||
969 | case GNUNET_MESSENGER_KIND_NAME: | ||
970 | recv_message_name (room, tunnel, message, hash); | ||
971 | break; | ||
972 | case GNUNET_MESSENGER_KIND_KEY: | ||
973 | recv_message_key (room, tunnel, message, hash); | ||
974 | break; | ||
975 | case GNUNET_MESSENGER_KIND_PEER: | ||
976 | recv_message_peer (room, tunnel, message, hash); | ||
977 | break; | ||
978 | case GNUNET_MESSENGER_KIND_ID: | ||
979 | recv_message_id (room, tunnel, message, hash); | ||
980 | break; | ||
981 | case GNUNET_MESSENGER_KIND_MISS: | ||
982 | recv_message_miss (room, tunnel, message, hash); | ||
983 | break; | ||
984 | case GNUNET_MESSENGER_KIND_REQUEST: | ||
985 | recv_message_request (room, tunnel, message, hash); | ||
986 | break; | ||
987 | default: | ||
988 | break; | ||
989 | } | ||
990 | |||
991 | if (GNUNET_YES == start_handle) | ||
992 | handle_room_messages (room); | ||
993 | } | ||
994 | |||
995 | #include "gnunet-service-messenger_message_send.h" | ||
996 | |||
997 | void | ||
998 | callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls, | ||
999 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
1000 | { | ||
1001 | const struct GNUNET_MESSENGER_Message *old_message = get_room_message (room, handle, hash, GNUNET_NO); | ||
1002 | |||
1003 | if ((old_message) || (GNUNET_OK != put_store_message (&(room->store), hash, message))) | ||
1004 | { | ||
1005 | if (old_message != message) | ||
1006 | GNUNET_free(message); | ||
1007 | } | ||
1008 | else | ||
1009 | { | ||
1010 | struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; // may be NULL | ||
1011 | |||
1012 | update_room_last_messages (room, message, hash); | ||
1013 | |||
1014 | const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES; | ||
1015 | |||
1016 | add_to_list_messages (&(room->handling), hash); | ||
1017 | |||
1018 | switch (message->header.kind) | ||
1019 | { | ||
1020 | case GNUNET_MESSENGER_KIND_INFO: | ||
1021 | send_message_info (room, handle, tunnel, message, hash); | ||
1022 | break; | ||
1023 | case GNUNET_MESSENGER_KIND_JOIN: | ||
1024 | send_message_join (room, handle, tunnel, message, hash); | ||
1025 | break; | ||
1026 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
1027 | send_message_leave (room, handle, tunnel, message, hash); | ||
1028 | break; | ||
1029 | case GNUNET_MESSENGER_KIND_NAME: | ||
1030 | send_message_name (room, handle, tunnel, message, hash); | ||
1031 | break; | ||
1032 | case GNUNET_MESSENGER_KIND_KEY: | ||
1033 | send_message_key (room, handle, tunnel, message, hash); | ||
1034 | break; | ||
1035 | case GNUNET_MESSENGER_KIND_PEER: | ||
1036 | send_message_peer (room, handle, tunnel, message, hash); | ||
1037 | break; | ||
1038 | case GNUNET_MESSENGER_KIND_ID: | ||
1039 | send_message_id (room, handle, tunnel, message, hash); | ||
1040 | break; | ||
1041 | case GNUNET_MESSENGER_KIND_MISS: | ||
1042 | send_message_miss (room, handle, tunnel, message, hash); | ||
1043 | break; | ||
1044 | default: | ||
1045 | break; | ||
1046 | } | ||
1047 | |||
1048 | if (GNUNET_YES == start_handle) | ||
1049 | handle_room_messages (room); | ||
1050 | } | ||
1051 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_room.h b/src/messenger/gnunet-service-messenger_room.h new file mode 100644 index 000000000..36c9e8cf5 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_room.h | |||
@@ -0,0 +1,378 @@ | |||
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_room.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_ROOM_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_ROOM_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_cadet_service.h" | ||
31 | #include "gnunet_container_lib.h" | ||
32 | #include "gnunet_crypto_lib.h" | ||
33 | #include "gnunet_identity_service.h" | ||
34 | #include "gnunet_mq_lib.h" | ||
35 | |||
36 | #include "gnunet-service-messenger_contact.h" | ||
37 | |||
38 | #include "gnunet_messenger_service.h" | ||
39 | #include "gnunet-service-messenger_basement.h" | ||
40 | #include "gnunet-service-messenger_handle.h" | ||
41 | #include "gnunet-service-messenger_tunnel.h" | ||
42 | |||
43 | #include "gnunet-service-messenger_list_messages.h" | ||
44 | #include "messenger_api_list_tunnels.h" | ||
45 | |||
46 | #include "gnunet-service-messenger_message_store.h" | ||
47 | #include "messenger_api_ego.h" | ||
48 | |||
49 | enum GNUNET_MESSENGER_MemberAccess | ||
50 | { | ||
51 | GNUNET_MESSENGER_MEMBER_ALLOWED = 1, | ||
52 | GNUNET_MESSENGER_MEMBER_BLOCKED = 1, | ||
53 | |||
54 | GNUNET_MESSENGER_MEMBER_UNKNOWN = 0 | ||
55 | }; | ||
56 | |||
57 | struct GNUNET_MESSENGER_MemberInfo | ||
58 | { | ||
59 | enum GNUNET_MESSENGER_MemberAccess access; | ||
60 | |||
61 | struct GNUNET_MESSENGER_ListMessages session_messages; | ||
62 | }; | ||
63 | |||
64 | struct GNUNET_MESSENGER_SrvRoom | ||
65 | { | ||
66 | struct GNUNET_MESSENGER_Service *service; | ||
67 | struct GNUNET_MESSENGER_SrvHandle *host; | ||
68 | struct GNUNET_CADET_Port *port; | ||
69 | |||
70 | struct GNUNET_HashCode key; | ||
71 | |||
72 | struct GNUNET_CONTAINER_MultiPeerMap *tunnels; | ||
73 | struct GNUNET_CONTAINER_MultiShortmap *members; | ||
74 | struct GNUNET_CONTAINER_MultiShortmap *member_infos; | ||
75 | |||
76 | struct GNUNET_MESSENGER_MessageStore store; | ||
77 | struct GNUNET_CONTAINER_MultiHashMap *requested; | ||
78 | |||
79 | struct GNUNET_MESSENGER_ListTunnels basement; | ||
80 | struct GNUNET_MESSENGER_ListMessages last_messages; | ||
81 | |||
82 | struct GNUNET_HashCode *peer_message; | ||
83 | |||
84 | struct GNUNET_MESSENGER_ListMessages handling; | ||
85 | struct GNUNET_SCHEDULER_Task *idle; | ||
86 | |||
87 | int strict_access; | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i>. | ||
92 | * | ||
93 | * @param handle Handle | ||
94 | * @param key Key of room | ||
95 | * @return New room | ||
96 | */ | ||
97 | struct GNUNET_MESSENGER_SrvRoom* | ||
98 | create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key); | ||
99 | |||
100 | /** | ||
101 | * Destroys a room and frees its memory fully. | ||
102 | * | ||
103 | * @param room Room | ||
104 | */ | ||
105 | void | ||
106 | destroy_room (struct GNUNET_MESSENGER_SrvRoom *room); | ||
107 | |||
108 | /** | ||
109 | * Returns the contact of a member in a <i>room</i> identified by a given <i>id</i>. If the <i>room</i> | ||
110 | * does not contain a member with the given <i>id</i>, NULL gets returned. | ||
111 | * | ||
112 | * @param room Room | ||
113 | * @param id Member id | ||
114 | * @return Contact or NULL | ||
115 | */ | ||
116 | struct GNUNET_MESSENGER_SrvContact* | ||
117 | get_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id); | ||
118 | |||
119 | /** | ||
120 | * Adds a contact from the service to a <i>room</i> under a specific <i>id</i> with a given public key. | ||
121 | * | ||
122 | * @param room Room | ||
123 | * @param id Member id | ||
124 | * @param pubkey Public key of EGO | ||
125 | */ | ||
126 | void | ||
127 | add_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id, | ||
128 | const struct GNUNET_IDENTITY_PublicKey *pubkey); | ||
129 | |||
130 | /** | ||
131 | * Returns the member information of a member in a <i>room</i> identified by a given <i>id</i>. If the <i>room</i> | ||
132 | * does not contain a member with the given <i>id</i>, NULL gets returned. | ||
133 | * | ||
134 | * @param room Room | ||
135 | * @param id Member id | ||
136 | * @return Member information or NULL | ||
137 | */ | ||
138 | struct GNUNET_MESSENGER_MemberInfo* | ||
139 | get_room_member_info (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id); | ||
140 | |||
141 | /** | ||
142 | * Tries to generate and allocate a new unique member id checking all current members for possible | ||
143 | * duplicates. If the function fails, NULL gets returned. | ||
144 | * | ||
145 | * @param room Room | ||
146 | * @return New member id or NULL | ||
147 | */ | ||
148 | struct GNUNET_ShortHashCode* | ||
149 | generate_room_member_id (const struct GNUNET_MESSENGER_SrvRoom *room); | ||
150 | |||
151 | /** | ||
152 | * Returns the member id of the member representing the handle currently hosting this <i>room</i>. | ||
153 | * | ||
154 | * @param room Room | ||
155 | * @return Host member id or NULL | ||
156 | */ | ||
157 | const struct GNUNET_ShortHashCode* | ||
158 | get_room_host_id (const struct GNUNET_MESSENGER_SrvRoom *room); | ||
159 | |||
160 | /** | ||
161 | * Changes the member id of the member representing the handle currently hosting this <i>room</i>. | ||
162 | * | ||
163 | * @param room Room | ||
164 | * @param unique_id Unique member id | ||
165 | */ | ||
166 | void | ||
167 | change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *unique_id); | ||
168 | |||
169 | /** | ||
170 | * Tries to open a <i>room</i> for a given <i>handle</i>. If the room has already been opened, the handle | ||
171 | * will locally join the room. | ||
172 | * | ||
173 | * Calling this method should result in joining a room and sending a peer message as well for this peer. | ||
174 | * | ||
175 | * If the function returns GNUNET_YES the port for this room is guranteed to be open for incoming connections. | ||
176 | * | ||
177 | * @param room Room | ||
178 | * @param handle Handle | ||
179 | * @return GNUNET_YES on success, GNUNET_NO on failure. | ||
180 | */ | ||
181 | int | ||
182 | open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle); | ||
183 | |||
184 | /** | ||
185 | * Connects a tunnel to a hosting peer of a <i>room</i> through a so called <i>door</i> which is represented by | ||
186 | * a peer identity of a hosting peer. During the connection the handle will join the room as a member, waiting for | ||
187 | * an info message from the selected host. | ||
188 | * | ||
189 | * @param room Room | ||
190 | * @param handle Handle | ||
191 | * @param door Peer identity | ||
192 | * @return GNUNET_YES on success, GNUNET_NO on failure. | ||
193 | */ | ||
194 | int | ||
195 | entry_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
196 | const struct GNUNET_PeerIdentity *door); | ||
197 | |||
198 | /** | ||
199 | * Returns a tunnel granting a direct connection to a specific member in a <i>room</i>. The member gets identified | ||
200 | * by an <i>id</i>. If no tunnel has been linked to the selected id, NULL gets returned. | ||
201 | * | ||
202 | * @param room Room | ||
203 | * @param contact_id Member id | ||
204 | * @return Tunnel to the member or NULL | ||
205 | */ | ||
206 | struct GNUNET_MESSENGER_SrvTunnel* | ||
207 | find_room_tunnel_to (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *contact_id); | ||
208 | |||
209 | /** | ||
210 | * Packs a <i>message</i> depending on the selected <i>mode</i> into a newly allocated envelope. It will set the | ||
211 | * timestamp of the message, the sender id and the previous messages hash automatically before packing. The message | ||
212 | * will be signed by the handles EGO. | ||
213 | * | ||
214 | * If the optional <i>hash</i> parameter is a valid pointer, its value will be overriden by the signed messages hash. | ||
215 | * | ||
216 | * If <i>mode</i> is set to GNUNET_MESSENGER_PACK_MODE_ENVELOPE, the function returns a valid envelope to send | ||
217 | * through a message queue, otherwise NULL. | ||
218 | * | ||
219 | * @param room Room | ||
220 | * @param handle Handle | ||
221 | * @param message Message | ||
222 | * @param[out] hash Hash of message | ||
223 | * @param mode Packing mode | ||
224 | * @return New envelope or NULL | ||
225 | */ | ||
226 | struct GNUNET_MQ_Envelope* | ||
227 | pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
228 | struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode); | ||
229 | |||
230 | /** | ||
231 | * Sends a <i>message</i> from a given <i>handle</i> into a <i>room</i>. The <i>hash</i> parameter will be | ||
232 | * updated with the hash-value resulting from the sent message. | ||
233 | * | ||
234 | * The function handles packing the message automatically and will call linked message-events locally even if | ||
235 | * the message won't be sent to another peer. | ||
236 | * | ||
237 | * @param room Room | ||
238 | * @param handle Handle | ||
239 | * @param message Message | ||
240 | * @param[out] hash Hash of message | ||
241 | */ | ||
242 | void | ||
243 | send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
244 | struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash); | ||
245 | |||
246 | /** | ||
247 | * Sends a <i>message</i> from a given <i>handle</i> into a <i>room</i> excluding one specific <i>tunnel</i>. | ||
248 | * The <i>hash</i> parameter will be updated with the hash-value resulting from the sent message. | ||
249 | * | ||
250 | * The function handles packing the message automatically and will call linked message-events locally even if | ||
251 | * the message won't be sent to another peer. | ||
252 | * | ||
253 | * @param room Room | ||
254 | * @param handle Handle | ||
255 | * @param message Message | ||
256 | * @param[out] hash Hash of message | ||
257 | * @param tunnel Tunnel | ||
258 | */ | ||
259 | void | ||
260 | send_room_message_ext (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
261 | struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, | ||
262 | struct GNUNET_MESSENGER_SrvTunnel *tunnel); | ||
263 | |||
264 | /** | ||
265 | * Forwards a <i>message</i> with a given <i>hash</i> to a specific <i>tunnel</i> inside of a <i>room</i>. | ||
266 | * | ||
267 | * @param room Room | ||
268 | * @param tunnel Tunnel | ||
269 | * @param message Message | ||
270 | * @param hash Hash of message | ||
271 | */ | ||
272 | void | ||
273 | forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | ||
274 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
275 | |||
276 | /** | ||
277 | * Reduces all current forks inside of the message history of a <i>room</i> to one remaining last message | ||
278 | * by merging them down. All merge messages will be sent from a given <i>handle</i>. | ||
279 | * | ||
280 | * @param room Room | ||
281 | * @param handle Handle | ||
282 | */ | ||
283 | void | ||
284 | merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle); | ||
285 | |||
286 | /** | ||
287 | * Returns the CADET handle from a rooms service. | ||
288 | * | ||
289 | * @param room Room | ||
290 | * @return CADET handle | ||
291 | */ | ||
292 | struct GNUNET_CADET_Handle* | ||
293 | get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room); | ||
294 | |||
295 | /** | ||
296 | * Returns the shared secret you need to access a <i>room</i>. | ||
297 | * | ||
298 | * @param room Room | ||
299 | * @return Shared secret | ||
300 | */ | ||
301 | struct GNUNET_HashCode* | ||
302 | get_room_key (struct GNUNET_MESSENGER_SrvRoom *room); | ||
303 | |||
304 | /** | ||
305 | * Returns a tunnel inside of a <i>room</i> leading towards a given <i>peer</i> if such a tunnel exists, | ||
306 | * otherwise NULL. | ||
307 | * | ||
308 | * @param room Room | ||
309 | * @param peer Peer identity | ||
310 | * @return Tunnel or NULL | ||
311 | */ | ||
312 | const struct GNUNET_MESSENGER_SrvTunnel* | ||
313 | get_room_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer); | ||
314 | |||
315 | /** | ||
316 | * Returns a message from a <i>room</i> identified by a given <i>hash</i>. If no matching message is | ||
317 | * found and <i>request</i> is set to GNUNET_YES, the <i>handle</i> will request the missing message | ||
318 | * automatically. | ||
319 | * | ||
320 | * The function uses the optimized check for a message via its hash from the message store. | ||
321 | * @see contains_store_message() | ||
322 | * | ||
323 | * If a message is missing independent of the following request, NULL gets returned instead of the | ||
324 | * matching message. | ||
325 | * | ||
326 | * @param room Room | ||
327 | * @param handle Handle | ||
328 | * @param hash Hash of message | ||
329 | * @param request Flag to request a message | ||
330 | * @return Message or NULL | ||
331 | */ | ||
332 | const struct GNUNET_MESSENGER_Message* | ||
333 | get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
334 | const struct GNUNET_HashCode *hash, int request); | ||
335 | |||
336 | /** | ||
337 | * Updates the last messages of a <i>room</i> by replacing them if the previous hash of a given <i>message</i> | ||
338 | * matches with one of the latest messages. | ||
339 | * | ||
340 | * @param room Room | ||
341 | * @param message Message | ||
342 | * @param hash Hash of message | ||
343 | */ | ||
344 | void | ||
345 | update_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_Message *message, | ||
346 | const struct GNUNET_HashCode *hash); | ||
347 | |||
348 | /** | ||
349 | * Changes an id of a current member from an old id to a new one and adds optionally the <i>hash</i> of an | ||
350 | * id message to the members information. | ||
351 | * | ||
352 | * @param room Room | ||
353 | * @param old_id Old member id | ||
354 | * @param new_id New member id | ||
355 | * @param hash Hash of id message | ||
356 | */ | ||
357 | void | ||
358 | switch_room_member_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *old_id, | ||
359 | const struct GNUNET_ShortHashCode *new_id, const struct GNUNET_HashCode *hash); | ||
360 | |||
361 | /** | ||
362 | * Rebuilds the decentralized structure for a <i>room</i> by ensuring all required connections are made | ||
363 | * depending on the amount of peers and this peers index in the list of them. | ||
364 | * | ||
365 | * @param room Room | ||
366 | */ | ||
367 | void | ||
368 | rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room); | ||
369 | |||
370 | /** | ||
371 | * Handles all queued up messages of a room to handle in correct order. | ||
372 | * | ||
373 | * @param room Room | ||
374 | */ | ||
375 | void | ||
376 | handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room); | ||
377 | |||
378 | #endif //GNUNET_SERVICE_MESSENGER_ROOM_H | ||
diff --git a/src/messenger/gnunet-service-messenger_service.c b/src/messenger/gnunet-service-messenger_service.c new file mode 100644 index 000000000..963314fd8 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_service.c | |||
@@ -0,0 +1,516 @@ | |||
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_service.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_service.h" | ||
27 | |||
28 | #include "gnunet-service-messenger_message_kind.h" | ||
29 | |||
30 | #include "gnunet-service-messenger.h" | ||
31 | #include "gnunet-service-messenger_util.h" | ||
32 | |||
33 | static void | ||
34 | callback_shutdown_service (void *cls) | ||
35 | { | ||
36 | struct GNUNET_MESSENGER_Service *service = cls; | ||
37 | |||
38 | if (service) | ||
39 | { | ||
40 | service->shutdown = NULL; | ||
41 | |||
42 | destroy_service (service); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | static void | ||
47 | callback_update_ego (void *cls, | ||
48 | struct GNUNET_IDENTITY_Ego *ego, | ||
49 | void **ctx, | ||
50 | const char *identifier) | ||
51 | { | ||
52 | if ((!ego) || (!identifier)) | ||
53 | return; | ||
54 | |||
55 | struct GNUNET_MESSENGER_Service *service = cls; | ||
56 | |||
57 | update_service_ego(service, identifier, GNUNET_IDENTITY_ego_get_private_key(ego)); | ||
58 | } | ||
59 | |||
60 | struct GNUNET_MESSENGER_Service* | ||
61 | create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service_handle) | ||
62 | { | ||
63 | struct GNUNET_MESSENGER_Service *service = GNUNET_new(struct GNUNET_MESSENGER_Service); | ||
64 | |||
65 | service->config = config; | ||
66 | service->service = service_handle; | ||
67 | |||
68 | service->shutdown = GNUNET_SCHEDULER_add_shutdown (&callback_shutdown_service, service); | ||
69 | |||
70 | service->dir = NULL; | ||
71 | |||
72 | if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (service->config, | ||
73 | GNUNET_MESSENGER_SERVICE_NAME, | ||
74 | "MESSENGER_DIR", &(service->dir))) | ||
75 | { | ||
76 | if (service->dir) | ||
77 | GNUNET_free(service->dir); | ||
78 | |||
79 | service->dir = NULL; | ||
80 | } | ||
81 | else | ||
82 | { | ||
83 | if ((GNUNET_YES != GNUNET_DISK_directory_test (service->dir, GNUNET_YES)) && (GNUNET_OK | ||
84 | != GNUNET_DISK_directory_create (service->dir))) | ||
85 | { | ||
86 | GNUNET_free(service->dir); | ||
87 | |||
88 | service->dir = NULL; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | service->cadet = GNUNET_CADET_connect (service->config); | ||
93 | service->identity = GNUNET_IDENTITY_connect (service->config, &callback_update_ego, service); | ||
94 | |||
95 | service->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | ||
96 | |||
97 | init_list_handles (&(service->handles)); | ||
98 | |||
99 | service->contacts = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | ||
100 | service->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | ||
101 | |||
102 | return service; | ||
103 | } | ||
104 | |||
105 | static int | ||
106 | iterate_destroy_egos (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
107 | { | ||
108 | struct GNUNET_MESSENGER_Ego *ego = value; | ||
109 | GNUNET_free(ego); | ||
110 | return GNUNET_YES; | ||
111 | } | ||
112 | |||
113 | static int | ||
114 | iterate_destroy_rooms (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
115 | { | ||
116 | struct GNUNET_MESSENGER_SrvRoom *room = value; | ||
117 | destroy_room (room); | ||
118 | return GNUNET_YES; | ||
119 | } | ||
120 | |||
121 | static int | ||
122 | iterate_destroy_contacts (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
123 | { | ||
124 | struct GNUNET_MESSENGER_SrvContact *contact = value; | ||
125 | destroy_contact (contact); | ||
126 | return GNUNET_YES; | ||
127 | } | ||
128 | |||
129 | void | ||
130 | destroy_service (struct GNUNET_MESSENGER_Service *service) | ||
131 | { | ||
132 | if (service->shutdown) | ||
133 | { | ||
134 | GNUNET_SCHEDULER_cancel (service->shutdown); | ||
135 | |||
136 | service->shutdown = NULL; | ||
137 | } | ||
138 | |||
139 | GNUNET_CONTAINER_multihashmap_iterate (service->egos, iterate_destroy_egos, NULL); | ||
140 | |||
141 | clear_list_handles (&(service->handles)); | ||
142 | |||
143 | GNUNET_CONTAINER_multihashmap_iterate (service->rooms, iterate_destroy_rooms, NULL); | ||
144 | GNUNET_CONTAINER_multihashmap_iterate (service->contacts, iterate_destroy_contacts, NULL); | ||
145 | |||
146 | GNUNET_CONTAINER_multihashmap_destroy (service->egos); | ||
147 | GNUNET_CONTAINER_multihashmap_destroy (service->rooms); | ||
148 | GNUNET_CONTAINER_multihashmap_destroy (service->contacts); | ||
149 | |||
150 | if (service->cadet) | ||
151 | { | ||
152 | GNUNET_CADET_disconnect (service->cadet); | ||
153 | |||
154 | service->cadet = NULL; | ||
155 | } | ||
156 | |||
157 | if (service->identity) | ||
158 | { | ||
159 | GNUNET_IDENTITY_disconnect (service->identity); | ||
160 | |||
161 | service->identity = NULL; | ||
162 | } | ||
163 | |||
164 | if (service->dir) | ||
165 | { | ||
166 | GNUNET_free(service->dir); | ||
167 | |||
168 | service->dir = NULL; | ||
169 | } | ||
170 | |||
171 | GNUNET_SERVICE_shutdown (service->service); | ||
172 | |||
173 | GNUNET_free(service); | ||
174 | } | ||
175 | |||
176 | struct GNUNET_MESSENGER_Ego* | ||
177 | lookup_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier) | ||
178 | { | ||
179 | GNUNET_assert(identifier); | ||
180 | |||
181 | struct GNUNET_HashCode hash; | ||
182 | |||
183 | GNUNET_CRYPTO_hash(identifier, strlen(identifier), &hash); | ||
184 | return GNUNET_CONTAINER_multihashmap_get(service->egos, &hash); | ||
185 | } | ||
186 | |||
187 | void | ||
188 | update_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier, | ||
189 | const struct GNUNET_IDENTITY_PrivateKey* key) | ||
190 | { | ||
191 | GNUNET_assert((identifier) && (key)); | ||
192 | |||
193 | struct GNUNET_HashCode hash; | ||
194 | |||
195 | GNUNET_CRYPTO_hash(identifier, strlen(identifier), &hash); | ||
196 | |||
197 | struct GNUNET_MESSENGER_Ego* ego = GNUNET_CONTAINER_multihashmap_get(service->egos, &hash); | ||
198 | |||
199 | if (!ego) | ||
200 | { | ||
201 | ego = GNUNET_new(struct GNUNET_MESSENGER_Ego); | ||
202 | GNUNET_CONTAINER_multihashmap_put(service->egos, &hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
203 | } | ||
204 | |||
205 | GNUNET_memcpy(&(ego->priv), key, sizeof(*key)); | ||
206 | |||
207 | if (GNUNET_OK != GNUNET_IDENTITY_key_get_public(key, &(ego->pub))) | ||
208 | GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating invalid ego key failed!\n"); | ||
209 | } | ||
210 | |||
211 | struct GNUNET_MESSENGER_SrvHandle* | ||
212 | add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq) | ||
213 | { | ||
214 | struct GNUNET_MESSENGER_SrvHandle *handle = create_handle (service, mq); | ||
215 | |||
216 | if (handle) | ||
217 | { | ||
218 | add_list_handle (&(service->handles), handle); | ||
219 | } | ||
220 | |||
221 | return handle; | ||
222 | } | ||
223 | |||
224 | void | ||
225 | remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle) | ||
226 | { | ||
227 | if (!handle) | ||
228 | return; | ||
229 | |||
230 | if (GNUNET_YES == remove_list_handle (&(service->handles), handle)) | ||
231 | destroy_handle (handle); | ||
232 | } | ||
233 | |||
234 | int | ||
235 | get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer) | ||
236 | { | ||
237 | return GNUNET_CRYPTO_get_peer_identity (service->config, peer); | ||
238 | } | ||
239 | |||
240 | struct GNUNET_MESSENGER_SrvContact* | ||
241 | get_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_IDENTITY_PublicKey *pubkey) | ||
242 | { | ||
243 | struct GNUNET_HashCode hash; | ||
244 | |||
245 | GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash); | ||
246 | |||
247 | struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multihashmap_get (service->contacts, &hash); | ||
248 | |||
249 | if (contact) | ||
250 | return contact; | ||
251 | |||
252 | contact = create_contact (pubkey); | ||
253 | |||
254 | if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->contacts, &hash, contact, | ||
255 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
256 | return contact; | ||
257 | |||
258 | destroy_contact (contact); | ||
259 | return NULL; | ||
260 | } | ||
261 | |||
262 | void | ||
263 | swap_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvContact *contact, | ||
264 | const struct GNUNET_IDENTITY_PublicKey *pubkey) | ||
265 | { | ||
266 | const struct GNUNET_HashCode *hash = get_contact_id_from_key (contact); | ||
267 | |||
268 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (service->contacts, hash, contact)) | ||
269 | { | ||
270 | GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey)); | ||
271 | |||
272 | hash = get_contact_id_from_key (contact); | ||
273 | |||
274 | GNUNET_CONTAINER_multihashmap_put (service->contacts, hash, contact, | ||
275 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | struct GNUNET_ShortHashCode* | ||
280 | generate_service_new_member_id (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key) | ||
281 | { | ||
282 | struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key); | ||
283 | |||
284 | if (room) | ||
285 | { | ||
286 | return generate_room_member_id (room); | ||
287 | } | ||
288 | else | ||
289 | { | ||
290 | struct GNUNET_ShortHashCode *random_id = GNUNET_new(struct GNUNET_ShortHashCode); | ||
291 | generate_free_member_id (random_id, NULL); | ||
292 | return random_id; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | struct GNUNET_MESSENGER_SrvRoom* | ||
297 | get_service_room (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key) | ||
298 | { | ||
299 | return GNUNET_CONTAINER_multihashmap_get (service->rooms, key); | ||
300 | } | ||
301 | |||
302 | int | ||
303 | open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
304 | const struct GNUNET_HashCode *key) | ||
305 | { | ||
306 | struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key); | ||
307 | |||
308 | if (room) | ||
309 | return open_room (room, handle); | ||
310 | |||
311 | room = create_room (handle, key); | ||
312 | |||
313 | if ((GNUNET_YES == open_room (room, handle)) && (GNUNET_OK | ||
314 | == GNUNET_CONTAINER_multihashmap_put (service->rooms, key, room, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) | ||
315 | return GNUNET_YES; | ||
316 | |||
317 | destroy_room (room); | ||
318 | return GNUNET_NO; | ||
319 | } | ||
320 | |||
321 | int | ||
322 | entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
323 | const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key) | ||
324 | { | ||
325 | struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key); | ||
326 | |||
327 | if (room) | ||
328 | { | ||
329 | if (GNUNET_YES == entry_room_at (room, handle, door)) | ||
330 | return GNUNET_YES; | ||
331 | else | ||
332 | return GNUNET_NO; | ||
333 | } | ||
334 | |||
335 | room = create_room (handle, key); | ||
336 | |||
337 | if ((GNUNET_YES == entry_room_at (room, handle, door)) && (GNUNET_OK | ||
338 | == GNUNET_CONTAINER_multihashmap_put (service->rooms, key, room, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) | ||
339 | { | ||
340 | return GNUNET_YES; | ||
341 | } | ||
342 | else | ||
343 | { | ||
344 | destroy_room (room); | ||
345 | return GNUNET_NO; | ||
346 | } | ||
347 | |||
348 | } | ||
349 | |||
350 | int | ||
351 | close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
352 | const struct GNUNET_HashCode *key) | ||
353 | { | ||
354 | struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key); | ||
355 | |||
356 | if (!room) | ||
357 | return GNUNET_NO; | ||
358 | |||
359 | struct GNUNET_MESSENGER_Message *message = create_message_leave (); | ||
360 | |||
361 | if (message) | ||
362 | { | ||
363 | struct GNUNET_HashCode hash; | ||
364 | |||
365 | send_room_message (room, handle, message, &hash); | ||
366 | destroy_message (message); | ||
367 | } | ||
368 | |||
369 | const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key); | ||
370 | |||
371 | GNUNET_assert(id); | ||
372 | |||
373 | if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (handle->member_ids, key, id)) | ||
374 | return GNUNET_NO; | ||
375 | |||
376 | struct GNUNET_MESSENGER_SrvHandle *member_handle = (struct GNUNET_MESSENGER_SrvHandle*) find_list_handle_by_member ( | ||
377 | &(service->handles), key); | ||
378 | |||
379 | if (!member_handle) | ||
380 | { | ||
381 | if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (service->rooms, key, room)) | ||
382 | { | ||
383 | destroy_room (room); | ||
384 | return GNUNET_YES; | ||
385 | } | ||
386 | else | ||
387 | return GNUNET_NO; | ||
388 | } | ||
389 | |||
390 | if (room->host == handle) | ||
391 | room->host = member_handle; | ||
392 | |||
393 | return GNUNET_YES; | ||
394 | } | ||
395 | |||
396 | static void | ||
397 | get_room_data_subdir (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room, char **dir) | ||
398 | { | ||
399 | GNUNET_asprintf (dir, "%s%s%c%s%c", service->dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (&(room->key)), DIR_SEPARATOR); | ||
400 | } | ||
401 | |||
402 | void | ||
403 | load_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room) | ||
404 | { | ||
405 | char *room_dir; | ||
406 | get_room_data_subdir (service, room, &room_dir); | ||
407 | |||
408 | if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES)) | ||
409 | { | ||
410 | load_message_store (&room->store, room_dir); | ||
411 | |||
412 | char *config_file; | ||
413 | GNUNET_asprintf (&config_file, "%s%s", room_dir, "room.cfg"); | ||
414 | |||
415 | struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create (); | ||
416 | |||
417 | if ((GNUNET_YES == GNUNET_DISK_file_test (config_file)) && (GNUNET_OK | ||
418 | == GNUNET_CONFIGURATION_parse (cfg, config_file))) | ||
419 | { | ||
420 | unsigned long long access; | ||
421 | |||
422 | if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "room", "access-rule", &access)) | ||
423 | room->strict_access = (int) (access); | ||
424 | |||
425 | char *message_string; | ||
426 | |||
427 | if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "room", "last-message", &message_string)) && (message_string)) | ||
428 | { | ||
429 | struct GNUNET_HashCode hash; | ||
430 | |||
431 | GNUNET_CRYPTO_hash_from_string(message_string, &hash); | ||
432 | |||
433 | const struct GNUNET_MESSENGER_Message *message = get_room_message (room, room->host, &hash, GNUNET_NO); | ||
434 | |||
435 | if (message) | ||
436 | update_room_last_messages (room, message, &hash); | ||
437 | |||
438 | GNUNET_free(message_string); | ||
439 | } | ||
440 | } | ||
441 | |||
442 | GNUNET_CONFIGURATION_destroy (cfg); | ||
443 | |||
444 | GNUNET_free(config_file); | ||
445 | } | ||
446 | |||
447 | GNUNET_free(room_dir); | ||
448 | } | ||
449 | |||
450 | void | ||
451 | save_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room) | ||
452 | { | ||
453 | if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains (service->rooms, &(room->key))) | ||
454 | { | ||
455 | return; | ||
456 | } | ||
457 | |||
458 | char *room_dir; | ||
459 | get_room_data_subdir (service, room, &room_dir); | ||
460 | |||
461 | if ((GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_NO)) || (GNUNET_OK | ||
462 | == GNUNET_DISK_directory_create (room_dir))) | ||
463 | { | ||
464 | save_message_store (&room->store, room_dir); | ||
465 | |||
466 | char *config_file; | ||
467 | GNUNET_asprintf (&config_file, "%s%s", room_dir, "room.cfg"); | ||
468 | |||
469 | struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create (); | ||
470 | |||
471 | GNUNET_CONFIGURATION_set_value_number (cfg, "room", "access-rule", room->strict_access); | ||
472 | |||
473 | if (room->last_messages.head) | ||
474 | GNUNET_CONFIGURATION_set_value_string (cfg, "room", "last-message", | ||
475 | GNUNET_h2s_full (&(room->last_messages.head->hash))); | ||
476 | |||
477 | GNUNET_CONFIGURATION_write (cfg, config_file); | ||
478 | GNUNET_CONFIGURATION_destroy (cfg); | ||
479 | |||
480 | GNUNET_free(config_file); | ||
481 | } | ||
482 | |||
483 | GNUNET_free(room_dir); | ||
484 | } | ||
485 | |||
486 | void | ||
487 | handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room, | ||
488 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) | ||
489 | { | ||
490 | struct GNUNET_MESSENGER_ListHandle *element = service->handles.head; | ||
491 | |||
492 | const uint16_t length = get_message_size (message); | ||
493 | |||
494 | while (element) | ||
495 | { | ||
496 | struct GNUNET_MESSENGER_SrvHandle *handle = (struct GNUNET_MESSENGER_SrvHandle*) element->handle; | ||
497 | |||
498 | if ((handle->mq) && (get_handle_member_id (handle, &(room->key)))) | ||
499 | { | ||
500 | struct GNUNET_MESSENGER_RecvMessage *msg; | ||
501 | struct GNUNET_MQ_Envelope *env; | ||
502 | |||
503 | env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE); | ||
504 | |||
505 | GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); | ||
506 | GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash)); | ||
507 | |||
508 | char *buffer = ((char*) msg) + sizeof(*msg); | ||
509 | encode_message (message, length, buffer); | ||
510 | |||
511 | GNUNET_MQ_send (handle->mq, env); | ||
512 | } | ||
513 | |||
514 | element = element->next; | ||
515 | } | ||
516 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_service.h b/src/messenger/gnunet-service-messenger_service.h new file mode 100644 index 000000000..246c74771 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_service.h | |||
@@ -0,0 +1,259 @@ | |||
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_service.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_SERVICE_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_SERVICE_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_configuration_lib.h" | ||
31 | #include "gnunet_crypto_lib.h" | ||
32 | #include "gnunet_container_lib.h" | ||
33 | #include "gnunet_disk_lib.h" | ||
34 | #include "gnunet_identity_service.h" | ||
35 | |||
36 | #include "messenger_api_ego.h" | ||
37 | |||
38 | #include "gnunet-service-messenger_list_handles.h" | ||
39 | |||
40 | #include "gnunet-service-messenger_contact.h" | ||
41 | #include "gnunet-service-messenger_room.h" | ||
42 | |||
43 | struct GNUNET_MESSENGER_Service | ||
44 | { | ||
45 | const struct GNUNET_CONFIGURATION_Handle *config; | ||
46 | struct GNUNET_SERVICE_Handle *service; | ||
47 | |||
48 | struct GNUNET_SCHEDULER_Task *shutdown; | ||
49 | |||
50 | char *dir; | ||
51 | |||
52 | struct GNUNET_CADET_Handle *cadet; | ||
53 | struct GNUNET_IDENTITY_Handle *identity; | ||
54 | |||
55 | struct GNUNET_CONTAINER_MultiHashMap *egos; | ||
56 | |||
57 | struct GNUNET_MESSENGER_ListHandles handles; | ||
58 | |||
59 | struct GNUNET_CONTAINER_MultiHashMap *contacts; | ||
60 | struct GNUNET_CONTAINER_MultiHashMap *rooms; | ||
61 | }; | ||
62 | |||
63 | /** | ||
64 | * Creates and allocates a new service using a given <i>config</i> and a GNUnet service handle. | ||
65 | * | ||
66 | * @param config Configuration | ||
67 | * @param service_handle GNUnet service handle | ||
68 | * @return New service | ||
69 | */ | ||
70 | struct GNUNET_MESSENGER_Service* | ||
71 | create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service_handle); | ||
72 | |||
73 | /** | ||
74 | * Destroys a <i>service</i> and frees its memory fully. | ||
75 | * | ||
76 | * @param service Service | ||
77 | */ | ||
78 | void | ||
79 | destroy_service (struct GNUNET_MESSENGER_Service *service); | ||
80 | |||
81 | /** | ||
82 | * Lookups an EGO which was registered to a <i>service</i> under | ||
83 | * a specific <i>identifier</i>. | ||
84 | * | ||
85 | * @param service Service | ||
86 | * @param identifier Identifier string | ||
87 | * @return EGO or NULL | ||
88 | */ | ||
89 | struct GNUNET_MESSENGER_Ego* | ||
90 | lookup_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier); | ||
91 | |||
92 | /** | ||
93 | * Updates the registration of an EGO to a <i>service</i> under | ||
94 | * a specific <i>identifier</i> with a new <i>key</i>. | ||
95 | * | ||
96 | * @param service Service | ||
97 | * @param identifier Identifier string | ||
98 | * @param key Private EGO key | ||
99 | */ | ||
100 | void | ||
101 | update_service_ego (struct GNUNET_MESSENGER_Service *service, const char *identifier, | ||
102 | const struct GNUNET_IDENTITY_PrivateKey* key); | ||
103 | |||
104 | /** | ||
105 | * Creates and adds a new handle to a <i>service</i> using a given message queue. | ||
106 | * | ||
107 | * @param service Service | ||
108 | * @param mq Message queue | ||
109 | * @return New handle | ||
110 | */ | ||
111 | struct GNUNET_MESSENGER_SrvHandle* | ||
112 | add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq); | ||
113 | |||
114 | /** | ||
115 | * Removes a <i>handle</i> from a <i>service</i> and destroys it. | ||
116 | * | ||
117 | * @param service Service | ||
118 | * @param handle Handle | ||
119 | */ | ||
120 | void | ||
121 | remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle); | ||
122 | |||
123 | /** | ||
124 | * Tries to write the peer identity of the peer running a <i>service</i> on to the <i>peer</i> | ||
125 | * parameter. The functions returns GNUNET_OK on success, otherwise GNUNET_SYSERR. | ||
126 | * | ||
127 | * @param service Service | ||
128 | * @param[out] peer Peer identity | ||
129 | * @return GNUNET_OK on success, otherwise GNUNET_SYSERR | ||
130 | */ | ||
131 | int | ||
132 | get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer); | ||
133 | |||
134 | /** | ||
135 | * Returns a contact of a <i>service</i> identified by a given public key. If no matching contact exists, | ||
136 | * it will tried to create one with the specific public key. If the function still fails to do so, | ||
137 | * NULL gets returned. | ||
138 | * | ||
139 | * @param service Service | ||
140 | * @param pubkey Public key of EGO | ||
141 | * @return Contact | ||
142 | */ | ||
143 | struct GNUNET_MESSENGER_SrvContact* | ||
144 | get_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_IDENTITY_PublicKey *pubkey); | ||
145 | |||
146 | /** | ||
147 | * Changes the public key for a <i>contact</i> known to a <i>service</i> to a specific public key and | ||
148 | * updates local map entries to access the contact by its updated key. | ||
149 | * | ||
150 | * @param service Service | ||
151 | * @param contact Contact | ||
152 | * @param pubkey Public key of EGO | ||
153 | */ | ||
154 | void | ||
155 | swap_service_contact_by_pubkey (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvContact *contact, | ||
156 | const struct GNUNET_IDENTITY_PublicKey *pubkey); | ||
157 | |||
158 | /** | ||
159 | * Tries to generate and allocate a new unique member id for a given room of a service identified by its <i>key</i>. | ||
160 | * If the generation fails caused by too many tries of duplicates, it returns NULL. | ||
161 | * | ||
162 | * @param service Service | ||
163 | * @param key Key of room | ||
164 | * @return Newly generated member id or NULL | ||
165 | */ | ||
166 | struct GNUNET_ShortHashCode* | ||
167 | generate_service_new_member_id (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key); | ||
168 | |||
169 | /** | ||
170 | * Returns the room identified by a given <i>key</i> for a <i>service</i>. If the service doesn't know any room | ||
171 | * using the given key, NULL gets returned. | ||
172 | * | ||
173 | * @param service Service | ||
174 | * @param key Key of room | ||
175 | * @return Room or NULL | ||
176 | */ | ||
177 | struct GNUNET_MESSENGER_SrvRoom* | ||
178 | get_service_room (struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key); | ||
179 | |||
180 | /** | ||
181 | * Tries to open a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will be | ||
182 | * created if necessary. If the function is successful, it returns GNUNET_YES, otherwise GNUNET_NO. | ||
183 | * | ||
184 | * @param service Service | ||
185 | * @param handle Handle | ||
186 | * @param key Key of room | ||
187 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
188 | */ | ||
189 | int | ||
190 | open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
191 | const struct GNUNET_HashCode *key); | ||
192 | |||
193 | /** | ||
194 | * Tries to enter a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will | ||
195 | * be created if necessary. If the function is successful, it returns GNUNET_YES, otherwise GNUNET_NO. | ||
196 | * | ||
197 | * The room will be entered through the peer identitied by the peer identity provided as <i>door</i> parameter and | ||
198 | * a new connection will be made. | ||
199 | * | ||
200 | * @param service Service | ||
201 | * @param handle Handle | ||
202 | * @param door Peer identity | ||
203 | * @param key Key of room | ||
204 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
205 | */ | ||
206 | int | ||
207 | entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
208 | const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key); | ||
209 | |||
210 | /** | ||
211 | * Tries to close a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will | ||
212 | * be created if necessary. If the function is successful, it returns GNUNET_YES, otherwise GNUNET_NO. | ||
213 | * | ||
214 | * If the specific handle is currently the host of the room for this service, a new handle which is a member will | ||
215 | * take its place. Otherwise the room will be destroyed for this service. | ||
216 | * | ||
217 | * @param service Service | ||
218 | * @param handle Handle | ||
219 | * @param key Key of room | ||
220 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
221 | */ | ||
222 | int | ||
223 | close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle, | ||
224 | const struct GNUNET_HashCode *key); | ||
225 | |||
226 | /** | ||
227 | * Loads the local configuration for a given <i>room</i> of a <i>service</i> which contains the last messages hash | ||
228 | * and the ruleset for general access of new members. | ||
229 | * | ||
230 | * @param service Service | ||
231 | * @param room Room | ||
232 | */ | ||
233 | void | ||
234 | load_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room); | ||
235 | |||
236 | /** | ||
237 | * Saves the configuration for a given <i>room</i> of a <i>service</i> which contains the last messages hash | ||
238 | * and the ruleset for general access of new members locally. | ||
239 | * | ||
240 | * @param service Service | ||
241 | * @param room Room | ||
242 | */ | ||
243 | void | ||
244 | save_service_room_and_messages (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room); | ||
245 | |||
246 | /** | ||
247 | * Sends a received or sent <i>message</i> with a given <i>hash</i> to each handle of a <i>service</i> which | ||
248 | * is currently member of a specific <i>room</i> for handling it in the client API. | ||
249 | * | ||
250 | * @param service Service | ||
251 | * @param room Room | ||
252 | * @param message Message | ||
253 | * @param hash Hash of message | ||
254 | */ | ||
255 | void | ||
256 | handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room, | ||
257 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
258 | |||
259 | #endif //GNUNET_SERVICE_MESSENGER_SERVICE_H | ||
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 | |||
31 | struct GNUNET_MESSENGER_SrvTunnel* | ||
32 | create_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 | |||
50 | void | ||
51 | destroy_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 | |||
72 | int | ||
73 | bind_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 | |||
90 | extern void | ||
91 | callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls); | ||
92 | |||
93 | void | ||
94 | callback_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 | |||
106 | extern int | ||
107 | callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, | ||
108 | struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash); | ||
109 | |||
110 | int | ||
111 | check_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 | |||
159 | extern void | ||
160 | callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message, | ||
161 | const struct GNUNET_HashCode *hash); | ||
162 | |||
163 | void | ||
164 | handle_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 | |||
190 | int | ||
191 | connect_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 | |||
212 | void | ||
213 | disconnect_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 | |||
223 | int | ||
224 | is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel) | ||
225 | { | ||
226 | return (tunnel->channel ? GNUNET_YES : GNUNET_NO); | ||
227 | } | ||
228 | |||
229 | struct GNUNET_MESSENGER_MessageSent | ||
230 | { | ||
231 | struct GNUNET_MESSENGER_SrvTunnel *tunnel; | ||
232 | struct GNUNET_HashCode hash; | ||
233 | }; | ||
234 | |||
235 | extern void | ||
236 | callback_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 | |||
239 | static void | ||
240 | callback_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 | |||
255 | void | ||
256 | send_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 | |||
273 | void | ||
274 | send_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 | |||
285 | void | ||
286 | forward_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 | |||
296 | const struct GNUNET_HashCode* | ||
297 | get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel) | ||
298 | { | ||
299 | return tunnel->peer_message; | ||
300 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_tunnel.h b/src/messenger/gnunet-service-messenger_tunnel.h new file mode 100644 index 000000000..e6efb226d --- /dev/null +++ b/src/messenger/gnunet-service-messenger_tunnel.h | |||
@@ -0,0 +1,155 @@ | |||
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.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_TUNNEL_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_TUNNEL_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_cadet_service.h" | ||
31 | #include "gnunet_peer_lib.h" | ||
32 | #include "gnunet_crypto_lib.h" | ||
33 | |||
34 | #include "gnunet-service-messenger_room.h" | ||
35 | |||
36 | struct GNUNET_MESSENGER_SrvTunnel | ||
37 | { | ||
38 | struct GNUNET_MESSENGER_SrvRoom *room; | ||
39 | struct GNUNET_CADET_Channel *channel; | ||
40 | |||
41 | GNUNET_PEER_Id peer; | ||
42 | struct GNUNET_ShortHashCode *contact_id; | ||
43 | |||
44 | struct GNUNET_HashCode *peer_message; | ||
45 | struct GNUNET_HashCode *last_message; | ||
46 | }; | ||
47 | |||
48 | /** | ||
49 | * Creates and allocates a tunnel of a <i>room</i> to a specific peer identity. | ||
50 | * | ||
51 | * @param room Room | ||
52 | * @param door Peer identity | ||
53 | * @return New tunnel | ||
54 | */ | ||
55 | struct GNUNET_MESSENGER_SrvTunnel* | ||
56 | create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *door); | ||
57 | |||
58 | /** | ||
59 | * Destroys a <i>tunnel</i> and frees its memory fully. | ||
60 | * | ||
61 | * @param tunnel | ||
62 | */ | ||
63 | void | ||
64 | destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); | ||
65 | |||
66 | /** | ||
67 | * Binds a CADET <i>channel</i> to a <i>tunnel</i> on returns GNUNET_YES only if | ||
68 | * the bounds channel was replaced successfully, otherwise GNUNET_NO gets returned. | ||
69 | * | ||
70 | * @param tunnel Tunnel | ||
71 | * @param channel CADET channel | ||
72 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
73 | */ | ||
74 | int | ||
75 | bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel); | ||
76 | |||
77 | /** | ||
78 | * Tries to connect a <i>tunnel</i> by creating a new CADET channel and binding it. | ||
79 | * The function returns GNUNET_YES on success, otherwise GNUNET_NO. | ||
80 | * | ||
81 | * @param tunnel Tunnel | ||
82 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
83 | */ | ||
84 | int | ||
85 | connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); | ||
86 | |||
87 | /** | ||
88 | * Disconnects and unbinds a channel from a <i>tunnel</i>. The actual disconnection | ||
89 | * will be asynchronous. | ||
90 | * | ||
91 | * @param tunnel Tunnel | ||
92 | */ | ||
93 | void | ||
94 | disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel); | ||
95 | |||
96 | /** | ||
97 | * Returns the status of a currently bound channel of a <i>tunnel</i>. | ||
98 | * | ||
99 | * @param tunnel Tunnel | ||
100 | * @return GNUNET_YES or GNUNET_NO | ||
101 | */ | ||
102 | int | ||
103 | is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel); | ||
104 | |||
105 | /** | ||
106 | * Sends an envelope containing a <i>message</i> with a given <i>hash</i> through | ||
107 | * a <i>tunnel</i> by a given <i>handle</i>. | ||
108 | * | ||
109 | * @param tunnel Tunnel | ||
110 | * @param handle Handle | ||
111 | * @param env Envelope | ||
112 | * @param message Message | ||
113 | * @param hash Hash of message | ||
114 | */ | ||
115 | void | ||
116 | send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MQ_Envelope *env, | ||
117 | struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
118 | |||
119 | /** | ||
120 | * Sends a <i>message</i> by packing it automatically into an envelope and passing it | ||
121 | * through the <i>tunnel</i>. The used <i>handle</i> will sign the message and | ||
122 | * the <i>hash</i> will be calculated and stored. | ||
123 | * | ||
124 | * @param tunnel Tunnel | ||
125 | * @param handle Handle | ||
126 | * @param[out] message Message | ||
127 | * @param[out] hash Hash of message | ||
128 | */ | ||
129 | void | ||
130 | send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message, | ||
131 | struct GNUNET_HashCode *hash); | ||
132 | |||
133 | /** | ||
134 | * Forwards a given <i>message</i> with a known <i>hash</i> through a <i>tunnel</i>. | ||
135 | * | ||
136 | * @param tunnel Tunnel | ||
137 | * @param message Message | ||
138 | * @param hash Hash of message | ||
139 | */ | ||
140 | void | ||
141 | forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message, | ||
142 | const struct GNUNET_HashCode *hash); | ||
143 | |||
144 | /** | ||
145 | * Returns the hash of the latest peer message published through a given <i>tunnel</i> | ||
146 | * and matching the tunnels peer identity. If no peer message has been linked to the tunnel | ||
147 | * yet, NULL gets returned. | ||
148 | * | ||
149 | * @param tunnel Tunnel | ||
150 | * @return Hash of peer message or NULL | ||
151 | */ | ||
152 | const struct GNUNET_HashCode* | ||
153 | get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel); | ||
154 | |||
155 | #endif //GNUNET_SERVICE_MESSENGER_TUNNEL_H | ||
diff --git a/src/messenger/gnunet-service-messenger_util.c b/src/messenger/gnunet-service-messenger_util.c new file mode 100644 index 000000000..94fc9469d --- /dev/null +++ b/src/messenger/gnunet-service-messenger_util.c | |||
@@ -0,0 +1,64 @@ | |||
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_util.c | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet-service-messenger_util.h" | ||
27 | |||
28 | static void | ||
29 | callback_close_channel (void *cls) | ||
30 | { | ||
31 | struct GNUNET_CADET_Channel *channel = cls; | ||
32 | |||
33 | if (channel) | ||
34 | GNUNET_CADET_channel_destroy (channel); | ||
35 | } | ||
36 | |||
37 | void | ||
38 | delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel) | ||
39 | { | ||
40 | GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (), GNUNET_SCHEDULER_PRIORITY_URGENT, | ||
41 | callback_close_channel, channel); | ||
42 | } | ||
43 | |||
44 | int | ||
45 | generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members) | ||
46 | { | ||
47 | size_t counter = 1 + (members ? GNUNET_CONTAINER_multishortmap_size (members) : 0); | ||
48 | |||
49 | do | ||
50 | { | ||
51 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, id, sizeof(struct GNUNET_ShortHashCode)); | ||
52 | |||
53 | if ((members) && (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (members, id))) | ||
54 | counter--; | ||
55 | else | ||
56 | break; | ||
57 | } | ||
58 | while (counter > 0); | ||
59 | |||
60 | if (counter) | ||
61 | return GNUNET_YES; | ||
62 | |||
63 | return GNUNET_NO; | ||
64 | } | ||
diff --git a/src/messenger/gnunet-service-messenger_util.h b/src/messenger/gnunet-service-messenger_util.h new file mode 100644 index 000000000..20f8f0afe --- /dev/null +++ b/src/messenger/gnunet-service-messenger_util.h | |||
@@ -0,0 +1,53 @@ | |||
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_util.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_SERVICE_MESSENGER_UTIL_H | ||
27 | #define GNUNET_SERVICE_MESSENGER_UTIL_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_cadet_service.h" | ||
31 | #include "gnunet_container_lib.h" | ||
32 | #include "gnunet_crypto_lib.h" | ||
33 | |||
34 | /** | ||
35 | * Starts an urgent task to close a CADET channel asynchronously. | ||
36 | * | ||
37 | * @param channel Channel | ||
38 | */ | ||
39 | void | ||
40 | delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel); | ||
41 | |||
42 | /** | ||
43 | * Tries to generate an unused member id and store it into the <i>id</i> parameter. A map containing all currently | ||
44 | * used member ids is used to check against. | ||
45 | * | ||
46 | * @param[out] id New member id | ||
47 | * @param members Map of member ids | ||
48 | * @return GNUNET_YES on success, GNUNET_NO on failure | ||
49 | */ | ||
50 | int | ||
51 | generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members); | ||
52 | |||
53 | #endif //GNUNET_SERVICE_MESSENGER_UTIL_H | ||
diff --git a/src/messenger/messenger.conf.in b/src/messenger/messenger.conf.in new file mode 100644 index 000000000..59e11b166 --- /dev/null +++ b/src/messenger/messenger.conf.in | |||
@@ -0,0 +1,13 @@ | |||
1 | [messenger] | ||
2 | START_ON_DEMAND = YES | ||
3 | PORT = 2097 | ||
4 | HOSTNAME = localhost | ||
5 | BINARY = gnunet-service-messenger | ||
6 | ACCEPT_FROM = 127.0.0.1; | ||
7 | ACCEPT_FROM6 = ::1; | ||
8 | UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-messenger.sock | ||
9 | UNIX_MATCH_UID = NO | ||
10 | UNIX_MATCH_GID = YES | ||
11 | |||
12 | # Directory to store messages and contacts | ||
13 | MESSENGER_DIR = $GNUNET_DATA_HOME/messenger/ \ No newline at end of file | ||
diff --git a/src/messenger/messenger_api.c b/src/messenger/messenger_api.c new file mode 100644 index 000000000..6401b18d7 --- /dev/null +++ b/src/messenger/messenger_api.c | |||
@@ -0,0 +1,568 @@ | |||
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/messenger_api.c | ||
23 | * @brief messenger api: client implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet_messenger_service.h" | ||
27 | |||
28 | #include "gnunet-service-messenger.h" | ||
29 | |||
30 | #include "messenger_api_handle.h" | ||
31 | #include "messenger_api_message.h" | ||
32 | |||
33 | const char* | ||
34 | GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind) | ||
35 | { | ||
36 | switch (kind) | ||
37 | { | ||
38 | case GNUNET_MESSENGER_KIND_INFO: | ||
39 | return "INFO"; | ||
40 | case GNUNET_MESSENGER_KIND_JOIN: | ||
41 | return "JOIN"; | ||
42 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
43 | return "LEAVE"; | ||
44 | case GNUNET_MESSENGER_KIND_NAME: | ||
45 | return "NAME"; | ||
46 | case GNUNET_MESSENGER_KIND_KEY: | ||
47 | return "KEY"; | ||
48 | case GNUNET_MESSENGER_KIND_PEER: | ||
49 | return "PEER"; | ||
50 | case GNUNET_MESSENGER_KIND_ID: | ||
51 | return "ID"; | ||
52 | case GNUNET_MESSENGER_KIND_MISS: | ||
53 | return "MISS"; | ||
54 | case GNUNET_MESSENGER_KIND_MERGE: | ||
55 | return "MERGE"; | ||
56 | case GNUNET_MESSENGER_KIND_REQUEST: | ||
57 | return "REQUEST"; | ||
58 | case GNUNET_MESSENGER_KIND_INVITE: | ||
59 | return "INVITE"; | ||
60 | case GNUNET_MESSENGER_KIND_TEXT: | ||
61 | return "TEXT"; | ||
62 | case GNUNET_MESSENGER_KIND_FILE: | ||
63 | return "FILE"; | ||
64 | default: | ||
65 | return "UNKNOWN"; | ||
66 | } | ||
67 | } | ||
68 | |||
69 | static int | ||
70 | check_get_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg) | ||
71 | { | ||
72 | GNUNET_MQ_check_zero_termination(msg); | ||
73 | return GNUNET_OK; | ||
74 | } | ||
75 | |||
76 | static void | ||
77 | handle_get_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg) | ||
78 | { | ||
79 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
80 | |||
81 | const char *name = ((const char*) msg) + sizeof(*msg); | ||
82 | |||
83 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set name of handle: %s\n", name); | ||
84 | |||
85 | set_handle_name (handle, strlen(name) > 0? name : NULL); | ||
86 | } | ||
87 | |||
88 | static void | ||
89 | handle_get_key (void *cls, const struct GNUNET_MESSENGER_KeyMessage *msg) | ||
90 | { | ||
91 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
92 | |||
93 | const struct GNUNET_IDENTITY_PublicKey *pubkey = &(msg->pubkey); | ||
94 | |||
95 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set key of handle: %s\n", GNUNET_IDENTITY_public_key_to_string (pubkey)); | ||
96 | |||
97 | set_handle_key (handle, pubkey); | ||
98 | |||
99 | if (handle->identity_callback) | ||
100 | handle->identity_callback (handle->identity_cls, handle); | ||
101 | } | ||
102 | |||
103 | static void | ||
104 | handle_member_id (void *cls, const struct GNUNET_MESSENGER_MemberMessage *msg) | ||
105 | { | ||
106 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
107 | |||
108 | const struct GNUNET_HashCode *key = &(msg->key); | ||
109 | const struct GNUNET_ShortHashCode *id = &(msg->id); | ||
110 | |||
111 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set id of handle in room: %s\n", GNUNET_h2s (key)); | ||
112 | |||
113 | struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); | ||
114 | |||
115 | if (room) | ||
116 | { | ||
117 | if (!room->contact_id) | ||
118 | room->contact_id = GNUNET_new(struct GNUNET_ShortHashCode); | ||
119 | |||
120 | GNUNET_memcpy(room->contact_id, id, sizeof(*id)); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static void | ||
125 | handle_room_open (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg) | ||
126 | { | ||
127 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
128 | |||
129 | const struct GNUNET_HashCode *key = &(msg->key); | ||
130 | |||
131 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opened room: %s\n", GNUNET_h2s (key)); | ||
132 | |||
133 | open_handle_room (handle, key); | ||
134 | } | ||
135 | |||
136 | static void | ||
137 | handle_room_entry (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg) | ||
138 | { | ||
139 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
140 | |||
141 | const struct GNUNET_PeerIdentity *door = &(msg->door); | ||
142 | const struct GNUNET_HashCode *key = &(msg->key); | ||
143 | |||
144 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entered room: %s\n", GNUNET_h2s (key)); | ||
145 | |||
146 | entry_handle_room_at (handle, door, key); | ||
147 | } | ||
148 | |||
149 | static void | ||
150 | handle_room_close (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg) | ||
151 | { | ||
152 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
153 | |||
154 | const struct GNUNET_HashCode *key = &(msg->key); | ||
155 | |||
156 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key)); | ||
157 | |||
158 | close_handle_room (handle, key); | ||
159 | } | ||
160 | |||
161 | static int | ||
162 | check_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg) | ||
163 | { | ||
164 | const uint16_t full_length = ntohs (msg->header.size) - sizeof(msg->header); | ||
165 | |||
166 | if (full_length < sizeof(msg->hash)) | ||
167 | return GNUNET_NO; | ||
168 | |||
169 | const uint16_t length = full_length - sizeof(msg->hash); | ||
170 | const char *buffer = ((const char*) msg) + sizeof(*msg); | ||
171 | |||
172 | struct GNUNET_MESSENGER_Message message; | ||
173 | |||
174 | if (length < sizeof(message.header)) | ||
175 | return GNUNET_NO; | ||
176 | |||
177 | if (GNUNET_YES != decode_message (&message, length, buffer)) | ||
178 | return GNUNET_NO; | ||
179 | |||
180 | return GNUNET_OK; | ||
181 | } | ||
182 | |||
183 | static void | ||
184 | handle_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg) | ||
185 | { | ||
186 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
187 | |||
188 | const struct GNUNET_HashCode *key = &(msg->key); | ||
189 | const struct GNUNET_HashCode *hash = &(msg->hash); | ||
190 | |||
191 | const char *buffer = ((const char*) msg) + sizeof(*msg); | ||
192 | |||
193 | const uint16_t length = ntohs (msg->header.size) - sizeof(*msg); | ||
194 | |||
195 | struct GNUNET_MESSENGER_Message message; | ||
196 | decode_message (&message, length, buffer); | ||
197 | |||
198 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", GNUNET_MESSENGER_name_of_kind (message.header.kind)); | ||
199 | |||
200 | struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); | ||
201 | |||
202 | if (room) | ||
203 | { | ||
204 | handle_room_message (room, &message, hash); | ||
205 | |||
206 | if (handle->msg_callback) | ||
207 | handle->msg_callback (handle->msg_cls, room, &message, hash); | ||
208 | } | ||
209 | else | ||
210 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MESSENGER ERROR: Room not found\n"); | ||
211 | } | ||
212 | |||
213 | static void | ||
214 | reconnect (struct GNUNET_MESSENGER_Handle *handle); | ||
215 | |||
216 | static void | ||
217 | send_open_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Room *room) | ||
218 | { | ||
219 | struct GNUNET_MESSENGER_RoomMessage *msg; | ||
220 | struct GNUNET_MQ_Envelope *env; | ||
221 | |||
222 | env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN); | ||
223 | GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); | ||
224 | GNUNET_MQ_send (handle->mq, env); | ||
225 | } | ||
226 | |||
227 | static void | ||
228 | send_entry_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Room *room, | ||
229 | const struct GNUNET_PeerIdentity *door) | ||
230 | { | ||
231 | struct GNUNET_MESSENGER_RoomMessage *msg; | ||
232 | struct GNUNET_MQ_Envelope *env; | ||
233 | |||
234 | env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY); | ||
235 | GNUNET_memcpy(&(msg->door), door, sizeof(*door)); | ||
236 | GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); | ||
237 | GNUNET_MQ_send (handle->mq, env); | ||
238 | } | ||
239 | |||
240 | static void | ||
241 | send_close_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Room *room) | ||
242 | { | ||
243 | struct GNUNET_MESSENGER_RoomMessage *msg; | ||
244 | struct GNUNET_MQ_Envelope *env; | ||
245 | |||
246 | env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE); | ||
247 | GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); | ||
248 | GNUNET_MQ_send (handle->mq, env); | ||
249 | } | ||
250 | |||
251 | static int | ||
252 | iterate_reset_room (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
253 | { | ||
254 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
255 | struct GNUNET_MESSENGER_Room *room = value; | ||
256 | |||
257 | if (GNUNET_YES == room->opened) | ||
258 | send_open_room (handle, room); | ||
259 | |||
260 | struct GNUNET_MESSENGER_ListTunnel *entry = room->entries.head; | ||
261 | |||
262 | struct GNUNET_PeerIdentity door; | ||
263 | |||
264 | while (entry) | ||
265 | { | ||
266 | GNUNET_PEER_resolve (entry->peer, &door); | ||
267 | |||
268 | send_entry_room (handle, room, &door); | ||
269 | |||
270 | entry = entry->next; | ||
271 | } | ||
272 | |||
273 | return GNUNET_YES; | ||
274 | } | ||
275 | |||
276 | static void | ||
277 | callback_reconnect (void *cls) | ||
278 | { | ||
279 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
280 | |||
281 | handle->reconnect_task = NULL; | ||
282 | handle->reconnect_time = GNUNET_TIME_STD_BACKOFF(handle->reconnect_time) | ||
283 | ; | ||
284 | |||
285 | reconnect (handle); | ||
286 | |||
287 | GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_reset_room, handle); | ||
288 | } | ||
289 | |||
290 | static int | ||
291 | iterate_close_room (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
292 | { | ||
293 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
294 | struct GNUNET_MESSENGER_Room *room = value; | ||
295 | |||
296 | send_close_room (handle, room); | ||
297 | |||
298 | return GNUNET_YES; | ||
299 | } | ||
300 | |||
301 | static void | ||
302 | callback_mq_error (void *cls, enum GNUNET_MQ_Error error) | ||
303 | { | ||
304 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
305 | |||
306 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MQ ERROR: %u\n", error); | ||
307 | |||
308 | GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room, handle); | ||
309 | |||
310 | if (handle->mq) | ||
311 | { | ||
312 | GNUNET_MQ_destroy (handle->mq); | ||
313 | handle->mq = NULL; | ||
314 | } | ||
315 | |||
316 | handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_time, &callback_reconnect, handle); | ||
317 | } | ||
318 | |||
319 | static void | ||
320 | reconnect (struct GNUNET_MESSENGER_Handle *handle) | ||
321 | { | ||
322 | const struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size( | ||
323 | get_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME, struct GNUNET_MESSENGER_NameMessage, handle), | ||
324 | GNUNET_MQ_hd_fixed_size( | ||
325 | get_key, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY, | ||
326 | struct GNUNET_MESSENGER_KeyMessage, handle), | ||
327 | GNUNET_MQ_hd_fixed_size( | ||
328 | member_id, | ||
329 | GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID, | ||
330 | struct GNUNET_MESSENGER_MemberMessage, handle), | ||
331 | GNUNET_MQ_hd_fixed_size(room_open, | ||
332 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN, | ||
333 | struct GNUNET_MESSENGER_RoomMessage, | ||
334 | handle), | ||
335 | GNUNET_MQ_hd_fixed_size(room_entry, | ||
336 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY, | ||
337 | struct GNUNET_MESSENGER_RoomMessage, | ||
338 | handle), | ||
339 | GNUNET_MQ_hd_fixed_size(room_close, | ||
340 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE, | ||
341 | struct GNUNET_MESSENGER_RoomMessage, | ||
342 | handle), | ||
343 | GNUNET_MQ_hd_var_size( | ||
344 | recv_message, | ||
345 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE, | ||
346 | struct GNUNET_MESSENGER_RecvMessage, handle), | ||
347 | GNUNET_MQ_handler_end() }; | ||
348 | |||
349 | handle->mq = GNUNET_CLIENT_connect (handle->cfg, | ||
350 | GNUNET_MESSENGER_SERVICE_NAME, | ||
351 | handlers, &callback_mq_error, handle); | ||
352 | } | ||
353 | |||
354 | struct GNUNET_MESSENGER_Handle* | ||
355 | GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *name, | ||
356 | GNUNET_MESSENGER_IdentityCallback identity_callback, void *identity_cls, | ||
357 | GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls) | ||
358 | { | ||
359 | struct GNUNET_MESSENGER_Handle *handle = create_handle (cfg, identity_callback, identity_cls, msg_callback, msg_cls); | ||
360 | |||
361 | reconnect (handle); | ||
362 | |||
363 | if (handle->mq) | ||
364 | { | ||
365 | const uint16_t name_len = name ? strlen (name) : 0; | ||
366 | |||
367 | struct GNUNET_MESSENGER_CreateMessage *msg; | ||
368 | struct GNUNET_MQ_Envelope *env; | ||
369 | |||
370 | env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE); | ||
371 | |||
372 | char *extra = ((char*) msg) + sizeof(*msg); | ||
373 | |||
374 | if (name_len) | ||
375 | GNUNET_memcpy(extra, name, name_len); | ||
376 | |||
377 | extra[name_len] = '\0'; | ||
378 | |||
379 | GNUNET_MQ_send (handle->mq, env); | ||
380 | return handle; | ||
381 | } | ||
382 | else | ||
383 | { | ||
384 | destroy_handle (handle); | ||
385 | return NULL; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | int | ||
390 | GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle) | ||
391 | { | ||
392 | if ((!handle) || (!get_handle_name(handle))) | ||
393 | return GNUNET_SYSERR; | ||
394 | |||
395 | struct GNUNET_MESSENGER_UpdateMessage *msg; | ||
396 | struct GNUNET_MQ_Envelope *env; | ||
397 | |||
398 | env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE); | ||
399 | GNUNET_MQ_send (handle->mq, env); | ||
400 | return GNUNET_OK; | ||
401 | } | ||
402 | |||
403 | void | ||
404 | GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle) | ||
405 | { | ||
406 | if (!handle) | ||
407 | return; | ||
408 | |||
409 | struct GNUNET_MESSENGER_DestroyMessage *msg; | ||
410 | struct GNUNET_MQ_Envelope *env; | ||
411 | |||
412 | env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY); | ||
413 | GNUNET_MQ_send (handle->mq, env); | ||
414 | |||
415 | destroy_handle (handle); | ||
416 | } | ||
417 | |||
418 | const char* | ||
419 | GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle) | ||
420 | { | ||
421 | if (!handle) | ||
422 | return NULL; | ||
423 | |||
424 | return get_handle_name (handle); | ||
425 | } | ||
426 | |||
427 | int | ||
428 | GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle, const char *name) | ||
429 | { | ||
430 | if (!handle) | ||
431 | return GNUNET_SYSERR; | ||
432 | |||
433 | const uint16_t name_len = name ? strlen (name) : 0; | ||
434 | |||
435 | struct GNUNET_MESSENGER_NameMessage *msg; | ||
436 | struct GNUNET_MQ_Envelope *env; | ||
437 | |||
438 | env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME); | ||
439 | |||
440 | char *extra = ((char*) msg) + sizeof(*msg); | ||
441 | |||
442 | if (name_len) | ||
443 | GNUNET_memcpy(extra, name, name_len); | ||
444 | |||
445 | extra[name_len] = '\0'; | ||
446 | |||
447 | GNUNET_MQ_send (handle->mq, env); | ||
448 | return GNUNET_YES; | ||
449 | } | ||
450 | |||
451 | const struct GNUNET_IDENTITY_PublicKey* | ||
452 | GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle) | ||
453 | { | ||
454 | if (!handle) | ||
455 | return NULL; | ||
456 | |||
457 | return get_handle_key (handle); | ||
458 | } | ||
459 | |||
460 | struct GNUNET_MESSENGER_Room* | ||
461 | GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) | ||
462 | { | ||
463 | struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); | ||
464 | |||
465 | if (!room) | ||
466 | { | ||
467 | room = create_room (handle, key); | ||
468 | |||
469 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room, | ||
470 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
471 | { | ||
472 | destroy_room (room); | ||
473 | return NULL; | ||
474 | } | ||
475 | } | ||
476 | |||
477 | send_open_room (handle, room); | ||
478 | return room; | ||
479 | } | ||
480 | |||
481 | struct GNUNET_MESSENGER_Room* | ||
482 | GNUNET_MESSENGER_entry_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, | ||
483 | const struct GNUNET_HashCode *key) | ||
484 | { | ||
485 | struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); | ||
486 | |||
487 | if (!room) | ||
488 | { | ||
489 | room = create_room (handle, key); | ||
490 | |||
491 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room, | ||
492 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
493 | { | ||
494 | destroy_room (room); | ||
495 | return NULL; | ||
496 | } | ||
497 | } | ||
498 | |||
499 | send_entry_room (handle, room, door); | ||
500 | return room; | ||
501 | } | ||
502 | |||
503 | void | ||
504 | GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room) | ||
505 | { | ||
506 | send_close_room (room->handle, room); | ||
507 | } | ||
508 | |||
509 | struct GNUNET_MESSENGER_Contact* | ||
510 | GNUNET_MESSENGER_get_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_ShortHashCode *id) | ||
511 | { | ||
512 | return GNUNET_CONTAINER_multishortmap_get (room->members, id); | ||
513 | } | ||
514 | |||
515 | const char* | ||
516 | GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact) | ||
517 | { | ||
518 | if (!contact) | ||
519 | return NULL; | ||
520 | |||
521 | return get_contact_name (contact); | ||
522 | } | ||
523 | |||
524 | const struct GNUNET_IDENTITY_PublicKey* | ||
525 | GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact) | ||
526 | { | ||
527 | if (!contact) | ||
528 | return NULL; | ||
529 | |||
530 | return get_contact_key (contact); | ||
531 | } | ||
532 | |||
533 | void | ||
534 | GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message) | ||
535 | { | ||
536 | const uint16_t length = get_message_size (message); | ||
537 | |||
538 | struct GNUNET_MESSENGER_SendMessage *msg; | ||
539 | struct GNUNET_MQ_Envelope *env; | ||
540 | |||
541 | env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE); | ||
542 | |||
543 | GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); | ||
544 | |||
545 | char *buffer = ((char*) msg) + sizeof(*msg); | ||
546 | encode_message (message, length, buffer); | ||
547 | |||
548 | GNUNET_MQ_send (room->handle->mq, env); | ||
549 | } | ||
550 | |||
551 | const struct GNUNET_MESSENGER_Message* | ||
552 | GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) | ||
553 | { | ||
554 | const struct GNUNET_MESSENGER_Message *message = get_room_message (room, hash); | ||
555 | |||
556 | if (!message) | ||
557 | { | ||
558 | struct GNUNET_MESSENGER_RecvMessage *msg; | ||
559 | struct GNUNET_MQ_Envelope *env; | ||
560 | |||
561 | env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE); | ||
562 | GNUNET_memcpy(&(msg->key), &(room->key), sizeof(room->key)); | ||
563 | GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash)); | ||
564 | GNUNET_MQ_send (room->handle->mq, env); | ||
565 | } | ||
566 | |||
567 | return message; | ||
568 | } | ||
diff --git a/src/messenger/messenger_api_contact.c b/src/messenger/messenger_api_contact.c new file mode 100644 index 000000000..9a242aa00 --- /dev/null +++ b/src/messenger/messenger_api_contact.c | |||
@@ -0,0 +1,78 @@ | |||
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/messenger_api_contact.c | ||
23 | * @brief messenger api: client implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "messenger_api_contact.h" | ||
27 | |||
28 | struct GNUNET_MESSENGER_Contact* | ||
29 | create_contact (const struct GNUNET_IDENTITY_PublicKey *key) | ||
30 | { | ||
31 | struct GNUNET_MESSENGER_Contact *contact = GNUNET_new(struct GNUNET_MESSENGER_Contact); | ||
32 | |||
33 | contact->name = NULL; | ||
34 | |||
35 | GNUNET_memcpy(&(contact->public_key), key, sizeof(contact->public_key)); | ||
36 | |||
37 | return contact; | ||
38 | } | ||
39 | |||
40 | void | ||
41 | destroy_contact (struct GNUNET_MESSENGER_Contact *contact) | ||
42 | { | ||
43 | if (contact->name) | ||
44 | GNUNET_free(contact->name); | ||
45 | |||
46 | GNUNET_free(contact); | ||
47 | } | ||
48 | |||
49 | const char* | ||
50 | get_contact_name (const struct GNUNET_MESSENGER_Contact *contact) | ||
51 | { | ||
52 | return contact->name; | ||
53 | } | ||
54 | |||
55 | void | ||
56 | set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name) | ||
57 | { | ||
58 | if (contact->name) | ||
59 | GNUNET_free(contact->name); | ||
60 | |||
61 | contact->name = name? GNUNET_strdup(name) : NULL; | ||
62 | } | ||
63 | |||
64 | const struct GNUNET_IDENTITY_PublicKey* | ||
65 | get_contact_key (const struct GNUNET_MESSENGER_Contact *contact) | ||
66 | { | ||
67 | return &(contact->public_key); | ||
68 | } | ||
69 | |||
70 | const struct GNUNET_HashCode* | ||
71 | get_contact_id_from_key (const struct GNUNET_MESSENGER_Contact *contact) | ||
72 | { | ||
73 | static struct GNUNET_HashCode id; | ||
74 | |||
75 | GNUNET_CRYPTO_hash (&(contact->public_key), sizeof(contact->public_key), &id); | ||
76 | |||
77 | return &id; | ||
78 | } | ||
diff --git a/src/messenger/messenger_api_contact.h b/src/messenger/messenger_api_contact.h new file mode 100644 index 000000000..0673b9b85 --- /dev/null +++ b/src/messenger/messenger_api_contact.h | |||
@@ -0,0 +1,93 @@ | |||
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/messenger_api_contact.h | ||
23 | * @brief messenger api: client implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_MESSENGER_API_CONTACT_H | ||
27 | #define GNUNET_MESSENGER_API_CONTACT_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_crypto_lib.h" | ||
31 | #include "gnunet_identity_service.h" | ||
32 | |||
33 | struct GNUNET_MESSENGER_Contact | ||
34 | { | ||
35 | char *name; | ||
36 | |||
37 | struct GNUNET_IDENTITY_PublicKey public_key; | ||
38 | }; | ||
39 | |||
40 | /** | ||
41 | * Creates and allocates a new contact with a given public <i>key</i> from an EGO. | ||
42 | * | ||
43 | * @param key Public key | ||
44 | * @return New contact | ||
45 | */ | ||
46 | struct GNUNET_MESSENGER_Contact* | ||
47 | create_contact (const struct GNUNET_IDENTITY_PublicKey *key); | ||
48 | |||
49 | /** | ||
50 | * Destroys a contact and frees its memory fully. | ||
51 | * | ||
52 | * @param contact Contact | ||
53 | */ | ||
54 | void | ||
55 | destroy_contact (struct GNUNET_MESSENGER_Contact *contact); | ||
56 | |||
57 | /** | ||
58 | * Returns the current name of a given <i>contact</i> or NULL if no valid name was assigned yet. | ||
59 | * | ||
60 | * @param contact Contact | ||
61 | * @return Name of the contact or NULL | ||
62 | */ | ||
63 | const char* | ||
64 | get_contact_name (const struct GNUNET_MESSENGER_Contact *contact); | ||
65 | |||
66 | /** | ||
67 | * Changes the current name of a given <i>contact</i> by copying it from the parameter <i>name</i>. | ||
68 | * | ||
69 | * @param contact Contact | ||
70 | * @param name Valid name (may not be NULL!) | ||
71 | */ | ||
72 | void | ||
73 | set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name); | ||
74 | |||
75 | /** | ||
76 | * Returns the public key of a given <i>contact</i>. | ||
77 | * | ||
78 | * @param contact Contact | ||
79 | * @return Public key of the contact | ||
80 | */ | ||
81 | const struct GNUNET_IDENTITY_PublicKey* | ||
82 | get_contact_key (const struct GNUNET_MESSENGER_Contact *contact); | ||
83 | |||
84 | /** | ||
85 | * Returns the resulting hashcode of the public key from a given <i>contact</i>. | ||
86 | * | ||
87 | * @param contact Contact | ||
88 | * @return Hash of the contacts public key | ||
89 | */ | ||
90 | const struct GNUNET_HashCode* | ||
91 | get_contact_id_from_key (const struct GNUNET_MESSENGER_Contact *contact); | ||
92 | |||
93 | #endif //GNUNET_MESSENGER_API_CONTACT_H | ||
diff --git a/src/messenger/messenger_api_ego.h b/src/messenger/messenger_api_ego.h new file mode 100644 index 000000000..c60eeac50 --- /dev/null +++ b/src/messenger/messenger_api_ego.h | |||
@@ -0,0 +1,38 @@ | |||
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/messenger_api_ego.h | ||
23 | * @brief GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_MESSENGER_API_EGO_H | ||
27 | #define GNUNET_MESSENGER_API_EGO_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_identity_service.h" | ||
31 | |||
32 | struct GNUNET_MESSENGER_Ego | ||
33 | { | ||
34 | struct GNUNET_IDENTITY_PrivateKey priv; | ||
35 | struct GNUNET_IDENTITY_PublicKey pub; | ||
36 | }; | ||
37 | |||
38 | #endif //GNUNET_MESSENGER_API_EGO_H | ||
diff --git a/src/messenger/messenger_api_handle.c b/src/messenger/messenger_api_handle.c new file mode 100644 index 000000000..20ef77254 --- /dev/null +++ b/src/messenger/messenger_api_handle.c | |||
@@ -0,0 +1,213 @@ | |||
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/messenger_api_handle.c | ||
23 | * @brief messenger api: client implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "messenger_api_handle.h" | ||
27 | |||
28 | struct GNUNET_MESSENGER_Handle* | ||
29 | create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_IdentityCallback identity_callback, | ||
30 | void *identity_cls, GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls) | ||
31 | { | ||
32 | struct GNUNET_MESSENGER_Handle *handle = GNUNET_new(struct GNUNET_MESSENGER_Handle); | ||
33 | |||
34 | handle->cfg = cfg; | ||
35 | handle->mq = NULL; | ||
36 | |||
37 | handle->identity_callback = identity_callback; | ||
38 | handle->identity_cls = identity_cls; | ||
39 | |||
40 | handle->msg_callback = msg_callback; | ||
41 | handle->msg_cls = msg_cls; | ||
42 | |||
43 | handle->name = NULL; | ||
44 | handle->pubkey = NULL; | ||
45 | |||
46 | handle->reconnect_time = GNUNET_TIME_relative_get_zero_ (); | ||
47 | handle->reconnect_task = NULL; | ||
48 | |||
49 | handle->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | ||
50 | handle->contacts = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | ||
51 | |||
52 | return handle; | ||
53 | } | ||
54 | |||
55 | static int | ||
56 | iterate_destroy_room (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
57 | { | ||
58 | struct GNUNET_MESSENGER_Room *room = value; | ||
59 | |||
60 | destroy_room (room); | ||
61 | |||
62 | return GNUNET_YES; | ||
63 | } | ||
64 | |||
65 | static int | ||
66 | iterate_destroy_contact (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
67 | { | ||
68 | struct GNUNET_MESSENGER_Contact *contact = value; | ||
69 | |||
70 | destroy_contact (contact); | ||
71 | |||
72 | return GNUNET_YES; | ||
73 | } | ||
74 | |||
75 | void | ||
76 | destroy_handle (struct GNUNET_MESSENGER_Handle *handle) | ||
77 | { | ||
78 | if (handle->reconnect_task) | ||
79 | GNUNET_SCHEDULER_cancel (handle->reconnect_task); | ||
80 | |||
81 | if (handle->mq) | ||
82 | GNUNET_MQ_destroy (handle->mq); | ||
83 | |||
84 | if (handle->name) | ||
85 | GNUNET_free(handle->name); | ||
86 | |||
87 | if (handle->pubkey) | ||
88 | GNUNET_free(handle->pubkey); | ||
89 | |||
90 | if (handle->rooms) | ||
91 | { | ||
92 | GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_destroy_room, NULL); | ||
93 | |||
94 | GNUNET_CONTAINER_multihashmap_destroy (handle->rooms); | ||
95 | } | ||
96 | |||
97 | if (handle->contacts) | ||
98 | { | ||
99 | GNUNET_CONTAINER_multihashmap_iterate (handle->contacts, iterate_destroy_contact, NULL); | ||
100 | |||
101 | GNUNET_CONTAINER_multihashmap_destroy (handle->contacts); | ||
102 | } | ||
103 | |||
104 | GNUNET_free(handle->name); | ||
105 | } | ||
106 | |||
107 | void | ||
108 | set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name) | ||
109 | { | ||
110 | if (handle->name) | ||
111 | GNUNET_free(handle->name); | ||
112 | |||
113 | handle->name = name? GNUNET_strdup(name) : NULL; | ||
114 | } | ||
115 | |||
116 | const char* | ||
117 | get_handle_name (const struct GNUNET_MESSENGER_Handle *handle) | ||
118 | { | ||
119 | return handle->name; | ||
120 | } | ||
121 | |||
122 | void | ||
123 | set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey) | ||
124 | { | ||
125 | if (!handle->pubkey) | ||
126 | handle->pubkey = GNUNET_new(struct GNUNET_IDENTITY_PublicKey); | ||
127 | |||
128 | GNUNET_memcpy(handle->pubkey, pubkey, sizeof(*pubkey)); | ||
129 | } | ||
130 | |||
131 | const struct GNUNET_IDENTITY_PublicKey* | ||
132 | get_handle_key (const struct GNUNET_MESSENGER_Handle *handle) | ||
133 | { | ||
134 | if (!handle->pubkey) | ||
135 | { | ||
136 | struct GNUNET_IDENTITY_Ego *anonymous = GNUNET_IDENTITY_ego_get_anonymous (); | ||
137 | static struct GNUNET_IDENTITY_PublicKey pubkey; | ||
138 | |||
139 | GNUNET_IDENTITY_ego_get_public_key (anonymous, &pubkey); | ||
140 | |||
141 | return &pubkey; | ||
142 | } | ||
143 | |||
144 | return handle->pubkey; | ||
145 | } | ||
146 | |||
147 | struct GNUNET_MESSENGER_Contact* | ||
148 | get_handle_contact_by_pubkey (const struct GNUNET_MESSENGER_Handle *handle, | ||
149 | const struct GNUNET_IDENTITY_PublicKey *pubkey) | ||
150 | { | ||
151 | struct GNUNET_HashCode hash; | ||
152 | |||
153 | GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash); | ||
154 | |||
155 | struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multihashmap_get (handle->contacts, &hash); | ||
156 | |||
157 | if (contact) | ||
158 | return contact; | ||
159 | |||
160 | contact = create_contact (pubkey); | ||
161 | |||
162 | if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (handle->contacts, &hash, contact, | ||
163 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
164 | return contact; | ||
165 | |||
166 | destroy_contact (contact); | ||
167 | return NULL; | ||
168 | } | ||
169 | |||
170 | void | ||
171 | swap_handle_contact_by_pubkey (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Contact *contact, | ||
172 | const struct GNUNET_IDENTITY_PublicKey *pubkey) | ||
173 | { | ||
174 | const struct GNUNET_HashCode *hash = get_contact_id_from_key (contact); | ||
175 | |||
176 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->contacts, hash, contact)) | ||
177 | { | ||
178 | GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey)); | ||
179 | |||
180 | hash = get_contact_id_from_key (contact); | ||
181 | |||
182 | GNUNET_CONTAINER_multihashmap_put (handle->contacts, hash, contact, | ||
183 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
184 | } | ||
185 | } | ||
186 | |||
187 | void | ||
188 | open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) | ||
189 | { | ||
190 | struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); | ||
191 | |||
192 | if (room) | ||
193 | room->opened = GNUNET_YES; | ||
194 | } | ||
195 | |||
196 | void | ||
197 | entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, | ||
198 | const struct GNUNET_HashCode *key) | ||
199 | { | ||
200 | struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); | ||
201 | |||
202 | if (room) | ||
203 | add_to_list_tunnels (&(room->entries), door); | ||
204 | } | ||
205 | |||
206 | void | ||
207 | close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) | ||
208 | { | ||
209 | struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key); | ||
210 | |||
211 | if ((room) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->rooms, key, room))) | ||
212 | destroy_room (room); | ||
213 | } | ||
diff --git a/src/messenger/messenger_api_handle.h b/src/messenger/messenger_api_handle.h new file mode 100644 index 000000000..d6cde0106 --- /dev/null +++ b/src/messenger/messenger_api_handle.h | |||
@@ -0,0 +1,174 @@ | |||
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/messenger_api_handle.h | ||
23 | * @brief messenger api: client implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_MESSENGER_API_HANDLE_H | ||
27 | #define GNUNET_MESSENGER_API_HANDLE_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_cadet_service.h" | ||
31 | #include "gnunet_container_lib.h" | ||
32 | #include "gnunet_crypto_lib.h" | ||
33 | #include "gnunet_identity_service.h" | ||
34 | #include "gnunet_peer_lib.h" | ||
35 | |||
36 | #include "gnunet_messenger_service.h" | ||
37 | |||
38 | #include "messenger_api_contact.h" | ||
39 | #include "messenger_api_room.h" | ||
40 | |||
41 | struct GNUNET_MESSENGER_Handle | ||
42 | { | ||
43 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
44 | |||
45 | struct GNUNET_MQ_Handle *mq; | ||
46 | |||
47 | GNUNET_MESSENGER_IdentityCallback identity_callback; | ||
48 | void *identity_cls; | ||
49 | |||
50 | GNUNET_MESSENGER_MessageCallback msg_callback; | ||
51 | void *msg_cls; | ||
52 | |||
53 | char *name; | ||
54 | struct GNUNET_IDENTITY_PublicKey *pubkey; | ||
55 | |||
56 | struct GNUNET_TIME_Relative reconnect_time; | ||
57 | struct GNUNET_SCHEDULER_Task *reconnect_task; | ||
58 | |||
59 | struct GNUNET_CONTAINER_MultiHashMap *rooms; | ||
60 | struct GNUNET_CONTAINER_MultiHashMap *contacts; | ||
61 | }; | ||
62 | |||
63 | /** | ||
64 | * Creates and allocates a new handle using a given configuration and a custom message callback | ||
65 | * with a given closure for the client API. | ||
66 | * | ||
67 | * @param cfg Configuration | ||
68 | * @param msg_callback Message callback | ||
69 | * @param msg_cls Closure | ||
70 | * @return New handle | ||
71 | */ | ||
72 | struct GNUNET_MESSENGER_Handle* | ||
73 | create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_IdentityCallback identity_callback, | ||
74 | void *identity_cls, GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls); | ||
75 | |||
76 | /** | ||
77 | * Destroys a <i>handle</i> and frees its memory fully from the client API. | ||
78 | * | ||
79 | * @param handle Handle | ||
80 | */ | ||
81 | void | ||
82 | destroy_handle (struct GNUNET_MESSENGER_Handle *handle); | ||
83 | |||
84 | /** | ||
85 | * Sets the name of a <i>handle</i> to a specific <i>name</i>. | ||
86 | * | ||
87 | * @param handle Handle | ||
88 | * @param name New name | ||
89 | */ | ||
90 | void | ||
91 | set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name); | ||
92 | |||
93 | /** | ||
94 | * Returns the current name of a given <i>handle</i> or NULL if no valid name was assigned yet. | ||
95 | * | ||
96 | * @param handle Handle | ||
97 | * @return Name of the handle or NULL | ||
98 | */ | ||
99 | const char* | ||
100 | get_handle_name (const struct GNUNET_MESSENGER_Handle *handle); | ||
101 | |||
102 | /** | ||
103 | * Sets the public key of a given <i>handle</i> to a specific public key. | ||
104 | * | ||
105 | * @param handle Handle | ||
106 | * @param pubkey Public key | ||
107 | */ | ||
108 | void | ||
109 | set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey); | ||
110 | |||
111 | /** | ||
112 | * Returns the public key of a given <i>handle</i>. | ||
113 | * | ||
114 | * @param handle Handle | ||
115 | * @return Public key of the handle | ||
116 | */ | ||
117 | const struct GNUNET_IDENTITY_PublicKey* | ||
118 | get_handle_key (const struct GNUNET_MESSENGER_Handle *handle); | ||
119 | |||
120 | /** | ||
121 | * Returns a contact known to a <i>handle</i> identified by a given public key. If not matching | ||
122 | * contact is found, NULL gets returned. | ||
123 | * | ||
124 | * @param handle Handle | ||
125 | * @param pubkey Public key of EGO | ||
126 | * @return Contact or NULL | ||
127 | */ | ||
128 | struct GNUNET_MESSENGER_Contact* | ||
129 | get_handle_contact_by_pubkey (const struct GNUNET_MESSENGER_Handle *handle, | ||
130 | const struct GNUNET_IDENTITY_PublicKey *pubkey); | ||
131 | |||
132 | /** | ||
133 | * Changes the public key for a <i>contact</i> known to a <i>handle</i> to a specific public key and | ||
134 | * updates local map entries to access the contact by its updated key. | ||
135 | * | ||
136 | * @param handle Handle | ||
137 | * @param contact Contact | ||
138 | * @param pubkey Public key of EGO | ||
139 | */ | ||
140 | void | ||
141 | swap_handle_contact_by_pubkey (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Contact *contact, | ||
142 | const struct GNUNET_IDENTITY_PublicKey *pubkey); | ||
143 | |||
144 | /** | ||
145 | * Marks a room known to a <i>handle</i> identified by a given <i>key</i> as open. | ||
146 | * | ||
147 | * @param handle Handle | ||
148 | * @param key Key of room | ||
149 | */ | ||
150 | void | ||
151 | open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); | ||
152 | |||
153 | /** | ||
154 | * Adds a tunnel for a room known to a <i>handle</i> identified by a given <i>key</i> to a | ||
155 | * list of opened connections. | ||
156 | * | ||
157 | * @param handle Handle | ||
158 | * @param door Peer identity | ||
159 | * @param key Key of room | ||
160 | */ | ||
161 | void | ||
162 | entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door, | ||
163 | const struct GNUNET_HashCode *key); | ||
164 | |||
165 | /** | ||
166 | * Destroys and so implicitly closes a room known to a <i>handle</i> identified by a given <i>key</i>. | ||
167 | * | ||
168 | * @param handle Handle | ||
169 | * @param key Key of room | ||
170 | */ | ||
171 | void | ||
172 | close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); | ||
173 | |||
174 | #endif //GNUNET_MESSENGER_API_HANDLE_H | ||
diff --git a/src/messenger/messenger_api_list_tunnels.c b/src/messenger/messenger_api_list_tunnels.c new file mode 100644 index 000000000..13d8c1906 --- /dev/null +++ b/src/messenger/messenger_api_list_tunnels.c | |||
@@ -0,0 +1,112 @@ | |||
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/messenger_api_list_tunnels.c | ||
23 | * @brief messenger api: client and service implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "messenger_api_list_tunnels.h" | ||
27 | |||
28 | void | ||
29 | init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels) | ||
30 | { | ||
31 | GNUNET_assert(tunnels); | ||
32 | |||
33 | tunnels->head = NULL; | ||
34 | tunnels->tail = NULL; | ||
35 | } | ||
36 | |||
37 | void | ||
38 | clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels) | ||
39 | { | ||
40 | GNUNET_assert(tunnels); | ||
41 | |||
42 | struct GNUNET_MESSENGER_ListTunnel *element; | ||
43 | |||
44 | for (element = tunnels->head; element; element = tunnels->head) | ||
45 | { | ||
46 | GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element); | ||
47 | GNUNET_PEER_change_rc (element->peer, -1); | ||
48 | GNUNET_free(element); | ||
49 | } | ||
50 | |||
51 | tunnels->head = NULL; | ||
52 | tunnels->tail = NULL; | ||
53 | } | ||
54 | |||
55 | static int | ||
56 | compare_list_tunnels (void *cls, struct GNUNET_MESSENGER_ListTunnel *element0, | ||
57 | struct GNUNET_MESSENGER_ListTunnel *element1) | ||
58 | { | ||
59 | return ((int) element0->peer) - ((int) element1->peer); | ||
60 | } | ||
61 | |||
62 | void | ||
63 | add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer) | ||
64 | { | ||
65 | struct GNUNET_MESSENGER_ListTunnel *element = GNUNET_new(struct GNUNET_MESSENGER_ListTunnel); | ||
66 | |||
67 | element->peer = GNUNET_PEER_intern (peer); | ||
68 | |||
69 | GNUNET_CONTAINER_DLL_insert_sorted(struct GNUNET_MESSENGER_ListTunnel, compare_list_tunnels, NULL, tunnels->head, | ||
70 | tunnels->tail, element); | ||
71 | } | ||
72 | |||
73 | struct GNUNET_MESSENGER_ListTunnel* | ||
74 | find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer, size_t *index) | ||
75 | { | ||
76 | struct GNUNET_MESSENGER_ListTunnel *element; | ||
77 | struct GNUNET_PeerIdentity pid; | ||
78 | |||
79 | if (index) | ||
80 | *index = 0; | ||
81 | |||
82 | for (element = tunnels->head; element; element = element->next) | ||
83 | { | ||
84 | GNUNET_PEER_resolve (element->peer, &pid); | ||
85 | |||
86 | if (0 == GNUNET_memcmp(&pid, peer)) | ||
87 | return element; | ||
88 | |||
89 | if (index) | ||
90 | (*index) = (*index) + 1; | ||
91 | } | ||
92 | |||
93 | return NULL; | ||
94 | } | ||
95 | |||
96 | int | ||
97 | contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer) | ||
98 | { | ||
99 | return find_list_tunnels (tunnels, peer, NULL) != NULL ? GNUNET_YES : GNUNET_NO; | ||
100 | } | ||
101 | |||
102 | struct GNUNET_MESSENGER_ListTunnel* | ||
103 | remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element) | ||
104 | { | ||
105 | struct GNUNET_MESSENGER_ListTunnel *next = element->next; | ||
106 | |||
107 | GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element); | ||
108 | GNUNET_PEER_change_rc (element->peer, -1); | ||
109 | GNUNET_free(element); | ||
110 | |||
111 | return next; | ||
112 | } | ||
diff --git a/src/messenger/messenger_api_list_tunnels.h b/src/messenger/messenger_api_list_tunnels.h new file mode 100644 index 000000000..0240fceb8 --- /dev/null +++ b/src/messenger/messenger_api_list_tunnels.h | |||
@@ -0,0 +1,112 @@ | |||
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/messenger_api_list_tunnels.h | ||
23 | * @brief messenger api: client and service implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_MESSENGER_API_LIST_TUNNELS_H | ||
27 | #define GNUNET_MESSENGER_API_LIST_TUNNELS_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_peer_lib.h" | ||
31 | #include "gnunet_container_lib.h" | ||
32 | |||
33 | struct GNUNET_MESSENGER_ListTunnel | ||
34 | { | ||
35 | struct GNUNET_MESSENGER_ListTunnel *prev; | ||
36 | struct GNUNET_MESSENGER_ListTunnel *next; | ||
37 | |||
38 | GNUNET_PEER_Id peer; | ||
39 | }; | ||
40 | |||
41 | struct GNUNET_MESSENGER_ListTunnels | ||
42 | { | ||
43 | struct GNUNET_MESSENGER_ListTunnel *head; | ||
44 | struct GNUNET_MESSENGER_ListTunnel *tail; | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * Initializes list of tunnels peer identities as empty list. | ||
49 | * | ||
50 | * @param tunnels List of peer identities | ||
51 | */ | ||
52 | void | ||
53 | init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels); | ||
54 | |||
55 | /** | ||
56 | * Clears the list of tunnels peer identities. | ||
57 | * | ||
58 | * @param tunnels List of peer identities | ||
59 | */ | ||
60 | void | ||
61 | clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels); | ||
62 | |||
63 | /** | ||
64 | * Adds a specific <i>peer</i> from a tunnel to the end of the list. | ||
65 | * | ||
66 | * @param tunnels List of peer identities | ||
67 | * @param peer Peer identity of tunnel | ||
68 | */ | ||
69 | void | ||
70 | add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer); | ||
71 | |||
72 | /** | ||
73 | * Searches linearly through the list of tunnels peer identities for matching a | ||
74 | * specific <i>peer</i> identity and returns the matching element of the list. | ||
75 | * | ||
76 | * If no matching element is found, NULL gets returned. | ||
77 | * | ||
78 | * If <i>index</i> is not NULL, <i>index</i> will be overriden with the numeric index of | ||
79 | * the found element in the list. If no matching element is found, <i>index</i> will | ||
80 | * contain the total amount of elements in the list. | ||
81 | * | ||
82 | * @param tunnels List of peer identities | ||
83 | * @param peer Peer identity of tunnel | ||
84 | * @param[out] index Index of found element (optional) | ||
85 | * @return Element in the list with matching peer identity | ||
86 | */ | ||
87 | struct GNUNET_MESSENGER_ListTunnel* | ||
88 | find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer, size_t *index); | ||
89 | |||
90 | /** | ||
91 | * Tests linearly if the list of tunnels peer identities contains a specific | ||
92 | * <i>peer</i> identity and returns GNUNET_YES on success, otherwise GNUNET_NO. | ||
93 | * | ||
94 | * @param tunnels List of peer identities | ||
95 | * @param peer Peer identity of tunnel | ||
96 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
97 | */ | ||
98 | int | ||
99 | contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer); | ||
100 | |||
101 | /** | ||
102 | * Removes a specific <i>element</i> from the list of tunnels peer identities and returns | ||
103 | * the next element in the list. | ||
104 | * | ||
105 | * @param tunnels List of peer identities | ||
106 | * @param element Element of the list | ||
107 | * @return Next element in the list | ||
108 | */ | ||
109 | struct GNUNET_MESSENGER_ListTunnel* | ||
110 | remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element); | ||
111 | |||
112 | #endif //GNUNET_MESSENGER_API_LIST_TUNNELS_H | ||
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c new file mode 100644 index 000000000..fdab60eef --- /dev/null +++ b/src/messenger/messenger_api_message.c | |||
@@ -0,0 +1,602 @@ | |||
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/messenger_api_message.c | ||
23 | * @brief messenger api: client and service implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "messenger_api_message.h" | ||
27 | |||
28 | struct GNUNET_MESSENGER_MessageSignature | ||
29 | { | ||
30 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
31 | struct GNUNET_HashCode hash; | ||
32 | }; | ||
33 | |||
34 | struct GNUNET_MESSENGER_ShortMessage | ||
35 | { | ||
36 | enum GNUNET_MESSENGER_MessageKind kind; | ||
37 | struct GNUNET_MESSENGER_MessageBody body; | ||
38 | }; | ||
39 | |||
40 | struct GNUNET_MESSENGER_Message* | ||
41 | create_message (enum GNUNET_MESSENGER_MessageKind kind) | ||
42 | { | ||
43 | struct GNUNET_MESSENGER_Message *message = GNUNET_new(struct GNUNET_MESSENGER_Message); | ||
44 | |||
45 | message->header.kind = kind; | ||
46 | |||
47 | switch (message->header.kind) | ||
48 | { | ||
49 | case GNUNET_MESSENGER_KIND_NAME: | ||
50 | message->body.name.name = NULL; | ||
51 | break; | ||
52 | case GNUNET_MESSENGER_KIND_TEXT: | ||
53 | message->body.text.text = NULL; | ||
54 | break; | ||
55 | case GNUNET_MESSENGER_KIND_FILE: | ||
56 | message->body.file.uri = NULL; | ||
57 | break; | ||
58 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
59 | message->body.private.length = 0; | ||
60 | message->body.private.data = NULL; | ||
61 | break; | ||
62 | default: | ||
63 | break; | ||
64 | } | ||
65 | |||
66 | return message; | ||
67 | } | ||
68 | |||
69 | struct GNUNET_MESSENGER_Message* | ||
70 | copy_message (const struct GNUNET_MESSENGER_Message *message) | ||
71 | { | ||
72 | struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message); | ||
73 | |||
74 | GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message)); | ||
75 | |||
76 | switch (message->header.kind) | ||
77 | { | ||
78 | case GNUNET_MESSENGER_KIND_NAME: | ||
79 | copy->body.name.name = GNUNET_strdup(message->body.name.name); | ||
80 | break; | ||
81 | case GNUNET_MESSENGER_KIND_TEXT: | ||
82 | copy->body.text.text = GNUNET_strdup(message->body.text.text); | ||
83 | break; | ||
84 | case GNUNET_MESSENGER_KIND_FILE: | ||
85 | copy->body.file.uri = GNUNET_strdup(message->body.file.uri); | ||
86 | break; | ||
87 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
88 | copy->body.private.data = copy->body.private.length ? GNUNET_malloc(copy->body.private.length) : NULL; | ||
89 | |||
90 | if (copy->body.private.data) | ||
91 | { | ||
92 | GNUNET_memcpy(copy->body.private.data, message->body.private.data, copy->body.private.length); | ||
93 | } | ||
94 | |||
95 | break; | ||
96 | default: | ||
97 | break; | ||
98 | } | ||
99 | |||
100 | return copy; | ||
101 | } | ||
102 | |||
103 | static void | ||
104 | destroy_message_body (enum GNUNET_MESSENGER_MessageKind kind, struct GNUNET_MESSENGER_MessageBody *body) | ||
105 | { | ||
106 | switch (kind) | ||
107 | { | ||
108 | case GNUNET_MESSENGER_KIND_NAME: | ||
109 | GNUNET_free(body->name.name); | ||
110 | break; | ||
111 | case GNUNET_MESSENGER_KIND_TEXT: | ||
112 | GNUNET_free(body->text.text); | ||
113 | break; | ||
114 | case GNUNET_MESSENGER_KIND_FILE: | ||
115 | GNUNET_free(body->file.uri); | ||
116 | break; | ||
117 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
118 | GNUNET_free(body->private.data); | ||
119 | break; | ||
120 | default: | ||
121 | break; | ||
122 | } | ||
123 | } | ||
124 | |||
125 | void | ||
126 | destroy_message (struct GNUNET_MESSENGER_Message *message) | ||
127 | { | ||
128 | destroy_message_body (message->header.kind, &(message->body)); | ||
129 | |||
130 | GNUNET_free(message); | ||
131 | } | ||
132 | |||
133 | static void | ||
134 | fold_short_message (const struct GNUNET_MESSENGER_Message *message, struct GNUNET_MESSENGER_ShortMessage *shortened) | ||
135 | { | ||
136 | shortened->kind = message->header.kind; | ||
137 | |||
138 | GNUNET_memcpy(&(shortened->body), &(message->body), sizeof(struct GNUNET_MESSENGER_MessageBody)); | ||
139 | } | ||
140 | |||
141 | static void | ||
142 | unfold_short_message (struct GNUNET_MESSENGER_ShortMessage *shortened, struct GNUNET_MESSENGER_Message *message) | ||
143 | { | ||
144 | destroy_message_body (message->header.kind, &(message->body)); | ||
145 | |||
146 | message->header.kind = shortened->kind; | ||
147 | |||
148 | GNUNET_memcpy(&(message->body), &(shortened->body), sizeof(struct GNUNET_MESSENGER_MessageBody)); | ||
149 | } | ||
150 | |||
151 | #define member_size(type, member) sizeof(((type*) NULL)->member) | ||
152 | |||
153 | static uint16_t | ||
154 | get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind) | ||
155 | { | ||
156 | uint16_t length = 0; | ||
157 | |||
158 | switch (kind) | ||
159 | { | ||
160 | case GNUNET_MESSENGER_KIND_INFO: | ||
161 | length += member_size(struct GNUNET_MESSENGER_Message, body.info.host_key); | ||
162 | length += member_size(struct GNUNET_MESSENGER_Message, body.info.unique_id); | ||
163 | break; | ||
164 | case GNUNET_MESSENGER_KIND_JOIN: | ||
165 | length += member_size(struct GNUNET_MESSENGER_Message, body.join.key); | ||
166 | break; | ||
167 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
168 | break; | ||
169 | case GNUNET_MESSENGER_KIND_NAME: | ||
170 | break; | ||
171 | case GNUNET_MESSENGER_KIND_KEY: | ||
172 | length += member_size(struct GNUNET_MESSENGER_Message, body.key.key); | ||
173 | break; | ||
174 | case GNUNET_MESSENGER_KIND_PEER: | ||
175 | length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer); | ||
176 | break; | ||
177 | case GNUNET_MESSENGER_KIND_ID: | ||
178 | length += member_size(struct GNUNET_MESSENGER_Message, body.id.id); | ||
179 | break; | ||
180 | case GNUNET_MESSENGER_KIND_MISS: | ||
181 | length += member_size(struct GNUNET_MESSENGER_Message, body.miss.peer); | ||
182 | break; | ||
183 | case GNUNET_MESSENGER_KIND_MERGE: | ||
184 | length += member_size(struct GNUNET_MESSENGER_Message, body.merge.previous); | ||
185 | break; | ||
186 | case GNUNET_MESSENGER_KIND_REQUEST: | ||
187 | length += member_size(struct GNUNET_MESSENGER_Message, body.request.hash); | ||
188 | break; | ||
189 | case GNUNET_MESSENGER_KIND_INVITE: | ||
190 | length += member_size(struct GNUNET_MESSENGER_Message, body.invite.door); | ||
191 | length += member_size(struct GNUNET_MESSENGER_Message, body.invite.key); | ||
192 | break; | ||
193 | case GNUNET_MESSENGER_KIND_TEXT: | ||
194 | break; | ||
195 | case GNUNET_MESSENGER_KIND_FILE: | ||
196 | length += member_size(struct GNUNET_MESSENGER_Message, body.file.key); | ||
197 | length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash); | ||
198 | length += NAME_MAX; | ||
199 | break; | ||
200 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
201 | length += member_size(struct GNUNET_MESSENGER_Message, body.private.key); | ||
202 | break; | ||
203 | default: | ||
204 | break; | ||
205 | } | ||
206 | |||
207 | return length; | ||
208 | } | ||
209 | |||
210 | uint16_t | ||
211 | get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind) | ||
212 | { | ||
213 | uint16_t length = 0; | ||
214 | |||
215 | length += member_size(struct GNUNET_MESSENGER_Message, header.signature); | ||
216 | length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp); | ||
217 | length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id); | ||
218 | length += member_size(struct GNUNET_MESSENGER_Message, header.previous); | ||
219 | length += member_size(struct GNUNET_MESSENGER_Message, header.kind); | ||
220 | |||
221 | return length + get_message_body_kind_size (kind); | ||
222 | } | ||
223 | |||
224 | static uint16_t | ||
225 | get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body) | ||
226 | { | ||
227 | uint16_t length = 0; | ||
228 | |||
229 | switch (kind) | ||
230 | { | ||
231 | case GNUNET_MESSENGER_KIND_NAME: | ||
232 | length += (body->name.name? strlen (body->name.name) : 0); | ||
233 | break; | ||
234 | case GNUNET_MESSENGER_KIND_TEXT: | ||
235 | length += strlen (body->text.text); | ||
236 | break; | ||
237 | case GNUNET_MESSENGER_KIND_FILE: | ||
238 | length += strlen (body->file.uri); | ||
239 | break; | ||
240 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
241 | length += body->private.length; | ||
242 | break; | ||
243 | default: | ||
244 | break; | ||
245 | } | ||
246 | |||
247 | return length; | ||
248 | } | ||
249 | |||
250 | uint16_t | ||
251 | get_message_size (const struct GNUNET_MESSENGER_Message *message) | ||
252 | { | ||
253 | return get_message_kind_size (message->header.kind) + get_message_body_size (message->header.kind, &(message->body)); | ||
254 | } | ||
255 | |||
256 | static uint16_t | ||
257 | get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message) | ||
258 | { | ||
259 | if (message) | ||
260 | return sizeof(message->kind) + get_message_body_kind_size (message->kind) | ||
261 | + get_message_body_size (message->kind, &(message->body)); | ||
262 | else | ||
263 | return sizeof(message->kind); | ||
264 | } | ||
265 | |||
266 | #define min(x, y) (x < y? x : y) | ||
267 | |||
268 | #define encode_step_ext(dst, offset, src, size) do { \ | ||
269 | GNUNET_memcpy(dst + offset, src, size); \ | ||
270 | offset += size; \ | ||
271 | } while (0) | ||
272 | |||
273 | #define encode_step(dst, offset, src) do { \ | ||
274 | encode_step_ext(dst, offset, src, sizeof(*src)); \ | ||
275 | } while(0) | ||
276 | |||
277 | static void | ||
278 | encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body, | ||
279 | uint16_t length, char *buffer, uint16_t offset) | ||
280 | { | ||
281 | switch (kind) | ||
282 | { | ||
283 | case GNUNET_MESSENGER_KIND_INFO: | ||
284 | encode_step(buffer, offset, &(body->info.host_key)); | ||
285 | encode_step(buffer, offset, &(body->info.unique_id)); | ||
286 | break; | ||
287 | case GNUNET_MESSENGER_KIND_JOIN: | ||
288 | encode_step(buffer, offset, &(body->join.key)); | ||
289 | break; | ||
290 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
291 | break; | ||
292 | case GNUNET_MESSENGER_KIND_NAME: | ||
293 | if (body->name.name) | ||
294 | encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name))); | ||
295 | break; | ||
296 | case GNUNET_MESSENGER_KIND_KEY: | ||
297 | encode_step(buffer, offset, &(body->key.key)); | ||
298 | break; | ||
299 | case GNUNET_MESSENGER_KIND_PEER: | ||
300 | encode_step(buffer, offset, &(body->peer.peer)); | ||
301 | break; | ||
302 | case GNUNET_MESSENGER_KIND_ID: | ||
303 | encode_step(buffer, offset, &(body->id.id)); | ||
304 | break; | ||
305 | case GNUNET_MESSENGER_KIND_MISS: | ||
306 | encode_step(buffer, offset, &(body->miss.peer)); | ||
307 | break; | ||
308 | case GNUNET_MESSENGER_KIND_MERGE: | ||
309 | encode_step(buffer, offset, &(body->merge.previous)); | ||
310 | break; | ||
311 | case GNUNET_MESSENGER_KIND_REQUEST: | ||
312 | encode_step(buffer, offset, &(body->request.hash)); | ||
313 | break; | ||
314 | case GNUNET_MESSENGER_KIND_INVITE: | ||
315 | encode_step(buffer, offset, &(body->invite.door)); | ||
316 | encode_step(buffer, offset, &(body->invite.key)); | ||
317 | break; | ||
318 | case GNUNET_MESSENGER_KIND_TEXT: | ||
319 | encode_step_ext(buffer, offset, body->text.text, min(length - offset, strlen(body->text.text))); | ||
320 | break; | ||
321 | case GNUNET_MESSENGER_KIND_FILE: | ||
322 | encode_step(buffer, offset, &(body->file.key)); | ||
323 | encode_step(buffer, offset, &(body->file.hash)); | ||
324 | encode_step_ext(buffer, offset, body->file.name, NAME_MAX); | ||
325 | encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri))); | ||
326 | break; | ||
327 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
328 | encode_step(buffer, offset, &(body->private.key)); | ||
329 | encode_step_ext(buffer, offset, body->private.data, min(length - offset, body->private.length)); | ||
330 | break; | ||
331 | default: | ||
332 | break; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | void | ||
337 | encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer) | ||
338 | { | ||
339 | uint16_t offset = 0; | ||
340 | |||
341 | encode_step(buffer, offset, &(message->header.signature)); | ||
342 | encode_step(buffer, offset, &(message->header.timestamp)); | ||
343 | encode_step(buffer, offset, &(message->header.sender_id)); | ||
344 | encode_step(buffer, offset, &(message->header.previous)); | ||
345 | encode_step(buffer, offset, &(message->header.kind)); | ||
346 | |||
347 | encode_message_body (message->header.kind, &(message->body), length, buffer, offset); | ||
348 | } | ||
349 | |||
350 | static void | ||
351 | encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, char *buffer) | ||
352 | { | ||
353 | uint16_t offset = 0; | ||
354 | |||
355 | encode_step(buffer, offset, &(message->kind)); | ||
356 | |||
357 | encode_message_body (message->kind, &(message->body), length, buffer, offset); | ||
358 | } | ||
359 | |||
360 | #define decode_step_ext(src, offset, dst, size) do { \ | ||
361 | GNUNET_memcpy(dst, src + offset, size); \ | ||
362 | offset += size; \ | ||
363 | } while (0) | ||
364 | |||
365 | #define decode_step(src, offset, dst) do { \ | ||
366 | decode_step_ext(src, offset, dst, sizeof(*dst)); \ | ||
367 | } while (0) | ||
368 | |||
369 | #define decode_step_malloc(src, offset, dst, size, zero) do { \ | ||
370 | dst = GNUNET_malloc(size + zero); \ | ||
371 | if (zero) dst[size] = 0; \ | ||
372 | decode_step_ext(src, offset, dst, size); \ | ||
373 | } while (0) | ||
374 | |||
375 | static void | ||
376 | decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESSENGER_MessageBody *body, | ||
377 | uint16_t length, const char *buffer, uint16_t offset) | ||
378 | { | ||
379 | switch (*kind) | ||
380 | { | ||
381 | case GNUNET_MESSENGER_KIND_INFO: | ||
382 | decode_step(buffer, offset, &(body->info.host_key)); | ||
383 | decode_step(buffer, offset, &(body->info.unique_id)); | ||
384 | break; | ||
385 | case GNUNET_MESSENGER_KIND_JOIN: | ||
386 | decode_step(buffer, offset, &(body->join.key)); | ||
387 | break; | ||
388 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
389 | break; | ||
390 | case GNUNET_MESSENGER_KIND_NAME: | ||
391 | if (length - offset > 0) | ||
392 | decode_step_malloc(buffer, offset, body->name.name, length - offset, 1); | ||
393 | else | ||
394 | body->name.name = NULL; | ||
395 | break; | ||
396 | case GNUNET_MESSENGER_KIND_KEY: | ||
397 | decode_step(buffer, offset, &(body->key.key)); | ||
398 | break; | ||
399 | case GNUNET_MESSENGER_KIND_PEER: | ||
400 | decode_step(buffer, offset, &(body->peer.peer)); | ||
401 | break; | ||
402 | case GNUNET_MESSENGER_KIND_ID: | ||
403 | decode_step(buffer, offset, &(body->id.id)); | ||
404 | break; | ||
405 | case GNUNET_MESSENGER_KIND_MISS: | ||
406 | decode_step(buffer, offset, &(body->miss.peer)); | ||
407 | break; | ||
408 | case GNUNET_MESSENGER_KIND_MERGE: | ||
409 | decode_step(buffer, offset, &(body->merge.previous)); | ||
410 | break; | ||
411 | case GNUNET_MESSENGER_KIND_REQUEST: | ||
412 | decode_step(buffer, offset, &(body->request.hash)); | ||
413 | break; | ||
414 | case GNUNET_MESSENGER_KIND_INVITE: | ||
415 | decode_step(buffer, offset, &(body->invite.door)); | ||
416 | decode_step(buffer, offset, &(body->invite.key)); | ||
417 | break; | ||
418 | case GNUNET_MESSENGER_KIND_TEXT: | ||
419 | decode_step_malloc(buffer, offset, body->text.text, length - offset, 1); | ||
420 | break; | ||
421 | case GNUNET_MESSENGER_KIND_FILE: | ||
422 | decode_step(buffer, offset, &(body->file.key)); | ||
423 | decode_step(buffer, offset, &(body->file.hash)); | ||
424 | decode_step_ext(buffer, offset, body->file.name, NAME_MAX); | ||
425 | decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1); | ||
426 | break; | ||
427 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
428 | decode_step(buffer, offset, &(body->private.key)); | ||
429 | |||
430 | body->private.length = (length - offset); | ||
431 | decode_step_malloc(buffer, offset, body->private.data, length - offset, 0); | ||
432 | break; | ||
433 | default: | ||
434 | *kind = GNUNET_MESSENGER_KIND_UNKNOWN; | ||
435 | break; | ||
436 | } | ||
437 | } | ||
438 | |||
439 | int | ||
440 | decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer) | ||
441 | { | ||
442 | uint16_t offset = 0; | ||
443 | |||
444 | if (length < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN)) | ||
445 | return GNUNET_NO; | ||
446 | |||
447 | decode_step(buffer, offset, &(message->header.signature)); | ||
448 | decode_step(buffer, offset, &(message->header.timestamp)); | ||
449 | decode_step(buffer, offset, &(message->header.sender_id)); | ||
450 | decode_step(buffer, offset, &(message->header.previous)); | ||
451 | decode_step(buffer, offset, &(message->header.kind)); | ||
452 | |||
453 | if (length < get_message_kind_size (message->header.kind)) | ||
454 | return GNUNET_NO; | ||
455 | |||
456 | decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset); | ||
457 | |||
458 | return GNUNET_YES; | ||
459 | } | ||
460 | |||
461 | static int | ||
462 | decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, const char *buffer) | ||
463 | { | ||
464 | uint16_t offset = 0; | ||
465 | |||
466 | if (length < get_short_message_size (NULL)) | ||
467 | return GNUNET_NO; | ||
468 | |||
469 | decode_step(buffer, offset, &(message->kind)); | ||
470 | |||
471 | if (length < get_short_message_size (message)) | ||
472 | return GNUNET_NO; | ||
473 | |||
474 | decode_message_body (&(message->kind), &(message->body), length, buffer, offset); | ||
475 | |||
476 | return GNUNET_YES; | ||
477 | } | ||
478 | |||
479 | void | ||
480 | hash_message (uint16_t length, const char *buffer, struct GNUNET_HashCode *hash) | ||
481 | { | ||
482 | GNUNET_CRYPTO_hash (buffer + sizeof(struct GNUNET_CRYPTO_EcdsaSignature), | ||
483 | length - sizeof(struct GNUNET_CRYPTO_EcdsaSignature), hash); | ||
484 | } | ||
485 | |||
486 | void | ||
487 | sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, | ||
488 | const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego) | ||
489 | { | ||
490 | struct GNUNET_MESSENGER_MessageSignature signature; | ||
491 | |||
492 | signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); | ||
493 | signature.purpose.size = htonl (sizeof(signature)); | ||
494 | |||
495 | GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode)); | ||
496 | |||
497 | GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature)); | ||
498 | GNUNET_memcpy(buffer, &(message->header.signature), sizeof(struct GNUNET_CRYPTO_EcdsaSignature)); | ||
499 | } | ||
500 | |||
501 | int | ||
502 | verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash, | ||
503 | const struct GNUNET_IDENTITY_PublicKey *key) | ||
504 | { | ||
505 | struct GNUNET_MESSENGER_MessageSignature signature; | ||
506 | |||
507 | signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE); | ||
508 | signature.purpose.size = htonl (sizeof(signature)); | ||
509 | |||
510 | GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode)); | ||
511 | |||
512 | return GNUNET_IDENTITY_signature_verify(GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature, | ||
513 | &(message->header.signature), key); | ||
514 | } | ||
515 | |||
516 | int | ||
517 | encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key) | ||
518 | { | ||
519 | struct GNUNET_MESSENGER_ShortMessage shortened; | ||
520 | |||
521 | fold_short_message (message, &shortened); | ||
522 | |||
523 | const uint16_t length = get_short_message_size (&shortened); | ||
524 | |||
525 | message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE; | ||
526 | message->body.private.data = GNUNET_malloc(length); | ||
527 | |||
528 | encode_short_message (&shortened, length, message->body.private.data); | ||
529 | |||
530 | if (GNUNET_IDENTITY_encrypt (message->body.private.data, length, key, &(message->body.private.key), | ||
531 | message->body.private.data) | ||
532 | == length) | ||
533 | { | ||
534 | destroy_message_body (shortened.kind, &(shortened.body)); | ||
535 | return GNUNET_YES; | ||
536 | } | ||
537 | else | ||
538 | { | ||
539 | unfold_short_message (&shortened, message); | ||
540 | return GNUNET_NO; | ||
541 | } | ||
542 | } | ||
543 | |||
544 | int | ||
545 | decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key) | ||
546 | { | ||
547 | if (message->body.private.length != GNUNET_IDENTITY_decrypt (message->body.private.data, | ||
548 | message->body.private.length, key, | ||
549 | &(message->body.private.key), | ||
550 | message->body.private.data)) | ||
551 | return GNUNET_NO; | ||
552 | |||
553 | struct GNUNET_MESSENGER_ShortMessage shortened; | ||
554 | |||
555 | if (GNUNET_YES != decode_short_message (&shortened, message->body.private.length, message->body.private.data)) | ||
556 | return GNUNET_NO; | ||
557 | |||
558 | unfold_short_message (&shortened, message); | ||
559 | return GNUNET_YES; | ||
560 | } | ||
561 | |||
562 | struct GNUNET_MQ_Envelope* | ||
563 | pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, | ||
564 | const struct GNUNET_MESSENGER_Ego *ego, int mode) | ||
565 | { | ||
566 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message: %u\n", message->header.kind); | ||
567 | |||
568 | struct GNUNET_MessageHeader *header; | ||
569 | |||
570 | uint16_t length = get_message_size (message); | ||
571 | |||
572 | struct GNUNET_MQ_Envelope *env; | ||
573 | char *buffer; | ||
574 | |||
575 | if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode) | ||
576 | { | ||
577 | env = GNUNET_MQ_msg_extra(header, length, GNUNET_MESSAGE_TYPE_CADET_CLI); | ||
578 | |||
579 | buffer = (char*) &(header[1]); | ||
580 | } | ||
581 | else | ||
582 | { | ||
583 | env = NULL; | ||
584 | |||
585 | buffer = GNUNET_malloc(length); | ||
586 | } | ||
587 | |||
588 | encode_message (message, length, buffer); | ||
589 | |||
590 | if (hash) | ||
591 | { | ||
592 | hash_message (length, buffer, hash); | ||
593 | |||
594 | if (ego) | ||
595 | sign_message (message, length, buffer, hash, ego); | ||
596 | } | ||
597 | |||
598 | if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE != mode) | ||
599 | GNUNET_free(buffer); | ||
600 | |||
601 | return env; | ||
602 | } | ||
diff --git a/src/messenger/messenger_api_message.h b/src/messenger/messenger_api_message.h new file mode 100644 index 000000000..0f0a97e9c --- /dev/null +++ b/src/messenger/messenger_api_message.h | |||
@@ -0,0 +1,190 @@ | |||
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/messenger_api_message.h | ||
23 | * @brief messenger api: client and service implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_MESSENGER_API_MESSAGE_H | ||
27 | #define GNUNET_MESSENGER_API_MESSAGE_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_crypto_lib.h" | ||
31 | #include "gnunet_identity_service.h" | ||
32 | #include "gnunet_mq_lib.h" | ||
33 | #include "gnunet_signatures.h" | ||
34 | |||
35 | #include "gnunet_messenger_service.h" | ||
36 | |||
37 | #include "messenger_api_ego.h" | ||
38 | |||
39 | /** | ||
40 | * Creates and allocates a new message with a specific <i>kind</i>. | ||
41 | * | ||
42 | * @param kind Kind of message | ||
43 | * @return New message | ||
44 | */ | ||
45 | struct GNUNET_MESSENGER_Message* | ||
46 | create_message (enum GNUNET_MESSENGER_MessageKind kind); | ||
47 | |||
48 | /** | ||
49 | * Creates and allocates a copy of a given <i>message</i>. | ||
50 | * | ||
51 | * @param message Message | ||
52 | * @return New message | ||
53 | */ | ||
54 | struct GNUNET_MESSENGER_Message* | ||
55 | copy_message (const struct GNUNET_MESSENGER_Message *message); | ||
56 | |||
57 | /** | ||
58 | * Destroys a message and frees its memory fully. | ||
59 | * | ||
60 | * @param message Message | ||
61 | */ | ||
62 | void | ||
63 | destroy_message (struct GNUNET_MESSENGER_Message *message); | ||
64 | |||
65 | /** | ||
66 | * Returns the minimal size in bytes to encode a message of a specific <i>kind</i>. | ||
67 | * | ||
68 | * @param kind Kind of message | ||
69 | * @return Minimal size to encode | ||
70 | */ | ||
71 | uint16_t | ||
72 | get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind); | ||
73 | |||
74 | /** | ||
75 | * Returns the exact size in bytes to encode a given <i>message</i>. | ||
76 | * | ||
77 | * @param message Message | ||
78 | * @return Size to encode | ||
79 | */ | ||
80 | uint16_t | ||
81 | get_message_size (const struct GNUNET_MESSENGER_Message *message); | ||
82 | |||
83 | /** | ||
84 | * Encodes a given <i>message</i> into a <i>buffer</i> of a maximal <i>length</i> in bytes. | ||
85 | * | ||
86 | * @param message Message | ||
87 | * @param length Maximal length to encode | ||
88 | * @param[out] buffer Buffer | ||
89 | */ | ||
90 | void | ||
91 | encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer); | ||
92 | |||
93 | /** | ||
94 | * Decodes a <i>message</i> from a given <i>buffer</i> of a maximal <i>length</i> in bytes. | ||
95 | * | ||
96 | * If the buffer is too small for a message of its decoded kind the function fails with | ||
97 | * resulting GNUNET_NO after decoding only the messages header. | ||
98 | * | ||
99 | * On success the function returns GNUNET_YES. | ||
100 | * | ||
101 | * @param[out] message Message | ||
102 | * @param length Maximal length to decode | ||
103 | * @param buffer Buffer | ||
104 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
105 | */ | ||
106 | int | ||
107 | decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer); | ||
108 | |||
109 | /** | ||
110 | * Calculates a <i>hash</i> of a given <i>buffer</i> of a <i>length</i> in bytes. | ||
111 | * | ||
112 | * @param length Length of buffer | ||
113 | * @param buffer Buffer | ||
114 | * @param[out] hash Hash | ||
115 | */ | ||
116 | void | ||
117 | hash_message (uint16_t length, const char *buffer, struct GNUNET_HashCode *hash); | ||
118 | |||
119 | /** | ||
120 | * Signs the <i>hash</i> of a <i>message</i> with a given <i>ego</i> and writes the signature | ||
121 | * into the <i>buffer</i> as well. | ||
122 | * | ||
123 | * @param[out] message Message | ||
124 | * @param length Length of buffer | ||
125 | * @param[out] buffer Buffer | ||
126 | * @param hash Hash of message | ||
127 | * @param ego EGO | ||
128 | */ | ||
129 | void | ||
130 | sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, | ||
131 | const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego); | ||
132 | |||
133 | /** | ||
134 | * Verifies the signature of a given <i>message</i> and its <i>hash</i> with a specific | ||
135 | * public key. The function returns GNUNET_OK if the signature was valid, otherwise | ||
136 | * GNUNET_SYSERR. | ||
137 | * | ||
138 | * @param message Message | ||
139 | * @param hash Hash of message | ||
140 | * @param key Public key of EGO | ||
141 | * @return GNUNET_OK on success, otherwise GNUNET_SYSERR | ||
142 | */ | ||
143 | int | ||
144 | verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash, | ||
145 | const struct GNUNET_IDENTITY_PublicKey *key); | ||
146 | |||
147 | /** | ||
148 | * Encrypts a <i>message</i> using a given public <i>key</i> and replaces its body | ||
149 | * and kind with the now private encrypted <i>message</i>. The function returns | ||
150 | * GNUNET_YES if the operation succeeded, otherwise GNUNET_NO. | ||
151 | * | ||
152 | * @param message Message | ||
153 | * @param key Public key of EGO | ||
154 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
155 | */ | ||
156 | int | ||
157 | encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key); | ||
158 | |||
159 | /** | ||
160 | * Decrypts a private <i>message</i> using a given private <i>key</i> and replaces its body | ||
161 | * and kind with the inner encrypted message. The function returns GNUNET_YES if the | ||
162 | * operation succeeded, otherwise GNUNET_NO. | ||
163 | * | ||
164 | * @param message Message | ||
165 | * @param key Private key of EGO | ||
166 | * @return GNUNET_YES on success, otherwise GNUNET_NO | ||
167 | */ | ||
168 | int | ||
169 | decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key); | ||
170 | |||
171 | #define GNUNET_MESSENGER_PACK_MODE_ENVELOPE 0x1 | ||
172 | #define GNUNET_MESSENGER_PACK_MODE_UNKNOWN 0x0 | ||
173 | |||
174 | /** | ||
175 | * Encodes the <i>message</i> to pack it into a newly allocated envelope if <i>mode</i> | ||
176 | * is equal to GNUNET_MESSENGER_PACK_MODE_ENVELOPE. Independent of the mode the message | ||
177 | * will be hashed if <i>hash</i> is not NULL and it will be signed if the <i>ego</i> is | ||
178 | * not NULL. | ||
179 | * | ||
180 | * @param[out] message Message | ||
181 | * @param[out] hash Hash of message | ||
182 | * @param ego EGO to sign | ||
183 | * @param mode Mode of packing | ||
184 | * @return Envelope or NULL | ||
185 | */ | ||
186 | struct GNUNET_MQ_Envelope* | ||
187 | pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, | ||
188 | const struct GNUNET_MESSENGER_Ego *ego, int mode); | ||
189 | |||
190 | #endif //GNUNET_MESSENGER_API_MESSAGE_H | ||
diff --git a/src/messenger/messenger_api_room.c b/src/messenger/messenger_api_room.c new file mode 100644 index 000000000..5fedf1a78 --- /dev/null +++ b/src/messenger/messenger_api_room.c | |||
@@ -0,0 +1,189 @@ | |||
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/messenger_api_room.c | ||
23 | * @brief messenger api: client implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "messenger_api_room.h" | ||
27 | |||
28 | #include "messenger_api_handle.h" | ||
29 | |||
30 | struct GNUNET_MESSENGER_Room* | ||
31 | create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key) | ||
32 | { | ||
33 | struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room); | ||
34 | |||
35 | room->handle = handle; | ||
36 | GNUNET_memcpy(&(room->key), key, sizeof(*key)); | ||
37 | |||
38 | room->opened = GNUNET_NO; | ||
39 | room->contact_id = NULL; | ||
40 | |||
41 | room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO); | ||
42 | |||
43 | init_list_tunnels (&(room->entries)); | ||
44 | |||
45 | room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); | ||
46 | |||
47 | return room; | ||
48 | } | ||
49 | |||
50 | static int | ||
51 | iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value) | ||
52 | { | ||
53 | struct GNUNET_MESSENGER_Message *message = value; | ||
54 | |||
55 | destroy_message (message); | ||
56 | |||
57 | return GNUNET_YES; | ||
58 | } | ||
59 | |||
60 | void | ||
61 | destroy_room (struct GNUNET_MESSENGER_Room *room) | ||
62 | { | ||
63 | if (room->members) | ||
64 | GNUNET_CONTAINER_multishortmap_destroy (room->members); | ||
65 | |||
66 | clear_list_tunnels (&(room->entries)); | ||
67 | |||
68 | if (room->messages) | ||
69 | { | ||
70 | GNUNET_CONTAINER_multihashmap_iterate (room->messages, iterate_destroy_message, NULL); | ||
71 | |||
72 | GNUNET_CONTAINER_multihashmap_destroy (room->messages); | ||
73 | } | ||
74 | |||
75 | if (room->contact_id) | ||
76 | GNUNET_free(room->contact_id); | ||
77 | |||
78 | GNUNET_free(room); | ||
79 | } | ||
80 | |||
81 | const struct GNUNET_MESSENGER_Message* | ||
82 | get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash) | ||
83 | { | ||
84 | return GNUNET_CONTAINER_multihashmap_get (room->messages, hash); | ||
85 | } | ||
86 | |||
87 | static void | ||
88 | handle_join_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | ||
89 | const struct GNUNET_HashCode *hash) | ||
90 | { | ||
91 | struct GNUNET_MESSENGER_Contact *contact = get_handle_contact_by_pubkey (room->handle, &(message->body.join.key)); | ||
92 | |||
93 | if (contact) | ||
94 | GNUNET_CONTAINER_multishortmap_put (room->members, &(message->header.sender_id), contact, | ||
95 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | ||
96 | } | ||
97 | |||
98 | static void | ||
99 | handle_leave_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | ||
100 | const struct GNUNET_HashCode *hash) | ||
101 | { | ||
102 | GNUNET_CONTAINER_multishortmap_remove_all (room->members, &(message->header.sender_id)); | ||
103 | } | ||
104 | |||
105 | static void | ||
106 | handle_name_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | ||
107 | const struct GNUNET_HashCode *hash) | ||
108 | { | ||
109 | struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, | ||
110 | &(message->header.sender_id)); | ||
111 | |||
112 | if (contact) | ||
113 | set_contact_name (contact, message->body.name.name); | ||
114 | } | ||
115 | |||
116 | static void | ||
117 | handle_key_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | ||
118 | const struct GNUNET_HashCode *hash) | ||
119 | { | ||
120 | struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, | ||
121 | &(message->header.sender_id)); | ||
122 | |||
123 | if (contact) | ||
124 | swap_handle_contact_by_pubkey (room->handle, contact, &(message->body.key.key)); | ||
125 | } | ||
126 | |||
127 | static void | ||
128 | handle_id_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | ||
129 | const struct GNUNET_HashCode *hash) | ||
130 | { | ||
131 | struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, | ||
132 | &(message->header.sender_id)); | ||
133 | |||
134 | if ((contact) && (GNUNET_OK | ||
135 | == GNUNET_CONTAINER_multishortmap_put (room->members, &(message->body.id.id), contact, | ||
136 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))) | ||
137 | GNUNET_CONTAINER_multishortmap_remove (room->members, &(message->header.sender_id), contact); | ||
138 | } | ||
139 | |||
140 | static void | ||
141 | handle_miss_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | ||
142 | const struct GNUNET_HashCode *hash) | ||
143 | { | ||
144 | if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id))) | ||
145 | { | ||
146 | struct GNUNET_MESSENGER_ListTunnel *match = find_list_tunnels (&(room->entries), &(message->body.miss.peer), NULL); | ||
147 | |||
148 | if (match) | ||
149 | remove_from_list_tunnels (&(room->entries), match); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | void | ||
154 | handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | ||
155 | const struct GNUNET_HashCode *hash) | ||
156 | { | ||
157 | if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash)) | ||
158 | return; | ||
159 | |||
160 | switch (message->header.kind) | ||
161 | { | ||
162 | case GNUNET_MESSENGER_KIND_JOIN: | ||
163 | handle_join_message (room, message, hash); | ||
164 | break; | ||
165 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
166 | handle_leave_message (room, message, hash); | ||
167 | break; | ||
168 | case GNUNET_MESSENGER_KIND_NAME: | ||
169 | handle_name_message (room, message, hash); | ||
170 | break; | ||
171 | case GNUNET_MESSENGER_KIND_KEY: | ||
172 | handle_key_message (room, message, hash); | ||
173 | break; | ||
174 | case GNUNET_MESSENGER_KIND_ID: | ||
175 | handle_id_message (room, message, hash); | ||
176 | break; | ||
177 | case GNUNET_MESSENGER_KIND_MISS: | ||
178 | handle_miss_message (room, message, hash); | ||
179 | break; | ||
180 | default: | ||
181 | break; | ||
182 | } | ||
183 | |||
184 | struct GNUNET_MESSENGER_Message *clone = copy_message (message); | ||
185 | |||
186 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, clone, | ||
187 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
188 | destroy_message (clone); | ||
189 | } | ||
diff --git a/src/messenger/messenger_api_room.h b/src/messenger/messenger_api_room.h new file mode 100644 index 000000000..0038128d8 --- /dev/null +++ b/src/messenger/messenger_api_room.h | |||
@@ -0,0 +1,95 @@ | |||
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/messenger_api_room.h | ||
23 | * @brief messenger api: client implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #ifndef GNUNET_MESSENGER_API_ROOM_H | ||
27 | #define GNUNET_MESSENGER_API_ROOM_H | ||
28 | |||
29 | #include "platform.h" | ||
30 | #include "gnunet_container_lib.h" | ||
31 | #include "gnunet_crypto_lib.h" | ||
32 | |||
33 | #include "gnunet_messenger_service.h" | ||
34 | |||
35 | #include "messenger_api_list_tunnels.h" | ||
36 | #include "messenger_api_contact.h" | ||
37 | #include "messenger_api_message.h" | ||
38 | |||
39 | struct GNUNET_MESSENGER_Room | ||
40 | { | ||
41 | struct GNUNET_MESSENGER_Handle *handle; | ||
42 | struct GNUNET_HashCode key; | ||
43 | |||
44 | int opened; | ||
45 | |||
46 | struct GNUNET_ShortHashCode *contact_id; | ||
47 | |||
48 | struct GNUNET_CONTAINER_MultiShortmap *members; | ||
49 | struct GNUNET_MESSENGER_ListTunnels entries; | ||
50 | |||
51 | struct GNUNET_CONTAINER_MultiHashMap *messages; | ||
52 | }; | ||
53 | |||
54 | /** | ||
55 | * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i> for the client API. | ||
56 | * | ||
57 | * @param handle Handle | ||
58 | * @param key Key of room | ||
59 | * @return New room | ||
60 | */ | ||
61 | struct GNUNET_MESSENGER_Room* | ||
62 | create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key); | ||
63 | |||
64 | /** | ||
65 | * Destroys a room and frees its memory fully from the client API. | ||
66 | * | ||
67 | * @param room Room | ||
68 | */ | ||
69 | void | ||
70 | destroy_room (struct GNUNET_MESSENGER_Room *room); | ||
71 | |||
72 | /** | ||
73 | * Returns a message locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no matching | ||
74 | * message is found, NULL gets returned. | ||
75 | * | ||
76 | * @param room Room | ||
77 | * @param hash Hash of message | ||
78 | * @return Message or NULL | ||
79 | */ | ||
80 | const struct GNUNET_MESSENGER_Message* | ||
81 | get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash); | ||
82 | |||
83 | /** | ||
84 | * Handles a <i>message</i> with a given <i>hash</i> in a <i>room</i> for the client API to update | ||
85 | * members and its information. The function also stores the message in map locally for access afterwards. | ||
86 | * | ||
87 | * @param room Room | ||
88 | * @param message Message | ||
89 | * @param hash Hash of message | ||
90 | */ | ||
91 | void | ||
92 | handle_room_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | ||
93 | const struct GNUNET_HashCode *hash); | ||
94 | |||
95 | #endif //GNUNET_MESSENGER_API_ROOM_H | ||
diff --git a/src/messenger/test_messenger.c b/src/messenger/test_messenger.c new file mode 100644 index 000000000..b42dfe6d9 --- /dev/null +++ b/src/messenger/test_messenger.c | |||
@@ -0,0 +1,187 @@ | |||
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 | * @file messenger/test_messenger.c | ||
22 | * @author Tobias Frisch | ||
23 | * @brief Test for the messenger service using cadet API. | ||
24 | */ | ||
25 | #include <stdio.h> | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_testing_lib.h" | ||
29 | #include "gnunet_messenger_service.h" | ||
30 | |||
31 | /** | ||
32 | * How long until we really give up on a particular testcase portion? | ||
33 | */ | ||
34 | #define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, \ | ||
35 | 60) | ||
36 | |||
37 | /** | ||
38 | * How long until we give up on any particular operation (and retry)? | ||
39 | */ | ||
40 | #define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
41 | |||
42 | #define TESTER_NAME "tester" | ||
43 | |||
44 | static int status = 1; | ||
45 | |||
46 | static struct GNUNET_SCHEDULER_Task *die_task = NULL; | ||
47 | static struct GNUNET_SCHEDULER_Task *op_task = NULL; | ||
48 | |||
49 | struct GNUNET_MESSENGER_Handle *messenger = NULL; | ||
50 | |||
51 | static void | ||
52 | end (void *cls) | ||
53 | { | ||
54 | die_task = NULL; | ||
55 | |||
56 | if (op_task) | ||
57 | { | ||
58 | GNUNET_SCHEDULER_cancel (op_task); | ||
59 | op_task = NULL; | ||
60 | } | ||
61 | |||
62 | if (messenger) | ||
63 | { | ||
64 | GNUNET_MESSENGER_disconnect(messenger); | ||
65 | messenger = NULL; | ||
66 | } | ||
67 | |||
68 | status = 0; | ||
69 | } | ||
70 | |||
71 | |||
72 | static void | ||
73 | end_badly (void *cls) | ||
74 | { | ||
75 | fprintf (stderr, "Testcase failed (timeout).\n"); | ||
76 | |||
77 | end (NULL); | ||
78 | status = 1; | ||
79 | } | ||
80 | |||
81 | static void | ||
82 | end_operation (void *cls) | ||
83 | { | ||
84 | op_task = NULL; | ||
85 | |||
86 | fprintf (stderr, "Testcase failed (operation: '%s').\n", cls? (const char*) cls : "unknown"); | ||
87 | |||
88 | if (die_task) | ||
89 | GNUNET_SCHEDULER_cancel (die_task); | ||
90 | |||
91 | end (NULL); | ||
92 | status = 1; | ||
93 | } | ||
94 | |||
95 | static int identity_counter = 0; | ||
96 | |||
97 | /** | ||
98 | * Function called when an identity is retrieved. | ||
99 | * | ||
100 | * @param cls Closure | ||
101 | * @param handle Handle of messenger service | ||
102 | */ | ||
103 | static void | ||
104 | on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle) | ||
105 | { | ||
106 | if (op_task) | ||
107 | { | ||
108 | GNUNET_SCHEDULER_cancel (op_task); | ||
109 | op_task = NULL; | ||
110 | } | ||
111 | |||
112 | const char* name = GNUNET_MESSENGER_get_name(handle); | ||
113 | |||
114 | if (0 != strcmp(name, TESTER_NAME)) | ||
115 | { | ||
116 | op_task = GNUNET_SCHEDULER_add_now (&end_operation, "name"); | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | struct GNUNET_IDENTITY_Ego* ego = GNUNET_IDENTITY_ego_get_anonymous(); | ||
121 | struct GNUNET_IDENTITY_PublicKey anonymous_key; | ||
122 | |||
123 | GNUNET_IDENTITY_ego_get_public_key(ego, &anonymous_key); | ||
124 | |||
125 | const struct GNUNET_IDENTITY_PublicKey* key = GNUNET_MESSENGER_get_key(handle); | ||
126 | |||
127 | if (((!identity_counter) && (0 != GNUNET_memcmp(key, (&anonymous_key)))) || | ||
128 | ((identity_counter) && (0 == GNUNET_memcmp(key, (&anonymous_key))))) | ||
129 | { | ||
130 | op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key"); | ||
131 | return; | ||
132 | } | ||
133 | |||
134 | if (identity_counter) { | ||
135 | GNUNET_MESSENGER_disconnect(handle); | ||
136 | |||
137 | op_task = NULL; | ||
138 | messenger = NULL; | ||
139 | |||
140 | if (die_task) | ||
141 | GNUNET_SCHEDULER_cancel (die_task); | ||
142 | |||
143 | die_task = GNUNET_SCHEDULER_add_now (&end, NULL); | ||
144 | return; | ||
145 | } | ||
146 | |||
147 | GNUNET_MESSENGER_update(messenger); | ||
148 | identity_counter++; | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * Main function for testcase. | ||
153 | * | ||
154 | * @param cls Closure | ||
155 | * @param cfg Configuration | ||
156 | * @param peer Peer for testing | ||
157 | */ | ||
158 | static void | ||
159 | run (void *cls, | ||
160 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
161 | struct GNUNET_TESTING_Peer *peer) | ||
162 | { | ||
163 | die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL); | ||
164 | |||
165 | identity_counter = 0; | ||
166 | |||
167 | op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect"); | ||
168 | messenger = GNUNET_MESSENGER_connect(cfg, TESTER_NAME, &on_identity, NULL, NULL, NULL); | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * The main function. | ||
173 | * | ||
174 | * @param argc number of arguments from the command line | ||
175 | * @param argv command line arguments | ||
176 | * @return 0 ok, 1 on error | ||
177 | */ | ||
178 | int | ||
179 | main(int argc, char **argv) | ||
180 | { | ||
181 | if (0 != GNUNET_TESTING_peer_run("test-messenger", | ||
182 | "test_messenger_api.conf", | ||
183 | &run, NULL)) | ||
184 | return 1; | ||
185 | |||
186 | return status; | ||
187 | } | ||
diff --git a/src/messenger/test_messenger_anonymous.c b/src/messenger/test_messenger_anonymous.c new file mode 100644 index 000000000..e2057acc4 --- /dev/null +++ b/src/messenger/test_messenger_anonymous.c | |||
@@ -0,0 +1,179 @@ | |||
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 | * @file messenger/test_messenger_anonymous.c | ||
22 | * @author Tobias Frisch | ||
23 | * @brief Test for the messenger service using cadet API. | ||
24 | */ | ||
25 | #include <stdio.h> | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_testing_lib.h" | ||
29 | #include "gnunet_messenger_service.h" | ||
30 | |||
31 | /** | ||
32 | * How long until we really give up on a particular testcase portion? | ||
33 | */ | ||
34 | #define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, \ | ||
35 | 60) | ||
36 | |||
37 | /** | ||
38 | * How long until we give up on any particular operation (and retry)? | ||
39 | */ | ||
40 | #define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
41 | |||
42 | static int status = 1; | ||
43 | |||
44 | static struct GNUNET_SCHEDULER_Task *die_task = NULL; | ||
45 | static struct GNUNET_SCHEDULER_Task *op_task = NULL; | ||
46 | |||
47 | struct GNUNET_MESSENGER_Handle *messenger = NULL; | ||
48 | |||
49 | static void | ||
50 | end (void *cls) | ||
51 | { | ||
52 | die_task = NULL; | ||
53 | |||
54 | if (op_task) | ||
55 | { | ||
56 | GNUNET_SCHEDULER_cancel (op_task); | ||
57 | op_task = NULL; | ||
58 | } | ||
59 | |||
60 | if (messenger) | ||
61 | { | ||
62 | GNUNET_MESSENGER_disconnect(messenger); | ||
63 | messenger = NULL; | ||
64 | } | ||
65 | |||
66 | status = 0; | ||
67 | } | ||
68 | |||
69 | |||
70 | static void | ||
71 | end_badly (void *cls) | ||
72 | { | ||
73 | fprintf (stderr, "Testcase failed (timeout).\n"); | ||
74 | |||
75 | end (NULL); | ||
76 | status = 1; | ||
77 | } | ||
78 | |||
79 | static void | ||
80 | end_operation (void *cls) | ||
81 | { | ||
82 | op_task = NULL; | ||
83 | |||
84 | fprintf (stderr, "Testcase failed (operation: '%s').\n", cls? (const char*) cls : "unknown"); | ||
85 | |||
86 | if (die_task) | ||
87 | GNUNET_SCHEDULER_cancel (die_task); | ||
88 | |||
89 | end (NULL); | ||
90 | status = 1; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * Function called when an identity is retrieved. | ||
95 | * | ||
96 | * @param cls Closure | ||
97 | * @param handle Handle of messenger service | ||
98 | */ | ||
99 | static void | ||
100 | on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle) | ||
101 | { | ||
102 | if (op_task) | ||
103 | { | ||
104 | GNUNET_SCHEDULER_cancel (op_task); | ||
105 | op_task = NULL; | ||
106 | } | ||
107 | |||
108 | const char* name = GNUNET_MESSENGER_get_name(handle); | ||
109 | |||
110 | if (NULL != name) | ||
111 | { | ||
112 | op_task = GNUNET_SCHEDULER_add_now (&end_operation, "name-anonymous"); | ||
113 | return; | ||
114 | } | ||
115 | |||
116 | if (GNUNET_SYSERR != GNUNET_MESSENGER_update(handle)) | ||
117 | { | ||
118 | op_task = GNUNET_SCHEDULER_add_now (&end_operation, "update-fail"); | ||
119 | return; | ||
120 | } | ||
121 | |||
122 | struct GNUNET_IDENTITY_Ego* ego = GNUNET_IDENTITY_ego_get_anonymous(); | ||
123 | struct GNUNET_IDENTITY_PublicKey anonymous_key; | ||
124 | |||
125 | GNUNET_IDENTITY_ego_get_public_key(ego, &anonymous_key); | ||
126 | |||
127 | const struct GNUNET_IDENTITY_PublicKey* key = GNUNET_MESSENGER_get_key(handle); | ||
128 | |||
129 | if (0 != GNUNET_memcmp(key, (&anonymous_key))) | ||
130 | { | ||
131 | op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key-anonymous"); | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | GNUNET_MESSENGER_disconnect(handle); | ||
136 | |||
137 | messenger = NULL; | ||
138 | |||
139 | if (die_task) | ||
140 | GNUNET_SCHEDULER_cancel (die_task); | ||
141 | |||
142 | die_task = GNUNET_SCHEDULER_add_now (&end, NULL); | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * Main function for testcase. | ||
147 | * | ||
148 | * @param cls Closure | ||
149 | * @param cfg Configuration | ||
150 | * @param peer Peer for testing | ||
151 | */ | ||
152 | static void | ||
153 | run (void *cls, | ||
154 | const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
155 | struct GNUNET_TESTING_Peer *peer) | ||
156 | { | ||
157 | die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL); | ||
158 | |||
159 | op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect"); | ||
160 | messenger = GNUNET_MESSENGER_connect(cfg, NULL, &on_identity, NULL, NULL, NULL); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * The main function. | ||
165 | * | ||
166 | * @param argc number of arguments from the command line | ||
167 | * @param argv command line arguments | ||
168 | * @return 0 ok, 1 on error | ||
169 | */ | ||
170 | int | ||
171 | main(int argc, char **argv) | ||
172 | { | ||
173 | if (0 != GNUNET_TESTING_peer_run("test-messenger", | ||
174 | "test_messenger_api.conf", | ||
175 | &run, NULL)) | ||
176 | return 1; | ||
177 | |||
178 | return status; | ||
179 | } | ||
diff --git a/src/messenger/test_messenger_comm0.c b/src/messenger/test_messenger_comm0.c new file mode 100644 index 000000000..631b5b2c9 --- /dev/null +++ b/src/messenger/test_messenger_comm0.c | |||
@@ -0,0 +1,252 @@ | |||
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 | * @file messenger/test_messenger_comm0.c | ||
22 | * @author Tobias Frisch | ||
23 | * @brief Test for the messenger service using cadet API. | ||
24 | */ | ||
25 | #include <stdio.h> | ||
26 | #include "platform.h" | ||
27 | #include "gnunet_util_lib.h" | ||
28 | #include "gnunet_testbed_logger_service.h" | ||
29 | #include "gnunet_testbed_service.h" | ||
30 | #include "gnunet_testing_lib.h" | ||
31 | #include "gnunet_messenger_service.h" | ||
32 | |||
33 | /** | ||
34 | * How long until we really give up on a particular testcase portion? | ||
35 | */ | ||
36 | #define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, \ | ||
37 | 60) | ||
38 | |||
39 | /** | ||
40 | * How long until we give up on any particular operation (and retry)? | ||
41 | */ | ||
42 | #define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) | ||
43 | |||
44 | static int status = 1; | ||
45 | |||
46 | static struct GNUNET_SCHEDULER_Task *die_task = NULL; | ||
47 | static struct GNUNET_SCHEDULER_Task *op_task = NULL; | ||
48 | |||
49 | static void | ||
50 | end (void *cls) | ||
51 | { | ||
52 | die_task = NULL; | ||
53 | |||
54 | if (op_task) | ||
55 | { | ||
56 | GNUNET_SCHEDULER_cancel (op_task); | ||
57 | op_task = NULL; | ||
58 | } | ||
59 | |||
60 | GNUNET_SCHEDULER_shutdown (); | ||
61 | status = 0; | ||
62 | } | ||
63 | |||
64 | |||
65 | static void | ||
66 | end_badly (void *cls) | ||
67 | { | ||
68 | fprintf (stderr, "Testcase failed (timeout).\n"); | ||
69 | |||
70 | end (NULL); | ||
71 | status = 1; | ||
72 | } | ||
73 | |||
74 | static void | ||
75 | end_operation (void *cls) | ||
76 | { | ||
77 | op_task = NULL; | ||
78 | |||
79 | fprintf (stderr, "Testcase failed (operation: '%s').\n", cls? (const char*) cls : "unknown"); | ||
80 | |||
81 | if (die_task) | ||
82 | GNUNET_SCHEDULER_cancel (die_task); | ||
83 | |||
84 | end (NULL); | ||
85 | status = 1; | ||
86 | } | ||
87 | |||
88 | static void | ||
89 | end_error (void *cls) | ||
90 | { | ||
91 | op_task = NULL; | ||
92 | |||
93 | fprintf (stderr, "Testcase failed (error: '%s').\n", cls? (const char*) cls : "unknown"); | ||
94 | GNUNET_free(cls); | ||
95 | |||
96 | if (die_task) | ||
97 | GNUNET_SCHEDULER_cancel (die_task); | ||
98 | |||
99 | end (NULL); | ||
100 | status = 1; | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * Function called whenever a message is received or sent. | ||
105 | * | ||
106 | * @param cls Closure | ||
107 | * @param room Room | ||
108 | * @param message Message | ||
109 | * @param hash Hash of message | ||
110 | */ | ||
111 | static void | ||
112 | on_message (void *cls, const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message, | ||
113 | const struct GNUNET_HashCode *hash) | ||
114 | { | ||
115 | // TODO | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * Function called when an identity is retrieved. | ||
120 | * | ||
121 | * @param cls Closure | ||
122 | * @param handle Handle of messenger service | ||
123 | */ | ||
124 | static void | ||
125 | on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle) | ||
126 | { | ||
127 | // TODO | ||
128 | } | ||
129 | |||
130 | static void | ||
131 | on_peer (void *cb_cls, struct GNUNET_TESTBED_Operation *op, | ||
132 | const struct GNUNET_TESTBED_PeerInformation *pinfo, | ||
133 | const char *emsg) | ||
134 | { | ||
135 | if (emsg) | ||
136 | { | ||
137 | op_task = GNUNET_SCHEDULER_add_now (&end_error, GNUNET_strdup(emsg)); | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | if (pinfo->pit != GNUNET_TESTBED_PIT_CONFIGURATION) | ||
142 | { | ||
143 | op_task = GNUNET_SCHEDULER_add_now (&end_operation, "config"); | ||
144 | return; | ||
145 | } | ||
146 | |||
147 | struct GNUNET_MESSENGER_Handle *handle; | ||
148 | struct GNUNET_MESSENGER_Room *room; | ||
149 | |||
150 | fprintf (stderr, "MSG: connect\n"); | ||
151 | |||
152 | handle = GNUNET_MESSENGER_connect(pinfo->result.cfg, "tester", &on_identity, NULL, &on_message, NULL); | ||
153 | |||
154 | struct GNUNET_HashCode hash; | ||
155 | GNUNET_CRYPTO_hash("test", 4, &hash); | ||
156 | |||
157 | fprintf (stderr, "MSG: open\n"); | ||
158 | |||
159 | room = GNUNET_MESSENGER_open_room(handle, &hash); | ||
160 | |||
161 | fprintf (stderr, "MSG: close\n"); | ||
162 | |||
163 | GNUNET_MESSENGER_close_room(room); | ||
164 | |||
165 | fprintf (stderr, "MSG: disconnect\n"); | ||
166 | |||
167 | GNUNET_MESSENGER_disconnect(handle); | ||
168 | |||
169 | GNUNET_TESTBED_operation_done(op); | ||
170 | |||
171 | } | ||
172 | |||
173 | /** | ||
174 | * Main function for a peer of the testcase. | ||
175 | * | ||
176 | * @param cls Closure | ||
177 | * @param event Information about the event | ||
178 | */ | ||
179 | static void | ||
180 | run (void *cls, const struct GNUNET_TESTBED_EventInformation *event) | ||
181 | { | ||
182 | if (GNUNET_TESTBED_ET_PEER_START != event->type) | ||
183 | { | ||
184 | op_task = GNUNET_SCHEDULER_add_now (&end_operation, "start"); | ||
185 | return; | ||
186 | } | ||
187 | |||
188 | GNUNET_TESTBED_peer_get_information(event->details.peer_start.peer, | ||
189 | GNUNET_TESTBED_PIT_CONFIGURATION, | ||
190 | on_peer, event->details.peer_start.peer); | ||
191 | |||
192 | fprintf (stderr, "MSG: barrier\n"); | ||
193 | |||
194 | GNUNET_TESTBED_barrier_wait("exit", NULL, NULL); | ||
195 | |||
196 | fprintf (stderr, "MSG: exit\n"); | ||
197 | } | ||
198 | |||
199 | static void | ||
200 | exit_status (void *cls, const char *name, | ||
201 | struct GNUNET_TESTBED_Barrier *barrier, | ||
202 | enum GNUNET_TESTBED_BarrierStatus status, | ||
203 | const char *emsg) | ||
204 | { | ||
205 | if (emsg) | ||
206 | { | ||
207 | op_task = GNUNET_SCHEDULER_add_now (&end_error, GNUNET_strdup(emsg)); | ||
208 | return; | ||
209 | } | ||
210 | |||
211 | if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status) | ||
212 | { | ||
213 | op_task = GNUNET_SCHEDULER_add_now (&end_operation, "exit"); | ||
214 | return; | ||
215 | } | ||
216 | else if (GNUNET_TESTBED_BARRIERSTATUS_CROSSED == status) | ||
217 | GNUNET_SCHEDULER_add_now(&end, NULL); | ||
218 | } | ||
219 | |||
220 | static void | ||
221 | init (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, | ||
222 | struct GNUNET_TESTBED_Peer **peers, unsigned int links_succeeded, | ||
223 | unsigned int links_failed) | ||
224 | { | ||
225 | die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL); | ||
226 | |||
227 | struct GNUNET_TESTBED_Controller *controller; | ||
228 | |||
229 | controller = GNUNET_TESTBED_run_get_controller_handle(h); | ||
230 | |||
231 | GNUNET_TESTBED_barrier_init(controller, "exit", num_peers, exit_status, NULL); | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * The main function. | ||
236 | * | ||
237 | * @param argc number of arguments from the command line | ||
238 | * @param argv command line arguments | ||
239 | * @return 0 ok, 1 on error | ||
240 | */ | ||
241 | int | ||
242 | main(int argc, char **argv) | ||
243 | { | ||
244 | if (GNUNET_OK != GNUNET_TESTBED_test_run("test-messenger-comm0", | ||
245 | "test_messenger_api.conf", | ||
246 | 2, 0, | ||
247 | &run, NULL, | ||
248 | &init, NULL)) | ||
249 | return 1; | ||
250 | |||
251 | return status; | ||
252 | } | ||