Websocketpp server that yield on boost fibers

Viewed 60

I try to implement a version of websocketpp server inside a mono-thread project that uses multiple coroutines based on boost fibers. The server is working fine but I'm having issue with the fact that the boost::fiber::sleep_for and other function does not yield back to the websocket.

Here is an example of my code:

#include "websocketpp/config/asio_no_tls.hpp"
#include "websocketpp/connection.hpp"
#include "websocketpp/server.hpp"

class Server {
private:
    using WebsocketConn = std::shared_ptr<websocketpp::connection<websocketpp::config::asio>>;

    websocketpp::server<websocketpp::config::asio> websocketServer;
    std::function<void(WebsocketConn)> connectCallback;
    std::function<void(WebsocketConn)> disconnectCallback;

public:
    Server() {
        websocketServer.set_reuse_addr(true);
        websocketServer.set_error_channels(websocketpp::log::elevel::none);
        websocketServer.set_access_channels(websocketpp::log::alevel::none);
        websocketServer.init_asio();

        websocketServer.set_open_handler(std::bind(&Server::onWebsocketOpen, this, std::placeholders::_1));
    }

    void listen(int port) {
        websocketServer.listen(port);
        websocketServer.start_accept();
        websocketServer.run();// <= here is the blocking point based on the io_service used
    }

    void Server::onConnect(std::function<void(WebsocketConn)> callback) {
        connectionCallback = callback;
    }

    void Server::onWebsocketOpen(websocketpp::connection_hdl connectionHandler) {
        auto websocketConnection = websocketServer.get_con_from_hdl(connectionHandler);
        connectionCallback(websocketConnection);
    }
};

int main() {
    Server server;
    server.onConnect([](std::shared_ptr<websocketpp::connection<websocketpp::config::asio>> connection) {
        boost::fibers::fiber([&](){ 
            while (true) {
               connection->send(/*some stuff*/); //This will never be sent until the loop is exited. After that it will send everything in one time.
               boost::this_fiber::sleep_for(1000);
            }
        });
     });
    server.listen(8080);
}

if instead of fibers I use a thread it's working fine. Do you have any idea how to use fibers with websocketpp ? I know the init_asio function can take a pointer to an external io_service (which is responsible of the run function) but I tried using boost io_service and it's still the same behavior.

Thanks for the help

0 Answers
Related