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:
parent
0ee386b656
commit
8a94ac4b49
4 changed files with 226 additions and 50 deletions
|
@ -100,6 +100,7 @@ enum SrsHttpParseState {
|
|||
SrsHttpParseStateInit = 0,
|
||||
SrsHttpParseStateStart,
|
||||
SrsHttpParseStateHeaderComplete,
|
||||
SrsHttpParseStateBody,
|
||||
SrsHttpParseStateMessageComplete
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue