iodine 0.7.45 → 0.7.48

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33f22236ecbf1c2166c056476bbefb6ab80b709cdb6cc16c0ec144926cf3fdc0
4
- data.tar.gz: 6b0c70cc71431eb3611d34af45c80f679c0177141843a5e03b1cdb6b242d4f19
3
+ metadata.gz: 1718fc25cba1ab9a96c643a16e34413067b30b6706659ca77becf907a92bafe6
4
+ data.tar.gz: 1b3fc0945e54e6eedf7e1fa27956cecfe46e80c8a43078f305343a9eb3497f50
5
5
  SHA512:
6
- metadata.gz: 3506324c77f3de50b9dda515922c3468bbb49c63cd58831d2f7711e02b28209ba7fb5d15e076e860092be4d783cf595fd69b2483bf7ee59b873040005468161f
7
- data.tar.gz: 7c4b0ffb76c749c11f18d66faaad5494e6ab7c675b0d887721de3c7494a7b764886bb8b7b4f5fc369e606e0f3b2e30172818dae27faa4c3cfffa73d094012cf9
6
+ metadata.gz: 70945896acf5a4497254bd631bcc427bde4051813c65d44d43567c0283a40c61a1ecefa547985ee481981a21e4bcf4d3380076fbc5816eed2fdc06a487553e64
7
+ data.tar.gz: bfba77e38f598db62a893ad356ad40485a9dfc768355357bc8242227991ecf8c24354f2f30e52d3afcf1d8f1c62b0fec15c7a2baec309c5b29d6b042918ff259
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.48 (2022-06-28)
10
+
11
+ **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.
12
+
13
+ #### Change log v.0.7.47 (2022-05-11)
14
+
15
+ **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.
16
+
17
+ #### Change log v.0.7.46 (2022-05-06)
18
+
19
+ **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.
20
+
9
21
  #### Change log v.0.7.45 (2021-11-26)
10
22
 
11
23
  **Security**: Fixes a number of issues with the HTTP parser that could have been leveraged in potential exploit attempts such as request smuggling. Credit to @dcepelik (David Čepelík).
