isomorfeus-iodine 0.7.44

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  3. data/.gitignore +20 -0
  4. data/.rspec +2 -0
  5. data/.travis.yml +32 -0
  6. data/.yardopts +8 -0
  7. data/CHANGELOG.md +1038 -0
  8. data/Gemfile +11 -0
  9. data/LICENSE.txt +21 -0
  10. data/LIMITS.md +41 -0
  11. data/README.md +782 -0
  12. data/Rakefile +44 -0
  13. data/SPEC-PubSub-Draft.md +159 -0
  14. data/SPEC-WebSocket-Draft.md +239 -0
  15. data/bin/console +22 -0
  16. data/bin/info.md +353 -0
  17. data/bin/mustache_bench.rb +100 -0
  18. data/bin/poc/Gemfile.lock +23 -0
  19. data/bin/poc/README.md +37 -0
  20. data/bin/poc/config.ru +66 -0
  21. data/bin/poc/gemfile +1 -0
  22. data/bin/poc/www/index.html +57 -0
  23. data/examples/async_task.ru +92 -0
  24. data/examples/config.ru +56 -0
  25. data/examples/echo.ru +59 -0
  26. data/examples/hello.ru +29 -0
  27. data/examples/pubsub_engine.ru +81 -0
  28. data/examples/redis.ru +70 -0
  29. data/examples/shootout.ru +73 -0
  30. data/examples/sub-protocols.ru +90 -0
  31. data/examples/tcp_client.rb +66 -0
  32. data/examples/x-sendfile.ru +14 -0
  33. data/exe/iodine +277 -0
  34. data/ext/iodine/extconf.rb +109 -0
  35. data/ext/iodine/fio.c +11985 -0
  36. data/ext/iodine/fio.h +6373 -0
  37. data/ext/iodine/fio_cli.c +431 -0
  38. data/ext/iodine/fio_cli.h +189 -0
  39. data/ext/iodine/fio_json_parser.h +687 -0
  40. data/ext/iodine/fio_siphash.c +157 -0
  41. data/ext/iodine/fio_siphash.h +37 -0
  42. data/ext/iodine/fio_tls.h +129 -0
  43. data/ext/iodine/fio_tls_missing.c +649 -0
  44. data/ext/iodine/fio_tls_openssl.c +1056 -0
  45. data/ext/iodine/fio_tmpfile.h +50 -0
  46. data/ext/iodine/fiobj.h +44 -0
  47. data/ext/iodine/fiobj4fio.h +21 -0
  48. data/ext/iodine/fiobj_ary.c +333 -0
  49. data/ext/iodine/fiobj_ary.h +139 -0
  50. data/ext/iodine/fiobj_data.c +1185 -0
  51. data/ext/iodine/fiobj_data.h +167 -0
  52. data/ext/iodine/fiobj_hash.c +409 -0
  53. data/ext/iodine/fiobj_hash.h +176 -0
  54. data/ext/iodine/fiobj_json.c +622 -0
  55. data/ext/iodine/fiobj_json.h +68 -0
  56. data/ext/iodine/fiobj_mem.h +71 -0
  57. data/ext/iodine/fiobj_mustache.c +317 -0
  58. data/ext/iodine/fiobj_mustache.h +62 -0
  59. data/ext/iodine/fiobj_numbers.c +344 -0
  60. data/ext/iodine/fiobj_numbers.h +127 -0
  61. data/ext/iodine/fiobj_str.c +433 -0
  62. data/ext/iodine/fiobj_str.h +172 -0
  63. data/ext/iodine/fiobject.c +620 -0
  64. data/ext/iodine/fiobject.h +654 -0
  65. data/ext/iodine/hpack.h +1923 -0
  66. data/ext/iodine/http.c +2754 -0
  67. data/ext/iodine/http.h +1002 -0
  68. data/ext/iodine/http1.c +912 -0
  69. data/ext/iodine/http1.h +29 -0
  70. data/ext/iodine/http1_parser.h +873 -0
  71. data/ext/iodine/http_internal.c +1278 -0
  72. data/ext/iodine/http_internal.h +237 -0
  73. data/ext/iodine/http_mime_parser.h +350 -0
  74. data/ext/iodine/iodine.c +1430 -0
  75. data/ext/iodine/iodine.h +63 -0
  76. data/ext/iodine/iodine_caller.c +218 -0
  77. data/ext/iodine/iodine_caller.h +27 -0
  78. data/ext/iodine/iodine_connection.c +933 -0
  79. data/ext/iodine/iodine_connection.h +55 -0
  80. data/ext/iodine/iodine_defer.c +420 -0
  81. data/ext/iodine/iodine_defer.h +6 -0
  82. data/ext/iodine/iodine_fiobj2rb.h +120 -0
  83. data/ext/iodine/iodine_helpers.c +282 -0
  84. data/ext/iodine/iodine_helpers.h +12 -0
  85. data/ext/iodine/iodine_http.c +1171 -0
  86. data/ext/iodine/iodine_http.h +23 -0
  87. data/ext/iodine/iodine_json.c +302 -0
  88. data/ext/iodine/iodine_json.h +6 -0
  89. data/ext/iodine/iodine_mustache.c +567 -0
  90. data/ext/iodine/iodine_mustache.h +6 -0
  91. data/ext/iodine/iodine_pubsub.c +580 -0
  92. data/ext/iodine/iodine_pubsub.h +26 -0
  93. data/ext/iodine/iodine_rack_io.c +281 -0
  94. data/ext/iodine/iodine_rack_io.h +20 -0
  95. data/ext/iodine/iodine_store.c +142 -0
  96. data/ext/iodine/iodine_store.h +20 -0
  97. data/ext/iodine/iodine_tcp.c +346 -0
  98. data/ext/iodine/iodine_tcp.h +13 -0
  99. data/ext/iodine/iodine_tls.c +261 -0
  100. data/ext/iodine/iodine_tls.h +13 -0
  101. data/ext/iodine/mustache_parser.h +1546 -0
  102. data/ext/iodine/redis_engine.c +957 -0
  103. data/ext/iodine/redis_engine.h +79 -0
  104. data/ext/iodine/resp_parser.h +317 -0
  105. data/ext/iodine/websocket_parser.h +505 -0
  106. data/ext/iodine/websockets.c +735 -0
  107. data/ext/iodine/websockets.h +185 -0
  108. data/isomorfeus-iodine.gemspec +42 -0
  109. data/lib/iodine/connection.rb +61 -0
  110. data/lib/iodine/json.rb +42 -0
  111. data/lib/iodine/mustache.rb +113 -0
  112. data/lib/iodine/pubsub.rb +55 -0
  113. data/lib/iodine/rack_utils.rb +43 -0
  114. data/lib/iodine/tls.rb +16 -0
  115. data/lib/iodine/version.rb +3 -0
  116. data/lib/iodine.rb +274 -0
  117. data/lib/rack/handler/iodine.rb +33 -0
  118. data/logo.png +0 -0
  119. metadata +271 -0
