Network library evaluation for http server implementation in VLC
Background
The "new web interface" for VLC desktop is an ongoing subject, and there has been some previous work:
- some big and difficult-to-merge MRs have been on vlc master for a long time now
- then VLC for Android team took some inspiration to have a proper interface, and split the frontend and backend parts (this will be in production starting January)
- then we tried (through a GSoC) to use the android team work on master, and we ended up with some big problems with the http server implementation (slow, single-threaded, API not that great, depends on Lua, etc)
Purpose
It seems there is some general consensus that it could be a good idea to replace the complete httpd stack with some proper external contrib (and a rework of the httpd API). Utilizing an external network library would allow us to leverage features such as low latency, lightweight design, multithreading, WebSocket support, etc.
Edit: There is a general consensus to explore the feasibility of modularizing the httpd stack using an external httpd contrib, along with a rework of the httpd API.
Benefits of modularization and using an external library:
- Reduced maintenance overhead for security patches (in the case of libmicrohttpd, active development of v2 is ongoing for both feature enhancements and security improvements, as confirmed through their repository, mailing list, and direct discussions with the maintainers), protocol updates, bug fixes, and dedicated test suites for HTTP functionalities.
- WebSockets support: Although it’s possible to implement this internally, for the same reasons mentioned above, delegating it to a specialized library is preferable. libmicrohttpd has WebSocket, HTTP/2, and HTTP/3 support planned in its roadmap. (Certificate provisioning for HTTP/2 and HTTP/3 remains a separate issue on our side.)
- Future extensibility: Modularization would enable integrating other specialized web servers and protocols in the future via plugins, without requiring invasive modifications to the core.
Purpose of httpd API rework:
- To address single-threaded limitations and existing design issues (refer to #25000).
- To make the API easier to extend for future use cases, such as unicast streaming, filesystem access, WebSockets, HTTP/2, HTTP/3, client-paced stream outputs, and more.
Deliverables
- Add a contrib for the chosen network library
- A module API for the contrib
Legacy httpd API will be deprecated- Edit: Migrate legacy httpd to a separate module
- Edit: A new vlc_httpd API implemented using contrib or legacy module API
- Plug the “new web interface” from android
Library requirements
-
License
Mandatory: GPLv2 compatible
Preferable: LGPLv2 compatible (LGPLv2, BSD, MIT) -
Integration
Maintained (at least with security updates), active community and developer support, proper test suite, CI, extensive documentation, and available examples -
Lightweight
-
Compatible with current contrib languages (C/C++/Rust)
-
Cross-platform (Linux, Windows, macOS)
-
Multi-threaded (pthread support)
-
TLS support, with easy integration of VLC TLS API (either out-of-the box or with minimal patches)
-
Websocket support
-
Edit: support integration with an external event loop
-
Edit: should set non-atomic close-on-exec (FD_CLOEXEC) on sockets.
Preferred choice
libmicrohttpd
- License: LGPL v2.1
- Integration: maintained (major v2 upgrade ongoing), extensive docs and examples available, active community and dev support
- Lightweight
- C
- Cross-platform: supported platforms include GNU/Linux, FreeBSD, OpenBSD, NetBSD, Android, Darwin (macOS), W32, OpenIndiana/Solaris, and z/OS
- Various threading modes: run in application thread, internal thread, thread pool, and thread-per-connection
- TLS: uses gnuTLS so shouldn't be difficult to give a patch in contribs (for VLC TLS support)
- Websocket support added in v2
-
Edit: supports integration with an external event loop using
MHD_WM_EXTERNAL_EVENT_LOOP_CB_LEVELorMHD_WM_EXTERNAL_EVENT_LOOP_CB_EDGE -
Edit: sets
mhd_SOCK_CLOEXECby default on POSIX systems andWSA_FLAG_NO_HANDLE_INHERITon Windows
Notes:
- mhd is going through a major rework from v1 to v2 which is being funded by Sovereign Tech Fund.
- The MHD main dev is suggesting us to use the v2 API unless we want to ship the http server immediately. The reasons being "it is easier, safer and should also be faster". Also, as we need TLS flexibility and websocket support, the v2 API would probably be the preferable choice.
- gnuTLS backend APIs (like, mhd_tls_gnu_conn_handshake and mhd_tls_gnu_conn_recv) are quite similar to our vlc_tls_* APIs.
- Kodi uses libmicrohttpd
Drawback:
- v2 is not yet released and thus the API is not totally stable yet
- v2 docs and examples aren't complete yet, indicating a steeper learning curve
Other choices
libwebsockets
- License: MIT
- Integration: maintained, extensive docs and examples available, active community and dev support
- Lightweight
- C
- Cross-platform: available for unix-style platforms like Linux and BSD (including Mac), and also for Windows and even ESP32 and FreeRTOS
- Uses a single-threaded non blocking event loop, but it also supports having n of these in n threads, spreading the connections between them by allocating them to the least busy service thread
- TLS: provides generic APIs1 to access hashing, RSA, X509 and TLS library features independent of the TLS backend
- Websocket support
Drawback:
- steep learning curve (as compared to mhd)
- whether LWS provides the liberty for a fully customisable TLS backend (for our VLC TLS API) is still unclear
We also investigated other popular libraries such as Mongoose, Civetweb, lighttpd, Hyper(C API), facil.io. However, since they did not meet all of our requirements, we decided not to proceed with them.
- Mongoose: feature rich with a good API design and docs, but GPL/proprietary license limits integration (not compatible with stream output modules)
- CivetWeb: MIT-licensed fork of Mongoose (from 2013), diverged significantly from Mongoose, GnuTLS patch is trivial and untested
- lighttpd: experimental Windows support
- Hyper (C API): unstable C API, no built-in WebSocket support, server C API is yet to be written
- facil.io: Lacks windows port support
Conclusion and next steps
After a thorough investigation, we have decided to begin our http server implementation using libmicrohttpd v2 and monitor the progress. The initial plan is creating a first draft that is doing a partial replacement of the old module (like publishing the vlc mediaplayer controls), and based on community feedback, we can continue adding more functionalities, such as WebSocket support.
Some potential blockers, as communicated within the community, that may arise during the rework include:
- there seems to be "some Windows issue" when using a shared library, which may require a fix
- the stack would need to accommodate the needs of the streaming output modules