winlin

merge from wenjie, the bandwidth test feature.

@@ -278,6 +278,7 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw @@ -278,6 +278,7 @@ usr sys idl wai hiq siq| read writ| recv send| in out | int csw
278 * nginx v1.5.0: 139524 lines <br/> 278 * nginx v1.5.0: 139524 lines <br/>
279 279
280 ### History 280 ### History
  281 +* v1.0, 2013-12-27, merge from wenjie, the bandwidth test feature.
281 * v0.9, 2013-12-25, [v0.9](https://github.com/winlinvip/simple-rtmp-server/releases/tag/0.9) released. 20926 lines. 282 * v0.9, 2013-12-25, [v0.9](https://github.com/winlinvip/simple-rtmp-server/releases/tag/0.9) released. 20926 lines.
282 * v0.9, 2013-12-25, fix the bitrate bug(in Bps), use enhanced microphone. 283 * v0.9, 2013-12-25, fix the bitrate bug(in Bps), use enhanced microphone.
283 * v0.9, 2013-12-22, demo video meeting or chat(srs+cherrypy+jquery+bootstrap). 284 * v0.9, 2013-12-22, demo video meeting or chat(srs+cherrypy+jquery+bootstrap).
@@ -223,7 +223,7 @@ vhost bandcheck.srs.com { @@ -223,7 +223,7 @@ vhost bandcheck.srs.com {
223 enabled on; 223 enabled on;
224 # the key for server to valid, 224 # the key for server to valid,
225 # if invalid key, server disconnect and abort the bandwidth check. 225 # if invalid key, server disconnect and abort the bandwidth check.
226 - key 35c9b402c12a7246868752e2878f7e0e; 226 + key "35c9b402c12a7246868752e2878f7e0e";
227 # the interval in seconds for bandwidth check, 227 # the interval in seconds for bandwidth check,
228 # server donot allow new test request. 228 # server donot allow new test request.
229 # default: 30 229 # default: 30
@@ -47,22 +47,27 @@ echo "" >> $SRS_AUTO_HEADERS_H @@ -47,22 +47,27 @@ echo "" >> $SRS_AUTO_HEADERS_H
47 echo "generate Makefile" 47 echo "generate Makefile"
48 48
49 cat << END > ${SRS_MAKEFILE} 49 cat << END > ${SRS_MAKEFILE}
50 -.PHONY: default help clean server _prepare_dir  
51 -default: server 50 +.PHONY: default help clean server bandwidth _prepare_dir
  51 +default: server bandwidth
52 52
53 help: 53 help:
54 - @echo "Usage: make <help>|<clean>|<server>" 54 + @echo "Usage: make <help>|<clean>|<server>|<bandwidth>"
55 @echo " help display this help menu" 55 @echo " help display this help menu"
56 @echo " clean cleanup project" 56 @echo " clean cleanup project"
57 @echo " server build the srs(simple rtmp server) over st(state-threads)" 57 @echo " server build the srs(simple rtmp server) over st(state-threads)"
  58 + @echo " bandwidth build the bandwidth test client tool."
58 59
59 clean: 60 clean:
60 - (rm -f Makefile; cd ${SRS_OBJS}; rm -rf srs Makefile *.hpp src st_*_load) 61 + (rm -f Makefile; cd ${SRS_OBJS}; rm -rf srs bandwidth Makefile *.hpp src st_*_load)
61 62
62 server: _prepare_dir 63 server: _prepare_dir
63 @echo "build the srs(simple rtmp server) over st(state-threads)" 64 @echo "build the srs(simple rtmp server) over st(state-threads)"
64 \$(MAKE) -f ${SRS_OBJS}/${SRS_MAKEFILE} srs 65 \$(MAKE) -f ${SRS_OBJS}/${SRS_MAKEFILE} srs
65 66
  67 +bandwidth: _prepare_dir
  68 + @echo "build the bandwidth test client tool"
  69 + \$(MAKE) -f ${SRS_OBJS}/${SRS_MAKEFILE} bandwidth
  70 +
66 # the ./configure will generate it. 71 # the ./configure will generate it.
67 _prepare_dir: 72 _prepare_dir:
68 @mkdir -p ${SRS_OBJS} 73 @mkdir -p ${SRS_OBJS}
@@ -87,7 +92,7 @@ GCC = g++ @@ -87,7 +92,7 @@ GCC = g++
87 LINK = \$(GCC) 92 LINK = \$(GCC)
88 AR = ar 93 AR = ar
89 94
90 -.PHONY: default srs 95 +.PHONY: default srs bandwidth
91 96
92 default: 97 default:
93 98
@@ -124,12 +129,12 @@ CORE_OBJS="${MODULE_OBJS[@]}" @@ -124,12 +129,12 @@ CORE_OBJS="${MODULE_OBJS[@]}"
124 MODULE_ID="MAIN" 129 MODULE_ID="MAIN"
125 MODULE_DEPENDS=("CORE") 130 MODULE_DEPENDS=("CORE")
126 ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS}) 131 ModuleLibIncs=(${LibSTRoot} ${SRS_OBJS})
127 -MODULE_FILES=("srs_main_server") 132 +MODULE_FILES=("srs_main_server" "srs_main_bandcheck")
128 MODULE_DIR="src/main" . auto/modules.sh 133 MODULE_DIR="src/main" . auto/modules.sh
129 MAIN_OBJS="${MODULE_OBJS[@].o}" 134 MAIN_OBJS="${MODULE_OBJS[@].o}"
130 135
131 # all main entrances 136 # all main entrances
132 -MAIN_ENTRANCES=("srs_main_server") 137 +MAIN_ENTRANCES=("srs_main_server" "srs_main_bandcheck")
133 138
134 # srs(simple rtmp server) over st(state-threads) 139 # srs(simple rtmp server) over st(state-threads)
135 ModuleLibFiles=(${LibSTfile}) 140 ModuleLibFiles=(${LibSTfile})
@@ -143,6 +148,7 @@ else @@ -143,6 +148,7 @@ else
143 LINK_OPTIONS="-ldl" 148 LINK_OPTIONS="-ldl"
144 fi 149 fi
145 BUILD_KEY="srs" APP_MAIN="srs_main_server" APP_NAME="srs" SO_PATH="" . auto/apps.sh 150 BUILD_KEY="srs" APP_MAIN="srs_main_server" APP_NAME="srs" SO_PATH="" . auto/apps.sh
  151 +BUILD_KEY="bandwidth" APP_MAIN="srs_main_bandcheck" APP_NAME="bandwidth" SO_PATH="" . auto/apps.sh
146 152
147 echo 'configure ok! ' 153 echo 'configure ok! '
148 154
  1 +// for bw to init url
  2 +// url: scheme://host:port/path?query#fragment
  3 +function srs_init_bwt(rtmp_url, hls_url) {
  4 + update_nav();
  5 +
  6 + if (rtmp_url) {
  7 + //var query = parse_query_string();
  8 + var search_filed = String(window.location.search).replace(" ", "").split("?")[1];
  9 + $(rtmp_url).val("rtmp://" + window.location.host + ":" + 1935 + "/app?" + search_filed);
  10 + }
  11 + if (hls_url) {
  12 + $(hls_url).val(build_default_hls_url());
  13 + }
  14 +}
  15 +
  16 +function srs_bwt_check_url(url) {
  17 + if (url.indexOf("key") != -1 && url.indexOf("vhost") != -1) {
  18 + return true;
  19 + }
  20 +
  21 + return false;
  22 +}
  23 +
  24 +function srs_bwt_build_default_url() {
  25 + var url_default = "rtmp://" + window.location.host + ":" + 1935 + "/app?key=35c9b402c12a7246868752e2878f7e0e&vhost=bandcheck.srs.com";
  26 + return url_default;
  27 +}
@@ -13,15 +13,112 @@ @@ -13,15 +13,112 @@
13 <script type="text/javascript" src="js/srs.publisher.js"></script> 13 <script type="text/javascript" src="js/srs.publisher.js"></script>
14 <script type="text/javascript" src="js/srs.utility.js"></script> 14 <script type="text/javascript" src="js/srs.utility.js"></script>
15 <script type="text/javascript" src="js/srs.utility.js"></script> 15 <script type="text/javascript" src="js/srs.utility.js"></script>
  16 + <script type="text/javascript" src="js/srs.bandwidth.js"></script>
16 <style> 17 <style>
17 body{ 18 body{
18 padding-top: 55px; 19 padding-top: 55px;
19 } 20 }
  21 + #main_modal {
  22 + width: 600px;
  23 + margin-left: -300px;
  24 + }
  25 + #check_status {
  26 + margin-left: 20px;
  27 + margin-top: -55px;
  28 + }
  29 + #pb_buffer_bg {
  30 + margin-top: 40px;
  31 + margin-bottom: 10px;
  32 + }
