Introduce a new API call ast_channel_search_locked, which iterates through the
authorSean Bright <sean@malleable.com>
Tue, 4 Nov 2008 23:23:39 +0000 (23:23 +0000)
committerSean Bright <sean@malleable.com>
Tue, 4 Nov 2008 23:23:39 +0000 (23:23 +0000)
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
include/asterisk/channel.h
main/channel.c

index 36a027e..4ebd970 100644 (file)
@@ -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
index 549b688..2f212cf 100644 (file)
@@ -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
index 4174613..34733af 100644 (file)
@@ -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)
 {