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"
28 #include "testbed_api_operations.h"
32 * Context information for transport try connect
34 struct TryConnectContext
37 * The identity of the peer to which the transport has to attempt a connection
39 struct GNUNET_PeerIdentity *pid;
42 * The transport handle
44 struct GNUNET_TRANSPORT_Handle *th_;
47 * The GetCacheHandle for the p1th transport handle
49 struct GSTCacheGetHandle *cgh_th;
52 * the try connect handle
54 struct GNUNET_TRANSPORT_TryConnectHandle *tch;
59 GNUNET_SCHEDULER_TaskIdentifier task;
62 * The id of the operation which is resposible for this context
67 * The number of times we attempted to connect
75 * Context information for connecting 2 peers in overlay
77 struct OverlayConnectContext
80 * The next pointer for maintaining a DLL
82 struct OverlayConnectContext *next;
85 * The prev pointer for maintaining a DLL
87 struct OverlayConnectContext *prev;
90 * The client which has requested for overlay connection
92 struct GNUNET_SERVER_Client *client;
95 * the peer which has to connect to the other peer
100 * Transport handle of the first peer to get its HELLO
102 struct GNUNET_TRANSPORT_Handle *p1th;
105 * The GetCacheHandle for the p1th transport handle
107 struct GSTGetCacheHandle *gch_p1th;
110 * Core handles of the first peer; used to notify when second peer connects to it
112 struct GNUNET_CORE_Handle *ch;
115 * HELLO of the other peer
117 struct GNUNET_MessageHeader *hello;
120 * Get hello handle to acquire HELLO of first peer
122 struct GNUNET_TRANSPORT_GetHelloHandle *ghh;
125 * The handle for offering HELLO
127 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
130 * The error message we send if this overlay connect operation has timed out
135 * Operation context for suboperations
137 struct OperationContext *opc;
140 * The local operation we create for this overlay connection
142 struct GNUNET_TESTBED_Operation *lop;
145 * Controller of peer 2; NULL if the peer is local
147 struct GNUNET_TESTBED_Controller *peer2_controller;
150 * The transport try connect context
152 struct TryConnectContext tcc;
155 * The peer identity of the first peer
157 struct GNUNET_PeerIdentity peer_identity;
160 * The peer identity of the other peer
162 struct GNUNET_PeerIdentity other_peer_identity;
165 * The id of the operation responsible for creating this context
170 * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
173 GNUNET_SCHEDULER_TaskIdentifier send_hello_task;
176 * The id of the overlay connect timeout task
178 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
181 * The id of the cleanup task
183 GNUNET_SCHEDULER_TaskIdentifier cleanup_task;
193 uint32_t other_peer_id;
199 * Context information for RequestOverlayConnect
200 * operations. RequestOverlayConnect is used when peers A, B reside on different
201 * hosts and the host controller for peer B is asked by the host controller of
202 * peer A to make peer B connect to peer A
204 struct RemoteOverlayConnectCtx
207 * the next pointer for DLL
209 struct RemoteOverlayConnectCtx *next;
212 * the prev pointer for DLL
214 struct RemoteOverlayConnectCtx *prev;
217 * The peer handle of peer B
224 struct GNUNET_MessageHeader *hello;
227 * The handle for offering HELLO
229 struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
232 * The transport try connect context
234 struct TryConnectContext tcc;
237 * The peer identity of peer A
239 struct GNUNET_PeerIdentity a_id;
242 * Task for offering HELLO of A to B and doing try_connect
244 GNUNET_SCHEDULER_TaskIdentifier attempt_connect_task_id;
247 * Task to timeout RequestOverlayConnect
249 GNUNET_SCHEDULER_TaskIdentifier timeout_rocc_task_id;
252 * The id of the operation responsible for creating this context
259 * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
261 static struct OverlayConnectContext *occq_head;
264 * DLL tail for OverlayConnectContext DLL
266 static struct OverlayConnectContext *occq_tail;
269 * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
272 static struct RemoteOverlayConnectCtx *roccq_head;
275 * DLL tail for RequectOverlayConnectContext DLL
277 static struct RemoteOverlayConnectCtx *roccq_tail;
281 * Cleans up ForwardedOverlayConnectContext
283 * @param focc the ForwardedOverlayConnectContext to cleanup
286 GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
288 GNUNET_free_non_null (focc->orig_msg);
294 * Timeout task for cancelling a forwarded overlay connect connect
296 * @param cls the ForwardedOverlayConnectContext
297 * @param tc the task context from the scheduler
300 forwarded_overlay_connect_timeout (void *cls,
301 const struct GNUNET_SCHEDULER_TaskContext
304 struct ForwardedOperationContext *fopc = cls;
305 struct RegisteredHostContext *rhc;
306 struct ForwardedOverlayConnectContext *focc;
309 focc = rhc->focc_dll_head;
310 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
311 GST_cleanup_focc (focc);
312 LOG_DEBUG ("Overlay linking between peers %u and %u failed\n", focc->peer1,
314 GST_forwarded_operation_timeout (cls, tc);
315 if (NULL != rhc->focc_dll_head)
316 GST_process_next_focc (rhc);
321 * Callback to be called when forwarded overlay connection operation has a reply
322 * from the sub-controller successfull. We have to relay the reply msg back to
325 * @param cls ForwardedOperationContext
326 * @param msg the peer create success message
329 forwarded_overlay_connect_listener (void *cls,
330 const struct GNUNET_MessageHeader *msg)
332 struct ForwardedOperationContext *fopc = cls;
333 struct RegisteredHostContext *rhc;
334 struct ForwardedOverlayConnectContext *focc;
337 GST_forwarded_operation_reply_relay (cls, msg);
338 focc = rhc->focc_dll_head;
339 GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
340 GST_cleanup_focc (focc);
341 if (NULL != rhc->focc_dll_head)
342 GST_process_next_focc (rhc);
347 * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
349 * @param rhc the RegisteredHostContext
352 GST_process_next_focc (struct RegisteredHostContext *rhc)
354 struct ForwardedOperationContext *fopc;
355 struct ForwardedOverlayConnectContext *focc;
357 focc = rhc->focc_dll_head;
358 GNUNET_assert (NULL != focc);
359 GNUNET_assert (RHC_OL_CONNECT == rhc->state);
360 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
361 GNUNET_SERVER_client_keep (rhc->client);
362 fopc->client = rhc->client;
363 fopc->operation_id = focc->operation_id;
365 fopc->type = OP_OVERLAY_CONNECT;
367 GNUNET_TESTBED_forward_operation_msg_ (rhc->gateway->controller,
368 focc->operation_id, focc->orig_msg,
369 &forwarded_overlay_connect_listener,
371 GNUNET_free (focc->orig_msg);
372 focc->orig_msg = NULL;
374 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &forwarded_overlay_connect_timeout,
376 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
381 * Cleanup overlay connect context structure
383 * @param occ the overlay connect context
386 cleanup_occ (struct OverlayConnectContext *occ)
388 if (NULL != occ->lop)
390 GNUNET_TESTBED_operation_release_ (occ->lop);
393 LOG_DEBUG ("0x%llx: Cleaning up occ\n", occ->op_id);
394 GNUNET_free_non_null (occ->emsg);
395 GNUNET_free_non_null (occ->hello);
396 GNUNET_SERVER_client_drop (occ->client);
397 if (NULL != occ->opc)
398 GNUNET_TESTBED_forward_operation_msg_cancel_ (occ->opc);
399 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
400 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
401 if (GNUNET_SCHEDULER_NO_TASK != occ->cleanup_task)
402 GNUNET_SCHEDULER_cancel (occ->cleanup_task);
403 if (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task)
404 GNUNET_SCHEDULER_cancel (occ->timeout_task);
407 GNUNET_CORE_disconnect (occ->ch);
408 occ->peer->reference_cnt--;
410 if (NULL != occ->ghh)
411 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
412 if (NULL != occ->ohh)
413 GNUNET_TRANSPORT_offer_hello_cancel (occ->ohh);
414 if (GNUNET_SCHEDULER_NO_TASK != occ->tcc.task)
415 GNUNET_SCHEDULER_cancel (occ->tcc.task);
416 if (NULL != occ->tcc.tch)
417 GNUNET_TRANSPORT_try_connect_cancel (occ->tcc.tch);
418 if (NULL != occ->p1th)
420 GNUNET_TRANSPORT_disconnect (occ->p1th);
421 occ->peer->reference_cnt--;
423 if (NULL != occ->tcc.cgh_th)
425 GST_cache_get_handle_done (occ->tcc.cgh_th);
426 GST_peer_list[occ->other_peer_id]->reference_cnt--;
428 if ((GNUNET_YES == occ->peer->destroy_flag) &&
429 (0 == occ->peer->reference_cnt))
430 GST_destroy_peer (occ->peer);
431 if ((NULL == occ->peer2_controller) &&
432 (GNUNET_YES == GST_peer_list[occ->other_peer_id]->destroy_flag) &&
433 (0 == GST_peer_list[occ->other_peer_id]->reference_cnt))
434 GST_destroy_peer (GST_peer_list[occ->other_peer_id]);
435 GNUNET_CONTAINER_DLL_remove (occq_head, occq_tail, occ);
436 GNUNET_assert (NULL == occ->lop);
442 * Task for cleaing up overlay connect context structure
444 * @param cls the overlay connect context
445 * @param tc the task context
448 do_cleanup_occ (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
450 struct OverlayConnectContext *occ = cls;
452 occ->cleanup_task = GNUNET_SCHEDULER_NO_TASK;
458 * Task which will be run when overlay connect request has been timed out
460 * @param cls the OverlayConnectContext
461 * @param tc the TaskContext
464 timeout_overlay_connect (void *cls,
465 const struct GNUNET_SCHEDULER_TaskContext *tc)
467 struct OverlayConnectContext *occ = cls;
469 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
470 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
471 LOG (GNUNET_ERROR_TYPE_WARNING,
472 "0x%llx: Timeout while connecting peers %u and %u\n", occ->op_id,
473 occ->peer_id, occ->other_peer_id);
474 GST_send_operation_fail_msg (occ->client, occ->op_id, occ->emsg);
480 * Function called to notify transport users that another
481 * peer connected to us.
484 * @param new_peer the peer that connected
485 * @param ats performance data
486 * @param ats_count number of entries in ats (excluding 0-termination)
489 overlay_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer,
490 const struct GNUNET_ATS_Information *ats,
491 unsigned int ats_count)
493 struct OverlayConnectContext *occ = cls;
494 struct GNUNET_TESTBED_ConnectionEventMessage *msg;
496 char *other_peer_str;
498 //LOG_DEBUG ("Overlay connect notify\n");
500 memcmp (new_peer, &occ->peer_identity,
501 sizeof (struct GNUNET_PeerIdentity)))
503 new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
504 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
506 memcmp (new_peer, &occ->other_peer_identity,
507 sizeof (struct GNUNET_PeerIdentity)))
509 /* LOG_DEBUG ("Unexpected peer %4s connected when expecting peer %4s\n", */
510 /* new_peer_str, other_peer_str); */
511 GNUNET_free (new_peer_str);
512 GNUNET_free (other_peer_str);
515 GNUNET_free (new_peer_str);
516 LOG_DEBUG ("0x%llx: Peer %4s connected to peer %4s\n", occ->op_id,
517 other_peer_str, GNUNET_i2s (&occ->peer_identity));
518 GNUNET_free (other_peer_str);
519 if (GNUNET_SCHEDULER_NO_TASK != occ->send_hello_task)
521 GNUNET_SCHEDULER_cancel (occ->send_hello_task);
522 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
524 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task);
525 GNUNET_SCHEDULER_cancel (occ->timeout_task);
526 occ->timeout_task = GNUNET_SCHEDULER_NO_TASK;
527 if (GNUNET_SCHEDULER_NO_TASK != occ->tcc.task)
529 GNUNET_SCHEDULER_cancel (occ->tcc.task);
530 occ->tcc.task = GNUNET_SCHEDULER_NO_TASK;
532 GNUNET_free_non_null (occ->emsg);
534 LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
536 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
538 htons (sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
539 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
540 msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
541 msg->peer1 = htonl (occ->peer_id);
542 msg->peer2 = htonl (occ->other_peer_id);
543 msg->operation_id = GNUNET_htonll (occ->op_id);
544 GST_queue_message (occ->client, &msg->header);
545 occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
551 * Task to ask transport of a peer to connect to another peer
553 * @param cls the TryConnectContext
554 * @param tc the scheduler task context
557 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
561 * Callback to be called with result of the try connect request.
563 * @param cls the overlay connect context
564 * @param result GNUNET_OK if message was transmitted to transport service
565 * GNUNET_SYSERR if message was not transmitted to transport service
568 try_connect_cb (void *cls, const int result)
570 struct TryConnectContext *tcc = cls;
573 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == tcc->task);
575 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
576 (GNUNET_TIME_UNIT_MILLISECONDS,
577 500 + pow (2, ++tcc->retries)),
578 &try_connect_task, tcc);
583 * Task to ask transport of a peer to connect to another peer
585 * @param cls the TryConnectContext
586 * @param tc the scheduler task context
589 try_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
591 struct TryConnectContext *tcc = cls;
593 tcc->task = GNUNET_SCHEDULER_NO_TASK;
594 if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
596 GNUNET_assert (NULL == tcc->tch);
597 GNUNET_assert (NULL != tcc->pid);
598 GNUNET_assert (NULL != tcc->th_);
599 GNUNET_assert (NULL != tcc->cgh_th);
600 LOG_DEBUG ("0x%llx: Trail %u to connect to peer %s\n", tcc->op_id,
601 tcc->retries, GNUNET_i2s (tcc->pid));
603 GNUNET_TRANSPORT_try_connect (tcc->th_, tcc->pid, &try_connect_cb, tcc);
608 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
611 * @param cls the OverlayConnectContext
612 * @param tc the TaskContext from scheduler
615 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
619 * Task that is run when hello has been sent
621 * @param cls the overlay connect context
622 * @param tc the scheduler task context; if tc->reason =
623 * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
624 * GNUNET_SCHEDULER_REASON_READ_READY is succeeded
627 occ_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
629 struct OverlayConnectContext *occ = cls;
632 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->send_hello_task);
633 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
635 GNUNET_free_non_null (occ->emsg);
636 GNUNET_asprintf (&occ->emsg,
637 "0x%llx: Timeout while offering HELLO to other peer",
639 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
642 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
644 GNUNET_free_non_null (occ->emsg);
645 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while try connect", occ->op_id);
646 occ->tcc.pid = &occ->peer_identity;
647 occ->tcc.op_id = occ->op_id;
648 occ->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &occ->tcc);
653 * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
656 * @param cls the OverlayConnectContext
657 * @param tc the TaskContext from scheduler
660 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
662 struct OverlayConnectContext *occ = cls;
663 char *other_peer_str;
665 occ->send_hello_task = GNUNET_SCHEDULER_NO_TASK;
666 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
668 GNUNET_assert (NULL != occ->hello);
669 other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
670 if (NULL != occ->peer2_controller)
672 struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
676 LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote "
677 "Overlay Request\n", occ->op_id,
678 GNUNET_i2s (&occ->peer_identity), ntohs (occ->hello->size),
680 hello_size = ntohs (occ->hello->size);
682 sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
683 msg = GNUNET_malloc (msize);
685 htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
686 msg->header.size = htons (msize);
687 msg->peer = htonl (occ->other_peer_id);
688 msg->operation_id = GNUNET_htonll (occ->op_id);
689 (void) memcpy (&msg->peer_identity, &occ->peer_identity,
690 sizeof (struct GNUNET_PeerIdentity));
691 memcpy (msg->hello, occ->hello, hello_size);
692 GNUNET_TESTBED_queue_message_ (occ->peer2_controller, &msg->header);
696 LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n", occ->op_id,
697 GNUNET_i2s (&occ->peer_identity), other_peer_str);
699 GNUNET_TRANSPORT_offer_hello (occ->tcc.th_, occ->hello,
700 occ_hello_sent_cb, occ);
701 if (NULL == occ->ohh)
704 occ->send_hello_task =
705 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
706 (GNUNET_TIME_UNIT_MILLISECONDS,
708 GNUNET_CRYPTO_random_u32
709 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
713 GNUNET_free (other_peer_str);
718 * Callback from cache with needed handles set
720 * @param cls the closure passed to GST_cache_get_handle_transport()
721 * @param ch the handle to CORE. Can be NULL if it is not requested
722 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
725 p2_transport_connect_cache_callback (void *cls, struct GNUNET_CORE_Handle *ch,
726 struct GNUNET_TRANSPORT_Handle *th)
728 struct OverlayConnectContext *occ = cls;
732 GNUNET_asprintf (&occ->emsg, "0x%llx: Cannot connect to TRANSPORT of %s",
733 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
734 GNUNET_SCHEDULER_cancel (occ->timeout_task);
736 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
740 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
741 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
742 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
747 * Connects to the transport of the other peer if it is a local peer and
748 * schedules the send hello task
750 * @param occ the overlay connect context
753 p2_transport_connect (struct OverlayConnectContext *occ)
755 GNUNET_assert (NULL == occ->emsg);
756 GNUNET_assert (NULL != occ->hello);
757 GNUNET_assert (NULL == occ->ghh);
758 GNUNET_assert (NULL == occ->p1th);
759 if (NULL == occ->peer2_controller)
761 GST_peer_list[occ->other_peer_id]->reference_cnt++;
763 GST_cache_get_handle_transport (occ->other_peer_id,
764 GST_peer_list[occ->other_peer_id]->
766 &p2_transport_connect_cache_callback,
770 GNUNET_asprintf (&occ->emsg, "0x%llx: Timeout while offering HELLO to %s",
771 occ->op_id, GNUNET_i2s (&occ->other_peer_identity));
772 occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
777 * Test for checking whether HELLO message is empty
779 * @param cls empty flag to set
780 * @param address the HELLO
781 * @param expiration expiration of the HELLO
785 test_address (void *cls, const struct GNUNET_HELLO_Address *address,
786 struct GNUNET_TIME_Absolute expiration)
796 * Function called whenever there is an update to the HELLO of peers in the
797 * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
798 * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
801 * @param hello our updated HELLO
804 hello_update_cb (void *cls, const struct GNUNET_MessageHeader *hello)
806 struct OverlayConnectContext *occ = cls;
810 msize = ntohs (hello->size);
812 (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
813 hello, GNUNET_NO, &test_address,
815 if (GNUNET_YES == empty)
817 LOG_DEBUG ("0x%llx: HELLO of %s is empty\n", occ->op_id,
818 GNUNET_i2s (&occ->peer_identity));
821 LOG_DEBUG ("0x%llx: Received HELLO of %s\n", occ->op_id,
822 GNUNET_i2s (&occ->peer_identity));
823 occ->hello = GNUNET_malloc (msize);
824 GST_cache_add_hello (occ->peer_id, hello);
825 memcpy (occ->hello, hello, msize);
826 GNUNET_TRANSPORT_get_hello_cancel (occ->ghh);
828 GNUNET_TRANSPORT_disconnect (occ->p1th);
830 occ->peer->reference_cnt--;
831 GNUNET_free_non_null (occ->emsg);
833 p2_transport_connect (occ);
838 * Function called after GNUNET_CORE_connect has succeeded (or failed
839 * for good). Note that the private key of the peer is intentionally
840 * not exposed here; if you need it, your process should try to read
841 * the private key file directly (which should work if you are
845 * @param server handle to the server, NULL if we failed
846 * @param my_identity ID of this peer, NULL if we failed
849 core_startup_cb (void *cls, struct GNUNET_CORE_Handle *server,
850 const struct GNUNET_PeerIdentity *my_identity)
852 struct OverlayConnectContext *occ = cls;
853 const struct GNUNET_MessageHeader *hello;
855 GNUNET_free_non_null (occ->emsg);
856 (void) GNUNET_asprintf (&occ->emsg,
857 "0x%llx: Failed to connect to CORE of peer with"
858 "id: %u", occ->op_id, occ->peer_id);
859 if ((NULL == server) || (NULL == my_identity))
861 GNUNET_free (occ->emsg);
864 memcpy (&occ->peer_identity, my_identity,
865 sizeof (struct GNUNET_PeerIdentity));
866 LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n", occ->op_id,
867 GNUNET_i2s (&occ->peer_identity));
868 /* Lookup for HELLO in hello cache */
869 if (NULL != (hello = GST_cache_lookup_hello (occ->peer_id)))
871 LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n", occ->op_id,
872 GNUNET_i2s (&occ->peer_identity));
873 occ->hello = GNUNET_copy_message (hello);
874 p2_transport_connect (occ);
877 occ->peer->reference_cnt++;
879 GNUNET_TRANSPORT_connect (occ->peer->details.local.cfg,
880 &occ->peer_identity, NULL, NULL, NULL, NULL);
881 if (NULL == occ->p1th)
883 GNUNET_asprintf (&occ->emsg,
884 "0x%llx: Cannot connect to TRANSPORT of peer %4s",
885 occ->op_id, GNUNET_i2s (&occ->peer_identity));
888 GNUNET_asprintf (&occ->emsg,
889 "0x%llx: Timeout while acquiring HELLO of peer %4s",
890 occ->op_id, GNUNET_i2s (&occ->peer_identity));
891 occ->ghh = GNUNET_TRANSPORT_get_hello (occ->p1th, &hello_update_cb, occ);
895 GNUNET_SCHEDULER_cancel (occ->timeout_task);
896 occ->timeout_task = GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
902 * Callback which will be called when overlay connect operation is started
904 * @param cls the closure from GNUNET_TESTBED_operation_create_()
907 opstart_overlay_connect (void *cls)
909 struct OverlayConnectContext *occ = cls;
911 const struct GNUNET_CORE_MessageHandler no_handlers[] = {
915 GNUNET_assert (NULL != occ->lop);
916 /* Connect to the core of 1st peer and wait for the 2nd peer to connect */
917 occ->emsg = GNUNET_strdup ("Timeout while connecting to CORE");
918 GNUNET_asprintf (&occ->emsg,
919 "0x%llx: Timeout while connecting to CORE of peer with "
920 "id: %u", occ->op_id, occ->peer_id);
921 occ->peer->reference_cnt++;
923 GNUNET_CORE_connect (occ->peer->details.local.cfg, occ, &core_startup_cb,
924 &overlay_connect_notify, NULL, NULL, GNUNET_NO, NULL,
925 GNUNET_NO, no_handlers);
926 if (GNUNET_SCHEDULER_NO_TASK != occ->timeout_task)
927 GNUNET_SCHEDULER_cancel (occ->timeout_task);
930 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
933 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_overlay_connect, occ);
938 * Callback which will be called when overlay connect operation is released
940 * @param cls the closure from GNUNET_TESTBED_operation_create_()
943 oprelease_overlay_connect (void *cls)
945 struct OverlayConnectContext *occ = cls;
947 GNUNET_assert (NULL != occ->lop);
954 * Callback to be called when forwarded get peer config operation as part of
955 * overlay connect is successfull. Connection to Peer 1's core is made and is
956 * checked for new connection from peer 2
958 * @param cls ForwardedOperationContext
959 * @param msg the peer create success message
962 overlay_connect_get_config (void *cls, const struct GNUNET_MessageHeader *msg)
964 struct OverlayConnectContext *occ = cls;
965 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
968 if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION != ntohs (msg->type))
970 GNUNET_SCHEDULER_cancel (occ->timeout_task);
972 GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
975 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
976 memcpy (&occ->other_peer_identity, &cmsg->peer_identity,
977 sizeof (struct GNUNET_PeerIdentity));
978 GNUNET_free_non_null (occ->emsg);
980 GNUNET_assert (NULL == occ->lop);
982 GNUNET_TESTBED_operation_create_ (occ, &opstart_overlay_connect,
983 &oprelease_overlay_connect);
984 /* This operation needs in total 2 connections (one to core and one to
986 GNUNET_TESTBED_operation_queue_insert2_ (GST_opq_openfds, occ->lop, 2);
987 GNUNET_TESTBED_operation_begin_wait_ (occ->lop);
993 * Callback which will be called to after a host registration succeeded or failed
995 * @param cls the RegisteredHostContext
996 * @param emsg the error message; NULL if host registration is successful
999 registeredhost_registration_completion (void *cls, const char *emsg)
1001 struct RegisteredHostContext *rhc = cls;
1002 struct GNUNET_CONFIGURATION_Handle *cfg;
1003 uint32_t peer2_host_id;
1005 /* if (NULL != rhc->focc_dll_head) */
1006 /* TESTBED_process_next_focc (rhc); */
1007 peer2_host_id = GNUNET_TESTBED_host_get_id_ (rhc->reg_host);
1008 GNUNET_assert (RHC_INIT == rhc->state);
1009 GNUNET_assert (NULL == rhc->sub_op);
1010 if ((NULL == rhc->gateway2) || ((peer2_host_id < GST_slave_list_size) /* Check if we have the needed config */
1011 && (NULL != GST_slave_list[peer2_host_id])))
1013 rhc->state = RHC_LINK;
1016 rhc->gateway2) ? our_config : GST_slave_list[peer2_host_id]->cfg;
1018 GNUNET_TESTBED_controller_link (rhc, rhc->gateway->controller,
1019 rhc->reg_host, rhc->host, cfg,
1023 rhc->state = RHC_GET_CFG;
1025 GNUNET_TESTBED_get_slave_config (rhc, rhc->gateway2->controller,
1031 * Iterator to match a registered host context
1033 * @param cls pointer 2 pointer of RegisteredHostContext
1034 * @param key current key code
1035 * @param value value in the hash map
1036 * @return GNUNET_YES if we should continue to
1041 reghost_match_iterator (void *cls, const struct GNUNET_HashCode *key,
1044 struct RegisteredHostContext **rh = cls;
1045 struct RegisteredHostContext *rh_val = value;
1047 if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
1058 * Function to generate the hashcode corresponding to a RegisteredHostContext
1060 * @param reg_host the host which is being registered in RegisteredHostContext
1061 * @param host the host of the controller which has to connect to the above rhost
1062 * @return the hashcode
1064 static struct GNUNET_HashCode
1065 hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
1066 struct GNUNET_TESTBED_Host *host)
1068 struct GNUNET_HashCode hash;
1069 uint32_t host_ids[2];
1071 host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
1072 host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
1073 GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
1079 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OLCONNECT messages
1082 * @param client identification of the client
1083 * @param message the actual message
1086 GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client,
1087 const struct GNUNET_MessageHeader *message)
1089 const struct GNUNET_TESTBED_OverlayConnectMessage *msg;
1091 struct OverlayConnectContext *occ;
1092 struct GNUNET_TESTBED_Controller *peer2_controller;
1093 uint64_t operation_id;
1096 uint32_t peer2_host_id;
1098 if (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage) !=
1099 ntohs (message->size))
1102 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1105 msg = (const struct GNUNET_TESTBED_OverlayConnectMessage *) message;
1106 p1 = ntohl (msg->peer1);
1107 p2 = ntohl (msg->peer2);
1108 if ((p1 >= GST_peer_list_size) || (NULL == GST_peer_list[p1]))
1111 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1114 peer = GST_peer_list[p1];
1115 peer2_host_id = ntohl (msg->peer2_host_id);
1116 operation_id = GNUNET_ntohll (msg->operation_id);
1118 ("Received overlay connect for peers %u and %u with op id: 0x%llx\n", p1,
1120 if (GNUNET_YES == peer->is_remote)
1122 struct ForwardedOperationContext *fopc;
1123 struct Route *route_to_peer2_host;
1124 struct Route *route_to_peer1_host;
1126 LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", operation_id);
1127 route_to_peer2_host = NULL;
1128 route_to_peer1_host = NULL;
1129 route_to_peer2_host = GST_find_dest_route (peer2_host_id);
1130 if ((NULL != route_to_peer2_host) ||
1131 (peer2_host_id == GST_context->host_id))
1133 /* Peer 2 either below us OR with us */
1134 route_to_peer1_host =
1135 GST_find_dest_route (GST_peer_list[p1]->details.
1136 remote.remote_host_id);
1137 /* Because we get this message only if we know where peer 1 is */
1138 GNUNET_assert (NULL != route_to_peer1_host);
1139 if ((peer2_host_id == GST_context->host_id) ||
1140 (route_to_peer2_host->dest != route_to_peer1_host->dest))
1142 /* Peer2 is either with us OR peer1 and peer2 can be reached through
1143 * different gateways */
1144 struct GNUNET_HashCode hash;
1145 struct RegisteredHostContext *rhc;
1148 rhc = GNUNET_malloc (sizeof (struct RegisteredHostContext));
1149 if (NULL != route_to_peer2_host)
1150 rhc->reg_host = GST_host_list[route_to_peer2_host->dest];
1152 rhc->reg_host = GST_host_list[GST_context->host_id];
1153 rhc->host = GST_host_list[route_to_peer1_host->dest];
1154 GNUNET_assert (NULL != rhc->reg_host);
1155 GNUNET_assert (NULL != rhc->host);
1156 rhc->gateway = peer->details.remote.slave;
1159 route_to_peer2_host) ? NULL :
1160 GST_slave_list[route_to_peer2_host->dest];
1161 rhc->state = RHC_INIT;
1162 GNUNET_SERVER_client_keep (client);
1163 rhc->client = client;
1164 hash = hash_hosts (rhc->reg_host, rhc->host);
1165 skip_focc = GNUNET_NO;
1167 GNUNET_CONTAINER_multihashmap_contains (peer->details.
1168 remote.slave->reghost_map,
1171 GNUNET_CONTAINER_multihashmap_get_multiple (peer->details.remote.
1174 reghost_match_iterator,
1177 /* create and add a new registerd host context */
1178 /* add the focc to its queue */
1179 GNUNET_CONTAINER_multihashmap_put (peer->details.remote.
1180 slave->reghost_map, &hash, rhc,
1181 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1182 GNUNET_assert (NULL != GST_host_list[peer2_host_id]);
1183 GST_queue_host_registration (peer->details.remote.slave,
1184 registeredhost_registration_completion,
1185 rhc, GST_host_list[peer2_host_id]);
1189 /* rhc is now set to the existing one from the hash map by
1190 * reghost_match_iterator() */
1191 /* if queue is empty then ignore creating focc and proceed with
1192 * normal forwarding */
1193 if (RHC_OL_CONNECT == rhc->state)
1194 skip_focc = GNUNET_YES;
1196 if (GNUNET_NO == skip_focc)
1198 struct ForwardedOverlayConnectContext *focc;
1200 focc = GNUNET_malloc (sizeof (struct ForwardedOverlayConnectContext));
1203 focc->peer2_host_id = peer2_host_id;
1204 focc->orig_msg = GNUNET_copy_message (message);
1205 focc->operation_id = operation_id;
1206 GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
1207 rhc->focc_dll_tail, focc);
1208 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1213 fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
1214 GNUNET_SERVER_client_keep (client);
1215 fopc->client = client;
1216 fopc->operation_id = operation_id;
1217 fopc->type = OP_OVERLAY_CONNECT;
1219 GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
1220 slave->controller, operation_id,
1222 &GST_forwarded_operation_reply_relay,
1224 fopc->timeout_task =
1225 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &GST_forwarded_operation_timeout,
1227 GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
1228 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1232 peer2_controller = NULL;
1233 if ((p2 >= GST_peer_list_size) || (NULL == GST_peer_list[p2]))
1235 if ((peer2_host_id >= GST_slave_list_size) ||
1236 (NULL == GST_slave_list[peer2_host_id]))
1238 LOG (GNUNET_ERROR_TYPE_WARNING,
1239 "0x%llx: Configuration of peer2's controller missing for connecting peers"
1240 "%u and %u\n", operation_id, p1, p2);
1241 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1244 peer2_controller = GST_slave_list[peer2_host_id]->controller;
1245 if (NULL == peer2_controller)
1247 GNUNET_break (0); /* What's going on? */
1248 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1254 if (GNUNET_YES == GST_peer_list[p2]->is_remote)
1255 peer2_controller = GST_peer_list[p2]->details.remote.slave->controller;
1257 occ = GNUNET_malloc (sizeof (struct OverlayConnectContext));
1258 GNUNET_CONTAINER_DLL_insert_tail (occq_head, occq_tail, occ);
1259 GNUNET_SERVER_client_keep (client);
1260 occ->client = client;
1262 occ->other_peer_id = p2;
1263 occ->peer = GST_peer_list[p1];
1264 occ->op_id = GNUNET_ntohll (msg->operation_id);
1265 occ->peer2_controller = peer2_controller;
1266 /* Get the identity of the second peer */
1267 if (NULL != occ->peer2_controller)
1269 struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
1272 htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
1274 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION);
1275 cmsg.peer_id = msg->peer2;
1276 cmsg.operation_id = msg->operation_id;
1278 GNUNET_TESTBED_forward_operation_msg_ (occ->peer2_controller,
1279 occ->op_id, &cmsg.header,
1280 &overlay_connect_get_config,
1282 GNUNET_asprintf (&occ->emsg,
1283 "0x%llx: Timeout while getting peer identity of peer "
1284 "with id: %u", occ->op_id, occ->other_peer_id);
1285 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == occ->timeout_task);
1287 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_overlay_connect, occ);
1288 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1291 GNUNET_TESTING_peer_get_identity (GST_peer_list[occ->other_peer_id]->
1293 &occ->other_peer_identity);
1295 GNUNET_TESTBED_operation_create_ (occ, &opstart_overlay_connect,
1296 &oprelease_overlay_connect);
1297 /* This operation needs in total 2 connections (one to core and one to
1299 GNUNET_TESTBED_operation_queue_insert2_ (GST_opq_openfds, occ->lop, 2);
1300 GNUNET_TESTBED_operation_begin_wait_ (occ->lop);
1301 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1306 * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
1309 * @param rocc the RemoteOverlayConnectCtx
1312 cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
1314 LOG_DEBUG ("0x%llx: Cleaning up rocc\n", rocc->op_id);
1315 if (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id)
1316 GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
1317 if (GNUNET_SCHEDULER_NO_TASK != rocc->timeout_rocc_task_id)
1318 GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
1319 if (NULL != rocc->ohh)
1320 GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
1321 if (NULL != rocc->tcc.tch)
1322 GNUNET_TRANSPORT_try_connect_cancel (rocc->tcc.tch);
1323 if (GNUNET_SCHEDULER_NO_TASK != rocc->tcc.task)
1324 GNUNET_SCHEDULER_cancel (rocc->tcc.task);
1325 //GNUNET_TRANSPORT_disconnect (rocc->tcc.th_);
1326 GST_cache_get_handle_done (rocc->tcc.cgh_th);
1327 rocc->peer->reference_cnt--;
1328 if ((GNUNET_YES == rocc->peer->destroy_flag) &&
1329 (0 == rocc->peer->reference_cnt))
1330 GST_destroy_peer (rocc->peer);
1331 GNUNET_free_non_null (rocc->hello);
1332 GNUNET_CONTAINER_DLL_remove (roccq_head, roccq_tail, rocc);
1338 * Task to timeout rocc and cleanit up
1340 * @param cls the RemoteOverlayConnectCtx
1341 * @param tc the TaskContext from scheduler
1344 timeout_rocc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1346 struct RemoteOverlayConnectCtx *rocc = cls;
1348 GNUNET_assert (rocc->timeout_rocc_task_id != GNUNET_SCHEDULER_NO_TASK);
1349 rocc->timeout_rocc_task_id = GNUNET_SCHEDULER_NO_TASK;
1350 LOG_DEBUG ("0x%llx: rocc timed out\n", rocc->op_id);
1351 cleanup_rocc (rocc);
1356 * Function called to notify transport users that another
1357 * peer connected to us.
1359 * @param cls closure
1360 * @param new_peer the peer that connected
1361 * @param ats performance data
1362 * @param ats_count number of entries in ats (excluding 0-termination)
1365 transport_connect_notify (void *cls, const struct GNUNET_PeerIdentity *new_peer,
1366 const struct GNUNET_ATS_Information *ats,
1369 struct RemoteOverlayConnectCtx *rocc = cls;
1371 LOG_DEBUG ("0x%llx: Request Overlay connect notify\n", rocc->op_id);
1372 if (0 != memcmp (new_peer, &rocc->a_id, sizeof (struct GNUNET_PeerIdentity)))
1374 LOG_DEBUG ("0x%llx: Peer %4s connected\n", rocc->op_id,
1375 GNUNET_i2s (&rocc->a_id));
1376 cleanup_rocc (rocc);
1381 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1382 * whose identity is in RemoteOverlayConnectCtx
1384 * @param cls the RemoteOverlayConnectCtx
1385 * @param tc the TaskContext from scheduler
1388 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1392 * Task that is run when hello has been sent
1394 * @param cls the overlay connect context
1395 * @param tc the scheduler task context; if tc->reason =
1396 * GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
1397 * GNUNET_SCHEDULER_REASON_READ_READY is succeeded
1400 rocc_hello_sent_cb (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1402 struct RemoteOverlayConnectCtx *rocc = cls;
1405 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rocc->attempt_connect_task_id);
1406 LOG_DEBUG ("0x%llx: HELLO of peer %4s sent to local peer with id: %u\n",
1407 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1408 if (GNUNET_SCHEDULER_REASON_TIMEOUT == tc->reason)
1411 rocc->attempt_connect_task_id =
1412 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1415 if (GNUNET_SCHEDULER_REASON_READ_READY != tc->reason)
1417 rocc->tcc.task = GNUNET_SCHEDULER_add_now (&try_connect_task, &rocc->tcc);
1422 * Task to offer the HELLO message to the peer and ask it to connect to the peer
1423 * whose identity is in RemoteOverlayConnectCtx
1425 * @param cls the RemoteOverlayConnectCtx
1426 * @param tc the TaskContext from scheduler
1429 attempt_connect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1431 struct RemoteOverlayConnectCtx *rocc = cls;
1433 GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != rocc->attempt_connect_task_id);
1434 rocc->attempt_connect_task_id = GNUNET_SCHEDULER_NO_TASK;
1435 LOG_DEBUG ("0x%llx: Offering HELLO of peer %4s to local peer with id: %u\n",
1436 rocc->op_id, GNUNET_i2s (&rocc->a_id), rocc->peer->id);
1438 GNUNET_TRANSPORT_offer_hello (rocc->tcc.th_, rocc->hello,
1439 rocc_hello_sent_cb, rocc);
1440 if (NULL == rocc->ohh)
1441 rocc->attempt_connect_task_id =
1442 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
1443 (GNUNET_TIME_UNIT_MILLISECONDS,
1445 GNUNET_CRYPTO_random_u32
1446 (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
1447 &attempt_connect_task, rocc);
1452 * Callback from cache with needed handles set
1454 * @param cls the closure passed to GST_cache_get_handle_transport()
1455 * @param ch the handle to CORE. Can be NULL if it is not requested
1456 * @param th the handle to TRANSPORT. Can be NULL if it is not requested
1459 rocc_cache_get_handle_transport_cb (void *cls, struct GNUNET_CORE_Handle *ch,
1460 struct GNUNET_TRANSPORT_Handle *th)
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;
1472 rocc->attempt_connect_task_id =
1473 GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
1478 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages
1481 * @param client identification of the client
1482 * @param message the actual message
1485 GST_handle_remote_overlay_connect (void *cls,
1486 struct GNUNET_SERVER_Client *client,
1487 const struct GNUNET_MessageHeader *message)
1489 const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
1490 struct RemoteOverlayConnectCtx *rocc;
1496 msize = ntohs (message->size);
1497 if (sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) >= msize)
1500 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1503 msg = (const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *) message;
1504 if ((NULL == msg->hello) ||
1505 (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type)))
1508 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1511 hsize = ntohs (msg->hello->size);
1512 if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
1516 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1519 peer_id = ntohl (msg->peer);
1520 if ((peer_id >= GST_peer_list_size) ||
1521 (NULL == (peer = GST_peer_list[peer_id])))
1523 GNUNET_break_op (0);
1524 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1527 if (GNUNET_YES == peer->is_remote)
1529 struct GNUNET_MessageHeader *msg2;
1531 msg2 = GNUNET_copy_message (message);
1532 GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
1534 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1537 rocc = GNUNET_malloc (sizeof (struct RemoteOverlayConnectCtx));
1538 rocc->op_id = GNUNET_ntohll (msg->operation_id);
1539 GNUNET_CONTAINER_DLL_insert_tail (roccq_head, roccq_tail, rocc);
1540 memcpy (&rocc->a_id, &msg->peer_identity,
1541 sizeof (struct GNUNET_PeerIdentity));
1542 LOG_DEBUG ("Received request for overlay connection with op_id: 0x%llx "
1543 "from local peer %u to peer %4s with hello size: %u\n",
1544 rocc->op_id, peer_id, GNUNET_i2s (&rocc->a_id), hsize);
1546 rocc->peer->reference_cnt++;
1547 rocc->hello = GNUNET_malloc (hsize);
1548 memcpy (rocc->hello, msg->hello, hsize);
1549 rocc->tcc.cgh_th = GST_cache_get_handle_transport (peer_id,
1550 rocc->peer->details.local.cfg,
1551 &rocc_cache_get_handle_transport_cb,
1553 rocc->timeout_rocc_task_id =
1554 GNUNET_SCHEDULER_add_delayed (TIMEOUT, &timeout_rocc_task, rocc);
1555 GNUNET_SERVER_receive_done (client, GNUNET_OK);
1560 * Clears all pending overlay connect contexts in queue
1565 struct OverlayConnectContext *occ;
1567 while (NULL != (occ = occq_head))
1573 * Clears all pending remote overlay connect contexts in queue
1578 struct RemoteOverlayConnectCtx *rocc;
1580 while (NULL != (rocc = roccq_head))
1581 cleanup_rocc (rocc);