HTTP/2 Server Support for Next-Generation Services in OpenSIPS 3.5

5G technology offers speeds up to 1000 times faster than 4G, as well as significantly lower latency and the ability to support large numbers of devices connecting to the network at the same time. With 5G deployments by telecom operators in both USA/Europe debuting as early as 2019[1] and continuing throughout the following years, it is a prime time to enhance OpenSIPS with HTTP/2 support so it can be leveraged in the next-generation 5GC (5G Core) networks as well.

HTTP/2 Summary

HTTP/2 is a binary protocol (yes, we need to always decode it in Wireshark now 😢) which enables a more efficient use of network resources and a reduced perception of latency by introducing header field compression and allowing multiple concurrent exchanges on the same connection. Specifically, it allows interleaving of request and response messages on the same connection and uses an efficient coding for HTTP header fields.

The binary framing of HTTP/2, helping deliver the same HTTP/1.1 content
A single HTTP/2 TCP connection being used to concurrently transfer multiple web resources
An HTTP/2 Server delivering two resources in an interleaved fashion (two streams), while the HTTP/2 client concurrently makes a 3rd request

More information about HTTP/2, its history and innerworkings can be found in this comprehensive web.dev HTTP/2 article, which was also the source for the nice protocol diagrams above.

The “nghttp2” Library and “libevent” Server Framework

When searching for C implementations of the HTTP/2 RFC 9113, it didn’t take long until we ran into Mr. Tatsuhiro Tsujikawa‘s work on the nghttp2 C library and tools, with the open-source project’s documentation being hosted on their personal https://nghttp2.org/ website and served by none other than the nghttp2d server, of course — hence your browser will connect to this website via HTTP/2 😊.

The nghttp2 open-source library is very well documented, both on the website as well as in the C source-code header files. It is heavily callback-driven, with appropriate abstractions whenever it comes to configuring, tuning or instructing the library to behave in different ways, according to your needs. While this leads to a steeper learning curve in learning and correctly carrying/managing your data across the tiringly numerous callbacks of a single HTTP/2 request and the data structures and abstractions tied to each callback, in the end it is well worth the investment, as you will end up with an application that is completely decoupled from the underlying HTTP/2 implementation. In the long run, this will maximize compatibility with future iterations of the nghttp2 library, as we expect system upgrades to be very smooth.

Worded as “an HTTP/2 implementation”, the nghttp2 library stays true to its definition and it is not an HTTP/2 server. For the server part, it is itself powered by the libevent.org open-source project and library, with the library’s code being hosted at github.com/libevent/libevent.

New Module in OpenSIPS 3.5: “http2d”

The next step was to piece together nghttp2, libevent and their other dependencies (libssl, libcrypto, libevent-openssl) into an OpenSIPS module. And instead of baking all these new library dependencies into httpd, which is powered by libmicrohttpd, we went with a new module: http2d.

Let’s take a look at some of its module parameters:

loadmodule "http2d.so"
modparam("http2d", "ip", "127.0.0.2")
modparam("http2d", "port", 443)
modparam("http2d", "tls_cert_path", "/etc/pki/http2/cert.pem")
modparam("http2d", "tls_key_path", "/etc/pki/http2/key.pem")
modparam("http2d", "max_headers_size", 8192)
modparam("http2d", "response_timeout", 2000)

Since HTTP/2 is predominantly provided in a secured fashion (e.g. Chrome and Mozilla do not support cleartext HTTP/2 servers, a.k.a. the “h2c” Upgrade), this was our choice for the starting point as well. Notice the tls_cert_path and tls_key_path settings, for the TLS communication. Finally, we put a sensible default limit on the amount of header data in a single HTTP/2 request using the max_headers_size (8 KB), as well as a limit to the amount of opensips.cfg processing done by OpenSIPS system developers on a single HTTP/2 request before OpenSIPS automatically replies to the client — response_timeout (2 seconds).

Below is an example on how OpenSIPS system developers can process HTTP/2 requests and build custom responses:

event_route [E_HTTP2_REQUEST]  
{
xlog("H2-Method: $param(method)\n");
xlog("H2-Path: $param(path)\n");
xlog("H2-Headers: $param(headers)\n");
xlog("H2-Data: $param(data)\n");

$var(headers) = "[
{ \"content-type\": \"application/json\" },
{ \"server\": \"OpenSIPS 3.5\" },
{ \"x-current-time\": \"1711457142\" },
{ \"x-call-cost\": \"0.355\" }
]";

$var(data) = "{\"status\": \"success\"}";

if (!http2_send_response(200, $var(rpl_headers), $var(data)))
xlog("ERROR - failed to send HTTP/2 response\n");
}

Key takeaways:

  • HTTP/2 requests arrive via the E_HTTP2_REQUEST event, so make sure to load the event_route.so module beforehand, as well as to define an event_route subscriber for the event
  • All data of the request is available via event parameters: method, path, headers and data. Tip: you can use the json module in order to parse the $param(headers) JSON data.
  • There is the ability to fully customize the HTTP/2 response:
    • you may include one or more custom reply headers, packed as a JSON array, then passed to the “http2_send_response()” function
    • you may also include a DATA payload for the response, by supplying the 3rd parameter of “http2_send_response()”

A first draft of the new http2d module is already available on master (development) branch, awaiting testing and feedback. And your feedback on it matters greatly: Are you satisfied with TLS communication 100% of the time, or should we provide an HTTP/2 cleartext (h2c) listening option as well? Do you happen to know situations or 3GPP drafts where “h2c” is being used/recommended in 5GC networks? Are there any features of HTTP/2 that http2d does not provide as of now? Or perhaps some non-HTTP/2 features (practical ones) that were missed?

Questions such as the above fuel our developer curiosity and keep us happily going forward. And, speaking of going — this year the OpenSIPS Project and the VoIP community is looking forward to the Valencia, Spain destination as part of the OpenSIPS Summit 2024 conference, May 14-17, where HTTP/2, 5G and other IMS related topics will be high on the priority list. If you are interested, do make sure to check it out. Cheers!

Leave a comment