2 This file is part of GNUnet.
3 Copyright (C) 2008--2015 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file testbed/gnunet-service-testbed_oc.c
23 * @brief code for handling overlay connect operations
24 * @author Sree Harsha Totakura
27 #include "gnunet-service-testbed.h"
28 #include "gnunet-service-testbed_connectionpool.h"
31 * Redefine LOG with a changed log component string
36 #define LOG(kind,...) \
37 GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__)
41 * Context information for requesting ATS to connect to a peer
43 struct ConnectivitySuggestContext
47 * The transport handle obtained from cache. Do NOT close/disconnect.
49 struct GNUNET_TRANSPORT_Handle *th_;
52 * The GetCacheHandle for the peer2's transport handle
53 * (used to offer the HELLO to the peer).
55 struct GST_ConnectionPool_GetHandle *cgh_p2_th;
58 * The GetCacheHandle for the peer2's ATS handle.
60 struct GST_ConnectionPool_GetHandle *cgh_p2_ats;
63 * The ATS handle for the connectivity suggestion.
65 struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
71 * Types for context information we create for overlay connect requests
73 enum OverlayConnectContextType
76 * This type is used if the overlay connection is local i.e. the connection
77 * has to be made between local peers
82 * Type to be used when the first peer is local and the other peer is on a slave
83 * controller started by us
85 OCC_TYPE_REMOTE_SLAVE,
88 * Type to be used when the first peer is local and the other peer is on a
89 * controller which is not started by us.
91 OCC_TYPE_REMOTE_LATERAL
96 * Context data for operations on second peer in local overlay connection
99 struct LocalPeer2Context
102 * The handle for offering the HELLO of the first peer to the second
105 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
108 * The transport ConnectivitySuggestContext
110 struct ConnectivitySuggestContext tcc;
115 * Context data for operations on second peer in remote overlay connection
118 struct RemotePeer2Context
121 * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay
122 * connection then this can be NULL until the connection to the controller is
125 struct GNUNET_TESTBED_Controller *p2c;
128 * Operation context for the suboperation we start to get the identity of the
131 struct OperationContext *opc;
134 * Notification handle acquire to connect to a remote controller. Only used
135 * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL.
137 struct NeighbourConnectNotification *ncn;
140 * The neighbour handle. Only used if the type of overlay connection is
141 * #OCC_TYPE_REMOTE_LATERAL.
143 struct Neighbour *p2n;
147 * Context information for connecting 2 peers in overlay.
149 struct OverlayConnectContext
152 * The next pointer for maintaining a DLL of all OverlayConnectContexts
154 struct OverlayConnectContext *next;
157 * The prev pointer for maintaining a DLL of all OverlayConnectContexts
159 struct OverlayConnectContext *prev;
162 * The client which has requested for overlay connection. This is used to send
163 * either a success of failure message
165 struct GNUNET_SERVER_Client *client;
168 * the first peer which is to expect an overlay connection from the second peer.
173 * Transport handle of the first peer obtained from cache to get its HELLO. Do
174 * NOT close/disconnect.
176 struct GNUNET_TRANSPORT_Handle *p1th_;
179 * The #GST_ConnectionPool_GetHandle for the peer1's transport handle
181 struct GST_ConnectionPool_GetHandle *cgh_p1th;
184 * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE
185 * level peer connects and to get our identity.
187 struct GST_ConnectionPool_GetHandle *cgh_ch;
190 * HELLO of the first peer. This should be sent to the second peer.
192 struct GNUNET_MessageHeader *hello;
195 * Get GetHelloHandle to acquire a HELLO of the first peer
197 struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
200 * The error message we send if this overlay connect operation has timed out
205 * Context information for operations on the second peer
210 * Context information to be used if the second peer is local
212 struct LocalPeer2Context local;
215 * Context information to be used if the second peer is remote
217 struct RemotePeer2Context remote;
222 * The peer identity of the first peer
224 struct GNUNET_PeerIdentity peer_identity;
227 * The peer identity of the other peer
229 struct GNUNET_PeerIdentity other_peer_identity;
232 * The id of the operation responsible for creating this context
237 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
240 struct GNUNET_SCHEDULER_Task *send_hello_task;
243 * The id of the overlay connect timeout task
245 struct GNUNET_SCHEDULER_Task *timeout_task;
248 * The id of the cleanup task
250 struct GNUNET_SCHEDULER_Task *cleanup_task;
253 * The type of this context information
255 enum OverlayConnectContextType type;
258 * The id of the second peer which is has to connect to the first peer
260 uint32_t other_peer_id;
265 * Context information for remote overlay connect operations. Remote overlay
266 * connections are used when peers A and B reside on different hosts. In these
267 * operations the host controller for peer B is asked by the host controller of
268 * peer A to make peer B connect to peer A by sending the controller of peer B
269 * the HELLO of peer A.
271 struct RemoteOverlayConnectCtx
274 * the next pointer for DLL
276 struct RemoteOverlayConnectCtx *next;
279 * the prev pointer for DLL
281 struct RemoteOverlayConnectCtx *prev;
284 * The peer handle of peer B
291 struct GNUNET_MessageHeader *hello;
294 * The handle for offering HELLO
296 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
299 * The transport try connect context
301 struct ConnectivitySuggestContext tcc;
304 * The peer identity of peer A
306 struct GNUNET_PeerIdentity a_id;
309 * Task for offering HELLO of A to B and doing try_connect
311 struct GNUNET_SCHEDULER_Task *attempt_connect_task_id;
314 * Task to timeout RequestOverlayConnect
316 struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id;
319 * The id of the operation responsible for creating this context
326 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
328 static struct OverlayConnectContext *occq_head;
331 * DLL tail for OverlayConnectContext DLL
333 static struct OverlayConnectContext *occq_tail;
336 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
339 static struct RemoteOverlayConnectCtx *roccq_head;
342 * DLL tail for RequectOverlayConnectContext DLL
344 static struct RemoteOverlayConnectCtx *roccq_tail;
348 * Cleans up ForwardedOverlayConnectContext
350 * @param focc the ForwardedOverlayConnectContext to cleanup
353 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
355 GNUNET_SERVER_client_drop (focc->client);
356 GNUNET_free_non_null (focc->orig_msg);
362 * Timeout task for cancelling a forwarded overlay connect connect
364 * @param cls the ForwardedOverlayConnectContext
367 forwarded_overlay_connect_timeout (void *cls)
369 struct ForwardedOperationContext *fopc = cls;
370 struct RegisteredHostContext *rhc;
371 struct ForwardedOverlayConnectContext *focc;
374 focc = rhc->focc_dll_head;
375 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
376 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1,
378 GST_cleanup_focc (focc);
379 GST_forwarded_operation_timeout (fopc);
380 if (NULL != rhc->focc_dll_head)
381 GST_process_next_focc (rhc);
386 * Callback to be called when forwarded overlay connection operation has a reply
387 * from the sub-controller successfull. We have to relay the reply msg back to
390 * @param cls ForwardedOperationContext
391 * @param msg the peer create success message
394 forwarded_overlay_connect_listener (void *cls,
395 const struct GNUNET_MessageHeader *msg)
397 struct ForwardedOperationContext *fopc = cls;
398 struct RegisteredHostContext *rhc;
399 struct ForwardedOverlayConnectContext *focc;
402 GST_forwarded_operation_reply_relay (cls, msg);
403 focc = rhc->focc_dll_head;
404 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
405 GST_cleanup_focc (focc);
406 if (NULL != rhc->focc_dll_head)
407 GST_process_next_focc (rhc);
412 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
414 * @param rhc the RegisteredHostContext
417 GST_process_next_focc (struct RegisteredHostContext *rhc)
419 struct ForwardedOperationContext *fopc;
420 struct ForwardedOverlayConnectContext *focc;
424 focc = rhc->focc_dll_head;
425 GNUNET_assert (NULL != focc);
426 GNUNET_assert (RHC_DONE == rhc->state);
427 GNUNET_assert (VALID_PEER_ID (focc->peer1));
428 peer = GST_peer_list[focc->peer1];
429 GNUNET_assert (GNUNET_YES == peer->is_remote);
430 GNUNET_assert (NULL != (slave = peer->details.remote.slave));
431 fopc = GNUNET_new (struct ForwardedOperationContext);
432 GNUNET_SERVER_client_keep (focc->client);
433 fopc->client = focc->client;
434 fopc->operation_id = focc->operation_id;
436 fopc->type = OP_OVERLAY_CONNECT;
438 GNUNET_TESTBED_forward_operation_msg_ (slave->controller,
439 focc->operation_id, focc->orig_msg,
440 &forwarded_overlay_connect_listener,
442 GNUNET_free (focc->orig_msg);
443 focc->orig_msg = NULL;
445 GNUNET_SCHEDULER_add_delayed (GST_timeout, &forwarded_overlay_connect_timeout,
447 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
452 * Cleans up any used handles in local peer2 context
454 * @param lp2c the local peer2 context information
457 cleanup_occ_lp2c (struct LocalPeer2Context *lp2c)
459 if (NULL != lp2c->ohh)
461 GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh);
464 if (NULL != lp2c->tcc.cgh_p2_th)
466 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th);
467 lp2c->tcc.cgh_p2_th = NULL;
469 if (NULL != lp2c->tcc.cgh_p2_ats)
471 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats);
472 lp2c->tcc.cgh_p2_ats = NULL;
474 if (NULL != lp2c->tcc.csh)
476 GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh);
477 lp2c->tcc.csh = NULL;
483 * Cleans up any used handles in remote peer2 context. Relinquishes the
484 * remote controller connection if it has been established on-demand.
486 * @param rp2c the remote peer2 context information
489 cleanup_occ_rp2c (struct RemotePeer2Context *rp2c)
491 if (NULL != rp2c->opc)
493 GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc);
496 if (NULL != rp2c->ncn)
498 GST_neighbour_get_connection_cancel (rp2c->ncn);
501 if ( (NULL != rp2c->p2c) && (NULL != rp2c->p2n) )
503 GST_neighbour_release_connection (rp2c->p2n);
509 * Condition for checking if given peer is ready to be destroyed
511 * @param peer the peer to check
513 #define PEER_EXPIRED(peer) \
514 ( (GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt) )
517 * Cleanup overlay connect context structure
519 * @param occ the overlay connect context
522 cleanup_occ (struct OverlayConnectContext *occ)
526 LOG_DEBUG ("0x%llx: Cleaning up occ\n",
528 GNUNET_free_non_null (occ->emsg);
529 GNUNET_free_non_null (occ->hello);
530 GNUNET_SERVER_client_drop (occ->client);
531 if (NULL != occ->send_hello_task)
532 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
533 if (NULL != occ->cleanup_task)
534 GNUNET_SCHEDULER_cancel (occ->cleanup_task);
535 if (NULL != occ->timeout_task)
536 GNUNET_SCHEDULER_cancel (occ->timeout_task);
537 if (NULL != occ->cgh_ch)
538 GST_connection_pool_get_handle_done (occ->cgh_ch);
539 if (NULL != occ->ghh)
540 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
541 GST_connection_pool_get_handle_done (occ->cgh_p1th);
542 GNUNET_assert (NULL != GST_peer_list);
543 GNUNET_assert (occ->peer->reference_cnt > 0);
544 occ->peer->reference_cnt--;
545 if (PEER_EXPIRED (occ->peer))
546 GST_destroy_peer (occ->peer);
550 peer2 = GST_peer_list[occ->other_peer_id];
551 GNUNET_assert (peer2->reference_cnt > 0);
552 peer2->reference_cnt--;
553 if (PEER_EXPIRED (peer2))
554 GST_destroy_peer (peer2);
555 cleanup_occ_lp2c (&occ->p2ctx.local);
557 case OCC_TYPE_REMOTE_SLAVE:
558 case OCC_TYPE_REMOTE_LATERAL:
559 cleanup_occ_rp2c (&occ->p2ctx.remote);
562 GNUNET_CONTAINER_DLL_remove (occq_head,
570 * Task for cleaing up overlay connect context structure
572 * @param cls the overlay connect context
575 do_cleanup_occ (void *cls)
577 struct OverlayConnectContext *occ = cls;
579 occ->cleanup_task = NULL;
585 * Task which will be run when overlay connect request has been timed out
587 * @param cls the OverlayConnectContext
590 timeout_overlay_connect (void *cls)
592 struct OverlayConnectContext *occ = cls;
594 GNUNET_assert (NULL != occ->timeout_task);
595 occ->timeout_task = NULL;
596 /* LOG (GNUNET_ERROR_TYPE_WARNING, */
597 /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
598 /* occ->peer->id, occ->other_peer_id, occ->emsg); */
599 GST_send_operation_fail_msg (occ->client,
610 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
612 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
614 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
616 msg = GNUNET_new (struct GNUNET_TESTBED_ConnectionEventMessage);
618 htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
619 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
620 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
621 msg->peer1 = htonl (occ->peer->id);
622 msg->peer2 = htonl (occ->other_peer_id);
623 msg->operation_id = GNUNET_htonll (occ->op_id);
624 GST_queue_message (occ->client, &msg->header);
629 * Function called to notify transport users that another
630 * peer connected to us.
633 * @param new_peer the peer that connected
636 overlay_connect_notify (void *cls,
637 const struct GNUNET_PeerIdentity *new_peer)
639 struct OverlayConnectContext *occ = cls;
641 char *other_peer_str;
643 LOG_DEBUG ("Overlay connect notify\n");
645 memcmp (new_peer, &occ->peer_identity,
646 sizeof (struct GNUNET_PeerIdentity)))
648 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
649 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
652 &occ->other_peer_identity,
653 sizeof (struct GNUNET_PeerIdentity)))
655 LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n",
658 GNUNET_free (new_peer_str);
659 GNUNET_free (other_peer_str);
662 GNUNET_free (new_peer_str);
663 LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n",
666 GNUNET_i2s (&occ->peer_identity));
667 GNUNET_free (other_peer_str);
668 if (NULL != occ->send_hello_task)
670 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
671 occ->send_hello_task = NULL;
673 GNUNET_assert (NULL != occ->timeout_task);
674 GNUNET_SCHEDULER_cancel (occ->timeout_task);
675 occ->timeout_task = NULL;
679 cleanup_occ_lp2c (&occ->p2ctx.local);
681 case OCC_TYPE_REMOTE_SLAVE:
682 case OCC_TYPE_REMOTE_LATERAL:
683 cleanup_occ_rp2c (&occ->p2ctx.remote);
686 GNUNET_free_non_null (occ->emsg);
688 send_overlay_connect_success_msg (occ);
689 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ,
695 * Callback from cache with needed ATS handle set
697 * @param cls a `struct OverlayConnectCtx *`
698 * @param ch the handle to CORE. Can be NULL if it is not requested
699 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
700 * @param ac the handle to ATS. Can be NULL if it is not requested
701 * @param my_identity the identity of our peer
704 occ_cache_get_handle_ats_occ_cb (void *cls,
705 struct GNUNET_CORE_Handle *ch,
706 struct GNUNET_TRANSPORT_Handle *th,
707 struct GNUNET_ATS_ConnectivityHandle *ac,
708 const struct GNUNET_PeerIdentity *my_identity)
710 struct OverlayConnectContext *occ = cls;
711 struct LocalPeer2Context *lp2c;
713 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
714 GNUNET_assert (NULL != occ->timeout_task);
715 GNUNET_free_non_null (occ->emsg);
718 GNUNET_asprintf (&occ->emsg,
719 "0x%llx: Failed to connect to ATS of peer with id: %u",
722 GNUNET_SCHEDULER_cancel (occ->timeout_task);
724 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect,
730 GNUNET_asprintf (&occ->emsg,
731 "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s",
733 GNUNET_i2s (&occ->other_peer_identity));
735 lp2c = &occ->p2ctx.local;
737 GNUNET_ATS_connectivity_suggest (ac,
744 * Callback from cache with needed ATS handle set
746 * @param cls a `struct RemoteOverlayConnectCtx *`
747 * @param ch the handle to CORE. Can be NULL if it is not requested
748 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
749 * @param ac the handle to ATS. Can be NULL if it is not requested
750 * @param my_identity the identity of our peer
753 occ_cache_get_handle_ats_rocc_cb (void *cls,
754 struct GNUNET_CORE_Handle *ch,
755 struct GNUNET_TRANSPORT_Handle *th,
756 struct GNUNET_ATS_ConnectivityHandle *ac,
757 const struct GNUNET_PeerIdentity *my_identity)
759 struct RemoteOverlayConnectCtx *rocc = cls;
762 GNUNET_ATS_connectivity_suggest (ac,
769 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
772 * @param cls the OverlayConnectContext
775 send_hello (void *cls);
779 * Task that is run when hello has been sent If tc->reason =
780 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
781 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
783 * @param cls the overlay connect context
786 occ_hello_sent_cb (void *cls)
788 struct OverlayConnectContext *occ = cls;
789 struct LocalPeer2Context *lp2c;
791 const struct GNUNET_SCHEDULER_TaskContext *tc;
793 tc = GNUNET_SCHEDULER_get_task_context ();
794 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
795 GNUNET_assert (NULL != occ->timeout_task);
796 lp2c = &occ->p2ctx.local;
799 GNUNET_assert (NULL == occ->send_hello_task);
800 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
802 GNUNET_free_non_null (occ->emsg);
803 GNUNET_asprintf (&occ->emsg,
804 "0x%llx: Timeout while offering HELLO to other peer",
806 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello,
810 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
812 GNUNET_free_non_null (occ->emsg);
814 GNUNET_asprintf (&occ->emsg,
815 "0x%llx: Timeout while acquiring ATS of %s from cache",
817 GNUNET_i2s (&occ->other_peer_identity));
818 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
819 lp2c->tcc.cgh_p2_ats =
820 GST_connection_pool_get_handle (occ->other_peer_id,
821 peer2->details.local.cfg,
822 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
823 &occ_cache_get_handle_ats_occ_cb,
824 occ, NULL, NULL, NULL);
829 * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
832 * @param occ the overlay connect context. Its type must be either
833 * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL
836 send_hello_thru_rocc (struct OverlayConnectContext *occ)
838 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
839 char *other_peer_str;
843 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
844 GNUNET_assert (NULL != occ->hello);
845 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
846 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n",
848 GNUNET_i2s (&occ->peer_identity),
849 ntohs (occ->hello->size),
851 GNUNET_free (other_peer_str);
852 hello_size = ntohs (occ->hello->size);
853 msize = sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
854 msg = GNUNET_malloc (msize);
856 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
857 msg->header.size = htons (msize);
858 msg->peer = htonl (occ->other_peer_id);
859 msg->operation_id = GNUNET_htonll (occ->op_id);
860 msg->peer_identity = occ->peer_identity;
864 GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c,
870 * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered
871 * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
872 * send_hello_thru_rocc()
874 * @param cls the OverlayConnectContext
877 send_hello (void *cls)
879 struct OverlayConnectContext *occ = cls;
880 struct LocalPeer2Context *lp2c;
881 char *other_peer_str;
883 occ->send_hello_task = NULL;
884 GNUNET_assert (NULL != occ->timeout_task);
885 GNUNET_assert (NULL != occ->hello);
886 if (OCC_TYPE_LOCAL != occ->type)
888 send_hello_thru_rocc (occ);
891 lp2c = &occ->p2ctx.local;
892 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
893 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n",
895 GNUNET_i2s (&occ->peer_identity),
897 GNUNET_free (other_peer_str);
899 GNUNET_TRANSPORT_offer_hello (lp2c->tcc.th_,
903 if (NULL == lp2c->ohh)
906 occ->send_hello_task =
907 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
908 (GNUNET_TIME_UNIT_MILLISECONDS,
910 GNUNET_CRYPTO_random_u32
911 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
918 * Callback from cache with needed handles set
920 * @param cls the closure passed to GST_cache_get_handle_transport()
921 * @param ch the handle to CORE. Can be NULL if it is not requested
922 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
923 * @param ac the handle to ATS. Can be NULL if it is not requested
924 * @param ignore_ peer identity which is ignored in this callback
927 p2_transport_connect_cache_callback (void *cls,
928 struct GNUNET_CORE_Handle *ch,
929 struct GNUNET_TRANSPORT_Handle *th,
930 struct GNUNET_ATS_ConnectivityHandle *ac,
931 const struct GNUNET_PeerIdentity *ignore_)
933 struct OverlayConnectContext *occ = cls;
935 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
938 GNUNET_asprintf (&occ->emsg,
939 "0x%llx: Cannot connect to TRANSPORT of %s",
941 GNUNET_i2s (&occ->other_peer_identity));
942 GNUNET_SCHEDULER_cancel (occ->timeout_task);
944 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
947 occ->p2ctx.local.tcc.th_ = th;
948 GNUNET_asprintf (&occ->emsg,
949 "0x%llx: Timeout while offering HELLO to %s",
951 GNUNET_i2s (&occ->other_peer_identity));
952 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
957 * Connects to the transport of the other peer if it is a local peer and
958 * schedules the send hello task
960 * @param occ the overlay connect context
963 p2_transport_connect (struct OverlayConnectContext *occ)
967 GNUNET_assert (NULL == occ->emsg);
968 GNUNET_assert (NULL != occ->hello);
969 GNUNET_assert (NULL == occ->ghh);
970 GNUNET_assert (NULL == occ->p1th_);
971 GNUNET_assert (NULL == occ->cgh_p1th);
972 if (OCC_TYPE_LOCAL == occ->type)
974 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
975 occ->p2ctx.local.tcc.cgh_p2_th =
976 GST_connection_pool_get_handle (occ->other_peer_id,
977 peer2->details.local.cfg,
978 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
979 &p2_transport_connect_cache_callback,
980 occ, NULL, NULL, NULL);
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 * Test for checking whether HELLO message is empty
994 * @param cls empty flag to set
995 * @param address the HELLO
996 * @param expiration expiration of the HELLO
1000 test_address (void *cls,
1001 const struct GNUNET_HELLO_Address *address,
1002 struct GNUNET_TIME_Absolute expiration)
1012 * Function called whenever there is an update to the HELLO of peers in the
1013 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
1014 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
1016 * @param cls closure
1017 * @param hello our updated HELLO
1020 hello_update_cb (void *cls,
1021 const struct GNUNET_MessageHeader *hello)
1023 struct OverlayConnectContext *occ = cls;
1027 msize = ntohs (hello->size);
1029 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
1033 if (GNUNET_YES == empty)
1035 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n",
1037 GNUNET_i2s (&occ->peer_identity));
1040 LOG_DEBUG ("0x%llx: Received HELLO of %s\n",
1042 GNUNET_i2s (&occ->peer_identity));
1043 occ->hello = GNUNET_malloc (msize);
1044 GST_cache_add_hello (occ->peer->id, hello);
1045 memcpy (occ->hello, hello, msize);
1046 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
1048 GST_connection_pool_get_handle_done (occ->cgh_p1th);
1049 occ->cgh_p1th = NULL;
1051 GNUNET_free_non_null (occ->emsg);
1053 p2_transport_connect (occ);
1058 * Callback from cache with needed handles set
1060 * @param cls the closure passed to GST_cache_get_handle_transport()
1061 * @param ch the handle to CORE. Can be NULL if it is not requested
1062 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1063 * @param ac the handle to ATS. Can be NULL if it is not requested
1064 * @param ignore_ peer identity which is ignored in this callback
1067 p1_transport_connect_cache_callback (void *cls,
1068 struct GNUNET_CORE_Handle *ch,
1069 struct GNUNET_TRANSPORT_Handle *th,
1070 struct GNUNET_ATS_ConnectivityHandle *ac,
1071 const struct GNUNET_PeerIdentity *ignore_)
1073 struct OverlayConnectContext *occ = cls;
1075 GNUNET_free_non_null (occ->emsg);
1079 GNUNET_asprintf (&occ->emsg,
1080 "0x%llx: Cannot connect to TRANSPORT of %s",
1082 GNUNET_i2s (&occ->peer_identity));
1083 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1085 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1088 GNUNET_assert (NULL == occ->p1th_);
1089 GNUNET_assert (NULL != occ->cgh_p1th);
1091 GNUNET_asprintf (&occ->emsg,
1092 "0x%llx: Timeout while acquiring HELLO of peer %s",
1094 GNUNET_i2s (&occ->peer_identity));
1095 occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th_,
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_Handle *th,
1114 struct GNUNET_ATS_ConnectivityHandle *ac,
1115 const struct GNUNET_PeerIdentity *my_identity)
1117 struct OverlayConnectContext *occ = cls;
1118 const struct GNUNET_MessageHeader *hello;
1120 GNUNET_assert (NULL != occ->timeout_task);
1121 GNUNET_free_non_null (occ->emsg);
1122 if ((NULL == ch) || (NULL == my_identity))
1124 GNUNET_asprintf (&occ->emsg,
1125 "0x%llx: Failed to connect to CORE of peer with "
1129 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1131 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1136 GNUNET_CORE_is_peer_connected_sync (ch,
1137 &occ->other_peer_identity))
1139 LOG_DEBUG ("0x%llx: Target peer already connected\n",
1141 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1142 occ->timeout_task = NULL;
1143 send_overlay_connect_success_msg (occ);
1144 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
1147 occ->peer_identity = *my_identity;
1148 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n",
1150 GNUNET_i2s (&occ->peer_identity));
1151 /* Lookup for HELLO in hello cache */
1152 if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
1154 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n",
1156 GNUNET_i2s (&occ->peer_identity));
1157 occ->hello = GNUNET_copy_message (hello);
1158 p2_transport_connect (occ);
1161 GNUNET_asprintf (&occ->emsg,
1162 "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
1164 GNUNET_i2s (&occ->peer_identity));
1166 GST_connection_pool_get_handle (occ->peer->id,
1167 occ->peer->details.local.cfg,
1168 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1169 p1_transport_connect_cache_callback,
1176 * Callback to be called when forwarded get peer config operation as part of
1177 * overlay connect is successfull. Connection to Peer 1's core is made and is
1178 * checked for new connection from peer 2
1180 * @param cls ForwardedOperationContext
1181 * @param msg the peer create success message
1184 overlay_connect_get_config (void *cls,
1185 const struct GNUNET_MessageHeader *msg)
1187 struct OverlayConnectContext *occ = cls;
1188 struct RemotePeer2Context *rp2c;
1189 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
1191 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1192 rp2c = &occ->p2ctx.remote;
1194 GNUNET_assert (NULL != occ->timeout_task);
1195 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
1197 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1199 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1202 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1203 occ->other_peer_identity = cmsg->peer_identity;
1204 GNUNET_free_non_null (occ->emsg);
1205 GNUNET_asprintf (&occ->emsg,
1206 "0x%llx: Timeout while connecting to CORE of peer with "
1211 GST_connection_pool_get_handle (occ->peer->id,
1212 occ->peer->details.local.cfg,
1213 GST_CONNECTIONPOOL_SERVICE_CORE,
1214 occ_cache_get_handle_core_cb,
1216 &occ->other_peer_identity,
1217 &overlay_connect_notify,
1224 * Callback which will be called after a host registration succeeded or failed
1226 * @param cls the RegisteredHostContext
1227 * @param emsg the error message; NULL if host registration is successful
1230 host_registration_comp (void *cls, const char *emsg)
1232 struct RegisteredHostContext *rhc = cls;
1234 rhc->state = RHC_DONE;
1235 GST_process_next_focc (rhc);
1240 * Iterator to match a registered host context
1242 * @param cls pointer 2 pointer of RegisteredHostContext
1243 * @param key current key code
1244 * @param value value in the hash map
1245 * @return #GNUNET_YES if we should continue to
1247 * #GNUNET_NO if not.
1250 reghost_match_iterator (void *cls,
1251 const struct GNUNET_HashCode *key,
1254 struct RegisteredHostContext **rh = cls;
1255 struct RegisteredHostContext *rh_val = value;
1257 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1268 * Function to generate the hashcode corresponding to a RegisteredHostContext
1270 * @param reg_host the host which is being registered in RegisteredHostContext
1271 * @param host the host of the controller which has to connect to the above rhost
1272 * @return the hashcode
1274 static struct GNUNET_HashCode
1275 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1276 struct GNUNET_TESTBED_Host *host)
1278 struct GNUNET_HashCode hash;
1279 uint32_t host_ids[2];
1281 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1282 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1283 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1289 * Checks if the given host is registered at the given slave.
1291 * @param slave the slave where registration has to be checked. The check is
1292 * actually done through a locally maintained hashmap. No
1293 * communication with the slave is involved.
1294 * @param host the host to register
1295 * @return If the given host is not registered already or the registration is
1296 * pending, it returns the registration context. Any overlay connects
1297 * to be forwarded should be queued in the context so that they can be
1298 * executed when the registration is completed. If the given host is
1299 * already registered, NULL is returned.
1301 static struct RegisteredHostContext *
1302 register_host (struct Slave *slave,
1303 struct GNUNET_TESTBED_Host *host)
1305 struct GNUNET_HashCode hash;
1306 struct RegisteredHostContext *rhc;
1308 rhc = GNUNET_new (struct RegisteredHostContext);
1309 rhc->reg_host = host;
1310 rhc->host = GST_host_list[slave->host_id];
1311 GNUNET_assert (NULL != rhc->reg_host);
1312 GNUNET_assert (NULL != rhc->host);
1313 rhc->state = RHC_INIT;
1314 hash = hash_hosts (rhc->reg_host, rhc->host);
1316 GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, &hash)) ||
1318 GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
1320 reghost_match_iterator,
1323 /* create and add a new registerd host context */
1324 /* add the focc to its queue */
1325 GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, &hash, rhc,
1326 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1327 GST_queue_host_registration (slave, host_registration_comp,
1328 rhc, rhc->reg_host);
1332 /* rhc is now set to the existing one from the hash map by
1333 * reghost_match_iterator() */
1334 /* if queue is empty then ignore creating focc and proceed with normal
1336 if (RHC_DONE == rhc->state)
1344 * Forwards the overlay connect request to a slave controller. Before
1345 * forwarding, any hosts which are needed to be known by the slave controller to
1346 * execute the overlay connect request are registered at slave.
1348 * @param msg the overlay connect request message to be forwarded
1349 * @param client the client to which the status of the forwarded request has to
1353 forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
1354 struct GNUNET_SERVER_Client *client)
1356 struct ForwardedOperationContext *fopc;
1357 struct Route *route_to_peer2_host;
1358 struct Route *route_to_peer1_host;
1360 struct RegisteredHostContext *rhc;
1361 struct ForwardedOverlayConnectContext *focc;
1363 uint32_t peer2_host_id;
1367 p1 = ntohl (msg->peer1);
1368 p2 = ntohl (msg->peer2);
1369 op_id = GNUNET_ntohll (msg->operation_id);
1370 peer2_host_id = ntohl (msg->peer2_host_id);
1371 GNUNET_assert (VALID_PEER_ID (p1));
1372 GNUNET_assert (VALID_HOST_ID (peer2_host_id));
1373 peer = GST_peer_list[p1];
1374 GNUNET_assert (GNUNET_YES == peer->is_remote);
1375 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
1376 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1377 route_to_peer1_host = GST_find_dest_route
1378 (peer->details.remote.remote_host_id);
1379 GNUNET_assert (NULL != route_to_peer1_host);
1380 if ((NULL != route_to_peer2_host) &&
1381 (route_to_peer1_host->dest == route_to_peer2_host->dest))
1383 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1384 different subtrees OR peer2 is on a subtree unknown to us */
1385 if (NULL != (rhc = register_host (peer->details.remote.slave,
1386 GST_host_list[peer2_host_id])))
1388 LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, p2);
1389 focc = GNUNET_new (struct ForwardedOverlayConnectContext);
1392 focc->peer2_host_id = peer2_host_id;
1393 focc->orig_msg = GNUNET_copy_message (&msg->header);
1394 focc->operation_id = op_id;
1395 focc->client = client;
1396 GNUNET_SERVER_client_keep (client);
1397 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, rhc->focc_dll_tail,
1403 LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, p2);
1404 fopc = GNUNET_new (struct ForwardedOperationContext);
1405 GNUNET_SERVER_client_keep (client);
1406 fopc->client = client;
1407 fopc->operation_id = op_id;
1408 fopc->type = OP_OVERLAY_CONNECT;
1410 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1411 slave->controller, op_id,
1413 &GST_forwarded_operation_reply_relay,
1415 fopc->timeout_task =
1416 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1417 &GST_forwarded_operation_timeout,
1419 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
1426 * Callback called when a connection to the controller of peer2 has been
1429 * @param cls the overlay connect contexts
1430 * @param c handle to the controller connection
1433 p2_controller_connect_cb (void *cls,
1434 struct GNUNET_TESTBED_Controller *c)
1436 struct OverlayConnectContext *occ = cls;
1437 struct RemotePeer2Context *rp2c;
1438 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1440 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1441 rp2c = &occ->p2ctx.remote;
1445 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1447 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
1448 cmsg.peer_id = htonl (occ->other_peer_id);
1449 cmsg.operation_id = GNUNET_htonll (occ->op_id);
1451 GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
1452 occ->op_id, &cmsg.header,
1453 &overlay_connect_get_config,
1455 GNUNET_free_non_null (occ->emsg);
1456 GNUNET_asprintf (&occ->emsg,
1457 "0x%llx: Timeout while getting peer identity of peer "
1460 occ->other_peer_id);
1465 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1468 * @param client identification of the client
1469 * @param message the actual message
1472 GST_handle_overlay_connect (void *cls,
1473 struct GNUNET_SERVER_Client *client,
1474 const struct GNUNET_MessageHeader *message)
1476 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1479 struct OverlayConnectContext *occ;
1480 struct Neighbour *p2n;
1481 uint64_t operation_id;
1484 uint32_t peer2_host_id;
1486 if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) !=
1487 ntohs (message->size))
1490 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1493 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1494 p1 = ntohl (msg->peer1);
1495 p2 = ntohl (msg->peer2);
1496 if (!VALID_PEER_ID (p1))
1499 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1502 peer = GST_peer_list[p1];
1503 operation_id = GNUNET_ntohll (msg->operation_id);
1505 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n",
1509 peer2_host_id = ntohl (msg->peer2_host_id);
1510 if (GNUNET_YES == peer->is_remote)
1512 if (! VALID_HOST_ID (peer2_host_id))
1515 GNUNET_SERVER_receive_done (client,
1519 forward_overlay_connect (msg, client);
1520 GNUNET_SERVER_receive_done (client,
1525 occ = GNUNET_new (struct OverlayConnectContext);
1526 occ->type = OCC_TYPE_LOCAL;
1527 if (!VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */
1529 if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1531 if (!VALID_HOST_ID (peer2_host_id))
1534 LOG (GNUNET_ERROR_TYPE_WARNING,
1535 "0x%llx: Peer %u's host not in our neighbours list\n",
1537 GNUNET_SERVER_receive_done (client,
1542 p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
1544 occ->type = OCC_TYPE_REMOTE_LATERAL;
1545 occ->p2ctx.remote.p2n = p2n;
1547 else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1549 occ->type = OCC_TYPE_REMOTE_SLAVE;
1550 occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
1552 GNUNET_CONTAINER_DLL_insert_tail (occq_head,
1555 GNUNET_SERVER_client_keep (client);
1556 occ->client = client;
1557 occ->other_peer_id = p2;
1558 GST_peer_list[p1]->reference_cnt++;
1559 occ->peer = GST_peer_list[p1];
1560 occ->op_id = operation_id;
1561 GNUNET_assert (NULL == occ->timeout_task);
1563 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1564 &timeout_overlay_connect,
1568 case OCC_TYPE_REMOTE_LATERAL:
1569 GNUNET_asprintf (&occ->emsg,
1570 "0x%llx: Timeout while acquiring connection to peer %u's "
1575 occ->p2ctx.remote.ncn =
1576 GST_neighbour_get_connection (p2n, &p2_controller_connect_cb, occ);
1578 case OCC_TYPE_REMOTE_SLAVE:
1579 p2_controller_connect_cb (occ, occ->p2ctx.remote.p2c);
1581 case OCC_TYPE_LOCAL:
1582 peer2 = GST_peer_list[occ->other_peer_id];
1583 peer2->reference_cnt++;
1584 GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
1585 &occ->other_peer_identity);
1586 GNUNET_asprintf (&occ->emsg,
1587 "0x%llx: Timeout while connecting to CORE of peer with "
1592 GST_connection_pool_get_handle (occ->peer->id,
1593 occ->peer->details.local.cfg,
1594 GST_CONNECTIONPOOL_SERVICE_CORE,
1595 occ_cache_get_handle_core_cb, occ,
1596 &occ->other_peer_identity,
1597 &overlay_connect_notify, occ);
1600 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1605 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1608 * @param rocc the RemoteOverlayConnectCtx
1611 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1613 LOG_DEBUG ("0x%llx: Cleaning up rocc\n",
1615 if (NULL != rocc->attempt_connect_task_id)
1616 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1617 if (NULL != rocc->timeout_rocc_task_id)
1618 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1619 if (NULL != rocc->ohh)
1620 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1621 if (NULL != rocc->tcc.csh)
1622 GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh);
1623 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th);
1624 GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats);
1625 GNUNET_assert (rocc->peer->reference_cnt > 0);
1626 rocc->peer->reference_cnt--;
1627 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1628 (0 == rocc->peer->reference_cnt))
1629 GST_destroy_peer (rocc->peer);
1630 GNUNET_free_non_null (rocc->hello);
1631 GNUNET_CONTAINER_DLL_remove (roccq_head,
1639 * Task to timeout rocc and cleanit up
1641 * @param cls the RemoteOverlayConnectCtx
1644 timeout_rocc_task (void *cls)
1646 struct RemoteOverlayConnectCtx *rocc = cls;
1648 GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
1649 rocc->timeout_rocc_task_id = NULL;
1650 LOG_DEBUG ("0x%llx: rocc timed out\n",
1652 cleanup_rocc (rocc);
1657 * Function called to notify transport users that another
1658 * peer connected to us.
1660 * @param cls the RemoteOverlayConnectContext
1661 * @param new_peer the peer that connected
1664 cache_transport_peer_connect_notify (void *cls,
1665 const struct GNUNET_PeerIdentity *new_peer)
1667 struct RemoteOverlayConnectCtx *rocc = cls;
1669 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n",
1672 memcmp (new_peer, &rocc->a_id,
1673 sizeof (struct GNUNET_PeerIdentity)));
1674 LOG_DEBUG ("0x%llx: Peer %s connected\n",
1676 GNUNET_i2s (&rocc->a_id));
1677 cleanup_rocc (rocc);
1682 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1683 * whose identity is in RemoteOverlayConnectCtx
1685 * @param cls the RemoteOverlayConnectCtx
1688 attempt_connect_task (void *cls);
1692 * Task that is run when hello has been sent If tc->reason =
1693 * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1694 * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1696 * @param cls the overlay connect context
1699 rocc_hello_sent_cb (void *cls)
1701 struct RemoteOverlayConnectCtx *rocc = cls;
1702 const struct GNUNET_SCHEDULER_TaskContext *tc;
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 tc = GNUNET_SCHEDULER_get_task_context ();
1711 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
1714 rocc->attempt_connect_task_id =
1715 GNUNET_SCHEDULER_add_now (&attempt_connect_task,
1719 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
1725 rocc->tcc.cgh_p2_ats =
1726 GST_connection_pool_get_handle (rocc->peer->id,
1727 rocc->peer->details.local.cfg,
1728 GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
1729 &occ_cache_get_handle_ats_rocc_cb,
1730 rocc, NULL, NULL, NULL);
1736 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1737 * whose identity is in RemoteOverlayConnectCtx
1739 * @param cls the RemoteOverlayConnectCtx
1742 attempt_connect_task (void *cls)
1744 struct RemoteOverlayConnectCtx *rocc = cls;
1746 GNUNET_assert (NULL != rocc->attempt_connect_task_id);
1747 rocc->attempt_connect_task_id = NULL;
1748 LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n",
1750 GNUNET_i2s (&rocc->a_id),
1753 GNUNET_TRANSPORT_offer_hello (rocc->tcc.th_,
1755 rocc_hello_sent_cb, rocc);
1756 if (NULL == rocc->ohh)
1757 rocc->attempt_connect_task_id =
1758 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1759 (GNUNET_TIME_UNIT_MILLISECONDS,
1761 GNUNET_CRYPTO_random_u32
1762 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1763 &attempt_connect_task, rocc);
1768 * Callback from cache with needed handles set
1770 * @param cls the closure passed to GST_cache_get_handle_transport()
1771 * @param ch the handle to CORE. Can be NULL if it is not requested
1772 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1773 * @param ac the handle to ATS. Can be NULL if it is not requested
1774 * @param ignore_ peer identity which is ignored in this callback
1777 rocc_cache_get_handle_transport_cb (void *cls,
1778 struct GNUNET_CORE_Handle *ch,
1779 struct GNUNET_TRANSPORT_Handle *th,
1780 struct GNUNET_ATS_ConnectivityHandle *ac,
1781 const struct GNUNET_PeerIdentity *ignore_)
1783 struct RemoteOverlayConnectCtx *rocc = cls;
1787 rocc->timeout_rocc_task_id =
1788 GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1793 GNUNET_TRANSPORT_check_peer_connected (rocc->tcc.th_,
1796 LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n",
1798 GNUNET_i2s (&rocc->a_id),
1800 cleanup_rocc (rocc);
1803 rocc->attempt_connect_task_id =
1804 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1809 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REQUEST_CONNECT messages
1812 * @param client identification of the client
1813 * @param message the actual message
1816 GST_handle_remote_overlay_connect (void *cls,
1817 struct GNUNET_SERVER_Client *client,
1818 const struct GNUNET_MessageHeader *message)
1820 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
1821 struct RemoteOverlayConnectCtx *rocc;
1823 struct GNUNET_PeerIdentity pid;
1824 static char pid_str[16];
1829 msize = ntohs (message->size);
1830 if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize)
1833 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1836 msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message;
1837 if ((NULL == msg->hello) ||
1838 ((GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))))
1841 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1844 hsize = ntohs (msg->hello->size);
1845 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1849 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1852 peer_id = ntohl (msg->peer);
1853 if ((peer_id >= GST_peer_list_size) ||
1854 (NULL == (peer = GST_peer_list[peer_id])))
1856 GNUNET_break_op (0);
1857 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1860 if (GNUNET_YES == peer->is_remote)
1862 struct GNUNET_MessageHeader *msg2;
1864 msg2 = GNUNET_copy_message (message);
1865 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1867 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1870 rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
1871 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1872 GNUNET_CONTAINER_DLL_insert_tail (roccq_head,
1875 rocc->a_id = msg->peer_identity;
1876 GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
1878 (void) strncpy (pid_str,
1881 LOG_DEBUG ("0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n",
1884 GNUNET_i2s (&rocc->a_id),
1887 rocc->peer->reference_cnt++;
1888 rocc->hello = GNUNET_malloc (hsize);
1889 memcpy (rocc->hello, msg->hello, hsize);
1890 rocc->tcc.cgh_p2_th =
1891 GST_connection_pool_get_handle (peer_id,
1892 rocc->peer->details.local.cfg,
1893 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1894 &rocc_cache_get_handle_transport_cb,
1897 &cache_transport_peer_connect_notify,
1899 rocc->timeout_rocc_task_id =
1900 GNUNET_SCHEDULER_add_delayed (GST_timeout,
1903 GNUNET_SERVER_receive_done (client,
1909 * Clears all pending overlay connect contexts in queue
1914 struct OverlayConnectContext *occ;
1916 while (NULL != (occ = occq_head))
1922 * Clears all pending remote overlay connect contexts in queue
1927 struct RemoteOverlayConnectCtx *rocc;
1929 while (NULL != (rocc = roccq_head))
1930 cleanup_rocc (rocc);