You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Reimplement REST interface using HTTP/2, HTTP3 (#371)
* Reimplement REST interface using HTTP/2
Instead of using the httplib-based HTTP server using blocking I/O in
a thread per client, implement a nghttp2-based HTTP/2 server, using
single-threaded non-blocking I/O directly integrated into the Broker
zmq_poll() loop.
* HTTP/3 server implementation
Implements HTTP/3 support in the server, following the implementation
in ngtcp2's server.cc example. A lot of the function logic and structure
from there has been preserved for easier debugging and comparing to the
example if needed.
* Prepare client for HTTP/3
Use CRTP to prepare for a Http3ClientSession (not implemented yet).
Signed-off-by: Frank Osterfeld <[email protected]>
_Majordomo Broker_ or _'Broker':_ is the central authority where multiple workers can register their services, allowing clients to perform get, set or subscriptions requests.
44
44
There can be multiple brokers for subset of services.
@@ -67,11 +67,11 @@ _Publisher:_ the [DataSourcePublisher](DataSourceExample.cpp) provides an interf
67
67
ring-buffer with events from OpenCMW, REST services or other sources.
68
68
While using disruptor ring-buffers is the preferred and most performing options, the client also supports classic patterns of registering call-back functions or returning `Future<reyly objects>` objects.
69
69
70
-
###OpenCMW Majordomo Protocol
70
+
## OpenCMW Majordomo Protocol
71
71
72
72
The OpenCMW Majordomo [protocol](docs/MajordomoProtocol.md) is based on the [ZeroMQ Majordomo protocol](https://rfc.zeromq.org/spec/7/), both extending and slightly modifying it (see [the comparison](docs/Majordomo_protocol_comparison.pdf)).
73
73
74
-
####Service Names
74
+
### Service Names
75
75
76
76
Service names must always start with `/`. For consistency, this also applies to the built-in MDP broker services like `/mmi.service` (instead of `mmi.service` without leading slash as in ZeroMQ Majordomo). A service name is a non-empty alphanumerical string (also allowing `.`, `_`), that must start with `/` but not end with `/`. It contain additional `/` to denote a hierarchical structure.
The "topic" field (frame 5 in the [OpenCMW MDP protocol](docs/Majordomo_protocol_comparison.pdf)) specifies the topic for subscriptions and GET/SET requests. It contains a URI with the service name as path and optional query parameters to specify further requests parameters and filter criteria.
90
90
@@ -99,7 +99,7 @@ Note that the whole path is considered the service name, and that there's no add
99
99
100
100
See also the documentation for [mdp::Topic](src/core/include/Topic.hpp).
101
101
102
-
####URL to Service/Topic Mapping (mds/mdp and REST)
102
+
### URL to Service/Topic Mapping (mds/mdp and REST)
103
103
104
104
With both the MDS/MDP-based ZeroMQ clients as well as the REST interface, a common scheme is used to map from mdp/hds/http(s) URLs used for subscriptions and requests to the OpenCMW service name and topic fields.
105
105
@@ -120,7 +120,7 @@ Other examples are:
120
120
-`mds://example.com:8080/DeviceName/Acquisition?signal=test` => service name `/DeviceName/Acquisition`, topic `/DeviceName/Acquisition?signal=test` (subscription via mds).
121
121
-`mdp://example.com:8080/dashboards/dashboard1?what=header` => service name `/dashboards/dashboard1`, topic `/dashboards/dashboard1?what=header` (Request via mdp).
122
122
123
-
###Compile-Time-Reflection
123
+
## Compile-Time-Reflection
124
124
125
125
The serialisers are based on a [compile-time-reflection](docs/CompileTimeSerialiser.md) that efficiently transform domain-objects to and from the given wire-format (binary, JSON, ...).
126
126
Compile-time reflection will become part of [C++23](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0592r4.html) as described by [David Sankel et al. , “C++ Extensions for Reflection”, ISO/IEC CD TS 23619, N4856](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4856.pdf).
@@ -142,7 +142,7 @@ provides also an optional light-weight `constexpr` annotation template wrapper `
142
142
that in turn can be used to (re-)generate and document the class definition (e.g. for other programming languages or projects that do not have the primary domain-object definition at hand)
143
143
or to generate a generic [OpenAPI](https://swagger.io/specification/) definition. More details can be found [here](docs/CompileTimeSerialiser.md).
144
144
145
-
### Building from source
145
+
## Building from source
146
146
147
147
Note that building from source is only required if you want to modify opencmw-cpp itself.
148
148
@@ -151,7 +151,7 @@ In that case, rather take a look at the project [opencmw-cpp-example](https://gi
151
151
152
152
For concrete build instructions, please check the [build instructions page](docs/BuildInstructions.md).
153
153
154
-
### Example
154
+
## Example
155
155
156
156
For an example on how to implement a simple, first service using opencmw-cpp, please take a look at the project [opencmw-cpp-example](https://github.com/alexxcons/opencmw-cpp-example).
157
157
@@ -217,7 +217,7 @@ or RESTful (HTTP)-based high-level protocols, or through a simple RESTful web-in
217
217
[comment]: <> (The basic HTML rendering is based on XXX template engine and can be customised. For more efficient, complexand cross-platform)
218
218
[comment]: <> (UI designs it is planned to allow embedding of WebAssembly-based ([WASM](https://en.wikipedia.org/wiki/WebAssembly)) applications.)
219
219
220
-
### Performance
220
+
## Performance
221
221
222
222
The end-to-end transmission achieving roughly 10k messages per second for synchronous communications and
223
223
about 140k messages per second for asynchronous andor publish-subscribe style data acquisition (TCP link via locahost).
@@ -241,17 +241,74 @@ Your mileage may vary depending on the specific domain-object, processing logic,
241
241
but you can check and compare the results for your platform using the [RoundTripAndNotifyEvaluation](RoundTripAndNotifyEvaluation.cpp)
The openCMW REST interface supports both HTTP/2 and HTTP/3. When connecting from a browser, the browser typically first connects
247
+
via HTTP/2. HTTP/2 responses contain a "alt-svc" header that informs the browser about the availability of HTTP/3. The browser
248
+
then should switch to HTTP/3. Note that if HTTP/3 fails for any reason (certificates, server error etc.), the browser might remember
249
+
that and not try HTTP/3 again. How to reset this depends on the browser. What I did in Google Chrome
250
+
251
+
1. open an private tab, open the developer console, go to "Network", enable the "Protocol" column
252
+
2. connect to the service; verify in the developer console that HTTP/3 is used (Protocol should switch to`H3` after the first `H2` request)
253
+
3. To reset browser status, close *all* private tabs and open a new one.
254
+
255
+
### SSL Certificates
256
+
257
+
QUIC/HTTP/3 requires the use of TLS, unencrypted servers are not possible.
258
+
259
+
At least in Google Chrome, the TLS stack used for QUIC seems quite separate from the normal settings, and its much stricter than for HTTP/1/2. *If
260
+
anything goes wrong here, Google Chrome will silently stick with HTTP/2, or show you an error, if you're lucky*.
261
+
262
+
Caveats:
263
+
264
+
1. The certificate must be trusted inside the Chrome Certificate store (e.g. on Mac, trusting it in Keychain might silence the warning for HTTP1/2,
265
+
but HTTP/3 will still fail. Add the server's public key under chrome://certificate-manager/.
266
+
2. The hostname in the certificate must match what you connect via in the browser. "Works-everywhere self-signed certificates" I couldn't get to work.
267
+
What I did: Create a certificate for hostname `foobar`, edit `/etc/hosts` to resolve `foobar` to the test host's IP address. Enter e.g. `https://foobar:8080`
268
+
in the browser, instead of the IP address.
269
+
3. For HTTP/2, you can ignore Chrome's warning with "Proceed anyway" or similar. This does not make the QUIC stack trust the certificate, HTTP/3 will
270
+
not be used.
271
+
4. To get the certificate's fingerprint in base64:
For verbose logging (netlog can be viewed in the [https://netlog-viewer.appspot.com/#import](netlog viewer)), add
288
+
```
289
+
--enable-logging=stderr --v=3 \
290
+
--log-net-log=netlog.json --quic-version=h3
291
+
```
292
+
293
+
### curl
294
+
295
+
curl needs to be built with QUIC/HTTP/3 enabled, which is not the case at least on Ubuntu 24.04. I used the docker image `badouralix/curl-http3`:
296
+
297
+
```
298
+
docker run --rm badouralix/curl-http3 curl -k -vvvv --http3 https://<yourhost>:8080/loadTest?topic=1&intervalMs=40&payloadSize=4096&nUpdates=100&LongPollingIdx=Next"
299
+
```
300
+
301
+
## Documentation
245
302
246
303
.... more to follow.
247
304
248
-
###Don't like Cpp?
305
+
## Don't like Cpp?
249
306
250
307
For prototyping applications or services that do not interact with hardware-based systems, a Java-based
251
308
[OpenCMW](https://github.com/fair-acc/opencmw-java) twin-project is being developed which follows the same functional style
252
309
but takes advantage of more concise implementation and C++-based type safety.
253
310
254
-
###Acknowledgements
311
+
## Acknowledgements
255
312
256
313
The implementation heavily relies upon and re-uses time-tried and well-established concepts from [ZeroMQ](https://zeromq.org/)
257
314
(notably the [Majordomo](https://rfc.zeromq.org/spec/7/) communication pattern, see [Z-Guide](https://zguide.zeromq.org/docs/chapter4/#Service-Oriented-Reliable-Queuing-Majordomo-Pattern)
0 commit comments