Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine the mock for including in config #1

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 69 additions & 107 deletions trunk/src/app/srs_app_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ bool SrsConfDirective::is_stream_caster()

srs_error_t SrsConfDirective::parse(SrsConfigBuffer* buffer, SrsConfig* conf)
{
return parse_conf(buffer, parse_file, conf);
return parse_conf(buffer, SrsDirectiveContextFile, conf);
}

srs_error_t SrsConfDirective::persistence(SrsFileWriter* writer, int level)
Expand Down Expand Up @@ -971,80 +971,30 @@ SrsJsonAny* SrsConfDirective::dumps_arg0_to_boolean()
// LCOV_EXCL_STOP

// see: ngx_conf_parse
srs_error_t SrsConfDirective::parse_conf(SrsConfigBuffer* buffer, SrsDirectiveType type, SrsConfig* conf)
srs_error_t SrsConfDirective::parse_conf(SrsConfigBuffer* buffer, SrsDirectiveContext ctx, SrsConfig* conf)
{
srs_error_t err = srs_success;

while (true) {
std::vector<string> args;
int line_start = 0;
err = read_token(buffer, args, line_start);

/**
* 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
*/
if (srs_error_code(err) == ERROR_SYSTEM_CONFIG_INVALID) {
return err;
SrsDirectiveState state = SrsDirectiveStateInit;
if ((err = read_token(buffer, args, line_start, state)) != srs_success) {
return srs_error_wrap(err, "read token, line=%d, state=%d", line_start, state);
}
if (srs_error_code(err) == ERROR_SYSTEM_CONFIG_BLOCK_END) {
if (type != parse_block) {
return srs_error_wrap(err, "line %d: unexpected \"}\"", buffer->line);
}

srs_freep(err);
return srs_success;

if (state == SrsDirectiveStateBlockEnd) {
return ctx == SrsDirectiveContextBlock ? srs_success : srs_error_wrap(err, "line %d: unexpected \"}\"", buffer->line);
}
if (srs_error_code(err) == ERROR_SYSTEM_CONFIG_EOF) {
if (type == parse_block) {
return srs_error_wrap(err, "line %d: unexpected end of file, expecting \"}\"", conf_line);
}

srs_freep(err);
return srs_success;
if (state == SrsDirectiveStateEOF) {
return ctx != SrsDirectiveContextBlock ? srs_success : srs_error_wrap(err, "line %d: unexpected end of file, expecting \"}\"", conf_line);
}

if (args.empty()) {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "line %d: empty directive", conf_line);
}

// build directive tree.
if (args.at(0) == "include") {
if (args.size() < 2) {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "line %d: include is empty directive", buffer->line);
}

for (int i = 1; i < (int)args.size(); i++) {
std::string file = args.at(i);

srs_freep(err);
if (file.empty()) {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "empty include config");
}

srs_trace("config parse include %s", file.c_str());
if (type != parse_block) {
if ((err = conf->parse_include_file(file.c_str())) != srs_success) {
return srs_error_wrap(err, "parse file");
}
} else {
SrsConfigBuffer* config_buffer = conf->get_buffer_from_include_file(file.c_str());
SrsAutoFree(SrsConfigBuffer, config_buffer);

if(config_buffer == NULL) {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "empty include buffer, file=%s", file.c_str());
} else {
if ((err = parse_conf(config_buffer, parse_file, conf)) != srs_success) {
return srs_error_wrap(err, "parse include buffer");
}
}
}
}
} else {
// Build normal directive which is not "include".
if (args.at(0) != "include") {
SrsConfDirective* directive = new SrsConfDirective();

directive->conf_line = line_start;
Expand All @@ -1054,21 +1004,45 @@ srs_error_t SrsConfDirective::parse_conf(SrsConfigBuffer* buffer, SrsDirectiveTy

directives.push_back(directive);

if (srs_error_code(err) == ERROR_SYSTEM_CONFIG_BLOCK_START) {
srs_freep(err);
if ((err = directive->parse_conf(buffer, parse_block, conf)) != srs_success) {
if (state == SrsDirectiveStateBlockStart) {
if ((err = directive->parse_conf(buffer, SrsDirectiveContextBlock, conf)) != srs_success) {
return srs_error_wrap(err, "parse dir");
}
}
continue;
}

// Parse including, allow multiple files.
vector<string> files(args.begin() + 1, args.end());
if (files.empty()) {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "line %d: include is empty directive", buffer->line);
}
if (!conf) {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "line %d: no config", buffer->line);
}

for (int i = 0; i < (int)files.size(); i++) {
std::string file = files.at(i);
srs_assert(!file.empty());
srs_trace("config parse include %s", file.c_str());

SrsConfigBuffer* include_file_buffer = NULL;
SrsAutoFree(SrsConfigBuffer, include_file_buffer);
if ((err = conf->build_buffer(file, &include_file_buffer)) != srs_success) {
return srs_error_wrap(err, "buffer fullfill %s", file.c_str());
}

if ((err = parse_conf(include_file_buffer, SrsDirectiveContextFile, conf)) != srs_success) {
return srs_error_wrap(err, "parse include buffer");
}
}
srs_freep(err);
}

return err;
}

// see: ngx_conf_read_token
srs_error_t SrsConfDirective::read_token(SrsConfigBuffer* buffer, vector<string>& args, int& line_start)
srs_error_t SrsConfDirective::read_token(SrsConfigBuffer* buffer, vector<string>& args, int& line_start, SrsDirectiveState& state)
{
srs_error_t err = srs_success;

Expand All @@ -1090,8 +1064,9 @@ srs_error_t SrsConfDirective::read_token(SrsConfigBuffer* buffer, vector<string>
buffer->line);
}
srs_trace("config parse complete");

return srs_error_new(ERROR_SYSTEM_CONFIG_EOF, "EOF");

state = SrsDirectiveStateEOF;
return err;
}

