2 This file is part of GNUnet.
3 Copyright (C) 2008--2013 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, 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 TRANSPORT to connect to a peer
43 struct TryConnectContext
46 * The identity of the peer to which the transport has to attempt a connection
48 struct GNUNET_PeerIdentity *pid;
51 * The transport handle obtained from cache. Do NOT close/disconnect.
53 struct GNUNET_TRANSPORT_Handle *th_;
56 * The GetCacheHandle for the p1th transport handle
58 struct GST_ConnectionPool_GetHandle *cgh_th;
61 * the try connect handle
63 struct GNUNET_TRANSPORT_TryConnectHandle *tch;
68 struct GNUNET_SCHEDULER_Task * task;
71 * The id of the operation which is resposible for this context
76 * The number of times we attempted to connect
84 * Types for context information we create for overlay connect requests
86 enum OverlayConnectContextType
89 * This type is used if the overlay connection is local i.e. the connection
90 * has to be made between local peers
95 * Type to be used when the first peer is local and the other peer is on a slave
96 * controller started by us
98 OCC_TYPE_REMOTE_SLAVE,
101 * Type to be used when the first peer is local and the other peer is on a
102 * controller which is not started by us.
104 OCC_TYPE_REMOTE_LATERAL
109 * Context data for operations on second peer in local overlay connection
112 struct LocalPeer2Context
115 * The handle for offering the HELLO of the first peer to the second
118 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
121 * The transport TryConnectContext
123 struct TryConnectContext tcc;
128 * Context data for operations on second peer in remote overlay connection
131 struct RemotePeer2Context
134 * Controller of peer 2; If OCC_TYPE_REMOTE_LATERAL is the type of overlay
135 * connection then this can be NULL until the connection to the controller is
138 struct GNUNET_TESTBED_Controller *p2c;
141 * Operation context for the suboperation we start to get the identity of the
144 struct OperationContext *opc;
147 * Notification handle acquire to connect to a remote controller. Only used
148 * if the type of overlay connection is OCC_TYPE_REMOTE_LATERAL.
150 struct NeighbourConnectNotification *ncn;
153 * The neighbour handle. Only used if the type of overlay connection is
154 * OCC_TYPE_REMOTE_LATERAL.
156 struct Neighbour *p2n;
160 * Context information for connecting 2 peers in overlay.
162 struct OverlayConnectContext
165 * The next pointer for maintaining a DLL of all OverlayConnectContexts
167 struct OverlayConnectContext *next;
170 * The prev pointer for maintaining a DLL of all OverlayConnectContexts
172 struct OverlayConnectContext *prev;
175 * The client which has requested for overlay connection. This is used to send
176 * either a success of failure message
178 struct GNUNET_SERVER_Client *client;
181 * the first peer which is to expect an overlay connection from the second peer.
186 * Transport handle of the first peer obtained from cache to get its HELLO. Do
187 * NOT close/disconnect.
189 struct GNUNET_TRANSPORT_Handle *p1th_;
192 * The #GST_ConnectionPool_GetHandle for the peer1's transport handle
194 struct GST_ConnectionPool_GetHandle *cgh_p1th;
197 * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE
198 * level peer connects and to get our identity.
200 struct GST_ConnectionPool_GetHandle *cgh_ch;
203 * HELLO of the first peer. This should be sent to the second peer.
205 struct GNUNET_MessageHeader *hello;
208 * Get GetHelloHandle to acquire a HELLO of the first peer
210 struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
213 * The error message we send if this overlay connect operation has timed out
218 * Context information for operations on the second peer
223 * Context information to be used if the second peer is local
225 struct LocalPeer2Context local;
228 * Context information to be used if the second peer is remote
230 struct RemotePeer2Context remote;
235 * The peer identity of the first peer
237 struct GNUNET_PeerIdentity peer_identity;
240 * The peer identity of the other peer
242 struct GNUNET_PeerIdentity other_peer_identity;
245 * The id of the operation responsible for creating this context
250 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
253 struct GNUNET_SCHEDULER_Task * send_hello_task;
256 * The id of the overlay connect timeout task
258 struct GNUNET_SCHEDULER_Task * timeout_task;
261 * The id of the cleanup task
263 struct GNUNET_SCHEDULER_Task * cleanup_task;
266 * The type of this context information
268 enum OverlayConnectContextType type;
271 * The id of the second peer which is has to connect to the first peer
273 uint32_t other_peer_id;
278 * Context information for remote overlay connect operations. Remote overlay
279 * connections are used when peers A and B reside on different hosts. In these
280 * operations the host controller for peer B is asked by the host controller of
281 * peer A to make peer B connect to peer A by sending the controller of peer B
282 * the HELLO of peer A.
284 struct RemoteOverlayConnectCtx
287 * the next pointer for DLL
289 struct RemoteOverlayConnectCtx *next;
292 * the prev pointer for DLL
294 struct RemoteOverlayConnectCtx *prev;
297 * The peer handle of peer B
304 struct GNUNET_MessageHeader *hello;
307 * The handle for offering HELLO
309 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
312 * The transport try connect context
314 struct TryConnectContext tcc;
317 * The peer identity of peer A
319 struct GNUNET_PeerIdentity a_id;
322 * Task for offering HELLO of A to B and doing try_connect
324 struct GNUNET_SCHEDULER_Task * attempt_connect_task_id;
327 * Task to timeout RequestOverlayConnect
329 struct GNUNET_SCHEDULER_Task * timeout_rocc_task_id;
332 * The id of the operation responsible for creating this context
339 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
341 static struct OverlayConnectContext *occq_head;
344 * DLL tail for OverlayConnectContext DLL
346 static struct OverlayConnectContext *occq_tail;
349 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
352 static struct RemoteOverlayConnectCtx *roccq_head;
355 * DLL tail for RequectOverlayConnectContext DLL
357 static struct RemoteOverlayConnectCtx *roccq_tail;
361 * Cleans up ForwardedOverlayConnectContext
363 * @param focc the ForwardedOverlayConnectContext to cleanup
366 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
368 GNUNET_SERVER_client_drop (focc->client);
369 GNUNET_free_non_null (focc->orig_msg);
375 * Timeout task for cancelling a forwarded overlay connect connect
377 * @param cls the ForwardedOverlayConnectContext
378 * @param tc the task context from the scheduler
381 forwarded_overlay_connect_timeout (void *cls,
382 const struct GNUNET_SCHEDULER_TaskContext
385 struct ForwardedOperationContext *fopc = cls;
386 struct RegisteredHostContext *rhc;
387 struct ForwardedOverlayConnectContext *focc;
390 focc = rhc->focc_dll_head;
391 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
392 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1,
394 GST_cleanup_focc (focc);
395 GST_forwarded_operation_timeout (fopc, tc);
396 if (NULL != rhc->focc_dll_head)
397 GST_process_next_focc (rhc);
402 * Callback to be called when forwarded overlay connection operation has a reply
403 * from the sub-controller successfull. We have to relay the reply msg back to
406 * @param cls ForwardedOperationContext
407 * @param msg the peer create success message
410 forwarded_overlay_connect_listener (void *cls,
411 const struct GNUNET_MessageHeader *msg)
413 struct ForwardedOperationContext *fopc = cls;
414 struct RegisteredHostContext *rhc;
415 struct ForwardedOverlayConnectContext *focc;
418 GST_forwarded_operation_reply_relay (cls, msg);
419 focc = rhc->focc_dll_head;
420 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
421 GST_cleanup_focc (focc);
422 if (NULL != rhc->focc_dll_head)
423 GST_process_next_focc (rhc);
428 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
430 * @param rhc the RegisteredHostContext
433 GST_process_next_focc (struct RegisteredHostContext *rhc)
435 struct ForwardedOperationContext *fopc;
436 struct ForwardedOverlayConnectContext *focc;
440 focc = rhc->focc_dll_head;
441 GNUNET_assert (NULL != focc);
442 GNUNET_assert (RHC_DONE == rhc->state);
443 GNUNET_assert (VALID_PEER_ID (focc->peer1));
444 peer = GST_peer_list[focc->peer1];
445 GNUNET_assert (GNUNET_YES == peer->is_remote);
446 GNUNET_assert (NULL != (slave = peer->details.remote.slave));
447 fopc = GNUNET_new (struct ForwardedOperationContext);
448 GNUNET_SERVER_client_keep (focc->client);
449 fopc->client = focc->client;
450 fopc->operation_id = focc->operation_id;
452 fopc->type = OP_OVERLAY_CONNECT;
454 GNUNET_TESTBED_forward_operation_msg_ (slave->controller,
455 focc->operation_id, focc->orig_msg,
456 &forwarded_overlay_connect_listener,
458 GNUNET_free (focc->orig_msg);
459 focc->orig_msg = NULL;
461 GNUNET_SCHEDULER_add_delayed (GST_timeout, &forwarded_overlay_connect_timeout,
463 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
468 * Cleans up any used handles in local peer2 context
470 * @param lp2c the local peer2 context information
473 cleanup_occ_lp2c (struct LocalPeer2Context *lp2c)
475 if (NULL != lp2c->ohh)
476 GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh);
477 if (NULL != lp2c->tcc.cgh_th)
478 GST_connection_pool_get_handle_done (lp2c->tcc.cgh_th);
479 if (NULL != lp2c->tcc.tch)
480 GNUNET_TRANSPORT_try_connect_cancel (lp2c->tcc.tch);
481 if (NULL != lp2c->tcc.task)
482 GNUNET_SCHEDULER_cancel (lp2c->tcc.task);
487 * Cleans up any used handles in remote peer2 context. Relinquishes the
488 * remote controller connection if it has been established on-demand.
490 * @param rp2c the remote peer2 context information
493 cleanup_occ_rp2c (struct RemotePeer2Context *rp2c)
495 if (NULL != rp2c->opc)
496 GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc);
497 if (NULL != rp2c->ncn)
498 GST_neighbour_get_connection_cancel (rp2c->ncn);
499 if ( (NULL != rp2c->p2c) && (NULL != rp2c->p2n) )
500 GST_neighbour_release_connection (rp2c->p2n);
505 * Condition for checking if given peer is ready to be destroyed
507 * @param peer the peer to check
509 #define PEER_EXPIRED(peer) \
510 ( (GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt) )
513 * Cleanup overlay connect context structure
515 * @param occ the overlay connect context
518 cleanup_occ (struct OverlayConnectContext *occ)
522 LOG_DEBUG ("0x%llx: Cleaning up occ\n", occ->op_id);
523 GNUNET_free_non_null (occ->emsg);
524 GNUNET_free_non_null (occ->hello);
525 GNUNET_SERVER_client_drop (occ->client);
526 if (NULL != occ->send_hello_task)
527 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
528 if (NULL != occ->cleanup_task)
529 GNUNET_SCHEDULER_cancel (occ->cleanup_task);
530 if (NULL != occ->timeout_task)
531 GNUNET_SCHEDULER_cancel (occ->timeout_task);
532 if (NULL != occ->cgh_ch)
533 GST_connection_pool_get_handle_done (occ->cgh_ch);
534 if (NULL != occ->ghh)
535 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
536 if (NULL != occ->cgh_p1th)
537 GST_connection_pool_get_handle_done (occ->cgh_p1th);
538 GNUNET_assert (NULL != GST_peer_list);
539 GNUNET_assert (occ->peer->reference_cnt > 0);
540 occ->peer->reference_cnt--;
541 if (PEER_EXPIRED (occ->peer))
542 GST_destroy_peer (occ->peer);
546 peer2 = GST_peer_list[occ->other_peer_id];
547 GNUNET_assert (peer2->reference_cnt > 0);
548 peer2->reference_cnt--;
549 if (PEER_EXPIRED (peer2))
550 GST_destroy_peer (peer2);
551 cleanup_occ_lp2c (&occ->p2ctx.local);
553 case OCC_TYPE_REMOTE_SLAVE:
554 case OCC_TYPE_REMOTE_LATERAL:
555 cleanup_occ_rp2c (&occ->p2ctx.remote);
558 GNUNET_CONTAINER_DLL_remove (occq_head, occq_tail, occ);
564 * Task for cleaing up overlay connect context structure
566 * @param cls the overlay connect context
567 * @param tc the task context
570 do_cleanup_occ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
572 struct OverlayConnectContext *occ = cls;
574 occ->cleanup_task = NULL;
580 * Task which will be run when overlay connect request has been timed out
582 * @param cls the OverlayConnectContext
583 * @param tc the TaskContext
586 timeout_overlay_connect (void *cls,
587 const struct GNUNET_SCHEDULER_TaskContext *tc)
589 struct OverlayConnectContext *occ = cls;
591 GNUNET_assert (NULL != occ->timeout_task);
592 occ->timeout_task = NULL;
593 /* LOG (GNUNET_ERROR_TYPE_WARNING, */
594 /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
595 /* occ->peer->id, occ->other_peer_id, occ->emsg); */
596 GST_send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
602 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
604 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
606 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
608 msg = GNUNET_new (struct GNUNET_TESTBED_ConnectionEventMessage);
610 htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
611 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
612 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
613 msg->peer1 = htonl (occ->peer->id);
614 msg->peer2 = htonl (occ->other_peer_id);
615 msg->operation_id = GNUNET_htonll (occ->op_id);
616 GST_queue_message (occ->client, &msg->header);
621 * Function called to notify transport users that another
622 * peer connected to us.
625 * @param new_peer the peer that connected
628 overlay_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer)
630 struct OverlayConnectContext *occ = cls;
631 struct LocalPeer2Context *lp2c;
633 char *other_peer_str;
635 LOG_DEBUG ("Overlay connect notify\n");
637 memcmp (new_peer, &occ->peer_identity,
638 sizeof (struct GNUNET_PeerIdentity)))
640 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
641 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
643 memcmp (new_peer, &occ->other_peer_identity,
644 sizeof (struct GNUNET_PeerIdentity)))
646 LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n",
647 new_peer_str, other_peer_str);
648 GNUNET_free (new_peer_str);
649 GNUNET_free (other_peer_str);
652 GNUNET_free (new_peer_str);
653 LOG_DEBUG ("0x%llx: Peer %4s connected to peer %4s\n", occ->op_id,
654 other_peer_str, GNUNET_i2s (&occ->peer_identity));
655 GNUNET_free (other_peer_str);
656 if (NULL != occ->send_hello_task)
658 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
659 occ->send_hello_task = NULL;
661 GNUNET_assert (NULL != occ->timeout_task);
662 GNUNET_SCHEDULER_cancel (occ->timeout_task);
663 occ->timeout_task = NULL;
664 if (OCC_TYPE_LOCAL == occ->type)
666 lp2c = &occ->p2ctx.local;
667 if (NULL != lp2c->tcc.task)
669 GNUNET_SCHEDULER_cancel (lp2c->tcc.task);
670 lp2c->tcc.task = NULL;
673 GNUNET_free_non_null (occ->emsg);
675 send_overlay_connect_success_msg (occ);
676 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
681 * Task to ask transport of a peer to connect to another peer
683 * @param cls the TryConnectContext
684 * @param tc the scheduler task context
687 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
691 * Callback to be called with result of the try connect request.
693 * @param cls the overlay connect context
694 * @param result GNUNET_OK if message was transmitted to transport service
695 * GNUNET_SYSERR if message was not transmitted to transport service
698 try_connect_cb (void *cls, const int result)
700 struct TryConnectContext *tcc = cls;
703 GNUNET_assert (NULL == tcc->task);
705 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
706 (GNUNET_TIME_UNIT_MILLISECONDS,
707 500 + pow (2, ++tcc->retries)),
708 &try_connect_task, tcc);
713 * Task to ask transport of a peer to connect to another peer
715 * @param cls the TryConnectContext
716 * @param tc the scheduler task context
719 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
721 struct TryConnectContext *tcc = cls;
724 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
726 GNUNET_assert (NULL == tcc->tch);
727 GNUNET_assert (NULL != tcc->pid);
728 GNUNET_assert (NULL != tcc->th_);
729 GNUNET_assert (NULL != tcc->cgh_th);
730 LOG_DEBUG ("0x%llx: Trail %u to connect to peer %4s\n", tcc->op_id,
731 tcc->retries, GNUNET_i2s (tcc->pid));
733 GNUNET_TRANSPORT_try_connect (tcc->th_, tcc->pid, &try_connect_cb, tcc);
738 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
741 * @param cls the OverlayConnectContext
742 * @param tc the TaskContext from scheduler
745 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
749 * Task that is run when hello has been sent
751 * @param cls the overlay connect context
752 * @param tc the scheduler task context; if tc->reason =
753 * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
754 * GNUNET_SCHEDULER_REASON_READ_READY is succeeded
757 occ_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
759 struct OverlayConnectContext *occ = cls;
760 struct LocalPeer2Context *lp2c;
762 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
763 lp2c = &occ->p2ctx.local;
765 GNUNET_assert (NULL == occ->send_hello_task);
766 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
768 GNUNET_free_non_null (occ->emsg);
769 GNUNET_asprintf (&occ->emsg,
770 "0x%llx: Timeout while offering HELLO to other peer",
772 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
775 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
777 GNUNET_free_non_null (occ->emsg);
778 GNUNET_asprintf (&occ->emsg,
779 "0x%llx: Timeout during TRANSPORT_try_connect() "
780 "at peer %4s", occ->op_id,
781 GNUNET_i2s(&occ->other_peer_identity));
782 lp2c->tcc.pid = &occ->peer_identity;
783 lp2c->tcc.op_id = occ->op_id;
784 lp2c->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &lp2c->tcc);
789 * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
792 * @param occ the overlay connect context. Its type must be either
793 * OCC_TYPE_REMOTE_SLAVE or OCC_TYPE_REMOTE_LATERAL
796 send_hello_thru_rocc (struct OverlayConnectContext *occ)
798 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
799 char *other_peer_str;
803 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
804 GNUNET_assert (NULL != occ->hello);
805 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
806 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote "
807 "Overlay Request\n", occ->op_id,
808 GNUNET_i2s (&occ->peer_identity), ntohs (occ->hello->size),
810 GNUNET_free (other_peer_str);
811 hello_size = ntohs (occ->hello->size);
813 sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
814 msg = GNUNET_malloc (msize);
816 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
817 msg->header.size = htons (msize);
818 msg->peer = htonl (occ->other_peer_id);
819 msg->operation_id = GNUNET_htonll (occ->op_id);
820 (void) memcpy (&msg->peer_identity, &occ->peer_identity,
821 sizeof (struct GNUNET_PeerIdentity));
822 memcpy (msg->hello, occ->hello, hello_size);
823 GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c, &msg->header);
828 * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered
829 * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
830 * send_hello_thru_rocc()
832 * @param cls the OverlayConnectContext
833 * @param tc the TaskContext from scheduler
836 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
838 struct OverlayConnectContext *occ = cls;
839 struct LocalPeer2Context *lp2c;
840 char *other_peer_str;
842 occ->send_hello_task = NULL;
843 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
845 GNUNET_assert (NULL != occ->hello);
846 if (OCC_TYPE_LOCAL != occ->type)
848 send_hello_thru_rocc (occ);
851 lp2c = &occ->p2ctx.local;
852 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
853 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n", occ->op_id,
854 GNUNET_i2s (&occ->peer_identity), other_peer_str);
855 GNUNET_free (other_peer_str);
857 GNUNET_TRANSPORT_offer_hello (lp2c->tcc.th_, occ->hello,
858 occ_hello_sent_cb, occ);
859 if (NULL == lp2c->ohh)
862 occ->send_hello_task =
863 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
864 (GNUNET_TIME_UNIT_MILLISECONDS,
866 GNUNET_CRYPTO_random_u32
867 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
874 * Callback from cache with needed handles set
876 * @param cls the closure passed to GST_cache_get_handle_transport()
877 * @param ch the handle to CORE. Can be NULL if it is not requested
878 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
879 * @param ignore_ peer identity which is ignored in this callback
882 p2_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch,
883 struct GNUNET_TRANSPORT_Handle *th,
884 const struct GNUNET_PeerIdentity *ignore_)
886 struct OverlayConnectContext *occ = cls;
888 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
891 GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s",
892 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
893 GNUNET_SCHEDULER_cancel (occ->timeout_task);
895 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
898 occ->p2ctx.local.tcc.th_ = th;
899 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
900 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
901 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
906 * Connects to the transport of the other peer if it is a local peer and
907 * schedules the send hello task
909 * @param occ the overlay connect context
912 p2_transport_connect (struct OverlayConnectContext *occ)
916 GNUNET_assert (NULL == occ->emsg);
917 GNUNET_assert (NULL != occ->hello);
918 GNUNET_assert (NULL == occ->ghh);
919 GNUNET_assert (NULL == occ->p1th_);
920 GNUNET_assert (NULL == occ->cgh_p1th);
921 if (OCC_TYPE_LOCAL == occ->type)
923 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
924 occ->p2ctx.local.tcc.cgh_th =
925 GST_connection_pool_get_handle (occ->other_peer_id,
926 peer2->details.local.cfg,
927 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
928 &p2_transport_connect_cache_callback,
929 occ, NULL, NULL, NULL);
932 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
933 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
934 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
939 * Test for checking whether HELLO message is empty
941 * @param cls empty flag to set
942 * @param address the HELLO
943 * @param expiration expiration of the HELLO
947 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
948 struct GNUNET_TIME_Absolute expiration)
958 * Function called whenever there is an update to the HELLO of peers in the
959 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
960 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
963 * @param hello our updated HELLO
966 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
968 struct OverlayConnectContext *occ = cls;
972 msize = ntohs (hello->size);
974 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
975 hello, GNUNET_NO, &test_address,
977 if (GNUNET_YES == empty)
979 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n", occ->op_id,
980 GNUNET_i2s (&occ->peer_identity));
983 LOG_DEBUG ("0x%llx: Received HELLO of %s\n", occ->op_id,
984 GNUNET_i2s (&occ->peer_identity));
985 occ->hello = GNUNET_malloc (msize);
986 GST_cache_add_hello (occ->peer->id, hello);
987 memcpy (occ->hello, hello, msize);
988 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
990 GST_connection_pool_get_handle_done (occ->cgh_p1th);
991 occ->cgh_p1th = NULL;
993 GNUNET_free_non_null (occ->emsg);
995 p2_transport_connect (occ);
1000 * Callback from cache with needed handles set
1002 * @param cls the closure passed to GST_cache_get_handle_transport()
1003 * @param ch the handle to CORE. Can be NULL if it is not requested
1004 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1005 * @param ignore_ peer identity which is ignored in this callback
1008 p1_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch,
1009 struct GNUNET_TRANSPORT_Handle *th,
1010 const struct GNUNET_PeerIdentity *ignore_)
1012 struct OverlayConnectContext *occ = cls;
1014 GNUNET_free_non_null (occ->emsg);
1018 GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s",
1019 occ->op_id, GNUNET_i2s (&occ->peer_identity));
1020 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1022 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1025 GNUNET_assert (NULL == occ->p1th_);
1026 GNUNET_assert (NULL != occ->cgh_p1th);
1028 GNUNET_asprintf (&occ->emsg,
1029 "0x%llx: Timeout while acquiring HELLO of peer %4s",
1030 occ->op_id, GNUNET_i2s (&occ->peer_identity));
1031 occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th_, &hello_update_cb, occ);
1036 * Callback from cache with needed handles set
1038 * @param cls the closure passed to GST_cache_get_handle_transport()
1039 * @param ch the handle to CORE. Can be NULL if it is not requested
1040 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1041 * @param my_identity the identity of our peer
1044 occ_cache_get_handle_core_cb (void *cls, struct GNUNET_CORE_Handle *ch,
1045 struct GNUNET_TRANSPORT_Handle *th,
1046 const struct GNUNET_PeerIdentity *my_identity)
1048 struct OverlayConnectContext *occ = cls;
1049 const struct GNUNET_MessageHeader *hello;
1051 GNUNET_assert (NULL != occ->timeout_task);
1052 GNUNET_free_non_null (occ->emsg);
1053 if ((NULL == ch) || (NULL == my_identity))
1055 GNUNET_asprintf (&occ->emsg,
1056 "0x%llx: Failed to connect to CORE of peer with "
1057 "id: %u", occ->op_id, occ->peer->id);
1058 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1060 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1065 GNUNET_CORE_is_peer_connected_sync (ch, &occ->other_peer_identity))
1067 LOG_DEBUG ("0x%llx: Target peer already connected\n", occ->op_id);
1068 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1069 occ->timeout_task = NULL;
1070 send_overlay_connect_success_msg (occ);
1071 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
1074 memcpy (&occ->peer_identity, my_identity,
1075 sizeof (struct GNUNET_PeerIdentity));
1076 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", occ->op_id,
1077 GNUNET_i2s (&occ->peer_identity));
1078 /* Lookup for HELLO in hello cache */
1079 if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
1081 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", occ->op_id,
1082 GNUNET_i2s (&occ->peer_identity));
1083 occ->hello = GNUNET_copy_message (hello);
1084 p2_transport_connect (occ);
1087 GNUNET_asprintf (&occ->emsg,
1088 "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
1089 occ->op_id, GNUNET_i2s (&occ->peer_identity));
1091 GST_connection_pool_get_handle (occ->peer->id,
1092 occ->peer->details.local.cfg,
1093 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1094 p1_transport_connect_cache_callback, occ,
1100 * Callback to be called when forwarded get peer config operation as part of
1101 * overlay connect is successfull. Connection to Peer 1's core is made and is
1102 * checked for new connection from peer 2
1104 * @param cls ForwardedOperationContext
1105 * @param msg the peer create success message
1108 overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg)
1110 struct OverlayConnectContext *occ = cls;
1111 struct RemotePeer2Context *rp2c;
1112 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
1114 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1115 rp2c = &occ->p2ctx.remote;
1117 GNUNET_assert (NULL != occ->timeout_task);
1118 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
1120 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1122 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1125 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1126 memcpy (&occ->other_peer_identity, &cmsg->peer_identity,
1127 sizeof (struct GNUNET_PeerIdentity));
1128 GNUNET_free_non_null (occ->emsg);
1129 GNUNET_asprintf (&occ->emsg,
1130 "0x%llx: Timeout while connecting to CORE of peer with "
1131 "id: %u", occ->op_id, occ->peer->id);
1133 GST_connection_pool_get_handle (occ->peer->id,
1134 occ->peer->details.local.cfg,
1135 GST_CONNECTIONPOOL_SERVICE_CORE,
1136 occ_cache_get_handle_core_cb, occ,
1137 &occ->other_peer_identity,
1138 &overlay_connect_notify, occ);
1144 * Callback which will be called after a host registration succeeded or failed
1146 * @param cls the RegisteredHostContext
1147 * @param emsg the error message; NULL if host registration is successful
1150 host_registration_comp (void *cls, const char *emsg)
1152 struct RegisteredHostContext *rhc = cls;
1154 rhc->state = RHC_DONE;
1155 GST_process_next_focc (rhc);
1160 * Iterator to match a registered host context
1162 * @param cls pointer 2 pointer of RegisteredHostContext
1163 * @param key current key code
1164 * @param value value in the hash map
1165 * @return GNUNET_YES if we should continue to
1170 reghost_match_iterator (void *cls, const struct GNUNET_HashCode *key,
1173 struct RegisteredHostContext **rh = cls;
1174 struct RegisteredHostContext *rh_val = value;
1176 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1187 * Function to generate the hashcode corresponding to a RegisteredHostContext
1189 * @param reg_host the host which is being registered in RegisteredHostContext
1190 * @param host the host of the controller which has to connect to the above rhost
1191 * @return the hashcode
1193 static struct GNUNET_HashCode
1194 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1195 struct GNUNET_TESTBED_Host *host)
1197 struct GNUNET_HashCode hash;
1198 uint32_t host_ids[2];
1200 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1201 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1202 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1208 * Checks if the given host is registered at the given slave.
1210 * @param slave the slave where registration has to be checked. The check is
1211 * actually done through a locally maintained hashmap. No
1212 * communication with the slave is involved.
1213 * @param host the host to register
1214 * @return If the given host is not registered already or the registration is
1215 * pending, it returns the registration context. Any overlay connects
1216 * to be forwarded should be queued in the context so that they can be
1217 * executed when the registration is completed. If the given host is
1218 * already registered, NULL is returned.
1220 static struct RegisteredHostContext *
1221 register_host (struct Slave *slave, struct GNUNET_TESTBED_Host *host)
1223 struct GNUNET_HashCode hash;
1224 struct RegisteredHostContext *rhc;
1226 rhc = GNUNET_new (struct RegisteredHostContext);
1227 rhc->reg_host = host;
1228 rhc->host = GST_host_list[slave->host_id];
1229 GNUNET_assert (NULL != rhc->reg_host);
1230 GNUNET_assert (NULL != rhc->host);
1231 rhc->state = RHC_INIT;
1232 hash = hash_hosts (rhc->reg_host, rhc->host);
1234 GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map, &hash)) ||
1236 GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
1238 reghost_match_iterator,
1241 /* create and add a new registerd host context */
1242 /* add the focc to its queue */
1243 GNUNET_CONTAINER_multihashmap_put (slave->reghost_map, &hash, rhc,
1244 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1245 GST_queue_host_registration (slave, host_registration_comp,
1246 rhc, rhc->reg_host);
1250 /* rhc is now set to the existing one from the hash map by
1251 * reghost_match_iterator() */
1252 /* if queue is empty then ignore creating focc and proceed with normal
1254 if (RHC_DONE == rhc->state)
1262 * Forwards the overlay connect request to a slave controller. Before
1263 * forwarding, any hosts which are needed to be known by the slave controller to
1264 * execute the overlay connect request are registered at slave.
1266 * @param msg the overlay connect request message to be forwarded
1267 * @param client the client to which the status of the forwarded request has to
1271 forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
1272 struct GNUNET_SERVER_Client *client)
1274 struct ForwardedOperationContext *fopc;
1275 struct Route *route_to_peer2_host;
1276 struct Route *route_to_peer1_host;
1278 struct RegisteredHostContext *rhc;
1279 struct ForwardedOverlayConnectContext *focc;
1281 uint32_t peer2_host_id;
1285 p1 = ntohl (msg->peer1);
1286 p2 = ntohl (msg->peer2);
1287 op_id = GNUNET_ntohll (msg->operation_id);
1288 peer2_host_id = ntohl (msg->peer2_host_id);
1289 GNUNET_assert (VALID_PEER_ID (p1));
1290 GNUNET_assert (VALID_HOST_ID (peer2_host_id));
1291 peer = GST_peer_list[p1];
1292 GNUNET_assert (GNUNET_YES == peer->is_remote);
1293 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
1294 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1295 route_to_peer1_host = GST_find_dest_route
1296 (peer->details.remote.remote_host_id);
1297 GNUNET_assert (NULL != route_to_peer1_host);
1298 if ((NULL != route_to_peer2_host) &&
1299 (route_to_peer1_host->dest == route_to_peer2_host->dest))
1301 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1302 different subtrees OR peer2 is on a subtree unknown to us */
1303 if (NULL != (rhc = register_host (peer->details.remote.slave,
1304 GST_host_list[peer2_host_id])))
1306 LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, p2);
1307 focc = GNUNET_new (struct ForwardedOverlayConnectContext);
1310 focc->peer2_host_id = peer2_host_id;
1311 focc->orig_msg = GNUNET_copy_message (&msg->header);
1312 focc->operation_id = op_id;
1313 focc->client = client;
1314 GNUNET_SERVER_client_keep (client);
1315 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head, rhc->focc_dll_tail,
1321 LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, p2);
1322 fopc = GNUNET_new (struct ForwardedOperationContext);
1323 GNUNET_SERVER_client_keep (client);
1324 fopc->client = client;
1325 fopc->operation_id = op_id;
1326 fopc->type = OP_OVERLAY_CONNECT;
1328 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1329 slave->controller, op_id,
1331 &GST_forwarded_operation_reply_relay,
1333 fopc->timeout_task =
1334 GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout,
1336 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
1341 * Callback called when a connection to the controller of peer2 has been
1344 * @param cls the overlay connect contexts
1345 * @param c handle to the controller connection
1348 p2_controller_connect_cb (void *cls, struct GNUNET_TESTBED_Controller *c)
1350 struct OverlayConnectContext *occ = cls;
1351 struct RemotePeer2Context *rp2c;
1352 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1354 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1355 rp2c = &occ->p2ctx.remote;
1359 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1361 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
1362 cmsg.peer_id = htonl (occ->other_peer_id);
1363 cmsg.operation_id = GNUNET_htonll (occ->op_id);
1365 GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
1366 occ->op_id, &cmsg.header,
1367 &overlay_connect_get_config,
1369 GNUNET_free_non_null (occ->emsg);
1370 GNUNET_asprintf (&occ->emsg,
1371 "0x%llx: Timeout while getting peer identity of peer "
1372 "with id: %u", occ->op_id, occ->other_peer_id);
1377 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1380 * @param client identification of the client
1381 * @param message the actual message
1384 GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
1385 const struct GNUNET_MessageHeader *message)
1387 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1390 struct OverlayConnectContext *occ;
1391 struct Neighbour *p2n;
1392 uint64_t operation_id;
1395 uint32_t peer2_host_id;
1397 if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) !=
1398 ntohs (message->size))
1401 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1404 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1405 p1 = ntohl (msg->peer1);
1406 p2 = ntohl (msg->peer2);
1407 if (!VALID_PEER_ID (p1))
1410 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1413 peer = GST_peer_list[p1];
1414 operation_id = GNUNET_ntohll (msg->operation_id);
1416 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n", p1,
1418 peer2_host_id = ntohl (msg->peer2_host_id);
1419 if (GNUNET_YES == peer->is_remote)
1421 if (!VALID_HOST_ID (peer2_host_id))
1424 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1427 forward_overlay_connect (msg, client);
1428 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1432 occ = GNUNET_new (struct OverlayConnectContext);
1433 occ->type = OCC_TYPE_LOCAL;
1434 if (!VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */
1436 if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1438 if (!VALID_HOST_ID (peer2_host_id))
1441 LOG (GNUNET_ERROR_TYPE_WARNING,
1442 "0x%llx: Peer %u's host not in our neighbours list\n",
1444 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1448 p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
1450 occ->type = OCC_TYPE_REMOTE_LATERAL;
1451 occ->p2ctx.remote.p2n = p2n;
1453 else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1455 occ->type = OCC_TYPE_REMOTE_SLAVE;
1456 occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
1458 GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ);
1459 GNUNET_SERVER_client_keep (client);
1460 occ->client = client;
1461 occ->other_peer_id = p2;
1462 GST_peer_list[p1]->reference_cnt++;
1463 occ->peer = GST_peer_list[p1];
1464 occ->op_id = operation_id;
1465 GNUNET_assert (NULL == occ->timeout_task);
1467 GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_overlay_connect, occ);
1470 case OCC_TYPE_REMOTE_LATERAL:
1471 GNUNET_asprintf (&occ->emsg,
1472 "0x%llx: Timeout while acquiring connection to peer %u's "
1473 "host: %u\n", occ->op_id, occ->other_peer_id, peer2_host_id);
1474 occ->p2ctx.remote.ncn =
1475 GST_neighbour_get_connection (p2n, &p2_controller_connect_cb, occ);
1477 case OCC_TYPE_REMOTE_SLAVE:
1478 p2_controller_connect_cb (occ, occ->p2ctx.remote.p2c);
1480 case OCC_TYPE_LOCAL:
1481 peer2 = GST_peer_list[occ->other_peer_id];
1482 peer2->reference_cnt++;
1483 GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
1484 &occ->other_peer_identity);
1485 GNUNET_asprintf (&occ->emsg,
1486 "0x%llx: Timeout while connecting to CORE of peer with "
1487 "id: %u", occ->op_id, occ->peer->id);
1489 GST_connection_pool_get_handle (occ->peer->id,
1490 occ->peer->details.local.cfg,
1491 GST_CONNECTIONPOOL_SERVICE_CORE,
1492 occ_cache_get_handle_core_cb, occ,
1493 &occ->other_peer_identity,
1494 &overlay_connect_notify, occ);
1497 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1502 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1505 * @param rocc the RemoteOverlayConnectCtx
1508 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1510 LOG_DEBUG ("0x%llx: Cleaning up rocc\n", rocc->op_id);
1511 if (NULL != rocc->attempt_connect_task_id)
1512 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1513 if (NULL != rocc->timeout_rocc_task_id)
1514 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1515 if (NULL != rocc->ohh)
1516 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1517 if (NULL != rocc->tcc.tch)
1518 GNUNET_TRANSPORT_try_connect_cancel (rocc->tcc.tch);
1519 if (NULL != rocc->tcc.task)
1520 GNUNET_SCHEDULER_cancel (rocc->tcc.task);
1521 GST_connection_pool_get_handle_done (rocc->tcc.cgh_th);
1522 GNUNET_assert (rocc->peer->reference_cnt > 0);
1523 rocc->peer->reference_cnt--;
1524 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1525 (0 == rocc->peer->reference_cnt))
1526 GST_destroy_peer (rocc->peer);
1527 GNUNET_free_non_null (rocc->hello);
1528 GNUNET_CONTAINER_DLL_remove (roccq_head, roccq_tail, rocc);
1534 * Task to timeout rocc and cleanit up
1536 * @param cls the RemoteOverlayConnectCtx
1537 * @param tc the TaskContext from scheduler
1540 timeout_rocc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1542 struct RemoteOverlayConnectCtx *rocc = cls;
1544 GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
1545 rocc->timeout_rocc_task_id = NULL;
1546 LOG_DEBUG ("0x%llx: rocc timed out\n", rocc->op_id);
1547 cleanup_rocc (rocc);
1552 * Function called to notify transport users that another
1553 * peer connected to us.
1555 * @param cls the RemoteOverlayConnectContext
1556 * @param new_peer the peer that connected
1559 cache_transport_peer_connect_notify (void *cls,
1560 const struct GNUNET_PeerIdentity *new_peer)
1562 struct RemoteOverlayConnectCtx *rocc = cls;
1564 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n", rocc->op_id);
1566 memcmp (new_peer, &rocc->a_id,
1567 sizeof (struct GNUNET_PeerIdentity)));
1568 LOG_DEBUG ("0x%llx: Peer %4s connected\n", rocc->op_id,
1569 GNUNET_i2s (&rocc->a_id));
1570 cleanup_rocc (rocc);
1575 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1576 * whose identity is in RemoteOverlayConnectCtx
1578 * @param cls the RemoteOverlayConnectCtx
1579 * @param tc the TaskContext from scheduler
1582 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1586 * Task that is run when hello has been sent
1588 * @param cls the overlay connect context
1589 * @param tc the scheduler task context; if tc->reason =
1590 * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1591 * GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1594 rocc_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1596 struct RemoteOverlayConnectCtx *rocc = cls;
1599 GNUNET_assert (NULL == rocc->attempt_connect_task_id);
1600 LOG_DEBUG ("0x%llx: HELLO of peer %4s sent to local peer with id: %u\n",
1601 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1602 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
1605 rocc->attempt_connect_task_id =
1606 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1609 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
1614 rocc->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &rocc->tcc);
1619 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1620 * whose identity is in RemoteOverlayConnectCtx
1622 * @param cls the RemoteOverlayConnectCtx
1623 * @param tc the TaskContext from scheduler
1626 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1628 struct RemoteOverlayConnectCtx *rocc = cls;
1630 GNUNET_assert (NULL != rocc->attempt_connect_task_id);
1631 rocc->attempt_connect_task_id = NULL;
1632 LOG_DEBUG ("0x%llx: Offering HELLO of peer %4s to local peer with id: %u\n",
1633 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1635 GNUNET_TRANSPORT_offer_hello (rocc->tcc.th_, rocc->hello,
1636 rocc_hello_sent_cb, rocc);
1637 if (NULL == rocc->ohh)
1638 rocc->attempt_connect_task_id =
1639 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1640 (GNUNET_TIME_UNIT_MILLISECONDS,
1642 GNUNET_CRYPTO_random_u32
1643 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1644 &attempt_connect_task, rocc);
1649 * Callback from cache with needed handles set
1651 * @param cls the closure passed to GST_cache_get_handle_transport()
1652 * @param ch the handle to CORE. Can be NULL if it is not requested
1653 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1654 * @param ignore_ peer identity which is ignored in this callback
1657 rocc_cache_get_handle_transport_cb (void *cls, struct GNUNET_CORE_Handle *ch,
1658 struct GNUNET_TRANSPORT_Handle *th,
1659 const struct GNUNET_PeerIdentity *ignore_)
1661 struct RemoteOverlayConnectCtx *rocc = cls;
1665 rocc->timeout_rocc_task_id =
1666 GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1670 rocc->tcc.pid = &rocc->a_id;
1672 GNUNET_TRANSPORT_check_peer_connected (rocc->tcc.th_, rocc->tcc.pid))
1674 LOG_DEBUG ("0x%llx: Target peer %4s already connected to local peer: %u\n",
1675 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1676 cleanup_rocc (rocc);
1679 rocc->attempt_connect_task_id =
1680 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1685 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages
1688 * @param client identification of the client
1689 * @param message the actual message
1692 GST_handle_remote_overlay_connect (void *cls,
1693 struct GNUNET_SERVER_Client *client,
1694 const struct GNUNET_MessageHeader *message)
1696 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
1697 struct RemoteOverlayConnectCtx *rocc;
1699 struct GNUNET_PeerIdentity pid;
1700 static char pid_str[16];
1705 msize = ntohs (message->size);
1706 if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize)
1709 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1712 msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message;
1713 if ((NULL == msg->hello) ||
1714 ((GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))))
1717 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1720 hsize = ntohs (msg->hello->size);
1721 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1725 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1728 peer_id = ntohl (msg->peer);
1729 if ((peer_id >= GST_peer_list_size) ||
1730 (NULL == (peer = GST_peer_list[peer_id])))
1732 GNUNET_break_op (0);
1733 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1736 if (GNUNET_YES == peer->is_remote)
1738 struct GNUNET_MessageHeader *msg2;
1740 msg2 = GNUNET_copy_message (message);
1741 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1743 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1746 rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
1747 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1748 GNUNET_CONTAINER_DLL_insert_tail (roccq_head, roccq_tail, rocc);
1749 memcpy (&rocc->a_id, &msg->peer_identity,
1750 sizeof (struct GNUNET_PeerIdentity));
1751 GNUNET_TESTING_peer_get_identity (peer->details.local.peer, &pid);
1752 (void) strncpy (pid_str, GNUNET_i2s (&pid), 15);
1753 LOG_DEBUG ("0x%llx: Remote overlay connect %4s to peer %4s with hello size: %u\n",
1754 rocc->op_id, pid_str, GNUNET_i2s (&rocc->a_id), hsize);
1756 rocc->peer->reference_cnt++;
1757 rocc->hello = GNUNET_malloc (hsize);
1758 memcpy (rocc->hello, msg->hello, hsize);
1759 rocc->tcc.op_id = rocc->op_id;
1761 GST_connection_pool_get_handle (peer_id,
1762 rocc->peer->details.local.cfg,
1763 GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
1764 &rocc_cache_get_handle_transport_cb,
1767 &cache_transport_peer_connect_notify,
1769 rocc->timeout_rocc_task_id =
1770 GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_rocc_task, rocc);
1771 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1776 * Clears all pending overlay connect contexts in queue
1781 struct OverlayConnectContext *occ;
1783 while (NULL != (occ = occq_head))
1789 * Clears all pending remote overlay connect contexts in queue
1794 struct RemoteOverlayConnectCtx *rocc;
1796 while (NULL != (rocc = roccq_head))
1797 cleanup_rocc (rocc);