testbed_api_peers.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  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_peers.c
  19. * @brief management of the knowledge about peers in this library
  20. * (we know the peer ID, its host, pending operations, etc.)
  21. * @author Christian Grothoff
  22. * @author Sree Harsha Totakura
  23. */
  24. #include "platform.h"
  25. #include "testbed_api_peers.h"
  26. #include "testbed_api.h"
  27. #include "testbed.h"
  28. #include "testbed_api_hosts.h"
  29. #include "testbed_api_operations.h"
  30. /**
  31. * Peer list DLL head
  32. */
  33. static struct GNUNET_TESTBED_Peer *peer_list_head;
  34. /**
  35. * Peer list DLL tail
  36. */
  37. static struct GNUNET_TESTBED_Peer *peer_list_tail;
  38. /**
  39. * Adds a peer to the peer list
  40. *
  41. * @param peer the peer to add to the peer list
  42. */
  43. void
  44. GNUNET_TESTBED_peer_register_ (struct GNUNET_TESTBED_Peer *peer)
  45. {
  46. GNUNET_CONTAINER_DLL_insert_tail (peer_list_head, peer_list_tail, peer);
  47. }
  48. /**
  49. * Removes a peer from the peer list
  50. *
  51. * @param peer the peer to remove
  52. */
  53. void
  54. GNUNET_TESTBED_peer_deregister_ (struct GNUNET_TESTBED_Peer *peer)
  55. {
  56. GNUNET_CONTAINER_DLL_remove (peer_list_head, peer_list_tail, peer);
  57. }
  58. /**
  59. * Frees all peers
  60. */
  61. void
  62. GNUNET_TESTBED_cleanup_peers_ (void)
  63. {
  64. struct GNUNET_TESTBED_Peer *peer;
  65. while (NULL != (peer = peer_list_head))
  66. {
  67. GNUNET_TESTBED_peer_deregister_ (peer);
  68. GNUNET_free (peer);
  69. }
  70. }
  71. /**
  72. * Function to call to start a peer_create type operation once all
  73. * queues the operation is part of declare that the
  74. * operation can be activated.
  75. *
  76. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  77. */
  78. static void
  79. opstart_peer_create (void *cls)
  80. {
  81. struct OperationContext *opc = cls;
  82. struct PeerCreateData *data = opc->data;
  83. struct GNUNET_TESTBED_PeerCreateMessage *msg;
  84. char *config;
  85. char *xconfig;
  86. size_t c_size;
  87. size_t xc_size;
  88. uint16_t msize;
  89. GNUNET_assert (OP_PEER_CREATE == opc->type);
  90. GNUNET_assert (NULL != data);
  91. GNUNET_assert (NULL != data->peer);
  92. opc->state = OPC_STATE_STARTED;
  93. config = GNUNET_CONFIGURATION_serialize (data->cfg, &c_size);
  94. xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
  95. GNUNET_free (config);
  96. msize = xc_size + sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
  97. msg = GNUNET_realloc (xconfig, msize);
  98. memmove (&msg[1], msg, xc_size);
  99. msg->header.size = htons (msize);
  100. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER);
  101. msg->operation_id = GNUNET_htonll (opc->id);
  102. msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->peer->host));
  103. msg->peer_id = htonl (data->peer->unique_id);
  104. msg->config_size = htons ((uint16_t) c_size);
  105. GNUNET_TESTBED_insert_opc_ (opc->c, opc);
  106. GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
  107. }
  108. /**
  109. * Callback which will be called when peer_create type operation is released
  110. *
  111. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  112. */
  113. static void
  114. oprelease_peer_create (void *cls)
  115. {
  116. struct OperationContext *opc = cls;
  117. switch (opc->state)
  118. {
  119. case OPC_STATE_STARTED:
  120. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  121. /* No break we continue flow */
  122. case OPC_STATE_INIT:
  123. GNUNET_free (((struct PeerCreateData *) opc->data)->peer);
  124. GNUNET_free (opc->data);
  125. break;
  126. case OPC_STATE_FINISHED:
  127. break;
  128. }
  129. GNUNET_free (opc);
  130. }
  131. /**
  132. * Function called when a peer destroy operation is ready
  133. *
  134. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  135. */
  136. static void
  137. opstart_peer_destroy (void *cls)
  138. {
  139. struct OperationContext *opc = cls;
  140. struct GNUNET_TESTBED_Peer *peer = opc->data;
  141. struct GNUNET_TESTBED_PeerDestroyMessage *msg;
  142. GNUNET_assert (OP_PEER_DESTROY == opc->type);
  143. GNUNET_assert (NULL != peer);
  144. opc->state = OPC_STATE_STARTED;
  145. msg = GNUNET_new (struct GNUNET_TESTBED_PeerDestroyMessage);
  146. msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerDestroyMessage));
  147. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER);
  148. msg->peer_id = htonl (peer->unique_id);
  149. msg->operation_id = GNUNET_htonll (opc->id);
  150. GNUNET_TESTBED_insert_opc_ (opc->c, opc);
  151. GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
  152. }
  153. /**
  154. * Callback which will be called when peer_create type operation is released
  155. *
  156. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  157. */
  158. static void
  159. oprelease_peer_destroy (void *cls)
  160. {
  161. struct OperationContext *opc = cls;
  162. switch (opc->state)
  163. {
  164. case OPC_STATE_STARTED:
  165. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  166. /* no break; continue */
  167. case OPC_STATE_INIT:
  168. break;
  169. case OPC_STATE_FINISHED:
  170. break;
  171. }
  172. GNUNET_free (opc);
  173. }
  174. /**
  175. * Function called when a peer start operation is ready
  176. *
  177. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  178. */
  179. static void
  180. opstart_peer_start (void *cls)
  181. {
  182. struct OperationContext *opc = cls;
  183. struct GNUNET_TESTBED_PeerStartMessage *msg;
  184. struct PeerEventData *data;
  185. struct GNUNET_TESTBED_Peer *peer;
  186. GNUNET_assert (OP_PEER_START == opc->type);
  187. GNUNET_assert (NULL != (data = opc->data));
  188. GNUNET_assert (NULL != (peer = data->peer));
  189. GNUNET_assert ((TESTBED_PS_CREATED == peer->state) || (TESTBED_PS_STOPPED == peer->state));
  190. opc->state = OPC_STATE_STARTED;
  191. msg = GNUNET_new (struct GNUNET_TESTBED_PeerStartMessage);
  192. msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerStartMessage));
  193. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_START_PEER);
  194. msg->peer_id = htonl (peer->unique_id);
  195. msg->operation_id = GNUNET_htonll (opc->id);
  196. GNUNET_TESTBED_insert_opc_ (opc->c, opc);
  197. GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
  198. }
  199. /**
  200. * Callback which will be called when peer start type operation is released
  201. *
  202. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  203. */
  204. static void
  205. oprelease_peer_start (void *cls)
  206. {
  207. struct OperationContext *opc = cls;
  208. switch (opc->state)
  209. {
  210. case OPC_STATE_STARTED:
  211. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  212. /* no break; continue */
  213. case OPC_STATE_INIT:
  214. GNUNET_free (opc->data);
  215. break;
  216. case OPC_STATE_FINISHED:
  217. break;
  218. }
  219. GNUNET_free (opc);
  220. }
  221. /**
  222. * Function called when a peer stop operation is ready
  223. *
  224. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  225. */
  226. static void
  227. opstart_peer_stop (void *cls)
  228. {
  229. struct OperationContext *opc = cls;
  230. struct GNUNET_TESTBED_PeerStopMessage *msg;
  231. struct PeerEventData *data;
  232. struct GNUNET_TESTBED_Peer *peer;
  233. GNUNET_assert (NULL != (data = opc->data));
  234. GNUNET_assert (NULL != (peer = data->peer));
  235. GNUNET_assert (TESTBED_PS_STARTED == peer->state);
  236. opc->state = OPC_STATE_STARTED;
  237. msg = GNUNET_new (struct GNUNET_TESTBED_PeerStopMessage);
  238. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER);
  239. msg->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerStopMessage));
  240. msg->peer_id = htonl (peer->unique_id);
  241. msg->operation_id = GNUNET_htonll (opc->id);
  242. GNUNET_TESTBED_insert_opc_ (opc->c, opc);
  243. GNUNET_TESTBED_queue_message_ (peer->controller, &msg->header);
  244. }
  245. /**
  246. * Callback which will be called when peer stop type operation is released
  247. *
  248. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  249. */
  250. static void
  251. oprelease_peer_stop (void *cls)
  252. {
  253. struct OperationContext *opc = cls;
  254. switch (opc->state)
  255. {
  256. case OPC_STATE_STARTED:
  257. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  258. /* no break; continue */
  259. case OPC_STATE_INIT:
  260. GNUNET_free (opc->data);
  261. break;
  262. case OPC_STATE_FINISHED:
  263. break;
  264. }
  265. GNUNET_free (opc);
  266. }
  267. /**
  268. * Generate PeerGetConfigurationMessage
  269. *
  270. * @param peer_id the id of the peer whose information we have to get
  271. * @param operation_id the ip of the operation that should be represented in the
  272. * message
  273. * @return the PeerGetConfigurationMessage
  274. */
  275. struct GNUNET_TESTBED_PeerGetConfigurationMessage *
  276. GNUNET_TESTBED_generate_peergetconfig_msg_ (uint32_t peer_id,
  277. uint64_t operation_id)
  278. {
  279. struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
  280. msg =
  281. GNUNET_malloc (sizeof
  282. (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
  283. msg->header.size =
  284. htons (sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage));
  285. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION);
  286. msg->peer_id = htonl (peer_id);
  287. msg->operation_id = GNUNET_htonll (operation_id);
  288. return msg;
  289. }
  290. /**
  291. * Function called when a peer get information operation is ready
  292. *
  293. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  294. */
  295. static void
  296. opstart_peer_getinfo (void *cls)
  297. {
  298. struct OperationContext *opc = cls;
  299. struct PeerInfoData *data = opc->data;
  300. struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
  301. GNUNET_assert (NULL != data);
  302. opc->state = OPC_STATE_STARTED;
  303. msg =
  304. GNUNET_TESTBED_generate_peergetconfig_msg_ (data->peer->unique_id,
  305. opc->id);
  306. GNUNET_TESTBED_insert_opc_ (opc->c, opc);
  307. GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
  308. }
  309. /**
  310. * Callback which will be called when peer stop type operation is released
  311. *
  312. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  313. */
  314. static void
  315. oprelease_peer_getinfo (void *cls)
  316. {
  317. struct OperationContext *opc = cls;
  318. struct GNUNET_TESTBED_PeerInformation *data;
  319. switch (opc->state)
  320. {
  321. case OPC_STATE_STARTED:
  322. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  323. /* no break; continue */
  324. case OPC_STATE_INIT:
  325. GNUNET_free (opc->data);
  326. break;
  327. case OPC_STATE_FINISHED:
  328. data = opc->data;
  329. GNUNET_assert (NULL != data);
  330. switch (data->pit)
  331. {
  332. case GNUNET_TESTBED_PIT_CONFIGURATION:
  333. if (NULL != data->result.cfg)
  334. GNUNET_CONFIGURATION_destroy (data->result.cfg);
  335. break;
  336. case GNUNET_TESTBED_PIT_IDENTITY:
  337. GNUNET_free (data->result.id);
  338. break;
  339. default:
  340. GNUNET_assert (0); /* We should never reach here */
  341. }
  342. GNUNET_free (data);
  343. break;
  344. }
  345. GNUNET_free (opc);
  346. }
  347. /**
  348. * Function called when a overlay connect operation is ready
  349. *
  350. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  351. */
  352. static void
  353. opstart_overlay_connect (void *cls)
  354. {
  355. struct OperationContext *opc = cls;
  356. struct GNUNET_TESTBED_OverlayConnectMessage *msg;
  357. struct OverlayConnectData *data;
  358. opc->state = OPC_STATE_STARTED;
  359. data = opc->data;
  360. GNUNET_assert (NULL != data);
  361. msg = GNUNET_new (struct GNUNET_TESTBED_OverlayConnectMessage);
  362. msg->header.size =
  363. htons (sizeof (struct GNUNET_TESTBED_OverlayConnectMessage));
  364. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT);
  365. msg->peer1 = htonl (data->p1->unique_id);
  366. msg->peer2 = htonl (data->p2->unique_id);
  367. msg->operation_id = GNUNET_htonll (opc->id);
  368. msg->peer2_host_id = htonl (GNUNET_TESTBED_host_get_id_ (data->p2->host));
  369. GNUNET_TESTBED_insert_opc_ (opc->c, opc);
  370. GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
  371. }
  372. /**
  373. * Callback which will be called when overlay connect operation is released
  374. *
  375. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  376. */
  377. static void
  378. oprelease_overlay_connect (void *cls)
  379. {
  380. struct OperationContext *opc = cls;
  381. struct OverlayConnectData *data;
  382. data = opc->data;
  383. switch (opc->state)
  384. {
  385. case OPC_STATE_INIT:
  386. break;
  387. case OPC_STATE_STARTED:
  388. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  389. break;
  390. case OPC_STATE_FINISHED:
  391. break;
  392. }
  393. GNUNET_free (data);
  394. GNUNET_free (opc);
  395. }
  396. /**
  397. * Function called when a peer reconfigure operation is ready
  398. *
  399. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  400. */
  401. static void
  402. opstart_peer_reconfigure (void *cls)
  403. {
  404. struct OperationContext *opc = cls;
  405. struct PeerReconfigureData *data = opc->data;
  406. struct GNUNET_TESTBED_PeerReconfigureMessage *msg;
  407. char *xconfig;
  408. size_t xc_size;
  409. uint16_t msize;
  410. opc->state = OPC_STATE_STARTED;
  411. GNUNET_assert (NULL != data);
  412. xc_size = GNUNET_TESTBED_compress_config_ (data->config, data->cfg_size,
  413. &xconfig);
  414. GNUNET_free (data->config);
  415. data->config = NULL;
  416. GNUNET_assert (xc_size <= UINT16_MAX);
  417. msize = (uint16_t) xc_size +
  418. sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage);
  419. msg = GNUNET_realloc (xconfig, msize);
  420. (void) memmove (&msg[1], msg, xc_size);
  421. msg->header.size = htons (msize);
  422. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER);
  423. msg->peer_id = htonl (data->peer->unique_id);
  424. msg->operation_id = GNUNET_htonll (opc->id);
  425. msg->config_size = htons (data->cfg_size);
  426. GNUNET_free (data);
  427. opc->data = NULL;
  428. GNUNET_TESTBED_insert_opc_ (opc->c, opc);
  429. GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
  430. }
  431. /**
  432. * Callback which will be called when a peer reconfigure operation is released
  433. *
  434. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  435. */
  436. static void
  437. oprelease_peer_reconfigure (void *cls)
  438. {
  439. struct OperationContext *opc = cls;
  440. struct PeerReconfigureData *data = opc->data;
  441. switch (opc->state)
  442. {
  443. case OPC_STATE_INIT:
  444. GNUNET_free (data->config);
  445. GNUNET_free (data);
  446. break;
  447. case OPC_STATE_STARTED:
  448. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  449. break;
  450. case OPC_STATE_FINISHED:
  451. break;
  452. }
  453. GNUNET_free (opc);
  454. }
  455. /**
  456. * Lookup a peer by ID.
  457. *
  458. * @param id global peer ID assigned to the peer
  459. * @return handle to the host, NULL on error
  460. */
  461. struct GNUNET_TESTBED_Peer *
  462. GNUNET_TESTBED_peer_lookup_by_id_ (uint32_t id)
  463. {
  464. GNUNET_break (0);
  465. return NULL;
  466. }
  467. /**
  468. * Create the given peer at the specified host using the given
  469. * controller. If the given controller is not running on the target
  470. * host, it should find or create a controller at the target host and
  471. * delegate creating the peer. Explicit delegation paths can be setup
  472. * using 'GNUNET_TESTBED_controller_link'. If no explicit delegation
  473. * path exists, a direct link with a subordinate controller is setup
  474. * for the first delegated peer to a particular host; the subordinate
  475. * controller is then destroyed once the last peer that was delegated
  476. * to the remote host is stopped.
  477. *
  478. * Creating the peer only creates the handle to manipulate and further
  479. * configure the peer; use "GNUNET_TESTBED_peer_start" and
  480. * "GNUNET_TESTBED_peer_stop" to actually start/stop the peer's
  481. * processes.
  482. *
  483. * Note that the given configuration will be adjusted by the
  484. * controller to avoid port/path conflicts with other peers.
  485. * The "final" configuration can be obtained using
  486. * 'GNUNET_TESTBED_peer_get_information'.
  487. *
  488. * @param controller controller process to use
  489. * @param host host to run the peer on; cannot be NULL
  490. * @param cfg Template configuration to use for the peer. Should exist until
  491. * operation is cancelled or GNUNET_TESTBED_operation_done() is called
  492. * @param cb the callback to call when the peer has been created
  493. * @param cls the closure to the above callback
  494. * @return the operation handle
  495. */
  496. struct GNUNET_TESTBED_Operation *
  497. GNUNET_TESTBED_peer_create (struct GNUNET_TESTBED_Controller *controller,
  498. struct GNUNET_TESTBED_Host *host,
  499. const struct GNUNET_CONFIGURATION_Handle *cfg,
  500. GNUNET_TESTBED_PeerCreateCallback cb, void *cls)
  501. {
  502. struct GNUNET_TESTBED_Peer *peer;
  503. struct PeerCreateData *data;
  504. struct OperationContext *opc;
  505. static uint32_t id_gen;
  506. peer = GNUNET_new (struct GNUNET_TESTBED_Peer);
  507. peer->controller = controller;
  508. peer->host = host;
  509. peer->unique_id = id_gen++;
  510. peer->state = TESTBED_PS_INVALID;
  511. data = GNUNET_new (struct PeerCreateData);
  512. data->host = host;
  513. data->cfg = cfg;
  514. data->cb = cb;
  515. data->cls = cls;
  516. data->peer = peer;
  517. opc = GNUNET_new (struct OperationContext);
  518. opc->c = controller;
  519. opc->data = data;
  520. opc->id = GNUNET_TESTBED_get_next_op_id (controller);
  521. opc->type = OP_PEER_CREATE;
  522. opc->op =
  523. GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_create,
  524. &oprelease_peer_create);
  525. GNUNET_TESTBED_operation_queue_insert_ (controller->opq_parallel_operations,
  526. opc->op);
  527. GNUNET_TESTBED_operation_begin_wait_ (opc->op);
  528. return opc->op;
  529. }
  530. /**
  531. * Start the given peer.
  532. *
  533. * @param op_cls the closure for this operation; will be set in
  534. * event->details.operation_finished.op_cls when this operation fails.
  535. * @param peer peer to start
  536. * @param pcc function to call upon completion
  537. * @param pcc_cls closure for 'pcc'
  538. * @return handle to the operation
  539. */
  540. struct GNUNET_TESTBED_Operation *
  541. GNUNET_TESTBED_peer_start (void *op_cls, struct GNUNET_TESTBED_Peer *peer,
  542. GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls)
  543. {
  544. struct OperationContext *opc;
  545. struct PeerEventData *data;
  546. data = GNUNET_new (struct PeerEventData);
  547. data->peer = peer;
  548. data->pcc = pcc;
  549. data->pcc_cls = pcc_cls;
  550. opc = GNUNET_new (struct OperationContext);
  551. opc->c = peer->controller;
  552. opc->data = data;
  553. opc->op_cls = op_cls;
  554. opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
  555. opc->type = OP_PEER_START;
  556. opc->op =
  557. GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_start,
  558. &oprelease_peer_start);
  559. GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
  560. opc->op);
  561. GNUNET_TESTBED_operation_begin_wait_ (opc->op);
  562. return opc->op;
  563. }
  564. /**
  565. * Stop the given peer. The handle remains valid (use
  566. * "GNUNET_TESTBED_peer_destroy" to fully clean up the
  567. * state of the peer).
  568. *
  569. * @param op_cls the closure for this operation; will be set in the event
  570. * information
  571. * @param peer peer to stop
  572. * @param pcc function to call upon completion
  573. * @param pcc_cls closure for 'pcc'
  574. * @return handle to the operation
  575. */
  576. struct GNUNET_TESTBED_Operation *
  577. GNUNET_TESTBED_peer_stop (void *op_cls,
  578. struct GNUNET_TESTBED_Peer *peer,
  579. GNUNET_TESTBED_PeerChurnCallback pcc, void *pcc_cls)
  580. {
  581. struct OperationContext *opc;
  582. struct PeerEventData *data;
  583. data = GNUNET_new (struct PeerEventData);
  584. data->peer = peer;
  585. data->pcc = pcc;
  586. data->pcc_cls = pcc_cls;
  587. opc = GNUNET_new (struct OperationContext);
  588. opc->c = peer->controller;
  589. opc->data = data;
  590. opc->op_cls = op_cls;
  591. opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
  592. opc->type = OP_PEER_STOP;
  593. opc->op =
  594. GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_stop,
  595. &oprelease_peer_stop);
  596. GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
  597. opc->op);
  598. GNUNET_TESTBED_operation_begin_wait_ (opc->op);
  599. return opc->op;
  600. }
  601. /**
  602. * Request information about a peer. The controller callback will not be called
  603. * with event type GNUNET_TESTBED_ET_OPERATION_FINISHED when result for this
  604. * operation is available. Instead, the GNUNET_TESTBED_PeerInfoCallback() will
  605. * be called.
  606. * The peer information in the callback is valid until the operation is canceled.
  607. *
  608. * @param peer peer to request information about
  609. * @param pit desired information
  610. * @param cb the convenience callback to be called when results for this
  611. * operation are available
  612. * @param cb_cls the closure for the above callback
  613. * @return handle to the operation
  614. */
  615. struct GNUNET_TESTBED_Operation *
  616. GNUNET_TESTBED_peer_get_information (struct GNUNET_TESTBED_Peer *peer,
  617. enum GNUNET_TESTBED_PeerInformationType
  618. pit, GNUNET_TESTBED_PeerInfoCallback cb,
  619. void *cb_cls)
  620. {
  621. struct OperationContext *opc;
  622. struct PeerInfoData *data;
  623. GNUNET_assert (GNUNET_TESTBED_PIT_GENERIC != pit);
  624. GNUNET_assert (NULL != cb);
  625. data = GNUNET_new (struct PeerInfoData);
  626. data->peer = peer;
  627. data->pit = pit;
  628. data->cb = cb;
  629. data->cb_cls = cb_cls;
  630. opc = GNUNET_new (struct OperationContext);
  631. opc->c = peer->controller;
  632. opc->data = data;
  633. opc->type = OP_PEER_INFO;
  634. opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
  635. opc->op =
  636. GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_getinfo,
  637. &oprelease_peer_getinfo);
  638. GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
  639. opc->op);
  640. GNUNET_TESTBED_operation_begin_wait_ (opc->op);
  641. return opc->op;
  642. }
  643. /**
  644. * Change peer configuration. Must only be called while the
  645. * peer is stopped. Ports and paths cannot be changed this
  646. * way.
  647. *
  648. * @param peer peer to change configuration for
  649. * @param cfg new configuration (differences to existing
  650. * configuration only)
  651. * @return handle to the operation
  652. */
  653. struct GNUNET_TESTBED_Operation *
  654. GNUNET_TESTBED_peer_update_configuration (struct GNUNET_TESTBED_Peer *peer,
  655. const struct
  656. GNUNET_CONFIGURATION_Handle *cfg)
  657. {
  658. struct OperationContext *opc;
  659. struct PeerReconfigureData *data;
  660. size_t csize;
  661. data = GNUNET_new (struct PeerReconfigureData);
  662. data->peer = peer;
  663. data->config = GNUNET_CONFIGURATION_serialize (cfg, &csize);
  664. if (NULL == data->config)
  665. {
  666. GNUNET_free (data);
  667. return NULL;
  668. }
  669. if (csize > UINT16_MAX)
  670. {
  671. GNUNET_break (0);
  672. GNUNET_free (data->config);
  673. GNUNET_free (data);
  674. return NULL;
  675. }
  676. data->cfg_size = (uint16_t) csize;
  677. opc = GNUNET_new (struct OperationContext);
  678. opc->c = peer->controller;
  679. opc->data = data;
  680. opc->type = OP_PEER_RECONFIGURE;
  681. opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
  682. opc->op =
  683. GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_reconfigure,
  684. &oprelease_peer_reconfigure);
  685. GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
  686. opc->op);
  687. GNUNET_TESTBED_operation_begin_wait_ (opc->op);
  688. return opc->op;
  689. }
  690. /**
  691. * Destroy the given peer; the peer should have been
  692. * stopped first (if it was started).
  693. *
  694. * @param peer peer to stop
  695. * @return handle to the operation
  696. */
  697. struct GNUNET_TESTBED_Operation *
  698. GNUNET_TESTBED_peer_destroy (struct GNUNET_TESTBED_Peer *peer)
  699. {
  700. struct OperationContext *opc;
  701. opc = GNUNET_new (struct OperationContext);
  702. opc->data = peer;
  703. opc->c = peer->controller;
  704. opc->id = GNUNET_TESTBED_get_next_op_id (peer->controller);
  705. opc->type = OP_PEER_DESTROY;
  706. opc->op =
  707. GNUNET_TESTBED_operation_create_ (opc, &opstart_peer_destroy,
  708. &oprelease_peer_destroy);
  709. GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
  710. opc->op);
  711. GNUNET_TESTBED_operation_begin_wait_ (opc->op);
  712. return opc->op;
  713. }
  714. /**
  715. * Manipulate the P2P underlay topology by configuring a link
  716. * between two peers.
  717. *
  718. * @param op_cls closure argument to give with the operation event
  719. * @param p1 first peer
  720. * @param p2 second peer
  721. * @param co option to change
  722. * @param ... option-specific values
  723. * @return handle to the operation, NULL if configuring the link at this
  724. * time is not allowed
  725. */
  726. struct GNUNET_TESTBED_Operation *
  727. GNUNET_TESTBED_underlay_configure_link (void *op_cls,
  728. struct GNUNET_TESTBED_Peer *p1,
  729. struct GNUNET_TESTBED_Peer *p2,
  730. enum GNUNET_TESTBED_ConnectOption co,
  731. ...)
  732. {
  733. GNUNET_break (0);
  734. return NULL;
  735. }
  736. /**
  737. * Both peers must have been started before calling this function.
  738. * This function then obtains a HELLO from 'p1', gives it to 'p2'
  739. * and asks 'p2' to connect to 'p1'.
  740. *
  741. * @param op_cls closure argument to give with the operation event
  742. * @param cb the callback to call when this operation has finished
  743. * @param cb_cls the closure for the above callback
  744. * @param p1 first peer
  745. * @param p2 second peer
  746. * @return handle to the operation, NULL if connecting these two
  747. * peers is fundamentally not possible at this time (peers
  748. * not running or underlay disallows)
  749. */
  750. struct GNUNET_TESTBED_Operation *
  751. GNUNET_TESTBED_overlay_connect (void *op_cls,
  752. GNUNET_TESTBED_OperationCompletionCallback cb,
  753. void *cb_cls, struct GNUNET_TESTBED_Peer *p1,
  754. struct GNUNET_TESTBED_Peer *p2)
  755. {
  756. struct OperationContext *opc;
  757. struct OverlayConnectData *data;
  758. GNUNET_assert ((TESTBED_PS_STARTED == p1->state) && (TESTBED_PS_STARTED == p2->state));
  759. data = GNUNET_new (struct OverlayConnectData);
  760. data->p1 = p1;
  761. data->p2 = p2;
  762. data->cb = cb;
  763. data->cb_cls = cb_cls;
  764. opc = GNUNET_new (struct OperationContext);
  765. opc->data = data;
  766. opc->c = p1->controller;
  767. opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
  768. opc->type = OP_OVERLAY_CONNECT;
  769. opc->op_cls = op_cls;
  770. opc->op =
  771. GNUNET_TESTBED_operation_create_ (opc, &opstart_overlay_connect,
  772. &oprelease_overlay_connect);
  773. GNUNET_TESTBED_host_queue_oc_ (p1->host, opc->op);
  774. GNUNET_TESTBED_operation_begin_wait_ (opc->op);
  775. return opc->op;
  776. }
  777. /**
  778. * Function called when a peer manage service operation is ready
  779. *
  780. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  781. */
  782. static void
  783. opstart_manage_service (void *cls)
  784. {
  785. struct OperationContext *opc = cls;
  786. struct ManageServiceData *data = opc->data;
  787. struct GNUNET_TESTBED_ManagePeerServiceMessage *msg;
  788. GNUNET_assert (NULL != data);
  789. msg = GNUNET_malloc (data->msize);
  790. msg->header.size = htons (data->msize);
  791. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE);
  792. msg->peer_id = htonl (data->peer->unique_id);
  793. msg->operation_id = GNUNET_htonll (opc->id);
  794. msg->start = (uint8_t) data->start;
  795. (void) memcpy (&msg[1], data->service_name, data->msize
  796. - sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage));
  797. GNUNET_free (data->service_name);
  798. data->service_name = NULL;
  799. opc->state = OPC_STATE_STARTED;
  800. GNUNET_TESTBED_insert_opc_ (opc->c, opc);
  801. GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
  802. }
  803. /**
  804. * Callback which will be called when peer manage server operation is released
  805. *
  806. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  807. */
  808. static void
  809. oprelease_manage_service (void *cls)
  810. {
  811. struct OperationContext *opc = cls;
  812. struct ManageServiceData *data;
  813. data = opc->data;
  814. switch (opc->state)
  815. {
  816. case OPC_STATE_STARTED:
  817. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  818. break;
  819. case OPC_STATE_INIT:
  820. GNUNET_assert (NULL != data);
  821. GNUNET_free (data->service_name);
  822. break;
  823. case OPC_STATE_FINISHED:
  824. break;
  825. }
  826. GNUNET_free_non_null (data);
  827. GNUNET_free (opc);
  828. }
  829. /**
  830. * Start or stop given service at a peer. This should not be called to
  831. * start/stop the peer's ARM service. Use GNUNET_TESTBED_peer_start(),
  832. * GNUNET_TESTBED_peer_stop() for starting/stopping peer's ARM service. Success
  833. * or failure of the generated operation is signalled through the controller
  834. * event callback and/or operation completion callback.
  835. *
  836. * @param op_cls the closure for the operation
  837. * @param peer the peer whose service is to be started/stopped
  838. * @param service_name the name of the service
  839. * @param cb the operation completion callback
  840. * @param cb_cls the closure for the operation completion callback
  841. * @param start 1 to start the service; 0 to stop the service
  842. * @return an operation handle; NULL upon error (peer not running)
  843. */
  844. struct GNUNET_TESTBED_Operation *
  845. GNUNET_TESTBED_peer_manage_service (void *op_cls,
  846. struct GNUNET_TESTBED_Peer *peer,
  847. const char *service_name,
  848. GNUNET_TESTBED_OperationCompletionCallback cb,
  849. void *cb_cls,
  850. unsigned int start)
  851. {
  852. struct ManageServiceData *data;
  853. struct OperationContext *opc;
  854. size_t msize;
  855. GNUNET_assert (TESTBED_PS_STARTED == peer->state); /* peer is not running? */
  856. msize = strlen (service_name) + 1;
  857. msize += sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage);
  858. if (GNUNET_SERVER_MAX_MESSAGE_SIZE < msize)
  859. return NULL;
  860. data = GNUNET_new (struct ManageServiceData);
  861. data->cb = cb;
  862. data->cb_cls = cb_cls;
  863. data->peer = peer;
  864. data->service_name = GNUNET_strdup (service_name);
  865. data->start = start;
  866. data->msize = (uint16_t) msize;
  867. opc = GNUNET_new (struct OperationContext);
  868. opc->data = data;
  869. opc->c = peer->controller;
  870. opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
  871. opc->type = OP_MANAGE_SERVICE;
  872. opc->op_cls = op_cls;
  873. opc->op =
  874. GNUNET_TESTBED_operation_create_ (opc, &opstart_manage_service,
  875. &oprelease_manage_service);
  876. GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
  877. opc->op);
  878. GNUNET_TESTBED_operation_begin_wait_ (opc->op);
  879. return opc->op;
  880. }
  881. /* end of testbed_api_peers.c */