1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978 |
- /*
- This file is part of GNUnet.
- Copyright (C) 2008--2016 GNUnet e.V.
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- SPDX-License-Identifier: AGPL3.0-or-later
- */
- /**
- * @file testbed/gnunet-service-testbed_oc.c
- * @brief code for handling overlay connect operations
- * @author Sree Harsha Totakura
- */
- #include "gnunet-service-testbed.h"
- #include "gnunet-service-testbed_connectionpool.h"
- #include "gnunet_transport_hello_service.h"
- /**
- * Redefine LOG with a changed log component string
- */
- #ifdef LOG
- #undef LOG
- #endif
- #define LOG(kind, ...) \
- GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__)
- /**
- * Context information for requesting ATS to connect to a peer
- */
- struct ConnectivitySuggestContext
- {
- /**
- * The transport handle obtained from cache. Do NOT close/disconnect.
- */
- struct GNUNET_TRANSPORT_CoreHandle *th_;
- /**
- * Configuration of the peer from cache. Do not free!
- */
- const struct GNUNET_CONFIGURATION_Handle *cfg;
- /**
- * The GetCacheHandle for the peer2's transport handle
- * (used to offer the HELLO to the peer).
- */
- struct GST_ConnectionPool_GetHandle *cgh_p2_th;
- /**
- * The GetCacheHandle for the peer2's ATS handle.
- */
- struct GST_ConnectionPool_GetHandle *cgh_p2_ats;
- /**
- * The ATS handle for the connectivity suggestion.
- */
- struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
- };
- /**
- * Types for context information we create for overlay connect requests
- */
- enum OverlayConnectContextType
- {
- /**
- * This type is used if the overlay connection is local i.e. the connection
- * has to be made between local peers
- */
- OCC_TYPE_LOCAL,
- /**
- * Type to be used when the first peer is local and the other peer is on a slave
- * controller started by us
- */
- OCC_TYPE_REMOTE_SLAVE,
- /**
- * Type to be used when the first peer is local and the other peer is on a
- * controller which is not started by us.
- */
- OCC_TYPE_REMOTE_LATERAL
- };
- /**
- * Context data for operations on second peer in local overlay connection
- * contexts
- */
- struct LocalPeer2Context
- {
- /**
- * The handle for offering the HELLO of the first peer to the second
- * peer.
- */
- struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
- /**
- * The transport ConnectivitySuggestContext
- */
- struct ConnectivitySuggestContext tcc;
- };
- /**
- * Context data for operations on second peer in remote overlay connection
- * contexts
- */
- struct RemotePeer2Context
- {
- /**
- * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay
- * connection then this can be NULL until the connection to the controller is
- * established
- */
- struct GNUNET_TESTBED_Controller *p2c;
- /**
- * Operation context for the suboperation we start to get the identity of the
- * second peer
- */
- struct OperationContext *opc;
- /**
- * Notification handle acquire to connect to a remote controller. Only used
- * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL.
- */
- struct NeighbourConnectNotification *ncn;
- /**
- * The neighbour handle. Only used if the type of overlay connection is
- * #OCC_TYPE_REMOTE_LATERAL.
- */
- struct Neighbour *p2n;
- };
- /**
- * Context information for connecting 2 peers in overlay.
- */
- struct OverlayConnectContext
- {
- /**
- * The next pointer for maintaining a DLL of all OverlayConnectContexts
- */
- struct OverlayConnectContext *next;
- /**
- * The prev pointer for maintaining a DLL of all OverlayConnectContexts
- */
- struct OverlayConnectContext *prev;
- /**
- * The client which has requested for overlay connection. This is used to send
- * either a success of failure message
- */
- struct GNUNET_SERVICE_Client *client;
- /**
- * the first peer which is to expect an overlay connection from the second peer.
- */
- struct Peer *peer;
- /**
- * Transport handle of the first peer obtained from cache to get its HELLO. Do
- * NOT close/disconnect.
- */
- struct GNUNET_TRANSPORT_CoreHandle *p1th_;
- /**
- * The #GST_ConnectionPool_GetHandle for the peer1's transport handle
- */
- struct GST_ConnectionPool_GetHandle *cgh_p1th;
- /**
- * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE
- * level peer connects and to get our identity.
- */
- struct GST_ConnectionPool_GetHandle *cgh_ch;
- /**
- * HELLO of the first peer. This should be sent to the second peer.
- */
- struct GNUNET_MessageHeader *hello;
- /**
- * Get GetHelloHandle to acquire a HELLO of the first peer
- */
- struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
- /**
- * The error message we send if this overlay connect operation has timed out
- */
- char *emsg;
- /**
- * Context information for operations on the second peer
- */
- union
- {
- /**
- * Context information to be used if the second peer is local
- */
- struct LocalPeer2Context local;
- /**
- * Context information to be used if the second peer is remote
- */
- struct RemotePeer2Context remote;
- } p2ctx;
- /**
- * The peer identity of the first peer
- */
- struct GNUNET_PeerIdentity peer_identity;
- /**
- * The peer identity of the other peer
- */
- struct GNUNET_PeerIdentity other_peer_identity;
- /**
- * The id of the operation responsible for creating this context
- */
- uint64_t op_id;
- /**
- * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
- * connect to peer 2
- */
- struct GNUNET_SCHEDULER_Task *send_hello_task;
- /**
- * The id of the overlay connect timeout task
- */
- struct GNUNET_SCHEDULER_Task *timeout_task;
- /**
- * The id of the cleanup task
- */
- struct GNUNET_SCHEDULER_Task *cleanup_task;
- /**
- * The type of this context information
- */
- enum OverlayConnectContextType type;
- /**
- * The id of the second peer which has to connect to the first peer
- */
- uint32_t other_peer_id;
- };
- /**
- * Context information for remote overlay connect operations. Remote overlay
- * connections are used when peers A and B reside on different hosts. In these
- * operations the host controller for peer B is asked by the host controller of
- * peer A to make peer B connect to peer A by sending the controller of peer B
- * the HELLO of peer A.
- */
- struct RemoteOverlayConnectCtx
- {
- /**
- * the next pointer for DLL
- */
- struct RemoteOverlayConnectCtx *next;
- /**
- * the prev pointer for DLL
- */
- struct RemoteOverlayConnectCtx *prev;
- /**
- * The peer handle of peer B
- */
- struct Peer *peer;
- /**
- * Peer A's HELLO
- */
- struct GNUNET_MessageHeader *hello;
- /**
- * The handle for offering HELLO
- */
- struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
- /**
- * The transport try connect context
- */
- struct ConnectivitySuggestContext tcc;
- /**
- * The peer identity of peer A
- */
- struct GNUNET_PeerIdentity a_id;
- /**
- * Task for offering HELLO of A to B and doing try_connect
- */
- struct GNUNET_SCHEDULER_Task *attempt_connect_task_id;
- /**
- * Task to timeout RequestOverlayConnect
- */
- struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id;
- /**
- * The id of the operation responsible for creating this context
- */
- uint64_t op_id;
- };
- /**
- * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
- */
- static struct OverlayConnectContext *occq_head;
- /**
- * DLL tail for OverlayConnectContext DLL
- */
- static struct OverlayConnectContext *occq_tail;
- /**
- * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
- * shutdown
- */
- static struct RemoteOverlayConnectCtx *roccq_head;
- /**
- * DLL tail for RequectOverlayConnectContext DLL
- */
- static struct RemoteOverlayConnectCtx *roccq_tail;
- /**
- * Cleans up ForwardedOverlayConnectContext
- *
- * @param focc the ForwardedOverlayConnectContext to cleanup
- */
- void
- GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
- {
- struct RegisteredHostContext *rhc = focc->rhc;
- GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head,
- rhc->focc_dll_tail,
- focc);
- GNUNET_free_non_null (focc->orig_msg);
- GNUNET_free (focc);
- }
- /**
- * Timeout task for cancelling a forwarded overlay connect connect
- *
- * @param cls the `struct ForwardedOperationContext`
- */
- static void
- forwarded_overlay_connect_timeout (void *cls)
- {
- struct ForwardedOperationContext *fopc = cls;
- struct RegisteredHostContext *rhc;
- struct ForwardedOverlayConnectContext *focc;
- fopc->timeout_task = NULL;
- rhc = fopc->cls;
- focc = rhc->focc_dll_head;
- LOG_DEBUG ("Overlay linking between peers %u and %u failed\n",
- focc->peer1,
- focc->peer2);
- GST_cleanup_focc (focc);
- GST_forwarded_operation_timeout (fopc);
- if (NULL != rhc->focc_dll_head)
- GST_process_next_focc (rhc);
- }
- /**
- * Callback to be called when forwarded overlay connection operation has a reply
- * from the sub-controller successfull. We have to relay the reply msg back to
- * the client
- *
- * @param cls ForwardedOperationContext
- * @param msg the peer create success message
- */
- static void
- forwarded_overlay_connect_listener (void *cls,
- const struct GNUNET_MessageHeader *msg)
- {
- struct ForwardedOperationContext *fopc = cls;
- struct RegisteredHostContext *rhc;
- struct ForwardedOverlayConnectContext *focc;
- rhc = fopc->cls;
- GST_forwarded_operation_reply_relay (cls, msg);
- focc = rhc->focc_dll_head;
- GST_cleanup_focc (focc);
- if (NULL != rhc->focc_dll_head)
- GST_process_next_focc (rhc);
- }
- /**
- * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
- *
- * @param rhc the RegisteredHostContext
- */
- void
- GST_process_next_focc (struct RegisteredHostContext *rhc)
- {
- struct ForwardedOperationContext *fopc;
- struct ForwardedOverlayConnectContext *focc;
- struct Peer *peer;
- struct Slave *slave;
- focc = rhc->focc_dll_head;
- GNUNET_assert (NULL != focc);
- GNUNET_assert (RHC_DONE == rhc->state);
- GNUNET_assert (VALID_PEER_ID (focc->peer1));
- peer = GST_peer_list[focc->peer1];
- GNUNET_assert (GNUNET_YES == peer->is_remote);
- GNUNET_assert (NULL != (slave = peer->details.remote.slave));
- fopc = GNUNET_new (struct ForwardedOperationContext);
- fopc->client = focc->client;
- fopc->operation_id = focc->operation_id;
- fopc->cls = rhc;
- fopc->type = OP_OVERLAY_CONNECT;
- fopc->opc =
- GNUNET_TESTBED_forward_operation_msg_ (slave->controller,
- focc->operation_id,
- focc->orig_msg,
- &forwarded_overlay_connect_listener,
- fopc);
- GNUNET_free (focc->orig_msg);
- focc->orig_msg = NULL;
- fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout,
- &
- forwarded_overlay_connect_timeout,
- fopc);
- GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
- fopcq_tail,
- fopc);
- }
- /**
- * Cleans up any used handles in local peer2 context
- *
- * @param lp2c the local peer2 context information
- */
- static void
- cleanup_occ_lp2c (struct LocalPeer2Context *lp2c)
- {
- if (NULL != lp2c->ohh)
- {
- GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh);
- lp2c->ohh = NULL;
- }
- if (NULL != lp2c->tcc.cgh_p2_th)
- {
- GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th);
- lp2c->tcc.cgh_p2_th = NULL;
- }
- if (NULL != lp2c->tcc.cgh_p2_ats)
- {
- GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats);
- lp2c->tcc.cgh_p2_ats = NULL;
- }
- if (NULL != lp2c->tcc.csh)
- {
- GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh);
- lp2c->tcc.csh = NULL;
- }
- }
- /**
- * Cleans up any used handles in remote peer2 context. Relinquishes the
- * remote controller connection if it has been established on-demand.
- *
- * @param rp2c the remote peer2 context information
- */
- static void
- cleanup_occ_rp2c (struct RemotePeer2Context *rp2c)
- {
- if (NULL != rp2c->opc)
- {
- GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc);
- rp2c->opc = NULL;
- }
- if (NULL != rp2c->ncn)
- {
- GST_neighbour_get_connection_cancel (rp2c->ncn);
- rp2c->ncn = NULL;
- }
- if ((NULL != rp2c->p2c) && (NULL != rp2c->p2n))
- {
- GST_neighbour_release_connection (rp2c->p2n);
- rp2c->p2n = NULL;
- }
- }
- /**
- * Condition for checking if given peer is ready to be destroyed
- *
- * @param peer the peer to check
- */
- #define PEER_EXPIRED(peer) \
- ((GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt))
- /**
- * Cleanup overlay connect context structure
- *
- * @param occ the overlay connect context
- */
- static void
- cleanup_occ (struct OverlayConnectContext *occ)
- {
- struct Peer *peer2;
- LOG_DEBUG ("0x%llx: Cleaning up occ\n",
- occ->op_id);
- GNUNET_free_non_null (occ->emsg);
- GNUNET_free_non_null (occ->hello);
- if (NULL != occ->send_hello_task)
- GNUNET_SCHEDULER_cancel (occ->send_hello_task);
- if (NULL != occ->cleanup_task)
- GNUNET_SCHEDULER_cancel (occ->cleanup_task);
- if (NULL != occ->timeout_task)
- GNUNET_SCHEDULER_cancel (occ->timeout_task);
- if (NULL != occ->cgh_ch)
- GST_connection_pool_get_handle_done (occ->cgh_ch);
- if (NULL != occ->ghh)
- GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
- GST_connection_pool_get_handle_done (occ->cgh_p1th);
- GNUNET_assert (NULL != GST_peer_list);
- GNUNET_assert (occ->peer->reference_cnt > 0);
- occ->peer->reference_cnt--;
- if (PEER_EXPIRED (occ->peer))
- GST_destroy_peer (occ->peer);
- switch (occ->type)
- {
- case OCC_TYPE_LOCAL:
- peer2 = GST_peer_list[occ->other_peer_id];
- GNUNET_assert (peer2->reference_cnt > 0);
- peer2->reference_cnt--;
- if (PEER_EXPIRED (peer2))
- GST_destroy_peer (peer2);
- cleanup_occ_lp2c (&occ->p2ctx.local);
- break;
- case OCC_TYPE_REMOTE_SLAVE:
- case OCC_TYPE_REMOTE_LATERAL:
- cleanup_occ_rp2c (&occ->p2ctx.remote);
- break;
- }
- GNUNET_CONTAINER_DLL_remove (occq_head,
- occq_tail,
- occ);
- GNUNET_free (occ);
- }
- /**
- * Task for cleaing up overlay connect context structure
- *
- * @param cls the overlay connect context
- */
- static void
- do_cleanup_occ (void *cls)
- {
- struct OverlayConnectContext *occ = cls;
- occ->cleanup_task = NULL;
- cleanup_occ (occ);
- }
- /**
- * Task which will be run when overlay connect request has been timed out
- *
- * @param cls the OverlayConnectContext
- */
- static void
- timeout_overlay_connect (void *cls)
- {
- struct OverlayConnectContext *occ = cls;
- GNUNET_assert (NULL != occ->timeout_task);
- occ->timeout_task = NULL;
- /* LOG (GNUNET_ERROR_TYPE_WARNING, */
- /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
- /* occ->peer->id, occ->other_peer_id, occ->emsg); */
- GST_send_operation_fail_msg (occ->client,
- occ->op_id,
- occ->emsg);
- cleanup_occ (occ);
- }
- /**
- * Notify OC subsystem that @a client disconnected.
- *
- * @param client the client that disconnected
- */
- void
- GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client)
- {
- struct ForwardedOperationContext *fopc;
- struct ForwardedOperationContext *fopcn;
- struct OverlayConnectContext *occ;
- struct OverlayConnectContext *occn;
- for (fopc = fopcq_head; NULL != fopc; fopc = fopcn)
- {
- fopcn = fopc->next;
- if (fopc->client == client)
- {
- GNUNET_SCHEDULER_cancel (fopc->timeout_task);
- GST_forwarded_operation_timeout (fopc);
- }
- }
- for (occ = occq_head; NULL != occ; occ = occn)
- {
- occn = occ->next;
- if (occ->client == client)
- cleanup_occ (occ);
- }
- // FIXME: implement clean up for client_keep replacements!
- }
- /**
- * FIXME.
- */
- static void
- send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
- {
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_TESTBED_ConnectionEventMessage *msg;
- LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
- occ->op_id);
- env = GNUNET_MQ_msg (msg,
- GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
- msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
- msg->peer1 = htonl (occ->peer->id);
- msg->peer2 = htonl (occ->other_peer_id);
- msg->operation_id = GNUNET_htonll (occ->op_id);
- GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (occ->client),
- env);
- }
- /**
- * Function called to notify transport users that another
- * peer connected to us.
- *
- * @param cls closure
- * @param new_peer the peer that connected
- */
- static void
- overlay_connect_notify (void *cls,
- const struct GNUNET_PeerIdentity *new_peer)
- {
- struct OverlayConnectContext *occ = cls;
- char *new_peer_str;
- char *other_peer_str;
- LOG_DEBUG ("Overlay connect notify\n");
- if (0 ==
- memcmp (new_peer, &occ->peer_identity,
- sizeof(struct GNUNET_PeerIdentity)))
- return;
- new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
- other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
- if (0 !=
- memcmp (new_peer,
- &occ->other_peer_identity,
- sizeof(struct GNUNET_PeerIdentity)))
- {
- LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n",
- new_peer_str,
- other_peer_str);
- GNUNET_free (new_peer_str);
- GNUNET_free (other_peer_str);
- return;
- }
- GNUNET_free (new_peer_str);
- LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n",
- occ->op_id,
- other_peer_str,
- GNUNET_i2s (&occ->peer_identity));
- GNUNET_free (other_peer_str);
- if (NULL != occ->send_hello_task)
- {
- GNUNET_SCHEDULER_cancel (occ->send_hello_task);
- occ->send_hello_task = NULL;
- }
- GNUNET_assert (NULL != occ->timeout_task);
- GNUNET_SCHEDULER_cancel (occ->timeout_task);
- occ->timeout_task = NULL;
- switch (occ->type)
- {
- case OCC_TYPE_LOCAL:
- cleanup_occ_lp2c (&occ->p2ctx.local);
- break;
- case OCC_TYPE_REMOTE_SLAVE:
- case OCC_TYPE_REMOTE_LATERAL:
- cleanup_occ_rp2c (&occ->p2ctx.remote);
- break;
- }
- GNUNET_free_non_null (occ->emsg);
- occ->emsg = NULL;
- send_overlay_connect_success_msg (occ);
- occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ,
- occ);
- }
- /**
- * Callback from cache with needed ATS handle set
- *
- * @param cls a `struct OverlayConnectCtx *`
- * @param ch the handle to CORE. Can be NULL if it is not requested
- * @param th the handle to TRANSPORT. Can be NULL if it is not requested
- * @param ac the handle to ATS. Can be NULL if it is not requested
- * @param my_identity the identity of our peer
- * @param cfg configuration of the peer
- */
- static void
- occ_cache_get_handle_ats_occ_cb (void *cls,
- struct GNUNET_CORE_Handle *ch,
- struct GNUNET_TRANSPORT_CoreHandle *th,
- struct GNUNET_ATS_ConnectivityHandle *ac,
- const struct GNUNET_PeerIdentity *my_identity,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
- {
- struct OverlayConnectContext *occ = cls;
- struct LocalPeer2Context *lp2c;
- GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
- GNUNET_assert (NULL != occ->timeout_task);
- GNUNET_free_non_null (occ->emsg);
- if (NULL == ac)
- {
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Failed to connect to ATS of peer with id: %u",
- occ->op_id,
- occ->peer->id);
- GNUNET_SCHEDULER_cancel (occ->timeout_task);
- occ->timeout_task =
- GNUNET_SCHEDULER_add_now (&timeout_overlay_connect,
- occ);
- return;
- }
- occ->emsg = NULL;
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s",
- occ->op_id,
- GNUNET_i2s (&occ->other_peer_identity));
- lp2c = &occ->p2ctx.local;
- lp2c->tcc.csh =
- GNUNET_ATS_connectivity_suggest (ac,
- &occ->peer_identity,
- 1);
- }
- /**
- * Callback from cache with needed ATS handle set
- *
- * @param cls a `struct RemoteOverlayConnectCtx *`
- * @param ch the handle to CORE. Can be NULL if it is not requested
- * @param th the handle to TRANSPORT. Can be NULL if it is not requested
- * @param ac the handle to ATS. Can be NULL if it is not requested
- * @param my_identity the identity of our peer
- */
- static void
- occ_cache_get_handle_ats_rocc_cb (void *cls,
- struct GNUNET_CORE_Handle *ch,
- struct GNUNET_TRANSPORT_CoreHandle *th,
- struct GNUNET_ATS_ConnectivityHandle *ac,
- const struct GNUNET_PeerIdentity *my_identity,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
- {
- struct RemoteOverlayConnectCtx *rocc = cls;
- rocc->tcc.csh =
- GNUNET_ATS_connectivity_suggest (ac,
- &rocc->a_id,
- 1);
- }
- /**
- * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
- * peer 1.
- *
- * @param cls the OverlayConnectContext
- */
- static void
- send_hello (void *cls);
- /**
- * Task that is run when hello has been sent If tc->reason =
- * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
- * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
- *
- * @param cls the overlay connect context
- */
- static void
- occ_hello_sent_cb (void *cls)
- {
- struct OverlayConnectContext *occ = cls;
- struct LocalPeer2Context *lp2c;
- struct Peer *peer2;
- GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
- GNUNET_assert (NULL != occ->timeout_task);
- lp2c = &occ->p2ctx.local;
- lp2c->ohh = NULL;
- GNUNET_assert (NULL == occ->send_hello_task);
- GNUNET_free_non_null (occ->emsg);
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Timeout while acquiring ATS of %s from cache",
- occ->op_id,
- GNUNET_i2s (&occ->other_peer_identity));
- GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
- lp2c->tcc.cgh_p2_ats =
- GST_connection_pool_get_handle (occ->other_peer_id,
- peer2->details.local.cfg,
- GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
- &occ_cache_get_handle_ats_occ_cb,
- occ, NULL, NULL, NULL);
- }
- /**
- * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
- * request.
- *
- * @param occ the overlay connect context. Its type must be either
- * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL
- */
- static void
- send_hello_thru_rocc (struct OverlayConnectContext *occ)
- {
- struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
- char *other_peer_str;
- uint16_t msize;
- uint16_t hello_size;
- GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
- GNUNET_assert (NULL != occ->hello);
- other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
- LOG_DEBUG (
- "0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n",
- occ->op_id,
- GNUNET_i2s (&occ->peer_identity),
- ntohs (occ->hello->size),
- other_peer_str);
- GNUNET_free (other_peer_str);
- hello_size = ntohs (occ->hello->size);
- msize = sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage)
- + hello_size;
- msg = GNUNET_malloc (msize);
- msg->header.type =
- htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
- msg->header.size = htons (msize);
- msg->peer = htonl (occ->other_peer_id);
- msg->operation_id = GNUNET_htonll (occ->op_id);
- msg->peer_identity = occ->peer_identity;
- GNUNET_memcpy (msg->hello,
- occ->hello,
- hello_size);
- GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c,
- &msg->header);
- }
- /**
- * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered
- * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
- * send_hello_thru_rocc()
- *
- * @param cls the OverlayConnectContext
- */
- static void
- send_hello (void *cls)
- {
- struct OverlayConnectContext *occ = cls;
- struct LocalPeer2Context *lp2c;
- char *other_peer_str;
- occ->send_hello_task = NULL;
- GNUNET_assert (NULL != occ->timeout_task);
- GNUNET_assert (NULL != occ->hello);
- if (OCC_TYPE_LOCAL != occ->type)
- {
- send_hello_thru_rocc (occ);
- return;
- }
- lp2c = &occ->p2ctx.local;
- other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
- LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n",
- occ->op_id,
- GNUNET_i2s (&occ->peer_identity),
- other_peer_str);
- GNUNET_free (other_peer_str);
- lp2c->ohh =
- GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg,
- occ->hello,
- &occ_hello_sent_cb,
- occ);
- if (NULL == lp2c->ohh)
- {
- GNUNET_break (0);
- occ->send_hello_task =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS,
- 100
- + GNUNET_CRYPTO_random_u32
- (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
- &send_hello, occ);
- }
- }
- /**
- * Callback from cache with needed handles set
- *
- * @param cls the closure passed to GST_cache_get_handle_transport()
- * @param ch the handle to CORE. Can be NULL if it is not requested
- * @param th the handle to TRANSPORT. Can be NULL if it is not requested
- * @param ac the handle to ATS. Can be NULL if it is not requested
- * @param ignore_ peer identity which is ignored in this callback
- * @param cfg configuration of the peer
- */
- static void
- p2_transport_connect_cache_callback (void *cls,
- struct GNUNET_CORE_Handle *ch,
- struct GNUNET_TRANSPORT_CoreHandle *th,
- struct GNUNET_ATS_ConnectivityHandle *ac,
- const struct GNUNET_PeerIdentity *ignore_,
- const struct
- GNUNET_CONFIGURATION_Handle *cfg)
- {
- struct OverlayConnectContext *occ = cls;
- GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
- if (NULL == th)
- {
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Cannot connect to TRANSPORT of %s",
- occ->op_id,
- GNUNET_i2s (&occ->other_peer_identity));
- GNUNET_SCHEDULER_cancel (occ->timeout_task);
- occ->timeout_task =
- GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
- return;
- }
- occ->p2ctx.local.tcc.th_ = th;
- occ->p2ctx.local.tcc.cfg = cfg;
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Timeout while offering HELLO to %s",
- occ->op_id,
- GNUNET_i2s (&occ->other_peer_identity));
- occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
- }
- /**
- * Connects to the transport of the other peer if it is a local peer and
- * schedules the send hello task
- *
- * @param occ the overlay connect context
- */
- static void
- p2_transport_connect (struct OverlayConnectContext *occ)
- {
- struct Peer *peer2;
- /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the
- HELLO! */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Connecting to transport of peer %s to obtain HELLO\n",
- GNUNET_i2s (&occ->other_peer_identity));
- GNUNET_assert (NULL == occ->emsg);
- GNUNET_assert (NULL != occ->hello);
- GNUNET_assert (NULL == occ->ghh);
- GNUNET_assert (NULL == occ->p1th_);
- GNUNET_assert (NULL == occ->cgh_p1th);
- if (OCC_TYPE_LOCAL == occ->type)
- {
- GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
- occ->p2ctx.local.tcc.cgh_p2_th =
- GST_connection_pool_get_handle (occ->other_peer_id,
- peer2->details.local.cfg,
- GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
- &p2_transport_connect_cache_callback,
- occ, NULL, NULL, NULL);
- return;
- }
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Timeout while offering HELLO to %s",
- occ->op_id,
- GNUNET_i2s (&occ->other_peer_identity));
- occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
- }
- /**
- * Test for checking whether HELLO message is empty
- *
- * @param cls empty flag to set
- * @param address the HELLO
- * @param expiration expiration of the HELLO
- * @return #GNUNET_OK
- */
- static int
- test_address (void *cls,
- const struct GNUNET_HELLO_Address *address,
- struct GNUNET_TIME_Absolute expiration)
- {
- int *empty = cls;
- *empty = GNUNET_NO;
- return GNUNET_OK;
- }
- /**
- * Function called whenever there is an update to the HELLO of peers in the
- * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
- * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
- *
- * @param cls closure
- * @param hello our updated HELLO
- */
- static void
- hello_update_cb (void *cls,
- const struct GNUNET_MessageHeader *hello)
- {
- struct OverlayConnectContext *occ = cls;
- int empty;
- uint16_t msize;
- msize = ntohs (hello->size);
- empty = GNUNET_YES;
- (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
- hello, GNUNET_NO,
- &test_address,
- &empty);
- if (GNUNET_YES == empty)
- {
- LOG_DEBUG ("0x%llx: HELLO of %s is empty\n",
- occ->op_id,
- GNUNET_i2s (&occ->peer_identity));
- return;
- }
- LOG_DEBUG ("0x%llx: Received HELLO of %s\n",
- occ->op_id,
- GNUNET_i2s (&occ->peer_identity));
- occ->hello = GNUNET_malloc (msize);
- GST_cache_add_hello (occ->peer->id, hello);
- GNUNET_memcpy (occ->hello, hello, msize);
- GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
- occ->ghh = NULL;
- GST_connection_pool_get_handle_done (occ->cgh_p1th);
- occ->cgh_p1th = NULL;
- occ->p1th_ = NULL;
- GNUNET_free_non_null (occ->emsg);
- occ->emsg = NULL;
- p2_transport_connect (occ);
- }
- /**
- * Callback from cache with needed handles set
- *
- * @param cls the closure passed to GST_cache_get_handle_transport()
- * @param ch the handle to CORE. Can be NULL if it is not requested
- * @param th the handle to TRANSPORT. Can be NULL if it is not requested
- * @param ac the handle to ATS. Can be NULL if it is not requested
- * @param ignore_ peer identity which is ignored in this callback
- */
- static void
- p1_transport_connect_cache_callback (void *cls,
- struct GNUNET_CORE_Handle *ch,
- struct GNUNET_TRANSPORT_CoreHandle *th,
- struct GNUNET_ATS_ConnectivityHandle *ac,
- const struct GNUNET_PeerIdentity *ignore_,
- const struct
- GNUNET_CONFIGURATION_Handle *cfg)
- {
- struct OverlayConnectContext *occ = cls;
- GNUNET_free_non_null (occ->emsg);
- occ->emsg = NULL;
- if (NULL == th)
- {
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Cannot connect to TRANSPORT of %s",
- occ->op_id,
- GNUNET_i2s (&occ->peer_identity));
- GNUNET_SCHEDULER_cancel (occ->timeout_task);
- occ->timeout_task =
- GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
- return;
- }
- GNUNET_assert (NULL == occ->p1th_);
- GNUNET_assert (NULL != occ->cgh_p1th);
- occ->p1th_ = th;
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Timeout while acquiring HELLO of peer %s",
- occ->op_id,
- GNUNET_i2s (&occ->peer_identity));
- occ->ghh = GNUNET_TRANSPORT_hello_get (cfg,
- GNUNET_TRANSPORT_AC_ANY,
- &hello_update_cb,
- occ);
- }
- /**
- * Callback from cache with needed CORE handle set
- *
- * @param cls the closure passed to GST_cache_get_handle_transport()
- * @param ch the handle to CORE. Can be NULL if it is not requested
- * @param th the handle to TRANSPORT. Can be NULL if it is not requested
- * @param ac the handle to ATS. Can be NULL if it is not requested
- * @param my_identity the identity of our peer
- */
- static void
- occ_cache_get_handle_core_cb (void *cls,
- struct GNUNET_CORE_Handle *ch,
- struct GNUNET_TRANSPORT_CoreHandle *th,
- struct GNUNET_ATS_ConnectivityHandle *ac,
- const struct GNUNET_PeerIdentity *my_identity,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
- {
- struct OverlayConnectContext *occ = cls;
- const struct GNUNET_MessageHeader *hello;
- GNUNET_assert (NULL != occ->timeout_task);
- GNUNET_free_non_null (occ->emsg);
- if ((NULL == ch) || (NULL == my_identity))
- {
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Failed to connect to CORE of peer with "
- "id: %u",
- occ->op_id,
- occ->peer->id);
- GNUNET_SCHEDULER_cancel (occ->timeout_task);
- occ->timeout_task =
- GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
- return;
- }
- occ->emsg = NULL;
- if (NULL !=
- GNUNET_CORE_get_mq (ch,
- &occ->other_peer_identity))
- {
- LOG_DEBUG ("0x%llx: Target peer already connected\n",
- occ->op_id);
- GNUNET_SCHEDULER_cancel (occ->timeout_task);
- occ->timeout_task = NULL;
- send_overlay_connect_success_msg (occ);
- occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
- return;
- }
- occ->peer_identity = *my_identity;
- LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n",
- occ->op_id,
- GNUNET_i2s (&occ->peer_identity));
- /* Lookup for HELLO in hello cache */
- if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
- {
- LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n",
- occ->op_id,
- GNUNET_i2s (&occ->peer_identity));
- occ->hello = GNUNET_copy_message (hello);
- p2_transport_connect (occ);
- return;
- }
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
- occ->op_id,
- GNUNET_i2s (&occ->peer_identity));
- occ->cgh_p1th =
- GST_connection_pool_get_handle (occ->peer->id,
- occ->peer->details.local.cfg,
- GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
- p1_transport_connect_cache_callback,
- occ,
- NULL, NULL, NULL);
- }
- /**
- * Callback to be called when forwarded get peer config operation as part of
- * overlay connect is successfull. Connection to Peer 1's core is made and is
- * checked for new connection from peer 2
- *
- * @param cls ForwardedOperationContext
- * @param msg the peer create success message
- */
- static void
- overlay_connect_get_config (void *cls,
- const struct GNUNET_MessageHeader *msg)
- {
- struct OverlayConnectContext *occ = cls;
- struct RemotePeer2Context *rp2c;
- const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
- GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
- rp2c = &occ->p2ctx.remote;
- rp2c->opc = NULL;
- GNUNET_assert (NULL != occ->timeout_task);
- if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
- {
- GNUNET_SCHEDULER_cancel (occ->timeout_task);
- occ->timeout_task =
- GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
- }
- cmsg =
- (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
- occ->other_peer_identity = cmsg->peer_identity;
- GNUNET_free_non_null (occ->emsg);
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Timeout while connecting to CORE of peer with "
- "id: %u",
- occ->op_id,
- occ->peer->id);
- occ->cgh_ch =
- GST_connection_pool_get_handle (occ->peer->id,
- occ->peer->details.local.cfg,
- GST_CONNECTIONPOOL_SERVICE_CORE,
- occ_cache_get_handle_core_cb,
- occ,
- &occ->other_peer_identity,
- &overlay_connect_notify,
- occ);
- return;
- }
- /**
- * Callback which will be called after a host registration succeeded or failed
- *
- * @param cls the RegisteredHostContext
- * @param emsg the error message; NULL if host registration is successful
- */
- static void
- host_registration_comp (void *cls, const char *emsg)
- {
- struct RegisteredHostContext *rhc = cls;
- rhc->state = RHC_DONE;
- GST_process_next_focc (rhc);
- }
- /**
- * Iterator to match a registered host context
- *
- * @param cls pointer 2 pointer of RegisteredHostContext
- * @param key current key code
- * @param value value in the hash map
- * @return #GNUNET_YES if we should continue to
- * iterate,
- * #GNUNET_NO if not.
- */
- static int
- reghost_match_iterator (void *cls,
- const struct GNUNET_HashCode *key,
- void *value)
- {
- struct RegisteredHostContext **rh = cls;
- struct RegisteredHostContext *rh_val = value;
- if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
- {
- GNUNET_free (*rh);
- *rh = rh_val;
- return GNUNET_NO;
- }
- return GNUNET_YES;
- }
- /**
- * Function to generate the hashcode corresponding to a RegisteredHostContext
- *
- * @param reg_host the host which is being registered in RegisteredHostContext
- * @param host the host of the controller which has to connect to the above rhost
- * @return the hashcode
- */
- static struct GNUNET_HashCode
- hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
- struct GNUNET_TESTBED_Host *host)
- {
- struct GNUNET_HashCode hash;
- uint32_t host_ids[2];
- host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
- host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
- GNUNET_CRYPTO_hash (host_ids, sizeof(host_ids), &hash);
- return hash;
- }
- /**
- * Checks if the given host is registered at the given slave.
- *
- * @param slave the slave where registration has to be checked. The check is
- * actually done through a locally maintained hashmap. No
- * communication with the slave is involved.
- * @param host the host to register
- * @return If the given host is not registered already or the registration is
- * pending, it returns the registration context. Any overlay connects
- * to be forwarded should be queued in the context so that they can be
- * executed when the registration is completed. If the given host is
- * already registered, NULL is returned.
- */
- static struct RegisteredHostContext *
- register_host (struct Slave *slave,
- struct GNUNET_TESTBED_Host *host)
- {
- struct GNUNET_HashCode hash;
- struct RegisteredHostContext *rhc;
- rhc = GNUNET_new (struct RegisteredHostContext);
- rhc->reg_host = host;
- rhc->host = GST_host_list[slave->host_id];
- GNUNET_assert (NULL != rhc->reg_host);
- GNUNET_assert (NULL != rhc->host);
- rhc->state = RHC_INIT;
- hash = hash_hosts (rhc->reg_host, rhc->host);
- if ((GNUNET_NO ==
- GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map,
- &hash)) ||
- (GNUNET_SYSERR !=
- GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
- &hash,
- reghost_match_iterator,
- &rhc)))
- {
- /* create and add a new registerd host context */
- /* add the focc to its queue */
- GNUNET_CONTAINER_multihashmap_put (slave->reghost_map,
- &hash,
- rhc,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
- GST_queue_host_registration (slave,
- host_registration_comp,
- rhc,
- rhc->reg_host);
- }
- else
- {
- /* rhc is now set to the existing one from the hash map by
- * reghost_match_iterator() */
- /* if queue is empty then ignore creating focc and proceed with normal
- * forwarding */
- if (RHC_DONE == rhc->state)
- return NULL;
- }
- return rhc;
- }
- /**
- * Forwards the overlay connect request to a slave controller. Before
- * forwarding, any hosts which are needed to be known by the slave controller to
- * execute the overlay connect request are registered at slave.
- *
- * @param msg the overlay connect request message to be forwarded
- * @param client the client to which the status of the forwarded request has to
- * be notified
- */
- static void
- forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
- struct GNUNET_SERVICE_Client *client)
- {
- struct ForwardedOperationContext *fopc;
- struct Route *route_to_peer2_host;
- struct Route *route_to_peer1_host;
- struct Peer *peer;
- struct RegisteredHostContext *rhc;
- struct ForwardedOverlayConnectContext *focc;
- uint64_t op_id;
- uint32_t peer2_host_id;
- uint32_t p1;
- uint32_t p2;
- p1 = ntohl (msg->peer1);
- p2 = ntohl (msg->peer2);
- op_id = GNUNET_ntohll (msg->operation_id);
- peer2_host_id = ntohl (msg->peer2_host_id);
- GNUNET_assert (VALID_PEER_ID (p1));
- GNUNET_assert (VALID_HOST_ID (peer2_host_id));
- peer = GST_peer_list[p1];
- GNUNET_assert (GNUNET_YES == peer->is_remote);
- LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
- route_to_peer2_host = GST_find_dest_route (peer2_host_id);
- route_to_peer1_host = GST_find_dest_route
- (peer->details.remote.remote_host_id);
- GNUNET_assert (NULL != route_to_peer1_host);
- if ((NULL != route_to_peer2_host) &&
- (route_to_peer1_host->dest == route_to_peer2_host->dest))
- goto forward;
- /* Peer2 is either with us OR peer1 and peer2 can be reached through
- different subtrees OR peer2 is on a subtree unknown to us */
- if (NULL != (rhc = register_host (peer->details.remote.slave,
- GST_host_list[peer2_host_id])))
- {
- LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1,
- p2);
- focc = GNUNET_new (struct ForwardedOverlayConnectContext);
- focc->rhc = rhc;
- focc->peer1 = p1;
- focc->peer2 = p2;
- focc->peer2_host_id = peer2_host_id;
- focc->orig_msg = GNUNET_copy_message (&msg->header);
- focc->operation_id = op_id;
- focc->client = client;
- GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
- rhc->focc_dll_tail,
- focc);
- return;
- }
- forward:
- LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1,
- p2);
- fopc = GNUNET_new (struct ForwardedOperationContext);
- fopc->client = client;
- fopc->operation_id = op_id;
- fopc->type = OP_OVERLAY_CONNECT;
- fopc->opc =
- GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
- slave->controller, op_id,
- &msg->header,
- &GST_forwarded_operation_reply_relay,
- fopc);
- fopc->timeout_task =
- GNUNET_SCHEDULER_add_delayed (GST_timeout,
- &GST_forwarded_operation_timeout,
- fopc);
- GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
- fopcq_tail,
- fopc);
- }
- /**
- * Callback called when a connection to the controller of peer2 has been
- * established
- *
- * @param cls the overlay connect contexts
- * @param c handle to the controller connection
- */
- static void
- p2_controller_connect_cb (void *cls,
- struct GNUNET_TESTBED_Controller *c)
- {
- struct OverlayConnectContext *occ = cls;
- struct RemotePeer2Context *rp2c;
- struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
- GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
- rp2c = &occ->p2ctx.remote;
- rp2c->ncn = NULL;
- rp2c->p2c = c;
- cmsg.header.size =
- htons (sizeof(struct GNUNET_TESTBED_PeerGetConfigurationMessage));
- cmsg.header.type =
- htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
- cmsg.peer_id = htonl (occ->other_peer_id);
- cmsg.operation_id = GNUNET_htonll (occ->op_id);
- rp2c->opc =
- GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
- occ->op_id,
- &cmsg.header,
- &overlay_connect_get_config,
- occ);
- GNUNET_free_non_null (occ->emsg);
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Timeout while getting peer identity of peer "
- "with id: %u",
- occ->op_id,
- occ->other_peer_id);
- }
- /**
- * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages
- *
- * @param cls identification of the client
- * @param msg the actual message
- */
- void
- handle_overlay_connect (void *cls,
- const struct GNUNET_TESTBED_OverlayConnectMessage *msg)
- {
- struct GNUNET_SERVICE_Client *client = cls;
- struct Peer *peer;
- struct Peer *peer2;
- struct OverlayConnectContext *occ;
- struct Neighbour *p2n;
- uint64_t operation_id;
- uint32_t p1;
- uint32_t p2;
- uint32_t peer2_host_id;
- p1 = ntohl (msg->peer1);
- p2 = ntohl (msg->peer2);
- if (! VALID_PEER_ID (p1))
- {
- GNUNET_break (0);
- GNUNET_SERVICE_client_drop (client);
- return;
- }
- peer = GST_peer_list[p1];
- operation_id = GNUNET_ntohll (msg->operation_id);
- LOG_DEBUG
- ("Received overlay connect for peers %u and %u with op id: 0x%llx\n",
- p1,
- p2,
- operation_id);
- peer2_host_id = ntohl (msg->peer2_host_id);
- if (GNUNET_YES == peer->is_remote)
- {
- if (! VALID_HOST_ID (peer2_host_id))
- {
- GNUNET_break (0);
- GNUNET_SERVICE_client_drop (client);
- return;
- }
- forward_overlay_connect (msg, client);
- GNUNET_SERVICE_client_continue (client);
- return;
- }
- p2n = NULL;
- occ = GNUNET_new (struct OverlayConnectContext);
- occ->type = OCC_TYPE_LOCAL;
- if (! VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */
- {
- if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
- {
- if (! VALID_HOST_ID (peer2_host_id))
- {
- GNUNET_break (0);
- LOG (GNUNET_ERROR_TYPE_WARNING,
- "0x%llx: Peer %u's host not in our neighbours list\n",
- operation_id, p2);
- GNUNET_SERVICE_client_drop (client);
- GNUNET_free (occ);
- return;
- }
- p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
- }
- occ->type = OCC_TYPE_REMOTE_LATERAL;
- occ->p2ctx.remote.p2n = p2n;
- }
- else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
- {
- occ->type = OCC_TYPE_REMOTE_SLAVE;
- occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
- }
- GNUNET_CONTAINER_DLL_insert_tail (occq_head,
- occq_tail,
- occ);
- occ->client = client;
- occ->other_peer_id = p2;
- GST_peer_list[p1]->reference_cnt++;
- occ->peer = GST_peer_list[p1];
- occ->op_id = operation_id;
- GNUNET_assert (NULL == occ->timeout_task);
- occ->timeout_task =
- GNUNET_SCHEDULER_add_delayed (GST_timeout,
- &timeout_overlay_connect,
- occ);
- switch (occ->type)
- {
- case OCC_TYPE_REMOTE_LATERAL:
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Timeout while acquiring connection to peer %u's "
- "host: %u\n",
- occ->op_id,
- occ->other_peer_id,
- peer2_host_id);
- occ->p2ctx.remote.ncn
- = GST_neighbour_get_connection (p2n,
- &p2_controller_connect_cb,
- occ);
- break;
- case OCC_TYPE_REMOTE_SLAVE:
- p2_controller_connect_cb (occ,
- occ->p2ctx.remote.p2c);
- break;
- case OCC_TYPE_LOCAL:
- peer2 = GST_peer_list[occ->other_peer_id];
- peer2->reference_cnt++;
- GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
- &occ->other_peer_identity);
- GNUNET_asprintf (&occ->emsg,
- "0x%llx: Timeout while connecting to CORE of peer with "
- "id: %u",
- occ->op_id,
- occ->peer->id);
- occ->cgh_ch =
- GST_connection_pool_get_handle (occ->peer->id,
- occ->peer->details.local.cfg,
- GST_CONNECTIONPOOL_SERVICE_CORE,
- occ_cache_get_handle_core_cb, occ,
- &occ->other_peer_identity,
- &overlay_connect_notify, occ);
- break;
- }
- GNUNET_SERVICE_client_continue (client);
- }
- /**
- * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
- * with it
- *
- * @param rocc the RemoteOverlayConnectCtx
- */
- static void
- cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
- {
- LOG_DEBUG ("0x%llx: Cleaning up rocc\n",
- rocc->op_id);
- if (NULL != rocc->attempt_connect_task_id)
- GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
- if (NULL != rocc->timeout_rocc_task_id)
- GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
- if (NULL != rocc->ohh)
- GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
- if (NULL != rocc->tcc.csh)
- GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh);
- GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th);
- GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats);
- GNUNET_assert (rocc->peer->reference_cnt > 0);
- rocc->peer->reference_cnt--;
- if ((GNUNET_YES == rocc->peer->destroy_flag) &&
- (0 == rocc->peer->reference_cnt))
- GST_destroy_peer (rocc->peer);
- GNUNET_free_non_null (rocc->hello);
- GNUNET_CONTAINER_DLL_remove (roccq_head,
- roccq_tail,
- rocc);
- GNUNET_free (rocc);
- }
- /**
- * Task to timeout rocc and cleanit up
- *
- * @param cls the RemoteOverlayConnectCtx
- */
- static void
- timeout_rocc_task (void *cls)
- {
- struct RemoteOverlayConnectCtx *rocc = cls;
- GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
- rocc->timeout_rocc_task_id = NULL;
- LOG_DEBUG ("0x%llx: rocc timed out\n",
- rocc->op_id);
- cleanup_rocc (rocc);
- }
- /**
- * Function called to notify transport users that another
- * peer connected to us.
- *
- * @param cls the RemoteOverlayConnectContext
- * @param new_peer the peer that connected
- */
- static void
- cache_transport_peer_connect_notify (void *cls,
- const struct GNUNET_PeerIdentity *new_peer)
- {
- struct RemoteOverlayConnectCtx *rocc = cls;
- LOG_DEBUG ("0x%llx: Request Overlay connect notify\n",
- rocc->op_id);
- GNUNET_assert (0 ==
- memcmp (new_peer, &rocc->a_id,
- sizeof(struct GNUNET_PeerIdentity)));
- LOG_DEBUG ("0x%llx: Peer %s connected\n",
- rocc->op_id,
- GNUNET_i2s (&rocc->a_id));
- cleanup_rocc (rocc);
- }
- /**
- * Task to offer the HELLO message to the peer and ask it to connect to the peer
- * whose identity is in RemoteOverlayConnectCtx
- *
- * @param cls the RemoteOverlayConnectCtx
- */
- static void
- attempt_connect_task (void *cls);
- /**
- * Task that is run when hello has been sent If tc->reason =
- * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
- * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
- *
- * @param cls the overlay connect context
- */
- static void
- rocc_hello_sent_cb (void *cls)
- {
- struct RemoteOverlayConnectCtx *rocc = cls;
- rocc->ohh = NULL;
- GNUNET_assert (NULL == rocc->attempt_connect_task_id);
- LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n",
- rocc->op_id,
- GNUNET_i2s (&rocc->a_id),
- rocc->peer->id);
- rocc->tcc.cgh_p2_ats =
- GST_connection_pool_get_handle (rocc->peer->id,
- rocc->peer->details.local.cfg,
- GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
- &occ_cache_get_handle_ats_rocc_cb,
- rocc, NULL, NULL, NULL);
- }
- /**
- * Task to offer the HELLO message to the peer and ask it to connect to the peer
- * whose identity is in RemoteOverlayConnectCtx
- *
- * @param cls the RemoteOverlayConnectCtx
- */
- static void
- attempt_connect_task (void *cls)
- {
- struct RemoteOverlayConnectCtx *rocc = cls;
- GNUNET_assert (NULL != rocc->attempt_connect_task_id);
- rocc->attempt_connect_task_id = NULL;
- LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n",
- rocc->op_id,
- GNUNET_i2s (&rocc->a_id),
- rocc->peer->id);
- rocc->ohh =
- GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg,
- rocc->hello,
- &rocc_hello_sent_cb,
- rocc);
- if (NULL == rocc->ohh)
- rocc->attempt_connect_task_id =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_MILLISECONDS,
- 100
- + GNUNET_CRYPTO_random_u32
- (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
- &attempt_connect_task, rocc);
- }
- /**
- * Callback from cache with needed handles set
- *
- * @param cls the closure passed to GST_cache_get_handle_transport()
- * @param ch the handle to CORE. Can be NULL if it is not requested
- * @param th the handle to TRANSPORT. Can be NULL if it is not requested
- * @param ac the handle to ATS. Can be NULL if it is not requested
- * @param ignore_ peer identity which is ignored in this callback
- */
- static void
- rocc_cache_get_handle_transport_cb (void *cls,
- struct GNUNET_CORE_Handle *ch,
- struct GNUNET_TRANSPORT_CoreHandle *th,
- struct GNUNET_ATS_ConnectivityHandle *ac,
- const struct GNUNET_PeerIdentity *ignore_,
- const struct
- GNUNET_CONFIGURATION_Handle *cfg)
- {
- struct RemoteOverlayConnectCtx *rocc = cls;
- if (NULL == th)
- {
- rocc->timeout_rocc_task_id =
- GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
- return;
- }
- rocc->tcc.th_ = th;
- rocc->tcc.cfg = cfg;
- if (NULL !=
- GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_,
- &rocc->a_id))
- {
- LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n",
- rocc->op_id,
- GNUNET_i2s (&rocc->a_id),
- rocc->peer->id);
- cleanup_rocc (rocc);
- return;
- }
- rocc->attempt_connect_task_id =
- GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
- }
- /**
- * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
- *
- * @param cls identification of the client
- * @param msg the actual message
- * @return #GNUNET_OK if @a msg is well-formed
- */
- int
- check_remote_overlay_connect (void *cls,
- const struct
- GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
- {
- uint32_t peer_id;
- uint16_t msize;
- uint16_t hsize;
- msize = ntohs (msg->header.size);
- if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- hsize = ntohs (msg->hello->size);
- if ((sizeof(struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) !=
- msize)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- peer_id = ntohl (msg->peer);
- if ((peer_id >= GST_peer_list_size) ||
- (NULL == GST_peer_list[peer_id]))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
- }
- /**
- * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
- *
- * @param cls identification of the client
- * @param msg the actual message
- */
- void
- handle_remote_overlay_connect (void *cls,
- const struct
- GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
- {
- struct GNUNET_SERVICE_Client *client = cls;
- struct RemoteOverlayConnectCtx *rocc;
- struct Peer *peer;
- struct GNUNET_PeerIdentity pid;
- static char pid_str[16];
- uint32_t peer_id;
- uint16_t hsize;
- hsize = ntohs (msg->hello->size);
- peer_id = ntohl (msg->peer);
- peer = GST_peer_list[peer_id];
- if (GNUNET_YES == peer->is_remote)
- {
- struct GNUNET_MessageHeader *msg2;
- msg2 = GNUNET_copy_message (&msg->header);
- GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
- msg2);
- GNUNET_SERVICE_client_continue (client);
- return;
- }
- rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
- rocc->op_id = GNUNET_ntohll (msg->operation_id);
- GNUNET_CONTAINER_DLL_insert_tail (roccq_head,
- roccq_tail,
- rocc);
- rocc->a_id = msg->peer_identity;
- GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
- &pid);
- (void) GNUNET_strlcpy (pid_str,
- GNUNET_i2s (&pid),
- sizeof(pid_str));
- LOG_DEBUG (
- "0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n",
- rocc->op_id,
- pid_str,
- GNUNET_i2s (&rocc->a_id),
- hsize);
- rocc->peer = peer;
- rocc->peer->reference_cnt++;
- rocc->hello = GNUNET_malloc (hsize);
- GNUNET_memcpy (rocc->hello,
- msg->hello,
- hsize);
- rocc->tcc.cgh_p2_th =
- GST_connection_pool_get_handle (peer_id,
- rocc->peer->details.local.cfg,
- GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
- &rocc_cache_get_handle_transport_cb,
- rocc,
- &rocc->a_id,
- &cache_transport_peer_connect_notify,
- rocc);
- rocc->timeout_rocc_task_id =
- GNUNET_SCHEDULER_add_delayed (GST_timeout,
- &timeout_rocc_task,
- rocc);
- GNUNET_SERVICE_client_continue (client);
- }
- /**
- * Clears all pending overlay connect contexts in queue
- */
- void
- GST_free_occq ()
- {
- struct OverlayConnectContext *occ;
- while (NULL != (occ = occq_head))
- cleanup_occ (occ);
- }
- /**
- * Clears all pending remote overlay connect contexts in queue
- */
- void
- GST_free_roccq ()
- {
- struct RemoteOverlayConnectCtx *rocc;
- while (NULL != (rocc = roccq_head))
- cleanup_rocc (rocc);
- }
|