GNUnet  0.11.x
gnunet-service-messenger_member.c
Go to the documentation of this file.
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  */
27 
29 
32  const struct GNUNET_ShortHashCode *id)
33 {
35 
37 
38  member->store = store;
39 
40  if (id)
41  GNUNET_memcpy(&(member->id), id, sizeof(member->id));
42  else if (GNUNET_YES != generate_free_member_id(&(member->id), store->members))
43  {
44  GNUNET_free (member);
45  return NULL;
46  }
47 
49 
50  return member;
51 }
52 
53 static int
55  const struct GNUNET_HashCode *key,
56  void *value)
57 {
58  struct GNUNET_MESSENGER_MemberSession *session = value;
59  destroy_member_session(session);
60  return GNUNET_YES;
61 }
62 
63 void
65 {
67 
70 
72 }
73 
74 const struct GNUNET_ShortHashCode*
75 get_member_id (const struct GNUNET_MESSENGER_Member *member)
76 {
77  GNUNET_assert (member);
78 
79  return &(member->id);
80 }
81 
82 static int
84  const char *filename)
85 {
86  struct GNUNET_MESSENGER_Member *member = cls;
87 
89  {
90  char *directory;
91 
92  GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
93 
94  load_member_session(member, directory);
95  GNUNET_free (directory);
96  }
97 
98  return GNUNET_OK;
99 }
100 
101 void
103  const char *directory)
104 {
105  GNUNET_assert ((store) && (directory));
106 
107  char *config_file;
108  GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
109 
110  struct GNUNET_MESSENGER_Member *member = NULL;
111 
113  goto free_config;
114 
115  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load member configuration: %s\n", config_file);
116 
118 
120  {
121  struct GNUNET_ShortHashCode id;
122 
123  if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "member", "id", &id, sizeof(id)))
124  goto destroy_config;
125 
126  member = add_store_member(store, &id);
127  }
128 
129 destroy_config:
130 
132 
133 free_config:
135 
136  if (!member)
137  return;
138 
139  char *scan_dir;
140  GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
141 
144 
146 }
147 
148 static int
150  const struct GNUNET_HashCode *key,
151  void *value)
152 {
153  const char* sessions_directory = cls;
154 
155  char* load_dir;
156  GNUNET_asprintf (&load_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
157 
158  struct GNUNET_MESSENGER_MemberSession *session = value;
159 
161  load_member_session_next (session, load_dir);
162 
163  GNUNET_free (load_dir);
164  return GNUNET_YES;
165 }
166 
167 void
169  const char *directory)
170 {
171  GNUNET_assert ((member) && (directory));
172 
173  char* load_dir;
174  GNUNET_asprintf (&load_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
175 
177 
178  GNUNET_free(load_dir);
179 }
180 
181 static int
183  const struct GNUNET_HashCode *key,
184  void *value)
185 {
186  const char* sessions_directory = cls;
187 
188  char* save_dir;
189  GNUNET_asprintf (&save_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
190 
191  struct GNUNET_MESSENGER_MemberSession *session = value;
192 
193  if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
194  (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
195  save_member_session (session, save_dir);
196 
197  GNUNET_free (save_dir);
198  return GNUNET_YES;
199 }
200 
201 void
203  const char *directory)
204 {
205  GNUNET_assert ((member) && (directory));
206 
207  char *config_file;
208  GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
209 
210  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save member configuration: %s\n", config_file);
211 
213 
214  char *id_data = GNUNET_STRINGS_data_to_string_alloc (&(member->id), sizeof(member->id));
215 
216  if (id_data)
217  {
218  GNUNET_CONFIGURATION_set_value_string (cfg, "member", "id", id_data);
219 
220  GNUNET_free(id_data);
221  }
222 
225 
227 
228  char* save_dir;
229  GNUNET_asprintf (&save_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
230 
231  if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
232  (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
234 
235  GNUNET_free(save_dir);
236 }
237 
238 static void
240  struct GNUNET_MESSENGER_MemberSession *next)
241 {
242  GNUNET_assert((session) && (next));
243 
244  if (session == next)
245  return;
246 
247  if (next->next)
248  sync_session_contact_from_next (session, next->next);
249  else
250  session->contact = next->contact;
251 }
252 
253 static int
255  const struct GNUNET_HashCode *key,
256  void *value)
257 {
258  struct GNUNET_MESSENGER_MemberSession *session = value;
259 
260  if (session->next)
261  sync_session_contact_from_next (session, session->next);
262 
263  return GNUNET_YES;
264 }
265 
266 void
268 {
270 
272 }
273 
277 {
279 
280  struct GNUNET_HashCode hash;
281  GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
282 
283  return GNUNET_CONTAINER_multihashmap_get(member->sessions, &hash);
284 }
285 
288  const struct GNUNET_HashCode *hash;
289 
291 };
292 
293 static int
295  const struct GNUNET_HashCode *key,
296  void *value)
297 {
298  struct GNUNET_MESSENGER_ClosureSearchSession* search = cls;
299  struct GNUNET_MESSENGER_MemberSession *session = value;
300 
301  if (GNUNET_OK != verify_member_session_as_sender(session, search->message, search->hash))
302  return GNUNET_YES;
303 
304  search->match = session;
305  return GNUNET_NO;
306 }
307 
308 static struct GNUNET_MESSENGER_MemberSession*
311 {
313 
314  if (session)
315  return session;
316 
318 
319  if (session)
320  add_member_session(member, session);
321 
322  return session;
323 }
324 
327  const struct GNUNET_MESSENGER_Message *message,
328  const struct GNUNET_HashCode *hash)
329 {
330  GNUNET_assert ((member) && (message) && (hash) &&
331  (0 == GNUNET_memcmp(&(member->id), &(message->header.sender_id))));
332 
333  if (GNUNET_MESSENGER_KIND_INFO == message->header.kind)
334  return try_member_session(member, &(message->body.info.host_key));
335  else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
336  return try_member_session(member, &(message->body.join.key));
337 
339 
340  search.message = message;
341  search.hash = hash;
342 
343  search.match = NULL;
345 
346  return search.match;
347 }
348 
349 void
351  struct GNUNET_MESSENGER_MemberSession *session)
352 {
353  if (!session)
354  return;
355 
356  GNUNET_assert((member) && (session->member == member));
357 
358  const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
359 
360  struct GNUNET_HashCode hash;
361  GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
362 
364  member->sessions, &hash, session,
366  GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Adding a member session failed: %s\n",
367  GNUNET_h2s(&hash));
368 }
369 
370 void
372  struct GNUNET_MESSENGER_MemberSession *session)
373 {
374  GNUNET_assert ((member) && (session) && (session->member == member));
375 
376  const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
377 
378  struct GNUNET_HashCode hash;
379  GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
380 
381  if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(member->sessions, &hash, session))
382  GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Removing a member session failed: %s\n",
383  GNUNET_h2s(&hash));
384 }
385 
388  void *cls;
389 };
390 
391 static int
393  const struct GNUNET_HashCode *key,
394  void *value)
395 {
397  struct GNUNET_MESSENGER_MemberSession *session = value;
398 
399  return iterate->it (iterate->cls, get_member_session_public_key(session), session);
400 }
401 
402 int
405  void *cls)
406 {
407  GNUNET_assert ((member) && (member->sessions) && (it));
408 
410 
411  iterate.it = it;
412  iterate.cls = cls;
413 
415 }
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static char * config_file
Set to the name of the config file used.
Definition: gnunet-arm.c:84
static struct GNUNET_IDENTITY_Handle * id
Handle to identity service.
struct GNUNET_HashCode key
The key used in the DHT.
static char * filename
static char * value
Value of the record to add/remove.
static struct GNUNET_MESSENGER_MemberSession * try_member_session(struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
struct GNUNET_MESSENGER_Member * create_member(struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
Creates and allocates a new member of a room with an optionally defined or random id.
void remove_member_session(struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
Removes a given member session from its member.
static int iterate_sync_session_contact(void *cls, const struct GNUNET_HashCode *key, void *value)
static int iterate_search_session(void *cls, const struct GNUNET_HashCode *key, void *value)
static void sync_session_contact_from_next(struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_MESSENGER_MemberSession *next)
struct GNUNET_MESSENGER_MemberSession * get_member_session(const struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
Returns the member session of a member identified by a given public key.
void save_member(struct GNUNET_MESSENGER_Member *member, const char *directory)
Saves data from a member into a directory which can be load to restore the member completely.
void destroy_member(struct GNUNET_MESSENGER_Member *member)
Destroys a member and frees its memory fully.
static int iterate_save_session(void *cls, const struct GNUNET_HashCode *key, void *value)
void load_member_next_sessions(const struct GNUNET_MESSENGER_Member *member, const char *directory)
Loads data about next sessions from a directory into an empty loaded member which does not contain a ...
void add_member_session(struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
Adds a given member session to its member.
void sync_member_contacts(struct GNUNET_MESSENGER_Member *member)
Synchronizes contacts between all sessions from a given member and other sessions which are linked to...
static int callback_scan_for_sessions(void *cls, const char *filename)
int iterate_member_sessions(struct GNUNET_MESSENGER_Member *member, GNUNET_MESSENGER_MemberIteratorCallback it, void *cls)
Iterate through all member sessions currently connected to a given member and call the provided itera...
const struct GNUNET_ShortHashCode * get_member_id(const struct GNUNET_MESSENGER_Member *member)
Returns the current id of a given member.
static int iterate_destroy_session(void *cls, const struct GNUNET_HashCode *key, void *value)
static int iterate_load_next_session(void *cls, const struct GNUNET_HashCode *key, void *value)
void load_member(struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
Loads data from a directory into a new allocated and created member of a store if the required inform...
struct GNUNET_MESSENGER_MemberSession * get_member_session_of(struct GNUNET_MESSENGER_Member *member, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
Returns the member session of a member using a public key which can verify the signature of a given m...
static int iterate_member_sessions_it(void *cls, const struct GNUNET_HashCode *key, void *value)
GNUnet MESSENGER service.
void destroy_member_session(struct GNUNET_MESSENGER_MemberSession *session)
Destroys a member session and frees its memory fully.
void load_member_session_next(struct GNUNET_MESSENGER_MemberSession *session, const char *directory)
Loads the connection from one session to another through the next attribute.
const struct GNUNET_IDENTITY_PublicKey * get_member_session_public_key(const struct GNUNET_MESSENGER_MemberSession *session)
Returns the public key from an EGO of a given member session.
int verify_member_session_as_sender(const struct GNUNET_MESSENGER_MemberSession *session, const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
Verifies a given member session as sender of a selected message and its hash.
void load_member_session(struct GNUNET_MESSENGER_Member *member, const char *directory)
Loads data from a directory into a new allocated and created member session of a member if the requir...
void save_member_session(struct GNUNET_MESSENGER_MemberSession *session, const char *directory)
Saves data from a member session into a directory which can be load to restore the member session com...
struct GNUNET_MESSENGER_MemberSession * create_member_session(struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *pubkey)
Creates and allocates a new member session of a member with a given public key.
struct GNUNET_MESSENGER_Member * add_store_member(struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
Adds a member to a store under a specific id and returns it on success.
int(* GNUNET_MESSENGER_MemberIteratorCallback)(void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key, struct GNUNET_MESSENGER_MemberSession *session)
#define GNUNET_log(kind,...)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
Definition: gnunet_common.h:95
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_NO
Definition: gnunet_common.h:94
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_data(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, void *buf, size_t buf_size)
Get Crockford32-encoded fixed-size binary data from a configuration.
void GNUNET_CONFIGURATION_set_value_string(struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *value)
Set a configuration value that should be a string.
struct GNUNET_CONFIGURATION_Handle * GNUNET_CONFIGURATION_create(void)
Create a new configuration object.
void GNUNET_CONFIGURATION_destroy(struct GNUNET_CONFIGURATION_Handle *cfg)
Destroy configuration object.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_parse(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Parse a configuration file, add all of the options in the file to the configuration environment.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_write(struct GNUNET_CONFIGURATION_Handle *cfg, const char *filename)
Write configuration file.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition: disk.c:482
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:404
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create(const char *dir)
Implementation of "mkdir -p".
Definition: disk.c:496
int GNUNET_DISK_directory_scan(const char *dir_name, GNUNET_FileNameCallback callback, void *callback_cls)
Scan a directory for files.
Definition: disk.c:814
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
int GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from the map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
int GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MulitHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST
, ' bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE...
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_free(ptr)
Wrapper around free.
@ GNUNET_MESSENGER_KIND_INFO
The info kind.
@ GNUNET_MESSENGER_KIND_JOIN
The join kind.
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:737
int generate_free_member_id(struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members)
Tries to generate an unused member id and store it into the id parameter.
#define DIR_SEPARATOR
Definition: platform.h:164
A 512-bit hashcode.
An identity key as per LSD0001.
GNUNET_MESSENGER_MemberIteratorCallback it
const struct GNUNET_MESSENGER_Message * message
struct GNUNET_MESSENGER_MemberSession * match
struct GNUNET_MESSENGER_MemberSession * next
struct GNUNET_CONTAINER_MultiShortmap * members
struct GNUNET_CONTAINER_MultiHashMap * sessions
struct GNUNET_MESSENGER_MemberStore * store
struct GNUNET_ShortHashCode id
struct GNUNET_MESSENGER_MessageJoin join
struct GNUNET_MESSENGER_MessageInfo info
enum GNUNET_MESSENGER_MessageKind kind
The kind of the message.
struct GNUNET_ShortHashCode sender_id
The senders id inside of the room the message was sent in.
struct GNUNET_IDENTITY_PublicKey host_key
The senders key to verify its signatures.
struct GNUNET_IDENTITY_PublicKey key
The senders public key to verify its signatures.
struct GNUNET_MESSENGER_MessageHeader header
Header.
struct GNUNET_MESSENGER_MessageBody body
Body.
A 256-bit hashcode.