aboutsummaryrefslogtreecommitdiff
path: root/src/service/messenger/messenger_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/messenger/messenger_api.c')
-rw-r--r--src/service/messenger/messenger_api.c1252
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
42const char*
43GNUNET_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
91static enum GNUNET_GenericReturnValue
92dequeue_messages_from_room (struct GNUNET_MESSENGER_Room *room);
93
94static void
95handle_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
118static void
119handle_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
143static void
144handle_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
163static void
164handle_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
185static void
186enqueue_message_to_room (struct GNUNET_MESSENGER_Room *room,
187 struct GNUNET_MESSENGER_Message *message,
188 struct GNUNET_MESSENGER_Message *transcript);
189
190static void
191handle_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
228static enum GNUNET_GenericReturnValue
229check_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
266static void
267handle_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
310skip_message:
311 cleanup_message (&message);
312}
313
314
315static void
316handle_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
347static void
348reconnect (struct GNUNET_MESSENGER_Handle *handle);
349
350static void
351send_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
381static void
382send_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
414static void
415send_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
434static void
435send_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
456static enum GNUNET_GenericReturnValue
457iterate_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
484static void
485callback_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
501static enum GNUNET_GenericReturnValue
502iterate_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
515static void
516callback_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
538static void
539reconnect (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
586struct GNUNET_MESSENGER_Handle*
587GNUNET_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
622void
623GNUNET_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
640static void
641callback_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
652static void
653send_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
700static void
701enqueue_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
732static enum GNUNET_GenericReturnValue
733dequeue_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
782const char*
783GNUNET_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
792static enum GNUNET_GenericReturnValue
793iterate_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
817enum GNUNET_GenericReturnValue
818GNUNET_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
830static const struct GNUNET_CRYPTO_PublicKey*
831get_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
840const struct GNUNET_CRYPTO_PublicKey*
841GNUNET_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
850static enum GNUNET_GenericReturnValue
851iterate_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
867enum GNUNET_GenericReturnValue
868GNUNET_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
893struct GNUNET_MESSENGER_Room*
894GNUNET_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
921struct GNUNET_MESSENGER_Room*
922GNUNET_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
950void
951GNUNET_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
965struct 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
973static enum GNUNET_GenericReturnValue
974iterate_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
999int
1000GNUNET_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
1020const struct GNUNET_HashCode*
1021GNUNET_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
1030const struct GNUNET_MESSENGER_Contact*
1031GNUNET_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
1041const struct GNUNET_MESSENGER_Contact*
1042GNUNET_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
1052const char*
1053GNUNET_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
1063const struct GNUNET_CRYPTO_PublicKey*
1064GNUNET_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
1074size_t
1075GNUNET_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
1085static void
1086send_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
1114skip_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
1135skip_encryption:
1136 enqueue_message_to_room (room, message, transcript);
1137}
1138
1139
1140void
1141GNUNET_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
1184void
1185delete_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
1203void
1204GNUNET_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
1215const struct GNUNET_MESSENGER_Message*
1216GNUNET_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
1243int
1244GNUNET_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}