2 This file is part of GNUnet.
3 Copyright (C) 2008--2016 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
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"
29 #include "gnunet_transport_hello_service.h"
32 * Redefine LOG with a changed log component string
37 #define LOG(kind,...) \
38 GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__)
42 * Context information for requesting ATS to connect to a peer
44 struct ConnectivitySuggestContext
48 * The transport handle obtained from cache. Do NOT close/disconnect.
50 struct GNUNET_TRANSPORT_CoreHandle *th_;
53 * Configuration of the peer from cache. Do not free!
55 const struct GNUNET_CONFIGURATION_Handle *cfg;
58 * The GetCacheHandle for the peer2's transport handle
59 * (used to offer the HELLO to the peer).
61 struct GST_ConnectionPool_GetHandle *cgh_p2_th;
64 * The GetCacheHandle for the peer2's ATS handle.
66 struct GST_ConnectionPool_GetHandle *cgh_p2_ats;
69 * The ATS handle for the connectivity suggestion.
71 struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
77 * Types for context information we create for overlay connect requests
79 enum OverlayConnectContextType
82 * This type is used if the overlay connection is local i.e. the connection
83 * has to be made between local peers
88 * Type to be used when the first peer is local and the other peer is on a slave
89 * controller started by us
91 OCC_TYPE_REMOTE_SLAVE,
94 * Type to be used when the first peer is local and the other peer is on a
95 * controller which is not started by us.
97 OCC_TYPE_REMOTE_LATERAL
102 * Context data for operations on second peer in local overlay connection
105 struct LocalPeer2Context
108 * The handle for offering the HELLO of the first peer to the second
111 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
114 * The transport ConnectivitySuggestContext
116 struct ConnectivitySuggestContext tcc;
121 * Context data for operations on second peer in remote overlay connection
124 struct RemotePeer2Context
127 * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay
128 * connection then this can be NULL until the connection to the controller is
131 struct GNUNET_TESTBED_Controller *p2c;
134 * Operation context for the suboperation we start to get the identity of the
137 struct OperationContext *opc;
140 * Notification handle acquire to connect to a remote controller. Only used
141 * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL.
143 struct NeighbourConnectNotification *ncn;
146 * The neighbour handle. Only used if the type of overlay connection is
147 * #OCC_TYPE_REMOTE_LATERAL.
149 struct Neighbour *p2n;
153 * Context information for connecting 2 peers in overlay.
155 struct OverlayConnectContext
158 * The next pointer for maintaining a DLL of all OverlayConnectContexts
160 struct OverlayConnectContext *next;
163 * The prev pointer for maintaining a DLL of all OverlayConnectContexts
165 struct OverlayConnectContext *prev;
168 * The client which has requested for overlay connection. This is used to send
169 * either a success of failure message
171 struct GNUNET_SERVICE_Client *client;
174 * the first peer which is to expect an overlay connection from the second peer.
179 * Transport handle of the first peer obtained from cache to get its HELLO. Do
180 * NOT close/disconnect.
182 struct GNUNET_TRANSPORT_CoreHandle *p1th_;
185 * The #GST_ConnectionPool_GetHandle for the peer1's transport handle
187 struct GST_ConnectionPool_GetHandle *cgh_p1th;
190 * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE
191 * level peer connects and to get our identity.
193 struct GST_ConnectionPool_GetHandle *cgh_ch;
196 * HELLO of the first peer. This should be sent to the second peer.
198 struct GNUNET_MessageHeader *hello;
201 * Get GetHelloHandle to acquire a HELLO of the first peer
203 struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
206 * The error message we send if this overlay connect operation has timed out
211 * Context information for operations on the second peer
216 * Context information to be used if the second peer is local
218 struct LocalPeer2Context local;
221 * Context information to be used if the second peer is remote
223 struct RemotePeer2Context remote;
228 * The peer identity of the first peer
230 struct GNUNET_PeerIdentity peer_identity;
233 * The peer identity of the other peer
235 struct GNUNET_PeerIdentity other_peer_identity;
238 * The id of the operation responsible for creating this context
243 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
246 struct GNUNET_SCHEDULER_Task *send_hello_task;
249 * The id of the overlay connect timeout task
251 struct GNUNET_SCHEDULER_Task *timeout_task;
254 * The id of the cleanup task
256 struct GNUNET_SCHEDULER_Task *cleanup_task;
259 * The type of this context information
261 enum OverlayConnectContextType type;
264 * The id of the second peer which has to connect to the first peer
266 uint32_t other_peer_id;
271 * Context information for remote overlay connect operations. Remote overlay
272 * connections are used when peers A and B reside on different hosts. In these
273 * operations the host controller for peer B is asked by the host controller of
274 * peer A to make peer B connect to peer A by sending the controller of peer B
275 * the HELLO of peer A.
277 struct RemoteOverlayConnectCtx
280 * the next pointer for DLL
282 struct RemoteOverlayConnectCtx *next;
285 * the prev pointer for DLL
287 struct RemoteOverlayConnectCtx *prev;
290 * The peer handle of peer B
297 struct GNUNET_MessageHeader *hello;
300 * The handle for offering HELLO
302 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
305 * The transport try connect context
307 struct ConnectivitySuggestContext tcc;
310 * The peer identity of peer A
312 struct GNUNET_PeerIdentity a_id;
315 * Task for offering HELLO of A to B and doing try_connect
317 struct GNUNET_SCHEDULER_Task *attempt_connect_task_id;
320 * Task to timeout RequestOverlayConnect
322 struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id;
325 * The id of the operation responsible for creating this context
332 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
334 static struct OverlayConnectContext *occq_head;
337 * DLL tail for OverlayConnectContext DLL
339 static struct OverlayConnectContext *occq_tail;
342 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
345 static struct RemoteOverlayConnectCtx *roccq_head;
348 * DLL tail for RequectOverlayConnectContext DLL
350 static struct RemoteOverlayConnectCtx *roccq_tail;
354 * Cleans up ForwardedOverlayConnectContext
356 * @param focc the ForwardedOverlayConnectContext to cleanup
359 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
361 struct RegisteredHostContext *rhc = focc->rhc;
363 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head,
366 GNUNET_free_non_null (focc->orig_msg);
372 * Timeout task for cancelling a forwarded overlay connect connect
374 * @param cls the `struct ForwardedOperationContext`
377 forwarded_overlay_connect_timeout (void *cls)
379 struct ForwardedOperationContext *fopc = cls;
380 struct RegisteredHostContext *rhc;
381 struct ForwardedOverlayConnectContext *focc;
383 fopc->timeout_task = NULL;
385 focc = rhc->focc_dll_head;
386 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n",
389 GST_cleanup_focc (focc);
390 GST_forwarded_operation_timeout (fopc);
391 if (NULL != rhc->focc_dll_head)
392 GST_process_next_focc (rhc);
397 * Callback to be called when forwarded overlay connection operation has a reply
398 * from the sub-controller successfull. We have to relay the reply msg back to
401 * @param cls ForwardedOperationContext
402 * @param msg the peer create success message
405 forwarded_overlay_connect_listener (void *cls,
406 const struct GNUNET_MessageHeader *msg)
408 struct ForwardedOperationContext *fopc = cls;
409 struct RegisteredHostContext *rhc;
410 struct ForwardedOverlayConnectContext *focc;
413 GST_forwarded_operation_reply_relay (cls, msg);
414 focc = rhc->focc_dll_head;
415 GST_cleanup_focc (focc);
416 if (NULL != rhc->focc_dll_head)
417 GST_process_next_focc (rhc);
422 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
424 * @param rhc the RegisteredHostContext
427 GST_process_next_focc (struct RegisteredHostContext *rhc)
429 struct ForwardedOperationContext *fopc;
430 struct ForwardedOverlayConnectContext *focc;
434 focc = rhc->focc_dll_head;
435 GNUNET_assert (NULL != focc);
436 GNUNET_assert (RHC_DONE == rhc->state);
437 GNUNET_assert (VALID_PEER_ID (focc->peer1));
438 peer = GST_peer_list[focc->peer1];
439 GNUNET_assert (GNUNET_YES == peer->is_remote);
440 GNUNET_assert (NULL != (slave = peer->details.remote.slave));
441 fopc = GNUNET_new (struct ForwardedOperationContext);
442 fopc->client = focc->client;
443 fopc->operation_id = focc->operation_id;
445 fopc->type = OP_OVERLAY_CONNECT;
447 GNUNET_TESTBED_forward_operation_msg_ (slave->controller,
450 &forwarded_overlay_connect_listener,
452 GNUNET_free (focc->orig_msg);
453 focc->orig_msg = NULL;
454 fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout,
455 &forwarded_overlay_connect_timeout,
457 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
464 * Cleans up any used handles in local peer2 context
466 * @param lp2c the local peer2 context information
469 cleanup_occ_lp2c (struct LocalPeer2Context *lp2c)
471 if (NULL != lp2c->ohh)
473 GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh);
476 if (NULL != lp2c->tcc.cgh_p2_th)
478 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th);
479 lp2c->tcc.cgh_p2_th = NULL;
481 if (NULL != lp2c->tcc.cgh_p2_ats)
483 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats);
484 lp2c->tcc.cgh_p2_ats = NULL;
486 if (NULL != lp2c->tcc.csh)
488 GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh);
489 lp2c->tcc.csh = NULL;
495 * Cleans up any used handles in remote peer2 context. Relinquishes the
496 * remote controller connection if it has been established on-demand.
498 * @param rp2c the remote peer2 context information
501 cleanup_occ_rp2c (struct RemotePeer2Context *rp2c)
503 if (NULL != rp2c->opc)
505 GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc);
508 if (NULL != rp2c->ncn)
510 GST_neighbour_get_connection_cancel (rp2c->ncn);
513 if ( (NULL != rp2c->p2c) && (NULL != rp2c->p2n) )
515 GST_neighbour_release_connection (rp2c->p2n);
521 * Condition for checking if given peer is ready to be destroyed
523 * @param peer the peer to check
525 #define PEER_EXPIRED(peer) \
526 ( (GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt) )
529 * Cleanup overlay connect context structure
531 * @param occ the overlay connect context
534 cleanup_occ (struct OverlayConnectContext *occ)
538 LOG_DEBUG ("0x%llx: Cleaning up occ\n",
540 GNUNET_free_non_null (occ->emsg);
541 GNUNET_free_non_null (occ->hello);
542 if (NULL != occ->send_hello_task)
543 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
544 if (NULL != occ->cleanup_task)
545 GNUNET_SCHEDULER_cancel (occ->cleanup_task);
546 if (NULL != occ->timeout_task)
547 GNUNET_SCHEDULER_cancel (occ->timeout_task);
548 if (NULL != occ->cgh_ch)
549 GST_connection_pool_get_handle_done (occ->cgh_ch);
550 if (NULL != occ->ghh)
551 GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
552 GST_connection_pool_get_handle_done (occ->cgh_p1th);
553 GNUNET_assert (NULL != GST_peer_list);
554 GNUNET_assert (occ->peer->reference_cnt > 0);
555 occ->peer->reference_cnt--;
556 if (PEER_EXPIRED (occ->peer))
557 GST_destroy_peer (occ->peer);
561 peer2 = GST_peer_list[occ->other_peer_id];
562 GNUNET_assert (peer2->reference_cnt > 0);
563 peer2->reference_cnt--;
564 if (PEER_EXPIRED (peer2))
565 GST_destroy_peer (peer2);
566 cleanup_occ_lp2c (&occ->p2ctx.local);
568 case OCC_TYPE_REMOTE_SLAVE:
569 case OCC_TYPE_REMOTE_LATERAL:
570 cleanup_occ_rp2c (&occ->p2ctx.remote);
573 GNUNET_CONTAINER_DLL_remove (occq_head,
581 * Task for cleaing up overlay connect context structure
583 * @param cls the overlay connect context
586 do_cleanup_occ (void *cls)
588 struct OverlayConnectContext *occ = cls;
590 occ->cleanup_task = NULL;
596 * Task which will be run when overlay connect request has been timed out
598 * @param cls the OverlayConnectContext
601 timeout_overlay_connect (void *cls)
603 struct OverlayConnectContext *occ = cls;
605 GNUNET_assert (NULL != occ->timeout_task);
606 occ->timeout_task = NULL;
607 /* LOG (GNUNET_ERROR_TYPE_WARNING, */
608 /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
609 /* occ->peer->id, occ->other_peer_id, occ->emsg); */
610 GST_send_operation_fail_msg (occ->client,
618 * Notify OC subsystem that @a client disconnected.
620 * @param client the client that disconnected
623 GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client)
625 struct ForwardedOperationContext *fopc;
626 struct ForwardedOperationContext *fopcn;
627 struct OverlayConnectContext *occ;
628 struct OverlayConnectContext *occn;
630 for (fopc = fopcq_head; NULL != fopc; fopc = fopcn)
633 if (fopc->client == client)
635 GNUNET_SCHEDULER_cancel (fopc->timeout_task);
636 GST_forwarded_operation_timeout (fopc);
639 for (occ = occq_head; NULL != occ; occ = occn)
642 if (occ->client == client)
645 // FIXME: implement clean up for client_keep replacements!
655 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
657 struct GNUNET_MQ_Envelope *env;
658 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
660 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
662 env = GNUNET_MQ_msg (msg,
663 GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
664 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
665 msg->peer1 = htonl (occ->peer->id);
666 msg->peer2 = htonl (occ->other_peer_id);
667 msg->operation_id = GNUNET_htonll (occ->op_id);
668 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (occ->client),
674 * Function called to notify transport users that another
675 * peer connected to us.
678 * @param new_peer the peer that connected
681 overlay_connect_notify (void *cls,
682 const struct GNUNET_PeerIdentity *new_peer)
684 struct OverlayConnectContext *occ = cls;
686 char *other_peer_str;
688 LOG_DEBUG ("Overlay connect notify\n");
690 memcmp (new_peer, &occ->peer_identity,
691 sizeof (struct GNUNET_PeerIdentity)))
693 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
694 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
697 &occ->other_peer_identity,
698 sizeof (struct GNUNET_PeerIdentity)))
700 LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n",
703 GNUNET_free (new_peer_str);
704 GNUNET_free (other_peer_str);
707 GNUNET_free (new_peer_str);
708 LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n",
711 GNUNET_i2s (&occ->peer_identity));
712 GNUNET_free (other_peer_str);
713 if (NULL != occ->send_hello_task)
715 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
716 occ->send_hello_task = NULL;
718 GNUNET_assert (NULL != occ->timeout_task);
719 GNUNET_SCHEDULER_cancel (occ->timeout_task);
720 occ->timeout_task = NULL;
724 cleanup_occ_lp2c (&occ->p2ctx.local);
726 case OCC_TYPE_REMOTE_SLAVE:
727 case OCC_TYPE_REMOTE_LATERAL:
728 cleanup_occ_rp2c (&occ->p2ctx.remote);
731 GNUNET_free_non_null (occ->emsg);
733 send_overlay_connect_success_msg (occ);
734 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ,
740 * Callback from cache with needed ATS handle set
742 * @param cls a `struct OverlayConnectCtx *`
743 * @param ch the handle to CORE. Can be NULL if it is not requested
744 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
745 * @param ac the handle to ATS. Can be NULL if it is not requested
746 * @param my_identity the identity of our peer
747 * @param cfg configuration of the peer
750 occ_cache_get_handle_ats_occ_cb (void *cls,
751 struct GNUNET_CORE_Handle *ch,
752 struct GNUNET_TRANSPORT_CoreHandle *th,
753 struct GNUNET_ATS_ConnectivityHandle *ac,
754 const struct GNUNET_PeerIdentity *my_identity,
755 const struct GNUNET_CONFIGURATION_Handle *cfg)
757 struct OverlayConnectContext *occ = cls;
758 struct LocalPeer2Context *lp2c;
760 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
761 GNUNET_assert (NULL != occ->timeout_task);
762 GNUNET_free_non_null (occ->emsg);
765 GNUNET_asprintf (&occ->emsg,
766 "0x%llx: Failed to connect to ATS of peer with id: %u",
769 GNUNET_SCHEDULER_cancel (occ->timeout_task);
771 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect,
777 GNUNET_asprintf (&occ->emsg,
778 "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s",
780 GNUNET_i2s (&occ->other_peer_identity));
782 lp2c = &occ->p2ctx.local;
784 GNUNET_ATS_connectivity_suggest (ac,
791 * Callback from cache with needed ATS handle set
793 * @param cls a `struct RemoteOverlayConnectCtx *`
794 * @param ch the handle to CORE. Can be NULL if it is not requested
795 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
796 * @param ac the handle to ATS. Can be NULL if it is not requested
797 * @param my_identity the identity of our peer
800 occ_cache_get_handle_ats_rocc_cb (void *cls,
801 struct GNUNET_CORE_Handle *ch,
802 struct GNUNET_TRANSPORT_CoreHandle *th,
803 struct GNUNET_ATS_ConnectivityHandle *ac,
804 const struct GNUNET_PeerIdentity *my_identity,
805 const struct GNUNET_CONFIGURATION_Handle *cfg)
807 struct RemoteOverlayConnectCtx *rocc = cls;
810 GNUNET_ATS_connectivity_suggest (ac,
817 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
820 * @param cls the OverlayConnectContext
823 send_hello (void *cls);
827 * Task that is run when hello has been sent If tc->reason =
828 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
829 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
831 * @param cls the overlay connect context
834 occ_hello_sent_cb (void *cls)
836 struct OverlayConnectContext *occ = cls;
837 struct LocalPeer2Context *lp2c;
840 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
841 GNUNET_assert (NULL != occ->timeout_task);
842 lp2c = &occ->p2ctx.local;
845 GNUNET_assert (NULL == occ->send_hello_task);
846 GNUNET_free_non_null (occ->emsg);
848 GNUNET_asprintf (&occ->emsg,
849 "0x%llx: Timeout while acquiring ATS of %s from cache",
851 GNUNET_i2s (&occ->other_peer_identity));
852 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
853 lp2c->tcc.cgh_p2_ats =
854 GST_connection_pool_get_handle (occ->other_peer_id,
855 peer2->details.local.cfg,
856 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
857 &occ_cache_get_handle_ats_occ_cb,
858 occ, NULL, NULL, NULL);
863 * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
866 * @param occ the overlay connect context. Its type must be either
867 * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL
870 send_hello_thru_rocc (struct OverlayConnectContext *occ)
872 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
873 char *other_peer_str;
877 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
878 GNUNET_assert (NULL != occ->hello);
879 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
880 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n",
882 GNUNET_i2s (&occ->peer_identity),
883 ntohs (occ->hello->size),
885 GNUNET_free (other_peer_str);
886 hello_size = ntohs (occ->hello->size);
887 msize = sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
888 msg = GNUNET_malloc (msize);
890 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
891 msg->header.size = htons (msize);
892 msg->peer = htonl (occ->other_peer_id);
893 msg->operation_id = GNUNET_htonll (occ->op_id);
894 msg->peer_identity = occ->peer_identity;
895 GNUNET_memcpy (msg->hello,
898 GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c,
904 * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered
905 * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
906 * send_hello_thru_rocc()
908 * @param cls the OverlayConnectContext
911 send_hello (void *cls)
913 struct OverlayConnectContext *occ = cls;
914 struct LocalPeer2Context *lp2c;
915 char *other_peer_str;
917 occ->send_hello_task = NULL;
918 GNUNET_assert (NULL != occ->timeout_task);
919 GNUNET_assert (NULL != occ->hello);
920 if (OCC_TYPE_LOCAL != occ->type)
922 send_hello_thru_rocc (occ);
925 lp2c = &occ->p2ctx.local;
926 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
927 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n",
929 GNUNET_i2s (&occ->peer_identity),
931 GNUNET_free (other_peer_str);
933 GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg,
937 if (NULL == lp2c->ohh)
940 occ->send_hello_task =
941 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
942 (GNUNET_TIME_UNIT_MILLISECONDS,
944 GNUNET_CRYPTO_random_u32
945 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
952 * Callback from cache with needed handles set
954 * @param cls the closure passed to GST_cache_get_handle_transport()
955 * @param ch the handle to CORE. Can be NULL if it is not requested
956 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
957 * @param ac the handle to ATS. Can be NULL if it is not requested
958 * @param ignore_ peer identity which is ignored in this callback
959 * @param cfg configuration of the peer
962 p2_transport_connect_cache_callback (void *cls,
963 struct GNUNET_CORE_Handle *ch,
964 struct GNUNET_TRANSPORT_CoreHandle *th,
965 struct GNUNET_ATS_ConnectivityHandle *ac,
966 const struct GNUNET_PeerIdentity *ignore_,
967 const struct GNUNET_CONFIGURATION_Handle *cfg)
969 struct OverlayConnectContext *occ = cls;
971 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
974 GNUNET_asprintf (&occ->emsg,
975 "0x%llx: Cannot connect to TRANSPORT of %s",
977 GNUNET_i2s (&occ->other_peer_identity));
978 GNUNET_SCHEDULER_cancel (occ->timeout_task);
980 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
983 occ->p2ctx.local.tcc.th_ = th;
984 occ->p2ctx.local.tcc.cfg = cfg;
985 GNUNET_asprintf (&occ->emsg,
986 "0x%llx: Timeout while offering HELLO to %s",
988 GNUNET_i2s (&occ->other_peer_identity));
989 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
994 * Connects to the transport of the other peer if it is a local peer and
995 * schedules the send hello task
997 * @param occ the overlay connect context
1000 p2_transport_connect (struct OverlayConnectContext *occ)
1004 /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the
1006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1007 "Connecting to transport of peer %s to obtain HELLO\n",
1008 GNUNET_i2s (&occ->other_peer_identity));
1009 GNUNET_assert (NULL == occ->emsg);
1010 GNUNET_assert (NULL != occ->hello);
1011 GNUNET_assert (NULL == occ->ghh);
1012 GNUNET_assert (NULL == occ->p1th_);
1013 GNUNET_assert (NULL == occ->cgh_p1th);
1014 if (OCC_TYPE_LOCAL == occ->type)
1016 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
1017 occ->p2ctx.local.tcc.cgh_p2_th =
1018 GST_connection_pool_get_handle (occ->other_peer_id,
1019 peer2->details.local.cfg,
1020 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1021 &p2_transport_connect_cache_callback,
1022 occ, NULL, NULL, NULL);
1025 GNUNET_asprintf (&occ->emsg,
1026 "0x%llx: Timeout while offering HELLO to %s",
1028 GNUNET_i2s (&occ->other_peer_identity));
1029 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
1034 * Test for checking whether HELLO message is empty
1036 * @param cls empty flag to set
1037 * @param address the HELLO
1038 * @param expiration expiration of the HELLO
1039 * @return #GNUNET_OK
1042 test_address (void *cls,
1043 const struct GNUNET_HELLO_Address *address,
1044 struct GNUNET_TIME_Absolute expiration)
1054 * Function called whenever there is an update to the HELLO of peers in the
1055 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
1056 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
1058 * @param cls closure
1059 * @param hello our updated HELLO
1062 hello_update_cb (void *cls,
1063 const struct GNUNET_MessageHeader *hello)
1065 struct OverlayConnectContext *occ = cls;
1069 msize = ntohs (hello->size);
1071 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
1075 if (GNUNET_YES == empty)
1077 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n",
1079 GNUNET_i2s (&occ->peer_identity));
1082 LOG_DEBUG ("0x%llx: Received HELLO of %s\n",
1084 GNUNET_i2s (&occ->peer_identity));
1085 occ->hello = GNUNET_malloc (msize);
1086 GST_cache_add_hello (occ->peer->id, hello);
1087 GNUNET_memcpy (occ->hello, hello, msize);
1088 GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
1090 GST_connection_pool_get_handle_done (occ->cgh_p1th);
1091 occ->cgh_p1th = NULL;
1093 GNUNET_free_non_null (occ->emsg);
1095 p2_transport_connect (occ);
1100 * Callback from cache with needed handles set
1102 * @param cls the closure passed to GST_cache_get_handle_transport()
1103 * @param ch the handle to CORE. Can be NULL if it is not requested
1104 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1105 * @param ac the handle to ATS. Can be NULL if it is not requested
1106 * @param ignore_ peer identity which is ignored in this callback
1109 p1_transport_connect_cache_callback (void *cls,
1110 struct GNUNET_CORE_Handle *ch,
1111 struct GNUNET_TRANSPORT_CoreHandle *th,
1112 struct GNUNET_ATS_ConnectivityHandle *ac,
1113 const struct GNUNET_PeerIdentity *ignore_,
1114 const struct GNUNET_CONFIGURATION_Handle *cfg)
1116 struct OverlayConnectContext *occ = cls;
1118 GNUNET_free_non_null (occ->emsg);
1122 GNUNET_asprintf (&occ->emsg,
1123 "0x%llx: Cannot connect to TRANSPORT of %s",
1125 GNUNET_i2s (&occ->peer_identity));
1126 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1128 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1131 GNUNET_assert (NULL == occ->p1th_);
1132 GNUNET_assert (NULL != occ->cgh_p1th);
1134 GNUNET_asprintf (&occ->emsg,
1135 "0x%llx: Timeout while acquiring HELLO of peer %s",
1137 GNUNET_i2s (&occ->peer_identity));
1138 occ->ghh = GNUNET_TRANSPORT_hello_get (cfg,
1139 GNUNET_TRANSPORT_AC_ANY,
1146 * Callback from cache with needed CORE handle set
1148 * @param cls the closure passed to GST_cache_get_handle_transport()
1149 * @param ch the handle to CORE. Can be NULL if it is not requested
1150 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1151 * @param ac the handle to ATS. Can be NULL if it is not requested
1152 * @param my_identity the identity of our peer
1155 occ_cache_get_handle_core_cb (void *cls,
1156 struct GNUNET_CORE_Handle *ch,
1157 struct GNUNET_TRANSPORT_CoreHandle *th,
1158 struct GNUNET_ATS_ConnectivityHandle *ac,
1159 const struct GNUNET_PeerIdentity *my_identity,
1160 const struct GNUNET_CONFIGURATION_Handle *cfg)
1162 struct OverlayConnectContext *occ = cls;
1163 const struct GNUNET_MessageHeader *hello;
1165 GNUNET_assert (NULL != occ->timeout_task);
1166 GNUNET_free_non_null (occ->emsg);
1167 if ((NULL == ch) || (NULL == my_identity))
1169 GNUNET_asprintf (&occ->emsg,
1170 "0x%llx: Failed to connect to CORE of peer with "
1174 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1176 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1181 GNUNET_CORE_get_mq (ch,
1182 &occ->other_peer_identity))
1184 LOG_DEBUG ("0x%llx: Target peer already connected\n",
1186 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1187 occ->timeout_task = NULL;
1188 send_overlay_connect_success_msg (occ);
1189 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
1192 occ->peer_identity = *my_identity;
1193 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n",
1195 GNUNET_i2s (&occ->peer_identity));
1196 /* Lookup for HELLO in hello cache */
1197 if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
1199 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n",
1201 GNUNET_i2s (&occ->peer_identity));
1202 occ->hello = GNUNET_copy_message (hello);
1203 p2_transport_connect (occ);
1206 GNUNET_asprintf (&occ->emsg,
1207 "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
1209 GNUNET_i2s (&occ->peer_identity));
1211 GST_connection_pool_get_handle (occ->peer->id,
1212 occ->peer->details.local.cfg,
1213 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1214 p1_transport_connect_cache_callback,
1221 * Callback to be called when forwarded get peer config operation as part of
1222 * overlay connect is successfull. Connection to Peer 1's core is made and is
1223 * checked for new connection from peer 2
1225 * @param cls ForwardedOperationContext
1226 * @param msg the peer create success message
1229 overlay_connect_get_config (void *cls,
1230 const struct GNUNET_MessageHeader *msg)
1232 struct OverlayConnectContext *occ = cls;
1233 struct RemotePeer2Context *rp2c;
1234 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
1236 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1237 rp2c = &occ->p2ctx.remote;
1239 GNUNET_assert (NULL != occ->timeout_task);
1240 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
1242 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1244 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1247 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1248 occ->other_peer_identity = cmsg->peer_identity;
1249 GNUNET_free_non_null (occ->emsg);
1250 GNUNET_asprintf (&occ->emsg,
1251 "0x%llx: Timeout while connecting to CORE of peer with "
1256 GST_connection_pool_get_handle (occ->peer->id,
1257 occ->peer->details.local.cfg,
1258 GST_CONNECTIONPOOL_SERVICE_CORE,
1259 occ_cache_get_handle_core_cb,
1261 &occ->other_peer_identity,
1262 &overlay_connect_notify,
1269 * Callback which will be called after a host registration succeeded or failed
1271 * @param cls the RegisteredHostContext
1272 * @param emsg the error message; NULL if host registration is successful
1275 host_registration_comp (void *cls, const char *emsg)
1277 struct RegisteredHostContext *rhc = cls;
1279 rhc->state = RHC_DONE;
1280 GST_process_next_focc (rhc);
1285 * Iterator to match a registered host context
1287 * @param cls pointer 2 pointer of RegisteredHostContext
1288 * @param key current key code
1289 * @param value value in the hash map
1290 * @return #GNUNET_YES if we should continue to
1292 * #GNUNET_NO if not.
1295 reghost_match_iterator (void *cls,
1296 const struct GNUNET_HashCode *key,
1299 struct RegisteredHostContext **rh = cls;
1300 struct RegisteredHostContext *rh_val = value;
1302 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1313 * Function to generate the hashcode corresponding to a RegisteredHostContext
1315 * @param reg_host the host which is being registered in RegisteredHostContext
1316 * @param host the host of the controller which has to connect to the above rhost
1317 * @return the hashcode
1319 static struct GNUNET_HashCode
1320 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1321 struct GNUNET_TESTBED_Host *host)
1323 struct GNUNET_HashCode hash;
1324 uint32_t host_ids[2];
1326 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1327 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1328 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1334 * Checks if the given host is registered at the given slave.
1336 * @param slave the slave where registration has to be checked. The check is
1337 * actually done through a locally maintained hashmap. No
1338 * communication with the slave is involved.
1339 * @param host the host to register
1340 * @return If the given host is not registered already or the registration is
1341 * pending, it returns the registration context. Any overlay connects
1342 * to be forwarded should be queued in the context so that they can be
1343 * executed when the registration is completed. If the given host is
1344 * already registered, NULL is returned.
1346 static struct RegisteredHostContext *
1347 register_host (struct Slave *slave,
1348 struct GNUNET_TESTBED_Host *host)
1350 struct GNUNET_HashCode hash;
1351 struct RegisteredHostContext *rhc;
1353 rhc = GNUNET_new (struct RegisteredHostContext);
1354 rhc->reg_host = host;
1355 rhc->host = GST_host_list[slave->host_id];
1356 GNUNET_assert (NULL != rhc->reg_host);
1357 GNUNET_assert (NULL != rhc->host);
1358 rhc->state = RHC_INIT;
1359 hash = hash_hosts (rhc->reg_host, rhc->host);
1361 GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map,
1364 GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
1366 reghost_match_iterator,
1369 /* create and add a new registerd host context */
1370 /* add the focc to its queue */
1371 GNUNET_CONTAINER_multihashmap_put (slave->reghost_map,
1374 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1375 GST_queue_host_registration (slave,
1376 host_registration_comp,
1382 /* rhc is now set to the existing one from the hash map by
1383 * reghost_match_iterator() */
1384 /* if queue is empty then ignore creating focc and proceed with normal
1386 if (RHC_DONE == rhc->state)
1394 * Forwards the overlay connect request to a slave controller. Before
1395 * forwarding, any hosts which are needed to be known by the slave controller to
1396 * execute the overlay connect request are registered at slave.
1398 * @param msg the overlay connect request message to be forwarded
1399 * @param client the client to which the status of the forwarded request has to
1403 forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
1404 struct GNUNET_SERVICE_Client *client)
1406 struct ForwardedOperationContext *fopc;
1407 struct Route *route_to_peer2_host;
1408 struct Route *route_to_peer1_host;
1410 struct RegisteredHostContext *rhc;
1411 struct ForwardedOverlayConnectContext *focc;
1413 uint32_t peer2_host_id;
1417 p1 = ntohl (msg->peer1);
1418 p2 = ntohl (msg->peer2);
1419 op_id = GNUNET_ntohll (msg->operation_id);
1420 peer2_host_id = ntohl (msg->peer2_host_id);
1421 GNUNET_assert (VALID_PEER_ID (p1));
1422 GNUNET_assert (VALID_HOST_ID (peer2_host_id));
1423 peer = GST_peer_list[p1];
1424 GNUNET_assert (GNUNET_YES == peer->is_remote);
1425 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
1426 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1427 route_to_peer1_host = GST_find_dest_route
1428 (peer->details.remote.remote_host_id);
1429 GNUNET_assert (NULL != route_to_peer1_host);
1430 if ((NULL != route_to_peer2_host) &&
1431 (route_to_peer1_host->dest == route_to_peer2_host->dest))
1433 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1434 different subtrees OR peer2 is on a subtree unknown to us */
1435 if (NULL != (rhc = register_host (peer->details.remote.slave,
1436 GST_host_list[peer2_host_id])))
1438 LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, p2);
1439 focc = GNUNET_new (struct ForwardedOverlayConnectContext);
1443 focc->peer2_host_id = peer2_host_id;
1444 focc->orig_msg = GNUNET_copy_message (&msg->header);
1445 focc->operation_id = op_id;
1446 focc->client = client;
1447 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
1454 LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, p2);
1455 fopc = GNUNET_new (struct ForwardedOperationContext);
1456 fopc->client = client;
1457 fopc->operation_id = op_id;
1458 fopc->type = OP_OVERLAY_CONNECT;
1460 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1461 slave->controller, op_id,
1463 &GST_forwarded_operation_reply_relay,
1465 fopc->timeout_task =
1466 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1467 &GST_forwarded_operation_timeout,
1469 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
1476 * Callback called when a connection to the controller of peer2 has been
1479 * @param cls the overlay connect contexts
1480 * @param c handle to the controller connection
1483 p2_controller_connect_cb (void *cls,
1484 struct GNUNET_TESTBED_Controller *c)
1486 struct OverlayConnectContext *occ = cls;
1487 struct RemotePeer2Context *rp2c;
1488 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1490 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1491 rp2c = &occ->p2ctx.remote;
1495 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1497 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
1498 cmsg.peer_id = htonl (occ->other_peer_id);
1499 cmsg.operation_id = GNUNET_htonll (occ->op_id);
1501 GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
1504 &overlay_connect_get_config,
1506 GNUNET_free_non_null (occ->emsg);
1507 GNUNET_asprintf (&occ->emsg,
1508 "0x%llx: Timeout while getting peer identity of peer "
1511 occ->other_peer_id);
1516 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages
1518 * @param cls identification of the client
1519 * @param msg the actual message
1522 handle_overlay_connect (void *cls,
1523 const struct GNUNET_TESTBED_OverlayConnectMessage *msg)
1525 struct GNUNET_SERVICE_Client *client = cls;
1528 struct OverlayConnectContext *occ;
1529 struct Neighbour *p2n;
1530 uint64_t operation_id;
1533 uint32_t peer2_host_id;
1535 p1 = ntohl (msg->peer1);
1536 p2 = ntohl (msg->peer2);
1537 if (! VALID_PEER_ID (p1))
1540 GNUNET_SERVICE_client_drop (client);
1543 peer = GST_peer_list[p1];
1544 operation_id = GNUNET_ntohll (msg->operation_id);
1546 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n",
1550 peer2_host_id = ntohl (msg->peer2_host_id);
1551 if (GNUNET_YES == peer->is_remote)
1553 if (! VALID_HOST_ID (peer2_host_id))
1556 GNUNET_SERVICE_client_drop (client);
1559 forward_overlay_connect (msg, client);
1560 GNUNET_SERVICE_client_continue (client);
1564 occ = GNUNET_new (struct OverlayConnectContext);
1565 occ->type = OCC_TYPE_LOCAL;
1566 if (! VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */
1568 if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1570 if (! VALID_HOST_ID (peer2_host_id))
1573 LOG (GNUNET_ERROR_TYPE_WARNING,
1574 "0x%llx: Peer %u's host not in our neighbours list\n",
1576 GNUNET_SERVICE_client_drop (client);
1580 p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
1582 occ->type = OCC_TYPE_REMOTE_LATERAL;
1583 occ->p2ctx.remote.p2n = p2n;
1585 else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1587 occ->type = OCC_TYPE_REMOTE_SLAVE;
1588 occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
1590 GNUNET_CONTAINER_DLL_insert_tail (occq_head,
1593 occ->client = client;
1594 occ->other_peer_id = p2;
1595 GST_peer_list[p1]->reference_cnt++;
1596 occ->peer = GST_peer_list[p1];
1597 occ->op_id = operation_id;
1598 GNUNET_assert (NULL == occ->timeout_task);
1600 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1601 &timeout_overlay_connect,
1605 case OCC_TYPE_REMOTE_LATERAL:
1606 GNUNET_asprintf (&occ->emsg,
1607 "0x%llx: Timeout while acquiring connection to peer %u's "
1612 occ->p2ctx.remote.ncn
1613 = GST_neighbour_get_connection (p2n,
1614 &p2_controller_connect_cb,
1617 case OCC_TYPE_REMOTE_SLAVE:
1618 p2_controller_connect_cb (occ,
1619 occ->p2ctx.remote.p2c);
1621 case OCC_TYPE_LOCAL:
1622 peer2 = GST_peer_list[occ->other_peer_id];
1623 peer2->reference_cnt++;
1624 GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
1625 &occ->other_peer_identity);
1626 GNUNET_asprintf (&occ->emsg,
1627 "0x%llx: Timeout while connecting to CORE of peer with "
1632 GST_connection_pool_get_handle (occ->peer->id,
1633 occ->peer->details.local.cfg,
1634 GST_CONNECTIONPOOL_SERVICE_CORE,
1635 occ_cache_get_handle_core_cb, occ,
1636 &occ->other_peer_identity,
1637 &overlay_connect_notify, occ);
1640 GNUNET_SERVICE_client_continue (client);
1645 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1648 * @param rocc the RemoteOverlayConnectCtx
1651 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1653 LOG_DEBUG ("0x%llx: Cleaning up rocc\n",
1655 if (NULL != rocc->attempt_connect_task_id)
1656 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1657 if (NULL != rocc->timeout_rocc_task_id)
1658 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1659 if (NULL != rocc->ohh)
1660 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1661 if (NULL != rocc->tcc.csh)
1662 GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh);
1663 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th);
1664 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats);
1665 GNUNET_assert (rocc->peer->reference_cnt > 0);
1666 rocc->peer->reference_cnt--;
1667 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1668 (0 == rocc->peer->reference_cnt))
1669 GST_destroy_peer (rocc->peer);
1670 GNUNET_free_non_null (rocc->hello);
1671 GNUNET_CONTAINER_DLL_remove (roccq_head,
1679 * Task to timeout rocc and cleanit up
1681 * @param cls the RemoteOverlayConnectCtx
1684 timeout_rocc_task (void *cls)
1686 struct RemoteOverlayConnectCtx *rocc = cls;
1688 GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
1689 rocc->timeout_rocc_task_id = NULL;
1690 LOG_DEBUG ("0x%llx: rocc timed out\n",
1692 cleanup_rocc (rocc);
1697 * Function called to notify transport users that another
1698 * peer connected to us.
1700 * @param cls the RemoteOverlayConnectContext
1701 * @param new_peer the peer that connected
1704 cache_transport_peer_connect_notify (void *cls,
1705 const struct GNUNET_PeerIdentity *new_peer)
1707 struct RemoteOverlayConnectCtx *rocc = cls;
1709 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n",
1712 memcmp (new_peer, &rocc->a_id,
1713 sizeof (struct GNUNET_PeerIdentity)));
1714 LOG_DEBUG ("0x%llx: Peer %s connected\n",
1716 GNUNET_i2s (&rocc->a_id));
1717 cleanup_rocc (rocc);
1722 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1723 * whose identity is in RemoteOverlayConnectCtx
1725 * @param cls the RemoteOverlayConnectCtx
1728 attempt_connect_task (void *cls);
1732 * Task that is run when hello has been sent If tc->reason =
1733 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1734 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1736 * @param cls the overlay connect context
1739 rocc_hello_sent_cb (void *cls)
1741 struct RemoteOverlayConnectCtx *rocc = cls;
1744 GNUNET_assert (NULL == rocc->attempt_connect_task_id);
1745 LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n",
1747 GNUNET_i2s (&rocc->a_id),
1749 rocc->tcc.cgh_p2_ats =
1750 GST_connection_pool_get_handle (rocc->peer->id,
1751 rocc->peer->details.local.cfg,
1752 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
1753 &occ_cache_get_handle_ats_rocc_cb,
1754 rocc, NULL, NULL, NULL);
1759 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1760 * whose identity is in RemoteOverlayConnectCtx
1762 * @param cls the RemoteOverlayConnectCtx
1765 attempt_connect_task (void *cls)
1767 struct RemoteOverlayConnectCtx *rocc = cls;
1769 GNUNET_assert (NULL != rocc->attempt_connect_task_id);
1770 rocc->attempt_connect_task_id = NULL;
1771 LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n",
1773 GNUNET_i2s (&rocc->a_id),
1776 GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg,
1778 &rocc_hello_sent_cb,
1780 if (NULL == rocc->ohh)
1781 rocc->attempt_connect_task_id =
1782 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1783 (GNUNET_TIME_UNIT_MILLISECONDS,
1785 GNUNET_CRYPTO_random_u32
1786 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1787 &attempt_connect_task, rocc);
1792 * Callback from cache with needed handles set
1794 * @param cls the closure passed to GST_cache_get_handle_transport()
1795 * @param ch the handle to CORE. Can be NULL if it is not requested
1796 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1797 * @param ac the handle to ATS. Can be NULL if it is not requested
1798 * @param ignore_ peer identity which is ignored in this callback
1801 rocc_cache_get_handle_transport_cb (void *cls,
1802 struct GNUNET_CORE_Handle *ch,
1803 struct GNUNET_TRANSPORT_CoreHandle *th,
1804 struct GNUNET_ATS_ConnectivityHandle *ac,
1805 const struct GNUNET_PeerIdentity *ignore_,
1806 const struct GNUNET_CONFIGURATION_Handle *cfg)
1808 struct RemoteOverlayConnectCtx *rocc = cls;
1812 rocc->timeout_rocc_task_id =
1813 GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1817 rocc->tcc.cfg = cfg;
1819 GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_,
1822 LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n",
1824 GNUNET_i2s (&rocc->a_id),
1826 cleanup_rocc (rocc);
1829 rocc->attempt_connect_task_id =
1830 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1835 * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
1837 * @param cls identification of the client
1838 * @param msg the actual message
1839 * @return #GNUNET_OK if @a msg is well-formed
1842 check_remote_overlay_connect (void *cls,
1843 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
1849 msize = ntohs (msg->header.size);
1850 if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))
1853 return GNUNET_SYSERR;
1855 hsize = ntohs (msg->hello->size);
1856 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) != msize)
1859 return GNUNET_SYSERR;
1861 peer_id = ntohl (msg->peer);
1862 if ((peer_id >= GST_peer_list_size) ||
1863 (NULL == GST_peer_list[peer_id]))
1865 GNUNET_break_op (0);
1866 return GNUNET_SYSERR;
1873 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
1875 * @param cls identification of the client
1876 * @param msg the actual message
1879 handle_remote_overlay_connect (void *cls,
1880 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
1882 struct GNUNET_SERVICE_Client *client = cls;
1883 struct RemoteOverlayConnectCtx *rocc;
1885 struct GNUNET_PeerIdentity pid;
1886 static char pid_str[16];
1890 hsize = ntohs (msg->hello->size);
1891 peer_id = ntohl (msg->peer);
1892 peer = GST_peer_list[peer_id];
1893 if (GNUNET_YES == peer->is_remote)
1895 struct GNUNET_MessageHeader *msg2;
1897 msg2 = GNUNET_copy_message (&msg->header);
1898 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1900 GNUNET_SERVICE_client_continue (client);
1903 rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
1904 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1905 GNUNET_CONTAINER_DLL_insert_tail (roccq_head,
1908 rocc->a_id = msg->peer_identity;
1909 GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
1911 (void) GNUNET_strlcpy (pid_str,
1914 LOG_DEBUG ("0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n",
1917 GNUNET_i2s (&rocc->a_id),
1920 rocc->peer->reference_cnt++;
1921 rocc->hello = GNUNET_malloc (hsize);
1922 GNUNET_memcpy (rocc->hello,
1925 rocc->tcc.cgh_p2_th =
1926 GST_connection_pool_get_handle (peer_id,
1927 rocc->peer->details.local.cfg,
1928 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1929 &rocc_cache_get_handle_transport_cb,
1932 &cache_transport_peer_connect_notify,
1934 rocc->timeout_rocc_task_id =
1935 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1938 GNUNET_SERVICE_client_continue (client);
1943 * Clears all pending overlay connect contexts in queue
1948 struct OverlayConnectContext *occ;
1950 while (NULL != (occ = occq_head))
1956 * Clears all pending remote overlay connect contexts in queue
1961 struct RemoteOverlayConnectCtx *rocc;
1963 while (NULL != (rocc = roccq_head))
1964 cleanup_rocc (rocc);