1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-14 20:31:56 +00:00

Upgrade http-parser to 2.9.2

This commit is contained in:
winlin 2019-04-25 10:39:38 +08:00
parent 0ee386b656
commit 8a94ac4b49
4 changed files with 226 additions and 50 deletions

View file

@ -100,6 +100,7 @@ enum SrsHttpParseState {
SrsHttpParseStateInit = 0,
SrsHttpParseStateStart,
SrsHttpParseStateHeaderComplete,
SrsHttpParseStateBody,
SrsHttpParseStateMessageComplete
};

View file

@ -82,7 +82,7 @@ srs_error_t SrsHttpParser::parse_message(ISrsReader* reader, ISrsHttpMessage** p
header = http_parser();
url = "";
headers.clear();
header_parsed = 0;
pbody = NULL;
// do parse
if ((err = parse_message_imp(reader)) != srs_success) {
@ -110,37 +110,34 @@ srs_error_t SrsHttpParser::parse_message_imp(ISrsReader* reader)
while (true) {
ssize_t nparsed = 0;
// when got entire http header, parse it.
// @see https://github.com/ossrs/srs/issues/400
char* start = buffer->bytes();
char* end = start + buffer->size();
for (char* p = start; p <= end - 4; p++) {
// SRS_HTTP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
if (p[0] == SRS_CONSTS_CR && p[1] == SRS_CONSTS_LF && p[2] == SRS_CONSTS_CR && p[3] == SRS_CONSTS_LF) {
nparsed = http_parser_execute(&parser, &settings, buffer->bytes(), buffer->size());
srs_info("buffer=%d, nparsed=%d, header=%d", buffer->size(), (int)nparsed, header_parsed);
break;
}
}
// consume the parsed bytes.
if (nparsed && header_parsed) {
buffer->read_slice(header_parsed);
}
// ok atleast header completed,
// never wait for body completed, for maybe chunked.
if (state == SrsHttpParseStateHeaderComplete || state == SrsHttpParseStateMessageComplete) {
break;
if (buffer->size() > 0) {
nparsed = http_parser_execute(&parser, &settings, buffer->bytes(), buffer->size());
if (buffer->size() != nparsed) {
return srs_error_new(ERROR_HTTP_PARSE_HEADER, "parse failed, nparsed=%d, size=%d", nparsed, buffer->size());
}
// The consumed size, does not include the body.
ssize_t consumed = nparsed;
if (pbody && start < pbody) {
consumed = pbody - start;
}
srs_info("size=%d, nparsed=%d, consumed=%d", buffer->size(), (int)nparsed, consumed);
// Only consume the header bytes.
buffer->read_slice(consumed);
// Done when header completed, never wait for body completed, because it maybe chunked.
if (state >= SrsHttpParseStateHeaderComplete) {
break;
}
}
// when nothing parsed, read more to parse.
if (nparsed == 0) {
// when requires more, only grow 1bytes, but the buffer will cache more.
if ((err = buffer->grow(reader, buffer->size() + 1)) != srs_success) {
return srs_error_wrap(err, "grow buffer");
}
// when requires more, only grow 1bytes, but the buffer will cache more.
if ((err = buffer->grow(reader, buffer->size() + 1)) != srs_success) {
return srs_error_wrap(err, "grow buffer");
}
}
@ -172,8 +169,7 @@ int SrsHttpParser::on_headers_complete(http_parser* parser)
obj->header = *parser;
// save the parser when header parse completed.
obj->state = SrsHttpParseStateHeaderComplete;
obj->header_parsed = (int)parser->nread;
srs_info("***HEADERS COMPLETE***");
// see http_parser.c:1570, return 1 to skip body.
@ -249,11 +245,11 @@ int SrsHttpParser::on_body(http_parser* parser, const char* at, size_t length)
SrsHttpParser* obj = (SrsHttpParser*)parser->data;
srs_assert(obj);
// When got body, but no header-parsed, we update it manually.
char* p = obj->buffer->bytes();
if (!obj->header_parsed && p < at) {
obj->header_parsed = int(at - p);
}
// save the parser when body parsed.
obj->state = SrsHttpParseStateBody;
// Save the body position.
obj->pbody = at;
srs_info("Body: %.*s", (int)length, at);

View file

@ -59,7 +59,7 @@ private:
http_parser header;
std::string url;
std::vector<SrsHttpHeaderField> headers;
int header_parsed;
const char* pbody;
public:
SrsHttpParser();
virtual ~SrsHttpParser();

View file

@ -5618,6 +5618,7 @@ class MockParser
private:
http_parser_settings settings;
http_parser* parser;
size_t parsed;
public:
MockStage* message_begin;
MockStage* url;
@ -5652,6 +5653,7 @@ MockParser::MockParser()
parser = new http_parser();
http_parser_init(parser, HTTP_REQUEST);
parser->data = (void*)this;
parsed = 0;
memset(&settings, 0, sizeof(settings));
settings.on_message_begin = on_message_begin;
@ -5820,6 +5822,8 @@ srs_error_t MockParser::parse(string data)
const char* buf = (const char*)data.data();
size_t size = (size_t)data.length();
size_t nparsed = http_parser_execute(parser, &settings, buf, size);
parsed = nparsed;
if (nparsed != size) {
return srs_error_new(-1, "nparsed=%d, size=%d", nparsed, size);
}
@ -5833,25 +5837,200 @@ VOID TEST(ProtocolHTTPTest, HTTPParser)
if (true) {
MockParser parser;
// size = 70, nparsed = 70, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\n"));
EXPECT_EQ(70, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
EXPECT_TRUE(!parser.body);
EXPECT_TRUE(parser.headers_complete);
EXPECT_TRUE(!parser.message_complete);
}
if (true) {
MockParser parser;
// size = 75, nparsed = 75, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello"));
EXPECT_EQ(75, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
EXPECT_TRUE(parser.body && 5 == parser.body->length);
EXPECT_TRUE(parser.headers_complete);
EXPECT_TRUE(parser.message_complete);
}
if (true) {
MockParser parser;
// size = 150, nparsed = 150, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHelloGET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nWorld"));
EXPECT_EQ(150, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
}
if (true) {
MockParser parser;
// size = 70, nparsed = 70, nread = 0, content_length = 5, Header("Content-Length", 5)
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\n"));
EXPECT_EQ(70, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
EXPECT_EQ(5, parser.parser->content_length);
// size = 79, nparsed = 5, nread = 1, content_length = -1, Header("Content-Length", 5)
HELPER_EXPECT_FAILED(parser.parse("elloGET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello"));
EXPECT_EQ(5, parser.parsed);
EXPECT_EQ(1, parser.parser->nread);
EXPECT_EQ(-1, (int64_t)parser.parser->content_length);
}
if (true) {
MockParser parser;
// size = 70, nparsed = 70, nread = 0, content_length = 5, Header("Content-Length", 5)
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\n"));
EXPECT_EQ(70, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
EXPECT_EQ(5, parser.parser->content_length);
// size = 80, nparsed = 70, nread = 0, content_length = 0, Header("Content-Length", 5)
HELPER_EXPECT_SUCCESS(parser.parse("HelloGET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nWorld"));
EXPECT_EQ(80, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
EXPECT_EQ(0, parser.parser->content_length);
}
if (true) {
MockParser parser;
// size = 73, nparsed = 73, nread = 0, content_length = 2, Header("Content-Length", 5)
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHel"));
EXPECT_EQ(73, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
EXPECT_EQ(2, parser.parser->content_length);
}
if (true) {
MockParser parser;
// size = 82, nparsed = 75, nread = 1, content_length = -1, Header("Content-Length", 5)
HELPER_EXPECT_FAILED(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello World!"));
EXPECT_EQ(75, parser.parsed);
EXPECT_EQ(1, parser.parser->nread);
EXPECT_EQ(-1, (int64_t)parser.parser->content_length);
}
if (true) {
MockParser parser;
// size = 34, nparsed = 34, nread = 34
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHo"));
EXPECT_EQ(34, parser.parsed);
EXPECT_EQ(34, parser.parser->nread);
// size = 41, nparsed = 41, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("st: ossrs.net\r\nContent-Length: 5\r\n\r\nHello"));
EXPECT_EQ(41, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
}
if (true) {
MockParser parser;
// size = 41, nparsed = 41, nread = 41
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: oss"));
EXPECT_EQ(41, parser.parsed);
EXPECT_EQ(41, parser.parser->nread);
// size = 34, nparsed = 34, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("rs.net\r\nContent-Length: 5\r\n\r\nHello"));
EXPECT_EQ(34, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
}
if (true) {
MockParser parser;
// size = 48, nparsed = 48, nread = 48
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r"));
EXPECT_EQ(48, parser.parsed);
EXPECT_EQ(48, parser.parser->nread);
// size = 27, nparsed = 27, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("\nContent-Length: 5\r\n\r\nHello"));
EXPECT_EQ(27, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
}
if (true) {
MockParser parser;
// size = 68, nparsed = 68, nread = 68
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n"));
EXPECT_EQ(68, parser.parsed);
EXPECT_EQ(68, parser.parser->nread);
// size = 7, nparsed = 7, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("\r\nHello"));
EXPECT_EQ(7, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
}
if (true) {
MockParser parser;
// size = 69, nparsed = 69, nread = 69
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r"));
EXPECT_EQ(69, parser.parsed);
EXPECT_EQ(69, parser.parser->nread);
// size = 6, nparsed = 6, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("\nHello"));
EXPECT_EQ(6, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
}
if (true) {
MockParser parser;
// size = 75, nparsed = 75, nread = 0
HELPER_EXPECT_SUCCESS(parser.parse("GET /gslb/v1/versions HTTP/1.1\r\nHost: ossrs.net\r\nContent-Length: 5\r\n\r\nHello"));
EXPECT_EQ(75, parser.parsed);
EXPECT_EQ(0, parser.parser->nread);
}
if (true) {
MockParser parser;
// nparsed = 2, size = 2, nread = 2
HELPER_EXPECT_SUCCESS(parser.parse("GE"));
EXPECT_EQ(2, parser.parsed);
EXPECT_EQ(2, parser.parser->nread);
// size = 0, nparsed = 1, nread=2
HELPER_EXPECT_FAILED(parser.parse(""));
EXPECT_EQ(1, parser.parsed);
EXPECT_EQ(2, parser.parser->nread);
}
if (true) {
MockParser parser;
// size = 2, nparsed = 2, nread = 2
HELPER_EXPECT_SUCCESS(parser.parse("GE"));
EXPECT_EQ(2, parser.parsed);
EXPECT_EQ(2, parser.parser->nread);
// size = 1, nparsed = 0, nread = 3
HELPER_EXPECT_FAILED(parser.parse("X"));
EXPECT_EQ(0, parser.parsed);
EXPECT_EQ(3, parser.parser->nread);
}
if (true) {
MockParser parser;
// size = 2, nparsed = 2, nread = 2
HELPER_EXPECT_SUCCESS(parser.parse("GE"));
EXPECT_EQ(2, parser.parsed);
EXPECT_EQ(2, parser.parser->nread);
// size = 1, nparsed = 1, nread = 3
HELPER_EXPECT_SUCCESS(parser.parse("T"));
EXPECT_EQ(1, parser.parsed);
EXPECT_EQ(3, parser.parser->nread);
}
if (true) {
MockParser parser;
// size = 3, nparsed = 3, nread = 3
HELPER_EXPECT_SUCCESS(parser.parse("GET"));
EXPECT_EQ(3, parser.parsed);
EXPECT_EQ(3, parser.parser->nread);
}
}
@ -5861,22 +6040,9 @@ VOID TEST(ProtocolHTTPTest, ParseHTTPMessage)
MockBufferIO bio;
SrsHttpParser hp;
bio.append("GET");
EXPECT_TRUE(0 == hp.initialize(HTTP_REQUEST, false));
// Should fail if not completed message.
ISrsHttpMessage* req = NULL;
ASSERT_FALSE(0 == hp.parse_message(&bio, &req));
srs_freep(req);
}
if (true) {
MockBufferIO bio;
SrsHttpParser hp;
bio.append("GET /gslb/v1/versions HTTP/1.1\r\nContent-Length: 5\r\n\r\nHello");
EXPECT_TRUE(0 == hp.initialize(HTTP_REQUEST, false));
ISrsHttpMessage* req = NULL;
ASSERT_TRUE(0 == hp.parse_message(&bio, &req));
@ -5893,6 +6059,19 @@ VOID TEST(ProtocolHTTPTest, ParseHTTPMessage)
ASSERT_FALSE(0 == hp.parse_message(&bio, &req));
srs_freep(req);
}
if (true) {
MockBufferIO bio;
SrsHttpParser hp;
bio.append("GET");
EXPECT_TRUE(0 == hp.initialize(HTTP_REQUEST, false));
// Should fail if not completed message.
ISrsHttpMessage* req = NULL;
ASSERT_FALSE(0 == hp.parse_message(&bio, &req));
srs_freep(req);
}
if (true) {
MockBufferIO bio;