mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
change to 0.9.42, add http parse framework
This commit is contained in:
parent
5aa0043934
commit
51c1615173
8 changed files with 214 additions and 37 deletions
5
trunk/configure
vendored
5
trunk/configure
vendored
|
@ -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"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue