diff --git a/UPGRADE.txt b/UPGRADE.txt index 82eeff453a4d12b61c4b0df525e39dccef3bb7ec..209ebd50d86776e520688d50a98ae8415f1d6431 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -291,6 +291,13 @@ Queues: new value has been added to the TRANSFER event that indicates the caller's original position in the queue they are being transfered from. +* Prior to Asterisk 1.6.2, queue names were treated in a case-sensitive + manner, meaning that queues with names like "sales" and "sALeS" would + be seen as unique queues. The parsing logic has changed to use case- + insensitive comparisons now when originally hashing based on queue + names, meaning that now the two queues mentioned as examples earlier + will be seen as having the same name. + iLBC Codec: * Previously, the Asterisk source code distribution included the iLBC diff --git a/apps/app_queue.c b/apps/app_queue.c index b3081028d9cb1d68bd8c876726d1a8adb04a5119..07829042b62941497aeabb3f5278fc31cd53dcfe 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -67,6 +67,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include <sys/time.h> #include <sys/signal.h> #include <netinet/in.h> +#include <ctype.h> #include "asterisk/lock.h" #include "asterisk/file.h" @@ -850,7 +851,8 @@ static int strat2int(const char *strategy) static int queue_hash_cb(const void *obj, const int flags) { const struct call_queue *q = obj; - return ast_str_hash(q->name); + + return ast_str_case_hash(q->name); } static int queue_cmp_cb(void *obj, void *arg, void *data, int flags) @@ -1671,7 +1673,6 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as /* Delete if unused (else will be deleted when last caller leaves). */ ao2_unlink(queues, q); ao2_unlock(q); - queue_unref(q); } return NULL; } @@ -2192,8 +2193,6 @@ static void leave_queue(struct queue_ent *qe) if (q->dead) { /* It's dead and nobody is in it, so kill it */ ao2_unlink(queues, q); - /* unref the container's reference to the queue */ - queue_unref(q); } /* unref the explicit ref earlier in the function */ queue_unref(q); @@ -2248,11 +2247,10 @@ static int compare_weight(struct call_queue *rq, struct member *member) } } ao2_unlock(q); + queue_unref(q); if (found) { - queue_unref(q); break; } - queue_unref(q); } return found; } @@ -4186,6 +4184,8 @@ static int remove_from_queue(const char *queuename, const char *interface) if (!mem->dynamic) { ao2_ref(mem, -1); ao2_unlock(q); + queue_unref(q); + ao2_unlock(queues); return RES_NOT_DYNAMIC; } q->membercount--; @@ -5691,13 +5691,15 @@ static char *__queues_show(struct mansession *s, int fd, int argc, char **argv) } } - queue_iter = ao2_iterator_init(queues, 0); + queue_iter = ao2_iterator_init(queues, F_AO2I_DONTLOCK); + ao2_lock(queues); while ((q = ao2_iterator_next(&queue_iter))) { float sl; ao2_lock(q); if (argc == 3 && strcasecmp(q->name, argv[2])) { ao2_unlock(q); + queue_unref(q); continue; } found = 1; @@ -5768,6 +5770,7 @@ static char *__queues_show(struct mansession *s, int fd, int argc, char **argv) } queue_unref(q); /* Unref the iterator's reference */ } + ao2_unlock(queues); if (!found) { if (argc == 3) ast_str_set(&out, 0, "No such queue: %s.", argv[2]); diff --git a/include/asterisk/strings.h b/include/asterisk/strings.h index 5ad362e5697dbc8982e0ffe6541b88c438ad6529..142fc7c627aab4012d06ee7c9eff684bae480bca 100644 --- a/include/asterisk/strings.h +++ b/include/asterisk/strings.h @@ -23,6 +23,8 @@ #ifndef _ASTERISK_STRINGS_H #define _ASTERISK_STRINGS_H +#include <ctype.h> + #include "asterisk/inline_api.h" #include "asterisk/utils.h" #include "asterisk/threadstorage.h" @@ -738,4 +740,21 @@ static force_inline int ast_str_hash(const char *str) return abs(hash); } +/*! + * \brief Compute a hash value on a case-insensitive string + * + * Uses the same hash algorithm as ast_str_hash, but converts + * all characters to lowercase prior to computing a hash. This + * allows for easy case-insensitive lookups in a hash table. + */ +static force_inline int ast_str_case_hash(const char *str) +{ + int hash = 5381; + + while (*str) { + hash = hash * 33 ^ tolower(*str++); + } + + return abs(hash); +} #endif /* _ASTERISK_STRINGS_H */