1 /** 2 * Copyright 2006 Christian Liesch 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * @file 19 * 20 * @Author christian liesch <liesch@gmx.ch> 21 * 22 * Interface of the HTTP Test Tool file. 23 */ 24 25 #ifndef HTTEST_WORKER_H 26 #define HTTEST_WORKER_H 27 28 #include <setjmp.h> 29 #include <apr_hooks.h> 30 #include "logger.h" 31 #include "transport.h" 32 #include "store.h" 33 #include "socket.h" 34 35 typedef struct command_s command_t; 36 typedef apr_status_t(*command_f) (command_t * self, void * type, char *data, 37 apr_pool_t *ptmp); 38 39 struct command_s { 40 char *name; 41 command_f func; 42 char *syntax; 43 char *help; 44 #define COMMAND_FLAGS_NONE 0x00000000 45 #define COMMAND_FLAGS_DEPRECIATED 0x00000001 46 #define COMMAND_FLAGS_EXPERIMENTAL 0x00000002 47 #define COMMAND_FLAGS_LINK 0x00000004 48 #define COMMAND_FLAGS_BODY 0x00000008 49 int flags; 50 }; 51 52 typedef struct socket_s { 53 int is_ssl; 54 transport_t *transport; 55 apr_socket_t *socket; 56 #define SOCKET_CLOSED 0 57 #define SOCKET_CONNECTED 1 58 int socket_state; 59 /* worker config */ 60 apr_hash_t *config; 61 apr_size_t peeklen; 62 char peek[32]; 63 apr_table_t *cookies; 64 char *cookie; 65 sockreader_t *sockreader; 66 } socket_t; 67 68 typedef struct validation_s { 69 apr_table_t *ns; 70 71 apr_table_t *dot; 72 apr_table_t *headers; 73 apr_table_t *body; 74 apr_table_t *error; 75 apr_table_t *exec; 76 } validation_t; 77 78 typedef struct worker_s worker_t; 79 typedef struct global_s global_t; 80 typedef apr_status_t(*interpret_f)(worker_t *worker, worker_t *parent, 81 apr_pool_t *ptmp); 82 typedef const char *(*readline_f)(worker_t *worker); 83 struct worker_s { 84 global_t *global; 85 /* readline function */ 86 readline_f readline; 87 /* interpreter function */ 88 interpret_f interpret; 89 /* worker config */ 90 apr_hash_t *config; 91 /* worker block if this is a CALL */ 92 worker_t *block; 93 /* this is the pool where the structure lives */ 94 apr_pool_t *heartbeat; 95 /* dies on END */ 96 apr_pool_t *pbody; 97 /* dies on every flush */ 98 apr_pool_t *pcache; 99 /* body variables */ 100 store_t *vars; 101 /* block parameters */ 102 store_t *params; 103 /* block return variables */ 104 store_t *retvars; 105 /* block local variables */ 106 store_t *locals; 107 /* buffered stdout */ 108 apr_file_t *out; 109 /* buffered errout */ 110 apr_file_t *err; 111 /* filename of current script part */ 112 const char *filename; 113 #define FLAGS_NONE 0x00000000 114 #define FLAGS_PIPE 0x00000001 115 #define FLAGS_CHUNKED 0x00000002 116 #define FLAGS_PIPE_IN 0x00000008 117 #define FLAGS_FILTER 0x00000010 118 #define FLAGS_CLIENT 0x00000020 119 #define FLAGS_SERVER 0x00000040 120 #define FLAGS_ONLY_PRINTABLE 0x00000080 121 #define FLAGS_PRINT_HEX 0x00000100 122 #define FLAGS_SSL_LEGACY 0x00000200 123 #define FLAGS_AUTO_CLOSE 0x00000400 124 #define FLAGS_AUTO_COOKIE 0x00000800 125 #define FLAGS_IGNORE_BODY 0x00001000 126 #define FLAGS_SKIP_FLUSH 0x00002000 127 #define FLAGS_LOADED_BLOCK 0x00004000 128 int flags; 129 int cmd; 130 int cmd_from; 131 int cmd_to; 132 int which; 133 int group; 134 char *name; 135 char *additional; 136 const char *short_desc; 137 const char *desc; 138 int chunksize; 139 apr_size_t sent; 140 int req_cnt; 141 char *match_seq; 142 apr_time_t socktmo; 143 apr_thread_t *mythread; 144 apr_thread_mutex_t *sync_mutex; 145 apr_thread_mutex_t *log_mutex; 146 apr_thread_mutex_t *mutex; 147 apr_table_t *lines; 148 apr_table_t *cache; 149 validation_t match; 150 validation_t grep; 151 validation_t expect; 152 apr_table_t *headers_allow; 153 apr_table_t *headers_filter; 154 apr_table_t *headers_add; 155 apr_table_t *headers; 156 apr_hash_t *modules; 157 apr_hash_t *blocks; 158 apr_hash_t *sockets; 159 apr_socket_t *listener; 160 socket_t *socket; 161 apr_port_t listener_port; 162 char *listener_addr; 163 logger_t *logger; 164 }; 165 166 struct global_s { 167 apr_pool_t *pool; 168 apr_pool_t *cleanup_pool; 169 apr_hash_t *config; 170 int flags; 171 const char *path; 172 const char *filename; 173 store_t *vars; 174 store_t *shared; 175 apr_hash_t *modules; 176 apr_hash_t *blocks; 177 apr_table_t *files; 178 apr_table_t *threads; 179 apr_table_t *clients; 180 apr_table_t *servers; 181 apr_table_t *daemons; 182 logger_t *logger; 183 int CLTs; 184 int SRVs; 185 int cur_threads; 186 int tot_threads; 187 int groups; 188 apr_thread_mutex_t *sync_mutex; 189 apr_thread_mutex_t *mutex; 190 int line_nr; 191 #define GLOBAL_STATE_NONE 0 192 #define GLOBAL_STATE_CLIENT 1 193 #define GLOBAL_STATE_SERVER 2 194 #define GLOBAL_STATE_BLOCK 3 195 #define GLOBAL_STATE_DAEMON 4 196 #define GLOBAL_STATE_FILE 5 197 int state; 198 #define GLOBAL_FILE_STATE_NORMAL 0 199 #define GLOBAL_FILE_STATE_MODULE 1 200 int file_state; 201 int socktmo; 202 worker_t *worker; 203 worker_t *cur_worker; 204 apr_threadattr_t *tattr; 205 int recursiv; 206 jmp_buf setjmpEnv; 207 }; 208 209 typedef struct line_s { 210 char *info; 211 char *buf; 212 apr_size_t len; 213 } line_t; 214 215 #ifndef min 216 #define min(a,b) ((a)<(b))?(a):(b) 217 #endif 218 #ifndef max 219 #define max(a,b) ((a)>(b))?(a):(b) 220 #endif 221 222 #ifndef DEFAULT_THREAD_STACKSIZE 223 #define DEFAULT_THREAD_STACKSIZE 262144 224 #endif 225 226 #define RSA_SERVER_CERT "server.cert.pem" 227 #define RSA_SERVER_KEY "server.key.pem" 228 229 #define LISTENBACKLOG_DEFAULT 511 230 231 #define COMMAND_NEED_ARG(err_text) \ 232 { \ 233 if (self && self->flags & COMMAND_FLAGS_DEPRECIATED) { \ 234 fprintf(stderr, "Command %s is depreciated", self->name); \ 235 fflush(stderr); \ 236 } \ 237 while (*data == ' ') { \ 238 ++data; \ 239 } \ 240 if(!*data) { \ 241 worker_log(worker, LOG_ERR, err_text); \ 242 return APR_EGENERAL; \ 243 } \ 244 copy = apr_pstrdup(ptmp, data); \ 245 copy = worker_replace_vars(worker, copy, NULL, ptmp); \ 246 if (self) { \ 247 worker_log(worker, LOG_CMD, "%s %s", self->name, copy); \ 248 } \ 249 else { \ 250 worker_log(worker, LOG_CMD, "%s", copy); \ 251 } \ 252 } 253 254 #define COMMAND_OPTIONAL_ARG \ 255 { \ 256 if (self && self->flags & COMMAND_FLAGS_DEPRECIATED) { \ 257 fprintf(stderr, "\n*** Command %s is depreciated ***", self->name); \ 258 fflush(stderr); \ 259 } \ 260 while (*data == ' ') { \ 261 ++data; \ 262 } \ 263 copy = apr_pstrdup(ptmp, data); \ 264 copy = worker_replace_vars(worker, copy, NULL, ptmp); \ 265 if (self) { \ 266 worker_log(worker, LOG_CMD, "%s %s", self->name, copy); \ 267 } \ 268 else { \ 269 worker_log(worker, LOG_CMD, "%s", copy); \ 270 } \ 271 } 272 273 #define COMMAND_NO_ARG \ 274 if (self && self->flags & COMMAND_FLAGS_DEPRECIATED) { \ 275 fprintf(stderr, "\n*** Command %s is depreciated ***", self->name); \ 276 fflush(stderr); \ 277 } \ 278 if (self) { \ 279 worker_log(worker, LOG_CMD, "%s", self->name); \ 280 } 281 282 /** register */ 283 # define HTT_DECLARE(type) type 284 285 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, line_get_length, 286 (worker_t *worker, line_t *line)) 287 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, line_flush, 288 (worker_t *worker, line_t *line)) 289 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, line_sent, 290 (worker_t *worker, line_t *line)) 291 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, client_port_args, 292 (worker_t *worker, char *portinfo, 293 char **new_portinfo, char *rest_of_line)) 294 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, server_port_args, 295 (worker_t *worker, char *portinfo, 296 char **new_portinfo, char *rest_of_line)) 297 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, pre_connect, 298 (worker_t *worker)) 299 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, connect, 300 (worker_t *worker)) 301 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, post_connect, 302 (worker_t *worker)) 303 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, accept, 304 (worker_t *worker, char *rest_of_line)) 305 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, pre_close, 306 (worker_t *worker)) 307 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, close, 308 (worker_t *worker, char *info, char **new_info)) 309 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, WAIT_begin, 310 (worker_t *worker)) 311 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, read_pre_headers, 312 (worker_t *worker)) 313 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, read_status_line, 314 (worker_t *worker, char *line)) 315 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, read_header, 316 (worker_t *worker, char *line)) 317 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, read_buf, 318 (worker_t *worker, char *buf, apr_size_t len)) 319 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, WAIT_end, 320 (worker_t *worker, apr_status_t status)) 321 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, worker_clone, 322 (worker_t *worker, worker_t *clone)) 323 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, read_line, 324 (global_t *global, char **line)) 325 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, block_start, 326 (global_t *global, char **line)) 327 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, block_end, 328 (global_t *global)) 329 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, client_create, 330 (worker_t *worker, apr_thread_start_t func, apr_thread_t **new_thread)) 331 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, server_create, 332 (worker_t *worker, apr_thread_start_t func, apr_thread_t **new_thread)) 333 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, worker_finally, 334 (worker_t *worker)) 335 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, thread_start, 336 (global_t *global, apr_thread_t *thread)) 337 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, thread_join, 338 (global_t *global, apr_thread_t *thread)) 339 APR_DECLARE_EXTERNAL_HOOK(htt, HTT, apr_status_t, worker_joined, 340 (global_t *global)) 341 342 apr_status_t transport_register(socket_t *socket, transport_t *transport); 343 apr_status_t transport_unregister(socket_t *socket, transport_t *transport); 344 transport_t *transport_get_current(socket_t *socket); 345 346 /** commands */ 347 apr_status_t command_CALL(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 348 apr_status_t command_REQ(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 349 apr_status_t command_RESWAIT(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 350 apr_status_t command_RES(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 351 apr_status_t command_WAIT(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 352 apr_status_t command_SLEEP(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 353 apr_status_t command_EXPECT(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 354 apr_status_t command_CLOSE(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 355 apr_status_t command_TIMEOUT(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 356 apr_status_t command_MATCH(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 357 apr_status_t command_GREP(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 358 apr_status_t command_ASSERT(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 359 apr_status_t command_SET(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 360 apr_status_t command_UNSET(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 361 apr_status_t command_DATA(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 362 apr_status_t command_BIN_DATA(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 363 apr_status_t command_FLUSH(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 364 apr_status_t command_CHUNK(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 365 apr_status_t command_EXEC(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 366 apr_status_t command_SENDFILE(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 367 apr_status_t command_PIPE(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 368 apr_status_t command_NOCRLF(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 369 apr_status_t command_SOCKSTATE(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 370 apr_status_t command_HEADER(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 371 apr_status_t command_RAND(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 372 apr_status_t command_DEBUG(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 373 apr_status_t command_PRINT(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 374 apr_status_t command_UP(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 375 apr_status_t command_DOWN(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 376 apr_status_t command_TIME(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 377 apr_status_t command_LOG_LEVEL_SET(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 378 apr_status_t command_LOG_LEVEL_GET(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 379 apr_status_t command_RECV(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 380 apr_status_t command_READLINE(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 381 apr_status_t command_CHECK(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 382 apr_status_t command_WHICH(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 383 apr_status_t command_ONLY_PRINTABLE(command_t *self, worker_t *worker, 384 char *data, apr_pool_t *ptmp); 385 apr_status_t command_SH(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 386 apr_status_t command_ADD_HEADER(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 387 apr_status_t command_DETACH(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 388 apr_status_t command_PID(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 389 apr_status_t command_URLENC(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 390 apr_status_t command_URLDEC(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 391 apr_status_t command_B64ENC(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 392 apr_status_t command_B64DEC(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 393 apr_status_t command_STRFTIME(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 394 apr_status_t command_TUNNEL(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 395 apr_status_t command_BREAK(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 396 apr_status_t command_PRINT_HEX(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 397 apr_status_t command_AUTO_CLOSE(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 398 apr_status_t command_AUTO_COOKIE(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 399 apr_status_t command_MATCH_SEQ(command_t * self, worker_t * worker, char *data, apr_pool_t *ptmp); 400 apr_status_t command_RECORD(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 401 apr_status_t command_PLAY(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 402 apr_status_t command_USE(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 403 apr_status_t command_LOCAL(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 404 apr_status_t command_LOCK(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 405 apr_status_t command_UNLOCK(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 406 apr_status_t command_IGNORE_BODY(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 407 apr_status_t command_VERSION(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 408 apr_status_t command_DUMMY(command_t *self, worker_t *worker, char *data, apr_pool_t *ptmp); 409 410 /** helper */ 411 void lock(apr_thread_mutex_t *mutex); 412 void unlock(apr_thread_mutex_t *mutex); 413 void worker_var_set_and_zero_terminate(worker_t * worker, const char *var, const char *val, apr_size_t len); 414 void worker_new(worker_t ** self, char *additional, 415 global_t *global, interpret_f interpret); 416 void worker_clone(worker_t ** self, worker_t * orig); 417 apr_status_t worker_handle_buf(worker_t *worker, apr_pool_t *pool, char *buf, 418 apr_size_t len); 419 420 void worker_log(worker_t * worker, int mode, char *fmt, ...); 421 void worker_log_buf(worker_t * worker, int mode, char dir, const char *buf, 422 apr_size_t len); 423 void worker_var_set(worker_t * worker, const char *var, const char *val); 424 const char * worker_var_get(worker_t * worker, const char *var); 425 void worker_test_reset(worker_t * worker); 426 apr_status_t worker_test_unused(worker_t * self); 427 apr_status_t worker_test_unused_errors(worker_t * self); 428 apr_status_t worker_expect(worker_t * self, apr_table_t * regexs, 429 const char *data, apr_size_t len); 430 apr_status_t worker_assert(worker_t * self, apr_status_t status); 431 apr_status_t worker_check_error(worker_t *self, apr_status_t status); 432 const char * worker_resolve_var(worker_t *worker, const char *name, 433 apr_pool_t *ptmp); 434 char * worker_replace_vars(worker_t * worker, char *line, int *unresolved, 435 apr_pool_t *ptmp); 436 apr_status_t worker_flush(worker_t * self, apr_pool_t *ptmp); 437 void worker_destroy(worker_t * self); 438 apr_status_t worker_match(worker_t * worker, apr_table_t * regexs, 439 const char *data, apr_size_t len); 440 void worker_conn_close_all(worker_t *self); 441 apr_status_t worker_listener_up(worker_t *worker, apr_int32_t backlog); 442 void worker_get_socket(worker_t *self, const char *hostname, 443 const char *portname); 444 apr_status_t worker_add_line(worker_t * self, const char *file_and_line, 445 char *line); 446 apr_status_t worker_socket_send(worker_t *self, char *buf, 447 apr_size_t len); 448 apr_status_t worker_to_file(worker_t * self); 449 const char *worker_get_value_from_param(worker_t *worker, const char *param, 450 apr_pool_t *ptmp); 451 void worker_finally_cleanup(worker_t *worker); 452 const char *worker_get_file_and_line(worker_t *worker); 453 apr_status_t worker_get_line_length(worker_t*, apr_table_entry_t, apr_size_t*); 454 apr_status_t worker_assert_match(worker_t*, apr_table_t*, char*, apr_status_t); 455 apr_status_t worker_assert_expect(worker_t*, apr_table_t*, char*, apr_status_t); 456 457 #endif 458