You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
4.4 KiB
151 lines
4.4 KiB
#include <memory>
|
|
#include <string>
|
|
#include <stdexcept>
|
|
|
|
#include <lib/libwebsockets.h>
|
|
#include "websockets.h"
|
|
|
|
#include "json.h"
|
|
#include "json_ext.h"
|
|
|
|
#include "basics.h"
|
|
#include "app.h"
|
|
|
|
|
|
std::unique_ptr<App> app;
|
|
|
|
using namespace websockets;
|
|
|
|
websockets::TestProtocol<User> 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<cheap_line_type>(object["data"]));
|
|
std::cout << "Line from: " << &user << ": " << user.name << std::endl;
|
|
request_write(binfo);
|
|
} else if (command == "remove line"){
|
|
app->remove_line(from_json<int>(object["data"]));
|
|
request_write(binfo);
|
|
} else if (command == "update user") {
|
|
user = from_json<IncomingPacket>(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<Empty> 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<cheap_line_type>(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<cheap_ball_type>(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();});
|
|
}
|
|
|