Changeset 298
- Timestamp:
- 04/23/2005 06:32:23 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 10 modified
-
src/Makefile.am (modified) (2 diffs)
-
src/array.c (modified) (1 diff)
-
src/array.h (modified) (5 diffs)
-
src/base.h (modified) (2 diffs)
-
src/configfile-glue.c (modified) (10 diffs)
-
src/configfile.c (modified) (12 diffs)
-
src/configfile.h (modified) (1 diff)
-
src/configparser.y (modified) (8 diffs)
-
src/connections.c (modified) (1 diff)
-
tests/Makefile.am (modified) (1 diff)
-
tests/condition.conf (added)
-
tests/core-condition.t (added)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/Makefile.am
r296 r298 34 34 data_string.c data_count.c data_array.c \ 35 35 data_integer.c md5.c data_fastcgi.c \ 36 data_config.c bitset.c configparser.c\36 data_config.c bitset.c \ 37 37 inet_ntop_cache.c \ 38 38 connections-glue.c \ … … 45 45 network_send.c network-glue.c fdevent-glue.c 46 46 47 src = server.c response.c connections.c configfile.c \47 src = server.c response.c connections.c configfile.c configparser.c \ 48 48 request.c network.c log.c fdevent.c \ 49 49 fdevent_select.c fdevent_linux_rtsig.c \ -
trunk/src/array.c
r288 r298 44 44 45 45 a->used = 0; 46 } 47 48 data_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; 46 58 } 47 59 -
trunk/src/array.h
r288 r298 63 63 64 64 typedef enum { CONFIG_COND_UNSET, CONFIG_COND_EQ, CONFIG_COND_MATCH, CONFIG_COND_NE, CONFIG_COND_NOMATCH } config_cond_t; 65 typedef enum { COND_RESULT_FALSE, COND_RESULT_TRUE, COND_RESULT_UNSET } cond_result_t; 65 66 66 67 /* $HTTP["host"] == "incremental.home.kneschke.de" { ... } … … 68 69 */ 69 70 70 typedef struct { 71 typedef struct _data_config data_config; 72 struct _data_config { 71 73 DATA_UNSET; 72 74 … … 76 78 77 79 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; 78 87 79 88 buffer *string; … … 82 91 pcre_extra *regex_study; 83 92 #endif 84 } data_config;93 }; 85 94 86 95 data_config *data_config_init(void); … … 112 121 void array_reset(array *a); 113 122 int array_insert_unique(array *a, data_unset *str); 123 data_unset *array_pop(array *a); 114 124 int array_print(array *a, int depth); 115 125 data_unset *array_get_unused_element(array *a, data_type_t t); -
trunk/src/base.h
r287 r298 216 216 unsigned short log_request_handling; 217 217 unsigned short log_response_header; 218 unsigned short log_condition_handling; 218 219 219 220 … … 344 345 345 346 specific_config conf; /* global connection specific config */ 347 cond_result_t *cond_results_cache; 346 348 347 349 buffer *server_name; -
trunk/src/configfile-glue.c
r272 r298 5 5 #include "array.h" 6 6 #include "log.h" 7 #include "plugin.h" 7 8 8 9 /** … … 156 157 } 157 158 158 int config_check_cond(server *srv, connection *con, data_config *dc) { 159 static int config_check_cond_cached(server *srv, connection *con, data_config *dc); 160 161 static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) { 159 162 server_socket *srv_sock = con->srv_socket; 160 163 buffer *l; 161 164 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 164 187 /* 165 188 * OPTIMIZE 166 189 * 167 190 * - replace all is_equal be simple == to an enum 168 * - only check each condition once at the start of the request169 * afterwards they will always evaluate in the same way170 * as they have the same input data171 191 * 172 192 */ 193 194 /* pass the rules */ 173 195 174 196 buffer_copy_string(srv->cond_check_buf, ""); … … 224 246 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string); 225 247 226 return 0;248 return COND_RESULT_FALSE; 227 249 } 228 250 … … 232 254 log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err); 233 255 234 return 0;256 return COND_RESULT_FALSE; 235 257 } 236 258 … … 241 263 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); 242 264 243 return 0;265 return COND_RESULT_FALSE; 244 266 } 245 267 … … 248 270 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); 249 271 250 return 0;272 return COND_RESULT_FALSE; 251 273 } 252 274 #endif … … 256 278 257 279 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; 259 281 } else { 260 return (dc->cond == CONFIG_COND_EQ) ? 0 : 1;282 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE; 261 283 } 262 284 } else { … … 296 318 } 297 319 } else { 298 return 0;320 return COND_RESULT_FALSE; 299 321 } 300 322 301 323 l = srv->cond_check_buf; 302 324 325 if (con->conf.log_condition_handling) { 326 log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key, "(", l, ") compare to ", dc->string); 327 } 303 328 switch(dc->cond) { 304 329 case CONFIG_COND_NE: 305 330 case CONFIG_COND_EQ: 306 331 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; 308 333 } else { 309 return (dc->cond == CONFIG_COND_EQ) ? 0 : 1;334 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE; 310 335 } 311 336 break; … … 321 346 322 347 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; 324 349 } else { 325 return (dc->cond == CONFIG_COND_MATCH) ? 0 : 1;350 return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_FALSE : COND_RESULT_TRUE; 326 351 } 327 352 #endif … … 334 359 } 335 360 336 return 0; 337 } 338 361 return COND_RESULT_FALSE; 362 } 363 364 static 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 391 int 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 71 71 { "server.close-stderr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */ 72 72 { "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 */ 73 74 74 75 { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, … … 169 170 170 171 cv[38].destination = &(s->force_lower_case); 172 cv[39].destination = &(s->log_condition_handling); 171 173 172 174 srv->config_storage[i] = s; … … 185 187 int config_setup_connection(server *srv, connection *con) { 186 188 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 } 187 194 188 195 PATCH(allow_http11); … … 206 213 PATCH(log_response_header); 207 214 PATCH(log_request_handling); 215 PATCH(log_condition_handling); 208 216 PATCH(log_file_not_found); 209 217 … … 265 273 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-response-header"))) { 266 274 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); 267 277 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) { 268 278 PATCH(log_file_not_found); … … 297 307 int in_cond; 298 308 } tokenizer_t; 309 310 static 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 321 static 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 } 299 330 300 331 static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) { … … 389 420 t->line_pos++; 390 421 break; 422 case '\n': 391 423 case '\r': 392 424 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 } 407 448 } 449 t->in_key = 1; 450 tid = TK_EOL; 451 buffer_copy_string(token, "(EOL)"); 408 452 } 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 } 424 457 break; 425 458 case ',': … … 501 534 502 535 break; 536 case '|': 537 t->offset++; 538 tid = TK_OR; 539 buffer_copy_string(token, "|"); 540 break; 541 503 542 case '{': 504 543 t->offset++; … … 520 559 521 560 break; 561 522 562 case '[': 523 563 t->offset++; … … 538 578 break; 539 579 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); 545 581 546 582 break; … … 663 699 664 700 context.ok = 1; 665 context.config = srv->config_context; 701 context.all_configs = srv->config_context; 702 context.configs_stack = array_init(); 666 703 667 704 dc = data_config_init(); 668 705 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; 673 711 674 712 /* default context */ … … 702 740 } 703 741 742 assert(context.configs_stack->used == 0); 743 array_free(context.configs_stack); 744 704 745 if (0 != config_insert(srv)) { 705 746 return -1; -
trunk/src/configfile.h
r1 r298 7 7 typedef struct { 8 8 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 { */ 12 12 } config_t; 13 13 -
trunk/src/configparser.y
r269 r298 11 11 #include "buffer.h" 12 12 #include "array.h" 13 14 static 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 23 static 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 13 29 } 14 30 … … 21 37 metalines ::= . 22 38 metaline ::= varline. 23 metaline ::= condline .39 metaline ::= condlines EOL. 24 40 metaline ::= EOL. 25 41 … … 28 44 %type aelements {array *} 29 45 %type array {array *} 46 %type condline {data_config *} 47 %type condlines {data_config *} 30 48 %type cond {config_cond_t } 31 49 %token_destructor { buffer_free($$); } … … 33 51 varline ::= key(A) ASSIGN value(B). { 34 52 buffer_copy_string_buffer(B->key, A); 35 if (NULL == array_get_element(ctx->c tx_config, B->key->ptr)) {36 array_insert_unique(ctx->c tx_config, B);53 if (NULL == array_get_element(ctx->current->value, B->key->ptr)) { 54 array_insert_unique(ctx->current->value, B); 37 55 } else { 38 fprintf(stderr, "Duplicate config variable in conditional %s: %s\n",39 ctx->c tx_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); 40 58 ctx->ok = 0; 41 59 B->free(B); … … 104 122 C = NULL; 105 123 } 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 125 eols ::= EOL. 126 eols ::= . 127 128 condlines(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 137 condlines(A) ::= condline(B). { 138 A = B; 139 B = NULL; 140 } 141 142 condline(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; 113 156 } 114 157
