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