fix the http read chunked encoding bug.

pull/133/head
winlin 10 years ago
parent a95fd6d140
commit ea1e015a4e

@ -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.
is_eof = true;
int nb_bytes = srs_min(nb_left_chunk, nb_data); } else {
ret = read_specified(data, nb_bytes, &nb_bytes); // for not the last chunk, there must always exists bytes.
// left bytes in chunk, read some.
srs_assert(nb_left_chunk);
// the nb_bytes used for output already read size of bytes. int nb_bytes = srs_min(nb_left_chunk, nb_data);
if (nb_read) { ret = read_specified(data, nb_bytes, &nb_bytes);
*nb_read = nb_bytes;
}
nb_left_chunk -= nb_bytes;
// error or still left bytes in chunk, ignore and read in future. // the nb_bytes used for output already read size of bytes.
if (nb_left_chunk > 0 || (ret != ERROR_SUCCESS)) { if (nb_read) {
return ret; *nb_read = nb_bytes;
} }
srs_info("http: read %d bytes of chunk", nb_bytes); nb_left_chunk -= nb_bytes;
srs_info("http: read %d bytes of chunk", nb_bytes);
// read payload when length specifies some payload. // error or still left bytes in chunk, ignore and read in future.
if (nb_left_chunk <= 0) { if (nb_left_chunk > 0 || (ret != ERROR_SUCCESS)) {
is_eof = true; 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…
Cancel
Save