opal-up 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +209 -0
  3. data/README.md +97 -29
  4. data/bin/up_ruby +4 -0
  5. data/bin/up_ruby_cluster +4 -0
  6. data/ext/up_ext/App.h +606 -0
  7. data/ext/up_ext/AsyncSocket.h +355 -0
  8. data/ext/up_ext/AsyncSocketData.h +87 -0
  9. data/ext/up_ext/BloomFilter.h +83 -0
  10. data/ext/up_ext/ChunkedEncoding.h +236 -0
  11. data/ext/up_ext/ClientApp.h +36 -0
  12. data/ext/up_ext/HttpContext.h +502 -0
  13. data/ext/up_ext/HttpContextData.h +56 -0
  14. data/ext/up_ext/HttpErrors.h +53 -0
  15. data/ext/up_ext/HttpParser.h +680 -0
  16. data/ext/up_ext/HttpResponse.h +578 -0
  17. data/ext/up_ext/HttpResponseData.h +95 -0
  18. data/ext/up_ext/HttpRouter.h +380 -0
  19. data/ext/up_ext/Loop.h +204 -0
  20. data/ext/up_ext/LoopData.h +112 -0
  21. data/ext/up_ext/MoveOnlyFunction.h +377 -0
  22. data/ext/up_ext/PerMessageDeflate.h +315 -0
  23. data/ext/up_ext/ProxyParser.h +163 -0
  24. data/ext/up_ext/QueryParser.h +120 -0
  25. data/ext/up_ext/TopicTree.h +363 -0
  26. data/ext/up_ext/Utilities.h +66 -0
  27. data/ext/up_ext/WebSocket.h +381 -0
  28. data/ext/up_ext/WebSocketContext.h +434 -0
  29. data/ext/up_ext/WebSocketContextData.h +109 -0
  30. data/ext/up_ext/WebSocketData.h +86 -0
  31. data/ext/up_ext/WebSocketExtensions.h +256 -0
  32. data/ext/up_ext/WebSocketHandshake.h +145 -0
  33. data/ext/up_ext/WebSocketProtocol.h +506 -0
  34. data/ext/up_ext/bsd.c +767 -0
  35. data/ext/up_ext/bsd.h +109 -0
  36. data/ext/up_ext/context.c +524 -0
  37. data/ext/up_ext/epoll_kqueue.c +458 -0
  38. data/ext/up_ext/epoll_kqueue.h +67 -0
  39. data/ext/up_ext/extconf.rb +5 -0
  40. data/ext/up_ext/internal.h +224 -0
  41. data/ext/up_ext/libusockets.h +350 -0
  42. data/ext/up_ext/libuwebsockets.cpp +1344 -0
  43. data/ext/up_ext/libuwebsockets.h +396 -0
  44. data/ext/up_ext/loop.c +386 -0
  45. data/ext/up_ext/loop_data.h +38 -0
  46. data/ext/up_ext/socket.c +231 -0
  47. data/ext/up_ext/up_ext.c +930 -0
  48. data/lib/up/bun/rack_env.rb +1 -13
  49. data/lib/up/bun/server.rb +93 -19
  50. data/lib/up/cli.rb +3 -0
  51. data/lib/up/client.rb +68 -0
  52. data/lib/up/ruby/cluster.rb +39 -0
  53. data/lib/up/ruby/cluster_cli.rb +10 -0
  54. data/lib/up/{node → ruby}/rack_cluster.rb +5 -4
  55. data/lib/up/{node → ruby}/rack_server.rb +4 -4
  56. data/lib/up/ruby/server_cli.rb +10 -0
  57. data/lib/up/u_web_socket/cluster.rb +18 -3
  58. data/lib/up/u_web_socket/server.rb +108 -15
  59. data/lib/up/version.rb +1 -1
  60. metadata +72 -30
  61. data/.gitignore +0 -5
  62. data/Gemfile +0 -2
  63. data/bin/up_node +0 -12
  64. data/bin/up_node_cluster +0 -12
  65. data/example_rack_app/Gemfile +0 -3
  66. data/example_rack_app/config.ru +0 -6
  67. data/example_rack_app/rack_app.rb +0 -5
  68. data/example_roda_app/Gemfile +0 -6
  69. data/example_roda_app/config.ru +0 -6
  70. data/example_roda_app/roda_app.rb +0 -37
  71. data/example_sinatra_app/Gemfile +0 -6
  72. data/example_sinatra_app/config.ru +0 -6
  73. data/example_sinatra_app/sinatra_app.rb +0 -7
  74. data/lib/up/node/cluster.rb +0 -39
  75. data/lib/up/node/cluster_cli.rb +0 -15
  76. data/lib/up/node/rack_env.rb +0 -106
  77. data/lib/up/node/server.rb +0 -84
  78. data/lib/up/node/server_cli.rb +0 -15
  79. data/lib/up/u_web_socket/rack_env.rb +0 -101
  80. data/opal-up.gemspec +0 -27
  81. data/up_logo.svg +0 -256
