rage-iodine 1.7.58

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  3. data/.github/workflows/ruby.yml +42 -0
  4. data/.gitignore +20 -0
  5. data/.rspec +2 -0
  6. data/.yardopts +8 -0
  7. data/CHANGELOG.md +1098 -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 +23 -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/bates/README.md +3 -0
  25. data/examples/bates/config.ru +342 -0
  26. data/examples/bates/david+bold.pdf +0 -0
  27. data/examples/bates/public/drop-pdf.png +0 -0
  28. data/examples/bates/public/index.html +600 -0
  29. data/examples/config.ru +59 -0
  30. data/examples/echo.ru +59 -0
  31. data/examples/etag.ru +16 -0
  32. data/examples/hello.ru +29 -0
  33. data/examples/pubsub_engine.ru +81 -0
  34. data/examples/rack3.ru +12 -0
  35. data/examples/redis.ru +70 -0
  36. data/examples/shootout.ru +73 -0
  37. data/examples/sub-protocols.ru +90 -0
  38. data/examples/tcp_client.rb +66 -0
  39. data/examples/x-sendfile.ru +14 -0
  40. data/exe/iodine +280 -0
  41. data/ext/iodine/extconf.rb +110 -0
  42. data/ext/iodine/fio.c +12096 -0
  43. data/ext/iodine/fio.h +6390 -0
  44. data/ext/iodine/fio_cli.c +431 -0
  45. data/ext/iodine/fio_cli.h +189 -0
  46. data/ext/iodine/fio_json_parser.h +687 -0
  47. data/ext/iodine/fio_siphash.c +157 -0
  48. data/ext/iodine/fio_siphash.h +37 -0
  49. data/ext/iodine/fio_tls.h +129 -0
  50. data/ext/iodine/fio_tls_missing.c +649 -0
  51. data/ext/iodine/fio_tls_openssl.c +1056 -0
  52. data/ext/iodine/fio_tmpfile.h +50 -0
  53. data/ext/iodine/fiobj.h +44 -0
  54. data/ext/iodine/fiobj4fio.h +21 -0
  55. data/ext/iodine/fiobj_ary.c +333 -0
  56. data/ext/iodine/fiobj_ary.h +139 -0
  57. data/ext/iodine/fiobj_data.c +1185 -0
  58. data/ext/iodine/fiobj_data.h +167 -0
  59. data/ext/iodine/fiobj_hash.c +409 -0
  60. data/ext/iodine/fiobj_hash.h +176 -0
  61. data/ext/iodine/fiobj_json.c +622 -0
  62. data/ext/iodine/fiobj_json.h +68 -0
  63. data/ext/iodine/fiobj_mem.h +71 -0
  64. data/ext/iodine/fiobj_mustache.c +317 -0
  65. data/ext/iodine/fiobj_mustache.h +62 -0
  66. data/ext/iodine/fiobj_numbers.c +344 -0
  67. data/ext/iodine/fiobj_numbers.h +127 -0
  68. data/ext/iodine/fiobj_str.c +433 -0
  69. data/ext/iodine/fiobj_str.h +172 -0
  70. data/ext/iodine/fiobject.c +620 -0
  71. data/ext/iodine/fiobject.h +654 -0
  72. data/ext/iodine/hpack.h +1923 -0
  73. data/ext/iodine/http.c +2736 -0
  74. data/ext/iodine/http.h +1019 -0
  75. data/ext/iodine/http1.c +825 -0
  76. data/ext/iodine/http1.h +29 -0
  77. data/ext/iodine/http1_parser.h +1835 -0
  78. data/ext/iodine/http_internal.c +1279 -0
  79. data/ext/iodine/http_internal.h +248 -0
  80. data/ext/iodine/http_mime_parser.h +350 -0
  81. data/ext/iodine/iodine.c +1433 -0
  82. data/ext/iodine/iodine.h +64 -0
  83. data/ext/iodine/iodine_caller.c +218 -0
  84. data/ext/iodine/iodine_caller.h +27 -0
  85. data/ext/iodine/iodine_connection.c +941 -0
  86. data/ext/iodine/iodine_connection.h +55 -0
  87. data/ext/iodine/iodine_defer.c +420 -0
  88. data/ext/iodine/iodine_defer.h +6 -0
  89. data/ext/iodine/iodine_fiobj2rb.h +120 -0
  90. data/ext/iodine/iodine_helpers.c +282 -0
  91. data/ext/iodine/iodine_helpers.h +12 -0
  92. data/ext/iodine/iodine_http.c +1280 -0
  93. data/ext/iodine/iodine_http.h +23 -0
  94. data/ext/iodine/iodine_json.c +302 -0
  95. data/ext/iodine/iodine_json.h +6 -0
  96. data/ext/iodine/iodine_mustache.c +567 -0
  97. data/ext/iodine/iodine_mustache.h +6 -0
  98. data/ext/iodine/iodine_pubsub.c +580 -0
  99. data/ext/iodine/iodine_pubsub.h +26 -0
  100. data/ext/iodine/iodine_rack_io.c +273 -0
  101. data/ext/iodine/iodine_rack_io.h +20 -0
  102. data/ext/iodine/iodine_store.c +142 -0
  103. data/ext/iodine/iodine_store.h +20 -0
  104. data/ext/iodine/iodine_tcp.c +346 -0
  105. data/ext/iodine/iodine_tcp.h +13 -0
  106. data/ext/iodine/iodine_tls.c +261 -0
  107. data/ext/iodine/iodine_tls.h +13 -0
  108. data/ext/iodine/mustache_parser.h +1546 -0
  109. data/ext/iodine/redis_engine.c +957 -0
  110. data/ext/iodine/redis_engine.h +79 -0
  111. data/ext/iodine/resp_parser.h +317 -0
  112. data/ext/iodine/scheduler.c +173 -0
  113. data/ext/iodine/scheduler.h +6 -0
  114. data/ext/iodine/websocket_parser.h +506 -0
  115. data/ext/iodine/websockets.c +752 -0
  116. data/ext/iodine/websockets.h +185 -0
  117. data/iodine.gemspec +50 -0
  118. data/lib/iodine/connection.rb +61 -0
  119. data/lib/iodine/json.rb +42 -0
  120. data/lib/iodine/mustache.rb +113 -0
  121. data/lib/iodine/pubsub.rb +55 -0
  122. data/lib/iodine/rack_utils.rb +43 -0
  123. data/lib/iodine/tls.rb +16 -0
  124. data/lib/iodine/version.rb +3 -0
  125. data/lib/iodine.rb +274 -0
  126. data/lib/rack/handler/iodine.rb +33 -0
  127. data/logo.png +0 -0
  128. metadata +284 -0
