winlin

update version, add build date

不能预览此文件类型
@@ -7,6 +7,9 @@ nginx-1.5.7.zip @@ -7,6 +7,9 @@ nginx-1.5.7.zip
7 st-1.9.zip 7 st-1.9.zip
8 basic framework for srs. 8 basic framework for srs.
9 9
  10 +CherryPy-3.2.4.zip
  11 + sample api server for srs.
  12 +
10 ffmpeg-2.1.1.tar.gz 13 ffmpeg-2.1.1.tar.gz
11 yasm-1.2.0.tar.gz 14 yasm-1.2.0.tar.gz
12 lame-3.99.5.tar.gz 15 lame-3.99.5.tar.gz
@@ -38,4 +41,7 @@ links: @@ -38,4 +41,7 @@ links:
38 yasm: 41 yasm:
39 http://yasm.tortall.net/ 42 http://yasm.tortall.net/
40 http://www.tortall.net/projects/yasm/releases/yasm-1.2.0.tar.gz 43 http://www.tortall.net/projects/yasm/releases/yasm-1.2.0.tar.gz
  44 + cherrypy:
  45 + http://www.cherrypy.org/
  46 + https://pypi.python.org/pypi/CherryPy/3.2.4
41 47
@@ -79,6 +79,31 @@ else @@ -79,6 +79,31 @@ else
79 fi 79 fi
80 80
81 ##################################################################################### 81 #####################################################################################
  82 +# cherrypy for http hooks callback, CherryPy-3.2.4
  83 +#####################################################################################
  84 +if [ $SRS_HTTP = YES ]; then
  85 + if [[ -f ${SRS_OBJS}/CherryPy-3.2.4/setup.py ]]; then
  86 + echo "CherryPy-3.2.4 is ok.";
  87 + else
  88 + echo "install CherryPy-3.2.4";
  89 + (
  90 + sudo rm -rf ${SRS_OBJS}/CherryPy-3.2.4 && cd ${SRS_OBJS} &&
  91 + unzip -q ../3rdparty/CherryPy-3.2.4.zip && cd CherryPy-3.2.4 &&
  92 + sudo python setup.py install
  93 + )
  94 + fi
  95 + # check status
  96 + ret=$?; if [[ $ret -ne 0 ]]; then echo "build CherryPy-3.2.4 failed, ret=$ret"; exit $ret; fi
  97 + if [ ! -f ${SRS_OBJS}/nginx/sbin/nginx ]; then echo "build CherryPy-3.2.4 failed."; exit -1; fi
  98 +fi
  99 +
  100 +if [ $SRS_HTTP = YES ]; then
  101 + echo "#define SRS_HTTP" >> $SRS_AUTO_HEADERS_H
  102 +else
  103 + echo "#undef SRS_HTTP" >> $SRS_AUTO_HEADERS_H
  104 +fi
  105 +
  106 +#####################################################################################
82 # openssl, for rtmp complex handshake 107 # openssl, for rtmp complex handshake
83 ##################################################################################### 108 #####################################################################################
84 if [ $SRS_SSL = YES ]; then 109 if [ $SRS_SSL = YES ]; then
@@ -5,11 +5,13 @@ help=no @@ -5,11 +5,13 @@ help=no
5 SRS_HLS=RESERVED 5 SRS_HLS=RESERVED
6 SRS_SSL=RESERVED 6 SRS_SSL=RESERVED
7 SRS_FFMPEG=RESERVED 7 SRS_FFMPEG=RESERVED
  8 +SRS_HTTP=RESERVED
8 9
9 # TODO: remove the default to yes. 10 # TODO: remove the default to yes.
10 SRS_HLS=YES 11 SRS_HLS=YES
11 SRS_SSL=YES 12 SRS_SSL=YES
12 SRS_FFMPEG=YES 13 SRS_FFMPEG=YES
  14 +SRS_HTTP=YES
13 15
14 opt= 16 opt=
15 17
@@ -28,10 +30,12 @@ do @@ -28,10 +30,12 @@ do
28 --with-ssl) SRS_SSL=YES ;; 30 --with-ssl) SRS_SSL=YES ;;
29 --with-hls) SRS_HLS=YES ;; 31 --with-hls) SRS_HLS=YES ;;
30 --with-ffmpeg) SRS_FFMPEG=YES ;; 32 --with-ffmpeg) SRS_FFMPEG=YES ;;
  33 + --with-http) SRS_HTTP=YES ;;
31 34
32 --without-ssl) SRS_SSL=NO ;; 35 --without-ssl) SRS_SSL=NO ;;
33 --without-hls) SRS_HLS=NO ;; 36 --without-hls) SRS_HLS=NO ;;
34 --without-ffmpeg) SRS_FFMPEG=NO ;; 37 --without-ffmpeg) SRS_FFMPEG=NO ;;
  38 + --without-http) SRS_HTTP=NO ;;
35 39
36 *) 40 *)
37 echo "$0: error: invalid option \"$option\"" 41 echo "$0: error: invalid option \"$option\""
@@ -50,10 +54,13 @@ cat << END @@ -50,10 +54,13 @@ cat << END
50 54
51 --with-ssl enable rtmp complex handshake, requires openssl-devel installed. 55 --with-ssl enable rtmp complex handshake, requires openssl-devel installed.
52 to delivery h264 video and aac audio to flash player. 56 to delivery h264 video and aac audio to flash player.
  57 + --with-http enable http hooks, build cherrypy as demo api server.
  58 + srs will call the http hooks, such as: on_connect.
53 --with-hls enable hls streaming, build nginx as http server for hls. 59 --with-hls enable hls streaming, build nginx as http server for hls.
54 60
55 --without-ssl disable rtmp complex handshake. 61 --without-ssl disable rtmp complex handshake.
56 --without-hls disable hls, rtmp streaming only. 62 --without-hls disable hls, rtmp streaming only.
  63 + --without-http disable http, http hooks callback.
57 64
58 END 65 END
59 66
@@ -73,6 +80,10 @@ if [ $SRS_FFMPEG = RESERVED ]; then @@ -73,6 +80,10 @@ if [ $SRS_FFMPEG = RESERVED ]; then
73 echo "you must specifies the ffmpeg, see: ./configure --help"; 80 echo "you must specifies the ffmpeg, see: ./configure --help";
74 __check_ok=NO 81 __check_ok=NO
75 fi 82 fi
  83 +if [ $SRS_HTTP = RESERVED ]; then
  84 + echo "you must specifies the http, see: ./configure --help";
  85 + __check_ok=NO
  86 +fi
