/* * private.h * * Copyright (C) 2003 - 2006 Bojan Smojver, Rexursive * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public Licence as published by the Free * Software Foundation; either version 2 of the Licence, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licence for * more details. * * You should have received a copy of the GNU General Public Licence along * with this program; if not, write to the Free Software Foundation, Inc., 59 * Temple Place, Suite 330, Boston, MA 02111-1307 USA * * In addition, as two special exceptions, Bojan Smojver, Rexursive, gives * permission to: * * 1. Link, both statically and dynamically, the code of this program with * Apache HTTP Server, Apache Portable Runtime and Apache Portable Runtime * Utility Library from Apache Software Foundation (or with modified versions * of the above, that use the same licence - Apache Software Licence 1.1, 2.0 * or any later version), and distribute linked combinations including the * program and the above software from Apache Software Foundation. You must * obey the GNU General Public Licence in all respects for all of the code * used other than Apache HTTP Server, Apache Portable Runtime and Apache * Portable Runtime Utility Library. * * 2. Dynamically link any shared library with this program at run-time, * through the interface of SpinApplication or LoadModule run-time * configuration directives of Apache HTTP Server, as provided by this program * or Apache HTTP Server itself, regardless of licensing terms of those shared * libraries. You must obey the GNU General Public Licence in all respects for * all of the code used other than that of those shared libraries. * * If you modify this file, you may extend these exceptions to your version of * the file, but you are not obligated to do so. If you do not wish to do so, * delete one or both of these exception statements from your version. * */ #ifndef __RXV_SPIN_PRIVATE__ #define __RXV_SPIN_PRIVATE__ #include #include /* * Type definitions */ typedef struct rxv_spin_txt rxv_spin_txt_t; typedef struct rxv_spin_ref rxv_spin_ref_t; typedef struct rxv_spin_for rxv_spin_for_t; typedef struct rxv_spin_if rxv_spin_if_t; typedef struct rxv_spin_node rxv_spin_node_t; typedef struct rxv_spin_cache rxv_spin_cache_t; typedef struct rxv_spin_extra rxv_spin_extra_t; typedef struct rxv_spin_config rxv_spin_config_t; typedef struct rxv_spin_conncf rxv_spin_conncf_t; typedef struct rxv_spin_reqcf rxv_spin_reqcf_t; typedef struct rxv_spin_private rxv_spin_private_t; typedef struct rxv_spin_db_stmt rxv_spin_db_stmt_t; typedef struct rxv_spin_cpool rxv_spin_cpool_t; /* * Generic true and false */ typedef enum{ RXV_SPIN_FALSE, RXV_SPIN_TRUE } rxv_spin_bool_e; /* * Data and context structures */ struct rxv_spin_ctx{ apr_pool_t *pool; /* context specific pool */ apr_pool_t *ppool; /* process specific pool */ rxv_spin_data_t *data; /* application prepared data */ request_rec *r; /* raw Apache request */ apreq_handle_t *req; /* parsed request */ rxv_spin_cpool_t *cpool; /* connection pool */ rxv_spin_private_t *priv; /* thread private data */ char *cfgfn; /* configuration file filename */ char *cinfo; /* store connection string */ char *sttbl; /* store table name */ rxv_spin_db_t *store; /* store connection */ apr_status_t (*close)(rxv_spin_ctx_t *ctx); /* store close function */ char *sesid; /* session id */ rxv_spin_bool_e valid:1; /* session is valid */ rxv_spin_bool_e sdirty:1; /* session store dirty */ rxv_spin_bool_e adirty:1; /* application store dirty */ apr_hash_t *app; /* application store */ apr_hash_t *ses; /* session store */ apr_time_t atime; /* time session was last accessed */ apr_time_t ptime; /* time configuration was last parsed */ apr_time_t tmout; /* session timeout in microseconds */ const char *sstore; /* select timestamp and data from store */ const char *ustore; /* update timestamp and data in store */ const char *istore; /* insert timestamp and data into store */ const char *ustamp; /* update timestamp in store */ void *extra; /* extra data placed in context by API user */ }; /* * Database structures */ struct rxv_spin_db{ APR_RING_ENTRY(rxv_spin_db) link; /* LRU: ring link */ apr_pool_t *pool; /* connection specific pool */ apr_pool_t *spool; /* select (temporary) pool */ char *cinfo; /* identification: type:connect string */ const apr_dbd_driver_t *driver; /* APR Util database driver */ apr_dbd_t *handle; /* APR Util database handle */ rxv_spin_cpool_t *cpool; /* the pool of connections */ apr_status_t (*cleanup)(void *data); /* cleanup function */ apr_hash_t *stmts; /* prepared statements */ }; struct rxv_spin_db_txn{ apr_pool_t *pool; /* transaction specific pool */ rxv_spin_db_t *db; /* database assiciated with this transaction */ apr_dbd_transaction_t *txn; /* APR Util transaction */ }; struct rxv_spin_cpool{ apr_pool_t *pool; apr_hash_t *conns; /* hash table of connections */ unsigned count; /* connections in the pool */ APR_RING_HEAD(rxv_spin_db_list,rxv_spin_db) list; /* LRU: conns list */ }; /* * Statement/node types */ typedef enum{ RXV_SPIN_UDF, RXV_SPIN_TXT, RXV_SPIN_REF, RXV_SPIN_FOR, RXV_SPIN_IF, RXV_SPIN_REG, RXV_SPIN_LIT, RXV_SPIN_NUM } rxv_spin_node_e; /* * Reference types */ typedef enum{ RXV_SPIN_REF_REG, RXV_SPIN_REF_SIZ, RXV_SPIN_REF_IND } rxv_spin_ref_e; /* * Conditional types: #if (guaranteed to be 0) and #unless (guaranteed to be 1) */ typedef enum{ RXV_SPIN_IF_IF, RXV_SPIN_IF_UNLESS } rxv_spin_if_e; /* * Comparison operators */ typedef enum{ RXV_SPIN_OP_NONE, RXV_SPIN_OP_MATCH, RXV_SPIN_OP_EQ_LIT, RXV_SPIN_OP_EQ_NUM, RXV_SPIN_OP_EQ_REF, RXV_SPIN_OP_MODULO } rxv_spin_op_e; /* * Useful constants */ #define RXV_SPIN_MIN_SENDFILE 256 /* never do sendfile up to this size */ #define RXV_SPIN_BUF_STEP 0x4000 /* scan buffer increment */ /* * Maximum nesting depth of the #if/#unless and #for */ #define RXV_SPIN_MAX_DEPTH 32 /* * Data structures for Abstract Syntax Tree */ struct rxv_spin_txt{ apr_off_t offset; /* from the beginning of the file */ apr_size_t length; char *cache; /* cached file chunk, if enabled */ }; struct rxv_spin_ref{ char *name; /* full name of the reference */ char *chunk; /* last chunk of the full name */ rxv_spin_data_t *data; /* data currently associated with this reference */ rxv_spin_for_t *loop; /* points to its for loop, if any */ rxv_spin_bool_e looked:1; /* did we look for the data before */ rxv_spin_ref_e type:2; /* type of reference: regular, size or index */ }; struct rxv_spin_for{ rxv_spin_ref_t *ref; /* what to loop around */ rxv_spin_node_t *stmt; /* what to replicate each time */ size_t index; /* the index of the loop */ }; struct rxv_spin_if{ rxv_spin_if_e type:1; /* is this actually the unless, not if */ rxv_spin_op_e oper:3; /* what operator is used */ rxv_spin_ref_t *ref; /* the reference we're checking, on the left */ union{ ap_regex_t *reg; /* regular expression to match */ rxv_spin_ref_t *rfr; /* the reference to match, on the right */ char *lit; /* literal string */ struct{ unsigned long num; /* number to the right of the operator */ unsigned long res; /* result of the modulo comparison, right of == */ }; }; rxv_spin_node_t *pos; /* statement if ref is not null */ rxv_spin_node_t *neg; /* statement if ref is null */ }; struct rxv_spin_node{ rxv_spin_node_e type:3; union{ rxv_spin_txt_t *txt; rxv_spin_ref_t *ref; rxv_spin_if_t *cond; rxv_spin_for_t *loop; ap_regex_t *reg; char *lit; unsigned long num; }; rxv_spin_node_t *next; }; /* * Parsed template (AST) cache structure */ struct rxv_spin_cache{ APR_RING_ENTRY(rxv_spin_cache) link; /* LRU: ring link */ apr_pool_t *pool; /* template specific pool */ char *file; /* filename of this template */ rxv_spin_node_t *root; /* root node of the AST */ apr_ino_t inode; /* inode of the file */ apr_time_t mtime; /* last template mod time */ apr_off_t size; /* last template size */ rxv_spin_bool_e sendfile:1; /* are we using sendfile */ rxv_spin_bool_e cacheall:1; /* should we cache all text */ rxv_spin_bool_e kill:1; /* template pool needs killing */ }; /* * Data structures for the scanner */ struct rxv_spin_extra{ apr_pool_t *pool; /* regular pool for all memory allocations */ apr_pool_t *tpool; /* template pool, from the cached entry */ apr_off_t offset; /* begining of TXT */ apr_size_t length; /* length of TXT */ apr_off_t row; /* current row of the template */ apr_off_t col; /* current column of the template */ rxv_spin_bool_e istxt:1; /* are we inside text */ rxv_spin_bool_e iseof:1; /* did we bump into the end of file */ rxv_spin_bool_e cacheall:1; /* do we cache all text */ rxv_spin_bool_e sendfile:1; /* should we enable sendfile */ rxv_spin_bool_e tcache:1; /* should cache templates between requests */ char *buf; /* buffer to hold cached text */ size_t bsize; /* size of the whole buffer */ rxv_spin_node_t *root; /* root of the abstract syntax tree */ rxv_spin_node_t **tail; /* tails of node lists on the stack */ rxv_spin_for_t **loop; /* nesting loops */ unsigned char *nest; /* nesting type stack, #if or #for */ size_t *boff; /* branch offset, RXV_SPIN_MAX_DEPTH for #else */ int depth; /* current nesting depth */ int ldepth; /* current loop nesting depth */ char *error; apr_bucket_brigade *brigade; /* where the result goes */ rxv_spin_ctx_t *ctx; /* the context - data, parameters etc. */ apr_file_t *fp; /* template file being processed */ apr_hash_t *cache; /* template cache */ apr_hash_t *used; /* used cache items that require cleaning */ rxv_spin_cache_t *ready; /* parsed, cached template */ }; /* Function declarations */ apr_status_t rxv_spin_file(const char *file,rxv_spin_extra_t *extra, apr_pool_t *pool,apr_finfo_t *finfo); rxv_spin_extra_t *rxv_spin_extra_create(apr_pool_t *pool, apr_bucket_alloc_t *balloc, rxv_spin_ctx_t *ctx); rxv_spin_ctx_t *rxv_spin_context_create(apr_pool_t *pool); rxv_spin_private_t *rxv_spin_private_create(apr_pool_t *pool); /* Missing parser and scanner stuff */ #define YYSTYPE rxv_spin_node_t* #define YY_EXTRA_TYPE rxv_spin_extra_t* int rxv_spin_parse(void *YYPARSE_PARAM); void rxv_spin_error(char *s); int rxv_spin_lex(rxv_spin_node_t **yyval_param,void *yyscanner); /* * Module configuration */ typedef enum{ RXV_SPIN_APPLICATION_SET=0x001, RXV_SPIN_APPENTRY_SET =0x002, RXV_SPIN_APPFIXUP_SET =0x004, RXV_SPIN_CFGFN_SET =0x008, RXV_SPIN_STORE_SET =0x010, RXV_SPIN_STORETBL_SET =0x020, RXV_SPIN_COOKIE_SET =0x040, RXV_SPIN_TIMEOUT_SET =0x080, RXV_SPIN_SENDFILE_SET =0x100, RXV_SPIN_CACHE_SET =0x200, RXV_SPIN_CACHEALL_SET =0x400, RXV_SPIN_CONNPOOL_SET =0x800 } rxv_spin_cfg_e; struct rxv_spin_config{ char *application; /* path to the application shared library */ char *appentry; /* application entry function name */ char *appfixup; /* application fixup function name */ char *cfgfn; /* configuration file filename */ char *store; /* store connect string */ char *storetbl; /* store table name */ char *cookie; /* name of the cookie used for session tracking */ apr_time_t timeout; /* session timeout */ rxv_spin_bool_e sendfile:1; /* sendfile flag */ rxv_spin_bool_e tcache:1; /* cache templates between requests */ rxv_spin_bool_e cacheall:1; /* cache whole files (i.e. all content) */ rxv_spin_bool_e connpool:1; /* enable connection pooling */ rxv_spin_cfg_e set:12; /* what options were actually set */ }; /* * Connection configuration */ struct rxv_spin_conncf{ rxv_spin_private_t *priv; /* thread private data */ apr_hash_t *used; /* used templates for this connection */ }; /* * Request configuration */ struct rxv_spin_reqcf{ char *sesid; /* session id */ rxv_spin_ctx_t *ctx; /* context passed from fixup to handler */ apr_dso_handle_sym_t fix; /* fixup function handle */ apr_dso_handle_sym_t svc; /* service function handle */ rxv_spin_bool_e valid:1; /* session is valid: value 1, otherwise 0 */ }; /* * Private thread data */ struct rxv_spin_private{ apr_pool_t *pool; /* thread specific pool to avoid concurrency */ apr_hash_t *cache; /* parsed template (AST) cache */ APR_RING_HEAD(rxv_spin_cache_list,rxv_spin_cache) list; /* LRU: cache list */ rxv_spin_cpool_t *cpool; /* connection pool */ apr_hash_t *dso; /* cache of DSOs so we don't keep opening */ }; /* * Useful macros */ #define RXV_SPIN_UNS_DIGITS(t) ((sizeof(t)*5)/2+sizeof(t)%2) #endif