testbed_api_peers.c 29 KB

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