2 This file is part of GNUnet.
3 Copyright (C) 2008--2015 GNUnet e.V.
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 3, 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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, 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"
28 #include "gnunet-service-testbed_connectionpool.h"
31 * Redefine LOG with a changed log component string
36 #define LOG(kind,...) \
37 GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__)
41 * Context information for requesting ATS to connect to a peer
43 struct ConnectivitySuggestContext
47 * The transport handle obtained from cache. Do NOT close/disconnect.
49 struct GNUNET_TRANSPORT_Handle *th_;
52 * Configuration of the peer from cache. Do not free!
54 const struct GNUNET_CONFIGURATION_Handle *cfg;
57 * The GetCacheHandle for the peer2's transport handle
58 * (used to offer the HELLO to the peer).
60 struct GST_ConnectionPool_GetHandle *cgh_p2_th;
63 * The GetCacheHandle for the peer2's ATS handle.
65 struct GST_ConnectionPool_GetHandle *cgh_p2_ats;
68 * The ATS handle for the connectivity suggestion.
70 struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
76 * Types for context information we create for overlay connect requests
78 enum OverlayConnectContextType
81 * This type is used if the overlay connection is local i.e. the connection
82 * has to be made between local peers
87 * Type to be used when the first peer is local and the other peer is on a slave
88 * controller started by us
90 OCC_TYPE_REMOTE_SLAVE,
93 * Type to be used when the first peer is local and the other peer is on a
94 * controller which is not started by us.
96 OCC_TYPE_REMOTE_LATERAL
101 * Context data for operations on second peer in local overlay connection
104 struct LocalPeer2Context
107 * The handle for offering the HELLO of the first peer to the second
110 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
113 * The transport ConnectivitySuggestContext
115 struct ConnectivitySuggestContext tcc;
120 * Context data for operations on second peer in remote overlay connection
123 struct RemotePeer2Context
126 * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay
127 * connection then this can be NULL until the connection to the controller is
130 struct GNUNET_TESTBED_Controller *p2c;
133 * Operation context for the suboperation we start to get the identity of the
136 struct OperationContext *opc;
139 * Notification handle acquire to connect to a remote controller. Only used
140 * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL.
142 struct NeighbourConnectNotification *ncn;
145 * The neighbour handle. Only used if the type of overlay connection is
146 * #OCC_TYPE_REMOTE_LATERAL.
148 struct Neighbour *p2n;
152 * Context information for connecting 2 peers in overlay.
154 struct OverlayConnectContext
157 * The next pointer for maintaining a DLL of all OverlayConnectContexts
159 struct OverlayConnectContext *next;
162 * The prev pointer for maintaining a DLL of all OverlayConnectContexts
164 struct OverlayConnectContext *prev;
167 * The client which has requested for overlay connection. This is used to send
168 * either a success of failure message
170 struct GNUNET_SERVER_Client *client;
173 * the first peer which is to expect an overlay connection from the second peer.
178 * Transport handle of the first peer obtained from cache to get its HELLO. Do
179 * NOT close/disconnect.
181 struct GNUNET_TRANSPORT_Handle *p1th_;
184 * The #GST_ConnectionPool_GetHandle for the peer1's transport handle
186 struct GST_ConnectionPool_GetHandle *cgh_p1th;
189 * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE
190 * level peer connects and to get our identity.
192 struct GST_ConnectionPool_GetHandle *cgh_ch;
195 * HELLO of the first peer. This should be sent to the second peer.
197 struct GNUNET_MessageHeader *hello;
200 * Get GetHelloHandle to acquire a HELLO of the first peer
202 struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
205 * The error message we send if this overlay connect operation has timed out
210 * Context information for operations on the second peer
215 * Context information to be used if the second peer is local
217 struct LocalPeer2Context local;
220 * Context information to be used if the second peer is remote
222 struct RemotePeer2Context remote;
227 * The peer identity of the first peer
229 struct GNUNET_PeerIdentity peer_identity;
232 * The peer identity of the other peer
234 struct GNUNET_PeerIdentity other_peer_identity;
237 * The id of the operation responsible for creating this context
242 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
245 struct GNUNET_SCHEDULER_Task *send_hello_task;
248 * The id of the overlay connect timeout task
250 struct GNUNET_SCHEDULER_Task *timeout_task;
253 * The id of the cleanup task
255 struct GNUNET_SCHEDULER_Task *cleanup_task;
258 * The type of this context information
260 enum OverlayConnectContextType type;
263 * The id of the second peer which is has to connect to the first peer
265 uint32_t other_peer_id;
270 * Context information for remote overlay connect operations. Remote overlay
271 * connections are used when peers A and B reside on different hosts. In these
272 * operations the host controller for peer B is asked by the host controller of
273 * peer A to make peer B connect to peer A by sending the controller of peer B
274 * the HELLO of peer A.
276 struct RemoteOverlayConnectCtx
279 * the next pointer for DLL
281 struct RemoteOverlayConnectCtx *next;
284 * the prev pointer for DLL
286 struct RemoteOverlayConnectCtx *prev;
289 * The peer handle of peer B
296 struct GNUNET_MessageHeader *hello;
299 * The handle for offering HELLO
301 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
304 * The transport try connect context
306 struct ConnectivitySuggestContext tcc;
309 * The peer identity of peer A
311 struct GNUNET_PeerIdentity a_id;
314 * Task for offering HELLO of A to B and doing try_connect
316 struct GNUNET_SCHEDULER_Task *attempt_connect_task_id;
319 * Task to timeout RequestOverlayConnect
321 struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id;
324 * The id of the operation responsible for creating this context
331 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
333 static struct OverlayConnectContext *occq_head;
336 * DLL tail for OverlayConnectContext DLL
338 static struct OverlayConnectContext *occq_tail;
341 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
344 static struct RemoteOverlayConnectCtx *roccq_head;
347 * DLL tail for RequectOverlayConnectContext DLL
349 static struct RemoteOverlayConnectCtx *roccq_tail;
353 * Cleans up ForwardedOverlayConnectContext
355 * @param focc the ForwardedOverlayConnectContext to cleanup
358 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
360 GNUNET_SERVER_client_drop (focc->client);
361 GNUNET_free_non_null (focc->orig_msg);
367 * Timeout task for cancelling a forwarded overlay connect connect
369 * @param cls the ForwardedOverlayConnectContext
372 forwarded_overlay_connect_timeout (void *cls)
374 struct ForwardedOperationContext *fopc = cls;
375 struct RegisteredHostContext *rhc;
376 struct ForwardedOverlayConnectContext *focc;
379 focc = rhc->focc_dll_head;
380 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
381 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1,
383 GST_cleanup_focc (focc);
384 GST_forwarded_operation_timeout (fopc);
385 if (NULL != rhc->focc_dll_head)
386 GST_process_next_focc (rhc);
391 * Callback to be called when forwarded overlay connection operation has a reply
392 * from the sub-controller successfull. We have to relay the reply msg back to
395 * @param cls ForwardedOperationContext
396 * @param msg the peer create success message
399 forwarded_overlay_connect_listener (void *cls,
400 const struct GNUNET_MessageHeader *msg)
402 struct ForwardedOperationContext *fopc = cls;
403 struct RegisteredHostContext *rhc;
404 struct ForwardedOverlayConnectContext *focc;
407 GST_forwarded_operation_reply_relay (cls, msg);
408 focc = rhc->focc_dll_head;
409 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
410 GST_cleanup_focc (focc);
411 if (NULL != rhc->focc_dll_head)
412 GST_process_next_focc (rhc);
417 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
419 * @param rhc the RegisteredHostContext
422 GST_process_next_focc (struct RegisteredHostContext *rhc)
424 struct ForwardedOperationContext *fopc;
425 struct ForwardedOverlayConnectContext *focc;
429 focc = rhc->focc_dll_head;
430 GNUNET_assert (NULL != focc);
431 GNUNET_assert (RHC_DONE == rhc->state);
432 GNUNET_assert (VALID_PEER_ID (focc->peer1));
433 peer = GST_peer_list[focc->peer1];
434 GNUNET_assert (GNUNET_YES == peer->is_remote);
435 GNUNET_assert (NULL != (slave = peer->details.remote.slave));
436 fopc = GNUNET_new (struct ForwardedOperationContext);
437 GNUNET_SERVER_client_keep (focc->client);
438 fopc->client = focc->client;
439 fopc->operation_id = focc->operation_id;
441 fopc->type = OP_OVERLAY_CONNECT;
443 GNUNET_TESTBED_forward_operation_msg_ (slave->controller,
444 focc->operation_id, focc->orig_msg,
445 &forwarded_overlay_connect_listener,
447 GNUNET_free (focc->orig_msg);
448 focc->orig_msg = NULL;
450 GNUNET_SCHEDULER_add_delayed (GST_timeout, &forwarded_overlay_connect_timeout,
452 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
457 * Cleans up any used handles in local peer2 context
459 * @param lp2c the local peer2 context information
462 cleanup_occ_lp2c (struct LocalPeer2Context *lp2c)
464 if (NULL != lp2c->ohh)
466 GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh);
469 if (NULL != lp2c->tcc.cgh_p2_th)
471 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th);
472 lp2c->tcc.cgh_p2_th = NULL;
474 if (NULL != lp2c->tcc.cgh_p2_ats)
476 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats);
477 lp2c->tcc.cgh_p2_ats = NULL;
479 if (NULL != lp2c->tcc.csh)
481 GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh);
482 lp2c->tcc.csh = NULL;
488 * Cleans up any used handles in remote peer2 context. Relinquishes the
489 * remote controller connection if it has been established on-demand.
491 * @param rp2c the remote peer2 context information
494 cleanup_occ_rp2c (struct RemotePeer2Context *rp2c)
496 if (NULL != rp2c->opc)
498 GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc);
501 if (NULL != rp2c->ncn)
503 GST_neighbour_get_connection_cancel (rp2c->ncn);
506 if ( (NULL != rp2c->p2c) && (NULL != rp2c->p2n) )
508 GST_neighbour_release_connection (rp2c->p2n);
514 * Condition for checking if given peer is ready to be destroyed
516 * @param peer the peer to check
518 #define PEER_EXPIRED(peer) \
519 ( (GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt) )
522 * Cleanup overlay connect context structure
524 * @param occ the overlay connect context
527 cleanup_occ (struct OverlayConnectContext *occ)
531 LOG_DEBUG ("0x%llx: Cleaning up occ\n",
533 GNUNET_free_non_null (occ->emsg);
534 GNUNET_free_non_null (occ->hello);
535 GNUNET_SERVER_client_drop (occ->client);
536 if (NULL != occ->send_hello_task)
537 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
538 if (NULL != occ->cleanup_task)
539 GNUNET_SCHEDULER_cancel (occ->cleanup_task);
540 if (NULL != occ->timeout_task)
541 GNUNET_SCHEDULER_cancel (occ->timeout_task);
542 if (NULL != occ->cgh_ch)
543 GST_connection_pool_get_handle_done (occ->cgh_ch);
544 if (NULL != occ->ghh)
545 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
546 GST_connection_pool_get_handle_done (occ->cgh_p1th);
547 GNUNET_assert (NULL != GST_peer_list);
548 GNUNET_assert (occ->peer->reference_cnt > 0);
549 occ->peer->reference_cnt--;
550 if (PEER_EXPIRED (occ->peer))
551 GST_destroy_peer (occ->peer);
555 peer2 = GST_peer_list[occ->other_peer_id];
556 GNUNET_assert (peer2->reference_cnt > 0);
557 peer2->reference_cnt--;
558 if (PEER_EXPIRED (peer2))
559 GST_destroy_peer (peer2);
560 cleanup_occ_lp2c (&occ->p2ctx.local);
562 case OCC_TYPE_REMOTE_SLAVE:
563 case OCC_TYPE_REMOTE_LATERAL:
564 cleanup_occ_rp2c (&occ->p2ctx.remote);
567 GNUNET_CONTAINER_DLL_remove (occq_head,
575 * Task for cleaing up overlay connect context structure
577 * @param cls the overlay connect context
580 do_cleanup_occ (void *cls)
582 struct OverlayConnectContext *occ = cls;
584 occ->cleanup_task = NULL;
590 * Task which will be run when overlay connect request has been timed out
592 * @param cls the OverlayConnectContext
595 timeout_overlay_connect (void *cls)
597 struct OverlayConnectContext *occ = cls;
599 GNUNET_assert (NULL != occ->timeout_task);
600 occ->timeout_task = NULL;
601 /* LOG (GNUNET_ERROR_TYPE_WARNING, */
602 /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
603 /* occ->peer->id, occ->other_peer_id, occ->emsg); */
604 GST_send_operation_fail_msg (occ->client,
615 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
617 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
619 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
621 msg = GNUNET_new (struct GNUNET_TESTBED_ConnectionEventMessage);
623 htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
624 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
625 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
626 msg->peer1 = htonl (occ->peer->id);
627 msg->peer2 = htonl (occ->other_peer_id);
628 msg->operation_id = GNUNET_htonll (occ->op_id);
629 GST_queue_message (occ->client, &msg->header);
634 * Function called to notify transport users that another
635 * peer connected to us.
638 * @param new_peer the peer that connected
641 overlay_connect_notify (void *cls,
642 const struct GNUNET_PeerIdentity *new_peer)
644 struct OverlayConnectContext *occ = cls;
646 char *other_peer_str;
648 LOG_DEBUG ("Overlay connect notify\n");
650 memcmp (new_peer, &occ->peer_identity,
651 sizeof (struct GNUNET_PeerIdentity)))
653 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
654 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
657 &occ->other_peer_identity,
658 sizeof (struct GNUNET_PeerIdentity)))
660 LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n",
663 GNUNET_free (new_peer_str);
664 GNUNET_free (other_peer_str);
667 GNUNET_free (new_peer_str);
668 LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n",
671 GNUNET_i2s (&occ->peer_identity));
672 GNUNET_free (other_peer_str);
673 if (NULL != occ->send_hello_task)
675 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
676 occ->send_hello_task = NULL;
678 GNUNET_assert (NULL != occ->timeout_task);
679 GNUNET_SCHEDULER_cancel (occ->timeout_task);
680 occ->timeout_task = NULL;
684 cleanup_occ_lp2c (&occ->p2ctx.local);
686 case OCC_TYPE_REMOTE_SLAVE:
687 case OCC_TYPE_REMOTE_LATERAL:
688 cleanup_occ_rp2c (&occ->p2ctx.remote);
691 GNUNET_free_non_null (occ->emsg);
693 send_overlay_connect_success_msg (occ);
694 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ,
700 * Callback from cache with needed ATS handle set
702 * @param cls a `struct OverlayConnectCtx *`
703 * @param ch the handle to CORE. Can be NULL if it is not requested
704 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
705 * @param ac the handle to ATS. Can be NULL if it is not requested
706 * @param my_identity the identity of our peer
707 * @param cfg configuration of the peer
710 occ_cache_get_handle_ats_occ_cb (void *cls,
711 struct GNUNET_CORE_Handle *ch,
712 struct GNUNET_TRANSPORT_Handle *th,
713 struct GNUNET_ATS_ConnectivityHandle *ac,
714 const struct GNUNET_PeerIdentity *my_identity,
715 const struct GNUNET_CONFIGURATION_Handle *cfg)
717 struct OverlayConnectContext *occ = cls;
718 struct LocalPeer2Context *lp2c;
720 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
721 GNUNET_assert (NULL != occ->timeout_task);
722 GNUNET_free_non_null (occ->emsg);
725 GNUNET_asprintf (&occ->emsg,
726 "0x%llx: Failed to connect to ATS of peer with id: %u",
729 GNUNET_SCHEDULER_cancel (occ->timeout_task);
731 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect,
737 GNUNET_asprintf (&occ->emsg,
738 "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s",
740 GNUNET_i2s (&occ->other_peer_identity));
742 lp2c = &occ->p2ctx.local;
744 GNUNET_ATS_connectivity_suggest (ac,
751 * Callback from cache with needed ATS handle set
753 * @param cls a `struct RemoteOverlayConnectCtx *`
754 * @param ch the handle to CORE. Can be NULL if it is not requested
755 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
756 * @param ac the handle to ATS. Can be NULL if it is not requested
757 * @param my_identity the identity of our peer
760 occ_cache_get_handle_ats_rocc_cb (void *cls,
761 struct GNUNET_CORE_Handle *ch,
762 struct GNUNET_TRANSPORT_Handle *th,
763 struct GNUNET_ATS_ConnectivityHandle *ac,
764 const struct GNUNET_PeerIdentity *my_identity,
765 const struct GNUNET_CONFIGURATION_Handle *cfg)
767 struct RemoteOverlayConnectCtx *rocc = cls;
770 GNUNET_ATS_connectivity_suggest (ac,
777 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
780 * @param cls the OverlayConnectContext
783 send_hello (void *cls);
787 * Task that is run when hello has been sent If tc->reason =
788 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
789 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
791 * @param cls the overlay connect context
794 occ_hello_sent_cb (void *cls)
796 struct OverlayConnectContext *occ = cls;
797 struct LocalPeer2Context *lp2c;
799 const struct GNUNET_SCHEDULER_TaskContext *tc;
801 tc = GNUNET_SCHEDULER_get_task_context ();
802 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
803 GNUNET_assert (NULL != occ->timeout_task);
804 lp2c = &occ->p2ctx.local;
807 GNUNET_assert (NULL == occ->send_hello_task);
808 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
810 GNUNET_free_non_null (occ->emsg);
811 GNUNET_asprintf (&occ->emsg,
812 "0x%llx: Timeout while offering HELLO to other peer",
814 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello,
818 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
820 GNUNET_free_non_null (occ->emsg);
822 GNUNET_asprintf (&occ->emsg,
823 "0x%llx: Timeout while acquiring ATS of %s from cache",
825 GNUNET_i2s (&occ->other_peer_identity));
826 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
827 lp2c->tcc.cgh_p2_ats =
828 GST_connection_pool_get_handle (occ->other_peer_id,
829 peer2->details.local.cfg,
830 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
831 &occ_cache_get_handle_ats_occ_cb,
832 occ, NULL, NULL, NULL);
837 * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
840 * @param occ the overlay connect context. Its type must be either
841 * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL
844 send_hello_thru_rocc (struct OverlayConnectContext *occ)
846 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
847 char *other_peer_str;
851 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
852 GNUNET_assert (NULL != occ->hello);
853 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
854 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n",
856 GNUNET_i2s (&occ->peer_identity),
857 ntohs (occ->hello->size),
859 GNUNET_free (other_peer_str);
860 hello_size = ntohs (occ->hello->size);
861 msize = sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
862 msg = GNUNET_malloc (msize);
864 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
865 msg->header.size = htons (msize);
866 msg->peer = htonl (occ->other_peer_id);
867 msg->operation_id = GNUNET_htonll (occ->op_id);
868 msg->peer_identity = occ->peer_identity;
872 GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c,
878 * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered
879 * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
880 * send_hello_thru_rocc()
882 * @param cls the OverlayConnectContext
885 send_hello (void *cls)
887 struct OverlayConnectContext *occ = cls;
888 struct LocalPeer2Context *lp2c;
889 char *other_peer_str;
891 occ->send_hello_task = NULL;
892 GNUNET_assert (NULL != occ->timeout_task);
893 GNUNET_assert (NULL != occ->hello);
894 if (OCC_TYPE_LOCAL != occ->type)
896 send_hello_thru_rocc (occ);
899 lp2c = &occ->p2ctx.local;
900 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
901 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n",
903 GNUNET_i2s (&occ->peer_identity),
905 GNUNET_free (other_peer_str);
907 GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg,
911 if (NULL == lp2c->ohh)
914 occ->send_hello_task =
915 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
916 (GNUNET_TIME_UNIT_MILLISECONDS,
918 GNUNET_CRYPTO_random_u32
919 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
926 * Callback from cache with needed handles set
928 * @param cls the closure passed to GST_cache_get_handle_transport()
929 * @param ch the handle to CORE. Can be NULL if it is not requested
930 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
931 * @param ac the handle to ATS. Can be NULL if it is not requested
932 * @param ignore_ peer identity which is ignored in this callback
933 * @param cfg configuration of the peer
936 p2_transport_connect_cache_callback (void *cls,
937 struct GNUNET_CORE_Handle *ch,
938 struct GNUNET_TRANSPORT_Handle *th,
939 struct GNUNET_ATS_ConnectivityHandle *ac,
940 const struct GNUNET_PeerIdentity *ignore_,
941 const struct GNUNET_CONFIGURATION_Handle *cfg)
943 struct OverlayConnectContext *occ = cls;
945 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
948 GNUNET_asprintf (&occ->emsg,
949 "0x%llx: Cannot connect to TRANSPORT of %s",
951 GNUNET_i2s (&occ->other_peer_identity));
952 GNUNET_SCHEDULER_cancel (occ->timeout_task);
954 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
957 occ->p2ctx.local.tcc.th_ = th;
958 occ->p2ctx.local.tcc.cfg = cfg;
959 GNUNET_asprintf (&occ->emsg,
960 "0x%llx: Timeout while offering HELLO to %s",
962 GNUNET_i2s (&occ->other_peer_identity));
963 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
968 * Connects to the transport of the other peer if it is a local peer and
969 * schedules the send hello task
971 * @param occ the overlay connect context
974 p2_transport_connect (struct OverlayConnectContext *occ)
978 GNUNET_assert (NULL == occ->emsg);
979 GNUNET_assert (NULL != occ->hello);
980 GNUNET_assert (NULL == occ->ghh);
981 GNUNET_assert (NULL == occ->p1th_);
982 GNUNET_assert (NULL == occ->cgh_p1th);
983 if (OCC_TYPE_LOCAL == occ->type)
985 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
986 occ->p2ctx.local.tcc.cgh_p2_th =
987 GST_connection_pool_get_handle (occ->other_peer_id,
988 peer2->details.local.cfg,
989 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
990 &p2_transport_connect_cache_callback,
991 occ, NULL, NULL, NULL);
994 GNUNET_asprintf (&occ->emsg,
995 "0x%llx: Timeout while offering HELLO to %s",
997 GNUNET_i2s (&occ->other_peer_identity));
998 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
1003 * Test for checking whether HELLO message is empty
1005 * @param cls empty flag to set
1006 * @param address the HELLO
1007 * @param expiration expiration of the HELLO
1008 * @return #GNUNET_OK
1011 test_address (void *cls,
1012 const struct GNUNET_HELLO_Address *address,
1013 struct GNUNET_TIME_Absolute expiration)
1023 * Function called whenever there is an update to the HELLO of peers in the
1024 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
1025 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
1027 * @param cls closure
1028 * @param hello our updated HELLO
1031 hello_update_cb (void *cls,
1032 const struct GNUNET_MessageHeader *hello)
1034 struct OverlayConnectContext *occ = cls;
1038 msize = ntohs (hello->size);
1040 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
1044 if (GNUNET_YES == empty)
1046 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n",
1048 GNUNET_i2s (&occ->peer_identity));
1051 LOG_DEBUG ("0x%llx: Received HELLO of %s\n",
1053 GNUNET_i2s (&occ->peer_identity));
1054 occ->hello = GNUNET_malloc (msize);
1055 GST_cache_add_hello (occ->peer->id, hello);
1056 memcpy (occ->hello, hello, msize);
1057 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
1059 GST_connection_pool_get_handle_done (occ->cgh_p1th);
1060 occ->cgh_p1th = NULL;
1062 GNUNET_free_non_null (occ->emsg);
1064 p2_transport_connect (occ);
1069 * Callback from cache with needed handles set
1071 * @param cls the closure passed to GST_cache_get_handle_transport()
1072 * @param ch the handle to CORE. Can be NULL if it is not requested
1073 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1074 * @param ac the handle to ATS. Can be NULL if it is not requested
1075 * @param ignore_ peer identity which is ignored in this callback
1078 p1_transport_connect_cache_callback (void *cls,
1079 struct GNUNET_CORE_Handle *ch,
1080 struct GNUNET_TRANSPORT_Handle *th,
1081 struct GNUNET_ATS_ConnectivityHandle *ac,
1082 const struct GNUNET_PeerIdentity *ignore_,
1083 const struct GNUNET_CONFIGURATION_Handle *cfg)
1085 struct OverlayConnectContext *occ = cls;
1087 GNUNET_free_non_null (occ->emsg);
1091 GNUNET_asprintf (&occ->emsg,
1092 "0x%llx: Cannot connect to TRANSPORT of %s",
1094 GNUNET_i2s (&occ->peer_identity));
1095 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1097 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1100 GNUNET_assert (NULL == occ->p1th_);
1101 GNUNET_assert (NULL != occ->cgh_p1th);
1103 GNUNET_asprintf (&occ->emsg,
1104 "0x%llx: Timeout while acquiring HELLO of peer %s",
1106 GNUNET_i2s (&occ->peer_identity));
1107 occ->ghh = GNUNET_TRANSPORT_get_hello (cfg,
1114 * Callback from cache with needed CORE handle set
1116 * @param cls the closure passed to GST_cache_get_handle_transport()
1117 * @param ch the handle to CORE. Can be NULL if it is not requested
1118 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1119 * @param ac the handle to ATS. Can be NULL if it is not requested
1120 * @param my_identity the identity of our peer
1123 occ_cache_get_handle_core_cb (void *cls,
1124 struct GNUNET_CORE_Handle *ch,
1125 struct GNUNET_TRANSPORT_Handle *th,
1126 struct GNUNET_ATS_ConnectivityHandle *ac,
1127 const struct GNUNET_PeerIdentity *my_identity,
1128 const struct GNUNET_CONFIGURATION_Handle *cfg)
1130 struct OverlayConnectContext *occ = cls;
1131 const struct GNUNET_MessageHeader *hello;
1133 GNUNET_assert (NULL != occ->timeout_task);
1134 GNUNET_free_non_null (occ->emsg);
1135 if ((NULL == ch) || (NULL == my_identity))
1137 GNUNET_asprintf (&occ->emsg,
1138 "0x%llx: Failed to connect to CORE of peer with "
1142 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1144 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1149 GNUNET_CORE_is_peer_connected_sync (ch,
1150 &occ->other_peer_identity))
1152 LOG_DEBUG ("0x%llx: Target peer already connected\n",
1154 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1155 occ->timeout_task = NULL;
1156 send_overlay_connect_success_msg (occ);
1157 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
1160 occ->peer_identity = *my_identity;
1161 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n",
1163 GNUNET_i2s (&occ->peer_identity));
1164 /* Lookup for HELLO in hello cache */
1165 if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
1167 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n",
1169 GNUNET_i2s (&occ->peer_identity));
1170 occ->hello = GNUNET_copy_message (hello);
1171 p2_transport_connect (occ);
1174 GNUNET_asprintf (&occ->emsg,
1175 "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
1177 GNUNET_i2s (&occ->peer_identity));
1179 GST_connection_pool_get_handle (occ->peer->id,
1180 occ->peer->details.local.cfg,
1181 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1182 p1_transport_connect_cache_callback,
1189 * Callback to be called when forwarded get peer config operation as part of
1190 * overlay connect is successfull. Connection to Peer 1's core is made and is
1191 * checked for new connection from peer 2
1193 * @param cls ForwardedOperationContext
1194 * @param msg the peer create success message
1197 overlay_connect_get_config (void *cls,
1198 const struct GNUNET_MessageHeader *msg)
1200 struct OverlayConnectContext *occ = cls;
1201 struct RemotePeer2Context *rp2c;
1202 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
1204 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1205 rp2c = &occ->p2ctx.remote;
1207 GNUNET_assert (NULL != occ->timeout_task);
1208 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
1210 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1212 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1215 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1216 occ->other_peer_identity = cmsg->peer_identity;
1217 GNUNET_free_non_null (occ->emsg);
1218 GNUNET_asprintf (&occ->emsg,
1219 "0x%llx: Timeout while connecting to CORE of peer with "
1224 GST_connection_pool_get_handle (occ->peer->id,
1225 occ->peer->details.local.cfg,
1226 GST_CONNECTIONPOOL_SERVICE_CORE,
1227 occ_cache_get_handle_core_cb,
1229 &occ->other_peer_identity,
1230 &overlay_connect_notify,
1237 * Callback which will be called after a host registration succeeded or failed
1239 * @param cls the RegisteredHostContext
1240 * @param emsg the error message; NULL if host registration is successful
1243 host_registration_comp (void *cls, const char *emsg)
1245 struct RegisteredHostContext *rhc = cls;
1247 rhc->state = RHC_DONE;
1248 GST_process_next_focc (rhc);
1253 * Iterator to match a registered host context
1255 * @param cls pointer 2 pointer of RegisteredHostContext
1256 * @param key current key code
1257 * @param value value in the hash map
1258 * @return #GNUNET_YES if we should continue to
1260 * #GNUNET_NO if not.
1263 reghost_match_iterator (void *cls,
1264 const struct GNUNET_HashCode *key,
1267 struct RegisteredHostContext **rh = cls;
1268 struct RegisteredHostContext *rh_val = value;
1270 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1281 * Function to generate the hashcode corresponding to a RegisteredHostContext
1283 * @param reg_host the host which is being registered in RegisteredHostContext
1284 * @param host the host of the controller which has to connect to the above rhost
1285 * @return the hashcode
1287 static struct GNUNET_HashCode
1288 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1289 struct GNUNET_TESTBED_Host *host)
1291 struct GNUNET_HashCode hash;
1292 uint32_t host_ids[2];
1294 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1295 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1296 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1302 * Checks if the given host is registered at the given slave.
1304 * @param slave the slave where registration has to be checked. The check is
1305 * actually done through a locally maintained hashmap. No
1306 * communication with the slave is involved.
1307 * @param host the host to register
1308 * @return If the given host is not registered already or the registration is
1309 * pending, it returns the registration context. Any overlay connects
1310 * to be forwarded should be queued in the context so that they can be
1311 * executed when the registration is completed. If the given host is
1312 * already registered, NULL is returned.
1314 static struct RegisteredHostContext *
1315 register_host (struct Slave *slave,
1316 struct GNUNET_TESTBED_Host *host)
1318 struct GNUNET_HashCode hash;
1319 struct RegisteredHostContext *rhc;
1321 rhc = GNUNET_new (struct RegisteredHostContext);
1322 rhc->reg_host = host;
1323 rhc->host = GST_host_list[slave->host_id];
1324 GNUNET_assert (NULL != rhc->reg_host);
1325 GNUNET_assert (NULL != rhc->host);
1326 rhc->state = RHC_INIT;
1327 hash = hash_hosts (rhc->reg_host, rhc->host);
1329 GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, &hash)) ||
1331 GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
1333 reghost_match_iterator,
1336 /* create and add a new registerd host context */
1337 /* add the focc to its queue */
1338 GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, &hash, rhc,
1339 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1340 GST_queue_host_registration (slave, host_registration_comp,
1341 rhc, rhc->reg_host);
1345 /* rhc is now set to the existing one from the hash map by
1346 * reghost_match_iterator() */
1347 /* if queue is empty then ignore creating focc and proceed with normal
1349 if (RHC_DONE == rhc->state)
1357 * Forwards the overlay connect request to a slave controller. Before
1358 * forwarding, any hosts which are needed to be known by the slave controller to
1359 * execute the overlay connect request are registered at slave.
1361 * @param msg the overlay connect request message to be forwarded
1362 * @param client the client to which the status of the forwarded request has to
1366 forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
1367 struct GNUNET_SERVER_Client *client)
1369 struct ForwardedOperationContext *fopc;
1370 struct Route *route_to_peer2_host;
1371 struct Route *route_to_peer1_host;
1373 struct RegisteredHostContext *rhc;
1374 struct ForwardedOverlayConnectContext *focc;
1376 uint32_t peer2_host_id;
1380 p1 = ntohl (msg->peer1);
1381 p2 = ntohl (msg->peer2);
1382 op_id = GNUNET_ntohll (msg->operation_id);
1383 peer2_host_id = ntohl (msg->peer2_host_id);
1384 GNUNET_assert (VALID_PEER_ID (p1));
1385 GNUNET_assert (VALID_HOST_ID (peer2_host_id));
1386 peer = GST_peer_list[p1];
1387 GNUNET_assert (GNUNET_YES == peer->is_remote);
1388 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
1389 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1390 route_to_peer1_host = GST_find_dest_route
1391 (peer->details.remote.remote_host_id);
1392 GNUNET_assert (NULL != route_to_peer1_host);
1393 if ((NULL != route_to_peer2_host) &&
1394 (route_to_peer1_host->dest == route_to_peer2_host->dest))
1396 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1397 different subtrees OR peer2 is on a subtree unknown to us */
1398 if (NULL != (rhc = register_host (peer->details.remote.slave,
1399 GST_host_list[peer2_host_id])))
1401 LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, p2);
1402 focc = GNUNET_new (struct ForwardedOverlayConnectContext);
1405 focc->peer2_host_id = peer2_host_id;
1406 focc->orig_msg = GNUNET_copy_message (&msg->header);
1407 focc->operation_id = op_id;
1408 focc->client = client;
1409 GNUNET_SERVER_client_keep (client);
1410 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, rhc->focc_dll_tail,
1416 LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, p2);
1417 fopc = GNUNET_new (struct ForwardedOperationContext);
1418 GNUNET_SERVER_client_keep (client);
1419 fopc->client = client;
1420 fopc->operation_id = op_id;
1421 fopc->type = OP_OVERLAY_CONNECT;
1423 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1424 slave->controller, op_id,
1426 &GST_forwarded_operation_reply_relay,
1428 fopc->timeout_task =
1429 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1430 &GST_forwarded_operation_timeout,
1432 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
1439 * Callback called when a connection to the controller of peer2 has been
1442 * @param cls the overlay connect contexts
1443 * @param c handle to the controller connection
1446 p2_controller_connect_cb (void *cls,
1447 struct GNUNET_TESTBED_Controller *c)
1449 struct OverlayConnectContext *occ = cls;
1450 struct RemotePeer2Context *rp2c;
1451 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1453 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1454 rp2c = &occ->p2ctx.remote;
1458 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1460 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
1461 cmsg.peer_id = htonl (occ->other_peer_id);
1462 cmsg.operation_id = GNUNET_htonll (occ->op_id);
1464 GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
1465 occ->op_id, &cmsg.header,
1466 &overlay_connect_get_config,
1468 GNUNET_free_non_null (occ->emsg);
1469 GNUNET_asprintf (&occ->emsg,
1470 "0x%llx: Timeout while getting peer identity of peer "
1473 occ->other_peer_id);
1478 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1481 * @param client identification of the client
1482 * @param message the actual message
1485 GST_handle_overlay_connect (void *cls,
1486 struct GNUNET_SERVER_Client *client,
1487 const struct GNUNET_MessageHeader *message)
1489 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1492 struct OverlayConnectContext *occ;
1493 struct Neighbour *p2n;
1494 uint64_t operation_id;
1497 uint32_t peer2_host_id;
1499 if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) !=
1500 ntohs (message->size))
1503 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1506 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1507 p1 = ntohl (msg->peer1);
1508 p2 = ntohl (msg->peer2);
1509 if (!VALID_PEER_ID (p1))
1512 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1515 peer = GST_peer_list[p1];
1516 operation_id = GNUNET_ntohll (msg->operation_id);
1518 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n",
1522 peer2_host_id = ntohl (msg->peer2_host_id);
1523 if (GNUNET_YES == peer->is_remote)
1525 if (! VALID_HOST_ID (peer2_host_id))
1528 GNUNET_SERVER_receive_done (client,
1532 forward_overlay_connect (msg, client);
1533 GNUNET_SERVER_receive_done (client,
1538 occ = GNUNET_new (struct OverlayConnectContext);
1539 occ->type = OCC_TYPE_LOCAL;
1540 if (!VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */
1542 if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1544 if (!VALID_HOST_ID (peer2_host_id))
1547 LOG (GNUNET_ERROR_TYPE_WARNING,
1548 "0x%llx: Peer %u's host not in our neighbours list\n",
1550 GNUNET_SERVER_receive_done (client,
1555 p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
1557 occ->type = OCC_TYPE_REMOTE_LATERAL;
1558 occ->p2ctx.remote.p2n = p2n;
1560 else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1562 occ->type = OCC_TYPE_REMOTE_SLAVE;
1563 occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
1565 GNUNET_CONTAINER_DLL_insert_tail (occq_head,
1568 GNUNET_SERVER_client_keep (client);
1569 occ->client = client;
1570 occ->other_peer_id = p2;
1571 GST_peer_list[p1]->reference_cnt++;
1572 occ->peer = GST_peer_list[p1];
1573 occ->op_id = operation_id;
1574 GNUNET_assert (NULL == occ->timeout_task);
1576 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1577 &timeout_overlay_connect,
1581 case OCC_TYPE_REMOTE_LATERAL:
1582 GNUNET_asprintf (&occ->emsg,
1583 "0x%llx: Timeout while acquiring connection to peer %u's "
1588 occ->p2ctx.remote.ncn =
1589 GST_neighbour_get_connection (p2n, &p2_controller_connect_cb, occ);
1591 case OCC_TYPE_REMOTE_SLAVE:
1592 p2_controller_connect_cb (occ, occ->p2ctx.remote.p2c);
1594 case OCC_TYPE_LOCAL:
1595 peer2 = GST_peer_list[occ->other_peer_id];
1596 peer2->reference_cnt++;
1597 GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
1598 &occ->other_peer_identity);
1599 GNUNET_asprintf (&occ->emsg,
1600 "0x%llx: Timeout while connecting to CORE of peer with "
1605 GST_connection_pool_get_handle (occ->peer->id,
1606 occ->peer->details.local.cfg,
1607 GST_CONNECTIONPOOL_SERVICE_CORE,
1608 occ_cache_get_handle_core_cb, occ,
1609 &occ->other_peer_identity,
1610 &overlay_connect_notify, occ);
1613 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1618 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1621 * @param rocc the RemoteOverlayConnectCtx
1624 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1626 LOG_DEBUG ("0x%llx: Cleaning up rocc\n",
1628 if (NULL != rocc->attempt_connect_task_id)
1629 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1630 if (NULL != rocc->timeout_rocc_task_id)
1631 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1632 if (NULL != rocc->ohh)
1633 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1634 if (NULL != rocc->tcc.csh)
1635 GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh);
1636 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th);
1637 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats);
1638 GNUNET_assert (rocc->peer->reference_cnt > 0);
1639 rocc->peer->reference_cnt--;
1640 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1641 (0 == rocc->peer->reference_cnt))
1642 GST_destroy_peer (rocc->peer);
1643 GNUNET_free_non_null (rocc->hello);
1644 GNUNET_CONTAINER_DLL_remove (roccq_head,
1652 * Task to timeout rocc and cleanit up
1654 * @param cls the RemoteOverlayConnectCtx
1657 timeout_rocc_task (void *cls)
1659 struct RemoteOverlayConnectCtx *rocc = cls;
1661 GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
1662 rocc->timeout_rocc_task_id = NULL;
1663 LOG_DEBUG ("0x%llx: rocc timed out\n",
1665 cleanup_rocc (rocc);
1670 * Function called to notify transport users that another
1671 * peer connected to us.
1673 * @param cls the RemoteOverlayConnectContext
1674 * @param new_peer the peer that connected
1677 cache_transport_peer_connect_notify (void *cls,
1678 const struct GNUNET_PeerIdentity *new_peer)
1680 struct RemoteOverlayConnectCtx *rocc = cls;
1682 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n",
1685 memcmp (new_peer, &rocc->a_id,
1686 sizeof (struct GNUNET_PeerIdentity)));
1687 LOG_DEBUG ("0x%llx: Peer %s connected\n",
1689 GNUNET_i2s (&rocc->a_id));
1690 cleanup_rocc (rocc);
1695 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1696 * whose identity is in RemoteOverlayConnectCtx
1698 * @param cls the RemoteOverlayConnectCtx
1701 attempt_connect_task (void *cls);
1705 * Task that is run when hello has been sent If tc->reason =
1706 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1707 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1709 * @param cls the overlay connect context
1712 rocc_hello_sent_cb (void *cls)
1714 struct RemoteOverlayConnectCtx *rocc = cls;
1715 const struct GNUNET_SCHEDULER_TaskContext *tc;
1718 GNUNET_assert (NULL == rocc->attempt_connect_task_id);
1719 LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n",
1721 GNUNET_i2s (&rocc->a_id),
1723 tc = GNUNET_SCHEDULER_get_task_context ();
1724 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
1727 rocc->attempt_connect_task_id =
1728 GNUNET_SCHEDULER_add_now (&attempt_connect_task,
1732 rocc->tcc.cgh_p2_ats =
1733 GST_connection_pool_get_handle (rocc->peer->id,
1734 rocc->peer->details.local.cfg,
1735 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
1736 &occ_cache_get_handle_ats_rocc_cb,
1737 rocc, NULL, NULL, NULL);
1742 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1743 * whose identity is in RemoteOverlayConnectCtx
1745 * @param cls the RemoteOverlayConnectCtx
1748 attempt_connect_task (void *cls)
1750 struct RemoteOverlayConnectCtx *rocc = cls;
1752 GNUNET_assert (NULL != rocc->attempt_connect_task_id);
1753 rocc->attempt_connect_task_id = NULL;
1754 LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n",
1756 GNUNET_i2s (&rocc->a_id),
1759 GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg,
1761 &rocc_hello_sent_cb,
1763 if (NULL == rocc->ohh)
1764 rocc->attempt_connect_task_id =
1765 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1766 (GNUNET_TIME_UNIT_MILLISECONDS,
1768 GNUNET_CRYPTO_random_u32
1769 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1770 &attempt_connect_task, rocc);
1775 * Callback from cache with needed handles set
1777 * @param cls the closure passed to GST_cache_get_handle_transport()
1778 * @param ch the handle to CORE. Can be NULL if it is not requested
1779 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1780 * @param ac the handle to ATS. Can be NULL if it is not requested
1781 * @param ignore_ peer identity which is ignored in this callback
1784 rocc_cache_get_handle_transport_cb (void *cls,
1785 struct GNUNET_CORE_Handle *ch,
1786 struct GNUNET_TRANSPORT_Handle *th,
1787 struct GNUNET_ATS_ConnectivityHandle *ac,
1788 const struct GNUNET_PeerIdentity *ignore_,
1789 const struct GNUNET_CONFIGURATION_Handle *cfg)
1791 struct RemoteOverlayConnectCtx *rocc = cls;
1795 rocc->timeout_rocc_task_id =
1796 GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1800 rocc->tcc.cfg = cfg;
1802 GNUNET_TRANSPORT_check_peer_connected (rocc->tcc.th_,
1805 LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n",
1807 GNUNET_i2s (&rocc->a_id),
1809 cleanup_rocc (rocc);
1812 rocc->attempt_connect_task_id =
1813 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1818 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REQUEST_CONNECT messages
1821 * @param client identification of the client
1822 * @param message the actual message
1825 GST_handle_remote_overlay_connect (void *cls,
1826 struct GNUNET_SERVER_Client *client,
1827 const struct GNUNET_MessageHeader *message)
1829 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
1830 struct RemoteOverlayConnectCtx *rocc;
1832 struct GNUNET_PeerIdentity pid;
1833 static char pid_str[16];
1838 msize = ntohs (message->size);
1839 if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize)
1842 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1845 msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message;
1846 if ((NULL == msg->hello) ||
1847 ((GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))))
1850 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1853 hsize = ntohs (msg->hello->size);
1854 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1858 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1861 peer_id = ntohl (msg->peer);
1862 if ((peer_id >= GST_peer_list_size) ||
1863 (NULL == (peer = GST_peer_list[peer_id])))
1865 GNUNET_break_op (0);
1866 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1869 if (GNUNET_YES == peer->is_remote)
1871 struct GNUNET_MessageHeader *msg2;
1873 msg2 = GNUNET_copy_message (message);
1874 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1876 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1879 rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
1880 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1881 GNUNET_CONTAINER_DLL_insert_tail (roccq_head,
1884 rocc->a_id = msg->peer_identity;
1885 GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
1887 (void) strncpy (pid_str,
1890 LOG_DEBUG ("0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n",
1893 GNUNET_i2s (&rocc->a_id),
1896 rocc->peer->reference_cnt++;
1897 rocc->hello = GNUNET_malloc (hsize);
1898 memcpy (rocc->hello, msg->hello, hsize);
1899 rocc->tcc.cgh_p2_th =
1900 GST_connection_pool_get_handle (peer_id,
1901 rocc->peer->details.local.cfg,
1902 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1903 &rocc_cache_get_handle_transport_cb,
1906 &cache_transport_peer_connect_notify,
1908 rocc->timeout_rocc_task_id =
1909 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1912 GNUNET_SERVER_receive_done (client,
1918 * Clears all pending overlay connect contexts in queue
1923 struct OverlayConnectContext *occ;
1925 while (NULL != (occ = occq_head))
1931 * Clears all pending remote overlay connect contexts in queue
1936 struct RemoteOverlayConnectCtx *rocc;
1938 while (NULL != (rocc = roccq_head))
1939 cleanup_rocc (rocc);