4

Qt Quick WebGL Streaming is a technology by which any Qt Quick ("QML") application can display its user interface to a user connecting via a web browser. All you have to do is to start the application like this on the host:

./my-qml-program -platform webgl:port=8080

This works, but is limited by design so that only one user can be connected at the same time and see the user interface. As the reason for this, they quote problems with user input, with querying the GPU, and with security (source).

Initially, the Qt developers wanted to support multiple users in WebGL streaming by serving multiple windows from one process:

How will concurrency be supported? Like does each connection get it's own QGuiApplication, or is there only one? […] You create a single QGuiApplication and different windows. There is a signal to notify when new clients connect to the HTTP server. When the signal is emitted, you create a different QWindow. The windows are independent (source)

Now however, the developers want to support multiple users in WebGL streaming by launching one process per user.

  • We are working in decoupling the HTTP Server from the plugin
  • A dedicated HTTP Server application will be provided
    • Instead of running all the users in the same process a new process will be spawned per user
    • The new process will handle the web socket

(source)

"Decoupling the HTTP Server from the plugin" would mean replacing it with QHttpServer:

I have planned some use-cases for this [QHttpServer] module: Change the current embedded web server (and WebSockets) in the WebGL plugin to make it easy to create your own custom solutions based on the plugin. (source)

So far, no solution has been implemented. What is the simplest way to implement support for multiple users in Qt WebGL streaming myself, without waiting for Qt to implement this?

tanius
  • 14,003
  • 3
  • 51
  • 63

1 Answers1

5

Here is a solution that uses the load balancer Pen to make a Qt application accessible via WebGL streaming to multiple users at the same time. It forwards an incoming connection to one of multiple Qt processes running on the same host, each of which running its own embedded web server. This kind of forwarding is exactly the job of a load balancer, just that it usually distributes connections to multiple hosts.

Caveat: In my tests, WebGL streaming in Qt 5.12.3 is fast enough for real use only in the local network, not over Internet. So you can't use it to "convert a Qt application into a web application on the cheap".

Instructions

These instructions apply to Ubuntu 19.10, 20.04 and other Debian based distributions.

  1. Install the Qt application on your web host.

  2. Install the Qt WebGL platform plugin on your web host. It is not contained in the Ubuntu 19.10 distribution, for example. In such a case, you'd have to compile and install it yourself. Under Ubuntu Linux, the result should be the following file:

    /usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqwebgl.so
    
  3. Start multiple processes of the Qt application. Each should serve one port with Qt WebGL streaming. Here we start three processes, but you can start as many as fit into your memory.

    nohup myapplication -platform webgl:port=8080 &
    nohup myapplication -platform webgl:port=8081 &
    nohup myapplication -platform webgl:port=8082 &
    
  4. Install the load balancer Pen.

    sudo apt install pen
    
  5. Start the load balancer. Note that with pen 80 … it is started so that the users only have to enter a simple URl such as http://example.com/ into their web browser to visit the application. If port 80 is already in use, you can choose any other port (say, 9090), start the load balancer with pen 9090 … and then let users visit a URL like http://example.com:9090/. Also note the :1:1 suffix for each server process listed, telling pen to only connect at most one client to one process.

    pen 80 localhost:8080:1:1 localhost:8081:1:1 localhost:8082:1:1
    
  6. Test the setup. To test, visit the associated URL http://example.com/ from multiple devices. You shoud be served one process of the application on each device. It is not possible to see two processes in two parallel browser tabs on the same device – pen would then try to connect the second such tab to the same Qt process as the first tab because the request comes from the same IP address. As a result, you'd see a spinning wheel in the second tab, because Qt processes only allow one connection each for WebGL streaming.

Improvements

This solution could be further improved by starting the Qt processes only on demand, once a client connects. This should be possible with systemd socket activation.

tanius
  • 14,003
  • 3
  • 51
  • 63