From 0f7cafe50b87a2d43e126a5cdfeaf1106670e9a7 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 15 May 2015 14:34:59 +0800 Subject: [PATCH 1/8] order the xcode project --- .../srs_xcode.xcodeproj/project.pbxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj index 94b678670..86c640b4c 100644 --- a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj +++ b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj @@ -408,17 +408,17 @@ isa = PBXGroup; children = ( 3C1232B81AAE824500CE8F6C /* configure */, - 3C36DB541ABD1CA70066CCAF /* libs */, - 3C1EE6AF1AB107EE00576EE9 /* conf */, - 3C1232EF1AAEAC5800CE8F6C /* etc */, - 3C1232BA1AAE826F00CE8F6C /* auto */, - 3C1232B91AAE825100CE8F6C /* scripts */, - 3C12324B1AAE81CE00CE8F6C /* app */, - 3C12322C1AAE819900CE8F6C /* protocol */, + 3C1231EF1AAE651100CE8F6C /* core */, 3C1232071AAE814200CE8F6C /* kernel */, + 3C12322C1AAE819900CE8F6C /* protocol */, + 3C12324B1AAE81CE00CE8F6C /* app */, 3C1232041AAE80CB00CE8F6C /* main */, 3C1231F91AAE670E00CE8F6C /* objs */, - 3C1231EF1AAE651100CE8F6C /* core */, + 3C1232BA1AAE826F00CE8F6C /* auto */, + 3C1232B91AAE825100CE8F6C /* scripts */, + 3C1EE6AF1AB107EE00576EE9 /* conf */, + 3C36DB541ABD1CA70066CCAF /* libs */, + 3C1232EF1AAEAC5800CE8F6C /* etc */, ); path = srs_xcode; sourceTree = ""; From 44bc7976ac60970d24d13bae657db07dfee28b46 Mon Sep 17 00:00:00 2001 From: winlin Date: Tue, 19 May 2015 18:06:20 +0800 Subject: [PATCH 2/8] merge from bravo system, add the rtmfp to bms(commercial srs). 2.0.163. --- README.md | 1 + .../srs_xcode.xcodeproj/project.pbxproj | 8 +- trunk/src/app/srs_app_config.cpp | 14 +- trunk/src/app/srs_app_reload.cpp | 5 + trunk/src/app/srs_app_reload.hpp | 2 + trunk/src/app/srs_app_rtmp_conn.cpp | 28 +-- trunk/src/app/srs_app_server.cpp | 164 ++++++++++-------- trunk/src/app/srs_app_server.hpp | 50 ++++-- trunk/src/core/srs_core.hpp | 2 +- trunk/src/main/srs_main_ingest_hls.cpp | 8 +- trunk/src/main/srs_main_server.cpp | 8 +- trunk/src/protocol/srs_rtmp_sdk.cpp | 30 ---- trunk/src/protocol/srs_rtmp_sdk.hpp | 30 ++++ trunk/src/protocol/srs_rtmp_stack.cpp | 101 ----------- trunk/src/protocol/srs_rtmp_stack.hpp | 104 +++++++++++ trunk/src/protocol/srs_rtmp_utility.cpp | 28 +-- trunk/src/protocol/srs_rtmp_utility.hpp | 4 +- 17 files changed, 317 insertions(+), 270 deletions(-) diff --git a/README.md b/README.md index fab5c9d27..2f136b943 100755 --- a/README.md +++ b/README.md @@ -562,6 +562,7 @@ Supported operating systems and hardware: ### SRS 2.0 history +* v2.0, 2015-05-19, merge from bravo system, add the rtmfp to bms(commercial srs). 2.0.163. * v2.0, 2015-05-10, support push flv stream over HTTP POST to SRS. * v2.0, 2015-04-20, support ingest hls live stream to RTMP. * v2.0, 2015-04-15, for [#383](https://github.com/simple-rtmp-server/srs/issues/383), support mix_correct algorithm. 2.0.161. diff --git a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj index 86c640b4c..6daf2f9b7 100644 --- a/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj +++ b/trunk/ide/srs_xcode/srs_xcode.xcodeproj/project.pbxproj @@ -514,12 +514,12 @@ 3C12324B1AAE81CE00CE8F6C /* app */ = { isa = PBXGroup; children = ( - 3C28EDDD1AF5C43F00A3AEAC /* srs_app_caster_flv.cpp */, - 3C28EDDE1AF5C43F00A3AEAC /* srs_app_caster_flv.hpp */, 3CD88B3D1ACA9C58000359E0 /* srs_app_async_call.cpp */, 3CD88B3E1ACA9C58000359E0 /* srs_app_async_call.hpp */, 3C12324C1AAE81D900CE8F6C /* srs_app_bandwidth.cpp */, 3C12324D1AAE81D900CE8F6C /* srs_app_bandwidth.hpp */, + 3C28EDDD1AF5C43F00A3AEAC /* srs_app_caster_flv.cpp */, + 3C28EDDE1AF5C43F00A3AEAC /* srs_app_caster_flv.hpp */, 3C12324E1AAE81D900CE8F6C /* srs_app_config.cpp */, 3C12324F1AAE81D900CE8F6C /* srs_app_config.hpp */, 3C1232501AAE81D900CE8F6C /* srs_app_conn.cpp */, @@ -536,10 +536,10 @@ 3C12325B1AAE81D900CE8F6C /* srs_app_ffmpeg.hpp */, 3C12325C1AAE81D900CE8F6C /* srs_app_forward.cpp */, 3C12325D1AAE81D900CE8F6C /* srs_app_forward.hpp */, - 3C12325E1AAE81D900CE8F6C /* srs_app_heartbeat.cpp */, - 3C12325F1AAE81D900CE8F6C /* srs_app_heartbeat.hpp */, 3C1EE6AC1AB1055800576EE9 /* srs_app_hds.cpp */, 3C1EE6AD1AB1055800576EE9 /* srs_app_hds.hpp */, + 3C12325E1AAE81D900CE8F6C /* srs_app_heartbeat.cpp */, + 3C12325F1AAE81D900CE8F6C /* srs_app_heartbeat.hpp */, 3C1232601AAE81D900CE8F6C /* srs_app_hls.cpp */, 3C1232611AAE81D900CE8F6C /* srs_app_hls.hpp */, 3C1232621AAE81D900CE8F6C /* srs_app_http_api.cpp */, diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 59aec4328..356b85bab 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -441,10 +441,22 @@ int SrsConfig::reload_conf(SrsConfig* conf) // daemon // // always support reload without additional code: - // chunk_size, ff_log_dir, max_connections, + // chunk_size, ff_log_dir, // bandcheck, http_hooks, heartbeat, // token_traverse, debug_srs_upnode, // security + + // merge config: max_connections + if (!srs_directive_equals(root->get("max_connections"), old_root->get("max_connections"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + ISrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_max_conns()) != ERROR_SUCCESS) { + srs_error("notify subscribes reload max_connections failed. ret=%d", ret); + return ret; + } + } + srs_trace("reload max_connections success."); + } // merge config: listen if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) { diff --git a/trunk/src/app/srs_app_reload.cpp b/trunk/src/app/srs_app_reload.cpp index ffd1868b1..ff856d344 100644 --- a/trunk/src/app/srs_app_reload.cpp +++ b/trunk/src/app/srs_app_reload.cpp @@ -40,6 +40,11 @@ int ISrsReloadHandler::on_reload_listen() return ERROR_SUCCESS; } +int ISrsReloadHandler::on_reload_max_conns() +{ + return ERROR_SUCCESS; +} + int ISrsReloadHandler::on_reload_pid() { return ERROR_SUCCESS; diff --git a/trunk/src/app/srs_app_reload.hpp b/trunk/src/app/srs_app_reload.hpp index 2e9ad3d81..8b6e9e4d8 100644 --- a/trunk/src/app/srs_app_reload.hpp +++ b/trunk/src/app/srs_app_reload.hpp @@ -44,6 +44,7 @@ public: ISrsReloadHandler(); virtual ~ISrsReloadHandler(); public: + virtual int on_reload_max_conns(); virtual int on_reload_listen(); virtual int on_reload_pid(); virtual int on_reload_log_tank(); @@ -55,6 +56,7 @@ public: virtual int on_reload_http_stream_enabled(); virtual int on_reload_http_stream_disabled(); virtual int on_reload_http_stream_updated(); +public: virtual int on_reload_vhost_http_updated(); virtual int on_reload_vhost_http_remux_updated(); virtual int on_reload_vhost_added(std::string vhost); diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index 6b0583f49..efadfa969 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -1068,24 +1068,24 @@ int SrsRtmpConn::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessag return ret; } - // pause or other msg. + // pause SrsPausePacket* pause = dynamic_cast(pkt); - if (!pause) { - srs_info("ignore all amf0/amf3 command except pause."); + if (pause) { + if ((ret = rtmp->on_play_client_pause(res->stream_id, pause->is_pause)) != ERROR_SUCCESS) { + srs_error("rtmp process play client pause failed. ret=%d", ret); + return ret; + } + + if ((ret = consumer->on_play_client_pause(pause->is_pause)) != ERROR_SUCCESS) { + srs_error("consumer process play client pause failed. ret=%d", ret); + return ret; + } + srs_info("process pause success, is_pause=%d, time=%d.", pause->is_pause, pause->time_ms); return ret; } - if ((ret = rtmp->on_play_client_pause(res->stream_id, pause->is_pause)) != ERROR_SUCCESS) { - srs_error("rtmp process play client pause failed. ret=%d", ret); - return ret; - } - - if ((ret = consumer->on_play_client_pause(pause->is_pause)) != ERROR_SUCCESS) { - srs_error("consumer process play client pause failed. ret=%d", ret); - return ret; - } - srs_info("process pause success, is_pause=%d, time=%d.", pause->is_pause, pause->time_ms); - + // other msg. + srs_info("ignore all amf0/amf3 command except pause and video control."); return ret; } diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index 9b06c8a9d..d91b5101d 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -113,23 +113,23 @@ std::string srs_listener_type2string(SrsListenerType type) } } -SrsListener::SrsListener(SrsServer* server, SrsListenerType type) +SrsListener::SrsListener(SrsServer* svr, SrsListenerType t) { - _port = 0; - _server = server; - _type = type; + port = 0; + server = svr; + type = t; } SrsListener::~SrsListener() { } -SrsListenerType SrsListener::type() +SrsListenerType SrsListener::listen_type() { - return _type; + return type; } -SrsStreamListener::SrsStreamListener(SrsServer* server, SrsListenerType type) : SrsListener(server, type) +SrsStreamListener::SrsStreamListener(SrsServer* svr, SrsListenerType t) : SrsListener(svr, t) { listener = NULL; } @@ -139,12 +139,12 @@ SrsStreamListener::~SrsStreamListener() srs_freep(listener); } -int SrsStreamListener::listen(string ip, int port) +int SrsStreamListener::listen(string i, int p) { int ret = ERROR_SUCCESS; - _ip = ip; - _port = port; + ip = i; + port = p; srs_freep(listener); listener = new SrsTcpListener(this, ip, port); @@ -158,7 +158,7 @@ int SrsStreamListener::listen(string ip, int port) "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d", pthread->cid(), _srs_context->get_id(), _port, _type, fd, ip.c_str(), port); - srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(_type).c_str(), ip.c_str(), _port, listener->fd()); + srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd()); return ret; } @@ -167,7 +167,7 @@ int SrsStreamListener::on_tcp_client(st_netfd_t stfd) { int ret = ERROR_SUCCESS; - if ((ret = _server->accept_client(_type, stfd)) != ERROR_SUCCESS) { + if ((ret = server->accept_client(type, stfd)) != ERROR_SUCCESS) { srs_warn("accept client error. ret=%d", ret); return ret; } @@ -176,14 +176,14 @@ int SrsStreamListener::on_tcp_client(st_netfd_t stfd) } #ifdef SRS_AUTO_STREAM_CASTER -SrsRtspListener::SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type) +SrsRtspListener::SrsRtspListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c) : SrsListener(svr, t) { listener = NULL; // the caller already ensure the type is ok, // we just assert here for unknown stream caster. - srs_assert(_type == SrsListenerRtsp); - if (_type == SrsListenerRtsp) { + srs_assert(type == SrsListenerRtsp); + if (type == SrsListenerRtsp) { caster = new SrsRtspCaster(c); } } @@ -194,16 +194,16 @@ SrsRtspListener::~SrsRtspListener() srs_freep(listener); } -int SrsRtspListener::listen(string ip, int port) +int SrsRtspListener::listen(string i, int p) { int ret = ERROR_SUCCESS; // the caller already ensure the type is ok, // we just assert here for unknown stream caster. - srs_assert(_type == SrsListenerRtsp); + srs_assert(type == SrsListenerRtsp); - _ip = ip; - _port = port; + ip = i; + port = p; srs_freep(listener); listener = new SrsTcpListener(this, ip, port); @@ -215,9 +215,9 @@ int SrsRtspListener::listen(string ip, int port) srs_info("listen thread cid=%d, current_cid=%d, " "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d", - pthread->cid(), _srs_context->get_id(), _port, _type, fd, ip.c_str(), port); + pthread->cid(), _srs_context->get_id(), port, type, fd, ip.c_str(), port); - srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(_type).c_str(), ip.c_str(), _port, listener->fd()); + srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd()); return ret; } @@ -234,14 +234,14 @@ int SrsRtspListener::on_tcp_client(st_netfd_t stfd) return ret; } -SrsHttpFlvListener::SrsHttpFlvListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type) +SrsHttpFlvListener::SrsHttpFlvListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c) : SrsListener(svr, t) { listener = NULL; // the caller already ensure the type is ok, // we just assert here for unknown stream caster. - srs_assert(_type == SrsListenerFlv); - if (_type == SrsListenerFlv) { + srs_assert(type == SrsListenerFlv); + if (type == SrsListenerFlv) { caster = new SrsAppCasterFlv(c); } } @@ -252,16 +252,16 @@ SrsHttpFlvListener::~SrsHttpFlvListener() srs_freep(listener); } -int SrsHttpFlvListener::listen(string ip, int port) +int SrsHttpFlvListener::listen(string i, int p) { int ret = ERROR_SUCCESS; // the caller already ensure the type is ok, // we just assert here for unknown stream caster. - srs_assert(_type == SrsListenerFlv); + srs_assert(type == SrsListenerFlv); - _ip = ip; - _port = port; + ip = i; + port = p; if ((ret = caster->initialize()) != ERROR_SUCCESS) { return ret; @@ -277,9 +277,9 @@ int SrsHttpFlvListener::listen(string ip, int port) srs_info("listen thread cid=%d, current_cid=%d, " "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d", - pthread->cid(), _srs_context->get_id(), _port, _type, fd, ip.c_str(), port); + pthread->cid(), _srs_context->get_id(), port, type, fd, ip.c_str(), port); - srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(_type).c_str(), ip.c_str(), _port, listener->fd()); + srs_trace("%s listen at tcp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd()); return ret; } @@ -295,36 +295,29 @@ int SrsHttpFlvListener::on_tcp_client(st_netfd_t stfd) return ret; } +#endif -SrsUdpCasterListener::SrsUdpCasterListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c) : SrsListener(server, type) +SrsUdpStreamListener::SrsUdpStreamListener(SrsServer* svr, SrsListenerType t, ISrsUdpHandler* c) : SrsListener(svr, t) { - _type = type; listener = NULL; - - // the caller already ensure the type is ok, - // we just assert here for unknown stream caster. - srs_assert(_type == SrsListenerMpegTsOverUdp); - if (_type == SrsListenerMpegTsOverUdp) { - caster = new SrsMpegtsOverUdp(c); - } + caster = c; } -SrsUdpCasterListener::~SrsUdpCasterListener() +SrsUdpStreamListener::~SrsUdpStreamListener() { - srs_freep(caster); srs_freep(listener); } -int SrsUdpCasterListener::listen(string ip, int port) +int SrsUdpStreamListener::listen(string i, int p) { int ret = ERROR_SUCCESS; // the caller already ensure the type is ok, // we just assert here for unknown stream caster. - srs_assert(_type == SrsListenerMpegTsOverUdp); + srs_assert(type == SrsListenerMpegTsOverUdp); - _ip = ip; - _port = port; + ip = i; + port = p; srs_freep(listener); listener = new SrsUdpListener(caster, ip, port); @@ -336,12 +329,28 @@ int SrsUdpCasterListener::listen(string ip, int port) srs_info("listen thread cid=%d, current_cid=%d, " "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d", - pthread->cid(), _srs_context->get_id(), _port, _type, fd, ip.c_str(), port); + pthread->cid(), _srs_context->get_id(), port, type, fd, ip.c_str(), port); - srs_trace("%s listen at udp://%s:%d, fd=%d", srs_listener_type2string(_type).c_str(), ip.c_str(), _port, listener->fd()); + srs_trace("%s listen at udp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd()); return ret; } + +#ifdef SRS_AUTO_STREAM_CASTER +SrsUdpCasterListener::SrsUdpCasterListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c) : SrsUdpStreamListener(svr, t, NULL) +{ + // the caller already ensure the type is ok, + // we just assert here for unknown stream caster. + srs_assert(type == SrsListenerMpegTsOverUdp); + if (type == SrsListenerMpegTsOverUdp) { + caster = new SrsMpegtsOverUdp(c); + } +} + +SrsUdpCasterListener::~SrsUdpCasterListener() +{ + srs_freep(caster); +} #endif SrsSignalManager* SrsSignalManager::instance = NULL; @@ -588,6 +597,34 @@ int SrsServer::initialize(ISrsServerCycle* cycle_handler) return ret; } +int SrsServer::initialize_st() +{ + int ret = ERROR_SUCCESS; + + // init st + if ((ret = srs_init_st()) != ERROR_SUCCESS) { + srs_error("init st failed. ret=%d", ret); + return ret; + } + + // @remark, st alloc segment use mmap, which only support 32757 threads, + // if need to support more, for instance, 100k threads, define the macro MALLOC_STACK. + // TODO: FIXME: maybe can use "sysctl vm.max_map_count" to refine. + if (_srs_config->get_max_connections() > 32756) { + ret = ERROR_ST_EXCEED_THREADS; + srs_error("st mmap for stack allocation must <= %d threads, " + "@see Makefile of st for MALLOC_STACK, please build st manually by " + "\"make EXTRA_CFLAGS=-DMALLOC_STACK linux-debug\", ret=%d", ret); + return ret; + } + + // set current log id. + _srs_context->generate_id(); + srs_trace("server main cid=%d", _srs_context->get_id()); + + return ret; +} + int SrsServer::initialize_signal() { return signal_manager->initialize(); @@ -669,34 +706,6 @@ int SrsServer::acquire_pid_file() return ret; } -int SrsServer::initialize_st() -{ - int ret = ERROR_SUCCESS; - - // init st - if ((ret = srs_init_st()) != ERROR_SUCCESS) { - srs_error("init st failed. ret=%d", ret); - return ret; - } - - // @remark, st alloc segment use mmap, which only support 32757 threads, - // if need to support more, for instance, 100k threads, define the macro MALLOC_STACK. - // TODO: FIXME: maybe can use "sysctl vm.max_map_count" to refine. - if (_srs_config->get_max_connections() > 32756) { - ret = ERROR_ST_EXCEED_THREADS; - srs_error("st mmap for stack allocation must <= %d threads, " - "@see Makefile of st for MALLOC_STACK, please build st manually by " - "\"make EXTRA_CFLAGS=-DMALLOC_STACK linux-debug\", ret=%d", ret); - return ret; - } - - // set current log id. - _srs_context->generate_id(); - srs_trace("server main cid=%d", _srs_context->get_id()); - - return ret; -} - int SrsServer::listen() { int ret = ERROR_SUCCESS; @@ -959,6 +968,7 @@ int SrsServer::do_cycle() } #endif #endif + srs_info("server main thread loop"); } } @@ -1103,7 +1113,7 @@ void SrsServer::close_listeners(SrsListenerType type) for (it = listeners.begin(); it != listeners.end();) { SrsListener* listener = *it; - if (listener->type() != type) { + if (listener->listen_type() != type) { ++it; continue; } @@ -1264,7 +1274,7 @@ int SrsServer::on_reload_http_stream_enabled() #ifdef SRS_AUTO_HTTP_SERVER ret = listen_http_stream(); #endif - + return ret; } diff --git a/trunk/src/app/srs_app_server.hpp b/trunk/src/app/srs_app_server.hpp index 1ff7cee90..76b681484 100644 --- a/trunk/src/app/srs_app_server.hpp +++ b/trunk/src/app/srs_app_server.hpp @@ -80,17 +80,17 @@ enum SrsListenerType class SrsListener { protected: - SrsListenerType _type; + SrsListenerType type; protected: - std::string _ip; - int _port; - SrsServer* _server; + std::string ip; + int port; + SrsServer* server; public: - SrsListener(SrsServer* server, SrsListenerType type); + SrsListener(SrsServer* svr, SrsListenerType t); virtual ~SrsListener(); public: - virtual SrsListenerType type(); - virtual int listen(std::string ip, int port) = 0; + virtual SrsListenerType listen_type(); + virtual int listen(std::string i, int p) = 0; }; /** @@ -120,10 +120,10 @@ private: SrsTcpListener* listener; ISrsTcpHandler* caster; public: - SrsRtspListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c); + SrsRtspListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c); virtual ~SrsRtspListener(); public: - virtual int listen(std::string ip, int port); + virtual int listen(std::string i, int p); // ISrsTcpHandler public: virtual int on_tcp_client(st_netfd_t stfd); @@ -138,28 +138,40 @@ private: SrsTcpListener* listener; SrsAppCasterFlv* caster; public: - SrsHttpFlvListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c); + SrsHttpFlvListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c); virtual ~SrsHttpFlvListener(); public: - virtual int listen(std::string ip, int port); + virtual int listen(std::string i, int p); // ISrsTcpHandler public: virtual int on_tcp_client(st_netfd_t stfd); }; +#endif /** -* the udp listener, for udp server. -*/ -class SrsUdpCasterListener : public SrsListener + * the udp listener, for udp server. + */ +class SrsUdpStreamListener : public SrsListener { -private: +protected: SrsUdpListener* listener; ISrsUdpHandler* caster; public: - SrsUdpCasterListener(SrsServer* server, SrsListenerType type, SrsConfDirective* c); - virtual ~SrsUdpCasterListener(); + SrsUdpStreamListener(SrsServer* svr, SrsListenerType t, ISrsUdpHandler* c); + virtual ~SrsUdpStreamListener(); public: - virtual int listen(std::string ip, int port); + virtual int listen(std::string i, int p); +}; + +/** + * the udp listener, for udp stream caster server. + */ +#ifdef SRS_AUTO_STREAM_CASTER +class SrsUdpCasterListener : public SrsUdpStreamListener +{ +public: + SrsUdpCasterListener(SrsServer* svr, SrsListenerType t, SrsConfDirective* c); + virtual ~SrsUdpCasterListener(); }; #endif @@ -337,7 +349,7 @@ public: * @param client_stfd, the client fd in st boxed, the underlayer fd. */ virtual int accept_client(SrsListenerType type, st_netfd_t client_stfd); -// interface ISrsThreadHandler. +// interface ISrsReloadHandler. public: virtual int on_reload_listen(); virtual int on_reload_pid(); diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 5d39ca714..6fae8ea45 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 162 +#define VERSION_REVISION 163 // server info. #define RTMP_SIG_SRS_KEY "SRS" diff --git a/trunk/src/main/srs_main_ingest_hls.cpp b/trunk/src/main/srs_main_ingest_hls.cpp index e01515470..4de2740ca 100644 --- a/trunk/src/main/srs_main_ingest_hls.cpp +++ b/trunk/src/main/srs_main_ingest_hls.cpp @@ -723,8 +723,8 @@ int SrsIngestSrsOutput::on_ts_message(SrsTsMessage* msg) // 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). // about the bytes of PES_packet_data_byte, defined in hls-mpeg-ts-iso13818-1.pdf, page 58 - // PES_packet_data_byte "C PES_packet_data_bytes shall be contiguous bytes of data from the elementary stream - // indicated by the packets stream_id or PID. When the elementary stream data conforms to ITU-T + // PES_packet_data_byte ¨C PES_packet_data_bytes shall be contiguous bytes of data from the elementary stream + // indicated by the packet¡¯s stream_id or PID. When the elementary stream data conforms to ITU-T // 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 // Recommendation | International Standard. The byte-order of the elementary stream shall be preserved. The number of // 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) // PES_packet_data_byte field are user definable and will not be specified by ITU-T | ISO/IEC in the future. // about the bytes of stream_id, define in hls-mpeg-ts-iso13818-1.pdf, page 49 - // stream_id "C In Program Streams, the stream_id specifies the type and number of the elementary stream as defined by the + // stream_id ¨C In Program Streams, the stream_id specifies the type and number of the elementary stream as defined by the // stream_id Table 2-18. In Transport Streams, the stream_id may be set to any valid value which correctly describes the // elementary stream type as defined in Table 2-18. In Transport Streams, the elementary stream type is specified in the // Program Specific Information as specified in 2.4.4. - // about the stream_id table, define in Table 2-18 "C Stream_id assignments, hls-mpeg-ts-iso13818-1.pdf, page 52. + // about the stream_id table, define in Table 2-18 ¨C Stream_id assignments, hls-mpeg-ts-iso13818-1.pdf, page 52. // // 110x xxxx // ISO/IEC 13818-3 or ISO/IEC 11172-3 or ISO/IEC 13818-7 or ISO/IEC diff --git a/trunk/src/main/srs_main_server.cpp b/trunk/src/main/srs_main_server.cpp index f948adb71..41d8f084f 100644 --- a/trunk/src/main/srs_main_server.cpp +++ b/trunk/src/main/srs_main_server.cpp @@ -344,6 +344,10 @@ int run_master() { int ret = ERROR_SUCCESS; + if ((ret = _srs_server->initialize_st()) != ERROR_SUCCESS) { + return ret; + } + if ((ret = _srs_server->initialize_signal()) != ERROR_SUCCESS) { return ret; } @@ -352,10 +356,6 @@ int run_master() return ret; } - if ((ret = _srs_server->initialize_st()) != ERROR_SUCCESS) { - return ret; - } - if ((ret = _srs_server->listen()) != ERROR_SUCCESS) { return ret; } diff --git a/trunk/src/protocol/srs_rtmp_sdk.cpp b/trunk/src/protocol/srs_rtmp_sdk.cpp index 2b0ba4200..3ee7ee9bd 100644 --- a/trunk/src/protocol/srs_rtmp_sdk.cpp +++ b/trunk/src/protocol/srs_rtmp_sdk.cpp @@ -38,36 +38,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. using namespace std; -/** -* the signature for packets to client. -*/ -#define RTMP_SIG_FMS_VER "3,5,3,888" -#define RTMP_SIG_AMF0_VER 0 -#define RTMP_SIG_CLIENT_ID "ASAICiss" - -/** -* onStatus consts. -*/ -#define StatusLevel "level" -#define StatusCode "code" -#define StatusDescription "description" -#define StatusDetails "details" -#define StatusClientId "clientid" -// status value -#define StatusLevelStatus "status" -// status error -#define StatusLevelError "error" -// code value -#define StatusCodeConnectSuccess "NetConnection.Connect.Success" -#define StatusCodeConnectRejected "NetConnection.Connect.Rejected" -#define StatusCodeStreamReset "NetStream.Play.Reset" -#define StatusCodeStreamStart "NetStream.Play.Start" -#define StatusCodeStreamPause "NetStream.Pause.Notify" -#define StatusCodeStreamUnpause "NetStream.Unpause.Notify" -#define StatusCodePublishStart "NetStream.Publish.Start" -#define StatusCodeDataStart "NetStream.Data.Start" -#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success" - // FMLE #define RTMP_AMF0_COMMAND_ON_FC_PUBLISH "onFCPublish" #define RTMP_AMF0_COMMAND_ON_FC_UNPUBLISH "onFCUnpublish" diff --git a/trunk/src/protocol/srs_rtmp_sdk.hpp b/trunk/src/protocol/srs_rtmp_sdk.hpp index 0ef5ac731..1baf457b9 100644 --- a/trunk/src/protocol/srs_rtmp_sdk.hpp +++ b/trunk/src/protocol/srs_rtmp_sdk.hpp @@ -48,6 +48,36 @@ class SrsPacket; class SrsAmf0Object; class IMergeReadHandler; +/** + * the signature for packets to client. + */ +#define RTMP_SIG_FMS_VER "3,5,3,888" +#define RTMP_SIG_AMF0_VER 0 +#define RTMP_SIG_CLIENT_ID "ASAICiss" + +/** + * onStatus consts. + */ +#define StatusLevel "level" +#define StatusCode "code" +#define StatusDescription "description" +#define StatusDetails "details" +#define StatusClientId "clientid" +// status value +#define StatusLevelStatus "status" +// status error +#define StatusLevelError "error" +// code value +#define StatusCodeConnectSuccess "NetConnection.Connect.Success" +#define StatusCodeConnectRejected "NetConnection.Connect.Rejected" +#define StatusCodeStreamReset "NetStream.Play.Reset" +#define StatusCodeStreamStart "NetStream.Play.Start" +#define StatusCodeStreamPause "NetStream.Pause.Notify" +#define StatusCodeStreamUnpause "NetStream.Unpause.Notify" +#define StatusCodePublishStart "NetStream.Publish.Start" +#define StatusCodeDataStart "NetStream.Data.Start" +#define StatusCodeUnpublishSuccess "NetStream.Unpublish.Success" + /** * the original request from client. */ diff --git a/trunk/src/protocol/srs_rtmp_stack.cpp b/trunk/src/protocol/srs_rtmp_stack.cpp index 2c9d6098b..359ddc950 100644 --- a/trunk/src/protocol/srs_rtmp_stack.cpp +++ b/trunk/src/protocol/srs_rtmp_stack.cpp @@ -43,89 +43,6 @@ using namespace std; // increase recv timeout to got an entire message. #define SRS_MIN_RECV_TIMEOUT_US (int64_t)(60*1000*1000LL) -/**************************************************************************** -***************************************************************************** -****************************************************************************/ -/** -5. Protocol Control Messages -RTMP reserves message type IDs 1-7 for protocol control messages. -These messages contain information needed by the RTM Chunk Stream -protocol or RTMP itself. Protocol messages with IDs 1 & 2 are -reserved for usage with RTM Chunk Stream protocol. Protocol messages -with IDs 3-6 are reserved for usage of RTMP. Protocol message with ID -7 is used between edge server and origin server. -*/ -#define RTMP_MSG_SetChunkSize 0x01 -#define RTMP_MSG_AbortMessage 0x02 -#define RTMP_MSG_Acknowledgement 0x03 -#define RTMP_MSG_UserControlMessage 0x04 -#define RTMP_MSG_WindowAcknowledgementSize 0x05 -#define RTMP_MSG_SetPeerBandwidth 0x06 -#define RTMP_MSG_EdgeAndOriginServerCommand 0x07 -/** -3. Types of messages -The server and the client send messages over the network to -communicate with each other. The messages can be of any type which -includes audio messages, video messages, command messages, shared -object messages, data messages, and user control messages. -3.1. Command message -Command messages carry the AMF-encoded commands between the client -and the server. These messages have been assigned message type value -of 20 for AMF0 encoding and message type value of 17 for AMF3 -encoding. These messages are sent to perform some operations like -connect, createStream, publish, play, pause on the peer. Command -messages like onstatus, result etc. are used to inform the sender -about the status of the requested commands. A command message -consists of command name, transaction ID, and command object that -contains related parameters. A client or a server can request Remote -Procedure Calls (RPC) over streams that are communicated using the -command messages to the peer. -*/ -#define RTMP_MSG_AMF3CommandMessage 17 // 0x11 -#define RTMP_MSG_AMF0CommandMessage 20 // 0x14 -/** -3.2. Data message -The client or the server sends this message to send Metadata or any -user data to the peer. Metadata includes details about the -data(audio, video etc.) like creation time, duration, theme and so -on. These messages have been assigned message type value of 18 for -AMF0 and message type value of 15 for AMF3. -*/ -#define RTMP_MSG_AMF0DataMessage 18 // 0x12 -#define RTMP_MSG_AMF3DataMessage 15 // 0x0F -/** -3.3. Shared object message -A shared object is a Flash object (a collection of name value pairs) -that are in synchronization across multiple clients, instances, and -so on. The message types kMsgContainer=19 for AMF0 and -kMsgContainerEx=16 for AMF3 are reserved for shared object events. -Each message can contain multiple events. -*/ -#define RTMP_MSG_AMF3SharedObject 16 // 0x10 -#define RTMP_MSG_AMF0SharedObject 19 // 0x13 -/** -3.4. Audio message -The client or the server sends this message to send audio data to the -peer. The message type value of 8 is reserved for audio messages. -*/ -#define RTMP_MSG_AudioMessage 8 // 0x08 -/* * -3.5. Video message -The client or the server sends this message to send video data to the -peer. The message type value of 9 is reserved for video messages. -These messages are large and can delay the sending of other type of -messages. To avoid such a situation, the video message is assigned -the lowest priority. -*/ -#define RTMP_MSG_VideoMessage 9 // 0x09 -/** -3.6. Aggregate message -An aggregate message is a single message that contains a list of submessages. -The message type value of 22 is reserved for aggregate -messages. -*/ -#define RTMP_MSG_AggregateMessage 22 // 0x16 - /**************************************************************************** ***************************************************************************** ****************************************************************************/ @@ -172,24 +89,6 @@ messages. /**************************************************************************** ***************************************************************************** ****************************************************************************/ -/** -* amf0 command message, command name macros -*/ -#define RTMP_AMF0_COMMAND_CONNECT "connect" -#define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream" -#define RTMP_AMF0_COMMAND_CLOSE_STREAM "closeStream" -#define RTMP_AMF0_COMMAND_PLAY "play" -#define RTMP_AMF0_COMMAND_PAUSE "pause" -#define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone" -#define RTMP_AMF0_COMMAND_ON_STATUS "onStatus" -#define RTMP_AMF0_COMMAND_RESULT "_result" -#define RTMP_AMF0_COMMAND_ERROR "_error" -#define RTMP_AMF0_COMMAND_RELEASE_STREAM "releaseStream" -#define RTMP_AMF0_COMMAND_FC_PUBLISH "FCPublish" -#define RTMP_AMF0_COMMAND_UNPUBLISH "FCUnpublish" -#define RTMP_AMF0_COMMAND_PUBLISH "publish" -#define RTMP_AMF0_DATA_SAMPLE_ACCESS "|RtmpSampleAccess" - /** * band width check method name, which will be invoked by client. * band width check mothods use SrsBandwidthPacket as its internal packet type, diff --git a/trunk/src/protocol/srs_rtmp_stack.hpp b/trunk/src/protocol/srs_rtmp_stack.hpp index 8d673e402..c0eb1dfec 100644 --- a/trunk/src/protocol/srs_rtmp_stack.hpp +++ b/trunk/src/protocol/srs_rtmp_stack.hpp @@ -56,6 +56,110 @@ class SrsChunkStream; class SrsSharedPtrMessage; class IMergeReadHandler; +/**************************************************************************** + ***************************************************************************** + ****************************************************************************/ +/** + 5. Protocol Control Messages + RTMP reserves message type IDs 1-7 for protocol control messages. + These messages contain information needed by the RTM Chunk Stream + protocol or RTMP itself. Protocol messages with IDs 1 & 2 are + reserved for usage with RTM Chunk Stream protocol. Protocol messages + with IDs 3-6 are reserved for usage of RTMP. Protocol message with ID + 7 is used between edge server and origin server. + */ +#define RTMP_MSG_SetChunkSize 0x01 +#define RTMP_MSG_AbortMessage 0x02 +#define RTMP_MSG_Acknowledgement 0x03 +#define RTMP_MSG_UserControlMessage 0x04 +#define RTMP_MSG_WindowAcknowledgementSize 0x05 +#define RTMP_MSG_SetPeerBandwidth 0x06 +#define RTMP_MSG_EdgeAndOriginServerCommand 0x07 +/** + 3. Types of messages + The server and the client send messages over the network to + communicate with each other. The messages can be of any type which + includes audio messages, video messages, command messages, shared + object messages, data messages, and user control messages. + 3.1. Command message + Command messages carry the AMF-encoded commands between the client + and the server. These messages have been assigned message type value + of 20 for AMF0 encoding and message type value of 17 for AMF3 + encoding. These messages are sent to perform some operations like + connect, createStream, publish, play, pause on the peer. Command + messages like onstatus, result etc. are used to inform the sender + about the status of the requested commands. A command message + consists of command name, transaction ID, and command object that + contains related parameters. A client or a server can request Remote + Procedure Calls (RPC) over streams that are communicated using the + command messages to the peer. + */ +#define RTMP_MSG_AMF3CommandMessage 17 // 0x11 +#define RTMP_MSG_AMF0CommandMessage 20 // 0x14 +/** + 3.2. Data message + The client or the server sends this message to send Metadata or any + user data to the peer. Metadata includes details about the + data(audio, video etc.) like creation time, duration, theme and so + on. These messages have been assigned message type value of 18 for + AMF0 and message type value of 15 for AMF3. + */ +#define RTMP_MSG_AMF0DataMessage 18 // 0x12 +#define RTMP_MSG_AMF3DataMessage 15 // 0x0F +/** + 3.3. Shared object message + A shared object is a Flash object (a collection of name value pairs) + that are in synchronization across multiple clients, instances, and + so on. The message types kMsgContainer=19 for AMF0 and + kMsgContainerEx=16 for AMF3 are reserved for shared object events. + Each message can contain multiple events. + */ +#define RTMP_MSG_AMF3SharedObject 16 // 0x10 +#define RTMP_MSG_AMF0SharedObject 19 // 0x13 +/** + 3.4. Audio message + The client or the server sends this message to send audio data to the + peer. The message type value of 8 is reserved for audio messages. + */ +#define RTMP_MSG_AudioMessage 8 // 0x08 +/* * + 3.5. Video message + The client or the server sends this message to send video data to the + peer. The message type value of 9 is reserved for video messages. + These messages are large and can delay the sending of other type of + messages. To avoid such a situation, the video message is assigned + the lowest priority. + */ +#define RTMP_MSG_VideoMessage 9 // 0x09 +/** + 3.6. Aggregate message + An aggregate message is a single message that contains a list of submessages. + The message type value of 22 is reserved for aggregate + messages. + */ +#define RTMP_MSG_AggregateMessage 22 // 0x16 + +/**************************************************************************** + ***************************************************************************** + ****************************************************************************/ +/** + * amf0 command message, command name macros + */ +#define RTMP_AMF0_COMMAND_CONNECT "connect" +#define RTMP_AMF0_COMMAND_CREATE_STREAM "createStream" +#define RTMP_AMF0_COMMAND_CLOSE_STREAM "closeStream" +#define RTMP_AMF0_COMMAND_PLAY "play" +#define RTMP_AMF0_COMMAND_PAUSE "pause" +#define RTMP_AMF0_COMMAND_ON_BW_DONE "onBWDone" +#define RTMP_AMF0_COMMAND_ON_STATUS "onStatus" +#define RTMP_AMF0_COMMAND_RESULT "_result" +#define RTMP_AMF0_COMMAND_ERROR "_error" +#define RTMP_AMF0_COMMAND_RELEASE_STREAM "releaseStream" +#define RTMP_AMF0_COMMAND_FC_PUBLISH "FCPublish" +#define RTMP_AMF0_COMMAND_UNPUBLISH "FCUnpublish" +#define RTMP_AMF0_COMMAND_PUBLISH "publish" +#define RTMP_AMF0_DATA_SAMPLE_ACCESS "|RtmpSampleAccess" + /**************************************************************************** ***************************************************************************** ****************************************************************************/ diff --git a/trunk/src/protocol/srs_rtmp_utility.cpp b/trunk/src/protocol/srs_rtmp_utility.cpp index 2ac6b75dd..bb1ed35ef 100644 --- a/trunk/src/protocol/srs_rtmp_utility.cpp +++ b/trunk/src/protocol/srs_rtmp_utility.cpp @@ -78,22 +78,22 @@ void srs_vhost_resolve(string& vhost, string& app, string& param) app = srs_string_replace(app, "&&", "?"); app = srs_string_replace(app, "=", "?"); - if ((pos = app.find("?")) == std::string::npos) { - return; - } - - std::string query = app.substr(pos + 1); - app = app.substr(0, pos); - - if ((pos = query.find("vhost?")) != std::string::npos) { - query = query.substr(pos + 6); - if (!query.empty()) { - vhost = query; - } - if ((pos = vhost.find("?")) != std::string::npos) { - vhost = vhost.substr(0, pos); + if ((pos = app.find("?")) != std::string::npos) { + std::string query = app.substr(pos + 1); + app = app.substr(0, pos); + + if ((pos = query.find("vhost?")) != std::string::npos) { + query = query.substr(pos + 6); + if (!query.empty()) { + vhost = query; + } + if ((pos = vhost.find("?")) != std::string::npos) { + vhost = vhost.substr(0, pos); + } } } + + /* others */ } void srs_random_generate(char* bytes, int size) diff --git a/trunk/src/protocol/srs_rtmp_utility.hpp b/trunk/src/protocol/srs_rtmp_utility.hpp index 0a63d8160..afa02eaa8 100644 --- a/trunk/src/protocol/srs_rtmp_utility.hpp +++ b/trunk/src/protocol/srs_rtmp_utility.hpp @@ -63,7 +63,9 @@ extern void srs_discovery_tc_url( * app...vhost...request_vhost * @param param, the query, for example, ?vhost=xxx */ -extern void srs_vhost_resolve(std::string& vhost, std::string& app, std::string& param); +extern void srs_vhost_resolve( + std::string& vhost, std::string& app, std::string& param +); /** * generate ramdom data for handshake. From 5d7b0edccc997c27ac5151a89822884fe5f39c2e Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 22 May 2015 11:20:25 +0800 Subject: [PATCH 3/8] merge from bravo code, fix some warnings. --- trunk/src/app/srs_app_kbps.cpp | 12 ++++++------ trunk/src/app/srs_app_listener.cpp | 26 +++++++++++++++++-------- trunk/src/app/srs_app_listener.hpp | 11 +++++++++-- trunk/src/app/srs_app_server.cpp | 6 ++++++ trunk/src/app/srs_app_source.cpp | 15 ++++++++++++++ trunk/src/app/srs_app_source.hpp | 4 ++++ trunk/src/app/srs_app_statistic.cpp | 1 + trunk/src/kernel/srs_kernel_error.hpp | 2 +- trunk/src/protocol/srs_rtmp_sdk.cpp | 10 +--------- trunk/src/protocol/srs_rtmp_utility.cpp | 16 +++++++++++++++ trunk/src/protocol/srs_rtmp_utility.hpp | 3 +++ 11 files changed, 80 insertions(+), 26 deletions(-) diff --git a/trunk/src/app/srs_app_kbps.cpp b/trunk/src/app/srs_app_kbps.cpp index c7fd53e0b..39e3fd149 100644 --- a/trunk/src/app/srs_app_kbps.cpp +++ b/trunk/src/app/srs_app_kbps.cpp @@ -77,22 +77,22 @@ void SrsKbpsSlice::sample() } if (now - sample_30s.time > 30 * 1000) { - sample_30s.kbps = (total_bytes - sample_30s.bytes) * 8 / (now - sample_30s.time); + sample_30s.kbps = (int)((total_bytes - sample_30s.bytes) * 8 / (now - sample_30s.time)); sample_30s.time = now; sample_30s.bytes = total_bytes; } if (now - sample_1m.time > 60 * 1000) { - sample_1m.kbps = (total_bytes - sample_1m.bytes) * 8 / (now - sample_1m.time); + sample_1m.kbps = (int)((total_bytes - sample_1m.bytes) * 8 / (now - sample_1m.time)); sample_1m.time = now; sample_1m.bytes = total_bytes; } if (now - sample_5m.time > 300 * 1000) { - sample_5m.kbps = (total_bytes - sample_5m.bytes) * 8 / (now - sample_5m.time); + sample_5m.kbps = (int)((total_bytes - sample_5m.bytes) * 8 / (now - sample_5m.time)); sample_5m.time = now; sample_5m.bytes = total_bytes; } if (now - sample_60m.time > 3600 * 1000) { - sample_60m.kbps = (total_bytes - sample_60m.bytes) * 8 / (now - sample_60m.time); + sample_60m.kbps = (int)((total_bytes - sample_60m.bytes) * 8 / (now - sample_60m.time)); sample_60m.time = now; sample_60m.bytes = total_bytes; } @@ -160,7 +160,7 @@ int SrsKbps::get_send_kbps() return 0; } int64_t bytes = get_send_bytes(); - return bytes * 8 / duration; + return (int)(bytes * 8 / duration); } int SrsKbps::get_recv_kbps() @@ -170,7 +170,7 @@ int SrsKbps::get_recv_kbps() return 0; } int64_t bytes = get_recv_bytes(); - return bytes * 8 / duration; + return (int)(bytes * 8 / duration); } int SrsKbps::get_send_kbps_30s() diff --git a/trunk/src/app/srs_app_listener.cpp b/trunk/src/app/srs_app_listener.cpp index fb370d708..915c95c23 100644 --- a/trunk/src/app/srs_app_listener.cpp +++ b/trunk/src/app/srs_app_listener.cpp @@ -54,6 +54,11 @@ ISrsUdpHandler::~ISrsUdpHandler() { } +int ISrsUdpHandler::on_stfd_change(st_netfd_t /*fd*/) +{ + return ERROR_SUCCESS; +} + ISrsTcpHandler::ISrsTcpHandler() { } @@ -69,7 +74,7 @@ SrsUdpListener::SrsUdpListener(ISrsUdpHandler* h, string i, int p) port = p; _fd = -1; - stfd = NULL; + _stfd = NULL; nb_buf = SRS_UDP_MAX_PACKET_SIZE; buf = new char[nb_buf]; @@ -80,7 +85,7 @@ SrsUdpListener::SrsUdpListener(ISrsUdpHandler* h, string i, int p) SrsUdpListener::~SrsUdpListener() { // close the stfd to trigger thread to interrupted. - srs_close_stfd(stfd); + srs_close_stfd(_stfd); pthread->stop(); srs_freep(pthread); @@ -97,6 +102,11 @@ int SrsUdpListener::fd() return _fd; } +st_netfd_t SrsUdpListener::stfd() +{ + return _stfd; +} + int SrsUdpListener::listen() { int ret = ERROR_SUCCESS; @@ -127,7 +137,7 @@ int SrsUdpListener::listen() } srs_verbose("bind socket success. ep=%s:%d, fd=%d", ip.c_str(), port, _fd); - if ((stfd = st_netfd_open_socket(_fd)) == NULL){ + if ((_stfd = st_netfd_open_socket(_fd)) == NULL){ ret = ERROR_ST_OPEN_SOCKET; srs_error("st_netfd_open_socket open socket failed. ep=%s:%d, ret=%d", ip.c_str(), port, ret); return ret; @@ -153,7 +163,7 @@ int SrsUdpListener::cycle() int nb_from = sizeof(sockaddr_in); int nread = 0; - if ((nread = st_recvfrom(stfd, buf, nb_buf, (sockaddr*)&from, &nb_from, ST_UTIME_NO_TIMEOUT)) <= 0) { + if ((nread = st_recvfrom(_stfd, buf, nb_buf, (sockaddr*)&from, &nb_from, ST_UTIME_NO_TIMEOUT)) <= 0) { srs_warn("ignore recv udp packet failed, nread=%d", nread); continue; } @@ -178,7 +188,7 @@ SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, string i, int p) port = p; _fd = -1; - stfd = NULL; + _stfd = NULL; pthread = new SrsThread("tcp", this, 0, true); } @@ -186,7 +196,7 @@ SrsTcpListener::SrsTcpListener(ISrsTcpHandler* h, string i, int p) SrsTcpListener::~SrsTcpListener() { // close the stfd to trigger thread to interrupted. - srs_close_stfd(stfd); + srs_close_stfd(_stfd); pthread->stop(); srs_freep(pthread); @@ -238,7 +248,7 @@ int SrsTcpListener::listen() } srs_verbose("listen socket success. ep=%s:%d, fd=%d", ip.c_str(), port, _fd); - if ((stfd = st_netfd_open_socket(_fd)) == NULL){ + if ((_stfd = st_netfd_open_socket(_fd)) == NULL){ ret = ERROR_ST_OPEN_SOCKET; srs_error("st_netfd_open_socket open socket failed. ep=%s:%d, ret=%d", ip.c_str(), port, ret); return ret; @@ -258,7 +268,7 @@ int SrsTcpListener::cycle() { int ret = ERROR_SUCCESS; - st_netfd_t client_stfd = st_accept(stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); + st_netfd_t client_stfd = st_accept(_stfd, NULL, NULL, ST_UTIME_NO_TIMEOUT); if(client_stfd == NULL){ // ignore error. diff --git a/trunk/src/app/srs_app_listener.hpp b/trunk/src/app/srs_app_listener.hpp index 679bf1bda..371b5acba 100644 --- a/trunk/src/app/srs_app_listener.hpp +++ b/trunk/src/app/srs_app_listener.hpp @@ -45,6 +45,12 @@ class ISrsUdpHandler public: ISrsUdpHandler(); virtual ~ISrsUdpHandler(); +public: + /** + * when fd changed, for instance, reload the listen port, + * notify the handler and user can do something. + */ + virtual int on_stfd_change(st_netfd_t fd); public: /** * when udp listener got a udp packet, notice server to process it. @@ -80,7 +86,7 @@ class SrsUdpListener : public ISrsThreadHandler { private: int _fd; - st_netfd_t stfd; + st_netfd_t _stfd; SrsThread* pthread; private: char* buf; @@ -94,6 +100,7 @@ public: virtual ~SrsUdpListener(); public: virtual int fd(); + virtual st_netfd_t stfd(); public: virtual int listen(); // interface ISrsThreadHandler. @@ -108,7 +115,7 @@ class SrsTcpListener : public ISrsThreadHandler { private: int _fd; - st_netfd_t stfd; + st_netfd_t _stfd; SrsThread* pthread; private: ISrsTcpHandler* handler; diff --git a/trunk/src/app/srs_app_server.cpp b/trunk/src/app/srs_app_server.cpp index d91b5101d..7e2c0809a 100644 --- a/trunk/src/app/srs_app_server.cpp +++ b/trunk/src/app/srs_app_server.cpp @@ -330,6 +330,12 @@ int SrsUdpStreamListener::listen(string i, int p) srs_info("listen thread cid=%d, current_cid=%d, " "listen at port=%d, type=%d, fd=%d started success, ep=%s:%d", pthread->cid(), _srs_context->get_id(), port, type, fd, ip.c_str(), port); + + // notify the handler the fd changed. + if ((ret = caster->on_stfd_change(listener->stfd())) != ERROR_SUCCESS) { + srs_error("notify handler fd changed. ret=%d", ret); + return ret; + } srs_trace("%s listen at udp://%s:%d, fd=%d", srs_listener_type2string(type).c_str(), ip.c_str(), port, listener->fd()); diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index d4c4d7823..7e6dfafe3 100644 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -45,6 +45,7 @@ using namespace std; #include #include #include +#include #define CONST_MAX_JITTER_MS 500 #define DEFAULT_FRAME_TIME_MS 40 @@ -759,6 +760,20 @@ SrsSource* SrsSource::fetch(SrsRequest* r) return source; } +SrsSource* SrsSource::fetch(std::string vhost, std::string app, std::string stream) +{ + SrsSource* source = NULL; + string stream_url = srs_generate_stream_url(vhost, app, stream); + + if (pool.find(stream_url) == pool.end()) { + return NULL; + } + + source = pool[stream_url]; + + return source; +} + void SrsSource::destroy() { std::map::iterator it; diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index 4d4799f70..3c83e1163 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -407,6 +407,10 @@ public: */ static SrsSource* fetch(SrsRequest* r); /** + * get the exists source by stream info(vhost, app, stream), NULL when not exists. + */ + static SrsSource* fetch(std::string vhost, std::string app, std::string stream); + /** * when system exit, destroy the sources, * for gmc to analysis mem leaks. */ diff --git a/trunk/src/app/srs_app_statistic.cpp b/trunk/src/app/srs_app_statistic.cpp index 59076db0f..275815917 100644 --- a/trunk/src/app/srs_app_statistic.cpp +++ b/trunk/src/app/srs_app_statistic.cpp @@ -195,6 +195,7 @@ int SrsStatistic::on_client(int id, SrsRequest* req) SrsStatisticClient* client = NULL; if (clients.find(id) == clients.end()) { client = new SrsStatisticClient(); + client->id = id; client->stream = stream; clients[id] = client; } else { diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index bfcdad6b6..11f3e35b6 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -255,7 +255,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_HTTP_INVALID_CHUNK_HEADER 4026 #define ERROR_AVC_NALU_UEV 4027 #define ERROR_AAC_BYTES_INVALID 4028 -#define ERROR_HTTP_REQUEST_EOF 4029 +#define ERROR_HTTP_REQUEST_EOF 4029 /////////////////////////////////////////////////////// // user-define error. diff --git a/trunk/src/protocol/srs_rtmp_sdk.cpp b/trunk/src/protocol/srs_rtmp_sdk.cpp index 3ee7ee9bd..ba5757340 100644 --- a/trunk/src/protocol/srs_rtmp_sdk.cpp +++ b/trunk/src/protocol/srs_rtmp_sdk.cpp @@ -99,15 +99,7 @@ void SrsRequest::update_auth(SrsRequest* req) string SrsRequest::get_stream_url() { - std::string url = ""; - - url += vhost; - url += "/"; - url += app; - url += "/"; - url += stream; - - return url; + return srs_generate_stream_url(vhost, app, stream); } void SrsRequest::strip() diff --git a/trunk/src/protocol/srs_rtmp_utility.cpp b/trunk/src/protocol/srs_rtmp_utility.cpp index bb1ed35ef..7c892ad36 100644 --- a/trunk/src/protocol/srs_rtmp_utility.cpp +++ b/trunk/src/protocol/srs_rtmp_utility.cpp @@ -31,6 +31,7 @@ using namespace std; #include #include #include +#include void srs_discovery_tc_url( string tcUrl, @@ -346,3 +347,18 @@ int srs_rtmp_create_msg(char type, u_int32_t timestamp, char* data, int size, in return ret; } +std::string srs_generate_stream_url(std::string vhost, std::string app, std::string stream) +{ + std::string url = ""; + + if (SRS_CONSTS_RTMP_DEFAULT_VHOST != vhost){ + url += vhost; + } + url += "/"; + url += app; + url += "/"; + url += stream; + + return url; +} + diff --git a/trunk/src/protocol/srs_rtmp_utility.hpp b/trunk/src/protocol/srs_rtmp_utility.hpp index afa02eaa8..09e834d09 100644 --- a/trunk/src/protocol/srs_rtmp_utility.hpp +++ b/trunk/src/protocol/srs_rtmp_utility.hpp @@ -120,5 +120,8 @@ extern int srs_chunk_header_c3( */ extern int srs_rtmp_create_msg(char type, u_int32_t timestamp, char* data, int size, int stream_id, SrsSharedPtrMessage** ppmsg); +// get the stream identify, vhost/app/stream. +extern std::string srs_generate_stream_url(std::string vhost, std::string app, std::string stream); + #endif From 948d200ce156c6ad89710fb73c61686926a29d61 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 22 May 2015 12:00:48 +0800 Subject: [PATCH 4/8] fix #400, parse when got entire http header, by feilong. 2.0.164. --- README.md | 1 + trunk/src/app/srs_app_http.cpp | 15 +++++++++++---- trunk/src/core/srs_core.hpp | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2f136b943..06fdde0a7 100755 --- a/README.md +++ b/README.md @@ -562,6 +562,7 @@ Supported operating systems and hardware: ### SRS 2.0 history +* 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. * v2.0, 2015-05-19, merge from bravo system, add the rtmfp to bms(commercial srs). 2.0.163. * v2.0, 2015-05-10, support push flv stream over HTTP POST to SRS. * v2.0, 2015-04-20, support ingest hls live stream to RTMP. diff --git a/trunk/src/app/srs_app_http.cpp b/trunk/src/app/srs_app_http.cpp index 4ed1453f2..d2d503008 100644 --- a/trunk/src/app/srs_app_http.cpp +++ b/trunk/src/app/srs_app_http.cpp @@ -1447,10 +1447,17 @@ int SrsHttpParser::parse_message_imp(SrsStSocket* skt) while (true) { ssize_t nparsed = 0; - // when buffer not empty, parse it. - if (buffer->size() > 0) { - nparsed = http_parser_execute(&parser, &settings, buffer->bytes(), buffer->size()); - srs_info("buffer=%d, nparsed=%d, header=%d", buffer->size(), (int)nparsed, header_parsed); + // when got entire http header, parse it. + // @see https://github.com/simple-rtmp-server/srs/issues/400 + char* start = buffer->bytes(); + char* end = start + buffer->size(); + for (char* p = start; p <= end - 4; p++) { + // SRS_HTTP_CRLFCRLF "\r\n\r\n" // 0x0D0A0D0A + if (p[0] == SRS_CONSTS_CR && p[1] == SRS_CONSTS_LF && p[2] == SRS_CONSTS_CR && p[3] == SRS_CONSTS_LF) { + nparsed = http_parser_execute(&parser, &settings, buffer->bytes(), buffer->size()); + srs_info("buffer=%d, nparsed=%d, header=%d", buffer->size(), (int)nparsed, header_parsed); + break; + } } // consume the parsed bytes. diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 6fae8ea45..775ca8f10 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 163 +#define VERSION_REVISION 164 // server info. #define RTMP_SIG_SRS_KEY "SRS" From 6f8c076b309f1b7d1d89681e4d91b9ba121cd300 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 22 May 2015 12:10:06 +0800 Subject: [PATCH 5/8] add comments for srs thread, add never quit thread. --- trunk/src/app/srs_app_thread.hpp | 186 ++++++++++++++++--------------- 1 file changed, 99 insertions(+), 87 deletions(-) diff --git a/trunk/src/app/srs_app_thread.hpp b/trunk/src/app/srs_app_thread.hpp index 5d73f2f95..db89b8df0 100644 --- a/trunk/src/app/srs_app_thread.hpp +++ b/trunk/src/app/srs_app_thread.hpp @@ -32,93 +32,105 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include /** -* the handler for the thread, callback interface. -* the thread model defines as: -* handler->on_thread_start() -* while loop: -* handler->on_before_cycle() -* handler->cycle() -* handler->on_end_cycle() -* if !loop then break for user stop thread. -* sleep(CycleIntervalMilliseconds) -* handler->on_thread_stop() -* when stop, the thread will interrupt the st_thread, -* which will cause the socket to return error and -* terminate the cycle thread. -* -* Usage 1: stop by other thread. -* user can create thread and stop then start again and again, -* generally must provides a start and stop method, @see SrsIngester. -* the step to create a thread stop by other thread: -* 1. create SrsThread field, with joinable true. -* 2. must use stop to stop and join the thread. -* for example: -* class SrsIngester : public ISrsThreadHandler { -* public: SrsIngester() { pthread = new SrsThread("ingest", this, SRS_AUTO_INGESTER_SLEEP_US, true); } -* public: virtual int start() { return pthread->start(); } -* public: virtual void stop() { pthread->stop(); } -* public: virtual int cycle() { -* // check status, start ffmpeg when stopped. -* } -* }; -* -* Usage 2: stop by thread itself. -* user can create thread which stop itself, -* generally only need to provides a start method, -* the object will destroy itself then terminate the thread, @see SrsConnection -* 1. create SrsThread field, with joinable false. -* 2. owner stop thread loop, destroy itself when thread stop. -* for example: -* class SrsConnection : public ISrsThreadHandler { -* public: SrsConnection() { pthread = new SrsThread("conn", this, 0, false); } -* public: virtual int start() { return pthread->start(); } -* public: virtual int cycle() { -* // serve client. -* // set loop to stop to quit, stop thread itself. -* pthread->stop_loop(); -* } -* public: virtual int on_thread_stop() { -* // remove the connection in thread itself. -* server->remove(this); -* } -* }; -* -* Usage 3: loop in the cycle method. -* user can use loop code in the cycle method, @see SrsForwarder -* 1. create SrsThread field, with or without joinable is ok. -* 2. loop code in cycle method, check the can_loop() for thread to quit. -* for example: -* class SrsForwarder : public ISrsThreadHandler { -* public: virtual int cycle() { -* while (pthread->can_loop()) { -* // read msgs from queue and forward to server. -* } -* } -* }; -* -* @remark why should check can_loop() in cycle method? -* when thread interrupt, the socket maybe not got EINT, -* espectially on st_usleep(), so the cycle must check the loop, -* when handler->cycle() has loop itself, for example: -* while (true): -* if (read_from_socket(skt) < 0) break; -* if thread stop when read_from_socket, it's ok, the loop will break, -* but when thread stop interrupt the s_usleep(0), then the loop is -* death loop. -* in a word, the handler->cycle() must: -* while (pthread->can_loop()): -* if (read_from_socket(skt) < 0) break; -* check the loop, then it works. -* -* @remark why should use stop_loop() to terminate thread in itself? -* in the thread itself, that is the cycle method, -* if itself want to terminate the thread, should never use stop(), -* but use stop_loop() to set the loop to false and terminate normally. -* -* @remark when should set the interval_us, and when not? -* the cycle will invoke util cannot loop, eventhough the return code of cycle is error, -* so the interval_us used to sleep for each cycle. -*/ + * the handler for the thread, callback interface. + * the thread model defines as: + * handler->on_thread_start() + * while loop: + * handler->on_before_cycle() + * handler->cycle() + * handler->on_end_cycle() + * if !loop then break for user stop thread. + * sleep(CycleIntervalMilliseconds) + * handler->on_thread_stop() + * when stop, the thread will interrupt the st_thread, + * which will cause the socket to return error and + * terminate the cycle thread. + * + * Usage 1: loop thread never quit. + * user can create thread always running util server terminate. + * the step to create a thread never stop: + * 1. create SrsThread field, with joinable false. + * for example: + * class SrsStreamCache : public ISrsThreadHandler { + * public: SrsStreamCache() { pthread = new SrsThread("http-stream", this, SRS_AUTO_STREAM_SLEEP_US, false); } + * public: virtual int cycle() { + * // check status, start ffmpeg when stopped. + * } + * } + * + * Usage 2: stop by other thread. + * user can create thread and stop then start again and again, + * generally must provides a start and stop method, @see SrsIngester. + * the step to create a thread stop by other thread: + * 1. create SrsThread field, with joinable true. + * 2. must use stop to stop and join the thread. + * for example: + * class SrsIngester : public ISrsThreadHandler { + * public: SrsIngester() { pthread = new SrsThread("ingest", this, SRS_AUTO_INGESTER_SLEEP_US, true); } + * public: virtual int start() { return pthread->start(); } + * public: virtual void stop() { pthread->stop(); } + * public: virtual int cycle() { + * // check status, start ffmpeg when stopped. + * } + * }; + * + * Usage 3: stop by thread itself. + * user can create thread which stop itself, + * generally only need to provides a start method, + * the object will destroy itself then terminate the thread, @see SrsConnection + * 1. create SrsThread field, with joinable false. + * 2. owner stop thread loop, destroy itself when thread stop. + * for example: + * class SrsConnection : public ISrsThreadHandler { + * public: SrsConnection() { pthread = new SrsThread("conn", this, 0, false); } + * public: virtual int start() { return pthread->start(); } + * public: virtual int cycle() { + * // serve client. + * // set loop to stop to quit, stop thread itself. + * pthread->stop_loop(); + * } + * public: virtual int on_thread_stop() { + * // remove the connection in thread itself. + * server->remove(this); + * } + * }; + * + * Usage 4: loop in the cycle method. + * user can use loop code in the cycle method, @see SrsForwarder + * 1. create SrsThread field, with or without joinable is ok. + * 2. loop code in cycle method, check the can_loop() for thread to quit. + * for example: + * class SrsForwarder : public ISrsThreadHandler { + * public: virtual int cycle() { + * while (pthread->can_loop()) { + * // read msgs from queue and forward to server. + * } + * } + * }; + * + * @remark why should check can_loop() in cycle method? + * when thread interrupt, the socket maybe not got EINT, + * espectially on st_usleep(), so the cycle must check the loop, + * when handler->cycle() has loop itself, for example: + * while (true): + * if (read_from_socket(skt) < 0) break; + * if thread stop when read_from_socket, it's ok, the loop will break, + * but when thread stop interrupt the s_usleep(0), then the loop is + * death loop. + * in a word, the handler->cycle() must: + * while (pthread->can_loop()): + * if (read_from_socket(skt) < 0) break; + * check the loop, then it works. + * + * @remark why should use stop_loop() to terminate thread in itself? + * in the thread itself, that is the cycle method, + * if itself want to terminate the thread, should never use stop(), + * but use stop_loop() to set the loop to false and terminate normally. + * + * @remark when should set the interval_us, and when not? + * the cycle will invoke util cannot loop, eventhough the return code of cycle is error, + * so the interval_us used to sleep for each cycle. + */ class ISrsThreadHandler { public: From 46a81372e7bc133f58607fbf077d431fad17a131 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 22 May 2015 13:57:04 +0800 Subject: [PATCH 6/8] fix #398, set recv timeout for http connection. --- trunk/src/app/srs_app_http_api.cpp | 4 ++++ trunk/src/app/srs_app_http_conn.cpp | 4 ++++ trunk/src/kernel/srs_kernel_consts.hpp | 3 +++ trunk/src/kernel/srs_kernel_error.cpp | 3 ++- 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index d4e3ea5fc..5b2f169d6 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -523,6 +523,10 @@ int SrsHttpApi::do_cycle() // underlayer socket SrsStSocket skt(stfd); + // set the recv timeout, for some clients never disconnect the connection. + // @see https://github.com/simple-rtmp-server/srs/issues/398 + skt.set_recv_timeout(SRS_HTTP_RECV_TIMEOUT_US); + // process http messages. for (;;) { SrsHttpMessage* req = NULL; diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index bdf8e2dc0..4350cd15d 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -1383,6 +1383,10 @@ int SrsHttpConn::do_cycle() // underlayer socket SrsStSocket skt(stfd); + // set the recv timeout, for some clients never disconnect the connection. + // @see https://github.com/simple-rtmp-server/srs/issues/398 + skt.set_recv_timeout(SRS_HTTP_RECV_TIMEOUT_US); + // process http messages. for (;;) { SrsHttpMessage* req = NULL; diff --git a/trunk/src/kernel/srs_kernel_consts.hpp b/trunk/src/kernel/srs_kernel_consts.hpp index c4a09831d..ee1142dc6 100644 --- a/trunk/src/kernel/srs_kernel_consts.hpp +++ b/trunk/src/kernel/srs_kernel_consts.hpp @@ -201,6 +201,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // query string seprator #define SRS_CONSTS_HTTP_QUERY_SEP '?' +// the default recv timeout. +#define SRS_HTTP_RECV_TIMEOUT_US 60 * 1000 * 1000 + // 6.1.1 Status Code and Reason Phrase #define SRS_CONSTS_HTTP_Continue 100 #define SRS_CONSTS_HTTP_SwitchingProtocols 101 diff --git a/trunk/src/kernel/srs_kernel_error.cpp b/trunk/src/kernel/srs_kernel_error.cpp index 0118ef935..dce0c54f0 100644 --- a/trunk/src/kernel/srs_kernel_error.cpp +++ b/trunk/src/kernel/srs_kernel_error.cpp @@ -33,6 +33,7 @@ bool srs_is_client_gracefully_close(int error_code) { return error_code == ERROR_SOCKET_READ || error_code == ERROR_SOCKET_READ_FULLY - || error_code == ERROR_SOCKET_WRITE; + || error_code == ERROR_SOCKET_WRITE + || error_code == ERROR_SOCKET_TIMEOUT; } From c17a1198cb9992198422e63c1c1eadc3b5e235d8 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 22 May 2015 16:27:48 +0800 Subject: [PATCH 7/8] fix #399, disconnect when not keep alive. --- trunk/src/app/srs_app_http.cpp | 9 +++++++++ trunk/src/app/srs_app_http.hpp | 9 +++++++++ trunk/src/app/srs_app_http_api.cpp | 6 ++++++ trunk/src/app/srs_app_http_conn.cpp | 6 ++++++ 4 files changed, 30 insertions(+) diff --git a/trunk/src/app/srs_app_http.cpp b/trunk/src/app/srs_app_http.cpp index d2d503008..ff7bf19b9 100644 --- a/trunk/src/app/srs_app_http.cpp +++ b/trunk/src/app/srs_app_http.cpp @@ -1082,6 +1082,7 @@ SrsHttpMessage::SrsHttpMessage(SrsStSocket* io, SrsConnection* c) { conn = c; chunked = false; + keep_alive = true; _uri = new SrsHttpUri(); _body = new SrsHttpResponseReader(this, io); _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, std::string transfer_encoding = get_request_header("Transfer-Encoding"); chunked = (transfer_encoding == "chunked"); + // whether keep alive. + keep_alive = http_should_keep_alive(header); + // set the buffer. if ((ret = _body->initialize(body)) != ERROR_SUCCESS) { return ret; @@ -1232,6 +1236,11 @@ bool SrsHttpMessage::is_chunked() return chunked; } +bool SrsHttpMessage::is_keep_alive() +{ + return keep_alive; +} + string SrsHttpMessage::uri() { std::string uri = _uri->get_schema(); diff --git a/trunk/src/app/srs_app_http.hpp b/trunk/src/app/srs_app_http.hpp index 190999b50..07b9fee08 100644 --- a/trunk/src/app/srs_app_http.hpp +++ b/trunk/src/app/srs_app_http.hpp @@ -494,6 +494,11 @@ private: * whether the body is chunked. */ bool chunked; + /** + * whether the request indicates should keep alive + * for the http connection. + */ + bool keep_alive; /** * uri parser */ @@ -538,6 +543,10 @@ public: * whether body is chunked encoding, for reader only. */ virtual bool is_chunked(); + /** + * whether should keep the connection alive. + */ + virtual bool is_keep_alive(); /** * the uri contains the host and path. */ diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index 5b2f169d6..43652643d 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -555,6 +555,12 @@ int SrsHttpApi::do_cycle() if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) { return ret; } + + // donot keep alive, disconnect it. + // @see https://github.com/simple-rtmp-server/srs/issues/399 + if (!req->is_keep_alive()) { + break; + } } return ret; diff --git a/trunk/src/app/srs_app_http_conn.cpp b/trunk/src/app/srs_app_http_conn.cpp index 4350cd15d..5c99f79ef 100644 --- a/trunk/src/app/srs_app_http_conn.cpp +++ b/trunk/src/app/srs_app_http_conn.cpp @@ -1412,6 +1412,12 @@ int SrsHttpConn::do_cycle() if ((ret = process_request(&writer, req)) != ERROR_SUCCESS) { return ret; } + + // donot keep alive, disconnect it. + // @see https://github.com/simple-rtmp-server/srs/issues/399 + if (!req->is_keep_alive()) { + break; + } } return ret; From 6ca46e84bc01f94424c96736d530bad8d68d9a14 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 22 May 2015 17:08:26 +0800 Subject: [PATCH 8/8] fix #397, the USER_HZ maybe not 100. 2.0.165 --- README.md | 5 +++++ trunk/src/app/srs_app_utility.cpp | 16 +++++++--------- trunk/src/core/srs_core.hpp | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 06fdde0a7..e344241d7 100755 --- a/README.md +++ b/README.md @@ -562,6 +562,7 @@ Supported operating systems and hardware: ### SRS 2.0 history +* 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 * 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. * v2.0, 2015-05-19, merge from bravo system, add the rtmfp to bms(commercial srs). 2.0.163. * v2.0, 2015-05-10, support push flv stream over HTTP POST to SRS. @@ -672,6 +673,10 @@ Supported operating systems and hardware: ### SRS 1.0 history +* 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 +* v1.0, 2015-03-26, fix hls aac adts bug, in aac mux. 1.0.31. +* 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. +* v1.0, 2015-03-17, remove the osx for 1.0.30. * v1.0, 2015-02-17, the join maybe failed, should use a variable to ensure thread terminated. 1.0.28. * 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. * v1.0, 2015-02-11, dev code HuKaiqun for 1.0.27. diff --git a/trunk/src/app/srs_app_utility.cpp b/trunk/src/app/srs_app_utility.cpp index fc1d81237..9c7ef3d47 100644 --- a/trunk/src/app/srs_app_utility.cpp +++ b/trunk/src/app/srs_app_utility.cpp @@ -418,15 +418,13 @@ bool get_proc_self_stat(SrsProcSelfStat& r) void srs_update_proc_stat() { - // always assert the USER_HZ is 1/100ths // @see: http://stackoverflow.com/questions/7298646/calculating-user-nice-sys-idle-iowait-irq-and-sirq-from-proc-stat/7298711 - static bool user_hz_assert = false; - if (!user_hz_assert) { - user_hz_assert = true; - - int USER_HZ = sysconf(_SC_CLK_TCK); - srs_trace("USER_HZ=%d", USER_HZ); - srs_assert(USER_HZ == 100); + // @see https://github.com/simple-rtmp-server/srs/issues/397 + static int user_hz = 0; + if (user_hz <= 0) { + user_hz = sysconf(_SC_CLK_TCK); + srs_trace("USER_HZ=%d", user_hz); + srs_assert(user_hz > 0); } // system cpu stat @@ -471,7 +469,7 @@ void srs_update_proc_stat() int64_t total = r.sample_time - o.sample_time; int64_t usage = (r.utime + r.stime) - (o.utime + o.stime); if (total > 0) { - r.percent = (float)(usage * 1000 / (double)total / 100); + r.percent = (float)(usage * 1000 / (double)total / user_hz); } // upate cache. diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 775ca8f10..433f07139 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 164 +#define VERSION_REVISION 165 // server info. #define RTMP_SIG_SRS_KEY "SRS"