Changeset 298

Show
Ignore:
Timestamp:
04/23/2005 06:32:23 PM (3 years ago)
Author:
moo
Message:

nesting/chaining condition
new config item: debug.log-condition-handling

Location:
trunk
Files:
2 added
10 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/Makefile.am

    r296 r298  
    3434      data_string.c data_count.c data_array.c \ 
    3535      data_integer.c md5.c data_fastcgi.c \ 
    36       data_config.c bitset.c  configparser.c \ 
     36      data_config.c bitset.c \ 
    3737      inet_ntop_cache.c \ 
    3838      connections-glue.c \ 
     
    4545      network_send.c network-glue.c fdevent-glue.c 
    4646 
    47 src = server.c response.c connections.c configfile.c \ 
     47src = server.c response.c connections.c configfile.c configparser.c \ 
    4848      request.c network.c log.c fdevent.c \ 
    4949      fdevent_select.c fdevent_linux_rtsig.c \ 
  • trunk/src/array.c

    r288 r298  
    4444         
    4545        a->used = 0; 
     46} 
     47 
     48data_unset *array_pop(array *a) { 
     49        data_unset *du; 
     50 
     51        assert(a->used != 0); 
     52 
     53        a->used --; 
     54        du = a->data[a->used]; 
     55        a->data[a->used] = NULL; 
     56 
     57        return du; 
    4658} 
    4759 
  • trunk/src/array.h

    r288 r298  
    6363 
    6464typedef enum { CONFIG_COND_UNSET, CONFIG_COND_EQ, CONFIG_COND_MATCH, CONFIG_COND_NE, CONFIG_COND_NOMATCH } config_cond_t; 
     65typedef enum { COND_RESULT_FALSE, COND_RESULT_TRUE, COND_RESULT_UNSET } cond_result_t; 
    6566 
    6667/* $HTTP["host"] ==    "incremental.home.kneschke.de" { ... }  
     
    6869 */ 
    6970 
    70 typedef struct { 
     71typedef struct _data_config data_config; 
     72struct _data_config { 
    7173        DATA_UNSET; 
    7274         
     
    7678         
    7779        config_cond_t cond; 
     80        int context_ndx; /* more or less like an id */ 
     81        array *childs; 
     82        /* nested */ 
     83        data_config *parent; 
     84        /* for chaining only */ 
     85        data_config *prev; 
     86        data_config *next; 
    7887         
    7988        buffer *string; 
     
    8291        pcre_extra *regex_study; 
    8392#endif 
    84 } data_config; 
     93}; 
    8594 
    8695data_config *data_config_init(void); 
     
    112121void array_reset(array *a); 
    113122int array_insert_unique(array *a, data_unset *str); 
     123data_unset *array_pop(array *a); 
    114124int array_print(array *a, int depth); 
    115125data_unset *array_get_unused_element(array *a, data_type_t t); 
  • trunk/src/base.h

    r287 r298  
    216216        unsigned short log_request_handling; 
    217217        unsigned short log_response_header; 
     218        unsigned short log_condition_handling; 
    218219         
    219220         
     
    344345         
    345346        specific_config conf;        /* global connection specific config */ 
     347        cond_result_t *cond_results_cache; 
    346348         
    347349        buffer *server_name; 
  • trunk/src/configfile-glue.c

    r272 r298  
    55#include "array.h" 
    66#include "log.h" 
     7#include "plugin.h" 
    78 
    89/** 
     
    156157} 
    157158 
    158 int config_check_cond(server *srv, connection *con, data_config *dc) { 
     159static int config_check_cond_cached(server *srv, connection *con, data_config *dc); 
     160 
     161static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) { 
    159162        server_socket *srv_sock = con->srv_socket; 
    160163        buffer *l; 
    161164         
    162         /* pass the rules */ 
    163          
     165        /* check parent first */ 
     166        if (dc->parent) { 
     167                if (con->conf.log_condition_handling) { 
     168                        log_error_write(srv, __FILE__, __LINE__,  "sb", "go parent", dc->parent->string); 
     169                } 
     170                if (!config_check_cond_cached(srv, con, dc->parent)) { 
     171                        return COND_RESULT_FALSE; 
     172                } 
     173        } 
     174 
     175        if (dc->prev) { 
     176                if (con->conf.log_condition_handling) { 
     177                        log_error_write(srv, __FILE__, __LINE__,  "sb", "go prev", dc->prev->string); 
     178                } 
     179                /* make sure prev is checked first */ 
     180                config_check_cond_cached(srv, con, dc->prev); 
     181                /* one of prev set me to FALSE */ 
     182                if (con->cond_results_cache[dc->context_ndx] == COND_RESULT_FALSE) { 
     183                        return COND_RESULT_FALSE; 
     184                } 
     185        } 
     186 
    164187        /*  
    165188         * OPTIMIZE 
    166189         *  
    167190         * - replace all is_equal be simple == to an enum 
    168          * - only check each condition once at the start of the request 
    169          *   afterwards they will always evaluate in the same way  
    170          *   as they have the same input data 
    171191         *  
    172192         */ 
     193 
     194        /* pass the rules */ 
    173195         
    174196        buffer_copy_string(srv->cond_check_buf, ""); 
     
    224246                                log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string); 
    225247                                         
    226                                 return 0; 
     248                                return COND_RESULT_FALSE; 
    227249                        } 
    228250                         
     
    232254                                log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err); 
    233255                                 
    234                                 return 0; 
     256                                return COND_RESULT_FALSE; 
    235257                        } 
    236258                         
     
    241263                                log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); 
    242264                                 
    243                                 return 0; 
     265                                return COND_RESULT_FALSE; 
    244266                        } 
    245267 
     
    248270                                log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); 
    249271                                 
    250                                 return 0; 
     272                                return COND_RESULT_FALSE; 
    251273                        } 
    252274#endif 
     
    256278                         
    257279                        if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) { 
    258                                 return (dc->cond == CONFIG_COND_EQ) ? 1 : 0; 
     280                                return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE; 
    259281                        } else { 
    260                                 return (dc->cond == CONFIG_COND_EQ) ? 0 : 1; 
     282                                return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE; 
    261283                        } 
    262284                } else { 
     
    296318                } 
    297319        } else { 
    298                 return 0; 
     320                return COND_RESULT_FALSE; 
    299321        } 
    300322         
    301323        l = srv->cond_check_buf; 
    302324         
     325        if (con->conf.log_condition_handling) { 
     326                log_error_write(srv, __FILE__, __LINE__,  "bsbsb", dc->comp_key, "(", l, ") compare to ", dc->string); 
     327        } 
    303328        switch(dc->cond) { 
    304329        case CONFIG_COND_NE: 
    305330        case CONFIG_COND_EQ: 
    306331                if (buffer_is_equal(l, dc->string)) { 
    307                         return (dc->cond == CONFIG_COND_EQ) ? 1 : 0; 
     332                        return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE; 
    308333                } else { 
    309                         return (dc->cond == CONFIG_COND_EQ) ? 0 : 1; 
     334                        return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE; 
    310335                } 
    311336                break; 
     
    321346                 
    322347                if (n > 0) { 
    323                         return (dc->cond == CONFIG_COND_MATCH) ? 1 : 0; 
     348                        return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE; 
    324349                } else { 
    325                         return (dc->cond == CONFIG_COND_MATCH) ? 0 : 1; 
     350                        return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_FALSE : COND_RESULT_TRUE; 
    326351                } 
    327352#endif           
     
    334359        } 
    335360         
    336         return 0; 
    337 } 
    338  
     361        return COND_RESULT_FALSE; 
     362} 
     363 
     364static int config_check_cond_cached(server *srv, connection *con, data_config *dc) { 
     365        cond_result_t *cache = con->cond_results_cache; 
     366 
     367        if (cache[dc->context_ndx] == COND_RESULT_UNSET) { 
     368                if (COND_RESULT_TRUE == (cache[dc->context_ndx] = config_check_cond_nocache(srv, con, dc))) { 
     369                        if (dc->next) { 
     370                                data_config *c; 
     371                                if (con->conf.log_condition_handling) { 
     372                                        log_error_write(srv, __FILE__, __LINE__, "s", "setting remains of chaining to FALSE"); 
     373                                } 
     374                                for (c = dc->next; c; c = c->next) { 
     375                                        cache[c->context_ndx] = COND_RESULT_FALSE; 
     376                                } 
     377                        } 
     378                } 
     379                if (con->conf.log_condition_handling) { 
     380                        log_error_write(srv, __FILE__, __LINE__, "dsd", dc->context_ndx, "(uncached) result:", cache[dc->context_ndx]); 
     381                } 
     382        } 
     383        else { 
     384                if (con->conf.log_condition_handling) { 
     385                        log_error_write(srv, __FILE__, __LINE__, "dsd", dc->context_ndx, "(cached) result:", cache[dc->context_ndx]); 
     386                } 
     387        } 
     388        return cache[dc->context_ndx]; 
     389} 
     390 
     391int config_check_cond(server *srv, connection *con, data_config *dc) { 
     392        if (con->conf.log_condition_handling) { 
     393                log_error_write(srv, __FILE__, __LINE__,  "s",  "=== start of condition block ==="); 
     394        } 
     395        return config_check_cond_cached(srv, con, dc); 
     396} 
  • trunk/src/configfile.c

    r258 r298  
    7171                { "server.close-stderr",         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },     /* 37 */ 
    7272                { "server.force-lowercase-filenames", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER },   /* 38 */ 
     73                { "debug.log-condition-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 39 */ 
    7374                 
    7475                { "server.host",                 "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, 
     
    169170                 
    170171                cv[38].destination = &(s->force_lower_case); 
     172                cv[39].destination = &(s->log_condition_handling); 
    171173                 
    172174                srv->config_storage[i] = s; 
     
    185187int config_setup_connection(server *srv, connection *con) { 
    186188        specific_config *s = srv->config_storage[0]; 
     189        int i; 
     190         
     191        for (i = srv->config_context->used - 1; i >= 0; i --) { 
     192                con->cond_results_cache[i] = COND_RESULT_UNSET; 
     193        } 
    187194         
    188195        PATCH(allow_http11); 
     
    206213        PATCH(log_response_header); 
    207214        PATCH(log_request_handling); 
     215        PATCH(log_condition_handling); 
    208216        PATCH(log_file_not_found); 
    209217         
     
    265273                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-response-header"))) { 
    266274                                PATCH(log_response_header); 
     275                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) { 
     276                                PATCH(log_condition_handling); 
    267277                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) { 
    268278                                PATCH(log_file_not_found); 
     
    297307        int in_cond; 
    298308} tokenizer_t; 
     309 
     310static int config_skip_newline(tokenizer_t *t) { 
     311        int skipped = 1; 
     312        assert(t->input[t->offset] == '\r' || t->input[t->offset] == '\n'); 
     313        if (t->input[t->offset] == '\r' && t->input[t->offset + 1] == '\n') { 
     314                skipped ++; 
     315                t->offset ++; 
     316        } 
     317        t->offset ++; 
     318        return skipped; 
     319} 
     320 
     321static int config_skip_comment(tokenizer_t *t) { 
     322        int i; 
     323        assert(t->input[t->offset] == '#'); 
     324        for (i = 1; t->input[t->offset + i] &&  
     325             (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r'); 
     326             i++); 
     327        t->offset += i; 
     328        return i; 
     329} 
    299330 
    300331static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) { 
     
    389420                        t->line_pos++; 
    390421                        break; 
     422                case '\n': 
    391423                case '\r': 
    392424                        if (t->in_brace == 0) { 
    393                                 if (t->input[t->offset + 1] == '\n') { 
    394                                         t->in_key = 1; 
    395                                         t->offset += 2; 
    396                                          
    397                                         tid = TK_EOL; 
    398                                         t->line++; 
    399                                         t->line_pos = 1; 
    400                                          
    401                                         buffer_copy_string(token, "(EOL)"); 
    402                                 } else { 
    403                                         log_error_write(srv, __FILE__, __LINE__, "sdsds",  
    404                                                         "line:", t->line, "pos:", t->line_pos,  
    405                                                         "CR without LF"); 
    406                                         return 0; 
     425                                int done = 0; 
     426                                while (!done) { 
     427                                        switch (t->input[t->offset]) { 
     428                                        case '\r': 
     429                                        case '\n': 
     430                                                config_skip_newline(t); 
     431                                                t->line_pos = 1; 
     432                                                t->line++; 
     433                                                break; 
     434 
     435                                        case '#': 
     436                                                t->line_pos += config_skip_comment(t); 
     437                                                break; 
     438 
     439                                        case '\t': 
     440                                        case ' ': 
     441                                                t->offset++; 
     442                                                t->line_pos++; 
     443                                                break; 
     444 
     445                                        default: 
     446                                                done = 1; 
     447                                        } 
    407448                                } 
     449                                t->in_key = 1; 
     450                                tid = TK_EOL; 
     451                                buffer_copy_string(token, "(EOL)"); 
    408452                        } else { 
    409                                 t->offset++; 
    410                                 t->line_pos++; 
    411                         } 
    412                         break; 
    413                 case '\n': 
    414                         if (t->in_brace == 0) { 
    415                                 t->in_key = 1; 
    416                                  
    417                                 tid = TK_EOL; 
    418                                  
    419                                 buffer_copy_string(token, "(EOL)"); 
    420                         } 
    421                         t->line++; 
    422                         t->line_pos = 1; 
    423                         t->offset++; 
     453                                config_skip_newline(t); 
     454                                t->line_pos = 1; 
     455                                t->line++; 
     456                        } 
    424457                        break; 
    425458                case ',': 
     
    501534                         
    502535                        break; 
     536                case '|': 
     537                        t->offset++; 
     538                        tid = TK_OR; 
     539                        buffer_copy_string(token, "|"); 
     540                        break; 
     541 
    503542                case '{': 
    504543                        t->offset++; 
     
    520559                         
    521560                        break; 
     561 
    522562                case '[': 
    523563                        t->offset++; 
     
    538578                        break; 
    539579                case '#': 
    540                         for (i = 1; t->input[t->offset + i] &&  
    541                              (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r'); 
    542                              i++); 
    543                          
    544                         t->offset += i; 
     580                        t->line_pos += config_skip_comment(t); 
    545581                         
    546582                        break; 
     
    663699         
    664700        context.ok = 1; 
    665         context.config = srv->config_context; 
     701        context.all_configs = srv->config_context; 
     702        context.configs_stack = array_init(); 
    666703         
    667704        dc = data_config_init(); 
    668705        buffer_copy_string(dc->key, "global"); 
    669         array_insert_unique(srv->config_context, (data_unset *)dc); 
    670          
    671         context.ctx_name = dc->key; 
    672         context.ctx_config = dc->value; 
     706 
     707        assert(context.all_configs->used == 0); 
     708        dc->context_ndx = context.all_configs->used; 
     709        array_insert_unique(context.all_configs, (data_unset *)dc); 
     710        context.current = dc; 
    673711         
    674712        /* default context */ 
     
    702740        } 
    703741         
     742        assert(context.configs_stack->used == 0); 
     743        array_free(context.configs_stack); 
     744 
    704745        if (0 != config_insert(srv)) { 
    705746                return -1; 
  • trunk/src/configfile.h

    r1 r298  
    77typedef struct { 
    88        int     ok; 
    9         array  *config; 
    10         buffer *ctx_name; 
    11         array  *ctx_config; 
     9        array  *all_configs; 
     10        array  *configs_stack; /* to parse nested block */ 
     11        data_config *current; /* current started with { */ 
    1212} config_t; 
    1313 
  • trunk/src/configparser.y

    r269 r298  
    1111#include "buffer.h" 
    1212#include "array.h" 
     13 
     14static void configparser_push(config_t *ctx, data_config *dc, int isnew) { 
     15  if (isnew) { 
     16    dc->context_ndx = ctx->all_configs->used; 
     17    array_insert_unique(ctx->all_configs, (data_unset *)dc); 
     18  } 
     19  array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current); 
     20  ctx->current = dc; 
     21} 
     22 
     23static data_config *configparser_pop(config_t *ctx) { 
     24  data_config *old = ctx->current; 
     25  ctx->current = (data_config *) array_pop(ctx->configs_stack); 
     26  return old; 
     27} 
     28 
    1329} 
    1430 
     
    2137metalines ::= . 
    2238metaline ::= varline. 
    23 metaline ::= condline. 
     39metaline ::= condlines EOL. 
    2440metaline ::= EOL. 
    2541 
     
    2844%type aelements {array *} 
    2945%type array {array *} 
     46%type condline {data_config *} 
     47%type condlines {data_config *} 
    3048%type cond {config_cond_t } 
    3149%token_destructor { buffer_free($$); } 
     
    3351varline ::= key(A) ASSIGN value(B). { 
    3452  buffer_copy_string_buffer(B->key, A); 
    35   if (NULL == array_get_element(ctx->ctx_config, B->key->ptr)) { 
    36     array_insert_unique(ctx->ctx_config, B); 
     53  if (NULL == array_get_element(ctx->current->value, B->key->ptr)) { 
     54    array_insert_unique(ctx->current->value, B); 
    3755  } else { 
    38     fprintf(stderr, "Duplicate config variable in conditional %s: %s\n",  
    39             ctx->ctx_name->ptr, B->key->ptr); 
     56    fprintf(stderr, "Duplicate config variable in conditional 1 %s: %s\n",  
     57            ctx->current->key->ptr, B->key->ptr); 
    4058    ctx->ok = 0; 
    4159    B->free(B); 
     
    104122  C = NULL; 
    105123} 
    106 condline ::= context LCURLY metalines RCURLY EOL. { 
    107   data_config *dc; 
    108    
    109   dc = (data_config *)array_get_element(ctx->config, "global"); 
    110   assert(dc); 
    111   ctx->ctx_name = dc->key; 
    112   ctx->ctx_config = dc->value; 
     124 
     125eols ::= EOL. 
     126eols ::= . 
     127 
     128condlines(A) ::= condlines(B) eols OR condline(C). { 
     129  assert(B->context_ndx < C->context_ndx); 
     130  C->prev = B; 
     131  B->next = C; 
     132  A = C; 
     133  B = NULL; 
     134  C = NULL; 
     135} 
     136 
     137condlines(A) ::= condline(B). { 
     138  A = B; 
     139  B = NULL; 
     140} 
     141 
     142condline(A) ::= context LCURLY metalines RCURLY. { 
     143  data_config *parent, *cur; 
     144   
     145  cur = ctx->current; 
     146  configparser_pop(ctx); 
     147  parent = ctx->current; 
     148 
     149  assert(cur && parent); 
     150 
     151  if (0 != parent->context_ndx) { /* not global */ 
     152    assert(cur->context_ndx > parent->context_ndx); 
     153    cur->parent = parent; 
     154  } 
     155  A = cur; 
    113156} 
    114157