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