From b04888a35d240ea33a2f67d8e04e2dc4516a0d8f Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 19 Jan 2015 01:05:24 +0800 Subject: [PATCH] for #293, #277, support http chunked encoding --- trunk/src/app/srs_app_http.cpp | 45 +++++++++++++++++++++++++++-- trunk/src/app/srs_app_http.hpp | 5 ++++ trunk/src/app/srs_app_http_conn.cpp | 2 +- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/trunk/src/app/srs_app_http.cpp b/trunk/src/app/srs_app_http.cpp index ba235dba4c..8af5710218 100644 --- a/trunk/src/app/srs_app_http.cpp +++ b/trunk/src/app/srs_app_http.cpp @@ -339,7 +339,8 @@ int SrsGoHttpFileServer::serve_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* int64_t length = fs.filesize(); - w->header()->set_content_length(length); + // unset the content length in chunked encoding. + //w->header()->set_content_length(length); static std::map _mime; if (_mime.empty()) { @@ -391,7 +392,7 @@ int SrsGoHttpFileServer::serve_file(ISrsGoHttpResponseWriter* w, SrsHttpMessage* return ret; } - return ret; + return w->final_request(); } int SrsGoHttpFileServer::serve_flv_stream(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r, string fullpath, int offset) @@ -653,6 +654,20 @@ SrsGoHttpResponseWriter::~SrsGoHttpResponseWriter() srs_freep(hdr); } +int SrsGoHttpResponseWriter::final_request() +{ + // complete the chunked encoding. + if (content_length == -1) { + std::stringstream ss; + ss << 0 << __SRS_CRLF << __SRS_CRLF; + std::string ch = ss.str(); + return skt->write((void*)ch.data(), (int)ch.length(), NULL); + } + + // ignore when send with content length + return ERROR_SUCCESS; +} + SrsGoHttpHeader* SrsGoHttpResponseWriter::header() { return hdr; @@ -678,7 +693,26 @@ int SrsGoHttpResponseWriter::write(char* data, int size) return ret; } - return skt->write((void*)data, size, NULL); + // directly send with content length + if (content_length != -1) { + return skt->write((void*)data, size, NULL); + } + + // send in chunked encoding. + std::stringstream ss; + ss << hex << size << __SRS_CRLF; + std::string ch = ss.str(); + if ((ret = skt->write((void*)ch.data(), (int)ch.length(), NULL)) != ERROR_SUCCESS) { + return ret; + } + if ((ret = skt->write((void*)data, size, NULL)) != ERROR_SUCCESS) { + return ret; + } + if ((ret = skt->write((void*)__SRS_CRLF, 2, NULL)) != ERROR_SUCCESS) { + return ret; + } + + return ret; } void SrsGoHttpResponseWriter::write_header(int code) @@ -722,6 +756,11 @@ int SrsGoHttpResponseWriter::send_header(char* data, int size) hdr->set("Server", RTMP_SIG_SRS_KEY"/"RTMP_SIG_SRS_VERSION); } + // chunked encoding + if (content_length == -1) { + hdr->set("Transfer-Encoding", "chunked"); + } + // write headers hdr->write(ss); diff --git a/trunk/src/app/srs_app_http.hpp b/trunk/src/app/srs_app_http.hpp index a73a7a9e23..5ca2de67bc 100644 --- a/trunk/src/app/srs_app_http.hpp +++ b/trunk/src/app/srs_app_http.hpp @@ -128,6 +128,10 @@ class ISrsGoHttpResponseWriter ISrsGoHttpResponseWriter(); virtual ~ISrsGoHttpResponseWriter(); public: + // when chunked mode, + // final the request to complete the chunked encoding. + virtual int final_request() = 0; + // Header returns the header map that will be sent by WriteHeader. // Changing the header after a call to WriteHeader (or Write) has // no effect. @@ -319,6 +323,7 @@ class SrsGoHttpResponseWriter : public ISrsGoHttpResponseWriter SrsGoHttpResponseWriter(SrsStSocket* io); virtual ~SrsGoHttpResponseWriter(); public: + virtual int final_request(); virtual SrsGoHttpHeader* header(); virtual int write(char* data, int size); virtual void write_header(int code); diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index a90b2dc8ab..17686c0219 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -304,7 +304,7 @@ int SrsLiveStream::serve_http(ISrsGoHttpResponseWriter* w, SrsHttpMessage* r) // TODO: FIMXE: add pithy print. // write http header for streaming. - w->header()->set_content_length((int64_t)2 * 1024 * 1024 * 1024); + // use chunked encoding, for we donot specifes the content length. if (serve_flv_streaming) { w->header()->set_content_type("video/x-flv"); }