testbed_api_testbed.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456
  1. /*
  2. This file is part of GNUnet
  3. (C) 2008--2013 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. 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. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file testbed/testbed_api_testbed.c
  19. * @brief high-level testbed management
  20. * @author Christian Grothoff
  21. * @author Sree Harsha Totakura
  22. */
  23. #include "platform.h"
  24. #include "gnunet_util_lib.h"
  25. #include "gnunet_testbed_service.h"
  26. #include "testbed_api.h"
  27. #include "testbed_api_peers.h"
  28. #include "testbed_api_hosts.h"
  29. #include "testbed_api_topology.h"
  30. /**
  31. * Generic loggins shorthand
  32. */
  33. #define LOG(kind,...) \
  34. GNUNET_log_from (kind, "testbed-api-testbed", __VA_ARGS__)
  35. /**
  36. * Debug logging shortcut
  37. */
  38. #define DEBUG(...) \
  39. LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
  40. /**
  41. * The default setup timeout in seconds
  42. */
  43. #define DEFAULT_SETUP_TIMEOUT 300
  44. /**
  45. * Configuration section for testbed
  46. */
  47. #define TESTBED_CONFIG_SECTION "testbed"
  48. /**
  49. * Option string for the maximum number of edges a peer is permitted to have
  50. * while generating scale free topology
  51. */
  52. #define SCALE_FREE_CAP "SCALE_FREE_TOPOLOGY_CAP"
  53. /**
  54. * Option string for the number of edges to be established when adding a new
  55. * node to the scale free network
  56. */
  57. #define SCALE_FREE_M "SCALE_FREE_TOPOLOGY_M"
  58. /**
  59. * Context information for the operation we start
  60. */
  61. struct RunContextOperation
  62. {
  63. /**
  64. * The testbed operation handle
  65. */
  66. struct GNUNET_TESTBED_Operation *op;
  67. /**
  68. * Context information for GNUNET_TESTBED_run()
  69. */
  70. struct GNUNET_TESTBED_RunHandle *rc;
  71. /**
  72. * Closure
  73. */
  74. void *cls;
  75. };
  76. /**
  77. * States of RunContext
  78. */
  79. enum State
  80. {
  81. /**
  82. * Initial state
  83. */
  84. RC_INIT = 0,
  85. /**
  86. * Controllers on given hosts started and linked
  87. */
  88. RC_LINKED,
  89. /**
  90. * Peers are created
  91. */
  92. RC_PEERS_CREATED,
  93. /**
  94. * The testbed run is ready and the master callback can be called now. At this
  95. * time the peers are all started and if a topology is provided in the
  96. * configuration the topology would have been attempted
  97. */
  98. RC_READY,
  99. /* /\** */
  100. /* * Peers are stopped */
  101. /* *\/ */
  102. /* RC_PEERS_STOPPED, */
  103. /* /\** */
  104. /* * Peers are destroyed */
  105. /* *\/ */
  106. /* RC_PEERS_DESTROYED */
  107. /**
  108. * All peers shutdown (stopped and destroyed)
  109. */
  110. RC_PEERS_SHUTDOWN
  111. };
  112. /**
  113. * Context for host compability checks
  114. */
  115. struct CompatibilityCheckContext
  116. {
  117. /**
  118. * The run context
  119. */
  120. struct GNUNET_TESTBED_RunHandle *rc;
  121. /**
  122. * Handle for the compability check
  123. */
  124. struct GNUNET_TESTBED_HostHabitableCheckHandle *h;
  125. /**
  126. * Index of the host in the run context's hosts array
  127. */
  128. unsigned int index;
  129. };
  130. /**
  131. * Testbed Run Handle
  132. */
  133. struct GNUNET_TESTBED_RunHandle
  134. {
  135. /**
  136. * The controller handle
  137. */
  138. struct GNUNET_TESTBED_Controller *c;
  139. /**
  140. * The configuration of the controller. This is based on the cfg given to the
  141. * function GNUNET_TESTBED_run(). We also use this config as a template while
  142. * for peers
  143. */
  144. struct GNUNET_CONFIGURATION_Handle *cfg;
  145. /**
  146. * Handle to the host on which the controller runs
  147. */
  148. struct GNUNET_TESTBED_Host *h;
  149. /**
  150. * The handle to the controller process
  151. */
  152. struct GNUNET_TESTBED_ControllerProc *cproc;
  153. /**
  154. * The callback to use as controller callback
  155. */
  156. GNUNET_TESTBED_ControllerCallback cc;
  157. /**
  158. * The pointer to the controller callback
  159. */
  160. void *cc_cls;
  161. /**
  162. * The trusted IP string
  163. */
  164. char *trusted_ip;
  165. /**
  166. * TestMaster callback to call when testbed initialization is done
  167. */
  168. GNUNET_TESTBED_TestMaster test_master;
  169. /**
  170. * The closure for the TestMaster callback
  171. */
  172. void *test_master_cls;
  173. /**
  174. * A hashmap for operations started by us
  175. */
  176. struct GNUNET_CONTAINER_MultiHashMap32 *rcop_map;
  177. /**
  178. * An array of hosts loaded from the hostkeys file
  179. */
  180. struct GNUNET_TESTBED_Host **hosts;
  181. /**
  182. * Array of compatibility check contexts
  183. */
  184. struct CompatibilityCheckContext *hclist;
  185. /**
  186. * Array of peers which we create
  187. */
  188. struct GNUNET_TESTBED_Peer **peers;
  189. /**
  190. * The topology generation operation. Will be null if no topology is set in
  191. * the configuration
  192. */
  193. struct GNUNET_TESTBED_Operation *topology_operation;
  194. /**
  195. * The file containing topology data. Only used if the topology is set to 'FROM_FILE'
  196. */
  197. char *topo_file;
  198. /**
  199. * Host registration handle
  200. */
  201. struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
  202. /**
  203. * Profiling start time
  204. */
  205. struct GNUNET_TIME_Absolute pstart_time;
  206. /**
  207. * Host registration task
  208. */
  209. GNUNET_SCHEDULER_TaskIdentifier register_hosts_task;
  210. /**
  211. * Task to be run of a timeout
  212. */
  213. GNUNET_SCHEDULER_TaskIdentifier timeout_task;
  214. /**
  215. * Task run upon shutdown interrupts
  216. */
  217. GNUNET_SCHEDULER_TaskIdentifier interrupt_task;
  218. /**
  219. * The event mask for the controller
  220. */
  221. uint64_t event_mask;
  222. /**
  223. * State of this context
  224. */
  225. enum State state;
  226. /**
  227. * The topology which has to be achieved with the peers started in this context
  228. */
  229. enum GNUNET_TESTBED_TopologyOption topology;
  230. /**
  231. * Have we already shutdown
  232. */
  233. int shutdown;
  234. /**
  235. * Number of hosts in the given host file
  236. */
  237. unsigned int num_hosts;
  238. /**
  239. * Number of registered hosts. Also used as a counter while checking
  240. * habitabillity of hosts
  241. */
  242. unsigned int reg_hosts;
  243. /**
  244. * Current peer count for an operation; Set this to 0 and increment for each
  245. * successful operation on a peer
  246. */
  247. unsigned int peer_count;
  248. /**
  249. * number of peers to start
  250. */
  251. unsigned int num_peers;
  252. /**
  253. * Expected overlay connects. Should be zero if no topology is relavant
  254. */
  255. unsigned int num_oc;
  256. /**
  257. * Number of random links to established
  258. */
  259. unsigned int random_links;
  260. /**
  261. * the number of overlay link connection attempts that succeeded
  262. */
  263. unsigned int links_succeeded;
  264. /**
  265. * the number of overlay link connection attempts that failed
  266. */
  267. unsigned int links_failed;
  268. };
  269. /**
  270. * Return a 32-bit key from a pointer
  271. *
  272. * @param rcop the pointer
  273. * @return 32-bit key
  274. */
  275. static uint32_t
  276. rcop_key (void *rcop)
  277. {
  278. return * ((uint32_t *) &rcop);
  279. }
  280. /**
  281. * Context information used for finding a pointer in the rcop_map
  282. */
  283. struct SearchContext
  284. {
  285. /**
  286. * The operation pointer to look for
  287. */
  288. struct GNUNET_TESTBED_Operation *query;
  289. /**
  290. * The Run context operation which has the operation being queried
  291. */
  292. struct RunContextOperation *result;
  293. };
  294. /**
  295. * Iterator for searching over the elements matching a given query
  296. *
  297. * @param cls the SearchContext
  298. * @param key the 32-bit key
  299. * @param value the RunContextOperation element
  300. * @return GNUNET_YES to continue iteration; GNUNET_NO to cancel it
  301. */
  302. static int
  303. search_iterator (void *cls, uint32_t key, void *value)
  304. {
  305. struct RunContextOperation *rcop = value;
  306. struct SearchContext *sc = cls;
  307. GNUNET_assert (NULL != rcop);
  308. if (sc->query == rcop->op)
  309. {
  310. GNUNET_assert (NULL == sc->result);
  311. sc->result = rcop;
  312. return GNUNET_NO;
  313. }
  314. return GNUNET_YES;
  315. }
  316. /**
  317. * Initiate a search for the given operation in the rcop_map
  318. *
  319. * @param rc the RunContext whose rcop_map will be searched for the given
  320. * operation
  321. * @param op the given operation to search for
  322. * @return the matching RunContextOperation if found; NULL if not
  323. */
  324. static struct RunContextOperation *
  325. search_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct GNUNET_TESTBED_Operation *op)
  326. {
  327. struct SearchContext sc;
  328. sc.query = op;
  329. sc.result = NULL;
  330. if (GNUNET_SYSERR ==
  331. GNUNET_CONTAINER_multihashmap32_get_multiple (rc->rcop_map,
  332. rcop_key (op),
  333. &search_iterator,
  334. &sc))
  335. {
  336. GNUNET_assert (NULL != sc.result);
  337. return sc.result;
  338. }
  339. return NULL;
  340. }
  341. /**
  342. * Insert an RunContextOperation into the rcop_map of the given RunContext
  343. *
  344. * @param rc the RunContext into whose map is to be used for insertion
  345. * @param rcop the RunContextOperation to insert
  346. */
  347. static void
  348. insert_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct RunContextOperation *rcop)
  349. {
  350. GNUNET_assert (GNUNET_OK ==
  351. GNUNET_CONTAINER_multihashmap32_put (rc->rcop_map,
  352. rcop_key (rcop->op), rcop,
  353. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
  354. }
  355. /**
  356. * Remove a RunContextOperation from the rcop_map of the given RunContext
  357. *
  358. * @param rc the RunContext from whose map the given RunContextOperaton has to
  359. * be removed
  360. * @param rcop the RunContextOperation
  361. */
  362. static void
  363. remove_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct RunContextOperation *rcop)
  364. {
  365. GNUNET_assert (GNUNET_YES ==
  366. GNUNET_CONTAINER_multihashmap32_remove (rc->rcop_map,
  367. rcop_key (rcop->op),
  368. rcop));
  369. }
  370. /**
  371. * Assuming all peers have been destroyed cleanup run handle
  372. *
  373. * @param rc the run context
  374. */
  375. static void
  376. cleanup (struct GNUNET_TESTBED_RunHandle *rc)
  377. {
  378. unsigned int hid;
  379. GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rc->register_hosts_task);
  380. GNUNET_assert (NULL == rc->reg_handle);
  381. GNUNET_assert (NULL == rc->peers);
  382. GNUNET_assert (NULL == rc->hclist);
  383. GNUNET_assert (RC_PEERS_SHUTDOWN == rc->state);
  384. GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (rc->rcop_map));
  385. GNUNET_CONTAINER_multihashmap32_destroy (rc->rcop_map);
  386. if (NULL != rc->c)
  387. GNUNET_TESTBED_controller_disconnect (rc->c);
  388. if (NULL != rc->cproc)
  389. GNUNET_TESTBED_controller_stop (rc->cproc);
  390. if (NULL != rc->h)
  391. GNUNET_TESTBED_host_destroy (rc->h);
  392. for (hid = 0; hid < rc->num_hosts; hid++)
  393. GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
  394. GNUNET_free_non_null (rc->hosts);
  395. if (NULL != rc->cfg)
  396. GNUNET_CONFIGURATION_destroy (rc->cfg);
  397. GNUNET_free_non_null (rc->topo_file);
  398. GNUNET_free_non_null (rc->trusted_ip);
  399. GNUNET_free (rc);
  400. }
  401. /**
  402. * Iterator for cleaning up elements from rcop_map
  403. *
  404. * @param cls the RunContext
  405. * @param key the 32-bit key
  406. * @param value the RunContextOperation element
  407. * @return always GNUNET_YES
  408. */
  409. static int
  410. rcop_cleanup_iterator (void *cls, uint32_t key, void *value)
  411. {
  412. struct GNUNET_TESTBED_RunHandle *rc = cls;
  413. struct RunContextOperation *rcop = value;
  414. GNUNET_assert (rc == rcop->rc);
  415. remove_rcop (rc, rcop);
  416. GNUNET_TESTBED_operation_done (rcop->op);
  417. GNUNET_free (rcop);
  418. return GNUNET_YES;
  419. }
  420. /**
  421. * Cancels operations and tasks which are assigned to the given run context
  422. *
  423. * @param rc the RunContext
  424. */
  425. static void
  426. rc_cleanup_operations (struct GNUNET_TESTBED_RunHandle *rc)
  427. {
  428. struct CompatibilityCheckContext *hc;
  429. unsigned int nhost;
  430. if (NULL != rc->hclist)
  431. {
  432. for (nhost = 0; nhost < rc->num_hosts; nhost++)
  433. {
  434. hc = &rc->hclist[nhost];
  435. if (NULL != hc->h)
  436. GNUNET_TESTBED_is_host_habitable_cancel (hc->h);
  437. }
  438. GNUNET_free (rc->hclist);
  439. rc->hclist = NULL;
  440. }
  441. /* Stop register hosts task if it is running */
  442. if (GNUNET_SCHEDULER_NO_TASK != rc->register_hosts_task)
  443. {
  444. GNUNET_SCHEDULER_cancel (rc->register_hosts_task);
  445. rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK;
  446. }
  447. if (GNUNET_SCHEDULER_NO_TASK != rc->timeout_task)
  448. {
  449. GNUNET_SCHEDULER_cancel (rc->timeout_task);
  450. rc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
  451. }
  452. if (NULL != rc->reg_handle)
  453. {
  454. GNUNET_TESTBED_cancel_registration (rc->reg_handle);
  455. rc->reg_handle = NULL;
  456. }
  457. if (NULL != rc->topology_operation)
  458. {
  459. GNUNET_TESTBED_operation_done (rc->topology_operation);
  460. rc->topology_operation = NULL;
  461. }
  462. /* cancel any exiting operations */
  463. GNUNET_assert (GNUNET_SYSERR !=
  464. GNUNET_CONTAINER_multihashmap32_iterate (rc->rcop_map,
  465. &rcop_cleanup_iterator,
  466. rc));
  467. }
  468. /**
  469. * Cancels the scheduled interrupt task
  470. *
  471. * @param rc the run context
  472. */
  473. static void
  474. cancel_interrupt_task (struct GNUNET_TESTBED_RunHandle *rc)
  475. {
  476. GNUNET_SCHEDULER_cancel (rc->interrupt_task);
  477. rc->interrupt_task = GNUNET_SCHEDULER_NO_TASK;
  478. }
  479. /**
  480. * This callback will be called when all the operations are completed
  481. * (done/cancelled)
  482. *
  483. * @param cls run context
  484. */
  485. static void
  486. wait_op_completion (void *cls)
  487. {
  488. struct GNUNET_TESTBED_RunHandle *rc = cls;
  489. struct RunContextOperation *rcop;
  490. if ( (NULL == rc->cproc)
  491. || (NULL == rc->c)
  492. || (GNUNET_YES == rc->shutdown) )
  493. {
  494. if (NULL != rc->peers)
  495. {
  496. GNUNET_free (rc->peers);
  497. rc->peers = NULL;
  498. }
  499. goto cleanup_;
  500. }
  501. if (NULL == rc->peers)
  502. goto cleanup_;
  503. rc->shutdown = GNUNET_YES;
  504. rcop = GNUNET_new (struct RunContextOperation);
  505. rcop->rc = rc;
  506. rcop->op = GNUNET_TESTBED_shutdown_peers (rc->c, rcop, NULL, NULL);
  507. GNUNET_assert (NULL != rcop->op);
  508. DEBUG ("Shutting down peers\n");
  509. rc->pstart_time = GNUNET_TIME_absolute_get ();
  510. insert_rcop (rc, rcop);
  511. return;
  512. cleanup_:
  513. rc->state = RC_PEERS_SHUTDOWN;
  514. cancel_interrupt_task (rc);
  515. cleanup (rc);
  516. }
  517. /**
  518. * Task run upon interrupts (SIGINT, SIGTERM) and upon scheduler shutdown.
  519. *
  520. * @param cls the RunContext which has to be acted upon
  521. * @param tc the scheduler task context
  522. */
  523. static void
  524. interrupt (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  525. {
  526. struct GNUNET_TESTBED_RunHandle *rc = cls;
  527. struct GNUNET_TESTBED_Controller *c = rc->c;
  528. unsigned int size;
  529. /* reschedule */
  530. rc->interrupt_task = GNUNET_SCHEDULER_add_delayed
  531. (GNUNET_TIME_UNIT_FOREVER_REL, &interrupt, rc);
  532. rc_cleanup_operations (rc);
  533. if ( (GNUNET_NO == rc->shutdown)
  534. && (NULL != c)
  535. && (0 != (size = GNUNET_CONTAINER_multihashmap32_size (c->opc_map))))
  536. {
  537. LOG (GNUNET_ERROR_TYPE_WARNING, "Shutdown postponed as there are "
  538. "%u operations currently active\n", size);
  539. c->opcq_empty_cb = &wait_op_completion;
  540. c->opcq_empty_cls = rc;
  541. return;
  542. }
  543. wait_op_completion (rc);
  544. }
  545. /**
  546. * Function to return the string representation of the duration between current
  547. * time and `pstart_time' in `RunContext'
  548. *
  549. * @param rc the RunContext
  550. * @return the representation string; this is NOT reentrant
  551. */
  552. static const char *
  553. prof_time (struct GNUNET_TESTBED_RunHandle *rc)
  554. {
  555. struct GNUNET_TIME_Relative ptime;
  556. ptime = GNUNET_TIME_absolute_get_duration (rc->pstart_time);
  557. return GNUNET_STRINGS_relative_time_to_string (ptime, GNUNET_YES);
  558. }
  559. /**
  560. * Task for starting peers
  561. *
  562. * @param cls the RunHandle
  563. * @param tc the task context from scheduler
  564. */
  565. static void
  566. start_peers_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  567. {
  568. struct GNUNET_TESTBED_RunHandle *rc = cls;
  569. struct RunContextOperation *rcop;
  570. unsigned int peer;
  571. DEBUG ("Starting Peers\n");
  572. rc->pstart_time = GNUNET_TIME_absolute_get ();
  573. for (peer = 0; peer < rc->num_peers; peer++)
  574. {
  575. rcop = GNUNET_new (struct RunContextOperation);
  576. rcop->rc = rc;
  577. rcop->op = GNUNET_TESTBED_peer_start (NULL, rc->peers[peer], NULL, NULL);
  578. GNUNET_assert (NULL != rcop->op);
  579. rcop->cls = rc->peers[peer];
  580. insert_rcop (rc, rcop);
  581. }
  582. rc->peer_count = 0;
  583. }
  584. /**
  585. * Functions of this signature are called when a peer has been successfully
  586. * created
  587. *
  588. * @param cls the closure from GNUNET_TESTBED_peer_create()
  589. * @param peer the handle for the created peer; NULL on any error during
  590. * creation
  591. * @param emsg NULL if peer is not NULL; else MAY contain the error description
  592. */
  593. static void
  594. peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
  595. {
  596. struct RunContextOperation *rcop = cls;
  597. struct GNUNET_TESTBED_RunHandle *rc;
  598. GNUNET_assert (NULL != rcop);
  599. GNUNET_assert (NULL != (rc = rcop->rc));
  600. remove_rcop (rc, rcop);
  601. GNUNET_TESTBED_operation_done (rcop->op);
  602. GNUNET_free (rcop);
  603. if (NULL == peer)
  604. {
  605. if (NULL != emsg)
  606. LOG (GNUNET_ERROR_TYPE_ERROR, "Error while creating a peer: %s\n",
  607. emsg);
  608. GNUNET_SCHEDULER_shutdown ();
  609. return;
  610. }
  611. rc->peers[rc->peer_count] = peer;
  612. rc->peer_count++;
  613. if (rc->peer_count < rc->num_peers)
  614. return;
  615. DEBUG ("%u peers created in %s\n", rc->num_peers, prof_time (rc));
  616. rc->state = RC_PEERS_CREATED;
  617. GNUNET_SCHEDULER_add_now (&start_peers_task, rc);
  618. }
  619. /**
  620. * call test master callback
  621. *
  622. * @param rc the RunContext
  623. */
  624. static void
  625. call_master (struct GNUNET_TESTBED_RunHandle *rc)
  626. {
  627. GNUNET_SCHEDULER_cancel (rc->timeout_task);
  628. rc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
  629. if (NULL != rc->test_master)
  630. rc->test_master (rc->test_master_cls, rc, rc->num_peers, rc->peers,
  631. rc->links_succeeded, rc->links_failed);
  632. }
  633. /**
  634. * Callbacks of this type are called when topology configuration is completed
  635. *
  636. * @param cls the operation closure given to
  637. * GNUNET_TESTBED_overlay_configure_topology_va() and
  638. * GNUNET_TESTBED_overlay_configure() calls
  639. * @param nsuccess the number of successful overlay connects
  640. * @param nfailures the number of overlay connects which failed
  641. */
  642. static void
  643. topology_completion_callback (void *cls, unsigned int nsuccess,
  644. unsigned int nfailures)
  645. {
  646. struct GNUNET_TESTBED_RunHandle *rc = cls;
  647. DEBUG ("Overlay topology generated in %s\n", prof_time (rc));
  648. GNUNET_TESTBED_operation_done (rc->topology_operation);
  649. rc->topology_operation = NULL;
  650. rc->links_succeeded = nsuccess;
  651. rc->links_failed = nfailures;
  652. rc->state = RC_READY;
  653. call_master (rc);
  654. }
  655. /**
  656. * Function to create peers
  657. *
  658. * @param rc the RunContext
  659. */
  660. static void
  661. create_peers (struct GNUNET_TESTBED_RunHandle *rc)
  662. {
  663. struct RunContextOperation *rcop;
  664. unsigned int peer;
  665. DEBUG ("Creating peers\n");
  666. rc->pstart_time = GNUNET_TIME_absolute_get ();
  667. rc->peers =
  668. GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer *) * rc->num_peers);
  669. GNUNET_assert (NULL != rc->c);
  670. rc->peer_count = 0;
  671. for (peer = 0; peer < rc->num_peers; peer++)
  672. {
  673. rcop = GNUNET_new (struct RunContextOperation);
  674. rcop->rc = rc;
  675. rcop->op =
  676. GNUNET_TESTBED_peer_create (rc->c,
  677. (0 ==
  678. rc->num_hosts) ? rc->h : rc->hosts[peer %
  679. rc->num_hosts],
  680. rc->cfg, &peer_create_cb, rcop);
  681. GNUNET_assert (NULL != rcop->op);
  682. insert_rcop (rc, rcop);
  683. }
  684. }
  685. /**
  686. * Signature of the event handler function called by the
  687. * respective event controller.
  688. *
  689. * @param cls closure
  690. * @param event information about the event
  691. */
  692. static void
  693. event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
  694. {
  695. struct GNUNET_TESTBED_RunHandle *rc = cls;
  696. struct RunContextOperation *rcop;
  697. if (RC_INIT == rc->state)
  698. {
  699. switch (event->type)
  700. {
  701. case GNUNET_TESTBED_ET_OPERATION_FINISHED:
  702. rcop = event->op_cls;
  703. if (NULL != event->details.operation_finished.emsg)
  704. {
  705. LOG (GNUNET_ERROR_TYPE_ERROR, _("Linking controllers failed. Exiting"));
  706. GNUNET_SCHEDULER_shutdown ();
  707. }
  708. else
  709. rc->reg_hosts++;
  710. GNUNET_assert (event->op == rcop->op);
  711. remove_rcop (rc, rcop);
  712. GNUNET_TESTBED_operation_done (rcop->op);
  713. GNUNET_free (rcop);
  714. if (rc->reg_hosts == rc->num_hosts)
  715. {
  716. rc->state = RC_LINKED;
  717. create_peers (rc);
  718. }
  719. return;
  720. default:
  721. GNUNET_break (0);
  722. GNUNET_SCHEDULER_shutdown ();
  723. return;
  724. }
  725. }
  726. if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type)
  727. goto call_cc;
  728. if (NULL == (rcop = search_rcop (rc, event->op)))
  729. goto call_cc;
  730. remove_rcop (rc, rcop);
  731. GNUNET_TESTBED_operation_done (rcop->op);
  732. GNUNET_free (rcop);
  733. if ( (GNUNET_NO == rc->shutdown)
  734. && (NULL != event->details.operation_finished.emsg) )
  735. {
  736. LOG (GNUNET_ERROR_TYPE_ERROR, "A operation has failed with error: %s\n",
  737. event->details.operation_finished.emsg);
  738. GNUNET_SCHEDULER_shutdown ();
  739. return;
  740. }
  741. GNUNET_assert (GNUNET_YES == rc->shutdown);
  742. switch (rc->state)
  743. {
  744. case RC_LINKED:
  745. case RC_PEERS_CREATED:
  746. case RC_READY:
  747. rc->state = RC_PEERS_SHUTDOWN;
  748. GNUNET_free_non_null (rc->peers);
  749. rc->peers = NULL;
  750. DEBUG ("Peers shut down in %s\n", prof_time (rc));
  751. GNUNET_SCHEDULER_shutdown ();
  752. break;
  753. default:
  754. GNUNET_assert (0);
  755. }
  756. return;
  757. call_cc:
  758. if ((0 != (rc->event_mask & (1LL << event->type))) && (NULL != rc->cc))
  759. rc->cc (rc->cc_cls, event);
  760. if (GNUNET_TESTBED_ET_PEER_START != event->type)
  761. return;
  762. if (NULL == (rcop = search_rcop (rc, event->op))) /* Not our operation */
  763. return;
  764. remove_rcop (rc, rcop);
  765. GNUNET_TESTBED_operation_done (rcop->op);
  766. GNUNET_free (rcop);
  767. rc->peer_count++;
  768. if (rc->peer_count < rc->num_peers)
  769. return;
  770. DEBUG ("%u peers started in %s\n", rc->num_peers, prof_time (rc));
  771. if (GNUNET_TESTBED_TOPOLOGY_NONE != rc->topology)
  772. {
  773. switch (rc->topology)
  774. {
  775. case GNUNET_TESTBED_TOPOLOGY_NONE:
  776. GNUNET_assert (0);
  777. case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
  778. case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
  779. case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
  780. rc->topology_operation =
  781. GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
  782. rc->peers, &rc->num_oc,
  783. &topology_completion_callback,
  784. rc,
  785. rc->topology,
  786. rc->random_links,
  787. GNUNET_TESTBED_TOPOLOGY_OPTION_END);
  788. break;
  789. case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
  790. GNUNET_assert (NULL != rc->topo_file);
  791. rc->topology_operation =
  792. GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
  793. rc->peers, &rc->num_oc,
  794. &topology_completion_callback,
  795. rc,
  796. rc->topology,
  797. rc->topo_file,
  798. GNUNET_TESTBED_TOPOLOGY_OPTION_END);
  799. break;
  800. case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
  801. {
  802. unsigned long long number;
  803. unsigned int cap;
  804. GNUNET_assert (GNUNET_OK ==
  805. GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION,
  806. SCALE_FREE_CAP,
  807. &number));
  808. cap = (unsigned int) number;
  809. GNUNET_assert (GNUNET_OK ==
  810. GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION,
  811. SCALE_FREE_M,
  812. &number));
  813. rc->topology_operation =
  814. GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
  815. rc->peers, &rc->num_oc,
  816. &topology_completion_callback,
  817. rc,
  818. rc->topology,
  819. cap, /* uint16_t */
  820. (unsigned int) number, /* uint8_t */
  821. GNUNET_TESTBED_TOPOLOGY_OPTION_END);
  822. }
  823. break;
  824. default:
  825. rc->topology_operation =
  826. GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
  827. rc->peers, &rc->num_oc,
  828. &topology_completion_callback,
  829. rc,
  830. rc->topology,
  831. GNUNET_TESTBED_TOPOLOGY_OPTION_END);
  832. }
  833. if (NULL == rc->topology_operation)
  834. LOG (GNUNET_ERROR_TYPE_WARNING,
  835. "Not generating a topology. Check number of peers\n");
  836. else
  837. {
  838. DEBUG ("Creating overlay topology\n");
  839. rc->pstart_time = GNUNET_TIME_absolute_get ();
  840. return;
  841. }
  842. }
  843. rc->state = RC_READY;
  844. call_master (rc);
  845. }
  846. /**
  847. * Task to register all hosts available in the global host list
  848. *
  849. * @param cls the RunContext
  850. * @param tc the scheduler task context
  851. */
  852. static void
  853. register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
  854. /**
  855. * Callback which will be called to after a host registration succeeded or failed
  856. *
  857. * @param cls the closure
  858. * @param emsg the error message; NULL if host registration is successful
  859. */
  860. static void
  861. host_registration_completion (void *cls, const char *emsg)
  862. {
  863. struct GNUNET_TESTBED_RunHandle *rc = cls;
  864. rc->reg_handle = NULL;
  865. if (NULL != emsg)
  866. {
  867. LOG (GNUNET_ERROR_TYPE_WARNING,
  868. _("Host registration failed for a host. Error: %s\n"), emsg);
  869. GNUNET_SCHEDULER_shutdown ();
  870. return;
  871. }
  872. rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc);
  873. }
  874. /**
  875. * Task to register all hosts available in the global host list
  876. *
  877. * @param cls RunContext
  878. * @param tc the scheduler task context
  879. */
  880. static void
  881. register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  882. {
  883. struct GNUNET_TESTBED_RunHandle *rc = cls;
  884. struct RunContextOperation *rcop;
  885. unsigned int slave;
  886. rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK;
  887. if (rc->reg_hosts == rc->num_hosts)
  888. {
  889. DEBUG ("All hosts successfully registered\n");
  890. /* Start slaves */
  891. for (slave = 0; slave < rc->num_hosts; slave++)
  892. {
  893. rcop = GNUNET_new (struct RunContextOperation);
  894. rcop->rc = rc;
  895. rcop->op =
  896. GNUNET_TESTBED_controller_link (rcop, rc->c, rc->hosts[slave],
  897. rc->h, GNUNET_YES);
  898. GNUNET_assert (NULL != rcop->op);
  899. insert_rcop (rc, rcop);
  900. }
  901. rc->reg_hosts = 0;
  902. return;
  903. }
  904. rc->reg_handle =
  905. GNUNET_TESTBED_register_host (rc->c, rc->hosts[rc->reg_hosts],
  906. host_registration_completion, rc);
  907. rc->reg_hosts++;
  908. }
  909. /**
  910. * Callback to signal successfull startup of the controller process
  911. *
  912. * @param cls the closure from GNUNET_TESTBED_controller_start()
  913. * @param cfg the configuration with which the controller has been started;
  914. * NULL if status is not GNUNET_OK
  915. * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
  916. * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
  917. */
  918. static void
  919. controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
  920. int status)
  921. {
  922. struct GNUNET_TESTBED_RunHandle *rc = cls;
  923. uint64_t event_mask;
  924. if (status != GNUNET_OK)
  925. {
  926. rc->cproc = NULL;
  927. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  928. _("Controller crash detected. Shutting down.\n"));
  929. GNUNET_SCHEDULER_shutdown ();
  930. return;
  931. }
  932. GNUNET_CONFIGURATION_destroy (rc->cfg);
  933. rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
  934. event_mask = rc->event_mask;
  935. event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
  936. event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START);
  937. if (rc->topology < GNUNET_TESTBED_TOPOLOGY_NONE)
  938. event_mask |= GNUNET_TESTBED_ET_CONNECT;
  939. rc->c =
  940. GNUNET_TESTBED_controller_connect (rc->h, event_mask, &event_cb, rc);
  941. if (0 < rc->num_hosts)
  942. {
  943. rc->reg_hosts = 0;
  944. rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc);
  945. return;
  946. }
  947. rc->state = RC_LINKED;
  948. create_peers (rc);
  949. }
  950. /**
  951. * Callback function invoked for each interface found.
  952. *
  953. * @param cls closure
  954. * @param name name of the interface (can be NULL for unknown)
  955. * @param isDefault is this presumably the default interface
  956. * @param addr address of this interface (can be NULL for unknown or unassigned)
  957. * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
  958. * @param netmask the network mask (can be NULL for unknown or unassigned))
  959. * @param addrlen length of the address
  960. * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort
  961. */
  962. static int
  963. netint_proc (void *cls, const char *name, int isDefault,
  964. const struct sockaddr *addr, const struct sockaddr *broadcast_addr,
  965. const struct sockaddr *netmask, socklen_t addrlen)
  966. {
  967. struct GNUNET_TESTBED_RunHandle *rc = cls;
  968. char hostip[NI_MAXHOST];
  969. char *buf;
  970. if (sizeof (struct sockaddr_in) != addrlen)
  971. return GNUNET_OK; /* Only consider IPv4 for now */
  972. if (0 !=
  973. getnameinfo (addr, addrlen, hostip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST))
  974. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "getnameinfo");
  975. if (NULL == rc->trusted_ip)
  976. {
  977. rc->trusted_ip = GNUNET_strdup (hostip);
  978. return GNUNET_YES;
  979. }
  980. (void) GNUNET_asprintf (&buf, "%s; %s", rc->trusted_ip, hostip);
  981. GNUNET_free (rc->trusted_ip);
  982. rc->trusted_ip = buf;
  983. return GNUNET_YES;
  984. }
  985. /**
  986. * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to
  987. * inform whether the given host is habitable or not. The Handle returned by
  988. * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called
  989. *
  990. * @param cls NULL
  991. * @param host the host whose status is being reported; will be NULL if the host
  992. * given to GNUNET_TESTBED_is_host_habitable() is NULL
  993. * @param status GNUNET_YES if it is habitable; GNUNET_NO if not
  994. */
  995. static void
  996. host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host,
  997. int status)
  998. {
  999. struct CompatibilityCheckContext *hc = cls;
  1000. struct GNUNET_TESTBED_RunHandle *rc;
  1001. struct GNUNET_TESTBED_Host **old_hosts;
  1002. unsigned int nhost;
  1003. GNUNET_assert (NULL != (rc = hc->rc));
  1004. nhost = hc->index;
  1005. GNUNET_assert (nhost <= rc->num_hosts);
  1006. GNUNET_assert (host == rc->hosts[nhost]);
  1007. hc->h = NULL;
  1008. if (GNUNET_NO == status)
  1009. {
  1010. if ((NULL != host) && (NULL != GNUNET_TESTBED_host_get_hostname (host)))
  1011. LOG (GNUNET_ERROR_TYPE_ERROR, _("Host %s cannot start testbed\n"),
  1012. GNUNET_TESTBED_host_get_hostname (host));
  1013. else
  1014. LOG (GNUNET_ERROR_TYPE_ERROR,
  1015. _("Testbed cannot be started on localhost\n"));
  1016. GNUNET_SCHEDULER_shutdown ();
  1017. return;
  1018. }
  1019. rc->reg_hosts++;
  1020. if (rc->reg_hosts < rc->num_hosts)
  1021. return;
  1022. GNUNET_free (rc->hclist);
  1023. rc->hclist = NULL;
  1024. rc->h = rc->hosts[0];
  1025. rc->num_hosts--;
  1026. if (0 < rc->num_hosts)
  1027. {
  1028. old_hosts = rc->hosts;
  1029. rc->hosts =
  1030. GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Host *) * rc->num_hosts);
  1031. memcpy (rc->hosts, &old_hosts[1],
  1032. (sizeof (struct GNUNET_TESTBED_Host *) * rc->num_hosts));
  1033. GNUNET_free (old_hosts);
  1034. }
  1035. else
  1036. {
  1037. GNUNET_free (rc->hosts);
  1038. rc->hosts = NULL;
  1039. }
  1040. GNUNET_TESTBED_host_resolve_ (rc->h);
  1041. for (nhost = 0; nhost < rc->num_hosts; nhost++)
  1042. GNUNET_TESTBED_host_resolve_ (rc->hosts[nhost]);
  1043. GNUNET_OS_network_interfaces_list (netint_proc, rc);
  1044. if (NULL == rc->trusted_ip)
  1045. rc->trusted_ip = GNUNET_strdup ("127.0.0.1");
  1046. rc->cproc =
  1047. GNUNET_TESTBED_controller_start (rc->trusted_ip, rc->h,
  1048. &controller_status_cb, rc);
  1049. GNUNET_free (rc->trusted_ip);
  1050. rc->trusted_ip = NULL;
  1051. if (NULL == rc->cproc)
  1052. {
  1053. LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot start the master controller"));
  1054. GNUNET_SCHEDULER_shutdown ();
  1055. }
  1056. }
  1057. /**
  1058. * Task run upon timeout while setting up the testbed
  1059. *
  1060. * @param cls the RunContext
  1061. * @param tc the task context
  1062. */
  1063. static void
  1064. timeout_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  1065. {
  1066. struct GNUNET_TESTBED_RunHandle *rc = cls;
  1067. rc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
  1068. LOG (GNUNET_ERROR_TYPE_ERROR, _("Shutting down testbed due to timeout while setup.\n"));
  1069. GNUNET_SCHEDULER_shutdown ();
  1070. if (NULL != rc->test_master)
  1071. rc->test_master (rc->test_master_cls, rc, 0, NULL, 0, 0);
  1072. rc->test_master = NULL;
  1073. }
  1074. /**
  1075. * Convenience method for running a testbed with
  1076. * a single call. Underlay and overlay topology
  1077. * are configured using the "UNDERLAY" and "OVERLAY"
  1078. * options in the "[testbed]" section of the configuration\
  1079. * (with possible options given in "UNDERLAY_XXX" and/or
  1080. * "OVERLAY_XXX").
  1081. *
  1082. * The testbed is to be terminated using a call to
  1083. * "GNUNET_SCHEDULER_shutdown".
  1084. *
  1085. * @param host_filename name of the file with the 'hosts', NULL
  1086. * to run everything on 'localhost'
  1087. * @param cfg configuration to use (for testbed, controller and peers)
  1088. * @param num_peers number of peers to start; FIXME: maybe put that ALSO into cfg?
  1089. * @param event_mask bit mask with set of events to call 'cc' for;
  1090. * or-ed values of "1LL" shifted by the
  1091. * respective 'enum GNUNET_TESTBED_EventType'
  1092. * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...")
  1093. * @param cc controller callback to invoke on events; This callback is called
  1094. * for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't
  1095. * set in the event_mask as this is the only way get access to the
  1096. * handle of each peer
  1097. * @param cc_cls closure for cc
  1098. * @param test_master this callback will be called once the test is ready
  1099. * @param test_master_cls closure for 'test_master'.
  1100. */
  1101. void
  1102. GNUNET_TESTBED_run (const char *host_filename,
  1103. const struct GNUNET_CONFIGURATION_Handle *cfg,
  1104. unsigned int num_peers, uint64_t event_mask,
  1105. GNUNET_TESTBED_ControllerCallback cc, void *cc_cls,
  1106. GNUNET_TESTBED_TestMaster test_master,
  1107. void *test_master_cls)
  1108. {
  1109. struct GNUNET_TESTBED_RunHandle *rc;
  1110. char *topology;
  1111. struct CompatibilityCheckContext *hc;
  1112. struct GNUNET_TIME_Relative timeout;
  1113. unsigned long long number;
  1114. unsigned int hid;
  1115. unsigned int nhost;
  1116. GNUNET_assert (num_peers > 0);
  1117. rc = GNUNET_new (struct GNUNET_TESTBED_RunHandle);
  1118. rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
  1119. #if ENABLE_SUPERMUC
  1120. rc->num_hosts = GNUNET_TESTBED_hosts_load_from_loadleveler (rc->cfg,
  1121. &rc->hosts);
  1122. if (0 == rc->num_hosts)
  1123. {
  1124. LOG (GNUNET_ERROR_TYPE_WARNING,
  1125. _("No hosts loaded from LoadLeveler. Need at least one host\n"));
  1126. goto error_cleanup;
  1127. }
  1128. #else
  1129. if (NULL != host_filename)
  1130. {
  1131. rc->num_hosts =
  1132. GNUNET_TESTBED_hosts_load_from_file (host_filename, rc->cfg,
  1133. &rc->hosts);
  1134. if (0 == rc->num_hosts)
  1135. {
  1136. LOG (GNUNET_ERROR_TYPE_WARNING,
  1137. _("No hosts loaded. Need at least one host\n"));
  1138. goto error_cleanup;
  1139. }
  1140. }
  1141. else
  1142. rc->h = GNUNET_TESTBED_host_create (NULL, NULL, rc->cfg, 0);
  1143. #endif
  1144. rc->num_peers = num_peers;
  1145. rc->event_mask = event_mask;
  1146. rc->cc = cc;
  1147. rc->cc_cls = cc_cls;
  1148. rc->test_master = test_master;
  1149. rc->test_master_cls = test_master_cls;
  1150. rc->state = RC_INIT;
  1151. rc->topology = GNUNET_TESTBED_TOPOLOGY_NONE;
  1152. if (GNUNET_OK ==
  1153. GNUNET_CONFIGURATION_get_value_string (rc->cfg, TESTBED_CONFIG_SECTION,
  1154. "OVERLAY_TOPOLOGY", &topology))
  1155. {
  1156. if (GNUNET_NO == GNUNET_TESTBED_topology_get_ (&rc->topology, topology))
  1157. {
  1158. GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION,
  1159. "OVERLAY_TOPLOGY",
  1160. _
  1161. ("Specified topology must be supported by testbed"));
  1162. }
  1163. GNUNET_free (topology);
  1164. }
  1165. switch (rc->topology)
  1166. {
  1167. case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
  1168. case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
  1169. case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
  1170. if (GNUNET_OK !=
  1171. GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION,
  1172. "OVERLAY_RANDOM_LINKS",
  1173. &number))
  1174. {
  1175. /* OVERLAY option RANDOM & SMALL_WORLD_RING requires OVERLAY_RANDOM_LINKS
  1176. * option to be set to the number of random links to be established */
  1177. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION,
  1178. "OVERLAY_RANDOM_LINKS");
  1179. goto error_cleanup;
  1180. }
  1181. if (number > UINT32_MAX)
  1182. {
  1183. GNUNET_break (0); /* Too big number */
  1184. goto error_cleanup;
  1185. }
  1186. rc->random_links = (unsigned int) number;
  1187. break;
  1188. case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
  1189. if (GNUNET_OK !=
  1190. GNUNET_CONFIGURATION_get_value_filename (rc->cfg, TESTBED_CONFIG_SECTION,
  1191. "OVERLAY_TOPOLOGY_FILE",
  1192. &rc->topo_file))
  1193. {
  1194. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION,
  1195. "OVERLAY_TOPOLOGY_FILE");
  1196. goto error_cleanup;
  1197. }
  1198. goto warn_ignore;
  1199. case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
  1200. if (GNUNET_OK !=
  1201. GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION,
  1202. SCALE_FREE_CAP, &number))
  1203. {
  1204. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION,
  1205. SCALE_FREE_CAP);
  1206. goto error_cleanup;
  1207. }
  1208. if (UINT16_MAX < number)
  1209. {
  1210. LOG (GNUNET_ERROR_TYPE_ERROR,
  1211. _("Maximum number of edges a peer can have in a scale free topology"
  1212. " cannot be more than %u. Given `%s = %llu'"), UINT16_MAX,
  1213. SCALE_FREE_CAP, number);
  1214. goto error_cleanup;
  1215. }
  1216. if (GNUNET_OK !=
  1217. GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION,
  1218. SCALE_FREE_M, &number))
  1219. {
  1220. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, TESTBED_CONFIG_SECTION,
  1221. SCALE_FREE_M);
  1222. goto error_cleanup;
  1223. }
  1224. if (UINT8_MAX < number)
  1225. {
  1226. LOG (GNUNET_ERROR_TYPE_ERROR,
  1227. _("The number of edges that can established when adding a new node"
  1228. " to scale free topology cannot be more than %u. Given `%s = %llu'"),
  1229. UINT8_MAX, SCALE_FREE_M, number);
  1230. goto error_cleanup;
  1231. }
  1232. goto warn_ignore;
  1233. default:
  1234. warn_ignore:
  1235. /* Warn if OVERLAY_RANDOM_LINKS is present that it will be ignored */
  1236. if (GNUNET_YES ==
  1237. GNUNET_CONFIGURATION_have_value (rc->cfg, TESTBED_CONFIG_SECTION,
  1238. "OVERLAY_RANDOM_LINKS"))
  1239. LOG (GNUNET_ERROR_TYPE_WARNING,
  1240. "Ignoring value of `OVERLAY_RANDOM_LINKS' in given configuration\n");
  1241. break;
  1242. }
  1243. if (0 != rc->num_hosts)
  1244. {
  1245. rc->hclist = GNUNET_malloc (sizeof (struct CompatibilityCheckContext)
  1246. * rc->num_hosts);
  1247. for (nhost = 0; nhost < rc->num_hosts; nhost++)
  1248. {
  1249. hc = &rc->hclist[nhost];
  1250. hc->index = nhost;
  1251. hc->rc = rc;
  1252. hc->h = GNUNET_TESTBED_is_host_habitable (rc->hosts[nhost], rc->cfg,
  1253. &host_habitable_cb, hc);
  1254. if (NULL == hc->h)
  1255. {
  1256. GNUNET_break (0);
  1257. for (nhost = 0; nhost < rc->num_hosts; nhost++)
  1258. {
  1259. hc = &rc->hclist[nhost];
  1260. if (NULL != hc->h)
  1261. GNUNET_TESTBED_is_host_habitable_cancel (hc->h);
  1262. }
  1263. GNUNET_free (rc->hclist);
  1264. rc->hclist = NULL;
  1265. goto error_cleanup;
  1266. }
  1267. }
  1268. }
  1269. else
  1270. rc->cproc =
  1271. GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h,
  1272. &controller_status_cb, rc);
  1273. if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, TESTBED_CONFIG_SECTION,
  1274. "SETUP_TIMEOUT",
  1275. &timeout))
  1276. {
  1277. timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
  1278. DEFAULT_SETUP_TIMEOUT);
  1279. }
  1280. rc->rcop_map = GNUNET_CONTAINER_multihashmap32_create (256);
  1281. rc->timeout_task =
  1282. GNUNET_SCHEDULER_add_delayed (timeout, &timeout_task, rc);
  1283. rc->interrupt_task =
  1284. GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &interrupt,
  1285. rc);
  1286. return;
  1287. error_cleanup:
  1288. if (NULL != rc->h)
  1289. GNUNET_TESTBED_host_destroy (rc->h);
  1290. if (NULL != rc->hosts)
  1291. {
  1292. for (hid = 0; hid < rc->num_hosts; hid++)
  1293. if (NULL != rc->hosts[hid])
  1294. GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
  1295. GNUNET_free (rc->hosts);
  1296. }
  1297. if (NULL != rc->cfg)
  1298. GNUNET_CONFIGURATION_destroy (rc->cfg);
  1299. GNUNET_free (rc);
  1300. }
  1301. /**
  1302. * Obtain handle to the master controller from a testbed run. The handle
  1303. * returned should not be disconnected.
  1304. *
  1305. * @param h the testbed run handle
  1306. * @return handle to the master controller
  1307. */
  1308. struct GNUNET_TESTBED_Controller *
  1309. GNUNET_TESTBED_run_get_controller_handle (struct GNUNET_TESTBED_RunHandle *h)
  1310. {
  1311. return h->c;
  1312. }
  1313. /* end of testbed_api_testbed.c */