opal-up 0.0.2 → 0.0.4

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.
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
data/ext/up_ext/bsd.h ADDED
@@ -0,0 +1,109 @@
1
+ /*
2
+ * Authored by Alex Hultman, 2018-2019.
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 BSD_H
19
+ #define BSD_H
20
+
21
+ // top-most wrapper of bsd-like syscalls
22
+
23
+ // holds everything you need from the bsd/winsock interfaces, only included by internal libusockets.h
24
+ // here everything about the syscalls are inline-wrapped and included
25
+
26
+ #include "libusockets.h"
27
+
28
+ #ifdef _WIN32
29
+ #ifndef NOMINMAX
30
+ #define NOMINMAX
31
+ #endif
32
+ #include <winsock2.h>
33
+ #include <ws2tcpip.h>
34
+ #pragma comment(lib, "ws2_32.lib")
35
+ #define SETSOCKOPT_PTR_TYPE const char *
36
+ #define LIBUS_SOCKET_ERROR INVALID_SOCKET
37
+ #else
38
+ #ifndef _GNU_SOURCE
39
+ #define _GNU_SOURCE
40
+ #endif
41
+ /* For socklen_t */
42
+ #include <sys/socket.h>
43
+ #define SETSOCKOPT_PTR_TYPE int *
44
+ #define LIBUS_SOCKET_ERROR -1
45
+ #endif
46
+
47
+ #define LIBUS_UDP_MAX_SIZE (64 * 1024)
48
+ #define LIBUS_UDP_MAX_NUM 1024
49
+
50
+ struct bsd_addr_t {
51
+ struct sockaddr_storage mem;
52
+ socklen_t len;
53
+ char *ip;
54
+ int ip_length;
55
+ int port;
56
+ };
57
+
58
+ int bsd_sendmmsg(LIBUS_SOCKET_DESCRIPTOR fd, void *msgvec, unsigned int vlen, int flags);
59
+ int bsd_recvmmsg(LIBUS_SOCKET_DESCRIPTOR fd, void *msgvec, unsigned int vlen, int flags, void *timeout);
60
+ int bsd_udp_packet_buffer_payload_length(void *msgvec, int index);
61
+ char *bsd_udp_packet_buffer_payload(void *msgvec, int index);
62
+ char *bsd_udp_packet_buffer_peer(void *msgvec, int index);
63
+ int bsd_udp_packet_buffer_local_ip(void *msgvec, int index, char *ip);
64
+ int bsd_udp_packet_buffer_ecn(void *msgvec, int index);
65
+ void *bsd_create_udp_packet_buffer();
66
+ void bsd_udp_buffer_set_packet_payload(struct us_udp_packet_buffer_t *send_buf, int index, int offset, void *payload, int length, void *peer_addr);
67
+
68
+ LIBUS_SOCKET_DESCRIPTOR apple_no_sigpipe(LIBUS_SOCKET_DESCRIPTOR fd);
69
+ LIBUS_SOCKET_DESCRIPTOR bsd_set_nonblocking(LIBUS_SOCKET_DESCRIPTOR fd);
70
+ void bsd_socket_nodelay(LIBUS_SOCKET_DESCRIPTOR fd, int enabled);
71
+ void bsd_socket_flush(LIBUS_SOCKET_DESCRIPTOR fd);
72
+ LIBUS_SOCKET_DESCRIPTOR bsd_create_socket(int domain, int type, int protocol);
73
+
74
+ void bsd_close_socket(LIBUS_SOCKET_DESCRIPTOR fd);
75
+ void bsd_shutdown_socket(LIBUS_SOCKET_DESCRIPTOR fd);
76
+ void bsd_shutdown_socket_read(LIBUS_SOCKET_DESCRIPTOR fd);
77
+
78
+ void internal_finalize_bsd_addr(struct bsd_addr_t *addr);
79
+
80
+ int bsd_local_addr(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr);
81
+ int bsd_remote_addr(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr);
82
+
83
+ char *bsd_addr_get_ip(struct bsd_addr_t *addr);
84
+ int bsd_addr_get_ip_length(struct bsd_addr_t *addr);
85
+
86
+ int bsd_addr_get_port(struct bsd_addr_t *addr);
87
+
88
+ // called by dispatch_ready_poll
89
+ LIBUS_SOCKET_DESCRIPTOR bsd_accept_socket(LIBUS_SOCKET_DESCRIPTOR fd, struct bsd_addr_t *addr);
90
+
91
+ int bsd_recv(LIBUS_SOCKET_DESCRIPTOR fd, void *buf, int length, int flags);
92
+ int bsd_send(LIBUS_SOCKET_DESCRIPTOR fd, const char *buf, int length, int msg_more);
93
+ int bsd_write2(LIBUS_SOCKET_DESCRIPTOR fd, const char *header, int header_length, const char *payload, int payload_length);
94
+ int bsd_would_block();
95
+
96
+ // return LIBUS_SOCKET_ERROR or the fd that represents listen socket
97
+ // listen both on ipv6 and ipv4
98
+ LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket(const char *host, int port, int options);
99
+
100
+ LIBUS_SOCKET_DESCRIPTOR bsd_create_listen_socket_unix(const char *path, int options);
101
+
102
+ /* Creates an UDP socket bound to the hostname and port */
103
+ LIBUS_SOCKET_DESCRIPTOR bsd_create_udp_socket(const char *host, int port);
104
+
105
+ LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(const char *host, int port, const char *source_host, int options);
106
+
107
+ LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket_unix(const char *server_path, int options);
108
+
109
+ #endif // BSD_H
@@ -0,0 +1,524 @@
1
+ /*
2
+ * Authored by Alex Hultman, 2018-2019.
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 LIBUS_USE_IO_URING
19
+
20
+ #include "libusockets.h"
21
+ #include "internal.h"
22
+ #include <stdlib.h>
23
+ #include <string.h>
24
+
25
+ int default_is_low_prio_handler(struct us_socket_t *s) {
26
+ return 0;
27
+ }
28
+
29
+ /* Shared with SSL */
30
+
31
+ unsigned short us_socket_context_timestamp(int ssl, struct us_socket_context_t *context) {
32
+ return context->timestamp;
33
+ }
34
+
35
+ void us_listen_socket_close(int ssl, struct us_listen_socket_t *ls) {
36
+ /* us_listen_socket_t extends us_socket_t so we close in similar ways */
37
+ if (!us_socket_is_closed(0, &ls->s)) {
38
+ us_internal_socket_context_unlink_listen_socket(ls->s.context, ls);
39
+ us_poll_stop((struct us_poll_t *) &ls->s, ls->s.context->loop);
40
+ bsd_close_socket(us_poll_fd((struct us_poll_t *) &ls->s));
41
+
42
+ /* Link this socket to the close-list and let it be deleted after this iteration */
43
+ ls->s.next = ls->s.context->loop->data.closed_head;
44
+ ls->s.context->loop->data.closed_head = &ls->s;
45
+
46
+ /* Any socket with prev = context is marked as closed */
47
+ ls->s.prev = (struct us_socket_t *) ls->s.context;
48
+ }
49
+
50
+ /* We cannot immediately free a listen socket as we can be inside an accept loop */
51
+ }
52
+
53
+ void us_socket_context_close(int ssl, struct us_socket_context_t *context) {
54
+ /* Begin by closing all listen sockets */
55
+ struct us_listen_socket_t *ls = context->head_listen_sockets;
56
+ while (ls) {
57
+ struct us_listen_socket_t *nextLS = (struct us_listen_socket_t *) ls->s.next;
58
+ us_listen_socket_close(ssl, ls);
59
+ ls = nextLS;
60
+ }
61
+
62
+ /* Then close all regular sockets */
63
+ struct us_socket_t *s = context->head_sockets;
64
+ while (s) {
65
+ struct us_socket_t *nextS = s->next;
66
+ us_socket_close(ssl, s, 0, 0);
67
+ s = nextS;
68
+ }
69
+ }
70
+
71
+ void us_internal_socket_context_unlink_listen_socket(struct us_socket_context_t *context, struct us_listen_socket_t *ls) {
72
+ /* We have to properly update the iterator used to sweep sockets for timeouts */
73
+ if (ls == (struct us_listen_socket_t *) context->iterator) {
74
+ context->iterator = ls->s.next;
75
+ }
76
+
77
+ if (ls->s.prev == ls->s.next) {
78
+ context->head_listen_sockets = 0;
79
+ } else {
80
+ if (ls->s.prev) {
81
+ ls->s.prev->next = ls->s.next;
82
+ } else {
83
+ context->head_listen_sockets = (struct us_listen_socket_t *) ls->s.next;
84
+ }
85
+ if (ls->s.next) {
86
+ ls->s.next->prev = ls->s.prev;
87
+ }
88
+ }
89
+ }
90
+
91
+ void us_internal_socket_context_unlink_socket(struct us_socket_context_t *context, struct us_socket_t *s) {
92
+ /* We have to properly update the iterator used to sweep sockets for timeouts */
93
+ if (s == context->iterator) {
94
+ context->iterator = s->next;
95
+ }
96
+
97
+ if (s->prev == s->next) {
98
+ context->head_sockets = 0;
99
+ } else {
100
+ if (s->prev) {
101
+ s->prev->next = s->next;
102
+ } else {
103
+ context->head_sockets = s->next;
104
+ }
105
+ if (s->next) {
106
+ s->next->prev = s->prev;
107
+ }
108
+ }
109
+ }
110
+
111
+ /* We always add in the top, so we don't modify any s.next */
112
+ void us_internal_socket_context_link_listen_socket(struct us_socket_context_t *context, struct us_listen_socket_t *ls) {
113
+ ls->s.context = context;
114
+ ls->s.next = (struct us_socket_t *) context->head_listen_sockets;
115
+ ls->s.prev = 0;
116
+ if (context->head_listen_sockets) {
117
+ context->head_listen_sockets->s.prev = &ls->s;
118
+ }
119
+ context->head_listen_sockets = ls;
120
+ }
121
+
122
+ /* We always add in the top, so we don't modify any s.next */
123
+ void us_internal_socket_context_link_socket(struct us_socket_context_t *context, struct us_socket_t *s) {
124
+ s->context = context;
125
+ s->next = context->head_sockets;
126
+ s->prev = 0;
127
+ if (context->head_sockets) {
128
+ context->head_sockets->prev = s;
129
+ }
130
+ context->head_sockets = s;
131
+ }
132
+
133
+ struct us_loop_t *us_socket_context_loop(int ssl, struct us_socket_context_t *context) {
134
+ return context->loop;
135
+ }
136
+
137
+ /* Not shared with SSL */
138
+
139
+ /* Lookup userdata by server name pattern */
140
+ void *us_socket_context_find_server_name_userdata(int ssl, struct us_socket_context_t *context, const char *hostname_pattern) {
141
+ #ifndef LIBUS_NO_SSL
142
+ if (ssl) {
143
+ return us_internal_ssl_socket_context_find_server_name_userdata((struct us_internal_ssl_socket_context_t *) context, hostname_pattern);
144
+ }
145
+ #endif
146
+ return NULL;
147
+ }
148
+
149
+ /* Get userdata attached to this SNI-routed socket, or nullptr if default */
150
+ void *us_socket_server_name_userdata(int ssl, struct us_socket_t *s) {
151
+ #ifndef LIBUS_NO_SSL
152
+ if (ssl) {
153
+ return us_internal_ssl_socket_get_sni_userdata((struct us_internal_ssl_socket_t *) s);
154
+ }
155
+ #endif
156
+ return NULL;
157
+ }
158
+
159
+ /* Add SNI context */
160
+ void us_socket_context_add_server_name(int ssl, struct us_socket_context_t *context, const char *hostname_pattern, struct us_socket_context_options_t options, void *user) {
161
+ #ifndef LIBUS_NO_SSL
162
+ if (ssl) {
163
+ us_internal_ssl_socket_context_add_server_name((struct us_internal_ssl_socket_context_t *) context, hostname_pattern, options, user);
164
+ }
165
+ #endif
166
+ }
167
+
168
+ /* Remove SNI context */
169
+ void us_socket_context_remove_server_name(int ssl, struct us_socket_context_t *context, const char *hostname_pattern) {
170
+ #ifndef LIBUS_NO_SSL
171
+ if (ssl) {
172
+ us_internal_ssl_socket_context_remove_server_name((struct us_internal_ssl_socket_context_t *) context, hostname_pattern);
173
+ }
174
+ #endif
175
+ }
176
+
177
+ /* I don't like this one - maybe rename it to on_missing_server_name? */
178
+
179
+ /* Called when SNI matching fails - not if a match could be made.
180
+ * You may modify the context by adding/removing names in this callback.
181
+ * If the correct name is added immediately in the callback, it will be used */
182
+ void us_socket_context_on_server_name(int ssl, struct us_socket_context_t *context, void (*cb)(struct us_socket_context_t *, const char *hostname)) {
183
+ #ifndef LIBUS_NO_SSL
184
+ if (ssl) {
185
+ us_internal_ssl_socket_context_on_server_name((struct us_internal_ssl_socket_context_t *) context, (void (*)(struct us_internal_ssl_socket_context_t *, const char *hostname)) cb);
186
+ }
187
+ #endif
188
+ }
189
+
190
+ /* Todo: get native context from SNI pattern */
191
+
192
+ void *us_socket_context_get_native_handle(int ssl, struct us_socket_context_t *context) {
193
+ #ifndef LIBUS_NO_SSL
194
+ if (ssl) {
195
+ return us_internal_ssl_socket_context_get_native_handle((struct us_internal_ssl_socket_context_t *) context);
196
+ }
197
+ #endif
198
+
199
+ /* There is no native handle for a non-SSL socket context */
200
+ return 0;
201
+ }
202
+
203
+ /* Options is currently only applicable for SSL - this will change with time (prefer_low_memory is one example) */
204
+ struct us_socket_context_t *us_create_socket_context(int ssl, struct us_loop_t *loop, int context_ext_size, struct us_socket_context_options_t options) {
205
+ #ifndef LIBUS_NO_SSL
206
+ if (ssl) {
207
+ /* This function will call us, again, with SSL = false and a bigger ext_size */
208
+ return (struct us_socket_context_t *) us_internal_create_ssl_socket_context(loop, context_ext_size, options);
209
+ }
210
+ #endif
211
+
212
+ /* This path is taken once either way - always BEFORE whatever SSL may do LATER.
213
+ * context_ext_size will however be modified larger in case of SSL, to hold SSL extensions */
214
+
215
+ struct us_socket_context_t *context = malloc(sizeof(struct us_socket_context_t) + context_ext_size);
216
+ context->loop = loop;
217
+ context->head_sockets = 0;
218
+ context->head_listen_sockets = 0;
219
+ context->iterator = 0;
220
+ context->next = 0;
221
+ context->is_low_prio = default_is_low_prio_handler;
222
+
223
+ /* Begin at 0 */
224
+ context->timestamp = 0;
225
+ context->long_timestamp = 0;
226
+ context->global_tick = 0;
227
+
228
+ /* Some new events must be set to null for backwards compatibility */
229
+ context->on_pre_open = 0;
230
+
231
+ us_internal_loop_link(loop, context);
232
+
233
+ /* If we are called from within SSL code, SSL code will make further changes to us */
234
+ return context;
235
+ }
236
+
237
+ void us_socket_context_free(int ssl, struct us_socket_context_t *context) {
238
+ #ifndef LIBUS_NO_SSL
239
+ if (ssl) {
240
+ /* This function will call us again with SSL=false */
241
+ us_internal_ssl_socket_context_free((struct us_internal_ssl_socket_context_t *) context);
242
+ return;
243
+ }
244
+ #endif
245
+
246
+ /* This path is taken once either way - always AFTER whatever SSL may do BEFORE.
247
+ * This is the opposite order compared to when creating the context - SSL code is cleaning up before non-SSL */
248
+
249
+ us_internal_loop_unlink(context->loop, context);
250
+ free(context);
251
+ }
252
+
253
+ struct us_listen_socket_t *us_socket_context_listen(int ssl, struct us_socket_context_t *context, const char *host, int port, int options, int socket_ext_size) {
254
+ #ifndef LIBUS_NO_SSL
255
+ if (ssl) {
256
+ return us_internal_ssl_socket_context_listen((struct us_internal_ssl_socket_context_t *) context, host, port, options, socket_ext_size);
257
+ }
258
+ #endif
259
+
260
+ LIBUS_SOCKET_DESCRIPTOR listen_socket_fd = bsd_create_listen_socket(host, port, options);
261
+
262
+ if (listen_socket_fd == LIBUS_SOCKET_ERROR) {
263
+ return 0;
264
+ }
265
+
266
+ struct us_poll_t *p = us_create_poll(context->loop, 0, sizeof(struct us_listen_socket_t));
267
+ us_poll_init(p, listen_socket_fd, POLL_TYPE_SEMI_SOCKET);
268
+ us_poll_start(p, context->loop, LIBUS_SOCKET_READABLE);
269
+
270
+ struct us_listen_socket_t *ls = (struct us_listen_socket_t *) p;
271
+
272
+ ls->s.context = context;
273
+ ls->s.timeout = 255;
274
+ ls->s.long_timeout = 255;
275
+ ls->s.low_prio_state = 0;
276
+ ls->s.next = 0;
277
+ us_internal_socket_context_link_listen_socket(context, ls);
278
+
279
+ ls->socket_ext_size = socket_ext_size;
280
+
281
+ return ls;
282
+ }
283
+
284
+ struct us_listen_socket_t *us_socket_context_listen_unix(int ssl, struct us_socket_context_t *context, const char *path, int options, int socket_ext_size) {
285
+ #ifndef LIBUS_NO_SSL
286
+ if (ssl) {
287
+ return us_internal_ssl_socket_context_listen_unix((struct us_internal_ssl_socket_context_t *) context, path, options, socket_ext_size);
288
+ }
289
+ #endif
290
+
291
+ LIBUS_SOCKET_DESCRIPTOR listen_socket_fd = bsd_create_listen_socket_unix(path, options);
292
+
293
+ if (listen_socket_fd == LIBUS_SOCKET_ERROR) {
294
+ return 0;
295
+ }
296
+
297
+ struct us_poll_t *p = us_create_poll(context->loop, 0, sizeof(struct us_listen_socket_t));
298
+ us_poll_init(p, listen_socket_fd, POLL_TYPE_SEMI_SOCKET);
299
+ us_poll_start(p, context->loop, LIBUS_SOCKET_READABLE);
300
+
301
+ struct us_listen_socket_t *ls = (struct us_listen_socket_t *) p;
302
+
303
+ ls->s.context = context;
304
+ ls->s.timeout = 255;
305
+ ls->s.long_timeout = 255;
306
+ ls->s.low_prio_state = 0;
307
+ ls->s.next = 0;
308
+ us_internal_socket_context_link_listen_socket(context, ls);
309
+
310
+ ls->socket_ext_size = socket_ext_size;
311
+
312
+ return ls;
313
+ }
314
+
315
+ struct us_socket_t *us_socket_context_connect(int ssl, struct us_socket_context_t *context, const char *host, int port, const char *source_host, int options, int socket_ext_size) {
316
+ #ifndef LIBUS_NO_SSL
317
+ if (ssl) {
318
+ return (struct us_socket_t *) us_internal_ssl_socket_context_connect((struct us_internal_ssl_socket_context_t *) context, host, port, source_host, options, socket_ext_size);
319
+ }
320
+ #endif
321
+
322
+ LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket(host, port, source_host, options);
323
+ if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
324
+ return 0;
325
+ }
326
+
327
+ /* Connect sockets are semi-sockets just like listen sockets */
328
+ struct us_poll_t *p = us_create_poll(context->loop, 0, sizeof(struct us_socket_t) + socket_ext_size);
329
+ us_poll_init(p, connect_socket_fd, POLL_TYPE_SEMI_SOCKET);
330
+ us_poll_start(p, context->loop, LIBUS_SOCKET_WRITABLE);
331
+
332
+ struct us_socket_t *connect_socket = (struct us_socket_t *) p;
333
+
334
+ /* Link it into context so that timeout fires properly */
335
+ connect_socket->context = context;
336
+ connect_socket->timeout = 255;
337
+ connect_socket->long_timeout = 255;
338
+ connect_socket->low_prio_state = 0;
339
+ us_internal_socket_context_link_socket(context, connect_socket);
340
+
341
+ return connect_socket;
342
+ }
343
+
344
+ struct us_socket_t *us_socket_context_connect_unix(int ssl, struct us_socket_context_t *context, const char *server_path, int options, int socket_ext_size) {
345
+ #ifndef LIBUS_NO_SSL
346
+ if (ssl) {
347
+ return (struct us_socket_t *) us_internal_ssl_socket_context_connect_unix((struct us_internal_ssl_socket_context_t *) context, server_path, options, socket_ext_size);
348
+ }
349
+ #endif
350
+
351
+ LIBUS_SOCKET_DESCRIPTOR connect_socket_fd = bsd_create_connect_socket_unix(server_path, options);
352
+ if (connect_socket_fd == LIBUS_SOCKET_ERROR) {
353
+ return 0;
354
+ }
355
+
356
+ /* Connect sockets are semi-sockets just like listen sockets */
357
+ struct us_poll_t *p = us_create_poll(context->loop, 0, sizeof(struct us_socket_t) + socket_ext_size);
358
+ us_poll_init(p, connect_socket_fd, POLL_TYPE_SEMI_SOCKET);
359
+ us_poll_start(p, context->loop, LIBUS_SOCKET_WRITABLE);
360
+
361
+ struct us_socket_t *connect_socket = (struct us_socket_t *) p;
362
+
363
+ /* Link it into context so that timeout fires properly */
364
+ connect_socket->context = context;
365
+ connect_socket->timeout = 255;
366
+ connect_socket->long_timeout = 255;
367
+ connect_socket->low_prio_state = 0;
368
+ us_internal_socket_context_link_socket(context, connect_socket);
369
+
370
+ return connect_socket;
371
+ }
372
+
373
+ struct us_socket_context_t *us_create_child_socket_context(int ssl, struct us_socket_context_t *context, int context_ext_size) {
374
+ #ifndef LIBUS_NO_SSL
375
+ if (ssl) {
376
+ return (struct us_socket_context_t *) us_internal_create_child_ssl_socket_context((struct us_internal_ssl_socket_context_t *) context, context_ext_size);
377
+ }
378
+ #endif
379
+
380
+ /* For TCP we simply create a new context as nothing is shared */
381
+ struct us_socket_context_options_t options = {0};
382
+ return us_create_socket_context(ssl, context->loop, context_ext_size, options);
383
+ }
384
+
385
+ /* Note: This will set timeout to 0 */
386
+ struct us_socket_t *us_socket_context_adopt_socket(int ssl, struct us_socket_context_t *context, struct us_socket_t *s, int ext_size) {
387
+ #ifndef LIBUS_NO_SSL
388
+ if (ssl) {
389
+ return (struct us_socket_t *) us_internal_ssl_socket_context_adopt_socket((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t *) s, ext_size);
390
+ }
391
+ #endif
392
+
393
+ /* Cannot adopt a closed socket */
394
+ if (us_socket_is_closed(ssl, s)) {
395
+ return s;
396
+ }
397
+
398
+ if (s->low_prio_state != 1) {
399
+ /* This properly updates the iterator if in on_timeout */
400
+ us_internal_socket_context_unlink_socket(s->context, s);
401
+ }
402
+
403
+ struct us_socket_t *new_s = (struct us_socket_t *) us_poll_resize(&s->p, s->context->loop, sizeof(struct us_socket_t) + ext_size);
404
+ new_s->timeout = 255;
405
+ new_s->long_timeout = 255;
406
+
407
+ if (new_s->low_prio_state == 1) {
408
+ /* update pointers in low-priority queue */
409
+ if (!new_s->prev) new_s->context->loop->data.low_prio_head = new_s;
410
+ else new_s->prev->next = new_s;
411
+
412
+ if (new_s->next) new_s->next->prev = new_s;
413
+ } else {
414
+ us_internal_socket_context_link_socket(context, new_s);
415
+ }
416
+
417
+ return new_s;
418
+ }
419
+
420
+ /* For backwards compatibility, this function will be set to nullptr by default. */
421
+ void us_socket_context_on_pre_open(int ssl, struct us_socket_context_t *context, LIBUS_SOCKET_DESCRIPTOR (*on_pre_open)(LIBUS_SOCKET_DESCRIPTOR fd)) {
422
+ /* For this event, there is no difference between SSL and non-SSL */
423
+ context->on_pre_open = on_pre_open;
424
+ }
425
+
426
+ void us_socket_context_on_open(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_open)(struct us_socket_t *s, int is_client, char *ip, int ip_length)) {
427
+ #ifndef LIBUS_NO_SSL
428
+ if (ssl) {
429
+ us_internal_ssl_socket_context_on_open((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, int, char *, int)) on_open);
430
+ return;
431
+ }
432
+ #endif
433
+
434
+ context->on_open = on_open;
435
+ }
436
+
437
+ void us_socket_context_on_close(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_close)(struct us_socket_t *s, int code, void *reason)) {
438
+ #ifndef LIBUS_NO_SSL
439
+ if (ssl) {
440
+ us_internal_ssl_socket_context_on_close((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, int code, void *reason)) on_close);
441
+ return;
442
+ }
443
+ #endif
444
+
445
+ context->on_close = on_close;
446
+ }
447
+
448
+ void us_socket_context_on_data(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_data)(struct us_socket_t *s, char *data, int length)) {
449
+ #ifndef LIBUS_NO_SSL
450
+ if (ssl) {
451
+ us_internal_ssl_socket_context_on_data((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, char *, int)) on_data);
452
+ return;
453
+ }
454
+ #endif
455
+
456
+ context->on_data = on_data;
457
+ }
458
+
459
+ void us_socket_context_on_writable(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_writable)(struct us_socket_t *s)) {
460
+ #ifndef LIBUS_NO_SSL
461
+ if (ssl) {
462
+ us_internal_ssl_socket_context_on_writable((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_writable);
463
+ return;
464
+ }
465
+ #endif
466
+
467
+ context->on_writable = on_writable;
468
+ }
469
+
470
+ void us_socket_context_on_long_timeout(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_long_timeout)(struct us_socket_t *)) {
471
+ #ifndef LIBUS_NO_SSL
472
+ if (ssl) {
473
+ us_internal_ssl_socket_context_on_long_timeout((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_long_timeout);
474
+ return;
475
+ }
476
+ #endif
477
+
478
+ context->on_socket_long_timeout = on_long_timeout;
479
+ }
480
+
481
+ void us_socket_context_on_timeout(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_timeout)(struct us_socket_t *)) {
482
+ #ifndef LIBUS_NO_SSL
483
+ if (ssl) {
484
+ us_internal_ssl_socket_context_on_timeout((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_timeout);
485
+ return;
486
+ }
487
+ #endif
488
+
489
+ context->on_socket_timeout = on_timeout;
490
+ }
491
+
492
+ void us_socket_context_on_end(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_end)(struct us_socket_t *)) {
493
+ #ifndef LIBUS_NO_SSL
494
+ if (ssl) {
495
+ us_internal_ssl_socket_context_on_end((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *)) on_end);
496
+ return;
497
+ }
498
+ #endif
499
+
500
+ context->on_end = on_end;
501
+ }
502
+
503
+ void us_socket_context_on_connect_error(int ssl, struct us_socket_context_t *context, struct us_socket_t *(*on_connect_error)(struct us_socket_t *s, int code)) {
504
+ #ifndef LIBUS_NO_SSL
505
+ if (ssl) {
506
+ us_internal_ssl_socket_context_on_connect_error((struct us_internal_ssl_socket_context_t *) context, (struct us_internal_ssl_socket_t * (*)(struct us_internal_ssl_socket_t *, int)) on_connect_error);
507
+ return;
508
+ }
509
+ #endif
510
+
511
+ context->on_connect_error = on_connect_error;
512
+ }
513
+
514
+ void *us_socket_context_ext(int ssl, struct us_socket_context_t *context) {
515
+ #ifndef LIBUS_NO_SSL
516
+ if (ssl) {
517
+ return us_internal_ssl_socket_context_ext((struct us_internal_ssl_socket_context_t *) context);
518
+ }
519
+ #endif
520
+
521
+ return context + 1;
522
+ }
523
+
524
+ #endif