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);
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);
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.
{
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;
/* 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)
{
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);
* 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
}
/*! \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);
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.
*/
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;