aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/gnunet-service-messenger_member_session.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/gnunet-service-messenger_member_session.c')
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.c759
1 files changed, 0 insertions, 759 deletions
diff --git a/src/messenger/gnunet-service-messenger_member_session.c b/src/messenger/gnunet-service-messenger_member_session.c
deleted file mode 100644
index 846dbbe2b..000000000
--- a/src/messenger/gnunet-service-messenger_member_session.c
+++ /dev/null
@@ -1,759 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 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_member_session.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member_session.h"
27
28#include "gnunet-service-messenger_room.h"
29#include "gnunet-service-messenger_message_store.h"
30
31#include "messenger_api_contact_store.h"
32
33struct GNUNET_MESSENGER_MemberSession*
34create_member_session (struct GNUNET_MESSENGER_Member *member,
35 const struct GNUNET_IDENTITY_PublicKey *pubkey)
36{
37 if ((!member) || (!pubkey) || (!(member->store)))
38 return NULL;
39
40 struct GNUNET_MESSENGER_MemberSession *session = GNUNET_new(struct GNUNET_MESSENGER_MemberSession);
41 session->member = member;
42
43 GNUNET_memcpy(&(session->public_key), pubkey, sizeof(session->public_key));
44
45 get_context_from_member (
46 get_member_session_key (session),
47 get_member_session_id (session),
48 &(session->context)
49 );
50
51 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
52
53 session->contact = get_store_contact(
54 store,
55 get_member_session_context (session),
56 get_member_session_public_key (session)
57 );
58
59 if (!(session->contact))
60 {
61 GNUNET_free(session);
62 return NULL;
63 }
64
65 increase_contact_rc (session->contact);
66
67 session->history = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
68
69 init_list_messages(&(session->messages));
70
71 session->prev = NULL;
72 session->next = NULL;
73
74 session->start = GNUNET_TIME_absolute_get();
75
76 session->closed = GNUNET_NO;
77 session->completed = GNUNET_NO;
78
79 return session;
80}
81
82static void
83check_member_session_completion (struct GNUNET_MESSENGER_MemberSession *session)
84{
85 GNUNET_assert (session);
86
87 if (!session->messages.tail)
88 {
89 session->completed = GNUNET_YES;
90 goto completion;
91 }
92
93 const struct GNUNET_HashCode* start = &(session->messages.head->hash);
94 const struct GNUNET_HashCode* end = &(session->messages.tail->hash);
95
96 struct GNUNET_MESSENGER_ListMessages level;
97 init_list_messages(&level);
98
99 add_to_list_messages(&level, end);
100
101 struct GNUNET_MESSENGER_MessageStore *store = get_room_message_store(session->member->store->room);
102
103 struct GNUNET_MESSENGER_ListMessages list;
104 init_list_messages(&list);
105
106 while (level.head)
107 {
108 struct GNUNET_MESSENGER_ListMessage *element;
109
110 for (element = level.head; element; element = element->next)
111 {
112 const struct GNUNET_MESSENGER_MessageLink *link = get_store_message_link(
113 store, &(element->hash), GNUNET_NO
114 );
115
116 if (!link)
117 continue;
118
119 add_to_list_messages(&list, &(link->first));
120
121 if (GNUNET_YES == link->multiple)
122 add_to_list_messages(&list, &(link->second));
123 }
124
125 clear_list_messages(&level);
126
127 for (element = list.head; element; element = element->next)
128 if (GNUNET_YES == check_member_session_history(session, &(element->hash), GNUNET_YES))
129 break;
130
131 if (element)
132 if (0 != GNUNET_CRYPTO_hash_cmp(&(element->hash), start))
133 add_to_list_messages(&level, &(element->hash));
134 else
135 session->completed = GNUNET_YES;
136 else
137 copy_list_messages(&level, &list);
138
139 clear_list_messages(&list);
140 }
141
142completion:
143 if (GNUNET_YES == is_member_session_completed(session))
144 {
145 GNUNET_CONTAINER_multihashmap_destroy (session->history);
146
147 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
148
149 if ((session->contact) && (GNUNET_YES == decrease_contact_rc (session->contact)))
150 remove_store_contact (
151 store,
152 session->contact,
153 get_member_session_context(session)
154 );
155
156 session->contact = NULL;
157 }
158}
159
160static int
161iterate_copy_history (void *cls,
162 const struct GNUNET_HashCode *key,
163 void *value)
164{
165 struct GNUNET_MESSENGER_MemberSession *next = cls;
166
167 GNUNET_CONTAINER_multihashmap_put(next->history, key, (value? next : NULL),
168 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
169
170 return GNUNET_YES;
171}
172
173struct GNUNET_MESSENGER_MemberSession*
174switch_member_session (struct GNUNET_MESSENGER_MemberSession *session,
175 const struct GNUNET_MESSENGER_Message *message,
176 const struct GNUNET_HashCode *hash)
177{
178 if ((!session) || (!message) || (!hash))
179 return NULL;
180
181 GNUNET_assert((GNUNET_MESSENGER_KIND_ID == message->header.kind) ||
182 (GNUNET_MESSENGER_KIND_KEY == message->header.kind));
183
184 struct GNUNET_MESSENGER_MemberSession *next = GNUNET_new(struct GNUNET_MESSENGER_MemberSession);
185
186 if (GNUNET_MESSENGER_KIND_ID == message->header.kind)
187 next->member = add_store_member(session->member->store, &(message->body.id.id));
188 else
189 next->member = session->member;
190
191 if (GNUNET_MESSENGER_KIND_KEY == message->header.kind)
192 GNUNET_memcpy(&(next->public_key), &(message->body.key.key), sizeof(next->public_key));
193 else
194 GNUNET_memcpy(&(next->public_key), get_member_session_public_key(session), sizeof(next->public_key));
195
196 get_context_from_member (
197 get_member_session_key (next),
198 get_member_session_id (next),
199 &(next->context)
200 );
201
202 update_store_contact(
203 get_member_contact_store(next->member->store),
204 get_member_session_contact(session),
205 get_member_session_context(session),
206 get_member_session_context(next),
207 get_member_session_public_key(next)
208 );
209
210 next->contact = get_member_session_contact(session);
211
212 if (!(next->contact))
213 {
214 GNUNET_free(next);
215 return NULL;
216 }
217
218 increase_contact_rc (next->contact);
219
220 next->history = GNUNET_CONTAINER_multihashmap_create(
221 GNUNET_CONTAINER_multihashmap_size(session->history), GNUNET_NO
222 );
223
224 GNUNET_CONTAINER_multihashmap_iterate(session->history, iterate_copy_history, next);
225
226 init_list_messages(&(next->messages));
227 copy_list_messages(&(next->messages), &(session->messages));
228
229 session->next = next;
230 next->prev = session;
231 next->next = NULL;
232
233 next->start = GNUNET_TIME_absolute_get();
234
235 session->closed = GNUNET_YES;
236 next->closed = GNUNET_NO;
237 next->completed = GNUNET_NO;
238
239 check_member_session_completion (session);
240
241 return next;
242}
243
244void
245destroy_member_session(struct GNUNET_MESSENGER_MemberSession* session)
246{
247 GNUNET_assert (session);
248
249 GNUNET_CONTAINER_multihashmap_destroy (session->history);
250
251 clear_list_messages (&(session->messages));
252
253 struct GNUNET_MESSENGER_Contact *contact = get_member_session_contact (session);
254
255 if ((contact) && (GNUNET_YES == decrease_contact_rc (contact)))
256 remove_store_contact (
257 get_member_contact_store(session->member->store),
258 contact,
259 get_member_session_context(session)
260 );
261
262 GNUNET_free(session);
263}
264
265int
266reset_member_session (struct GNUNET_MESSENGER_MemberSession* session,
267 const struct GNUNET_HashCode *hash)
268{
269 GNUNET_assert ((session) && (hash));
270
271 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
272 struct GNUNET_MESSENGER_Contact *contact = get_store_contact(
273 store,
274 get_member_session_context (session),
275 get_member_session_public_key (session)
276 );
277
278 if (!contact)
279 return GNUNET_SYSERR;
280
281 if (contact == session->contact)
282 goto clear_messages;
283
284 session->contact = contact;
285 increase_contact_rc (session->contact);
286
287clear_messages:
288 clear_list_messages(&(session->messages));
289 add_to_list_messages(&(session->messages), hash);
290
291 session->next = NULL;
292 session->closed = GNUNET_NO;
293 session->completed = GNUNET_NO;
294
295 return GNUNET_OK;
296}
297
298void
299close_member_session (struct GNUNET_MESSENGER_MemberSession* session)
300{
301 GNUNET_assert (session);
302
303 session->closed = GNUNET_YES;
304 check_member_session_completion (session);
305}
306
307int
308is_member_session_closed (const struct GNUNET_MESSENGER_MemberSession* session)
309{
310 GNUNET_assert(session);
311
312 return session->closed;
313}
314
315int
316is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session)
317{
318 GNUNET_assert(session);
319
320 return session->completed;
321}
322
323struct GNUNET_TIME_Absolute
324get_member_session_start (const struct GNUNET_MESSENGER_MemberSession* session)
325{
326 GNUNET_assert(session);
327
328 if (session->prev)
329 return get_member_session_start(session->prev);
330
331 return session->start;
332}
333
334const struct GNUNET_HashCode*
335get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session)
336{
337 GNUNET_assert((session) && (session->member));
338
339 return get_member_store_key(session->member->store);
340}
341
342const struct GNUNET_ShortHashCode*
343get_member_session_id (const struct GNUNET_MESSENGER_MemberSession* session)
344{
345 GNUNET_assert(session);
346
347 return get_member_id(session->member);
348}
349
350const struct GNUNET_IDENTITY_PublicKey*
351get_member_session_public_key (const struct GNUNET_MESSENGER_MemberSession* session)
352{
353 GNUNET_assert(session);
354
355 return &(session->public_key);
356}
357
358const struct GNUNET_HashCode*
359get_member_session_context (const struct GNUNET_MESSENGER_MemberSession* session)
360{
361 GNUNET_assert(session);
362
363 return &(session->context);
364}
365
366struct GNUNET_MESSENGER_Contact*
367get_member_session_contact (struct GNUNET_MESSENGER_MemberSession* session)
368{
369 GNUNET_assert (session);
370
371 return session->contact;
372}
373
374int verify_member_session_as_sender (const struct GNUNET_MESSENGER_MemberSession *session,
375 const struct GNUNET_MESSENGER_Message *message,
376 const struct GNUNET_HashCode *hash)
377{
378 GNUNET_assert((session) && (message) && (hash));
379
380 if (GNUNET_YES == is_member_session_completed(session))
381 return GNUNET_SYSERR;
382
383 if (0 != GNUNET_memcmp(get_member_session_id(session), &(message->header.sender_id)))
384 return GNUNET_SYSERR;
385
386 return verify_message(message, hash, get_member_session_public_key(session));
387}
388
389int
390check_member_session_history (const struct GNUNET_MESSENGER_MemberSession *session,
391 const struct GNUNET_HashCode *hash, int ownership)
392{
393 GNUNET_assert((session) && (hash));
394
395 if (GNUNET_YES == ownership)
396 return (NULL != GNUNET_CONTAINER_multihashmap_get(session->history, hash)? GNUNET_YES : GNUNET_NO);
397 else
398 return GNUNET_CONTAINER_multihashmap_contains(session->history, hash);
399}
400
401static void
402update_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
403 const struct GNUNET_HashCode *hash, int ownership)
404{
405 GNUNET_assert ((session) && (hash));
406
407 if ((GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(session->history, hash, (GNUNET_YES == ownership? session : NULL),
408 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) && (session->next))
409 update_member_chain_history (session->next, hash, ownership);
410}
411
412void
413update_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
414 const struct GNUNET_MESSENGER_Message *message,
415 const struct GNUNET_HashCode *hash)
416{
417 GNUNET_assert((session) && (message) && (hash));
418
419 if (GNUNET_YES == is_member_session_completed(session))
420 return;
421
422 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating sessions history (%s) += (%s)\n",
423 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
424
425 if (GNUNET_OK == verify_member_session_as_sender (session, message, hash))
426 {
427 if (GNUNET_YES == is_message_session_bound (message))
428 add_to_list_messages(&(session->messages), hash);
429
430 update_member_chain_history (session, hash, GNUNET_YES);
431 }
432 else
433 update_member_chain_history (session, hash, GNUNET_NO);
434
435 if (GNUNET_YES == session->closed)
436 check_member_session_completion(session);
437}
438
439static void
440clear_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
441 const struct GNUNET_HashCode *hash)
442{
443 GNUNET_assert ((session) && (hash));
444
445 if ((0 < GNUNET_CONTAINER_multihashmap_remove_all(session->history, hash)) && (session->next))
446 clear_member_session_history(session->next, hash);
447}
448
449void
450clear_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
451 const struct GNUNET_HashCode *hash)
452{
453 GNUNET_assert((session) && (hash));
454
455 clear_member_chain_history (session, hash);
456}
457
458struct GNUNET_MESSENGER_MemberSessionHistoryEntry
459{
460 struct GNUNET_HashCode hash;
461 unsigned char ownership;
462};
463
464static void
465load_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
466 const char *path)
467{
468 GNUNET_assert((session) && (path));
469
470 if (GNUNET_YES != GNUNET_DISK_file_test (path))
471 return;
472
473 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
474
475 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
476 path, GNUNET_DISK_OPEN_READ, permission
477 );
478
479 if (!handle)
480 return;
481
482 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
483
484 struct GNUNET_MESSENGER_MemberSessionHistoryEntry entry;
485 ssize_t len;
486
487 int status;
488
489 do {
490 len = GNUNET_DISK_file_read(handle, &(entry.hash), sizeof(entry.hash));
491
492 if (len != sizeof(entry.hash))
493 break;
494
495 len = GNUNET_DISK_file_read(handle, &(entry.ownership), sizeof(entry.ownership));
496
497 if (len != sizeof(entry.ownership))
498 break;
499
500 status = GNUNET_CONTAINER_multihashmap_put(session->history, &(entry.hash), (entry.ownership? session : NULL),
501 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
502 } while (status == GNUNET_OK);
503
504 GNUNET_DISK_file_close(handle);
505}
506
507void
508load_member_session (struct GNUNET_MESSENGER_Member *member,
509 const char *directory)
510{
511 GNUNET_assert ((member) && (directory));
512
513 char *config_file;
514 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
515
516 struct GNUNET_MESSENGER_MemberSession *session = NULL;
517
518 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
519 goto free_config;
520
521 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load session configuration of member: %s\n", config_file);
522
523 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
524
525 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
526 {
527 char *key_data;
528
529 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "key", &key_data))
530 goto destroy_config;
531
532 struct GNUNET_IDENTITY_PublicKey key;
533
534 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &key);
535
536 GNUNET_free(key_data);
537
538 if (GNUNET_OK != key_return)
539 goto destroy_config;
540
541 session = create_member_session(member, &key);
542
543 unsigned long long numeric_value;
544
545 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "start", &numeric_value))
546 session->start.abs_value_us = numeric_value;
547
548 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "closed", &numeric_value))
549 session->closed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO);
550
551 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "completed", &numeric_value))
552 session->completed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO);
553 }
554
555destroy_config:
556 GNUNET_CONFIGURATION_destroy (cfg);
557
558free_config:
559 GNUNET_free(config_file);
560
561 if (!session)
562 return;
563
564 char *history_file;
565 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
566
567 load_member_session_history (session, history_file);
568 GNUNET_free(history_file);
569
570 char *messages_file;
571 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
572
573 load_list_messages(&(session->messages), messages_file);
574 GNUNET_free(messages_file);
575
576 add_member_session(member, session);
577}
578
579static struct GNUNET_MESSENGER_MemberSession*
580get_cycle_safe_next_session (struct GNUNET_MESSENGER_MemberSession *session,
581 struct GNUNET_MESSENGER_MemberSession *next)
582{
583 if (!next)
584 return NULL;
585
586 struct GNUNET_MESSENGER_MemberSession *check = next;
587
588 do {
589 if (check == session)
590 return NULL;
591
592 check = check->next;
593 } while (check);
594
595 return next;
596}
597
598void
599load_member_session_next (struct GNUNET_MESSENGER_MemberSession *session,
600 const char *directory)
601{
602 GNUNET_assert ((session) && (directory));
603
604 char *config_file;
605 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
606
607 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
608 goto free_config;
609
610 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load next session configuration of member: %s\n", config_file);
611
612 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
613
614 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
615 {
616 char *key_data;
617
618 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "next_key", &key_data))
619 goto destroy_config;
620
621 struct GNUNET_IDENTITY_PublicKey next_key;
622
623 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &next_key);
624
625 GNUNET_free(key_data);
626
627 if (GNUNET_OK != key_return)
628 goto destroy_config;
629
630 struct GNUNET_ShortHashCode next_id;
631
632 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "session", "next_id", &next_id, sizeof(next_id)))
633 goto destroy_config;
634
635 struct GNUNET_MESSENGER_Member *member = get_store_member(session->member->store, &next_id);
636
637 session->next = get_cycle_safe_next_session(
638 session, member? get_member_session (member, &next_key) : NULL
639 );
640
641 if (session->next)
642 session->next->prev = session;
643 }
644
645destroy_config:
646 GNUNET_CONFIGURATION_destroy (cfg);
647
648free_config:
649 GNUNET_free(config_file);
650}
651
652static int
653iterate_save_member_session_history_hentries (void *cls,
654 const struct GNUNET_HashCode *key,
655 void *value)
656{
657 struct GNUNET_DISK_FileHandle *handle = cls;
658 unsigned char ownership = value? GNUNET_YES : GNUNET_NO;
659
660 GNUNET_DISK_file_write(handle, key, sizeof(*key));
661 GNUNET_DISK_file_write(handle, &ownership, sizeof(ownership));
662
663 return GNUNET_YES;
664}
665
666static void
667save_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
668 const char *path)
669{
670 GNUNET_assert((session) && (path));
671
672 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
673
674 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
675 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
676 );
677
678 if (!handle)
679 return;
680
681 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
682
683 GNUNET_CONTAINER_multihashmap_iterate(
684 session->history,
685 iterate_save_member_session_history_hentries,
686 handle
687 );
688
689 GNUNET_DISK_file_sync(handle);
690 GNUNET_DISK_file_close(handle);
691}
692
693void
694save_member_session (struct GNUNET_MESSENGER_MemberSession *session,
695 const char *directory)
696{
697 GNUNET_assert ((session) && (directory));
698
699 char *config_file;
700 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
701
702 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save session configuration of member: %s\n", config_file);
703
704 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
705
706 char *key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session));
707
708 if (key_data)
709 {
710 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "key", key_data);
711
712 GNUNET_free(key_data);
713 }
714
715 if (session->next)
716 {
717 const struct GNUNET_ShortHashCode *next_id = get_member_session_id(session->next);
718
719 char *next_id_data = GNUNET_STRINGS_data_to_string_alloc (next_id, sizeof(*next_id));
720
721 if (next_id_data)
722 {
723 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_id", next_id_data);
724
725 GNUNET_free(next_id_data);
726 }
727
728 key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session->next));
729
730 if (key_data)
731 {
732 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_key", key_data);
733
734 GNUNET_free(key_data);
735 }
736 }
737
738 GNUNET_CONFIGURATION_set_value_number(cfg, "session", "start", session->start.abs_value_us);
739
740 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "closed", session->closed);
741 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "completed", session->completed);
742
743 GNUNET_CONFIGURATION_write (cfg, config_file);
744 GNUNET_CONFIGURATION_destroy (cfg);
745
746 GNUNET_free(config_file);
747
748 char *history_file;
749 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
750
751 save_member_session_history (session, history_file);
752 GNUNET_free(history_file);
753
754 char *messages_file;
755 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
756
757 save_list_messages(&(session->messages), messages_file);
758 GNUNET_free(messages_file);
759}