iodine 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +63 -100
- data/bin/raw-rbhttp +12 -7
- data/examples/config.ru +8 -7
- data/examples/echo.ru +8 -7
- data/examples/info.md +41 -35
- data/examples/pubsub_engine.ru +12 -12
- data/examples/redis.ru +10 -12
- data/examples/shootout.ru +19 -42
- data/exe/iodine +116 -1
- data/ext/iodine/defer.c +1 -1
- data/ext/iodine/facil.c +12 -8
- data/ext/iodine/facil.h +2 -2
- data/ext/iodine/iodine.c +177 -343
- data/ext/iodine/iodine.h +18 -72
- data/ext/iodine/iodine_caller.c +132 -0
- data/ext/iodine/iodine_caller.h +21 -0
- data/ext/iodine/iodine_connection.c +841 -0
- data/ext/iodine/iodine_connection.h +55 -0
- data/ext/iodine/iodine_defer.c +391 -0
- data/ext/iodine/iodine_defer.h +7 -0
- data/ext/iodine/{rb-fiobj2rb.h → iodine_fiobj2rb.h} +6 -6
- data/ext/iodine/iodine_helpers.c +51 -5
- data/ext/iodine/iodine_helpers.h +2 -3
- data/ext/iodine/iodine_http.c +284 -141
- data/ext/iodine/iodine_http.h +2 -2
- data/ext/iodine/iodine_json.c +13 -13
- data/ext/iodine/iodine_json.h +1 -1
- data/ext/iodine/iodine_pubsub.c +573 -823
- data/ext/iodine/iodine_pubsub.h +15 -27
- data/ext/iodine/{rb-rack-io.c → iodine_rack_io.c} +30 -8
- data/ext/iodine/{rb-rack-io.h → iodine_rack_io.h} +1 -0
- data/ext/iodine/iodine_store.c +136 -0
- data/ext/iodine/iodine_store.h +20 -0
- data/ext/iodine/iodine_tcp.c +385 -0
- data/ext/iodine/iodine_tcp.h +9 -0
- data/lib/iodine.rb +73 -171
- data/lib/iodine/connection.rb +34 -0
- data/lib/iodine/pubsub.rb +5 -18
- data/lib/iodine/rack_utils.rb +43 -0
- data/lib/iodine/version.rb +1 -1
- data/lib/rack/handler/iodine.rb +1 -182
- metadata +17 -18
- data/ext/iodine/iodine_protocol.c +0 -689
- data/ext/iodine/iodine_protocol.h +0 -13
- data/ext/iodine/iodine_websockets.c +0 -550
- data/ext/iodine/iodine_websockets.h +0 -17
- data/ext/iodine/rb-call.c +0 -156
- data/ext/iodine/rb-call.h +0 -70
- data/ext/iodine/rb-defer.c +0 -124
- data/ext/iodine/rb-registry.c +0 -150
- data/ext/iodine/rb-registry.h +0 -34
- data/lib/iodine/cli.rb +0 -89
- data/lib/iodine/monkeypatch.rb +0 -46
- data/lib/iodine/protocol.rb +0 -42
- data/lib/iodine/websocket.rb +0 -16
@@ -9,7 +9,7 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
9
9
|
#include <fiobj.h>
|
10
10
|
#include <ruby.h>
|
11
11
|
|
12
|
-
#include "
|
12
|
+
#include "iodine_store.h"
|
13
13
|
|
14
14
|
typedef struct {
|
15
15
|
FIOBJ stack;
|
@@ -35,7 +35,7 @@ static inline VALUE fiobj2rb(FIOBJ o, uint8_t str2sym) {
|
|
35
35
|
rb = Qfalse;
|
36
36
|
break;
|
37
37
|
case FIOBJ_T_FLOAT:
|
38
|
-
rb =
|
38
|
+
rb = rb_float_new(fiobj_obj2float(o));
|
39
39
|
break;
|
40
40
|
case FIOBJ_T_DATA: /* fallthrough */
|
41
41
|
case FIOBJ_T_UNKNOWN: /* fallthrough */
|
@@ -67,7 +67,7 @@ static int fiobj2rb_task(FIOBJ o, void *data_) {
|
|
67
67
|
fiobj2rb_s *data = data_;
|
68
68
|
VALUE rb_tmp;
|
69
69
|
rb_tmp = fiobj2rb(o, 0);
|
70
|
-
|
70
|
+
IodineStore.add(rb_tmp);
|
71
71
|
if (data->rb) {
|
72
72
|
if (RB_TYPE_P(data->rb, T_HASH)) {
|
73
73
|
rb_hash_aset(data->rb, fiobj2rb(fiobj_hash_key_in_loop(), data->str2sym),
|
@@ -76,10 +76,10 @@ static int fiobj2rb_task(FIOBJ o, void *data_) {
|
|
76
76
|
rb_ary_push(data->rb, rb_tmp);
|
77
77
|
}
|
78
78
|
--(data->count);
|
79
|
-
|
79
|
+
IodineStore.remove(rb_tmp);
|
80
80
|
} else {
|
81
81
|
data->rb = rb_tmp;
|
82
|
-
//
|
82
|
+
// IodineStore.add(rb_tmp);
|
83
83
|
}
|
84
84
|
if (FIOBJ_TYPE_IS(o, FIOBJ_T_ARRAY)) {
|
85
85
|
fiobj_ary_push(data->stack, (FIOBJ)data->count);
|
@@ -108,7 +108,7 @@ static inline VALUE fiobj2rb_deep(FIOBJ obj, uint8_t str2sym) {
|
|
108
108
|
while (fiobj_ary_pop(data.stack))
|
109
109
|
;
|
110
110
|
fiobj_free(data.stack);
|
111
|
-
|
111
|
+
IodineStore.remove(data.rb);
|
112
112
|
return data.rb;
|
113
113
|
}
|
114
114
|
|
data/ext/iodine/iodine_helpers.c
CHANGED
@@ -4,18 +4,21 @@ License: MIT
|
|
4
4
|
|
5
5
|
Feel free to copy, use and enjoy according to the license provided.
|
6
6
|
*/
|
7
|
-
#include "
|
7
|
+
#include "iodine.h"
|
8
8
|
|
9
9
|
#include "http.h"
|
10
|
+
#include <ruby/encoding.h>
|
10
11
|
|
11
12
|
/*
|
12
13
|
Add all sorts of useless stuff here.
|
13
14
|
*/
|
14
15
|
|
16
|
+
static ID iodine_to_i_func_id;
|
17
|
+
static rb_encoding *IodineUTF8Encoding;
|
18
|
+
|
15
19
|
/* *****************************************************************************
|
16
20
|
URL Decoding
|
17
21
|
***************************************************************************** */
|
18
|
-
|
19
22
|
/**
|
20
23
|
Decodes a URL encoded String in place.
|
21
24
|
|
@@ -210,9 +213,47 @@ static VALUE iodine_rfc2109(VALUE self, VALUE rtm) {
|
|
210
213
|
Ruby Initialization
|
211
214
|
***************************************************************************** */
|
212
215
|
|
213
|
-
void
|
214
|
-
|
216
|
+
void iodine_init_helpers(void) {
|
217
|
+
iodine_to_i_func_id = rb_intern("to_i");
|
218
|
+
IodineUTF8Encoding = rb_enc_find("UTF-8");
|
219
|
+
VALUE tmp = rb_define_module_under(IodineModule, "Rack");
|
220
|
+
// clang-format off
|
221
|
+
/*
|
222
|
+
Iodine does NOT monkey patch Rack automatically. However, it's possible and recommended to moneky patch Rack::Utils to use the methods in this module.
|
223
|
+
|
224
|
+
Choosing to monkey patch Rack::Utils could offer significant performance gains for some applications. i.e. (on my machine):
|
225
|
+
|
226
|
+
require 'iodine'
|
227
|
+
require 'rack'
|
228
|
+
# a String in need of decoding
|
229
|
+
s = '%E3%83%AB%E3%83%93%E3%82%A4%E3%82%B9%E3%81%A8'
|
230
|
+
Benchmark.bm do |bm|
|
231
|
+
# Pre-Patch
|
232
|
+
bm.report(" Rack.unescape") {1_000_000.times { Rack::Utils.unescape s } }
|
233
|
+
bm.report(" Rack.rfc2822") {1_000_000.times { Rack::Utils.rfc2822(Time.now) } }
|
234
|
+
bm.report(" Rack.rfc2109") {1_000_000.times { Rack::Utils.rfc2109(Time.now) } }
|
235
|
+
# Perform Patch
|
236
|
+
Iodine.patch_rack
|
237
|
+
puts " --- Monkey Patching Rack ---"
|
238
|
+
# Post Patch
|
239
|
+
bm.report("Patched.unescape") {1_000_000.times { Rack::Utils.unescape s } }
|
240
|
+
bm.report(" Patched.rfc2822") {1_000_000.times { Rack::Utils.rfc2822(Time.now) } }
|
241
|
+
bm.report(" Patched.rfc2109") {1_000_000.times { Rack::Utils.rfc2109(Time.now) } }
|
242
|
+
end && nil
|
243
|
+
|
244
|
+
Results:
|
245
|
+
user system total real
|
246
|
+
Rack.unescape 8.706881 0.019995 8.726876 ( 8.740530)
|
247
|
+
Rack.rfc2822 3.270305 0.007519 3.277824 ( 3.279416)
|
248
|
+
Rack.rfc2109 3.152188 0.003852 3.156040 ( 3.157975)
|
249
|
+
--- Monkey Patching Rack ---
|
250
|
+
Patched.unescape 0.327231 0.003125 0.330356 ( 0.337090)
|
251
|
+
Patched.rfc2822 0.691304 0.003330 0.694634 ( 0.701172)
|
252
|
+
Patched.rfc2109 0.685029 0.001956 0.686985 ( 0.687607)
|
253
|
+
|
254
|
+
*/
|
215
255
|
tmp = rb_define_module_under(tmp, "Utils");
|
256
|
+
// clang-format on
|
216
257
|
rb_define_module_function(tmp, "decode_url!", url_decode_inplace, 1);
|
217
258
|
rb_define_module_function(tmp, "decode_url", url_decode, 1);
|
218
259
|
rb_define_module_function(tmp, "decode_path!", path_decode_inplace, 1);
|
@@ -221,8 +262,13 @@ void Iodine_init_helpers(void) {
|
|
221
262
|
rb_define_module_function(tmp, "rfc2109", iodine_rfc2109, 1);
|
222
263
|
rb_define_module_function(tmp, "rfc2822", iodine_rfc2822, 1);
|
223
264
|
|
224
|
-
|
265
|
+
/*
|
266
|
+
The monkey-patched methods are in this module, allowing Iodine::Rack::Utils to
|
267
|
+
include non-patched methods as well.
|
268
|
+
*/
|
269
|
+
tmp = rb_define_module_under(IodineBaseModule, "MonkeyPatch");
|
225
270
|
tmp = rb_define_module_under(tmp, "RackUtils");
|
271
|
+
// clang-format on
|
226
272
|
/* we define it all twice for easier monkey patching */
|
227
273
|
rb_define_method(tmp, "unescape", unescape, -1);
|
228
274
|
rb_define_method(tmp, "unescape_path", path_decode, 1);
|
data/ext/iodine/iodine_helpers.h
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
#ifndef H_IODINE_HELPERS_H
|
2
2
|
#define H_IODINE_HELPERS_H
|
3
3
|
/*
|
4
|
-
Copyright: Boaz segev, 2016-
|
4
|
+
Copyright: Boaz segev, 2016-2018
|
5
5
|
License: MIT
|
6
6
|
|
7
7
|
Feel free to copy, use and enjoy according to the license provided.
|
8
8
|
*/
|
9
|
-
#include "iodine.h"
|
10
9
|
|
11
|
-
void
|
10
|
+
void iodine_init_helpers(void);
|
12
11
|
|
13
12
|
#endif
|
data/ext/iodine/iodine_http.c
CHANGED
@@ -4,12 +4,14 @@ License: MIT
|
|
4
4
|
|
5
5
|
Feel free to copy, use and enjoy according to the license provided.
|
6
6
|
*/
|
7
|
-
#include "
|
7
|
+
#include "iodine.h"
|
8
|
+
|
9
|
+
#include "evio.h"
|
8
10
|
#include "fio_mem.h"
|
9
11
|
#include "http.h"
|
10
|
-
#include
|
11
|
-
#include
|
12
|
-
#include "
|
12
|
+
#include <ruby/encoding.h>
|
13
|
+
#include <ruby/io.h>
|
14
|
+
// #include "iodine_websockets.h"
|
13
15
|
|
14
16
|
#include <arpa/inet.h>
|
15
17
|
#include <ctype.h>
|
@@ -26,31 +28,36 @@ typedef struct {
|
|
26
28
|
VALUE env;
|
27
29
|
} iodine_http_settings_s;
|
28
30
|
|
29
|
-
/* these three are used also by
|
31
|
+
/* these three are used also by iodin_rack_io.c */
|
30
32
|
VALUE IODINE_R_HIJACK;
|
31
33
|
VALUE IODINE_R_HIJACK_IO;
|
32
34
|
VALUE IODINE_R_HIJACK_CB;
|
33
35
|
|
34
|
-
static VALUE UPGRADE_TCP;
|
35
|
-
static VALUE UPGRADE_TCP_Q;
|
36
|
-
static VALUE UPGRADE_WEBSOCKET;
|
37
|
-
static VALUE UPGRADE_WEBSOCKET_Q;
|
38
36
|
static VALUE RACK_UPGRADE;
|
39
37
|
static VALUE RACK_UPGRADE_Q;
|
40
38
|
static VALUE RACK_UPGRADE_SSE;
|
41
39
|
static VALUE RACK_UPGRADE_WEBSOCKET;
|
40
|
+
static VALUE UPGRADE_TCP;
|
42
41
|
|
43
42
|
static VALUE hijack_func_sym;
|
44
43
|
static ID close_method_id;
|
45
44
|
static ID each_method_id;
|
46
45
|
static ID attach_method_id;
|
46
|
+
static ID iodine_to_s_method_id;
|
47
|
+
static ID iodine_call_proc_id;
|
47
48
|
|
48
49
|
static VALUE env_template_no_upgrade;
|
49
50
|
static VALUE env_template_websockets;
|
50
51
|
static VALUE env_template_sse;
|
51
52
|
|
53
|
+
static rb_encoding *IodineUTF8Encoding;
|
54
|
+
static rb_encoding *IodineBinaryEncoding;
|
55
|
+
|
52
56
|
static uint8_t support_xsendfile = 0;
|
53
57
|
|
58
|
+
/** Used by {listen2http} to set missing arguments. */
|
59
|
+
static VALUE iodine_default_args;
|
60
|
+
|
54
61
|
#define rack_declare(rack_name) static VALUE rack_name
|
55
62
|
|
56
63
|
#define rack_set(rack_name, str) \
|
@@ -104,6 +111,136 @@ typedef struct {
|
|
104
111
|
} upgrade;
|
105
112
|
} iodine_http_request_handle_s;
|
106
113
|
|
114
|
+
/* *****************************************************************************
|
115
|
+
WebSocket support
|
116
|
+
***************************************************************************** */
|
117
|
+
|
118
|
+
typedef struct {
|
119
|
+
char *data;
|
120
|
+
size_t size;
|
121
|
+
uint8_t is_text;
|
122
|
+
VALUE io;
|
123
|
+
} iodine_msg2ruby_s;
|
124
|
+
|
125
|
+
static void *iodine_ws_fire_message(void *msg_) {
|
126
|
+
iodine_msg2ruby_s *msg = msg_;
|
127
|
+
VALUE data = rb_enc_str_new(
|
128
|
+
msg->data, msg->size,
|
129
|
+
(msg->is_text ? rb_utf8_encoding() : rb_ascii8bit_encoding()));
|
130
|
+
iodine_connection_fire_event(msg->io, IODINE_CONNECTION_ON_MESSAGE, data);
|
131
|
+
return NULL;
|
132
|
+
}
|
133
|
+
|
134
|
+
static void iodine_ws_on_message(ws_s *ws, char *data, size_t size,
|
135
|
+
uint8_t is_text) {
|
136
|
+
iodine_msg2ruby_s msg = {
|
137
|
+
.data = data,
|
138
|
+
.size = size,
|
139
|
+
.is_text = is_text,
|
140
|
+
.io = (VALUE)websocket_udata(ws),
|
141
|
+
};
|
142
|
+
IodineCaller.leaveGVL(iodine_ws_fire_message, &msg);
|
143
|
+
}
|
144
|
+
/**
|
145
|
+
* The (optional) on_open callback will be called once the websocket
|
146
|
+
* connection is established and before is is registered with `facil`, so no
|
147
|
+
* `on_message` events are raised before `on_open` returns.
|
148
|
+
*/
|
149
|
+
static void iodine_ws_on_open(ws_s *ws) {
|
150
|
+
VALUE h = (VALUE)websocket_udata(ws);
|
151
|
+
iodine_connection_s *c = iodine_connection_CData(h);
|
152
|
+
c->arg = ws;
|
153
|
+
c->uuid = websocket_uuid(ws);
|
154
|
+
iodine_connection_fire_event(h, IODINE_CONNECTION_ON_OPEN, Qnil);
|
155
|
+
}
|
156
|
+
/**
|
157
|
+
* The (optional) on_ready callback will be after a the underlying socket's
|
158
|
+
* buffer changes it's state from full to empty.
|
159
|
+
*
|
160
|
+
* If the socket's buffer is never used, the callback is never called.
|
161
|
+
*/
|
162
|
+
static void iodine_ws_on_ready(ws_s *ws) {
|
163
|
+
iodine_connection_fire_event((VALUE)websocket_udata(ws),
|
164
|
+
IODINE_CONNECTION_ON_DRAINED, Qnil);
|
165
|
+
}
|
166
|
+
/**
|
167
|
+
* The (optional) on_shutdown callback will be called if a websocket
|
168
|
+
* connection is still open while the server is shutting down (called before
|
169
|
+
* `on_close`).
|
170
|
+
*/
|
171
|
+
static void iodine_ws_on_shutdown(ws_s *ws) {
|
172
|
+
iodine_connection_fire_event((VALUE)websocket_udata(ws),
|
173
|
+
IODINE_CONNECTION_ON_SHUTDOWN, Qnil);
|
174
|
+
}
|
175
|
+
/**
|
176
|
+
* The (optional) on_close callback will be called once a websocket connection
|
177
|
+
* is terminated or failed to be established.
|
178
|
+
*
|
179
|
+
* The `uuid` is the connection's unique ID that can identify the Websocket. A
|
180
|
+
* value of `uuid == 0` indicates the Websocket connection wasn't established
|
181
|
+
* (an error occured).
|
182
|
+
*
|
183
|
+
* The `udata` is the user data as set during the upgrade or using the
|
184
|
+
* `websocket_udata_set` function.
|
185
|
+
*/
|
186
|
+
static void iodine_ws_on_close(intptr_t uuid, void *udata) {
|
187
|
+
iodine_connection_fire_event((VALUE)udata, IODINE_CONNECTION_ON_CLOSE, Qnil);
|
188
|
+
(void)uuid;
|
189
|
+
}
|
190
|
+
|
191
|
+
static void iodine_ws_attach(http_s *h, VALUE handler, VALUE env) {
|
192
|
+
VALUE io =
|
193
|
+
iodine_connection_new(.type = IODINE_CONNECTION_WEBSOCKET, .arg = NULL,
|
194
|
+
.handler = handler, .env = env, .uuid = 0);
|
195
|
+
if (io == Qnil)
|
196
|
+
return;
|
197
|
+
|
198
|
+
http_upgrade2ws(.http = h, .on_message = iodine_ws_on_message,
|
199
|
+
.on_open = iodine_ws_on_open, .on_ready = iodine_ws_on_ready,
|
200
|
+
.on_shutdown = iodine_ws_on_shutdown,
|
201
|
+
.on_close = iodine_ws_on_close, .udata = (void *)io);
|
202
|
+
}
|
203
|
+
|
204
|
+
/* *****************************************************************************
|
205
|
+
SSE support
|
206
|
+
***************************************************************************** */
|
207
|
+
|
208
|
+
static void iodine_sse_on_ready(http_sse_s *sse) {
|
209
|
+
iodine_connection_fire_event((VALUE)sse->udata, IODINE_CONNECTION_ON_DRAINED,
|
210
|
+
Qnil);
|
211
|
+
}
|
212
|
+
|
213
|
+
static void iodine_sse_on_shutdown(http_sse_s *sse) {
|
214
|
+
iodine_connection_fire_event((VALUE)sse->udata, IODINE_CONNECTION_ON_SHUTDOWN,
|
215
|
+
Qnil);
|
216
|
+
}
|
217
|
+
static void iodine_sse_on_close(http_sse_s *sse) {
|
218
|
+
iodine_connection_fire_event((VALUE)sse->udata, IODINE_CONNECTION_ON_CLOSE,
|
219
|
+
Qnil);
|
220
|
+
}
|
221
|
+
|
222
|
+
static void iodine_sse_on_open(http_sse_s *sse) {
|
223
|
+
VALUE h = (VALUE)sse->udata;
|
224
|
+
iodine_connection_s *c = iodine_connection_CData(h);
|
225
|
+
c->arg = sse;
|
226
|
+
c->uuid = http_sse2uuid(sse);
|
227
|
+
iodine_connection_fire_event(h, IODINE_CONNECTION_ON_OPEN, Qnil);
|
228
|
+
sse->on_ready = iodine_sse_on_ready;
|
229
|
+
evio_add_write(sock_uuid2fd(c->uuid), (void *)c->uuid);
|
230
|
+
}
|
231
|
+
|
232
|
+
static void iodine_sse_attach(http_s *h, VALUE handler, VALUE env) {
|
233
|
+
VALUE io = iodine_connection_new(.type = IODINE_CONNECTION_SSE, .arg = NULL,
|
234
|
+
.handler = handler, .env = env, .uuid = 0);
|
235
|
+
if (io == Qnil)
|
236
|
+
return;
|
237
|
+
|
238
|
+
http_upgrade2sse(h, .on_open = iodine_sse_on_open,
|
239
|
+
.on_ready = NULL /* will be set after the on_open */,
|
240
|
+
.on_shutdown = iodine_sse_on_shutdown,
|
241
|
+
.on_close = iodine_sse_on_close, .udata = (void *)io);
|
242
|
+
}
|
243
|
+
|
107
244
|
/* *****************************************************************************
|
108
245
|
Copying data from the C request to the Rack's ENV
|
109
246
|
***************************************************************************** */
|
@@ -164,7 +301,7 @@ static inline VALUE copy2env(iodine_http_request_handle_s *handle) {
|
|
164
301
|
env = rb_hash_dup(env_template_no_upgrade);
|
165
302
|
break;
|
166
303
|
}
|
167
|
-
|
304
|
+
IodineStore.add(env);
|
168
305
|
|
169
306
|
fio_cstr_s tmp;
|
170
307
|
char *pos = NULL;
|
@@ -207,14 +344,6 @@ static inline VALUE copy2env(iodine_http_request_handle_s *handle) {
|
|
207
344
|
}
|
208
345
|
}
|
209
346
|
|
210
|
-
/* setup input IO + hijack support */
|
211
|
-
{
|
212
|
-
VALUE m;
|
213
|
-
rb_hash_aset(env, R_INPUT, (m = IodineRackIO.create(h, env)));
|
214
|
-
m = rb_obj_method(m, hijack_func_sym);
|
215
|
-
rb_hash_aset(env, IODINE_R_HIJACK, m);
|
216
|
-
}
|
217
|
-
|
218
347
|
/* handle the HOST header, including the possible host:#### format*/
|
219
348
|
static uint64_t host_hash = 0;
|
220
349
|
if (!host_hash)
|
@@ -333,11 +462,11 @@ static int for_each_header_data(VALUE key, VALUE val, VALUE h_) {
|
|
333
462
|
http_s *h = (http_s *)h_;
|
334
463
|
// fprintf(stderr, "For_each - headers\n");
|
335
464
|
if (TYPE(key) != T_STRING)
|
336
|
-
key =
|
465
|
+
key = IodineCaller.call(key, iodine_to_s_method_id);
|
337
466
|
if (TYPE(key) != T_STRING)
|
338
467
|
return ST_CONTINUE;
|
339
468
|
if (TYPE(val) != T_STRING) {
|
340
|
-
val =
|
469
|
+
val = IodineCaller.call(val, iodine_to_s_method_id);
|
341
470
|
if (TYPE(val) != T_STRING)
|
342
471
|
return ST_STOP;
|
343
472
|
}
|
@@ -392,7 +521,7 @@ static inline int ruby2c_response_send(iodine_http_request_handle_s *handle,
|
|
392
521
|
if (handle->h->status < 200 || handle->h->status == 204 ||
|
393
522
|
handle->h->status == 304) {
|
394
523
|
if (rb_respond_to(body, close_method_id))
|
395
|
-
|
524
|
+
IodineCaller.call(body, close_method_id);
|
396
525
|
body = Qnil;
|
397
526
|
handle->type = IODINE_HTTP_NONE;
|
398
527
|
return 0;
|
@@ -420,7 +549,7 @@ static inline int ruby2c_response_send(iodine_http_request_handle_s *handle,
|
|
420
549
|
(VALUE)handle->body);
|
421
550
|
// we need to call `close` in case the object is an IO / BodyProxy
|
422
551
|
if (rb_respond_to(body, close_method_id))
|
423
|
-
|
552
|
+
IodineCaller.call(body, close_method_id);
|
424
553
|
return 0;
|
425
554
|
}
|
426
555
|
return -1;
|
@@ -438,37 +567,54 @@ static inline int ruby2c_review_upgrade(iodine_http_request_handle_s *req,
|
|
438
567
|
// send headers
|
439
568
|
http_finish(h);
|
440
569
|
// call the callback
|
441
|
-
VALUE io_ruby =
|
442
|
-
|
443
|
-
|
570
|
+
VALUE io_ruby = IodineCaller.call(rb_hash_aref(env, IODINE_R_HIJACK),
|
571
|
+
iodine_call_proc_id);
|
572
|
+
IodineCaller.call2(handler, iodine_call_proc_id, 1, &io_ruby);
|
573
|
+
goto upgraded;
|
444
574
|
} else if ((handler = rb_hash_aref(env, IODINE_R_HIJACK_IO)) != Qnil) {
|
445
|
-
// do nothing
|
446
|
-
|
447
|
-
((handler = rb_hash_aref(env, RACK_UPGRADE)) != Qnil ||
|
448
|
-
(handler = rb_hash_aref(env, UPGRADE_WEBSOCKET)) != Qnil)) {
|
449
|
-
// use response as existing base for native websocket upgrade
|
450
|
-
iodine_upgrade_websocket(h, handler);
|
451
|
-
} else if (req->upgrade == IODINE_UPGRADE_SSE &&
|
452
|
-
(handler = rb_hash_aref(env, RACK_UPGRADE)) != Qnil) {
|
453
|
-
// use response as existing base for SSE upgrade
|
454
|
-
iodine_upgrade_sse(h, handler);
|
575
|
+
// do nothing, just cleanup
|
576
|
+
goto upgraded;
|
455
577
|
} else if ((handler = rb_hash_aref(env, UPGRADE_TCP)) != Qnil) {
|
456
|
-
|
457
|
-
intptr_t uuid = http_hijack(h, NULL);
|
458
|
-
// send headers
|
459
|
-
http_finish(h);
|
460
|
-
// upgrade protocol
|
461
|
-
VALUE args[2] = {(ULONG2NUM(sock_uuid2fd(uuid))), handler};
|
462
|
-
RubyCaller.call2(Iodine, attach_method_id, 2, args);
|
463
|
-
// nothing left to do to prevent response processing.
|
578
|
+
goto tcp_ip_upgrade;
|
464
579
|
} else {
|
465
|
-
|
580
|
+
switch (req->upgrade) {
|
581
|
+
case IODINE_UPGRADE_WEBSOCKET:
|
582
|
+
if ((handler = rb_hash_aref(env, RACK_UPGRADE)) != Qnil) {
|
583
|
+
// use response as existing base for native websocket upgrade
|
584
|
+
iodine_ws_attach(h, handler, env);
|
585
|
+
goto upgraded;
|
586
|
+
}
|
587
|
+
break;
|
588
|
+
case IODINE_UPGRADE_SSE:
|
589
|
+
if ((handler = rb_hash_aref(env, RACK_UPGRADE)) != Qnil) {
|
590
|
+
// use response as existing base for SSE upgrade
|
591
|
+
iodine_sse_attach(h, handler, env);
|
592
|
+
goto upgraded;
|
593
|
+
}
|
594
|
+
break;
|
595
|
+
default:
|
596
|
+
if ((handler = rb_hash_aref(env, RACK_UPGRADE)) != Qnil) {
|
597
|
+
tcp_ip_upgrade : {
|
598
|
+
// use response as existing base for raw TCP/IP upgrade
|
599
|
+
intptr_t uuid = http_hijack(h, NULL);
|
600
|
+
// send headers
|
601
|
+
http_finish(h);
|
602
|
+
// upgrade protocol to raw TCP/IP
|
603
|
+
iodine_tcp_attch_uuid(uuid, handler);
|
604
|
+
goto upgraded;
|
605
|
+
}
|
606
|
+
}
|
607
|
+
break;
|
608
|
+
}
|
466
609
|
}
|
610
|
+
return 0;
|
611
|
+
|
612
|
+
upgraded:
|
467
613
|
// get body object to close it (if needed)
|
468
614
|
handler = rb_ary_entry(rbresponse, 2);
|
469
615
|
// we need to call `close` in case the object is an IO / BodyProxy
|
470
616
|
if (handler != Qnil && rb_respond_to(handler, close_method_id))
|
471
|
-
|
617
|
+
IodineCaller.call(handler, close_method_id);
|
472
618
|
return 1;
|
473
619
|
}
|
474
620
|
|
@@ -486,14 +632,17 @@ static inline void *iodine_handle_request_in_GVL(void *handle_) {
|
|
486
632
|
|
487
633
|
// create / register env variable
|
488
634
|
env = copy2env(handle);
|
489
|
-
//
|
490
|
-
VALUE tmp;
|
635
|
+
// create rack.io
|
636
|
+
VALUE tmp = IodineRackIO.create(h, env);
|
491
637
|
// pass env variable to handler
|
492
|
-
rbresponse =
|
638
|
+
rbresponse =
|
639
|
+
IodineCaller.call2((VALUE)h->udata, iodine_call_proc_id, 1, &env);
|
640
|
+
// close rack.io
|
641
|
+
IodineRackIO.close(tmp);
|
493
642
|
// test handler's return value
|
494
643
|
if (rbresponse == 0 || rbresponse == Qnil)
|
495
644
|
goto internal_error;
|
496
|
-
|
645
|
+
IodineStore.add(rbresponse);
|
497
646
|
|
498
647
|
// set response status
|
499
648
|
tmp = rb_ary_entry(rbresponse, 0);
|
@@ -519,7 +668,7 @@ static inline void *iodine_handle_request_in_GVL(void *handle_) {
|
|
519
668
|
if (OBJ_FROZEN(response_headers)) {
|
520
669
|
response_headers = rb_hash_dup(response_headers);
|
521
670
|
}
|
522
|
-
|
671
|
+
IodineStore.add(response_headers);
|
523
672
|
handle->body = fiobj_str_new(RSTRING_PTR(xfiles), RSTRING_LEN(xfiles));
|
524
673
|
handle->type = IODINE_HTTP_XSENDFILE;
|
525
674
|
rb_hash_delete(response_headers, XSENDFILE);
|
@@ -527,7 +676,7 @@ static inline void *iodine_handle_request_in_GVL(void *handle_) {
|
|
527
676
|
rb_hash_delete(response_headers, CONTENT_LENGTH_HEADER);
|
528
677
|
// review each header and write it to the response.
|
529
678
|
rb_hash_foreach(response_headers, for_each_header_data, (VALUE)(h));
|
530
|
-
|
679
|
+
IodineStore.remove(response_headers);
|
531
680
|
// send the file directly and finish
|
532
681
|
return NULL;
|
533
682
|
}
|
@@ -540,26 +689,26 @@ static inline void *iodine_handle_request_in_GVL(void *handle_) {
|
|
540
689
|
if (ruby2c_response_send(handle, rbresponse, env))
|
541
690
|
goto internal_error;
|
542
691
|
|
543
|
-
|
544
|
-
|
692
|
+
IodineStore.remove(rbresponse);
|
693
|
+
IodineStore.remove(env);
|
545
694
|
return NULL;
|
546
695
|
|
547
696
|
external_done:
|
548
|
-
|
549
|
-
|
697
|
+
IodineStore.remove(rbresponse);
|
698
|
+
IodineStore.remove(env);
|
550
699
|
handle->type = IODINE_HTTP_NONE;
|
551
700
|
return NULL;
|
552
701
|
|
553
702
|
err_not_found:
|
554
|
-
|
555
|
-
|
703
|
+
IodineStore.remove(rbresponse);
|
704
|
+
IodineStore.remove(env);
|
556
705
|
h->status = 404;
|
557
706
|
handle->type = IODINE_HTTP_ERROR;
|
558
707
|
return NULL;
|
559
708
|
|
560
709
|
internal_error:
|
561
|
-
|
562
|
-
|
710
|
+
IodineStore.remove(rbresponse);
|
711
|
+
IodineStore.remove(env);
|
563
712
|
h->status = 500;
|
564
713
|
handle->type = IODINE_HTTP_ERROR;
|
565
714
|
return NULL;
|
@@ -606,7 +755,8 @@ static void on_rack_request(http_s *h) {
|
|
606
755
|
iodine_http_request_handle_s handle = (iodine_http_request_handle_s){
|
607
756
|
.h = h, .upgrade = IODINE_UPGRADE_NONE,
|
608
757
|
};
|
609
|
-
|
758
|
+
IodineCaller.enterGVL((void *(*)(void *))iodine_handle_request_in_GVL,
|
759
|
+
&handle);
|
610
760
|
iodine_perform_handle_action(handle);
|
611
761
|
}
|
612
762
|
|
@@ -616,11 +766,13 @@ static void on_rack_upgrade(http_s *h, char *proto, size_t len) {
|
|
616
766
|
handle.upgrade = IODINE_UPGRADE_WEBSOCKET;
|
617
767
|
} else if (len == 3 && proto[0] == 's') {
|
618
768
|
handle.upgrade = IODINE_UPGRADE_SSE;
|
619
|
-
} else {
|
620
|
-
http_send_error(h, 400);
|
621
|
-
return;
|
622
769
|
}
|
623
|
-
|
770
|
+
/* when we stop supporting custom Upgrade headers: */
|
771
|
+
// else {
|
772
|
+
// http_send_error(h, 400);
|
773
|
+
// return;
|
774
|
+
// }
|
775
|
+
IodineCaller.enterGVL(iodine_handle_request_in_GVL, &handle);
|
624
776
|
iodine_perform_handle_action(handle);
|
625
777
|
(void)proto;
|
626
778
|
(void)len;
|
@@ -631,7 +783,7 @@ Listenninng to HTTP
|
|
631
783
|
*****************************************************************************
|
632
784
|
*/
|
633
785
|
|
634
|
-
void *
|
786
|
+
void *iodine_print_http_msg_in_gvl(void *d_) {
|
635
787
|
// Write message
|
636
788
|
struct {
|
637
789
|
VALUE www;
|
@@ -646,64 +798,26 @@ void *iodine_print_http_msg2_in_gvl(void *d_) {
|
|
646
798
|
return NULL;
|
647
799
|
}
|
648
800
|
|
649
|
-
void
|
650
|
-
// Write message
|
651
|
-
VALUE iodine_version = rb_const_get(Iodine, rb_intern("VERSION"));
|
652
|
-
VALUE ruby_version = rb_const_get(Iodine, rb_intern("RUBY_VERSION"));
|
653
|
-
struct {
|
654
|
-
VALUE www;
|
655
|
-
VALUE port;
|
656
|
-
} *arg = d_;
|
657
|
-
if (arg->www) {
|
658
|
-
fprintf(stderr,
|
659
|
-
"\nStarting up Iodine HTTP Server on port %s:\n"
|
660
|
-
" * Ruby v.%s\n * Iodine v.%s \n"
|
661
|
-
" * Serving static files from %s\n\n",
|
662
|
-
StringValueCStr(arg->port), StringValueCStr(ruby_version),
|
663
|
-
StringValueCStr(iodine_version), StringValueCStr(arg->www));
|
664
|
-
} else {
|
665
|
-
fprintf(stderr,
|
666
|
-
"\nStarting up Iodine HTTP Server on port %s:\n"
|
667
|
-
" * Ruby v.%s\n * Iodine v.%s \n\n",
|
668
|
-
StringValueCStr(arg->port), StringValueCStr(ruby_version),
|
669
|
-
StringValueCStr(iodine_version));
|
670
|
-
}
|
671
|
-
|
672
|
-
return NULL;
|
673
|
-
}
|
674
|
-
|
675
|
-
static void iodine_print_http_msg1(void *www, void *port) {
|
801
|
+
static void iodine_print_http_msg(void *www, void *port) {
|
676
802
|
if (getpid() != facil_parent_pid())
|
677
803
|
goto finish;
|
678
804
|
struct {
|
679
805
|
void *www;
|
680
806
|
void *port;
|
681
807
|
} data = {.www = www, .port = port};
|
682
|
-
|
808
|
+
IodineCaller.enterGVL(iodine_print_http_msg_in_gvl, (void *)&data);
|
683
809
|
finish:
|
684
810
|
if (www) {
|
685
|
-
|
811
|
+
IodineStore.remove((VALUE)www);
|
686
812
|
}
|
687
|
-
|
688
|
-
}
|
689
|
-
static void iodine_print_http_msg2(void *www, void *port) {
|
690
|
-
if (getpid() != facil_parent_pid())
|
691
|
-
goto finish;
|
692
|
-
struct {
|
693
|
-
void *www;
|
694
|
-
void *port;
|
695
|
-
} data = {.www = www, .port = port};
|
696
|
-
RubyCaller.call_c(iodine_print_http_msg2_in_gvl, (void *)&data);
|
697
|
-
finish:
|
698
|
-
if (www) {
|
699
|
-
Registry.remove((VALUE)www);
|
700
|
-
}
|
701
|
-
Registry.remove((VALUE)port);
|
813
|
+
IodineStore.remove((VALUE)port);
|
702
814
|
}
|
703
815
|
|
704
816
|
static void free_iodine_http(http_settings_s *s) {
|
705
|
-
|
817
|
+
IodineStore.remove((VALUE)s->udata);
|
706
818
|
}
|
819
|
+
|
820
|
+
// clang-format off
|
707
821
|
/**
|
708
822
|
Listens to incoming HTTP connections and handles incoming requests using the
|
709
823
|
Rack specification.
|
@@ -714,6 +828,8 @@ specifications.
|
|
714
828
|
|
715
829
|
Accepts a single Hash argument with the following properties:
|
716
830
|
|
831
|
+
(it's possible to set default values using the {Iodine::DEFAULT_HTTP_ARGS} Hash)
|
832
|
+
|
717
833
|
app:: the Rack application that handles incoming requests. Default: `nil`.
|
718
834
|
port:: the port to listen to. Default: 3000.
|
719
835
|
address:: the address to bind to. Default: binds to all possible addresses.
|
@@ -721,6 +837,7 @@ log:: enable response logging (Hijacked sockets aren't logged). Default: off.
|
|
721
837
|
public:: The root public folder for static file service. Default: none.
|
722
838
|
timeout:: Timeout for inactive HTTP/1.x connections. Defaults: 40 seconds.
|
723
839
|
max_body:: The maximum body size for incoming HTTP messages. Default: ~50Mib.
|
840
|
+
max_headers:: The maximum total header length for incoming HTTP messages. Default: ~64Kib.
|
724
841
|
max_msg:: The maximum Websocket message size allowed. Default: ~250Kib.
|
725
842
|
ping:: The Websocket `ping` interval. Default: 40 seconds.
|
726
843
|
|
@@ -740,60 +857,89 @@ timeouts will be dynamically managed by Iodine. The `timeout` option is only
|
|
740
857
|
relevant to HTTP/1.x connections.
|
741
858
|
*/
|
742
859
|
VALUE iodine_http_listen(VALUE self, VALUE opt) {
|
743
|
-
|
860
|
+
// clang-format on
|
744
861
|
uint8_t log_http = 0;
|
745
862
|
size_t ping = 0;
|
746
863
|
size_t max_body = 0;
|
747
864
|
size_t max_headers = 0;
|
748
865
|
size_t max_msg = 0;
|
749
866
|
Check_Type(opt, T_HASH);
|
867
|
+
/* copy from deafult hash */
|
868
|
+
/* test arguments */
|
750
869
|
VALUE app = rb_hash_aref(opt, ID2SYM(rb_intern("app")));
|
751
870
|
VALUE www = rb_hash_aref(opt, ID2SYM(rb_intern("public")));
|
752
871
|
VALUE port = rb_hash_aref(opt, ID2SYM(rb_intern("port")));
|
753
872
|
VALUE address = rb_hash_aref(opt, ID2SYM(rb_intern("address")));
|
754
873
|
VALUE tout = rb_hash_aref(opt, ID2SYM(rb_intern("timeout")));
|
874
|
+
if (www == Qnil) {
|
875
|
+
www = rb_hash_aref(iodine_default_args, ID2SYM(rb_intern("public")));
|
876
|
+
}
|
877
|
+
if (port == Qnil) {
|
878
|
+
port = rb_hash_aref(iodine_default_args, ID2SYM(rb_intern("port")));
|
879
|
+
}
|
880
|
+
if (address == Qnil) {
|
881
|
+
address = rb_hash_aref(iodine_default_args, ID2SYM(rb_intern("address")));
|
882
|
+
}
|
883
|
+
if (tout == Qnil) {
|
884
|
+
tout = rb_hash_aref(iodine_default_args, ID2SYM(rb_intern("timeout")));
|
885
|
+
}
|
755
886
|
|
756
887
|
VALUE tmp = rb_hash_aref(opt, ID2SYM(rb_intern("max_msg")));
|
888
|
+
if (tmp == Qnil) {
|
889
|
+
tmp = rb_hash_aref(iodine_default_args, ID2SYM(rb_intern("max_msg")));
|
890
|
+
}
|
757
891
|
if (tmp != Qnil && tmp != Qfalse) {
|
758
892
|
Check_Type(tmp, T_FIXNUM);
|
759
893
|
max_msg = FIX2ULONG(tmp);
|
760
894
|
}
|
761
895
|
|
762
896
|
tmp = rb_hash_aref(opt, ID2SYM(rb_intern("max_body")));
|
897
|
+
if (tmp == Qnil) {
|
898
|
+
tmp = rb_hash_aref(iodine_default_args, ID2SYM(rb_intern("max_body")));
|
899
|
+
}
|
763
900
|
if (tmp != Qnil && tmp != Qfalse) {
|
764
901
|
Check_Type(tmp, T_FIXNUM);
|
765
902
|
max_body = FIX2ULONG(tmp);
|
766
903
|
}
|
767
904
|
tmp = rb_hash_aref(opt, ID2SYM(rb_intern("max_headers")));
|
905
|
+
if (tmp == Qnil) {
|
906
|
+
tmp = rb_hash_aref(iodine_default_args, ID2SYM(rb_intern("max_headers")));
|
907
|
+
}
|
768
908
|
if (tmp != Qnil && tmp != Qfalse) {
|
769
909
|
Check_Type(tmp, T_FIXNUM);
|
770
910
|
max_headers = FIX2ULONG(tmp);
|
771
911
|
}
|
772
912
|
|
773
913
|
tmp = rb_hash_aref(opt, ID2SYM(rb_intern("ping")));
|
914
|
+
if (tmp == Qnil) {
|
915
|
+
tmp = rb_hash_aref(iodine_default_args, ID2SYM(rb_intern("ping")));
|
916
|
+
}
|
774
917
|
if (tmp != Qnil && tmp != Qfalse) {
|
775
918
|
Check_Type(tmp, T_FIXNUM);
|
776
919
|
ping = FIX2ULONG(tmp);
|
777
920
|
}
|
778
921
|
if (ping > 255) {
|
779
922
|
fprintf(stderr, "Iodine Warning: Websocket timeout value "
|
780
|
-
"is over 255 and
|
923
|
+
"is over 255 and will be ignored.\n");
|
781
924
|
ping = 0;
|
782
925
|
}
|
783
926
|
|
784
927
|
tmp = rb_hash_aref(opt, ID2SYM(rb_intern("log")));
|
928
|
+
if (tmp == Qnil) {
|
929
|
+
tmp = rb_hash_aref(iodine_default_args, ID2SYM(rb_intern("log")));
|
930
|
+
}
|
785
931
|
if (tmp != Qnil && tmp != Qfalse)
|
786
932
|
log_http = 1;
|
787
933
|
|
788
934
|
if ((app == Qnil || app == Qfalse) && (www == Qnil || www == Qfalse)) {
|
789
935
|
fprintf(stderr, "Iodine Warning: HTTP without application or public folder "
|
790
|
-
"(
|
936
|
+
"(ignored).\n");
|
791
937
|
return Qfalse;
|
792
938
|
}
|
793
939
|
|
794
940
|
if ((www != Qnil && www != Qfalse)) {
|
795
941
|
Check_Type(www, T_STRING);
|
796
|
-
|
942
|
+
IodineStore.add(www);
|
797
943
|
rb_hash_aset(env_template_no_upgrade, XSENDFILE_TYPE, XSENDFILE);
|
798
944
|
rb_hash_aset(env_template_no_upgrade, XSENDFILE_TYPE_HEADER, XSENDFILE);
|
799
945
|
support_xsendfile = 1;
|
@@ -822,16 +968,16 @@ VALUE iodine_http_listen(VALUE self, VALUE opt) {
|
|
822
968
|
"The `port` property MUST be either a String or a Number");
|
823
969
|
if (RB_TYPE_P(port, T_FIXNUM))
|
824
970
|
port = rb_funcall2(port, iodine_to_s_method_id, 0, NULL);
|
825
|
-
|
971
|
+
IodineStore.add(port);
|
826
972
|
} else if (port == Qfalse)
|
827
973
|
port = 0;
|
828
974
|
else {
|
829
975
|
port = rb_str_new("3000", 4);
|
830
|
-
|
976
|
+
IodineStore.add(port);
|
831
977
|
}
|
832
978
|
|
833
979
|
if ((app != Qnil && app != Qfalse))
|
834
|
-
|
980
|
+
IodineStore.add(app);
|
835
981
|
else
|
836
982
|
app = 0;
|
837
983
|
|
@@ -855,12 +1001,7 @@ VALUE iodine_http_listen(VALUE self, VALUE opt) {
|
|
855
1001
|
"static files.\n",
|
856
1002
|
(port ? StringValueCStr(port) : "3000"));
|
857
1003
|
}
|
858
|
-
|
859
|
-
defer(iodine_print_http_msg2, (www ? (void *)www : NULL), (void *)port);
|
860
|
-
} else {
|
861
|
-
called_once = 1;
|
862
|
-
defer(iodine_print_http_msg1, (www ? (void *)www : NULL), (void *)port);
|
863
|
-
}
|
1004
|
+
defer(iodine_print_http_msg, (www ? (void *)www : NULL), (void *)port);
|
864
1005
|
|
865
1006
|
return Qtrue;
|
866
1007
|
(void)self;
|
@@ -870,7 +1011,7 @@ static void initialize_env_template(void) {
|
|
870
1011
|
if (env_template_no_upgrade)
|
871
1012
|
return;
|
872
1013
|
env_template_no_upgrade = rb_hash_new();
|
873
|
-
|
1014
|
+
IodineStore.add(env_template_no_upgrade);
|
874
1015
|
|
875
1016
|
#define add_str_to_env(env, key, value) \
|
876
1017
|
{ \
|
@@ -890,10 +1031,6 @@ static void initialize_env_template(void) {
|
|
890
1031
|
/* Set global template */
|
891
1032
|
rb_hash_aset(env_template_no_upgrade, RACK_UPGRADE_Q, Qnil);
|
892
1033
|
rb_hash_aset(env_template_no_upgrade, RACK_UPGRADE, Qnil);
|
893
|
-
rb_hash_aset(env_template_no_upgrade, UPGRADE_WEBSOCKET_Q, Qnil);
|
894
|
-
rb_hash_aset(env_template_no_upgrade, UPGRADE_WEBSOCKET, Qnil);
|
895
|
-
rb_hash_aset(env_template_no_upgrade, UPGRADE_TCP_Q, Qnil);
|
896
|
-
rb_hash_aset(env_template_no_upgrade, UPGRADE_TCP, Qnil);
|
897
1034
|
{
|
898
1035
|
/* add the rack.version */
|
899
1036
|
static VALUE rack_version = 0;
|
@@ -927,26 +1064,32 @@ static void initialize_env_template(void) {
|
|
927
1064
|
|
928
1065
|
/* WebSocket upgrade support */
|
929
1066
|
env_template_websockets = rb_hash_dup(env_template_no_upgrade);
|
930
|
-
|
931
|
-
rb_hash_aset(env_template_websockets, UPGRADE_WEBSOCKET_Q, Qtrue);
|
1067
|
+
IodineStore.add(env_template_websockets);
|
932
1068
|
rb_hash_aset(env_template_websockets, RACK_UPGRADE_Q, RACK_UPGRADE_WEBSOCKET);
|
933
|
-
rb_hash_aset(env_template_websockets, UPGRADE_TCP_Q, Qtrue);
|
934
1069
|
|
935
1070
|
/* SSE upgrade support */
|
936
1071
|
env_template_sse = rb_hash_dup(env_template_no_upgrade);
|
937
|
-
|
1072
|
+
IodineStore.add(env_template_sse);
|
938
1073
|
rb_hash_aset(env_template_sse, RACK_UPGRADE_Q, RACK_UPGRADE_SSE);
|
939
1074
|
|
940
1075
|
#undef add_value_to_env
|
941
1076
|
#undef add_str_to_env
|
942
1077
|
}
|
1078
|
+
|
943
1079
|
/* *****************************************************************************
|
944
1080
|
Initialization
|
945
1081
|
***************************************************************************** */
|
946
1082
|
|
947
|
-
void
|
1083
|
+
void iodine_init_http(void) {
|
1084
|
+
|
1085
|
+
rb_define_module_function(IodineModule, "listen2http", iodine_http_listen, 1);
|
1086
|
+
|
1087
|
+
/** Used by {listen2http} to set missing arguments. */
|
1088
|
+
iodine_default_args = rb_hash_new();
|
948
1089
|
|
949
|
-
|
1090
|
+
/** Used by {listen2http} to set missing arguments. */
|
1091
|
+
rb_const_set(IodineModule, rb_intern2("DEFAULT_HTTP_ARGS", 17),
|
1092
|
+
iodine_default_args);
|
950
1093
|
|
951
1094
|
rack_autoset(REQUEST_METHOD);
|
952
1095
|
rack_autoset(PATH_INFO);
|
@@ -972,22 +1115,22 @@ void Iodine_init_http(void) {
|
|
972
1115
|
rack_set(IODINE_R_HIJACK, "rack.hijack");
|
973
1116
|
rack_set(IODINE_R_HIJACK_CB, "iodine.hijack_cb");
|
974
1117
|
|
975
|
-
rack_set(UPGRADE_TCP, "upgrade.tcp");
|
976
|
-
rack_set(UPGRADE_WEBSOCKET, "upgrade.websocket");
|
977
|
-
|
978
|
-
rack_set(UPGRADE_TCP_Q, "upgrade.tcp?");
|
979
|
-
rack_set(UPGRADE_WEBSOCKET_Q, "upgrade.websocket?");
|
980
1118
|
rack_set(RACK_UPGRADE, "rack.upgrade");
|
981
1119
|
rack_set(RACK_UPGRADE_Q, "rack.upgrade?");
|
982
1120
|
rack_set_sym(RACK_UPGRADE_SSE, "sse");
|
983
1121
|
rack_set_sym(RACK_UPGRADE_WEBSOCKET, "websocket");
|
984
1122
|
|
1123
|
+
UPGRADE_TCP = IodineStore.add(rb_str_new("upgrade.tcp", 11));
|
1124
|
+
|
985
1125
|
hijack_func_sym = ID2SYM(rb_intern("_hijack"));
|
986
1126
|
close_method_id = rb_intern("close");
|
987
1127
|
each_method_id = rb_intern("each");
|
988
1128
|
attach_method_id = rb_intern("attach_fd");
|
1129
|
+
iodine_to_s_method_id = rb_intern("to_s");
|
1130
|
+
iodine_call_proc_id = rb_intern("call");
|
1131
|
+
|
1132
|
+
IodineUTF8Encoding = rb_enc_find("UTF-8");
|
1133
|
+
IodineBinaryEncoding = rb_enc_find("binary");
|
989
1134
|
|
990
|
-
IodineRackIO.init();
|
991
1135
|
initialize_env_template();
|
992
|
-
Iodine_init_json();
|
993
1136
|
}
|