mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
fix the http read chunked encoding bug.
This commit is contained in:
parent
a95fd6d140
commit
ea1e015a4e
7 changed files with 104 additions and 34 deletions
|
@ -37,6 +37,8 @@ using namespace std;
|
||||||
#include <srs_app_http_conn.hpp>
|
#include <srs_app_http_conn.hpp>
|
||||||
#include <srs_core_autofree.hpp>
|
#include <srs_core_autofree.hpp>
|
||||||
|
|
||||||
|
#define SRS_HTTP_FLV_STREAM_BUFFER 4096
|
||||||
|
|
||||||
SrsAppCasterFlv::SrsAppCasterFlv(SrsConfDirective* c)
|
SrsAppCasterFlv::SrsAppCasterFlv(SrsConfDirective* c)
|
||||||
{
|
{
|
||||||
http_mux = new SrsHttpServeMux();
|
http_mux = new SrsHttpServeMux();
|
||||||
|
@ -62,7 +64,7 @@ int SrsAppCasterFlv::on_tcp_client(st_netfd_t stfd)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
SrsHttpConn* conn = new SrsHttpConn(this, stfd, http_mux);
|
SrsHttpConn* conn = new SrsDynamicHttpConn(this, stfd, http_mux);
|
||||||
conns.push_back(conn);
|
conns.push_back(conn);
|
||||||
|
|
||||||
if ((ret = conn->start()) != ERROR_SUCCESS) {
|
if ((ret = conn->start()) != ERROR_SUCCESS) {
|
||||||
|
@ -79,7 +81,7 @@ void SrsAppCasterFlv::remove(SrsConnection* c)
|
||||||
conns.erase(it);
|
conns.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#define SRS_HTTP_FLV_STREAM_BUFFER 4096
|
|
||||||
int SrsAppCasterFlv::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r)
|
int SrsAppCasterFlv::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
@ -95,10 +97,25 @@ int SrsAppCasterFlv::serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
if ((ret = rr->read(buffer, SRS_HTTP_FLV_STREAM_BUFFER, &nb_read)) != ERROR_SUCCESS) {
|
if ((ret = rr->read(buffer, SRS_HTTP_FLV_STREAM_BUFFER, &nb_read)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
srs_trace("flv: read %dB from %s", nb_read, r->path().c_str());
|
//srs_trace("flv: read %dB from %s", nb_read, r->path().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsDynamicHttpConn::SrsDynamicHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m)
|
||||||
|
: SrsHttpConn(cm, fd, m)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsDynamicHttpConn::~SrsDynamicHttpConn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsDynamicHttpConn::on_got_http_message(SrsHttpMessage* msg)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -43,6 +43,7 @@ class SrsHttpConn;
|
||||||
#include <srs_app_listener.hpp>
|
#include <srs_app_listener.hpp>
|
||||||
#include <srs_app_conn.hpp>
|
#include <srs_app_conn.hpp>
|
||||||
#include <srs_app_http.hpp>
|
#include <srs_app_http.hpp>
|
||||||
|
#include <srs_app_http_conn.hpp>
|
||||||
|
|
||||||
class SrsAppCasterFlv : virtual public ISrsTcpHandler
|
class SrsAppCasterFlv : virtual public ISrsTcpHandler
|
||||||
, virtual public IConnectionManager, virtual public ISrsHttpHandler
|
, virtual public IConnectionManager, virtual public ISrsHttpHandler
|
||||||
|
@ -67,6 +68,15 @@ public:
|
||||||
virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r);
|
virtual int serve_http(ISrsHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SrsDynamicHttpConn : public SrsHttpConn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SrsDynamicHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m);
|
||||||
|
virtual ~SrsDynamicHttpConn();
|
||||||
|
public:
|
||||||
|
virtual int on_got_http_message(SrsHttpMessage* msg);
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -905,6 +905,7 @@ int SrsHttpResponseReader::initialize(SrsFastBuffer* body)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
nb_chunk = 0;
|
||||||
nb_left_chunk = 0;
|
nb_left_chunk = 0;
|
||||||
nb_total_read = 0;
|
nb_total_read = 0;
|
||||||
buffer = body;
|
buffer = body;
|
||||||
|
@ -999,33 +1000,35 @@ int SrsHttpResponseReader::read_chunked(char* data, int nb_data, int* nb_read)
|
||||||
}
|
}
|
||||||
|
|
||||||
// all bytes in chunk is left now.
|
// all bytes in chunk is left now.
|
||||||
nb_left_chunk = ilength;
|
nb_chunk = nb_left_chunk = ilength;
|
||||||
}
|
}
|
||||||
|
|
||||||
// left bytes in chunk, read some.
|
if (nb_chunk <= 0) {
|
||||||
srs_assert(nb_left_chunk);
|
// for the last chunk, eof.
|
||||||
|
|
||||||
int nb_bytes = srs_min(nb_left_chunk, nb_data);
|
|
||||||
ret = read_specified(data, nb_bytes, &nb_bytes);
|
|
||||||
|
|
||||||
// the nb_bytes used for output already read size of bytes.
|
|
||||||
if (nb_read) {
|
|
||||||
*nb_read = nb_bytes;
|
|
||||||
}
|
|
||||||
nb_left_chunk -= nb_bytes;
|
|
||||||
|
|
||||||
// error or still left bytes in chunk, ignore and read in future.
|
|
||||||
if (nb_left_chunk > 0 || (ret != ERROR_SUCCESS)) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
srs_info("http: read %d bytes of chunk", nb_bytes);
|
|
||||||
|
|
||||||
// read payload when length specifies some payload.
|
|
||||||
if (nb_left_chunk <= 0) {
|
|
||||||
is_eof = true;
|
is_eof = true;
|
||||||
|
} else {
|
||||||
|
// for not the last chunk, there must always exists bytes.
|
||||||
|
// left bytes in chunk, read some.
|
||||||
|
srs_assert(nb_left_chunk);
|
||||||
|
|
||||||
|
int nb_bytes = srs_min(nb_left_chunk, nb_data);
|
||||||
|
ret = read_specified(data, nb_bytes, &nb_bytes);
|
||||||
|
|
||||||
|
// the nb_bytes used for output already read size of bytes.
|
||||||
|
if (nb_read) {
|
||||||
|
*nb_read = nb_bytes;
|
||||||
|
}
|
||||||
|
nb_left_chunk -= nb_bytes;
|
||||||
|
srs_info("http: read %d bytes of chunk", nb_bytes);
|
||||||
|
|
||||||
|
// error or still left bytes in chunk, ignore and read in future.
|
||||||
|
if (nb_left_chunk > 0 || (ret != ERROR_SUCCESS)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
srs_info("http: read total chunk %dB", nb_chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the CRLF of chunk payload end.
|
// for both the last or not, the CRLF of chunk payload end.
|
||||||
if ((ret = buffer->grow(skt, 2)) != ERROR_SUCCESS) {
|
if ((ret = buffer->grow(skt, 2)) != ERROR_SUCCESS) {
|
||||||
if (!srs_is_client_gracefully_close(ret)) {
|
if (!srs_is_client_gracefully_close(ret)) {
|
||||||
srs_error("read EOF of chunk from server failed. ret=%d", ret);
|
srs_error("read EOF of chunk from server failed. ret=%d", ret);
|
||||||
|
@ -1064,9 +1067,12 @@ int SrsHttpResponseReader::read_specified(char* data, int nb_data, int* nb_read)
|
||||||
// increase the total read to determine whether EOF.
|
// increase the total read to determine whether EOF.
|
||||||
nb_total_read += nb_bytes;
|
nb_total_read += nb_bytes;
|
||||||
|
|
||||||
// when read completed, eof.
|
// for not chunked
|
||||||
if (nb_total_read >= (int)owner->content_length()) {
|
if (!owner->is_chunked()) {
|
||||||
is_eof = true;
|
// when read completed, eof.
|
||||||
|
if (nb_total_read >= (int)owner->content_length()) {
|
||||||
|
is_eof = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -436,6 +436,8 @@ private:
|
||||||
bool is_eof;
|
bool is_eof;
|
||||||
// the left bytes in chunk.
|
// the left bytes in chunk.
|
||||||
int nb_left_chunk;
|
int nb_left_chunk;
|
||||||
|
// the number of bytes of current chunk.
|
||||||
|
int nb_chunk;
|
||||||
// already read total bytes.
|
// already read total bytes.
|
||||||
int64_t nb_total_read;
|
int64_t nb_total_read;
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1398,11 +1398,8 @@ int SrsHttpConn::do_cycle()
|
||||||
// always free it in this scope.
|
// always free it in this scope.
|
||||||
SrsAutoFree(SrsHttpMessage, req);
|
SrsAutoFree(SrsHttpMessage, req);
|
||||||
|
|
||||||
// TODO: FIXME: use the post body.
|
// may should discard the body.
|
||||||
std::string res;
|
if ((ret = on_got_http_message(req)) != ERROR_SUCCESS) {
|
||||||
|
|
||||||
// get response body.
|
|
||||||
if ((ret = req->body_read_all(res)) != ERROR_SUCCESS) {
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1434,5 +1431,29 @@ int SrsHttpConn::process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrsStaticHttpConn::SrsStaticHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m)
|
||||||
|
: SrsHttpConn(cm, fd, m)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsStaticHttpConn::~SrsStaticHttpConn()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsStaticHttpConn::on_got_http_message(SrsHttpMessage* msg)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
// TODO: FIXME: use the post body.
|
||||||
|
std::string res;
|
||||||
|
|
||||||
|
// get response body.
|
||||||
|
if ((ret = msg->body_read_all(res)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -388,10 +388,24 @@ public:
|
||||||
virtual void cleanup();
|
virtual void cleanup();
|
||||||
protected:
|
protected:
|
||||||
virtual int do_cycle();
|
virtual int do_cycle();
|
||||||
|
protected:
|
||||||
|
// when got http message,
|
||||||
|
// for the static service or api, discard any body.
|
||||||
|
// for the stream caster, for instance, http flv streaming, may discard the flv header or not.
|
||||||
|
virtual int on_got_http_message(SrsHttpMessage* msg) = 0;
|
||||||
private:
|
private:
|
||||||
virtual int process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r);
|
virtual int process_request(ISrsHttpResponseWriter* w, SrsHttpMessage* r);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SrsStaticHttpConn : public SrsHttpConn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SrsStaticHttpConn(IConnectionManager* cm, st_netfd_t fd, SrsHttpServeMux* m);
|
||||||
|
virtual ~SrsStaticHttpConn();
|
||||||
|
public:
|
||||||
|
virtual int on_got_http_message(SrsHttpMessage* msg);
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1163,7 +1163,7 @@ int SrsServer::accept_client(SrsListenerType type, st_netfd_t client_stfd)
|
||||||
#endif
|
#endif
|
||||||
} else if (type == SrsListenerHttpStream) {
|
} else if (type == SrsListenerHttpStream) {
|
||||||
#ifdef SRS_AUTO_HTTP_SERVER
|
#ifdef SRS_AUTO_HTTP_SERVER
|
||||||
conn = new SrsHttpConn(this, client_stfd, &http_stream_mux->mux);
|
conn = new SrsStaticHttpConn(this, client_stfd, &http_stream_mux->mux);
|
||||||
#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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue