gnunet-service-testbed_links.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2008--2013 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_links.c
  18. * @brief TESTBED service components that deals with starting slave controllers
  19. * and establishing lateral links between controllers
  20. * @author Sree Harsha Totakura
  21. */
  22. #include "gnunet-service-testbed.h"
  23. /**
  24. * Redefine LOG with a changed log component string
  25. */
  26. #ifdef LOG
  27. #undef LOG
  28. #endif
  29. #define LOG(kind, ...) \
  30. GNUNET_log_from (kind, "testbed-links", __VA_ARGS__)
  31. /**
  32. * The event mask for the events we listen from sub-controllers
  33. */
  34. #define EVENT_MASK (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED)
  35. /**
  36. * States of LCFContext
  37. */
  38. enum LCFContextState
  39. {
  40. /**
  41. * The Context has been initialized; Nothing has been done on it
  42. */
  43. INIT,
  44. /**
  45. * Delegated host has been registered at the forwarding controller
  46. */
  47. DELEGATED_HOST_REGISTERED,
  48. /**
  49. * The slave host has been registred at the forwarding controller
  50. */
  51. SLAVE_HOST_REGISTERED,
  52. /**
  53. * The context has been finished (may have error)
  54. */
  55. FINISHED
  56. };
  57. /**
  58. * Link controllers request forwarding context
  59. */
  60. struct LCFContext
  61. {
  62. /**
  63. * The LCFContext
  64. */
  65. struct LCFContext *next;
  66. /**
  67. * The LCFContext
  68. */
  69. struct LCFContext *prev;
  70. /**
  71. * The gateway which will pass the link message to delegated host
  72. */
  73. struct Slave *gateway;
  74. /**
  75. * The client which has asked to perform this operation
  76. */
  77. struct GNUNET_SERVICE_Client *client;
  78. /**
  79. * Handle for operations which are forwarded while linking controllers
  80. */
  81. struct GNUNET_TESTBED_Operation *op;
  82. /**
  83. * The timeout task
  84. */
  85. struct GNUNET_SCHEDULER_Task *timeout_task;
  86. /**
  87. * The id of the operation which created this context
  88. */
  89. uint64_t operation_id;
  90. /**
  91. * should the slave controller start the delegated controller?
  92. */
  93. int is_subordinate;
  94. /**
  95. * The state of this context
  96. */
  97. enum LCFContextState state;
  98. /**
  99. * The delegated host
  100. */
  101. uint32_t delegated_host_id;
  102. /**
  103. * The slave host
  104. */
  105. uint32_t slave_host_id;
  106. };
  107. /**
  108. * Notification context to be used to notify when connection to the neighbour's
  109. * controller is opened
  110. */
  111. struct NeighbourConnectNotification
  112. {
  113. /**
  114. * DLL next for inclusion in neighbour's list of notification requests
  115. */
  116. struct NeighbourConnectNotification *next;
  117. /**
  118. * DLL prev
  119. */
  120. struct NeighbourConnectNotification *prev;
  121. /**
  122. * The neighbour
  123. */
  124. struct Neighbour *n;
  125. /**
  126. * The notification callback to call when we are connect to neighbour
  127. */
  128. GST_NeigbourConnectNotifyCallback cb;
  129. /**
  130. * The closure for the above callback
  131. */
  132. void *cb_cls;
  133. };
  134. /**
  135. * A connected controller which is not our child
  136. */
  137. struct Neighbour
  138. {
  139. /**
  140. * The controller handle
  141. */
  142. struct GNUNET_TESTBED_Controller *controller;
  143. /**
  144. * Operation handle for opening a lateral connection to another controller.
  145. * Will be NULL if the slave controller is started by this controller
  146. */
  147. struct GNUNET_TESTBED_Operation *conn_op;
  148. /**
  149. * DLL head for the list of notification requests
  150. */
  151. struct NeighbourConnectNotification *nl_head;
  152. /**
  153. * DLL tail for the list of notification requests
  154. */
  155. struct NeighbourConnectNotification *nl_tail;
  156. /**
  157. * Task id for the task to call notifications from the notification list
  158. */
  159. struct GNUNET_SCHEDULER_Task *notify_task;
  160. /**
  161. * How many references are present currently to this neighbour's connection
  162. */
  163. unsigned int reference_cnt;
  164. /**
  165. * Is the conn_op inactivated?
  166. */
  167. unsigned int inactive;
  168. /**
  169. * The id of the host this controller is running on
  170. */
  171. uint32_t host_id;
  172. };
  173. /**
  174. * The neighbour list
  175. */
  176. static struct Neighbour **neighbour_list;
  177. /**
  178. * The size of the neighbour list
  179. */
  180. static unsigned int neighbour_list_size;
  181. /**
  182. * Context information for establishing a link to neighbour (Used is
  183. * GST_handle_link_controllers()
  184. */
  185. struct NeighbourConnectCtxt
  186. {
  187. /**
  188. * DLL next for inclusion in the corresponding context list
  189. */
  190. struct NeighbourConnectCtxt *next;
  191. /**
  192. * DLL tail
  193. */
  194. struct NeighbourConnectCtxt *prev;
  195. /**
  196. * The neighbour to whom connection should be made
  197. */
  198. struct Neighbour *n;
  199. /**
  200. * The client requesting the connection
  201. */
  202. struct GNUNET_SERVICE_Client *client;
  203. /**
  204. * Task to be run upon timeout
  205. */
  206. struct GNUNET_SCHEDULER_Task *timeout_task;
  207. /**
  208. * The notification handle associated with the neighbour's connection request
  209. */
  210. struct NeighbourConnectNotification *nh;
  211. /**
  212. * The id of the link-controllers operation responsible for creating this
  213. * context
  214. */
  215. uint64_t op_id;
  216. };
  217. /**
  218. * DLL head for the list of neighbour connect contexts
  219. */
  220. struct NeighbourConnectCtxt *ncc_head;
  221. /**
  222. * DLL tail for the list of neighbour connect contexts
  223. */
  224. struct NeighbourConnectCtxt *ncc_tail;
  225. /**
  226. * A list of directly linked neighbours
  227. */
  228. struct Slave **GST_slave_list;
  229. /**
  230. * The size of directly linked neighbours list
  231. */
  232. unsigned int GST_slave_list_size;
  233. /**
  234. * A list of routes
  235. */
  236. static struct Route **route_list;
  237. /**
  238. * The LCF queue
  239. */
  240. static struct LCFContext *lcf_head;
  241. /**
  242. * The tail for the LCF queue
  243. */
  244. static struct LCFContext *lcf_tail;
  245. /**
  246. * The lcf_task handle
  247. */
  248. static struct GNUNET_SCHEDULER_Task *lcf_proc_task_id;
  249. /**
  250. * The size of the route list
  251. */
  252. static unsigned int route_list_size;
  253. /**
  254. * Adds a slave to the slave array
  255. *
  256. * @param slave the slave controller to add
  257. */
  258. static void
  259. slave_list_add (struct Slave *slave)
  260. {
  261. if (slave->host_id >= GST_slave_list_size)
  262. GST_array_grow_large_enough (GST_slave_list,
  263. GST_slave_list_size,
  264. slave->host_id);
  265. GNUNET_assert (NULL == GST_slave_list[slave->host_id]);
  266. GST_slave_list[slave->host_id] = slave;
  267. }
  268. /**
  269. * Clean up all forwarded operation overlay context matching the
  270. * client given in @a cls.
  271. *
  272. * @param cls a `struct GNUNET_SERVICE_Client *` to match
  273. * @param key unused
  274. * @param value the `struct RegisteredHostContext` to search for @a cls
  275. * @return #GNUNET_OK (continue iterating)
  276. */
  277. static int
  278. drop_client_entries (void *cls,
  279. const struct GNUNET_HashCode *key,
  280. void *value)
  281. {
  282. struct GNUNET_SERVICE_Client *client = cls;
  283. struct RegisteredHostContext *rhc = value;
  284. struct ForwardedOverlayConnectContext *focc;
  285. struct ForwardedOverlayConnectContext *foccn;
  286. for (focc = rhc->focc_dll_head; NULL != focc; focc = foccn)
  287. {
  288. foccn = focc->next;
  289. if (focc->client == client)
  290. GST_cleanup_focc (focc);
  291. }
  292. return GNUNET_OK;
  293. }
  294. /**
  295. * Adds a route to the route list
  296. *
  297. * @param route the route to add
  298. */
  299. static void
  300. route_list_add (struct Route *route)
  301. {
  302. if (route->dest >= route_list_size)
  303. GST_array_grow_large_enough (route_list, route_list_size, route->dest);
  304. GNUNET_assert (NULL == route_list[route->dest]);
  305. route_list[route->dest] = route;
  306. }
  307. /**
  308. * Add a neighbour to the neighbour list. Grows the neighbour list
  309. * automatically.
  310. *
  311. * @param n the neighbour to add
  312. */
  313. static void
  314. neighbour_list_add (struct Neighbour *n)
  315. {
  316. if (n->host_id >= neighbour_list_size)
  317. GST_array_grow_large_enough (neighbour_list, neighbour_list_size,
  318. n->host_id);
  319. GNUNET_assert (NULL == neighbour_list[n->host_id]);
  320. neighbour_list[n->host_id] = n;
  321. }
  322. /**
  323. * Cleans up the route list
  324. */
  325. void
  326. GST_route_list_clear ()
  327. {
  328. unsigned int id;
  329. for (id = 0; id < route_list_size; id++)
  330. if (NULL != route_list[id])
  331. GNUNET_free (route_list[id]);
  332. GNUNET_free_non_null (route_list);
  333. route_list = NULL;
  334. }
  335. /**
  336. * Iterator for freeing hash map entries in a slave's reghost_map
  337. *
  338. * @param cls handle to the slave
  339. * @param key current key code
  340. * @param value value in the hash map
  341. * @return #GNUNET_YES if we should continue to iterate,
  342. * #GNUNET_NO if not.
  343. */
  344. static int
  345. reghost_free_iterator (void *cls,
  346. const struct GNUNET_HashCode *key,
  347. void *value)
  348. {
  349. struct Slave *slave = cls;
  350. struct RegisteredHostContext *rhc = value;
  351. struct ForwardedOverlayConnectContext *focc;
  352. GNUNET_assert (GNUNET_YES ==
  353. GNUNET_CONTAINER_multihashmap_remove (slave->reghost_map, key,
  354. value));
  355. while (NULL != (focc = rhc->focc_dll_head))
  356. GST_cleanup_focc (focc);
  357. GNUNET_free (value);
  358. return GNUNET_YES;
  359. }
  360. /**
  361. * Kill a #Slave object
  362. *
  363. * @param slave the #Slave object
  364. */
  365. static void
  366. kill_slave (struct Slave *slave)
  367. {
  368. struct HostRegistration *hr_entry;
  369. while (NULL != (hr_entry = slave->hr_dll_head))
  370. {
  371. GNUNET_CONTAINER_DLL_remove (slave->hr_dll_head, slave->hr_dll_tail,
  372. hr_entry);
  373. GNUNET_free (hr_entry);
  374. }
  375. if (NULL != slave->rhandle)
  376. GNUNET_TESTBED_cancel_registration (slave->rhandle);
  377. GNUNET_assert (GNUNET_SYSERR !=
  378. GNUNET_CONTAINER_multihashmap_iterate (slave->reghost_map,
  379. reghost_free_iterator,
  380. slave));
  381. GNUNET_CONTAINER_multihashmap_destroy (slave->reghost_map);
  382. if (NULL != slave->controller)
  383. GNUNET_TESTBED_controller_disconnect (slave->controller);
  384. if (NULL != slave->controller_proc)
  385. {
  386. LOG_DEBUG ("Stopping a slave\n");
  387. GNUNET_TESTBED_controller_kill_ (slave->controller_proc);
  388. }
  389. }
  390. /**
  391. * Destroy a #Slave object
  392. *
  393. * @param slave the #Slave object
  394. */
  395. static void
  396. destroy_slave (struct Slave *slave)
  397. {
  398. if (NULL != slave->controller_proc)
  399. {
  400. GNUNET_TESTBED_controller_destroy_ (slave->controller_proc);
  401. LOG_DEBUG ("Slave stopped\n");
  402. }
  403. GST_slave_list[slave->host_id] = NULL;
  404. GNUNET_free (slave);
  405. }
  406. /**
  407. * Cleans up the slave list
  408. */
  409. void
  410. GST_slave_list_clear ()
  411. {
  412. struct Slave *slave;
  413. unsigned int id;
  414. for (id = 0; id < GST_slave_list_size; id++)
  415. {
  416. slave = GST_slave_list[id];
  417. if (NULL == slave)
  418. continue;
  419. kill_slave (slave);
  420. }
  421. for (id = 0; id < GST_slave_list_size; id++)
  422. {
  423. slave = GST_slave_list[id];
  424. if (NULL == slave)
  425. continue;
  426. destroy_slave (slave);
  427. }
  428. GNUNET_free_non_null (GST_slave_list);
  429. GST_slave_list = NULL;
  430. }
  431. /**
  432. * Finds the route with directly connected host as destination through which
  433. * the destination host can be reached
  434. *
  435. * @param host_id the id of the destination host
  436. * @return the route with directly connected destination host; NULL if no route
  437. * is found
  438. */
  439. struct Route *
  440. GST_find_dest_route (uint32_t host_id)
  441. {
  442. struct Route *route;
  443. if (route_list_size <= host_id)
  444. return NULL;
  445. while (NULL != (route = route_list[host_id]))
  446. {
  447. if (route->thru == GST_context->host_id)
  448. break;
  449. host_id = route->thru;
  450. }
  451. return route;
  452. }
  453. /**
  454. * Function to send a failure reponse for controller link operation
  455. *
  456. * @param client the client to send the message to
  457. * @param operation_id the operation ID of the controller link request
  458. * @param cfg the configuration with which the delegated controller is started.
  459. * Can be NULL if the delegated controller is not started but just
  460. * linked to.
  461. * @param emsg set to an error message explaining why the controller link
  462. * failed. Setting this to NULL signifies success. !This should be
  463. * NULL if cfg is set!
  464. */
  465. static void
  466. send_controller_link_response (struct GNUNET_SERVICE_Client *client,
  467. uint64_t operation_id,
  468. const struct GNUNET_CONFIGURATION_Handle *cfg,
  469. const char *emsg)
  470. {
  471. struct GNUNET_MQ_Envelope *env;
  472. struct GNUNET_TESTBED_ControllerLinkResponse *msg;
  473. char *xconfig;
  474. size_t config_size;
  475. size_t xconfig_size;
  476. uint16_t msize;
  477. GNUNET_assert ((NULL == cfg) || (NULL == emsg));
  478. xconfig = NULL;
  479. xconfig_size = 0;
  480. config_size = 0;
  481. msize = 0;
  482. if (NULL != cfg)
  483. {
  484. xconfig = GNUNET_TESTBED_compress_cfg_ (cfg,
  485. &config_size,
  486. &xconfig_size);
  487. msize += xconfig_size;
  488. }
  489. if (NULL != emsg)
  490. msize += strlen (emsg);
  491. env = GNUNET_MQ_msg_extra (msg,
  492. msize,
  493. GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT);
  494. if (NULL == emsg)
  495. msg->success = htons (GNUNET_YES);
  496. msg->operation_id = GNUNET_htonll (operation_id);
  497. msg->config_size = htons ((uint16_t) config_size);
  498. if (NULL != xconfig)
  499. {
  500. GNUNET_memcpy (&msg[1],
  501. xconfig,
  502. xconfig_size);
  503. GNUNET_free (xconfig);
  504. }
  505. if (NULL != emsg)
  506. GNUNET_memcpy (&msg[1],
  507. emsg,
  508. strlen (emsg));
  509. GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
  510. env);
  511. }
  512. /**
  513. * The Link Controller forwarding task
  514. *
  515. * @param cls the LCFContext
  516. */
  517. static void
  518. lcf_proc_task (void *cls);
  519. /**
  520. * Completion callback for host registrations while forwarding Link Controller messages
  521. *
  522. * @param cls the LCFContext
  523. * @param emsg the error message; NULL if host registration is successful
  524. */
  525. static void
  526. lcf_proc_cc (void *cls,
  527. const char *emsg)
  528. {
  529. struct LCFContext *lcf = cls;
  530. GNUNET_assert (NULL == lcf_proc_task_id);
  531. switch (lcf->state)
  532. {
  533. case INIT:
  534. if (NULL != emsg)
  535. goto registration_error;
  536. lcf->state = DELEGATED_HOST_REGISTERED;
  537. lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
  538. break;
  539. case DELEGATED_HOST_REGISTERED:
  540. if (NULL != emsg)
  541. goto registration_error;
  542. lcf->state = SLAVE_HOST_REGISTERED;
  543. lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
  544. break;
  545. default:
  546. GNUNET_assert (0); /* Shouldn't reach here */
  547. }
  548. return;
  549. registration_error:
  550. LOG (GNUNET_ERROR_TYPE_WARNING,
  551. "Host registration failed with message: %s\n",
  552. emsg);
  553. lcf->state = FINISHED;
  554. lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task,
  555. lcf);
  556. }
  557. /**
  558. * The Link Controller forwarding task
  559. *
  560. * @param cls the LCFContext
  561. */
  562. static void
  563. lcf_proc_task (void *cls);
  564. /**
  565. * Task to free resources when forwarded link controllers has been timedout
  566. *
  567. * @param cls the LCFContext
  568. */
  569. static void
  570. lcf_forwarded_operation_timeout (void *cls)
  571. {
  572. struct LCFContext *lcf = cls;
  573. lcf->timeout_task = NULL;
  574. // GST_forwarded_operation_timeout (lcf->fopc, tc);
  575. LOG (GNUNET_ERROR_TYPE_WARNING,
  576. "A forwarded controller link operation has timed out\n");
  577. send_controller_link_response (lcf->client,
  578. lcf->operation_id,
  579. NULL,
  580. "A forwarded controller link operation has timed out\n");
  581. GNUNET_assert (NULL == lcf_proc_task_id);
  582. lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task,
  583. lcf);
  584. }
  585. /**
  586. * The Link Controller forwarding task
  587. *
  588. * @param cls the LCFContext
  589. */
  590. static void
  591. lcf_proc_task (void *cls)
  592. {
  593. struct LCFContext *lcf = cls;
  594. lcf_proc_task_id = NULL;
  595. switch (lcf->state)
  596. {
  597. case INIT:
  598. if (GNUNET_NO ==
  599. GNUNET_TESTBED_is_host_registered_ (GST_host_list
  600. [lcf->delegated_host_id],
  601. lcf->gateway->controller))
  602. {
  603. GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf,
  604. GST_host_list[lcf->delegated_host_id]);
  605. }
  606. else
  607. {
  608. lcf->state = DELEGATED_HOST_REGISTERED;
  609. lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
  610. }
  611. break;
  612. case DELEGATED_HOST_REGISTERED:
  613. if (GNUNET_NO ==
  614. GNUNET_TESTBED_is_host_registered_ (GST_host_list[lcf->slave_host_id],
  615. lcf->gateway->controller))
  616. {
  617. GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf,
  618. GST_host_list[lcf->slave_host_id]);
  619. }
  620. else
  621. {
  622. lcf->state = SLAVE_HOST_REGISTERED;
  623. lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
  624. }
  625. break;
  626. case SLAVE_HOST_REGISTERED:
  627. lcf->op = GNUNET_TESTBED_controller_link (lcf,
  628. lcf->gateway->controller,
  629. GST_host_list[lcf->
  630. delegated_host_id],
  631. GST_host_list[lcf->slave_host_id],
  632. lcf->is_subordinate);
  633. lcf->timeout_task =
  634. GNUNET_SCHEDULER_add_delayed (GST_timeout,
  635. &lcf_forwarded_operation_timeout,
  636. lcf);
  637. lcf->state = FINISHED;
  638. break;
  639. case FINISHED:
  640. if (NULL != lcf->op)
  641. GNUNET_TESTBED_operation_done (lcf->op);
  642. GNUNET_CONTAINER_DLL_remove (lcf_head,
  643. lcf_tail,
  644. lcf);
  645. GNUNET_free (lcf);
  646. if (NULL != lcf_head)
  647. lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task,
  648. lcf_head);
  649. }
  650. }
  651. /**
  652. * Callback for event from slave controllers
  653. *
  654. * @param cls NULL
  655. * @param event information about the event
  656. */
  657. static void
  658. slave_event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
  659. {
  660. struct LCFContext *lcf;
  661. /* We currently only get here when working on LCFContexts */
  662. GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
  663. lcf = event->op_cls;
  664. GNUNET_assert (lcf->op == event->op);
  665. GNUNET_TESTBED_operation_done (lcf->op);
  666. lcf->op = NULL;
  667. GNUNET_assert (FINISHED == lcf->state);
  668. GNUNET_assert (NULL != lcf->timeout_task);
  669. GNUNET_SCHEDULER_cancel (lcf->timeout_task);
  670. if (NULL == event->details.operation_finished.emsg)
  671. send_controller_link_response (lcf->client, lcf->operation_id,
  672. GNUNET_TESTBED_host_get_cfg_
  673. (GST_host_list[lcf->delegated_host_id]),
  674. NULL);
  675. else
  676. send_controller_link_response (lcf->client, lcf->operation_id,
  677. NULL,
  678. event->details.operation_finished.emsg);
  679. GNUNET_assert (NULL == lcf_proc_task_id);
  680. lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
  681. return;
  682. }
  683. /**
  684. * Callback to signal successfull startup of the controller process
  685. *
  686. * @param cls the handle to the slave whose status is to be found here
  687. * @param cfg the configuration with which the controller has been started;
  688. * NULL if status is not #GNUNET_OK
  689. * @param status #GNUNET_OK if the startup is successfull; #GNUNET_SYSERR if not,
  690. * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
  691. */
  692. static void
  693. slave_status_cb (void *cls,
  694. const struct GNUNET_CONFIGURATION_Handle *cfg,
  695. int status)
  696. {
  697. struct Slave *slave = cls;
  698. struct LinkControllersContext *lcc;
  699. lcc = slave->lcc;
  700. if (GNUNET_SYSERR == status)
  701. {
  702. slave->controller_proc = NULL;
  703. /* Stop all link controller forwarding tasks since we shutdown here anyway
  704. and as these tasks they depend on the operation queues which are created
  705. through GNUNET_TESTBED_controller_connect() and in kill_slave() we call
  706. the destructor function GNUNET_TESTBED_controller_disconnect() */
  707. GST_free_lcf ();
  708. kill_slave (slave);
  709. destroy_slave (slave);
  710. slave = NULL;
  711. LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n");
  712. GNUNET_SCHEDULER_shutdown (); /* We too shutdown */
  713. goto clean_lcc;
  714. }
  715. slave->controller =
  716. GNUNET_TESTBED_controller_connect (GST_host_list[slave->host_id],
  717. EVENT_MASK, &slave_event_cb,
  718. slave);
  719. if (NULL != slave->controller)
  720. {
  721. send_controller_link_response (lcc->client, lcc->operation_id, cfg, NULL);
  722. }
  723. else
  724. {
  725. send_controller_link_response (lcc->client, lcc->operation_id, NULL,
  726. "Could not connect to delegated controller");
  727. kill_slave (slave);
  728. destroy_slave (slave);
  729. slave = NULL;
  730. }
  731. clean_lcc:
  732. if (NULL != lcc)
  733. {
  734. if (NULL != lcc->client)
  735. {
  736. GNUNET_SERVICE_client_continue (lcc->client);
  737. lcc->client = NULL;
  738. }
  739. GNUNET_free (lcc);
  740. }
  741. if (NULL != slave)
  742. slave->lcc = NULL;
  743. }
  744. /**
  745. * Trigger notification task if there are notification requests currently
  746. * waiting in the given neighbour. Also activates the neighbour connect operation
  747. * if it was previously inactivated so that the connection to the neighbour can
  748. * be re-used
  749. *
  750. * @param n the neighbour
  751. */
  752. static void
  753. trigger_notifications (struct Neighbour *n);
  754. /**
  755. * Task to call the notification queued in the notifications list of the given
  756. * neighbour
  757. *
  758. * @param cls the neighbour
  759. */
  760. static void
  761. neighbour_connect_notify_task (void *cls)
  762. {
  763. struct Neighbour *n = cls;
  764. struct NeighbourConnectNotification *h;
  765. GNUNET_assert (NULL != (h = n->nl_head));
  766. GNUNET_assert (NULL != n->notify_task);
  767. n->notify_task = NULL;
  768. GNUNET_assert (NULL != n->controller);
  769. GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h);
  770. trigger_notifications (n);
  771. h->cb (h->cb_cls, n->controller);
  772. GNUNET_free (h);
  773. }
  774. /**
  775. * Trigger notification task if there are notification requests currently
  776. * waiting in the given neighbour. Also activates the neighbour connect operation
  777. * if it was previously inactivated so that the connection to the neighbour can
  778. * be re-used
  779. *
  780. * @param n the neighbour
  781. */
  782. static void
  783. trigger_notifications (struct Neighbour *n)
  784. {
  785. GNUNET_assert (NULL != n->conn_op);
  786. if (NULL == n->nl_head)
  787. return;
  788. if (NULL == n->controller)
  789. return;
  790. if (NULL != n->notify_task)
  791. return;
  792. if (1 == n->inactive)
  793. {
  794. GNUNET_assert (0 == n->reference_cnt);
  795. GNUNET_TESTBED_operation_activate_ (n->conn_op);
  796. n->inactive = 0;
  797. }
  798. n->reference_cnt++;
  799. n->notify_task =
  800. GNUNET_SCHEDULER_add_now (&neighbour_connect_notify_task, n);
  801. }
  802. /**
  803. * Callback to be called when the neighbour connect operation is started. The
  804. * connection to the neigbour is opened here and any pending notifications are
  805. * trigger.
  806. *
  807. * @param cls the neighbour
  808. */
  809. static void
  810. opstart_neighbour_conn (void *cls)
  811. {
  812. struct Neighbour *n = cls;
  813. GNUNET_assert (NULL != n->conn_op);
  814. GNUNET_assert (NULL == n->controller);
  815. LOG_DEBUG ("Opening connection to controller on host %u\n", n->host_id);
  816. n->controller = GNUNET_TESTBED_controller_connect (GST_host_list[n->host_id],
  817. EVENT_MASK,
  818. &slave_event_cb,
  819. NULL);
  820. trigger_notifications (n);
  821. }
  822. /**
  823. * Callback to be called when the neighbour connect operation is released
  824. *
  825. * @param cls the neighbour
  826. */
  827. static void
  828. oprelease_neighbour_conn (void *cls)
  829. {
  830. struct Neighbour *n = cls;
  831. GNUNET_assert (0 == n->reference_cnt);
  832. GNUNET_assert (NULL == n->notify_task);
  833. GNUNET_assert (NULL == n->nl_head);
  834. if (NULL != n->controller)
  835. {
  836. LOG_DEBUG ("Closing connection to controller on host %u\n", n->host_id);
  837. GNUNET_TESTBED_controller_disconnect (n->controller);
  838. n->controller = NULL;
  839. }
  840. n->conn_op = NULL;
  841. n->inactive = 0;
  842. }
  843. /**
  844. * Try to open a connection to the given neigbour. If the connection is open
  845. * already, then it is re-used. If not, the request is queued in the operation
  846. * queues responsible for bounding the total number of file descriptors. The
  847. * actual connection will happen when the operation queue marks the
  848. * corresponding operation as active.
  849. *
  850. * @param n the neighbour to open a connection to
  851. * @param cb the notification callback to call when the connection is opened
  852. * @param cb_cls the closure for the above callback
  853. */
  854. struct NeighbourConnectNotification *
  855. GST_neighbour_get_connection (struct Neighbour *n,
  856. GST_NeigbourConnectNotifyCallback cb,
  857. void *cb_cls)
  858. {
  859. struct NeighbourConnectNotification *h;
  860. GNUNET_assert (NULL != cb);
  861. LOG_DEBUG ("Attempting to get connection to controller on host %u\n",
  862. n->host_id);
  863. h = GNUNET_new (struct NeighbourConnectNotification);
  864. h->n = n;
  865. h->cb = cb;
  866. h->cb_cls = cb_cls;
  867. GNUNET_CONTAINER_DLL_insert_tail (n->nl_head, n->nl_tail, h);
  868. if (NULL == n->conn_op)
  869. {
  870. GNUNET_assert (NULL == n->controller);
  871. n->conn_op = GNUNET_TESTBED_operation_create_ (n, &opstart_neighbour_conn,
  872. &oprelease_neighbour_conn);
  873. GNUNET_TESTBED_operation_queue_insert_ (GST_opq_openfds, n->conn_op);
  874. GNUNET_TESTBED_operation_begin_wait_ (n->conn_op);
  875. return h;
  876. }
  877. trigger_notifications (n);
  878. return h;
  879. }
  880. /**
  881. * Cancel the request for opening a connection to the neighbour
  882. *
  883. * @param h the notification handle
  884. */
  885. void
  886. GST_neighbour_get_connection_cancel (struct NeighbourConnectNotification *h)
  887. {
  888. struct Neighbour *n;
  889. int cleanup_task;
  890. n = h->n;
  891. cleanup_task = (h == n->nl_head) ? GNUNET_YES : GNUNET_NO;
  892. GNUNET_CONTAINER_DLL_remove (n->nl_head, n->nl_tail, h);
  893. GNUNET_free (h);
  894. if (GNUNET_NO == cleanup_task)
  895. return;
  896. if (NULL == n->notify_task)
  897. return;
  898. GNUNET_assert (0 < n->reference_cnt);
  899. n->reference_cnt--;
  900. GNUNET_SCHEDULER_cancel (n->notify_task);
  901. n->notify_task = NULL;
  902. if (NULL == n->nl_head)
  903. {
  904. if ((0 == n->reference_cnt) && (0 == n->inactive))
  905. {
  906. n->inactive = 1;
  907. GNUNET_TESTBED_operation_inactivate_ (n->conn_op);
  908. }
  909. return;
  910. }
  911. trigger_notifications (n);
  912. }
  913. /**
  914. * Release the connection to the neighbour. The actual connection will be
  915. * closed if connections to other neighbour are waiting (to maintain a bound on
  916. * the total number of connections that are open).
  917. *
  918. * @param n the neighbour whose connection can be closed
  919. */
  920. void
  921. GST_neighbour_release_connection (struct Neighbour *n)
  922. {
  923. GNUNET_assert (0 == n->inactive);
  924. GNUNET_assert (0 < n->reference_cnt);
  925. n->reference_cnt--;
  926. if (0 == n->reference_cnt)
  927. {
  928. n->inactive = 1;
  929. GNUNET_TESTBED_operation_inactivate_ (n->conn_op);
  930. }
  931. }
  932. /**
  933. * Cleanup neighbour connect contexts
  934. *
  935. * @param ncc the neighbour connect context to cleanup
  936. */
  937. static void
  938. cleanup_ncc (struct NeighbourConnectCtxt *ncc)
  939. {
  940. if (NULL != ncc->nh)
  941. GST_neighbour_get_connection_cancel (ncc->nh);
  942. if (NULL != ncc->timeout_task)
  943. GNUNET_SCHEDULER_cancel (ncc->timeout_task);
  944. GNUNET_CONTAINER_DLL_remove (ncc_head,
  945. ncc_tail,
  946. ncc);
  947. GNUNET_free (ncc);
  948. }
  949. /**
  950. * Cleans up the neighbour list
  951. */
  952. void
  953. GST_neighbour_list_clean ()
  954. {
  955. struct Neighbour *n;
  956. unsigned int id;
  957. for (id = 0; id < neighbour_list_size; id++)
  958. {
  959. if (NULL == (n = neighbour_list[id]))
  960. continue;
  961. if (NULL != n->conn_op)
  962. GNUNET_TESTBED_operation_release_ (n->conn_op);
  963. GNUNET_free (n);
  964. neighbour_list[id] = NULL;
  965. }
  966. GNUNET_free_non_null (neighbour_list);
  967. }
  968. /**
  969. * Get a neighbour from the neighbour list
  970. *
  971. * @param id the index of the neighbour in the neighbour list
  972. * @return the Neighbour; NULL if the given index in invalid (index greater than
  973. * the list size or neighbour at that index is NULL)
  974. */
  975. struct Neighbour *
  976. GST_get_neighbour (uint32_t id)
  977. {
  978. if (neighbour_list_size <= id)
  979. return NULL;
  980. return neighbour_list[id];
  981. }
  982. /**
  983. * Function to cleanup the neighbour connect contexts
  984. */
  985. void
  986. GST_free_nccq ()
  987. {
  988. while (NULL != ncc_head)
  989. cleanup_ncc (ncc_head);
  990. }
  991. /**
  992. * Task to be run upon timeout while attempting to connect to the neighbour
  993. *
  994. * @param cls the NeighbourConnectCtxt created in GST_handle_link_controllers()
  995. */
  996. static void
  997. timeout_neighbour_connect (void *cls)
  998. {
  999. struct NeighbourConnectCtxt *ncc = cls;
  1000. ncc->timeout_task = NULL;
  1001. send_controller_link_response (ncc->client,
  1002. ncc->op_id,
  1003. NULL,
  1004. "Could not connect to delegated controller");
  1005. cleanup_ncc (ncc);
  1006. }
  1007. /**
  1008. * Callback called when a connection to the neighbour is made
  1009. *
  1010. * @param cls the NeighbourConnectCtxt created in GST_handle_link_controllers()
  1011. * @param c the handle the neighbour's controller
  1012. */
  1013. static void
  1014. neighbour_connect_cb (void *cls,
  1015. struct GNUNET_TESTBED_Controller *c)
  1016. {
  1017. struct NeighbourConnectCtxt *ncc = cls;
  1018. GNUNET_SCHEDULER_cancel (ncc->timeout_task);
  1019. ncc->timeout_task = NULL;
  1020. ncc->nh = NULL;
  1021. GST_neighbour_release_connection (ncc->n);
  1022. send_controller_link_response (ncc->client,
  1023. ncc->op_id,
  1024. NULL,
  1025. NULL);
  1026. cleanup_ncc (ncc);
  1027. }
  1028. /**
  1029. * Function to create a neigbour and add it into the neighbour list
  1030. *
  1031. * @param host the host of the neighbour
  1032. */
  1033. struct Neighbour *
  1034. GST_create_neighbour (struct GNUNET_TESTBED_Host *host)
  1035. {
  1036. struct Neighbour *n;
  1037. n = GNUNET_new (struct Neighbour);
  1038. n->host_id = GNUNET_TESTBED_host_get_id_ (host);
  1039. neighbour_list_add (n); /* just add; connect on-demand */
  1040. return n;
  1041. }
  1042. /**
  1043. * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
  1044. *
  1045. * @param cls identification of the client
  1046. * @param msg the actual message
  1047. */
  1048. void
  1049. handle_link_controllers (void *cls,
  1050. const struct GNUNET_TESTBED_ControllerLinkRequest *msg)
  1051. {
  1052. struct GNUNET_SERVICE_Client *client = cls;
  1053. struct LCFContext *lcf;
  1054. struct Route *route;
  1055. struct Route *new_route;
  1056. uint64_t op_id;
  1057. uint32_t delegated_host_id;
  1058. uint32_t slave_host_id;
  1059. if (NULL == GST_context)
  1060. {
  1061. GNUNET_break (0);
  1062. GNUNET_SERVICE_client_drop (client);
  1063. return;
  1064. }
  1065. delegated_host_id = ntohl (msg->delegated_host_id);
  1066. if (delegated_host_id == GST_context->host_id)
  1067. {
  1068. GNUNET_break (0);
  1069. LOG (GNUNET_ERROR_TYPE_WARNING,
  1070. "Trying to link ourselves\n");
  1071. GNUNET_SERVICE_client_drop (client);
  1072. return;
  1073. }
  1074. if ((delegated_host_id >= GST_host_list_size) ||
  1075. (NULL == GST_host_list[delegated_host_id]))
  1076. {
  1077. LOG (GNUNET_ERROR_TYPE_WARNING,
  1078. "Delegated host %u not registered with us\n",
  1079. delegated_host_id);
  1080. GNUNET_SERVICE_client_drop (client);
  1081. return;
  1082. }
  1083. slave_host_id = ntohl (msg->slave_host_id);
  1084. if ((slave_host_id >= GST_host_list_size) ||
  1085. (NULL == GST_host_list[slave_host_id]))
  1086. {
  1087. LOG (GNUNET_ERROR_TYPE_WARNING,
  1088. "Slave host %u not registered with us\n",
  1089. slave_host_id);
  1090. GNUNET_SERVICE_client_drop (client);
  1091. return;
  1092. }
  1093. if (slave_host_id == delegated_host_id)
  1094. {
  1095. LOG (GNUNET_ERROR_TYPE_WARNING,
  1096. "Slave and delegated host are same\n");
  1097. GNUNET_SERVICE_client_drop (client);
  1098. return;
  1099. }
  1100. op_id = GNUNET_ntohll (msg->operation_id);
  1101. if (slave_host_id == GST_context->host_id) /* Link from us */
  1102. {
  1103. struct Slave *slave;
  1104. struct LinkControllersContext *lcc;
  1105. if (1 != msg->is_subordinate)
  1106. {
  1107. struct Neighbour *n;
  1108. struct NeighbourConnectCtxt *ncc;
  1109. if ((delegated_host_id < neighbour_list_size) &&
  1110. (NULL != neighbour_list[delegated_host_id]))
  1111. {
  1112. GNUNET_break (0);
  1113. GNUNET_SERVICE_client_drop (client);
  1114. return;
  1115. }
  1116. LOG_DEBUG ("Received request to establish a link to host %u\n",
  1117. delegated_host_id);
  1118. n = GST_create_neighbour (GST_host_list[delegated_host_id]);
  1119. ncc = GNUNET_new (struct NeighbourConnectCtxt);
  1120. ncc->n = n;
  1121. ncc->op_id = op_id;
  1122. ncc->client = client;
  1123. ncc->nh = GST_neighbour_get_connection (n,
  1124. &neighbour_connect_cb,
  1125. ncc);
  1126. ncc->timeout_task
  1127. = GNUNET_SCHEDULER_add_delayed (GST_timeout,
  1128. &timeout_neighbour_connect,
  1129. ncc);
  1130. GNUNET_CONTAINER_DLL_insert_tail (ncc_head,
  1131. ncc_tail,
  1132. ncc);
  1133. GNUNET_SERVICE_client_continue (client);
  1134. return;
  1135. }
  1136. if ((delegated_host_id < GST_slave_list_size) &&
  1137. (NULL != GST_slave_list[delegated_host_id]))
  1138. {
  1139. GNUNET_break (0);
  1140. GNUNET_SERVICE_client_drop (client);
  1141. return;
  1142. }
  1143. LOG_DEBUG ("Received request to start and establish a link to host %u\n",
  1144. delegated_host_id);
  1145. slave = GNUNET_new (struct Slave);
  1146. slave->host_id = delegated_host_id;
  1147. slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100,
  1148. GNUNET_NO);
  1149. slave_list_add (slave);
  1150. lcc = GNUNET_new (struct LinkControllersContext);
  1151. lcc->operation_id = op_id;
  1152. lcc->client = client;
  1153. slave->lcc = lcc;
  1154. slave->controller_proc
  1155. = GNUNET_TESTBED_controller_start (GST_context->master_ip,
  1156. GST_host_list[slave->host_id],
  1157. &slave_status_cb,
  1158. slave);
  1159. new_route = GNUNET_new (struct Route);
  1160. new_route->dest = delegated_host_id;
  1161. new_route->thru = GST_context->host_id;
  1162. route_list_add (new_route);
  1163. return;
  1164. }
  1165. /* Route the request */
  1166. if (slave_host_id >= route_list_size)
  1167. {
  1168. LOG (GNUNET_ERROR_TYPE_WARNING,
  1169. "No route towards slave host");
  1170. GNUNET_SERVICE_client_drop (client);
  1171. return;
  1172. }
  1173. lcf = GNUNET_new (struct LCFContext);
  1174. lcf->delegated_host_id = delegated_host_id;
  1175. lcf->slave_host_id = slave_host_id;
  1176. route = GST_find_dest_route (slave_host_id);
  1177. GNUNET_assert (NULL != route); /* because we add routes carefully */
  1178. GNUNET_assert (route->dest < GST_slave_list_size);
  1179. GNUNET_assert (NULL != GST_slave_list[route->dest]);
  1180. lcf->is_subordinate = msg->is_subordinate;
  1181. lcf->state = INIT;
  1182. lcf->operation_id = op_id;
  1183. lcf->gateway = GST_slave_list[route->dest];
  1184. lcf->client = client;
  1185. if (NULL == lcf_head)
  1186. {
  1187. GNUNET_assert (NULL == lcf_proc_task_id);
  1188. GNUNET_CONTAINER_DLL_insert_tail (lcf_head,
  1189. lcf_tail,
  1190. lcf);
  1191. lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task,
  1192. lcf);
  1193. }
  1194. else
  1195. {
  1196. GNUNET_CONTAINER_DLL_insert_tail (lcf_head,
  1197. lcf_tail,
  1198. lcf);
  1199. }
  1200. /* FIXME: Adding a new route should happen after the controllers are linked
  1201. * successfully */
  1202. if (1 != msg->is_subordinate)
  1203. {
  1204. GNUNET_SERVICE_client_continue (client);
  1205. return;
  1206. }
  1207. if ((delegated_host_id < route_list_size) &&
  1208. (NULL != route_list[delegated_host_id]))
  1209. {
  1210. GNUNET_break_op (0); /* Are you trying to link delegated host twice
  1211. * with is subordinate flag set to GNUNET_YES? */
  1212. GNUNET_SERVICE_client_drop (client);
  1213. return;
  1214. }
  1215. new_route = GNUNET_new (struct Route);
  1216. new_route->dest = delegated_host_id;
  1217. new_route->thru = route->dest;
  1218. route_list_add (new_route);
  1219. GNUNET_SERVICE_client_continue (client);
  1220. }
  1221. /**
  1222. * Clean up @a client handle if we stored any via #handle_link_controllers(),
  1223. * the given client disconnected.
  1224. *
  1225. * @param client the client that is history
  1226. */
  1227. void
  1228. GST_link_notify_disconnect (struct GNUNET_SERVICE_Client *client)
  1229. {
  1230. struct NeighbourConnectCtxt *ncc;
  1231. struct NeighbourConnectCtxt *nccn;
  1232. struct LCFContext *lcf;
  1233. struct LCFContext *lcfn;
  1234. for (ncc = ncc_head; NULL != ncc; ncc = nccn)
  1235. {
  1236. nccn = ncc->next;
  1237. if (ncc->client == client)
  1238. cleanup_ncc (ncc);
  1239. }
  1240. for (unsigned int i = 0; i < GST_slave_list_size; i++)
  1241. {
  1242. struct Slave *slave = GST_slave_list[i];
  1243. struct LinkControllersContext *lcc;
  1244. if (NULL == slave)
  1245. continue;
  1246. GNUNET_CONTAINER_multihashmap_iterate (slave->reghost_map,
  1247. &drop_client_entries,
  1248. client);
  1249. lcc = slave->lcc;
  1250. if (NULL == lcc)
  1251. continue;
  1252. if (lcc->client == client)
  1253. {
  1254. slave->lcc = NULL;
  1255. GNUNET_free (lcc);
  1256. }
  1257. }
  1258. for (lcf = lcf_head; NULL != lcf; lcf = lcfn)
  1259. {
  1260. lcfn = lcf->next;
  1261. if ((NULL != lcf) &&
  1262. (client == lcf->client))
  1263. {
  1264. if (NULL != lcf->op)
  1265. GNUNET_TESTBED_operation_done (lcf->op);
  1266. GNUNET_CONTAINER_DLL_remove (lcf_head,
  1267. lcf_tail,
  1268. lcf);
  1269. GNUNET_free (lcf);
  1270. }
  1271. }
  1272. }
  1273. /**
  1274. * Cleans up the queue used for forwarding link controllers requests
  1275. */
  1276. void
  1277. GST_free_lcf ()
  1278. {
  1279. struct LCFContext *lcf;
  1280. if (NULL != lcf_head)
  1281. {
  1282. if (NULL != lcf_proc_task_id)
  1283. {
  1284. GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
  1285. lcf_proc_task_id = NULL;
  1286. }
  1287. }
  1288. GNUNET_assert (NULL == lcf_proc_task_id);
  1289. for (lcf = lcf_head; NULL != lcf; lcf = lcf_head)
  1290. {
  1291. if (NULL != lcf->op)
  1292. GNUNET_TESTBED_operation_done (lcf->op);
  1293. if (NULL != lcf->timeout_task)
  1294. GNUNET_SCHEDULER_cancel (lcf->timeout_task);
  1295. GNUNET_CONTAINER_DLL_remove (lcf_head,
  1296. lcf_tail,
  1297. lcf);
  1298. GNUNET_free (lcf);
  1299. }
  1300. }