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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +24 -0
  5. data/README.md +2 -2
  6. data/SPEC-PubSub-Draft.md +89 -47
  7. data/SPEC-WebSocket-Draft.md +92 -55
  8. data/examples/async_task.ru +92 -0
  9. data/ext/iodine/extconf.rb +21 -16
  10. data/ext/iodine/fio.c +1108 -162
  11. data/ext/iodine/fio.h +49 -13
  12. data/ext/iodine/fio_cli.c +1 -1
  13. data/ext/iodine/fio_tls_missing.c +8 -0
  14. data/ext/iodine/fio_tls_openssl.c +8 -0
  15. data/ext/iodine/fio_tmpfile.h +13 -1
  16. data/ext/iodine/fiobj_data.c +6 -4
  17. data/ext/iodine/fiobj_data.h +2 -1
  18. data/ext/iodine/fiobj_hash.c +32 -6
  19. data/ext/iodine/fiobj_mustache.c +9 -0
  20. data/ext/iodine/fiobj_numbers.c +86 -8
  21. data/ext/iodine/fiobj_str.c +24 -11
  22. data/ext/iodine/fiobject.c +1 -1
  23. data/ext/iodine/fiobject.h +5 -3
  24. data/ext/iodine/http.c +66 -10
  25. data/ext/iodine/http1.c +2 -1
  26. data/ext/iodine/http1_parser.h +1065 -103
  27. data/ext/iodine/http_internal.c +1 -0
  28. data/ext/iodine/http_internal.h +4 -2
  29. data/ext/iodine/iodine.c +66 -1
  30. data/ext/iodine/iodine.h +3 -0
  31. data/ext/iodine/iodine_caller.c +48 -8
  32. data/ext/iodine/iodine_connection.c +24 -8
  33. data/ext/iodine/iodine_http.c +32 -8
  34. data/ext/iodine/iodine_mustache.c +2 -4
  35. data/ext/iodine/iodine_rack_io.c +21 -0
  36. data/ext/iodine/iodine_tcp.c +14 -0
  37. data/ext/iodine/iodine_tls.c +8 -0
  38. data/ext/iodine/mustache_parser.h +4 -0
  39. data/ext/iodine/redis_engine.c +14 -11
  40. data/ext/iodine/websockets.c +7 -3
  41. data/iodine.gemspec +5 -4
  42. data/lib/iodine/version.rb +1 -1
  43. data/lib/rack/handler/iodine.rb +6 -0
  44. metadata +15 -13
@@ -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, (uint64_t)eng);
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, (uint64_t)engine);
792
- fio_u2str64(ti.data + 8, (uint64_t)callback);
793
- fio_u2str64(ti.data + 16, (uint64_t)udata);
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),
@@ -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', '~> 12.0', '< 13.0'
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'
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '0.7.41'.freeze
2
+ VERSION = '0.7.45'.freeze
3
3
  end
@@ -14,6 +14,12 @@ module Iodine
14
14
 
15
15
  true
16
16
  end
17
+
18
+ # patches an assumption by Rack, issue #98 code donated by @Shelvak (Néstor Coppi)
19
+ def self.shutdown
20
+ Iodine.stop
21
+ end
22
+
17
23
  IODINE_RACK_LOADED = true
18
24
  end
19
25
  end
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.41
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: 2020-07-23 00:00:00.000000000 Z
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: '13.0'
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: '13.0'
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.41.
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
- rubygems_version: 3.1.2
269
- signing_key:
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: []