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 * Context information for connecting 2 peers in overlay.
85 struct OverlayConnectContext
88 * The next pointer for maintaining a DLL of all OverlayConnectContexts
90 struct OverlayConnectContext *next;
93 * The prev pointer for maintaining a DLL of all OverlayConnectContexts
95 struct OverlayConnectContext *prev;
98 * The client which has requested for overlay connection. This is used to send
99 * either a success of failure message
101 struct GNUNET_SERVER_Client *client;
104 * the first peer which is to expect an overlay connection from the second peer.
109 * Transport handle of the first peer obtained from cache to get its HELLO. Do
110 * NOT close/disconnect.
112 struct GNUNET_TRANSPORT_Handle *p1th_;
115 * The CacheGetHandle for the p1th transport handle
117 struct GSTCacheGetHandle *cgh_p1th;
120 * The GetCacheHandle for registering callback to notify CORE level peer
121 * connects and to get our identity.
123 struct GSTCacheGetHandle *cgh_ch;
126 * HELLO of the first peer. This should be sent to the second peer.
128 struct GNUNET_MessageHeader *hello;
131 * Get GetHelloHandle to acquire a HELLO of the first peer
133 struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
136 * The handle for offering the HELLO of the first peer to the second
137 * peer. This is only used if the second peer is a local peer.
139 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
142 * The error message we send if this overlay connect operation has timed out
147 * Operation context for the suboperation we start to get the identity of the
148 * second peer if it is a remote peer
150 struct OperationContext *opc;
153 * Controller of peer 2; NULL if the peer is a local peer or until the
154 * connection to the controller is established
156 struct GNUNET_TESTBED_Controller *p2c;
158 struct NeighbourConnectNotification *p2_ncn;
160 struct Neighbour *p2n;
163 * The transport TryConnectContext. This will be NULL if the second peer is a
166 struct TryConnectContext tcc;
169 * The peer identity of the first peer
171 struct GNUNET_PeerIdentity peer_identity;
174 * The peer identity of the other peer
176 struct GNUNET_PeerIdentity other_peer_identity;
179 * The id of the operation responsible for creating this context
184 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
187 GNUNET_SCHEDULER_TaskIdentifier send_hello_task;
190 * The id of the overlay connect timeout task
192 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
195 * The id of the cleanup task
197 GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
200 * The id of the second peer which is has to connect to the first peer
202 uint32_t other_peer_id;
208 * Context information for remote overlay connect operations. Remote overlay
209 * connections are used when peers A and B reside on different hosts. In these
210 * operations the host controller for peer B is asked by the host controller of
211 * peer A to make peer B connect to peer A by sending the controller of peer B
212 * the HELLO of peer A.
214 struct RemoteOverlayConnectCtx
217 * the next pointer for DLL
219 struct RemoteOverlayConnectCtx *next;
222 * the prev pointer for DLL
224 struct RemoteOverlayConnectCtx *prev;
227 * The peer handle of peer B
234 struct GNUNET_MessageHeader *hello;
237 * The handle for offering HELLO
239 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
242 * The transport try connect context
244 struct TryConnectContext tcc;
247 * The peer identity of peer A
249 struct GNUNET_PeerIdentity a_id;
252 * Task for offering HELLO of A to B and doing try_connect
254 GNUNET_SCHEDULER_TaskIdentifier attempt_connect_task_id;
257 * Task to timeout RequestOverlayConnect
259 GNUNET_SCHEDULER_TaskIdentifier timeout_rocc_task_id;
262 * The id of the operation responsible for creating this context
269 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
271 static struct OverlayConnectContext *occq_head;
274 * DLL tail for OverlayConnectContext DLL
276 static struct OverlayConnectContext *occq_tail;
279 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
282 static struct RemoteOverlayConnectCtx *roccq_head;
285 * DLL tail for RequectOverlayConnectContext DLL
287 static struct RemoteOverlayConnectCtx *roccq_tail;
291 * Cleans up ForwardedOverlayConnectContext
293 * @param focc the ForwardedOverlayConnectContext to cleanup
296 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
298 GNUNET_free_non_null (focc->orig_msg);
304 * Timeout task for cancelling a forwarded overlay connect connect
306 * @param cls the ForwardedOverlayConnectContext
307 * @param tc the task context from the scheduler
310 forwarded_overlay_connect_timeout (void *cls,
311 const struct GNUNET_SCHEDULER_TaskContext
314 struct ForwardedOperationContext *fopc = cls;
315 struct RegisteredHostContext *rhc;
316 struct ForwardedOverlayConnectContext *focc;
319 focc = rhc->focc_dll_head;
320 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
321 GST_cleanup_focc (focc);
322 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1,
324 GST_forwarded_operation_timeout (cls, tc);
325 if (NULL != rhc->focc_dll_head)
326 GST_process_next_focc (rhc);
331 * Callback to be called when forwarded overlay connection operation has a reply
332 * from the sub-controller successfull. We have to relay the reply msg back to
335 * @param cls ForwardedOperationContext
336 * @param msg the peer create success message
339 forwarded_overlay_connect_listener (void *cls,
340 const struct GNUNET_MessageHeader *msg)
342 struct ForwardedOperationContext *fopc = cls;
343 struct RegisteredHostContext *rhc;
344 struct ForwardedOverlayConnectContext *focc;
347 GST_forwarded_operation_reply_relay (cls, msg);
348 focc = rhc->focc_dll_head;
349 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
350 GST_cleanup_focc (focc);
351 if (NULL != rhc->focc_dll_head)
352 GST_process_next_focc (rhc);
357 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
359 * @param rhc the RegisteredHostContext
362 GST_process_next_focc (struct RegisteredHostContext *rhc)
364 struct ForwardedOperationContext *fopc;
365 struct ForwardedOverlayConnectContext *focc;
367 focc = rhc->focc_dll_head;
368 GNUNET_assert (NULL != focc);
369 GNUNET_assert (RHC_OL_CONNECT == rhc->state);
370 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
371 GNUNET_SERVER_client_keep (rhc->client);
372 fopc->client = rhc->client;
373 fopc->operation_id = focc->operation_id;
375 fopc->type = OP_OVERLAY_CONNECT;
377 GNUNET_TESTBED_forward_operation_msg_ (rhc->gateway->controller,
378 focc->operation_id, focc->orig_msg,
379 &forwarded_overlay_connect_listener,
381 GNUNET_free (focc->orig_msg);
382 focc->orig_msg = NULL;
384 GNUNET_SCHEDULER_add_delayed (GST_timeout, &forwarded_overlay_connect_timeout,
386 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
391 * Cleanup overlay connect context structure
393 * @param occ the overlay connect context
396 cleanup_occ (struct OverlayConnectContext *occ)
398 struct Peer *other_peer;
400 LOG_DEBUG ("0x%llx: Cleaning up occ\n", occ->op_id);
401 GNUNET_free_non_null (occ->emsg);
402 GNUNET_free_non_null (occ->hello);
403 GNUNET_SERVER_client_drop (occ->client);
404 if (NULL != occ->opc)
405 GNUNET_TESTBED_forward_operation_msg_cancel_ (occ->opc);
406 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
407 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
408 if (GNUNET_SCHEDULER_NO_TASK != occ->cleanup_task)
409 GNUNET_SCHEDULER_cancel (occ->cleanup_task);
410 if (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task)
411 GNUNET_SCHEDULER_cancel (occ->timeout_task);
412 if (NULL != occ->cgh_ch)
413 GST_cache_get_handle_done (occ->cgh_ch);
414 if (NULL != occ->ghh)
415 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
416 if (NULL != occ->ohh)
417 GNUNET_TRANSPORT_offer_hello_cancel (occ->ohh);
418 if (GNUNET_SCHEDULER_NO_TASK != occ->tcc.task)
419 GNUNET_SCHEDULER_cancel (occ->tcc.task);
420 if (NULL != occ->tcc.tch)
421 GNUNET_TRANSPORT_try_connect_cancel (occ->tcc.tch);
422 if (NULL != occ->cgh_p1th)
423 GST_cache_get_handle_done (occ->cgh_p1th);
424 if (NULL != occ->tcc.cgh_th)
425 GST_cache_get_handle_done (occ->tcc.cgh_th);
426 if (NULL != occ->p2n)
428 if (NULL != occ->p2_ncn)
429 GST_neighbour_get_connection_cancel (occ->p2_ncn);
430 if (NULL != occ->p2c)
431 GST_neighbour_release_connection (occ->p2n);
433 GNUNET_assert (NULL != GST_peer_list);
434 GNUNET_assert (occ->peer->reference_cnt > 0);
435 occ->peer->reference_cnt--;
436 if ( (GNUNET_YES == occ->peer->destroy_flag) &&
437 (0 == occ->peer->reference_cnt) )
438 GST_destroy_peer (occ->peer);
439 if ( (occ->other_peer_id < GST_peer_list_size)
440 && (NULL != (other_peer = GST_peer_list[occ->other_peer_id]))
441 && (GNUNET_YES != other_peer->is_remote) )
443 GNUNET_assert (other_peer->reference_cnt > 0);
444 other_peer->reference_cnt--;
445 if ( (GNUNET_YES == other_peer->destroy_flag) &&
446 (0 == other_peer->reference_cnt) )
447 GST_destroy_peer (other_peer);
449 GNUNET_CONTAINER_DLL_remove (occq_head, occq_tail, occ);
455 * Task for cleaing up overlay connect context structure
457 * @param cls the overlay connect context
458 * @param tc the task context
461 do_cleanup_occ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
463 struct OverlayConnectContext *occ = cls;
465 occ->cleanup_task = GNUNET_SCHEDULER_NO_TASK;
471 * Task which will be run when overlay connect request has been timed out
473 * @param cls the OverlayConnectContext
474 * @param tc the TaskContext
477 timeout_overlay_connect (void *cls,
478 const struct GNUNET_SCHEDULER_TaskContext *tc)
480 struct OverlayConnectContext *occ = cls;
482 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
483 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
484 /* LOG (GNUNET_ERROR_TYPE_WARNING, */
485 /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
486 /* occ->peer->id, occ->other_peer_id, occ->emsg); */
487 GST_send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
493 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
495 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
497 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
499 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
501 htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
502 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
503 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
504 msg->peer1 = htonl (occ->peer->id);
505 msg->peer2 = htonl (occ->other_peer_id);
506 msg->operation_id = GNUNET_htonll (occ->op_id);
507 GST_queue_message (occ->client, &msg->header);
512 * Function called to notify transport users that another
513 * peer connected to us.
516 * @param new_peer the peer that connected
519 overlay_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer)
521 struct OverlayConnectContext *occ = cls;
523 char *other_peer_str;
525 //LOG_DEBUG ("Overlay connect notify\n");
527 memcmp (new_peer, &occ->peer_identity,
528 sizeof (struct GNUNET_PeerIdentity)))
530 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
531 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
533 memcmp (new_peer, &occ->other_peer_identity,
534 sizeof (struct GNUNET_PeerIdentity)))
536 /* LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n", */
537 /* new_peer_str, other_peer_str); */
538 GNUNET_free (new_peer_str);
539 GNUNET_free (other_peer_str);
542 GNUNET_free (new_peer_str);
543 LOG_DEBUG ("0x%llx: Peer %4s connected to peer %4s\n", occ->op_id,
544 other_peer_str, GNUNET_i2s (&occ->peer_identity));
545 GNUNET_free (other_peer_str);
546 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
548 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
549 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
551 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
552 GNUNET_SCHEDULER_cancel (occ->timeout_task);
553 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
554 if (GNUNET_SCHEDULER_NO_TASK != occ->tcc.task)
556 GNUNET_SCHEDULER_cancel (occ->tcc.task);
557 occ->tcc.task = GNUNET_SCHEDULER_NO_TASK;
559 GNUNET_free_non_null (occ->emsg);
561 send_overlay_connect_success_msg (occ);
562 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
568 * Task to ask transport of a peer to connect to another peer
570 * @param cls the TryConnectContext
571 * @param tc the scheduler task context
574 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
578 * Callback to be called with result of the try connect request.
580 * @param cls the overlay connect context
581 * @param result GNUNET_OK if message was transmitted to transport service
582 * GNUNET_SYSERR if message was not transmitted to transport service
585 try_connect_cb (void *cls, const int result)
587 struct TryConnectContext *tcc = cls;
590 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == tcc->task);
592 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
593 (GNUNET_TIME_UNIT_MILLISECONDS,
594 500 + pow (2, ++tcc->retries)),
595 &try_connect_task, tcc);
600 * Task to ask transport of a peer to connect to another peer
602 * @param cls the TryConnectContext
603 * @param tc the scheduler task context
606 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
608 struct TryConnectContext *tcc = cls;
610 tcc->task = GNUNET_SCHEDULER_NO_TASK;
611 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
613 GNUNET_assert (NULL == tcc->tch);
614 GNUNET_assert (NULL != tcc->pid);
615 GNUNET_assert (NULL != tcc->th_);
616 GNUNET_assert (NULL != tcc->cgh_th);
617 LOG_DEBUG ("0x%llx: Trail %u to connect to peer %4s\n", tcc->op_id,
618 tcc->retries, GNUNET_i2s (tcc->pid));
620 GNUNET_TRANSPORT_try_connect (tcc->th_, tcc->pid, &try_connect_cb, tcc);
625 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
628 * @param cls the OverlayConnectContext
629 * @param tc the TaskContext from scheduler
632 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
636 * Task that is run when hello has been sent
638 * @param cls the overlay connect context
639 * @param tc the scheduler task context; if tc->reason =
640 * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
641 * GNUNET_SCHEDULER_REASON_READ_READY is succeeded
644 occ_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
646 struct OverlayConnectContext *occ = cls;
649 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->send_hello_task);
650 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
652 GNUNET_free_non_null (occ->emsg);
653 GNUNET_asprintf (&occ->emsg,
654 "0x%llx: Timeout while offering HELLO to other peer",
656 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
659 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
661 GNUNET_free_non_null (occ->emsg);
662 GNUNET_asprintf (&occ->emsg,
663 "0x%llx: Timeout during TRANSPORT_try_connect() "
664 "at peer %4s", occ->op_id,
665 GNUNET_i2s(&occ->peer_identity));
666 occ->tcc.pid = &occ->peer_identity;
667 occ->tcc.op_id = occ->op_id;
668 occ->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &occ->tcc);
673 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
676 * @param cls the OverlayConnectContext
677 * @param tc the TaskContext from scheduler
680 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
682 struct OverlayConnectContext *occ = cls;
683 char *other_peer_str;
685 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
686 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
688 GNUNET_assert (NULL != occ->hello);
689 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
690 if (NULL != occ->p2c)
692 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
696 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote "
697 "Overlay Request\n", occ->op_id,
698 GNUNET_i2s (&occ->peer_identity), ntohs (occ->hello->size),
700 hello_size = ntohs (occ->hello->size);
702 sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
703 msg = GNUNET_malloc (msize);
705 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
706 msg->header.size = htons (msize);
707 msg->peer = htonl (occ->other_peer_id);
708 msg->operation_id = GNUNET_htonll (occ->op_id);
709 (void) memcpy (&msg->peer_identity, &occ->peer_identity,
710 sizeof (struct GNUNET_PeerIdentity));
711 memcpy (msg->hello, occ->hello, hello_size);
712 GNUNET_TESTBED_queue_message_ (occ->p2c, &msg->header);
716 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n", occ->op_id,
717 GNUNET_i2s (&occ->peer_identity), other_peer_str);
719 GNUNET_TRANSPORT_offer_hello (occ->tcc.th_, occ->hello,
720 occ_hello_sent_cb, occ);
721 if (NULL == occ->ohh)
724 occ->send_hello_task =
725 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
726 (GNUNET_TIME_UNIT_MILLISECONDS,
728 GNUNET_CRYPTO_random_u32
729 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
733 GNUNET_free (other_peer_str);
738 * Callback from cache with needed handles set
740 * @param cls the closure passed to GST_cache_get_handle_transport()
741 * @param ch the handle to CORE. Can be NULL if it is not requested
742 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
743 * @param ignore_ peer identity which is ignored in this callback
746 p2_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch,
747 struct GNUNET_TRANSPORT_Handle *th,
748 const struct GNUNET_PeerIdentity *ignore_)
750 struct OverlayConnectContext *occ = cls;
754 GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s",
755 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
756 GNUNET_SCHEDULER_cancel (occ->timeout_task);
758 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
762 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
763 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
764 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
769 * Connects to the transport of the other peer if it is a local peer and
770 * schedules the send hello task
772 * @param occ the overlay connect context
775 p2_transport_connect (struct OverlayConnectContext *occ)
777 GNUNET_assert (NULL == occ->emsg);
778 GNUNET_assert (NULL != occ->hello);
779 GNUNET_assert (NULL == occ->ghh);
780 GNUNET_assert (NULL == occ->p1th_);
781 GNUNET_assert (NULL == occ->cgh_p1th);
782 if (NULL == occ->p2c)
784 GNUNET_assert (NULL != GST_peer_list[occ->other_peer_id]);
786 GST_cache_get_handle_transport (occ->other_peer_id,
787 GST_peer_list[occ->other_peer_id]
789 &p2_transport_connect_cache_callback,
790 occ, NULL, NULL, NULL);
793 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
794 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
795 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
800 * Test for checking whether HELLO message is empty
802 * @param cls empty flag to set
803 * @param address the HELLO
804 * @param expiration expiration of the HELLO
808 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
809 struct GNUNET_TIME_Absolute expiration)
819 * Function called whenever there is an update to the HELLO of peers in the
820 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
821 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
824 * @param hello our updated HELLO
827 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
829 struct OverlayConnectContext *occ = cls;
833 msize = ntohs (hello->size);
835 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
836 hello, GNUNET_NO, &test_address,
838 if (GNUNET_YES == empty)
840 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n", occ->op_id,
841 GNUNET_i2s (&occ->peer_identity));
844 LOG_DEBUG ("0x%llx: Received HELLO of %s\n", occ->op_id,
845 GNUNET_i2s (&occ->peer_identity));
846 occ->hello = GNUNET_malloc (msize);
847 GST_cache_add_hello (occ->peer->id, hello);
848 memcpy (occ->hello, hello, msize);
849 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
851 GST_cache_get_handle_done (occ->cgh_p1th);
852 occ->cgh_p1th = NULL;
854 GNUNET_free_non_null (occ->emsg);
856 p2_transport_connect (occ);
861 * Callback from cache with needed handles set
863 * @param cls the closure passed to GST_cache_get_handle_transport()
864 * @param ch the handle to CORE. Can be NULL if it is not requested
865 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
866 * @param ignore_ peer identity which is ignored in this callback
869 p1_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch,
870 struct GNUNET_TRANSPORT_Handle *th,
871 const struct GNUNET_PeerIdentity *ignore_)
873 struct OverlayConnectContext *occ = cls;
875 GNUNET_free_non_null (occ->emsg);
879 GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s",
880 occ->op_id, GNUNET_i2s (&occ->peer_identity));
881 GNUNET_SCHEDULER_cancel (occ->timeout_task);
883 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
886 GNUNET_assert (NULL == occ->p1th_);
887 GNUNET_assert (NULL != occ->cgh_p1th);
889 GNUNET_asprintf (&occ->emsg,
890 "0x%llx: Timeout while acquiring HELLO of peer %4s",
891 occ->op_id, GNUNET_i2s (&occ->peer_identity));
892 occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th_, &hello_update_cb, occ);
897 * Callback from cache with needed handles set
899 * @param cls the closure passed to GST_cache_get_handle_transport()
900 * @param ch the handle to CORE. Can be NULL if it is not requested
901 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
902 * @param my_identity the identity of our peer
905 occ_cache_get_handle_core_cb (void *cls, struct GNUNET_CORE_Handle *ch,
906 struct GNUNET_TRANSPORT_Handle *th,
907 const struct GNUNET_PeerIdentity *my_identity)
909 struct OverlayConnectContext *occ = cls;
910 const struct GNUNET_MessageHeader *hello;
912 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
913 GNUNET_free_non_null (occ->emsg);
914 if ((NULL == ch) || (NULL == my_identity))
916 (void) GNUNET_asprintf (&occ->emsg,
917 "0x%llx: Failed to connect to CORE of peer with "
918 "id: %u", occ->op_id, occ->peer->id);
919 GNUNET_SCHEDULER_cancel (occ->timeout_task);
921 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
927 GNUNET_CORE_is_peer_connected_sync (ch, &occ->other_peer_identity))
929 LOG_DEBUG ("0x%llx: Target peer already connected\n", occ->op_id);
930 GNUNET_SCHEDULER_cancel (occ->timeout_task);
931 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
932 send_overlay_connect_success_msg (occ);
933 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
936 memcpy (&occ->peer_identity, my_identity,
937 sizeof (struct GNUNET_PeerIdentity));
938 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", occ->op_id,
939 GNUNET_i2s (&occ->peer_identity));
940 /* Lookup for HELLO in hello cache */
941 if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
943 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", occ->op_id,
944 GNUNET_i2s (&occ->peer_identity));
945 occ->hello = GNUNET_copy_message (hello);
946 p2_transport_connect (occ);
949 GNUNET_asprintf (&occ->emsg,
950 "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
951 occ->op_id, GNUNET_i2s (&occ->peer_identity));
953 GST_cache_get_handle_transport (occ->peer->id,
954 occ->peer->details.local.cfg,
955 p1_transport_connect_cache_callback, occ,
961 * Callback to be called when forwarded get peer config operation as part of
962 * overlay connect is successfull. Connection to Peer 1's core is made and is
963 * checked for new connection from peer 2
965 * @param cls ForwardedOperationContext
966 * @param msg the peer create success message
969 overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg)
971 struct OverlayConnectContext *occ = cls;
972 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
975 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
976 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION != ntohs (msg->type))
978 GNUNET_SCHEDULER_cancel (occ->timeout_task);
980 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
983 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
984 memcpy (&occ->other_peer_identity, &cmsg->peer_identity,
985 sizeof (struct GNUNET_PeerIdentity));
986 GNUNET_free_non_null (occ->emsg);
987 GNUNET_asprintf (&occ->emsg,
988 "0x%llx: Timeout while connecting to CORE of peer with "
989 "id: %u", occ->op_id, occ->peer->id);
991 GST_cache_get_handle_core (occ->peer->id, occ->peer->details.local.cfg,
992 occ_cache_get_handle_core_cb, occ,
993 &occ->other_peer_identity,
994 &overlay_connect_notify, occ);
1000 * Callback which will be called after a host registration succeeded or failed
1002 * @param cls the RegisteredHostContext
1003 * @param emsg the error message; NULL if host registration is successful
1006 registeredhost_registration_completion (void *cls, const char *emsg)
1008 struct RegisteredHostContext *rhc = cls;
1009 const struct GNUNET_CONFIGURATION_Handle *cfg;
1010 uint32_t peer2_host_id;
1012 peer2_host_id = GNUNET_TESTBED_host_get_id_ (rhc->reg_host);
1013 GNUNET_assert (RHC_INIT == rhc->state);
1014 GNUNET_assert (NULL == rhc->sub_op);
1015 if ((NULL == rhc->gateway2) ||
1016 ( (peer2_host_id < GST_host_list_size) /* Check if we have the needed config */
1017 && (NULL != GST_host_list[peer2_host_id]) ) )
1019 rhc->state = RHC_LINK;
1022 rhc->gateway2) ? our_config
1023 : GNUNET_TESTBED_host_get_cfg_ (GST_host_list[peer2_host_id]);
1025 GNUNET_TESTBED_controller_link (rhc, rhc->gateway->controller,
1026 rhc->reg_host, rhc->host, cfg,
1030 rhc->state = RHC_GET_CFG;
1032 GNUNET_TESTBED_get_slave_config (rhc, rhc->gateway2->controller,
1038 * Iterator to match a registered host context
1040 * @param cls pointer 2 pointer of RegisteredHostContext
1041 * @param key current key code
1042 * @param value value in the hash map
1043 * @return GNUNET_YES if we should continue to
1048 reghost_match_iterator (void *cls, const struct GNUNET_HashCode *key,
1051 struct RegisteredHostContext **rh = cls;
1052 struct RegisteredHostContext *rh_val = value;
1054 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1065 * Function to generate the hashcode corresponding to a RegisteredHostContext
1067 * @param reg_host the host which is being registered in RegisteredHostContext
1068 * @param host the host of the controller which has to connect to the above rhost
1069 * @return the hashcode
1071 static struct GNUNET_HashCode
1072 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1073 struct GNUNET_TESTBED_Host *host)
1075 struct GNUNET_HashCode hash;
1076 uint32_t host_ids[2];
1078 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1079 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1080 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1085 p2_controller_connect_cb (void *cls, struct GNUNET_TESTBED_Controller *c)
1087 struct OverlayConnectContext *occ = cls;
1088 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1093 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1095 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION);
1096 cmsg.peer_id = htonl (occ->other_peer_id);
1097 cmsg.operation_id = GNUNET_htonll (occ->op_id);
1099 GNUNET_TESTBED_forward_operation_msg_ (occ->p2c,
1100 occ->op_id, &cmsg.header,
1101 &overlay_connect_get_config,
1103 GNUNET_free_non_null (occ->emsg);
1104 GNUNET_asprintf (&occ->emsg,
1105 "0x%llx: Timeout while getting peer identity of peer "
1106 "with id: %u", occ->op_id, occ->other_peer_id);
1111 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1114 * @param client identification of the client
1115 * @param message the actual message
1118 GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
1119 const struct GNUNET_MessageHeader *message)
1121 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1123 struct OverlayConnectContext *occ;
1124 struct GNUNET_TESTBED_Controller *p2c;
1125 uint64_t operation_id;
1128 uint32_t peer2_host_id;
1130 if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) !=
1131 ntohs (message->size))
1134 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1137 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1138 p1 = ntohl (msg->peer1);
1139 p2 = ntohl (msg->peer2);
1140 if ((p1 >= GST_peer_list_size) || (NULL == GST_peer_list[p1]))
1143 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1146 peer = GST_peer_list[p1];
1147 peer2_host_id = ntohl (msg->peer2_host_id);
1148 operation_id = GNUNET_ntohll (msg->operation_id);
1150 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n", p1,
1152 if (GNUNET_YES == peer->is_remote)
1154 struct ForwardedOperationContext *fopc;
1155 struct Route *route_to_peer2_host;
1156 struct Route *route_to_peer1_host;
1158 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", operation_id);
1159 route_to_peer2_host = NULL;
1160 route_to_peer1_host = NULL;
1161 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1162 if ((NULL != route_to_peer2_host) ||
1163 (peer2_host_id == GST_context->host_id))
1165 /* Peer 2 either below us OR with us */
1166 route_to_peer1_host =
1167 GST_find_dest_route (GST_peer_list[p1]->details.
1168 remote.remote_host_id);
1169 /* Because we get this message only if we know where peer 1 is */
1170 GNUNET_assert (NULL != route_to_peer1_host);
1171 if ((peer2_host_id == GST_context->host_id) ||
1172 (route_to_peer2_host->dest != route_to_peer1_host->dest))
1174 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1175 * different gateways */
1176 struct GNUNET_HashCode hash;
1177 struct RegisteredHostContext *rhc;
1180 rhc = GNUNET_malloc (sizeof (struct RegisteredHostContext));
1181 rhc->type = CLOSURE_TYPE_RHC;
1182 if (NULL != route_to_peer2_host)
1183 rhc->reg_host = GST_host_list[route_to_peer2_host->dest];
1185 rhc->reg_host = GST_host_list[GST_context->host_id];
1186 rhc->host = GST_host_list[route_to_peer1_host->dest];
1187 GNUNET_assert (NULL != rhc->reg_host);
1188 GNUNET_assert (NULL != rhc->host);
1189 rhc->gateway = peer->details.remote.slave;
1192 route_to_peer2_host) ? NULL :
1193 GST_slave_list[route_to_peer2_host->dest];
1194 rhc->state = RHC_INIT;
1195 GNUNET_SERVER_client_keep (client);
1196 rhc->client = client;
1197 hash = hash_hosts (rhc->reg_host, rhc->host);
1198 skip_focc = GNUNET_NO;
1200 GNUNET_CONTAINER_multihashmap_contains (peer->details.
1201 remote.slave->reghost_map,
1204 GNUNET_CONTAINER_multihashmap_get_multiple (peer->details.remote.
1207 reghost_match_iterator,
1210 /* create and add a new registerd host context */
1211 /* add the focc to its queue */
1212 GNUNET_CONTAINER_multihashmap_put (peer->details.remote.
1213 slave->reghost_map, &hash, rhc,
1214 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1215 GNUNET_assert (NULL != GST_host_list[peer2_host_id]);
1216 GST_queue_host_registration (peer->details.remote.slave,
1217 registeredhost_registration_completion,
1218 rhc, GST_host_list[peer2_host_id]);
1222 /* rhc is now set to the existing one from the hash map by
1223 * reghost_match_iterator() */
1224 /* if queue is empty then ignore creating focc and proceed with
1225 * normal forwarding */
1226 if (RHC_OL_CONNECT == rhc->state)
1227 skip_focc = GNUNET_YES;
1229 if (GNUNET_NO == skip_focc)
1231 struct ForwardedOverlayConnectContext *focc;
1233 focc = GNUNET_malloc (sizeof (struct ForwardedOverlayConnectContext));
1236 focc->peer2_host_id = peer2_host_id;
1237 focc->orig_msg = GNUNET_copy_message (message);
1238 focc->operation_id = operation_id;
1239 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
1240 rhc->focc_dll_tail, focc);
1241 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1246 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1247 GNUNET_SERVER_client_keep (client);
1248 fopc->client = client;
1249 fopc->operation_id = operation_id;
1250 fopc->type = OP_OVERLAY_CONNECT;
1252 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1253 slave->controller, operation_id,
1255 &GST_forwarded_operation_reply_relay,
1257 fopc->timeout_task =
1258 GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout,
1260 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
1261 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1265 struct Neighbour *p2n;
1268 if ((p2 >= GST_peer_list_size) || (NULL == GST_peer_list[p2]))
1270 if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
1273 LOG (GNUNET_ERROR_TYPE_WARNING,
1274 "0x%llx: Peer %u's host not in our neighbours list\n",
1276 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1282 if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1283 p2c = GST_peer_list[p2]->details.remote.slave->controller;
1285 occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
1286 GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ);
1287 GNUNET_SERVER_client_keep (client);
1288 occ->client = client;
1289 occ->other_peer_id = p2;
1290 GST_peer_list[p1]->reference_cnt++;
1291 occ->peer = GST_peer_list[p1];
1292 occ->op_id = operation_id;
1294 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->timeout_task);
1296 GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_overlay_connect, occ);
1297 /* Get the identity of the second peer */
1300 GNUNET_asprintf (&occ->emsg,
1301 "0x%llx: Timeout while acquiring connection to peer %u's "
1302 "host: %u\n", occ->op_id, occ->other_peer_id, peer2_host_id);
1303 occ->p2_ncn = GST_neighbour_get_connection (p2n, &p2_controller_connect_cb,
1305 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1310 p2_controller_connect_cb (occ, p2c);
1311 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1314 GST_peer_list[occ->other_peer_id]->reference_cnt++;
1315 GNUNET_TESTING_peer_get_identity (GST_peer_list[occ->other_peer_id]->
1317 &occ->other_peer_identity);
1318 GNUNET_asprintf (&occ->emsg,
1319 "0x%llx: Timeout while connecting to CORE of peer with "
1320 "id: %u", occ->op_id, occ->peer->id);
1322 GST_cache_get_handle_core (occ->peer->id, occ->peer->details.local.cfg,
1323 occ_cache_get_handle_core_cb, occ,
1324 &occ->other_peer_identity,
1325 &overlay_connect_notify, occ);
1326 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1331 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1334 * @param rocc the RemoteOverlayConnectCtx
1337 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1339 LOG_DEBUG ("0x%llx: Cleaning up rocc\n", rocc->op_id);
1340 if (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id)
1341 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1342 if (GNUNET_SCHEDULER_NO_TASK != rocc->timeout_rocc_task_id)
1343 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1344 if (NULL != rocc->ohh)
1345 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1346 if (NULL != rocc->tcc.tch)
1347 GNUNET_TRANSPORT_try_connect_cancel (rocc->tcc.tch);
1348 if (GNUNET_SCHEDULER_NO_TASK != rocc->tcc.task)
1349 GNUNET_SCHEDULER_cancel (rocc->tcc.task);
1350 //GNUNET_TRANSPORT_disconnect (rocc->tcc.th_);
1351 GST_cache_get_handle_done (rocc->tcc.cgh_th);
1352 GNUNET_assert (rocc->peer->reference_cnt > 0);
1353 rocc->peer->reference_cnt--;
1354 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1355 (0 == rocc->peer->reference_cnt))
1356 GST_destroy_peer (rocc->peer);
1357 GNUNET_free_non_null (rocc->hello);
1358 GNUNET_CONTAINER_DLL_remove (roccq_head, roccq_tail, rocc);
1364 * Task to timeout rocc and cleanit up
1366 * @param cls the RemoteOverlayConnectCtx
1367 * @param tc the TaskContext from scheduler
1370 timeout_rocc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1372 struct RemoteOverlayConnectCtx *rocc = cls;
1374 GNUNET_assert (rocc->timeout_rocc_task_id != GNUNET_SCHEDULER_NO_TASK);
1375 rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_NO_TASK;
1376 LOG_DEBUG ("0x%llx: rocc timed out\n", rocc->op_id);
1377 cleanup_rocc (rocc);
1382 * Function called to notify transport users that another
1383 * peer connected to us.
1385 * @param cls the RemoteOverlayConnectContext
1386 * @param new_peer the peer that connected
1389 cache_transport_peer_connect_notify (void *cls,
1390 const struct GNUNET_PeerIdentity *new_peer)
1392 struct RemoteOverlayConnectCtx *rocc = cls;
1394 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n", rocc->op_id);
1396 memcmp (new_peer, &rocc->a_id,
1397 sizeof (struct GNUNET_PeerIdentity)));
1398 LOG_DEBUG ("0x%llx: Peer %4s connected\n", rocc->op_id,
1399 GNUNET_i2s (&rocc->a_id));
1400 cleanup_rocc (rocc);
1405 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1406 * whose identity is in RemoteOverlayConnectCtx
1408 * @param cls the RemoteOverlayConnectCtx
1409 * @param tc the TaskContext from scheduler
1412 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1416 * Task that is run when hello has been sent
1418 * @param cls the overlay connect context
1419 * @param tc the scheduler task context; if tc->reason =
1420 * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1421 * GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1424 rocc_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1426 struct RemoteOverlayConnectCtx *rocc = cls;
1429 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rocc->attempt_connect_task_id);
1430 LOG_DEBUG ("0x%llx: HELLO of peer %4s sent to local peer with id: %u\n",
1431 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1432 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
1435 rocc->attempt_connect_task_id =
1436 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1439 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
1444 rocc->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &rocc->tcc);
1449 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1450 * whose identity is in RemoteOverlayConnectCtx
1452 * @param cls the RemoteOverlayConnectCtx
1453 * @param tc the TaskContext from scheduler
1456 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1458 struct RemoteOverlayConnectCtx *rocc = cls;
1460 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id);
1461 rocc->attempt_connect_task_id = GNUNET_SCHEDULER_NO_TASK;
1462 LOG_DEBUG ("0x%llx: Offering HELLO of peer %4s to local peer with id: %u\n",
1463 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1465 GNUNET_TRANSPORT_offer_hello (rocc->tcc.th_, rocc->hello,
1466 rocc_hello_sent_cb, rocc);
1467 if (NULL == rocc->ohh)
1468 rocc->attempt_connect_task_id =
1469 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1470 (GNUNET_TIME_UNIT_MILLISECONDS,
1472 GNUNET_CRYPTO_random_u32
1473 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1474 &attempt_connect_task, rocc);
1479 * Callback from cache with needed handles set
1481 * @param cls the closure passed to GST_cache_get_handle_transport()
1482 * @param ch the handle to CORE. Can be NULL if it is not requested
1483 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1484 * @param ignore_ peer identity which is ignored in this callback
1487 rocc_cache_get_handle_transport_cb (void *cls, struct GNUNET_CORE_Handle *ch,
1488 struct GNUNET_TRANSPORT_Handle *th,
1489 const struct GNUNET_PeerIdentity *ignore_)
1491 struct RemoteOverlayConnectCtx *rocc = cls;
1495 rocc->timeout_rocc_task_id =
1496 GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1500 rocc->tcc.pid = &rocc->a_id;
1502 GNUNET_TRANSPORT_check_neighbour_connected (rocc->tcc.th_, rocc->tcc.pid))
1504 LOG_DEBUG ("0x%llx: Target peer %4s already connected to local peer: %u\n",
1505 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1506 cleanup_rocc (rocc);
1509 rocc->attempt_connect_task_id =
1510 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1515 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages
1518 * @param client identification of the client
1519 * @param message the actual message
1522 GST_handle_remote_overlay_connect (void *cls,
1523 struct GNUNET_SERVER_Client *client,
1524 const struct GNUNET_MessageHeader *message)
1526 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
1527 struct RemoteOverlayConnectCtx *rocc;
1533 msize = ntohs (message->size);
1534 if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize)
1537 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1540 msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message;
1541 if ((NULL == msg->hello) ||
1542 ((GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))))
1545 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1548 hsize = ntohs (msg->hello->size);
1549 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1553 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1556 peer_id = ntohl (msg->peer);
1557 if ((peer_id >= GST_peer_list_size) ||
1558 (NULL == (peer = GST_peer_list[peer_id])))
1560 GNUNET_break_op (0);
1561 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1564 if (GNUNET_YES == peer->is_remote)
1566 struct GNUNET_MessageHeader *msg2;
1568 msg2 = GNUNET_copy_message (message);
1569 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1571 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1574 rocc = GNUNET_malloc (sizeof (struct RemoteOverlayConnectCtx));
1575 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1576 GNUNET_CONTAINER_DLL_insert_tail (roccq_head, roccq_tail, rocc);
1577 memcpy (&rocc->a_id, &msg->peer_identity,
1578 sizeof (struct GNUNET_PeerIdentity));
1579 LOG_DEBUG ("Received request for overlay connection with op_id: 0x%llx "
1580 "from local peer %u to peer %4s with hello size: %u\n",
1581 rocc->op_id, peer_id, GNUNET_i2s (&rocc->a_id), hsize);
1583 rocc->peer->reference_cnt++;
1584 rocc->hello = GNUNET_malloc (hsize);
1585 memcpy (rocc->hello, msg->hello, hsize);
1587 GST_cache_get_handle_transport (peer_id, rocc->peer->details.local.cfg,
1588 &rocc_cache_get_handle_transport_cb, rocc,
1590 &cache_transport_peer_connect_notify,
1592 rocc->timeout_rocc_task_id =
1593 GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_rocc_task, rocc);
1594 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1599 * Clears all pending overlay connect contexts in queue
1604 struct OverlayConnectContext *occ;
1606 while (NULL != (occ = occq_head))
1612 * Clears all pending remote overlay connect contexts in queue
1617 struct RemoteOverlayConnectCtx *rocc;
1619 while (NULL != (rocc = roccq_head))
1620 cleanup_rocc (rocc);