iodine 0.1.21 → 0.2.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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -2
  3. data/.travis.yml +23 -2
  4. data/CHANGELOG.md +9 -2
  5. data/README.md +232 -179
  6. data/Rakefile +13 -1
  7. data/bin/config.ru +63 -0
  8. data/bin/console +6 -0
  9. data/bin/echo +42 -32
  10. data/bin/http-hello +62 -0
  11. data/bin/http-playground +124 -0
  12. data/bin/playground +62 -0
  13. data/bin/poc/Gemfile.lock +23 -0
  14. data/bin/poc/README.md +37 -0
  15. data/bin/poc/config.ru +66 -0
  16. data/bin/poc/gemfile +1 -0
  17. data/bin/poc/www/index.html +57 -0
  18. data/bin/raw-rbhttp +35 -0
  19. data/bin/raw_broadcast +66 -0
  20. data/bin/test_with_faye +40 -0
  21. data/bin/ws-broadcast +108 -0
  22. data/bin/ws-echo +108 -0
  23. data/exe/iodine +59 -0
  24. data/ext/iodine/base64.c +264 -0
  25. data/ext/iodine/base64.h +72 -0
  26. data/ext/iodine/bscrypt-common.h +109 -0
  27. data/ext/iodine/bscrypt.h +49 -0
  28. data/ext/iodine/extconf.rb +41 -0
  29. data/ext/iodine/hex.c +123 -0
  30. data/ext/iodine/hex.h +70 -0
  31. data/ext/iodine/http.c +200 -0
  32. data/ext/iodine/http.h +128 -0
  33. data/ext/iodine/http1.c +402 -0
  34. data/ext/iodine/http1.h +56 -0
  35. data/ext/iodine/http1_simple_parser.c +473 -0
  36. data/ext/iodine/http1_simple_parser.h +59 -0
  37. data/ext/iodine/http_request.h +128 -0
  38. data/ext/iodine/http_response.c +1606 -0
  39. data/ext/iodine/http_response.h +393 -0
  40. data/ext/iodine/http_response_http1.h +374 -0
  41. data/ext/iodine/iodine_core.c +641 -0
  42. data/ext/iodine/iodine_core.h +70 -0
  43. data/ext/iodine/iodine_http.c +615 -0
  44. data/ext/iodine/iodine_http.h +19 -0
  45. data/ext/iodine/iodine_websocket.c +430 -0
  46. data/ext/iodine/iodine_websocket.h +21 -0
  47. data/ext/iodine/libasync.c +552 -0
  48. data/ext/iodine/libasync.h +117 -0
  49. data/ext/iodine/libreact.c +347 -0
  50. data/ext/iodine/libreact.h +244 -0
  51. data/ext/iodine/libserver.c +912 -0
  52. data/ext/iodine/libserver.h +435 -0
  53. data/ext/iodine/libsock.c +950 -0
  54. data/ext/iodine/libsock.h +478 -0
  55. data/ext/iodine/misc.c +181 -0
  56. data/ext/iodine/misc.h +76 -0
  57. data/ext/iodine/random.c +193 -0
  58. data/ext/iodine/random.h +48 -0
  59. data/ext/iodine/rb-call.c +127 -0
  60. data/ext/iodine/rb-call.h +60 -0
  61. data/ext/iodine/rb-libasync.h +79 -0
  62. data/ext/iodine/rb-rack-io.c +389 -0
  63. data/ext/iodine/rb-rack-io.h +17 -0
  64. data/ext/iodine/rb-registry.c +213 -0
  65. data/ext/iodine/rb-registry.h +33 -0
  66. data/ext/iodine/sha1.c +359 -0
  67. data/ext/iodine/sha1.h +85 -0
  68. data/ext/iodine/sha2.c +825 -0
  69. data/ext/iodine/sha2.h +138 -0
  70. data/ext/iodine/siphash.c +136 -0
  71. data/ext/iodine/siphash.h +15 -0
  72. data/ext/iodine/spnlock.h +235 -0
  73. data/ext/iodine/websockets.c +696 -0
  74. data/ext/iodine/websockets.h +120 -0
  75. data/ext/iodine/xor-crypt.c +189 -0
  76. data/ext/iodine/xor-crypt.h +107 -0
  77. data/iodine.gemspec +25 -18
  78. data/lib/iodine.rb +57 -58
  79. data/lib/iodine/http.rb +0 -189
  80. data/lib/iodine/protocol.rb +36 -245
  81. data/lib/iodine/version.rb +1 -1
  82. data/lib/rack/handler/iodine.rb +145 -2
  83. metadata +115 -37
  84. data/bin/core_http_test +0 -51
  85. data/bin/em playground +0 -56
  86. data/bin/hello_world +0 -75
  87. data/bin/setup +0 -7
  88. data/lib/iodine/client.rb +0 -5
  89. data/lib/iodine/core.rb +0 -102
  90. data/lib/iodine/core_init.rb +0 -143
  91. data/lib/iodine/http/hpack.rb +0 -553
  92. data/lib/iodine/http/http1.rb +0 -251
  93. data/lib/iodine/http/http2.rb +0 -507
  94. data/lib/iodine/http/rack_support.rb +0 -108
  95. data/lib/iodine/http/request.rb +0 -462
  96. data/lib/iodine/http/response.rb +0 -474
  97. data/lib/iodine/http/session.rb +0 -143
  98. data/lib/iodine/http/websocket_client.rb +0 -335
  99. data/lib/iodine/http/websocket_handler.rb +0 -101
  100. data/lib/iodine/http/websockets.rb +0 -336
  101. data/lib/iodine/io.rb +0 -56
  102. data/lib/iodine/logging.rb +0 -46
  103. data/lib/iodine/settings.rb +0 -158
  104. data/lib/iodine/ssl_connector.rb +0 -48
  105. data/lib/iodine/timers.rb +0 -95
