testbed_api_peers.c 29 KB

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