iodine 0.7.17 → 0.7.18
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/ext/iodine/websocket_parser.h +42 -103
- data/ext/iodine/websockets.c +24 -19
- data/lib/iodine/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 664ebf25c0cad461467cdb2af2b789d3a0897721566c015bff60b68768a7e3ad
|
4
|
+
data.tar.gz: cc31d5af68fd2a59dc8fa927af51c2228082f05ca7b69c2c4b31e1d208f88337
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae79cb205f288cb84b14d92f7b987f7e350f747c560e3a6e23cb3c1f1d43864234e75dd7f8b71f179f3cecfc8841c0f1da53a41995502c2c8c8c6945c248cc86
|
7
|
+
data.tar.gz: 705d7b0d312e1c3b7953cf503878a2c91a006cef1c7bf9612f83f8f3d97494208bdc8c2ef1a6a857839586525dcd3cbaa4e64758c597a5fd1d929a364f2b9b3c
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,10 @@ 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.18
|
10
|
+
|
11
|
+
**Fix** (`pubsub`) fixed pub/sub for longer WebSocket messages. Issue where network byte ordering wasn't always respected and integer bit size was wrong for larger payloads. Credit to Marouane Elmidaoui (@moxgeek) for exposing the issue.
|
12
|
+
|
9
13
|
#### Change log v.0.7.17
|
10
14
|
|
11
15
|
**Security**: (`fio`) improved security against hash flooding attacks.
|
@@ -221,82 +221,40 @@ void websocket_xmask(void *msg, uint64_t len, uint32_t mask) {
|
|
221
221
|
Message wrapping
|
222
222
|
***************************************************************************** */
|
223
223
|
|
224
|
-
|
225
|
-
#
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
#
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
#
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
uint8_t *const pret = (uint8_t *)&ret;
|
259
|
-
pret[1] = i[1];
|
260
|
-
pret[0] = i[0];
|
261
|
-
return ret;
|
262
|
-
}
|
263
|
-
#define netiswap64(i) (i)
|
264
|
-
#define netiswap16(i) (i)
|
265
|
-
|
266
|
-
#else
|
267
|
-
// TODO: check for __builtin_bswap64
|
268
|
-
/** byte swap 64 bit integer */
|
269
|
-
#define netiswap64(i) \
|
270
|
-
((((i)&0xFFULL) << 56) | (((i)&0xFF00ULL) << 40) | \
|
271
|
-
(((i)&0xFF0000ULL) << 24) | (((i)&0xFF000000ULL) << 8) | \
|
272
|
-
(((i)&0xFF00000000ULL) >> 8) | (((i)&0xFF0000000000ULL) >> 24) | \
|
273
|
-
(((i)&0xFF000000000000ULL) >> 40) | (((i)&0xFF00000000000000ULL) >> 56))
|
274
|
-
/** byte swap 16 bit integer */
|
275
|
-
#define netiswap16(i) ((((i)&0x00ff) << 8) | (((i)&0xff00) >> 8))
|
276
|
-
/** byte swap 64 bit integer from pointer */
|
277
|
-
static inline uint64_t netpiswap64(uint8_t *i) {
|
278
|
-
uint64_t ret = 0;
|
279
|
-
uint8_t *const pret = (uint8_t *)&ret;
|
280
|
-
pret[0] = i[7];
|
281
|
-
pret[1] = i[6];
|
282
|
-
pret[2] = i[5];
|
283
|
-
pret[3] = i[4];
|
284
|
-
pret[4] = i[3];
|
285
|
-
pret[5] = i[2];
|
286
|
-
pret[6] = i[1];
|
287
|
-
pret[7] = i[0];
|
288
|
-
return ret;
|
289
|
-
}
|
290
|
-
/** byte swap 16 bit integer from pointer */
|
291
|
-
static inline uint16_t netpiswap16(uint8_t *i) {
|
292
|
-
uint16_t ret = 0;
|
293
|
-
uint8_t *const pret = (uint8_t *)&ret;
|
294
|
-
pret[0] = i[1];
|
295
|
-
pret[1] = i[0];
|
296
|
-
return ret;
|
297
|
-
}
|
298
|
-
|
299
|
-
#endif
|
224
|
+
/** Converts an unaligned network ordered byte stream to a 16 bit number. */
|
225
|
+
#define websocket_str2u16(c) \
|
226
|
+
((uint16_t)(((uint16_t)(((uint8_t *)(c))[0]) << 8) | \
|
227
|
+
(uint16_t)(((uint8_t *)(c))[1])))
|
228
|
+
|
229
|
+
/** Converts an unaligned network ordered byte stream to a 64 bit number. */
|
230
|
+
#define websocket_str2u64(c) \
|
231
|
+
((uint64_t)((((uint64_t)((uint8_t *)(c))[0]) << 56) | \
|
232
|
+
(((uint64_t)((uint8_t *)(c))[1]) << 48) | \
|
233
|
+
(((uint64_t)((uint8_t *)(c))[2]) << 40) | \
|
234
|
+
(((uint64_t)((uint8_t *)(c))[3]) << 32) | \
|
235
|
+
(((uint64_t)((uint8_t *)(c))[4]) << 24) | \
|
236
|
+
(((uint64_t)((uint8_t *)(c))[5]) << 16) | \
|
237
|
+
(((uint64_t)((uint8_t *)(c))[6]) << 8) | (((uint8_t *)(c))[7])))
|
238
|
+
|
239
|
+
/** Writes a local 16 bit number to an unaligned buffer in network order. */
|
240
|
+
#define websocket_u2str16(buffer, i) \
|
241
|
+
do { \
|
242
|
+
((uint8_t *)(buffer))[0] = ((uint16_t)(i) >> 8) & 0xFF; \
|
243
|
+
((uint8_t *)(buffer))[1] = ((uint16_t)(i)) & 0xFF; \
|
244
|
+
} while (0);
|
245
|
+
|
246
|
+
/** Writes a local 64 bit number to an unaligned buffer in network order. */
|
247
|
+
#define websocket_u2str64(buffer, i) \
|
248
|
+
do { \
|
249
|
+
((uint8_t *)(buffer))[0] = ((uint64_t)(i) >> 56) & 0xFF; \
|
250
|
+
((uint8_t *)(buffer))[1] = ((uint64_t)(i) >> 48) & 0xFF; \
|
251
|
+
((uint8_t *)(buffer))[2] = ((uint64_t)(i) >> 40) & 0xFF; \
|
252
|
+
((uint8_t *)(buffer))[3] = ((uint64_t)(i) >> 32) & 0xFF; \
|
253
|
+
((uint8_t *)(buffer))[4] = ((uint64_t)(i) >> 24) & 0xFF; \
|
254
|
+
((uint8_t *)(buffer))[5] = ((uint64_t)(i) >> 16) & 0xFF; \
|
255
|
+
((uint8_t *)(buffer))[6] = ((uint64_t)(i) >> 8) & 0xFF; \
|
256
|
+
((uint8_t *)(buffer))[7] = ((uint64_t)(i)) & 0xFF; \
|
257
|
+
} while (0);
|
300
258
|
|
301
259
|
/** returns the length of the buffer required to wrap a message `len` long */
|
302
260
|
static inline uint64_t websocket_wrapped_len(uint64_t len) {
|
@@ -346,23 +304,13 @@ static uint64_t websocket_server_wrap(void *target, void *msg, uint64_t len,
|
|
346
304
|
} else if (len < (1UL << 16)) {
|
347
305
|
/* head is 4 bytes */
|
348
306
|
((uint8_t *)target)[1] = 126;
|
349
|
-
|
350
|
-
((uint8_t *)target)[2] = ((uint8_t *)(&net_len))[0];
|
351
|
-
((uint8_t *)target)[3] = ((uint8_t *)(&net_len))[1];
|
307
|
+
websocket_u2str16(((uint8_t *)target + 2), len);
|
352
308
|
memcpy((uint8_t *)target + 4, msg, len);
|
353
309
|
return len + 4;
|
354
310
|
}
|
355
311
|
/* Really Long Message */
|
356
312
|
((uint8_t *)target)[1] = 127;
|
357
|
-
|
358
|
-
((uint8_t *)target)[2] = ((uint8_t *)(&net_len))[0];
|
359
|
-
((uint8_t *)target)[3] = ((uint8_t *)(&net_len))[1];
|
360
|
-
((uint8_t *)target)[4] = ((uint8_t *)(&net_len))[2];
|
361
|
-
((uint8_t *)target)[5] = ((uint8_t *)(&net_len))[3];
|
362
|
-
((uint8_t *)target)[6] = ((uint8_t *)(&net_len))[4];
|
363
|
-
((uint8_t *)target)[7] = ((uint8_t *)(&net_len))[5];
|
364
|
-
((uint8_t *)target)[8] = ((uint8_t *)(&net_len))[6];
|
365
|
-
((uint8_t *)target)[9] = ((uint8_t *)(&net_len))[7];
|
313
|
+
websocket_u2str64(((uint8_t *)target + 2), len);
|
366
314
|
memcpy((uint8_t *)target + 10, msg, len);
|
367
315
|
return len + 10;
|
368
316
|
}
|
@@ -402,9 +350,7 @@ static uint64_t websocket_client_wrap(void *target, void *msg, uint64_t len,
|
|
402
350
|
} else if (len < (1UL << 16)) {
|
403
351
|
/* head is 4 bytes */
|
404
352
|
((uint8_t *)target)[1] = 126 | 128;
|
405
|
-
|
406
|
-
((uint8_t *)target)[2] = ((uint8_t *)(&net_len))[0];
|
407
|
-
((uint8_t *)target)[3] = ((uint8_t *)(&net_len))[1];
|
353
|
+
websocket_u2str16(((uint8_t *)target + 2), len);
|
408
354
|
((uint8_t *)target)[4] = ((uint8_t *)(&mask))[0];
|
409
355
|
((uint8_t *)target)[5] = ((uint8_t *)(&mask))[1];
|
410
356
|
((uint8_t *)target)[6] = ((uint8_t *)(&mask))[2];
|
@@ -415,15 +361,7 @@ static uint64_t websocket_client_wrap(void *target, void *msg, uint64_t len,
|
|
415
361
|
}
|
416
362
|
/* Really Long Message */
|
417
363
|
((uint8_t *)target)[1] = 255;
|
418
|
-
|
419
|
-
((uint8_t *)target)[2] = ((uint8_t *)(&net_len))[0];
|
420
|
-
((uint8_t *)target)[3] = ((uint8_t *)(&net_len))[1];
|
421
|
-
((uint8_t *)target)[4] = ((uint8_t *)(&net_len))[2];
|
422
|
-
((uint8_t *)target)[5] = ((uint8_t *)(&net_len))[3];
|
423
|
-
((uint8_t *)target)[6] = ((uint8_t *)(&net_len))[4];
|
424
|
-
((uint8_t *)target)[7] = ((uint8_t *)(&net_len))[5];
|
425
|
-
((uint8_t *)target)[8] = ((uint8_t *)(&net_len))[6];
|
426
|
-
((uint8_t *)target)[9] = ((uint8_t *)(&net_len))[7];
|
364
|
+
websocket_u2str64(((uint8_t *)target + 2), len);
|
427
365
|
((uint8_t *)target)[10] = ((uint8_t *)(&mask))[0];
|
428
366
|
((uint8_t *)target)[11] = ((uint8_t *)(&mask))[1];
|
429
367
|
((uint8_t *)target)[12] = ((uint8_t *)(&mask))[2];
|
@@ -460,14 +398,15 @@ websocket_buffer_peek(void *buffer, uint64_t len) {
|
|
460
398
|
if (len < 4)
|
461
399
|
return (struct websocket_packet_info_s){0, (uint8_t)(4 + mask_l), mask_f};
|
462
400
|
return (struct websocket_packet_info_s){
|
463
|
-
(uint64_t)
|
464
|
-
mask_f};
|
401
|
+
(uint64_t)websocket_str2u16(((uint8_t *)buffer + 2)),
|
402
|
+
(uint8_t)(4 + mask_l), mask_f};
|
465
403
|
case 127:
|
466
404
|
if (len < 10)
|
467
405
|
return (struct websocket_packet_info_s){0, (uint8_t)(10 + mask_l),
|
468
406
|
mask_f};
|
469
407
|
return (struct websocket_packet_info_s){
|
470
|
-
|
408
|
+
websocket_str2u64(((uint8_t *)buffer + 2)), (uint8_t)(10 + mask_l),
|
409
|
+
mask_f};
|
471
410
|
default:
|
472
411
|
return (struct websocket_packet_info_s){len_indicator,
|
473
412
|
(uint8_t)(2 + mask_l), mask_f};
|
data/ext/iodine/websockets.c
CHANGED
@@ -542,29 +542,34 @@ static inline void websocket_on_pubsub_message_direct_internal(fio_msg_s *msg,
|
|
542
542
|
}
|
543
543
|
FIOBJ message = FIOBJ_INVALID;
|
544
544
|
FIOBJ pre_wrapped = FIOBJ_INVALID;
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
545
|
+
if (!((ws_s *)pr)->is_client) {
|
546
|
+
/* pre-wrapping is only for client data */
|
547
|
+
switch (txt) {
|
548
|
+
case 0:
|
549
|
+
pre_wrapped =
|
550
|
+
(FIOBJ)fio_message_metadata(msg, WEBSOCKET_OPTIMIZE_PUBSUB_BINARY);
|
551
|
+
break;
|
552
|
+
case 1:
|
553
|
+
pre_wrapped =
|
554
|
+
(FIOBJ)fio_message_metadata(msg, WEBSOCKET_OPTIMIZE_PUBSUB_TEXT);
|
555
|
+
break;
|
556
|
+
case 2:
|
557
|
+
pre_wrapped = (FIOBJ)fio_message_metadata(msg, WEBSOCKET_OPTIMIZE_PUBSUB);
|
558
|
+
break;
|
559
|
+
default:
|
560
|
+
break;
|
561
|
+
}
|
562
|
+
if (pre_wrapped) {
|
563
|
+
// FIO_LOG_DEBUG(
|
564
|
+
// "pub/sub WebSocket optimization route for pre-wrapped message.");
|
565
|
+
fiobj_send_free((intptr_t)msg->udata1, fiobj_dup(pre_wrapped));
|
566
|
+
goto finish;
|
567
|
+
}
|
563
568
|
}
|
564
569
|
if (txt == 2) {
|
565
570
|
/* unknown text state */
|
566
571
|
fio_str_s tmp =
|
567
|
-
|
572
|
+
FIO_STR_INIT_STATIC2(msg->msg.data, msg->msg.len); // don't free
|
568
573
|
txt = (tmp.len >= (2 << 14) ? 0 : fio_str_utf8_valid(&tmp));
|
569
574
|
}
|
570
575
|
websocket_write((ws_s *)pr, msg->msg, txt & 1);
|
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.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boaz Segev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -220,7 +220,7 @@ licenses:
|
|
220
220
|
- MIT
|
221
221
|
metadata:
|
222
222
|
allowed_push_host: https://rubygems.org
|
223
|
-
post_install_message: 'Thank you for installing Iodine 0.7.
|
223
|
+
post_install_message: 'Thank you for installing Iodine 0.7.18.
|
224
224
|
|
225
225
|
'
|
226
226
|
rdoc_options: []
|