dpnode.cc 6.1 KB

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