uws-react-native 0.0.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +84 -0
- package/UwsReactNative.podspec +71 -0
- package/android/build.gradle.kts +138 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/id/sufeni/oss/uwsreactnative/UwsReactNativePackage.kt +18 -0
- package/apple/OnLoad.mm +17 -0
- package/cpp/CMakeLists.txt +154 -0
- package/cpp/UwsReactNativeModule.cpp +191 -0
- package/cpp/UwsReactNativeModule.h +30 -0
- package/cpp/app/AppHost.h +37 -0
- package/cpp/app/AppRunner.h +88 -0
- package/cpp/app/CMakeLists.txt +39 -0
- package/cpp/app/HttpRequestObject.h +173 -0
- package/cpp/app/HttpResponseObject.h +623 -0
- package/cpp/app/RecognizedString.h +71 -0
- package/cpp/app/TemplatedAppObject.h +472 -0
- package/cpp/bridging/ArrayBuffer.h +150 -0
- package/cpp/bridging/CMakeLists.txt +34 -0
- package/cpp/jsi/Buffer.h +91 -0
- package/cpp/jsi/CMakeLists.txt +34 -0
- package/cpp/uSockets/bsd.c +767 -0
- package/cpp/uSockets/context.c +524 -0
- package/cpp/uSockets/crypto/openssl.c +858 -0
- package/cpp/uSockets/crypto/sni_tree.cpp +218 -0
- package/cpp/uSockets/eventing/asio.cpp +475 -0
- package/cpp/uSockets/eventing/epoll_kqueue.c +458 -0
- package/cpp/uSockets/eventing/gcd.c +278 -0
- package/cpp/uSockets/eventing/libuv.c +305 -0
- package/cpp/uSockets/internal/eventing/asio.h +45 -0
- package/cpp/uSockets/internal/eventing/epoll_kqueue.h +67 -0
- package/cpp/uSockets/internal/eventing/gcd.h +40 -0
- package/cpp/uSockets/internal/eventing/libuv.h +45 -0
- package/cpp/uSockets/internal/internal.h +224 -0
- package/cpp/uSockets/internal/loop_data.h +38 -0
- package/cpp/uSockets/internal/networking/bsd.h +109 -0
- package/cpp/uSockets/io_uring/internal.h +98 -0
- package/cpp/uSockets/io_uring/io_context.c +302 -0
- package/cpp/uSockets/io_uring/io_loop.c +422 -0
- package/cpp/uSockets/io_uring/io_socket.c +139 -0
- package/cpp/uSockets/libusockets.h +350 -0
- package/cpp/uSockets/loop.c +396 -0
- package/cpp/uSockets/quic.c +1071 -0
- package/cpp/uSockets/quic.h +68 -0
- package/cpp/uSockets/socket.c +231 -0
- package/cpp/uSockets/udp.c +151 -0
- package/cpp/uWebSockets/uWebSockets/App.h +676 -0
- package/cpp/uWebSockets/uWebSockets/AsyncSocket.h +376 -0
- package/cpp/uWebSockets/uWebSockets/AsyncSocketData.h +94 -0
- package/cpp/uWebSockets/uWebSockets/BloomFilter.h +83 -0
- package/cpp/uWebSockets/uWebSockets/CachingApp.h +115 -0
- package/cpp/uWebSockets/uWebSockets/ChunkedEncoding.h +237 -0
- package/cpp/uWebSockets/uWebSockets/ClientApp.h +36 -0
- package/cpp/uWebSockets/uWebSockets/Http3App.h +140 -0
- package/cpp/uWebSockets/uWebSockets/Http3Context.h +157 -0
- package/cpp/uWebSockets/uWebSockets/Http3ContextData.h +21 -0
- package/cpp/uWebSockets/uWebSockets/Http3Request.h +22 -0
- package/cpp/uWebSockets/uWebSockets/Http3Response.h +120 -0
- package/cpp/uWebSockets/uWebSockets/Http3ResponseData.h +25 -0
- package/cpp/uWebSockets/uWebSockets/HttpContext.h +521 -0
- package/cpp/uWebSockets/uWebSockets/HttpContextData.h +60 -0
- package/cpp/uWebSockets/uWebSockets/HttpErrors.h +53 -0
- package/cpp/uWebSockets/uWebSockets/HttpParser.h +747 -0
- package/cpp/uWebSockets/uWebSockets/HttpResponse.h +605 -0
- package/cpp/uWebSockets/uWebSockets/HttpResponseData.h +123 -0
- package/cpp/uWebSockets/uWebSockets/HttpRouter.h +384 -0
- package/cpp/uWebSockets/uWebSockets/LocalCluster.h +64 -0
- package/cpp/uWebSockets/uWebSockets/Loop.h +238 -0
- package/cpp/uWebSockets/uWebSockets/LoopData.h +113 -0
- package/cpp/uWebSockets/uWebSockets/MessageParser.h +64 -0
- package/cpp/uWebSockets/uWebSockets/MoveOnlyFunction.h +389 -0
- package/cpp/uWebSockets/uWebSockets/Multipart.h +231 -0
- package/cpp/uWebSockets/uWebSockets/PerMessageDeflate.h +303 -0
- package/cpp/uWebSockets/uWebSockets/ProxyParser.h +187 -0
- package/cpp/uWebSockets/uWebSockets/QueryParser.h +120 -0
- package/cpp/uWebSockets/uWebSockets/TopicTree.h +364 -0
- package/cpp/uWebSockets/uWebSockets/Utilities.h +66 -0
- package/cpp/uWebSockets/uWebSockets/WebSocket.h +407 -0
- package/cpp/uWebSockets/uWebSockets/WebSocketContext.h +436 -0
- package/cpp/uWebSockets/uWebSockets/WebSocketContextData.h +109 -0
- package/cpp/uWebSockets/uWebSockets/WebSocketData.h +86 -0
- package/cpp/uWebSockets/uWebSockets/WebSocketExtensions.h +256 -0
- package/cpp/uWebSockets/uWebSockets/WebSocketHandshake.h +145 -0
- package/cpp/uWebSockets/uWebSockets/WebSocketProtocol.h +525 -0
- package/lib/commonjs/_internal/native-modules/NativeReactNativeUws.js +12 -0
- package/lib/commonjs/_internal/native-modules/NativeReactNativeUws.js.map +1 -0
- package/lib/commonjs/index.js +28 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/modules/App.js +17 -0
- package/lib/commonjs/modules/App.js.map +1 -0
- package/lib/commonjs/modules/CompressOptions.js +103 -0
- package/lib/commonjs/modules/CompressOptions.js.map +1 -0
- package/lib/commonjs/modules/EnvironmentVariables.js +17 -0
- package/lib/commonjs/modules/EnvironmentVariables.js.map +1 -0
- package/lib/commonjs/modules/ListenOptions.js +12 -0
- package/lib/commonjs/modules/ListenOptions.js.map +1 -0
- package/lib/commonjs/modules/SSLApp.js +15 -0
- package/lib/commonjs/modules/SSLApp.js.map +1 -0
- package/lib/commonjs/modules/getParts.js +28 -0
- package/lib/commonjs/modules/getParts.js.map +1 -0
- package/lib/commonjs/modules/index.js +61 -0
- package/lib/commonjs/modules/index.js.map +1 -0
- package/lib/commonjs/modules/us_listen_socket_close.js +21 -0
- package/lib/commonjs/modules/us_listen_socket_close.js.map +1 -0
- package/lib/commonjs/modules/us_socket_local_port.js +22 -0
- package/lib/commonjs/modules/us_socket_local_port.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/types/AppDescriptor.js +2 -0
- package/lib/commonjs/types/AppDescriptor.js.map +1 -0
- package/lib/commonjs/types/AppOptions.js +2 -0
- package/lib/commonjs/types/AppOptions.js.map +1 -0
- package/lib/commonjs/types/HttpRequest.js +6 -0
- package/lib/commonjs/types/HttpRequest.js.map +1 -0
- package/lib/commonjs/types/HttpResponse.js +6 -0
- package/lib/commonjs/types/HttpResponse.js.map +1 -0
- package/lib/commonjs/types/HttpRouterOptions.js +2 -0
- package/lib/commonjs/types/HttpRouterOptions.js.map +1 -0
- package/lib/commonjs/types/MultipartField.js +2 -0
- package/lib/commonjs/types/MultipartField.js.map +1 -0
- package/lib/commonjs/types/RecognizedString.js +2 -0
- package/lib/commonjs/types/RecognizedString.js.map +1 -0
- package/lib/commonjs/types/TemplatedApp.js +6 -0
- package/lib/commonjs/types/TemplatedApp.js.map +1 -0
- package/lib/commonjs/types/WebSocket.js +6 -0
- package/lib/commonjs/types/WebSocket.js.map +1 -0
- package/lib/commonjs/types/WebSocketBehaviour.js +139 -0
- package/lib/commonjs/types/WebSocketBehaviour.js.map +1 -0
- package/lib/commonjs/types/index.js +2 -0
- package/lib/commonjs/types/index.js.map +1 -0
- package/lib/commonjs/types/us_listen_socket.js +2 -0
- package/lib/commonjs/types/us_listen_socket.js.map +1 -0
- package/lib/commonjs/types/us_socket.js +2 -0
- package/lib/commonjs/types/us_socket.js.map +1 -0
- package/lib/commonjs/types/us_socket_context_t.js +2 -0
- package/lib/commonjs/types/us_socket_context_t.js.map +1 -0
- package/lib/module/_internal/native-modules/NativeReactNativeUws.js +10 -0
- package/lib/module/_internal/native-modules/NativeReactNativeUws.js.map +1 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/modules/App.js +12 -0
- package/lib/module/modules/App.js.map +1 -0
- package/lib/module/modules/CompressOptions.js +103 -0
- package/lib/module/modules/CompressOptions.js.map +1 -0
- package/lib/module/modules/EnvironmentVariables.js +13 -0
- package/lib/module/modules/EnvironmentVariables.js.map +1 -0
- package/lib/module/modules/ListenOptions.js +8 -0
- package/lib/module/modules/ListenOptions.js.map +1 -0
- package/lib/module/modules/SSLApp.js +15 -0
- package/lib/module/modules/SSLApp.js.map +1 -0
- package/lib/module/modules/getParts.js +23 -0
- package/lib/module/modules/getParts.js.map +1 -0
- package/lib/module/modules/index.js +11 -0
- package/lib/module/modules/index.js.map +1 -0
- package/lib/module/modules/us_listen_socket_close.js +17 -0
- package/lib/module/modules/us_listen_socket_close.js.map +1 -0
- package/lib/module/modules/us_socket_local_port.js +18 -0
- package/lib/module/modules/us_socket_local_port.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types/AppDescriptor.js +2 -0
- package/lib/module/types/AppDescriptor.js.map +1 -0
- package/lib/module/types/AppOptions.js +2 -0
- package/lib/module/types/AppOptions.js.map +1 -0
- package/lib/module/types/HttpRequest.js +4 -0
- package/lib/module/types/HttpRequest.js.map +1 -0
- package/lib/module/types/HttpResponse.js +4 -0
- package/lib/module/types/HttpResponse.js.map +1 -0
- package/lib/module/types/HttpRouterOptions.js +2 -0
- package/lib/module/types/HttpRouterOptions.js.map +1 -0
- package/lib/module/types/MultipartField.js +2 -0
- package/lib/module/types/MultipartField.js.map +1 -0
- package/lib/module/types/RecognizedString.js +2 -0
- package/lib/module/types/RecognizedString.js.map +1 -0
- package/lib/module/types/TemplatedApp.js +4 -0
- package/lib/module/types/TemplatedApp.js.map +1 -0
- package/lib/module/types/WebSocket.js +4 -0
- package/lib/module/types/WebSocket.js.map +1 -0
- package/lib/module/types/WebSocketBehaviour.js +139 -0
- package/lib/module/types/WebSocketBehaviour.js.map +1 -0
- package/lib/module/types/index.js +2 -0
- package/lib/module/types/index.js.map +1 -0
- package/lib/module/types/us_listen_socket.js +2 -0
- package/lib/module/types/us_listen_socket.js.map +1 -0
- package/lib/module/types/us_socket.js +2 -0
- package/lib/module/types/us_socket.js.map +1 -0
- package/lib/module/types/us_socket_context_t.js +2 -0
- package/lib/module/types/us_socket_context_t.js.map +1 -0
- package/lib/typescript/commonjs/_internal/native-modules/NativeReactNativeUws.d.ts +22 -0
- package/lib/typescript/commonjs/_internal/native-modules/NativeReactNativeUws.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +3 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/modules/App.d.ts +7 -0
- package/lib/typescript/commonjs/modules/App.d.ts.map +1 -0
- package/lib/typescript/commonjs/modules/CompressOptions.d.ts +1 -0
- package/lib/typescript/commonjs/modules/CompressOptions.d.ts.map +1 -0
- package/lib/typescript/commonjs/modules/EnvironmentVariables.d.ts +16 -0
- package/lib/typescript/commonjs/modules/EnvironmentVariables.d.ts.map +1 -0
- package/lib/typescript/commonjs/modules/ListenOptions.d.ts +5 -0
- package/lib/typescript/commonjs/modules/ListenOptions.d.ts.map +1 -0
- package/lib/typescript/commonjs/modules/SSLApp.d.ts +1 -0
- package/lib/typescript/commonjs/modules/SSLApp.d.ts.map +1 -0
- package/lib/typescript/commonjs/modules/getParts.d.ts +6 -0
- package/lib/typescript/commonjs/modules/getParts.d.ts.map +1 -0
- package/lib/typescript/commonjs/modules/index.d.ts +6 -0
- package/lib/typescript/commonjs/modules/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/modules/us_listen_socket_close.d.ts +5 -0
- package/lib/typescript/commonjs/modules/us_listen_socket_close.d.ts.map +1 -0
- package/lib/typescript/commonjs/modules/us_socket_local_port.d.ts +5 -0
- package/lib/typescript/commonjs/modules/us_socket_local_port.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/types/AppDescriptor.d.ts +8 -0
- package/lib/typescript/commonjs/types/AppDescriptor.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/AppOptions.d.ts +17 -0
- package/lib/typescript/commonjs/types/AppOptions.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/HttpRequest.d.ts +54 -0
- package/lib/typescript/commonjs/types/HttpRequest.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/HttpResponse.d.ts +169 -0
- package/lib/typescript/commonjs/types/HttpResponse.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/HttpRouterOptions.d.ts +24 -0
- package/lib/typescript/commonjs/types/HttpRouterOptions.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/MultipartField.d.ts +7 -0
- package/lib/typescript/commonjs/types/MultipartField.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/RecognizedString.d.ts +10 -0
- package/lib/typescript/commonjs/types/RecognizedString.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/TemplatedApp.d.ts +108 -0
- package/lib/typescript/commonjs/types/TemplatedApp.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/WebSocket.d.ts +96 -0
- package/lib/typescript/commonjs/types/WebSocket.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/WebSocketBehaviour.d.ts +1 -0
- package/lib/typescript/commonjs/types/WebSocketBehaviour.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/index.d.ts +6 -0
- package/lib/typescript/commonjs/types/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/us_listen_socket.d.ts +7 -0
- package/lib/typescript/commonjs/types/us_listen_socket.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/us_socket.d.ts +7 -0
- package/lib/typescript/commonjs/types/us_socket.d.ts.map +1 -0
- package/lib/typescript/commonjs/types/us_socket_context_t.d.ts +7 -0
- package/lib/typescript/commonjs/types/us_socket_context_t.d.ts.map +1 -0
- package/lib/typescript/module/_internal/native-modules/NativeReactNativeUws.d.ts +22 -0
- package/lib/typescript/module/_internal/native-modules/NativeReactNativeUws.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +3 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/modules/App.d.ts +7 -0
- package/lib/typescript/module/modules/App.d.ts.map +1 -0
- package/lib/typescript/module/modules/CompressOptions.d.ts +1 -0
- package/lib/typescript/module/modules/CompressOptions.d.ts.map +1 -0
- package/lib/typescript/module/modules/EnvironmentVariables.d.ts +16 -0
- package/lib/typescript/module/modules/EnvironmentVariables.d.ts.map +1 -0
- package/lib/typescript/module/modules/ListenOptions.d.ts +5 -0
- package/lib/typescript/module/modules/ListenOptions.d.ts.map +1 -0
- package/lib/typescript/module/modules/SSLApp.d.ts +1 -0
- package/lib/typescript/module/modules/SSLApp.d.ts.map +1 -0
- package/lib/typescript/module/modules/getParts.d.ts +6 -0
- package/lib/typescript/module/modules/getParts.d.ts.map +1 -0
- package/lib/typescript/module/modules/index.d.ts +6 -0
- package/lib/typescript/module/modules/index.d.ts.map +1 -0
- package/lib/typescript/module/modules/us_listen_socket_close.d.ts +5 -0
- package/lib/typescript/module/modules/us_listen_socket_close.d.ts.map +1 -0
- package/lib/typescript/module/modules/us_socket_local_port.d.ts +5 -0
- package/lib/typescript/module/modules/us_socket_local_port.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/types/AppDescriptor.d.ts +8 -0
- package/lib/typescript/module/types/AppDescriptor.d.ts.map +1 -0
- package/lib/typescript/module/types/AppOptions.d.ts +17 -0
- package/lib/typescript/module/types/AppOptions.d.ts.map +1 -0
- package/lib/typescript/module/types/HttpRequest.d.ts +54 -0
- package/lib/typescript/module/types/HttpRequest.d.ts.map +1 -0
- package/lib/typescript/module/types/HttpResponse.d.ts +169 -0
- package/lib/typescript/module/types/HttpResponse.d.ts.map +1 -0
- package/lib/typescript/module/types/HttpRouterOptions.d.ts +24 -0
- package/lib/typescript/module/types/HttpRouterOptions.d.ts.map +1 -0
- package/lib/typescript/module/types/MultipartField.d.ts +7 -0
- package/lib/typescript/module/types/MultipartField.d.ts.map +1 -0
- package/lib/typescript/module/types/RecognizedString.d.ts +10 -0
- package/lib/typescript/module/types/RecognizedString.d.ts.map +1 -0
- package/lib/typescript/module/types/TemplatedApp.d.ts +108 -0
- package/lib/typescript/module/types/TemplatedApp.d.ts.map +1 -0
- package/lib/typescript/module/types/WebSocket.d.ts +96 -0
- package/lib/typescript/module/types/WebSocket.d.ts.map +1 -0
- package/lib/typescript/module/types/WebSocketBehaviour.d.ts +1 -0
- package/lib/typescript/module/types/WebSocketBehaviour.d.ts.map +1 -0
- package/lib/typescript/module/types/index.d.ts +6 -0
- package/lib/typescript/module/types/index.d.ts.map +1 -0
- package/lib/typescript/module/types/us_listen_socket.d.ts +7 -0
- package/lib/typescript/module/types/us_listen_socket.d.ts.map +1 -0
- package/lib/typescript/module/types/us_socket.d.ts +7 -0
- package/lib/typescript/module/types/us_socket.d.ts.map +1 -0
- package/lib/typescript/module/types/us_socket_context_t.d.ts +7 -0
- package/lib/typescript/module/types/us_socket_context_t.d.ts.map +1 -0
- package/lib/typescript/tsconfig.tsbuildinfo +1 -0
- package/package.json +62 -0
- package/src/_internal/native-modules/NativeUwsReactNative.ts +40 -0
- package/src/index.ts +2 -0
- package/src/modules/App.ts +14 -0
- package/src/modules/CompressOptions.ts +101 -0
- package/src/modules/EnvironmentVariables.ts +16 -0
- package/src/modules/ListenOptions.ts +4 -0
- package/src/modules/SSLApp.ts +13 -0
- package/src/modules/getParts.ts +29 -0
- package/src/modules/index.ts +8 -0
- package/src/modules/us_listen_socket_close.ts +15 -0
- package/src/modules/us_socket_local_port.ts +16 -0
- package/src/types/AppDescriptor.ts +7 -0
- package/src/types/AppOptions.ts +22 -0
- package/src/types/HttpRequest.ts +74 -0
- package/src/types/HttpResponse.ts +309 -0
- package/src/types/HttpRouterOptions.ts +24 -0
- package/src/types/MultipartField.ts +6 -0
- package/src/types/RecognizedString.ts +11 -0
- package/src/types/TemplatedApp.ts +285 -0
- package/src/types/WebSocket.ts +147 -0
- package/src/types/WebSocketBehaviour.ts +137 -0
- package/src/types/index.ts +12 -0
- package/src/types/us_listen_socket.ts +6 -0
- package/src/types/us_socket.ts +6 -0
- package/src/types/us_socket_context_t.ts +6 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Authored by Alex Hultman, 2018-2020.
|
|
3
|
+
* Intellectual property of third-party.
|
|
4
|
+
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#ifndef UWS_HTTPRESPONSEDATA_H
|
|
19
|
+
#define UWS_HTTPRESPONSEDATA_H
|
|
20
|
+
|
|
21
|
+
/* This data belongs to the HttpResponse */
|
|
22
|
+
|
|
23
|
+
#include "HttpParser.h"
|
|
24
|
+
#include "AsyncSocketData.h"
|
|
25
|
+
#include "ProxyParser.h"
|
|
26
|
+
|
|
27
|
+
#include "MoveOnlyFunction.h"
|
|
28
|
+
|
|
29
|
+
namespace uWS {
|
|
30
|
+
|
|
31
|
+
template <bool SSL>
|
|
32
|
+
struct HttpResponseData : AsyncSocketData<SSL>, HttpParser {
|
|
33
|
+
template <bool> friend struct HttpResponse;
|
|
34
|
+
template <bool> friend struct HttpContext;
|
|
35
|
+
|
|
36
|
+
/* When we are done with a response we mark it like so */
|
|
37
|
+
void markDone() {
|
|
38
|
+
onAborted = nullptr;
|
|
39
|
+
/* Also remove onWritable so that we do not emit when draining behind the scenes. */
|
|
40
|
+
onWritable = nullptr;
|
|
41
|
+
|
|
42
|
+
/* We are done with this request */
|
|
43
|
+
state &= ~HttpResponseData<SSL>::HTTP_RESPONSE_PENDING;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Caller of onWritable. It is possible onWritable calls markDone so we need to borrow it.
|
|
47
|
+
* It is also possible user code sets a new onWritable while running user registered onWritable. */
|
|
48
|
+
bool callOnWritable(uintmax_t offset) {
|
|
49
|
+
/* 1. Borrow the real callback */
|
|
50
|
+
MoveOnlyFunction<bool(uintmax_t)> borrowedOnWritable = std::move(onWritable);
|
|
51
|
+
|
|
52
|
+
/* 2. Setup the stack-based detection flag */
|
|
53
|
+
bool placeholderReplaced = false;
|
|
54
|
+
|
|
55
|
+
struct Sentinel {
|
|
56
|
+
bool *replacedFlag;
|
|
57
|
+
Sentinel(bool *f) : replacedFlag(f) {}
|
|
58
|
+
|
|
59
|
+
Sentinel(Sentinel &&other) noexcept : replacedFlag(other.replacedFlag) {
|
|
60
|
+
other.replacedFlag = nullptr;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
~Sentinel() {
|
|
64
|
+
if (replacedFlag) {
|
|
65
|
+
*replacedFlag = true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* Delete copy to ensure move-only semantics */
|
|
70
|
+
Sentinel(const Sentinel&) = delete;
|
|
71
|
+
Sentinel& operator=(const Sentinel&) = delete;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/* 3. Set placeholder with the captured Sentinel */
|
|
75
|
+
onWritable = [tracker = Sentinel(&placeholderReplaced)](uintmax_t) {
|
|
76
|
+
return true;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/* 4. Run the borrowed callback */
|
|
80
|
+
bool ret = borrowedOnWritable(offset);
|
|
81
|
+
|
|
82
|
+
/*
|
|
83
|
+
5. If placeholderReplaced is STILL false, it means the lambda (and its Sentinel)
|
|
84
|
+
is still sitting inside 'onWritable'. If it's true, the lambda was destroyed
|
|
85
|
+
to make room for a new one.
|
|
86
|
+
*/
|
|
87
|
+
if (!placeholderReplaced) {
|
|
88
|
+
onWritable = std::move(borrowedOnWritable);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return ret;
|
|
92
|
+
}
|
|
93
|
+
private:
|
|
94
|
+
/* Bits of status */
|
|
95
|
+
enum {
|
|
96
|
+
HTTP_STATUS_CALLED = 1, // used
|
|
97
|
+
HTTP_WRITE_CALLED = 2, // used
|
|
98
|
+
HTTP_END_CALLED = 4, // used
|
|
99
|
+
HTTP_RESPONSE_PENDING = 8, // used
|
|
100
|
+
HTTP_CONNECTION_CLOSE = 16 // used
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/* Per socket event handlers */
|
|
104
|
+
MoveOnlyFunction<bool(uintmax_t)> onWritable;
|
|
105
|
+
MoveOnlyFunction<void()> onAborted;
|
|
106
|
+
MoveOnlyFunction<void(std::string_view, uint64_t)> inStream; // onData
|
|
107
|
+
/* Outgoing offset */
|
|
108
|
+
uintmax_t offset = 0;
|
|
109
|
+
|
|
110
|
+
/* Let's track number of bytes since last timeout reset in data handler */
|
|
111
|
+
unsigned int received_bytes_per_timeout = 0;
|
|
112
|
+
|
|
113
|
+
/* Current state (content-length sent, status sent, write called, etc */
|
|
114
|
+
int state = 0;
|
|
115
|
+
|
|
116
|
+
#ifdef UWS_WITH_PROXY
|
|
117
|
+
ProxyParser proxyParser;
|
|
118
|
+
#endif
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
#endif // UWS_HTTPRESPONSEDATA_H
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Authored by Alex Hultman, 2018-2020.
|
|
3
|
+
* Intellectual property of third-party.
|
|
4
|
+
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#ifndef UWS_HTTPROUTER_HPP
|
|
19
|
+
#define UWS_HTTPROUTER_HPP
|
|
20
|
+
|
|
21
|
+
#include <map>
|
|
22
|
+
#include <vector>
|
|
23
|
+
#include <cstring>
|
|
24
|
+
#include <string_view>
|
|
25
|
+
#include <string>
|
|
26
|
+
#include <algorithm>
|
|
27
|
+
#include <memory>
|
|
28
|
+
#include <utility>
|
|
29
|
+
|
|
30
|
+
#include <iostream>
|
|
31
|
+
|
|
32
|
+
#include "MoveOnlyFunction.h"
|
|
33
|
+
|
|
34
|
+
namespace uWS {
|
|
35
|
+
|
|
36
|
+
template <class USERDATA>
|
|
37
|
+
struct HttpRouter {
|
|
38
|
+
static constexpr std::string_view ANY_METHOD_TOKEN = "*";
|
|
39
|
+
static const uint32_t HIGH_PRIORITY = 0xd0000000, MEDIUM_PRIORITY = 0xe0000000, LOW_PRIORITY = 0xf0000000;
|
|
40
|
+
|
|
41
|
+
private:
|
|
42
|
+
USERDATA userData;
|
|
43
|
+
static const unsigned int MAX_URL_SEGMENTS = 100;
|
|
44
|
+
|
|
45
|
+
/* Handler ids are 32-bit */
|
|
46
|
+
static const uint32_t HANDLER_MASK = 0x0fffffff;
|
|
47
|
+
|
|
48
|
+
/* List of handlers */
|
|
49
|
+
std::vector<MoveOnlyFunction<bool(HttpRouter *)>> handlers;
|
|
50
|
+
|
|
51
|
+
/* Current URL cache */
|
|
52
|
+
std::string_view currentUrl;
|
|
53
|
+
std::string_view urlSegmentVector[MAX_URL_SEGMENTS];
|
|
54
|
+
int urlSegmentTop;
|
|
55
|
+
|
|
56
|
+
/* The matching tree */
|
|
57
|
+
struct Node {
|
|
58
|
+
std::string name;
|
|
59
|
+
std::vector<std::unique_ptr<Node>> children;
|
|
60
|
+
std::vector<uint32_t> handlers;
|
|
61
|
+
bool isHighPriority;
|
|
62
|
+
|
|
63
|
+
Node(std::string name) : name(name) {}
|
|
64
|
+
} root = {"rootNode"};
|
|
65
|
+
|
|
66
|
+
/* Sort wildcards after alphanum */
|
|
67
|
+
int lexicalOrder(std::string &name) {
|
|
68
|
+
if (!name.length()) {
|
|
69
|
+
return 2;
|
|
70
|
+
}
|
|
71
|
+
if (name[0] == ':') {
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
if (name[0] == '*') {
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
return 2;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Advance from parent to child, adding child if necessary */
|
|
81
|
+
Node *getNode(Node *parent, std::string child, bool isHighPriority) {
|
|
82
|
+
for (std::unique_ptr<Node> &node : parent->children) {
|
|
83
|
+
if (node->name == child && node->isHighPriority == isHighPriority) {
|
|
84
|
+
return node.get();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Insert sorted, but keep order if parent is root (we sort methods by priority elsewhere) */
|
|
89
|
+
std::unique_ptr<Node> newNode(new Node(child));
|
|
90
|
+
newNode->isHighPriority = isHighPriority;
|
|
91
|
+
return parent->children.emplace(std::upper_bound(parent->children.begin(), parent->children.end(), newNode, [parent, this](auto &a, auto &b) {
|
|
92
|
+
|
|
93
|
+
if (a->isHighPriority != b->isHighPriority) {
|
|
94
|
+
return a->isHighPriority;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return b->name.length() && (parent != &root) && (lexicalOrder(b->name) < lexicalOrder(a->name));
|
|
98
|
+
}), std::move(newNode))->get();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Basically a pre-allocated stack */
|
|
102
|
+
struct RouteParameters {
|
|
103
|
+
friend struct HttpRouter;
|
|
104
|
+
private:
|
|
105
|
+
std::string_view params[MAX_URL_SEGMENTS];
|
|
106
|
+
int paramsTop;
|
|
107
|
+
|
|
108
|
+
void reset() {
|
|
109
|
+
paramsTop = -1;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
void push(std::string_view param) {
|
|
113
|
+
/* We check these bounds indirectly via the urlSegments limit */
|
|
114
|
+
params[++paramsTop] = param;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
void pop() {
|
|
118
|
+
/* Same here, we cannot pop outside */
|
|
119
|
+
paramsTop--;
|
|
120
|
+
}
|
|
121
|
+
} routeParameters;
|
|
122
|
+
|
|
123
|
+
/* Set URL for router. Will reset any URL cache */
|
|
124
|
+
inline void setUrl(std::string_view url) {
|
|
125
|
+
|
|
126
|
+
/* Todo: URL may also start with "http://domain/" or "*", not only "/" */
|
|
127
|
+
|
|
128
|
+
/* We expect to stand on a slash */
|
|
129
|
+
currentUrl = url;
|
|
130
|
+
urlSegmentTop = -1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* Lazily parse or read from cache */
|
|
134
|
+
inline std::pair<std::string_view, bool> getUrlSegment(int urlSegment) {
|
|
135
|
+
if (urlSegment > urlSegmentTop) {
|
|
136
|
+
/* Signal as STOP when we have no more URL or stack space */
|
|
137
|
+
if (!currentUrl.length() || urlSegment > int(MAX_URL_SEGMENTS - 1)) {
|
|
138
|
+
return {{}, true};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* We always stand on a slash here, so step over it */
|
|
142
|
+
currentUrl.remove_prefix(1);
|
|
143
|
+
|
|
144
|
+
auto segmentLength = currentUrl.find('/');
|
|
145
|
+
if (segmentLength == std::string::npos) {
|
|
146
|
+
segmentLength = currentUrl.length();
|
|
147
|
+
|
|
148
|
+
/* Push to url segment vector */
|
|
149
|
+
urlSegmentVector[urlSegment] = currentUrl.substr(0, segmentLength);
|
|
150
|
+
urlSegmentTop++;
|
|
151
|
+
|
|
152
|
+
/* Update currentUrl */
|
|
153
|
+
currentUrl = currentUrl.substr(segmentLength);
|
|
154
|
+
} else {
|
|
155
|
+
/* Push to url segment vector */
|
|
156
|
+
urlSegmentVector[urlSegment] = currentUrl.substr(0, segmentLength);
|
|
157
|
+
urlSegmentTop++;
|
|
158
|
+
|
|
159
|
+
/* Update currentUrl */
|
|
160
|
+
currentUrl = currentUrl.substr(segmentLength);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/* In any case we return it */
|
|
164
|
+
return {urlSegmentVector[urlSegment], false};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* Executes as many handlers it can */
|
|
168
|
+
bool executeHandlers(Node *parent, int urlSegment, USERDATA &userData) {
|
|
169
|
+
|
|
170
|
+
auto [segment, isStop] = getUrlSegment(urlSegment);
|
|
171
|
+
|
|
172
|
+
/* If we are on STOP, return where we may stand */
|
|
173
|
+
if (isStop) {
|
|
174
|
+
/* We have reached accross the entire URL with no stoppage, execute */
|
|
175
|
+
for (uint32_t handler : parent->handlers) {
|
|
176
|
+
if (handlers[handler & HANDLER_MASK](this)) {
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/* We reached the end, so go back */
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
for (auto &p : parent->children) {
|
|
185
|
+
if (p->name.length() && p->name[0] == '*') {
|
|
186
|
+
/* Wildcard match (can be seen as a shortcut) */
|
|
187
|
+
for (uint32_t handler : p->handlers) {
|
|
188
|
+
if (handlers[handler & HANDLER_MASK](this)) {
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
} else if (p->name.length() && p->name[0] == ':' && segment.length()) {
|
|
193
|
+
/* Parameter match */
|
|
194
|
+
routeParameters.push(segment);
|
|
195
|
+
if (executeHandlers(p.get(), urlSegment + 1, userData)) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
routeParameters.pop();
|
|
199
|
+
} else if (p->name == segment) {
|
|
200
|
+
/* Static match */
|
|
201
|
+
if (executeHandlers(p.get(), urlSegment + 1, userData)) {
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* Scans for one matching handler, returning the handler and its priority or UINT32_MAX for not found */
|
|
210
|
+
uint32_t findHandler(std::string method, std::string pattern, uint32_t priority) {
|
|
211
|
+
for (std::unique_ptr<Node> &node : root.children) {
|
|
212
|
+
if (method == node->name) {
|
|
213
|
+
setUrl(pattern);
|
|
214
|
+
Node *n = node.get();
|
|
215
|
+
for (int i = 0; !getUrlSegment(i).second; i++) {
|
|
216
|
+
/* Go to next segment or quit */
|
|
217
|
+
std::string segment = std::string(getUrlSegment(i).first);
|
|
218
|
+
Node *next = nullptr;
|
|
219
|
+
for (std::unique_ptr<Node> &child : n->children) {
|
|
220
|
+
if (((segment.length() && child->name.length() && segment[0] == ':' && child->name[0] == ':') || child->name == segment) && child->isHighPriority == (priority == HIGH_PRIORITY)) {
|
|
221
|
+
next = child.get();
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (!next) {
|
|
226
|
+
return UINT32_MAX;
|
|
227
|
+
}
|
|
228
|
+
n = next;
|
|
229
|
+
}
|
|
230
|
+
/* Seek for a priority match in the found node */
|
|
231
|
+
for (unsigned int i = 0; i < n->handlers.size(); i++) {
|
|
232
|
+
if ((n->handlers[i] & ~HANDLER_MASK) == priority) {
|
|
233
|
+
return n->handlers[i];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return UINT32_MAX;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return UINT32_MAX;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
public:
|
|
243
|
+
HttpRouter() {
|
|
244
|
+
/* Always have ANY route */
|
|
245
|
+
getNode(&root, std::string(ANY_METHOD_TOKEN.data(), ANY_METHOD_TOKEN.length()), false);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
std::pair<int, std::string_view *> getParameters() {
|
|
249
|
+
return {routeParameters.paramsTop, routeParameters.params};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
USERDATA &getUserData() {
|
|
253
|
+
return userData;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/* Fast path */
|
|
257
|
+
bool route(std::string_view method, std::string_view url) {
|
|
258
|
+
/* Reset url parsing cache */
|
|
259
|
+
setUrl(url);
|
|
260
|
+
routeParameters.reset();
|
|
261
|
+
|
|
262
|
+
/* Begin by finding the method node */
|
|
263
|
+
for (auto &p : root.children) {
|
|
264
|
+
if (p->name == method) {
|
|
265
|
+
/* Then route the url */
|
|
266
|
+
if (executeHandlers(p.get(), 0, userData)) {
|
|
267
|
+
return true;
|
|
268
|
+
} else {
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/* Always test any route last (this check should not be necessary if we always have at least one handler) */
|
|
275
|
+
if (root.children.empty()) [[unlikely]] {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
return executeHandlers(root.children.back().get(), 0, userData);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/* Adds the corresponding entires in matching tree and handler list */
|
|
282
|
+
void add(std::vector<std::string> methods, std::string pattern, MoveOnlyFunction<bool(HttpRouter *)> &&handler, uint32_t priority = MEDIUM_PRIORITY) {
|
|
283
|
+
/* First remove existing handler */
|
|
284
|
+
remove(methods[0], pattern, priority);
|
|
285
|
+
|
|
286
|
+
for (std::string method : methods) {
|
|
287
|
+
/* Lookup method */
|
|
288
|
+
Node *node = getNode(&root, method, false);
|
|
289
|
+
/* Iterate over all segments */
|
|
290
|
+
setUrl(pattern);
|
|
291
|
+
for (int i = 0; !getUrlSegment(i).second; i++) {
|
|
292
|
+
std::string strippedSegment(getUrlSegment(i).first);
|
|
293
|
+
if (strippedSegment.length() && strippedSegment[0] == ':') {
|
|
294
|
+
/* Parameter routes must be named only : */
|
|
295
|
+
strippedSegment = ":";
|
|
296
|
+
}
|
|
297
|
+
node = getNode(node, strippedSegment, priority == HIGH_PRIORITY);
|
|
298
|
+
}
|
|
299
|
+
/* Insert handler in order sorted by priority (most significant 1 byte) */
|
|
300
|
+
node->handlers.insert(std::upper_bound(node->handlers.begin(), node->handlers.end(), (uint32_t) (priority | handlers.size())), (uint32_t) (priority | handlers.size()));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/* Alloate this handler */
|
|
304
|
+
handlers.emplace_back(std::move(handler));
|
|
305
|
+
|
|
306
|
+
/* ANY method must be last, GET must be first */
|
|
307
|
+
std::sort(root.children.begin(), root.children.end(), [](const auto &a, const auto &b) {
|
|
308
|
+
if (a->name == "GET" && b->name != "GET") {
|
|
309
|
+
return true;
|
|
310
|
+
} else if (b->name == "GET" && a->name != "GET") {
|
|
311
|
+
return false;
|
|
312
|
+
} else if (a->name == ANY_METHOD_TOKEN && b->name != ANY_METHOD_TOKEN) {
|
|
313
|
+
return false;
|
|
314
|
+
} else if (b->name == ANY_METHOD_TOKEN && a->name != ANY_METHOD_TOKEN) {
|
|
315
|
+
return true;
|
|
316
|
+
} else {
|
|
317
|
+
return a->name < b->name;
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
bool cullNode(Node *parent, Node *node, uint32_t handler) {
|
|
323
|
+
/* For all children */
|
|
324
|
+
for (unsigned int i = 0; i < node->children.size(); ) {
|
|
325
|
+
/* Optimization todo: only enter those with same isHighPrioirty */
|
|
326
|
+
/* Enter child so we get depth first */
|
|
327
|
+
if (!cullNode(node, node->children[i].get(), handler)) {
|
|
328
|
+
/* Only increase if this node was not removed */
|
|
329
|
+
i++;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* Cull this node (but skip the root node) */
|
|
334
|
+
if (parent /*&& parent != &root*/) {
|
|
335
|
+
/* Scan for equal (remove), greater (lower by 1) */
|
|
336
|
+
for (auto it = node->handlers.begin(); it != node->handlers.end(); ) {
|
|
337
|
+
if ((*it & HANDLER_MASK) > (handler & HANDLER_MASK)) {
|
|
338
|
+
*it = ((*it & HANDLER_MASK) - 1) | (*it & ~HANDLER_MASK);
|
|
339
|
+
} else if (*it == handler) {
|
|
340
|
+
it = node->handlers.erase(it);
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
it++;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* If we have no children and no handlers, remove us from the parent->children list */
|
|
347
|
+
if (!node->handlers.size() && !node->children.size()) {
|
|
348
|
+
parent->children.erase(std::find_if(parent->children.begin(), parent->children.end(), [node](const std::unique_ptr<Node> &a) {
|
|
349
|
+
return a.get() == node;
|
|
350
|
+
}));
|
|
351
|
+
/* Returning true means we removed node from parent */
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/* Removes ALL routes with the same handler as can be found with the given parameters.
|
|
360
|
+
* Removing a wildcard is done by removing ONE OF the methods the wildcard would match with.
|
|
361
|
+
* Example: If wildcard includes POST, GET, PUT, you can remove ALL THREE by removing GET. */
|
|
362
|
+
bool remove(std::string method, std::string pattern, uint32_t priority) {
|
|
363
|
+
uint32_t handler = findHandler(method, pattern, priority);
|
|
364
|
+
if (handler == UINT32_MAX) {
|
|
365
|
+
/* Not found or already removed, do nothing */
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/* Cull the entire tree */
|
|
370
|
+
/* For all nodes in depth first tree traveral;
|
|
371
|
+
* if node contains handler - remove the handler -
|
|
372
|
+
* if node holds no handlers after removal, remove the node and return */
|
|
373
|
+
cullNode(nullptr, &root, handler);
|
|
374
|
+
|
|
375
|
+
/* Now remove the actual handler */
|
|
376
|
+
handlers.erase(handlers.begin() + (handler & HANDLER_MASK));
|
|
377
|
+
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
#endif // UWS_HTTPROUTER_HPP
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/* This header is highly experimental and needs refactorings but will do for now */
|
|
2
|
+
|
|
3
|
+
#include <thread>
|
|
4
|
+
#include <algorithm>
|
|
5
|
+
#include <mutex>
|
|
6
|
+
|
|
7
|
+
unsigned int roundRobin = 0;
|
|
8
|
+
unsigned int hardwareConcurrency = std::thread::hardware_concurrency();
|
|
9
|
+
std::vector<std::thread *> threads(hardwareConcurrency);
|
|
10
|
+
std::vector<uWS::SSLApp *> apps;
|
|
11
|
+
std::mutex m;
|
|
12
|
+
|
|
13
|
+
namespace uWS {
|
|
14
|
+
struct LocalCluster {
|
|
15
|
+
|
|
16
|
+
//std::vector<std::thread *> threads = std::thread::hardware_concurrency();
|
|
17
|
+
//std::vector<uWS::SSLApp *> apps;
|
|
18
|
+
//std::mutex m;
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
static void loadBalancer() {
|
|
22
|
+
static std::atomic<unsigned int> roundRobin = 0; // atomic fetch_add
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
LocalCluster(SocketContextOptions options = {}, std::function<void(uWS::SSLApp &)> cb = nullptr) {
|
|
26
|
+
std::transform(threads.begin(), threads.end(), threads.begin(), [options, &cb](std::thread *) {
|
|
27
|
+
|
|
28
|
+
return new std::thread([options, &cb]() {
|
|
29
|
+
|
|
30
|
+
// lock this
|
|
31
|
+
m.lock();
|
|
32
|
+
apps.emplace_back(new uWS::SSLApp(options));
|
|
33
|
+
uWS::SSLApp *app = apps.back();
|
|
34
|
+
|
|
35
|
+
cb(*app);
|
|
36
|
+
|
|
37
|
+
app->preOpen([](struct us_socket_context_t *context, LIBUS_SOCKET_DESCRIPTOR fd, char *ip, int ip_length) -> LIBUS_SOCKET_DESCRIPTOR {
|
|
38
|
+
|
|
39
|
+
std::ignore = context;
|
|
40
|
+
|
|
41
|
+
/* Distribute this socket in round robin fashion */
|
|
42
|
+
//std::cout << "About to load balance " << fd << " to " << roundRobin << std::endl;
|
|
43
|
+
|
|
44
|
+
auto receivingApp = apps[roundRobin];
|
|
45
|
+
apps[roundRobin]->getLoop()->defer([fd, ipStore = std::string(ip, ip + ip_length), receivingApp]() {
|
|
46
|
+
receivingApp->adoptSocket(fd, std::string_view(ipStore));
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
roundRobin = (roundRobin + 1) % hardwareConcurrency;
|
|
50
|
+
return (LIBUS_SOCKET_DESCRIPTOR) -1;
|
|
51
|
+
});
|
|
52
|
+
m.unlock();
|
|
53
|
+
app->run();
|
|
54
|
+
std::cout << "Fallthrough!" << std::endl;
|
|
55
|
+
delete app;
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
std::for_each(threads.begin(), threads.end(), [](std::thread *t) {
|
|
60
|
+
t->join();
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|