char ch = *buffer->pos++;
Expand All @@ -1112,10 +1087,12 @@ srs_error_t SrsConfDirective::read_token(SrsConfigBuffer* buffer, vector<string>
continue;
}
if (ch == ';') {
return srs_error_new(ERROR_SYSTEM_CONFIG_DIRECTIVE, "dir");
state = SrsDirectiveStateEntire;
return err;
}
if (ch == '{') {
return srs_error_new(ERROR_SYSTEM_CONFIG_BLOCK_START, "block");
state = SrsDirectiveStateBlockStart;
return err;
}
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "line %d: unexpected '%c'", buffer->line, ch);
}
Expand All @@ -1131,17 +1108,20 @@ srs_error_t SrsConfDirective::read_token(SrsConfigBuffer* buffer, vector<string>
if (args.size() == 0) {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "line %d: unexpected ';'", buffer->line);
}
return srs_error_new(ERROR_SYSTEM_CONFIG_DIRECTIVE, "dir");
state = SrsDirectiveStateEntire;
return err;
case '{':
if (args.size() == 0) {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "line %d: unexpected '{'", buffer->line);
}
return srs_error_new(ERROR_SYSTEM_CONFIG_BLOCK_START, "block");
state = SrsDirectiveStateBlockStart;
return err;
case '}':
if (args.size() != 0) {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "line %d: unexpected '}'", buffer->line);
}
return srs_error_new(ERROR_SYSTEM_CONFIG_BLOCK_END, "block");
state = SrsDirectiveStateBlockEnd;
return err;
case '#':
sharp_comment = 1;
continue;
Expand Down Expand Up @@ -1196,10 +1176,12 @@ srs_error_t SrsConfDirective::read_token(SrsConfigBuffer* buffer, vector<string>
srs_freepa(aword);

if (ch == ';') {
return srs_error_new(ERROR_SYSTEM_CONFIG_DIRECTIVE, "dir");
state = SrsDirectiveStateEntire;
return err;
}
if (ch == '{') {
return srs_error_new(ERROR_SYSTEM_CONFIG_BLOCK_START, "block");
state = SrsDirectiveStateBlockStart;
return err;
}
}
}
Expand Down Expand Up @@ -2439,53 +2421,33 @@ srs_error_t SrsConfig::parse_file(const char* filename)
if (config_file.empty()) {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "empty config");
}
SrsConfigBuffer buffer;

