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"]
|
||||
path = contrib/json-spirit
|
||||
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;
|
||||
|
||||
using namespace websockets;
|
||||
|
||||
websockets::TestProtocol<User> default_protocol{
|
||||
// connection established
|
||||
[](User& user){
|
||||
[](User& user, basic_websocket_info){
|
||||
app->login(user);
|
||||
},
|
||||
// connection closed
|
||||
[](User& user){
|
||||
[](User& user, basic_websocket_info){
|
||||
app->logout(user);
|
||||
},
|
||||
// write (will always come after receive)
|
||||
[](User& user) -> std::string{
|
||||
app->update_positions();
|
||||
return write_json(ptrvector_to_json(app->people_online));
|
||||
[](User& user, basic_websocket_info) -> std::string{
|
||||
},
|
||||
// receive
|
||||
[](User& user, std::string in){
|
||||
[](User& user, std::string in, basic_websocket_info){
|
||||
try{
|
||||
user = from_json<IncomingPacket>(parse_json(in));
|
||||
} catch(std::exception& e) {
|
||||
|
@ -40,16 +42,16 @@ websockets::TestProtocol<User> default_protocol{
|
|||
|
||||
websockets::TestProtocol<Empty> observer_protocol{
|
||||
// connection established
|
||||
[](Empty& user){},
|
||||
[](Empty& user, basic_websocket_info){},
|
||||
// connection closed
|
||||
[](Empty& user){},
|
||||
[](Empty& user, basic_websocket_info){},
|
||||
// write (will always come after receive)
|
||||
[](Empty& user) -> std::string{
|
||||
app->update_positions();
|
||||
return write_json(ptrvector_to_json(app->people_online));
|
||||
[](Empty& user, basic_websocket_info) -> std::string{
|
||||
},
|
||||
// receive
|
||||
[](Empty& user, std::string in){}
|
||||
[](Empty& user, std::string in, basic_websocket_info){}
|
||||
};
|
||||
|
||||
int main(int argc, char **argv){
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
|
||||
#include "websockets.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
namespace websockets {
|
||||
|
||||
option options[] = {
|
||||
|
@ -11,7 +14,7 @@ namespace websockets {
|
|||
{ 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 use_ssl = 0;
|
||||
char interface_name[128] = "";
|
||||
|
@ -63,9 +66,21 @@ namespace websockets {
|
|||
static bool force_exit = false;
|
||||
signal(SIGINT, [](int){ force_exit = true; });
|
||||
|
||||
|
||||
using clock = std::chrono::steady_clock;
|
||||
using duration = std::chrono::duration<double>;
|
||||
while (!force_exit) {
|
||||
auto begin = clock::now();
|
||||
auto ret = libwebsocket_service(context.get_raw(), 10);
|
||||
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)
|
||||
// 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)
|
||||
|
@ -95,10 +104,10 @@ namespace websockets {
|
|||
struct TestProtocol {
|
||||
typedef T user_type;
|
||||
|
||||
std::function<void(user_type&)> establish_func;
|
||||
std::function<void(user_type&)> close_func;
|
||||
std::function<std::string(user_type&)> write_func;
|
||||
std::function<void(user_type&, std::string)> receive_func;
|
||||
std::function<void(user_type&, basic_websocket_info)> establish_func;
|
||||
std::function<void(user_type&, basic_websocket_info)> close_func;
|
||||
std::function<std::string(user_type&, basic_websocket_info)> write_func;
|
||||
std::function<void(user_type&, std::string, basic_websocket_info)> receive_func;
|
||||
|
||||
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){
|
||||
user_type& user = *static_cast<user_type*>(user_ptr);
|
||||
basic_websocket_info binfo{context, wsi};
|
||||
try{
|
||||
switch (reason) {
|
||||
case LWS_CALLBACK_ESTABLISHED:
|
||||
lwsl_notice("Connection established (%p, %p)\n", this, user_ptr);
|
||||
new (user_ptr) user_type();
|
||||
establish_func(user);
|
||||
establish_func(user, binfo);
|
||||
break;
|
||||
case LWS_CALLBACK_CLOSED:
|
||||
lwsl_notice("Connection closed (%p, %p)\n", this, user_ptr);
|
||||
user.~user_type();
|
||||
close_func(user);
|
||||
close_func(user, binfo);
|
||||
break;
|
||||
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;
|
||||
// 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];
|
||||
|
@ -135,7 +145,7 @@ namespace websockets {
|
|||
break;
|
||||
}
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
|
@ -158,6 +168,6 @@ namespace websockets {
|
|||
#define WSstandard_protocol(name, protocol)\
|
||||
{ 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
|
||||
|
|
Reference in a new issue