20 </style> 33 </style>
21 <script type="text/javascript"> 34 <script type="text/javascript">
  35 +
  36 + function update_progress(percent) {
  37 + $("#progress_bar").width(percent);
  38 + }
  39 +
  40 + function progress_reset() {
  41 + $("#progress_bar").width("0%");
  42 + }
  43 +
  44 + function update_status(text) {
  45 + $("#check_status").text(text);
  46 + }
  47 +
  48 + function get_swf_width() {
  49 + return 1;
  50 + }
  51 +
  52 + function get_swf_height() {
  53 + return 1;
  54 + }
  55 +
  56 + function show_modal() {
  57 + $("#main_modal").modal({show:true, keyboard:false});
  58 + }
  59 +
  60 + function band_check(url) {
  61 +
  62 + // remove flash contet
  63 + var bw_div = $("<div/>");
  64 + $(bw_div).attr("id", "bw_div");
  65 + $("#bw_center").append(bw_div);
  66 +
  67 + var flashvars = {};
  68 + flashvars.url = url;
  69 + flashvars.update_progress = "update_progress";
  70 + flashvars.progress_reset = "progress_reset";
  71 + flashvars.update_status = "update_status";
  72 +
  73 + var params = {};
  74 + params.allowFullScreen = true;
  75 +
  76 + var attributes = {};
  77 +
  78 + swfobject.embedSWF(
  79 + "srs_bwt/release/srs_bwt.swf", "bw_div",
  80 + get_swf_width(), get_swf_height(),
  81 + "11.1.0", "js/AdobeFlashPlayerInstall.swf",
  82 + flashvars, params, attributes
  83 + );
  84 + }
  85 +
22 $(function(){ 86 $(function(){
23 update_nav(); 87 update_nav();
24 - }); 88 + srs_init_bwt("#txt_url");
  89 +
  90 + var txt_input = $("#txt_url").val();
  91 + // if valid ?
  92 + if (!srs_bwt_check_url(txt_input)) {
  93 + $("#txt_url").val(srs_bwt_build_default_url());
  94 + }
  95 +
  96 + $("#main_modal").on(
  97 + "show",
  98 + function()
  99 + {
  100 + progress_reset();
  101 + update_status("");
  102 + var url = $("#txt_url").val();
  103 + /*!
  104 + url encode
  105 + */
  106 + url = escape(url);
  107 + band_check(url);
  108 + }
  109 + );
  110 +
  111 + $("#main_modal").on("hide", function(){
  112 + $("#bw_div").remove();
  113 + });
  114 +
  115 + $("#btn_play").click(
  116 + function()
  117 + {
  118 + $("#main_modal").modal({show:true, keyboard:false});
  119 + }
  120 + );
  121 + });
25 </script> 122 </script>
26 </head> 123 </head>
27 <body> 124 <body>
@@ -44,6 +141,34 @@ @@ -44,6 +141,34 @@
44 </div> 141 </div>
45 </div> 142 </div>
46 <div class="container"> 143 <div class="container">
  144 +
  145 + <div class="form-inline">
  146 + URL:
  147 + <input type="text" id="txt_url" class="input-xxlarge" value="" placeholder="例如:rtmp://host:port/app?key=xx&vhost=yy"></input>
  148 + <button class="btn btn-primary" id="btn_play">开始测速</button>
  149 + </div>
  150 +
  151 + <div id="main_modal" class="modal hide fade">
  152 + <div class="modal-header">
  153 + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  154 + <h3>SRS Band Check</h3>
  155 + </div>
  156 + <div class="modal-body">
  157 + <div id="player"></div>
  158 + <div class="progress progress-striped active" id="pb_buffer_bg">
  159 + <div class="bar" style="width: 50%;" id="progress_bar"></div>
  160 + </div>
  161 + </div>
  162 +
  163 + <div class="modal-body" id="bw_center">
  164 + </div>
  165 + <span id="check_status1"><font ><strong id="check_status">status</strong></font> </span>
  166 +
  167 + <div class="modal-footer">
  168 + <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true"> 关闭 </button>
  169 + </div>
  170 + </div>
  171 +
