dpnode.cc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. extern "C" {
  2. #include <event2/listener.h>
  3. #include <event2/bufferevent.h>
  4. #include <event2/buffer.h>
  5. #include <event2/util.h>
  6. }
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <set>
  11. #include <map>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <errno.h>
  15. #include "evutils.h"
  16. #include "subproblem.h"
  17. typedef map<std::string, pair<ZZ,ZZ> > DTable;
  18. typedef enum {
  19. DPSTATE_START,
  20. DPSTATE_END
  21. } DPState;
  22. struct DPNodeConnInfo {
  23. DPState state;
  24. DPNodeConnInfo() : state(DPSTATE_START) {}
  25. };
  26. static struct DPControllerState {
  27. struct bufferevent *controller_bev;
  28. Subproblem *current_problem;
  29. struct evconnlistener *listener;
  30. std::set<struct bufferevent *> workers;
  31. DTable table;
  32. unsigned long long numdps;
  33. DPControllerState() : controller_bev(NULL), current_problem(NULL),
  34. listener(NULL) {}
  35. } dpctrlstate;
  36. static void dpnode_event_cb(struct bufferevent *bev, short events,
  37. void *ctx)
  38. {
  39. if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
  40. cerr << "Closing connection " << bev << " ";
  41. if (events & BEV_EVENT_EOF) {
  42. cerr << "EOF";
  43. }
  44. if (events & BEV_EVENT_ERROR) {
  45. cerr << "ERR (" << evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()) << ")";
  46. }
  47. cerr << "\n";
  48. DPNodeConnInfo *info = (DPNodeConnInfo*)ctx;
  49. delete info;
  50. dpctrlstate.workers.erase(bev);
  51. bufferevent_free(bev);
  52. }
  53. }
  54. static void stop_problem(void);
  55. static void dpnode_reader(struct bufferevent *bev, void *ctx)
  56. {
  57. struct evbuffer *input = bufferevent_get_input(bev);
  58. unsigned int dp[WORDS+6];
  59. while(1) {
  60. size_t len = evbuffer_get_length(input);
  61. if (len < ((WORDS+6)*sizeof(unsigned int))) break;
  62. bufferevent_read(bev, dp, (WORDS+6)*sizeof(unsigned int));
  63. if (dpctrlstate.current_problem == NULL) continue;
  64. // The (WORDS+6) unsigned ints we read are:
  65. // - WORDS words for the value of the dp
  66. // - 3 words for a
  67. // - 3 words for b
  68. ZZ zz_a, zz_b;
  69. ZZFromBytes(zz_a, (const unsigned char *)(dp+WORDS),
  70. 3*sizeof(unsigned int));
  71. ZZFromBytes(zz_b, (const unsigned char *)(dp+WORDS+3),
  72. 3*sizeof(unsigned int));
  73. string x((const char *)(dp), WORDS*sizeof(unsigned int));
  74. pair<ZZ,ZZ> ab(zz_a,zz_b);
  75. pair<DTable::iterator, bool> res =
  76. dpctrlstate.table.insert(DTable::value_type(x,ab));
  77. if (!res.second) {
  78. const ZZ& order = dpctrlstate.current_problem->order;
  79. // Collision!
  80. ZZ adiff = res.first->second.first - zz_a;
  81. ZZ bdiff = zz_b - res.first->second.second;
  82. while (bdiff < 0) bdiff += order;
  83. while (bdiff >= order) bdiff -= order;
  84. while (adiff < 0) adiff += order;
  85. while (adiff >= order) adiff -= order;
  86. ZZ binv;
  87. if (InvModStatus(binv, bdiff, order) == 0) {
  88. ZZ expon = MulMod(binv, adiff, order);
  89. cerr << "Collision after " << dpctrlstate.numdps << " DPs\n";
  90. unsigned char exponbytes[3+3*sizeof(unsigned int)];
  91. exponbytes[0] = 'E';
  92. memmove(exponbytes+1,
  93. &(dpctrlstate.current_problem->problemid), 2);
  94. BytesFromZZ(exponbytes+3, expon, 3*sizeof(unsigned int));
  95. bufferevent_write(dpctrlstate.controller_bev, exponbytes,
  96. 3+3*sizeof(unsigned int));
  97. stop_problem();
  98. return;
  99. }
  100. }
  101. ++dpctrlstate.numdps;
  102. }
  103. }
  104. static void dpnode_accept_cb(struct evconnlistener *listener,
  105. evutil_socket_t fd, struct sockaddr *address, int socklen,
  106. void *ctx)
  107. {
  108. DPNodeConnInfo *info = new DPNodeConnInfo();
  109. // Create a bufferevent for the new connection
  110. struct event_base *base = evconnlistener_get_base(listener);
  111. struct bufferevent *bev = bufferevent_socket_new(
  112. base, fd, BEV_OPT_CLOSE_ON_FREE);
  113. cerr << "accepted connection " << bev << "\n";
  114. bufferevent_setcb(bev, dpnode_reader, NULL,
  115. dpnode_event_cb, info);
  116. bufferevent_enable(bev, EV_READ);
  117. dpctrlstate.workers.insert(bev);
  118. }
  119. // Create a new DPnode socket. ip and boundport are set to the IP and
  120. // port of the socket, in network byte order.
  121. struct evconnlistener *dpnode_create(struct event_base *evbase,
  122. unsigned int *ip, unsigned short *boundport)
  123. {
  124. struct evconnlistener *ecl = listener_create(evbase, 0,
  125. dpnode_accept_cb, NULL, ip, boundport, false);
  126. cerr << "Listening at " << ecl << "\n";
  127. return ecl;
  128. }
  129. typedef enum {
  130. DPCCSTATE_AWAITCMD,
  131. DPCCSTATE_RDPROBLEM,
  132. DPCCSTATE_END
  133. } DPCCState;
  134. struct DPControllerConnInfo {
  135. DPCCState state;
  136. DPControllerConnInfo() : state(DPCCSTATE_AWAITCMD) {}
  137. };
  138. static void stop_problem(void)
  139. {
  140. cerr << "Stopping problem\n";
  141. if (dpctrlstate.current_problem) {
  142. delete dpctrlstate.current_problem;
  143. dpctrlstate.current_problem = NULL;
  144. }
  145. if (dpctrlstate.listener) {
  146. cerr << "Closing listener " << dpctrlstate.listener << "\n";
  147. evconnlistener_free(dpctrlstate.listener);
  148. dpctrlstate.listener = NULL;
  149. }
  150. std::set<struct bufferevent *>::iterator wit;
  151. for (wit = dpctrlstate.workers.begin(); wit != dpctrlstate.workers.end();
  152. ++wit) {
  153. cerr << "Closing connection " << *wit << "\n";
  154. bufferevent_free(*wit);
  155. }
  156. dpctrlstate.workers.clear();
  157. dpctrlstate.table.clear();
  158. dpctrlstate.numdps = 0;
  159. }
  160. static void start_problem(struct bufferevent *bev,
  161. const unsigned char *subproblem)
  162. {
  163. unsigned int myip;
  164. unsigned short myport;
  165. stop_problem();
  166. dpctrlstate.current_problem = new Subproblem(subproblem);
  167. dpctrlstate.current_problem->dump(cerr);
  168. // Create the DPNode server socket
  169. dpctrlstate.listener = dpnode_create(bufferevent_get_base(bev),
  170. &myip, &myport);
  171. struct in_addr myaddr = { myip };
  172. fprintf(stderr, "Bound to %s:%d\n", inet_ntoa(myaddr), ntohs(myport));
  173. unsigned char idstring[7];
  174. idstring[0] = 'L';
  175. memmove(idstring+1, &myip, 4);
  176. memmove(idstring+5, &myport, 2);
  177. bufferevent_write(bev, idstring, 7);
  178. }
  179. static void controllerconn_reader(struct bufferevent *bev, void *ctx)
  180. {
  181. struct evbuffer *input = bufferevent_get_input(bev);
  182. DPControllerConnInfo *info = (DPControllerConnInfo *)ctx;
  183. unsigned char cmd[1];
  184. unsigned char subproblem[SUBPROBLEM_DESC_LEN];
  185. while(1) {
  186. size_t len = evbuffer_get_length(input);
  187. switch(info->state) {
  188. case DPCCSTATE_AWAITCMD:
  189. if (len < 1) return;
  190. bufferevent_read(bev, cmd, 1);
  191. cerr << "Received command " << cmd[0] << "\n";
  192. switch(cmd[0]) {
  193. case 'P':
  194. info->state = DPCCSTATE_RDPROBLEM;
  195. break;
  196. case 'S':
  197. stop_problem();
  198. break;
  199. default:
  200. /* Unknown command received */
  201. fprintf(stderr, "Unknown command in "
  202. "controllerconn_reader: %c\n", cmd[0]);
  203. info->state = DPCCSTATE_END;
  204. break;
  205. }
  206. break;
  207. case DPCCSTATE_RDPROBLEM:
  208. if (len < SUBPROBLEM_DESC_LEN) return;
  209. bufferevent_read(bev, subproblem, SUBPROBLEM_DESC_LEN);
  210. start_problem(bev, subproblem);
  211. info->state = DPCCSTATE_AWAITCMD;
  212. break;
  213. case DPCCSTATE_END:
  214. // Shut down
  215. delete info;
  216. event_base_loopbreak(bufferevent_get_base(bev));
  217. cerr << "END conenction " << bev << "\n";
  218. dpctrlstate.workers.erase(bev);
  219. bufferevent_free(bev);
  220. return;
  221. }
  222. }
  223. }
  224. static void controllerconn_event_cb(struct bufferevent *bev, short events,
  225. void *ctx)
  226. {
  227. if (events & BEV_EVENT_CONNECTED) {
  228. // We have successfully connected to the controller
  229. char id[1] = { 'D' };
  230. bufferevent_enable(bev, EV_READ|EV_WRITE);
  231. bufferevent_write(bev, id, 1);
  232. bufferevent_setcb(bev, controllerconn_reader, NULL,
  233. controllerconn_event_cb, new DPControllerConnInfo());
  234. dpctrlstate.controller_bev = bev;
  235. } else if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
  236. fprintf(stderr, "Closing connection to controller and exiting\n");
  237. event_base_loopbreak(bufferevent_get_base(bev));
  238. bufferevent_free(bev);
  239. }
  240. }
  241. int main(int argc, char **argv)
  242. {
  243. if (argc != 3) {
  244. fprintf(stderr, "Usage: %s controller_host controller_port\n", argv[0]);
  245. return 1;
  246. }
  247. unsigned short controller_port = strtoul(argv[2], NULL, 10);
  248. return controller_client(argv[1], controller_port,
  249. controllerconn_event_cb, false);
  250. }