isomorfeus-iodine 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -518,10 +518,10 @@ static iodine_sub_args_s iodine_subscribe_args(int argc, VALUE *argv) {
518
518
  /* single argument must be a Hash / channel name */
519
519
  if (TYPE(argv[0]) == T_HASH) {
520
520
  rb_opt = argv[0];
521
- ret.channel = rb_hash_aref(argv[0], to_id);
521
+ ret.channel = rb_hash_aref(argv[0], ID2SYM(to_id));
522
522
  if (ret.channel == Qnil || ret.channel == Qfalse) {
523
523
  /* temporary backport support */
524
- ret.channel = rb_hash_aref(argv[0], channel_id);
524
+ ret.channel = rb_hash_aref(argv[0], ID2SYM(channel_id));
525
525
  if (ret.channel != Qnil) {
526
526
  FIO_LOG_WARNING("use of :channel in subscribe is deprecated.");
527
527
  }
@@ -546,13 +546,16 @@ static iodine_sub_args_s iodine_subscribe_args(int argc, VALUE *argv) {
546
546
  Check_Type(ret.channel, T_STRING);
547
547
 
548
548
  if (rb_opt) {
549
- if (rb_hash_aref(rb_opt, as_id) == binary_id) {
549
+ VALUE tmp = Qnil;
550
+ if ((tmp = rb_hash_aref(rb_opt, ID2SYM(as_id))) != Qnil &&
551
+ TYPE(tmp) == T_SYMBOL && rb_sym2id(tmp) == binary_id) {
550
552
  ret.binary = 1;
551
553
  }
552
- if (rb_hash_aref(rb_opt, match_id) == redis_id) {
554
+ if ((tmp = rb_hash_aref(rb_opt, ID2SYM(match_id))) != Qnil &&
555
+ TYPE(tmp) == T_SYMBOL && rb_sym2id(tmp) == redis_id) {
553
556
  ret.pattern = FIO_MATCH_GLOB;
554
557
  }
555
- ret.block = rb_hash_aref(rb_opt, handler_id);
558
+ ret.block = rb_hash_aref(rb_opt, ID2SYM(handler_id));
556
559
  if (ret.block != Qnil) {
557
560
  IodineStore.add(ret.block);
558
561
  }
@@ -900,7 +903,8 @@ void iodine_connection_init(void) {
900
903
  IodineStore.add(RAWSymbol);
901
904
 
902
905
  // define the Connection Class and it's methods
903
- ConnectionKlass = rb_define_class_under(IodineModule, "Connection", rb_cObject);
906
+ ConnectionKlass =
907
+ rb_define_class_under(IodineModule, "Connection", rb_cObject);
904
908
  rb_define_alloc_func(ConnectionKlass, iodine_connection_data_alloc_c);
905
909
  rb_define_method(ConnectionKlass, "write", iodine_connection_write, 1);
906
910
  rb_define_method(ConnectionKlass, "close", iodine_connection_close, 0);
@@ -477,6 +477,10 @@ Handling the HTTP response
477
477
  static int for_each_header_data(VALUE key, VALUE val, VALUE h_) {
478
478
  http_s *h = (http_s *)h_;
479
479
  // fprintf(stderr, "For_each - headers\n");
480
+ if (TYPE(val) == T_NIL || TYPE(key) == T_NIL)
481
+ return ST_CONTINUE;
482
+ if (TYPE(val) == T_ARRAY)
483
+ goto array_style_multi_value;
480
484
  if (TYPE(key) != T_STRING)
481
485
  key = IodineCaller.call(key, iodine_to_s_id);
482
486
  if (TYPE(key) != T_STRING)
@@ -515,6 +519,14 @@ static int for_each_header_data(VALUE key, VALUE val, VALUE h_) {
515
519
  fiobj_free(name);
516
520
  // no errors, return 0
517
521
  return ST_CONTINUE;
522
+
523
+ array_style_multi_value:
524
+ for (size_t i = 0, end = RARRAY_LEN(val); i < end; ++i) {
525
+ if (for_each_header_data(key, RARRAY_AREF(val, i), h_) == ST_CONTINUE)
526
+ continue;
527
+ return ST_STOP;
528
+ }
529
+ return ST_CONTINUE;
518
530
  }
519
531
 
520
532
  // writes the body to the response object
@@ -941,15 +953,15 @@ intptr_t iodine_http_listen(iodine_connection_args_s args){
941
953
  support_xsendfile = 1;
942
954
  }
943
955
  IodineStore.add(args.handler);
944
- #ifdef __MINGW32__
945
- intptr_t uuid = http_listen(
956
+ #ifdef __MINGW32__
957
+ intptr_t uuid = http_listen(
946
958
  args.port.data, args.address.data, .on_request = on_rack_request,
947
959
  .on_upgrade = on_rack_upgrade, .udata = (void *)args.handler,
948
960
  .timeout = args.timeout, .ws_timeout = args.ping,
949
961
  .ws_max_msg_size = args.max_msg, .max_header_size = args.max_headers,
950
962
  .on_finish = free_iodine_http, .log = args.log,
951
963
  .max_body_size = args.max_body, .public_folder = args.public.data);
952
- #else
964
+ #else
953
965
  intptr_t uuid = http_listen(
954
966
  args.port.data, args.address.data, .on_request = on_rack_request,
955
967
  .on_upgrade = on_rack_upgrade, .udata = (void *)args.handler,
@@ -957,7 +969,7 @@ intptr_t iodine_http_listen(iodine_connection_args_s args){
957
969
  .ws_max_msg_size = args.max_msg, .max_header_size = args.max_headers,
958
970
  .on_finish = free_iodine_http, .log = args.log,
959
971
  .max_body_size = args.max_body, .public_folder = args.public.data);
960
- #endif
972
+ #endif
961
973
  if (uuid == -1)
962
974
  return uuid;
963
975
 
@@ -1067,11 +1079,11 @@ intptr_t iodine_ws_connect(iodine_connection_args_s args) {
1067
1079
  FIOBJ url_tmp = FIOBJ_INVALID;
1068
1080
  if (!args.url.data) {
1069
1081
  url_tmp = fiobj_str_buf(64);
1070
- #ifndef __MINGW32__
1082
+ #ifndef __MINGW32__
1071
1083
  if (args.tls)
1072
1084
  fiobj_str_write(url_tmp, "wss://", 6);
1073
1085
  else
1074
- #endif
1086
+ #endif
1075
1087
  fiobj_str_write(url_tmp, "ws://", 5);
1076
1088
  if (!is_unix_socket) {
1077
1089
  fiobj_str_write(url_tmp, args.address.data, args.address.len);
@@ -1088,11 +1100,11 @@ intptr_t iodine_ws_connect(iodine_connection_args_s args) {
1088
1100
  }
1089
1101
 
1090
1102
  #ifdef __MINGW32__
1091
- intptr_t uuid = http_connect(
1092
- args.url.data, (is_unix_socket ? args.address.data : NULL),
1093
- .udata = request_data_create(&args),
1094
- .on_response = ws_client_http_connected,
1095
- .on_finish = ws_client_http_connection_finished);
1103
+ intptr_t uuid =
1104
+ http_connect(args.url.data, (is_unix_socket ? args.address.data : NULL),
1105
+ .udata = request_data_create(&args),
1106
+ .on_response = ws_client_http_connected,
1107
+ .on_finish = ws_client_http_connection_finished);
1096
1108
  #else
1097
1109
  intptr_t uuid = http_connect(
1098
1110
  args.url.data, (is_unix_socket ? args.address.data : NULL),
@@ -453,6 +453,7 @@ static uint64_t websocket_consume(void *buffer, uint64_t len, void *udata,
453
453
  fprintf(stderr, "ERROR: WebSocket protocol error - unmasked data.\n");
454
454
  #endif
455
455
  websocket_on_protocol_error(udata);
456
+ return 0;
456
457
  }
457
458
  /* call callback */
458
459
  switch (pos[0] & 15) {
@@ -28,7 +28,8 @@ Feel free to copy, use and enjoy according to the license provided.
28
28
 
29
29
  #include <websocket_parser.h>
30
30
 
31
- #if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) && !defined(__MINGW32__)
31
+ #if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) && \
32
+ !defined(__MINGW32__)
32
33
  #include <endian.h>
33
34
  #if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) && \
34
35
  __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
@@ -126,6 +127,8 @@ struct ws_s {
126
127
  struct buffer_s buffer;
127
128
  /** data length (how much of the buffer actually used). */
128
129
  size_t length;
130
+ /** total data length (including continuation frames). */
131
+ size_t total_length;
129
132
  /** message buffer. */
130
133
  FIOBJ msg;
131
134
  /** latest text state. */
@@ -154,20 +157,24 @@ static void websocket_on_unwrapped(void *ws_p, void *msg, uint64_t len,
154
157
  char first, char last, char text,
155
158
  unsigned char rsv) {
156
159
  ws_s *ws = ws_p;
160
+ if (!ws)
161
+ return;
157
162
  if (last && first) {
158
163
  ws->on_message(ws, (fio_str_info_s){.data = msg, .len = len},
159
164
  (uint8_t)text);
160
165
  return;
161
166
  }
167
+ if (ws->msg == FIOBJ_INVALID)
168
+ ws->msg = fiobj_str_buf(len);
169
+ ws->total_length += len;
162
170
  if (first) {
163
171
  ws->is_text = (uint8_t)text;
164
- if (ws->msg == FIOBJ_INVALID)
165
- ws->msg = fiobj_str_buf(len);
166
- fiobj_str_resize(ws->msg, 0);
167
172
  }
168
173
  fiobj_str_write(ws->msg, msg, len);
169
174
  if (last) {
170
175
  ws->on_message(ws, fiobj_obj2cstr(ws->msg), ws->is_text);
176
+ fiobj_str_resize(ws->msg, 0);
177
+ ws->total_length = 0;
171
178
  }
172
179
 
173
180
  (void)rsv;
@@ -183,15 +190,19 @@ static void websocket_on_protocol_ping(void *ws_p, void *msg_, uint64_t len) {
183
190
  fio_write2(ws->fd, .data.buffer = buff, .length = len);
184
191
  } else {
185
192
  if (((ws_s *)ws)->is_client) {
186
- fio_write2(ws->fd, .data.buffer = "\x89\x80mask", .length = 2,
193
+ fio_write2(ws->fd, .data.buffer = "\x8a\x80mask", .length = 6,
187
194
  .after.dealloc = FIO_DEALLOC_NOOP);
188
195
  } else {
189
- fio_write2(ws->fd, .data.buffer = "\x89\x00", .length = 2,
196
+ fio_write2(ws->fd, .data.buffer = "\x8a\x00", .length = 2,
190
197
  .after.dealloc = FIO_DEALLOC_NOOP);
191
198
  }
192
199
  }
200
+ FIO_LOG_DEBUG("Received ping and sent pong for Websocket %p (%d)", ws_p,
201
+ (int)(((ws_s *)ws_p)->fd));
193
202
  }
194
203
  static void websocket_on_protocol_pong(void *ws_p, void *msg, uint64_t len) {
204
+ FIO_LOG_DEBUG("Received pong for Websocket %p (%d)", ws_p,
205
+ (int)(((ws_s *)ws_p)->fd));
195
206
  (void)len;
196
207
  (void)msg;
197
208
  (void)ws_p;
@@ -220,6 +231,7 @@ static void ws_ping(intptr_t fd, fio_protocol_s *ws) {
220
231
  fio_write2(fd, .data.buffer = "\x89\x00", .length = 2,
221
232
  .after.dealloc = FIO_DEALLOC_NOOP);
222
233
  }
234
+ FIO_LOG_DEBUG("Sent ping for Websocket %p (%d)", (void *)ws, (int)fd);
223
235
  }
224
236
 
225
237
  static void on_close(intptr_t uuid, fio_protocol_s *_ws) {
@@ -238,10 +250,10 @@ static uint8_t on_shutdown(intptr_t fd, fio_protocol_s *ws) {
238
250
  if (ws && ((ws_s *)ws)->on_shutdown)
239
251
  ((ws_s *)ws)->on_shutdown((ws_s *)ws);
240
252
  if (((ws_s *)ws)->is_client) {
241
- fio_write2(fd, .data.buffer = "\x8a\x80MASK", .length = 6,
253
+ fio_write2(fd, .data.buffer = "\x88\x80MASK", .length = 6,
242
254
  .after.dealloc = FIO_DEALLOC_NOOP);
243
255
  } else {
244
- fio_write2(fd, .data.buffer = "\x8a\x00", .length = 2,
256
+ fio_write2(fd, .data.buffer = "\x88\x00", .length = 2,
245
257
  .after.dealloc = FIO_DEALLOC_NOOP);
246
258
  }
247
259
  return 0;
@@ -255,7 +267,7 @@ static void on_data(intptr_t sockfd, fio_protocol_s *ws_) {
255
267
  websocket_buffer_peek(ws->buffer.data, ws->length);
256
268
  const uint64_t raw_length = info.packet_length + info.head_length;
257
269
  /* test expected data amount */
258
- if (ws->max_msg_size < raw_length) {
270
+ if (ws->max_msg_size < raw_length + ws->total_length) {
259
271
  /* too big */
260
272
  websocket_close(ws);
261
273
  return;
@@ -728,8 +740,13 @@ int websocket_write(ws_s *ws, fio_str_info_s msg, uint8_t is_text) {
728
740
  }
729
741
  /** Closes a websocket connection. */
730
742
  void websocket_close(ws_s *ws) {
731
- fio_write2(ws->fd, .data.buffer = "\x88\x00", .length = 2,
732
- .after.dealloc = FIO_DEALLOC_NOOP);
743
+ if (ws->is_client) {
744
+ fio_write2(ws->fd, .data.buffer = "\x88\x80MASK", .length = 6,
745
+ .after.dealloc = FIO_DEALLOC_NOOP);
746
+ } else {
747
+ fio_write2(ws->fd, .data.buffer = "\x88\x00", .length = 2,
748
+ .after.dealloc = FIO_DEALLOC_NOOP);
749
+ }
733
750
  fio_close(ws->fd);
734
751
  return;
735
752
  }
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '0.8.1'.freeze
2
+ VERSION = '0.8.2'.freeze
3
3
  end
@@ -1,7 +1,7 @@
1
1
  require 'iodine' unless defined?(::Iodine::VERSION)
2
2
 
3
3
  module Iodine
4
- # Iodine's {Iodine::Rack} module provides a Rack complient interface (connecting Iodine to Rack) for an HTTP and Websocket Server.
4
+ # Iodine's {Iodine::Rack} module provides a Rack compliant interface (connecting Iodine to Rack) for an HTTP and Websocket Server.
5
5
  module Rack
6
6
 
7
7
  # Runs a Rack app, as par the Rack handler requirements.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isomorfeus-iodine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Biedermann
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-06 00:00:00.000000000 Z
11
+ date: 2022-12-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rackup
@@ -152,7 +152,6 @@ files:
152
152
  - ".gitignore"
153
153
  - ".gitlab-ci.yml"
154
154
  - ".rspec"
155
- - ".travis.yml"
156
155
  - ".yardopts"
157
156
  - CHANGELOG.md
158
157
  - Gemfile
@@ -177,6 +176,7 @@ files:
177
176
  - examples/etag.ru
178
177
  - examples/hello.ru
179
178
  - examples/pubsub_engine.ru
179
+ - examples/rack3.ru
180
180
  - examples/redis.ru
181
181
  - examples/shootout.ru
182
182
  - examples/sub-protocols.ru
@@ -275,7 +275,7 @@ metadata:
275
275
  github_repo: ssh://github.com/isomorfeus/gems
276
276
  source_code_uri: https://github.com/isomorfeus/isomorfeus-iodine
277
277
  post_install_message: |-
278
- Thank you for installing Iodine 0.8.1.
278
+ Thank you for installing Iodine 0.8.2.
279
279
  Remember: if iodine supports your business, it's only fair to give value back (code contributions / donations) to Bo, see https://github.com/boazsegev/iodine
280
280
  rdoc_options: []
281
281
  require_paths:
data/.travis.yml DELETED
@@ -1,32 +0,0 @@
1
- language: ruby
2
- arch:
3
- - amd64
4
- - arm64
5
- os:
6
- - linux
7
- # - osx
8
- before_install:
9
- - gem install bundler -v 1.10.6
10
- - bundle install
11
- rvm:
12
- - 2.7.1
13
- - 2.6.5
14
- - 2.5.7
15
- - 2.4.9
16
- - 2.3.8
17
- - 2.2.2
18
- notifications:
19
- email: false
20
- sudo: required
21
- dist: xenial
22
- addons:
23
- apt:
24
- sources:
25
- - ubuntu-toolchain-r-test
26
- packages:
27
- - gcc
28
- script:
29
- - echo CFLAGS = $CFLAGS
30
- - echo cflags = $cflags
31
- - bundle exec rake install
32
- - env VERBOSE=1 bundle exec rspec --format documentation