gnunet-service-testbed_oc.c 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2008--2016 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file testbed/gnunet-service-testbed_oc.c
  18. * @brief code for handling overlay connect operations
  19. * @author Sree Harsha Totakura
  20. */
  21. #include "gnunet-service-testbed.h"
  22. #include "gnunet-service-testbed_connectionpool.h"
  23. #include "gnunet_transport_hello_service.h"
  24. /**
  25. * Redefine LOG with a changed log component string
  26. */
  27. #ifdef LOG
  28. #undef LOG
  29. #endif
  30. #define LOG(kind,...) \
  31. GNUNET_log_from (kind, "testbed-OC", __VA_ARGS__)
  32. /**
  33. * Context information for requesting ATS to connect to a peer
  34. */
  35. struct ConnectivitySuggestContext
  36. {
  37. /**
  38. * The transport handle obtained from cache. Do NOT close/disconnect.
  39. */
  40. struct GNUNET_TRANSPORT_CoreHandle *th_;
  41. /**
  42. * Configuration of the peer from cache. Do not free!
  43. */
  44. const struct GNUNET_CONFIGURATION_Handle *cfg;
  45. /**
  46. * The GetCacheHandle for the peer2's transport handle
  47. * (used to offer the HELLO to the peer).
  48. */
  49. struct GST_ConnectionPool_GetHandle *cgh_p2_th;
  50. /**
  51. * The GetCacheHandle for the peer2's ATS handle.
  52. */
  53. struct GST_ConnectionPool_GetHandle *cgh_p2_ats;
  54. /**
  55. * The ATS handle for the connectivity suggestion.
  56. */
  57. struct GNUNET_ATS_ConnectivitySuggestHandle *csh;
  58. };
  59. /**
  60. * Types for context information we create for overlay connect requests
  61. */
  62. enum OverlayConnectContextType
  63. {
  64. /**
  65. * This type is used if the overlay connection is local i.e. the connection
  66. * has to be made between local peers
  67. */
  68. OCC_TYPE_LOCAL,
  69. /**
  70. * Type to be used when the first peer is local and the other peer is on a slave
  71. * controller started by us
  72. */
  73. OCC_TYPE_REMOTE_SLAVE,
  74. /**
  75. * Type to be used when the first peer is local and the other peer is on a
  76. * controller which is not started by us.
  77. */
  78. OCC_TYPE_REMOTE_LATERAL
  79. };
  80. /**
  81. * Context data for operations on second peer in local overlay connection
  82. * contexts
  83. */
  84. struct LocalPeer2Context
  85. {
  86. /**
  87. * The handle for offering the HELLO of the first peer to the second
  88. * peer.
  89. */
  90. struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
  91. /**
  92. * The transport ConnectivitySuggestContext
  93. */
  94. struct ConnectivitySuggestContext tcc;
  95. };
  96. /**
  97. * Context data for operations on second peer in remote overlay connection
  98. * contexts
  99. */
  100. struct RemotePeer2Context
  101. {
  102. /**
  103. * Controller of peer 2; If #OCC_TYPE_REMOTE_LATERAL is the type of overlay
  104. * connection then this can be NULL until the connection to the controller is
  105. * established
  106. */
  107. struct GNUNET_TESTBED_Controller *p2c;
  108. /**
  109. * Operation context for the suboperation we start to get the identity of the
  110. * second peer
  111. */
  112. struct OperationContext *opc;
  113. /**
  114. * Notification handle acquire to connect to a remote controller. Only used
  115. * if the type of overlay connection is #OCC_TYPE_REMOTE_LATERAL.
  116. */
  117. struct NeighbourConnectNotification *ncn;
  118. /**
  119. * The neighbour handle. Only used if the type of overlay connection is
  120. * #OCC_TYPE_REMOTE_LATERAL.
  121. */
  122. struct Neighbour *p2n;
  123. };
  124. /**
  125. * Context information for connecting 2 peers in overlay.
  126. */
  127. struct OverlayConnectContext
  128. {
  129. /**
  130. * The next pointer for maintaining a DLL of all OverlayConnectContexts
  131. */
  132. struct OverlayConnectContext *next;
  133. /**
  134. * The prev pointer for maintaining a DLL of all OverlayConnectContexts
  135. */
  136. struct OverlayConnectContext *prev;
  137. /**
  138. * The client which has requested for overlay connection. This is used to send
  139. * either a success of failure message
  140. */
  141. struct GNUNET_SERVICE_Client *client;
  142. /**
  143. * the first peer which is to expect an overlay connection from the second peer.
  144. */
  145. struct Peer *peer;
  146. /**
  147. * Transport handle of the first peer obtained from cache to get its HELLO. Do
  148. * NOT close/disconnect.
  149. */
  150. struct GNUNET_TRANSPORT_CoreHandle *p1th_;
  151. /**
  152. * The #GST_ConnectionPool_GetHandle for the peer1's transport handle
  153. */
  154. struct GST_ConnectionPool_GetHandle *cgh_p1th;
  155. /**
  156. * The #GST_ConnectionPool_GetHandle for registering callback to notify CORE
  157. * level peer connects and to get our identity.
  158. */
  159. struct GST_ConnectionPool_GetHandle *cgh_ch;
  160. /**
  161. * HELLO of the first peer. This should be sent to the second peer.
  162. */
  163. struct GNUNET_MessageHeader *hello;
  164. /**
  165. * Get GetHelloHandle to acquire a HELLO of the first peer
  166. */
  167. struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
  168. /**
  169. * The error message we send if this overlay connect operation has timed out
  170. */
  171. char *emsg;
  172. /**
  173. * Context information for operations on the second peer
  174. */
  175. union {
  176. /**
  177. * Context information to be used if the second peer is local
  178. */
  179. struct LocalPeer2Context local;
  180. /**
  181. * Context information to be used if the second peer is remote
  182. */
  183. struct RemotePeer2Context remote;
  184. } p2ctx;
  185. /**
  186. * The peer identity of the first peer
  187. */
  188. struct GNUNET_PeerIdentity peer_identity;
  189. /**
  190. * The peer identity of the other peer
  191. */
  192. struct GNUNET_PeerIdentity other_peer_identity;
  193. /**
  194. * The id of the operation responsible for creating this context
  195. */
  196. uint64_t op_id;
  197. /**
  198. * The id of the task for sending HELLO of peer 2 to peer 1 and ask peer 1 to
  199. * connect to peer 2
  200. */
  201. struct GNUNET_SCHEDULER_Task *send_hello_task;
  202. /**
  203. * The id of the overlay connect timeout task
  204. */
  205. struct GNUNET_SCHEDULER_Task *timeout_task;
  206. /**
  207. * The id of the cleanup task
  208. */
  209. struct GNUNET_SCHEDULER_Task *cleanup_task;
  210. /**
  211. * The type of this context information
  212. */
  213. enum OverlayConnectContextType type;
  214. /**
  215. * The id of the second peer which has to connect to the first peer
  216. */
  217. uint32_t other_peer_id;
  218. };
  219. /**
  220. * Context information for remote overlay connect operations. Remote overlay
  221. * connections are used when peers A and B reside on different hosts. In these
  222. * operations the host controller for peer B is asked by the host controller of
  223. * peer A to make peer B connect to peer A by sending the controller of peer B
  224. * the HELLO of peer A.
  225. */
  226. struct RemoteOverlayConnectCtx
  227. {
  228. /**
  229. * the next pointer for DLL
  230. */
  231. struct RemoteOverlayConnectCtx *next;
  232. /**
  233. * the prev pointer for DLL
  234. */
  235. struct RemoteOverlayConnectCtx *prev;
  236. /**
  237. * The peer handle of peer B
  238. */
  239. struct Peer *peer;
  240. /**
  241. * Peer A's HELLO
  242. */
  243. struct GNUNET_MessageHeader *hello;
  244. /**
  245. * The handle for offering HELLO
  246. */
  247. struct GNUNET_TRANSPORT_OfferHelloHandle *ohh;
  248. /**
  249. * The transport try connect context
  250. */
  251. struct ConnectivitySuggestContext tcc;
  252. /**
  253. * The peer identity of peer A
  254. */
  255. struct GNUNET_PeerIdentity a_id;
  256. /**
  257. * Task for offering HELLO of A to B and doing try_connect
  258. */
  259. struct GNUNET_SCHEDULER_Task *attempt_connect_task_id;
  260. /**
  261. * Task to timeout RequestOverlayConnect
  262. */
  263. struct GNUNET_SCHEDULER_Task *timeout_rocc_task_id;
  264. /**
  265. * The id of the operation responsible for creating this context
  266. */
  267. uint64_t op_id;
  268. };
  269. /**
  270. * DLL head for OverlayConnectContext DLL - to be used to clean up during shutdown
  271. */
  272. static struct OverlayConnectContext *occq_head;
  273. /**
  274. * DLL tail for OverlayConnectContext DLL
  275. */
  276. static struct OverlayConnectContext *occq_tail;
  277. /**
  278. * DLL head for RequectOverlayConnectContext DLL - to be used to clean up during
  279. * shutdown
  280. */
  281. static struct RemoteOverlayConnectCtx *roccq_head;
  282. /**
  283. * DLL tail for RequectOverlayConnectContext DLL
  284. */
  285. static struct RemoteOverlayConnectCtx *roccq_tail;
  286. /**
  287. * Cleans up ForwardedOverlayConnectContext
  288. *
  289. * @param focc the ForwardedOverlayConnectContext to cleanup
  290. */
  291. void
  292. GST_cleanup_focc (struct ForwardedOverlayConnectContext *focc)
  293. {
  294. struct RegisteredHostContext *rhc = focc->rhc;
  295. GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head,
  296. rhc->focc_dll_tail,
  297. focc);
  298. GNUNET_free_non_null (focc->orig_msg);
  299. GNUNET_free (focc);
  300. }
  301. /**
  302. * Timeout task for cancelling a forwarded overlay connect connect
  303. *
  304. * @param cls the `struct ForwardedOperationContext`
  305. */
  306. static void
  307. forwarded_overlay_connect_timeout (void *cls)
  308. {
  309. struct ForwardedOperationContext *fopc = cls;
  310. struct RegisteredHostContext *rhc;
  311. struct ForwardedOverlayConnectContext *focc;
  312. fopc->timeout_task = NULL;
  313. rhc = fopc->cls;
  314. focc = rhc->focc_dll_head;
  315. LOG_DEBUG ("Overlay linking between peers %u and %u failed\n",
  316. focc->peer1,
  317. focc->peer2);
  318. GST_cleanup_focc (focc);
  319. GST_forwarded_operation_timeout (fopc);
  320. if (NULL != rhc->focc_dll_head)
  321. GST_process_next_focc (rhc);
  322. }
  323. /**
  324. * Callback to be called when forwarded overlay connection operation has a reply
  325. * from the sub-controller successfull. We have to relay the reply msg back to
  326. * the client
  327. *
  328. * @param cls ForwardedOperationContext
  329. * @param msg the peer create success message
  330. */
  331. static void
  332. forwarded_overlay_connect_listener (void *cls,
  333. const struct GNUNET_MessageHeader *msg)
  334. {
  335. struct ForwardedOperationContext *fopc = cls;
  336. struct RegisteredHostContext *rhc;
  337. struct ForwardedOverlayConnectContext *focc;
  338. rhc = fopc->cls;
  339. GST_forwarded_operation_reply_relay (cls, msg);
  340. focc = rhc->focc_dll_head;
  341. GST_cleanup_focc (focc);
  342. if (NULL != rhc->focc_dll_head)
  343. GST_process_next_focc (rhc);
  344. }
  345. /**
  346. * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext
  347. *
  348. * @param rhc the RegisteredHostContext
  349. */
  350. void
  351. GST_process_next_focc (struct RegisteredHostContext *rhc)
  352. {
  353. struct ForwardedOperationContext *fopc;
  354. struct ForwardedOverlayConnectContext *focc;
  355. struct Peer *peer;
  356. struct Slave *slave;
  357. focc = rhc->focc_dll_head;
  358. GNUNET_assert (NULL != focc);
  359. GNUNET_assert (RHC_DONE == rhc->state);
  360. GNUNET_assert (VALID_PEER_ID (focc->peer1));
  361. peer = GST_peer_list[focc->peer1];
  362. GNUNET_assert (GNUNET_YES == peer->is_remote);
  363. GNUNET_assert (NULL != (slave = peer->details.remote.slave));
  364. fopc = GNUNET_new (struct ForwardedOperationContext);
  365. fopc->client = focc->client;
  366. fopc->operation_id = focc->operation_id;
  367. fopc->cls = rhc;
  368. fopc->type = OP_OVERLAY_CONNECT;
  369. fopc->opc =
  370. GNUNET_TESTBED_forward_operation_msg_ (slave->controller,
  371. focc->operation_id,
  372. focc->orig_msg,
  373. &forwarded_overlay_connect_listener,
  374. fopc);
  375. GNUNET_free (focc->orig_msg);
  376. focc->orig_msg = NULL;
  377. fopc->timeout_task = GNUNET_SCHEDULER_add_delayed (GST_timeout,
  378. &forwarded_overlay_connect_timeout,
  379. fopc);
  380. GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
  381. fopcq_tail,
  382. fopc);
  383. }
  384. /**
  385. * Cleans up any used handles in local peer2 context
  386. *
  387. * @param lp2c the local peer2 context information
  388. */
  389. static void
  390. cleanup_occ_lp2c (struct LocalPeer2Context *lp2c)
  391. {
  392. if (NULL != lp2c->ohh)
  393. {
  394. GNUNET_TRANSPORT_offer_hello_cancel (lp2c->ohh);
  395. lp2c->ohh = NULL;
  396. }
  397. if (NULL != lp2c->tcc.cgh_p2_th)
  398. {
  399. GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_th);
  400. lp2c->tcc.cgh_p2_th = NULL;
  401. }
  402. if (NULL != lp2c->tcc.cgh_p2_ats)
  403. {
  404. GST_connection_pool_get_handle_done (lp2c->tcc.cgh_p2_ats);
  405. lp2c->tcc.cgh_p2_ats = NULL;
  406. }
  407. if (NULL != lp2c->tcc.csh)
  408. {
  409. GNUNET_ATS_connectivity_suggest_cancel (lp2c->tcc.csh);
  410. lp2c->tcc.csh = NULL;
  411. }
  412. }
  413. /**
  414. * Cleans up any used handles in remote peer2 context. Relinquishes the
  415. * remote controller connection if it has been established on-demand.
  416. *
  417. * @param rp2c the remote peer2 context information
  418. */
  419. static void
  420. cleanup_occ_rp2c (struct RemotePeer2Context *rp2c)
  421. {
  422. if (NULL != rp2c->opc)
  423. {
  424. GNUNET_TESTBED_forward_operation_msg_cancel_ (rp2c->opc);
  425. rp2c->opc = NULL;
  426. }
  427. if (NULL != rp2c->ncn)
  428. {
  429. GST_neighbour_get_connection_cancel (rp2c->ncn);
  430. rp2c->ncn = NULL;
  431. }
  432. if ( (NULL != rp2c->p2c) && (NULL != rp2c->p2n) )
  433. {
  434. GST_neighbour_release_connection (rp2c->p2n);
  435. rp2c->p2n = NULL;
  436. }
  437. }
  438. /**
  439. * Condition for checking if given peer is ready to be destroyed
  440. *
  441. * @param peer the peer to check
  442. */
  443. #define PEER_EXPIRED(peer) \
  444. ( (GNUNET_YES == peer->destroy_flag) && (0 == peer->reference_cnt) )
  445. /**
  446. * Cleanup overlay connect context structure
  447. *
  448. * @param occ the overlay connect context
  449. */
  450. static void
  451. cleanup_occ (struct OverlayConnectContext *occ)
  452. {
  453. struct Peer *peer2;
  454. LOG_DEBUG ("0x%llx: Cleaning up occ\n",
  455. occ->op_id);
  456. GNUNET_free_non_null (occ->emsg);
  457. GNUNET_free_non_null (occ->hello);
  458. if (NULL != occ->send_hello_task)
  459. GNUNET_SCHEDULER_cancel (occ->send_hello_task);
  460. if (NULL != occ->cleanup_task)
  461. GNUNET_SCHEDULER_cancel (occ->cleanup_task);
  462. if (NULL != occ->timeout_task)
  463. GNUNET_SCHEDULER_cancel (occ->timeout_task);
  464. if (NULL != occ->cgh_ch)
  465. GST_connection_pool_get_handle_done (occ->cgh_ch);
  466. if (NULL != occ->ghh)
  467. GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
  468. GST_connection_pool_get_handle_done (occ->cgh_p1th);
  469. GNUNET_assert (NULL != GST_peer_list);
  470. GNUNET_assert (occ->peer->reference_cnt > 0);
  471. occ->peer->reference_cnt--;
  472. if (PEER_EXPIRED (occ->peer))
  473. GST_destroy_peer (occ->peer);
  474. switch (occ->type)
  475. {
  476. case OCC_TYPE_LOCAL:
  477. peer2 = GST_peer_list[occ->other_peer_id];
  478. GNUNET_assert (peer2->reference_cnt > 0);
  479. peer2->reference_cnt--;
  480. if (PEER_EXPIRED (peer2))
  481. GST_destroy_peer (peer2);
  482. cleanup_occ_lp2c (&occ->p2ctx.local);
  483. break;
  484. case OCC_TYPE_REMOTE_SLAVE:
  485. case OCC_TYPE_REMOTE_LATERAL:
  486. cleanup_occ_rp2c (&occ->p2ctx.remote);
  487. break;
  488. }
  489. GNUNET_CONTAINER_DLL_remove (occq_head,
  490. occq_tail,
  491. occ);
  492. GNUNET_free (occ);
  493. }
  494. /**
  495. * Task for cleaing up overlay connect context structure
  496. *
  497. * @param cls the overlay connect context
  498. */
  499. static void
  500. do_cleanup_occ (void *cls)
  501. {
  502. struct OverlayConnectContext *occ = cls;
  503. occ->cleanup_task = NULL;
  504. cleanup_occ (occ);
  505. }
  506. /**
  507. * Task which will be run when overlay connect request has been timed out
  508. *
  509. * @param cls the OverlayConnectContext
  510. */
  511. static void
  512. timeout_overlay_connect (void *cls)
  513. {
  514. struct OverlayConnectContext *occ = cls;
  515. GNUNET_assert (NULL != occ->timeout_task);
  516. occ->timeout_task = NULL;
  517. /* LOG (GNUNET_ERROR_TYPE_WARNING, */
  518. /* "0x%llx: Timeout while connecting peers %u and %u: %s\n", occ->op_id, */
  519. /* occ->peer->id, occ->other_peer_id, occ->emsg); */
  520. GST_send_operation_fail_msg (occ->client,
  521. occ->op_id,
  522. occ->emsg);
  523. cleanup_occ (occ);
  524. }
  525. /**
  526. * Notify OC subsystem that @a client disconnected.
  527. *
  528. * @param client the client that disconnected
  529. */
  530. void
  531. GST_notify_client_disconnect_oc (struct GNUNET_SERVICE_Client *client)
  532. {
  533. struct ForwardedOperationContext *fopc;
  534. struct ForwardedOperationContext *fopcn;
  535. struct OverlayConnectContext *occ;
  536. struct OverlayConnectContext *occn;
  537. for (fopc = fopcq_head; NULL != fopc; fopc = fopcn)
  538. {
  539. fopcn = fopc->next;
  540. if (fopc->client == client)
  541. {
  542. GNUNET_SCHEDULER_cancel (fopc->timeout_task);
  543. GST_forwarded_operation_timeout (fopc);
  544. }
  545. }
  546. for (occ = occq_head; NULL != occ; occ = occn)
  547. {
  548. occn = occ->next;
  549. if (occ->client == client)
  550. cleanup_occ (occ);
  551. }
  552. // FIXME: implement clean up for client_keep replacements!
  553. }
  554. /**
  555. * FIXME.
  556. */
  557. static void
  558. send_overlay_connect_success_msg (struct OverlayConnectContext *occ)
  559. {
  560. struct GNUNET_MQ_Envelope *env;
  561. struct GNUNET_TESTBED_ConnectionEventMessage *msg;
  562. LOG_DEBUG ("0x%llx: Peers connected - Sending overlay connect success\n",
  563. occ->op_id);
  564. env = GNUNET_MQ_msg (msg,
  565. GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT);
  566. msg->event_type = htonl (GNUNET_TESTBED_ET_CONNECT);
  567. msg->peer1 = htonl (occ->peer->id);
  568. msg->peer2 = htonl (occ->other_peer_id);
  569. msg->operation_id = GNUNET_htonll (occ->op_id);
  570. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (occ->client),
  571. env);
  572. }
  573. /**
  574. * Function called to notify transport users that another
  575. * peer connected to us.
  576. *
  577. * @param cls closure
  578. * @param new_peer the peer that connected
  579. */
  580. static void
  581. overlay_connect_notify (void *cls,
  582. const struct GNUNET_PeerIdentity *new_peer)
  583. {
  584. struct OverlayConnectContext *occ = cls;
  585. char *new_peer_str;
  586. char *other_peer_str;
  587. LOG_DEBUG ("Overlay connect notify\n");
  588. if (0 ==
  589. memcmp (new_peer, &occ->peer_identity,
  590. sizeof (struct GNUNET_PeerIdentity)))
  591. return;
  592. new_peer_str = GNUNET_strdup (GNUNET_i2s (new_peer));
  593. other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
  594. if (0 !=
  595. memcmp (new_peer,
  596. &occ->other_peer_identity,
  597. sizeof (struct GNUNET_PeerIdentity)))
  598. {
  599. LOG_DEBUG ("Unexpected peer %s connected when expecting peer %s\n",
  600. new_peer_str,
  601. other_peer_str);
  602. GNUNET_free (new_peer_str);
  603. GNUNET_free (other_peer_str);
  604. return;
  605. }
  606. GNUNET_free (new_peer_str);
  607. LOG_DEBUG ("0x%llx: Peer %s connected to peer %s\n",
  608. occ->op_id,
  609. other_peer_str,
  610. GNUNET_i2s (&occ->peer_identity));
  611. GNUNET_free (other_peer_str);
  612. if (NULL != occ->send_hello_task)
  613. {
  614. GNUNET_SCHEDULER_cancel (occ->send_hello_task);
  615. occ->send_hello_task = NULL;
  616. }
  617. GNUNET_assert (NULL != occ->timeout_task);
  618. GNUNET_SCHEDULER_cancel (occ->timeout_task);
  619. occ->timeout_task = NULL;
  620. switch (occ->type)
  621. {
  622. case OCC_TYPE_LOCAL:
  623. cleanup_occ_lp2c (&occ->p2ctx.local);
  624. break;
  625. case OCC_TYPE_REMOTE_SLAVE:
  626. case OCC_TYPE_REMOTE_LATERAL:
  627. cleanup_occ_rp2c (&occ->p2ctx.remote);
  628. break;
  629. }
  630. GNUNET_free_non_null (occ->emsg);
  631. occ->emsg = NULL;
  632. send_overlay_connect_success_msg (occ);
  633. occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ,
  634. occ);
  635. }
  636. /**
  637. * Callback from cache with needed ATS handle set
  638. *
  639. * @param cls a `struct OverlayConnectCtx *`
  640. * @param ch the handle to CORE. Can be NULL if it is not requested
  641. * @param th the handle to TRANSPORT. Can be NULL if it is not requested
  642. * @param ac the handle to ATS. Can be NULL if it is not requested
  643. * @param my_identity the identity of our peer
  644. * @param cfg configuration of the peer
  645. */
  646. static void
  647. occ_cache_get_handle_ats_occ_cb (void *cls,
  648. struct GNUNET_CORE_Handle *ch,
  649. struct GNUNET_TRANSPORT_CoreHandle *th,
  650. struct GNUNET_ATS_ConnectivityHandle *ac,
  651. const struct GNUNET_PeerIdentity *my_identity,
  652. const struct GNUNET_CONFIGURATION_Handle *cfg)
  653. {
  654. struct OverlayConnectContext *occ = cls;
  655. struct LocalPeer2Context *lp2c;
  656. GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
  657. GNUNET_assert (NULL != occ->timeout_task);
  658. GNUNET_free_non_null (occ->emsg);
  659. if (NULL == ac)
  660. {
  661. GNUNET_asprintf (&occ->emsg,
  662. "0x%llx: Failed to connect to ATS of peer with id: %u",
  663. occ->op_id,
  664. occ->peer->id);
  665. GNUNET_SCHEDULER_cancel (occ->timeout_task);
  666. occ->timeout_task =
  667. GNUNET_SCHEDULER_add_now (&timeout_overlay_connect,
  668. occ);
  669. return;
  670. }
  671. occ->emsg = NULL;
  672. GNUNET_asprintf (&occ->emsg,
  673. "0x%llx: Timeout during GNUNET_ATS_connectivity_suggest() at peer %s",
  674. occ->op_id,
  675. GNUNET_i2s (&occ->other_peer_identity));
  676. lp2c = &occ->p2ctx.local;
  677. lp2c->tcc.csh =
  678. GNUNET_ATS_connectivity_suggest (ac,
  679. &occ->peer_identity,
  680. 1);
  681. }
  682. /**
  683. * Callback from cache with needed ATS handle set
  684. *
  685. * @param cls a `struct RemoteOverlayConnectCtx *`
  686. * @param ch the handle to CORE. Can be NULL if it is not requested
  687. * @param th the handle to TRANSPORT. Can be NULL if it is not requested
  688. * @param ac the handle to ATS. Can be NULL if it is not requested
  689. * @param my_identity the identity of our peer
  690. */
  691. static void
  692. occ_cache_get_handle_ats_rocc_cb (void *cls,
  693. struct GNUNET_CORE_Handle *ch,
  694. struct GNUNET_TRANSPORT_CoreHandle *th,
  695. struct GNUNET_ATS_ConnectivityHandle *ac,
  696. const struct GNUNET_PeerIdentity *my_identity,
  697. const struct GNUNET_CONFIGURATION_Handle *cfg)
  698. {
  699. struct RemoteOverlayConnectCtx *rocc = cls;
  700. rocc->tcc.csh =
  701. GNUNET_ATS_connectivity_suggest (ac,
  702. &rocc->a_id,
  703. 1);
  704. }
  705. /**
  706. * Task to offer HELLO of peer 1 to peer 2 and try to make peer 2 to connect to
  707. * peer 1.
  708. *
  709. * @param cls the OverlayConnectContext
  710. */
  711. static void
  712. send_hello (void *cls);
  713. /**
  714. * Task that is run when hello has been sent If tc->reason =
  715. * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
  716. * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
  717. *
  718. * @param cls the overlay connect context
  719. */
  720. static void
  721. occ_hello_sent_cb (void *cls)
  722. {
  723. struct OverlayConnectContext *occ = cls;
  724. struct LocalPeer2Context *lp2c;
  725. struct Peer *peer2;
  726. GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
  727. GNUNET_assert (NULL != occ->timeout_task);
  728. lp2c = &occ->p2ctx.local;
  729. lp2c->ohh = NULL;
  730. GNUNET_assert (NULL == occ->send_hello_task);
  731. GNUNET_free_non_null (occ->emsg);
  732. GNUNET_asprintf (&occ->emsg,
  733. "0x%llx: Timeout while acquiring ATS of %s from cache",
  734. occ->op_id,
  735. GNUNET_i2s (&occ->other_peer_identity));
  736. GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
  737. lp2c->tcc.cgh_p2_ats =
  738. GST_connection_pool_get_handle (occ->other_peer_id,
  739. peer2->details.local.cfg,
  740. GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
  741. &occ_cache_get_handle_ats_occ_cb,
  742. occ, NULL, NULL, NULL);
  743. }
  744. /**
  745. * Sends the HELLO of peer1 to peer2's controller through remote overlay connect
  746. * request.
  747. *
  748. * @param occ the overlay connect context. Its type must be either
  749. * #OCC_TYPE_REMOTE_SLAVE or #OCC_TYPE_REMOTE_LATERAL
  750. */
  751. static void
  752. send_hello_thru_rocc (struct OverlayConnectContext *occ)
  753. {
  754. struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg;
  755. char *other_peer_str;
  756. uint16_t msize;
  757. uint16_t hello_size;
  758. GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
  759. GNUNET_assert (NULL != occ->hello);
  760. other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
  761. LOG_DEBUG ("0x%llx: Offering HELLO of %s (size: %u) to %s via Remote Overlay Request\n",
  762. occ->op_id,
  763. GNUNET_i2s (&occ->peer_identity),
  764. ntohs (occ->hello->size),
  765. other_peer_str);
  766. GNUNET_free (other_peer_str);
  767. hello_size = ntohs (occ->hello->size);
  768. msize = sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hello_size;
  769. msg = GNUNET_malloc (msize);
  770. msg->header.type =
  771. htons (GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT);
  772. msg->header.size = htons (msize);
  773. msg->peer = htonl (occ->other_peer_id);
  774. msg->operation_id = GNUNET_htonll (occ->op_id);
  775. msg->peer_identity = occ->peer_identity;
  776. GNUNET_memcpy (msg->hello,
  777. occ->hello,
  778. hello_size);
  779. GNUNET_TESTBED_queue_message_ (occ->p2ctx.remote.p2c,
  780. &msg->header);
  781. }
  782. /**
  783. * Task to offer HELLO of peer 1 to peer 2. If peer2 is local it is offered
  784. * using its TRANSPORT connection; if remote the HELLO is sent remotely by using
  785. * send_hello_thru_rocc()
  786. *
  787. * @param cls the OverlayConnectContext
  788. */
  789. static void
  790. send_hello (void *cls)
  791. {
  792. struct OverlayConnectContext *occ = cls;
  793. struct LocalPeer2Context *lp2c;
  794. char *other_peer_str;
  795. occ->send_hello_task = NULL;
  796. GNUNET_assert (NULL != occ->timeout_task);
  797. GNUNET_assert (NULL != occ->hello);
  798. if (OCC_TYPE_LOCAL != occ->type)
  799. {
  800. send_hello_thru_rocc (occ);
  801. return;
  802. }
  803. lp2c = &occ->p2ctx.local;
  804. other_peer_str = GNUNET_strdup (GNUNET_i2s (&occ->other_peer_identity));
  805. LOG_DEBUG ("0x%llx: Offering HELLO of %s to %s\n",
  806. occ->op_id,
  807. GNUNET_i2s (&occ->peer_identity),
  808. other_peer_str);
  809. GNUNET_free (other_peer_str);
  810. lp2c->ohh =
  811. GNUNET_TRANSPORT_offer_hello (lp2c->tcc.cfg,
  812. occ->hello,
  813. &occ_hello_sent_cb,
  814. occ);
  815. if (NULL == lp2c->ohh)
  816. {
  817. GNUNET_break (0);
  818. occ->send_hello_task =
  819. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
  820. (GNUNET_TIME_UNIT_MILLISECONDS,
  821. 100 +
  822. GNUNET_CRYPTO_random_u32
  823. (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
  824. &send_hello, occ);
  825. }
  826. }
  827. /**
  828. * Callback from cache with needed handles set
  829. *
  830. * @param cls the closure passed to GST_cache_get_handle_transport()
  831. * @param ch the handle to CORE. Can be NULL if it is not requested
  832. * @param th the handle to TRANSPORT. Can be NULL if it is not requested
  833. * @param ac the handle to ATS. Can be NULL if it is not requested
  834. * @param ignore_ peer identity which is ignored in this callback
  835. * @param cfg configuration of the peer
  836. */
  837. static void
  838. p2_transport_connect_cache_callback (void *cls,
  839. struct GNUNET_CORE_Handle *ch,
  840. struct GNUNET_TRANSPORT_CoreHandle *th,
  841. struct GNUNET_ATS_ConnectivityHandle *ac,
  842. const struct GNUNET_PeerIdentity *ignore_,
  843. const struct GNUNET_CONFIGURATION_Handle *cfg)
  844. {
  845. struct OverlayConnectContext *occ = cls;
  846. GNUNET_assert (OCC_TYPE_LOCAL == occ->type);
  847. if (NULL == th)
  848. {
  849. GNUNET_asprintf (&occ->emsg,
  850. "0x%llx: Cannot connect to TRANSPORT of %s",
  851. occ->op_id,
  852. GNUNET_i2s (&occ->other_peer_identity));
  853. GNUNET_SCHEDULER_cancel (occ->timeout_task);
  854. occ->timeout_task =
  855. GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
  856. return;
  857. }
  858. occ->p2ctx.local.tcc.th_ = th;
  859. occ->p2ctx.local.tcc.cfg = cfg;
  860. GNUNET_asprintf (&occ->emsg,
  861. "0x%llx: Timeout while offering HELLO to %s",
  862. occ->op_id,
  863. GNUNET_i2s (&occ->other_peer_identity));
  864. occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
  865. }
  866. /**
  867. * Connects to the transport of the other peer if it is a local peer and
  868. * schedules the send hello task
  869. *
  870. * @param occ the overlay connect context
  871. */
  872. static void
  873. p2_transport_connect (struct OverlayConnectContext *occ)
  874. {
  875. struct Peer *peer2;
  876. /* HUH? Why to *obtain* HELLO? Seems we use this to *SEND* the
  877. HELLO! */
  878. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  879. "Connecting to transport of peer %s to obtain HELLO\n",
  880. GNUNET_i2s (&occ->other_peer_identity));
  881. GNUNET_assert (NULL == occ->emsg);
  882. GNUNET_assert (NULL != occ->hello);
  883. GNUNET_assert (NULL == occ->ghh);
  884. GNUNET_assert (NULL == occ->p1th_);
  885. GNUNET_assert (NULL == occ->cgh_p1th);
  886. if (OCC_TYPE_LOCAL == occ->type)
  887. {
  888. GNUNET_assert (NULL != (peer2 = GST_peer_list[occ->other_peer_id]));
  889. occ->p2ctx.local.tcc.cgh_p2_th =
  890. GST_connection_pool_get_handle (occ->other_peer_id,
  891. peer2->details.local.cfg,
  892. GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
  893. &p2_transport_connect_cache_callback,
  894. occ, NULL, NULL, NULL);
  895. return;
  896. }
  897. GNUNET_asprintf (&occ->emsg,
  898. "0x%llx: Timeout while offering HELLO to %s",
  899. occ->op_id,
  900. GNUNET_i2s (&occ->other_peer_identity));
  901. occ->send_hello_task = GNUNET_SCHEDULER_add_now (&send_hello, occ);
  902. }
  903. /**
  904. * Test for checking whether HELLO message is empty
  905. *
  906. * @param cls empty flag to set
  907. * @param address the HELLO
  908. * @param expiration expiration of the HELLO
  909. * @return #GNUNET_OK
  910. */
  911. static int
  912. test_address (void *cls,
  913. const struct GNUNET_HELLO_Address *address,
  914. struct GNUNET_TIME_Absolute expiration)
  915. {
  916. int *empty = cls;
  917. *empty = GNUNET_NO;
  918. return GNUNET_OK;
  919. }
  920. /**
  921. * Function called whenever there is an update to the HELLO of peers in the
  922. * OverlayConnectClosure. If we have a valid HELLO, we connect to the peer 2's
  923. * transport and offer peer 1's HELLO and ask peer 2 to connect to peer 1
  924. *
  925. * @param cls closure
  926. * @param hello our updated HELLO
  927. */
  928. static void
  929. hello_update_cb (void *cls,
  930. const struct GNUNET_MessageHeader *hello)
  931. {
  932. struct OverlayConnectContext *occ = cls;
  933. int empty;
  934. uint16_t msize;
  935. msize = ntohs (hello->size);
  936. empty = GNUNET_YES;
  937. (void) GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *)
  938. hello, GNUNET_NO,
  939. &test_address,
  940. &empty);
  941. if (GNUNET_YES == empty)
  942. {
  943. LOG_DEBUG ("0x%llx: HELLO of %s is empty\n",
  944. occ->op_id,
  945. GNUNET_i2s (&occ->peer_identity));
  946. return;
  947. }
  948. LOG_DEBUG ("0x%llx: Received HELLO of %s\n",
  949. occ->op_id,
  950. GNUNET_i2s (&occ->peer_identity));
  951. occ->hello = GNUNET_malloc (msize);
  952. GST_cache_add_hello (occ->peer->id, hello);
  953. GNUNET_memcpy (occ->hello, hello, msize);
  954. GNUNET_TRANSPORT_hello_get_cancel (occ->ghh);
  955. occ->ghh = NULL;
  956. GST_connection_pool_get_handle_done (occ->cgh_p1th);
  957. occ->cgh_p1th = NULL;
  958. occ->p1th_ = NULL;
  959. GNUNET_free_non_null (occ->emsg);
  960. occ->emsg = NULL;
  961. p2_transport_connect (occ);
  962. }
  963. /**
  964. * Callback from cache with needed handles set
  965. *
  966. * @param cls the closure passed to GST_cache_get_handle_transport()
  967. * @param ch the handle to CORE. Can be NULL if it is not requested
  968. * @param th the handle to TRANSPORT. Can be NULL if it is not requested
  969. * @param ac the handle to ATS. Can be NULL if it is not requested
  970. * @param ignore_ peer identity which is ignored in this callback
  971. */
  972. static void
  973. p1_transport_connect_cache_callback (void *cls,
  974. struct GNUNET_CORE_Handle *ch,
  975. struct GNUNET_TRANSPORT_CoreHandle *th,
  976. struct GNUNET_ATS_ConnectivityHandle *ac,
  977. const struct GNUNET_PeerIdentity *ignore_,
  978. const struct GNUNET_CONFIGURATION_Handle *cfg)
  979. {
  980. struct OverlayConnectContext *occ = cls;
  981. GNUNET_free_non_null (occ->emsg);
  982. occ->emsg = NULL;
  983. if (NULL == th)
  984. {
  985. GNUNET_asprintf (&occ->emsg,
  986. "0x%llx: Cannot connect to TRANSPORT of %s",
  987. occ->op_id,
  988. GNUNET_i2s (&occ->peer_identity));
  989. GNUNET_SCHEDULER_cancel (occ->timeout_task);
  990. occ->timeout_task =
  991. GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
  992. return;
  993. }
  994. GNUNET_assert (NULL == occ->p1th_);
  995. GNUNET_assert (NULL != occ->cgh_p1th);
  996. occ->p1th_ = th;
  997. GNUNET_asprintf (&occ->emsg,
  998. "0x%llx: Timeout while acquiring HELLO of peer %s",
  999. occ->op_id,
  1000. GNUNET_i2s (&occ->peer_identity));
  1001. occ->ghh = GNUNET_TRANSPORT_hello_get (cfg,
  1002. GNUNET_TRANSPORT_AC_ANY,
  1003. &hello_update_cb,
  1004. occ);
  1005. }
  1006. /**
  1007. * Callback from cache with needed CORE handle set
  1008. *
  1009. * @param cls the closure passed to GST_cache_get_handle_transport()
  1010. * @param ch the handle to CORE. Can be NULL if it is not requested
  1011. * @param th the handle to TRANSPORT. Can be NULL if it is not requested
  1012. * @param ac the handle to ATS. Can be NULL if it is not requested
  1013. * @param my_identity the identity of our peer
  1014. */
  1015. static void
  1016. occ_cache_get_handle_core_cb (void *cls,
  1017. struct GNUNET_CORE_Handle *ch,
  1018. struct GNUNET_TRANSPORT_CoreHandle *th,
  1019. struct GNUNET_ATS_ConnectivityHandle *ac,
  1020. const struct GNUNET_PeerIdentity *my_identity,
  1021. const struct GNUNET_CONFIGURATION_Handle *cfg)
  1022. {
  1023. struct OverlayConnectContext *occ = cls;
  1024. const struct GNUNET_MessageHeader *hello;
  1025. GNUNET_assert (NULL != occ->timeout_task);
  1026. GNUNET_free_non_null (occ->emsg);
  1027. if ((NULL == ch) || (NULL == my_identity))
  1028. {
  1029. GNUNET_asprintf (&occ->emsg,
  1030. "0x%llx: Failed to connect to CORE of peer with "
  1031. "id: %u",
  1032. occ->op_id,
  1033. occ->peer->id);
  1034. GNUNET_SCHEDULER_cancel (occ->timeout_task);
  1035. occ->timeout_task =
  1036. GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
  1037. return;
  1038. }
  1039. occ->emsg = NULL;
  1040. if (NULL !=
  1041. GNUNET_CORE_get_mq (ch,
  1042. &occ->other_peer_identity))
  1043. {
  1044. LOG_DEBUG ("0x%llx: Target peer already connected\n",
  1045. occ->op_id);
  1046. GNUNET_SCHEDULER_cancel (occ->timeout_task);
  1047. occ->timeout_task = NULL;
  1048. send_overlay_connect_success_msg (occ);
  1049. occ->cleanup_task = GNUNET_SCHEDULER_add_now (&do_cleanup_occ, occ);
  1050. return;
  1051. }
  1052. occ->peer_identity = *my_identity;
  1053. LOG_DEBUG ("0x%llx: Acquiring HELLO of peer %s\n",
  1054. occ->op_id,
  1055. GNUNET_i2s (&occ->peer_identity));
  1056. /* Lookup for HELLO in hello cache */
  1057. if (NULL != (hello = GST_cache_lookup_hello (occ->peer->id)))
  1058. {
  1059. LOG_DEBUG ("0x%llx: HELLO of peer %s found in cache\n",
  1060. occ->op_id,
  1061. GNUNET_i2s (&occ->peer_identity));
  1062. occ->hello = GNUNET_copy_message (hello);
  1063. p2_transport_connect (occ);
  1064. return;
  1065. }
  1066. GNUNET_asprintf (&occ->emsg,
  1067. "0x%llx: Timeout while acquiring TRANSPORT of %s from cache",
  1068. occ->op_id,
  1069. GNUNET_i2s (&occ->peer_identity));
  1070. occ->cgh_p1th =
  1071. GST_connection_pool_get_handle (occ->peer->id,
  1072. occ->peer->details.local.cfg,
  1073. GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
  1074. p1_transport_connect_cache_callback,
  1075. occ,
  1076. NULL, NULL, NULL);
  1077. }
  1078. /**
  1079. * Callback to be called when forwarded get peer config operation as part of
  1080. * overlay connect is successfull. Connection to Peer 1's core is made and is
  1081. * checked for new connection from peer 2
  1082. *
  1083. * @param cls ForwardedOperationContext
  1084. * @param msg the peer create success message
  1085. */
  1086. static void
  1087. overlay_connect_get_config (void *cls,
  1088. const struct GNUNET_MessageHeader *msg)
  1089. {
  1090. struct OverlayConnectContext *occ = cls;
  1091. struct RemotePeer2Context *rp2c;
  1092. const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *cmsg;
  1093. GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
  1094. rp2c = &occ->p2ctx.remote;
  1095. rp2c->opc = NULL;
  1096. GNUNET_assert (NULL != occ->timeout_task);
  1097. if (GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION != ntohs (msg->type))
  1098. {
  1099. GNUNET_SCHEDULER_cancel (occ->timeout_task);
  1100. occ->timeout_task =
  1101. GNUNET_SCHEDULER_add_now (&timeout_overlay_connect, occ);
  1102. }
  1103. cmsg =
  1104. (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
  1105. occ->other_peer_identity = cmsg->peer_identity;
  1106. GNUNET_free_non_null (occ->emsg);
  1107. GNUNET_asprintf (&occ->emsg,
  1108. "0x%llx: Timeout while connecting to CORE of peer with "
  1109. "id: %u",
  1110. occ->op_id,
  1111. occ->peer->id);
  1112. occ->cgh_ch =
  1113. GST_connection_pool_get_handle (occ->peer->id,
  1114. occ->peer->details.local.cfg,
  1115. GST_CONNECTIONPOOL_SERVICE_CORE,
  1116. occ_cache_get_handle_core_cb,
  1117. occ,
  1118. &occ->other_peer_identity,
  1119. &overlay_connect_notify,
  1120. occ);
  1121. return;
  1122. }
  1123. /**
  1124. * Callback which will be called after a host registration succeeded or failed
  1125. *
  1126. * @param cls the RegisteredHostContext
  1127. * @param emsg the error message; NULL if host registration is successful
  1128. */
  1129. static void
  1130. host_registration_comp (void *cls, const char *emsg)
  1131. {
  1132. struct RegisteredHostContext *rhc = cls;
  1133. rhc->state = RHC_DONE;
  1134. GST_process_next_focc (rhc);
  1135. }
  1136. /**
  1137. * Iterator to match a registered host context
  1138. *
  1139. * @param cls pointer 2 pointer of RegisteredHostContext
  1140. * @param key current key code
  1141. * @param value value in the hash map
  1142. * @return #GNUNET_YES if we should continue to
  1143. * iterate,
  1144. * #GNUNET_NO if not.
  1145. */
  1146. static int
  1147. reghost_match_iterator (void *cls,
  1148. const struct GNUNET_HashCode *key,
  1149. void *value)
  1150. {
  1151. struct RegisteredHostContext **rh = cls;
  1152. struct RegisteredHostContext *rh_val = value;
  1153. if ((rh_val->host == (*rh)->host) && (rh_val->reg_host == (*rh)->reg_host))
  1154. {
  1155. GNUNET_free (*rh);
  1156. *rh = rh_val;
  1157. return GNUNET_NO;
  1158. }
  1159. return GNUNET_YES;
  1160. }
  1161. /**
  1162. * Function to generate the hashcode corresponding to a RegisteredHostContext
  1163. *
  1164. * @param reg_host the host which is being registered in RegisteredHostContext
  1165. * @param host the host of the controller which has to connect to the above rhost
  1166. * @return the hashcode
  1167. */
  1168. static struct GNUNET_HashCode
  1169. hash_hosts (struct GNUNET_TESTBED_Host *reg_host,
  1170. struct GNUNET_TESTBED_Host *host)
  1171. {
  1172. struct GNUNET_HashCode hash;
  1173. uint32_t host_ids[2];
  1174. host_ids[0] = GNUNET_TESTBED_host_get_id_ (reg_host);
  1175. host_ids[1] = GNUNET_TESTBED_host_get_id_ (host);
  1176. GNUNET_CRYPTO_hash (host_ids, sizeof (host_ids), &hash);
  1177. return hash;
  1178. }
  1179. /**
  1180. * Checks if the given host is registered at the given slave.
  1181. *
  1182. * @param slave the slave where registration has to be checked. The check is
  1183. * actually done through a locally maintained hashmap. No
  1184. * communication with the slave is involved.
  1185. * @param host the host to register
  1186. * @return If the given host is not registered already or the registration is
  1187. * pending, it returns the registration context. Any overlay connects
  1188. * to be forwarded should be queued in the context so that they can be
  1189. * executed when the registration is completed. If the given host is
  1190. * already registered, NULL is returned.
  1191. */
  1192. static struct RegisteredHostContext *
  1193. register_host (struct Slave *slave,
  1194. struct GNUNET_TESTBED_Host *host)
  1195. {
  1196. struct GNUNET_HashCode hash;
  1197. struct RegisteredHostContext *rhc;
  1198. rhc = GNUNET_new (struct RegisteredHostContext);
  1199. rhc->reg_host = host;
  1200. rhc->host = GST_host_list[slave->host_id];
  1201. GNUNET_assert (NULL != rhc->reg_host);
  1202. GNUNET_assert (NULL != rhc->host);
  1203. rhc->state = RHC_INIT;
  1204. hash = hash_hosts (rhc->reg_host, rhc->host);
  1205. if ((GNUNET_NO ==
  1206. GNUNET_CONTAINER_multihashmap_contains (slave->reghost_map,
  1207. &hash)) ||
  1208. (GNUNET_SYSERR !=
  1209. GNUNET_CONTAINER_multihashmap_get_multiple (slave->reghost_map,
  1210. &hash,
  1211. reghost_match_iterator,
  1212. &rhc)))
  1213. {
  1214. /* create and add a new registerd host context */
  1215. /* add the focc to its queue */
  1216. GNUNET_CONTAINER_multihashmap_put (slave->reghost_map,
  1217. &hash,
  1218. rhc,
  1219. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  1220. GST_queue_host_registration (slave,
  1221. host_registration_comp,
  1222. rhc,
  1223. rhc->reg_host);
  1224. }
  1225. else
  1226. {
  1227. /* rhc is now set to the existing one from the hash map by
  1228. * reghost_match_iterator() */
  1229. /* if queue is empty then ignore creating focc and proceed with normal
  1230. * forwarding */
  1231. if (RHC_DONE == rhc->state)
  1232. return NULL;
  1233. }
  1234. return rhc;
  1235. }
  1236. /**
  1237. * Forwards the overlay connect request to a slave controller. Before
  1238. * forwarding, any hosts which are needed to be known by the slave controller to
  1239. * execute the overlay connect request are registered at slave.
  1240. *
  1241. * @param msg the overlay connect request message to be forwarded
  1242. * @param client the client to which the status of the forwarded request has to
  1243. * be notified
  1244. */
  1245. static void
  1246. forward_overlay_connect (const struct GNUNET_TESTBED_OverlayConnectMessage *msg,
  1247. struct GNUNET_SERVICE_Client *client)
  1248. {
  1249. struct ForwardedOperationContext *fopc;
  1250. struct Route *route_to_peer2_host;
  1251. struct Route *route_to_peer1_host;
  1252. struct Peer *peer;
  1253. struct RegisteredHostContext *rhc;
  1254. struct ForwardedOverlayConnectContext *focc;
  1255. uint64_t op_id;
  1256. uint32_t peer2_host_id;
  1257. uint32_t p1;
  1258. uint32_t p2;
  1259. p1 = ntohl (msg->peer1);
  1260. p2 = ntohl (msg->peer2);
  1261. op_id = GNUNET_ntohll (msg->operation_id);
  1262. peer2_host_id = ntohl (msg->peer2_host_id);
  1263. GNUNET_assert (VALID_PEER_ID (p1));
  1264. GNUNET_assert (VALID_HOST_ID (peer2_host_id));
  1265. peer = GST_peer_list[p1];
  1266. GNUNET_assert (GNUNET_YES == peer->is_remote);
  1267. LOG_DEBUG ("0x%llx: Forwarding overlay connect\n", op_id);
  1268. route_to_peer2_host = GST_find_dest_route (peer2_host_id);
  1269. route_to_peer1_host = GST_find_dest_route
  1270. (peer->details.remote.remote_host_id);
  1271. GNUNET_assert (NULL != route_to_peer1_host);
  1272. if ((NULL != route_to_peer2_host) &&
  1273. (route_to_peer1_host->dest == route_to_peer2_host->dest))
  1274. goto forward;
  1275. /* Peer2 is either with us OR peer1 and peer2 can be reached through
  1276. different subtrees OR peer2 is on a subtree unknown to us */
  1277. if (NULL != (rhc = register_host (peer->details.remote.slave,
  1278. GST_host_list[peer2_host_id])))
  1279. {
  1280. LOG_DEBUG ("Queueing forwarding FOCC for connecting peers %u and %u\n", p1, p2);
  1281. focc = GNUNET_new (struct ForwardedOverlayConnectContext);
  1282. focc->rhc = rhc;
  1283. focc->peer1 = p1;
  1284. focc->peer2 = p2;
  1285. focc->peer2_host_id = peer2_host_id;
  1286. focc->orig_msg = GNUNET_copy_message (&msg->header);
  1287. focc->operation_id = op_id;
  1288. focc->client = client;
  1289. GNUNET_CONTAINER_DLL_insert_tail (rhc->focc_dll_head,
  1290. rhc->focc_dll_tail,
  1291. focc);
  1292. return;
  1293. }
  1294. forward:
  1295. LOG_DEBUG ("Forwarding without FOCC for connecting peers %u and %u\n", p1, p2);
  1296. fopc = GNUNET_new (struct ForwardedOperationContext);
  1297. fopc->client = client;
  1298. fopc->operation_id = op_id;
  1299. fopc->type = OP_OVERLAY_CONNECT;
  1300. fopc->opc =
  1301. GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
  1302. slave->controller, op_id,
  1303. &msg->header,
  1304. &GST_forwarded_operation_reply_relay,
  1305. fopc);
  1306. fopc->timeout_task =
  1307. GNUNET_SCHEDULER_add_delayed (GST_timeout,
  1308. &GST_forwarded_operation_timeout,
  1309. fopc);
  1310. GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
  1311. fopcq_tail,
  1312. fopc);
  1313. }
  1314. /**
  1315. * Callback called when a connection to the controller of peer2 has been
  1316. * established
  1317. *
  1318. * @param cls the overlay connect contexts
  1319. * @param c handle to the controller connection
  1320. */
  1321. static void
  1322. p2_controller_connect_cb (void *cls,
  1323. struct GNUNET_TESTBED_Controller *c)
  1324. {
  1325. struct OverlayConnectContext *occ = cls;
  1326. struct RemotePeer2Context *rp2c;
  1327. struct GNUNET_TESTBED_PeerGetConfigurationMessage cmsg;
  1328. GNUNET_assert (OCC_TYPE_LOCAL != occ->type);
  1329. rp2c = &occ->p2ctx.remote;
  1330. rp2c->ncn = NULL;
  1331. rp2c->p2c = c;
  1332. cmsg.header.size =
  1333. htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
  1334. cmsg.header.type =
  1335. htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
  1336. cmsg.peer_id = htonl (occ->other_peer_id);
  1337. cmsg.operation_id = GNUNET_htonll (occ->op_id);
  1338. rp2c->opc =
  1339. GNUNET_TESTBED_forward_operation_msg_ (rp2c->p2c,
  1340. occ->op_id,
  1341. &cmsg.header,
  1342. &overlay_connect_get_config,
  1343. occ);
  1344. GNUNET_free_non_null (occ->emsg);
  1345. GNUNET_asprintf (&occ->emsg,
  1346. "0x%llx: Timeout while getting peer identity of peer "
  1347. "with id: %u",
  1348. occ->op_id,
  1349. occ->other_peer_id);
  1350. }
  1351. /**
  1352. * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT messages
  1353. *
  1354. * @param cls identification of the client
  1355. * @param msg the actual message
  1356. */
  1357. void
  1358. handle_overlay_connect (void *cls,
  1359. const struct GNUNET_TESTBED_OverlayConnectMessage *msg)
  1360. {
  1361. struct GNUNET_SERVICE_Client *client = cls;
  1362. struct Peer *peer;
  1363. struct Peer *peer2;
  1364. struct OverlayConnectContext *occ;
  1365. struct Neighbour *p2n;
  1366. uint64_t operation_id;
  1367. uint32_t p1;
  1368. uint32_t p2;
  1369. uint32_t peer2_host_id;
  1370. p1 = ntohl (msg->peer1);
  1371. p2 = ntohl (msg->peer2);
  1372. if (! VALID_PEER_ID (p1))
  1373. {
  1374. GNUNET_break (0);
  1375. GNUNET_SERVICE_client_drop (client);
  1376. return;
  1377. }
  1378. peer = GST_peer_list[p1];
  1379. operation_id = GNUNET_ntohll (msg->operation_id);
  1380. LOG_DEBUG
  1381. ("Received overlay connect for peers %u and %u with op id: 0x%llx\n",
  1382. p1,
  1383. p2,
  1384. operation_id);
  1385. peer2_host_id = ntohl (msg->peer2_host_id);
  1386. if (GNUNET_YES == peer->is_remote)
  1387. {
  1388. if (! VALID_HOST_ID (peer2_host_id))
  1389. {
  1390. GNUNET_break (0);
  1391. GNUNET_SERVICE_client_drop (client);
  1392. return;
  1393. }
  1394. forward_overlay_connect (msg, client);
  1395. GNUNET_SERVICE_client_continue (client);
  1396. return;
  1397. }
  1398. p2n = NULL;
  1399. occ = GNUNET_new (struct OverlayConnectContext);
  1400. occ->type = OCC_TYPE_LOCAL;
  1401. if (! VALID_PEER_ID (p2)) /* May be peer2 is on a another controller */
  1402. {
  1403. if (NULL == (p2n = GST_get_neighbour (peer2_host_id)))
  1404. {
  1405. if (! VALID_HOST_ID (peer2_host_id))
  1406. {
  1407. GNUNET_break (0);
  1408. LOG (GNUNET_ERROR_TYPE_WARNING,
  1409. "0x%llx: Peer %u's host not in our neighbours list\n",
  1410. operation_id, p2);
  1411. GNUNET_SERVICE_client_drop (client);
  1412. GNUNET_free (occ);
  1413. return;
  1414. }
  1415. p2n = GST_create_neighbour (GST_host_list[peer2_host_id]);
  1416. }
  1417. occ->type = OCC_TYPE_REMOTE_LATERAL;
  1418. occ->p2ctx.remote.p2n = p2n;
  1419. }
  1420. else if (GNUNET_YES == GST_peer_list[p2]->is_remote)
  1421. {
  1422. occ->type = OCC_TYPE_REMOTE_SLAVE;
  1423. occ->p2ctx.remote.p2c = GST_peer_list[p2]->details.remote.slave->controller;
  1424. }
  1425. GNUNET_CONTAINER_DLL_insert_tail (occq_head,
  1426. occq_tail,
  1427. occ);
  1428. occ->client = client;
  1429. occ->other_peer_id = p2;
  1430. GST_peer_list[p1]->reference_cnt++;
  1431. occ->peer = GST_peer_list[p1];
  1432. occ->op_id = operation_id;
  1433. GNUNET_assert (NULL == occ->timeout_task);
  1434. occ->timeout_task =
  1435. GNUNET_SCHEDULER_add_delayed (GST_timeout,
  1436. &timeout_overlay_connect,
  1437. occ);
  1438. switch (occ->type)
  1439. {
  1440. case OCC_TYPE_REMOTE_LATERAL:
  1441. GNUNET_asprintf (&occ->emsg,
  1442. "0x%llx: Timeout while acquiring connection to peer %u's "
  1443. "host: %u\n",
  1444. occ->op_id,
  1445. occ->other_peer_id,
  1446. peer2_host_id);
  1447. occ->p2ctx.remote.ncn
  1448. = GST_neighbour_get_connection (p2n,
  1449. &p2_controller_connect_cb,
  1450. occ);
  1451. break;
  1452. case OCC_TYPE_REMOTE_SLAVE:
  1453. p2_controller_connect_cb (occ,
  1454. occ->p2ctx.remote.p2c);
  1455. break;
  1456. case OCC_TYPE_LOCAL:
  1457. peer2 = GST_peer_list[occ->other_peer_id];
  1458. peer2->reference_cnt++;
  1459. GNUNET_TESTING_peer_get_identity (peer2->details.local.peer,
  1460. &occ->other_peer_identity);
  1461. GNUNET_asprintf (&occ->emsg,
  1462. "0x%llx: Timeout while connecting to CORE of peer with "
  1463. "id: %u",
  1464. occ->op_id,
  1465. occ->peer->id);
  1466. occ->cgh_ch =
  1467. GST_connection_pool_get_handle (occ->peer->id,
  1468. occ->peer->details.local.cfg,
  1469. GST_CONNECTIONPOOL_SERVICE_CORE,
  1470. occ_cache_get_handle_core_cb, occ,
  1471. &occ->other_peer_identity,
  1472. &overlay_connect_notify, occ);
  1473. break;
  1474. }
  1475. GNUNET_SERVICE_client_continue (client);
  1476. }
  1477. /**
  1478. * Function to cleanup RemoteOverlayConnectCtx and any associated tasks
  1479. * with it
  1480. *
  1481. * @param rocc the RemoteOverlayConnectCtx
  1482. */
  1483. static void
  1484. cleanup_rocc (struct RemoteOverlayConnectCtx *rocc)
  1485. {
  1486. LOG_DEBUG ("0x%llx: Cleaning up rocc\n",
  1487. rocc->op_id);
  1488. if (NULL != rocc->attempt_connect_task_id)
  1489. GNUNET_SCHEDULER_cancel (rocc->attempt_connect_task_id);
  1490. if (NULL != rocc->timeout_rocc_task_id)
  1491. GNUNET_SCHEDULER_cancel (rocc->timeout_rocc_task_id);
  1492. if (NULL != rocc->ohh)
  1493. GNUNET_TRANSPORT_offer_hello_cancel (rocc->ohh);
  1494. if (NULL != rocc->tcc.csh)
  1495. GNUNET_ATS_connectivity_suggest_cancel (rocc->tcc.csh);
  1496. GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_th);
  1497. GST_connection_pool_get_handle_done (rocc->tcc.cgh_p2_ats);
  1498. GNUNET_assert (rocc->peer->reference_cnt > 0);
  1499. rocc->peer->reference_cnt--;
  1500. if ((GNUNET_YES == rocc->peer->destroy_flag) &&
  1501. (0 == rocc->peer->reference_cnt))
  1502. GST_destroy_peer (rocc->peer);
  1503. GNUNET_free_non_null (rocc->hello);
  1504. GNUNET_CONTAINER_DLL_remove (roccq_head,
  1505. roccq_tail,
  1506. rocc);
  1507. GNUNET_free (rocc);
  1508. }
  1509. /**
  1510. * Task to timeout rocc and cleanit up
  1511. *
  1512. * @param cls the RemoteOverlayConnectCtx
  1513. */
  1514. static void
  1515. timeout_rocc_task (void *cls)
  1516. {
  1517. struct RemoteOverlayConnectCtx *rocc = cls;
  1518. GNUNET_assert (rocc->timeout_rocc_task_id != NULL);
  1519. rocc->timeout_rocc_task_id = NULL;
  1520. LOG_DEBUG ("0x%llx: rocc timed out\n",
  1521. rocc->op_id);
  1522. cleanup_rocc (rocc);
  1523. }
  1524. /**
  1525. * Function called to notify transport users that another
  1526. * peer connected to us.
  1527. *
  1528. * @param cls the RemoteOverlayConnectContext
  1529. * @param new_peer the peer that connected
  1530. */
  1531. static void
  1532. cache_transport_peer_connect_notify (void *cls,
  1533. const struct GNUNET_PeerIdentity *new_peer)
  1534. {
  1535. struct RemoteOverlayConnectCtx *rocc = cls;
  1536. LOG_DEBUG ("0x%llx: Request Overlay connect notify\n",
  1537. rocc->op_id);
  1538. GNUNET_assert (0 ==
  1539. memcmp (new_peer, &rocc->a_id,
  1540. sizeof (struct GNUNET_PeerIdentity)));
  1541. LOG_DEBUG ("0x%llx: Peer %s connected\n",
  1542. rocc->op_id,
  1543. GNUNET_i2s (&rocc->a_id));
  1544. cleanup_rocc (rocc);
  1545. }
  1546. /**
  1547. * Task to offer the HELLO message to the peer and ask it to connect to the peer
  1548. * whose identity is in RemoteOverlayConnectCtx
  1549. *
  1550. * @param cls the RemoteOverlayConnectCtx
  1551. */
  1552. static void
  1553. attempt_connect_task (void *cls);
  1554. /**
  1555. * Task that is run when hello has been sent If tc->reason =
  1556. * #GNUNET_SCHEDULER_REASON_TIMEOUT then sending HELLO failed; if
  1557. * #GNUNET_SCHEDULER_REASON_READ_READY is succeeded
  1558. *
  1559. * @param cls the overlay connect context
  1560. */
  1561. static void
  1562. rocc_hello_sent_cb (void *cls)
  1563. {
  1564. struct RemoteOverlayConnectCtx *rocc = cls;
  1565. rocc->ohh = NULL;
  1566. GNUNET_assert (NULL == rocc->attempt_connect_task_id);
  1567. LOG_DEBUG ("0x%llx: HELLO of peer %s delivered to local peer with id: %u\n",
  1568. rocc->op_id,
  1569. GNUNET_i2s (&rocc->a_id),
  1570. rocc->peer->id);
  1571. rocc->tcc.cgh_p2_ats =
  1572. GST_connection_pool_get_handle (rocc->peer->id,
  1573. rocc->peer->details.local.cfg,
  1574. GST_CONNECTIONPOOL_SERVICE_ATS_CONNECTIVITY,
  1575. &occ_cache_get_handle_ats_rocc_cb,
  1576. rocc, NULL, NULL, NULL);
  1577. }
  1578. /**
  1579. * Task to offer the HELLO message to the peer and ask it to connect to the peer
  1580. * whose identity is in RemoteOverlayConnectCtx
  1581. *
  1582. * @param cls the RemoteOverlayConnectCtx
  1583. */
  1584. static void
  1585. attempt_connect_task (void *cls)
  1586. {
  1587. struct RemoteOverlayConnectCtx *rocc = cls;
  1588. GNUNET_assert (NULL != rocc->attempt_connect_task_id);
  1589. rocc->attempt_connect_task_id = NULL;
  1590. LOG_DEBUG ("0x%llx: Offering HELLO of peer %s to remote peer with id: %u\n",
  1591. rocc->op_id,
  1592. GNUNET_i2s (&rocc->a_id),
  1593. rocc->peer->id);
  1594. rocc->ohh =
  1595. GNUNET_TRANSPORT_offer_hello (rocc->tcc.cfg,
  1596. rocc->hello,
  1597. &rocc_hello_sent_cb,
  1598. rocc);
  1599. if (NULL == rocc->ohh)
  1600. rocc->attempt_connect_task_id =
  1601. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
  1602. (GNUNET_TIME_UNIT_MILLISECONDS,
  1603. 100 +
  1604. GNUNET_CRYPTO_random_u32
  1605. (GNUNET_CRYPTO_QUALITY_WEAK, 500)),
  1606. &attempt_connect_task, rocc);
  1607. }
  1608. /**
  1609. * Callback from cache with needed handles set
  1610. *
  1611. * @param cls the closure passed to GST_cache_get_handle_transport()
  1612. * @param ch the handle to CORE. Can be NULL if it is not requested
  1613. * @param th the handle to TRANSPORT. Can be NULL if it is not requested
  1614. * @param ac the handle to ATS. Can be NULL if it is not requested
  1615. * @param ignore_ peer identity which is ignored in this callback
  1616. */
  1617. static void
  1618. rocc_cache_get_handle_transport_cb (void *cls,
  1619. struct GNUNET_CORE_Handle *ch,
  1620. struct GNUNET_TRANSPORT_CoreHandle *th,
  1621. struct GNUNET_ATS_ConnectivityHandle *ac,
  1622. const struct GNUNET_PeerIdentity *ignore_,
  1623. const struct GNUNET_CONFIGURATION_Handle *cfg)
  1624. {
  1625. struct RemoteOverlayConnectCtx *rocc = cls;
  1626. if (NULL == th)
  1627. {
  1628. rocc->timeout_rocc_task_id =
  1629. GNUNET_SCHEDULER_add_now (&timeout_rocc_task, rocc);
  1630. return;
  1631. }
  1632. rocc->tcc.th_ = th;
  1633. rocc->tcc.cfg = cfg;
  1634. if (NULL !=
  1635. GNUNET_TRANSPORT_core_get_mq (rocc->tcc.th_,
  1636. &rocc->a_id))
  1637. {
  1638. LOG_DEBUG ("0x%llx: Target peer %s already connected to local peer: %u\n",
  1639. rocc->op_id,
  1640. GNUNET_i2s (&rocc->a_id),
  1641. rocc->peer->id);
  1642. cleanup_rocc (rocc);
  1643. return;
  1644. }
  1645. rocc->attempt_connect_task_id =
  1646. GNUNET_SCHEDULER_add_now (&attempt_connect_task, rocc);
  1647. }
  1648. /**
  1649. * Check #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
  1650. *
  1651. * @param cls identification of the client
  1652. * @param msg the actual message
  1653. * @return #GNUNET_OK if @a msg is well-formed
  1654. */
  1655. int
  1656. check_remote_overlay_connect (void *cls,
  1657. const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
  1658. {
  1659. uint32_t peer_id;
  1660. uint16_t msize;
  1661. uint16_t hsize;
  1662. msize = ntohs (msg->header.size);
  1663. if (GNUNET_MESSAGE_TYPE_HELLO != ntohs (msg->hello->type))
  1664. {
  1665. GNUNET_break (0);
  1666. return GNUNET_SYSERR;
  1667. }
  1668. hsize = ntohs (msg->hello->size);
  1669. if ((sizeof (struct GNUNET_TESTBED_RemoteOverlayConnectMessage) + hsize) != msize)
  1670. {
  1671. GNUNET_break (0);
  1672. return GNUNET_SYSERR;
  1673. }
  1674. peer_id = ntohl (msg->peer);
  1675. if ((peer_id >= GST_peer_list_size) ||
  1676. (NULL == GST_peer_list[peer_id]))
  1677. {
  1678. GNUNET_break_op (0);
  1679. return GNUNET_SYSERR;
  1680. }
  1681. return GNUNET_OK;
  1682. }
  1683. /**
  1684. * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT messages
  1685. *
  1686. * @param cls identification of the client
  1687. * @param msg the actual message
  1688. */
  1689. void
  1690. handle_remote_overlay_connect (void *cls,
  1691. const struct GNUNET_TESTBED_RemoteOverlayConnectMessage *msg)
  1692. {
  1693. struct GNUNET_SERVICE_Client *client = cls;
  1694. struct RemoteOverlayConnectCtx *rocc;
  1695. struct Peer *peer;
  1696. struct GNUNET_PeerIdentity pid;
  1697. static char pid_str[16];
  1698. uint32_t peer_id;
  1699. uint16_t hsize;
  1700. hsize = ntohs (msg->hello->size);
  1701. peer_id = ntohl (msg->peer);
  1702. peer = GST_peer_list[peer_id];
  1703. if (GNUNET_YES == peer->is_remote)
  1704. {
  1705. struct GNUNET_MessageHeader *msg2;
  1706. msg2 = GNUNET_copy_message (&msg->header);
  1707. GNUNET_TESTBED_queue_message_ (peer->details.remote.slave->controller,
  1708. msg2);
  1709. GNUNET_SERVICE_client_continue (client);
  1710. return;
  1711. }
  1712. rocc = GNUNET_new (struct RemoteOverlayConnectCtx);
  1713. rocc->op_id = GNUNET_ntohll (msg->operation_id);
  1714. GNUNET_CONTAINER_DLL_insert_tail (roccq_head,
  1715. roccq_tail,
  1716. rocc);
  1717. rocc->a_id = msg->peer_identity;
  1718. GNUNET_TESTING_peer_get_identity (peer->details.local.peer,
  1719. &pid);
  1720. (void) strncpy (pid_str,
  1721. GNUNET_i2s (&pid),
  1722. 15);
  1723. LOG_DEBUG ("0x%llx: Remote overlay connect %s to peer %s with hello size: %u\n",
  1724. rocc->op_id,
  1725. pid_str,
  1726. GNUNET_i2s (&rocc->a_id),
  1727. hsize);
  1728. rocc->peer = peer;
  1729. rocc->peer->reference_cnt++;
  1730. rocc->hello = GNUNET_malloc (hsize);
  1731. GNUNET_memcpy (rocc->hello,
  1732. msg->hello,
  1733. hsize);
  1734. rocc->tcc.cgh_p2_th =
  1735. GST_connection_pool_get_handle (peer_id,
  1736. rocc->peer->details.local.cfg,
  1737. GST_CONNECTIONPOOL_SERVICE_TRANSPORT,
  1738. &rocc_cache_get_handle_transport_cb,
  1739. rocc,
  1740. &rocc->a_id,
  1741. &cache_transport_peer_connect_notify,
  1742. rocc);
  1743. rocc->timeout_rocc_task_id =
  1744. GNUNET_SCHEDULER_add_delayed (GST_timeout,
  1745. &timeout_rocc_task,
  1746. rocc);
  1747. GNUNET_SERVICE_client_continue (client);
  1748. }
  1749. /**
  1750. * Clears all pending overlay connect contexts in queue
  1751. */
  1752. void
  1753. GST_free_occq ()
  1754. {
  1755. struct OverlayConnectContext *occ;
  1756. while (NULL != (occ = occq_head))
  1757. cleanup_occ (occ);
  1758. }
  1759. /**
  1760. * Clears all pending remote overlay connect contexts in queue
  1761. */
  1762. void
  1763. GST_free_roccq ()
  1764. {
  1765. struct RemoteOverlayConnectCtx *rocc;
  1766. while (NULL != (rocc = roccq_head))
  1767. cleanup_rocc (rocc);
  1768. }