winlin

merge from 2.0release.

@@ -566,6 +566,9 @@ Supported operating systems and hardware: @@ -566,6 +566,9 @@ Supported operating systems and hardware:
566 566
567 ### SRS 2.0 history 567 ### SRS 2.0 history
568 568
  569 +* v2.0, 2015-05-22, fix [#397](https://github.com/simple-rtmp-server/srs/issues/397) the USER_HZ maybe not 100. 2.0.165
  570 +* v2.0, 2015-05-22, for [#400](https://github.com/simple-rtmp-server/srs/issues/400), parse when got entire http header, by feilong. 2.0.164.
  571 +* v2.0, 2015-05-19, merge from bravo system, add the rtmfp to bms(commercial srs). 2.0.163.
569 * v2.0, 2015-05-10, support push flv stream over HTTP POST to SRS. 572 * v2.0, 2015-05-10, support push flv stream over HTTP POST to SRS.
570 * v2.0, 2015-04-20, support ingest hls live stream to RTMP. 573 * v2.0, 2015-04-20, support ingest hls live stream to RTMP.
571 * v2.0, 2015-04-15, for [#383](https://github.com/simple-rtmp-server/srs/issues/383), support mix_correct algorithm. 2.0.161. 574 * v2.0, 2015-04-15, for [#383](https://github.com/simple-rtmp-server/srs/issues/383), support mix_correct algorithm. 2.0.161.
@@ -674,6 +677,10 @@ Supported operating systems and hardware: @@ -674,6 +677,10 @@ Supported operating systems and hardware:
674 677
675 ### SRS 1.0 history 678 ### SRS 1.0 history
676 679
  680 +* v1.0, 2015-05-22, fix [#397](https://github.com/simple-rtmp-server/srs/issues/397) the USER_HZ maybe not 100. 1.0.32
  681 +* v1.0, 2015-03-26, fix hls aac adts bug, in aac mux. 1.0.31.
  682 +* <strong>v1.0, 2015-03-19, [1.0r3 release(1.0.30)](https://github.com/simple-rtmp-server/srs/releases/tag/1.0r3) released. 59511 lines.</strong>
  683 +* v1.0, 2015-03-17, remove the osx for 1.0.30.
677 * v1.0, 2015-02-17, the join maybe failed, should use a variable to ensure thread terminated. 1.0.28. 684 * v1.0, 2015-02-17, the join maybe failed, should use a variable to ensure thread terminated. 1.0.28.
678 * <strong>v1.0, 2015-02-12, [1.0r2 release(1.0.27)](https://github.com/simple-rtmp-server/srs/releases/tag/1.0r2) released. 59507 lines.</strong> 685 * <strong>v1.0, 2015-02-12, [1.0r2 release(1.0.27)](https://github.com/simple-rtmp-server/srs/releases/tag/1.0r2) released. 59507 lines.</strong>
679 * v1.0, 2015-02-11, dev code HuKaiqun for 1.0.27. 686 * v1.0, 2015-02-11, dev code HuKaiqun for 1.0.27.
@@ -408,17 +408,17 @@ @@ -408,17 +408,17 @@
408 isa = PBXGroup; 408 isa = PBXGroup;
409 children = ( 409 children = (
410 3C1232B81AAE824500CE8F6C /* configure */, 410 3C1232B81AAE824500CE8F6C /* configure */,
411 - 3C36DB541ABD1CA70066CCAF /* libs */,  
412 - 3C1EE6AF1AB107EE00576EE9 /* conf */,  
413 - 3C1232EF1AAEAC5800CE8F6C /* etc */,  
414 - 3C1232BA1AAE826F00CE8F6C /* auto */,  
415 - 3C1232B91AAE825100CE8F6C /* scripts */,  
416 - 3C12324B1AAE81CE00CE8F6C /* app */,  
417 - 3C12322C1AAE819900CE8F6C /* protocol */, 411 + 3C1231EF1AAE651100CE8F6C /* core */,
418 3C1232071AAE814200CE8F6C /* kernel */, 412 3C1232071AAE814200CE8F6C /* kernel */,
  413 + 3C12322C1AAE819900CE8F6C /* protocol */,
  414 + 3C12324B1AAE81CE00CE8F6C /* app */,
419 3C1232041AAE80CB00CE8F6C /* main */, 415 3C1232041AAE80CB00CE8F6C /* main */,
420 3C1231F91AAE670E00CE8F6C /* objs */, 416 3C1231F91AAE670E00CE8F6C /* objs */,
421 - 3C1231EF1AAE651100CE8F6C /* core */, 417 + 3C1232BA1AAE826F00CE8F6C /* auto */,
  418 + 3C1232B91AAE825100CE8F6C /* scripts */,
  419 + 3C1EE6AF1AB107EE00576EE9 /* conf */,
  420 + 3C36DB541ABD1CA70066CCAF /* libs */,
  421 + 3C1232EF1AAEAC5800CE8F6C /* etc */,
422 ); 422 );
423 path = srs_xcode; 423 path = srs_xcode;
424 sourceTree = "<group>"; 424 sourceTree = "<group>";
@@ -514,12 +514,12 @@ @@ -514,12 +514,12 @@
514 3C12324B1AAE81CE00CE8F6C /* app */ = { 514 3C12324B1AAE81CE00CE8F6C /* app */ = {
515 isa = PBXGroup; 515 isa = PBXGroup;
516 children = ( 516 children = (
517 - 3C28EDDD1AF5C43F00A3AEAC /* srs_app_caster_flv.cpp */,  
518 - 3C28EDDE1AF5C43F00A3AEAC /* srs_app_caster_flv.hpp */,  
519 3CD88B3D1ACA9C58000359E0 /* srs_app_async_call.cpp */, 517 3CD88B3D1ACA9C58000359E0 /* srs_app_async_call.cpp */,
520 3CD88B3E1ACA9C58000359E0 /* srs_app_async_call.hpp */, 518 3CD88B3E1ACA9C58000359E0 /* srs_app_async_call.hpp */,
521 3C12324C1AAE81D900CE8F6C /* srs_app_bandwidth.cpp */, 519 3C12324C1AAE81D900CE8F6C /* srs_app_bandwidth.cpp */,
522 3C12324D1AAE81D900CE8F6C /* srs_app_bandwidth.hpp */, 520 3C12324D1AAE81D900CE8F6C /* srs_app_bandwidth.hpp */,
  521 + 3C28EDDD1AF5C43F00A3AEAC /* srs_app_caster_flv.cpp */,
  522 + 3C28EDDE1AF5C43F00A3AEAC /* srs_app_caster_flv.hpp */,
523 3C12324E1AAE81D900CE8F6C /* srs_app_config.cpp */, 523 3C12324E1AAE81D900CE8F6C /* srs_app_config.cpp */,
524 3C12324F1AAE81D900CE8F6C /* srs_app_config.hpp */, 524 3C12324F1AAE81D900CE8F6C /* srs_app_config.hpp */,
525 3C1232501AAE81D900CE8F6C /* srs_app_conn.cpp */, 525 3C1232501AAE81D900CE8F6C /* srs_app_conn.cpp */,
@@ -536,10 +536,10 @@ @@ -536,10 +536,10 @@
536 3C12325B1AAE81D900CE8F6C /* srs_app_ffmpeg.hpp */, 536 3C12325B1AAE81D900CE8F6C /* srs_app_ffmpeg.hpp */,
537 3C12325C1AAE81D900CE8F6C /* srs_app_forward.cpp */, 537 3C12325C1AAE81D900CE8F6C /* srs_app_forward.cpp */,
538 3C12325D1AAE81D900CE8F6C /* srs_app_forward.hpp */, 538 3C12325D1AAE81D900CE8F6C /* srs_app_forward.hpp */,
539 - 3C12325E1AAE81D900CE8F6C /* srs_app_heartbeat.cpp */,  
540 - 3C12325F1AAE81D900CE8F6C /* srs_app_heartbeat.hpp */,  
541 3C1EE6AC1AB1055800576EE9 /* srs_app_hds.cpp */, 539 3C1EE6AC1AB1055800576EE9 /* srs_app_hds.cpp */,
542 3C1EE6AD1AB1055800576EE9 /* srs_app_hds.hpp */, 540 3C1EE6AD1AB1055800576EE9 /* srs_app_hds.hpp */,
  541 + 3C12325E1AAE81D900CE8F6C /* srs_app_heartbeat.cpp */,
  542 + 3C12325F1AAE81D900CE8F6C /* srs_app_heartbeat.hpp */,
543 3C1232601AAE81D900CE8F6C /* srs_app_hls.cpp */, 543 3C1232601AAE81D900CE8F6C /* srs_app_hls.cpp */,
544 3C1232611AAE81D900CE8F6C /* srs_app_hls.hpp */, 544 3C1232611AAE81D900CE8F6C /* srs_app_hls.hpp */,
545 3C1232621AAE81D900CE8F6C /* srs_app_http_api.cpp */, 545 3C1232621AAE81D900CE8F6C /* srs_app_http_api.cpp */,
@@ -441,10 +441,22 @@ int SrsConfig::reload_conf(SrsConfig* conf) @@ -441,10 +441,22 @@ int SrsConfig::reload_conf(SrsConfig* conf)
441 // daemon 441 // daemon
442 // 442 //
443 // always support reload without additional code: 443 // always support reload without additional code:
444 - // chunk_size, ff_log_dir, max_connections, 444 + // chunk_size, ff_log_dir,
445 // bandcheck, http_hooks, heartbeat, 445 // bandcheck, http_hooks, heartbeat,
446 // token_traverse, debug_srs_upnode, 446 // token_traverse, debug_srs_upnode,
447 // security 447 // security
  448 +
  449 + // merge config: max_connections
  450 + if (!srs_directive_equals(root->get("max_connections"), old_root->get("max_connections"))) {
  451 + for (it = subscribes.begin(); it != subscribes.end(); ++it) {
  452 + ISrsReloadHandler* subscribe = *it;
  453 + if ((ret = subscribe->on_reload_max_conns()) != ERROR_SUCCESS) {
  454 + srs_error("notify subscribes reload max_connections failed. ret=%d", ret);
  455 + return ret;
  456 + }
  457 + }
  458 + srs_trace("reload max_connections success.");
  459 + }
448 460
449 // merge config: listen 461 // merge config: listen
450 if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) { 462 if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) {
@@ -1082,6 +1082,7 @@ SrsHttpMessage::SrsHttpMessage(SrsStSocket* io, SrsConnection* c) @@ -1082,6 +1082,7 @@ SrsHttpMessage::SrsHttpMessage(SrsStSocket* io, SrsConnection* c)
1082 { 1082 {
1083 conn = c; 1083 conn = c;
1084 chunked = false; 1084 chunked = false;
  1085 + keep_alive = true;
1085 _uri = new SrsHttpUri(); 1086 _uri = new SrsHttpUri();
1086 _body = new SrsHttpResponseReader(this, io); 1087 _body = new SrsHttpResponseReader(this, io);
1087 _http_ts_send_buffer = new char[SRS_HTTP_TS_SEND_BUFFER_SIZE]; 1088 _http_ts_send_buffer = new char[SRS_HTTP_TS_SEND_BUFFER_SIZE];
@@ -1106,6 +1107,9 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body, @@ -1106,6 +1107,9 @@ int SrsHttpMessage::update(string url, http_parser* header, SrsFastBuffer* body,
1106 std::string transfer_encoding = get_request_header("Transfer-Encoding"); 1107 std::string transfer_encoding = get_request_header("Transfer-Encoding");
1107 chunked = (transfer_encoding == "chunked"); 1108 chunked = (transfer_encoding == "chunked");
1108 1109
  1110 + // whether keep alive.
  1111 + keep_alive = http_should_keep_alive(header);
  1112 +
1109 // set the buffer. 1113 // set the buffer.
1110 if ((ret = _body->initialize(body)) != ERROR_SUCCESS) { 1114 if ((ret = _body->initialize(body)) != ERROR_SUCCESS) {
1111 return ret; 1115 return ret;
@@ -1232,6 +1236,11 @@ bool SrsHttpMessage::is_chunked() @@ -1232,6 +1236,11 @@ bool SrsHttpMessage::is_chunked()
1232 return chunked; 1236 return chunked;
1233 } 1237 }
1234 1238
  1239 +bool SrsHttpMessage::is_keep_alive()
  1240 +{
  1241 + return keep_alive;
  1242 +}
  1243 +
1235 string SrsHttpMessage::uri() 1244 string SrsHttpMessage::uri()
1236 { 1245 {
1237 std::string uri = _uri->get_schema(); 1246 std::string uri = _uri->get_schema();
@@ -1447,10 +1456,17 @@ int SrsHttpParser::parse_message_imp(SrsStSocket* skt) @@ -1447,10 +1456,17 @@ int SrsHttpParser::parse_message_imp(SrsStSocket* skt)
1447 while (true) { 1456 while (true) {
1448 ssize_t nparsed = 0; 1457 ssize_t nparsed = 0;
1449 1458
1450 - // when buffer not empty, parse it.  
1451 - if (buffer->size() > 0) {  
1452 - nparsed = http_parser_execute(&parser, &settings, buffer->bytes(), buffer->size());  
1453 - srs_info("buffer=%d, nparsed=%d, header=%d", buffer->size(), (int)nparsed, header_parsed); 1459 + // when got entire http header, parse it.
  1460 + // @see https://github.com/simple-rtmp-server/srs/issues/400
  1461 + char* start = buffer->bytes();
  1462 + char* end = start + buffer->size();
  1463 + for (char* p = start; p <= end - 4; p++) {
  1464 + // SRS_HTTP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A
  1465 + if (p[0] == SRS_CONSTS_CR && p[1] == SRS_CONSTS_LF && p[2] == SRS_CONSTS_CR && p[3] == SRS_CONSTS_LF) {
  1466 + nparsed = http_parser_execute(&parser, &settings, buffer->bytes(), buffer->size());
  1467 + srs_info("buffer=%d, nparsed=%d, header=%d", buffer->size(), (int)nparsed, header_parsed);
  1468 + break;
  1469 + }
1454 } 1470 }
1455 1471
1456 // consume the parsed bytes. 1472 // consume the parsed bytes.
@@ -495,6 +495,11 @@ private: @@ -495,6 +495,11 @@ private:
495 */ 495 */
496 bool chunked; 496 bool chunked;
497 /** 497 /**
  498 + * whether the request indicates should keep alive
  499 + * for the http connection.
  500 + */
  501 + bool keep_alive;
  502 + /**
498 * uri parser 503 * uri parser
499 */ 504 */
500 SrsHttpUri* _uri; 505 SrsHttpUri* _uri;
@@ -539,6 +544,10 @@ public: @@ -539,6 +544,10 @@ public:
539 */ 544 */
540 virtual bool is_chunked(); 545 virtual bool is_chunked();
541 /** 546 /**
  547 + * whether should keep the connection alive.
  548 + */
  549 + virtual bool is_keep_alive();
  550 + /**
542 * the uri contains the host and path. 551 * the uri contains the host and path.
543 */ 552 */
544 virtual std::string uri(); 553 virtual std::string uri();
@@ -523,6 +523,10 @@ int SrsHttpApi::do_cycle() @@ -523,6 +523,10 @@ int SrsHttpApi::do_cycle()
523 // underlayer socket 523 // underlayer socket
524 SrsStSocket skt(stfd); 524 SrsStSocket skt(stfd);
525 525
  526 + // set the recv timeout, for some clients never disconnect the connection.
  527 + // @see https://github.com/simple-rtmp-server/srs/issues/398
  528 + skt.set_recv_timeout(SRS_HTTP_RECV_TIMEOUT_US);
  529 +
526 // process http messages. 530 // process http messages.
527 for (;;) { 531 for (;;) {
528 SrsHttpMessage* req = NULL; 532 SrsHttpMessage* req = NULL;
@@ -551,6 +555,12 @@ int SrsHttpApi::do_cycle() @@ -551,6 +555,12 @@ int SrsHttpApi::do_cycle()
551 if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) { 555 if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) {
552 return ret; 556 return ret;
553 } 557 }
  558 +
  559 + // donot keep alive, disconnect it.
  560 + // @see https://github.com/simple-rtmp-server/srs/issues/399
  561 + if (!req->is_keep_alive()) {
  562 + break;
  563 + }
554 } 564 }
555 565
556 return ret; 566 return ret;
@@ -1383,6 +1383,10 @@ int SrsHttpConn::do_cycle() @@ -1383,6 +1383,10 @@ int SrsHttpConn::do_cycle()
1383 // underlayer socket 1383 // underlayer socket
1384 SrsStSocket skt(stfd); 1384 SrsStSocket skt(stfd);
1385 1385
  1386 + // set the recv timeout, for some clients never disconnect the connection.
  1387 + // @see https://github.com/simple-rtmp-server/srs/issues/398
  1388 + skt.set_recv_timeout(SRS_HTTP_RECV_TIMEOUT_US);
  1389 +
1386 // process http messages. 1390 // process http messages.
1387 for (;;) { 1391 for (;;) {
1388 SrsHttpMessage* req = NULL; 1392 SrsHttpMessage* req = NULL;
@@ -1408,6 +1412,12 @@ int SrsHttpConn::do_cycle() @@ -1408,6 +1412,12 @@ int SrsHttpConn::do_cycle()
1408 if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) { 1412 if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) {
1409 return ret; 1413 return ret;
1410 } 1414 }
  1415 +
  1416 + // donot keep alive, disconnect it.
  1417 + // @see https://github.com/simple-rtmp-server/srs/issues/399
  1418 + if (!req->is_keep_alive()) {
  1419 + break;
  1420 + }
1411 } 1421 }
1412 1422
1413 return ret; 1423 return ret;
@@ -77,22 +77,22 @@ void SrsKbpsSlice::sample() @@ -77,22 +77,22 @@ void SrsKbpsSlice::sample()
77 } 77 }
78 78
79 if (now - sample_30s.time > 30 * 1000) { 79 if (now - sample_30s.time > 30 * 1000) {
80 - sample_30s.kbps = (total_bytes - sample_30s.bytes) * 8 / (now - sample_30s.time); 80 + sample_30s.kbps = (int)((total_bytes - sample_30s.bytes) * 8 / (now - sample_30s.time));
81 sample_30s.time = now; 81 sample_30s.time = now;
82 sample_30s.bytes = total_bytes; 82 sample_30s.bytes = total_bytes;
83 } 83 }
84 if (now - sample_1m.time > 60 * 1000) { 84 if (now - sample_1m.time > 60 * 1000) {
85 - sample_1m.kbps = (total_bytes - sample_1m.bytes) * 8 / (now - sample_1m.time); 85 + sample_1m.kbps = (int)((total_bytes - sample_1m.bytes) * 8 / (now - sample_1m.time));
86 sample_1m.time = now; 86 sample_1m.time = now;
87 sample_1m.bytes = total_bytes; 87 sample_1m.bytes = total_bytes;
88 } 88 }
89 if (now - sample_5m.time > 300 * 1000) { 89 if (now - sample_5m.time > 300 * 1000) {
90 - sample_5m.kbps = (total_bytes - sample_5m.bytes) * 8 / (now - sample_5m.time); 90 + sample_5m.kbps = (int)((total_bytes - sample_5m.bytes) * 8 / (now - sample_5m.time));
91 sample_5m.time = now; 91 sample_5m.time = now;
92 sample_5m.bytes = total_bytes; 92 sample_5m.bytes = total_bytes;
93 } 93 }
94 if (now - sample_60m.time > 3600 * 1000) { 94 if (now - sample_60m.time > 3600 * 1000) {
95 - sample_60m.kbps = (total_bytes - sample_60m.bytes) * 8 / (now - sample_60m.time); 95 + sample_60m.kbps = (int)((total_bytes - sample_60m.bytes) * 8 / (now - sample_60m.time));
96 sample_60m.time = now; 96 sample_60m.time = now;
97 sample_60m.bytes = total_bytes; 97 sample_60m.bytes = total_bytes;
98 } 98 }
@@ -160,7 +160,7 @@ int SrsKbps::get_send_kbps() @@ -160,7 +160,7 @@ int SrsKbps::get_send_kbps()
160 return 0; 160 return 0;
161 } 161 }
162 int64_t bytes = get_send_bytes(); 162 int64_t bytes = get_send_bytes();
163 - return bytes * 8 / duration; 163 + return (int)(bytes * 8 / duration);
164 } 164 }
165 165
166 int SrsKbps::get_recv_kbps() 166 int SrsKbps::get_recv_kbps()
@@ -170,7 +170,7 @@ int SrsKbps::get_recv_kbps() @@ -170,7 +170,7 @@ int SrsKbps::get_recv_kbps()
170 return 0; 170 return 0;
171 } 171 }
172 int64_t bytes = get_recv_bytes(); 172 int64_t bytes = get_recv_bytes();
173 - return bytes * 8 / duration; 173 + return (int)(bytes * 8 / duration);
174 } 174 }
175 175
176 int SrsKbps::get_send_kbps_30s() 176 int SrsKbps::get_send_kbps_30s()
@@ -54,6 +54,11 @@ ISrsUdpHandler::~ISrsUdpHandler() @@ -54,6 +54,11 @@ ISrsUdpHandler::~ISrsUdpHandler()
54 { 54 {
55 } 55 }
56 56
  57 +int ISrsUdpHandler::on_stfd_change(st_netfd_t /*fd*/)
  58 +{
  59 + return ERROR_SUCCESS;
  60 +}
  61 +
57 ISrsTcpHandler::ISrsTcpHandler() 62 ISrsTcpHandler::ISrsTcpHandler()
58 { 63 {
59 } 64 }
@@ -69,7 +74,7 @@ SrsUdpListener::SrsUdpListener(ISrsUdpHandler* h, string i, int p) @@ -69,7 +74,7 @@ SrsUdpListener::SrsUdpListener(ISrsUdpHandler* h, string i, int p)
69 port = p; 74 port = p;
70 75
71 _fd = -1; 76 _fd = -1;
72 - stfd = NULL; 77 + _stfd = NULL;
73 78
74 nb_buf = SRS_UDP_MAX_PACKET_SIZE; 79 nb_buf = SRS_UDP_MAX_PACKET_SIZE;
75 buf = new char[nb_buf]; 80 buf = new char[nb_buf];
@@ -80,7 +85,7 @@ SrsUdpListener::SrsUdpListener(ISrsUdpHandler* h, string i, int p) @@ -80,7 +85,7 @@ SrsUdpListener::SrsUdpListener(ISrsUdpHandler* h, string i, int p)
80 SrsUdpListener::~SrsUdpListener() 85 SrsUdpListener::~SrsUdpListener()
81 { 86 {
82 // close the stfd to trigger thread to interrupted. 87 // close the stfd to trigger thread to interrupted.
83 - srs_close_stfd(stfd); 88 + srs_close_stfd(_stfd);
84 89
85 pthread->stop(); 90 pthread->stop();
86 srs_freep(pthread); 91 srs_freep(pthread);
@@ -97,6 +102,11 @@ int SrsUdpListener::fd() @@ -97,6 +102,11 @@ int SrsUdpListener::fd()
97 return _fd; 102 return _fd;
98 } 103 }
99 104
  105 +st_netfd_t SrsUdpListener::stfd()
  106 +{
  107 + return _stfd;
  108 +}
  109 +
100 int SrsUdpListener::listen() 110 int SrsUdpListener::listen()
101 { 111 {
102 int ret = ERROR_SUCCESS; 112 int ret = ERROR_SUCCESS;
@@ -127,7 +137,7 @@ int SrsUdpListener::listen() @@ -127,7 +137,7 @@ int SrsUdpListener::listen()
127 } 137 }
128 srs_verbose("bind socket success. ep=%s:%d, fd=%d", ip.c_str(), port, _fd); 138 srs_verbose("bind socket success. ep=%s:%d, fd=%d", ip.c_str(), port, _fd);
129 139
130 - if ((stfd = st_netfd_open_socket(_fd)) == NULL){ 140 + if ((_stfd = st_netfd_open_socket(_fd)) == NULL){
131 ret = ERROR_ST_OPEN_SOCKET; 141 ret = ERROR_ST_OPEN_SOCKET;
132 srs_error("st_netfd_open_socket open socket failed. ep=%s:%d, ret=%d", ip.c_str(), port, ret); 142 srs_error("st_netfd_open_socket open socket failed. ep=%s:%d, ret=%d", ip.c_str(), port, ret);
133 return ret; 143 return ret;
@@ -153,7 +163,7 @@ int SrsUdpListener::cycle() @@ -153,7 +163,7 @@ int SrsUdpListener::cycle()
153 int nb_from = sizeof(sockaddr_in); 163 int nb_from = sizeof(sockaddr_in);
154 int nread = 0; 164 int nread = 0;
155 165
156 - if ((nread = st_recvfrom(stfd, buf, nb_buf, (sockaddr*)&from, &nb_from, ST_UTIME_NO_TIMEOUT)) <= 0) { 166 + if ((nread = st_recvfrom(_stfd, buf, nb_buf, (sockaddr*)&from, &nb_from, ST_UTIME_NO_TIMEOUT)) <= 0) {
157 srs_warn("ignore recv udp packet failed, nread=%d", nread); 167 srs_warn("ignore recv udp packet failed, nread=%d", nread);
158 continue; 168 continue;
159 } 169 }
@@ -178,7 +188,7 @@ SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, string i, int p) @@ -178,7 +188,7 @@ SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, string i, int p)
178 port = p; 188 port = p;
179 189
180 _fd = -1; 190 _fd = -1;
181 - stfd = NULL; 191 + _stfd = NULL;
182 192
183 pthread = new SrsThread("tcp", this, 0, true); 193 pthread = new SrsThread("tcp", this, 0, true);
184 } 194 }
@@ -186,7 +196,7 @@ SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, string i, int p) @@ -186,7 +196,7 @@ SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, string i, int p)
186 SrsTcpListener::~SrsTcpListener() 196 SrsTcpListener::~SrsTcpListener()
187 { 197 {
188 // close the stfd to trigger thread to interrupted. 198 // close the stfd to trigger thread to interrupted.
189 - srs_close_stfd(stfd); 199 + srs_close_stfd(_stfd);
190 200
191 pthread->stop(); 201 pthread->stop();
192 srs_freep(pthread); 202 srs_freep(pthread);
@@ -238,7 +248,7 @@ int SrsTcpListener::listen() @@ -238,7 +248,7 @@ int SrsTcpListener::listen()
238 } 248 }
239 srs_verbose("listen socket success. ep=%s:%d, fd=%d", ip.c_str(), port, _fd); 249 srs_verbose("listen socket success. ep=%s:%d, fd=%d", ip.c_str(), port, _fd);
240 250
241 - if ((stfd = st_netfd_open_socket(_fd)) == NULL){ 251 + if ((_stfd = st_netfd_open_socket(_fd)) == NULL){
242 ret = ERROR_ST_OPEN_SOCKET; 252 ret = ERROR_ST_OPEN_SOCKET;
243 srs_error("st_netfd_open_socket open socket failed. ep=%s:%d, ret=%d", ip.c_str(), port, ret); 253 srs_error("st_netfd_open_socket open socket failed. ep=%s:%d, ret=%d", ip.c_str(), port, ret);
244 return ret; 254 return ret;
@@ -258,7 +268,7 @@ int SrsTcpListener::cycle() @@ -258,7 +268,7 @@ int SrsTcpListener::cycle()
258 { 268 {
259 int ret = ERROR_SUCCESS; 269 int ret = ERROR_SUCCESS;
260 270
261 - st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); 271 + st_netfd_t client_stfd = st_accept(_stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT);
262 272
263 if(client_stfd == NULL){ 273 if(client_stfd == NULL){
264 // ignore error. 274 // ignore error.
@@ -47,6 +47,12 @@ public: @@ -47,6 +47,12 @@ public:
47 virtual ~ISrsUdpHandler(); 47 virtual ~ISrsUdpHandler();
48 public: 48 public:
49 /** 49 /**
  50 + * when fd changed, for instance, reload the listen port,
  51 + * notify the handler and user can do something.
  52 + */
  53 + virtual int on_stfd_change(st_netfd_t fd);
  54 +public:
  55 + /**
50 * when udp listener got a udp packet, notice server to process it. 56 * when udp listener got a udp packet, notice server to process it.
51 * @param type, the client type, used to create concrete connection, 57 * @param type, the client type, used to create concrete connection,
52 * for instance RTMP connection to serve client. 58 * for instance RTMP connection to serve client.
@@ -80,7 +86,7 @@ class SrsUdpListener : public ISrsThreadHandler @@ -80,7 +86,7 @@ class SrsUdpListener : public ISrsThreadHandler
80 { 86 {
81 private: 87 private:
82 int _fd; 88 int _fd;
83 - st_netfd_t stfd; 89 + st_netfd_t _stfd;
84 SrsThread* pthread; 90 SrsThread* pthread;
85 private: 91 private:
86 char* buf; 92 char* buf;
@@ -94,6 +100,7 @@ public: @@ -94,6 +100,7 @@ public:
94 virtual ~SrsUdpListener(); 100 virtual ~SrsUdpListener();
95 public: 101 public:
96 virtual int fd(); 102 virtual int fd();
  103 + virtual st_netfd_t stfd();
97 public: 104 public:
98 virtual int listen(); 105 virtual int listen();
99 // interface ISrsThreadHandler. 106 // interface ISrsThreadHandler.
@@ -108,7 +115,7 @@ class SrsTcpListener : public ISrsThreadHandler @@ -108,7 +115,7 @@ class SrsTcpListener : public ISrsThreadHandler
108 { 115 {
109 private: 116 private:
110 int _fd; 117 int _fd;
111 - st_netfd_t stfd; 118 + st_netfd_t _stfd;
112 SrsThread* pthread; 119 SrsThread* pthread;
113 private: 120 private:
114 ISrsTcpHandler* handler; 121 ISrsTcpHandler* handler;
@@ -40,6 +40,11 @@ int ISrsReloadHandler::on_reload_listen() @@ -40,6 +40,11 @@ int ISrsReloadHandler::on_reload_listen()
40 return ERROR_SUCCESS; 40 return ERROR_SUCCESS;
41 } 41 }
42 42
  43 +int ISrsReloadHandler::on_reload_max_conns()
  44 +{
  45 + return ERROR_SUCCESS;
  46 +}
  47 +
43 int ISrsReloadHandler::on_reload_pid() 48 int ISrsReloadHandler::on_reload_pid()
44 { 49 {
45 return ERROR_SUCCESS; 50 return ERROR_SUCCESS;
@@ -44,6 +44,7 @@ public: @@ -44,6 +44,7 @@ public:
44 ISrsReloadHandler(); 44 ISrsReloadHandler();
45 virtual ~ISrsReloadHandler(); 45 virtual ~ISrsReloadHandler();
46 public: 46 public:
  47 + virtual int on_reload_max_conns();
47 virtual int on_reload_listen(); 48 virtual int on_reload_listen();
48 virtual int on_reload_pid(); 49 virtual int on_reload_pid();
49 virtual int on_reload_log_tank(); 50 virtual int on_reload_log_tank();
@@ -55,6 +56,7 @@ public: @@ -55,6 +56,7 @@ public:
55 virtual int on_reload_http_stream_enabled(); 56 virtual int on_reload_http_stream_enabled();
56 virtual int on_reload_http_stream_disabled(); 57 virtual int on_reload_http_stream_disabled();
57 virtual int on_reload_http_stream_updated(); 58 virtual int on_reload_http_stream_updated();
  59 +public:
58 virtual int on_reload_vhost_http_updated(); 60 virtual int on_reload_vhost_http_updated();
59 virtual int on_reload_vhost_http_remux_updated(); 61 virtual int on_reload_vhost_http_remux_updated();
60 virtual int on_reload_vhost_added(std::string vhost); 62 virtual int on_reload_vhost_added(std::string vhost);
@@ -1068,24 +1068,24 @@ int SrsRtmpConn::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessag @@ -1068,24 +1068,24 @@ int SrsRtmpConn::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessag
1068 return ret; 1068 return ret;
1069 } 1069 }
1070 1070
1071 - // pause or other msg. 1071 + // pause
1072 SrsPausePacket* pause = dynamic_cast<SrsPausePacket*>(pkt); 1072 SrsPausePacket* pause = dynamic_cast<SrsPausePacket*>(pkt);
1073 - if (!pause) {  
1074 - srs_info("ignore all amf0/amf3 command except pause.");  
1075 - return ret;  
1076 - }  
1077 -  
1078 - if ((ret = rtmp->on_play_client_pause(res->stream_id, pause->is_pause)) != ERROR_SUCCESS) {  
1079 - srs_error("rtmp process play client pause failed. ret=%d", ret);  
1080 - return ret;  
1081 - }  
1082 -  
1083 - if ((ret = consumer->on_play_client_pause(pause->is_pause)) != ERROR_SUCCESS) {  
1084 - srs_error("consumer process play client pause failed. ret=%d", ret); 1073 + if (pause) {
  1074 + if ((ret = rtmp->on_play_client_pause(res->stream_id, pause->is_pause)) != ERROR_SUCCESS) {
  1075 + srs_error("rtmp process play client pause failed. ret=%d", ret);
  1076 + return ret;
  1077 + }
  1078 +
  1079 + if ((ret = consumer->on_play_client_pause(pause->is_pause)) != ERROR_SUCCESS) {
  1080 + srs_error("consumer process play client pause failed. ret=%d", ret);
  1081 + return ret;
  1082 + }
  1083 + srs_info("process pause success, is_pause=%d, time=%d.", pause->is_pause, pause->time_ms);
1085 return ret; 1084 return ret;
1086 } 1085 }
1087 - srs_info("process pause success, is_pause=%d, time=%d.", pause->is_pause, pause->time_ms);  
1088 1086
  1087 + // other msg.
  1088 + srs_info("ignore all amf0/amf3 command except pause and video control.");
1089 return ret; 1089 return ret;
1090 } 1090 }
1091 1091
@@ -113,23 +113,23 @@ std::string srs_listener_type2string(SrsListenerType type) @@ -113,23 +113,23 @@ std::string srs_listener_type2string(SrsListenerType type)
113 } 113 }
114 } 114 }
115 115
116 -SrsListener::SrsListener(SrsServer* server, SrsListenerType type) 116 +SrsListener::SrsListener(SrsServer* svr, SrsListenerType t)
117 { 117 {
118 - _port = 0;  
119 - _server = server;  
120 - _type = type; 118 + port = 0;
  119 + server = svr;
  120 + type = t;
121 } 121 }
122 122
123 SrsListener::~SrsListener() 123 SrsListener::~SrsListener()
124 { 124 {
125 } 125 }
126 126
127 -SrsListenerType SrsListener::type() 127 +SrsListenerType SrsListener::listen_type()
128 { 128 {
129 - return _type; 129 + return type;
130 } 130 }
131 131
132 -SrsStreamListener::SrsStreamListener(SrsServer* server, SrsListenerType type) : SrsListener(server, type) 132 +SrsStreamListener::SrsStreamListener(SrsServer* svr, SrsListenerType t) : SrsListener(svr, t)
133 { 133 {
134 listener = NULL; 134 listener = NULL;
135 } 135 }
@@ -139,12 +139,12 @@ SrsStreamListener::~SrsStreamListener() @@ -139,12 +139,12 @@ SrsStreamListener::~SrsStreamListener()
139 srs_freep(listener); 139 srs_freep(listener);
140 } 140 }
141 141
142 -int SrsStreamListener::listen(string ip, int port) 142 +int SrsStreamListener::listen(string i, int p)
143 { 143 {
144 int ret = ERROR_SUCCESS; 144 int ret = ERROR_SUCCESS;
145 145
146 - _ip = ip;  
147 - _port = port; 146 + ip = i;
  147 + port = p;
148 148
149 srs_freep(listener); 149 srs_freep(listener);
150 listener = new SrsTcpListener(this, ip, port); 150 listener = new SrsTcpListener(this, ip, port);
@@ -158,7 +158,7 @@ int SrsStreamListener::listen(string ip, int port) @@ -158,7 +158,7 @@ int SrsStreamListener::listen(string ip, int port)
158 "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d", 158 "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d",
159 pthread->cid(), _srs_context->get_id(), _port, _type, fd, ip.c_str(), port); 159 pthread->cid(), _srs_context->get_id(), _port, _type, fd, ip.c_str(), port);
160 160
161 - srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(_type).c_str(), ip.c_str(), _port, listener->fd()); 161 + srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd());
162 162
163 return ret; 163 return ret;
164 } 164 }
@@ -167,7 +167,7 @@ int SrsStreamListener::on_tcp_client(st_netfd_t stfd) @@ -167,7 +167,7 @@ int SrsStreamListener::on_tcp_client(st_netfd_t stfd)
167 { 167 {
168 int ret = ERROR_SUCCESS; 168 int ret = ERROR_SUCCESS;
169 169
170 - if ((ret = _server->accept_client(_type, stfd)) != ERROR_SUCCESS) { 170 + if ((ret = server->accept_client(type, stfd)) != ERROR_SUCCESS) {
171 srs_warn("accept client error. ret=%d", ret); 171 srs_warn("accept client error. ret=%d", ret);
172 return ret; 172 return ret;
173 } 173 }
@@ -176,14 +176,14 @@ int SrsStreamListener::on_tcp_client(st_netfd_t stfd) @@ -176,14 +176,14 @@ int SrsStreamListener::on_tcp_client(st_netfd_t stfd)
176 } 176 }
177 177
178 #ifdef SRS_AUTO_STREAM_CASTER 178 #ifdef SRS_AUTO_STREAM_CASTER
179 -SrsRtspListener::SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type) 179 +SrsRtspListener::SrsRtspListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c) : SrsListener(svr, t)
180 { 180 {
181 listener = NULL; 181 listener = NULL;
182 182
183 // the caller already ensure the type is ok, 183 // the caller already ensure the type is ok,
184 // we just assert here for unknown stream caster. 184 // we just assert here for unknown stream caster.
185 - srs_assert(_type == SrsListenerRtsp);  
186 - if (_type == SrsListenerRtsp) { 185 + srs_assert(type == SrsListenerRtsp);
  186 + if (type == SrsListenerRtsp) {
187 caster = new SrsRtspCaster(c); 187 caster = new SrsRtspCaster(c);
188 } 188 }
189 } 189 }
@@ -194,16 +194,16 @@ SrsRtspListener::~SrsRtspListener() @@ -194,16 +194,16 @@ SrsRtspListener::~SrsRtspListener()
194 srs_freep(listener); 194 srs_freep(listener);
195 } 195 }
196 196
197 -int SrsRtspListener::listen(string ip, int port) 197 +int SrsRtspListener::listen(string i, int p)
198 { 198 {
199 int ret = ERROR_SUCCESS; 199 int ret = ERROR_SUCCESS;
200 200
201 // the caller already ensure the type is ok, 201 // the caller already ensure the type is ok,
202 // we just assert here for unknown stream caster. 202 // we just assert here for unknown stream caster.
203 - srs_assert(_type == SrsListenerRtsp); 203 + srs_assert(type == SrsListenerRtsp);
204 204
205 - _ip = ip;  
206 - _port = port; 205 + ip = i;
  206 + port = p;
207 207
208 srs_freep(listener); 208 srs_freep(listener);
209 listener = new SrsTcpListener(this, ip, port); 209 listener = new SrsTcpListener(this, ip, port);
@@ -215,9 +215,9 @@ int SrsRtspListener::listen(string ip, int port) @@ -215,9 +215,9 @@ int SrsRtspListener::listen(string ip, int port)
215 215
216 srs_info("listen thread cid=%d, current_cid=%d, " 216 srs_info("listen thread cid=%d, current_cid=%d, "
217 "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d", 217 "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d",
218 - pthread->cid(), _srs_context->get_id(), _port, _type, fd, ip.c_str(), port); 218 + pthread->cid(), _srs_context->get_id(), port, type, fd, ip.c_str(), port);
219 219
220 - srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(_type).c_str(), ip.c_str(), _port, listener->fd()); 220 + srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd());
221 221
222 return ret; 222 return ret;
223 } 223 }
@@ -234,14 +234,14 @@ int SrsRtspListener::on_tcp_client(st_netfd_t stfd) @@ -234,14 +234,14 @@ int SrsRtspListener::on_tcp_client(st_netfd_t stfd)
234 return ret; 234 return ret;
235 } 235 }
236 236
237 -SrsHttpFlvListener::SrsHttpFlvListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type) 237 +SrsHttpFlvListener::SrsHttpFlvListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c) : SrsListener(svr, t)
238 { 238 {
239 listener = NULL; 239 listener = NULL;
240 240
241 // the caller already ensure the type is ok, 241 // the caller already ensure the type is ok,
242 // we just assert here for unknown stream caster. 242 // we just assert here for unknown stream caster.
243 - srs_assert(_type == SrsListenerFlv);  
244 - if (_type == SrsListenerFlv) { 243 + srs_assert(type == SrsListenerFlv);
  244 + if (type == SrsListenerFlv) {
245 caster = new SrsAppCasterFlv(c); 245 caster = new SrsAppCasterFlv(c);
246 } 246 }
247 } 247 }
@@ -252,16 +252,16 @@ SrsHttpFlvListener::~SrsHttpFlvListener() @@ -252,16 +252,16 @@ SrsHttpFlvListener::~SrsHttpFlvListener()
252 srs_freep(listener); 252 srs_freep(listener);
253 } 253 }
254 254
255 -int SrsHttpFlvListener::listen(string ip, int port) 255 +int SrsHttpFlvListener::listen(string i, int p)
256 { 256 {
257 int ret = ERROR_SUCCESS; 257 int ret = ERROR_SUCCESS;
258 258
259 // the caller already ensure the type is ok, 259 // the caller already ensure the type is ok,
260 // we just assert here for unknown stream caster. 260 // we just assert here for unknown stream caster.
261 - srs_assert(_type == SrsListenerFlv); 261 + srs_assert(type == SrsListenerFlv);
262 262
263 - _ip = ip;  
264 - _port = port; 263 + ip = i;
  264 + port = p;
265 265
266 if ((ret = caster->initialize()) != ERROR_SUCCESS) { 266 if ((ret = caster->initialize()) != ERROR_SUCCESS) {
267 return ret; 267 return ret;
@@ -277,9 +277,9 @@ int SrsHttpFlvListener::listen(string ip, int port) @@ -277,9 +277,9 @@ int SrsHttpFlvListener::listen(string ip, int port)
277 277
278 srs_info("listen thread cid=%d, current_cid=%d, " 278 srs_info("listen thread cid=%d, current_cid=%d, "
279 "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d", 279 "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d",
280 - pthread->cid(), _srs_context->get_id(), _port, _type, fd, ip.c_str(), port); 280 + pthread->cid(), _srs_context->get_id(), port, type, fd, ip.c_str(), port);
281 281
282 - srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(_type).c_str(), ip.c_str(), _port, listener->fd()); 282 + srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd());
283 283
284 return ret; 284 return ret;
285 } 285 }
@@ -295,36 +295,29 @@ int SrsHttpFlvListener::on_tcp_client(st_netfd_t stfd) @@ -295,36 +295,29 @@ int SrsHttpFlvListener::on_tcp_client(st_netfd_t stfd)
295 295
296 return ret; 296 return ret;
297 } 297 }
  298 +#endif
298 299
299 -SrsUdpCasterListener::SrsUdpCasterListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type) 300 +SrsUdpStreamListener::SrsUdpStreamListener(SrsServer* svr, SrsListenerType t, ISrsUdpHandler* c) : SrsListener(svr, t)
300 { 301 {
301 - _type = type;  
302 listener = NULL; 302 listener = NULL;
303 -  
304 - // the caller already ensure the type is ok,  
305 - // we just assert here for unknown stream caster.  
306 - srs_assert(_type == SrsListenerMpegTsOverUdp);  
307 - if (_type == SrsListenerMpegTsOverUdp) {  
308 - caster = new SrsMpegtsOverUdp(c);  
309 - } 303 + caster = c;
310 } 304 }
311 305
312 -SrsUdpCasterListener::~SrsUdpCasterListener() 306 +SrsUdpStreamListener::~SrsUdpStreamListener()
313 { 307 {
314 - srs_freep(caster);  
315 srs_freep(listener); 308 srs_freep(listener);
316 } 309 }
317 310
318 -int SrsUdpCasterListener::listen(string ip, int port) 311 +int SrsUdpStreamListener::listen(string i, int p)
319 { 312 {
320 int ret = ERROR_SUCCESS; 313 int ret = ERROR_SUCCESS;
321 314
322 // the caller already ensure the type is ok, 315 // the caller already ensure the type is ok,
323 // we just assert here for unknown stream caster. 316 // we just assert here for unknown stream caster.
324 - srs_assert(_type == SrsListenerMpegTsOverUdp); 317 + srs_assert(type == SrsListenerMpegTsOverUdp);
325 318
326 - _ip = ip;  
327 - _port = port; 319 + ip = i;
  320 + port = p;
328 321
329 srs_freep(listener); 322 srs_freep(listener);
330 listener = new SrsUdpListener(caster, ip, port); 323 listener = new SrsUdpListener(caster, ip, port);
@@ -336,12 +329,34 @@ int SrsUdpCasterListener::listen(string ip, int port) @@ -336,12 +329,34 @@ int SrsUdpCasterListener::listen(string ip, int port)
336 329
337 srs_info("listen thread cid=%d, current_cid=%d, " 330 srs_info("listen thread cid=%d, current_cid=%d, "
338 "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d", 331 "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d",
339 - pthread->cid(), _srs_context->get_id(), _port, _type, fd, ip.c_str(), port); 332 + pthread->cid(), _srs_context->get_id(), port, type, fd, ip.c_str(), port);
  333 +
  334 + // notify the handler the fd changed.
  335 + if ((ret = caster->on_stfd_change(listener->stfd())) != ERROR_SUCCESS) {
  336 + srs_error("notify handler fd changed. ret=%d", ret);
  337 + return ret;
  338 + }
340 339
341 - srs_trace("%s listen at udp://%s:%d, fd=%d", srs_listener_type2string(_type).c_str(), ip.c_str(), _port, listener->fd()); 340 + srs_trace("%s listen at udp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd());
342 341
343 return ret; 342 return ret;
344 } 343 }
  344 +
  345 +#ifdef SRS_AUTO_STREAM_CASTER
  346 +SrsUdpCasterListener::SrsUdpCasterListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c) : SrsUdpStreamListener(svr, t, NULL)
  347 +{
  348 + // the caller already ensure the type is ok,
  349 + // we just assert here for unknown stream caster.
  350 + srs_assert(type == SrsListenerMpegTsOverUdp);
  351 + if (type == SrsListenerMpegTsOverUdp) {
  352 + caster = new SrsMpegtsOverUdp(c);
  353 + }
  354 +}
  355 +
  356 +SrsUdpCasterListener::~SrsUdpCasterListener()
  357 +{
  358 + srs_freep(caster);
  359 +}
345 #endif 360 #endif
346 361
347 SrsSignalManager* SrsSignalManager::instance = NULL; 362 SrsSignalManager* SrsSignalManager::instance = NULL;
@@ -588,6 +603,34 @@ int SrsServer::initialize(ISrsServerCycle* cycle_handler) @@ -588,6 +603,34 @@ int SrsServer::initialize(ISrsServerCycle* cycle_handler)
588 return ret; 603 return ret;
589 } 604 }
590 605
  606 +int SrsServer::initialize_st()
  607 +{
  608 + int ret = ERROR_SUCCESS;
  609 +
  610 + // init st
  611 + if ((ret = srs_init_st()) != ERROR_SUCCESS) {
  612 + srs_error("init st failed. ret=%d", ret);
  613 + return ret;
  614 + }
  615 +
  616 + // @remark, st alloc segment use mmap, which only support 32757 threads,
  617 + // if need to support more, for instance, 100k threads, define the macro MALLOC_STACK.
  618 + // TODO: FIXME: maybe can use "sysctl vm.max_map_count" to refine.
  619 + if (_srs_config->get_max_connections() > 32756) {
  620 + ret = ERROR_ST_EXCEED_THREADS;
  621 + srs_error("st mmap for stack allocation must <= %d threads, "
  622 + "@see Makefile of st for MALLOC_STACK, please build st manually by "
  623 + "\"make EXTRA_CFLAGS=-DMALLOC_STACK linux-debug\", ret=%d", ret);
  624 + return ret;
  625 + }
  626 +
  627 + // set current log id.
  628 + _srs_context->generate_id();
  629 + srs_trace("server main cid=%d", _srs_context->get_id());
  630 +
  631 + return ret;
  632 +}
  633 +
591 int SrsServer::initialize_signal() 634 int SrsServer::initialize_signal()
592 { 635 {
593 return signal_manager->initialize(); 636 return signal_manager->initialize();
@@ -669,34 +712,6 @@ int SrsServer::acquire_pid_file() @@ -669,34 +712,6 @@ int SrsServer::acquire_pid_file()
669 return ret; 712 return ret;
670 } 713 }
671 714
672 -int SrsServer::initialize_st()  
673 -{  
674 - int ret = ERROR_SUCCESS;  
675 -  
676 - // init st  
677 - if ((ret = srs_init_st()) != ERROR_SUCCESS) {  
678 - srs_error("init st failed. ret=%d", ret);  
679 - return ret;  
680 - }  
681 -  
682 - // @remark, st alloc segment use mmap, which only support 32757 threads,  
683 - // if need to support more, for instance, 100k threads, define the macro MALLOC_STACK.  
684 - // TODO: FIXME: maybe can use "sysctl vm.max_map_count" to refine.  
685 - if (_srs_config->get_max_connections() > 32756) {  
686 - ret = ERROR_ST_EXCEED_THREADS;  
687 - srs_error("st mmap for stack allocation must <= %d threads, "  
688 - "@see Makefile of st for MALLOC_STACK, please build st manually by "  
689 - "\"make EXTRA_CFLAGS=-DMALLOC_STACK linux-debug\", ret=%d", ret);  
690 - return ret;  
691 - }  
692 -  
693 - // set current log id.  
694 - _srs_context->generate_id();  
695 - srs_trace("server main cid=%d", _srs_context->get_id());  
696 -  
697 - return ret;  
698 -}  
699 -  
700 int SrsServer::listen() 715 int SrsServer::listen()
701 { 716 {
702 int ret = ERROR_SUCCESS; 717 int ret = ERROR_SUCCESS;
@@ -959,6 +974,7 @@ int SrsServer::do_cycle() @@ -959,6 +974,7 @@ int SrsServer::do_cycle()
959 } 974 }
960 #endif 975 #endif
961 #endif 976 #endif
  977 +
962 srs_info("server main thread loop"); 978 srs_info("server main thread loop");
963 } 979 }
964 } 980 }
@@ -1103,7 +1119,7 @@ void SrsServer::close_listeners(SrsListenerType type) @@ -1103,7 +1119,7 @@ void SrsServer::close_listeners(SrsListenerType type)
1103 for (it = listeners.begin(); it != listeners.end();) { 1119 for (it = listeners.begin(); it != listeners.end();) {
1104 SrsListener* listener = *it; 1120 SrsListener* listener = *it;
1105 1121
1106 - if (listener->type() != type) { 1122 + if (listener->listen_type() != type) {
1107 ++it; 1123 ++it;
1108 continue; 1124 continue;
1109 } 1125 }
@@ -1264,7 +1280,7 @@ int SrsServer::on_reload_http_stream_enabled() @@ -1264,7 +1280,7 @@ int SrsServer::on_reload_http_stream_enabled()
1264 #ifdef SRS_AUTO_HTTP_SERVER 1280 #ifdef SRS_AUTO_HTTP_SERVER
1265 ret = listen_http_stream(); 1281 ret = listen_http_stream();
1266 #endif 1282 #endif
1267 - 1283 +
1268 return ret; 1284 return ret;
1269 } 1285 }
1270 1286
@@ -80,17 +80,17 @@ enum SrsListenerType @@ -80,17 +80,17 @@ enum SrsListenerType
80 class SrsListener 80 class SrsListener
81 { 81 {
82 protected: 82 protected:
83 - SrsListenerType _type; 83 + SrsListenerType type;
84 protected: 84 protected:
85 - std::string _ip;  
86 - int _port;  
87 - SrsServer* _server; 85 + std::string ip;
  86 + int port;
  87 + SrsServer* server;
88 public: 88 public:
89 - SrsListener(SrsServer* server, SrsListenerType type); 89 + SrsListener(SrsServer* svr, SrsListenerType t);
90 virtual ~SrsListener(); 90 virtual ~SrsListener();
91 public: 91 public:
92 - virtual SrsListenerType type();  
93 - virtual int listen(std::string ip, int port) = 0; 92 + virtual SrsListenerType listen_type();
  93 + virtual int listen(std::string i, int p) = 0;
94 }; 94 };
95 95
96 /** 96 /**
@@ -120,10 +120,10 @@ private: @@ -120,10 +120,10 @@ private:
120 SrsTcpListener* listener; 120 SrsTcpListener* listener;
121 ISrsTcpHandler* caster; 121 ISrsTcpHandler* caster;
122 public: 122 public:
123 - SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c); 123 + SrsRtspListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c);
124 virtual ~SrsRtspListener(); 124 virtual ~SrsRtspListener();
125 public: 125 public:
126 - virtual int listen(std::string ip, int port); 126 + virtual int listen(std::string i, int p);
127 // ISrsTcpHandler 127 // ISrsTcpHandler
128 public: 128 public:
129 virtual int on_tcp_client(st_netfd_t stfd); 129 virtual int on_tcp_client(st_netfd_t stfd);
@@ -138,28 +138,40 @@ private: @@ -138,28 +138,40 @@ private:
138 SrsTcpListener* listener; 138 SrsTcpListener* listener;
139 SrsAppCasterFlv* caster; 139 SrsAppCasterFlv* caster;
140 public: 140 public:
141 - SrsHttpFlvListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c); 141 + SrsHttpFlvListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c);
142 virtual ~SrsHttpFlvListener(); 142 virtual ~SrsHttpFlvListener();
143 public: 143 public:
144 - virtual int listen(std::string ip, int port); 144 + virtual int listen(std::string i, int p);
145 // ISrsTcpHandler 145 // ISrsTcpHandler
146 public: 146 public:
147 virtual int on_tcp_client(st_netfd_t stfd); 147 virtual int on_tcp_client(st_netfd_t stfd);
148 }; 148 };
  149 +#endif
149 150
150 /** 151 /**
151 -* the udp listener, for udp server.  
152 -*/  
153 -class SrsUdpCasterListener : public SrsListener 152 + * the udp listener, for udp server.
  153 + */
  154 +class SrsUdpStreamListener : public SrsListener
154 { 155 {
155 -private: 156 +protected:
156 SrsUdpListener* listener; 157 SrsUdpListener* listener;
157 ISrsUdpHandler* caster; 158 ISrsUdpHandler* caster;
158 public: 159 public:
159 - SrsUdpCasterListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c);  
160 - virtual ~SrsUdpCasterListener(); 160 + SrsUdpStreamListener(SrsServer* svr, SrsListenerType t, ISrsUdpHandler* c);
  161 + virtual ~SrsUdpStreamListener();
161 public: 162 public:
162 - virtual int listen(std::string ip, int port); 163 + virtual int listen(std::string i, int p);
  164 +};
  165 +
  166 +/**
  167 + * the udp listener, for udp stream caster server.
  168 + */
  169 +#ifdef SRS_AUTO_STREAM_CASTER
  170 +class SrsUdpCasterListener : public SrsUdpStreamListener
  171 +{
  172 +public:
  173 + SrsUdpCasterListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c);
  174 + virtual ~SrsUdpCasterListener();
163 }; 175 };
164 #endif 176 #endif
165 177
@@ -337,7 +349,7 @@ public: @@ -337,7 +349,7 @@ public:
337 * @param client_stfd, the client fd in st boxed, the underlayer fd. 349 * @param client_stfd, the client fd in st boxed, the underlayer fd.
338 */ 350 */
339 virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd); 351 virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd);
340 -// interface ISrsThreadHandler. 352 +// interface ISrsReloadHandler.
341 public: 353 public:
342 virtual int on_reload_listen(); 354 virtual int on_reload_listen();
343 virtual int on_reload_pid(); 355 virtual int on_reload_pid();
@@ -45,6 +45,7 @@ using namespace std; @@ -45,6 +45,7 @@ using namespace std;
45 #include <srs_app_hds.hpp> 45 #include <srs_app_hds.hpp>
46 #include <srs_app_statistic.hpp> 46 #include <srs_app_statistic.hpp>
47 #include <srs_core_autofree.hpp> 47 #include <srs_core_autofree.hpp>
  48 +#include <srs_rtmp_utility.hpp>
48 49
49 #define CONST_MAX_JITTER_MS 500 50 #define CONST_MAX_JITTER_MS 500
50 #define DEFAULT_FRAME_TIME_MS 40 51 #define DEFAULT_FRAME_TIME_MS 40
@@ -759,6 +760,20 @@ SrsSource* SrsSource::fetch(SrsRequest* r) @@ -759,6 +760,20 @@ SrsSource* SrsSource::fetch(SrsRequest* r)
759 return source; 760 return source;
760 } 761 }
761 762
  763 +SrsSource* SrsSource::fetch(std::string vhost, std::string app, std::string stream)
  764 +{
  765 + SrsSource* source = NULL;
  766 + string stream_url = srs_generate_stream_url(vhost, app, stream);
  767 +
  768 + if (pool.find(stream_url) == pool.end()) {
  769 + return NULL;
  770 + }
  771 +
  772 + source = pool[stream_url];
  773 +
  774 + return source;
  775 +}
  776 +
