From 3669419e4c238321044693d0a214328cb9040ccd Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 10 Nov 2013 11:52:19 +0800 Subject: [PATCH] support config and reload the pithy print. --- README.md | 1 + trunk/3rdparty/http-parser-2.1.zip | Bin 0 -> 46278 bytes trunk/auto/modules.sh | 8 +- trunk/conf/srs.conf | 15 +++- trunk/configure | 49 ++++++++---- ...re_auto_free.cpp => srs_core_autofree.cpp} | 2 +- ...re_auto_free.hpp => srs_core_autofree.hpp} | 2 +- trunk/src/core/srs_core_client.cpp | 2 +- trunk/src/core/srs_core_config.cpp | 34 ++++++++- trunk/src/core/srs_core_config.hpp | 2 + ...x_handshake.cpp => srs_core_handshake.cpp} | 70 +++++++++++++++++- ...x_handshake.hpp => srs_core_handshake.hpp} | 19 ++++- trunk/src/core/srs_core_pithy_print.cpp | 49 +++++++++--- trunk/src/core/srs_core_protocol.cpp | 2 +- trunk/src/core/srs_core_reload.cpp | 8 +- trunk/src/core/srs_core_reload.hpp | 1 + trunk/src/core/srs_core_rtmp.cpp | 56 ++------------ trunk/src/core/srs_core_rtmp.hpp | 2 - trunk/src/core/srs_core_source.cpp | 2 +- trunk/src/srs/srs.upp | 8 +- 20 files changed, 235 insertions(+), 97 deletions(-) create mode 100644 trunk/3rdparty/http-parser-2.1.zip mode change 100644 => 100755 trunk/auto/modules.sh rename trunk/src/core/{srs_core_auto_free.cpp => srs_core_autofree.cpp} (94%) rename trunk/src/core/{srs_core_auto_free.hpp => srs_core_autofree.hpp} (94%) rename trunk/src/core/{srs_core_complex_handshake.cpp => srs_core_handshake.cpp} (90%) rename trunk/src/core/{srs_core_complex_handshake.hpp => srs_core_handshake.hpp} (81%) diff --git a/README.md b/README.md index 1c5e1577b..fb2398638 100755 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ url: rtmp://127.0.0.1:1935/live/livestream * nginx v1.5.0: 139524 lines
### History +* v0.4, 2013-11-10, support config and reload the pithy print. * v0.4, 2013-11-09, support reload config(vhost and its detail). * v0.4, 2013-11-09, support reload config(listen and chunk_size) by SIGHUP(1). * v0.4, 2013-11-09, support longtime(>4.6hours) publish/play. diff --git a/trunk/3rdparty/http-parser-2.1.zip b/trunk/3rdparty/http-parser-2.1.zip new file mode 100644 index 0000000000000000000000000000000000000000..e8452f83b917ae50bad50440ae3b0d38185be94d GIT binary patch literal 46278 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 DxiKrE literal 0 HcmV?d00001 diff --git a/trunk/auto/modules.sh b/trunk/auto/modules.sh old mode 100644 new mode 100755 index faa097ac9..6a30d706e --- a/trunk/auto/modules.sh +++ b/trunk/auto/modules.sh @@ -15,15 +15,15 @@ FILE=${GLOBAL_DIR_OBJS}/${GLOBAL_FILE_MAKEFILE} # INCS INCS_NAME="${MODULE_ID}_INCS" echo "# the ${MODULE_ID} module." >> ${FILE} -echo "${MODULE_ID}_MODULE_INCS = -I ${MODULE_DIR} " >> ${FILE} -echo -n "${INCS_NAME} = -I ${MODULE_DIR} " >> ${FILE} +echo "${MODULE_ID}_MODULE_INCS = -I${MODULE_DIR} " >> ${FILE} +echo -n "${INCS_NAME} = -I${MODULE_DIR} " >> ${FILE} for item in ${MODULE_DEPENDS[*]}; do DEP_INCS_NAME="${item}_INCS"do DEP_INCS_NAME="${item}_MODULE_INCS" echo -n "\$(${DEP_INCS_NAME}) " >> ${FILE} done for item in ${ModuleLibIncs[*]}; do - echo -n "-I ${item} " >> ${FILE} + echo -n "-I${item} " >> ${FILE} done echo "" >> ${FILE} @@ -50,7 +50,7 @@ for item in ${MODULE_FILES[*]}; do MODULE_OBJS="${MODULE_OBJS[@]} ${CPP_FILE}" if [ -f ${CPP_FILE} ]; then echo "${OBJ_FILE}: \$(${DEPS_NAME}) ${CPP_FILE} " >> ${FILE} - echo " \$(GCC) -c \$(CXXFLAGS) \$(${INCS_NAME}) -o ${OBJ_FILE} ${CPP_FILE}" >> ${FILE} + echo " \$(GCC) -c \$(CXXFLAGS) \$(${INCS_NAME})-o ${OBJ_FILE} ${CPP_FILE}" >> ${FILE} fi done echo "" >> ${FILE} diff --git a/trunk/conf/srs.conf b/trunk/conf/srs.conf index 7e8bfeb81..633848f8a 100755 --- a/trunk/conf/srs.conf +++ b/trunk/conf/srs.conf @@ -1,11 +1,11 @@ # the listen ports, split by space. -listen 1935; +listen 1935; # the default chunk size is 128, max is 65536, # some client does not support chunk size change, # however, most clients supports it and it can improve # performance about 10%. # if not specified, set to 4096. -chunk_size 65000; +chunk_size 65000; # vhost list, the __defaultVhost__ is the default vhost # for which cannot identify the required vhost. vhost __defaultVhost__ { @@ -47,4 +47,15 @@ vhost refer.anti_suck.com { # default: not specified. refer_play github.com github.io; } +# config for the pithy print, +# which always print constant message specified by interval, +# whatever the clients in concurrency. +pithy_print { + # shared print interval for all publish clients, in milliseconds. + # if not specified, set to 1100. + publish 2000; + # shared print interval for all play clients, in milliseconds. + # if not specified, set to 1300. + play 3000; +} diff --git a/trunk/configure b/trunk/configure index 71876c391..431e8c537 100755 --- a/trunk/configure +++ b/trunk/configure @@ -16,13 +16,36 @@ if [[ -f ${GLOBAL_DIR_OBJS}/st-1.9/obj/libst.a && -f ${GLOBAL_DIR_OBJS}/st-1.9/o echo "st-1.9t is ok."; else echo "build st-1.9t"; - (rm -rf ${GLOBAL_DIR_OBJS}/st-1.9 && cd ${GLOBAL_DIR_OBJS} && unzip ../3rdparty/st-1.9.zip && cd st-1.9 && make linux-debug) + ( + rm -rf ${GLOBAL_DIR_OBJS}/st-1.9 && cd ${GLOBAL_DIR_OBJS} && + unzip -q ../3rdparty/st-1.9.zip && cd st-1.9 && make linux-debug && + cd .. && rm -f st && ln -sf st-1.9/obj st + ) fi # check status ret=$?; if [[ $ret -ne 0 ]]; then echo "build st-1.9 failed, ret=$ret"; exit $ret; fi if [ ! -f ${GLOBAL_DIR_OBJS}/st-1.9/obj/libst.a ]; then echo "build st-1.9 failed."; exit -1; fi if [ ! -f ${GLOBAL_DIR_OBJS}/st-1.9/obj/libst.so ]; then echo "build st-1.9 failed."; exit -1; fi +# http-parser-2.1 +if [[ -f ${GLOBAL_DIR_OBJS}/http-parser-2.1/http_parser.h && -f ${GLOBAL_DIR_OBJS}/http-parser-2.1/libhttp_parser.a ]]; then + echo "http-parser-2.1 is ok."; +else + echo "build http-parser-2.1"; + ( + rm -rf ${GLOBAL_DIR_OBJS}/http-parser-2.1 && cd ${GLOBAL_DIR_OBJS} && unzip -q ../3rdparty/http-parser-2.1.zip && + cd http-parser-2.1 && + sed -i "s/CPPFLAGS_FAST +=.*$/CPPFLAGS_FAST = \$\(CPPFLAGS_DEBUG\)/g" Makefile && + sed -i "s/CFLAGS_FAST =.*$/CFLAGS_FAST = \$\(CFLAGS_DEBUG\)/g" Makefile && + make package && + cd .. && rm -f hp && ln -sf http-parser-2.1 hp + ) +fi +# check status +ret=$?; if [[ $ret -ne 0 ]]; then echo "build http-parser-2.1 failed, ret=$ret"; exit $ret; fi +if [[ ! -f ${GLOBAL_DIR_OBJS}/http-parser-2.1/http_parser.h ]]; then echo "build http-parser-2.1 failed"; exit -1; fi +if [[ ! -f ${GLOBAL_DIR_OBJS}/http-parser-2.1/libhttp_parser.a ]]; then echo "build http-parser-2.1 failed"; exit -1; fi + ##################################################################################### # generate Makefile. ##################################################################################### @@ -53,18 +76,16 @@ END echo 'generate Makefile ok!' # the performance analysis, uncomments the following when use gperf to analysis the performance. see third-party/readme.txt -#Performance="-pg" -#PerformanceLink="-pg" +Performance="-pg" # enable gdb debug GDBDebug="-g -O0" # the warning level. -WarnLevel="-Wall -Wextra" +WarnLevel="-Wall" # the compile standard. -CppStd="-std=c++98" -# other macros defined -UserMacros="" +CppStd="-ansi" # the cxx flag generated. -CXXFLAGS="${CppStd} ${WarnLevel} ${GDBDebug} ${Performance} ${UserMacros}" +CXXFLAGS="${CppStd} ${WarnLevel} ${GDBDebug}" +#CXXFLAGS="${CppStd} ${WarnLevel} ${GDBDebug} ${Performance}" cat << END > ${GLOBAL_DIR_OBJS}/${GLOBAL_FILE_MAKEFILE} CXXFLAGS = ${CXXFLAGS} GCC = g++ @@ -78,19 +99,21 @@ default: END # Libraries -LibSTRoot="${GLOBAL_DIR_OBJS}/st-1.9/obj" +LibSTRoot="${GLOBAL_DIR_OBJS}/st" LibSTfile="${LibSTRoot}/libst.a" +LibHttpParserRoot="${GLOBAL_DIR_OBJS}/hp" +LibHttpParserfile="${LibHttpParserRoot}/libhttp_parser.a" #Core Module MODULE_ID="CORE" MODULE_DEPENDS=() -ModuleLibIncs=(${LibSTRoot}) +ModuleLibIncs=(${LibSTRoot} ${LibHttpParserRoot}) MODULE_FILES=("srs_core" "srs_core_log" "srs_core_server" "srs_core_error" "srs_core_conn" "srs_core_client" "srs_core_rtmp" "srs_core_socket" "srs_core_buffer" - "srs_core_auto_free" "srs_core_protocol" "srs_core_amf0" + "srs_core_autofree" "srs_core_protocol" "srs_core_amf0" "srs_core_stream" "srs_core_source" "srs_core_codec" - "srs_core_complex_handshake" "srs_core_pithy_print" + "srs_core_handshake" "srs_core_pithy_print" "srs_core_config" "srs_core_refer" "srs_core_reload") MODULE_DIR="src/core" . auto/modules.sh CORE_OBJS="${MODULE_OBJS[@]}" @@ -107,7 +130,7 @@ MAIN_OBJS="${MODULE_OBJS[@].o}" MAIN_ENTRANCES=("srs_main_server") # srs(simple rtmp server) over st(state-threads) -ModuleLibFiles=(${LibSTfile}) +ModuleLibFiles=(${LibSTfile} ${LibHttpParserfile}) MODULE_OBJS="${CORE_OBJS[@]} ${CONFIG_OBJS[@]} ${PROTOCOL_OBJS[@]} ${MAIN_OBJS[@]}" BUILD_KEY="simple_rtmp_server" APP_MAIN="srs_main_server" APP_NAME="simple_rtmp_server" LINK_OPTIONS="-ldl -lssl" SO_PATH="" . auto/apps.sh diff --git a/trunk/src/core/srs_core_auto_free.cpp b/trunk/src/core/srs_core_autofree.cpp similarity index 94% rename from trunk/src/core/srs_core_auto_free.cpp rename to trunk/src/core/srs_core_autofree.cpp index 6e2b42276..3e04c6e12 100755 --- a/trunk/src/core/srs_core_auto_free.cpp +++ b/trunk/src/core/srs_core_autofree.cpp @@ -21,4 +21,4 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include +#include diff --git a/trunk/src/core/srs_core_auto_free.hpp b/trunk/src/core/srs_core_autofree.hpp similarity index 94% rename from trunk/src/core/srs_core_auto_free.hpp rename to trunk/src/core/srs_core_autofree.hpp index 65cafead7..9581bd952 100755 --- a/trunk/src/core/srs_core_auto_free.hpp +++ b/trunk/src/core/srs_core_autofree.hpp @@ -25,7 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SRS_CORE_AUTO_FREE_HPP /* -#include +#include */ #include diff --git a/trunk/src/core/srs_core_client.cpp b/trunk/src/core/srs_core_client.cpp index ebcc9e541..8aba9e23c 100755 --- a/trunk/src/core/srs_core_client.cpp +++ b/trunk/src/core/srs_core_client.cpp @@ -30,7 +30,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include -#include +#include #include #include #include diff --git a/trunk/src/core/srs_core_config.cpp b/trunk/src/core/srs_core_config.cpp index 67feb6414..415e9f50b 100755 --- a/trunk/src/core/srs_core_config.cpp +++ b/trunk/src/core/srs_core_config.cpp @@ -38,7 +38,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include -#include +#include #define FILE_OFFSET(fd) lseek(fd, 0, SEEK_CUR) @@ -455,6 +455,18 @@ int SrsConfig::reload() return ret; } } + srs_trace("reload listen success."); + } + // merge config: pithy_print + if (!srs_directive_equals(root->get("pithy_print"), old_root->get("pithy_print"))) { + for (it = subscribes.begin(); it != subscribes.end(); ++it) { + SrsReloadHandler* subscribe = *it; + if ((ret = subscribe->on_reload_pithy_print()) != ERROR_SUCCESS) { + srs_error("notify subscribes pithy_print listen failed. ret=%d", ret); + return ret; + } + } + srs_trace("reload pithy_print success."); } return ret; @@ -593,6 +605,26 @@ SrsConfDirective* SrsConfig::get_chunk_size() return root->get("chunk_size"); } +SrsConfDirective* SrsConfig::get_pithy_print_publish() +{ + SrsConfDirective* pithy = root->get("pithy_print"); + if (!pithy) { + return NULL; + } + + return pithy->get("publish"); +} + +SrsConfDirective* SrsConfig::get_pithy_print_play() +{ + SrsConfDirective* pithy = root->get("pithy_print"); + if (!pithy) { + return NULL; + } + + return pithy->get("play"); +} + int SrsConfig::parse_file(const char* filename) { int ret = ERROR_SUCCESS; diff --git a/trunk/src/core/srs_core_config.hpp b/trunk/src/core/srs_core_config.hpp index 2c8c34c83..cf48b8766 100755 --- a/trunk/src/core/srs_core_config.hpp +++ b/trunk/src/core/srs_core_config.hpp @@ -114,6 +114,8 @@ public: virtual SrsConfDirective* get_refer_publish(std::string vhost); virtual SrsConfDirective* get_listen(); virtual SrsConfDirective* get_chunk_size(); + virtual SrsConfDirective* get_pithy_print_publish(); + virtual SrsConfDirective* get_pithy_print_play(); private: virtual int parse_file(const char* filename); virtual int parse_argv(int& i, char** argv); diff --git a/trunk/src/core/srs_core_complex_handshake.cpp b/trunk/src/core/srs_core_handshake.cpp similarity index 90% rename from trunk/src/core/srs_core_complex_handshake.cpp rename to trunk/src/core/srs_core_handshake.cpp index dd2fba174..67d3dc2d4 100755 --- a/trunk/src/core/srs_core_complex_handshake.cpp +++ b/trunk/src/core/srs_core_handshake.cpp @@ -21,14 +21,14 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include +#include #include #include #include #include -#include +#include #include // 68bytes FMS key which is used to sign the sever packet. @@ -1058,6 +1058,72 @@ void c1s1::destroy_blocks() } } +SrsSimpleHandshake::SrsSimpleHandshake() +{ +} + +SrsSimpleHandshake::~SrsSimpleHandshake() +{ +} + +int SrsSimpleHandshake::handshake(SrsSocket& skt) +{ + int ret = ERROR_SUCCESS; + + ssize_t nsize; + + char* c0c1 = new char[1537]; + SrsAutoFree(char, c0c1, true); + if ((ret = skt.read_fully(c0c1, 1537, &nsize)) != ERROR_SUCCESS) { + srs_warn("read c0c1 failed. ret=%d", ret); + return ret; + } + srs_verbose("read c0c1 success."); + + // plain text required. + if (c0c1[0] != 0x03) { + ret = ERROR_RTMP_PLAIN_REQUIRED; + srs_warn("only support rtmp plain text. ret=%d", ret); + return ret; + } + srs_verbose("check c0 success, required plain text."); + + // try complex handshake + SrsComplexHandshake complex_handshake; + ret = complex_handshake.handshake(skt, c0c1 + 1); + if (ret == ERROR_SUCCESS) { + srs_trace("complex handshake success."); + return ret; + } + if (ret != ERROR_RTMP_TRY_SIMPLE_HS) { + srs_error("complex handshake failed. ret=%d", ret); + return ret; + } + srs_info("complex handhskae failed, try simple. ret=%d", ret); + + char* s0s1s2 = new char[3073]; + SrsAutoFree(char, s0s1s2, true); + // plain text required. + s0s1s2[0] = 0x03; + if ((ret = skt.write(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { + srs_warn("simple handshake send s0s1s2 failed. ret=%d", ret); + return ret; + } + srs_verbose("simple handshake send s0s1s2 success."); + + char* c2 = new char[1536]; + SrsAutoFree(char, c2, true); + if ((ret = skt.read_fully(c2, 1536, &nsize)) != ERROR_SUCCESS) { + srs_warn("simple handshake read c2 failed. ret=%d", ret); + return ret; + } + srs_verbose("simple handshake read c2 success."); + + srs_trace("simple handshake success."); + + return ret; +} + SrsComplexHandshake::SrsComplexHandshake() { } diff --git a/trunk/src/core/srs_core_complex_handshake.hpp b/trunk/src/core/srs_core_handshake.hpp similarity index 81% rename from trunk/src/core/srs_core_complex_handshake.hpp rename to trunk/src/core/srs_core_handshake.hpp index 5ed6c2df6..e5ba22b7c 100755 --- a/trunk/src/core/srs_core_complex_handshake.hpp +++ b/trunk/src/core/srs_core_handshake.hpp @@ -21,8 +21,8 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef SRS_CORE_COMPLEX_HANDSHKAE_HPP -#define SRS_CORE_COMPLEX_HANDSHKAE_HPP +#ifndef SRS_CORE_HANDSHKAE_HPP +#define SRS_CORE_HANDSHKAE_HPP /* #include @@ -32,6 +32,21 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. class SrsSocket; +/** +* try complex handshake, if failed, fallback to simple handshake. +*/ +class SrsSimpleHandshake +{ +public: + SrsSimpleHandshake(); + virtual ~SrsSimpleHandshake(); +public: + /** + * simple handshake. + */ + virtual int handshake(SrsSocket& skt); +}; + /** * rtmp complex handshake, * @see also crtmp(crtmpserver) or librtmp, diff --git a/trunk/src/core/srs_core_pithy_print.cpp b/trunk/src/core/srs_core_pithy_print.cpp index e2917fb0a..96954c41f 100755 --- a/trunk/src/core/srs_core_pithy_print.cpp +++ b/trunk/src/core/srs_core_pithy_print.cpp @@ -23,15 +23,19 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include +#include #include #include +#include +#include +#include #define SRS_STAGE_DEFAULT_INTERVAL_MS 1200 #define SRS_STAGE_PLAY_USER_INTERVAL_MS 1300 #define SRS_STAGE_PUBLISH_USER_INTERVAL_MS 1100 -struct SrsStageInfo +struct SrsStageInfo : public SrsReloadHandler { int stage_id; int pithy_print_time_ms; @@ -40,19 +44,46 @@ struct SrsStageInfo SrsStageInfo(int _stage_id) { stage_id = _stage_id; - - switch (_stage_id) { - case SRS_STAGE_PLAY_USER: + nb_clients = 0; + + update_print_time(); + + config->subscribe(this); + } + virtual ~SrsStageInfo() + { + config->unsubscribe(this); + } + void update_print_time() + { + switch (stage_id) { + case SRS_STAGE_PLAY_USER: { pithy_print_time_ms = SRS_STAGE_PLAY_USER_INTERVAL_MS; - case SRS_STAGE_PUBLISH_USER: - pithy_print_time_ms = SRS_STAGE_PUBLISH_USER_INTERVAL_MS; + SrsConfDirective* conf = config->get_pithy_print_play(); + if (conf && !conf->arg0().empty()) { + pithy_print_time_ms = ::atoi(conf->arg0().c_str()); + } break; - default: + } + case SRS_STAGE_PUBLISH_USER: { + pithy_print_time_ms = SRS_STAGE_PUBLISH_USER_INTERVAL_MS; + SrsConfDirective* conf = config->get_pithy_print_publish(); + if (conf && !conf->arg0().empty()) { + pithy_print_time_ms = ::atoi(conf->arg0().c_str()); + } + break; + } + default: { pithy_print_time_ms = SRS_STAGE_DEFAULT_INTERVAL_MS; break; + } } - - nb_clients = 0; + } +public: + virtual int on_reload_pithy_print() + { + update_print_time(); + return ERROR_SUCCESS; } }; static std::map _srs_stages; diff --git a/trunk/src/core/srs_core_protocol.cpp b/trunk/src/core/srs_core_protocol.cpp index 45f84df4d..4cc512dbb 100755 --- a/trunk/src/core/srs_core_protocol.cpp +++ b/trunk/src/core/srs_core_protocol.cpp @@ -29,7 +29,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include -#include +#include /**************************************************************************** ***************************************************************************** diff --git a/trunk/src/core/srs_core_reload.cpp b/trunk/src/core/srs_core_reload.cpp index 52b7c2df2..56b115652 100755 --- a/trunk/src/core/srs_core_reload.cpp +++ b/trunk/src/core/srs_core_reload.cpp @@ -35,7 +35,11 @@ SrsReloadHandler::~SrsReloadHandler() int SrsReloadHandler::on_reload_listen() { - int ret = ERROR_SUCCESS; - return ret; + return ERROR_SUCCESS; +} + +int SrsReloadHandler::on_reload_pithy_print() +{ + return ERROR_SUCCESS; } diff --git a/trunk/src/core/srs_core_reload.hpp b/trunk/src/core/srs_core_reload.hpp index be48e19b5..8748ea7c3 100755 --- a/trunk/src/core/srs_core_reload.hpp +++ b/trunk/src/core/srs_core_reload.hpp @@ -39,6 +39,7 @@ public: virtual ~SrsReloadHandler(); public: virtual int on_reload_listen(); + virtual int on_reload_pithy_print(); }; #endif \ No newline at end of file diff --git a/trunk/src/core/srs_core_rtmp.cpp b/trunk/src/core/srs_core_rtmp.cpp index eda853f0b..838ea742f 100755 --- a/trunk/src/core/srs_core_rtmp.cpp +++ b/trunk/src/core/srs_core_rtmp.cpp @@ -27,9 +27,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include -#include +#include #include -#include +#include /** * the signature for packets to client. @@ -167,13 +167,11 @@ SrsRtmp::SrsRtmp(st_netfd_t client_stfd) { protocol = new SrsProtocol(client_stfd); stfd = client_stfd; - complex_handshake = new SrsComplexHandshake(); } SrsRtmp::~SrsRtmp() { srs_freep(protocol); - srs_freep(complex_handshake); } void SrsRtmp::set_recv_timeout(int64_t timeout_us) @@ -225,58 +223,14 @@ int SrsRtmp::handshake() { int ret = ERROR_SUCCESS; - ssize_t nsize; SrsSocket skt(stfd); - char* c0c1 = new char[1537]; - SrsAutoFree(char, c0c1, true); - if ((ret = skt.read_fully(c0c1, 1537, &nsize)) != ERROR_SUCCESS) { - srs_warn("read c0c1 failed. ret=%d", ret); + SrsSimpleHandshake hs; + if ((ret = hs.handshake(skt)) != ERROR_SUCCESS) { return ret; } - srs_verbose("read c0c1 success."); - - // plain text required. - if (c0c1[0] != 0x03) { - ret = ERROR_RTMP_PLAIN_REQUIRED; - srs_warn("only support rtmp plain text. ret=%d", ret); - return ret; - } - srs_verbose("check c0 success, required plain text."); - // try complex handshake - ret = complex_handshake->handshake(skt, c0c1 + 1); - if (ret == ERROR_SUCCESS) { - srs_trace("complex handshake success."); - return ret; - } - if (ret != ERROR_RTMP_TRY_SIMPLE_HS) { - srs_error("complex handshake failed. ret=%d", ret); - return ret; - } - srs_info("complex handhskae failed, try simple. ret=%d", ret); - - char* s0s1s2 = new char[3073]; - SrsAutoFree(char, s0s1s2, true); - // plain text required. - s0s1s2[0] = 0x03; - if ((ret = skt.write(s0s1s2, 3073, &nsize)) != ERROR_SUCCESS) { - srs_warn("simple handshake send s0s1s2 failed. ret=%d", ret); - return ret; - } - srs_verbose("simple handshake send s0s1s2 success."); - - char* c2 = new char[1536]; - SrsAutoFree(char, c2, true); - if ((ret = skt.read_fully(c2, 1536, &nsize)) != ERROR_SUCCESS) { - srs_warn("simple handshake read c2 failed. ret=%d", ret); - return ret; - } - srs_verbose("simple handshake read c2 success."); - - srs_trace("simple handshake success."); - - return ret; + return ret; } int SrsRtmp::connect_app(SrsRequest* req) diff --git a/trunk/src/core/srs_core_rtmp.hpp b/trunk/src/core/srs_core_rtmp.hpp index 707ebc0f0..7590de411 100755 --- a/trunk/src/core/srs_core_rtmp.hpp +++ b/trunk/src/core/srs_core_rtmp.hpp @@ -39,7 +39,6 @@ class ISrsMessage; class SrsCommonMessage; class SrsCreateStreamPacket; class SrsFMLEStartPacket; -class SrsComplexHandshake; class SrsPublishPacket; /** @@ -101,7 +100,6 @@ enum SrsClientType class SrsRtmp { private: - SrsComplexHandshake* complex_handshake; SrsProtocol* protocol; st_netfd_t stfd; public: diff --git a/trunk/src/core/srs_core_source.cpp b/trunk/src/core/srs_core_source.cpp index eb40f62b9..cc28286ff 100755 --- a/trunk/src/core/srs_core_source.cpp +++ b/trunk/src/core/srs_core_source.cpp @@ -27,7 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include -#include +#include #include #include diff --git a/trunk/src/srs/srs.upp b/trunk/src/srs/srs.upp index 66a7817a8..6cb7f96c1 100755 --- a/trunk/src/srs/srs.upp +++ b/trunk/src/srs/srs.upp @@ -6,8 +6,8 @@ file ..\core\srs_core.cpp, ..\core\srs_core_error.hpp, ..\core\srs_core_error.cpp, - ..\core\srs_core_auto_free.hpp, - ..\core\srs_core_auto_free.cpp, + ..\core\srs_core_autofree.hpp, + ..\core\srs_core_autofree.cpp, ..\core\srs_core_server.hpp, ..\core\srs_core_server.cpp, ..\core\srs_core_reload.hpp, @@ -26,8 +26,8 @@ file ..\core\srs_core_codec.cpp, ..\core\srs_core_rtmp.hpp, ..\core\srs_core_rtmp.cpp, - ..\core\srs_core_complex_handshake.hpp, - ..\core\srs_core_complex_handshake.cpp, + ..\core\srs_core_handshake.hpp, + ..\core\srs_core_handshake.cpp, ..\core\srs_core_protocol.hpp, ..\core\srs_core_protocol.cpp, ..\core\srs_core_amf0.hpp,