iodine 0.7.14 → 0.7.15
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/CHANGELOG.md +12 -0
- data/README.md +9 -8
- data/SPEC-PubSub-Draft.md +26 -22
- data/SPEC-Websocket-Draft.md +4 -4
- data/examples/sub-protocols.ru +90 -0
- data/exe/iodine +3 -1
- data/ext/iodine/fio.c +103 -69
- data/ext/iodine/fio.h +1 -1
- data/ext/iodine/fio_cli.c +26 -18
- data/ext/iodine/fio_cli.h +3 -1
- data/ext/iodine/fiobj_data.c +6 -1
- data/ext/iodine/fiobj_mustache.c +69 -13
- data/ext/iodine/http.c +26 -11
- data/ext/iodine/http1.c +3 -3
- data/ext/iodine/http_mime_parser.h +9 -0
- data/ext/iodine/iodine.c +34 -16
- data/ext/iodine/iodine_mustache.c +0 -65
- data/ext/iodine/iodine_pubsub.c +0 -1
- data/ext/iodine/mustache_parser.h +40 -14
- data/lib/iodine.rb +16 -8
- data/lib/iodine/version.rb +1 -1
- metadata +4 -3
data/ext/iodine/fio.h
CHANGED
@@ -109,7 +109,7 @@ Version and helper macros
|
|
109
109
|
#define FIO_VERSION_MAJOR 0
|
110
110
|
#define FIO_VERSION_MINOR 7
|
111
111
|
#define FIO_VERSION_PATCH 0
|
112
|
-
#define FIO_VERSION_BETA
|
112
|
+
#define FIO_VERSION_BETA 4
|
113
113
|
|
114
114
|
/* Automatically convert version data to a string constant - ignore these two */
|
115
115
|
#define FIO_MACRO2STR_STEP2(macro) #macro
|
data/ext/iodine/fio_cli.c
CHANGED
@@ -91,10 +91,11 @@ char const *fio_cli_get_line_type(fio_cli_parser_data_s *parser,
|
|
91
91
|
char const **pos = parser->names;
|
92
92
|
while (*pos) {
|
93
93
|
switch ((intptr_t)*pos) {
|
94
|
-
case /* FIO_CLI_TYPE_STRING */ 0x1:
|
95
|
-
case /* FIO_CLI_TYPE_BOOL */ 0x2:
|
96
|
-
case /* FIO_CLI_TYPE_INT */ 0x3:
|
97
|
-
case /* FIO_CLI_TYPE_PRINT */ 0x4:
|
94
|
+
case /* FIO_CLI_TYPE_STRING */ 0x1: /* fallthrough */
|
95
|
+
case /* FIO_CLI_TYPE_BOOL */ 0x2: /* fallthrough */
|
96
|
+
case /* FIO_CLI_TYPE_INT */ 0x3: /* fallthrough */
|
97
|
+
case /* FIO_CLI_TYPE_PRINT */ 0x4: /* fallthrough */
|
98
|
+
case /* FIO_CLI_TYPE_PRINT_HEADER */ 0x5: /* fallthrough */
|
98
99
|
++pos;
|
99
100
|
continue;
|
100
101
|
}
|
@@ -106,10 +107,11 @@ char const *fio_cli_get_line_type(fio_cli_parser_data_s *parser,
|
|
106
107
|
return NULL;
|
107
108
|
found:
|
108
109
|
switch ((size_t)pos[1]) {
|
109
|
-
case /* FIO_CLI_TYPE_STRING */ 0x1:
|
110
|
-
case /* FIO_CLI_TYPE_BOOL */ 0x2:
|
111
|
-
case /* FIO_CLI_TYPE_INT */ 0x3:
|
112
|
-
case /* FIO_CLI_TYPE_PRINT */ 0x4:
|
110
|
+
case /* FIO_CLI_TYPE_STRING */ 0x1: /* fallthrough */
|
111
|
+
case /* FIO_CLI_TYPE_BOOL */ 0x2: /* fallthrough */
|
112
|
+
case /* FIO_CLI_TYPE_INT */ 0x3: /* fallthrough */
|
113
|
+
case /* FIO_CLI_TYPE_PRINT */ 0x4: /* fallthrough */
|
114
|
+
case /* FIO_CLI_TYPE_PRINT_HEADER */ 0x5: /* fallthrough */
|
113
115
|
return pos[1];
|
114
116
|
}
|
115
117
|
return NULL;
|
@@ -196,7 +198,7 @@ error: /* handle errors*/
|
|
196
198
|
(int)arg.len, arg.data, arg.len ? "with value" : "",
|
197
199
|
value ? (value[0] ? value : "(empty)") : "(null)");
|
198
200
|
print_help:
|
199
|
-
fprintf(stderr, "\n%s\n
|
201
|
+
fprintf(stderr, "\n%s\n",
|
200
202
|
parser->description ? parser->description
|
201
203
|
: "This application accepts any of the following "
|
202
204
|
"possible arguments:");
|
@@ -204,10 +206,11 @@ print_help:
|
|
204
206
|
char const **pos = parser->names;
|
205
207
|
while (*pos) {
|
206
208
|
switch ((intptr_t)*pos) {
|
207
|
-
case /* FIO_CLI_TYPE_STRING */ 0x1:
|
208
|
-
case /* FIO_CLI_TYPE_BOOL */ 0x2:
|
209
|
-
case /* FIO_CLI_TYPE_INT */ 0x3:
|
210
|
-
case /* FIO_CLI_TYPE_PRINT */ 0x4:
|
209
|
+
case /* FIO_CLI_TYPE_STRING */ 0x1: /* fallthrough */
|
210
|
+
case /* FIO_CLI_TYPE_BOOL */ 0x2: /* fallthrough */
|
211
|
+
case /* FIO_CLI_TYPE_INT */ 0x3: /* fallthrough */
|
212
|
+
case /* FIO_CLI_TYPE_PRINT */ 0x4: /* fallthrough */
|
213
|
+
case /* FIO_CLI_TYPE_PRINT_HEADER */ 0x5: /* fallthrough */
|
211
214
|
++pos;
|
212
215
|
continue;
|
213
216
|
}
|
@@ -217,6 +220,10 @@ print_help:
|
|
217
220
|
fprintf(stderr, "%s\n", pos[0]);
|
218
221
|
pos += 2;
|
219
222
|
continue;
|
223
|
+
case /* FIO_CLI_TYPE_PRINT_HEADER */ 0x5:
|
224
|
+
fprintf(stderr, "\n\x1B[4m%s\x1B[0m\n", pos[0]);
|
225
|
+
pos += 2;
|
226
|
+
continue;
|
220
227
|
|
221
228
|
case /* FIO_CLI_TYPE_STRING */ 0x1: /* fallthrough */
|
222
229
|
case /* FIO_CLI_TYPE_BOOL */ 0x2: /* fallthrough */
|
@@ -321,14 +328,15 @@ void fio_cli_start AVOID_MACRO(int argc, char const *argv[], int unnamed_min,
|
|
321
328
|
char const **line = names;
|
322
329
|
while (*line) {
|
323
330
|
switch ((intptr_t)*line) {
|
324
|
-
case /* FIO_CLI_TYPE_STRING */ 0x1:
|
325
|
-
case /* FIO_CLI_TYPE_BOOL */ 0x2:
|
326
|
-
case /* FIO_CLI_TYPE_INT */ 0x3:
|
327
|
-
case /* FIO_CLI_TYPE_PRINT */ 0x4:
|
331
|
+
case /* FIO_CLI_TYPE_STRING */ 0x1: /* fallthrough */
|
332
|
+
case /* FIO_CLI_TYPE_BOOL */ 0x2: /* fallthrough */
|
333
|
+
case /* FIO_CLI_TYPE_INT */ 0x3: /* fallthrough */
|
334
|
+
case /* FIO_CLI_TYPE_PRINT */ 0x4: /* fallthrough */
|
335
|
+
case /* FIO_CLI_TYPE_PRINT_HEADER */ 0x5: /* fallthrough */
|
328
336
|
++line;
|
329
337
|
continue;
|
330
338
|
}
|
331
|
-
if (line[1] != FIO_CLI_TYPE_PRINT)
|
339
|
+
if (line[1] != FIO_CLI_TYPE_PRINT && line[1] != FIO_CLI_TYPE_PRINT_HEADER)
|
332
340
|
fio_cli_map_line2alias(*line);
|
333
341
|
++line;
|
334
342
|
}
|
data/ext/iodine/fio_cli.h
CHANGED
@@ -22,8 +22,10 @@ CLI API
|
|
22
22
|
#define FIO_CLI_TYPE_BOOL ((char *)0x2)
|
23
23
|
/** Indicates the previous CLI argument should be an Integer (numerical). */
|
24
24
|
#define FIO_CLI_TYPE_INT ((char *)0x3)
|
25
|
-
/** Indicates the previous CLI
|
25
|
+
/** Indicates the previous CLI string should be printed as is. */
|
26
26
|
#define FIO_CLI_TYPE_PRINT ((char *)0x4)
|
27
|
+
/** Indicates the previous CLI string should be printed as a header. */
|
28
|
+
#define FIO_CLI_TYPE_PRINT_HEADER ((char *)0x5)
|
27
29
|
|
28
30
|
/**
|
29
31
|
* This function parses the Command Line Interface (CLI), creating a temporary
|
data/ext/iodine/fiobj_data.c
CHANGED
@@ -867,11 +867,16 @@ static fio_str_info_s fiobj_data_pread_file(FIOBJ io, intptr_t start_at,
|
|
867
867
|
start_at = 0;
|
868
868
|
if (length + start_at > (uint64_t)size)
|
869
869
|
length = size - start_at;
|
870
|
-
if (length == 0)
|
870
|
+
if (length == 0) {
|
871
|
+
/* free memory once there's no more data to read */
|
872
|
+
obj2io(io)->capa = 0;
|
873
|
+
fio_free(obj2io(io)->buffer);
|
874
|
+
obj2io(io)->buffer = NULL;
|
871
875
|
return (fio_str_info_s){
|
872
876
|
.data = NULL,
|
873
877
|
.len = 0,
|
874
878
|
};
|
879
|
+
}
|
875
880
|
obj2io(io)->len = 0;
|
876
881
|
obj2io(io)->pos = 0;
|
877
882
|
fiobj_data_pre_write(io, length + 1);
|
data/ext/iodine/fiobj_mustache.c
CHANGED
@@ -73,20 +73,68 @@ FIOBJ fiobj_mustache_build(mustache_s *mustache, FIOBJ data) {
|
|
73
73
|
Mustache Callbacks
|
74
74
|
***************************************************************************** */
|
75
75
|
|
76
|
-
static inline FIOBJ
|
77
|
-
|
78
|
-
|
76
|
+
static inline FIOBJ fiobj_mustache_find_obj_absolute(FIOBJ parent, FIOBJ key) {
|
77
|
+
if (!FIOBJ_TYPE_IS(parent, FIOBJ_T_HASH))
|
78
|
+
return FIOBJ_INVALID;
|
79
|
+
FIOBJ o = FIOBJ_INVALID;
|
80
|
+
o = fiobj_hash_get(parent, key);
|
81
|
+
return o;
|
82
|
+
}
|
83
|
+
|
84
|
+
static inline FIOBJ fiobj_mustache_find_obj_tree(mustache_section_s *section,
|
85
|
+
const char *name,
|
86
|
+
uint32_t name_len) {
|
79
87
|
FIOBJ key = fiobj_str_tmp();
|
80
88
|
fiobj_str_write(key, name, name_len);
|
81
|
-
FIOBJ o = FIOBJ_INVALID;
|
82
89
|
do {
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
} while (
|
88
|
-
return
|
90
|
+
FIOBJ tmp = fiobj_mustache_find_obj_absolute((FIOBJ)section->udata2, key);
|
91
|
+
if (tmp != FIOBJ_INVALID) {
|
92
|
+
return tmp;
|
93
|
+
}
|
94
|
+
} while ((section = mustache_section_parent(section)));
|
95
|
+
return FIOBJ_INVALID;
|
89
96
|
}
|
97
|
+
|
98
|
+
static inline FIOBJ fiobj_mustache_find_obj(mustache_section_s *section,
|
99
|
+
const char *name,
|
100
|
+
uint32_t name_len) {
|
101
|
+
FIOBJ tmp = fiobj_mustache_find_obj_tree(section, name, name_len);
|
102
|
+
if (tmp != FIOBJ_INVALID)
|
103
|
+
return tmp;
|
104
|
+
/* interpolate sections... */
|
105
|
+
uint32_t dot = 0;
|
106
|
+
while (dot < name_len && name[dot] != '.')
|
107
|
+
++dot;
|
108
|
+
if (dot == name_len)
|
109
|
+
return FIOBJ_INVALID;
|
110
|
+
tmp = fiobj_mustache_find_obj_tree(section, name, dot);
|
111
|
+
if (!tmp) {
|
112
|
+
return FIOBJ_INVALID;
|
113
|
+
}
|
114
|
+
++dot;
|
115
|
+
for (;;) {
|
116
|
+
FIOBJ key = fiobj_str_tmp();
|
117
|
+
fiobj_str_write(key, name + dot, name_len - dot);
|
118
|
+
FIOBJ obj = fiobj_mustache_find_obj_absolute(tmp, key);
|
119
|
+
if (obj != FIOBJ_INVALID)
|
120
|
+
return obj;
|
121
|
+
name += dot;
|
122
|
+
name_len -= dot;
|
123
|
+
dot = 0;
|
124
|
+
while (dot < name_len && name[dot] != '.')
|
125
|
+
++dot;
|
126
|
+
if (dot == name_len) {
|
127
|
+
return FIOBJ_INVALID;
|
128
|
+
}
|
129
|
+
key = fiobj_str_tmp();
|
130
|
+
fiobj_str_write(key, name, dot);
|
131
|
+
tmp = fiobj_mustache_find_obj_absolute(tmp, key);
|
132
|
+
if (tmp == FIOBJ_INVALID)
|
133
|
+
return FIOBJ_INVALID;
|
134
|
+
++dot;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
90
138
|
/**
|
91
139
|
* Called when an argument name was detected in the current section.
|
92
140
|
*
|
@@ -209,11 +257,11 @@ void fiobj_mustache_test(void) {
|
|
209
257
|
exit(-1); \
|
210
258
|
}
|
211
259
|
|
212
|
-
char const *template =
|
213
|
-
|
260
|
+
char const *template =
|
261
|
+
"{{=<< >>=}}* Users:\r\n<<#users>><<id>>. <<& name>> "
|
262
|
+
"(<<name>>)\r\n<</users>>\r\nNested: <<& nested.item >>.";
|
214
263
|
char const *template_name = "mustache_test_template.mustache";
|
215
264
|
mustache_save2file(template_name, template, strlen(template));
|
216
|
-
// mustache_error_en err = MUSTACHE_OK;
|
217
265
|
mustache_s *m =
|
218
266
|
fiobj_mustache_load((fio_str_info_s){.data = (char *)template_name});
|
219
267
|
unlink(template_name);
|
@@ -238,11 +286,19 @@ void fiobj_mustache_test(void) {
|
|
238
286
|
fiobj_free(key);
|
239
287
|
fiobj_ary_push(ary, usr);
|
240
288
|
}
|
289
|
+
key = fiobj_str_new("nested", 6);
|
290
|
+
ary = fiobj_hash_new2(2);
|
291
|
+
fiobj_hash_set(data, key, ary);
|
292
|
+
fiobj_free(key);
|
293
|
+
key = fiobj_str_new("item", 4);
|
294
|
+
fiobj_hash_set(ary, key, fiobj_str_new("dot notation success", 20));
|
295
|
+
fiobj_free(key);
|
241
296
|
key = fiobj_mustache_build(m, data);
|
242
297
|
fiobj_free(data);
|
243
298
|
TEST_ASSERT(key, "fiobj_mustache_build failed!\n");
|
244
299
|
fprintf(stderr, "%s\n", fiobj_obj2cstr(key).data);
|
245
300
|
fiobj_free(key);
|
301
|
+
fiobj_mustache_free(m);
|
246
302
|
}
|
247
303
|
|
248
304
|
#endif
|
data/ext/iodine/http.c
CHANGED
@@ -1833,7 +1833,7 @@ static void http_mime_parser_on_data(http_mime_parser_s *parser, void *name,
|
|
1833
1833
|
size_t filename_len, void *mimetype,
|
1834
1834
|
size_t mimetype_len, void *value,
|
1835
1835
|
size_t value_len) {
|
1836
|
-
if (!
|
1836
|
+
if (!filename_len) {
|
1837
1837
|
http_add2hash(http_mime_parser2fio(parser)->h->params, name, name_len,
|
1838
1838
|
value, value_len, 0);
|
1839
1839
|
return;
|
@@ -1844,15 +1844,17 @@ static void http_mime_parser_on_data(http_mime_parser_s *parser, void *name,
|
|
1844
1844
|
http_add2hash(http_mime_parser2fio(parser)->h->params, tmp.data, tmp.len,
|
1845
1845
|
value, value_len, 0);
|
1846
1846
|
fiobj_str_resize(n, name_len);
|
1847
|
-
fiobj_str_write(n, "[type]", 6);
|
1848
|
-
tmp = fiobj_obj2cstr(n);
|
1849
|
-
http_add2hash(http_mime_parser2fio(parser)->h->params, tmp.data, tmp.len,
|
1850
|
-
mimetype, mimetype_len, 0);
|
1851
|
-
fiobj_str_resize(n, name_len);
|
1852
1847
|
fiobj_str_write(n, "[name]", 6);
|
1853
1848
|
tmp = fiobj_obj2cstr(n);
|
1854
1849
|
http_add2hash(http_mime_parser2fio(parser)->h->params, tmp.data, tmp.len,
|
1855
1850
|
filename, filename_len, 0);
|
1851
|
+
if (mimetype_len) {
|
1852
|
+
fiobj_str_resize(n, name_len);
|
1853
|
+
fiobj_str_write(n, "[type]", 6);
|
1854
|
+
tmp = fiobj_obj2cstr(n);
|
1855
|
+
http_add2hash(http_mime_parser2fio(parser)->h->params, tmp.data, tmp.len,
|
1856
|
+
mimetype, mimetype_len, 0);
|
1857
|
+
}
|
1856
1858
|
fiobj_free(n);
|
1857
1859
|
}
|
1858
1860
|
|
@@ -1900,13 +1902,25 @@ static void http_mime_parser_on_partial_end(http_mime_parser_s *parser) {
|
|
1900
1902
|
|
1901
1903
|
fio_str_info_s tmp =
|
1902
1904
|
fiobj_obj2cstr(http_mime_parser2fio(parser)->partial_name);
|
1903
|
-
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1905
|
+
FIOBJ o = FIOBJ_INVALID;
|
1906
|
+
if (!http_mime_parser2fio(parser)->partial_length)
|
1907
|
+
return;
|
1908
|
+
if (http_mime_parser2fio(parser)->partial_length < 42) {
|
1909
|
+
/* short data gets a new object */
|
1910
|
+
o = fiobj_str_new(http_mime_parser2fio(parser)->buffer.data +
|
1911
|
+
http_mime_parser2fio(parser)->partial_offset,
|
1912
|
+
http_mime_parser2fio(parser)->partial_length);
|
1913
|
+
} else {
|
1914
|
+
/* longer data gets a reference object (memory collision concerns) */
|
1915
|
+
o = fiobj_data_slice(http_mime_parser2fio(parser)->h->body,
|
1916
|
+
http_mime_parser2fio(parser)->partial_offset,
|
1917
|
+
http_mime_parser2fio(parser)->partial_length);
|
1918
|
+
}
|
1919
|
+
http_add2hash2(http_mime_parser2fio(parser)->h->params, tmp.data, tmp.len, o,
|
1907
1920
|
0);
|
1908
1921
|
fiobj_free(http_mime_parser2fio(parser)->partial_name);
|
1909
1922
|
http_mime_parser2fio(parser)->partial_name = FIOBJ_INVALID;
|
1923
|
+
http_mime_parser2fio(parser)->partial_offset = 0;
|
1910
1924
|
}
|
1911
1925
|
|
1912
1926
|
/**
|
@@ -1976,7 +1990,7 @@ int http_parse_body(http_s *h) {
|
|
1976
1990
|
do {
|
1977
1991
|
size_t cons = http_mime_parse(&p.p, p.buffer.data, p.buffer.len);
|
1978
1992
|
p.pos += cons;
|
1979
|
-
p.buffer = fiobj_data_pread(h->body, p.pos,
|
1993
|
+
p.buffer = fiobj_data_pread(h->body, p.pos, 4096);
|
1980
1994
|
} while (p.buffer.data && !p.p.done && !p.p.error);
|
1981
1995
|
fiobj_free(p.partial_name);
|
1982
1996
|
p.partial_name = FIOBJ_INVALID;
|
@@ -2903,5 +2917,6 @@ void http_tests(void) {
|
|
2903
2917
|
FIOBJ html_mime = http_mimetype_find("html", 4);
|
2904
2918
|
FIO_ASSERT(html_mime,
|
2905
2919
|
"HTML mime-type not found! Mime-Type registry invalid!\n");
|
2920
|
+
fiobj_free(html_mime);
|
2906
2921
|
}
|
2907
2922
|
#endif
|
data/ext/iodine/http1.c
CHANGED
@@ -554,7 +554,7 @@ static int http1_on_request(http1_parser_s *parser) {
|
|
554
554
|
if (p->request.method && !p->stop)
|
555
555
|
http_finish(&p->request);
|
556
556
|
h1_reset(p);
|
557
|
-
return
|
557
|
+
return fio_is_closed(p->p.uuid);
|
558
558
|
}
|
559
559
|
/** called when a response was received. */
|
560
560
|
static int http1_on_response(http1_parser_s *parser) {
|
@@ -563,7 +563,7 @@ static int http1_on_response(http1_parser_s *parser) {
|
|
563
563
|
if (p->request.status_str && !p->stop)
|
564
564
|
http_finish(&p->request);
|
565
565
|
h1_reset(p);
|
566
|
-
return
|
566
|
+
return fio_is_closed(p->p.uuid);
|
567
567
|
}
|
568
568
|
/** called when a request method is parsed. */
|
569
569
|
static int http1_on_method(http1_parser_s *parser, char *method,
|
@@ -751,7 +751,7 @@ static void http1_on_data_first_time(intptr_t uuid, fio_protocol_s *protocol) {
|
|
751
751
|
/* ensure future reads skip this first time HTTP/2.0 test */
|
752
752
|
p->p.protocol.on_data = http1_on_data;
|
753
753
|
if (i >= 24 && !memcmp(p->buf, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", 24)) {
|
754
|
-
|
754
|
+
FIO_LOG_WARNING("client claimed unsupported HTTP/2 prior knowledge.");
|
755
755
|
fio_close(uuid);
|
756
756
|
return;
|
757
757
|
}
|
@@ -10,6 +10,15 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
10
10
|
#include <stdlib.h>
|
11
11
|
#include <string.h>
|
12
12
|
|
13
|
+
/* *****************************************************************************
|
14
|
+
Known Limitations:
|
15
|
+
|
16
|
+
- Doesn't support nested multipart form structures (i.e., multi-file selection).
|
17
|
+
See: https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
|
18
|
+
|
19
|
+
To circumvent limitation, initialize a new parser to parse nested multiparts.
|
20
|
+
***************************************************************************** */
|
21
|
+
|
13
22
|
/* *****************************************************************************
|
14
23
|
The HTTP MIME Multipart Form Parser Type
|
15
24
|
***************************************************************************** */
|
data/ext/iodine/iodine.c
CHANGED
@@ -286,13 +286,15 @@ CLI parser (Ruby's OptParser is more limiting than I knew...)
|
|
286
286
|
*
|
287
287
|
* @params [String] desc a String containg the iodine server's description.
|
288
288
|
*/
|
289
|
-
static VALUE iodine_cli_parse(VALUE self
|
289
|
+
static VALUE iodine_cli_parse(VALUE self) {
|
290
290
|
(void)self;
|
291
|
-
Check_Type(desc, T_STRING);
|
292
291
|
VALUE ARGV = rb_get_argv();
|
293
292
|
VALUE ret = Qtrue;
|
294
293
|
VALUE defaults = iodine_default_args;
|
295
|
-
|
294
|
+
VALUE iodine_version = rb_const_get(IodineModule, rb_intern("VERSION"));
|
295
|
+
char desc[1024];
|
296
|
+
if (!defaults || !ARGV || TYPE(ARGV) != T_ARRAY || TYPE(defaults) != T_HASH ||
|
297
|
+
TYPE(iodine_version) != T_STRING || RSTRING_LEN(iodine_version) > 512) {
|
296
298
|
FIO_LOG_ERROR("CLI parsing initialization error "
|
297
299
|
"ARGV=%p, Array?(%d), defaults == %p (%d)",
|
298
300
|
(void *)ARGV, (int)(TYPE(ARGV) == T_ARRAY), (void *)defaults,
|
@@ -300,7 +302,7 @@ static VALUE iodine_cli_parse(VALUE self, VALUE desc) {
|
|
300
302
|
return Qnil;
|
301
303
|
}
|
302
304
|
/* Copy the Ruby ARGV to a C valid ARGV */
|
303
|
-
int argc = (int)
|
305
|
+
int argc = (int)RARRAY_LEN(ARGV) + 1;
|
304
306
|
if (argc <= 1) {
|
305
307
|
FIO_LOG_DEBUG("CLI: No arguments to parse...\n");
|
306
308
|
return Qnil;
|
@@ -324,36 +326,52 @@ static VALUE iodine_cli_parse(VALUE self, VALUE desc) {
|
|
324
326
|
argv[i][s.len] = 0;
|
325
327
|
}
|
326
328
|
/* Levarage the facil.io CLI library */
|
329
|
+
memcpy(desc, "Iodine's HTTP/WebSocket server version ", 39);
|
330
|
+
memcpy(desc + 39, StringValueCStr(iodine_version),
|
331
|
+
RSTRING_LEN(iodine_version));
|
332
|
+
memcpy(desc + 39 + RSTRING_LEN(iodine_version),
|
333
|
+
"\r\n\r\nUse:\r\n iodine <options> <filename>\r\n\r\n"
|
334
|
+
"Both <options> and <filename> are optional. i.e.,:\r\n"
|
335
|
+
" iodine -p 0 -b /tmp/my_unix_sock\r\n"
|
336
|
+
" iodine -p 8080 path/to/app/conf.ru\r\n"
|
337
|
+
" iodine -p 8080 -w 4 -t 16\r\n"
|
338
|
+
" iodine -w -1 -t 4 -r redis://usr:pass@localhost:6379/",
|
339
|
+
263);
|
340
|
+
desc[39 + 263 + RSTRING_LEN(iodine_version)] = 0;
|
327
341
|
fio_cli_start(
|
328
|
-
argc, (const char **)argv, 0, -1,
|
329
|
-
"
|
330
|
-
"-bind -b -address address to listen to. defaults any available.",
|
342
|
+
argc, (const char **)argv, 0, -1, desc,
|
343
|
+
"Address Binding:", FIO_CLI_TYPE_PRINT_HEADER,
|
344
|
+
"-bind -b -address address to listen to. defaults to any available.",
|
331
345
|
"-port -p port number to listen to. defaults port 3000", FIO_CLI_TYPE_INT,
|
332
|
-
"\
|
346
|
+
"\t\t\x1B[4mNote\x1B[0m: to bind to a Unix socket, "
|
347
|
+
"set \x1B[1mport\x1B[0m to 0.",
|
348
|
+
FIO_CLI_TYPE_PRINT, "Concurrency:", FIO_CLI_TYPE_PRINT_HEADER,
|
333
349
|
"-workers -w number of processes to use.", FIO_CLI_TYPE_INT,
|
334
350
|
"-threads -t number of threads per process.", FIO_CLI_TYPE_INT,
|
335
|
-
"
|
351
|
+
"HTTP Server:", FIO_CLI_TYPE_PRINT_HEADER,
|
336
352
|
"-public -www public folder, for static file service.",
|
337
353
|
"-log -v HTTP request logging.", FIO_CLI_TYPE_BOOL,
|
338
|
-
"-keep-alive -k -tout HTTP keep-alive timeout (0..255).
|
354
|
+
"-keep-alive -k -tout HTTP keep-alive timeout in seconds (0..255). "
|
355
|
+
"Default: 40s",
|
339
356
|
FIO_CLI_TYPE_INT, "-ping websocket ping interval (0..255). Default: 40s",
|
340
357
|
FIO_CLI_TYPE_INT,
|
341
358
|
"-max-body -maxbd HTTP upload limit in Mega-Bytes. Default: 50Mb",
|
342
359
|
FIO_CLI_TYPE_INT,
|
343
360
|
"-max-header -maxhd header limit per HTTP request in Kb."
|
344
361
|
" Default: 32Kb.",
|
345
|
-
FIO_CLI_TYPE_INT, "
|
362
|
+
FIO_CLI_TYPE_INT, "WebSocket Server:", FIO_CLI_TYPE_PRINT_HEADER,
|
346
363
|
"-max-msg -maxms incoming WebSocket message limit in Kb. "
|
347
364
|
"Default: 250Kb",
|
348
|
-
FIO_CLI_TYPE_INT,
|
349
|
-
|
365
|
+
FIO_CLI_TYPE_INT,
|
366
|
+
"Connecting Iodine to Redis:", FIO_CLI_TYPE_PRINT_HEADER,
|
350
367
|
"-redis -r an optional Redis URL server address. Default: none.",
|
351
|
-
"-redis-ping -rp websocket ping interval (0..255). Default:
|
352
|
-
FIO_CLI_TYPE_INT, "
|
368
|
+
"-redis-ping -rp websocket ping interval (0..255). Default: 300s",
|
369
|
+
FIO_CLI_TYPE_INT, "Misc:", FIO_CLI_TYPE_PRINT_HEADER,
|
353
370
|
"-warmup --preload warm up the application. CAREFUL! with workers.",
|
354
371
|
FIO_CLI_TYPE_BOOL,
|
355
372
|
"-verbosity -V 0..5 server verbosity level. Default: 4",
|
356
373
|
FIO_CLI_TYPE_INT);
|
374
|
+
|
357
375
|
/* copy values from CLI library to iodine */
|
358
376
|
if (fio_cli_get("-V")) {
|
359
377
|
int level = fio_cli_get_i("-V");
|
@@ -472,7 +490,7 @@ void Init_iodine(void) {
|
|
472
490
|
rb_define_module_function(IodineModule, "worker?", iodine_worker_is, 0);
|
473
491
|
|
474
492
|
// register CLI methods
|
475
|
-
rb_define_module_function(IodineCLIModule, "parse", iodine_cli_parse,
|
493
|
+
rb_define_module_function(IodineCLIModule, "parse", iodine_cli_parse, 0);
|
476
494
|
|
477
495
|
// initialize Object storage for GC protection
|
478
496
|
iodine_storage_init();
|