47 <hr> 172 <hr>
48 <footer> 173 <footer>
49 <p><a href="https://github.com/winlinvip/simple-rtmp-server">SRS Team &copy; 2013</a></p> 174 <p><a href="https://github.com/winlinvip/simple-rtmp-server">SRS Team &copy; 2013</a></p>
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<actionScriptProperties analytics="false" mainApplicationPath="srs_bwt.as" projectUUID="00251213-e6a2-4dd5-a033-125cc78f843c" version="10">
  3 + <compiler additionalCompilerArguments="-locale en_US" autoRSLOrdering="true" copyDependentFiles="true" fteInMXComponents="false" generateAccessible="true" htmlExpressInstall="true" htmlGenerate="true" htmlHistoryManagement="true" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="bin-debug" removeUnusedRSL="true" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" verifyDigests="true" warn="true">
  4 + <compilerSourcePath/>
  5 + <libraryPath defaultLinkType="0">
  6 + <libraryPathEntry kind="4" path="">
  7 + <excludedEntries>
  8 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_charts.swc" useDefaultLinkType="false"/>
  9 + <libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
  10 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/advancedgrids.swc" useDefaultLinkType="false"/>
  11 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp.swc" useDefaultLinkType="false"/>
  12 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_air.swc" useDefaultLinkType="false"/>
  13 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/charts.swc" useDefaultLinkType="false"/>
  14 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="false"/>
  15 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/mx/mx.swc" useDefaultLinkType="false"/>
  16 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/netmon.swc" useDefaultLinkType="false"/>
  17 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark.swc" useDefaultLinkType="false"/>
  18 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/sparkskins.swc" useDefaultLinkType="false"/>
  19 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="false"/>
  20 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/videoPlayer.swc" useDefaultLinkType="false"/>
  21 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp_air.swc" useDefaultLinkType="false"/>
  22 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
  23 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark_dmv.swc" useDefaultLinkType="false"/>
  24 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation.swc" useDefaultLinkType="false"/>
  25 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flash-integration.swc" useDefaultLinkType="false"/>
  26 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_dmv.swc" useDefaultLinkType="false"/>
  27 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_flashflexkit.swc" useDefaultLinkType="false"/>
  28 + <libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_agent.swc" useDefaultLinkType="false"/>
  29 + </excludedEntries>
  30 + </libraryPathEntry>
  31 + </libraryPath>
  32 + <sourceAttachmentPath/>
  33 + </compiler>
  34 + <applications>
  35 + <application path="srs_bwt.as"/>
  36 + </applications>
  37 + <modules/>
  38 + <buildCSSFiles/>
  39 + <flashCatalyst validateFlashCatalystCompatibility="false"/>
  40 +</actionScriptProperties>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<projectDescription>
  3 + <name>srs_bwt</name>
  4 + <comment></comment>
  5 + <projects>
  6 + </projects>
  7 + <buildSpec>
  8 + <buildCommand>
  9 + <name>com.adobe.flexbuilder.project.flexbuilder</name>
  10 + <arguments>
  11 + </arguments>
  12 + </buildCommand>
  13 + </buildSpec>
  14 + <natures>
  15 + <nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
  16 + </natures>
  17 +</projectDescription>
  1 +package SrsClass
  2 +{
  3 + import flash.system.System;
  4 +
  5 + public class SrsElapsedTimer
  6 + {
  7 + private var beginDate:Date;
  8 + public function SrsElapsedTimer()
  9 + {
  10 + beginDate = new Date;
  11 + }
  12 +
  13 + public function elapsed():Number{
  14 + var endDate:Date = new Date;
  15 +
  16 + // get deiff by ms
  17 + return (endDate.time - beginDate.time);
  18 + }
  19 +
  20 + public function restart():void{
  21 + beginDate = new Date;
  22 + }
  23 + }
  24 +}
  1 +package SrsClass
  2 +{
  3 + import flash.net.SharedObject;
  4 +
  5 + public class SrsSettings
  6 + {
  7 + private var settings:SharedObject;
  8 + private var key:String = "SrsBandCheck";
  9 +
  10 + public function SrsSettings()
  11 + {
  12 + settings = SharedObject.getLocal(key);
  13 + }
  14 +
  15 + public function addAddressText(val:String):void{
  16 + settings.data.address_text = val;
  17 + }
  18 +
  19 + public function addressText():String{
  20 + return settings.data.address_text;
  21 + }
  22 +
  23 + static public function instance():SrsSettings{
  24 + return new SrsSettings;
  25 + }
  26 + }
  27 +}
  1 +package
  2 +{
  3 + import SrsClass.SrsElapsedTimer;
  4 +
  5 + import flash.display.LoaderInfo;
  6 + import flash.display.Sprite;
  7 + import flash.display.StageAlign;
  8 + import flash.display.StageScaleMode;
  9 + import flash.events.Event;
  10 + import flash.events.NetStatusEvent;
  11 + import flash.events.TimerEvent;
  12 + import flash.external.ExternalInterface;
  13 + import flash.net.NetConnection;
  14 + import flash.net.ObjectEncoding;
  15 + import flash.system.System;
  16 + import flash.ui.ContextMenu;
  17 + import flash.ui.ContextMenuItem;
  18 + import flash.utils.Timer;
  19 + import flash.utils.setTimeout;
  20 +
  21 + public class srs_bwt extends Sprite
  22 + {
  23 + private var connection:NetConnection;
  24 +
  25 + private var updatePlayProgressTimer:Timer;
  26 + private var elapTimer:SrsElapsedTimer;
  27 +
  28 + // server ip get from server
  29 + private var server_ip:String;
  30 +
  31 + // test wheth publish should to stop
  32 + private var stop_pub:Boolean = false;
  33 +
  34 + // js interface
  35 + private var js_update_progress:String;
  36 + private var js_progress_reset:String;
  37 + private var js_update_status:String;
  38 +
  39 + private var value_progressbar:Number = 0;
  40 + private var max_progressbar:Number = 0;
  41 +
  42 + // set NetConnection ObjectEncoding to AMF0
  43 + NetConnection.defaultObjectEncoding = ObjectEncoding.AMF0;
  44 +
  45 + public function srs_bwt()
  46 + {
  47 + this.stage.scaleMode = StageScaleMode.NO_SCALE;
  48 + this.stage.align = StageAlign.TOP_LEFT;
  49 +
  50 + var flashvars:Object = this.root.loaderInfo.parameters;
  51 + this.js_update_progress = flashvars.update_progress;
  52 + this.js_progress_reset = flashvars.progress_reset;
  53 + this.js_update_status = flashvars.update_status;
  54 +
  55 + // init context menu, add action "Srs 带宽测试工具 0.1"
  56 + var myMenu:ContextMenu = new ContextMenu();
  57 + myMenu.hideBuiltInItems();
  58 + myMenu.customItems.push(new ContextMenuItem("Srs 带宽测试工具 0.1", true));
  59 + this.contextMenu = myMenu;
  60 +
  61 + // init connection
  62 + connection = new NetConnection;
  63 + connection.client = this;
  64 + connection.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
  65 + connection.connect(flashvars.url);
  66 + //connection.connect("rtmp://192.168.8.234:1935/app?key=35c9b402c12a7246868752e2878f7e0e&vhost=bandcheck.srs.com");
  67 +
  68 + // for play to update progress bar
  69 + elapTimer = new SrsElapsedTimer;
  70 +
  71 + // we suppose the check time = 7 S
  72 + updatePlayProgressTimer = new Timer(100);
  73 + updatePlayProgressTimer.addEventListener(TimerEvent.TIMER, onTimerTimeout);
  74 + updatePlayProgressTimer.start();
  75 + }
  76 +
  77 + // get NetConnection NetStatusEvent
  78 + public function onStatus(evt:NetStatusEvent) : void{
  79 + trace(evt.info.code);
  80 + switch(evt.info.code){
  81 + case "NetConnection.Connect.Failed":
  82 + updateState("连接服务器失败!");
  83 + break;
  84 + case "NetConnection.Connect.Rejected":
  85 + updateState("服务器拒绝连接!");
  86 + break;
  87 + case "NetConnection.Connect.Success":
  88 + server_ip = evt.info.data.srs_server_ip;
  89 + updateState("连接服务器成功!");
  90 + break;
  91 + case "NetConnection.Connect.Closed":
  92 + //updateState("连接已断开!");
  93 + break;
  94 + }
  95 +
  96 + }
  97 +
  98 + /**
  99 + * NetConnection callback this function, when recv server call "onSrsBandCheckStartPlayBytes"
  100 + * then start @updatePlayProgressTimer for updating the progressbar
  101 + * */
  102 + public function onSrsBandCheckStartPlayBytes(evt:Object):void{
  103 + var duration_ms:Number = evt.duration_ms;
  104 + var interval_ms:Number = evt.interval_ms;
  105 +
  106 + connection.call("onSrsBandCheckStartingPlayBytes", null);
  107 + updateState("测试下行带宽(" + server_ip + ")");
  108 +
  109 + // we suppose play duration_ms = pub duration_ms
  110 + max_progressbar = duration_ms * 2;
  111 + }
  112 +
  113 + public function onSrsBandCheckPlaying(evt:Object):void{
  114 +
  115 + }
  116 +
  117 + public function onTimerTimeout(evt:TimerEvent):void
  118 + {
  119 + value_progressbar = elapTimer.elapsed();
  120 + updateProgess(value_progressbar, max_progressbar);
  121 + }
  122 +
  123 + public function onSrsBandCheckStopPlayBytes(evt:Object):void{
  124 + var duration_ms:Number = evt.duration_ms;
  125 + var interval_ms:Number = evt.interval_ms;
  126 + var duration_delta:Number = evt.duration_delta;
  127 + var bytes_delta:Number = evt.bytes_delta;
  128 +
  129 + var kbps:Number = 0;
  130 + if(duration_delta > 0){
  131 + kbps = bytes_delta * 8.0 / duration_delta; // b/ms == kbps
  132 + }
  133 + kbps = (int(kbps * 10))/10.0;
  134 +
  135 + flash.utils.setTimeout(stopPlayTest, 0);
  136 + }
  137 +
  138 + private function stopPlayTest():void{
  139 + connection.call("onSrsBandCheckStoppedPlayBytes", null);
  140 + }
  141 +
  142 + public function onSrsBandCheckStartPublishBytes(evt:Object):void{
  143 + var duration_ms:Number = evt.duration_ms;
  144 + var interval_ms:Number = evt.interval_ms;
  145 +
  146 + connection.call("onSrsBandCheckStartingPublishBytes", null);
  147 + updateState("测试上行带宽(" + server_ip + ")");
  148 +
  149 + flash.utils.setTimeout(publisher, 0);
  150 + }
  151 +
  152 + private function publisher():void{
  153 + if (stop_pub) {
  154 + return;
  155 + }
  156 +
  157 + var data:Array = new Array();
  158 +
  159 + var data_size:int = 100;
  160 + for(var i:int; i < data_size; i++){
  161 + data.push("SrS band check data from client's publishing......");
  162 + }
  163 + data_size += 100;
  164 + connection.call("onSrsBandCheckPublishing", null, data);
  165 +
  166 + flash.utils.setTimeout(publisher, 0);
  167 + }
  168 +
  169 + public function onSrsBandCheckStopPublishBytes(evt:Object):void{
  170 + var duration_ms:Number = evt.duration_ms;
  171 + var interval_ms:Number = evt.interval_ms;
  172 + var duration_delta:Number = evt.duration_delta;
  173 + var bytes_delta:Number = evt.bytes_delta;
  174 +
  175 + var kbps:Number = 0;
  176 + if(duration_delta > 0){
  177 + kbps = bytes_delta * 8.0 / duration_delta; // b/ms == kbps
  178 + }
  179 + kbps = (int(kbps * 10))/10.0;
  180 +
  181 + stopPublishTest();
  182 + }
  183 +
  184 + private function stopPublishTest():void{
  185 + if(connection.connected){
  186 + connection.call("onSrsBandCheckStoppedPublishBytes", null);
  187 + }
  188 + stop_pub = true;
  189 +
  190 + value_progressbar = max_progressbar;
  191 + updateProgess(value_progressbar, max_progressbar);
  192 + updatePlayProgressTimer.stop();
  193 + }
  194 +
  195 + public function onSrsBandCheckFinished(evt:Object):void{
  196 + var code:Number = evt.code;
  197 + var start_time:Number = evt.start_time;
  198 + var end_time:Number = evt.end_time;
  199 + var play_kbps:Number = evt.play_kbps;
  200 + var publish_kbps:Number = evt.publish_kbps;
  201 + var play_bytes:Number = evt.play_bytes;
  202 + var play_time:Number = evt.play_time;
  203 + var publish_bytes:Number = evt.publish_bytes;
  204 + var publish_time:Number = evt.publish_time;
  205 +
  206 + updateState("检测结束: 服务器: " + server_ip + " 上行: " + publish_kbps + " kbps" + " 下行: " + play_kbps + " kbps"
  207 + + " 测试时间: " + (end_time-start_time)/1000 + " 秒");
  208 + connection.call("finalClientPacket", null);
  209 + }
  210 +
  211 + public function onBWDone():void{
  212 + // do nothing
  213 + }
  214 +
  215 + // update progressBar's value
  216 + private function updateProgess(value:Number, maxValue:Number):void{
  217 + flash.external.ExternalInterface.call(this.js_update_progress, value * 100 / maxValue + "%");
  218 + trace(value + "-" + maxValue + "-" + value * 100 / maxValue + "%");
  219 + }
  220 +
  221 + // update checking status
  222 + private function updateState(text:String):void{
  223 + flash.external.ExternalInterface.call(this.js_update_status, text);
  224 + trace(text);
  225 + }
  226 + }
  227 +}
@@ -24,6 +24,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -24,6 +24,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include <srs_core_bandwidth.hpp> 24 #include <srs_core_bandwidth.hpp>
25 25
26 #include <arpa/inet.h> 26 #include <arpa/inet.h>
  27 +#include <sstream>
