diff --git a/trunk/src/app/srs_app_http.cpp b/trunk/src/app/srs_app_http.cpp index 16409aef3..d156c6ce3 100644 --- a/trunk/src/app/srs_app_http.cpp +++ b/trunk/src/app/srs_app_http.cpp @@ -495,6 +495,14 @@ SrsHttpMuxEntry::~SrsHttpMuxEntry() srs_freep(handler); } +ISrsHttpMatchHijacker::ISrsHttpMatchHijacker() +{ +} + +ISrsHttpMatchHijacker::~ISrsHttpMatchHijacker() +{ +} + SrsHttpServeMux::SrsHttpServeMux() { } @@ -509,6 +517,7 @@ SrsHttpServeMux::~SrsHttpServeMux() entries.clear(); vhosts.clear(); + hijackers.clear(); } int SrsHttpServeMux::initialize() @@ -518,6 +527,24 @@ int SrsHttpServeMux::initialize() return ret; } +void SrsHttpServeMux::hijack(ISrsHttpMatchHijacker* h) +{ + std::vector::iterator it = ::find(hijackers.begin(), hijackers.end(), h); + if (it != hijackers.end()) { + return; + } + hijackers.push_back(h); +} + +void SrsHttpServeMux::unhijack(ISrsHttpMatchHijacker* h) +{ + std::vector::iterator it = ::find(hijackers.begin(), hijackers.end(), h); + if (it == hijackers.end()) { + return; + } + hijackers.erase(it); +} + int SrsHttpServeMux::handle(std::string pattern, ISrsHttpHandler* handler) { int ret = ERROR_SUCCESS; @@ -629,8 +656,22 @@ int SrsHttpServeMux::find_handler(SrsHttpMessage* r, ISrsHttpHandler** ph) srs_error("http match handler failed. ret=%d", ret); return ret; } + + // always hijack. + if (!hijackers.empty()) { + // notice all hijacker the match failed. + std::vector::iterator it; + for (it = hijackers.begin(); it != hijackers.end(); ++it) { + ISrsHttpMatchHijacker* hijacker = *it; + if ((ret = hijacker->hijack(r, ph)) != ERROR_SUCCESS) { + srs_error("hijacker match failed. ret=%d", ret); + return ret; + } + } + } if (*ph == NULL) { + // TODO: FIXME: memory leak. *ph = new SrsHttpNotFoundHandler(); } @@ -1066,6 +1107,14 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, _query[k] = v; } + // parse ext. + _ext = _uri->get_path(); + if ((pos = _ext.rfind(".")) != string::npos) { + _ext = _ext.substr(pos); + } else { + _ext = ""; + } + return ret; } @@ -1162,6 +1211,11 @@ string SrsHttpMessage::path() return _uri->get_path(); } +string SrsHttpMessage::ext() +{ + return _ext; +} + int SrsHttpMessage::body_read_all(string& body) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_http.hpp b/trunk/src/app/srs_app_http.hpp index 563b92953..c056cb2dd 100644 --- a/trunk/src/app/srs_app_http.hpp +++ b/trunk/src/app/srs_app_http.hpp @@ -288,6 +288,7 @@ protected: }; // the mux entry for server mux. +// the matcher info, for example, the pattern and handler. class SrsHttpMuxEntry { public: @@ -300,6 +301,23 @@ public: virtual ~SrsHttpMuxEntry(); }; +/** +* the hijacker for http pattern match. +*/ +class ISrsHttpMatchHijacker +{ +public: + ISrsHttpMatchHijacker(); + virtual ~ISrsHttpMatchHijacker(); +public: + /** + * when match the request failed, no handler to process request. + * @param request the http request message to match the handler. + * @param ph the already matched handler, hijack can rewrite it. + */ + virtual int hijack(SrsHttpMessage* request, ISrsHttpHandler** ph) = 0; +}; + // ServeMux is an HTTP request multiplexer. // It matches the URL of each incoming request against a list of registered // patterns and calls the handler for the pattern that @@ -338,6 +356,10 @@ private: // for example, for pattern /live/livestream.flv of vhost ossrs.net, // the path will rewrite to ossrs.net/live/livestream.flv std::map vhosts; + // all hijackers for http match. + // for example, the hstrs(http stream trigger rtmp source) + // can hijack and install handler when request incoming and no handler. + std::vector hijackers; public: SrsHttpServeMux(); virtual ~SrsHttpServeMux(); @@ -346,6 +368,11 @@ public: * initialize the http serve mux. */ virtual int initialize(); + /** + * hijack the http match. + */ + virtual void hijack(ISrsHttpMatchHijacker* h); + virtual void unhijack(ISrsHttpMatchHijacker* h); public: // Handle registers the handler for the given pattern. // If a handler already exists for pattern, Handle panics. @@ -442,6 +469,10 @@ private: */ std::string _url; /** + * the extension of file, for example, .flv + */ + std::string _ext; + /** * parsed http header. */ http_parser _header; @@ -505,6 +536,7 @@ public: virtual std::string url(); virtual std::string host(); virtual std::string path(); + virtual std::string ext(); public: /** * read body to string. diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index c9ccee95e..33dcd4143 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -689,10 +689,43 @@ int SrsLiveStream::streaming_send_messages(ISrsStreamEncoder* enc, SrsSharedPtrM return ret; } -SrsLiveEntry::SrsLiveEntry() +SrsLiveEntry::SrsLiveEntry(std::string m, bool h) { + mount = m; + hstrs = h; + stream = NULL; cache = NULL; + + std::string ext; + size_t pos = string::npos; + if ((pos = m.rfind(".")) != string::npos) { + ext = m.substr(pos); + } + _is_flv = (ext == ".flv"); + _is_ts = (ext == ".ts"); + _is_mp3 = (ext == ".mp3"); + _is_aac = (ext == ".aac"); +} + +bool SrsLiveEntry::is_flv() +{ + return _is_flv; +} + +bool SrsLiveEntry::is_ts() +{ + return _is_ts; +} + +bool SrsLiveEntry::is_aac() +{ + return _is_aac; +} + +bool SrsLiveEntry::is_mp3() +{ + return _is_mp3; } SrsHlsM3u8Stream::SrsHlsM3u8Stream() @@ -765,10 +798,13 @@ SrsHlsEntry::SrsHlsEntry() SrsHttpServer::SrsHttpServer() { + mux.hijack(this); } SrsHttpServer::~SrsHttpServer() { + mux.unhijack(this); + if (true) { std::map::iterator it; for (it = tflvs.begin(); it != tflvs.end(); ++it) { @@ -853,8 +889,7 @@ int SrsHttpServer::http_mount(SrsSource* s, SrsRequest* r) // remove the default vhost mount mount = srs_string_replace(mount, SRS_CONSTS_RTMP_DEFAULT_VHOST"/", "/"); - entry = new SrsLiveEntry(); - entry->mount = mount; + entry = new SrsLiveEntry(mount, tmpl->hstrs); entry->cache = new SrsStreamCache(s, r); entry->stream = new SrsLiveStream(s, r, entry->cache); @@ -1060,6 +1095,29 @@ int SrsHttpServer::on_reload_vhost_hls(string vhost) return ret; } +int SrsHttpServer::hijack(SrsHttpMessage* request, ISrsHttpHandler** ph) +{ + int ret = ERROR_SUCCESS; + + // when handler not the root, we think the handler is ok. + ISrsHttpHandler* h = ph? *ph : NULL; + if (h->entry && h->entry->pattern != "/") { + return ret; + } + + // only hijack for http streaming, http-flv/ts/mp3/aac. + std::string ext = request->ext(); + if (ext.empty()) { + return ret; + } + if (ext != ".flv" && ext != ".ts" && ext != ".mp3" && ext != ".aac") { + return ret; + } + + // TODO: FIXME: implements it. + return ret; +} + int SrsHttpServer::initialize_static_file() { int ret = ERROR_SUCCESS; @@ -1138,8 +1196,10 @@ int SrsHttpServer::initialize_flv_streaming() continue; } - SrsLiveEntry* entry = new SrsLiveEntry(); - entry->mount = _srs_config->get_vhost_http_remux_mount(vhost); + SrsLiveEntry* entry = new SrsLiveEntry( + _srs_config->get_vhost_http_remux_mount(vhost), + _srs_config->get_vhost_http_remux_hstrs(vhost) + ); tflvs[vhost] = entry; srs_trace("http flv live stream, vhost=%s, mount=%s", vhost.c_str(), entry->mount.c_str()); diff --git a/trunk/src/app/srs_app_http_conn.hpp b/trunk/src/app/srs_app_http_conn.hpp index f1d65cef5..6d4b02672 100644 --- a/trunk/src/app/srs_app_http_conn.hpp +++ b/trunk/src/app/srs_app_http_conn.hpp @@ -252,14 +252,27 @@ private: */ struct SrsLiveEntry { +private: + bool _is_flv; + bool _is_ts; + bool _is_aac; + bool _is_mp3; +public: // for template, the mount contains variables. // for concrete stream, the mount is url to access. std::string mount; + // whether hstrs(http stream trigger rtmp source) + bool hstrs; SrsLiveStream* stream; SrsStreamCache* cache; - SrsLiveEntry(); + SrsLiveEntry(std::string m, bool h); + + bool is_flv(); + bool is_ts(); + bool is_mp3(); + bool is_aac(); }; /** @@ -314,13 +327,14 @@ struct SrsHlsEntry * the http server instance, * serve http static file, flv vod stream and flv live stream. */ -class SrsHttpServer : public ISrsReloadHandler +class SrsHttpServer : virtual public ISrsReloadHandler + , virtual public ISrsHttpMatchHijacker { public: SrsHttpServeMux mux; - // the flv live streaming template, to create streams. + // the http live streaming template, to create streams. std::map tflvs; - // the flv live streaming streams, crote by template. + // the http live streaming streams, crote by template. std::map sflvs; // the hls live streaming template, to create streams. std::map thls; @@ -346,6 +360,9 @@ public: virtual int on_reload_vhost_http_updated(); virtual int on_reload_vhost_http_remux_updated(); virtual int on_reload_vhost_hls(std::string vhost); +// interface ISrsHttpMatchHijacker +public: + virtual int hijack(SrsHttpMessage* request, ISrsHttpHandler** ph); private: virtual int initialize_static_file(); virtual int initialize_flv_streaming();