summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrofl0r <rofl0r@users.noreply.github.com>2020-09-16 18:23:35 +0100
committerrofl0r <rofl0r@users.noreply.github.com>2020-09-16 21:01:02 +0100
commit45323584a0b24dc82d583cb34c85051363488bc9 (patch)
tree043c84e9121a3bab0a93de5328a532230c9bad73
parentcaeab31fcaab5b4fc1985314447c4509f96c7265 (diff)
speed up big config parsing by 2x using gperf
-rw-r--r--src/Makefile.am4
-rw-r--r--src/conf-tokens.gperf61
-rw-r--r--src/conf-tokens.h53
-rw-r--r--src/conf.c66
-rw-r--r--src/conf.h2
-rw-r--r--src/main.c2
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
+
diff --git a/src/conf.c b/src/conf.c
index 4a845c1..e7e0f32 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -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;
}
diff --git a/src/conf.h b/src/conf.h
index d71208c..9453d66 100644
--- a/src/conf.h
+++ b/src/conf.h
@@ -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
diff --git a/src/main.c b/src/main.c
index 98e024c..deb1f6d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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);
}