1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Merge pull request #1 from winlinvip/develop

merge origin
This commit is contained in:
tufang14 2015-01-05 14:02:29 +08:00
commit 532a48409d
29 changed files with 1234 additions and 362 deletions

View file

@ -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
View 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
View 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
View file

View 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
View file

@ -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

View file

@ -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",

View file

@ -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=$?

View file

@ -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);

View file

@ -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.

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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());
}

View file

@ -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

View file

@ -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

View file

@ -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) {

View file

@ -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

View 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;
}

View 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

View file

@ -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;
}

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -91,6 +91,7 @@ SrsRequest* SrsRequest::copy()
{
SrsRequest* cp = new SrsRequest();
cp->ip = ip;
cp->app = app;
cp->objectEncoding = objectEncoding;
cp->pageUrl = pageUrl;

View file

@ -53,6 +53,9 @@ class IMergeReadHandler;
*/
class SrsRequest
{
public:
// client ip.
std::string ip;
public:
/**
* tcUrl: rtmp://request_vhost:port/app/stream

View file

@ -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";

View file

@ -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());