wenjie

+server support band check +every vhost can have it's own chunk size

@@ -80,7 +80,7 @@ else @@ -80,7 +80,7 @@ else
80 --yasmexe=${ff_yasm_bin} \ 80 --yasmexe=${ff_yasm_bin} \
81 --prefix=${ff_release_dir} --cc= \ 81 --prefix=${ff_release_dir} --cc= \
82 --enable-static --disable-shared --disable-debug \ 82 --enable-static --disable-shared --disable-debug \
83 - --extra-cflags='-I${ffmpeg_exported_release_dir}/include' \ 83 + --extra-cflags='-I${ffmpeg_exported_release_dir}/include -I /usr/include/freetype2/' \
84 --extra-ldflags='-L${ffmpeg_exported_release_dir}/lib -lm -ldl' \ 84 --extra-ldflags='-L${ffmpeg_exported_release_dir}/lib -lm -ldl' \
85 --disable-ffplay --disable-ffprobe --disable-ffserver --disable-doc \ 85 --disable-ffplay --disable-ffprobe --disable-ffserver --disable-doc \
86 --enable-postproc --enable-bzlib --enable-zlib --enable-parsers \ 86 --enable-postproc --enable-bzlib --enable-zlib --enable-parsers \
1 listen 19350; 1 listen 19350;
2 -chunk_size 65000;  
3 vhost __defaultVhost__ { 2 vhost __defaultVhost__ {
  3 + chunk_size 65000;
4 enabled on; 4 enabled on;
5 gop_cache on; 5 gop_cache on;
6 hls on; 6 hls on;
1 # the listen ports, split by space. 1 # the listen ports, split by space.
2 listen 1935; 2 listen 1935;
3 -# the default chunk size is 128, max is 65536,  
4 -# some client does not support chunk size change,  
5 -# however, most clients supports it and it can improve  
6 -# performance about 10%.  
7 -# if not specified, set to 4096.  
8 -chunk_size 65000;  
9 # the logs dir. 3 # the logs dir.
10 # if enabled ffmpeg, each stracoding stream will create a log file. 4 # if enabled ffmpeg, each stracoding stream will create a log file.
11 # default: ./objs/logs 5 # default: ./objs/logs
@@ -19,6 +13,12 @@ max_connections 2000; @@ -19,6 +13,12 @@ max_connections 2000;
19 # for which cannot identify the required vhost. 13 # for which cannot identify the required vhost.
20 # for default demo. 14 # for default demo.
21 vhost __defaultVhost__ { 15 vhost __defaultVhost__ {
  16 + # the default chunk size is 128, max is 65536,
  17 + # some client does not support chunk size change,
  18 + # however, most clients supports it and it can improve
  19 + # performance about 10%.
  20 + # if not specified, set to 4096.
  21 + chunk_size 65000;
22 enabled on; 22 enabled on;
23 gop_cache on; 23 gop_cache on;
24 hls on; 24 hls on;
@@ -79,6 +79,7 @@ vhost __defaultVhost__ { @@ -79,6 +79,7 @@ vhost __defaultVhost__ {
79 } 79 }
80 # for development 80 # for development
81 vhost dev { 81 vhost dev {
  82 + chunk_size 65000;
82 enabled on; 83 enabled on;
83 gop_cache on; 84 gop_cache on;
84 hls on; 85 hls on;
@@ -87,7 +88,7 @@ vhost dev { @@ -87,7 +88,7 @@ vhost dev {
87 hls_window 30; 88 hls_window 30;
88 forward 127.0.0.1:19350; 89 forward 127.0.0.1:19350;
89 http_hooks { 90 http_hooks {
90 - enabled on; 91 + enabled off;
91 on_connect http://127.0.0.1:8085/api/v1/clients; 92 on_connect http://127.0.0.1:8085/api/v1/clients;
92 on_close http://127.0.0.1:8085/api/v1/clients; 93 on_close http://127.0.0.1:8085/api/v1/clients;
93 on_publish http://127.0.0.1:8085/api/v1/streams; 94 on_publish http://127.0.0.1:8085/api/v1/streams;
@@ -133,6 +134,20 @@ vhost dev { @@ -133,6 +134,20 @@ vhost dev {
133 } 134 }
134 } 135 }
135 } 136 }
  137 +
  138 +vhost bandcheck.srs.com {
  139 + chunk_size 65000;
  140 + enabled on;
  141 + # vhost for band width check
  142 + bandcheck{
  143 + enabled on;
  144 + key test kate;
  145 + interval 30;
  146 + max_play_kbps 45000;
  147 + max_pub_kbps 25000;
  148 + }
  149 +}
  150 +
136 # the http hook callback vhost, srs will invoke the hooks for specified events. 151 # the http hook callback vhost, srs will invoke the hooks for specified events.
137 vhost hooks.callback.vhost.com { 152 vhost hooks.callback.vhost.com {
138 http_hooks { 153 http_hooks {
@@ -33,7 +33,7 @@ static int64_t _srs_system_time_us_cache = 0; @@ -33,7 +33,7 @@ static int64_t _srs_system_time_us_cache = 0;
33 33
34 int64_t srs_get_system_time_ms() 34 int64_t srs_get_system_time_ms()
35 { 35 {
36 - return _srs_system_time_us_cache / 1000; 36 + return _srs_system_time_us_cache / 1000;
37 } 37 }
38 38
39 void srs_update_system_time_ms() 39 void srs_update_system_time_ms()
@@ -43,7 +43,7 @@ void srs_update_system_time_ms() @@ -43,7 +43,7 @@ void srs_update_system_time_ms()
43 gettimeofday(&now, NULL); 43 gettimeofday(&now, NULL);
44 44
45 // we must convert the tv_sec/tv_usec to int64_t. 45 // we must convert the tv_sec/tv_usec to int64_t.
46 - _srs_system_time_us_cache = now.tv_sec * 1000 * 1000 + now.tv_usec; 46 + _srs_system_time_us_cache = ((int64_t)now.tv_sec) * 1000 * 1000 + (int64_t)now.tv_usec;
47 47
48 _srs_system_time_us_cache = srs_max(0, _srs_system_time_us_cache); 48 _srs_system_time_us_cache = srs_max(0, _srs_system_time_us_cache);
49 } 49 }
@@ -103,11 +103,11 @@ void srs_vhost_resolve(std::string& vhost, std::string& app) @@ -103,11 +103,11 @@ void srs_vhost_resolve(std::string& vhost, std::string& app)
103 if ((pos = query.find("vhost?")) != std::string::npos 103 if ((pos = query.find("vhost?")) != std::string::npos
104 || (pos = query.find("vhost=")) != std::string::npos 104 || (pos = query.find("vhost=")) != std::string::npos
105 || (pos = query.find("Vhost?")) != std::string::npos 105 || (pos = query.find("Vhost?")) != std::string::npos
106 - || (pos = query.find("Vhost=")) != std::string::npos  
107 - ) { 106 + || (pos = query.find("Vhost=")) != std::string::npos)
  107 + {
108 query = query.substr(pos + 6); 108 query = query.substr(pos + 6);
109 if (!query.empty()) { 109 if (!query.empty()) {
110 vhost = query; 110 vhost = query;
111 } 111 }
112 - } 112 + }
113 } 113 }
@@ -102,4 +102,4 @@ extern std::string srs_dns_resolve(std::string host); @@ -102,4 +102,4 @@ extern std::string srs_dns_resolve(std::string host);
102 // app...vhost...request_vhost 102 // app...vhost...request_vhost
103 extern void srs_vhost_resolve(std::string& vhost, std::string& app); 103 extern void srs_vhost_resolve(std::string& vhost, std::string& app);
104 104
105 -#endif  
  105 +#endif
@@ -117,8 +117,8 @@ int SrsClient::do_cycle() @@ -117,8 +117,8 @@ int SrsClient::do_cycle()
117 int SrsClient::service_cycle() 117 int SrsClient::service_cycle()
118 { 118 {
119 int ret = ERROR_SUCCESS; 119 int ret = ERROR_SUCCESS;
120 -  
121 - if ((ret = rtmp->set_window_ack_size(2.5 * 1000 * 1000)) != ERROR_SUCCESS) { 120 +
  121 + if ((ret = rtmp->set_window_ack_size(2.5 * 1000 * 1000)) != ERROR_SUCCESS) {
122 srs_error("set window acknowledgement size failed. ret=%d", ret); 122 srs_error("set window acknowledgement size failed. ret=%d", ret);
123 return ret; 123 return ret;
124 } 124 }
@@ -129,29 +129,59 @@ int SrsClient::service_cycle() @@ -129,29 +129,59 @@ int SrsClient::service_cycle()
129 return ret; 129 return ret;
130 } 130 }
131 srs_verbose("set peer bandwidth success"); 131 srs_verbose("set peer bandwidth success");
  132 +
  133 + if(config->get_bw_check_enabled(req->vhost, req->bw_key))
  134 + {
  135 + static int64_t last_check_time_ms = srs_get_system_time_ms();
  136 + int64_t interval_ms = 0;
  137 + int play_kbps = 0;
  138 + int pub_kbps = 0;
  139 + config->get_bw_check_settings(req->vhost, interval_ms, play_kbps, pub_kbps);
  140 +
  141 + if((srs_get_system_time_ms() - last_check_time_ms) < interval_ms
  142 + && last_check_time_ms != srs_get_system_time_ms())
  143 + {
  144 + srs_trace("bandcheck interval less than limted interval. last time=%lld, current time=%lld"
  145 + , last_check_time_ms, srs_get_system_time_ms());
  146 + return rtmp->response_connect_reject(req, "your bandcheck frequency is too high!");
  147 + } else {
  148 + last_check_time_ms = srs_get_system_time_ms(); // update last check time
  149 + char* local_ip = 0;
  150 + if((ret = get_local_ip(local_ip)) != ERROR_SUCCESS){
  151 + srs_error("get local ip failed. ret = %d", ret);
  152 + return ret;
  153 + }
  154 + if ((ret = rtmp->response_connect_app(req, local_ip)) != ERROR_SUCCESS) {
  155 + srs_error("response connect app failed. ret=%d", ret);
  156 + return ret;
  157 + }
  158 + return rtmp->start_bandwidth_check(play_kbps, pub_kbps);
  159 + }
  160 + }
132 161
133 if ((ret = rtmp->response_connect_app(req)) != ERROR_SUCCESS) { 162 if ((ret = rtmp->response_connect_app(req)) != ERROR_SUCCESS) {
134 srs_error("response connect app failed. ret=%d", ret); 163 srs_error("response connect app failed. ret=%d", ret);
135 return ret; 164 return ret;
136 } 165 }
137 - srs_verbose("response connect app success"); 166 + srs_verbose("response connect app success");
138 167
139 if ((ret = rtmp->on_bw_done()) != ERROR_SUCCESS) { 168 if ((ret = rtmp->on_bw_done()) != ERROR_SUCCESS) {
140 srs_error("on_bw_done failed. ret=%d", ret); 169 srs_error("on_bw_done failed. ret=%d", ret);
141 return ret; 170 return ret;
142 } 171 }
143 srs_verbose("on_bw_done success"); 172 srs_verbose("on_bw_done success");
144 -  
145 - SrsClientType type;  
146 - if ((ret = rtmp->identify_client(res->stream_id, type, req->stream)) != ERROR_SUCCESS) {  
147 - srs_error("identify client failed. ret=%d", ret);  
148 - return ret;  
149 - } 173 +
  174 + SrsClientType type;
  175 + if ((ret = rtmp->identify_client(res->stream_id, type, req->stream)) != ERROR_SUCCESS) {
  176 + srs_error("identify client failed. ret=%d", ret);
  177 + return ret;
  178 + }
  179 +
150 req->strip(); 180 req->strip();
151 srs_trace("identify client success. type=%d, stream_name=%s", type, req->stream.c_str()); 181 srs_trace("identify client success. type=%d, stream_name=%s", type, req->stream.c_str());
152 182
153 int chunk_size = 4096; 183 int chunk_size = 4096;
154 - SrsConfDirective* conf = config->get_chunk_size(); 184 + SrsConfDirective* conf = config->get_chunk_size(req->vhost);
155 if (conf && !conf->arg0().empty()) { 185 if (conf && !conf->arg0().empty()) {
156 chunk_size = ::atoi(conf->arg0().c_str()); 186 chunk_size = ::atoi(conf->arg0().c_str());
157 } 187 }
@@ -517,6 +547,40 @@ int SrsClient::get_peer_ip() @@ -517,6 +547,40 @@ int SrsClient::get_peer_ip()
517 return ret; 547 return ret;
518 } 548 }
519 549
  550 +int SrsClient::get_local_ip(char *&local_ip)
  551 +{
  552 + int ret = ERROR_SUCCESS;
  553 +
  554 + int fd = st_netfd_fileno(stfd);
  555 +
  556 + // discovery client information
  557 + sockaddr_in addr;
  558 + socklen_t addrlen = sizeof(addr);
  559 + if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) {
  560 + ret = ERROR_SOCKET_GET_LOCAL_IP;
  561 + srs_error("discovery local ip information failed. ret=%d", ret);
  562 + return ret;
  563 + }
  564 + srs_verbose("get local ip success.");
  565 +
  566 + // ip v4 or v6
  567 + char buf[INET6_ADDRSTRLEN];
  568 + memset(buf, 0, sizeof(buf));
  569 +
  570 + if ((inet_ntop(addr.sin_family, &addr.sin_addr, buf, sizeof(buf))) == NULL) {
  571 + ret = ERROR_SOCKET_GET_LOCAL_IP;
  572 + srs_error("convert local ip information failed. ret=%d", ret);
  573 + return ret;
  574 + }
  575 +
  576 + local_ip = new char[strlen(buf) + 1];
  577 + strcpy(local_ip, buf);
  578 +
  579 + srs_verbose("get local ip of client ip=%s, fd=%d", buf, fd);
  580 +
  581 + return ret;
  582 +}
  583 +
520 int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg) 584 int SrsClient::process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg)
521 { 585 {
522 int ret = ERROR_SUCCESS; 586 int ret = ERROR_SUCCESS;
@@ -70,6 +70,7 @@ private: @@ -70,6 +70,7 @@ private:
70 virtual int publish(SrsSource* source, bool is_fmle); 70 virtual int publish(SrsSource* source, bool is_fmle);
71 virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg, bool is_fmle); 71 virtual int process_publish_message(SrsSource* source, SrsCommonMessage* msg, bool is_fmle);
72 virtual int get_peer_ip(); 72 virtual int get_peer_ip();
  73 + virtual int get_local_ip(char *&local_ip);
73 virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg); 74 virtual int process_play_control_msg(SrsConsumer* consumer, SrsCommonMessage* msg);
74 private: 75 private:
75 virtual int on_connect(); 76 virtual int on_connect();
@@ -80,4 +81,4 @@ private: @@ -80,4 +81,4 @@ private:
80 virtual void on_stop(); 81 virtual void on_stop();
81 }; 82 };
82 83
83 -#endif  
  84 +#endif
@@ -539,7 +539,7 @@ int SrsConfig::parse_options(int argc, char** argv) @@ -539,7 +539,7 @@ int SrsConfig::parse_options(int argc, char** argv)
539 return parse_file(config_file.c_str()); 539 return parse_file(config_file.c_str());
540 } 540 }
541 541
542 -SrsConfDirective* SrsConfig::get_vhost(std::string vhost) 542 +SrsConfDirective* SrsConfig::get_vhost(const std::string& vhost)
543 { 543 {
544 srs_assert(root); 544 srs_assert(root);
545 545
@@ -562,7 +562,7 @@ SrsConfDirective* SrsConfig::get_vhost(std::string vhost) @@ -562,7 +562,7 @@ SrsConfDirective* SrsConfig::get_vhost(std::string vhost)
562 return NULL; 562 return NULL;
563 } 563 }
564 564
565 -SrsConfDirective* SrsConfig::get_vhost_on_connect(std::string vhost) 565 +SrsConfDirective* SrsConfig::get_vhost_on_connect(const std::string &vhost)
566 { 566 {
567 SrsConfDirective* conf = get_vhost(vhost); 567 SrsConfDirective* conf = get_vhost(vhost);
568 568
@@ -583,7 +583,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_connect(std::string vhost) @@ -583,7 +583,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_connect(std::string vhost)
583 return conf->get("on_connect"); 583 return conf->get("on_connect");
584 } 584 }
585 585
586 -SrsConfDirective* SrsConfig::get_vhost_on_close(std::string vhost) 586 +SrsConfDirective* SrsConfig::get_vhost_on_close(const std::string &vhost)
587 { 587 {
588 SrsConfDirective* conf = get_vhost(vhost); 588 SrsConfDirective* conf = get_vhost(vhost);
589 589
@@ -604,7 +604,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_close(std::string vhost) @@ -604,7 +604,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_close(std::string vhost)
604 return conf->get("on_close"); 604 return conf->get("on_close");
605 } 605 }
606 606
607 -SrsConfDirective* SrsConfig::get_vhost_on_publish(std::string vhost) 607 +SrsConfDirective* SrsConfig::get_vhost_on_publish(const std::string &vhost)
608 { 608 {
609 SrsConfDirective* conf = get_vhost(vhost); 609 SrsConfDirective* conf = get_vhost(vhost);
610 610
@@ -625,7 +625,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_publish(std::string vhost) @@ -625,7 +625,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_publish(std::string vhost)
625 return conf->get("on_publish"); 625 return conf->get("on_publish");
626 } 626 }
627 627
628 -SrsConfDirective* SrsConfig::get_vhost_on_unpublish(std::string vhost) 628 +SrsConfDirective* SrsConfig::get_vhost_on_unpublish(const std::string &vhost)
629 { 629 {
630 SrsConfDirective* conf = get_vhost(vhost); 630 SrsConfDirective* conf = get_vhost(vhost);
631 631
@@ -646,7 +646,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_unpublish(std::string vhost) @@ -646,7 +646,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_unpublish(std::string vhost)
646 return conf->get("on_unpublish"); 646 return conf->get("on_unpublish");
647 } 647 }
648 648
649 -SrsConfDirective* SrsConfig::get_vhost_on_play(std::string vhost) 649 +SrsConfDirective* SrsConfig::get_vhost_on_play(const std::string &vhost)
650 { 650 {
651 SrsConfDirective* conf = get_vhost(vhost); 651 SrsConfDirective* conf = get_vhost(vhost);
652 652
@@ -667,7 +667,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_play(std::string vhost) @@ -667,7 +667,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_play(std::string vhost)
667 return conf->get("on_play"); 667 return conf->get("on_play");
668 } 668 }
669 669
670 -SrsConfDirective* SrsConfig::get_vhost_on_stop(std::string vhost) 670 +SrsConfDirective* SrsConfig::get_vhost_on_stop(const std::string &vhost)
671 { 671 {
672 SrsConfDirective* conf = get_vhost(vhost); 672 SrsConfDirective* conf = get_vhost(vhost);
673 673
@@ -688,7 +688,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_stop(std::string vhost) @@ -688,7 +688,7 @@ SrsConfDirective* SrsConfig::get_vhost_on_stop(std::string vhost)
688 return conf->get("on_stop"); 688 return conf->get("on_stop");
689 } 689 }
690 690
691 -bool SrsConfig::get_vhost_enabled(std::string vhost) 691 +bool SrsConfig::get_vhost_enabled(const std::string &vhost)
692 { 692 {
693 SrsConfDirective* vhost_conf = get_vhost(vhost); 693 SrsConfDirective* vhost_conf = get_vhost(vhost);
694 694
@@ -708,7 +708,7 @@ bool SrsConfig::get_vhost_enabled(std::string vhost) @@ -708,7 +708,7 @@ bool SrsConfig::get_vhost_enabled(std::string vhost)
708 return true; 708 return true;
709 } 709 }
710 710
711 -SrsConfDirective* SrsConfig::get_transcode(std::string vhost, std::string scope) 711 +SrsConfDirective* SrsConfig::get_transcode(const std::string &vhost, const std::string &scope)
712 { 712 {
713 SrsConfDirective* conf = get_vhost(vhost); 713 SrsConfDirective* conf = get_vhost(vhost);
714 714
@@ -1059,7 +1059,7 @@ int SrsConfig::get_max_connections() @@ -1059,7 +1059,7 @@ int SrsConfig::get_max_connections()
1059 return ::atoi(conf->arg0().c_str()); 1059 return ::atoi(conf->arg0().c_str());
1060 } 1060 }
1061 1061
1062 -SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost) 1062 +SrsConfDirective* SrsConfig::get_gop_cache(const std::string &vhost)
1063 { 1063 {
1064 SrsConfDirective* conf = get_vhost(vhost); 1064 SrsConfDirective* conf = get_vhost(vhost);
1065 1065
@@ -1070,7 +1070,7 @@ SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost) @@ -1070,7 +1070,7 @@ SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost)
1070 return conf->get("gop_cache"); 1070 return conf->get("gop_cache");
1071 } 1071 }
1072 1072
1073 -SrsConfDirective* SrsConfig::get_forward(std::string vhost) 1073 +SrsConfDirective* SrsConfig::get_forward(const std::string &vhost)
1074 { 1074 {
1075 SrsConfDirective* conf = get_vhost(vhost); 1075 SrsConfDirective* conf = get_vhost(vhost);
1076 1076
@@ -1081,7 +1081,7 @@ SrsConfDirective* SrsConfig::get_forward(std::string vhost) @@ -1081,7 +1081,7 @@ SrsConfDirective* SrsConfig::get_forward(std::string vhost)
1081 return conf->get("forward"); 1081 return conf->get("forward");
1082 } 1082 }
1083 1083
1084 -SrsConfDirective* SrsConfig::get_hls(std::string vhost) 1084 +SrsConfDirective* SrsConfig::get_hls(const std::string &vhost)
1085 { 1085 {
1086 SrsConfDirective* conf = get_vhost(vhost); 1086 SrsConfDirective* conf = get_vhost(vhost);
1087 1087
@@ -1092,7 +1092,7 @@ SrsConfDirective* SrsConfig::get_hls(std::string vhost) @@ -1092,7 +1092,7 @@ SrsConfDirective* SrsConfig::get_hls(std::string vhost)
1092 return conf->get("hls"); 1092 return conf->get("hls");
1093 } 1093 }
1094 1094
1095 -bool SrsConfig::get_hls_enabled(std::string vhost) 1095 +bool SrsConfig::get_hls_enabled(const std::string &vhost)
1096 { 1096 {
1097 SrsConfDirective* hls = get_hls(vhost); 1097 SrsConfDirective* hls = get_hls(vhost);
1098 1098
@@ -1107,7 +1107,7 @@ bool SrsConfig::get_hls_enabled(std::string vhost) @@ -1107,7 +1107,7 @@ bool SrsConfig::get_hls_enabled(std::string vhost)
1107 return true; 1107 return true;
1108 } 1108 }
1109 1109
1110 -SrsConfDirective* SrsConfig::get_hls_path(std::string vhost) 1110 +SrsConfDirective* SrsConfig::get_hls_path(const std::string &vhost)
1111 { 1111 {
1112 SrsConfDirective* conf = get_vhost(vhost); 1112 SrsConfDirective* conf = get_vhost(vhost);
1113 1113
@@ -1118,7 +1118,7 @@ SrsConfDirective* SrsConfig::get_hls_path(std::string vhost) @@ -1118,7 +1118,7 @@ SrsConfDirective* SrsConfig::get_hls_path(std::string vhost)
1118 return conf->get("hls_path"); 1118 return conf->get("hls_path");
1119 } 1119 }
1120 1120
1121 -SrsConfDirective* SrsConfig::get_hls_fragment(std::string vhost) 1121 +SrsConfDirective* SrsConfig::get_hls_fragment(const std::string &vhost)
1122 { 1122 {
1123 SrsConfDirective* conf = get_vhost(vhost); 1123 SrsConfDirective* conf = get_vhost(vhost);
1124 1124
@@ -1129,7 +1129,7 @@ SrsConfDirective* SrsConfig::get_hls_fragment(std::string vhost) @@ -1129,7 +1129,7 @@ SrsConfDirective* SrsConfig::get_hls_fragment(std::string vhost)
1129 return conf->get("hls_fragment"); 1129 return conf->get("hls_fragment");
1130 } 1130 }
1131 1131
1132 -SrsConfDirective* SrsConfig::get_hls_window(std::string vhost) 1132 +SrsConfDirective* SrsConfig::get_hls_window(const std::string &vhost)
1133 { 1133 {
1134 SrsConfDirective* conf = get_vhost(vhost); 1134 SrsConfDirective* conf = get_vhost(vhost);
1135 1135
@@ -1140,7 +1140,7 @@ SrsConfDirective* SrsConfig::get_hls_window(std::string vhost) @@ -1140,7 +1140,7 @@ SrsConfDirective* SrsConfig::get_hls_window(std::string vhost)
1140 return conf->get("hls_window"); 1140 return conf->get("hls_window");
1141 } 1141 }
1142 1142
1143 -SrsConfDirective* SrsConfig::get_refer(std::string vhost) 1143 +SrsConfDirective* SrsConfig::get_refer(const std::string &vhost)
1144 { 1144 {
1145 SrsConfDirective* conf = get_vhost(vhost); 1145 SrsConfDirective* conf = get_vhost(vhost);
1146 1146
@@ -1151,7 +1151,7 @@ SrsConfDirective* SrsConfig::get_refer(std::string vhost) @@ -1151,7 +1151,7 @@ SrsConfDirective* SrsConfig::get_refer(std::string vhost)
1151 return conf->get("refer"); 1151 return conf->get("refer");
1152 } 1152 }
1153 1153
1154 -SrsConfDirective* SrsConfig::get_refer_play(std::string vhost) 1154 +SrsConfDirective* SrsConfig::get_refer_play(const std::string &vhost)
1155 { 1155 {
1156 SrsConfDirective* conf = get_vhost(vhost); 1156 SrsConfDirective* conf = get_vhost(vhost);
1157 1157
@@ -1162,7 +1162,7 @@ SrsConfDirective* SrsConfig::get_refer_play(std::string vhost) @@ -1162,7 +1162,7 @@ SrsConfDirective* SrsConfig::get_refer_play(std::string vhost)
1162 return conf->get("refer_play"); 1162 return conf->get("refer_play");
1163 } 1163 }
1164 1164
1165 -SrsConfDirective* SrsConfig::get_refer_publish(std::string vhost) 1165 +SrsConfDirective* SrsConfig::get_refer_publish(const std::string &vhost)
1166 { 1166 {
1167 SrsConfDirective* conf = get_vhost(vhost); 1167 SrsConfDirective* conf = get_vhost(vhost);
1168 1168
@@ -1178,9 +1178,15 @@ SrsConfDirective* SrsConfig::get_listen() @@ -1178,9 +1178,15 @@ SrsConfDirective* SrsConfig::get_listen()
1178 return root->get("listen"); 1178 return root->get("listen");
1179 } 1179 }
1180 1180
1181 -SrsConfDirective* SrsConfig::get_chunk_size() 1181 +SrsConfDirective* SrsConfig::get_chunk_size(const std::string &vhost)
1182 { 1182 {
1183 - return root->get("chunk_size"); 1183 + SrsConfDirective* conf = get_vhost(vhost);
  1184 +
  1185 + if (!conf) {
  1186 + return NULL;
  1187 + }
  1188 +
  1189 + return conf->get("chunk_size");
1184 } 1190 }
1185 1191
1186 SrsConfDirective* SrsConfig::get_pithy_print_publish() 1192 SrsConfDirective* SrsConfig::get_pithy_print_publish()
@@ -1230,7 +1236,63 @@ SrsConfDirective* SrsConfig::get_pithy_print_play() @@ -1230,7 +1236,63 @@ SrsConfDirective* SrsConfig::get_pithy_print_play()
1230 return NULL; 1236 return NULL;
1231 } 1237 }
1232 1238
1233 - return pithy->get("play"); 1239 + return pithy->get("play");
  1240 +}
  1241 +
  1242 +bool SrsConfig::get_bw_check_enabled(const std::string &vhost, const std::string &key)
  1243 +{
  1244 + SrsConfDirective* conf = get_vhost(vhost);
  1245 +
  1246 + if (!conf) {
  1247 + return false;
  1248 + }
  1249 +
  1250 + SrsConfDirective* bw_test = conf->get("bandcheck");
  1251 + if(!bw_test)
  1252 + return false;
  1253 +
  1254 + SrsConfDirective* bw_enabled_conf = bw_test->get("enabled");
  1255 + if(bw_enabled_conf && bw_enabled_conf->arg0() == "on"){
  1256 + SrsConfDirective* bw_key = bw_test->get("key");
  1257 + if(!bw_key) return false;
  1258 +
  1259 + std::vector<std::string> &args = bw_key->args;
  1260 + for(unsigned int i = 0; i < args.size(); ++i){
  1261 + if(args.at(i) == key)
  1262 + return true;
  1263 + }
  1264 + }
  1265 +
  1266 + return false;
  1267 +}
  1268 +
  1269 +void SrsConfig::get_bw_check_settings(const std::string &vhost, int64_t &interval_ms, int &play_kbps, int &pub_kbps)
  1270 +{
  1271 + // set default value;
  1272 + interval_ms = 30 * 1000;
  1273 + play_kbps = 45000;
  1274 + pub_kbps = 25000;
  1275 +
  1276 + SrsConfDirective* conf = get_vhost(vhost);
  1277 + if (!conf) {
  1278 + return;
  1279 + }
  1280 +
  1281 + SrsConfDirective* bw_test = conf->get("bandcheck");
  1282 + if(!bw_test)
  1283 + return;
  1284 +
  1285 + SrsConfDirective* interval_conf = bw_test->get("interval");
  1286 + if(interval_conf)
  1287 + interval_ms = ::atoll(interval_conf->arg0().c_str()) * 1000;
  1288 +
  1289 + SrsConfDirective* play_conf = bw_test->get("max_play_kbps");
  1290 + if(play_conf)
  1291 + play_kbps = ::atoi(play_conf->arg0().c_str());
  1292 +
  1293 + SrsConfDirective* pub_conf = bw_test->get("max_pub_kbps");
  1294 + if(pub_conf)
  1295 + pub_kbps = ::atoi(pub_conf->arg0().c_str());
1234 } 1296 }
1235 1297
1236 int SrsConfig::parse_file(const char* filename) 1298 int SrsConfig::parse_file(const char* filename)
@@ -117,15 +117,15 @@ public: @@ -117,15 +117,15 @@ public:
117 public: 117 public:
118 virtual int parse_options(int argc, char** argv); 118 virtual int parse_options(int argc, char** argv);
119 public: 119 public:
120 - virtual SrsConfDirective* get_vhost(std::string vhost);  
121 - virtual bool get_vhost_enabled(std::string vhost);  
122 - virtual SrsConfDirective* get_vhost_on_connect(std::string vhost);  
123 - virtual SrsConfDirective* get_vhost_on_close(std::string vhost);  
124 - virtual SrsConfDirective* get_vhost_on_publish(std::string vhost);  
125 - virtual SrsConfDirective* get_vhost_on_unpublish(std::string vhost);  
126 - virtual SrsConfDirective* get_vhost_on_play(std::string vhost);  
127 - virtual SrsConfDirective* get_vhost_on_stop(std::string vhost);  
128 - virtual SrsConfDirective* get_transcode(std::string vhost, std::string scope); 120 + virtual SrsConfDirective* get_vhost(const std::string &vhost);
  121 + virtual bool get_vhost_enabled(const std::string& vhost);
  122 + virtual SrsConfDirective* get_vhost_on_connect(const std::string& vhost);
  123 + virtual SrsConfDirective* get_vhost_on_close(const std::string& vhost);
  124 + virtual SrsConfDirective* get_vhost_on_publish(const std::string& vhost);
  125 + virtual SrsConfDirective* get_vhost_on_unpublish(const std::string& vhost);
  126 + virtual SrsConfDirective* get_vhost_on_play(const std::string& vhost);
  127 + virtual SrsConfDirective* get_vhost_on_stop(const std::string& vhost);
  128 + virtual SrsConfDirective* get_transcode(const std::string& vhost, const std::string& scope);
