Beispiel #1
0
/*!
 * \brief Dial timeout
 *
 * This is a bridge interval hook callback. The interval hook triggering
 * means that the dial timeout has been reached. If the channel has not
 * been answered by the time this callback is called, then the channel
 * is hung up
 *
 * \param bridge_channel Bridge channel on which interval hook has been called
 * \param ignore Ignored
 * \return -1 (i.e. remove the interval hook)
 */
static int bridge_timeout(struct ast_bridge_channel *bridge_channel, void *ignore)
{
	struct ast_datastore *datastore;
	RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);

	control = stasis_app_control_find_by_channel(bridge_channel->chan);

	ast_channel_lock(bridge_channel->chan);
	if (ast_channel_state(bridge_channel->chan) != AST_STATE_UP) {
		/* Don't bother removing the datastore because it will happen when the channel is hung up */
		ast_channel_unlock(bridge_channel->chan);
		stasis_app_send_command_async(control, hangup_channel, NULL, NULL);
		return -1;
	}

	datastore = ast_channel_datastore_find(bridge_channel->chan, &timeout_datastore, NULL);
	if (!datastore) {
		ast_channel_unlock(bridge_channel->chan);
		return -1;
	}
	ast_channel_datastore_remove(bridge_channel->chan, datastore);
	ast_channel_unlock(bridge_channel->chan);
	ast_datastore_free(datastore);

	return -1;
}
Beispiel #2
0
static int app_control_silence_start(struct stasis_app_control *control,
	struct ast_channel *chan, void *data)
{
	if (ast_channel_state(chan) != AST_STATE_UP) {
		ast_indicate(chan, AST_CONTROL_PROGRESS);
	}

	if (control->silgen) {
		/* We have a silence generator, but it may have been implicitly
		 * disabled by media actions (music on hold, playing media,
		 * etc.) Just stop it and restart a new one.
		 */
		ast_channel_stop_silence_generator(
			control->channel, control->silgen);
	}

	ast_debug(3, "%s: Starting silence generator\n",
		stasis_app_control_get_channel_id(control));
	control->silgen = ast_channel_start_silence_generator(control->channel);

	if (!control->silgen) {
		ast_log(LOG_WARNING,
			"%s: Failed to start silence generator.\n",
			stasis_app_control_get_channel_id(control));
	}

	return 0;
}
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;
}
Beispiel #4
0
static int dahdiras_exec(struct ast_channel *chan, const char *data)
{
    int res=-1;
    char *args;
    struct dahdi_params dahdip;

    if (!data)
        data = "";

    args = ast_strdupa(data);

    /* Answer the channel if it's not up */
    if (ast_channel_state(chan) != AST_STATE_UP)
        ast_answer(chan);
    if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
        /* If it's not a DAHDI channel, we're done.  Wait a couple of
           seconds and then hangup... */
        ast_verb(2, "Channel %s is not a DAHDI channel\n", ast_channel_name(chan));
        sleep(2);
    } else {
        memset(&dahdip, 0, sizeof(dahdip));
        if (ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip)) {
            ast_log(LOG_WARNING, "Unable to get DAHDI parameters\n");
        } else if (dahdip.sigtype != DAHDI_SIG_CLEAR) {
            ast_verb(2, "Channel %s is not a clear channel\n", ast_channel_name(chan));
        } else {
            /* Everything should be okay.  Run PPP. */
            ast_verb(3, "Starting RAS on %s\n", ast_channel_name(chan));
            /* Execute RAS */
            run_ras(chan, args);
        }
    }
    return res;
}
Beispiel #5
0
int ast_can_pickup(struct ast_channel *chan)
{
	if (!ast_channel_pbx(chan) && !ast_channel_masq(chan) && !ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE)
		&& (ast_channel_state(chan) == AST_STATE_RINGING
			|| ast_channel_state(chan) == AST_STATE_RING
			/*
			 * Check the down state as well because some SIP devices do not
			 * give 180 ringing when they can just give 183 session progress
			 * instead.  Issue 14005.  (Some ISDN switches as well for that
			 * matter.)
			 */
			|| ast_channel_state(chan) == AST_STATE_DOWN)
		&& !ast_channel_datastore_find(chan, &pickup_active, NULL)) {
		return 1;
	}
	return 0;
}
Beispiel #6
0
static int transmit(fax_session *s)
{
	int res = 0;

	/* Clear all channel variables which to be set by the application.
	   Pre-set status to error so in case of any problems we can just leave */
	pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "FAILED"); 
	pbx_builtin_setvar_helper(s->chan, "FAXERROR", "Channel problems"); 

	pbx_builtin_setvar_helper(s->chan, "FAXMODE", NULL);
	pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", NULL);
	pbx_builtin_setvar_helper(s->chan, "FAXPAGES", "0");
	pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", NULL);
	pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", NULL); 

	if (ast_channel_state(s->chan) != AST_STATE_UP) {
		/* Shouldn't need this, but checking to see if channel is already answered
		 * Theoretically asterisk should already have answered before running the app */
		res = ast_answer(s->chan);
		if (res) {
			ast_log(LOG_WARNING, "Could not answer channel '%s'\n", ast_channel_name(s->chan));
			return res;
		}
	}

	s->t38state = ast_channel_get_t38_state(s->chan);
	if (s->t38state != T38_STATE_NEGOTIATED) {
		/* T38 is not negotiated on the channel yet. First start regular transmission. If it switches to T38, follow */	
		pbx_builtin_setvar_helper(s->chan, "FAXMODE", "audio"); 
		res = transmit_audio(s);
		if (res > 0) {
			/* transmit_audio reports switchover to T38. Update t38state */
			s->t38state = ast_channel_get_t38_state(s->chan);
			if (s->t38state != T38_STATE_NEGOTIATED) {
				ast_log(LOG_ERROR, "Audio loop reports T38 switchover but t38state != T38_STATE_NEGOTIATED\n");
			}
		}
	}

	if (s->t38state == T38_STATE_NEGOTIATED) {
		pbx_builtin_setvar_helper(s->chan, "FAXMODE", "T38"); 
		res = transmit_t38(s);
	}

	if (res) {
		ast_log(LOG_WARNING, "Transmission error\n");
		res = -1;
	} else if (s->finished < 0) {
		ast_log(LOG_WARNING, "Transmission failed\n");
	} else if (s->finished > 0) {
		ast_debug(1, "Transmission finished Ok\n");
	}

	return res;
}
Beispiel #7
0
/*!
 * \brief Depart a channel from a bridge, and potentially add it back to the dial bridge
 *
 * \param control Take a guess
 * \param chan Take another guess
 */
static int depart_channel(struct stasis_app_control *control, struct ast_channel *chan)
{
	ast_bridge_depart(chan);

	if (!ast_check_hangup(chan) && ast_channel_state(chan) != AST_STATE_UP) {
		/* Channel is still being dialed, so put it back in the dialing bridge */
		add_to_dial_bridge(control, chan);
	}

	return 0;
}
Beispiel #8
0
static int app_control_moh_start(struct stasis_app_control *control,
	struct ast_channel *chan, void *data)
{
	char *moh_class = data;

	if (ast_channel_state(chan) != AST_STATE_UP) {
		ast_indicate(chan, AST_CONTROL_PROGRESS);
	}

	ast_moh_start(chan, moh_class, NULL);

	return 0;
}
Beispiel #9
0
/*!
 * \ingroup applications
 */
int indicate_congestion(struct ast_channel *chan, const char *data)
{
	ast_indicate(chan, AST_CONTROL_CONGESTION);
	/* Don't change state of an UP channel, just indicate
	   congestion in audio */
	ast_channel_lock(chan);
	if (ast_channel_state(chan) != AST_STATE_UP) {
		ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
		ast_setstate(chan, AST_STATE_BUSY);
	}
	ast_channel_unlock(chan);
	wait_for_hangup(chan, data);
	return -1;
}
Beispiel #10
0
static int bridgeadd_exec(struct ast_channel *chan, const char *data)
{
	struct ast_channel *c_ref;
	struct ast_bridge_features chan_features;
	struct ast_bridge *bridge;
	char *c_name;

	/* Answer the channel if needed */
	if (ast_channel_state(chan) != AST_STATE_UP) {
		ast_answer(chan);
	}

	if (!(c_ref = ast_channel_get_by_name_prefix(data, strlen(data)))) {
		ast_log(LOG_WARNING, "Channel %s not found\n", data);
		return -1;
	}

	c_name = ast_strdupa(ast_channel_name(c_ref));

	ast_channel_lock(c_ref);
	bridge = ast_channel_get_bridge(c_ref);
	ast_channel_unlock(c_ref);

	ast_channel_unref(c_ref);

	if (!bridge) {
		ast_log(LOG_WARNING, "Channel %s is not in a bridge\n", c_name);
		return -1;
	}

	ast_verb(3, "%s is joining %s in bridge %s\n", ast_channel_name(chan),
		c_name, bridge->uniqueid);

	if (ast_bridge_features_init(&chan_features)
		|| ast_bridge_join(bridge, chan, NULL, &chan_features, NULL, 0)) {

		ast_log(LOG_WARNING, "%s failed to join %s in bridge %s\n", ast_channel_name(chan),
			 c_name, bridge->uniqueid);

		ast_bridge_features_cleanup(&chan_features);
		ao2_cleanup(bridge);
		return -1;
	}

	ast_bridge_features_cleanup(&chan_features);
	ao2_cleanup(bridge);
	return 0;
}
Beispiel #11
0
static int old_milliwatt_exec(struct ast_channel *chan)
{
	ast_set_write_format_by_id(chan, AST_FORMAT_ULAW);
	ast_set_read_format_by_id(chan, AST_FORMAT_ULAW);

	if (ast_channel_state(chan) != AST_STATE_UP) {
		ast_answer(chan);
	}

	if (ast_activate_generator(chan,&milliwattgen,"milliwatt") < 0) {
		ast_log(LOG_WARNING,"Failed to activate generator on '%s'\n",ast_channel_name(chan));
		return -1;
	}

	while (!ast_safe_sleep(chan, 10000))
		;

	ast_deactivate_generator(chan);

	return -1;
}
Beispiel #12
0
static int app_control_dtmf(struct stasis_app_control *control,
	struct ast_channel *chan, void *data)
{
	struct stasis_app_control_dtmf_data *dtmf_data = data;

	if (ast_channel_state(chan) != AST_STATE_UP) {
		ast_indicate(chan, AST_CONTROL_PROGRESS);
	}

	if (dtmf_data->before) {
		ast_safe_sleep(chan, dtmf_data->before);
	}

	ast_dtmf_stream(chan, NULL, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);

	if (dtmf_data->after) {
		ast_safe_sleep(chan, dtmf_data->after);
	}

	return 0;
}
Beispiel #13
0
static int skel_exec(struct ast_channel *chan, const char *data)
{
	int res=0;
	char *tmp;

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "skel requires an argument (filename)\n");
		return -1;
	}

	tmp = ast_strdupa(data);

	/* Do our thing here */

	if (ast_channel_state(chan) != AST_STATE_UP)
		res = ast_answer(chan);
	if (!res)
		res = ast_ivr_menu_run(chan, &ivr_demo, tmp);

	return res;
}
Beispiel #14
0
static int waitfor_exec(struct ast_channel *chan, const char *data, int wait_for_silence)
{
	int res = 1;
	int timereqd = 1000;
	int timeout = 0;
	int iterations = 1, i;
	time_t waitstart;
	struct ast_silence_generator *silgen = NULL;

	if (ast_channel_state(chan) != AST_STATE_UP) {
		res = ast_answer(chan); /* Answer the channel */
	}

	if (!data || ( (sscanf(data, "%30d,%30d,%30d", &timereqd, &iterations, &timeout) != 3) &&
		(sscanf(data, "%30d,%30d", &timereqd, &iterations) != 2) &&
		(sscanf(data, "%30d", &timereqd) != 1) ) ) {
		ast_log(LOG_WARNING, "Using default value of 1000ms, 1 iteration, no timeout\n");
	}

	ast_verb(3, "Waiting %d time(s) for %d ms silence with %d timeout\n", iterations, timereqd, timeout);

	if (ast_opt_transmit_silence) {
		silgen = ast_channel_start_silence_generator(chan);
	}
	time(&waitstart);
	res = 1;
	for (i=0; (i<iterations) && (res == 1); i++) {
		res = do_waiting(chan, timereqd, waitstart, timeout, wait_for_silence);
	}
	if (silgen) {
		ast_channel_stop_silence_generator(chan, silgen);
	}


	if (res > 0)
		res = 0;
	return res;
}
Beispiel #15
0
static int func_channel_read(struct ast_channel *chan, const char *function,
			     char *data, char *buf, size_t len)
{
	int ret = 0;
	struct ast_format_cap *tmpcap;

	if (!chan) {
		ast_log(LOG_WARNING, "No channel was provided to %s function.\n", function);
		return -1;
	}

	if (!strcasecmp(data, "audionativeformat")) {
		tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
		if (tmpcap) {
			struct ast_str *codec_buf = ast_str_alloca(128);

			ast_channel_lock(chan);
			ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_AUDIO);
			ast_channel_unlock(chan);
			ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
			ao2_ref(tmpcap, -1);
		}
	} else if (!strcasecmp(data, "videonativeformat")) {
		tmpcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
		if (tmpcap) {
			struct ast_str *codec_buf = ast_str_alloca(128);

			ast_channel_lock(chan);
			ast_format_cap_append_from_cap(tmpcap, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_VIDEO);
			ast_channel_unlock(chan);
			ast_copy_string(buf, ast_format_cap_get_names(tmpcap, &codec_buf), len);
			ao2_ref(tmpcap, -1);
		}
	} else if (!strcasecmp(data, "audioreadformat")) {
		locked_copy_string(chan, buf, ast_format_get_name(ast_channel_readformat(chan)), len);
	} else if (!strcasecmp(data, "audiowriteformat")) {
		locked_copy_string(chan, buf, ast_format_get_name(ast_channel_writeformat(chan)), len);
#ifdef CHANNEL_TRACE
	} else if (!strcasecmp(data, "trace")) {
		locked_copy_string(chan, buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
#endif
	} else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan)) {
		locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
	} else if (!strcasecmp(data, "dtmf_features")) {
		if (ast_bridge_features_ds_get_string(chan, buf, len)) {
			buf[0] = '\0';
		}
	} else if (!strcasecmp(data, "language"))
		locked_copy_string(chan, buf, ast_channel_language(chan), len);
	else if (!strcasecmp(data, "musicclass"))
		locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
	else if (!strcasecmp(data, "name")) {
		locked_copy_string(chan, buf, ast_channel_name(chan), len);
	} else if (!strcasecmp(data, "parkinglot"))
		locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
	else if (!strcasecmp(data, "state"))
		locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
	else if (!strcasecmp(data, "onhold")) {
		locked_copy_string(chan, buf,
			ast_channel_hold_state(chan) == AST_CONTROL_HOLD ? "1" : "0", len);
	} else if (!strcasecmp(data, "channeltype"))
		locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
	else if (!strcasecmp(data, "accountcode"))
		locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
	else if (!strcasecmp(data, "checkhangup")) {
		locked_copy_string(chan, buf, ast_check_hangup(chan) ? "1" : "0", len);
	} else if (!strcasecmp(data, "peeraccount"))
		locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
	else if (!strcasecmp(data, "hangupsource"))
		locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
	else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
		locked_copy_string(chan, buf, ast_channel_appl(chan), len);
	else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
		locked_copy_string(chan, buf, ast_channel_data(chan), len);
	else if (!strcasecmp(data, "exten") && ast_channel_data(chan))
		locked_copy_string(chan, buf, ast_channel_exten(chan), len);
	else if (!strcasecmp(data, "context") && ast_channel_data(chan))
		locked_copy_string(chan, buf, ast_channel_context(chan), len);
	else if (!strcasecmp(data, "userfield") && ast_channel_data(chan))
		locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
	else if (!strcasecmp(data, "channame") && ast_channel_data(chan))
		locked_copy_string(chan, buf, ast_channel_name(chan), len);
	else if (!strcasecmp(data, "linkedid")) {
		ast_channel_lock(chan);
		if (ast_strlen_zero(ast_channel_linkedid(chan))) {
			/* fall back on the channel's uniqueid if linkedid is unset */
			ast_copy_string(buf, ast_channel_uniqueid(chan), len);
		}
		else {
			ast_copy_string(buf, ast_channel_linkedid(chan), len);
		}
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "peer")) {
		struct ast_channel *peer;

		peer = ast_channel_bridge_peer(chan);
		if (peer) {
			/* Only real channels could have a bridge peer this way. */
			ast_channel_lock(peer);
			ast_copy_string(buf, ast_channel_name(peer), len);
			ast_channel_unlock(peer);
			ast_channel_unref(peer);
		} else {
			buf[0] = '\0';
			ast_channel_lock(chan);
			if (!ast_channel_tech(chan)) {
				const char *pname;

				/*
				 * A dummy channel can still pass along bridged peer info
				 * via the BRIDGEPEER variable.
				 *
				 * A horrible kludge, but... how else?
				 */
				pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
				if (!ast_strlen_zero(pname)) {
					ast_copy_string(buf, pname, len);
				}
			}
			ast_channel_unlock(chan);
		}
	} else if (!strcasecmp(data, "uniqueid")) {
		locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
	} else if (!strcasecmp(data, "transfercapability")) {
		locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
	} else if (!strcasecmp(data, "callgroup")) {
		char groupbuf[256];

		locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
	} else if (!strcasecmp(data, "pickupgroup")) {
		char groupbuf[256];

		locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
	} else if (!strcasecmp(data, "namedcallgroup")) {
		struct ast_str *tmp_str = ast_str_alloca(1024);

		locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_callgroups(chan)), len);
	} else if (!strcasecmp(data, "namedpickupgroup")) {
		struct ast_str *tmp_str = ast_str_alloca(1024);

		locked_copy_string(chan, buf,  ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
	} else if (!strcasecmp(data, "after_bridge_goto")) {
		ast_bridge_read_after_goto(chan, buf, len);
	} else if (!strcasecmp(data, "amaflags")) {
		ast_channel_lock(chan);
		snprintf(buf, len, "%u", ast_channel_amaflags(chan));
		ast_channel_unlock(chan);
	} else if (!strncasecmp(data, "secure_bridge_", 14)) {
		struct ast_datastore *ds;

		buf[0] = '\0';
		ast_channel_lock(chan);
		if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
			struct ast_secure_call_store *encrypt = ds->data;

			if (!strcasecmp(data, "secure_bridge_signaling")) {
				snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
			} else if (!strcasecmp(data, "secure_bridge_media")) {
				snprintf(buf, len, "%s", encrypt->media ? "1" : "");
			}
		}
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "max_forwards")) {
		ast_channel_lock(chan);
		snprintf(buf, len, "%d", ast_max_forwards_get(chan));
		ast_channel_unlock(chan);
	} else if (!ast_channel_tech(chan) || !ast_channel_tech(chan)->func_channel_read || ast_channel_tech(chan)->func_channel_read(chan, function, data, buf, len)) {
		ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
		ret = -1;
	}

	return ret;
}
Beispiel #16
0
/*!
 * \internal
 * \brief ast_bridge parking push method.
 * \since 12.0.0
 *
 * \param self Bridge to operate upon
 * \param bridge_channel Bridge channel to push
 * \param swap Bridge channel to swap places with if not NULL
 *
 * \note On entry, self is already locked
 *
 * \retval 0 on success
 * \retval -1 on failure
 */
static int bridge_parking_push(struct ast_bridge_parking *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
{
	struct parked_user *pu;
	const char *blind_transfer;
	RAII_VAR(struct ast_channel *, parker, NULL, ao2_cleanup); /* XXX replace with ast_channel_cleanup when available */
	RAII_VAR(struct park_common_datastore *, park_datastore, NULL, park_common_datastore_free);

	ast_bridge_base_v_table.push(&self->base, bridge_channel, swap);

	ast_assert(self->lot != NULL);

	/* Answer the channel if needed */
	if (ast_channel_state(bridge_channel->chan) != AST_STATE_UP) {
		ast_answer(bridge_channel->chan);
	}

	if (swap) {
		int use_ringing = 0;

		ast_bridge_channel_lock(swap);
		pu = swap->bridge_pvt;
		if (!pu) {
			/* This should be impossible since the only way a channel can enter in the first place
			 * is if it has a parked user associated with it */
			publish_parked_call_failure(bridge_channel->chan);
			ast_bridge_channel_unlock(swap);
			return -1;
		}

		/* Give the swap channel's parked user reference to the incoming channel */
		pu->chan = bridge_channel->chan;
		bridge_channel->bridge_pvt = pu;
		swap->bridge_pvt = NULL;

		if (ast_bridge_channel_has_role(swap, "holding_participant")) {
			const char *idle_mode = ast_bridge_channel_get_role_option(swap, "holding_participant", "idle_mode");

			if (!ast_strlen_zero(idle_mode) && !strcmp(idle_mode, "ringing")) {
				use_ringing = 1;
			}
		}

		ast_bridge_channel_unlock(swap);

		parking_set_duration(bridge_channel->features, pu);

		if (parking_channel_set_roles(bridge_channel->chan, self->lot, use_ringing)) {
			ast_log(LOG_WARNING, "Failed to apply holding bridge roles to %s while joining the parking lot.\n",
				ast_channel_name(bridge_channel->chan));
		}

		publish_parked_call(pu, PARKED_CALL_SWAP);

		return 0;
	}

	if (!(park_datastore = get_park_common_datastore_copy(bridge_channel->chan))) {
		/* There was either a failure to apply the datastore when performing park common setup or else we had alloc failures while cloning. Abort. */
		return -1;
	}
	parker = ast_channel_get_by_name(park_datastore->parker_uuid);

	/* If the parker and the parkee are the same channel pointer, then the channel entered using
	 * the park application. It's possible that the channel that transferred it is still alive (particularly
	 * when a multichannel bridge is parked), so try to get the real parker if possible. */
	ast_channel_lock(bridge_channel->chan);
	blind_transfer = S_OR(pbx_builtin_getvar_helper(bridge_channel->chan, "BLINDTRANSFER"),
		ast_channel_name(bridge_channel->chan));
	if (blind_transfer) {
		blind_transfer = ast_strdupa(blind_transfer);
	}
	ast_channel_unlock(bridge_channel->chan);

	if (parker == bridge_channel->chan) {
		struct ast_channel *real_parker = ast_channel_get_by_name(blind_transfer);

		if (real_parker) {
			ao2_cleanup(parker);
			parker = real_parker;
		}
	}

	pu = generate_parked_user(self->lot, bridge_channel->chan, parker,
		park_datastore->parker_dial_string, park_datastore->randomize, park_datastore->time_limit);
	if (!pu) {
		publish_parked_call_failure(bridge_channel->chan);
		return -1;
	}

	/* If a comeback_override was provided, set it for the parked user's comeback string. */
	if (park_datastore->comeback_override) {
		ast_copy_string(pu->comeback, park_datastore->comeback_override, sizeof(pu->comeback));
	}

	/* Generate ParkedCall Stasis Message */
	publish_parked_call(pu, PARKED_CALL);

	/* If the parkee and the parker are the same and silence_announce isn't set, play the announcement to the parkee */
	if (!strcmp(blind_transfer, ast_channel_name(bridge_channel->chan)) && !park_datastore->silence_announce) {
		char saynum_buf[16];

		snprintf(saynum_buf, sizeof(saynum_buf), "%u %u", 0, pu->parking_space);
		ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL);
	}

	/* Apply parking duration limits */
	parking_set_duration(bridge_channel->features, pu);

	/* Set this to the bridge pvt so that we don't have to refind the parked user associated with this bridge channel again. */
	bridge_channel->bridge_pvt = pu;

	ast_verb(3, "Parking '" COLORIZE_FMT "' in '" COLORIZE_FMT "' at space %d\n",
		COLORIZE(COLOR_BRMAGENTA, 0, ast_channel_name(bridge_channel->chan)),
		COLORIZE(COLOR_BRMAGENTA, 0, self->lot->name),
		pu->parking_space);

	parking_notify_metermaids(pu->parking_space, self->lot->cfg->parking_con, AST_DEVICE_INUSE);

	return 0;
}
Beispiel #17
0
static int ices_exec(struct ast_channel *chan, const char *data)
{
	int res = 0;
	int fds[2];
	int ms = -1;
	int pid = -1;
	int flags;
	struct ast_format oreadformat;
	struct ast_frame *f;
	char filename[256]="";
	char *c;

	ast_format_clear(&oreadformat);
	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
		return -1;
	}
	
	if (pipe(fds)) {
		ast_log(LOG_WARNING, "Unable to create pipe\n");
		return -1;
	}
	flags = fcntl(fds[1], F_GETFL);
	fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
	
	ast_stopstream(chan);

	if (ast_channel_state(chan) != AST_STATE_UP)
		res = ast_answer(chan);
		
	if (res) {
		close(fds[0]);
		close(fds[1]);
		ast_log(LOG_WARNING, "Answer failed!\n");
		return -1;
	}

	ast_format_copy(&oreadformat, ast_channel_readformat(chan));
	res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
	if (res < 0) {
		close(fds[0]);
		close(fds[1]);
		ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
		return -1;
	}
	if (((char *)data)[0] == '/')
		ast_copy_string(filename, (char *) data, sizeof(filename));
	else
		snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_CONFIG_DIR, (char *)data);
	/* Placeholder for options */		
	c = strchr(filename, '|');
	if (c)
		*c = '\0';	
	res = icesencode(filename, fds[0]);
	if (res >= 0) {
		pid = res;
		for (;;) {
			/* Wait for audio, and stream */
			ms = ast_waitfor(chan, -1);
			if (ms < 0) {
				ast_debug(1, "Hangup detected\n");
				res = -1;
				break;
			}
			f = ast_read(chan);
			if (!f) {
				ast_debug(1, "Null frame == hangup() detected\n");
				res = -1;
				break;
			}
			if (f->frametype == AST_FRAME_VOICE) {
				res = write(fds[1], f->data.ptr, f->datalen);
				if (res < 0) {
					if (errno != EAGAIN) {
						ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
						res = -1;
						ast_frfree(f);
						break;
					}
				}
			}
			ast_frfree(f);
		}
	}
	close(fds[0]);
	close(fds[1]);

	if (pid > -1)
		kill(pid, SIGKILL);
	if (!res && oreadformat.id)
		ast_set_read_format(chan, &oreadformat);

	return res;
}
Beispiel #18
0
static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
	int volfactor, const int fd, struct spy_dtmf_options *user_options,
	const char *mygroup, const char *myenforced, const char *spec, const char *exten,
	const char *context, const char *mailbox, const char *name_context)
{
	char nameprefix[AST_NAME_STRLEN];
	char exitcontext[AST_MAX_CONTEXT] = "";
	signed char zero_volume = 0;
	int waitms;
	int res;
	int num_spyed_upon = 1;
	struct ast_channel_iterator *iter = NULL;

	if (ast_test_flag(flags, OPTION_EXIT)) {
		const char *c;
		ast_channel_lock(chan);
		if ((c = pbx_builtin_getvar_helper(chan, "SPY_EXIT_CONTEXT"))) {
			ast_copy_string(exitcontext, c, sizeof(exitcontext));
		} else if (!ast_strlen_zero(ast_channel_macrocontext(chan))) {
			ast_copy_string(exitcontext, ast_channel_macrocontext(chan), sizeof(exitcontext));
		} else {
			ast_copy_string(exitcontext, ast_channel_context(chan), sizeof(exitcontext));
		}
		ast_channel_unlock(chan);
	}

	if (ast_channel_state(chan) != AST_STATE_UP)
		ast_answer(chan);

	ast_set_flag(ast_channel_flags(chan), AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */

	waitms = 100;

	for (;;) {
		struct ast_autochan *autochan = NULL, *next_autochan = NULL;
		struct ast_channel *prev = NULL;

		if (!ast_test_flag(flags, OPTION_QUIET) && num_spyed_upon) {
			res = ast_streamfile(chan, "beep", ast_channel_language(chan));
			if (!res)
				res = ast_waitstream(chan, "");
			else if (res < 0) {
				ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);
				break;
			}
			if (!ast_strlen_zero(exitcontext)) {
				char tmp[2];
				tmp[0] = res;
				tmp[1] = '\0';
				if (!ast_goto_if_exists(chan, exitcontext, tmp, 1))
					goto exit;
				else
					ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
			}
		}

		/* Set up the iterator we'll be using during this call */
		if (!ast_strlen_zero(spec)) {
			iter = ast_channel_iterator_by_name_new(spec, strlen(spec));
		} else if (!ast_strlen_zero(exten)) {
			iter = ast_channel_iterator_by_exten_new(exten, context);
		} else {
			iter = ast_channel_iterator_all_new();
		}

		if (!iter) {
			res = -1;
			goto exit;
		}

		res = ast_waitfordigit(chan, waitms);
		if (res < 0) {
			iter = ast_channel_iterator_destroy(iter);
			ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);
			break;
		}
		if (!ast_strlen_zero(exitcontext)) {
			char tmp[2];
			tmp[0] = res;
			tmp[1] = '\0';
			if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) {
				iter = ast_channel_iterator_destroy(iter);
				goto exit;
			} else {
				ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
			}
		}

		/* reset for the next loop around, unless overridden later */
		waitms = 100;
		num_spyed_upon = 0;

		for (autochan = next_channel(iter, autochan, chan);
		     autochan;
			 prev = autochan->chan, ast_autochan_destroy(autochan),
		     autochan = next_autochan ? next_autochan : 
				next_channel(iter, autochan, chan), next_autochan = NULL) {
			int igrp = !mygroup;
			int ienf = !myenforced;

			if (autochan->chan == prev) {
				ast_autochan_destroy(autochan);
				break;
			}

			if (ast_check_hangup(chan)) {
				ast_autochan_destroy(autochan);
				break;
			}

			if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_bridged_channel(autochan->chan)) {
				continue;
			}

			if (ast_check_hangup(autochan->chan) || ast_test_flag(ast_channel_flags(autochan->chan), AST_FLAG_SPYING)) {
				continue;
			}

			if (mygroup) {
				int num_groups = 0;
				int num_mygroups = 0;
				char dup_group[512];
				char dup_mygroup[512];
				char *groups[NUM_SPYGROUPS];
				char *mygroups[NUM_SPYGROUPS];
				const char *group = NULL;
				int x;
				int y;
				ast_copy_string(dup_mygroup, mygroup, sizeof(dup_mygroup));
				num_mygroups = ast_app_separate_args(dup_mygroup, ':', mygroups,
					ARRAY_LEN(mygroups));

				/* Before dahdi scan was part of chanspy, it would use the "GROUP" variable 
				 * rather than "SPYGROUP", this check is done to preserve expected behavior */
				if (ast_test_flag(flags, OPTION_DAHDI_SCAN)) {
					group = pbx_builtin_getvar_helper(autochan->chan, "GROUP");
				} else {
					group = pbx_builtin_getvar_helper(autochan->chan, "SPYGROUP");
				}

				if (!ast_strlen_zero(group)) {
					ast_copy_string(dup_group, group, sizeof(dup_group));
					num_groups = ast_app_separate_args(dup_group, ':', groups,
						ARRAY_LEN(groups));
				}

				for (y = 0; y < num_mygroups; y++) {
					for (x = 0; x < num_groups; x++) {
						if (!strcmp(mygroups[y], groups[x])) {
							igrp = 1;
							break;
						}
					}
				}
			}

			if (!igrp) {
				continue;
			}
			if (myenforced) {
				char ext[AST_CHANNEL_NAME + 3];
				char buffer[512];
				char *end;

				snprintf(buffer, sizeof(buffer) - 1, ":%s:", myenforced);

				ast_copy_string(ext + 1, ast_channel_name(autochan->chan), sizeof(ext) - 1);
				if ((end = strchr(ext, '-'))) {
					*end++ = ':';
					*end = '\0';
				}

				ext[0] = ':';

				if (strcasestr(buffer, ext)) {
					ienf = 1;
				}
			}

			if (!ienf) {
				continue;
			}

			if (!ast_test_flag(flags, OPTION_QUIET)) {
				char peer_name[AST_NAME_STRLEN + 5];
				char *ptr, *s;

				strcpy(peer_name, "spy-");
				strncat(peer_name, ast_channel_name(autochan->chan), AST_NAME_STRLEN - 4 - 1);
				if ((ptr = strchr(peer_name, '/'))) {
					*ptr++ = '\0';
					for (s = peer_name; s < ptr; s++) {
						*s = tolower(*s);
					}
					if ((s = strchr(ptr, '-'))) {
						*s = '\0';
					}
				}

				if (ast_test_flag(flags, OPTION_NAME)) {
					const char *local_context = S_OR(name_context, "default");
					const char *local_mailbox = S_OR(mailbox, ptr);
					if (local_mailbox) {
						res = ast_app_sayname(chan, local_mailbox, local_context);
					} else {
						res = -1;
					}
				}
				if (!ast_test_flag(flags, OPTION_NAME) || res < 0) {
					int num;
					if (!ast_test_flag(flags, OPTION_NOTECH)) {
						if (ast_fileexists(peer_name, NULL, NULL) > 0) {
							res = ast_streamfile(chan, peer_name, ast_channel_language(chan));
							if (!res) {
								res = ast_waitstream(chan, "");
							}
							if (res) {
								ast_autochan_destroy(autochan);
								break;
							}
						} else {
							res = ast_say_character_str(chan, peer_name, "", ast_channel_language(chan));
						}
					}
					if (ptr && (num = atoi(ptr))) {
						ast_say_digits(chan, num, "", ast_channel_language(chan));
					}
				}
			}

			res = channel_spy(chan, autochan, &volfactor, fd, user_options, flags, exitcontext);
			num_spyed_upon++;

			if (res == -1) {
				ast_autochan_destroy(autochan);
				iter = ast_channel_iterator_destroy(iter);
				goto exit;
			} else if (res == -2) {
				res = 0;
				ast_autochan_destroy(autochan);
				iter = ast_channel_iterator_destroy(iter);
				goto exit;
			} else if (res > 1 && spec) {
				struct ast_channel *next;

				snprintf(nameprefix, AST_NAME_STRLEN, "%s/%d", spec, res);

				if ((next = ast_channel_get_by_name_prefix(nameprefix, strlen(nameprefix)))) {
					next_autochan = ast_autochan_setup(next);
					next = ast_channel_unref(next);
				} else {
					/* stay on this channel, if it is still valid */
					if (!ast_check_hangup(autochan->chan)) {
						next_autochan = ast_autochan_setup(autochan->chan);
					} else {
						/* the channel is gone */
						next_autochan = NULL;
					}
				}
			} else if (res == 0 && ast_test_flag(flags, OPTION_EXITONHANGUP)) {
				ast_autochan_destroy(autochan);
				iter = ast_channel_iterator_destroy(iter);
				goto exit;
			}
		}

		iter = ast_channel_iterator_destroy(iter);

		if (res == -1 || ast_check_hangup(chan))
			break;
		if (ast_test_flag(flags, OPTION_STOP) && !next_autochan) {
			break;
		}
	}
