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.
17 * @file testbed/gnunet-service-testbed_oc.c
18 * @brief code for handling overlay connect operations
19 * @author Sree Harsha Totakura
22 #include "gnunet-service-testbed.h"
23 #include "gnunet-service-testbed_connectionpool.h"
24 #include "gnunet_transport_hello_service.h"
27 * Redefine LOG with a changed log component string
32 #define LOG(kind,...) \
33 GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__)
37 * Context information for requesting ATS to connect to a peer
39 struct ConnectivitySuggestContext
43 * The transport handle obtained from cache. Do NOT close/disconnect.
45 struct GNUNET_TRANSPORT_CoreHandle *th_;
48 * Configuration of the peer from cache. Do not free!
50 const struct GNUNET_CONFIGURATION_Handle *cfg;
53 * The GetCacheHandle for the peer2's transport handle
54 * (used to offer the HELLO to the peer).
56 struct GST_ConnectionPool_GetHandle *cgh_p2_th;
59 * The GetCacheHandle for the peer2's ATS handle.
61 struct GST_ConnectionPool_GetHandle *cgh_p2_ats;
64 * The ATS handle for the connectivity suggestion.
66 struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
72 * Types for context information we create for overlay connect requests
74 enum OverlayConnectContextType
77 * This type is used if the overlay connection is local i.e. the connection
78 * has to be made between local peers
83 * Type to be used when the first peer is local and the other peer is on a slave
84 * controller started by us
86 OCC_TYPE_REMOTE_SLAVE,
89 * Type to be used when the first peer is local and the other peer is on a
90 * controller which is not started by us.
92 OCC_TYPE_REMOTE_LATERAL
97 * Context data for operations on second peer in local overlay connection
100 struct LocalPeer2Context
103 * The handle for offering the HELLO of the first peer to the second
106 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
109 * The transport ConnectivitySuggestContext
111 struct ConnectivitySuggestContext tcc;
116 * Context data for operations on second peer in remote overlay connection
119 struct RemotePeer2Context
122 * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay
123 * connection then this can be NULL until the connection to the controller is
126 struct GNUNET_TESTBED_Controller *p2c;
129 * Operation context for the suboperation we start to get the identity of the
132 struct OperationContext *opc;
135 * Notification handle acquire to connect to a remote controller. Only used
136 * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL.
138 struct NeighbourConnectNotification *ncn;
141 * The neighbour handle. Only used if the type of overlay connection is
142 * #OCC_TYPE_REMOTE_LATERAL.
144 struct Neighbour *p2n;
148 * Context information for connecting 2 peers in overlay.
150 struct OverlayConnectContext
153 * The next pointer for maintaining a DLL of all OverlayConnectContexts
155 struct OverlayConnectContext *next;
158 * The prev pointer for maintaining a DLL of all OverlayConnectContexts
160 struct OverlayConnectContext *prev;
163 * The client which has requested for overlay connection. This is used to send
164 * either a success of failure message
166 struct GNUNET_SERVICE_Client *client;
169 * the first peer which is to expect an overlay connection from the second peer.
174 * Transport handle of the first peer obtained from cache to get its HELLO. Do
175 * NOT close/disconnect.
177 struct GNUNET_TRANSPORT_CoreHandle *p1th_;
180 * The #GST_ConnectionPool_GetHandle for the peer1's transport handle
182 struct GST_ConnectionPool_GetHandle *cgh_p1th;
185 * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE
186 * level peer connects and to get our identity.
188 struct GST_ConnectionPool_GetHandle *cgh_ch;
191 * HELLO of the first peer. This should be sent to the second peer.
193 struct GNUNET_MessageHeader *hello;
196 * Get GetHelloHandle to acquire a HELLO of the first peer
198 struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
201 * The error message we send if this overlay connect operation has timed out
206 * Context information for operations on the second peer
211 * Context information to be used if the second peer is local
213 struct LocalPeer2Context local;
216 * Context information to be used if the second peer is remote
218 struct RemotePeer2Context remote;
223 * The peer identity of the first peer
225 struct GNUNET_PeerIdentity peer_identity;
228 * The peer identity of the other peer
230 struct GNUNET_PeerIdentity other_peer_identity;
233 * The id of the operation responsible for creating this context
238 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
241 struct GNUNET_SCHEDULER_Task *send_hello_task;
244 * The id of the overlay connect timeout task
246 struct GNUNET_SCHEDULER_Task *timeout_task;
249 * The id of the cleanup task
251 struct GNUNET_SCHEDULER_Task *cleanup_task;
254 * The type of this context information
256 enum OverlayConnectContextType type;
259 * The id of the second peer which has to connect to the first peer
261 uint32_t other_peer_id;
266 * Context information for remote overlay connect operations. Remote overlay
267 * connections are used when peers A and B reside on different hosts. In these
268 * operations the host controller for peer B is asked by the host controller of
269 * peer A to make peer B connect to peer A by sending the controller of peer B
270 * the HELLO of peer A.
272 struct RemoteOverlayConnectCtx
275 * the next pointer for DLL
277 struct RemoteOverlayConnectCtx *next;
280 * the prev pointer for DLL
282 struct RemoteOverlayConnectCtx *prev;
285 * The peer handle of peer B
292 struct GNUNET_MessageHeader *hello;
295 * The handle for offering HELLO
297 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
300 * The transport try connect context
302 struct ConnectivitySuggestContext tcc;
305 * The peer identity of peer A
307 struct GNUNET_PeerIdentity a_id;
310 * Task for offering HELLO of A to B and doing try_connect
312 struct GNUNET_SCHEDULER_Task *attempt_connect_task_id;
315 * Task to timeout RequestOverlayConnect
317 struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id;
320 * The id of the operation responsible for creating this context
327 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
329 static struct OverlayConnectContext *occq_head;
332 * DLL tail for OverlayConnectContext DLL
334 static struct OverlayConnectContext *occq_tail;
337 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
340 static struct RemoteOverlayConnectCtx *roccq_head;
343 * DLL tail for RequectOverlayConnectContext DLL
345 static struct RemoteOverlayConnectCtx *roccq_tail;
349 * Cleans up ForwardedOverlayConnectContext
351 * @param focc the ForwardedOverlayConnectContext to cleanup
354 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
356 struct RegisteredHostContext *rhc = focc->rhc;
358 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head,
361 GNUNET_free_non_null (focc->orig_msg);
367 * Timeout task for cancelling a forwarded overlay connect connect
369 * @param cls the `struct ForwardedOperationContext`
372 forwarded_overlay_connect_timeout (void *cls)
374 struct ForwardedOperationContext *fopc = cls;
375 struct RegisteredHostContext *rhc;
376 struct ForwardedOverlayConnectContext *focc;
378 fopc->timeout_task = NULL;
380 focc = rhc->focc_dll_head;
381 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n",
384 GST_cleanup_focc (focc);
385 GST_forwarded_operation_timeout (fopc);
386 if (NULL != rhc->focc_dll_head)
387 GST_process_next_focc (rhc);
392 * Callback to be called when forwarded overlay connection operation has a reply
393 * from the sub-controller successfull. We have to relay the reply msg back to
396 * @param cls ForwardedOperationContext
397 * @param msg the peer create success message
400 forwarded_overlay_connect_listener (void *cls,
401 const struct GNUNET_MessageHeader *msg)
403 struct ForwardedOperationContext *fopc = cls;
404 struct RegisteredHostContext *rhc;
405 struct ForwardedOverlayConnectContext *focc;
408 GST_forwarded_operation_reply_relay (cls, msg);
409 focc = rhc->focc_dll_head;
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 fopc->client = focc->client;
438 fopc->operation_id = focc->operation_id;
440 fopc->type = OP_OVERLAY_CONNECT;
442 GNUNET_TESTBED_forward_operation_msg_ (slave->controller,
445 &forwarded_overlay_connect_listener,
447 GNUNET_free (focc->orig_msg);
448 focc->orig_msg = NULL;
449 fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout,
450 &forwarded_overlay_connect_timeout,
452 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
459 * Cleans up any used handles in local peer2 context
461 * @param lp2c the local peer2 context information
464 cleanup_occ_lp2c (struct LocalPeer2Context *lp2c)
466 if (NULL != lp2c->ohh)
468 GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh);
471 if (NULL != lp2c->tcc.cgh_p2_th)
473 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th);
474 lp2c->tcc.cgh_p2_th = NULL;
476 if (NULL != lp2c->tcc.cgh_p2_ats)
478 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats);
479 lp2c->tcc.cgh_p2_ats = NULL;
481 if (NULL != lp2c->tcc.csh)
483 GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh);
484 lp2c->tcc.csh = NULL;
490 * Cleans up any used handles in remote peer2 context. Relinquishes the
491 * remote controller connection if it has been established on-demand.
493 * @param rp2c the remote peer2 context information
496 cleanup_occ_rp2c (struct RemotePeer2Context *rp2c)
498 if (NULL != rp2c->opc)
500 GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc);
503 if (NULL != rp2c->ncn)
505 GST_neighbour_get_connection_cancel (rp2c->ncn);
508 if ( (NULL != rp2c->p2c) && (NULL != rp2c->p2n) )
510 GST_neighbour_release_connection (rp2c->p2n);
516 * Condition for checking if given peer is ready to be destroyed
518 * @param peer the peer to check
520 #define PEER_EXPIRED(peer) \
521 ( (GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt) )
524 * Cleanup overlay connect context structure
526 * @param occ the overlay connect context
529 cleanup_occ (struct OverlayConnectContext *occ)
533 LOG_DEBUG ("0x%llx: Cleaning up occ\n",
535 GNUNET_free_non_null (occ->emsg);
536 GNUNET_free_non_null (occ->hello);
537 if (NULL != occ->send_hello_task)
538 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
539 if (NULL != occ->cleanup_task)
540 GNUNET_SCHEDULER_cancel (occ->cleanup_task);
541 if (NULL != occ->timeout_task)
542 GNUNET_SCHEDULER_cancel (occ->timeout_task);
543 if (NULL != occ->cgh_ch)
544 GST_connection_pool_get_handle_done (occ->cgh_ch);
545 if (NULL != occ->ghh)
546 GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
547 GST_connection_pool_get_handle_done (occ->cgh_p1th);
548 GNUNET_assert (NULL != GST_peer_list);
549 GNUNET_assert (occ->peer->reference_cnt > 0);
550 occ->peer->reference_cnt--;
551 if (PEER_EXPIRED (occ->peer))
552 GST_destroy_peer (occ->peer);
556 peer2 = GST_peer_list[occ->other_peer_id];
557 GNUNET_assert (peer2->reference_cnt > 0);
558 peer2->reference_cnt--;
559 if (PEER_EXPIRED (peer2))
560 GST_destroy_peer (peer2);
561 cleanup_occ_lp2c (&occ->p2ctx.local);
563 case OCC_TYPE_REMOTE_SLAVE:
564 case OCC_TYPE_REMOTE_LATERAL:
565 cleanup_occ_rp2c (&occ->p2ctx.remote);
568 GNUNET_CONTAINER_DLL_remove (occq_head,
576 * Task for cleaing up overlay connect context structure
578 * @param cls the overlay connect context
581 do_cleanup_occ (void *cls)
583 struct OverlayConnectContext *occ = cls;
585 occ->cleanup_task = NULL;
591 * Task which will be run when overlay connect request has been timed out
593 * @param cls the OverlayConnectContext
596 timeout_overlay_connect (void *cls)
598 struct OverlayConnectContext *occ = cls;
600 GNUNET_assert (NULL != occ->timeout_task);
601 occ->timeout_task = NULL;
602 /* LOG (GNUNET_ERROR_TYPE_WARNING, */
603 /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
604 /* occ->peer->id, occ->other_peer_id, occ->emsg); */
605 GST_send_operation_fail_msg (occ->client,
613 * Notify OC subsystem that @a client disconnected.
615 * @param client the client that disconnected
618 GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client)
620 struct ForwardedOperationContext *fopc;
621 struct ForwardedOperationContext *fopcn;
622 struct OverlayConnectContext *occ;
623 struct OverlayConnectContext *occn;
625 for (fopc = fopcq_head; NULL != fopc; fopc = fopcn)
628 if (fopc->client == client)
630 GNUNET_SCHEDULER_cancel (fopc->timeout_task);
631 GST_forwarded_operation_timeout (fopc);
634 for (occ = occq_head; NULL != occ; occ = occn)
637 if (occ->client == client)
640 // FIXME: implement clean up for client_keep replacements!
650 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
652 struct GNUNET_MQ_Envelope *env;
653 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
655 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
657 env = GNUNET_MQ_msg (msg,
658 GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
659 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
660 msg->peer1 = htonl (occ->peer->id);
661 msg->peer2 = htonl (occ->other_peer_id);
662 msg->operation_id = GNUNET_htonll (occ->op_id);
663 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (occ->client),
669 * Function called to notify transport users that another
670 * peer connected to us.
673 * @param new_peer the peer that connected
676 overlay_connect_notify (void *cls,
677 const struct GNUNET_PeerIdentity *new_peer)
679 struct OverlayConnectContext *occ = cls;
681 char *other_peer_str;
683 LOG_DEBUG ("Overlay connect notify\n");
685 memcmp (new_peer, &occ->peer_identity,
686 sizeof (struct GNUNET_PeerIdentity)))
688 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
689 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
692 &occ->other_peer_identity,
693 sizeof (struct GNUNET_PeerIdentity)))
695 LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n",
698 GNUNET_free (new_peer_str);
699 GNUNET_free (other_peer_str);
702 GNUNET_free (new_peer_str);
703 LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n",
706 GNUNET_i2s (&occ->peer_identity));
707 GNUNET_free (other_peer_str);
708 if (NULL != occ->send_hello_task)
710 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
711 occ->send_hello_task = NULL;
713 GNUNET_assert (NULL != occ->timeout_task);
714 GNUNET_SCHEDULER_cancel (occ->timeout_task);
715 occ->timeout_task = NULL;
719 cleanup_occ_lp2c (&occ->p2ctx.local);
721 case OCC_TYPE_REMOTE_SLAVE:
722 case OCC_TYPE_REMOTE_LATERAL:
723 cleanup_occ_rp2c (&occ->p2ctx.remote);
726 GNUNET_free_non_null (occ->emsg);
728 send_overlay_connect_success_msg (occ);
729 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ,
735 * Callback from cache with needed ATS handle set
737 * @param cls a `struct OverlayConnectCtx *`
738 * @param ch the handle to CORE. Can be NULL if it is not requested
739 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
740 * @param ac the handle to ATS. Can be NULL if it is not requested
741 * @param my_identity the identity of our peer
742 * @param cfg configuration of the peer
745 occ_cache_get_handle_ats_occ_cb (void *cls,
746 struct GNUNET_CORE_Handle *ch,
747 struct GNUNET_TRANSPORT_CoreHandle *th,
748 struct GNUNET_ATS_ConnectivityHandle *ac,
749 const struct GNUNET_PeerIdentity *my_identity,
750 const struct GNUNET_CONFIGURATION_Handle *cfg)
752 struct OverlayConnectContext *occ = cls;
753 struct LocalPeer2Context *lp2c;
755 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
756 GNUNET_assert (NULL != occ->timeout_task);
757 GNUNET_free_non_null (occ->emsg);
760 GNUNET_asprintf (&occ->emsg,
761 "0x%llx: Failed to connect to ATS of peer with id: %u",
764 GNUNET_SCHEDULER_cancel (occ->timeout_task);
766 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect,
772 GNUNET_asprintf (&occ->emsg,
773 "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s",
775 GNUNET_i2s (&occ->other_peer_identity));
777 lp2c = &occ->p2ctx.local;
779 GNUNET_ATS_connectivity_suggest (ac,
786 * Callback from cache with needed ATS handle set
788 * @param cls a `struct RemoteOverlayConnectCtx *`
789 * @param ch the handle to CORE. Can be NULL if it is not requested
790 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
791 * @param ac the handle to ATS. Can be NULL if it is not requested
792 * @param my_identity the identity of our peer
795 occ_cache_get_handle_ats_rocc_cb (void *cls,
796 struct GNUNET_CORE_Handle *ch,
797 struct GNUNET_TRANSPORT_CoreHandle *th,
798 struct GNUNET_ATS_ConnectivityHandle *ac,
799 const struct GNUNET_PeerIdentity *my_identity,
800 const struct GNUNET_CONFIGURATION_Handle *cfg)
802 struct RemoteOverlayConnectCtx *rocc = cls;
805 GNUNET_ATS_connectivity_suggest (ac,
812 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
815 * @param cls the OverlayConnectContext
818 send_hello (void *cls);
822 * Task that is run when hello has been sent If tc->reason =
823 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
824 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
826 * @param cls the overlay connect context
829 occ_hello_sent_cb (void *cls)
831 struct OverlayConnectContext *occ = cls;
832 struct LocalPeer2Context *lp2c;
835 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
836 GNUNET_assert (NULL != occ->timeout_task);
837 lp2c = &occ->p2ctx.local;
840 GNUNET_assert (NULL == occ->send_hello_task);
841 GNUNET_free_non_null (occ->emsg);
843 GNUNET_asprintf (&occ->emsg,
844 "0x%llx: Timeout while acquiring ATS of %s from cache",
846 GNUNET_i2s (&occ->other_peer_identity));
847 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
848 lp2c->tcc.cgh_p2_ats =
849 GST_connection_pool_get_handle (occ->other_peer_id,
850 peer2->details.local.cfg,
851 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
852 &occ_cache_get_handle_ats_occ_cb,
853 occ, NULL, NULL, NULL);
858 * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
861 * @param occ the overlay connect context. Its type must be either
862 * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL
865 send_hello_thru_rocc (struct OverlayConnectContext *occ)
867 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
868 char *other_peer_str;
872 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
873 GNUNET_assert (NULL != occ->hello);
874 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
875 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n",
877 GNUNET_i2s (&occ->peer_identity),
878 ntohs (occ->hello->size),
880 GNUNET_free (other_peer_str);
881 hello_size = ntohs (occ->hello->size);
882 msize = sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
883 msg = GNUNET_malloc (msize);
885 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
886 msg->header.size = htons (msize);
887 msg->peer = htonl (occ->other_peer_id);
888 msg->operation_id = GNUNET_htonll (occ->op_id);
889 msg->peer_identity = occ->peer_identity;
890 GNUNET_memcpy (msg->hello,
893 GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c,
899 * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered
900 * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
901 * send_hello_thru_rocc()
903 * @param cls the OverlayConnectContext
906 send_hello (void *cls)
908 struct OverlayConnectContext *occ = cls;
909 struct LocalPeer2Context *lp2c;
910 char *other_peer_str;
912 occ->send_hello_task = NULL;
913 GNUNET_assert (NULL != occ->timeout_task);
914 GNUNET_assert (NULL != occ->hello);
915 if (OCC_TYPE_LOCAL != occ->type)
917 send_hello_thru_rocc (occ);
920 lp2c = &occ->p2ctx.local;
921 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
922 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n",
924 GNUNET_i2s (&occ->peer_identity),
926 GNUNET_free (other_peer_str);
928 GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg,
932 if (NULL == lp2c->ohh)
935 occ->send_hello_task =
936 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
937 (GNUNET_TIME_UNIT_MILLISECONDS,
939 GNUNET_CRYPTO_random_u32
940 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
947 * Callback from cache with needed handles set
949 * @param cls the closure passed to GST_cache_get_handle_transport()
950 * @param ch the handle to CORE. Can be NULL if it is not requested
951 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
952 * @param ac the handle to ATS. Can be NULL if it is not requested
953 * @param ignore_ peer identity which is ignored in this callback
954 * @param cfg configuration of the peer
957 p2_transport_connect_cache_callback (void *cls,
958 struct GNUNET_CORE_Handle *ch,
959 struct GNUNET_TRANSPORT_CoreHandle *th,
960 struct GNUNET_ATS_ConnectivityHandle *ac,
961 const struct GNUNET_PeerIdentity *ignore_,
962 const struct GNUNET_CONFIGURATION_Handle *cfg)
964 struct OverlayConnectContext *occ = cls;
966 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
969 GNUNET_asprintf (&occ->emsg,
970 "0x%llx: Cannot connect to TRANSPORT of %s",
972 GNUNET_i2s (&occ->other_peer_identity));
973 GNUNET_SCHEDULER_cancel (occ->timeout_task);
975 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
978 occ->p2ctx.local.tcc.th_ = th;
979 occ->p2ctx.local.tcc.cfg = cfg;
980 GNUNET_asprintf (&occ->emsg,
981 "0x%llx: Timeout while offering HELLO to %s",
983 GNUNET_i2s (&occ->other_peer_identity));
984 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
989 * Connects to the transport of the other peer if it is a local peer and
990 * schedules the send hello task
992 * @param occ the overlay connect context
995 p2_transport_connect (struct OverlayConnectContext *occ)
999 /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the
1001 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1002 "Connecting to transport of peer %s to obtain HELLO\n",
1003 GNUNET_i2s (&occ->other_peer_identity));
1004 GNUNET_assert (NULL == occ->emsg);
1005 GNUNET_assert (NULL != occ->hello);
1006 GNUNET_assert (NULL == occ->ghh);
1007 GNUNET_assert (NULL == occ->p1th_);
1008 GNUNET_assert (NULL == occ->cgh_p1th);
1009 if (OCC_TYPE_LOCAL == occ->type)
1011 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
1012 occ->p2ctx.local.tcc.cgh_p2_th =
1013 GST_connection_pool_get_handle (occ->other_peer_id,
1014 peer2->details.local.cfg,
1015 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1016 &p2_transport_connect_cache_callback,
1017 occ, NULL, NULL, NULL);
1020 GNUNET_asprintf (&occ->emsg,
1021 "0x%llx: Timeout while offering HELLO to %s",
1023 GNUNET_i2s (&occ->other_peer_identity));
1024 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
1029 * Test for checking whether HELLO message is empty
1031 * @param cls empty flag to set
1032 * @param address the HELLO
1033 * @param expiration expiration of the HELLO
1034 * @return #GNUNET_OK
1037 test_address (void *cls,
1038 const struct GNUNET_HELLO_Address *address,
1039 struct GNUNET_TIME_Absolute expiration)
1049 * Function called whenever there is an update to the HELLO of peers in the
1050 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
1051 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
1053 * @param cls closure
1054 * @param hello our updated HELLO
1057 hello_update_cb (void *cls,
1058 const struct GNUNET_MessageHeader *hello)
1060 struct OverlayConnectContext *occ = cls;
1064 msize = ntohs (hello->size);
1066 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
1070 if (GNUNET_YES == empty)
1072 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n",
1074 GNUNET_i2s (&occ->peer_identity));
1077 LOG_DEBUG ("0x%llx: Received HELLO of %s\n",
1079 GNUNET_i2s (&occ->peer_identity));
1080 occ->hello = GNUNET_malloc (msize);
1081 GST_cache_add_hello (occ->peer->id, hello);
1082 GNUNET_memcpy (occ->hello, hello, msize);
1083 GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
1085 GST_connection_pool_get_handle_done (occ->cgh_p1th);
1086 occ->cgh_p1th = NULL;
1088 GNUNET_free_non_null (occ->emsg);
1090 p2_transport_connect (occ);
1095 * Callback from cache with needed handles set
1097 * @param cls the closure passed to GST_cache_get_handle_transport()
1098 * @param ch the handle to CORE. Can be NULL if it is not requested
1099 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1100 * @param ac the handle to ATS. Can be NULL if it is not requested
1101 * @param ignore_ peer identity which is ignored in this callback
1104 p1_transport_connect_cache_callback (void *cls,
1105 struct GNUNET_CORE_Handle *ch,
1106 struct GNUNET_TRANSPORT_CoreHandle *th,
1107 struct GNUNET_ATS_ConnectivityHandle *ac,
1108 const struct GNUNET_PeerIdentity *ignore_,
1109 const struct GNUNET_CONFIGURATION_Handle *cfg)
1111 struct OverlayConnectContext *occ = cls;
1113 GNUNET_free_non_null (occ->emsg);
1117 GNUNET_asprintf (&occ->emsg,
1118 "0x%llx: Cannot connect to TRANSPORT of %s",
1120 GNUNET_i2s (&occ->peer_identity));
1121 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1123 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1126 GNUNET_assert (NULL == occ->p1th_);
1127 GNUNET_assert (NULL != occ->cgh_p1th);
1129 GNUNET_asprintf (&occ->emsg,
1130 "0x%llx: Timeout while acquiring HELLO of peer %s",
1132 GNUNET_i2s (&occ->peer_identity));
1133 occ->ghh = GNUNET_TRANSPORT_hello_get (cfg,
1134 GNUNET_TRANSPORT_AC_ANY,
1141 * Callback from cache with needed CORE handle set
1143 * @param cls the closure passed to GST_cache_get_handle_transport()
1144 * @param ch the handle to CORE. Can be NULL if it is not requested
1145 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1146 * @param ac the handle to ATS. Can be NULL if it is not requested
1147 * @param my_identity the identity of our peer
1150 occ_cache_get_handle_core_cb (void *cls,
1151 struct GNUNET_CORE_Handle *ch,
1152 struct GNUNET_TRANSPORT_CoreHandle *th,
1153 struct GNUNET_ATS_ConnectivityHandle *ac,
1154 const struct GNUNET_PeerIdentity *my_identity,
1155 const struct GNUNET_CONFIGURATION_Handle *cfg)
1157 struct OverlayConnectContext *occ = cls;
1158 const struct GNUNET_MessageHeader *hello;
1160 GNUNET_assert (NULL != occ->timeout_task);
1161 GNUNET_free_non_null (occ->emsg);
1162 if ((NULL == ch) || (NULL == my_identity))
1164 GNUNET_asprintf (&occ->emsg,
1165 "0x%llx: Failed to connect to CORE of peer with "
1169 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1171 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1176 GNUNET_CORE_get_mq (ch,
1177 &occ->other_peer_identity))
1179 LOG_DEBUG ("0x%llx: Target peer already connected\n",
1181 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1182 occ->timeout_task = NULL;
1183 send_overlay_connect_success_msg (occ);
1184 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
1187 occ->peer_identity = *my_identity;
1188 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n",
1190 GNUNET_i2s (&occ->peer_identity));
1191 /* Lookup for HELLO in hello cache */
1192 if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
1194 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n",
1196 GNUNET_i2s (&occ->peer_identity));
1197 occ->hello = GNUNET_copy_message (hello);
1198 p2_transport_connect (occ);
1201 GNUNET_asprintf (&occ->emsg,
1202 "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
1204 GNUNET_i2s (&occ->peer_identity));
1206 GST_connection_pool_get_handle (occ->peer->id,
1207 occ->peer->details.local.cfg,
1208 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1209 p1_transport_connect_cache_callback,
1216 * Callback to be called when forwarded get peer config operation as part of
1217 * overlay connect is successfull. Connection to Peer 1's core is made and is
1218 * checked for new connection from peer 2
1220 * @param cls ForwardedOperationContext
1221 * @param msg the peer create success message
1224 overlay_connect_get_config (void *cls,
1225 const struct GNUNET_MessageHeader *msg)
1227 struct OverlayConnectContext *occ = cls;
1228 struct RemotePeer2Context *rp2c;
1229 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
1231 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1232 rp2c = &occ->p2ctx.remote;
1234 GNUNET_assert (NULL != occ->timeout_task);
1235 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
1237 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1239 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1242 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1243 occ->other_peer_identity = cmsg->peer_identity;
1244 GNUNET_free_non_null (occ->emsg);
1245 GNUNET_asprintf (&occ->emsg,
1246 "0x%llx: Timeout while connecting to CORE of peer with "
1251 GST_connection_pool_get_handle (occ->peer->id,
1252 occ->peer->details.local.cfg,
1253 GST_CONNECTIONPOOL_SERVICE_CORE,
1254 occ_cache_get_handle_core_cb,
1256 &occ->other_peer_identity,
1257 &overlay_connect_notify,
1264 * Callback which will be called after a host registration succeeded or failed
1266 * @param cls the RegisteredHostContext
1267 * @param emsg the error message; NULL if host registration is successful
1270 host_registration_comp (void *cls, const char *emsg)
1272 struct RegisteredHostContext *rhc = cls;
1274 rhc->state = RHC_DONE;
1275 GST_process_next_focc (rhc);
1280 * Iterator to match a registered host context
1282 * @param cls pointer 2 pointer of RegisteredHostContext
1283 * @param key current key code
1284 * @param value value in the hash map
1285 * @return #GNUNET_YES if we should continue to
1287 * #GNUNET_NO if not.
1290 reghost_match_iterator (void *cls,
1291 const struct GNUNET_HashCode *key,
1294 struct RegisteredHostContext **rh = cls;
1295 struct RegisteredHostContext *rh_val = value;
1297 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1308 * Function to generate the hashcode corresponding to a RegisteredHostContext
1310 * @param reg_host the host which is being registered in RegisteredHostContext
1311 * @param host the host of the controller which has to connect to the above rhost
1312 * @return the hashcode
1314 static struct GNUNET_HashCode
1315 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1316 struct GNUNET_TESTBED_Host *host)
1318 struct GNUNET_HashCode hash;
1319 uint32_t host_ids[2];
1321 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1322 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1323 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1329 * Checks if the given host is registered at the given slave.
1331 * @param slave the slave where registration has to be checked. The check is
1332 * actually done through a locally maintained hashmap. No
1333 * communication with the slave is involved.
1334 * @param host the host to register
1335 * @return If the given host is not registered already or the registration is
1336 * pending, it returns the registration context. Any overlay connects
1337 * to be forwarded should be queued in the context so that they can be
1338 * executed when the registration is completed. If the given host is
1339 * already registered, NULL is returned.
1341 static struct RegisteredHostContext *
1342 register_host (struct Slave *slave,
1343 struct GNUNET_TESTBED_Host *host)
1345 struct GNUNET_HashCode hash;
1346 struct RegisteredHostContext *rhc;
1348 rhc = GNUNET_new (struct RegisteredHostContext);
1349 rhc->reg_host = host;
1350 rhc->host = GST_host_list[slave->host_id];
1351 GNUNET_assert (NULL != rhc->reg_host);
1352 GNUNET_assert (NULL != rhc->host);
1353 rhc->state = RHC_INIT;
1354 hash = hash_hosts (rhc->reg_host, rhc->host);
1356 GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map,
1359 GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
1361 reghost_match_iterator,
1364 /* create and add a new registerd host context */
1365 /* add the focc to its queue */
1366 GNUNET_CONTAINER_multihashmap_put (slave->reghost_map,
1369 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1370 GST_queue_host_registration (slave,
1371 host_registration_comp,
1377 /* rhc is now set to the existing one from the hash map by
1378 * reghost_match_iterator() */
1379 /* if queue is empty then ignore creating focc and proceed with normal
1381 if (RHC_DONE == rhc->state)
1389 * Forwards the overlay connect request to a slave controller. Before
1390 * forwarding, any hosts which are needed to be known by the slave controller to
1391 * execute the overlay connect request are registered at slave.
1393 * @param msg the overlay connect request message to be forwarded
1394 * @param client the client to which the status of the forwarded request has to
1398 forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
1399 struct GNUNET_SERVICE_Client *client)
1401 struct ForwardedOperationContext *fopc;
1402 struct Route *route_to_peer2_host;
1403 struct Route *route_to_peer1_host;
1405 struct RegisteredHostContext *rhc;
1406 struct ForwardedOverlayConnectContext *focc;
1408 uint32_t peer2_host_id;
1412 p1 = ntohl (msg->peer1);
1413 p2 = ntohl (msg->peer2);
1414 op_id = GNUNET_ntohll (msg->operation_id);
1415 peer2_host_id = ntohl (msg->peer2_host_id);
1416 GNUNET_assert (VALID_PEER_ID (p1));
1417 GNUNET_assert (VALID_HOST_ID (peer2_host_id));
1418 peer = GST_peer_list[p1];
1419 GNUNET_assert (GNUNET_YES == peer->is_remote);
1420 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
1421 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1422 route_to_peer1_host = GST_find_dest_route
1423 (peer->details.remote.remote_host_id);
1424 GNUNET_assert (NULL != route_to_peer1_host);
1425 if ((NULL != route_to_peer2_host) &&
1426 (route_to_peer1_host->dest == route_to_peer2_host->dest))
1428 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1429 different subtrees OR peer2 is on a subtree unknown to us */
1430 if (NULL != (rhc = register_host (peer->details.remote.slave,
1431 GST_host_list[peer2_host_id])))
1433 LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, p2);
1434 focc = GNUNET_new (struct ForwardedOverlayConnectContext);
1438 focc->peer2_host_id = peer2_host_id;
1439 focc->orig_msg = GNUNET_copy_message (&msg->header);
1440 focc->operation_id = op_id;
1441 focc->client = client;
1442 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
1449 LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, p2);
1450 fopc = GNUNET_new (struct ForwardedOperationContext);
1451 fopc->client = client;
1452 fopc->operation_id = op_id;
1453 fopc->type = OP_OVERLAY_CONNECT;
1455 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1456 slave->controller, op_id,
1458 &GST_forwarded_operation_reply_relay,
1460 fopc->timeout_task =
1461 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1462 &GST_forwarded_operation_timeout,
1464 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
1471 * Callback called when a connection to the controller of peer2 has been
1474 * @param cls the overlay connect contexts
1475 * @param c handle to the controller connection
1478 p2_controller_connect_cb (void *cls,
1479 struct GNUNET_TESTBED_Controller *c)
1481 struct OverlayConnectContext *occ = cls;
1482 struct RemotePeer2Context *rp2c;
1483 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1485 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1486 rp2c = &occ->p2ctx.remote;
1490 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1492 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
1493 cmsg.peer_id = htonl (occ->other_peer_id);
1494 cmsg.operation_id = GNUNET_htonll (occ->op_id);
1496 GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
1499 &overlay_connect_get_config,
1501 GNUNET_free_non_null (occ->emsg);
1502 GNUNET_asprintf (&occ->emsg,
1503 "0x%llx: Timeout while getting peer identity of peer "
1506 occ->other_peer_id);
1511 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages
1513 * @param cls identification of the client
1514 * @param msg the actual message
1517 handle_overlay_connect (void *cls,
1518 const struct GNUNET_TESTBED_OverlayConnectMessage *msg)
1520 struct GNUNET_SERVICE_Client *client = cls;
1523 struct OverlayConnectContext *occ;
1524 struct Neighbour *p2n;
1525 uint64_t operation_id;
1528 uint32_t peer2_host_id;
1530 p1 = ntohl (msg->peer1);
1531 p2 = ntohl (msg->peer2);
1532 if (! VALID_PEER_ID (p1))
1535 GNUNET_SERVICE_client_drop (client);
1538 peer = GST_peer_list[p1];
1539 operation_id = GNUNET_ntohll (msg->operation_id);
1541 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n",
1545 peer2_host_id = ntohl (msg->peer2_host_id);
1546 if (GNUNET_YES == peer->is_remote)
1548 if (! VALID_HOST_ID (peer2_host_id))
1551 GNUNET_SERVICE_client_drop (client);
1554 forward_overlay_connect (msg, client);
1555 GNUNET_SERVICE_client_continue (client);
1559 occ = GNUNET_new (struct OverlayConnectContext);
1560 occ->type = OCC_TYPE_LOCAL;
1561 if (! VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */
1563 if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1565 if (! VALID_HOST_ID (peer2_host_id))
1568 LOG (GNUNET_ERROR_TYPE_WARNING,
1569 "0x%llx: Peer %u's host not in our neighbours list\n",
1571 GNUNET_SERVICE_client_drop (client);
1575 p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
1577 occ->type = OCC_TYPE_REMOTE_LATERAL;
1578 occ->p2ctx.remote.p2n = p2n;
1580 else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1582 occ->type = OCC_TYPE_REMOTE_SLAVE;
1583 occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
1585 GNUNET_CONTAINER_DLL_insert_tail (occq_head,
1588 occ->client = client;
1589 occ->other_peer_id = p2;
1590 GST_peer_list[p1]->reference_cnt++;
1591 occ->peer = GST_peer_list[p1];
1592 occ->op_id = operation_id;
1593 GNUNET_assert (NULL == occ->timeout_task);
1595 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1596 &timeout_overlay_connect,
1600 case OCC_TYPE_REMOTE_LATERAL:
1601 GNUNET_asprintf (&occ->emsg,
1602 "0x%llx: Timeout while acquiring connection to peer %u's "
1607 occ->p2ctx.remote.ncn
1608 = GST_neighbour_get_connection (p2n,
1609 &p2_controller_connect_cb,
1612 case OCC_TYPE_REMOTE_SLAVE:
1613 p2_controller_connect_cb (occ,
1614 occ->p2ctx.remote.p2c);
1616 case OCC_TYPE_LOCAL:
1617 peer2 = GST_peer_list[occ->other_peer_id];
1618 peer2->reference_cnt++;
1619 GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
1620 &occ->other_peer_identity);
1621 GNUNET_asprintf (&occ->emsg,
1622 "0x%llx: Timeout while connecting to CORE of peer with "
1627 GST_connection_pool_get_handle (occ->peer->id,
1628 occ->peer->details.local.cfg,
1629 GST_CONNECTIONPOOL_SERVICE_CORE,
1630 occ_cache_get_handle_core_cb, occ,
1631 &occ->other_peer_identity,
1632 &overlay_connect_notify, occ);
1635 GNUNET_SERVICE_client_continue (client);
1640 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1643 * @param rocc the RemoteOverlayConnectCtx
1646 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1648 LOG_DEBUG ("0x%llx: Cleaning up rocc\n",
1650 if (NULL != rocc->attempt_connect_task_id)
1651 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1652 if (NULL != rocc->timeout_rocc_task_id)
1653 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1654 if (NULL != rocc->ohh)
1655 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1656 if (NULL != rocc->tcc.csh)
1657 GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh);
1658 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th);
1659 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats);
1660 GNUNET_assert (rocc->peer->reference_cnt > 0);
1661 rocc->peer->reference_cnt--;
1662 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1663 (0 == rocc->peer->reference_cnt))
1664 GST_destroy_peer (rocc->peer);
1665 GNUNET_free_non_null (rocc->hello);
1666 GNUNET_CONTAINER_DLL_remove (roccq_head,
1674 * Task to timeout rocc and cleanit up
1676 * @param cls the RemoteOverlayConnectCtx
1679 timeout_rocc_task (void *cls)
1681 struct RemoteOverlayConnectCtx *rocc = cls;
1683 GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
1684 rocc->timeout_rocc_task_id = NULL;
1685 LOG_DEBUG ("0x%llx: rocc timed out\n",
1687 cleanup_rocc (rocc);
1692 * Function called to notify transport users that another
1693 * peer connected to us.
1695 * @param cls the RemoteOverlayConnectContext
1696 * @param new_peer the peer that connected
1699 cache_transport_peer_connect_notify (void *cls,
1700 const struct GNUNET_PeerIdentity *new_peer)
1702 struct RemoteOverlayConnectCtx *rocc = cls;
1704 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n",
1707 memcmp (new_peer, &rocc->a_id,
1708 sizeof (struct GNUNET_PeerIdentity)));
1709 LOG_DEBUG ("0x%llx: Peer %s connected\n",
1711 GNUNET_i2s (&rocc->a_id));
1712 cleanup_rocc (rocc);
1717 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1718 * whose identity is in RemoteOverlayConnectCtx
1720 * @param cls the RemoteOverlayConnectCtx
1723 attempt_connect_task (void *cls);
1727 * Task that is run when hello has been sent If tc->reason =
1728 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1729 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1731 * @param cls the overlay connect context
1734 rocc_hello_sent_cb (void *cls)
1736 struct RemoteOverlayConnectCtx *rocc = cls;
1739 GNUNET_assert (NULL == rocc->attempt_connect_task_id);
1740 LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n",
1742 GNUNET_i2s (&rocc->a_id),
1744 rocc->tcc.cgh_p2_ats =
1745 GST_connection_pool_get_handle (rocc->peer->id,
1746 rocc->peer->details.local.cfg,
1747 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
1748 &occ_cache_get_handle_ats_rocc_cb,
1749 rocc, NULL, NULL, NULL);
1754 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1755 * whose identity is in RemoteOverlayConnectCtx
1757 * @param cls the RemoteOverlayConnectCtx
1760 attempt_connect_task (void *cls)
1762 struct RemoteOverlayConnectCtx *rocc = cls;
1764 GNUNET_assert (NULL != rocc->attempt_connect_task_id);
1765 rocc->attempt_connect_task_id = NULL;
1766 LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n",
1768 GNUNET_i2s (&rocc->a_id),
1771 GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg,
1773 &rocc_hello_sent_cb,
1775 if (NULL == rocc->ohh)
1776 rocc->attempt_connect_task_id =
1777 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1778 (GNUNET_TIME_UNIT_MILLISECONDS,
1780 GNUNET_CRYPTO_random_u32
1781 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1782 &attempt_connect_task, rocc);
1787 * Callback from cache with needed handles set
1789 * @param cls the closure passed to GST_cache_get_handle_transport()
1790 * @param ch the handle to CORE. Can be NULL if it is not requested
1791 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1792 * @param ac the handle to ATS. Can be NULL if it is not requested
1793 * @param ignore_ peer identity which is ignored in this callback
1796 rocc_cache_get_handle_transport_cb (void *cls,
1797 struct GNUNET_CORE_Handle *ch,
1798 struct GNUNET_TRANSPORT_CoreHandle *th,
1799 struct GNUNET_ATS_ConnectivityHandle *ac,
1800 const struct GNUNET_PeerIdentity *ignore_,
1801 const struct GNUNET_CONFIGURATION_Handle *cfg)
1803 struct RemoteOverlayConnectCtx *rocc = cls;
1807 rocc->timeout_rocc_task_id =
1808 GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1812 rocc->tcc.cfg = cfg;
1814 GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_,
1817 LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n",
1819 GNUNET_i2s (&rocc->a_id),
1821 cleanup_rocc (rocc);
1824 rocc->attempt_connect_task_id =
1825 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1830 * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
1832 * @param cls identification of the client
1833 * @param msg the actual message
1834 * @return #GNUNET_OK if @a msg is well-formed
1837 check_remote_overlay_connect (void *cls,
1838 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
1844 msize = ntohs (msg->header.size);
1845 if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))
1848 return GNUNET_SYSERR;
1850 hsize = ntohs (msg->hello->size);
1851 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) != msize)
1854 return GNUNET_SYSERR;
1856 peer_id = ntohl (msg->peer);
1857 if ((peer_id >= GST_peer_list_size) ||
1858 (NULL == GST_peer_list[peer_id]))
1860 GNUNET_break_op (0);
1861 return GNUNET_SYSERR;
1868 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
1870 * @param cls identification of the client
1871 * @param msg the actual message
1874 handle_remote_overlay_connect (void *cls,
1875 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
1877 struct GNUNET_SERVICE_Client *client = cls;
1878 struct RemoteOverlayConnectCtx *rocc;
1880 struct GNUNET_PeerIdentity pid;
1881 static char pid_str[16];
1885 hsize = ntohs (msg->hello->size);
1886 peer_id = ntohl (msg->peer);
1887 peer = GST_peer_list[peer_id];
1888 if (GNUNET_YES == peer->is_remote)
1890 struct GNUNET_MessageHeader *msg2;
1892 msg2 = GNUNET_copy_message (&msg->header);
1893 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1895 GNUNET_SERVICE_client_continue (client);
1898 rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
1899 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1900 GNUNET_CONTAINER_DLL_insert_tail (roccq_head,
1903 rocc->a_id = msg->peer_identity;
1904 GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
1906 (void) strncpy (pid_str,
1909 LOG_DEBUG ("0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n",
1912 GNUNET_i2s (&rocc->a_id),
1915 rocc->peer->reference_cnt++;
1916 rocc->hello = GNUNET_malloc (hsize);
1917 GNUNET_memcpy (rocc->hello,
1920 rocc->tcc.cgh_p2_th =
1921 GST_connection_pool_get_handle (peer_id,
1922 rocc->peer->details.local.cfg,
1923 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1924 &rocc_cache_get_handle_transport_cb,
1927 &cache_transport_peer_connect_notify,
1929 rocc->timeout_rocc_task_id =
1930 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1933 GNUNET_SERVICE_client_continue (client);
1938 * Clears all pending overlay connect contexts in queue
1943 struct OverlayConnectContext *occ;
1945 while (NULL != (occ = occq_head))
1951 * Clears all pending remote overlay connect contexts in queue
1956 struct RemoteOverlayConnectCtx *rocc;
1958 while (NULL != (rocc = roccq_head))
1959 cleanup_rocc (rocc);