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.

Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -1
  3. data/README.md +5 -1
  4. data/ext/iodine/base64.c +3 -3
  5. data/ext/iodine/base64.h +3 -3
  6. data/ext/iodine/bscrypt-common.h +5 -5
  7. data/ext/iodine/bscrypt.h +4 -4
  8. data/ext/iodine/hex.c +11 -10
  9. data/ext/iodine/hex.h +3 -3
  10. data/ext/iodine/http.c +34 -27
  11. data/ext/iodine/http.h +15 -8
  12. data/ext/iodine/http1.c +63 -60
  13. data/ext/iodine/http1.h +10 -5
  14. data/ext/iodine/http1_simple_parser.c +6 -0
  15. data/ext/iodine/http1_simple_parser.h +10 -6
  16. data/ext/iodine/http_request.h +28 -22
  17. data/ext/iodine/http_response.c +22 -7
  18. data/ext/iodine/http_response.h +6 -0
  19. data/ext/iodine/http_response_http1.h +9 -1
  20. data/ext/iodine/iodine_core.c +6 -1
  21. data/ext/iodine/iodine_core.h +13 -6
  22. data/ext/iodine/iodine_http.c +6 -0
  23. data/ext/iodine/iodine_http.h +6 -0
  24. data/ext/iodine/iodine_websocket.c +23 -4
  25. data/ext/iodine/iodine_websocket.h +2 -2
  26. data/ext/iodine/libasync.c +5 -3
  27. data/ext/iodine/libasync.h +8 -8
  28. data/ext/iodine/libreact.c +8 -8
  29. data/ext/iodine/libreact.h +5 -5
  30. data/ext/iodine/libserver.c +2 -2
  31. data/ext/iodine/libserver.h +2 -2
  32. data/ext/iodine/libsock.c +2 -2
  33. data/ext/iodine/libsock.h +3 -3
  34. data/ext/iodine/mempool.h +826 -0
  35. data/ext/iodine/misc.c +14 -14
  36. data/ext/iodine/misc.h +3 -3
  37. data/ext/iodine/random.c +6 -6
  38. data/ext/iodine/random.h +3 -3
  39. data/ext/iodine/rb-call.c +6 -0
  40. data/ext/iodine/rb-call.h +2 -2
  41. data/ext/iodine/rb-libasync.h +5 -3
  42. data/ext/iodine/rb-rack-io.c +15 -3
  43. data/ext/iodine/rb-rack-io.h +5 -2
  44. data/ext/iodine/rb-registry.c +6 -0
  45. data/ext/iodine/rb-registry.h +2 -2
  46. data/ext/iodine/sha1.c +13 -11
  47. data/ext/iodine/sha1.h +3 -3
  48. data/ext/iodine/sha2.c +8 -6
  49. data/ext/iodine/sha2.h +3 -3
  50. data/ext/iodine/siphash.c +9 -2
  51. data/ext/iodine/siphash.h +8 -1
  52. data/ext/iodine/spnlock.h +9 -3
  53. data/ext/iodine/websockets.c +62 -38
  54. data/ext/iodine/websockets.h +6 -0
  55. data/ext/iodine/xor-crypt.c +3 -3
  56. data/ext/iodine/xor-crypt.h +3 -3
  57. data/lib/iodine/version.rb +1 -1
  58. metadata +3 -4
  59. data/ext/iodine/rb-call.c_old +0 -127
  60. data/ext/iodine/rb-registry_old.c_old +0 -213
@@ -1,7 +1,7 @@
1
1
  /*
2
- (un)copyright: Boaz segev, 2016
3
- License: Public Domain except for any non-public-domain algorithms, which are
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* bscrypt_fdump(const char* file_path, size_t size_limit) {
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* container = NULL;
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* bscrypt_gmtime(const time_t* timer, struct tm* tmbuf) {
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, // nonleap year
92
- 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 // leap year
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; // tm_year == The number of years since 1900
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) // leap century divisable by 400 => add leap
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) { // leap year
150
+ if ((tmbuf->tm_year & 3) == 0) { // leap year
151
151
  if (tmp > 0) {
152
152
  --tmp;
153
153
  continue;
@@ -1,7 +1,7 @@
1
1
  /*
2
- (un)copyright: Boaz segev, 2016
3
- License: Public Domain except for any non-public-domain algorithms, which are
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
  */
