Passing tests

event_stream
Ryan Dahl 16 years ago
parent 0642366f0e
commit 3ac0ebdee5

@ -166,52 +166,55 @@ static const uint32_t usual[] = {
}; };
enum state enum state
{ s_start_req = 1 { s_start_res = 1
, s_start_res , s_res_H
, s_res_HT
, s_method_G , s_res_HTT
, s_method_GE , s_res_HTTP
, s_res_first_http_major
, s_method_P , s_res_http_major
, s_method_PU , s_res_first_http_minor
, s_method_PO , s_res_http_minor
, s_method_POS , s_res_first_status_code
, s_res_status_code
, s_method_H , s_res_status
, s_method_HE , s_res_line_almost_done
, s_method_HEA
, s_start_req
, s_method_D , s_req_method_G
, s_method_DE , s_req_method_GE
, s_method_DEL , s_req_method_P
, s_method_DELE , s_req_method_PU
, s_method_DELET , s_req_method_PO
, s_req_method_POS
, s_spaces_before_url , s_req_method_H
, s_req_method_HE
, s_schema , s_req_method_HEA
, s_schema_slash , s_req_method_D
, s_schema_slash_slash , s_req_method_DE
, s_host , s_req_method_DEL
, s_port , s_req_method_DELE
, s_req_method_DELET
, s_path , s_req_spaces_before_url
, s_query_string_start , s_req_schema
, s_query_string , s_req_schema_slash
, s_fragment_start , s_req_schema_slash_slash
, s_fragment , s_req_host
, s_req_port
, s_http_start , s_req_path
, s_http_H , s_req_query_string_start
, s_http_HT , s_req_query_string
, s_http_HTT , s_req_fragment_start
, s_http_HTTP , s_req_fragment
, s_req_http_start
, s_first_major_digit , s_req_http_H
, s_major_digit , s_req_http_HT
, s_first_minor_digit , s_req_http_HTT
, s_minor_digit , s_req_http_HTTP
, s_req_first_major_digit
, s_req_major_digit
, s_req_first_minor_digit
, s_req_minor_digit
, s_req_line_almost_done , s_req_line_almost_done
, s_header_field_start , s_header_field_start
@ -298,6 +301,153 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
for (p=data, pe=data+len; p != pe; p++) { for (p=data, pe=data+len; p != pe; p++) {
ch = *p; ch = *p;
switch (state) { switch (state) {
case s_start_res:
{
parser->flags = 0;
parser->content_length = -1;
CALLBACK2(message_begin);
switch (ch) {
case 'H':
state = s_res_H;
break;
case CR:
case LF:
break;
default:
return ERROR;
}
break;
}
case s_res_H:
if (ch != 'T') return ERROR;
state = s_res_HT;
break;
case s_res_HT:
if (ch != 'T') return ERROR;
state = s_res_HTT;
break;
case s_res_HTT:
if (ch != 'P') return ERROR;
state = s_res_HTTP;
break;
case s_res_HTTP:
if (ch != '/') return ERROR;
state = s_res_first_http_major;
break;
case s_res_first_http_major:
if (ch < '1' || ch > '9') return ERROR;
parser->http_major = ch - '0';
state = s_res_http_major;
break;
/* major HTTP version or dot */
case s_res_http_major:
{
if (ch == '.') {
state = s_res_first_http_minor;
break;
}
if (ch < '0' || ch > '9') return ERROR;
parser->http_major *= 10;
parser->http_major += ch - '0';
if (parser->http_major > 999) return ERROR;
break;
}
/* first digit of minor HTTP version */
case s_res_first_http_minor:
if (ch < '0' || ch > '9') return ERROR;
parser->http_minor = ch - '0';
state = s_res_http_minor;
break;
/* minor HTTP version or end of request line */
case s_res_http_minor:
{
if (ch == ' ') {
state = s_res_first_status_code;
break;
}
if (ch < '0' || ch > '9') return ERROR;
parser->http_minor *= 10;
parser->http_minor += ch - '0';
if (parser->http_minor > 999) return ERROR;
break;
}
case s_res_first_status_code:
{
if (ch < '0' || ch > '9') {
if (ch == ' ') {
break;
}
return ERROR;
}
parser->status_code = ch - '0';
state = s_res_status_code;
break;
}
case s_res_status_code:
{
if (ch < '0' || ch > '9') {
switch (ch) {
case ' ':
state = s_res_status;
break;
case CR:
state = s_res_line_almost_done;
break;
case LF:
state = s_header_field_start;
break;
default:
return ERROR;
}
break;
}
parser->status_code *= 10;
parser->status_code += ch - '0';
if (parser->status_code > 999) return ERROR;
break;
}
case s_res_status:
/* the human readable status. e.g. "NOT FOUND"
* we are not humans so just ignore this */
if (ch == CR) {
state = s_res_line_almost_done;
break;
}
if (ch == LF) {
state = s_header_field_start;
break;
}
break;
case s_res_line_almost_done:
if (ch != LF) return ERROR;
state = s_header_field_start;
break;
case s_start_req: case s_start_req:
{ {
parser->flags = 0; parser->flags = 0;
@ -308,22 +458,22 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
switch (ch) { switch (ch) {
/* GET */ /* GET */
case 'G': case 'G':
state = s_method_G; state = s_req_method_G;
break; break;
/* POST, PUT */ /* POST, PUT */
case 'P': case 'P':
state = s_method_P; state = s_req_method_P;
break; break;
/* HEAD */ /* HEAD */
case 'H': case 'H':
state = s_method_H; state = s_req_method_H;
break; break;
/* DELETE */ /* DELETE */
case 'D': case 'D':
state = s_method_D; state = s_req_method_D;
break; break;
case CR: case CR:
@ -338,45 +488,45 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
/* GET */ /* GET */
case s_method_G: case s_req_method_G:
if (ch != 'E') return ERROR; if (ch != 'E') return ERROR;
state = s_method_GE; state = s_req_method_GE;
break; break;
case s_method_GE: case s_req_method_GE:
if (ch != 'T') return ERROR; if (ch != 'T') return ERROR;
parser->method = HTTP_GET; parser->method = HTTP_GET;
state = s_spaces_before_url; state = s_req_spaces_before_url;
break; break;
/* HEAD */ /* HEAD */
case s_method_H: case s_req_method_H:
if (ch != 'E') return ERROR; if (ch != 'E') return ERROR;
state = s_method_HE; state = s_req_method_HE;
break; break;
case s_method_HE: case s_req_method_HE:
if (ch != 'A') return ERROR; if (ch != 'A') return ERROR;
state = s_method_HEA; state = s_req_method_HEA;
break; break;
case s_method_HEA: case s_req_method_HEA:
if (ch != 'D') return ERROR; if (ch != 'D') return ERROR;
parser->method = HTTP_HEAD; parser->method = HTTP_HEAD;
state = s_spaces_before_url; state = s_req_spaces_before_url;
break; break;
/* POST, PUT */ /* POST, PUT */
case s_method_P: case s_req_method_P:
switch (ch) { switch (ch) {
case 'O': case 'O':
state = s_method_PO; state = s_req_method_PO;
break; break;
case 'U': case 'U':
state = s_method_PU; state = s_req_method_PU;
break; break;
default: default:
@ -386,62 +536,62 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
/* PUT */ /* PUT */
case s_method_PU: case s_req_method_PU:
if (ch != 'T') return ERROR; if (ch != 'T') return ERROR;
parser->method = HTTP_PUT; parser->method = HTTP_PUT;
state = s_spaces_before_url; state = s_req_spaces_before_url;
break; break;
/* POST */ /* POST */
case s_method_PO: case s_req_method_PO:
if (ch != 'S') return ERROR; if (ch != 'S') return ERROR;
state = s_method_POS; state = s_req_method_POS;
break; break;
case s_method_POS: case s_req_method_POS:
if (ch != 'T') return ERROR; if (ch != 'T') return ERROR;
parser->method = HTTP_POST; parser->method = HTTP_POST;
state = s_spaces_before_url; state = s_req_spaces_before_url;
break; break;
/* DELETE */ /* DELETE */
case s_method_D: case s_req_method_D:
if (ch != 'E') return ERROR; if (ch != 'E') return ERROR;
state = s_method_DE; state = s_req_method_DE;
break; break;
case s_method_DE: case s_req_method_DE:
if (ch != 'L') return ERROR; if (ch != 'L') return ERROR;
state = s_method_DEL; state = s_req_method_DEL;
break; break;
case s_method_DEL: case s_req_method_DEL:
if (ch != 'E') return ERROR; if (ch != 'E') return ERROR;
state = s_method_DELE; state = s_req_method_DELE;
break; break;
case s_method_DELE: case s_req_method_DELE:
if (ch != 'T') return ERROR; if (ch != 'T') return ERROR;
state = s_method_DELET; state = s_req_method_DELET;
break; break;
case s_method_DELET: case s_req_method_DELET:
if (ch != 'E') return ERROR; if (ch != 'E') return ERROR;
parser->method = HTTP_DELETE; parser->method = HTTP_DELETE;
state = s_spaces_before_url; state = s_req_spaces_before_url;
break; break;
case s_spaces_before_url: case s_req_spaces_before_url:
{ {
if (ch == ' ') break; if (ch == ' ') break;
if (ch == '/') { if (ch == '/') {
MARK(url); MARK(url);
MARK(path); MARK(path);
state = s_path; state = s_req_path;
break; break;
} }
@ -449,49 +599,49 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
if (c >= 'a' && c <= 'z') { if (c >= 'a' && c <= 'z') {
MARK(url); MARK(url);
state = s_schema; state = s_req_schema;
break; break;
} }
return ERROR; return ERROR;
} }
case s_schema: case s_req_schema:
{ {
c = LOWER(ch); c = LOWER(ch);
if (c >= 'a' && c <= 'z') break; if (c >= 'a' && c <= 'z') break;
if (ch == ':') { if (ch == ':') {
state = s_schema_slash; state = s_req_schema_slash;
break; break;
} }
return ERROR; return ERROR;
} }
case s_schema_slash: case s_req_schema_slash:
if (ch != '/') return ERROR; if (ch != '/') return ERROR;
state = s_schema_slash_slash; state = s_req_schema_slash_slash;
break; break;
case s_schema_slash_slash: case s_req_schema_slash_slash:
if (ch != '/') return ERROR; if (ch != '/') return ERROR;
state = s_host; state = s_req_host;
break; break;
case s_host: case s_req_host:
{ {
c = LOWER(ch); c = LOWER(ch);
if (c >= 'a' && c <= 'z') break; if (c >= 'a' && c <= 'z') break;
if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') break; if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') break;
switch (ch) { switch (ch) {
case ':': case ':':
state = s_port; state = s_req_port;
break; break;
case '/': case '/':
MARK(path); MARK(path);
state = s_path; state = s_req_path;
break; break;
case ' ': case ' ':
/* The request line looks like: /* The request line looks like:
@ -499,7 +649,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
* That is, there is no path. * That is, there is no path.
*/ */
CALLBACK(url); CALLBACK(url);
state = s_http_start; state = s_req_http_start;
break; break;
default: default:
return ERROR; return ERROR;
@ -507,13 +657,13 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
break; break;
} }
case s_port: case s_req_port:
{ {
if (ch >= '0' && ch <= '9') break; if (ch >= '0' && ch <= '9') break;
switch (ch) { switch (ch) {
case '/': case '/':
MARK(path); MARK(path);
state = s_path; state = s_req_path;
break; break;
case ' ': case ' ':
/* The request line looks like: /* The request line looks like:
@ -521,7 +671,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
* That is, there is no path. * That is, there is no path.
*/ */
CALLBACK(url); CALLBACK(url);
state = s_http_start; state = s_req_http_start;
break; break;
default: default:
return ERROR; return ERROR;
@ -529,7 +679,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
break; break;
} }
case s_path: case s_req_path:
{ {
if (usual[ch >> 5] & (1 << (ch & 0x1f))) break; if (usual[ch >> 5] & (1 << (ch & 0x1f))) break;
@ -537,7 +687,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
case ' ': case ' ':
CALLBACK(url); CALLBACK(url);
CALLBACK(path); CALLBACK(path);
state = s_http_start; state = s_req_http_start;
break; break;
case CR: case CR:
CALLBACK(url); CALLBACK(url);
@ -553,11 +703,11 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
break; break;
case '?': case '?':
CALLBACK(path); CALLBACK(path);
state = s_query_string_start; state = s_req_query_string_start;
break; break;
case '#': case '#':
CALLBACK(path); CALLBACK(path);
state = s_fragment_start; state = s_req_fragment_start;
break; break;
default: default:
return ERROR; return ERROR;
@ -565,11 +715,11 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
break; break;
} }
case s_query_string_start: case s_req_query_string_start:
{ {
if (usual[ch >> 5] & (1 << (ch & 0x1f))) { if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
MARK(query_string); MARK(query_string);
state = s_query_string; state = s_req_query_string;
break; break;
} }
@ -578,7 +728,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
break; // XXX ignore extra '?' ... is this right? break; // XXX ignore extra '?' ... is this right?
case ' ': case ' ':
CALLBACK(url); CALLBACK(url);
state = s_http_start; state = s_req_http_start;
break; break;
case CR: case CR:
CALLBACK(url); CALLBACK(url);
@ -591,7 +741,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
state = s_header_field_start; state = s_header_field_start;
break; break;
case '#': case '#':
state = s_fragment_start; state = s_req_fragment_start;
break; break;
default: default:
return ERROR; return ERROR;
@ -599,7 +749,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
break; break;
} }
case s_query_string: case s_req_query_string:
{ {
if (usual[ch >> 5] & (1 << (ch & 0x1f))) break; if (usual[ch >> 5] & (1 << (ch & 0x1f))) break;
@ -607,7 +757,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
case ' ': case ' ':
CALLBACK(url); CALLBACK(url);
CALLBACK(query_string); CALLBACK(query_string);
state = s_http_start; state = s_req_http_start;
break; break;
case CR: case CR:
CALLBACK(url); CALLBACK(url);
@ -623,7 +773,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
break; break;
case '#': case '#':
CALLBACK(query_string); CALLBACK(query_string);
state = s_fragment_start; state = s_req_fragment_start;
break; break;
default: default:
return ERROR; return ERROR;
@ -631,18 +781,18 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
break; break;
} }
case s_fragment_start: case s_req_fragment_start:
{ {
if (usual[ch >> 5] & (1 << (ch & 0x1f))) { if (usual[ch >> 5] & (1 << (ch & 0x1f))) {
MARK(fragment); MARK(fragment);
state = s_fragment; state = s_req_fragment;
break; break;
} }
switch (ch) { switch (ch) {
case ' ': case ' ':
CALLBACK(url); CALLBACK(url);
state = s_http_start; state = s_req_http_start;
break; break;
case CR: case CR:
CALLBACK(url); CALLBACK(url);
@ -656,7 +806,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
break; break;
case '?': case '?':
MARK(fragment); MARK(fragment);
state = s_fragment; state = s_req_fragment;
break; break;
case '#': case '#':
break; break;
@ -666,7 +816,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
break; break;
} }
case s_fragment: case s_req_fragment:
{ {
if (usual[ch >> 5] & (1 << (ch & 0x1f))) break; if (usual[ch >> 5] & (1 << (ch & 0x1f))) break;
@ -674,7 +824,7 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
case ' ': case ' ':
CALLBACK(url); CALLBACK(url);
CALLBACK(fragment); CALLBACK(fragment);
state = s_http_start; state = s_req_http_start;
break; break;
case CR: case CR:
CALLBACK(url); CALLBACK(url);
@ -697,10 +847,10 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
break; break;
} }
case s_http_start: case s_req_http_start:
switch (ch) { switch (ch) {
case 'H': case 'H':
state = s_http_H; state = s_req_http_H;
break; break;
case ' ': case ' ':
break; break;
@ -709,38 +859,38 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
} }
break; break;
case s_http_H: case s_req_http_H:
if (ch != 'T') return ERROR; if (ch != 'T') return ERROR;
state = s_http_HT; state = s_req_http_HT;
break; break;
case s_http_HT: case s_req_http_HT:
if (ch != 'T') return ERROR; if (ch != 'T') return ERROR;
state = s_http_HTT; state = s_req_http_HTT;
break; break;
case s_http_HTT: case s_req_http_HTT:
if (ch != 'P') return ERROR; if (ch != 'P') return ERROR;
state = s_http_HTTP; state = s_req_http_HTTP;
break; break;
case s_http_HTTP: case s_req_http_HTTP:
if (ch != '/') return ERROR; if (ch != '/') return ERROR;
state = s_first_major_digit; state = s_req_first_major_digit;
break; break;
/* first digit of major HTTP version */ /* first digit of major HTTP version */
case s_first_major_digit: case s_req_first_major_digit:
if (ch < '1' || ch > '9') return ERROR; if (ch < '1' || ch > '9') return ERROR;
parser->http_major = ch - '0'; parser->http_major = ch - '0';
state = s_major_digit; state = s_req_major_digit;
break; break;
/* major HTTP version or dot */ /* major HTTP version or dot */
case s_major_digit: case s_req_major_digit:
{ {
if (ch == '.') { if (ch == '.') {
state = s_first_minor_digit; state = s_req_first_minor_digit;
break; break;
} }
@ -754,14 +904,14 @@ size_t parse (http_parser *parser, const char *data, size_t len, int start_state
} }
/* first digit of minor HTTP version */ /* first digit of minor HTTP version */
case s_first_minor_digit: case s_req_first_minor_digit:
if (ch < '0' || ch > '9') return ERROR; if (ch < '0' || ch > '9') return ERROR;
parser->http_minor = ch - '0'; parser->http_minor = ch - '0';
state = s_minor_digit; state = s_req_minor_digit;
break; break;
/* minor HTTP version or end of request line */ /* minor HTTP version or end of request line */
case s_minor_digit: case s_req_minor_digit:
{ {
if (ch == CR) { if (ch == CR) {
state = s_req_line_almost_done; state = s_req_line_almost_done;

@ -659,8 +659,11 @@ message_eq (int index, const struct message *expected)
int i; int i;
struct message *m = &messages[index]; struct message *m = &messages[index];
MESSAGE_CHECK_NUM_EQ(expected, m, method); if (expected->type == REQUEST) {
MESSAGE_CHECK_NUM_EQ(expected, m, status_code); MESSAGE_CHECK_NUM_EQ(expected, m, method);
} else {
MESSAGE_CHECK_NUM_EQ(expected, m, status_code);
}
assert(m->message_begin_cb_called); assert(m->message_begin_cb_called);
assert(m->headers_complete_cb_called); assert(m->headers_complete_cb_called);

Loading…
Cancel
Save