aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/gnunet-service-messenger_handle.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/gnunet-service-messenger_handle.c')
-rw-r--r--src/messenger/gnunet-service-messenger_handle.c711
1 files changed, 0 insertions, 711 deletions
diff --git a/src/messenger/gnunet-service-messenger_handle.c b/src/messenger/gnunet-service-messenger_handle.c
deleted file mode 100644
index 341bb7251..000000000
--- a/src/messenger/gnunet-service-messenger_handle.c
+++ /dev/null
@@ -1,711 +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/gnunet-service-messenger_handle.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_handle.h"
27
28#include "gnunet-service-messenger.h"
29#include "gnunet-service-messenger_message_kind.h"
30
31#include "messenger_api_util.h"
32
33struct GNUNET_MESSENGER_SrvHandle*
34create_handle (struct GNUNET_MESSENGER_Service *service,
35 struct GNUNET_MQ_Handle *mq)
36{
37 GNUNET_assert((service) && (mq));
38
39 struct GNUNET_MESSENGER_SrvHandle *handle = GNUNET_new(struct GNUNET_MESSENGER_SrvHandle);
40
41 handle->service = service;
42 handle->mq = mq;
43
44 handle->name = NULL;
45 handle->ego = NULL;
46
47 handle->member_ids = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
48
49 return handle;
50}
51
52int
53iterate_free_member_ids (void *cls,
54 const struct GNUNET_HashCode *key,
55 void *value)
56{
57 GNUNET_free(value);
58
59 return GNUNET_YES;
60}
61
62void
63destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
64{
65 GNUNET_assert(handle);
66
67 if (handle->service->dir)
68 save_handle_configuration (handle);
69
70 if (handle->name)
71 GNUNET_free(handle->name);
72
73 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_free_member_ids, NULL);
74 GNUNET_CONTAINER_multihashmap_destroy (handle->member_ids);
75
76 GNUNET_free(handle);
77}
78
79void
80get_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle,
81 const char *name,
82 char **dir)
83{
84 GNUNET_assert((handle) && (dir));
85
86 if (name)
87 GNUNET_asprintf (dir, "%s%s%c%s%c", handle->service->dir, "identities",
88 DIR_SEPARATOR, name, DIR_SEPARATOR);
89 else
90 GNUNET_asprintf (dir, "%s%s%c", handle->service->dir, "anonymous",
91 DIR_SEPARATOR);
92}
93
94static int
95create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle,
96 const struct GNUNET_HashCode *key)
97{
98 GNUNET_assert((handle) && (key));
99
100 struct GNUNET_ShortHashCode *random_id = GNUNET_new(struct GNUNET_ShortHashCode);
101
102 if (!random_id)
103 return GNUNET_NO;
104
105 generate_free_member_id (random_id, NULL);
106
107 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, random_id,
108 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
109 {
110 GNUNET_free(random_id);
111 return GNUNET_NO;
112 }
113
114 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Created a new member id (%s) for room: %s\n", GNUNET_sh2s (random_id),
115 GNUNET_h2s (key));
116
117 return GNUNET_YES;
118}
119
120const struct GNUNET_ShortHashCode*
121get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle,
122 const struct GNUNET_HashCode *key)
123{
124 GNUNET_assert((handle) && (key));
125
126 return GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
127}
128
129int
130change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle,
131 const struct GNUNET_HashCode *key,
132 const struct GNUNET_ShortHashCode *unique_id)
133{
134 GNUNET_assert((handle) && (key) && (unique_id));
135
136 struct GNUNET_ShortHashCode *member_id = GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
137
138 if (!member_id)
139 {
140 member_id = GNUNET_new(struct GNUNET_ShortHashCode);
141 GNUNET_memcpy(member_id, unique_id, sizeof(*member_id));
142
143 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, member_id,
144 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
145 {
146 GNUNET_free(member_id);
147 return GNUNET_SYSERR;
148 }
149 }
150
151 if (0 == GNUNET_memcmp(unique_id, member_id))
152 goto send_message_to_client;
153
154 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Change a member id (%s) for room (%s).\n", GNUNET_sh2s (member_id),
155 GNUNET_h2s (key));
156
157 GNUNET_memcpy(member_id, unique_id, sizeof(*unique_id));
158
159 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member id changed to (%s).\n", GNUNET_sh2s (unique_id));
160
161 struct GNUNET_MESSENGER_MemberMessage *msg;
162 struct GNUNET_MQ_Envelope *env;
163
164send_message_to_client:
165
166 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID);
167
168 GNUNET_memcpy(&(msg->key), key, sizeof(*key));
169 GNUNET_memcpy(&(msg->id), member_id, sizeof(*member_id));
170
171 GNUNET_MQ_send (handle->mq, env);
172 return GNUNET_OK;
173}
174
175static void
176change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
177 const char *name)
178{
179 GNUNET_assert(handle);
180
181 if (handle->name)
182 GNUNET_free(handle->name);
183
184 handle->name = name ? GNUNET_strdup(name) : NULL;
185
186 const uint16_t name_len = handle->name ? strlen (handle->name) : 0;
187
188 struct GNUNET_MESSENGER_NameMessage *msg;
189 struct GNUNET_MQ_Envelope *env;
190
191 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME);
192
193 char *extra = ((char*) msg) + sizeof(*msg);
194
195 if (name_len)
196 GNUNET_memcpy(extra, handle->name, name_len);
197
198 extra[name_len] = '\0';
199
200 GNUNET_MQ_send (handle->mq, env);
201}
202
203static void
204change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
205 const struct GNUNET_MESSENGER_Ego *ego)
206{
207 GNUNET_assert(handle);
208
209 handle->ego = ego;
210
211 ego = get_handle_ego (handle);
212
213 const uint16_t length = GNUNET_IDENTITY_key_get_length(&(ego->pub));
214
215 struct GNUNET_MESSENGER_KeyMessage *msg;
216 struct GNUNET_MQ_Envelope *env;
217
218 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY);
219
220 char *extra = ((char*) msg) + sizeof(*msg);
221
222 if (GNUNET_IDENTITY_write_key_to_buffer(&(ego->pub), extra, length) < 0)
223 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Could not write key to buffer.\n");
224
225 GNUNET_MQ_send (handle->mq, env);
226}
227
228struct GNUNET_MESSENGER_MessageHandle
229{
230 struct GNUNET_MESSENGER_SrvHandle *handle;
231 struct GNUNET_MESSENGER_Message *message;
232};
233
234static int
235iterate_send_message (void *cls,
236 const struct GNUNET_HashCode *key,
237 void *value)
238{
239 struct GNUNET_MESSENGER_MessageHandle *msg_handle = cls;
240
241 send_handle_message (msg_handle->handle, key, msg_handle->message);
242
243 return GNUNET_YES;
244}
245
246void
247set_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
248 const struct GNUNET_MESSENGER_Ego *ego)
249{
250 GNUNET_assert((handle) && (ego));
251
252 struct GNUNET_MESSENGER_MessageHandle msg_handle;
253
254 msg_handle.handle = handle;
255 msg_handle.message = create_message_key (&(ego->priv));
256
257 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
258
259 destroy_message (msg_handle.message);
260
261 change_handle_ego (handle, ego);
262}
263
264const struct GNUNET_MESSENGER_Ego*
265get_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle)
266{
267 GNUNET_assert(handle);
268
269 static struct GNUNET_MESSENGER_Ego anonymous;
270 static int read_keys = 0;
271
272 if (handle->ego)
273 return handle->ego;
274
275 if (!read_keys)
276 {
277 struct GNUNET_IDENTITY_Ego *ego = GNUNET_IDENTITY_ego_get_anonymous ();
278 GNUNET_memcpy(&(anonymous.priv), GNUNET_IDENTITY_ego_get_private_key (ego), sizeof(anonymous.priv));
279 GNUNET_IDENTITY_ego_get_public_key (ego, &(anonymous.pub));
280 read_keys = 1;
281 }
282
283 return &anonymous;
284}
285
286static void
287callback_setup_handle_name (void *cls,
288 const char *name,
289 const struct GNUNET_MESSENGER_Ego *ego)
290{
291 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
292
293 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Setting up handle...\n");
294
295 change_handle_name (handle, name);
296 change_handle_ego (handle, ego);
297
298 if (handle->service->dir)
299 load_handle_configuration (handle);
300}
301
302void
303setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
304 const char *name)
305{
306 GNUNET_assert(handle);
307
308 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
309
310 lookup_store_ego (store, name, callback_setup_handle_name, handle);
311}
312
313static void
314callback_update_handle (void *cls,
315 const char *name,
316 const struct GNUNET_MESSENGER_Ego *ego)
317{
318 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
319
320 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating handle...\n");
321
322 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
323
324 if (!ego)
325 create_store_ego(store, handle->name, handle);
326 else
327 change_handle_ego (handle, ego);
328}
329
330void
331update_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
332{
333 GNUNET_assert(handle);
334
335 if (!handle->name)
336 {
337 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating handle failed: Name is required!\n");
338 return;
339 }
340
341 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
342
343 lookup_store_ego (store, handle->name, callback_update_handle, handle);
344}
345
346static void
347callback_set_handle_name (void *cls,
348 const char *name,
349 const struct GNUNET_MESSENGER_Ego *ego)
350{
351 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
352
353 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Renaming handle...\n");
354
355 if (ego)
356 {
357 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is occupied! (%s)\n", name);
358 return;
359 }
360
361 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
362
363 int rename_ego_in_store = handle->ego? GNUNET_YES : GNUNET_NO;
364
365 char *old_dir;
366 get_handle_data_subdir (handle, handle->name, &old_dir);
367
368 char *new_dir;
369 get_handle_data_subdir (handle, name, &new_dir);
370
371 int result = 0;
372
373 if (GNUNET_YES == GNUNET_DISK_directory_test (old_dir, GNUNET_YES))
374 {
375 GNUNET_DISK_directory_create_for_file (new_dir);
376
377 result = rename (old_dir, new_dir);
378 }
379 else if (GNUNET_YES == GNUNET_DISK_directory_test (new_dir, GNUNET_NO))
380 result = -1;
381
382 if (0 == result)
383 {
384 struct GNUNET_MESSENGER_MessageHandle msg_handle;
385
386 msg_handle.handle = handle;
387 msg_handle.message = create_message_name (name);
388
389 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
390
391 destroy_message (msg_handle.message);
392
393 change_handle_name (handle, name);
394 }
395 else
396 rename_ego_in_store = GNUNET_NO;
397
398 GNUNET_free(old_dir);
399 GNUNET_free(new_dir);
400
401 if (GNUNET_YES == rename_ego_in_store)
402 rename_store_ego(store, handle->name, name);
403}
404
405void
406set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
407 const char *name)
408{
409 GNUNET_assert(handle);
410
411 if (!name)
412 {
413 if (handle->ego)
414 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is required!\n");
415 else
416 change_handle_name (handle, name);
417
418 return;
419 }
420
421 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
422
423 lookup_store_ego (store, name, callback_set_handle_name, handle);
424}
425
426int
427open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
428 const struct GNUNET_HashCode *key)
429{
430 GNUNET_assert((handle) && (key));
431
432 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
433 return GNUNET_NO;
434
435 return open_service_room (handle->service, handle, key);
436}
437
438int
439entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
440 const struct GNUNET_PeerIdentity *door,
441 const struct GNUNET_HashCode *key)
442{
443 GNUNET_assert((handle) && (door) && (key));
444
445 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
446 return GNUNET_NO;
447
448 return entry_service_room (handle->service, handle, door, key);
449}
450
451int
452close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
453 const struct GNUNET_HashCode *key)
454{
455 GNUNET_assert((handle) && (key));
456
457 if (!get_handle_member_id (handle, key))
458 return GNUNET_NO;
459
460 return close_service_room (handle->service, handle, key);
461}
462
463int
464send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
465 const struct GNUNET_HashCode *key,
466 const struct GNUNET_MESSENGER_Message *message)
467{
468 GNUNET_assert((handle) && (key) && (message));
469
470 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key);
471
472 if (!id)
473 {
474 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "It is required to be a member of a room to send messages!\n");
475 return GNUNET_NO;
476 }
477
478 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (handle->service, key);
479
480 if (!room)
481 {
482 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "The room (%s) is unknown!\n", GNUNET_h2s (key));
483 return GNUNET_NO;
484 }
485
486 struct GNUNET_MESSENGER_Message *msg = copy_message(message);
487
488 GNUNET_memcpy(&(msg->header.sender_id), id, sizeof(*id));
489
490 return send_room_message (room, handle, msg);
491}
492
493static const struct GNUNET_HashCode*
494get_next_member_session_contect(const struct GNUNET_MESSENGER_MemberSession *session)
495{
496 if (session->next)
497 return get_next_member_session_contect (session->next);
498 else
499 return get_member_session_context(session);
500}
501
502static const struct GNUNET_MESSENGER_MemberSession*
503get_handle_member_session (struct GNUNET_MESSENGER_SrvHandle *handle,
504 struct GNUNET_MESSENGER_SrvRoom *room,
505 const struct GNUNET_HashCode *key)
506{
507 GNUNET_assert((handle) && (room) && (key) && (handle->service));
508
509 const struct GNUNET_ShortHashCode *id = get_handle_member_id(handle, key);
510
511 if (!id)
512 return NULL;
513
514 struct GNUNET_MESSENGER_MemberStore *store = get_room_member_store(room);
515 struct GNUNET_MESSENGER_Member *member = get_store_member(store, id);
516
517 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(handle);
518
519 if (!ego)
520 return NULL;
521
522 return get_member_session(member, &(ego->pub));
523}
524
525void
526notify_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
527 struct GNUNET_MESSENGER_SrvRoom *room,
528 const struct GNUNET_MESSENGER_MemberSession *session,
529 const struct GNUNET_MESSENGER_Message *message,
530 const struct GNUNET_HashCode *hash)
531{
532 GNUNET_assert((handle) && (room) && (session) && (message) && (hash));
533
534 const struct GNUNET_HashCode *key = get_room_key(room);
535
536 if ((!handle->mq) || (!get_handle_member_id (handle, key)))
537 {
538 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notifying client about message requires membership!\n");
539 return;
540 }
541
542 const struct GNUNET_IDENTITY_PublicKey *pubkey = get_contact_key(session->contact);
543
544 struct GNUNET_HashCode sender;
545 GNUNET_CRYPTO_hash(pubkey, sizeof(*pubkey), &sender);
546
547 const struct GNUNET_HashCode *context = get_next_member_session_contect (session);
548
549 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying client about message: %s\n", GNUNET_h2s (hash));
550
551 struct GNUNET_MESSENGER_Message *private_message = NULL;
552
553 if (GNUNET_MESSENGER_KIND_PRIVATE == message->header.kind)
554 {
555 private_message = copy_message(message);
556
557 if (GNUNET_YES != decrypt_message(private_message, &(get_handle_ego(handle)->priv)))
558 {
559 destroy_message(private_message);
560 private_message = NULL;
561 }
562 else
563 message = private_message;
564 }
565
566 struct GNUNET_MESSENGER_RecvMessage *msg;
567 struct GNUNET_MQ_Envelope *env;
568
569 uint16_t length = get_message_size (message, GNUNET_YES);
570
571 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE);
572
573 GNUNET_memcpy(&(msg->key), key, sizeof(msg->key));
574 GNUNET_memcpy(&(msg->sender), &sender, sizeof(msg->sender));
575 GNUNET_memcpy(&(msg->context), context, sizeof(msg->context));
576 GNUNET_memcpy(&(msg->hash), hash, sizeof(msg->hash));
577
578 msg->flags = (uint32_t) GNUNET_MESSENGER_FLAG_NONE;
579
580 if (get_handle_member_session(handle, room, key) == session)
581 msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_SENT;
582
583 if (private_message)
584 msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_PRIVATE;
585
586 char *buffer = ((char*) msg) + sizeof(*msg);
587 encode_message (message, length, buffer, GNUNET_YES);
588
589 if (private_message)
590 destroy_message(private_message);
591
592 GNUNET_MQ_send (handle->mq, env);
593}
594
595static int
596callback_scan_for_rooms (void *cls,
597 const char *filename)
598{
599 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
600
601 if ((strlen(filename) <= 4) || (0 != strcmp(filename + strlen(filename) - 4, ".cfg")))
602 return GNUNET_OK;
603
604 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load room configuration of handle: %s\n", filename);
605
606 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
607
608 if ((GNUNET_YES == GNUNET_DISK_file_test (filename)) && (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, filename)))
609 {
610 struct GNUNET_HashCode key;
611 struct GNUNET_ShortHashCode member_id;
612
613 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "key", &key, sizeof(key))) &&
614 (GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "member_id", &member_id, sizeof(member_id))))
615 change_handle_member_id (handle, &key, &member_id);
616 }
617
618 GNUNET_CONFIGURATION_destroy (cfg);
619 return GNUNET_OK;
620}
621
622void
623load_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
624{
625 GNUNET_assert(handle);
626
627 char *id_dir;
628 get_handle_data_subdir (handle, handle->name, &id_dir);
629
630 if (GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_YES))
631 {
632 char *scan_dir;
633 GNUNET_asprintf (&scan_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
634
635 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
636 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_rooms, handle);
637
638 GNUNET_free(scan_dir);
639 }
640
641 GNUNET_free(id_dir);
642}
643
644static int
645iterate_save_rooms (void *cls,
646 const struct GNUNET_HashCode *key,
647 void *value)
648{
649 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
650 struct GNUNET_ShortHashCode *member_id = value;
651
652 char *id_dir;
653 get_handle_data_subdir (handle, handle->name, &id_dir);
654
655 char *filename;
656 GNUNET_asprintf (&filename, "%s%s%c%s.cfg", id_dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (key));
657 GNUNET_free(id_dir);
658
659 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save room configuration of handle: %s\n", filename);
660
661 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
662
663 char *key_data = GNUNET_STRINGS_data_to_string_alloc (key, sizeof(*key));
664
665 if (key_data)
666 {
667 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "key", key_data);
668
669 GNUNET_free(key_data);
670 }
671
672 char *member_id_data = GNUNET_STRINGS_data_to_string_alloc (member_id, sizeof(*member_id));
673
674 if (member_id_data)
675 {
676 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "member_id", member_id_data);
677
678 GNUNET_free(member_id_data);
679 }
680
681 GNUNET_CONFIGURATION_write (cfg, filename);
682 GNUNET_CONFIGURATION_destroy (cfg);
683
684 GNUNET_free(filename);
685
686 return GNUNET_YES;
687}
688
689void
690save_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
691{
692 GNUNET_assert(handle);
693
694 char *id_dir;
695 get_handle_data_subdir (handle, handle->name, &id_dir);
696
697 if ((GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_NO)) || (GNUNET_OK
698 == GNUNET_DISK_directory_create (id_dir)))
699 {
700 char *save_dir;
701 GNUNET_asprintf (&save_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
702
703 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
704 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
705 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_save_rooms, handle);
706
707 GNUNET_free(save_dir);
708 }
709
710 GNUNET_free(id_dir);
711}