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.
- checksums.yaml +4 -4
- data/LICENSE +209 -0
- data/README.md +97 -29
- data/bin/up_ruby +4 -0
- data/bin/up_ruby_cluster +4 -0
- data/ext/up_ext/App.h +606 -0
- data/ext/up_ext/AsyncSocket.h +355 -0
- data/ext/up_ext/AsyncSocketData.h +87 -0
- data/ext/up_ext/BloomFilter.h +83 -0
- data/ext/up_ext/ChunkedEncoding.h +236 -0
- data/ext/up_ext/ClientApp.h +36 -0
- data/ext/up_ext/HttpContext.h +502 -0
- data/ext/up_ext/HttpContextData.h +56 -0
- data/ext/up_ext/HttpErrors.h +53 -0
- data/ext/up_ext/HttpParser.h +680 -0
- data/ext/up_ext/HttpResponse.h +578 -0
- data/ext/up_ext/HttpResponseData.h +95 -0
- data/ext/up_ext/HttpRouter.h +380 -0
- data/ext/up_ext/Loop.h +204 -0
- data/ext/up_ext/LoopData.h +112 -0
- data/ext/up_ext/MoveOnlyFunction.h +377 -0
- data/ext/up_ext/PerMessageDeflate.h +315 -0
- data/ext/up_ext/ProxyParser.h +163 -0
- data/ext/up_ext/QueryParser.h +120 -0
- data/ext/up_ext/TopicTree.h +363 -0
- data/ext/up_ext/Utilities.h +66 -0
- data/ext/up_ext/WebSocket.h +381 -0
- data/ext/up_ext/WebSocketContext.h +434 -0
- data/ext/up_ext/WebSocketContextData.h +109 -0
- data/ext/up_ext/WebSocketData.h +86 -0
- data/ext/up_ext/WebSocketExtensions.h +256 -0
- data/ext/up_ext/WebSocketHandshake.h +145 -0
- data/ext/up_ext/WebSocketProtocol.h +506 -0
- data/ext/up_ext/bsd.c +767 -0
- data/ext/up_ext/bsd.h +109 -0
- data/ext/up_ext/context.c +524 -0
- data/ext/up_ext/epoll_kqueue.c +458 -0
- data/ext/up_ext/epoll_kqueue.h +67 -0
- data/ext/up_ext/extconf.rb +5 -0
- data/ext/up_ext/internal.h +224 -0
- data/ext/up_ext/libusockets.h +350 -0
- data/ext/up_ext/libuwebsockets.cpp +1344 -0
- data/ext/up_ext/libuwebsockets.h +396 -0
- data/ext/up_ext/loop.c +386 -0
- data/ext/up_ext/loop_data.h +38 -0
- data/ext/up_ext/socket.c +231 -0
- data/ext/up_ext/up_ext.c +930 -0
- data/lib/up/bun/rack_env.rb +1 -13
- data/lib/up/bun/server.rb +93 -19
- data/lib/up/cli.rb +3 -0
- data/lib/up/client.rb +68 -0
- data/lib/up/ruby/cluster.rb +39 -0
- data/lib/up/ruby/cluster_cli.rb +10 -0
- data/lib/up/{node → ruby}/rack_cluster.rb +5 -4
- data/lib/up/{node → ruby}/rack_server.rb +4 -4
- data/lib/up/ruby/server_cli.rb +10 -0
- data/lib/up/u_web_socket/cluster.rb +18 -3
- data/lib/up/u_web_socket/server.rb +108 -15
- data/lib/up/version.rb +1 -1
- metadata +72 -30
- data/.gitignore +0 -5
- data/Gemfile +0 -2
- data/bin/up_node +0 -12
- data/bin/up_node_cluster +0 -12
- data/example_rack_app/Gemfile +0 -3
- data/example_rack_app/config.ru +0 -6
- data/example_rack_app/rack_app.rb +0 -5
- data/example_roda_app/Gemfile +0 -6
- data/example_roda_app/config.ru +0 -6
- data/example_roda_app/roda_app.rb +0 -37
- data/example_sinatra_app/Gemfile +0 -6
- data/example_sinatra_app/config.ru +0 -6
- data/example_sinatra_app/sinatra_app.rb +0 -7
- data/lib/up/node/cluster.rb +0 -39
- data/lib/up/node/cluster_cli.rb +0 -15
- data/lib/up/node/rack_env.rb +0 -106
- data/lib/up/node/server.rb +0 -84
- data/lib/up/node/server_cli.rb +0 -15
- data/lib/up/u_web_socket/rack_env.rb +0 -101
- data/opal-up.gemspec +0 -27
- 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
|