Merge branch 'release/1.1.0' Conflicts: evhtp.c
diff --git a/ChangeLog b/ChangeLog index 70a991a..79fd9f2 100644 --- a/ChangeLog +++ b/ChangeLog
@@ -1,3 +1,8 @@ +v1.1.0 + o Add ability for rules to be ordered. (ad8c468 Mark Ellzey) + o Cleanup the old rule code. (fbfda73 Mark Ellzey) + o Fixed missing variable in callback_find (4eb5e87 Mark Ellzey) + v1.0.1 o Fixes to make coverity happy. (6776d85 Mark Ellzey) o Add support for empty header values. (7ec160f Mark Ellzey)
diff --git a/evhtp.c b/evhtp.c index 0704e31..66a149c 100644 --- a/evhtp.c +++ b/evhtp.c
@@ -494,41 +494,6 @@ } /** - * @brief attempts to find a callback via hashing the path - * - * @param callbacks a evhtp_callbacks_t * structure - * @param path a null terminated string to be hashed and searched - * - * @return evhtp_callback_t * if found, NULL if not found. - */ -static evhtp_callback_t * -_evhtp_callback_hash_find(evhtp_callbacks_t * callbacks, const char * path) { - evhtp_callback_t * callback; - unsigned int hash; - unsigned int shash; - - if (path == NULL) { - return NULL; - } - - hash = _evhtp_quick_hash(path); - shash = (hash & (callbacks->buckets - 1)); - callback = callbacks->callbacks[shash]; - - while (callback != NULL) { - if (callback->hash == hash && - callback->type == evhtp_callback_type_hash && - strcmp(callback->val.path, path) == 0) { - return callback; - } - - callback = callback->next; - } - - return NULL; -} - -/** * @brief glob/wildcard type pattern matching. * * Note: This code was derived from redis's (v2.6) stringmatchlen() function. @@ -599,126 +564,53 @@ return 0; } /* _evhtp_glob_match */ -/** - * @brief iterate through a list of glob/wildcard defined callbacks. - * - * @param callbacks - * @param path - * - * @return - */ static evhtp_callback_t * -_evhtp_callback_glob_find(evhtp_callbacks_t * callbacks, const char * path) { - evhtp_callback_t * callback; - - if (!callbacks || !path) { - return NULL; - } - - callback = callbacks->glob_callbacks; - - while (callback != NULL) { - if (callback->type == evhtp_callback_type_glob) { - if (_evhtp_glob_match(callback->val.glob, path) == 1) { - return callback; - } - } - - callback = callback->next; - } - - return NULL; -} - -/** - * @brief iterate through a tailq of callback hooks defined as a regex until a - * match is found. - * - * @param callbacks a evhtp_callbacks_t structure - * @param path a string containing a path to be matched against - * @param soff a pointer to an integer which will be filled with the start - * offset in the string if matched. - * @param eoff a pointer to an integer which will be filled with the end - * offset in the string if matched - * - * @return an evhtp_callback_t function on success, otherwise NULL - */ -#ifndef EVHTP_DISABLE_REGEX -static evhtp_callback_t * -_evhtp_callback_regex_find(evhtp_callbacks_t * callbacks, const char * path, - unsigned int * soff, unsigned int * eoff) { - evhtp_callback_t * callback = callbacks->regex_callbacks; - - if (path == NULL) { - return NULL; - } - - while (callback != NULL) { - regmatch_t pmatch[28]; - - if (callback->type == evhtp_callback_type_regex) { - if (regexec(callback->val.regex, path, callback->val.regex->re_nsub + 1, pmatch, 0) == 0) { - *soff = (unsigned int)pmatch[callback->val.regex->re_nsub].rm_so; - *eoff = (unsigned int)pmatch[callback->val.regex->re_nsub].rm_eo; - - return callback; - } - } - - callback = callback->next; - } - - return NULL; -} - -#endif - -/** - * @brief A wrapper around hash, glob, and regex hook lookups - * Search is done in this order: - * hash - * glob - * regex - * - * @param callbacks - * @param path - * @param start_offset - * @param end_offset - * - * @return evhtp_callback_t on success, otherwise NULL - */ -static evhtp_callback_t * -_evhtp_callback_find(evhtp_callbacks_t * callbacks, +_evhtp_callback_find(evhtp_callbacks_t * cbs, const char * path, unsigned int * start_offset, unsigned int * end_offset) { +#ifndef EVHTP_DISABLE_REGEX + regmatch_t pmatch[28]; +#endif evhtp_callback_t * callback; - if (callbacks == NULL) { + if (cbs == NULL) { return NULL; } - if ((callback = _evhtp_callback_hash_find(callbacks, path)) != NULL) { - *start_offset = 0; - *end_offset = (unsigned int)strlen(path); - return callback; - } - - if ((callback = _evhtp_callback_glob_find(callbacks, path)) != NULL) { - *start_offset = 0; - *end_offset = (unsigned int)strlen(path); - return callback; - } - + TAILQ_FOREACH(callback, cbs, next) { + switch (callback->type) { + case evhtp_callback_type_hash: + if (strcmp(callback->val.path, path) == 0) { + *start_offset = 0; + *end_offset = (unsigned int)strlen(path); + return callback; + } + break; #ifndef EVHTP_DISABLE_REGEX - if ((callback = _evhtp_callback_regex_find(callbacks, path, - start_offset, end_offset)) != NULL) { - return callback; - } + case evhtp_callback_type_regex: + if (regexec(callback->val.regex, path, callback->val.regex->re_nsub + 1, pmatch, 0) == 0) { + *start_offset = pmatch[callback->val.regex->re_nsub].rm_so; + *end_offset = pmatch[callback->val.regex->re_nsub].rm_eo; + + return callback; + } + + break; #endif + case evhtp_callback_type_glob: + if (_evhtp_glob_match(callback->val.glob, path) == 1) { + *start_offset = 0; + *end_offset = (unsigned int)strlen(path); + return callback; + } + default: + break; + } /* switch */ + } return NULL; -} +} /* _evhtp_callback_find */ /** * @brief Creates a new evhtp_request_t @@ -2632,63 +2524,9 @@ evconnlistener_free(htp->server); } -evhtp_callbacks_t * -evhtp_callbacks_new(unsigned int buckets) { - evhtp_callbacks_t * cbs; - - if (!(cbs = calloc(sizeof(evhtp_callbacks_t), 1))) { - return NULL; - } - - if (!(cbs->callbacks = calloc(sizeof(evhtp_callback_t *), buckets))) { - free(cbs); - return NULL; - } - - cbs->buckets = buckets; - cbs->count = 0; - - return cbs; -} - void evhtp_callbacks_free(evhtp_callbacks_t * callbacks) { - evhtp_callback_t * callback; - evhtp_callback_t * next; - unsigned int idx; - - if (callbacks == NULL) { - return; - } - - if (callbacks->callbacks) { - for (idx = 0; idx < callbacks->buckets; idx++) { - if (callbacks->callbacks[idx] == NULL) { - continue; - } - - callback = callbacks->callbacks[idx]; - - while (callback != NULL) { - next = callback->next; - evhtp_callback_free(callback); - callback = next; - } - } - free(callbacks->callbacks); - } - -#ifndef EVHTP_DISABLE_REGEX - callback = callbacks->regex_callbacks; - - while (callback != NULL) { - next = callback->next; - evhtp_callback_free(callback); - callback = next; - } -#endif - - free(callbacks); + /* XXX TODO */ } evhtp_callback_t * @@ -2757,32 +2595,7 @@ int evhtp_callbacks_add_callback(evhtp_callbacks_t * cbs, evhtp_callback_t * cb) { - unsigned int hkey; - - switch (cb->type) { - case evhtp_callback_type_hash: - hkey = cb->hash & (cbs->buckets - 1); - - if (cbs->callbacks[hkey] == NULL) { - cbs->callbacks[hkey] = cb; - } else { - cb->next = cbs->callbacks[hkey]; - cbs->callbacks[hkey] = cb; - } - break; -#ifndef EVHTP_DISABLE_REGEX - case evhtp_callback_type_regex: - cb->next = cbs->regex_callbacks; - cbs->regex_callbacks = cb; - break; -#endif - case evhtp_callback_type_glob: - cb->next = cbs->glob_callbacks; - cbs->glob_callbacks = cb; - break; - default: - return -1; - } /* switch */ + TAILQ_INSERT_TAIL(cbs, cb, next); return 0; } @@ -2918,10 +2731,12 @@ _evhtp_lock(htp); if (htp->callbacks == NULL) { - if (!(htp->callbacks = evhtp_callbacks_new(1024))) { + if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), sizeof(char)))) { _evhtp_unlock(htp); return NULL; } + + TAILQ_INIT(htp->callbacks); } if (!(hcb = evhtp_callback_new(path, evhtp_callback_type_hash, cb, arg))) { @@ -2992,10 +2807,12 @@ _evhtp_lock(htp); if (htp->callbacks == NULL) { - if (!(htp->callbacks = evhtp_callbacks_new(1024))) { + if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), sizeof(char)))) { _evhtp_unlock(htp); return NULL; } + + TAILQ_INIT(htp->callbacks); } if (!(hcb = evhtp_callback_new(pattern, evhtp_callback_type_regex, cb, arg))) { @@ -3022,10 +2839,12 @@ _evhtp_lock(htp); if (htp->callbacks == NULL) { - if (!(htp->callbacks = evhtp_callbacks_new(1024))) { + if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), sizeof(char)))) { _evhtp_unlock(htp); return NULL; } + + TAILQ_INIT(htp->callbacks); } if (!(hcb = evhtp_callback_new(pattern, evhtp_callback_type_glob, cb, arg))) {
diff --git a/evhtp.h b/evhtp.h index f242ca4..e826a4a 100644 --- a/evhtp.h +++ b/evhtp.h
@@ -155,10 +155,10 @@ typedef evhtp_ssl_sess_t * (*evhtp_ssl_scache_get)(evhtp_connection_t * connection, unsigned char * sid, int sid_len); typedef void * (*evhtp_ssl_scache_init)(evhtp_t *); -#define EVHTP_VERSION "1.0.1" +#define EVHTP_VERSION "1.1.0" #define EVHTP_VERSION_MAJOR 1 -#define EVHTP_VERSION_MINOR 0 -#define EVHTP_VERSION_PATCH 1 +#define EVHTP_VERSION_MINOR 1 +#define EVHTP_VERSION_PATCH 0 #define evhtp_headers_iterator evhtp_kvs_iterator @@ -276,23 +276,6 @@ }; /** - * @brief structure containing all registered evhtp_callbacks_t - * - * This structure holds information which correlates either - * a path string (via a hash) or a regular expression callback. - * - */ -struct evhtp_callbacks_s { - evhtp_callback_t ** callbacks; /**< hash of path callbacks */ -#ifndef EVHTP_DISABLE_REGEX - evhtp_callback_t * regex_callbacks; /**< list of regex callbacks */ -#endif - evhtp_callback_t * glob_callbacks; /**< list of wildcard callbacks */ - unsigned int count; /**< number of callbacks defined */ - unsigned int buckets; /**< buckets allocated for hash */ -}; - -/** * @brief structure containing a single callback and configuration * * The definition structure which is used within the evhtp_callbacks_t @@ -321,9 +304,10 @@ #endif } val; - evhtp_callback_t * next; + TAILQ_ENTRY(evhtp_callback_s) next; }; +TAILQ_HEAD(evhtp_callbacks_s, evhtp_callback_s); /** * @brief a generic key/value structure @@ -711,22 +695,6 @@ */ void evhtp_send_reply_chunk_end(evhtp_request_t * request); - -/** - * @brief creates a new evhtp_callbacks_t structure - * - * this structure is used to store all known - * callbacks for a request. - * - * @param buckets the number of buckets to allocate for the - * path type hash. - * - * @return an evhtp_callbacks_t structure - */ -evhtp_callbacks_t * evhtp_callbacks_new(unsigned int buckets); -void evhtp_callbacks_free(evhtp_callbacks_t * callbacks); - - /** * @brief creates a new evhtp_callback_t structure. *