提交 11aed420 编写于 作者: S Shengliang Guan

TD-1311

上级 a1527b62
#ifndef _ehttp_parser_fc7f9ac9_52da_4ee3_b556_deb2e1c3866e #ifndef HTTP_PARSER_H
#define _ehttp_parser_fc7f9ac9_52da_4ee3_b556_deb2e1c3866e #define HTTP_PARSER_H
#include <stddef.h> #include "ehttp_util_string.h"
#include "ehttp_gzip.h"
typedef struct ehttp_parser_s ehttp_parser_t; struct HttpContext;
typedef struct ehttp_parser_callbacks_s ehttp_parser_callbacks_t;
typedef struct ehttp_parser_conf_s ehttp_parser_conf_t;
typedef struct ehttp_status_code_s ehttp_status_code_t;
struct ehttp_parser_callbacks_s { typedef enum HTTP_PARSER_STATE {
HTTP_PARSER_BEGIN,
HTTP_PARSER_REQUEST_OR_RESPONSE,
HTTP_PARSER_METHOD,
HTTP_PARSER_TARGET,
HTTP_PARSER_HTTP_VERSION,
HTTP_PARSER_SP,
HTTP_PARSER_STATUS_CODE,
HTTP_PARSER_REASON_PHRASE,
HTTP_PARSER_CRLF,
HTTP_PARSER_HEADER,
HTTP_PARSER_HEADER_KEY,
HTTP_PARSER_HEADER_VAL,
HTTP_PARSER_CHUNK_SIZE,
HTTP_PARSER_CHUNK,
HTTP_PARSER_END,
HTTP_PARSER_ERROR,
} HTTP_PARSER_STATE;
typedef struct HttpParserStatusObj {
int32_t status_code;
const char *status_desc;
} HttpParserStatusObj;
typedef struct HttpParserCallbackObj {
void (*on_request_line)(void *arg, const char *method, const char *target, const char *version, const char *target_raw); void (*on_request_line)(void *arg, const char *method, const char *target, const char *version, const char *target_raw);
void (*on_status_line)(void *arg, const char *version, int status_code, const char *reason_phrase); void (*on_status_line)(void *arg, const char *version, int status_code, const char *reason_phrase);
void (*on_header_field)(void *arg, const char *key, const char *val); void (*on_header_field)(void *arg, const char *key, const char *val);
void (*on_body)(void *arg, const char *chunk, size_t len); void (*on_body)(void *arg, const char *chunk, size_t len);
void (*on_end)(void *arg); void (*on_end)(void *arg);
void (*on_error)(void *arg, int status_code); void (*on_error)(void *arg, int status_code);
}; } HttpParserCallbackObj;
typedef struct HttpParserConfObj {
size_t flush_block_size; // <=0: immediately
} HttpParserConfObj;
struct ehttp_parser_conf_s { typedef struct HttpParseKvObj {
size_t flush_block_size; // <=0: immediately char *key;
}; char *val;
} HttpParseKvObj;
ehttp_parser_t* ehttp_parser_create(ehttp_parser_callbacks_t callbacks, ehttp_parser_conf_t conf, void *arg); typedef struct HttpParserObj {
void ehttp_parser_destroy(ehttp_parser_t *parser); HttpParserCallbackObj callbacks;
int ehttp_parser_parse(ehttp_parser_t *parser, const char *buf, size_t len); HttpParserConfObj conf;
int ehttp_parser_parse_string(ehttp_parser_t *parser, const char *str); void * arg;
int ehttp_parser_parse_char(ehttp_parser_t *parser, const char c); char * method;
int ehttp_parser_parse_end(ehttp_parser_t *parser); char * target;
char * target_raw;
char * version;
int http_10 : 2;
int http_11 : 2;
int accept_encoding_gzip : 2;
int accept_encoding_chunked : 2;
int transfer_gzip : 2;
int transfer_chunked : 2;
int content_length_specified : 2;
int content_chunked : 2;
int status_code;
char * reason_phrase;
char * key;
char * val;
HttpParseKvObj * kvs;
size_t kvs_count;
char * auth_basic;
char * auth_taosd;
size_t content_length;
size_t chunk_size;
size_t received_chunk_size;
size_t received_size;
ehttp_gzip_t * gzip;
HttpUtilString str;
HTTP_PARSER_STATE *stacks;
size_t stacks_count;
} HttpParserObj;
HttpParserObj* httpParserCreate(HttpParserCallbackObj callbacks, HttpParserConfObj conf, void *arg);
void httpParserDestroy(HttpParserObj *parser);
int32_t httpParserBuf(struct HttpContext *pContext, HttpParserObj *parser, const char *buf, int32_t len);
char* ehttp_parser_urldecode(const char *enc); char* ehttp_parser_urldecode(const char *enc);
const char* ehttp_status_code_get_desc(const int status_code); const char* ehttp_status_code_get_desc(const int status_code);
#endif // _ehttp_parser_fc7f9ac9_52da_4ee3_b556_deb2e1c3866e #endif
#ifndef _ehttp_util_string_h_99dacde5_2e7d_4662_97d6_04611fde683b_ #ifndef HTTP_UTIL_STRING
#define _ehttp_util_string_h_99dacde5_2e7d_4662_97d6_04611fde683b_ #define HTTP_UTIL_STRING
#include <stddef.h> typedef struct HttpUtilString {
char * str;
size_t len;
} HttpUtilString;
typedef struct ehttp_util_string_s ehttp_util_string_t; void httpParserCleanupString(HttpUtilString *str);
int32_t httpParserAppendString(HttpUtilString *str, const char *s, int32_t len);
struct ehttp_util_string_s { void httpParserClearString(HttpUtilString *str);
char *str;
size_t len;
};
void ehttp_util_string_cleanup(ehttp_util_string_t *str);
int ehttp_util_string_append(ehttp_util_string_t *str, const char *s, size_t len);
void ehttp_util_string_clear(ehttp_util_string_t *str);
#endif // _ehttp_util_string_h_99dacde5_2e7d_4662_97d6_04611fde683b_
#endif
...@@ -179,10 +179,9 @@ typedef struct { ...@@ -179,10 +179,9 @@ typedef struct {
HttpBuf data; // body content HttpBuf data; // body content
HttpBuf token; // auth token HttpBuf token; // auth token
HttpDecodeMethod *pMethod; HttpDecodeMethod *pMethod;
HttpParserObj * parser;
ehttp_parser_t *parser; int8_t inited;
int inited:2; int8_t failed;
int failed:4;
} HttpParser; } HttpParser;
typedef struct HttpContext { typedef struct HttpContext {
......
#include "os.h"
#include "httpLog.h"
#include "httpContext.h"
#include "ehttp_util_string.h"
#include "ehttp_parser.h" #include "ehttp_parser.h"
#include "ehttp_gzip.h" #include "ehttp_gzip.h"
#include "ehttp_util_string.h" #include "ehttp_util_string.h"
#include "elog.h" #include "elog.h"
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
struct ehttp_status_code_s {
int status_code;
const char *status_desc;
};
static ehttp_status_code_t status_codes[] = { static HttpParserStatusObj status_codes[] = {
{100, "Continue"}, {100, "Continue"},
{101, "Switching Protocol"}, {101, "Switching Protocol"},
{102, "Processing (WebDAV)"}, {102, "Processing (WebDAV)"},
...@@ -81,7 +82,7 @@ static ehttp_status_code_t status_codes[] = { ...@@ -81,7 +82,7 @@ static ehttp_status_code_t status_codes[] = {
}; };
const char* ehttp_status_code_get_desc(const int status_code) { const char* ehttp_status_code_get_desc(const int status_code) {
ehttp_status_code_t *p = status_codes; HttpParserStatusObj *p = status_codes;
while (p->status_code!=0) { while (p->status_code!=0) {
if (p->status_code==status_code) return p->status_desc; if (p->status_code==status_code) return p->status_desc;
++p; ++p;
...@@ -89,74 +90,6 @@ const char* ehttp_status_code_get_desc(const int status_code) { ...@@ -89,74 +90,6 @@ const char* ehttp_status_code_get_desc(const int status_code) {
return "Unknow status code"; return "Unknow status code";
} }
typedef enum HTTP_PARSER_STATE {
HTTP_PARSER_BEGIN,
HTTP_PARSER_REQUEST_OR_RESPONSE,
HTTP_PARSER_METHOD,
HTTP_PARSER_TARGET,
HTTP_PARSER_HTTP_VERSION,
HTTP_PARSER_SP,
HTTP_PARSER_STATUS_CODE,
HTTP_PARSER_REASON_PHRASE,
HTTP_PARSER_CRLF,
HTTP_PARSER_HEADER,
HTTP_PARSER_HEADER_KEY,
HTTP_PARSER_HEADER_VAL,
HTTP_PARSER_CHUNK_SIZE,
HTTP_PARSER_CHUNK,
HTTP_PARSER_END,
HTTP_PARSER_ERROR,
} HTTP_PARSER_STATE;
typedef struct ehttp_parser_kv_s ehttp_parser_kv_t;
struct ehttp_parser_kv_s {
char *key;
char *val;
};
struct ehttp_parser_s {
ehttp_parser_callbacks_t callbacks;
void *arg;
ehttp_parser_conf_t conf;
char *method;
char *target;
char *target_raw;
char *version;
int http_10:2;
int http_11:2;
int accept_encoding_gzip:2;
int accept_encoding_chunked:2;
int transfer_gzip:2;
int transfer_chunked:2;
int content_length_specified:2;
int content_chunked:2;
int status_code;
char *reason_phrase;
char *key;
char *val;
ehttp_parser_kv_t *kvs;
size_t kvs_count;
char *auth_basic;
size_t content_length;
size_t chunk_size;
size_t received_chunk_size;
size_t received_size;
ehttp_gzip_t *gzip;
ehttp_util_string_t str;
HTTP_PARSER_STATE *stacks;
size_t stacks_count;
};
static void dummy_on_request_line(void *arg, const char *method, const char *target, const char *version, const char *target_raw) { static void dummy_on_request_line(void *arg, const char *method, const char *target, const char *version, const char *target_raw) {
} }
...@@ -175,15 +108,14 @@ static void dummy_on_end(void *arg) { ...@@ -175,15 +108,14 @@ static void dummy_on_end(void *arg) {
static void dummy_on_error(void *arg, int status_code) { static void dummy_on_error(void *arg, int status_code) {
} }
static HTTP_PARSER_STATE httpParserTop(HttpParserObj *parser) {
ASSERT(parser->stacks_count >= 1);
ASSERT(parser->stacks);
static HTTP_PARSER_STATE ehttp_parser_top(ehttp_parser_t *parser) { return parser->stacks[parser->stacks_count - 1];
EQ_ASSERT(parser->stacks_count >= 1);
EQ_ASSERT(parser->stacks);
return parser->stacks[parser->stacks_count-1];
} }
static int ehttp_parser_push(ehttp_parser_t *parser, HTTP_PARSER_STATE state) { static int httpParserPush(HttpParserObj *parser, HTTP_PARSER_STATE state) {
size_t n = parser->stacks_count + 1; size_t n = parser->stacks_count + 1;
// HTTP_PARSER_STATE *stacks = (HTTP_PARSER_STATE*)reallocarray(parser->stacks, n, sizeof(*stacks)); // HTTP_PARSER_STATE *stacks = (HTTP_PARSER_STATE*)reallocarray(parser->stacks, n, sizeof(*stacks));
HTTP_PARSER_STATE *stacks = (HTTP_PARSER_STATE*)realloc(parser->stacks, n * sizeof(*stacks)); HTTP_PARSER_STATE *stacks = (HTTP_PARSER_STATE*)realloc(parser->stacks, n * sizeof(*stacks));
...@@ -196,15 +128,15 @@ static int ehttp_parser_push(ehttp_parser_t *parser, HTTP_PARSER_STATE state) { ...@@ -196,15 +128,15 @@ static int ehttp_parser_push(ehttp_parser_t *parser, HTTP_PARSER_STATE state) {
return 0; return 0;
} }
static int ehttp_parser_pop(ehttp_parser_t *parser) { static int httpParserPop(HttpParserObj *parser) {
if (parser->stacks_count <= 0) return -1; if (parser->stacks_count <= 0) return -1;
--parser->stacks_count; --parser->stacks_count;
return 0; return 0;
} }
ehttp_parser_t *ehttp_parser_create(ehttp_parser_callbacks_t callbacks, ehttp_parser_conf_t conf, void *arg) { HttpParserObj *httpParserCreate(HttpParserCallbackObj callbacks, HttpParserConfObj conf, void *arg) {
ehttp_parser_t *parser = (ehttp_parser_t*)calloc(1, sizeof(*parser)); HttpParserObj *parser = (HttpParserObj*)calloc(1, sizeof(*parser));
if (!parser) return NULL; if (!parser) return NULL;
parser->callbacks = callbacks; parser->callbacks = callbacks;
...@@ -230,16 +162,16 @@ ehttp_parser_t *ehttp_parser_create(ehttp_parser_callbacks_t callbacks, ehttp_pa ...@@ -230,16 +162,16 @@ ehttp_parser_t *ehttp_parser_create(ehttp_parser_callbacks_t callbacks, ehttp_pa
parser->callbacks.on_error = dummy_on_error; parser->callbacks.on_error = dummy_on_error;
} }
ehttp_parser_push(parser, HTTP_PARSER_BEGIN); httpParserPush(parser, HTTP_PARSER_BEGIN);
return parser; return parser;
} }
static void ehttp_parser_kvs_destroy(ehttp_parser_t *parser) { static void ehttp_parser_kvs_destroy(HttpParserObj *parser) {
if (!parser->kvs) return; if (!parser->kvs) return;
for (size_t i=0; i<parser->kvs_count; ++i) { for (size_t i=0; i<parser->kvs_count; ++i) {
ehttp_parser_kv_t *p = &parser->kvs[i]; HttpParseKvObj *p = &parser->kvs[i];
free(p->key); p->key = NULL; free(p->key); p->key = NULL;
free(p->val); p->val = NULL; free(p->val); p->val = NULL;
} }
...@@ -251,7 +183,7 @@ static void ehttp_parser_kvs_destroy(ehttp_parser_t *parser) { ...@@ -251,7 +183,7 @@ static void ehttp_parser_kvs_destroy(ehttp_parser_t *parser) {
parser->auth_basic = NULL; parser->auth_basic = NULL;
} }
void ehttp_parser_destroy(ehttp_parser_t *parser) { void httpParserDestroy(HttpParserObj *parser) {
if (!parser) return; if (!parser) return;
free(parser->method); parser->method = NULL; free(parser->method); parser->method = NULL;
...@@ -268,7 +200,7 @@ void ehttp_parser_destroy(ehttp_parser_t *parser) { ...@@ -268,7 +200,7 @@ void ehttp_parser_destroy(ehttp_parser_t *parser) {
ehttp_parser_kvs_destroy(parser); ehttp_parser_kvs_destroy(parser);
ehttp_util_string_cleanup(&parser->str); httpParserCleanupString(&parser->str);
if (parser->gzip) { if (parser->gzip) {
ehttp_gzip_destroy(parser->gzip); ehttp_gzip_destroy(parser->gzip);
parser->gzip = NULL; parser->gzip = NULL;
...@@ -281,52 +213,52 @@ void ehttp_parser_destroy(ehttp_parser_t *parser) { ...@@ -281,52 +213,52 @@ void ehttp_parser_destroy(ehttp_parser_t *parser) {
char *ehttp_parser_urldecode(const char *enc) { char *ehttp_parser_urldecode(const char *enc) {
int ok = 1; int ok = 1;
ehttp_util_string_t str = {0}; HttpUtilString str = {0};
while (*enc) { while (*enc) {
char *p = strchr(enc, '%'); char *p = strchr(enc, '%');
if (!p) break; if (!p) break;
int hex, cnt; int hex, cnt;
int n = sscanf(p+1, "%2x%n", &hex, &cnt); int n = sscanf(p+1, "%2x%n", &hex, &cnt);
if (n!=1 && cnt !=2) { ok = 0; break; } if (n!=1 && cnt !=2) { ok = 0; break; }
if (ehttp_util_string_append(&str, enc, p-enc)) { ok = 0; break; } if (httpParserAppendString(&str, enc, p-enc)) { ok = 0; break; }
char c = (char)hex; char c = (char)hex;
if (ehttp_util_string_append(&str, &c, 1)) { ok = 0; break; } if (httpParserAppendString(&str, &c, 1)) { ok = 0; break; }
enc = p+3; enc = p+3;
} }
char *dec = NULL; char *dec = NULL;
if (ok && *enc) { if (ok && *enc) {
if (ehttp_util_string_append(&str, enc, strlen(enc))) { ok = 0; } if (httpParserAppendString(&str, enc, strlen(enc))) { ok = 0; }
} }
if (ok) { if (ok) {
dec = str.str; dec = str.str;
str.str = NULL; str.str = NULL;
} }
ehttp_util_string_cleanup(&str); httpParserCleanupString(&str);
return dec; return dec;
} }
static void on_data(ehttp_gzip_t *gzip, void *arg, const char *buf, size_t len) { static void on_data(ehttp_gzip_t *gzip, void *arg, const char *buf, size_t len) {
ehttp_parser_t *parser = (ehttp_parser_t*)arg; HttpParserObj *parser = (HttpParserObj*)arg;
parser->callbacks.on_body(parser->arg, buf, len); parser->callbacks.on_body(parser->arg, buf, len);
} }
static int ehttp_parser_check_field(ehttp_parser_t *parser, const char *key, const char *val) { static int32_t httpParserCheckField(HttpContext *pContext, HttpParserObj *parser, const char *key, const char *val) {
int ok = 0; int32_t ok = 0;
do { do {
if (0==strcasecmp(key, "Content-Length")) { if (0 == strcasecmp(key, "Content-Length")) {
size_t len = 0; int32_t len = 0;
int bytes = 0; int32_t bytes = 0;
int n = sscanf(val, "%ld%n", &len, &bytes); int32_t n = sscanf(val, "%d%n", &len, &bytes);
if (n==1 && bytes==strlen(val)) { if (n == 1 && bytes == strlen(val)) {
parser->content_length = len; parser->content_length = len;
parser->chunk_size = len; parser->chunk_size = len;
parser->content_length_specified = 1; parser->content_length_specified = 1;
break; break;
} }
ok = -1; ok = -1;
break; break;
} }
if (0==strcasecmp(key, "Accept-Encoding")) { if (0 == strcasecmp(key, "Accept-Encoding")) {
if (strstr(val, "gzip")) { if (strstr(val, "gzip")) {
parser->accept_encoding_gzip = 1; parser->accept_encoding_gzip = 1;
} }
...@@ -335,13 +267,13 @@ static int ehttp_parser_check_field(ehttp_parser_t *parser, const char *key, con ...@@ -335,13 +267,13 @@ static int ehttp_parser_check_field(ehttp_parser_t *parser, const char *key, con
} }
break; break;
} }
if (0==strcasecmp(key, "Content-Encoding")) { if (0 == strcasecmp(key, "Content-Encoding")) {
if (0==strcmp(val, "gzip")) { if (0 == strcmp(val, "gzip")) {
parser->content_chunked = 1; parser->content_chunked = 1;
} }
break; break;
} }
if (0==strcasecmp(key, "Transfer-Encoding")) { if (0 == strcasecmp(key, "Transfer-Encoding")) {
if (strstr(val, "gzip")) { if (strstr(val, "gzip")) {
parser->transfer_gzip = 1; parser->transfer_gzip = 1;
ehttp_gzip_conf_t conf = {0}; ehttp_gzip_conf_t conf = {0};
...@@ -352,7 +284,7 @@ static int ehttp_parser_check_field(ehttp_parser_t *parser, const char *key, con ...@@ -352,7 +284,7 @@ static int ehttp_parser_check_field(ehttp_parser_t *parser, const char *key, con
parser->gzip = ehttp_gzip_create_decompressor(conf, callbacks, parser); parser->gzip = ehttp_gzip_create_decompressor(conf, callbacks, parser);
if (!parser->gzip) { if (!parser->gzip) {
E("failed to create gzip decompressor"); httpDebug("failed to create gzip decompressor");
ok = -1; ok = -1;
break; break;
} }
...@@ -365,24 +297,37 @@ static int ehttp_parser_check_field(ehttp_parser_t *parser, const char *key, con ...@@ -365,24 +297,37 @@ static int ehttp_parser_check_field(ehttp_parser_t *parser, const char *key, con
if (0==strcasecmp(key, "Authorization")) { if (0==strcasecmp(key, "Authorization")) {
char *t = NULL; char *t = NULL;
char *s = NULL; char *s = NULL;
int bytes = 0; int32_t bytes = 0;
int n = sscanf(val, "%ms %ms%n", &t, &s, &bytes); int32_t n = sscanf(val, "%ms %ms%n", &t, &s, &bytes);
if (n==2 && t && s && bytes==strlen(val) && strcmp(t, "Basic")) { if (n == 2 && t && s && bytes == strlen(val)) {
free(parser->auth_basic); if (strcmp(t, "Basic") == 0) {
parser->auth_basic = s; s = NULL; free(parser->auth_basic);
parser->auth_basic = s;
s = NULL;
} else if (n == 2 && t && s && strcmp(t, "Taosd") == 0) {
free(parser->auth_taosd);
parser->auth_taosd = s;
s = NULL;
} else {
httpError("context:%p, fd:%d, invalid auth, t:%s s:%s", pContext, pContext->fd, t, s);
ok = -1;
}
} else { } else {
httpError("context:%p, fd:%d, parse auth failed, t:%s s:%s", pContext, pContext->fd, t, s);
ok = -1; ok = -1;
} }
free(t); free(s);
free(t);
free(s);
break; break;
} }
} while (0); } while (0);
return ok; return ok;
} }
static int ehttp_parser_kvs_append_kv(ehttp_parser_t *parser, const char *key, const char *val) { static int httpParserAppendKv(HttpParserObj *parser, const char *key, const char *val) {
// ehttp_parser_kv_t *kvs = (ehttp_parser_kv_t*)reallocarray(parser->kvs, parser->kvs_count + 1, sizeof(*kvs)); // HttpParseKvObj *kvs = (HttpParseKvObj*)reallocarray(parser->kvs, parser->kvs_count + 1, sizeof(*kvs));
ehttp_parser_kv_t *kvs = (ehttp_parser_kv_t*)realloc(parser->kvs, (parser->kvs_count + 1) * sizeof(*kvs)); HttpParseKvObj *kvs = (HttpParseKvObj*)realloc(parser->kvs, (parser->kvs_count + 1) * sizeof(*kvs));
if (!kvs) return -1; if (!kvs) return -1;
parser->kvs = kvs; parser->kvs = kvs;
...@@ -403,69 +348,70 @@ static int ehttp_parser_kvs_append_kv(ehttp_parser_t *parser, const char *key, c ...@@ -403,69 +348,70 @@ static int ehttp_parser_kvs_append_kv(ehttp_parser_t *parser, const char *key, c
return -1; return -1;
} }
static int on_begin(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnBegin(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) {
int ok = 0; int32_t ok = 0;
do { do {
if (c=='G' || c=='P' || c=='H' || c=='D' || c=='C' || c=='O' || c=='T') { if (c == 'G' || c == 'P' || c == 'H' || c == 'D' || c == 'C' || c == 'O' || c == 'T') {
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
} }
ehttp_parser_pop(parser); httpParserPop(parser);
ehttp_parser_push(parser, HTTP_PARSER_REQUEST_OR_RESPONSE); httpParserPush(parser, HTTP_PARSER_REQUEST_OR_RESPONSE);
break; break;
} }
E("parser state: %d, unexpected char: [%c]%02x", state, c, c); httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 400); parser->callbacks.on_error(parser->arg, 400);
} while (0); } while (0);
return ok; return ok;
} }
static int on_request_or_response(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnRquestOrResponse(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) {
int ok = 0; int32_t ok = 0;
do { do {
if (parser->str.len==1) { if (parser->str.len == 1) {
if (c=='T' && parser->str.str[0]=='H') { if (c == 'T' && parser->str.str[0] == 'H') {
ehttp_parser_pop(parser); httpParserPop(parser);
ehttp_parser_push(parser, HTTP_PARSER_END); httpParserPush(parser, HTTP_PARSER_END);
ehttp_parser_push(parser, HTTP_PARSER_HEADER); httpParserPush(parser, HTTP_PARSER_HEADER);
ehttp_parser_push(parser, HTTP_PARSER_CRLF); httpParserPush(parser, HTTP_PARSER_CRLF);
ehttp_parser_push(parser, HTTP_PARSER_REASON_PHRASE); httpParserPush(parser, HTTP_PARSER_REASON_PHRASE);
ehttp_parser_push(parser, HTTP_PARSER_SP); httpParserPush(parser, HTTP_PARSER_SP);
ehttp_parser_push(parser, HTTP_PARSER_STATUS_CODE); httpParserPush(parser, HTTP_PARSER_STATUS_CODE);
ehttp_parser_push(parser, HTTP_PARSER_SP); httpParserPush(parser, HTTP_PARSER_SP);
ehttp_parser_push(parser, HTTP_PARSER_HTTP_VERSION); httpParserPush(parser, HTTP_PARSER_HTTP_VERSION);
*again = 1; *again = 1;
break; break;
} }
ehttp_parser_pop(parser); httpParserPop(parser);
ehttp_parser_push(parser, HTTP_PARSER_END); httpParserPush(parser, HTTP_PARSER_END);
ehttp_parser_push(parser, HTTP_PARSER_HEADER); httpParserPush(parser, HTTP_PARSER_HEADER);
ehttp_parser_push(parser, HTTP_PARSER_CRLF); httpParserPush(parser, HTTP_PARSER_CRLF);
ehttp_parser_push(parser, HTTP_PARSER_HTTP_VERSION); httpParserPush(parser, HTTP_PARSER_HTTP_VERSION);
ehttp_parser_push(parser, HTTP_PARSER_SP); httpParserPush(parser, HTTP_PARSER_SP);
ehttp_parser_push(parser, HTTP_PARSER_TARGET); httpParserPush(parser, HTTP_PARSER_TARGET);
ehttp_parser_push(parser, HTTP_PARSER_SP); httpParserPush(parser, HTTP_PARSER_SP);
ehttp_parser_push(parser, HTTP_PARSER_METHOD); httpParserPush(parser, HTTP_PARSER_METHOD);
*again = 1; *again = 1;
break; break;
} }
E("parser state: %d, unexpected char: [%c]%02x", state, c, c);
httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 400); parser->callbacks.on_error(parser->arg, 400);
} while (0); } while (0);
return ok; return ok;
} }
static int on_method(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnMethod(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) {
int ok = 0; int32_t ok = 0;
do { do {
if (isalnum(c) || strchr("!#$%&'*+-.^_`|~", c)) { if (isalnum(c) || strchr("!#$%&'*+-.^_`|~", c)) {
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpDebug("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
...@@ -474,24 +420,24 @@ static int on_method(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char ...@@ -474,24 +420,24 @@ static int on_method(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char
} }
parser->method = strdup(parser->str.str); parser->method = strdup(parser->str.str);
if (!parser->method) { if (!parser->method) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
} }
ehttp_util_string_clear(&parser->str); httpParserClearString(&parser->str);
ehttp_parser_pop(parser); httpParserPop(parser);
*again = 1; *again = 1;
} while (0); } while (0);
return ok; return ok;
} }
static int on_target(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnTarget(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) {
int ok = 0; int32_t ok = 0;
do { do {
if (!isspace(c) && c!='\r' && c!='\n') { if (!isspace(c) && c != '\r' && c != '\n') {
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
...@@ -499,34 +445,34 @@ static int on_target(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char ...@@ -499,34 +445,34 @@ static int on_target(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char
break; break;
} }
parser->target_raw = strdup(parser->str.str); parser->target_raw = strdup(parser->str.str);
parser->target = ehttp_parser_urldecode(parser->str.str); parser->target = ehttp_parser_urldecode(parser->str.str);
if (!parser->target_raw || !parser->target) { if (!parser->target_raw || !parser->target) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
} }
ehttp_util_string_clear(&parser->str); httpParserClearString(&parser->str);
ehttp_parser_pop(parser); httpParserPop(parser);
*again = 1; *again = 1;
} while (0); } while (0);
return ok; return ok;
} }
static int on_version(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnVersion(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) {
int ok = 0; int32_t ok = 0;
do { do {
const char *prefix = "HTTP/1."; const char *prefix = "HTTP/1.";
int len = strlen(prefix); int32_t len = strlen(prefix);
if (parser->str.len < len) { if (parser->str.len < len) {
if (prefix[parser->str.len]!=c) { if (prefix[parser->str.len]!=c) {
E("parser state: %d, unexpected char: [%c]%02x", state, c, c); httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 400); parser->callbacks.on_error(parser->arg, 400);
break; break;
} }
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
...@@ -535,13 +481,13 @@ static int on_version(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const cha ...@@ -535,13 +481,13 @@ static int on_version(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const cha
} }
if (c!='0' && c!='1') { if (c!='0' && c!='1') {
E("parser state: %d, unexpected char: [%c]%02x", state, c, c); httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 400); parser->callbacks.on_error(parser->arg, 400);
break; break;
} }
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
...@@ -551,7 +497,7 @@ static int on_version(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const cha ...@@ -551,7 +497,7 @@ static int on_version(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const cha
parser->version = strdup(parser->str.str); parser->version = strdup(parser->str.str);
if (!parser->version) { if (!parser->version) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
...@@ -561,32 +507,32 @@ static int on_version(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const cha ...@@ -561,32 +507,32 @@ static int on_version(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const cha
parser->callbacks.on_request_line(parser->arg, parser->method, parser->target, parser->version, parser->target_raw); parser->callbacks.on_request_line(parser->arg, parser->method, parser->target, parser->version, parser->target_raw);
} }
ehttp_util_string_clear(&parser->str); httpParserClearString(&parser->str);
ehttp_parser_pop(parser); httpParserPop(parser);
} while (0); } while (0);
return ok; return ok;
} }
static int on_sp(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnSp(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int *again) {
int ok = 0; int32_t ok = 0;
do { do {
if (c==' ') { if (c == ' ') {
ehttp_parser_pop(parser); httpParserPop(parser);
break; break;
} }
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpDebug("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
} while (0); } while (0);
return ok; return ok;
} }
static int on_status_code(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnStatusCode(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int *again) {
int ok = 0; int ok = 0;
do { do {
if (isdigit(c)) { if (isdigit(c)) {
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
...@@ -594,36 +540,36 @@ static int on_status_code(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const ...@@ -594,36 +540,36 @@ static int on_status_code(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const
if (parser->str.len < 3) break; if (parser->str.len < 3) break;
sscanf(parser->str.str, "%d", &parser->status_code); sscanf(parser->str.str, "%d", &parser->status_code);
ehttp_util_string_clear(&parser->str); httpParserClearString(&parser->str);
ehttp_parser_pop(parser); httpParserPop(parser);
break; break;
} }
E("parser state: %d, unexpected char: [%c]%02x", state, c, c); httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 400); parser->callbacks.on_error(parser->arg, 400);
} while (0); } while (0);
return ok; return ok;
} }
static int on_reason_phrase(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnReasonPhrase(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int *again) {
int ok = 0; int ok = 0;
do { do {
if (c=='\r') { if (c=='\r') {
parser->reason_phrase = strdup(parser->str.str); parser->reason_phrase = strdup(parser->str.str);
if (!parser->reason_phrase) { if (!parser->reason_phrase) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
} }
parser->callbacks.on_status_line(parser->arg, parser->version, parser->status_code, parser->reason_phrase); parser->callbacks.on_status_line(parser->arg, parser->version, parser->status_code, parser->reason_phrase);
ehttp_util_string_clear(&parser->str); httpParserClearString(&parser->str);
ehttp_parser_pop(parser); httpParserPop(parser);
*again = 1; *again = 1;
break; break;
} }
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
...@@ -632,10 +578,10 @@ static int on_reason_phrase(ehttp_parser_t *parser, HTTP_PARSER_STATE state, con ...@@ -632,10 +578,10 @@ static int on_reason_phrase(ehttp_parser_t *parser, HTTP_PARSER_STATE state, con
return ok; return ok;
} }
static int post_process(ehttp_parser_t *parser) { static int32_t httpParserPostProcess(HttpContext *pContext, HttpParserObj *parser) {
if (parser->gzip) { if (parser->gzip) {
if (ehttp_gzip_finish(parser->gzip)) { if (ehttp_gzip_finish(parser->gzip)) {
E("gzip failed"); httpError("context:%p, fd:%d, gzip failed", pContext, pContext->fd);
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
return -1; return -1;
} }
...@@ -644,28 +590,28 @@ static int post_process(ehttp_parser_t *parser) { ...@@ -644,28 +590,28 @@ static int post_process(ehttp_parser_t *parser) {
return 0; return 0;
} }
static int on_crlf(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnCrlf(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) {
int ok = 0; int32_t ok = 0;
do { do {
const char *s = "\r\n"; const char *s = "\r\n";
int len = strlen(s); int32_t len = strlen(s);
if (s[parser->str.len]!=c) { if (s[parser->str.len]!=c) {
E("parser state: %d, unexpected char: [%c]%02x", state, c, c); httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 400); parser->callbacks.on_error(parser->arg, 400);
break; break;
} }
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
} }
if (parser->str.len == len) { if (parser->str.len == len) {
ehttp_util_string_clear(&parser->str); httpParserClearString(&parser->str);
ehttp_parser_pop(parser); httpParserPop(parser);
if (ehttp_parser_top(parser) == HTTP_PARSER_END) { if (httpParserTop(parser) == HTTP_PARSER_END) {
ok = post_process(parser); ok = httpParserPostProcess(pContext, parser);
} }
} }
break; break;
...@@ -673,49 +619,49 @@ static int on_crlf(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c ...@@ -673,49 +619,49 @@ static int on_crlf(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c
return ok; return ok;
} }
static int on_header(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnHeader(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) {
int ok = 0; int32_t ok = 0;
do { do {
if (c=='\r') { if (c=='\r') {
ehttp_parser_pop(parser); httpParserPop(parser);
if (parser->transfer_chunked) { if (parser->transfer_chunked) {
ehttp_parser_push(parser, HTTP_PARSER_CHUNK_SIZE); httpParserPush(parser, HTTP_PARSER_CHUNK_SIZE);
ehttp_parser_push(parser, HTTP_PARSER_CRLF); httpParserPush(parser, HTTP_PARSER_CRLF);
} else { } else {
if (parser->content_length > 0) { if (parser->content_length > 0) {
ehttp_parser_push(parser, HTTP_PARSER_CHUNK); httpParserPush(parser, HTTP_PARSER_CHUNK);
} }
ehttp_parser_push(parser, HTTP_PARSER_CRLF); httpParserPush(parser, HTTP_PARSER_CRLF);
} }
*again = 1; *again = 1;
break; break;
} }
if (c!=' ' && c!='\t' && c!=':' ) { if (c!=' ' && c!='\t' && c!=':' ) {
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
} }
ehttp_parser_push(parser, HTTP_PARSER_CRLF); httpParserPush(parser, HTTP_PARSER_CRLF);
ehttp_parser_push(parser, HTTP_PARSER_HEADER_VAL); httpParserPush(parser, HTTP_PARSER_HEADER_VAL);
ehttp_parser_push(parser, HTTP_PARSER_SP); httpParserPush(parser, HTTP_PARSER_SP);
ehttp_parser_push(parser, HTTP_PARSER_HEADER_KEY); httpParserPush(parser, HTTP_PARSER_HEADER_KEY);
break; break;
} }
E("parser state: %d, unexpected char: [%c]%02x", state, c, c); httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 400); parser->callbacks.on_error(parser->arg, 400);
} while (0); } while (0);
return ok; return ok;
} }
static int on_header_key(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int httpParserOnHeaderKey(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int *again) {
int ok = 0; int ok = 0;
do { do {
if (isalnum(c) || strchr("!#$%&'*+-.^_`|~", c)) { if (isalnum(c) || strchr("!#$%&'*+-.^_`|~", c)) {
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
...@@ -725,61 +671,62 @@ static int on_header_key(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const ...@@ -725,61 +671,62 @@ static int on_header_key(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const
if (c==':') { if (c==':') {
parser->key = strdup(parser->str.str); parser->key = strdup(parser->str.str);
if (!parser->key) { if (!parser->key) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
} }
ehttp_util_string_clear(&parser->str); httpParserClearString(&parser->str);
ehttp_parser_pop(parser); httpParserPop(parser);
break; break;
} }
E("parser state: %d, unexpected char: [%c]%02x", state, c, c); httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 400); parser->callbacks.on_error(parser->arg, 400);
} while (0); } while (0);
return ok; return ok;
} }
static int on_header_val(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnHeaderVal(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) {
int ok = 0; int32_t ok = 0;
do { do {
if (c != '\r' && c != '\n' && (!isspace(c) || parser->str.len>0)) { if (c != '\r' && c != '\n' && (!isspace(c) || parser->str.len>0)) {
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
} }
break; break;
} }
const char *val = parser->str.str; const char *val = parser->str.str;
ok = ehttp_parser_check_field(parser, parser->key, val); ok = httpParserCheckField(pContext, parser, parser->key, val);
if (ehttp_parser_kvs_append_kv(parser, parser->key, val)) { if (httpParserAppendKv(parser, parser->key, val)) {
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
} else { } else {
parser->callbacks.on_header_field(parser->arg, parser->key, val); parser->callbacks.on_header_field(parser->arg, parser->key, val);
} }
free(parser->key); parser->key = NULL; free(parser->key);
parser->key = NULL;
val = NULL; val = NULL;
if (ok==-1) break; if (ok == -1) break;
ehttp_util_string_clear(&parser->str); httpParserClearString(&parser->str);
ehttp_parser_pop(parser); httpParserPop(parser);
*again = 1; *again = 1;
} while (0); } while (0);
return ok; return ok;
} }
static int on_chunk_size(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnChunkSize(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) {
int ok = 0; int32_t ok = 0;
int bytes; int32_t bytes;
size_t len; int32_t len;
int n; int n;
do { do {
if (isxdigit(c)) { if (isxdigit(c)) {
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
...@@ -787,44 +734,44 @@ static int on_chunk_size(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const ...@@ -787,44 +734,44 @@ static int on_chunk_size(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const
break; break;
} }
if (c=='\r') { if (c=='\r') {
n = sscanf(parser->str.str, "%lx%n", &len, &bytes); n = sscanf(parser->str.str, "%x%n", &len, &bytes);
if (n==1 && bytes==strlen(parser->str.str) && len>=0) { if (n==1 && bytes==strlen(parser->str.str) && len>=0) {
if (len==0) { if (len==0) {
if (parser->content_length_specified == 0 || parser->received_size == parser->content_length) { if (parser->content_length_specified == 0 || parser->received_size == parser->content_length) {
ehttp_util_string_clear(&parser->str); httpParserClearString(&parser->str);
ehttp_parser_pop(parser); httpParserPop(parser);
ehttp_parser_push(parser, HTTP_PARSER_CRLF); httpParserPush(parser, HTTP_PARSER_CRLF);
ehttp_parser_push(parser, HTTP_PARSER_CRLF); httpParserPush(parser, HTTP_PARSER_CRLF);
*again = 1; *again = 1;
break; break;
} }
} else { } else {
if (parser->content_length_specified == 0 || parser->received_size + len <= parser->content_length) { if (parser->content_length_specified == 0 || parser->received_size + len <= parser->content_length) {
parser->chunk_size = len; parser->chunk_size = len;
ehttp_util_string_clear(&parser->str); httpParserClearString(&parser->str);
ehttp_parser_pop(parser); httpParserPop(parser);
ehttp_parser_push(parser, HTTP_PARSER_CHUNK_SIZE); httpParserPush(parser, HTTP_PARSER_CHUNK_SIZE);
ehttp_parser_push(parser, HTTP_PARSER_CRLF); httpParserPush(parser, HTTP_PARSER_CRLF);
ehttp_parser_push(parser, HTTP_PARSER_CHUNK); httpParserPush(parser, HTTP_PARSER_CHUNK);
ehttp_parser_push(parser, HTTP_PARSER_CRLF); httpParserPush(parser, HTTP_PARSER_CRLF);
*again = 1; *again = 1;
break; break;
} }
} }
} }
} }
E("parser state: %d, unexpected char: [%c]%02x", state, c, c); httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 400); parser->callbacks.on_error(parser->arg, 400);
} while (0); } while (0);
return ok; return ok;
} }
static int on_chunk(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int httpParserOnChunk(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int *again) {
int ok = 0; int ok = 0;
do { do {
if (ehttp_util_string_append(&parser->str, &c, 1)) { if (httpParserAppendString(&parser->str, &c, 1)) {
E("parser state: %d, char: [%c]%02x, oom", state, c, c); httpError("context:%p, fd:%d, parser state:%d, char:[%c]%02x, oom", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
...@@ -835,7 +782,7 @@ static int on_chunk(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char ...@@ -835,7 +782,7 @@ static int on_chunk(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char
if (parser->gzip) { if (parser->gzip) {
if (ehttp_gzip_write(parser->gzip, parser->str.str, parser->str.len)) { if (ehttp_gzip_write(parser->gzip, parser->str.str, parser->str.len)) {
E("gzip failed"); httpError("context:%p, fd:%d, gzip failed", pContext, pContext->fd);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
break; break;
...@@ -844,124 +791,128 @@ static int on_chunk(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char ...@@ -844,124 +791,128 @@ static int on_chunk(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char
parser->callbacks.on_body(parser->arg, parser->str.str, parser->str.len); parser->callbacks.on_body(parser->arg, parser->str.str, parser->str.len);
} }
parser->received_chunk_size = 0; parser->received_chunk_size = 0;
ehttp_util_string_clear(&parser->str); httpParserClearString(&parser->str);
ehttp_parser_pop(parser); httpParserPop(parser);
if (ehttp_parser_top(parser) == HTTP_PARSER_END) { if (httpParserTop(parser) == HTTP_PARSER_END) {
ok = post_process(parser); ok = httpParserPostProcess(pContext, parser);
} }
} while (0); } while (0);
return ok; return ok;
} }
static int on_end(ehttp_parser_t *parser, HTTP_PARSER_STATE state, const char c, int *again) { static int32_t httpParserOnEnd(HttpContext *pContext, HttpParserObj *parser, HTTP_PARSER_STATE state, const char c, int32_t *again) {
int ok = 0; int32_t ok = 0;
do { do {
E("parser state: %d, unexpected char: [%c]%02x", state, c, c); httpError("context:%p, fd:%d, parser state:%d, unexpected char:[%c]%02x", pContext, pContext->fd, state, c, c);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 507); parser->callbacks.on_error(parser->arg, 507);
} while (0); } while (0);
return ok; return ok;
} }
static int parse_char(ehttp_parser_t *parser, const char c, int *again) { static int32_t httpParseChar(HttpContext *pContext, HttpParserObj *parser, const char c, int32_t *again) {
int ok = 0; int32_t ok = 0;
HTTP_PARSER_STATE state = ehttp_parser_top(parser); HTTP_PARSER_STATE state = httpParserTop(parser);
do { do {
if (state == HTTP_PARSER_BEGIN) { if (state == HTTP_PARSER_BEGIN) {
ok = on_begin(parser, state, c, again); ok = httpParserOnBegin(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_REQUEST_OR_RESPONSE) { if (state == HTTP_PARSER_REQUEST_OR_RESPONSE) {
ok = on_request_or_response(parser, state, c, again); ok = httpParserOnRquestOrResponse(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_METHOD) { if (state == HTTP_PARSER_METHOD) {
ok = on_method(parser, state, c, again); ok = httpParserOnMethod(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_TARGET) { if (state == HTTP_PARSER_TARGET) {
ok = on_target(parser, state, c, again); ok = httpParserOnTarget(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_HTTP_VERSION) { if (state == HTTP_PARSER_HTTP_VERSION) {
ok = on_version(parser, state, c, again); ok = httpParserOnVersion(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_SP) { if (state == HTTP_PARSER_SP) {
ok = on_sp(parser, state, c, again); ok = httpParserOnSp(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_STATUS_CODE) { if (state == HTTP_PARSER_STATUS_CODE) {
ok = on_status_code(parser, state, c, again); ok = httpParserOnStatusCode(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_REASON_PHRASE) { if (state == HTTP_PARSER_REASON_PHRASE) {
ok = on_reason_phrase(parser, state, c, again); ok = httpParserOnReasonPhrase(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_CRLF) { if (state == HTTP_PARSER_CRLF) {
ok = on_crlf(parser, state, c, again); ok = httpParserOnCrlf(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_HEADER) { if (state == HTTP_PARSER_HEADER) {
ok = on_header(parser, state, c, again); ok = httpParserOnHeader(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_HEADER_KEY) { if (state == HTTP_PARSER_HEADER_KEY) {
ok = on_header_key(parser, state, c, again); ok = httpParserOnHeaderKey(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_HEADER_VAL) { if (state == HTTP_PARSER_HEADER_VAL) {
ok = on_header_val(parser, state, c, again); ok = httpParserOnHeaderVal(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_CHUNK_SIZE) { if (state == HTTP_PARSER_CHUNK_SIZE) {
ok = on_chunk_size(parser, state, c, again); ok = httpParserOnChunkSize(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_CHUNK) { if (state == HTTP_PARSER_CHUNK) {
ok = on_chunk(parser, state, c, again); ok = httpParserOnChunk(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_END) { if (state == HTTP_PARSER_END) {
ok = on_end(parser, state, c, again); ok = httpParserOnEnd(pContext, parser, state, c, again);
break; break;
} }
if (state == HTTP_PARSER_ERROR) { if (state == HTTP_PARSER_ERROR) {
ok = -2; ok = -2;
break; break;
} }
E("unknown parser state: %d", state);
httpError("context:%p, fd:%d, unknown parse state:%d", pContext, pContext->fd, state);
ok = -1; ok = -1;
parser->callbacks.on_error(parser->arg, 500); parser->callbacks.on_error(parser->arg, 500);
} while (0); } while (0);
if (ok==-1) {
ehttp_parser_push(parser, HTTP_PARSER_ERROR); if (ok == -1) {
httpError("context:%p, fd:%d, failed to parse, state:%d ok:%d", pContext, pContext->fd, state, ok);
httpParserPush(parser, HTTP_PARSER_ERROR);
} }
if (ok==-2) ok = -1;
return ok;
}
int ehttp_parser_parse_string(ehttp_parser_t *parser, const char *str) { if (ok == -2) {
return ehttp_parser_parse(parser, str, str?strlen(str):0); httpError("context:%p, fd:%d, failed to parse, state:%d ok:%d", pContext, pContext->fd, state, ok);
} ok = -1;
}
int ehttp_parser_parse_char(ehttp_parser_t *parser, const char c) { return ok;
return ehttp_parser_parse(parser, &c, 1);
} }
int ehttp_parser_parse(ehttp_parser_t *parser, const char *buf, size_t len) { int32_t httpParserBuf(HttpContext *pContext, HttpParserObj *parser, const char *buf, int32_t len) {
const char *p = buf; const char *p = buf;
int ret = 0; int32_t ret = 0;
size_t i = 0; int32_t i = 0;
while (i < len) { while (i < len) {
int again = 0; int32_t again = 0;
ret = parse_char(parser, *p, &again); ret = httpParseChar(pContext, parser, *p, &again);
if (ret) break; if (ret != 0) {
httpError("context:%p, fd:%d, parse failed, ret:%d i:%d len:%d buf:%s", pContext, pContext->fd, ret, i, len, buf);
break;
}
if (again) continue; if (again) continue;
++p; ++p;
++i; ++i;
} }
return ret; return ret;
} }
#include "os.h"
#include "ehttp_util_string.h" #include "ehttp_util_string.h"
#include <stdlib.h> void httpParserCleanupString(HttpUtilString *str) {
#include <string.h>
void ehttp_util_string_cleanup(ehttp_util_string_t *str) {
free(str->str); free(str->str);
str->str = NULL; str->str = NULL;
str->len = 0; str->len = 0;
} }
int ehttp_util_string_append(ehttp_util_string_t *str, const char *s, size_t len) { int32_t httpParserAppendString(HttpUtilString *str, const char *s, int32_t len) {
// int n = str->str?strlen(str->str):0; int32_t n = str->len;
int n = str->len;
char *p = (char*)realloc(str->str, n + len + 1); char *p = (char*)realloc(str->str, n + len + 1);
if (!p) return -1; if (!p) return -1;
strncpy(p+n, s, len); strncpy(p+n, s, len);
...@@ -21,7 +18,7 @@ int ehttp_util_string_append(ehttp_util_string_t *str, const char *s, size_t len ...@@ -21,7 +18,7 @@ int ehttp_util_string_append(ehttp_util_string_t *str, const char *s, size_t len
return 0; return 0;
} }
void ehttp_util_string_clear(ehttp_util_string_t *str) { void httpParserClearString(HttpUtilString *str) {
if (str->str) { if (str->str) {
str->str[0] = '\0'; str->str[0] = '\0';
str->len = 0; str->len = 0;
......
...@@ -26,11 +26,9 @@ ...@@ -26,11 +26,9 @@
#include "httpResp.h" #include "httpResp.h"
#include "httpSql.h" #include "httpSql.h"
#include "httpSession.h" #include "httpSession.h"
#include "httpContext.h" #include "httpContext.h"
#include "elog.h" #include "elog.h"
// dirty tweak
extern bool httpGetHttpMethod(HttpContext* pContext); extern bool httpGetHttpMethod(HttpContext* pContext);
extern bool httpParseURL(HttpContext* pContext); extern bool httpParseURL(HttpContext* pContext);
extern bool httpParseHttpVersion(HttpContext* pContext); extern bool httpParseHttpVersion(HttpContext* pContext);
...@@ -74,7 +72,7 @@ static void httpDestroyContext(void *data) { ...@@ -74,7 +72,7 @@ static void httpDestroyContext(void *data) {
httpFreeMultiCmds(pContext); httpFreeMultiCmds(pContext);
if (pContext->parser.parser) { if (pContext->parser.parser) {
ehttp_parser_destroy(pContext->parser.parser); httpParserDestroy(pContext->parser.parser);
pContext->parser.parser = NULL; pContext->parser.parser = NULL;
} }
...@@ -195,7 +193,7 @@ bool httpInitContext(HttpContext *pContext) { ...@@ -195,7 +193,7 @@ bool httpInitContext(HttpContext *pContext) {
memset(pParser, 0, sizeof(HttpParser)); memset(pParser, 0, sizeof(HttpParser));
pParser->pCur = pParser->pLast = pParser->buffer; pParser->pCur = pParser->pLast = pParser->buffer;
ehttp_parser_callbacks_t callbacks = { HttpParserCallbackObj callbacks = {
httpParseOnRequestLine, httpParseOnRequestLine,
httpParseOnStatusLine, httpParseOnStatusLine,
httpParseOnHeaderField, httpParseOnHeaderField,
...@@ -203,10 +201,10 @@ bool httpInitContext(HttpContext *pContext) { ...@@ -203,10 +201,10 @@ bool httpInitContext(HttpContext *pContext) {
httpParseOnEnd, httpParseOnEnd,
httpParseOnError httpParseOnError
}; };
ehttp_parser_conf_t conf = { HttpParserConfObj conf = {
.flush_block_size = 0 .flush_block_size = 0
}; };
pParser->parser = ehttp_parser_create(callbacks, conf, pContext); pParser->parser = httpParserCreate(callbacks, conf, pContext);
pParser->inited = 1; pParser->inited = 1;
httpDebug("context:%p, fd:%d, parsed:%d", pContext, pContext->fd, pContext->parsed); httpDebug("context:%p, fd:%d, parsed:%d", pContext, pContext->fd, pContext->parsed);
......
...@@ -352,8 +352,11 @@ static bool httpReadData(HttpContext *pContext) { ...@@ -352,8 +352,11 @@ static bool httpReadData(HttpContext *pContext) {
int nread = (int)taosReadSocket(pContext->fd, buf, sizeof(buf)); int nread = (int)taosReadSocket(pContext->fd, buf, sizeof(buf));
if (nread > 0) { if (nread > 0) {
buf[nread] = '\0'; buf[nread] = '\0';
if (ehttp_parser_parse(pParser->parser, buf, nread)) { httpTrace("context:%p, fd:%d, nread:%d content:%s", pContext, pContext->fd, nread, buf);
httpError("context:%p, fd:%d, init parse failed, close connect", pContext, pContext->fd); int ok = httpParserBuf(pContext, pParser->parser, buf, nread);
if (ok) {
httpError("context:%p, fd:%d, init parse failed, reason:%d close connect", pContext, pContext->fd, ok);
httpNotifyContextClose(pContext); httpNotifyContextClose(pContext);
return false; return false;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册