762 void SrsSource::destroy() 777 void SrsSource::destroy()
763 { 778 {
764 std::map<std::string, SrsSource*>::iterator it; 779 std::map<std::string, SrsSource*>::iterator it;
@@ -407,6 +407,10 @@ public: @@ -407,6 +407,10 @@ public:
407 */ 407 */
408 static SrsSource* fetch(SrsRequest* r); 408 static SrsSource* fetch(SrsRequest* r);
409 /** 409 /**
  410 + * get the exists source by stream info(vhost, app, stream), NULL when not exists.
  411 + */
  412 + static SrsSource* fetch(std::string vhost, std::string app, std::string stream);
  413 + /**
410 * when system exit, destroy the sources, 414 * when system exit, destroy the sources,
411 * for gmc to analysis mem leaks. 415 * for gmc to analysis mem leaks.
412 */ 416 */
@@ -195,6 +195,7 @@ int SrsStatistic::on_client(int id, SrsRequest* req) @@ -195,6 +195,7 @@ int SrsStatistic::on_client(int id, SrsRequest* req)
195 SrsStatisticClient* client = NULL; 195 SrsStatisticClient* client = NULL;
196 if (clients.find(id) == clients.end()) { 196 if (clients.find(id) == clients.end()) {
197 client = new SrsStatisticClient(); 197 client = new SrsStatisticClient();
  198 + client->id = id;
198 client->stream = stream; 199 client->stream = stream;
199 clients[id] = client; 200 clients[id] = client;
200 } else { 201 } else {
@@ -32,93 +32,105 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -32,93 +32,105 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 #include <srs_app_st.hpp> 32 #include <srs_app_st.hpp>
33 33
34 /** 34 /**
35 -* the handler for the thread, callback interface.  
36 -* the thread model defines as:  
37 -* handler->on_thread_start()  
38 -* while loop:  
39 -* handler->on_before_cycle()  
40 -* handler->cycle()  
41 -* handler->on_end_cycle()  
42 -* if !loop then break for user stop thread.  
43 -* sleep(CycleIntervalMilliseconds)  
44 -* handler->on_thread_stop()  
45 -* when stop, the thread will interrupt the st_thread,  
46 -* which will cause the socket to return error and  
47 -* terminate the cycle thread.  
48 -*  
49 -* Usage 1: stop by other thread.  
50 -* user can create thread and stop then start again and again,  
51 -* generally must provides a start and stop method, @see SrsIngester.  
52 -* the step to create a thread stop by other thread:  
53 -* 1. create SrsThread field, with joinable true.  
54 -* 2. must use stop to stop and join the thread.  
55 -* for example:  
56 -* class SrsIngester : public ISrsThreadHandler {  
57 -* public: SrsIngester() { pthread = new SrsThread("ingest", this, SRS_AUTO_INGESTER_SLEEP_US, true); }  
58 -* public: virtual int start() { return pthread->start(); }  
59 -* public: virtual void stop() { pthread->stop(); }  
60 -* public: virtual int cycle() {  
61 -* // check status, start ffmpeg when stopped.  
62 -* }  
63 -* };  
64 -*  
65 -* Usage 2: stop by thread itself.  
66 -* user can create thread which stop itself,  
67 -* generally only need to provides a start method,  
68 -* the object will destroy itself then terminate the thread, @see SrsConnection  
69 -* 1. create SrsThread field, with joinable false.  
70 -* 2. owner stop thread loop, destroy itself when thread stop.  
71 -* for example:  
72 -* class SrsConnection : public ISrsThreadHandler {  
73 -* public: SrsConnection() { pthread = new SrsThread("conn", this, 0, false); }  
74 -* public: virtual int start() { return pthread->start(); }  
75 -* public: virtual int cycle() {  
76 -* // serve client.  
77 -* // set loop to stop to quit, stop thread itself.  
78 -* pthread->stop_loop();  
79 -* }  
80 -* public: virtual int on_thread_stop() {  
81 -* // remove the connection in thread itself.  
82 -* server->remove(this);  
83 -* }  
84 -* };  
85 -*  
86 -* Usage 3: loop in the cycle method.  
87 -* user can use loop code in the cycle method, @see SrsForwarder  
88 -* 1. create SrsThread field, with or without joinable is ok.  
89 -* 2. loop code in cycle method, check the can_loop() for thread to quit.  
90 -* for example:  
91 -* class SrsForwarder : public ISrsThreadHandler {  
92 -* public: virtual int cycle() {  
93 -* while (pthread->can_loop()) {  
94 -* // read msgs from queue and forward to server.  
95 -* }  
96 -* }  
97 -* };  
98 -*  
99 -* @remark why should check can_loop() in cycle method?  
100 -* when thread interrupt, the socket maybe not got EINT,  
101 -* espectially on st_usleep(), so the cycle must check the loop,  
102 -* when handler->cycle() has loop itself, for example:  
103 -* while (true):  
104 -* if (read_from_socket(skt) < 0) break;  
105 -* if thread stop when read_from_socket, it's ok, the loop will break,  
106 -* but when thread stop interrupt the s_usleep(0), then the loop is  
107 -* death loop.  
108 -* in a word, the handler->cycle() must:  
109 -* while (pthread->can_loop()):  
110 -* if (read_from_socket(skt) < 0) break;  
111 -* check the loop, then it works.  
112 -*  
113 -* @remark why should use stop_loop() to terminate thread in itself?  
114 -* in the thread itself, that is the cycle method,  
115 -* if itself want to terminate the thread, should never use stop(),  
116 -* but use stop_loop() to set the loop to false and terminate normally.  
117 -*  
118 -* @remark when should set the interval_us, and when not?  
119 -* the cycle will invoke util cannot loop, eventhough the return code of cycle is error,  
120 -* so the interval_us used to sleep for each cycle.  
121 -*/ 35 + * the handler for the thread, callback interface.
  36 + * the thread model defines as:
  37 + * handler->on_thread_start()
  38 + * while loop:
  39 + * handler->on_before_cycle()
  40 + * handler->cycle()
  41 + * handler->on_end_cycle()
  42 + * if !loop then break for user stop thread.
  43 + * sleep(CycleIntervalMilliseconds)
  44 + * handler->on_thread_stop()
  45 + * when stop, the thread will interrupt the st_thread,
  46 + * which will cause the socket to return error and
  47 + * terminate the cycle thread.
  48 + *
  49 + * Usage 1: loop thread never quit.
  50 + * user can create thread always running util server terminate.
  51 + * the step to create a thread never stop:
  52 + * 1. create SrsThread field, with joinable false.
  53 + * for example:
  54 + * class SrsStreamCache : public ISrsThreadHandler {
  55 + * public: SrsStreamCache() { pthread = new SrsThread("http-stream", this, SRS_AUTO_STREAM_SLEEP_US, false); }
  56 + * public: virtual int cycle() {
  57 + * // check status, start ffmpeg when stopped.
  58 + * }
  59 + * }
  60 + *
  61 + * Usage 2: stop by other thread.
  62 + * user can create thread and stop then start again and again,
  63 + * generally must provides a start and stop method, @see SrsIngester.
  64 + * the step to create a thread stop by other thread:
  65 + * 1. create SrsThread field, with joinable true.
  66 + * 2. must use stop to stop and join the thread.
  67 + * for example:
  68 + * class SrsIngester : public ISrsThreadHandler {
  69 + * public: SrsIngester() { pthread = new SrsThread("ingest", this, SRS_AUTO_INGESTER_SLEEP_US, true); }
  70 + * public: virtual int start() { return pthread->start(); }
  71 + * public: virtual void stop() { pthread->stop(); }
  72 + * public: virtual int cycle() {
  73 + * // check status, start ffmpeg when stopped.
  74 + * }
  75 + * };
  76 + *
  77 + * Usage 3: stop by thread itself.
  78 + * user can create thread which stop itself,
  79 + * generally only need to provides a start method,
  80 + * the object will destroy itself then terminate the thread, @see SrsConnection
  81 + * 1. create SrsThread field, with joinable false.
  82 + * 2. owner stop thread loop, destroy itself when thread stop.
  83 + * for example:
  84 + * class SrsConnection : public ISrsThreadHandler {
  85 + * public: SrsConnection() { pthread = new SrsThread("conn", this, 0, false); }
  86 + * public: virtual int start() { return pthread->start(); }
  87 + * public: virtual int cycle() {
  88 + * // serve client.
  89 + * // set loop to stop to quit, stop thread itself.
  90 + * pthread->stop_loop();
  91 + * }
  92 + * public: virtual int on_thread_stop() {
  93 + * // remove the connection in thread itself.
  94 + * server->remove(this);
  95 + * }
  96 + * };
  97 + *
  98 + * Usage 4: loop in the cycle method.
  99 + * user can use loop code in the cycle method, @see SrsForwarder
  100 + * 1. create SrsThread field, with or without joinable is ok.
  101 + * 2. loop code in cycle method, check the can_loop() for thread to quit.
  102 + * for example:
  103 + * class SrsForwarder : public ISrsThreadHandler {
  104 + * public: virtual int cycle() {
  105 + * while (pthread->can_loop()) {
  106 + * // read msgs from queue and forward to server.
  107 + * }
  108 + * }
  109 + * };
  110 + *
  111 + * @remark why should check can_loop() in cycle method?
  112 + * when thread interrupt, the socket maybe not got EINT,
  113 + * espectially on st_usleep(), so the cycle must check the loop,
  114 + * when handler->cycle() has loop itself, for example:
  115 + * while (true):
  116 + * if (read_from_socket(skt) < 0) break;
  117 + * if thread stop when read_from_socket, it's ok, the loop will break,
  118 + * but when thread stop interrupt the s_usleep(0), then the loop is
  119 + * death loop.
  120 + * in a word, the handler->cycle() must:
  121 + * while (pthread->can_loop()):
  122 + * if (read_from_socket(skt) < 0) break;
  123 + * check the loop, then it works.
  124 + *
  125 + * @remark why should use stop_loop() to terminate thread in itself?
  126 + * in the thread itself, that is the cycle method,
  127 + * if itself want to terminate the thread, should never use stop(),
  128 + * but use stop_loop() to set the loop to false and terminate normally.
  129 + *
  130 + * @remark when should set the interval_us, and when not?
  131 + * the cycle will invoke util cannot loop, eventhough the return code of cycle is error,
  132 + * so the interval_us used to sleep for each cycle.
  133 + */
122 class ISrsThreadHandler 134 class ISrsThreadHandler
123 { 135 {
124 public: 136 public:
@@ -418,15 +418,13 @@ bool get_proc_self_stat(SrsProcSelfStat& r) @@ -418,15 +418,13 @@ bool get_proc_self_stat(SrsProcSelfStat& r)
418 418
419 void srs_update_proc_stat() 419 void srs_update_proc_stat()
420 { 420 {
421 - // always assert the USER_HZ is 1/100ths  
422 // @see: http://stackoverflow.com/questions/7298646/calculating-user-nice-sys-idle-iowait-irq-and-sirq-from-proc-stat/7298711 421 // @see: http://stackoverflow.com/questions/7298646/calculating-user-nice-sys-idle-iowait-irq-and-sirq-from-proc-stat/7298711
423 - static bool user_hz_assert = false;  
424 - if (!user_hz_assert) {  
425 - user_hz_assert = true;  
426 -  
427 - int USER_HZ = sysconf(_SC_CLK_TCK);  
428 - srs_trace("USER_HZ=%d", USER_HZ);  
429 - srs_assert(USER_HZ == 100); 422 + // @see https://github.com/simple-rtmp-server/srs/issues/397
  423 + static int user_hz = 0;
  424 + if (user_hz <= 0) {
  425 + user_hz = sysconf(_SC_CLK_TCK);
  426 + srs_trace("USER_HZ=%d", user_hz);
  427 + srs_assert(user_hz > 0);
430 } 428 }
431 429
432 // system cpu stat 430 // system cpu stat
@@ -471,7 +469,7 @@ void srs_update_proc_stat() @@ -471,7 +469,7 @@ void srs_update_proc_stat()
471 int64_t total = r.sample_time - o.sample_time; 469 int64_t total = r.sample_time - o.sample_time;
472 int64_t usage = (r.utime + r.stime) - (o.utime + o.stime); 470 int64_t usage = (r.utime + r.stime) - (o.utime + o.stime);
473 if (total > 0) { 471 if (total > 0) {
474 - r.percent = (float)(usage * 1000 / (double)total / 100); 472 + r.percent = (float)(usage * 1000 / (double)total / user_hz);
475 } 473 }
476 474
477 // upate cache. 475 // upate cache.
@@ -201,6 +201,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -201,6 +201,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
201 // query string seprator 201 // query string seprator
202 #define SRS_CONSTS_HTTP_QUERY_SEP '?' 202 #define SRS_CONSTS_HTTP_QUERY_SEP '?'
203 203
  204 +// the default recv timeout.
  205 +#define SRS_HTTP_RECV_TIMEOUT_US 60 * 1000 * 1000
  206 +
204 // 6.1.1 Status Code and Reason Phrase 207 // 6.1.1 Status Code and Reason Phrase
205 #define SRS_CONSTS_HTTP_Continue 100 208 #define SRS_CONSTS_HTTP_Continue 100
206 #define SRS_CONSTS_HTTP_SwitchingProtocols 101 209 #define SRS_CONSTS_HTTP_SwitchingProtocols 101
@@ -33,6 +33,7 @@ bool srs_is_client_gracefully_close(int error_code) @@ -33,6 +33,7 @@ bool srs_is_client_gracefully_close(int error_code)
33 { 33 {
34 return error_code == ERROR_SOCKET_READ 34 return error_code == ERROR_SOCKET_READ
35 || error_code == ERROR_SOCKET_READ_FULLY 35 || error_code == ERROR_SOCKET_READ_FULLY
36 - || error_code == ERROR_SOCKET_WRITE; 36 + || error_code == ERROR_SOCKET_WRITE
  37 + || error_code == ERROR_SOCKET_TIMEOUT;
37 } 38 }
38 39
@@ -255,7 +255,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -255,7 +255,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
255 #define ERROR_HTTP_INVALID_CHUNK_HEADER 4026 255 #define ERROR_HTTP_INVALID_CHUNK_HEADER 4026
256 #define ERROR_AVC_NALU_UEV 4027 256 #define ERROR_AVC_NALU_UEV 4027
257 #define ERROR_AAC_BYTES_INVALID 4028 257 #define ERROR_AAC_BYTES_INVALID 4028
258 -#define ERROR_HTTP_REQUEST_EOF 4029 258 +#define ERROR_HTTP_REQUEST_EOF 4029
259 259
260 /////////////////////////////////////////////////////// 260 ///////////////////////////////////////////////////////
261 // user-define error. 261 // user-define error.
@@ -723,8 +723,8 @@ int SrsIngestSrsOutput::on_ts_message(SrsTsMessage* msg) @@ -723,8 +723,8 @@ int SrsIngestSrsOutput::on_ts_message(SrsTsMessage* msg)
723 // because when audio stream_number is 0, the elementary is ADTS(aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 75, 1.A.2.2 ADTS). 723 // because when audio stream_number is 0, the elementary is ADTS(aac-mp4a-format-ISO_IEC_14496-3+2001.pdf, page 75, 1.A.2.2 ADTS).
724 724
725 // about the bytes of PES_packet_data_byte, defined in hls-mpeg-ts-iso13818-1.pdf, page 58 725 // about the bytes of PES_packet_data_byte, defined in hls-mpeg-ts-iso13818-1.pdf, page 58
726 - // PES_packet_data_byte "C PES_packet_data_bytes shall be contiguous bytes of data from the elementary stream  
727 - // indicated by the packets stream_id or PID. When the elementary stream data conforms to ITU-T 726 + // PES_packet_data_byte ¨C PES_packet_data_bytes shall be contiguous bytes of data from the elementary stream
  727 + // indicated by the packet¡¯s stream_id or PID. When the elementary stream data conforms to ITU-T
728 // Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 13818-3, the PES_packet_data_bytes shall be byte aligned to the bytes of this 728 // Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 13818-3, the PES_packet_data_bytes shall be byte aligned to the bytes of this
729 // Recommendation | International Standard. The byte-order of the elementary stream shall be preserved. The number of 729 // Recommendation | International Standard. The byte-order of the elementary stream shall be preserved. The number of
730 // PES_packet_data_bytes, N, is specified by the PES_packet_length field. N shall be equal to the value indicated in the 730 // PES_packet_data_bytes, N, is specified by the PES_packet_length field. N shall be equal to the value indicated in the
@@ -735,12 +735,12 @@ int SrsIngestSrsOutput::on_ts_message(SrsTsMessage* msg) @@ -735,12 +735,12 @@ int SrsIngestSrsOutput::on_ts_message(SrsTsMessage* msg)
735 // PES_packet_data_byte field are user definable and will not be specified by ITU-T | ISO/IEC in the future. 735 // PES_packet_data_byte field are user definable and will not be specified by ITU-T | ISO/IEC in the future.
736 736
737 // about the bytes of stream_id, define in hls-mpeg-ts-iso13818-1.pdf, page 49 737 // about the bytes of stream_id, define in hls-mpeg-ts-iso13818-1.pdf, page 49
738 - // stream_id "C In Program Streams, the stream_id specifies the type and number of the elementary stream as defined by the 738 + // stream_id ¨C In Program Streams, the stream_id specifies the type and number of the elementary stream as defined by the
739 // stream_id Table 2-18. In Transport Streams, the stream_id may be set to any valid value which correctly describes the 739 // stream_id Table 2-18. In Transport Streams, the stream_id may be set to any valid value which correctly describes the
740 // elementary stream type as defined in Table 2-18. In Transport Streams, the elementary stream type is specified in the 740 // elementary stream type as defined in Table 2-18. In Transport Streams, the elementary stream type is specified in the
741 // Program Specific Information as specified in 2.4.4. 741 // Program Specific Information as specified in 2.4.4.
742 742
743 - // about the stream_id table, define in Table 2-18 "C Stream_id assignments, hls-mpeg-ts-iso13818-1.pdf, page 52. 743 + // about the stream_id table, define in Table 2-18 ¨C Stream_id assignments, hls-mpeg-ts-iso13818-1.pdf, page 52.
744 // 744 //
745 // 110x xxxx 745 // 110x xxxx
746 // ISO/IEC 13818-3 or ISO/IEC 11172-3 or ISO/IEC 13818-7 or ISO/IEC 746 // ISO/IEC 13818-3 or ISO/IEC 11172-3 or ISO/IEC 13818-7 or ISO/IEC
@@ -344,15 +344,15 @@ int run_master() @@ -344,15 +344,15 @@ int run_master()
344 { 344 {
345 int ret = ERROR_SUCCESS; 345 int ret = ERROR_SUCCESS;
346 346
347 - if ((ret = _srs_server->initialize_signal()) != ERROR_SUCCESS) { 347 + if ((ret = _srs_server->initialize_st()) != ERROR_SUCCESS) {
348 return ret; 348 return ret;
349 } 349 }
350 350
351 - if ((ret = _srs_server->acquire_pid_file()) != ERROR_SUCCESS) { 351 + if ((ret = _srs_server->initialize_signal()) != ERROR_SUCCESS) {
352 return ret; 352 return ret;
353 } 353 }
354 354
355 - if ((ret = _srs_server->initialize_st()) != ERROR_SUCCESS) { 355 + if ((ret = _srs_server->acquire_pid_file()) != ERROR_SUCCESS) {
356 return ret; 356 return ret;
357 } 357 }
358 358
@@ -38,36 +38,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -38,36 +38,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 38
39 using namespace std; 39 using namespace std;
40 40
41 -/**  
42 -* the signature for packets to client.  
43 -*/  
44 -#define RTMP_SIG_FMS_VER "3,5,3,888"  
45 -#define RTMP_SIG_AMF0_VER 0  
46 -#define RTMP_SIG_CLIENT_ID "ASAICiss"  
47 -  
48 -/**  
49 -* onStatus consts.  
50 -*/  
51 -#define StatusLevel "level"  
52 -#define StatusCode "code"  
53 -#define StatusDescription "description"  
54 -#define StatusDetails "details"  
55 -#define StatusClientId "clientid"  
56 -// status value  
57 -#define StatusLevelStatus "status"  
58 -// status error  
59 -#define StatusLevelError "error"  
60 -// code value  
61 -#define StatusCodeConnectSuccess "NetConnection.Connect.Success"  
62 -#define StatusCodeConnectRejected "NetConnection.Connect.Rejected"  
63 -#define StatusCodeStreamReset "NetStream.Play.Reset"  
64 -#define StatusCodeStreamStart "NetStream.Play.Start"  
65 -#define StatusCodeStreamPause "NetStream.Pause.Notify"  
66 -#define StatusCodeStreamUnpause "NetStream.Unpause.Notify"  
67 -#define StatusCodePublishStart "NetStream.Publish.Start"  
68 -#define StatusCodeDataStart "NetStream.Data.Start"  
69 -#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success"  
70 -  
71 // FMLE 41 // FMLE
72 #define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish" 42 #define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish"
73 #define RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH "onFCUnpublish" 43 #define RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH "onFCUnpublish"
@@ -129,15 +99,7 @@ void SrsRequest::update_auth(SrsRequest* req) @@ -129,15 +99,7 @@ void SrsRequest::update_auth(SrsRequest* req)
129 99
130 string SrsRequest::get_stream_url() 100 string SrsRequest::get_stream_url()
131 { 101 {
132 - std::string url = "";  
133 -  
134 - url += vhost;  
135 - url += "/";  
136 - url += app;  
137 - url += "/";  
138 - url += stream;  
139 -  
140 - return url; 102 + return srs_generate_stream_url(vhost, app, stream);
141 } 103 }
142 104
143 void SrsRequest::strip() 105 void SrsRequest::strip()
@@ -49,6 +49,36 @@ class SrsAmf0Object; @@ -49,6 +49,36 @@ class SrsAmf0Object;
49 class IMergeReadHandler; 49 class IMergeReadHandler;
50 50
51 /** 51 /**
  52 + * the signature for packets to client.
  53 + */
  54 +#define RTMP_SIG_FMS_VER "3,5,3,888"
  55 +#define RTMP_SIG_AMF0_VER 0
  56 +#define RTMP_SIG_CLIENT_ID "ASAICiss"
  57 +
  58 +/**
  59 + * onStatus consts.
  60 + */
  61 +#define StatusLevel "level"
  62 +#define StatusCode "code"
  63 +#define StatusDescription "description"
  64 +#define StatusDetails "details"
  65 +#define StatusClientId "clientid"
  66 +// status value
  67 +#define StatusLevelStatus "status"
  68 +// status error
  69 +#define StatusLevelError "error"
  70 +// code value
  71 +#define StatusCodeConnectSuccess "NetConnection.Connect.Success"
  72 +#define StatusCodeConnectRejected "NetConnection.Connect.Rejected"
  73 +#define StatusCodeStreamReset "NetStream.Play.Reset"
  74 +#define StatusCodeStreamStart "NetStream.Play.Start"
  75 +#define StatusCodeStreamPause "NetStream.Pause.Notify"
  76 +#define StatusCodeStreamUnpause "NetStream.Unpause.Notify"
  77 +#define StatusCodePublishStart "NetStream.Publish.Start"
  78 +#define StatusCodeDataStart "NetStream.Data.Start"
  79 +#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success"
  80 +
  81 +/**
52 * the original request from client. 82 * the original request from client.
53 */ 83 */
54 class SrsRequest 84 class SrsRequest
@@ -47,89 +47,6 @@ using namespace std; @@ -47,89 +47,6 @@ using namespace std;
47 ***************************************************************************** 47 *****************************************************************************
48 ****************************************************************************/ 48 ****************************************************************************/
49 /** 49 /**
50 -5. Protocol Control Messages  
51 -RTMP reserves message type IDs 1-7 for protocol control messages.  
52 -These messages contain information needed by the RTM Chunk Stream  
53 -protocol or RTMP itself. Protocol messages with IDs 1 & 2 are  
54 -reserved for usage with RTM Chunk Stream protocol. Protocol messages  
55 -with IDs 3-6 are reserved for usage of RTMP. Protocol message with ID  
56 -7 is used between edge server and origin server.  
57 -*/  
58 -#define RTMP_MSG_SetChunkSize 0x01  
59 -#define RTMP_MSG_AbortMessage 0x02  
60 -#define RTMP_MSG_Acknowledgement 0x03  
61 -#define RTMP_MSG_UserControlMessage 0x04  
62 -#define RTMP_MSG_WindowAcknowledgementSize 0x05  
63 -#define RTMP_MSG_SetPeerBandwidth 0x06  
64 -#define RTMP_MSG_EdgeAndOriginServerCommand 0x07  
65 -/**  
66 -3. Types of messages  
67 -The server and the client send messages over the network to  
68 -communicate with each other. The messages can be of any type which  
69 -includes audio messages, video messages, command messages, shared  
70 -object messages, data messages, and user control messages.  
71 -3.1. Command message  
72 -Command messages carry the AMF-encoded commands between the client  
73 -and the server. These messages have been assigned message type value  
74 -of 20 for AMF0 encoding and message type value of 17 for AMF3  
75 -encoding. These messages are sent to perform some operations like  
76 -connect, createStream, publish, play, pause on the peer. Command  
77 -messages like onstatus, result etc. are used to inform the sender  
78 -about the status of the requested commands. A command message  
79 -consists of command name, transaction ID, and command object that  
80 -contains related parameters. A client or a server can request Remote  
81 -Procedure Calls (RPC) over streams that are communicated using the  
82 -command messages to the peer.  
83 -*/  
84 -#define RTMP_MSG_AMF3CommandMessage 17 // 0x11  
85 -#define RTMP_MSG_AMF0CommandMessage 20 // 0x14  
86 -/**  
87 -3.2. Data message  
88 -The client or the server sends this message to send Metadata or any  
89 -user data to the peer. Metadata includes details about the  
90 -data(audio, video etc.) like creation time, duration, theme and so  
91 -on. These messages have been assigned message type value of 18 for  
92 -AMF0 and message type value of 15 for AMF3.  
93 -*/  
94 -#define RTMP_MSG_AMF0DataMessage 18 // 0x12  
95 -#define RTMP_MSG_AMF3DataMessage 15 // 0x0F  
96 -/**  
97 -3.3. Shared object message  
98 -A shared object is a Flash object (a collection of name value pairs)  
99 -that are in synchronization across multiple clients, instances, and  
100 -so on. The message types kMsgContainer=19 for AMF0 and  
101 -kMsgContainerEx=16 for AMF3 are reserved for shared object events.  
102 -Each message can contain multiple events.  
103 -*/  
104 -#define RTMP_MSG_AMF3SharedObject 16 // 0x10  
105 -#define RTMP_MSG_AMF0SharedObject 19 // 0x13  
106 -/**  
107 -3.4. Audio message  
108 -The client or the server sends this message to send audio data to the  
109 -peer. The message type value of 8 is reserved for audio messages.  
110 -*/  
111 -#define RTMP_MSG_AudioMessage 8 // 0x08  
112 -/* *  
113 -3.5. Video message  
114 -The client or the server sends this message to send video data to the  
115 -peer. The message type value of 9 is reserved for video messages.  
116 -These messages are large and can delay the sending of other type of  
117 -messages. To avoid such a situation, the video message is assigned  
118 -the lowest priority.  
119 -*/  
120 -#define RTMP_MSG_VideoMessage 9 // 0x09  
121 -/**  
122 -3.6. Aggregate message  
123 -An aggregate message is a single message that contains a list of submessages.  
124 -The message type value of 22 is reserved for aggregate  
125 -messages.  
126 -*/  
127 -#define RTMP_MSG_AggregateMessage 22 // 0x16  
128 -  
129 -/****************************************************************************  
130 -*****************************************************************************  
131 -****************************************************************************/  
132 -/**  
133 * 6.1.2. Chunk Message Header 50 * 6.1.2. Chunk Message Header
134 * There are four different formats for the chunk message header, 51 * There are four different formats for the chunk message header,
135 * selected by the "fmt" field in the chunk basic header. 52 * selected by the "fmt" field in the chunk basic header.
@@ -173,24 +90,6 @@ messages. @@ -173,24 +90,6 @@ messages.
173 ***************************************************************************** 90 *****************************************************************************
174 ****************************************************************************/ 91 ****************************************************************************/
175 /** 92 /**
176 -* amf0 command message, command name macros  
177 -*/  
178 -#define RTMP_AMF0_COMMAND_CONNECT "connect"  
179 -#define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream"  
180 -#define RTMP_AMF0_COMMAND_CLOSE_STREAM "closeStream"  
181 -#define RTMP_AMF0_COMMAND_PLAY "play"  
182 -#define RTMP_AMF0_COMMAND_PAUSE "pause"  
183 -#define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone"  
184 -#define RTMP_AMF0_COMMAND_ON_STATUS "onStatus"  
185 -#define RTMP_AMF0_COMMAND_RESULT "_result"  
186 -#define RTMP_AMF0_COMMAND_ERROR "_error"  
187 -#define RTMP_AMF0_COMMAND_RELEASE_STREAM "releaseStream"  
188 -#define RTMP_AMF0_COMMAND_FC_PUBLISH "FCPublish"  
189 -#define RTMP_AMF0_COMMAND_UNPUBLISH "FCUnpublish"  
190 -#define RTMP_AMF0_COMMAND_PUBLISH "publish"  
191 -#define RTMP_AMF0_DATA_SAMPLE_ACCESS "|RtmpSampleAccess"  
192 -  
193 -/**  
194 * band width check method name, which will be invoked by client. 93 * band width check method name, which will be invoked by client.
195 * band width check mothods use SrsBandwidthPacket as its internal packet type, 94 * band width check mothods use SrsBandwidthPacket as its internal packet type,
196 * so ensure you set command name when you use it. 95 * so ensure you set command name when you use it.
@@ -57,6 +57,110 @@ class SrsSharedPtrMessage; @@ -57,6 +57,110 @@ class SrsSharedPtrMessage;
57 class IMergeReadHandler; 57 class IMergeReadHandler;
58 58
59 /**************************************************************************** 59 /****************************************************************************
  60 + *****************************************************************************
  61 + ****************************************************************************/
  62 +/**
  63 + 5. Protocol Control Messages
  64 + RTMP reserves message type IDs 1-7 for protocol control messages.
  65 + These messages contain information needed by the RTM Chunk Stream
  66 + protocol or RTMP itself. Protocol messages with IDs 1 & 2 are
  67 + reserved for usage with RTM Chunk Stream protocol. Protocol messages
  68 + with IDs 3-6 are reserved for usage of RTMP. Protocol message with ID
  69 + 7 is used between edge server and origin server.
  70 + */
  71 +#define RTMP_MSG_SetChunkSize 0x01
  72 +#define RTMP_MSG_AbortMessage 0x02
  73 +#define RTMP_MSG_Acknowledgement 0x03
  74 +#define RTMP_MSG_UserControlMessage 0x04
  75 +#define RTMP_MSG_WindowAcknowledgementSize 0x05
  76 +#define RTMP_MSG_SetPeerBandwidth 0x06
  77 +#define RTMP_MSG_EdgeAndOriginServerCommand 0x07
  78 +/**
  79 + 3. Types of messages
  80 + The server and the client send messages over the network to
  81 + communicate with each other. The messages can be of any type which
  82 + includes audio messages, video messages, command messages, shared
  83 + object messages, data messages, and user control messages.
  84 + 3.1. Command message
  85 + Command messages carry the AMF-encoded commands between the client
  86 + and the server. These messages have been assigned message type value
  87 + of 20 for AMF0 encoding and message type value of 17 for AMF3
  88 + encoding. These messages are sent to perform some operations like
  89 + connect, createStream, publish, play, pause on the peer. Command
  90 + messages like onstatus, result etc. are used to inform the sender
  91 + about the status of the requested commands. A command message
  92 + consists of command name, transaction ID, and command object that
  93 + contains related parameters. A client or a server can request Remote
  94 + Procedure Calls (RPC) over streams that are communicated using the
  95 + command messages to the peer.
  96 + */
  97 +#define RTMP_MSG_AMF3CommandMessage 17 // 0x11
  98 +#define RTMP_MSG_AMF0CommandMessage 20 // 0x14
  99 +/**
  100 + 3.2. Data message
  101 + The client or the server sends this message to send Metadata or any
  102 + user data to the peer. Metadata includes details about the
  103 + data(audio, video etc.) like creation time, duration, theme and so
  104 + on. These messages have been assigned message type value of 18 for
  105 + AMF0 and message type value of 15 for AMF3.
  106 + */
  107 +#define RTMP_MSG_AMF0DataMessage 18 // 0x12
  108 +#define RTMP_MSG_AMF3DataMessage 15 // 0x0F
  109 +/**
  110 + 3.3. Shared object message
  111 + A shared object is a Flash object (a collection of name value pairs)
  112 + that are in synchronization across multiple clients, instances, and
  113 + so on. The message types kMsgContainer=19 for AMF0 and
  114 + kMsgContainerEx=16 for AMF3 are reserved for shared object events.
  115 + Each message can contain multiple events.
  116 + */
  117 +#define RTMP_MSG_AMF3SharedObject 16 // 0x10
  118 +#define RTMP_MSG_AMF0SharedObject 19 // 0x13
  119 +/**
  120 + 3.4. Audio message
  121 + The client or the server sends this message to send audio data to the
  122 + peer. The message type value of 8 is reserved for audio messages.
  123 + */
  124 +#define RTMP_MSG_AudioMessage 8 // 0x08
  125 +/* *
  126 + 3.5. Video message
  127 + The client or the server sends this message to send video data to the
  128 + peer. The message type value of 9 is reserved for video messages.
  129 + These messages are large and can delay the sending of other type of
  130 + messages. To avoid such a situation, the video message is assigned
  131 + the lowest priority.
  132 + */
  133 +#define RTMP_MSG_VideoMessage 9 // 0x09
  134 +/**
  135 + 3.6. Aggregate message
  136 + An aggregate message is a single message that contains a list of submessages.
  137 + The message type value of 22 is reserved for aggregate
  138 + messages.
  139 + */
  140 +#define RTMP_MSG_AggregateMessage 22 // 0x16
  141 +
  142 +/****************************************************************************
  143 + *****************************************************************************
  144 + ****************************************************************************/
  145 +/**
  146 + * amf0 command message, command name macros
  147 + */
  148 +#define RTMP_AMF0_COMMAND_CONNECT "connect"
  149 +#define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream"
  150 +#define RTMP_AMF0_COMMAND_CLOSE_STREAM "closeStream"
  151 +#define RTMP_AMF0_COMMAND_PLAY "play"
  152 +#define RTMP_AMF0_COMMAND_PAUSE "pause"
  153 +#define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone"
  154 +#define RTMP_AMF0_COMMAND_ON_STATUS "onStatus"
  155 +#define RTMP_AMF0_COMMAND_RESULT "_result"
  156 +#define RTMP_AMF0_COMMAND_ERROR "_error"
  157 +#define RTMP_AMF0_COMMAND_RELEASE_STREAM "releaseStream"
  158 +#define RTMP_AMF0_COMMAND_FC_PUBLISH "FCPublish"
  159 +#define RTMP_AMF0_COMMAND_UNPUBLISH "FCUnpublish"
  160 +#define RTMP_AMF0_COMMAND_PUBLISH "publish"
  161 +#define RTMP_AMF0_DATA_SAMPLE_ACCESS "|RtmpSampleAccess"
  162 +
  163 +/****************************************************************************
60 ***************************************************************************** 164 *****************************************************************************
61 ****************************************************************************/ 165 ****************************************************************************/
62 /** 166 /**
@@ -31,6 +31,7 @@ using namespace std; @@ -31,6 +31,7 @@ using namespace std;
31 #include <srs_kernel_stream.hpp> 31 #include <srs_kernel_stream.hpp>
32 #include <srs_rtmp_stack.hpp> 32 #include <srs_rtmp_stack.hpp>
33 #include <srs_kernel_codec.hpp> 33 #include <srs_kernel_codec.hpp>
  34 +#include <srs_kernel_consts.hpp>
34 35
35 void srs_discovery_tc_url( 36 void srs_discovery_tc_url(
36 string tcUrl, 37 string tcUrl,
@@ -78,22 +79,22 @@ void srs_vhost_resolve(string& vhost, string& app, string& param) @@ -78,22 +79,22 @@ void srs_vhost_resolve(string& vhost, string& app, string& param)
78 app = srs_string_replace(app, "&&", "?"); 79 app = srs_string_replace(app, "&&", "?");
79 app = srs_string_replace(app, "=", "?"); 80 app = srs_string_replace(app, "=", "?");
80 81
81 - if ((pos = app.find("?")) == std::string::npos) {  
82 - return;  
83 - }  
84 -  
85 - std::string query = app.substr(pos + 1);  
86 - app = app.substr(0, pos);  
87 -  
88 - if ((pos = query.find("vhost?")) != std::string::npos) {  
89 - query = query.substr(pos + 6);  
90 - if (!query.empty()) {  
91 - vhost = query;  
92 - }  
93 - if ((pos = vhost.find("?")) != std::string::npos) {  
94 - vhost = vhost.substr(0, pos); 82 + if ((pos = app.find("?")) != std::string::npos) {
  83 + std::string query = app.substr(pos + 1);
  84 + app = app.substr(0, pos);
  85 +
  86 + if ((pos = query.find("vhost?")) != std::string::npos) {
  87 + query = query.substr(pos + 6);
  88 + if (!query.empty()) {
  89 + vhost = query;
  90 + }
  91 + if ((pos = vhost.find("?")) != std::string::npos) {
  92 + vhost = vhost.substr(0, pos);
  93 + }
95 } 94 }
96 } 95 }
  96 +
  97 + /* others */
97 } 98 }
98 99
99 void srs_random_generate(char* bytes, int size) 100 void srs_random_generate(char* bytes, int size)
@@ -346,3 +347,18 @@ int srs_rtmp_create_msg(char type, u_int32_t timestamp, char* data, int size, in @@ -346,3 +347,18 @@ int srs_rtmp_create_msg(char type, u_int32_t timestamp, char* data, int size, in
346 return ret; 347 return ret;
347 } 348 }
348 349
  350 +std::string srs_generate_stream_url(std::string vhost, std::string app, std::string stream)
  351 +{
  352 + std::string url = "";
  353 +
  354 + if (SRS_CONSTS_RTMP_DEFAULT_VHOST != vhost){
  355 + url += vhost;
  356 + }
  357 + url += "/";
  358 + url += app;
  359 + url += "/";
  360 + url += stream;
  361 +
  362 + return url;
  363 +}
  364 +
@@ -63,7 +63,9 @@ extern void srs_discovery_tc_url( @@ -63,7 +63,9 @@ extern void srs_discovery_tc_url(
63 * app...vhost...request_vhost 63 * app...vhost...request_vhost
64 * @param param, the query, for example, ?vhost=xxx 64 * @param param, the query, for example, ?vhost=xxx
65 */ 65 */
66 -extern void srs_vhost_resolve(std::string& vhost, std::string& app, std::string& param); 66 +extern void srs_vhost_resolve(
  67 + std::string& vhost, std::string& app, std::string& param
  68 +);
67 69
68 /** 70 /**
69 * generate ramdom data for handshake. 71 * generate ramdom data for handshake.
@@ -118,5 +120,8 @@ extern int srs_chunk_header_c3( @@ -118,5 +120,8 @@ extern int srs_chunk_header_c3(
118 */ 120 */
119 extern int srs_rtmp_create_msg(char type, u_int32_t timestamp, char* data, int size, int stream_id, SrsSharedPtrMessage** ppmsg); 121 extern int srs_rtmp_create_msg(char type, u_int32_t timestamp, char* data, int size, int stream_id, SrsSharedPtrMessage** ppmsg);
120 122
  123 +// get the stream identify, vhost/app/stream.
  124 +extern std::string srs_generate_stream_url(std::string vhost, std::string app, std::string stream);
  125 +
121 #endif 126 #endif
122 127