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