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