@@ -1,7 +1,7 @@
1
1
  /*
2
- (un)copyright: Boaz segev, 2016
3
- License: Public Domain except for any non-public-domain algorithms, which are
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 <unistd.h>
100
+ #include <fcntl.h>
102
101
  #include <pthread.h>
102
+ #include <unistd.h>
103
103
 
104
104
  /* ***************************************************************************
105
105
  Machine specific changes
@@ -1,7 +1,7 @@
1
1
  /*
2
- (un)copyright: Boaz segev, 2016
3
- License: Public Domain except for any non-public-domain algorithms, which are
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
  */
@@ -1,3 +1,9 @@
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 "rb-call.h"
2
8
  #include <pthread.h>
3
9
  #include <ruby.h>
@@ -1,6 +1,6 @@
1
1
  /*
2
- copyright: Boaz segev, 2016
3
- license: MIT
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
  */
@@ -1,14 +1,16 @@
1
1
  /*
2
- copyright: Boaz segev, 2016
3
- license: MIT
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
- #include "rb-registry.h"
13
+ // clang-format on
12
14
 
13
15
  /******************************************************************************
14
16
  Portability - used to help port this to different frameworks (i.e. Ruby).
@@ -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:
@@ -1,12 +1,15 @@
1
1
  /*
2
- copyright: Boaz segev, 2016
3
- license: MIT
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_ {
@@ -1,3 +1,9 @@
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 "rb-registry.h"
2
8
  #include "spnlock.h"
3
9
  #include <ruby.h>
@@ -1,6 +1,6 @@
1
1
  /*
2
- copyright: Boaz segev, 2016
3
- license: MIT
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
  */
@@ -1,7 +1,7 @@
1
1
  /*
2
- (un)copyright: Boaz segev, 2016
3
- License: Public Domain except for any non-public-domain algorithms, which are
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) && __has_include(<openssl/sha.h>)
280
- # include <openssl/sha.h>
281
- # define HAS_OPEN_SSL 1
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, 0xe1,
292
- 0xbb, 0x76, 0xe7, 0x39, 0x1b, 0x93, 0xeb, 0x12,
293
- 0}}, // a set with a string
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, 0xbf,
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
  };
@@ -1,7 +1,7 @@
1
1
  /*
2
- (un)copyright: Boaz segev, 2016
3
- License: Public Domain except for any non-public-domain algorithms, which are
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
  */
@@ -1,7 +1,7 @@
1
1
  /*
2
- (un)copyright: Boaz segev, 2016
3
- License: Public Domain except for any non-public-domain algorithms, which are
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) && __has_include(<openssl/sha.h>)
662
- # include <openssl/sha.h>
663
- # define HAS_OPEN_SSL 1
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
 
@@ -1,7 +1,7 @@
1
1
  /*
2
- (un)copyright: Boaz segev, 2016
3
- License: Public Domain except for any non-public-domain algorithms, which are
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
  */
@@ -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:
@@ -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 }
@@ -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 comperative work (i.e the Linux
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
@@ -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. (16Kb)*/
38
- #define WS_INITIAL_BUFFER_SIZE 16384
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 = malloc(buff.size);
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 = realloc(buff.data, buff.size);
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
- free(buff.data);
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 *_ws) {
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, ws->parser.tmp_buffer, 1024)) > 0) {
202
+ while ((len = sock_read(sockfd, read_buffer.buffer, 1024)) > 0) {
183
203
  ws->parser.data_len = 0;
184
- ws->parser.pos = 0;
185
- while (ws->parser.pos < len) {
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))) = ws->parser.tmp_buffer[ws->parser.pos];
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
- ws->parser.pos++;
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
- ws->parser.pos++;
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
- ws->parser.tmp_buffer[ws->parser.pos++];
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
- ws->parser.tmp_buffer[ws->parser.pos++];
229
- if (ws->parser.pos < len)
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
- ws->parser.tmp_buffer[ws->parser.pos++];
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
- ws->parser.tmp_buffer[ws->parser.pos++];
243
- if (ws->parser.pos < len)
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
- ws->parser.tmp_buffer[ws->parser.pos++];
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
- ws->parser.tmp_buffer[ws->parser.pos++];
264
- if (ws->parser.pos < len)
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 - ws->parser.pos;
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
- ws->parser.tmp_buffer[i + ws->parser.pos] ^=
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 Ruby buffer - only if it's a user message
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
- ws->parser.tmp_buffer + ws->parser.pos, ws->parser.data_len);
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
- ws->parser.pos += ws->parser.data_len;
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, ws->parser.tmp_buffer + ws->parser.pos,
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
- ws->parser.pos += ws->parser.data_len;
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
- ws->parser.pos += ws->parser.data_len;
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 (TODO: (maybe) pooling)
408
- ws_s *ws = calloc(sizeof(*ws), 1);
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
- free(ws);
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) { return server_count(WEBSOCKET_ID_STR); }
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);