#include #include #include #include #include "websockets.h" #include "json.h" #include "json_ext.h" #include "basics.h" #include "app.h" std::unique_ptr app; using namespace websockets; websockets::TestProtocol default_protocol{ // connection established [](User& user, basic_websocket_info){ app->login(user); std::cout << "New user!\n"; }, // connection closed [](User& user, basic_websocket_info){ app->logout(user); std::cout << "User left: " << &user << ": " << user.name << std::endl; }, // write (will always come after receive) [](User& user, basic_websocket_info) -> std::string{ js::Object ret; if(user.update_lines){ if(app->uberclient){ ret["lines"] = vector_to_json(app->offline_sim.lines); } else { ret["lines"] = vector_to_json(app->online_sim.lines, [](AbstractLine const & l){return cheap_line_type(l);}); } user.update_lines = false; } else { if(app->uberclient){ ret["balls"] = vector_to_json(app->offline_sim.balls, Identity(), [&user](cheap_ball_type const & b){ return user.is_inside(b); }); } else { ret["balls"] = vector_to_json(app->online_sim.sim.balls, [](ball_type const & b){return cheap_ball_type(b);}, [&user](ball_type const & b){ return user.is_inside(b); }); } } return write_json(ret); }, // receive [](User& user, std::string in, basic_websocket_info binfo){ try{ auto object = parse_json(in).getObject(); auto command = object["command"]; if(command == "add line"){ app->add_line(from_json(object["data"])); std::cout << "Line from: " << &user << ": " << user.name << std::endl; request_write(binfo); } else if (command == "remove line"){ app->remove_line(from_json(object["data"])); request_write(binfo); } else if (command == "update user") { user = from_json(object["data"]); std::cout << "Updated user: " << &user << ": " << user.name << std::endl; app->peeps = true; } else if (command == "poll") { request_write(binfo); } } catch(std::exception& e) { throw websockets::runtime_error(e.what()); } } }; websockets::TestProtocol uberclient_protocol{ // connection established [](Empty& user, basic_websocket_info binfo){ std::cout << "uberclient connected!\n"; app->uberclient_connected(binfo); }, // connection closed [](Empty& user, basic_websocket_info binfo){ std::cout << "uberclient left!\n"; app->uberclient_disconnected(binfo); }, // write (will always come after receive) [](Empty& user, basic_websocket_info) -> std::string{ if(app->peeps){ app->peeps = false; std::string str; for(auto & u : app->people_online){ str += u->name; if(u != app->people_online.back()) str += ", "; } js::Object ret; ret["command"] = "peeps"; ret["data"] = to_json(str); return write_json(ret); } if(!app->offline_sim.lines_to_remove.empty()){ js::Object ret; ret["command"] = "remove lines"; ret["data"] = vector_to_json(app->offline_sim.lines_to_remove); app->offline_sim.lines_to_remove.clear(); return write_json(ret); } if(!app->offline_sim.lines_to_add.empty()){ js::Object ret; ret["command"] = "add lines"; ret["data"] = vector_to_json(app->offline_sim.lines_to_add); app->offline_sim.lines_to_add.clear(); return write_json(ret); } return ""; }, // receive [](Empty& user, std::string in, basic_websocket_info binfo){ auto object = parse_json(in).getObject(); if(object.count("lines")){ app->offline_sim.lines.clear(); auto lines = object["lines"]; for(auto&& js : lines.getArray()){ app->offline_sim.lines.push_back(from_json(js)); } app->lines_changed(); } if(object.count("balls")){ app->offline_sim.balls.clear(); auto balls = object["balls"]; for(auto&& js : balls.getArray()){ app->offline_sim.balls.push_back(from_json(js)); } } if(app->peeps || !app->offline_sim.lines_to_add.empty() || !app->offline_sim.lines_to_remove.empty()){ request_write(binfo); } } }; int main(int argc, char **argv){ app.reset(new App); libwebsocket_protocols protocols[] = { WSstandard_protocol("default", default_protocol), WSstandard_protocol("uberclient", uberclient_protocol), { NULL, NULL, 0 } // end of list }; return websockets::default_main(argc, argv, protocols, []{app->update();}); }