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/redis_engine.c
CHANGED
@@ -493,6 +493,7 @@ static void redis_pub_ping(intptr_t uuid, fio_protocol_s *pr) {
|
|
493
493
|
return;
|
494
494
|
}
|
495
495
|
redis_commands_s *cmd = fio_malloc(sizeof(*cmd) + 15);
|
496
|
+
FIO_ASSERT_ALLOC(cmd);
|
496
497
|
*cmd = (redis_commands_s){.cmd_len = 14};
|
497
498
|
memcpy(cmd->cmd, "*1\r\n$4\r\nPING\r\n\0", 15);
|
498
499
|
redis_attach_cmd(r, cmd);
|
@@ -534,6 +535,7 @@ static void redis_on_connect(intptr_t uuid, void *i_) {
|
|
534
535
|
r = pub2redis(i);
|
535
536
|
if (r->auth_len) {
|
536
537
|
redis_commands_s *cmd = fio_malloc(sizeof(*cmd) + r->auth_len);
|
538
|
+
FIO_ASSERT_ALLOC(cmd);
|
537
539
|
*cmd =
|
538
540
|
(redis_commands_s){.cmd_len = r->auth_len, .callback = redis_on_auth};
|
539
541
|
memcpy(cmd->cmd, r->auth, r->auth_len);
|
@@ -638,6 +640,7 @@ static void redis_on_publish_root(const fio_pubsub_engine_s *eng,
|
|
638
640
|
uint8_t is_json) {
|
639
641
|
redis_engine_s *r = (redis_engine_s *)eng;
|
640
642
|
redis_commands_s *cmd = fio_malloc(sizeof(*cmd) + channel.len + msg.len + 96);
|
643
|
+
FIO_ASSERT_ALLOC(cmd);
|
641
644
|
*cmd = (redis_commands_s){.cmd_len = 0};
|
642
645
|
memcpy(cmd->cmd, "*3\r\n$7\r\nPUBLISH\r\n$", 18);
|
643
646
|
char *buf = (char *)cmd->cmd + 18;
|
@@ -684,7 +687,7 @@ static void redis_on_publish_child(const fio_pubsub_engine_s *eng,
|
|
684
687
|
fio_str_s tmp = FIO_STR_INIT;
|
685
688
|
/* by using fio_str_s, short names are allocated on the stack */
|
686
689
|
fio_str_info_s tmp_info = fio_str_resize(&tmp, channel.len + 8);
|
687
|
-
fio_u2str64(tmp_info.data, (
|
690
|
+
fio_u2str64(tmp_info.data, (uintptr_t)eng);
|
688
691
|
memcpy(tmp_info.data + 8, channel.data, channel.len);
|
689
692
|
/* forward publication request to Root */
|
690
693
|
fio_publish(.filter = -1, .channel = tmp_info, .message = msg,
|
@@ -701,7 +704,7 @@ Root Publication Handler
|
|
701
704
|
static void redis_on_internal_publish(fio_msg_s *msg) {
|
702
705
|
if (msg->channel.len < 8)
|
703
706
|
return; /* internal error, unexpected data */
|
704
|
-
void *en = (void *)fio_str2u64(msg->channel.data);
|
707
|
+
void *en = (void *)(uintptr_t)fio_str2u64(msg->channel.data);
|
705
708
|
if (en != msg->udata1)
|
706
709
|
return; /* should be delivered by a different engine */
|
707
710
|
/* step after the engine data */
|
@@ -721,8 +724,8 @@ Sending commands using the Root connection
|
|
721
724
|
static void redis_forward_reply(fio_pubsub_engine_s *e, FIOBJ reply,
|
722
725
|
void *udata) {
|
723
726
|
uint8_t *data = udata;
|
724
|
-
fio_pubsub_engine_s *engine = (fio_pubsub_engine_s *)fio_str2u64(data + 0);
|
725
|
-
void *callback = (void *)fio_str2u64(data + 8);
|
727
|
+
fio_pubsub_engine_s *engine = (fio_pubsub_engine_s *)(uintptr_t)fio_str2u64(data + 0);
|
728
|
+
void *callback = (void *)(uintptr_t)fio_str2u64(data + 8);
|
726
729
|
if (engine != e || !callback) {
|
727
730
|
FIO_LOG_DEBUG("Redis reply not forwarded (callback: %p)", callback);
|
728
731
|
return;
|
@@ -738,7 +741,7 @@ static void redis_forward_reply(fio_pubsub_engine_s *e, FIOBJ reply,
|
|
738
741
|
static void redis_on_internal_cmd(fio_msg_s *msg) {
|
739
742
|
// void*(void *)fio_str2u64(msg->msg.data);
|
740
743
|
fio_pubsub_engine_s *engine =
|
741
|
-
(fio_pubsub_engine_s *)fio_str2u64(msg->channel.data + 0);
|
744
|
+
(fio_pubsub_engine_s *)(uintptr_t)fio_str2u64(msg->channel.data + 0);
|
742
745
|
if (engine != msg->udata1) {
|
743
746
|
return;
|
744
747
|
}
|
@@ -756,7 +759,7 @@ static void redis_on_internal_cmd(fio_msg_s *msg) {
|
|
756
759
|
/* Listens on filter `-10 -getpid()` for incoming reply data */
|
757
760
|
static void redis_on_internal_reply(fio_msg_s *msg) {
|
758
761
|
fio_pubsub_engine_s *engine =
|
759
|
-
(fio_pubsub_engine_s *)fio_str2u64(msg->channel.data + 0);
|
762
|
+
(fio_pubsub_engine_s *)(uintptr_t)fio_str2u64(msg->channel.data + 0);
|
760
763
|
if (engine != msg->udata1) {
|
761
764
|
FIO_LOG_DEBUG("Redis reply not forwarded (engine mismatch: %p != %p)",
|
762
765
|
(void *)engine, msg->udata1);
|
@@ -765,8 +768,8 @@ static void redis_on_internal_reply(fio_msg_s *msg) {
|
|
765
768
|
FIOBJ reply;
|
766
769
|
fiobj_json2obj(&reply, msg->msg.data, msg->msg.len);
|
767
770
|
void (*callback)(fio_pubsub_engine_s *, FIOBJ, void *) = (void (*)(
|
768
|
-
fio_pubsub_engine_s *, FIOBJ, void *))fio_str2u64(msg->channel.data + 8);
|
769
|
-
void *udata = (void *)fio_str2u64(msg->channel.data + 16);
|
771
|
+
fio_pubsub_engine_s *, FIOBJ, void *))(uintptr_t)fio_str2u64(msg->channel.data + 8);
|
772
|
+
void *udata = (void *)(uintptr_t)fio_str2u64(msg->channel.data + 16);
|
770
773
|
callback(engine, reply, udata);
|
771
774
|
fiobj_free(reply);
|
772
775
|
}
|
@@ -788,9 +791,9 @@ intptr_t redis_engine_send(fio_pubsub_engine_s *engine, FIOBJ command,
|
|
788
791
|
fio_str_s tmp = FIO_STR_INIT;
|
789
792
|
fio_str_info_s ti = fio_str_resize(&tmp, 28);
|
790
793
|
/* combine metadata */
|
791
|
-
fio_u2str64(ti.data + 0, (
|
792
|
-
fio_u2str64(ti.data + 8, (
|
793
|
-
fio_u2str64(ti.data + 16, (
|
794
|
+
fio_u2str64(ti.data + 0, (uintptr_t)engine);
|
795
|
+
fio_u2str64(ti.data + 8, (uintptr_t)callback);
|
796
|
+
fio_u2str64(ti.data + 16, (uintptr_t)udata);
|
794
797
|
fio_u2str32(ti.data + 24, (uint32_t)getpid());
|
795
798
|
FIOBJ cmd = fiobj2resp_tmp(command);
|
796
799
|
fio_publish(.filter = -2, .channel = ti, .message = fiobj_obj2cstr(cmd),
|
data/ext/iodine/websockets.c
CHANGED
@@ -17,7 +17,9 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
17
17
|
#include <http.h>
|
18
18
|
#include <http_internal.h>
|
19
19
|
|
20
|
+
#ifndef __MINGW32__
|
20
21
|
#include <arpa/inet.h>
|
22
|
+
#endif
|
21
23
|
#include <errno.h>
|
22
24
|
#include <stdio.h>
|
23
25
|
#include <stdlib.h>
|
@@ -26,7 +28,7 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
26
28
|
|
27
29
|
#include <websocket_parser.h>
|
28
30
|
|
29
|
-
#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
|
31
|
+
#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) && !defined(__MINGW32__)
|
30
32
|
#include <endian.h>
|
31
33
|
#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) && \
|
32
34
|
__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
@@ -71,6 +73,7 @@ struct buffer_s create_ws_buffer(ws_s *owner) {
|
|
71
73
|
struct buffer_s buff;
|
72
74
|
buff.size = WS_INITIAL_BUFFER_SIZE;
|
73
75
|
buff.data = malloc(buff.size);
|
76
|
+
FIO_ASSERT_ALLOC(buff.data);
|
74
77
|
return buff;
|
75
78
|
}
|
76
79
|
|
@@ -79,7 +82,6 @@ struct buffer_s resize_ws_buffer(ws_s *owner, struct buffer_s buff) {
|
|
79
82
|
void *tmp = realloc(buff.data, buff.size);
|
80
83
|
if (!tmp) {
|
81
84
|
free_ws_buffer(owner, buff);
|
82
|
-
buff.data = NULL;
|
83
85
|
buff.size = 0;
|
84
86
|
}
|
85
87
|
buff.data = tmp;
|
@@ -174,6 +176,7 @@ static void websocket_on_protocol_ping(void *ws_p, void *msg_, uint64_t len) {
|
|
174
176
|
ws_s *ws = ws_p;
|
175
177
|
if (msg_) {
|
176
178
|
void *buff = malloc(len + 16);
|
179
|
+
FIO_ASSERT_ALLOC(buff);
|
177
180
|
len = (((ws_s *)ws)->is_client
|
178
181
|
? websocket_client_wrap(buff, msg_, len, 10, 1, 1, 0)
|
179
182
|
: websocket_server_wrap(buff, msg_, len, 10, 1, 1, 0));
|
@@ -305,6 +308,7 @@ Create/Destroy the websocket object
|
|
305
308
|
static ws_s *new_websocket(intptr_t uuid) {
|
306
309
|
// allocate the protocol object
|
307
310
|
ws_s *ws = malloc(sizeof(*ws));
|
311
|
+
FIO_ASSERT_ALLOC(ws);
|
308
312
|
*ws = (ws_s){
|
309
313
|
.protocol.ping = ws_ping,
|
310
314
|
.protocol.on_data = on_data_first,
|
@@ -330,7 +334,6 @@ static void destroy_ws(ws_s *ws) {
|
|
330
334
|
void websocket_attach(intptr_t uuid, http_settings_s *http_settings,
|
331
335
|
websocket_settings_s *args, void *data, size_t length) {
|
332
336
|
ws_s *ws = new_websocket(uuid);
|
333
|
-
FIO_ASSERT_ALLOC(ws);
|
334
337
|
// we have an active websocket connection - prep the connection buffer
|
335
338
|
ws->buffer = create_ws_buffer(ws);
|
336
339
|
// Setup ws callbacks
|
@@ -383,6 +386,7 @@ static void websocket_write_impl(intptr_t fd, void *data, size_t len, char text,
|
|
383
386
|
char first, char last, char client) {
|
384
387
|
if (len <= WS_MAX_FRAME_SIZE) {
|
385
388
|
void *buff = fio_malloc(len + 16);
|
389
|
+
FIO_ASSERT_ALLOC(buff);
|
386
390
|
len = (client ? websocket_client_wrap(buff, data, len, (text ? 1 : 2),
|
387
391
|
first, last, 0)
|
388
392
|
: websocket_server_wrap(buff, data, len, (text ? 1 : 2),
|
data/iodine.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ['Boaz Segev']
|
10
10
|
spec.email = ['bo@plezi.io']
|
11
11
|
|
12
|
-
spec.summary = 'iodine - a fast HTTP / Websocket Server with Pub/Sub support, optimized for Ruby MRI on Linux / BSD'
|
13
|
-
spec.description = 'A fast HTTP / Websocket Server with built-in Pub/Sub support (with or without Redis), static file support and many other features, optimized for Ruby MRI on Linux / BSD / macOS'
|
12
|
+
spec.summary = 'iodine - a fast HTTP / Websocket Server with Pub/Sub support, optimized for Ruby MRI on Linux / BSD / Windows'
|
13
|
+
spec.description = 'A fast HTTP / Websocket Server with built-in Pub/Sub support (with or without Redis), static file support and many other features, optimized for Ruby MRI on Linux / BSD / macOS / Windows'
|
14
14
|
spec.homepage = 'https://github.com/boazsegev/iodine'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
@@ -35,10 +35,11 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.requirements << 'An updated C compiler.'
|
36
36
|
spec.requirements << 'Ruby >= 2.3.8 (Ruby EOL).'
|
37
37
|
spec.requirements << 'Ruby >= 2.5.0 recommended.'
|
38
|
-
spec.requirements << 'TLS requires OpenSSL >= 1.1.0'
|
38
|
+
spec.requirements << 'TLS requires OpenSSL >= 1.1.0.'
|
39
|
+
spec.requirements << 'Or Windows with Ruby >= 3.0.0 build with MingW and MingW as compiler.'
|
39
40
|
|
40
41
|
# spec.add_development_dependency 'bundler', '>= 1.10', '< 2.0'
|
41
|
-
spec.add_development_dependency 'rake', '
|
42
|
+
spec.add_development_dependency 'rake', '>= 12.0', '< 14.0'
|
42
43
|
spec.add_development_dependency 'minitest', '>=5', '< 6.0'
|
43
44
|
spec.add_development_dependency 'rspec', '>=3.9.0', '< 4.0'
|
44
45
|
spec.add_development_dependency 'spec', '>=5.3.0', '< 6.0'
|
data/lib/iodine/version.rb
CHANGED
data/lib/rack/handler/iodine.rb
CHANGED
metadata
CHANGED
@@ -1,35 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iodine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.45
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boaz Segev
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '12.0'
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '14.0'
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
|
-
- - "
|
27
|
+
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '12.0'
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '14.0'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: minitest
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,7 +112,7 @@ dependencies:
|
|
112
112
|
version: '2.0'
|
113
113
|
description: A fast HTTP / Websocket Server with built-in Pub/Sub support (with or
|
114
114
|
without Redis), static file support and many other features, optimized for Ruby
|
115
|
-
MRI on Linux / BSD / macOS
|
115
|
+
MRI on Linux / BSD / macOS / Windows
|
116
116
|
email:
|
117
117
|
- bo@plezi.io
|
118
118
|
executables:
|
@@ -142,6 +142,7 @@ files:
|
|
142
142
|
- bin/poc/config.ru
|
143
143
|
- bin/poc/gemfile
|
144
144
|
- bin/poc/www/index.html
|
145
|
+
- examples/async_task.ru
|
145
146
|
- examples/config.ru
|
146
147
|
- examples/echo.ru
|
147
148
|
- examples/hello.ru
|
@@ -243,7 +244,7 @@ licenses:
|
|
243
244
|
metadata:
|
244
245
|
allowed_push_host: https://rubygems.org
|
245
246
|
post_install_message: |-
|
246
|
-
Thank you for installing Iodine 0.7.
|
247
|
+
Thank you for installing Iodine 0.7.45.
|
247
248
|
Remember: if iodine supports your business, it's only fair to give value back (code contributions / donations).
|
248
249
|
rdoc_options: []
|
249
250
|
require_paths:
|
@@ -264,10 +265,11 @@ requirements:
|
|
264
265
|
- An updated C compiler.
|
265
266
|
- Ruby >= 2.3.8 (Ruby EOL).
|
266
267
|
- Ruby >= 2.5.0 recommended.
|
267
|
-
- TLS requires OpenSSL >= 1.1.0
|
268
|
-
|
269
|
-
|
268
|
+
- TLS requires OpenSSL >= 1.1.0.
|
269
|
+
- Or Windows with Ruby >= 3.0.0 build with MingW and MingW as compiler.
|
270
|
+
rubygems_version: 3.2.3
|
271
|
+
signing_key:
|
270
272
|
specification_version: 4
|
271
273
|
summary: iodine - a fast HTTP / Websocket Server with Pub/Sub support, optimized for
|
272
|
-
Ruby MRI on Linux / BSD
|
274
|
+
Ruby MRI on Linux / BSD / Windows
|
273
275
|
test_files: []
|