diff options
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 | ||
268 | static void | 273 | static void |
274 | callback_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 | |||
302 | static void | ||
269 | handle_get_message (void *cls, const struct GNUNET_MESSENGER_GetMessage *msg) | 303 | handle_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 | ||
304 | end_handling: | 339 | end_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 | ||
321 | struct GNUNET_TIME_Absolute | ||
322 | get_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 | |||
317 | const struct GNUNET_HashCode* | 332 | const struct GNUNET_HashCode* |
318 | get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session) | 333 | get_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 | |||
140 | is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session); | 143 | is_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 | */ | ||
151 | struct GNUNET_TIME_Absolute | ||
152 | get_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 | ||
49 | void | 56 | void |
@@ -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 | ||
96 | void | 110 | void |
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 | ||
30 | static void | ||
31 | forward_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 | |||
30 | static int | 56 | static int |
31 | iterate_forward_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key, | 57 | iterate_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 | ||
100 | int | 128 | static void |
101 | recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel, | 129 | callback_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 | */ | ||
154 | int | ||
155 | recv_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 | ||
49 | void | 49 | void |
50 | send_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 | |||
56 | void | ||
50 | send_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 57 | send_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 | */ | ||
72 | void | ||
73 | send_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 | |||
28 | void | ||
29 | init_message_state (struct GNUNET_MESSENGER_MessageState *state) | ||
30 | { | ||
31 | GNUNET_assert(state); | ||
32 | |||
33 | init_list_messages (&(state->last_messages)); | ||
34 | } | ||
35 | |||
36 | void | ||
37 | clear_message_state (struct GNUNET_MESSENGER_MessageState *state) | ||
38 | { | ||
39 | GNUNET_assert(state); | ||
40 | |||
41 | clear_list_messages (&(state->last_messages)); | ||
42 | } | ||
43 | |||
44 | void | ||
45 | get_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 | |||
56 | const struct GNUNET_HashCode* | ||
57 | get_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 | |||
67 | void | ||
68 | update_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 | |||
85 | void | ||
86 | load_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 | |||
97 | void | ||
98 | save_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 | |||
35 | struct GNUNET_MESSENGER_MessageState | ||
36 | { | ||
37 | struct GNUNET_MESSENGER_ListMessages last_messages; | ||
38 | }; | ||
39 | |||
40 | void | ||
41 | init_message_state (struct GNUNET_MESSENGER_MessageState *state); | ||
42 | |||
43 | void | ||
44 | clear_message_state (struct GNUNET_MESSENGER_MessageState *state); | ||
45 | |||
46 | void | ||
47 | get_message_state_chain_hash (const struct GNUNET_MESSENGER_MessageState *state, | ||
48 | struct GNUNET_HashCode *hash); | ||
49 | |||
50 | const struct GNUNET_HashCode* | ||
51 | get_message_state_merge_hash (const struct GNUNET_MESSENGER_MessageState *state); | ||
52 | |||
53 | void | ||
54 | update_message_state (struct GNUNET_MESSENGER_MessageState *state, int requested, | ||
55 | const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); | ||
56 | |||
57 | void | ||
58 | load_message_state (struct GNUNET_MESSENGER_MessageState *state, const char *path); | ||
59 | |||
60 | void | ||
61 | save_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 | ||
152 | const struct GNUNET_ShortHashCode* | ||
153 | get_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 | |||
160 | void | ||
161 | change_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 | |||
168 | static int | 152 | static int |
169 | send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 153 | send_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 | ||
246 | static int | 230 | static void |
247 | iterate_notify_about_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key, | 231 | notify_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 | |||
260 | static int | ||
261 | iterate_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 | ||
584 | static void | ||
585 | merge_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 | |||
593 | void | 592 | void |
594 | merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle) | 593 | merge_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 | |||
602 | merge_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 | ||
608 | void | 612 | void |
609 | callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash) | 613 | callback_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 | ||
632 | int | 631 | int |
@@ -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 | ||
694 | const struct GNUNET_MESSENGER_Message* | 695 | static int |
695 | get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 696 | request_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; | 717 | forward: |
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 | |||
732 | int | ||
733 | request_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 | ||
713 | void | 747 | void |
@@ -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 | |||
792 | skip_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 | ||
774 | void | 826 | void |
827 | solve_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 | |||
866 | void | ||
775 | rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room) | 867 | rebuild_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) | |||
821 | static void | 913 | static void |
822 | handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room) | 914 | handle_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 | ||
844 | finish_handling: | 938 | finish_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 | ||
850 | static void | ||
851 | remove_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 | |||
861 | int | 944 | int |
862 | update_room_message (struct GNUNET_MESSENGER_SrvRoom *room, | 945 | update_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* | |||
126 | get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room); | 127 | get_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 | */ | ||
134 | const struct GNUNET_ShortHashCode* | ||
135 | get_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 | */ | ||
143 | void | ||
144 | change_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* | |||
289 | get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer); | 272 | get_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 | */ | ||
282 | typedef 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 | */ | ||
303 | int | ||
304 | request_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 | */ |
308 | const struct GNUNET_MESSENGER_Message* | 317 | void |
309 | get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, | 318 | solve_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 | ||
32 | struct GNUNET_MESSENGER_SrvTunnel* | 35 | struct 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 | |||
143 | static void | 146 | static void |
144 | update_tunnel_last_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_HashCode *hash) | 147 | update_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 | ||
152 | void | 163 | void |
@@ -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 | |||
313 | forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message, | 326 | forward_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 | ||
36 | struct GNUNET_MESSENGER_SrvTunnel | 37 | struct 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 | |||
590 | decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer, | 590 | decode_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 | ||