data/examples/etag.ru ADDED
@@ -0,0 +1,16 @@
1
+ # This example uses Rack::ETag to allow for response caching.
2
+
3
+ require 'rack'
4
+ require 'iodine'
5
+
6
+ App = Proc.new do |env|
7
+ [200,
8
+ { "Content-Type" => "text/html".freeze,
9
+ "Content-Length" => "16".freeze },
10
+ ['Hello from Rack!'.freeze] ]
11
+ end
12
+
13
+ use Rack::ConditionalGet
14
+ use Rack::ETag, 'public'
15
+
16
+ run App
data/ext/iodine/http.c CHANGED
@@ -92,14 +92,12 @@ static inline void add_date(http_s *r) {
92
92
  static uint64_t date_hash = 0;
93
93
  if (!date_hash)
94
94
  date_hash = fiobj_hash_string("date", 4);
95
- static uint64_t mod_hash = 0;
96
- if (!mod_hash)
97
- mod_hash = fiobj_hash_string("last-modified", 13);
98
95
 
99
96
  if (fio_last_tick().tv_sec > last_date_added) {
100
97
  fio_lock(&date_lock);
101
98
  if (fio_last_tick().tv_sec > last_date_added) { /* retest inside lock */
102
- /* 32 chars are ok for a while, but http_time2str below has a buffer sized 48 chars and does a memcpy ... */
99
+ /* 32 chars are ok for a while, but http_time2str below has a buffer sized
100
+ * 48 chars and does a memcpy ... */
103
101
  FIOBJ tmp = fiobj_str_buf(32);
104
102
  FIOBJ old = current_date;
105
103
  fiobj_str_resize(
@@ -115,11 +113,6 @@ static inline void add_date(http_s *r) {
115
113
  fiobj_hash_set(r->private_data.out_headers, HTTP_HEADER_DATE,
116
114
  fiobj_dup(current_date));
117
115
  }
118
- if (r->status_str == FIOBJ_INVALID &&
119
- !fiobj_hash_get2(r->private_data.out_headers, mod_hash)) {
120
- fiobj_hash_set(r->private_data.out_headers, HTTP_HEADER_LAST_MODIFIED,
121
- fiobj_dup(current_date));
122
- }
123
116
  }
124
117
 
125
118
  struct header_writer_s {
@@ -2355,7 +2348,7 @@ static void init_cached_key_ptr(void) {
2355
2348
  time_t *cached_tick = malloc(sizeof(time_t));
2356
2349
  FIO_ASSERT_ALLOC(cached_tick);
2357
2350
  memset(cached_tick, 0, sizeof(time_t));
2358
- char *cached_httpdate = malloc(sizeof(char)*48);
2351
+ char *cached_httpdate = malloc(sizeof(char) * 48);
2359
2352
  FIO_ASSERT_ALLOC(cached_tick);
2360
2353
  memset(cached_httpdate, 0, 48);
2361
2354
  size_t *cached_len = malloc(sizeof(size_t));
@@ -2401,28 +2394,24 @@ size_t http_time2str(char *target, const time_t t) {
2401
2394
 
2402
2395
  /* Credit to Jonathan Leffler for the idea of a unified conditional */
2403
2396
  #define hex_val(c) \
2404
- (((c) >= '0' && (c) <= '9') \
2405
- ? ((c)-48) \
2406
- : (((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) \
2407
- ? (((c) | 32) - 87) \
2408
- : ({ \
2409
- return -1; \
2410
- 0; \
2411
- }))
2397
+ (((c) >= '0' && (c) <= '9') ? ((c)-48) \
2398
+ : (((c) | 32) >= 'a' && ((c) | 32) <= 'f') ? (((c) | 32) - 87) \
2399
+ : ({ \
2400
+ return -1; \
2401
+ 0; \
2402
+ }))
2412
2403
  static inline int hex2byte(uint8_t *dest, const uint8_t *source) {
2413
2404
  if (source[0] >= '0' && source[0] <= '9')
2414
2405
  *dest = (source[0] - '0');
2415
- else if ((source[0] >= 'a' && source[0] <= 'f') ||
2416
- (source[0] >= 'A' && source[0] <= 'F'))
2417
- *dest = (source[0] | 32) - 87;
2406
+ else if ((source[0] | 32) >= 'a' && (source[0] | 32) <= 'f')
2407
+ *dest = (source[0] | 32) - ('a' - 10);
2418
2408
  else
2419
2409
  return -1;
2420
2410
  *dest <<= 4;
2421
2411
  if (source[1] >= '0' && source[1] <= '9')
2422
2412
  *dest |= (source[1] - '0');
2423
- else if ((source[1] >= 'a' && source[1] <= 'f') ||
2424
- (source[1] >= 'A' && source[1] <= 'F'))
2425
- *dest |= (source[1] | 32) - 87;
2413
+ else if ((source[1] | 32) >= 'a' && (source[1] | 32) <= 'f')
2414
+ *dest |= (source[1] | 32) - ('a' - 10);
2426
2415
  else
2427
2416
  return -1;
2428
2417
  return 0;
@@ -2561,9 +2550,7 @@ FIOBJ http_mimetype_find(char *file_ext, size_t file_ext_len) {
2561
2550
 
2562
2551
  static pthread_key_t buffer_key;
2563
2552
  static pthread_once_t buffer_once = PTHREAD_ONCE_INIT;
2564
- static void init_buffer_key(void) {
2565
- pthread_key_create(&buffer_key, free);
2566
- }
2553
+ static void init_buffer_key(void) { pthread_key_create(&buffer_key, free); }
2567
2554
  static void init_buffer_ptr(void) {
2568
2555
  char *buffer = malloc(sizeof(char) * (LONGEST_FILE_EXTENSION_LENGTH + 1));
2569
2556
  FIO_ASSERT_ALLOC(buffer);
@@ -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 */
@@ -72,11 +72,7 @@ static rb_encoding *IodineBinaryEncoding;
72
72
 
73
73
  inline static http_s *get_handle(VALUE obj) {
74
74
  VALUE i = rb_ivar_get(obj, iodine_fd_var_id);
75
- #ifdef __MINGW32__
76
75
  return (http_s *)NUM2ULL(i);
77
- #else
78
- return (http_s *)FIX2ULONG(i);
79
- #endif
80
76
  }
81
77
 
82
78
  /* *****************************************************************************
@@ -85,11 +81,7 @@ IO API
85
81
 
86
82
  static inline FIOBJ get_data(VALUE self) {
87
83
  VALUE i = rb_ivar_get(self, io_id);
88
- #ifdef __MINGW32__
89
84
  return (FIOBJ)NUM2ULL(i);
90
- #else
91
- return (FIOBJ)FIX2ULONG(i);
92
- #endif
93
85
  }
94
86
 
95
87
  static VALUE rio_rewind(VALUE self) {
@@ -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__
@@ -183,15 +184,19 @@ static void websocket_on_protocol_ping(void *ws_p, void *msg_, uint64_t len) {
183
184
  fio_write2(ws->fd, .data.buffer = buff, .length = len);
184
185
  } else {
185
186
  if (((ws_s *)ws)->is_client) {
186
- fio_write2(ws->fd, .data.buffer = "\x89\x80mask", .length = 2,
187
+ fio_write2(ws->fd, .data.buffer = "\x8a\x80mask", .length = 6,
187
188
  .after.dealloc = FIO_DEALLOC_NOOP);
188
189
  } else {
189
- fio_write2(ws->fd, .data.buffer = "\x89\x00", .length = 2,
190
+ fio_write2(ws->fd, .data.buffer = "\x8a\x00", .length = 2,
190
191
  .after.dealloc = FIO_DEALLOC_NOOP);
191
192
  }
192
193
  }
194
+ FIO_LOG_DEBUG("Received ping and sent pong for Websocket %p (%d)", ws_p,
195
+ (int)(((ws_s *)ws_p)->fd));
193
196
  }
194
197
  static void websocket_on_protocol_pong(void *ws_p, void *msg, uint64_t len) {
198
+ FIO_LOG_DEBUG("Received pong for Websocket %p (%d)", ws_p,
199
+ (int)(((ws_s *)ws_p)->fd));
195
200
  (void)len;
196
201
  (void)msg;
197
202
  (void)ws_p;
@@ -220,6 +225,7 @@ static void ws_ping(intptr_t fd, fio_protocol_s *ws) {
220
225
  fio_write2(fd, .data.buffer = "\x89\x00", .length = 2,
221
226
  .after.dealloc = FIO_DEALLOC_NOOP);
222
227
  }
228
+ FIO_LOG_DEBUG("Sent ping for Websocket %p (%d)", (void *)ws, (int)fd);
223
229
  }
224
230
 
225
231
  static void on_close(intptr_t uuid, fio_protocol_s *_ws) {
@@ -238,10 +244,10 @@ static uint8_t on_shutdown(intptr_t fd, fio_protocol_s *ws) {
238
244
  if (ws && ((ws_s *)ws)->on_shutdown)
239
245
  ((ws_s *)ws)->on_shutdown((ws_s *)ws);
240
246
  if (((ws_s *)ws)->is_client) {
241
- fio_write2(fd, .data.buffer = "\x8a\x80MASK", .length = 6,
247
+ fio_write2(fd, .data.buffer = "\x88\x80MASK", .length = 6,
242
248
  .after.dealloc = FIO_DEALLOC_NOOP);
243
249
  } else {
244
- fio_write2(fd, .data.buffer = "\x8a\x00", .length = 2,
250
+ fio_write2(fd, .data.buffer = "\x88\x00", .length = 2,
245
251
  .after.dealloc = FIO_DEALLOC_NOOP);
246
252
  }
247
253
  return 0;
@@ -728,8 +734,13 @@ int websocket_write(ws_s *ws, fio_str_info_s msg, uint8_t is_text) {
728
734
  }
729
735
  /** Closes a websocket connection. */
730
736
  void websocket_close(ws_s *ws) {
731
- fio_write2(ws->fd, .data.buffer = "\x88\x00", .length = 2,
732
- .after.dealloc = FIO_DEALLOC_NOOP);
737
+ if (ws->is_client) {
738
+ fio_write2(ws->fd, .data.buffer = "\x88\x80MASK", .length = 6,
739
+ .after.dealloc = FIO_DEALLOC_NOOP);
740
+ } else {
741
+ fio_write2(ws->fd, .data.buffer = "\x88\x00", .length = 2,
742
+ .after.dealloc = FIO_DEALLOC_NOOP);
743
+ }
733
744
  fio_close(ws->fd);
734
745
  return;
735
746
  }
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '0.7.45'.freeze
2
+ VERSION = '0.7.48'.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.45
4
+ version: 0.7.48
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-26 00:00:00.000000000 Z
11
+ date: 2022-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -145,6 +145,7 @@ files:
145
145
  - examples/async_task.ru
146
146
  - examples/config.ru
147
147
  - examples/echo.ru
148
+ - examples/etag.ru
148
149
  - examples/hello.ru
149
150
  - examples/pubsub_engine.ru
150
151
  - examples/redis.ru
@@ -244,7 +245,7 @@ licenses:
244
245
  metadata:
245
246
  allowed_push_host: https://rubygems.org
246
247
  post_install_message: |-
247
- Thank you for installing Iodine 0.7.45.
248
+ Thank you for installing Iodine 0.7.48.
248
249
  Remember: if iodine supports your business, it's only fair to give value back (code contributions / donations).
249
250
  rdoc_options: []
250
251
  require_paths:
@@ -267,7 +268,7 @@ requirements:
267
268
  - Ruby >= 2.5.0 recommended.
268
269
  - TLS requires OpenSSL >= 1.1.0.
269
270
  - Or Windows with Ruby >= 3.0.0 build with MingW and MingW as compiler.
270
- rubygems_version: 3.2.3
271
+ rubygems_version: 3.2.32
271
272
  signing_key:
272
273
  specification_version: 4
273
274
  summary: iodine - a fast HTTP / Websocket Server with Pub/Sub support, optimized for