winlin

merge from srs2

@@ -1414,8 +1414,12 @@ int SrsHttpApi::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) @@ -1414,8 +1414,12 @@ int SrsHttpApi::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
1414 { 1414 {
1415 int ret = ERROR_SUCCESS; 1415 int ret = ERROR_SUCCESS;
1416 1416
1417 - srs_trace("HTTP %s %s, content-length=%"PRId64"",  
1418 - r->method_str().c_str(), r->url().c_str(), r->content_length()); 1417 + SrsHttpMessage* hm = dynamic_cast<SrsHttpMessage*>(r);
  1418 + srs_assert(hm);
  1419 +
  1420 + srs_trace("HTTP API %s %s, content-length=%"PRId64", chunked=%d/%d",
  1421 + r->method_str().c_str(), r->url().c_str(), r->content_length(),
  1422 + hm->is_chunked(), hm->is_infinite_chunked());
1419 1423
1420 // method is OPTIONS and enable crossdomain, required crossdomain header. 1424 // method is OPTIONS and enable crossdomain, required crossdomain header.
1421 if (r->is_http_options() && _srs_config->get_http_api_crossdomain()) { 1425 if (r->is_http_options() && _srs_config->get_http_api_crossdomain()) {
@@ -357,15 +357,29 @@ int SrsHttpResponseReader::read(char* data, int nb_data, int* nb_read) @@ -357,15 +357,29 @@ int SrsHttpResponseReader::read(char* data, int nb_data, int* nb_read)
357 } 357 }
358 358
359 // read by specified content-length 359 // read by specified content-length
360 - int max = (int)owner->content_length() - (int)nb_total_read;  
361 - if (max <= 0) {  
362 - is_eof = true;  
363 - return ret; 360 + if (owner->content_length() != -1) {
  361 + int max = (int)owner->content_length() - (int)nb_total_read;
  362 + if (max <= 0) {
  363 + is_eof = true;
  364 + return ret;
  365 + }
  366 +
  367 + // change the max to read.
  368 + nb_data = srs_min(nb_data, max);
  369 + return read_specified(data, nb_data, nb_read);
364 } 370 }
365 371
366 - // change the max to read.  
367 - nb_data = srs_min(nb_data, max);  
368 - return read_specified(data, nb_data, nb_read); 372 + // infinite chunked mode, directly read.
  373 + if (owner->is_infinite_chunked()) {
  374 + srs_assert(!owner->is_chunked() && owner->content_length() == -1);
  375 + return read_specified(data, nb_data, nb_read);
  376 + }
  377 +
  378 + // infinite chunked mode, but user not set it,
  379 + // we think there is no data left.
  380 + is_eof = true;
  381 +
  382 + return ret;
369 } 383 }
370 384
371 int SrsHttpResponseReader::read_chunked(char* data, int nb_data, int* nb_read) 385 int SrsHttpResponseReader::read_chunked(char* data, int nb_data, int* nb_read)
@@ -505,6 +519,7 @@ SrsHttpMessage::SrsHttpMessage(ISrsProtocolReaderWriter* io, SrsConnection* c) : @@ -505,6 +519,7 @@ SrsHttpMessage::SrsHttpMessage(ISrsProtocolReaderWriter* io, SrsConnection* c) :
505 { 519 {
506 conn = c; 520 conn = c;
507 chunked = false; 521 chunked = false;
  522 + infinite_chunked = false;
508 keep_alive = true; 523 keep_alive = true;
509 _uri = new SrsHttpUri(); 524 _uri = new SrsHttpUri();
510 _body = new SrsHttpResponseReader(this, io); 525 _body = new SrsHttpResponseReader(this, io);
@@ -660,6 +675,11 @@ bool SrsHttpMessage::is_keep_alive() @@ -660,6 +675,11 @@ bool SrsHttpMessage::is_keep_alive()
660 return keep_alive; 675 return keep_alive;
661 } 676 }
662 677
  678 +bool SrsHttpMessage::is_infinite_chunked()
  679 +{
  680 + return infinite_chunked;
  681 +}
  682 +
663 string SrsHttpMessage::uri() 683 string SrsHttpMessage::uri()
664 { 684 {
665 std::string uri = _uri->get_schema(); 685 std::string uri = _uri->get_schema();
@@ -714,6 +734,25 @@ int SrsHttpMessage::parse_rest_id(string pattern) @@ -714,6 +734,25 @@ int SrsHttpMessage::parse_rest_id(string pattern)
714 return -1; 734 return -1;
715 } 735 }
716 736
  737 +int SrsHttpMessage::enter_infinite_chunked()
  738 +{
  739 + int ret = ERROR_SUCCESS;
  740 +
  741 + if (infinite_chunked) {
  742 + return ret;
  743 + }
  744 +
  745 + if (is_chunked() || content_length() != -1) {
  746 + ret = ERROR_HTTP_DATA_INVALID;
  747 + srs_error("infinite chunkted not supported in specified codec. ret=%d", ret);
  748 + return ret;
  749 + }
  750 +
  751 + infinite_chunked = true;
  752 +
  753 + return ret;
  754 +}
  755 +
