static int do_pause_or_unpause(struct mansession *s, struct message *m, int action) { struct ast_channel *c = NULL; char *name = astman_get_header(m, "Channel"); if (IS_NULL_STRING(name)) { astman_send_error(s, m, "No channel specified"); return -1; } c = ast_get_channel_by_name_locked(name); if (!c) { astman_send_error(s, m, "No such channel"); return -1; } if (action == MONITOR_ACTION_PAUSE) ast_monitor_pause(c); else ast_monitor_unpause(c); ast_channel_unlock(c); astman_send_ack(s, m, "Paused monitoring of the channel"); return 0; }
static int action_setcdruserfield(struct mansession *s, struct message *m) { struct ast_channel *c = NULL; char *userfield = astman_get_header(m, "UserField"); char *channel = astman_get_header(m, "Channel"); char *append = astman_get_header(m, "Append"); if (ast_strlen_zero(channel)) { astman_send_error(s, m, "No Channel specified"); return 0; } if (ast_strlen_zero(userfield)) { astman_send_error(s, m, "No UserField specified"); return 0; } c = ast_get_channel_by_name_locked(channel); if (!c) { astman_send_error(s, m, "No such channel"); return 0; } if (ast_true(append)) ast_cdr_appenduserfield(c, userfield); else ast_cdr_setuserfield(c, userfield); ast_mutex_unlock(&c->lock); astman_send_ack(s, m, "CDR Userfield Set"); return 0; }
static int change_monitor_action(struct mansession *s, struct message *m) { struct ast_channel *c = NULL; char *name = astman_get_header(m, "Channel"); char *fname = astman_get_header(m, "File"); if (ast_strlen_zero(name)) { astman_send_error(s, m, "No channel specified"); return 0; } if (ast_strlen_zero(fname)) { astman_send_error(s, m, "No filename specified"); return 0; } c = ast_get_channel_by_name_locked(name); if (!c) { astman_send_error(s, m, "No such channel"); return 0; } if (ast_monitor_change_fname(c, fname, 1)) { astman_send_error(s, m, "Could not change monitored filename of channel"); ast_channel_unlock(c); return 0; } ast_channel_unlock(c); astman_send_ack(s, m, "Changed monitor filename"); return 0; }
static int start_monitor_action(struct mansession *s, struct message *m) { struct ast_channel *c = NULL; char *name = astman_get_header(m, "Channel"); char *fname = astman_get_header(m, "File"); char *format = astman_get_header(m, "Format"); char *mix = astman_get_header(m, "Mix"); char *d; if (ast_strlen_zero(name)) { astman_send_error(s, m, "No channel specified"); return 0; } c = ast_get_channel_by_name_locked(name); if (!c) { astman_send_error(s, m, "No such channel"); return 0; } if (ast_strlen_zero(fname)) { /* No filename base specified, default to channel name as per CLI */ fname = malloc (FILENAME_MAX); if (!fname) { astman_send_error(s, m, "Could not start monitoring channel"); ast_mutex_unlock(&c->lock); return 0; } memset(fname, 0, FILENAME_MAX); ast_copy_string(fname, c->name, FILENAME_MAX); /* Channels have the format technology/channel_name - have to replace that / */ if ((d=strchr(fname, '/'))) *d='-'; } if (ast_monitor_start(c, format, fname, 1)) { if (ast_monitor_change_fname(c, fname, 1)) { astman_send_error(s, m, "Could not start monitoring channel"); ast_mutex_unlock(&c->lock); return 0; } } if (ast_true(mix)) { ast_monitor_setjoinfiles(c, 1); } ast_mutex_unlock(&c->lock); astman_send_ack(s, m, "Started monitoring channel"); return 0; }
static char *handle_redirect(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { const char *name, *dest; struct ast_channel *chan; int res; switch (cmd) { case CLI_INIT: e->command = "channel redirect"; e->usage = "" "Usage: channel redirect <channel> <[[context,]exten,]priority>\n" " Redirect an active channel to a specified extension.\n"; /*! \todo It would be nice to be able to redirect 2 channels at the same * time like you can with AMI redirect. However, it is not possible to acquire * two channels without the potential for a deadlock with how ast_channel structs * are managed today. Once ast_channel is a refcounted object, this command * will be able to support that. */ return NULL; case CLI_GENERATE: return ast_complete_channels(a->line, a->word, a->pos, a->n, 2); } if (a->argc != e->args + 2) { return CLI_SHOWUSAGE; } name = a->argv[2]; dest = a->argv[3]; chan = ast_get_channel_by_name_locked(name); if (!chan) { ast_cli(a->fd, "Channel '%s' not found\n", name); return CLI_FAILURE; } res = ast_async_parseable_goto(chan, dest); ast_channel_unlock(chan); if (!res) { ast_cli(a->fd, "Channel '%s' successfully redirected to %s\n", name, dest); } else { ast_cli(a->fd, "Channel '%s' failed to be redirected to %s\n", name, dest); } return res ? CLI_FAILURE : CLI_SUCCESS; }
static int stop_monitor_action(struct mansession *s, struct message *m) { struct ast_channel *c = NULL; char *name = astman_get_header(m, "Channel"); int res; if (ast_strlen_zero(name)) { astman_send_error(s, m, "No channel specified"); return 0; } c = ast_get_channel_by_name_locked(name); if (!c) { astman_send_error(s, m, "No such channel"); return 0; } res = ast_monitor_stop(c, 1); ast_channel_unlock(c); if (res) { astman_send_error(s, m, "Could not stop monitoring channel"); return 0; } astman_send_ack(s, m, "Stopped monitoring channel"); return 0; }
static int manager_play_dtmf(struct mansession *s, const struct message *m) { const char *channel = astman_get_header(m, "Channel"); const char *digit = astman_get_header(m, "Digit"); struct ast_channel *chan = ast_get_channel_by_name_locked(channel); if (!chan) { astman_send_error(s, m, "Channel not specified"); return 0; } if (ast_strlen_zero(digit)) { astman_send_error(s, m, "No digit specified"); ast_mutex_unlock(&chan->lock); return 0; } ast_senddigit(chan, *digit); ast_mutex_unlock(&chan->lock); astman_send_ack(s, m, "DTMF successfully queued"); return 0; }
static int pickup_exec(struct ast_channel *chan, void *data) { int res = 0; struct localuser *u = NULL; struct ast_channel *origin = NULL, *target = NULL; char *tmp = NULL, *exten = NULL, *context = NULL, *rest=data; char workspace[256] = ""; const char *tmp2 = NULL; if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Pickup requires an argument (extension) !\n"); return -1; } LOCAL_USER_ADD(u); while (!target && (exten = rest) ) { res = 0; rest = strchr(exten, '&'); if (rest) *rest++ = 0; /* Get the extension and context if present */ context = strchr(exten, '@'); if (context) *context++ = '\0'; /* If the context is the pickup mark, iterate through all channels finding the right origin one */ if (!strcmp(context, PICKUPMARK)) { while ((origin = ast_channel_walk_locked(origin))) { if (origin) { tmp2 = pbx_builtin_getvar_helper(origin, PICKUPMARK); if (tmp2 && !strcmp(tmp2, exten)) break; ast_mutex_unlock(&origin->lock); } } } else { /* Use the classic mode of searching */ origin = ast_get_channel_by_exten_locked(exten, context); } if (origin) { ast_cdr_getvar(origin->cdr, "dstchannel", &tmp, workspace, sizeof(workspace), 0, 0); if (tmp) { /* We have a possible channel... now we need to find it! */ target = ast_get_channel_by_name_locked(tmp); } else { ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten); res = -1; } ast_mutex_unlock(&origin->lock); } else { ast_log(LOG_DEBUG, "No originating channel found.\n"); } if (res) continue; if (target && (!target->pbx) && ((target->_state == AST_STATE_RINGING) || (target->_state == AST_STATE_RING) ) ) { ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n", target->name, chan->name); res = ast_answer(chan); if (res) { ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); res = -1; break; } res = ast_queue_control(chan, AST_CONTROL_ANSWER); if (res) { ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); res = -1; break; } res = ast_channel_masquerade(target, chan); if (res) { ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name); res = -1; break; } } else { ast_log(LOG_NOTICE, "No call pickup possible for %s...\n", exten); res = -1; } } if (target) ast_mutex_unlock(&target->lock); LOCAL_USER_REMOVE(u); return res; }
static struct ast_channel *get_dahdi_channel_locked(int num) { char name[80]; snprintf(name, sizeof(name), "DAHDI/%d-1", num); return ast_get_channel_by_name_locked(name); }
static int pickup_exec(struct ast_channel *chan, void *data) { int res = 0; struct localuser *u = NULL; struct ast_channel *origin = NULL, *target = NULL; char *tmp = NULL, *exten = NULL, *context = NULL; char workspace[256] = ""; if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Pickup requires an argument (extension) !\n"); return -1; } LOCAL_USER_ADD(u); /* Get the extension and context if present */ exten = data; context = strchr(data, '@'); if (context) { *context = '\0'; context++; } /* Find a channel to pickup */ origin = ast_get_channel_by_exten_locked(exten, context); if (origin && origin->cdr) { ast_cdr_getvar(origin->cdr, "dstchannel", &tmp, workspace, sizeof(workspace), 0); if (tmp) { /* We have a possible channel... now we need to find it! */ target = ast_get_channel_by_name_locked(tmp); } else { ast_log(LOG_DEBUG, "No target channel found.\n"); res = -1; } ast_mutex_unlock(&origin->lock); } else { if (origin) ast_mutex_unlock(&origin->lock); ast_log(LOG_DEBUG, "No originating channel found.\n"); } if (res) goto out; if (target && (!target->pbx) && ((target->_state == AST_STATE_RINGING) || (target->_state == AST_STATE_RING))) { ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n", target->name, chan->name); res = ast_answer(chan); if (res) { ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); res = -1; goto out; } res = ast_queue_control(chan, AST_CONTROL_ANSWER); if (res) { ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); res = -1; goto out; } res = ast_channel_masquerade(target, chan); if (res) { ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name); res = -1; goto out; } } else { ast_log(LOG_DEBUG, "No call pickup possible...\n"); res = -1; } /* Done */ out: if (target) ast_mutex_unlock(&target->lock); LOCAL_USER_REMOVE(u); return res; }