aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2021-03-20 13:53:23 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2021-04-04 17:58:11 +0200
commitac3aa3cc3a617bc54ed8beb2b5a30c0b95483525 (patch)
tree6e0444e568722f18501746665a07dfa3434c7ad6 /src
parent2413977f917534aa24ef562a28da193a2cdaa343 (diff)
downloadgnunet-ac3aa3cc3a617bc54ed8beb2b5a30c0b95483525.tar.gz
gnunet-ac3aa3cc3a617bc54ed8beb2b5a30c0b95483525.zip
-multiple fixes and correction regarding messenger service
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added message states to tunnels Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed requests for deleted messages returning previous ones Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added automatic solving of member id collissions Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added light timestamp verification Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed decoding asserts and member session forwarding Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added permission check for member sessions during local join Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/messenger/Makefile.am1
-rwxr-xr-xsrc/messenger/gnunet-service-messenger.c59
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.c20
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.h12
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.c14
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.c71
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.c7
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.h13
-rw-r--r--src/messenger/gnunet-service-messenger_message_state.c109
-rw-r--r--src/messenger/gnunet-service-messenger_message_state.h63
-rwxr-xr-xsrc/messenger/gnunet-service-messenger_message_store.c3
-rw-r--r--src/messenger/gnunet-service-messenger_room.c277
-rw-r--r--src/messenger/gnunet-service-messenger_room.h73
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.c30
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.h3
-rw-r--r--src/messenger/messenger_api.c2
-rwxr-xr-xsrc/messenger/messenger_api_message.c2
17 files changed, 587 insertions, 172 deletions
diff --git a/src/messenger/Makefile.am b/src/messenger/Makefile.am
index 2bb9ad922..3fc532e7e 100644
--- a/src/messenger/Makefile.am
+++ b/src/messenger/Makefile.am
@@ -68,6 +68,7 @@ gnunet_service_messenger_SOURCES = \
68 gnunet-service-messenger_message_kind.c gnunet-service-messenger_message_kind.h \ 68 gnunet-service-messenger_message_kind.c gnunet-service-messenger_message_kind.h \
69 gnunet-service-messenger_message_recv.c gnunet-service-messenger_message_recv.h \ 69 gnunet-service-messenger_message_recv.c gnunet-service-messenger_message_recv.h \
70 gnunet-service-messenger_message_send.c gnunet-service-messenger_message_send.h \ 70 gnunet-service-messenger_message_send.c gnunet-service-messenger_message_send.h \
71 gnunet-service-messenger_message_state.c gnunet-service-messenger_message_state.h \
71 gnunet-service-messenger_message_store.c gnunet-service-messenger_message_store.h \ 72 gnunet-service-messenger_message_store.c gnunet-service-messenger_message_store.h \
72 gnunet-service-messenger_operation_store.c gnunet-service-messenger_operation_store.h \ 73 gnunet-service-messenger_operation_store.c gnunet-service-messenger_operation_store.h \
73 gnunet-service-messenger_operation.c gnunet-service-messenger_operation.h \ 74 gnunet-service-messenger_operation.c gnunet-service-messenger_operation.h \
diff --git a/src/messenger/gnunet-service-messenger.c b/src/messenger/gnunet-service-messenger.c
index 76fb31d95..7edd76d32 100755
--- a/src/messenger/gnunet-service-messenger.c
+++ b/src/messenger/gnunet-service-messenger.c
@@ -25,6 +25,8 @@
25 25
26#include "gnunet-service-messenger.h" 26#include "gnunet-service-messenger.h"
27 27
28#include "gnunet-service-messenger_handle.h"
29#include "gnunet-service-messenger_message_kind.h"
28#include "gnunet-service-messenger_service.h" 30#include "gnunet-service-messenger_service.h"
29#include "messenger_api_message.h" 31#include "messenger_api_message.h"
30 32
@@ -209,6 +211,9 @@ check_for_message:
209 211
210 struct GNUNET_MESSENGER_Message message; 212 struct GNUNET_MESSENGER_Message message;
211 213
214 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN))
215 return GNUNET_NO;
216
212 if (GNUNET_YES != decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL)) 217 if (GNUNET_YES != decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL))
213 return GNUNET_NO; 218 return GNUNET_NO;
214 219
@@ -266,6 +271,35 @@ end_handling:
266} 271}
267 272
268static void 273static void
274callback_found_message (void *cls, struct GNUNET_MESSENGER_SrvRoom *room,
275 const struct GNUNET_MESSENGER_Message *message,
276 const struct GNUNET_HashCode *hash)
277{
278 struct GNUNET_MESSENGER_Client *msg_client = cls;
279
280 if (!message)
281 {
282 send_room_message(room, msg_client->handle, create_message_request(hash));
283 return;
284 }
285
286 struct GNUNET_MESSENGER_MemberStore *store = get_room_member_store(room);
287
288 struct GNUNET_MESSENGER_Member *member = get_store_member_of(store, message);
289
290 if (!member)
291 {
292 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sender of message (%s) unknown!\n", GNUNET_h2s (hash));
293 return;
294 }
295
296 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
297
298 if (session)
299 notify_handle_message (msg_client->handle, get_room_key(room), session, message, hash);
300}
301
302static void
269handle_get_message (void *cls, const struct GNUNET_MESSENGER_GetMessage *msg) 303handle_get_message (void *cls, const struct GNUNET_MESSENGER_GetMessage *msg)
270{ 304{
271 struct GNUNET_MESSENGER_Client *msg_client = cls; 305 struct GNUNET_MESSENGER_Client *msg_client = cls;
@@ -280,26 +314,27 @@ handle_get_message (void *cls, const struct GNUNET_MESSENGER_GetMessage *msg)
280 goto end_handling; 314 goto end_handling;
281 } 315 }
282 316
283 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, msg_client->handle, &(msg->hash), 317 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
284 GNUNET_YES);
285
286 if (!message)
287 goto end_handling;
288
289 struct GNUNET_MESSENGER_MemberStore *store = get_room_member_store(room);
290 318
291 struct GNUNET_MESSENGER_Member *member = get_store_member_of(store, message); 319 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, get_handle_member_id(
320 msg_client->handle, &(msg->key)
321 ));
292 322
293 if (!member) 323 if (!member)
294 { 324 {
295 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sender of message (%s) unknown!\n", GNUNET_h2s (&(msg->hash))); 325 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Member not valid to request a message!\n");
296 goto end_handling; 326 goto end_handling;
297 } 327 }
298 328
299 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, &(msg->hash)); 329 struct GNUNET_MESSENGER_MemberSession *session = get_member_session(member, &(get_handle_ego(msg_client->handle)->pub));
300 330
301 if (session) 331 if (!session)
302 notify_handle_message (msg_client->handle, get_room_key(room), session, message, &(msg->hash)); 332 {
333 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Session not valid to request a message!\n");
334 goto end_handling;
335 }
336
337 request_room_message (room, &(msg->hash), session, callback_found_message, msg_client);
303 338
304end_handling: 339end_handling:
305 GNUNET_SERVICE_client_continue (msg_client->client); 340 GNUNET_SERVICE_client_continue (msg_client->client);
diff --git a/src/messenger/gnunet-service-messenger_member_session.c b/src/messenger/gnunet-service-messenger_member_session.c
index 2e6eae59e..690c703b2 100644
--- a/src/messenger/gnunet-service-messenger_member_session.c
+++ b/src/messenger/gnunet-service-messenger_member_session.c
@@ -71,6 +71,8 @@ create_member_session (struct GNUNET_MESSENGER_Member *member,
71 session->prev = NULL; 71 session->prev = NULL;
72 session->next = NULL; 72 session->next = NULL;
73 73
74 session->start = GNUNET_TIME_absolute_get();
75
74 session->closed = GNUNET_NO; 76 session->closed = GNUNET_NO;
75 session->completed = GNUNET_NO; 77 session->completed = GNUNET_NO;
76 78
@@ -226,6 +228,8 @@ switch_member_session (struct GNUNET_MESSENGER_MemberSession *session,
226 next->prev = session; 228 next->prev = session;
227 next->next = NULL; 229 next->next = NULL;
228 230
231 next->start = GNUNET_TIME_absolute_get();
232
229 session->closed = GNUNET_YES; 233 session->closed = GNUNET_YES;
230 next->closed = GNUNET_NO; 234 next->closed = GNUNET_NO;
231 next->completed = GNUNET_NO; 235 next->completed = GNUNET_NO;
@@ -314,6 +318,17 @@ is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* sessio
314 return session->completed; 318 return session->completed;
315} 319}
316 320
321struct GNUNET_TIME_Absolute
322get_member_session_start (const struct GNUNET_MESSENGER_MemberSession* session)
323{
324 GNUNET_assert(session);
325
326 if (session->prev)
327 return get_member_session_start(session->prev);
328
329 return session->start;
330}
331
317const struct GNUNET_HashCode* 332const struct GNUNET_HashCode*
318get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session) 333get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session)
319{ 334{
@@ -521,6 +536,9 @@ load_member_session (struct GNUNET_MESSENGER_Member *member, const char *directo
521 536
522 unsigned long long numeric_value; 537 unsigned long long numeric_value;
523 538
539 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "start", &numeric_value))
540 session->start.abs_value_us = numeric_value;
541
524 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "closed", &numeric_value)) 542 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "closed", &numeric_value))
525 session->closed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO); 543 session->closed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO);
526 544
@@ -701,6 +719,8 @@ save_member_session (struct GNUNET_MESSENGER_MemberSession *session, const char
701 } 719 }
702 } 720 }
703 721
722 GNUNET_CONFIGURATION_set_value_number(cfg, "session", "start", session->start.abs_value_us);
723
704 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "closed", session->closed); 724 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "closed", session->closed);
705 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "completed", session->completed); 725 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "completed", session->completed);
706 726
diff --git a/src/messenger/gnunet-service-messenger_member_session.h b/src/messenger/gnunet-service-messenger_member_session.h
index cf4a6bb07..fa9c6b829 100644
--- a/src/messenger/gnunet-service-messenger_member_session.h
+++ b/src/messenger/gnunet-service-messenger_member_session.h
@@ -30,6 +30,7 @@
30#include "gnunet_crypto_lib.h" 30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h" 31#include "gnunet_container_lib.h"
32#include "gnunet_identity_service.h" 32#include "gnunet_identity_service.h"
33#include "gnunet_time_lib.h"
33 34
34#include "gnunet-service-messenger_member.h" 35#include "gnunet-service-messenger_member.h"
35 36
@@ -49,6 +50,8 @@ struct GNUNET_MESSENGER_MemberSession {
49 struct GNUNET_MESSENGER_MemberSession* prev; 50 struct GNUNET_MESSENGER_MemberSession* prev;
50 struct GNUNET_MESSENGER_MemberSession* next; 51 struct GNUNET_MESSENGER_MemberSession* next;
51 52
53 struct GNUNET_TIME_Absolute start;
54
52 int closed; 55 int closed;
53 int completed; 56 int completed;
54}; 57};
@@ -140,6 +143,15 @@ int
140is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session); 143is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session);
141 144
142/** 145/**
146 * Returns the timestamp of the member <i>session</i>'s start.
147 *
148 * @param[in] session Member session
149 * @return Absolute timestamp
150 */
151struct GNUNET_TIME_Absolute
152get_member_session_start (const struct GNUNET_MESSENGER_MemberSession* session);
153
154/**
143 * Returns the key of the room a given member <i>session</i> belongs to. 155 * Returns the key of the room a given member <i>session</i> belongs to.
144 * 156 *
145 * @param[in] session Member session 157 * @param[in] session Member session
diff --git a/src/messenger/gnunet-service-messenger_message_handle.c b/src/messenger/gnunet-service-messenger_message_handle.c
index c22e51fbf..1d489310c 100644
--- a/src/messenger/gnunet-service-messenger_message_handle.c
+++ b/src/messenger/gnunet-service-messenger_message_handle.c
@@ -44,6 +44,13 @@ handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSEN
44 44
45 if (GNUNET_OK != reset_member_session(session, hash)) 45 if (GNUNET_OK != reset_member_session(session, hash))
46 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Resetting member session failed!\n"); 46 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Resetting member session failed!\n");
47
48 solve_room_member_collisions (
49 room,
50 &(message->body.join.key),
51 &(message->header.sender_id),
52 GNUNET_TIME_absolute_ntoh(message->header.timestamp)
53 );
47} 54}
48 55
49void 56void
@@ -91,6 +98,13 @@ handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGE
91 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 98 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
92{ 99{
93 handle_session_switch (session, message, hash); 100 handle_session_switch (session, message, hash);
101
102 solve_room_member_collisions (
103 room,
104 get_member_session_public_key(session),
105 &(message->body.id.id),
106 GNUNET_TIME_absolute_ntoh(message->header.timestamp)
107 );
94} 108}
95 109
96void 110void
diff --git a/src/messenger/gnunet-service-messenger_message_recv.c b/src/messenger/gnunet-service-messenger_message_recv.c
index 8aab805d2..b2a5052d2 100644
--- a/src/messenger/gnunet-service-messenger_message_recv.c
+++ b/src/messenger/gnunet-service-messenger_message_recv.c
@@ -27,18 +27,46 @@
27 27
28#include "gnunet-service-messenger_operation.h" 28#include "gnunet-service-messenger_operation.h"
29 29
30static void
31forward_about_members (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
32 struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_CONTAINER_MultiHashMap *map)
33{
34 if (session->prev)
35 forward_about_members (room, tunnel, session->prev, map);
36
37 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
38 struct GNUNET_MESSENGER_ListMessage *element;
39
40 for (element = session->messages.head; element; element = element->next)
41 {
42 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, &(element->hash)))
43 continue;
44
45 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), NULL,
46 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
47 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Forwarding of session message could be duplicated!\n");
48
49 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, &(element->hash));
50
51 if (message)
52 forward_tunnel_message(tunnel, message, &(element->hash));
53 }
54}
55
30static int 56static int
31iterate_forward_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key, 57iterate_forward_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
32 struct GNUNET_MESSENGER_MemberSession *session) 58 struct GNUNET_MESSENGER_MemberSession *session)
33{ 59{
34 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; 60 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
35 struct GNUNET_MESSENGER_SrvRoom *room = tunnel->room;
36 61
37 struct GNUNET_MESSENGER_ListMessage *element; 62 if (GNUNET_YES == is_member_session_completed(session))
63 return GNUNET_YES;
38 64
39 for (element = session->messages.head; element; element = element->next) 65 struct GNUNET_CONTAINER_MultiHashMap *map = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
40 forward_tunnel_message(tunnel, get_room_message(room, NULL, &(element->hash), GNUNET_NO), &(element->hash));
41 66
67 forward_about_members (tunnel->room, tunnel, session, map);
68
69 GNUNET_CONTAINER_multihashmap_destroy(map);
42 return GNUNET_YES; 70 return GNUNET_YES;
43} 71}
44 72
@@ -97,32 +125,40 @@ recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGE
97 return GNUNET_YES; 125 return GNUNET_YES;
98} 126}
99 127
100int 128static void
101recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, 129callback_found_message (void *cls, struct GNUNET_MESSENGER_SrvRoom *room,
102 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 130 const struct GNUNET_MESSENGER_Message *message,
131 const struct GNUNET_HashCode *hash)
103{ 132{
104 const struct GNUNET_MESSENGER_Message *msg = get_room_message ( 133 struct GNUNET_MESSENGER_SrvTunnel *tunnel = tunnel;
105 room, NULL, &(message->body.request.hash), GNUNET_NO
106 );
107 134
108 if (!msg) 135 if (!message)
109 { 136 {
110 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room); 137 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
111 138
112 use_store_operation( 139 use_store_operation(
113 operation_store, 140 operation_store,
114 &(message->body.request.hash), 141 hash,
115 GNUNET_MESSENGER_OP_REQUEST, 142 GNUNET_MESSENGER_OP_REQUEST,
116 GNUNET_MESSENGER_REQUEST_DELAY 143 GNUNET_MESSENGER_REQUEST_DELAY
117 ); 144 );
118
119 return GNUNET_YES;
120 } 145 }
146 else
147 forward_tunnel_message (tunnel, message, hash);
148}
121 149
150/*
151 * Function returns GNUNET_NO to drop forwarding the request.
152 * It will only be forwarded if it can't be answered!
153 */
154int
155recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
156 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
157{
122 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room); 158 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
123 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message); 159 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
124 160
125 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Callback for message (%s)\n", GNUNET_h2s (hash)); 161 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Request for message (%s)\n", GNUNET_h2s (hash));
126 162
127 if (!member) 163 if (!member)
128 return GNUNET_NO; 164 return GNUNET_NO;
@@ -132,7 +168,8 @@ recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSE
132 if ((!session) || (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO))) 168 if ((!session) || (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO)))
133 return GNUNET_NO; 169 return GNUNET_NO;
134 170
135 forward_tunnel_message (tunnel, msg, &(message->body.request.hash)); 171 if (GNUNET_NO == request_room_message(room, &(message->body.request.hash), session, callback_found_message, tunnel))
172 return GNUNET_YES;
136 173
137 return GNUNET_NO; 174 return GNUNET_NO;
138} 175}
diff --git a/src/messenger/gnunet-service-messenger_message_send.c b/src/messenger/gnunet-service-messenger_message_send.c
index 59bbaea8d..a59a178cc 100644
--- a/src/messenger/gnunet-service-messenger_message_send.c
+++ b/src/messenger/gnunet-service-messenger_message_send.c
@@ -47,6 +47,13 @@ send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGE
47} 47}
48 48
49void 49void
50send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
51 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
52{
53 change_handle_member_id (handle, get_room_key(room), &(message->body.id.id));
54}
55
56void
50send_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 57send_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
51 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 58 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
52{ 59{
diff --git a/src/messenger/gnunet-service-messenger_message_send.h b/src/messenger/gnunet-service-messenger_message_send.h
index 8e3ff4495..63320ab17 100644
--- a/src/messenger/gnunet-service-messenger_message_send.h
+++ b/src/messenger/gnunet-service-messenger_message_send.h
@@ -61,6 +61,19 @@ send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGE
61 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); 61 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
62 62
63/** 63/**
64 * Handles a sent id message to update the handles member id in the room.
65 * (changing member id is useful to prevent collisions)
66 *
67 * @param[in/out] room Room of the message
68 * @param[in/out] handle Sending handle
69 * @param[in] message ID-Message
70 * @param[in] hash Hash of the message
71 */
72void
73send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
74 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
75
76/**
64 * Handles a sent request message to trigger the request operation for this service. 77 * Handles a sent request message to trigger the request operation for this service.
65 * (the request operation will deactivate the possibility of spamming requests) 78 * (the request operation will deactivate the possibility of spamming requests)
66 * 79 *
diff --git a/src/messenger/gnunet-service-messenger_message_state.c b/src/messenger/gnunet-service-messenger_message_state.c
new file mode 100644
index 000000000..cdd2d9712
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_message_state.c
@@ -0,0 +1,109 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_message_state.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_message_state.h"
27
28void
29init_message_state (struct GNUNET_MESSENGER_MessageState *state)
30{
31 GNUNET_assert(state);
32
33 init_list_messages (&(state->last_messages));
34}
35
36void
37clear_message_state (struct GNUNET_MESSENGER_MessageState *state)
38{
39 GNUNET_assert(state);
40
41 clear_list_messages (&(state->last_messages));
42}
43
44void
45get_message_state_chain_hash (const struct GNUNET_MESSENGER_MessageState *state,
46 struct GNUNET_HashCode *hash)
47{
48 GNUNET_assert((state) && (hash));
49
50 if (state->last_messages.head)
51 GNUNET_memcpy(hash, &(state->last_messages.head->hash), sizeof(*hash));
52 else
53 memset (hash, 0, sizeof(*hash));
54}
55
56const struct GNUNET_HashCode*
57get_message_state_merge_hash (const struct GNUNET_MESSENGER_MessageState *state)
58{
59 GNUNET_assert(state);
60
61 if (state->last_messages.head == state->last_messages.tail)
62 return NULL;
63
64 return &(state->last_messages.tail->hash);
65}
66
67void
68update_message_state (struct GNUNET_MESSENGER_MessageState *state, int requested,
69 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
70{
71 GNUNET_assert((state) && (message) && (hash));
72
73 if ((GNUNET_YES == requested) ||
74 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
75 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
76 return;
77
78 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
79 remove_from_list_messages(&(state->last_messages), &(message->body.merge.previous));
80 remove_from_list_messages(&(state->last_messages), &(message->header.previous));
81
82 add_to_list_messages (&(state->last_messages), hash);
83}
84
85void
86load_message_state (struct GNUNET_MESSENGER_MessageState *state, const char *path)
87{
88 GNUNET_assert((state) && (path));
89
90 char *last_messages_file;
91 GNUNET_asprintf (&last_messages_file, "%s%s", path, "last_messages.list");
92
93 load_list_messages(&(state->last_messages), last_messages_file);
94 GNUNET_free(last_messages_file);
95}
96
97void
98save_message_state (const struct GNUNET_MESSENGER_MessageState *state, const char *path)
99{
100 GNUNET_assert((state) && (path));
101
102 char *last_messages_file;
103 GNUNET_asprintf (&last_messages_file, "%s%s", path, "last_messages.list");
104
105 save_list_messages(&(state->last_messages), last_messages_file);
106 GNUNET_free(last_messages_file);
107}
108
109
diff --git a/src/messenger/gnunet-service-messenger_message_state.h b/src/messenger/gnunet-service-messenger_message_state.h
new file mode 100644
index 000000000..dc8671df4
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_message_state.h
@@ -0,0 +1,63 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_message_state.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_STATE_H
27#define GNUNET_SERVICE_MESSENGER_MESSAGE_STATE_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31
32#include "messenger_api_message.h"
33#include "gnunet-service-messenger_list_messages.h"
34
35struct GNUNET_MESSENGER_MessageState
36{
37 struct GNUNET_MESSENGER_ListMessages last_messages;
38};
39
40void
41init_message_state (struct GNUNET_MESSENGER_MessageState *state);
42
43void
44clear_message_state (struct GNUNET_MESSENGER_MessageState *state);
45
46void
47get_message_state_chain_hash (const struct GNUNET_MESSENGER_MessageState *state,
48 struct GNUNET_HashCode *hash);
49
50const struct GNUNET_HashCode*
51get_message_state_merge_hash (const struct GNUNET_MESSENGER_MessageState *state);
52
53void
54update_message_state (struct GNUNET_MESSENGER_MessageState *state, int requested,
55 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
56
57void
58load_message_state (struct GNUNET_MESSENGER_MessageState *state, const char *path);
59
60void
61save_message_state (const struct GNUNET_MESSENGER_MessageState *state, const char *path);
62
63#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_STATE_H
diff --git a/src/messenger/gnunet-service-messenger_message_store.c b/src/messenger/gnunet-service-messenger_message_store.c
index b143c6c98..1984eba21 100755
--- a/src/messenger/gnunet-service-messenger_message_store.c
+++ b/src/messenger/gnunet-service-messenger_message_store.c
@@ -408,7 +408,8 @@ get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNU
408 if (!buffer) 408 if (!buffer)
409 return NULL; 409 return NULL;
410 410
411 if (GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length) 411 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length) ||
412 (entry->length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN)))
412 goto free_buffer; 413 goto free_buffer;
413 414
414 message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN); 415 message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN);
diff --git a/src/messenger/gnunet-service-messenger_room.c b/src/messenger/gnunet-service-messenger_room.c
index 027df682c..e8fe5b1f3 100644
--- a/src/messenger/gnunet-service-messenger_room.c
+++ b/src/messenger/gnunet-service-messenger_room.c
@@ -62,7 +62,7 @@ create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_Hash
62 init_operation_store(get_room_operation_store(room), room); 62 init_operation_store(get_room_operation_store(room), room);
63 63
64 init_list_tunnels (&(room->basement)); 64 init_list_tunnels (&(room->basement));
65 init_list_messages (&(room->last_messages)); 65 init_message_state(&(room->state));
66 66
67 room->peer_message = NULL; 67 room->peer_message = NULL;
68 68
@@ -117,7 +117,7 @@ destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
117 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels); 117 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels);
118 118
119 clear_list_tunnels (&(room->basement)); 119 clear_list_tunnels (&(room->basement));
120 clear_list_messages (&(room->last_messages)); 120 clear_message_state(&(room->state));
121 121
122 if (room->peer_message) 122 if (room->peer_message)
123 GNUNET_free(room->peer_message); 123 GNUNET_free(room->peer_message);
@@ -149,22 +149,6 @@ get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room)
149 return &(room->operation_store); 149 return &(room->operation_store);
150} 150}
151 151
152const struct GNUNET_ShortHashCode*
153get_room_host_id (const struct GNUNET_MESSENGER_SrvRoom *room)
154{
155 GNUNET_assert(room);
156
157 return get_handle_member_id (room->host, get_room_key(room));
158}
159
160void
161change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *unique_id)
162{
163 GNUNET_assert(room);
164
165 change_handle_member_id (room->host, get_room_key(room), unique_id);
166}
167
168static int 152static int
169send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 153send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
170 struct GNUNET_MESSENGER_SrvTunnel *tunnel) 154 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
@@ -243,27 +227,50 @@ struct GNUNET_MESSENGER_MemberNotify
243 struct GNUNET_MESSENGER_MemberSession *session; 227 struct GNUNET_MESSENGER_MemberSession *session;
244}; 228};
245 229
246static int 230static void
247iterate_notify_about_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key, 231notify_about_members (struct GNUNET_MESSENGER_MemberNotify *notify, struct GNUNET_MESSENGER_MemberSession *session,
248 struct GNUNET_MESSENGER_MemberSession *session) 232 struct GNUNET_CONTAINER_MultiHashMap *map, int check_permission)
249{ 233{
250 struct GNUNET_MESSENGER_MemberNotify *notify = cls; 234 if (session->prev)
251 235 notify_about_members (notify, session->prev, map, GNUNET_YES);
252 if (notify->session == session)
253 return GNUNET_YES;
254 236
237 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(notify->room);
255 struct GNUNET_MESSENGER_ListMessage *element; 238 struct GNUNET_MESSENGER_ListMessage *element;
256 239
257 for (element = session->messages.head; element; element = element->next) 240 for (element = session->messages.head; element; element = element->next)
258 { 241 {
259 const struct GNUNET_MESSENGER_Message *message = get_room_message ( 242 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, &(element->hash)))
260 notify->room, notify->handle, &(element->hash), GNUNET_NO 243 continue;
261 ); 244
245 if ((GNUNET_YES == check_permission) &&
246 (GNUNET_YES != check_member_session_history(notify->session, &(element->hash), GNUNET_NO)))
247 continue;
248
249 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), NULL,
250 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
251 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notification of session message could be duplicated!\n");
252
253 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, &(element->hash));
262 254
263 if (message) 255 if (message)
264 notify_handle_message (notify->handle, get_room_key(notify->room), session, message, &(element->hash)); 256 notify_handle_message (notify->handle, get_room_key(notify->room), session, message, &(element->hash));
265 } 257 }
258}
259
260static int
261iterate_notify_about_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
262 struct GNUNET_MESSENGER_MemberSession *session)
263{
264 struct GNUNET_MESSENGER_MemberNotify *notify = cls;
266 265
266 if ((notify->session == session) || (GNUNET_YES == is_member_session_completed(session)))
267 return GNUNET_YES;
268
269 struct GNUNET_CONTAINER_MultiHashMap *map = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
270
271 notify_about_members (notify, session, map, GNUNET_NO);
272
273 GNUNET_CONTAINER_multihashmap_destroy(map);
267 return GNUNET_YES; 274 return GNUNET_YES;
268} 275}
269 276
@@ -407,11 +414,7 @@ pack_room_message (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNU
407 GNUNET_assert(id); 414 GNUNET_assert(id);
408 415
409 GNUNET_memcpy(&(message->header.sender_id), id, sizeof(struct GNUNET_ShortHashCode)); 416 GNUNET_memcpy(&(message->header.sender_id), id, sizeof(struct GNUNET_ShortHashCode));
410 417 get_message_state_chain_hash (&(room->state), &(message->header.previous));
411 if (room->last_messages.head)
412 GNUNET_memcpy(&(message->header.previous), &(room->last_messages.head->hash), sizeof(struct GNUNET_HashCode));
413 else
414 memset (&(message->header.previous), 0, sizeof(struct GNUNET_HashCode));
415 418
416 return pack_message (message, hash, get_handle_ego (handle), mode); 419 return pack_message (message, hash, get_handle_ego (handle), mode);
417} 420}
@@ -510,6 +513,9 @@ send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGE
510 case GNUNET_MESSENGER_KIND_PEER: 513 case GNUNET_MESSENGER_KIND_PEER:
511 send_message_peer (room, handle, message, &hash); 514 send_message_peer (room, handle, message, &hash);
512 break; 515 break;
516 case GNUNET_MESSENGER_KIND_ID:
517 send_message_id (room, handle, message, &hash);
518 break;
513 case GNUNET_MESSENGER_KIND_REQUEST: 519 case GNUNET_MESSENGER_KIND_REQUEST:
514 send_message_request (room, handle, message, &hash); 520 send_message_request (room, handle, message, &hash);
515 break; 521 break;
@@ -551,7 +557,9 @@ check_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MES
551 if (!room->peer_message) 557 if (!room->peer_message)
552 return; 558 return;
553 559
554 const struct GNUNET_MESSENGER_Message *message = get_room_message(room, NULL, room->peer_message, GNUNET_NO); 560 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
561
562 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, room->peer_message);
555 563
556 if (!message) 564 if (!message)
557 { 565 {
@@ -581,15 +589,6 @@ resend_peer_message:
581 send_room_message (room, room->host, create_message_peer (room->service)); 589 send_room_message (room, room->host, create_message_peer (room->service));
582} 590}
583 591
584static void
585merge_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
586 const struct GNUNET_HashCode *hash)
587{
588 GNUNET_assert((room) && (handle) && (hash));
589
590 send_room_message (room, handle, create_message_merge (hash));
591}
592
593void 592void
594merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) 593merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
595{ 594{
@@ -598,21 +597,21 @@ merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_M
598 if (!handle) 597 if (!handle)
599 return; 598 return;
600 599
601 if (!room->last_messages.head) 600 const struct GNUNET_HashCode *hash;
601
602merge_next:
603 hash = get_message_state_merge_hash (&(room->state));
604
605 if (!hash)
602 return; 606 return;
603 607
604 while (room->last_messages.head != room->last_messages.tail) 608 send_room_message (room, handle, create_message_merge (hash));
605 merge_room_message (room, handle, &(room->last_messages.tail->hash)); 609 goto merge_next;
606} 610}
607 611
608void 612void
609callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash) 613callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
610{ 614{
611 const struct GNUNET_MESSENGER_Message *message = get_room_message(room, NULL, hash, GNUNET_NO);
612
613 if (message)
614 add_to_list_messages(&(room->last_messages), &(message->header.previous));
615
616 if (GNUNET_OK != delete_store_message (get_room_message_store(room), hash)) 615 if (GNUNET_OK != delete_store_message (get_room_message_store(room), hash))
617 { 616 {
618 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Deletion of message failed! (%s)\n", GNUNET_h2s(hash)); 617 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Deletion of message failed! (%s)\n", GNUNET_h2s(hash));
@@ -626,7 +625,7 @@ callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_
626 if (!room->host) 625 if (!room->host)
627 return; 626 return;
628 627
629 merge_room_message (room, room->host, hash); 628 send_room_message (room, room->host, create_message_merge (hash));
630} 629}
631 630
632int 631int
@@ -643,7 +642,9 @@ delete_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSEN
643 return GNUNET_SYSERR; 642 return GNUNET_SYSERR;
644 } 643 }
645 644
646 const struct GNUNET_MESSENGER_Message *message = get_room_message(room, NULL, hash, GNUNET_NO); 645 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
646
647 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
647 648
648 if (!message) 649 if (!message)
649 return GNUNET_YES; 650 return GNUNET_YES;
@@ -691,23 +692,56 @@ get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNE
691 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer); 692 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer);
692} 693}
693 694
694const struct GNUNET_MESSENGER_Message* 695static int
695get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 696request_room_message_step (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash,
696 const struct GNUNET_HashCode *hash, int request) 697 const struct GNUNET_MESSENGER_MemberSession *session,
698 GNUNET_MESSENGER_MessageRequestCallback callback, void* cls)
697{ 699{
698 GNUNET_assert((room) && (hash)); 700 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
699 701
700 const struct GNUNET_MESSENGER_Message *message = get_store_message (get_room_message_store(room), hash); 702 const struct GNUNET_MESSENGER_MessageLink *link = get_store_message_link(
703 message_store, hash, GNUNET_YES
704 );
701 705
702 if ((message) || (!handle) || (GNUNET_YES != request)) 706 if (!link)
703 return message; 707 goto forward;
704 708
705 struct GNUNET_MESSENGER_OperationStore* operation_store = get_room_operation_store(room); 709 int result = request_room_message_step(room, &(link->first), session, callback, cls);
706 710
707 if (GNUNET_OK == use_store_operation(operation_store, hash, GNUNET_MESSENGER_OP_REQUEST, GNUNET_MESSENGER_REQUEST_DELAY)) 711 if ((GNUNET_YES == link->multiple) &&
708 send_room_message (room, handle, create_message_request (hash)); 712 (GNUNET_YES == request_room_message_step(room, &(link->second), session, callback, cls)))
713 return GNUNET_YES;
714 else
715 return result;
709 716
710 return NULL; 717forward:
718 if (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO))
719 return GNUNET_YES;
720
721 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
722
723 if (!message)
724 return GNUNET_NO;
725
726 if (callback)
727 callback (cls, room, message, hash);
728
729 return GNUNET_YES;
730}
731
732int
733request_room_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash,
734 const struct GNUNET_MESSENGER_MemberSession *session,
735 GNUNET_MESSENGER_MessageRequestCallback callback, void* cls)
736{
737 GNUNET_assert((room) && (hash));
738
739 int result = request_room_message_step (room, hash, session, callback, cls);
740
741 if ((GNUNET_NO == result) && (callback))
742 callback (cls, room, NULL, hash);
743
744 return result;
711} 745}
712 746
713void 747void
@@ -739,6 +773,23 @@ callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls,
739 return GNUNET_SYSERR; 773 return GNUNET_SYSERR;
740 } 774 }
741 775
776 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
777
778 const struct GNUNET_MESSENGER_Message *previous = get_store_message(message_store, &(message->header.previous));
779
780 if (!previous)
781 goto skip_time_comparison;
782
783 struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_ntoh(message->header.timestamp);
784 struct GNUNET_TIME_Absolute last = GNUNET_TIME_absolute_ntoh(previous->header.timestamp);
785
786 if (GNUNET_TIME_relative_get_zero_().rel_value_us != GNUNET_TIME_absolute_get_difference(timestamp, last).rel_value_us)
787 {
788 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Message error: Timestamp does not check out!\n");
789 return GNUNET_SYSERR;
790 }
791
792skip_time_comparison:
742 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message of kind: %s!\n", 793 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message of kind: %s!\n",
743 GNUNET_MESSENGER_name_of_kind(message->header.kind)); 794 GNUNET_MESSENGER_name_of_kind(message->header.kind));
744 795
@@ -753,12 +804,13 @@ idle_request_room_messages (void *cls)
753 room->idle = NULL; 804 room->idle = NULL;
754 805
755 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room); 806 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
807 const struct GNUNET_HashCode *hash = get_message_state_merge_hash(&(room->state));
756 808
757 if ((room->last_messages.head != room->last_messages.tail) && 809 if ((hash) &&
758 (GNUNET_MESSENGER_OP_UNKNOWN == get_store_operation_type(operation_store, &(room->last_messages.tail->hash)))) 810 (GNUNET_MESSENGER_OP_UNKNOWN == get_store_operation_type(operation_store, hash)))
759 use_store_operation( 811 use_store_operation(
760 operation_store, 812 operation_store,
761 &(room->last_messages.tail->hash), 813 hash,
762 GNUNET_MESSENGER_OP_MERGE, 814 GNUNET_MESSENGER_OP_MERGE,
763 GNUNET_MESSENGER_MERGE_DELAY 815 GNUNET_MESSENGER_MERGE_DELAY
764 ); 816 );
@@ -772,6 +824,46 @@ idle_request_room_messages (void *cls)
772} 824}
773 825
774void 826void
827solve_room_member_collisions (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_IDENTITY_PublicKey *public_key,
828 const struct GNUNET_ShortHashCode *member_id, struct GNUNET_TIME_Absolute timestamp)
829{
830 GNUNET_assert ((room) && (public_key) && (member_id));
831
832 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
833 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, member_id);
834
835 if ((!member) || (1 >= GNUNET_CONTAINER_multihashmap_size(member->sessions)))
836 return;
837
838 struct GNUNET_MESSENGER_ListHandles *handles = &(room->service->handles);
839 struct GNUNET_MESSENGER_ListHandle* element;
840
841 for (element = handles->head; element; element = element->next)
842 {
843 if (0 != GNUNET_memcmp(member_id, get_handle_member_id(element->handle, get_room_key(room))))
844 continue;
845
846 if (0 == GNUNET_memcmp(public_key, &(get_handle_ego(element->handle)->pub)))
847 continue;
848
849 struct GNUNET_MESSENGER_MemberSession *session = get_member_session(member, &(get_handle_ego(element->handle)->pub));
850
851 if (!session)
852 continue;
853
854 struct GNUNET_TIME_Absolute start = get_member_session_start(session);
855
856 if (GNUNET_TIME_relative_get_zero_().rel_value_us != GNUNET_TIME_absolute_get_difference(start, timestamp).rel_value_us)
857 continue;
858
859 struct GNUNET_ShortHashCode random_id;
860 generate_free_member_id (&random_id, member_store->members);
861
862 send_room_message(room, element->handle, create_message_id(&random_id));
863 }
864}
865
866void
775rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room) 867rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
776{ 868{
777 GNUNET_assert(room); 869 GNUNET_assert(room);
@@ -821,25 +913,27 @@ rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
821static void 913static void
822handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room) 914handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
823{ 915{
916 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
917 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
918
824 while (room->handling.head) 919 while (room->handling.head)
825 { 920 {
826 struct GNUNET_MESSENGER_ListMessage *element = room->handling.head; 921 struct GNUNET_MESSENGER_ListMessage *element = room->handling.head;
827 922
828 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, room->host, &(element->hash), GNUNET_NO); 923 const struct GNUNET_MESSENGER_Message *message = get_store_message (message_store, &(element->hash));
829 924
830 if (!msg) 925 if (!message)
831 goto finish_handling; 926 goto finish_handling;
832 927
833 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room); 928 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
834 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, msg);
835 929
836 if (!member) 930 if (!member)
837 goto finish_handling; 931 goto finish_handling;
838 932
839 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, msg, &(element->hash)); 933 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, &(element->hash));
840 934
841 if (session) 935 if (session)
842 handle_service_message (room->service, room, session, msg, &(element->hash)); 936 handle_service_message (room->service, room, session, message, &(element->hash));
843 937
844finish_handling: 938finish_handling:
845 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element); 939 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element);
@@ -847,17 +941,6 @@ finish_handling:
847 } 941 }
848} 942}
849 943
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 944int
862update_room_message (struct GNUNET_MESSENGER_SrvRoom *room, 945update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
863 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) 946 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
@@ -873,11 +956,13 @@ update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
873 if (GNUNET_YES == requested) 956 if (GNUNET_YES == requested)
874 cancel_store_operation(operation_store, hash); 957 cancel_store_operation(operation_store, hash);
875 958
876 const struct GNUNET_MESSENGER_Message *old_message = get_room_message (room, NULL, hash, GNUNET_NO); 959 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
960
961 const struct GNUNET_MESSENGER_Message *old_message = get_store_message (message_store, hash);
877 962
878 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle a message in room (%s).\n", GNUNET_h2s (get_room_key(room))); 963 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle a message in room (%s).\n", GNUNET_h2s (get_room_key(room)));
879 964
880 if ((old_message) || (GNUNET_OK != put_store_message (get_room_message_store(room), hash, message))) 965 if ((old_message) || (GNUNET_OK != put_store_message (message_store, hash, message)))
881 { 966 {
882 if (old_message != message) 967 if (old_message != message)
883 destroy_message(message); 968 destroy_message(message);
@@ -886,16 +971,19 @@ update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
886 return GNUNET_NO; 971 return GNUNET_NO;
887 } 972 }
888 973
974 update_message_state(&(room->state), requested, message, hash);
975
889 if ((GNUNET_YES == requested) || 976 if ((GNUNET_YES == requested) ||
890 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) || 977 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
891 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind)) 978 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
892 return GNUNET_YES; 979 return GNUNET_YES;
893 980
894 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind) 981 if ((GNUNET_MESSENGER_KIND_MERGE == message->header.kind) &&
895 remove_room_last_message(room, &(message->body.merge.previous)); 982 (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, &(message->body.merge.previous))))
896 remove_room_last_message(room, &(message->header.previous)); 983 cancel_store_operation(operation_store, &(message->body.merge.previous));
897 984
898 add_to_list_messages (&(room->last_messages), hash); 985 if (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, &(message->header.previous)))
986 cancel_store_operation(operation_store, &(message->header.previous));
899 987
900 return GNUNET_YES; 988 return GNUNET_YES;
901} 989}
@@ -1053,8 +1141,7 @@ load_room (struct GNUNET_MESSENGER_SrvRoom *room)
1053 char *last_messages_file; 1141 char *last_messages_file;
1054 GNUNET_asprintf (&last_messages_file, "%s%s", room_dir, "last_messages.list"); 1142 GNUNET_asprintf (&last_messages_file, "%s%s", room_dir, "last_messages.list");
1055 1143
1056 load_list_messages(&(room->last_messages), last_messages_file); 1144 load_message_state(&(room->state), room_dir);
1057 GNUNET_free(last_messages_file);
1058 } 1145 }
1059 1146
1060 GNUNET_free(room_dir); 1147 GNUNET_free(room_dir);
@@ -1081,11 +1168,7 @@ save_room (struct GNUNET_MESSENGER_SrvRoom *room)
1081 save_list_tunnels(&(room->basement), basement_file); 1168 save_list_tunnels(&(room->basement), basement_file);
1082 GNUNET_free(basement_file); 1169 GNUNET_free(basement_file);
1083 1170
1084 char *last_messages_file; 1171 save_message_state(&(room->state), room_dir);
1085 GNUNET_asprintf (&last_messages_file, "%s%s", room_dir, "last_messages.list");
1086
1087 save_list_messages(&(room->last_messages), last_messages_file);
1088 GNUNET_free(last_messages_file);
1089 } 1172 }
1090 1173
1091 GNUNET_free(room_dir); 1174 GNUNET_free(room_dir);
diff --git a/src/messenger/gnunet-service-messenger_room.h b/src/messenger/gnunet-service-messenger_room.h
index a40961177..b6a0f1064 100644
--- a/src/messenger/gnunet-service-messenger_room.h
+++ b/src/messenger/gnunet-service-messenger_room.h
@@ -36,6 +36,7 @@
36#include "gnunet_messenger_service.h" 36#include "gnunet_messenger_service.h"
37#include "gnunet-service-messenger_basement.h" 37#include "gnunet-service-messenger_basement.h"
38#include "gnunet-service-messenger_handle.h" 38#include "gnunet-service-messenger_handle.h"
39#include "gnunet-service-messenger_message_state.h"
39#include "gnunet-service-messenger_list_messages.h" 40#include "gnunet-service-messenger_list_messages.h"
40 41
41#include "messenger_api_list_tunnels.h" 42#include "messenger_api_list_tunnels.h"
@@ -72,7 +73,7 @@ struct GNUNET_MESSENGER_SrvRoom
72 struct GNUNET_MESSENGER_OperationStore operation_store; 73 struct GNUNET_MESSENGER_OperationStore operation_store;
73 74
74 struct GNUNET_MESSENGER_ListTunnels basement; 75 struct GNUNET_MESSENGER_ListTunnels basement;
75 struct GNUNET_MESSENGER_ListMessages last_messages; 76 struct GNUNET_MESSENGER_MessageState state;
76 77
77 struct GNUNET_HashCode *peer_message; 78 struct GNUNET_HashCode *peer_message;
78 79
@@ -126,24 +127,6 @@ struct GNUNET_MESSENGER_OperationStore*
126get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room); 127get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room);
127 128
128/** 129/**
129 * Returns the member id of the member representing the handle currently hosting this <i>room</i>.
130 *
131 * @param[in] room Room
132 * @return Host member id or NULL
133 */
134const struct GNUNET_ShortHashCode*
135get_room_host_id (const struct GNUNET_MESSENGER_SrvRoom *room);
136
137/**
138 * Changes the member id of the member representing the handle currently hosting this <i>room</i>.
139 *
140 * @param[in/out] room Room
141 * @param[in] unique_id Unique member id
142 */
143void
144change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *unique_id);
145
146/**
147 * Tries to open a <i>room</i> for a given <i>handle</i>. If the room has already been opened, the handle 130 * Tries to open a <i>room</i> for a given <i>handle</i>. If the room has already been opened, the handle
148 * will locally join the room. 131 * will locally join the room.
149 * 132 *
@@ -289,25 +272,51 @@ const struct GNUNET_MESSENGER_SrvTunnel*
289get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer); 272get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer);
290 273
291/** 274/**
292 * Returns a message from a <i>room</i> identified by a given <i>hash</i>. If no matching message is 275 * Method called whenever a <i>message</i> is found during a request in a <i>room</i>.
293 * found and <i>request</i> is set to #GNUNET_YES, the <i>handle</i> will request the missing message
294 * automatically.
295 * 276 *
296 * The function uses the optimized check for a message via its hash from the message store. 277 * @param[in/out] cls Closure from #request_room_message
297 * @see contains_store_message() 278 * @param[in/out] room Room
279 * @param[in] message Message or NULL
280 * @param[in] hash Hash of message
281 */
282typedef void (GNUNET_MESSENGER_MessageRequestCallback) (
283 void *cls, struct GNUNET_MESSENGER_SrvRoom *room,
284 const struct GNUNET_MESSENGER_Message *message,
285 const struct GNUNET_HashCode *hash
286);
287
288/**
289 * Requests a message from a <i>room</i> identified by a given <i>hash</i>. If the message is found,
290 * the selected <i>callback</i> will be called with it and the provided closure. If no matching message
291 * is found but it wasn't deleted the selected callback will be called with #NULL as message instead.
292 * In case of deletion the next available previous message will be used to call the callback.
298 * 293 *
299 * If a message is missing independent of the following request, NULL gets returned instead of the 294 * It is also possible that the given callback will not be called if the requesting session is not
300 * matching message. 295 * permitted!
301 * 296 *
302 * @param[in/out] room Room 297 * @param[in/out] room Room
303 * @param[in/out] handle Handle
304 * @param[in] hash Hash of message 298 * @param[in] hash Hash of message
305 * @param[in] request Flag to request a message 299 * @param[in] callback Callback to process result
306 * @return Message or NULL 300 * @param[in] cls Closure for the <i>callback</i>
301 * @return #GNUNET_YES if the request could be processed, otherwise #GNUNET_NO
302 */
303int
304request_room_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash,
305 const struct GNUNET_MESSENGER_MemberSession *session,
306 GNUNET_MESSENGER_MessageRequestCallback callback, void* cls);
307
308/**
309 * Checks for potential collisions with member ids and solves them changing active handles ids if they
310 * use an already used member id (comparing public key and timestamp).
311 *
312 * @param[in/out] room Room
313 * @param[in] public_key Public key of EGO
314 * @param[in] member_id Member ID
315 * @param[in] timestamp Timestamp
307 */ 316 */
308const struct GNUNET_MESSENGER_Message* 317void
309get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, 318solve_room_member_collisions (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_IDENTITY_PublicKey *public_key,
310 const struct GNUNET_HashCode *hash, int request); 319 const struct GNUNET_ShortHashCode *member_id, struct GNUNET_TIME_Absolute timestamp);
311 320
312/** 321/**
313 * Rebuilds the decentralized structure for a <i>room</i> by ensuring all required connections are made 322 * Rebuilds the decentralized structure for a <i>room</i> by ensuring all required connections are made
diff --git a/src/messenger/gnunet-service-messenger_tunnel.c b/src/messenger/gnunet-service-messenger_tunnel.c
index f7e8713c6..80d8dfa5e 100644
--- a/src/messenger/gnunet-service-messenger_tunnel.c
+++ b/src/messenger/gnunet-service-messenger_tunnel.c
@@ -27,6 +27,9 @@
27 27
28#include "gnunet-service-messenger_handle.h" 28#include "gnunet-service-messenger_handle.h"
29#include "gnunet-service-messenger_message_recv.h" 29#include "gnunet-service-messenger_message_recv.h"
30#include "gnunet-service-messenger_message_store.h"
31#include "gnunet-service-messenger_operation_store.h"
32#include "gnunet-service-messenger_operation.h"
30#include "messenger_api_util.h" 33#include "messenger_api_util.h"
31 34
32struct GNUNET_MESSENGER_SrvTunnel* 35struct GNUNET_MESSENGER_SrvTunnel*
@@ -44,7 +47,8 @@ create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerId
44 tunnel->messenger_version = 0; 47 tunnel->messenger_version = 0;
45 48
46 tunnel->peer_message = NULL; 49 tunnel->peer_message = NULL;
47 tunnel->last_message = NULL; 50
51 init_message_state(&(tunnel->state));
48 52
49 return tunnel; 53 return tunnel;
50} 54}
@@ -62,8 +66,7 @@ destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
62 if (tunnel->peer_message) 66 if (tunnel->peer_message)
63 GNUNET_free(tunnel->peer_message); 67 GNUNET_free(tunnel->peer_message);
64 68
65 if (tunnel->last_message) 69 clear_message_state(&(tunnel->state));
66 GNUNET_free(tunnel->last_message);
67 70
68 GNUNET_free(tunnel); 71 GNUNET_free(tunnel);
69} 72}
@@ -143,10 +146,18 @@ callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUN
143static void 146static void
144update_tunnel_last_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_HashCode *hash) 147update_tunnel_last_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_HashCode *hash)
145{ 148{
146 if (!tunnel->last_message) 149 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(tunnel->room);
147 tunnel->last_message = GNUNET_new(struct GNUNET_HashCode); 150
151 const int requested = (GNUNET_MESSENGER_OP_REQUEST == get_store_operation_type(operation_store, hash)?
152 GNUNET_YES : GNUNET_NO
153 );
154
155 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(tunnel->room);
156
157 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
148 158
149 GNUNET_memcpy(tunnel->last_message, hash, sizeof(*hash)); 159 if (message)
160 update_message_state(&(tunnel->state), requested, message, hash);
150} 161}
151 162
152void 163void
@@ -171,7 +182,9 @@ handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
171 if (!tunnel) 182 if (!tunnel)
172 return; 183 return;
173 184
174 const int new_message = update_room_message (tunnel->room, copy_message (&message), &hash); 185 const int new_message = update_room_message (
186 tunnel->room, copy_message (&message), &hash
187 );
175 188
176 if (GNUNET_YES != new_message) 189 if (GNUNET_YES != new_message)
177 goto receive_done; 190 goto receive_done;
@@ -313,9 +326,6 @@ void
313forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message, 326forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message,
314 const struct GNUNET_HashCode *hash) 327 const struct GNUNET_HashCode *hash)
315{ 328{
316 if (!message)
317 return;
318
319 GNUNET_assert((tunnel) && (message) && (hash)); 329 GNUNET_assert((tunnel) && (message) && (hash));
320 330
321 struct GNUNET_MESSENGER_Message *copy = copy_message(message); 331 struct GNUNET_MESSENGER_Message *copy = copy_message(message);
diff --git a/src/messenger/gnunet-service-messenger_tunnel.h b/src/messenger/gnunet-service-messenger_tunnel.h
index 51c5d32c1..96d98546d 100644
--- a/src/messenger/gnunet-service-messenger_tunnel.h
+++ b/src/messenger/gnunet-service-messenger_tunnel.h
@@ -32,6 +32,7 @@
32#include "gnunet_crypto_lib.h" 32#include "gnunet_crypto_lib.h"
33 33
34#include "gnunet-service-messenger_room.h" 34#include "gnunet-service-messenger_room.h"
35#include "gnunet-service-messenger_message_state.h"
35 36
36struct GNUNET_MESSENGER_SrvTunnel 37struct GNUNET_MESSENGER_SrvTunnel
37{ 38{
@@ -43,7 +44,7 @@ struct GNUNET_MESSENGER_SrvTunnel
43 uint32_t messenger_version; 44 uint32_t messenger_version;
44 45
45 struct GNUNET_HashCode *peer_message; 46 struct GNUNET_HashCode *peer_message;
46 struct GNUNET_HashCode *last_message; 47 struct GNUNET_MESSENGER_MessageState state;
47}; 48};
48 49
49/** 50/**
diff --git a/src/messenger/messenger_api.c b/src/messenger/messenger_api.c
index dc6d11aaf..b42bb40cc 100644
--- a/src/messenger/messenger_api.c
+++ b/src/messenger/messenger_api.c
@@ -199,7 +199,7 @@ check_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg)
199 199
200 struct GNUNET_MESSENGER_Message message; 200 struct GNUNET_MESSENGER_Message message;
201 201
202 if (length < sizeof(message.header)) 202 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN))
203 return GNUNET_NO; 203 return GNUNET_NO;
204 204
205 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, NULL)) 205 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, NULL))
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c
index 0d885f9ee..d65b80576 100755
--- a/src/messenger/messenger_api_message.c
+++ b/src/messenger/messenger_api_message.c
@@ -590,7 +590,7 @@ int
590decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer, 590decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
591 int include_signature, uint16_t *padding) 591 int include_signature, uint16_t *padding)
592{ 592{
593 GNUNET_assert((message) && (buffer) && (length >= sizeof(message->header))); 593 GNUNET_assert((message) && (buffer) && (length >= get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN)));
594 594
595 uint16_t offset = 0; 595 uint16_t offset = 0;
596 596