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/>.
20 * @file testbed/gnunet-service-testbed_oc.c
21 * @brief code for handling overlay connect operations
22 * @author Sree Harsha Totakura
25 #include "gnunet-service-testbed.h"
26 #include "gnunet-service-testbed_connectionpool.h"
27 #include "gnunet_transport_hello_service.h"
30 * Redefine LOG with a changed log component string
35 #define LOG(kind,...) \
36 GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__)
40 * Context information for requesting ATS to connect to a peer
42 struct ConnectivitySuggestContext
46 * The transport handle obtained from cache. Do NOT close/disconnect.
48 struct GNUNET_TRANSPORT_CoreHandle *th_;
51 * Configuration of the peer from cache. Do not free!
53 const struct GNUNET_CONFIGURATION_Handle *cfg;
56 * The GetCacheHandle for the peer2's transport handle
57 * (used to offer the HELLO to the peer).
59 struct GST_ConnectionPool_GetHandle *cgh_p2_th;
62 * The GetCacheHandle for the peer2's ATS handle.
64 struct GST_ConnectionPool_GetHandle *cgh_p2_ats;
67 * The ATS handle for the connectivity suggestion.
69 struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
75 * Types for context information we create for overlay connect requests
77 enum OverlayConnectContextType
80 * This type is used if the overlay connection is local i.e. the connection
81 * has to be made between local peers
86 * Type to be used when the first peer is local and the other peer is on a slave
87 * controller started by us
89 OCC_TYPE_REMOTE_SLAVE,
92 * Type to be used when the first peer is local and the other peer is on a
93 * controller which is not started by us.
95 OCC_TYPE_REMOTE_LATERAL
100 * Context data for operations on second peer in local overlay connection
103 struct LocalPeer2Context
106 * The handle for offering the HELLO of the first peer to the second
109 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
112 * The transport ConnectivitySuggestContext
114 struct ConnectivitySuggestContext tcc;
119 * Context data for operations on second peer in remote overlay connection
122 struct RemotePeer2Context
125 * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay
126 * connection then this can be NULL until the connection to the controller is
129 struct GNUNET_TESTBED_Controller *p2c;
132 * Operation context for the suboperation we start to get the identity of the
135 struct OperationContext *opc;
138 * Notification handle acquire to connect to a remote controller. Only used
139 * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL.
141 struct NeighbourConnectNotification *ncn;
144 * The neighbour handle. Only used if the type of overlay connection is
145 * #OCC_TYPE_REMOTE_LATERAL.
147 struct Neighbour *p2n;
151 * Context information for connecting 2 peers in overlay.
153 struct OverlayConnectContext
156 * The next pointer for maintaining a DLL of all OverlayConnectContexts
158 struct OverlayConnectContext *next;
161 * The prev pointer for maintaining a DLL of all OverlayConnectContexts
163 struct OverlayConnectContext *prev;
166 * The client which has requested for overlay connection. This is used to send
167 * either a success of failure message
169 struct GNUNET_SERVICE_Client *client;
172 * the first peer which is to expect an overlay connection from the second peer.
177 * Transport handle of the first peer obtained from cache to get its HELLO. Do
178 * NOT close/disconnect.
180 struct GNUNET_TRANSPORT_CoreHandle *p1th_;
183 * The #GST_ConnectionPool_GetHandle for the peer1's transport handle
185 struct GST_ConnectionPool_GetHandle *cgh_p1th;
188 * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE
189 * level peer connects and to get our identity.
191 struct GST_ConnectionPool_GetHandle *cgh_ch;
194 * HELLO of the first peer. This should be sent to the second peer.
196 struct GNUNET_MessageHeader *hello;
199 * Get GetHelloHandle to acquire a HELLO of the first peer
201 struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
204 * The error message we send if this overlay connect operation has timed out
209 * Context information for operations on the second peer
214 * Context information to be used if the second peer is local
216 struct LocalPeer2Context local;
219 * Context information to be used if the second peer is remote
221 struct RemotePeer2Context remote;
226 * The peer identity of the first peer
228 struct GNUNET_PeerIdentity peer_identity;
231 * The peer identity of the other peer
233 struct GNUNET_PeerIdentity other_peer_identity;
236 * The id of the operation responsible for creating this context
241 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
244 struct GNUNET_SCHEDULER_Task *send_hello_task;
247 * The id of the overlay connect timeout task
249 struct GNUNET_SCHEDULER_Task *timeout_task;
252 * The id of the cleanup task
254 struct GNUNET_SCHEDULER_Task *cleanup_task;
257 * The type of this context information
259 enum OverlayConnectContextType type;
262 * The id of the second peer which has to connect to the first peer
264 uint32_t other_peer_id;
269 * Context information for remote overlay connect operations. Remote overlay
270 * connections are used when peers A and B reside on different hosts. In these
271 * operations the host controller for peer B is asked by the host controller of
272 * peer A to make peer B connect to peer A by sending the controller of peer B
273 * the HELLO of peer A.
275 struct RemoteOverlayConnectCtx
278 * the next pointer for DLL
280 struct RemoteOverlayConnectCtx *next;
283 * the prev pointer for DLL
285 struct RemoteOverlayConnectCtx *prev;
288 * The peer handle of peer B
295 struct GNUNET_MessageHeader *hello;
298 * The handle for offering HELLO
300 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
303 * The transport try connect context
305 struct ConnectivitySuggestContext tcc;
308 * The peer identity of peer A
310 struct GNUNET_PeerIdentity a_id;
313 * Task for offering HELLO of A to B and doing try_connect
315 struct GNUNET_SCHEDULER_Task *attempt_connect_task_id;
318 * Task to timeout RequestOverlayConnect
320 struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id;
323 * The id of the operation responsible for creating this context
330 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
332 static struct OverlayConnectContext *occq_head;
335 * DLL tail for OverlayConnectContext DLL
337 static struct OverlayConnectContext *occq_tail;
340 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
343 static struct RemoteOverlayConnectCtx *roccq_head;
346 * DLL tail for RequectOverlayConnectContext DLL
348 static struct RemoteOverlayConnectCtx *roccq_tail;
352 * Cleans up ForwardedOverlayConnectContext
354 * @param focc the ForwardedOverlayConnectContext to cleanup
357 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
359 struct RegisteredHostContext *rhc = focc->rhc;
361 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head,
364 GNUNET_free_non_null (focc->orig_msg);
370 * Timeout task for cancelling a forwarded overlay connect connect
372 * @param cls the `struct ForwardedOperationContext`
375 forwarded_overlay_connect_timeout (void *cls)
377 struct ForwardedOperationContext *fopc = cls;
378 struct RegisteredHostContext *rhc;
379 struct ForwardedOverlayConnectContext *focc;
381 fopc->timeout_task = NULL;
383 focc = rhc->focc_dll_head;
384 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n",
387 GST_cleanup_focc (focc);
388 GST_forwarded_operation_timeout (fopc);
389 if (NULL != rhc->focc_dll_head)
390 GST_process_next_focc (rhc);
395 * Callback to be called when forwarded overlay connection operation has a reply
396 * from the sub-controller successfull. We have to relay the reply msg back to
399 * @param cls ForwardedOperationContext
400 * @param msg the peer create success message
403 forwarded_overlay_connect_listener (void *cls,
404 const struct GNUNET_MessageHeader *msg)
406 struct ForwardedOperationContext *fopc = cls;
407 struct RegisteredHostContext *rhc;
408 struct ForwardedOverlayConnectContext *focc;
411 GST_forwarded_operation_reply_relay (cls, msg);
412 focc = rhc->focc_dll_head;
413 GST_cleanup_focc (focc);
414 if (NULL != rhc->focc_dll_head)
415 GST_process_next_focc (rhc);
420 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
422 * @param rhc the RegisteredHostContext
425 GST_process_next_focc (struct RegisteredHostContext *rhc)
427 struct ForwardedOperationContext *fopc;
428 struct ForwardedOverlayConnectContext *focc;
432 focc = rhc->focc_dll_head;
433 GNUNET_assert (NULL != focc);
434 GNUNET_assert (RHC_DONE == rhc->state);
435 GNUNET_assert (VALID_PEER_ID (focc->peer1));
436 peer = GST_peer_list[focc->peer1];
437 GNUNET_assert (GNUNET_YES == peer->is_remote);
438 GNUNET_assert (NULL != (slave = peer->details.remote.slave));
439 fopc = GNUNET_new (struct ForwardedOperationContext);
440 fopc->client = focc->client;
441 fopc->operation_id = focc->operation_id;
443 fopc->type = OP_OVERLAY_CONNECT;
445 GNUNET_TESTBED_forward_operation_msg_ (slave->controller,
448 &forwarded_overlay_connect_listener,
450 GNUNET_free (focc->orig_msg);
451 focc->orig_msg = NULL;
452 fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout,
453 &forwarded_overlay_connect_timeout,
455 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
462 * Cleans up any used handles in local peer2 context
464 * @param lp2c the local peer2 context information
467 cleanup_occ_lp2c (struct LocalPeer2Context *lp2c)
469 if (NULL != lp2c->ohh)
471 GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh);
474 if (NULL != lp2c->tcc.cgh_p2_th)
476 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th);
477 lp2c->tcc.cgh_p2_th = NULL;
479 if (NULL != lp2c->tcc.cgh_p2_ats)
481 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats);
482 lp2c->tcc.cgh_p2_ats = NULL;
484 if (NULL != lp2c->tcc.csh)
486 GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh);
487 lp2c->tcc.csh = NULL;
493 * Cleans up any used handles in remote peer2 context. Relinquishes the
494 * remote controller connection if it has been established on-demand.
496 * @param rp2c the remote peer2 context information
499 cleanup_occ_rp2c (struct RemotePeer2Context *rp2c)
501 if (NULL != rp2c->opc)
503 GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc);
506 if (NULL != rp2c->ncn)
508 GST_neighbour_get_connection_cancel (rp2c->ncn);
511 if ( (NULL != rp2c->p2c) && (NULL != rp2c->p2n) )
513 GST_neighbour_release_connection (rp2c->p2n);
519 * Condition for checking if given peer is ready to be destroyed
521 * @param peer the peer to check
523 #define PEER_EXPIRED(peer) \
524 ( (GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt) )
527 * Cleanup overlay connect context structure
529 * @param occ the overlay connect context
532 cleanup_occ (struct OverlayConnectContext *occ)
536 LOG_DEBUG ("0x%llx: Cleaning up occ\n",
538 GNUNET_free_non_null (occ->emsg);
539 GNUNET_free_non_null (occ->hello);
540 if (NULL != occ->send_hello_task)
541 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
542 if (NULL != occ->cleanup_task)
543 GNUNET_SCHEDULER_cancel (occ->cleanup_task);
544 if (NULL != occ->timeout_task)
545 GNUNET_SCHEDULER_cancel (occ->timeout_task);
546 if (NULL != occ->cgh_ch)
547 GST_connection_pool_get_handle_done (occ->cgh_ch);
548 if (NULL != occ->ghh)
549 GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
550 GST_connection_pool_get_handle_done (occ->cgh_p1th);
551 GNUNET_assert (NULL != GST_peer_list);
552 GNUNET_assert (occ->peer->reference_cnt > 0);
553 occ->peer->reference_cnt--;
554 if (PEER_EXPIRED (occ->peer))
555 GST_destroy_peer (occ->peer);
559 peer2 = GST_peer_list[occ->other_peer_id];
560 GNUNET_assert (peer2->reference_cnt > 0);
561 peer2->reference_cnt--;
562 if (PEER_EXPIRED (peer2))
563 GST_destroy_peer (peer2);
564 cleanup_occ_lp2c (&occ->p2ctx.local);
566 case OCC_TYPE_REMOTE_SLAVE:
567 case OCC_TYPE_REMOTE_LATERAL:
568 cleanup_occ_rp2c (&occ->p2ctx.remote);
571 GNUNET_CONTAINER_DLL_remove (occq_head,
579 * Task for cleaing up overlay connect context structure
581 * @param cls the overlay connect context
584 do_cleanup_occ (void *cls)
586 struct OverlayConnectContext *occ = cls;
588 occ->cleanup_task = NULL;
594 * Task which will be run when overlay connect request has been timed out
596 * @param cls the OverlayConnectContext
599 timeout_overlay_connect (void *cls)
601 struct OverlayConnectContext *occ = cls;
603 GNUNET_assert (NULL != occ->timeout_task);
604 occ->timeout_task = NULL;
605 /* LOG (GNUNET_ERROR_TYPE_WARNING, */
606 /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
607 /* occ->peer->id, occ->other_peer_id, occ->emsg); */
608 GST_send_operation_fail_msg (occ->client,
616 * Notify OC subsystem that @a client disconnected.
618 * @param client the client that disconnected
621 GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client)
623 struct ForwardedOperationContext *fopc;
624 struct ForwardedOperationContext *fopcn;
625 struct OverlayConnectContext *occ;
626 struct OverlayConnectContext *occn;
628 for (fopc = fopcq_head; NULL != fopc; fopc = fopcn)
631 if (fopc->client == client)
633 GNUNET_SCHEDULER_cancel (fopc->timeout_task);
634 GST_forwarded_operation_timeout (fopc);
637 for (occ = occq_head; NULL != occ; occ = occn)
640 if (occ->client == client)
643 // FIXME: implement clean up for client_keep replacements!
653 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
655 struct GNUNET_MQ_Envelope *env;
656 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
658 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
660 env = GNUNET_MQ_msg (msg,
661 GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
662 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
663 msg->peer1 = htonl (occ->peer->id);
664 msg->peer2 = htonl (occ->other_peer_id);
665 msg->operation_id = GNUNET_htonll (occ->op_id);
666 GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (occ->client),
672 * Function called to notify transport users that another
673 * peer connected to us.
676 * @param new_peer the peer that connected
679 overlay_connect_notify (void *cls,
680 const struct GNUNET_PeerIdentity *new_peer)
682 struct OverlayConnectContext *occ = cls;
684 char *other_peer_str;
686 LOG_DEBUG ("Overlay connect notify\n");
688 memcmp (new_peer, &occ->peer_identity,
689 sizeof (struct GNUNET_PeerIdentity)))
691 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
692 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
695 &occ->other_peer_identity,
696 sizeof (struct GNUNET_PeerIdentity)))
698 LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n",
701 GNUNET_free (new_peer_str);
702 GNUNET_free (other_peer_str);
705 GNUNET_free (new_peer_str);
706 LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n",
709 GNUNET_i2s (&occ->peer_identity));
710 GNUNET_free (other_peer_str);
711 if (NULL != occ->send_hello_task)
713 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
714 occ->send_hello_task = NULL;
716 GNUNET_assert (NULL != occ->timeout_task);
717 GNUNET_SCHEDULER_cancel (occ->timeout_task);
718 occ->timeout_task = NULL;
722 cleanup_occ_lp2c (&occ->p2ctx.local);
724 case OCC_TYPE_REMOTE_SLAVE:
725 case OCC_TYPE_REMOTE_LATERAL:
726 cleanup_occ_rp2c (&occ->p2ctx.remote);
729 GNUNET_free_non_null (occ->emsg);
731 send_overlay_connect_success_msg (occ);
732 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ,
738 * Callback from cache with needed ATS handle set
740 * @param cls a `struct OverlayConnectCtx *`
741 * @param ch the handle to CORE. Can be NULL if it is not requested
742 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
743 * @param ac the handle to ATS. Can be NULL if it is not requested
744 * @param my_identity the identity of our peer
745 * @param cfg configuration of the peer
748 occ_cache_get_handle_ats_occ_cb (void *cls,
749 struct GNUNET_CORE_Handle *ch,
750 struct GNUNET_TRANSPORT_CoreHandle *th,
751 struct GNUNET_ATS_ConnectivityHandle *ac,
752 const struct GNUNET_PeerIdentity *my_identity,
753 const struct GNUNET_CONFIGURATION_Handle *cfg)
755 struct OverlayConnectContext *occ = cls;
756 struct LocalPeer2Context *lp2c;
758 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
759 GNUNET_assert (NULL != occ->timeout_task);
760 GNUNET_free_non_null (occ->emsg);
763 GNUNET_asprintf (&occ->emsg,
764 "0x%llx: Failed to connect to ATS of peer with id: %u",
767 GNUNET_SCHEDULER_cancel (occ->timeout_task);
769 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect,
775 GNUNET_asprintf (&occ->emsg,
776 "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s",
778 GNUNET_i2s (&occ->other_peer_identity));
780 lp2c = &occ->p2ctx.local;
782 GNUNET_ATS_connectivity_suggest (ac,
789 * Callback from cache with needed ATS handle set
791 * @param cls a `struct RemoteOverlayConnectCtx *`
792 * @param ch the handle to CORE. Can be NULL if it is not requested
793 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
794 * @param ac the handle to ATS. Can be NULL if it is not requested
795 * @param my_identity the identity of our peer
798 occ_cache_get_handle_ats_rocc_cb (void *cls,
799 struct GNUNET_CORE_Handle *ch,
800 struct GNUNET_TRANSPORT_CoreHandle *th,
801 struct GNUNET_ATS_ConnectivityHandle *ac,
802 const struct GNUNET_PeerIdentity *my_identity,
803 const struct GNUNET_CONFIGURATION_Handle *cfg)
805 struct RemoteOverlayConnectCtx *rocc = cls;
808 GNUNET_ATS_connectivity_suggest (ac,
815 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
818 * @param cls the OverlayConnectContext
821 send_hello (void *cls);
825 * Task that is run when hello has been sent If tc->reason =
826 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
827 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
829 * @param cls the overlay connect context
832 occ_hello_sent_cb (void *cls)
834 struct OverlayConnectContext *occ = cls;
835 struct LocalPeer2Context *lp2c;
838 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
839 GNUNET_assert (NULL != occ->timeout_task);
840 lp2c = &occ->p2ctx.local;
843 GNUNET_assert (NULL == occ->send_hello_task);
844 GNUNET_free_non_null (occ->emsg);
846 GNUNET_asprintf (&occ->emsg,
847 "0x%llx: Timeout while acquiring ATS of %s from cache",
849 GNUNET_i2s (&occ->other_peer_identity));
850 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
851 lp2c->tcc.cgh_p2_ats =
852 GST_connection_pool_get_handle (occ->other_peer_id,
853 peer2->details.local.cfg,
854 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
855 &occ_cache_get_handle_ats_occ_cb,
856 occ, NULL, NULL, NULL);
861 * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
864 * @param occ the overlay connect context. Its type must be either
865 * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL
868 send_hello_thru_rocc (struct OverlayConnectContext *occ)
870 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
871 char *other_peer_str;
875 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
876 GNUNET_assert (NULL != occ->hello);
877 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
878 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n",
880 GNUNET_i2s (&occ->peer_identity),
881 ntohs (occ->hello->size),
883 GNUNET_free (other_peer_str);
884 hello_size = ntohs (occ->hello->size);
885 msize = sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
886 msg = GNUNET_malloc (msize);
888 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
889 msg->header.size = htons (msize);
890 msg->peer = htonl (occ->other_peer_id);
891 msg->operation_id = GNUNET_htonll (occ->op_id);
892 msg->peer_identity = occ->peer_identity;
893 GNUNET_memcpy (msg->hello,
896 GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c,
902 * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered
903 * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
904 * send_hello_thru_rocc()
906 * @param cls the OverlayConnectContext
909 send_hello (void *cls)
911 struct OverlayConnectContext *occ = cls;
912 struct LocalPeer2Context *lp2c;
913 char *other_peer_str;
915 occ->send_hello_task = NULL;
916 GNUNET_assert (NULL != occ->timeout_task);
917 GNUNET_assert (NULL != occ->hello);
918 if (OCC_TYPE_LOCAL != occ->type)
920 send_hello_thru_rocc (occ);
923 lp2c = &occ->p2ctx.local;
924 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
925 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n",
927 GNUNET_i2s (&occ->peer_identity),
929 GNUNET_free (other_peer_str);
931 GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg,
935 if (NULL == lp2c->ohh)
938 occ->send_hello_task =
939 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
940 (GNUNET_TIME_UNIT_MILLISECONDS,
942 GNUNET_CRYPTO_random_u32
943 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
950 * Callback from cache with needed handles set
952 * @param cls the closure passed to GST_cache_get_handle_transport()
953 * @param ch the handle to CORE. Can be NULL if it is not requested
954 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
955 * @param ac the handle to ATS. Can be NULL if it is not requested
956 * @param ignore_ peer identity which is ignored in this callback
957 * @param cfg configuration of the peer
960 p2_transport_connect_cache_callback (void *cls,
961 struct GNUNET_CORE_Handle *ch,
962 struct GNUNET_TRANSPORT_CoreHandle *th,
963 struct GNUNET_ATS_ConnectivityHandle *ac,
964 const struct GNUNET_PeerIdentity *ignore_,
965 const struct GNUNET_CONFIGURATION_Handle *cfg)
967 struct OverlayConnectContext *occ = cls;
969 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
972 GNUNET_asprintf (&occ->emsg,
973 "0x%llx: Cannot connect to TRANSPORT of %s",
975 GNUNET_i2s (&occ->other_peer_identity));
976 GNUNET_SCHEDULER_cancel (occ->timeout_task);
978 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
981 occ->p2ctx.local.tcc.th_ = th;
982 occ->p2ctx.local.tcc.cfg = cfg;
983 GNUNET_asprintf (&occ->emsg,
984 "0x%llx: Timeout while offering HELLO to %s",
986 GNUNET_i2s (&occ->other_peer_identity));
987 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
992 * Connects to the transport of the other peer if it is a local peer and
993 * schedules the send hello task
995 * @param occ the overlay connect context
998 p2_transport_connect (struct OverlayConnectContext *occ)
1002 /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the
1004 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1005 "Connecting to transport of peer %s to obtain HELLO\n",
1006 GNUNET_i2s (&occ->other_peer_identity));
1007 GNUNET_assert (NULL == occ->emsg);
1008 GNUNET_assert (NULL != occ->hello);
1009 GNUNET_assert (NULL == occ->ghh);
1010 GNUNET_assert (NULL == occ->p1th_);
1011 GNUNET_assert (NULL == occ->cgh_p1th);
1012 if (OCC_TYPE_LOCAL == occ->type)
1014 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
1015 occ->p2ctx.local.tcc.cgh_p2_th =
1016 GST_connection_pool_get_handle (occ->other_peer_id,
1017 peer2->details.local.cfg,
1018 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1019 &p2_transport_connect_cache_callback,
1020 occ, NULL, NULL, NULL);
1023 GNUNET_asprintf (&occ->emsg,
1024 "0x%llx: Timeout while offering HELLO to %s",
1026 GNUNET_i2s (&occ->other_peer_identity));
1027 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
1032 * Test for checking whether HELLO message is empty
1034 * @param cls empty flag to set
1035 * @param address the HELLO
1036 * @param expiration expiration of the HELLO
1037 * @return #GNUNET_OK
1040 test_address (void *cls,
1041 const struct GNUNET_HELLO_Address *address,
1042 struct GNUNET_TIME_Absolute expiration)
1052 * Function called whenever there is an update to the HELLO of peers in the
1053 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
1054 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
1056 * @param cls closure
1057 * @param hello our updated HELLO
1060 hello_update_cb (void *cls,
1061 const struct GNUNET_MessageHeader *hello)
1063 struct OverlayConnectContext *occ = cls;
1067 msize = ntohs (hello->size);
1069 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
1073 if (GNUNET_YES == empty)
1075 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n",
1077 GNUNET_i2s (&occ->peer_identity));
1080 LOG_DEBUG ("0x%llx: Received HELLO of %s\n",
1082 GNUNET_i2s (&occ->peer_identity));
1083 occ->hello = GNUNET_malloc (msize);
1084 GST_cache_add_hello (occ->peer->id, hello);
1085 GNUNET_memcpy (occ->hello, hello, msize);
1086 GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
1088 GST_connection_pool_get_handle_done (occ->cgh_p1th);
1089 occ->cgh_p1th = NULL;
1091 GNUNET_free_non_null (occ->emsg);
1093 p2_transport_connect (occ);
1098 * Callback from cache with needed handles set
1100 * @param cls the closure passed to GST_cache_get_handle_transport()
1101 * @param ch the handle to CORE. Can be NULL if it is not requested
1102 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1103 * @param ac the handle to ATS. Can be NULL if it is not requested
1104 * @param ignore_ peer identity which is ignored in this callback
1107 p1_transport_connect_cache_callback (void *cls,
1108 struct GNUNET_CORE_Handle *ch,
1109 struct GNUNET_TRANSPORT_CoreHandle *th,
1110 struct GNUNET_ATS_ConnectivityHandle *ac,
1111 const struct GNUNET_PeerIdentity *ignore_,
1112 const struct GNUNET_CONFIGURATION_Handle *cfg)
1114 struct OverlayConnectContext *occ = cls;
1116 GNUNET_free_non_null (occ->emsg);
1120 GNUNET_asprintf (&occ->emsg,
1121 "0x%llx: Cannot connect to TRANSPORT of %s",
1123 GNUNET_i2s (&occ->peer_identity));
1124 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1126 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1129 GNUNET_assert (NULL == occ->p1th_);
1130 GNUNET_assert (NULL != occ->cgh_p1th);
1132 GNUNET_asprintf (&occ->emsg,
1133 "0x%llx: Timeout while acquiring HELLO of peer %s",
1135 GNUNET_i2s (&occ->peer_identity));
1136 occ->ghh = GNUNET_TRANSPORT_hello_get (cfg,
1137 GNUNET_TRANSPORT_AC_ANY,
1144 * Callback from cache with needed CORE handle set
1146 * @param cls the closure passed to GST_cache_get_handle_transport()
1147 * @param ch the handle to CORE. Can be NULL if it is not requested
1148 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1149 * @param ac the handle to ATS. Can be NULL if it is not requested
1150 * @param my_identity the identity of our peer
1153 occ_cache_get_handle_core_cb (void *cls,
1154 struct GNUNET_CORE_Handle *ch,
1155 struct GNUNET_TRANSPORT_CoreHandle *th,
1156 struct GNUNET_ATS_ConnectivityHandle *ac,
1157 const struct GNUNET_PeerIdentity *my_identity,
1158 const struct GNUNET_CONFIGURATION_Handle *cfg)
1160 struct OverlayConnectContext *occ = cls;
1161 const struct GNUNET_MessageHeader *hello;
1163 GNUNET_assert (NULL != occ->timeout_task);
1164 GNUNET_free_non_null (occ->emsg);
1165 if ((NULL == ch) || (NULL == my_identity))
1167 GNUNET_asprintf (&occ->emsg,
1168 "0x%llx: Failed to connect to CORE of peer with "
1172 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1174 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1179 GNUNET_CORE_get_mq (ch,
1180 &occ->other_peer_identity))
1182 LOG_DEBUG ("0x%llx: Target peer already connected\n",
1184 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1185 occ->timeout_task = NULL;
1186 send_overlay_connect_success_msg (occ);
1187 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
1190 occ->peer_identity = *my_identity;
1191 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n",
1193 GNUNET_i2s (&occ->peer_identity));
1194 /* Lookup for HELLO in hello cache */
1195 if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
1197 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n",
1199 GNUNET_i2s (&occ->peer_identity));
1200 occ->hello = GNUNET_copy_message (hello);
1201 p2_transport_connect (occ);
1204 GNUNET_asprintf (&occ->emsg,
1205 "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
1207 GNUNET_i2s (&occ->peer_identity));
1209 GST_connection_pool_get_handle (occ->peer->id,
1210 occ->peer->details.local.cfg,
1211 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1212 p1_transport_connect_cache_callback,
1219 * Callback to be called when forwarded get peer config operation as part of
1220 * overlay connect is successfull. Connection to Peer 1's core is made and is
1221 * checked for new connection from peer 2
1223 * @param cls ForwardedOperationContext
1224 * @param msg the peer create success message
1227 overlay_connect_get_config (void *cls,
1228 const struct GNUNET_MessageHeader *msg)
1230 struct OverlayConnectContext *occ = cls;
1231 struct RemotePeer2Context *rp2c;
1232 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
1234 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1235 rp2c = &occ->p2ctx.remote;
1237 GNUNET_assert (NULL != occ->timeout_task);
1238 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
1240 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1242 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1245 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1246 occ->other_peer_identity = cmsg->peer_identity;
1247 GNUNET_free_non_null (occ->emsg);
1248 GNUNET_asprintf (&occ->emsg,
1249 "0x%llx: Timeout while connecting to CORE of peer with "
1254 GST_connection_pool_get_handle (occ->peer->id,
1255 occ->peer->details.local.cfg,
1256 GST_CONNECTIONPOOL_SERVICE_CORE,
1257 occ_cache_get_handle_core_cb,
1259 &occ->other_peer_identity,
1260 &overlay_connect_notify,
1267 * Callback which will be called after a host registration succeeded or failed
1269 * @param cls the RegisteredHostContext
1270 * @param emsg the error message; NULL if host registration is successful
1273 host_registration_comp (void *cls, const char *emsg)
1275 struct RegisteredHostContext *rhc = cls;
1277 rhc->state = RHC_DONE;
1278 GST_process_next_focc (rhc);
1283 * Iterator to match a registered host context
1285 * @param cls pointer 2 pointer of RegisteredHostContext
1286 * @param key current key code
1287 * @param value value in the hash map
1288 * @return #GNUNET_YES if we should continue to
1290 * #GNUNET_NO if not.
1293 reghost_match_iterator (void *cls,
1294 const struct GNUNET_HashCode *key,
1297 struct RegisteredHostContext **rh = cls;
1298 struct RegisteredHostContext *rh_val = value;
1300 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1311 * Function to generate the hashcode corresponding to a RegisteredHostContext
1313 * @param reg_host the host which is being registered in RegisteredHostContext
1314 * @param host the host of the controller which has to connect to the above rhost
1315 * @return the hashcode
1317 static struct GNUNET_HashCode
1318 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1319 struct GNUNET_TESTBED_Host *host)
1321 struct GNUNET_HashCode hash;
1322 uint32_t host_ids[2];
1324 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1325 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1326 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1332 * Checks if the given host is registered at the given slave.
1334 * @param slave the slave where registration has to be checked. The check is
1335 * actually done through a locally maintained hashmap. No
1336 * communication with the slave is involved.
1337 * @param host the host to register
1338 * @return If the given host is not registered already or the registration is
1339 * pending, it returns the registration context. Any overlay connects
1340 * to be forwarded should be queued in the context so that they can be
1341 * executed when the registration is completed. If the given host is
1342 * already registered, NULL is returned.
1344 static struct RegisteredHostContext *
1345 register_host (struct Slave *slave,
1346 struct GNUNET_TESTBED_Host *host)
1348 struct GNUNET_HashCode hash;
1349 struct RegisteredHostContext *rhc;
1351 rhc = GNUNET_new (struct RegisteredHostContext);
1352 rhc->reg_host = host;
1353 rhc->host = GST_host_list[slave->host_id];
1354 GNUNET_assert (NULL != rhc->reg_host);
1355 GNUNET_assert (NULL != rhc->host);
1356 rhc->state = RHC_INIT;
1357 hash = hash_hosts (rhc->reg_host, rhc->host);
1359 GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map,
1362 GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
1364 reghost_match_iterator,
1367 /* create and add a new registerd host context */
1368 /* add the focc to its queue */
1369 GNUNET_CONTAINER_multihashmap_put (slave->reghost_map,
1372 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1373 GST_queue_host_registration (slave,
1374 host_registration_comp,
1380 /* rhc is now set to the existing one from the hash map by
1381 * reghost_match_iterator() */
1382 /* if queue is empty then ignore creating focc and proceed with normal
1384 if (RHC_DONE == rhc->state)
1392 * Forwards the overlay connect request to a slave controller. Before
1393 * forwarding, any hosts which are needed to be known by the slave controller to
1394 * execute the overlay connect request are registered at slave.
1396 * @param msg the overlay connect request message to be forwarded
1397 * @param client the client to which the status of the forwarded request has to
1401 forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
1402 struct GNUNET_SERVICE_Client *client)
1404 struct ForwardedOperationContext *fopc;
1405 struct Route *route_to_peer2_host;
1406 struct Route *route_to_peer1_host;
1408 struct RegisteredHostContext *rhc;
1409 struct ForwardedOverlayConnectContext *focc;
1411 uint32_t peer2_host_id;
1415 p1 = ntohl (msg->peer1);
1416 p2 = ntohl (msg->peer2);
1417 op_id = GNUNET_ntohll (msg->operation_id);
1418 peer2_host_id = ntohl (msg->peer2_host_id);
1419 GNUNET_assert (VALID_PEER_ID (p1));
1420 GNUNET_assert (VALID_HOST_ID (peer2_host_id));
1421 peer = GST_peer_list[p1];
1422 GNUNET_assert (GNUNET_YES == peer->is_remote);
1423 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
1424 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1425 route_to_peer1_host = GST_find_dest_route
1426 (peer->details.remote.remote_host_id);
1427 GNUNET_assert (NULL != route_to_peer1_host);
1428 if ((NULL != route_to_peer2_host) &&
1429 (route_to_peer1_host->dest == route_to_peer2_host->dest))
1431 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1432 different subtrees OR peer2 is on a subtree unknown to us */
1433 if (NULL != (rhc = register_host (peer->details.remote.slave,
1434 GST_host_list[peer2_host_id])))
1436 LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, p2);
1437 focc = GNUNET_new (struct ForwardedOverlayConnectContext);
1441 focc->peer2_host_id = peer2_host_id;
1442 focc->orig_msg = GNUNET_copy_message (&msg->header);
1443 focc->operation_id = op_id;
1444 focc->client = client;
1445 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
1452 LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, p2);
1453 fopc = GNUNET_new (struct ForwardedOperationContext);
1454 fopc->client = client;
1455 fopc->operation_id = op_id;
1456 fopc->type = OP_OVERLAY_CONNECT;
1458 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1459 slave->controller, op_id,
1461 &GST_forwarded_operation_reply_relay,
1463 fopc->timeout_task =
1464 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1465 &GST_forwarded_operation_timeout,
1467 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
1474 * Callback called when a connection to the controller of peer2 has been
1477 * @param cls the overlay connect contexts
1478 * @param c handle to the controller connection
1481 p2_controller_connect_cb (void *cls,
1482 struct GNUNET_TESTBED_Controller *c)
1484 struct OverlayConnectContext *occ = cls;
1485 struct RemotePeer2Context *rp2c;
1486 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1488 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1489 rp2c = &occ->p2ctx.remote;
1493 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1495 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
1496 cmsg.peer_id = htonl (occ->other_peer_id);
1497 cmsg.operation_id = GNUNET_htonll (occ->op_id);
1499 GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
1502 &overlay_connect_get_config,
1504 GNUNET_free_non_null (occ->emsg);
1505 GNUNET_asprintf (&occ->emsg,
1506 "0x%llx: Timeout while getting peer identity of peer "
1509 occ->other_peer_id);
1514 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages
1516 * @param cls identification of the client
1517 * @param msg the actual message
1520 handle_overlay_connect (void *cls,
1521 const struct GNUNET_TESTBED_OverlayConnectMessage *msg)
1523 struct GNUNET_SERVICE_Client *client = cls;
1526 struct OverlayConnectContext *occ;
1527 struct Neighbour *p2n;
1528 uint64_t operation_id;
1531 uint32_t peer2_host_id;
1533 p1 = ntohl (msg->peer1);
1534 p2 = ntohl (msg->peer2);
1535 if (! VALID_PEER_ID (p1))
1538 GNUNET_SERVICE_client_drop (client);
1541 peer = GST_peer_list[p1];
1542 operation_id = GNUNET_ntohll (msg->operation_id);
1544 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n",
1548 peer2_host_id = ntohl (msg->peer2_host_id);
1549 if (GNUNET_YES == peer->is_remote)
1551 if (! VALID_HOST_ID (peer2_host_id))
1554 GNUNET_SERVICE_client_drop (client);
1557 forward_overlay_connect (msg, client);
1558 GNUNET_SERVICE_client_continue (client);
1562 occ = GNUNET_new (struct OverlayConnectContext);
1563 occ->type = OCC_TYPE_LOCAL;
1564 if (! VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */
1566 if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1568 if (! VALID_HOST_ID (peer2_host_id))
1571 LOG (GNUNET_ERROR_TYPE_WARNING,
1572 "0x%llx: Peer %u's host not in our neighbours list\n",
1574 GNUNET_SERVICE_client_drop (client);
1578 p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
1580 occ->type = OCC_TYPE_REMOTE_LATERAL;
1581 occ->p2ctx.remote.p2n = p2n;
1583 else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1585 occ->type = OCC_TYPE_REMOTE_SLAVE;
1586 occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
1588 GNUNET_CONTAINER_DLL_insert_tail (occq_head,
1591 occ->client = client;
1592 occ->other_peer_id = p2;
1593 GST_peer_list[p1]->reference_cnt++;
1594 occ->peer = GST_peer_list[p1];
1595 occ->op_id = operation_id;
1596 GNUNET_assert (NULL == occ->timeout_task);
1598 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1599 &timeout_overlay_connect,
1603 case OCC_TYPE_REMOTE_LATERAL:
1604 GNUNET_asprintf (&occ->emsg,
1605 "0x%llx: Timeout while acquiring connection to peer %u's "
1610 occ->p2ctx.remote.ncn
1611 = GST_neighbour_get_connection (p2n,
1612 &p2_controller_connect_cb,
1615 case OCC_TYPE_REMOTE_SLAVE:
1616 p2_controller_connect_cb (occ,
1617 occ->p2ctx.remote.p2c);
1619 case OCC_TYPE_LOCAL:
1620 peer2 = GST_peer_list[occ->other_peer_id];
1621 peer2->reference_cnt++;
1622 GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
1623 &occ->other_peer_identity);
1624 GNUNET_asprintf (&occ->emsg,
1625 "0x%llx: Timeout while connecting to CORE of peer with "
1630 GST_connection_pool_get_handle (occ->peer->id,
1631 occ->peer->details.local.cfg,
1632 GST_CONNECTIONPOOL_SERVICE_CORE,
1633 occ_cache_get_handle_core_cb, occ,
1634 &occ->other_peer_identity,
1635 &overlay_connect_notify, occ);
1638 GNUNET_SERVICE_client_continue (client);
1643 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1646 * @param rocc the RemoteOverlayConnectCtx
1649 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1651 LOG_DEBUG ("0x%llx: Cleaning up rocc\n",
1653 if (NULL != rocc->attempt_connect_task_id)
1654 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1655 if (NULL != rocc->timeout_rocc_task_id)
1656 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1657 if (NULL != rocc->ohh)
1658 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1659 if (NULL != rocc->tcc.csh)
1660 GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh);
1661 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th);
1662 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats);
1663 GNUNET_assert (rocc->peer->reference_cnt > 0);
1664 rocc->peer->reference_cnt--;
1665 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1666 (0 == rocc->peer->reference_cnt))
1667 GST_destroy_peer (rocc->peer);
1668 GNUNET_free_non_null (rocc->hello);
1669 GNUNET_CONTAINER_DLL_remove (roccq_head,
1677 * Task to timeout rocc and cleanit up
1679 * @param cls the RemoteOverlayConnectCtx
1682 timeout_rocc_task (void *cls)
1684 struct RemoteOverlayConnectCtx *rocc = cls;
1686 GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
1687 rocc->timeout_rocc_task_id = NULL;
1688 LOG_DEBUG ("0x%llx: rocc timed out\n",
1690 cleanup_rocc (rocc);
1695 * Function called to notify transport users that another
1696 * peer connected to us.
1698 * @param cls the RemoteOverlayConnectContext
1699 * @param new_peer the peer that connected
1702 cache_transport_peer_connect_notify (void *cls,
1703 const struct GNUNET_PeerIdentity *new_peer)
1705 struct RemoteOverlayConnectCtx *rocc = cls;
1707 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n",
1710 memcmp (new_peer, &rocc->a_id,
1711 sizeof (struct GNUNET_PeerIdentity)));
1712 LOG_DEBUG ("0x%llx: Peer %s connected\n",
1714 GNUNET_i2s (&rocc->a_id));
1715 cleanup_rocc (rocc);
1720 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1721 * whose identity is in RemoteOverlayConnectCtx
1723 * @param cls the RemoteOverlayConnectCtx
1726 attempt_connect_task (void *cls);
1730 * Task that is run when hello has been sent If tc->reason =
1731 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1732 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1734 * @param cls the overlay connect context
1737 rocc_hello_sent_cb (void *cls)
1739 struct RemoteOverlayConnectCtx *rocc = cls;
1742 GNUNET_assert (NULL == rocc->attempt_connect_task_id);
1743 LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n",
1745 GNUNET_i2s (&rocc->a_id),
1747 rocc->tcc.cgh_p2_ats =
1748 GST_connection_pool_get_handle (rocc->peer->id,
1749 rocc->peer->details.local.cfg,
1750 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
1751 &occ_cache_get_handle_ats_rocc_cb,
1752 rocc, NULL, NULL, NULL);
1757 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1758 * whose identity is in RemoteOverlayConnectCtx
1760 * @param cls the RemoteOverlayConnectCtx
1763 attempt_connect_task (void *cls)
1765 struct RemoteOverlayConnectCtx *rocc = cls;
1767 GNUNET_assert (NULL != rocc->attempt_connect_task_id);
1768 rocc->attempt_connect_task_id = NULL;
1769 LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n",
1771 GNUNET_i2s (&rocc->a_id),
1774 GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg,
1776 &rocc_hello_sent_cb,
1778 if (NULL == rocc->ohh)
1779 rocc->attempt_connect_task_id =
1780 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1781 (GNUNET_TIME_UNIT_MILLISECONDS,
1783 GNUNET_CRYPTO_random_u32
1784 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1785 &attempt_connect_task, rocc);
1790 * Callback from cache with needed handles set
1792 * @param cls the closure passed to GST_cache_get_handle_transport()
1793 * @param ch the handle to CORE. Can be NULL if it is not requested
1794 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1795 * @param ac the handle to ATS. Can be NULL if it is not requested
1796 * @param ignore_ peer identity which is ignored in this callback
1799 rocc_cache_get_handle_transport_cb (void *cls,
1800 struct GNUNET_CORE_Handle *ch,
1801 struct GNUNET_TRANSPORT_CoreHandle *th,
1802 struct GNUNET_ATS_ConnectivityHandle *ac,
1803 const struct GNUNET_PeerIdentity *ignore_,
1804 const struct GNUNET_CONFIGURATION_Handle *cfg)
1806 struct RemoteOverlayConnectCtx *rocc = cls;
1810 rocc->timeout_rocc_task_id =
1811 GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1815 rocc->tcc.cfg = cfg;
1817 GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_,
1820 LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n",
1822 GNUNET_i2s (&rocc->a_id),
1824 cleanup_rocc (rocc);
1827 rocc->attempt_connect_task_id =
1828 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1833 * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
1835 * @param cls identification of the client
1836 * @param msg the actual message
1837 * @return #GNUNET_OK if @a msg is well-formed
1840 check_remote_overlay_connect (void *cls,
1841 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
1847 msize = ntohs (msg->header.size);
1848 if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))
1851 return GNUNET_SYSERR;
1853 hsize = ntohs (msg->hello->size);
1854 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) != msize)
1857 return GNUNET_SYSERR;
1859 peer_id = ntohl (msg->peer);
1860 if ((peer_id >= GST_peer_list_size) ||
1861 (NULL == GST_peer_list[peer_id]))
1863 GNUNET_break_op (0);
1864 return GNUNET_SYSERR;
1871 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
1873 * @param cls identification of the client
1874 * @param msg the actual message
1877 handle_remote_overlay_connect (void *cls,
1878 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
1880 struct GNUNET_SERVICE_Client *client = cls;
1881 struct RemoteOverlayConnectCtx *rocc;
1883 struct GNUNET_PeerIdentity pid;
1884 static char pid_str[16];
1888 hsize = ntohs (msg->hello->size);
1889 peer_id = ntohl (msg->peer);
1890 peer = GST_peer_list[peer_id];
1891 if (GNUNET_YES == peer->is_remote)
1893 struct GNUNET_MessageHeader *msg2;
1895 msg2 = GNUNET_copy_message (&msg->header);
1896 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1898 GNUNET_SERVICE_client_continue (client);
1901 rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
1902 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1903 GNUNET_CONTAINER_DLL_insert_tail (roccq_head,
1906 rocc->a_id = msg->peer_identity;
1907 GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
1909 (void) strncpy (pid_str,
1912 LOG_DEBUG ("0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n",
1915 GNUNET_i2s (&rocc->a_id),
1918 rocc->peer->reference_cnt++;
1919 rocc->hello = GNUNET_malloc (hsize);
1920 GNUNET_memcpy (rocc->hello,
1923 rocc->tcc.cgh_p2_th =
1924 GST_connection_pool_get_handle (peer_id,
1925 rocc->peer->details.local.cfg,
1926 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1927 &rocc_cache_get_handle_transport_cb,
1930 &cache_transport_peer_connect_notify,
1932 rocc->timeout_rocc_task_id =
1933 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1936 GNUNET_SERVICE_client_continue (client);
1941 * Clears all pending overlay connect contexts in queue
1946 struct OverlayConnectContext *occ;
1948 while (NULL != (occ = occq_head))
1954 * Clears all pending remote overlay connect contexts in queue
1959 struct RemoteOverlayConnectCtx *rocc;
1961 while (NULL != (rocc = roccq_head))
1962 cleanup_rocc (rocc);