diff --git a/apps/app_queue.c b/apps/app_queue.c index e531dc4657d5a688ca39a7c877bb902e8830f3b9..3c3a2cff78d54b0687fef4430d81c82ac9bfc810 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -676,63 +676,31 @@ struct statechange { * Lock interface list find sc, iterate through each queues queue_member list for member to * update state inside queues */ -static void *handle_statechange(struct statechange *sc) +static int update_status(const char *interface, const int status) { - struct call_queue *q; struct member *cur; - struct ao2_iterator mem_iter; - struct member_interface *curint; - struct ao2_iterator queue_iter; - char *loc; - char *technology; - - technology = ast_strdupa(sc->dev); - loc = strchr(technology, '/'); - if (loc) { - *loc++ = '\0'; - } else { - return NULL; - } - - AST_LIST_LOCK(&interfaces); - AST_LIST_TRAVERSE(&interfaces, curint, list) { - char *interface; - char *slash_pos; - interface = ast_strdupa(curint->interface); - if ((slash_pos = strchr(interface, '/'))) - if ((slash_pos = strchr(slash_pos + 1, '/'))) - *slash_pos = '\0'; - - if (!strcasecmp(interface, sc->dev)) - break; - } - AST_LIST_UNLOCK(&interfaces); - - if (!curint) { - ast_debug(3, "Device '%s/%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", technology, loc, sc->state, devstate2str(sc->state)); - return NULL; - } + struct ao2_iterator mem_iter, queue_iter; + struct call_queue *q; - ast_debug(1, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state)); queue_iter = ao2_iterator_init(queues, 0); while ((q = ao2_iterator_next(&queue_iter))) { ao2_lock(q); mem_iter = ao2_iterator_init(q->members, 0); while ((cur = ao2_iterator_next(&mem_iter))) { - char *interface; + char *tmp_interface; char *slash_pos; - interface = ast_strdupa(cur->state_interface); + tmp_interface = ast_strdupa(cur->state_interface); if ((slash_pos = strchr(interface, '/'))) if ((slash_pos = strchr(slash_pos + 1, '/'))) *slash_pos = '\0'; - if (strcasecmp(sc->dev, interface)) { + if (strcasecmp(interface, tmp_interface)) { ao2_ref(cur, -1); continue; } - if (cur->status != sc->state) { - cur->status = sc->state; + if (cur->status != status) { + cur->status = status; if (q->maskmemberstatus) { ao2_ref(cur, -1); continue; @@ -757,6 +725,49 @@ static void *handle_statechange(struct statechange *sc) ao2_unlock(q); } + return 0; +} + +/*! \brief set a member's status based on device state of that member's interface*/ +static void *handle_statechange(struct statechange *sc) +{ + struct member_interface *curint; + char *loc; + char *technology; + + technology = ast_strdupa(sc->dev); + loc = strchr(technology, '/'); + if (loc) { + *loc++ = '\0'; + } else { + return NULL; + } + + AST_LIST_LOCK(&interfaces); + AST_LIST_TRAVERSE(&interfaces, curint, list) { + char *interface; + char *slash_pos; + interface = ast_strdupa(curint->interface); + if ((slash_pos = strchr(interface, '/'))) + if ((slash_pos = strchr(slash_pos + 1, '/'))) + *slash_pos = '\0'; + + if (!strcasecmp(interface, sc->dev)) + break; + } + AST_LIST_UNLOCK(&interfaces); + + if (!curint) { + if (option_debug > 2) + ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", technology, loc, sc->state, devstate2str(sc->state)); + return NULL; + } + + if (option_debug) + ast_log(LOG_DEBUG, "Device '%s/%s' changed to state '%d' (%s)\n", technology, loc, sc->state, devstate2str(sc->state)); + + update_status(sc->dev, sc->state); + return NULL; } @@ -1991,55 +2002,6 @@ static void hangupcalls(struct callattempt *outgoing, struct ast_channel *except } } -static int update_status(struct call_queue *q, struct member *member, int status) -{ - struct member *cur; - struct ao2_iterator mem_iter; - - /* Since a reload could have taken place, we have to traverse the list to - be sure it's still valid */ - ao2_lock(q); - mem_iter = ao2_iterator_init(q->members, 0); - while ((cur = ao2_iterator_next(&mem_iter))) { - if (member != cur) { - ao2_ref(cur, -1); - continue; - } - - cur->status = status; - if (!q->maskmemberstatus) { - manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus", - "Queue: %s\r\n" - "Location: %s\r\n" - "MemberName: %s\r\n" - "Membership: %s\r\n" - "Penalty: %d\r\n" - "CallsTaken: %d\r\n" - "LastCall: %d\r\n" - "Status: %d\r\n" - "Paused: %d\r\n", - q->name, cur->interface, cur->membername, cur->dynamic ? "dynamic" : cur->realtime ? "realtime": "static", - cur->penalty, cur->calls, (int)cur->lastcall, cur->status, cur->paused); - } - ao2_ref(cur, -1); - } - ao2_unlock(q); - return 0; -} - -static int update_dial_status(struct call_queue *q, struct member *member, int status) -{ - if (status == AST_CAUSE_BUSY) - status = AST_DEVICE_BUSY; - else if (status == AST_CAUSE_UNREGISTERED) - status = AST_DEVICE_UNAVAILABLE; - else if (status == AST_CAUSE_NOSUCHDRIVER) - status = AST_DEVICE_INVALID; - else - status = AST_DEVICE_UNKNOWN; - return update_status(q, member, status); -} - /*! * \brief traverse all defined queues which have calls waiting and contain this member * \retval 0 if no other queue has precedence (higher weight) @@ -2196,7 +2158,8 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies if (qe->chan->cdr) ast_cdr_busy(qe->chan->cdr); tmp->stillgoing = 0; - update_dial_status(qe->parent, tmp->member, status); + + update_status(tmp->member->state_interface, ast_device_state(tmp->member->state_interface)); ao2_lock(qe->parent); qe->parent->rrpos++; @@ -2206,8 +2169,7 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies (*busies)++; return 0; - } else if (status != tmp->oldstatus) - update_dial_status(qe->parent, tmp->member, status); + } tmp->chan->appl = "AppQueue"; tmp->chan->data = "(Outgoing Line)"; @@ -2576,8 +2538,6 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name); /* Setup parameters */ o->chan = ast_request(tech, in->nativeformats, stuff, &status); - if (status != o->oldstatus) - update_dial_status(qe->parent, o->member, status); if (!o->chan) { ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff); o->stillgoing = 0; @@ -3290,8 +3250,8 @@ static int try_calling(struct queue_ent *qe, const char *options, char *announce to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1; orig = to; ++qe->pending; - ring_one(qe, outgoing, &numbusies); ao2_unlock(qe->parent); + ring_one(qe, outgoing, &numbusies); if (use_weight) ao2_unlock(queues); lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies, ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT), forwardsallowed);