diff options
Diffstat (limited to 'src/service/messenger/messenger_api.c')
-rw-r--r-- | src/service/messenger/messenger_api.c | 1252 |
1 files changed, 1252 insertions, 0 deletions
diff --git a/src/service/messenger/messenger_api.c b/src/service/messenger/messenger_api.c new file mode 100644 index 000000000..df4499fe0 --- /dev/null +++ b/src/service/messenger/messenger_api.c | |||
@@ -0,0 +1,1252 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2020--2024 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @author Tobias Frisch | ||
22 | * @file src/messenger/messenger_api.c | ||
23 | * @brief messenger api: client implementation of GNUnet MESSENGER service | ||
24 | */ | ||
25 | |||
26 | #include "gnunet_common.h" | ||
27 | #include "gnunet_messenger_service.h" | ||
28 | |||
29 | #include "gnunet-service-messenger.h" | ||
30 | |||
31 | #include "gnunet_reclaim_service.h" | ||
32 | #include "gnunet_time_lib.h" | ||
33 | #include "messenger_api_contact.h" | ||
34 | #include "messenger_api_contact_store.h" | ||
35 | #include "messenger_api_handle.h" | ||
36 | #include "messenger_api_message.h" | ||
37 | #include "messenger_api_message_control.h" | ||
38 | #include "messenger_api_message_kind.h" | ||
39 | #include "messenger_api_room.h" | ||
40 | #include "messenger_api_util.h" | ||
41 | |||
42 | const char* | ||
43 | GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind) | ||
44 | { | ||
45 | switch (kind) | ||
46 | { | ||
47 | case GNUNET_MESSENGER_KIND_INFO: | ||
48 | return "INFO"; | ||
49 | case GNUNET_MESSENGER_KIND_JOIN: | ||
50 | return "JOIN"; | ||
51 | case GNUNET_MESSENGER_KIND_LEAVE: | ||
52 | return "LEAVE"; | ||
53 | case GNUNET_MESSENGER_KIND_NAME: | ||
54 | return "NAME"; | ||
55 | case GNUNET_MESSENGER_KIND_KEY: | ||
56 | return "KEY"; | ||
57 | case GNUNET_MESSENGER_KIND_PEER: | ||
58 | return "PEER"; | ||
59 | case GNUNET_MESSENGER_KIND_ID: | ||
60 | return "ID"; | ||
61 | case GNUNET_MESSENGER_KIND_MISS: | ||
62 | return "MISS"; | ||
63 | case GNUNET_MESSENGER_KIND_MERGE: | ||
64 | return "MERGE"; | ||
65 | case GNUNET_MESSENGER_KIND_REQUEST: | ||
66 | return "REQUEST"; | ||
67 | case GNUNET_MESSENGER_KIND_INVITE: | ||
68 | return "INVITE"; | ||
69 | case GNUNET_MESSENGER_KIND_TEXT: | ||
70 | return "TEXT"; | ||
71 | case GNUNET_MESSENGER_KIND_FILE: | ||
72 | return "FILE"; | ||
73 | case GNUNET_MESSENGER_KIND_PRIVATE: | ||
74 | return "PRIVATE"; | ||
75 | case GNUNET_MESSENGER_KIND_DELETE: | ||
76 | return "DELETE"; | ||
77 | case GNUNET_MESSENGER_KIND_CONNECTION: | ||
78 | return "CONNECTION"; | ||
79 | case GNUNET_MESSENGER_KIND_TICKET: | ||
80 | return "TICKET"; | ||
81 | case GNUNET_MESSENGER_KIND_TRANSCRIPT: | ||
82 | return "TRANSCRIPT"; | ||
83 | case GNUNET_MESSENGER_KIND_TAG: | ||
84 | return "TAG"; | ||
85 | default: | ||
86 | return "UNKNOWN"; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | |||
91 | static enum GNUNET_GenericReturnValue | ||
92 | dequeue_messages_from_room (struct GNUNET_MESSENGER_Room *room); | ||
93 | |||
94 | static void | ||
95 | handle_room_open (void *cls, | ||
96 | const struct GNUNET_MESSENGER_RoomMessage *msg) | ||
97 | { | ||
98 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
99 | |||
100 | const struct GNUNET_HashCode *key = &(msg->key); | ||
101 | const struct GNUNET_HashCode *prev = &(msg->previous); | ||
102 | |||
103 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opened room: %s\n", GNUNET_h2s (key)); | ||
104 | |||
105 | open_handle_room (handle, key); | ||
106 | |||
107 | struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key); | ||
108 | |||
109 | if (! room) | ||
110 | return; | ||
111 | |||
112 | update_room_last_message (room, prev); | ||
113 | |||
114 | dequeue_messages_from_room (room); | ||
115 | } | ||
116 | |||
117 | |||
118 | static void | ||
119 | handle_room_entry (void *cls, | ||
120 | const struct GNUNET_MESSENGER_RoomMessage *msg) | ||
121 | { | ||
122 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
123 | |||
124 | const struct GNUNET_PeerIdentity *door = &(msg->door); | ||
125 | const struct GNUNET_HashCode *key = &(msg->key); | ||
126 | const struct GNUNET_HashCode *prev = &(msg->previous); | ||
127 | |||
128 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Entered room: %s\n", GNUNET_h2s (key)); | ||
129 | |||
130 | entry_handle_room_at (handle, door, key); | ||
131 | |||
132 | struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key); | ||
133 | |||
134 | if (! room) | ||
135 | return; | ||
136 | |||
137 | update_room_last_message (room, prev); | ||
138 | |||
139 | dequeue_messages_from_room (room); | ||
140 | } | ||
141 | |||
142 | |||
143 | static void | ||
144 | handle_room_close (void *cls, | ||
145 | const struct GNUNET_MESSENGER_RoomMessage *msg) | ||
146 | { | ||
147 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
148 | |||
149 | const struct GNUNET_HashCode *key = &(msg->key); | ||
150 | const struct GNUNET_HashCode *prev = &(msg->previous); | ||
151 | |||
152 | struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key); | ||
153 | |||
154 | if (room) | ||
155 | update_room_last_message (room, prev); | ||
156 | |||
157 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key)); | ||
158 | |||
159 | close_handle_room (handle, key); | ||
160 | } | ||
161 | |||
162 | |||
163 | static void | ||
164 | handle_room_sync (void *cls, | ||
165 | const struct GNUNET_MESSENGER_RoomMessage *msg) | ||
166 | { | ||
167 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
168 | |||
169 | const struct GNUNET_HashCode *key = &(msg->key); | ||
170 | const struct GNUNET_HashCode *prev = &(msg->previous); | ||
171 | |||
172 | struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key); | ||
173 | |||
174 | if (! room) | ||
175 | return; | ||
176 | |||
177 | update_room_last_message (room, prev); | ||
178 | |||
179 | room->wait_for_sync = GNUNET_NO; | ||
180 | |||
181 | dequeue_messages_from_room (room); | ||
182 | } | ||
183 | |||
184 | |||
185 | static void | ||
186 | enqueue_message_to_room (struct GNUNET_MESSENGER_Room *room, | ||
187 | struct GNUNET_MESSENGER_Message *message, | ||
188 | struct GNUNET_MESSENGER_Message *transcript); | ||
189 | |||
190 | static void | ||
191 | handle_member_id (void *cls, | ||
192 | const struct GNUNET_MESSENGER_MemberMessage *msg) | ||
193 | { | ||
194 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
195 | |||
196 | const struct GNUNET_HashCode *key = &(msg->key); | ||
197 | const struct GNUNET_ShortHashCode *id = &(msg->id); | ||
198 | const uint32_t reset = msg->reset; | ||
199 | |||
200 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Changed member id in room: %s\n", | ||
201 | GNUNET_h2s (key)); | ||
202 | |||
203 | struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key); | ||
204 | |||
205 | if (! room) | ||
206 | { | ||
207 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Room is unknown to handle: %s\n", | ||
208 | GNUNET_h2s (key)); | ||
209 | return; | ||
210 | } | ||
211 | |||
212 | struct GNUNET_MESSENGER_Message *message; | ||
213 | if ((! get_room_sender_id (room)) || (GNUNET_YES == reset)) | ||
214 | { | ||
215 | set_room_sender_id (room, id); | ||
216 | message = create_message_join (get_handle_key (handle)); | ||
217 | } | ||
218 | else | ||
219 | message = create_message_id (id); | ||
220 | |||
221 | if (! message) | ||
222 | return; | ||
223 | |||
224 | enqueue_message_to_room (room, message, NULL); | ||
225 | } | ||
226 | |||
227 | |||
228 | static enum GNUNET_GenericReturnValue | ||
229 | check_recv_message (void *cls, | ||
230 | const struct GNUNET_MESSENGER_RecvMessage *msg) | ||
231 | { | ||
232 | const uint16_t full_length = ntohs (msg->header.size); | ||
233 | |||
234 | if (full_length < sizeof(*msg)) | ||
235 | { | ||
236 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
237 | "Receiving failed: Message invalid!\n"); | ||
238 | return GNUNET_NO; | ||
239 | } | ||
240 | |||
241 | const uint16_t length = full_length - sizeof(*msg); | ||
242 | const char *buffer = ((const char*) msg) + sizeof(*msg); | ||
243 | |||
244 | struct GNUNET_MESSENGER_Message message; | ||
245 | |||
246 | if (length < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN, | ||
247 | GNUNET_YES)) | ||
248 | { | ||
249 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
250 | "Receiving failed: Message too short!\n"); | ||
251 | return GNUNET_NO; | ||
252 | } | ||
253 | |||
254 | if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, NULL)) | ||
255 | { | ||
256 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
257 | "Receiving failed: Message decoding failed!\n"); | ||
258 | return GNUNET_NO; | ||
259 | } | ||
260 | |||
261 | cleanup_message (&message); | ||
262 | return GNUNET_OK; | ||
263 | } | ||
264 | |||
265 | |||
266 | static void | ||
267 | handle_recv_message (void *cls, | ||
268 | const struct GNUNET_MESSENGER_RecvMessage *msg) | ||
269 | { | ||
270 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
271 | |||
272 | const struct GNUNET_HashCode *key = &(msg->key); | ||
273 | const struct GNUNET_HashCode *sender = &(msg->sender); | ||
274 | const struct GNUNET_HashCode *context = &(msg->context); | ||
275 | const struct GNUNET_HashCode *hash = &(msg->hash); | ||
276 | |||
277 | enum GNUNET_MESSENGER_MessageFlags flags = ( | ||
278 | (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)); | ||
279 | |||
280 | const uint16_t length = ntohs (msg->header.size) - sizeof(*msg); | ||
281 | const char *buffer = ((const char*) msg) + sizeof(*msg); | ||
282 | |||
283 | struct GNUNET_MESSENGER_Message message; | ||
284 | decode_message (&message, length, buffer, GNUNET_YES, NULL); | ||
285 | |||
286 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", | ||
287 | GNUNET_MESSENGER_name_of_kind (message.header.kind)); | ||
288 | |||
289 | struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key); | ||
290 | |||
291 | if (! room) | ||
292 | { | ||
293 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unknown room for this client: %s\n", | ||
294 | GNUNET_h2s (key)); | ||
295 | |||
296 | goto skip_message; | ||
297 | } | ||
298 | |||
299 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
300 | "Raw contact from sender and context: (%s : %s)\n", | ||
301 | GNUNET_h2s (sender), GNUNET_h2s_full (context)); | ||
302 | |||
303 | process_message_control (room->control, | ||
304 | sender, | ||
305 | context, | ||
306 | hash, | ||
307 | &message, | ||
308 | flags); | ||
309 | |||
310 | skip_message: | ||
311 | cleanup_message (&message); | ||
312 | } | ||
313 | |||
314 | |||
315 | static void | ||
316 | handle_miss_message (void *cls, | ||
317 | const struct GNUNET_MESSENGER_GetMessage *msg) | ||
318 | { | ||
319 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
320 | |||
321 | const struct GNUNET_HashCode *key = &(msg->key); | ||
322 | const struct GNUNET_HashCode *hash = &(msg->hash); | ||
323 | |||
324 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Missing message in room: %s\n", | ||
325 | GNUNET_h2s (hash)); | ||
326 | |||
327 | struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key); | ||
328 | |||
329 | if (! room) | ||
330 | { | ||
331 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
332 | "Miss in unknown room for this client: %s\n", GNUNET_h2s (key)); | ||
333 | return; | ||
334 | } | ||
335 | |||
336 | if (! get_room_sender_id (room)) | ||
337 | return; | ||
338 | |||
339 | struct GNUNET_MESSENGER_Message *message = create_message_request (hash); | ||
340 | if (! message) | ||
341 | return; | ||
342 | |||
343 | enqueue_message_to_room (room, message, NULL); | ||
344 | } | ||
345 | |||
346 | |||
347 | static void | ||
348 | reconnect (struct GNUNET_MESSENGER_Handle *handle); | ||
349 | |||
350 | static void | ||
351 | send_open_room (struct GNUNET_MESSENGER_Handle *handle, | ||
352 | struct GNUNET_MESSENGER_Room *room) | ||
353 | { | ||
354 | const struct GNUNET_CRYPTO_PublicKey *key = get_handle_pubkey (handle); | ||
355 | |||
356 | struct GNUNET_MESSENGER_RoomMessage *msg; | ||
357 | struct GNUNET_MQ_Envelope *env; | ||
358 | |||
359 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
360 | "Open room (%s) by member using key: %s\n", | ||
361 | GNUNET_h2s (&(room->key)), | ||
362 | GNUNET_CRYPTO_public_key_to_string (key)); | ||
363 | |||
364 | const ssize_t len = GNUNET_CRYPTO_public_key_get_length (key); | ||
365 | |||
366 | env = GNUNET_MQ_msg_extra (msg, len > 0 ? len : 0, | ||
367 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN); | ||
368 | GNUNET_memcpy (&(msg->key), &(room->key), sizeof(msg->key)); | ||
369 | GNUNET_memcpy (&(msg->previous), &(room->last_message), | ||
370 | sizeof(msg->previous)); | ||
371 | |||
372 | char *msg_buffer = ((char*) msg) + sizeof(*msg); | ||
373 | |||
374 | if (len > 0) | ||
375 | GNUNET_CRYPTO_write_public_key_to_buffer (key, msg_buffer, len); | ||
376 | |||
377 | GNUNET_MQ_send (handle->mq, env); | ||
378 | } | ||
379 | |||
380 | |||
381 | static void | ||
382 | send_enter_room (struct GNUNET_MESSENGER_Handle *handle, | ||
383 | struct GNUNET_MESSENGER_Room *room, | ||
384 | const struct GNUNET_PeerIdentity *door) | ||
385 | { | ||
386 | const struct GNUNET_CRYPTO_PublicKey *key = get_handle_pubkey (handle); | ||
387 | |||
388 | struct GNUNET_MESSENGER_RoomMessage *msg; | ||
389 | struct GNUNET_MQ_Envelope *env; | ||
390 | |||
391 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Enter room (%s) via door: %s (%s)\n", | ||
392 | GNUNET_h2s (&(room->key)), | ||
393 | GNUNET_i2s (door), | ||
394 | GNUNET_CRYPTO_public_key_to_string (key)); | ||
395 | |||
396 | const ssize_t len = GNUNET_CRYPTO_public_key_get_length (key); | ||
397 | |||
398 | env = GNUNET_MQ_msg_extra (msg, len > 0 ? len : 0, | ||
399 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY); | ||
400 | GNUNET_memcpy (&(msg->door), door, sizeof(*door)); | ||
401 | GNUNET_memcpy (&(msg->key), &(room->key), sizeof(msg->key)); | ||
402 | GNUNET_memcpy (&(msg->previous), &(room->last_message), | ||
403 | sizeof(msg->previous)); | ||
404 | |||
405 | char *msg_buffer = ((char*) msg) + sizeof(*msg); | ||
406 | |||
407 | if (len > 0) | ||
408 | GNUNET_CRYPTO_write_public_key_to_buffer (key, msg_buffer, len); | ||
409 | |||
410 | GNUNET_MQ_send (handle->mq, env); | ||
411 | } | ||
412 | |||
413 | |||
414 | static void | ||
415 | send_close_room (struct GNUNET_MESSENGER_Handle *handle, | ||
416 | struct GNUNET_MESSENGER_Room *room) | ||
417 | { | ||
418 | struct GNUNET_MESSENGER_RoomMessage *msg; | ||
419 | struct GNUNET_MQ_Envelope *env; | ||
420 | |||
421 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Close room (%s)!\n", | ||
422 | GNUNET_h2s (&(room->key))); | ||
423 | |||
424 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE); | ||
425 | |||
426 | GNUNET_memcpy (&(msg->key), &(room->key), sizeof(msg->key)); | ||
427 | GNUNET_memcpy (&(msg->previous), &(room->last_message), | ||
428 | sizeof(msg->previous)); | ||
429 | |||
430 | GNUNET_MQ_send (handle->mq, env); | ||
431 | } | ||
432 | |||
433 | |||
434 | static void | ||
435 | send_sync_room (struct GNUNET_MESSENGER_Handle *handle, | ||
436 | struct GNUNET_MESSENGER_Room *room) | ||
437 | { | ||
438 | struct GNUNET_MESSENGER_RoomMessage *msg; | ||
439 | struct GNUNET_MQ_Envelope *env; | ||
440 | |||
441 | room->wait_for_sync = GNUNET_YES; | ||
442 | |||
443 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sync room (%s)!\n", | ||
444 | GNUNET_h2s (&(room->key))); | ||
445 | |||
446 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SYNC); | ||
447 | |||
448 | GNUNET_memcpy (&(msg->key), &(room->key), sizeof(msg->key)); | ||
449 | GNUNET_memcpy (&(msg->previous), &(room->last_message), | ||
450 | sizeof(msg->previous)); | ||
451 | |||
452 | GNUNET_MQ_send (handle->mq, env); | ||
453 | } | ||
454 | |||
455 | |||
456 | static enum GNUNET_GenericReturnValue | ||
457 | iterate_reset_room (void *cls, | ||
458 | const struct GNUNET_HashCode *key, | ||
459 | void *value) | ||
460 | { | ||
461 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
462 | struct GNUNET_MESSENGER_Room *room = value; | ||
463 | |||
464 | if (GNUNET_YES == room->opened) | ||
465 | send_open_room (handle, room); | ||
466 | |||
467 | struct GNUNET_MESSENGER_ListTunnel *entry = room->entries.head; | ||
468 | |||
469 | struct GNUNET_PeerIdentity door; | ||
470 | |||
471 | while (entry) | ||
472 | { | ||
473 | GNUNET_PEER_resolve (entry->peer, &door); | ||
474 | |||
475 | send_enter_room (handle, room, &door); | ||
476 | |||
477 | entry = entry->next; | ||
478 | } | ||
479 | |||
480 | return GNUNET_YES; | ||
481 | } | ||
482 | |||
483 | |||
484 | static void | ||
485 | callback_reconnect (void *cls) | ||
486 | { | ||
487 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
488 | |||
489 | handle->reconnect_task = NULL; | ||
490 | handle->reconnect_time = GNUNET_TIME_STD_BACKOFF (handle->reconnect_time); | ||
491 | |||
492 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnect messenger!\n"); | ||
493 | |||
494 | reconnect (handle); | ||
495 | |||
496 | GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_reset_room, | ||
497 | handle); | ||
498 | } | ||
499 | |||
500 | |||
501 | static enum GNUNET_GenericReturnValue | ||
502 | iterate_close_room (void *cls, | ||
503 | const struct GNUNET_HashCode *key, | ||
504 | void *value) | ||
505 | { | ||
506 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
507 | struct GNUNET_MESSENGER_Room *room = value; | ||
508 | |||
509 | send_close_room (handle, room); | ||
510 | |||
511 | return GNUNET_YES; | ||
512 | } | ||
513 | |||
514 | |||
515 | static void | ||
516 | callback_mq_error (void *cls, | ||
517 | enum GNUNET_MQ_Error error) | ||
518 | { | ||
519 | struct GNUNET_MESSENGER_Handle *handle = cls; | ||
520 | |||
521 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MQ_Error: %u\n", error); | ||
522 | |||
523 | GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room, | ||
524 | handle); | ||
525 | |||
526 | if (handle->mq) | ||
527 | { | ||
528 | GNUNET_MQ_destroy (handle->mq); | ||
529 | handle->mq = NULL; | ||
530 | } | ||
531 | |||
532 | handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_time, | ||
533 | &callback_reconnect, | ||
534 | handle); | ||
535 | } | ||
536 | |||
537 | |||
538 | static void | ||
539 | reconnect (struct GNUNET_MESSENGER_Handle *handle) | ||
540 | { | ||
541 | const struct GNUNET_MQ_MessageHandler handlers[] = { | ||
542 | GNUNET_MQ_hd_fixed_size ( | ||
543 | member_id, | ||
544 | GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID, | ||
545 | struct GNUNET_MESSENGER_MemberMessage, handle | ||
546 | ), | ||
547 | GNUNET_MQ_hd_fixed_size ( | ||
548 | room_open, | ||
549 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN, | ||
550 | struct GNUNET_MESSENGER_RoomMessage, handle | ||
551 | ), | ||
552 | GNUNET_MQ_hd_fixed_size ( | ||
553 | room_entry, | ||
554 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY, | ||
555 | struct GNUNET_MESSENGER_RoomMessage, handle | ||
556 | ), | ||
557 | GNUNET_MQ_hd_fixed_size ( | ||
558 | room_close, | ||
559 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE, | ||
560 | struct GNUNET_MESSENGER_RoomMessage, handle | ||
561 | ), | ||
562 | GNUNET_MQ_hd_var_size ( | ||
563 | recv_message, | ||
564 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE, | ||
565 | struct GNUNET_MESSENGER_RecvMessage, handle | ||
566 | ), | ||
567 | GNUNET_MQ_hd_fixed_size ( | ||
568 | miss_message, | ||
569 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE, | ||
570 | struct GNUNET_MESSENGER_GetMessage, handle | ||
571 | ), | ||
572 | GNUNET_MQ_hd_fixed_size ( | ||
573 | room_sync, | ||
574 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SYNC, | ||
575 | struct GNUNET_MESSENGER_RoomMessage, handle | ||
576 | ), | ||
577 | GNUNET_MQ_handler_end () | ||
578 | }; | ||
579 | |||
580 | handle->mq = GNUNET_CLIENT_connect (handle->cfg, | ||
581 | GNUNET_MESSENGER_SERVICE_NAME, handlers, | ||
582 | &callback_mq_error, handle); | ||
583 | } | ||
584 | |||
585 | |||
586 | struct GNUNET_MESSENGER_Handle* | ||
587 | GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
588 | const char *name, | ||
589 | const struct GNUNET_CRYPTO_PrivateKey *key, | ||
590 | GNUNET_MESSENGER_MessageCallback msg_callback, | ||
591 | void *msg_cls) | ||
592 | { | ||
593 | struct GNUNET_MESSENGER_Handle *handle = create_handle (cfg, msg_callback, | ||
594 | msg_cls); | ||
595 | |||
596 | reconnect (handle); | ||
597 | |||
598 | if (handle->mq) | ||
599 | { | ||
600 | set_handle_name (handle, name); | ||
601 | |||
602 | if ((! key) || (0 < GNUNET_CRYPTO_private_key_get_length (key))) | ||
603 | set_handle_key (handle, key); | ||
604 | |||
605 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connect handle!\n"); | ||
606 | |||
607 | struct GNUNET_MESSENGER_CreateMessage *msg; | ||
608 | struct GNUNET_MQ_Envelope *env; | ||
609 | |||
610 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE); | ||
611 | GNUNET_MQ_send (handle->mq, env); | ||
612 | return handle; | ||
613 | } | ||
614 | else | ||
615 | { | ||
616 | destroy_handle (handle); | ||
617 | return NULL; | ||
618 | } | ||
619 | } | ||
620 | |||
621 | |||
622 | void | ||
623 | GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle) | ||
624 | { | ||
625 | if (! handle) | ||
626 | return; | ||
627 | |||
628 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnect handle!\n"); | ||
629 | |||
630 | struct GNUNET_MESSENGER_DestroyMessage *msg; | ||
631 | struct GNUNET_MQ_Envelope *env; | ||
632 | |||
633 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY); | ||
634 | GNUNET_MQ_send (handle->mq, env); | ||
635 | |||
636 | destroy_handle (handle); | ||
637 | } | ||
638 | |||
639 | |||
640 | static void | ||
641 | callback_leave_message_sent (void *cls) | ||
642 | { | ||
643 | struct GNUNET_MESSENGER_Room *room = cls; | ||
644 | |||
645 | room->opened = GNUNET_NO; | ||
646 | clear_list_tunnels (&(room->entries)); | ||
647 | |||
648 | send_close_room (room->handle, room); | ||
649 | } | ||
650 | |||
651 | |||
652 | static void | ||
653 | send_message_to_room (struct GNUNET_MESSENGER_Room *room, | ||
654 | struct GNUNET_MESSENGER_Message *message, | ||
655 | const struct GNUNET_CRYPTO_PrivateKey *key, | ||
656 | struct GNUNET_HashCode *hash) | ||
657 | { | ||
658 | const struct GNUNET_ShortHashCode *sender_id = get_room_sender_id (room); | ||
659 | |||
660 | message->header.timestamp = GNUNET_TIME_absolute_hton ( | ||
661 | GNUNET_TIME_absolute_get ()); | ||
662 | |||
663 | GNUNET_memcpy (&(message->header.sender_id), sender_id, | ||
664 | sizeof(message->header.sender_id)); | ||
665 | GNUNET_memcpy (&(message->header.previous), &(room->last_message), | ||
666 | sizeof(message->header.previous)); | ||
667 | |||
668 | message->header.signature.type = key->type; | ||
669 | |||
670 | const uint16_t msg_length = get_message_size (message, GNUNET_YES); | ||
671 | |||
672 | struct GNUNET_MESSENGER_SendMessage *msg; | ||
673 | struct GNUNET_MQ_Envelope *env; | ||
674 | |||
675 | env = GNUNET_MQ_msg_extra ( | ||
676 | msg, msg_length, | ||
677 | GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE | ||
678 | ); | ||
679 | |||
680 | GNUNET_memcpy (&(msg->key), &(room->key), sizeof(msg->key)); | ||
681 | |||
682 | char *msg_buffer = ((char*) msg) + sizeof(*msg); | ||
683 | encode_message (message, msg_length, msg_buffer, GNUNET_YES); | ||
684 | |||
685 | hash_message (message, msg_length, msg_buffer, hash); | ||
686 | sign_message (message, msg_length, msg_buffer, hash, key); | ||
687 | |||
688 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send message (%s)!\n", | ||
689 | GNUNET_h2s (hash)); | ||
690 | |||
691 | update_room_last_message (room, hash); | ||
692 | |||
693 | if (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind) | ||
694 | GNUNET_MQ_notify_sent (env, callback_leave_message_sent, room); | ||
695 | |||
696 | GNUNET_MQ_send (room->handle->mq, env); | ||
697 | } | ||
698 | |||
699 | |||
700 | static void | ||
701 | enqueue_message_to_room (struct GNUNET_MESSENGER_Room *room, | ||
702 | struct GNUNET_MESSENGER_Message *message, | ||
703 | struct GNUNET_MESSENGER_Message *transcript) | ||
704 | { | ||
705 | GNUNET_assert ((room) && (message)); | ||
706 | |||
707 | const struct GNUNET_CRYPTO_PrivateKey *key = get_handle_key (room->handle); | ||
708 | enum GNUNET_GenericReturnValue priority; | ||
709 | |||
710 | switch (message->header.kind) | ||
711 | { | ||
712 | case GNUNET_MESSENGER_KIND_JOIN: | ||
713 | priority = GNUNET_YES; | ||
714 | break; | ||
715 | default: | ||
716 | priority = GNUNET_NO; | ||
717 | break; | ||
718 | } | ||
719 | |||
720 | enqueue_to_messages (&(room->queue), key, message, transcript, priority); | ||
721 | |||
722 | if (GNUNET_YES != is_room_available (room)) | ||
723 | return; | ||
724 | |||
725 | if (GNUNET_YES == is_message_session_bound (message)) | ||
726 | send_sync_room (room->handle, room); | ||
727 | else if (GNUNET_YES != room->wait_for_sync) | ||
728 | dequeue_messages_from_room (room); | ||
729 | } | ||
730 | |||
731 | |||
732 | static enum GNUNET_GenericReturnValue | ||
733 | dequeue_messages_from_room (struct GNUNET_MESSENGER_Room *room) | ||
734 | { | ||
735 | if (GNUNET_YES != is_room_available (room)) | ||
736 | return room->queue.head ? GNUNET_NO : GNUNET_YES; | ||
737 | |||
738 | struct GNUNET_MESSENGER_Message *message = NULL; | ||
739 | struct GNUNET_MESSENGER_Message *transcript = NULL; | ||
740 | struct GNUNET_CRYPTO_PublicKey pubkey; | ||
741 | struct GNUNET_CRYPTO_PrivateKey key; | ||
742 | struct GNUNET_HashCode hash, other; | ||
743 | |||
744 | do { | ||
745 | if (message) | ||
746 | destroy_message (message); | ||
747 | |||
748 | message = dequeue_from_messages (&(room->queue), &key, &transcript); | ||
749 | |||
750 | if (! message) | ||
751 | { | ||
752 | message = transcript; | ||
753 | continue; | ||
754 | } | ||
755 | |||
756 | send_message_to_room (room, message, &key, &hash); | ||
757 | |||
758 | if (! transcript) | ||
759 | continue; | ||
760 | |||
761 | GNUNET_memcpy (&(transcript->body.transcript.hash), &hash, sizeof(hash)); | ||
762 | GNUNET_CRYPTO_key_get_public (&key, &pubkey); | ||
763 | |||
764 | if (GNUNET_YES == encrypt_message (transcript, &pubkey)) | ||
765 | { | ||
766 | send_message_to_room (room, transcript, &key, &other); | ||
767 | |||
768 | link_room_message (room, &hash, &other); | ||
769 | link_room_message (room, &other, &hash); | ||
770 | } | ||
771 | else | ||
772 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
773 | "Sending transcript aborted: Encryption failed!\n"); | ||
774 | |||
775 | destroy_message (transcript); | ||
776 | } while (message); | ||
777 | |||
778 | return GNUNET_YES; | ||
779 | } | ||
780 | |||
781 | |||
782 | const char* | ||
783 | GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle) | ||
784 | { | ||
785 | if (! handle) | ||
786 | return NULL; | ||
787 | |||
788 | return get_handle_name (handle); | ||
789 | } | ||
790 | |||
791 | |||
792 | static enum GNUNET_GenericReturnValue | ||
793 | iterate_send_name_to_room (void *cls, | ||
794 | struct GNUNET_MESSENGER_Room *room, | ||
795 | const struct GNUNET_MESSENGER_Contact *contact) | ||
796 | { | ||
797 | const struct GNUNET_MESSENGER_Handle *handle = cls; | ||
798 | |||
799 | if (GNUNET_YES != room->use_handle_name) | ||
800 | return GNUNET_YES; | ||
801 | |||
802 | const char *name = get_handle_name (handle); | ||
803 | |||
804 | if (! name) | ||
805 | return GNUNET_YES; | ||
806 | |||
807 | struct GNUNET_MESSENGER_Message *message = create_message_name (name); | ||
808 | |||
809 | if (! message) | ||
810 | return GNUNET_NO; | ||
811 | |||
812 | enqueue_message_to_room (room, message, NULL); | ||
813 | return GNUNET_YES; | ||
814 | } | ||
815 | |||
816 | |||
817 | enum GNUNET_GenericReturnValue | ||
818 | GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle, | ||
819 | const char *name) | ||
820 | { | ||
821 | if (! handle) | ||
822 | return GNUNET_SYSERR; | ||
823 | |||
824 | set_handle_name (handle, strlen (name) > 0 ? name : NULL); | ||
825 | GNUNET_MESSENGER_find_rooms (handle, NULL, iterate_send_name_to_room, handle); | ||
826 | return GNUNET_YES; | ||
827 | } | ||
828 | |||
829 | |||
830 | static const struct GNUNET_CRYPTO_PublicKey* | ||
831 | get_non_anonymous_key (const struct GNUNET_CRYPTO_PublicKey *public_key) | ||
832 | { | ||
833 | if (0 == GNUNET_memcmp (public_key, get_anonymous_public_key ())) | ||
834 | return NULL; | ||
835 | |||
836 | return public_key; | ||
837 | } | ||
838 | |||
839 | |||
840 | const struct GNUNET_CRYPTO_PublicKey* | ||
841 | GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle) | ||
842 | { | ||
843 | if (! handle) | ||
844 | return NULL; | ||
845 | |||
846 | return get_non_anonymous_key (get_handle_pubkey (handle)); | ||
847 | } | ||
848 | |||
849 | |||
850 | static enum GNUNET_GenericReturnValue | ||
851 | iterate_send_key_to_room (void *cls, | ||
852 | struct GNUNET_MESSENGER_Room *room, | ||
853 | const struct GNUNET_MESSENGER_Contact *contact) | ||
854 | { | ||
855 | const struct GNUNET_CRYPTO_PrivateKey *key = cls; | ||
856 | |||
857 | struct GNUNET_MESSENGER_Message *message = create_message_key (key); | ||
858 | |||
859 | if (! message) | ||
860 | return GNUNET_NO; | ||
861 | |||
862 | enqueue_message_to_room (room, message, NULL); | ||
863 | return GNUNET_YES; | ||
864 | } | ||
865 | |||
866 | |||
867 | enum GNUNET_GenericReturnValue | ||
868 | GNUNET_MESSENGER_set_key (struct GNUNET_MESSENGER_Handle *handle, | ||
869 | const struct GNUNET_CRYPTO_PrivateKey *key) | ||
870 | { | ||
871 | if (! handle) | ||
872 | return GNUNET_SYSERR; | ||
873 | |||
874 | if (! key) | ||
875 | { | ||
876 | GNUNET_MESSENGER_find_rooms (handle, NULL, iterate_send_key_to_room, NULL); | ||
877 | set_handle_key (handle, NULL); | ||
878 | return GNUNET_YES; | ||
879 | } | ||
880 | |||
881 | if (0 >= GNUNET_CRYPTO_private_key_get_length (key)) | ||
882 | return GNUNET_SYSERR; | ||
883 | |||
884 | struct GNUNET_CRYPTO_PrivateKey priv; | ||
885 | GNUNET_memcpy (&priv, key, sizeof (priv)); | ||
886 | |||
887 | GNUNET_MESSENGER_find_rooms (handle, NULL, iterate_send_key_to_room, &priv); | ||
888 | set_handle_key (handle, &priv); | ||
889 | return GNUNET_YES; | ||
890 | } | ||
891 | |||
892 | |||
893 | struct GNUNET_MESSENGER_Room* | ||
894 | GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, | ||
895 | const struct GNUNET_HashCode *key) | ||
896 | { | ||
897 | if ((! handle) || (! key)) | ||
898 | return NULL; | ||
899 | |||
900 | struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get ( | ||
901 | handle->rooms, key); | ||
902 | |||
903 | if (! room) | ||
904 | { | ||
905 | room = create_room (handle, key); | ||
906 | |||
907 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, | ||
908 | room, | ||
909 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
910 | { | ||
911 | destroy_room (room); | ||
912 | return NULL; | ||
913 | } | ||
914 | } | ||
915 | |||
916 | send_open_room (handle, room); | ||
917 | return room; | ||
918 | } | ||
919 | |||
920 | |||
921 | struct GNUNET_MESSENGER_Room* | ||
922 | GNUNET_MESSENGER_enter_room (struct GNUNET_MESSENGER_Handle *handle, | ||
923 | const struct GNUNET_PeerIdentity *door, | ||
924 | const struct GNUNET_HashCode *key) | ||
925 | { | ||
926 | if ((! handle) || (! door) || (! key)) | ||
927 | return NULL; | ||
928 | |||
929 | struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get ( | ||
930 | handle->rooms, key); | ||
931 | |||
932 | if (! room) | ||
933 | { | ||
934 | room = create_room (handle, key); | ||
935 | |||
936 | if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, | ||
937 | room, | ||
938 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) | ||
939 | { | ||
940 | destroy_room (room); | ||
941 | return NULL; | ||
942 | } | ||
943 | } | ||
944 | |||
945 | send_enter_room (handle, room, door); | ||
946 | return room; | ||
947 | } | ||
948 | |||
949 | |||
950 | void | ||
951 | GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room) | ||
952 | { | ||
953 | if (! room) | ||
954 | return; | ||
955 | |||
956 | struct GNUNET_MESSENGER_Message *message = create_message_leave (); | ||
957 | |||
958 | if (! message) | ||
959 | return; | ||
960 | |||
961 | enqueue_message_to_room (room, message, NULL); | ||
962 | } | ||
963 | |||
964 | |||
965 | struct GNUNET_MESSENGER_RoomFind | ||
966 | { | ||
967 | const struct GNUNET_MESSENGER_Contact *contact; | ||
968 | GNUNET_MESSENGER_MemberCallback callback; | ||
969 | size_t counter; | ||
970 | void *cls; | ||
971 | }; | ||
972 | |||
973 | static enum GNUNET_GenericReturnValue | ||
974 | iterate_find_room (void *cls, | ||
975 | const struct GNUNET_HashCode *key, | ||
976 | void *value) | ||
977 | { | ||
978 | struct GNUNET_MESSENGER_RoomFind *find = cls; | ||
979 | struct GNUNET_MESSENGER_Room *room = value; | ||
980 | |||
981 | if ((find->counter > 0) && ((! find->contact) || (GNUNET_YES == | ||
982 | find_room_member (room, | ||
983 | find-> | ||
984 | contact))) | ||
985 | ) | ||
986 | { | ||
987 | find->counter--; | ||
988 | |||
989 | if (! find->callback) | ||
990 | return GNUNET_YES; | ||
991 | |||
992 | return find->callback (find->cls, room, find->contact); | ||
993 | } | ||
994 | else | ||
995 | return GNUNET_NO; | ||
996 | } | ||
997 | |||
998 | |||
999 | int | ||
1000 | GNUNET_MESSENGER_find_rooms (const struct GNUNET_MESSENGER_Handle *handle, | ||
1001 | const struct GNUNET_MESSENGER_Contact *contact, | ||
1002 | GNUNET_MESSENGER_MemberCallback callback, | ||
1003 | void *cls) | ||
1004 | { | ||
1005 | if (! handle) | ||
1006 | return GNUNET_SYSERR; | ||
1007 | |||
1008 | struct GNUNET_MESSENGER_RoomFind find; | ||
1009 | |||
1010 | find.contact = contact; | ||
1011 | find.callback = callback; | ||
1012 | find.counter = (contact? contact->rc : SIZE_MAX); | ||
1013 | find.cls = cls; | ||
1014 | |||
1015 | return GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, | ||
1016 | iterate_find_room, &find); | ||
1017 | } | ||
1018 | |||
1019 | |||
1020 | const struct GNUNET_HashCode* | ||
1021 | GNUNET_MESSENGER_room_get_key (const struct GNUNET_MESSENGER_Room *room) | ||
1022 | { | ||
1023 | if (! room) | ||
1024 | return NULL; | ||
1025 | |||
1026 | return &(room->key); | ||
1027 | } | ||
1028 | |||
1029 | |||
1030 | const struct GNUNET_MESSENGER_Contact* | ||
1031 | GNUNET_MESSENGER_get_sender (const struct GNUNET_MESSENGER_Room *room, | ||
1032 | const struct GNUNET_HashCode *hash) | ||
1033 | { | ||
1034 | if ((! room) || (! hash)) | ||
1035 | return NULL; | ||
1036 | |||
1037 | return get_room_sender (room, hash); | ||
1038 | } | ||
1039 | |||
1040 | |||
1041 | const struct GNUNET_MESSENGER_Contact* | ||
1042 | GNUNET_MESSENGER_get_recipient (const struct GNUNET_MESSENGER_Room *room, | ||
1043 | const struct GNUNET_HashCode *hash) | ||
1044 | { | ||
1045 | if ((! room) || (! hash)) | ||
1046 | return NULL; | ||
1047 | |||
1048 | return get_room_recipient (room, hash); | ||
1049 | } | ||
1050 | |||
1051 | |||
1052 | const char* | ||
1053 | GNUNET_MESSENGER_contact_get_name (const struct | ||
1054 | GNUNET_MESSENGER_Contact *contact) | ||
1055 | { | ||
1056 | if (! contact) | ||
1057 | return NULL; | ||
1058 | |||
1059 | return get_contact_name (contact); | ||
1060 | } | ||
1061 | |||
1062 | |||
1063 | const struct GNUNET_CRYPTO_PublicKey* | ||
1064 | GNUNET_MESSENGER_contact_get_key (const struct | ||
1065 | GNUNET_MESSENGER_Contact *contact) | ||
1066 | { | ||
1067 | if (! contact) | ||
1068 | return NULL; | ||
1069 | |||
1070 | return get_non_anonymous_key (get_contact_key (contact)); | ||
1071 | } | ||
1072 | |||
1073 | |||
1074 | size_t | ||
1075 | GNUNET_MESSENGER_contact_get_id (const struct | ||
1076 | GNUNET_MESSENGER_Contact *contact) | ||
1077 | { | ||
1078 | if (! contact) | ||
1079 | return 0; | ||
1080 | |||
1081 | return get_contact_id (contact); | ||
1082 | } | ||
1083 | |||
1084 | |||
1085 | static void | ||
1086 | send_message_to_room_with_key (struct GNUNET_MESSENGER_Room *room, | ||
1087 | struct GNUNET_MESSENGER_Message *message, | ||
1088 | const struct GNUNET_CRYPTO_PublicKey *public_key) | ||
1089 | { | ||
1090 | struct GNUNET_MESSENGER_Message *transcript = NULL; | ||
1091 | const struct GNUNET_CRYPTO_PublicKey *pubkey; | ||
1092 | |||
1093 | char *original_name; | ||
1094 | |||
1095 | if (GNUNET_MESSENGER_KIND_NAME != message->header.kind) | ||
1096 | goto skip_naming; | ||
1097 | |||
1098 | original_name = message->body.name.name; | ||
1099 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1100 | "Apply rule for using handle name in room: %s\n", GNUNET_h2s ( | ||
1101 | &(room->key))); | ||
1102 | |||
1103 | const char *handle_name = get_handle_name (room->handle); | ||
1104 | |||
1105 | if ((handle_name) && (GNUNET_YES == room->use_handle_name) && | ||
1106 | ((! original_name) || (0 == strlen (original_name)))) | ||
1107 | { | ||
1108 | if (original_name) | ||
1109 | GNUNET_free (original_name); | ||
1110 | |||
1111 | message->body.name.name = GNUNET_strdup (handle_name); | ||
1112 | } | ||
1113 | |||
1114 | skip_naming: | ||
1115 | if (! public_key) | ||
1116 | goto skip_encryption; | ||
1117 | |||
1118 | pubkey = get_handle_pubkey (room->handle); | ||
1119 | |||
1120 | if (0 != GNUNET_memcmp (pubkey, public_key)) | ||
1121 | transcript = transcribe_message (message, public_key); | ||
1122 | |||
1123 | if (GNUNET_YES != encrypt_message (message, public_key)) | ||
1124 | { | ||
1125 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1126 | "Sending message aborted: Encryption failed!\n"); | ||
1127 | |||
1128 | if (transcript) | ||
1129 | destroy_message (transcript); | ||
1130 | |||
1131 | destroy_message (message); | ||
1132 | return; | ||
1133 | } | ||
1134 | |||
1135 | skip_encryption: | ||
1136 | enqueue_message_to_room (room, message, transcript); | ||
1137 | } | ||
1138 | |||
1139 | |||
1140 | void | ||
1141 | GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, | ||
1142 | const struct GNUNET_MESSENGER_Message *message, | ||
1143 | const struct GNUNET_MESSENGER_Contact *contact) | ||
1144 | { | ||
1145 | if ((! room) || (! message)) | ||
1146 | return; | ||
1147 | |||
1148 | switch (filter_message_sending (message)) | ||
1149 | { | ||
1150 | case GNUNET_SYSERR: | ||
1151 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1152 | "Sending message aborted: This kind of message is reserved for the service!\n"); | ||
1153 | return; | ||
1154 | case GNUNET_NO: | ||
1155 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1156 | "Sending message aborted: This kind of message could cause issues!\n"); | ||
1157 | return; | ||
1158 | default: | ||
1159 | break; | ||
1160 | } | ||
1161 | |||
1162 | const struct GNUNET_CRYPTO_PublicKey *public_key; | ||
1163 | |||
1164 | if (contact) | ||
1165 | { | ||
1166 | public_key = get_non_anonymous_key ( | ||
1167 | get_contact_key (contact) | ||
1168 | ); | ||
1169 | |||
1170 | if (! public_key) | ||
1171 | { | ||
1172 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1173 | "Sending message aborted: Invalid key!\n"); | ||
1174 | return; | ||
1175 | } | ||
1176 | } | ||
1177 | else | ||
1178 | public_key = NULL; | ||
1179 | |||
1180 | send_message_to_room_with_key (room, copy_message (message), public_key); | ||
1181 | } | ||
1182 | |||
1183 | |||
1184 | void | ||
1185 | delete_message_in_room (struct GNUNET_MESSENGER_Room *room, | ||
1186 | const struct GNUNET_HashCode *hash, | ||
1187 | const struct GNUNET_TIME_Relative delay) | ||
1188 | { | ||
1189 | struct GNUNET_MESSENGER_Message *message = create_message_delete (hash, | ||
1190 | delay); | ||
1191 | |||
1192 | if (! message) | ||
1193 | { | ||
1194 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | ||
1195 | "Sending deletion aborted: Message creation failed!\n"); | ||
1196 | return; | ||
1197 | } | ||
1198 | |||
1199 | send_message_to_room_with_key (room, message, NULL); | ||
1200 | } | ||
1201 | |||
1202 | |||
1203 | void | ||
1204 | GNUNET_MESSENGER_delete_message (struct GNUNET_MESSENGER_Room *room, | ||
1205 | const struct GNUNET_HashCode *hash, | ||
1206 | const struct GNUNET_TIME_Relative delay) | ||
1207 | { | ||
1208 | if ((! room) || (! hash)) | ||
1209 | return; | ||
1210 | |||
1211 | delete_message_in_room (room, hash, delay); | ||
1212 | } | ||
1213 | |||
1214 | |||
1215 | const struct GNUNET_MESSENGER_Message* | ||
1216 | GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, | ||
1217 | const struct GNUNET_HashCode *hash) | ||
1218 | { | ||
1219 | if ((! room) || (! hash)) | ||
1220 | return NULL; | ||
1221 | |||
1222 | const struct GNUNET_MESSENGER_Message *message = get_room_message (room, | ||
1223 | hash); | ||
1224 | |||
1225 | if (! message) | ||
1226 | { | ||
1227 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request message (%s)!\n", | ||
1228 | GNUNET_h2s (hash)); | ||
1229 | |||
1230 | struct GNUNET_MESSENGER_GetMessage *msg; | ||
1231 | struct GNUNET_MQ_Envelope *env; | ||
1232 | |||
1233 | env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE); | ||
1234 | GNUNET_memcpy (&(msg->key), &(room->key), sizeof(msg->key)); | ||
1235 | GNUNET_memcpy (&(msg->hash), hash, sizeof(*hash)); | ||
1236 | GNUNET_MQ_send (room->handle->mq, env); | ||
1237 | } | ||
1238 | |||
1239 | return message; | ||
1240 | } | ||
1241 | |||
1242 | |||
1243 | int | ||
1244 | GNUNET_MESSENGER_iterate_members (struct GNUNET_MESSENGER_Room *room, | ||
1245 | GNUNET_MESSENGER_MemberCallback callback, | ||
1246 | void *cls) | ||
1247 | { | ||
1248 | if (! room) | ||
1249 | return GNUNET_SYSERR; | ||
1250 | |||
1251 | return iterate_room_members (room, callback, cls); | ||
1252 | } | ||