iodine 0.4.19 → 0.5.0

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.

Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -2
  3. data/CHANGELOG.md +22 -0
  4. data/LIMITS.md +19 -9
  5. data/README.md +92 -77
  6. data/SPEC-PubSub-Draft.md +113 -0
  7. data/SPEC-Websocket-Draft.md +127 -143
  8. data/bin/http-hello +0 -1
  9. data/bin/raw-rbhttp +1 -1
  10. data/bin/raw_broadcast +8 -10
  11. data/bin/updated api +2 -2
  12. data/bin/ws-broadcast +2 -4
  13. data/bin/ws-echo +2 -2
  14. data/examples/config.ru +13 -13
  15. data/examples/echo.ru +5 -6
  16. data/examples/hello.ru +2 -3
  17. data/examples/info.md +316 -0
  18. data/examples/pubsub_engine.ru +81 -0
  19. data/examples/redis.ru +9 -9
  20. data/examples/shootout.ru +45 -11
  21. data/ext/iodine/defer.c +194 -297
  22. data/ext/iodine/defer.h +61 -53
  23. data/ext/iodine/evio.c +0 -260
  24. data/ext/iodine/evio.h +50 -22
  25. data/ext/iodine/evio_callbacks.c +26 -0
  26. data/ext/iodine/evio_epoll.c +251 -0
  27. data/ext/iodine/evio_kqueue.c +193 -0
  28. data/ext/iodine/extconf.rb +1 -1
  29. data/ext/iodine/facil.c +1420 -542
  30. data/ext/iodine/facil.h +151 -64
  31. data/ext/iodine/fio_ary.h +418 -0
  32. data/ext/iodine/{base64.c → fio_base64.c} +33 -24
  33. data/ext/iodine/{base64.h → fio_base64.h} +6 -7
  34. data/ext/iodine/{fio_cli_helper.c → fio_cli.c} +77 -58
  35. data/ext/iodine/{fio_cli_helper.h → fio_cli.h} +9 -4
  36. data/ext/iodine/fio_hashmap.h +759 -0
  37. data/ext/iodine/fio_json_parser.h +651 -0
  38. data/ext/iodine/fio_llist.h +257 -0
  39. data/ext/iodine/fio_mem.c +672 -0
  40. data/ext/iodine/fio_mem.h +140 -0
  41. data/ext/iodine/fio_random.c +248 -0
  42. data/ext/iodine/{random.h → fio_random.h} +11 -14
  43. data/ext/iodine/{sha1.c → fio_sha1.c} +28 -24
  44. data/ext/iodine/{sha1.h → fio_sha1.h} +38 -16
  45. data/ext/iodine/{sha2.c → fio_sha2.c} +66 -49
  46. data/ext/iodine/{sha2.h → fio_sha2.h} +57 -26
  47. data/ext/iodine/{fiobj_internal.c → fio_siphash.c} +9 -90
  48. data/ext/iodine/fio_siphash.h +18 -0
  49. data/ext/iodine/fio_tmpfile.h +38 -0
  50. data/ext/iodine/fiobj.h +24 -7
  51. data/ext/iodine/fiobj4sock.h +23 -0
  52. data/ext/iodine/fiobj_ary.c +143 -226
  53. data/ext/iodine/fiobj_ary.h +17 -16
  54. data/ext/iodine/fiobj_data.c +1160 -0
  55. data/ext/iodine/fiobj_data.h +164 -0
  56. data/ext/iodine/fiobj_hash.c +298 -406
  57. data/ext/iodine/fiobj_hash.h +101 -54
  58. data/ext/iodine/fiobj_json.c +478 -601
  59. data/ext/iodine/fiobj_json.h +34 -9
  60. data/ext/iodine/fiobj_numbers.c +383 -51
  61. data/ext/iodine/fiobj_numbers.h +87 -11
  62. data/ext/iodine/fiobj_str.c +423 -184
  63. data/ext/iodine/fiobj_str.h +81 -32
  64. data/ext/iodine/fiobject.c +273 -522
  65. data/ext/iodine/fiobject.h +477 -112
  66. data/ext/iodine/http.c +2243 -83
  67. data/ext/iodine/http.h +842 -121
  68. data/ext/iodine/http1.c +810 -385
  69. data/ext/iodine/http1.h +16 -39
  70. data/ext/iodine/http1_parser.c +146 -74
  71. data/ext/iodine/http1_parser.h +15 -4
  72. data/ext/iodine/http_internal.c +1258 -0
  73. data/ext/iodine/http_internal.h +226 -0
  74. data/ext/iodine/http_mime_parser.h +341 -0
  75. data/ext/iodine/iodine.c +86 -68
  76. data/ext/iodine/iodine.h +26 -11
  77. data/ext/iodine/iodine_helpers.c +8 -7
  78. data/ext/iodine/iodine_http.c +487 -324
  79. data/ext/iodine/iodine_json.c +304 -0
  80. data/ext/iodine/iodine_json.h +6 -0
  81. data/ext/iodine/iodine_protocol.c +107 -45
  82. data/ext/iodine/iodine_pubsub.c +526 -225
  83. data/ext/iodine/iodine_pubsub.h +10 -0
  84. data/ext/iodine/iodine_websockets.c +268 -510
  85. data/ext/iodine/iodine_websockets.h +2 -4
  86. data/ext/iodine/pubsub.c +726 -432
  87. data/ext/iodine/pubsub.h +85 -103
  88. data/ext/iodine/rb-call.c +4 -4
  89. data/ext/iodine/rb-defer.c +46 -22
  90. data/ext/iodine/rb-fiobj2rb.h +117 -0
  91. data/ext/iodine/rb-rack-io.c +73 -238
  92. data/ext/iodine/rb-rack-io.h +2 -2
  93. data/ext/iodine/rb-registry.c +35 -93
  94. data/ext/iodine/rb-registry.h +1 -0
  95. data/ext/iodine/redis_engine.c +742 -304
  96. data/ext/iodine/redis_engine.h +42 -39
  97. data/ext/iodine/resp_parser.h +311 -0
  98. data/ext/iodine/sock.c +627 -490
  99. data/ext/iodine/sock.h +345 -297
  100. data/ext/iodine/spnlock.inc +15 -4
  101. data/ext/iodine/websocket_parser.h +16 -20
  102. data/ext/iodine/websockets.c +188 -257
  103. data/ext/iodine/websockets.h +24 -133
  104. data/lib/iodine.rb +52 -7
  105. data/lib/iodine/cli.rb +6 -24
  106. data/lib/iodine/json.rb +40 -0
  107. data/lib/iodine/version.rb +1 -1
  108. data/lib/iodine/websocket.rb +5 -3
  109. data/lib/rack/handler/iodine.rb +58 -13
  110. metadata +38 -48
  111. data/bin/ws-shootout +0 -107
  112. data/examples/broadcast.ru +0 -56
  113. data/ext/iodine/bscrypt-common.h +0 -116
  114. data/ext/iodine/bscrypt.h +0 -49
  115. data/ext/iodine/fio2resp.c +0 -60
  116. data/ext/iodine/fio2resp.h +0 -51
  117. data/ext/iodine/fio_dict.c +0 -446
  118. data/ext/iodine/fio_dict.h +0 -99
  119. data/ext/iodine/fio_hash_table.h +0 -370
  120. data/ext/iodine/fio_list.h +0 -111
  121. data/ext/iodine/fiobj_internal.h +0 -280
  122. data/ext/iodine/fiobj_primitives.c +0 -131
  123. data/ext/iodine/fiobj_primitives.h +0 -55
  124. data/ext/iodine/fiobj_sym.c +0 -135
  125. data/ext/iodine/fiobj_sym.h +0 -60
  126. data/ext/iodine/hex.c +0 -124
  127. data/ext/iodine/hex.h +0 -70
  128. data/ext/iodine/http1_request.c +0 -81
  129. data/ext/iodine/http1_request.h +0 -58
  130. data/ext/iodine/http1_response.c +0 -417
  131. data/ext/iodine/http1_response.h +0 -95
  132. data/ext/iodine/http_request.c +0 -111
  133. data/ext/iodine/http_request.h +0 -102
  134. data/ext/iodine/http_response.c +0 -1703
  135. data/ext/iodine/http_response.h +0 -250
  136. data/ext/iodine/misc.c +0 -182
  137. data/ext/iodine/misc.h +0 -74
  138. data/ext/iodine/random.c +0 -208
  139. data/ext/iodine/redis_connection.c +0 -278
  140. data/ext/iodine/redis_connection.h +0 -86
  141. data/ext/iodine/resp.c +0 -842
  142. data/ext/iodine/resp.h +0 -261
  143. data/ext/iodine/siphash.c +0 -154
  144. data/ext/iodine/siphash.h +0 -22
  145. data/ext/iodine/xor-crypt.c +0 -193
  146. data/ext/iodine/xor-crypt.h +0 -107
