diff options
-rw-r--r-- | src/set/gnunet-service-set.c | 142 | ||||
-rw-r--r-- | src/set/gnunet-service-set.h | 12 | ||||
-rw-r--r-- | src/set/gnunet-service-set_union.c | 6 |
3 files changed, 100 insertions, 60 deletions
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c index bab29b097..cfc0068ab 100644 --- a/src/set/gnunet-service-set.c +++ b/src/set/gnunet-service-set.c | |||
@@ -91,6 +91,7 @@ static struct Set * | |||
91 | set_get (struct GNUNET_SERVER_Client *client) | 91 | set_get (struct GNUNET_SERVER_Client *client) |
92 | { | 92 | { |
93 | struct Set *set; | 93 | struct Set *set; |
94 | |||
94 | for (set = sets_head; NULL != set; set = set->next) | 95 | for (set = sets_head; NULL != set; set = set->next) |
95 | if (set->client == client) | 96 | if (set->client == client) |
96 | return set; | 97 | return set; |
@@ -99,16 +100,17 @@ set_get (struct GNUNET_SERVER_Client *client) | |||
99 | 100 | ||
100 | 101 | ||
101 | /** | 102 | /** |
102 | * Get the listener associated to a client, if any. | 103 | * Get the listener associated with the given client, if any. |
103 | * | 104 | * |
104 | * @param client the client | 105 | * @param client the client |
105 | * @return listener associated with the client, NULL | 106 | * @return listener associated with the client, NULL |
106 | * if there isn't any | 107 | * if there isn't any |
107 | */ | 108 | */ |
108 | static struct Listener * | 109 | static struct Listener * |
109 | get_listener (struct GNUNET_SERVER_Client *client) | 110 | listener_get (struct GNUNET_SERVER_Client *client) |
110 | { | 111 | { |
111 | struct Listener *listener; | 112 | struct Listener *listener; |
113 | |||
112 | for (listener = listeners_head; NULL != listener; listener = listener->next) | 114 | for (listener = listeners_head; NULL != listener; listener = listener->next) |
113 | if (listener->client == client) | 115 | if (listener->client == client) |
114 | return listener; | 116 | return listener; |
@@ -127,6 +129,7 @@ static struct Incoming * | |||
127 | get_incoming (uint32_t id) | 129 | get_incoming (uint32_t id) |
128 | { | 130 | { |
129 | struct Incoming *incoming; | 131 | struct Incoming *incoming; |
132 | |||
130 | for (incoming = incoming_head; NULL != incoming; incoming = incoming->next) | 133 | for (incoming = incoming_head; NULL != incoming; incoming = incoming->next) |
131 | if (incoming->accept_id == id) | 134 | if (incoming->accept_id == id) |
132 | return incoming; | 135 | return incoming; |
@@ -193,7 +196,7 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | |||
193 | set = set_get (client); | 196 | set = set_get (client); |
194 | if (NULL != set) | 197 | if (NULL != set) |
195 | set_destroy (set); | 198 | set_destroy (set); |
196 | listener = get_listener (client); | 199 | listener = listener_get (client); |
197 | if (NULL != listener) | 200 | if (NULL != listener) |
198 | listener_destroy (listener); | 201 | listener_destroy (listener); |
199 | } | 202 | } |
@@ -207,20 +210,13 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client) | |||
207 | static void | 210 | static void |
208 | incoming_destroy (struct Incoming *incoming) | 211 | incoming_destroy (struct Incoming *incoming) |
209 | { | 212 | { |
210 | if (NULL != incoming->tc) | ||
211 | { | ||
212 | GNUNET_free (incoming->tc); | ||
213 | GNUNET_assert (NULL != incoming->tc->tunnel); | ||
214 | GNUNET_MESH_tunnel_destroy (incoming->tc->tunnel); | ||
215 | incoming->tc = NULL; | ||
216 | } | ||
217 | GNUNET_CONTAINER_DLL_remove (incoming_head, incoming_tail, incoming); | 213 | GNUNET_CONTAINER_DLL_remove (incoming_head, incoming_tail, incoming); |
218 | GNUNET_free (incoming); | 214 | GNUNET_free (incoming); |
219 | } | 215 | } |
220 | 216 | ||
221 | 217 | ||
222 | static struct Listener * | 218 | static struct Listener * |
223 | get_listener_by_target (enum GNUNET_SET_OperationType op, | 219 | listener_get_by_target (enum GNUNET_SET_OperationType op, |
224 | const struct GNUNET_HashCode *app_id) | 220 | const struct GNUNET_HashCode *app_id) |
225 | { | 221 | { |
226 | struct Listener *l; | 222 | struct Listener *l; |
@@ -237,12 +233,31 @@ get_listener_by_target (enum GNUNET_SET_OperationType op, | |||
237 | } | 233 | } |
238 | 234 | ||
239 | 235 | ||
240 | 236 | /** | |
237 | * Suggest the given request to the listener, | ||
238 | * who can accept or reject the request. | ||
239 | * | ||
240 | * @param incoming the incoming peer with the request to suggest | ||
241 | * @param listener the listener to suggest the request to | ||
242 | */ | ||
241 | static void | 243 | static void |
242 | tunnel_context_destroy (struct TunnelContext *tc) | 244 | incoming_suggest (struct Incoming *incoming, struct Listener *listener) |
243 | { | 245 | { |
244 | GNUNET_free (tc); | 246 | struct GNUNET_MQ_Envelope *mqm; |
245 | /* FIXME destroy the rest */ | 247 | struct GNUNET_SET_RequestMessage *cmsg; |
248 | |||
249 | GNUNET_assert (GNUNET_NO == incoming->suggested); | ||
250 | incoming->suggested = GNUNET_YES; | ||
251 | |||
252 | GNUNET_SCHEDULER_cancel (incoming->timeout_task); | ||
253 | mqm = GNUNET_MQ_msg_nested_mh (cmsg, GNUNET_MESSAGE_TYPE_SET_REQUEST, | ||
254 | incoming->context_msg); | ||
255 | GNUNET_assert (NULL != mqm); | ||
256 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "suggesting request with accept id %u\n", incoming->accept_id); | ||
257 | cmsg->accept_id = htonl (incoming->accept_id); | ||
258 | cmsg->peer_id = incoming->tc->peer; | ||
259 | GNUNET_MQ_send (listener->client_mq, mqm); | ||
260 | |||
246 | } | 261 | } |
247 | 262 | ||
248 | 263 | ||
@@ -264,49 +279,46 @@ handle_p2p_operation_request (void *cls, | |||
264 | struct TunnelContext *tc = *tunnel_ctx; | 279 | struct TunnelContext *tc = *tunnel_ctx; |
265 | struct Incoming *incoming; | 280 | struct Incoming *incoming; |
266 | const struct OperationRequestMessage *msg = (const struct OperationRequestMessage *) mh; | 281 | const struct OperationRequestMessage *msg = (const struct OperationRequestMessage *) mh; |
267 | struct GNUNET_MQ_Envelope *mqm; | ||
268 | struct GNUNET_SET_RequestMessage *cmsg; | ||
269 | struct Listener *listener; | 282 | struct Listener *listener; |
270 | const struct GNUNET_MessageHeader *context_msg; | ||
271 | 283 | ||
272 | if (CONTEXT_INCOMING != tc->type) | 284 | if (CONTEXT_INCOMING != tc->type) |
273 | { | 285 | { |
274 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "unexpected operation request\n"); | 286 | /* unexpected request */ |
275 | tunnel_context_destroy (tc); | 287 | GNUNET_break_op (0); |
276 | /* don't kill the whole mesh connection */ | 288 | /* kill the tunnel, cleaner will be called */ |
277 | return GNUNET_OK; | 289 | return GNUNET_SYSERR; |
278 | } | 290 | } |
279 | 291 | ||
280 | incoming = tc->data; | 292 | incoming = tc->data; |
281 | 293 | ||
282 | context_msg = GNUNET_MQ_extract_nested_mh (msg); | 294 | if (GNUNET_YES == incoming->received_request) |
283 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "received P2P operation request (op %u, app %s)\n", | ||
284 | ntohs (msg->operation), GNUNET_h2s (&msg->app_id)); | ||
285 | listener = get_listener_by_target (ntohs (msg->operation), &msg->app_id); | ||
286 | if (NULL == listener) | ||
287 | { | 295 | { |
288 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 296 | /* double operation request */ |
289 | "set operation request from peer failed: " | 297 | GNUNET_break_op (0); |
290 | "no set with matching application ID and operation type\n"); | 298 | return GNUNET_SYSERR; |
291 | tunnel_context_destroy (tc); | ||
292 | /* don't kill the whole mesh connection */ | ||
293 | return GNUNET_OK; | ||
294 | } | 299 | } |
295 | mqm = GNUNET_MQ_msg_nested_mh (cmsg, GNUNET_MESSAGE_TYPE_SET_REQUEST, context_msg); | 300 | |
296 | if (NULL == mqm) | 301 | incoming->accept_id = accept_id++; |
302 | incoming->context_msg = | ||
303 | GNUNET_copy_message (GNUNET_MQ_extract_nested_mh (msg)); | ||
304 | |||
305 | if ( (NULL != incoming->context_msg) && | ||
306 | (ntohs (incoming->context_msg->size) > GNUNET_SET_CONTEXT_MESSAGE_MAX_SIZE) ) | ||
297 | { | 307 | { |
298 | /* FIXME: disconnect the peer */ | ||
299 | GNUNET_break_op (0); | 308 | GNUNET_break_op (0); |
300 | tunnel_context_destroy (tc); | 309 | return GNUNET_SYSERR; |
301 | /* don't kill the whole mesh connection */ | ||
302 | return GNUNET_OK; | ||
303 | } | 310 | } |
304 | incoming->accept_id = accept_id++; | ||
305 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "sending request with accept id %u\n", incoming->accept_id); | ||
306 | cmsg->accept_id = htonl (incoming->accept_id); | ||
307 | cmsg->peer_id = incoming->tc->peer; | ||
308 | GNUNET_MQ_send (listener->client_mq, mqm); | ||
309 | 311 | ||
312 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "received P2P operation request (op %u, app %s)\n", | ||
313 | ntohs (msg->operation), GNUNET_h2s (&msg->app_id)); | ||
314 | listener = listener_get_by_target (ntohs (msg->operation), &msg->app_id); | ||
315 | if (NULL == listener) | ||
316 | { | ||
317 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
318 | "no listener matches incoming request, waiting with timeout\n"); | ||
319 | return GNUNET_OK; | ||
320 | } | ||
321 | incoming_suggest (incoming, listener); | ||
310 | return GNUNET_OK; | 322 | return GNUNET_OK; |
311 | } | 323 | } |
312 | 324 | ||
@@ -375,8 +387,9 @@ handle_client_listen (void *cls, | |||
375 | { | 387 | { |
376 | struct GNUNET_SET_ListenMessage *msg = (struct GNUNET_SET_ListenMessage *) m; | 388 | struct GNUNET_SET_ListenMessage *msg = (struct GNUNET_SET_ListenMessage *) m; |
377 | struct Listener *listener; | 389 | struct Listener *listener; |
390 | struct Incoming *incoming; | ||
378 | 391 | ||
379 | if (NULL != get_listener (client)) | 392 | if (NULL != listener_get (client)) |
380 | { | 393 | { |
381 | GNUNET_break (0); | 394 | GNUNET_break (0); |
382 | GNUNET_SERVER_client_disconnect (client); | 395 | GNUNET_SERVER_client_disconnect (client); |
@@ -390,6 +403,17 @@ handle_client_listen (void *cls, | |||
390 | GNUNET_CONTAINER_DLL_insert_tail (listeners_head, listeners_tail, listener); | 403 | GNUNET_CONTAINER_DLL_insert_tail (listeners_head, listeners_tail, listener); |
391 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "new listener created (op %u, app %s)\n", | 404 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "new listener created (op %u, app %s)\n", |
392 | listener->operation, GNUNET_h2s (&listener->app_id)); | 405 | listener->operation, GNUNET_h2s (&listener->app_id)); |
406 | for (incoming = incoming_head; NULL != incoming; incoming = incoming->next) | ||
407 | { | ||
408 | if ( (GNUNET_NO == incoming->received_request) || | ||
409 | (GNUNET_YES == incoming->suggested) ) | ||
410 | continue; | ||
411 | if (listener->operation != incoming->operation) | ||
412 | continue; | ||
413 | if (0 != GNUNET_CRYPTO_hash_cmp (&listener->app_id, &incoming->app_id)) | ||
414 | continue; | ||
415 | incoming_suggest (incoming, listener); | ||
416 | } | ||
393 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 417 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
394 | } | 418 | } |
395 | 419 | ||
@@ -459,7 +483,8 @@ handle_client_reject (void *cls, | |||
459 | return; | 483 | return; |
460 | } | 484 | } |
461 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "peer request rejected by client\n"); | 485 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "peer request rejected by client\n"); |
462 | incoming_destroy (incoming); | 486 | /* the incoming peer will be destroyed in the tunnel end handler */ |
487 | GNUNET_MESH_tunnel_destroy (incoming->tc->tunnel); | ||
463 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 488 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
464 | } | 489 | } |
465 | 490 | ||
@@ -475,8 +500,8 @@ handle_client_reject (void *cls, | |||
475 | */ | 500 | */ |
476 | static void | 501 | static void |
477 | handle_client_add (void *cls, | 502 | handle_client_add (void *cls, |
478 | struct GNUNET_SERVER_Client *client, | 503 | struct GNUNET_SERVER_Client *client, |
479 | const struct GNUNET_MessageHeader *m) | 504 | const struct GNUNET_MessageHeader *m) |
480 | { | 505 | { |
481 | struct Set *set; | 506 | struct Set *set; |
482 | 507 | ||
@@ -611,7 +636,7 @@ handle_client_accept (void *cls, | |||
611 | break; | 636 | break; |
612 | } | 637 | } |
613 | 638 | ||
614 | /* note: _GSS_*_accept has to make sure the socket and mq are set to NULL, | 639 | /* note: _GSS_*_accept has to make sure the tunnel and mq are set to NULL, |
615 | * otherwise they will be destroyed and disconnected */ | 640 | * otherwise they will be destroyed and disconnected */ |
616 | incoming_destroy (incoming); | 641 | incoming_destroy (incoming); |
617 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 642 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
@@ -635,19 +660,13 @@ shutdown_task (void *cls, | |||
635 | } | 660 | } |
636 | 661 | ||
637 | while (NULL != incoming_head) | 662 | while (NULL != incoming_head) |
638 | { | ||
639 | incoming_destroy (incoming_head); | 663 | incoming_destroy (incoming_head); |
640 | } | ||
641 | 664 | ||
642 | while (NULL != listeners_head) | 665 | while (NULL != listeners_head) |
643 | { | ||
644 | listener_destroy (listeners_head); | 666 | listener_destroy (listeners_head); |
645 | } | ||
646 | 667 | ||
647 | while (NULL != sets_head) | 668 | while (NULL != sets_head) |
648 | { | ||
649 | set_destroy (sets_head); | 669 | set_destroy (sets_head); |
650 | } | ||
651 | 670 | ||
652 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "handled shutdown request\n"); | 671 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "handled shutdown request\n"); |
653 | } | 672 | } |
@@ -706,7 +725,8 @@ tunnel_new_cb (void *cls, | |||
706 | tc->mq = GNUNET_MESH_mq_create (tunnel); | 725 | tc->mq = GNUNET_MESH_mq_create (tunnel); |
707 | tc->data = incoming; | 726 | tc->data = incoming; |
708 | tc->type = CONTEXT_INCOMING; | 727 | tc->type = CONTEXT_INCOMING; |
709 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, incoming_timeout_cb, incoming); | 728 | incoming->timeout_task = |
729 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, incoming_timeout_cb, incoming); | ||
710 | GNUNET_CONTAINER_DLL_insert_tail (incoming_head, incoming_tail, incoming); | 730 | GNUNET_CONTAINER_DLL_insert_tail (incoming_head, incoming_tail, incoming); |
711 | 731 | ||
712 | return tc; | 732 | return tc; |
@@ -730,6 +750,15 @@ tunnel_end_cb (void *cls, | |||
730 | { | 750 | { |
731 | struct TunnelContext *ctx = tunnel_ctx; | 751 | struct TunnelContext *ctx = tunnel_ctx; |
732 | 752 | ||
753 | /* tunnel is dead already */ | ||
754 | ctx->tunnel = NULL; | ||
755 | |||
756 | if (NULL != ctx->mq) | ||
757 | { | ||
758 | GNUNET_MQ_destroy (ctx->mq); | ||
759 | ctx->mq = NULL; | ||
760 | } | ||
761 | |||
733 | switch (ctx->type) | 762 | switch (ctx->type) |
734 | { | 763 | { |
735 | case CONTEXT_INCOMING: | 764 | case CONTEXT_INCOMING: |
@@ -746,6 +775,7 @@ tunnel_end_cb (void *cls, | |||
746 | GNUNET_assert (0); | 775 | GNUNET_assert (0); |
747 | } | 776 | } |
748 | 777 | ||
778 | GNUNET_free (tunnel_ctx); | ||
749 | } | 779 | } |
750 | 780 | ||
751 | 781 | ||
diff --git a/src/set/gnunet-service-set.h b/src/set/gnunet-service-set.h index d60b5f477..533fd0ef7 100644 --- a/src/set/gnunet-service-set.h +++ b/src/set/gnunet-service-set.h | |||
@@ -186,11 +186,23 @@ struct Incoming | |||
186 | enum GNUNET_SET_OperationType operation; | 186 | enum GNUNET_SET_OperationType operation; |
187 | 187 | ||
188 | /** | 188 | /** |
189 | * Has the incoming request been suggested to | ||
190 | * a client listener yet? | ||
191 | */ | ||
192 | int suggested; | ||
193 | |||
194 | /** | ||
189 | * Unique request id for the request from | 195 | * Unique request id for the request from |
190 | * a remote peer, sent to the client, which will | 196 | * a remote peer, sent to the client, which will |
191 | * accept or reject the request. | 197 | * accept or reject the request. |
192 | */ | 198 | */ |
193 | uint32_t accept_id; | 199 | uint32_t accept_id; |
200 | |||
201 | /** | ||
202 | * Timeout task, if the incoming peer has not been accepted | ||
203 | * after the timeout, it will be disconnected. | ||
204 | */ | ||
205 | GNUNET_SCHEDULER_TaskIdentifier timeout_task; | ||
194 | }; | 206 | }; |
195 | 207 | ||
196 | 208 | ||
diff --git a/src/set/gnunet-service-set_union.c b/src/set/gnunet-service-set_union.c index 670626cd4..5b1f28cf4 100644 --- a/src/set/gnunet-service-set_union.c +++ b/src/set/gnunet-service-set_union.c | |||
@@ -1370,9 +1370,8 @@ _GSS_union_handle_p2p_message (void *cls, | |||
1370 | 1370 | ||
1371 | if (CONTEXT_OPERATION_UNION != tc->type) | 1371 | if (CONTEXT_OPERATION_UNION != tc->type) |
1372 | { | 1372 | { |
1373 | /* FIXME: kill the tunnel */ | 1373 | GNUNET_break_op (0); |
1374 | /* never kill mesh */ | 1374 | return GNUNET_SYSERR; |
1375 | return GNUNET_OK; | ||
1376 | } | 1375 | } |
1377 | 1376 | ||
1378 | eo = tc->data; | 1377 | eo = tc->data; |
@@ -1398,6 +1397,5 @@ _GSS_union_handle_p2p_message (void *cls, | |||
1398 | /* something wrong with mesh's message handlers? */ | 1397 | /* something wrong with mesh's message handlers? */ |
1399 | GNUNET_assert (0); | 1398 | GNUNET_assert (0); |
1400 | } | 1399 | } |
1401 | /* never kill mesh! */ | ||
1402 | return GNUNET_OK; | 1400 | return GNUNET_OK; |
1403 | } | 1401 | } |