Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Qt Wrapper class on libWebSockets - not emitting a signal from the callback method
Forum Updated to NodeBB v4.3 + New Features

Qt Wrapper class on libWebSockets - not emitting a signal from the callback method

Scheduled Pinned Locked Moved Solved General and Desktop
8 Posts 2 Posters 1.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    chaithubk
    wrote on 30 Nov 2019, 09:11 last edited by chaithubk
    #1

    I am writing a WebSocket client application, based on the example, where the client application needs to pass the WebSocket Protocol while establishing connection with the server. Since QtWebSockets does not support the Websocket protocols, I am writing a C++ wrapper to use libWebSockets library and emit connected, disconnected, textReceived kind of signals similar to QWebSocket.

    My client application is able to connect to the server and is receiving the text message from the server, and I have copied minimum example code below, here I am facing an issue that when I emit a signal from the callback function the signal is not actually published and the slot I have connected to this signal never executed. I have verified that the object address passed in the session data is correct (copied the Logs of my program). What am I doing wrong here.


    WebSocket.h

    class WebSocket : public QObject
    {
    	Q_OBJECT
    
    public:
    	WebSocket(QObject *parent = Q_NULLPTR);
    	~WebSocket();
    
    signals:
    	void connected();
    	void disconnected();
    	void textMessageReceived(const QString &message);
    
    private:
    	static int callback_dumb_increment(struct lws *wsi, enum lws_callback_reasons reason,
    		void *user, void *in, size_t len);
    
    	struct lws_context *context;
    	struct lws *client_wsi;
    	static const struct lws_protocols protocols[];
    };
    

    WebSocket.cpp

    const struct lws_protocols WebSocket::protocols[] = {
    	{
    		"dumb_protocol",
    		callback_dumb_increment,
    		sizeof(per_session_data),
    		0,
    	},
    	{ NULL, NULL, 0, 0 }
    };
    
    WebSocket::WebSocket(QObject *parent) : QObject(parent)
    {
    	struct lws_context_creation_info info;
    	struct lws_client_connect_info i;
    	int n = 0;
    
    	memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */
    	info.port = CONTEXT_PORT_NO_LISTEN; /* we do not run any server */
    	info.protocols = protocols;
    
    	qDebug() << "[parent] address: " << this;
    	info.user = this;
    
    	/*
    	 * since we know this lws context is only ever going to be used with
    	 * one client wsis / fds / sockets at a time, let lws know it doesn't
    	 * have to use the default allocations for fd tables up to ulimit -n.
    	 * It will just allocate for 1 internal and 1 (+ 1 http2 nwsi) that we
    	 * will use.
    	 */
    	info.fd_limit_per_thread = 1 + 1 + 1;
    
    	context = lws_create_context(&info);
    	if (!context) {
    		qDebug() << "lws init failed";
    	}
    
    	memset(&i, 0, sizeof i); /* otherwise uninitialized garbage */
    	i.context = context;
    
    	i.port = 7070;
    	i.address = "localhost";
    	i.path = "/";
    	i.host = i.address;
    	i.origin = i.address;
    	i.pwsi = &client_wsi;
    
    	lws_client_connect_via_info(&i);
    
    	while (n >= 0 && client_wsi)
    		n = lws_service(context, 0);
    }
    
    
    int WebSocket::callback_dumb_increment(	struct lws *wsi, enum lws_callback_reasons reason,
    										void *user, void *in, size_t len )
    {
    	/* This will be same for every connected peer */
    	void *userdata = lws_context_user(lws_get_context(wsi));
    	qDebug() << "userData address: " << userdata;
    
    	QString message = "";
    
    	switch (reason) {
    
    	case LWS_CALLBACK_CLIENT_CONNECTION_ERROR:
    		if (in)
    			qDebug() << "CLIENT_CONNECTION_ERROR: " << (char *)in;
    		else
    			qDebug() << "CLIENT_CONNECTION_ERROR: (null)";
    		wsi = NULL;
    		break;
    
    	case LWS_CALLBACK_CLIENT_ESTABLISHED:
    		qDebug() << __func__ << " established";
    		emit static_cast<WebSocket*>(userdata)->connected();
    		break;
    
    	case LWS_CALLBACK_CLIENT_RECEIVE:
    		message = QString::fromUtf8((const char *)in);
    		qDebug() << "RX: " << message;
    		emit static_cast<WebSocket*>(userdata)->textMessageReceived(message);
    		break;
    
    	case LWS_CALLBACK_CLIENT_CLOSED:
    		wsi = NULL;
    		emit static_cast<WebSocket*>(userdata)->disconnected();
    		break;
    
    	default:
    		break;
    
    	}
    
    	return lws_callback_http_dummy(wsi, reason, user, in, len);
    }
    

    SocketClient.h

    class SocketClient : public QObject
    {
    	Q_OBJECT
    public:
    	explicit SocketClient(QObject *parent = Q_NULLPTR);
    	~SocketClient();
    
    public slots:
    	void onConnected();
    	void onTextMessageReceived(QString message);
    
    private:
    	std::shared_ptr<WebSocket> webSock = nullptr;
    };
    

    SocketClient.cpp

    SocketClient::SocketClient(QObject *parent) :QObject(parent)
    {
    	webSock = std::make_shared<WebSocket>(this);	
    
    	connect(webSock .get(), &WebSocket::connected, this, &SocketClient::onConnected);
    	connect(webSock .get(), &WebSocket::textMessageReceived,
    		this, &SocketClient::onTextMessageReceived);
    }
    

    Logs:

    [parent] address:  WebSocket(0x1b2cae32140)
    userData address:  0x1b2cae32140
    WebSocket::callback_dumb_increment  established
    userData address:  0x1b2cae32140
    RX:  "Hello World"
    
    1 Reply Last reply
    0
    • C Offline
      C Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on 30 Nov 2019, 09:15 last edited by Christian Ehrlicher
      #2

      Is the Qt eventloop running? What happens inside SocketClient::onTextMessageReceived() ? What does QtWebSockets does not support so you need to use another library?

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      C 1 Reply Last reply 30 Nov 2019, 09:22
      2
      • C Christian Ehrlicher
        30 Nov 2019, 09:15

        Is the Qt eventloop running? What happens inside SocketClient::onTextMessageReceived() ? What does QtWebSockets does not support so you need to use another library?

        C Offline
        C Offline
        chaithubk
        wrote on 30 Nov 2019, 09:22 last edited by
        #3

        @Christian-Ehrlicher I have written my SocketClient as a library in Windows, this library is instantiated inside a QMainWindow application. Initially I used the QWebSocket and I received all the signals from the QWebSocket in my main window, now that I have replaced QWebSocket class inside SocketClient with my WebSocket class, and now I am not receiving the signals in my main window.

        The reason I went with my own class is because of the reason below:

        QWebSocket currently does not support WebSocket Extensions and WebSocket Subprotocols.
        
        1 Reply Last reply
        0
        • C Offline
          C Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on 30 Nov 2019, 09:51 last edited by
          #4

          @chaithubk said in Qt Wrapper class on libWebSockets - not emitting a signal from the callback method:

          QWebSocket currently does not support WebSocket Extensions and WebSocket Subprotocols.

          What exactly do you need from those protocols?

          Did you actually add a breakpoint or some debug output inside onConnected() / onTextMessageReceived()?

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          C 1 Reply Last reply 30 Nov 2019, 10:13
          1
          • C Christian Ehrlicher
            30 Nov 2019, 09:51

            @chaithubk said in Qt Wrapper class on libWebSockets - not emitting a signal from the callback method:

            QWebSocket currently does not support WebSocket Extensions and WebSocket Subprotocols.

            What exactly do you need from those protocols?

            Did you actually add a breakpoint or some debug output inside onConnected() / onTextMessageReceived()?

            C Offline
            C Offline
            chaithubk
            wrote on 30 Nov 2019, 10:13 last edited by
            #5

            @Christian-Ehrlicher SubProtocol is a negotiation between server and client, this is something I can't remove from the server implementation. SO, client definitely need to pass the subprotocol to connect with the server.

            Yes, I have put breakpoints and logs inside the slots, they were never executed.

            1 Reply Last reply
            0
            • C Offline
              C Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on 30 Nov 2019, 10:23 last edited by
              #6

              Maybe a threading issue? Is the callback executed in the correct thread? Please check with QThread::currentThreadId(). Otherwise I've no real idea.

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              C 2 Replies Last reply 30 Nov 2019, 10:51
              0
              • C Christian Ehrlicher
                30 Nov 2019, 10:23

                Maybe a threading issue? Is the callback executed in the correct thread? Please check with QThread::currentThreadId(). Otherwise I've no real idea.

                C Offline
                C Offline
                chaithubk
                wrote on 30 Nov 2019, 10:51 last edited by
                #7

                @Christian-Ehrlicher The thread ID matched, the callback method is executed in the same thread.

                1 Reply Last reply
                0
                • C Christian Ehrlicher
                  30 Nov 2019, 10:23

                  Maybe a threading issue? Is the callback executed in the correct thread? Please check with QThread::currentThreadId(). Otherwise I've no real idea.

                  C Offline
                  C Offline
                  chaithubk
                  wrote on 4 Dec 2019, 11:33 last edited by
                  #8

                  @Christian-Ehrlicher I figured it's a threading issue, I should launch the Websocket instance in a separate thread, that resolved the problems and signals are passed as expected.

                  1 Reply Last reply
                  0

                  1/8

                  30 Nov 2019, 09:11

                  • Login

                  • Login or register to search.
                  1 out of 8
                  • First post
                    1/8
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved