static int status_session(struct respoke_session *session, enum respoke_status status) { if (!session->channel) { return 0; } switch (status) { case RESPOKE_STATUS_RINGING: ast_queue_control(session->channel, AST_CONTROL_RINGING); ast_channel_lock(session->channel); if (ast_channel_state(session->channel) != AST_STATE_UP) { ast_setstate(session->channel, AST_STATE_RINGING); } ast_channel_unlock(session->channel); break; case RESPOKE_STATUS_PROGRESS: ast_queue_control(session->channel, AST_CONTROL_PROGRESS); break; default: set_cause_code(session, status); ast_queue_hangup(session->channel); break; } return 0; }
/*! \brief Function called when we should actually call the destination */ static int multicast_rtp_call(struct ast_channel *ast, const char *dest, int timeout) { struct ast_rtp_instance *instance = ast_channel_tech_pvt(ast); ast_queue_control(ast, AST_CONTROL_ANSWER); return ast_rtp_instance_activate(instance); }
static int phone_call(struct ast_channel *ast, char *dest, int timeout) { struct phone_pvt *p; PHONE_CID cid; time_t UtcTime; struct tm tm; time(&UtcTime); localtime_r(&UtcTime,&tm); memset(&cid, 0, sizeof(PHONE_CID)); if(&tm != NULL) { snprintf(cid.month, sizeof(cid.month), "%02d",(tm.tm_mon + 1)); snprintf(cid.day, sizeof(cid.day), "%02d", tm.tm_mday); snprintf(cid.hour, sizeof(cid.hour), "%02d", tm.tm_hour); snprintf(cid.min, sizeof(cid.min), "%02d", tm.tm_min); } /* the standard format of ast->callerid is: "name" <number>, but not always complete */ if (!ast->callerid || ast_strlen_zero(ast->callerid)){ strncpy(cid.name, DEFAULT_CALLER_ID, sizeof(cid.name) - 1); cid.number[0]='\0'; } else { char *n, *l; char callerid[256] = ""; strncpy(callerid, ast->callerid, sizeof(callerid) - 1); ast_callerid_parse(callerid, &n, &l); if (l) { ast_shrink_phone_number(l); if (!ast_isphonenumber(l)) l = NULL; } if (l) strncpy(cid.number, l, sizeof(cid.number) - 1); if (n) strncpy(cid.name, n, sizeof(cid.name) - 1); } p = ast->pvt->pvt; if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { ast_log(LOG_WARNING, "phone_call called on %s, neither down nor reserved\n", ast->name); return -1; } if (option_debug) ast_log(LOG_DEBUG, "Ringing %s on %s (%d)\n", dest, ast->name, ast->fds[0]); IXJ_PHONE_RING_START(cid); ast_setstate(ast, AST_STATE_RINGING); ast_queue_control(ast, AST_CONTROL_RINGING); return 0; }
static int answer_session(struct respoke_session *session, enum respoke_status status) { if (!session->channel) { return 0; } switch (status) { case RESPOKE_STATUS_FINAL: default: ast_queue_control(session->channel, AST_CONTROL_ANSWER); break; } set_cause_code(session, status); return 0; }
/* Perform actual pickup between two channels */ static int pickup_do(struct ast_channel *chan, struct ast_channel *target) { int res = 0; if (option_debug) ast_log(LOG_DEBUG, "Call pickup on '%s' by '%s'\n", target->name, chan->name); if ((res = ast_answer(chan))) { ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name); return -1; } if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) { ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name); return -1; } if ((res = ast_channel_masquerade(target, chan))) { ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name); return -1; } return res; }
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 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; }
int stasis_app_control_queue_control(struct stasis_app_control *control, enum ast_control_frame_type frame_type) { return ast_queue_control(control->channel, frame_type); }
int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target) { struct ast_party_connected_line connected_caller; struct ast_datastore *ds_pickup; const char *chan_name;/*!< A masquerade changes channel names. */ const char *target_name;/*!< A masquerade changes channel names. */ int res = -1; RAII_VAR(struct ast_channel_snapshot *, chan_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, target_snapshot, NULL, ao2_cleanup); target_name = ast_strdupa(ast_channel_name(target)); ast_debug(1, "Call pickup on '%s' by '%s'\n", target_name, ast_channel_name(chan)); /* Mark the target to block any call pickup race. */ ds_pickup = ast_datastore_alloc(&pickup_active, NULL); if (!ds_pickup) { ast_log(LOG_WARNING, "Unable to create channel datastore on '%s' for call pickup\n", target_name); return -1; } ast_channel_datastore_add(target, ds_pickup); ast_party_connected_line_init(&connected_caller); ast_party_connected_line_copy(&connected_caller, ast_channel_connected(target)); ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */ /* Reset any earlier private connected id representation */ ast_party_id_reset(&connected_caller.priv); connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; if (ast_channel_connected_line_sub(NULL, chan, &connected_caller, 0) && ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) { ast_channel_update_connected_line(chan, &connected_caller, NULL); } ast_party_connected_line_free(&connected_caller); ast_channel_lock(chan); chan_name = ast_strdupa(ast_channel_name(chan)); ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(chan)); ast_channel_unlock(chan); connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; if (ast_answer(chan)) { ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name); goto pickup_failed; } if (ast_queue_control(chan, AST_CONTROL_ANSWER)) { ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name); goto pickup_failed; } ast_channel_queue_connected_line_update(chan, &connected_caller, NULL); /* setting the HANGUPCAUSE so the ringing channel knows this call was not a missed call */ ast_channel_hangupcause_set(chan, AST_CAUSE_ANSWERED_ELSEWHERE); ast_channel_lock(chan); chan_snapshot = ast_channel_snapshot_create(chan); ast_channel_unlock(chan); if (!chan_snapshot) { goto pickup_failed; } target_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(target)); if (!target_snapshot) { goto pickup_failed; } if (ast_channel_move(target, chan)) { ast_log(LOG_WARNING, "Unable to complete call pickup of '%s' with '%s'\n", chan_name, target_name); goto pickup_failed; } /* target points to the channel that did the pickup at this point, so use that channel's topic instead of chan */ send_call_pickup_stasis_message(target, chan_snapshot, target_snapshot); res = 0; pickup_failed: ast_channel_lock(target); if (!ast_channel_datastore_remove(target, ds_pickup)) { ast_datastore_free(ds_pickup); } ast_party_connected_line_free(&connected_caller); return res; }