controller.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. extern "C" {
  2. #include <event2/listener.h>
  3. #include <event2/bufferevent.h>
  4. #include <event2/buffer.h>
  5. }
  6. #include <NTL/vec_ZZ.h>
  7. #include <NTL/ZZ.h>
  8. #include <NTL/ZZ_p.h>
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11. #include <arpa/inet.h>
  12. #include <fstream>
  13. #include <vector>
  14. #include <set>
  15. #include <map>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include "evutils.h"
  19. #include "subproblem.h"
  20. NTL_CLIENT
  21. #define DEBUG
  22. struct SubproblemProgress;
  23. typedef std::set<struct bufferevent *> BESet;
  24. typedef std::map<struct bufferevent *, SubproblemProgress *> BEMap;
  25. void besetdump(const BESet &bes, ostream &os)
  26. {
  27. BESet::const_iterator besit;
  28. os << hex << " ";
  29. for (besit = bes.begin(); besit != bes.end(); ++besit) {
  30. os << *besit << " ";
  31. }
  32. os << dec << "\n";
  33. }
  34. void bemapdump(const BEMap &bem, ostream &os)
  35. {
  36. BEMap::const_iterator bemit;
  37. os << hex << " ";
  38. for (bemit = bem.begin(); bemit != bem.end(); ++bemit) {
  39. os << bemit->first << "->" << bemit->second << " ";
  40. }
  41. os << dec << "\n";
  42. }
  43. struct Statuses {
  44. BESet idle;
  45. BEMap working;
  46. // Dump the state for debug purposes
  47. void dump(ostream &os) const {
  48. os << " idle (" << idle.size() << "):\n";
  49. besetdump(idle, os);
  50. os << " working (" << working.size() << "):\n";
  51. bemapdump(working, os);
  52. }
  53. };
  54. struct FactorDecomp {
  55. ZZ factor;
  56. vec_ZZ fvec;
  57. };
  58. void vsppdump(const vector<SubproblemProgress> &spv, ostream &os);
  59. static struct ControllerState {
  60. ZZ rho;
  61. FactorDecomp p, q;
  62. ZZ base, target;
  63. bool working;
  64. vector<SubproblemProgress> subproblems_p, subproblems_q;
  65. Statuses dpnodes, workers;
  66. unsigned int num_unsolved_subproblems;
  67. ControllerState() : working(false), num_unsolved_subproblems(0) {}
  68. // Reset the state for a new problem with the same modulus
  69. void reset(void) {
  70. base = 0;
  71. target = 0;
  72. working = false;
  73. subproblems_p.clear();
  74. subproblems_q.clear();
  75. num_unsolved_subproblems = 0;
  76. }
  77. // Dump the state for debug purposes
  78. void dump(ostream &os) const {
  79. if (!working) {
  80. os << "Not working\n";
  81. return;
  82. }
  83. os << "P:\n";
  84. vsppdump(subproblems_p, os);
  85. os << "Q:\n";
  86. vsppdump(subproblems_q, os);
  87. os << "dpnodes:\n";
  88. dpnodes.dump(os);
  89. os << "workers:\n";
  90. workers.dump(os);
  91. }
  92. } ctrlstate;
  93. struct IPPort {
  94. unsigned char ipport[6];
  95. IPPort(unsigned char *ipp) {
  96. memmove(ipport, ipp, 6);
  97. }
  98. void dump(ostream &os) const {
  99. os << int(ipport[0]) << "." << int(ipport[1]) << "." <<
  100. int(ipport[2]) << "." << int(ipport[3]) << ":" <<
  101. ((ipport[4] << 8) + ipport[5]) << " ";
  102. }
  103. };
  104. typedef vector<IPPort> IPPortSet;
  105. void ipportsetdump(const IPPortSet &ipps, ostream &os)
  106. {
  107. IPPortSet::const_iterator ippsit;
  108. os << " ";
  109. for (ippsit = ipps.begin(); ippsit != ipps.end(); ++ippsit) {
  110. ippsit->dump(os);
  111. }
  112. os << "\n";
  113. }
  114. struct SubproblemProgress : Subproblem {
  115. // The sets of dpnodes and workers currently working on this subproblem
  116. BESet dpnodes, workers;
  117. // The dpnode IPPorts registered for this subproblem
  118. IPPortSet ipports;
  119. // The desired number of DPnodes for this subproblem
  120. unsigned short desired_dpnodes;
  121. // The maximum number of workers useful for this subproblem
  122. unsigned int max_workers;
  123. // Have we found a solution?
  124. bool solved;
  125. // The solution, if found.
  126. ZZ solution;
  127. SubproblemProgress(unsigned short id, const ZZ &b, const ZZ &t,
  128. const ZZ &m, const ZZ &o, unsigned int dpf) :
  129. Subproblem(id, b, t, m, o, dpf), solved(false) {
  130. // How many DPnodes should we use for a problem of this size?
  131. desired_dpnodes = 2;
  132. // How many workers would we like to use?
  133. ZZ sorder = SqrRoot(order >> 46);
  134. if (NumBits(sorder) > 30) {
  135. // Just use all the workers we can find
  136. max_workers = 4294967295U; // 2^32 - 1
  137. } else {
  138. max_workers = trunc_long(sorder,31) + 1;
  139. }
  140. }
  141. // Stop all dpnodes and workers
  142. void stop(void) {
  143. BESet::iterator iter;
  144. unsigned char stopcmd[1] = { 'S' };
  145. for (BESet::iterator iter = dpnodes.begin(); iter != dpnodes.end();
  146. ++iter) {
  147. bufferevent_write(*iter, stopcmd, 1);
  148. ctrlstate.dpnodes.working.erase(*iter);
  149. ctrlstate.dpnodes.idle.insert(*iter);
  150. }
  151. for (BESet::iterator iter = workers.begin(); iter != workers.end();
  152. ++iter) {
  153. bufferevent_write(*iter, stopcmd, 1);
  154. ctrlstate.workers.working.erase(*iter);
  155. ctrlstate.workers.idle.insert(*iter);
  156. }
  157. dpnodes.clear();
  158. workers.clear();
  159. ipports.clear();
  160. }
  161. // Dump for debugging purposes
  162. void dump(ostream &os) const {
  163. os << " Subproblem " << problemid << "\n";
  164. os << " dpnodes (" << dpnodes.size() << "):\n";
  165. besetdump(dpnodes, os);
  166. os << " workers (" << workers.size() << "):\n";
  167. besetdump(workers, os);
  168. os << " ipports (" << ipports.size() << "):\n";
  169. ipportsetdump(ipports, os);
  170. if (solved) {
  171. os << " solution: " << solution << "\n\n";
  172. }
  173. }
  174. void worker_write(struct bufferevent *bev) {
  175. bev_write(bev);
  176. unsigned short num_ipports = ipports.size();
  177. bufferevent_write(bev, &num_ipports, 2);
  178. for (unsigned short i = 0; i < num_ipports; ++i) {
  179. bufferevent_write(bev, ipports[i].ipport, 6);
  180. }
  181. #ifdef DEBUG
  182. cerr << "Added worker " << bev << "to subproblem "
  183. << problemid << "\n";
  184. #endif
  185. }
  186. };
  187. // Dump the state for debug purposes
  188. void vsppdump(const vector<SubproblemProgress> &spv, ostream &os)
  189. {
  190. vector<SubproblemProgress>::const_iterator spiter;
  191. int count = 0;
  192. for (spiter = spv.begin(); spiter != spv.end(); ++spiter) {
  193. ++count;
  194. os << " " << count << ":\n";
  195. spiter->dump(os);
  196. }
  197. os << "\n";
  198. }
  199. // Find a subproblem in the given vector that could use another DPnode,
  200. // and give it one of the idle ones. Only allocate it to a subproblem
  201. // with no current DPnodes if consider_empty is true.
  202. static void find_subproblem_for_dpnode(vector<SubproblemProgress> &spv,
  203. bool consider_empty)
  204. {
  205. vector<SubproblemProgress>::iterator spiter;
  206. for (spiter = spv.begin(); spiter != spv.end(); ++spiter) {
  207. if (spiter->solved) continue;
  208. if (spiter->dpnodes.size() == 0 && consider_empty == false) continue;
  209. // How many DPnodes would we like to have for this subproblem?
  210. while (spiter->dpnodes.size() < spiter->desired_dpnodes &&
  211. ctrlstate.dpnodes.idle.size() > 0) {
  212. // Get the first idle DPnode
  213. BESet::iterator beviter = ctrlstate.dpnodes.idle.begin();
  214. struct bufferevent *firstbev = *beviter;
  215. // Allocate it to the subproblem
  216. spiter->dpnodes.insert(firstbev);
  217. ctrlstate.dpnodes.working[firstbev] = &(*spiter);
  218. ctrlstate.dpnodes.idle.erase(firstbev);
  219. // Tell it to start listening for DPs
  220. spiter->bev_write(firstbev);
  221. }
  222. }
  223. }
  224. // Find a subproblem in the given vector that has all of its DPnodes and
  225. // could use another worker, and give it one of the idle ones.
  226. static void find_subproblem_for_worker(vector<SubproblemProgress> &spv)
  227. {
  228. vector<SubproblemProgress>::iterator spiter;
  229. for (spiter = spv.begin(); spiter != spv.end(); ++spiter) {
  230. if (spiter->solved) continue;
  231. while (spiter->ipports.size() == spiter->desired_dpnodes &&
  232. spiter->workers.size() < spiter->max_workers &&
  233. ctrlstate.workers.idle.size() > 0) {
  234. // Get the first idle worker
  235. BESet::iterator beviter = ctrlstate.workers.idle.begin();
  236. struct bufferevent *firstbev = *beviter;
  237. // Allocate it to the subproblem
  238. spiter->workers.insert(firstbev);
  239. ctrlstate.workers.working[firstbev] = &(*spiter);
  240. ctrlstate.workers.idle.erase(firstbev);
  241. // Tell it to start working on the subproblem
  242. spiter->worker_write(firstbev);
  243. }
  244. }
  245. }
  246. // See if there are any idle DPnodes or workers we can put to use
  247. static void schedule(void)
  248. {
  249. // Check the DPnodes
  250. // Iterate through the subproblems, looking for one that can use
  251. // another DPnode. First look for subproblems that already have
  252. // some, but not all, of their DPnodes
  253. if (ctrlstate.dpnodes.idle.size() > 0) {
  254. find_subproblem_for_dpnode(ctrlstate.subproblems_p, false);
  255. }
  256. if (ctrlstate.dpnodes.idle.size() > 0) {
  257. find_subproblem_for_dpnode(ctrlstate.subproblems_q, false);
  258. }
  259. // If there are still more dpnodes to place, start assigning them to
  260. // subproblems with no current dpnodes
  261. if (ctrlstate.dpnodes.idle.size() > 0) {
  262. find_subproblem_for_dpnode(ctrlstate.subproblems_p, true);
  263. }
  264. if (ctrlstate.dpnodes.idle.size() > 0) {
  265. find_subproblem_for_dpnode(ctrlstate.subproblems_q, true);
  266. }
  267. // Check the workers
  268. // Iterate through the subproblems, looking for one that can use
  269. // another worker.
  270. if (ctrlstate.workers.idle.size() > 0) {
  271. find_subproblem_for_worker(ctrlstate.subproblems_p);
  272. }
  273. if (ctrlstate.workers.idle.size() > 0) {
  274. find_subproblem_for_worker(ctrlstate.subproblems_q);
  275. }
  276. // cerr << "After schedule:\n"; ctrlstate.dump(cerr);
  277. }
  278. static ZZ computation_complete_p(const vector<SubproblemProgress> &v)
  279. {
  280. ZZ curmodulus, curexp;
  281. curmodulus = 2;
  282. curexp = 0;
  283. vector<SubproblemProgress>::const_iterator vit;
  284. for(vit = v.begin(); vit != v.end(); ++vit) {
  285. CRT(curexp, curmodulus, vit->solution, vit->order);
  286. }
  287. if (curexp < 0) {
  288. curexp += curmodulus;
  289. }
  290. return curexp;
  291. }
  292. // All subproblems are solved. Combine the results.
  293. static void computation_complete(void)
  294. {
  295. ZZ exp_p = computation_complete_p(ctrlstate.subproblems_p);
  296. ZZ exp_q = computation_complete_p(ctrlstate.subproblems_q);
  297. ZZ pm1 = (ctrlstate.p.factor - 1)/2;
  298. ZZ qm1 = (ctrlstate.q.factor - 1)/2;
  299. CRT(exp_p, pm1, exp_q, qm1);
  300. if (exp_p < 0) {
  301. exp_p += pm1;
  302. }
  303. ZZ& expon = exp_p;
  304. cout << "expon = " << expon << "\n";
  305. ZZ base_exp = PowerMod(ctrlstate.base, expon, ctrlstate.rho);
  306. if (base_exp == ctrlstate.target) {
  307. cout << "CORRECT!\n";
  308. } else {
  309. cout << "INCORRECT:\nbase^exp = " << base_exp << "\n";
  310. cout << "target = " << ctrlstate.target << "\n";
  311. }
  312. ctrlstate.reset();
  313. }
  314. static unsigned short curproblemid = 0;
  315. // Take base and target mod f.factor, then decompose that into small
  316. // subproblems given our knowledge of the factors of phi(f.factor)
  317. static vector<SubproblemProgress> decomp(const ZZ_p &base, const ZZ_p &target,
  318. const FactorDecomp &f)
  319. {
  320. vector<SubproblemProgress> ret;
  321. // Compute phi(factor)
  322. const int fveclen = f.fvec.length();
  323. ZZ phi = to_ZZ(2);
  324. for (int i = 0; i < fveclen; ++i) {
  325. phi *= f.fvec[i];
  326. }
  327. ZZ_p::init(f.factor);
  328. for (int i = 0; i < fveclen; ++i) {
  329. const ZZ& order = f.fvec[i];
  330. ZZ quotient = phi / order;
  331. ZZ_p subgroup_base = to_ZZ_p(rep(base));
  332. subgroup_base = power(subgroup_base, quotient);
  333. ZZ_p subgroup_target = to_ZZ_p(rep(target));
  334. subgroup_target = power(subgroup_target, quotient);
  335. if (subgroup_base == 1) {
  336. // The original base wasn't a generator of the whole group
  337. if (subgroup_target == 1) {
  338. // But the target is in the subgroup. Lucky us.
  339. continue;
  340. } else {
  341. ret.clear();
  342. return ret;
  343. }
  344. }
  345. // By default, 1 in 1000 points are distinguihed points. The
  346. // number in the next line is 2^32/1000
  347. unsigned int dpfreq = 4294967;
  348. if (order < 1000) {
  349. // Just make every point a DP
  350. dpfreq = 4294967295U;
  351. } else if (NumBits(order) < 27) {
  352. // The frequency of DPs should be 10/sqrt(order) to avoid
  353. // a DP-free cycle, so dpfreq = (10*2^32)/sqrt(order)
  354. ZZ f = (to_ZZ(10) << 32) / SqrRoot(order);
  355. dpfreq = trunc_long(f, 31);
  356. }
  357. ++curproblemid;
  358. ret.push_back(SubproblemProgress(curproblemid, rep(subgroup_base),
  359. rep(subgroup_target),
  360. f.factor, order, dpfreq));
  361. }
  362. return ret;
  363. }
  364. static int generate_problem(struct event_base *evbase)
  365. {
  366. // If there's already a problem on the go, don't generate another one
  367. if (ctrlstate.working == true) {
  368. return -1;
  369. }
  370. ctrlstate.working = true;
  371. int num_subproblems_p = 0;
  372. int num_subproblems_q = 0;
  373. // Generate a DLP mod rho (in the large odd-order subgroup)
  374. ZZ_p::init(ctrlstate.rho);
  375. do {
  376. ZZ_p base = power(random_ZZ_p(), 2);
  377. ZZ_p target = power(random_ZZ_p(), 2);
  378. ctrlstate.base = rep(base);
  379. ctrlstate.target = rep(target);
  380. // Decompose it mod p and mod q
  381. ctrlstate.subproblems_p = decomp(base, target, ctrlstate.p);
  382. ctrlstate.subproblems_q = decomp(base, target, ctrlstate.q);
  383. num_subproblems_p = ctrlstate.subproblems_p.size();
  384. num_subproblems_q = ctrlstate.subproblems_q.size();
  385. } while (num_subproblems_p == 0 || num_subproblems_q == 0);
  386. ctrlstate.num_unsolved_subproblems =
  387. num_subproblems_p + num_subproblems_q;
  388. schedule();
  389. return 0;
  390. }
  391. typedef enum {
  392. CCSTATE_START,
  393. CCSTATE_DPWAITRESP,
  394. CCSTATE_DPLISTENING,
  395. CCSTATE_DPEXPON,
  396. CCSTATE_END
  397. } CCState;
  398. struct ControllerConnInfo {
  399. CCState state;
  400. ControllerConnInfo() : state(CCSTATE_DPWAITRESP) {}
  401. };
  402. static void controller_dpnode_reader(struct bufferevent *bev, void *ctx)
  403. {
  404. struct evbuffer *input = bufferevent_get_input(bev);
  405. ControllerConnInfo *info = (ControllerConnInfo *)ctx;
  406. unsigned char cmd[1];
  407. ZZ expon;
  408. while(1) {
  409. size_t len = evbuffer_get_length(input);
  410. switch (info->state) {
  411. case CCSTATE_START:
  412. case CCSTATE_DPWAITRESP:
  413. if (len < 1) return;
  414. bufferevent_read(bev, cmd, 1);
  415. switch (cmd[0]) {
  416. case 'L':
  417. info->state = CCSTATE_DPLISTENING;
  418. break;
  419. case 'E':
  420. info->state = CCSTATE_DPEXPON;
  421. break;
  422. default:
  423. /* Unknown DPnode command received */
  424. fprintf(stderr, "Unknown command in "
  425. "controller_dpnode_reader: "
  426. "%c\n", cmd[0]);
  427. info->state = CCSTATE_END;
  428. break;
  429. }
  430. break;
  431. case CCSTATE_DPLISTENING:
  432. // Read 6 bytes
  433. if (len < 6) return;
  434. unsigned char ipport[6];
  435. unsigned int DPip;
  436. unsigned short DPport;
  437. bufferevent_read(bev, ipport, 6);
  438. memmove(&DPip, ipport, 4);
  439. memmove(&DPport, ipport+4, 2);
  440. {
  441. struct in_addr DPaddr = { DPip };
  442. #ifdef DEBUG
  443. fprintf(stderr, "DP node at %s:%d\n", inet_ntoa(DPaddr), ntohs(DPport));
  444. #endif
  445. if (ctrlstate.dpnodes.working.count(bev) > 0) {
  446. ctrlstate.dpnodes.working[bev]->ipports.push_back(
  447. IPPort(ipport));
  448. schedule();
  449. }
  450. }
  451. info->state = CCSTATE_DPWAITRESP;
  452. break;
  453. case CCSTATE_DPEXPON:
  454. // Read the subproblemid and the answer to the subproblem
  455. if (len < 2 + 3*sizeof(unsigned int)) return;
  456. unsigned char exponbytes[2 + 3*sizeof(unsigned int)];
  457. unsigned short problemid;
  458. bufferevent_read(bev, exponbytes, 2 + 3*sizeof(unsigned int));
  459. memmove(&problemid, exponbytes, 2);
  460. ZZFromBytes(expon, exponbytes+2, 3*sizeof(unsigned int));
  461. // Find the subproblem and check the answer
  462. if (ctrlstate.dpnodes.working.count(bev) > 0) {
  463. SubproblemProgress *spp = ctrlstate.dpnodes.working[bev];
  464. if (spp->problemid == problemid &&
  465. spp->solved == false &&
  466. spp->target ==
  467. PowerMod(spp->base, expon, spp->modulus)) {
  468. // Subproblem solved!
  469. spp->solution = expon;
  470. spp->solved = true;
  471. spp->stop();
  472. ctrlstate.num_unsolved_subproblems--;
  473. if (ctrlstate.num_unsolved_subproblems == 0) {
  474. computation_complete();
  475. generate_problem(bufferevent_get_base(bev));
  476. ctrlstate.dump(cerr);
  477. }
  478. schedule();
  479. }
  480. }
  481. info->state = CCSTATE_DPWAITRESP;
  482. break;
  483. case CCSTATE_END:
  484. // Shut down the connection
  485. delete info;
  486. bufferevent_free(bev);
  487. return;
  488. }
  489. }
  490. }
  491. static void controller_dpnode_event_cb(struct bufferevent *bev, short events,
  492. void *ctx)
  493. {
  494. if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
  495. ControllerConnInfo *info = (ControllerConnInfo*)ctx;
  496. fprintf(stderr, "Closing dpnode connection\n");
  497. if (ctrlstate.dpnodes.working.count(bev)) {
  498. // If we lose a dpnode from an active computation, the
  499. // computation is useless.
  500. SubproblemProgress *spp = ctrlstate.dpnodes.working[bev];
  501. ctrlstate.dpnodes.working.erase(bev);
  502. spp->dpnodes.erase(bev);
  503. spp->stop();
  504. } else {
  505. ctrlstate.dpnodes.idle.erase(bev);
  506. }
  507. delete info;
  508. bufferevent_free(bev);
  509. schedule();
  510. }
  511. }
  512. static void controller_worker_event_cb(struct bufferevent *bev, short events,
  513. void *ctx)
  514. {
  515. if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
  516. ControllerConnInfo *info = (ControllerConnInfo*)ctx;
  517. fprintf(stderr, "Closing worker connection\n");
  518. if (ctrlstate.workers.working.count(bev)) {
  519. SubproblemProgress *spp = ctrlstate.workers.working[bev];
  520. ctrlstate.workers.working.erase(bev);
  521. spp->workers.erase(bev);
  522. } else {
  523. ctrlstate.workers.idle.erase(bev);
  524. }
  525. delete info;
  526. bufferevent_free(bev);
  527. schedule();
  528. }
  529. }
  530. static void controller_event_cb(struct bufferevent *bev, short events,
  531. void *ctx)
  532. {
  533. if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
  534. fprintf(stderr, "Closing connection\n");
  535. ControllerConnInfo *info = (ControllerConnInfo*)ctx;
  536. delete info;
  537. bufferevent_free(bev);
  538. }
  539. }
  540. // We're just going to read a single byte that will tell us whether the
  541. // peer is a DPnode or a Worker
  542. static void controller_master_reader(struct bufferevent *bev, void *ctx)
  543. {
  544. struct evbuffer *input = bufferevent_get_input(bev);
  545. size_t len = evbuffer_get_length(input);
  546. if (len < 1) return;
  547. char indata[1];
  548. bufferevent_read(bev, indata, 1);
  549. switch(indata[0]) {
  550. case 'D':
  551. /* Add this DPnode to the list of available ones */
  552. ctrlstate.dpnodes.idle.insert(bev);
  553. bufferevent_setcb(bev, controller_dpnode_reader, NULL,
  554. controller_dpnode_event_cb, ctx);
  555. controller_dpnode_reader(bev, ctx);
  556. schedule();
  557. return;
  558. case 'W':
  559. ctrlstate.workers.idle.insert(bev);
  560. // We don't actually read anything from workers
  561. bufferevent_enable(bev, EV_WRITE);
  562. bufferevent_setcb(bev, NULL, NULL,
  563. controller_worker_event_cb, ctx);
  564. schedule();
  565. return;
  566. default:
  567. fprintf(stderr, "Unknown command in controller_master_reader: "
  568. "%c\n", indata[0]);
  569. ControllerConnInfo *info = (ControllerConnInfo*)ctx;
  570. delete info;
  571. bufferevent_free(bev);
  572. return;
  573. }
  574. }
  575. static void controller_accept_cb(struct evconnlistener *listener,
  576. evutil_socket_t fd, struct sockaddr *address, int socklen,
  577. void *ctx)
  578. {
  579. // Create the state of the new connection
  580. ControllerConnInfo *info = new ControllerConnInfo();
  581. // Create a bufferevent for the new connection
  582. struct event_base *base = evconnlistener_get_base(listener);
  583. struct bufferevent *bev = bufferevent_socket_new(
  584. base, fd, BEV_OPT_CLOSE_ON_FREE);
  585. bufferevent_setcb(bev, controller_master_reader, NULL,
  586. controller_event_cb, info);
  587. bufferevent_enable(bev, EV_READ|EV_WRITE);
  588. }
  589. // Create a new controller socket. bindport is the port to bind to (in
  590. // host byte order), or 0 if any port will do. ip and boundport are set
  591. // to the IP and port of the socket, in network byte order.
  592. void *controller_create(struct event_base *evbase, unsigned short bindport,
  593. unsigned int *ip, unsigned short *boundport)
  594. {
  595. return listener_create(evbase, bindport, controller_accept_cb, NULL,
  596. ip, boundport, false);
  597. }
  598. int main(int argc, char **argv)
  599. {
  600. // Initialize the prng with some randomness from the kernel
  601. unsigned char randbuf[1024];
  602. ifstream urand("/dev/urandom");
  603. urand.read((char *)randbuf, sizeof(randbuf));
  604. urand.close();
  605. ZZ randzz = ZZFromBytes(randbuf, sizeof(randbuf));
  606. SetSeed(randzz);
  607. // Read the modulus and the factorization of its totient from cin
  608. cin >> ctrlstate.rho >> ctrlstate.p.factor >> ctrlstate.p.fvec >>
  609. ctrlstate.q.factor >> ctrlstate.q.fvec;
  610. unsigned short bindport = 0;
  611. if (argc > 1) {
  612. bindport = strtoul(argv[1], NULL, 10);
  613. }
  614. struct event_base *evbase = event_base_new();
  615. unsigned int myip;
  616. unsigned short myport;
  617. controller_create(evbase, bindport, &myip, &myport);
  618. struct in_addr myaddr = { myip };
  619. printf("Bound to %s:%d\n", inet_ntoa(myaddr), ntohs(myport));
  620. // Kick off the first problem to solve
  621. generate_problem(evbase);
  622. event_base_dispatch(evbase);
  623. return 0;
  624. }