mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
commit
532a48409d
29 changed files with 1234 additions and 362 deletions
12
README.md
12
README.md
|
@ -468,6 +468,13 @@ Supported operating systems and hardware:
|
|||
[EN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_SrsLibrtmp#publish-audio-raw-stream)
|
||||
) by srs-librtmp.
|
||||
1. Support 0.1s+ latency, read [#257](https://github.com/winlinvip/simple-rtmp-server/issues/257).
|
||||
1. Support allow/deny publish/play for all or specified ip(
|
||||
[CN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_Security),
|
||||
[EN](https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_Security)
|
||||
).
|
||||
1. Support custom dvr path and http callback, read
|
||||
[#179](https://github.com/winlinvip/simple-rtmp-server/issues/179) and
|
||||
[274](https://github.com/winlinvip/simple-rtmp-server/issues/274).
|
||||
1. [no-plan] Support <500ms latency, FRSC(Fast RTMP-compatible Stream Channel tech).
|
||||
1. [no-plan] Support RTMP 302 redirect [#92](https://github.com/winlinvip/simple-rtmp-server/issues/92).
|
||||
1. [no-plan] Support multiple processes, for both origin and edge
|
||||
|
@ -501,6 +508,10 @@ Supported operating systems and hardware:
|
|||
* 2013-10-17, Created.<br/>
|
||||
|
||||
## History
|
||||
* v2.0, 2015-01-03, fix [#274](https://github.com/winlinvip/simple-rtmp-server/issues/274), http-callback support on_dvr when reap a dvr file. 2.0.89
|
||||
* v2.0, 2015-01-03, hotfix to remove the pageUrl for http callback. 2.0.88
|
||||
* v2.0, 2015-01-03, fix [#179](https://github.com/winlinvip/simple-rtmp-server/issues/179), dvr support custom filepath by variables. 2.0.87
|
||||
* v2.0, 2015-01-02, fix [#211](https://github.com/winlinvip/simple-rtmp-server/issues/211), support security allow/deny publish/play all/ip. 2.0.86
|
||||
* v2.0, 2015-01-02, hotfix [#207](https://github.com/winlinvip/simple-rtmp-server/issues/207), trim the last 0 of log. 2.0.85
|
||||
* v2.0, 2014-01-02, fix [#158](https://github.com/winlinvip/simple-rtmp-server/issues/158), http-callback check http status code ok(200). 2.0.84
|
||||
* v2.0, 2015-01-02, hotfix [#216](https://github.com/winlinvip/simple-rtmp-server/issues/216), http-callback post in application/json content-type. 2.0.83
|
||||
|
@ -550,6 +561,7 @@ Supported operating systems and hardware:
|
|||
* v2.0, 2014-10-18, remove supports for OSX(darwin). 2.0.1.
|
||||
* v2.0, 2014-10-16, revert github srs README to English. 2.0.0.
|
||||
|
||||
* v1.0, 2015-01-03, hotfix to remove the pageUrl for http callback. 1.0.19
|
||||
* v1.0, 2015-01-02, hotfix [#207](https://github.com/winlinvip/simple-rtmp-server/issues/207), trim the last 0 of log. 1.0.18
|
||||
* v1.0, 2015-01-02, hotfix [#216](https://github.com/winlinvip/simple-rtmp-server/issues/216), http-callback post in application/json content-type. 1.0.17
|
||||
* v1.0, 2015-01-01, hotfix [#270](https://github.com/winlinvip/simple-rtmp-server/issues/270), memory leak for http client post. 1.0.16
|
||||
|
|
16
trunk/conf/dvr.path.conf
Normal file
16
trunk/conf/dvr.path.conf
Normal file
|
@ -0,0 +1,16 @@
|
|||
# the config for srs to dvr in custom path.
|
||||
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#custom-path
|
||||
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#custom-path
|
||||
# @see full.conf for detail config.
|
||||
|
||||
listen 1935;
|
||||
max_connections 1000;
|
||||
vhost __defaultVhost__ {
|
||||
dvr {
|
||||
enabled on;
|
||||
dvr_path ./objs/nginx/html/[app]/[stream]/[2006]/[01]/[02]/[15].[04].[05].[999].flv;
|
||||
dvr_plan segment;
|
||||
dvr_duration 30;
|
||||
dvr_wait_keyframe on;
|
||||
}
|
||||
}
|
249
trunk/conf/full.conf
Executable file → Normal file
249
trunk/conf/full.conf
Executable file → Normal file
|
@ -142,6 +142,35 @@ http_stream {
|
|||
vhost __defaultVhost__ {
|
||||
}
|
||||
|
||||
# the security to allow or deny clients.
|
||||
vhost security.srs.com {
|
||||
# security for host to allow or deny clients.
|
||||
# @see https://github.com/winlinvip/simple-rtmp-server/issues/211
|
||||
security {
|
||||
# whether enable the security for vhost.
|
||||
# default: off
|
||||
enabled on;
|
||||
# the security list, each item format as:
|
||||
# allow|deny publish|play all|<ip>
|
||||
# for example:
|
||||
# allow publish all;
|
||||
# deny publish all;
|
||||
# allow publish 127.0.0.1;
|
||||
# deny publish 127.0.0.1;
|
||||
# allow play all;
|
||||
# deny play all;
|
||||
# allow play 127.0.0.1;
|
||||
# deny play 127.0.0.1;
|
||||
# SRS apply the following simple strategies one by one:
|
||||
# 1. allow all if security disabled.
|
||||
# 2. default to deny all when security enabled.
|
||||
# 3. allow if matches allow strategy.
|
||||
# 4. deny if matches deny strategy.
|
||||
allow play all;
|
||||
allow publish all;
|
||||
}
|
||||
}
|
||||
|
||||
# the MR(merged-read) setting for publisher.
|
||||
# the MW(merged-write) settings for player.
|
||||
vhost mrw.srs.com {
|
||||
|
@ -207,15 +236,38 @@ vhost dvr.srs.com {
|
|||
# default: off
|
||||
enabled on;
|
||||
# the dvr output path.
|
||||
# the app dir is auto created under the dvr_path.
|
||||
# for example, for rtmp stream:
|
||||
# rtmp://127.0.0.1/live/livestream
|
||||
# http://127.0.0.1/live/livestream.m3u8
|
||||
# where dvr_path is /dvr, srs will create the following files:
|
||||
# /dvr/live the app dir for all streams.
|
||||
# /dvr/live/livestream.{time}.flv the dvr flv file.
|
||||
# @remark, the time use system timestamp in ms, user can use http callback to rename it.
|
||||
# in a word, the dvr_path is for vhost.
|
||||
# we supports some variables to generate the filename.
|
||||
# [vhost], the vhost of stream.
|
||||
# [app], the app of stream.
|
||||
# [stream], the stream name of stream.
|
||||
# [2006], replace this const to current year.
|
||||
# [01], replace this const to current month.
|
||||
# [02], replace this const to current date.
|
||||
# [15], replace this const to current hour.
|
||||
# [04], repleace this const to current minute.
|
||||
# [05], repleace this const to current second.
|
||||
# [999], repleace this const to current millisecond.
|
||||
# [timestamp],replace this const to current UNIX timestamp in ms.
|
||||
# @remark we use golang time format "2006-01-02 15:04:05.999"
|
||||
# for example, for url rtmp://ossrs.net/live/livestream and time 2015-01-03 10:57:30.776
|
||||
# 1. No variables, the rule of SRS1.0(auto add [stream].[timestamp].flv as filename):
|
||||
# dvr_path ./objs/nginx/html;
|
||||
# =>
|
||||
# dvr_path ./objs/nginx/html/live/livestream.1420254068776.flv;
|
||||
# 2. Use stream and date as dir name, time as filename:
|
||||
# dvr_path /data/[vhost]/[app]/[stream]/[2006]/[01]/[02]/[15].[04].[05].[999].flv;
|
||||
# =>
|
||||
# dvr_path /data/ossrs.net/live/livestream/2015/01/03/10.57.30.776.flv;
|
||||
# 3. Use stream and year/month as dir name, date and time as filename:
|
||||
# dvr_path /data/[vhost]/[app]/[stream]/[2006]/[01]/[02]-[15].[04].[05].[999].flv;
|
||||
# =>
|
||||
# dvr_path /data/ossrs.net/live/livestream/2015/01/03-10.57.30.776.flv;
|
||||
# 4. Use vhost/app and year/month as dir name, stream/date/time as filename:
|
||||
# dvr_path /data/[vhost]/[app]/[2006]/[01]/[stream]-[02]-[15].[04].[05].[999].flv;
|
||||
# =>
|
||||
# dvr_path /data/ossrs.net/live/2015/01/livestream-03-10.57.30.776.flv;
|
||||
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#custom-path
|
||||
# @see https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#custom-path
|
||||
# default: ./objs/nginx/html
|
||||
dvr_path ./objs/nginx/html;
|
||||
# the dvr plan. canbe:
|
||||
|
@ -244,6 +296,11 @@ vhost dvr.srs.com {
|
|||
# 3. off, disable the time jitter algorithm, like atc.
|
||||
# default: full
|
||||
time_jitter full;
|
||||
|
||||
# on_dvr
|
||||
# for the dvr http callback, @see http_hooks.on_dvr of vhost hooks.callback.srs.com
|
||||
# @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_CN_DVR#http-callback
|
||||
# @read https://github.com/winlinvip/simple-rtmp-server/wiki/v2_EN_DVR#http-callback
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,7 +343,7 @@ vhost ingest.srs.com {
|
|||
}
|
||||
}
|
||||
|
||||
# vhost for http
|
||||
# vhost for http server config in each vhost.
|
||||
vhost http.srs.com {
|
||||
# http vhost specified config
|
||||
http {
|
||||
|
@ -438,6 +495,20 @@ vhost hooks.callback.srs.com {
|
|||
# support multiple api hooks, format:
|
||||
# on_stop http://xxx/api0 http://xxx/api1 http://xxx/apiN
|
||||
on_stop http://127.0.0.1:8085/api/v1/sessions http://localhost:8085/api/v1/sessions;
|
||||
# when srs reap a dvr file, call the hook,
|
||||
# the request in the POST data string is a object encode by json:
|
||||
# {
|
||||
# "action": "on_dvr",
|
||||
# "client_id": 1985,
|
||||
# "ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
# "stream": "livestream",
|
||||
# "cwd": "/usr/local/srs",
|
||||
# "file": "./objs/nginx/html/live/livestream.1420254068776.flv"
|
||||
# }
|
||||
# if valid, the hook must return HTTP code 200(Stauts OK) and response
|
||||
# an int value specifies the error code(0 corresponding to success):
|
||||
# 0
|
||||
on_dvr http://127.0.0.1:8085/api/v1/dvrs http://localhost:8085/api/v1/dvrs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -501,11 +572,105 @@ vhost same.vhost.forward.srs.com {
|
|||
# this used to split/forward the current stream for cluster active-standby,
|
||||
# active-active for cdn to build high available fault tolerance system.
|
||||
# format: {ip}:{port} {ip_N}:{port_N}
|
||||
# or specify the vhost by params, @see: change.vhost.forward.srs.com
|
||||
# if vhost not specified, use the request vhost instead.
|
||||
forward 127.0.0.1:1936 127.0.0.1:1937;
|
||||
}
|
||||
|
||||
# the main comments for transcode
|
||||
vhost example.transcode.srs.com {
|
||||
# the streaming transcode configs.
|
||||
transcode {
|
||||
# whether the transcode enabled.
|
||||
# if off, donot transcode.
|
||||
# default: off.
|
||||
enabled on;
|
||||
# the ffmpeg
|
||||
ffmpeg ./objs/ffmpeg/bin/ffmpeg;
|
||||
# the transcode engine for matched stream.
|
||||
# all matched stream will transcoded to the following stream.
|
||||
# the transcode set name(ie. hd) is optional and not used.
|
||||
engine example {
|
||||
# whether the engine is enabled
|
||||
# default: off.
|
||||
enabled on;
|
||||
# input format, can be:
|
||||
# off, do not specifies the format, ffmpeg will guess it.
|
||||
# flv, for flv or RTMP stream.
|
||||
# other format, for example, mp4/aac whatever.
|
||||
# default: flv
|
||||
iformat flv;
|
||||
# ffmpeg filters, follows the main input.
|
||||
vfilter {
|
||||
# the logo input file.
|
||||
i ./doc/ffmpeg-logo.png;
|
||||
# the ffmpeg complex filter.
|
||||
# for filters, @see: http://ffmpeg.org/ffmpeg-filters.html
|
||||
filter_complex 'overlay=10:10';
|
||||
}
|
||||
# video encoder name. can be:
|
||||
# libx264: use h.264(libx264) video encoder.
|
||||
# copy: donot encoder the video stream, copy it.
|
||||
# vn: disable video output.
|
||||
vcodec libx264;
|
||||
# video bitrate, in kbps
|
||||
vbitrate 1500;
|
||||
# video framerate.
|
||||
vfps 25;
|
||||
# video width, must be even numbers.
|
||||
vwidth 768;
|
||||
# video height, must be even numbers.
|
||||
vheight 320;
|
||||
# the max threads for ffmpeg to used.
|
||||
vthreads 12;
|
||||
# x264 profile, @see x264 -help, can be:
|
||||
# high,main,baseline
|
||||
vprofile main;
|
||||
# x264 preset, @see x264 -help, can be:
|
||||
# ultrafast,superfast,veryfast,faster,fast
|
||||
# medium,slow,slower,veryslow,placebo
|
||||
vpreset medium;
|
||||
# other x264 or ffmpeg video params
|
||||
vparams {
|
||||
# ffmpeg options, @see: http://ffmpeg.org/ffmpeg.html
|
||||
t 100;
|
||||
# 264 params, @see: http://ffmpeg.org/ffmpeg-codecs.html#libx264
|
||||
coder 1;
|
||||
b_strategy 2;
|
||||
bf 3;
|
||||
refs 10;
|
||||
}
|
||||
# audio encoder name. can be:
|
||||
# libaacplus: use aac(libaacplus) audio encoder.
|
||||
# copy: donot encoder the audio stream, copy it.
|
||||
# an: disable audio output.
|
||||
acodec libaacplus;
|
||||
# audio bitrate, in kbps. [16, 72] for libaacplus.
|
||||
abitrate 70;
|
||||
# audio sample rate. for flv/rtmp, it must be:
|
||||
# 44100,22050,11025,5512
|
||||
asample_rate 44100;
|
||||
# audio channel, 1 for mono, 2 for stereo.
|
||||
achannels 2;
|
||||
# other ffmpeg audio params
|
||||
aparams {
|
||||
# audio params, @see: http://ffmpeg.org/ffmpeg-codecs.html#Audio-Encoders
|
||||
profile:a aac_low;
|
||||
}
|
||||
# output format, can be:
|
||||
# off, do not specifies the format, ffmpeg will guess it.
|
||||
# flv, for flv or RTMP stream.
|
||||
# other format, for example, mp4/aac whatever.
|
||||
# default: flv
|
||||
oformat flv;
|
||||
# output stream. variables:
|
||||
# [vhost] the input stream vhost.
|
||||
# [port] the intput stream port.
|
||||
# [app] the input stream app.
|
||||
# [stream] the input stream name.
|
||||
# [engine] the tanscode engine name.
|
||||
output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine];
|
||||
}
|
||||
}
|
||||
}
|
||||
# the mirror filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#Filtering-Introduction
|
||||
vhost mirror.transcode.srs.com {
|
||||
transcode {
|
||||
|
@ -536,10 +701,8 @@ vhost mirror.transcode.srs.com {
|
|||
}
|
||||
}
|
||||
}
|
||||
#
|
||||
# the drawtext filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#drawtext-1
|
||||
# remark: we remove the libfreetype which always cause build failed, you must add it manual if needed.
|
||||
#
|
||||
#######################################################################################################
|
||||
# the crop filter of ffmpeg, @see: http://ffmpeg.org/ffmpeg-filters.html#crop
|
||||
vhost crop.transcode.srs.com {
|
||||
|
@ -656,97 +819,41 @@ vhost copy.transcode.srs.com {
|
|||
}
|
||||
}
|
||||
# transcode all app and stream of vhost
|
||||
# the comments, read example.transcode.srs.com
|
||||
vhost all.transcode.srs.com {
|
||||
# the streaming transcode configs.
|
||||
transcode {
|
||||
# whether the transcode enabled.
|
||||
# if off, donot transcode.
|
||||
# default: off.
|
||||
enabled on;
|
||||
# the ffmpeg
|
||||
ffmpeg ./objs/ffmpeg/bin/ffmpeg;
|
||||
# the transcode engine for matched stream.
|
||||
# all matched stream will transcoded to the following stream.
|
||||
# the transcode set name(ie. hd) is optional and not used.
|
||||
engine ffsuper {
|
||||
# whether the engine is enabled
|
||||
# default: off.
|
||||
enabled on;
|
||||
# input format, can be:
|
||||
# off, do not specifies the format, ffmpeg will guess it.
|
||||
# flv, for flv or RTMP stream.
|
||||
# other format, for example, mp4/aac whatever.
|
||||
# default: flv
|
||||
iformat flv;
|
||||
# ffmpeg filters, follows the main input.
|
||||
vfilter {
|
||||
# the logo input file.
|
||||
i ./doc/ffmpeg-logo.png;
|
||||
# the ffmpeg complex filter.
|
||||
# for filters, @see: http://ffmpeg.org/ffmpeg-filters.html
|
||||
filter_complex 'overlay=10:10';
|
||||
}
|
||||
# video encoder name. can be:
|
||||
# libx264: use h.264(libx264) video encoder.
|
||||
# copy: donot encoder the video stream, copy it.
|
||||
# vn: disable video output.
|
||||
vcodec libx264;
|
||||
# video bitrate, in kbps
|
||||
vbitrate 1500;
|
||||
# video framerate.
|
||||
vfps 25;
|
||||
# video width, must be even numbers.
|
||||
vwidth 768;
|
||||
# video height, must be even numbers.
|
||||
vheight 320;
|
||||
# the max threads for ffmpeg to used.
|
||||
vthreads 12;
|
||||
# x264 profile, @see x264 -help, can be:
|
||||
# high,main,baseline
|
||||
vprofile main;
|
||||
# x264 preset, @see x264 -help, can be:
|
||||
# ultrafast,superfast,veryfast,faster,fast
|
||||
# medium,slow,slower,veryslow,placebo
|
||||
vpreset medium;
|
||||
# other x264 or ffmpeg video params
|
||||
vparams {
|
||||
# ffmpeg options, @see: http://ffmpeg.org/ffmpeg.html
|
||||
t 100;
|
||||
# 264 params, @see: http://ffmpeg.org/ffmpeg-codecs.html#libx264
|
||||
coder 1;
|
||||
b_strategy 2;
|
||||
bf 3;
|
||||
refs 10;
|
||||
}
|
||||
# audio encoder name. can be:
|
||||
# libaacplus: use aac(libaacplus) audio encoder.
|
||||
# copy: donot encoder the audio stream, copy it.
|
||||
# an: disable audio output.
|
||||
acodec libaacplus;
|
||||
# audio bitrate, in kbps. [16, 72] for libaacplus.
|
||||
abitrate 70;
|
||||
# audio sample rate. for flv/rtmp, it must be:
|
||||
# 44100,22050,11025,5512
|
||||
asample_rate 44100;
|
||||
# audio channel, 1 for mono, 2 for stereo.
|
||||
achannels 2;
|
||||
# other ffmpeg audio params
|
||||
aparams {
|
||||
# audio params, @see: http://ffmpeg.org/ffmpeg-codecs.html#Audio-Encoders
|
||||
profile:a aac_low;
|
||||
}
|
||||
# output format, can be:
|
||||
# off, do not specifies the format, ffmpeg will guess it.
|
||||
# flv, for flv or RTMP stream.
|
||||
# other format, for example, mp4/aac whatever.
|
||||
# default: flv
|
||||
oformat flv;
|
||||
# output stream. variables:
|
||||
# [vhost] the input stream vhost.
|
||||
# [port] the intput stream port.
|
||||
# [app] the input stream app.
|
||||
# [stream] the input stream name.
|
||||
# [engine] the tanscode engine name.
|
||||
output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine];
|
||||
}
|
||||
engine ffhd {
|
||||
|
|
0
trunk/conf/realtime.conf
Executable file → Normal file
0
trunk/conf/realtime.conf
Executable file → Normal file
13
trunk/conf/security.deny.publish.conf
Normal file
13
trunk/conf/security.deny.publish.conf
Normal file
|
@ -0,0 +1,13 @@
|
|||
# security config for srs, allow play and deny publish.
|
||||
# @see https://github.com/winlinvip/simple-rtmp-server/issues/211#issuecomment-68507035
|
||||
# @see full.conf for detail config.
|
||||
|
||||
listen 1935;
|
||||
max_connections 1000;
|
||||
vhost __defaultVhost__ {
|
||||
security {
|
||||
enabled on;
|
||||
deny publish all;
|
||||
allow play all;
|
||||
}
|
||||
}
|
2
trunk/configure
vendored
2
trunk/configure
vendored
|
@ -389,7 +389,7 @@ if [ $SRS_EXPORT_LIBRTMP_PROJECT = NO ]; then
|
|||
"srs_app_pithy_print" "srs_app_reload" "srs_app_http_api" "srs_app_http_conn" "srs_app_http_hooks"
|
||||
"srs_app_json" "srs_app_ingest" "srs_app_ffmpeg" "srs_app_utility" "srs_app_dvr" "srs_app_edge"
|
||||
"srs_app_kbps" "srs_app_heartbeat" "srs_app_empty" "srs_app_http_client" "srs_app_avc_aac"
|
||||
"srs_app_recv_thread" "srs_app_statistic")
|
||||
"srs_app_recv_thread" "srs_app_security" "srs_app_statistic")
|
||||
APP_INCS="src/app"; MODULE_DIR=${APP_INCS} . auto/modules.sh
|
||||
APP_OBJS="${MODULE_OBJS[@]}"
|
||||
fi
|
||||
|
|
|
@ -240,6 +240,74 @@ class RESTStreams(object):
|
|||
|
||||
return code
|
||||
|
||||
'''
|
||||
handle the dvrs requests: dvr stream.
|
||||
'''
|
||||
class RESTDvrs(object):
|
||||
exposed = True
|
||||
|
||||
def GET(self):
|
||||
enable_crossdomain()
|
||||
|
||||
dvrs = {}
|
||||
return json.dumps(dvrs)
|
||||
|
||||
'''
|
||||
for SRS hook: on_dvr
|
||||
on_dvr:
|
||||
when srs reap a dvr file, call the hook,
|
||||
the request in the POST data string is a object encode by json:
|
||||
{
|
||||
"action": "on_dvr",
|
||||
"client_id": 1985,
|
||||
"ip": "192.168.1.10", "vhost": "video.test.com", "app": "live",
|
||||
"stream": "livestream",
|
||||
"cwd": "/usr/local/srs",
|
||||
"file": "./objs/nginx/html/live/livestream.1420254068776.flv"
|
||||
}
|
||||
if valid, the hook must return HTTP code 200(Stauts OK) and response
|
||||
an int value specifies the error code(0 corresponding to success):
|
||||
0
|
||||
'''
|
||||
def POST(self):
|
||||
enable_crossdomain()
|
||||
|
||||
# return the error code in str
|
||||
code = Error.success
|
||||
|
||||
req = cherrypy.request.body.read()
|
||||
trace("post to dvrs, req=%s"%(req))
|
||||
try:
|
||||
json_req = json.loads(req)
|
||||
except Exception, ex:
|
||||
code = Error.system_parse_json
|
||||
trace("parse the request to json failed, req=%s, ex=%s, code=%s"%(req, ex, code))
|
||||
return str(code)
|
||||
|
||||
action = json_req["action"]
|
||||
if action == "on_dvr":
|
||||
code = self.__on_dvr(json_req)
|
||||
else:
|
||||
trace("invalid request action: %s"%(json_req["action"]))
|
||||
code = Error.request_invalid_action
|
||||
|
||||
return str(code)
|
||||
|
||||
def OPTIONS(self, *args, **kwargs):
|
||||
enable_crossdomain()
|
||||
|
||||
def __on_dvr(self, req):
|
||||
code = Error.success
|
||||
|
||||
trace("srs %s: client id=%s, ip=%s, vhost=%s, app=%s, stream=%s, cwd=%s, file=%s"%(
|
||||
req["action"], req["client_id"], req["ip"], req["vhost"], req["app"], req["stream"],
|
||||
req["cwd"], req["file"]
|
||||
))
|
||||
|
||||
# TODO: process the on_dvr event
|
||||
|
||||
return code
|
||||
|
||||
'''
|
||||
handle the sessions requests: client play/stop stream
|
||||
'''
|
||||
|
@ -1039,6 +1107,7 @@ class V1(object):
|
|||
self.clients = RESTClients()
|
||||
self.streams = RESTStreams()
|
||||
self.sessions = RESTSessions()
|
||||
self.dvrs = RESTDvrs()
|
||||
self.chats = RESTChats()
|
||||
self.servers = RESTServers()
|
||||
self.nodes = RESTNodes()
|
||||
|
@ -1048,6 +1117,7 @@ class V1(object):
|
|||
"clients": "for srs http callback, to handle the clients requests: connect/disconnect vhost/app.",
|
||||
"streams": "for srs http callback, to handle the streams requests: publish/unpublish stream.",
|
||||
"sessions": "for srs http callback, to handle the sessions requests: client play/stop stream",
|
||||
"dvrs": "for srs http callback, to handle the dvr requests: dvr stream.",
|
||||
"chats": "for srs demo meeting, the chat streams, public chat room.",
|
||||
"nodes": {
|
||||
"summary": "for srs cdn node",
|
||||
|
|
|
@ -15,7 +15,7 @@ ret=$?; if [[ 0 -ne $ret ]]; then
|
|||
exit $ret
|
||||
fi
|
||||
|
||||
files=`git status|egrep "(modified|new file)"|awk -F ':' '{print $2}'|awk '{print $1}'|egrep "(.hpp$|.cpp$|.cc$|.h$|.c$|.txt$|.sh$)"`;
|
||||
files=`git status|egrep "(modified|new file)"|awk -F ':' '{print $2}'|awk '{print $1}'|egrep "(.hpp$|.cpp$|.cc$|.h$|.c$|.txt$|.sh|.conf$)"`;
|
||||
for file in $files; do
|
||||
dos2unix $file;
|
||||
echo $file|grep ".sh$" >/dev/null 2>&1; EOF_SH=$?
|
||||
|
|
|
@ -434,7 +434,8 @@ int SrsConfig::reload_conf(SrsConfig* conf)
|
|||
// always support reload without additional code:
|
||||
// chunk_size, ff_log_dir, max_connections,
|
||||
// bandcheck, http_hooks, heartbeat,
|
||||
// token_traverse, debug_srs_upnode
|
||||
// token_traverse, debug_srs_upnode,
|
||||
// security
|
||||
|
||||
// merge config: listen
|
||||
if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) {
|
||||
|
@ -1363,6 +1364,7 @@ int SrsConfig::check_config()
|
|||
&& n != "atc" && n != "atc_auto"
|
||||
&& n != "debug_srs_upnode"
|
||||
&& n != "mr" && n != "mw_latency" && n != "min_latency"
|
||||
&& n != "security"
|
||||
) {
|
||||
ret = ERROR_SYSTEM_CONFIG_INVALID;
|
||||
srs_error("unsupported vhost directive %s, ret=%d", n.c_str(), ret);
|
||||
|
@ -1424,6 +1426,7 @@ int SrsConfig::check_config()
|
|||
string m = conf->at(j)->name.c_str();
|
||||
if (m != "enabled" && m != "on_connect" && m != "on_close" && m != "on_publish"
|
||||
&& m != "on_unpublish" && m != "on_play" && m != "on_stop"
|
||||
&& m != "on_dvr"
|
||||
) {
|
||||
ret = ERROR_SYSTEM_CONFIG_INVALID;
|
||||
srs_error("unsupported vhost http_hooks directive %s, ret=%d", m.c_str(), ret);
|
||||
|
@ -1440,6 +1443,16 @@ int SrsConfig::check_config()
|
|||
return ret;
|
||||
}
|
||||
}*/
|
||||
} else if (n == "security") {
|
||||
for (int j = 0; j < (int)conf->directives.size(); j++) {
|
||||
SrsConfDirective* security = conf->at(j);
|
||||
string m = security->name.c_str();
|
||||
if (m != "enabled" && m != "deny" && m != "allow") {
|
||||
ret = ERROR_SYSTEM_CONFIG_INVALID;
|
||||
srs_error("unsupported vhost security directive %s, ret=%d", m.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else if (n == "transcode") {
|
||||
for (int j = 0; j < (int)conf->directives.size(); j++) {
|
||||
SrsConfDirective* trans = conf->at(j);
|
||||
|
@ -2323,6 +2336,17 @@ SrsConfDirective* SrsConfig::get_vhost_on_stop(string vhost)
|
|||
return conf->get("on_stop");
|
||||
}
|
||||
|
||||
SrsConfDirective* SrsConfig::get_vhost_on_dvr(string vhost)
|
||||
{
|
||||
SrsConfDirective* conf = get_vhost_http_hooks(vhost);
|
||||
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return conf->get("on_dvr");
|
||||
}
|
||||
|
||||
bool SrsConfig::get_bw_check_enabled(string vhost)
|
||||
{
|
||||
SrsConfDirective* conf = get_vhost(vhost);
|
||||
|
@ -2456,6 +2480,43 @@ bool SrsConfig::get_vhost_edge_token_traverse(string vhost)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SrsConfig::get_security_enabled(string vhost)
|
||||
{
|
||||
SrsConfDirective* conf = get_vhost(vhost);
|
||||
|
||||
if (!conf) {
|
||||
return SRS_CONF_DEFAULT_SECURITY_ENABLED;
|
||||
}
|
||||
|
||||
SrsConfDirective* security = conf->get("security");
|
||||
if (!security) {
|
||||
return SRS_CONF_DEFAULT_SECURITY_ENABLED;
|
||||
}
|
||||
|
||||
conf = security->get("enabled");
|
||||
if (!conf || conf->arg0() != "on") {
|
||||
return SRS_CONF_DEFAULT_SECURITY_ENABLED;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SrsConfDirective* SrsConfig::get_security_rules(string vhost)
|
||||
{
|
||||
SrsConfDirective* conf = get_vhost(vhost);
|
||||
|
||||
if (!conf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SrsConfDirective* security = conf->get("security");
|
||||
if (!security) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return security;
|
||||
}
|
||||
|
||||
SrsConfDirective* SrsConfig::get_transcode(string vhost, string scope)
|
||||
{
|
||||
SrsConfDirective* conf = get_vhost(vhost);
|
||||
|
|
|
@ -76,6 +76,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define SRS_CONF_DEFAULT_HTTP_HEAETBEAT_URL "http://"SRS_CONSTS_LOCALHOST":8085/api/v1/servers"
|
||||
#define SRS_CONF_DEFAULT_HTTP_HEAETBEAT_SUMMARIES false
|
||||
|
||||
#define SRS_CONF_DEFAULT_SECURITY_ENABLED false
|
||||
|
||||
#define SRS_CONF_DEFAULT_STATS_NETWORK_DEVICE_INDEX 0
|
||||
|
||||
#define SRS_CONF_DEFAULT_STAGE_PLAY_USER_INTERVAL_MS 10000
|
||||
|
@ -608,6 +610,11 @@ public:
|
|||
* @return the on_stop callback directive, the args is the url to callback.
|
||||
*/
|
||||
virtual SrsConfDirective* get_vhost_on_stop(std::string vhost);
|
||||
/**
|
||||
* get the on_dvr callbacks of vhost.
|
||||
* @return the on_dvr callback directive, the args is the url to callback.
|
||||
*/
|
||||
virtual SrsConfDirective* get_vhost_on_dvr(std::string vhost);
|
||||
// bwct(bandwidth check tool) section
|
||||
public:
|
||||
/**
|
||||
|
@ -659,6 +666,16 @@ public:
|
|||
* all clients connected to edge must be tranverse to origin to verify.
|
||||
*/
|
||||
virtual bool get_vhost_edge_token_traverse(std::string vhost);
|
||||
// vhost security section
|
||||
public:
|
||||
/**
|
||||
* whether the secrity of vhost enabled.
|
||||
*/
|
||||
virtual bool get_security_enabled(std::string vhost);
|
||||
/**
|
||||
* get the security rules.
|
||||
*/
|
||||
virtual SrsConfDirective* get_security_rules(std::string vhost);
|
||||
// vhost transcode section
|
||||
public:
|
||||
/**
|
||||
|
@ -776,7 +793,7 @@ public:
|
|||
* @remark, we will use some variable, for instance, [vhost] to substitude with vhost.
|
||||
*/
|
||||
virtual std::string get_engine_output(SrsConfDirective* engine);
|
||||
// ingest section
|
||||
// vhost ingest section
|
||||
public:
|
||||
/**
|
||||
* get the ingest directives of vhost.
|
||||
|
|
|
@ -27,6 +27,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#include <fcntl.h>
|
||||
#include <sstream>
|
||||
#include <sys/time.h>
|
||||
using namespace std;
|
||||
|
||||
#include <srs_app_config.hpp>
|
||||
|
@ -136,14 +137,97 @@ int SrsDvrPlan::open_new_segment()
|
|||
|
||||
SrsRequest* req = _req;
|
||||
|
||||
// new flv file
|
||||
std::stringstream path;
|
||||
// the path in config, for example,
|
||||
// /data/[vhost]/[app]/[stream]/[2006]/[01]/[02]/[15].[04].[05].[999].flv
|
||||
std::string path_config = _srs_config->get_dvr_path(req->vhost);
|
||||
|
||||
path << _srs_config->get_dvr_path(req->vhost)
|
||||
<< "/" << req->app << "/"
|
||||
<< req->stream << "." << srs_get_system_time_ms() << ".flv";
|
||||
// add [stream].[timestamp].flv as filename for dir
|
||||
if (path_config.find(".flv") != path_config.length() - 4) {
|
||||
path_config += "/[stream].[timestamp].flv";
|
||||
}
|
||||
|
||||
if ((ret = flv_open(req->get_stream_url(), path.str())) != ERROR_SUCCESS) {
|
||||
// the flv file path
|
||||
std::string path = path_config;
|
||||
|
||||
// variable [vhost]
|
||||
path = srs_string_replace(path, "[vhost]", req->vhost);
|
||||
// variable [app]
|
||||
path = srs_string_replace(path, "[app]", req->app);
|
||||
// variable [stream]
|
||||
path = srs_string_replace(path, "[stream]", req->stream);
|
||||
|
||||
// date and time substitude
|
||||
// clock time
|
||||
timeval tv;
|
||||
if (gettimeofday(&tv, NULL) == -1) {
|
||||
return ERROR_SYSTEM_TIME;
|
||||
}
|
||||
|
||||
// to calendar time
|
||||
struct tm* tm;
|
||||
if ((tm = localtime(&tv.tv_sec)) == NULL) {
|
||||
return ERROR_SYSTEM_TIME;
|
||||
}
|
||||
|
||||
// the buffer to format the date and time.
|
||||
char buf[64];
|
||||
|
||||
// [2006], replace with current year.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", 1900 + tm->tm_year);
|
||||
path = srs_string_replace(path, "[2006]", buf);
|
||||
}
|
||||
// [2006], replace with current year.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", 1900 + tm->tm_year);
|
||||
path = srs_string_replace(path, "[2006]", buf);
|
||||
}
|
||||
// [01], replace this const to current month.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", 1 + tm->tm_mon);
|
||||
path = srs_string_replace(path, "[01]", buf);
|
||||
}
|
||||
// [02], replace this const to current date.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_mday);
|
||||
path = srs_string_replace(path, "[02]", buf);
|
||||
}
|
||||
// [15], replace this const to current hour.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_hour);
|
||||
path = srs_string_replace(path, "[15]", buf);
|
||||
}
|
||||
// [04], repleace this const to current minute.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_min);
|
||||
path = srs_string_replace(path, "[04]", buf);
|
||||
}
|
||||
// [05], repleace this const to current second.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%d", tm->tm_sec);
|
||||
path = srs_string_replace(path, "[05]", buf);
|
||||
}
|
||||
// [999], repleace this const to current millisecond.
|
||||
if (true) {
|
||||
snprintf(buf, sizeof(buf), "%03d", (int)(tv.tv_usec / 1000));
|
||||
path = srs_string_replace(path, "[999]", buf);
|
||||
}
|
||||
// [timestamp],replace this const to current UNIX timestamp in ms.
|
||||
if (true) {
|
||||
int64_t now_us = ((int64_t)tv.tv_sec) * 1000 * 1000 + (int64_t)tv.tv_usec;
|
||||
snprintf(buf, sizeof(buf), "%"PRId64, now_us / 1000);
|
||||
path = srs_string_replace(path, "[timestamp]", buf);
|
||||
}
|
||||
|
||||
// create dir first.
|
||||
std::string dir = path.substr(0, path.rfind("/"));
|
||||
if ((ret = srs_create_dir_recursively(dir)) != ERROR_SUCCESS) {
|
||||
srs_error("create dir=%s failed. ret=%d", dir.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("create dir=%s ok", dir.c_str());
|
||||
|
||||
if ((ret = flv_open(req->get_stream_url(), path)) != ERROR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
dvr_enabled = true;
|
||||
|
@ -320,6 +404,30 @@ int SrsDvrPlan::flv_close()
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef SRS_AUTO_HTTP_CALLBACK
|
||||
SrsRequest* req = _req;
|
||||
if (_srs_config->get_vhost_http_hooks_enabled(req->vhost)) {
|
||||
// HTTP: on_dvr
|
||||
SrsConfDirective* on_dvr = _srs_config->get_vhost_on_dvr(req->vhost);
|
||||
if (!on_dvr) {
|
||||
srs_info("ignore the empty http callback: on_dvr");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int connection_id = _srs_context->get_id();
|
||||
std::string ip = req->ip;
|
||||
std::string cwd = _srs_config->cwd();
|
||||
std::string file = segment->path;
|
||||
for (int i = 0; i < (int)on_dvr->args.size(); i++) {
|
||||
std::string url = on_dvr->args.at(i);
|
||||
if ((ret = SrsHttpHooks::on_dvr(url, connection_id, ip, req, cwd, file)) != ERROR_SUCCESS) {
|
||||
srs_error("hook client on_dvr failed. url=%s, ret=%d", url.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -951,16 +951,12 @@ int SrsHlsMuxer::create_dir()
|
|||
app_dir += app;
|
||||
|
||||
// TODO: cleanup the dir when startup.
|
||||
|
||||
mode_t mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH;
|
||||
if (::mkdir(app_dir.c_str(), mode) < 0) {
|
||||
if (errno != EEXIST) {
|
||||
ret = ERROR_HLS_CREATE_DIR;
|
||||
srs_error("create app dir %s failed. ret=%d", app_dir.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = srs_create_dir_recursively(app_dir)) != ERROR_SUCCESS) {
|
||||
srs_error("create app dir %s failed. ret=%d", app_dir.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("create app dir %s success.", app_dir.c_str());
|
||||
srs_info("create app dir %s ok", app_dir.c_str());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#ifdef SRS_AUTO_HTTP_API
|
||||
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
using namespace std;
|
||||
|
||||
#include <srs_kernel_log.hpp>
|
||||
|
@ -153,8 +152,8 @@ int SrsApiV1::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
|||
<< __SRS_JFIELD_STR("meminfos", "the meminfo of system") << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("authors", "the primary authors and contributors") << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("requests", "the request itself, for http debug") << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("vhosts", "list all vhosts") << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("streams", "list streams that match the name or vhost")
|
||||
<< __SRS_JFIELD_STR("vhosts", "dumps vhost to json") << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("streams", "dumps streams to json")
|
||||
<< __SRS_JOBJECT_END
|
||||
<< __SRS_JOBJECT_END;
|
||||
|
||||
|
@ -522,30 +521,19 @@ bool SrsApiVhosts::can_handle(const char* path, int length, const char** /*pchil
|
|||
|
||||
int SrsApiVhosts::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||
{
|
||||
std::stringstream data;
|
||||
SrsStatistic* stat = SrsStatistic::instance();
|
||||
int ret = stat->dumps_vhosts(data);
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
std::set<std::string> vhost_set;
|
||||
SrsStreamInfoMap* pool = SrsStatistic::instance()->get_pool();
|
||||
SrsStreamInfoMap::iterator it;
|
||||
for (it = pool->begin(); it != pool->end(); it++) {
|
||||
if (it->second->_req == NULL)
|
||||
continue;
|
||||
vhost_set.insert(it->second->_req->vhost);
|
||||
}
|
||||
|
||||
ss << __SRS_JARRAY_START;
|
||||
bool first = true;
|
||||
std::set<std::string>::iterator it_set;
|
||||
for (it_set = vhost_set.begin(); it_set != vhost_set.end(); it_set++) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
ss << __SRS_JFIELD_CONT;
|
||||
}
|
||||
|
||||
ss << "\"" << (*it_set) << "\"";
|
||||
}
|
||||
ss << __SRS_JARRAY_END;
|
||||
ss << __SRS_JOBJECT_START
|
||||
<< __SRS_JFIELD_ERROR(ret) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_ORG("server", stat->server_id()) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_ORG("vhosts", __SRS_JARRAY_START)
|
||||
<< data.str()
|
||||
<< __SRS_JARRAY_END
|
||||
<< __SRS_JOBJECT_END;
|
||||
|
||||
return res_json(skt, req, ss.str());
|
||||
}
|
||||
|
@ -565,41 +553,19 @@ bool SrsApiStreams::can_handle(const char* path, int length, const char** /*pchi
|
|||
|
||||
int SrsApiStreams::do_process_request(SrsStSocket* skt, SrsHttpMessage* req)
|
||||
{
|
||||
std::stringstream data;
|
||||
SrsStatistic* stat = SrsStatistic::instance();
|
||||
int ret = stat->dumps_streams(data);
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
std::string query_name = req->query_get("name");
|
||||
std::string query_vhost = req->query_get("vhost");
|
||||
if (query_name.size() > 0 || query_vhost.size() > 0) {
|
||||
ss << __SRS_JARRAY_START;
|
||||
bool first = true;
|
||||
SrsStreamInfoMap* pool = SrsStatistic::instance()->get_pool();
|
||||
SrsStreamInfoMap::iterator it;
|
||||
for (it = pool->begin(); it != pool->end(); it++) {
|
||||
SrsRequest* reqinfo = it->second->_req;
|
||||
if (reqinfo == NULL)
|
||||
continue;
|
||||
|
||||
if (reqinfo->stream == query_name || reqinfo->vhost == query_vhost) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
ss << __SRS_JFIELD_CONT;
|
||||
}
|
||||
|
||||
ss << __SRS_JOBJECT_START
|
||||
<< __SRS_JFIELD_STR("name", reqinfo->stream) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("url", reqinfo->tcUrl) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_ORG("clients", 0) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("status", "idle") << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("type", "") << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("codec", "")
|
||||
<< __SRS_JOBJECT_END;
|
||||
}
|
||||
}
|
||||
ss << __SRS_JARRAY_END;
|
||||
} else {
|
||||
return res_error(skt, req, 400, "Bad Request", "unknown query");
|
||||
}
|
||||
ss << __SRS_JOBJECT_START
|
||||
<< __SRS_JFIELD_ERROR(ret) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_ORG("server", stat->server_id()) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_ORG("streams", __SRS_JARRAY_START)
|
||||
<< data.str()
|
||||
<< __SRS_JARRAY_END
|
||||
<< __SRS_JOBJECT_END;
|
||||
|
||||
return res_json(skt, req, ss.str());
|
||||
}
|
||||
|
|
|
@ -122,8 +122,7 @@ void SrsHttpHooks::on_close(string url, int client_id, string ip, SrsRequest* re
|
|||
<< __SRS_JFIELD_ORG("client_id", client_id) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("ip", ip) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("pageUrl", req->pageUrl)
|
||||
<< __SRS_JFIELD_STR("app", req->app)
|
||||
<< __SRS_JOBJECT_END;
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
|
@ -178,7 +177,6 @@ int SrsHttpHooks::on_publish(string url, int client_id, string ip, SrsRequest* r
|
|||
<< __SRS_JFIELD_STR("ip", ip) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("pageUrl", req->pageUrl) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("stream", req->stream)
|
||||
<< __SRS_JOBJECT_END;
|
||||
std::string data = ss.str();
|
||||
|
@ -234,7 +232,6 @@ void SrsHttpHooks::on_unpublish(string url, int client_id, string ip, SrsRequest
|
|||
<< __SRS_JFIELD_STR("ip", ip) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("pageUrl", req->pageUrl) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("stream", req->stream)
|
||||
<< __SRS_JOBJECT_END;
|
||||
std::string data = ss.str();
|
||||
|
@ -290,7 +287,6 @@ int SrsHttpHooks::on_play(string url, int client_id, string ip, SrsRequest* req)
|
|||
<< __SRS_JFIELD_STR("ip", ip) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("pageUrl", req->pageUrl) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("stream", req->stream)
|
||||
<< __SRS_JOBJECT_END;
|
||||
std::string data = ss.str();
|
||||
|
@ -346,7 +342,6 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req
|
|||
<< __SRS_JFIELD_STR("ip", ip) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("pageUrl", req->pageUrl) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("stream", req->stream)
|
||||
<< __SRS_JOBJECT_END;
|
||||
std::string data = ss.str();
|
||||
|
@ -384,5 +379,61 @@ void SrsHttpHooks::on_stop(string url, int client_id, string ip, SrsRequest* req
|
|||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
int SrsHttpHooks::on_dvr(string url, int client_id, string ip, SrsRequest* req, string cwd, string file)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
SrsHttpUri uri;
|
||||
if ((ret = uri.initialize(url)) != ERROR_SUCCESS) {
|
||||
srs_error("http uri parse on_dvr url failed, ignored. "
|
||||
"client_id=%d, url=%s, ret=%d", client_id, url.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << __SRS_JOBJECT_START
|
||||
<< __SRS_JFIELD_STR("action", "on_dvr") << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_ORG("client_id", client_id) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("ip", ip) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("vhost", req->vhost) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("app", req->app) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("stream", req->stream) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("cwd", cwd) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("file", file)
|
||||
<< __SRS_JOBJECT_END;
|
||||
std::string data = ss.str();
|
||||
std::string res;
|
||||
int status_code;
|
||||
|
||||
SrsHttpClient http;
|
||||
if ((ret = http.post(&uri, data, status_code, res)) != ERROR_SUCCESS) {
|
||||
srs_error("http post on_dvr uri failed, ignored. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ensure the http status is ok.
|
||||
// https://github.com/winlinvip/simple-rtmp-server/issues/158
|
||||
if (status_code != SRS_CONSTS_HTTP_OK) {
|
||||
ret = ERROR_HTTP_STATUS_INVLIAD;
|
||||
srs_error("http hook on_dvr status failed. "
|
||||
"client_id=%d, code=%d, ret=%d", client_id, status_code, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (res.empty() || res != SRS_HTTP_RESPONSE_OK) {
|
||||
ret = ERROR_HTTP_DATA_INVLIAD;
|
||||
srs_warn("http hook on_dvr validate failed, ignored. "
|
||||
"client_id=%d, res=%s, ret=%d", client_id, res.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
srs_trace("http hook on_dvr success. "
|
||||
"client_id=%d, url=%s, request=%s, response=%s, ret=%d",
|
||||
client_id, url.c_str(), data.c_str(), res.c_str(), ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -58,7 +58,6 @@ public:
|
|||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to valid the client.
|
||||
* ignore if empty.
|
||||
* @return valid failed or connect to the url failed.
|
||||
*/
|
||||
static int on_connect(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||
/**
|
||||
|
@ -73,7 +72,6 @@ public:
|
|||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to valid the client.
|
||||
* ignore if empty.
|
||||
* @return valid failed or connect to the url failed.
|
||||
*/
|
||||
static int on_publish(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||
/**
|
||||
|
@ -88,7 +86,6 @@ public:
|
|||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to valid the client.
|
||||
* ignore if empty.
|
||||
* @return valid failed or connect to the url failed.
|
||||
*/
|
||||
static int on_play(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||
/**
|
||||
|
@ -98,6 +95,15 @@ public:
|
|||
* ignore if empty.
|
||||
*/
|
||||
static void on_stop(std::string url, int client_id, std::string ip, SrsRequest* req);
|
||||
/**
|
||||
* on_dvr hook, when reap a dvr file.
|
||||
* @param client_id the id of client on server.
|
||||
* @param url the api server url, to process the event.
|
||||
* ignore if empty.
|
||||
* @param cwd the current work directory, used to resolve the reltive file path.
|
||||
* @param file the file path, can be relative or absolute path.
|
||||
*/
|
||||
static int on_dvr(std::string url, int client_id, std::string ip, SrsRequest* req, std::string cwd, std::string file);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,6 +51,7 @@ using namespace std;
|
|||
#include <srs_app_recv_thread.hpp>
|
||||
#include <srs_core_performance.hpp>
|
||||
#include <srs_kernel_utility.hpp>
|
||||
#include <srs_app_security.hpp>
|
||||
#include <srs_app_statistic.hpp>
|
||||
|
||||
// when stream is busy, for example, streaming is already
|
||||
|
@ -82,6 +83,7 @@ SrsRtmpConn::SrsRtmpConn(SrsServer* srs_server, st_netfd_t client_stfd)
|
|||
rtmp = new SrsRtmpServer(skt);
|
||||
refer = new SrsRefer();
|
||||
bandwidth = new SrsBandwidth();
|
||||
security = new SrsSecurity();
|
||||
duration = 0;
|
||||
kbps = new SrsKbps();
|
||||
kbps->set_io(skt, skt);
|
||||
|
@ -103,6 +105,7 @@ SrsRtmpConn::~SrsRtmpConn()
|
|||
srs_freep(skt);
|
||||
srs_freep(refer);
|
||||
srs_freep(bandwidth);
|
||||
srs_freep(security);
|
||||
srs_freep(kbps);
|
||||
}
|
||||
|
||||
|
@ -133,6 +136,9 @@ int SrsRtmpConn::do_cycle()
|
|||
}
|
||||
srs_verbose("rtmp connect app success");
|
||||
|
||||
// set client ip to request.
|
||||
req->ip = ip;
|
||||
|
||||
// discovery vhost, resolve the vhost from config
|
||||
SrsConfDirective* parsed_vhost = _srs_config->get_vhost(req->vhost);
|
||||
if (parsed_vhost) {
|
||||
|
@ -361,6 +367,13 @@ int SrsRtmpConn::stream_service_cycle()
|
|||
req->strip();
|
||||
srs_trace("client identified, type=%s, stream_name=%s, duration=%.2f",
|
||||
srs_client_type_string(type).c_str(), req->stream.c_str(), req->duration);
|
||||
|
||||
// security check
|
||||
if ((ret = security->check(type, ip, req)) != ERROR_SUCCESS) {
|
||||
srs_error("security check failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("security check ok");
|
||||
|
||||
// client is identified, set the timeout to service timeout.
|
||||
rtmp->set_recv_timeout(SRS_CONSTS_RTMP_RECV_TIMEOUT_US);
|
||||
|
@ -383,7 +396,12 @@ int SrsRtmpConn::stream_service_cycle()
|
|||
}
|
||||
srs_assert(source != NULL);
|
||||
|
||||
SrsStatistic::instance()->add_request_info(source, req);
|
||||
// update the statistic when source disconveried.
|
||||
SrsStatistic* stat = SrsStatistic::instance();
|
||||
if ((ret = stat->on_client(_srs_context->get_id(), req)) != ERROR_SUCCESS) {
|
||||
srs_error("stat client failed. ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// check ASAP, to fail it faster if invalid.
|
||||
if (type != SrsRtmpConnPlay && !vhost_is_edge) {
|
||||
|
|
|
@ -51,6 +51,7 @@ class SrsRtmpClient;
|
|||
class SrsSharedPtrMessage;
|
||||
class SrsQueueRecvThread;
|
||||
class SrsPublishRecvThread;
|
||||
class SrsSecurity;
|
||||
|
||||
/**
|
||||
* the client provides the main logic control for RTMP clients.
|
||||
|
@ -66,6 +67,7 @@ private:
|
|||
SrsRtmpServer* rtmp;
|
||||
SrsRefer* refer;
|
||||
SrsBandwidth* bandwidth;
|
||||
SrsSecurity* security;
|
||||
// elapse duration in ms
|
||||
// for live play duration, for instance, rtmpdump to record.
|
||||
// @see https://github.com/winlinvip/simple-rtmp-server/issues/47
|
||||
|
|
159
trunk/src/app/srs_app_security.cpp
Normal file
159
trunk/src/app/srs_app_security.cpp
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 winlin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <srs_app_security.hpp>
|
||||
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_app_config.hpp>
|
||||
|
||||
using namespace std;
|
||||
|
||||
SrsSecurity::SrsSecurity()
|
||||
{
|
||||
}
|
||||
|
||||
SrsSecurity::~SrsSecurity()
|
||||
{
|
||||
}
|
||||
|
||||
int SrsSecurity::check(SrsRtmpConnType type, string ip, SrsRequest* req)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// allow all if security disabled.
|
||||
if (!_srs_config->get_security_enabled(req->vhost)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// default to deny all when security enabled.
|
||||
ret = ERROR_SYSTEM_SECURITY;
|
||||
|
||||
// rules to apply
|
||||
SrsConfDirective* rules = _srs_config->get_security_rules(req->vhost);
|
||||
if (!rules) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// allow if matches allow strategy.
|
||||
if (allow_check(rules, type, ip) == ERROR_SYSTEM_SECURITY_ALLOW) {
|
||||
ret = ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// deny if matches deny strategy.
|
||||
if (deny_check(rules, type, ip) == ERROR_SYSTEM_SECURITY_DENY) {
|
||||
ret = ERROR_SYSTEM_SECURITY_DENY;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsSecurity::allow_check(SrsConfDirective* rules, SrsRtmpConnType type, std::string ip)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
for (int i = 0; i < (int)rules->directives.size(); i++) {
|
||||
SrsConfDirective* rule = rules->at(i);
|
||||
|
||||
if (rule->name != "allow") {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SrsRtmpConnPlay:
|
||||
if (rule->arg0() != "play") {
|
||||
break;
|
||||
}
|
||||
if (rule->arg1() == "all" || rule->arg1() == ip) {
|
||||
ret = ERROR_SYSTEM_SECURITY_ALLOW;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SrsRtmpConnFMLEPublish:
|
||||
case SrsRtmpConnFlashPublish:
|
||||
if (rule->arg0() != "publish") {
|
||||
break;
|
||||
}
|
||||
if (rule->arg1() == "all" || rule->arg1() == ip) {
|
||||
ret = ERROR_SYSTEM_SECURITY_ALLOW;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SrsRtmpConnUnknown:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// when matched, donot search more.
|
||||
if (ret == ERROR_SYSTEM_SECURITY_ALLOW) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsSecurity::deny_check(SrsConfDirective* rules, SrsRtmpConnType type, std::string ip)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
for (int i = 0; i < (int)rules->directives.size(); i++) {
|
||||
SrsConfDirective* rule = rules->at(i);
|
||||
|
||||
if (rule->name != "deny") {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SrsRtmpConnPlay:
|
||||
if (rule->arg0() != "play") {
|
||||
break;
|
||||
}
|
||||
if (rule->arg1() == "all" || rule->arg1() == ip) {
|
||||
ret = ERROR_SYSTEM_SECURITY_DENY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SrsRtmpConnFMLEPublish:
|
||||
case SrsRtmpConnFlashPublish:
|
||||
if (rule->arg0() != "publish") {
|
||||
break;
|
||||
}
|
||||
if (rule->arg1() == "all" || rule->arg1() == ip) {
|
||||
ret = ERROR_SYSTEM_SECURITY_DENY;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SrsRtmpConnUnknown:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// when matched, donot search more.
|
||||
if (ret == ERROR_SYSTEM_SECURITY_DENY) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
70
trunk/src/app/srs_app_security.hpp
Normal file
70
trunk/src/app/srs_app_security.hpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 winlin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SRS_APP_SECURITY_HPP
|
||||
#define SRS_APP_SECURITY_HPP
|
||||
|
||||
/*
|
||||
#include <srs_app_security.hpp>
|
||||
*/
|
||||
|
||||
#include <srs_core.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <srs_protocol_rtmp.hpp>
|
||||
|
||||
class SrsConfDirective;
|
||||
|
||||
/**
|
||||
* the security apply on vhost.
|
||||
* @see https://github.com/winlinvip/simple-rtmp-server/issues/211
|
||||
*/
|
||||
class SrsSecurity
|
||||
{
|
||||
public:
|
||||
SrsSecurity();
|
||||
virtual ~SrsSecurity();
|
||||
public:
|
||||
/**
|
||||
* security check the client apply by vhost security strategy
|
||||
* @param type the client type, publish or play.
|
||||
* @param ip the ip address of client.
|
||||
* @param req the request object of client.
|
||||
*/
|
||||
virtual int check(SrsRtmpConnType type, std::string ip, SrsRequest* req);
|
||||
private:
|
||||
/**
|
||||
* security check the allow,
|
||||
* @return, if allowed, ERROR_SYSTEM_SECURITY_ALLOW.
|
||||
*/
|
||||
virtual int allow_check(SrsConfDirective* rules, SrsRtmpConnType type, std::string ip);
|
||||
/**
|
||||
* security check the deny,
|
||||
* @return, if denied, ERROR_SYSTEM_SECURITY_DENY.
|
||||
*/
|
||||
virtual int deny_check(SrsConfDirective* rules, SrsRtmpConnType type, std::string ip);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -23,53 +23,142 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#include <srs_app_statistic.hpp>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sstream>
|
||||
using namespace std;
|
||||
|
||||
#include <srs_protocol_rtmp.hpp>
|
||||
#include <srs_app_json.hpp>
|
||||
|
||||
SrsStreamInfo::SrsStreamInfo()
|
||||
int64_t __srs_gvid = getpid();
|
||||
|
||||
int64_t __srs_generate_id()
|
||||
{
|
||||
_req = NULL;
|
||||
return __srs_gvid++;
|
||||
}
|
||||
|
||||
SrsStreamInfo::~SrsStreamInfo()
|
||||
SrsStatisticVhost::SrsStatisticVhost()
|
||||
{
|
||||
if (_req != NULL)
|
||||
delete _req;
|
||||
id = __srs_generate_id();
|
||||
}
|
||||
|
||||
SrsStatistic *SrsStatistic::_instance = NULL;
|
||||
SrsStatisticVhost::~SrsStatisticVhost()
|
||||
{
|
||||
}
|
||||
|
||||
SrsStatisticStream::SrsStatisticStream()
|
||||
{
|
||||
id = __srs_generate_id();
|
||||
vhost = NULL;
|
||||
}
|
||||
|
||||
SrsStatisticStream::~SrsStatisticStream()
|
||||
{
|
||||
}
|
||||
|
||||
SrsStatistic* SrsStatistic::_instance = new SrsStatistic();
|
||||
|
||||
SrsStatistic::SrsStatistic()
|
||||
{
|
||||
|
||||
_server_id = __srs_generate_id();
|
||||
}
|
||||
|
||||
SrsStatistic::~SrsStatistic()
|
||||
{
|
||||
SrsStreamInfoMap::iterator it;
|
||||
for (it = pool.begin(); it != pool.end(); it++) {
|
||||
delete it->second;
|
||||
}
|
||||
if (true) {
|
||||
std::map<std::string, SrsStatisticVhost*>::iterator it;
|
||||
for (it = vhosts.begin(); it != vhosts.end(); it++) {
|
||||
SrsStatisticVhost* vhost = it->second;
|
||||
srs_freep(vhost);
|
||||
}
|
||||
}
|
||||
if (true) {
|
||||
std::map<std::string, SrsStatisticStream*>::iterator it;
|
||||
for (it = streams.begin(); it != streams.end(); it++) {
|
||||
SrsStatisticStream* stream = it->second;
|
||||
srs_freep(stream);
|
||||
}
|
||||
}
|
||||
if (true) {
|
||||
std::map<int, SrsStatisticClient*>::iterator it;
|
||||
for (it = clients.begin(); it != clients.end(); it++) {
|
||||
SrsStatisticClient* client = it->second;
|
||||
srs_freep(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SrsStreamInfoMap* SrsStatistic::get_pool()
|
||||
SrsStatistic* SrsStatistic::instance()
|
||||
{
|
||||
return &pool;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
SrsStreamInfo* SrsStatistic::get(void *p)
|
||||
int SrsStatistic::on_client(int id, SrsRequest* req)
|
||||
{
|
||||
SrsStreamInfoMap::iterator it = pool.find(p);
|
||||
if (it == pool.end()) {
|
||||
pool[p] = new SrsStreamInfo();
|
||||
return pool[p];
|
||||
} else {
|
||||
return it->second;
|
||||
}
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
// create vhost if not exists.
|
||||
SrsStatisticVhost* vhost = NULL;
|
||||
if (vhosts.find(req->vhost) == vhosts.end()) {
|
||||
vhost = new SrsStatisticVhost();
|
||||
vhost->vhost = req->vhost;
|
||||
vhosts[req->vhost] = vhost;
|
||||
} else {
|
||||
vhost = vhosts[req->vhost];
|
||||
}
|
||||
|
||||
// the url to identify the stream.
|
||||
std::string url = req->get_stream_url();
|
||||
|
||||
// create stream if not exists.
|
||||
SrsStatisticStream* stream = NULL;
|
||||
if (streams.find(url) == streams.end()) {
|
||||
stream = new SrsStatisticStream();
|
||||
stream->vhost = vhost;
|
||||
stream->stream = req->stream;
|
||||
stream->url = url;
|
||||
streams[url] = stream;
|
||||
} else {
|
||||
stream = streams[url];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SrsStatistic::add_request_info(void *p, SrsRequest *req)
|
||||
int64_t SrsStatistic::server_id()
|
||||
{
|
||||
SrsStreamInfo *info = get(p);
|
||||
if (info->_req == NULL)
|
||||
info->_req = req->copy();
|
||||
}
|
||||
return _server_id;
|
||||
}
|
||||
|
||||
int SrsStatistic::dumps_vhosts(stringstream& ss)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
std::map<std::string, SrsStatisticVhost*>::iterator it;
|
||||
for (it = vhosts.begin(); it != vhosts.end(); it++) {
|
||||
SrsStatisticVhost* vhost = it->second;
|
||||
ss << __SRS_JOBJECT_START
|
||||
<< __SRS_JFIELD_ORG("id", vhost->id) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("name", vhost->vhost)
|
||||
<< __SRS_JOBJECT_END;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SrsStatistic::dumps_streams(stringstream& ss)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
std::map<std::string, SrsStatisticStream*>::iterator it;
|
||||
for (it = streams.begin(); it != streams.end(); it++) {
|
||||
SrsStatisticStream* stream = it->second;
|
||||
ss << __SRS_JOBJECT_START
|
||||
<< __SRS_JFIELD_ORG("id", stream->id) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_STR("name", stream->stream) << __SRS_JFIELD_CONT
|
||||
<< __SRS_JFIELD_ORG("vhost", stream->vhost->id)
|
||||
<< __SRS_JOBJECT_END;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -31,40 +31,78 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <srs_core.hpp>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class SrsRequest;
|
||||
|
||||
class SrsStreamInfo
|
||||
struct SrsStatisticVhost
|
||||
{
|
||||
public:
|
||||
SrsStreamInfo();
|
||||
virtual ~SrsStreamInfo();
|
||||
|
||||
SrsRequest *_req;
|
||||
int64_t id;
|
||||
std::string vhost;
|
||||
public:
|
||||
SrsStatisticVhost();
|
||||
virtual ~SrsStatisticVhost();
|
||||
};
|
||||
|
||||
struct SrsStatisticStream
|
||||
{
|
||||
public:
|
||||
int64_t id;
|
||||
SrsStatisticVhost* vhost;
|
||||
std::string app;
|
||||
std::string stream;
|
||||
std::string url;
|
||||
public:
|
||||
SrsStatisticStream();
|
||||
virtual ~SrsStatisticStream();
|
||||
};
|
||||
|
||||
struct SrsStatisticClient
|
||||
{
|
||||
public:
|
||||
SrsStatisticStream* stream;
|
||||
int id;
|
||||
};
|
||||
typedef std::map<void*, SrsStreamInfo*> SrsStreamInfoMap;
|
||||
|
||||
class SrsStatistic
|
||||
{
|
||||
public:
|
||||
static SrsStatistic *instance()
|
||||
{
|
||||
if (_instance == NULL) {
|
||||
_instance = new SrsStatistic();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
virtual SrsStreamInfoMap* get_pool();
|
||||
|
||||
virtual void add_request_info(void *p, SrsRequest *req);
|
||||
|
||||
private:
|
||||
static SrsStatistic *_instance;
|
||||
// the id to identify the sever.
|
||||
int64_t _server_id;
|
||||
// key: vhost name, value: vhost object.
|
||||
std::map<std::string, SrsStatisticVhost*> vhosts;
|
||||
// key: stream name, value: stream object.
|
||||
std::map<std::string, SrsStatisticStream*> streams;
|
||||
// key: client id, value: stream object.
|
||||
std::map<int, SrsStatisticClient*> clients;
|
||||
private:
|
||||
SrsStatistic();
|
||||
virtual ~SrsStatistic();
|
||||
static SrsStatistic *_instance;
|
||||
SrsStreamInfoMap pool;
|
||||
virtual SrsStreamInfo *get(void *p);
|
||||
public:
|
||||
static SrsStatistic* instance();
|
||||
public:
|
||||
/**
|
||||
* when got a client to publish/play stream,
|
||||
* @param id, the client srs id.
|
||||
* @param req, the client request object.
|
||||
*/
|
||||
virtual int on_client(int id, SrsRequest* req);
|
||||
public:
|
||||
/**
|
||||
* get the server id, used to identify the server.
|
||||
* for example, when restart, the server id must changed.
|
||||
*/
|
||||
virtual int64_t server_id();
|
||||
/**
|
||||
* dumps the vhosts to sstream in json.
|
||||
*/
|
||||
virtual int dumps_vhosts(std::stringstream& ss);
|
||||
/**
|
||||
* dumps the streams to sstream in json.
|
||||
*/
|
||||
virtual int dumps_streams(std::stringstream& ss);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
// current release version
|
||||
#define VERSION_MAJOR 2
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 85
|
||||
#define VERSION_REVISION 89
|
||||
// server info.
|
||||
#define RTMP_SIG_SRS_KEY "SRS"
|
||||
#define RTMP_SIG_SRS_ROLE "origin/edge server"
|
||||
|
|
|
@ -90,6 +90,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define ERROR_SYSTEM_FILE_SEEK 1049
|
||||
#define ERROR_SYSTEM_IO_INVALID 1050
|
||||
#define ERROR_ST_EXCEED_THREADS 1051
|
||||
#define ERROR_SYSTEM_SECURITY 1052
|
||||
#define ERROR_SYSTEM_SECURITY_DENY 1053
|
||||
#define ERROR_SYSTEM_SECURITY_ALLOW 1054
|
||||
#define ERROR_SYSTEM_TIME 1055
|
||||
#define ERROR_SYSTEM_DIR_EXISTS 1056
|
||||
#define ERROR_SYSTEM_CREATE_DIR 1057
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// RTMP protocol error.
|
||||
|
@ -149,7 +155,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
///////////////////////////////////////////////////////
|
||||
#define ERROR_HLS_METADATA 3000
|
||||
#define ERROR_HLS_DECODE_ERROR 3001
|
||||
#define ERROR_HLS_CREATE_DIR 3002
|
||||
//#define ERROR_HLS_CREATE_DIR 3002
|
||||
#define ERROR_HLS_OPEN_FAILED 3003
|
||||
#define ERROR_HLS_WRITE_FAILED 3004
|
||||
#define ERROR_HLS_AAC_FRAME_LENGTH 3005
|
||||
|
|
|
@ -32,10 +32,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include <srs_kernel_log.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
|
||||
// this value must:
|
||||
// equals to (SRS_SYS_CYCLE_INTERVAL*SRS_SYS_TIME_RESOLUTION_MS_TIMES)*1000
|
||||
|
@ -222,3 +225,56 @@ bool srs_string_ends_with(string str, string flag)
|
|||
return str.rfind(flag) == str.length() - flag.length();
|
||||
}
|
||||
|
||||
int __srs_create_dir_recursively(string dir)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
struct stat st;
|
||||
|
||||
// stat current dir, if exists, return error.
|
||||
if (stat(dir.c_str(), &st) == 0) {
|
||||
return ERROR_SYSTEM_DIR_EXISTS;
|
||||
}
|
||||
|
||||
// create parent first.
|
||||
size_t pos;
|
||||
if ((pos = dir.rfind("/")) != std::string::npos) {
|
||||
std::string parent = dir.substr(0, pos);
|
||||
ret = __srs_create_dir_recursively(parent);
|
||||
// return for error.
|
||||
if (ret != ERROR_SUCCESS && ret != ERROR_SYSTEM_DIR_EXISTS) {
|
||||
return ret;
|
||||
}
|
||||
// parent exists, set to ok.
|
||||
ret = ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
// create curren dir.
|
||||
mode_t mode = S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH;
|
||||
if (::mkdir(dir.c_str(), mode) < 0) {
|
||||
if (errno == EEXIST) {
|
||||
return ERROR_SYSTEM_DIR_EXISTS;
|
||||
}
|
||||
|
||||
ret = ERROR_SYSTEM_CREATE_DIR;
|
||||
srs_error("create dir %s failed. ret=%d", dir.c_str(), ret);
|
||||
return ret;
|
||||
}
|
||||
srs_info("create dir %s success.", dir.c_str());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int srs_create_dir_recursively(string dir)
|
||||
{
|
||||
int ret = ERROR_SUCCESS;
|
||||
|
||||
ret = __srs_create_dir_recursively(dir);
|
||||
|
||||
if (ret == ERROR_SYSTEM_DIR_EXISTS) {
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,5 +59,8 @@ extern std::string srs_string_remove(std::string str, std::string remove_chars);
|
|||
// whether string end with
|
||||
extern bool srs_string_ends_with(std::string str, std::string flag);
|
||||
|
||||
// create dir recursively
|
||||
extern int srs_create_dir_recursively(std::string dir);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ SrsRequest* SrsRequest::copy()
|
|||
{
|
||||
SrsRequest* cp = new SrsRequest();
|
||||
|
||||
cp->ip = ip;
|
||||
cp->app = app;
|
||||
cp->objectEncoding = objectEncoding;
|
||||
cp->pageUrl = pageUrl;
|
||||
|
|
|
@ -53,6 +53,9 @@ class IMergeReadHandler;
|
|||
*/
|
||||
class SrsRequest
|
||||
{
|
||||
public:
|
||||
// client ip.
|
||||
std::string ip;
|
||||
public:
|
||||
/**
|
||||
* tcUrl: rtmp://request_vhost:port/app/stream
|
||||
|
|
|
@ -1,151 +1,155 @@
|
|||
file
|
||||
main readonly separator,
|
||||
..\main\srs_main_server.cpp,
|
||||
auto readonly separator,
|
||||
..\..\objs\srs_auto_headers.hpp,
|
||||
libs readonly separator,
|
||||
..\libs\srs_librtmp.hpp,
|
||||
..\libs\srs_librtmp.cpp,
|
||||
..\libs\srs_lib_bandwidth.hpp,
|
||||
..\libs\srs_lib_bandwidth.cpp,
|
||||
..\libs\srs_lib_simple_socket.hpp,
|
||||
..\libs\srs_lib_simple_socket.cpp,
|
||||
core readonly separator,
|
||||
..\core\srs_core.hpp,
|
||||
..\core\srs_core.cpp,
|
||||
..\core\srs_core_autofree.hpp,
|
||||
..\core\srs_core_autofree.cpp,
|
||||
..\core\srs_core_performance.hpp,
|
||||
..\core\srs_core_performance.cpp,
|
||||
kernel readonly separator,
|
||||
..\kernel\srs_kernel_codec.hpp,
|
||||
..\kernel\srs_kernel_codec.cpp,
|
||||
..\kernel\srs_kernel_consts.hpp,
|
||||
..\kernel\srs_kernel_consts.cpp,
|
||||
..\kernel\srs_kernel_error.hpp,
|
||||
..\kernel\srs_kernel_error.cpp,
|
||||
..\kernel\srs_kernel_file.hpp,
|
||||
..\kernel\srs_kernel_file.cpp,
|
||||
..\kernel\srs_kernel_flv.hpp,
|
||||
..\kernel\srs_kernel_flv.cpp,
|
||||
..\kernel\srs_kernel_log.hpp,
|
||||
..\kernel\srs_kernel_log.cpp,
|
||||
..\kernel\srs_kernel_stream.hpp,
|
||||
..\kernel\srs_kernel_stream.cpp,
|
||||
..\kernel\srs_kernel_utility.hpp,
|
||||
..\kernel\srs_kernel_utility.cpp,
|
||||
rtmp-protocol readonly separator,
|
||||
..\rtmp\srs_protocol_amf0.hpp,
|
||||
..\rtmp\srs_protocol_amf0.cpp,
|
||||
..\rtmp\srs_protocol_buffer.hpp,
|
||||
..\rtmp\srs_protocol_buffer.cpp,
|
||||
..\rtmp\srs_protocol_handshake.hpp,
|
||||
..\rtmp\srs_protocol_handshake.cpp,
|
||||
..\rtmp\srs_protocol_io.hpp,
|
||||
..\rtmp\srs_protocol_io.cpp,
|
||||
..\rtmp\srs_protocol_msg_array.hpp,
|
||||
..\rtmp\srs_protocol_msg_array.cpp,
|
||||
..\rtmp\srs_protocol_rtmp.hpp,
|
||||
..\rtmp\srs_protocol_rtmp.cpp,
|
||||
..\rtmp\srs_protocol_stack.hpp,
|
||||
..\rtmp\srs_protocol_stack.cpp,
|
||||
..\rtmp\srs_protocol_utility.hpp,
|
||||
..\rtmp\srs_protocol_utility.cpp,
|
||||
app readonly separator,
|
||||
..\app\srs_app_avc_aac.hpp,
|
||||
..\app\srs_app_avc_aac.cpp,
|
||||
..\app\srs_app_bandwidth.hpp,
|
||||
..\app\srs_app_bandwidth.cpp,
|
||||
..\app\srs_app_conn.hpp,
|
||||
..\app\srs_app_conn.cpp,
|
||||
..\app\srs_app_config.hpp,
|
||||
..\app\srs_app_config.cpp,
|
||||
..\app\srs_app_dvr.hpp,
|
||||
..\app\srs_app_dvr.cpp,
|
||||
..\app\srs_app_edge.hpp,
|
||||
..\app\srs_app_edge.cpp,
|
||||
..\app\srs_app_empty.hpp,
|
||||
..\app\srs_app_empty.cpp,
|
||||
..\app\srs_app_encoder.hpp,
|
||||
..\app\srs_app_encoder.cpp,
|
||||
..\app\srs_app_ffmpeg.hpp,
|
||||
..\app\srs_app_ffmpeg.cpp,
|
||||
..\app\srs_app_forward.hpp,
|
||||
..\app\srs_app_forward.cpp,
|
||||
..\app\srs_app_heartbeat.hpp,
|
||||
..\app\srs_app_heartbeat.cpp,
|
||||
..\app\srs_app_hls.hpp,
|
||||
..\app\srs_app_hls.cpp,
|
||||
..\app\srs_app_http.hpp,
|
||||
..\app\srs_app_http.cpp,
|
||||
..\app\srs_app_http_api.hpp,
|
||||
..\app\srs_app_http_api.cpp,
|
||||
..\app\srs_app_http_client.hpp,
|
||||
..\app\srs_app_http_client.cpp,
|
||||
..\app\srs_app_http_conn.hpp,
|
||||
..\app\srs_app_http_conn.cpp,
|
||||
..\app\srs_app_http_hooks.hpp,
|
||||
..\app\srs_app_http_hooks.cpp,
|
||||
..\app\srs_app_ingest.hpp,
|
||||
..\app\srs_app_ingest.cpp,
|
||||
..\app\srs_app_json.hpp,
|
||||
..\app\srs_app_json.cpp,
|
||||
..\app\srs_app_kbps.hpp,
|
||||
..\app\srs_app_kbps.cpp,
|
||||
..\app\srs_app_log.hpp,
|
||||
..\app\srs_app_log.cpp,
|
||||
..\app\srs_app_recv_thread.hpp,
|
||||
..\app\srs_app_recv_thread.cpp,
|
||||
..\app\srs_app_refer.hpp,
|
||||
..\app\srs_app_refer.cpp,
|
||||
..\app\srs_app_reload.hpp,
|
||||
..\app\srs_app_reload.cpp,
|
||||
..\app\srs_app_rtmp_conn.hpp,
|
||||
..\app\srs_app_rtmp_conn.cpp,
|
||||
..\app\srs_app_pithy_print.hpp,
|
||||
..\app\srs_app_pithy_print.cpp,
|
||||
..\app\srs_app_server.hpp,
|
||||
..\app\srs_app_server.cpp,
|
||||
..\app\srs_app_st.hpp,
|
||||
..\app\srs_app_st.cpp,
|
||||
..\app\srs_app_st_socket.hpp,
|
||||
..\app\srs_app_st_socket.cpp,
|
||||
..\app\srs_app_source.hpp,
|
||||
..\app\srs_app_source.cpp,
|
||||
..\app\srs_app_thread.hpp,
|
||||
..\app\srs_app_thread.cpp,
|
||||
..\app\srs_app_utility.hpp,
|
||||
..\app\srs_app_utility.cpp,
|
||||
utest readonly separator,
|
||||
..\utest\srs_utest.hpp,
|
||||
..\utest\srs_utest.cpp,
|
||||
..\utest\srs_utest_amf0.hpp,
|
||||
..\utest\srs_utest_amf0.cpp,
|
||||
..\utest\srs_utest_config.hpp,
|
||||
..\utest\srs_utest_config.cpp,
|
||||
..\utest\srs_utest_core.hpp,
|
||||
..\utest\srs_utest_core.cpp,
|
||||
..\utest\srs_utest_kernel.hpp,
|
||||
..\utest\srs_utest_kernel.cpp,
|
||||
..\utest\srs_utest_protocol.hpp,
|
||||
..\utest\srs_utest_protocol.cpp,
|
||||
..\utest\srs_utest_reload.hpp,
|
||||
..\utest\srs_utest_reload.cpp,
|
||||
research readonly separator,
|
||||
..\..\research\librtmp\srs_aac_raw_publish.c,
|
||||
..\..\research\librtmp\srs_audio_raw_publish.c,
|
||||
..\..\research\librtmp\srs_bandwidth_check.c,
|
||||
..\..\research\librtmp\srs_detect_rtmp.c,
|
||||
..\..\research\librtmp\srs_flv_injecter.c,
|
||||
..\..\research\librtmp\srs_flv_parser.c,
|
||||
..\..\research\librtmp\srs_h264_raw_publish.c,
|
||||
..\..\research\librtmp\srs_ingest_flv.c,
|
||||
..\..\research\librtmp\srs_ingest_rtmp.c,
|
||||
..\..\research\librtmp\srs_play.c,
|
||||
..\..\research\librtmp\srs_publish.c,
|
||||
..\..\research\librtmp\srs_rtmp_dump.c,
|
||||
..\..\research\hls\ts_info.cc;
|
||||
main readonly separator,
|
||||
..\main\srs_main_server.cpp,
|
||||
auto readonly separator,
|
||||
..\..\objs\srs_auto_headers.hpp,
|
||||
libs readonly separator,
|
||||
..\libs\srs_librtmp.hpp,
|
||||
..\libs\srs_librtmp.cpp,
|
||||
..\libs\srs_lib_bandwidth.hpp,
|
||||
..\libs\srs_lib_bandwidth.cpp,
|
||||
..\libs\srs_lib_simple_socket.hpp,
|
||||
..\libs\srs_lib_simple_socket.cpp,
|
||||
core readonly separator,
|
||||
..\core\srs_core.hpp,
|
||||
..\core\srs_core.cpp,
|
||||
..\core\srs_core_autofree.hpp,
|
||||
..\core\srs_core_autofree.cpp,
|
||||
..\core\srs_core_performance.hpp,
|
||||
..\core\srs_core_performance.cpp,
|
||||
kernel readonly separator,
|
||||
..\kernel\srs_kernel_codec.hpp,
|
||||
..\kernel\srs_kernel_codec.cpp,
|
||||
..\kernel\srs_kernel_consts.hpp,
|
||||
..\kernel\srs_kernel_consts.cpp,
|
||||
..\kernel\srs_kernel_error.hpp,
|
||||
..\kernel\srs_kernel_error.cpp,
|
||||
..\kernel\srs_kernel_file.hpp,
|
||||
..\kernel\srs_kernel_file.cpp,
|
||||
..\kernel\srs_kernel_flv.hpp,
|
||||
..\kernel\srs_kernel_flv.cpp,
|
||||
..\kernel\srs_kernel_log.hpp,
|
||||
..\kernel\srs_kernel_log.cpp,
|
||||
..\kernel\srs_kernel_stream.hpp,
|
||||
..\kernel\srs_kernel_stream.cpp,
|
||||
..\kernel\srs_kernel_utility.hpp,
|
||||
..\kernel\srs_kernel_utility.cpp,
|
||||
rtmp-protocol readonly separator,
|
||||
..\rtmp\srs_protocol_amf0.hpp,
|
||||
..\rtmp\srs_protocol_amf0.cpp,
|
||||
..\rtmp\srs_protocol_buffer.hpp,
|
||||
..\rtmp\srs_protocol_buffer.cpp,
|
||||
..\rtmp\srs_protocol_handshake.hpp,
|
||||
..\rtmp\srs_protocol_handshake.cpp,
|
||||
..\rtmp\srs_protocol_io.hpp,
|
||||
..\rtmp\srs_protocol_io.cpp,
|
||||
..\rtmp\srs_protocol_msg_array.hpp,
|
||||
..\rtmp\srs_protocol_msg_array.cpp,
|
||||
..\rtmp\srs_protocol_rtmp.hpp,
|
||||
..\rtmp\srs_protocol_rtmp.cpp,
|
||||
..\rtmp\srs_protocol_stack.hpp,
|
||||
..\rtmp\srs_protocol_stack.cpp,
|
||||
..\rtmp\srs_protocol_utility.hpp,
|
||||
..\rtmp\srs_protocol_utility.cpp,
|
||||
app readonly separator,
|
||||
..\app\srs_app_avc_aac.hpp,
|
||||
..\app\srs_app_avc_aac.cpp,
|
||||
..\app\srs_app_bandwidth.hpp,
|
||||
..\app\srs_app_bandwidth.cpp,
|
||||
..\app\srs_app_conn.hpp,
|
||||
..\app\srs_app_conn.cpp,
|
||||
..\app\srs_app_config.hpp,
|
||||
..\app\srs_app_config.cpp,
|
||||
..\app\srs_app_dvr.hpp,
|
||||
..\app\srs_app_dvr.cpp,
|
||||
..\app\srs_app_edge.hpp,
|
||||
..\app\srs_app_edge.cpp,
|
||||
..\app\srs_app_empty.hpp,
|
||||
..\app\srs_app_empty.cpp,
|
||||
..\app\srs_app_encoder.hpp,
|
||||
..\app\srs_app_encoder.cpp,
|
||||
..\app\srs_app_ffmpeg.hpp,
|
||||
..\app\srs_app_ffmpeg.cpp,
|
||||
..\app\srs_app_forward.hpp,
|
||||
..\app\srs_app_forward.cpp,
|
||||
..\app\srs_app_heartbeat.hpp,
|
||||
..\app\srs_app_heartbeat.cpp,
|
||||
..\app\srs_app_hls.hpp,
|
||||
..\app\srs_app_hls.cpp,
|
||||
..\app\srs_app_http.hpp,
|
||||
..\app\srs_app_http.cpp,
|
||||
..\app\srs_app_http_api.hpp,
|
||||
..\app\srs_app_http_api.cpp,
|
||||
..\app\srs_app_http_client.hpp,
|
||||
..\app\srs_app_http_client.cpp,
|
||||
..\app\srs_app_http_conn.hpp,
|
||||
..\app\srs_app_http_conn.cpp,
|
||||
..\app\srs_app_http_hooks.hpp,
|
||||
..\app\srs_app_http_hooks.cpp,
|
||||
..\app\srs_app_ingest.hpp,
|
||||
..\app\srs_app_ingest.cpp,
|
||||
..\app\srs_app_json.hpp,
|
||||
..\app\srs_app_json.cpp,
|
||||
..\app\srs_app_kbps.hpp,
|
||||
..\app\srs_app_kbps.cpp,
|
||||
..\app\srs_app_log.hpp,
|
||||
..\app\srs_app_log.cpp,
|
||||
..\app\srs_app_recv_thread.hpp,
|
||||
..\app\srs_app_recv_thread.cpp,
|
||||
..\app\srs_app_refer.hpp,
|
||||
..\app\srs_app_refer.cpp,
|
||||
..\app\srs_app_reload.hpp,
|
||||
..\app\srs_app_reload.cpp,
|
||||
..\app\srs_app_rtmp_conn.hpp,
|
||||
..\app\srs_app_rtmp_conn.cpp,
|
||||
..\app\srs_app_pithy_print.hpp,
|
||||
..\app\srs_app_pithy_print.cpp,
|
||||
..\app\srs_app_security.hpp,
|
||||
..\app\srs_app_security.cpp,
|
||||
..\app\srs_app_server.hpp,
|
||||
..\app\srs_app_server.cpp,
|
||||
..\app\srs_app_st.hpp,
|
||||
..\app\srs_app_st.cpp,
|
||||
..\app\srs_app_st_socket.hpp,
|
||||
..\app\srs_app_st_socket.cpp,
|
||||
..\app\srs_app_statistic.hpp,
|
||||
..\app\srs_app_statistic.cpp,
|
||||
..\app\srs_app_source.hpp,
|
||||
..\app\srs_app_source.cpp,
|
||||
..\app\srs_app_thread.hpp,
|
||||
..\app\srs_app_thread.cpp,
|
||||
..\app\srs_app_utility.hpp,
|
||||
..\app\srs_app_utility.cpp,
|
||||
utest readonly separator,
|
||||
..\utest\srs_utest.hpp,
|
||||
..\utest\srs_utest.cpp,
|
||||
..\utest\srs_utest_amf0.hpp,
|
||||
..\utest\srs_utest_amf0.cpp,
|
||||
..\utest\srs_utest_config.hpp,
|
||||
..\utest\srs_utest_config.cpp,
|
||||
..\utest\srs_utest_core.hpp,
|
||||
..\utest\srs_utest_core.cpp,
|
||||
..\utest\srs_utest_kernel.hpp,
|
||||
..\utest\srs_utest_kernel.cpp,
|
||||
..\utest\srs_utest_protocol.hpp,
|
||||
..\utest\srs_utest_protocol.cpp,
|
||||
..\utest\srs_utest_reload.hpp,
|
||||
..\utest\srs_utest_reload.cpp,
|
||||
research readonly separator,
|
||||
..\..\research\librtmp\srs_aac_raw_publish.c,
|
||||
..\..\research\librtmp\srs_audio_raw_publish.c,
|
||||
..\..\research\librtmp\srs_bandwidth_check.c,
|
||||
..\..\research\librtmp\srs_detect_rtmp.c,
|
||||
..\..\research\librtmp\srs_flv_injecter.c,
|
||||
..\..\research\librtmp\srs_flv_parser.c,
|
||||
..\..\research\librtmp\srs_h264_raw_publish.c,
|
||||
..\..\research\librtmp\srs_ingest_flv.c,
|
||||
..\..\research\librtmp\srs_ingest_rtmp.c,
|
||||
..\..\research\librtmp\srs_play.c,
|
||||
..\..\research\librtmp\srs_publish.c,
|
||||
..\..\research\librtmp\srs_rtmp_dump.c,
|
||||
..\..\research\hls\ts_info.cc;
|
||||
|
||||
mainconfig
|
||||
"" = "MAIN";
|
||||
"" = "MAIN";
|
||||
|
||||
|
|
|
@ -1206,12 +1206,12 @@ VOID TEST(KernelStreamTest, StreamRead8Bytes)
|
|||
data[18] = 0x13;
|
||||
data[19] = 0x14;
|
||||
|
||||
EXPECT_EQ(0x0102030405060708, s.read_8bytes());
|
||||
EXPECT_EQ(0x090a0b0c0d0e0f10, s.read_8bytes());
|
||||
EXPECT_EQ(0x0102030405060708LL, s.read_8bytes());
|
||||
EXPECT_EQ(0x090a0b0c0d0e0f10LL, s.read_8bytes());
|
||||
|
||||
s.skip(-1 * s.pos());
|
||||
s.skip(5);
|
||||
EXPECT_EQ(0x060708090a0b0c0d, s.read_8bytes());
|
||||
EXPECT_EQ(0x060708090a0b0c0dLL, s.read_8bytes());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1364,8 +1364,8 @@ VOID TEST(KernelStreamTest, StreamWrite8Bytes)
|
|||
|
||||
EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024));
|
||||
|
||||
s.write_8bytes(0x1011121314151617);
|
||||
s.write_8bytes(0x1819202122232425);
|
||||
s.write_8bytes(0x1011121314151617LL);
|
||||
s.write_8bytes(0x1819202122232425LL);
|
||||
|
||||
s.skip(-1 * s.pos());
|
||||
EXPECT_EQ(0x10, s.read_1bytes());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue