2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
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 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testbed/gnunet-service-testbed_oc.c
23 * @brief code for handling overlay connect operations
24 * @author Sree Harsha Totakura
27 #include "gnunet-service-testbed.h"
30 * Redefine LOG with a changed log component string
35 #define LOG(kind,...) \
36 GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__)
40 * Context information for transport try connect
42 struct TryConnectContext
45 * The identity of the peer to which the transport has to attempt a connection
47 struct GNUNET_PeerIdentity *pid;
50 * The transport handle
52 struct GNUNET_TRANSPORT_Handle *th_;
55 * The GetCacheHandle for the p1th transport handle
57 struct GSTCacheGetHandle *cgh_th;
60 * the try connect handle
62 struct GNUNET_TRANSPORT_TryConnectHandle *tch;
67 GNUNET_SCHEDULER_TaskIdentifier task;
70 * The id of the operation which is resposible for this context
75 * The number of times we attempted to connect
83 * Context information for connecting 2 peers in overlay
85 struct OverlayConnectContext
88 * The next pointer for maintaining a DLL
90 struct OverlayConnectContext *next;
93 * The prev pointer for maintaining a DLL
95 struct OverlayConnectContext *prev;
98 * The client which has requested for overlay connection
100 struct GNUNET_SERVER_Client *client;
103 * the peer which has to connect to the other peer
108 * Transport handle of the first peer to get its HELLO
110 struct GNUNET_TRANSPORT_Handle *p1th;
113 * The GetCacheHandle for the p1th transport handle
115 struct GSTGetCacheHandle *gch_p1th;
118 * Core handles of the first peer; used to notify when second peer connects to it
120 //struct GNUNET_CORE_Handle *ch_;
123 * The GetCacheHandle for the p1th transport handle
125 struct GSTCacheGetHandle *cgh_ch;
128 * HELLO of the other peer
130 struct GNUNET_MessageHeader *hello;
133 * Get hello handle to acquire HELLO of first peer
135 struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
138 * The handle for offering HELLO
140 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
143 * The error message we send if this overlay connect operation has timed out
148 * Operation context for suboperations
150 struct OperationContext *opc;
153 * Controller of peer 2; NULL if the peer is local
155 struct GNUNET_TESTBED_Controller *peer2_controller;
158 * The transport try connect context
160 struct TryConnectContext tcc;
163 * The peer identity of the first peer
165 struct GNUNET_PeerIdentity peer_identity;
168 * The peer identity of the other peer
170 struct GNUNET_PeerIdentity other_peer_identity;
173 * The id of the operation responsible for creating this context
178 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
181 GNUNET_SCHEDULER_TaskIdentifier send_hello_task;
184 * The id of the overlay connect timeout task
186 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
189 * The id of the cleanup task
191 GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
201 uint32_t other_peer_id;
207 * Context information for RequestOverlayConnect
208 * operations. RequestOverlayConnect is used when peers A, B reside on different
209 * hosts and the host controller for peer B is asked by the host controller of
210 * peer A to make peer B connect to peer A
212 struct RemoteOverlayConnectCtx
215 * the next pointer for DLL
217 struct RemoteOverlayConnectCtx *next;
220 * the prev pointer for DLL
222 struct RemoteOverlayConnectCtx *prev;
225 * The peer handle of peer B
232 struct GNUNET_MessageHeader *hello;
235 * The handle for offering HELLO
237 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
240 * The transport try connect context
242 struct TryConnectContext tcc;
245 * The peer identity of peer A
247 struct GNUNET_PeerIdentity a_id;
250 * Task for offering HELLO of A to B and doing try_connect
252 GNUNET_SCHEDULER_TaskIdentifier attempt_connect_task_id;
255 * Task to timeout RequestOverlayConnect
257 GNUNET_SCHEDULER_TaskIdentifier timeout_rocc_task_id;
260 * The id of the operation responsible for creating this context
267 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
269 static struct OverlayConnectContext *occq_head;
272 * DLL tail for OverlayConnectContext DLL
274 static struct OverlayConnectContext *occq_tail;
277 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
280 static struct RemoteOverlayConnectCtx *roccq_head;
283 * DLL tail for RequectOverlayConnectContext DLL
285 static struct RemoteOverlayConnectCtx *roccq_tail;
289 * Cleans up ForwardedOverlayConnectContext
291 * @param focc the ForwardedOverlayConnectContext to cleanup
294 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
296 GNUNET_free_non_null (focc->orig_msg);
302 * Timeout task for cancelling a forwarded overlay connect connect
304 * @param cls the ForwardedOverlayConnectContext
305 * @param tc the task context from the scheduler
308 forwarded_overlay_connect_timeout (void *cls,
309 const struct GNUNET_SCHEDULER_TaskContext
312 struct ForwardedOperationContext *fopc = cls;
313 struct RegisteredHostContext *rhc;
314 struct ForwardedOverlayConnectContext *focc;
317 focc = rhc->focc_dll_head;
318 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
319 GST_cleanup_focc (focc);
320 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1,
322 GST_forwarded_operation_timeout (cls, tc);
323 if (NULL != rhc->focc_dll_head)
324 GST_process_next_focc (rhc);
329 * Callback to be called when forwarded overlay connection operation has a reply
330 * from the sub-controller successfull. We have to relay the reply msg back to
333 * @param cls ForwardedOperationContext
334 * @param msg the peer create success message
337 forwarded_overlay_connect_listener (void *cls,
338 const struct GNUNET_MessageHeader *msg)
340 struct ForwardedOperationContext *fopc = cls;
341 struct RegisteredHostContext *rhc;
342 struct ForwardedOverlayConnectContext *focc;
345 GST_forwarded_operation_reply_relay (cls, msg);
346 focc = rhc->focc_dll_head;
347 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
348 GST_cleanup_focc (focc);
349 if (NULL != rhc->focc_dll_head)
350 GST_process_next_focc (rhc);
355 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
357 * @param rhc the RegisteredHostContext
360 GST_process_next_focc (struct RegisteredHostContext *rhc)
362 struct ForwardedOperationContext *fopc;
363 struct ForwardedOverlayConnectContext *focc;
365 focc = rhc->focc_dll_head;
366 GNUNET_assert (NULL != focc);
367 GNUNET_assert (RHC_OL_CONNECT == rhc->state);
368 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
369 GNUNET_SERVER_client_keep (rhc->client);
370 fopc->client = rhc->client;
371 fopc->operation_id = focc->operation_id;
373 fopc->type = OP_OVERLAY_CONNECT;
375 GNUNET_TESTBED_forward_operation_msg_ (rhc->gateway->controller,
376 focc->operation_id, focc->orig_msg,
377 &forwarded_overlay_connect_listener,
379 GNUNET_free (focc->orig_msg);
380 focc->orig_msg = NULL;
382 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_overlay_connect_timeout,
384 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
389 * Cleanup overlay connect context structure
391 * @param occ the overlay connect context
394 cleanup_occ (struct OverlayConnectContext *occ)
396 LOG_DEBUG ("0x%llx: Cleaning up occ\n", occ->op_id);
397 GNUNET_free_non_null (occ->emsg);
398 GNUNET_free_non_null (occ->hello);
399 GNUNET_SERVER_client_drop (occ->client);
400 if (NULL != occ->opc)
401 GNUNET_TESTBED_forward_operation_msg_cancel_ (occ->opc);
402 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
403 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
404 if (GNUNET_SCHEDULER_NO_TASK != occ->cleanup_task)
405 GNUNET_SCHEDULER_cancel (occ->cleanup_task);
406 if (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task)
407 GNUNET_SCHEDULER_cancel (occ->timeout_task);
408 if (NULL != occ->cgh_ch)
410 GST_cache_get_handle_done (occ->cgh_ch);
411 occ->peer->reference_cnt--;
413 if (NULL != occ->ghh)
414 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
415 if (NULL != occ->ohh)
416 GNUNET_TRANSPORT_offer_hello_cancel (occ->ohh);
417 if (GNUNET_SCHEDULER_NO_TASK != occ->tcc.task)
418 GNUNET_SCHEDULER_cancel (occ->tcc.task);
419 if (NULL != occ->tcc.tch)
420 GNUNET_TRANSPORT_try_connect_cancel (occ->tcc.tch);
421 if (NULL != occ->p1th)
423 GNUNET_TRANSPORT_disconnect (occ->p1th);
424 occ->peer->reference_cnt--;
426 if (NULL != occ->tcc.cgh_th)
428 GST_cache_get_handle_done (occ->tcc.cgh_th);
429 GST_peer_list[occ->other_peer_id]->reference_cnt--;
431 if ((GNUNET_YES == occ->peer->destroy_flag) &&
432 (0 == occ->peer->reference_cnt))
433 GST_destroy_peer (occ->peer);
434 if ((NULL == occ->peer2_controller) &&
435 (GNUNET_YES == GST_peer_list[occ->other_peer_id]->destroy_flag) &&
436 (0 == GST_peer_list[occ->other_peer_id]->reference_cnt))
437 GST_destroy_peer (GST_peer_list[occ->other_peer_id]);
438 GNUNET_CONTAINER_DLL_remove (occq_head, occq_tail, occ);
444 * Task for cleaing up overlay connect context structure
446 * @param cls the overlay connect context
447 * @param tc the task context
450 do_cleanup_occ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
452 struct OverlayConnectContext *occ = cls;
454 occ->cleanup_task = GNUNET_SCHEDULER_NO_TASK;
460 * Task which will be run when overlay connect request has been timed out
462 * @param cls the OverlayConnectContext
463 * @param tc the TaskContext
466 timeout_overlay_connect (void *cls,
467 const struct GNUNET_SCHEDULER_TaskContext *tc)
469 struct OverlayConnectContext *occ = cls;
471 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
472 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
473 LOG (GNUNET_ERROR_TYPE_WARNING,
474 "0x%llx: Timeout while connecting peers %u and %u\n", occ->op_id,
475 occ->peer_id, occ->other_peer_id);
476 GST_send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
482 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
484 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
486 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
488 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
490 htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
491 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
492 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
493 msg->peer1 = htonl (occ->peer_id);
494 msg->peer2 = htonl (occ->other_peer_id);
495 msg->operation_id = GNUNET_htonll (occ->op_id);
496 GST_queue_message (occ->client, &msg->header);
501 * Function called to notify transport users that another
502 * peer connected to us.
505 * @param new_peer the peer that connected
508 overlay_connect_notify (void *cls,
509 const struct GNUNET_PeerIdentity *new_peer)
511 struct OverlayConnectContext *occ = cls;
513 char *other_peer_str;
515 //LOG_DEBUG ("Overlay connect notify\n");
517 memcmp (new_peer, &occ->peer_identity,
518 sizeof (struct GNUNET_PeerIdentity)))
520 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
521 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
523 memcmp (new_peer, &occ->other_peer_identity,
524 sizeof (struct GNUNET_PeerIdentity)))
526 /* LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n", */
527 /* new_peer_str, other_peer_str); */
528 GNUNET_free (new_peer_str);
529 GNUNET_free (other_peer_str);
532 GNUNET_free (new_peer_str);
533 LOG_DEBUG ("0x%llx: Peer %4s connected to peer %4s\n", occ->op_id,
534 other_peer_str, GNUNET_i2s (&occ->peer_identity));
535 GNUNET_free (other_peer_str);
536 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
538 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
539 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
541 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
542 GNUNET_SCHEDULER_cancel (occ->timeout_task);
543 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
544 if (GNUNET_SCHEDULER_NO_TASK != occ->tcc.task)
546 GNUNET_SCHEDULER_cancel (occ->tcc.task);
547 occ->tcc.task = GNUNET_SCHEDULER_NO_TASK;
549 GST_cache_get_handle_done (occ->cgh_ch);
550 occ->peer->reference_cnt--;
552 GNUNET_free_non_null (occ->emsg);
554 send_overlay_connect_success_msg (occ);
555 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
561 * Task to ask transport of a peer to connect to another peer
563 * @param cls the TryConnectContext
564 * @param tc the scheduler task context
567 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
571 * Callback to be called with result of the try connect request.
573 * @param cls the overlay connect context
574 * @param result GNUNET_OK if message was transmitted to transport service
575 * GNUNET_SYSERR if message was not transmitted to transport service
578 try_connect_cb (void *cls, const int result)
580 struct TryConnectContext *tcc = cls;
583 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == tcc->task);
585 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
586 (GNUNET_TIME_UNIT_MILLISECONDS,
587 500 + pow (2, ++tcc->retries)),
588 &try_connect_task, tcc);
593 * Task to ask transport of a peer to connect to another peer
595 * @param cls the TryConnectContext
596 * @param tc the scheduler task context
599 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
601 struct TryConnectContext *tcc = cls;
603 tcc->task = GNUNET_SCHEDULER_NO_TASK;
604 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
606 GNUNET_assert (NULL == tcc->tch);
607 GNUNET_assert (NULL != tcc->pid);
608 GNUNET_assert (NULL != tcc->th_);
609 GNUNET_assert (NULL != tcc->cgh_th);
610 LOG_DEBUG ("0x%llx: Trail %u to connect to peer %s\n", tcc->op_id,
611 tcc->retries, GNUNET_i2s (tcc->pid));
613 GNUNET_TRANSPORT_try_connect (tcc->th_, tcc->pid, &try_connect_cb, tcc);
618 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
621 * @param cls the OverlayConnectContext
622 * @param tc the TaskContext from scheduler
625 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
629 * Task that is run when hello has been sent
631 * @param cls the overlay connect context
632 * @param tc the scheduler task context; if tc->reason =
633 * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
634 * GNUNET_SCHEDULER_REASON_READ_READY is succeeded
637 occ_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
639 struct OverlayConnectContext *occ = cls;
642 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->send_hello_task);
643 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
645 GNUNET_free_non_null (occ->emsg);
646 GNUNET_asprintf (&occ->emsg,
647 "0x%llx: Timeout while offering HELLO to other peer",
649 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
652 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
654 GNUNET_free_non_null (occ->emsg);
655 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while try connect", occ->op_id);
656 occ->tcc.pid = &occ->peer_identity;
657 occ->tcc.op_id = occ->op_id;
658 occ->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &occ->tcc);
663 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
666 * @param cls the OverlayConnectContext
667 * @param tc the TaskContext from scheduler
670 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
672 struct OverlayConnectContext *occ = cls;
673 char *other_peer_str;
675 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
676 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
678 GNUNET_assert (NULL != occ->hello);
679 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
680 if (NULL != occ->peer2_controller)
682 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
686 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote "
687 "Overlay Request\n", occ->op_id,
688 GNUNET_i2s (&occ->peer_identity), ntohs (occ->hello->size),
690 hello_size = ntohs (occ->hello->size);
692 sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
693 msg = GNUNET_malloc (msize);
695 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
696 msg->header.size = htons (msize);
697 msg->peer = htonl (occ->other_peer_id);
698 msg->operation_id = GNUNET_htonll (occ->op_id);
699 (void) memcpy (&msg->peer_identity, &occ->peer_identity,
700 sizeof (struct GNUNET_PeerIdentity));
701 memcpy (msg->hello, occ->hello, hello_size);
702 GNUNET_TESTBED_queue_message_ (occ->peer2_controller, &msg->header);
706 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n", occ->op_id,
707 GNUNET_i2s (&occ->peer_identity), other_peer_str);
709 GNUNET_TRANSPORT_offer_hello (occ->tcc.th_, occ->hello,
710 occ_hello_sent_cb, occ);
711 if (NULL == occ->ohh)
714 occ->send_hello_task =
715 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
716 (GNUNET_TIME_UNIT_MILLISECONDS,
718 GNUNET_CRYPTO_random_u32
719 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
723 GNUNET_free (other_peer_str);
728 * Callback from cache with needed handles set
730 * @param cls the closure passed to GST_cache_get_handle_transport()
731 * @param ch the handle to CORE. Can be NULL if it is not requested
732 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
733 * @param ignore_ peer identity which is ignored in this callback
736 p2_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch,
737 struct GNUNET_TRANSPORT_Handle *th,
738 const struct GNUNET_PeerIdentity *ignore_)
740 struct OverlayConnectContext *occ = cls;
744 GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s",
745 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
746 GNUNET_SCHEDULER_cancel (occ->timeout_task);
748 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
752 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
753 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
754 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
759 * Connects to the transport of the other peer if it is a local peer and
760 * schedules the send hello task
762 * @param occ the overlay connect context
765 p2_transport_connect (struct OverlayConnectContext *occ)
767 GNUNET_assert (NULL == occ->emsg);
768 GNUNET_assert (NULL != occ->hello);
769 GNUNET_assert (NULL == occ->ghh);
770 GNUNET_assert (NULL == occ->p1th);
771 if (NULL == occ->peer2_controller)
773 GST_peer_list[occ->other_peer_id]->reference_cnt++;
775 GST_cache_get_handle_transport (occ->other_peer_id,
776 GST_peer_list[occ->other_peer_id]->
778 &p2_transport_connect_cache_callback,
783 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
784 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
785 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
790 * Test for checking whether HELLO message is empty
792 * @param cls empty flag to set
793 * @param address the HELLO
794 * @param expiration expiration of the HELLO
798 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
799 struct GNUNET_TIME_Absolute expiration)
809 * Function called whenever there is an update to the HELLO of peers in the
810 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
811 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
814 * @param hello our updated HELLO
817 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
819 struct OverlayConnectContext *occ = cls;
823 msize = ntohs (hello->size);
825 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
826 hello, GNUNET_NO, &test_address,
828 if (GNUNET_YES == empty)
830 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n", occ->op_id,
831 GNUNET_i2s (&occ->peer_identity));
834 LOG_DEBUG ("0x%llx: Received HELLO of %s\n", occ->op_id,
835 GNUNET_i2s (&occ->peer_identity));
836 occ->hello = GNUNET_malloc (msize);
837 GST_cache_add_hello (occ->peer_id, hello);
838 memcpy (occ->hello, hello, msize);
839 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
841 GNUNET_TRANSPORT_disconnect (occ->p1th);
843 occ->peer->reference_cnt--;
844 GNUNET_free_non_null (occ->emsg);
846 p2_transport_connect (occ);
851 * Callback from cache with needed handles set
853 * @param cls the closure passed to GST_cache_get_handle_transport()
854 * @param ch the handle to CORE. Can be NULL if it is not requested
855 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
856 * @param my_identity the identity of our peer
859 occ_cache_get_handle_core_cb (void *cls, struct GNUNET_CORE_Handle *ch,
860 struct GNUNET_TRANSPORT_Handle *th,
861 const struct GNUNET_PeerIdentity *my_identity)
863 struct OverlayConnectContext *occ = cls;
864 const struct GNUNET_MessageHeader *hello;
866 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
867 GNUNET_free_non_null (occ->emsg);
868 (void) GNUNET_asprintf (&occ->emsg,
869 "0x%llx: Failed to connect to CORE of peer with"
870 "id: %u", occ->op_id, occ->peer_id);
871 if ((NULL == ch) || (NULL == my_identity))
873 GNUNET_free (occ->emsg);
877 GNUNET_CORE_is_peer_connected_sync (ch, &occ->other_peer_identity))
879 LOG_DEBUG ("0x%llx: Target peer already connected\n", occ->op_id);
880 GNUNET_SCHEDULER_cancel (occ->timeout_task);
881 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
882 send_overlay_connect_success_msg (occ);
883 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
886 memcpy (&occ->peer_identity, my_identity,
887 sizeof (struct GNUNET_PeerIdentity));
888 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", occ->op_id,
889 GNUNET_i2s (&occ->peer_identity));
890 /* Lookup for HELLO in hello cache */
891 if (NULL != (hello = GST_cache_lookup_hello (occ->peer_id)))
893 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", occ->op_id,
894 GNUNET_i2s (&occ->peer_identity));
895 occ->hello = GNUNET_copy_message (hello);
896 p2_transport_connect (occ);
899 occ->peer->reference_cnt++;
901 GNUNET_TRANSPORT_connect (occ->peer->details.local.cfg,
902 &occ->peer_identity, NULL, NULL, NULL, NULL);
903 if (NULL == occ->p1th)
905 GNUNET_asprintf (&occ->emsg,
906 "0x%llx: Cannot connect to TRANSPORT of peer %4s",
907 occ->op_id, GNUNET_i2s (&occ->peer_identity));
910 GNUNET_asprintf (&occ->emsg,
911 "0x%llx: Timeout while acquiring HELLO of peer %4s",
912 occ->op_id, GNUNET_i2s (&occ->peer_identity));
913 occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th, &hello_update_cb, occ);
917 GNUNET_SCHEDULER_cancel (occ->timeout_task);
918 occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
924 * Callback to be called when forwarded get peer config operation as part of
925 * overlay connect is successfull. Connection to Peer 1's core is made and is
926 * checked for new connection from peer 2
928 * @param cls ForwardedOperationContext
929 * @param msg the peer create success message
932 overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg)
934 struct OverlayConnectContext *occ = cls;
935 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
938 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
939 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION != ntohs (msg->type))
941 GNUNET_SCHEDULER_cancel (occ->timeout_task);
943 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
946 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
947 memcpy (&occ->other_peer_identity, &cmsg->peer_identity,
948 sizeof (struct GNUNET_PeerIdentity));
949 GNUNET_free_non_null (occ->emsg);
950 GNUNET_asprintf (&occ->emsg,
951 "0x%llx: Timeout while connecting to CORE of peer with "
952 "id: %u", occ->op_id, occ->peer_id);
953 occ->peer->reference_cnt++;
954 occ->cgh_ch = GST_cache_get_handle_core (occ->peer_id,
955 occ->peer->details.local.cfg,
956 occ_cache_get_handle_core_cb,
958 &occ->other_peer_identity,
959 &overlay_connect_notify,
966 * Callback which will be called to after a host registration succeeded or failed
968 * @param cls the RegisteredHostContext
969 * @param emsg the error message; NULL if host registration is successful
972 registeredhost_registration_completion (void *cls, const char *emsg)
974 struct RegisteredHostContext *rhc = cls;
975 struct GNUNET_CONFIGURATION_Handle *cfg;
976 uint32_t peer2_host_id;
978 /* if (NULL != rhc->focc_dll_head) */
979 /* TESTBED_process_next_focc (rhc); */
980 peer2_host_id = GNUNET_TESTBED_host_get_id_ (rhc->reg_host);
981 GNUNET_assert (RHC_INIT == rhc->state);
982 GNUNET_assert (NULL == rhc->sub_op);
983 if ((NULL == rhc->gateway2) || ((peer2_host_id < GST_slave_list_size) /* Check if we have the needed config */
984 && (NULL != GST_slave_list[peer2_host_id])))
986 rhc->state = RHC_LINK;
989 rhc->gateway2) ? our_config : GST_slave_list[peer2_host_id]->cfg;
991 GNUNET_TESTBED_controller_link (rhc, rhc->gateway->controller,
992 rhc->reg_host, rhc->host, cfg,
996 rhc->state = RHC_GET_CFG;
998 GNUNET_TESTBED_get_slave_config (rhc, rhc->gateway2->controller,
1004 * Iterator to match a registered host context
1006 * @param cls pointer 2 pointer of RegisteredHostContext
1007 * @param key current key code
1008 * @param value value in the hash map
1009 * @return GNUNET_YES if we should continue to
1014 reghost_match_iterator (void *cls, const struct GNUNET_HashCode *key,
1017 struct RegisteredHostContext **rh = cls;
1018 struct RegisteredHostContext *rh_val = value;
1020 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1031 * Function to generate the hashcode corresponding to a RegisteredHostContext
1033 * @param reg_host the host which is being registered in RegisteredHostContext
1034 * @param host the host of the controller which has to connect to the above rhost
1035 * @return the hashcode
1037 static struct GNUNET_HashCode
1038 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1039 struct GNUNET_TESTBED_Host *host)
1041 struct GNUNET_HashCode hash;
1042 uint32_t host_ids[2];
1044 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1045 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1046 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1052 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1055 * @param client identification of the client
1056 * @param message the actual message
1059 GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
1060 const struct GNUNET_MessageHeader *message)
1062 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1064 struct OverlayConnectContext *occ;
1065 struct GNUNET_TESTBED_Controller *peer2_controller;
1066 uint64_t operation_id;
1069 uint32_t peer2_host_id;
1071 if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) !=
1072 ntohs (message->size))
1075 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1078 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1079 p1 = ntohl (msg->peer1);
1080 p2 = ntohl (msg->peer2);
1081 if ((p1 >= GST_peer_list_size) || (NULL == GST_peer_list[p1]))
1084 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1087 peer = GST_peer_list[p1];
1088 peer2_host_id = ntohl (msg->peer2_host_id);
1089 operation_id = GNUNET_ntohll (msg->operation_id);
1091 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n", p1,
1093 if (GNUNET_YES == peer->is_remote)
1095 struct ForwardedOperationContext *fopc;
1096 struct Route *route_to_peer2_host;
1097 struct Route *route_to_peer1_host;
1099 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", operation_id);
1100 route_to_peer2_host = NULL;
1101 route_to_peer1_host = NULL;
1102 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1103 if ((NULL != route_to_peer2_host) ||
1104 (peer2_host_id == GST_context->host_id))
1106 /* Peer 2 either below us OR with us */
1107 route_to_peer1_host =
1108 GST_find_dest_route (GST_peer_list[p1]->details.
1109 remote.remote_host_id);
1110 /* Because we get this message only if we know where peer 1 is */
1111 GNUNET_assert (NULL != route_to_peer1_host);
1112 if ((peer2_host_id == GST_context->host_id) ||
1113 (route_to_peer2_host->dest != route_to_peer1_host->dest))
1115 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1116 * different gateways */
1117 struct GNUNET_HashCode hash;
1118 struct RegisteredHostContext *rhc;
1121 rhc = GNUNET_malloc (sizeof (struct RegisteredHostContext));
1122 if (NULL != route_to_peer2_host)
1123 rhc->reg_host = GST_host_list[route_to_peer2_host->dest];
1125 rhc->reg_host = GST_host_list[GST_context->host_id];
1126 rhc->host = GST_host_list[route_to_peer1_host->dest];
1127 GNUNET_assert (NULL != rhc->reg_host);
1128 GNUNET_assert (NULL != rhc->host);
1129 rhc->gateway = peer->details.remote.slave;
1132 route_to_peer2_host) ? NULL :
1133 GST_slave_list[route_to_peer2_host->dest];
1134 rhc->state = RHC_INIT;
1135 GNUNET_SERVER_client_keep (client);
1136 rhc->client = client;
1137 hash = hash_hosts (rhc->reg_host, rhc->host);
1138 skip_focc = GNUNET_NO;
1140 GNUNET_CONTAINER_multihashmap_contains (peer->details.
1141 remote.slave->reghost_map,
1144 GNUNET_CONTAINER_multihashmap_get_multiple (peer->details.remote.
1147 reghost_match_iterator,
1150 /* create and add a new registerd host context */
1151 /* add the focc to its queue */
1152 GNUNET_CONTAINER_multihashmap_put (peer->details.remote.
1153 slave->reghost_map, &hash, rhc,
1154 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1155 GNUNET_assert (NULL != GST_host_list[peer2_host_id]);
1156 GST_queue_host_registration (peer->details.remote.slave,
1157 registeredhost_registration_completion,
1158 rhc, GST_host_list[peer2_host_id]);
1162 /* rhc is now set to the existing one from the hash map by
1163 * reghost_match_iterator() */
1164 /* if queue is empty then ignore creating focc and proceed with
1165 * normal forwarding */
1166 if (RHC_OL_CONNECT == rhc->state)
1167 skip_focc = GNUNET_YES;
1169 if (GNUNET_NO == skip_focc)
1171 struct ForwardedOverlayConnectContext *focc;
1173 focc = GNUNET_malloc (sizeof (struct ForwardedOverlayConnectContext));
1176 focc->peer2_host_id = peer2_host_id;
1177 focc->orig_msg = GNUNET_copy_message (message);
1178 focc->operation_id = operation_id;
1179 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
1180 rhc->focc_dll_tail, focc);
1181 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1186 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1187 GNUNET_SERVER_client_keep (client);
1188 fopc->client = client;
1189 fopc->operation_id = operation_id;
1190 fopc->type = OP_OVERLAY_CONNECT;
1192 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1193 slave->controller, operation_id,
1195 &GST_forwarded_operation_reply_relay,
1197 fopc->timeout_task =
1198 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &GST_forwarded_operation_timeout,
1200 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
1201 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1205 peer2_controller = NULL;
1206 if ((p2 >= GST_peer_list_size) || (NULL == GST_peer_list[p2]))
1208 if ((peer2_host_id >= GST_slave_list_size) ||
1209 (NULL == GST_slave_list[peer2_host_id]))
1211 LOG (GNUNET_ERROR_TYPE_WARNING,
1212 "0x%llx: Configuration of peer2's controller missing for connecting peers"
1213 "%u and %u\n", operation_id, p1, p2);
1214 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1217 peer2_controller = GST_slave_list[peer2_host_id]->controller;
1218 if (NULL == peer2_controller)
1220 GNUNET_break (0); /* What's going on? */
1221 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1227 if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1228 peer2_controller = GST_peer_list[p2]->details.remote.slave->controller;
1230 occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
1231 GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ);
1232 GNUNET_SERVER_client_keep (client);
1233 occ->client = client;
1235 occ->other_peer_id = p2;
1236 occ->peer = GST_peer_list[p1];
1237 occ->op_id = GNUNET_ntohll (msg->operation_id);
1238 occ->peer2_controller = peer2_controller;
1239 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->timeout_task);
1241 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_overlay_connect, occ);
1242 /* Get the identity of the second peer */
1243 if (NULL != occ->peer2_controller)
1245 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1248 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1250 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION);
1251 cmsg.peer_id = msg->peer2;
1252 cmsg.operation_id = msg->operation_id;
1254 GNUNET_TESTBED_forward_operation_msg_ (occ->peer2_controller,
1255 occ->op_id, &cmsg.header,
1256 &overlay_connect_get_config,
1258 GNUNET_asprintf (&occ->emsg,
1259 "0x%llx: Timeout while getting peer identity of peer "
1260 "with id: %u", occ->op_id, occ->other_peer_id);
1261 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1264 GNUNET_TESTING_peer_get_identity (GST_peer_list[occ->other_peer_id]->
1266 &occ->other_peer_identity);
1267 GNUNET_asprintf (&occ->emsg,
1268 "0x%llx: Timeout while connecting to CORE of peer with "
1269 "id: %u", occ->op_id, occ->peer_id);
1270 occ->peer->reference_cnt++;
1271 occ->cgh_ch = GST_cache_get_handle_core (occ->peer_id,
1272 occ->peer->details.local.cfg,
1273 occ_cache_get_handle_core_cb,
1275 &occ->other_peer_identity,
1276 &overlay_connect_notify,
1278 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1283 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1286 * @param rocc the RemoteOverlayConnectCtx
1289 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1291 LOG_DEBUG ("0x%llx: Cleaning up rocc\n", rocc->op_id);
1292 if (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id)
1293 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1294 if (GNUNET_SCHEDULER_NO_TASK != rocc->timeout_rocc_task_id)
1295 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1296 if (NULL != rocc->ohh)
1297 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1298 if (NULL != rocc->tcc.tch)
1299 GNUNET_TRANSPORT_try_connect_cancel (rocc->tcc.tch);
1300 if (GNUNET_SCHEDULER_NO_TASK != rocc->tcc.task)
1301 GNUNET_SCHEDULER_cancel (rocc->tcc.task);
1302 //GNUNET_TRANSPORT_disconnect (rocc->tcc.th_);
1303 GST_cache_get_handle_done (rocc->tcc.cgh_th);
1304 rocc->peer->reference_cnt--;
1305 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1306 (0 == rocc->peer->reference_cnt))
1307 GST_destroy_peer (rocc->peer);
1308 GNUNET_free_non_null (rocc->hello);
1309 GNUNET_CONTAINER_DLL_remove (roccq_head, roccq_tail, rocc);
1315 * Task to timeout rocc and cleanit up
1317 * @param cls the RemoteOverlayConnectCtx
1318 * @param tc the TaskContext from scheduler
1321 timeout_rocc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1323 struct RemoteOverlayConnectCtx *rocc = cls;
1325 GNUNET_assert (rocc->timeout_rocc_task_id != GNUNET_SCHEDULER_NO_TASK);
1326 rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_NO_TASK;
1327 LOG_DEBUG ("0x%llx: rocc timed out\n", rocc->op_id);
1328 cleanup_rocc (rocc);
1333 * Function called to notify transport users that another
1334 * peer connected to us.
1336 * @param cls closure
1337 * @param new_peer the peer that connected
1338 * @param ats performance data
1339 * @param ats_count number of entries in ats (excluding 0-termination)
1342 cache_transport_peer_connect_notify (void *cls,
1343 const struct GNUNET_PeerIdentity *new_peer)
1345 struct RemoteOverlayConnectCtx *rocc = cls;
1347 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n", rocc->op_id);
1348 GNUNET_assert (0 == memcmp (new_peer, &rocc->a_id, sizeof (struct GNUNET_PeerIdentity)));
1349 LOG_DEBUG ("0x%llx: Peer %4s connected\n", rocc->op_id,
1350 GNUNET_i2s (&rocc->a_id));
1351 cleanup_rocc (rocc);
1356 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1357 * whose identity is in RemoteOverlayConnectCtx
1359 * @param cls the RemoteOverlayConnectCtx
1360 * @param tc the TaskContext from scheduler
1363 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1367 * Task that is run when hello has been sent
1369 * @param cls the overlay connect context
1370 * @param tc the scheduler task context; if tc->reason =
1371 * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1372 * GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1375 rocc_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1377 struct RemoteOverlayConnectCtx *rocc = cls;
1380 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rocc->attempt_connect_task_id);
1381 LOG_DEBUG ("0x%llx: HELLO of peer %4s sent to local peer with id: %u\n",
1382 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1383 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
1386 rocc->attempt_connect_task_id =
1387 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1390 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
1392 rocc->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &rocc->tcc);
1397 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1398 * whose identity is in RemoteOverlayConnectCtx
1400 * @param cls the RemoteOverlayConnectCtx
1401 * @param tc the TaskContext from scheduler
1404 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1406 struct RemoteOverlayConnectCtx *rocc = cls;
1408 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id);
1409 rocc->attempt_connect_task_id = GNUNET_SCHEDULER_NO_TASK;
1410 LOG_DEBUG ("0x%llx: Offering HELLO of peer %4s to local peer with id: %u\n",
1411 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1413 GNUNET_TRANSPORT_offer_hello (rocc->tcc.th_, rocc->hello,
1414 rocc_hello_sent_cb, rocc);
1415 if (NULL == rocc->ohh)
1416 rocc->attempt_connect_task_id =
1417 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1418 (GNUNET_TIME_UNIT_MILLISECONDS,
1420 GNUNET_CRYPTO_random_u32
1421 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1422 &attempt_connect_task, rocc);
1427 * Callback from cache with needed handles set
1429 * @param cls the closure passed to GST_cache_get_handle_transport()
1430 * @param ch the handle to CORE. Can be NULL if it is not requested
1431 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1432 * @param ignore_ peer identity which is ignored in this callback
1435 rocc_cache_get_handle_transport_cb (void *cls, struct GNUNET_CORE_Handle *ch,
1436 struct GNUNET_TRANSPORT_Handle *th,
1437 const struct GNUNET_PeerIdentity *ignore_)
1439 struct RemoteOverlayConnectCtx *rocc = cls;
1443 rocc->timeout_rocc_task_id =
1444 GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1448 rocc->tcc.pid = &rocc->a_id;
1449 if (GNUNET_YES == GNUNET_TRANSPORT_check_neighbour_connected (rocc->tcc.th_,
1452 LOG_DEBUG ("0x%llx: Target peer %4s already connected to local peer: %u\n",
1453 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1454 cleanup_rocc (rocc);
1457 rocc->attempt_connect_task_id =
1458 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1463 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages
1466 * @param client identification of the client
1467 * @param message the actual message
1470 GST_handle_remote_overlay_connect (void *cls,
1471 struct GNUNET_SERVER_Client *client,
1472 const struct GNUNET_MessageHeader *message)
1474 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
1475 struct RemoteOverlayConnectCtx *rocc;
1481 msize = ntohs (message->size);
1482 if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize)
1485 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1488 msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message;
1489 if ((NULL == msg->hello) ||
1490 (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)))
1493 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1496 hsize = ntohs (msg->hello->size);
1497 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1501 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1504 peer_id = ntohl (msg->peer);
1505 if ((peer_id >= GST_peer_list_size) ||
1506 (NULL == (peer = GST_peer_list[peer_id])))
1508 GNUNET_break_op (0);
1509 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1512 if (GNUNET_YES == peer->is_remote)
1514 struct GNUNET_MessageHeader *msg2;
1516 msg2 = GNUNET_copy_message (message);
1517 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1519 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1522 rocc = GNUNET_malloc (sizeof (struct RemoteOverlayConnectCtx));
1523 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1524 GNUNET_CONTAINER_DLL_insert_tail (roccq_head, roccq_tail, rocc);
1525 memcpy (&rocc->a_id, &msg->peer_identity,
1526 sizeof (struct GNUNET_PeerIdentity));
1527 LOG_DEBUG ("Received request for overlay connection with op_id: 0x%llx "
1528 "from local peer %u to peer %4s with hello size: %u\n",
1529 rocc->op_id, peer_id, GNUNET_i2s (&rocc->a_id), hsize);
1531 rocc->peer->reference_cnt++;
1532 rocc->hello = GNUNET_malloc (hsize);
1533 memcpy (rocc->hello, msg->hello, hsize);
1535 GST_cache_get_handle_transport (peer_id,
1536 rocc->peer->details.local.cfg,
1537 &rocc_cache_get_handle_transport_cb,
1540 &cache_transport_peer_connect_notify,
1542 rocc->timeout_rocc_task_id =
1543 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_rocc_task, rocc);
1544 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1549 * Clears all pending overlay connect contexts in queue
1554 struct OverlayConnectContext *occ;
1556 while (NULL != (occ = occq_head))
1562 * Clears all pending remote overlay connect contexts in queue
1567 struct RemoteOverlayConnectCtx *rocc;
1569 while (NULL != (rocc = roccq_head))
1570 cleanup_rocc (rocc);