129 virtual bool get_transcode_enabled(SrsConfDirective* transcode); 129 virtual bool get_transcode_enabled(SrsConfDirective* transcode);
130 virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode); 130 virtual std::string get_transcode_ffmpeg(SrsConfDirective* transcode);
131 virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines); 131 virtual void get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines);
@@ -148,23 +148,25 @@ public: @@ -148,23 +148,25 @@ public:
148 virtual std::string get_engine_output(SrsConfDirective* engine); 148 virtual std::string get_engine_output(SrsConfDirective* engine);
149 virtual std::string get_log_dir(); 149 virtual std::string get_log_dir();
150 virtual int get_max_connections(); 150 virtual int get_max_connections();
151 - virtual SrsConfDirective* get_gop_cache(std::string vhost);  
152 - virtual SrsConfDirective* get_forward(std::string vhost);  
153 - virtual SrsConfDirective* get_hls(std::string vhost);  
154 - virtual bool get_hls_enabled(std::string vhost);  
155 - virtual SrsConfDirective* get_hls_path(std::string vhost);  
156 - virtual SrsConfDirective* get_hls_fragment(std::string vhost);  
157 - virtual SrsConfDirective* get_hls_window(std::string vhost);  
158 - virtual SrsConfDirective* get_refer(std::string vhost);  
159 - virtual SrsConfDirective* get_refer_play(std::string vhost);  
160 - virtual SrsConfDirective* get_refer_publish(std::string vhost); 151 + virtual SrsConfDirective* get_gop_cache(const std::string& vhost);
  152 + virtual SrsConfDirective* get_forward(const std::string& vhost);
  153 + virtual SrsConfDirective* get_hls(const std::string &vhost);
  154 + virtual bool get_hls_enabled(const std::string& vhost);
  155 + virtual SrsConfDirective* get_hls_path(const std::string& vhost);
  156 + virtual SrsConfDirective* get_hls_fragment(const std::string& vhost);
  157 + virtual SrsConfDirective* get_hls_window(const std::string& vhost);
  158 + virtual SrsConfDirective* get_refer(const std::string& vhost);
  159 + virtual SrsConfDirective* get_refer_play(const std::string& vhost);
  160 + virtual SrsConfDirective* get_refer_publish(const std::string& vhost);