27 28
28 using namespace std; 29 using namespace std;
29 30
@@ -260,21 +261,24 @@ int SrsBandwidth::check_play( @@ -260,21 +261,24 @@ int SrsBandwidth::check_play(
260 int64_t current_time = srs_get_system_time_ms(); 261 int64_t current_time = srs_get_system_time_ms();
261 int size = 1024; // TODO: FIXME: magic number 262 int size = 1024; // TODO: FIXME: magic number
262 char random_data[size]; 263 char random_data[size];
263 - memset(random_data, 0x01, size); 264 + memset(random_data, 'A', size);
264 265
265 int interval = 0; 266 int interval = 0;
  267 + int data_count = 1;
266 while ( (srs_get_system_time_ms() - current_time) < duration_ms ) { 268 while ( (srs_get_system_time_ms() - current_time) < duration_ms ) {
267 st_usleep(interval); 269 st_usleep(interval);
268 270
269 // TODO: FIXME: use shared ptr message. 271 // TODO: FIXME: use shared ptr message.
270 SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_playing(); 272 SrsBandwidthPacket* pkt = SrsBandwidthPacket::create_playing();
271 273
272 - // TODO: FIXME: magic number  
273 - for (int i = 0; i < 100; ++i) {  
274 - char buf[32]; // TODO: FIXME: magic number  
275 - sprintf(buf, "%d", i);  
276 - pkt->data->set(buf, new SrsAmf0String(random_data)); 274 + // TODO: FIXME: magic number
  275 + for (int i = 0; i < data_count; ++i) {
  276 + std::stringstream seq;
  277 + seq << i;
  278 + std::string play_data = "SrS band check data from server's playing......";
  279 + pkt->data->set(seq.str(), new SrsAmf0String(play_data.c_str()));
277 } 280 }
  281 + data_count += 2;
278 282
279 // TODO: FIXME: get length from the rtmp protocol stack. 283 // TODO: FIXME: get length from the rtmp protocol stack.
280 play_bytes += pkt->get_payload_length(); 284 play_bytes += pkt->get_payload_length();
@@ -2789,7 +2789,7 @@ SrsBandwidthPacket* SrsBandwidthPacket::create_start_play() @@ -2789,7 +2789,7 @@ SrsBandwidthPacket* SrsBandwidthPacket::create_start_play()
2789 SrsBandwidthPacket* SrsBandwidthPacket::create_playing() 2789 SrsBandwidthPacket* SrsBandwidthPacket::create_playing()
2790 { 2790 {
2791 SrsBandwidthPacket* pkt = new SrsBandwidthPacket(); 2791 SrsBandwidthPacket* pkt = new SrsBandwidthPacket();
2792 - return pkt->set_command(SRS_BW_CHECK_STARTING_PLAY); 2792 + return pkt->set_command(SRS_BW_CHECK_PLAYING);
2793 } 2793 }
2794 2794
2795 SrsBandwidthPacket* SrsBandwidthPacket::create_stop_play() 2795 SrsBandwidthPacket* SrsBandwidthPacket::create_stop_play()
1 -/*  
2 -The MIT License (MIT)  
3 -  
4 -Copyright (c) 2013 winlin  
5 -  
6 -Permission is hereby granted, free of charge, to any person obtaining a copy of  
7 -this software and associated documentation files (the "Software"), to deal in  
8 -the Software without restriction, including without limitation the rights to  
9 -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of  
10 -the Software, and to permit persons to whom the Software is furnished to do so,  
11 -subject to the following conditions:  
12 -  
13 -The above copyright notice and this permission notice shall be included in all  
14 -copies or substantial portions of the Software.  
15 -  
16 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS  
18 -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR  
19 -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER  
20 -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
21 -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
22 -*/  
23 -  
24 -#ifndef SRS_CORE_RTMP_HPP  
25 -#define SRS_CORE_RTMP_HPP  
26 -  
27 -/*  
28 -#include <srs_core_rtmp.hpp>  
29 -*/  
30 -  
31 -#include <srs_core.hpp>  
32 -  
33 -#include <string>  
34 -  
35 -class SrsProtocol;  
36 -class ISrsMessage;  
37 -class SrsCommonMessage;  
38 -class SrsCreateStreamPacket;  
39 -class SrsFMLEStartPacket;  
40 -class SrsPublishPacket;  
41 -class SrsSharedPtrMessage;  
42 -class SrsOnMetaDataPacket;  
43 -  
44 -/**  
45 -* the original request from client.  
46 -*/  
47 -struct SrsRequest  
48 -{  
49 - /**  
50 - * tcUrl: rtmp://request_vhost:port/app/stream  
51 - * support pass vhost in query string, such as:  
52 - * rtmp://ip:port/app?vhost=request_vhost/stream  
53 - * rtmp://ip:port/app...vhost...request_vhost/stream  
54 - */  
55 - std::string tcUrl;  
56 - std::string pageUrl;  
57 - std::string swfUrl;  
58 - double objectEncoding;  
59 -  
60 - std::string schema;  
61 - std::string vhost;  
62 - std::string port;  
63 - std::string app;  
64 - std::string stream;  
65 -  
66 - SrsRequest();  
67 - virtual ~SrsRequest();  
68 -  
69 - /**  
70 - * deep copy the request, for source to use it to support reload,  
71 - * for when initialize the source, the request is valid,  
72 - * when reload it, the request maybe invalid, so need to copy it.  
73 - */  
74 - virtual SrsRequest* copy();  
75 -  
76 - /**  
77 - * disconvery vhost/app from tcUrl.  
78 - */  
79 - virtual int discovery_app();  
80 - virtual std::string get_stream_url();  
81 - virtual void strip();  
82 -private:  
83 - std::string& trim(std::string& str, std::string chs);  
84 -};  
85 -  
86 -/**  
87 -* the response to client.  
88 -*/  
89 -struct SrsResponse  
90 -{  
91 - int stream_id;  
92 -  
93 - SrsResponse();  
94 - virtual ~SrsResponse();  
95 -};  
96 -  
97 -/**  
98 -* the rtmp client type.  
99 -*/  
100 -enum SrsClientType  
101 -{  
102 - SrsClientUnknown,  
103 - SrsClientPlay,  
104 - SrsClientFMLEPublish,  
105 - SrsClientFlashPublish,  
106 -};  
107 -  
108 -/**  
109 -* implements the client role protocol.  
110 -*/  
111 -class SrsRtmpClient  
112 -{  
113 -private:  
114 - SrsProtocol* protocol;  
115 - st_netfd_t stfd;  
116 -public:  
117 - SrsRtmpClient(st_netfd_t _stfd);  
118 - virtual ~SrsRtmpClient();  
119 -public:  
120 - virtual void set_recv_timeout(int64_t timeout_us);  
121 - virtual void set_send_timeout(int64_t timeout_us);  
122 - virtual int64_t get_recv_bytes();  
123 - virtual int64_t get_send_bytes();  
124 - virtual int get_recv_kbps();  
125 - virtual int get_send_kbps();  
126 - virtual int recv_message(SrsCommonMessage** pmsg);  
127 - virtual int send_message(ISrsMessage* msg);  
128 -public:  
129 - virtual int handshake();  
130 - virtual int connect_app(std::string app, std::string tc_url);  
131 - virtual int create_stream(int& stream_id);  
132 - virtual int play(std::string stream, int stream_id);  
133 - virtual int publish(std::string stream, int stream_id);  
134 -};  
135 -  
136 -/**  
137 -* the rtmp provices rtmp-command-protocol services,  
138 -* a high level protocol, media stream oriented services,  
139 -* such as connect to vhost/app, play stream, get audio/video data.  
140 -*/  
141 -class SrsRtmp  
142 -{  
143 -private:  
144 - SrsProtocol* protocol;  
145 - st_netfd_t stfd;  
146 -public:  
147 - SrsRtmp(st_netfd_t client_stfd);  
148 - virtual ~SrsRtmp();  
149 -public:  
150 - virtual SrsProtocol* get_protocol();  
151 - virtual void set_recv_timeout(int64_t timeout_us);  
152 - virtual int64_t get_recv_timeout();  
153 - virtual void set_send_timeout(int64_t timeout_us);  
154 - virtual int64_t get_send_timeout();  
155 - virtual int64_t get_recv_bytes();  
156 - virtual int64_t get_send_bytes();  
157 - virtual int get_recv_kbps();  
158 - virtual int get_send_kbps();  
159 - virtual int recv_message(SrsCommonMessage** pmsg);  
160 - virtual int send_message(ISrsMessage* msg);  
161 -public:  
162 - virtual int handshake();  
163 - virtual int connect_app(SrsRequest* req);  
164 - virtual int set_window_ack_size(int ack_size);  
165 - /**  
166 - * @type: The sender can mark this message hard (0), soft (1), or dynamic (2)  
167 - * using the Limit type field.  
168 - */  
169 - virtual int set_peer_bandwidth(int bandwidth, int type);  
170 - /**  
171 - * @param server_ip the ip of server.  
172 - */  
173 - virtual int response_connect_app(SrsRequest* req, const char* server_ip = NULL);  
174 - virtual void response_connect_reject(SrsRequest* req, const char* desc);  
175 - virtual int on_bw_done();  
176 - /**  
177 - * recv some message to identify the client.  
178 - * @stream_id, client will createStream to play or publish by flash,  
179 - * the stream_id used to response the createStream request.  
180 - * @type, output the client type.  
181 - */  
182 - virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name);  
183 - /**  
184 - * set the chunk size when client type identified.  
185 - */  
186 - virtual int set_chunk_size(int chunk_size);  
187 - /**  
188 - * when client type is play, response with packets:  
189 - * StreamBegin,  
190 - * onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start).,  
191 - * |RtmpSampleAccess(false, false),  
192 - * onStatus(NetStream.Data.Start).  
193 - */  
194 - virtual int start_play(int stream_id);  
195 - /**  
196 - * when client(type is play) send pause message,  
197 - * if is_pause, response the following packets:  
198 - * onStatus(NetStream.Pause.Notify)  
199 - * StreamEOF  
200 - * if not is_pause, response the following packets:  
201 - * onStatus(NetStream.Unpause.Notify)  
202 - * StreamBegin  
203 - */  
204 - virtual int on_play_client_pause(int stream_id, bool is_pause);  
205 - /**  
206 - * when client type is publish, response with packets:  
207 - * releaseStream response  
208 - * FCPublish  
209 - * FCPublish response  
210 - * createStream response  
211 - * onFCPublish(NetStream.Publish.Start)  
212 - * onStatus(NetStream.Publish.Start)  
213 - */  
214 - virtual int start_fmle_publish(int stream_id);  
215 - /**  
216 - * process the FMLE unpublish event.  
217 - * @unpublish_tid the unpublish request transaction id.  
218 - */  
219 - virtual int fmle_unpublish(int stream_id, double unpublish_tid);  
220 - /**  
221 - * when client type is publish, response with packets:  
222 - * onStatus(NetStream.Publish.Start)  
223 - */  
224 - virtual int start_flash_publish(int stream_id);  
225 -private:  
226 - virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name);  
227 - virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name);  
228 - virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name);  
229 -};  
230 - 1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_CORE_RTMP_HPP
  25 +#define SRS_CORE_RTMP_HPP
  26 +
  27 +/*
  28 +#include <srs_core_rtmp.hpp>
  29 +*/
  30 +
  31 +#include <srs_core.hpp>
  32 +
  33 +#include <string>
  34 +
  35 +class SrsProtocol;
  36 +class ISrsMessage;
  37 +class SrsCommonMessage;
  38 +class SrsCreateStreamPacket;
  39 +class SrsFMLEStartPacket;
  40 +class SrsPublishPacket;
  41 +class SrsSharedPtrMessage;
  42 +class SrsOnMetaDataPacket;
  43 +
  44 +/**
  45 +* the original request from client.
  46 +*/
  47 +struct SrsRequest
  48 +{
  49 + /**
  50 + * tcUrl: rtmp://request_vhost:port/app/stream
  51 + * support pass vhost in query string, such as:
  52 + * rtmp://ip:port/app?vhost=request_vhost/stream
  53 + * rtmp://ip:port/app...vhost...request_vhost/stream
  54 + */
  55 + std::string tcUrl;
  56 + std::string pageUrl;
  57 + std::string swfUrl;
  58 + double objectEncoding;
  59 +
  60 + std::string schema;
  61 + std::string vhost;
  62 + std::string port;
  63 + std::string app;
  64 + std::string stream;
  65 +
  66 + SrsRequest();
  67 + virtual ~SrsRequest();
  68 +
  69 + /**
  70 + * deep copy the request, for source to use it to support reload,
  71 + * for when initialize the source, the request is valid,
  72 + * when reload it, the request maybe invalid, so need to copy it.
  73 + */
  74 + virtual SrsRequest* copy();
  75 +
  76 + /**
  77 + * disconvery vhost/app from tcUrl.
  78 + */
  79 + virtual int discovery_app();
  80 + virtual std::string get_stream_url();
  81 + virtual void strip();
  82 +private:
  83 + std::string& trim(std::string& str, std::string chs);
  84 +};
  85 +
  86 +/**
  87 +* the response to client.
  88 +*/
  89 +struct SrsResponse
  90 +{
  91 + int stream_id;
  92 +
  93 + SrsResponse();
  94 + virtual ~SrsResponse();
  95 +};
  96 +
  97 +/**
  98 +* the rtmp client type.
  99 +*/
  100 +enum SrsClientType
  101 +{
  102 + SrsClientUnknown,
  103 + SrsClientPlay,
  104 + SrsClientFMLEPublish,
  105 + SrsClientFlashPublish,
  106 +};
  107 +
  108 +/**
  109 +* implements the client role protocol.
  110 +*/
  111 +class SrsRtmpClient
  112 +{
  113 +protected:
  114 + SrsProtocol* protocol;
  115 + st_netfd_t stfd;
  116 +public:
  117 + SrsRtmpClient(st_netfd_t _stfd);
  118 + virtual ~SrsRtmpClient();
  119 +public:
  120 + virtual void set_recv_timeout(int64_t timeout_us);
  121 + virtual void set_send_timeout(int64_t timeout_us);
  122 + virtual int64_t get_recv_bytes();
  123 + virtual int64_t get_send_bytes();
  124 + virtual int get_recv_kbps();
  125 + virtual int get_send_kbps();
  126 + virtual int recv_message(SrsCommonMessage** pmsg);
  127 + virtual int send_message(ISrsMessage* msg);
  128 +public:
  129 + virtual int handshake();
  130 + virtual int connect_app(std::string app, std::string tc_url);
  131 + virtual int create_stream(int& stream_id);
  132 + virtual int play(std::string stream, int stream_id);
  133 + virtual int publish(std::string stream, int stream_id);
  134 +};
  135 +
  136 +/**
  137 +* the rtmp provices rtmp-command-protocol services,
  138 +* a high level protocol, media stream oriented services,
  139 +* such as connect to vhost/app, play stream, get audio/video data.
  140 +*/
  141 +class SrsRtmp
  142 +{
  143 +private:
  144 + SrsProtocol* protocol;
  145 + st_netfd_t stfd;
  146 +public:
  147 + SrsRtmp(st_netfd_t client_stfd);
  148 + virtual ~SrsRtmp();
  149 +public:
  150 + virtual SrsProtocol* get_protocol();
  151 + virtual void set_recv_timeout(int64_t timeout_us);
  152 + virtual int64_t get_recv_timeout();
  153 + virtual void set_send_timeout(int64_t timeout_us);
  154 + virtual int64_t get_send_timeout();
  155 + virtual int64_t get_recv_bytes();
  156 + virtual int64_t get_send_bytes();
  157 + virtual int get_recv_kbps();
  158 + virtual int get_send_kbps();
  159 + virtual int recv_message(SrsCommonMessage** pmsg);
  160 + virtual int send_message(ISrsMessage* msg);
  161 +public:
  162 + virtual int handshake();
  163 + virtual int connect_app(SrsRequest* req);
  164 + virtual int set_window_ack_size(int ack_size);
  165 + /**
  166 + * @type: The sender can mark this message hard (0), soft (1), or dynamic (2)
  167 + * using the Limit type field.
  168 + */
  169 + virtual int set_peer_bandwidth(int bandwidth, int type);
  170 + /**
  171 + * @param server_ip the ip of server.
  172 + */
  173 + virtual int response_connect_app(SrsRequest* req, const char* server_ip = NULL);
  174 + virtual void response_connect_reject(SrsRequest* req, const char* desc);
  175 + virtual int on_bw_done();
  176 + /**
  177 + * recv some message to identify the client.
  178 + * @stream_id, client will createStream to play or publish by flash,
  179 + * the stream_id used to response the createStream request.
  180 + * @type, output the client type.
  181 + */
  182 + virtual int identify_client(int stream_id, SrsClientType& type, std::string& stream_name);
  183 + /**
  184 + * set the chunk size when client type identified.
  185 + */
  186 + virtual int set_chunk_size(int chunk_size);
  187 + /**
  188 + * when client type is play, response with packets:
  189 + * StreamBegin,
  190 + * onStatus(NetStream.Play.Reset), onStatus(NetStream.Play.Start).,
  191 + * |RtmpSampleAccess(false, false),
  192 + * onStatus(NetStream.Data.Start).
  193 + */
  194 + virtual int start_play(int stream_id);
  195 + /**
  196 + * when client(type is play) send pause message,
  197 + * if is_pause, response the following packets:
  198 + * onStatus(NetStream.Pause.Notify)
  199 + * StreamEOF
  200 + * if not is_pause, response the following packets:
  201 + * onStatus(NetStream.Unpause.Notify)
  202 + * StreamBegin
  203 + */
  204 + virtual int on_play_client_pause(int stream_id, bool is_pause);
  205 + /**
  206 + * when client type is publish, response with packets:
  207 + * releaseStream response
  208 + * FCPublish
  209 + * FCPublish response
  210 + * createStream response
  211 + * onFCPublish(NetStream.Publish.Start)
  212 + * onStatus(NetStream.Publish.Start)
  213 + */
  214 + virtual int start_fmle_publish(int stream_id);
  215 + /**
  216 + * process the FMLE unpublish event.
  217 + * @unpublish_tid the unpublish request transaction id.
  218 + */
  219 + virtual int fmle_unpublish(int stream_id, double unpublish_tid);
  220 + /**
  221 + * when client type is publish, response with packets:
  222 + * onStatus(NetStream.Publish.Start)
  223 + */
  224 + virtual int start_flash_publish(int stream_id);
  225 +private:
  226 + virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name);
  227 + virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name);
  228 + virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name);
  229 +};
  230 +
