2 This file is part of GNUnet.
3 (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 2, 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"
30 * Redefine LOG with a changed log component string
35 #define LOG(kind,...) \
36 GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__)
40 * Context information for requesting TRANSPORT to connect to a peer
42 struct TryConnectContext
45 * The identity of the peer to which the transport has to attempt a connection
47 struct GNUNET_PeerIdentity *pid;
50 * The transport handle obtained from cache. Do NOT close/disconnect.
52 struct GNUNET_TRANSPORT_Handle *th_;
55 * The GetCacheHandle for the p1th transport handle
57 struct GSTCacheGetHandle *cgh_th;
60 * the try connect handle
62 struct GNUNET_TRANSPORT_TryConnectHandle *tch;
67 GNUNET_SCHEDULER_TaskIdentifier task;
70 * The id of the operation which is resposible for this context
75 * The number of times we attempted to connect
83 * Types for context information we create for overlay connect requests
85 enum OverlayConnectContextType
88 * This type is used if the overlay connection is local i.e. the connection
89 * has to be made between local peers
94 * Type to be used when the first peer is local and the other peer is on a slave
95 * controller started by us
97 OCC_TYPE_REMOTE_SLAVE,
100 * Type to be used when the first peer is local and the other peer is on a
101 * controller which is not started by us.
103 OCC_TYPE_REMOTE_LATERAL
108 * Context data for operations on second peer in local overlay connection
111 struct LocalPeer2Context
114 * The handle for offering the HELLO of the first peer to the second
117 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
120 * The transport TryConnectContext
122 struct TryConnectContext tcc;
127 * Context data for operations on second peer in remote overlay connection
130 struct RemotePeer2Context
133 * Controller of peer 2; If OCC_TYPE_REMOTE_LATERAL is the type of overlay
134 * connection then this can be NULL until the connection to the controller is
137 struct GNUNET_TESTBED_Controller *p2c;
140 * Operation context for the suboperation we start to get the identity of the
143 struct OperationContext *opc;
146 * Notification handle acquire to connect to a remote controller. Only used
147 * if the type of overlay connection is OCC_TYPE_REMOTE_LATERAL.
149 struct NeighbourConnectNotification *ncn;
152 * The neighbour handle. Only used if the type of overlay connection is
153 * OCC_TYPE_REMOTE_LATERAL.
155 struct Neighbour *p2n;
159 * Context information for connecting 2 peers in overlay.
161 struct OverlayConnectContext
164 * The next pointer for maintaining a DLL of all OverlayConnectContexts
166 struct OverlayConnectContext *next;
169 * The prev pointer for maintaining a DLL of all OverlayConnectContexts
171 struct OverlayConnectContext *prev;
174 * The client which has requested for overlay connection. This is used to send
175 * either a success of failure message
177 struct GNUNET_SERVER_Client *client;
180 * the first peer which is to expect an overlay connection from the second peer.
185 * Transport handle of the first peer obtained from cache to get its HELLO. Do
186 * NOT close/disconnect.
188 struct GNUNET_TRANSPORT_Handle *p1th_;
191 * The CacheGetHandle for the p1th transport handle
193 struct GSTCacheGetHandle *cgh_p1th;
196 * The GetCacheHandle for registering callback to notify CORE level peer
197 * connects and to get our identity.
199 struct GSTCacheGetHandle *cgh_ch;
202 * HELLO of the first peer. This should be sent to the second peer.
204 struct GNUNET_MessageHeader *hello;
207 * Get GetHelloHandle to acquire a HELLO of the first peer
209 struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
212 * The error message we send if this overlay connect operation has timed out
217 * Context information for operations on the second peer
222 * Context information to be used if the second peer is local
224 struct LocalPeer2Context local;
227 * Context information to be used if the second peer is remote
229 struct RemotePeer2Context remote;
234 * The peer identity of the first peer
236 struct GNUNET_PeerIdentity peer_identity;
239 * The peer identity of the other peer
241 struct GNUNET_PeerIdentity other_peer_identity;
244 * The id of the operation responsible for creating this context
249 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
252 GNUNET_SCHEDULER_TaskIdentifier send_hello_task;
255 * The id of the overlay connect timeout task
257 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
260 * The id of the cleanup task
262 GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
265 * The type of this context information
267 enum OverlayConnectContextType type;
270 * The id of the second peer which is has to connect to the first peer
272 uint32_t other_peer_id;
277 * Context information for remote overlay connect operations. Remote overlay
278 * connections are used when peers A and B reside on different hosts. In these
279 * operations the host controller for peer B is asked by the host controller of
280 * peer A to make peer B connect to peer A by sending the controller of peer B
281 * the HELLO of peer A.
283 struct RemoteOverlayConnectCtx
286 * the next pointer for DLL
288 struct RemoteOverlayConnectCtx *next;
291 * the prev pointer for DLL
293 struct RemoteOverlayConnectCtx *prev;
296 * The peer handle of peer B
303 struct GNUNET_MessageHeader *hello;
306 * The handle for offering HELLO
308 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
311 * The transport try connect context
313 struct TryConnectContext tcc;
316 * The peer identity of peer A
318 struct GNUNET_PeerIdentity a_id;
321 * Task for offering HELLO of A to B and doing try_connect
323 GNUNET_SCHEDULER_TaskIdentifier attempt_connect_task_id;
326 * Task to timeout RequestOverlayConnect
328 GNUNET_SCHEDULER_TaskIdentifier timeout_rocc_task_id;
331 * The id of the operation responsible for creating this context
338 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
340 static struct OverlayConnectContext *occq_head;
343 * DLL tail for OverlayConnectContext DLL
345 static struct OverlayConnectContext *occq_tail;
348 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
351 static struct RemoteOverlayConnectCtx *roccq_head;
354 * DLL tail for RequectOverlayConnectContext DLL
356 static struct RemoteOverlayConnectCtx *roccq_tail;
360 * Cleans up ForwardedOverlayConnectContext
362 * @param focc the ForwardedOverlayConnectContext to cleanup
365 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
367 GNUNET_free_non_null (focc->orig_msg);
373 * Timeout task for cancelling a forwarded overlay connect connect
375 * @param cls the ForwardedOverlayConnectContext
376 * @param tc the task context from the scheduler
379 forwarded_overlay_connect_timeout (void *cls,
380 const struct GNUNET_SCHEDULER_TaskContext
383 struct ForwardedOperationContext *fopc = cls;
384 struct RegisteredHostContext *rhc;
385 struct ForwardedOverlayConnectContext *focc;
388 focc = rhc->focc_dll_head;
389 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
390 GST_cleanup_focc (focc);
391 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1,
393 GST_forwarded_operation_timeout (cls, tc);
394 if (NULL != rhc->focc_dll_head)
395 GST_process_next_focc (rhc);
400 * Callback to be called when forwarded overlay connection operation has a reply
401 * from the sub-controller successfull. We have to relay the reply msg back to
404 * @param cls ForwardedOperationContext
405 * @param msg the peer create success message
408 forwarded_overlay_connect_listener (void *cls,
409 const struct GNUNET_MessageHeader *msg)
411 struct ForwardedOperationContext *fopc = cls;
412 struct RegisteredHostContext *rhc;
413 struct ForwardedOverlayConnectContext *focc;
416 GST_forwarded_operation_reply_relay (cls, msg);
417 focc = rhc->focc_dll_head;
418 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
419 GST_cleanup_focc (focc);
420 if (NULL != rhc->focc_dll_head)
421 GST_process_next_focc (rhc);
426 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
428 * @param rhc the RegisteredHostContext
431 GST_process_next_focc (struct RegisteredHostContext *rhc)
433 struct ForwardedOperationContext *fopc;
434 struct ForwardedOverlayConnectContext *focc;
436 focc = rhc->focc_dll_head;
437 GNUNET_assert (NULL != focc);
438 GNUNET_assert (RHC_OL_CONNECT == rhc->state);
439 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
440 GNUNET_SERVER_client_keep (rhc->client);
441 fopc->client = rhc->client;
442 fopc->operation_id = focc->operation_id;
444 fopc->type = OP_OVERLAY_CONNECT;
446 GNUNET_TESTBED_forward_operation_msg_ (rhc->gateway->controller,
447 focc->operation_id, focc->orig_msg,
448 &forwarded_overlay_connect_listener,
450 GNUNET_free (focc->orig_msg);
451 focc->orig_msg = NULL;
453 GNUNET_SCHEDULER_add_delayed (GST_timeout, &forwarded_overlay_connect_timeout,
455 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
460 * Cleans up any used handles in local peer2 context
462 * @param lp2c the local peer2 context information
465 cleanup_occ_lp2c (struct LocalPeer2Context *lp2c)
467 if (NULL != lp2c->ohh)
468 GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh);
469 if (NULL != lp2c->tcc.cgh_th)
470 GST_cache_get_handle_done (lp2c->tcc.cgh_th);
471 if (NULL != lp2c->tcc.tch)
472 GNUNET_TRANSPORT_try_connect_cancel (lp2c->tcc.tch);
473 if (GNUNET_SCHEDULER_NO_TASK != lp2c->tcc.task)
474 GNUNET_SCHEDULER_cancel (lp2c->tcc.task);
479 * Cleans up any used handles in remote peer2 context. Relinquishes the
480 * remote controller connection if it has been established on-demand.
482 * @param rp2c the remote peer2 context information
485 cleanup_occ_rp2c (struct RemotePeer2Context *rp2c)
487 if (NULL != rp2c->opc)
488 GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc);
489 if (NULL != rp2c->ncn)
490 GST_neighbour_get_connection_cancel (rp2c->ncn);
491 if ( (NULL != rp2c->p2c) && (NULL != rp2c->p2n) )
492 GST_neighbour_release_connection (rp2c->p2n);
497 * Condition for checking if given peer is ready to be destroyed
499 * @param peer the peer to check
501 #define PEER_EXPIRED(peer) \
502 ( (GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt) )
505 * Cleanup overlay connect context structure
507 * @param occ the overlay connect context
510 cleanup_occ (struct OverlayConnectContext *occ)
514 LOG_DEBUG ("0x%llx: Cleaning up occ\n", occ->op_id);
515 GNUNET_free_non_null (occ->emsg);
516 GNUNET_free_non_null (occ->hello);
517 GNUNET_SERVER_client_drop (occ->client);
518 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
519 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
520 if (GNUNET_SCHEDULER_NO_TASK != occ->cleanup_task)
521 GNUNET_SCHEDULER_cancel (occ->cleanup_task);
522 if (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task)
523 GNUNET_SCHEDULER_cancel (occ->timeout_task);
524 if (NULL != occ->cgh_ch)
525 GST_cache_get_handle_done (occ->cgh_ch);
526 if (NULL != occ->ghh)
527 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
528 if (NULL != occ->cgh_p1th)
529 GST_cache_get_handle_done (occ->cgh_p1th);
530 GNUNET_assert (NULL != GST_peer_list);
531 GNUNET_assert (occ->peer->reference_cnt > 0);
532 occ->peer->reference_cnt--;
533 if (PEER_EXPIRED (occ->peer))
534 GST_destroy_peer (occ->peer);
538 peer2 = GST_peer_list[occ->other_peer_id];
539 GNUNET_assert (peer2->reference_cnt > 0);
540 peer2->reference_cnt--;
541 if (PEER_EXPIRED (peer2))
542 GST_destroy_peer (peer2);
543 cleanup_occ_lp2c (&occ->p2ctx.local);
545 case OCC_TYPE_REMOTE_SLAVE:
546 case OCC_TYPE_REMOTE_LATERAL:
547 cleanup_occ_rp2c (&occ->p2ctx.remote);
550 GNUNET_CONTAINER_DLL_remove (occq_head, occq_tail, occ);
556 * Task for cleaing up overlay connect context structure
558 * @param cls the overlay connect context
559 * @param tc the task context
562 do_cleanup_occ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
564 struct OverlayConnectContext *occ = cls;
566 occ->cleanup_task = GNUNET_SCHEDULER_NO_TASK;
572 * Task which will be run when overlay connect request has been timed out
574 * @param cls the OverlayConnectContext
575 * @param tc the TaskContext
578 timeout_overlay_connect (void *cls,
579 const struct GNUNET_SCHEDULER_TaskContext *tc)
581 struct OverlayConnectContext *occ = cls;
583 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
584 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
585 /* LOG (GNUNET_ERROR_TYPE_WARNING, */
586 /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
587 /* occ->peer->id, occ->other_peer_id, occ->emsg); */
588 GST_send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
594 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
596 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
598 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
600 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
602 htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
603 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
604 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
605 msg->peer1 = htonl (occ->peer->id);
606 msg->peer2 = htonl (occ->other_peer_id);
607 msg->operation_id = GNUNET_htonll (occ->op_id);
608 GST_queue_message (occ->client, &msg->header);
613 * Function called to notify transport users that another
614 * peer connected to us.
617 * @param new_peer the peer that connected
620 overlay_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer)
622 struct OverlayConnectContext *occ = cls;
623 struct LocalPeer2Context *lp2c;
625 char *other_peer_str;
627 LOG_DEBUG ("Overlay connect notify\n");
629 memcmp (new_peer, &occ->peer_identity,
630 sizeof (struct GNUNET_PeerIdentity)))
632 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
633 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
635 memcmp (new_peer, &occ->other_peer_identity,
636 sizeof (struct GNUNET_PeerIdentity)))
638 LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n",
639 new_peer_str, other_peer_str);
640 GNUNET_free (new_peer_str);
641 GNUNET_free (other_peer_str);
644 GNUNET_free (new_peer_str);
645 LOG_DEBUG ("0x%llx: Peer %4s connected to peer %4s\n", occ->op_id,
646 other_peer_str, GNUNET_i2s (&occ->peer_identity));
647 GNUNET_free (other_peer_str);
648 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
650 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
651 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
653 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
654 GNUNET_SCHEDULER_cancel (occ->timeout_task);
655 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
656 if (OCC_TYPE_LOCAL == occ->type)
658 lp2c = &occ->p2ctx.local;
659 if (GNUNET_SCHEDULER_NO_TASK != lp2c->tcc.task)
661 GNUNET_SCHEDULER_cancel (lp2c->tcc.task);
662 lp2c->tcc.task = GNUNET_SCHEDULER_NO_TASK;
665 GNUNET_free_non_null (occ->emsg);
667 send_overlay_connect_success_msg (occ);
668 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
673 * Task to ask transport of a peer to connect to another peer
675 * @param cls the TryConnectContext
676 * @param tc the scheduler task context
679 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
683 * Callback to be called with result of the try connect request.
685 * @param cls the overlay connect context
686 * @param result GNUNET_OK if message was transmitted to transport service
687 * GNUNET_SYSERR if message was not transmitted to transport service
690 try_connect_cb (void *cls, const int result)
692 struct TryConnectContext *tcc = cls;
695 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == tcc->task);
697 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
698 (GNUNET_TIME_UNIT_MILLISECONDS,
699 500 + pow (2, ++tcc->retries)),
700 &try_connect_task, tcc);
705 * Task to ask transport of a peer to connect to another peer
707 * @param cls the TryConnectContext
708 * @param tc the scheduler task context
711 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
713 struct TryConnectContext *tcc = cls;
715 tcc->task = GNUNET_SCHEDULER_NO_TASK;
716 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
718 GNUNET_assert (NULL == tcc->tch);
719 GNUNET_assert (NULL != tcc->pid);
720 GNUNET_assert (NULL != tcc->th_);
721 GNUNET_assert (NULL != tcc->cgh_th);
722 LOG_DEBUG ("0x%llx: Trail %u to connect to peer %4s\n", tcc->op_id,
723 tcc->retries, GNUNET_i2s (tcc->pid));
725 GNUNET_TRANSPORT_try_connect (tcc->th_, tcc->pid, &try_connect_cb, tcc);
730 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
733 * @param cls the OverlayConnectContext
734 * @param tc the TaskContext from scheduler
737 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
741 * Task that is run when hello has been sent
743 * @param cls the overlay connect context
744 * @param tc the scheduler task context; if tc->reason =
745 * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
746 * GNUNET_SCHEDULER_REASON_READ_READY is succeeded
749 occ_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
751 struct OverlayConnectContext *occ = cls;
752 struct LocalPeer2Context *lp2c;
754 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
755 lp2c = &occ->p2ctx.local;
757 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->send_hello_task);
758 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
760 GNUNET_free_non_null (occ->emsg);
761 GNUNET_asprintf (&occ->emsg,
762 "0x%llx: Timeout while offering HELLO to other peer",
764 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
767 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
769 GNUNET_free_non_null (occ->emsg);
770 GNUNET_asprintf (&occ->emsg,
771 "0x%llx: Timeout during TRANSPORT_try_connect() "
772 "at peer %4s", occ->op_id,
773 GNUNET_i2s(&occ->peer_identity));
774 lp2c->tcc.pid = &occ->peer_identity;
775 lp2c->tcc.op_id = occ->op_id;
776 lp2c->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &lp2c->tcc);
781 * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
784 * @param occ the overlay connect context. Its type must be either
785 * OCC_TYPE_REMOTE_SLAVE or OCC_TYPE_REMOTE_LATERAL
788 send_hello_thru_rocc (struct OverlayConnectContext *occ)
790 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
791 char *other_peer_str;
795 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
796 GNUNET_assert (NULL != occ->hello);
797 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
798 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote "
799 "Overlay Request\n", occ->op_id,
800 GNUNET_i2s (&occ->peer_identity), ntohs (occ->hello->size),
802 GNUNET_free (other_peer_str);
803 hello_size = ntohs (occ->hello->size);
805 sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
806 msg = GNUNET_malloc (msize);
808 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
809 msg->header.size = htons (msize);
810 msg->peer = htonl (occ->other_peer_id);
811 msg->operation_id = GNUNET_htonll (occ->op_id);
812 (void) memcpy (&msg->peer_identity, &occ->peer_identity,
813 sizeof (struct GNUNET_PeerIdentity));
814 memcpy (msg->hello, occ->hello, hello_size);
815 GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c, &msg->header);
820 * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered
821 * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
822 * send_hello_thru_rocc()
824 * @param cls the OverlayConnectContext
825 * @param tc the TaskContext from scheduler
828 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
830 struct OverlayConnectContext *occ = cls;
831 struct LocalPeer2Context *lp2c;
832 char *other_peer_str;
834 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
835 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
837 GNUNET_assert (NULL != occ->hello);
838 if (OCC_TYPE_LOCAL != occ->type)
840 send_hello_thru_rocc (occ);
843 lp2c = &occ->p2ctx.local;
844 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
845 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n", occ->op_id,
846 GNUNET_i2s (&occ->peer_identity), other_peer_str);
847 GNUNET_free (other_peer_str);
849 GNUNET_TRANSPORT_offer_hello (lp2c->tcc.th_, occ->hello,
850 occ_hello_sent_cb, occ);
851 if (NULL == lp2c->ohh)
854 occ->send_hello_task =
855 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
856 (GNUNET_TIME_UNIT_MILLISECONDS,
858 GNUNET_CRYPTO_random_u32
859 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
866 * Callback from cache with needed handles set
868 * @param cls the closure passed to GST_cache_get_handle_transport()
869 * @param ch the handle to CORE. Can be NULL if it is not requested
870 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
871 * @param ignore_ peer identity which is ignored in this callback
874 p2_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch,
875 struct GNUNET_TRANSPORT_Handle *th,
876 const struct GNUNET_PeerIdentity *ignore_)
878 struct OverlayConnectContext *occ = cls;
880 GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
883 GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s",
884 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
885 GNUNET_SCHEDULER_cancel (occ->timeout_task);
887 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
890 occ->p2ctx.local.tcc.th_ = th;
891 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
892 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
893 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
898 * Connects to the transport of the other peer if it is a local peer and
899 * schedules the send hello task
901 * @param occ the overlay connect context
904 p2_transport_connect (struct OverlayConnectContext *occ)
908 GNUNET_assert (NULL == occ->emsg);
909 GNUNET_assert (NULL != occ->hello);
910 GNUNET_assert (NULL == occ->ghh);
911 GNUNET_assert (NULL == occ->p1th_);
912 GNUNET_assert (NULL == occ->cgh_p1th);
913 if (OCC_TYPE_LOCAL == occ->type)
915 GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
916 occ->p2ctx.local.tcc.cgh_th =
917 GST_cache_get_handle_transport (occ->other_peer_id,
918 peer2->details.local.cfg,
919 &p2_transport_connect_cache_callback,
920 occ, NULL, NULL, NULL);
923 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
924 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
925 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
930 * Test for checking whether HELLO message is empty
932 * @param cls empty flag to set
933 * @param address the HELLO
934 * @param expiration expiration of the HELLO
938 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
939 struct GNUNET_TIME_Absolute expiration)
949 * Function called whenever there is an update to the HELLO of peers in the
950 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
951 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
954 * @param hello our updated HELLO
957 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
959 struct OverlayConnectContext *occ = cls;
963 msize = ntohs (hello->size);
965 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
966 hello, GNUNET_NO, &test_address,
968 if (GNUNET_YES == empty)
970 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n", occ->op_id,
971 GNUNET_i2s (&occ->peer_identity));
974 LOG_DEBUG ("0x%llx: Received HELLO of %s\n", occ->op_id,
975 GNUNET_i2s (&occ->peer_identity));
976 occ->hello = GNUNET_malloc (msize);
977 GST_cache_add_hello (occ->peer->id, hello);
978 memcpy (occ->hello, hello, msize);
979 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
981 GST_cache_get_handle_done (occ->cgh_p1th);
982 occ->cgh_p1th = NULL;
984 GNUNET_free_non_null (occ->emsg);
986 p2_transport_connect (occ);
991 * Callback from cache with needed handles set
993 * @param cls the closure passed to GST_cache_get_handle_transport()
994 * @param ch the handle to CORE. Can be NULL if it is not requested
995 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
996 * @param ignore_ peer identity which is ignored in this callback
999 p1_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch,
1000 struct GNUNET_TRANSPORT_Handle *th,
1001 const struct GNUNET_PeerIdentity *ignore_)
1003 struct OverlayConnectContext *occ = cls;
1005 GNUNET_free_non_null (occ->emsg);
1009 GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s",
1010 occ->op_id, GNUNET_i2s (&occ->peer_identity));
1011 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1013 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1016 GNUNET_assert (NULL == occ->p1th_);
1017 GNUNET_assert (NULL != occ->cgh_p1th);
1019 GNUNET_asprintf (&occ->emsg,
1020 "0x%llx: Timeout while acquiring HELLO of peer %4s",
1021 occ->op_id, GNUNET_i2s (&occ->peer_identity));
1022 occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th_, &hello_update_cb, occ);
1027 * Callback from cache with needed handles set
1029 * @param cls the closure passed to GST_cache_get_handle_transport()
1030 * @param ch the handle to CORE. Can be NULL if it is not requested
1031 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1032 * @param my_identity the identity of our peer
1035 occ_cache_get_handle_core_cb (void *cls, struct GNUNET_CORE_Handle *ch,
1036 struct GNUNET_TRANSPORT_Handle *th,
1037 const struct GNUNET_PeerIdentity *my_identity)
1039 struct OverlayConnectContext *occ = cls;
1040 const struct GNUNET_MessageHeader *hello;
1042 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
1043 GNUNET_free_non_null (occ->emsg);
1044 if ((NULL == ch) || (NULL == my_identity))
1046 GNUNET_asprintf (&occ->emsg,
1047 "0x%llx: Failed to connect to CORE of peer with "
1048 "id: %u", occ->op_id, occ->peer->id);
1049 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1051 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1056 GNUNET_CORE_is_peer_connected_sync (ch, &occ->other_peer_identity))
1058 LOG_DEBUG ("0x%llx: Target peer already connected\n", occ->op_id);
1059 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1060 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1061 send_overlay_connect_success_msg (occ);
1062 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
1065 memcpy (&occ->peer_identity, my_identity,
1066 sizeof (struct GNUNET_PeerIdentity));
1067 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", occ->op_id,
1068 GNUNET_i2s (&occ->peer_identity));
1069 /* Lookup for HELLO in hello cache */
1070 if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
1072 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", occ->op_id,
1073 GNUNET_i2s (&occ->peer_identity));
1074 occ->hello = GNUNET_copy_message (hello);
1075 p2_transport_connect (occ);
1078 GNUNET_asprintf (&occ->emsg,
1079 "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
1080 occ->op_id, GNUNET_i2s (&occ->peer_identity));
1082 GST_cache_get_handle_transport (occ->peer->id,
1083 occ->peer->details.local.cfg,
1084 p1_transport_connect_cache_callback, occ,
1090 * Callback to be called when forwarded get peer config operation as part of
1091 * overlay connect is successfull. Connection to Peer 1's core is made and is
1092 * checked for new connection from peer 2
1094 * @param cls ForwardedOperationContext
1095 * @param msg the peer create success message
1098 overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg)
1100 struct OverlayConnectContext *occ = cls;
1101 struct RemotePeer2Context *rp2c;
1102 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
1104 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1105 rp2c = &occ->p2ctx.remote;
1107 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
1108 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION != ntohs (msg->type))
1110 GNUNET_SCHEDULER_cancel (occ->timeout_task);
1112 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
1115 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1116 memcpy (&occ->other_peer_identity, &cmsg->peer_identity,
1117 sizeof (struct GNUNET_PeerIdentity));
1118 GNUNET_free_non_null (occ->emsg);
1119 GNUNET_asprintf (&occ->emsg,
1120 "0x%llx: Timeout while connecting to CORE of peer with "
1121 "id: %u", occ->op_id, occ->peer->id);
1123 GST_cache_get_handle_core (occ->peer->id, occ->peer->details.local.cfg,
1124 occ_cache_get_handle_core_cb, occ,
1125 &occ->other_peer_identity,
1126 &overlay_connect_notify, occ);
1132 * Callback which will be called after a host registration succeeded or failed
1134 * @param cls the RegisteredHostContext
1135 * @param emsg the error message; NULL if host registration is successful
1138 registeredhost_registration_completion (void *cls, const char *emsg)
1140 struct RegisteredHostContext *rhc = cls;
1141 const struct GNUNET_CONFIGURATION_Handle *cfg;
1142 uint32_t peer2_host_id;
1144 peer2_host_id = GNUNET_TESTBED_host_get_id_ (rhc->reg_host);
1145 GNUNET_assert (RHC_INIT == rhc->state);
1146 GNUNET_assert (NULL == rhc->sub_op);
1147 if ((NULL == rhc->gateway2) ||
1148 ( (peer2_host_id < GST_host_list_size) /* Check if we have the needed config */
1149 && (NULL != GST_host_list[peer2_host_id]) ) )
1151 rhc->state = RHC_LINK;
1154 rhc->gateway2) ? our_config
1155 : GNUNET_TESTBED_host_get_cfg_ (GST_host_list[peer2_host_id]);
1157 GNUNET_TESTBED_controller_link (rhc, rhc->gateway->controller,
1158 rhc->reg_host, rhc->host, cfg,
1162 rhc->state = RHC_GET_CFG;
1164 GNUNET_TESTBED_get_slave_config (rhc, rhc->gateway2->controller,
1170 * Iterator to match a registered host context
1172 * @param cls pointer 2 pointer of RegisteredHostContext
1173 * @param key current key code
1174 * @param value value in the hash map
1175 * @return GNUNET_YES if we should continue to
1180 reghost_match_iterator (void *cls, const struct GNUNET_HashCode *key,
1183 struct RegisteredHostContext **rh = cls;
1184 struct RegisteredHostContext *rh_val = value;
1186 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1197 * Function to generate the hashcode corresponding to a RegisteredHostContext
1199 * @param reg_host the host which is being registered in RegisteredHostContext
1200 * @param host the host of the controller which has to connect to the above rhost
1201 * @return the hashcode
1203 static struct GNUNET_HashCode
1204 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1205 struct GNUNET_TESTBED_Host *host)
1207 struct GNUNET_HashCode hash;
1208 uint32_t host_ids[2];
1210 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1211 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1212 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1218 * Forwards the overlay connect request to a slave controller. Before
1219 * forwarding, any hosts which are needed to be known by the slave controller to
1220 * execute the overlay connect request are registered at slave.
1222 * @param msg the overlay connect request message to be forwarded
1223 * @param client the client to which the status of the forwarded request has to
1227 forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
1228 struct GNUNET_SERVER_Client *client)
1230 struct ForwardedOperationContext *fopc;
1231 struct Route *route_to_peer2_host;
1232 struct Route *route_to_peer1_host;
1235 uint32_t peer2_host_id;
1239 p1 = ntohl (msg->peer1);
1240 p2 = ntohl (msg->peer2);
1241 op_id = GNUNET_ntohll (msg->operation_id);
1242 peer2_host_id = ntohl (msg->peer2_host_id);
1243 GNUNET_assert (p1 < GST_peer_list_size);
1244 GNUNET_assert (NULL != (peer = GST_peer_list[p1]));
1245 GNUNET_assert (GNUNET_YES == peer->is_remote);
1246 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
1247 route_to_peer2_host = NULL;
1248 route_to_peer1_host = NULL;
1249 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1250 if ((NULL != route_to_peer2_host) ||
1251 (peer2_host_id == GST_context->host_id))
1253 /* Peer 2 either below us OR with us */
1254 route_to_peer1_host =
1255 GST_find_dest_route (GST_peer_list[p1]->details.
1256 remote.remote_host_id);
1257 /* Because we get this message only if we know where peer 1 is */
1258 GNUNET_assert (NULL != route_to_peer1_host);
1259 if ((peer2_host_id == GST_context->host_id) ||
1260 (route_to_peer2_host->dest != route_to_peer1_host->dest))
1262 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1263 * different gateways */
1264 struct GNUNET_HashCode hash;
1265 struct RegisteredHostContext *rhc;
1268 rhc = GNUNET_malloc (sizeof (struct RegisteredHostContext));
1269 rhc->type = CLOSURE_TYPE_RHC;
1270 if (NULL != route_to_peer2_host)
1271 rhc->reg_host = GST_host_list[route_to_peer2_host->dest];
1273 rhc->reg_host = GST_host_list[GST_context->host_id];
1274 rhc->host = GST_host_list[route_to_peer1_host->dest];
1275 GNUNET_assert (NULL != rhc->reg_host);
1276 GNUNET_assert (NULL != rhc->host);
1277 rhc->gateway = peer->details.remote.slave;
1280 route_to_peer2_host) ? NULL :
1281 GST_slave_list[route_to_peer2_host->dest];
1282 rhc->state = RHC_INIT;
1283 GNUNET_SERVER_client_keep (client);
1284 rhc->client = client;
1285 hash = hash_hosts (rhc->reg_host, rhc->host);
1286 skip_focc = GNUNET_NO;
1288 GNUNET_CONTAINER_multihashmap_contains (peer->details.
1289 remote.slave->reghost_map,
1292 GNUNET_CONTAINER_multihashmap_get_multiple (peer->details.remote.
1295 reghost_match_iterator,
1298 /* create and add a new registerd host context */
1299 /* add the focc to its queue */
1300 GNUNET_CONTAINER_multihashmap_put (peer->details.remote.
1301 slave->reghost_map, &hash, rhc,
1302 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1303 GNUNET_assert (NULL != GST_host_list[peer2_host_id]);
1304 GST_queue_host_registration (peer->details.remote.slave,
1305 registeredhost_registration_completion,
1306 rhc, GST_host_list[peer2_host_id]);
1310 /* rhc is now set to the existing one from the hash map by
1311 * reghost_match_iterator() */
1312 /* if queue is empty then ignore creating focc and proceed with
1313 * normal forwarding */
1314 if (RHC_OL_CONNECT == rhc->state)
1315 skip_focc = GNUNET_YES;
1317 if (GNUNET_NO == skip_focc)
1319 struct ForwardedOverlayConnectContext *focc;
1321 focc = GNUNET_malloc (sizeof (struct ForwardedOverlayConnectContext));
1324 focc->peer2_host_id = peer2_host_id;
1325 focc->orig_msg = GNUNET_copy_message (&msg->header);
1326 focc->operation_id = op_id;
1327 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
1328 rhc->focc_dll_tail, focc);
1333 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1334 GNUNET_SERVER_client_keep (client);
1335 fopc->client = client;
1336 fopc->operation_id = op_id;
1337 fopc->type = OP_OVERLAY_CONNECT;
1339 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1340 slave->controller, op_id,
1342 &GST_forwarded_operation_reply_relay,
1344 fopc->timeout_task =
1345 GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout,
1347 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
1352 * Callback called when a connection to the controller of peer2 has been
1355 * @param cls the overlay connect contexts
1356 * @param c handle to the controller connection
1359 p2_controller_connect_cb (void *cls, struct GNUNET_TESTBED_Controller *c)
1361 struct OverlayConnectContext *occ = cls;
1362 struct RemotePeer2Context *rp2c;
1363 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1365 GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
1366 rp2c = &occ->p2ctx.remote;
1370 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1372 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION);
1373 cmsg.peer_id = htonl (occ->other_peer_id);
1374 cmsg.operation_id = GNUNET_htonll (occ->op_id);
1376 GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
1377 occ->op_id, &cmsg.header,
1378 &overlay_connect_get_config,
1380 GNUNET_free_non_null (occ->emsg);
1381 GNUNET_asprintf (&occ->emsg,
1382 "0x%llx: Timeout while getting peer identity of peer "
1383 "with id: %u", occ->op_id, occ->other_peer_id);
1388 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1391 * @param client identification of the client
1392 * @param message the actual message
1395 GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
1396 const struct GNUNET_MessageHeader *message)
1398 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1401 struct OverlayConnectContext *occ;
1402 struct Neighbour *p2n;
1403 uint64_t operation_id;
1406 uint32_t peer2_host_id;
1408 if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) !=
1409 ntohs (message->size))
1412 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1415 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1416 p1 = ntohl (msg->peer1);
1417 p2 = ntohl (msg->peer2);
1418 if ((p1 >= GST_peer_list_size) || (NULL == GST_peer_list[p1]))
1421 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1424 peer = GST_peer_list[p1];
1425 operation_id = GNUNET_ntohll (msg->operation_id);
1427 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n", p1,
1429 if (GNUNET_YES == peer->is_remote)
1431 forward_overlay_connect (msg, client);
1432 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1436 occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
1437 occ->type = OCC_TYPE_LOCAL;
1438 peer2_host_id = ntohl (msg->peer2_host_id);
1439 if ((p2 >= GST_peer_list_size) || (NULL == GST_peer_list[p2]))
1441 if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1444 LOG (GNUNET_ERROR_TYPE_WARNING,
1445 "0x%llx: Peer %u's host not in our neighbours list\n",
1447 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1451 occ->type = OCC_TYPE_REMOTE_LATERAL;
1452 occ->p2ctx.remote.p2n = p2n;
1454 else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1456 occ->type = OCC_TYPE_REMOTE_SLAVE;
1457 occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
1459 GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ);
1460 GNUNET_SERVER_client_keep (client);
1461 occ->client = client;
1462 occ->other_peer_id = p2;
1463 GST_peer_list[p1]->reference_cnt++;
1464 occ->peer = GST_peer_list[p1];
1465 occ->op_id = operation_id;
1466 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->timeout_task);
1468 GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_overlay_connect, occ);
1471 case OCC_TYPE_REMOTE_LATERAL:
1472 GNUNET_asprintf (&occ->emsg,
1473 "0x%llx: Timeout while acquiring connection to peer %u's "
1474 "host: %u\n", occ->op_id, occ->other_peer_id, peer2_host_id);
1475 occ->p2ctx.remote.ncn =
1476 GST_neighbour_get_connection (p2n, &p2_controller_connect_cb, occ);
1478 case OCC_TYPE_REMOTE_SLAVE:
1479 p2_controller_connect_cb (occ, occ->p2ctx.remote.p2c);
1481 case OCC_TYPE_LOCAL:
1482 peer2 = GST_peer_list[occ->other_peer_id];
1483 peer2->reference_cnt++;
1484 GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
1485 &occ->other_peer_identity);
1486 GNUNET_asprintf (&occ->emsg,
1487 "0x%llx: Timeout while connecting to CORE of peer with "
1488 "id: %u", occ->op_id, occ->peer->id);
1490 GST_cache_get_handle_core (occ->peer->id, occ->peer->details.local.cfg,
1491 occ_cache_get_handle_core_cb, occ,
1492 &occ->other_peer_identity,
1493 &overlay_connect_notify, occ);
1496 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1501 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1504 * @param rocc the RemoteOverlayConnectCtx
1507 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1509 LOG_DEBUG ("0x%llx: Cleaning up rocc\n", rocc->op_id);
1510 if (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id)
1511 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1512 if (GNUNET_SCHEDULER_NO_TASK != rocc->timeout_rocc_task_id)
1513 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1514 if (NULL != rocc->ohh)
1515 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1516 if (NULL != rocc->tcc.tch)
1517 GNUNET_TRANSPORT_try_connect_cancel (rocc->tcc.tch);
1518 if (GNUNET_SCHEDULER_NO_TASK != rocc->tcc.task)
1519 GNUNET_SCHEDULER_cancel (rocc->tcc.task);
1520 //GNUNET_TRANSPORT_disconnect (rocc->tcc.th_);
1521 GST_cache_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 != GNUNET_SCHEDULER_NO_TASK);
1545 rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_NO_TASK;
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 (GNUNET_SCHEDULER_NO_TASK == 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 (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id);
1631 rocc->attempt_connect_task_id = GNUNET_SCHEDULER_NO_TASK;
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_neighbour_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;
1703 msize = ntohs (message->size);
1704 if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize)
1707 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1710 msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message;
1711 if ((NULL == msg->hello) ||
1712 ((GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))))
1715 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1718 hsize = ntohs (msg->hello->size);
1719 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1723 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1726 peer_id = ntohl (msg->peer);
1727 if ((peer_id >= GST_peer_list_size) ||
1728 (NULL == (peer = GST_peer_list[peer_id])))
1730 GNUNET_break_op (0);
1731 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1734 if (GNUNET_YES == peer->is_remote)
1736 struct GNUNET_MessageHeader *msg2;
1738 msg2 = GNUNET_copy_message (message);
1739 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1741 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1744 rocc = GNUNET_malloc (sizeof (struct RemoteOverlayConnectCtx));
1745 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1746 GNUNET_CONTAINER_DLL_insert_tail (roccq_head, roccq_tail, rocc);
1747 memcpy (&rocc->a_id, &msg->peer_identity,
1748 sizeof (struct GNUNET_PeerIdentity));
1749 LOG_DEBUG ("Received request for overlay connection with op_id: 0x%llx "
1750 "from local peer %u to peer %4s with hello size: %u\n",
1751 rocc->op_id, peer_id, GNUNET_i2s (&rocc->a_id), hsize);
1753 rocc->peer->reference_cnt++;
1754 rocc->hello = GNUNET_malloc (hsize);
1755 memcpy (rocc->hello, msg->hello, hsize);
1757 GST_cache_get_handle_transport (peer_id, rocc->peer->details.local.cfg,
1758 &rocc_cache_get_handle_transport_cb, rocc,
1760 &cache_transport_peer_connect_notify,
1762 rocc->timeout_rocc_task_id =
1763 GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_rocc_task, rocc);
1764 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1769 * Clears all pending overlay connect contexts in queue
1774 struct OverlayConnectContext *occ;
1776 while (NULL != (occ = occq_head))
1782 * Clears all pending remote overlay connect contexts in queue
1787 struct RemoteOverlayConnectCtx *rocc;
1789 while (NULL != (rocc = roccq_head))
1790 cleanup_rocc (rocc);