summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_directed_pickup.c47
-rw-r--r--channels/chan_sip.c71
-rw-r--r--include/asterisk/channel.h3
-rw-r--r--main/channel.c4
-rw-r--r--main/features.c22
5 files changed, 89 insertions, 58 deletions
diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c
index deca8f3de..7fb5f6fea 100644
--- a/apps/app_directed_pickup.c
+++ b/apps/app_directed_pickup.c
@@ -169,17 +169,30 @@ static int pickup_by_channel(struct ast_channel *chan, char *pickup)
return res;
}
+struct pickup_criteria {
+ const char *exten;
+ const char *context;
+};
+
+static int find_by_exten(struct ast_channel *c, void *data)
+{
+ struct pickup_criteria *info = data;
+
+ return (!strcasecmp(c->macroexten, info->exten) || !strcasecmp(c->exten, info->exten)) &&
+ !strcasecmp(c->dialcontext, info->context) &&
+ can_pickup(c);
+}
+
/* Attempt to pick up specified extension with context */
static int pickup_by_exten(struct ast_channel *chan, const char *exten, const char *context)
{
- auto int find_by_exten(struct ast_channel *c);
- int find_by_exten(struct ast_channel *c) {
- return (!strcasecmp(c->macroexten, exten) || !strcasecmp(c->exten, exten)) &&
- !strcasecmp(c->dialcontext, context) &&
- can_pickup(c);
- }
+ struct ast_channel *target = NULL;
+ struct pickup_criteria search = {
+ .exten = exten,
+ .context = context,
+ };
- struct ast_channel *target = ast_channel_search_locked(find_by_exten);
+ target = ast_channel_search_locked(find_by_exten, &search);
if (target) {
int res = pickup_do(chan, target);
@@ -191,18 +204,20 @@ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const ch
return -1;
}
+static int find_by_mark(struct ast_channel *c, void *data)
+{
+ const char *mark = data;
+ const char *tmp;
+
+ return (tmp = pbx_builtin_getvar_helper(c, PICKUPMARK)) &&
+ !strcasecmp(tmp, mark) &&
+ can_pickup(c);
+}
+
/* Attempt to pick up specified mark */
static int pickup_by_mark(struct ast_channel *chan, const char *mark)
{
- auto int find_by_mark(struct ast_channel *);
- int find_by_mark(struct ast_channel *c) {
- const char *tmp;
- return (tmp = pbx_builtin_getvar_helper(c, PICKUPMARK)) &&
- !strcasecmp(tmp, mark) &&
- can_pickup(c);
- }
-
- struct ast_channel *target = ast_channel_search_locked(find_by_mark);
+ struct ast_channel *target = ast_channel_search_locked(find_by_mark, (char *) mark);
if (target) {
int res = pickup_do(chan, target);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 06d8d6f3c..d3d79fd08 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -4421,6 +4421,26 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
return peer;
}
+/* Function to assist finding peers by name only */
+static int find_by_name(void *obj, void *arg, void *data, int flags)
+{
+ struct sip_peer *search = obj, *match = arg;
+ int *forcenamematch = data;
+
+ /* Usernames in SIP uri's are case sensitive. Domains are not */
+ if (strcmp(search->name, match->name)) {
+ return 0;
+ }
+
+ /* If we're only looking for name matches, we should avoid type=peer devices,
+ since these should not match on any name-based search */
+ if (*forcenamematch && search->onlymatchonip) {
+ return 0;
+ }
+
+ return CMP_MATCH | CMP_STOP;
+}
+
/*! \brief Locate device by name or ip address
* This is used on find matching device on name or ip/port.
If the device was declared as type=peer, we don't match on peer name on incoming INVITEs.
@@ -4433,31 +4453,10 @@ static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int
{
struct sip_peer *p = NULL;
struct sip_peer tmp_peer;
-
- /* Inline function to assist finding peers by name only */
- auto int find_by_name(void *obj, void *arg, void *data, int flags);
-
- int find_by_name(void *obj, void *arg, void *data, int flags)
- {
- struct sip_peer *search = obj, *match = arg;
-
- /* Usernames in SIP uri's are case sensitive. Domains are not */
- if (strcmp(search->name, match->name)) {
- return 0;
- }
-
- /* If we're only looking for name matches, we should avoid type=peer devices,
- since these should not match on any name-based search */
- if (forcenamematch && search->onlymatchonip) {
- return 0;
- }
-
- return CMP_MATCH | CMP_STOP;
- }
if (peer) {
ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name));
- p = ao2_t_callback(peers, OBJ_POINTER, find_by_name, &tmp_peer, NULL, "ao2_find in peers table");
+ p = ao2_t_callback(peers, OBJ_POINTER, find_by_name, &tmp_peer, &forcenamematch, "ao2_find in peers table");
} else if (sin) { /* search by addr? */
tmp_peer.addr.sin_addr.s_addr = sin->sin_addr.s_addr;
tmp_peer.addr.sin_port = sin->sin_port;
@@ -9870,10 +9869,23 @@ static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi)
/* Actually send the packet */
transmit_invite(mwi->call, SIP_SUBSCRIBE, 0, 2);
-
+
return 0;
}
+struct caller_criteria {
+ const char *exten;
+ const char *context;
+};
+
+static int find_calling_channel(struct ast_channel *c, void *data) {
+ struct caller_criteria *info = data;
+
+ return (c->pbx &&
+ (!strcasecmp(c->macroexten, info->exten) || !strcasecmp(c->exten, info->exten)) &&
+ !strcasecmp(c->context, info->context));
+}
+
/*! \brief Used in the SUBSCRIBE notification subsystem (RFC3265) */
static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout)
{
@@ -10039,14 +10051,13 @@ 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) {
- 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 = NULL;
+ struct caller_criteria data = {
+ .exten = p->exten,
+ .context = p->context,
+ };
- struct ast_channel *caller = ast_channel_search_locked(find_calling_channel);
+ caller = ast_channel_search_locked(find_calling_channel, &data);
if (caller) {
local_display = ast_strdupa(caller->cid.cid_name);
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index c1423462e..64aaca069 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -1185,9 +1185,10 @@ struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *c
* 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.
+ * \param data data passed to the is_match callback during each invocation.
* \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 *));
+struct ast_channel *ast_channel_search_locked(int (*is_match)(struct ast_channel *, void *), void *data);
/*! ! \brief Waits for a digit
* \param c channel to wait for a digit on
diff --git a/main/channel.c b/main/channel.c
index ec253ae04..b5a4054a4 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -1227,14 +1227,14 @@ struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *c
}
/*! \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 *ast_channel_search_locked(int (*is_match)(struct ast_channel *, void *), void *data)
{
struct ast_channel *c = NULL;
AST_RWLIST_RDLOCK(&channels);
AST_RWLIST_TRAVERSE(&channels, c, chan_list) {
ast_channel_lock(c);
- if (is_match(c)) {
+ if (is_match(c, data)) {
break;
}
ast_channel_unlock(c);
diff --git a/main/features.c b/main/features.c
index ed13ee4fc..932f1b8a1 100644
--- a/main/features.c
+++ b/main/features.c
@@ -3987,6 +3987,18 @@ static int manager_park(struct mansession *s, const struct message *m)
return 0;
}
+static int find_channel_by_group(struct ast_channel *c, void *data) {
+ struct ast_channel *chan = data;
+
+ return !c->pbx &&
+ /* Accessing 'chan' here is safe without locking, because there is no way for
+ the channel do disappear from under us at this point. pickupgroup *could*
+ change while we're here, but that isn't a problem. */
+ (c != chan) &&
+ (chan->pickupgroup & c->callgroup) &&
+ ((c->_state == AST_STATE_RINGING) || (c->_state == AST_STATE_RING));
+}
+
/*!
* \brief Pickup a call
* \param chan channel that initiated pickup.
@@ -3997,15 +4009,7 @@ static int manager_park(struct mansession *s, const struct message *m)
*/
int ast_pickup_call(struct ast_channel *chan)
{
- auto int find_channel_by_group(struct ast_channel *);
- int find_channel_by_group(struct ast_channel *c) {
- return !c->pbx &&
- (c != chan) &&
- (chan->pickupgroup & c->callgroup) &&
- ((c->_state == AST_STATE_RINGING) ||
- (c->_state == AST_STATE_RING));
- }
- struct ast_channel *cur = ast_channel_search_locked(find_channel_by_group);
+ struct ast_channel *cur = ast_channel_search_locked(find_channel_by_group, chan);
if (cur) {
int res = -1;