isomorfeus-iodine 0.7.44
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/.travis.yml +32 -0
- data/.yardopts +8 -0
- data/CHANGELOG.md +1038 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +21 -0
- data/LIMITS.md +41 -0
- data/README.md +782 -0
- data/Rakefile +44 -0
- data/SPEC-PubSub-Draft.md +159 -0
- data/SPEC-WebSocket-Draft.md +239 -0
- data/bin/console +22 -0
- data/bin/info.md +353 -0
- data/bin/mustache_bench.rb +100 -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/examples/async_task.ru +92 -0
- data/examples/config.ru +56 -0
- data/examples/echo.ru +59 -0
- data/examples/hello.ru +29 -0
- data/examples/pubsub_engine.ru +81 -0
- data/examples/redis.ru +70 -0
- data/examples/shootout.ru +73 -0
- data/examples/sub-protocols.ru +90 -0
- data/examples/tcp_client.rb +66 -0
- data/examples/x-sendfile.ru +14 -0
- data/exe/iodine +277 -0
- data/ext/iodine/extconf.rb +109 -0
- data/ext/iodine/fio.c +11985 -0
- data/ext/iodine/fio.h +6373 -0
- data/ext/iodine/fio_cli.c +431 -0
- data/ext/iodine/fio_cli.h +189 -0
- data/ext/iodine/fio_json_parser.h +687 -0
- data/ext/iodine/fio_siphash.c +157 -0
- data/ext/iodine/fio_siphash.h +37 -0
- data/ext/iodine/fio_tls.h +129 -0
- data/ext/iodine/fio_tls_missing.c +649 -0
- data/ext/iodine/fio_tls_openssl.c +1056 -0
- data/ext/iodine/fio_tmpfile.h +50 -0
- data/ext/iodine/fiobj.h +44 -0
- data/ext/iodine/fiobj4fio.h +21 -0
- data/ext/iodine/fiobj_ary.c +333 -0
- data/ext/iodine/fiobj_ary.h +139 -0
- data/ext/iodine/fiobj_data.c +1185 -0
- data/ext/iodine/fiobj_data.h +167 -0
- data/ext/iodine/fiobj_hash.c +409 -0
- data/ext/iodine/fiobj_hash.h +176 -0
- data/ext/iodine/fiobj_json.c +622 -0
- data/ext/iodine/fiobj_json.h +68 -0
- data/ext/iodine/fiobj_mem.h +71 -0
- data/ext/iodine/fiobj_mustache.c +317 -0
- data/ext/iodine/fiobj_mustache.h +62 -0
- data/ext/iodine/fiobj_numbers.c +344 -0
- data/ext/iodine/fiobj_numbers.h +127 -0
- data/ext/iodine/fiobj_str.c +433 -0
- data/ext/iodine/fiobj_str.h +172 -0
- data/ext/iodine/fiobject.c +620 -0
- data/ext/iodine/fiobject.h +654 -0
- data/ext/iodine/hpack.h +1923 -0
- data/ext/iodine/http.c +2754 -0
- data/ext/iodine/http.h +1002 -0
- data/ext/iodine/http1.c +912 -0
- data/ext/iodine/http1.h +29 -0
- data/ext/iodine/http1_parser.h +873 -0
- data/ext/iodine/http_internal.c +1278 -0
- data/ext/iodine/http_internal.h +237 -0
- data/ext/iodine/http_mime_parser.h +350 -0
- data/ext/iodine/iodine.c +1430 -0
- data/ext/iodine/iodine.h +63 -0
- data/ext/iodine/iodine_caller.c +218 -0
- data/ext/iodine/iodine_caller.h +27 -0
- data/ext/iodine/iodine_connection.c +933 -0
- data/ext/iodine/iodine_connection.h +55 -0
- data/ext/iodine/iodine_defer.c +420 -0
- data/ext/iodine/iodine_defer.h +6 -0
- data/ext/iodine/iodine_fiobj2rb.h +120 -0
- data/ext/iodine/iodine_helpers.c +282 -0
- data/ext/iodine/iodine_helpers.h +12 -0
- data/ext/iodine/iodine_http.c +1171 -0
- data/ext/iodine/iodine_http.h +23 -0
- data/ext/iodine/iodine_json.c +302 -0
- data/ext/iodine/iodine_json.h +6 -0
- data/ext/iodine/iodine_mustache.c +567 -0
- data/ext/iodine/iodine_mustache.h +6 -0
- data/ext/iodine/iodine_pubsub.c +580 -0
- data/ext/iodine/iodine_pubsub.h +26 -0
- data/ext/iodine/iodine_rack_io.c +281 -0
- data/ext/iodine/iodine_rack_io.h +20 -0
- data/ext/iodine/iodine_store.c +142 -0
- data/ext/iodine/iodine_store.h +20 -0
- data/ext/iodine/iodine_tcp.c +346 -0
- data/ext/iodine/iodine_tcp.h +13 -0
- data/ext/iodine/iodine_tls.c +261 -0
- data/ext/iodine/iodine_tls.h +13 -0
- data/ext/iodine/mustache_parser.h +1546 -0
- data/ext/iodine/redis_engine.c +957 -0
- data/ext/iodine/redis_engine.h +79 -0
- data/ext/iodine/resp_parser.h +317 -0
- data/ext/iodine/websocket_parser.h +505 -0
- data/ext/iodine/websockets.c +735 -0
- data/ext/iodine/websockets.h +185 -0
- data/isomorfeus-iodine.gemspec +42 -0
- data/lib/iodine/connection.rb +61 -0
- data/lib/iodine/json.rb +42 -0
- data/lib/iodine/mustache.rb +113 -0
- data/lib/iodine/pubsub.rb +55 -0
- data/lib/iodine/rack_utils.rb +43 -0
- data/lib/iodine/tls.rb +16 -0
- data/lib/iodine/version.rb +3 -0
- data/lib/iodine.rb +274 -0
- data/lib/rack/handler/iodine.rb +33 -0
- data/logo.png +0 -0
- metadata +271 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
/*
|
2
|
+
Copyright: Boaz segev, 2016-2019
|
3
|
+
License: MIT
|
4
|
+
|
5
|
+
Feel free to copy, use and enjoy according to the license provided.
|
6
|
+
*/
|
7
|
+
#ifndef H_REDIS_ENGINE_H
|
8
|
+
#define H_REDIS_ENGINE_H
|
9
|
+
|
10
|
+
#include <fio.h>
|
11
|
+
#include <fiobj.h>
|
12
|
+
|
13
|
+
/* support C++ */
|
14
|
+
#ifdef __cplusplus
|
15
|
+
extern "C" {
|
16
|
+
#endif
|
17
|
+
|
18
|
+
/** possible arguments for the `redis_engine_create` function call */
|
19
|
+
struct redis_engine_create_args {
|
20
|
+
/** Redis server's address, defaults to localhost. */
|
21
|
+
fio_str_info_s address;
|
22
|
+
/** Redis server's port, defaults to 6379. */
|
23
|
+
fio_str_info_s port;
|
24
|
+
/** Redis server's password, if any. */
|
25
|
+
fio_str_info_s auth;
|
26
|
+
/** A `ping` will be sent every `ping_interval` interval or inactivity. */
|
27
|
+
uint8_t ping_interval;
|
28
|
+
};
|
29
|
+
|
30
|
+
/**
|
31
|
+
* See the {fio.h} file for documentation about engines.
|
32
|
+
*
|
33
|
+
* The engine is active only after facil.io starts running.
|
34
|
+
*
|
35
|
+
* A `ping` will be sent every `ping_interval` interval or inactivity. The
|
36
|
+
* default value (0) will fallback to facil.io's maximum time of inactivity (5
|
37
|
+
* minutes) before polling on the connection's protocol.
|
38
|
+
*
|
39
|
+
* function names speak for themselves ;-)
|
40
|
+
*
|
41
|
+
* Note: The Redis engine assumes it will stay alive until all the messages and
|
42
|
+
* callbacks have been called (or facil.io exits)... If the engine is destroyed
|
43
|
+
* midway, memory leaks might occur (and little puppies might cry).
|
44
|
+
*/
|
45
|
+
fio_pubsub_engine_s *redis_engine_create(struct redis_engine_create_args);
|
46
|
+
#define redis_engine_create(...) \
|
47
|
+
redis_engine_create((struct redis_engine_create_args){__VA_ARGS__})
|
48
|
+
|
49
|
+
/**
|
50
|
+
* Sends a Redis command through the engine's connection.
|
51
|
+
*
|
52
|
+
* The response will be sent back using the optional callback. `udata` is passed
|
53
|
+
* along untouched.
|
54
|
+
*
|
55
|
+
* The message will be resent on network failures, until a response validates
|
56
|
+
* the fact that the command was sent (or the engine is destroyed).
|
57
|
+
*
|
58
|
+
* Note: NEVER call Pub/Sub commands using this function, as it will violate the
|
59
|
+
* Redis connection's protocol (best case scenario, a disconnection will occur
|
60
|
+
* before and messages are lost).
|
61
|
+
*/
|
62
|
+
intptr_t redis_engine_send(fio_pubsub_engine_s *engine, FIOBJ command,
|
63
|
+
void (*callback)(fio_pubsub_engine_s *e, FIOBJ reply,
|
64
|
+
void *udata),
|
65
|
+
void *udata);
|
66
|
+
|
67
|
+
/**
|
68
|
+
* See the {pubsub.h} file for documentation about engines.
|
69
|
+
*
|
70
|
+
* function names speak for themselves ;-)
|
71
|
+
*/
|
72
|
+
void redis_engine_destroy(fio_pubsub_engine_s *engine);
|
73
|
+
|
74
|
+
/* support C++ */
|
75
|
+
#ifdef __cplusplus
|
76
|
+
}
|
77
|
+
#endif
|
78
|
+
|
79
|
+
#endif /* H_REDIS_ENGINE_H */
|
@@ -0,0 +1,317 @@
|
|
1
|
+
/*
|
2
|
+
Copyright: Boaz segev, 2016-2019
|
3
|
+
License: MIT
|
4
|
+
|
5
|
+
Feel free to copy, use and enjoy according to the license provided.
|
6
|
+
*/
|
7
|
+
#ifndef H_RESP_PARSER_H
|
8
|
+
/**
|
9
|
+
* This single file library is a RESP parser for Redis connections.
|
10
|
+
*
|
11
|
+
* To use this file, the `.c` file in which this file is included MUST define a
|
12
|
+
* number of callbacks, as later inticated.
|
13
|
+
*
|
14
|
+
* When feeding the parser, the parser will inform of any trailing bytes (bytes
|
15
|
+
* at the end of the buffer that could not be parsed). These bytes should be
|
16
|
+
* resent to the parser along with more data. Zero is a valid return value.
|
17
|
+
*
|
18
|
+
* Note: mostly, callback return vaslues are ignored.
|
19
|
+
*/
|
20
|
+
#define H_RESP_PARSER_H
|
21
|
+
|
22
|
+
#ifndef _GNU_SOURCE
|
23
|
+
#define _GNU_SOURCE
|
24
|
+
#endif
|
25
|
+
|
26
|
+
#include <stdint.h>
|
27
|
+
#include <stdlib.h>
|
28
|
+
#include <string.h>
|
29
|
+
|
30
|
+
/* *****************************************************************************
|
31
|
+
The Parser
|
32
|
+
***************************************************************************** */
|
33
|
+
|
34
|
+
typedef struct resp_parser_s {
|
35
|
+
/* for internal use - (array / object countdown) */
|
36
|
+
intptr_t obj_countdown;
|
37
|
+
/* for internal use - (string byte consumption) */
|
38
|
+
intptr_t expecting;
|
39
|
+
} resp_parser_s;
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Returns the number of bytes to be resent. i.e., for a return value 5, the
|
43
|
+
* last 5 bytes in the buffer need to be resent to the parser.
|
44
|
+
*/
|
45
|
+
static size_t resp_parse(resp_parser_s *parser, const void *buffer,
|
46
|
+
size_t length);
|
47
|
+
|
48
|
+
/* *****************************************************************************
|
49
|
+
Required Parser Callbacks (to be defined by the including file)
|
50
|
+
***************************************************************************** */
|
51
|
+
|
52
|
+
/** a local static callback, called when the RESP message is complete. */
|
53
|
+
static int resp_on_message(resp_parser_s *parser);
|
54
|
+
|
55
|
+
/** a local static callback, called when a Number object is parsed. */
|
56
|
+
static int resp_on_number(resp_parser_s *parser, int64_t num);
|
57
|
+
/** a local static callback, called when a OK message is received. */
|
58
|
+
static int resp_on_okay(resp_parser_s *parser);
|
59
|
+
/** a local static callback, called when NULL is received. */
|
60
|
+
static int resp_on_null(resp_parser_s *parser);
|
61
|
+
|
62
|
+
/**
|
63
|
+
* a local static callback, called when a String should be allocated.
|
64
|
+
*
|
65
|
+
* `str_len` is the expected number of bytes that will fill the final string
|
66
|
+
* object, without any NUL byte marker (the string might be binary).
|
67
|
+
*
|
68
|
+
* If this function returns any value besides 0, parsing is stopped.
|
69
|
+
*/
|
70
|
+
static int resp_on_start_string(resp_parser_s *parser, size_t str_len);
|
71
|
+
/** a local static callback, called as String objects are streamed. */
|
72
|
+
static int resp_on_string_chunk(resp_parser_s *parser, void *data, size_t len);
|
73
|
+
/** a local static callback, called when a String object had finished streaming.
|
74
|
+
*/
|
75
|
+
static int resp_on_end_string(resp_parser_s *parser);
|
76
|
+
|
77
|
+
/** a local static callback, called an error message is received. */
|
78
|
+
static int resp_on_err_msg(resp_parser_s *parser, void *data, size_t len);
|
79
|
+
|
80
|
+
/**
|
81
|
+
* a local static callback, called when an Array should be allocated.
|
82
|
+
*
|
83
|
+
* `array_len` is the expected number of objects that will fill the Array
|
84
|
+
* object.
|
85
|
+
*
|
86
|
+
* There's no `resp_on_end_array` callback since the RESP protocol assumes the
|
87
|
+
* message is finished along with the Array (`resp_on_message` is called).
|
88
|
+
* However, just in case a non-conforming client/server sends nested Arrays, the
|
89
|
+
* callback should test against possible overflow or nested Array endings.
|
90
|
+
*
|
91
|
+
* If this function returns any value besides 0, parsing is stopped.
|
92
|
+
*/
|
93
|
+
static int resp_on_start_array(resp_parser_s *parser, size_t array_len);
|
94
|
+
|
95
|
+
/** a local static callback, called when a parser / protocol error occurs. */
|
96
|
+
static int resp_on_parser_error(resp_parser_s *parser);
|
97
|
+
|
98
|
+
/* *****************************************************************************
|
99
|
+
Seeking the new line...
|
100
|
+
***************************************************************************** */
|
101
|
+
|
102
|
+
#if FIO_MEMCHAR
|
103
|
+
|
104
|
+
/**
|
105
|
+
* This seems to be faster on some systems, especially for smaller distances.
|
106
|
+
*
|
107
|
+
* On newer systems, `memchr` should be faster.
|
108
|
+
*/
|
109
|
+
static inline int seek2ch(uint8_t **buffer, register const uint8_t *limit,
|
110
|
+
const uint8_t c) {
|
111
|
+
if (**buffer == c)
|
112
|
+
return 1;
|
113
|
+
|
114
|
+
#if !ALLOW_UNALIGNED_MEMORY_ACCESS || !defined(__x86_64__)
|
115
|
+
/* too short for this mess */
|
116
|
+
if ((uintptr_t)limit <= 16 + ((uintptr_t)*buffer & (~(uintptr_t)7)))
|
117
|
+
goto finish;
|
118
|
+
|
119
|
+
/* align memory */
|
120
|
+
{
|
121
|
+
const uint8_t *alignment =
|
122
|
+
(uint8_t *)(((uintptr_t)(*buffer) & (~(uintptr_t)7)) + 8);
|
123
|
+
if (limit >= alignment) {
|
124
|
+
while (*buffer < alignment) {
|
125
|
+
if (**buffer == c)
|
126
|
+
return 1;
|
127
|
+
*buffer += 1;
|
128
|
+
}
|
129
|
+
}
|
130
|
+
}
|
131
|
+
const uint8_t *limit64 = (uint8_t *)((uintptr_t)limit & (~(uintptr_t)7));
|
132
|
+
#else
|
133
|
+
const uint8_t *limit64 = (uint8_t *)limit - 7;
|
134
|
+
#endif
|
135
|
+
uint64_t wanted1 = 0x0101010101010101ULL * c;
|
136
|
+
for (; *buffer < limit64; *buffer += 8) {
|
137
|
+
const uint64_t eq1 = ~((*((uint64_t *)*buffer)) ^ wanted1);
|
138
|
+
const uint64_t t0 = (eq1 & 0x7f7f7f7f7f7f7f7fllu) + 0x0101010101010101llu;
|
139
|
+
const uint64_t t1 = (eq1 & 0x8080808080808080llu);
|
140
|
+
if ((t0 & t1)) {
|
141
|
+
break;
|
142
|
+
}
|
143
|
+
}
|
144
|
+
#if !ALLOW_UNALIGNED_MEMORY_ACCESS || !defined(__x86_64__)
|
145
|
+
finish:
|
146
|
+
#endif
|
147
|
+
while (*buffer < limit) {
|
148
|
+
if (**buffer == c)
|
149
|
+
return 1;
|
150
|
+
(*buffer)++;
|
151
|
+
}
|
152
|
+
return 0;
|
153
|
+
}
|
154
|
+
|
155
|
+
#else
|
156
|
+
|
157
|
+
/* a helper that seeks any char, converts it to NUL and returns 1 if found. */
|
158
|
+
inline static uint8_t seek2ch(uint8_t **pos, const uint8_t *limit, uint8_t ch) {
|
159
|
+
/* This is library based alternative that is sometimes slower */
|
160
|
+
if (*pos >= limit || **pos == ch) {
|
161
|
+
return 0;
|
162
|
+
}
|
163
|
+
uint8_t *tmp = (uint8_t *)memchr(*pos, ch, limit - (*pos));
|
164
|
+
if (tmp) {
|
165
|
+
*pos = tmp;
|
166
|
+
return 1;
|
167
|
+
}
|
168
|
+
*pos = (uint8_t *)limit;
|
169
|
+
return 0;
|
170
|
+
}
|
171
|
+
|
172
|
+
#endif
|
173
|
+
|
174
|
+
/* *****************************************************************************
|
175
|
+
Parsing RESP requests
|
176
|
+
***************************************************************************** */
|
177
|
+
|
178
|
+
/**
|
179
|
+
* Returns the number of bytes to be resent. i.e., for a return value 5, the
|
180
|
+
* last 5 bytes in the buffer need to be resent to the parser.
|
181
|
+
*/
|
182
|
+
static size_t resp_parse(resp_parser_s *parser, const void *buffer,
|
183
|
+
size_t length) {
|
184
|
+
if (!parser->obj_countdown)
|
185
|
+
parser->obj_countdown = 1; /* always expect something... */
|
186
|
+
uint8_t *pos = (uint8_t *)buffer;
|
187
|
+
const uint8_t *stop = pos + length;
|
188
|
+
while (pos < stop) {
|
189
|
+
uint8_t *eol;
|
190
|
+
if (parser->expecting) {
|
191
|
+
if (pos + parser->expecting + 2 > stop) {
|
192
|
+
/* read, but make sure the buffer includes the new line markers */
|
193
|
+
size_t tmp = (size_t)((uintptr_t)stop - (uintptr_t)pos);
|
194
|
+
if ((intptr_t)tmp >= parser->expecting)
|
195
|
+
tmp = parser->expecting - 1;
|
196
|
+
resp_on_string_chunk(parser, (void *)pos, tmp);
|
197
|
+
parser->expecting -= tmp;
|
198
|
+
return (size_t)((uintptr_t)stop - ((uintptr_t)pos + tmp)); /* 0 or 1 */
|
199
|
+
} else {
|
200
|
+
resp_on_string_chunk(parser, (void *)pos, parser->expecting);
|
201
|
+
resp_on_end_string(parser);
|
202
|
+
pos += parser->expecting;
|
203
|
+
if (pos[0] == '\r')
|
204
|
+
++pos;
|
205
|
+
if (pos[0] == '\n')
|
206
|
+
++pos;
|
207
|
+
parser->expecting = 0;
|
208
|
+
--parser->obj_countdown;
|
209
|
+
if (parser->obj_countdown <= 0) {
|
210
|
+
parser->obj_countdown = 1;
|
211
|
+
if (resp_on_message(parser))
|
212
|
+
goto finish;
|
213
|
+
}
|
214
|
+
continue;
|
215
|
+
}
|
216
|
+
}
|
217
|
+
eol = pos;
|
218
|
+
if (seek2ch(&eol, stop, '\n') == 0)
|
219
|
+
break;
|
220
|
+
switch (*pos) {
|
221
|
+
case '+':
|
222
|
+
if (pos[1] == 'O' && pos[2] == 'K' && pos[3] == '\r' && pos[4] == '\n') {
|
223
|
+
resp_on_okay(parser);
|
224
|
+
--parser->obj_countdown;
|
225
|
+
break;
|
226
|
+
}
|
227
|
+
if (resp_on_start_string(parser,
|
228
|
+
(size_t)((uintptr_t)eol - (uintptr_t)pos - 2))) {
|
229
|
+
pos = eol + 1;
|
230
|
+
goto finish;
|
231
|
+
}
|
232
|
+
resp_on_string_chunk(parser, (void *)(pos + 1),
|
233
|
+
(size_t)((uintptr_t)eol - (uintptr_t)pos - 1));
|
234
|
+
resp_on_end_string(parser);
|
235
|
+
--parser->obj_countdown;
|
236
|
+
break;
|
237
|
+
case '-':
|
238
|
+
resp_on_err_msg(parser, pos,
|
239
|
+
(size_t)((uintptr_t)eol - (uintptr_t)pos - 1));
|
240
|
+
--parser->obj_countdown;
|
241
|
+
break;
|
242
|
+
case '*': /* fallthrough */
|
243
|
+
case '$': /* fallthrough */
|
244
|
+
case ':': {
|
245
|
+
uint8_t id = *pos;
|
246
|
+
uint8_t inv = 0;
|
247
|
+
int64_t i = 0;
|
248
|
+
++pos;
|
249
|
+
if (pos[0] == '-') {
|
250
|
+
inv = 1;
|
251
|
+
++pos;
|
252
|
+
}
|
253
|
+
while ((size_t)(pos[0] - (uint8_t)'0') <= 9) {
|
254
|
+
i = (i * 10) + (pos[0] - ((uint8_t)'0'));
|
255
|
+
++pos;
|
256
|
+
}
|
257
|
+
if (inv)
|
258
|
+
i = i * -1;
|
259
|
+
|
260
|
+
switch (id) {
|
261
|
+
case ':':
|
262
|
+
resp_on_number(parser, i);
|
263
|
+
--parser->obj_countdown;
|
264
|
+
break;
|
265
|
+
case '$':
|
266
|
+
if (i < 0) {
|
267
|
+
resp_on_null(parser);
|
268
|
+
--parser->obj_countdown;
|
269
|
+
} else if (i == 0) {
|
270
|
+
resp_on_start_string(parser, 0);
|
271
|
+
resp_on_end_string(parser);
|
272
|
+
--parser->obj_countdown;
|
273
|
+
eol += 2; /* consume the extra "\r\n" */
|
274
|
+
} else {
|
275
|
+
if (resp_on_start_string(parser, i)) {
|
276
|
+
pos = eol + 1;
|
277
|
+
goto finish;
|
278
|
+
}
|
279
|
+
parser->expecting = i;
|
280
|
+
}
|
281
|
+
break;
|
282
|
+
case '*':
|
283
|
+
if (i < 0) {
|
284
|
+
resp_on_null(parser);
|
285
|
+
} else {
|
286
|
+
if (resp_on_start_array(parser, i)) {
|
287
|
+
pos = eol + 1;
|
288
|
+
goto finish;
|
289
|
+
}
|
290
|
+
parser->obj_countdown += i;
|
291
|
+
}
|
292
|
+
--parser->obj_countdown;
|
293
|
+
break;
|
294
|
+
}
|
295
|
+
} break;
|
296
|
+
default:
|
297
|
+
if (!parser->obj_countdown && !parser->expecting) {
|
298
|
+
/* possible (probable) inline command... for server authoring. */
|
299
|
+
/* Not Supported, PRs are welcome. */
|
300
|
+
resp_on_parser_error(parser);
|
301
|
+
return (size_t)((uintptr_t)stop - (uintptr_t)pos);
|
302
|
+
} else {
|
303
|
+
resp_on_parser_error(parser);
|
304
|
+
return (size_t)((uintptr_t)stop - (uintptr_t)pos);
|
305
|
+
}
|
306
|
+
}
|
307
|
+
pos = eol + 1;
|
308
|
+
if (parser->obj_countdown <= 0 && !parser->expecting) {
|
309
|
+
parser->obj_countdown = 1;
|
310
|
+
resp_on_message(parser);
|
311
|
+
}
|
312
|
+
}
|
313
|
+
finish:
|
314
|
+
return (size_t)((uintptr_t)stop - (uintptr_t)pos);
|
315
|
+
}
|
316
|
+
|
317
|
+
#endif /* H_RESP_PARSER_H */
|