if ((err = buffer.fullfill(config_file.c_str())) != srs_success) {
return srs_error_wrap(err, "buffer fullfil");

SrsConfigBuffer* buffer = NULL;
SrsAutoFree(SrsConfigBuffer, buffer);
if ((err = build_buffer(config_file, &buffer)) != srs_success) {
return srs_error_wrap(err, "buffer fullfill %s", config_file.c_str());
}

if ((err = parse_buffer(&buffer)) != srs_success) {
if ((err = parse_buffer(buffer)) != srs_success) {
return srs_error_wrap(err, "parse buffer");
}

return err;
}

srs_error_t SrsConfig::parse_include_file(const char *filename)
{
srs_error_t err = srs_success;

std::string file = filename;

SrsConfigBuffer buffer;

if ((err = buffer.fullfill(file.c_str())) != srs_success) {
return srs_error_wrap(err, "buffer fullfil");
}

// Parse root tree from buffer.
if ((err = root->parse(&buffer, this)) != srs_success) {
return srs_error_wrap(err, "parse include buffer");
}

return err;
}

SrsConfigBuffer* SrsConfig::get_buffer_from_include_file(const char* filename)
srs_error_t SrsConfig::build_buffer(string src, SrsConfigBuffer** pbuffer)
{
srs_error_t err = srs_success;

SrsConfigBuffer* buffer = new SrsConfigBuffer();

if ((err = buffer->fullfill(filename)) != srs_success) {
if ((err = buffer->fullfill(src.c_str())) != srs_success) {
srs_freep(buffer);

return NULL;
return srs_error_wrap(err, "read from src %s", src.c_str());
}

return buffer;
*pbuffer = buffer;
return err;
}
// LCOV_EXCL_STOP

Expand Down
35 changes: 24 additions & 11 deletions trunk/src/app/srs_app_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,24 +223,36 @@ class SrsConfDirective
virtual SrsJsonAny* dumps_arg0_to_boolean();
// private parse.
private:
// The directive parsing type.
enum SrsDirectiveType {
// The directive parsing context.
enum SrsDirectiveContext {
// The root directives, parsing file.
parse_file,
// For each direcitve, parsing text block.
parse_block
SrsDirectiveContextFile,
// For each directive, parsing text block.
SrsDirectiveContextBlock,
};
enum SrsDirectiveState {
// Init state
SrsDirectiveStateInit,
// The directive terminated by ';' found
SrsDirectiveStateEntire,
// The token terminated by '{' found
SrsDirectiveStateBlockStart,
// The '}' found
SrsDirectiveStateBlockEnd,
// The config file is done
SrsDirectiveStateEOF,
};
// 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 srs_error_t parse_conf(srs_internal::SrsConfigBuffer* buffer, SrsDirectiveType type, SrsConfig* conf);
virtual srs_error_t parse_conf(srs_internal::SrsConfigBuffer* buffer, SrsDirectiveContext ctx, SrsConfig* conf);
// 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.
// @param line_start, the actual start line of directive.
// @return, an error code indicates error or has child-directives.
virtual srs_error_t read_token(srs_internal::SrsConfigBuffer* buffer, std::vector<std::string>& args, int& line_start);
virtual srs_error_t read_token(srs_internal::SrsConfigBuffer* buffer, std::vector<std::string>& args, int& line_start, SrsDirectiveState& state);
};

// The config service provider.
Expand All @@ -250,6 +262,7 @@ class SrsConfDirective
// You could keep it before st-thread switch, or simply never keep it.
class SrsConfig
{
friend class SrsConfDirective;
// user command
private:
// Whether srs is run in dolphin mode.
Expand Down Expand Up @@ -356,10 +369,10 @@ class SrsConfig
public:
// Parse the config file, which is specified by cli.
virtual srs_error_t parse_file(const char* filename);
// Parse the include config file.
virtual srs_error_t parse_include_file(const char* filename);
// Get buffer from include config file.
virtual srs_internal::SrsConfigBuffer* get_buffer_from_include_file(const char* filename);
private:
// Build a buffer from a src, which is string content or filename.
virtual srs_error_t build_buffer(std::string src, srs_internal::SrsConfigBuffer** pbuffer);
public:
// Check the parsed config.
virtual srs_error_t check_config();
protected:
Expand Down
4 changes: 0 additions & 4 deletions trunk/src/kernel/srs_kernel_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@
#define ERROR_SYSTEM_ASSERT_FAILED 1021
#define ERROR_READER_BUFFER_OVERFLOW 1022
#define ERROR_SYSTEM_CONFIG_INVALID 1023
#define ERROR_SYSTEM_CONFIG_DIRECTIVE 1024
#define ERROR_SYSTEM_CONFIG_BLOCK_START 1025
#define ERROR_SYSTEM_CONFIG_BLOCK_END 1026
#define ERROR_SYSTEM_CONFIG_EOF 1027
#define ERROR_SYSTEM_STREAM_BUSY 1028
#define ERROR_SYSTEM_IP_INVALID 1029
#define ERROR_SYSTEM_FORWARD_LOOP 1030
Expand Down
Loading