717 int SrsHttpMessage::body_read_all(string& body) 756 int SrsHttpMessage::body_read_all(string& body)
718 { 757 {
719 int ret = ERROR_SUCCESS; 758 int ret = ERROR_SUCCESS;
@@ -152,9 +152,6 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField; @@ -152,9 +152,6 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField;
152 // The field semantics differ slightly between client and server 152 // The field semantics differ slightly between client and server
153 // usage. In addition to the notes on the fields below, see the 153 // usage. In addition to the notes on the fields below, see the
154 // documentation for Request.Write and RoundTripper. 154 // documentation for Request.Write and RoundTripper.
155 -/**  
156 - * the http message, request or response.  
157 - */  
158 class SrsHttpMessage : public ISrsHttpMessage 155 class SrsHttpMessage : public ISrsHttpMessage
159 { 156 {
160 private: 157 private:
@@ -180,6 +177,10 @@ private: @@ -180,6 +177,10 @@ private:
180 */ 177 */
181 bool chunked; 178 bool chunked;
182 /** 179 /**
  180 + * whether the body is infinite chunked.
  181 + */
  182 + bool infinite_chunked;
  183 + /**
183 * whether the request indicates should keep alive 184 * whether the request indicates should keep alive
184 * for the http connection. 185 * for the http connection.
185 */ 186 */
@@ -232,6 +233,11 @@ public: @@ -232,6 +233,11 @@ public:
232 */ 233 */
233 virtual bool is_chunked(); 234 virtual bool is_chunked();
234 /** 235 /**
  236 + * whether body is infinite chunked encoding.
  237 + * @remark set by enter_infinite_chunked.
  238 + */
  239 + virtual bool is_infinite_chunked();
  240 + /**
235 * whether should keep the connection alive. 241 * whether should keep the connection alive.
236 */ 242 */
237 virtual bool is_keep_alive(); 243 virtual bool is_keep_alive();
@@ -252,6 +258,8 @@ public: @@ -252,6 +258,8 @@ public:
252 */ 258 */
253 virtual int parse_rest_id(std::string pattern); 259 virtual int parse_rest_id(std::string pattern);
254 public: 260 public:
  261 + virtual int enter_infinite_chunked();
  262 +public:
255 /** 263 /**
256 * read body to string. 264 * read body to string.
257 * @remark for small http body. 265 * @remark for small http body.
@@ -231,6 +231,12 @@ public: @@ -231,6 +231,12 @@ public:
231 * @param nb_data, the max size of data buffer. 231 * @param nb_data, the max size of data buffer.
232 * @param nb_read, the actual read size of bytes. NULL to ignore. 232 * @param nb_read, the actual read size of bytes. NULL to ignore.
233 * @remark when eof(), return error. 233 * @remark when eof(), return error.
  234 + * @remark for some server, the content-length not specified and not chunked,
  235 + * which is actually the infinite chunked encoding, which after http header
  236 + * is http response data, it's ok for browser. that is,
  237 + * when user call this read, please ensure there is data to read(by content-length
  238 + * or by chunked), because the sdk never know whether there is no data or
  239 + * infinite chunked.
234 */ 240 */
235 virtual int read(char* data, int nb_data, int* nb_read) = 0; 241 virtual int read(char* data, int nb_data, int* nb_read) = 0;
236 }; 242 };
@@ -445,9 +451,19 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField; @@ -445,9 +451,19 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField;
445 // The field semantics differ slightly between client and server 451 // The field semantics differ slightly between client and server
446 // usage. In addition to the notes on the fields below, see the 452 // usage. In addition to the notes on the fields below, see the
447 // documentation for Request.Write and RoundTripper. 453 // documentation for Request.Write and RoundTripper.
448 -/**  
449 - * the http message, request or response.  
450 - */ 454 +//
  455 +// There are some modes to determine the length of body:
  456 +// 1. content-length and chunked.
  457 +// 2. user confirmed infinite chunked.
  458 +// 3. no body or user not confirmed infinite chunked.
  459 +// For example:
  460 +// ISrsHttpMessage* r = ...;
  461 +// while (!r->eof()) r->read(); // read in mode 1 or 3.
  462 +// For some server, we can confirm the body is infinite chunked:
  463 +// ISrsHttpMessage* r = ...;
  464 +// r->enter_infinite_chunked();
  465 +// while (!r->eof()) r->read(); // read in mode 2
  466 +// @rmark for mode 2, the infinite chunked, all left data is body.
451 class ISrsHttpMessage 467 class ISrsHttpMessage
452 { 468 {
453 private: 469 private:
@@ -503,6 +519,12 @@ public: @@ -503,6 +519,12 @@ public:
503 virtual int parse_rest_id(std::string pattern) = 0; 519 virtual int parse_rest_id(std::string pattern) = 0;
504 public: 520 public:
505 /** 521 /**
  522 + * the left all data is chunked body, the infinite chunked mode,
  523 + * which is chunked encoding without chunked header.
  524 + * @remark error when message is in chunked or content-length specified.
  525 + */
  526 + virtual int enter_infinite_chunked() = 0;
  527 + /**
506 * read body to string. 528 * read body to string.
507 * @remark for small http body. 529 * @remark for small http body.
508 */ 530 */