@@ -0,0 +1,282 @@
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
+ #include "iodine.h"
8
+
9
+ #include "http.h"
10
+ #include <ruby/encoding.h>
11
+
12
+ /*
13
+ Add all sorts of useless stuff here.
14
+ */
15
+
16
+ static ID iodine_to_i_func_id;
17
+ static rb_encoding *IodineUTF8Encoding;
18
+
19
+ /* *****************************************************************************
20
+ URL Decoding
21
+ ***************************************************************************** */
22
+ /**
23
+ Decodes a URL encoded String in place.
24
+
25
+ Raises an exception on error... but this might result in a partially decoded
26
+ String.
27
+ */
28
+ static VALUE url_decode_inplace(VALUE self, VALUE str) {
29
+ Check_Type(str, T_STRING);
30
+ ssize_t len =
31
+ http_decode_url(RSTRING_PTR(str), RSTRING_PTR(str), RSTRING_LEN(str));
32
+ if (len < 0)
33
+ rb_raise(rb_eRuntimeError, "Malformed URL string - couldn't decode (String "
34
+ "might have been partially altered).");
35
+ rb_str_set_len(str, len);
36
+ return str;
37
+ (void)self;
38
+ }
39
+
40
+ /**
41
+ Decodes a URL encoded String, returning a new String with the decoded data.
42
+ */
43
+ static VALUE url_decode(VALUE self, VALUE str) {
44
+ Check_Type(str, T_STRING);
45
+ VALUE str2 = rb_str_buf_new(RSTRING_LEN(str));
46
+ ssize_t len =
47
+ http_decode_url(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str));
48
+ if (len < 0)
49
+ rb_raise(rb_eRuntimeError, "Malformed URL string - couldn't decode.");
50
+ rb_str_set_len(str2, len);
51
+ return str2;
52
+ (void)self;
53
+ }
54
+
55
+ /**
56
+ Decodes a percent encoded String (normally the "path" of a request), editing the
57
+ String in place.
58
+
59
+ Raises an exception on error... but this might result in a partially decoded
60
+ String.
61
+ */
62
+ static VALUE path_decode_inplace(VALUE self, VALUE str) {
63
+ Check_Type(str, T_STRING);
64
+ ssize_t len =
65
+ http_decode_path(RSTRING_PTR(str), RSTRING_PTR(str), RSTRING_LEN(str));
66
+ if (len < 0)
67
+ rb_raise(rb_eRuntimeError,
68
+ "Malformed URL path string - couldn't decode (String "
69
+ "might have been partially altered).");
70
+ rb_str_set_len(str, len);
71
+ return str;
72
+ (void)self;
73
+ }
74
+
75
+ /**
76
+ Decodes a percent encoded String (normally the "path" of a request), returning a
77
+ new String with the decoded data.
78
+ */
79
+ static VALUE path_decode(VALUE self, VALUE str) {
80
+ Check_Type(str, T_STRING);
81
+ VALUE str2 = rb_str_buf_new(RSTRING_LEN(str));
82
+ ssize_t len =
83
+ http_decode_path(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str));
84
+ if (len < 0)
85
+ rb_raise(rb_eRuntimeError, "Malformed URL path string - couldn't decode.");
86
+ rb_str_set_len(str2, len);
87
+ return str2;
88
+ (void)self;
89
+ }
90
+
91
+ /**
92
+ Decodes a URL encoded String, returning a new String with the decoded data.
93
+
94
+ This variation matches the Rack::Utils.unescape signature by accepting and
95
+ mostly ignoring an optional Encoding argument.
96
+ */
97
+ static VALUE unescape(int argc, VALUE *argv, VALUE self) {
98
+ if (argc < 1 || argc > 2)
99
+ rb_raise(rb_eArgError,
100
+ "wrong number of arguments (given %d, expected 1..2).", argc);
101
+ VALUE str = argv[0];
102
+ Check_Type(str, T_STRING);
103
+ VALUE str2 = rb_str_buf_new(RSTRING_LEN(str));
104
+ ssize_t len =
105
+ http_decode_url(RSTRING_PTR(str2), RSTRING_PTR(str), RSTRING_LEN(str));
106
+ if (len < 0)
107
+ rb_raise(rb_eRuntimeError, "Malformed URL path string - couldn't decode.");
108
+ rb_str_set_len(str2, len);
109
+ rb_encoding *enc = IodineUTF8Encoding;
110
+ if (argc == 2 && argv[1] != Qnil && argv[1] != Qfalse) {
111
+ enc = rb_enc_get(argv[1]);
112
+ if (!enc)
113
+ enc = IodineUTF8Encoding;
114
+ }
115
+ rb_enc_associate(str2, enc);
116
+ return str2;
117
+ (void)self;
118
+ }
119
+
120
+ /* *****************************************************************************
121
+ HTTP Dates
122
+ ***************************************************************************** */
123
+
124
+ /**
125
+ Takes an optional Integer for Unix Time and returns a faster (though less
126
+ localized) HTTP Date formatted String.
127
+
128
+
129
+ Iodine::Rack.time2str => "Sun, 11 Jun 2017 06:14:08 GMT"
130
+
131
+ Iodine::Rack.time2str(Time.now.to_i) => "Wed, 15 Nov 1995 06:25:24 GMT"
132
+
133
+ Since Iodine uses time caching within it's reactor, using the default value
134
+ (now) will be faster than providing an explicit time using `Time.now.to_i`.
135
+
136
+ */
137
+ static VALUE date_str(int argc, VALUE *argv, VALUE self) {
138
+ if (argc > 1)
139
+ rb_raise(rb_eArgError,
140
+ "wrong number of arguments (given %d, expected 0..1).", argc);
141
+ time_t last_tick;
142
+ if (argc) {
143
+ if (TYPE(argv[0]) != T_FIXNUM)
144
+ argv[0] = rb_funcallv(argv[0], iodine_to_i_func_id, 0, NULL);
145
+ Check_Type(argv[0], T_FIXNUM);
146
+ last_tick =
147
+ FIX2ULONG(argv[0]) ? FIX2ULONG(argv[0]) : fio_last_tick().tv_sec;
148
+ } else
149
+ last_tick = fio_last_tick().tv_sec;
150
+ VALUE str = rb_str_buf_new(32);
151
+ struct tm tm;
152
+
153
+ http_gmtime(last_tick, &tm);
154
+ size_t len = http_date2str(RSTRING_PTR(str), &tm);
155
+ rb_str_set_len(str, len);
156
+ return str;
157
+ (void)self;
158
+ }
159
+
160
+ /**
161
+ Takes `time` and returns a faster (though less localized) HTTP Date formatted
162
+ String.
163
+
164
+
165
+ Iodine::Rack.rfc2822(Time.now) => "Sun, 11 Jun 2017 06:14:08 -0000"
166
+
167
+ Iodine::Rack.rfc2822(0) => "Sun, 11 Jun 2017 06:14:08 -0000"
168
+
169
+ Since Iodine uses time caching within it's reactor, using the default value
170
+ (by passing 0) will be faster than providing an explicit time using `Time.now`.
171
+ */
172
+ static VALUE iodine_rfc2822(VALUE self, VALUE rtm) {
173
+ time_t last_tick;
174
+ rtm = rb_funcallv(rtm, iodine_to_i_func_id, 0, NULL);
175
+ last_tick = FIX2ULONG(rtm) ? FIX2ULONG(rtm) : fio_last_tick().tv_sec;
176
+ VALUE str = rb_str_buf_new(34);
177
+ struct tm tm;
178
+
179
+ http_gmtime(last_tick, &tm);
180
+ size_t len = http_date2rfc2822(RSTRING_PTR(str), &tm);
181
+ rb_str_set_len(str, len);
182
+ return str;
183
+ (void)self;
184
+ }
185
+
186
+ /**
187
+ Takes `time` and returns a faster (though less localized) HTTP Date formatted
188
+ String.
189
+
190
+
191
+ Iodine::Rack.rfc2109(Time.now) => "Sun, 11-Jun-2017 06:14:08 GMT"
192
+
193
+ Iodine::Rack.rfc2109(0) => "Sun, 11-Jun-2017 06:14:08 GMT"
194
+
195
+ Since Iodine uses time caching within it's reactor, using the default value
196
+ (by passing 0) will be faster than providing an explicit time using `Time.now`.
197
+ */
198
+ static VALUE iodine_rfc2109(VALUE self, VALUE rtm) {
199
+ time_t last_tick;
200
+ rtm = rb_funcallv(rtm, iodine_to_i_func_id, 0, NULL);
201
+ last_tick = FIX2ULONG(rtm) ? FIX2ULONG(rtm) : fio_last_tick().tv_sec;
202
+ VALUE str = rb_str_buf_new(32);
203
+ struct tm tm;
204
+
205
+ http_gmtime(last_tick, &tm);
206
+ size_t len = http_date2rfc2109(RSTRING_PTR(str), &tm);
207
+ rb_str_set_len(str, len);
208
+ return str;
209
+ (void)self;
210
+ }
211
+
212
+ /* *****************************************************************************
213
+ Ruby Initialization
214
+ ***************************************************************************** */
215
+
216
+ void iodine_init_helpers(void) {
217
+ iodine_to_i_func_id = rb_intern("to_i");
218
+ IodineUTF8Encoding = rb_enc_find("UTF-8");
219
+ VALUE tmp = rb_define_module_under(IodineModule, "Rack");
220
+ // clang-format off
221
+ /*
222
+ Iodine does NOT monkey patch Rack automatically. However, it's possible and recommended to moneky patch Rack::Utils to use the methods in this module.
223
+
224
+ Choosing to monkey patch Rack::Utils could offer significant performance gains for some applications. i.e. (on my machine):
225
+
226
+ require 'iodine'
227
+ require 'rack'
228
+ # a String in need of decoding
229
+ s = '%E3%83%AB%E3%83%93%E3%82%A4%E3%82%B9%E3%81%A8'
230
+ Benchmark.bm do |bm|
231
+ # Pre-Patch
232
+ bm.report(" Rack.unescape") {1_000_000.times { Rack::Utils.unescape s } }
233
+ bm.report(" Rack.rfc2822") {1_000_000.times { Rack::Utils.rfc2822(Time.now) } }
234
+ bm.report(" Rack.rfc2109") {1_000_000.times { Rack::Utils.rfc2109(Time.now) } }
235
+ # Perform Patch
236
+ Iodine.patch_rack
237
+ puts " --- Monkey Patching Rack ---"
238
+ # Post Patch
239
+ bm.report("Patched.unescape") {1_000_000.times { Rack::Utils.unescape s } }
240
+ bm.report(" Patched.rfc2822") {1_000_000.times { Rack::Utils.rfc2822(Time.now) } }
241
+ bm.report(" Patched.rfc2109") {1_000_000.times { Rack::Utils.rfc2109(Time.now) } }
242
+ end && nil
243
+
244
+ Results:
245
+ user system total real
246
+ Rack.unescape 8.706881 0.019995 8.726876 ( 8.740530)
247
+ Rack.rfc2822 3.270305 0.007519 3.277824 ( 3.279416)
248
+ Rack.rfc2109 3.152188 0.003852 3.156040 ( 3.157975)
249
+ --- Monkey Patching Rack ---
250
+ Patched.unescape 0.327231 0.003125 0.330356 ( 0.337090)
251
+ Patched.rfc2822 0.691304 0.003330 0.694634 ( 0.701172)
252
+ Patched.rfc2109 0.685029 0.001956 0.686985 ( 0.687607)
253
+
254
+ */
255
+ tmp = rb_define_module_under(tmp, "Utils");
256
+ // clang-format on
257
+ rb_define_module_function(tmp, "decode_url!", url_decode_inplace, 1);
258
+ rb_define_module_function(tmp, "decode_url", url_decode, 1);
259
+ rb_define_module_function(tmp, "decode_path!", path_decode_inplace, 1);
260
+ rb_define_module_function(tmp, "decode_path", path_decode, 1);
261
+ rb_define_module_function(tmp, "time2str", date_str, -1);
262
+ rb_define_module_function(tmp, "rfc2109", iodine_rfc2109, 1);
263
+ rb_define_module_function(tmp, "rfc2822", iodine_rfc2822, 1);
264
+
265
+ /*
266
+ The monkey-patched methods are in this module, allowing Iodine::Rack::Utils to
267
+ include non-patched methods as well.
268
+ */
269
+ tmp = rb_define_module_under(IodineBaseModule, "MonkeyPatch");
270
+ tmp = rb_define_module_under(tmp, "RackUtils");
271
+ // clang-format on
272
+ /* we define it all twice for easier monkey patching */
273
+ rb_define_method(tmp, "unescape", unescape, -1);
274
+ rb_define_method(tmp, "unescape_path", path_decode, 1);
275
+ rb_define_method(tmp, "rfc2109", iodine_rfc2109, 1);
276
+ rb_define_method(tmp, "rfc2822", iodine_rfc2822, 1);
277
+ rb_define_singleton_method(tmp, "unescape", unescape, -1);
278
+ rb_define_singleton_method(tmp, "unescape_path", path_decode, 1);
279
+ rb_define_singleton_method(tmp, "rfc2109", iodine_rfc2109, 1);
280
+ rb_define_singleton_method(tmp, "rfc2822", iodine_rfc2822, 1);
281
+ // rb_define_module_function(IodineUtils, "time2str", date_str, -1);
282
+ }
@@ -0,0 +1,12 @@
1
+ #ifndef H_IODINE_HELPERS_H
2
+ #define H_IODINE_HELPERS_H
3
+ /*
4
+ Copyright: Boaz segev, 2016-2018
5
+ License: MIT
6
+
7
+ Feel free to copy, use and enjoy according to the license provided.
8
+ */
9
+
10
+ void iodine_init_helpers(void);
11
+
12
+ #endif