2 This file is part of GNUnet.
3 (C) 2012 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
155 struct GNUNET_TESTBED_Controller *peer2_controller;
158 * The transport TryConnectContext. This will be NULL if the second peer is a
161 struct TryConnectContext tcc;
164 * The peer identity of the first peer
166 struct GNUNET_PeerIdentity peer_identity;
169 * The peer identity of the other peer
171 struct GNUNET_PeerIdentity other_peer_identity;
174 * The id of the operation responsible for creating this context
179 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
182 GNUNET_SCHEDULER_TaskIdentifier send_hello_task;
185 * The id of the overlay connect timeout task
187 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
190 * The id of the cleanup task
192 GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
195 * The id of the second peer which is has to connect to the first peer
197 uint32_t other_peer_id;
203 * Context information for remote overlay connect operations. Remote overlay
204 * connections are used when peers A and B reside on different hosts. In these
205 * operations the host controller for peer B is asked by the host controller of
206 * peer A to make peer B connect to peer A by sending the controller of peer B
207 * the HELLO of peer A.
209 struct RemoteOverlayConnectCtx
212 * the next pointer for DLL
214 struct RemoteOverlayConnectCtx *next;
217 * the prev pointer for DLL
219 struct RemoteOverlayConnectCtx *prev;
222 * The peer handle of peer B
229 struct GNUNET_MessageHeader *hello;
232 * The handle for offering HELLO
234 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
237 * The transport try connect context
239 struct TryConnectContext tcc;
242 * The peer identity of peer A
244 struct GNUNET_PeerIdentity a_id;
247 * Task for offering HELLO of A to B and doing try_connect
249 GNUNET_SCHEDULER_TaskIdentifier attempt_connect_task_id;
252 * Task to timeout RequestOverlayConnect
254 GNUNET_SCHEDULER_TaskIdentifier timeout_rocc_task_id;
257 * The id of the operation responsible for creating this context
264 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
266 static struct OverlayConnectContext *occq_head;
269 * DLL tail for OverlayConnectContext DLL
271 static struct OverlayConnectContext *occq_tail;
274 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
277 static struct RemoteOverlayConnectCtx *roccq_head;
280 * DLL tail for RequectOverlayConnectContext DLL
282 static struct RemoteOverlayConnectCtx *roccq_tail;
286 * Cleans up ForwardedOverlayConnectContext
288 * @param focc the ForwardedOverlayConnectContext to cleanup
291 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
293 GNUNET_free_non_null (focc->orig_msg);
299 * Timeout task for cancelling a forwarded overlay connect connect
301 * @param cls the ForwardedOverlayConnectContext
302 * @param tc the task context from the scheduler
305 forwarded_overlay_connect_timeout (void *cls,
306 const struct GNUNET_SCHEDULER_TaskContext
309 struct ForwardedOperationContext *fopc = cls;
310 struct RegisteredHostContext *rhc;
311 struct ForwardedOverlayConnectContext *focc;
314 focc = rhc->focc_dll_head;
315 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
316 GST_cleanup_focc (focc);
317 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1,
319 GST_forwarded_operation_timeout (cls, tc);
320 if (NULL != rhc->focc_dll_head)
321 GST_process_next_focc (rhc);
326 * Callback to be called when forwarded overlay connection operation has a reply
327 * from the sub-controller successfull. We have to relay the reply msg back to
330 * @param cls ForwardedOperationContext
331 * @param msg the peer create success message
334 forwarded_overlay_connect_listener (void *cls,
335 const struct GNUNET_MessageHeader *msg)
337 struct ForwardedOperationContext *fopc = cls;
338 struct RegisteredHostContext *rhc;
339 struct ForwardedOverlayConnectContext *focc;
342 GST_forwarded_operation_reply_relay (cls, msg);
343 focc = rhc->focc_dll_head;
344 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
345 GST_cleanup_focc (focc);
346 if (NULL != rhc->focc_dll_head)
347 GST_process_next_focc (rhc);
352 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
354 * @param rhc the RegisteredHostContext
357 GST_process_next_focc (struct RegisteredHostContext *rhc)
359 struct ForwardedOperationContext *fopc;
360 struct ForwardedOverlayConnectContext *focc;
362 focc = rhc->focc_dll_head;
363 GNUNET_assert (NULL != focc);
364 GNUNET_assert (RHC_OL_CONNECT == rhc->state);
365 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
366 GNUNET_SERVER_client_keep (rhc->client);
367 fopc->client = rhc->client;
368 fopc->operation_id = focc->operation_id;
370 fopc->type = OP_OVERLAY_CONNECT;
372 GNUNET_TESTBED_forward_operation_msg_ (rhc->gateway->controller,
373 focc->operation_id, focc->orig_msg,
374 &forwarded_overlay_connect_listener,
376 GNUNET_free (focc->orig_msg);
377 focc->orig_msg = NULL;
379 GNUNET_SCHEDULER_add_delayed (GST_timeout, &forwarded_overlay_connect_timeout,
381 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
386 * Cleanup overlay connect context structure
388 * @param occ the overlay connect context
391 cleanup_occ (struct OverlayConnectContext *occ)
393 struct Peer *other_peer;
395 LOG_DEBUG ("0x%llx: Cleaning up occ\n", occ->op_id);
396 GNUNET_free_non_null (occ->emsg);
397 GNUNET_free_non_null (occ->hello);
398 GNUNET_SERVER_client_drop (occ->client);
399 if (NULL != occ->opc)
400 GNUNET_TESTBED_forward_operation_msg_cancel_ (occ->opc);
401 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
402 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
403 if (GNUNET_SCHEDULER_NO_TASK != occ->cleanup_task)
404 GNUNET_SCHEDULER_cancel (occ->cleanup_task);
405 if (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task)
406 GNUNET_SCHEDULER_cancel (occ->timeout_task);
407 if (NULL != occ->cgh_ch)
408 GST_cache_get_handle_done (occ->cgh_ch);
409 if (NULL != occ->ghh)
410 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
411 if (NULL != occ->ohh)
412 GNUNET_TRANSPORT_offer_hello_cancel (occ->ohh);
413 if (GNUNET_SCHEDULER_NO_TASK != occ->tcc.task)
414 GNUNET_SCHEDULER_cancel (occ->tcc.task);
415 if (NULL != occ->tcc.tch)
416 GNUNET_TRANSPORT_try_connect_cancel (occ->tcc.tch);
417 if (NULL != occ->cgh_p1th)
418 GST_cache_get_handle_done (occ->cgh_p1th);
419 if (NULL != occ->tcc.cgh_th)
420 GST_cache_get_handle_done (occ->tcc.cgh_th);
421 GNUNET_assert (NULL != GST_peer_list);
422 GNUNET_assert (occ->peer->reference_cnt > 0);
423 occ->peer->reference_cnt--;
424 if ( (GNUNET_YES == occ->peer->destroy_flag) &&
425 (0 == occ->peer->reference_cnt) )
426 GST_destroy_peer (occ->peer);
427 if (NULL == occ->peer2_controller)
429 other_peer = GST_peer_list[occ->other_peer_id];
430 GNUNET_assert (NULL != other_peer);
431 GNUNET_assert (other_peer->reference_cnt > 0);
432 other_peer->reference_cnt--;
433 if ( (GNUNET_YES == other_peer->destroy_flag) &&
434 (0 == other_peer->reference_cnt) )
435 GST_destroy_peer (other_peer);
437 GNUNET_CONTAINER_DLL_remove (occq_head, occq_tail, occ);
443 * Task for cleaing up overlay connect context structure
445 * @param cls the overlay connect context
446 * @param tc the task context
449 do_cleanup_occ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
451 struct OverlayConnectContext *occ = cls;
453 occ->cleanup_task = GNUNET_SCHEDULER_NO_TASK;
459 * Task which will be run when overlay connect request has been timed out
461 * @param cls the OverlayConnectContext
462 * @param tc the TaskContext
465 timeout_overlay_connect (void *cls,
466 const struct GNUNET_SCHEDULER_TaskContext *tc)
468 struct OverlayConnectContext *occ = cls;
470 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
471 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
472 /* LOG (GNUNET_ERROR_TYPE_WARNING, */
473 /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
474 /* occ->peer->id, occ->other_peer_id, occ->emsg); */
475 GST_send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
481 send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
483 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
485 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
487 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
489 htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
490 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
491 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
492 msg->peer1 = htonl (occ->peer->id);
493 msg->peer2 = htonl (occ->other_peer_id);
494 msg->operation_id = GNUNET_htonll (occ->op_id);
495 GST_queue_message (occ->client, &msg->header);
500 * Function called to notify transport users that another
501 * peer connected to us.
504 * @param new_peer the peer that connected
507 overlay_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer)
509 struct OverlayConnectContext *occ = cls;
511 char *other_peer_str;
513 //LOG_DEBUG ("Overlay connect notify\n");
515 memcmp (new_peer, &occ->peer_identity,
516 sizeof (struct GNUNET_PeerIdentity)))
518 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
519 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
521 memcmp (new_peer, &occ->other_peer_identity,
522 sizeof (struct GNUNET_PeerIdentity)))
524 /* LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n", */
525 /* new_peer_str, other_peer_str); */
526 GNUNET_free (new_peer_str);
527 GNUNET_free (other_peer_str);
530 GNUNET_free (new_peer_str);
531 LOG_DEBUG ("0x%llx: Peer %4s connected to peer %4s\n", occ->op_id,
532 other_peer_str, GNUNET_i2s (&occ->peer_identity));
533 GNUNET_free (other_peer_str);
534 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
536 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
537 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
539 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
540 GNUNET_SCHEDULER_cancel (occ->timeout_task);
541 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
542 if (GNUNET_SCHEDULER_NO_TASK != occ->tcc.task)
544 GNUNET_SCHEDULER_cancel (occ->tcc.task);
545 occ->tcc.task = GNUNET_SCHEDULER_NO_TASK;
547 GNUNET_free_non_null (occ->emsg);
549 send_overlay_connect_success_msg (occ);
550 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
556 * Task to ask transport of a peer to connect to another peer
558 * @param cls the TryConnectContext
559 * @param tc the scheduler task context
562 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
566 * Callback to be called with result of the try connect request.
568 * @param cls the overlay connect context
569 * @param result GNUNET_OK if message was transmitted to transport service
570 * GNUNET_SYSERR if message was not transmitted to transport service
573 try_connect_cb (void *cls, const int result)
575 struct TryConnectContext *tcc = cls;
578 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == tcc->task);
580 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
581 (GNUNET_TIME_UNIT_MILLISECONDS,
582 500 + pow (2, ++tcc->retries)),
583 &try_connect_task, tcc);
588 * Task to ask transport of a peer to connect to another peer
590 * @param cls the TryConnectContext
591 * @param tc the scheduler task context
594 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
596 struct TryConnectContext *tcc = cls;
598 tcc->task = GNUNET_SCHEDULER_NO_TASK;
599 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
601 GNUNET_assert (NULL == tcc->tch);
602 GNUNET_assert (NULL != tcc->pid);
603 GNUNET_assert (NULL != tcc->th_);
604 GNUNET_assert (NULL != tcc->cgh_th);
605 LOG_DEBUG ("0x%llx: Trail %u to connect to peer %s\n", tcc->op_id,
606 tcc->retries, GNUNET_i2s (tcc->pid));
608 GNUNET_TRANSPORT_try_connect (tcc->th_, tcc->pid, &try_connect_cb, tcc);
613 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
616 * @param cls the OverlayConnectContext
617 * @param tc the TaskContext from scheduler
620 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
624 * Task that is run when hello has been sent
626 * @param cls the overlay connect context
627 * @param tc the scheduler task context; if tc->reason =
628 * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
629 * GNUNET_SCHEDULER_REASON_READ_READY is succeeded
632 occ_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
634 struct OverlayConnectContext *occ = cls;
637 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->send_hello_task);
638 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
640 GNUNET_free_non_null (occ->emsg);
641 GNUNET_asprintf (&occ->emsg,
642 "0x%llx: Timeout while offering HELLO to other peer",
644 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
647 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
649 GNUNET_free_non_null (occ->emsg);
650 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while try connect", occ->op_id);
651 occ->tcc.pid = &occ->peer_identity;
652 occ->tcc.op_id = occ->op_id;
653 occ->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &occ->tcc);
658 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
661 * @param cls the OverlayConnectContext
662 * @param tc the TaskContext from scheduler
665 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
667 struct OverlayConnectContext *occ = cls;
668 char *other_peer_str;
670 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
671 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
673 GNUNET_assert (NULL != occ->hello);
674 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
675 if (NULL != occ->peer2_controller)
677 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
681 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote "
682 "Overlay Request\n", occ->op_id,
683 GNUNET_i2s (&occ->peer_identity), ntohs (occ->hello->size),
685 hello_size = ntohs (occ->hello->size);
687 sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
688 msg = GNUNET_malloc (msize);
690 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
691 msg->header.size = htons (msize);
692 msg->peer = htonl (occ->other_peer_id);
693 msg->operation_id = GNUNET_htonll (occ->op_id);
694 (void) memcpy (&msg->peer_identity, &occ->peer_identity,
695 sizeof (struct GNUNET_PeerIdentity));
696 memcpy (msg->hello, occ->hello, hello_size);
697 GNUNET_TESTBED_queue_message_ (occ->peer2_controller, &msg->header);
701 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n", occ->op_id,
702 GNUNET_i2s (&occ->peer_identity), other_peer_str);
704 GNUNET_TRANSPORT_offer_hello (occ->tcc.th_, occ->hello,
705 occ_hello_sent_cb, occ);
706 if (NULL == occ->ohh)
709 occ->send_hello_task =
710 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
711 (GNUNET_TIME_UNIT_MILLISECONDS,
713 GNUNET_CRYPTO_random_u32
714 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
718 GNUNET_free (other_peer_str);
723 * Callback from cache with needed handles set
725 * @param cls the closure passed to GST_cache_get_handle_transport()
726 * @param ch the handle to CORE. Can be NULL if it is not requested
727 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
728 * @param ignore_ peer identity which is ignored in this callback
731 p2_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch,
732 struct GNUNET_TRANSPORT_Handle *th,
733 const struct GNUNET_PeerIdentity *ignore_)
735 struct OverlayConnectContext *occ = cls;
739 GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s",
740 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
741 GNUNET_SCHEDULER_cancel (occ->timeout_task);
743 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
747 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
748 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
749 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
754 * Connects to the transport of the other peer if it is a local peer and
755 * schedules the send hello task
757 * @param occ the overlay connect context
760 p2_transport_connect (struct OverlayConnectContext *occ)
762 GNUNET_assert (NULL == occ->emsg);
763 GNUNET_assert (NULL != occ->hello);
764 GNUNET_assert (NULL == occ->ghh);
765 GNUNET_assert (NULL == occ->p1th_);
766 GNUNET_assert (NULL == occ->cgh_p1th);
767 if (NULL == occ->peer2_controller)
769 GNUNET_assert (NULL != GST_peer_list[occ->other_peer_id]);
771 GST_cache_get_handle_transport (occ->other_peer_id,
772 GST_peer_list[occ->other_peer_id]
774 &p2_transport_connect_cache_callback,
775 occ, NULL, NULL, NULL);
778 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
779 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
780 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
785 * Test for checking whether HELLO message is empty
787 * @param cls empty flag to set
788 * @param address the HELLO
789 * @param expiration expiration of the HELLO
793 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
794 struct GNUNET_TIME_Absolute expiration)
804 * Function called whenever there is an update to the HELLO of peers in the
805 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
806 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
809 * @param hello our updated HELLO
812 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
814 struct OverlayConnectContext *occ = cls;
818 msize = ntohs (hello->size);
820 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
821 hello, GNUNET_NO, &test_address,
823 if (GNUNET_YES == empty)
825 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n", occ->op_id,
826 GNUNET_i2s (&occ->peer_identity));
829 LOG_DEBUG ("0x%llx: Received HELLO of %s\n", occ->op_id,
830 GNUNET_i2s (&occ->peer_identity));
831 occ->hello = GNUNET_malloc (msize);
832 GST_cache_add_hello (occ->peer->id, hello);
833 memcpy (occ->hello, hello, msize);
834 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
836 GST_cache_get_handle_done (occ->cgh_p1th);
837 occ->cgh_p1th = NULL;
839 GNUNET_free_non_null (occ->emsg);
841 p2_transport_connect (occ);
846 * Callback from cache with needed handles set
848 * @param cls the closure passed to GST_cache_get_handle_transport()
849 * @param ch the handle to CORE. Can be NULL if it is not requested
850 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
851 * @param ignore_ peer identity which is ignored in this callback
854 p1_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch,
855 struct GNUNET_TRANSPORT_Handle *th,
856 const struct GNUNET_PeerIdentity *ignore_)
858 struct OverlayConnectContext *occ = cls;
860 GNUNET_free_non_null (occ->emsg);
864 GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s",
865 occ->op_id, GNUNET_i2s (&occ->peer_identity));
866 GNUNET_SCHEDULER_cancel (occ->timeout_task);
868 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
871 GNUNET_assert (NULL == occ->p1th_);
872 GNUNET_assert (NULL != occ->cgh_p1th);
874 GNUNET_asprintf (&occ->emsg,
875 "0x%llx: Timeout while acquiring HELLO of peer %4s",
876 occ->op_id, GNUNET_i2s (&occ->peer_identity));
877 occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th_, &hello_update_cb, occ);
882 * Callback from cache with needed handles set
884 * @param cls the closure passed to GST_cache_get_handle_transport()
885 * @param ch the handle to CORE. Can be NULL if it is not requested
886 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
887 * @param my_identity the identity of our peer
890 occ_cache_get_handle_core_cb (void *cls, struct GNUNET_CORE_Handle *ch,
891 struct GNUNET_TRANSPORT_Handle *th,
892 const struct GNUNET_PeerIdentity *my_identity)
894 struct OverlayConnectContext *occ = cls;
895 const struct GNUNET_MessageHeader *hello;
897 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
898 GNUNET_free_non_null (occ->emsg);
899 if ((NULL == ch) || (NULL == my_identity))
901 (void) GNUNET_asprintf (&occ->emsg,
902 "0x%llx: Failed to connect to CORE of peer with "
903 "id: %u", occ->op_id, occ->peer->id);
904 GNUNET_SCHEDULER_cancel (occ->timeout_task);
906 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
912 GNUNET_CORE_is_peer_connected_sync (ch, &occ->other_peer_identity))
914 LOG_DEBUG ("0x%llx: Target peer already connected\n", occ->op_id);
915 GNUNET_SCHEDULER_cancel (occ->timeout_task);
916 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
917 send_overlay_connect_success_msg (occ);
918 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
921 memcpy (&occ->peer_identity, my_identity,
922 sizeof (struct GNUNET_PeerIdentity));
923 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", occ->op_id,
924 GNUNET_i2s (&occ->peer_identity));
925 /* Lookup for HELLO in hello cache */
926 if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
928 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", occ->op_id,
929 GNUNET_i2s (&occ->peer_identity));
930 occ->hello = GNUNET_copy_message (hello);
931 p2_transport_connect (occ);
934 GNUNET_asprintf (&occ->emsg,
935 "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
936 occ->op_id, GNUNET_i2s (&occ->peer_identity));
938 GST_cache_get_handle_transport (occ->peer->id,
939 occ->peer->details.local.cfg,
940 p1_transport_connect_cache_callback, occ,
947 * Callback to be called when forwarded get peer config operation as part of
948 * overlay connect is successfull. Connection to Peer 1's core is made and is
949 * checked for new connection from peer 2
951 * @param cls ForwardedOperationContext
952 * @param msg the peer create success message
955 overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg)
957 struct OverlayConnectContext *occ = cls;
958 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
961 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
962 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION != ntohs (msg->type))
964 GNUNET_SCHEDULER_cancel (occ->timeout_task);
966 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
969 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
970 memcpy (&occ->other_peer_identity, &cmsg->peer_identity,
971 sizeof (struct GNUNET_PeerIdentity));
972 GNUNET_free_non_null (occ->emsg);
973 GNUNET_asprintf (&occ->emsg,
974 "0x%llx: Timeout while connecting to CORE of peer with "
975 "id: %u", occ->op_id, occ->peer->id);
977 GST_cache_get_handle_core (occ->peer->id, occ->peer->details.local.cfg,
978 occ_cache_get_handle_core_cb, occ,
979 &occ->other_peer_identity,
980 &overlay_connect_notify, occ);
986 * Callback which will be called after a host registration succeeded or failed
988 * @param cls the RegisteredHostContext
989 * @param emsg the error message; NULL if host registration is successful
992 registeredhost_registration_completion (void *cls, const char *emsg)
994 struct RegisteredHostContext *rhc = cls;
995 const struct GNUNET_CONFIGURATION_Handle *cfg;
996 uint32_t peer2_host_id;
998 /* if (NULL != rhc->focc_dll_head) */
999 /* TESTBED_process_next_focc (rhc); */
1000 peer2_host_id = GNUNET_TESTBED_host_get_id_ (rhc->reg_host);
1001 GNUNET_assert (RHC_INIT == rhc->state);
1002 GNUNET_assert (NULL == rhc->sub_op);
1003 if ((NULL == rhc->gateway2) || ((peer2_host_id < GST_host_list_size) /* Check if we have the needed config */
1004 && (NULL != GST_host_list[peer2_host_id])))
1006 rhc->state = RHC_LINK;
1009 rhc->gateway2) ? our_config
1010 : GNUNET_TESTBED_host_get_cfg_ (GST_host_list[peer2_host_id]);
1012 GNUNET_TESTBED_controller_link (rhc, rhc->gateway->controller,
1013 rhc->reg_host, rhc->host, cfg,
1017 rhc->state = RHC_GET_CFG;
1019 GNUNET_TESTBED_get_slave_config (rhc, rhc->gateway2->controller,
1025 * Iterator to match a registered host context
1027 * @param cls pointer 2 pointer of RegisteredHostContext
1028 * @param key current key code
1029 * @param value value in the hash map
1030 * @return GNUNET_YES if we should continue to
1035 reghost_match_iterator (void *cls, const struct GNUNET_HashCode *key,
1038 struct RegisteredHostContext **rh = cls;
1039 struct RegisteredHostContext *rh_val = value;
1041 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1052 * Function to generate the hashcode corresponding to a RegisteredHostContext
1054 * @param reg_host the host which is being registered in RegisteredHostContext
1055 * @param host the host of the controller which has to connect to the above rhost
1056 * @return the hashcode
1058 static struct GNUNET_HashCode
1059 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1060 struct GNUNET_TESTBED_Host *host)
1062 struct GNUNET_HashCode hash;
1063 uint32_t host_ids[2];
1065 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1066 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1067 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1073 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1076 * @param client identification of the client
1077 * @param message the actual message
1080 GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
1081 const struct GNUNET_MessageHeader *message)
1083 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1085 struct OverlayConnectContext *occ;
1086 struct GNUNET_TESTBED_Controller *peer2_controller;
1087 uint64_t operation_id;
1090 uint32_t peer2_host_id;
1092 if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) !=
1093 ntohs (message->size))
1096 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1099 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1100 p1 = ntohl (msg->peer1);
1101 p2 = ntohl (msg->peer2);
1102 if ((p1 >= GST_peer_list_size) || (NULL == GST_peer_list[p1]))
1105 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1108 peer = GST_peer_list[p1];
1109 peer2_host_id = ntohl (msg->peer2_host_id);
1110 operation_id = GNUNET_ntohll (msg->operation_id);
1112 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n", p1,
1114 if (GNUNET_YES == peer->is_remote)
1116 struct ForwardedOperationContext *fopc;
1117 struct Route *route_to_peer2_host;
1118 struct Route *route_to_peer1_host;
1120 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", operation_id);
1121 route_to_peer2_host = NULL;
1122 route_to_peer1_host = NULL;
1123 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1124 if ((NULL != route_to_peer2_host) ||
1125 (peer2_host_id == GST_context->host_id))
1127 /* Peer 2 either below us OR with us */
1128 route_to_peer1_host =
1129 GST_find_dest_route (GST_peer_list[p1]->details.
1130 remote.remote_host_id);
1131 /* Because we get this message only if we know where peer 1 is */
1132 GNUNET_assert (NULL != route_to_peer1_host);
1133 if ((peer2_host_id == GST_context->host_id) ||
1134 (route_to_peer2_host->dest != route_to_peer1_host->dest))
1136 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1137 * different gateways */
1138 struct GNUNET_HashCode hash;
1139 struct RegisteredHostContext *rhc;
1142 rhc = GNUNET_malloc (sizeof (struct RegisteredHostContext));
1143 rhc->type = CLOSURE_TYPE_RHC;
1144 if (NULL != route_to_peer2_host)
1145 rhc->reg_host = GST_host_list[route_to_peer2_host->dest];
1147 rhc->reg_host = GST_host_list[GST_context->host_id];
1148 rhc->host = GST_host_list[route_to_peer1_host->dest];
1149 GNUNET_assert (NULL != rhc->reg_host);
1150 GNUNET_assert (NULL != rhc->host);
1151 rhc->gateway = peer->details.remote.slave;
1154 route_to_peer2_host) ? NULL :
1155 GST_slave_list[route_to_peer2_host->dest];
1156 rhc->state = RHC_INIT;
1157 GNUNET_SERVER_client_keep (client);
1158 rhc->client = client;
1159 hash = hash_hosts (rhc->reg_host, rhc->host);
1160 skip_focc = GNUNET_NO;
1162 GNUNET_CONTAINER_multihashmap_contains (peer->details.
1163 remote.slave->reghost_map,
1166 GNUNET_CONTAINER_multihashmap_get_multiple (peer->details.remote.
1169 reghost_match_iterator,
1172 /* create and add a new registerd host context */
1173 /* add the focc to its queue */
1174 GNUNET_CONTAINER_multihashmap_put (peer->details.remote.
1175 slave->reghost_map, &hash, rhc,
1176 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1177 GNUNET_assert (NULL != GST_host_list[peer2_host_id]);
1178 GST_queue_host_registration (peer->details.remote.slave,
1179 registeredhost_registration_completion,
1180 rhc, GST_host_list[peer2_host_id]);
1184 /* rhc is now set to the existing one from the hash map by
1185 * reghost_match_iterator() */
1186 /* if queue is empty then ignore creating focc and proceed with
1187 * normal forwarding */
1188 if (RHC_OL_CONNECT == rhc->state)
1189 skip_focc = GNUNET_YES;
1191 if (GNUNET_NO == skip_focc)
1193 struct ForwardedOverlayConnectContext *focc;
1195 focc = GNUNET_malloc (sizeof (struct ForwardedOverlayConnectContext));
1198 focc->peer2_host_id = peer2_host_id;
1199 focc->orig_msg = GNUNET_copy_message (message);
1200 focc->operation_id = operation_id;
1201 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
1202 rhc->focc_dll_tail, focc);
1203 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1208 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1209 GNUNET_SERVER_client_keep (client);
1210 fopc->client = client;
1211 fopc->operation_id = operation_id;
1212 fopc->type = OP_OVERLAY_CONNECT;
1214 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1215 slave->controller, operation_id,
1217 &GST_forwarded_operation_reply_relay,
1219 fopc->timeout_task =
1220 GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout,
1222 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
1223 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1227 peer2_controller = NULL;
1228 if ((p2 >= GST_peer_list_size) || (NULL == GST_peer_list[p2]))
1230 if ((peer2_host_id >= GST_slave_list_size) ||
1231 (NULL == GST_slave_list[peer2_host_id]))
1233 LOG (GNUNET_ERROR_TYPE_WARNING,
1234 "0x%llx: Configuration of peer2's controller missing for connecting peers"
1235 "%u and %u\n", operation_id, p1, p2);
1236 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1239 peer2_controller = GST_slave_list[peer2_host_id]->controller;
1240 if (NULL == peer2_controller)
1242 GNUNET_break (0); /* What's going on? */
1243 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1249 if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1250 peer2_controller = GST_peer_list[p2]->details.remote.slave->controller;
1252 occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
1253 GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ);
1254 GNUNET_SERVER_client_keep (client);
1255 occ->client = client;
1256 occ->other_peer_id = p2;
1257 GST_peer_list[p1]->reference_cnt++;
1258 occ->peer = GST_peer_list[p1];
1259 occ->op_id = GNUNET_ntohll (msg->operation_id);
1260 occ->peer2_controller = peer2_controller;
1261 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->timeout_task);
1263 GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_overlay_connect, occ);
1264 /* Get the identity of the second peer */
1265 if (NULL != occ->peer2_controller)
1267 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1270 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1272 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION);
1273 cmsg.peer_id = msg->peer2;
1274 cmsg.operation_id = msg->operation_id;
1276 GNUNET_TESTBED_forward_operation_msg_ (occ->peer2_controller,
1277 occ->op_id, &cmsg.header,
1278 &overlay_connect_get_config,
1280 GNUNET_asprintf (&occ->emsg,
1281 "0x%llx: Timeout while getting peer identity of peer "
1282 "with id: %u", occ->op_id, occ->other_peer_id);
1283 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1286 GST_peer_list[occ->other_peer_id]->reference_cnt++;
1287 GNUNET_TESTING_peer_get_identity (GST_peer_list[occ->other_peer_id]->
1289 &occ->other_peer_identity);
1290 GNUNET_asprintf (&occ->emsg,
1291 "0x%llx: Timeout while connecting to CORE of peer with "
1292 "id: %u", occ->op_id, occ->peer->id);
1294 GST_cache_get_handle_core (occ->peer->id, occ->peer->details.local.cfg,
1295 occ_cache_get_handle_core_cb, occ,
1296 &occ->other_peer_identity,
1297 &overlay_connect_notify, occ);
1298 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1303 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1306 * @param rocc the RemoteOverlayConnectCtx
1309 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1311 LOG_DEBUG ("0x%llx: Cleaning up rocc\n", rocc->op_id);
1312 if (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id)
1313 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1314 if (GNUNET_SCHEDULER_NO_TASK != rocc->timeout_rocc_task_id)
1315 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1316 if (NULL != rocc->ohh)
1317 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1318 if (NULL != rocc->tcc.tch)
1319 GNUNET_TRANSPORT_try_connect_cancel (rocc->tcc.tch);
1320 if (GNUNET_SCHEDULER_NO_TASK != rocc->tcc.task)
1321 GNUNET_SCHEDULER_cancel (rocc->tcc.task);
1322 //GNUNET_TRANSPORT_disconnect (rocc->tcc.th_);
1323 GST_cache_get_handle_done (rocc->tcc.cgh_th);
1324 GNUNET_assert (rocc->peer->reference_cnt > 0);
1325 rocc->peer->reference_cnt--;
1326 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1327 (0 == rocc->peer->reference_cnt))
1328 GST_destroy_peer (rocc->peer);
1329 GNUNET_free_non_null (rocc->hello);
1330 GNUNET_CONTAINER_DLL_remove (roccq_head, roccq_tail, rocc);
1336 * Task to timeout rocc and cleanit up
1338 * @param cls the RemoteOverlayConnectCtx
1339 * @param tc the TaskContext from scheduler
1342 timeout_rocc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1344 struct RemoteOverlayConnectCtx *rocc = cls;
1346 GNUNET_assert (rocc->timeout_rocc_task_id != GNUNET_SCHEDULER_NO_TASK);
1347 rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_NO_TASK;
1348 LOG_DEBUG ("0x%llx: rocc timed out\n", rocc->op_id);
1349 cleanup_rocc (rocc);
1354 * Function called to notify transport users that another
1355 * peer connected to us.
1357 * @param cls closure
1358 * @param new_peer the peer that connected
1359 * @param ats performance data
1360 * @param ats_count number of entries in ats (excluding 0-termination)
1363 cache_transport_peer_connect_notify (void *cls,
1364 const struct GNUNET_PeerIdentity *new_peer)
1366 struct RemoteOverlayConnectCtx *rocc = cls;
1368 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n", rocc->op_id);
1370 memcmp (new_peer, &rocc->a_id,
1371 sizeof (struct GNUNET_PeerIdentity)));
1372 LOG_DEBUG ("0x%llx: Peer %4s connected\n", rocc->op_id,
1373 GNUNET_i2s (&rocc->a_id));
1374 cleanup_rocc (rocc);
1379 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1380 * whose identity is in RemoteOverlayConnectCtx
1382 * @param cls the RemoteOverlayConnectCtx
1383 * @param tc the TaskContext from scheduler
1386 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1390 * Task that is run when hello has been sent
1392 * @param cls the overlay connect context
1393 * @param tc the scheduler task context; if tc->reason =
1394 * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1395 * GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1398 rocc_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1400 struct RemoteOverlayConnectCtx *rocc = cls;
1403 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rocc->attempt_connect_task_id);
1404 LOG_DEBUG ("0x%llx: HELLO of peer %4s sent to local peer with id: %u\n",
1405 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1406 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
1409 rocc->attempt_connect_task_id =
1410 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1413 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
1415 rocc->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &rocc->tcc);
1420 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1421 * whose identity is in RemoteOverlayConnectCtx
1423 * @param cls the RemoteOverlayConnectCtx
1424 * @param tc the TaskContext from scheduler
1427 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1429 struct RemoteOverlayConnectCtx *rocc = cls;
1431 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id);
1432 rocc->attempt_connect_task_id = GNUNET_SCHEDULER_NO_TASK;
1433 LOG_DEBUG ("0x%llx: Offering HELLO of peer %4s to local peer with id: %u\n",
1434 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1436 GNUNET_TRANSPORT_offer_hello (rocc->tcc.th_, rocc->hello,
1437 rocc_hello_sent_cb, rocc);
1438 if (NULL == rocc->ohh)
1439 rocc->attempt_connect_task_id =
1440 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1441 (GNUNET_TIME_UNIT_MILLISECONDS,
1443 GNUNET_CRYPTO_random_u32
1444 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1445 &attempt_connect_task, rocc);
1450 * Callback from cache with needed handles set
1452 * @param cls the closure passed to GST_cache_get_handle_transport()
1453 * @param ch the handle to CORE. Can be NULL if it is not requested
1454 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1455 * @param ignore_ peer identity which is ignored in this callback
1458 rocc_cache_get_handle_transport_cb (void *cls, struct GNUNET_CORE_Handle *ch,
1459 struct GNUNET_TRANSPORT_Handle *th,
1460 const struct GNUNET_PeerIdentity *ignore_)
1462 struct RemoteOverlayConnectCtx *rocc = cls;
1466 rocc->timeout_rocc_task_id =
1467 GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
1471 rocc->tcc.pid = &rocc->a_id;
1473 GNUNET_TRANSPORT_check_neighbour_connected (rocc->tcc.th_, rocc->tcc.pid))
1475 LOG_DEBUG ("0x%llx: Target peer %4s already connected to local peer: %u\n",
1476 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1477 cleanup_rocc (rocc);
1480 rocc->attempt_connect_task_id =
1481 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1486 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages
1489 * @param client identification of the client
1490 * @param message the actual message
1493 GST_handle_remote_overlay_connect (void *cls,
1494 struct GNUNET_SERVER_Client *client,
1495 const struct GNUNET_MessageHeader *message)
1497 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
1498 struct RemoteOverlayConnectCtx *rocc;
1504 msize = ntohs (message->size);
1505 if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize)
1508 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1511 msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message;
1512 if ((NULL == msg->hello) ||
1513 (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)))
1516 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1519 hsize = ntohs (msg->hello->size);
1520 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1524 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1527 peer_id = ntohl (msg->peer);
1528 if ((peer_id >= GST_peer_list_size) ||
1529 (NULL == (peer = GST_peer_list[peer_id])))
1531 GNUNET_break_op (0);
1532 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1535 if (GNUNET_YES == peer->is_remote)
1537 struct GNUNET_MessageHeader *msg2;
1539 msg2 = GNUNET_copy_message (message);
1540 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1542 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1545 rocc = GNUNET_malloc (sizeof (struct RemoteOverlayConnectCtx));
1546 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1547 GNUNET_CONTAINER_DLL_insert_tail (roccq_head, roccq_tail, rocc);
1548 memcpy (&rocc->a_id, &msg->peer_identity,
1549 sizeof (struct GNUNET_PeerIdentity));
1550 LOG_DEBUG ("Received request for overlay connection with op_id: 0x%llx "
1551 "from local peer %u to peer %4s with hello size: %u\n",
1552 rocc->op_id, peer_id, GNUNET_i2s (&rocc->a_id), hsize);
1554 rocc->peer->reference_cnt++;
1555 rocc->hello = GNUNET_malloc (hsize);
1556 memcpy (rocc->hello, msg->hello, hsize);
1558 GST_cache_get_handle_transport (peer_id, rocc->peer->details.local.cfg,
1559 &rocc_cache_get_handle_transport_cb, rocc,
1561 &cache_transport_peer_connect_notify,
1563 rocc->timeout_rocc_task_id =
1564 GNUNET_SCHEDULER_add_delayed (GST_timeout, &timeout_rocc_task, rocc);
1565 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1570 * Clears all pending overlay connect contexts in queue
1575 struct OverlayConnectContext *occ;
1577 while (NULL != (occ = occq_head))
1583 * Clears all pending remote overlay connect contexts in queue
1588 struct RemoteOverlayConnectCtx *rocc;
1590 while (NULL != (rocc = roccq_head))
1591 cleanup_rocc (rocc);