Websockets: added callback in runloop, added more info to protocols
This commit is contained in:
parent
ad010c5ab4
commit
8882fe3952
6 changed files with 80 additions and 18 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -4,3 +4,6 @@
|
||||||
[submodule "contrib/json-spirit"]
|
[submodule "contrib/json-spirit"]
|
||||||
path = contrib/json-spirit
|
path = contrib/json-spirit
|
||||||
url = git://github.com/sirikata/json-spirit.git
|
url = git://github.com/sirikata/json-spirit.git
|
||||||
|
[submodule "simulation"]
|
||||||
|
path = simulation
|
||||||
|
url = git@github.com:Jaxan/beats-sim.git
|
||||||
|
|
1
simulation
Submodule
1
simulation
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 018cb176c4b3970cd2a6ecae8a63520183c5ddd3
|
31
src/adaptions.h
Normal file
31
src/adaptions.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <boost/fusion/include/define_struct.hpp>
|
||||||
|
#include <boost/fusion/include/adapt_struct.hpp>
|
||||||
|
|
||||||
|
#include "simulation/Simulation.h"
|
||||||
|
#include "simulation/Beat.h"
|
||||||
|
#include "simulation/math.h"
|
||||||
|
|
||||||
|
BOOST_FUSION_ADAPT_STRUCT(
|
||||||
|
::math::Vec2,
|
||||||
|
(float, x)
|
||||||
|
(float, y)
|
||||||
|
)
|
||||||
|
|
||||||
|
BOOST_FUSION_ADAPT_TPL_STRUCT(
|
||||||
|
(BallInfo),
|
||||||
|
(simulation::Ball) (BallInfo),
|
||||||
|
(BallInfo, information)
|
||||||
|
(::math::Vec2, position)
|
||||||
|
(::math::Vec2, speed)
|
||||||
|
)
|
||||||
|
|
||||||
|
BOOST_FUSION_ADAPT_TPL_STRUCT(
|
||||||
|
(LineInfo),
|
||||||
|
(simulation::Line) (LineInfo),
|
||||||
|
(::math::Vec2, starting_point)
|
||||||
|
(::math::Vec2, end_point)
|
||||||
|
(simulation::LineKind, line_kind)
|
||||||
|
)
|
18
src/main.cpp
18
src/main.cpp
|
@ -14,22 +14,24 @@
|
||||||
|
|
||||||
std::unique_ptr<App> app;
|
std::unique_ptr<App> app;
|
||||||
|
|
||||||
|
using namespace websockets;
|
||||||
|
|
||||||
websockets::TestProtocol<User> default_protocol{
|
websockets::TestProtocol<User> default_protocol{
|
||||||
// connection established
|
// connection established
|
||||||
[](User& user){
|
[](User& user, basic_websocket_info){
|
||||||
app->login(user);
|
app->login(user);
|
||||||
},
|
},
|
||||||
// connection closed
|
// connection closed
|
||||||
[](User& user){
|
[](User& user, basic_websocket_info){
|
||||||
app->logout(user);
|
app->logout(user);
|
||||||
},
|
},
|
||||||
// write (will always come after receive)
|
// write (will always come after receive)
|
||||||
[](User& user) -> std::string{
|
|
||||||
app->update_positions();
|
app->update_positions();
|
||||||
return write_json(ptrvector_to_json(app->people_online));
|
return write_json(ptrvector_to_json(app->people_online));
|
||||||
|
[](User& user, basic_websocket_info) -> std::string{
|
||||||
},
|
},
|
||||||
// receive
|
// receive
|
||||||
[](User& user, std::string in){
|
[](User& user, std::string in, basic_websocket_info){
|
||||||
try{
|
try{
|
||||||
user = from_json<IncomingPacket>(parse_json(in));
|
user = from_json<IncomingPacket>(parse_json(in));
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
|
@ -40,16 +42,16 @@ websockets::TestProtocol<User> default_protocol{
|
||||||
|
|
||||||
websockets::TestProtocol<Empty> observer_protocol{
|
websockets::TestProtocol<Empty> observer_protocol{
|
||||||
// connection established
|
// connection established
|
||||||
[](Empty& user){},
|
[](Empty& user, basic_websocket_info){},
|
||||||
// connection closed
|
// connection closed
|
||||||
[](Empty& user){},
|
[](Empty& user, basic_websocket_info){},
|
||||||
// write (will always come after receive)
|
// write (will always come after receive)
|
||||||
[](Empty& user) -> std::string{
|
|
||||||
app->update_positions();
|
app->update_positions();
|
||||||
return write_json(ptrvector_to_json(app->people_online));
|
return write_json(ptrvector_to_json(app->people_online));
|
||||||
|
[](Empty& user, basic_websocket_info) -> std::string{
|
||||||
},
|
},
|
||||||
// receive
|
// receive
|
||||||
[](Empty& user, std::string in){}
|
[](Empty& user, std::string in, basic_websocket_info){}
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char **argv){
|
int main(int argc, char **argv){
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
|
|
||||||
#include "websockets.h"
|
#include "websockets.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace websockets {
|
namespace websockets {
|
||||||
|
|
||||||
option options[] = {
|
option options[] = {
|
||||||
|
@ -11,7 +14,7 @@ namespace websockets {
|
||||||
{ NULL, 0, 0, 0 }
|
{ NULL, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
int default_main(int argc, char **argv, libwebsocket_protocols* protocols){
|
int default_main(int argc, char **argv, libwebsocket_protocols* protocols, std::function<void()> runloop_callback){
|
||||||
int port = 7681;
|
int port = 7681;
|
||||||
int use_ssl = 0;
|
int use_ssl = 0;
|
||||||
char interface_name[128] = "";
|
char interface_name[128] = "";
|
||||||
|
@ -63,9 +66,21 @@ namespace websockets {
|
||||||
static bool force_exit = false;
|
static bool force_exit = false;
|
||||||
signal(SIGINT, [](int){ force_exit = true; });
|
signal(SIGINT, [](int){ force_exit = true; });
|
||||||
|
|
||||||
|
|
||||||
|
using clock = std::chrono::steady_clock;
|
||||||
|
using duration = std::chrono::duration<double>;
|
||||||
while (!force_exit) {
|
while (!force_exit) {
|
||||||
|
auto begin = clock::now();
|
||||||
auto ret = libwebsocket_service(context.get_raw(), 10);
|
auto ret = libwebsocket_service(context.get_raw(), 10);
|
||||||
if(ret < 0) break;
|
if(ret < 0) break;
|
||||||
|
|
||||||
|
if(runloop_callback) runloop_callback();
|
||||||
|
|
||||||
|
auto end = clock::now();
|
||||||
|
duration dur = (end - begin);
|
||||||
|
dur = duration(1.0/60.0) - dur;
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(dur);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,15 @@ namespace websockets {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct basic_websocket_info{
|
||||||
|
libwebsocket_context* context{nullptr};
|
||||||
|
libwebsocket* wsi{nullptr};
|
||||||
|
basic_websocket_info(libwebsocket_context* context, libwebsocket* wsi)
|
||||||
|
: context(context)
|
||||||
|
, wsi(wsi)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
// 4-function Protocol, provide functions to handle establishment, closing, receiving and writing (follows receiving)
|
// 4-function Protocol, provide functions to handle establishment, closing, receiving and writing (follows receiving)
|
||||||
// To let the callback return something non-zero (in case of error), use websockets::runtime_error
|
// To let the callback return something non-zero (in case of error), use websockets::runtime_error
|
||||||
// Only types with no-arg ctor are allowed (uses placement new, because libwebsockets allocates for us)
|
// Only types with no-arg ctor are allowed (uses placement new, because libwebsockets allocates for us)
|
||||||
|
@ -95,10 +104,10 @@ namespace websockets {
|
||||||
struct TestProtocol {
|
struct TestProtocol {
|
||||||
typedef T user_type;
|
typedef T user_type;
|
||||||
|
|
||||||
std::function<void(user_type&)> establish_func;
|
std::function<void(user_type&, basic_websocket_info)> establish_func;
|
||||||
std::function<void(user_type&)> close_func;
|
std::function<void(user_type&, basic_websocket_info)> close_func;
|
||||||
std::function<std::string(user_type&)> write_func;
|
std::function<std::string(user_type&, basic_websocket_info)> write_func;
|
||||||
std::function<void(user_type&, std::string)> receive_func;
|
std::function<void(user_type&, std::string, basic_websocket_info)> receive_func;
|
||||||
|
|
||||||
bool verbose{false};
|
bool verbose{false};
|
||||||
|
|
||||||
|
@ -111,20 +120,21 @@ namespace websockets {
|
||||||
|
|
||||||
int callback(libwebsocket_context* context, libwebsocket* wsi, libwebsocket_callback_reasons reason, void* user_ptr, void *in, size_t len){
|
int callback(libwebsocket_context* context, libwebsocket* wsi, libwebsocket_callback_reasons reason, void* user_ptr, void *in, size_t len){
|
||||||
user_type& user = *static_cast<user_type*>(user_ptr);
|
user_type& user = *static_cast<user_type*>(user_ptr);
|
||||||
|
basic_websocket_info binfo{context, wsi};
|
||||||
try{
|
try{
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
case LWS_CALLBACK_ESTABLISHED:
|
case LWS_CALLBACK_ESTABLISHED:
|
||||||
lwsl_notice("Connection established (%p, %p)\n", this, user_ptr);
|
lwsl_notice("Connection established (%p, %p)\n", this, user_ptr);
|
||||||
new (user_ptr) user_type();
|
new (user_ptr) user_type();
|
||||||
establish_func(user);
|
establish_func(user, binfo);
|
||||||
break;
|
break;
|
||||||
case LWS_CALLBACK_CLOSED:
|
case LWS_CALLBACK_CLOSED:
|
||||||
lwsl_notice("Connection closed (%p, %p)\n", this, user_ptr);
|
lwsl_notice("Connection closed (%p, %p)\n", this, user_ptr);
|
||||||
user.~user_type();
|
user.~user_type();
|
||||||
close_func(user);
|
close_func(user, binfo);
|
||||||
break;
|
break;
|
||||||
case LWS_CALLBACK_SERVER_WRITEABLE:{
|
case LWS_CALLBACK_SERVER_WRITEABLE:{
|
||||||
std::string string_to_send = write_func(user);
|
std::string string_to_send = write_func(user, binfo);
|
||||||
if(verbose) std::cout << string_to_send << std::endl;
|
if(verbose) std::cout << string_to_send << std::endl;
|
||||||
// we need the extra bytes padding on both sides :(
|
// we need the extra bytes padding on both sides :(
|
||||||
unsigned char * buf = new unsigned char [LWS_SEND_BUFFER_PRE_PADDING + string_to_send.size() + LWS_SEND_BUFFER_POST_PADDING];
|
unsigned char * buf = new unsigned char [LWS_SEND_BUFFER_PRE_PADDING + string_to_send.size() + LWS_SEND_BUFFER_POST_PADDING];
|
||||||
|
@ -135,7 +145,7 @@ namespace websockets {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LWS_CALLBACK_RECEIVE:
|
case LWS_CALLBACK_RECEIVE:
|
||||||
receive_func(user, std::string((char*)in, len));
|
receive_func(user, std::string((char*)in, len), binfo);
|
||||||
libwebsocket_callback_on_writable(context, wsi);
|
libwebsocket_callback_on_writable(context, wsi);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -158,6 +168,6 @@ namespace websockets {
|
||||||
#define WSstandard_protocol(name, protocol)\
|
#define WSstandard_protocol(name, protocol)\
|
||||||
{ name, WSprotocol_callback(protocol), sizeof(decltype(protocol)::user_type) }
|
{ name, WSprotocol_callback(protocol), sizeof(decltype(protocol)::user_type) }
|
||||||
|
|
||||||
int default_main(int argc, char **argv, libwebsocket_protocols* protocols);
|
int default_main(int argc, char **argv, libwebsocket_protocols* protocols, std::function<void()> runloop_callback = nullptr);
|
||||||
|
|
||||||
} // namespace websockets
|
} // namespace websockets
|
||||||
|
|
Reference in a new issue