From 086a52d9d1cc00b28b3146376935b6c64b258cb0 Mon Sep 17 00:00:00 2001 From: Sean Bright <sean@malleable.com> Date: Tue, 4 Nov 2008 23:23:39 +0000 Subject: [PATCH] Introduce a new API call ast_channel_search_locked, which iterates through the channel list calling a caller-defined callback. The callback returns non-zero if a match is found. This should speed up some of the code that I committed earlier today in chan_sip (which is also updated by this commit). Reviewed by russellb and kpfleming via ReviewBoard: http://reviewboard.digium.com/r/28/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@154429 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 26 ++++++++++++++------------ include/asterisk/channel.h | 11 +++++++++++ main/channel.c | 18 ++++++++++++++++++ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 36a027ed38..4ebd970dc8 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -10037,19 +10037,21 @@ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int tim callee must be dialing the same extension that is being monitored. Simply dialing the hint'd device is not sufficient. */ if (global_notifycid) { - struct ast_channel *caller = NULL; - - while ((caller = ast_channel_walk_locked(caller))) { - if (caller->pbx && - (!strcasecmp(caller->macroexten, p->exten) || !strcasecmp(caller->exten, p->exten)) && - !strcasecmp(caller->context, p->context)) { - local_display = ast_strdupa(caller->cid.cid_name); - local_target = ast_strdupa(caller->cid.cid_num); - ast_channel_unlock(caller); - break; - } + auto int find_calling_channel(struct ast_channel *c); + int find_calling_channel(struct ast_channel *c) { + return (c->pbx && + (!strcasecmp(c->macroexten, p->exten) || !strcasecmp(c->exten, p->exten)) && + !strcasecmp(c->context, p->context)); + } + + struct ast_channel *caller = ast_channel_search_locked(find_calling_channel); + + if (caller) { + local_display = ast_strdupa(caller->cid.cid_name); + local_target = ast_strdupa(caller->cid.cid_num); ast_channel_unlock(caller); - } + caller = NULL; + } } /* We create a fake call-id which the phone will send back in an INVITE diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 549b6883ff..2f212cf653 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -1177,6 +1177,17 @@ struct ast_channel *ast_get_channel_by_exten_locked(const char *exten, const cha struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *chan, const char *exten, const char *context); +/*! \brief Search for a channel based on the passed channel matching callback + * Search for a channel based on the specified is_match callback, and return the + * first channel that we match. When returned, the channel will be locked. Note + * that the is_match callback is called with the passed channel locked, and should + * return 0 if there is no match, and non-zero if there is. + * \param is_match callback executed on each channel until non-zero is returned, or we + * run out of channels to search. + * \return Returns the matched channel, or NULL if no channel was matched. + */ +struct ast_channel *ast_channel_search_locked(int (*is_match)(struct ast_channel *)); + /*! ! \brief Waits for a digit * \param c channel to wait for a digit on * \param ms how many milliseconds to wait diff --git a/main/channel.c b/main/channel.c index 4174613ec4..34733af541 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1226,6 +1226,24 @@ struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *c return channel_find_locked(chan, NULL, 0, context, exten); } +/*! \brief Search for a channel based on the passed channel matching callback (first match) and return it, locked */ +struct ast_channel *ast_channel_search_locked(int (*is_match)(struct ast_channel *)) +{ + struct ast_channel *c = NULL; + + AST_RWLIST_RDLOCK(&channels); + AST_RWLIST_TRAVERSE(&channels, c, chan_list) { + ast_channel_lock(c); + if (is_match(c)) { + break; + } + ast_channel_unlock(c); + } + AST_RWLIST_UNLOCK(&channels); + + return c; +} + /*! \brief Wait, look for hangups and condition arg */ int ast_safe_sleep_conditional(struct ast_channel *chan, int ms, int (*cond)(void*), void *data) { -- GitLab