iodine 0.7.41 → 0.7.45

Sign up to get free protection for your applications and to get access to all the features.
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: []