winlin

fix http reader bug, support infinite chunkted. 2.0.209

@@ -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
@@ -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 */