eidheim / Simple-WebSocket-Server

A very simple, fast, multithreaded, platform independent WebSocket (WS) and WebSocket Secure (WSS) server and client library implemented using C++11, Boost.Asio and OpenSSL. Created to be an easy way to make WebSocket endpoints in C++.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Getter to Class Connection Status

opened this issue · comments

Hi,
First of all, thank you for this great library !

I was wondering, how do I get the status of a Connection ?
Let me explain, in my program, each of the Server's Clients are linked with a User, therefore when a Client connects to the WsServer, I instantiate a new User and store the Connection in it.

But when i need to clean my list of User, I would like to know the status of the socket so that I can delete the User when the connection is lost.
With that idea in mind, in my class User you can see that I had to create a boolean closed, this variable is set to true by the WsServer.on_close function.

The User class looks like that:

class User{
        std::shared_ptr<WsServer::Connection> connection;
        Player* player;
        bool closed;
        //...
    public:
        User(std::shared_ptr<WsServer::Connection> co, Player* pl): 
                 connection(co), player(pl), closed(false){}
        ~User(){
          delete player;
        }
        bool closed(){
           return closed;
        }
    };

Do you think it is possible to add a getter to the Connection Class to get it's status ?

I would maybe do something like this:

#include "server_ws.hpp"
#include <unordered_map>

using namespace std;

typedef SimpleWeb::SocketServer<SimpleWeb::WS> WsServer;

class Player {
};

int main() {
    WsServer server;
    server.config.port = 8080;

    unordered_map<std::shared_ptr<WsServer::Connection>, Player> connections;

    auto &echo = server.endpoint["^/echo/?$"];

    echo.on_message = [&server](shared_ptr<WsServer::Connection> connection, shared_ptr<WsServer::Message> message) {

    };

    echo.on_open = [&connections](shared_ptr<WsServer::Connection> connection) {
        connections.emplace(connection, Player());
    };

    //See RFC 6455 7.4.1. for status codes
    echo.on_close = [&connections](shared_ptr<WsServer::Connection> connection, int status, const string & /*reason*/) {
        connections.erase(connection);
    };

    //See http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference.html, Error Codes for error code meanings
    echo.on_error = [&connections](shared_ptr<WsServer::Connection> connection, const boost::system::error_code &ec) {
        connections.erase(connection);
    };

    server.start();
}

edit: decided to use shared_ptr in unordered_map<std::shared_ptr<WsServer::Connection>, Player> connections; for simplicity

Of course the above example takes it for granted that you run the server in one thread. If more threads are used, you would need a connections_mutex that needs to be locked whenever emplace or erase is called.

Thank you, that fast answer, i will try your solution.
And, out of curiosity, why don't you put any getter on the status ?

If it is needed, I'll add the getter. You mean a getter for socket::is_open I take it?

I was thinking something like the javascript implementation of WebSocket with a readyState that could be an enum

Constant Value Description
CONNECTING 0 The connection is not yet open.
OPEN 1 The connection is open and ready to communicate.
CLOSING 2 The connection is in the process of closing.
CLOSED 3 The connection is closed or couldn't be opened.

so we can have a:

socket::getReadyState;

I do not immediately see a need for this. Also, one can easily implement this oneself using the on_open, on_close/on_error, on_message handlers.

yes it's true but i think it will be nice if we can get the status of the socket somehow without having to redo the work twice.
if i have the time i'll try to do a pull request with a readyState and if you like it you can merge it.