diff --git a/trunk/auto/depends.sh b/trunk/auto/depends.sh index 0fd5997bd..614e0ee4b 100755 --- a/trunk/auto/depends.sh +++ b/trunk/auto/depends.sh @@ -561,7 +561,7 @@ else fi ##################################################################################### -# build research code +# build research code, librtmp ##################################################################################### if [ $SRS_RESEARCH = YES ]; then mkdir -p ${SRS_OBJS}/research @@ -571,6 +571,10 @@ if [ $SRS_RESEARCH = YES ]; then (cd research/ffempty && make ${SRS_JOBS} && mv ffempty ../../${SRS_OBJS}/research) ret=$?; if [[ $ret -ne 0 ]]; then echo "build research/ffempty failed, ret=$ret"; exit $ret; fi +fi + +if [ $SRS_LIBRTMP = YES ]; then + mkdir -p ${SRS_OBJS}/research # librtmp (cd research/librtmp && mkdir -p objs && ln -sf `pwd`/objs ../../${SRS_OBJS}/research/librtmp) diff --git a/trunk/configure b/trunk/configure index ed85ce46d..89a5e2506 100755 --- a/trunk/configure +++ b/trunk/configure @@ -483,7 +483,7 @@ APP_OBJS="${MODULE_OBJS[@]}" MODULE_ID="LIBS" MODULE_DEPENDS=("CORE" "KERNEL" "RTMP") ModuleLibIncs=(${SRS_OBJS}) -MODULE_FILES=("srs_librtmp" "srs_lib_simple_socket") +MODULE_FILES=("srs_librtmp" "srs_lib_simple_socket" "srs_lib_bandwidth") LIBS_INCS="src/libs"; MODULE_DIR=${LIBS_INCS} . auto/modules.sh LIBS_OBJS="${MODULE_OBJS[@]}" # diff --git a/trunk/research/librtmp/Makefile b/trunk/research/librtmp/Makefile old mode 100644 new mode 100755 index 6002b139f..aeac262e5 --- a/trunk/research/librtmp/Makefile +++ b/trunk/research/librtmp/Makefile @@ -3,7 +3,10 @@ GCC = gcc ifeq ($(HANDSHAKE),) ST_ALL = help else - ST_ALL = objs/srs_flv_parser objs/srs_flv_injecter objs/srs_publish objs/srs_play objs/srs_ingest_flv objs/srs_ingest_rtmp objs/srs_detect_rtmp + ST_ALL = objs/srs_flv_parser \ + objs/srs_flv_injecter objs/srs_publish objs/srs_play \ + objs/srs_ingest_flv objs/srs_ingest_rtmp objs/srs_detect_rtmp \ + objs/srs_bandwidth_check endif .PHONY: default clean help ssl nossl @@ -24,6 +27,7 @@ help: @echo " srs_ingest_flv ingest flv file and publish to RTMP server." @echo " srs_ingest_rtmp ingest RTMP and publish to RTMP server." @echo " srs_detect_rtmp detect RTMP stream info." + @echo " srs_bandwidth_check bandwidth check/test tool." @echo "Remark: about simple/complex handshake, see: http://blog.csdn.net/win_lin/article/details/13006803" @echo "Remark: srs Makefile will auto invoke this by --with/without-ssl, " @echo " that is, if user specified ssl(by --with-ssl), srs will make this by 'make ssl'" @@ -88,3 +92,6 @@ objs/srs_ingest_rtmp: srs_ingest_rtmp.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $( objs/srs_detect_rtmp: srs_detect_rtmp.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(GCC) srs_detect_rtmp.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o objs/srs_detect_rtmp + +objs/srs_bandwidth_check: srs_bandwidth_check.c $(SRS_RESEARCH_DEPS) $(SRS_LIBRTMP_I) $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) + $(GCC) srs_bandwidth_check.c $(SRS_LIBRTMP_L) $(SRS_LIBSSL_L) $(EXTRA_CXX_FLAG) -o objs/srs_bandwidth_check diff --git a/trunk/research/librtmp/srs_bandwidth_check.c b/trunk/research/librtmp/srs_bandwidth_check.c new file mode 100644 index 000000000..223048a29 --- /dev/null +++ b/trunk/research/librtmp/srs_bandwidth_check.c @@ -0,0 +1,113 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013-2014 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +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. +*/ +/** +gcc srs_bandwidth_check.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_bandwidth_check +*/ + +#include +#include + +#include "../../objs/include/srs_librtmp.h" + +int main(int argc, char** argv) +{ + int ret = 0; + srs_rtmp_t rtmp; + + // packet data + int type, size; + u_int32_t timestamp = 0; + char* data; + + // srs debug info. + char srs_server[128]; + char srs_primary_authors[128]; + char srs_id[64]; + char srs_pid[64]; + char srs_server_ip[128]; + // bandwidth test data. + int64_t start_time, end_time; + int play_kbps, publish_kbps; + int play_bytes, publish_bytes; + int play_duration, publish_duration; + + if (argc <= 1) { + printf("RTMP bandwidth check/test with server.\n" + "Usage: %s \n" + " rtmp_url RTMP bandwidth url to check. format: rtmp://server:port/app?key=xxx&&vhost=xxx\n" + "For example:\n" + " %s rtmp://127.0.0.1:1935/app?key=35c9b402c12a7246868752e2878f7e0e,vhost=bandcheck.srs.com\n" + "@remark, output text to stdout, while json to stderr.\n", + argv[0], argv[0]); + ret = 1; + exit(ret); + return ret; + } + + rtmp = srs_rtmp_create2(argv[1]); + + printf("RTMP bandwidth check/test with server.\n"); + printf("srs(simple-rtmp-server) client librtmp library.\n"); + printf("version: %d.%d.%d\n", srs_version_major(), srs_version_minor(), srs_version_revision()); + printf("bandwidth check/test url: %s\n", argv[1]); + + if ((ret = srs_simple_handshake(rtmp)) != 0) { + printf("simple handshake failed.\n"); + goto rtmp_destroy; + } + printf("simple handshake success\n"); + + if ((ret = srs_connect_app(rtmp)) != 0) { + printf("connect vhost/app failed.\n"); + goto rtmp_destroy; + } + printf("connect vhost/app success\n"); + + if ((ret = srs_bandwidth_check(rtmp, + srs_server, srs_primary_authors, + srs_id, srs_pid, srs_server_ip, + &start_time, &end_time, &play_kbps, &publish_kbps, + &play_bytes, &publish_bytes, &play_duration, &publish_duration)) != 0 + ) { + printf("bandwidth check/test failed.\n"); + goto rtmp_destroy; + } + printf("bandwidth check/test success\n"); + + printf("\n%s, %s\n" + "%s, srs_pid=%s, srs_id=%s\n" + "duration: %dms(%d+%d)\n" + "play: %dkbps\n" + "publish: %dkbps\n\n", + (char*)srs_server, (char*)srs_primary_authors, + (char*)srs_server_ip, (char*)srs_pid, (char*)srs_id, + (int)(end_time - start_time), play_duration, publish_duration, + play_kbps, + publish_kbps); + +rtmp_destroy: + srs_rtmp_destroy(rtmp); + + printf("terminate with ret=%d\n", ret); + return ret; +} diff --git a/trunk/research/players/srs_bwt/release/srs_bwt.swf b/trunk/research/players/srs_bwt/release/srs_bwt.swf index 3376abed0..e0c6cd423 100755 Binary files a/trunk/research/players/srs_bwt/release/srs_bwt.swf and b/trunk/research/players/srs_bwt/release/srs_bwt.swf differ diff --git a/trunk/research/players/srs_bwt/src/SrsBandwidth.as b/trunk/research/players/srs_bwt/src/SrsBandwidth.as index c0862ae13..e09e55ffc 100755 --- a/trunk/research/players/srs_bwt/src/SrsBandwidth.as +++ b/trunk/research/players/srs_bwt/src/SrsBandwidth.as @@ -429,8 +429,7 @@ package publish_timeout_handler = 0; } } - private function onSrsBandCheckFinished(evt:Object):void{ - var code:Number = evt.code; + private function onSrsBandCheckFinished(evt:Object):void{ var start_time:Number = evt.start_time; var end_time:Number = evt.end_time; var play_kbps:Number = evt.play_kbps; diff --git a/trunk/src/app/srs_app_bandwidth.cpp b/trunk/src/app/srs_app_bandwidth.cpp index 11f0569cb..4c55d0619 100644 --- a/trunk/src/app/srs_app_bandwidth.cpp +++ b/trunk/src/app/srs_app_bandwidth.cpp @@ -68,9 +68,9 @@ void SrsBandwidthSample::calc_kbps(int _bytes, int _duration) * recv bandwidth helper. */ typedef bool (*_CheckPacketType)(SrsBandwidthPacket* pkt); -bool _bandwidth_is_flash_final(SrsBandwidthPacket* pkt) +bool _bandwidth_is_final(SrsBandwidthPacket* pkt) { - return pkt->is_flash_final(); + return pkt->is_final(); } bool _bandwidth_is_starting_play(SrsBandwidthPacket* pkt) { @@ -183,7 +183,12 @@ int SrsBandwidth::do_bandwidth_check(SrsKbpsLimit* limit) SrsBandwidthSample play_sample; SrsBandwidthSample publish_sample; + + // timeout for a packet. + _rtmp->set_send_timeout(play_sample.duration_ms * 1000); + _rtmp->set_recv_timeout(publish_sample.duration_ms * 1000); + // start test. int64_t start_time = srs_get_system_time_ms(); // sample play @@ -254,7 +259,7 @@ int SrsBandwidth::play_start(SrsBandwidthSample* sample, SrsKbpsLimit* limit) return ret; } } - srs_info("BW check begin."); + srs_info("BW check play begin."); if ((ret = _srs_expect_bandwidth_packet(_rtmp, _bandwidth_is_starting_play)) != ERROR_SUCCESS) { return ret; @@ -424,7 +429,6 @@ int SrsBandwidth::finial(SrsBandwidthSample& play_sample, SrsBandwidthSample& pu // flash client will close connection when got this packet, // for the publish queue may contains packets. SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_finish(); - pkt->data->set("code", SrsAmf0Any::number(ERROR_SUCCESS)); pkt->data->set("start_time", SrsAmf0Any::number(start_time)); pkt->data->set("end_time", SrsAmf0Any::number(end_time)); pkt->data->set("play_kbps", SrsAmf0Any::number(play_sample.kbps)); @@ -445,7 +449,7 @@ int SrsBandwidth::finial(SrsBandwidthSample& play_sample, SrsBandwidthSample& pu bool is_flash = (_req->swfUrl != ""); if (!is_flash) { // ignore any error. - _srs_expect_bandwidth_packet(_rtmp, _bandwidth_is_flash_final); + _srs_expect_bandwidth_packet(_rtmp, _bandwidth_is_final); srs_info("BW check recv flash final response."); } diff --git a/trunk/src/app/srs_app_forward.cpp b/trunk/src/app/srs_app_forward.cpp index 1bd20fa97..7e80f1710 100644 --- a/trunk/src/app/srs_app_forward.cpp +++ b/trunk/src/app/srs_app_forward.cpp @@ -97,11 +97,10 @@ int SrsForwarder::on_publish(SrsRequest* req, std::string forward_server) } // discovery vhost std::string vhost = req->vhost; - srs_vhost_resolve(vhost, s_port); port = ::atoi(s_port.c_str()); // generate tcUrl - tc_url = srs_generate_tc_url(forward_server, vhost, req->app, s_port); + tc_url = srs_generate_tc_url(forward_server, vhost, req->app, s_port, req->param); // dead loop check std::string source_ep = "rtmp://"; diff --git a/trunk/src/libs/srs_lib_bandwidth.cpp b/trunk/src/libs/srs_lib_bandwidth.cpp new file mode 100644 index 000000000..8c00ad253 --- /dev/null +++ b/trunk/src/libs/srs_lib_bandwidth.cpp @@ -0,0 +1,254 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013-2014 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +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 + +/** +* recv bandwidth helper. +*/ +typedef bool (*_CheckPacketType)(SrsBandwidthPacket* pkt); +bool _bandwidth_is_start_play(SrsBandwidthPacket* pkt) +{ + return pkt->is_start_play(); +} +bool _bandwidth_is_stop_play(SrsBandwidthPacket* pkt) +{ + return pkt->is_stop_play(); +} +bool _bandwidth_is_start_publish(SrsBandwidthPacket* pkt) +{ + return pkt->is_start_publish(); +} +bool _bandwidth_is_finish(SrsBandwidthPacket* pkt) +{ + return pkt->is_finish(); +} +int _srs_expect_bandwidth_packet(SrsRtmpClient* rtmp, _CheckPacketType pfn) +{ + int ret = ERROR_SUCCESS; + + while (true) { + SrsMessage* msg = NULL; + SrsBandwidthPacket* pkt = NULL; + if ((ret = rtmp->expect_message(&msg, &pkt)) != ERROR_SUCCESS) { + return ret; + } + SrsAutoFree(SrsMessage, msg); + SrsAutoFree(SrsBandwidthPacket, pkt); + srs_info("get final message success."); + + if (pfn(pkt)) { + return ret; + } + } + + return ret; +} + +SrsBandwidthClient::SrsBandwidthClient() +{ + _rtmp = NULL; +} + +SrsBandwidthClient::~SrsBandwidthClient() +{ +} + +int SrsBandwidthClient::initialize(SrsRtmpClient* rtmp) +{ + _rtmp = rtmp; + + return ERROR_SUCCESS; +} + +int SrsBandwidthClient::bandwidth_check( + char srs_server[128], char srs_primary_authors[128], + char srs_id[64], char srs_pid[64], char srs_server_ip[128], + int64_t* start_time, int64_t* end_time, + int* play_kbps, int* publish_kbps, + int* play_bytes, int* publish_bytes, + int* play_duration, int* publish_duration +) { + int ret = ERROR_SUCCESS; + + *start_time = srs_get_system_time_ms(); + + // play + if ((ret = play_start()) != ERROR_SUCCESS) { + return ret; + } + if ((ret = play_checking()) != ERROR_SUCCESS) { + return ret; + } + if ((ret = play_stop()) != ERROR_SUCCESS) { + return ret; + } + + // publish + if ((ret = publish_start()) != ERROR_SUCCESS) { + return ret; + } + if ((ret = publish_checking()) != ERROR_SUCCESS) { + return ret; + } + if ((ret = publish_stop()) != ERROR_SUCCESS) { + return ret; + } + + *end_time = srs_get_system_time_ms(); + + return ret; +} + +int SrsBandwidthClient::play_start() +{ + int ret = ERROR_SUCCESS; + + if ((ret = _srs_expect_bandwidth_packet(_rtmp, _bandwidth_is_start_play)) != ERROR_SUCCESS) { + return ret; + } + srs_info("BW check recv play begin request."); + + if (true) { + // send start play response to server. + SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_starting_play(); + + if ((ret = _rtmp->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { + srs_error("send bandwidth check start play message failed. ret=%d", ret); + return ret; + } + } + srs_info("BW check play begin."); + + return ret; +} + +int SrsBandwidthClient::play_checking() +{ + int ret = ERROR_SUCCESS; + return ret; +} + +int SrsBandwidthClient::play_stop() +{ + int ret = ERROR_SUCCESS; + + if ((ret = _srs_expect_bandwidth_packet(_rtmp, _bandwidth_is_stop_play)) != ERROR_SUCCESS) { + return ret; + } + srs_info("BW check recv play stop request."); + + if (true) { + // send stop play response to server. + SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_stop_play(); + + if ((ret = _rtmp->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { + srs_error("send bandwidth check stop play message failed. ret=%d", ret); + return ret; + } + } + srs_info("BW check play stop."); + + return ret; +} + +int SrsBandwidthClient::publish_start() +{ + int ret = ERROR_SUCCESS; + + if ((ret = _srs_expect_bandwidth_packet(_rtmp, _bandwidth_is_start_publish)) != ERROR_SUCCESS) { + return ret; + } + srs_info("BW check recv publish begin request."); + + if (true) { + // send start publish response to server. + SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_starting_publish(); + + if ((ret = _rtmp->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { + srs_error("send bandwidth check start publish message failed. ret=%d", ret); + return ret; + } + } + srs_info("BW check publish begin."); + + return ret; +} + +int SrsBandwidthClient::publish_checking() +{ + int ret = ERROR_SUCCESS; + return ret; +} + +int SrsBandwidthClient::publish_stop() +{ + int ret = ERROR_SUCCESS; + + if ((ret = _srs_expect_bandwidth_packet(_rtmp, _bandwidth_is_start_publish)) != ERROR_SUCCESS) { + return ret; + } + srs_info("BW check recv publish stop request."); + + if (true) { + // send start publish response to server. + SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_starting_publish(); + + if ((ret = _rtmp->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { + srs_error("send bandwidth check stop publish message failed. ret=%d", ret); + return ret; + } + } + srs_info("BW check publish stop."); + + return ret; +} + +int SrsBandwidthClient::finial() +{ + int ret = ERROR_SUCCESS; + + if ((ret = _srs_expect_bandwidth_packet(_rtmp, _bandwidth_is_finish)) != ERROR_SUCCESS) { + return ret; + } + srs_info("BW check recv finish/report request."); + + if (true) { + // send final response to server. + SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_final(); + + if ((ret = _rtmp->send_and_free_packet(pkt, 0)) != ERROR_SUCCESS) { + srs_error("send bandwidth check final message failed. ret=%d", ret); + return ret; + } + } + srs_info("BW check final."); + + return ret; +} diff --git a/trunk/src/libs/srs_lib_bandwidth.hpp b/trunk/src/libs/srs_lib_bandwidth.hpp new file mode 100644 index 000000000..1fa7fcfa3 --- /dev/null +++ b/trunk/src/libs/srs_lib_bandwidth.hpp @@ -0,0 +1,97 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013-2014 winlin + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +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_LIB_BANDWIDTH_HPP +#define SRS_LIB_BANDWIDTH_HPP + +/* +#include +*/ + +#include + +class SrsRtmpClient; + +/** +* bandwith client library for srs-librtmp. +*/ +class SrsBandwidthClient +{ +private: + SrsRtmpClient* _rtmp; +public: + SrsBandwidthClient(); + virtual ~SrsBandwidthClient(); +public: + /** + * initialize the bandwidth check client. + */ + virtual int initialize(SrsRtmpClient* rtmp); + /** + * do bandwidth check. + * + * SRS debug info: + * @param srs_server, 128bytes, server info. + * @param srs_primary_authors, 128bytes, primary authors. + * @param srs_id, 64bytes, debug info, client id in server log. + * @param srs_pid, 64bytes, debug info, server pid in log. + * @param srs_server_ip, 128bytes, debug info, server ip client connected at. + * + * bandwidth info: + * @param start_time, output the start time, in ms. + * @param end_time, output the end time, in ms. + * @param play_kbps, output the play/download kbps. + * @param publish_kbps, output the publish/upload kbps. + * @param play_bytes, output the play/download bytes. + * @param publish_bytes, output the publish/upload bytes. + * @param play_duration, output the play/download test duration, in ms. + * @param publish_duration, output the publish/upload test duration, in ms. + */ + virtual int bandwidth_check( + char srs_server[128], char srs_primary_authors[128], + char srs_id[64], char srs_pid[64], char srs_server_ip[128], + int64_t* start_time, int64_t* end_time, + int* play_kbps, int* publish_kbps, + int* play_bytes, int* publish_bytes, + int* play_duration, int* publish_duration + ); +private: + /** + * play check/test, downloading bandwidth kbps. + */ + virtual int play_start(); + virtual int play_checking(); + virtual int play_stop(); + /** + * publish check/test, publishing bandwidth kbps. + */ + virtual int publish_start(); + virtual int publish_checking(); + virtual int publish_stop(); + /** + * report and final packet + */ + virtual int finial(); +}; + +#endif diff --git a/trunk/src/libs/srs_librtmp.cpp b/trunk/src/libs/srs_librtmp.cpp index 7cbac9a7c..291e4fcc6 100644 --- a/trunk/src/libs/srs_librtmp.cpp +++ b/trunk/src/libs/srs_librtmp.cpp @@ -42,6 +42,7 @@ using namespace std; #include #include #include +#include // if user want to define log, define the folowing macro. #ifndef SRS_RTMP_USER_DEFINED_LOG @@ -63,6 +64,7 @@ struct Context std::string vhost; std::string app; std::string stream; + std::string param; SrsRtmpClient* rtmp; SimpleSocketStream* skt; @@ -91,39 +93,11 @@ int srs_librtmp_context_parse_uri(Context* context) context->stream = uri.substr(pos + 1); context->tcUrl = uri = uri.substr(0, pos); } - // schema - if ((pos = uri.find("rtmp://")) != string::npos) { - uri = uri.substr(pos + 7); - } - // host/vhost/port - if ((pos = uri.find(":")) != string::npos) { - context->vhost = context->host = uri.substr(0, pos); - uri = uri.substr(pos + 1); - - if ((pos = uri.find("/")) != string::npos) { - context->port = uri.substr(0, pos); - uri = uri.substr(pos + 1); - } - } else { - if ((pos = uri.find("/")) != string::npos) { - context->vhost = context->host = uri.substr(0, pos); - uri = uri.substr(pos + 1); - } - context->port = RTMP_DEFAULT_PORT; - } - // app - context->app = uri; - // query of app - if ((pos = uri.find("?")) != string::npos) { - context->app = uri.substr(0, pos); - string query = uri.substr(pos + 1); - if ((pos = query.find("vhost=")) != string::npos) { - context->vhost = query.substr(pos + 6); - if ((pos = context->vhost.find("&")) != string::npos) { - context->vhost = context->vhost.substr(pos); - } - } - } + + std::string schema; + srs_discovery_tc_url(context->tcUrl, + schema, context->host, context->vhost, context->app, context->port, + context->param); return ret; } @@ -176,6 +150,18 @@ srs_rtmp_t srs_rtmp_create(const char* url) return context; } +srs_rtmp_t srs_rtmp_create2(const char* url) +{ + Context* context = new Context(); + + // use url as tcUrl. + context->url = url; + // auto append stream. + context->url += "/livestream"; + + return context; +} + void srs_rtmp_destroy(srs_rtmp_t rtmp) { srs_assert(rtmp != NULL); @@ -263,7 +249,10 @@ int srs_connect_app(srs_rtmp_t rtmp) srs_assert(rtmp != NULL); Context* context = (Context*)rtmp; - string tcUrl = srs_generate_tc_url(context->ip, context->vhost, context->app, context->port); + string tcUrl = srs_generate_tc_url( + context->ip, context->vhost, context->app, context->port, + context->param + ); if ((ret = context->rtmp->connect_app(context->app, tcUrl)) != ERROR_SUCCESS) { return ret; } @@ -319,6 +308,52 @@ const char* srs_type2string(int type) return unknown; } +int srs_bandwidth_check(srs_rtmp_t rtmp, + char srs_server[128], char srs_primary_authors[128], + char srs_id[64], char srs_pid[64], char srs_server_ip[128], + int64_t* start_time, int64_t* end_time, + int* play_kbps, int* publish_kbps, + int* play_bytes, int* publish_bytes, + int* play_duration, int* publish_duration +) { + srs_server[0] = 0; + srs_primary_authors[0] = 0; + srs_id[0] = 0; + srs_pid[0] = 0; + srs_server_ip[0] = 0; + + *start_time = 0; + *end_time = 0; + *play_kbps = 0; + *publish_kbps = 0; + *play_bytes = 0; + *publish_bytes = 0; + *play_duration = 0; + *publish_duration = 0; + + int ret = ERROR_SUCCESS; + + srs_assert(rtmp != NULL); + Context* context = (Context*)rtmp; + + SrsBandwidthClient client; + + if ((ret = client.initialize(context->rtmp)) != ERROR_SUCCESS) { + return ret; + } + + if ((ret = client.bandwidth_check( + srs_server, srs_primary_authors, + srs_id, srs_pid, srs_server_ip, + start_time, end_time, play_kbps, publish_kbps, + play_bytes, publish_bytes, play_duration, publish_duration)) != ERROR_SUCCESS + ) { + return ret; + } + + return ret; +} + int srs_read_packet(srs_rtmp_t rtmp, int* type, u_int32_t* timestamp, char** data, int* size) { *type = 0; diff --git a/trunk/src/libs/srs_librtmp.hpp b/trunk/src/libs/srs_librtmp.hpp index b3c02c90f..086403a38 100644 --- a/trunk/src/libs/srs_librtmp.hpp +++ b/trunk/src/libs/srs_librtmp.hpp @@ -52,6 +52,18 @@ typedef void* srs_rtmp_t; * @return a rtmp handler, or NULL if error occured. */ srs_rtmp_t srs_rtmp_create(const char* url); +/** +* create rtmp with url, used for connection specified application. +* @param url the tcUrl, for exmple: +* rtmp://127.0.0.1/live +* @remark this is used to create application connection-oriented, +* for example, the bandwidth client used this, no stream specified. +*/ +srs_rtmp_t srs_rtmp_create2(const char* url); +/** +* close and destroy the rtmp stack. +* @remark, user should use the rtmp again. +*/ void srs_rtmp_destroy(srs_rtmp_t rtmp); /** @@ -107,6 +119,35 @@ int srs_play_stream(srs_rtmp_t rtmp); */ int srs_publish_stream(srs_rtmp_t rtmp); +/** +* do bandwidth check with srs server. +* +* SRS debug info: +* @param srs_server, 128bytes, server info. +* @param srs_primary_authors, 128bytes, primary authors. +* @param srs_id, 64bytes, debug info, client id in server log. +* @param srs_pid, 64bytes, debug info, server pid in log. +* @param srs_server_ip, 128bytes, debug info, server ip client connected at. +* +* bandwidth info: +* @param start_time, output the start time, in ms. +* @param end_time, output the end time, in ms. +* @param play_kbps, output the play/download kbps. +* @param publish_kbps, output the publish/upload kbps. +* @param play_bytes, output the play/download bytes. +* @param publish_bytes, output the publish/upload bytes. +* @param play_duration, output the play/download test duration, in ms. +* @param publish_duration, output the publish/upload test duration, in ms. +*/ +int srs_bandwidth_check(srs_rtmp_t rtmp, + char srs_server[128], char srs_primary_authors[128], + char srs_id[64], char srs_pid[64], char srs_server_ip[128], + int64_t* start_time, int64_t* end_time, + int* play_kbps, int* publish_kbps, + int* play_bytes, int* publish_bytes, + int* play_duration, int* publish_duration +); + /** * E.4.1 FLV Tag, page 75 */ diff --git a/trunk/src/rtmp/srs_protocol_rtmp.cpp b/trunk/src/rtmp/srs_protocol_rtmp.cpp index fc717ee63..90363fc0a 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp.cpp +++ b/trunk/src/rtmp/srs_protocol_rtmp.cpp @@ -95,6 +95,7 @@ SrsRequest* SrsRequest::copy() cp->pageUrl = pageUrl; cp->host = host; cp->port = port; + cp->param = param; cp->schema = schema; cp->stream = stream; cp->swfUrl = swfUrl; @@ -823,7 +824,9 @@ int SrsRtmpServer::connect_app(SrsRequest* req) srs_info("get connect app message params success."); - srs_discovery_tc_url(req->tcUrl, req->schema, req->host, req->vhost, req->app, req->port); + srs_discovery_tc_url(req->tcUrl, + req->schema, req->host, req->vhost, req->app, req->port, + req->param); req->strip(); return ret; diff --git a/trunk/src/rtmp/srs_protocol_rtmp.hpp b/trunk/src/rtmp/srs_protocol_rtmp.hpp index 4c31dd583..2e907bcc1 100644 --- a/trunk/src/rtmp/srs_protocol_rtmp.hpp +++ b/trunk/src/rtmp/srs_protocol_rtmp.hpp @@ -67,10 +67,17 @@ public: public: // discovery from tcUrl and play/publish. std::string schema; + // the vhost in tcUrl. std::string vhost; + // the host in tcUrl. std::string host; + // the port in tcUrl. std::string port; + // the app in tcUrl, without param. std::string app; + // the param in tcUrl(app). + std::string param; + // the stream in play/publish std::string stream; // for play live stream, // used to specified the stop when exceed the duration. diff --git a/trunk/src/rtmp/srs_protocol_stack.cpp b/trunk/src/rtmp/srs_protocol_stack.cpp index 62b87d6a8..118757a50 100644 --- a/trunk/src/rtmp/srs_protocol_stack.cpp +++ b/trunk/src/rtmp/srs_protocol_stack.cpp @@ -232,17 +232,16 @@ messages. #define SRS_BW_CHECK_START_PUBLISH "onSrsBandCheckStartPublishBytes" #define SRS_BW_CHECK_STARTING_PUBLISH "onSrsBandCheckStartingPublishBytes" #define SRS_BW_CHECK_STOP_PUBLISH "onSrsBandCheckStopPublishBytes" +// @remark, flash never send out this packet, for its queue is full. #define SRS_BW_CHECK_STOPPED_PUBLISH "onSrsBandCheckStoppedPublishBytes" // EOF control. +// the report packet when check finished. #define SRS_BW_CHECK_FINISHED "onSrsBandCheckFinished" -// for flash, it will sendout a final call, -// used to confirm got the report. -// actually, client send out this packet and close the connection, -// so server may cannot got this packet, ignore is ok. -#define SRS_BW_CHECK_FLASH_FINAL "finalClientPacket" +// @remark, flash never send out this packet, for its queue is full. +#define SRS_BW_CHECK_FINAL "finalClientPacket" -// client only +// data packets #define SRS_BW_CHECK_PLAYING "onSrsBandCheckPlaying" #define SRS_BW_CHECK_PUBLISHING "onSrsBandCheckPublishing" @@ -688,7 +687,7 @@ int SrsProtocol::do_decode_message(SrsMessageHeader& header, SrsStream* stream, || command == SRS_BW_CHECK_STOP_PLAY || command == SRS_BW_CHECK_STOP_PUBLISH || command == SRS_BW_CHECK_STOPPED_PUBLISH - || command == SRS_BW_CHECK_FLASH_FINAL) + || command == SRS_BW_CHECK_FINAL) { srs_info("decode the AMF0/AMF3 band width check message."); *ppacket = packet = new SrsBandwidthPacket(); @@ -3270,35 +3269,54 @@ int SrsBandwidthPacket::encode_packet(SrsStream* stream) return ret; } +bool SrsBandwidthPacket::is_start_play() +{ + return command_name == SRS_BW_CHECK_START_PLAY; +} + bool SrsBandwidthPacket::is_starting_play() { return command_name == SRS_BW_CHECK_STARTING_PLAY; } +bool SrsBandwidthPacket::is_stop_play() +{ + return command_name == SRS_BW_CHECK_STOP_PLAY; +} + bool SrsBandwidthPacket::is_stopped_play() { return command_name == SRS_BW_CHECK_STOPPED_PLAY; } +bool SrsBandwidthPacket::is_start_publish() +{ + return command_name == SRS_BW_CHECK_START_PUBLISH; +} + bool SrsBandwidthPacket::is_starting_publish() { return command_name == SRS_BW_CHECK_STARTING_PUBLISH; } +bool SrsBandwidthPacket::is_stop_publish() +{ + return command_name == SRS_BW_CHECK_STOP_PUBLISH; +} + bool SrsBandwidthPacket::is_stopped_publish() { return command_name == SRS_BW_CHECK_STOPPED_PUBLISH; } -bool SrsBandwidthPacket::is_flash_final() +bool SrsBandwidthPacket::is_finish() { - return command_name == SRS_BW_CHECK_FLASH_FINAL; + return command_name == SRS_BW_CHECK_FINISHED; } -SrsBandwidthPacket* SrsBandwidthPacket::create_finish() +bool SrsBandwidthPacket::is_final() { - SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); - return pkt->set_command(SRS_BW_CHECK_FINISHED); + return command_name == SRS_BW_CHECK_FINAL; } SrsBandwidthPacket* SrsBandwidthPacket::create_start_play() @@ -3307,6 +3325,12 @@ SrsBandwidthPacket* SrsBandwidthPacket::create_start_play() return pkt->set_command(SRS_BW_CHECK_START_PLAY); } +SrsBandwidthPacket* SrsBandwidthPacket::create_starting_play() +{ + SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); + return pkt->set_command(SRS_BW_CHECK_STARTING_PLAY); +} + SrsBandwidthPacket* SrsBandwidthPacket::create_playing() { SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); @@ -3325,12 +3349,36 @@ SrsBandwidthPacket* SrsBandwidthPacket::create_start_publish() return pkt->set_command(SRS_BW_CHECK_START_PUBLISH); } +SrsBandwidthPacket* SrsBandwidthPacket::create_starting_publish() +{ + SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); + return pkt->set_command(SRS_BW_CHECK_STARTING_PUBLISH); +} + +SrsBandwidthPacket* SrsBandwidthPacket::create_publishing() +{ + SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); + return pkt->set_command(SRS_BW_CHECK_PUBLISHING); +} + SrsBandwidthPacket* SrsBandwidthPacket::create_stop_publish() { SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); return pkt->set_command(SRS_BW_CHECK_STOP_PUBLISH); } +SrsBandwidthPacket* SrsBandwidthPacket::create_finish() +{ + SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); + return pkt->set_command(SRS_BW_CHECK_FINISHED); +} + +SrsBandwidthPacket* SrsBandwidthPacket::create_final() +{ + SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); + return pkt->set_command(SRS_BW_CHECK_FINAL); +} + SrsBandwidthPacket* SrsBandwidthPacket::set_command(string command) { command_name = command; diff --git a/trunk/src/rtmp/srs_protocol_stack.hpp b/trunk/src/rtmp/srs_protocol_stack.hpp index adfe81aac..a235032e0 100644 --- a/trunk/src/rtmp/srs_protocol_stack.hpp +++ b/trunk/src/rtmp/srs_protocol_stack.hpp @@ -1230,17 +1230,26 @@ protected: virtual int encode_packet(SrsStream* stream); // help function for bandwidth packet. public: + virtual bool is_start_play(); virtual bool is_starting_play(); + virtual bool is_stop_play(); virtual bool is_stopped_play(); + virtual bool is_start_publish(); virtual bool is_starting_publish(); + virtual bool is_stop_publish(); virtual bool is_stopped_publish(); - virtual bool is_flash_final(); - static SrsBandwidthPacket* create_finish(); + virtual bool is_finish(); + virtual bool is_final(); static SrsBandwidthPacket* create_start_play(); + static SrsBandwidthPacket* create_starting_play(); static SrsBandwidthPacket* create_playing(); static SrsBandwidthPacket* create_stop_play(); static SrsBandwidthPacket* create_start_publish(); + static SrsBandwidthPacket* create_starting_publish(); + static SrsBandwidthPacket* create_publishing(); static SrsBandwidthPacket* create_stop_publish(); + static SrsBandwidthPacket* create_finish(); + static SrsBandwidthPacket* create_final(); private: virtual SrsBandwidthPacket* set_command(std::string command); }; diff --git a/trunk/src/rtmp/srs_protocol_utility.cpp b/trunk/src/rtmp/srs_protocol_utility.cpp index f85c06b57..af850b380 100644 --- a/trunk/src/rtmp/srs_protocol_utility.cpp +++ b/trunk/src/rtmp/srs_protocol_utility.cpp @@ -32,7 +32,7 @@ using namespace std; void srs_discovery_tc_url( string tcUrl, string& schema, string& host, string& vhost, - string& app, string& port + string& app, string& port, std::string& param ) { size_t pos = std::string::npos; std::string url = tcUrl; @@ -58,16 +58,23 @@ void srs_discovery_tc_url( app = url; vhost = host; - srs_vhost_resolve(vhost, app); + srs_vhost_resolve(vhost, app, param); } -void srs_vhost_resolve(string& vhost, string& app) +void srs_vhost_resolve(string& vhost, string& app, string& param) { + // get original param + size_t pos = 0; + if ((pos = app.find("?")) != std::string::npos) { + param = app.substr(pos); + } + + // filter tcUrl + app = srs_string_replace(app, ",", "?"); app = srs_string_replace(app, "...", "?"); app = srs_string_replace(app, "&&", "?"); app = srs_string_replace(app, "=", "?"); - size_t pos = 0; if ((pos = app.find("?")) == std::string::npos) { return; } @@ -106,7 +113,7 @@ void srs_random_generate(char* bytes, int size) } } -string srs_generate_tc_url(string ip, string vhost, string app, string port) +string srs_generate_tc_url(string ip, string vhost, string app, string port, string param) { string tcUrl = "rtmp://"; @@ -123,6 +130,7 @@ string srs_generate_tc_url(string ip, string vhost, string app, string port) tcUrl += "/"; tcUrl += app; + tcUrl += param; return tcUrl; } diff --git a/trunk/src/rtmp/srs_protocol_utility.hpp b/trunk/src/rtmp/srs_protocol_utility.hpp index 5aff42108..38b4e125d 100644 --- a/trunk/src/rtmp/srs_protocol_utility.hpp +++ b/trunk/src/rtmp/srs_protocol_utility.hpp @@ -50,20 +50,23 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * @param app, for example, live * @param port, for example, 19350 * default to 1935 if not specified. +* param param, for example, vhost=vhost.ossrs.net */ extern void srs_discovery_tc_url( std::string tcUrl, std::string& schema, std::string& host, std::string& vhost, - std::string& app, std::string& port + std::string& app, std::string& port, std::string& param ); /** * resolve the vhost in query string +* @pram vhost, update the vhost if query contains the vhost. * @param app, may contains the vhost in query string format: * app?vhost=request_vhost * app...vhost...request_vhost +* @param param, the query, for example, ?vhost=xxx */ -extern void srs_vhost_resolve(std::string& vhost, std::string& app); +extern void srs_vhost_resolve(std::string& vhost, std::string& app, std::string& param); /** * generate ramdom data for handshake. @@ -72,12 +75,14 @@ extern void srs_random_generate(char* bytes, int size); /** * generate the tcUrl. +* @param param, the app parameters in tcUrl. for example, ?key=xxx,vhost=xxx * @return the tcUrl generated from ip/vhost/app/port. * @remark when vhost equals to __defaultVhost__, use ip as vhost. * @remark ignore port if port equals to default port 1935. */ extern std::string srs_generate_tc_url( - std::string ip, std::string vhost, std::string app, std::string port + std::string ip, std::string vhost, std::string app, std::string port, + std::string param ); /** diff --git a/trunk/src/srs/srs.upp b/trunk/src/srs/srs.upp index a759b5e10..2bb52dfba 100755 --- a/trunk/src/srs/srs.upp +++ b/trunk/src/srs/srs.upp @@ -7,6 +7,8 @@ file libs readonly separator, ..\libs\srs_librtmp.hpp, ..\libs\srs_librtmp.cpp, + ..\libs\srs_lib_bandwidth.hpp, + ..\libs\srs_lib_bandwidth.cpp, ..\libs\srs_lib_simple_socket.hpp, ..\libs\srs_lib_simple_socket.cpp, core readonly separator, @@ -121,6 +123,7 @@ file ..\utest\srs_utest_protocol.hpp, ..\utest\srs_utest_protocol.cpp, research readonly separator, + ..\..\research\librtmp\srs_bandwidth_check.c, ..\..\research\librtmp\srs_detect_rtmp.c, ..\..\research\librtmp\srs_flv_injecter.c, ..\..\research\librtmp\srs_flv_parser.c, diff --git a/trunk/src/utest/srs_utest_protocol.cpp b/trunk/src/utest/srs_utest_protocol.cpp index ba9421a38..a564864ee 100644 --- a/trunk/src/utest/srs_utest_protocol.cpp +++ b/trunk/src/utest/srs_utest_protocol.cpp @@ -429,27 +429,28 @@ VOID TEST(ProtocolUtilityTest, VhostResolve) { std::string vhost = "vhost"; std::string app = "app"; - srs_vhost_resolve(vhost, app); + std::string param; + srs_vhost_resolve(vhost, app, param); EXPECT_STREQ("vhost", vhost.c_str()); EXPECT_STREQ("app", app.c_str()); app = "app?vhost=changed"; - srs_vhost_resolve(vhost, app); + srs_vhost_resolve(vhost, app, param); EXPECT_STREQ("changed", vhost.c_str()); EXPECT_STREQ("app", app.c_str()); app = "app?vhost=changed1&&query=true"; - srs_vhost_resolve(vhost, app); + srs_vhost_resolve(vhost, app, param); EXPECT_STREQ("changed1", vhost.c_str()); EXPECT_STREQ("app", app.c_str()); app = "app?other=true&&vhost=changed2&&query=true"; - srs_vhost_resolve(vhost, app); + srs_vhost_resolve(vhost, app, param); EXPECT_STREQ("changed2", vhost.c_str()); EXPECT_STREQ("app", app.c_str()); app = "app...other...true...vhost...changed3...query...true"; - srs_vhost_resolve(vhost, app); + srs_vhost_resolve(vhost, app, param); EXPECT_STREQ("changed3", vhost.c_str()); EXPECT_STREQ("app", app.c_str()); } @@ -461,10 +462,10 @@ VOID TEST(ProtocolUtilityTest, DiscoveryTcUrl) { std::string tcUrl; std::string schema; std::string host; std::string vhost; - std::string app; std::string port; + std::string app; std::string port; std::string param; tcUrl = "rtmp://127.0.0.1:1935/live"; - srs_discovery_tc_url(tcUrl, schema, host, vhost, app, port); + srs_discovery_tc_url(tcUrl, schema, host, vhost, app, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("127.0.0.1", host.c_str()); EXPECT_STREQ("127.0.0.1", vhost.c_str()); @@ -472,7 +473,7 @@ VOID TEST(ProtocolUtilityTest, DiscoveryTcUrl) EXPECT_STREQ("1935", port.c_str()); tcUrl = "rtmp://127.0.0.1:19351/live"; - srs_discovery_tc_url(tcUrl, schema, host, vhost, app, port); + srs_discovery_tc_url(tcUrl, schema, host, vhost, app, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("127.0.0.1", host.c_str()); EXPECT_STREQ("127.0.0.1", vhost.c_str()); @@ -480,7 +481,7 @@ VOID TEST(ProtocolUtilityTest, DiscoveryTcUrl) EXPECT_STREQ("19351", port.c_str()); tcUrl = "rtmp://127.0.0.1:19351/live?vhost=demo"; - srs_discovery_tc_url(tcUrl, schema, host, vhost, app, port); + srs_discovery_tc_url(tcUrl, schema, host, vhost, app, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("127.0.0.1", host.c_str()); EXPECT_STREQ("demo", vhost.c_str()); @@ -488,7 +489,7 @@ VOID TEST(ProtocolUtilityTest, DiscoveryTcUrl) EXPECT_STREQ("19351", port.c_str()); tcUrl = "rtmp://127.0.0.1:19351/live/show?vhost=demo"; - srs_discovery_tc_url(tcUrl, schema, host, vhost, app, port); + srs_discovery_tc_url(tcUrl, schema, host, vhost, app, port, param); EXPECT_STREQ("rtmp", schema.c_str()); EXPECT_STREQ("127.0.0.1", host.c_str()); EXPECT_STREQ("demo", vhost.c_str()); @@ -501,18 +502,18 @@ VOID TEST(ProtocolUtilityTest, DiscoveryTcUrl) */ VOID TEST(ProtocolUtilityTest, GenerateTcUrl) { - string ip; string vhost; string app; string port; string tcUrl; + string ip; string vhost; string app; string port; string tcUrl; string param; ip = "127.0.0.1"; vhost = "__defaultVhost__"; app = "live"; port = "1935"; - tcUrl = srs_generate_tc_url(ip, vhost, app, port); + tcUrl = srs_generate_tc_url(ip, vhost, app, port, param); EXPECT_STREQ("rtmp://127.0.0.1/live", tcUrl.c_str()); ip = "127.0.0.1"; vhost = "demo"; app = "live"; port = "1935"; - tcUrl = srs_generate_tc_url(ip, vhost, app, port); + tcUrl = srs_generate_tc_url(ip, vhost, app, port, param); EXPECT_STREQ("rtmp://demo/live", tcUrl.c_str()); ip = "127.0.0.1"; vhost = "demo"; app = "live"; port = "19351"; - tcUrl = srs_generate_tc_url(ip, vhost, app, port); + tcUrl = srs_generate_tc_url(ip, vhost, app, port, param); EXPECT_STREQ("rtmp://demo:19351/live", tcUrl.c_str()); } @@ -5375,10 +5376,11 @@ VOID TEST(ProtocolStackTest, ProtocolExcpectMessage) VOID TEST(ProtocolRTMPTest, RTMPRequest) { SrsRequest req; + std::string param; req.stream = "livestream"; srs_discovery_tc_url("rtmp://std.ossrs.net/live", - req.schema, req.host, req.vhost, req.app, req.port); + req.schema, req.host, req.vhost, req.app, req.port, param); req.strip(); EXPECT_STREQ("rtmp", req.schema.c_str()); EXPECT_STREQ("std.ossrs.net", req.host.c_str()); @@ -5388,7 +5390,7 @@ VOID TEST(ProtocolRTMPTest, RTMPRequest) req.stream = "livestream"; srs_discovery_tc_url("rtmp://s td.os srs.n et/li v e", - req.schema, req.host, req.vhost, req.app, req.port); + req.schema, req.host, req.vhost, req.app, req.port, param); req.strip(); EXPECT_STREQ("rtmp", req.schema.c_str()); EXPECT_STREQ("std.ossrs.net", req.host.c_str()); @@ -5398,7 +5400,7 @@ VOID TEST(ProtocolRTMPTest, RTMPRequest) req.stream = "livestream"; srs_discovery_tc_url("rtmp://s\ntd.o\rssrs.ne\nt/li\nve", - req.schema, req.host, req.vhost, req.app, req.port); + req.schema, req.host, req.vhost, req.app, req.port, param); req.strip(); EXPECT_STREQ("rtmp", req.schema.c_str()); EXPECT_STREQ("std.ossrs.net", req.host.c_str()); @@ -5408,7 +5410,7 @@ VOID TEST(ProtocolRTMPTest, RTMPRequest) req.stream = "livestream"; srs_discovery_tc_url("rtmp://std.ossrs.net/live ", - req.schema, req.host, req.vhost, req.app, req.port); + req.schema, req.host, req.vhost, req.app, req.port, param); req.strip(); EXPECT_STREQ("rtmp", req.schema.c_str()); EXPECT_STREQ("std.ossrs.net", req.host.c_str());