@@ -0,0 +1,236 @@
1
+ /*
2
+ * Authored by Alex Hultman, 2018-2022.
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_CHUNKEDENCODING_H
19
+ #define UWS_CHUNKEDENCODING_H
20
+
21
+ /* Independent chunked encoding parser, used by HttpParser. */
22
+
23
+ #include <string>
24
+ #include <cstring>
25
+ #include <algorithm>
26
+ #include <string_view>
27
+ #include "MoveOnlyFunction.h"
28
+ #include <optional>
29
+
30
+ namespace uWS {
31
+
32
+ constexpr uint64_t STATE_HAS_SIZE = 1ull << (sizeof(uint64_t) * 8 - 1);//0x80000000;
33
+ constexpr uint64_t STATE_IS_CHUNKED = 1ull << (sizeof(uint64_t) * 8 - 2);//0x40000000;
34
+ constexpr uint64_t STATE_SIZE_MASK = ~(3ull << (sizeof(uint64_t) * 8 - 2));//0x3FFFFFFF;
35
+ constexpr uint64_t STATE_IS_ERROR = ~0ull;//0xFFFFFFFF;
36
+ constexpr uint64_t STATE_SIZE_OVERFLOW = 0x0Full << (sizeof(uint64_t) * 8 - 8);//0x0F000000;
37
+
38
+ inline uint64_t chunkSize(uint64_t state) {
39
+ return state & STATE_SIZE_MASK;
40
+ }
41
+
42
+ /* Reads hex number until CR or out of data to consume. Updates state. Returns bytes consumed. */
43
+ inline void consumeHexNumber(std::string_view &data, uint64_t &state) {
44
+ /* Consume everything higher than 32 */
45
+ while (data.length() && data.data()[0] > 32) {
46
+
47
+ unsigned char digit = (unsigned char)data.data()[0];
48
+ if (digit >= 'a') {
49
+ digit = (unsigned char) (digit - ('a' - ':'));
50
+ } else if (digit >= 'A') {
51
+ digit = (unsigned char) (digit - ('A' - ':'));
52
+ }
53
+
54
+ unsigned int number = ((unsigned int) digit - (unsigned int) '0');
55
+
56
+ if (number > 16 || (chunkSize(state) & STATE_SIZE_OVERFLOW)) {
57
+ state = STATE_IS_ERROR;
58
+ return;
59
+ }
60
+
61
+ // extract state bits
62
+ uint64_t bits = /*state &*/ STATE_IS_CHUNKED;
63
+
64
+ state = (state & STATE_SIZE_MASK) * 16ull + number;
65
+
66
+ state |= bits;
67
+ data.remove_prefix(1);
68
+ }
69
+ /* Consume everything not /n */
70
+ while (data.length() && data.data()[0] != '\n') {
71
+ data.remove_prefix(1);
72
+ }
73
+ /* Now we stand on \n so consume it and enable size */
74
+ if (data.length()) {
75
+ state += 2; // include the two last /r/n
76
+ state |= STATE_HAS_SIZE | STATE_IS_CHUNKED;
77
+ data.remove_prefix(1);
78
+ }
79
+ }
80
+
81
+ inline void decChunkSize(uint64_t &state, unsigned int by) {
82
+
83
+ //unsigned int bits = state & STATE_IS_CHUNKED;
84
+
85
+ state = (state & ~STATE_SIZE_MASK) | (chunkSize(state) - by);
86
+
87
+ //state |= bits;
88
+ }
89
+
90
+ inline bool hasChunkSize(uint64_t state) {
91
+ return state & STATE_HAS_SIZE;
92
+ }
93
+
94
+ /* Are we in the middle of parsing chunked encoding? */
95
+ inline bool isParsingChunkedEncoding(uint64_t state) {
96
+ return state & ~STATE_SIZE_MASK;
97
+ }
98
+
99
+ inline bool isParsingInvalidChunkedEncoding(uint64_t state) {
100
+ return state == STATE_IS_ERROR;
101
+ }
102
+
103
+ /* Returns next chunk (empty or not), or if all data was consumed, nullopt is returned. */
104
+ static std::optional<std::string_view> getNextChunk(std::string_view &data, uint64_t &state, bool trailer = false) {
105
+
106
+ while (data.length()) {
107
+
108
+ // if in "drop trailer mode", just drop up to what we have as size
109
+ if (((state & STATE_IS_CHUNKED) == 0) && hasChunkSize(state) && chunkSize(state)) {
110
+
111
+ //printf("Parsing trailer now\n");
112
+
113
+ while(data.length() && chunkSize(state)) {
114
+ data.remove_prefix(1);
115
+ decChunkSize(state, 1);
116
+
117
+ if (chunkSize(state) == 0) {
118
+
119
+ /* This is an actual place where we need 0 as state */
120
+ state = 0;
121
+
122
+ /* The parser MUST stop consuming here */
123
+ return std::nullopt;
124
+ }
125
+ }
126
+ continue;
127
+ }
128
+
129
+ if (!hasChunkSize(state)) {
130
+ consumeHexNumber(data, state);
131
+ if (isParsingInvalidChunkedEncoding(state)) {
132
+ return std::nullopt;
133
+ }
134
+ if (hasChunkSize(state) && chunkSize(state) == 2) {
135
+
136
+ //printf("Setting state to trailer-parsing and emitting empty chunk\n");
137
+
138
+ // set trailer state and increase size to 4
139
+ if (trailer) {
140
+ state = 4 /*| STATE_IS_CHUNKED*/ | STATE_HAS_SIZE;
141
+ } else {
142
+ state = 2 /*| STATE_IS_CHUNKED*/ | STATE_HAS_SIZE;
143
+ }
144
+
145
+ return std::string_view(nullptr, 0);
146
+ }
147
+ continue;
148
+ }
149
+
150
+ // do we have data to emit all?
151
+ if (data.length() >= chunkSize(state)) {
152
+ // emit all but 2 bytes then reset state to 0 and goto beginning
153
+ // not fin
154
+ std::string_view emitSoon;
155
+ bool shouldEmit = false;
156
+ if (chunkSize(state) > 2) {
157
+ emitSoon = std::string_view(data.data(), chunkSize(state) - 2);
158
+ shouldEmit = true;
159
+ }
160
+ data.remove_prefix(chunkSize(state));
161
+ state = STATE_IS_CHUNKED;
162
+ if (shouldEmit) {
163
+ return emitSoon;
164
+ }
165
+ continue;
166
+ } else {
167
+ /* We will consume all our input data */
168
+ std::string_view emitSoon;
169
+ if (chunkSize(state) > 2) {
170
+ uint64_t maximalAppEmit = chunkSize(state) - 2;
171
+ if (data.length() > maximalAppEmit) {
172
+ emitSoon = data.substr(0, maximalAppEmit);
173
+ } else {
174
+ //cb(data);
175
+ emitSoon = data;
176
+ }
177
+ }
178
+ decChunkSize(state, (unsigned int) data.length());
179
+ state |= STATE_IS_CHUNKED;
180
+ // new: decrease data by its size (bug)
181
+ data.remove_prefix(data.length()); // ny bug fix för getNextChunk
182
+ if (emitSoon.length()) {
183
+ return emitSoon;
184
+ } else {
185
+ return std::nullopt;
186
+ }
187
+ }
188
+ }
189
+
190
+ return std::nullopt;
191
+ }
192
+
193
+ /* This is really just a wrapper for convenience */
194
+ struct ChunkIterator {
195
+
196
+ std::string_view *data;
197
+ std::optional<std::string_view> chunk;
198
+ uint64_t *state;
199
+ bool trailer;
200
+
201
+ ChunkIterator(std::string_view *data, uint64_t *state, bool trailer = false) : data(data), state(state), trailer(trailer) {
202
+ chunk = uWS::getNextChunk(*data, *state, trailer);
203
+ }
204
+
205
+ ChunkIterator() {
206
+
207
+ }
208
+
209
+ ChunkIterator begin() {
210
+ return *this;
211
+ }
212
+
213
+ ChunkIterator end() {
214
+ return ChunkIterator();
215
+ }
216
+
217
+ std::string_view operator*() {
218
+ if (!chunk.has_value()) {
219
+ std::abort();
220
+ }
221
+ return chunk.value();
222
+ }
223
+
224
+ bool operator!=(const ChunkIterator &other) const {
225
+ return other.chunk.has_value() != chunk.has_value();
226
+ }
227
+
228
+ ChunkIterator &operator++() {
229
+ chunk = uWS::getNextChunk(*data, *state, trailer);
230
+ return *this;
231
+ }
232
+
233
+ };
234
+ }
235
+
236
+ #endif // UWS_CHUNKEDENCODING_H
@@ -0,0 +1,36 @@
1
+ #include "MoveOnlyFunction.h"
2
+ #include "WebSocketContext.h"
3
+ #include <string>
4
+
5
+ namespace uWS {
6
+
7
+ struct WebSocketClientBehavior {
8
+ MoveOnlyFunction<void()> open;
9
+ MoveOnlyFunction<void()> message;
10
+ MoveOnlyFunction<void()> close;
11
+ //MoveOnlyFunction<void()> failed;
12
+
13
+ };
14
+
15
+ struct ClientApp {
16
+
17
+ WebSocketContext<0, false, int> *webSocketContext;
18
+ // behöver ett nytt http context med minimal klient, som slår om till den riktiga websocketcontext
19
+ // om samma storlek på httpsocket och websocket blir det enkel övergång
20
+
21
+ ClientApp(WebSocketClientBehavior &&behavior) {
22
+ //webSocketContext = WebSocketContext<0, false, int>::create();
23
+ }
24
+
25
+ ClientApp &&connect(std::string url, std::string protocol = "") {
26
+
27
+ return std::move(*this);
28
+ }
29
+
30
+ void run() {
31
+
32
+ }
33
+
34
+ };
35
+
36
+ }