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