testbed_api.c 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173
  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.c
  19. * @brief API for accessing the GNUnet testing service.
  20. * This library is supposed to make it easier to write
  21. * testcases and script large-scale benchmarks.
  22. * @author Christian Grothoff
  23. * @author Sree Harsha Totakura
  24. */
  25. #include "platform.h"
  26. #include "gnunet_testbed_service.h"
  27. #include "gnunet_core_service.h"
  28. #include "gnunet_constants.h"
  29. #include "gnunet_transport_service.h"
  30. #include "gnunet_hello_lib.h"
  31. #include <zlib.h>
  32. #include "testbed.h"
  33. #include "testbed_api.h"
  34. #include "testbed_api_hosts.h"
  35. #include "testbed_api_peers.h"
  36. #include "testbed_api_operations.h"
  37. #include "testbed_api_sd.h"
  38. /**
  39. * Generic logging shorthand
  40. */
  41. #define LOG(kind, ...) \
  42. GNUNET_log_from (kind, "testbed-api", __VA_ARGS__)
  43. /**
  44. * Debug logging
  45. */
  46. #define LOG_DEBUG(...) \
  47. LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
  48. /**
  49. * Relative time seconds shorthand
  50. */
  51. #define TIME_REL_SECS(sec) \
  52. GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
  53. /**
  54. * Default server message sending retry timeout
  55. */
  56. #define TIMEOUT_REL TIME_REL_SECS(1)
  57. /**
  58. * The message queue for sending messages to the controller service
  59. */
  60. struct MessageQueue
  61. {
  62. /**
  63. * The message to be sent
  64. */
  65. struct GNUNET_MessageHeader *msg;
  66. /**
  67. * next pointer for DLL
  68. */
  69. struct MessageQueue *next;
  70. /**
  71. * prev pointer for DLL
  72. */
  73. struct MessageQueue *prev;
  74. };
  75. /**
  76. * Context data for forwarded Operation
  77. */
  78. struct ForwardedOperationData
  79. {
  80. /**
  81. * The callback to call when reply is available
  82. */
  83. GNUNET_CLIENT_MessageHandler cc;
  84. /**
  85. * The closure for the above callback
  86. */
  87. void *cc_cls;
  88. };
  89. /**
  90. * Context data for get slave config operations
  91. */
  92. struct GetSlaveConfigData
  93. {
  94. /**
  95. * The id of the slave controller
  96. */
  97. uint32_t slave_id;
  98. };
  99. /**
  100. * Context data for controller link operations
  101. */
  102. struct ControllerLinkData
  103. {
  104. /**
  105. * The controller link message
  106. */
  107. struct GNUNET_TESTBED_ControllerLinkRequest *msg;
  108. /**
  109. * The id of the host which is hosting the controller to be linked
  110. */
  111. uint32_t host_id;
  112. };
  113. /**
  114. * Date context for OP_SHUTDOWN_PEERS operations
  115. */
  116. struct ShutdownPeersData
  117. {
  118. /**
  119. * The operation completion callback to call
  120. */
  121. GNUNET_TESTBED_OperationCompletionCallback cb;
  122. /**
  123. * The closure for the above callback
  124. */
  125. void *cb_cls;
  126. };
  127. /**
  128. * An entry in the stack for keeping operations which are about to expire
  129. */
  130. struct ExpireOperationEntry
  131. {
  132. /**
  133. * DLL head; new entries are to be inserted here
  134. */
  135. struct ExpireOperationEntry *next;
  136. /**
  137. * DLL tail; entries are deleted from here
  138. */
  139. struct ExpireOperationEntry *prev;
  140. /**
  141. * The operation. This will be a dangling pointer when the operation is freed
  142. */
  143. const struct GNUNET_TESTBED_Operation *op;
  144. };
  145. /**
  146. * DLL head for list of operations marked for expiry
  147. */
  148. static struct ExpireOperationEntry *exop_head;
  149. /**
  150. * DLL tail for list of operation marked for expiry
  151. */
  152. static struct ExpireOperationEntry *exop_tail;
  153. /**
  154. * Inserts an operation into the list of operations marked for expiry
  155. *
  156. * @param op the operation to insert
  157. */
  158. static void
  159. exop_insert (struct GNUNET_TESTBED_Operation *op)
  160. {
  161. struct ExpireOperationEntry *entry;
  162. entry = GNUNET_new (struct ExpireOperationEntry);
  163. entry->op = op;
  164. GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry);
  165. }
  166. /**
  167. * Checks if an operation is present in the list of operations marked for
  168. * expiry. If the operation is found, it and the tail of operations after it
  169. * are removed from the list.
  170. *
  171. * @param op the operation to check
  172. * @return GNUNET_NO if the operation is not present in the list; GNUNET_YES if
  173. * the operation is found in the list (the operation is then removed
  174. * from the list -- calling this function again with the same
  175. * paramenter will return GNUNET_NO)
  176. */
  177. static int
  178. exop_check (const struct GNUNET_TESTBED_Operation *const op)
  179. {
  180. struct ExpireOperationEntry *entry;
  181. struct ExpireOperationEntry *entry2;
  182. int found;
  183. found = GNUNET_NO;
  184. entry = exop_head;
  185. while (NULL != entry)
  186. {
  187. if (op == entry->op)
  188. {
  189. found = GNUNET_YES;
  190. break;
  191. }
  192. entry = entry->next;
  193. }
  194. if (GNUNET_NO == found)
  195. return GNUNET_NO;
  196. /* Truncate the tail */
  197. while (NULL != entry)
  198. {
  199. entry2 = entry->next;
  200. GNUNET_CONTAINER_DLL_remove (exop_head, exop_tail, entry);
  201. GNUNET_free (entry);
  202. entry = entry2;
  203. }
  204. return GNUNET_YES;
  205. }
  206. /**
  207. * Context information to be used while searching for operation contexts
  208. */
  209. struct SearchContext
  210. {
  211. /**
  212. * The result of the search
  213. */
  214. struct OperationContext *opc;
  215. /**
  216. * The id of the operation context we are searching for
  217. */
  218. uint64_t id;
  219. };
  220. /**
  221. * Search iterator for searching an operation context
  222. *
  223. * @param cls the serach context
  224. * @param key current key code
  225. * @param value value in the hash map
  226. * @return GNUNET_YES if we should continue to
  227. * iterate,
  228. * GNUNET_NO if not.
  229. */
  230. static int
  231. opc_search_iterator (void *cls, uint32_t key, void *value)
  232. {
  233. struct SearchContext *sc = cls;
  234. struct OperationContext *opc = value;
  235. GNUNET_assert (NULL != opc);
  236. GNUNET_assert (NULL == sc->opc);
  237. if (opc->id != sc->id)
  238. return GNUNET_YES;
  239. sc->opc = opc;
  240. return GNUNET_NO;
  241. }
  242. /**
  243. * Returns the operation context with the given id if found in the Operation
  244. * context queues of the controller
  245. *
  246. * @param c the controller whose operation context map is searched
  247. * @param id the id which has to be checked
  248. * @return the matching operation context; NULL if no match found
  249. */
  250. static struct OperationContext *
  251. find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
  252. {
  253. struct SearchContext sc;
  254. sc.id = id;
  255. sc.opc = NULL;
  256. GNUNET_assert (NULL != c->opc_map);
  257. if (GNUNET_SYSERR !=
  258. GNUNET_CONTAINER_multihashmap32_get_multiple (c->opc_map, (uint32_t) id,
  259. &opc_search_iterator, &sc))
  260. return NULL;
  261. return sc.opc;
  262. }
  263. /**
  264. * Inserts the given operation context into the operation context map of the
  265. * given controller. Creates the operation context map if one does not exist
  266. * for the controller
  267. *
  268. * @param c the controller
  269. * @param opc the operation context to be inserted
  270. */
  271. void
  272. GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c,
  273. struct OperationContext *opc)
  274. {
  275. if (NULL == c->opc_map)
  276. c->opc_map = GNUNET_CONTAINER_multihashmap32_create (256);
  277. GNUNET_assert (GNUNET_OK ==
  278. GNUNET_CONTAINER_multihashmap32_put (c->opc_map,
  279. (uint32_t) opc->id, opc,
  280. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
  281. }
  282. /**
  283. * Removes the given operation context from the operation context map of the
  284. * given controller
  285. *
  286. * @param c the controller
  287. * @param opc the operation context to remove
  288. */
  289. void
  290. GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c,
  291. struct OperationContext *opc)
  292. {
  293. GNUNET_assert (NULL != c->opc_map);
  294. GNUNET_assert (GNUNET_YES ==
  295. GNUNET_CONTAINER_multihashmap32_remove (c->opc_map,
  296. (uint32_t) opc->id,
  297. opc));
  298. if ( (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
  299. && (NULL != c->opcq_empty_cb) )
  300. c->opcq_empty_cb (c->opcq_empty_cls);
  301. }
  302. /**
  303. * Handler for forwarded operations
  304. *
  305. * @param c the controller handle
  306. * @param opc the opearation context
  307. * @param msg the message
  308. */
  309. static void
  310. handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
  311. struct OperationContext *opc,
  312. const struct GNUNET_MessageHeader *msg)
  313. {
  314. struct ForwardedOperationData *fo_data;
  315. fo_data = opc->data;
  316. if (NULL != fo_data->cc)
  317. fo_data->cc (fo_data->cc_cls, msg);
  318. GNUNET_TESTBED_remove_opc_ (c, opc);
  319. GNUNET_free (fo_data);
  320. GNUNET_free (opc);
  321. }
  322. /**
  323. * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
  324. * controller (testbed service)
  325. *
  326. * @param c the controller handler
  327. * @param msg message received
  328. * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
  329. * not
  330. */
  331. static int
  332. handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
  333. const struct
  334. GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
  335. {
  336. struct OperationContext *opc;
  337. GNUNET_TESTBED_OperationCompletionCallback op_comp_cb;
  338. void *op_comp_cb_cls;
  339. struct GNUNET_TESTBED_EventInformation event;
  340. uint64_t op_id;
  341. op_id = GNUNET_ntohll (msg->operation_id);
  342. LOG_DEBUG ("Operation %lu successful\n", op_id);
  343. if (NULL == (opc = find_opc (c, op_id)))
  344. {
  345. LOG_DEBUG ("Operation not found\n");
  346. return GNUNET_YES;
  347. }
  348. event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
  349. event.op = opc->op;
  350. event.op_cls = opc->op_cls;
  351. event.details.operation_finished.emsg = NULL;
  352. event.details.operation_finished.generic = NULL;
  353. op_comp_cb = NULL;
  354. op_comp_cb_cls = NULL;
  355. switch (opc->type)
  356. {
  357. case OP_FORWARDED:
  358. {
  359. handle_forwarded_operation_msg (c, opc,
  360. (const struct GNUNET_MessageHeader *) msg);
  361. return GNUNET_YES;
  362. }
  363. break;
  364. case OP_PEER_DESTROY:
  365. {
  366. struct GNUNET_TESTBED_Peer *peer;
  367. peer = opc->data;
  368. GNUNET_TESTBED_peer_deregister_ (peer);
  369. GNUNET_free (peer);
  370. opc->data = NULL;
  371. //PEERDESTROYDATA
  372. }
  373. break;
  374. case OP_SHUTDOWN_PEERS:
  375. {
  376. struct ShutdownPeersData *data;
  377. data = opc->data;
  378. op_comp_cb = data->cb;
  379. op_comp_cb_cls = data->cb_cls;
  380. GNUNET_free (data);
  381. opc->data = NULL;
  382. GNUNET_TESTBED_cleanup_peers_ ();
  383. }
  384. break;
  385. case OP_MANAGE_SERVICE:
  386. {
  387. struct ManageServiceData *data;
  388. GNUNET_assert (NULL != (data = opc->data));
  389. op_comp_cb = data->cb;
  390. op_comp_cb_cls = data->cb_cls;
  391. GNUNET_free (data);
  392. opc->data = NULL;
  393. }
  394. break;
  395. case OP_PEER_RECONFIGURE:
  396. break;
  397. default:
  398. GNUNET_assert (0);
  399. }
  400. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  401. opc->state = OPC_STATE_FINISHED;
  402. exop_insert (event.op);
  403. if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
  404. {
  405. if (NULL != c->cc)
  406. c->cc (c->cc_cls, &event);
  407. if (GNUNET_NO == exop_check (event.op))
  408. return GNUNET_YES;
  409. }
  410. else
  411. LOG_DEBUG ("Not calling callback\n");
  412. if (NULL != op_comp_cb)
  413. op_comp_cb (op_comp_cb_cls, event.op, NULL);
  414. /* You could have marked the operation as done by now */
  415. GNUNET_break (GNUNET_NO == exop_check (event.op));
  416. return GNUNET_YES;
  417. }
  418. /**
  419. * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
  420. * controller (testbed service)
  421. *
  422. * @param c the controller handle
  423. * @param msg message received
  424. * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
  425. * not
  426. */
  427. static int
  428. handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
  429. const struct
  430. GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
  431. {
  432. struct OperationContext *opc;
  433. struct PeerCreateData *data;
  434. struct GNUNET_TESTBED_Peer *peer;
  435. struct GNUNET_TESTBED_Operation *op;
  436. GNUNET_TESTBED_PeerCreateCallback cb;
  437. void *cls;
  438. uint64_t op_id;
  439. GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
  440. ntohs (msg->header.size));
  441. op_id = GNUNET_ntohll (msg->operation_id);
  442. if (NULL == (opc = find_opc (c, op_id)))
  443. {
  444. LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
  445. return GNUNET_YES;
  446. }
  447. if (OP_FORWARDED == opc->type)
  448. {
  449. handle_forwarded_operation_msg (c, opc,
  450. (const struct GNUNET_MessageHeader *) msg);
  451. return GNUNET_YES;
  452. }
  453. GNUNET_assert (OP_PEER_CREATE == opc->type);
  454. GNUNET_assert (NULL != opc->data);
  455. data = opc->data;
  456. GNUNET_assert (NULL != data->peer);
  457. peer = data->peer;
  458. GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
  459. peer->state = TESTBED_PS_CREATED;
  460. GNUNET_TESTBED_peer_register_ (peer);
  461. cb = data->cb;
  462. cls = data->cls;
  463. op = opc->op;
  464. GNUNET_free (opc->data);
  465. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  466. opc->state = OPC_STATE_FINISHED;
  467. exop_insert (op);
  468. if (NULL != cb)
  469. cb (cls, peer, NULL);
  470. /* You could have marked the operation as done by now */
  471. GNUNET_break (GNUNET_NO == exop_check (op));
  472. return GNUNET_YES;
  473. }
  474. /**
  475. * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
  476. * controller (testbed service)
  477. *
  478. * @param c the controller handler
  479. * @param msg message received
  480. * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
  481. * not
  482. */
  483. static int
  484. handle_peer_event (struct GNUNET_TESTBED_Controller *c,
  485. const struct GNUNET_TESTBED_PeerEventMessage *msg)
  486. {
  487. struct OperationContext *opc;
  488. struct GNUNET_TESTBED_Peer *peer;
  489. struct PeerEventData *data;
  490. GNUNET_TESTBED_PeerChurnCallback pcc;
  491. void *pcc_cls;
  492. struct GNUNET_TESTBED_EventInformation event;
  493. uint64_t op_id;
  494. uint64_t mask;
  495. GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
  496. ntohs (msg->header.size));
  497. op_id = GNUNET_ntohll (msg->operation_id);
  498. if (NULL == (opc = find_opc (c, op_id)))
  499. {
  500. LOG_DEBUG ("Operation not found\n");
  501. return GNUNET_YES;
  502. }
  503. if (OP_FORWARDED == opc->type)
  504. {
  505. handle_forwarded_operation_msg (c, opc,
  506. (const struct GNUNET_MessageHeader *) msg);
  507. return GNUNET_YES;
  508. }
  509. GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
  510. data = opc->data;
  511. GNUNET_assert (NULL != data);
  512. peer = data->peer;
  513. GNUNET_assert (NULL != peer);
  514. event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
  515. event.op = opc->op;
  516. event.op_cls = opc->op_cls;
  517. switch (event.type)
  518. {
  519. case GNUNET_TESTBED_ET_PEER_START:
  520. peer->state = TESTBED_PS_STARTED;
  521. event.details.peer_start.host = peer->host;
  522. event.details.peer_start.peer = peer;
  523. break;
  524. case GNUNET_TESTBED_ET_PEER_STOP:
  525. peer->state = TESTBED_PS_STOPPED;
  526. event.details.peer_stop.peer = peer;
  527. break;
  528. default:
  529. GNUNET_assert (0); /* We should never reach this state */
  530. }
  531. pcc = data->pcc;
  532. pcc_cls = data->pcc_cls;
  533. GNUNET_free (data);
  534. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  535. opc->state = OPC_STATE_FINISHED;
  536. exop_insert (event.op);
  537. mask = 1LL << GNUNET_TESTBED_ET_PEER_START;
  538. mask |= 1LL << GNUNET_TESTBED_ET_PEER_STOP;
  539. if (0 != (mask & c->event_mask))
  540. {
  541. if (NULL != c->cc)
  542. c->cc (c->cc_cls, &event);
  543. if (GNUNET_NO == exop_check (event.op))
  544. return GNUNET_YES;
  545. }
  546. if (NULL != pcc)
  547. pcc (pcc_cls, NULL);
  548. /* You could have marked the operation as done by now */
  549. GNUNET_break (GNUNET_NO == exop_check (event.op));
  550. return GNUNET_YES;
  551. }
  552. /**
  553. * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
  554. * controller (testbed service)
  555. *
  556. * @param c the controller handler
  557. * @param msg message received
  558. * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
  559. * not
  560. */
  561. static int
  562. handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
  563. const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
  564. {
  565. struct OperationContext *opc;
  566. struct OverlayConnectData *data;
  567. GNUNET_TESTBED_OperationCompletionCallback cb;
  568. void *cb_cls;
  569. struct GNUNET_TESTBED_EventInformation event;
  570. uint64_t op_id;
  571. uint64_t mask;
  572. op_id = GNUNET_ntohll (msg->operation_id);
  573. if (NULL == (opc = find_opc (c, op_id)))
  574. {
  575. LOG_DEBUG ("Operation not found\n");
  576. return GNUNET_YES;
  577. }
  578. if (OP_FORWARDED == opc->type)
  579. {
  580. handle_forwarded_operation_msg (c, opc,
  581. (const struct GNUNET_MessageHeader *) msg);
  582. return GNUNET_YES;
  583. }
  584. GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
  585. GNUNET_assert (NULL != (data = opc->data));
  586. GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
  587. (ntohl (msg->peer2) == data->p2->unique_id));
  588. event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
  589. event.op = opc->op;
  590. event.op_cls = opc->op_cls;
  591. switch (event.type)
  592. {
  593. case GNUNET_TESTBED_ET_CONNECT:
  594. event.details.peer_connect.peer1 = data->p1;
  595. event.details.peer_connect.peer2 = data->p2;
  596. break;
  597. case GNUNET_TESTBED_ET_DISCONNECT:
  598. GNUNET_assert (0); /* FIXME: implement */
  599. break;
  600. default:
  601. GNUNET_assert (0); /* Should never reach here */
  602. break;
  603. }
  604. cb = data->cb;
  605. cb_cls = data->cb_cls;
  606. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  607. opc->state = OPC_STATE_FINISHED;
  608. exop_insert (event.op);
  609. mask = 1LL << GNUNET_TESTBED_ET_CONNECT;
  610. mask |= 1LL << GNUNET_TESTBED_ET_DISCONNECT;
  611. if (0 != (mask & c->event_mask))
  612. {
  613. if (NULL != c->cc)
  614. c->cc (c->cc_cls, &event);
  615. if (GNUNET_NO == exop_check (event.op))
  616. return GNUNET_YES;
  617. }
  618. if (NULL != cb)
  619. cb (cb_cls, opc->op, NULL);
  620. /* You could have marked the operation as done by now */
  621. GNUNET_break (GNUNET_NO == exop_check (event.op));
  622. return GNUNET_YES;
  623. }
  624. /**
  625. * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
  626. * controller (testbed service)
  627. *
  628. * @param c the controller handler
  629. * @param msg message received
  630. * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
  631. * not
  632. */
  633. static int
  634. handle_peer_config (struct GNUNET_TESTBED_Controller *c,
  635. const struct
  636. GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
  637. {
  638. struct OperationContext *opc;
  639. struct GNUNET_TESTBED_Peer *peer;
  640. struct PeerInfoData *data;
  641. struct GNUNET_TESTBED_PeerInformation *pinfo;
  642. GNUNET_TESTBED_PeerInfoCallback cb;
  643. void *cb_cls;
  644. uint64_t op_id;
  645. op_id = GNUNET_ntohll (msg->operation_id);
  646. if (NULL == (opc = find_opc (c, op_id)))
  647. {
  648. LOG_DEBUG ("Operation not found\n");
  649. return GNUNET_YES;
  650. }
  651. if (OP_FORWARDED == opc->type)
  652. {
  653. handle_forwarded_operation_msg (c, opc,
  654. (const struct GNUNET_MessageHeader *) msg);
  655. return GNUNET_YES;
  656. }
  657. data = opc->data;
  658. GNUNET_assert (NULL != data);
  659. peer = data->peer;
  660. GNUNET_assert (NULL != peer);
  661. GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
  662. pinfo = GNUNET_new (struct GNUNET_TESTBED_PeerInformation);
  663. pinfo->pit = data->pit;
  664. cb = data->cb;
  665. cb_cls = data->cb_cls;
  666. GNUNET_assert (NULL != cb);
  667. GNUNET_free (data);
  668. opc->data = NULL;
  669. switch (pinfo->pit)
  670. {
  671. case GNUNET_TESTBED_PIT_IDENTITY:
  672. pinfo->result.id = GNUNET_new (struct GNUNET_PeerIdentity);
  673. (void) memcpy (pinfo->result.id, &msg->peer_identity,
  674. sizeof (struct GNUNET_PeerIdentity));
  675. break;
  676. case GNUNET_TESTBED_PIT_CONFIGURATION:
  677. pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
  678. GNUNET_TESTBED_extract_config_ (&msg->header);
  679. break;
  680. case GNUNET_TESTBED_PIT_GENERIC:
  681. GNUNET_assert (0); /* never reach here */
  682. break;
  683. }
  684. opc->data = pinfo;
  685. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  686. opc->state = OPC_STATE_FINISHED;
  687. cb (cb_cls, opc->op, pinfo, NULL);
  688. /* We dont check whether the operation is marked as done here as the
  689. operation contains data (cfg/identify) which will be freed at a later point
  690. */
  691. return GNUNET_YES;
  692. }
  693. /**
  694. * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
  695. * controller (testbed service)
  696. *
  697. * @param c the controller handler
  698. * @param msg message received
  699. * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
  700. * not
  701. */
  702. static int
  703. handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
  704. const struct GNUNET_TESTBED_OperationFailureEventMessage
  705. *msg)
  706. {
  707. struct OperationContext *opc;
  708. const char *emsg;
  709. uint64_t op_id;
  710. uint64_t mask;
  711. struct GNUNET_TESTBED_EventInformation event;
  712. op_id = GNUNET_ntohll (msg->operation_id);
  713. if (NULL == (opc = find_opc (c, op_id)))
  714. {
  715. LOG_DEBUG ("Operation not found\n");
  716. return GNUNET_YES;
  717. }
  718. if (OP_FORWARDED == opc->type)
  719. {
  720. handle_forwarded_operation_msg (c, opc,
  721. (const struct GNUNET_MessageHeader *) msg);
  722. return GNUNET_YES;
  723. }
  724. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  725. opc->state = OPC_STATE_FINISHED;
  726. emsg = GNUNET_TESTBED_parse_error_string_ (msg);
  727. if (NULL == emsg)
  728. emsg = "Unknown error";
  729. if (OP_PEER_INFO == opc->type)
  730. {
  731. struct PeerInfoData *data;
  732. data = opc->data;
  733. if (NULL != data->cb)
  734. data->cb (data->cb_cls, opc->op, NULL, emsg);
  735. GNUNET_free (data);
  736. return GNUNET_YES; /* We do not call controller callback for peer info */
  737. }
  738. event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
  739. event.op = opc->op;
  740. event.op_cls = opc->op_cls;
  741. event.details.operation_finished.emsg = emsg;
  742. event.details.operation_finished.generic = NULL;
  743. mask = (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
  744. if ((0 != (mask & c->event_mask)) && (NULL != c->cc))
  745. {
  746. exop_insert (event.op);
  747. c->cc (c->cc_cls, &event);
  748. if (GNUNET_NO == exop_check (event.op))
  749. return GNUNET_YES;
  750. }
  751. switch (opc->type)
  752. {
  753. case OP_PEER_CREATE:
  754. {
  755. struct PeerCreateData *data;
  756. data = opc->data;
  757. GNUNET_free (data->peer);
  758. if (NULL != data->cb)
  759. data->cb (data->cls, NULL, emsg);
  760. GNUNET_free (data);
  761. }
  762. break;
  763. case OP_PEER_START:
  764. case OP_PEER_STOP:
  765. {
  766. struct PeerEventData *data;
  767. data = opc->data;
  768. if (NULL != data->pcc)
  769. data->pcc (data->pcc_cls, emsg);
  770. GNUNET_free (data);
  771. }
  772. break;
  773. case OP_PEER_DESTROY:
  774. break;
  775. case OP_PEER_INFO:
  776. GNUNET_assert (0);
  777. case OP_OVERLAY_CONNECT:
  778. {
  779. struct OverlayConnectData *data;
  780. data = opc->data;
  781. GNUNET_TESTBED_operation_mark_failed (opc->op);
  782. if (NULL != data->cb)
  783. data->cb (data->cb_cls, opc->op, emsg);
  784. }
  785. break;
  786. case OP_FORWARDED:
  787. GNUNET_assert (0);
  788. case OP_LINK_CONTROLLERS: /* No secondary callback */
  789. break;
  790. case OP_SHUTDOWN_PEERS:
  791. {
  792. struct ShutdownPeersData *data;
  793. data = opc->data;
  794. GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */
  795. opc->data = NULL;
  796. }
  797. break;
  798. case OP_MANAGE_SERVICE:
  799. {
  800. struct ManageServiceData *data = opc->data;
  801. GNUNET_TESTBED_OperationCompletionCallback cb;
  802. void *cb_cls;
  803. GNUNET_assert (NULL != data);
  804. cb = data->cb;
  805. cb_cls = data->cb_cls;
  806. GNUNET_free (data);
  807. opc->data = NULL;
  808. exop_insert (event.op);
  809. if (NULL != cb)
  810. cb (cb_cls, opc->op, emsg);
  811. /* You could have marked the operation as done by now */
  812. GNUNET_break (GNUNET_NO == exop_check (event.op));
  813. }
  814. break;
  815. default:
  816. GNUNET_break (0);
  817. }
  818. return GNUNET_YES;
  819. }
  820. /**
  821. * Function to build GET_SLAVE_CONFIG message
  822. *
  823. * @param op_id the id this message should contain in its operation id field
  824. * @param slave_id the id this message should contain in its slave id field
  825. * @return newly allocated SlaveGetConfigurationMessage
  826. */
  827. static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
  828. GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
  829. {
  830. struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
  831. uint16_t msize;
  832. msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
  833. msg = GNUNET_malloc (msize);
  834. msg->header.size = htons (msize);
  835. msg->header.type =
  836. htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
  837. msg->operation_id = GNUNET_htonll (op_id);
  838. msg->slave_id = htonl (slave_id);
  839. return msg;
  840. }
  841. /**
  842. * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
  843. * (testbed service)
  844. *
  845. * @param c the controller handler
  846. * @param msg message received
  847. * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
  848. * not
  849. */
  850. static int
  851. handle_slave_config (struct GNUNET_TESTBED_Controller *c,
  852. const struct GNUNET_TESTBED_SlaveConfiguration *msg)
  853. {
  854. struct OperationContext *opc;
  855. uint64_t op_id;
  856. uint64_t mask;
  857. struct GNUNET_TESTBED_EventInformation event;
  858. op_id = GNUNET_ntohll (msg->operation_id);
  859. if (NULL == (opc = find_opc (c, op_id)))
  860. {
  861. LOG_DEBUG ("Operation not found\n");
  862. return GNUNET_YES;
  863. }
  864. if (OP_GET_SLAVE_CONFIG != opc->type)
  865. {
  866. GNUNET_break (0);
  867. return GNUNET_YES;
  868. }
  869. opc->state = OPC_STATE_FINISHED;
  870. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  871. mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
  872. if ((0 != (mask & c->event_mask)) &&
  873. (NULL != c->cc))
  874. {
  875. opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
  876. event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
  877. event.op = opc->op;
  878. event.op_cls = opc->op_cls;
  879. event.details.operation_finished.generic = opc->data;
  880. event.details.operation_finished.emsg = NULL;
  881. c->cc (c->cc_cls, &event);
  882. }
  883. return GNUNET_YES;
  884. }
  885. /**
  886. * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
  887. * (testbed service)
  888. *
  889. * @param c the controller handler
  890. * @param msg message received
  891. * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
  892. * not
  893. */
  894. static int
  895. handle_link_controllers_result (struct GNUNET_TESTBED_Controller *c,
  896. const struct
  897. GNUNET_TESTBED_ControllerLinkResponse *msg)
  898. {
  899. struct OperationContext *opc;
  900. struct ControllerLinkData *data;
  901. struct GNUNET_CONFIGURATION_Handle *cfg;
  902. struct GNUNET_TESTBED_Host *host;
  903. char *emsg;
  904. uint64_t op_id;
  905. struct GNUNET_TESTBED_EventInformation event;
  906. op_id = GNUNET_ntohll (msg->operation_id);
  907. if (NULL == (opc = find_opc (c, op_id)))
  908. {
  909. LOG_DEBUG ("Operation not found\n");
  910. return GNUNET_YES;
  911. }
  912. if (OP_FORWARDED == opc->type)
  913. {
  914. handle_forwarded_operation_msg (c, opc,
  915. (const struct GNUNET_MessageHeader *) msg);
  916. return GNUNET_YES;
  917. }
  918. if (OP_LINK_CONTROLLERS != opc->type)
  919. {
  920. GNUNET_break (0);
  921. return GNUNET_YES;
  922. }
  923. GNUNET_assert (NULL != (data = opc->data));
  924. host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id);
  925. GNUNET_assert (NULL != host);
  926. GNUNET_free (data);
  927. opc->data = NULL;
  928. opc->state = OPC_STATE_FINISHED;
  929. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  930. event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
  931. event.op = opc->op;
  932. event.op_cls = opc->op_cls;
  933. event.details.operation_finished.emsg = NULL;
  934. event.details.operation_finished.generic = NULL;
  935. emsg = NULL;
  936. cfg = NULL;
  937. if (GNUNET_NO == ntohs (msg->success))
  938. {
  939. emsg = GNUNET_malloc (ntohs (msg->header.size)
  940. - sizeof (struct
  941. GNUNET_TESTBED_ControllerLinkResponse) + 1);
  942. memcpy (emsg, &msg[1], ntohs (msg->header.size)
  943. - sizeof (struct
  944. GNUNET_TESTBED_ControllerLinkResponse));
  945. event.details.operation_finished.emsg = emsg;
  946. }
  947. else
  948. {
  949. if (0 != ntohs (msg->config_size))
  950. {
  951. cfg = GNUNET_TESTBED_extract_config_ ((const struct GNUNET_MessageHeader *) msg);
  952. GNUNET_assert (NULL != cfg);
  953. GNUNET_TESTBED_host_replace_cfg_ (host, cfg);
  954. }
  955. }
  956. if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
  957. {
  958. if (NULL != c->cc)
  959. c->cc (c->cc_cls, &event);
  960. }
  961. else
  962. LOG_DEBUG ("Not calling callback\n");
  963. if (NULL != cfg)
  964. GNUNET_CONFIGURATION_destroy (cfg);
  965. GNUNET_free_non_null (emsg);
  966. return GNUNET_YES;
  967. }
  968. /**
  969. * Handler for messages from controller (testbed service)
  970. *
  971. * @param cls the controller handler
  972. * @param msg message received, NULL on timeout or fatal error
  973. */
  974. static void
  975. message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
  976. {
  977. struct GNUNET_TESTBED_Controller *c = cls;
  978. int status;
  979. uint16_t msize;
  980. c->in_receive = GNUNET_NO;
  981. /* FIXME: Add checks for message integrity */
  982. if (NULL == msg)
  983. {
  984. LOG_DEBUG ("Receive timed out or connection to service dropped\n");
  985. return;
  986. }
  987. msize = ntohs (msg->size);
  988. switch (ntohs (msg->type))
  989. {
  990. case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS:
  991. GNUNET_assert (msize >=
  992. sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
  993. status =
  994. GNUNET_TESTBED_host_handle_addhostconfirm_
  995. (c, (const struct GNUNET_TESTBED_HostConfirmedMessage*) msg);
  996. break;
  997. case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS:
  998. GNUNET_assert (msize ==
  999. sizeof (struct
  1000. GNUNET_TESTBED_GenericOperationSuccessEventMessage));
  1001. status =
  1002. handle_opsuccess (c,
  1003. (const struct
  1004. GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
  1005. msg);
  1006. break;
  1007. case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT:
  1008. GNUNET_assert (msize >=
  1009. sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
  1010. status =
  1011. handle_op_fail_event (c,
  1012. (const struct
  1013. GNUNET_TESTBED_OperationFailureEventMessage *)
  1014. msg);
  1015. break;
  1016. case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS:
  1017. GNUNET_assert (msize ==
  1018. sizeof (struct
  1019. GNUNET_TESTBED_PeerCreateSuccessEventMessage));
  1020. status =
  1021. handle_peer_create_success (c,
  1022. (const struct
  1023. GNUNET_TESTBED_PeerCreateSuccessEventMessage
  1024. *) msg);
  1025. break;
  1026. case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT:
  1027. GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
  1028. status =
  1029. handle_peer_event (c,
  1030. (const struct GNUNET_TESTBED_PeerEventMessage *)
  1031. msg);
  1032. break;
  1033. case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION:
  1034. GNUNET_assert (msize >=
  1035. sizeof (struct
  1036. GNUNET_TESTBED_PeerConfigurationInformationMessage));
  1037. status =
  1038. handle_peer_config (c,
  1039. (const struct
  1040. GNUNET_TESTBED_PeerConfigurationInformationMessage
  1041. *) msg);
  1042. break;
  1043. case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT:
  1044. GNUNET_assert (msize ==
  1045. sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
  1046. status =
  1047. handle_peer_conevent (c,
  1048. (const struct
  1049. GNUNET_TESTBED_ConnectionEventMessage *) msg);
  1050. break;
  1051. case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
  1052. GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
  1053. status =
  1054. handle_slave_config (c,
  1055. (const struct GNUNET_TESTBED_SlaveConfiguration *)
  1056. msg);
  1057. break;
  1058. case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
  1059. status =
  1060. handle_link_controllers_result (c,
  1061. (const struct
  1062. GNUNET_TESTBED_ControllerLinkResponse
  1063. *) msg);
  1064. break;
  1065. case GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS:
  1066. status =
  1067. GNUNET_TESTBED_handle_barrier_status_ (c,
  1068. (const struct
  1069. GNUNET_TESTBED_BarrierStatusMsg *)
  1070. msg);
  1071. break;
  1072. default:
  1073. GNUNET_assert (0);
  1074. }
  1075. if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
  1076. {
  1077. c->in_receive = GNUNET_YES;
  1078. GNUNET_CLIENT_receive (c->client, &message_handler, c,
  1079. GNUNET_TIME_UNIT_FOREVER_REL);
  1080. }
  1081. }
  1082. /**
  1083. * Function called to notify a client about the connection begin ready to queue
  1084. * more data. "buf" will be NULL and "size" zero if the connection was closed
  1085. * for writing in the meantime.
  1086. *
  1087. * @param cls closure
  1088. * @param size number of bytes available in buf
  1089. * @param buf where the callee should write the message
  1090. * @return number of bytes written to buf
  1091. */
  1092. static size_t
  1093. transmit_ready_notify (void *cls, size_t size, void *buf)
  1094. {
  1095. struct GNUNET_TESTBED_Controller *c = cls;
  1096. struct MessageQueue *mq_entry;
  1097. c->th = NULL;
  1098. mq_entry = c->mq_head;
  1099. GNUNET_assert (NULL != mq_entry);
  1100. if ((0 == size) && (NULL == buf)) /* Timeout */
  1101. {
  1102. LOG_DEBUG ("Message sending timed out -- retrying\n");
  1103. c->th =
  1104. GNUNET_CLIENT_notify_transmit_ready (c->client,
  1105. ntohs (mq_entry->msg->size),
  1106. TIMEOUT_REL, GNUNET_YES,
  1107. &transmit_ready_notify, c);
  1108. return 0;
  1109. }
  1110. GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
  1111. size = ntohs (mq_entry->msg->size);
  1112. memcpy (buf, mq_entry->msg, size);
  1113. LOG_DEBUG ("Message of type: %u and size: %u sent\n",
  1114. ntohs (mq_entry->msg->type), size);
  1115. GNUNET_free (mq_entry->msg);
  1116. GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
  1117. GNUNET_free (mq_entry);
  1118. mq_entry = c->mq_head;
  1119. if (NULL != mq_entry)
  1120. c->th =
  1121. GNUNET_CLIENT_notify_transmit_ready (c->client,
  1122. ntohs (mq_entry->msg->size),
  1123. TIMEOUT_REL, GNUNET_YES,
  1124. &transmit_ready_notify, c);
  1125. if (GNUNET_NO == c->in_receive)
  1126. {
  1127. c->in_receive = GNUNET_YES;
  1128. GNUNET_CLIENT_receive (c->client, &message_handler, c,
  1129. GNUNET_TIME_UNIT_FOREVER_REL);
  1130. }
  1131. return size;
  1132. }
  1133. /**
  1134. * Queues a message in send queue for sending to the service
  1135. *
  1136. * @param controller the handle to the controller
  1137. * @param msg the message to queue
  1138. */
  1139. void
  1140. GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
  1141. struct GNUNET_MessageHeader *msg)
  1142. {
  1143. struct MessageQueue *mq_entry;
  1144. uint16_t type;
  1145. uint16_t size;
  1146. type = ntohs (msg->type);
  1147. size = ntohs (msg->size);
  1148. GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
  1149. (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
  1150. mq_entry = GNUNET_new (struct MessageQueue);
  1151. mq_entry->msg = msg;
  1152. LOG (GNUNET_ERROR_TYPE_DEBUG,
  1153. "Queueing message of type %u, size %u for sending\n", type,
  1154. ntohs (msg->size));
  1155. GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
  1156. mq_entry);
  1157. if (NULL == controller->th)
  1158. controller->th =
  1159. GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
  1160. TIMEOUT_REL, GNUNET_YES,
  1161. &transmit_ready_notify,
  1162. controller);
  1163. }
  1164. /**
  1165. * Sends the given message as an operation. The given callback is called when a
  1166. * reply for the operation is available. Call
  1167. * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
  1168. * operation context if the cc hasn't been called
  1169. *
  1170. * @param controller the controller to which the message has to be sent
  1171. * @param operation_id the operation id of the message
  1172. * @param msg the message to send
  1173. * @param cc the callback to call when reply is available
  1174. * @param cc_cls the closure for the above callback
  1175. * @return the operation context which can be used to cancel the forwarded
  1176. * operation
  1177. */
  1178. struct OperationContext *
  1179. GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
  1180. *controller, uint64_t operation_id,
  1181. const struct GNUNET_MessageHeader *msg,
  1182. GNUNET_CLIENT_MessageHandler cc,
  1183. void *cc_cls)
  1184. {
  1185. struct OperationContext *opc;
  1186. struct ForwardedOperationData *data;
  1187. struct GNUNET_MessageHeader *dup_msg;
  1188. uint16_t msize;
  1189. data = GNUNET_new (struct ForwardedOperationData);
  1190. data->cc = cc;
  1191. data->cc_cls = cc_cls;
  1192. opc = GNUNET_new (struct OperationContext);
  1193. opc->c = controller;
  1194. opc->type = OP_FORWARDED;
  1195. opc->data = data;
  1196. opc->id = operation_id;
  1197. msize = ntohs (msg->size);
  1198. dup_msg = GNUNET_malloc (msize);
  1199. (void) memcpy (dup_msg, msg, msize);
  1200. GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
  1201. GNUNET_TESTBED_insert_opc_ (controller, opc);
  1202. return opc;
  1203. }
  1204. /**
  1205. * Function to cancel an operation created by simply forwarding an operation
  1206. * message.
  1207. *
  1208. * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
  1209. */
  1210. void
  1211. GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
  1212. {
  1213. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  1214. GNUNET_free (opc->data);
  1215. GNUNET_free (opc);
  1216. }
  1217. /**
  1218. * Function to call to start a link-controllers type operation once all queues
  1219. * the operation is part of declare that the operation can be activated.
  1220. *
  1221. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  1222. */
  1223. static void
  1224. opstart_link_controllers (void *cls)
  1225. {
  1226. struct OperationContext *opc = cls;
  1227. struct ControllerLinkData *data;
  1228. struct GNUNET_TESTBED_ControllerLinkRequest *msg;
  1229. GNUNET_assert (NULL != opc->data);
  1230. data = opc->data;
  1231. msg = data->msg;
  1232. data->msg = NULL;
  1233. opc->state = OPC_STATE_STARTED;
  1234. GNUNET_TESTBED_insert_opc_ (opc->c, opc);
  1235. GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
  1236. }
  1237. /**
  1238. * Callback which will be called when link-controllers type operation is released
  1239. *
  1240. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  1241. */
  1242. static void
  1243. oprelease_link_controllers (void *cls)
  1244. {
  1245. struct OperationContext *opc = cls;
  1246. struct ControllerLinkData *data;
  1247. data = opc->data;
  1248. switch (opc->state)
  1249. {
  1250. case OPC_STATE_INIT:
  1251. GNUNET_free (data->msg);
  1252. break;
  1253. case OPC_STATE_STARTED:
  1254. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  1255. break;
  1256. case OPC_STATE_FINISHED:
  1257. break;
  1258. }
  1259. GNUNET_free_non_null (data);
  1260. GNUNET_free (opc);
  1261. }
  1262. /**
  1263. * Function to be called when get slave config operation is ready
  1264. *
  1265. * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
  1266. */
  1267. static void
  1268. opstart_get_slave_config (void *cls)
  1269. {
  1270. struct OperationContext *opc = cls;
  1271. struct GetSlaveConfigData *data = opc->data;
  1272. struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
  1273. GNUNET_assert (NULL != data);
  1274. msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
  1275. GNUNET_free (opc->data);
  1276. data = NULL;
  1277. opc->data = NULL;
  1278. GNUNET_TESTBED_insert_opc_ (opc->c, opc);
  1279. GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
  1280. opc->state = OPC_STATE_STARTED;
  1281. }
  1282. /**
  1283. * Function to be called when get slave config operation is cancelled or finished
  1284. *
  1285. * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
  1286. */
  1287. static void
  1288. oprelease_get_slave_config (void *cls)
  1289. {
  1290. struct OperationContext *opc = cls;
  1291. switch (opc->state)
  1292. {
  1293. case OPC_STATE_INIT:
  1294. GNUNET_free (opc->data);
  1295. break;
  1296. case OPC_STATE_STARTED:
  1297. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  1298. break;
  1299. case OPC_STATE_FINISHED:
  1300. if (NULL != opc->data)
  1301. GNUNET_CONFIGURATION_destroy (opc->data);
  1302. break;
  1303. }
  1304. GNUNET_free (opc);
  1305. }
  1306. /**
  1307. * Start a controller process using the given configuration at the
  1308. * given host.
  1309. *
  1310. * @param host host to run the controller on; This should be the same host if
  1311. * the controller was previously started with
  1312. * GNUNET_TESTBED_controller_start()
  1313. * @param event_mask bit mask with set of events to call 'cc' for;
  1314. * or-ed values of "1LL" shifted by the
  1315. * respective 'enum GNUNET_TESTBED_EventType'
  1316. * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
  1317. * @param cc controller callback to invoke on events
  1318. * @param cc_cls closure for cc
  1319. * @return handle to the controller
  1320. */
  1321. struct GNUNET_TESTBED_Controller *
  1322. GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host,
  1323. uint64_t event_mask,
  1324. GNUNET_TESTBED_ControllerCallback cc,
  1325. void *cc_cls)
  1326. {
  1327. struct GNUNET_TESTBED_Controller *controller;
  1328. struct GNUNET_TESTBED_InitMessage *msg;
  1329. const struct GNUNET_CONFIGURATION_Handle *cfg;
  1330. const char *controller_hostname;
  1331. unsigned long long max_parallel_operations;
  1332. unsigned long long max_parallel_service_connections;
  1333. unsigned long long max_parallel_topology_config_operations;
  1334. GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host)));
  1335. if (GNUNET_OK !=
  1336. GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
  1337. "MAX_PARALLEL_OPERATIONS",
  1338. &max_parallel_operations))
  1339. {
  1340. GNUNET_break (0);
  1341. return NULL;
  1342. }
  1343. if (GNUNET_OK !=
  1344. GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
  1345. "MAX_PARALLEL_SERVICE_CONNECTIONS",
  1346. &max_parallel_service_connections))
  1347. {
  1348. GNUNET_break (0);
  1349. return NULL;
  1350. }
  1351. if (GNUNET_OK !=
  1352. GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
  1353. "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
  1354. &max_parallel_topology_config_operations))
  1355. {
  1356. GNUNET_break (0);
  1357. return NULL;
  1358. }
  1359. controller = GNUNET_new (struct GNUNET_TESTBED_Controller);
  1360. controller->cc = cc;
  1361. controller->cc_cls = cc_cls;
  1362. controller->event_mask = event_mask;
  1363. controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
  1364. controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
  1365. if (NULL == controller->client)
  1366. {
  1367. GNUNET_TESTBED_controller_disconnect (controller);
  1368. return NULL;
  1369. }
  1370. GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
  1371. controller->host = host;
  1372. controller->opq_parallel_operations =
  1373. GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
  1374. (unsigned int) max_parallel_operations);
  1375. controller->opq_parallel_service_connections =
  1376. GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
  1377. (unsigned int)
  1378. max_parallel_service_connections);
  1379. controller->opq_parallel_topology_config_operations =
  1380. GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
  1381. (unsigned int)
  1382. max_parallel_topology_config_operations);
  1383. controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
  1384. if (NULL == controller_hostname)
  1385. controller_hostname = "127.0.0.1";
  1386. msg =
  1387. GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
  1388. strlen (controller_hostname) + 1);
  1389. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
  1390. msg->header.size =
  1391. htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
  1392. strlen (controller_hostname) + 1);
  1393. msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
  1394. msg->event_mask = GNUNET_htonll (controller->event_mask);
  1395. strcpy ((char *) &msg[1], controller_hostname);
  1396. GNUNET_TESTBED_queue_message_ (controller,
  1397. (struct GNUNET_MessageHeader *) msg);
  1398. return controller;
  1399. }
  1400. /**
  1401. * Iterator to free opc map entries
  1402. *
  1403. * @param cls closure
  1404. * @param key current key code
  1405. * @param value value in the hash map
  1406. * @return GNUNET_YES if we should continue to
  1407. * iterate,
  1408. * GNUNET_NO if not.
  1409. */
  1410. static int
  1411. opc_free_iterator (void *cls, uint32_t key, void *value)
  1412. {
  1413. struct GNUNET_CONTAINER_MultiHashMap32 *map = cls;
  1414. struct OperationContext *opc = value;
  1415. GNUNET_assert (NULL != opc);
  1416. GNUNET_break (0);
  1417. GNUNET_assert (GNUNET_YES ==
  1418. GNUNET_CONTAINER_multihashmap32_remove (map, key, value));
  1419. GNUNET_free (opc);
  1420. return GNUNET_YES;
  1421. }
  1422. /**
  1423. * Stop the given controller (also will terminate all peers and
  1424. * controllers dependent on this controller). This function
  1425. * blocks until the testbed has been fully terminated (!).
  1426. *
  1427. * @param c handle to controller to stop
  1428. */
  1429. void
  1430. GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
  1431. *c)
  1432. {
  1433. struct MessageQueue *mq_entry;
  1434. if (NULL != c->th)
  1435. GNUNET_CLIENT_notify_transmit_ready_cancel (c->th);
  1436. /* Clear the message queue */
  1437. while (NULL != (mq_entry = c->mq_head))
  1438. {
  1439. GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail,
  1440. mq_entry);
  1441. GNUNET_free (mq_entry->msg);
  1442. GNUNET_free (mq_entry);
  1443. }
  1444. if (NULL != c->client)
  1445. GNUNET_CLIENT_disconnect (c->client);
  1446. if (NULL != c->host)
  1447. GNUNET_TESTBED_deregister_host_at_ (c->host, c);
  1448. GNUNET_CONFIGURATION_destroy (c->cfg);
  1449. GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_operations);
  1450. GNUNET_TESTBED_operation_queue_destroy_
  1451. (c->opq_parallel_service_connections);
  1452. GNUNET_TESTBED_operation_queue_destroy_
  1453. (c->opq_parallel_topology_config_operations);
  1454. if (NULL != c->opc_map)
  1455. {
  1456. GNUNET_assert (GNUNET_SYSERR !=
  1457. GNUNET_CONTAINER_multihashmap32_iterate (c->opc_map,
  1458. &opc_free_iterator,
  1459. c->opc_map));
  1460. GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map));
  1461. GNUNET_CONTAINER_multihashmap32_destroy (c->opc_map);
  1462. }
  1463. GNUNET_free (c);
  1464. }
  1465. /**
  1466. * Compresses given configuration using zlib compress
  1467. *
  1468. * @param config the serialized configuration
  1469. * @param size the size of config
  1470. * @param xconfig will be set to the compressed configuration (memory is fresly
  1471. * allocated)
  1472. * @return the size of the xconfig
  1473. */
  1474. size_t
  1475. GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
  1476. char **xconfig)
  1477. {
  1478. size_t xsize;
  1479. xsize = compressBound ((uLong) size);
  1480. *xconfig = GNUNET_malloc (xsize);
  1481. GNUNET_assert (Z_OK ==
  1482. compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
  1483. (const Bytef *) config, (uLongf) size,
  1484. Z_BEST_SPEED));
  1485. return xsize;
  1486. }
  1487. /**
  1488. * Function to serialize and compress using zlib a configuration through a
  1489. * configuration handle
  1490. *
  1491. * @param cfg the configuration
  1492. * @param size the size of configuration when serialize. Will be set on success.
  1493. * @param xsize the sizeo of the compressed configuration. Will be set on success.
  1494. * @return the serialized and compressed configuration
  1495. */
  1496. char *
  1497. GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg,
  1498. size_t *size, size_t *xsize)
  1499. {
  1500. char *config;
  1501. char *xconfig;
  1502. size_t size_;
  1503. size_t xsize_;
  1504. config = GNUNET_CONFIGURATION_serialize (cfg, &size_);
  1505. xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig);
  1506. GNUNET_free (config);
  1507. *size = size_;
  1508. *xsize = xsize_;
  1509. return xconfig;
  1510. }
  1511. /**
  1512. * Create a link from slave controller to delegated controller. Whenever the
  1513. * master controller is asked to start a peer at the delegated controller the
  1514. * request will be routed towards slave controller (if a route exists). The
  1515. * slave controller will then route it to the delegated controller. The
  1516. * configuration of the delegated controller is given and is used to either
  1517. * create the delegated controller or to connect to an existing controller. Note
  1518. * that while starting the delegated controller the configuration will be
  1519. * modified to accommodate available free ports. the 'is_subordinate' specifies
  1520. * if the given delegated controller should be started and managed by the slave
  1521. * controller, or if the delegated controller already has a master and the slave
  1522. * controller connects to it as a non master controller. The success or failure
  1523. * of this operation will be signalled through the
  1524. * GNUNET_TESTBED_ControllerCallback() with an event of type
  1525. * GNUNET_TESTBED_ET_OPERATION_FINISHED
  1526. *
  1527. * @param op_cls the operation closure for the event which is generated to
  1528. * signal success or failure of this operation
  1529. * @param master handle to the master controller who creates the association
  1530. * @param delegated_host requests to which host should be delegated; cannot be NULL
  1531. * @param slave_host which host is used to run the slave controller; use NULL to
  1532. * make the master controller connect to the delegated host
  1533. * @param is_subordinate GNUNET_YES if the controller at delegated_host should
  1534. * be started by the slave controller; GNUNET_NO if the slave
  1535. * controller has to connect to the already started delegated
  1536. * controller via TCP/IP
  1537. * @return the operation handle
  1538. */
  1539. struct GNUNET_TESTBED_Operation *
  1540. GNUNET_TESTBED_controller_link (void *op_cls,
  1541. struct GNUNET_TESTBED_Controller *master,
  1542. struct GNUNET_TESTBED_Host *delegated_host,
  1543. struct GNUNET_TESTBED_Host *slave_host,
  1544. int is_subordinate)
  1545. {
  1546. struct OperationContext *opc;
  1547. struct GNUNET_TESTBED_ControllerLinkRequest *msg;
  1548. struct ControllerLinkData *data;
  1549. uint32_t slave_host_id;
  1550. uint32_t delegated_host_id;
  1551. uint16_t msg_size;
  1552. GNUNET_assert (GNUNET_YES ==
  1553. GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
  1554. slave_host_id =
  1555. GNUNET_TESTBED_host_get_id_ ((NULL !=
  1556. slave_host) ? slave_host : master->host);
  1557. delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
  1558. if ((NULL != slave_host) && (0 != slave_host_id))
  1559. GNUNET_assert (GNUNET_YES ==
  1560. GNUNET_TESTBED_is_host_registered_ (slave_host, master));
  1561. msg_size = sizeof (struct GNUNET_TESTBED_ControllerLinkRequest);
  1562. msg = GNUNET_malloc (msg_size);
  1563. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
  1564. msg->header.size = htons (msg_size);
  1565. msg->delegated_host_id = htonl (delegated_host_id);
  1566. msg->slave_host_id = htonl (slave_host_id);
  1567. msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
  1568. data = GNUNET_new (struct ControllerLinkData);
  1569. data->msg = msg;
  1570. data->host_id = delegated_host_id;
  1571. opc = GNUNET_new (struct OperationContext);
  1572. opc->c = master;
  1573. opc->data = data;
  1574. opc->type = OP_LINK_CONTROLLERS;
  1575. opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
  1576. opc->state = OPC_STATE_INIT;
  1577. opc->op_cls = op_cls;
  1578. msg->operation_id = GNUNET_htonll (opc->id);
  1579. opc->op =
  1580. GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
  1581. &oprelease_link_controllers);
  1582. GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
  1583. opc->op);
  1584. GNUNET_TESTBED_operation_begin_wait_ (opc->op);
  1585. return opc->op;
  1586. }
  1587. /**
  1588. * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
  1589. * check. Another difference is that this function takes the id of the slave
  1590. * host.
  1591. *
  1592. * @param op_cls the closure for the operation
  1593. * @param master the handle to master controller
  1594. * @param slave_host_id id of the host where the slave controller is running to
  1595. * the slave_host should remain valid until this operation is cancelled
  1596. * or marked as finished
  1597. * @return the operation handle;
  1598. */
  1599. struct GNUNET_TESTBED_Operation *
  1600. GNUNET_TESTBED_get_slave_config_ (void *op_cls,
  1601. struct GNUNET_TESTBED_Controller *master,
  1602. uint32_t slave_host_id)
  1603. {
  1604. struct OperationContext *opc;
  1605. struct GetSlaveConfigData *data;
  1606. data = GNUNET_new (struct GetSlaveConfigData);
  1607. data->slave_id = slave_host_id;
  1608. opc = GNUNET_new (struct OperationContext);
  1609. opc->state = OPC_STATE_INIT;
  1610. opc->c = master;
  1611. opc->id = GNUNET_TESTBED_get_next_op_id (master);
  1612. opc->type = OP_GET_SLAVE_CONFIG;
  1613. opc->data = data;
  1614. opc->op_cls = op_cls;
  1615. opc->op =
  1616. GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
  1617. &oprelease_get_slave_config);
  1618. GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
  1619. opc->op);
  1620. GNUNET_TESTBED_operation_begin_wait_ (opc->op);
  1621. return opc->op;
  1622. }
  1623. /**
  1624. * Function to acquire the configuration of a running slave controller. The
  1625. * completion of the operation is signalled through the controller_cb from
  1626. * GNUNET_TESTBED_controller_connect(). If the operation is successful the
  1627. * handle to the configuration is available in the generic pointer of
  1628. * operation_finished field of struct GNUNET_TESTBED_EventInformation.
  1629. *
  1630. * @param op_cls the closure for the operation
  1631. * @param master the handle to master controller
  1632. * @param slave_host the host where the slave controller is running; the handle
  1633. * to the slave_host should remain valid until this operation is
  1634. * cancelled or marked as finished
  1635. * @return the operation handle; NULL if the slave_host is not registered at
  1636. * master
  1637. */
  1638. struct GNUNET_TESTBED_Operation *
  1639. GNUNET_TESTBED_get_slave_config (void *op_cls,
  1640. struct GNUNET_TESTBED_Controller *master,
  1641. struct GNUNET_TESTBED_Host *slave_host)
  1642. {
  1643. if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
  1644. return NULL;
  1645. return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
  1646. GNUNET_TESTBED_host_get_id_
  1647. (slave_host));
  1648. }
  1649. /**
  1650. * Ask the testbed controller to write the current overlay topology to
  1651. * a file. Naturally, the file will only contain a snapshot as the
  1652. * topology may evolve all the time.
  1653. *
  1654. * @param controller overlay controller to inspect
  1655. * @param filename name of the file the topology should
  1656. * be written to.
  1657. */
  1658. void
  1659. GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
  1660. *controller,
  1661. const char *filename)
  1662. {
  1663. GNUNET_break (0);
  1664. }
  1665. /**
  1666. * Creates a helper initialization message. This function is here because we
  1667. * want to use this in testing
  1668. *
  1669. * @param trusted_ip the ip address of the controller which will be set as TRUSTED
  1670. * HOST(all connections form this ip are permitted by the testbed) when
  1671. * starting testbed controller at host. This can either be a single ip
  1672. * address or a network address in CIDR notation.
  1673. * @param hostname the hostname of the destination this message is intended for
  1674. * @param cfg the configuration that has to used to start the testbed service
  1675. * thru helper
  1676. * @return the initialization message
  1677. */
  1678. struct GNUNET_TESTBED_HelperInit *
  1679. GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
  1680. const char *hostname,
  1681. const struct GNUNET_CONFIGURATION_Handle
  1682. *cfg)
  1683. {
  1684. struct GNUNET_TESTBED_HelperInit *msg;
  1685. char *config;
  1686. char *xconfig;
  1687. size_t config_size;
  1688. size_t xconfig_size;
  1689. uint16_t trusted_ip_len;
  1690. uint16_t hostname_len;
  1691. uint16_t msg_size;
  1692. config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
  1693. GNUNET_assert (NULL != config);
  1694. xconfig_size =
  1695. GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
  1696. GNUNET_free (config);
  1697. trusted_ip_len = strlen (trusted_ip);
  1698. hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
  1699. msg_size =
  1700. xconfig_size + trusted_ip_len + 1 +
  1701. sizeof (struct GNUNET_TESTBED_HelperInit);
  1702. msg_size += hostname_len;
  1703. msg = GNUNET_realloc (xconfig, msg_size);
  1704. (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
  1705. xconfig_size);
  1706. msg->header.size = htons (msg_size);
  1707. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
  1708. msg->trusted_ip_size = htons (trusted_ip_len);
  1709. msg->hostname_size = htons (hostname_len);
  1710. msg->config_size = htons (config_size);
  1711. (void) strcpy ((char *) &msg[1], trusted_ip);
  1712. if (0 != hostname_len)
  1713. (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
  1714. hostname_len);
  1715. return msg;
  1716. }
  1717. /**
  1718. * This function is used to signal that the event information (struct
  1719. * GNUNET_TESTBED_EventInformation) from an operation has been fully processed
  1720. * i.e. if the event callback is ever called for this operation. If the event
  1721. * callback for this operation has not yet been called, calling this function
  1722. * cancels the operation, frees its resources and ensures the no event is
  1723. * generated with respect to this operation. Note that however cancelling an
  1724. * operation does NOT guarantee that the operation will be fully undone (or that
  1725. * nothing ever happened).
  1726. *
  1727. * This function MUST be called for every operation to fully remove the
  1728. * operation from the operation queue. After calling this function, if
  1729. * operation is completed and its event information is of type
  1730. * GNUNET_TESTBED_ET_OPERATION_FINISHED, the 'op_result' becomes invalid (!).
  1731. * If the operation is generated from GNUNET_TESTBED_service_connect() then
  1732. * calling this function on such as operation calls the disconnect adapter if
  1733. * the connect adapter was ever called.
  1734. *
  1735. * @param operation operation to signal completion or cancellation
  1736. */
  1737. void
  1738. GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
  1739. {
  1740. (void) exop_check (operation);
  1741. GNUNET_TESTBED_operation_release_ (operation);
  1742. }
  1743. /**
  1744. * Generates configuration by uncompressing configuration in given message. The
  1745. * given message should be of the following types:
  1746. * GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION,
  1747. * GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
  1748. * GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST,
  1749. * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
  1750. * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
  1751. *
  1752. * @param msg the message containing compressed configuration
  1753. * @return handle to the parsed configuration; NULL upon error while parsing the message
  1754. */
  1755. struct GNUNET_CONFIGURATION_Handle *
  1756. GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
  1757. {
  1758. struct GNUNET_CONFIGURATION_Handle *cfg;
  1759. Bytef *data;
  1760. const Bytef *xdata;
  1761. uLong data_len;
  1762. uLong xdata_len;
  1763. int ret;
  1764. switch (ntohs (msg->type))
  1765. {
  1766. case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION:
  1767. {
  1768. const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
  1769. imsg =
  1770. (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
  1771. data_len = (uLong) ntohs (imsg->config_size);
  1772. xdata_len =
  1773. ntohs (imsg->header.size) -
  1774. sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
  1775. xdata = (const Bytef *) &imsg[1];
  1776. }
  1777. break;
  1778. case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
  1779. {
  1780. const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
  1781. imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
  1782. data_len = (uLong) ntohs (imsg->config_size);
  1783. xdata_len =
  1784. ntohs (imsg->header.size) -
  1785. sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
  1786. xdata = (const Bytef *) &imsg[1];
  1787. }
  1788. break;
  1789. case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST:
  1790. {
  1791. const struct GNUNET_TESTBED_AddHostMessage *imsg;
  1792. uint16_t osize;
  1793. imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
  1794. data_len = (uLong) ntohs (imsg->config_size);
  1795. osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) +
  1796. ntohs (imsg->username_length) + ntohs (imsg->hostname_length);
  1797. xdata_len = ntohs (imsg->header.size) - osize;
  1798. xdata = (const Bytef *) ((const void *) imsg + osize);
  1799. }
  1800. break;
  1801. case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
  1802. {
  1803. const struct GNUNET_TESTBED_ControllerLinkResponse *imsg;
  1804. imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg;
  1805. data_len = ntohs (imsg->config_size);
  1806. xdata_len = ntohs (imsg->header.size) -
  1807. sizeof (const struct GNUNET_TESTBED_ControllerLinkResponse);
  1808. xdata = (const Bytef *) &imsg[1];
  1809. }
  1810. break;
  1811. case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER:
  1812. {
  1813. const struct GNUNET_TESTBED_PeerCreateMessage *imsg;
  1814. imsg = (const struct GNUNET_TESTBED_PeerCreateMessage *) msg;
  1815. data_len = ntohs (imsg->config_size);
  1816. xdata_len = ntohs (imsg->header.size) -
  1817. sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
  1818. xdata = (const Bytef *) &imsg[1];
  1819. }
  1820. break;
  1821. case GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER:
  1822. {
  1823. const struct GNUNET_TESTBED_PeerReconfigureMessage *imsg;
  1824. imsg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) msg;
  1825. data_len = ntohs (imsg->config_size);
  1826. xdata_len = ntohs (imsg->header.size) -
  1827. sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage);
  1828. xdata = (const Bytef *) &imsg[1];
  1829. }
  1830. break;
  1831. default:
  1832. GNUNET_assert (0);
  1833. }
  1834. data = GNUNET_malloc (data_len);
  1835. if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
  1836. {
  1837. GNUNET_free (data);
  1838. GNUNET_break_op (0); /* Un-compression failure */
  1839. return NULL;
  1840. }
  1841. cfg = GNUNET_CONFIGURATION_create ();
  1842. if (GNUNET_OK !=
  1843. GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
  1844. (size_t) data_len,
  1845. GNUNET_NO))
  1846. {
  1847. GNUNET_free (data);
  1848. GNUNET_break_op (0); /* De-serialization failure */
  1849. return NULL;
  1850. }
  1851. GNUNET_free (data);
  1852. return cfg;
  1853. }
  1854. /**
  1855. * Checks the integrity of the OperationFailureEventMessage and if good returns
  1856. * the error message it contains.
  1857. *
  1858. * @param msg the OperationFailureEventMessage
  1859. * @return the error message
  1860. */
  1861. const char *
  1862. GNUNET_TESTBED_parse_error_string_ (const struct
  1863. GNUNET_TESTBED_OperationFailureEventMessage
  1864. *msg)
  1865. {
  1866. uint16_t msize;
  1867. const char *emsg;
  1868. msize = ntohs (msg->header.size);
  1869. if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
  1870. return NULL;
  1871. msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
  1872. emsg = (const char *) &msg[1];
  1873. if ('\0' != emsg[msize - 1])
  1874. {
  1875. GNUNET_break (0);
  1876. return NULL;
  1877. }
  1878. return emsg;
  1879. }
  1880. /**
  1881. * Function to return the operation id for a controller. The operation id is
  1882. * created from the controllers host id and its internal operation counter.
  1883. *
  1884. * @param controller the handle to the controller whose operation id has to be incremented
  1885. * @return the incremented operation id.
  1886. */
  1887. uint64_t
  1888. GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
  1889. {
  1890. uint64_t op_id;
  1891. op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
  1892. op_id = op_id << 32;
  1893. op_id |= (uint64_t) controller->operation_counter++;
  1894. return op_id;
  1895. }
  1896. /**
  1897. * Function called when a shutdown peers operation is ready
  1898. *
  1899. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  1900. */
  1901. static void
  1902. opstart_shutdown_peers (void *cls)
  1903. {
  1904. struct OperationContext *opc = cls;
  1905. struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
  1906. opc->state = OPC_STATE_STARTED;
  1907. msg = GNUNET_new (struct GNUNET_TESTBED_ShutdownPeersMessage);
  1908. msg->header.size =
  1909. htons (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage));
  1910. msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS);
  1911. msg->operation_id = GNUNET_htonll (opc->id);
  1912. GNUNET_TESTBED_insert_opc_ (opc->c, opc);
  1913. GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
  1914. }
  1915. /**
  1916. * Callback which will be called when shutdown peers operation is released
  1917. *
  1918. * @param cls the closure from GNUNET_TESTBED_operation_create_()
  1919. */
  1920. static void
  1921. oprelease_shutdown_peers (void *cls)
  1922. {
  1923. struct OperationContext *opc = cls;
  1924. switch (opc->state)
  1925. {
  1926. case OPC_STATE_STARTED:
  1927. GNUNET_TESTBED_remove_opc_ (opc->c, opc);
  1928. /* no break; continue */
  1929. case OPC_STATE_INIT:
  1930. GNUNET_free (opc->data);
  1931. break;
  1932. case OPC_STATE_FINISHED:
  1933. break;
  1934. }
  1935. GNUNET_free (opc);
  1936. }
  1937. /**
  1938. * Stops and destroys all peers. Is equivalent of calling
  1939. * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers,
  1940. * except that the peer stop event and operation finished event corresponding to
  1941. * the respective functions are not generated. This function should be called
  1942. * when there are no other pending operations. If there are pending operations,
  1943. * it will return NULL
  1944. *
  1945. * @param c the controller to send this message to
  1946. * @param op_cls closure for the operation
  1947. * @param cb the callback to call when all peers are stopped and destroyed
  1948. * @param cb_cls the closure for the callback
  1949. * @return operation handle on success; NULL if any pending operations are
  1950. * present
  1951. */
  1952. struct GNUNET_TESTBED_Operation *
  1953. GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *c,
  1954. void *op_cls,
  1955. GNUNET_TESTBED_OperationCompletionCallback cb,
  1956. void *cb_cls)
  1957. {
  1958. struct OperationContext *opc;
  1959. struct ShutdownPeersData *data;
  1960. if (0 != GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
  1961. return NULL;
  1962. data = GNUNET_new (struct ShutdownPeersData);
  1963. data->cb = cb;
  1964. data->cb_cls = cb_cls;
  1965. opc = GNUNET_new (struct OperationContext);
  1966. opc->c = c;
  1967. opc->op_cls = op_cls;
  1968. opc->data = data;
  1969. opc->id = GNUNET_TESTBED_get_next_op_id (c);
  1970. opc->type = OP_SHUTDOWN_PEERS;
  1971. opc->state = OPC_STATE_INIT;
  1972. opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_shutdown_peers,
  1973. &oprelease_shutdown_peers);
  1974. GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
  1975. opc->op);
  1976. GNUNET_TESTBED_operation_begin_wait_ (opc->op);
  1977. return opc->op;
  1978. }
  1979. /**
  1980. * Return the index of the peer inside of the total peer array,
  1981. * aka. the peer's "unique ID".
  1982. *
  1983. * @param peer Peer handle.
  1984. *
  1985. * @return The peer's unique ID.
  1986. */
  1987. uint32_t
  1988. GNUNET_TESTBED_get_index (const struct GNUNET_TESTBED_Peer *peer)
  1989. {
  1990. return peer->unique_id;
  1991. }
  1992. /* end of testbed_api.c */