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