正在显示
4 个修改的文件
包含
88 行增加
和
15 行删除
| @@ -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 | */ |
-
请 注册 或 登录 后发表评论