231 #endif 231 #endif
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013 wenjiegit
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <sys/socket.h>
  25 +#include <netinet/in.h>
  26 +#include <arpa/inet.h>
  27 +#include <sstream>
  28 +#include <getopt.h>
  29 +#include <stdlib.h>
  30 +
  31 +#include <srs_core_rtmp.hpp>
  32 +#include <srs_core_protocol.hpp>
  33 +#include <srs_core_error.hpp>
  34 +#include <srs_core_amf0.hpp>
  35 +#include <srs_core_autofree.hpp>
  36 +#include <srs_core_stream.hpp>
  37 +
  38 +#include <st.h>
  39 +
  40 +// server play control
  41 +#define SRS_BW_CHECK_START_PLAY "onSrsBandCheckStartPlayBytes"
  42 +#define SRS_BW_CHECK_STARTING_PLAY "onSrsBandCheckStartingPlayBytes"
  43 +#define SRS_BW_CHECK_STOP_PLAY "onSrsBandCheckStopPlayBytes"
  44 +#define SRS_BW_CHECK_STOPPED_PLAY "onSrsBandCheckStoppedPlayBytes"
  45 +
  46 +// server publish control
  47 +#define SRS_BW_CHECK_START_PUBLISH "onSrsBandCheckStartPublishBytes"
  48 +#define SRS_BW_CHECK_STARTING_PUBLISH "onSrsBandCheckStartingPublishBytes"
  49 +#define SRS_BW_CHECK_STOP_PUBLISH "onSrsBandCheckStopPublishBytes"
  50 +#define SRS_BW_CHECK_STOPPED_PUBLISH "onSrsBandCheckStoppedPublishBytes"
  51 +
  52 +// EOF control.
  53 +#define SRS_BW_CHECK_FINISHED "onSrsBandCheckFinished"
  54 +#define SRS_BW_CHECK_FLASH_FINAL "finalClientPacket"
  55 +
  56 +// client only
  57 +#define SRS_BW_CHECK_PLAYING "onSrsBandCheckPlaying"
  58 +#define SRS_BW_CHECK_PUBLISHING "onSrsBandCheckPublishing"
  59 +
  60 +/**
  61 +* @brief class of Linux version band check client
  62 +* check play and publish speed.
  63 +*/
  64 +class SrsBandCheckClient : public SrsRtmpClient
  65 +{
  66 +public:
  67 + SrsBandCheckClient(st_netfd_t _stfd);
  68 + ~SrsBandCheckClient();
  69 +
  70 +public:
  71 + /**
  72 + * @brief test play
  73 + *
  74 + */
  75 + int check_play();
  76 + /**
  77 + * @brief test publish
  78 + *
  79 + */
  80 + int check_publish();
  81 +
  82 +private:
  83 + /**
  84 + * @brief just return success.
  85 + */
  86 + int create_stream(int& stream_id);
  87 + /**
  88 + * @brief just return success.
  89 + */
  90 + int play(std::string stream, int stream_id);
  91 + /**
  92 + * @brief just return success.
  93 + */
  94 + int publish(std::string stream, int stream_id);
  95 +
  96 +private:
  97 + int expect_start_play();
  98 + int send_starting_play();
  99 + int expect_stop_play();
  100 + int send_stopped_play();
  101 + int expect_start_pub();
  102 + int send_starting_pub();
  103 + int send_pub_data();
  104 + int expect_stop_pub();
  105 + /**
  106 + * @brief expect result.
  107 + * because the core module has no method to decode this packet
  108 + * so we must get the internal data and decode it here.
  109 + */
  110 + int expect_finished();
  111 + int send_stopped_pub();
  112 + /**
  113 + * @brief notify server the check procedure is over.
  114 + */
  115 + int send_final();
  116 +};
  117 +
  118 +/**
  119 +* @brief class of band check
  120 +* used to check band width with a client @param bandCheck_Client
  121 +*/
  122 +class SrsBandCheck
  123 +{
  124 +public:
  125 + SrsBandCheck();
  126 + ~SrsBandCheck();
  127 +
  128 +public:
  129 + /**
  130 + * @brief band check method
  131 + *
  132 + * connect to server------>rtmp handshake------>rtmp connect------>play------>publish
  133 + * @retval ERROR_SUCCESS when success.
  134 + */
  135 + int check(const std::string& app, const std::string& tcUrl);
  136 +
  137 + /**
  138 + * @brief set the address and port of test server
  139 + *
  140 + * @param server server address, domain or ip
  141 + * @param server listened port ,default is 1935
  142 + */
  143 + void set_server(const std::string& server, int port = 1935);
  144 +
  145 +private:
  146 + int connect_server();
  147 +
  148 +private:
  149 + SrsBandCheckClient* bandCheck_Client;
  150 + std::string server_address;
  151 + int server_port;
  152 +};
  153 +
  154 +/**
  155 +* @brief init st lib
  156 +*/
  157 +static int init_st();
  158 +static void print_help(char** argv);
  159 +static void print_version();
  160 +
  161 +/**
  162 +* @brief get user option
  163 +* @internal ip Mandatory arguments
  164 +* @internal key Mandatory arguments
  165 +* @internal port default 1935
  166 +* @internal vhost default bandcheck.srs.com
  167 +*/
  168 +static int get_opt(int argc ,char* argv[]);
  169 +
  170 +/**
  171 +* global var.
  172 +*/
  173 +static struct option long_options[] =
  174 +{
  175 + {"ip", required_argument, 0, 'i'},
  176 + {"port", optional_argument, 0, 'p'},
  177 + {"key", required_argument, 0, 'k'},
  178 + {"vhost", optional_argument, 0, 'v'},
  179 + {"help", no_argument, 0, 'h'},
  180 + {"version", no_argument, 0, 'V'},
  181 +};
  182 +
  183 +static const char* short_options = "i:p::k:v::hV";
  184 +
  185 +static std::string g_ip;
  186 +static int g_port = 1935;
  187 +static std::string g_key;
  188 +static std::string g_vhost = "bandcheck.srs.com";
  189 +
  190 +#define BUILD_VERSION "srs band check 0.1"
  191 +
  192 +int main(int argc ,char* argv[])
  193 +{
  194 + int ret = ERROR_SUCCESS;
  195 +
  196 + if (argc <= 1) {
  197 + print_help(argv);
  198 + exit(1);
  199 + }
  200 +
  201 + if ((ret = get_opt(argc, argv)) != ERROR_SUCCESS) {
  202 + return -1;
  203 + }
  204 +
  205 + // check param
  206 + if (g_ip.empty()) {
  207 + printf("ip address should not be empty.\n");
  208 + return -1;
  209 + }
  210 +
  211 + if (g_key.empty()) {
  212 + printf("test key should not be empty.\n");
  213 + return -1;
  214 + }
  215 +
  216 + if ((ret = init_st()) != ERROR_SUCCESS) {
  217 + srs_error("band check init failed. ret=%d", ret);
  218 + return ret;
  219 + }
  220 +
  221 + std::string app = "app?key=" + g_key + "&vhost=" + g_vhost;
  222 +
  223 + char tcUrl_buffer[1024] = {0};
  224 + sprintf(tcUrl_buffer, "rtmp://%s:%d/%s", g_ip.c_str(), g_port, app.c_str());
  225 + std::string tcUrl = tcUrl_buffer;
  226 +
  227 + SrsBandCheck band_check;
  228 + band_check.set_server(g_ip, g_port);
  229 + if ((ret = band_check.check(app, tcUrl)) != ERROR_SUCCESS) {
  230 + srs_error("band check failed. address=%s ret=%d", "xx.com", ret);
  231 + return -1;
  232 + }
  233 +
  234 + return 0;
  235 +}
  236 +
  237 +SrsBandCheckClient::SrsBandCheckClient(st_netfd_t _stfd)
  238 + : SrsRtmpClient(_stfd)
  239 +{
  240 +}
  241 +
  242 +SrsBandCheckClient::~SrsBandCheckClient()
  243 +{
  244 +}
  245 +
  246 +int SrsBandCheckClient::check_play()
  247 +{
  248 + int ret = ERROR_SUCCESS;
  249 +
  250 + if ((ret = expect_start_play()) != ERROR_SUCCESS) {
  251 + srs_error("expect_start_play failed. ret=%d", ret);
  252 + return ret;
  253 + }
  254 +
  255 + if ((ret = send_starting_play()) != ERROR_SUCCESS) {
  256 + srs_error("send starting play failed. ret=%d", ret);
  257 + return ret;
  258 + }
  259 +
  260 + if ((ret = expect_stop_play()) != ERROR_SUCCESS) {
  261 + srs_error("expect stop play failed. ret=%d", ret);
  262 + return ret;
  263 + }
  264 +
  265 + if ((ret = send_stopped_play()) != ERROR_SUCCESS) {
  266 + srs_error("send stopped play failed. ret=%d", ret);
  267 + return ret;
  268 + }
  269 +
  270 + return ret;
  271 +}
  272 +
  273 +int SrsBandCheckClient::check_publish()
  274 +{
  275 + int ret = ERROR_SUCCESS;
  276 +
  277 + if ((ret = expect_start_pub()) != ERROR_SUCCESS) {
  278 + srs_error("expect start pub failed. ret=%d", ret);
  279 + return ret;
  280 + }
  281 +
  282 + if ((ret = send_starting_pub())!= ERROR_SUCCESS) {
  283 + srs_error("send starting pub failed. ret=%d", ret);
  284 + return ret;
  285 + }
  286 +
  287 + if ((ret = send_pub_data()) != ERROR_SUCCESS) {
  288 + srs_error("publish data failed. ret=%d", ret);
  289 + return ret;
  290 + }
  291 +
  292 + if ((ret = send_stopped_pub()) != ERROR_SUCCESS) {
  293 + srs_error("send stopped pub failed. ret=%d", ret);
  294 + return ret;
  295 + }
  296 +
  297 + if ((ret = expect_finished()) != ERROR_SUCCESS) {
  298 + srs_error("expect finished msg failed. ret=%d", ret);
  299 + return ret;
  300 + }
  301 +
  302 + if ((ret = send_final()) != ERROR_SUCCESS) {
  303 + srs_error("send final msg failed. ret=%d", ret);
  304 + return ret;
  305 + }
  306 +
  307 + return ret;
  308 +}
  309 +
  310 +int SrsBandCheckClient::create_stream(int &stream_id)
  311 +{
  312 + return ERROR_SUCCESS;
  313 +}
  314 +
  315 +int SrsBandCheckClient::play(std::string stream, int stream_id)
  316 +{
  317 + return ERROR_SUCCESS;
  318 +}
  319 +
  320 +int SrsBandCheckClient::publish(std::string stream, int stream_id)
  321 +{
  322 + return ERROR_SUCCESS;
  323 +}
  324 +
  325 +int SrsBandCheckClient::expect_start_play()
  326 +{
  327 + int ret = ERROR_SUCCESS;
  328 +
  329 + // expect connect _result
  330 + SrsCommonMessage* msg = NULL;
  331 + SrsBandwidthPacket* pkt = NULL;
  332 + if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
  333 + srs_error("expect bandcheck start play message failed. ret=%d", ret);
  334 + return ret;
  335 + }
  336 + SrsAutoFree(SrsCommonMessage, msg, false);
  337 + srs_info("get bandcheck start play message");
  338 +
  339 + if (pkt->command_name != SRS_BW_CHECK_START_PLAY) {
  340 + srs_error("pkt error. expect=%s, actual=%s", SRS_BW_CHECK_START_PLAY, pkt->command_name.c_str());
  341 + return -1;
  342 + }
  343 +
  344 + return ret;
  345 +}
  346 +
  347 +int SrsBandCheckClient::send_starting_play()
  348 +{
  349 + int ret = ERROR_SUCCESS;
  350 +
  351 + SrsCommonMessage* msg = new SrsCommonMessage;
  352 + SrsBandwidthPacket* pkt = new SrsBandwidthPacket;
  353 + pkt->command_name = SRS_BW_CHECK_STARTING_PLAY;
  354 + msg->set_packet(pkt, 0);
  355 +
  356 + if ((ret = send_message(msg)) != ERROR_SUCCESS) {
  357 + srs_error("send starting play msg failed. ret=%d", ret);
  358 + return ret;
  359 + }
  360 +
  361 + return ret;
  362 +}
  363 +
  364 +int SrsBandCheckClient::expect_stop_play()
  365 +{
  366 + int ret = ERROR_SUCCESS;
  367 +
  368 + while (true) {
  369 + SrsCommonMessage* msg = NULL;
  370 + SrsBandwidthPacket* pkt = NULL;
  371 + if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
  372 + srs_error("expect stop play message failed. ret=%d", ret);
  373 + return ret;
  374 + }
  375 + SrsAutoFree(SrsCommonMessage, msg, false);
  376 + srs_info("get bandcheck stop play message");
  377 +
  378 + if (pkt->command_name == SRS_BW_CHECK_STOP_PLAY) {
  379 + break;
  380 + }
  381 + }
  382 +
  383 + return ret;
  384 +}
  385 +
  386 +int SrsBandCheckClient::send_stopped_play()
  387 +{
  388 + int ret = ERROR_SUCCESS;
  389 +
  390 + SrsCommonMessage* msg = new SrsCommonMessage;
  391 + SrsBandwidthPacket* pkt = new SrsBandwidthPacket;
  392 + pkt->command_name = SRS_BW_CHECK_STOPPED_PLAY;
  393 + msg->set_packet(pkt, 0);
  394 +
  395 + if ((ret = send_message(msg)) != ERROR_SUCCESS) {
  396 + srs_error("send stopped play msg failed. ret=%d", ret);
  397 + return ret;
  398 + }
  399 +
  400 + return ret;
  401 +}
  402 +
  403 +int SrsBandCheckClient::expect_start_pub()
  404 +{
  405 + int ret = ERROR_SUCCESS;
  406 +
  407 + while (true) {
  408 + SrsCommonMessage* msg = NULL;
  409 + SrsBandwidthPacket* pkt = NULL;
  410 + if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
  411 + srs_error("expect start pub message failed. ret=%d", ret);
  412 + return ret;
  413 + }
  414 + SrsAutoFree(SrsCommonMessage, msg, false);
  415 + srs_info("get bandcheck start pub message");
  416 +
  417 + if (pkt->command_name == SRS_BW_CHECK_START_PUBLISH) {
  418 + break;
  419 + }
  420 + }
  421 +
  422 + return ret;
  423 +}
  424 +
  425 +int SrsBandCheckClient::send_starting_pub()
  426 +{
  427 + int ret = ERROR_SUCCESS;
  428 +
  429 + SrsCommonMessage* msg = new SrsCommonMessage;
  430 + SrsBandwidthPacket* pkt = new SrsBandwidthPacket;
  431 + pkt->command_name = SRS_BW_CHECK_STARTING_PUBLISH;
  432 + msg->set_packet(pkt, 0);
  433 +
  434 + if ((ret = send_message(msg)) != ERROR_SUCCESS) {
  435 + srs_error("send starting play msg failed. ret=%d", ret);
  436 + return ret;
  437 + }
  438 + srs_info("send starting play msg success.");
  439 +
  440 + return ret;
  441 +}
  442 +
  443 +int SrsBandCheckClient::send_pub_data()
  444 +{
  445 + int ret = ERROR_SUCCESS;
  446 +
  447 + int data_count = 100;
  448 + while (true) {
  449 + SrsCommonMessage* msg = new SrsCommonMessage;
  450 + SrsBandwidthPacket* pkt = new SrsBandwidthPacket;
  451 + pkt->command_name = SRS_BW_CHECK_PUBLISHING;
  452 + msg->set_packet(pkt, 0);
  453 +
  454 + for (int i = 0; i < data_count; ++i) {
  455 + std::stringstream seq;
  456 + seq << i;
  457 + std::string play_data = "SrS band check data from client's publishing......";
  458 + pkt->data->set(seq.str(), new SrsAmf0String(play_data.c_str()));
  459 + }
  460 + data_count += 100;
  461 +
  462 + if ((ret = send_message(msg)) != ERROR_SUCCESS) {
  463 + srs_error("send publish message failed.ret=%d", ret);
  464 + return ret;
  465 + }
  466 +
  467 + if ((ret = expect_stop_pub()) == ERROR_SUCCESS) {
  468 + break;
  469 + }
  470 + }
  471 +
  472 + return ret;
  473 +}
  474 +
  475 +int SrsBandCheckClient::expect_stop_pub()
  476 +{
  477 + int ret = ERROR_SUCCESS;
  478 +
  479 + while (true) {
  480 + if ((ret = st_netfd_poll(stfd, POLLIN, 1000)) == ERROR_SUCCESS) {
  481 + SrsCommonMessage* msg = 0;
  482 + if ((ret = recv_message(&msg)) != ERROR_SUCCESS)
  483 + {
  484 + srs_error("recv message failed while expect stop pub. ret=%d", ret);
  485 + return ret;
  486 + }
  487 +
  488 + if ((ret = msg->decode_packet(protocol)) != ERROR_SUCCESS) {
  489 + srs_error("decode packet error while expect stop pub. ret=%d", ret);
  490 + return ret;
  491 + }
  492 +
  493 + SrsBandwidthPacket* pkt = dynamic_cast<SrsBandwidthPacket*>(msg->get_packet());
  494 + if (pkt && pkt->command_name == SRS_BW_CHECK_STOP_PUBLISH) {
  495 +
  496 + return ret;
  497 + }
  498 + } else {
  499 + break;
  500 + }
  501 + }
  502 +
  503 + return ret;
  504 +}
  505 +
  506 +int SrsBandCheckClient::expect_finished()
  507 +{
  508 + int ret = ERROR_SUCCESS;
  509 +
  510 + while (true) {
  511 + SrsCommonMessage* msg = NULL;
  512 + SrsBandwidthPacket* pkt = NULL;
  513 + if ((ret = srs_rtmp_expect_message<SrsBandwidthPacket>(protocol, &msg, &pkt)) != ERROR_SUCCESS) {
  514 + srs_error("expect finished message failed. ret=%d", ret);
  515 + return ret;
  516 + }
  517 + SrsAutoFree(SrsCommonMessage, msg, false);
  518 + srs_info("get bandcheck finished message");
  519 +
  520 + if (pkt->command_name == SRS_BW_CHECK_FINISHED) {
  521 + SrsStream *stream = new SrsStream;
  522 + SrsAutoFree(SrsStream, stream, false);
  523 +
  524 + if ((ret = stream->initialize((char*)msg->payload, msg->size)) != ERROR_SUCCESS) {
  525 + srs_error("initialize stream error. ret=%d", ret);
  526 + return ret;
  527 + }
  528 +
  529 + std::string command_name;
  530 + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) {
  531 + srs_error("amfo read string error. ret=%d", ret);
  532 + return ret;
  533 + }
  534 +
  535 + double action_id;
  536 + if ((ret = srs_amf0_read_number(stream, action_id)) != ERROR_SUCCESS) {
  537 + srs_error("amfo read number error. ret=%d", ret);
  538 + return ret;
  539 + }
  540 +
  541 + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) {
  542 + srs_error("amfo read number error. ret=%d", ret);
  543 + return ret;
  544 + }
  545 +
  546 + SrsAmf0Object* object;
  547 + if ((ret = srs_amf0_read_object(stream, object)) != ERROR_SUCCESS) {
  548 + srs_error("amfo read object error. ret=%d", ret);
  549 + return ret;
  550 + }
  551 +
  552 + int64_t start_time = 0;
  553 + int64_t end_time = 0;
  554 +
  555 + SrsAmf0Any* start_time_any = object->get_property("start_time");
  556 + if (start_time_any && start_time_any->is_number()) {
  557 + SrsAmf0Number* start_time_number = dynamic_cast<SrsAmf0Number*> (start_time_any);
  558 + if (start_time_number) {
  559 + start_time = start_time_number->value;
  560 + }
  561 + }
  562 +
  563 + SrsAmf0Any* end_time_any = object->get_property("end_time");
  564 + if (end_time_any && end_time_any->is_number()) {
  565 + SrsAmf0Number* end_time_number = dynamic_cast<SrsAmf0Number*> (end_time_any);
  566 + if (end_time_number) {
  567 + end_time = end_time_number->value;
  568 + }
  569 + }
  570 +
  571 + int play_kbps = 0;
  572 + int pub_kbps = 0;
  573 + SrsAmf0Any* play_kbp_any = object->get_property("play_kbps");
  574 + if (play_kbp_any && play_kbp_any->is_number()) {
  575 + SrsAmf0Number* play_kbps_number = dynamic_cast<SrsAmf0Number*> (play_kbp_any);
  576 + if (play_kbps_number) {
  577 + play_kbps = play_kbps_number->value;
  578 + }
  579 + }
  580 +
  581 + SrsAmf0Any* pub_kbp_any = object->get_property("publish_kbps");
  582 + if (pub_kbp_any && pub_kbp_any->is_number()) {
  583 + SrsAmf0Number* pub_kbps_number = dynamic_cast<SrsAmf0Number*> (pub_kbp_any);
  584 + if (pub_kbps_number) {
  585 + pub_kbps = pub_kbps_number->value;
  586 + }
  587 + }
  588 +
  589 + float time_elapsed;
  590 + if (end_time - start_time > 0) {
  591 + time_elapsed = (end_time - start_time) / 1000.00;
  592 + }
  593 +
  594 + srs_trace("result: play %d kbps, publish %d kbps, check time %.4f S\n"
  595 + , play_kbps, pub_kbps, time_elapsed);
  596 +
  597 + break;
  598 + }
  599 + }
  600 +
  601 + return ret;
  602 +}
  603 +
  604 +int SrsBandCheckClient::send_stopped_pub()
  605 +{
  606 + int ret = ERROR_SUCCESS;
  607 +
  608 + SrsCommonMessage* msg = new SrsCommonMessage;
  609 + SrsBandwidthPacket* pkt = new SrsBandwidthPacket;
  610 + pkt->command_name = SRS_BW_CHECK_STOPPED_PUBLISH;
  611 + msg->set_packet(pkt, 0);
  612 +
  613 + if ((ret = send_message(msg)) != ERROR_SUCCESS) {
  614 + srs_error("send stopped pub msg failed. ret=%d", ret);
  615 + return ret;
  616 + }
  617 + srs_info("send stopped pub msg success.");
  618 +
  619 + return ret;
  620 +}
  621 +
  622 +int SrsBandCheckClient::send_final()
  623 +{
  624 + int ret = ERROR_SUCCESS;
  625 +
  626 + SrsCommonMessage* msg = new SrsCommonMessage;
  627 + SrsBandwidthPacket* pkt = new SrsBandwidthPacket;
  628 + pkt->command_name = SRS_BW_CHECK_FLASH_FINAL;
  629 + msg->set_packet(pkt, 0);
  630 +
  631 + if ((ret = send_message(msg)) != ERROR_SUCCESS) {
  632 + srs_error("send final msg failed. ret=%d", ret);
  633 + return ret;
  634 + }
  635 + srs_info("send final msg success.");
  636 +
  637 + return ret;
  638 +}
  639 +
  640 +SrsBandCheck::SrsBandCheck()
  641 + : bandCheck_Client(0)
  642 +{
  643 +}
  644 +
  645 +SrsBandCheck::~SrsBandCheck()
  646 +{
  647 + if (bandCheck_Client) {
  648 + srs_freep(bandCheck_Client);
  649 + }
  650 +}
  651 +
  652 +int SrsBandCheck::check(const std::string &app, const std::string &tcUrl)
  653 +{
  654 + int ret = ERROR_SUCCESS;
  655 +
  656 + if ((ret = connect_server()) != ERROR_SUCCESS) {
  657 + srs_error("connect to server failed. ret = %d", ret);
  658 + return ret;
  659 + }
  660 +
  661 + if ((ret = bandCheck_Client->handshake()) != ERROR_SUCCESS) {
  662 + srs_error("handshake failed. ret = %d", ret);
  663 + return ret;
  664 + }
  665 +
  666 + if ((ret = bandCheck_Client->connect_app(app, tcUrl)) != ERROR_SUCCESS) {
  667 + srs_error("handshake failed. ret = %d", ret);
  668 + return ret;
  669 + }
  670 +
  671 + if ((ret = bandCheck_Client->check_play()) != ERROR_SUCCESS) {
  672 + srs_error("band check play failed.");
  673 + return ret;
  674 + }
  675 +
  676 + if ((ret = bandCheck_Client->check_publish()) != ERROR_SUCCESS) {
  677 + srs_error("band check publish failed.");
  678 + return ret;
  679 + }
  680 +
  681 + return ret;
  682 +}
  683 +
  684 +void SrsBandCheck::set_server(const std::string &server, int port)
  685 +{
  686 + server_address = server;
  687 + server_port = port;
  688 +}
  689 +
  690 +int SrsBandCheck::connect_server()
  691 +{
  692 + int ret = ERROR_SUCCESS;
  693 +
  694 + int sock = socket(AF_INET, SOCK_STREAM, 0);
  695 + if(sock == -1){
  696 + ret = ERROR_SOCKET_CREATE;
  697 + srs_error("create socket error. ret=%d", ret);
  698 + return ret;
  699 + }
  700 +
  701 + st_netfd_t stfd = st_netfd_open_socket(sock);
  702 + if(stfd == NULL){
  703 + ret = ERROR_ST_OPEN_SOCKET;
  704 + srs_error("st_netfd_open_socket failed. ret=%d", ret);
  705 + return ret;
  706 + }
  707 +
  708 + bandCheck_Client = new SrsBandCheckClient(stfd);
  709 +
  710 + // connect to server.
  711 + std::string ip = srs_dns_resolve(server_address);
  712 + if (ip.empty()) {
  713 + ret = ERROR_SYSTEM_IP_INVALID;
  714 + srs_error("dns resolve server error, ip empty. ret=%d", ret);
  715 + return ret;
  716 + }
  717 +
  718 + sockaddr_in addr;
  719 + addr.sin_family = AF_INET;
  720 + addr.sin_port = htons(server_port);
  721 + addr.sin_addr.s_addr = inet_addr(ip.c_str());
  722 +
  723 + if (st_connect(stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), ST_UTIME_NO_TIMEOUT) == -1){
  724 + ret = ERROR_ST_CONNECT;
  725 + srs_error("connect to server error. ip=%s, port=%d, ret=%d", ip.c_str(), server_port, ret);
  726 + return ret;
  727 + }
  728 + srs_trace("connect to server success. server=%s, ip=%s, port=%d", server_address.c_str(), ip.c_str(), server_port);
  729 +
  730 + return ret;
  731 +}
  732 +
  733 +int init_st()
  734 +{
  735 + int ret = ERROR_SUCCESS;
  736 +
  737 + if (st_set_eventsys(ST_EVENTSYS_ALT) == -1) {
  738 + ret = ERROR_ST_SET_EPOLL;
  739 + srs_error("st_set_eventsys use linux epoll failed. ret=%d", ret);
  740 + return ret;
  741 + }
  742 +
  743 + if(st_init() != 0){
  744 + ret = ERROR_ST_INITIALIZE;
  745 + srs_error("st_init failed. ret=%d", ret);
  746 + return ret;
  747 + }
  748 +
  749 + return ret;
  750 +}
  751 +
  752 +void print_help(char** argv)
  753 +{
  754 + printf(
  755 + "Usage: %s [OPTION]...\n"
  756 + "test band width from client to rtmp server.\n"
  757 + "Mandatory arguments to long options are mandatory for short options too.\n"
  758 + " -i, --ip the ip or domain that to test\n"
  759 + " -p, --port the port that server listen \n"
  760 + " -k, --key the key used to test \n"
  761 + " -v, --vhost the vhost used to test \n"
  762 + " -V, --version output version information and exit \n"
  763 + " -h, --help display this help and exit \n"
  764 + "\n"
  765 + "For example:\n"
  766 + " %s -i 192.168.1.248 -p 1935 -v bandcheck.srs.com -k 35c9b402c12a7246868752e2878f7e0e"
  767 + "\n\n"
  768 + "Exit status:\n"
  769 + "0 if OK,\n"
  770 + "other if error occured, and the detail should be printed.\n"
  771 + "\n\n"
  772 + "srs home page: <http://blog.chinaunix.net/uid/25006789.html>\n",
  773 + argv[0], argv[0]);
  774 +}
  775 +
  776 +void print_version()
  777 +{
  778 + const char *version = ""
  779 + "srs_bandcheck "BUILD_VERSION"\n"
  780 + "Copyright (C) 2013 wenjiegit.\n"
  781 + "License MIT\n"
  782 + "This is free software: you are free to change and redistribute it.\n"
  783 + "There is NO WARRANTY, to the extent permitted by law.\n"
  784 + "\n"
  785 + "Written by wenjie.\n";
  786 +
  787 + printf("%s", version);
  788 +}
  789 +
  790 +int get_opt(int argc, char *argv[])
  791 +{
  792 + int ret = ERROR_SUCCESS;
  793 +
  794 + int c;
  795 + while ((c = getopt_long (argc, argv, short_options, long_options, NULL)) != -1) {
  796 + switch (c) {
  797 + case 'i':
  798 + if (optarg) {
  799 + g_ip = optarg;
  800 + }
  801 + break;
  802 + case 'p':
  803 + if (optarg) {
  804 + g_port = atoi(optarg);
  805 + }
  806 + break;
  807 + case 'k':
  808 + if (optarg) {
  809 + g_key = optarg;
  810 + }
  811 + break;
  812 + case 'v':
  813 + if (optarg) {
  814 + g_vhost = optarg;
  815 + }
  816 + break;
  817 + case 'V':
  818 + print_version();
  819 + exit(0);
  820 + break;
  821 + case 'h':
  822 + print_help(argv);
  823 + exit(0);
  824 + break;
  825 + default:
  826 + printf("see --help or -h\n");
  827 + ret = -1;
  828 + }
  829 + }
  830 +
  831 + return ret;
  832 +}
1 file 1 file
2 main readonly separator, 2 main readonly separator,
3 ..\main\srs_main_server.cpp, 3 ..\main\srs_main_server.cpp,
  4 + ..\main\srs_main_bandcheck.cpp,
4 auto readonly separator, 5 auto readonly separator,
5 ..\..\objs\srs_auto_headers.hpp, 6 ..\..\objs\srs_auto_headers.hpp,
6 core readonly separator, 7 core readonly separator,