gnunet-service-testbed_oc.c 59 KB

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