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.
- checksums.yaml +4 -4
- data/.gitignore +3 -2
- data/.travis.yml +23 -2
- data/CHANGELOG.md +9 -2
- data/README.md +232 -179
- data/Rakefile +13 -1
- data/bin/config.ru +63 -0
- data/bin/console +6 -0
- data/bin/echo +42 -32
- data/bin/http-hello +62 -0
- data/bin/http-playground +124 -0
- data/bin/playground +62 -0
- data/bin/poc/Gemfile.lock +23 -0
- data/bin/poc/README.md +37 -0
- data/bin/poc/config.ru +66 -0
- data/bin/poc/gemfile +1 -0
- data/bin/poc/www/index.html +57 -0
- data/bin/raw-rbhttp +35 -0
- data/bin/raw_broadcast +66 -0
- data/bin/test_with_faye +40 -0
- data/bin/ws-broadcast +108 -0
- data/bin/ws-echo +108 -0
- data/exe/iodine +59 -0
- data/ext/iodine/base64.c +264 -0
- data/ext/iodine/base64.h +72 -0
- data/ext/iodine/bscrypt-common.h +109 -0
- data/ext/iodine/bscrypt.h +49 -0
- data/ext/iodine/extconf.rb +41 -0
- data/ext/iodine/hex.c +123 -0
- data/ext/iodine/hex.h +70 -0
- data/ext/iodine/http.c +200 -0
- data/ext/iodine/http.h +128 -0
- data/ext/iodine/http1.c +402 -0
- data/ext/iodine/http1.h +56 -0
- data/ext/iodine/http1_simple_parser.c +473 -0
- data/ext/iodine/http1_simple_parser.h +59 -0
- data/ext/iodine/http_request.h +128 -0
- data/ext/iodine/http_response.c +1606 -0
- data/ext/iodine/http_response.h +393 -0
- data/ext/iodine/http_response_http1.h +374 -0
- data/ext/iodine/iodine_core.c +641 -0
- data/ext/iodine/iodine_core.h +70 -0
- data/ext/iodine/iodine_http.c +615 -0
- data/ext/iodine/iodine_http.h +19 -0
- data/ext/iodine/iodine_websocket.c +430 -0
- data/ext/iodine/iodine_websocket.h +21 -0
- data/ext/iodine/libasync.c +552 -0
- data/ext/iodine/libasync.h +117 -0
- data/ext/iodine/libreact.c +347 -0
- data/ext/iodine/libreact.h +244 -0
- data/ext/iodine/libserver.c +912 -0
- data/ext/iodine/libserver.h +435 -0
- data/ext/iodine/libsock.c +950 -0
- data/ext/iodine/libsock.h +478 -0
- data/ext/iodine/misc.c +181 -0
- data/ext/iodine/misc.h +76 -0
- data/ext/iodine/random.c +193 -0
- data/ext/iodine/random.h +48 -0
- data/ext/iodine/rb-call.c +127 -0
- data/ext/iodine/rb-call.h +60 -0
- data/ext/iodine/rb-libasync.h +79 -0
- data/ext/iodine/rb-rack-io.c +389 -0
- data/ext/iodine/rb-rack-io.h +17 -0
- data/ext/iodine/rb-registry.c +213 -0
- data/ext/iodine/rb-registry.h +33 -0
- data/ext/iodine/sha1.c +359 -0
- data/ext/iodine/sha1.h +85 -0
- data/ext/iodine/sha2.c +825 -0
- data/ext/iodine/sha2.h +138 -0
- data/ext/iodine/siphash.c +136 -0
- data/ext/iodine/siphash.h +15 -0
- data/ext/iodine/spnlock.h +235 -0
- data/ext/iodine/websockets.c +696 -0
- data/ext/iodine/websockets.h +120 -0
- data/ext/iodine/xor-crypt.c +189 -0
- data/ext/iodine/xor-crypt.h +107 -0
- data/iodine.gemspec +25 -18
- data/lib/iodine.rb +57 -58
- data/lib/iodine/http.rb +0 -189
- data/lib/iodine/protocol.rb +36 -245
- data/lib/iodine/version.rb +1 -1
- data/lib/rack/handler/iodine.rb +145 -2
- metadata +115 -37
- data/bin/core_http_test +0 -51
- data/bin/em playground +0 -56
- data/bin/hello_world +0 -75
- data/bin/setup +0 -7
- data/lib/iodine/client.rb +0 -5
- data/lib/iodine/core.rb +0 -102
- data/lib/iodine/core_init.rb +0 -143
- data/lib/iodine/http/hpack.rb +0 -553
- data/lib/iodine/http/http1.rb +0 -251
- data/lib/iodine/http/http2.rb +0 -507
- data/lib/iodine/http/rack_support.rb +0 -108
- data/lib/iodine/http/request.rb +0 -462
- data/lib/iodine/http/response.rb +0 -474
- data/lib/iodine/http/session.rb +0 -143
- data/lib/iodine/http/websocket_client.rb +0 -335
- data/lib/iodine/http/websocket_handler.rb +0 -101
- data/lib/iodine/http/websockets.rb +0 -336
- data/lib/iodine/io.rb +0 -56
- data/lib/iodine/logging.rb +0 -46
- data/lib/iodine/settings.rb +0 -158
- data/lib/iodine/ssl_connector.rb +0 -48
- 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)
|
data/ext/iodine/base64.c
ADDED
@@ -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
|
data/ext/iodine/base64.h
ADDED
@@ -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
|