iodine 0.7.41 → 0.7.45
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/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
- data/.gitignore +1 -0
- data/CHANGELOG.md +24 -0
- data/README.md +2 -2
- data/SPEC-PubSub-Draft.md +89 -47
- data/SPEC-WebSocket-Draft.md +92 -55
- data/examples/async_task.ru +92 -0
- data/ext/iodine/extconf.rb +21 -16
- data/ext/iodine/fio.c +1108 -162
- data/ext/iodine/fio.h +49 -13
- data/ext/iodine/fio_cli.c +1 -1
- data/ext/iodine/fio_tls_missing.c +8 -0
- data/ext/iodine/fio_tls_openssl.c +8 -0
- data/ext/iodine/fio_tmpfile.h +13 -1
- data/ext/iodine/fiobj_data.c +6 -4
- data/ext/iodine/fiobj_data.h +2 -1
- data/ext/iodine/fiobj_hash.c +32 -6
- data/ext/iodine/fiobj_mustache.c +9 -0
- data/ext/iodine/fiobj_numbers.c +86 -8
- data/ext/iodine/fiobj_str.c +24 -11
- data/ext/iodine/fiobject.c +1 -1
- data/ext/iodine/fiobject.h +5 -3
- data/ext/iodine/http.c +66 -10
- data/ext/iodine/http1.c +2 -1
- data/ext/iodine/http1_parser.h +1065 -103
- data/ext/iodine/http_internal.c +1 -0
- data/ext/iodine/http_internal.h +4 -2
- data/ext/iodine/iodine.c +66 -1
- data/ext/iodine/iodine.h +3 -0
- data/ext/iodine/iodine_caller.c +48 -8
- data/ext/iodine/iodine_connection.c +24 -8
- data/ext/iodine/iodine_http.c +32 -8
- data/ext/iodine/iodine_mustache.c +2 -4
- data/ext/iodine/iodine_rack_io.c +21 -0
- data/ext/iodine/iodine_tcp.c +14 -0
- data/ext/iodine/iodine_tls.c +8 -0
- data/ext/iodine/mustache_parser.h +4 -0
- data/ext/iodine/redis_engine.c +14 -11
- data/ext/iodine/websockets.c +7 -3
- data/iodine.gemspec +5 -4
- data/lib/iodine/version.rb +1 -1
- data/lib/rack/handler/iodine.rb +6 -0
- metadata +15 -13
data/ext/iodine/http_internal.c
CHANGED
@@ -98,6 +98,7 @@ int http_send_error2(size_t error, intptr_t uuid, http_settings_s *settings) {
|
|
98
98
|
return -1;
|
99
99
|
fio_protocol_s *pr = http1_new(uuid, settings, NULL, 0);
|
100
100
|
http_s *r = fio_malloc(sizeof(*r));
|
101
|
+
FIO_ASSERT_ALLOC(r);
|
101
102
|
FIO_ASSERT(pr, "Couldn't allocate response object for error report.")
|
102
103
|
http_s_new(r, (http_fio_protocol_s *)pr, http1_vtable());
|
103
104
|
int ret = http_send_error(r, error);
|
data/ext/iodine/http_internal.h
CHANGED
@@ -15,7 +15,9 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
15
15
|
|
16
16
|
#include <http.h>
|
17
17
|
|
18
|
+
#ifndef __MINGW32__
|
18
19
|
#include <arpa/inet.h>
|
20
|
+
#endif
|
19
21
|
#include <errno.h>
|
20
22
|
|
21
23
|
/* *****************************************************************************
|
@@ -121,8 +123,8 @@ static inline void http_s_destroy(http_s *h, uint8_t log) {
|
|
121
123
|
fiobj_free(h->params);
|
122
124
|
|
123
125
|
*h = (http_s){
|
124
|
-
|
125
|
-
|
126
|
+
.private_data.vtbl = h->private_data.vtbl,
|
127
|
+
.private_data.flag = h->private_data.flag,
|
126
128
|
};
|
127
129
|
}
|
128
130
|
|
data/ext/iodine/iodine.c
CHANGED
@@ -33,6 +33,7 @@ VALUE IodineBaseModule;
|
|
33
33
|
VALUE iodine_default_args;
|
34
34
|
|
35
35
|
ID iodine_call_id;
|
36
|
+
ID iodine_to_s_id;
|
36
37
|
|
37
38
|
static VALUE address_sym;
|
38
39
|
static VALUE app_sym;
|
@@ -412,7 +413,7 @@ static VALUE iodine_cli_parse(VALUE self) {
|
|
412
413
|
FIO_CLI_PRINT_HEADER("WebSocket Settings:"),
|
413
414
|
FIO_CLI_INT("-max-msg -maxms incoming WebSocket message limit in Kb. "
|
414
415
|
"Default: 250Kb"),
|
415
|
-
FIO_CLI_INT("-ping websocket ping interval (
|
416
|
+
FIO_CLI_INT("-ping websocket ping interval (1..255). Default: 40s"),
|
416
417
|
FIO_CLI_PRINT_HEADER("SSL/TLS:"),
|
417
418
|
FIO_CLI_BOOL("-tls enable SSL/TLS using a self-signed certificate."),
|
418
419
|
FIO_CLI_STRING(
|
@@ -518,6 +519,7 @@ static VALUE iodine_cli_parse(VALUE self) {
|
|
518
519
|
rb_hash_aset(defaults, max_headers_sym,
|
519
520
|
INT2NUM((fio_cli_get_i("-maxhd") /* * 1024 */)));
|
520
521
|
}
|
522
|
+
#ifndef __MINGW32__
|
521
523
|
if (fio_cli_get_bool("-tls") || fio_cli_get("-key") || fio_cli_get("-cert")) {
|
522
524
|
VALUE rbtls = IodineCaller.call(IodineTLSClass, rb_intern2("new", 3));
|
523
525
|
if (rbtls == Qnil) {
|
@@ -542,6 +544,7 @@ static VALUE iodine_cli_parse(VALUE self) {
|
|
542
544
|
}
|
543
545
|
rb_hash_aset(defaults, tls_sym, rbtls);
|
544
546
|
}
|
547
|
+
#endif
|
545
548
|
if (fio_cli_unnamed_count()) {
|
546
549
|
rb_hash_aset(defaults, ID2SYM(rb_intern("filename_")),
|
547
550
|
rb_str_new_cstr(fio_cli_unnamed(0)));
|
@@ -633,8 +636,10 @@ FIO_FUNC void iodine_connect_args_cleanup(iodine_connection_args_s *s) {
|
|
633
636
|
fio_free(s->port.data);
|
634
637
|
if (s->address.capa)
|
635
638
|
fio_free(s->address.data);
|
639
|
+
#ifndef __MINGW32__
|
636
640
|
if (s->tls)
|
637
641
|
fio_tls_destroy(s->tls);
|
642
|
+
#endif
|
638
643
|
}
|
639
644
|
|
640
645
|
/*
|
@@ -685,7 +690,9 @@ FIO_FUNC iodine_connection_args_s iodine_connect_args(VALUE s, uint8_t is_srv) {
|
|
685
690
|
VALUE r_public = rb_hash_aref(s, public_sym);
|
686
691
|
VALUE service = rb_hash_aref(s, service_sym);
|
687
692
|
VALUE timeout = rb_hash_aref(s, timeout_sym);
|
693
|
+
#ifndef __MINGW32__
|
688
694
|
VALUE tls = rb_hash_aref(s, tls_sym);
|
695
|
+
#endif
|
689
696
|
VALUE r_url = rb_hash_aref(s, url_sym);
|
690
697
|
fio_str_info_s service_str = {.data = NULL};
|
691
698
|
|
@@ -725,8 +732,10 @@ FIO_FUNC iodine_connection_args_s iodine_connect_args(VALUE s, uint8_t is_srv) {
|
|
725
732
|
// service = rb_hash_aref(iodine_default_args, service_sym);
|
726
733
|
if (timeout == Qnil)
|
727
734
|
timeout = rb_hash_aref(iodine_default_args, timeout_sym);
|
735
|
+
#ifndef __MINGW32__
|
728
736
|
if (tls == Qnil)
|
729
737
|
tls = rb_hash_aref(iodine_default_args, tls_sym);
|
738
|
+
#endif
|
730
739
|
|
731
740
|
/* TODO: deprecation */
|
732
741
|
if (handler == Qnil) {
|
@@ -823,11 +832,13 @@ FIO_FUNC iodine_connection_args_s iodine_connect_args(VALUE s, uint8_t is_srv) {
|
|
823
832
|
else
|
824
833
|
r.timeout = FIX2ULONG(timeout);
|
825
834
|
}
|
835
|
+
#ifndef __MINGW32__
|
826
836
|
if (tls != Qnil) {
|
827
837
|
r.tls = iodine_tls2c(tls);
|
828
838
|
if (r.tls)
|
829
839
|
fio_tls_dup(r.tls);
|
830
840
|
}
|
841
|
+
#endif
|
831
842
|
/* URL parsing */
|
832
843
|
if (r_url != Qnil && RB_TYPE_P(r_url, T_STRING)) {
|
833
844
|
r.url = IODINE_RSTRINFO(r_url);
|
@@ -887,6 +898,56 @@ FIO_FUNC iodine_connection_args_s iodine_connect_args(VALUE s, uint8_t is_srv) {
|
|
887
898
|
/* test/set service type */
|
888
899
|
r.service = IODINE_SERVICE_RAW;
|
889
900
|
if (service_str.data) {
|
901
|
+
#ifdef __MINGW32__
|
902
|
+
switch (service_str.data[0]) {
|
903
|
+
case 't': /* overflow */
|
904
|
+
/* tcp or tls */
|
905
|
+
if (service_str.data[1] == 'l') {
|
906
|
+
char *local = NULL;
|
907
|
+
char buf[1024];
|
908
|
+
buf[1023] = 0;
|
909
|
+
if (is_srv) {
|
910
|
+
local = buf;
|
911
|
+
if (fio_local_addr(buf, 1023) >= 1022)
|
912
|
+
local = NULL;
|
913
|
+
}
|
914
|
+
}
|
915
|
+
/* overflow */
|
916
|
+
case 'u': /* overflow */
|
917
|
+
/* unix */
|
918
|
+
case 'r':
|
919
|
+
/* raw */
|
920
|
+
r.service = IODINE_SERVICE_RAW;
|
921
|
+
break;
|
922
|
+
case 'h':
|
923
|
+
/* http(s) */
|
924
|
+
r.service = IODINE_SERVICE_HTTP;
|
925
|
+
if (service_str.len == 5) {
|
926
|
+
char *local = NULL;
|
927
|
+
char buf[1024];
|
928
|
+
buf[1023] = 0;
|
929
|
+
if (is_srv) {
|
930
|
+
local = buf;
|
931
|
+
if (fio_local_addr(buf, 1023) >= 1022)
|
932
|
+
local = NULL;
|
933
|
+
}
|
934
|
+
}
|
935
|
+
case 'w':
|
936
|
+
/* ws(s) */
|
937
|
+
r.service = IODINE_SERVICE_WS;
|
938
|
+
if (service_str.len == 3) {
|
939
|
+
char *local = NULL;
|
940
|
+
char buf[1024];
|
941
|
+
buf[1023] = 0;
|
942
|
+
if (is_srv) {
|
943
|
+
local = buf;
|
944
|
+
if (fio_local_addr(buf, 1023) >= 1022)
|
945
|
+
local = NULL;
|
946
|
+
}
|
947
|
+
}
|
948
|
+
break;
|
949
|
+
}
|
950
|
+
#else
|
890
951
|
switch (service_str.data[0]) {
|
891
952
|
case 't': /* overflow */
|
892
953
|
/* tcp or tls */
|
@@ -938,6 +999,7 @@ FIO_FUNC iodine_connection_args_s iodine_connect_args(VALUE s, uint8_t is_srv) {
|
|
938
999
|
}
|
939
1000
|
break;
|
940
1001
|
}
|
1002
|
+
#endif
|
941
1003
|
}
|
942
1004
|
return r;
|
943
1005
|
}
|
@@ -1302,6 +1364,7 @@ void Init_iodine(void) {
|
|
1302
1364
|
IodineBaseModule = rb_define_module_under(IodineModule, "Base");
|
1303
1365
|
VALUE IodineCLIModule = rb_define_module_under(IodineBaseModule, "CLI");
|
1304
1366
|
iodine_call_id = rb_intern2("call", 4);
|
1367
|
+
iodine_to_s_id = rb_intern("to_s");
|
1305
1368
|
|
1306
1369
|
// register core methods
|
1307
1370
|
rb_define_module_function(IodineModule, "threads", iodine_threads_get, 0);
|
@@ -1347,8 +1410,10 @@ void Init_iodine(void) {
|
|
1347
1410
|
// initialize the HTTP module
|
1348
1411
|
iodine_init_http();
|
1349
1412
|
|
1413
|
+
#ifndef __MINGW32__
|
1350
1414
|
// initialize SSL/TLS support module
|
1351
1415
|
iodine_init_tls();
|
1416
|
+
#endif
|
1352
1417
|
|
1353
1418
|
// initialize JSON helpers
|
1354
1419
|
iodine_init_json();
|
data/ext/iodine/iodine.h
CHANGED
@@ -15,7 +15,9 @@ typedef struct {
|
|
15
15
|
fio_str_info_s body;
|
16
16
|
fio_str_info_s public;
|
17
17
|
fio_str_info_s url;
|
18
|
+
#ifndef __MINGW32__
|
18
19
|
fio_tls_s *tls;
|
20
|
+
#endif
|
19
21
|
VALUE handler;
|
20
22
|
FIOBJ headers;
|
21
23
|
FIOBJ cookies;
|
@@ -53,6 +55,7 @@ extern VALUE IodineModule;
|
|
53
55
|
extern VALUE IodineBaseModule;
|
54
56
|
extern VALUE iodine_default_args;
|
55
57
|
extern ID iodine_call_id;
|
58
|
+
extern ID iodine_to_s_id;
|
56
59
|
|
57
60
|
#define IODINE_RSTRINFO(rstr) \
|
58
61
|
((fio_str_info_s){.len = RSTRING_LEN(rstr), .data = RSTRING_PTR(rstr)})
|
data/ext/iodine/iodine_caller.c
CHANGED
@@ -5,7 +5,19 @@
|
|
5
5
|
|
6
6
|
#include <fio.h>
|
7
7
|
|
8
|
-
|
8
|
+
#include <pthread.h>
|
9
|
+
|
10
|
+
static pthread_key_t iodine_GVL_state_key;
|
11
|
+
static pthread_once_t iodine_GVL_state_once = PTHREAD_ONCE_INIT;
|
12
|
+
static void init_iodine_GVL_state_key(void) {
|
13
|
+
pthread_key_create(&iodine_GVL_state_key, NULL);
|
14
|
+
}
|
15
|
+
static void init_iodine_GVL_state_init(void) {
|
16
|
+
uint8_t *gvl = malloc(sizeof(uint8_t));
|
17
|
+
FIO_ASSERT_ALLOC(gvl);
|
18
|
+
*gvl = 1;
|
19
|
+
pthread_setspecific(iodine_GVL_state_key, gvl);
|
20
|
+
}
|
9
21
|
|
10
22
|
/* *****************************************************************************
|
11
23
|
Calling protected Ruby methods
|
@@ -84,25 +96,37 @@ API
|
|
84
96
|
|
85
97
|
/** Calls a C function within the GVL. */
|
86
98
|
static void *iodine_enterGVL(void *(*func)(void *), void *arg) {
|
87
|
-
|
99
|
+
pthread_once(&iodine_GVL_state_once, init_iodine_GVL_state_key);
|
100
|
+
uint8_t *iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
|
101
|
+
if (!iodine_GVL_state) {
|
102
|
+
init_iodine_GVL_state_init();
|
103
|
+
iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
|
104
|
+
}
|
105
|
+
if (*iodine_GVL_state) {
|
88
106
|
return func(arg);
|
89
107
|
}
|
90
108
|
void *rv = NULL;
|
91
|
-
iodine_GVL_state = 1;
|
109
|
+
*iodine_GVL_state = 1;
|
92
110
|
rv = rb_thread_call_with_gvl(func, arg);
|
93
|
-
iodine_GVL_state = 0;
|
111
|
+
*iodine_GVL_state = 0;
|
94
112
|
return rv;
|
95
113
|
}
|
96
114
|
|
97
115
|
/** Calls a C function outside the GVL. */
|
98
116
|
static void *iodine_leaveGVL(void *(*func)(void *), void *arg) {
|
117
|
+
pthread_once(&iodine_GVL_state_once, init_iodine_GVL_state_key);
|
118
|
+
uint8_t *iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
|
99
119
|
if (!iodine_GVL_state) {
|
120
|
+
init_iodine_GVL_state_init();
|
121
|
+
iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
|
122
|
+
}
|
123
|
+
if (!*iodine_GVL_state) {
|
100
124
|
return func(arg);
|
101
125
|
}
|
102
126
|
void *rv = NULL;
|
103
|
-
iodine_GVL_state = 0;
|
127
|
+
*iodine_GVL_state = 0;
|
104
128
|
rv = rb_thread_call_without_gvl(func, arg, NULL, NULL);
|
105
|
-
iodine_GVL_state = 1;
|
129
|
+
*iodine_GVL_state = 1;
|
106
130
|
return rv;
|
107
131
|
}
|
108
132
|
|
@@ -151,10 +175,26 @@ static VALUE iodine_call_block(VALUE obj, ID method, int argc, VALUE *argv,
|
|
151
175
|
}
|
152
176
|
|
153
177
|
/** Returns the GVL state flag. */
|
154
|
-
static uint8_t iodine_in_GVL(void) {
|
178
|
+
static uint8_t iodine_in_GVL(void) {
|
179
|
+
pthread_once(&iodine_GVL_state_once, init_iodine_GVL_state_key);
|
180
|
+
uint8_t *iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
|
181
|
+
if (!iodine_GVL_state) {
|
182
|
+
init_iodine_GVL_state_init();
|
183
|
+
iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
|
184
|
+
}
|
185
|
+
return *iodine_GVL_state;
|
186
|
+
}
|
155
187
|
|
156
188
|
/** Forces the GVL state flag. */
|
157
|
-
static void iodine_set_GVL(uint8_t state) {
|
189
|
+
static void iodine_set_GVL(uint8_t state) {
|
190
|
+
pthread_once(&iodine_GVL_state_once, init_iodine_GVL_state_key);
|
191
|
+
uint8_t *iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
|
192
|
+
if (!iodine_GVL_state) {
|
193
|
+
init_iodine_GVL_state_init();
|
194
|
+
iodine_GVL_state = pthread_getspecific(iodine_GVL_state_key);
|
195
|
+
}
|
196
|
+
*iodine_GVL_state = state;
|
197
|
+
}
|
158
198
|
|
159
199
|
/* *****************************************************************************
|
160
200
|
Caller Initialization
|
@@ -159,7 +159,7 @@ Ruby Connection Methods - write, close open? pending
|
|
159
159
|
***************************************************************************** */
|
160
160
|
|
161
161
|
/**
|
162
|
-
* Writes data to the connection asynchronously.
|
162
|
+
* Writes data to the connection asynchronously. `data` MUST be a String.
|
163
163
|
*
|
164
164
|
* In effect, the `write` call does nothing, it only schedules the data to be
|
165
165
|
* sent and marks the data as pending.
|
@@ -174,6 +174,16 @@ static VALUE iodine_connection_write(VALUE self, VALUE data) {
|
|
174
174
|
return Qnil;
|
175
175
|
// rb_raise(rb_eIOError, "Connection closed or invalid.");
|
176
176
|
}
|
177
|
+
if (!RB_TYPE_P(data, T_STRING)) {
|
178
|
+
VALUE tmp = data;
|
179
|
+
data = IodineCaller.call(data, iodine_to_s_id);
|
180
|
+
if (!RB_TYPE_P(data, T_STRING))
|
181
|
+
Check_Type(tmp, T_STRING);
|
182
|
+
rb_backtrace();
|
183
|
+
FIO_LOG_WARNING(
|
184
|
+
"`Iodine::Connection#write` was called with a non-String object.");
|
185
|
+
}
|
186
|
+
|
177
187
|
switch (c->info.type) {
|
178
188
|
case IODINE_CONNECTION_WEBSOCKET:
|
179
189
|
/* WebSockets*/
|
@@ -234,6 +244,14 @@ static VALUE iodine_connection_is_open(VALUE self) {
|
|
234
244
|
}
|
235
245
|
return Qfalse;
|
236
246
|
}
|
247
|
+
|
248
|
+
/**
|
249
|
+
* Always returns true, since Iodine connections support the pub/sub extension.
|
250
|
+
*/
|
251
|
+
static VALUE iodine_connection_is_pubsub(VALUE self) {
|
252
|
+
return INT2NUM(0);
|
253
|
+
(void)self;
|
254
|
+
}
|
237
255
|
/**
|
238
256
|
* Returns the number of pending `write` operations that need to complete
|
239
257
|
* before the next `on_drained` callback is called.
|
@@ -385,8 +403,12 @@ static void *iodine_on_pubsub_call_block(void *msg_) {
|
|
385
403
|
fio_msg_s *msg = msg_;
|
386
404
|
VALUE args[2];
|
387
405
|
args[0] = rb_str_new(msg->channel.data, msg->channel.len);
|
406
|
+
IodineStore.add(args[0]);
|
388
407
|
args[1] = rb_str_new(msg->msg.data, msg->msg.len);
|
408
|
+
IodineStore.add(args[1]);
|
389
409
|
IodineCaller.call2((VALUE)msg->udata2, call_id, 2, args);
|
410
|
+
IodineStore.remove(args[1]);
|
411
|
+
IodineStore.remove(args[0]);
|
390
412
|
return NULL;
|
391
413
|
}
|
392
414
|
|
@@ -675,13 +697,6 @@ The method accepts an optional `engine` argument:
|
|
675
697
|
|
676
698
|
publish(to, message, my_pubsub_engine)
|
677
699
|
|
678
|
-
|
679
|
-
Alternatively, accepts the following named arguments:
|
680
|
-
|
681
|
-
- `:to` - The channel to publish to (required).
|
682
|
-
- `:message` - The message to be published (required).
|
683
|
-
- `:engine` - If provided, the engine to use for pub/sub. Otherwise the default engine is used.
|
684
|
-
|
685
700
|
*/
|
686
701
|
static VALUE iodine_pubsub_publish(int argc, VALUE *argv, VALUE self) {
|
687
702
|
// clang-format on
|
@@ -903,6 +918,7 @@ void iodine_connection_init(void) {
|
|
903
918
|
0);
|
904
919
|
rb_define_method(ConnectionKlass, "handler=", iodine_connection_handler_set,
|
905
920
|
1);
|
921
|
+
rb_define_method(ConnectionKlass, "pubsub?", iodine_connection_is_pubsub, 0);
|
906
922
|
rb_define_method(ConnectionKlass, "subscribe", iodine_pubsub_subscribe, -1);
|
907
923
|
rb_define_method(ConnectionKlass, "unsubscribe", iodine_pubsub_unsubscribe,
|
908
924
|
1);
|
data/ext/iodine/iodine_http.c
CHANGED
@@ -12,11 +12,15 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
12
12
|
#include <ruby/io.h>
|
13
13
|
// #include "iodine_websockets.h"
|
14
14
|
|
15
|
+
#ifndef __MINGW32__
|
15
16
|
#include <arpa/inet.h>
|
17
|
+
#endif
|
16
18
|
#include <ctype.h>
|
17
19
|
#include <stdlib.h>
|
18
20
|
#include <string.h>
|
21
|
+
#ifndef __MINGW32__
|
19
22
|
#include <sys/socket.h>
|
23
|
+
#endif
|
20
24
|
|
21
25
|
/* *****************************************************************************
|
22
26
|
Available Globals
|
@@ -51,7 +55,6 @@ static VALUE hijack_func_sym;
|
|
51
55
|
static ID close_method_id;
|
52
56
|
static ID each_method_id;
|
53
57
|
static ID attach_method_id;
|
54
|
-
static ID iodine_to_s_method_id;
|
55
58
|
static ID iodine_call_proc_id;
|
56
59
|
|
57
60
|
static VALUE env_template_no_upgrade;
|
@@ -294,9 +297,9 @@ static int iodine_copy2env_task(FIOBJ o, void *env_) {
|
|
294
297
|
|
295
298
|
} else {
|
296
299
|
/* it's an array */
|
297
|
-
VALUE ary = rb_ary_new();
|
298
|
-
rb_hash_aset(env, hname, ary);
|
299
300
|
size_t count = fiobj_ary_count(o);
|
301
|
+
VALUE ary = rb_ary_new2(count);
|
302
|
+
rb_hash_aset(env, hname, ary);
|
300
303
|
for (size_t i = 0; i < count; ++i) {
|
301
304
|
tmp = fiobj_obj2cstr(fiobj_ary_index(o, i));
|
302
305
|
rb_ary_push(ary, rb_enc_str_new(tmp.data, tmp.len, IodineBinaryEncoding));
|
@@ -476,11 +479,11 @@ static int for_each_header_data(VALUE key, VALUE val, VALUE h_) {
|
|
476
479
|
http_s *h = (http_s *)h_;
|
477
480
|
// fprintf(stderr, "For_each - headers\n");
|
478
481
|
if (TYPE(key) != T_STRING)
|
479
|
-
key = IodineCaller.call(key,
|
482
|
+
key = IodineCaller.call(key, iodine_to_s_id);
|
480
483
|
if (TYPE(key) != T_STRING)
|
481
484
|
return ST_CONTINUE;
|
482
485
|
if (TYPE(val) != T_STRING) {
|
483
|
-
val = IodineCaller.call(val,
|
486
|
+
val = IodineCaller.call(val, iodine_to_s_id);
|
484
487
|
if (TYPE(val) != T_STRING)
|
485
488
|
return ST_STOP;
|
486
489
|
}
|
@@ -556,9 +559,11 @@ static inline int ruby2c_response_send(iodine_http_request_handle_s *handle,
|
|
556
559
|
|
557
560
|
if (TYPE(body) == T_STRING) {
|
558
561
|
// fprintf(stderr, "Review body as String\n");
|
559
|
-
|
562
|
+
handle->type = IODINE_HTTP_NONE;
|
563
|
+
if (RSTRING_LEN(body)) {
|
560
564
|
handle->body = fiobj_str_new(RSTRING_PTR(body), RSTRING_LEN(body));
|
561
|
-
|
565
|
+
handle->type = IODINE_HTTP_SENDBODY;
|
566
|
+
}
|
562
567
|
return 0;
|
563
568
|
} else if (rb_respond_to(body, each_method_id)) {
|
564
569
|
// fprintf(stderr, "Review body as for-each ...\n");
|
@@ -937,6 +942,15 @@ intptr_t iodine_http_listen(iodine_connection_args_s args){
|
|
937
942
|
support_xsendfile = 1;
|
938
943
|
}
|
939
944
|
IodineStore.add(args.handler);
|
945
|
+
#ifdef __MINGW32__
|
946
|
+
intptr_t uuid = http_listen(
|
947
|
+
args.port.data, args.address.data, .on_request = on_rack_request,
|
948
|
+
.on_upgrade = on_rack_upgrade, .udata = (void *)args.handler,
|
949
|
+
.timeout = args.timeout, .ws_timeout = args.ping,
|
950
|
+
.ws_max_msg_size = args.max_msg, .max_header_size = args.max_headers,
|
951
|
+
.on_finish = free_iodine_http, .log = args.log,
|
952
|
+
.max_body_size = args.max_body, .public_folder = args.public.data);
|
953
|
+
#else
|
940
954
|
intptr_t uuid = http_listen(
|
941
955
|
args.port.data, args.address.data, .on_request = on_rack_request,
|
942
956
|
.on_upgrade = on_rack_upgrade, .udata = (void *)args.handler,
|
@@ -944,6 +958,7 @@ intptr_t iodine_http_listen(iodine_connection_args_s args){
|
|
944
958
|
.ws_max_msg_size = args.max_msg, .max_header_size = args.max_headers,
|
945
959
|
.on_finish = free_iodine_http, .log = args.log,
|
946
960
|
.max_body_size = args.max_body, .public_folder = args.public.data);
|
961
|
+
#endif
|
947
962
|
if (uuid == -1)
|
948
963
|
return uuid;
|
949
964
|
|
@@ -1053,9 +1068,11 @@ intptr_t iodine_ws_connect(iodine_connection_args_s args) {
|
|
1053
1068
|
FIOBJ url_tmp = FIOBJ_INVALID;
|
1054
1069
|
if (!args.url.data) {
|
1055
1070
|
url_tmp = fiobj_str_buf(64);
|
1071
|
+
#ifndef __MINGW32__
|
1056
1072
|
if (args.tls)
|
1057
1073
|
fiobj_str_write(url_tmp, "wss://", 6);
|
1058
1074
|
else
|
1075
|
+
#endif
|
1059
1076
|
fiobj_str_write(url_tmp, "ws://", 5);
|
1060
1077
|
if (!is_unix_socket) {
|
1061
1078
|
fiobj_str_write(url_tmp, args.address.data, args.address.len);
|
@@ -1071,11 +1088,19 @@ intptr_t iodine_ws_connect(iodine_connection_args_s args) {
|
|
1071
1088
|
args.url = fiobj_obj2cstr(url_tmp);
|
1072
1089
|
}
|
1073
1090
|
|
1091
|
+
#ifdef __MINGW32__
|
1092
|
+
intptr_t uuid = http_connect(
|
1093
|
+
args.url.data, (is_unix_socket ? args.address.data : NULL),
|
1094
|
+
.udata = request_data_create(&args),
|
1095
|
+
.on_response = ws_client_http_connected,
|
1096
|
+
.on_finish = ws_client_http_connection_finished);
|
1097
|
+
#else
|
1074
1098
|
intptr_t uuid = http_connect(
|
1075
1099
|
args.url.data, (is_unix_socket ? args.address.data : NULL),
|
1076
1100
|
.udata = request_data_create(&args),
|
1077
1101
|
.on_response = ws_client_http_connected,
|
1078
1102
|
.on_finish = ws_client_http_connection_finished, .tls = args.tls);
|
1103
|
+
#endif
|
1079
1104
|
fiobj_free(url_tmp);
|
1080
1105
|
return uuid;
|
1081
1106
|
}
|
@@ -1130,7 +1155,6 @@ void iodine_init_http(void) {
|
|
1130
1155
|
close_method_id = rb_intern("close");
|
1131
1156
|
each_method_id = rb_intern("each");
|
1132
1157
|
attach_method_id = rb_intern("attach_fd");
|
1133
|
-
iodine_to_s_method_id = rb_intern("to_s");
|
1134
1158
|
iodine_call_proc_id = rb_intern("call");
|
1135
1159
|
|
1136
1160
|
IodineUTF8Encoding = rb_enc_find("UTF-8");
|
@@ -8,7 +8,6 @@
|
|
8
8
|
#include <fio.h>
|
9
9
|
|
10
10
|
static ID call_func_id;
|
11
|
-
static ID to_s_func_id;
|
12
11
|
static VALUE filename_id;
|
13
12
|
static VALUE data_id;
|
14
13
|
static VALUE template_id;
|
@@ -169,7 +168,7 @@ static int mustache_on_arg(mustache_section_s *section, const char *name,
|
|
169
168
|
if (rb_respond_to(o, call_func_id))
|
170
169
|
o = IodineCaller.call(o, call_func_id);
|
171
170
|
if (!RB_TYPE_P(o, T_STRING))
|
172
|
-
o = IodineCaller.call(o,
|
171
|
+
o = IodineCaller.call(o, iodine_to_s_id);
|
173
172
|
}
|
174
173
|
if (!RB_TYPE_P(o, T_STRING) || !RSTRING_LEN(o))
|
175
174
|
return 0;
|
@@ -220,7 +219,7 @@ static int32_t mustache_on_section_test(mustache_section_s *section,
|
|
220
219
|
}
|
221
220
|
o = IodineCaller.call2(o, call_func_id, 1, &str);
|
222
221
|
if (!RB_TYPE_P(o, T_STRING))
|
223
|
-
o = rb_funcall2(o,
|
222
|
+
o = rb_funcall2(o, iodine_to_s_id, 0, NULL);
|
224
223
|
if (RB_TYPE_P(o, T_STRING) && RSTRING_LEN(o))
|
225
224
|
mustache_write_text(section, RSTRING_PTR(o), RSTRING_LEN(o), 0);
|
226
225
|
return 0;
|
@@ -553,7 +552,6 @@ Initialize Iodine::Mustache
|
|
553
552
|
|
554
553
|
void iodine_init_mustache(void) {
|
555
554
|
call_func_id = rb_intern2("call", 4);
|
556
|
-
to_s_func_id = rb_intern2("to_s", 4);
|
557
555
|
filename_id = rb_id2sym(rb_intern2("filename", 8));
|
558
556
|
data_id = rb_id2sym(rb_intern2("data", 4));
|
559
557
|
template_id = rb_id2sym(rb_intern2("template", 8));
|
data/ext/iodine/iodine_rack_io.c
CHANGED
@@ -61,6 +61,9 @@ static VALUE TCPSOCKET_CLASS;
|
|
61
61
|
static ID for_fd_id;
|
62
62
|
static ID iodine_fd_var_id;
|
63
63
|
static ID iodine_new_func_id;
|
64
|
+
#ifdef __MINGW32__
|
65
|
+
static ID iodine_osffd_id;
|
66
|
+
#endif
|
64
67
|
static rb_encoding *IodineUTF8Encoding;
|
65
68
|
static rb_encoding *IodineBinaryEncoding;
|
66
69
|
|
@@ -69,7 +72,11 @@ static rb_encoding *IodineBinaryEncoding;
|
|
69
72
|
|
70
73
|
inline static http_s *get_handle(VALUE obj) {
|
71
74
|
VALUE i = rb_ivar_get(obj, iodine_fd_var_id);
|
75
|
+
#ifdef __MINGW32__
|
76
|
+
return (http_s *)NUM2ULL(i);
|
77
|
+
#else
|
72
78
|
return (http_s *)FIX2ULONG(i);
|
79
|
+
#endif
|
73
80
|
}
|
74
81
|
|
75
82
|
/* *****************************************************************************
|
@@ -78,7 +85,11 @@ IO API
|
|
78
85
|
|
79
86
|
static inline FIOBJ get_data(VALUE self) {
|
80
87
|
VALUE i = rb_ivar_get(self, io_id);
|
88
|
+
#ifdef __MINGW32__
|
89
|
+
return (FIOBJ)NUM2ULL(i);
|
90
|
+
#else
|
81
91
|
return (FIOBJ)FIX2ULONG(i);
|
92
|
+
#endif
|
82
93
|
}
|
83
94
|
|
84
95
|
static VALUE rio_rewind(VALUE self) {
|
@@ -196,7 +207,14 @@ static VALUE rio_get_io(int argc, VALUE *argv, VALUE self) {
|
|
196
207
|
set_handle(self, NULL);
|
197
208
|
// hijack the IO object
|
198
209
|
intptr_t uuid = http_hijack(h, NULL);
|
210
|
+
#ifdef __MINGW32__
|
211
|
+
int osffd = fio_osffd4fd(fio_uuid2fd(uuid));
|
212
|
+
if (osffd == -1)
|
213
|
+
return Qfalse;
|
214
|
+
VALUE fd = INT2FIX(osffd);
|
215
|
+
#else
|
199
216
|
VALUE fd = INT2FIX(fio_uuid2fd(uuid));
|
217
|
+
#endif
|
200
218
|
// VALUE new_io = how the fuck do we create a new IO from the fd?
|
201
219
|
VALUE new_io = IodineCaller.call2(TCPSOCKET_CLASS, for_fd_id, 1,
|
202
220
|
&fd); // TCPSocket.for_fd(fd) ... cool...
|
@@ -238,6 +256,9 @@ static void init_rack_io(void) {
|
|
238
256
|
for_fd_id = rb_intern("for_fd");
|
239
257
|
iodine_fd_var_id = rb_intern("fd");
|
240
258
|
iodine_new_func_id = rb_intern("new");
|
259
|
+
#ifdef __MINGW32__
|
260
|
+
iodine_osffd_id = rb_intern("osffd");
|
261
|
+
#endif
|
241
262
|
hijack_func_sym = ID2SYM(rb_intern("_hijack"));
|
242
263
|
|
243
264
|
TCPSOCKET_CLASS = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
data/ext/iodine/iodine_tcp.c
CHANGED
@@ -209,10 +209,17 @@ Returns the handler object used.
|
|
209
209
|
intptr_t iodine_tcp_listen(iodine_connection_args_s args) {
|
210
210
|
// clang-format on
|
211
211
|
IodineStore.add(args.handler);
|
212
|
+
#ifdef __MINGW32__
|
213
|
+
return fio_listen(.port = args.port.data, .address = args.address.data,
|
214
|
+
.on_open = iodine_tcp_on_open,
|
215
|
+
.on_finish = iodine_tcp_on_finish,
|
216
|
+
.udata = (void *)args.handler);
|
217
|
+
#else
|
212
218
|
return fio_listen(.port = args.port.data, .address = args.address.data,
|
213
219
|
.on_open = iodine_tcp_on_open,
|
214
220
|
.on_finish = iodine_tcp_on_finish, .tls = args.tls,
|
215
221
|
.udata = (void *)args.handler);
|
222
|
+
#endif
|
216
223
|
}
|
217
224
|
|
218
225
|
// clang-format off
|
@@ -238,10 +245,17 @@ Returns the handler object used.
|
|
238
245
|
intptr_t iodine_tcp_connect(iodine_connection_args_s args){
|
239
246
|
// clang-format on
|
240
247
|
IodineStore.add(args.handler);
|
248
|
+
#ifdef __MINGW32__
|
249
|
+
return fio_connect(.port = args.port.data, .address = args.address.data,
|
250
|
+
.on_connect = iodine_tcp_on_connect,
|
251
|
+
.on_fail = iodine_tcp_on_fail, .timeout = args.ping,
|
252
|
+
.udata = (void *)args.handler);
|
253
|
+
#else
|
241
254
|
return fio_connect(.port = args.port.data, .address = args.address.data,
|
242
255
|
.on_connect = iodine_tcp_on_connect, .tls = args.tls,
|
243
256
|
.on_fail = iodine_tcp_on_fail, .timeout = args.ping,
|
244
257
|
.udata = (void *)args.handler);
|
258
|
+
#endif
|
245
259
|
}
|
246
260
|
|
247
261
|
// clang-format off
|
data/ext/iodine/iodine_tls.c
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
#ifdef __MINGW32__
|
2
|
+
// make pedantic compiler happy
|
3
|
+
typedef struct {
|
4
|
+
int bogus;
|
5
|
+
} bogus_s;
|
6
|
+
|
7
|
+
#else
|
1
8
|
#include <ruby.h>
|
2
9
|
|
3
10
|
#include <fio.h>
|
@@ -251,3 +258,4 @@ void iodine_init_tls(void) {
|
|
251
258
|
#endif
|
252
259
|
}
|
253
260
|
#undef IODINE_MAKE_SYM
|
261
|
+
#endif
|
@@ -28,6 +28,10 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
28
28
|
#include <sys/stat.h>
|
29
29
|
#include <sys/types.h>
|
30
30
|
|
31
|
+
#ifdef __MINGW32__
|
32
|
+
ssize_t pread(int, void*, size_t, off_t);
|
33
|
+
#endif
|
34
|
+
|
31
35
|
#if !defined(__GNUC__) && !defined(__clang__) && !defined(FIO_GNUC_BYPASS)
|
32
36
|
#define __attribute__(...)
|
33
37
|
#define __has_include(...) 0
|