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