2
0

testbed_api.c 73 KB

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