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;
}
Example #2
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);
}
Example #3
0
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;
}
Example #5
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;
}
Example #8
0
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);
}
Example #9
0
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;
}