aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/messenger_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/messenger_api.c')
-rw-r--r--src/messenger/messenger_api.c792
1 files changed, 0 insertions, 792 deletions
diff --git a/src/messenger/messenger_api.c b/src/messenger/messenger_api.c
deleted file mode 100644
index a37b1b10b..000000000
--- a/src/messenger/messenger_api.c
+++ /dev/null
@@ -1,792 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/messenger_api.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "gnunet_messenger_service.h"
27
28#include "gnunet-service-messenger.h"
29
30#include "messenger_api_handle.h"
31#include "messenger_api_message.h"
32#include "messenger_api_util.h"
33
34const char*
35GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind)
36{
37 switch (kind)
38 {
39 case GNUNET_MESSENGER_KIND_INFO:
40 return "INFO";
41 case GNUNET_MESSENGER_KIND_JOIN:
42 return "JOIN";
43 case GNUNET_MESSENGER_KIND_LEAVE:
44 return "LEAVE";
45 case GNUNET_MESSENGER_KIND_NAME:
46 return "NAME";
47 case GNUNET_MESSENGER_KIND_KEY:
48 return "KEY";
49 case GNUNET_MESSENGER_KIND_PEER:
50 return "PEER";
51 case GNUNET_MESSENGER_KIND_ID:
52 return "ID";
53 case GNUNET_MESSENGER_KIND_MISS:
54 return "MISS";
55 case GNUNET_MESSENGER_KIND_MERGE:
56 return "MERGE";
57 case GNUNET_MESSENGER_KIND_REQUEST:
58 return "REQUEST";
59 case GNUNET_MESSENGER_KIND_INVITE:
60 return "INVITE";
61 case GNUNET_MESSENGER_KIND_TEXT:
62 return "TEXT";
63 case GNUNET_MESSENGER_KIND_FILE:
64 return "FILE";
65 case GNUNET_MESSENGER_KIND_PRIVATE:
66 return "PRIVATE";
67 default:
68 return "UNKNOWN";
69 }
70}
71
72static int
73check_get_name (void *cls,
74 const struct GNUNET_MESSENGER_NameMessage *msg)
75{
76 GNUNET_MQ_check_zero_termination(msg);
77 return GNUNET_OK;
78}
79
80static void
81handle_get_name (void *cls,
82 const struct GNUNET_MESSENGER_NameMessage *msg)
83{
84 struct GNUNET_MESSENGER_Handle *handle = cls;
85
86 const char *name = ((const char*) msg) + sizeof(*msg);
87
88 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set name of handle: %s\n", name);
89
90 set_handle_name (handle, strlen (name) > 0 ? name : NULL);
91}
92
93static int
94check_get_key (void *cls,
95 const struct GNUNET_MESSENGER_KeyMessage *msg)
96{
97 const uint16_t full_length = ntohs (msg->header.size);
98
99 if (full_length < sizeof(*msg))
100 return GNUNET_NO;
101
102 const uint16_t length = full_length - sizeof(*msg);
103 const char *buffer = ((const char*) msg) + sizeof(*msg);
104
105 struct GNUNET_IDENTITY_PublicKey pubkey;
106 if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
107 return GNUNET_NO;
108
109 return GNUNET_OK;
110}
111
112static void
113handle_get_key (void *cls,
114 const struct GNUNET_MESSENGER_KeyMessage *msg)
115{
116 struct GNUNET_MESSENGER_Handle *handle = cls;
117
118 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
119 const char *buffer = ((const char*) msg) + sizeof(*msg);
120
121 struct GNUNET_IDENTITY_PublicKey pubkey;
122 if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
123 return;
124
125 char* str = GNUNET_IDENTITY_public_key_to_string (&pubkey);
126 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set key of handle: %s\n", str);
127 GNUNET_free(str);
128
129 set_handle_key (handle, &pubkey);
130
131 if (handle->identity_callback)
132 handle->identity_callback (handle->identity_cls, handle);
133}
134
135static void
136handle_member_id (void *cls,
137 const struct GNUNET_MESSENGER_MemberMessage *msg)
138{
139 struct GNUNET_MESSENGER_Handle *handle = cls;
140
141 const struct GNUNET_HashCode *key = &(msg->key);
142 const struct GNUNET_ShortHashCode *id = &(msg->id);
143
144 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set id of handle in room: %s\n", GNUNET_h2s (key));
145
146 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
147
148 if (room)
149 {
150 if (!room->contact_id)
151 room->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
152
153 GNUNET_memcpy(room->contact_id, id, sizeof(*id));
154 }
155}
156
157static void
158handle_room_open (void *cls,
159 const struct GNUNET_MESSENGER_RoomMessage *msg)
160{
161 struct GNUNET_MESSENGER_Handle *handle = cls;
162
163 const struct GNUNET_HashCode *key = &(msg->key);
164
165 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opened room: %s\n", GNUNET_h2s (key));
166
167 open_handle_room (handle, key);
168}
169
170static void
171handle_room_entry (void *cls,
172 const struct GNUNET_MESSENGER_RoomMessage *msg)
173{
174 struct GNUNET_MESSENGER_Handle *handle = cls;
175
176 const struct GNUNET_PeerIdentity *door = &(msg->door);
177 const struct GNUNET_HashCode *key = &(msg->key);
178
179 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entered room: %s\n", GNUNET_h2s (key));
180
181 entry_handle_room_at (handle, door, key);
182}
183
184static void
185handle_room_close (void *cls,
186 const struct GNUNET_MESSENGER_RoomMessage *msg)
187{
188 struct GNUNET_MESSENGER_Handle *handle = cls;
189
190 const struct GNUNET_HashCode *key = &(msg->key);
191
192 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key));
193
194 close_handle_room (handle, key);
195}
196
197static int
198check_recv_message (void *cls,
199 const struct GNUNET_MESSENGER_RecvMessage *msg)
200{
201 const uint16_t full_length = ntohs (msg->header.size);
202
203 if (full_length < sizeof(*msg))
204 return GNUNET_NO;
205
206 const uint16_t length = full_length - sizeof(*msg);
207 const char *buffer = ((const char*) msg) + sizeof(*msg);
208
209 struct GNUNET_MESSENGER_Message message;
210
211 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, GNUNET_YES))
212 return GNUNET_NO;
213
214 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, NULL))
215 return GNUNET_NO;
216
217 cleanup_message(&message);
218 return GNUNET_OK;
219}
220
221static void
222handle_recv_message (void *cls,
223 const struct GNUNET_MESSENGER_RecvMessage *msg)
224{
225 struct GNUNET_MESSENGER_Handle *handle = cls;
226
227 const struct GNUNET_HashCode *key = &(msg->key);
228 const struct GNUNET_HashCode *sender = &(msg->sender);
229 const struct GNUNET_HashCode *context = &(msg->context);
230 const struct GNUNET_HashCode *hash = &(msg->hash);
231 const enum GNUNET_MESSENGER_MessageFlags flags = (
232 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
233 );
234
235 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
236 const char *buffer = ((const char*) msg) + sizeof(*msg);
237
238 struct GNUNET_MESSENGER_Message message;
239 decode_message (&message, length, buffer, GNUNET_YES, NULL);
240
241 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", GNUNET_MESSENGER_name_of_kind (message.header.kind));
242
243 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
244
245 if (room)
246 {
247 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(handle);
248
249 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Raw contact from sender and context: (%s : %s)\n",
250 GNUNET_h2s(sender), GNUNET_h2s_full(context));
251
252 struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw(
253 store, context, sender
254 );
255
256 handle_room_message (room, contact, &message, hash);
257
258 const struct GNUNET_MESSENGER_Message *stored_message = get_room_message(room, hash);
259
260 if (handle->msg_callback)
261 handle->msg_callback (handle->msg_cls, room, contact, stored_message, hash, flags);
262 }
263 else
264 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Unknown room for this client: %s\n", GNUNET_h2s (key));
265
266 cleanup_message(&message);
267}
268
269static void
270reconnect (struct GNUNET_MESSENGER_Handle *handle);
271
272static void
273send_open_room (struct GNUNET_MESSENGER_Handle *handle,
274 struct GNUNET_MESSENGER_Room *room)
275{
276 struct GNUNET_MESSENGER_RoomMessage *msg;
277 struct GNUNET_MQ_Envelope *env;
278
279 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
280 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
281 GNUNET_MQ_send (handle->mq, env);
282}
283
284static void
285send_enter_room (struct GNUNET_MESSENGER_Handle *handle,
286 struct GNUNET_MESSENGER_Room *room,
287 const struct GNUNET_PeerIdentity *door)
288{
289 struct GNUNET_MESSENGER_RoomMessage *msg;
290 struct GNUNET_MQ_Envelope *env;
291
292 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
293 GNUNET_memcpy(&(msg->door), door, sizeof(*door));
294 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
295 GNUNET_MQ_send (handle->mq, env);
296}
297
298static void
299send_close_room (struct GNUNET_MESSENGER_Handle *handle,
300 struct GNUNET_MESSENGER_Room *room)
301{
302 struct GNUNET_MESSENGER_RoomMessage *msg;
303 struct GNUNET_MQ_Envelope *env;
304
305 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
306 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
307 GNUNET_MQ_send (handle->mq, env);
308}
309
310static int
311iterate_reset_room (void *cls,
312 const struct GNUNET_HashCode *key,
313 void *value)
314{
315 struct GNUNET_MESSENGER_Handle *handle = cls;
316 struct GNUNET_MESSENGER_Room *room = value;
317
318 if (GNUNET_YES == room->opened)
319 send_open_room (handle, room);
320
321 struct GNUNET_MESSENGER_ListTunnel *entry = room->entries.head;
322
323 struct GNUNET_PeerIdentity door;
324
325 while (entry)
326 {
327 GNUNET_PEER_resolve (entry->peer, &door);
328
329 send_enter_room (handle, room, &door);
330
331 entry = entry->next;
332 }
333
334 return GNUNET_YES;
335}
336
337static void
338callback_reconnect (void *cls)
339{
340 struct GNUNET_MESSENGER_Handle *handle = cls;
341
342 handle->reconnect_task = NULL;
343 handle->reconnect_time = GNUNET_TIME_STD_BACKOFF(handle->reconnect_time)
344 ;
345
346 reconnect (handle);
347
348 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_reset_room, handle);
349}
350
351static int
352iterate_close_room (void *cls,
353 const struct GNUNET_HashCode *key,
354 void *value)
355{
356 struct GNUNET_MESSENGER_Handle *handle = cls;
357 struct GNUNET_MESSENGER_Room *room = value;
358
359 send_close_room (handle, room);
360
361 return GNUNET_YES;
362}
363
364static void
365callback_mq_error (void *cls,
366 enum GNUNET_MQ_Error error)
367{
368 struct GNUNET_MESSENGER_Handle *handle = cls;
369
370 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "MQ_Error: %u\n", error);
371
372 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room, handle);
373
374 if (handle->mq)
375 {
376 GNUNET_MQ_destroy (handle->mq);
377 handle->mq = NULL;
378 }
379
380 handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_time, &callback_reconnect, handle);
381}
382
383static void
384reconnect (struct GNUNET_MESSENGER_Handle *handle)
385{
386 const struct GNUNET_MQ_MessageHandler handlers[] =
387 {
388 GNUNET_MQ_hd_var_size(
389 get_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME,
390 struct GNUNET_MESSENGER_NameMessage, handle
391 ),
392 GNUNET_MQ_hd_var_size(
393 get_key, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY,
394 struct GNUNET_MESSENGER_KeyMessage, handle
395 ),
396 GNUNET_MQ_hd_fixed_size(
397 member_id,
398 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID,
399 struct GNUNET_MESSENGER_MemberMessage, handle
400 ),
401 GNUNET_MQ_hd_fixed_size(
402 room_open,
403 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN,
404 struct GNUNET_MESSENGER_RoomMessage, handle
405 ),
406 GNUNET_MQ_hd_fixed_size(
407 room_entry,
408 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY,
409 struct GNUNET_MESSENGER_RoomMessage, handle
410 ),
411 GNUNET_MQ_hd_fixed_size(
412 room_close,
413 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE,
414 struct GNUNET_MESSENGER_RoomMessage, handle
415 ),
416 GNUNET_MQ_hd_var_size(
417 recv_message,
418 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE,
419 struct GNUNET_MESSENGER_RecvMessage, handle
420 ),
421 GNUNET_MQ_handler_end()
422 };
423
424 handle->mq = GNUNET_CLIENT_connect (handle->cfg, GNUNET_MESSENGER_SERVICE_NAME, handlers, &callback_mq_error, handle);
425}
426
427struct GNUNET_MESSENGER_Handle*
428GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
429 const char *name,
430 GNUNET_MESSENGER_IdentityCallback identity_callback,
431 void *identity_cls,
432 GNUNET_MESSENGER_MessageCallback msg_callback,
433 void *msg_cls)
434{
435 struct GNUNET_MESSENGER_Handle *handle = create_handle (cfg, identity_callback, identity_cls, msg_callback, msg_cls);
436
437 reconnect (handle);
438
439 if (handle->mq)
440 {
441 const uint16_t name_len = name ? strlen (name) : 0;
442
443 struct GNUNET_MESSENGER_CreateMessage *msg;
444 struct GNUNET_MQ_Envelope *env;
445
446 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE);
447
448 char *extra = ((char*) msg) + sizeof(*msg);
449
450 if (name_len)
451 GNUNET_memcpy(extra, name, name_len);
452
453 extra[name_len] = '\0';
454
455 GNUNET_MQ_send (handle->mq, env);
456 return handle;
457 }
458 else
459 {
460 destroy_handle (handle);
461 return NULL;
462 }
463}
464
465int
466GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle)
467{
468 if ((!handle) || (!get_handle_name (handle)))
469 return GNUNET_SYSERR;
470
471 struct GNUNET_MESSENGER_UpdateMessage *msg;
472 struct GNUNET_MQ_Envelope *env;
473
474 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE);
475 GNUNET_MQ_send (handle->mq, env);
476 return GNUNET_OK;
477}
478
479void
480GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle)
481{
482 if (!handle)
483 return;
484
485 struct GNUNET_MESSENGER_DestroyMessage *msg;
486 struct GNUNET_MQ_Envelope *env;
487
488 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY);
489 GNUNET_MQ_send (handle->mq, env);
490
491 destroy_handle (handle);
492}
493
494const char*
495GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle)
496{
497 if (!handle)
498 return NULL;
499
500 return get_handle_name (handle);
501}
502
503int
504GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle,
505 const char *name)
506{
507 if (!handle)
508 return GNUNET_SYSERR;
509
510 const uint16_t name_len = name ? strlen (name) : 0;
511
512 struct GNUNET_MESSENGER_NameMessage *msg;
513 struct GNUNET_MQ_Envelope *env;
514
515 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME);
516
517 char *extra = ((char*) msg) + sizeof(*msg);
518
519 if (name_len)
520 GNUNET_memcpy(extra, name, name_len);
521
522 extra[name_len] = '\0';
523
524 GNUNET_MQ_send (handle->mq, env);
525 return GNUNET_YES;
526}
527
528static const struct GNUNET_IDENTITY_PublicKey*
529get_non_anonymous_key (const struct GNUNET_IDENTITY_PublicKey* public_key)
530{
531 if (0 == GNUNET_memcmp(public_key, get_anonymous_public_key()))
532 return NULL;
533
534 return public_key;
535}
536
537const struct GNUNET_IDENTITY_PublicKey*
538GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle)
539{
540 if (!handle)
541 return NULL;
542
543 return get_non_anonymous_key (get_handle_key (handle));
544}
545
546struct GNUNET_MESSENGER_Room*
547GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle,
548 const struct GNUNET_HashCode *key)
549{
550 if ((!handle) || (!key))
551 return NULL;
552
553 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
554
555 if (!room)
556 {
557 room = create_room (handle, key);
558
559 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room,
560 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
561 {
562 destroy_room (room);
563 return NULL;
564 }
565 }
566
567 send_open_room (handle, room);
568 return room;
569}
570
571struct GNUNET_MESSENGER_Room*
572GNUNET_MESSENGER_enter_room (struct GNUNET_MESSENGER_Handle *handle,
573 const struct GNUNET_PeerIdentity *door,
574 const struct GNUNET_HashCode *key)
575{
576 if ((!handle) || (!door) || (!key))
577 return NULL;
578
579 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
580
581 if (!room)
582 {
583 room = create_room (handle, key);
584
585 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room,
586 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
587 {
588 destroy_room (room);
589 return NULL;
590 }
591 }
592
593 send_enter_room (handle, room, door);
594 return room;
595}
596
597void
598GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room)
599{
600 if (!room)
601 return;
602
603 send_close_room (room->handle, room);
604}
605
606struct GNUNET_MESSENGER_RoomFind
607{
608 const struct GNUNET_MESSENGER_Contact *contact;
609 GNUNET_MESSENGER_MemberCallback callback;
610 size_t counter;
611 void *cls;
612};
613
614static int
615iterate_find_room (void* cls,
616 const struct GNUNET_HashCode *key,
617 void *value)
618{
619 struct GNUNET_MESSENGER_RoomFind *find = cls;
620 struct GNUNET_MESSENGER_Room *room = value;
621
622 if ((find->counter > 0) && ((!find->contact) || (GNUNET_YES == find_room_member(room, find->contact))))
623 {
624 find->counter--;
625
626 if (!find->callback)
627 return GNUNET_YES;
628
629 return find->callback(find->cls, room, find->contact);
630 }
631 else
632 return GNUNET_NO;
633}
634
635int
636GNUNET_MESSENGER_find_rooms (const struct GNUNET_MESSENGER_Handle *handle,
637 const struct GNUNET_MESSENGER_Contact *contact,
638 GNUNET_MESSENGER_MemberCallback callback,
639 void *cls)
640{
641 if (!handle)
642 return GNUNET_SYSERR;
643
644 struct GNUNET_MESSENGER_RoomFind find;
645
646 find.contact = contact;
647 find.callback = callback;
648 find.counter = (contact? contact->rc : SIZE_MAX);
649 find.cls = cls;
650
651 return GNUNET_CONTAINER_multihashmap_iterate(handle->rooms, iterate_find_room, &find);
652}
653
654const struct GNUNET_HashCode*
655GNUNET_MESSENGER_room_get_key (const struct GNUNET_MESSENGER_Room *room)
656{
657 if (!room)
658 return NULL;
659
660 return &(room->key);
661}
662
663const struct GNUNET_MESSENGER_Contact*
664GNUNET_MESSENGER_get_sender (const struct GNUNET_MESSENGER_Room *room,
665 const struct GNUNET_HashCode *hash)
666{
667 if ((!room) || (!hash))
668 return NULL;
669
670 return get_room_sender(room, hash);
671}
672
673const char*
674GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact)
675{
676 if (!contact)
677 return NULL;
678
679 return get_contact_name (contact);
680}
681
682const struct GNUNET_IDENTITY_PublicKey*
683GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact)
684{
685 if (!contact)
686 return NULL;
687
688 return get_non_anonymous_key (get_contact_key (contact));
689}
690
691void
692GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room,
693 const struct GNUNET_MESSENGER_Message *message,
694 const struct GNUNET_MESSENGER_Contact *contact)
695{
696 if ((!room) || (!message))
697 return;
698
699 switch (filter_message_sending (message))
700 {
701 case GNUNET_SYSERR:
702 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message aborted: This kind of message is reserved for the service!\n");
703 return;
704 case GNUNET_NO:
705 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: This kind of message could cause issues!\n");
706 return;
707 default:
708 break;
709 }
710
711 ssize_t key_length = 0;
712
713 if (contact)
714 {
715 const struct GNUNET_IDENTITY_PublicKey *public_key = get_non_anonymous_key (
716 get_contact_key(contact)
717 );
718
719 if (public_key)
720 key_length = GNUNET_IDENTITY_key_get_length(public_key);
721 else
722 key_length = -1;
723 }
724
725 if (key_length < 0)
726 {
727 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: Invalid key!\n");
728 return;
729 }
730
731 const uint16_t msg_length = get_message_size (message, GNUNET_NO);
732
733 struct GNUNET_MESSENGER_SendMessage *msg;
734 struct GNUNET_MQ_Envelope *env;
735
736 const uint16_t length = (uint16_t) key_length + msg_length;
737
738 env = GNUNET_MQ_msg_extra(
739 msg, length,
740 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE
741 );
742
743 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
744
745 msg->flags = (uint32_t) (
746 contact? GNUNET_MESSENGER_FLAG_PRIVATE : GNUNET_MESSENGER_FLAG_NONE
747 );
748
749 char *buffer = ((char*) msg) + sizeof(*msg);
750 char *msg_buffer = buffer + key_length;
751
752 if (key_length > 0)
753 GNUNET_IDENTITY_write_key_to_buffer(get_contact_key(contact), buffer, key_length);
754
755 encode_message (message, msg_length, msg_buffer, GNUNET_NO);
756
757 GNUNET_MQ_send (room->handle->mq, env);
758}
759
760const struct GNUNET_MESSENGER_Message*
761GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room,
762 const struct GNUNET_HashCode *hash)
763{
764 if ((!room) || (!hash))
765 return NULL;
766
767 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, hash);
768
769 if (!message)
770 {
771 struct GNUNET_MESSENGER_GetMessage *msg;
772 struct GNUNET_MQ_Envelope *env;
773
774 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE);
775 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
776 GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash));
777 GNUNET_MQ_send (room->handle->mq, env);
778 }
779
780 return message;
781}
782
783int
784GNUNET_MESSENGER_iterate_members (struct GNUNET_MESSENGER_Room *room,
785 GNUNET_MESSENGER_MemberCallback callback,
786 void *cls)
787{
788 if (!room)
789 return GNUNET_SYSERR;
790
791 return iterate_room_members(room, callback, cls);
792}