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 +4 -4
- data/CHANGELOG.md +12 -0
- data/examples/etag.ru +16 -0
- data/ext/iodine/http.c +14 -27
- data/ext/iodine/iodine_http.c +0 -2
- data/ext/iodine/iodine_rack_io.c +0 -8
- data/ext/iodine/websockets.c +18 -7
- data/lib/iodine/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1718fc25cba1ab9a96c643a16e34413067b30b6706659ca77becf907a92bafe6
|
4
|
+
data.tar.gz: 1b3fc0945e54e6eedf7e1fa27956cecfe46e80c8a43078f305343a9eb3497f50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
2406
|
-
|
2407
|
-
|
2408
|
-
|
2409
|
-
|
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
|
-
|
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
|
-
|
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);
|
data/ext/iodine/iodine_http.c
CHANGED
@@ -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 */
|
data/ext/iodine/iodine_rack_io.c
CHANGED
@@ -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) {
|
data/ext/iodine/websockets.c
CHANGED
@@ -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__) &&
|
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 = "\
|
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 = "\
|
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 = "\
|
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 = "\
|
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
|
-
|
732
|
-
|
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
|
}
|
data/lib/iodine/version.rb
CHANGED
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.
|
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:
|
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.
|
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.
|
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
|