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
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