161 virtual SrsConfDirective* get_listen(); 161 virtual SrsConfDirective* get_listen();
162 - virtual SrsConfDirective* get_chunk_size(); 162 + virtual SrsConfDirective* get_chunk_size(const std::string &vhost);
163 virtual SrsConfDirective* get_pithy_print_publish(); 163 virtual SrsConfDirective* get_pithy_print_publish();
164 virtual SrsConfDirective* get_pithy_print_forwarder(); 164 virtual SrsConfDirective* get_pithy_print_forwarder();
165 virtual SrsConfDirective* get_pithy_print_encoder(); 165 virtual SrsConfDirective* get_pithy_print_encoder();
166 virtual SrsConfDirective* get_pithy_print_hls(); 166 virtual SrsConfDirective* get_pithy_print_hls();
167 virtual SrsConfDirective* get_pithy_print_play(); 167 virtual SrsConfDirective* get_pithy_print_play();
  168 + virtual bool get_bw_check_enabled(const std::string &vhost, const std::string &key);
  169 + virtual void get_bw_check_settings(const std::string &vhost, int64_t &interval_ms, int &play_kbps, int &pub_kbps);
168 private: 170 private:
169 virtual int parse_file(const char* filename); 171 virtual int parse_file(const char* filename);
170 virtual int parse_argv(int& i, char** argv); 172 virtual int parse_argv(int& i, char** argv);
@@ -179,4 +181,4 @@ bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b); @@ -179,4 +181,4 @@ bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b);
179 // global config 181 // global config
180 extern SrsConfig* config; 182 extern SrsConfig* config;
181 183
182 -#endif  
  184 +#endif
@@ -52,6 +52,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -52,6 +52,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
52 #define ERROR_SOCKET_WRITE 209 52 #define ERROR_SOCKET_WRITE 209
53 #define ERROR_SOCKET_WAIT 210 53 #define ERROR_SOCKET_WAIT 210
54 #define ERROR_SOCKET_TIMEOUT 211 54 #define ERROR_SOCKET_TIMEOUT 211
  55 +#define ERROR_SOCKET_GET_LOCAL_IP 222
55 56
56 #define ERROR_RTMP_PLAIN_REQUIRED 300 57 #define ERROR_RTMP_PLAIN_REQUIRED 300
57 #define ERROR_RTMP_CHUNK_START 301 58 #define ERROR_RTMP_CHUNK_START 301
@@ -146,4 +147,4 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -146,4 +147,4 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
146 #define ERROR_HTTP_DATA_INVLIAD 801 147 #define ERROR_HTTP_DATA_INVLIAD 801
147 #define ERROR_HTTP_PARSE_HEADER 802 148 #define ERROR_HTTP_PARSE_HEADER 802
148 149
149 -#endif  
  150 +#endif
@@ -1138,7 +1138,12 @@ bool SrsMessageHeader::is_set_chunk_size() @@ -1138,7 +1138,12 @@ bool SrsMessageHeader::is_set_chunk_size()
1138 1138
1139 bool SrsMessageHeader::is_user_control_message() 1139 bool SrsMessageHeader::is_user_control_message()
1140 { 1140 {
1141 - return message_type == RTMP_MSG_UserControlMessage; 1141 + return message_type == RTMP_MSG_UserControlMessage;
  1142 +}
  1143 +
  1144 +bool SrsMessageHeader::is_windows_ackledgement()
  1145 +{
  1146 + return message_type == RTMP_MSG_Acknowledgement;
1142 } 1147 }
1143 1148
1144 SrsChunkStream::SrsChunkStream(int _cid) 1149 SrsChunkStream::SrsChunkStream(int _cid)
@@ -1311,7 +1316,21 @@ int SrsCommonMessage::decode_packet(SrsProtocol* protocol) @@ -1311,7 +1316,21 @@ int SrsCommonMessage::decode_packet(SrsProtocol* protocol)
1311 srs_info("decode the AMF0/AMF3 data(onMetaData message)."); 1316 srs_info("decode the AMF0/AMF3 data(onMetaData message).");
1312 packet = new SrsOnMetaDataPacket(); 1317 packet = new SrsOnMetaDataPacket();
1313 return packet->decode(stream); 1318 return packet->decode(stream);
1314 - } 1319 + } else if( command == SRS_BW_CHECK_FINISHED
  1320 + || command == SRS_BW_CHECK_PLAYING
  1321 + || command == SRS_BW_CHECK_PUBLISHING
  1322 + || command == SRS_BW_CHECK_STARTING_PLAY
  1323 + || command == SRS_BW_CHECK_STARTING_PUBLISH
  1324 + || command == SRS_BW_CHECK_START_PLAY
  1325 + || command == SRS_BW_CHECK_START_PUBLISH
  1326 + || command == SRS_BW_CHECK_STOPPED_PLAY
  1327 + || command == SRS_BW_CHECK_STOP_PLAY
  1328 + || command == SRS_BW_CHECK_STOP_PUBLISH)
  1329 + {
  1330 + srs_info("decode the AMF0/AMF3 band width check message.");
  1331 + packet = new SrsOnStatusCallPacket();
  1332 + return packet->decode(stream);
  1333 + }
