正在显示
8 个修改的文件
包含
160 行增加
和
23 行删除
| @@ -338,6 +338,7 @@ Remark: | @@ -338,6 +338,7 @@ Remark: | ||
| 338 | 338 | ||
| 339 | ## History | 339 | ## History |
| 340 | 340 | ||
| 341 | +* v2.0, 2016-01-13, fix http reader bug, support infinite chunkted. 2.0.209 | ||
| 341 | * v2.0, 2016-01-09, merge [#559][pr #559] fix memory leak bug. 2.0.208 | 342 | * v2.0, 2016-01-09, merge [#559][pr #559] fix memory leak bug. 2.0.208 |
| 342 | * v2.0, 2016-01-09, merge [#558][pr #558] add tcUrl for on_publish. | 343 | * v2.0, 2016-01-09, merge [#558][pr #558] add tcUrl for on_publish. |
| 343 | * v2.0, 2016-01-05, add keyword XCORE for coredump to identify the version. 2.0.207 | 344 | * v2.0, 2016-01-05, add keyword XCORE for coredump to identify the version. 2.0.207 |
trunk/src/app/srs_app_http_api.cpp
100755 → 100644
| @@ -950,8 +950,12 @@ int SrsHttpApi::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) | @@ -950,8 +950,12 @@ int SrsHttpApi::process_request(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) | ||
| 950 | { | 950 | { |
| 951 | int ret = ERROR_SUCCESS; | 951 | int ret = ERROR_SUCCESS; |
| 952 | 952 | ||
| 953 | - srs_trace("HTTP %s %s, content-length=%"PRId64"", | ||
| 954 | - r->method_str().c_str(), r->url().c_str(), r->content_length()); | 953 | + SrsHttpMessage* hm = dynamic_cast<SrsHttpMessage*>(r); |
| 954 | + srs_assert(hm); | ||
| 955 | + | ||
| 956 | + srs_trace("HTTP API %s %s, content-length=%"PRId64", chunked=%d/%d", | ||
| 957 | + r->method_str().c_str(), r->url().c_str(), r->content_length(), | ||
| 958 | + hm->is_chunked(), hm->is_infinite_chunked()); | ||
| 955 | 959 | ||
| 956 | // method is OPTIONS and enable crossdomain, required crossdomain header. | 960 | // method is OPTIONS and enable crossdomain, required crossdomain header. |
| 957 | if (r->is_http_options() && _srs_config->get_http_api_crossdomain()) { | 961 | if (r->is_http_options() && _srs_config->get_http_api_crossdomain()) { |
| @@ -55,6 +55,7 @@ using namespace std; | @@ -55,6 +55,7 @@ using namespace std; | ||
| 55 | #include <srs_app_http_static.hpp> | 55 | #include <srs_app_http_static.hpp> |
| 56 | #include <srs_app_http_stream.hpp> | 56 | #include <srs_app_http_stream.hpp> |
| 57 | #include <srs_app_http_api.hpp> | 57 | #include <srs_app_http_api.hpp> |
| 58 | +#include <srs_app_utility.hpp> | ||
| 58 | 59 | ||
| 59 | #endif | 60 | #endif |
| 60 | 61 | ||
| @@ -347,15 +348,29 @@ int SrsHttpResponseReader::read(char* data, int nb_data, int* nb_read) | @@ -347,15 +348,29 @@ int SrsHttpResponseReader::read(char* data, int nb_data, int* nb_read) | ||
| 347 | } | 348 | } |
| 348 | 349 | ||
| 349 | // read by specified content-length | 350 | // read by specified content-length |
| 350 | - int max = (int)owner->content_length() - (int)nb_total_read; | ||
| 351 | - if (max <= 0) { | ||
| 352 | - is_eof = true; | ||
| 353 | - return ret; | 351 | + if (owner->content_length() != -1) { |
| 352 | + int max = (int)owner->content_length() - (int)nb_total_read; | ||
| 353 | + if (max <= 0) { | ||
| 354 | + is_eof = true; | ||
| 355 | + return ret; | ||
| 356 | + } | ||
| 357 | + | ||
| 358 | + // change the max to read. | ||
| 359 | + nb_data = srs_min(nb_data, max); | ||
| 360 | + return read_specified(data, nb_data, nb_read); | ||
| 361 | + } | ||
| 362 | + | ||
| 363 | + // infinite chunked mode, directly read. | ||
| 364 | + if (owner->is_infinite_chunked()) { | ||
| 365 | + srs_assert(!owner->is_chunked() && owner->content_length() == -1); | ||
| 366 | + return read_specified(data, nb_data, nb_read); | ||
| 354 | } | 367 | } |
| 355 | 368 | ||
| 356 | - // change the max to read. | ||
| 357 | - nb_data = srs_min(nb_data, max); | ||
| 358 | - return read_specified(data, nb_data, nb_read); | 369 | + // infinite chunked mode, but user not set it, |
| 370 | + // we think there is no data left. | ||
| 371 | + is_eof = true; | ||
| 372 | + | ||
| 373 | + return ret; | ||
| 359 | } | 374 | } |
| 360 | 375 | ||
| 361 | int SrsHttpResponseReader::read_chunked(char* data, int nb_data, int* nb_read) | 376 | int SrsHttpResponseReader::read_chunked(char* data, int nb_data, int* nb_read) |
| @@ -480,8 +495,8 @@ int SrsHttpResponseReader::read_specified(char* data, int nb_data, int* nb_read) | @@ -480,8 +495,8 @@ int SrsHttpResponseReader::read_specified(char* data, int nb_data, int* nb_read) | ||
| 480 | // increase the total read to determine whether EOF. | 495 | // increase the total read to determine whether EOF. |
| 481 | nb_total_read += nb_bytes; | 496 | nb_total_read += nb_bytes; |
| 482 | 497 | ||
| 483 | - // for not chunked | ||
| 484 | - if (!owner->is_chunked()) { | 498 | + // for not chunked and specified content length. |
| 499 | + if (!owner->is_chunked() && owner->content_length() != -1) { | ||
| 485 | // when read completed, eof. | 500 | // when read completed, eof. |
| 486 | if (nb_total_read >= (int)owner->content_length()) { | 501 | if (nb_total_read >= (int)owner->content_length()) { |
| 487 | is_eof = true; | 502 | is_eof = true; |
| @@ -495,6 +510,7 @@ SrsHttpMessage::SrsHttpMessage(SrsStSocket* io, SrsConnection* c) : ISrsHttpMess | @@ -495,6 +510,7 @@ SrsHttpMessage::SrsHttpMessage(SrsStSocket* io, SrsConnection* c) : ISrsHttpMess | ||
| 495 | { | 510 | { |
| 496 | conn = c; | 511 | conn = c; |
| 497 | chunked = false; | 512 | chunked = false; |
| 513 | + infinite_chunked = false; | ||
| 498 | keep_alive = true; | 514 | keep_alive = true; |
| 499 | _uri = new SrsHttpUri(); | 515 | _uri = new SrsHttpUri(); |
| 500 | _body = new SrsHttpResponseReader(this, io); | 516 | _body = new SrsHttpResponseReader(this, io); |
| @@ -532,11 +548,10 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, | @@ -532,11 +548,10 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, | ||
| 532 | // parse uri from url. | 548 | // parse uri from url. |
| 533 | std::string host = get_request_header("Host"); | 549 | std::string host = get_request_header("Host"); |
| 534 | 550 | ||
| 535 | - // donot parse the empty host for uri, | ||
| 536 | - // for example, the response contains no host, | ||
| 537 | - // ignore it is ok. | 551 | + // use server public ip when no host specified. |
| 552 | + // to make telnet happy. | ||
| 538 | if (host.empty()) { | 553 | if (host.empty()) { |
| 539 | - return ret; | 554 | + host= srs_get_public_internet_address(); |
| 540 | } | 555 | } |
| 541 | 556 | ||
| 542 | // parse uri to schema/server:port/path?query | 557 | // parse uri to schema/server:port/path?query |
| @@ -674,6 +689,11 @@ bool SrsHttpMessage::is_keep_alive() | @@ -674,6 +689,11 @@ bool SrsHttpMessage::is_keep_alive() | ||
| 674 | return keep_alive; | 689 | return keep_alive; |
| 675 | } | 690 | } |
| 676 | 691 | ||
| 692 | +bool SrsHttpMessage::is_infinite_chunked() | ||
| 693 | +{ | ||
| 694 | + return infinite_chunked; | ||
| 695 | +} | ||
| 696 | + | ||
| 677 | string SrsHttpMessage::uri() | 697 | string SrsHttpMessage::uri() |
| 678 | { | 698 | { |
| 679 | std::string uri = _uri->get_schema(); | 699 | std::string uri = _uri->get_schema(); |
| @@ -728,6 +748,25 @@ int SrsHttpMessage::parse_rest_id(string pattern) | @@ -728,6 +748,25 @@ int SrsHttpMessage::parse_rest_id(string pattern) | ||
| 728 | return -1; | 748 | return -1; |
| 729 | } | 749 | } |
| 730 | 750 | ||
| 751 | +int SrsHttpMessage::enter_infinite_chunked() | ||
| 752 | +{ | ||
| 753 | + int ret = ERROR_SUCCESS; | ||
| 754 | + | ||
| 755 | + if (infinite_chunked) { | ||
| 756 | + return ret; | ||
| 757 | + } | ||
| 758 | + | ||
| 759 | + if (is_chunked() || content_length() != -1) { | ||
| 760 | + ret = ERROR_HTTP_DATA_INVALID; | ||
| 761 | + srs_error("infinite chunkted not supported in specified codec. ret=%d", ret); | ||
| 762 | + return ret; | ||
| 763 | + } | ||
| 764 | + | ||
| 765 | + infinite_chunked = true; | ||
| 766 | + | ||
| 767 | + return ret; | ||
| 768 | +} | ||
| 769 | + | ||
| 731 | int SrsHttpMessage::body_read_all(string& body) | 770 | int SrsHttpMessage::body_read_all(string& body) |
| 732 | { | 771 | { |
| 733 | int ret = ERROR_SUCCESS; | 772 | int ret = ERROR_SUCCESS; |
| @@ -156,9 +156,6 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField; | @@ -156,9 +156,6 @@ typedef std::pair<std::string, std::string> SrsHttpHeaderField; | ||
| 156 | // The field semantics differ slightly between client and server | 156 | // The field semantics differ slightly between client and server |
| 157 | // usage. In addition to the notes on the fields below, see the | 157 | // usage. In addition to the notes on the fields below, see the |
| 158 | // documentation for Request.Write and RoundTripper. | 158 | // documentation for Request.Write and RoundTripper. |
| 159 | -/** | ||
| 160 | - * the http message, request or response. | ||
| 161 | - */ | ||
| 162 | class SrsHttpMessage : public ISrsHttpMessage | 159 | class SrsHttpMessage : public ISrsHttpMessage |
| 163 | { | 160 | { |
| 164 | private: | 161 | private: |
| @@ -184,6 +181,10 @@ private: | @@ -184,6 +181,10 @@ private: | ||
| 184 | */ | 181 | */ |
| 185 | bool chunked; | 182 | bool chunked; |
| 186 | /** | 183 | /** |
| 184 | + * whether the body is infinite chunked. | ||
| 185 | + */ | ||
| 186 | + bool infinite_chunked; | ||
| 187 | + /** | ||
| 187 | * whether the request indicates should keep alive | 188 | * whether the request indicates should keep alive |
| 188 | * for the http connection. | 189 | * for the http connection. |
| 189 | */ | 190 | */ |
| @@ -236,6 +237,11 @@ public: | @@ -236,6 +237,11 @@ public: | ||
| 236 | */ | 237 | */ |
| 237 | virtual bool is_chunked(); | 238 | virtual bool is_chunked(); |
| 238 | /** | 239 | /** |
| 240 | + * whether body is infinite chunked encoding. | ||
| 241 | + * @remark set by enter_infinite_chunked. | ||
| 242 | + */ | ||
| 243 | + virtual bool is_infinite_chunked(); | ||
| 244 | + /** | ||
| 239 | * whether should keep the connection alive. | 245 | * whether should keep the connection alive. |
| 240 | */ | 246 | */ |
| 241 | virtual bool is_keep_alive(); | 247 | virtual bool is_keep_alive(); |
| @@ -256,6 +262,8 @@ public: | @@ -256,6 +262,8 @@ public: | ||
| 256 | */ | 262 | */ |
| 257 | virtual int parse_rest_id(std::string pattern); | 263 | virtual int parse_rest_id(std::string pattern); |
| 258 | public: | 264 | public: |
| 265 | + virtual int enter_infinite_chunked(); | ||
| 266 | +public: | ||
| 259 | /** | 267 | /** |
| 260 | * read body to string. | 268 | * read body to string. |
| 261 | * @remark for small http body. | 269 | * @remark for small http body. |
| @@ -485,7 +485,7 @@ void srs_update_proc_stat() | @@ -485,7 +485,7 @@ void srs_update_proc_stat() | ||
| 485 | static int user_hz = 0; | 485 | static int user_hz = 0; |
| 486 | if (user_hz <= 0) { | 486 | if (user_hz <= 0) { |
| 487 | user_hz = (int)sysconf(_SC_CLK_TCK); | 487 | user_hz = (int)sysconf(_SC_CLK_TCK); |
| 488 | - srs_trace("USER_HZ=%d", user_hz); | 488 | + srs_info("USER_HZ=%d", user_hz); |
| 489 | srs_assert(user_hz > 0); | 489 | srs_assert(user_hz > 0); |
| 490 | } | 490 | } |
| 491 | 491 | ||
| @@ -1279,6 +1279,66 @@ vector<string>& srs_get_local_ipv4_ips() | @@ -1279,6 +1279,66 @@ vector<string>& srs_get_local_ipv4_ips() | ||
| 1279 | return _srs_system_ipv4_ips; | 1279 | return _srs_system_ipv4_ips; |
| 1280 | } | 1280 | } |
| 1281 | 1281 | ||
| 1282 | +std::string _public_internet_address; | ||
| 1283 | + | ||
| 1284 | +string srs_get_public_internet_address() | ||
| 1285 | +{ | ||
| 1286 | + if (!_public_internet_address.empty()) { | ||
| 1287 | + return _public_internet_address; | ||
| 1288 | + } | ||
| 1289 | + | ||
| 1290 | + std::vector<std::string>& ips = srs_get_local_ipv4_ips(); | ||
| 1291 | + | ||
| 1292 | + // find the best match public address. | ||
| 1293 | + for (int i = 0; i < (int)ips.size(); i++) { | ||
| 1294 | + std::string ip = ips[i]; | ||
| 1295 | + in_addr_t addr = inet_addr(ip.c_str()); | ||
| 1296 | + u_int32_t addr_h = ntohl(addr); | ||
| 1297 | + // lo, 127.0.0.0-127.0.0.1 | ||
| 1298 | + if (addr_h >= 0x7f000000 && addr_h <= 0x7f000001) { | ||
| 1299 | + srs_trace("ignore private address: %s", ip.c_str()); | ||
| 1300 | + continue; | ||
| 1301 | + } | ||
| 1302 | + // Class A 10.0.0.0-10.255.255.255 | ||
| 1303 | + if (addr_h >= 0x0a000000 && addr_h <= 0x0affffff) { | ||
| 1304 | + srs_trace("ignore private address: %s", ip.c_str()); | ||
| 1305 | + continue; | ||
| 1306 | + } | ||
| 1307 | + // Class B 172.16.0.0-172.31.255.255 | ||
| 1308 | + if (addr_h >= 0xac100000 && addr_h <= 0xac1fffff) { | ||
| 1309 | + srs_trace("ignore private address: %s", ip.c_str()); | ||
| 1310 | + continue; | ||
| 1311 | + } | ||
| 1312 | + // Class C 192.168.0.0-192.168.255.255 | ||
| 1313 | + if (addr_h >= 0xc0a80000 && addr_h <= 0xc0a8ffff) { | ||
| 1314 | + srs_trace("ignore private address: %s", ip.c_str()); | ||
| 1315 | + continue; | ||
| 1316 | + } | ||
| 1317 | + srs_warn("use public address as ip: %s", ip.c_str()); | ||
| 1318 | + | ||
| 1319 | + _public_internet_address = ip; | ||
| 1320 | + return ip; | ||
| 1321 | + } | ||
| 1322 | + | ||
| 1323 | + // no public address, use private address. | ||
| 1324 | + for (int i = 0; i < (int)ips.size(); i++) { | ||
| 1325 | + std::string ip = ips[i]; | ||
| 1326 | + in_addr_t addr = inet_addr(ip.c_str()); | ||
| 1327 | + u_int32_t addr_h = ntohl(addr); | ||
| 1328 | + // lo, 127.0.0.0-127.0.0.1 | ||
| 1329 | + if (addr_h >= 0x7f000000 && addr_h <= 0x7f000001) { | ||
| 1330 | + srs_trace("ignore private address: %s", ip.c_str()); | ||
| 1331 | + continue; | ||
| 1332 | + } | ||
| 1333 | + srs_warn("use private address as ip: %s", ip.c_str()); | ||
| 1334 | + | ||
| 1335 | + _public_internet_address = ip; | ||
| 1336 | + return ip; | ||
| 1337 | + } | ||
| 1338 | + | ||
| 1339 | + return ""; | ||
| 1340 | +} | ||
| 1341 | + | ||
| 1282 | string srs_get_local_ip(int fd) | 1342 | string srs_get_local_ip(int fd) |
| 1283 | { | 1343 | { |
| 1284 | std::string ip; | 1344 | std::string ip; |
| @@ -660,6 +660,9 @@ extern void srs_update_rtmp_server(int nb_conn, SrsKbps* kbps); | @@ -660,6 +660,9 @@ extern void srs_update_rtmp_server(int nb_conn, SrsKbps* kbps); | ||
| 660 | // get local ip, fill to @param ips | 660 | // get local ip, fill to @param ips |
| 661 | extern std::vector<std::string>& srs_get_local_ipv4_ips(); | 661 | extern std::vector<std::string>& srs_get_local_ipv4_ips(); |
| 662 | 662 | ||
| 663 | +// get local public ip, empty string if no public internet address found. | ||
| 664 | +extern std::string srs_get_public_internet_address(); | ||
| 665 | + | ||
| 663 | // get local or peer ip. | 666 | // get local or peer ip. |
| 664 | // where local ip is the server ip which client connected. | 667 | // where local ip is the server ip which client connected. |
| 665 | extern std::string srs_get_local_ip(int fd); | 668 | extern std::string srs_get_local_ip(int fd); |
| @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 31 | // current release version | 31 | // current release version |
| 32 | #define VERSION_MAJOR 2 | 32 | #define VERSION_MAJOR 2 |
| 33 | #define VERSION_MINOR 0 | 33 | #define VERSION_MINOR 0 |
| 34 | -#define VERSION_REVISION 208 | 34 | +#define VERSION_REVISION 209 |
| 35 | 35 | ||
| 36 | // generated by configure, only macros. | 36 | // generated by configure, only macros. |
| 37 | #include <srs_auto_headers.hpp> | 37 | #include <srs_auto_headers.hpp> |
| @@ -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 | */ |
-
请 注册 或 登录 后发表评论