76 if [ $__check_ok = NO ]; then 87 if [ $__check_ok = NO ]; then
77 exit 1; 88 exit 1;
78 fi 89 fi
@@ -81,14 +81,14 @@ vhost __defaultVhost__ { @@ -81,14 +81,14 @@ vhost __defaultVhost__ {
81 vhost dev { 81 vhost dev {
82 enabled on; 82 enabled on;
83 gop_cache on; 83 gop_cache on;
84 - hls on; 84 + hls off;
85 hls_path ./objs/nginx/html; 85 hls_path ./objs/nginx/html;
86 hls_fragment 5; 86 hls_fragment 5;
87 hls_window 30; 87 hls_window 30;
88 - forward 127.0.0.1:19350; 88 + #forward 127.0.0.1:19350;
89 #forward 127.0.0.1:1936; 89 #forward 127.0.0.1:1936;
90 transcode { 90 transcode {
91 - enabled on; 91 + enabled off;
92 ffmpeg ./objs/ffmpeg/bin/ffmpeg; 92 ffmpeg ./objs/ffmpeg/bin/ffmpeg;
93 engine dev { 93 engine dev {
94 enabled off; 94 enabled off;
@@ -15,6 +15,15 @@ BLACK="\\e[0m" @@ -15,6 +15,15 @@ BLACK="\\e[0m"
15 # parse user options. 15 # parse user options.
16 . auto/options.sh 16 . auto/options.sh
17 17
  18 +# if specifies http, requires sudo to install the CherryPy.
  19 +if [ $SRS_HTTP = YES ]; then
  20 + sudo echo "" >/dev/null 2>&1
  21 + ret=$?; if [[ 0 -ne $ret ]]; then echo
  22 + "--with-http requires sudoer, ret=$ret";
  23 + exit $ret;
  24 + fi
  25 +fi
  26 +
18 # clean the exists 27 # clean the exists
19 if [[ -f Makefile ]]; then 28 if [[ -f Makefile ]]; then
20 make clean 29 make clean
@@ -22,6 +31,8 @@ fi @@ -22,6 +31,8 @@ fi
22 31
23 # generate the audo headers file. 32 # generate the audo headers file.
24 echo "#define SRS_CONFIGURE \"${SRS_CONFIGURE}\"" > $SRS_AUTO_HEADERS_H 33 echo "#define SRS_CONFIGURE \"${SRS_CONFIGURE}\"" > $SRS_AUTO_HEADERS_H
  34 +echo "#define SRS_BUILD_DATE \"`date \"+%Y-%m-%d %H:%M:%S\"`\"" >> $SRS_AUTO_HEADERS_H
  35 +echo "#define SRS_BUILD_TS \"`date +%s`\"" >> $SRS_AUTO_HEADERS_H
25 36
26 # apply user options. 37 # apply user options.
27 . auto/depends.sh 38 . auto/depends.sh
@@ -143,6 +154,11 @@ if [ $SRS_FFMPEG = YES ]; then @@ -143,6 +154,11 @@ if [ $SRS_FFMPEG = YES ]; then
143 else 154 else
144 echo -e "${YELLOW}warning: without live stream transcoding over FFMPEG support${BLACK}" 155 echo -e "${YELLOW}warning: without live stream transcoding over FFMPEG support${BLACK}"
145 fi 156 fi
  157 +if [ $SRS_HTTP = YES ]; then
  158 + echo -e "${GREEN}http hooks callback over CherryPy is enabled${BLACK}"
  159 +else
  160 + echo -e "${YELLOW}warning: without http hooks callback over CherryPy support${BLACK}"
  161 +fi
146 162
147 # mkdir dirs 163 # mkdir dirs
148 mkdir -p ${SRS_OBJS}/logs 164 mkdir -p ${SRS_OBJS}/logs
1 -/*  
2 -The MIT License (MIT)  
3 -  
4 -Copyright (c) 2013 winlin  
5 -  
6 -Permission is hereby granted, free of charge, to any person obtaining a copy of  
7 -this software and associated documentation files (the "Software"), to deal in  
8 -the Software without restriction, including without limitation the rights to  
9 -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of  
10 -the Software, and to permit persons to whom the Software is furnished to do so,  
11 -subject to the following conditions:  
12 -  
13 -The above copyright notice and this permission notice shall be included in all  
14 -copies or substantial portions of the Software.  
15 -  
16 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS  
18 -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR  
19 -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER  
20 -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
21 -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
22 -*/  
23 -  
24 -#ifndef SRS_CORE_HPP  
25 -#define SRS_CORE_HPP  
26 -  
27 -/*  
28 -#include <srs_core.hpp>  
29 -*/  
30 -  
31 -/**  
32 -* the core provides the common defined macros, utilities,  
33 -* user must include the srs_core.hpp before any header, or maybe  
34 -* build failed.  
35 -*/  
36 -  
37 -// for int64_t print using PRId64 format.  
38 -#ifndef __STDC_FORMAT_MACROS  
39 - #define __STDC_FORMAT_MACROS  
40 -#endif  
41 -#include <inttypes.h>  
42 -  
43 -#include <assert.h>  
44 -#define srs_assert(expression) assert(expression)  
45 -  
46 -#include <stddef.h>  
47 -#include <sys/types.h>  
48 -  
49 -// generated by configure.  
50 -#include <srs_auto_headers.hpp>  
51 -  
52 -// free the p and set to NULL.  
53 -// p must be a T*.  
54 -#define srs_freep(p) \  
55 - if (p) { \  
56 - delete p; \  
57 - p = NULL; \  
58 - } \  
59 - (void)0  
60 -// free the p which represents a array  
61 -#define srs_freepa(p) \  
62 - if (p) { \  
63 - delete[] p; \  
64 - p = NULL; \  
65 - } \  
66 - (void)0  
67 -  
68 -// current release version  
69 -#define RTMP_SIG_SRS_VERSION "0.5.0"  
70 -// server info.  
71 -#define RTMP_SIG_SRS_KEY "srs"  
72 -#define RTMP_SIG_SRS_ROLE "origin server"  
73 -#define RTMP_SIG_SRS_NAME RTMP_SIG_SRS_KEY"(simple rtmp server)"  
74 -#define RTMP_SIG_SRS_URL "https://"RTMP_SIG_SRS_URL_SHORT  
75 -#define RTMP_SIG_SRS_URL_SHORT "github.com/winlinvip/simple-rtmp-server"  
76 -#define RTMP_SIG_SRS_WEB "http://blog.csdn.net/win_lin"  
77 -#define RTMP_SIG_SRS_EMAIL "winterserver@126.com"  
78 -#define RTMP_SIG_SRS_LICENSE "The MIT License (MIT)"  
79 -#define RTMP_SIG_SRS_COPYRIGHT "Copyright (c) 2013 winlin"  
80 -#define RTMP_SIG_SRS_CONTRIBUTOR "winlin"  
81 -  
82 -// compare  
83 -#define srs_min(a, b) (((a) < (b))? (a) : (b))  
84 -#define srs_max(a, b) (((a) < (b))? (b) : (a))  
85 -  
86 -// get current system time in ms, use cache to avoid performance problem  
87 -extern int64_t srs_get_system_time_ms();  
88 -// the deamon st-thread will update it.  
89 -extern void srs_update_system_time_ms();  
90 -  
91 -// signal defines.  
92 -#define SIGNAL_RELOAD SIGHUP  
93 -  
94 -#include <string>  
95 -// replace utility  
96 -extern std::string srs_replace(std::string str, std::string old_str, std::string new_str);  
97 -// dns resolve utility, return the resolved ip address.  
98 -extern std::string srs_dns_resolve(std::string host);  
99 -// resolve the vhost in query string  
100 -// @param app, may contains the vhost in query string format:  
101 -// app?vhost=request_vhost  
102 -// app...vhost...request_vhost  
103 -extern void srs_vhost_resolve(std::string& vhost, std::string& app);  
104 - 1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#ifndef SRS_CORE_HPP
  25 +#define SRS_CORE_HPP
  26 +
  27 +/*
  28 +#include <srs_core.hpp>
  29 +*/
  30 +
  31 +/**
  32 +* the core provides the common defined macros, utilities,
  33 +* user must include the srs_core.hpp before any header, or maybe
  34 +* build failed.
  35 +*/
  36 +
  37 +// for int64_t print using PRId64 format.
  38 +#ifndef __STDC_FORMAT_MACROS
  39 + #define __STDC_FORMAT_MACROS
  40 +#endif
  41 +#include <inttypes.h>
  42 +
  43 +#include <assert.h>
  44 +#define srs_assert(expression) assert(expression)
  45 +
  46 +#include <stddef.h>
  47 +#include <sys/types.h>
  48 +
  49 +// generated by configure.
  50 +#include <srs_auto_headers.hpp>
  51 +
  52 +// free the p and set to NULL.
  53 +// p must be a T*.
  54 +#define srs_freep(p) \
  55 + if (p) { \
  56 + delete p; \
  57 + p = NULL; \
  58 + } \
  59 + (void)0
  60 +// free the p which represents a array
  61 +#define srs_freepa(p) \
  62 + if (p) { \
  63 + delete[] p; \
  64 + p = NULL; \
  65 + } \
  66 + (void)0
  67 +
  68 +// current release version
  69 +#define RTMP_SIG_SRS_VERSION "0.8.0"
  70 +// server info.
  71 +#define RTMP_SIG_SRS_KEY "srs"
  72 +#define RTMP_SIG_SRS_ROLE "origin server"
  73 +#define RTMP_SIG_SRS_NAME RTMP_SIG_SRS_KEY"(simple rtmp server)"
  74 +#define RTMP_SIG_SRS_URL "https://"RTMP_SIG_SRS_URL_SHORT
  75 +#define RTMP_SIG_SRS_URL_SHORT "github.com/winlinvip/simple-rtmp-server"
  76 +#define RTMP_SIG_SRS_WEB "http://blog.csdn.net/win_lin"
  77 +#define RTMP_SIG_SRS_EMAIL "winterserver@126.com"
  78 +#define RTMP_SIG_SRS_LICENSE "The MIT License (MIT)"
  79 +#define RTMP_SIG_SRS_COPYRIGHT "Copyright (c) 2013 winlin"
  80 +#define RTMP_SIG_SRS_CONTRIBUTOR "winlin"
  81 +
  82 +// compare
  83 +#define srs_min(a, b) (((a) < (b))? (a) : (b))
  84 +#define srs_max(a, b) (((a) < (b))? (b) : (a))
  85 +
  86 +// get current system time in ms, use cache to avoid performance problem
  87 +extern int64_t srs_get_system_time_ms();
  88 +// the deamon st-thread will update it.
  89 +extern void srs_update_system_time_ms();
  90 +
  91 +// signal defines.
  92 +#define SIGNAL_RELOAD SIGHUP
  93 +
  94 +#include <string>
  95 +// replace utility
  96 +extern std::string srs_replace(std::string str, std::string old_str, std::string new_str);
  97 +// dns resolve utility, return the resolved ip address.
  98 +extern std::string srs_dns_resolve(std::string host);
  99 +// resolve the vhost in query string
  100 +// @param app, may contains the vhost in query string format:
  101 +// app?vhost=request_vhost
  102 +// app...vhost...request_vhost
  103 +extern void srs_vhost_resolve(std::string& vhost, std::string& app);
  104 +
105 #endif 105 #endif
1 -/*  
2 -The MIT License (MIT)  
3 -  
4 -Copyright (c) 2013 winlin  
5 -  
6 -Permission is hereby granted, free of charge, to any person obtaining a copy of  
7 -this software and associated documentation files (the "Software"), to deal in  
8 -the Software without restriction, including without limitation the rights to  
9 -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of  
10 -the Software, and to permit persons to whom the Software is furnished to do so,  
11 -subject to the following conditions:  
12 -  
13 -The above copyright notice and this permission notice shall be included in all  
14 -copies or substantial portions of the Software.  
15 -  
16 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS  
18 -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR  
19 -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER  
20 -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN  
21 -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
22 -*/  
23 -  
24 -#include <srs_core_config.hpp>  
25 -  
26 -#include <stdio.h>  
27 -#include <stdlib.h>  
28 -#include <errno.h>  
29 -#include <string.h>  
30 -// file operations.  
31 -#include <unistd.h>  
32 -#include <sys/types.h>  
33 -#include <sys/stat.h>  
34 -#include <fcntl.h>  
35 -  
36 -#include <vector>  
37 -#include <algorithm>  
38 -  
39 -#include <srs_core_error.hpp>  
40 -#include <srs_core_log.hpp>  
41 -#include <srs_core_autofree.hpp>  
42 -  
43 -#define FILE_OFFSET(fd) lseek(fd, 0, SEEK_CUR)  
44 -  
45 -int64_t FILE_SIZE(int fd)  
46 -{  
47 - int64_t pre = FILE_OFFSET(fd);  
48 - int64_t pos = lseek(fd, 0, SEEK_END);  
49 - lseek(fd, pre, SEEK_SET);  
50 - return pos;  
51 -}  
52 -  
53 -#define LF (char)0x0a  
54 -#define CR (char)0x0d  
55 -  
56 -bool is_common_space(char ch)  
57 -{  
58 - return (ch == ' ' || ch == '\t' || ch == CR || ch == LF);  
59 -}  
60 -  
61 -#define CONF_BUFFER_SIZE 1024 * 1024  
62 -  
63 -SrsFileBuffer::SrsFileBuffer()  
64 -{  
65 - fd = -1;  
66 - line = 0;  
67 -  
68 - pos = last = start = new char[CONF_BUFFER_SIZE];  
69 - end = start + CONF_BUFFER_SIZE;  
70 -}  
71 -  
72 -SrsFileBuffer::~SrsFileBuffer()  
73 -{  
74 - if (fd > 0) {  
75 - close(fd);  
76 - }  
77 - srs_freepa(start);  
78 -}  
79 -  
80 -int SrsFileBuffer::open(const char* filename)  
81 -{  
82 - assert(fd == -1);  
83 -  
84 - if ((fd = ::open(filename, O_RDONLY, 0)) < 0) {  
85 - srs_error("open conf file error. errno=%d(%s)", errno, strerror(errno));  
86 - return ERROR_SYSTEM_CONFIG_INVALID;  
87 - }  
88 -  
89 - line = 1;  
90 -  
91 - return ERROR_SUCCESS;  
92 -}  
93 -  
94 -SrsConfDirective::SrsConfDirective()  
95 -{  
96 -}  
97 -  
98 -SrsConfDirective::~SrsConfDirective()  
99 -{  
100 - std::vector<SrsConfDirective*>::iterator it;  
101 - for (it = directives.begin(); it != directives.end(); ++it) {  
102 - SrsConfDirective* directive = *it;  
103 - srs_freep(directive);  
104 - }  
105 - directives.clear();  
106 -}  
107 -  
108 -std::string SrsConfDirective::arg0()  
109 -{  
110 - if (args.size() > 0) {  
111 - return args.at(0);  
112 - }  
113 -  
114 - return "";  
115 -}  
116 -  
117 -std::string SrsConfDirective::arg1()  
118 -{  
119 - if (args.size() > 1) {  
120 - return args.at(1);  
121 - }  
122 -  
123 - return "";  
124 -}  
125 -  
126 -std::string SrsConfDirective::arg2()  
127 -{  
128 - if (args.size() > 2) {  
129 - return args.at(2);  
130 - }  
131 -  
132 - return "";  
133 -}  
134 -  
135 -SrsConfDirective* SrsConfDirective::at(int index)  
136 -{  
137 - return directives.at(index);  
138 -}  
139 -  
140 -SrsConfDirective* SrsConfDirective::get(std::string _name)  
141 -{  
142 - std::vector<SrsConfDirective*>::iterator it;  
143 - for (it = directives.begin(); it != directives.end(); ++it) {  
144 - SrsConfDirective* directive = *it;  
145 - if (directive->name == _name) {  
146 - return directive;  
147 - }  
148 - }  
149 -  
150 - return NULL;  
151 -}  
152 -  
153 -int SrsConfDirective::parse(const char* filename)  
154 -{  
155 - int ret = ERROR_SUCCESS;  
156 -  
157 - SrsFileBuffer buffer;  
158 -  
159 - if ((ret = buffer.open(filename)) != ERROR_SUCCESS) {  
160 - return ret;  
161 - }  
162 -  
163 - return parse_conf(&buffer, parse_file);  
164 -}  
165 -  
166 -// see: ngx_conf_parse  
167 -int SrsConfDirective::parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type)  
168 -{  
169 - int ret = ERROR_SUCCESS;  
170 -  
171 - while (true) {  
172 - std::vector<std::string> args;  
173 - ret = read_token(buffer, args);  
174 -  
175 - /**  
176 - * ret maybe:  
177 - * ERROR_SYSTEM_CONFIG_INVALID error.  
178 - * ERROR_SYSTEM_CONFIG_DIRECTIVE directive terminated by ';' found  
179 - * ERROR_SYSTEM_CONFIG_BLOCK_START token terminated by '{' found  
180 - * ERROR_SYSTEM_CONFIG_BLOCK_END the '}' found  
181 - * ERROR_SYSTEM_CONFIG_EOF the config file is done  
182 - */  
183 - if (ret == ERROR_SYSTEM_CONFIG_INVALID) {  
184 - return ret;  
185 - }  
186 - if (ret == ERROR_SYSTEM_CONFIG_BLOCK_END) {  
187 - if (type != parse_block) {  
188 - srs_error("line %d: unexpected \"}\"", buffer->line);  
189 - return ret;  
190 - }  
191 - return ERROR_SUCCESS;  
192 - }  
193 - if (ret == ERROR_SYSTEM_CONFIG_EOF) {  
194 - if (type == parse_block) {  
195 - srs_error("line %d: unexpected end of file, expecting \"}\"", buffer->line);  
196 - return ret;  
197 - }  
198 - return ERROR_SUCCESS;  
199 - }  
200 -  
201 - if (args.empty()) {  
202 - srs_error("line %d: empty directive.", buffer->line);  
203 - return ret;  
204 - }  
205 -  
206 - // build directive tree.  
207 - SrsConfDirective* directive = new SrsConfDirective();  
208 -  
209 - directive->conf_line = buffer->line;  
210 - directive->name = args[0];  
211 - args.erase(args.begin());  
212 - directive->args.swap(args);  
213 -  
214 - directives.push_back(directive);  
215 -  
216 - if (ret == ERROR_SYSTEM_CONFIG_BLOCK_START) {  
217 - if ((ret = directive->parse_conf(buffer, parse_block)) != ERROR_SUCCESS) {  
218 - return ret;  
219 - }  
220 - }  
221 - }  
222 -  
223 - return ret;  
224 -}  
225 -  
226 -// see: ngx_conf_read_token  
227 -int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string>& args)  
228 -{  
229 - int ret = ERROR_SUCCESS;  
230 -  
231 - char* pstart = buffer->pos;  
232 - int startline = buffer->line;  
233 -  
234 - bool sharp_comment = false;  
235 -  
236 - bool d_quoted = false;  
237 - bool s_quoted = false;  
238 -  
239 - bool need_space = false;  
240 - bool last_space = true;  
241 -  
242 - while (true) {  
243 - if ((ret = refill_buffer(buffer, d_quoted, s_quoted, startline, pstart)) != ERROR_SUCCESS) {  
244 - if (!args.empty() || !last_space) {  
245 - srs_error("line %d: unexpected end of file, expecting ; or \"}\"", buffer->line);  
246 - return ERROR_SYSTEM_CONFIG_INVALID;  
247 - }  
248 - return ret;  
249 - }  
250 -  
251 - char ch = *buffer->pos++;  
252 -  
253 - if (ch == LF) {  
254 - buffer->line++;  
255 - sharp_comment = false;  
256 - }  
257 -  
258 - if (sharp_comment) {  
259 - continue;  
260 - }  
261 -  
262 - if (need_space) {  
263 - if (is_common_space(ch)) {  
264 - last_space = true;  
265 - need_space = false;  
266 - continue;  
267 - }  
268 - if (ch == ';') {  
269 - return ERROR_SYSTEM_CONFIG_DIRECTIVE;  
270 - }  
271 - if (ch == '{') {  
272 - return ERROR_SYSTEM_CONFIG_BLOCK_START;  
273 - }  
274 - srs_error("line %d: unexpected '%c'", buffer->line, ch);  
275 - return ERROR_SYSTEM_CONFIG_INVALID;  
276 - }  
277 -  
278 - // last charecter is space.  
279 - if (last_space) {  
280 - if (is_common_space(ch)) {  
281 - continue;  
282 - }  
283 - pstart = buffer->pos - 1;  
284 - startline = buffer->line;  
285 - switch (ch) {  
286 - case ';':  
287 - if (args.size() == 0) {  
288 - srs_error("line %d: unexpected ';'", buffer->line);  
289 - return ERROR_SYSTEM_CONFIG_INVALID;  
290 - }  
291 - return ERROR_SYSTEM_CONFIG_DIRECTIVE;  
292 - case '{':  
293 - if (args.size() == 0) {  
294 - srs_error("line %d: unexpected '{'", buffer->line);  
295 - return ERROR_SYSTEM_CONFIG_INVALID;  
296 - }  
297 - return ERROR_SYSTEM_CONFIG_BLOCK_START;  
298 - case '}':  
299 - if (args.size() != 0) {  
300 - srs_error("line %d: unexpected '}'", buffer->line);  
301 - return ERROR_SYSTEM_CONFIG_INVALID;  
302 - }  
303 - return ERROR_SYSTEM_CONFIG_BLOCK_END;  
304 - case '#':  
305 - sharp_comment = 1;  
306 - continue;  
307 - case '"':  
308 - pstart++;  
309 - d_quoted = true;  
310 - last_space = 0;  
311 - continue;  
312 - case '\'':  
313 - pstart++;  
314 - s_quoted = true;  
315 - last_space = 0;  
316 - continue;  
317 - default:  
318 - last_space = 0;  
319 - continue;  
320 - }  
321 - } else {  
322 - // last charecter is not space  
323 - bool found = false;  
324 - if (d_quoted) {  
325 - if (ch == '"') {  
326 - d_quoted = false;  
327 - need_space = true;  
328 - found = true;  
329 - }  
330 - } else if (s_quoted) {  
331 - if (ch == '\'') {  
332 - s_quoted = false;  
333 - need_space = true;  
334 - found = true;  
335 - }  
336 - } else if (is_common_space(ch) || ch == ';' || ch == '{') {  
337 - last_space = true;  
338 - found = 1;  
339 - }  
340 -  
341 - if (found) {  
342 - int len = buffer->pos - pstart;  
343 - char* word = new char[len];  
344 - memcpy(word, pstart, len);  
345 - word[len - 1] = 0;  
346 -  
347 - args.push_back(word);  
348 - srs_freepa(word);  
349 -  
350 - if (ch == ';') {  
351 - return ERROR_SYSTEM_CONFIG_DIRECTIVE;  
352 - }  
353 - if (ch == '{') {  
354 - return ERROR_SYSTEM_CONFIG_BLOCK_START;  
355 - }  
356 - }  
357 - }  
358 - }  
359 -  
360 - return ret;  
361 -}  
362 -  
363 -int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s_quoted, int startline, char*& pstart)  
364 -{  
365 - int ret = ERROR_SUCCESS;  
366 -  
367 - if (buffer->pos < buffer->last) {  
368 - return ret;  
369 - }  
370 -  
371 - int size = FILE_SIZE(buffer->fd) - FILE_OFFSET(buffer->fd);  
372 - if (size > CONF_BUFFER_SIZE) {  
373 - ret = ERROR_SYSTEM_CONFIG_TOO_LARGE;  
374 - srs_error("config file too large, max=%d, actual=%d, ret=%d",  
375 - CONF_BUFFER_SIZE, size, ret);  
376 - return ret;  
377 - }  
378 -  
379 - if (size <= 0) {  
380 - return ERROR_SYSTEM_CONFIG_EOF;  
381 - }  
382 -  
383 - int len = buffer->pos - buffer->start;  
384 - if (len >= CONF_BUFFER_SIZE) {  
385 - buffer->line = startline;  
386 -  
387 - if (!d_quoted && !s_quoted) {  
388 - srs_error("line %d: too long parameter \"%*s...\" started",  
389 - buffer->line, 10, buffer->start);  
390 -  
391 - } else {  
392 - srs_error("line %d: too long parameter, "  
393 - "probably missing terminating '%c' character", buffer->line, d_quoted? '"':'\'');  
394 - }  
395 - return ERROR_SYSTEM_CONFIG_INVALID;  
396 - }  
397 -  
398 - if (len) {  
399 - memmove(buffer->start, pstart, len);  
400 - }  
401 -  
402 - size = srs_min(size, buffer->end - (buffer->start + len));  
403 - int n = read(buffer->fd, buffer->start + len, size);  
404 - if (n != size) {  
405 - srs_error("read file read error. expect %d, actual %d bytes.", size, n);  
406 - return ERROR_SYSTEM_CONFIG_INVALID;  
407 - }  
408 -  
409 - buffer->pos = buffer->start + len;  
410 - buffer->last = buffer->pos + n;  
411 - pstart = buffer->start;  
412 -  
413 - return ret;  
414 -}  
415 -  
416 -SrsConfig* config = new SrsConfig();  
417 -  
418 -SrsConfig::SrsConfig()  
419 -{  
420 - show_help = false;  
421 - show_version = false;  
422 -  
423 - root = new SrsConfDirective();  
424 - root->conf_line = 0;  
425 - root->name = "root";  
426 -}  
427 -  
428 -SrsConfig::~SrsConfig()  
429 -{  
430 - srs_freep(root);  
431 -}  
432 -  
433 -int SrsConfig::reload()  
434 -{  
435 - int ret = ERROR_SUCCESS;  
436 -  
437 - SrsConfig conf;  
438 - if ((ret = conf.parse_file(config_file.c_str())) != ERROR_SUCCESS) {  
439 - srs_error("config reloader parse file failed. ret=%d", ret);  
440 - return ret;  
441 - }  
442 - srs_info("config reloader parse file success.");  
443 -  
444 - // store current root to old_root,  
445 - // and reap the root from conf to current root.  
446 - SrsConfDirective* old_root = root;  
447 - SrsAutoFree(SrsConfDirective, old_root, false);  
448 -  
449 - root = conf.root;  
450 - conf.root = NULL;  
451 -  
452 - // merge config.  
453 - std::vector<SrsReloadHandler*>::iterator it;  
454 -  
455 - // merge config: listen  
456 - if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) {  
457 - for (it = subscribes.begin(); it != subscribes.end(); ++it) {  
458 - SrsReloadHandler* subscribe = *it;  
459 - if ((ret = subscribe->on_reload_listen()) != ERROR_SUCCESS) {  
460 - srs_error("notify subscribes reload listen failed. ret=%d", ret);  
461 - return ret;  
462 - }  
463 - }  
464 - srs_trace("reload listen success.");  
465 - }  
466 - // merge config: pithy_print  
467 - if (!srs_directive_equals(root->get("pithy_print"), old_root->get("pithy_print"))) {  
468 - for (it = subscribes.begin(); it != subscribes.end(); ++it) {  
469 - SrsReloadHandler* subscribe = *it;  
470 - if ((ret = subscribe->on_reload_pithy_print()) != ERROR_SUCCESS) {  
471 - srs_error("notify subscribes pithy_print listen failed. ret=%d", ret);  
472 - return ret;  
473 - }  
474 - }  
475 - srs_trace("reload pithy_print success.");  
476 - }  
477 -  
478 - return ret;  
479 -}  
480 -  
481 -void SrsConfig::subscribe(SrsReloadHandler* handler)  
482 -{  
483 - std::vector<SrsReloadHandler*>::iterator it;  
484 -  
485 - it = std::find(subscribes.begin(), subscribes.end(), handler);  
486 - if (it != subscribes.end()) {  
487 - return;  
488 - }  
489 -  
490 - subscribes.push_back(handler);  
491 -}  
492 -  
493 -void SrsConfig::unsubscribe(SrsReloadHandler* handler)  
494 -{  
495 - std::vector<SrsReloadHandler*>::iterator it;  
496 -  
497 - it = std::find(subscribes.begin(), subscribes.end(), handler);  
498 - if (it == subscribes.end()) {  
499 - return;  
500 - }  
501 -  
502 - subscribes.erase(it);  
503 -}  
504 -  
505 -// see: ngx_get_options  
506 -int SrsConfig::parse_options(int argc, char** argv)  
507 -{  
508 - int ret = ERROR_SUCCESS;  
509 -  
510 - for (int i = 1; i < argc; i++) {  
511 - if ((ret = parse_argv(i, argv)) != ERROR_SUCCESS) {  
512 - return ret;  
513 - }  
514 - }  
515 -  
516 - if (show_help) {  
517 - print_help(argv);  
518 - }  
519 -  
520 - if (show_version) {  
521 - printf("%s\n", RTMP_SIG_SRS_VERSION);  
522 - }  
523 -  
524 - if (show_help || show_version) {  
525 - exit(0);  
526 - }  
527 -  
528 - if (config_file.empty()) {  
529 - ret = ERROR_SYSTEM_CONFIG_INVALID;  
530 - srs_error("config file not specified, see help: %s -h, ret=%d", argv[0], ret);  
531 - return ret;  
532 - }  
533 -  
534 - return parse_file(config_file.c_str());  
535 -}  
536 -  
537 -SrsConfDirective* SrsConfig::get_vhost(std::string vhost)  
538 -{  
539 - srs_assert(root);  
540 -  
541 - for (int i = 0; i < (int)root->directives.size(); i++) {  
542 - SrsConfDirective* conf = root->at(i);  
543 -  
544 - if (conf->name != "vhost") {  
545 - continue;  
546 - }  
547 -  
548 - if (conf->arg0() == vhost) {  
549 - return conf;  
550 - }  
551 - }  
552 -  
553 - if (vhost != RTMP_VHOST_DEFAULT) {  
554 - return get_vhost(RTMP_VHOST_DEFAULT);  
555 - }  
556 -  
557 - return NULL;  
558 -}  
559 -  
560 -bool SrsConfig::get_vhost_enabled(std::string vhost)  
561 -{  
562 - SrsConfDirective* vhost_conf = get_vhost(vhost);  
563 -  
564 - if (!vhost_conf) {  
565 - return true;  
566 - }  
567 -  
568 - SrsConfDirective* conf = vhost_conf->get("enabled");  
569 - if (!conf) {  
570 - return true;  
571 - }  
572 -  
573 - if (conf->arg0() == "off") {  
574 - return false;  
575 - }  
576 -  
577 - return true;  
578 -}  
579 -  
580 -SrsConfDirective* SrsConfig::get_transcode(std::string vhost, std::string scope)  
581 -{  
582 - SrsConfDirective* conf = get_vhost(vhost);  
583 -  
584 - if (!conf) {  
585 - return NULL;  
586 - }  
587 -  
588 - SrsConfDirective* transcode = conf->get("transcode");  
589 - if (!transcode) {  
590 - return NULL;  
591 - }  
592 -  
593 - if (transcode->arg0() == scope) {  
594 - return transcode;  
595 - }  
596 -  
597 - return NULL;  
598 -}  
599 -  
600 -bool SrsConfig::get_transcode_enabled(SrsConfDirective* transcode)  
601 -{  
602 - if (!transcode) {  
603 - return false;  
604 - }  
605 -  
606 - SrsConfDirective* conf = transcode->get("enabled");  
607 - if (!conf || conf->arg0() != "on") {  
608 - return false;  
609 - }  
610 -  
611 - return true;  
612 -}  
613 -  
614 -std::string SrsConfig::get_transcode_ffmpeg(SrsConfDirective* transcode)  
615 -{  
616 - if (!transcode) {  
617 - return "";  
618 - }  
619 -  
620 - SrsConfDirective* conf = transcode->get("ffmpeg");  
621 - if (!conf) {  
622 - return "";  
623 - }  
624 -  
625 - return conf->arg0();  
626 -}  
627 -  
628 -void SrsConfig::get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines)  
629 -{  
630 - if (!transcode) {  
631 - return;  
632 - }  
633 -  
634 - for (int i = 0; i < (int)transcode->directives.size(); i++) {  
635 - SrsConfDirective* conf = transcode->directives[i];  
636 -  
637 - if (conf->name == "engine") {  
638 - engines.push_back(conf);  
639 - }  
640 - }  
641 -  
642 - return;  
643 -}  
644 -  
645 -bool SrsConfig::get_engine_enabled(SrsConfDirective* engine)  
646 -{  
647 - if (!engine) {  
648 - return false;  
649 - }  
650 -  
651 - SrsConfDirective* conf = engine->get("enabled");  
652 - if (!conf || conf->arg0() != "on") {  
653 - return false;  
654 - }  
655 -  
656 - return true;  
657 -}  
658 -  
659 -std::string SrsConfig::get_engine_vcodec(SrsConfDirective* engine)  
660 -{  
661 - if (!engine) {  
662 - return "";  
663 - }  
664 -  
665 - SrsConfDirective* conf = engine->get("vcodec");  
666 - if (!conf) {  
667 - return "";  
668 - }  
669 -  
670 - return conf->arg0();  
671 -}  
672 -  
673 -int SrsConfig::get_engine_vbitrate(SrsConfDirective* engine)  
674 -{  
675 - if (!engine) {  
676 - return 0;  
677 - }  
678 -  
679 - SrsConfDirective* conf = engine->get("vbitrate");  
680 - if (!conf) {  
681 - return 0;  
682 - }  
683 -  
684 - return ::atoi(conf->arg0().c_str());  
685 -}  
686 -  
687 -double SrsConfig::get_engine_vfps(SrsConfDirective* engine)  
688 -{  
689 - if (!engine) {  
690 - return 0;  
691 - }  
692 -  
693 - SrsConfDirective* conf = engine->get("vfps");  
694 - if (!conf) {  
695 - return 0;  
696 - }  
697 -  
698 - return ::atof(conf->arg0().c_str());  
699 -}  
700 -  
701 -int SrsConfig::get_engine_vwidth(SrsConfDirective* engine)  
702 -{  
703 - if (!engine) {  
704 - return 0;  
705 - }  
706 -  
707 - SrsConfDirective* conf = engine->get("vwidth");  
708 - if (!conf) {  
709 - return 0;  
710 - }  
711 -  
712 - return ::atoi(conf->arg0().c_str());  
713 -}  
714 -  
715 -int SrsConfig::get_engine_vheight(SrsConfDirective* engine)  
716 -{  
717 - if (!engine) {  
718 - return 0;  
719 - }  
720 -  
721 - SrsConfDirective* conf = engine->get("vheight");  
722 - if (!conf) {  
723 - return 0;  
724 - }  
725 -  
726 - return ::atoi(conf->arg0().c_str());  
727 -}  
728 -  
729 -int SrsConfig::get_engine_vthreads(SrsConfDirective* engine)  
730 -{  
731 - if (!engine) {  
732 - return 0;  
733 - }  
734 -  
735 - SrsConfDirective* conf = engine->get("vthreads");  
736 - if (!conf) {  
737 - return 0;  
738 - }  
739 -  
740 - return ::atoi(conf->arg0().c_str());  
741 -}  
742 -  
743 -std::string SrsConfig::get_engine_vprofile(SrsConfDirective* engine)  
744 -{  
745 - if (!engine) {  
746 - return "";  
747 - }  
748 -  
749 - SrsConfDirective* conf = engine->get("vprofile");  
750 - if (!conf) {  
751 - return "";  
752 - }  
753 -  
754 - return conf->arg0();  
755 -}  
756 -  
757 -std::string SrsConfig::get_engine_vpreset(SrsConfDirective* engine)  
758 -{  
759 - if (!engine) {  
760 - return "";  
761 - }  
762 -  
763 - SrsConfDirective* conf = engine->get("vpreset");  
764 - if (!conf) {  
765 - return "";  
766 - }  
767 -  
768 - return conf->arg0();  
769 -}  
770 -  
771 -void SrsConfig::get_engine_vparams(SrsConfDirective* engine, std::vector<std::string>& vparams)  
772 -{  
773 - if (!engine) {  
774 - return;  
775 - }  
776 -  
777 - SrsConfDirective* conf = engine->get("vparams");  
778 - if (!conf) {  
779 - return;  
780 - }  
781 -  
782 - for (int i = 0; i < (int)conf->directives.size(); i++) {  
783 - SrsConfDirective* p = conf->directives[i];  
784 - if (!p) {  
785 - continue;  
786 - }  
787 -  
788 - vparams.push_back("-" + p->name);  
789 - vparams.push_back(p->arg0());  
790 - }  
791 -}  
792 -  
793 -void SrsConfig::get_engine_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter)  
794 -{  
795 - if (!engine) {  
796 - return;  
797 - }  
798 -  
799 - SrsConfDirective* conf = engine->get("vfilter");  
800 - if (!conf) {  
801 - return;  
802 - }  
803 -  
804 - for (int i = 0; i < (int)conf->directives.size(); i++) {  
805 - SrsConfDirective* p = conf->directives[i];  
806 - if (!p) {  
807 - continue;  
808 - }  
809 -  
810 - vfilter.push_back("-" + p->name);  
811 - vfilter.push_back(p->arg0());  
812 - }  
813 -}  
814 -  
815 -std::string SrsConfig::get_engine_acodec(SrsConfDirective* engine)  
816 -{  
817 - if (!engine) {  
818 - return "";  
819 - }  
820 -  
821 - SrsConfDirective* conf = engine->get("acodec");  
822 - if (!conf) {  
823 - return "";  
824 - }  
825 -  
826 - return conf->arg0();  
827 -}  
828 -  
829 -int SrsConfig::get_engine_abitrate(SrsConfDirective* engine)  
830 -{  
831 - if (!engine) {  
832 - return 0;  
833 - }  
834 -  
835 - SrsConfDirective* conf = engine->get("abitrate");  
836 - if (!conf) {  
837 - return 0;  
838 - }  
839 -  
840 - return ::atoi(conf->arg0().c_str());  
841 -}  
842 -  
843 -int SrsConfig::get_engine_asample_rate(SrsConfDirective* engine)  
844 -{  
845 - if (!engine) {  
846 - return 0;  
847 - }  
848 -  
849 - SrsConfDirective* conf = engine->get("asample_rate");  
850 - if (!conf) {  
851 - return 0;  
852 - }  
853 -  
854 - return ::atoi(conf->arg0().c_str());  
855 -}  
856 -  
857 -int SrsConfig::get_engine_achannels(SrsConfDirective* engine)  
858 -{  
859 - if (!engine) {  
860 - return 0;  
861 - }  
862 -  
863 - SrsConfDirective* conf = engine->get("achannels");  
864 - if (!conf) {  
865 - return 0;  
866 - }  
867 -  
868 - return ::atoi(conf->arg0().c_str());  
869 -}  
870 -  
871 -void SrsConfig::get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams)  
872 -{  
873 - if (!engine) {  
874 - return;  
875 - }  
876 -  
877 - SrsConfDirective* conf = engine->get("aparams");  
878 - if (!conf) {  
879 - return;  
880 - }  
881 -  
882 - for (int i = 0; i < (int)conf->directives.size(); i++) {  
883 - SrsConfDirective* p = conf->directives[i];  
884 - if (!p) {  
885 - continue;  
886 - }  
887 -  
888 - aparams.push_back("-" + p->name);  
889 - aparams.push_back(p->arg0());  
890 - }  
891 -}  
892 -  
893 -std::string SrsConfig::get_engine_output(SrsConfDirective* engine)  
894 -{  
895 - if (!engine) {  
896 - return "";  
897 - }  
898 -  
899 - SrsConfDirective* conf = engine->get("output");  
900 - if (!conf) {  
901 - return "";  
902 - }  
903 -  
904 - return conf->arg0();  
905 -}  
906 -  
907 -std::string SrsConfig::get_log_dir()  
908 -{  
909 - srs_assert(root);  
910 -  
911 - SrsConfDirective* conf = root->get("log_dir");  
912 - if (!conf || conf->arg0().empty()) {  
913 - return "./objs/logs";  
914 - }  
915 -  
916 - return conf->arg0();  
917 -}  
918 -  
919 -int SrsConfig::get_max_connections()  
920 -{  
921 - srs_assert(root);  
922 -  
923 - SrsConfDirective* conf = root->get("max_connections");  
924 - if (!conf || conf->arg0().empty()) {  
925 - return 2000;  
926 - }  
927 -  
928 - return ::atoi(conf->arg0().c_str());  
929 -}  
930 -  
931 -SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost)  
932 -{  
933 - SrsConfDirective* conf = get_vhost(vhost);  
934 -  
935 - if (!conf) {  
936 - return NULL;  
937 - }  
938 -  
939 - return conf->get("gop_cache");  
940 -}  
941 -  
942 -SrsConfDirective* SrsConfig::get_forward(std::string vhost)  
943 -{  
944 - SrsConfDirective* conf = get_vhost(vhost);  
945 -  
946 - if (!conf) {  
947 - return NULL;  
948 - }  
949 -  
950 - return conf->get("forward");  
951 -}  
952 -  
953 -SrsConfDirective* SrsConfig::get_hls(std::string vhost)  
954 -{  
955 - SrsConfDirective* conf = get_vhost(vhost);  
956 -  
957 - if (!conf) {  
958 - return NULL;  
959 - }  
960 -  
961 - return conf->get("hls");  
962 -}  
963 -  
964 -bool SrsConfig::get_hls_enabled(std::string vhost)  
965 -{  
966 - SrsConfDirective* hls = get_hls(vhost);  
967 -  
968 - if (!hls) {  
969 - return true;  
970 - }  
971 -  
972 - if (hls->arg0() == "off") {  
973 - return false;  
974 - }  
975 -  
976 - return true;  
977 -}  
978 -  
979 -SrsConfDirective* SrsConfig::get_hls_path(std::string vhost)  
980 -{  
981 - SrsConfDirective* conf = get_vhost(vhost);  
982 -  
983 - if (!conf) {  
984 - return NULL;  
985 - }  
986 -  
987 - return conf->get("hls_path");  
988 -}  
989 -  
990 -SrsConfDirective* SrsConfig::get_hls_fragment(std::string vhost)  
991 -{  
992 - SrsConfDirective* conf = get_vhost(vhost);  
993 -  
994 - if (!conf) {  
995 - return NULL;  
996 - }  
997 -  
998 - return conf->get("hls_fragment");  
999 -}  
1000 -  
1001 -SrsConfDirective* SrsConfig::get_hls_window(std::string vhost)  
1002 -{  
1003 - SrsConfDirective* conf = get_vhost(vhost);  
1004 -  
1005 - if (!conf) {  
1006 - return NULL;  
1007 - }  
1008 -  
1009 - return conf->get("hls_window");  
1010 -}  
1011 -  
1012 -SrsConfDirective* SrsConfig::get_refer(std::string vhost)  
1013 -{  
1014 - SrsConfDirective* conf = get_vhost(vhost);  
1015 -  
1016 - if (!conf) {  
1017 - return NULL;  
1018 - }  
1019 -  
1020 - return conf->get("refer");  
1021 -}  
1022 -  
1023 -SrsConfDirective* SrsConfig::get_refer_play(std::string vhost)  
1024 -{  
1025 - SrsConfDirective* conf = get_vhost(vhost);  
1026 -  
1027 - if (!conf) {  
1028 - return NULL;  
1029 - }  
1030 -  
1031 - return conf->get("refer_play");  
1032 -}  
1033 -  
1034 -SrsConfDirective* SrsConfig::get_refer_publish(std::string vhost)  
1035 -{  
1036 - SrsConfDirective* conf = get_vhost(vhost);  
1037 -  
1038 - if (!conf) {  
1039 - return NULL;  
1040 - }  
1041 -  
1042 - return conf->get("refer_publish");  
1043 -}  
1044 -  
1045 -SrsConfDirective* SrsConfig::get_listen()  
1046 -{  
1047 - return root->get("listen");  
1048 -}  
1049 -  
1050 -SrsConfDirective* SrsConfig::get_chunk_size()  
1051 -{  
1052 - return root->get("chunk_size");  
1053 -}  
1054 -  
1055 -SrsConfDirective* SrsConfig::get_pithy_print_publish()  
1056 -{  
1057 - SrsConfDirective* pithy = root->get("pithy_print");  
1058 - if (!pithy) {  
1059 - return NULL;  
1060 - }  
1061 -  
1062 - return pithy->get("publish");  
1063 -}  
1064 -  
1065 -SrsConfDirective* SrsConfig::get_pithy_print_forwarder()  
1066 -{  
1067 - SrsConfDirective* pithy = root->get("pithy_print");  
1068 - if (!pithy) {  
1069 - return NULL;  
1070 - }  
1071 -  
1072 - return pithy->get("forwarder");  
1073 -}  
1074 -  
1075 -SrsConfDirective* SrsConfig::get_pithy_print_hls()  
1076 -{  
1077 - SrsConfDirective* pithy = root->get("pithy_print");  
1078 - if (!pithy) {  
1079 - return NULL;  
1080 - }  
1081 -  
1082 - return pithy->get("hls");  
1083 -}  
1084 -  
1085 -SrsConfDirective* SrsConfig::get_pithy_print_encoder()  
1086 -{  
1087 - SrsConfDirective* pithy = root->get("encoder");  
1088 - if (!pithy) {  
1089 - return NULL;  
1090 - }  
1091 -  
1092 - return pithy->get("forwarder");  
1093 -}  
1094 -  
1095 -SrsConfDirective* SrsConfig::get_pithy_print_play()  
1096 -{  
1097 - SrsConfDirective* pithy = root->get("pithy_print");  
1098 - if (!pithy) {  
1099 - return NULL;  
1100 - }  
1101 -  
1102 - return pithy->get("play");  
1103 -}  
1104 -  
1105 -int SrsConfig::parse_file(const char* filename)  
1106 -{  
1107 - int ret = ERROR_SUCCESS;  
1108 -  
1109 - config_file = filename;  
1110 -  
1111 - if (config_file.empty()) {  
1112 - return ERROR_SYSTEM_CONFIG_INVALID;  
1113 - }  
1114 -  
1115 - if ((ret = root->parse(config_file.c_str())) != ERROR_SUCCESS) {  
1116 - return ret;  
1117 - }  
1118 -  
1119 - SrsConfDirective* conf = NULL;  
1120 - if ((conf = get_listen()) == NULL || conf->args.size() == 0) {  
1121 - ret = ERROR_SYSTEM_CONFIG_INVALID;  
1122 - srs_error("line %d: conf error, "  
1123 - "directive \"listen\" is empty, ret=%d", (conf? conf->conf_line:0), ret);  
1124 - return ret;  
1125 - }  
1126 - // TODO: check the hls.  
1127 - // TODO: check other config.  
1128 - // TODO: check hls.  
1129 - // TODO: check ssl.  
1130 - // TODO: check ffmpeg.  
1131 -  
1132 - return ret;  
1133 -}  
1134 -  
1135 -int SrsConfig::parse_argv(int& i, char** argv)  
1136 -{  
1137 - int ret = ERROR_SUCCESS;  
1138 -  
1139 - char* p = argv[i];  
1140 -  
1141 - if (*p++ != '-') {  
1142 - ret = ERROR_SYSTEM_CONFIG_INVALID;  
1143 - srs_error("invalid options(index=%d, value=%s), "  
1144 - "must starts with -, see help: %s -h, ret=%d", i, argv[i], argv[0], ret);  
1145 - return ret;  
1146 - }  
1147 -  
1148 - while (*p) {  
1149 - switch (*p++) {  
1150 - case '?':  
1151 - case 'h':  
1152 - show_help = true;  
1153 - break;  
1154 - case 'v':  
1155 - case 'V':  
1156 - show_version = true;  
1157 - break;  
1158 - case 'c':  
1159 - if (*p) {  
1160 - config_file = p;  
1161 - return ret;  
1162 - }  
1163 - if (argv[++i]) {  
1164 - config_file = argv[i];  
1165 - return ret;  
1166 - }  
1167 - ret = ERROR_SYSTEM_CONFIG_INVALID;  
1168 - srs_error("option \"-c\" requires parameter, ret=%d", ret);  
1169 - return ret;  
1170 - default:  
1171 - ret = ERROR_SYSTEM_CONFIG_INVALID;  
1172 - srs_error("invalid option: \"%c\", see help: %s -h, ret=%d", *(p - 1), argv[0], ret);  
1173 - return ret;  
1174 - }  
1175 - }  
1176 -  
1177 - return ret;  
1178 -}  
1179 -  
1180 -void SrsConfig::print_help(char** argv)  
1181 -{  
1182 - printf(RTMP_SIG_SRS_NAME" "RTMP_SIG_SRS_VERSION  
1183 - " Copyright (c) 2013 winlin\n"  
1184 - "Contributors: "RTMP_SIG_SRS_CONTRIBUTOR"\n"  
1185 - "Configuration: "SRS_CONFIGURE"\n"  
1186 - "Usage: %s [-h?vV] [-c <filename>]\n"  
1187 - "\n"  
1188 - "Options:\n"  
1189 - " -?-h : show help\n"  
1190 - " -v-V : show version and exit\n"  
1191 - " -c filename : set configuration file\n"  
1192 - "\n"  
1193 - RTMP_SIG_SRS_WEB"\n"  
1194 - RTMP_SIG_SRS_URL"\n"  
1195 - "Email: "RTMP_SIG_SRS_EMAIL"\n"  
1196 - "\n",  
1197 - argv[0]);  
1198 -}  
1199 -  
1200 -bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b)  
1201 -{  
1202 - if (!a || !b) {  
1203 - return false;  
1204 - }  
1205 -  
1206 - if (a->name != b->name) {  
1207 - return false;  
1208 - }  
1209 -  
1210 - if (a->args.size() != b->args.size()) {  
1211 - return false;  
1212 - }  
1213 -  
1214 - for (int i = 0; i < (int)a->args.size(); i++) {  
1215 - if (a->args.at(i) != b->args.at(i)) {  
1216 - return false;  
1217 - }  
1218 - }  
1219 -  
1220 - if (a->directives.size() != b->directives.size()) {  
1221 - return false;  
1222 - }  
1223 -  
1224 - for (int i = 0; i < (int)a->directives.size(); i++) {  
1225 - SrsConfDirective* a0 = a->at(i);  
1226 - SrsConfDirective* b0 = b->at(i);  
1227 -  
1228 - if (!srs_directive_equals(a0, b0)) {  
1229 - return false;  
1230 - }  
1231 - }  
1232 -  
1233 - return true;  
1234 -}  
1235 - 1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +
  24 +#include <srs_core_config.hpp>
  25 +
  26 +#include <stdio.h>
  27 +#include <stdlib.h>
  28 +#include <errno.h>
  29 +#include <string.h>
  30 +// file operations.
  31 +#include <unistd.h>
  32 +#include <sys/types.h>
  33 +#include <sys/stat.h>
  34 +#include <fcntl.h>
  35 +
  36 +#include <vector>
  37 +#include <algorithm>
  38 +
  39 +#include <srs_core_error.hpp>
  40 +#include <srs_core_log.hpp>
  41 +#include <srs_core_autofree.hpp>
  42 +
  43 +#define FILE_OFFSET(fd) lseek(fd, 0, SEEK_CUR)
  44 +
  45 +int64_t FILE_SIZE(int fd)
  46 +{
  47 + int64_t pre = FILE_OFFSET(fd);
  48 + int64_t pos = lseek(fd, 0, SEEK_END);
  49 + lseek(fd, pre, SEEK_SET);
  50 + return pos;
  51 +}
  52 +
  53 +#define LF (char)0x0a
  54 +#define CR (char)0x0d
  55 +
  56 +bool is_common_space(char ch)
  57 +{
  58 + return (ch == ' ' || ch == '\t' || ch == CR || ch == LF);
  59 +}
  60 +
  61 +#define CONF_BUFFER_SIZE 1024 * 1024
  62 +
  63 +SrsFileBuffer::SrsFileBuffer()
  64 +{
  65 + fd = -1;
  66 + line = 0;
  67 +
  68 + pos = last = start = new char[CONF_BUFFER_SIZE];
  69 + end = start + CONF_BUFFER_SIZE;
  70 +}
  71 +
  72 +SrsFileBuffer::~SrsFileBuffer()
  73 +{
  74 + if (fd > 0) {
  75 + close(fd);
  76 + }
  77 + srs_freepa(start);
  78 +}
  79 +
  80 +int SrsFileBuffer::open(const char* filename)
  81 +{
  82 + assert(fd == -1);
  83 +
  84 + if ((fd = ::open(filename, O_RDONLY, 0)) < 0) {
  85 + srs_error("open conf file error. errno=%d(%s)", errno, strerror(errno));
  86 + return ERROR_SYSTEM_CONFIG_INVALID;
  87 + }
  88 +
  89 + line = 1;
  90 +
  91 + return ERROR_SUCCESS;
  92 +}
  93 +
  94 +SrsConfDirective::SrsConfDirective()
  95 +{
  96 +}
  97 +
  98 +SrsConfDirective::~SrsConfDirective()
  99 +{
  100 + std::vector<SrsConfDirective*>::iterator it;
  101 + for (it = directives.begin(); it != directives.end(); ++it) {
  102 + SrsConfDirective* directive = *it;
  103 + srs_freep(directive);
  104 + }
  105 + directives.clear();
  106 +}
  107 +
  108 +std::string SrsConfDirective::arg0()
  109 +{
  110 + if (args.size() > 0) {
  111 + return args.at(0);
  112 + }
  113 +
  114 + return "";
  115 +}
  116 +
  117 +std::string SrsConfDirective::arg1()
  118 +{
  119 + if (args.size() > 1) {
  120 + return args.at(1);
  121 + }
  122 +
  123 + return "";
  124 +}
  125 +
  126 +std::string SrsConfDirective::arg2()
  127 +{
  128 + if (args.size() > 2) {
  129 + return args.at(2);
  130 + }
  131 +
  132 + return "";
  133 +}
  134 +
  135 +SrsConfDirective* SrsConfDirective::at(int index)
  136 +{
  137 + return directives.at(index);
  138 +}
  139 +
  140 +SrsConfDirective* SrsConfDirective::get(std::string _name)
  141 +{
  142 + std::vector<SrsConfDirective*>::iterator it;
  143 + for (it = directives.begin(); it != directives.end(); ++it) {
  144 + SrsConfDirective* directive = *it;
  145 + if (directive->name == _name) {
  146 + return directive;
  147 + }
  148 + }
  149 +
  150 + return NULL;
  151 +}
  152 +
  153 +int SrsConfDirective::parse(const char* filename)
  154 +{
  155 + int ret = ERROR_SUCCESS;
  156 +
  157 + SrsFileBuffer buffer;
  158 +
  159 + if ((ret = buffer.open(filename)) != ERROR_SUCCESS) {
  160 + return ret;
  161 + }
  162 +
  163 + return parse_conf(&buffer, parse_file);
  164 +}
  165 +
  166 +// see: ngx_conf_parse
  167 +int SrsConfDirective::parse_conf(SrsFileBuffer* buffer, SrsDirectiveType type)
  168 +{
  169 + int ret = ERROR_SUCCESS;
  170 +
  171 + while (true) {
  172 + std::vector<std::string> args;
  173 + ret = read_token(buffer, args);
  174 +
  175 + /**
  176 + * ret maybe:
  177 + * ERROR_SYSTEM_CONFIG_INVALID error.
  178 + * ERROR_SYSTEM_CONFIG_DIRECTIVE directive terminated by ';' found
  179 + * ERROR_SYSTEM_CONFIG_BLOCK_START token terminated by '{' found
  180 + * ERROR_SYSTEM_CONFIG_BLOCK_END the '}' found
  181 + * ERROR_SYSTEM_CONFIG_EOF the config file is done
  182 + */
  183 + if (ret == ERROR_SYSTEM_CONFIG_INVALID) {
  184 + return ret;
  185 + }
  186 + if (ret == ERROR_SYSTEM_CONFIG_BLOCK_END) {
  187 + if (type != parse_block) {
  188 + srs_error("line %d: unexpected \"}\"", buffer->line);
  189 + return ret;
  190 + }
  191 + return ERROR_SUCCESS;
  192 + }
  193 + if (ret == ERROR_SYSTEM_CONFIG_EOF) {
  194 + if (type == parse_block) {
  195 + srs_error("line %d: unexpected end of file, expecting \"}\"", buffer->line);
  196 + return ret;
  197 + }
  198 + return ERROR_SUCCESS;
  199 + }
  200 +
  201 + if (args.empty()) {
  202 + srs_error("line %d: empty directive.", buffer->line);
  203 + return ret;
  204 + }
  205 +
  206 + // build directive tree.
  207 + SrsConfDirective* directive = new SrsConfDirective();
  208 +
  209 + directive->conf_line = buffer->line;
  210 + directive->name = args[0];
  211 + args.erase(args.begin());
  212 + directive->args.swap(args);
  213 +
  214 + directives.push_back(directive);
  215 +
  216 + if (ret == ERROR_SYSTEM_CONFIG_BLOCK_START) {
  217 + if ((ret = directive->parse_conf(buffer, parse_block)) != ERROR_SUCCESS) {
  218 + return ret;
  219 + }
  220 + }
  221 + }
  222 +
  223 + return ret;
  224 +}
  225 +
  226 +// see: ngx_conf_read_token
  227 +int SrsConfDirective::read_token(SrsFileBuffer* buffer, std::vector<std::string>& args)
  228 +{
  229 + int ret = ERROR_SUCCESS;
  230 +
  231 + char* pstart = buffer->pos;
  232 + int startline = buffer->line;
  233 +
  234 + bool sharp_comment = false;
  235 +
  236 + bool d_quoted = false;
  237 + bool s_quoted = false;
  238 +
  239 + bool need_space = false;
  240 + bool last_space = true;
  241 +
  242 + while (true) {
  243 + if ((ret = refill_buffer(buffer, d_quoted, s_quoted, startline, pstart)) != ERROR_SUCCESS) {
  244 + if (!args.empty() || !last_space) {
  245 + srs_error("line %d: unexpected end of file, expecting ; or \"}\"", buffer->line);
  246 + return ERROR_SYSTEM_CONFIG_INVALID;
  247 + }
  248 + return ret;
  249 + }
  250 +
  251 + char ch = *buffer->pos++;
  252 +
  253 + if (ch == LF) {
  254 + buffer->line++;
  255 + sharp_comment = false;
  256 + }
  257 +
  258 + if (sharp_comment) {
  259 + continue;
  260 + }
  261 +
  262 + if (need_space) {
  263 + if (is_common_space(ch)) {
  264 + last_space = true;
  265 + need_space = false;
  266 + continue;
  267 + }
  268 + if (ch == ';') {
  269 + return ERROR_SYSTEM_CONFIG_DIRECTIVE;
  270 + }
  271 + if (ch == '{') {
  272 + return ERROR_SYSTEM_CONFIG_BLOCK_START;
  273 + }
  274 + srs_error("line %d: unexpected '%c'", buffer->line, ch);
  275 + return ERROR_SYSTEM_CONFIG_INVALID;
  276 + }
  277 +
  278 + // last charecter is space.
  279 + if (last_space) {
  280 + if (is_common_space(ch)) {
  281 + continue;
  282 + }
  283 + pstart = buffer->pos - 1;
  284 + startline = buffer->line;
  285 + switch (ch) {
  286 + case ';':
  287 + if (args.size() == 0) {
  288 + srs_error("line %d: unexpected ';'", buffer->line);
  289 + return ERROR_SYSTEM_CONFIG_INVALID;
  290 + }
  291 + return ERROR_SYSTEM_CONFIG_DIRECTIVE;
  292 + case '{':
  293 + if (args.size() == 0) {
  294 + srs_error("line %d: unexpected '{'", buffer->line);
  295 + return ERROR_SYSTEM_CONFIG_INVALID;
  296 + }
  297 + return ERROR_SYSTEM_CONFIG_BLOCK_START;
  298 + case '}':
  299 + if (args.size() != 0) {
  300 + srs_error("line %d: unexpected '}'", buffer->line);
  301 + return ERROR_SYSTEM_CONFIG_INVALID;
  302 + }
  303 + return ERROR_SYSTEM_CONFIG_BLOCK_END;
  304 + case '#':
  305 + sharp_comment = 1;
  306 + continue;
  307 + case '"':
  308 + pstart++;
  309 + d_quoted = true;
  310 + last_space = 0;
  311 + continue;
  312 + case '\'':
  313 + pstart++;
  314 + s_quoted = true;
  315 + last_space = 0;
  316 + continue;
  317 + default:
  318 + last_space = 0;
  319 + continue;
  320 + }
  321 + } else {
  322 + // last charecter is not space
  323 + bool found = false;
  324 + if (d_quoted) {
  325 + if (ch == '"') {
  326 + d_quoted = false;
  327 + need_space = true;
  328 + found = true;
  329 + }
  330 + } else if (s_quoted) {
  331 + if (ch == '\'') {
  332 + s_quoted = false;
  333 + need_space = true;
  334 + found = true;
  335 + }
  336 + } else if (is_common_space(ch) || ch == ';' || ch == '{') {
  337 + last_space = true;
  338 + found = 1;
  339 + }
  340 +
  341 + if (found) {
  342 + int len = buffer->pos - pstart;
  343 + char* word = new char[len];
  344 + memcpy(word, pstart, len);
  345 + word[len - 1] = 0;
  346 +
  347 + args.push_back(word);
  348 + srs_freepa(word);
  349 +
  350 + if (ch == ';') {
  351 + return ERROR_SYSTEM_CONFIG_DIRECTIVE;
  352 + }
  353 + if (ch == '{') {
  354 + return ERROR_SYSTEM_CONFIG_BLOCK_START;
  355 + }
  356 + }
  357 + }
  358 + }
  359 +
  360 + return ret;
  361 +}
  362 +
  363 +int SrsConfDirective::refill_buffer(SrsFileBuffer* buffer, bool d_quoted, bool s_quoted, int startline, char*& pstart)
  364 +{
  365 + int ret = ERROR_SUCCESS;
  366 +
  367 + if (buffer->pos < buffer->last) {
  368 + return ret;
  369 + }
  370 +
  371 + int size = FILE_SIZE(buffer->fd) - FILE_OFFSET(buffer->fd);
  372 + if (size > CONF_BUFFER_SIZE) {
  373 + ret = ERROR_SYSTEM_CONFIG_TOO_LARGE;
  374 + srs_error("config file too large, max=%d, actual=%d, ret=%d",
  375 + CONF_BUFFER_SIZE, size, ret);
  376 + return ret;
  377 + }
  378 +
  379 + if (size <= 0) {
  380 + return ERROR_SYSTEM_CONFIG_EOF;
  381 + }
  382 +
  383 + int len = buffer->pos - buffer->start;
  384 + if (len >= CONF_BUFFER_SIZE) {
  385 + buffer->line = startline;
  386 +
  387 + if (!d_quoted && !s_quoted) {
  388 + srs_error("line %d: too long parameter \"%*s...\" started",
  389 + buffer->line, 10, buffer->start);
  390 +
  391 + } else {
  392 + srs_error("line %d: too long parameter, "
  393 + "probably missing terminating '%c' character", buffer->line, d_quoted? '"':'\'');
  394 + }
  395 + return ERROR_SYSTEM_CONFIG_INVALID;
  396 + }
  397 +
  398 + if (len) {
  399 + memmove(buffer->start, pstart, len);
  400 + }
  401 +
  402 + size = srs_min(size, buffer->end - (buffer->start + len));
  403 + int n = read(buffer->fd, buffer->start + len, size);
  404 + if (n != size) {
  405 + srs_error("read file read error. expect %d, actual %d bytes.", size, n);
  406 + return ERROR_SYSTEM_CONFIG_INVALID;
  407 + }
  408 +
  409 + buffer->pos = buffer->start + len;
  410 + buffer->last = buffer->pos + n;
  411 + pstart = buffer->start;
  412 +
  413 + return ret;
  414 +}
  415 +
  416 +SrsConfig* config = new SrsConfig();
  417 +
  418 +SrsConfig::SrsConfig()
  419 +{
  420 + show_help = false;
  421 + show_version = false;
  422 +
  423 + root = new SrsConfDirective();
  424 + root->conf_line = 0;
  425 + root->name = "root";
  426 +}
  427 +
  428 +SrsConfig::~SrsConfig()
  429 +{
  430 + srs_freep(root);
  431 +}
  432 +
  433 +int SrsConfig::reload()
  434 +{
  435 + int ret = ERROR_SUCCESS;
  436 +
  437 + SrsConfig conf;
  438 + if ((ret = conf.parse_file(config_file.c_str())) != ERROR_SUCCESS) {
  439 + srs_error("config reloader parse file failed. ret=%d", ret);
  440 + return ret;
  441 + }
  442 + srs_info("config reloader parse file success.");
  443 +
  444 + // store current root to old_root,
  445 + // and reap the root from conf to current root.
  446 + SrsConfDirective* old_root = root;
  447 + SrsAutoFree(SrsConfDirective, old_root, false);
  448 +
  449 + root = conf.root;
  450 + conf.root = NULL;
  451 +
  452 + // merge config.
  453 + std::vector<SrsReloadHandler*>::iterator it;
  454 +
  455 + // merge config: listen
  456 + if (!srs_directive_equals(root->get("listen"), old_root->get("listen"))) {
  457 + for (it = subscribes.begin(); it != subscribes.end(); ++it) {
  458 + SrsReloadHandler* subscribe = *it;
  459 + if ((ret = subscribe->on_reload_listen()) != ERROR_SUCCESS) {
  460 + srs_error("notify subscribes reload listen failed. ret=%d", ret);
  461 + return ret;
  462 + }
  463 + }
  464 + srs_trace("reload listen success.");
  465 + }
  466 + // merge config: pithy_print
  467 + if (!srs_directive_equals(root->get("pithy_print"), old_root->get("pithy_print"))) {
  468 + for (it = subscribes.begin(); it != subscribes.end(); ++it) {
  469 + SrsReloadHandler* subscribe = *it;
  470 + if ((ret = subscribe->on_reload_pithy_print()) != ERROR_SUCCESS) {
  471 + srs_error("notify subscribes pithy_print listen failed. ret=%d", ret);
  472 + return ret;
  473 + }
  474 + }
  475 + srs_trace("reload pithy_print success.");
  476 + }
  477 +
  478 + return ret;
  479 +}
  480 +
  481 +void SrsConfig::subscribe(SrsReloadHandler* handler)
  482 +{
  483 + std::vector<SrsReloadHandler*>::iterator it;
  484 +
  485 + it = std::find(subscribes.begin(), subscribes.end(), handler);
  486 + if (it != subscribes.end()) {
  487 + return;
  488 + }
  489 +
  490 + subscribes.push_back(handler);
  491 +}
  492 +
  493 +void SrsConfig::unsubscribe(SrsReloadHandler* handler)
  494 +{
  495 + std::vector<SrsReloadHandler*>::iterator it;
  496 +
  497 + it = std::find(subscribes.begin(), subscribes.end(), handler);
  498 + if (it == subscribes.end()) {
  499 + return;
  500 + }
  501 +
  502 + subscribes.erase(it);
  503 +}
  504 +
  505 +// see: ngx_get_options
  506 +int SrsConfig::parse_options(int argc, char** argv)
  507 +{
  508 + int ret = ERROR_SUCCESS;
  509 +
  510 + for (int i = 1; i < argc; i++) {
  511 + if ((ret = parse_argv(i, argv)) != ERROR_SUCCESS) {
  512 + return ret;
  513 + }
  514 + }
  515 +
  516 + if (show_help) {
  517 + print_help(argv);
  518 + }
  519 +
  520 + if (show_version) {
  521 + printf("%s\n", RTMP_SIG_SRS_VERSION);
  522 + }
  523 +
  524 + if (show_help || show_version) {
  525 + exit(0);
  526 + }
  527 +
  528 + if (config_file.empty()) {
  529 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  530 + srs_error("config file not specified, see help: %s -h, ret=%d", argv[0], ret);
  531 + return ret;
  532 + }
  533 +
  534 + return parse_file(config_file.c_str());
  535 +}
  536 +
  537 +SrsConfDirective* SrsConfig::get_vhost(std::string vhost)
  538 +{
  539 + srs_assert(root);
  540 +
  541 + for (int i = 0; i < (int)root->directives.size(); i++) {
  542 + SrsConfDirective* conf = root->at(i);
  543 +
  544 + if (conf->name != "vhost") {
  545 + continue;
  546 + }
  547 +
  548 + if (conf->arg0() == vhost) {
  549 + return conf;
  550 + }
  551 + }
  552 +
  553 + if (vhost != RTMP_VHOST_DEFAULT) {
  554 + return get_vhost(RTMP_VHOST_DEFAULT);
  555 + }
  556 +
  557 + return NULL;
  558 +}
  559 +
  560 +bool SrsConfig::get_vhost_enabled(std::string vhost)
  561 +{
  562 + SrsConfDirective* vhost_conf = get_vhost(vhost);
  563 +
  564 + if (!vhost_conf) {
  565 + return true;
  566 + }
  567 +
  568 + SrsConfDirective* conf = vhost_conf->get("enabled");
  569 + if (!conf) {
  570 + return true;
  571 + }
  572 +
  573 + if (conf->arg0() == "off") {
  574 + return false;
  575 + }
  576 +
  577 + return true;
  578 +}
  579 +
  580 +SrsConfDirective* SrsConfig::get_transcode(std::string vhost, std::string scope)
  581 +{
  582 + SrsConfDirective* conf = get_vhost(vhost);
  583 +
  584 + if (!conf) {
  585 + return NULL;
  586 + }
  587 +
  588 + SrsConfDirective* transcode = conf->get("transcode");
  589 + if (!transcode) {
  590 + return NULL;
  591 + }
  592 +
  593 + if (transcode->arg0() == scope) {
  594 + return transcode;
  595 + }
  596 +
  597 + return NULL;
  598 +}
  599 +
  600 +bool SrsConfig::get_transcode_enabled(SrsConfDirective* transcode)
  601 +{
  602 + if (!transcode) {
  603 + return false;
  604 + }
  605 +
  606 + SrsConfDirective* conf = transcode->get("enabled");
  607 + if (!conf || conf->arg0() != "on") {
  608 + return false;
  609 + }
  610 +
  611 + return true;
  612 +}
  613 +
  614 +std::string SrsConfig::get_transcode_ffmpeg(SrsConfDirective* transcode)
  615 +{
  616 + if (!transcode) {
  617 + return "";
  618 + }
  619 +
  620 + SrsConfDirective* conf = transcode->get("ffmpeg");
  621 + if (!conf) {
  622 + return "";
  623 + }
  624 +
  625 + return conf->arg0();
  626 +}
  627 +
  628 +void SrsConfig::get_transcode_engines(SrsConfDirective* transcode, std::vector<SrsConfDirective*>& engines)
  629 +{
  630 + if (!transcode) {
  631 + return;
  632 + }
  633 +
  634 + for (int i = 0; i < (int)transcode->directives.size(); i++) {
  635 + SrsConfDirective* conf = transcode->directives[i];
  636 +
  637 + if (conf->name == "engine") {
  638 + engines.push_back(conf);
  639 + }
  640 + }
  641 +
  642 + return;
  643 +}
  644 +
  645 +bool SrsConfig::get_engine_enabled(SrsConfDirective* engine)
  646 +{
  647 + if (!engine) {
  648 + return false;
  649 + }
  650 +
  651 + SrsConfDirective* conf = engine->get("enabled");
  652 + if (!conf || conf->arg0() != "on") {
  653 + return false;
  654 + }
  655 +
  656 + return true;
  657 +}
  658 +
  659 +std::string SrsConfig::get_engine_vcodec(SrsConfDirective* engine)
  660 +{
  661 + if (!engine) {
  662 + return "";
  663 + }
  664 +
  665 + SrsConfDirective* conf = engine->get("vcodec");
  666 + if (!conf) {
  667 + return "";
  668 + }
  669 +
  670 + return conf->arg0();
  671 +}
  672 +
  673 +int SrsConfig::get_engine_vbitrate(SrsConfDirective* engine)
  674 +{
  675 + if (!engine) {
  676 + return 0;
  677 + }
  678 +
  679 + SrsConfDirective* conf = engine->get("vbitrate");
  680 + if (!conf) {
  681 + return 0;
  682 + }
  683 +
  684 + return ::atoi(conf->arg0().c_str());
  685 +}
  686 +
  687 +double SrsConfig::get_engine_vfps(SrsConfDirective* engine)
  688 +{
  689 + if (!engine) {
  690 + return 0;
  691 + }
  692 +
  693 + SrsConfDirective* conf = engine->get("vfps");
  694 + if (!conf) {
  695 + return 0;
  696 + }
  697 +
  698 + return ::atof(conf->arg0().c_str());
  699 +}
  700 +
  701 +int SrsConfig::get_engine_vwidth(SrsConfDirective* engine)
  702 +{
  703 + if (!engine) {
  704 + return 0;
  705 + }
  706 +
  707 + SrsConfDirective* conf = engine->get("vwidth");
  708 + if (!conf) {
  709 + return 0;
  710 + }
  711 +
  712 + return ::atoi(conf->arg0().c_str());
  713 +}
  714 +
  715 +int SrsConfig::get_engine_vheight(SrsConfDirective* engine)
  716 +{
  717 + if (!engine) {
  718 + return 0;
  719 + }
  720 +
  721 + SrsConfDirective* conf = engine->get("vheight");
  722 + if (!conf) {
  723 + return 0;
  724 + }
  725 +
  726 + return ::atoi(conf->arg0().c_str());
  727 +}
  728 +
  729 +int SrsConfig::get_engine_vthreads(SrsConfDirective* engine)
  730 +{
  731 + if (!engine) {
  732 + return 0;
  733 + }
  734 +
  735 + SrsConfDirective* conf = engine->get("vthreads");
  736 + if (!conf) {
  737 + return 0;
  738 + }
  739 +
  740 + return ::atoi(conf->arg0().c_str());
  741 +}
  742 +
  743 +std::string SrsConfig::get_engine_vprofile(SrsConfDirective* engine)
  744 +{
  745 + if (!engine) {
  746 + return "";
  747 + }
  748 +
  749 + SrsConfDirective* conf = engine->get("vprofile");
  750 + if (!conf) {
  751 + return "";
  752 + }
  753 +
  754 + return conf->arg0();
  755 +}
  756 +
  757 +std::string SrsConfig::get_engine_vpreset(SrsConfDirective* engine)
  758 +{
  759 + if (!engine) {
  760 + return "";
  761 + }
  762 +
  763 + SrsConfDirective* conf = engine->get("vpreset");
  764 + if (!conf) {
  765 + return "";
  766 + }
  767 +
  768 + return conf->arg0();
  769 +}
  770 +
  771 +void SrsConfig::get_engine_vparams(SrsConfDirective* engine, std::vector<std::string>& vparams)
  772 +{
  773 + if (!engine) {
  774 + return;
  775 + }
  776 +
  777 + SrsConfDirective* conf = engine->get("vparams");
  778 + if (!conf) {
  779 + return;
  780 + }
  781 +
  782 + for (int i = 0; i < (int)conf->directives.size(); i++) {
  783 + SrsConfDirective* p = conf->directives[i];
  784 + if (!p) {
  785 + continue;
  786 + }
  787 +
  788 + vparams.push_back("-" + p->name);
  789 + vparams.push_back(p->arg0());
  790 + }
  791 +}
  792 +
  793 +void SrsConfig::get_engine_vfilter(SrsConfDirective* engine, std::vector<std::string>& vfilter)
  794 +{
  795 + if (!engine) {
  796 + return;
  797 + }
  798 +
  799 + SrsConfDirective* conf = engine->get("vfilter");
  800 + if (!conf) {
  801 + return;
  802 + }
  803 +
  804 + for (int i = 0; i < (int)conf->directives.size(); i++) {
  805 + SrsConfDirective* p = conf->directives[i];
  806 + if (!p) {
  807 + continue;
  808 + }
  809 +
  810 + vfilter.push_back("-" + p->name);
  811 + vfilter.push_back(p->arg0());
  812 + }
  813 +}
  814 +
  815 +std::string SrsConfig::get_engine_acodec(SrsConfDirective* engine)
  816 +{
  817 + if (!engine) {
  818 + return "";
  819 + }
  820 +
  821 + SrsConfDirective* conf = engine->get("acodec");
  822 + if (!conf) {
  823 + return "";
  824 + }
  825 +
  826 + return conf->arg0();
  827 +}
  828 +
  829 +int SrsConfig::get_engine_abitrate(SrsConfDirective* engine)
  830 +{
  831 + if (!engine) {
  832 + return 0;
  833 + }
  834 +
  835 + SrsConfDirective* conf = engine->get("abitrate");
  836 + if (!conf) {
  837 + return 0;
  838 + }
  839 +
  840 + return ::atoi(conf->arg0().c_str());
  841 +}
  842 +
  843 +int SrsConfig::get_engine_asample_rate(SrsConfDirective* engine)
  844 +{
  845 + if (!engine) {
  846 + return 0;
  847 + }
  848 +
  849 + SrsConfDirective* conf = engine->get("asample_rate");
  850 + if (!conf) {
  851 + return 0;
  852 + }
  853 +
  854 + return ::atoi(conf->arg0().c_str());
  855 +}
  856 +
  857 +int SrsConfig::get_engine_achannels(SrsConfDirective* engine)
  858 +{
  859 + if (!engine) {
  860 + return 0;
  861 + }
  862 +
  863 + SrsConfDirective* conf = engine->get("achannels");
  864 + if (!conf) {
  865 + return 0;
  866 + }
  867 +
  868 + return ::atoi(conf->arg0().c_str());
  869 +}
  870 +
  871 +void SrsConfig::get_engine_aparams(SrsConfDirective* engine, std::vector<std::string>& aparams)
  872 +{
  873 + if (!engine) {
  874 + return;
  875 + }
  876 +
  877 + SrsConfDirective* conf = engine->get("aparams");
  878 + if (!conf) {
  879 + return;
  880 + }
  881 +
  882 + for (int i = 0; i < (int)conf->directives.size(); i++) {
  883 + SrsConfDirective* p = conf->directives[i];
  884 + if (!p) {
  885 + continue;
  886 + }
  887 +
  888 + aparams.push_back("-" + p->name);
  889 + aparams.push_back(p->arg0());
  890 + }
  891 +}
  892 +
  893 +std::string SrsConfig::get_engine_output(SrsConfDirective* engine)
  894 +{
  895 + if (!engine) {
  896 + return "";
  897 + }
  898 +
  899 + SrsConfDirective* conf = engine->get("output");
  900 + if (!conf) {
  901 + return "";
  902 + }
  903 +
  904 + return conf->arg0();
  905 +}
  906 +
  907 +std::string SrsConfig::get_log_dir()
  908 +{
  909 + srs_assert(root);
  910 +
  911 + SrsConfDirective* conf = root->get("log_dir");
  912 + if (!conf || conf->arg0().empty()) {
  913 + return "./objs/logs";
  914 + }
  915 +
  916 + return conf->arg0();
  917 +}
  918 +
  919 +int SrsConfig::get_max_connections()
  920 +{
  921 + srs_assert(root);
  922 +
  923 + SrsConfDirective* conf = root->get("max_connections");
  924 + if (!conf || conf->arg0().empty()) {
  925 + return 2000;
  926 + }
  927 +
  928 + return ::atoi(conf->arg0().c_str());
  929 +}
  930 +
  931 +SrsConfDirective* SrsConfig::get_gop_cache(std::string vhost)
  932 +{
  933 + SrsConfDirective* conf = get_vhost(vhost);
  934 +
  935 + if (!conf) {
  936 + return NULL;
  937 + }
  938 +
  939 + return conf->get("gop_cache");
  940 +}
  941 +
  942 +SrsConfDirective* SrsConfig::get_forward(std::string vhost)
  943 +{
  944 + SrsConfDirective* conf = get_vhost(vhost);
  945 +
  946 + if (!conf) {
  947 + return NULL;
  948 + }
  949 +
  950 + return conf->get("forward");
  951 +}
  952 +
  953 +SrsConfDirective* SrsConfig::get_hls(std::string vhost)
  954 +{
  955 + SrsConfDirective* conf = get_vhost(vhost);
  956 +
  957 + if (!conf) {
  958 + return NULL;
  959 + }
  960 +
  961 + return conf->get("hls");
  962 +}
  963 +
  964 +bool SrsConfig::get_hls_enabled(std::string vhost)
  965 +{
  966 + SrsConfDirective* hls = get_hls(vhost);
  967 +
  968 + if (!hls) {
  969 + return true;
  970 + }
  971 +
  972 + if (hls->arg0() == "off") {
  973 + return false;
  974 + }
  975 +
  976 + return true;
  977 +}
  978 +
  979 +SrsConfDirective* SrsConfig::get_hls_path(std::string vhost)
  980 +{
  981 + SrsConfDirective* conf = get_vhost(vhost);
  982 +
  983 + if (!conf) {
  984 + return NULL;
  985 + }
  986 +
  987 + return conf->get("hls_path");
  988 +}
  989 +
  990 +SrsConfDirective* SrsConfig::get_hls_fragment(std::string vhost)
  991 +{
  992 + SrsConfDirective* conf = get_vhost(vhost);
  993 +
  994 + if (!conf) {
  995 + return NULL;
  996 + }
  997 +
  998 + return conf->get("hls_fragment");
  999 +}
  1000 +
  1001 +SrsConfDirective* SrsConfig::get_hls_window(std::string vhost)
  1002 +{
  1003 + SrsConfDirective* conf = get_vhost(vhost);
  1004 +
  1005 + if (!conf) {
  1006 + return NULL;
  1007 + }
  1008 +
  1009 + return conf->get("hls_window");
  1010 +}
  1011 +
  1012 +SrsConfDirective* SrsConfig::get_refer(std::string vhost)
  1013 +{
  1014 + SrsConfDirective* conf = get_vhost(vhost);
  1015 +
  1016 + if (!conf) {
  1017 + return NULL;
  1018 + }
  1019 +
  1020 + return conf->get("refer");
  1021 +}
  1022 +
  1023 +SrsConfDirective* SrsConfig::get_refer_play(std::string vhost)
  1024 +{
  1025 + SrsConfDirective* conf = get_vhost(vhost);
  1026 +
  1027 + if (!conf) {
  1028 + return NULL;
  1029 + }
  1030 +
  1031 + return conf->get("refer_play");
  1032 +}
  1033 +
  1034 +SrsConfDirective* SrsConfig::get_refer_publish(std::string vhost)
  1035 +{
  1036 + SrsConfDirective* conf = get_vhost(vhost);
  1037 +
  1038 + if (!conf) {
  1039 + return NULL;
  1040 + }
  1041 +
  1042 + return conf->get("refer_publish");
  1043 +}
  1044 +
  1045 +SrsConfDirective* SrsConfig::get_listen()
  1046 +{
  1047 + return root->get("listen");
  1048 +}
  1049 +
  1050 +SrsConfDirective* SrsConfig::get_chunk_size()
  1051 +{
  1052 + return root->get("chunk_size");
  1053 +}
  1054 +
  1055 +SrsConfDirective* SrsConfig::get_pithy_print_publish()
  1056 +{
  1057 + SrsConfDirective* pithy = root->get("pithy_print");
  1058 + if (!pithy) {
  1059 + return NULL;
  1060 + }
  1061 +
  1062 + return pithy->get("publish");
  1063 +}
  1064 +
  1065 +SrsConfDirective* SrsConfig::get_pithy_print_forwarder()
  1066 +{
  1067 + SrsConfDirective* pithy = root->get("pithy_print");
  1068 + if (!pithy) {
  1069 + return NULL;
  1070 + }
  1071 +
  1072 + return pithy->get("forwarder");
  1073 +}
  1074 +
  1075 +SrsConfDirective* SrsConfig::get_pithy_print_hls()
  1076 +{
  1077 + SrsConfDirective* pithy = root->get("pithy_print");
  1078 + if (!pithy) {
  1079 + return NULL;
  1080 + }
  1081 +
  1082 + return pithy->get("hls");
  1083 +}
  1084 +
  1085 +SrsConfDirective* SrsConfig::get_pithy_print_encoder()
  1086 +{
  1087 + SrsConfDirective* pithy = root->get("encoder");
  1088 + if (!pithy) {
  1089 + return NULL;
  1090 + }
  1091 +
  1092 + return pithy->get("forwarder");
  1093 +}
  1094 +
  1095 +SrsConfDirective* SrsConfig::get_pithy_print_play()
  1096 +{
  1097 + SrsConfDirective* pithy = root->get("pithy_print");
  1098 + if (!pithy) {
  1099 + return NULL;
  1100 + }
  1101 +
  1102 + return pithy->get("play");
  1103 +}
  1104 +
  1105 +int SrsConfig::parse_file(const char* filename)
  1106 +{
  1107 + int ret = ERROR_SUCCESS;
  1108 +
  1109 + config_file = filename;
  1110 +
  1111 + if (config_file.empty()) {
  1112 + return ERROR_SYSTEM_CONFIG_INVALID;
  1113 + }
  1114 +
  1115 + if ((ret = root->parse(config_file.c_str())) != ERROR_SUCCESS) {
  1116 + return ret;
  1117 + }
  1118 +
  1119 + SrsConfDirective* conf = NULL;
  1120 + if ((conf = get_listen()) == NULL || conf->args.size() == 0) {
  1121 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  1122 + srs_error("line %d: conf error, "
  1123 + "directive \"listen\" is empty, ret=%d", (conf? conf->conf_line:0), ret);
  1124 + return ret;
  1125 + }
  1126 + // TODO: check the hls.
  1127 + // TODO: check other config.
  1128 + // TODO: check hls.
  1129 + // TODO: check ssl.
  1130 + // TODO: check ffmpeg.
  1131 +
  1132 + return ret;
  1133 +}
  1134 +
  1135 +int SrsConfig::parse_argv(int& i, char** argv)
  1136 +{
  1137 + int ret = ERROR_SUCCESS;
  1138 +
  1139 + char* p = argv[i];
  1140 +
  1141 + if (*p++ != '-') {
  1142 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  1143 + srs_error("invalid options(index=%d, value=%s), "
  1144 + "must starts with -, see help: %s -h, ret=%d", i, argv[i], argv[0], ret);
  1145 + return ret;
  1146 + }
  1147 +
  1148 + while (*p) {
  1149 + switch (*p++) {
  1150 + case '?':
  1151 + case 'h':
  1152 + show_help = true;
  1153 + break;
  1154 + case 'v':
  1155 + case 'V':
  1156 + show_version = true;
  1157 + break;
  1158 + case 'c':
  1159 + if (*p) {
  1160 + config_file = p;
  1161 + return ret;
  1162 + }
  1163 + if (argv[++i]) {
  1164 + config_file = argv[i];
  1165 + return ret;
  1166 + }
  1167 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  1168 + srs_error("option \"-c\" requires parameter, ret=%d", ret);
  1169 + return ret;
  1170 + default:
  1171 + ret = ERROR_SYSTEM_CONFIG_INVALID;
  1172 + srs_error("invalid option: \"%c\", see help: %s -h, ret=%d", *(p - 1), argv[0], ret);
  1173 + return ret;
  1174 + }
  1175 + }
  1176 +
  1177 + return ret;
  1178 +}
  1179 +
  1180 +void SrsConfig::print_help(char** argv)
  1181 +{
  1182 + printf(RTMP_SIG_SRS_NAME" "RTMP_SIG_SRS_VERSION
  1183 + " Copyright (c) 2013 winlin\n"
  1184 + "Contributors: "RTMP_SIG_SRS_CONTRIBUTOR"\n"
  1185 + "Build: "SRS_BUILD_DATE" Configuration: "SRS_CONFIGURE"\n"
  1186 + "Usage: %s [-h?vV] [-c <filename>]\n"
  1187 + "\n"
  1188 + "Options:\n"
  1189 + " -?-h : show help\n"
  1190 + " -v-V : show version and exit\n"
  1191 + " -c filename : set configuration file\n"
  1192 + "\n"
  1193 + RTMP_SIG_SRS_WEB"\n"
  1194 + RTMP_SIG_SRS_URL"\n"
  1195 + "Email: "RTMP_SIG_SRS_EMAIL"\n"
  1196 + "\n",
  1197 + argv[0]);
  1198 +}
  1199 +
  1200 +bool srs_directive_equals(SrsConfDirective* a, SrsConfDirective* b)
  1201 +{
  1202 + if (!a || !b) {
  1203 + return false;
  1204 + }
  1205 +
  1206 + if (a->name != b->name) {
  1207 + return false;
  1208 + }
  1209 +
  1210 + if (a->args.size() != b->args.size()) {
  1211 + return false;
  1212 + }
  1213 +
  1214 + for (int i = 0; i < (int)a->args.size(); i++) {
  1215 + if (a->args.at(i) != b->args.at(i)) {
  1216 + return false;
  1217 + }
  1218 + }
  1219 +
  1220 + if (a->directives.size() != b->directives.size()) {
  1221 + return false;
  1222 + }
  1223 +
  1224 + for (int i = 0; i < (int)a->directives.size(); i++) {
  1225 + SrsConfDirective* a0 = a->at(i);
  1226 + SrsConfDirective* b0 = b->at(i);
  1227 +
  1228 + if (!srs_directive_equals(a0, b0)) {
  1229 + return false;
  1230 + }
  1231 + }
  1232 +
  1233 + return true;
  1234 +}
  1235 +