diff options
author | rofl0r <rofl0r@users.noreply.github.com> | 2020-09-16 18:23:35 +0100 |
---|---|---|
committer | rofl0r <rofl0r@users.noreply.github.com> | 2020-09-16 21:01:02 +0100 |
commit | 45323584a0b24dc82d583cb34c85051363488bc9 (patch) | |
tree | 043c84e9121a3bab0a93de5328a532230c9bad73 | |
parent | caeab31fcaab5b4fc1985314447c4509f96c7265 (diff) |
speed up big config parsing by 2x using gperf
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/conf-tokens.gperf | 61 | ||||
-rw-r--r-- | src/conf-tokens.h | 53 | ||||
-rw-r--r-- | src/conf.c | 66 | ||||
-rw-r--r-- | src/conf.h | 2 | ||||
-rw-r--r-- | src/main.c | 2 |
6 files changed, 157 insertions, 31 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 51665f0..f028e4a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,6 +29,7 @@ tinyproxy_SOURCES = \ buffer.c buffer.h \ child.c child.h \ common.h \ + conf-tokens.c conf-tokens.h \ conf.c conf.h \ conns.c conns.h \ daemon.c daemon.h \ @@ -58,3 +59,6 @@ EXTRA_tinyproxy_SOURCES = filter.c filter.h \ transparent-proxy.c transparent-proxy.h tinyproxy_DEPENDENCIES = @ADDITIONAL_OBJECTS@ tinyproxy_LDADD = @ADDITIONAL_OBJECTS@ -lpthread + +conf-tokens.c: conf-tokens.gperf + gperf $< > $@ diff --git a/src/conf-tokens.gperf b/src/conf-tokens.gperf new file mode 100644 index 0000000..ef93245 --- /dev/null +++ b/src/conf-tokens.gperf @@ -0,0 +1,61 @@ +%{ +#include <string.h> +#include <stdlib.h> +#include "conf-tokens.h" +%} + +struct config_directive_entry { const char* name; enum config_directive value; }; + +%struct-type +%define slot-name name +%define initializer-suffix ,CD_NIL +%define lookup-function-name config_directive_find +%ignore-case +%7bit +%compare-lengths +%readonly-tables +%define constants-prefix CDS_ +%omit-struct-type + +%% +logfile, CD_logfile +pidfile, CD_pidfile +anonymous, CD_anonymous +viaproxyname, CD_viaproxyname +defaulterrorfile, CD_defaulterrorfile +statfile, CD_statfile +stathost, CD_stathost +xtinyproxy, CD_xtinyproxy +syslog, CD_syslog +bindsame, CD_bindsame +disableviaheader, CD_disableviaheader +port, CD_port +maxclients, CD_maxclients +maxspareservers, CD_maxspareservers +minspareservers, CD_minspareservers +startservers, CD_startservers +maxrequestsperchild, CD_maxrequestsperchild +timeout, CD_timeout +connectport, CD_connectport +user, CD_user +group, CD_group +listen, CD_listen +allow, CD_allow +deny, CD_deny +bind, CD_bind +basicauth, CD_basicauth +errorfile, CD_errorfile +addheader, CD_addheader +filter, CD_filter +filterurls, CD_filterurls +filterextended, CD_filterextended +filterdefaultdeny, CD_filterdefaultdeny +filtercasesensitive, CD_filtercasesensitive +reversebaseurl, CD_reversebaseurl +reverseonly, CD_reverseonly +reversemagic, CD_reversemagic +reversepath, CD_reversepath +upstream, CD_upstream +loglevel, CD_loglevel +%% + diff --git a/src/conf-tokens.h b/src/conf-tokens.h new file mode 100644 index 0000000..d9f03cd --- /dev/null +++ b/src/conf-tokens.h @@ -0,0 +1,53 @@ +#ifndef CONF_TOKENS_H +#define CONF_TOKENS_H + +enum config_directive { +CD_NIL = 0, +CD_logfile, +CD_pidfile, +CD_anonymous, +CD_viaproxyname, +CD_defaulterrorfile, +CD_statfile, +CD_stathost, +CD_xtinyproxy, +CD_syslog, +CD_bindsame, +CD_disableviaheader, +CD_port, +CD_maxclients, +CD_maxspareservers, +CD_minspareservers, +CD_startservers, +CD_maxrequestsperchild, +CD_timeout, +CD_connectport, +CD_user, +CD_group, +CD_listen, +CD_allow, +CD_deny, +CD_bind, +CD_basicauth, +CD_errorfile, +CD_addheader, +CD_filter, +CD_filterurls, +CD_filterextended, +CD_filterdefaultdeny, +CD_filtercasesensitive, +CD_reversebaseurl, +CD_reverseonly, +CD_reversemagic, +CD_reversepath, +CD_upstream, +CD_loglevel, +}; + +struct config_directive_entry { const char* name; enum config_directive value; }; + +const struct config_directive_entry * +config_directive_find (register const char *str, register size_t len); + +#endif + @@ -37,6 +37,7 @@ #include "upstream.h" #include "connect-ports.h" #include "basicauth.h" +#include "conf-tokens.h" /* * The configuration directives are defined in the structure below. Each @@ -98,10 +99,13 @@ typedef int (*CONFFILE_HANDLER) (struct config_s *, const char *, * List all the handling functions. These are defined later, but they need * to be in-scope before the big structure below. */ -static HANDLE_FUNC (handle_nop) +static HANDLE_FUNC (handle_disabled_feature) { - return 0; -} /* do nothing function */ + fprintf (stderr, "ERROR: accessing feature that was disabled at compiletime on line %lu\n", + lineno); + + return -1; +} static HANDLE_FUNC (handle_allow); static HANDLE_FUNC (handle_basicauth); @@ -161,7 +165,7 @@ static void config_free_regex (void); * do not follow the pattern above. This macro is for convenience * only. */ -#define STDCONF(d, re, func) { BEGIN "(" #d ")" WS re END, func, NULL } +#define STDCONF(d, re, func) [CD_ ## d] = { BEGIN "()" WS re END, func, NULL } /* * Holds the regular expression used to match the configuration directive, @@ -174,14 +178,6 @@ struct { CONFFILE_HANDLER handler; regex_t *cre; } directives[] = { - /* comments */ - { - BEGIN "#", handle_nop, NULL - }, - /* blank lines */ - { - "^[[:space:]]+$", handle_nop, NULL - }, /* string arguments */ STDCONF (logfile, STR, handle_logfile), STDCONF (pidfile, STR, handle_pidfile), @@ -326,20 +322,25 @@ void free_config (struct config_s *conf) } /* + * Initializes Config parser. Currently this means: * Compiles the regular expressions used by the configuration file. This * routine MUST be called before trying to parse the configuration file. * * Returns 0 on success; negative upon failure. */ int -config_compile_regex (void) +config_init (void) { unsigned int i, r; for (i = 0; i != ndirectives; ++i) { - assert (directives[i].handler); assert (!directives[i].cre); + if (!directives[i].handler) { + directives[i].handler = handle_disabled_feature; + continue; + } + directives[i].cre = (regex_t *) safemalloc (sizeof (regex_t)); if (!directives[i].cre) return -1; @@ -383,20 +384,17 @@ config_free_regex (void) * a negative number is returned. */ static int check_match (struct config_s *conf, const char *line, - unsigned long lineno) + unsigned long lineno, enum config_directive cd) { regmatch_t match[RE_MAX_MATCHES]; - unsigned int i; - - assert (ndirectives > 0); + unsigned int i = cd; - for (i = 0; i != ndirectives; ++i) { - assert (directives[i].cre); - if (!regexec - (directives[i].cre, line, RE_MAX_MATCHES, match, 0)) - return (*directives[i].handler) (conf, line, lineno, match); - } + if (!directives[i].cre) + return (*directives[i].handler) (conf, line, lineno, match); + if (!regexec + (directives[i].cre, line, RE_MAX_MATCHES, match, 0)) + return (*directives[i].handler) (conf, line, lineno, match); return -1; } @@ -405,15 +403,25 @@ static int check_match (struct config_s *conf, const char *line, */ static int config_parse (struct config_s *conf, FILE * f) { - char buffer[LINE_MAX]; + char buffer[LINE_MAX], *p, *q, c; + const struct config_directive_entry *e; unsigned long lineno = 1; - while (fgets (buffer, sizeof (buffer), f)) { - if (check_match (conf, buffer, lineno)) { - printf ("Syntax error on line %ld\n", lineno); + for (;fgets (buffer, sizeof (buffer), f);++lineno) { + if(buffer[0] == '#') continue; + p = buffer; + while(isspace(*p))p++; + if(!*p) continue; + q = p; + while(!isspace(*q))q++; + c = *q; + *q = 0; + e = config_directive_find(p, strlen(p)); + *q = c; + if (!e || e->value == CD_NIL || check_match (conf, q, lineno, e->value)) { + fprintf (stderr, "ERROR: Syntax error on line %lu\n", lineno); return 1; } - ++lineno; } return 0; } @@ -115,7 +115,7 @@ struct config_s { extern int reload_config_file (const char *config_fname, struct config_s *conf); -int config_compile_regex (void); +int config_init (void); void free_config (struct config_s *conf); #endif @@ -300,7 +300,7 @@ main (int argc, char **argv) log_message (LOG_NOTICE, "Initializing " PACKAGE " ..."); - if (config_compile_regex()) { + if (config_init()) { exit (EX_SOFTWARE); } |