From 4325809daf461bf577bc5dbdc1a0d13be435412d Mon Sep 17 00:00:00 2001 From: winlin Date: Thu, 5 Mar 2015 21:45:01 +0800 Subject: [PATCH] refine http --- trunk/configure | 2 +- trunk/ide/srs_qt/srs-qt.pro.user | 73 +++++++++++++++++++++++--- trunk/src/app/srs_app_http.cpp | 25 ++++++++- trunk/src/app/srs_app_http.hpp | 9 ++++ trunk/src/app/srs_app_http_client.cpp | 65 +++++++++++++++++++++-- trunk/src/app/srs_app_http_client.hpp | 11 +++- trunk/src/app/srs_app_rtsp.cpp | 2 +- trunk/src/main/srs_main_server.cpp | 18 +++++++ trunk/src/protocol/srs_rtmp_buffer.hpp | 1 + 9 files changed, 190 insertions(+), 16 deletions(-) diff --git a/trunk/configure b/trunk/configure index 44bb1916a..5489d7aa5 100755 --- a/trunk/configure +++ b/trunk/configure @@ -409,7 +409,7 @@ LIBS_OBJS="${MODULE_OBJS[@]}" if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then MODULE_ID="MAIN" MODULE_DEPENDS=("CORE" "KERNEL" "RTMP" "APP") - ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS_DIR} ${LibGperfRoot}) + ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS_DIR} ${LibGperfRoot} ${LibHttpParserRoot}) MODULE_FILES=("srs_main_server") MAIN_INCS="src/main"; MODULE_DIR=${MAIN_INCS} . auto/modules.sh MAIN_OBJS="${MODULE_OBJS[@]}" diff --git a/trunk/ide/srs_qt/srs-qt.pro.user b/trunk/ide/srs_qt/srs-qt.pro.user index 572bbe375..5d891ca10 100755 --- a/trunk/ide/srs_qt/srs-qt.pro.user +++ b/trunk/ide/srs_qt/srs-qt.pro.user @@ -1,6 +1,6 @@ - + ProjectExplorer.Project.ActiveTarget @@ -56,12 +56,12 @@ Desktop Desktop - {fa2d28f9-85de-4a75-8e79-69d805f974bf} + {fdda5a74-8ef6-4e67-b28c-c5be6c667578} 0 0 0 - /home/winlin/git/simple-rtmp-server/trunk/src/build-qt-Desktop-Debug + /home/winlin/git/simple-rtmp-server/trunk/ide/build-srs-qt-Desktop-Debug true @@ -119,7 +119,66 @@ 2 true - 1 + + /home/winlin/git/simple-rtmp-server/trunk/ide/build-srs-qt-Desktop-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + true + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 2 0 @@ -172,13 +231,13 @@ 2 srs-qt - srs-qt2 + Qt4ProjectManager.Qt4RunConfiguration:/home/winlin/git/simple-rtmp-server/trunk/ide/srs_qt/srs-qt.pro - -c console.conf + srs-qt.pro false true - /home/winlin/srs + 3768 false true diff --git a/trunk/src/app/srs_app_http.cpp b/trunk/src/app/srs_app_http.cpp index ddc971a55..685ee97c8 100644 --- a/trunk/src/app/srs_app_http.cpp +++ b/trunk/src/app/srs_app_http.cpp @@ -904,6 +904,7 @@ int SrsHttpResponseReader::read(int max, std::string& data) SrsHttpMessage::SrsHttpMessage(SrsStSocket* io) { + chunked = false; _uri = new SrsHttpUri(); _body = new SrsHttpResponseReader(this, io); _http_ts_send_buffer = new char[__SRS_HTTP_TS_SEND_BUFFER_SIZE]; @@ -924,6 +925,11 @@ int SrsHttpMessage::initialize(string url, http_parser* header, string body, vec _header = *header; _headers = headers; + // whether chunked. + std::string transfer_encoding = get_request_header("Transfer-Encoding"); + chunked = (transfer_encoding == "chunked"); + + // TODO: FIXME: remove it, use fast buffer instead. if (!body.empty()) { _body->append((char*)body.data(), (int)body.length()); } @@ -1031,6 +1037,11 @@ bool SrsHttpMessage::is_http_options() return _header.method == SRS_CONSTS_HTTP_OPTIONS; } +bool SrsHttpMessage::is_chunked() +{ + return chunked; +} + string SrsHttpMessage::uri() { std::string uri = _uri->get_schema(); @@ -1104,6 +1115,11 @@ int SrsHttpMessage::body_read_all(string body) return ret; } +ISrsHttpResponseReader* SrsHttpMessage::body_reader() +{ + return _body; +} + int64_t SrsHttpMessage::content_length() { return _header.content_length; @@ -1258,6 +1274,11 @@ int SrsHttpParser::parse_message_imp(SrsStSocket* skt) return ret; } } + + // parse last header. + if (!filed_name.empty() && !field_value.empty()) { + headers.push_back(std::make_pair(filed_name, field_value)); + } // when parse completed, cache the left body. if (nread && nparsed < nread) { @@ -1341,7 +1362,7 @@ int SrsHttpParser::on_header_field(http_parser* parser, const char* at, size_t l obj->filed_name.append(at, (int)length); } - srs_trace("Header field(%d bytes): %.*s", (int)length, (int)length, at); + srs_info("Header field(%d bytes): %.*s", (int)length, (int)length, at); return 0; } @@ -1355,7 +1376,7 @@ int SrsHttpParser::on_header_value(http_parser* parser, const char* at, size_t l } obj->expect_filed_name = false; - srs_trace("Header value(%d bytes): %.*s", (int)length, (int)length, at); + srs_info("Header value(%d bytes): %.*s", (int)length, (int)length, at); return 0; } diff --git a/trunk/src/app/srs_app_http.hpp b/trunk/src/app/srs_app_http.hpp index ed6305936..c77cdc352 100644 --- a/trunk/src/app/srs_app_http.hpp +++ b/trunk/src/app/srs_app_http.hpp @@ -49,6 +49,7 @@ class SrsFileReader; class SrsSimpleBuffer; class SrsHttpMuxEntry; class ISrsHttpResponseWriter; +class SrsFastBuffer; // http specification // CR = @@ -442,6 +443,10 @@ private: */ SrsHttpResponseReader* _body; /** + * whether the body is chunked. + */ + bool chunked; + /** * uri parser */ SrsHttpUri* _uri; @@ -474,12 +479,14 @@ public: virtual bool is_http_post(); virtual bool is_http_delete(); virtual bool is_http_options(); + virtual bool is_chunked(); virtual std::string uri(); virtual std::string url(); virtual std::string host(); virtual std::string path(); public: virtual int body_read_all(std::string body); + virtual ISrsHttpResponseReader* body_reader(); virtual int64_t content_length(); /** * get the param in query string, @@ -502,6 +509,8 @@ class SrsHttpParser private: http_parser_settings settings; http_parser parser; + // the global parse buffer. + SrsFastBuffer* fbuffer; private: // http parse data, reset before parse message. bool expect_filed_name; diff --git a/trunk/src/app/srs_app_http_client.cpp b/trunk/src/app/srs_app_http_client.cpp index 298754386..9068082a0 100644 --- a/trunk/src/app/srs_app_http_client.cpp +++ b/trunk/src/app/srs_app_http_client.cpp @@ -45,6 +45,7 @@ SrsHttpClient::SrsHttpClient() connected = false; stfd = NULL; parser = NULL; + skt = NULL; } SrsHttpClient::~SrsHttpClient() @@ -86,10 +87,8 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r << __SRS_HTTP_CRLF << req; - SrsStSocket skt(stfd); - std::string data = ss.str(); - if ((ret = skt.write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) { + if ((ret = skt->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) { // disconnect when error. disconnect(); @@ -98,7 +97,7 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r } SrsHttpMessage* msg = NULL; - if ((ret = parser->parse_message(&skt, &msg)) != ERROR_SUCCESS) { + if ((ret = parser->parse_message(skt, &msg)) != ERROR_SUCCESS) { srs_error("parse http post response failed. ret=%d", ret); return ret; } @@ -119,11 +118,67 @@ int SrsHttpClient::post(SrsHttpUri* uri, string req, int& status_code, string& r return ret; } +int SrsHttpClient::get(SrsHttpUri* uri, std::string req, SrsHttpMessage** ppmsg) +{ + *ppmsg = NULL; + + int ret = ERROR_SUCCESS; + + if (!parser) { + parser = new SrsHttpParser(); + + if ((ret = parser->initialize(HTTP_RESPONSE)) != ERROR_SUCCESS) { + srs_error("initialize parser failed. ret=%d", ret); + return ret; + } + } + + if ((ret = connect(uri)) != ERROR_SUCCESS) { + srs_warn("http connect server failed. ret=%d", ret); + return ret; + } + + // send POST request to uri + // GET %s HTTP/1.1\r\nHost: %s\r\nContent-Length: %d\r\n\r\n%s + std::stringstream ss; + ss << "GET " << uri->get_path() << " " + << "HTTP/1.1" << __SRS_HTTP_CRLF + << "Host: " << uri->get_host() << __SRS_HTTP_CRLF + << "Connection: Keep-Alive" << __SRS_HTTP_CRLF + << "Content-Length: " << std::dec << req.length() << __SRS_HTTP_CRLF + << "User-Agent: " << RTMP_SIG_SRS_NAME << RTMP_SIG_SRS_VERSION << __SRS_HTTP_CRLF + << "Content-Type: application/json" << __SRS_HTTP_CRLF + << __SRS_HTTP_CRLF + << req; + + std::string data = ss.str(); + if ((ret = skt->write((void*)data.c_str(), data.length(), NULL)) != ERROR_SUCCESS) { + // disconnect when error. + disconnect(); + + srs_error("write http get failed. ret=%d", ret); + return ret; + } + + SrsHttpMessage* msg = NULL; + if ((ret = parser->parse_message(skt, &msg)) != ERROR_SUCCESS) { + srs_error("parse http post response failed. ret=%d", ret); + return ret; + } + + srs_assert(msg); + *ppmsg = msg; + srs_info("parse http get response success."); + + return ret; +} + void SrsHttpClient::disconnect() { connected = false; srs_close_stfd(stfd); + srs_freep(skt); } int SrsHttpClient::connect(SrsHttpUri* uri) @@ -149,6 +204,8 @@ int SrsHttpClient::connect(SrsHttpUri* uri) srs_info("connect to server success. http url=%s, server=%s, port=%d", uri->get_url(), uri->get_host(), uri->get_port()); + srs_assert(!skt); + skt = new SrsStSocket(stfd); connected = true; return ret; diff --git a/trunk/src/app/srs_app_http_client.hpp b/trunk/src/app/srs_app_http_client.hpp index 1ffef3bc9..0dbcd2475 100644 --- a/trunk/src/app/srs_app_http_client.hpp +++ b/trunk/src/app/srs_app_http_client.hpp @@ -37,6 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class SrsHttpUri; class SrsHttpParser; +class SrsHttpMessage; +class SrsStSocket; /** * http client to GET/POST/PUT/DELETE uri @@ -46,6 +48,7 @@ class SrsHttpClient private: bool connected; st_netfd_t stfd; + SrsStSocket* skt; SrsHttpParser* parser; public: SrsHttpClient(); @@ -53,11 +56,17 @@ public: public: /** * to post data to the uri. - * @param req the data post to uri. + * @param req the data post to uri. empty string to ignore. * @param status_code the output status code response by server. * @param res output the response data from server. */ virtual int post(SrsHttpUri* uri, std::string req, int& status_code, std::string& res); + /** + * to get data from the uri. + * @param req the data post to uri. empty string to ignore. + * @param ppmsg output the http message to read the response. + */ + virtual int get(SrsHttpUri* uri, std::string req, SrsHttpMessage** ppmsg); private: virtual void disconnect(); virtual int connect(SrsHttpUri* uri); diff --git a/trunk/src/app/srs_app_rtsp.cpp b/trunk/src/app/srs_app_rtsp.cpp index 0747160de..ad1c4f360 100644 --- a/trunk/src/app/srs_app_rtsp.cpp +++ b/trunk/src/app/srs_app_rtsp.cpp @@ -131,7 +131,7 @@ int SrsRtpConn::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) SrsRtspAudioCache::SrsRtspAudioCache() { - dts = NULL; + dts = 0; audio_samples = NULL; payload = NULL; } diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index 783c9a7b9..ebcbbc2c6 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -312,6 +312,8 @@ int run() return run_master(); } +#include +#include int run_master() { int ret = ERROR_SUCCESS; @@ -327,6 +329,22 @@ int run_master() if ((ret = _srs_server->initialize_st()) != ERROR_SUCCESS) { return ret; } +/*SrsHttpClient client; +SrsHttpUri uri; +if ((ret = uri.initialize("http://ossrs.net:8081/live/livestream.flv")) != ERROR_SUCCESS) { + return ret; +} +SrsHttpMessage* msg = NULL; +if ((ret = client.get(&uri, "", &msg)) != ERROR_SUCCESS) { + return ret; +} +for (;;) { + ISrsHttpResponseReader* br = msg->body_reader(); + std::string data; + if ((ret = br->read(0, data)) != ERROR_SUCCESS) { + return ret; + } +}*/ if ((ret = _srs_server->listen()) != ERROR_SUCCESS) { return ret; diff --git a/trunk/src/protocol/srs_rtmp_buffer.hpp b/trunk/src/protocol/srs_rtmp_buffer.hpp index 98f6ec792..9382cbfbc 100644 --- a/trunk/src/protocol/srs_rtmp_buffer.hpp +++ b/trunk/src/protocol/srs_rtmp_buffer.hpp @@ -130,6 +130,7 @@ public: * @param v true to ename merged read. * @param handler the handler when merge read is enabled. * @see https://github.com/winlinvip/simple-rtmp-server/issues/241 + * @remark the merged read is optional, ignore if not specifies. */ virtual void set_merge_read(bool v, IMergeReadHandler* handler); #endif