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.c1075
1 files changed, 1075 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..a5b2d7687
--- /dev/null
+++ b/src/service/messenger/messenger_api.c
@@ -0,0 +1,1075 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2023 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 "platform.h"
27#include "gnunet_identity_service.h"
28#include "gnunet_messenger_service.h"
29
30#include "gnunet-service-messenger.h"
31
32#include "messenger_api_handle.h"
33#include "messenger_api_message.h"
34#include "messenger_api_message_kind.h"
35#include "messenger_api_room.h"
36#include "messenger_api_util.h"
37
38const char*
39GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind)
40{
41 switch (kind)
42 {
43 case GNUNET_MESSENGER_KIND_INFO:
44 return "INFO";
45 case GNUNET_MESSENGER_KIND_JOIN:
46 return "JOIN";
47 case GNUNET_MESSENGER_KIND_LEAVE:
48 return "LEAVE";
49 case GNUNET_MESSENGER_KIND_NAME:
50 return "NAME";
51 case GNUNET_MESSENGER_KIND_KEY:
52 return "KEY";
53 case GNUNET_MESSENGER_KIND_PEER:
54 return "PEER";
55 case GNUNET_MESSENGER_KIND_ID:
56 return "ID";
57 case GNUNET_MESSENGER_KIND_MISS:
58 return "MISS";
59 case GNUNET_MESSENGER_KIND_MERGE:
60 return "MERGE";
61 case GNUNET_MESSENGER_KIND_REQUEST:
62 return "REQUEST";
63 case GNUNET_MESSENGER_KIND_INVITE:
64 return "INVITE";
65 case GNUNET_MESSENGER_KIND_TEXT:
66 return "TEXT";
67 case GNUNET_MESSENGER_KIND_FILE:
68 return "FILE";
69 case GNUNET_MESSENGER_KIND_PRIVATE:
70 return "PRIVATE";
71 case GNUNET_MESSENGER_KIND_DELETE:
72 return "DELETE";
73 default:
74 return "UNKNOWN";
75 }
76}
77
78
79static enum GNUNET_GenericReturnValue
80dequeue_messages_from_room (struct GNUNET_MESSENGER_Room *room);
81
82static void
83handle_room_open (void *cls,
84 const struct GNUNET_MESSENGER_RoomMessage *msg)
85{
86 struct GNUNET_MESSENGER_Handle *handle = cls;
87
88 const struct GNUNET_HashCode *key = &(msg->key);
89
90 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opened room: %s\n", GNUNET_h2s (key));
91
92 open_handle_room (handle, key);
93
94 struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
95
96 if (room)
97 dequeue_messages_from_room (room);
98}
99
100
101static void
102handle_room_entry (void *cls,
103 const struct GNUNET_MESSENGER_RoomMessage *msg)
104{
105 struct GNUNET_MESSENGER_Handle *handle = cls;
106
107 const struct GNUNET_PeerIdentity *door = &(msg->door);
108 const struct GNUNET_HashCode *key = &(msg->key);
109
110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Entered room: %s\n", GNUNET_h2s (key));
111
112 entry_handle_room_at (handle, door, key);
113
114 struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
115
116 if (room)
117 dequeue_messages_from_room (room);
118}
119
120
121static void
122handle_room_close (void *cls,
123 const struct GNUNET_MESSENGER_RoomMessage *msg)
124{
125 struct GNUNET_MESSENGER_Handle *handle = cls;
126
127 const struct GNUNET_HashCode *key = &(msg->key);
128
129 struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
130
131 if (room)
132 dequeue_messages_from_room (room);
133
134 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key));
135
136 close_handle_room (handle, key);
137}
138
139
140static void
141enqueue_message_to_room (struct GNUNET_MESSENGER_Room *room,
142 struct GNUNET_MESSENGER_Message *message);
143
144static void
145handle_member_id (void *cls,
146 const struct GNUNET_MESSENGER_MemberMessage *msg)
147{
148 struct GNUNET_MESSENGER_Handle *handle = cls;
149
150 const struct GNUNET_HashCode *key = &(msg->key);
151 const struct GNUNET_ShortHashCode *id = &(msg->id);
152 const uint32_t reset = msg->reset;
153
154 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Changed member id in room: %s\n",
155 GNUNET_h2s (key));
156
157 struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
158
159 if (! room)
160 {
161 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Room is unknown to handle: %s\n",
162 GNUNET_h2s (key));
163 return;
164 }
165
166 struct GNUNET_MESSENGER_Message *message;
167 switch (reset)
168 {
169 case GNUNET_YES:
170 set_room_sender_id (room, id);
171 message = create_message_join (get_handle_key (handle));
172 break;
173 case GNUNET_NO:
174 message = create_message_id (id);
175 break;
176 default:
177 break;
178 }
179
180 if (! message)
181 return;
182
183 enqueue_message_to_room (room, message);
184 destroy_message (message);
185}
186
187
188static int
189check_recv_message (void *cls,
190 const struct GNUNET_MESSENGER_RecvMessage *msg)
191{
192 const uint16_t full_length = ntohs (msg->header.size);
193
194 if (full_length < sizeof(*msg))
195 {
196 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
197 "Receiving failed: Message invalid!\n");
198 return GNUNET_NO;
199 }
200
201 const uint16_t length = full_length - sizeof(*msg);
202 const char *buffer = ((const char*) msg) + sizeof(*msg);
203
204 struct GNUNET_MESSENGER_Message message;
205
206 if (length < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN,
207 GNUNET_YES))
208 {
209 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
210 "Receiving failed: Message too short!\n");
211 return GNUNET_NO;
212 }
213
214 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, NULL))
215 {
216 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
217 "Receiving failed: Message decoding failed!\n");
218 return GNUNET_NO;
219 }
220
221 cleanup_message (&message);
222 return GNUNET_OK;
223}
224
225
226static void
227handle_recv_message (void *cls,
228 const struct GNUNET_MESSENGER_RecvMessage *msg)
229{
230 struct GNUNET_MESSENGER_Handle *handle = cls;
231
232 const struct GNUNET_HashCode *key = &(msg->key);
233 const struct GNUNET_HashCode *sender = &(msg->sender);
234 const struct GNUNET_HashCode *context = &(msg->context);
235 const struct GNUNET_HashCode *hash = &(msg->hash);
236
237 enum GNUNET_MESSENGER_MessageFlags flags = (
238 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
239 );
240
241 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
242 const char *buffer = ((const char*) msg) + sizeof(*msg);
243
244 struct GNUNET_MESSENGER_Message message;
245 decode_message (&message, length, buffer, GNUNET_YES, NULL);
246
247 struct GNUNET_MESSENGER_Message *private_message = NULL;
248 if (GNUNET_MESSENGER_KIND_PRIVATE == message.header.kind)
249 {
250 private_message = copy_message (&message);
251
252 if (GNUNET_YES != decrypt_message (private_message, get_handle_key (
253 handle)))
254 {
255 destroy_message (private_message);
256 private_message = NULL;
257 }
258 }
259
260 if (private_message)
261 flags |= GNUNET_MESSENGER_FLAG_PRIVATE;
262
263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n",
264 GNUNET_MESSENGER_name_of_kind (private_message ?
265 private_message->header.kind :
266 message.header.kind));
267
268 struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
269
270 if (room)
271 {
272 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store (
273 handle);
274
275 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
276 "Raw contact from sender and context: (%s : %s)\n",
277 GNUNET_h2s (sender), GNUNET_h2s_full (context));
278
279 struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw (
280 store, context, sender
281 );
282
283 contact = handle_room_message (room, contact, private_message ?
284 private_message : &message, hash, flags);
285
286 const struct GNUNET_MESSENGER_Message *stored_message = get_room_message (
287 room, hash);
288
289 if (handle->msg_callback)
290 handle->msg_callback (handle->msg_cls, room, contact, stored_message,
291 hash, flags);
292 }
293 else
294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unknown room for this client: %s\n",
295 GNUNET_h2s (key));
296
297 cleanup_message (&message);
298
299 if (private_message)
300 destroy_message (private_message);
301}
302
303
304static void
305handle_miss_message (void *cls,
306 const struct GNUNET_MESSENGER_GetMessage *msg)
307{
308 struct GNUNET_MESSENGER_Handle *handle = cls;
309
310 const struct GNUNET_HashCode *key = &(msg->key);
311 const struct GNUNET_HashCode *hash = &(msg->hash);
312
313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Missing message in room: %s\n",
314 GNUNET_h2s (hash));
315
316 struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
317
318 if (! room)
319 {
320 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
321 "Miss in unknown room for this client: %s\n", GNUNET_h2s (key));
322 return;
323 }
324
325 if (! get_room_sender_id (room))
326 return;
327
328 struct GNUNET_MESSENGER_Message *message = create_message_request (hash);
329 if (! message)
330 return;
331
332 enqueue_message_to_room (room, message);
333 destroy_message (message);
334}
335
336
337static void
338reconnect (struct GNUNET_MESSENGER_Handle *handle);
339
340static void
341send_open_room (struct GNUNET_MESSENGER_Handle *handle,
342 struct GNUNET_MESSENGER_Room *room)
343{
344 const struct GNUNET_CRYPTO_PublicKey *key = get_handle_pubkey (handle);
345
346 struct GNUNET_MESSENGER_RoomMessage *msg;
347 struct GNUNET_MQ_Envelope *env;
348
349 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
350 "Open room (%s) by member using key: %s\n",
351 GNUNET_h2s (&(room->key)),
352 GNUNET_CRYPTO_public_key_to_string (key));
353
354 const ssize_t len = GNUNET_CRYPTO_public_key_get_length (key);
355
356 env = GNUNET_MQ_msg_extra (msg, len > 0 ? len : 0,
357 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
358 GNUNET_memcpy (&(msg->key), &(room->key), sizeof(msg->key));
359
360 char *msg_buffer = ((char*) msg) + sizeof(*msg);
361
362 if (len > 0)
363 GNUNET_CRYPTO_write_public_key_to_buffer (key, msg_buffer, len);
364
365 GNUNET_MQ_send (handle->mq, env);
366}
367
368
369static void
370send_enter_room (struct GNUNET_MESSENGER_Handle *handle,
371 struct GNUNET_MESSENGER_Room *room,
372 const struct GNUNET_PeerIdentity *door)
373{
374 const struct GNUNET_CRYPTO_PublicKey *key = get_handle_pubkey (handle);
375
376 struct GNUNET_MESSENGER_RoomMessage *msg;
377 struct GNUNET_MQ_Envelope *env;
378
379 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Enter room (%s) via door: %s (%s)\n",
380 GNUNET_h2s (&(room->key)),
381 GNUNET_i2s (door),
382 GNUNET_CRYPTO_public_key_to_string (key));
383
384 const ssize_t len = GNUNET_CRYPTO_public_key_get_length (key);
385
386 env = GNUNET_MQ_msg_extra (msg, len > 0 ? len : 0,
387 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
388 GNUNET_memcpy (&(msg->door), door, sizeof(*door));
389 GNUNET_memcpy (&(msg->key), &(room->key), sizeof(msg->key));
390
391 char *msg_buffer = ((char*) msg) + sizeof(*msg);
392
393 if (len > 0)
394 GNUNET_CRYPTO_write_public_key_to_buffer (key, msg_buffer, len);
395
396 GNUNET_MQ_send (handle->mq, env);
397}
398
399
400static void
401send_close_room (struct GNUNET_MESSENGER_Handle *handle,
402 struct GNUNET_MESSENGER_Room *room)
403{
404 struct GNUNET_MESSENGER_RoomMessage *msg;
405 struct GNUNET_MQ_Envelope *env;
406
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Close room (%s)!\n",
408 GNUNET_h2s (&(room->key)));
409
410 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
411 GNUNET_memcpy (&(msg->key), &(room->key), sizeof(msg->key));
412 GNUNET_MQ_send (handle->mq, env);
413}
414
415
416static int
417iterate_reset_room (void *cls,
418 const struct GNUNET_HashCode *key,
419 void *value)
420{
421 struct GNUNET_MESSENGER_Handle *handle = cls;
422 struct GNUNET_MESSENGER_Room *room = value;
423
424 if (GNUNET_YES == room->opened)
425 send_open_room (handle, room);
426
427 struct GNUNET_MESSENGER_ListTunnel *entry = room->entries.head;
428
429 struct GNUNET_PeerIdentity door;
430
431 while (entry)
432 {
433 GNUNET_PEER_resolve (entry->peer, &door);
434
435 send_enter_room (handle, room, &door);
436
437 entry = entry->next;
438 }
439
440 return GNUNET_YES;
441}
442
443
444static void
445callback_reconnect (void *cls)
446{
447 struct GNUNET_MESSENGER_Handle *handle = cls;
448
449 handle->reconnect_task = NULL;
450 handle->reconnect_time = GNUNET_TIME_STD_BACKOFF (handle->reconnect_time);
451
452 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnect messenger!\n");
453
454 reconnect (handle);
455
456 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_reset_room,
457 handle);
458}
459
460
461static int
462iterate_close_room (void *cls,
463 const struct GNUNET_HashCode *key,
464 void *value)
465{
466 struct GNUNET_MESSENGER_Handle *handle = cls;
467 struct GNUNET_MESSENGER_Room *room = value;
468
469 send_close_room (handle, room);
470
471 return GNUNET_YES;
472}
473
474
475static void
476callback_mq_error (void *cls,
477 enum GNUNET_MQ_Error error)
478{
479 struct GNUNET_MESSENGER_Handle *handle = cls;
480
481 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MQ_Error: %u\n", error);
482
483 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room,
484 handle);
485
486 if (handle->mq)
487 {
488 GNUNET_MQ_destroy (handle->mq);
489 handle->mq = NULL;
490 }
491
492 handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_time,
493 &callback_reconnect,
494 handle);
495}
496
497
498static void
499reconnect (struct GNUNET_MESSENGER_Handle *handle)
500{
501 const struct GNUNET_MQ_MessageHandler handlers[] = {
502 GNUNET_MQ_hd_fixed_size (
503 member_id,
504 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID,
505 struct GNUNET_MESSENGER_MemberMessage, handle
506 ),
507 GNUNET_MQ_hd_fixed_size (
508 room_open,
509 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN,
510 struct GNUNET_MESSENGER_RoomMessage, handle
511 ),
512 GNUNET_MQ_hd_fixed_size (
513 room_entry,
514 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY,
515 struct GNUNET_MESSENGER_RoomMessage, handle
516 ),
517 GNUNET_MQ_hd_fixed_size (
518 room_close,
519 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE,
520 struct GNUNET_MESSENGER_RoomMessage, handle
521 ),
522 GNUNET_MQ_hd_var_size (
523 recv_message,
524 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE,
525 struct GNUNET_MESSENGER_RecvMessage, handle
526 ),
527 GNUNET_MQ_hd_fixed_size (
528 miss_message,
529 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE,
530 struct GNUNET_MESSENGER_GetMessage, handle
531 ),
532 GNUNET_MQ_handler_end ()
533 };
534
535 handle->mq = GNUNET_CLIENT_connect (handle->cfg,
536 GNUNET_MESSENGER_SERVICE_NAME, handlers,
537 &callback_mq_error, handle);
538}
539
540
541struct GNUNET_MESSENGER_Handle*
542GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
543 const char *name,
544 const struct GNUNET_CRYPTO_PrivateKey *key,
545 GNUNET_MESSENGER_MessageCallback msg_callback,
546 void *msg_cls)
547{
548 struct GNUNET_MESSENGER_Handle *handle = create_handle (cfg, msg_callback,
549 msg_cls);
550
551 reconnect (handle);
552
553 if (handle->mq)
554 {
555 set_handle_name (handle, name);
556
557 if ((! key) || (0 < GNUNET_CRYPTO_private_key_get_length (key)))
558 set_handle_key (handle, key);
559
560 struct GNUNET_MESSENGER_CreateMessage *msg;
561 struct GNUNET_MQ_Envelope *env;
562
563 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE);
564 GNUNET_MQ_send (handle->mq, env);
565 return handle;
566 }
567 else
568 {
569 destroy_handle (handle);
570 return NULL;
571 }
572}
573
574
575void
576GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle)
577{
578 if (! handle)
579 return;
580
581 struct GNUNET_MESSENGER_DestroyMessage *msg;
582 struct GNUNET_MQ_Envelope *env;
583
584 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY);
585 GNUNET_MQ_send (handle->mq, env);
586
587 destroy_handle (handle);
588}
589
590
591static void
592send_message_to_room (struct GNUNET_MESSENGER_Room *room,
593 struct GNUNET_MESSENGER_Message *message,
594 const struct GNUNET_CRYPTO_PrivateKey *key)
595{
596 const struct GNUNET_ShortHashCode *sender_id = get_room_sender_id (room);
597
598 message->header.timestamp = GNUNET_TIME_absolute_hton (
599 GNUNET_TIME_absolute_get ());
600
601 GNUNET_memcpy (&(message->header.sender_id), sender_id,
602 sizeof(message->header.sender_id));
603 GNUNET_memcpy (&(message->header.previous), &(room->last_message),
604 sizeof(message->header.previous));
605
606 message->header.signature.type = key->type;
607
608 const uint16_t msg_length = get_message_size (message, GNUNET_YES);
609
610 struct GNUNET_MESSENGER_SendMessage *msg;
611 struct GNUNET_MQ_Envelope *env;
612
613 env = GNUNET_MQ_msg_extra (
614 msg, msg_length,
615 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE
616 );
617
618 GNUNET_memcpy (&(msg->key), &(room->key), sizeof(msg->key));
619
620 char *msg_buffer = ((char*) msg) + sizeof(*msg);
621 encode_message (message, msg_length, msg_buffer, GNUNET_YES);
622
623 struct GNUNET_HashCode hash;
624 hash_message (message, msg_length, msg_buffer, &hash);
625 sign_message (message, msg_length, msg_buffer, &hash, key);
626
627 GNUNET_memcpy (&(room->last_message), &hash, sizeof(room->last_message));
628
629 GNUNET_MQ_send (room->handle->mq, env);
630}
631
632
633static void
634enqueue_message_to_room (struct GNUNET_MESSENGER_Room *room,
635 struct GNUNET_MESSENGER_Message *message)
636{
637 const struct GNUNET_CRYPTO_PrivateKey *key = get_handle_key (room->handle);
638
639 if (GNUNET_YES == is_room_available (room))
640 {
641 send_message_to_room (room, message, key);
642 dequeue_messages_from_room (room);
643 }
644 else
645 enqueue_to_messages (&(room->queue), key, message);
646}
647
648
649static enum GNUNET_GenericReturnValue
650dequeue_messages_from_room (struct GNUNET_MESSENGER_Room *room)
651{
652 struct GNUNET_MESSENGER_Message *message = NULL;
653 struct GNUNET_CRYPTO_PrivateKey key;
654
655 if (GNUNET_YES != is_room_available (room))
656 return room->queue.head ? GNUNET_NO : GNUNET_YES;
657
658 do {
659 if (message)
660 destroy_message (message);
661
662 message = dequeue_from_messages (&(room->queue), &key);
663
664 if (message)
665 send_message_to_room (room, message, &key);
666 } while (message);
667
668 return GNUNET_YES;
669}
670
671
672const char*
673GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle)
674{
675 if (! handle)
676 return NULL;
677
678 return get_handle_name (handle);
679}
680
681
682static int
683iterate_send_name_to_room (void *cls,
684 struct GNUNET_MESSENGER_Room *room,
685 const struct GNUNET_MESSENGER_Contact *contact)
686{
687 const struct GNUNET_MESSENGER_Handle *handle = cls;
688
689 if (GNUNET_YES != room->use_handle_name)
690 return GNUNET_YES;
691
692 const char *name = get_handle_name (handle);
693
694 if (! name)
695 return GNUNET_YES;
696
697 struct GNUNET_MESSENGER_Message *message = create_message_name (name);
698
699 if (! message)
700 return GNUNET_NO;
701
702 enqueue_message_to_room (room, message);
703 destroy_message (message);
704 return GNUNET_YES;
705}
706
707
708int
709GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle,
710 const char *name)
711{
712 if (! handle)
713 return GNUNET_SYSERR;
714
715 set_handle_name (handle, strlen (name) > 0 ? name : NULL);
716 GNUNET_MESSENGER_find_rooms (handle, NULL, iterate_send_name_to_room, handle);
717 return GNUNET_YES;
718}
719
720
721static const struct GNUNET_CRYPTO_PublicKey*
722get_non_anonymous_key (const struct GNUNET_CRYPTO_PublicKey *public_key)
723{
724 if (0 == GNUNET_memcmp (public_key, get_anonymous_public_key ()))
725 return NULL;
726
727 return public_key;
728}
729
730
731const struct GNUNET_CRYPTO_PublicKey*
732GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle)
733{
734 if (! handle)
735 return NULL;
736
737 return get_non_anonymous_key (get_handle_pubkey (handle));
738}
739
740
741static int
742iterate_send_key_to_room (void *cls,
743 struct GNUNET_MESSENGER_Room *room,
744 const struct GNUNET_MESSENGER_Contact *contact)
745{
746 const struct GNUNET_CRYPTO_PrivateKey *key = cls;
747
748 struct GNUNET_MESSENGER_Message *message = create_message_key (key);
749
750 if (! message)
751 return GNUNET_NO;
752
753 enqueue_message_to_room (room, message);
754 destroy_message (message);
755 return GNUNET_YES;
756}
757
758
759int
760GNUNET_MESSENGER_set_key (struct GNUNET_MESSENGER_Handle *handle,
761 const struct GNUNET_CRYPTO_PrivateKey *key)
762{
763 if (! handle)
764 return GNUNET_SYSERR;
765
766 if (! key)
767 {
768 GNUNET_MESSENGER_find_rooms (handle, NULL, iterate_send_key_to_room, NULL);
769 set_handle_key (handle, NULL);
770 return GNUNET_YES;
771 }
772
773 if (0 >= GNUNET_CRYPTO_private_key_get_length (key))
774 return GNUNET_SYSERR;
775
776 struct GNUNET_CRYPTO_PrivateKey priv;
777 GNUNET_memcpy (&priv, key, sizeof (priv));
778
779 GNUNET_MESSENGER_find_rooms (handle, NULL, iterate_send_key_to_room, &priv);
780 set_handle_key (handle, &priv);
781 return GNUNET_YES;
782}
783
784
785struct GNUNET_MESSENGER_Room*
786GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle,
787 const struct GNUNET_HashCode *key)
788{
789 if ((! handle) || (! key))
790 return NULL;
791
792 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (
793 handle->rooms, key);
794
795 if (! room)
796 {
797 room = create_room (handle, key);
798
799 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key,
800 room,
801 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
802 {
803 destroy_room (room);
804 return NULL;
805 }
806 }
807
808 send_open_room (handle, room);
809 return room;
810}
811
812
813struct GNUNET_MESSENGER_Room*
814GNUNET_MESSENGER_enter_room (struct GNUNET_MESSENGER_Handle *handle,
815 const struct GNUNET_PeerIdentity *door,
816 const struct GNUNET_HashCode *key)
817{
818 if ((! handle) || (! door) || (! key))
819 return NULL;
820
821 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (
822 handle->rooms, key);
823
824 if (! room)
825 {
826 room = create_room (handle, key);
827
828 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key,
829 room,
830 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
831 {
832 destroy_room (room);
833 return NULL;
834 }
835 }
836
837 send_enter_room (handle, room, door);
838 return room;
839}
840
841
842void
843GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room)
844{
845 if (! room)
846 return;
847
848 struct GNUNET_MESSENGER_Message *message = create_message_leave ();
849
850 if (message)
851 {
852 enqueue_message_to_room (room, message);
853 destroy_message (message);
854 }
855
856 send_close_room (room->handle, room);
857}
858
859
860struct GNUNET_MESSENGER_RoomFind
861{
862 const struct GNUNET_MESSENGER_Contact *contact;
863 GNUNET_MESSENGER_MemberCallback callback;
864 size_t counter;
865 void *cls;
866};
867
868static int
869iterate_find_room (void *cls,
870 const struct GNUNET_HashCode *key,
871 void *value)
872{
873 struct GNUNET_MESSENGER_RoomFind *find = cls;
874 struct GNUNET_MESSENGER_Room *room = value;
875
876 if ((find->counter > 0) && ((! find->contact) || (GNUNET_YES ==
877 find_room_member (room,
878 find->
879 contact))))
880 {
881 find->counter--;
882
883 if (! find->callback)
884 return GNUNET_YES;
885
886 return find->callback (find->cls, room, find->contact);
887 }
888 else
889 return GNUNET_NO;
890}
891
892
893int
894GNUNET_MESSENGER_find_rooms (const struct GNUNET_MESSENGER_Handle *handle,
895 const struct GNUNET_MESSENGER_Contact *contact,
896 GNUNET_MESSENGER_MemberCallback callback,
897 void *cls)
898{
899 if (! handle)
900 return GNUNET_SYSERR;
901
902 struct GNUNET_MESSENGER_RoomFind find;
903
904 find.contact = contact;
905 find.callback = callback;
906 find.counter = (contact? contact->rc : SIZE_MAX);
907 find.cls = cls;
908
909 return GNUNET_CONTAINER_multihashmap_iterate (handle->rooms,
910 iterate_find_room, &find);
911}
912
913
914const struct GNUNET_HashCode*
915GNUNET_MESSENGER_room_get_key (const struct GNUNET_MESSENGER_Room *room)
916{
917 if (! room)
918 return NULL;
919
920 return &(room->key);
921}
922
923
924const struct GNUNET_MESSENGER_Contact*
925GNUNET_MESSENGER_get_sender (const struct GNUNET_MESSENGER_Room *room,
926 const struct GNUNET_HashCode *hash)
927{
928 if ((! room) || (! hash))
929 return NULL;
930
931 return get_room_sender (room, hash);
932}
933
934
935const char*
936GNUNET_MESSENGER_contact_get_name (const struct
937 GNUNET_MESSENGER_Contact *contact)
938{
939 if (! contact)
940 return NULL;
941
942 return get_contact_name (contact);
943}
944
945
946const struct GNUNET_CRYPTO_PublicKey*
947GNUNET_MESSENGER_contact_get_key (const struct
948 GNUNET_MESSENGER_Contact *contact)
949{
950 if (! contact)
951 return NULL;
952
953 return get_non_anonymous_key (get_contact_key (contact));
954}
955
956
957void
958GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room,
959 struct GNUNET_MESSENGER_Message *message,
960 const struct GNUNET_MESSENGER_Contact *contact)
961{
962 if ((! room) || (! message))
963 return;
964
965 switch (filter_message_sending (message))
966 {
967 case GNUNET_SYSERR:
968 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
969 "Sending message aborted: This kind of message is reserved for the service!\n");
970 return;
971 case GNUNET_NO:
972 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
973 "Sending message aborted: This kind of message could cause issues!\n");
974 return;
975 default:
976 break;
977 }
978
979 char *original_name;
980 char *changed_name = NULL;
981
982 if (GNUNET_MESSENGER_KIND_NAME != message->header.kind)
983 goto skip_naming;
984
985 original_name = message->body.name.name;
986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
987 "Apply rule for using handle name in room: %s\n", GNUNET_h2s (
988 &(room->key)));
989
990 const char *handle_name = get_handle_name (room->handle);
991
992 if ((handle_name) && (GNUNET_YES == room->use_handle_name) &&
993 ((! original_name) || (0 == strlen (original_name))))
994 {
995 changed_name = GNUNET_strdup (handle_name);
996 message->body.name.name = changed_name;
997 }
998
999skip_naming:
1000 if (contact)
1001 {
1002 const struct GNUNET_CRYPTO_PublicKey *public_key = get_non_anonymous_key (
1003 get_contact_key (contact)
1004 );
1005
1006 if (! public_key)
1007 {
1008 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1009 "Sending message aborted: Invalid key!\n");
1010 goto reset_naming;
1011 }
1012
1013 struct GNUNET_MESSENGER_Message *original = message;
1014 message = copy_message (original);
1015
1016 if (GNUNET_YES != encrypt_message (message, public_key))
1017 {
1018 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1019 "Sending message aborted: Encryption failed!\n");
1020
1021 destroy_message (message);
1022 message = original;
1023
1024 goto reset_naming;
1025 }
1026 }
1027
1028 enqueue_message_to_room (room, message);
1029
1030reset_naming:
1031 if (changed_name)
1032 GNUNET_free (changed_name);
1033
1034 if (GNUNET_MESSENGER_KIND_NAME != message->header.kind)
1035 return;
1036
1037 message->body.name.name = original_name;
1038}
1039
1040
1041const struct GNUNET_MESSENGER_Message*
1042GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room,
1043 const struct GNUNET_HashCode *hash)
1044{
1045 if ((! room) || (! hash))
1046 return NULL;
1047
1048 const struct GNUNET_MESSENGER_Message *message = get_room_message (room,
1049 hash);
1050
1051 if (! message)
1052 {
1053 struct GNUNET_MESSENGER_GetMessage *msg;
1054 struct GNUNET_MQ_Envelope *env;
1055
1056 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE);
1057 GNUNET_memcpy (&(msg->key), &(room->key), sizeof(msg->key));
1058 GNUNET_memcpy (&(msg->hash), hash, sizeof(*hash));
1059 GNUNET_MQ_send (room->handle->mq, env);
1060 }
1061
1062 return message;
1063}
1064
1065
1066int
1067GNUNET_MESSENGER_iterate_members (struct GNUNET_MESSENGER_Room *room,
1068 GNUNET_MESSENGER_MemberCallback callback,
1069 void *cls)
1070{
1071 if (! room)
1072 return GNUNET_SYSERR;
1073
1074 return iterate_room_members (room, callback, cls);
1075}