1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

create http handler framework

This commit is contained in:
winlin 2014-04-02 18:07:34 +08:00
parent eae9b94153
commit 341b5151d9
10 changed files with 244 additions and 9 deletions

View file

@ -285,7 +285,7 @@ fi
##################################################################################### #####################################################################################
function write_nginx_html5() function write_nginx_html5()
{ {
cat<<END >> ${html_file} cat<<END > ${html_file}
<video width="640" height="360" <video width="640" height="360"
autoplay controls autobuffer autoplay controls autobuffer
src="${hls_stream}" src="${hls_stream}"
@ -398,7 +398,7 @@ if [ $__SRS_BUILD_NGINX = YES ]; then
ln -sf `pwd`/research/players/nginx_index.html ${SRS_OBJS}/nginx/html/index.html ln -sf `pwd`/research/players/nginx_index.html ${SRS_OBJS}/nginx/html/index.html
else else
rm -f ${SRS_OBJS}/nginx/html/index.html && rm -f ${SRS_OBJS}/nginx/html/index.html &&
cat<<END >> ${SRS_OBJS}/nginx/html/index.html cat<<END > ${SRS_OBJS}/nginx/html/index.html
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>

View file

@ -32,11 +32,101 @@ using namespace std;
#include <srs_kernel_error.hpp> #include <srs_kernel_error.hpp>
#include <srs_kernel_log.hpp> #include <srs_kernel_log.hpp>
#include <srs_app_socket.hpp> #include <srs_app_socket.hpp>
#include <srs_app_http_api.hpp>
#include <srs_app_http_conn.hpp>
#define SRS_DEFAULT_HTTP_PORT 80 #define SRS_DEFAULT_HTTP_PORT 80
#define SRS_HTTP_HEADER_BUFFER 1024 #define SRS_HTTP_HEADER_BUFFER 1024
SrsHttpHandler::SrsHttpHandler()
{
}
SrsHttpHandler::~SrsHttpHandler()
{
std::vector<SrsHttpHandler*>::iterator it;
for (it = handlers.begin(); it != handlers.end(); ++it) {
SrsHttpHandler* handler = *it;
srs_freep(handler);
}
handlers.clear();
}
int SrsHttpHandler::initialize()
{
int ret = ERROR_SUCCESS;
return ret;
}
bool SrsHttpHandler::can_handle(const char* /*path*/, int /*length*/)
{
return false;
}
int SrsHttpHandler::process_request(SrsSocket* /*skt*/, SrsHttpMessage* /*req*/, const char* /*path*/, int /*length*/)
{
int ret = ERROR_SUCCESS;
return ret;
}
int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandler** phandler, const char** pstart, int* plength)
{
int ret = ERROR_SUCCESS;
for (;;) {
// ensure cur is not NULL.
// ensure p not NULL and has bytes to parse.
if (!path || length <= 0) {
break;
}
const char* p = NULL;
for (p = path + 1; p - path < length && *p != __PATH_SEP; p++) {
}
// whether the handler can handler the node.
int node_size = p - path;
if (!can_handle(path, node_size)) {
break;
}
*phandler = this;
*pstart = path;
*plength = node_size;
std::vector<SrsHttpHandler*>::iterator it;
for (it = handlers.begin(); it != handlers.end(); ++it) {
SrsHttpHandler* handler = *it;
// matched, donot search.
if (handler->best_match(p, length - node_size, phandler, pstart, plength) == ERROR_SUCCESS) {
break;
}
}
// whatever, donot loop.
break;
}
if (*phandler == NULL) {
ret = ERROR_HTTP_HANDLER_MATCH_URL;
return ret;
}
return ret;
}
SrsHttpHandler* SrsHttpHandler::create_http_api()
{
return new SrsApiRoot();
}
SrsHttpHandler* SrsHttpHandler::create_http_stream()
{
// TODO: FIXME: use http stream handler instead.
return new SrsHttpHandler();
}
SrsHttpMessage::SrsHttpMessage() SrsHttpMessage::SrsHttpMessage()
{ {
_body = new SrsBuffer(); _body = new SrsBuffer();

View file

@ -32,6 +32,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifdef SRS_HTTP_PARSER #ifdef SRS_HTTP_PARSER
#include <string> #include <string>
#include <vector>
#include <http_parser.h> #include <http_parser.h>
@ -40,6 +41,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsBuffer; class SrsBuffer;
class SrsRequest; class SrsRequest;
class SrsSocket; class SrsSocket;
class SrsHttpMessage;
// http specification // http specification
// CR = <US-ASCII CR, carriage return (13)> // CR = <US-ASCII CR, carriage return (13)>
@ -57,12 +59,58 @@ class SrsSocket;
#define __CRLF "\r\n" // 0x0D0A #define __CRLF "\r\n" // 0x0D0A
#define __CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A #define __CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
// linux path seprator
#define __PATH_SEP '/'
// state of message
enum SrsHttpParseState { enum SrsHttpParseState {
SrsHttpParseStateInit = 0, SrsHttpParseStateInit = 0,
SrsHttpParseStateStart, SrsHttpParseStateStart,
SrsHttpParseStateComplete SrsHttpParseStateComplete
}; };
/**
* resource handler for HTTP RESTful api.
*/
class SrsHttpHandler
{
protected:
/**
* we use handler chain to process request.
*/
std::vector<SrsHttpHandler*> handlers;
public:
SrsHttpHandler();
virtual ~SrsHttpHandler();
public:
/**
* initialize the handler.
*/
virtual int initialize();
/**
* whether current handler can handle the specified path.
*/
virtual bool can_handle(const char* path, int length);
/**
* use the handler to process the request.
*/
virtual int process_request(SrsSocket* skt, SrsHttpMessage* req, const char* path, int length);
public:
/**
* find the best matched handler
*/
virtual int best_match(const char* path, int length, SrsHttpHandler** phandler, const char** pstart, int* plength);
public:
/**
* create http api resource handler.
*/
static SrsHttpHandler* create_http_api();
/**
* create http stream resource handler.
*/
static SrsHttpHandler* create_http_stream();
};
/** /**
* the http message, request or response. * the http message, request or response.
*/ */

View file

@ -34,10 +34,30 @@ using namespace std;
#include <srs_app_socket.hpp> #include <srs_app_socket.hpp>
#include <srs_core_autofree.hpp> #include <srs_core_autofree.hpp>
SrsHttpApi::SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd) SrsApiRoot::SrsApiRoot()
{
}
SrsApiRoot::~SrsApiRoot()
{
}
bool SrsApiRoot::can_handle(const char* /*path*/, int /*length*/)
{
return true;
}
int SrsApiRoot::process_request(SrsSocket* /*skt*/, SrsHttpMessage* /*req*/, const char* /*path*/, int /*length*/)
{
int ret = ERROR_SUCCESS;
return ret;
}
SrsHttpApi::SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler)
: SrsConnection(srs_server, client_stfd) : SrsConnection(srs_server, client_stfd)
{ {
parser = new SrsHttpParser(); parser = new SrsHttpParser();
handler = _handler;
} }
SrsHttpApi::~SrsHttpApi() SrsHttpApi::~SrsHttpApi()
@ -93,6 +113,28 @@ int SrsHttpApi::process_request(SrsSocket* skt, SrsHttpMessage* req)
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
// TODO: maybe need to parse the url.
std::string uri = req->url();
int length = 0;
const char* start = NULL;
SrsHttpHandler* p = NULL;
if ((ret = handler->best_match(uri.data(), uri.length(), &p, &start, &length)) != ERROR_SUCCESS) {
srs_warn("failed to find the best match handler for url. ret=%d", ret);
return ret;
}
// if success, p and pstart should be valid.
srs_assert(p);
srs_assert(start);
srs_assert(length <= (int)uri.length());
// use handler to process request.
if ((ret = p->process_request(skt, req, start, length)) != ERROR_SUCCESS) {
srs_warn("handler failed to process http request. ret=%d", ret);
return ret;
}
if (req->method() == HTTP_OPTIONS) { if (req->method() == HTTP_OPTIONS) {
char data[] = "HTTP/1.1 200 OK" __CRLF char data[] = "HTTP/1.1 200 OK" __CRLF
"Content-Length: 0"__CRLF "Content-Length: 0"__CRLF

View file

@ -35,16 +35,30 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsSocket; class SrsSocket;
class SrsHttpMessage; class SrsHttpMessage;
class SrsHttpParser; class SrsHttpParser;
class SrsHttpHandler;
#include <srs_app_st.hpp> #include <srs_app_st.hpp>
#include <srs_app_conn.hpp> #include <srs_app_conn.hpp>
#include <srs_app_http.hpp>
// for http root.
class SrsApiRoot : public SrsHttpHandler
{
public:
SrsApiRoot();
virtual ~SrsApiRoot();
public:
virtual bool can_handle(const char* path, int length);
virtual int process_request(SrsSocket* skt, SrsHttpMessage* req, const char* path, int length);
};
class SrsHttpApi : public SrsConnection class SrsHttpApi : public SrsConnection
{ {
private: private:
SrsHttpParser* parser; SrsHttpParser* parser;
SrsHttpHandler* handler;
public: public:
SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd); SrsHttpApi(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler);
virtual ~SrsHttpApi(); virtual ~SrsHttpApi();
protected: protected:
virtual int do_cycle(); virtual int do_cycle();

View file

@ -37,10 +37,11 @@ using namespace std;
#define SRS_HTTP_HEADER_BUFFER 1024 #define SRS_HTTP_HEADER_BUFFER 1024
SrsHttpConn::SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd) SrsHttpConn::SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler)
: SrsConnection(srs_server, client_stfd) : SrsConnection(srs_server, client_stfd)
{ {
parser = new SrsHttpParser(); parser = new SrsHttpParser();
handler = _handler;
} }
SrsHttpConn::~SrsHttpConn() SrsHttpConn::~SrsHttpConn()

View file

@ -40,13 +40,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsSocket; class SrsSocket;
class SrsHttpParser; class SrsHttpParser;
class SrsHttpMessage; class SrsHttpMessage;
class SrsHttpHandler;
class SrsHttpConn : public SrsConnection class SrsHttpConn : public SrsConnection
{ {
private: private:
SrsHttpParser* parser; SrsHttpParser* parser;
SrsHttpHandler* handler;
public: public:
SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd); SrsHttpConn(SrsServer* srs_server, st_netfd_t client_stfd, SrsHttpHandler* _handler);
virtual ~SrsHttpConn(); virtual ~SrsHttpConn();
protected: protected:
virtual int do_cycle(); virtual int do_cycle();

View file

@ -40,6 +40,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <srs_kernel_utility.hpp> #include <srs_kernel_utility.hpp>
#include <srs_app_http_api.hpp> #include <srs_app_http_api.hpp>
#include <srs_app_http_conn.hpp> #include <srs_app_http_conn.hpp>
#include <srs_app_http.hpp>
#define SERVER_LISTEN_BACKLOG 512 #define SERVER_LISTEN_BACKLOG 512
#define SRS_TIME_RESOLUTION_MS 500 #define SRS_TIME_RESOLUTION_MS 500
@ -160,6 +161,13 @@ SrsServer::SrsServer()
srs_assert(_srs_config); srs_assert(_srs_config);
_srs_config->subscribe(this); _srs_config->subscribe(this);
#ifdef SRS_HTTP_API
http_api_handler = SrsHttpHandler::create_http_api();
#endif
#ifdef SRS_HTTP_SERVER
http_stream_handler = SrsHttpHandler::create_http_stream();
#endif
} }
SrsServer::~SrsServer() SrsServer::~SrsServer()
@ -176,11 +184,32 @@ SrsServer::~SrsServer()
} }
close_listeners(); close_listeners();
#ifdef SRS_HTTP_API
srs_freep(http_api_handler);
#endif
#ifdef SRS_HTTP_SERVER
srs_freep(http_stream_handler);
#endif
} }
int SrsServer::initialize() int SrsServer::initialize()
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
#ifdef SRS_HTTP_API
if ((ret = http_api_handler->initialize()) != ERROR_SUCCESS) {
return ret;
}
#endif
#ifdef SRS_HTTP_SERVER
if ((ret = http_stream_handler->initialize()) != ERROR_SUCCESS) {
return ret;
}
#endif
return ret; return ret;
} }
@ -443,7 +472,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
conn = new SrsRtmpConn(this, client_stfd); conn = new SrsRtmpConn(this, client_stfd);
} else if (type == SrsListenerHttpApi) { } else if (type == SrsListenerHttpApi) {
#ifdef SRS_HTTP_API #ifdef SRS_HTTP_API
conn = new SrsHttpApi(this, client_stfd); conn = new SrsHttpApi(this, client_stfd, http_api_handler);
#else #else
srs_warn("close http client for server not support http-api"); srs_warn("close http client for server not support http-api");
srs_close_stfd(client_stfd); srs_close_stfd(client_stfd);
@ -451,7 +480,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
#endif #endif
} else if (type == SrsListenerHttpStream) { } else if (type == SrsListenerHttpStream) {
#ifdef SRS_HTTP_SERVER #ifdef SRS_HTTP_SERVER
conn = new SrsHttpConn(this, client_stfd); conn = new SrsHttpConn(this, client_stfd, http_stream_handler);
#else #else
srs_warn("close http client for server not support http-server"); srs_warn("close http client for server not support http-server");
srs_close_stfd(client_stfd); srs_close_stfd(client_stfd);

View file

@ -38,6 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
class SrsServer; class SrsServer;
class SrsConnection; class SrsConnection;
class SrsHttpHandler;
// listener type for server to identify the connection, // listener type for server to identify the connection,
// that is, use different type to process the connection. // that is, use different type to process the connection.
@ -75,6 +76,13 @@ public:
class SrsServer : public ISrsReloadHandler class SrsServer : public ISrsReloadHandler
{ {
friend class SrsListener; friend class SrsListener;
private:
#ifdef SRS_HTTP_API
SrsHttpHandler* http_api_handler;
#endif
#ifdef SRS_HTTP_SERVER
SrsHttpHandler* http_stream_handler;
#endif
private: private:
std::vector<SrsConnection*> conns; std::vector<SrsConnection*> conns;
std::vector<SrsListener*> listeners; std::vector<SrsListener*> listeners;

View file

@ -157,6 +157,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_HTTP_PARSE_URI 800 #define ERROR_HTTP_PARSE_URI 800
#define ERROR_HTTP_DATA_INVLIAD 801 #define ERROR_HTTP_DATA_INVLIAD 801
#define ERROR_HTTP_PARSE_HEADER 802 #define ERROR_HTTP_PARSE_HEADER 802
#define ERROR_HTTP_HANDLER_MATCH_URL 803
// system control message, // system control message,
// not an error, but special control logic. // not an error, but special control logic.