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
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file testbed/gnunet-service-testbed_oc.c
23 * @brief code for handling overlay connect operations
24 * @author Sree Harsha Totakura
27 #include "gnunet-service-testbed.h"
28 #include "gnunet-service-testbed_connectionpool.h"
29 #include "gnunet_transport_hello_service.h"
32 * Redefine LOG with a changed log component string
37 #define LOG(kind,...) \
38 GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__)
42 * Context information for requesting ATS to connect to a peer
44 struct ConnectivitySuggestContext
48 * The transport handle obtained from cache. Do NOT close/disconnect.
50 struct GNUNET_TRANSPORT_CoreHandle *th_;
53 * Configuration of the peer from cache. Do not free!
55 const struct GNUNET_CONFIGURATION_Handle *cfg;
58 * The GetCacheHandle for the peer2's transport handle
59 * (used to offer the HELLO to the peer).
61 struct GST_ConnectionPool_GetHandle *cgh_p2_th;
64 * The GetCacheHandle for the peer2's ATS handle.
66 struct GST_ConnectionPool_GetHandle *cgh_p2_ats;
69 * The ATS handle for the connectivity suggestion.
71 struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
77 * Types for context information we create for overlay connect requests
79 enum OverlayConnectContextType
82 * This type is used if the overlay connection is local i.e. the connection
83 * has to be made between local peers
88 * Type to be used when the first peer is local and the other peer is on a slave
89 * controller started by us
91 OCC_TYPE_REMOTE_SLAVE,
94 * Type to be used when the first peer is local and the other peer is on a
95 * controller which is not started by us.
97 OCC_TYPE_REMOTE_LATERAL
102 * Context data for operations on second peer in local overlay connection
105 struct LocalPeer2Context
108 * The handle for offering the HELLO of the first peer to the second
111 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
114 * The transport ConnectivitySuggestContext
116 struct ConnectivitySuggestContext tcc;
121 * Context data for operations on second peer in remote overlay connection
124 struct RemotePeer2Context
127 * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay
128 * connection then this can be NULL until the connection to the controller is
131 struct GNUNET_TESTBED_Controller *p2c;
134 * Operation context for the suboperation we start to get the identity of the
137 struct OperationContext *opc;
140 * Notification handle acquire to connect to a remote controller. Only used
141 * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL.
143 struct NeighbourConnectNotification *ncn;
146 * The neighbour handle. Only used if the type of overlay connection is
147 * #OCC_TYPE_REMOTE_LATERAL.
149 struct Neighbour *p2n;
153 * Context information for connecting 2 peers in overlay.
155 struct OverlayConnectContext
158 * The next pointer for maintaining a DLL of all OverlayConnectContexts
160 struct OverlayConnectContext *next;
163 * The prev pointer for maintaining a DLL of all OverlayConnectContexts
165 struct OverlayConnectContext *prev;
168 * The client which has requested for overlay connection. This is used to send
169 * either a success of failure message
171 struct GNUNET_SERVER_Client *client;
174 * the first peer which is to expect an overlay connection from the second peer.
179 * Transport handle of the first peer obtained from cache to get its HELLO. Do
180 * NOT close/disconnect.
182 struct GNUNET_TRANSPORT_CoreHandle *p1th_;
185 * The #GST_ConnectionPool_GetHandle for the peer1's transport handle
187 struct GST_ConnectionPool_GetHandle *cgh_p1th;
190 * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE
191 * level peer connects and to get our identity.
193 struct GST_ConnectionPool_GetHandle *cgh_ch;
196 * HELLO of the first peer. This should be sent to the second peer.
198 struct GNUNET_MessageHeader *hello;
201 * Get GetHelloHandle to acquire a HELLO of the first peer
203 struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
206 * The error message we send if this overlay connect operation has timed out
211 * Context information for operations on the second peer
216 * Context information to be used if the second peer is local
218 struct LocalPeer2Context local;
221 * Context information to be used if the second peer is remote
223 struct RemotePeer2Context remote;
228 * The peer identity of the first peer
230 struct GNUNET_PeerIdentity peer_identity;
233 * The peer identity of the other peer
235 struct GNUNET_PeerIdentity other_peer_identity;
238 * The id of the operation responsible for creating this context
243 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
246 struct GNUNET_SCHEDULER_Task *send_hello_task;
249 * The id of the overlay connect timeout task
251 struct GNUNET_SCHEDULER_Task *timeout_task;
254 * The id of the cleanup task
256 struct GNUNET_SCHEDULER_Task *cleanup_task;
259 * The type of this context information
261 enum OverlayConnectContextType type;
264 * The id of the second peer which is has to connect to the first peer
266 uint32_t other_peer_id;
271 * Context information for remote overlay connect operations. Remote overlay
272 * connections are used when peers A and B reside on different hosts. In these
273 * operations the host controller for peer B is asked by the host controller of
274 * peer A to make peer B connect to peer A by sending the controller of peer B
275 * the HELLO of peer A.
277 struct RemoteOverlayConnectCtx
280 * the next pointer for DLL
282 struct RemoteOverlayConnectCtx *next;
285 * the prev pointer for DLL
287 struct RemoteOverlayConnectCtx *prev;
290 * The peer handle of peer B
297 struct GNUNET_MessageHeader *hello;
300 * The handle for offering HELLO
302 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
305 * The transport try connect context
307 struct ConnectivitySuggestContext tcc;
310 * The peer identity of peer A
312 struct GNUNET_PeerIdentity a_id;
315 * Task for offering HELLO of A to B and doing try_connect
317 struct GNUNET_SCHEDULER_Task *attempt_connect_task_id;
320 * Task to timeout RequestOverlayConnect
322 struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id;
325 * The id of the operation responsible for creating this context
332 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
334 static struct OverlayConnectContext *occq_head;
337 * DLL tail for OverlayConnectContext DLL
339 static struct OverlayConnectContext *occq_tail;
342 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
345 static struct RemoteOverlayConnectCtx *roccq_head;
348 * DLL tail for RequectOverlayConnectContext DLL
350 static struct RemoteOverlayConnectCtx *roccq_tail;
354 * Cleans up ForwardedOverlayConnectContext
356 * @param focc the ForwardedOverlayConnectContext to cleanup
359 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
361 GNUNET_SERVER_client_drop (focc->client);
362 GNUNET_free_non_null (focc->orig_msg);
368 * Timeout task for cancelling a forwarded overlay connect connect
370 * @param cls the ForwardedOverlayConnectContext
373 forwarded_overlay_connect_timeout (void *cls)
375 struct ForwardedOperationContext *fopc = cls;
376 struct RegisteredHostContext *rhc;
377 struct ForwardedOverlayConnectContext *focc;
380 focc = rhc->focc_dll_head;
381 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
382 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1,
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 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
411 GST_cleanup_focc (focc);
412 if (NULL != rhc->focc_dll_head)
413 GST_process_next_focc (rhc);
418 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
420 * @param rhc the RegisteredHostContext
423 GST_process_next_focc (struct RegisteredHostContext *rhc)
425 struct ForwardedOperationContext *fopc;
426 struct ForwardedOverlayConnectContext *focc;
430 focc = rhc->focc_dll_head;
431 GNUNET_assert (NULL != focc);
432 GNUNET_assert (RHC_DONE == rhc->state);
433 GNUNET_assert (VALID_PEER_ID (focc->peer1));
434 peer = GST_peer_list[focc->peer1];
435 GNUNET_assert (GNUNET_YES == peer->is_remote);
436 GNUNET_assert (NULL != (slave = peer->details.remote.slave));
437 fopc = GNUNET_new (struct ForwardedOperationContext);
438 GNUNET_SERVER_client_keep (focc->client);
439 fopc->client = focc->client;
440 fopc->operation_id = focc->operation_id;
442 fopc->type = OP_OVERLAY_CONNECT;
444 GNUNET_TESTBED_forward_operation_msg_ (slave->controller,
445 focc->operation_id, focc->orig_msg,
446 &forwarded_overlay_connect_listener,
448 GNUNET_free (focc->orig_msg);
449 focc->orig_msg = NULL;
451 GNUNET_SCHEDULER_add_delayed (GST_timeout, &forwarded_overlay_connect_timeout,
453 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
458 * Cleans up any used handles in local peer2 context
460 * @param lp2c the local peer2 context information
463 cleanup_occ_lp2c (struct LocalPeer2Context *lp2c)
465 if (NULL != lp2c->ohh)
467 GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh);
470 if (NULL != lp2c->tcc.cgh_p2_th)
472 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th);
473 lp2c->tcc.cgh_p2_th = NULL;
475 if (NULL != lp2c->tcc.cgh_p2_ats)
477 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats);
478 lp2c->tcc.cgh_p2_ats = NULL;
480 if (NULL != lp2c->tcc.csh)
482 GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh);
483 lp2c->tcc.csh = NULL;
489 * Cleans up any used handles in remote peer2 context. Relinquishes the
490 * remote controller connection if it has been established on-demand.
492 * @param rp2c the remote peer2 context information
495 cleanup_occ_rp2c (struct RemotePeer2Context *rp2c)
497 if (NULL != rp2c->opc)
499 GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc);
502 if (NULL != rp2c->ncn)
504 GST_neighbour_get_connection_cancel (rp2c->ncn);
507 if ( (NULL != rp2c->p2c) && (NULL != rp2c->p2n) )
509 GST_neighbour_release_connection (rp2c->p2n);
515 * Condition for checking if given peer is ready to be destroyed
517 * @param peer the peer to check
519 #define PEER_EXPIRED(peer) \
520 ( (GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt) )
523 * Cleanup overlay connect context structure
525 * @param occ the overlay connect context
528 cleanup_occ (struct OverlayConnectContext *occ)
532 LOG_DEBUG ("0x%llx: Cleaning up occ\n",
534 GNUNET_free_non_null (occ->emsg);
535 GNUNET_free_non_null (occ->hello);
536 GNUNET_SERVER_client_drop (occ->client);
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,
616 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
618 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
620 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
622 msg = GNUNET_new (struct GNUNET_TESTBED_ConnectionEventMessage);
624 htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
625 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
626 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
627 msg->peer1 = htonl (occ->peer->id);
628 msg->peer2 = htonl (occ->other_peer_id);
629 msg->operation_id = GNUNET_htonll (occ->op_id);
630 GST_queue_message (occ->client, &msg->header);
635 * Function called to notify transport users that another
636 * peer connected to us.
639 * @param new_peer the peer that connected
642 overlay_connect_notify (void *cls,
643 const struct GNUNET_PeerIdentity *new_peer)
645 struct OverlayConnectContext *occ = cls;
647 char *other_peer_str;
649 LOG_DEBUG ("Overlay connect notify\n");
651 memcmp (new_peer, &occ->peer_identity,
652 sizeof (struct GNUNET_PeerIdentity)))
654 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
655 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
658 &occ->other_peer_identity,
659 sizeof (struct GNUNET_PeerIdentity)))
661 LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n",
664 GNUNET_free (new_peer_str);
665 GNUNET_free (other_peer_str);
668 GNUNET_free (new_peer_str);
669 LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n",
672 GNUNET_i2s (&occ->peer_identity));
673 GNUNET_free (other_peer_str);
674 if (NULL != occ->send_hello_task)
676 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
677 occ->send_hello_task = NULL;
679 GNUNET_assert (NULL != occ->timeout_task);
680 GNUNET_SCHEDULER_cancel (occ->timeout_task);
681 occ->timeout_task = NULL;
685 cleanup_occ_lp2c (&occ->p2ctx.local);
687 case OCC_TYPE_REMOTE_SLAVE:
688 case OCC_TYPE_REMOTE_LATERAL:
689 cleanup_occ_rp2c (&occ->p2ctx.remote);
692 GNUNET_free_non_null (occ->emsg);
694 send_overlay_connect_success_msg (occ);
695 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ,
701 * Callback from cache with needed ATS handle set
703 * @param cls a `struct OverlayConnectCtx *`
704 * @param ch the handle to CORE. Can be NULL if it is not requested
705 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
706 * @param ac the handle to ATS. Can be NULL if it is not requested
707 * @param my_identity the identity of our peer
708 * @param cfg configuration of the peer
711 occ_cache_get_handle_ats_occ_cb (void *cls,
712 struct GNUNET_CORE_Handle *ch,
713 struct GNUNET_TRANSPORT_CoreHandle *th,
714 struct GNUNET_ATS_ConnectivityHandle *ac,
715 const struct GNUNET_PeerIdentity *my_identity,
716 const struct GNUNET_CONFIGURATION_Handle *cfg)
718 struct OverlayConnectContext *occ = cls;
719 struct LocalPeer2Context *lp2c;
721 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
722 GNUNET_assert (NULL != occ->timeout_task);
723 GNUNET_free_non_null (occ->emsg);
726 GNUNET_asprintf (&occ->emsg,
727 "0x%llx: Failed to connect to ATS of peer with id: %u",
730 GNUNET_SCHEDULER_cancel (occ->timeout_task);
732 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect,
738 GNUNET_asprintf (&occ->emsg,
739 "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s",
741 GNUNET_i2s (&occ->other_peer_identity));
743 lp2c = &occ->p2ctx.local;
745 GNUNET_ATS_connectivity_suggest (ac,
752 * Callback from cache with needed ATS handle set
754 * @param cls a `struct RemoteOverlayConnectCtx *`
755 * @param ch the handle to CORE. Can be NULL if it is not requested
756 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
757 * @param ac the handle to ATS. Can be NULL if it is not requested
758 * @param my_identity the identity of our peer
761 occ_cache_get_handle_ats_rocc_cb (void *cls,
762 struct GNUNET_CORE_Handle *ch,
763 struct GNUNET_TRANSPORT_CoreHandle *th,
764 struct GNUNET_ATS_ConnectivityHandle *ac,
765 const struct GNUNET_PeerIdentity *my_identity,
766 const struct GNUNET_CONFIGURATION_Handle *cfg)
768 struct RemoteOverlayConnectCtx *rocc = cls;
771 GNUNET_ATS_connectivity_suggest (ac,
778 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
781 * @param cls the OverlayConnectContext
784 send_hello (void *cls);
788 * Task that is run when hello has been sent If tc->reason =
789 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
790 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
792 * @param cls the overlay connect context
795 occ_hello_sent_cb (void *cls)
797 struct OverlayConnectContext *occ = cls;
798 struct LocalPeer2Context *lp2c;
801 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
802 GNUNET_assert (NULL != occ->timeout_task);
803 lp2c = &occ->p2ctx.local;
806 GNUNET_assert (NULL == occ->send_hello_task);
807 GNUNET_free_non_null (occ->emsg);
809 GNUNET_asprintf (&occ->emsg,
810 "0x%llx: Timeout while acquiring ATS of %s from cache",
812 GNUNET_i2s (&occ->other_peer_identity));
813 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
814 lp2c->tcc.cgh_p2_ats =
815 GST_connection_pool_get_handle (occ->other_peer_id,
816 peer2->details.local.cfg,
817 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
818 &occ_cache_get_handle_ats_occ_cb,
819 occ, NULL, NULL, NULL);
824 * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
827 * @param occ the overlay connect context. Its type must be either
828 * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL
831 send_hello_thru_rocc (struct OverlayConnectContext *occ)
833 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
834 char *other_peer_str;
838 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
839 GNUNET_assert (NULL != occ->hello);
840 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
841 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n",
843 GNUNET_i2s (&occ->peer_identity),
844 ntohs (occ->hello->size),
846 GNUNET_free (other_peer_str);
847 hello_size = ntohs (occ->hello->size);
848 msize = sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
849 msg = GNUNET_malloc (msize);
851 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
852 msg->header.size = htons (msize);
853 msg->peer = htonl (occ->other_peer_id);
854 msg->operation_id = GNUNET_htonll (occ->op_id);
855 msg->peer_identity = occ->peer_identity;
856 GNUNET_memcpy (msg->hello,
859 GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c,
865 * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered
866 * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
867 * send_hello_thru_rocc()
869 * @param cls the OverlayConnectContext
872 send_hello (void *cls)
874 struct OverlayConnectContext *occ = cls;
875 struct LocalPeer2Context *lp2c;
876 char *other_peer_str;
878 occ->send_hello_task = NULL;
879 GNUNET_assert (NULL != occ->timeout_task);
880 GNUNET_assert (NULL != occ->hello);
881 if (OCC_TYPE_LOCAL != occ->type)
883 send_hello_thru_rocc (occ);
886 lp2c = &occ->p2ctx.local;
887 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
888 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n",
890 GNUNET_i2s (&occ->peer_identity),
892 GNUNET_free (other_peer_str);
894 GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg,
898 if (NULL == lp2c->ohh)
901 occ->send_hello_task =
902 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
903 (GNUNET_TIME_UNIT_MILLISECONDS,
905 GNUNET_CRYPTO_random_u32
906 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
913 * Callback from cache with needed handles set
915 * @param cls the closure passed to GST_cache_get_handle_transport()
916 * @param ch the handle to CORE. Can be NULL if it is not requested
917 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
918 * @param ac the handle to ATS. Can be NULL if it is not requested
919 * @param ignore_ peer identity which is ignored in this callback
920 * @param cfg configuration of the peer
923 p2_transport_connect_cache_callback (void *cls,
924 struct GNUNET_CORE_Handle *ch,
925 struct GNUNET_TRANSPORT_CoreHandle *th,
926 struct GNUNET_ATS_ConnectivityHandle *ac,
927 const struct GNUNET_PeerIdentity *ignore_,
928 const struct GNUNET_CONFIGURATION_Handle *cfg)
930 struct OverlayConnectContext *occ = cls;
932 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
935 GNUNET_asprintf (&occ->emsg,
936 "0x%llx: Cannot connect to TRANSPORT of %s",
938 GNUNET_i2s (&occ->other_peer_identity));
939 GNUNET_SCHEDULER_cancel (occ->timeout_task);
941 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
944 occ->p2ctx.local.tcc.th_ = th;
945 occ->p2ctx.local.tcc.cfg = cfg;
946 GNUNET_asprintf (&occ->emsg,
947 "0x%llx: Timeout while offering HELLO to %s",
949 GNUNET_i2s (&occ->other_peer_identity));
950 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
955 * Connects to the transport of the other peer if it is a local peer and
956 * schedules the send hello task
958 * @param occ the overlay connect context
961 p2_transport_connect (struct OverlayConnectContext *occ)
965 GNUNET_assert (NULL == occ->emsg);
966 GNUNET_assert (NULL != occ->hello);
967 GNUNET_assert (NULL == occ->ghh);
968 GNUNET_assert (NULL == occ->p1th_);
969 GNUNET_assert (NULL == occ->cgh_p1th);
970 if (OCC_TYPE_LOCAL == occ->type)
972 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
973 occ->p2ctx.local.tcc.cgh_p2_th =
974 GST_connection_pool_get_handle (occ->other_peer_id,
975 peer2->details.local.cfg,
976 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
977 &p2_transport_connect_cache_callback,
978 occ, NULL, NULL, NULL);
981 GNUNET_asprintf (&occ->emsg,
982 "0x%llx: Timeout while offering HELLO to %s",
984 GNUNET_i2s (&occ->other_peer_identity));
985 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
990 * Test for checking whether HELLO message is empty
992 * @param cls empty flag to set
993 * @param address the HELLO
994 * @param expiration expiration of the HELLO
998 test_address (void *cls,
999 const struct GNUNET_HELLO_Address *address,
1000 struct GNUNET_TIME_Absolute expiration)
1010 * Function called whenever there is an update to the HELLO of peers in the
1011 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
1012 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
1014 * @param cls closure
1015 * @param hello our updated HELLO
1018 hello_update_cb (void *cls,
1019 const struct GNUNET_MessageHeader *hello)
1021 struct OverlayConnectContext *occ = cls;
1025 msize = ntohs (hello->size);
1027 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
1031 if (GNUNET_YES == empty)
1033 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n",
1035 GNUNET_i2s (&occ->peer_identity));
1038 LOG_DEBUG ("0x%llx: Received HELLO of %s\n",
1040 GNUNET_i2s (&occ->peer_identity));
1041 occ->hello = GNUNET_malloc (msize);
1042 GST_cache_add_hello (occ->peer->id, hello);
1043 GNUNET_memcpy (occ->hello, hello, msize);
1044 GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
1046 GST_connection_pool_get_handle_done (occ->cgh_p1th);
1047 occ->cgh_p1th = NULL;
1049 GNUNET_free_non_null (occ->emsg);
1051 p2_transport_connect (occ);
1056 * Callback from cache with needed handles set
1058 * @param cls the closure passed to GST_cache_get_handle_transport()
1059 * @param ch the handle to CORE. Can be NULL if it is not requested
1060 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1061 * @param ac the handle to ATS. Can be NULL if it is not requested
1062 * @param ignore_ peer identity which is ignored in this callback
1065 p1_transport_connect_cache_callback (void *cls,
1066 struct GNUNET_CORE_Handle *ch,
1067 struct GNUNET_TRANSPORT_CoreHandle *th,
1068 struct GNUNET_ATS_ConnectivityHandle *ac,
1069 const struct GNUNET_PeerIdentity *ignore_,
1070 const struct GNUNET_CONFIGURATION_Handle *cfg)
1072 struct OverlayConnectContext *occ = cls;
1074 GNUNET_free_non_null (occ->emsg);
1078 GNUNET_asprintf (&occ->emsg,
1079 "0x%llx: Cannot connect to TRANSPORT of %s",
1081 GNUNET_i2s (&occ->peer_identity));
1082 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1084 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1087 GNUNET_assert (NULL == occ->p1th_);
1088 GNUNET_assert (NULL != occ->cgh_p1th);
1090 GNUNET_asprintf (&occ->emsg,
1091 "0x%llx: Timeout while acquiring HELLO of peer %s",
1093 GNUNET_i2s (&occ->peer_identity));
1094 occ->ghh = GNUNET_TRANSPORT_hello_get (cfg,
1095 GNUNET_TRANSPORT_AC_ANY,
1102 * Callback from cache with needed CORE handle set
1104 * @param cls the closure passed to GST_cache_get_handle_transport()
1105 * @param ch the handle to CORE. Can be NULL if it is not requested
1106 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1107 * @param ac the handle to ATS. Can be NULL if it is not requested
1108 * @param my_identity the identity of our peer
1111 occ_cache_get_handle_core_cb (void *cls,
1112 struct GNUNET_CORE_Handle *ch,
1113 struct GNUNET_TRANSPORT_CoreHandle *th,
1114 struct GNUNET_ATS_ConnectivityHandle *ac,
1115 const struct GNUNET_PeerIdentity *my_identity,
1116 const struct GNUNET_CONFIGURATION_Handle *cfg)
1118 struct OverlayConnectContext *occ = cls;
1119 const struct GNUNET_MessageHeader *hello;
1121 GNUNET_assert (NULL != occ->timeout_task);
1122 GNUNET_free_non_null (occ->emsg);
1123 if ((NULL == ch) || (NULL == my_identity))
1125 GNUNET_asprintf (&occ->emsg,
1126 "0x%llx: Failed to connect to CORE of peer with "
1130 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1132 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1137 GNUNET_CORE_get_mq (ch,
1138 &occ->other_peer_identity))
1140 LOG_DEBUG ("0x%llx: Target peer already connected\n",
1142 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1143 occ->timeout_task = NULL;
1144 send_overlay_connect_success_msg (occ);
1145 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
1148 occ->peer_identity = *my_identity;
1149 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n",
1151 GNUNET_i2s (&occ->peer_identity));
1152 /* Lookup for HELLO in hello cache */
1153 if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
1155 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n",
1157 GNUNET_i2s (&occ->peer_identity));
1158 occ->hello = GNUNET_copy_message (hello);
1159 p2_transport_connect (occ);
1162 GNUNET_asprintf (&occ->emsg,
1163 "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
1165 GNUNET_i2s (&occ->peer_identity));
1167 GST_connection_pool_get_handle (occ->peer->id,
1168 occ->peer->details.local.cfg,
1169 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1170 p1_transport_connect_cache_callback,
1177 * Callback to be called when forwarded get peer config operation as part of
1178 * overlay connect is successfull. Connection to Peer 1's core is made and is
1179 * checked for new connection from peer 2
1181 * @param cls ForwardedOperationContext
1182 * @param msg the peer create success message
1185 overlay_connect_get_config (void *cls,
1186 const struct GNUNET_MessageHeader *msg)
1188 struct OverlayConnectContext *occ = cls;
1189 struct RemotePeer2Context *rp2c;
1190 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
1192 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1193 rp2c = &occ->p2ctx.remote;
1195 GNUNET_assert (NULL != occ->timeout_task);
1196 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
1198 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1200 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1203 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1204 occ->other_peer_identity = cmsg->peer_identity;
1205 GNUNET_free_non_null (occ->emsg);
1206 GNUNET_asprintf (&occ->emsg,
1207 "0x%llx: Timeout while connecting to CORE of peer with "
1212 GST_connection_pool_get_handle (occ->peer->id,
1213 occ->peer->details.local.cfg,
1214 GST_CONNECTIONPOOL_SERVICE_CORE,
1215 occ_cache_get_handle_core_cb,
1217 &occ->other_peer_identity,
1218 &overlay_connect_notify,
1225 * Callback which will be called after a host registration succeeded or failed
1227 * @param cls the RegisteredHostContext
1228 * @param emsg the error message; NULL if host registration is successful
1231 host_registration_comp (void *cls, const char *emsg)
1233 struct RegisteredHostContext *rhc = cls;
1235 rhc->state = RHC_DONE;
1236 GST_process_next_focc (rhc);
1241 * Iterator to match a registered host context
1243 * @param cls pointer 2 pointer of RegisteredHostContext
1244 * @param key current key code
1245 * @param value value in the hash map
1246 * @return #GNUNET_YES if we should continue to
1248 * #GNUNET_NO if not.
1251 reghost_match_iterator (void *cls,
1252 const struct GNUNET_HashCode *key,
1255 struct RegisteredHostContext **rh = cls;
1256 struct RegisteredHostContext *rh_val = value;
1258 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1269 * Function to generate the hashcode corresponding to a RegisteredHostContext
1271 * @param reg_host the host which is being registered in RegisteredHostContext
1272 * @param host the host of the controller which has to connect to the above rhost
1273 * @return the hashcode
1275 static struct GNUNET_HashCode
1276 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1277 struct GNUNET_TESTBED_Host *host)
1279 struct GNUNET_HashCode hash;
1280 uint32_t host_ids[2];
1282 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1283 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1284 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1290 * Checks if the given host is registered at the given slave.
1292 * @param slave the slave where registration has to be checked. The check is
1293 * actually done through a locally maintained hashmap. No
1294 * communication with the slave is involved.
1295 * @param host the host to register
1296 * @return If the given host is not registered already or the registration is
1297 * pending, it returns the registration context. Any overlay connects
1298 * to be forwarded should be queued in the context so that they can be
1299 * executed when the registration is completed. If the given host is
1300 * already registered, NULL is returned.
1302 static struct RegisteredHostContext *
1303 register_host (struct Slave *slave,
1304 struct GNUNET_TESTBED_Host *host)
1306 struct GNUNET_HashCode hash;
1307 struct RegisteredHostContext *rhc;
1309 rhc = GNUNET_new (struct RegisteredHostContext);
1310 rhc->reg_host = host;
1311 rhc->host = GST_host_list[slave->host_id];
1312 GNUNET_assert (NULL != rhc->reg_host);
1313 GNUNET_assert (NULL != rhc->host);
1314 rhc->state = RHC_INIT;
1315 hash = hash_hosts (rhc->reg_host, rhc->host);
1317 GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, &hash)) ||
1319 GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
1321 reghost_match_iterator,
1324 /* create and add a new registerd host context */
1325 /* add the focc to its queue */
1326 GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, &hash, rhc,
1327 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1328 GST_queue_host_registration (slave, host_registration_comp,
1329 rhc, rhc->reg_host);
1333 /* rhc is now set to the existing one from the hash map by
1334 * reghost_match_iterator() */
1335 /* if queue is empty then ignore creating focc and proceed with normal
1337 if (RHC_DONE == rhc->state)
1345 * Forwards the overlay connect request to a slave controller. Before
1346 * forwarding, any hosts which are needed to be known by the slave controller to
1347 * execute the overlay connect request are registered at slave.
1349 * @param msg the overlay connect request message to be forwarded
1350 * @param client the client to which the status of the forwarded request has to
1354 forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
1355 struct GNUNET_SERVER_Client *client)
1357 struct ForwardedOperationContext *fopc;
1358 struct Route *route_to_peer2_host;
1359 struct Route *route_to_peer1_host;
1361 struct RegisteredHostContext *rhc;
1362 struct ForwardedOverlayConnectContext *focc;
1364 uint32_t peer2_host_id;
1368 p1 = ntohl (msg->peer1);
1369 p2 = ntohl (msg->peer2);
1370 op_id = GNUNET_ntohll (msg->operation_id);
1371 peer2_host_id = ntohl (msg->peer2_host_id);
1372 GNUNET_assert (VALID_PEER_ID (p1));
1373 GNUNET_assert (VALID_HOST_ID (peer2_host_id));
1374 peer = GST_peer_list[p1];
1375 GNUNET_assert (GNUNET_YES == peer->is_remote);
1376 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
1377 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1378 route_to_peer1_host = GST_find_dest_route
1379 (peer->details.remote.remote_host_id);
1380 GNUNET_assert (NULL != route_to_peer1_host);
1381 if ((NULL != route_to_peer2_host) &&
1382 (route_to_peer1_host->dest == route_to_peer2_host->dest))
1384 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1385 different subtrees OR peer2 is on a subtree unknown to us */
1386 if (NULL != (rhc = register_host (peer->details.remote.slave,
1387 GST_host_list[peer2_host_id])))
1389 LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, p2);
1390 focc = GNUNET_new (struct ForwardedOverlayConnectContext);
1393 focc->peer2_host_id = peer2_host_id;
1394 focc->orig_msg = GNUNET_copy_message (&msg->header);
1395 focc->operation_id = op_id;
1396 focc->client = client;
1397 GNUNET_SERVER_client_keep (client);
1398 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, rhc->focc_dll_tail,
1404 LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, p2);
1405 fopc = GNUNET_new (struct ForwardedOperationContext);
1406 GNUNET_SERVER_client_keep (client);
1407 fopc->client = client;
1408 fopc->operation_id = op_id;
1409 fopc->type = OP_OVERLAY_CONNECT;
1411 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1412 slave->controller, op_id,
1414 &GST_forwarded_operation_reply_relay,
1416 fopc->timeout_task =
1417 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1418 &GST_forwarded_operation_timeout,
1420 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
1427 * Callback called when a connection to the controller of peer2 has been
1430 * @param cls the overlay connect contexts
1431 * @param c handle to the controller connection
1434 p2_controller_connect_cb (void *cls,
1435 struct GNUNET_TESTBED_Controller *c)
1437 struct OverlayConnectContext *occ = cls;
1438 struct RemotePeer2Context *rp2c;
1439 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1441 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1442 rp2c = &occ->p2ctx.remote;
1446 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1448 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
1449 cmsg.peer_id = htonl (occ->other_peer_id);
1450 cmsg.operation_id = GNUNET_htonll (occ->op_id);
1452 GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
1453 occ->op_id, &cmsg.header,
1454 &overlay_connect_get_config,
1456 GNUNET_free_non_null (occ->emsg);
1457 GNUNET_asprintf (&occ->emsg,
1458 "0x%llx: Timeout while getting peer identity of peer "
1461 occ->other_peer_id);
1466 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1469 * @param client identification of the client
1470 * @param message the actual message
1473 GST_handle_overlay_connect (void *cls,
1474 struct GNUNET_SERVER_Client *client,
1475 const struct GNUNET_MessageHeader *message)
1477 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1480 struct OverlayConnectContext *occ;
1481 struct Neighbour *p2n;
1482 uint64_t operation_id;
1485 uint32_t peer2_host_id;
1487 if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) !=
1488 ntohs (message->size))
1491 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1494 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1495 p1 = ntohl (msg->peer1);
1496 p2 = ntohl (msg->peer2);
1497 if (!VALID_PEER_ID (p1))
1500 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1503 peer = GST_peer_list[p1];
1504 operation_id = GNUNET_ntohll (msg->operation_id);
1506 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n",
1510 peer2_host_id = ntohl (msg->peer2_host_id);
1511 if (GNUNET_YES == peer->is_remote)
1513 if (! VALID_HOST_ID (peer2_host_id))
1516 GNUNET_SERVER_receive_done (client,
1520 forward_overlay_connect (msg, client);
1521 GNUNET_SERVER_receive_done (client,
1526 occ = GNUNET_new (struct OverlayConnectContext);
1527 occ->type = OCC_TYPE_LOCAL;
1528 if (!VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */
1530 if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1532 if (!VALID_HOST_ID (peer2_host_id))
1535 LOG (GNUNET_ERROR_TYPE_WARNING,
1536 "0x%llx: Peer %u's host not in our neighbours list\n",
1538 GNUNET_SERVER_receive_done (client,
1543 p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
1545 occ->type = OCC_TYPE_REMOTE_LATERAL;
1546 occ->p2ctx.remote.p2n = p2n;
1548 else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1550 occ->type = OCC_TYPE_REMOTE_SLAVE;
1551 occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
1553 GNUNET_CONTAINER_DLL_insert_tail (occq_head,
1556 GNUNET_SERVER_client_keep (client);
1557 occ->client = client;
1558 occ->other_peer_id = p2;
1559 GST_peer_list[p1]->reference_cnt++;
1560 occ->peer = GST_peer_list[p1];
1561 occ->op_id = operation_id;
1562 GNUNET_assert (NULL == occ->timeout_task);
1564 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1565 &timeout_overlay_connect,
1569 case OCC_TYPE_REMOTE_LATERAL:
1570 GNUNET_asprintf (&occ->emsg,
1571 "0x%llx: Timeout while acquiring connection to peer %u's "
1576 occ->p2ctx.remote.ncn =
1577 GST_neighbour_get_connection (p2n, &p2_controller_connect_cb, occ);
1579 case OCC_TYPE_REMOTE_SLAVE:
1580 p2_controller_connect_cb (occ, occ->p2ctx.remote.p2c);
1582 case OCC_TYPE_LOCAL:
1583 peer2 = GST_peer_list[occ->other_peer_id];
1584 peer2->reference_cnt++;
1585 GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
1586 &occ->other_peer_identity);
1587 GNUNET_asprintf (&occ->emsg,
1588 "0x%llx: Timeout while connecting to CORE of peer with "
1593 GST_connection_pool_get_handle (occ->peer->id,
1594 occ->peer->details.local.cfg,
1595 GST_CONNECTIONPOOL_SERVICE_CORE,
1596 occ_cache_get_handle_core_cb, occ,
1597 &occ->other_peer_identity,
1598 &overlay_connect_notify, occ);
1601 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1606 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1609 * @param rocc the RemoteOverlayConnectCtx
1612 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1614 LOG_DEBUG ("0x%llx: Cleaning up rocc\n",
1616 if (NULL != rocc->attempt_connect_task_id)
1617 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1618 if (NULL != rocc->timeout_rocc_task_id)
1619 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1620 if (NULL != rocc->ohh)
1621 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1622 if (NULL != rocc->tcc.csh)
1623 GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh);
1624 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th);
1625 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats);
1626 GNUNET_assert (rocc->peer->reference_cnt > 0);
1627 rocc->peer->reference_cnt--;
1628 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1629 (0 == rocc->peer->reference_cnt))
1630 GST_destroy_peer (rocc->peer);
1631 GNUNET_free_non_null (rocc->hello);
1632 GNUNET_CONTAINER_DLL_remove (roccq_head,
1640 * Task to timeout rocc and cleanit up
1642 * @param cls the RemoteOverlayConnectCtx
1645 timeout_rocc_task (void *cls)
1647 struct RemoteOverlayConnectCtx *rocc = cls;
1649 GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
1650 rocc->timeout_rocc_task_id = NULL;
1651 LOG_DEBUG ("0x%llx: rocc timed out\n",
1653 cleanup_rocc (rocc);
1658 * Function called to notify transport users that another
1659 * peer connected to us.
1661 * @param cls the RemoteOverlayConnectContext
1662 * @param new_peer the peer that connected
1665 cache_transport_peer_connect_notify (void *cls,
1666 const struct GNUNET_PeerIdentity *new_peer)
1668 struct RemoteOverlayConnectCtx *rocc = cls;
1670 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n",
1673 memcmp (new_peer, &rocc->a_id,
1674 sizeof (struct GNUNET_PeerIdentity)));
1675 LOG_DEBUG ("0x%llx: Peer %s connected\n",
1677 GNUNET_i2s (&rocc->a_id));
1678 cleanup_rocc (rocc);
1683 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1684 * whose identity is in RemoteOverlayConnectCtx
1686 * @param cls the RemoteOverlayConnectCtx
1689 attempt_connect_task (void *cls);
1693 * Task that is run when hello has been sent If tc->reason =
1694 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1695 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1697 * @param cls the overlay connect context
1700 rocc_hello_sent_cb (void *cls)
1702 struct RemoteOverlayConnectCtx *rocc = cls;
1705 GNUNET_assert (NULL == rocc->attempt_connect_task_id);
1706 LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n",
1708 GNUNET_i2s (&rocc->a_id),
1710 rocc->tcc.cgh_p2_ats =
1711 GST_connection_pool_get_handle (rocc->peer->id,
1712 rocc->peer->details.local.cfg,
1713 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
1714 &occ_cache_get_handle_ats_rocc_cb,
1715 rocc, NULL, NULL, NULL);
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)
1728 struct RemoteOverlayConnectCtx *rocc = cls;
1730 GNUNET_assert (NULL != rocc->attempt_connect_task_id);
1731 rocc->attempt_connect_task_id = NULL;
1732 LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n",
1734 GNUNET_i2s (&rocc->a_id),
1737 GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg,
1739 &rocc_hello_sent_cb,
1741 if (NULL == rocc->ohh)
1742 rocc->attempt_connect_task_id =
1743 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1744 (GNUNET_TIME_UNIT_MILLISECONDS,
1746 GNUNET_CRYPTO_random_u32
1747 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1748 &attempt_connect_task, rocc);
1753 * Callback from cache with needed handles set
1755 * @param cls the closure passed to GST_cache_get_handle_transport()
1756 * @param ch the handle to CORE. Can be NULL if it is not requested
1757 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1758 * @param ac the handle to ATS. Can be NULL if it is not requested
1759 * @param ignore_ peer identity which is ignored in this callback
1762 rocc_cache_get_handle_transport_cb (void *cls,
1763 struct GNUNET_CORE_Handle *ch,
1764 struct GNUNET_TRANSPORT_CoreHandle *th,
1765 struct GNUNET_ATS_ConnectivityHandle *ac,
1766 const struct GNUNET_PeerIdentity *ignore_,
1767 const struct GNUNET_CONFIGURATION_Handle *cfg)
1769 struct RemoteOverlayConnectCtx *rocc = cls;
1773 rocc->timeout_rocc_task_id =
1774 GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1778 rocc->tcc.cfg = cfg;
1780 GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_,
1783 LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n",
1785 GNUNET_i2s (&rocc->a_id),
1787 cleanup_rocc (rocc);
1790 rocc->attempt_connect_task_id =
1791 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1796 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REQUEST_CONNECT messages
1799 * @param client identification of the client
1800 * @param message the actual message
1803 GST_handle_remote_overlay_connect (void *cls,
1804 struct GNUNET_SERVER_Client *client,
1805 const struct GNUNET_MessageHeader *message)
1807 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
1808 struct RemoteOverlayConnectCtx *rocc;
1810 struct GNUNET_PeerIdentity pid;
1811 static char pid_str[16];
1816 msize = ntohs (message->size);
1817 if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize)
1820 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1823 msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message;
1824 if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))
1827 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1830 hsize = ntohs (msg->hello->size);
1831 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1835 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1838 peer_id = ntohl (msg->peer);
1839 if ((peer_id >= GST_peer_list_size) ||
1840 (NULL == (peer = GST_peer_list[peer_id])))
1842 GNUNET_break_op (0);
1843 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1846 if (GNUNET_YES == peer->is_remote)
1848 struct GNUNET_MessageHeader *msg2;
1850 msg2 = GNUNET_copy_message (message);
1851 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1853 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1856 rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
1857 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1858 GNUNET_CONTAINER_DLL_insert_tail (roccq_head,
1861 rocc->a_id = msg->peer_identity;
1862 GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
1864 (void) strncpy (pid_str,
1867 LOG_DEBUG ("0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n",
1870 GNUNET_i2s (&rocc->a_id),
1873 rocc->peer->reference_cnt++;
1874 rocc->hello = GNUNET_malloc (hsize);
1875 GNUNET_memcpy (rocc->hello, msg->hello, hsize);
1876 rocc->tcc.cgh_p2_th =
1877 GST_connection_pool_get_handle (peer_id,
1878 rocc->peer->details.local.cfg,
1879 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1880 &rocc_cache_get_handle_transport_cb,
1883 &cache_transport_peer_connect_notify,
1885 rocc->timeout_rocc_task_id =
1886 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1889 GNUNET_SERVER_receive_done (client,
1895 * Clears all pending overlay connect contexts in queue
1900 struct OverlayConnectContext *occ;
1902 while (NULL != (occ = occq_head))
1908 * Clears all pending remote overlay connect contexts in queue
1913 struct RemoteOverlayConnectCtx *rocc;
1915 while (NULL != (rocc = roccq_head))
1916 cleanup_rocc (rocc);