data/exe/iodine ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'iodine'
4
+ require 'rack'
5
+
6
+ if ARGV[0] =~ /(\-\?)|(help)|(\?)$/
7
+ puts <<-EOS
8
+
9
+ Iodine's HTTP/Websocket server version #{Iodine::VERSION}
10
+
11
+ Use:
12
+
13
+ iodine <options> <filename>
14
+
15
+ Both <options> and <filename> are optional.
16
+
17
+ Available options:
18
+ -p Port number. Default: 3000.
19
+ -t Number of threads. Default: 1 => single worker thread.
20
+ -w Number of worker processes. Default: 1 => a single process.
21
+ -www Public folder for static file serving. Default: nil (none).
22
+ -v Log responses.
23
+ -q Never log responses.
24
+ -warmup Warmup invokes autoloading (lazy loading) during server startup.
25
+ -maxbd Maximum Mb per HTTP message (max body size). Default: ~50Mb.
26
+ -maxms Maximum Bytes per Websocket message. Default: ~250Kb.
27
+ -ping Websocket ping interval in seconds. Default: 40 seconds.
28
+ <filename> Defaults to: config.ru
29
+
30
+ Example:
31
+
32
+ iodine -p 80
33
+
34
+ iodine -p 8080 path/to/app/conf.ru
35
+
36
+ iodine -p 8080 -w 4 -t 16
37
+
38
+ EOS
39
+ exit(0)
40
+ end
41
+
42
+ filename = (ARGV[-2].to_s[0] != '-' && ARGV[-1].to_s[0] != '-' && ARGV[-1]) || 'config.ru'
43
+ app, opt = Rack::Builder.parse_file filename
44
+ if ARGV.index('-maxbd') && ARGV[ARGV.index('-maxbd') + 1]
45
+ Iodine::Rack.max_body_size = ARGV[ARGV.index('-maxbd') + 1].to_i
46
+ end
47
+ if ARGV.index('-maxms') && ARGV[ARGV.index('-maxms') + 1]
48
+ Iodine::Rack.max_msg_size = ARGV[ARGV.index('-maxms') + 1].to_i
49
+ end
50
+ if ARGV.index('-ping') && ARGV[ARGV.index('-ping') + 1]
51
+ Iodine::Rack.ws_timeout = ARGV[ARGV.index('-ping') + 1].to_i
52
+ end
53
+ if ARGV.index('-www') && ARGV[ARGV.index('-www') + 1]
54
+ Iodine::Rack.public = ARGV[ARGV.index('-www') + 1]
55
+ end
56
+ Iodine::Rack.log = true if ARGV.index('-v')
57
+ Iodine::Rack.log = false if ARGV.index('-q')
58
+ Iodine.warmup if ARGV.index('-warmup')
59
+ Iodine::Rack.run(app, opt)
@@ -0,0 +1,264 @@
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.
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 "base64.h"
12
+
13
+ /* ***************************************************************************
14
+ Base64 encoding
15
+ */
16
+
17
+ /** the base64 encoding array */
18
+ static char base64_encodes[] =
19
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
20
+
21
+ /**
22
+ a base64 decoding array
23
+ */
24
+ static unsigned base64_decodes[] = {
25
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
26
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
27
+ 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
28
+ 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
29
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0,
30
+ 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
31
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
34
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
38
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
39
+
40
+ /**
41
+ a union used for Base64 parsing
42
+ */
43
+ union base64_parser_u {
44
+ struct {
45
+ unsigned tail : 2;
46
+ unsigned data : 6;
47
+ } byte1;
48
+ struct {
49
+ unsigned prev : 8;
50
+ unsigned tail : 4;
51
+ unsigned head : 4;
52
+ } byte2;
53
+ struct {
54
+ unsigned prev : 16;
55
+ unsigned data : 6;
56
+ unsigned head : 2;
57
+ } byte3;
58
+ char bytes[3];
59
+ };
60
+
61
+ /**
62
+ This will encode a byte array (data) of a specified length (len) and
63
+ place the encoded data into the target byte buffer (target). The target buffer
64
+ MUST have enough room for the expected data.
65
+
66
+ Base64 encoding always requires 4 bytes for each 3 bytes. Padding is added if
67
+ the raw data's length isn't devisable by 3.
68
+
69
+ Always assume the target buffer should have room enough for (len*4/3 + 4)
70
+ bytes.
71
+
72
+ Returns the number of bytes actually written to the target buffer
73
+ (including the Base64 required padding and excluding a NULL terminator).
74
+
75
+ A NULL terminator char is NOT written to the target buffer.
76
+ */
77
+ int bscrypt_base64_encode(char *target, const char *data, int len) {
78
+ int written = 0;
79
+ // // optional implementation: allow a non writing, length computation.
80
+ // if (!target)
81
+ // return (len % 3) ? (((len + 3) / 3) * 4) : (len / 3);
82
+ // use a union to avoid padding issues.
83
+ union base64_parser_u *section;
84
+ while (len >= 3) {
85
+ section = (void *)data;
86
+ target[0] = base64_encodes[section->byte1.data];
87
+ target[1] =
88
+ base64_encodes[(section->byte1.tail << 4) | (section->byte2.head)];
89
+ target[2] =
90
+ base64_encodes[(section->byte2.tail << 2) | (section->byte3.head)];
91
+ target[3] = base64_encodes[section->byte3.data];
92
+
93
+ target += 4;
94
+ data += 3;
95
+ len -= 3;
96
+ written += 4;
97
+ }
98
+ section = (void *)data;
99
+ if (len == 2) {
100
+ target[0] = base64_encodes[section->byte1.data];
101
+ target[1] =
102
+ base64_encodes[(section->byte1.tail << 4) | (section->byte2.head)];
103
+ target[2] = base64_encodes[section->byte2.tail << 2];
104
+ target[3] = '=';
105
+ target += 4;
106
+ written += 4;
107
+ } else if (len == 1) {
108
+ target[0] = base64_encodes[section->byte1.data];
109
+ target[1] = base64_encodes[section->byte1.tail << 4];
110
+ target[2] = '=';
111
+ target[3] = '=';
112
+ target += 4;
113
+ written += 4;
114
+ }
115
+ target[0] = 0; // NULL terminator
116
+ return written;
117
+ }
118
+
119
+ /**
120
+ This will decode a Base64 encoded string of a specified length (len) and
121
+ place the decoded data into the target byte buffer (target).
122
+
123
+ The target buffer MUST have enough room for the expected data.
124
+
125
+ A NULL byte will be appended to the target buffer. The function will return
126
+ the number of bytes written to the target buffer.
127
+
128
+ If the target buffer is NULL, the encoded string will be destructively edited
129
+ and the decoded data will be placed in the original string's buffer.
130
+
131
+ Base64 encoding always requires 4 bytes for each 3 bytes. Padding is added if
132
+ the raw data's length isn't devisable by 3. Hence, the target buffer should
133
+ be, at least, `base64_len/4*3 + 3` long.
134
+
135
+ Returns the number of bytes actually written to the target buffer (excluding
136
+ the NULL terminator byte).
137
+ */
138
+ int bscrypt_base64_decode(char *target, char *encoded, int base64_len) {
139
+ if (base64_len <= 0)
140
+ return -1;
141
+ if (!target)
142
+ target = encoded;
143
+ union base64_parser_u section;
144
+ int written = 0;
145
+ // base64_encodes
146
+ // a struct that will be used to read the data.
147
+ while (base64_len >= 4) {
148
+ base64_len -= 4; // make sure we don't loop forever.
149
+ // copying the data allows us to write destructively to the same buffer
150
+ section.byte1.data = base64_decodes[(unsigned char)(*encoded)];
151
+ encoded++;
152
+ section.byte1.tail = (base64_decodes[(unsigned char)(*encoded)] >> 4);
153
+ section.byte2.head = base64_decodes[(unsigned char)(*encoded)];
154
+ encoded++;
155
+ section.byte2.tail = (base64_decodes[(unsigned char)(*encoded)] >> 2);
156
+ section.byte3.head = base64_decodes[(unsigned char)(*encoded)];
157
+ encoded++;
158
+ section.byte3.data = base64_decodes[(unsigned char)(*encoded)];
159
+ encoded++;
160
+ // write to the target buffer
161
+ *(target++) = section.bytes[0];
162
+ *(target++) = section.bytes[1];
163
+ *(target++) = section.bytes[2];
164
+ // count written bytes
165
+ written += section.bytes[2] ? 3 : section.bytes[1] ? 2 : 1;
166
+ }
167
+ // deal with the "tail" of the encoded stream
168
+ if (base64_len) {
169
+ // zero out data
170
+ section.bytes[0] = 0;
171
+ section.bytes[1] = 0;
172
+ section.bytes[2] = 0;
173
+ // byte 1 + 2 (2 might be padding)
174
+ section.byte1.data = base64_decodes[(unsigned char)*(encoded++)];
175
+ if (--base64_len) {
176
+ section.byte1.tail = base64_decodes[(unsigned char)(*encoded)] >> 4;
177
+ section.byte2.head = base64_decodes[(unsigned char)(*encoded)];
178
+ encoded++;
179
+ if (--base64_len) {
180
+ section.byte2.tail = base64_decodes[(unsigned char)(*encoded)] >> 4;
181
+ section.byte3.head = base64_decodes[(unsigned char)(*encoded)];
182
+ // --base64_len; // will always be 0 at this point (or it was 4)
183
+ }
184
+ }
185
+ // write to the target buffer
186
+ *(target++) = section.bytes[0];
187
+ if (section.bytes[1] || section.bytes[2])
188
+ *(target++) = section.bytes[1];
189
+ if (section.bytes[2])
190
+ *(target++) = section.bytes[2];
191
+ // count written bytes
192
+ written += section.bytes[2] ? 3 : section.bytes[1] ? 2 : 1;
193
+ }
194
+ *target = 0;
195
+ return written;
196
+ }
197
+
198
+ /*******************************************************************************
199
+ Base64
200
+ */
201
+ #if defined(DEBUG) && DEBUG == 1
202
+ void bscrypt_test_base64(void) {
203
+ struct {
204
+ char *str;
205
+ char *base64;
206
+ } sets[] = {
207
+ // {"Man is distinguished, not only by his reason, but by this singular "
208
+ // "passion from other animals, which is a lust of the mind, that by a "
209
+ // "perseverance of delight in the continued and indefatigable generation
210
+ // "
211
+ // "of knowledge, exceeds the short vehemence of any carnal pleasure.",
212
+ // "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB"
213
+ // "0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG"
214
+ // "x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpb"
215
+ // "iB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xl"
216
+ // "ZGdlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3V"
217
+ // "yZS4="},
218
+ {"any carnal pleasure.", "YW55IGNhcm5hbCBwbGVhc3VyZS4="},
219
+ {"any carnal pleasure", "YW55IGNhcm5hbCBwbGVhc3VyZQ=="},
220
+ {"any carnal pleasur", "YW55IGNhcm5hbCBwbGVhc3Vy"},
221
+ {NULL, NULL} // Stop
222
+ };
223
+ int i = 0;
224
+ char buffer[1024];
225
+ fprintf(stderr, "+ bscrypt");
226
+ while (sets[i].str) {
227
+ bscrypt_base64_encode(buffer, sets[i].str, strlen(sets[i].str));
228
+ if (strcmp(buffer, sets[i].base64)) {
229
+ fprintf(stderr,
230
+ ":\n--- bscrypt Base64 Test FAILED!\nstring: %s\nlength: %lu\n "
231
+ "expected: %s\ngot: %s\n\n",
232
+ sets[i].str, strlen(sets[i].str), sets[i].base64, buffer);
233
+ break;
234
+ }
235
+ i++;
236
+ }
237
+ if (!sets[i].str)
238
+ fprintf(stderr, " Base64 encode passed.\n");
239
+
240
+ i = 0;
241
+ fprintf(stderr, "+ bscrypt");
242
+ while (sets[i].str) {
243
+ bscrypt_base64_decode(buffer, sets[i].base64, strlen(sets[i].base64));
244
+ if (strcmp(buffer, sets[i].str)) {
245
+ fprintf(stderr,
246
+ ":\n--- bscrypt Base64 Test FAILED!\nbase64: %s\nexpected: "
247
+ "%s\ngot: %s\n\n",
248
+ sets[i].base64, sets[i].str, buffer);
249
+ return;
250
+ }
251
+ i++;
252
+ }
253
+ fprintf(stderr, " Base64 decode passed.\n");
254
+ char buff_b64[] = "any carnal pleasure.";
255
+ size_t b64_len;
256
+ clock_t start = clock();
257
+ for (size_t i = 0; i < 100000; i++) {
258
+ b64_len = bscrypt_base64_encode(buffer, buff_b64, sizeof(buff_b64) - 1);
259
+ bscrypt_base64_decode(buff_b64, buffer, b64_len);
260
+ }
261
+ fprintf(stderr, "bscrypt 100K Base64: %lf\n",
262
+ (double)(clock() - start) / CLOCKS_PER_SEC);
263
+ }
264
+ #endif
@@ -0,0 +1,72 @@
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.
5
+
6
+ Feel free to copy, use and enjoy in accordance with to the license(s).
7
+ */
8
+ #ifndef BSCRYPT_BASE64_H
9
+ #define BSCRYPT_BASE64_H
10
+ #include "bscrypt-common.h"
11
+ /* *****************************************************************************
12
+ C++ extern
13
+ */
14
+ #if defined(__cplusplus)
15
+ extern "C" {
16
+ #endif
17
+
18
+ /* ***************************************************************************
19
+ Base64 encoding
20
+ */
21
+
22
+ /**
23
+ This will encode a byte array (data) of a specified length (len) and
24
+ place the encoded data into the target byte buffer (target). The target buffer
25
+ MUST have enough room for the expected data.
26
+
27
+ Base64 encoding always requires 4 bytes for each 3 bytes. Padding is added if
28
+ the raw data's length isn't devisable by 3.
29
+
30
+ Always assume the target buffer should have room enough for (len*4/3 + 4)
31
+ bytes.
32
+
33
+ Returns the number of bytes actually written to the target buffer
34
+ (including the Base64 required padding and excluding a NULL terminator).
35
+
36
+ A NULL terminator char is NOT written to the target buffer.
37
+ */
38
+ int bscrypt_base64_encode(char *target, const char *data, int len);
39
+
40
+ /**
41
+ This will decode a Base64 encoded string of a specified length (len) and
42
+ place the decoded data into the target byte buffer (target).
43
+
44
+ The target buffer MUST have enough room for the expected data.
45
+
46
+ A NULL byte will be appended to the target buffer. The function will return
47
+ the number of bytes written to the target buffer.
48
+
49
+ If the target buffer is NULL, the encoded string will be destructively edited
50
+ and the decoded data will be placed in the original string's buffer.
51
+
52
+ Base64 encoding always requires 4 bytes for each 3 bytes. Padding is added if
53
+ the raw data's length isn't devisable by 3. Hence, the target buffer should
54
+ be, at least, `base64_len/4*3 + 3` long.
55
+
56
+ Returns the number of bytes actually written to the target buffer (excluding
57
+ the NULL terminator byte).
58
+ */
59
+ int bscrypt_base64_decode(char *target, char *encoded, int base64_len);
60
+
61
+ #if defined(DEBUG) && DEBUG == 1
62
+ void bscrypt_test_base64(void);
63
+ #endif
64
+
65
+ /* *****************************************************************************
66
+ C++ extern finish
67
+ */
68
+ #if defined(__cplusplus)
69
+ }
70
+ #endif
71
+
72
+ #endif
@@ -0,0 +1,109 @@
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.
5
+
6
+ Feel free to copy, use and enjoy in accordance with to the license(s).
7
+ */
8
+ #ifndef BSCRYPT_COMMON_H
9
+ #define BSCRYPT_COMMON_H
10
+ /* *****************************************************************************
11
+ Environment - you can safely ignore this part... probably.
12
+ */
13
+
14
+ #include <stdio.h>
15
+ #include <stdlib.h>
16
+ #include <stdint.h>
17
+ #include <string.h>
18
+ #include <time.h>
19
+
20
+ /* check for __uint128_t support */
21
+ #if defined(__SIZEOF_INT128__) || defined(__SIZEOF_INT128__)
22
+ #define HAS_UINT128
23
+ #endif
24
+
25
+ /* check for features used by lib-bscrypt using include file methology */
26
+ #ifdef __has_include
27
+
28
+ /* check for unix support */
29
+ #if __has_include(<unistd.h>)&&__has_include(<pthread.h>)
30
+ #define HAS_UNIX_FEATURES
31
+ #endif
32
+
33
+ /* include intrinsics if supported */
34
+ #if __has_include(<x86intrin.h>)
35
+ #include <x86intrin.h>
36
+ #define HAVE_X86Intrin
37
+ /*
38
+ see: https://software.intel.com/en-us/node/513411
39
+ and: https://software.intel.com/sites/landingpage/IntrinsicsGuide/
40
+ */
41
+ #endif /* __has_include(<x86intrin.h>) */
42
+
43
+ #endif
44
+
45
+ // clang-format off
46
+ #if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
47
+ # if defined(__has_include)
48
+ # if __has_include(<endian.h>)
49
+ # include <endian.h>
50
+ # elif __has_include(<sys/endian.h>)
51
+ # include <sys/endian.h>
52
+ # endif
53
+ # endif
54
+ # if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) && \
55
+ __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
56
+ # define __BIG_ENDIAN__
57
+ # endif
58
+ #endif
59
+
60
+ #ifndef __unused
61
+ # define __unused __attribute__((unused))
62
+ #endif
63
+ // clang-format on
64
+
65
+ /* *****************************************************************************
66
+ C++ extern
67
+ */
68
+ #if defined(__cplusplus)
69
+ extern "C" {
70
+ #endif
71
+
72
+ /* ***************************************************************************
73
+ Types commonly used by the bscrypt libraries
74
+ */
75
+
76
+ typedef union {
77
+ #ifdef HAVE_X86Intrin
78
+ __m128i mm;
79
+ #endif
80
+ #ifdef HAS_UINT128
81
+ __uint128_t i;
82
+ #endif
83
+ uint8_t bytes[16];
84
+ uint8_t matrix[4][4];
85
+ uint32_t words_small[4];
86
+ uint64_t words[2];
87
+ } bits128_u;
88
+
89
+ typedef union {
90
+ #if defined(HAVE_X86Intrin) && defined(__AVX__)
91
+ __m256i mm;
92
+ #endif
93
+ #ifdef HAS_UINT128
94
+ __uint128_t huge[2];
95
+ #endif
96
+ uint8_t bytes[32];
97
+ uint8_t matrix[8][4];
98
+ uint32_t ints[8];
99
+ uint64_t words[4];
100
+ } bits256_u;
101
+
102
+ /* *****************************************************************************
103
+ C++ extern finish
104
+ */
105
+ #if defined(__cplusplus)
106
+ }
107
+ #endif
108
+
109
+ #endif