@@ -0,0 +1,23 @@
1
+ #ifndef H_IODINE_HTTP_H
2
+ #define H_IODINE_HTTP_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
+ #include "iodine.h"
10
+
11
+ /* these three are used also by rb-rack-io.c */
12
+ extern VALUE IODINE_R_INPUT;
13
+ extern VALUE IODINE_R_INPUT_DEFAULT;
14
+ extern VALUE IODINE_R_HIJACK;
15
+ extern VALUE IODINE_R_HIJACK_IO;
16
+ extern VALUE IODINE_R_HIJACK_CB;
17
+ void iodine_init_http(void);
18
+
19
+ intptr_t iodine_http_listen(iodine_connection_args_s args);
20
+ // intptr_t iodine_http_connect(iodine_connection_args_s args); // not yet...
21
+ intptr_t iodine_ws_connect(iodine_connection_args_s args);
22
+
23
+ #endif
@@ -0,0 +1,302 @@
1
+ #include "iodine.h"
2
+
3
+ #include "fio.h"
4
+
5
+ #include "fio_json_parser.h"
6
+ #include "fiobj.h"
7
+ #include "iodine_fiobj2rb.h"
8
+ #include "iodine_store.h"
9
+
10
+ static VALUE max_nesting;
11
+ static VALUE allow_nan;
12
+ static VALUE symbolize_names;
13
+ static VALUE create_additions;
14
+ static VALUE object_class;
15
+ static VALUE array_class;
16
+
17
+ #define FIO_ARY_NAME fio_json_stack
18
+ #define FIO_ARY_TYPE VALUE
19
+ #include "fio.h"
20
+
21
+ /* *****************************************************************************
22
+ JSON Callacks - these must be implemented in the C file that uses the parser
23
+ ***************************************************************************** */
24
+
25
+ /* *****************************************************************************
26
+ JSON Parser handling (practically copied from the FIOBJ library)
27
+ ***************************************************************************** */
28
+
29
+ typedef struct {
30
+ json_parser_s p;
31
+ VALUE key;
32
+ VALUE top;
33
+ VALUE target;
34
+ fio_json_stack_s stack;
35
+ uint8_t is_hash;
36
+ uint8_t symbolize;
37
+ } iodine_json_parser_s;
38
+
39
+ static inline void iodine_json_add2parser(iodine_json_parser_s *p, VALUE o) {
40
+ if (p->top) {
41
+ if (p->is_hash) {
42
+ if (p->key) {
43
+ rb_hash_aset(p->top, p->key, o);
44
+ IodineStore.remove(p->key);
45
+ p->key = (VALUE)0;
46
+ } else {
47
+ p->key = o;
48
+ IodineStore.add(o);
49
+ }
50
+ } else {
51
+ rb_ary_push(p->top, o);
52
+ }
53
+ } else {
54
+ IodineStore.add(o);
55
+ p->top = o;
56
+ }
57
+ }
58
+
59
+ /** a NULL object was detected */
60
+ static void fio_json_on_null(json_parser_s *p) {
61
+ iodine_json_add2parser((iodine_json_parser_s *)p, Qnil);
62
+ }
63
+ /** a TRUE object was detected */
64
+ static void fio_json_on_true(json_parser_s *p) {
65
+ iodine_json_add2parser((iodine_json_parser_s *)p, Qtrue);
66
+ }
67
+ /** a FALSE object was detected */
68
+ static void fio_json_on_false(json_parser_s *p) {
69
+ iodine_json_add2parser((iodine_json_parser_s *)p, Qfalse);
70
+ }
71
+ /** a Numberl was detected (long long). */
72
+ static void fio_json_on_number(json_parser_s *p, long long i) {
73
+ iodine_json_add2parser((iodine_json_parser_s *)p, LONG2NUM(i));
74
+ }
75
+ /** a Float was detected (double). */
76
+ static void fio_json_on_float(json_parser_s *p, double f) {
77
+ iodine_json_add2parser((iodine_json_parser_s *)p, DBL2NUM(f));
78
+ }
79
+ /** a String was detected (int / float). update `pos` to point at ending */
80
+ static void fio_json_on_string(json_parser_s *p, void *start, size_t length) {
81
+ /* Ruby overhead for a rb_str_buf_new is very high. Double copy is faster. */
82
+ char *tmp = fio_malloc(length);
83
+ size_t new_len = fio_json_unescape_str(tmp, start, length);
84
+ VALUE buf;
85
+ if (((iodine_json_parser_s *)p)->symbolize &&
86
+ ((iodine_json_parser_s *)p)->is_hash &&
87
+ !((iodine_json_parser_s *)p)->key) {
88
+ ID id = rb_intern2(tmp, new_len);
89
+ buf = rb_id2sym(id);
90
+ } else {
91
+ buf = rb_str_new(tmp, new_len);
92
+ }
93
+ iodine_json_add2parser((iodine_json_parser_s *)p, buf);
94
+ fio_free(tmp);
95
+ }
96
+ /** a dictionary object was detected, should return 0 unless error occurred. */
97
+ static int fio_json_on_start_object(json_parser_s *p) {
98
+ iodine_json_parser_s *pr = (iodine_json_parser_s *)p;
99
+ if (pr->target) {
100
+ /* push NULL, don't free the objects */
101
+ fio_json_stack_push(&pr->stack, pr->top);
102
+ pr->top = pr->target;
103
+ pr->target = 0;
104
+ } else {
105
+ VALUE h = rb_hash_new();
106
+ iodine_json_add2parser(pr, h);
107
+ fio_json_stack_push(&pr->stack, pr->top);
108
+ pr->top = h;
109
+ }
110
+ pr->is_hash = 1;
111
+ return 0;
112
+ }
113
+ /** a dictionary object closure detected */
114
+ static void fio_json_on_end_object(json_parser_s *p) {
115
+ iodine_json_parser_s *pr = (iodine_json_parser_s *)p;
116
+ if (pr->key) {
117
+ FIO_LOG_WARNING("(JSON parsing) malformed JSON, "
118
+ "ignoring dangling Hash key.");
119
+ IodineStore.remove(pr->key);
120
+ pr->key = (VALUE)0;
121
+ }
122
+ fio_json_stack_pop(&pr->stack, &pr->top);
123
+ pr->is_hash = (TYPE(pr->top) == T_HASH);
124
+ }
125
+ /** an array object was detected */
126
+ static int fio_json_on_start_array(json_parser_s *p) {
127
+ iodine_json_parser_s *pr = (iodine_json_parser_s *)p;
128
+ if (pr->target)
129
+ return -1;
130
+ VALUE ary = rb_ary_new();
131
+ iodine_json_add2parser(pr, ary);
132
+ fio_json_stack_push(&pr->stack, pr->top);
133
+ pr->top = ary;
134
+ pr->is_hash = 0;
135
+ return 0;
136
+ }
137
+ /** an array closure was detected */
138
+ static void fio_json_on_end_array(json_parser_s *p) {
139
+ iodine_json_parser_s *pr = (iodine_json_parser_s *)p;
140
+ fio_json_stack_pop(&pr->stack, &pr->top);
141
+ pr->is_hash = (TYPE(pr->top) == T_HASH);
142
+ }
143
+ /** the JSON parsing is complete */
144
+ static void fio_json_on_json(json_parser_s *p) { (void)p; /* do nothing */ }
145
+ /** the JSON parsing is complete */
146
+ static void fio_json_on_error(json_parser_s *p) {
147
+ iodine_json_parser_s *pr = (iodine_json_parser_s *)p;
148
+ #if DEBUG
149
+ FIO_LOG_ERROR("JSON on error called.");
150
+ #endif
151
+ IodineStore.remove((VALUE)fio_json_stack_get(&pr->stack, 0));
152
+ IodineStore.remove(pr->key);
153
+ fio_json_stack_free(&pr->stack);
154
+ *pr = (iodine_json_parser_s){.top = 0};
155
+ }
156
+
157
+ /* *****************************************************************************
158
+ Iodine JSON Implementation
159
+ ***************************************************************************** */
160
+
161
+ static inline VALUE iodine_json_convert(VALUE str, fiobj2rb_settings_s s) {
162
+
163
+ iodine_json_parser_s p = {.top = 0, .symbolize = s.str2sym};
164
+ size_t consumed = fio_json_parse(&p.p, RSTRING_PTR(str), RSTRING_LEN(str));
165
+ if (!consumed || p.p.depth) {
166
+ IodineStore.remove((VALUE)fio_json_stack_get(&p.stack, 0));
167
+ p.top = FIOBJ_INVALID;
168
+ }
169
+ fio_json_stack_free(&p.stack);
170
+ if (p.key) {
171
+ IodineStore.remove((VALUE)p.key);
172
+ }
173
+ if (!p.top) {
174
+ rb_raise(rb_eEncodingError, "Malformed JSON format.");
175
+ }
176
+ IodineStore.remove(p.top);
177
+ return p.top;
178
+ }
179
+
180
+ // static inline VALUE iodine_json_convert2(VALUE str, fiobj2rb_settings_s s) {
181
+ // FIOBJ json;
182
+ // if (!fiobj_json2obj(&json, RSTRING_PTR(str), RSTRING_LEN(str)) || !json) {
183
+ // rb_raise(rb_eRuntimeError, "JSON parsing failed. Not JSON?");
184
+ // return Qnil;
185
+ // }
186
+ // VALUE ret = fiobj2rb_deep(json, s.str2sym);
187
+ // fiobj_free(json);
188
+ // IodineStore.remove(ret);
189
+ // return ret;
190
+ // }
191
+
192
+ static inline void iodine_json_update_settings(VALUE h,
193
+ fiobj2rb_settings_s *s) {
194
+ VALUE tmp;
195
+ if (rb_hash_aref(h, max_nesting) != Qnil)
196
+ FIO_LOG_WARNING("max_nesting ignored on this JSON implementation.");
197
+ if (rb_hash_aref(h, allow_nan) != Qnil)
198
+ fprintf(stderr, "WARNING: allow_nan ignored on this JSON implementation. "
199
+ "NaN always allowed.\n");
200
+ if (rb_hash_aref(h, create_additions) != Qnil)
201
+ FIO_LOG_WARNING("create_additions ignored on this JSON implementation.");
202
+ if (rb_hash_aref(h, object_class) != Qnil)
203
+ FIO_LOG_WARNING("object_class ignored on this JSON implementation.");
204
+ if (rb_hash_aref(h, array_class) != Qnil)
205
+ FIO_LOG_WARNING("array_class ignored on this JSON implementation.");
206
+ if ((tmp = rb_hash_aref(h, symbolize_names)) != Qnil) {
207
+ if (tmp == Qtrue)
208
+ s->str2sym = 1;
209
+ else if (tmp == Qfalse)
210
+ s->str2sym = 0;
211
+ }
212
+ }
213
+
214
+ /**
215
+ Parse a JSON string using the iodine lenient parser (it's also faster).
216
+ */
217
+ static VALUE iodine_json_parse(int argc, VALUE *argv, VALUE self) {
218
+ fiobj2rb_settings_s s = {.str2sym = 0};
219
+ if (argc > 2)
220
+ rb_raise(rb_eTypeError, "function requires supports up to two arguments.");
221
+ if (argc == 2) {
222
+ Check_Type(argv[1], T_HASH);
223
+ iodine_json_update_settings(argv[1], &s);
224
+ }
225
+ if (argc >= 1)
226
+ Check_Type(argv[0], T_STRING);
227
+ else
228
+ rb_raise(rb_eTypeError, "function requires at least one argument.");
229
+ return iodine_json_convert(argv[0], s);
230
+ (void)self;
231
+ }
232
+
233
+ /**
234
+ Parse a JSON string using the iodine lenient parser with a default Symbol
235
+ rather than String key (this is often faster than the regular
236
+ {Iodine::JSON.parse} function).
237
+ */
238
+ static VALUE iodine_json_parse_bang(int argc, VALUE *argv, VALUE self) {
239
+ fiobj2rb_settings_s s = {.str2sym = 0};
240
+ if (argc > 2)
241
+ rb_raise(rb_eTypeError, "function requires supports up to two arguments.");
242
+ if (argc == 2) {
243
+ Check_Type(argv[1], T_HASH);
244
+ iodine_json_update_settings(argv[1], &s);
245
+ }
246
+ if (argc >= 1)
247
+ Check_Type(argv[0], T_STRING);
248
+ else
249
+ rb_raise(rb_eTypeError, "function requires at least one argument.");
250
+ return iodine_json_convert(argv[0], s);
251
+ (void)self;
252
+ }
253
+
254
+ void iodine_init_json(void) {
255
+ /**
256
+ Iodine::JSON offers a fast(er) JSON parser that is also lenient and supports
257
+ some JSON extensions such as Hex number recognition and comments.
258
+
259
+ You can test the parser using:
260
+
261
+ JSON_FILENAME="foo.json"
262
+
263
+ require 'json'
264
+ require 'iodine'
265
+ TIMES = 100
266
+ STR = IO.binread(JSON_FILENAME); nil
267
+
268
+ JSON.parse(STR) == Iodine::JSON.parse(STR) # => true
269
+ JSON.parse(STR,
270
+ symbolize_names: true) == Iodine::JSON.parse(STR,
271
+ symbolize_names: true) # => true
272
+ JSON.parse!(STR) == Iodine::JSON.parse!(STR) # => true/false (unknown)
273
+
274
+ # warm-up
275
+ TIMES.times { JSON.parse STR }
276
+ TIMES.times { Iodine::JSON.parse STR }
277
+
278
+ Benchmark.bm do |b|
279
+ sys = b.report("system") { TIMES.times { JSON.parse STR } }
280
+ sys_sym = b.report("system sym") { TIMES.times { JSON.parse STR,
281
+ symbolize_names: true } }
282
+ iodine = b.report("iodine") { TIMES.times { Iodine::JSON.parse STR } }
283
+ iodine_sym = b.report("iodine sym") do
284
+ TIMES.times { Iodine::JSON.parse STR,
285
+ symbolize_names: true }
286
+ end
287
+ puts "System / Iodine: #{sys/iodine}"
288
+ puts "System-sym/Iodine-sym: #{sys_sym/iodine_sym}"
289
+ end; nil
290
+
291
+
292
+ */
293
+ VALUE tmp = rb_define_module_under(IodineModule, "JSON");
294
+ max_nesting = ID2SYM(rb_intern("max_nesting"));
295
+ allow_nan = ID2SYM(rb_intern("allow_nan"));
296
+ symbolize_names = ID2SYM(rb_intern("symbolize_names"));
297
+ create_additions = ID2SYM(rb_intern("create_additions"));
298
+ object_class = ID2SYM(rb_intern("object_class"));
299
+ array_class = ID2SYM(rb_intern("array_class"));
300
+ rb_define_module_function(tmp, "parse", iodine_json_parse, -1);
301
+ rb_define_module_function(tmp, "parse!", iodine_json_parse_bang, -1);
302
+ }
@@ -0,0 +1,6 @@
1
+ #ifndef H_IODINE_JSON_H
2
+ #define H_IODINE_JSON_H
3
+
4
+ void iodine_init_json(void);
5
+
6
+ #endif