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.
136 lines
2.8 KiB
136 lines
2.8 KiB
|
|
#include <string>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <chrono>
|
|
#include <cmath>
|
|
|
|
#include <lib/libwebsockets.h>
|
|
#include "json.h"
|
|
#include "websockets.h"
|
|
|
|
template <typename C>
|
|
inline js::Value ptrvector_to_json(C const & container){
|
|
js::Array array;
|
|
for(auto x : container){
|
|
array.push_back(to_json(*x));
|
|
}
|
|
return array;
|
|
}
|
|
|
|
BOOST_FUSION_DEFINE_STRUCT(
|
|
, Size,
|
|
(int, width)
|
|
(int, height)
|
|
)
|
|
|
|
BOOST_FUSION_DEFINE_STRUCT(
|
|
, Position,
|
|
(int, x)
|
|
(int, y)
|
|
)
|
|
|
|
BOOST_FUSION_DEFINE_STRUCT(
|
|
, IncomingPacket,
|
|
(std::string, name)
|
|
(Size, size)
|
|
)
|
|
|
|
int uid = 0;
|
|
struct User {
|
|
unsigned int index{0};
|
|
std::string name{"Unknown guest"};
|
|
|
|
Size size{0,0};
|
|
Position position{0,0};
|
|
|
|
User()
|
|
: index(uid++)
|
|
{}
|
|
|
|
User& operator=(IncomingPacket const & p){
|
|
name = p.name;
|
|
size = p.size;
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
BOOST_FUSION_ADAPT_STRUCT(
|
|
User,
|
|
(unsigned int, index)
|
|
(std::string, name)
|
|
(Size, size)
|
|
(Position, position)
|
|
)
|
|
|
|
// unfortunately libwebsockets owns the user thingy
|
|
std::vector<User*> people_online;
|
|
|
|
inline void update_positions(){
|
|
typedef std::chrono::duration<double, std::ratio<1,1>> fseconds;
|
|
static auto start = std::chrono::steady_clock::now();
|
|
auto end = std::chrono::steady_clock::now();
|
|
double time = std::chrono::duration_cast<fseconds>(end-start).count();
|
|
|
|
//std::cout << time << std::endl;
|
|
auto n = people_online.size();
|
|
for(int i = 0; i < n; ++i){
|
|
User& user = *people_online[i];
|
|
double x = cos(0.1 * time + 2*M_PI*i/double(n));
|
|
double y = sin(0.1 * time + 2*M_PI*i/double(n));
|
|
|
|
user.position.x = 200 + 180*x;
|
|
user.position.y = 200 + 180*y;
|
|
}
|
|
}
|
|
|
|
|
|
websockets::TestProtocol<User> default_protocol{
|
|
// connection established
|
|
[](User& user){
|
|
people_online.push_back(&user);
|
|
},
|
|
// connection closed
|
|
[](User& user){
|
|
people_online.erase(std::remove(people_online.begin(), people_online.end(), &user), people_online.end());
|
|
},
|
|
// write (will always come after receive)
|
|
[](User& user) -> std::string{
|
|
update_positions();
|
|
return write_json(ptrvector_to_json(people_online));
|
|
},
|
|
// receive
|
|
[](User& user, std::string in){
|
|
try{
|
|
user = from_json<IncomingPacket>(parse_json(in));
|
|
} catch(std::exception& e) {
|
|
throw websockets::runtime_error(e.what());
|
|
}
|
|
}
|
|
};
|
|
|
|
struct Empty{};
|
|
|
|
websockets::TestProtocol<Empty> observer_protocol{
|
|
// connection established
|
|
[](Empty& user){},
|
|
// connection closed
|
|
[](Empty& user){},
|
|
// write (will always come after receive)
|
|
[](Empty& user) -> std::string{
|
|
update_positions();
|
|
return write_json(ptrvector_to_json(people_online));
|
|
},
|
|
// receive
|
|
[](Empty& user, std::string in){}
|
|
};
|
|
|
|
int main(int argc, char **argv){
|
|
libwebsocket_protocols protocols[] = {
|
|
WSstandard_protocol("default", default_protocol),
|
|
WSstandard_protocol("observer", observer_protocol),
|
|
{ NULL, NULL, 0 } // end of list
|
|
};
|
|
|
|
return websockets::default_main(argc, argv, protocols);
|
|
}
|
|
|