aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/gnunet-service-messenger_room.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/gnunet-service-messenger_room.c')
-rw-r--r--src/messenger/gnunet-service-messenger_room.c1092
1 files changed, 565 insertions, 527 deletions
diff --git a/src/messenger/gnunet-service-messenger_room.c b/src/messenger/gnunet-service-messenger_room.c
index 7383e1d20..e0bec7991 100644
--- a/src/messenger/gnunet-service-messenger_room.c
+++ b/src/messenger/gnunet-service-messenger_room.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 GNUnet e.V. 3 Copyright (C) 2020--2021 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
@@ -25,10 +25,19 @@
25 25
26#include "gnunet-service-messenger_room.h" 26#include "gnunet-service-messenger_room.h"
27 27
28#include "gnunet-service-messenger_member.h"
29#include "gnunet-service-messenger_member_session.h"
30
28#include "gnunet-service-messenger_message_kind.h" 31#include "gnunet-service-messenger_message_kind.h"
32#include "gnunet-service-messenger_message_handle.h"
33#include "gnunet-service-messenger_message_send.h"
29 34
35#include "gnunet-service-messenger_operation.h"
36
37#include "gnunet-service-messenger.h"
30#include "gnunet-service-messenger_service.h" 38#include "gnunet-service-messenger_service.h"
31#include "gnunet-service-messenger_util.h" 39#include "gnunet-service-messenger_tunnel.h"
40#include "messenger_api_util.h"
32 41
33static void 42static void
34idle_request_room_messages (void *cls); 43idle_request_room_messages (void *cls);
@@ -47,11 +56,10 @@ create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_Hash
47 GNUNET_memcpy(&(room->key), key, sizeof(struct GNUNET_HashCode)); 56 GNUNET_memcpy(&(room->key), key, sizeof(struct GNUNET_HashCode));
48 57
49 room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO); 58 room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO);
50 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
51 room->member_infos = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
52 59
53 init_message_store (&(room->store)); 60 init_member_store(get_room_member_store(room), room);
54 room->requested = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 61 init_message_store (get_room_message_store(room));
62 init_operation_store(get_room_operation_store(room), room);
55 63
56 init_list_tunnels (&(room->basement)); 64 init_list_tunnels (&(room->basement));
57 init_list_messages (&(room->last_messages)); 65 init_list_messages (&(room->last_messages));
@@ -61,10 +69,8 @@ create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_Hash
61 init_list_messages (&(room->handling)); 69 init_list_messages (&(room->handling));
62 room->idle = NULL; 70 room->idle = NULL;
63 71
64 room->strict_access = GNUNET_NO;
65
66 if (room->service->dir) 72 if (room->service->dir)
67 load_service_room_and_messages (room->service, room); 73 load_room (room);
68 74
69 room->idle = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room); 75 room->idle = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room);
70 76
@@ -79,34 +85,8 @@ iterate_destroy_tunnels (void *cls, const struct GNUNET_PeerIdentity *key, void
79 return GNUNET_YES; 85 return GNUNET_YES;
80} 86}
81 87
82static int 88static void
83iterate_clear_members (void *cls, const struct GNUNET_ShortHashCode *key, void *value) 89handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room);
84{
85 struct GNUNET_MESSENGER_SrvContact *contact = value;
86
87 if (GNUNET_YES == decrease_contact_rc (contact))
88 {
89 struct GNUNET_MESSENGER_SrvRoom *room = cls;
90
91 const struct GNUNET_HashCode *id = get_contact_id_from_key (contact);
92
93 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->service->contacts, id, contact))
94 destroy_contact (contact);
95 }
96
97 return GNUNET_YES;
98}
99
100static int
101iterate_destroy_member_infos (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
102{
103 struct GNUNET_MESSENGER_MemberInfo *info = value;
104
105 clear_list_messages (&(info->session_messages));
106
107 GNUNET_free(info);
108 return GNUNET_YES;
109}
110 90
111void 91void
112destroy_room (struct GNUNET_MESSENGER_SrvRoom *room) 92destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
@@ -123,26 +103,18 @@ destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
123 if (room->port) 103 if (room->port)
124 GNUNET_CADET_close_port (room->port); 104 GNUNET_CADET_close_port (room->port);
125 105
126 merge_room_last_messages (room, room->host); 106 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels, NULL);
127
128 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels,
129 NULL);
130 107
131 handle_room_messages (room); 108 handle_room_messages (room);
132 109
133 if (room->service->dir) 110 if (room->service->dir)
134 save_service_room_and_messages (room->service, room); 111 save_room (room);
135
136 GNUNET_CONTAINER_multishortmap_iterate (room->members, iterate_clear_members, room);
137 GNUNET_CONTAINER_multishortmap_iterate (room->member_infos, iterate_destroy_member_infos, NULL);
138 112
139 clear_message_store (&(room->store)); 113 clear_member_store (get_room_member_store(room));
140 114 clear_message_store (get_room_message_store(room));
141 GNUNET_CONTAINER_multihashmap_destroy (room->requested); 115 clear_operation_store(get_room_operation_store(room));
142 116
143 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels); 117 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels);
144 GNUNET_CONTAINER_multishortmap_destroy (room->members);
145 GNUNET_CONTAINER_multishortmap_destroy (room->member_infos);
146 118
147 clear_list_tunnels (&(room->basement)); 119 clear_list_tunnels (&(room->basement));
148 clear_list_messages (&(room->last_messages)); 120 clear_list_messages (&(room->last_messages));
@@ -153,47 +125,28 @@ destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
153 GNUNET_free(room); 125 GNUNET_free(room);
154} 126}
155 127
156struct GNUNET_MESSENGER_SrvContact* 128struct GNUNET_MESSENGER_MemberStore*
157get_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id) 129get_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room)
158{ 130{
159 GNUNET_assert((room) && (room->members)); 131 GNUNET_assert(room);
160
161 return GNUNET_CONTAINER_multishortmap_get (room->members, id);
162}
163
164void
165add_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id,
166 const struct GNUNET_IDENTITY_PublicKey *pubkey)
167{
168 struct GNUNET_MESSENGER_SrvContact *contact = get_service_contact_by_pubkey (room->service, pubkey);
169 132
170 if (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put (room->members, id, contact, 133 return &(room->member_store);
171 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
172 increase_contact_rc (contact);
173} 134}
174 135
175struct GNUNET_MESSENGER_MemberInfo* 136struct GNUNET_MESSENGER_MessageStore*
176get_room_member_info (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id) 137get_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room)
177{ 138{
178 GNUNET_assert((room) && (room->member_infos)); 139 GNUNET_assert(room);
179 140
180 return GNUNET_CONTAINER_multishortmap_get (room->member_infos, id); 141 return &(room->message_store);
181} 142}
182 143
183struct GNUNET_ShortHashCode* 144struct GNUNET_MESSENGER_OperationStore*
184generate_room_member_id (const struct GNUNET_MESSENGER_SrvRoom *room) 145get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room)
185{ 146{
186 struct GNUNET_ShortHashCode *unique_id = GNUNET_new(struct GNUNET_ShortHashCode);
187
188 GNUNET_assert(room); 147 GNUNET_assert(room);
189 148
190 if (GNUNET_YES == generate_free_member_id (unique_id, room->members)) 149 return &(room->operation_store);
191 return unique_id;
192 else
193 {
194 GNUNET_free(unique_id);
195 return NULL;
196 }
197} 150}
198 151
199const struct GNUNET_ShortHashCode* 152const struct GNUNET_ShortHashCode*
@@ -201,7 +154,7 @@ get_room_host_id (const struct GNUNET_MESSENGER_SrvRoom *room)
201{ 154{
202 GNUNET_assert(room); 155 GNUNET_assert(room);
203 156
204 return get_handle_member_id (room->host, &(room->key)); 157 return get_handle_member_id (room->host, get_room_key(room));
205} 158}
206 159
207void 160void
@@ -209,47 +162,17 @@ change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_
209{ 162{
210 GNUNET_assert(room); 163 GNUNET_assert(room);
211 164
212 change_handle_member_id (room->host, &(room->key), unique_id); 165 change_handle_member_id (room->host, get_room_key(room), unique_id);
213} 166}
214 167
215static int 168static int
216send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 169send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
217 struct GNUNET_MESSENGER_SrvTunnel *tunnel) 170 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
218{ 171{
219 if (!handle) 172 if ((!handle) || (!is_tunnel_connected (tunnel)))
220 return GNUNET_NO;
221
222 merge_room_last_messages (room, handle);
223
224 if (!is_tunnel_connected (tunnel))
225 return GNUNET_NO;
226
227 struct GNUNET_MESSENGER_Message *message = create_message_info (get_handle_ego(handle), room->members);
228
229 if (!message)
230 return GNUNET_NO; 173 return GNUNET_NO;
231 174
232 if ((tunnel->peer_message) && (tunnel->contact_id)) 175 return send_tunnel_message (tunnel, handle, create_message_info (get_handle_ego (handle)));
233 {
234 GNUNET_memcpy(&(message->body.info.unique_id), &(tunnel->contact_id), sizeof(struct GNUNET_ShortHashCode));
235 GNUNET_free(tunnel->contact_id);
236
237 tunnel->contact_id = NULL;
238 }
239
240 struct GNUNET_HashCode hash;
241
242 send_tunnel_message (tunnel, handle, message, &hash);
243 destroy_message (message);
244
245 if (tunnel->contact_id)
246 {
247 GNUNET_free(tunnel->contact_id);
248
249 tunnel->contact_id = NULL;
250 }
251
252 return GNUNET_YES;
253} 176}
254 177
255static void* 178static void*
@@ -257,63 +180,51 @@ callback_room_connect (void *cls, struct GNUNET_CADET_Channel *channel, const st
257{ 180{
258 struct GNUNET_MESSENGER_SrvRoom *room = cls; 181 struct GNUNET_MESSENGER_SrvRoom *room = cls;
259 182
260 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, source); 183 struct GNUNET_MESSENGER_SrvTunnel *tunnel = create_tunnel (room, source);
261 184
262 if (tunnel) 185 if ((tunnel) &&
186 (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, source, tunnel,
187 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
263 { 188 {
264 if (GNUNET_YES == bind_tunnel (tunnel, channel)) 189 destroy_tunnel (tunnel);
265 { 190 tunnel = NULL;
266 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
267 return tunnel;
268 else
269 {
270 disconnect_tunnel (tunnel);
271 return NULL;
272 }
273 }
274 else
275 {
276 delayed_disconnect_channel (channel);
277 return NULL;
278 }
279 } 191 }
280 else 192
193 if (!tunnel)
281 { 194 {
282 tunnel = create_tunnel (room, source); 195 delayed_disconnect_channel (channel);
196 return NULL;
197 }
283 198
284 if ((GNUNET_YES == bind_tunnel (tunnel, channel)) && (GNUNET_OK 199 bind_tunnel(tunnel, channel);
285 == GNUNET_CONTAINER_multipeermap_put (room->tunnels, source, tunnel,
286 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
287 {
288 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
289 return tunnel;
290 else
291 {
292 GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source, tunnel);
293 200
294 disconnect_tunnel (tunnel); 201 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "New tunnel in room (%s) established to peer: %s\n",
295 destroy_tunnel (tunnel); 202 GNUNET_h2s(get_room_key(room)), GNUNET_i2s (source));
296 return NULL;
297 }
298 }
299 else
300 {
301 tunnel->channel = NULL;
302 destroy_tunnel (tunnel);
303 203
304 delayed_disconnect_channel (channel); 204 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
305 return NULL; 205 return tunnel;
306 } 206
307 } 207 disconnect_tunnel (tunnel);
208
209 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source, tunnel))
210 destroy_tunnel (tunnel);
211
212 return NULL;
308} 213}
309 214
310static int 215static int
311join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 216join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
312 const struct GNUNET_ShortHashCode *member_id) 217 struct GNUNET_MESSENGER_Member *member)
313{ 218{
314 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s(get_room_key(room)), GNUNET_sh2s(member_id)); 219 GNUNET_assert((room) && (handle) && (member));
220
221 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s (get_room_key (room)),
222 GNUNET_sh2s (get_member_id(member)));
223
224 if (GNUNET_OK != change_handle_member_id (handle, get_room_key(room), get_member_id(member)))
225 return GNUNET_NO;
315 226
316 struct GNUNET_MESSENGER_Message *message = create_message_join (get_handle_ego(handle)); 227 struct GNUNET_MESSENGER_Message *message = create_message_join (get_handle_ego (handle));
317 228
318 if (!message) 229 if (!message)
319 { 230 {
@@ -322,48 +233,74 @@ join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHan
322 return GNUNET_NO; 233 return GNUNET_NO;
323 } 234 }
324 235
325 struct GNUNET_HashCode hash; 236 return send_room_message (room, handle, message);
237}
326 238
327 send_room_message (room, handle, message, &hash); 239struct GNUNET_MESSENGER_MemberNotify
328 destroy_message (message); 240{
241 struct GNUNET_MESSENGER_SrvRoom *room;
242 struct GNUNET_MESSENGER_SrvHandle *handle;
243 struct GNUNET_MESSENGER_MemberSession *session;
244};
329 245
330 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_new(struct GNUNET_MESSENGER_MemberInfo); 246static int
247iterate_notify_about_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
248 struct GNUNET_MESSENGER_MemberSession *session)
249{
250 struct GNUNET_MESSENGER_MemberNotify *notify = cls;
331 251
332 info->access = GNUNET_MESSENGER_MEMBER_ALLOWED; 252 if (notify->session == session)
333 init_list_messages (&(info->session_messages)); 253 return GNUNET_YES;
334 254
335 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_put (room->member_infos, member_id, info, 255 struct GNUNET_MESSENGER_ListMessage *element;
336 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
337 {
338 change_handle_member_id (handle, &(room->key), member_id);
339 256
340 add_to_list_messages (&(info->session_messages), &hash); 257 for (element = session->messages.head; element; element = element->next)
341 return GNUNET_YES;
342 }
343 else
344 { 258 {
345 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Your member information could not be registered!\n"); 259 const struct GNUNET_MESSENGER_Message *message = get_room_message (
260 notify->room, notify->handle, &(element->hash), GNUNET_NO
261 );
346 262
347 GNUNET_free(info); 263 if (message)
348 return GNUNET_NO; 264 notify_handle_message (notify->handle, get_room_key(notify->room), session, message, &(element->hash));
349 } 265 }
266
267 return GNUNET_YES;
350} 268}
351 269
352static int 270static int
353join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) 271join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
354{ 272{
355 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, &(room->key)); 273 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, get_room_key(room));
274
275 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
276 struct GNUNET_MESSENGER_Member *member = add_store_member(member_store, member_id);
277
278 if (GNUNET_NO == join_room (room, handle, member))
279 return GNUNET_NO;
356 280
357 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, member_id); 281 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(handle);
282 struct GNUNET_MESSENGER_MemberSession *session = get_member_session (member, &(ego->pub));
358 283
359 if ((!info) && (GNUNET_NO == join_room (room, handle, member_id))) 284 if (!session)
285 {
286 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "A valid session is required to join a room!\n");
360 return GNUNET_NO; 287 return GNUNET_NO;
288 }
289
290 struct GNUNET_MESSENGER_MemberNotify notify;
291
292 notify.room = room;
293 notify.handle = handle;
294 notify.session = session;
295
296 iterate_store_members(get_room_member_store(room), iterate_notify_about_members, &notify);
361 297
362 return GNUNET_YES; 298 return GNUNET_YES;
363} 299}
364 300
365extern int 301extern int
366check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header); 302check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header);
303
367extern void 304extern void
368handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header); 305handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header);
369 306
@@ -373,24 +310,39 @@ callback_tunnel_disconnect (void *cls, const struct GNUNET_CADET_Channel *channe
373int 310int
374open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) 311open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
375{ 312{
313 GNUNET_assert((room) && (handle));
314
376 if (room->port) 315 if (room->port)
377 return join_room_locally (room, handle); 316 return join_room_locally (room, handle);
378 317
379 struct GNUNET_CADET_Handle *cadet = get_room_cadet (room); 318 struct GNUNET_CADET_Handle *cadet = get_room_cadet (room);
380 struct GNUNET_HashCode *key = get_room_key (room); 319 const struct GNUNET_HashCode *key = get_room_key (room);
381 320
382 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI, 321 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
383 struct GNUNET_MessageHeader, NULL), 322 struct GNUNET_MessageHeader, NULL),
384 GNUNET_MQ_handler_end() }; 323 GNUNET_MQ_handler_end() };
385 324
386 room->port = GNUNET_CADET_open_port (cadet, key, callback_room_connect, room, NULL, 325 room->port = GNUNET_CADET_open_port (cadet, key, callback_room_connect, room, NULL, callback_tunnel_disconnect,
387 callback_tunnel_disconnect, handlers); 326 handlers);
388 327
389 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, &(room->key)); 328 if (room->port)
329 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Port of room (%s) was opened!\n",
330 GNUNET_h2s(get_room_key(room)));
331 else
332 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Port of room (%s) could not be opened!\n",
333 GNUNET_h2s(get_room_key(room)));
334
335 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, get_room_key(room));
336
337 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
338 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, member_id);
390 339
391 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, member_id); 340 if (member)
341 goto exit_open_room;
392 342
393 if ((!info) && (GNUNET_NO == join_room (room, handle, member_id)) && (room->port)) 343 member = add_store_member(member_store, member_id);
344
345 if ((GNUNET_NO == join_room (room, handle, member)) && (room->port))
394 { 346 {
395 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not join the room, therefore it keeps closed!\n"); 347 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not join the room, therefore it keeps closed!\n");
396 348
@@ -400,102 +352,57 @@ open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHan
400 return GNUNET_NO; 352 return GNUNET_NO;
401 } 353 }
402 354
403 struct GNUNET_MESSENGER_Message *message = create_message_peer (room->service); 355exit_open_room:
404 356 return (room->port ? send_room_message (room, handle, create_message_peer (room->service)) : GNUNET_NO);
405 if (message)
406 {
407 struct GNUNET_HashCode hash;
408
409 send_room_message (room, handle, message, &hash);
410 destroy_message (message);
411 }
412
413 return (room->port ? GNUNET_YES : GNUNET_NO);
414} 357}
415 358
416int 359int
417entry_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 360enter_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
418 const struct GNUNET_PeerIdentity *door) 361 const struct GNUNET_PeerIdentity *door)
419{ 362{
420 if (room->peer_message) 363 GNUNET_assert((room) && (handle) && (door));
421 {
422 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, handle, room->peer_message, GNUNET_NO);
423 364
424 if (0 == GNUNET_memcmp(&(msg->body.peer.peer), door)) 365 struct GNUNET_PeerIdentity peer;
425 return join_room_locally (room, handle); 366
426 } 367 if ((GNUNET_OK == get_service_peer_identity (room->service, &peer)) &&
368 (0 == GNUNET_memcmp(&peer, door)))
369 return join_room_locally (room, handle);
427 370
428 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, door); 371 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, door);
429 372
430 if (tunnel) 373 if (!tunnel)
431 { 374 {
432 switch (connect_tunnel (tunnel)) 375 tunnel = create_tunnel (room, door);
376
377 if (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, door, tunnel,
378 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))
433 { 379 {
434 case GNUNET_YES: 380 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not connect to that door!\n");
435 return GNUNET_YES; 381 destroy_tunnel (tunnel);
436 case GNUNET_NO:
437 return join_room_locally (room, handle);
438 default:
439 return GNUNET_NO; 382 return GNUNET_NO;
440 } 383 }
441 } 384 }
442 385
443 tunnel = create_tunnel (room, door); 386 if (GNUNET_SYSERR == connect_tunnel (tunnel))
444
445 if ((GNUNET_YES == connect_tunnel (tunnel)) &&
446 (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (room->tunnels, door, tunnel,
447 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
448 return GNUNET_YES;
449 else
450 { 387 {
451 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not connect to that door!\n"); 388 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connection failure during entrance!\n");
452 389 GNUNET_CONTAINER_multipeermap_remove (room->tunnels, door, tunnel);
453 destroy_tunnel (tunnel); 390 destroy_tunnel (tunnel);
454 return GNUNET_NO; 391 return GNUNET_NO;
455 } 392 }
456}
457
458struct GNUNET_MESSENGER_SrvTunnelFinder
459{
460 const struct GNUNET_ShortHashCode *needle;
461 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
462};
463
464static int
465iterate_find_tunnel (void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
466{
467 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
468 struct GNUNET_MESSENGER_SrvTunnelFinder *finder = cls;
469
470 if ((tunnel->contact_id) && (0 == GNUNET_memcmp(tunnel->contact_id, finder->needle)))
471 {
472 finder->tunnel = tunnel;
473 return GNUNET_NO;
474 }
475
476 return GNUNET_YES;
477}
478
479struct GNUNET_MESSENGER_SrvTunnel*
480find_room_tunnel_to (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *contact_id)
481{
482 struct GNUNET_MESSENGER_SrvTunnelFinder finder;
483 393
484 finder.needle = contact_id; 394 return join_room_locally (room, handle);
485 finder.tunnel = NULL;
486
487 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_find_tunnel, &finder);
488
489 return finder.tunnel;
490} 395}
491 396
492struct GNUNET_MQ_Envelope* 397struct GNUNET_MQ_Envelope*
493pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 398pack_room_message (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_SrvHandle *handle,
494 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode) 399 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode)
495{ 400{
401 GNUNET_assert((room) && (handle) && (message) && (hash));
402
496 message->header.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); 403 message->header.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
497 404
498 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, &(room->key)); 405 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, get_room_key(room));
499 406
500 GNUNET_assert(id); 407 GNUNET_assert(id);
501 408
@@ -524,7 +431,8 @@ iterate_send_room_message (void *cls, const struct GNUNET_PeerIdentity *key, voi
524{ 431{
525 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value; 432 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
526 433
527 if ((!is_tunnel_connected (tunnel)) || (!tunnel->contact_id)) 434 if ((!is_tunnel_connected (tunnel)) ||
435 (get_tunnel_messenger_version(tunnel) < GNUNET_MESSENGER_VERSION))
528 return GNUNET_YES; 436 return GNUNET_YES;
529 437
530 struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls; 438 struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls;
@@ -540,80 +448,88 @@ iterate_send_room_message (void *cls, const struct GNUNET_PeerIdentity *key, voi
540 GNUNET_MESSENGER_PACK_MODE_ENVELOPE); 448 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
541 449
542 if (env) 450 if (env)
543 {
544 closure->message = copy_message (closure->message);
545 closure->packed = GNUNET_YES; 451 closure->packed = GNUNET_YES;
546 }
547 } 452 }
548 else 453 else
549 { 454 env = pack_message (closure->message, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
550 env = pack_message (closure->message, NULL, NULL,
551 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
552 }
553 455
554 if (env) 456 if (env)
555 send_tunnel_envelope (tunnel, closure->handle, env, closure->message, closure->hash); 457 send_tunnel_envelope (tunnel, env, closure->hash);
556 458
557 return GNUNET_YES; 459 return GNUNET_YES;
558} 460}
559 461
560void 462int
561callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls, 463update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
562 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 464 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
563 465
564void 466void
467callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
468 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
469
470int
565send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 471send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
566 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash) 472 struct GNUNET_MESSENGER_Message *message)
567{ 473{
568 struct GNUNET_MESSENGER_ClosureSendRoom closure; 474 GNUNET_assert((room) && (handle));
569
570 closure.room = room;
571 closure.handle = handle;
572 closure.exclude = NULL;
573 closure.message = message;
574 closure.hash = hash;
575 closure.packed = GNUNET_NO;
576 475
577 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure); 476 if (!message)
477 return GNUNET_NO;
578 478
579 if ((GNUNET_NO == closure.packed) && (closure.message == message)) 479 if (GNUNET_YES == is_message_session_bound(message))
580 { 480 merge_room_last_messages(room, handle);
581 pack_room_message (room, handle, message, hash,
582 GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
583 481
584 callback_room_sent (room, handle, NULL, copy_message (message), hash); 482 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Sending message from handle with member id: %s\n",
585 } 483 GNUNET_sh2s(get_handle_member_id(handle, get_room_key(room))));
586}
587 484
588void 485 struct GNUNET_HashCode hash;
589send_room_message_ext (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
590 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
591 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
592{
593 struct GNUNET_MESSENGER_ClosureSendRoom closure; 486 struct GNUNET_MESSENGER_ClosureSendRoom closure;
594 487
595 closure.room = room; 488 closure.room = room;
596 closure.handle = handle; 489 closure.handle = handle;
597 closure.exclude = tunnel; 490 closure.exclude = NULL;
598 closure.message = message; 491 closure.message = message;
599 closure.hash = hash; 492 closure.hash = &hash;
600 closure.packed = GNUNET_NO; 493 closure.packed = GNUNET_NO;
601 494
602 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure); 495 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
603 496
604 if ((GNUNET_NO == closure.packed) && (closure.message == message)) 497 if (GNUNET_NO == closure.packed)
605 { 498 pack_room_message (room, handle, message, &hash, GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
606 pack_room_message (room, handle, message, hash, 499
607 GNUNET_MESSENGER_PACK_MODE_UNKNOWN); 500 const int new_message = update_room_message (room, message, &hash);
608 501
609 callback_room_sent (room, handle, NULL, copy_message (message), hash); 502 if (GNUNET_YES != new_message)
503 return GNUNET_SYSERR;
504
505 switch (message->header.kind)
506 {
507 case GNUNET_MESSENGER_KIND_JOIN:
508 send_message_join (room, handle, message, &hash);
509 break;
510 case GNUNET_MESSENGER_KIND_PEER:
511 send_message_peer (room, handle, message, &hash);
512 break;
513 case GNUNET_MESSENGER_KIND_REQUEST:
514 send_message_request (room, handle, message, &hash);
515 break;
516 default:
517 break;
610 } 518 }
519
520 callback_room_handle_message (room, handle, message, &hash);
521 return GNUNET_YES;
611} 522}
612 523
613void 524void
614forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 525forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
615 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 526 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
616{ 527{
528 GNUNET_assert((room) && (tunnel));
529
530 if (!message)
531 return;
532
617 struct GNUNET_MESSENGER_ClosureSendRoom closure; 533 struct GNUNET_MESSENGER_ClosureSendRoom closure;
618 struct GNUNET_HashCode message_hash; 534 struct GNUNET_HashCode message_hash;
619 535
@@ -622,7 +538,7 @@ forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSE
622 closure.room = room; 538 closure.room = room;
623 closure.handle = NULL; 539 closure.handle = NULL;
624 closure.exclude = tunnel; 540 closure.exclude = tunnel;
625 closure.message = copy_message (message); 541 closure.message = message;
626 closure.hash = &message_hash; 542 closure.hash = &message_hash;
627 closure.packed = GNUNET_YES; 543 closure.packed = GNUNET_YES;
628 544
@@ -630,257 +546,241 @@ forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSE
630} 546}
631 547
632void 548void
633merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) 549check_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel)
634{ 550{
635 if (!handle) 551 if (!room->peer_message)
636 return; 552 return;
637 553
638 if (!room->last_messages.head) 554 const struct GNUNET_MESSENGER_Message *message = get_room_message(room, NULL, room->peer_message, GNUNET_NO);
639 return;
640 555
641 while (room->last_messages.head != room->last_messages.tail) 556 if (!message)
642 { 557 {
643 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.tail; 558 GNUNET_free(room->peer_message);
559 room->peer_message = NULL;
560 return;
561 }
644 562
645 struct GNUNET_MESSENGER_Message *message = create_message_merge (&(element->hash)); 563 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
564 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
646 565
647 if (message) 566 if (!member)
648 { 567 goto resend_peer_message;
649 struct GNUNET_HashCode hash;
650 568
651 send_room_message (room, handle, message, &hash); 569 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, room->peer_message);
652 destroy_message (message);
653 }
654 570
655 if (element->prev) 571 if (GNUNET_YES == is_member_session_closed(session))
656 GNUNET_CONTAINER_DLL_remove(room->last_messages.head, room->last_messages.tail, element); 572 goto resend_peer_message;
657 }
658}
659 573
660struct GNUNET_CADET_Handle* 574 if (tunnel)
661get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room) 575 forward_tunnel_message(tunnel, message, room->peer_message);
662{
663 return room->service->cadet;
664}
665 576
666struct GNUNET_HashCode* 577 return;
667get_room_key (struct GNUNET_MESSENGER_SrvRoom *room) 578
668{ 579resend_peer_message:
669 return &(room->key); 580 if (room->host)
581 send_room_message (room, room->host, create_message_peer (room->service));
670} 582}
671 583
672const struct GNUNET_MESSENGER_SrvTunnel* 584static void
673get_room_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer) 585merge_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
586 const struct GNUNET_HashCode *hash)
674{ 587{
675 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer); 588 GNUNET_assert((room) && (handle) && (hash));
589
590 send_room_message (room, handle, create_message_merge (hash));
676} 591}
677 592
678const struct GNUNET_MESSENGER_Message* 593void
679get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 594merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
680 const struct GNUNET_HashCode *hash, int request)
681{ 595{
682 const struct GNUNET_MESSENGER_Message *message = get_store_message (&(room->store), hash); 596 GNUNET_assert(room);
683 597
684 if ((message) || (!handle) || (GNUNET_YES != request) 598 if (!handle)
685 || (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->requested, hash))) 599 return;
686 return message;
687 600
688 struct GNUNET_MESSENGER_Message *request_msg = create_message_request (hash); 601 if (!room->last_messages.head)
602 return;
689 603
690 if (request_msg) 604 while (room->last_messages.head != room->last_messages.tail)
691 { 605 merge_room_message (room, handle, &(room->last_messages.tail->hash));
692 if (GNUNET_CONTAINER_multihashmap_put (room->requested, hash, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST) == GNUNET_OK) 606}
693 {
694 struct GNUNET_HashCode request_hash;
695 607
696 send_room_message (room, handle, request_msg, &request_hash); 608void
697 } 609callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
610{
611 const struct GNUNET_MESSENGER_Message *message = get_room_message(room, NULL, hash, GNUNET_NO);
698 612
699 destroy_message (request_msg); 613 if (message)
700 } 614 add_to_list_messages(&(room->last_messages), &(message->header.previous));
701 615
702 return message; 616 if (GNUNET_OK != delete_store_message (get_room_message_store(room), hash))
617 {
618 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Deletion of message failed! (%s)\n", GNUNET_h2s(hash));
619 return;
620 }
703} 621}
704 622
705void 623void
706callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls) 624callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
707{ 625{
708 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
709
710 if (!room->host) 626 if (!room->host)
711 return; 627 return;
712 628
713 struct GNUNET_PeerIdentity identity; 629 merge_room_message (room, room->host, hash);
714
715 GNUNET_PEER_resolve (tunnel->peer, &identity);
716
717 if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity))
718 {
719 struct GNUNET_MESSENGER_Message *message = create_message_miss (&identity);
720
721 if (message)
722 {
723 struct GNUNET_HashCode hash;
724
725 send_room_message (room, room->host, message, &hash);
726 destroy_message (message);
727 }
728 }
729} 630}
730 631
731int 632int
732callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, 633delete_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
733 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash) 634 const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay)
734{ 635{
735 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind) 636 GNUNET_assert((room) && (session) && (hash));
736 return GNUNET_SYSERR;
737 637
738 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, 638 const struct GNUNET_TIME_Relative forever = GNUNET_TIME_relative_get_forever_ ();
739 &(message->header.sender_id));
740 639
741 if (!contact) 640 if (0 == GNUNET_memcmp(&forever, &delay))
742 { 641 {
743 if (GNUNET_MESSENGER_KIND_INFO == message->header.kind) 642 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Deletion is delayed forever: operation is impossible!\n");
744 contact = get_service_contact_by_pubkey (room->service, &(message->body.info.host_key)); 643 return GNUNET_SYSERR;
745 else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
746 contact = get_service_contact_by_pubkey (room->service, &(message->body.join.key));
747 } 644 }
748 645
749 if ((!contact) || (GNUNET_SYSERR == verify_message (message, hash, get_contact_key (contact)))) 646 const struct GNUNET_MESSENGER_Message *message = get_room_message(room, NULL, hash, GNUNET_NO);
750 return GNUNET_SYSERR;
751 647
752 if (GNUNET_YES == room->strict_access) 648 if (!message)
649 return GNUNET_YES;
650
651 if (GNUNET_YES != check_member_session_history(session, hash, GNUNET_YES))
753 { 652 {
754 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, 653 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unpermitted request for deletion by member (%s) of message (%s)!\n",
755 &(message->header.sender_id)); 654 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
756 655
757 if ((info) && (GNUNET_MESSENGER_MEMBER_BLOCKED == info->access)) 656 return GNUNET_NO;
758 return GNUNET_SYSERR;
759 } 657 }
760 658
761 if (GNUNET_YES == contains_store_message (&(room->store), hash)) 659 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
762 return GNUNET_NO; 660
661 if (GNUNET_OK != use_store_operation(operation_store, hash, GNUNET_MESSENGER_OP_DELETE, delay))
662 {
663 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Deletion has failed: operation denied!\n");
664 return GNUNET_SYSERR;
665 }
763 666
764 return GNUNET_YES; 667 return GNUNET_YES;
765} 668}
766 669
767static void 670struct GNUNET_CADET_Handle*
768search_room_for_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash) 671get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room)
769{ 672{
770 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, room->host, hash, GNUNET_YES); 673 GNUNET_assert(room);
771 674
772 if (!message) 675 return room->service->cadet;
773 return; 676}
774 677
775 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind) 678const struct GNUNET_HashCode*
776 search_room_for_message (room, &(message->body.merge.previous)); 679get_room_key (const struct GNUNET_MESSENGER_SrvRoom *room)
680{
681 GNUNET_assert(room);
777 682
778 search_room_for_message (room, &(message->header.previous)); 683 return &(room->key);
779} 684}
780 685
781static void 686const struct GNUNET_MESSENGER_SrvTunnel*
782idle_request_room_messages (void *cls) 687get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer)
783{ 688{
784 struct GNUNET_MESSENGER_SrvRoom *room = cls; 689 GNUNET_assert((room) && (peer));
785 690
786 room->idle = NULL; 691 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer);
692}
787 693
788 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.head; 694const struct GNUNET_MESSENGER_Message*
695get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
696 const struct GNUNET_HashCode *hash, int request)
697{
698 GNUNET_assert((room) && (hash));
789 699
790 while (element) 700 const struct GNUNET_MESSENGER_Message *message = get_store_message (get_room_message_store(room), hash);
791 {
792 search_room_for_message (room, &(element->hash));
793 701
794 element = element->next; 702 if ((message) || (!handle) || (GNUNET_YES != request))
795 } 703 return message;
796 704
797 merge_room_last_messages (room, room->host); 705 struct GNUNET_MESSENGER_OperationStore* operation_store = get_room_operation_store(room);
798 706
799 room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_second_ (), 707 if (GNUNET_OK == use_store_operation(operation_store, hash, GNUNET_MESSENGER_OP_REQUEST, GNUNET_MESSENGER_REQUEST_DELAY))
800 GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, 708 send_room_message (room, handle, create_message_request (hash));
801 cls); 709
710 return NULL;
802} 711}
803 712
804void 713void
805update_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_Message *message, 714callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls)
806 const struct GNUNET_HashCode *hash)
807{ 715{
808 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.head; 716 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
809 struct GNUNET_MESSENGER_ListMessage *merging = NULL;
810
811 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
812 {
813 merging = room->last_messages.head;
814
815 while (merging)
816 {
817 if (0 == GNUNET_CRYPTO_hash_cmp (&(merging->hash), &(message->body.merge.previous)))
818 break;
819 717
820 merging = merging->next; 718 if (!room->host)
821 } 719 return;
822 720
823 if (merging) 721 struct GNUNET_PeerIdentity identity;
824 element = merging->next; 722 get_tunnel_peer_identity(tunnel, &identity);
825 }
826 723
827 while (element) 724 if ((GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove (room->tunnels, &identity, tunnel)) ||
828 { 725 (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains(room->tunnels, &identity)))
829 if (0 == GNUNET_CRYPTO_hash_cmp (&(element->hash), &(message->header.previous))) 726 return;
830 break;
831 727
832 element = element->next; 728 if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity))
833 } 729 send_room_message (room, room->host, create_message_miss (&identity));
730}
834 731
835 if ((merging) && (!element)) 732int
733callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls,
734 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash)
735{
736 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind)
836 { 737 {
837 element = merging; 738 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Message error: Kind is unknown! (%d)\n", message->header.kind);
838 merging = NULL; 739 return GNUNET_SYSERR;
839 } 740 }
840 741
841 if (element) 742 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message of kind: %s!\n",
842 { 743 GNUNET_MESSENGER_name_of_kind(message->header.kind));
843 GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode));
844 744
845 if (merging) 745 return GNUNET_OK;
846 GNUNET_CONTAINER_DLL_remove(room->last_messages.head, room->last_messages.tail, merging);
847 }
848 else
849 add_to_list_messages (&(room->last_messages), hash);
850
851 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (room->requested, hash))
852 GNUNET_CONTAINER_multihashmap_remove_all (room->requested, hash);
853} 746}
854 747
855void 748static void
856switch_room_member_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *old_id, 749idle_request_room_messages (void *cls)
857 const struct GNUNET_ShortHashCode *new_id, const struct GNUNET_HashCode *hash)
858{ 750{
859 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, old_id); 751 struct GNUNET_MESSENGER_SrvRoom *room = cls;
860
861 if ((contact) && (GNUNET_YES == GNUNET_CONTAINER_multishortmap_remove (room->members, old_id, contact)))
862 GNUNET_CONTAINER_multishortmap_put (room->members, new_id, contact,
863 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
864
865 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, old_id);
866 752
867 if ((!info) || (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove (room->member_infos, old_id, contact)) 753 room->idle = NULL;
868 || (GNUNET_YES != GNUNET_CONTAINER_multishortmap_put (room->member_infos, new_id, contact,
869 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
870 return;
871 754
872 if (hash) 755 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
873 add_to_list_messages (&(info->session_messages), hash); 756
757 if ((room->last_messages.head != room->last_messages.tail) &&
758 (GNUNET_MESSENGER_OP_UNKNOWN == get_store_operation_type(operation_store, &(room->last_messages.tail->hash))))
759 use_store_operation(
760 operation_store,
761 &(room->last_messages.tail->hash),
762 GNUNET_MESSENGER_OP_MERGE,
763 GNUNET_MESSENGER_MERGE_DELAY
764 );
765
766 room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (
767 GNUNET_MESSENGER_IDLE_DELAY,
768 GNUNET_SCHEDULER_PRIORITY_IDLE,
769 idle_request_room_messages,
770 cls
771 );
874} 772}
875 773
876void 774void
877rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room) 775rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
878{ 776{
777 GNUNET_assert(room);
778
879 struct GNUNET_PeerIdentity peer; 779 struct GNUNET_PeerIdentity peer;
880 size_t src; 780 size_t src;
881 781
882 if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) || (!find_list_tunnels (&(room->basement), &peer, 782 if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) ||
883 &src))) 783 (!find_list_tunnels (&(room->basement), &peer, &src)))
884 return; 784 return;
885 785
886 size_t count = count_of_tunnels (&(room->basement)); 786 size_t count = count_of_tunnels (&(room->basement));
@@ -918,7 +818,7 @@ rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
918 } 818 }
919} 819}
920 820
921void 821static void
922handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room) 822handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
923{ 823{
924 while (room->handling.head) 824 while (room->handling.head)
@@ -927,29 +827,159 @@ handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
927 827
928 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, room->host, &(element->hash), GNUNET_NO); 828 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, room->host, &(element->hash), GNUNET_NO);
929 829
930 if (msg) 830 if (!msg)
931 handle_service_message (room->service, room, msg, &(element->hash)); 831 goto finish_handling;
832
833 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
834 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, msg);
835
836 if (!member)
837 goto finish_handling;
838
839 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, msg, &(element->hash));
932 840
841 if (session)
842 handle_service_message (room->service, room, session, msg, &(element->hash));
843
844finish_handling:
933 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element); 845 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element);
934 GNUNET_free(element); 846 GNUNET_free(element);
935 } 847 }
936} 848}
937 849
938#include "gnunet-service-messenger_message_recv.h" 850static void
851remove_room_last_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
852{
853 remove_from_list_messages(&(room->last_messages), hash);
854
855 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
856
857 if (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, hash))
858 cancel_store_operation(operation_store, hash);
859}
860
861int
862update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
863 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
864{
865 GNUNET_assert((room) && (message) && (hash));
866
867 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
868
869 const int requested = (GNUNET_MESSENGER_OP_REQUEST == get_store_operation_type(operation_store, hash)?
870 GNUNET_YES : GNUNET_NO
871 );
872
873 if (GNUNET_YES == requested)
874 cancel_store_operation(operation_store, hash);
875
876 const struct GNUNET_MESSENGER_Message *old_message = get_room_message (room, NULL, hash, GNUNET_NO);
877
878 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle a message in room (%s).\n", GNUNET_h2s (get_room_key(room)));
879
880 if ((old_message) || (GNUNET_OK != put_store_message (get_room_message_store(room), hash, message)))
881 {
882 if (old_message != message)
883 destroy_message(message);
884
885 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Duplicate message got dropped!\n");
886 return GNUNET_NO;
887 }
888
889 if ((GNUNET_YES == requested) ||
890 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
891 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
892 return GNUNET_YES;
893
894 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
895 remove_room_last_message(room, &(message->body.merge.previous));
896 remove_room_last_message(room, &(message->header.previous));
897
898 add_to_list_messages (&(room->last_messages), hash);
899
900 return GNUNET_YES;
901}
902
903struct GNUNET_MESSENGER_MemberSessionCompletion
904{
905 struct GNUNET_MESSENGER_MemberSessionCompletion *prev;
906 struct GNUNET_MESSENGER_MemberSessionCompletion *next;
907
908 struct GNUNET_MESSENGER_MemberSession *session;
909};
910
911struct GNUNET_MESSENGER_MemberUpdate
912{
913 const struct GNUNET_MESSENGER_Message *message;
914 const struct GNUNET_HashCode *hash;
915
916 struct GNUNET_MESSENGER_MemberSessionCompletion *head;
917 struct GNUNET_MESSENGER_MemberSessionCompletion *tail;
918};
919
920static int
921iterate_update_member_sessions (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
922 struct GNUNET_MESSENGER_MemberSession *session)
923{
924 struct GNUNET_MESSENGER_MemberUpdate *update = cls;
925
926 update_member_session_history(session, update->message, update->hash);
927
928 if (GNUNET_YES == is_member_session_completed(session))
929 {
930 struct GNUNET_MESSENGER_MemberSessionCompletion *element = GNUNET_new(
931 struct GNUNET_MESSENGER_MemberSessionCompletion
932 );
933
934 element->session = session;
935
936 GNUNET_CONTAINER_DLL_insert_tail(update->head, update->tail, element);
937 }
938
939 return GNUNET_YES;
940}
939 941
940void 942void
941callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message, 943callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
942 const struct GNUNET_HashCode *hash) 944 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
943{ 945{
944 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; 946 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
947 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
948
949 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Callback for message (%s)\n", GNUNET_h2s (hash));
950
951 if (!member)
952 {
953 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Member is missing!\n");
954 return;
955 }
956
957 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
945 958
946 if (GNUNET_OK != put_store_message (&(room->store), hash, message)) 959 if (!session)
960 {
961 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Session is missing!\n");
947 return; 962 return;
963 }
964
965 struct GNUNET_MESSENGER_MemberUpdate update;
966 update.message = message;
967 update.hash = hash;
968
969 update.head = NULL;
970 update.tail = NULL;
971
972 iterate_store_members(member_store, iterate_update_member_sessions, &update);
973
974 while (update.head)
975 {
976 struct GNUNET_MESSENGER_MemberSessionCompletion *element = update.head;
948 977
949 update_room_last_messages (room, message, hash); 978 remove_member_session (element->session->member, element->session);
950 979
951 if (GNUNET_MESSENGER_KIND_INFO != message->header.kind) 980 GNUNET_CONTAINER_DLL_remove(update.head, update.tail, element);
952 forward_room_message (room, tunnel, message, hash); 981 GNUNET_free (element);
982 }
953 983
954 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES; 984 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES;
955 985
@@ -957,32 +987,29 @@ callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNU
957 987
958 switch (message->header.kind) 988 switch (message->header.kind)
959 { 989 {
960 case GNUNET_MESSENGER_KIND_INFO:
961 recv_message_info (room, tunnel, message, hash);
962 break;
963 case GNUNET_MESSENGER_KIND_JOIN: 990 case GNUNET_MESSENGER_KIND_JOIN:
964 recv_message_join (room, tunnel, message, hash); 991 handle_message_join (room, session, message, hash);
965 break; 992 break;
966 case GNUNET_MESSENGER_KIND_LEAVE: 993 case GNUNET_MESSENGER_KIND_LEAVE:
967 recv_message_leave (room, tunnel, message, hash); 994 handle_message_leave (room, session, message, hash);
968 break; 995 break;
969 case GNUNET_MESSENGER_KIND_NAME: 996 case GNUNET_MESSENGER_KIND_NAME:
970 recv_message_name (room, tunnel, message, hash); 997 handle_message_name (room, session, message, hash);
971 break; 998 break;
972 case GNUNET_MESSENGER_KIND_KEY: 999 case GNUNET_MESSENGER_KIND_KEY:
973 recv_message_key (room, tunnel, message, hash); 1000 handle_message_key (room, session, message, hash);
974 break; 1001 break;
975 case GNUNET_MESSENGER_KIND_PEER: 1002 case GNUNET_MESSENGER_KIND_PEER:
976 recv_message_peer (room, tunnel, message, hash); 1003 handle_message_peer (room, session, message, hash);
977 break; 1004 break;
978 case GNUNET_MESSENGER_KIND_ID: 1005 case GNUNET_MESSENGER_KIND_ID:
979 recv_message_id (room, tunnel, message, hash); 1006 handle_message_id (room, session, message, hash);
980 break; 1007 break;
981 case GNUNET_MESSENGER_KIND_MISS: 1008 case GNUNET_MESSENGER_KIND_MISS:
982 recv_message_miss (room, tunnel, message, hash); 1009 handle_message_miss (room, session, message, hash);
983 break; 1010 break;
984 case GNUNET_MESSENGER_KIND_REQUEST: 1011 case GNUNET_MESSENGER_KIND_DELETE:
985 recv_message_request (room, tunnel, message, hash); 1012 handle_message_delete (room, session, message, hash);
986 break; 1013 break;
987 default: 1014 default:
988 break; 1015 break;
@@ -992,60 +1019,71 @@ callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNU
992 handle_room_messages (room); 1019 handle_room_messages (room);
993} 1020}
994 1021
995#include "gnunet-service-messenger_message_send.h" 1022static void
1023get_room_data_subdir (struct GNUNET_MESSENGER_SrvRoom *room, char **dir)
1024{
1025 GNUNET_assert((room) && (dir));
1026
1027 GNUNET_asprintf (dir, "%s%s%c%s%c", room->service->dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (get_room_key(room)), DIR_SEPARATOR);
1028}
996 1029
997void 1030void
998callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls, 1031load_room (struct GNUNET_MESSENGER_SrvRoom *room)
999 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
1000{ 1032{
1001 const struct GNUNET_MESSENGER_Message *old_message = get_room_message (room, handle, hash, GNUNET_NO); 1033 GNUNET_assert(room);
1002 1034
1003 if ((old_message) || (GNUNET_OK != put_store_message (&(room->store), hash, message))) 1035 char *room_dir;
1036 get_room_data_subdir (room, &room_dir);
1037
1038 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
1004 { 1039 {
1005 if (old_message != message) 1040 load_member_store (get_room_member_store(room), room_dir);
1006 GNUNET_free(message); 1041 load_message_store (get_room_message_store(room), room_dir);
1042 load_operation_store(get_room_operation_store(room), room_dir);
1043
1044 char *basement_file;
1045 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1046
1047 load_list_tunnels(&(room->basement), basement_file);
1048 GNUNET_free(basement_file);
1049
1050 char *last_messages_file;
1051 GNUNET_asprintf (&last_messages_file, "%s%s", room_dir, "last_messages.list");
1052
1053 load_list_messages(&(room->last_messages), last_messages_file);
1054 GNUNET_free(last_messages_file);
1007 } 1055 }
1008 else
1009 {
1010 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; // may be NULL
1011 1056
1012 update_room_last_messages (room, message, hash); 1057 GNUNET_free(room_dir);
1058}
1059
1060void
1061save_room (struct GNUNET_MESSENGER_SrvRoom *room)
1062{
1063 GNUNET_assert(room);
1064
1065 char *room_dir;
1066 get_room_data_subdir (room, &room_dir);
1013 1067
1014 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES; 1068 if ((GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_NO)) ||
1069 (GNUNET_OK == GNUNET_DISK_directory_create (room_dir)))
1070 {
1071 save_member_store(get_room_member_store(room), room_dir);
1072 save_message_store (get_room_message_store(room), room_dir);
1073 save_operation_store(get_room_operation_store(room), room_dir);
1015 1074
1016 add_to_list_messages (&(room->handling), hash); 1075 char *basement_file;
1076 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1017 1077
1018 switch (message->header.kind) 1078 save_list_tunnels(&(room->basement), basement_file);
1019 { 1079 GNUNET_free(basement_file);
1020 case GNUNET_MESSENGER_KIND_INFO: 1080
1021 send_message_info (room, handle, tunnel, message, hash); 1081 char *last_messages_file;
1022 break; 1082 GNUNET_asprintf (&last_messages_file, "%s%s", room_dir, "last_messages.list");
1023 case GNUNET_MESSENGER_KIND_JOIN:
1024 send_message_join (room, handle, tunnel, message, hash);
1025 break;
1026 case GNUNET_MESSENGER_KIND_LEAVE:
1027 send_message_leave (room, handle, tunnel, message, hash);
1028 break;
1029 case GNUNET_MESSENGER_KIND_NAME:
1030 send_message_name (room, handle, tunnel, message, hash);
1031 break;
1032 case GNUNET_MESSENGER_KIND_KEY:
1033 send_message_key (room, handle, tunnel, message, hash);
1034 break;
1035 case GNUNET_MESSENGER_KIND_PEER:
1036 send_message_peer (room, handle, tunnel, message, hash);
1037 break;
1038 case GNUNET_MESSENGER_KIND_ID:
1039 send_message_id (room, handle, tunnel, message, hash);
1040 break;
1041 case GNUNET_MESSENGER_KIND_MISS:
1042 send_message_miss (room, handle, tunnel, message, hash);
1043 break;
1044 default:
1045 break;
1046 }
1047 1083
1048 if (GNUNET_YES == start_handle) 1084 save_list_messages(&(room->last_messages), last_messages_file);
1049 handle_room_messages (room); 1085 GNUNET_free(last_messages_file);
1050 } 1086 }
1087
1088 GNUNET_free(room_dir);
1051} 1089}