iodine 0.7.41 → 0.7.45
Sign up to get free protection for your applications and to get access to all the features.
- 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
|