/*! \brief Helper Function to walk through ALL channels checking NAME and STATE */ static struct ast_channel *my_ast_get_channel_by_name_locked(const char *channame) { char *chkchan; struct pickup_by_name_args pickup_args; /* Check if channel name contains a '-'. * In this case the channel name will be interpreted as full channel name. */ if (strchr(channame, '-')) { /* check full channel name */ pickup_args.len = strlen(channame); pickup_args.name = channame; } else { /* need to append a '-' for the comparison so we check full channel name, * i.e SIP/hgc- , use a temporary variable so original stays the same for * debugging. */ pickup_args.len = strlen(channame) + 1; chkchan = ast_alloca(pickup_args.len + 1); strcpy(chkchan, channame); strcat(chkchan, "-"); pickup_args.name = chkchan; } return ast_channel_callback(pickup_by_name_cb, NULL, &pickup_args, 0); }
struct ast_channel *ast_pickup_find_by_group(struct ast_channel *chan) { struct ao2_container *candidates;/*!< Candidate channels found to pickup. */ struct ast_channel *target;/*!< Potential pickup target */ candidates = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL); if (!candidates) { return NULL; } /* Find all candidate targets by group. */ ast_channel_callback(find_channel_by_group, chan, candidates, 0); /* Find the oldest pickup target candidate */ target = NULL; for (;;) { struct ast_channel *candidate;/*!< Potential new older target */ struct ao2_iterator iter; iter = ao2_iterator_init(candidates, 0); while ((candidate = ao2_iterator_next(&iter))) { if (!target) { /* First target. */ target = candidate; continue; } if (ast_tvcmp(ast_channel_creationtime(candidate), ast_channel_creationtime(target)) < 0) { /* We have a new target. */ ast_channel_unref(target); target = candidate; continue; } ast_channel_unref(candidate); } ao2_iterator_destroy(&iter); if (!target) { /* No candidates found. */ break; } /* The found channel must be locked and ref'd. */ ast_channel_lock(target); /* Recheck pickup ability */ if (ast_can_pickup(target)) { /* This is the channel to pickup. */ break; } /* Someone else picked it up or the call went away. */ ast_channel_unlock(target); ao2_unlink(candidates, target); target = ast_channel_unref(target); } ao2_ref(candidates, -1); return target; }
/* Find channel for pick up specified by partial channel name */ static struct ast_channel *find_by_part(struct ast_channel *chan, const char *part) { struct ast_channel *target; struct pickup_by_name_args pickup_args; pickup_args.chan = chan; /* Try a partial channel name search. */ pickup_args.name = part; pickup_args.len = strlen(part); target = ast_channel_callback(find_by_name, NULL, &pickup_args, 0); if (target) { return target; } /* Now try a search for uniqueid. */ pickup_args.name = part; pickup_args.len = 0; return ast_channel_callback(find_by_uniqueid, NULL, &pickup_args, 0); }
/*! \brief Helper Function to walk through ALL channels checking NAME and STATE */ static struct ast_channel *find_by_channel(struct ast_channel *chan, const char *channame) { struct ast_channel *target; char *chkchan; struct pickup_by_name_args pickup_args; pickup_args.chan = chan; if (strchr(channame, '-')) { /* * Use the given channel name string as-is. This allows a full channel * name with a typical sequence number to be used as well as still * allowing the odd partial channel name that has a '-' in it to still * work, i.e. Local/bob@en-phone. */ pickup_args.len = strlen(channame); pickup_args.name = channame; } else { /* * Append a '-' for the comparison so we check the channel name less * a sequence number, i.e Find SIP/bob- and not SIP/bobby. */ pickup_args.len = strlen(channame) + 1; chkchan = ast_alloca(pickup_args.len + 1); strcpy(chkchan, channame);/* Safe */ strcat(chkchan, "-"); pickup_args.name = chkchan; } target = ast_channel_callback(find_by_name, NULL, &pickup_args, 0); if (target) { return target; } /* Now try a search for uniqueid. */ pickup_args.name = channame; pickup_args.len = 0; return ast_channel_callback(find_by_uniqueid, NULL, &pickup_args, 0); }
/* Attempt to pick up specified by partial channel name */ static int pickup_by_part(struct ast_channel *chan, const char *part) { struct ast_channel *target;/*!< Potential pickup target */ int res = -1; /* The found channel is already locked. */ target = ast_channel_callback(find_by_part, NULL, (char *) part, 0); if (target) { res = ast_do_pickup(chan, target); ast_channel_unlock(target); target = ast_channel_unref(target); } return res; }
static int pickup_by_group(struct ast_channel *chan) { struct ast_channel *target;/*!< Potential pickup target */ int res = -1; /* The found channel is already locked. */ target = ast_channel_callback(find_channel_by_group, NULL, chan, 0); if (target) { ast_log(LOG_NOTICE, "pickup %s attempt by %s\n", target->name, chan->name); res = ast_do_pickup(chan, target); ast_channel_unlock(target); target = ast_channel_unref(target); } return res; }
void ast_cel_check_retire_linkedid(struct ast_channel *chan) { const char *linkedid = chan->linkedid; struct channel_find_data find_dat; /* make sure we need to do all this work */ if (!ast_strlen_zero(linkedid) && ast_cel_track_event(AST_CEL_LINKEDID_END)) { struct ast_channel *tmp = NULL; find_dat.chan = chan; find_dat.linkedid = linkedid; if ((tmp = ast_channel_callback(linkedid_match, NULL, &find_dat, 0))) { tmp = ast_channel_unref(tmp); } else { ast_cel_report_event(chan, AST_CEL_LINKEDID_END, NULL, NULL, NULL); } } }