iodine 0.2.7 → 0.2.8
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.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -1
- data/README.md +5 -1
- data/ext/iodine/base64.c +3 -3
- data/ext/iodine/base64.h +3 -3
- data/ext/iodine/bscrypt-common.h +5 -5
- data/ext/iodine/bscrypt.h +4 -4
- data/ext/iodine/hex.c +11 -10
- data/ext/iodine/hex.h +3 -3
- data/ext/iodine/http.c +34 -27
- data/ext/iodine/http.h +15 -8
- data/ext/iodine/http1.c +63 -60
- data/ext/iodine/http1.h +10 -5
- data/ext/iodine/http1_simple_parser.c +6 -0
- data/ext/iodine/http1_simple_parser.h +10 -6
- data/ext/iodine/http_request.h +28 -22
- data/ext/iodine/http_response.c +22 -7
- data/ext/iodine/http_response.h +6 -0
- data/ext/iodine/http_response_http1.h +9 -1
- data/ext/iodine/iodine_core.c +6 -1
- data/ext/iodine/iodine_core.h +13 -6
- data/ext/iodine/iodine_http.c +6 -0
- data/ext/iodine/iodine_http.h +6 -0
- data/ext/iodine/iodine_websocket.c +23 -4
- data/ext/iodine/iodine_websocket.h +2 -2
- data/ext/iodine/libasync.c +5 -3
- data/ext/iodine/libasync.h +8 -8
- data/ext/iodine/libreact.c +8 -8
- data/ext/iodine/libreact.h +5 -5
- data/ext/iodine/libserver.c +2 -2
- data/ext/iodine/libserver.h +2 -2
- data/ext/iodine/libsock.c +2 -2
- data/ext/iodine/libsock.h +3 -3
- data/ext/iodine/mempool.h +826 -0
- data/ext/iodine/misc.c +14 -14
- data/ext/iodine/misc.h +3 -3
- data/ext/iodine/random.c +6 -6
- data/ext/iodine/random.h +3 -3
- data/ext/iodine/rb-call.c +6 -0
- data/ext/iodine/rb-call.h +2 -2
- data/ext/iodine/rb-libasync.h +5 -3
- data/ext/iodine/rb-rack-io.c +15 -3
- data/ext/iodine/rb-rack-io.h +5 -2
- data/ext/iodine/rb-registry.c +6 -0
- data/ext/iodine/rb-registry.h +2 -2
- data/ext/iodine/sha1.c +13 -11
- data/ext/iodine/sha1.h +3 -3
- data/ext/iodine/sha2.c +8 -6
- data/ext/iodine/sha2.h +3 -3
- data/ext/iodine/siphash.c +9 -2
- data/ext/iodine/siphash.h +8 -1
- data/ext/iodine/spnlock.h +9 -3
- data/ext/iodine/websockets.c +62 -38
- data/ext/iodine/websockets.h +6 -0
- data/ext/iodine/xor-crypt.c +3 -3
- data/ext/iodine/xor-crypt.h +3 -3
- data/lib/iodine/version.rb +1 -1
- metadata +3 -4
- data/ext/iodine/rb-call.c_old +0 -127
- data/ext/iodine/rb-registry_old.c_old +0 -213
data/ext/iodine/misc.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
License:
|
4
|
-
subject to their own licenses.
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT except for any non-public-domain algorithms (none that I'm aware
|
4
|
+
of), which might be subject to their own licenses.
|
5
5
|
|
6
6
|
Feel free to copy, use and enjoy in accordance with to the license(s).
|
7
7
|
*/
|
@@ -14,12 +14,12 @@ Other helper functions
|
|
14
14
|
*/
|
15
15
|
|
16
16
|
#ifdef HAS_UNIX_FEATURES
|
17
|
+
#include <errno.h>
|
17
18
|
#include <fcntl.h>
|
18
19
|
#include <limits.h>
|
19
|
-
#include <errno.h>
|
20
|
-
#include <unistd.h>
|
21
|
-
#include <sys/types.h>
|
22
20
|
#include <sys/stat.h>
|
21
|
+
#include <sys/types.h>
|
22
|
+
#include <unistd.h>
|
23
23
|
|
24
24
|
/**
|
25
25
|
Allocates memory and dumps the whole file into the memory allocated.
|
@@ -32,10 +32,10 @@ container pointer to NULL.
|
|
32
32
|
This function has some Unix specific properties that resolve links and user
|
33
33
|
folder referencing.
|
34
34
|
*/
|
35
|
-
fdump_s*
|
35
|
+
fdump_s *bscrypt_fdump(const char *file_path, size_t size_limit) {
|
36
36
|
struct stat f_data;
|
37
37
|
int file = -1;
|
38
|
-
fdump_s*
|
38
|
+
fdump_s *container = NULL;
|
39
39
|
size_t file_path_len;
|
40
40
|
if (file_path == NULL || (file_path_len = strlen(file_path)) == 0 ||
|
41
41
|
file_path_len > PATH_MAX)
|
@@ -82,14 +82,14 @@ See the libc `gmtime_r` documentation for details.
|
|
82
82
|
|
83
83
|
Falls back to `gmtime_r` for dates before epoch.
|
84
84
|
*/
|
85
|
-
struct tm*
|
85
|
+
struct tm *bscrypt_gmtime(const time_t *timer, struct tm *tmbuf) {
|
86
86
|
// static char* DAYS[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
|
87
87
|
// static char * Months = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
88
88
|
// "Jul",
|
89
89
|
// "Aug", "Sep", "Oct", "Nov", "Dec"};
|
90
90
|
static uint8_t month_len[] = {
|
91
|
-
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
|
92
|
-
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
|
91
|
+
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, // nonleap year
|
92
|
+
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 // leap year
|
93
93
|
};
|
94
94
|
if (*timer < 0)
|
95
95
|
return gmtime_r(timer, tmbuf);
|
@@ -97,7 +97,7 @@ struct tm* bscrypt_gmtime(const time_t* timer, struct tm* tmbuf) {
|
|
97
97
|
tmbuf->tm_gmtoff = 0;
|
98
98
|
tmbuf->tm_zone = "UTC";
|
99
99
|
tmbuf->tm_isdst = 0;
|
100
|
-
tmbuf->tm_year = 70;
|
100
|
+
tmbuf->tm_year = 70; // tm_year == The number of years since 1900
|
101
101
|
tmbuf->tm_mon = 0;
|
102
102
|
// for seconds up to weekdays, we build up, as small values clean up larger
|
103
103
|
// values.
|
@@ -122,7 +122,7 @@ struct tm* bscrypt_gmtime(const time_t* timer, struct tm* tmbuf) {
|
|
122
122
|
tmbuf->tm_year += 100;
|
123
123
|
tmp -= DAYS_PER_100_YEARS;
|
124
124
|
if (((tmbuf->tm_year / 100) & 3) ==
|
125
|
-
0)
|
125
|
+
0) // leap century divisable by 400 => add leap
|
126
126
|
--tmp;
|
127
127
|
}
|
128
128
|
#undef DAYS_PER_100_YEARS
|
@@ -147,7 +147,7 @@ struct tm* bscrypt_gmtime(const time_t* timer, struct tm* tmbuf) {
|
|
147
147
|
while (tmp >= 365) {
|
148
148
|
tmbuf->tm_year += 1;
|
149
149
|
tmp -= 365;
|
150
|
-
if ((tmbuf->tm_year & 3) == 0) {
|
150
|
+
if ((tmbuf->tm_year & 3) == 0) { // leap year
|
151
151
|
if (tmp > 0) {
|
152
152
|
--tmp;
|
153
153
|
continue;
|
data/ext/iodine/misc.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
License:
|
4
|
-
subject to their own licenses.
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT except for any non-public-domain algorithms (none that I'm aware
|
4
|
+
of), which might be subject to their own licenses.
|
5
5
|
|
6
6
|
Feel free to copy, use and enjoy in accordance with to the license(s).
|
7
7
|
*/
|
data/ext/iodine/random.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
License:
|
4
|
-
subject to their own licenses.
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT except for any non-public-domain algorithms (none that I'm aware
|
4
|
+
of), which might be subject to their own licenses.
|
5
5
|
|
6
6
|
Feel free to copy, use and enjoy in accordance with to the license(s).
|
7
7
|
*/
|
@@ -11,8 +11,8 @@ Feel free to copy, use and enjoy in accordance with to the license(s).
|
|
11
11
|
#include "random.h"
|
12
12
|
|
13
13
|
#if defined(USE_ALT_RANDOM) || !defined(HAS_UNIX_FEATURES)
|
14
|
-
#include <time.h>
|
15
14
|
#include "sha2.h"
|
15
|
+
#include <time.h>
|
16
16
|
uint32_t bscrypt_rand32(void) {
|
17
17
|
bits256_u pseudo = bscrypt_rand256();
|
18
18
|
return pseudo.ints[3];
|
@@ -96,10 +96,10 @@ void bscrypt_rand_bytes(void *target, size_t length) {
|
|
96
96
|
/* ***************************************************************************
|
97
97
|
Unix Random Engine (use built in machine)
|
98
98
|
*/
|
99
|
-
#include <fcntl.h>
|
100
99
|
#include <errno.h>
|
101
|
-
#include <
|
100
|
+
#include <fcntl.h>
|
102
101
|
#include <pthread.h>
|
102
|
+
#include <unistd.h>
|
103
103
|
|
104
104
|
/* ***************************************************************************
|
105
105
|
Machine specific changes
|
data/ext/iodine/random.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
License:
|
4
|
-
subject to their own licenses.
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT except for any non-public-domain algorithms (none that I'm aware
|
4
|
+
of), which might be subject to their own licenses.
|
5
5
|
|
6
6
|
Feel free to copy, use and enjoy in accordance with to the license(s).
|
7
7
|
*/
|
data/ext/iodine/rb-call.c
CHANGED
data/ext/iodine/rb-call.h
CHANGED
data/ext/iodine/rb-libasync.h
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT
|
4
4
|
|
5
5
|
Feel free to copy, use and enjoy according to the license provided.
|
6
6
|
*/
|
7
7
|
#ifndef RB_ASYNC_EXT_H
|
8
8
|
#define RB_ASYNC_EXT_H
|
9
|
+
// clang-format off
|
10
|
+
#include "rb-registry.h"
|
9
11
|
#include <ruby.h>
|
10
12
|
#include <ruby/thread.h>
|
11
|
-
|
13
|
+
// clang-format on
|
12
14
|
|
13
15
|
/******************************************************************************
|
14
16
|
Portability - used to help port this to different frameworks (i.e. Ruby).
|
data/ext/iodine/rb-rack-io.c
CHANGED
@@ -1,9 +1,21 @@
|
|
1
|
+
/*
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT
|
4
|
+
|
5
|
+
Feel free to copy, use and enjoy according to the license provided.
|
6
|
+
*/
|
7
|
+
// clang-format off
|
1
8
|
#include "rb-rack-io.h"
|
2
|
-
#include "rb-call.h"
|
3
9
|
#include "iodine_core.h"
|
4
|
-
#include <ruby/encoding.h>
|
5
|
-
#include <ruby/io.h>
|
6
10
|
#include <ruby/io.h>
|
11
|
+
#include <ruby/encoding.h>
|
12
|
+
#include <unistd.h>
|
13
|
+
// clang-format on
|
14
|
+
|
15
|
+
#ifndef _GNU_SOURCE
|
16
|
+
#define _GNU_SOURCE
|
17
|
+
#endif
|
18
|
+
#include "rb-call.h"
|
7
19
|
|
8
20
|
/* RackIO manages a minimal interface to act as an IO wrapper according to
|
9
21
|
these Rack specifications:
|
data/ext/iodine/rb-rack-io.h
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT
|
4
4
|
|
5
5
|
Feel free to copy, use and enjoy according to the license provided.
|
6
6
|
*/
|
7
7
|
#ifndef RUBY_RACK_IO_H
|
8
8
|
#define RUBY_RACK_IO_H
|
9
|
+
// clang-format off
|
9
10
|
#include <ruby.h>
|
11
|
+
// clang-format on
|
12
|
+
|
10
13
|
#include "http_request.h"
|
11
14
|
|
12
15
|
extern struct _RackIO_ {
|
data/ext/iodine/rb-registry.c
CHANGED
data/ext/iodine/rb-registry.h
CHANGED
data/ext/iodine/sha1.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
License:
|
4
|
-
subject to their own licenses.
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT except for any non-public-domain algorithms (none that I'm aware
|
4
|
+
of), which might be subject to their own licenses.
|
5
5
|
|
6
6
|
Feel free to copy, use and enjoy in accordance with to the license(s).
|
7
7
|
*/
|
@@ -276,9 +276,11 @@ SHA-1 testing
|
|
276
276
|
#include <time.h>
|
277
277
|
|
278
278
|
// clang-format off
|
279
|
-
#if defined(TEST_OPENSSL) && defined(__has_include)
|
280
|
-
#
|
281
|
-
#
|
279
|
+
#if defined(TEST_OPENSSL) && defined(__has_include)
|
280
|
+
# if __has_include(<openssl/sha.h>)
|
281
|
+
# include <openssl/sha.h>
|
282
|
+
# define HAS_OPEN_SSL 1
|
283
|
+
# endif
|
282
284
|
#endif
|
283
285
|
// clang-format on
|
284
286
|
|
@@ -288,13 +290,13 @@ void bscrypt_test_sha1(void) {
|
|
288
290
|
char hash[21];
|
289
291
|
} sets[] = {
|
290
292
|
{"The quick brown fox jumps over the lazy dog",
|
291
|
-
{0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e,
|
292
|
-
0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12,
|
293
|
-
|
293
|
+
{0x2f, 0xd4, 0xe1, 0xc6, 0x7a, 0x2d, 0x28, 0xfc, 0xed, 0x84, 0x9e,
|
294
|
+
0xe1, 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12, 0}}, // a set with
|
295
|
+
// a string
|
294
296
|
{"",
|
295
297
|
{
|
296
|
-
0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
|
297
|
-
0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09,
|
298
|
+
0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55,
|
299
|
+
0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09,
|
298
300
|
}}, // an empty set
|
299
301
|
{NULL, {0}} // Stop
|
300
302
|
};
|
data/ext/iodine/sha1.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
License:
|
4
|
-
subject to their own licenses.
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT except for any non-public-domain algorithms (none that I'm aware
|
4
|
+
of), which might be subject to their own licenses.
|
5
5
|
|
6
6
|
Feel free to copy, use and enjoy in accordance with to the license(s).
|
7
7
|
*/
|
data/ext/iodine/sha2.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
License:
|
4
|
-
subject to their own licenses.
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT except for any non-public-domain algorithms (none that I'm aware
|
4
|
+
of), which might be subject to their own licenses.
|
5
5
|
|
6
6
|
Feel free to copy, use and enjoy in accordance with to the license(s).
|
7
7
|
*/
|
@@ -658,9 +658,11 @@ static char *sha2_variant_names[] = {
|
|
658
658
|
};
|
659
659
|
|
660
660
|
// clang-format off
|
661
|
-
#if defined(TEST_OPENSSL) && defined(__has_include)
|
662
|
-
#
|
663
|
-
#
|
661
|
+
#if defined(TEST_OPENSSL) && defined(__has_include)
|
662
|
+
# if __has_include(<openssl/sha.h>)
|
663
|
+
# include <openssl/sha.h>
|
664
|
+
# define HAS_OPEN_SSL 1
|
665
|
+
# endif
|
664
666
|
#endif
|
665
667
|
// clang-format on
|
666
668
|
|
data/ext/iodine/sha2.h
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
License:
|
4
|
-
subject to their own licenses.
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT except for any non-public-domain algorithms (none that I'm aware
|
4
|
+
of), which might be subject to their own licenses.
|
5
5
|
|
6
6
|
Feel free to copy, use and enjoy in accordance with to the license(s).
|
7
7
|
*/
|
data/ext/iodine/siphash.c
CHANGED
@@ -1,6 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT except for any non-public-domain algorithms (none that I'm aware
|
4
|
+
of), which might be subject to their own licenses.
|
5
|
+
|
6
|
+
Feel free to copy, use and enjoy in accordance with to the license(s).
|
7
|
+
*/
|
1
8
|
#include "siphash.h"
|
2
|
-
#include <stdlib.h>
|
3
9
|
#include <stdint.h>
|
10
|
+
#include <stdlib.h>
|
4
11
|
|
5
12
|
// clang-format off
|
6
13
|
#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
|
@@ -80,7 +87,7 @@ uint64_t siphash24(const void *data, size_t len, uint64_t iv_key[2]) {
|
|
80
87
|
word.i = 0;
|
81
88
|
uint8_t *pos = word.str;
|
82
89
|
uint8_t *w8 = (void *)w64;
|
83
|
-
switch (len) {
|
90
|
+
switch (len) { // fallthrough is intentional
|
84
91
|
case 7:
|
85
92
|
pos[6] = w8[6];
|
86
93
|
case 6:
|
data/ext/iodine/siphash.h
CHANGED
@@ -1,7 +1,14 @@
|
|
1
|
+
/*
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT except for any non-public-domain algorithms (none that I'm aware
|
4
|
+
of), which might be subject to their own licenses.
|
5
|
+
|
6
|
+
Feel free to copy, use and enjoy in accordance with to the license(s).
|
7
|
+
*/
|
1
8
|
#ifndef BS_SIPHASH_H
|
2
9
|
#define BS_SIPHASH_H
|
3
|
-
#include <stdlib.h>
|
4
10
|
#include <stdint.h>
|
11
|
+
#include <stdlib.h>
|
5
12
|
|
6
13
|
#define SIPHASH_DEFAULT_KEY \
|
7
14
|
(uint64_t[]) { 0x0706050403020100, 0x0f0e0d0c0b0a0908 }
|
data/ext/iodine/spnlock.h
CHANGED
@@ -1,12 +1,18 @@
|
|
1
|
+
/*
|
2
|
+
Copyright: Boaz segev, 2016-2017
|
3
|
+
License: MIT
|
4
|
+
|
5
|
+
Feel free to copy, use and enjoy according to the license provided.
|
6
|
+
*/
|
7
|
+
#ifndef _SPN_LOCK_H
|
1
8
|
/* *****************************************************************************
|
2
9
|
A Simple busy lock implementation ... (spnlock.h)
|
3
10
|
|
4
|
-
Based on a lot of internet reading as well as
|
11
|
+
Based on a lot of internet reading as well as comparative work (i.e the Linux
|
5
12
|
karnel's code and the more readable Apple's kernel code)
|
6
13
|
|
7
14
|
Written by Boaz Segev at 2016. Donated to the public domain for all to enjoy.
|
8
15
|
*/
|
9
|
-
#ifndef _SPN_LOCK_H
|
10
16
|
#define _SPN_LOCK_H
|
11
17
|
|
12
18
|
/* allow of the unused flag */
|
@@ -14,8 +20,8 @@ Written by Boaz Segev at 2016. Donated to the public domain for all to enjoy.
|
|
14
20
|
#define __unused __attribute__((unused))
|
15
21
|
#endif
|
16
22
|
|
17
|
-
#include <stdlib.h>
|
18
23
|
#include <stdint.h>
|
24
|
+
#include <stdlib.h>
|
19
25
|
|
20
26
|
/*********
|
21
27
|
* manage the way threads "wait" for the lock to release
|
data/ext/iodine/websockets.c
CHANGED
@@ -1,6 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
copyright: Boaz segev, 2016-2017
|
3
|
+
license: MIT
|
4
|
+
|
5
|
+
Feel free to copy, use and enjoy according to the license provided.
|
6
|
+
*/
|
1
7
|
#include "websockets.h"
|
2
8
|
#include "bscrypt.h"
|
3
9
|
#include "libserver.h"
|
10
|
+
#include "mempool.h"
|
4
11
|
#include <arpa/inet.h>
|
5
12
|
#include <stdio.h>
|
6
13
|
#include <stdlib.h>
|
@@ -34,8 +41,8 @@ struct buffer_s resize_ws_buffer(ws_s *owner, struct buffer_s);
|
|
34
41
|
/** releases an existing buffer. */
|
35
42
|
void free_ws_buffer(ws_s *owner, struct buffer_s);
|
36
43
|
|
37
|
-
/** Sets the initial buffer size. (
|
38
|
-
#define WS_INITIAL_BUFFER_SIZE
|
44
|
+
/** Sets the initial buffer size. (4Kb)*/
|
45
|
+
#define WS_INITIAL_BUFFER_SIZE 4096
|
39
46
|
|
40
47
|
/*******************************************************************************
|
41
48
|
Buffer management - simple implementation...
|
@@ -47,15 +54,16 @@ the code probably wouldn't offer a high performance boost.
|
|
47
54
|
#define round_up_buffer_size(size) (((size) >> 12) + 1) << 12
|
48
55
|
|
49
56
|
struct buffer_s create_ws_buffer(ws_s *owner) {
|
57
|
+
(void)(owner);
|
50
58
|
struct buffer_s buff;
|
51
59
|
buff.size = round_up_buffer_size(WS_INITIAL_BUFFER_SIZE);
|
52
|
-
buff.data =
|
60
|
+
buff.data = mempool_malloc(buff.size);
|
53
61
|
return buff;
|
54
62
|
}
|
55
63
|
|
56
64
|
struct buffer_s resize_ws_buffer(ws_s *owner, struct buffer_s buff) {
|
57
65
|
buff.size = round_up_buffer_size(buff.size);
|
58
|
-
void *tmp =
|
66
|
+
void *tmp = mempool_realloc(buff.data, buff.size);
|
59
67
|
if (!tmp) {
|
60
68
|
free_ws_buffer(owner, buff);
|
61
69
|
buff.size = 0;
|
@@ -64,8 +72,9 @@ struct buffer_s resize_ws_buffer(ws_s *owner, struct buffer_s buff) {
|
|
64
72
|
return buff;
|
65
73
|
}
|
66
74
|
void free_ws_buffer(ws_s *owner, struct buffer_s buff) {
|
75
|
+
(void)(owner);
|
67
76
|
if (buff.data)
|
68
|
-
|
77
|
+
mempool_free(buff.data);
|
69
78
|
}
|
70
79
|
|
71
80
|
#undef round_up_buffer_size
|
@@ -107,10 +116,8 @@ struct Websocket {
|
|
107
116
|
} psize;
|
108
117
|
size_t length;
|
109
118
|
size_t received;
|
110
|
-
int pos;
|
111
119
|
int data_len;
|
112
120
|
char mask[4];
|
113
|
-
char tmp_buffer[1024];
|
114
121
|
struct {
|
115
122
|
unsigned op_code : 4;
|
116
123
|
unsigned rsv3 : 1;
|
@@ -137,13 +144,22 @@ The Websocket Protocol Identifying String. Used for the `each` function.
|
|
137
144
|
*/
|
138
145
|
char *WEBSOCKET_ID_STR = "websockets";
|
139
146
|
|
147
|
+
/**
|
148
|
+
A thread localized buffer used for reading and parsing data from the socket.
|
149
|
+
*/
|
150
|
+
static __thread struct {
|
151
|
+
int pos;
|
152
|
+
char buffer[1024];
|
153
|
+
} read_buffer;
|
154
|
+
|
140
155
|
/*******************************************************************************
|
141
156
|
The Websocket Protocol implementation
|
142
157
|
*/
|
143
158
|
|
144
159
|
#define ws_protocol(fd) ((ws_s *)(server_get_protocol(fd)))
|
145
160
|
|
146
|
-
static void ws_ping(intptr_t fd, protocol_s *
|
161
|
+
static void ws_ping(intptr_t fd, protocol_s *ws) {
|
162
|
+
(void)(ws);
|
147
163
|
sock_packet_s *packet;
|
148
164
|
while ((packet = sock_checkout_packet()) == NULL)
|
149
165
|
sock_flush_all();
|
@@ -156,16 +172,19 @@ static void ws_ping(intptr_t fd, protocol_s *_ws) {
|
|
156
172
|
static void on_close(protocol_s *_ws) { destroy_ws((ws_s *)_ws); }
|
157
173
|
|
158
174
|
static void on_ready(intptr_t fduuid, protocol_s *ws) {
|
175
|
+
(void)(fduuid);
|
159
176
|
if (ws && ws->service == WEBSOCKET_ID_STR && ((ws_s *)ws)->on_ready)
|
160
177
|
((ws_s *)ws)->on_ready((ws_s *)ws);
|
161
178
|
}
|
162
179
|
|
163
180
|
static void on_open(intptr_t fd, protocol_s *ws, void *callback) {
|
181
|
+
(void)(fd);
|
164
182
|
if (callback && ws && ws->service == WEBSOCKET_ID_STR)
|
165
183
|
((void (*)(void *))callback)(ws);
|
166
184
|
}
|
167
185
|
|
168
186
|
static void on_shutdown(intptr_t fd, protocol_s *ws) {
|
187
|
+
(void)(fd);
|
169
188
|
if (ws && ((ws_s *)ws)->on_shutdown)
|
170
189
|
((ws_s *)ws)->on_shutdown((ws_s *)ws);
|
171
190
|
}
|
@@ -174,37 +193,37 @@ static void on_shutdown(intptr_t fd, protocol_s *ws) {
|
|
174
193
|
static void websocket_write_impl(intptr_t fd, void *data, size_t len, char text,
|
175
194
|
char first, char last, char client);
|
176
195
|
|
196
|
+
/* read data from the socket, parse it and invoke the websocket events. */
|
177
197
|
static void on_data(intptr_t sockfd, protocol_s *_ws) {
|
178
198
|
#define ws ((ws_s *)_ws)
|
179
199
|
if (ws == NULL || ws->protocol.service != WEBSOCKET_ID_STR)
|
180
200
|
return;
|
181
201
|
ssize_t len = 0;
|
182
|
-
while ((len = sock_read(sockfd,
|
202
|
+
while ((len = sock_read(sockfd, read_buffer.buffer, 1024)) > 0) {
|
183
203
|
ws->parser.data_len = 0;
|
184
|
-
|
185
|
-
while (
|
204
|
+
read_buffer.pos = 0;
|
205
|
+
while (read_buffer.pos < len) {
|
186
206
|
// collect the frame's head
|
187
207
|
if (!(*(char *)(&ws->parser.head))) {
|
188
|
-
*((char *)(&(ws->parser.head))) =
|
208
|
+
*((char *)(&(ws->parser.head))) = read_buffer.buffer[read_buffer.pos];
|
189
209
|
// save a copy if it's the first head in a fragmented message
|
190
210
|
if (!(*(char *)(&ws->parser.head2))) {
|
191
211
|
ws->parser.head2 = ws->parser.head;
|
192
212
|
}
|
193
213
|
// advance
|
194
|
-
|
214
|
+
read_buffer.pos++;
|
195
215
|
// go back to the `while` head, to review if there's more data
|
196
216
|
continue;
|
197
217
|
}
|
198
218
|
|
199
219
|
// save the mask and size information
|
200
220
|
if (!(*(char *)(&ws->parser.sdata))) {
|
201
|
-
*((char *)(&(ws->parser.sdata))) =
|
202
|
-
ws->parser.tmp_buffer[ws->parser.pos];
|
221
|
+
*((char *)(&(ws->parser.sdata))) = read_buffer.buffer[read_buffer.pos];
|
203
222
|
// set length
|
204
223
|
ws->parser.state.at_len = ws->parser.sdata.size == 127
|
205
224
|
? 7
|
206
225
|
: ws->parser.sdata.size == 126 ? 1 : 0;
|
207
|
-
|
226
|
+
read_buffer.pos++;
|
208
227
|
continue;
|
209
228
|
}
|
210
229
|
|
@@ -218,29 +237,29 @@ static void on_data(intptr_t sockfd, protocol_s *_ws) {
|
|
218
237
|
if ((ws->parser.state.at_len == 1 && ws->parser.sdata.size == 126) ||
|
219
238
|
(ws->parser.state.at_len == 7 && ws->parser.sdata.size == 127)) {
|
220
239
|
ws->parser.psize.bytes[ws->parser.state.at_len] =
|
221
|
-
|
240
|
+
read_buffer.buffer[read_buffer.pos++];
|
222
241
|
ws->parser.state.has_len = 1;
|
223
242
|
ws->parser.length = (ws->parser.sdata.size == 126)
|
224
243
|
? ws->parser.psize.len1
|
225
244
|
: ws->parser.psize.len2;
|
226
245
|
} else {
|
227
246
|
ws->parser.psize.bytes[ws->parser.state.at_len++] =
|
228
|
-
|
229
|
-
if (
|
247
|
+
read_buffer.buffer[read_buffer.pos++];
|
248
|
+
if (read_buffer.pos < len)
|
230
249
|
goto collect_len;
|
231
250
|
}
|
232
251
|
#else
|
233
252
|
if (ws->parser.state.at_len == 0) {
|
234
253
|
ws->parser.psize.bytes[ws->parser.state.at_len] =
|
235
|
-
|
254
|
+
read_buffer.buffer[read_buffer.pos++];
|
236
255
|
ws->parser.state.has_len = 1;
|
237
256
|
ws->parser.length = (ws->parser.sdata.size == 126)
|
238
257
|
? ws->parser.psize.len1
|
239
258
|
: ws->parser.psize.len2;
|
240
259
|
} else {
|
241
260
|
ws->parser.psize.bytes[ws->parser.state.at_len--] =
|
242
|
-
|
243
|
-
if (
|
261
|
+
read_buffer.buffer[read_buffer.pos++];
|
262
|
+
if (read_buffer.pos < len)
|
244
263
|
goto collect_len;
|
245
264
|
}
|
246
265
|
#endif
|
@@ -255,13 +274,13 @@ static void on_data(intptr_t sockfd, protocol_s *_ws) {
|
|
255
274
|
collect_mask:
|
256
275
|
if (ws->parser.state.at_mask == 3) {
|
257
276
|
ws->parser.mask[ws->parser.state.at_mask] =
|
258
|
-
|
277
|
+
read_buffer.buffer[read_buffer.pos++];
|
259
278
|
ws->parser.state.has_mask = 1;
|
260
279
|
ws->parser.state.at_mask = 0;
|
261
280
|
} else {
|
262
281
|
ws->parser.mask[ws->parser.state.at_mask++] =
|
263
|
-
|
264
|
-
if (
|
282
|
+
read_buffer.buffer[read_buffer.pos++];
|
283
|
+
if (read_buffer.pos < len)
|
265
284
|
goto collect_mask;
|
266
285
|
else
|
267
286
|
continue;
|
@@ -274,7 +293,7 @@ static void on_data(intptr_t sockfd, protocol_s *_ws) {
|
|
274
293
|
// Now that we know everything about the frame, let's collect the data
|
275
294
|
|
276
295
|
// How much data in the buffer is part of the frame?
|
277
|
-
ws->parser.data_len = len -
|
296
|
+
ws->parser.data_len = len - read_buffer.pos;
|
278
297
|
if (ws->parser.data_len + ws->parser.received > ws->parser.length)
|
279
298
|
ws->parser.data_len = ws->parser.length - ws->parser.received;
|
280
299
|
|
@@ -283,7 +302,7 @@ static void on_data(intptr_t sockfd, protocol_s *_ws) {
|
|
283
302
|
// unmask:
|
284
303
|
if (ws->parser.sdata.masked) {
|
285
304
|
for (int i = 0; i < ws->parser.data_len; i++) {
|
286
|
-
|
305
|
+
read_buffer.buffer[i + read_buffer.pos] ^=
|
287
306
|
ws->parser.mask[ws->parser.state.at_mask++];
|
288
307
|
}
|
289
308
|
} else if (ws->parser.state.client == 0) {
|
@@ -292,8 +311,7 @@ static void on_data(intptr_t sockfd, protocol_s *_ws) {
|
|
292
311
|
sock_close(sockfd);
|
293
312
|
return;
|
294
313
|
}
|
295
|
-
// Copy the data to the
|
296
|
-
// RubyCaller.call_c(copy_data_to_buffer_in_gvl, ws);
|
314
|
+
// Copy the data to the Websocket buffer - only if it's a user message
|
297
315
|
if (ws->parser.head.op_code == 1 || ws->parser.head.op_code == 2 ||
|
298
316
|
(!ws->parser.head.op_code &&
|
299
317
|
(ws->parser.head2.op_code == 1 || ws->parser.head2.op_code == 2))) {
|
@@ -316,7 +334,7 @@ static void on_data(intptr_t sockfd, protocol_s *_ws) {
|
|
316
334
|
}
|
317
335
|
// copy here
|
318
336
|
memcpy(ws->buffer.data + ws->length,
|
319
|
-
|
337
|
+
read_buffer.buffer + read_buffer.pos, ws->parser.data_len);
|
320
338
|
ws->length += ws->parser.data_len;
|
321
339
|
}
|
322
340
|
// set the frame's data received so far (copied or not)
|
@@ -326,7 +344,7 @@ static void on_data(intptr_t sockfd, protocol_s *_ws) {
|
|
326
344
|
|
327
345
|
// check that we have collected the whole of the frame.
|
328
346
|
if (ws->parser.length > ws->parser.received) {
|
329
|
-
|
347
|
+
read_buffer.pos += ws->parser.data_len;
|
330
348
|
continue;
|
331
349
|
}
|
332
350
|
|
@@ -358,7 +376,7 @@ static void on_data(intptr_t sockfd, protocol_s *_ws) {
|
|
358
376
|
} else if (ws->parser.head.op_code == 9) {
|
359
377
|
/* ping */
|
360
378
|
// write Pong - including ping data...
|
361
|
-
websocket_write_impl(sockfd,
|
379
|
+
websocket_write_impl(sockfd, read_buffer.buffer + read_buffer.pos,
|
362
380
|
ws->parser.data_len, 10, 1, 1,
|
363
381
|
ws->parser.state.client);
|
364
382
|
if (ws->parser.head2.op_code == ws->parser.head.op_code)
|
@@ -378,13 +396,13 @@ static void on_data(intptr_t sockfd, protocol_s *_ws) {
|
|
378
396
|
goto reset_parser;
|
379
397
|
}
|
380
398
|
// not done, but move the pos marker along
|
381
|
-
|
399
|
+
read_buffer.pos += ws->parser.data_len;
|
382
400
|
continue;
|
383
401
|
|
384
402
|
reset_parser:
|
385
403
|
// move the pos marker along - in case we have more then one frame in the
|
386
404
|
// buffer
|
387
|
-
|
405
|
+
read_buffer.pos += ws->parser.data_len;
|
388
406
|
// clear the parser
|
389
407
|
*((char *)(&(ws->parser.state))) = *((char *)(&(ws->parser.sdata))) =
|
390
408
|
*((char *)(&(ws->parser.head2))) = *((char *)(&(ws->parser.head))) =
|
@@ -404,8 +422,9 @@ Create/Destroy the websocket object
|
|
404
422
|
*/
|
405
423
|
|
406
424
|
static ws_s *new_websocket() {
|
407
|
-
// allocate the protocol object
|
408
|
-
ws_s *ws =
|
425
|
+
// allocate the protocol object
|
426
|
+
ws_s *ws = mempool_malloc(sizeof(*ws));
|
427
|
+
memset(ws, 0, sizeof(*ws));
|
409
428
|
|
410
429
|
// setup the protocol & protocol callbacks
|
411
430
|
ws->protocol.ping = ws_ping;
|
@@ -421,7 +440,7 @@ static void destroy_ws(ws_s *ws) {
|
|
421
440
|
if (ws->on_close)
|
422
441
|
ws->on_close(ws);
|
423
442
|
free_ws_buffer(ws, ws->buffer);
|
424
|
-
|
443
|
+
mempool_free(ws);
|
425
444
|
}
|
426
445
|
|
427
446
|
/*******************************************************************************
|
@@ -654,7 +673,10 @@ void websocket_close(ws_s *ws) {
|
|
654
673
|
/**
|
655
674
|
Counts the number of websocket connections.
|
656
675
|
*/
|
657
|
-
size_t websocket_count(ws_s *ws) {
|
676
|
+
size_t websocket_count(ws_s *ws) {
|
677
|
+
(void)(ws);
|
678
|
+
return server_count(WEBSOCKET_ID_STR);
|
679
|
+
}
|
658
680
|
|
659
681
|
/*******************************************************************************
|
660
682
|
Each Implementation
|
@@ -668,11 +690,13 @@ struct WSTask {
|
|
668
690
|
};
|
669
691
|
/** Performs a task on each websocket connection that shares the same process */
|
670
692
|
static void perform_ws_task(intptr_t fd, protocol_s *_ws, void *_arg) {
|
693
|
+
(void)(fd);
|
671
694
|
struct WSTask *tsk = _arg;
|
672
695
|
tsk->task((ws_s *)(_ws), tsk->arg);
|
673
696
|
}
|
674
697
|
/** clears away a wesbocket task. */
|
675
698
|
static void finish_ws_task(intptr_t fd, protocol_s *_ws, void *_arg) {
|
699
|
+
(void)(fd);
|
676
700
|
struct WSTask *tsk = _arg;
|
677
701
|
if (tsk->on_finish)
|
678
702
|
tsk->on_finish((ws_s *)(_ws), tsk->arg);
|