diff --git a/src/include/switch_apr.h b/src/include/switch_apr.h index 8e98893eda..75cc0a09c8 100644 --- a/src/include/switch_apr.h +++ b/src/include/switch_apr.h @@ -202,6 +202,8 @@ SWITCH_DECLARE(switch_memory_pool_t *) switch_hash_pool_get(switch_hash_t *ht); */ SWITCH_DECLARE(unsigned int) switch_hashfunc_default(const char *key, switch_ssize_t *klen); +SWITCH_DECLARE(unsigned int) switch_ci_hashfunc_default(const char *char_key, switch_ssize_t *klen); + /** * @defgroup switch_time Time Routines diff --git a/src/include/switch_event.h b/src/include/switch_event.h index a94440d319..07bfe1f93c 100644 --- a/src/include/switch_event.h +++ b/src/include/switch_event.h @@ -67,6 +67,8 @@ SWITCH_BEGIN_EXTERN_C char *name; /*! the header value */ char *value; + /*! hash of the header name */ + unsigned long hash; struct switch_event_header *next; }; diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 64841ec5c8..32a553faa1 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -295,6 +295,40 @@ static inline char *switch_safe_strdup(const char *it) } +static inline char *switch_lc_strdup(const char *it) +{ + char *dup; + char *p; + + if (it) { + dup = strdup(it); + for(p = dup; p && *p; p++) { + *p = tolower(*p); + } + return dup; + } + + return NULL; +} + + +static inline char *switch_uc_strdup(const char *it) +{ + char *dup; + char *p; + + if (it) { + dup = strdup(it); + for(p = dup; p && *p; p++) { + *p = toupper(*p); + } + return dup; + } + + return NULL; +} + + /*! \brief Test if one string is inside another with extra case checking \param s the inner string diff --git a/src/switch_apr.c b/src/switch_apr.c index d46b8608d0..f2c644779d 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -74,6 +74,30 @@ SWITCH_DECLARE(void) switch_pool_clear(switch_memory_pool_t *p) apr_pool_clear(p); } +SWITCH_DECLARE(unsigned int) switch_ci_hashfunc_default(const char *char_key, switch_ssize_t *klen) + +{ + unsigned int hash = 0; + const unsigned char *key = (const unsigned char *)char_key; + const unsigned char *p; + apr_ssize_t i; + + if (*klen == APR_HASH_KEY_STRING) { + for (p = key; *p; p++) { + hash = hash * 33 + tolower(*p); + } + *klen = p - key; + } + else { + for (p = key, i = *klen; i; i--, p++) { + hash = hash * 33 + tolower(*p); + } + } + + return hash; +} + + SWITCH_DECLARE(unsigned int) switch_hashfunc_default(const char *key, switch_ssize_t *klen) { return apr_hashfunc_default(key, klen); diff --git a/src/switch_event.c b/src/switch_event.c index c8b57e0741..31e7d2e5a3 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -586,12 +586,17 @@ SWITCH_DECLARE(switch_status_t) switch_event_set_priority(switch_event_t *event, SWITCH_DECLARE(char *) switch_event_get_header(switch_event_t *event, const char *header_name) { switch_event_header_t *hp; - switch_assert(event); - if (!header_name) - return NULL; + switch_ssize_t hlen = -1; + unsigned long hash = 0; + switch_assert(event); + + if (!header_name) return NULL; + + hash = switch_ci_hashfunc_default(header_name, &hlen); + for (hp = event->headers; hp; hp = hp->next) { - if (!strcasecmp(hp->name, header_name)) { + if ((!hp->hash || hash == hp->hash) && !strcasecmp(hp->name, header_name) ) { return hp->value; } } @@ -608,6 +613,9 @@ SWITCH_DECLARE(switch_status_t) switch_event_del_header(switch_event_t *event, c switch_event_header_t *hp, *lp = NULL, *tp; switch_status_t status = SWITCH_STATUS_FALSE; int x = 0; + switch_ssize_t hlen = -1; + unsigned long hash = 0; + tp = event->headers; while (tp) { hp = tp; @@ -615,7 +623,9 @@ SWITCH_DECLARE(switch_status_t) switch_event_del_header(switch_event_t *event, c x++; switch_assert(x < 1000); - if (!strcasecmp(header_name, hp->name)) { + hash = switch_ci_hashfunc_default(header_name, &hlen); + + if ((!hp->hash || hash == hp->hash) && !strcasecmp(header_name, hp->name)) { if (lp) { lp->next = hp->next; } else { @@ -642,6 +652,7 @@ SWITCH_DECLARE(switch_status_t) switch_event_del_header(switch_event_t *event, c switch_status_t switch_event_base_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, char *data) { switch_event_header_t *header; + switch_ssize_t hlen = -1; void *pop; if (switch_queue_trypop(EVENT_HEADER_RECYCLE_QUEUE, &pop) == SWITCH_STATUS_SUCCESS) { @@ -655,7 +666,8 @@ switch_status_t switch_event_base_add_header(switch_event_t *event, switch_stack header->name = DUP(header_name); header->value = data; - + header->hash = switch_ci_hashfunc_default(header->name, &hlen); + if (stack == SWITCH_STACK_TOP) { header->next = event->headers; event->headers = header;