data/ext/iodine/resp.h DELETED
@@ -1,261 +0,0 @@
1
- /*
2
- Copyright: Boaz segev, 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
- */
8
- #ifndef H_RESP_PARSER_H
9
- /**
10
- This is a neive implementation of the RESP protocol for Redis.
11
- */
12
- #define H_RESP_PARSER_H
13
-
14
- #include <stdint.h>
15
- #include <stdlib.h>
16
-
17
- /* support C++ */
18
- #ifdef __cplusplus
19
- extern "C" {
20
- #endif
21
-
22
- /** The RESP Parser Type */
23
- typedef struct resp_parser_s *resp_parser_pt;
24
-
25
- /* *****************************************************************************
26
- RESP types and objects (Arrays, Strings & Integers)
27
- ***************************************************************************** */
28
-
29
- enum resp_type_enum {
30
- /** A simple flag object object (`resp_object_s`) for NULL. */
31
- RESP_NULL = 0,
32
- /** A simple flag object object (`resp_object_s`) for OK. */
33
- RESP_OK = 1,
34
- /** A String object (`resp_string_s`) that indicates an error. */
35
- RESP_ERR = (2 + 8),
36
- /** A Number object object (`resp_number_s`). */
37
- RESP_NUMBER = 4,
38
- /** A String object (`resp_string_s`). */
39
- RESP_STRING = 8,
40
- /** An Array object object (`resp_array_s`). */
41
- RESP_ARRAY = 16,
42
- /**
43
- * A specific Array object object (`resp_array_s`) for Pub/Sub semantics.
44
- *
45
- * This is more of a hint than a decree, sometimes pubsub semantics are
46
- * misleading.
47
- */
48
- RESP_PUBSUB = (32 + 16),
49
- };
50
-
51
- /** a simple emtpy object type, used for RESP_NULL and RESP_OK */
52
- typedef struct { enum resp_type_enum type; } resp_object_s;
53
-
54
- /** The RESP_ARRAY and RESP_PUBSUB types */
55
- typedef struct {
56
- enum resp_type_enum type;
57
- size_t len;
58
- size_t pos; /** allows simple iteration. */
59
- resp_object_s *array[];
60
- } resp_array_s;
61
-
62
- /** The RESP_STRING and RESP_ERR types */
63
- typedef struct {
64
- enum resp_type_enum type;
65
- size_t len;
66
- uint8_t string[];
67
- } resp_string_s;
68
-
69
- /** The RESP_NUMBER type */
70
- typedef struct {
71
- enum resp_type_enum type;
72
- int64_t number;
73
- } resp_number_s;
74
-
75
- #define resp_obj2arr(obj) \
76
- ((resp_array_s *)((obj)->type == RESP_ARRAY || (obj)->type == RESP_PUBSUB \
77
- ? (obj) \
78
- : NULL))
79
- #define resp_obj2str(obj) \
80
- ((resp_string_s *)((obj)->type == RESP_STRING || (obj)->type == RESP_ERR \
81
- ? (obj) \
82
- : NULL))
83
- #define resp_obj2num(obj) \
84
- ((resp_number_s *)((obj)->type == RESP_NUMBER ? (obj) : NULL))
85
-
86
- /** Allocates an RESP NULL objcet. Remeber to free when done. */
87
- resp_object_s *resp_nil2obj(void);
88
-
89
- /** Allocates an RESP OK objcet. Remeber to free when done. */
90
- resp_object_s *resp_OK2obj(void);
91
-
92
- /** Allocates an RESP Error objcet. Remeber to free when done. */
93
- resp_object_s *resp_err2obj(const void *msg, size_t len);
94
-
95
- /** Allocates an RESP Number objcet. Remeber to free when done. */
96
- resp_object_s *resp_num2obj(uint64_t num);
97
-
98
- /** Allocates an RESP String objcet. Remeber to free when done. */
99
- resp_object_s *resp_str2obj(const void *str, size_t len);
100
-
101
- /**
102
- *Allocates an RESP Array objcet. Remeber to free when done (freeing an array
103
- *frees it's children automatically).
104
- *
105
- * It's possible to pass NULL as the `argv`, in which case the array created
106
- * will have the capacity `argc` and could me manually populated.
107
- *
108
- * The objects are MOVED into the array's possesion. If you wish to retain a
109
- * copy of the objects, use the `resp_dup_object` to increase their reference
110
- * count.
111
- */
112
- resp_object_s *resp_arr2obj(int argc, resp_object_s *argv[]);
113
-
114
- /** Duplicates an object by increasing it's reference count. */
115
- resp_object_s *resp_dup_object(resp_object_s *obj);
116
-
117
- /** frees an object by decreasing it's reference count and testing. */
118
- void resp_free_object(resp_object_s *obj);
119
-
120
- /**
121
- * Formats a RESP object back into a string.
122
- *
123
- * Returns 0 on success and -1 on failur.
124
- *
125
- * Accepts a memory buffer `dest` to which the data will be written and a poiner
126
- * to the size of the buffer.
127
- *
128
- * Once the function returns, `size` will be updated to include the number of
129
- * bytes required for the string. If the function returned a failure, this value
130
- * can be used to allocate enough memory to contain the string.
131
- *
132
- * The string is Binary safe and it ISN'T always NUL terminated.
133
- *
134
- * The optional `parser` argument allows experimental extensions to be used when
135
- * formatting the object. It can be ignored when formatting without extensions.
136
- *
137
- * **If implementing a server**:
138
- *
139
- * When implementing a server, Pub/Sub should avoid multiple copies by using a
140
- * dedicated buffer with a reference count. By decreasing the reference count
141
- * every time the message was sent (see the `sock_write2` support for the
142
- * dealloc callback), it's possible to avoid multiple copies of the message.
143
- */
144
- int resp_format(resp_parser_pt p, uint8_t *dest, size_t *size,
145
- resp_object_s *obj);
146
-
147
- /**
148
- * Performs a task on each object. Protects from loop-backs.
149
- *
150
- * To break loop in the middle, `task` can return -1.
151
- *
152
- * Returns count.
153
- */
154
- size_t resp_obj_each(resp_parser_pt p, resp_object_s *obj,
155
- int (*task)(resp_parser_pt p, resp_object_s *obj,
156
- void *arg),
157
- void *arg);
158
-
159
- /* *****************************************************************************
160
- The RESP Parser
161
- ***************************************************************************** */
162
-
163
- /** create the parser */
164
- resp_parser_pt resp_parser_new(void);
165
-
166
- /** free the parser and it's resources. */
167
- void resp_parser_destroy(resp_parser_pt);
168
-
169
- /** Clears the parser state, as if starting a new session / connection. */
170
- void resp_parser_clear(resp_parser_pt);
171
-
172
- /**
173
- * Feed the parser with data.
174
- *
175
- * Returns any fully parsed object / reply (often an array, but not always) or
176
- * NULL (needs more data / error).
177
- *
178
- * If a RESP object was parsed, it is returned and `len` is updated to reflect
179
- * the number of bytes actually read.
180
- *
181
- * If more data is needed, NULL is returned and `len` is left unchanged.
182
- *
183
- * An error is reported by by returning NULL and setting `len` to 0 at the same
184
- * time.
185
- *
186
- * Partial consumption is possible when multiple replys were available in the
187
- * buffer. Otherwise the parser will consume the whole of the buffer.
188
- *
189
- */
190
- resp_object_s *resp_parser_feed(resp_parser_pt, uint8_t *buffer, size_t *len);
191
-
192
- /* *****************************************************************************
193
- State - The Pub / Sub Multiplexer (Experimental)
194
- ***************************************************************************** */
195
-
196
- /**
197
- It seems to me that the main reason that pub/sub messages and normal RESP
198
- connetcions cannot share the same socket is the risk of identity collisions.
199
-
200
- For example, the command LRANGE might return the following array response
201
- `["message", "users", "hello"]`... this looks exactly like a Pub/Sub
202
- notification.
203
-
204
- However, this situation is very uncomfortable. For example:
205
-
206
- * The sender already knows the content of the message. There is no reason to
207
- waste bandwidth to send the same message back to the sender using a different
208
- socket.
209
-
210
- * The cost isn't just Bandwidth, but also memory, since the sender will have two
211
- copies of the same message (if not more), the one being sent and the other
212
- being received (sometimes more then once, for different channel patterns).
213
-
214
-
215
- * Instead of handling the message localy, the sender is forced to wait until the
216
- message is received by the pub/sub Redis conection - otherwise tere will be
217
- duplicate messages being published.
218
-
219
- * This design doubles the client load (number of connections) for each Redis
220
- server (and client).
221
-
222
- But we can solve this.
223
-
224
- For example, what if we use a "magic byte" to distinguish between the array
225
- `["message", "users", "hello"]` and the pub/sub notification `["message",
226
- "users", "hello"]`?
227
-
228
- What if every time the first word in an array response satrts with an `"m"` or a
229
- `"+"`, we will add the `"+"` byte infront of it?
230
-
231
- Now the notification will look like this: `["message", "users", "hello"]`, and
232
- the array response (i.e. to `LRANGE`) will be: `["+message", "users", "hello"]`
233
- - a distinct difference allowing for pub/sub and regular conections to use the
234
- same pipelining socket.
235
-
236
- The big issue (and I may be wrong), is backwards compatibility - we can't change
237
- the semantics of the protocol without breaking existing clients... or can we?
238
-
239
- I believe this hurdle can be easily circumvented by adding a single command to
240
- the existing pallet. Somthing along the lines of: `ENABLE <feature>`.
241
-
242
- Such a flexible command allows clients to negotiate changes to the semantics
243
- for the connection. It's meant to be a single non-reversible change for the
244
- specific connection (similar to the `Upgrade` HTTP/Websocket concept).
245
-
246
- Now, the little `"+"` "magic byte" can be easily handled.
247
-
248
- The following function activates the "magic byte" assuming the `ENABLE` command
249
- was negotiated for the connection.
250
- */
251
- void resp_enable_duplex_pubsub(resp_parser_pt parser);
252
-
253
- #ifdef DEBUG
254
- void resp_test(void);
255
- #endif
256
-
257
- #ifdef __cplusplus
258
- } /* extern "C" */
259
- #endif
260
-
261
- #endif
data/ext/iodine/siphash.c DELETED
@@ -1,154 +0,0 @@
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
- */
8
- #include "siphash.h"
9
- #include <stdint.h>
10
- #include <stdlib.h>
11
-
12
- // clang-format off
13
- #if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
14
- # if defined(__has_include)
15
- # if __has_include(<endian.h>)
16
- # include <endian.h>
17
- # elif __has_include(<sys/endian.h>)
18
- # include <sys/endian.h>
19
- # endif
20
- # endif
21
- # if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) && \
22
- __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
23
- # define __BIG_ENDIAN__
24
- # endif
25
- #endif
26
-
27
- #ifndef UNUSED_FUNC
28
- # define UNUSED_FUNC __attribute__((unused))
29
- #endif
30
- // clang-format on
31
-
32
- /** 64Bit left rotation, inlined. */
33
- #define _lrot64(i, bits) \
34
- (((uint64_t)(i) << (bits)) | ((uint64_t)(i) >> (64 - (bits))))
35
-
36
- #ifdef __BIG_ENDIAN__
37
- /* the algorithm was designed as little endian */
38
- /** inplace byte swap 64 bit integer */
39
- #define sip_local64(i) \
40
- (((i)&0xFFULL) << 56) | (((i)&0xFF00ULL) << 40) | \
41
- (((i)&0xFF0000ULL) << 24) | (((i)&0xFF000000ULL) << 8) | \
42
- (((i)&0xFF00000000ULL) >> 8) | (((i)&0xFF0000000000ULL) >> 24) | \
43
- (((i)&0xFF000000000000ULL) >> 40) | (((i)&0xFF00000000000000ULL) >> 56)
44
-
45
- #else
46
- /** no need */
47
- #define sip_local64(i) (i)
48
- #endif
49
-
50
- uint64_t siphash24(const void *data, size_t len, uint64_t iv_key[2]) {
51
- /* initialize the 4 words */
52
- uint64_t v0 = iv_key[0] ^ 0x736f6d6570736575ULL;
53
- uint64_t v1 = iv_key[1] ^ 0x646f72616e646f6dULL;
54
- uint64_t v2 = iv_key[0] ^ 0x6c7967656e657261ULL;
55
- uint64_t v3 = iv_key[1] ^ 0x7465646279746573ULL;
56
- const uint64_t *w64 = data;
57
- uint8_t len_mod = len & 255;
58
- union {
59
- uint64_t i;
60
- uint8_t str[8];
61
- } word;
62
-
63
- #define _bs_map_SipRound \
64
- do { \
65
- v2 += v3; \
66
- v3 = _lrot64(v3, 16) ^ v2; \
67
- v0 += v1; \
68
- v1 = _lrot64(v1, 13) ^ v0; \
69
- v0 = _lrot64(v0, 32); \
70
- v2 += v1; \
71
- v0 += v3; \
72
- v1 = _lrot64(v1, 17) ^ v2; \
73
- v3 = _lrot64(v3, 21) ^ v0; \
74
- v2 = _lrot64(v2, 32); \
75
- } while (0);
76
-
77
- while (len >= 8) {
78
- word.i = sip_local64(*w64);
79
- v3 ^= word.i;
80
- /* Sip Rounds */
81
- _bs_map_SipRound;
82
- _bs_map_SipRound;
83
- v0 ^= word.i;
84
- w64 += 1;
85
- len -= 8;
86
- }
87
- word.i = 0;
88
- uint8_t *pos = word.str;
89
- uint8_t *w8 = (void *)w64;
90
- switch (len) { // fallthrough is intentional
91
- case 7:
92
- pos[6] = w8[6];
93
- case 6:
94
- pos[5] = w8[5];
95
- case 5:
96
- pos[4] = w8[4];
97
- case 4:
98
- pos[3] = w8[3];
99
- case 3:
100
- pos[2] = w8[2];
101
- case 2:
102
- pos[1] = w8[1];
103
- case 1:
104
- pos[0] = w8[0];
105
- }
106
- word.str[7] = len_mod;
107
- // word.i = sip_local64(word.i);
108
-
109
- /* last round */
110
- v3 ^= word.i;
111
- _bs_map_SipRound;
112
- _bs_map_SipRound;
113
- v0 ^= word.i;
114
- /* Finalization */
115
- v2 ^= 0xff;
116
- /* d iterations of SipRound */
117
- _bs_map_SipRound;
118
- _bs_map_SipRound;
119
- _bs_map_SipRound;
120
- _bs_map_SipRound;
121
- /* XOR it all together */
122
- v0 ^= v1 ^ v2 ^ v3;
123
- #undef _bs_map_SipRound
124
- return v0;
125
- }
126
-
127
- #undef sip_local64
128
- #undef _lrot64
129
-
130
- #if defined(DEBUG) && DEBUG == 1
131
-
132
- #include <stdio.h>
133
- #include <time.h>
134
-
135
- void bscrypt_test_siphash(void) {
136
- uint64_t result =
137
- siphash24("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e",
138
- 15, SIPHASH_DEFAULT_KEY);
139
- fprintf(stderr, "===================================\n");
140
- fprintf(stderr, "SipHash simple test %s\n",
141
- (result == 0xa129ca6149be45e5ULL) ? "passed" : "FAILED");
142
- clock_t start;
143
- start = clock();
144
- for (size_t i = 0; i < 100000; i++) {
145
- __asm__ volatile("" ::: "memory");
146
- result = siphash24("The quick brown fox jumps over the lazy dog ", 43,
147
- SIPHASH_DEFAULT_KEY);
148
- }
149
- fprintf(stderr, "bscrypt 100K SipHash: %lf\n",
150
- (double)(clock() - start) / CLOCKS_PER_SEC);
151
- fprintf(stderr, "===================================\n");
152
- }
153
-
154
- #endif
data/ext/iodine/siphash.h DELETED
@@ -1,22 +0,0 @@
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
- */
8
- #ifndef BS_SIPHASH_H
9
- #define BS_SIPHASH_H
10
- #include <stdint.h>
11
- #include <stdlib.h>
12
-
13
- #define SIPHASH_DEFAULT_KEY \
14
- (uint64_t[]) { 0x0706050403020100, 0x0f0e0d0c0b0a0908 }
15
- uint64_t siphash24(const void *data, size_t len, uint64_t iv_key[2]);
16
-
17
- #if defined(DEBUG) && DEBUG == 1
18
- void bscrypt_test_siphash(void);
19
-
20
- #endif
21
-
22
- #endif
@@ -1,193 +0,0 @@
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
- */
8
- #ifndef _GNU_SOURCE
9
- #define _GNU_SOURCE
10
- #endif
11
- #include "xor-crypt.h"
12
- /*****************************************************************************
13
- Useful Macros
14
- */
15
-
16
- /** 32Bit left rotation, inlined. */
17
- #define left_rotate32(i, bits) \
18
- (((uint32_t)(i) << (bits)) | ((uint32_t)(i) >> (32 - (bits))))
19
- /** 32Bit right rotation, inlined. */
20
- #define right_rotate32(i, bits) \
21
- (((uint32_t)(i) >> (bits)) | ((uint32_t)(i) << (32 - (bits))))
22
- /** 64Bit left rotation, inlined. */
23
- #define left_rotate64(i, bits) \
24
- (((uint64_t)(i) << (bits)) | ((uint64_t)(i) >> (64 - (bits))))
25
- /** 64Bit right rotation, inlined. */
26
- #define right_rotate64(i, bits) \
27
- (((uint64_t)(i) >> (bits)) | ((uint64_t)(i) << (64 - (bits))))
28
- /** unknown size element - left rotation, inlined. */
29
- #define left_rotate(i, bits) (((i) << (bits)) | ((i) >> (sizeof((i)) - (bits))))
30
- /** unknown size element - right rotation, inlined. */
31
- #define right_rotate(i, bits) \
32
- (((i) >> (bits)) | ((i) << (sizeof((i)) - (bits))))
33
- /** inplace byte swap 16 bit integer */
34
- #define bswap16(i) \
35
- do { \
36
- (i) = (((i)&0xFFU) << 8) | (((i)&0xFF00U) >> 8); \
37
- } while (0);
38
- /** inplace byte swap 32 bit integer */
39
- #define bswap32(i) \
40
- do { \
41
- (i) = (((i)&0xFFUL) << 24) | (((i)&0xFF00UL) << 8) | \
42
- (((i)&0xFF0000UL) >> 8) | (((i)&0xFF000000UL) >> 24); \
43
- } while (0);
44
- /** inplace byte swap 64 bit integer */
45
- #define bswap64(i) \
46
- do { \
47
- (i) = (((i)&0xFFULL) << 56) | (((i)&0xFF00ULL) << 40) | \
48
- (((i)&0xFF0000ULL) << 24) | (((i)&0xFF000000ULL) << 8) | \
49
- (((i)&0xFF00000000ULL) >> 8) | (((i)&0xFF0000000000ULL) >> 24) | \
50
- (((i)&0xFF000000000000ULL) >> 40) | \
51
- (((i)&0xFF00000000000000ULL) >> 56); \
52
- } while (0);
53
-
54
- #ifdef HAVE_X86Intrin
55
- #undef bswap64
56
- #define bswap64(i) \
57
- { __asm__("bswapq %0" : "+r"(i) :); }
58
-
59
- // shadow sched_yield as _mm_pause for spinwait
60
- #define sched_yield() _mm_pause()
61
- #endif
62
-
63
- /* ***************************************************************************
64
- XOR encryption
65
- */
66
-
67
- /**
68
- Uses an XOR key `xor_key_s` to encrypt / decrypt the data provided.
69
-
70
- Encryption/decryption can be destructive (the target and the source can point
71
- to the same object).
72
-
73
- The key's `on_cycle` callback option should be utilized to er-calculate the
74
- key every cycle. Otherwise, XOR encryption should be avoided.
75
-
76
- A more secure encryption would be easier to implement using seperate
77
- `xor_key_s` objects for encryption and decription.
78
-
79
- If `target` is NULL, the source will be used as the target (destructive mode).
80
-
81
- Returns -1 on error and 0 on success.
82
- */
83
- int bscrypt_xor_crypt(xor_key_s *key, void *target, const void *source,
84
- size_t length) {
85
- if (!source || !key)
86
- return -1;
87
- if (!length)
88
- return 0;
89
- if (!target)
90
- target = (void *)source;
91
- if (key->on_cycle) {
92
- /* loop to provide vector initialization when needed. */
93
- while (key->position >= key->length) {
94
- if (key->on_cycle(key))
95
- return -1;
96
- key->position -= key->length;
97
- }
98
- } else if (key->position >= key->length)
99
- key->position = 0; /* no callback? no need for vector alterations. */
100
- size_t i = 0;
101
-
102
- /* start decryption */
103
- while (length > i) {
104
- while ((key->length - key->position >= 8) // we have 8 bytes for key.
105
- && ((i + 8) <= length) // we have 8 bytes for stream.
106
- && (((uintptr_t)((uintptr_t)target + i)) & 7) ==
107
- 0 // target memory is aligned.
108
- && (((uintptr_t)((uintptr_t)source + i)) & 7) ==
109
- 0 // source memory is aligned.
110
- && ((uintptr_t)(key->key + key->position) & 7) == 0 // key aligned.
111
- ) {
112
- // fprintf(stderr, "XOR optimization used i= %lu, key pos = %lu.\n", i,
113
- // key->position);
114
- *((uint64_t *)((uintptr_t)target + i)) =
115
- *((uint64_t *)((uintptr_t)source + i)) ^
116
- *((uint64_t *)(key->key + key->position));
117
- key->position += 8;
118
- i += 8;
119
- if (key->position < key->length)
120
- continue;
121
- if (key->on_cycle && key->on_cycle(key))
122
- return -1;
123
- key->position = 0;
124
- }
125
-
126
- if (i < length) {
127
- // fprintf(stderr, "XOR single byte.\n");
128
- *((uint8_t *)((uintptr_t)target + i)) =
129
- *((uint8_t *)((uintptr_t)source + i)) ^
130
- *((uint8_t *)(key->key + key->position));
131
- ++i;
132
- ++key->position;
133
- if (key->position == key->length) {
134
- if (key->on_cycle && key->on_cycle(key))
135
- return -1;
136
- key->position = 0;
137
- }
138
- }
139
- }
140
- return 0;
141
- }
142
-
143
- /**
144
- Similar to the bscrypt_xor_crypt except with a fixed key size of 128bits.
145
- */
146
- int bscrypt_xor128_crypt(uint64_t *key, void *target, const void *source,
147
- size_t length, int (*on_cycle)(uint64_t *key)) {
148
- length = length & 31;
149
- uint8_t pos = 0;
150
- for (size_t i = 0; i < (length >> 3); i++) {
151
- ((uint64_t *)target)[0] = ((uint64_t *)source)[0] ^ key[pos++];
152
- target = (void *)((uintptr_t)target + 8);
153
- source = (void *)((uintptr_t)source + 8);
154
- if (pos < 2)
155
- continue;
156
- if (on_cycle && on_cycle(key))
157
- return -1;
158
- pos = 0;
159
- }
160
- length = length & 7;
161
- for (size_t i = 0; i < length; i++) {
162
- ((uint64_t *)target)[i] = ((uint64_t *)source)[i] ^ key[pos];
163
- }
164
- return 0;
165
- }
166
- /**
167
- Similar to the bscrypt_xor_crypt except with a fixed key size of 256bits.
168
- */
169
- int bscrypt_xor256_crypt(uint64_t *key, void *target, const void *source,
170
- size_t length, int (*on_cycle)(uint64_t *key)) {
171
- for (size_t i = 0; i < (length >> 5); i++) {
172
- ((uint64_t *)target)[0] = ((uint64_t *)source)[0] ^ key[0];
173
- ((uint64_t *)target)[1] = ((uint64_t *)source)[1] ^ key[1];
174
- ((uint64_t *)target)[2] = ((uint64_t *)source)[2] ^ key[2];
175
- ((uint64_t *)target)[3] = ((uint64_t *)source)[3] ^ key[3];
176
- target = (void *)((uintptr_t)target + 32);
177
- source = (void *)((uintptr_t)source + 32);
178
- if (on_cycle && on_cycle(key))
179
- return -1;
180
- }
181
- length = length & 31;
182
- uint8_t pos = 0;
183
- for (size_t i = 0; i < (length >> 3); i++) {
184
- ((uint64_t *)target)[0] = ((uint64_t *)source)[0] ^ key[pos++];
185
- target = (void *)((uintptr_t)target + 8);
186
- source = (void *)((uintptr_t)source + 8);
187
- }
188
- length = length & 7;
189
- for (size_t i = 0; i < length; i++) {
190
- ((uint64_t *)target)[i] = ((uint64_t *)source)[i] ^ key[pos];
191
- }
192
- return 0;
193
- }