| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- extern "C" {
- #include <event2/listener.h>
- #include <event2/bufferevent.h>
- #include <event2/buffer.h>
- #include <event2/util.h>
- }
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <set>
- #include <map>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include "evutils.h"
- #include "subproblem.h"
- #include "dpnode.h"
- typedef map<std::string, pair<ZZ,ZZ> > DTable;
- typedef enum {
- DPSTATE_START,
- DPSTATE_END
- } DPState;
- struct DPNodeConnInfo {
- DPState state;
- DPNodeConnInfo() : state(DPSTATE_START) {}
- };
- static struct DPControllerState {
- struct bufferevent *controller_bev;
- Subproblem *current_problem;
- struct evconnlistener *listener;
- std::set<struct bufferevent *> workers;
- DTable table;
- unsigned long long numdps;
- DPControllerState() : controller_bev(NULL), current_problem(NULL),
- listener(NULL) {}
- } dpctrlstate;
- static void dpnode_event_cb(struct bufferevent *bev, short events,
- void *ctx)
- {
- if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
- cerr << "Closing connection " << bev << " ";
- if (events & BEV_EVENT_EOF) {
- cerr << "EOF";
- }
- if (events & BEV_EVENT_ERROR) {
- cerr << "ERR (" << evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()) << ")";
- }
- cerr << "\n";
- DPNodeConnInfo *info = (DPNodeConnInfo*)ctx;
- delete info;
- dpctrlstate.workers.erase(bev);
- bufferevent_free(bev);
- }
- }
- static void stop_problem(void);
- static void dpnode_reader(struct bufferevent *bev, void *ctx)
- {
- struct evbuffer *input = bufferevent_get_input(bev);
- unsigned int dp[WORDS+6];
- while(1) {
- size_t len = evbuffer_get_length(input);
- if (len < ((WORDS+6)*sizeof(unsigned int))) break;
- bufferevent_read(bev, dp, (WORDS+6)*sizeof(unsigned int));
- if (dpctrlstate.current_problem == NULL) continue;
- // The (WORDS+6) unsigned ints we read are:
- // - WORDS words for the value of the dp
- // - 3 words for a
- // - 3 words for b
- ZZ zz_a, zz_b;
- ZZFromBytes(zz_a, (const unsigned char *)(dp+WORDS),
- 3*sizeof(unsigned int));
- ZZFromBytes(zz_b, (const unsigned char *)(dp+WORDS+3),
- 3*sizeof(unsigned int));
- string x((const char *)(dp), WORDS*sizeof(unsigned int));
- pair<ZZ,ZZ> ab(zz_a,zz_b);
- pair<DTable::iterator, bool> res =
- dpctrlstate.table.insert(DTable::value_type(x,ab));
- if (!res.second) {
- const ZZ& order = dpctrlstate.current_problem->order;
- // Collision!
- ZZ adiff = res.first->second.first - zz_a;
- ZZ bdiff = zz_b - res.first->second.second;
- while (bdiff < 0) bdiff += order;
- while (bdiff >= order) bdiff -= order;
- while (adiff < 0) adiff += order;
- while (adiff >= order) adiff -= order;
- ZZ binv;
- if (InvModStatus(binv, bdiff, order) == 0) {
- ZZ expon = MulMod(binv, adiff, order);
- cerr << "Collision after " << dpctrlstate.numdps << " DPs\n";
- unsigned char exponbytes[3+3*sizeof(unsigned int)];
- exponbytes[0] = 'E';
- memmove(exponbytes+1,
- &(dpctrlstate.current_problem->problemid), 2);
- BytesFromZZ(exponbytes+3, expon, 3*sizeof(unsigned int));
- bufferevent_write(dpctrlstate.controller_bev, exponbytes,
- 3+3*sizeof(unsigned int));
- stop_problem();
- return;
- }
- }
- ++dpctrlstate.numdps;
- }
- }
- static void dpnode_accept_cb(struct evconnlistener *listener,
- evutil_socket_t fd, struct sockaddr *address, int socklen,
- void *ctx)
- {
- DPNodeConnInfo *info = new DPNodeConnInfo();
- // Create a bufferevent for the new connection
- struct event_base *base = evconnlistener_get_base(listener);
- struct bufferevent *bev = bufferevent_socket_new(
- base, fd, BEV_OPT_CLOSE_ON_FREE);
- cerr << "accepted connection " << bev << "\n";
- bufferevent_setcb(bev, dpnode_reader, NULL,
- dpnode_event_cb, info);
- bufferevent_enable(bev, EV_READ);
- dpctrlstate.workers.insert(bev);
- }
- // Create a new DPnode socket. ip and boundport are set to the IP and
- // port of the socket, in network byte order.
- struct evconnlistener *dpnode_create(struct event_base *evbase,
- unsigned int *ip, unsigned short *boundport)
- {
- struct evconnlistener *ecl = listener_create(evbase, 0,
- dpnode_accept_cb, NULL, ip, boundport, false);
- cerr << "Listening at " << ecl << "\n";
- return ecl;
- }
- typedef enum {
- DPCCSTATE_AWAITCMD,
- DPCCSTATE_RDPROBLEM,
- DPCCSTATE_END
- } DPCCState;
- struct DPControllerConnInfo {
- DPCCState state;
- DPControllerConnInfo() : state(DPCCSTATE_AWAITCMD) {}
- };
- static void stop_problem(void)
- {
- cerr << "Stopping problem\n";
- if (dpctrlstate.current_problem) {
- delete dpctrlstate.current_problem;
- dpctrlstate.current_problem = NULL;
- }
- if (dpctrlstate.listener) {
- cerr << "Closing listener " << dpctrlstate.listener << "\n";
- evconnlistener_free(dpctrlstate.listener);
- dpctrlstate.listener = NULL;
- }
- std::set<struct bufferevent *>::iterator wit;
- for (wit = dpctrlstate.workers.begin(); wit != dpctrlstate.workers.end();
- ++wit) {
- cerr << "Closing connection " << *wit << "\n";
- bufferevent_free(*wit);
- }
- dpctrlstate.workers.clear();
- dpctrlstate.table.clear();
- dpctrlstate.numdps = 0;
- }
- static void start_problem(struct bufferevent *bev,
- const unsigned char *subproblem)
- {
- unsigned int myip;
- unsigned short myport;
- stop_problem();
- dpctrlstate.current_problem = new Subproblem(subproblem);
- dpctrlstate.current_problem->dump(cerr);
- // Create the DPNode server socket
- dpctrlstate.listener = dpnode_create(bufferevent_get_base(bev),
- &myip, &myport);
- struct in_addr myaddr = { myip };
- fprintf(stderr, "Bound to %s:%d\n", inet_ntoa(myaddr), ntohs(myport));
- unsigned char idstring[7];
- idstring[0] = 'L';
- memmove(idstring+1, &myip, 4);
- memmove(idstring+5, &myport, 2);
- bufferevent_write(bev, idstring, 7);
- }
- static void controllerconn_reader(struct bufferevent *bev, void *ctx)
- {
- struct evbuffer *input = bufferevent_get_input(bev);
- DPControllerConnInfo *info = (DPControllerConnInfo *)ctx;
- unsigned char cmd[1];
- unsigned char subproblem[SUBPROBLEM_DESC_LEN];
- while(1) {
- size_t len = evbuffer_get_length(input);
- switch(info->state) {
- case DPCCSTATE_AWAITCMD:
- if (len < 1) return;
- bufferevent_read(bev, cmd, 1);
- cerr << "Received command " << cmd[0] << "\n";
- switch(cmd[0]) {
- case 'P':
- info->state = DPCCSTATE_RDPROBLEM;
- break;
- case 'S':
- stop_problem();
- break;
- default:
- /* Unknown command received */
- fprintf(stderr, "Unknown command in "
- "controllerconn_reader: %c\n", cmd[0]);
- info->state = DPCCSTATE_END;
- break;
- }
- break;
- case DPCCSTATE_RDPROBLEM:
- if (len < SUBPROBLEM_DESC_LEN) return;
- bufferevent_read(bev, subproblem, SUBPROBLEM_DESC_LEN);
- start_problem(bev, subproblem);
- info->state = DPCCSTATE_AWAITCMD;
- break;
- case DPCCSTATE_END:
- // Shut down
- delete info;
- event_base_loopbreak(bufferevent_get_base(bev));
- cerr << "END conenction " << bev << "\n";
- dpctrlstate.workers.erase(bev);
- bufferevent_free(bev);
- return;
- }
- }
- }
- static void controllerconn_event_cb(struct bufferevent *bev, short events,
- void *ctx)
- {
- if (events & BEV_EVENT_CONNECTED) {
- // We have successfully connected to the controller
- char id[1] = { 'D' };
- bufferevent_enable(bev, EV_READ|EV_WRITE);
- bufferevent_write(bev, id, 1);
- bufferevent_setcb(bev, controllerconn_reader, NULL,
- controllerconn_event_cb, new DPControllerConnInfo());
- dpctrlstate.controller_bev = bev;
- } else if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
- fprintf(stderr, "Closing connection to controller and exiting\n");
- event_base_loopbreak(bufferevent_get_base(bev));
- bufferevent_free(bev);
- }
- }
- int dpnode_main(const char *controller_host, unsigned short controller_port)
- {
- return controller_client(controller_host, controller_port,
- controllerconn_event_cb, false);
- }
|