diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index c3d7d0fde..62ccd4284 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -42,6 +42,7 @@ using namespace std; #include #include #include +#include #define SRS_WIKI_URL_LOG "https://github.com/winlinvip/simple-rtmp-server/wiki/SrsLog" @@ -104,16 +105,9 @@ string SrsConfDirective::arg2() return ""; } -void SrsConfDirective::set_arg0(string value) -{ - if (args.size() > 0) { - args[0] = value; - } - args.push_back(value); -} - SrsConfDirective* SrsConfDirective::at(int index) { + srs_assert(index < (int)directives.size()); return directives.at(index); } @@ -143,21 +137,18 @@ SrsConfDirective* SrsConfDirective::get(string _name, string _arg0) return NULL; } -int SrsConfDirective::parse(const char* filename) +bool SrsConfDirective::is_vhost() { - int ret = ERROR_SUCCESS; - - _srs_internal::SrsFileBuffer buffer; - - if ((ret = buffer.fullfill(filename)) != ERROR_SUCCESS) { - return ret; - } - - return parse_conf(&buffer, parse_file); + return name == "vhost"; +} + +int SrsConfDirective::parse(_srs_internal::SrsConfigBuffer* buffer) +{ + return parse_conf(buffer, parse_file); } // see: ngx_conf_parse -int SrsConfDirective::parse_conf(_srs_internal::SrsFileBuffer* buffer, SrsDirectiveType type) +int SrsConfDirective::parse_conf(_srs_internal::SrsConfigBuffer* buffer, SrsDirectiveType type) { int ret = ERROR_SUCCESS; @@ -167,11 +158,11 @@ int SrsConfDirective::parse_conf(_srs_internal::SrsFileBuffer* buffer, SrsDirect /** * ret maybe: - * ERROR_SYSTEM_CONFIG_INVALID error. - * ERROR_SYSTEM_CONFIG_DIRECTIVE directive terminated by ';' found - * ERROR_SYSTEM_CONFIG_BLOCK_START token terminated by '{' found - * ERROR_SYSTEM_CONFIG_BLOCK_END the '}' found - * ERROR_SYSTEM_CONFIG_EOF the config file is done + * ERROR_SYSTEM_CONFIG_INVALID error. + * ERROR_SYSTEM_CONFIG_DIRECTIVE directive terminated by ';' found + * ERROR_SYSTEM_CONFIG_BLOCK_START token terminated by '{' found + * ERROR_SYSTEM_CONFIG_BLOCK_END the '}' found + * ERROR_SYSTEM_CONFIG_EOF the config file is done */ if (ret == ERROR_SYSTEM_CONFIG_INVALID) { return ret; @@ -217,7 +208,7 @@ int SrsConfDirective::parse_conf(_srs_internal::SrsFileBuffer* buffer, SrsDirect } // see: ngx_conf_read_token -int SrsConfDirective::read_token(_srs_internal::SrsFileBuffer* buffer, vector& args) +int SrsConfDirective::read_token(_srs_internal::SrsConfigBuffer* buffer, vector& args) { int ret = ERROR_SUCCESS; @@ -358,11 +349,6 @@ int SrsConfDirective::read_token(_srs_internal::SrsFileBuffer* buffer, vectorparse(config_file.c_str())) != ERROR_SUCCESS) { + _srs_internal::SrsConfigBuffer buffer; + + if ((ret = buffer.fullfill(config_file.c_str())) != ERROR_SUCCESS) { + return ret; + } + + if ((ret = root->parse(&buffer)) != ERROR_SUCCESS) { return ret; } @@ -2772,7 +2764,7 @@ bool SrsConfig::get_heartbeat_summaries() namespace _srs_internal { - SrsFileBuffer::SrsFileBuffer() + SrsConfigBuffer::SrsConfigBuffer() { line = 0; @@ -2780,54 +2772,43 @@ namespace _srs_internal end = start; } - SrsFileBuffer::~SrsFileBuffer() + SrsConfigBuffer::~SrsConfigBuffer() { srs_freep(start); } - int SrsFileBuffer::fullfill(const char* filename) + int SrsConfigBuffer::fullfill(const char* filename) { int ret = ERROR_SUCCESS; - int fd = -1; - int nread = 0; - int filesize = 0; + SrsFileReader reader; - // TODO: FIXME: refine the file stream. - if ((fd = ::open(filename, O_RDONLY, 0)) < 0) { - ret = ERROR_SYSTEM_CONFIG_INVALID; + // open file reader. + if ((ret = reader.open(filename)) != ERROR_SUCCESS) { srs_error("open conf file error. ret=%d", ret); - goto finish; + return ret; } - if ((filesize = FILE_SIZE(fd) - FILE_OFFSET(fd)) <= 0) { - ret = ERROR_SYSTEM_CONFIG_EOF; - srs_error("read conf file error. ret=%d", ret); - goto finish; - } - + // read all. + int filesize = (int)reader.filesize(); + + // create buffer srs_freep(start); pos = last = start = new char[filesize]; end = start + filesize; - if ((nread = read(fd, start, filesize)) != filesize) { - ret = ERROR_SYSTEM_CONFIG_INVALID; + // read total content from file. + ssize_t nread = 0; + if ((ret = reader.read(start, filesize, &nread)) != ERROR_SUCCESS) { srs_error("read file read error. expect %d, actual %d bytes, ret=%d", filesize, nread, ret); - goto finish; - } - - line = 1; - - finish: - if (fd > 0) { - ::close(fd); + return ret; } return ret; } - bool SrsFileBuffer::empty() + bool SrsConfigBuffer::empty() { return pos >= end; } diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 7be9a64e3..0f8ddd286 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -84,35 +84,129 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. namespace _srs_internal { - class SrsFileBuffer; + class SrsConfigBuffer; }; +/** +* the config directive. +* the config file is a group of directives, +* all directive has name, args and child-directives. +* for example, the following config text: + vhost vhost.ossrs.net { + enabled on; + ingest livestream { + enabled on; + ffmpeg /bin/ffmpeg; + } + } +* will be parsed to: +* SrsConfDirective: name="vhost", arg0="vhost.ossrs.net", child-directives=[ +* SrsConfDirective: name="enabled", arg0="on", child-directives=[] +* SrsConfDirective: name="ingest", arg0="livestream", child-directives=[ +* SrsConfDirective: name="enabled", arg0="on", child-directives=[] +* SrsConfDirective: name="ffmpeg", arg0="/bin/ffmpeg", child-directives=[] +* ] +* ] +*/ class SrsConfDirective { public: + /** + * the line of config file in which the directive from + */ int conf_line; + /** + * the name of directive, for example, the following config text: + * enabled on; + * will be parsed to a directive, its name is "enalbed" + */ std::string name; + /** + * the args of directive, for example, the following config text: + * listen 1935 1936; + * will be parsed to a directive, its args is ["1935", "1936"]. + */ std::vector args; + /** + * the child directives, for example, the following config text: + * vhost vhost.ossrs.net { + * enabled on; + * } + * will be parsed to a directive, its directives is a vector contains + * a directive, which is: + * name:"enalbed", args:["on"], directives:[] + * + * @remark, the directives can contains directives. + */ std::vector directives; public: SrsConfDirective(); virtual ~SrsConfDirective(); +// args public: + /** + * get the args0,1,2, if user want to get more args, + * directly use the args.at(index). + */ virtual std::string arg0(); - virtual std::string arg1(); + virtual std::string arg1(); virtual std::string arg2(); - virtual void set_arg0(std::string value); +// directives +public: + /** + * get the directive by index. + * @remark, assert the index& args); -public: + /** + * whether current directive is vhost. + */ virtual bool is_vhost(); +// parse utilities +public: + /** + * parse config directive from file buffer. + */ + virtual int parse(_srs_internal::SrsConfigBuffer* buffer); +// private parse. +private: + /** + * the directive parsing type. + */ + enum SrsDirectiveType { + /** + * the root directives, parsing file. + */ + parse_file, + /** + * for each direcitve, parsing text block. + */ + parse_block + }; + /** + * parse the conf from buffer. the work flow: + * 1. read a token(directive args and a ret flag), + * 2. initialize the directive by args, args[0] is name, args[1-N] is args of directive, + * 3. if ret flag indicates there are child-directives, read_conf(directive, block) recursively. + */ + virtual int parse_conf(_srs_internal::SrsConfigBuffer* buffer, SrsDirectiveType type); + /** + * read a token from buffer. + * a token, is the directive args and a flag indicates whether has child-directives. + * @param args, the output directive args, the first is the directive name, left is the args. + * @return, an error code indicates error or has child-directives. + */ + virtual int read_token(_srs_internal::SrsConfigBuffer* buffer, std::vector& args); }; /** @@ -294,10 +388,12 @@ public: namespace _srs_internal { - // TODO: FIXME: use SrsFileReader. - class SrsFileBuffer + /** + * the buffer of config content. + */ + class SrsConfigBuffer { - private: + protected: // last available position. char* last; // end of buffer. @@ -309,10 +405,17 @@ namespace _srs_internal char* pos; // current parsed line. int line; - - SrsFileBuffer(); - virtual ~SrsFileBuffer(); + public: + SrsConfigBuffer(); + virtual ~SrsConfigBuffer(); + public: + /** + * fullfill the buffer with content of file specified by filename. + */ virtual int fullfill(const char* filename); + /** + * whether buffer is empty. + */ virtual bool empty(); }; };