1315 1334
1316 // default packet to drop message. 1335 // default packet to drop message.
1317 srs_trace("drop the AMF0/AMF3 command message, command_name=%s", command.c_str()); 1336 srs_trace("drop the AMF0/AMF3 command message, command_name=%s", command.c_str());
@@ -1329,7 +1348,11 @@ int SrsCommonMessage::decode_packet(SrsProtocol* protocol) @@ -1329,7 +1348,11 @@ int SrsCommonMessage::decode_packet(SrsProtocol* protocol)
1329 srs_verbose("start to decode set chunk size message."); 1348 srs_verbose("start to decode set chunk size message.");
1330 packet = new SrsSetChunkSizePacket(); 1349 packet = new SrsSetChunkSizePacket();
1331 return packet->decode(stream); 1350 return packet->decode(stream);
1332 - } else { 1351 + } else if(header.is_windows_ackledgement()) {
  1352 + srs_verbose("start to decode AcknowledgementPacket message.");
  1353 + packet = new SrsAcknowledgementPacket();
  1354 + return packet->decode(stream);
  1355 + } else {
1333 // default packet to drop message. 1356 // default packet to drop message.
1334 srs_trace("drop the unknown message, type=%d", header.message_type); 1357 srs_trace("drop the unknown message, type=%d", header.message_type);
1335 packet = new SrsPacket(); 1358 packet = new SrsPacket();
@@ -1775,8 +1798,13 @@ int SrsConnectAppResPacket::get_message_type() @@ -1775,8 +1798,13 @@ int SrsConnectAppResPacket::get_message_type()
1775 1798
1776 int SrsConnectAppResPacket::get_size() 1799 int SrsConnectAppResPacket::get_size()
1777 { 1800 {
1778 - return srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size()  
1779 - + srs_amf0_get_object_size(props)+ srs_amf0_get_object_size(info); 1801 + int size = srs_amf0_get_string_size(command_name) + srs_amf0_get_number_size();
  1802 + if(props->size() > 0)
  1803 + size += srs_amf0_get_object_size(props);
  1804 + if(info->size() > 0)
  1805 + size += srs_amf0_get_object_size(info);
  1806 +
  1807 + return size;
1780 } 1808 }
1781 1809
1782 int SrsConnectAppResPacket::encode_packet(SrsStream* stream) 1810 int SrsConnectAppResPacket::encode_packet(SrsStream* stream)
@@ -1795,16 +1823,22 @@ int SrsConnectAppResPacket::encode_packet(SrsStream* stream) @@ -1795,16 +1823,22 @@ int SrsConnectAppResPacket::encode_packet(SrsStream* stream)
1795 } 1823 }
1796 srs_verbose("encode transaction_id success."); 1824 srs_verbose("encode transaction_id success.");
1797 1825
1798 - if ((ret = srs_amf0_write_object(stream, props)) != ERROR_SUCCESS) {  
1799 - srs_error("encode props failed. ret=%d", ret);  
1800 - return ret;  
1801 - } 1826 + if(props->size() > 0){
  1827 + if ((ret = srs_amf0_write_object(stream, props)) != ERROR_SUCCESS) {
  1828 + srs_error("encode props failed. ret=%d", ret);
  1829 + return ret;
  1830 + }
  1831 + }
  1832 +
1802 srs_verbose("encode props success."); 1833 srs_verbose("encode props success.");
1803 1834
1804 - if ((ret = srs_amf0_write_object(stream, info)) != ERROR_SUCCESS) {  
1805 - srs_error("encode info failed. ret=%d", ret);  
1806 - return ret;  
1807 - } 1835 + if(info->size() > 0){
  1836 + if ((ret = srs_amf0_write_object(stream, info)) != ERROR_SUCCESS) {
  1837 + srs_error("encode info failed. ret=%d", ret);
  1838 + return ret;
  1839 + }
  1840 + }
  1841 +
1808 srs_verbose("encode info success."); 1842 srs_verbose("encode info success.");
1809 1843
1810 srs_info("encode connect app response packet success."); 1844 srs_info("encode connect app response packet success.");
@@ -2537,7 +2571,31 @@ SrsOnStatusCallPacket::SrsOnStatusCallPacket() @@ -2537,7 +2571,31 @@ SrsOnStatusCallPacket::SrsOnStatusCallPacket()
2537 SrsOnStatusCallPacket::~SrsOnStatusCallPacket() 2571 SrsOnStatusCallPacket::~SrsOnStatusCallPacket()
2538 { 2572 {
2539 srs_freep(args); 2573 srs_freep(args);
2540 - srs_freep(data); 2574 + srs_freep(data);
  2575 +}
  2576 +
  2577 +int SrsOnStatusCallPacket::decode(SrsStream *stream)
  2578 +{
  2579 + int ret = ERROR_SUCCESS;
  2580 +
  2581 + if ((ret = srs_amf0_read_string(stream, command_name)) != ERROR_SUCCESS) {
  2582 + srs_error("amf0 decode play command_name failed. ret=%d", ret);
  2583 + return ret;
  2584 + }
  2585 +
  2586 + if ((ret = srs_amf0_read_number(stream, transaction_id)) != ERROR_SUCCESS) {
  2587 + srs_error("amf0 decode play transaction_id failed. ret=%d", ret);
  2588 + return ret;
  2589 + }
  2590 +
  2591 + if ((ret = srs_amf0_read_null(stream)) != ERROR_SUCCESS) {
  2592 + srs_error("amf0 decode play command_object failed. ret=%d", ret);
  2593 + return ret;
  2594 + }
  2595 +
  2596 + srs_info("decode SrsOnStatusCallPacket success.");
  2597 +
  2598 + return ret;
2541 } 2599 }
2542 2600
2543 int SrsOnStatusCallPacket::get_perfer_cid() 2601 int SrsOnStatusCallPacket::get_perfer_cid()
@@ -2853,6 +2911,14 @@ SrsAcknowledgementPacket::~SrsAcknowledgementPacket() @@ -2853,6 +2911,14 @@ SrsAcknowledgementPacket::~SrsAcknowledgementPacket()
2853 { 2911 {
2854 } 2912 }
2855 2913
  2914 +int SrsAcknowledgementPacket::decode(SrsStream *stream)
  2915 +{
  2916 + int ret = ERROR_SUCCESS;
  2917 + ret = sequence_number = stream->read_4bytes();
  2918 +
  2919 + return ret;
  2920 +}
  2921 +
2856 int SrsAcknowledgementPacket::get_perfer_cid() 2922 int SrsAcknowledgementPacket::get_perfer_cid()
2857 { 2923 {
2858 return RTMP_CID_ProtocolControl; 2924 return RTMP_CID_ProtocolControl;
@@ -3078,4 +3144,3 @@ int SrsUserControlPacket::encode_packet(SrsStream* stream) @@ -3078,4 +3144,3 @@ int SrsUserControlPacket::encode_packet(SrsStream* stream)
3078 3144
3079 return ret; 3145 return ret;
3080 } 3146 }
3081 -  
@@ -220,6 +220,7 @@ struct SrsMessageHeader @@ -220,6 +220,7 @@ struct SrsMessageHeader
220 bool is_window_ackledgement_size(); 220 bool is_window_ackledgement_size();
221 bool is_set_chunk_size(); 221 bool is_set_chunk_size();
222 bool is_user_control_message(); 222 bool is_user_control_message();
  223 + bool is_windows_ackledgement();
223 }; 224 };
224 225
225 /** 226 /**
@@ -801,6 +802,26 @@ protected: @@ -801,6 +802,26 @@ protected:
801 virtual int encode_packet(SrsStream* stream); 802 virtual int encode_packet(SrsStream* stream);
802 }; 803 };
803 804
  805 +
  806 +/**
  807 +* band width check method name, which will be invoked by client.
  808 +* band width check mothods use SrsOnStatusCallPacket as its internal packet type,
  809 +* so ensure you set command name when you use it.
  810 +*/
  811 +// for play
  812 +#define SRS_BW_CHECK_START_PLAY "onSrsBandCheckStartPlayBytes"
  813 +#define SRS_BW_CHECK_STARTING_PLAY "onSrsBandCheckStartingPlayBytes"
  814 +#define SRS_BW_CHECK_STOP_PLAY "onSrsBandCheckStopPlayBytes"
  815 +#define SRS_BW_CHECK_STOPPED_PLAY "onSrsBandCheckStoppedPlayBytes"
  816 +#define SRS_BW_CHECK_PLAYING "onSrsBandCheckPlaying"
  817 +
  818 +// for publish
  819 +#define SRS_BW_CHECK_START_PUBLISH "onSrsBandCheckStartPublishBytes"
  820 +#define SRS_BW_CHECK_STARTING_PUBLISH "onSrsBandCheckStartingPublishBytes"
  821 +#define SRS_BW_CHECK_STOP_PUBLISH "onSrsBandCheckStopPublishBytes"
  822 +#define SRS_BW_CHECK_FINISHED "onSrsBandCheckFinished"
  823 +#define SRS_BW_CHECK_PUBLISHING "onSrsBandCheckPublishing"
  824 +
804 /** 825 /**
805 * onStatus command, AMF0 Call 826 * onStatus command, AMF0 Call
806 * @remark, user must set the stream_id by SrsMessage.set_packet(). 827 * @remark, user must set the stream_id by SrsMessage.set_packet().
@@ -822,6 +843,10 @@ public: @@ -822,6 +843,10 @@ public:
822 public: 843 public:
823 SrsOnStatusCallPacket(); 844 SrsOnStatusCallPacket();
824 virtual ~SrsOnStatusCallPacket(); 845 virtual ~SrsOnStatusCallPacket();
  846 +
  847 +public:
  848 + virtual int decode(SrsStream* stream);
  849 +
825 public: 850 public:
826 virtual int get_perfer_cid(); 851 virtual int get_perfer_cid();
827 public: 852 public:
@@ -968,6 +993,10 @@ public: @@ -968,6 +993,10 @@ public:
968 public: 993 public:
969 SrsAcknowledgementPacket(); 994 SrsAcknowledgementPacket();
970 virtual ~SrsAcknowledgementPacket(); 995 virtual ~SrsAcknowledgementPacket();
  996 +
  997 +public:
  998 + virtual int decode(SrsStream *stream);
  999 +
971 public: 1000 public:
972 virtual int get_perfer_cid(); 1001 virtual int get_perfer_cid();
973 public: 1002 public:
@@ -1141,4 +1170,4 @@ int srs_rtmp_expect_message(SrsProtocol* protocol, SrsCommonMessage** pmsg, T** @@ -1141,4 +1170,4 @@ int srs_rtmp_expect_message(SrsProtocol* protocol, SrsCommonMessage** pmsg, T**
1141 return ret; 1170 return ret;
1142 } 1171 }
1143 1172
1144 -#endif  
  1173 +#endif
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 The MIT License (MIT) 2 The MIT License (MIT)
3 3
4 Copyright (c) 2013 winlin 4 Copyright (c) 2013 winlin
  5 +Copyright (c) 2013 wenjiejit
5 6
6 Permission is hereby granted, free of charge, to any person obtaining a copy of 7 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 this software and associated documentation files (the "Software"), to deal in
@@ -49,8 +50,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -49,8 +50,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49 #define StatusClientId "clientid" 50 #define StatusClientId "clientid"
50 // status value 51 // status value
51 #define StatusLevelStatus "status" 52 #define StatusLevelStatus "status"
  53 +// status error
  54 +#define StatusLevelError "error"
52 // code value 55 // code value
53 #define StatusCodeConnectSuccess "NetConnection.Connect.Success" 56 #define StatusCodeConnectSuccess "NetConnection.Connect.Success"
  57 +#define StatusCodeConnectRejected "NetConnection.Connect.Rejected"
54 #define StatusCodeStreamReset "NetStream.Play.Reset" 58 #define StatusCodeStreamReset "NetStream.Play.Reset"
55 #define StatusCodeStreamStart "NetStream.Play.Start" 59 #define StatusCodeStreamStart "NetStream.Play.Start"
56 #define StatusCodeStreamPause "NetStream.Pause.Notify" 60 #define StatusCodeStreamPause "NetStream.Pause.Notify"
@@ -67,8 +71,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -67,8 +71,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
67 #define SRS_DEFAULT_SID 1 71 #define SRS_DEFAULT_SID 1
68 72
69 SrsRequest::SrsRequest() 73 SrsRequest::SrsRequest()
  74 + : objectEncoding(RTMP_SIG_AMF0_VER)
70 { 75 {
71 - objectEncoding = RTMP_SIG_AMF0_VER;  
72 } 76 }
73 77
74 SrsRequest::~SrsRequest() 78 SrsRequest::~SrsRequest()
@@ -99,11 +103,23 @@ int SrsRequest::discovery_app() @@ -99,11 +103,23 @@ int SrsRequest::discovery_app()
99 port = vhost.substr(pos + 1); 103 port = vhost.substr(pos + 1);
100 vhost = vhost.substr(0, pos); 104 vhost = vhost.substr(0, pos);
101 srs_verbose("discovery vhost=%s, port=%s", vhost.c_str(), port.c_str()); 105 srs_verbose("discovery vhost=%s, port=%s", vhost.c_str(), port.c_str());
102 - }  
103 - 106 + }
  107 +
104 app = url; 108 app = url;
105 srs_vhost_resolve(vhost, app); 109 srs_vhost_resolve(vhost, app);
106 - 110 +
  111 + // reslove bw check key
  112 + std::string app_str = url;
  113 + if ((pos = app_str.find("key=")) != std::string::npos){
  114 + std::string temp_key = app_str.substr(pos + strlen("key="));
  115 + for(unsigned int i = 0; i < temp_key.size(); ++i){
  116 + char c = temp_key[i];
  117 + if(c != '&')
  118 + bw_key.push_back(c);
  119 + else break;
  120 + }
  121 + }
  122 +
107 // resolve the vhost from config 123 // resolve the vhost from config
108 SrsConfDirective* parsed_vhost = config->get_vhost(vhost); 124 SrsConfDirective* parsed_vhost = config->get_vhost(vhost);
109 if (parsed_vhost) { 125 if (parsed_vhost) {
@@ -238,7 +254,7 @@ int SrsRtmpClient::handshake() @@ -238,7 +254,7 @@ int SrsRtmpClient::handshake()
238 return ret; 254 return ret;
239 } 255 }
240 256
241 -int SrsRtmpClient::connect_app(std::string app, std::string tc_url) 257 +int SrsRtmpClient::connect_app(const std::string &app, const std::string &tc_url)
242 { 258 {
243 int ret = ERROR_SUCCESS; 259 int ret = ERROR_SUCCESS;
244 260
@@ -324,7 +340,7 @@ int SrsRtmpClient::create_stream(int& stream_id) @@ -324,7 +340,7 @@ int SrsRtmpClient::create_stream(int& stream_id)
324 return ret; 340 return ret;
325 } 341 }
326 342
327 -int SrsRtmpClient::play(std::string stream, int stream_id) 343 +int SrsRtmpClient::play(const std::string &stream, int stream_id)
328 { 344 {
329 int ret = ERROR_SUCCESS; 345 int ret = ERROR_SUCCESS;
330 346
@@ -366,7 +382,7 @@ int SrsRtmpClient::play(std::string stream, int stream_id) @@ -366,7 +382,7 @@ int SrsRtmpClient::play(std::string stream, int stream_id)
366 return ret; 382 return ret;
367 } 383 }
368 384
369 -int SrsRtmpClient::publish(std::string stream, int stream_id) 385 +int SrsRtmpClient::publish(const std::string &stream, int stream_id)
370 { 386 {
371 int ret = ERROR_SUCCESS; 387 int ret = ERROR_SUCCESS;
372 388
@@ -544,7 +560,7 @@ int SrsRtmp::set_peer_bandwidth(int bandwidth, int type) @@ -544,7 +560,7 @@ int SrsRtmp::set_peer_bandwidth(int bandwidth, int type)
544 return ret; 560 return ret;
545 } 561 }
546 562
547 -int SrsRtmp::response_connect_app(SrsRequest* req) 563 +int SrsRtmp::response_connect_app(SrsRequest *req, const char *ip)
548 { 564 {
549 int ret = ERROR_SUCCESS; 565 int ret = ERROR_SUCCESS;
550 566
@@ -556,7 +572,7 @@ int SrsRtmp::response_connect_app(SrsRequest* req) @@ -556,7 +572,7 @@ int SrsRtmp::response_connect_app(SrsRequest* req)
556 pkt->props->set("mode", new SrsAmf0Number(1)); 572 pkt->props->set("mode", new SrsAmf0Number(1));
557 573
558 pkt->info->set(StatusLevel, new SrsAmf0String(StatusLevelStatus)); 574 pkt->info->set(StatusLevel, new SrsAmf0String(StatusLevelStatus));
559 - pkt->info->set(StatusCode, new SrsAmf0String(StatusCodeConnectSuccess)); 575 + pkt->info->set(StatusCode, new SrsAmf0String(StatusCodeConnectSuccess));
560 pkt->info->set(StatusDescription, new SrsAmf0String("Connection succeeded")); 576 pkt->info->set(StatusDescription, new SrsAmf0String("Connection succeeded"));
561 pkt->info->set("objectEncoding", new SrsAmf0Number(req->objectEncoding)); 577 pkt->info->set("objectEncoding", new SrsAmf0Number(req->objectEncoding));
562 SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray(); 578 SrsASrsAmf0EcmaArray* data = new SrsASrsAmf0EcmaArray();
@@ -571,6 +587,9 @@ int SrsRtmp::response_connect_app(SrsRequest* req) @@ -571,6 +587,9 @@ int SrsRtmp::response_connect_app(SrsRequest* req)
571 data->set("srs_site", new SrsAmf0String(RTMP_SIG_SRS_WEB)); 587 data->set("srs_site", new SrsAmf0String(RTMP_SIG_SRS_WEB));
572 data->set("srs_email", new SrsAmf0String(RTMP_SIG_SRS_EMAIL)); 588 data->set("srs_email", new SrsAmf0String(RTMP_SIG_SRS_EMAIL));
573 data->set("srs_copyright", new SrsAmf0String(RTMP_SIG_SRS_COPYRIGHT)); 589 data->set("srs_copyright", new SrsAmf0String(RTMP_SIG_SRS_COPYRIGHT));
  590 +
  591 + if(ip)
  592 + data->set("srs_server_ip", new SrsAmf0String(ip));
574 593
575 msg->set_packet(pkt, 0); 594 msg->set_packet(pkt, 0);
576 595
@@ -580,7 +599,30 @@ int SrsRtmp::response_connect_app(SrsRequest* req) @@ -580,7 +599,30 @@ int SrsRtmp::response_connect_app(SrsRequest* req)
580 } 599 }
581 srs_info("send connect app response message success."); 600 srs_info("send connect app response message success.");
582 601
583 - return ret; 602 + return ret;
  603 +}
  604 +
  605 +int SrsRtmp::response_connect_reject(SrsRequest *req, const std::string &description)
  606 +{
  607 + int ret = ERROR_SUCCESS;
  608 +
  609 + SrsCommonMessage* msg = new SrsCommonMessage();
  610 + SrsConnectAppResPacket* pkt = new SrsConnectAppResPacket();
  611 + pkt->command_name = "_error";
  612 + pkt->props->set(StatusLevel, new SrsAmf0String(StatusLevelError));
  613 + pkt->props->set(StatusCode, new SrsAmf0String(StatusCodeConnectRejected));
  614 + pkt->props->set(StatusDescription, new SrsAmf0String(description.c_str()));
  615 + //pkt->props->set("objectEncoding", new SrsAmf0Number(req->objectEncoding));
  616 +
  617 + msg->set_packet(pkt, 0);
  618 +
  619 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  620 + srs_error("send connect app response rejected message failed. ret=%d", ret);
  621 + return ret;
  622 + }
  623 + srs_info("send connect app response rejected message success.");
  624 +
  625 + return ret;
584 } 626 }
585 627
586 int SrsRtmp::on_bw_done() 628 int SrsRtmp::on_bw_done()
@@ -1029,7 +1071,60 @@ int SrsRtmp::start_flash_publish(int stream_id) @@ -1029,7 +1071,60 @@ int SrsRtmp::start_flash_publish(int stream_id)
1029 1071
1030 srs_info("flash publish success."); 1072 srs_info("flash publish success.");
1031 1073
1032 - return ret; 1074 + return ret;
  1075 +}
  1076 +
  1077 +int SrsRtmp::start_bandwidth_check(int max_play_kbps, int max_pub_kbps)
  1078 +{
  1079 + int ret = ERROR_SUCCESS;
  1080 +
  1081 + int play_duration_ms = 3000;
  1082 + int play_interval_ms = 0;
  1083 + int play_actual_duration_ms = 0;
  1084 + int play_bytes = 0;
  1085 +
  1086 + int publish_duration_ms = 3000;
  1087 + int publish_interval_ms = 0;
  1088 + int publish_actual_duration_ms = 0;
  1089 + int publish_bytes = 0;
  1090 +
  1091 + int64_t start_time = srs_get_system_time_ms();
  1092 + if((ret = bandwidth_check_play(play_duration_ms, play_interval_ms,
  1093 + play_actual_duration_ms, play_bytes, max_play_kbps) != ERROR_SUCCESS)
  1094 + || (ret = bandwidth_check_publish(publish_duration_ms, publish_interval_ms,
  1095 + publish_actual_duration_ms, publish_bytes, max_pub_kbps)) != ERROR_SUCCESS)
  1096 + {
  1097 + srs_error("band width check failed. ret = %d", ret);
  1098 +
  1099 + return ret;
  1100 + }
  1101 +
  1102 + int64_t end_time = srs_get_system_time_ms();
  1103 + int play_kbps = play_bytes * 8 / play_actual_duration_ms;
  1104 + int publish_kbps = publish_bytes * 8 / publish_actual_duration_ms;
  1105 +
  1106 + // send finished msg
  1107 + SrsCommonMessage* finish_msg = new SrsCommonMessage();
  1108 + SrsOnStatusCallPacket* finish_pkt = new SrsOnStatusCallPacket;
  1109 + finish_pkt->command_name = SRS_BW_CHECK_FINISHED;
  1110 + finish_pkt->data->set("code", new SrsAmf0Number(0));
  1111 + finish_pkt->data->set("start_time", new SrsAmf0Number(start_time));
  1112 + finish_pkt->data->set("end_time", new SrsAmf0Number(end_time));
  1113 + finish_pkt->data->set("play_kbps", new SrsAmf0Number(play_kbps));
  1114 + finish_pkt->data->set("publish_kbps", new SrsAmf0Number(publish_kbps));
  1115 + finish_pkt->data->set("play_bytes", new SrsAmf0Number(play_bytes));
  1116 + finish_pkt->data->set("play_time", new SrsAmf0Number(play_actual_duration_ms));
  1117 + finish_pkt->data->set("publish_bytes", new SrsAmf0Number(publish_bytes));
  1118 + finish_pkt->data->set("publish_time", new SrsAmf0Number(publish_actual_duration_ms));
  1119 +
  1120 + finish_msg->set_packet(finish_pkt, 0);
  1121 + if ((ret = protocol->send_message(finish_msg)) != ERROR_SUCCESS) {
  1122 + srs_error("send bandwidth check finish message failed. ret=%d", ret);
  1123 + return ret;
  1124 + }
  1125 + srs_trace("BW check finished.");
  1126 +
  1127 + return ret;
1033 } 1128 }
1034 1129
1035 int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name) 1130 int SrsRtmp::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name)
@@ -1120,6 +1215,221 @@ int SrsRtmp::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& @@ -1120,6 +1215,221 @@ int SrsRtmp::identify_flash_publish_client(SrsPublishPacket* req, SrsClientType&
1120 type = SrsClientFlashPublish; 1215 type = SrsClientFlashPublish;
1121 stream_name = req->stream_name; 1216 stream_name = req->stream_name;
1122 1217
1123 - return ret; 1218 + return ret;
  1219 +}
  1220 +
  1221 +int SrsRtmp::bandwidth_check_play(int duration_ms, int interval_ms, int &actual_duration_ms,
  1222 + int &play_bytes, int max_play_kbps)
  1223 +{
  1224 + int ret = ERROR_SUCCESS;
  1225 +
  1226 + // send start play command to client
  1227 + SrsCommonMessage* start_play_msg = new SrsCommonMessage();
  1228 + SrsOnStatusCallPacket* start_play_packet = new SrsOnStatusCallPacket;
  1229 + start_play_packet->command_name = SRS_BW_CHECK_START_PLAY;
  1230 + start_play_packet->data->set("duration_ms", new SrsAmf0Number(duration_ms));
  1231 + start_play_packet->data->set("interval_ms", new SrsAmf0Number(interval_ms));
  1232 +
  1233 + start_play_msg->set_packet(start_play_packet, 0);
  1234 + if ((ret = protocol->send_message(start_play_msg)) != ERROR_SUCCESS) {
  1235 + srs_error("send bandwidth check start play message failed. ret=%d", ret);
  1236 + return ret;
  1237 + }
  1238 + srs_trace("BW check begin.");
  1239 +
  1240 + // recv client's starting play response
  1241 + while (true) {
  1242 + SrsCommonMessage* msg = 0;
  1243 + if( (ret = protocol->recv_message(&msg)) != ERROR_SUCCESS)
  1244 + {
  1245 + srs_error("recv client's starting play response failed. ret= %d", ret);
  1246 + return ret;
  1247 + }
  1248 +
  1249 + msg->decode_packet(protocol);
  1250 + SrsOnStatusCallPacket* pkt = dynamic_cast<SrsOnStatusCallPacket*>(msg->get_packet());
  1251 + if(pkt && (pkt->command_name == SRS_BW_CHECK_STARTING_PLAY))
  1252 + break;
  1253 + }
  1254 + srs_trace("BW check recv play begin response.");
  1255 +
  1256 + // send play data to client
  1257 + int64_t current_Time = srs_get_system_time_ms();
  1258 + int size = 1024*4; // 32KB
  1259 + char random_data[size];
  1260 + memset(random_data, 0x01, size);
  1261 +
  1262 + int64_t last_time = current_Time;
  1263 + int interval = 0;
  1264 + while ( (srs_get_system_time_ms() - current_Time) < duration_ms ){
  1265 + st_usleep(interval);
  1266 + SrsCommonMessage* msg = new SrsCommonMessage;
  1267 + SrsOnStatusCallPacket* pkt = new SrsOnStatusCallPacket;
  1268 + pkt->command_name = SRS_BW_CHECK_PLAYING;
  1269 +
  1270 + for(int i = 0; i < 10; ++i)
  1271 + {
  1272 + char buf[32];
  1273 + sprintf(buf, "%d", i);
  1274 + pkt->data->set(buf, new SrsAmf0String(random_data));
  1275 + }
  1276 + msg->set_packet(pkt, 0);
  1277 +
  1278 + play_bytes += pkt->get_payload_length();
  1279 +
  1280 + if ((ret = protocol->send_message(msg)) != ERROR_SUCCESS) {
  1281 + srs_error("send bandwidth check play messages failed. ret=%d", ret);
  1282 + return ret;
  1283 + }
  1284 +
  1285 + if((srs_get_system_time_ms() - last_time) > 5){ // check kbps every 5 ms;
  1286 + int kbps = play_bytes * 8 / (srs_get_system_time_ms() - current_Time);
  1287 + if(kbps > max_play_kbps){
  1288 + interval += 1000*3; // 2 ms
  1289 + } else {
  1290 + interval -= 1000*3;
  1291 + if(interval < 0)
  1292 + interval = 0;
  1293 + }
  1294 + }
  1295 + }
  1296 + actual_duration_ms = srs_get_system_time_ms() - current_Time;
  1297 + srs_trace("BW check send play bytes over.");
  1298 +
  1299 + // notify client to stop play
  1300 + SrsCommonMessage* stop_play_msg = new SrsCommonMessage;
  1301 + SrsOnStatusCallPacket* stop_play_pkt = new SrsOnStatusCallPacket;
  1302 + stop_play_pkt->command_name = SRS_BW_CHECK_STOP_PLAY;
  1303 + stop_play_pkt->data->set("duration_ms", new SrsAmf0Number(duration_ms));
  1304 + stop_play_pkt->data->set("interval_ms", new SrsAmf0Number(interval_ms));
  1305 + stop_play_pkt->data->set("duration_delta", new SrsAmf0Number(actual_duration_ms));
  1306 + stop_play_pkt->data->set("bytes_delta", new SrsAmf0Number(play_bytes));
  1307 +
  1308 + stop_play_msg->set_packet(stop_play_pkt, 0);
  1309 +
  1310 + if ((ret = protocol->send_message(stop_play_msg)) != ERROR_SUCCESS) {
  1311 + srs_error("send bandwidth check stop play message failed. ret=%d", ret);
  1312 + return ret;
  1313 + }
  1314 + srs_trace("BW check stop play bytes.");
  1315 +
  1316 + // recv client's stop play response.
  1317 + while (true) {
  1318 + SrsCommonMessage* msg = 0;
  1319 + if((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS)
  1320 + {
  1321 + srs_error("recv client's stop play response failed. ret = %d", ret);
  1322 + return ret;
  1323 + }
  1324 +
  1325 + msg->decode_packet(protocol);
  1326 + SrsOnStatusCallPacket* pkt = dynamic_cast<SrsOnStatusCallPacket*>(msg->get_packet());
  1327 + if(pkt && (pkt->command_name == SRS_BW_CHECK_STOPPED_PLAY))
  1328 + break;
  1329 + }
  1330 + srs_trace("BW check recv stop play response.");
  1331 +
  1332 + return ret;
  1333 +}
  1334 +
  1335 +int SrsRtmp::bandwidth_check_publish(int duration_ms, int interval_ms, int &actual_duration_ms,
  1336 + int &publish_bytes, int max_pub_kbps)
  1337 +{
  1338 + int ret = ERROR_SUCCESS;
  1339 +
  1340 + // notify client to start publish
  1341 + SrsCommonMessage* start_publish_msg = new SrsCommonMessage;
  1342 + SrsOnStatusCallPacket* start_publish_pkt = new SrsOnStatusCallPacket;
  1343 + start_publish_pkt->command_name = SRS_BW_CHECK_START_PUBLISH;
  1344 + start_publish_pkt->data->set("duration_ms", new SrsAmf0Number(duration_ms));
  1345 + start_publish_pkt->data->set("interval_ms", new SrsAmf0Number(interval_ms));
  1346 +
  1347 + start_publish_msg->set_packet(start_publish_pkt, 0);
  1348 + if ((ret = protocol->send_message(start_publish_msg)) != ERROR_SUCCESS) {
  1349 + srs_error("send bandwidth check start publish message failed. ret=%d", ret);
  1350 + return ret;
  1351 + }
  1352 + srs_trace("BW check publish begin.");
  1353 +
  1354 + // read client's notification of starting publish
  1355 + while (true) {
  1356 + SrsCommonMessage* msg = 0;
  1357 + if((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS)
  1358 + {
  1359 + srs_error("recv client's notification of starting publish failed. ret = %d", ret);
  1360 + return ret;
  1361 + }
  1362 +
  1363 + msg->decode_packet(protocol);
  1364 + SrsOnStatusCallPacket* pkt = dynamic_cast<SrsOnStatusCallPacket*>(msg->get_packet());
  1365 + if(pkt && (pkt->command_name == SRS_BW_CHECK_STARTING_PUBLISH))
  1366 + break;
  1367 + }
  1368 + srs_trace("BW check recv publish begin response.");
  1369 +
  1370 + // recv publish msgs until @duration_ms ms
  1371 + int64_t current_time = srs_get_system_time_ms();
  1372 + int64_t last_time = current_time;
  1373 + int interval = 0;
  1374 +
  1375 + while( (srs_get_system_time_ms() - current_time) < duration_ms )
  1376 + {
  1377 + st_usleep(interval);
  1378 + SrsCommonMessage* msg = NULL;
  1379 + if ((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS) {
  1380 + srs_error("recv message failed. ret=%d", ret);
  1381 + return ret;
  1382 + }
  1383 + SrsAutoFree(SrsCommonMessage, msg, false);
  1384 +
  1385 + publish_bytes += msg->header.payload_length;
  1386 +
  1387 + if((srs_get_system_time_ms() - last_time) > 5){ // check kbps every 5 ms;
  1388 + int kbps = publish_bytes * 8 / (srs_get_system_time_ms() - current_time);
  1389 + if(kbps > max_pub_kbps){
  1390 + interval += 1000*3; // 2 ms
  1391 + } else {
  1392 + interval -= 1000*3;
  1393 + if(interval < 0)
  1394 + interval = 0;
  1395 + }
  1396 + }
  1397 + }
  1398 + actual_duration_ms = srs_get_system_time_ms() - current_time;
  1399 + srs_trace("BW check recv publish data over.");
  1400 +
  1401 + // notify client to stop publish
  1402 + SrsCommonMessage* stop_publish_msg = new SrsCommonMessage;
  1403 + SrsOnStatusCallPacket* stop_publish_pkt = new SrsOnStatusCallPacket;
  1404 + stop_publish_pkt->command_name = SRS_BW_CHECK_STOP_PUBLISH;
  1405 + stop_publish_pkt->data->set("duration_ms", new SrsAmf0Number(duration_ms));
  1406 + stop_publish_pkt->data->set("interval_ms", new SrsAmf0Number(interval_ms));
  1407 + stop_publish_pkt->data->set("duration_delta", new SrsAmf0Number(actual_duration_ms));
  1408 + stop_publish_pkt->data->set("bytes_delta", new SrsAmf0Number(publish_bytes));
  1409 +
  1410 + stop_publish_msg->set_packet(stop_publish_pkt, 0);
  1411 + if ((ret = protocol->send_message(stop_publish_msg)) != ERROR_SUCCESS) {
  1412 + srs_error("send bandwidth check stop publish message failed. ret=%d", ret);
  1413 + return ret;
  1414 + }
  1415 + srs_trace("BW check stop pulish.");
  1416 +
  1417 + // recv left msg
  1418 + while (true) {
  1419 + if((ret = st_netfd_poll(stfd, POLLIN, 1000*500)) == ERROR_SUCCESS)
  1420 + {
  1421 + SrsCommonMessage* msg = 0;
  1422 + if((ret = protocol->recv_message(&msg)) != ERROR_SUCCESS)
  1423 + {
  1424 + srs_error("recv client's left msg failed, ret = %d", ret);
  1425 + return ret;
  1426 + }
  1427 + } else {
  1428 + ret = ERROR_SUCCESS;
  1429 + break;
  1430 + }
  1431 + }
  1432 +
  1433 + return ret;
1124 } 1434 }
1125 1435
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 The MIT License (MIT) 2 The MIT License (MIT)
3 3
4 Copyright (c) 2013 winlin 4 Copyright (c) 2013 winlin
  5 +Copyright (c) 2013 wenjiegit
5 6
6 Permission is hereby granted, free of charge, to any person obtaining a copy of 7 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 this software and associated documentation files (the "Software"), to deal in
@@ -64,6 +65,7 @@ struct SrsRequest @@ -64,6 +65,7 @@ struct SrsRequest
64 std::string port; 65 std::string port;
65 std::string app; 66 std::string app;
66 std::string stream; 67 std::string stream;
  68 + std::string bw_key;
67 69
68 SrsRequest(); 70 SrsRequest();
69 virtual ~SrsRequest(); 71 virtual ~SrsRequest();
@@ -97,7 +99,7 @@ enum SrsClientType @@ -97,7 +99,7 @@ enum SrsClientType
97 SrsClientUnknown, 99 SrsClientUnknown,
98 SrsClientPlay, 100 SrsClientPlay,
99 SrsClientFMLEPublish, 101 SrsClientFMLEPublish,
100 - SrsClientFlashPublish, 102 + SrsClientFlashPublish
101 }; 103 };
102 104
103 /** 105 /**
@@ -122,10 +124,10 @@ public: @@ -122,10 +124,10 @@ public:
122 virtual int send_message(ISrsMessage* msg); 124 virtual int send_message(ISrsMessage* msg);
123 public: 125 public:
124 virtual int handshake(); 126 virtual int handshake();
125 - virtual int connect_app(std::string app, std::string tc_url); 127 + virtual int connect_app(const std::string &app, const std::string &tc_url);
126 virtual int create_stream(int& stream_id); 128 virtual int create_stream(int& stream_id);
127 - virtual int play(std::string stream, int stream_id);  
128 - virtual int publish(std::string stream, int stream_id); 129 + virtual int play(const std::string &stream, int stream_id);
  130 + virtual int publish(const std::string &stream, int stream_id);
129 }; 131 };
130 132
131 /** 133 /**
@@ -161,7 +163,8 @@ public: @@ -161,7 +163,8 @@ public:
161 * using the Limit type field. 163 * using the Limit type field.
162 */ 164 */
163 virtual int set_peer_bandwidth(int bandwidth, int type); 165 virtual int set_peer_bandwidth(int bandwidth, int type);
164 - virtual int response_connect_app(SrsRequest* req); 166 + virtual int response_connect_app(SrsRequest* req, const char *ip = 0);
  167 + virtual int response_connect_reject(SrsRequest* req, const std::string& description);
165 virtual int on_bw_done(); 168 virtual int on_bw_done();
166 /** 169 /**
167 * recv some message to identify the client. 170 * recv some message to identify the client.
@@ -212,10 +215,18 @@ public: @@ -212,10 +215,18 @@ public:
212 * onStatus(NetStream.Publish.Start) 215 * onStatus(NetStream.Publish.Start)
213 */ 216 */
214 virtual int start_flash_publish(int stream_id); 217 virtual int start_flash_publish(int stream_id);
  218 +
  219 + /**
  220 + * used to process band width check from client.
  221 + */
  222 + virtual int start_bandwidth_check(int max_play_kbps, int max_pub_kbps);
  223 +
215 private: 224 private:
216 virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name); 225 virtual int identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsClientType& type, std::string& stream_name);
217 virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name); 226 virtual int identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsClientType& type, std::string& stream_name);
218 virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name); 227 virtual int identify_flash_publish_client(SrsPublishPacket* req, SrsClientType& type, std::string& stream_name);
  228 + virtual int bandwidth_check_play(int duration_ms, int interval_ms, int& actual_duration_ms, int& play_bytes, int max_play_kbps);
  229 + virtual int bandwidth_check_publish(int duration_ms, int interval_ms, int& actual_duration_ms, int& publish_bytes, int max_pub_kbps);
219 }; 230 };
220 231
221 -#endif  
  232 +#endif
@@ -144,14 +144,14 @@ void SrsListener::listen_cycle() @@ -144,14 +144,14 @@ void SrsListener::listen_cycle()
144 // ignore error. 144 // ignore error.
145 srs_warn("ignore accept thread stoppped for accept client error"); 145 srs_warn("ignore accept thread stoppped for accept client error");
146 continue; 146 continue;
147 - } 147 + }
148 srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd)); 148 srs_verbose("get a client. fd=%d", st_netfd_fileno(client_stfd));
149 149
150 if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) { 150 if ((ret = server->accept_client(type, client_stfd)) != ERROR_SUCCESS) {
151 srs_warn("accept client error. ret=%d", ret); 151 srs_warn("accept client error. ret=%d", ret);
152 continue; 152 continue;
153 } 153 }
154 - 154 +
155 srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret); 155 srs_verbose("accept client finished. conns=%d, ret=%d", (int)conns.size(), ret);
156 } 156 }
157 } 157 }
@@ -250,7 +250,7 @@ int SrsServer::cycle() @@ -250,7 +250,7 @@ int SrsServer::cycle()
250 // the deamon thread, update the time cache 250 // the deamon thread, update the time cache
251 while (true) { 251 while (true) {
252 st_usleep(SRS_TIME_RESOLUTION_MS * 1000); 252 st_usleep(SRS_TIME_RESOLUTION_MS * 1000);
253 - srs_update_system_time_ms(); 253 + srs_update_system_time_ms();
254 254
255 if (signal_reload) { 255 if (signal_reload) {
256 signal_reload = false; 256 signal_reload = false;
@@ -344,7 +344,7 @@ int SrsGopCache::dump(SrsConsumer* consumer, int tba, int tbv) @@ -344,7 +344,7 @@ int SrsGopCache::dump(SrsConsumer* consumer, int tba, int tbv)
344 344
345 std::map<std::string, SrsSource*> SrsSource::pool; 345 std::map<std::string, SrsSource*> SrsSource::pool;
346 346
347 -SrsSource* SrsSource::find(std::string stream_url) 347 +SrsSource* SrsSource::find(const std::string &stream_url)
348 { 348 {
349 if (pool.find(stream_url) == pool.end()) { 349 if (pool.find(stream_url) == pool.end()) {
350 pool[stream_url] = new SrsSource(stream_url); 350 pool[stream_url] = new SrsSource(stream_url);