exit:

	ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);

	ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);

	return res;
}
Beispiel #19
0
static int func_channel_read(struct ast_channel *chan, const char *function,
                             char *data, char *buf, size_t len)
{
    int ret = 0;
    char tmp[512];
    struct ast_format_cap *tmpcap;

    if (!strcasecmp(data, "audionativeformat")) {
        if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_AUDIO))) {
            ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
            tmpcap = ast_format_cap_destroy(tmpcap);
        }
    } else if (!strcasecmp(data, "videonativeformat")) {
        if ((tmpcap = ast_format_cap_get_type(ast_channel_nativeformats(chan), AST_FORMAT_TYPE_VIDEO))) {
            ast_copy_string(buf, ast_getformatname_multiple(tmp, sizeof(tmp), tmpcap), len);
            tmpcap = ast_format_cap_destroy(tmpcap);
        }
    } else if (!strcasecmp(data, "audioreadformat")) {
        ast_copy_string(buf, ast_getformatname(ast_channel_readformat(chan)), len);
    } else if (!strcasecmp(data, "audiowriteformat")) {
        ast_copy_string(buf, ast_getformatname(ast_channel_writeformat(chan)), len);
#ifdef CHANNEL_TRACE
    } else if (!strcasecmp(data, "trace")) {
        ast_channel_lock(chan);
        ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
        ast_channel_unlock(chan);
#endif
    } else if (!strcasecmp(data, "tonezone") && ast_channel_zone(chan))
        locked_copy_string(chan, buf, ast_channel_zone(chan)->country, len);
    else if (!strcasecmp(data, "language"))
        locked_copy_string(chan, buf, ast_channel_language(chan), len);
    else if (!strcasecmp(data, "musicclass"))
        locked_copy_string(chan, buf, ast_channel_musicclass(chan), len);
    else if (!strcasecmp(data, "name")) {
        locked_copy_string(chan, buf, ast_channel_name(chan), len);
    } else if (!strcasecmp(data, "parkinglot"))
        locked_copy_string(chan, buf, ast_channel_parkinglot(chan), len);
    else if (!strcasecmp(data, "state"))
        locked_copy_string(chan, buf, ast_state2str(ast_channel_state(chan)), len);
    else if (!strcasecmp(data, "channeltype"))
        locked_copy_string(chan, buf, ast_channel_tech(chan)->type, len);
    else if (!strcasecmp(data, "accountcode"))
        locked_copy_string(chan, buf, ast_channel_accountcode(chan), len);
    else if (!strcasecmp(data, "checkhangup")) {
        ast_channel_lock(chan);
        ast_copy_string(buf, ast_check_hangup(chan) ? "1" : "0", len);
        ast_channel_unlock(chan);
    } else if (!strcasecmp(data, "peeraccount"))
        locked_copy_string(chan, buf, ast_channel_peeraccount(chan), len);
    else if (!strcasecmp(data, "hangupsource"))
        locked_copy_string(chan, buf, ast_channel_hangupsource(chan), len);
    else if (!strcasecmp(data, "appname") && ast_channel_appl(chan))
        locked_copy_string(chan, buf, ast_channel_appl(chan), len);
    else if (!strcasecmp(data, "appdata") && ast_channel_data(chan))
        locked_copy_string(chan, buf, ast_channel_data(chan), len);
    else if (!strcasecmp(data, "exten") && ast_channel_data(chan))
        locked_copy_string(chan, buf, ast_channel_exten(chan), len);
    else if (!strcasecmp(data, "context") && ast_channel_data(chan))
        locked_copy_string(chan, buf, ast_channel_context(chan), len);
    else if (!strcasecmp(data, "userfield") && ast_channel_data(chan))
        locked_copy_string(chan, buf, ast_channel_userfield(chan), len);
    else if (!strcasecmp(data, "channame") && ast_channel_data(chan))
        locked_copy_string(chan, buf, ast_channel_name(chan), len);
    else if (!strcasecmp(data, "linkedid")) {
        ast_channel_lock(chan);
        if (ast_strlen_zero(ast_channel_linkedid(chan))) {
            /* fall back on the channel's uniqueid if linkedid is unset */
            ast_copy_string(buf, ast_channel_uniqueid(chan), len);
        }
        else {
            ast_copy_string(buf, ast_channel_linkedid(chan), len);
        }
        ast_channel_unlock(chan);
    } else if (!strcasecmp(data, "peer")) {
        struct ast_channel *p;
        ast_channel_lock(chan);
        p = ast_bridged_channel(chan);
        if (p || ast_channel_tech(chan) || ast_channel_cdr(chan)) /* dummy channel? if so, we hid the peer name in the language */
            ast_copy_string(buf, (p ? ast_channel_name(p) : ""), len);
        else {
            /* a dummy channel can still pass along bridged peer info via
                           the BRIDGEPEER variable */
            const char *pname = pbx_builtin_getvar_helper(chan, "BRIDGEPEER");
            if (!ast_strlen_zero(pname))
                ast_copy_string(buf, pname, len); /* a horrible kludge, but... how else? */
            else
                buf[0] = 0;
        }
        ast_channel_unlock(chan);
    } else if (!strcasecmp(data, "uniqueid")) {
        locked_copy_string(chan, buf, ast_channel_uniqueid(chan), len);
    } else if (!strcasecmp(data, "transfercapability")) {
        locked_copy_string(chan, buf, transfercapability_table[ast_channel_transfercapability(chan) & 0x1f], len);
    } else if (!strcasecmp(data, "callgroup")) {
        char groupbuf[256];
        locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_callgroup(chan)), len);
    } else if (!strcasecmp(data, "pickupgroup")) {
        char groupbuf[256];
        locked_copy_string(chan, buf,  ast_print_group(groupbuf, sizeof(groupbuf), ast_channel_pickupgroup(chan)), len);
    } else if (!strcasecmp(data, "amaflags")) {
        char amabuf[256];
        snprintf(amabuf,sizeof(amabuf), "%d", ast_channel_amaflags(chan));
        locked_copy_string(chan, buf, amabuf, len);
    } else if (!strncasecmp(data, "secure_bridge_", 14)) {
        struct ast_datastore *ds;
        ast_channel_lock(chan);
        if ((ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
            struct ast_secure_call_store *encrypt = ds->data;
            if (!strcasecmp(data, "secure_bridge_signaling")) {
                snprintf(buf, len, "%s", encrypt->signaling ? "1" : "");
            } else if (!strcasecmp(data, "secure_bridge_media")) {
                snprintf(buf, len, "%s", encrypt->media ? "1" : "");
            }
        }
        ast_channel_unlock(chan);
    } else if (!ast_channel_tech(chan) || !ast_channel_tech(chan)->func_channel_read || ast_channel_tech(chan)->func_channel_read(chan, function, data, buf, len)) {
        ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data);
        ret = -1;
    }

    return ret;
}
Beispiel #20
0
static int testserver_exec(struct ast_channel *chan, const char *data)
{
    int res = 0;
    char testid[80]="";
    char fn[80];
    FILE *f;
    if (ast_channel_state(chan) != AST_STATE_UP)
        res = ast_answer(chan);
    /* Read version */
    ast_debug(1, "Read client version\n");
    if (!res)
        res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
    if (res > 0)
        res = 0;

    ast_debug(1, "client version: %s\n", testid);
    ast_debug(1, "Transmit server version\n");

    res = ast_safe_sleep(chan, 1000);
    if (!res)
        res = ast_dtmf_stream(chan, NULL, "8378*1#", 0, 0);
    if (res > 0)
        res = 0;

    if (!res)
        res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
    ast_debug(1, "read test identifier: %s\n", testid);
    /* Check for sneakyness */
    if (strchr(testid, '/'))
        res = -1;
    if ((res >=0) && (!ast_strlen_zero(testid))) {
        /* Got a Test ID!  Whoo hoo! */
        /* Make the directory to hold the test results in case it's not there */
        snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
        ast_mkdir(fn, 0777);
        snprintf(fn, sizeof(fn), "%s/testresults/%s-server.txt", ast_config_AST_LOG_DIR, testid);
        if ((f = fopen(fn, "w+"))) {
            setlinebuf(f);
            fprintf(f, "SERVERCHAN:    %s\n", ast_channel_name(chan));
            fprintf(f, "SERVERTEST ID: %s\n", testid);
            fprintf(f, "ANSWER:        PASS\n");
            ast_debug(1, "Processing Test ID '%s'\n", testid);
            res = ast_safe_sleep(chan, 1000);
            if (!res) {
                /* Step 1: Send "1" */
                ast_debug(1, "TestServer: 1.  Send DTMF 1\n");
                res = ast_dtmf_stream(chan, NULL, "1", 0,0 );
                fprintf(f, "SEND DTMF 1:   %s\n", (res < 0) ? "FAIL" : "PASS");
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 2: Wait for "2" */
                ast_debug(1, "TestServer: 2.  Wait DTMF 2\n");
                res = ast_waitfordigit(chan, 3000);
                fprintf(f, "WAIT DTMF 2:   %s\n", (res != '2') ? "FAIL" : "PASS");
                if (res == '2')
                    res = 0;
                else
                    res = -1;
            }
            if (!res) {
                /* Step 3: Measure noise */
                ast_debug(1, "TestServer: 3.  Measure noise\n");
                res = measurenoise(chan, 6000, "TestServer");
                fprintf(f, "MEASURENOISE:  %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 4: Send "4" */
                ast_debug(1, "TestServer: 4.  Send DTMF 4\n");
                res = ast_dtmf_stream(chan, NULL, "4", 0, 0);
                fprintf(f, "SEND DTMF 4:   %s\n", (res < 0) ? "FAIL" : "PASS");
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 5: Wait one second */
                ast_debug(1, "TestServer: 5.  Wait one second\n");
                res = ast_safe_sleep(chan, 1000);
                fprintf(f, "WAIT 1 SEC:    %s\n", (res < 0) ? "FAIL" : "PASS");
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 6: Measure noise */
                ast_debug(1, "TestServer: 6.  Measure tone\n");
                res = measurenoise(chan, 4000, "TestServer");
                fprintf(f, "MEASURETONE:   %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 7: Send "5" */
                ast_debug(1, "TestServer: 7.  Send DTMF 5\n");
                res = ast_dtmf_stream(chan, NULL, "5", 0, 0);
                fprintf(f, "SEND DTMF 5:   %s\n", (res < 0) ? "FAIL" : "PASS");
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 8: Transmit tone noise */
                ast_debug(1, "TestServer: 8.  Transmit tone\n");
                res = sendnoise(chan, 6000);
                fprintf(f, "SENDTONE:      %s\n", (res < 0) ? "FAIL" : "PASS");
            }

            if (!res || (res == '7')) {
                /* Step 9: Wait for "7" */
                ast_debug(1, "TestServer: 9.  Wait DTMF 7\n");
                if (!res)
                    res = ast_waitfordigit(chan, 3000);
                fprintf(f, "WAIT DTMF 7:   %s\n", (res != '7') ? "FAIL" : "PASS");
                if (res == '7')
                    res = 0;
                else
                    res = -1;
            }
            if (!res) {
                res = ast_safe_sleep(chan, 1000);
            }
            if (!res) {
                /* Step 10: Send "8" */
                ast_debug(1, "TestServer: 10.  Send DTMF 8\n");
                res = ast_dtmf_stream(chan, NULL, "8", 0, 0);
                fprintf(f, "SEND DTMF 8:   %s\n", (res < 0) ? "FAIL" : "PASS");
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 11: Wait for hangup to arrive! */
                ast_debug(1, "TestServer: 11.  Waiting for hangup\n");
                res = ast_safe_sleep(chan, 10000);
                fprintf(f, "WAIT HANGUP:   %s\n", (res < 0) ? "PASS" : "FAIL");
            }

            ast_log(LOG_NOTICE, "-- TEST COMPLETE--\n");
            fprintf(f, "-- END TEST--\n");
            fclose(f);
            res = -1;
        } else
            res = -1;
    } else {
        ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", ast_channel_name(chan));
        res = -1;
    }
    return res;
}
Beispiel #21
0
struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
{
	struct ast_channel_snapshot *snapshot;
	struct ast_bridge *bridge;
	char nativeformats[256];
	struct ast_str *write_transpath = ast_str_alloca(256);
	struct ast_str *read_transpath = ast_str_alloca(256);
	struct ast_party_id effective_connected_id;
	struct ast_callid *callid;

	/* no snapshots for dummy channels */
	if (!ast_channel_tech(chan)) {
		return NULL;
	}

	snapshot = ao2_alloc(sizeof(*snapshot), channel_snapshot_dtor);
	if (!snapshot || ast_string_field_init(snapshot, 1024)) {
		ao2_cleanup(snapshot);
		return NULL;
	}

	ast_string_field_set(snapshot, name, ast_channel_name(chan));
	ast_string_field_set(snapshot, type, ast_channel_tech(chan)->type);
	ast_string_field_set(snapshot, accountcode, ast_channel_accountcode(chan));
	ast_string_field_set(snapshot, peeraccount, ast_channel_peeraccount(chan));
	ast_string_field_set(snapshot, userfield, ast_channel_userfield(chan));
	ast_string_field_set(snapshot, uniqueid, ast_channel_uniqueid(chan));
	ast_string_field_set(snapshot, linkedid, ast_channel_linkedid(chan));
	ast_string_field_set(snapshot, hangupsource, ast_channel_hangupsource(chan));
	if (ast_channel_appl(chan)) {
		ast_string_field_set(snapshot, appl, ast_channel_appl(chan));
	}
	if (ast_channel_data(chan)) {
		ast_string_field_set(snapshot, data, ast_channel_data(chan));
	}
	ast_string_field_set(snapshot, context, ast_channel_context(chan));
	ast_string_field_set(snapshot, exten, ast_channel_exten(chan));

	ast_string_field_set(snapshot, caller_name,
		S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""));
	ast_string_field_set(snapshot, caller_number,
		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""));
	ast_string_field_set(snapshot, caller_dnid, S_OR(ast_channel_dialed(chan)->number.str, ""));
	ast_string_field_set(snapshot, caller_subaddr,
		S_COR(ast_channel_caller(chan)->id.subaddress.valid, ast_channel_caller(chan)->id.subaddress.str, ""));
	ast_string_field_set(snapshot, dialed_subaddr,
		S_COR(ast_channel_dialed(chan)->subaddress.valid, ast_channel_dialed(chan)->subaddress.str, ""));
	ast_string_field_set(snapshot, caller_ani,
		S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, ""));
	ast_string_field_set(snapshot, caller_rdnis,
		S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, ""));
	ast_string_field_set(snapshot, caller_dnid,
		S_OR(ast_channel_dialed(chan)->number.str, ""));

	ast_string_field_set(snapshot, connected_name,
		S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, ""));
	ast_string_field_set(snapshot, connected_number,
		S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, ""));
	ast_string_field_set(snapshot, language, ast_channel_language(chan));

	if ((bridge = ast_channel_get_bridge(chan))) {
		ast_string_field_set(snapshot, bridgeid, bridge->uniqueid);
		ao2_cleanup(bridge);
	}

	ast_string_field_set(snapshot, nativeformats, ast_getformatname_multiple(nativeformats, sizeof(nativeformats),
		ast_channel_nativeformats(chan)));
	ast_string_field_set(snapshot, readformat, ast_getformatname(ast_channel_readformat(chan)));
	ast_string_field_set(snapshot, writeformat, ast_getformatname(ast_channel_writeformat(chan)));
	ast_string_field_set(snapshot, writetrans, ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath));
	ast_string_field_set(snapshot, readtrans, ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath));

	effective_connected_id = ast_channel_connected_effective_id(chan);
	ast_string_field_set(snapshot, effective_name,
		S_COR(effective_connected_id.name.valid, effective_connected_id.name.str, ""));
	ast_string_field_set(snapshot, effective_number,
		S_COR(effective_connected_id.number.valid, effective_connected_id.number.str, ""));

	if ((callid = ast_channel_callid(chan))) {
		ast_callid_strnprint(snapshot->callid, sizeof(snapshot->callid), callid);
		ast_callid_unref(callid);
	}

	snapshot->creationtime = ast_channel_creationtime(chan);
	snapshot->hanguptime = *(ast_channel_whentohangup(chan));
	snapshot->state = ast_channel_state(chan);
	snapshot->priority = ast_channel_priority(chan);
	snapshot->amaflags = ast_channel_amaflags(chan);
	snapshot->hangupcause = ast_channel_hangupcause(chan);
	ast_copy_flags(&snapshot->flags, ast_channel_flags(chan), 0xFFFFFFFF);
	snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
	snapshot->callgroup = ast_channel_callgroup(chan);
	snapshot->pickupgroup = ast_channel_pickupgroup(chan);
	ast_set_flag(&snapshot->softhangup_flags, ast_channel_softhangup_internal_flag(chan));

	snapshot->manager_vars = ast_channel_get_manager_vars(chan);
	snapshot->channel_vars = ast_channel_get_vars(chan);
	snapshot->tech_properties = ast_channel_tech(chan)->properties;

	return snapshot;
}
Beispiel #22
0
static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *length,
									int exact, size_t *var_len, WriteMethod **write_method)
{
	static unsigned long long_ret;
	static u_char bits_ret[2];
	static char string_ret[256];
	struct ast_channel *chan, *bridge;
	struct timeval tval;
	u_char *ret = NULL;
	int i, bit;
	struct ast_str *out = ast_str_alloca(2048);
	struct ast_channel_iterator *iter;

	if (header_simple_table(vp, name, length, exact, var_len, write_method, ast_active_channels()))
		return NULL;

	i = name[*length - 1] - 1;

	if (!(iter = ast_channel_iterator_all_new())) {
		return NULL;
	}

	while ((chan = ast_channel_iterator_next(iter)) && i) {
		ast_channel_unref(chan);
		i--;
	}

	iter = ast_channel_iterator_destroy(iter);

	if (chan == NULL) {
		return NULL;
	}

	*var_len = sizeof(long_ret);

	ast_channel_lock(chan);

	switch (vp->magic) {
	case ASTCHANINDEX:
		long_ret = name[*length - 1];
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANNAME:
		if (!ast_strlen_zero(ast_channel_name(chan))) {
			ast_copy_string(string_ret, ast_channel_name(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANLANGUAGE:
		if (!ast_strlen_zero(ast_channel_language(chan))) {
			ast_copy_string(string_ret, ast_channel_language(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANTYPE:
		ast_copy_string(string_ret, ast_channel_tech(chan)->type, sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANMUSICCLASS:
		if (!ast_strlen_zero(ast_channel_musicclass(chan))) {
			ast_copy_string(string_ret, ast_channel_musicclass(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANBRIDGE:
		if ((bridge = ast_bridged_channel(chan)) != NULL) {
			ast_copy_string(string_ret, ast_channel_name(bridge), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANMASQ:
		if (ast_channel_masq(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masq(chan)))) {
			ast_copy_string(string_ret, ast_channel_name(ast_channel_masq(chan)), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANMASQR:
		if (ast_channel_masqr(chan) && !ast_strlen_zero(ast_channel_name(ast_channel_masqr(chan)))) {
			ast_copy_string(string_ret, ast_channel_name(ast_channel_masqr(chan)), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANWHENHANGUP:
		if (!ast_tvzero(*ast_channel_whentohangup(chan))) {
			gettimeofday(&tval, NULL);
			long_ret = difftime(ast_channel_whentohangup(chan)->tv_sec, tval.tv_sec) * 100 - tval.tv_usec / 10000;
			ret= (u_char *)&long_ret;
		}
		break;
	case ASTCHANAPP:
		if (ast_channel_appl(chan)) {
			ast_copy_string(string_ret, ast_channel_appl(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANDATA:
		if (ast_channel_data(chan)) {
			ast_copy_string(string_ret, ast_channel_data(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCONTEXT:
		ast_copy_string(string_ret, ast_channel_context(chan), sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANMACROCONTEXT:
		ast_copy_string(string_ret, ast_channel_macrocontext(chan), sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANMACROEXTEN:
		ast_copy_string(string_ret, ast_channel_macroexten(chan), sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANMACROPRI:
		long_ret = ast_channel_macropriority(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANEXTEN:
		ast_copy_string(string_ret, ast_channel_exten(chan), sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANPRI:
		long_ret = ast_channel_priority(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANACCOUNTCODE:
		if (!ast_strlen_zero(ast_channel_accountcode(chan))) {
			ast_copy_string(string_ret, ast_channel_accountcode(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANFORWARDTO:
		if (!ast_strlen_zero(ast_channel_call_forward(chan))) {
			ast_copy_string(string_ret, ast_channel_call_forward(chan), sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANUNIQUEID:
		ast_copy_string(string_ret, ast_channel_uniqueid(chan), sizeof(string_ret));
		*var_len = strlen(string_ret);
		ret = (u_char *)string_ret;
		break;
	case ASTCHANCALLGROUP:
		long_ret = ast_channel_callgroup(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANPICKUPGROUP:
		long_ret = ast_channel_pickupgroup(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANSTATE:
		long_ret = ast_channel_state(chan) & 0xffff;
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANMUTED:
		long_ret = ast_channel_state(chan) & AST_STATE_MUTE ? 1 : 2;
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANRINGS:
		long_ret = ast_channel_rings(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANCIDDNID:
		if (ast_channel_dialed(chan)->number.str) {
			ast_copy_string(string_ret, ast_channel_dialed(chan)->number.str, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCIDNUM:
		if (ast_channel_caller(chan)->id.number.valid && ast_channel_caller(chan)->id.number.str) {
			ast_copy_string(string_ret, ast_channel_caller(chan)->id.number.str, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCIDNAME:
		if (ast_channel_caller(chan)->id.name.valid && ast_channel_caller(chan)->id.name.str) {
			ast_copy_string(string_ret, ast_channel_caller(chan)->id.name.str, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCIDANI:
		if (ast_channel_caller(chan)->ani.number.valid && ast_channel_caller(chan)->ani.number.str) {
			ast_copy_string(string_ret, ast_channel_caller(chan)->ani.number.str, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCIDRDNIS:
		if (ast_channel_redirecting(chan)->from.number.valid && ast_channel_redirecting(chan)->from.number.str) {
			ast_copy_string(string_ret, ast_channel_redirecting(chan)->from.number.str, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANCIDPRES:
		long_ret = ast_party_id_presentation(&ast_channel_caller(chan)->id);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANCIDANI2:
		long_ret = ast_channel_caller(chan)->ani2;
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANCIDTON:
		long_ret = ast_channel_caller(chan)->id.number.plan;
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANCIDTNS:
		long_ret = ast_channel_dialed(chan)->transit_network_select;
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANAMAFLAGS:
		long_ret = ast_channel_amaflags(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANADSI:
		long_ret = ast_channel_adsicpe(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANTONEZONE:
		if (ast_channel_zone(chan)) {
			ast_copy_string(string_ret, ast_channel_zone(chan)->country, sizeof(string_ret));
			*var_len = strlen(string_ret);
			ret = (u_char *)string_ret;
		}
		break;
	case ASTCHANHANGUPCAUSE:
		long_ret = ast_channel_hangupcause(chan);
		ret = (u_char *)&long_ret;
		break;
	case ASTCHANVARIABLES:
		if (pbx_builtin_serialize_variables(chan, &out)) {
			*var_len = ast_str_strlen(out);
			ret = (u_char *)ast_str_buffer(out);
		}
		break;
	case ASTCHANFLAGS:
		bits_ret[0] = 0;
		for (bit = 0; bit < 8; bit++)
			bits_ret[0] |= ((ast_channel_flags(chan)->flags & (1 << bit)) >> bit) << (7 - bit);
		bits_ret[1] = 0;
		for (bit = 0; bit < 8; bit++)
			bits_ret[1] |= (((ast_channel_flags(chan)->flags >> 8) & (1 << bit)) >> bit) << (7 - bit);
		*var_len = 2;
		ret = bits_ret;
		break;
	case ASTCHANTRANSFERCAP:
		long_ret = ast_channel_transfercapability(chan);
		ret = (u_char *)&long_ret;
	default:
		break;
	}

	ast_channel_unlock(chan);
	chan = ast_channel_unref(chan);

	return ret;
}
Beispiel #23
0
static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
{
	long elapsed_seconds = 0;
	int hour = 0, min = 0, sec = 0;
	struct ast_str *format_buf = ast_str_alloca(64);
	char cgrp[256];
	char pgrp[256];
	struct ast_str *write_transpath = ast_str_alloca(256);
	struct ast_str *read_transpath = ast_str_alloca(256);
	struct ast_bridge *bridge;

	memset(buf, 0, size);
	if (!c)
		return 0;

	elapsed_seconds = ast_channel_get_duration(c);
	hour = elapsed_seconds / 3600;
	min = (elapsed_seconds % 3600) / 60;
	sec = elapsed_seconds % 60;

	ast_channel_lock(c);
	bridge = ast_channel_get_bridge(c);
	ast_channel_unlock(c);

	snprintf(buf,size,
		"Name=               %s\n"
		"Type=               %s\n"
		"UniqueID=           %s\n"
		"LinkedID=           %s\n"
		"CallerIDNum=        %s\n"
		"CallerIDName=       %s\n"
		"ConnectedLineIDNum= %s\n"
		"ConnectedLineIDName=%s\n"
		"DNIDDigits=         %s\n"
		"RDNIS=              %s\n"
		"Parkinglot=         %s\n"
		"Language=           %s\n"
		"State=              %s (%u)\n"
		"Rings=              %d\n"
		"NativeFormat=       %s\n"
		"WriteFormat=        %s\n"
		"ReadFormat=         %s\n"
		"RawWriteFormat=     %s\n"
		"RawReadFormat=      %s\n"
		"WriteTranscode=     %s %s\n"
		"ReadTranscode=      %s %s\n"
		"1stFileDescriptor=  %d\n"
		"Framesin=           %u %s\n"
		"Framesout=          %u %s\n"
		"TimetoHangup=       %ld\n"
		"ElapsedTime=        %dh%dm%ds\n"
		"BridgeID=           %s\n"
		"Context=            %s\n"
		"Extension=          %s\n"
		"Priority=           %d\n"
		"CallGroup=          %s\n"
		"PickupGroup=        %s\n"
		"Application=        %s\n"
		"Data=               %s\n"
		"Blocking_in=        %s\n",
		ast_channel_name(c),
		ast_channel_tech(c)->type,
		ast_channel_uniqueid(c),
		ast_channel_linkedid(c),
		S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, "(N/A)"),
		S_COR(ast_channel_caller(c)->id.name.valid, ast_channel_caller(c)->id.name.str, "(N/A)"),
		S_COR(ast_channel_connected(c)->id.number.valid, ast_channel_connected(c)->id.number.str, "(N/A)"),
		S_COR(ast_channel_connected(c)->id.name.valid, ast_channel_connected(c)->id.name.str, "(N/A)"),
		S_OR(ast_channel_dialed(c)->number.str, "(N/A)"),
		S_COR(ast_channel_redirecting(c)->from.number.valid, ast_channel_redirecting(c)->from.number.str, "(N/A)"),
		ast_channel_parkinglot(c),
		ast_channel_language(c),
		ast_state2str(ast_channel_state(c)),
		ast_channel_state(c),
		ast_channel_rings(c),
		ast_format_cap_get_names(ast_channel_nativeformats(c), &format_buf),
		ast_format_get_name(ast_channel_writeformat(c)),
		ast_format_get_name(ast_channel_readformat(c)),
		ast_format_get_name(ast_channel_rawwriteformat(c)),
		ast_format_get_name(ast_channel_rawreadformat(c)),
		ast_channel_writetrans(c) ? "Yes" : "No",
		ast_translate_path_to_str(ast_channel_writetrans(c), &write_transpath),
		ast_channel_readtrans(c) ? "Yes" : "No",
		ast_translate_path_to_str(ast_channel_readtrans(c), &read_transpath),
		ast_channel_fd(c, 0),
		ast_channel_fin(c) & ~DEBUGCHAN_FLAG, (ast_channel_fin(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
		ast_channel_fout(c) & ~DEBUGCHAN_FLAG, (ast_channel_fout(c) & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
		(long)ast_channel_whentohangup(c)->tv_sec,
		hour,
		min,
		sec,
		bridge ? bridge->uniqueid : "(Not bridged)",
		ast_channel_context(c),
		ast_channel_exten(c),
		ast_channel_priority(c),
		ast_print_group(cgrp, sizeof(cgrp), ast_channel_callgroup(c)),
		ast_print_group(pgrp, sizeof(pgrp), ast_channel_pickupgroup(c)),
		ast_channel_appl(c) ? ast_channel_appl(c) : "(N/A)",
		ast_channel_data(c) ? S_OR(ast_channel_data(c), "(Empty)") : "(None)",
		(ast_test_flag(ast_channel_flags(c), AST_FLAG_BLOCKING) ? ast_channel_blockproc(c) : "(Not Blocking)"));

	ao2_cleanup(bridge);
	return 0;
}
Beispiel #24
0
static int pre_bridge_setup(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config,
		struct ast_bridge_features *chan_features, struct ast_bridge_features *peer_features)
{
	int res;

	set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
	add_features_datastores(chan, peer, config);

	/*
	 * This is an interesting case.  One example is if a ringing
	 * channel gets redirected to an extension that picks up a
	 * parked call.  This will make sure that the call taken out of
	 * parking gets told that the channel it just got bridged to is
	 * still ringing.
	 */
	if (ast_channel_state(chan) == AST_STATE_RINGING
		&& ast_channel_visible_indication(peer) != AST_CONTROL_RINGING) {
		ast_indicate(peer, AST_CONTROL_RINGING);
	}

	bridge_check_monitor(chan, peer);

	set_config_flags(chan, config);

	/* Answer if need be */
	if (ast_channel_state(chan) != AST_STATE_UP) {
		if (ast_raw_answer(chan)) {
			return -1;
		}
	}

#ifdef FOR_DEBUG
	/* show the two channels and cdrs involved in the bridge for debug & devel purposes */
	ast_channel_log("Pre-bridge CHAN Channel info", chan);
	ast_channel_log("Pre-bridge PEER Channel info", peer);
#endif

	res = 0;
	ast_channel_lock(chan);
	ast_max_forwards_reset(chan);
	res |= ast_bridge_features_ds_append(chan, &config->features_caller);
	ast_channel_unlock(chan);
	ast_channel_lock(peer);
	ast_max_forwards_reset(peer);
	res |= ast_bridge_features_ds_append(peer, &config->features_callee);
	ast_channel_unlock(peer);

	if (res) {
		return -1;
	}

	if (config->timelimit) {
		struct ast_bridge_features_limits call_duration_limits_chan;
		struct ast_bridge_features_limits call_duration_limits_peer;
		int abandon_call = 0; /* TRUE if set limits fails so we can abandon the call. */

		if (ast_bridge_features_limits_construct(&call_duration_limits_chan)) {
			ast_log(LOG_ERROR, "Could not construct caller duration limits. Bridge canceled.\n");

			return -1;
		}

		if (ast_bridge_features_limits_construct(&call_duration_limits_peer)) {
			ast_log(LOG_ERROR, "Could not construct callee duration limits. Bridge canceled.\n");
			ast_bridge_features_limits_destroy(&call_duration_limits_chan);

			return -1;
		}

		bridge_config_set_limits(config, &call_duration_limits_chan, &call_duration_limits_peer);

		if (ast_bridge_features_set_limits(chan_features, &call_duration_limits_chan, 0)) {
			abandon_call = 1;
		}
		if (ast_bridge_features_set_limits(peer_features, &call_duration_limits_peer, 0)) {
			abandon_call = 1;
		}

		/* At this point we are done with the limits structs since they have been copied to the individual feature sets. */
		ast_bridge_features_limits_destroy(&call_duration_limits_chan);
		ast_bridge_features_limits_destroy(&call_duration_limits_peer);

		if (abandon_call) {
			ast_log(LOG_ERROR, "Could not set duration limits on one or more sides of the call. Bridge canceled.\n");
			return -1;
		}
	}

	return 0;
}
Beispiel #25
0
/*!
 * \brief This is the main function called by Asterisk Core whenever the App is invoked in the extension logic.
 *
 * \param chan Asterisk Channel
 * \param data Application data
 *
 * \retval 0 success
 * \retval -1 failure
 */
static int alarmreceiver_exec(struct ast_channel *chan, const char *data)
{
	int res = 0;
	int no_checksum = 0;
	event_node_t *elp, *efree;
	char signalling_type[64] = "";
	event_node_t *event_head = NULL;

	if ((ast_format_cmp(ast_channel_writeformat(chan), ast_format_ulaw) == AST_FORMAT_CMP_NOT_EQUAL) &&
		(ast_format_cmp(ast_channel_writeformat(chan), ast_format_alaw) == AST_FORMAT_CMP_NOT_EQUAL)) {
		ast_verb(4, "AlarmReceiver: Setting write format to Mu-law\n");
		if (ast_set_write_format(chan, ast_format_ulaw)) {
			ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",ast_channel_name(chan));
			return -1;
		}
	}

	if ((ast_format_cmp(ast_channel_readformat(chan), ast_format_ulaw) == AST_FORMAT_CMP_NOT_EQUAL) &&
		(ast_format_cmp(ast_channel_readformat(chan), ast_format_alaw) == AST_FORMAT_CMP_NOT_EQUAL)) {
		ast_verb(4, "AlarmReceiver: Setting read format to Mu-law\n");
		if (ast_set_read_format(chan, ast_format_ulaw)) {
			ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",ast_channel_name(chan));
			return -1;
		}
	}

	/* Set default values for this invocation of the application */
	ast_copy_string(signalling_type, UNKNOWN_FORMAT, sizeof(signalling_type));
	call_start_time = ast_tvnow();

	/* Answer the channel if it is not already */
	if (ast_channel_state(chan) != AST_STATE_UP) {
		ast_verb(4, "AlarmReceiver: Answering channel\n");
		if (ast_answer(chan)) {
			return -1;
		}
	}

	/* Wait for the connection to settle post-answer */
	ast_verb(4, "AlarmReceiver: Waiting for connection to stabilize\n");
	if (ast_safe_sleep(chan, answait)) {
		return -1;
	}

	/* Attempt to receive the events */
	receive_ademco_event(chan, &event_head, signalling_type, &no_checksum);

	/* Events queued by receiver, write them all out here if so configured */
	if (!log_individual_events) {
		res = log_events(chan, signalling_type, event_head, no_checksum);
	}

	/* Do we exec a command line at the end? */
	if ((!res) && (!ast_strlen_zero(event_app)) && (event_head)) {
		ast_debug(1,"Alarmreceiver: executing: %s\n", event_app);
		ast_safe_system(event_app);
	}

	/* Free up the data allocated in our linked list */
	for (elp = event_head; (elp != NULL);) {
		efree = elp;
		elp = elp->next;
		ast_free(efree);
	}

	return 0;
}
Beispiel #26
0
int ast_channel_data_add_structure(struct ast_data *tree,
	struct ast_channel *chan, int add_bridged)
{
	struct ast_data *data_bridged;
	struct ast_data *data_cdr;
	struct ast_data *data_flags;
	struct ast_data *data_zones;
	struct ast_data *enum_node;
	struct ast_data *data_softhangup;
#if 0	/* XXX AstData: ast_callerid no longer exists. (Equivalent code not readily apparent.) */
	struct ast_data *data_callerid;
	char value_str[100];
#endif

	if (!tree) {
		return -1;
	}

	ast_data_add_structure(ast_channel, tree, chan);

	if (add_bridged) {
		RAII_VAR(struct ast_channel *, bc, ast_channel_bridge_peer(chan), ast_channel_cleanup);
		if (bc) {
			data_bridged = ast_data_add_node(tree, "bridged");
			if (!data_bridged) {
				return -1;
			}
			ast_channel_data_add_structure(data_bridged, bc, 0);
		}
	}

	ast_data_add_codec(tree, "oldwriteformat", ast_channel_oldwriteformat(chan));
	ast_data_add_codec(tree, "readformat", ast_channel_readformat(chan));
	ast_data_add_codec(tree, "writeformat", ast_channel_writeformat(chan));
	ast_data_add_codec(tree, "rawreadformat", ast_channel_rawreadformat(chan));
	ast_data_add_codec(tree, "rawwriteformat", ast_channel_rawwriteformat(chan));
	ast_data_add_codecs(tree, "nativeformats", ast_channel_nativeformats(chan));

	/* state */
	enum_node = ast_data_add_node(tree, "state");
	if (!enum_node) {
		return -1;
	}
	ast_data_add_str(enum_node, "text", ast_state2str(ast_channel_state(chan)));
	ast_data_add_int(enum_node, "value", ast_channel_state(chan));

	/* hangupcause */
	enum_node = ast_data_add_node(tree, "hangupcause");
	if (!enum_node) {
		return -1;
	}
	ast_data_add_str(enum_node, "text", ast_cause2str(ast_channel_hangupcause(chan)));
	ast_data_add_int(enum_node, "value", ast_channel_hangupcause(chan));

	/* amaflags */
	enum_node = ast_data_add_node(tree, "amaflags");
	if (!enum_node) {
		return -1;
	}
	ast_data_add_str(enum_node, "text", ast_channel_amaflags2string(ast_channel_amaflags(chan)));
	ast_data_add_int(enum_node, "value", ast_channel_amaflags(chan));

	/* transfercapability */
	enum_node = ast_data_add_node(tree, "transfercapability");
	if (!enum_node) {
		return -1;
	}
	ast_data_add_str(enum_node, "text", ast_transfercapability2str(ast_channel_transfercapability(chan)));
	ast_data_add_int(enum_node, "value", ast_channel_transfercapability(chan));

	/* _softphangup */
	data_softhangup = ast_data_add_node(tree, "softhangup");
	if (!data_softhangup) {
		return -1;
	}
	ast_data_add_bool(data_softhangup, "dev", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_DEV);
	ast_data_add_bool(data_softhangup, "asyncgoto", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO);
	ast_data_add_bool(data_softhangup, "shutdown", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_SHUTDOWN);
	ast_data_add_bool(data_softhangup, "timeout", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_TIMEOUT);
	ast_data_add_bool(data_softhangup, "appunload", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_APPUNLOAD);
	ast_data_add_bool(data_softhangup, "explicit", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_EXPLICIT);
	ast_data_add_bool(data_softhangup, "unbridge", ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_UNBRIDGE);

	/* channel flags */
	data_flags = ast_data_add_node(tree, "flags");
	if (!data_flags) {
		return -1;
	}
	channel_data_add_flags(data_flags, chan);

	ast_data_add_uint(tree, "timetohangup", ast_channel_whentohangup(chan)->tv_sec);

#if 0	/* XXX AstData: ast_callerid no longer exists. (Equivalent code not readily apparent.) */
	/* callerid */
	data_callerid = ast_data_add_node(tree, "callerid");
	if (!data_callerid) {
		return -1;
	}
	ast_data_add_structure(ast_callerid, data_callerid, &(chan->cid));
	/* insert the callerid ton */
	enum_node = ast_data_add_node(data_callerid, "cid_ton");
	if (!enum_node) {
		return -1;
	}
	ast_data_add_int(enum_node, "value", chan->cid.cid_ton);
	snprintf(value_str, sizeof(value_str), "TON: %s/Plan: %s",
		party_number_ton2str(chan->cid.cid_ton),
		party_number_plan2str(chan->cid.cid_ton));
	ast_data_add_str(enum_node, "text", value_str);
#endif

	/* tone zone */
	if (ast_channel_zone(chan)) {
		data_zones = ast_data_add_node(tree, "zone");
		if (!data_zones) {
			return -1;
		}
		ast_tone_zone_data_add_structure(data_zones, ast_channel_zone(chan));
	}

	/* insert cdr */
	data_cdr = ast_data_add_node(tree, "cdr");
	if (!data_cdr) {
		return -1;
	}

	return 0;
}
Beispiel #27
0
static int testclient_exec(struct ast_channel *chan, const char *data)
{
    int res = 0;
    const char *testid=data;
    char fn[80];
    char serverver[80];
    FILE *f;

    /* Check for test id */
    if (ast_strlen_zero(testid)) {
        ast_log(LOG_WARNING, "TestClient requires an argument - the test id\n");
        return -1;
    }

    if (ast_channel_state(chan) != AST_STATE_UP)
        res = ast_answer(chan);

    /* Wait a few just to be sure things get started */
    res = ast_safe_sleep(chan, 3000);
    /* Transmit client version */
    if (!res)
        res = ast_dtmf_stream(chan, NULL, "8378*1#", 0, 0);
    ast_debug(1, "Transmit client version\n");

    /* Read server version */
    ast_debug(1, "Read server version\n");
    if (!res)
        res = ast_app_getdata(chan, NULL, serverver, sizeof(serverver) - 1, 0);
    if (res > 0)
        res = 0;
    ast_debug(1, "server version: %s\n", serverver);

    if (res > 0)
        res = 0;

    if (!res)
        res = ast_safe_sleep(chan, 1000);
    /* Send test id */
    if (!res)
        res = ast_dtmf_stream(chan, NULL, testid, 0, 0);
    if (!res)
        res = ast_dtmf_stream(chan, NULL, "#", 0, 0);
    ast_debug(1, "send test identifier: %s\n", testid);

    if ((res >=0) && (!ast_strlen_zero(testid))) {
        /* Make the directory to hold the test results in case it's not there */
        snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
        ast_mkdir(fn, 0777);
        snprintf(fn, sizeof(fn), "%s/testresults/%s-client.txt", ast_config_AST_LOG_DIR, testid);
        if ((f = fopen(fn, "w+"))) {
            setlinebuf(f);
            fprintf(f, "CLIENTCHAN:    %s\n", ast_channel_name(chan));
            fprintf(f, "CLIENTTEST ID: %s\n", testid);
            fprintf(f, "ANSWER:        PASS\n");
            res = 0;

            if (!res) {
                /* Step 1: Wait for "1" */
                ast_debug(1, "TestClient: 2.  Wait DTMF 1\n");
                res = ast_waitfordigit(chan, 3000);
                fprintf(f, "WAIT DTMF 1:   %s\n", (res != '1') ? "FAIL" : "PASS");
                if (res == '1')
                    res = 0;
                else
                    res = -1;
            }
            if (!res) {
                res = ast_safe_sleep(chan, 1000);
            }
            if (!res) {
                /* Step 2: Send "2" */
                ast_debug(1, "TestClient: 2.  Send DTMF 2\n");
                res = ast_dtmf_stream(chan, NULL, "2", 0, 0);
                fprintf(f, "SEND DTMF 2:   %s\n", (res < 0) ? "FAIL" : "PASS");
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 3: Wait one second */
                ast_debug(1, "TestClient: 3.  Wait one second\n");
                res = ast_safe_sleep(chan, 1000);
                fprintf(f, "WAIT 1 SEC:    %s\n", (res < 0) ? "FAIL" : "PASS");
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 4: Measure noise */
                ast_debug(1, "TestClient: 4.  Measure noise\n");
                res = measurenoise(chan, 5000, "TestClient");
                fprintf(f, "MEASURENOISE:  %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 5: Wait for "4" */
                ast_debug(1, "TestClient: 5.  Wait DTMF 4\n");
                res = ast_waitfordigit(chan, 3000);
                fprintf(f, "WAIT DTMF 4:   %s\n", (res != '4') ? "FAIL" : "PASS");
                if (res == '4')
                    res = 0;
                else
                    res = -1;
            }
            if (!res) {
                /* Step 6: Transmit tone noise */
                ast_debug(1, "TestClient: 6.  Transmit tone\n");
                res = sendnoise(chan, 6000);
                fprintf(f, "SENDTONE:      %s\n", (res < 0) ? "FAIL" : "PASS");
            }
            if (!res || (res == '5')) {
                /* Step 7: Wait for "5" */
                ast_debug(1, "TestClient: 7.  Wait DTMF 5\n");
                if (!res)
                    res = ast_waitfordigit(chan, 3000);
                fprintf(f, "WAIT DTMF 5:   %s\n", (res != '5') ? "FAIL" : "PASS");
                if (res == '5')
                    res = 0;
                else
                    res = -1;
            }
            if (!res) {
                /* Step 8: Wait one second */
                ast_debug(1, "TestClient: 8.  Wait one second\n");
                res = ast_safe_sleep(chan, 1000);
                fprintf(f, "WAIT 1 SEC:    %s\n", (res < 0) ? "FAIL" : "PASS");
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 9: Measure noise */
                ast_debug(1, "TestClient: 9.  Measure tone\n");
                res = measurenoise(chan, 4000, "TestClient");
                fprintf(f, "MEASURETONE:   %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
                if (res > 0)
                    res = 0;
            }
            if (!res) {
                /* Step 10: Send "7" */
                ast_debug(1, "TestClient: 10.  Send DTMF 7\n");
                res = ast_dtmf_stream(chan, NULL, "7", 0, 0);
                fprintf(f, "SEND DTMF 7:   %s\n", (res < 0) ? "FAIL" : "PASS");
                if (res > 0)
                    res =0;
            }
            if (!res) {
                /* Step 11: Wait for "8" */
                ast_debug(1, "TestClient: 11.  Wait DTMF 8\n");
                res = ast_waitfordigit(chan, 3000);
                fprintf(f, "WAIT DTMF 8:   %s\n", (res != '8') ? "FAIL" : "PASS");
                if (res == '8')
                    res = 0;
                else
                    res = -1;
            }
            if (!res) {
                res = ast_safe_sleep(chan, 1000);
            }
            if (!res) {
                /* Step 12: Hangup! */
                ast_debug(1, "TestClient: 12.  Hangup\n");
            }

            ast_debug(1, "-- TEST COMPLETE--\n");
            fprintf(f, "-- END TEST--\n");
            fclose(f);
            res = -1;
        } else
            res = -1;
    } else {
        ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", ast_channel_name(chan));
        res = -1;
    }
    return res;
}
Beispiel #28
0
/*
* This is the main function called by Asterisk Core whenever the App is invoked in the extension logic.
* This function will always return 0.
*/
static int alarmreceiver_exec(struct ast_channel *chan, const char *data)
{
	int res = 0;
	event_node_t *elp, *efree;
	char signalling_type[64] = "";
	event_node_t *event_head = NULL;

	/* Set write and read formats to ULAW */
	ast_verb(4, "AlarmReceiver: Setting read and write formats to ULAW\n");

	if (ast_set_write_format_by_id(chan,AST_FORMAT_ULAW)) {
		ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",ast_channel_name(chan));
		return -1;
	}

	if (ast_set_read_format_by_id(chan,AST_FORMAT_ULAW)) {
		ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",ast_channel_name(chan));
		return -1;
	}

	/* Set default values for this invocation of the application */
	ast_copy_string(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type));

	/* Answer the channel if it is not already */
	ast_verb(4, "AlarmReceiver: Answering channel\n");
	if (ast_channel_state(chan) != AST_STATE_UP) {
		if ((res = ast_answer(chan)))
			return -1;
	}

	/* Wait for the connection to settle post-answer */
	ast_verb(4, "AlarmReceiver: Waiting for connection to stabilize\n");
	res = ast_safe_sleep(chan, 1250);

	/* Attempt to receive the events */
	if (!res) {
		/* Determine the protocol to receive in advance */
		/* Note: Ademco contact is the only one supported at this time */
		/* Others may be added later */
		if(!strcmp(signalling_type, ADEMCO_CONTACT_ID))
			receive_ademco_contact_id(chan, data, fdtimeout, sdtimeout, toneloudness, &event_head);
		else
			res = -1;
	}

	/* Events queued by receiver, write them all out here if so configured */
	if ((!res) && (log_individual_events == 0))
		res = log_events(chan, signalling_type, event_head);

	/*
	* Do we exec a command line at the end?
	*/
	if ((!res) && (!ast_strlen_zero(event_app)) && (event_head)) {
		ast_debug(1,"Alarmreceiver: executing: %s\n", event_app);
		ast_safe_system(event_app);
	}

	/*
	* Free up the data allocated in our linked list
	*/
	for (elp = event_head; (elp != NULL);) {
		efree = elp;
		elp = elp->next;
		ast_free(efree);
	}

	return 0;
}
static int nv_detectfax_exec(struct ast_channel *chan, const char *data)
{
	int res = 0;
	char tmp[256] = "\0";
	char *p = NULL;
	char *waitstr = NULL;
	char *options = NULL;
	char *silstr = NULL;
	char *minstr = NULL;
	char *maxstr = NULL;
	struct ast_frame *fr = NULL;
	struct ast_frame *fr2 = NULL;
	int notsilent = 0;
	struct timeval start = {0, 0}, end = {0, 0};
	int waitdur = 4;
	int sildur = 1000;
	int mindur = 100;
	int maxdur = -1;
	int skipanswer = 0;
	int noextneeded = 0;
	int ignoredtmf = 0;
	int ignorefax = 0;
	int ignoretalk = 0;
	int x = 0;
	struct ast_format* origrformat = NULL;
	int features = 0;
	time_t timeout = 0;
	struct ast_dsp *dsp = NULL;
	
	struct ast_format_cap *cap;
	struct ast_format linearFormat;
	
	/* linear format capabilities */
	ast_format_set(&linearFormat, AST_FORMAT_SLINEAR, 0);
	cap = ast_format_cap_alloc_nolock();
	ast_format_cap_add(cap, &linearFormat);
	/* done */
	
	pbx_builtin_setvar_helper(chan, "FAX_DETECTED", "");
	pbx_builtin_setvar_helper(chan, "FAXEXTEN", "");
	pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", "");
	pbx_builtin_setvar_helper(chan, "TALK_DETECTED", "");
	
	if (data || !ast_strlen_zero(data)) {
		strncpy(tmp, data, sizeof(tmp)-1);
	}	
	
	p = tmp;
	
	waitstr = strsep(&p, ",");
	options = strsep(&p, ",");
	silstr = strsep(&p, ",");
	minstr = strsep(&p, ",");	
	maxstr = strsep(&p, ",");	
	
	if (waitstr) {
		if ((sscanf(waitstr, "%d", &x) == 1) && (x > 0))
			waitdur = x;
	}
	
	if (options) {
		if (strchr(options, 'n'))
			skipanswer = 1;
		if (strchr(options, 'x'))
			noextneeded = 1;
		if (strchr(options, 'd'))
			ignoredtmf = 1;
		if (strchr(options, 'f'))
			ignorefax = 1;
		if (strchr(options, 't'))
			ignoretalk = 1;
	}
	
	if (silstr) {
		if ((sscanf(silstr, "%d", &x) == 1) && (x > 0))
			sildur = x;
	}
	
	if (minstr) {
		if ((sscanf(minstr, "%d", &x) == 1) && (x > 0))
			mindur = x;
	}
	
	if (maxstr) {
		if ((sscanf(maxstr, "%d", &x) == 1) && (x > 0))
			maxdur = x;
	}
	
	ast_log(LOG_DEBUG, "Preparing detect of fax (waitdur=%dms, sildur=%dms, mindur=%dms, maxdur=%dms)\n", 
						waitdur, sildur, mindur, maxdur);
						
	//	LOCAL_USER_ADD(u);
// 	if (chan->_state != AST_STATE_UP && !skipanswer) {
	if (ast_channel_state(chan) != AST_STATE_UP && !skipanswer) {
		/* Otherwise answer unless we're supposed to send this while on-hook */
		res = ast_answer(chan);
	}
	if (!res) {
// 		origrformat = chan->readformat;
		origrformat = ast_channel_readformat(chan);
		
// 		if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR))) 
		if ((res = ast_set_read_format_from_cap(chan, cap)) ){
			ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
		}
	}
	if (!(dsp = ast_dsp_new())) {
		ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
		res = -1;
	}
	
	if (dsp) {	
		if (!ignoretalk)
			; /* features |= DSP_FEATURE_SILENCE_SUPPRESS; */
		if (!ignorefax)
			features |= DSP_FEATURE_FAX_DETECT;
		//if (!ignoredtmf)
			features |= DSP_FEATURE_DIGIT_DETECT;
			
		ast_dsp_set_threshold(dsp, 256); 
		ast_dsp_set_features(dsp, features | DSP_DIGITMODE_RELAXDTMF);
		ast_dsp_set_digitmode(dsp, DSP_DIGITMODE_DTMF);
	}

	if (!res) {
		if (waitdur > 0)
			timeout = time(NULL) + (time_t)waitdur;

		while(ast_waitfor(chan, -1) > -1) {
			if (waitdur > 0 && time(NULL) > timeout) {
				res = 0;
				break;
			}

			fr = ast_read(chan);
			if (!fr) {
				ast_log(LOG_DEBUG, "Got hangup\n");
				res = -1;
				break;
			}

			fr2 = ast_dsp_process(chan, dsp, fr);
			if (!fr2) {
				ast_log(LOG_WARNING, "Bad DSP received (what happened?)\n");
				fr2 = fr;
			} 

			if (fr2->frametype == AST_FRAME_DTMF) {
				if (fr2->subclass.integer == 'f' && !ignorefax) {
					/* Fax tone -- Handle and return NULL */
					ast_log(LOG_DEBUG, "Fax detected on %s\n", ast_channel_name(chan));
					ast_log(LOG_DEBUG, "Fax detected on %s\n", ast_channel_name(chan));
					if (strcmp(ast_channel_exten(chan), "fax")) {
						ast_log(LOG_NOTICE, "Redirecting %s to fax extension\n", ast_channel_name(chan));
						pbx_builtin_setvar_helper(chan, "FAX_DETECTED", "1");
						pbx_builtin_setvar_helper(chan,"FAXEXTEN",ast_channel_exten(chan));								
						if (ast_exists_extension(chan, ast_channel_context(chan), "fax", 1, ast_channel_caller(chan)->id.number.str)) {
							/* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
// 							strncpy(ast_channel_exten(chan), "fax", sizeof(ast_channel_exten(chan))-1);
// 							chan->priority = 0;
							ast_channel_exten_set(chan, "fax");
							ast_channel_priority_set(chan, 0);
						} else
							ast_log(LOG_WARNING, "Fax detected, but no fax extension\n");
					} else
						ast_log(LOG_WARNING, "Already in a fax extension, not redirecting\n");

					res = 0;
					ast_frfree(fr);
					break;
				} else if (!ignoredtmf) {
					ast_log(LOG_DEBUG, "DTMF detected on %s\n", ast_channel_name(chan));
					char t[2];
					t[0] = fr2->subclass.integer;
					t[1] = '\0';
					if (noextneeded || ast_canmatch_extension(chan, ast_channel_context(chan), t, 1, ast_channel_caller(chan)->id.number.str)) {
						pbx_builtin_setvar_helper(chan, "DTMF_DETECTED", "1");
						/* They entered a valid extension, or might be anyhow */
						if (noextneeded) {
							ast_log(LOG_NOTICE, "DTMF received (not matching to exten)\n");
							res = 0;
						} else {
							ast_log(LOG_NOTICE, "DTMF received (matching to exten)\n");
							res = fr2->subclass.integer;
						}
						ast_frfree(fr);
						break;
					} else
						ast_log(LOG_DEBUG, "Valid extension requested and DTMF did not match\n");
				}
// 			} else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR) && !ignoretalk) {
			} else if ((fr->frametype == AST_FRAME_VOICE) && ( ast_format_cap_iscompatible(cap, &fr->subclass.format)) && !ignoretalk) {
				int totalsilence;
				int ms;
				res = ast_dsp_silence(dsp, fr, &totalsilence);
				if (res && (totalsilence > sildur)) {
					/* We've been quiet a little while */
					if (notsilent) {
						/* We had heard some talking */
						gettimeofday(&end, NULL);
						ms = (end.tv_sec - start.tv_sec) * 1000;
						ms += (end.tv_usec - start.tv_usec) / 1000;
						ms -= sildur;
						if (ms < 0)
							ms = 0;
						if ((ms > mindur) && ((maxdur < 0) || (ms < maxdur))) {
							char ms_str[10];
							ast_log(LOG_DEBUG, "Found qualified token of %d ms\n", ms);
							ast_log(LOG_NOTICE, "Redirecting %s to talk extension\n", ast_channel_name(chan));

							/* Save detected talk time (in milliseconds) */ 
							sprintf(ms_str, "%d", ms);	
							pbx_builtin_setvar_helper(chan, "TALK_DETECTED", ms_str);

							if (ast_exists_extension(chan, ast_channel_context(chan), "talk", 1, ast_channel_caller(chan)->id.number.str)) {
// 								strncpy(ast_channel_exten(chan), "talk", sizeof(ast_channel_exten(chan)) - 1);
// 								chan->priority = 0;
								ast_channel_exten_set(chan, "talk");
								ast_channel_priority_set(chan, 0);
							} else
								ast_log(LOG_WARNING, "Talk detected, but no talk extension\n");
							res = 0;
							ast_frfree(fr);
							break;
						} else
							ast_log(LOG_DEBUG, "Found unqualified token of %d ms\n", ms);
						notsilent = 0;
					}
				} else {
					if (!notsilent) {
						/* Heard some audio, mark the begining of the token */
						gettimeofday(&start, NULL);
						ast_log(LOG_DEBUG, "Start of voice token!\n");
						notsilent = 1;
					}
				}						
			}
			ast_frfree(fr);
		}
	} else
		ast_log(LOG_WARNING, "Could not answer channel '%s'\n", ast_channel_name(chan));
	
	if (res > -1) {
		if (origrformat && ast_set_read_format(chan, origrformat)) {
			ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n", 
				ast_channel_name(chan), ast_getformatname(origrformat));
		}
	}
	
	if (dsp)
		ast_dsp_free(dsp);
	
	//	LOCAL_USER_REMOVE(u);
	ast_format_cap_destroy(cap);
	return res;
}
Beispiel #30
0
static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, int length, char *intkeys)
{
	int res = 0;
	int fds[2];
	int needed = 0;
	struct ast_format *owriteformat;
	struct ast_frame *f;
	struct myframe {
		struct ast_frame f;
		char offset[AST_FRIENDLY_OFFSET];
		char frdata[2048];
	} myf = {
		.f = { 0, },
	};

	if (pipe(fds)) {
		ast_log(LOG_WARNING, "Unable to create pipe\n");
		return -1;
	}

	/* Answer if it's not already going */
	if (ast_channel_state(chan) != AST_STATE_UP)
		ast_answer(chan);
	ast_stopstream(chan);
	ast_indicate(chan, -1);
	
	owriteformat = ao2_bump(ast_channel_writeformat(chan));
	res = ast_set_write_format(chan, ast_format_slin);
	if (res < 0) {
		ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
		ao2_cleanup(owriteformat);
		return -1;
	}

	myf.f.frametype = AST_FRAME_VOICE;
	myf.f.subclass.format = ast_format_slin;
	myf.f.offset = AST_FRIENDLY_OFFSET;
	myf.f.src = __PRETTY_FUNCTION__;
	myf.f.data.ptr = myf.frdata;
	
	res = send_waveform_to_fd(waveform, length, fds[1]);
	if (res >= 0) {
		/* Order is important -- there's almost always going to be mp3...  we want to prioritize the
		   user */
		for (;;) {
			res = ast_waitfor(chan, 1000);
			if (res < 1) {
				res = -1;
				break;
			}
			f = ast_read(chan);
			if (!f) {
				ast_log(LOG_WARNING, "Null frame == hangup() detected\n");
				res = -1;
				break;
			}
			if (f->frametype == AST_FRAME_DTMF) {
				ast_debug(1, "User pressed a key\n");
				if (intkeys && strchr(intkeys, f->subclass.integer)) {
					res = f->subclass.integer;
					ast_frfree(f);
					break;
				}
			}
			if (f->frametype == AST_FRAME_VOICE) {
				/* Treat as a generator */
				needed = f->samples * 2;
				if (needed > sizeof(myf.frdata)) {
					ast_log(LOG_WARNING, "Only able to deliver %d of %d requested samples\n",
						(int)sizeof(myf.frdata) / 2, needed/2);
					needed = sizeof(myf.frdata);
				}
				res = read(fds[0], myf.frdata, needed);
				if (res > 0) {
					myf.f.datalen = res;
					myf.f.samples = res / 2;
					if (ast_write(chan, &myf.f) < 0) {
						res = -1;
						ast_frfree(f);
						break;
					}
					if (res < needed) { /* last frame */
						ast_debug(1, "Last frame\n");
						res = 0;
						ast_frfree(f);
						break;
					}
				} else {
					ast_debug(1, "No more waveform\n");
					res = 0;
				}
			}
			ast_frfree(f);
		}
	}
	close(fds[0]);
	close(fds[1]);

	if (!res && owriteformat)
		ast_set_write_format(chan, owriteformat);
	ao2_cleanup(owriteformat);

	return res;
}