mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 20:01:56 +00:00
Merge branch 'develop' into 3.0release.srt.dev
This commit is contained in:
commit
ed1a3aa37c
26 changed files with 424 additions and 84 deletions
4
.github/ISSUE_TEMPLATE
vendored
4
.github/ISSUE_TEMPLATE
vendored
|
@ -16,6 +16,10 @@ assignees: ''
|
||||||
```
|
```
|
||||||
xxxxxxxxxxxx
|
xxxxxxxxxxxx
|
||||||
```
|
```
|
||||||
|
1. SRS的配置如下(Config):
|
||||||
|
```
|
||||||
|
xxxxxxxxxxxx
|
||||||
|
```
|
||||||
|
|
||||||
**重现(Replay)**
|
**重现(Replay)**
|
||||||
|
|
||||||
|
|
41
README.md
41
README.md
|
@ -153,6 +153,11 @@ For previous versions, please read:
|
||||||
|
|
||||||
## V4 changes
|
## V4 changes
|
||||||
|
|
||||||
|
* v4.0, 2020-02-25, For [#1615][bug #1615], support default app(live) for vmix SRT. 4.0.9
|
||||||
|
* v4.0, 2020-02-21, For [#1598][bug #1598], support SLB health checking by TCP. 4.0.8
|
||||||
|
* v4.0, 2020-02-19, For [#1579][bug #1579], support rolling update of k8s. 4.0.7
|
||||||
|
* v4.0, 2020-02-18, For [#1579][bug #1579], support start/final wait for gracefully quit. 4.0.6
|
||||||
|
* v4.0, 2020-02-18, For [#1579][bug #1579], support gracefully quit and force to. 4.0.5
|
||||||
* v4.0, 2020-02-13, SRT supports detail config for [DynamicEncoding](https://github.com/runner365/srt_encoder). 4.0.4
|
* v4.0, 2020-02-13, SRT supports detail config for [DynamicEncoding](https://github.com/runner365/srt_encoder). 4.0.4
|
||||||
* v4.0, 2020-02-04, Update project code. 4.0.3
|
* v4.0, 2020-02-04, Update project code. 4.0.3
|
||||||
* v4.0, 2020-01-26, Allow use libsrt.so for SRT is MPL license. 4.0.2
|
* v4.0, 2020-01-26, Allow use libsrt.so for SRT is MPL license. 4.0.2
|
||||||
|
@ -160,6 +165,14 @@ For previous versions, please read:
|
||||||
|
|
||||||
## V3 changes
|
## V3 changes
|
||||||
|
|
||||||
|
* v3.0, 2020-02-21, For [#1598][bug #1598], support SLB health checking by TCP. 3.0.123
|
||||||
|
* v3.0, 2020-02-21, Fix bug for librtmp client ipv4/ipv6 socket. 3.0.122
|
||||||
|
* v3.0, 2020-02-18, For [#1579][bug #1579], support start/final wait for gracefully quit. 3.0.121
|
||||||
|
* v3.0, 2020-02-18, For [#1579][bug #1579], support force gracefully quit. 3.0.120
|
||||||
|
* v3.0, 2020-02-18, For [#1579][bug #1579], support gracefully quit. 3.0.119
|
||||||
|
* v3.0, 2020-02-17, For [#1601][bug #1601], flush async on_dvr/on_hls events before stop. 3.0.118
|
||||||
|
* <strong>v3.0, 2020-02-14, [3.0 beta1(3.0.117)][r3.0b1] released. 121964 lines.</strong>
|
||||||
|
* v3.0, 2020-02-14, For [#1595][bug #1595], migrating streaming from ossrs.net to r.ossrs.net. 3.0.117
|
||||||
* v3.0, 2020-02-05, For [#665][bug #665], fix HTTP-FLV reloading bug. 3.0.116
|
* v3.0, 2020-02-05, For [#665][bug #665], fix HTTP-FLV reloading bug. 3.0.116
|
||||||
* v3.0, 2020-02-05, For [#1592][bug #1592], fix terminal echo off by redirect process stdin. 3.0.115
|
* v3.0, 2020-02-05, For [#1592][bug #1592], fix terminal echo off by redirect process stdin. 3.0.115
|
||||||
* v3.0, 2020-02-04, For [#1186][bug #1186], refactor security check. 3.0.114
|
* v3.0, 2020-02-04, For [#1186][bug #1186], refactor security check. 3.0.114
|
||||||
|
@ -751,6 +764,7 @@ For previous versions, please read:
|
||||||
|
|
||||||
## Releases
|
## Releases
|
||||||
|
|
||||||
|
* 2020-02-14, [Release v3.0-b1][r3.0b1], 3.0 beta1, 3.0.117, 121964 lines.
|
||||||
* 2020-02-02, [Release v3.0-b0][r3.0b0], 3.0 beta0, 3.0.112, 121709 lines.
|
* 2020-02-02, [Release v3.0-b0][r3.0b0], 3.0 beta0, 3.0.112, 121709 lines.
|
||||||
* 2020-01-21, [Release v3.0-a9][r3.0a9], 3.0 alpha9, 3.0.105, 121577 lines.
|
* 2020-01-21, [Release v3.0-a9][r3.0a9], 3.0 alpha9, 3.0.105, 121577 lines.
|
||||||
* 2020-01-10, [Release v3.0-a8][r3.0a8], 3.0 alpha8, 3.0.97, 121555 lines.
|
* 2020-01-10, [Release v3.0-a8][r3.0a8], 3.0 alpha8, 3.0.97, 121555 lines.
|
||||||
|
@ -1100,21 +1114,20 @@ Remark:
|
||||||
|
|
||||||
There are two types of people that have contributed to the SRS project:
|
There are two types of people that have contributed to the SRS project:
|
||||||
|
|
||||||
* AUTHORS: Contribute important features. Names of all authors responsed in NetConnection.connect and metadata.
|
* Maintainers: Contribute and maintain important features. SRS always remembers and thanks you by writing your names in stream metadata.
|
||||||
* CONTRIBUTORS: Submit patches, report bugs, add translations, help answer newbie questions, and generally make SRS much better.
|
* [Contributors][authors]: Submit patches, report bugs, add translations, help answer newbie questions, and generally make SRS much better.
|
||||||
|
|
||||||
About all AUTHORS and CONTRIBUTORS, read [AUTHORS.txt][authors].
|
Maintainers of SRS project:
|
||||||
|
|
||||||
|
* [Winlin](https://github.com/winlinvip): All areas of streaming server and documents.
|
||||||
|
* [Wenjie](https://github.com/wenjiegit): The focus of his work is on the [HDS](https://github.com/simple-rtmp-server/srs/wiki/v2_CN_DeliveryHDS) module.
|
||||||
|
* [Runner365](https://github.com/runner365): The focus of his work is on the [SRT](https://github.com/simple-rtmp-server/srs/wiki/v4_CN_SRTWiki) module.
|
||||||
|
|
||||||
A big THANK YOU goes to:
|
A big THANK YOU goes to:
|
||||||
|
|
||||||
* All friends of SRS for [big supports][bigthanks].
|
* All friends of SRS for [big supports][bigthanks].
|
||||||
* Genes amd Mabbott for creating [st][st]([state-threads][st2]).
|
* Genes amd Mabbott for creating [st][st]([state-threads][st2]).
|
||||||
* Michael Talyanksy for introducing us to use st.
|
* [Michael Talyanksy](https://github.com/michaeltalyansky) for introducing ST to us.
|
||||||
* Roman Arutyunyan for creating [nginx-rtmp][nginx-rtmp] for SRS to refer to.
|
|
||||||
* Joyent for creating [http-parser][http-parser] for http-api for SRS.
|
|
||||||
* Igor Sysoev for creating [nginx][nginx] for SRS to refer to.
|
|
||||||
* [FFMPEG][FFMPEG] and [libx264][libx264] group for SRS to use as transcoder.
|
|
||||||
* Guido van Rossum for creating Python for api-server for SRS.
|
|
||||||
|
|
||||||
## Mirrors
|
## Mirrors
|
||||||
|
|
||||||
|
@ -1187,8 +1200,8 @@ Winlin
|
||||||
[authors]: https://github.com/ossrs/srs/blob/develop/AUTHORS.txt
|
[authors]: https://github.com/ossrs/srs/blob/develop/AUTHORS.txt
|
||||||
[bigthanks]: https://github.com/ossrs/srs/wiki/v1_CN_Product#bigthanks
|
[bigthanks]: https://github.com/ossrs/srs/wiki/v1_CN_Product#bigthanks
|
||||||
[st]: https://github.com/winlinvip/state-threads
|
[st]: https://github.com/winlinvip/state-threads
|
||||||
[st2]: http://sourceforge.net/projects/state-threads/
|
[st2]: https://github.com/ossrs/state-threads/tree/srs
|
||||||
[state-threads]: http://sourceforge.net/projects/state-threads/
|
[state-threads]: https://github.com/ossrs/state-threads/tree/srs
|
||||||
[nginx-rtmp]: https://github.com/arut/nginx-rtmp-module
|
[nginx-rtmp]: https://github.com/arut/nginx-rtmp-module
|
||||||
[http-parser]: https://github.com/joyent/http-parser
|
[http-parser]: https://github.com/joyent/http-parser
|
||||||
[nginx]: http://nginx.org/
|
[nginx]: http://nginx.org/
|
||||||
|
@ -1669,10 +1682,16 @@ Winlin
|
||||||
[bug #1186]: https://github.com/ossrs/srs/issues/1186
|
[bug #1186]: https://github.com/ossrs/srs/issues/1186
|
||||||
[bug #1592]: https://github.com/ossrs/srs/issues/1592
|
[bug #1592]: https://github.com/ossrs/srs/issues/1592
|
||||||
[bug #665]: https://github.com/ossrs/srs/issues/665
|
[bug #665]: https://github.com/ossrs/srs/issues/665
|
||||||
|
[bug #1595]: https://github.com/ossrs/srs/issues/1595
|
||||||
|
[bug #1601]: https://github.com/ossrs/srs/issues/1601
|
||||||
|
[bug #1579]: https://github.com/ossrs/srs/issues/1579
|
||||||
|
[bug #1598]: https://github.com/ossrs/srs/issues/1598
|
||||||
|
[bug #1615]: https://github.com/ossrs/srs/issues/1615
|
||||||
[bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx
|
[bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx
|
||||||
|
|
||||||
[exo #828]: https://github.com/google/ExoPlayer/pull/828
|
[exo #828]: https://github.com/google/ExoPlayer/pull/828
|
||||||
|
|
||||||
|
[r3.0b1]: https://github.com/ossrs/srs/releases/tag/v3.0-b1
|
||||||
[r3.0b0]: https://github.com/ossrs/srs/releases/tag/v3.0-b0
|
[r3.0b0]: https://github.com/ossrs/srs/releases/tag/v3.0-b0
|
||||||
[r3.0a9]: https://github.com/ossrs/srs/releases/tag/v3.0-a9
|
[r3.0a9]: https://github.com/ossrs/srs/releases/tag/v3.0-a9
|
||||||
[r3.0a8]: https://github.com/ossrs/srs/releases/tag/v3.0-a8
|
[r3.0a8]: https://github.com/ossrs/srs/releases/tag/v3.0-a8
|
||||||
|
|
|
@ -204,6 +204,10 @@ Remark:
|
||||||
END
|
END
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ignore_option() {
|
||||||
|
echo "ignore option \"$option\""
|
||||||
|
}
|
||||||
|
|
||||||
function parse_user_option() {
|
function parse_user_option() {
|
||||||
case "$option" in
|
case "$option" in
|
||||||
-h) help=yes ;;
|
-h) help=yes ;;
|
||||||
|
@ -293,18 +297,16 @@ function parse_user_option() {
|
||||||
--with-hls) SRS_HLS=YES ;;
|
--with-hls) SRS_HLS=YES ;;
|
||||||
--with-dvr) SRS_DVR=YES ;;
|
--with-dvr) SRS_DVR=YES ;;
|
||||||
|
|
||||||
--without-stream-caster) ;&
|
--without-stream-caster) ignore_option ;;
|
||||||
--without-ingest) ;&
|
--without-ingest) ignore_option ;;
|
||||||
--without-ssl) ;&
|
--without-ssl) ignore_option ;;
|
||||||
--without-stat) ;&
|
--without-stat) ignore_option ;;
|
||||||
--without-transcode) ;&
|
--without-transcode) ignore_option ;;
|
||||||
--without-http-callback) ;&
|
--without-http-callback) ignore_option ;;
|
||||||
--without-http-server) ;&
|
--without-http-server) ignore_option ;;
|
||||||
--without-http-api) ;&
|
--without-http-api) ignore_option ;;
|
||||||
--without-hls) ;&
|
--without-hls) ignore_option ;;
|
||||||
--without-dvr)
|
--without-dvr) ignore_option ;;
|
||||||
echo "ignore option \"$option\""
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo "$0: error: invalid option \"$option\""
|
echo "$0: error: invalid option \"$option\""
|
||||||
|
|
|
@ -72,6 +72,27 @@ work_dir ./;
|
||||||
# @reamrk do not support reload.
|
# @reamrk do not support reload.
|
||||||
# default: off
|
# default: off
|
||||||
asprocess off;
|
asprocess off;
|
||||||
|
# Whether client empty IP is ok, for example, health checking by SLB.
|
||||||
|
# If ok(on), we will ignore this connection without warnings or errors.
|
||||||
|
# default: on
|
||||||
|
empty_ip_ok on;
|
||||||
|
|
||||||
|
# For gracefully quit, wait for a while then close listeners,
|
||||||
|
# because K8S notify SRS with SIGQUIT and update Service simultaneously,
|
||||||
|
# maybe there is some new connections incoming before Service updated.
|
||||||
|
# @see https://github.com/ossrs/srs/issues/1595#issuecomment-587516567
|
||||||
|
# default: 2300
|
||||||
|
grace_start_wait 2300;
|
||||||
|
# For gracefully quit, final wait for cleanup in milliseconds.
|
||||||
|
# @see https://github.com/ossrs/srs/issues/1579#issuecomment-587414898
|
||||||
|
# default: 3200
|
||||||
|
grace_final_wait 3200;
|
||||||
|
# Whether force gracefully quit, never fast quit.
|
||||||
|
# By default, SIGTERM which means fast quit, is sent by K8S, so we need to
|
||||||
|
# force SRS to treat SIGTERM as gracefully quit for gray release or canary.
|
||||||
|
# @see https://github.com/ossrs/srs/issues/1579#issuecomment-587475077
|
||||||
|
# default: off
|
||||||
|
force_grace_quit off;
|
||||||
|
|
||||||
#############################################################################################
|
#############################################################################################
|
||||||
# heartbeat/stats sections
|
# heartbeat/stats sections
|
||||||
|
@ -269,6 +290,9 @@ srt_server {
|
||||||
connect_timeout 4000;
|
connect_timeout 4000;
|
||||||
peerlatency 300;
|
peerlatency 300;
|
||||||
recvlatency 300;
|
recvlatency 300;
|
||||||
|
# Default app for vmix, see https://github.com/ossrs/srs/pull/1615
|
||||||
|
# default: live
|
||||||
|
default_app live;
|
||||||
}
|
}
|
||||||
|
|
||||||
#############################################################################################
|
#############################################################################################
|
||||||
|
|
|
@ -178,6 +178,18 @@ logrotate() {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grace() {
|
||||||
|
# not start, exit
|
||||||
|
load_process_info
|
||||||
|
if [[ 0 -ne $? ]]; then failed_msg "SRS not start."; return 0; fi
|
||||||
|
|
||||||
|
ok_msg "Gracefully quit for SRS(pid ${srs_pid})..."
|
||||||
|
kill -s SIGQUIT ${srs_pid}
|
||||||
|
|
||||||
|
ok_msg "Gracefully quit"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
menu() {
|
menu() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
start)
|
start)
|
||||||
|
@ -199,10 +211,14 @@ menu() {
|
||||||
rotate)
|
rotate)
|
||||||
logrotate
|
logrotate
|
||||||
;;
|
;;
|
||||||
|
grace)
|
||||||
|
grace
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Usage: $0 {start|stop|status|restart|reload|rotate}"
|
echo "Usage: $0 {start|stop|status|restart|reload|rotate|grace}"
|
||||||
echo " reload Apply log file by not restarting SRS"
|
echo " reload Apply log file by not restarting SRS"
|
||||||
echo " rotate For log rotate, to send SIGUSR1 to SRS to reopen the log file."
|
echo " rotate For log rotate, to send SIGUSR1 to SRS to reopen the log file."
|
||||||
|
echo " grace For gracefully quit, to send SIGQUIT to SRS."
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -43,6 +43,15 @@ function user_extra_params(query, params) {
|
||||||
var server = (query.server == undefined)? window.location.hostname:query.server;
|
var server = (query.server == undefined)? window.location.hostname:query.server;
|
||||||
var vhost = (query.vhost == undefined)? window.location.hostname:query.vhost;
|
var vhost = (query.vhost == undefined)? window.location.hostname:query.vhost;
|
||||||
|
|
||||||
|
// Note that ossrs.net provides only web service,
|
||||||
|
// that is migrating to r.ossrs.net
|
||||||
|
if (vhost == "ossrs.net") {
|
||||||
|
vhost = "r.ossrs.net";
|
||||||
|
}
|
||||||
|
if (server == "ossrs.net") {
|
||||||
|
server = "r.ossrs.net";
|
||||||
|
}
|
||||||
|
|
||||||
for (var key in query.user_query) {
|
for (var key in query.user_query) {
|
||||||
if (key == 'app' || key == 'autostart' || key == 'dir'
|
if (key == 'app' || key == 'autostart' || key == 'dir'
|
||||||
|| key == 'filename' || key == 'host' || key == 'hostname'
|
|| key == 'filename' || key == 'host' || key == 'hostname'
|
||||||
|
@ -78,6 +87,15 @@ function build_default_rtmp_url() {
|
||||||
var app = (!query.app)? "live":query.app;
|
var app = (!query.app)? "live":query.app;
|
||||||
var stream = (!query.stream)? "livestream":query.stream;
|
var stream = (!query.stream)? "livestream":query.stream;
|
||||||
|
|
||||||
|
// Note that ossrs.net provides only web service,
|
||||||
|
// that is migrating to r.ossrs.net
|
||||||
|
if (vhost == "ossrs.net") {
|
||||||
|
vhost = "r.ossrs.net";
|
||||||
|
}
|
||||||
|
if (server == "ossrs.net") {
|
||||||
|
server = "r.ossrs.net";
|
||||||
|
}
|
||||||
|
|
||||||
var queries = [];
|
var queries = [];
|
||||||
if (server != vhost && vhost != "__defaultVhost__") {
|
if (server != vhost && vhost != "__defaultVhost__") {
|
||||||
queries.push("vhost=" + vhost);
|
queries.push("vhost=" + vhost);
|
||||||
|
@ -102,6 +120,15 @@ function build_default_publish_rtmp_url() {
|
||||||
var app = (!query.app)? "live":query.app;
|
var app = (!query.app)? "live":query.app;
|
||||||
var stream = (!query.stream)? "demo":query.stream;
|
var stream = (!query.stream)? "demo":query.stream;
|
||||||
|
|
||||||
|
// Note that ossrs.net provides only web service,
|
||||||
|
// that is migrating to r.ossrs.net
|
||||||
|
if (vhost == "ossrs.net") {
|
||||||
|
vhost = "r.ossrs.net";
|
||||||
|
}
|
||||||
|
if (server == "ossrs.net") {
|
||||||
|
server = "r.ossrs.net";
|
||||||
|
}
|
||||||
|
|
||||||
var queries = [];
|
var queries = [];
|
||||||
if (server != vhost && vhost != "__defaultVhost__") {
|
if (server != vhost && vhost != "__defaultVhost__") {
|
||||||
queries.push("vhost=" + vhost);
|
queries.push("vhost=" + vhost);
|
||||||
|
@ -127,6 +154,15 @@ function build_default_bandwidth_rtmp_url() {
|
||||||
var app = (!query.app)? "app":query.app;
|
var app = (!query.app)? "app":query.app;
|
||||||
var key = (!query.key)? "35c9b402c12a7246868752e2878f7e0e":query.key;
|
var key = (!query.key)? "35c9b402c12a7246868752e2878f7e0e":query.key;
|
||||||
|
|
||||||
|
// Note that ossrs.net provides only web service,
|
||||||
|
// that is migrating to r.ossrs.net
|
||||||
|
if (vhost == "ossrs.net") {
|
||||||
|
vhost = "r.ossrs.net";
|
||||||
|
}
|
||||||
|
if (server == "ossrs.net") {
|
||||||
|
server = "r.ossrs.net";
|
||||||
|
}
|
||||||
|
|
||||||
return "rtmp://" + server + ":" + port + "/" + app + "?key=" + key + "&vhost=" + vhost;
|
return "rtmp://" + server + ":" + port + "/" + app + "?key=" + key + "&vhost=" + vhost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +177,12 @@ function build_default_bandwidth_rtmp_url() {
|
||||||
function build_default_hls_url() {
|
function build_default_hls_url() {
|
||||||
var query = parse_query_string();
|
var query = parse_query_string();
|
||||||
|
|
||||||
|
// Note that ossrs.net provides only web service,
|
||||||
|
// that is migrating to r.ossrs.net
|
||||||
|
if (query.hls_vhost == "ossrs.net") {
|
||||||
|
query.hls_vhost = "r.ossrs.net";
|
||||||
|
}
|
||||||
|
|
||||||
// for http, use hls_vhost to override server if specified.
|
// for http, use hls_vhost to override server if specified.
|
||||||
var server = window.location.hostname;
|
var server = window.location.hostname;
|
||||||
if (query.server != undefined) {
|
if (query.server != undefined) {
|
||||||
|
|
|
@ -40,6 +40,7 @@ SrsAsyncCallWorker::SrsAsyncCallWorker()
|
||||||
{
|
{
|
||||||
trd = new SrsDummyCoroutine();
|
trd = new SrsDummyCoroutine();
|
||||||
wait = srs_cond_new();
|
wait = srs_cond_new();
|
||||||
|
lock = srs_mutex_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsAsyncCallWorker::~SrsAsyncCallWorker()
|
SrsAsyncCallWorker::~SrsAsyncCallWorker()
|
||||||
|
@ -54,6 +55,7 @@ SrsAsyncCallWorker::~SrsAsyncCallWorker()
|
||||||
tasks.clear();
|
tasks.clear();
|
||||||
|
|
||||||
srs_cond_destroy(wait);
|
srs_cond_destroy(wait);
|
||||||
|
srs_mutex_destroy(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsAsyncCallWorker::execute(ISrsAsyncCallTask* t)
|
srs_error_t SrsAsyncCallWorker::execute(ISrsAsyncCallTask* t)
|
||||||
|
@ -87,6 +89,7 @@ srs_error_t SrsAsyncCallWorker::start()
|
||||||
|
|
||||||
void SrsAsyncCallWorker::stop()
|
void SrsAsyncCallWorker::stop()
|
||||||
{
|
{
|
||||||
|
flush_tasks();
|
||||||
srs_cond_signal(wait);
|
srs_cond_signal(wait);
|
||||||
trd->stop();
|
trd->stop();
|
||||||
}
|
}
|
||||||
|
@ -104,22 +107,39 @@ srs_error_t SrsAsyncCallWorker::cycle()
|
||||||
srs_cond_wait(wait);
|
srs_cond_wait(wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ISrsAsyncCallTask*> copy = tasks;
|
flush_tasks();
|
||||||
tasks.clear();
|
|
||||||
|
|
||||||
std::vector<ISrsAsyncCallTask*>::iterator it;
|
|
||||||
for (it = copy.begin(); it != copy.end(); ++it) {
|
|
||||||
ISrsAsyncCallTask* task = *it;
|
|
||||||
|
|
||||||
if ((err = task->call()) != srs_success) {
|
|
||||||
srs_warn("ignore task failed %s", srs_error_desc(err).c_str());
|
|
||||||
srs_freep(err);
|
|
||||||
}
|
|
||||||
srs_freep(task);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SrsAsyncCallWorker::flush_tasks()
|
||||||
|
{
|
||||||
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
// Avoid the async call blocking other coroutines.
|
||||||
|
std::vector<ISrsAsyncCallTask*> copy;
|
||||||
|
if (true) {
|
||||||
|
SrsLocker(lock);
|
||||||
|
|
||||||
|
if (tasks.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy = tasks;
|
||||||
|
tasks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ISrsAsyncCallTask*>::iterator it;
|
||||||
|
for (it = copy.begin(); it != copy.end(); ++it) {
|
||||||
|
ISrsAsyncCallTask* task = *it;
|
||||||
|
|
||||||
|
if ((err = task->call()) != srs_success) {
|
||||||
|
srs_warn("ignore task failed %s", srs_error_desc(err).c_str());
|
||||||
|
srs_freep(err);
|
||||||
|
}
|
||||||
|
srs_freep(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ private:
|
||||||
protected:
|
protected:
|
||||||
std::vector<ISrsAsyncCallTask*> tasks;
|
std::vector<ISrsAsyncCallTask*> tasks;
|
||||||
srs_cond_t wait;
|
srs_cond_t wait;
|
||||||
|
srs_mutex_t lock;
|
||||||
public:
|
public:
|
||||||
SrsAsyncCallWorker();
|
SrsAsyncCallWorker();
|
||||||
virtual ~SrsAsyncCallWorker();
|
virtual ~SrsAsyncCallWorker();
|
||||||
|
@ -73,6 +74,8 @@ public:
|
||||||
// Interface ISrsReusableThreadHandler
|
// Interface ISrsReusableThreadHandler
|
||||||
public:
|
public:
|
||||||
virtual srs_error_t cycle();
|
virtual srs_error_t cycle();
|
||||||
|
private:
|
||||||
|
virtual void flush_tasks();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -78,6 +78,10 @@ srs_error_t SrsAppCasterFlv::on_tcp_client(srs_netfd_t stfd)
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
string ip = srs_get_peer_ip(srs_netfd_fileno(stfd));
|
string ip = srs_get_peer_ip(srs_netfd_fileno(stfd));
|
||||||
|
if (ip.empty() && !_srs_config->empty_ip_ok()) {
|
||||||
|
srs_warn("empty ip for fd=%d", srs_netfd_fileno(stfd));
|
||||||
|
}
|
||||||
|
|
||||||
SrsHttpConn* conn = new SrsDynamicHttpConn(this, stfd, http_mux, ip);
|
SrsHttpConn* conn = new SrsDynamicHttpConn(this, stfd, http_mux, ip);
|
||||||
conns.push_back(conn);
|
conns.push_back(conn);
|
||||||
|
|
||||||
|
|
|
@ -3488,7 +3488,8 @@ srs_error_t SrsConfig::check_normal_config()
|
||||||
&& n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print_ms"
|
&& n != "http_api" && n != "stats" && n != "vhost" && n != "pithy_print_ms"
|
||||||
&& n != "http_server" && n != "stream_caster" && n != "srt_server"
|
&& n != "http_server" && n != "stream_caster" && n != "srt_server"
|
||||||
&& n != "utc_time" && n != "work_dir" && n != "asprocess"
|
&& n != "utc_time" && n != "work_dir" && n != "asprocess"
|
||||||
&& n != "ff_log_level"
|
&& n != "ff_log_level" && n != "grace_final_wait" && n != "force_grace_quit"
|
||||||
|
&& n != "grace_start_wait" && n != "empty_ip_ok"
|
||||||
) {
|
) {
|
||||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal directive %s", n.c_str());
|
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal directive %s", n.c_str());
|
||||||
}
|
}
|
||||||
|
@ -3528,7 +3529,8 @@ srs_error_t SrsConfig::check_normal_config()
|
||||||
if (n != "enabled" && n != "listen" && n != "maxbw"
|
if (n != "enabled" && n != "listen" && n != "maxbw"
|
||||||
&& n != "mss" && n != "latency" && n != "recvlatency"
|
&& n != "mss" && n != "latency" && n != "recvlatency"
|
||||||
&& n != "peerlatency" && n != "tlpkdrop" && n != "connect_timeout"
|
&& n != "peerlatency" && n != "tlpkdrop" && n != "connect_timeout"
|
||||||
&& n != "sendbuf" && n != "recvbuf" && n != "payloadsize") {
|
&& n != "sendbuf" && n != "recvbuf" && n != "payloadsize"
|
||||||
|
&& n != "default_app") {
|
||||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal srt_stream.%s", n.c_str());
|
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal srt_stream.%s", n.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4064,6 +4066,54 @@ bool SrsConfig::get_asprocess()
|
||||||
return SRS_CONF_PERFER_FALSE(conf->arg0());
|
return SRS_CONF_PERFER_FALSE(conf->arg0());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SrsConfig::empty_ip_ok()
|
||||||
|
{
|
||||||
|
static bool DEFAULT = true;
|
||||||
|
|
||||||
|
SrsConfDirective* conf = root->get("empty_ip_ok");
|
||||||
|
if (!conf || conf->arg0().empty()) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SRS_CONF_PERFER_TRUE(conf->arg0());
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_utime_t SrsConfig::get_grace_start_wait()
|
||||||
|
{
|
||||||
|
static srs_utime_t DEFAULT = 2300 * SRS_UTIME_MILLISECONDS;
|
||||||
|
|
||||||
|
SrsConfDirective* conf = root->get("grace_start_wait");
|
||||||
|
if (!conf || conf->arg0().empty()) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (srs_utime_t)(::atol(conf->arg0().c_str()) * SRS_UTIME_MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_utime_t SrsConfig::get_grace_final_wait()
|
||||||
|
{
|
||||||
|
static srs_utime_t DEFAULT = 3200 * SRS_UTIME_MILLISECONDS;
|
||||||
|
|
||||||
|
SrsConfDirective* conf = root->get("grace_final_wait");
|
||||||
|
if (!conf || conf->arg0().empty()) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (srs_utime_t)(::atol(conf->arg0().c_str()) * SRS_UTIME_MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SrsConfig::is_force_grace_quit()
|
||||||
|
{
|
||||||
|
static bool DEFAULT = false;
|
||||||
|
|
||||||
|
SrsConfDirective* conf = root->get("force_grace_quit");
|
||||||
|
if (!conf || conf->arg0().empty()) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SRS_CONF_PERFER_FALSE(conf->arg0());
|
||||||
|
}
|
||||||
|
|
||||||
vector<SrsConfDirective*> SrsConfig::get_stream_casters()
|
vector<SrsConfDirective*> SrsConfig::get_stream_casters()
|
||||||
{
|
{
|
||||||
srs_assert(root);
|
srs_assert(root);
|
||||||
|
@ -6844,6 +6894,20 @@ int SrsConfig::get_srto_payloadsize() {
|
||||||
return atoi(conf->arg0().c_str());
|
return atoi(conf->arg0().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string SrsConfig::get_default_app_name() {
|
||||||
|
static string DEFAULT = "live";
|
||||||
|
SrsConfDirective* conf = root->get("srt_server");
|
||||||
|
if (!conf) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf = conf->get("default_app");
|
||||||
|
if (!conf || conf->arg0().empty()) {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
return conf->arg0();
|
||||||
|
}
|
||||||
|
|
||||||
bool SrsConfig::get_http_stream_enabled()
|
bool SrsConfig::get_http_stream_enabled()
|
||||||
{
|
{
|
||||||
SrsConfDirective* conf = root->get("http_server");
|
SrsConfDirective* conf = root->get("http_server");
|
||||||
|
|
|
@ -468,6 +468,14 @@ public:
|
||||||
virtual std::string get_work_dir();
|
virtual std::string get_work_dir();
|
||||||
// Whether use asprocess mode.
|
// Whether use asprocess mode.
|
||||||
virtual bool get_asprocess();
|
virtual bool get_asprocess();
|
||||||
|
// Whether empty client IP is ok.
|
||||||
|
virtual bool empty_ip_ok();
|
||||||
|
// Get the start wait in ms for gracefully quit.
|
||||||
|
virtual srs_utime_t get_grace_start_wait();
|
||||||
|
// Get the final wait in ms for gracefully quit.
|
||||||
|
virtual srs_utime_t get_grace_final_wait();
|
||||||
|
// Whether force to gracefully quit, never fast quit.
|
||||||
|
virtual bool is_force_grace_quit();
|
||||||
// stream_caster section
|
// stream_caster section
|
||||||
public:
|
public:
|
||||||
// Get all stream_caster in config file.
|
// Get all stream_caster in config file.
|
||||||
|
@ -615,6 +623,8 @@ public:
|
||||||
virtual int get_srto_recvbuf();
|
virtual int get_srto_recvbuf();
|
||||||
// SRTO_PAYLOADSIZE
|
// SRTO_PAYLOADSIZE
|
||||||
virtual int get_srto_payloadsize();
|
virtual int get_srto_payloadsize();
|
||||||
|
// Get the default app.
|
||||||
|
virtual std::string get_default_app_name();
|
||||||
|
|
||||||
// http_hooks section
|
// http_hooks section
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -740,8 +740,6 @@ srs_error_t SrsDvrSessionPlan::on_publish()
|
||||||
|
|
||||||
void SrsDvrSessionPlan::on_unpublish()
|
void SrsDvrSessionPlan::on_unpublish()
|
||||||
{
|
{
|
||||||
SrsDvrPlan::on_unpublish();
|
|
||||||
|
|
||||||
// support multiple publish.
|
// support multiple publish.
|
||||||
if (!dvr_enabled) {
|
if (!dvr_enabled) {
|
||||||
return;
|
return;
|
||||||
|
@ -754,6 +752,10 @@ void SrsDvrSessionPlan::on_unpublish()
|
||||||
}
|
}
|
||||||
|
|
||||||
dvr_enabled = false;
|
dvr_enabled = false;
|
||||||
|
|
||||||
|
// We should notify the on_dvr, then stop the async.
|
||||||
|
// @see https://github.com/ossrs/srs/issues/1601
|
||||||
|
SrsDvrPlan::on_unpublish();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsDvrSegmentPlan::SrsDvrSegmentPlan()
|
SrsDvrSegmentPlan::SrsDvrSegmentPlan()
|
||||||
|
@ -815,14 +817,16 @@ void SrsDvrSegmentPlan::on_unpublish()
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
SrsDvrPlan::on_unpublish();
|
|
||||||
|
|
||||||
if ((err = segment->close()) != srs_success) {
|
if ((err = segment->close()) != srs_success) {
|
||||||
srs_warn("ignore err %s", srs_error_desc(err).c_str());
|
srs_warn("ignore err %s", srs_error_desc(err).c_str());
|
||||||
srs_freep(err);
|
srs_freep(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
dvr_enabled = false;
|
dvr_enabled = false;
|
||||||
|
|
||||||
|
// We should notify the on_dvr, then stop the async.
|
||||||
|
// @see https://github.com/ossrs/srs/issues/1601
|
||||||
|
SrsDvrPlan::on_unpublish();
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsDvrSegmentPlan::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
|
srs_error_t SrsDvrSegmentPlan::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
|
||||||
|
|
|
@ -230,7 +230,7 @@ srs_error_t SrsFFMPEG::start()
|
||||||
params.push_back(ffmpeg);
|
params.push_back(ffmpeg);
|
||||||
|
|
||||||
// input params
|
// input params
|
||||||
for (int i = 0; i < iparams.size(); i++) {
|
for (int i = 0; i < (int)iparams.size(); i++) {
|
||||||
string iparam = iparams.at(i);
|
string iparam = iparams.at(i);
|
||||||
if (!iparam.empty()) {
|
if (!iparam.empty()) {
|
||||||
params.push_back(iparam);
|
params.push_back(iparam);
|
||||||
|
|
|
@ -406,7 +406,7 @@ srs_error_t SrsRtmpConn::service_cycle()
|
||||||
rtmp->set_send_timeout(SRS_REPUBLISH_RECV_TIMEOUT);
|
rtmp->set_send_timeout(SRS_REPUBLISH_RECV_TIMEOUT);
|
||||||
rtmp->set_recv_timeout(SRS_REPUBLISH_SEND_TIMEOUT);
|
rtmp->set_recv_timeout(SRS_REPUBLISH_SEND_TIMEOUT);
|
||||||
|
|
||||||
srs_trace("rtmp: retry for republish");
|
srs_info("rtmp: retry for republish");
|
||||||
srs_freep(err);
|
srs_freep(err);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,11 +94,14 @@ srs_error_t SrsRtpConn::on_udp_packet(const sockaddr* from, const int fromlen, c
|
||||||
}
|
}
|
||||||
cache->copy(&pkt);
|
cache->copy(&pkt);
|
||||||
cache->payload->append(pkt.payload->bytes(), pkt.payload->length());
|
cache->payload->append(pkt.payload->bytes(), pkt.payload->length());
|
||||||
if (!cache->completed && pprint->can_print()) {
|
if (pprint->can_print()) {
|
||||||
srs_trace("<- " SRS_CONSTS_LOG_STREAM_CASTER " rtsp: rtp chunked %dB, age=%d, vt=%d/%u, sts=%u/%#x/%#x, paylod=%dB",
|
srs_trace("<- " SRS_CONSTS_LOG_STREAM_CASTER " rtsp: rtp chunked %dB, age=%d, vt=%d/%u, sts=%u/%#x/%#x, paylod=%dB",
|
||||||
nb_buf, pprint->age(), cache->version, cache->payload_type, cache->sequence_number, cache->timestamp, cache->ssrc,
|
nb_buf, pprint->age(), cache->version, cache->payload_type, cache->sequence_number, cache->timestamp, cache->ssrc,
|
||||||
cache->payload->length()
|
cache->payload->length()
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cache->completed){
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -243,6 +246,9 @@ srs_error_t SrsRtspConn::do_cycle()
|
||||||
|
|
||||||
// retrieve ip of client.
|
// retrieve ip of client.
|
||||||
std::string ip = srs_get_peer_ip(srs_netfd_fileno(stfd));
|
std::string ip = srs_get_peer_ip(srs_netfd_fileno(stfd));
|
||||||
|
if (ip.empty() && !_srs_config->empty_ip_ok()) {
|
||||||
|
srs_warn("empty ip for fd=%d", srs_netfd_fileno(stfd));
|
||||||
|
}
|
||||||
srs_trace("rtsp: serve %s", ip.c_str());
|
srs_trace("rtsp: serve %s", ip.c_str());
|
||||||
|
|
||||||
// consume all rtsp messages.
|
// consume all rtsp messages.
|
||||||
|
@ -645,6 +651,7 @@ srs_error_t SrsRtspConn::connect()
|
||||||
std::string output = output_template;
|
std::string output = output_template;
|
||||||
output = srs_string_replace(output, "[app]", app);
|
output = srs_string_replace(output, "[app]", app);
|
||||||
output = srs_string_replace(output, "[stream]", rtsp_stream);
|
output = srs_string_replace(output, "[stream]", rtsp_stream);
|
||||||
|
url = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect host.
|
// connect host.
|
||||||
|
|
|
@ -392,6 +392,11 @@ srs_error_t SrsSignalManager::start()
|
||||||
sa.sa_flags = 0;
|
sa.sa_flags = 0;
|
||||||
sigaction(SRS_SIGNAL_RELOAD, &sa, NULL);
|
sigaction(SRS_SIGNAL_RELOAD, &sa, NULL);
|
||||||
|
|
||||||
|
sa.sa_handler = SrsSignalManager::sig_catcher;
|
||||||
|
sigemptyset(&sa.sa_mask);
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
sigaction(SRS_SIGNAL_FAST_QUIT, &sa, NULL);
|
||||||
|
|
||||||
sa.sa_handler = SrsSignalManager::sig_catcher;
|
sa.sa_handler = SrsSignalManager::sig_catcher;
|
||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sa.sa_flags = 0;
|
sa.sa_flags = 0;
|
||||||
|
@ -407,8 +412,8 @@ srs_error_t SrsSignalManager::start()
|
||||||
sa.sa_flags = 0;
|
sa.sa_flags = 0;
|
||||||
sigaction(SRS_SIGNAL_REOPEN_LOG, &sa, NULL);
|
sigaction(SRS_SIGNAL_REOPEN_LOG, &sa, NULL);
|
||||||
|
|
||||||
srs_trace("signal installed, reload=%d, reopen=%d, grace_quit=%d",
|
srs_trace("signal installed, reload=%d, reopen=%d, fast_quit=%d, grace_quit=%d",
|
||||||
SRS_SIGNAL_RELOAD, SRS_SIGNAL_REOPEN_LOG, SRS_SIGNAL_GRACEFULLY_QUIT);
|
SRS_SIGNAL_RELOAD, SRS_SIGNAL_REOPEN_LOG, SRS_SIGNAL_FAST_QUIT, SRS_SIGNAL_GRACEFULLY_QUIT);
|
||||||
|
|
||||||
if ((err = trd->start()) != srs_success) {
|
if ((err = trd->start()) != srs_success) {
|
||||||
return srs_error_wrap(err, "signal manager");
|
return srs_error_wrap(err, "signal manager");
|
||||||
|
@ -465,6 +470,7 @@ SrsServer::SrsServer()
|
||||||
signal_reload = false;
|
signal_reload = false;
|
||||||
signal_persistence_config = false;
|
signal_persistence_config = false;
|
||||||
signal_gmc_stop = false;
|
signal_gmc_stop = false;
|
||||||
|
signal_fast_quit = false;
|
||||||
signal_gracefully_quit = false;
|
signal_gracefully_quit = false;
|
||||||
pid_fd = -1;
|
pid_fd = -1;
|
||||||
|
|
||||||
|
@ -533,6 +539,48 @@ void SrsServer::dispose()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SrsServer::gracefully_dispose()
|
||||||
|
{
|
||||||
|
_srs_config->unsubscribe(this);
|
||||||
|
|
||||||
|
// Always wait for a while to start.
|
||||||
|
srs_usleep(_srs_config->get_grace_start_wait());
|
||||||
|
srs_trace("start wait for %dms", srsu2msi(_srs_config->get_grace_start_wait()));
|
||||||
|
|
||||||
|
// prevent fresh clients.
|
||||||
|
close_listeners(SrsListenerRtmpStream);
|
||||||
|
close_listeners(SrsListenerHttpApi);
|
||||||
|
close_listeners(SrsListenerHttpStream);
|
||||||
|
close_listeners(SrsListenerMpegTsOverUdp);
|
||||||
|
close_listeners(SrsListenerRtsp);
|
||||||
|
close_listeners(SrsListenerFlv);
|
||||||
|
|
||||||
|
// Fast stop to notify FFMPEG to quit, wait for a while then fast kill.
|
||||||
|
ingester->stop();
|
||||||
|
|
||||||
|
// Wait for connections to quit.
|
||||||
|
// While gracefully quiting, user can requires SRS to fast quit.
|
||||||
|
int wait_step = 1;
|
||||||
|
while (!conns.empty() && !signal_fast_quit) {
|
||||||
|
for (int i = 0; i < wait_step && !conns.empty() && !signal_fast_quit; i++) {
|
||||||
|
srs_usleep(1000 * SRS_UTIME_MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_step = (wait_step * 2) % 33;
|
||||||
|
srs_trace("wait for %d conns to quit", conns.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
// dispose the source for hls and dvr.
|
||||||
|
_srs_sources->dispose();
|
||||||
|
|
||||||
|
#ifdef SRS_AUTO_MEM_WATCH
|
||||||
|
srs_memory_report();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
srs_usleep(_srs_config->get_grace_final_wait());
|
||||||
|
srs_trace("final wait for %dms", srsu2msi(_srs_config->get_grace_final_wait()));
|
||||||
|
}
|
||||||
|
|
||||||
srs_error_t SrsServer::initialize(ISrsServerCycle* ch)
|
srs_error_t SrsServer::initialize(ISrsServerCycle* ch)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
@ -802,10 +850,25 @@ srs_error_t SrsServer::cycle()
|
||||||
srs_warn("sleep a long time for system st-threads to cleanup.");
|
srs_warn("sleep a long time for system st-threads to cleanup.");
|
||||||
srs_usleep(3 * 1000 * 1000);
|
srs_usleep(3 * 1000 * 1000);
|
||||||
srs_warn("system quit");
|
srs_warn("system quit");
|
||||||
#else
|
|
||||||
// normally quit with neccessary cleanup by dispose().
|
return err;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// quit normally.
|
||||||
srs_warn("main cycle terminated, system quit normally.");
|
srs_warn("main cycle terminated, system quit normally.");
|
||||||
dispose();
|
|
||||||
|
// fast quit, do some essential cleanup.
|
||||||
|
if (signal_fast_quit) {
|
||||||
|
dispose();
|
||||||
|
srs_trace("srs disposed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// gracefully quit, do carefully cleanup.
|
||||||
|
if (signal_gracefully_quit) {
|
||||||
|
gracefully_dispose();
|
||||||
|
srs_trace("srs gracefully quit");
|
||||||
|
}
|
||||||
|
|
||||||
srs_trace("srs terminated");
|
srs_trace("srs terminated");
|
||||||
|
|
||||||
// for valgrind to detect.
|
// for valgrind to detect.
|
||||||
|
@ -813,7 +876,6 @@ srs_error_t SrsServer::cycle()
|
||||||
srs_freep(_srs_log);
|
srs_freep(_srs_log);
|
||||||
|
|
||||||
exit(0);
|
exit(0);
|
||||||
#endif
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -858,8 +920,21 @@ void SrsServer::on_signal(int signo)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((signo == SIGINT || signo == SRS_SIGNAL_GRACEFULLY_QUIT) && !signal_gracefully_quit) {
|
// For K8S, force to gracefully quit for gray release or canary.
|
||||||
srs_trace("sig=%d, user terminate program, gracefully quit", signo);
|
// @see https://github.com/ossrs/srs/issues/1595#issuecomment-587473037
|
||||||
|
if (signo == SRS_SIGNAL_FAST_QUIT && _srs_config->is_force_grace_quit()) {
|
||||||
|
srs_trace("force gracefully quit, signo=%d", signo);
|
||||||
|
signo = SRS_SIGNAL_GRACEFULLY_QUIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((signo == SIGINT || signo == SRS_SIGNAL_FAST_QUIT) && !signal_fast_quit) {
|
||||||
|
srs_trace("sig=%d, user terminate program, fast quit", signo);
|
||||||
|
signal_fast_quit = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signo == SRS_SIGNAL_GRACEFULLY_QUIT && !signal_gracefully_quit) {
|
||||||
|
srs_trace("sig=%d, user start gracefully quit", signo);
|
||||||
signal_gracefully_quit = true;
|
signal_gracefully_quit = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -904,9 +979,9 @@ srs_error_t SrsServer::do_cycle()
|
||||||
return srs_error_new(ERROR_ASPROCESS_PPID, "asprocess ppid changed from %d to %d", ppid, ::getppid());
|
return srs_error_new(ERROR_ASPROCESS_PPID, "asprocess ppid changed from %d to %d", ppid, ::getppid());
|
||||||
}
|
}
|
||||||
|
|
||||||
// gracefully quit for SIGINT or SIGTERM.
|
// gracefully quit for SIGINT or SIGTERM or SIGQUIT.
|
||||||
if (signal_gracefully_quit) {
|
if (signal_fast_quit || signal_gracefully_quit) {
|
||||||
srs_trace("cleanup for gracefully terminate.");
|
srs_trace("cleanup for quit signal fast=%d, grace=%d", signal_fast_quit, signal_gracefully_quit);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1157,6 +1232,10 @@ srs_error_t SrsServer::accept_client(SrsListenerType type, srs_netfd_t stfd)
|
||||||
SrsConnection* conn = NULL;
|
SrsConnection* conn = NULL;
|
||||||
|
|
||||||
if ((err = fd2conn(type, stfd, &conn)) != srs_success) {
|
if ((err = fd2conn(type, stfd, &conn)) != srs_success) {
|
||||||
|
if (srs_error_code(err) == ERROR_SOCKET_GET_PEER_IP && _srs_config->empty_ip_ok()) {
|
||||||
|
srs_close_stfd(stfd); srs_error_reset(err);
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
return srs_error_wrap(err, "fd2conn");
|
return srs_error_wrap(err, "fd2conn");
|
||||||
}
|
}
|
||||||
srs_assert(conn);
|
srs_assert(conn);
|
||||||
|
|
|
@ -227,6 +227,7 @@ private:
|
||||||
bool signal_reload;
|
bool signal_reload;
|
||||||
bool signal_persistence_config;
|
bool signal_persistence_config;
|
||||||
bool signal_gmc_stop;
|
bool signal_gmc_stop;
|
||||||
|
bool signal_fast_quit;
|
||||||
bool signal_gracefully_quit;
|
bool signal_gracefully_quit;
|
||||||
// Parent pid for asprocess.
|
// Parent pid for asprocess.
|
||||||
int ppid;
|
int ppid;
|
||||||
|
@ -241,6 +242,9 @@ private:
|
||||||
// When SIGTERM, SRS should do cleanup, for example,
|
// When SIGTERM, SRS should do cleanup, for example,
|
||||||
// to stop all ingesters, cleanup HLS and dvr.
|
// to stop all ingesters, cleanup HLS and dvr.
|
||||||
virtual void dispose();
|
virtual void dispose();
|
||||||
|
// Close listener to stop accepting new connections,
|
||||||
|
// then wait and quit when all connections finished.
|
||||||
|
virtual void gracefully_dispose();
|
||||||
// server startup workflow, @see run_master()
|
// server startup workflow, @see run_master()
|
||||||
public:
|
public:
|
||||||
// Initialize server with callback handler ch.
|
// Initialize server with callback handler ch.
|
||||||
|
@ -260,12 +264,13 @@ public:
|
||||||
// The signal manager convert signal to io message,
|
// The signal manager convert signal to io message,
|
||||||
// whatever, we will got the signo like the orignal signal(int signo) handler.
|
// whatever, we will got the signo like the orignal signal(int signo) handler.
|
||||||
// @param signo the signal number from user, where:
|
// @param signo the signal number from user, where:
|
||||||
// SRS_SIGNAL_GRACEFULLY_QUIT, the SIGTERM, dispose then quit.
|
// SRS_SIGNAL_FAST_QUIT, the SIGTERM, do essential dispose then quit.
|
||||||
|
// SRS_SIGNAL_GRACEFULLY_QUIT, the SIGQUIT, do careful dispose then quit.
|
||||||
// SRS_SIGNAL_REOPEN_LOG, the SIGUSR1, reopen the log file.
|
// SRS_SIGNAL_REOPEN_LOG, the SIGUSR1, reopen the log file.
|
||||||
// SRS_SIGNAL_RELOAD, the SIGHUP, reload the config.
|
// SRS_SIGNAL_RELOAD, the SIGHUP, reload the config.
|
||||||
// SRS_SIGNAL_PERSISTENCE_CONFIG, application level signal, persistence config to file.
|
// SRS_SIGNAL_PERSISTENCE_CONFIG, application level signal, persistence config to file.
|
||||||
// @remark, for SIGINT:
|
// @remark, for SIGINT:
|
||||||
// no gmc, directly exit.
|
// no gmc, fast quit, do essential dispose then quit.
|
||||||
// for gmc, set the variable signal_gmc_stop, the cycle will return and cleanup for gmc.
|
// for gmc, set the variable signal_gmc_stop, the cycle will return and cleanup for gmc.
|
||||||
// @remark, maybe the HTTP RAW API will trigger the on_signal() also.
|
// @remark, maybe the HTTP RAW API will trigger the on_signal() also.
|
||||||
virtual void on_signal(int signo);
|
virtual void on_signal(int signo);
|
||||||
|
|
|
@ -74,7 +74,7 @@ void srs_memory_report()
|
||||||
std::map<void*, SrsMemoryObject*>::iterator it;
|
std::map<void*, SrsMemoryObject*>::iterator it;
|
||||||
for (it = _srs_ptrs.begin(); it != _srs_ptrs.end(); ++it) {
|
for (it = _srs_ptrs.begin(); it != _srs_ptrs.end(); ++it) {
|
||||||
SrsMemoryObject* obj = it->second;
|
SrsMemoryObject* obj = it->second;
|
||||||
printf(" %s: %#"PRIx64", %dB\n", obj->category.c_str(), (int64_t)obj->ptr, obj->size);
|
printf(" %s: %#" PRIx64 ", %dB\n", obj->category.c_str(), (int64_t)obj->ptr, obj->size);
|
||||||
total += obj->size;
|
total += obj->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,6 @@
|
||||||
#ifndef SRS_CORE_VERSION3_HPP
|
#ifndef SRS_CORE_VERSION3_HPP
|
||||||
#define SRS_CORE_VERSION3_HPP
|
#define SRS_CORE_VERSION3_HPP
|
||||||
|
|
||||||
#define SRS_VERSION3_REVISION 116
|
#define SRS_VERSION3_REVISION 123
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,6 +24,6 @@
|
||||||
#ifndef SRS_CORE_VERSION4_HPP
|
#ifndef SRS_CORE_VERSION4_HPP
|
||||||
#define SRS_CORE_VERSION4_HPP
|
#define SRS_CORE_VERSION4_HPP
|
||||||
|
|
||||||
#define SRS_VERSION4_REVISION 4
|
#define SRS_VERSION4_REVISION 9
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -124,8 +124,15 @@
|
||||||
#define SRS_SIGNAL_RELOAD SIGHUP
|
#define SRS_SIGNAL_RELOAD SIGHUP
|
||||||
// Reopen the log file.
|
// Reopen the log file.
|
||||||
#define SRS_SIGNAL_REOPEN_LOG SIGUSR1
|
#define SRS_SIGNAL_REOPEN_LOG SIGUSR1
|
||||||
// The signal for srs to gracefully quit, do dispose then exit.
|
// For gracefully upgrade, start new SRS and gracefully quit old one.
|
||||||
#define SRS_SIGNAL_GRACEFULLY_QUIT SIGTERM
|
// @see https://github.com/ossrs/srs/issues/1579
|
||||||
|
// TODO: Not implemented.
|
||||||
|
#define SRS_SIGNAL_UPGRADE SIGUSR2
|
||||||
|
// The signal for srs to fast quit, do essential dispose then exit.
|
||||||
|
#define SRS_SIGNAL_FAST_QUIT SIGTERM
|
||||||
|
// The signal for srs to gracefully quit, do carefully dispose then exit.
|
||||||
|
// @see https://github.com/ossrs/srs/issues/1579
|
||||||
|
#define SRS_SIGNAL_GRACEFULLY_QUIT SIGQUIT
|
||||||
|
|
||||||
// The application level signals.
|
// The application level signals.
|
||||||
// Persistence the config in memory to config file.
|
// Persistence the config in memory to config file.
|
||||||
|
@ -146,7 +153,7 @@
|
||||||
// Downloading speed-up, play to edge, ingest from origin
|
// Downloading speed-up, play to edge, ingest from origin
|
||||||
#define SRS_CONSTS_LOG_EDGE_PLAY "EIG"
|
#define SRS_CONSTS_LOG_EDGE_PLAY "EIG"
|
||||||
// Uploading speed-up, publish to edge, foward to origin
|
// Uploading speed-up, publish to edge, foward to origin
|
||||||
#define SRS_CONSTS_LOG_EDGE_PUBLISH "EFW"
|
#define SRS_CONSTS_LOG_EDGE_PUBLISH "EPB"
|
||||||
// The edge/origin forwarder.
|
// The edge/origin forwarder.
|
||||||
#define SRS_CONSTS_LOG_FOWARDER "FWR"
|
#define SRS_CONSTS_LOG_FOWARDER "FWR"
|
||||||
// Play stream on edge/origin.
|
// Play stream on edge/origin.
|
||||||
|
|
|
@ -77,8 +77,11 @@
|
||||||
#ifndef SRS_HIJACK_IO
|
#ifndef SRS_HIJACK_IO
|
||||||
struct SrsBlockSyncSocket
|
struct SrsBlockSyncSocket
|
||||||
{
|
{
|
||||||
|
int family;
|
||||||
SOCKET fd;
|
SOCKET fd;
|
||||||
int family;
|
SOCKET fdv4;
|
||||||
|
SOCKET fdv6;
|
||||||
|
// Bytes transmit.
|
||||||
int64_t rbytes;
|
int64_t rbytes;
|
||||||
int64_t sbytes;
|
int64_t sbytes;
|
||||||
// The send/recv timeout in ms.
|
// The send/recv timeout in ms.
|
||||||
|
@ -86,15 +89,26 @@ struct SrsBlockSyncSocket
|
||||||
int64_t stm;
|
int64_t stm;
|
||||||
|
|
||||||
SrsBlockSyncSocket() {
|
SrsBlockSyncSocket() {
|
||||||
|
family = AF_UNSPEC;
|
||||||
stm = rtm = SRS_UTIME_NO_TIMEOUT;
|
stm = rtm = SRS_UTIME_NO_TIMEOUT;
|
||||||
rbytes = sbytes = 0;
|
rbytes = sbytes = 0;
|
||||||
|
|
||||||
SOCKET_RESET(fd);
|
SOCKET_RESET(fd);
|
||||||
|
SOCKET_RESET(fdv4);
|
||||||
|
SOCKET_RESET(fdv6);
|
||||||
SOCKET_SETUP();
|
SOCKET_SETUP();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~SrsBlockSyncSocket() {
|
virtual ~SrsBlockSyncSocket() {
|
||||||
SOCKET_CLOSE(fd);
|
if (SOCKET_VALID(fd)) {
|
||||||
|
SOCKET_CLOSE(fd);
|
||||||
|
}
|
||||||
|
if (SOCKET_VALID(fdv4)) {
|
||||||
|
SOCKET_CLOSE(fdv4);
|
||||||
|
}
|
||||||
|
if (SOCKET_VALID(fdv6)) {
|
||||||
|
SOCKET_CLOSE(fdv6);
|
||||||
|
}
|
||||||
SOCKET_CLEANUP();
|
SOCKET_CLEANUP();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -112,19 +126,17 @@ int srs_hijack_io_create_socket(srs_hijack_io_t ctx, srs_rtmp_t owner)
|
||||||
{
|
{
|
||||||
SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx;
|
SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx;
|
||||||
|
|
||||||
skt->family = AF_INET6;
|
skt->family = AF_UNSPEC;
|
||||||
skt->fd = ::socket(skt->family, SOCK_STREAM, 0); // Try IPv6 first.
|
skt->fdv4 = ::socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (!SOCKET_VALID(skt->fd)) {
|
skt->fdv6 = ::socket(AF_INET6, SOCK_STREAM, 0);
|
||||||
skt->family = AF_INET;
|
if (!SOCKET_VALID(skt->fdv4) && !SOCKET_VALID(skt->fdv4)) {
|
||||||
skt->fd = ::socket(skt->family, SOCK_STREAM, 0); // Try IPv4 instead, if IPv6 fails.
|
|
||||||
}
|
|
||||||
if (!SOCKET_VALID(skt->fd)) {
|
|
||||||
return ERROR_SOCKET_CREATE;
|
return ERROR_SOCKET_CREATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// No TCP cache.
|
// No TCP cache.
|
||||||
int v = 1;
|
int v = 1;
|
||||||
setsockopt(skt->fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
|
setsockopt(skt->fdv4, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
|
||||||
|
setsockopt(skt->fdv6, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
|
||||||
|
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +149,7 @@ int srs_hijack_io_connect(srs_hijack_io_t ctx, const char* server_ip, int port)
|
||||||
|
|
||||||
addrinfo hints;
|
addrinfo hints;
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = skt->family;
|
hints.ai_family = AF_UNSPEC;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
addrinfo* r = NULL;
|
addrinfo* r = NULL;
|
||||||
|
@ -146,6 +158,15 @@ int srs_hijack_io_connect(srs_hijack_io_t ctx, const char* server_ip, int port)
|
||||||
return ERROR_SOCKET_CONNECT;
|
return ERROR_SOCKET_CONNECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skt->family = r->ai_family;
|
||||||
|
if (r->ai_family == AF_INET6) {
|
||||||
|
skt->fd = skt->fdv6;
|
||||||
|
SOCKET_RESET(skt->fdv6);
|
||||||
|
} else {
|
||||||
|
skt->fd = skt->fdv4;
|
||||||
|
SOCKET_RESET(skt->fdv4);
|
||||||
|
}
|
||||||
|
|
||||||
if(::connect(skt->fd, r->ai_addr, r->ai_addrlen) < 0){
|
if(::connect(skt->fd, r->ai_addr, r->ai_addrlen) < 0){
|
||||||
return ERROR_SOCKET_CONNECT;
|
return ERROR_SOCKET_CONNECT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1105,6 +1105,7 @@ extern void srs_hijack_io_destroy(srs_hijack_io_t ctx);
|
||||||
* create socket, not connect yet.
|
* create socket, not connect yet.
|
||||||
* @param owner, the rtmp context which create this socket.
|
* @param owner, the rtmp context which create this socket.
|
||||||
* @return 0, success; otherswise, failed.
|
* @return 0, success; otherswise, failed.
|
||||||
|
* TODO: FIXME: Incompatible API for https://github.com/ossrs/srs/blob/2.0release/trunk/src/libs/srs_librtmp.hpp#L989
|
||||||
*/
|
*/
|
||||||
extern int srs_hijack_io_create_socket(srs_hijack_io_t ctx, srs_rtmp_t owner);
|
extern int srs_hijack_io_create_socket(srs_hijack_io_t ctx, srs_rtmp_t owner);
|
||||||
/**
|
/**
|
||||||
|
@ -1156,6 +1157,7 @@ extern int srs_hijack_io_writev(srs_hijack_io_t ctx, const iovec *iov, int iov_s
|
||||||
/**
|
/**
|
||||||
* whether the timeout is never timeout in ms.
|
* whether the timeout is never timeout in ms.
|
||||||
* @return 0, with timeout specified; otherwise, never timeout.
|
* @return 0, with timeout specified; otherwise, never timeout.
|
||||||
|
* TODO: FIXME: Incompatible API for https://github.com/ossrs/srs/blob/2.0release/trunk/src/libs/srs_librtmp.hpp#L1039
|
||||||
*/
|
*/
|
||||||
extern int srs_hijack_io_is_never_timeout(srs_hijack_io_t ctx, int64_t tm);
|
extern int srs_hijack_io_is_never_timeout(srs_hijack_io_t ctx, int64_t tm);
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -122,7 +122,7 @@ void srs_discovery_tc_url(string tcUrl, string& schema, string& host, string& vh
|
||||||
srs_vhost_resolve(vhost, stream, param);
|
srs_vhost_resolve(vhost, stream, param);
|
||||||
|
|
||||||
// Ignore when the param only contains the default vhost.
|
// Ignore when the param only contains the default vhost.
|
||||||
if (param == "?vhost="SRS_CONSTS_RTMP_DEFAULT_VHOST) {
|
if (param == "?vhost=" SRS_CONSTS_RTMP_DEFAULT_VHOST) {
|
||||||
param = "";
|
param = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "stringex.hpp"
|
#include "stringex.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <srs_app_config.hpp>
|
||||||
|
|
||||||
bool is_streamid_valid(const std::string& streamid) {
|
bool is_streamid_valid(const std::string& streamid) {
|
||||||
if (streamid.empty()) {
|
if (streamid.empty()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -71,7 +73,7 @@ bool get_streamid_info(const std::string& streamid, int& mode, std::string& url_
|
||||||
if (pos != 0) {
|
if (pos != 0) {
|
||||||
pos = streamid.find("/");
|
pos = streamid.find("/");
|
||||||
if (pos == streamid.npos) {
|
if (pos == streamid.npos) {
|
||||||
url_subpath = "live/" + streamid;
|
url_subpath = _srs_config->get_default_app_name() + "/" + streamid;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
url_subpath = streamid;
|
url_subpath = streamid;
|
||||||
|
|
|
@ -256,7 +256,12 @@ void srt_server::on_work()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New API at 2020-01-28, >1.4.1
|
||||||
|
// @see https://github.com/Haivision/srt/commit/b8c70ec801a56bea151ecce9c09c4ebb720c2f68#diff-fb66028e8746fea578788532533a296bR786
|
||||||
|
#if (SRT_VERSION_MAJOR<<24 | SRT_VERSION_MINOR<<16 | SRT_VERSION_PATCH<<8) > 0x01040100
|
||||||
srt_epoll_clear_usocks(_pollid);
|
srt_epoll_clear_usocks(_pollid);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SrtServerAdapter::SrtServerAdapter()
|
SrtServerAdapter::SrtServerAdapter()
|
||||||
|
|
Loading…
Reference in a new issue