iodine 0.7.46 → 0.7.49

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a2b1c5f8f5b6ec1d2259cf33e2cde27e3811a2df5715fa3463891062db2c9ae
4
- data.tar.gz: 8b1140297cdbf2501ab145712b5cccce06beb1d7350d0d4d7176e86053d5255a
3
+ metadata.gz: 1dad2816193abeda90adf195c3c9cfcaa53eb9a1c5f1e4ad8364be45cd10bc2f
4
+ data.tar.gz: 02e35b8bbdf6516d210bd8cfc012035a1de2ec3a783e4346152bead0186ba668
5
5
  SHA512:
6
- metadata.gz: 96ce75b3a7ef9548e33e73438b4aaf785a41594b4dec4a214081699c556c60512a54a231748de3f1478f622cb540fd67d3afd6bb87cc1bc38ee32471ab4ce016
7
- data.tar.gz: 40d9d0e4499fd59e7e25f37f300c246c4f9d645246c31a4af7b28f622699a8c12861e0a884ecfd1274451e0a24f5b28be212748286023ff75e6ceb406b6031db
6
+ metadata.gz: bca7fb5be56837c4a729cef3f755ee4fa8a5a289d448961e01f9449a6e3d76865b03956d7525802a2a1c3768da61b4b8cf8a6088ca63ed57e3b966575e95fb51
7
+ data.tar.gz: f2fcb35e2cd7452dbeb7fb20bbe5deb3f661e8a3f3ec387d878a858732a414d3d383320164a8a3164be0cdebf900a14360e60d87488c5d61e5b8105ada6270d8
data/CHANGELOG.md CHANGED
@@ -6,6 +6,18 @@ Please notice that this change log contains changes for upcoming releases as wel
6
6
 
7
7
  ## Changes:
8
8
 
9
+ #### Change log v.0.7.49
10
+
11
+ **Fix**: Fixes an issue where named arguments for `subscribe` might not be properly recognized.
12
+
13
+ #### Change log v.0.7.48 (2022-06-28)
14
+
15
+ **Fix**: Fixes an issue with `pong` WebSocket frames when a client sends a WebSocket `ping`. Credit to Lucas Kuan (@lucaskuan) for finding this issue and for PR #124.
16
+
17
+ #### Change log v.0.7.47 (2022-05-11)
18
+
19
+ **Fix**: Fixes an issue that causes `Rack::Lint` to complain about `SERVER_PORT` being an empty string. Credit to @adam12 (Adam Daniels) for PR #108 and issue #107.
20
+
9
21
  #### Change log v.0.7.46 (2022-05-06)
10
22
 
11
23
  **Fix**: Fixes the (erroneous) default insertion of the `last-modified` header in order to both better express the intent of RFC 2616 and prevent conflict with the `Rack::ETag` middleware. Credit to @raxoft (Patrik Rak) for opening issue #122.
data/examples/config.ru CHANGED
@@ -12,6 +12,9 @@
12
12
  #
13
13
  # ab -c 2000 -t 5 -n 1000000 -k http://127.0.0.1:3000/
14
14
  # wrk -c2000 -d5 -t12 http://localhost:3000/
15
+ #
16
+ # Test websocket echo using the browser. For example:
17
+ # ws = new WebSocket("ws://localhost:3000"); ws.onmessage = function(e) {console.log("Got message!"); console.log(e.data);}; ws.onclose = function(e) {console.log("closed")}; ws.onopen = function(e) {ws.send("hi");};
15
18
 
16
19
 
17
20
  # A simple router - Checks for Websocket Upgrade and answers HTTP.
data/ext/iodine/fio.c CHANGED
@@ -3689,7 +3689,8 @@ closed:
3689
3689
  return -1;
3690
3690
 
3691
3691
  flush_rw_hook:
3692
- flushed = uuid_data(uuid).rw_hooks->flush(uuid, uuid_data(uuid).rw_udata);
3692
+ if(uuid_data(uuid).rw_hooks)
3693
+ flushed = uuid_data(uuid).rw_hooks->flush(uuid, uuid_data(uuid).rw_udata);
3693
3694
  fio_unlock(&uuid_data(uuid).sock_lock);
3694
3695
  if (!flushed)
3695
3696
  return 0;
@@ -3749,7 +3750,8 @@ size_t fio_flush_all(void) {
3749
3750
  return 0;
3750
3751
  size_t count = 0;
3751
3752
  for (uintptr_t i = 0; i <= fio_data->max_protocol_fd; ++i) {
3752
- if ((fd_data(i).open || fd_data(i).packet) && fio_flush(fd2uuid(i)) > 0)
3753
+ if ((fd_data(i).open || fd_data(i).packet) &&
3754
+ fd_data(i).rw_hooks && fio_flush(fd2uuid(i)) > 0)
3753
3755
  ++count;
3754
3756
  }
3755
3757
  return count;
@@ -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
  }
@@ -369,7 +369,6 @@ static inline VALUE copy2env(iodine_http_request_handle_s *handle) {
369
369
  if (*pos == 0) {
370
370
  rb_hash_aset(env, SERVER_NAME,
371
371
  rb_enc_str_new(tmp.data, tmp.len, IodineBinaryEncoding));
372
- rb_hash_aset(env, SERVER_PORT, QUERY_ESTRING);
373
372
  } else {
374
373
  rb_hash_aset(
375
374
  env, SERVER_NAME,
@@ -869,7 +868,6 @@ static void initialize_env_template(void) {
869
868
  rb_hash_aset(env_template_no_upgrade, REMOTE_ADDR, QUERY_STRING);
870
869
  rb_hash_aset(env_template_no_upgrade, REQUEST_METHOD, QUERY_STRING);
871
870
  rb_hash_aset(env_template_no_upgrade, SERVER_NAME, QUERY_STRING);
872
- rb_hash_aset(env_template_no_upgrade, SERVER_PORT, QUERY_ESTRING);
873
871
  rb_hash_aset(env_template_no_upgrade, SERVER_PROTOCOL, QUERY_STRING);
874
872
 
875
873
  /* WebSocket upgrade support */
@@ -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.7.46'.freeze
2
+ VERSION = '0.7.49'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iodine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.46
4
+ version: 0.7.49
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-05-07 00:00:00.000000000 Z
11
+ date: 2022-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -245,7 +245,7 @@ licenses:
245
245
  metadata:
246
246
  allowed_push_host: https://rubygems.org
247
247
  post_install_message: |-
248
- Thank you for installing Iodine 0.7.46.
248
+ Thank you for installing Iodine 0.7.49.
249
249
  Remember: if iodine supports your business, it's only fair to give value back (code contributions / donations).
250
250
  rdoc_options: []
251
251
  require_paths: