dpnode.cc 7.2 KB

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