winlin

change to 0.9.42, add http parse framework

... ... @@ -204,8 +204,9 @@ help:
@echo " uninstall uninstall srs from prefix path"
clean:
(cd ${SRS_OBJS}; rm -f rm -rf srs bandwidth srs_utest)
(cd ${SRS_OBJS}; rm -rf src research include lib utest)
(cd ${SRS_OBJS}; rm -rf srs bandwidth srs_utest)
(cd ${SRS_OBJS}; rm -rf src research include lib)
(cd ${SRS_OBJS}/utest; rm -rf *.o *.a)
(cd research/librtmp; make clean)
(cd research/api-server/static-dir; rm -rf crossdomain.xml forward live players)
... ...
... ... @@ -43,6 +43,9 @@ using namespace srs;
#define SRS_DEFAULT_HTTP_PORT 80
#define SRS_HTTP_RESPONSE_OK "0"
#define SRS_HTTP_HEADER_BUFFER 1024
#define SRS_HTTP_BODY_BUFFER 32 * 1024
SrsHttpUri::SrsHttpUri()
{
port = SRS_DEFAULT_HTTP_PORT;
... ... @@ -153,13 +156,13 @@ int SrsHttpClient::post(SrsHttpUri* uri, std::string req, std::string& res)
// POST %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s
std::stringstream ss;
ss << "POST " << uri->get_path() << " "
<< "HTTP/1.1" << CRLF
<< "Host: " << uri->get_host() << CRLF
<< "Connection: Keep-Alive" << CRLF
<< "Content-Length: " << std::dec << req.length() << CRLF
<< "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << CRLF
<< "Content-Type: text/html" << CRLF
<< CRLF
<< "HTTP/1.1" << __CRLF
<< "Host: " << uri->get_host() << __CRLF
<< "Connection: Keep-Alive" << __CRLF
<< "Content-Length: " << std::dec << req.length() << __CRLF
<< "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << __CRLF
<< "Content-Type: text/html" << __CRLF
<< __CRLF
<< req;
SrsSocket skt(stfd);
... ... @@ -375,13 +378,13 @@ int SrsHttpClient::parse_response_body_data(SrsHttpUri* uri, SrsSocket* skt, std
int SrsHttpClient::on_headers_complete(http_parser* parser)
{
SrsHttpClient* obj = (SrsHttpClient*)parser->data;
obj->comple_header(parser);
obj->complete_header(parser);
// see http_parser.c:1570, return 1 to skip body.
return 1;
}
void SrsHttpClient::comple_header(http_parser* parser)
void SrsHttpClient::complete_header(http_parser* parser)
{
// save the parser status when header parse completed.
memcpy(&http_header, parser, sizeof(http_header));
... ...
... ... @@ -35,18 +35,18 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
namespace srs
{
// CR = <US-ASCII CR, carriage return (13)>
const static char CR = '\r';
#define __CR "\r" // 0x0D
// LF = <US-ASCII LF, linefeed (10)>
const static char LF = '\n';
#define __LF "\n" // 0x0A
// SP = <US-ASCII SP, space (32)>
const static char SP = ' ';
#define __SP " " // 0x20
// HT = <US-ASCII HT, horizontal-tab (9)>
const static char HT = 9;
#define __HT "\x09" // 0x09
// HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
// protocol elements except the entity-body (see appendix 19.3 for
// tolerant applications).
const static char* CRLF = "\r\n";
#define __CRLF __CR""__LF // 0x0D0A
};
#ifdef SRS_HTTP_CALLBACK
... ... @@ -58,9 +58,6 @@ class SrsSocket;
#include <http_parser.h>
#define SRS_HTTP_HEADER_BUFFER 1024
#define SRS_HTTP_BODY_BUFFER 32 * 1024
/**
* used to resolve the http uri.
*/
... ... @@ -124,7 +121,7 @@ private:
virtual int parse_response_body_data(SrsHttpUri* uri, SrsSocket* skt, std::string* response, size_t body_left, const void* buf, size_t size);
private:
static int on_headers_complete(http_parser* parser);
virtual void comple_header(http_parser* parser);
virtual void complete_header(http_parser* parser);
};
/**
... ...
... ... @@ -25,6 +25,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_kernel_log.hpp>
#include <srs_kernel_error.hpp>
#include <srs_app_socket.hpp>
#define SRS_HTTP_HEADER_BUFFER 1024
SrsHttpConn::SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd)
: SrsConnection(srs_server, client_stfd)
... ... @@ -44,13 +47,151 @@ int SrsHttpConn::do_cycle()
return ret;
}
srs_trace("http get peer ip success. ip=%s", ip);
// setup http parser
http_parser_settings settings;
memset(&settings, 0, sizeof(settings));
settings.on_message_begin = on_message_begin;
settings.on_url = on_url;
settings.on_header_field = on_header_field;
settings.on_header_value = on_header_value;
settings.on_headers_complete = on_headers_complete;
settings.on_body = on_body;
settings.on_message_complete = on_message_complete;
http_parser parser;
http_parser_init(&parser, HTTP_REQUEST);
// callback object ptr.
parser.data = (void*)this;
// underlayer socket
SrsSocket skt(stfd);
for (;;) {
if ((ret = process_request(&skt, &parser, &settings)) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) {
srs_error("http client cycle failed. ret=%d", ret);
}
return ret;
}
}
return ret;
}
int SrsHttpConn::process_request(SrsSocket* skt, http_parser* parser, http_parser_settings* settings)
{
int ret = ERROR_SUCCESS;
// reset response header.
http_header = NULL;
// parser header.
char buf[SRS_HTTP_HEADER_BUFFER];
for (;;) {
ssize_t nread;
if ((ret = skt->read(buf, (size_t)sizeof(buf), &nread)) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) {
srs_error("read body from server failed. ret=%d", ret);
}
return ret;
}
ssize_t nparsed = http_parser_execute(parser, settings, buf, nread);
srs_info("read_size=%d, nparsed=%d", (int)nread, (int)nparsed);
// check header size.
if (http_header) {
int nb_body = nread - nparsed;
srs_info("http header parsed, size=%d, content-length=%"PRId64", nb_body=%d",
http_header->nread, http_header->content_length, nb_body);
return complete_header(skt, http_header, buf + nparsed, nb_body);
}
if (nparsed != nread) {
ret = ERROR_HTTP_PARSE_HEADER;
srs_error("parse response error, parsed(%d)!=read(%d), ret=%d", (int)nparsed, (int)nread, ret);
return ret;
}
}
return ret;
}
int SrsHttpConn::complete_header(SrsSocket* skt, http_parser* header, char* body, int nb_body)
{
int ret = ERROR_SUCCESS;
char data[] = "HTTP/1.1 200 OK\r\n"
"Server: SRS/"RTMP_SIG_SRS_VERSION"\r\n"
"Content-Length: 15\r\n"
"Content-Type: text/html;charset=utf-8\r\n\r\n"
"hello http/1.1~";
st_write(stfd, data, sizeof(data), -1);
skt->write(data, sizeof(data), NULL);
return ret;
}
int SrsHttpConn::on_message_begin(http_parser* parser)
{
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
(void)obj;
srs_trace("***MESSAGE BEGIN***");
return 0;
}
int SrsHttpConn::on_headers_complete(http_parser* parser)
{
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
(void)obj;
srs_trace("***HEADERS COMPLETE***");
// see http_parser.c:1570, return 1 to skip body.
return 0;
}
int SrsHttpConn::on_message_complete(http_parser* parser)
{
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
srs_trace("***MESSAGE COMPLETE***\n");
// save the parser when header parse completed.
obj->http_header = parser;
return 0;
}
int SrsHttpConn::on_url(http_parser* parser, const char* at, size_t length)
{
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
(void)obj;
srs_trace("Method: %d, Url: %.*s", parser->method, (int)length, at);
return 0;
}
int SrsHttpConn::on_header_field(http_parser* parser, const char* at, size_t length)
{
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
(void)obj;
srs_trace("Header field: %.*s", (int)length, at);
return 0;
}
int SrsHttpConn::on_header_value(http_parser* parser, const char* at, size_t length)
{
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
(void)obj;
srs_trace("Header value: %.*s", (int)length, at);
return 0;
}
int SrsHttpConn::on_body(http_parser* parser, const char* at, size_t length)
{
SrsHttpConn* obj = (SrsHttpConn*)parser->data;
(void)obj;
srs_trace("Body: %.*s", (int)length, at);
return 0;
}
... ...
... ... @@ -33,13 +33,30 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_app_st.hpp>
#include <srs_app_conn.hpp>
#include <http_parser.h>
class SrsSocket;
class SrsHttpConn : public SrsConnection
{
private:
http_parser* http_header;
public:
SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd);
virtual ~SrsHttpConn();
protected:
virtual int do_cycle();
private:
virtual int process_request(SrsSocket* skt, http_parser* parser, http_parser_settings* settings);
virtual int complete_header(SrsSocket* skt, http_parser* header, char* body, int nb_body);
private:
static int on_message_begin(http_parser* parser);
static int on_headers_complete(http_parser* parser);
static int on_message_complete(http_parser* parser);
static int on_url(http_parser* parser, const char* at, size_t length);
static int on_header_field(http_parser* parser, const char* at, size_t length);
static int on_header_value(http_parser* parser, const char* at, size_t length);
static int on_body(http_parser* parser, const char* at, size_t length);
};
#endif
... ...
... ... @@ -99,23 +99,26 @@ int SrsSocket::read(const void* buf, size_t size, ssize_t* nread)
{
int ret = ERROR_SUCCESS;
*nread = st_read(stfd, (void*)buf, size, recv_timeout);
ssize_t nb_read = st_read(stfd, (void*)buf, size, recv_timeout);
if (nread) {
*nread = nb_read;
}
// On success a non-negative integer indicating the number of bytes actually read is returned
// (a value of 0 means the network connection is closed or end of file is reached).
if (*nread <= 0) {
if (nb_read <= 0) {
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (*nread == 0) {
if (nb_read == 0) {
errno = ECONNRESET;
}
return ERROR_SOCKET_READ;
}
recv_bytes += *nread;
recv_bytes += nb_read;
return ret;
}
... ... @@ -124,23 +127,26 @@ int SrsSocket::read_fully(const void* buf, size_t size, ssize_t* nread)
{
int ret = ERROR_SUCCESS;
*nread = st_read_fully(stfd, (void*)buf, size, recv_timeout);
ssize_t nb_read = st_read_fully(stfd, (void*)buf, size, recv_timeout);
if (nread) {
*nread = nb_read;
}
// On success a non-negative integer indicating the number of bytes actually read is returned
// (a value less than nbyte means the network connection is closed or end of file is reached)
if (*nread != (ssize_t)size) {
if (nb_read != (ssize_t)size) {
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
if (*nread >= 0) {
if (nb_read >= 0) {
errno = ECONNRESET;
}
return ERROR_SOCKET_READ_FULLY;
}
recv_bytes += *nread;
recv_bytes += nb_read;
return ret;
}
... ... @@ -149,9 +155,12 @@ int SrsSocket::write(const void* buf, size_t size, ssize_t* nwrite)
{
int ret = ERROR_SUCCESS;
*nwrite = st_write(stfd, (void*)buf, size, send_timeout);
ssize_t nb_write = st_write(stfd, (void*)buf, size, send_timeout);
if (nwrite) {
*nwrite = nb_write;
}
if (*nwrite <= 0) {
if (nb_write <= 0) {
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
... ... @@ -159,7 +168,7 @@ int SrsSocket::write(const void* buf, size_t size, ssize_t* nwrite)
return ERROR_SOCKET_WRITE;
}
send_bytes += *nwrite;
send_bytes += nb_write;
return ret;
}
... ... @@ -168,9 +177,12 @@ int SrsSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
{
int ret = ERROR_SUCCESS;
*nwrite = st_writev(stfd, iov, iov_size, send_timeout);
ssize_t nb_write = st_writev(stfd, iov, iov_size, send_timeout);
if (nwrite) {
*nwrite = nb_write;
}
if (*nwrite <= 0) {
if (nb_write <= 0) {
if (errno == ETIME) {
return ERROR_SOCKET_TIMEOUT;
}
... ... @@ -178,7 +190,7 @@ int SrsSocket::writev(const iovec *iov, int iov_size, ssize_t* nwrite)
return ERROR_SOCKET_WRITE;
}
send_bytes += *nwrite;
send_bytes += nb_write;
return ret;
}
... ...
... ... @@ -60,8 +60,14 @@ public:
virtual int get_recv_kbps();
virtual int get_send_kbps();
public:
/**
* @param nread, the actual read bytes, ignore if NULL.
*/
virtual int read(const void* buf, size_t size, ssize_t* nread);
virtual int read_fully(const void* buf, size_t size, ssize_t* nread);
/**
* @param nwrite, the actual write bytes, ignore if NULL.
*/
virtual int write(const void* buf, size_t size, ssize_t* nwrite);
virtual int writev(const iovec *iov, int iov_size, ssize_t* nwrite);
};
... ...
... ... @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// current release version
#define VERSION_MAJOR "0"
#define VERSION_MINOR "9"
#define VERSION_REVISION "41"
#define VERSION_REVISION "42"
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
// server info.
#define RTMP_SIG_SRS_KEY "srs"
... ...