Esempio n. 1
0
int ast_tls_read_conf(struct ast_tls_config *tls_cfg, struct ast_tcptls_session_args *tls_desc, const char *varname, const char *value)
{
    if (!strcasecmp(varname, "tlsenable") || !strcasecmp(varname, "sslenable")) {
        tls_cfg->enabled = ast_true(value) ? 1 : 0;
    } else if (!strcasecmp(varname, "tlscertfile") || !strcasecmp(varname, "sslcert") || !strcasecmp(varname, "tlscert")) {
        ast_free(tls_cfg->certfile);
        tls_cfg->certfile = ast_strdup(value);
    } else if (!strcasecmp(varname, "tlsprivatekey") || !strcasecmp(varname, "sslprivatekey")) {
        ast_free(tls_cfg->pvtfile);
        tls_cfg->pvtfile = ast_strdup(value);
    } else if (!strcasecmp(varname, "tlscipher") || !strcasecmp(varname, "sslcipher")) {
        ast_free(tls_cfg->cipher);
        tls_cfg->cipher = ast_strdup(value);
    } else if (!strcasecmp(varname, "tlscafile")) {
        ast_free(tls_cfg->cafile);
        tls_cfg->cafile = ast_strdup(value);
    } else if (!strcasecmp(varname, "tlscapath") || !strcasecmp(varname, "tlscadir")) {
        ast_free(tls_cfg->capath);
        tls_cfg->capath = ast_strdup(value);
    } else if (!strcasecmp(varname, "tlsverifyclient")) {
        ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_VERIFY_CLIENT);
    } else if (!strcasecmp(varname, "tlsdontverifyserver")) {
        ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DONT_VERIFY_SERVER);
    } else if (!strcasecmp(varname, "tlsbindaddr") || !strcasecmp(varname, "sslbindaddr")) {
        if (ast_parse_arg(value, PARSE_ADDR, &tls_desc->local_address))
            ast_log(LOG_ERROR, "Invalid %s '%s'\n", varname, value);
    } else if (!strcasecmp(varname, "tlsclientmethod") || !strcasecmp(varname, "sslclientmethod")) {
        if (!strcasecmp(value, "tlsv1")) {
            ast_set_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
            ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
            ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
        } else if (!strcasecmp(value, "sslv3")) {
            ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
            ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
            ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
        } else if (!strcasecmp(value, "sslv2")) {
            ast_set_flag(&tls_cfg->flags, AST_SSL_SSLV2_CLIENT);
            ast_clear_flag(&tls_cfg->flags, AST_SSL_TLSV1_CLIENT);
            ast_clear_flag(&tls_cfg->flags, AST_SSL_SSLV3_CLIENT);
        }
    } else if (!strcasecmp(varname, "tlsservercipherorder")) {
        ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_SERVER_CIPHER_ORDER);
    } else if (!strcasecmp(varname, "tlsdisablev1")) {
        ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DISABLE_TLSV1);
    } else if (!strcasecmp(varname, "tlsdisablev11")) {
        ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DISABLE_TLSV11);
    } else if (!strcasecmp(varname, "tlsdisablev12")) {
        ast_set2_flag(&tls_cfg->flags, ast_true(value), AST_SSL_DISABLE_TLSV12);
    } else {
        return -1;
    }

    return 0;
}
Esempio n. 2
0
static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, char *set) 
{
	struct ast_cdr *cdr;
	struct ast_cdr *newcdr;
	struct ast_flags flags = { AST_CDR_FLAG_KEEP_VARS };

	cdr = chan->cdr;

	while (cdr->next)
		cdr = cdr->next;
	
	if (!(newcdr = ast_cdr_dup_unique(cdr)))
		return;
	
	ast_cdr_append(cdr, newcdr);

	if (!ast_test_flag(&optflags, OPT_NORESET))
		ast_cdr_reset(newcdr, &flags);
		
	if (!ast_test_flag(cdr, AST_CDR_FLAG_KEEP_VARS))
		ast_cdr_free_vars(cdr, 0);
	
	if (!ast_strlen_zero(set)) {
		char *varname = ast_strdupa(set), *varval;
		varval = strchr(varname,'=');
		if (varval) {
			*varval = 0;
			varval++;
			ast_cdr_setvar(cdr, varname, varval, 0);
		}
	}
	
	if (ast_test_flag(&optflags, OPT_SETANS) && !ast_tvzero(cdr->answer))
		newcdr->answer = newcdr->start;

	if (ast_test_flag(&optflags, OPT_SETDISP))
		newcdr->disposition = cdr->disposition;
	
	if (ast_test_flag(&optflags, OPT_RESETDEST))
		newcdr->dstchannel[0] = 0;
	
	if (ast_test_flag(&optflags, OPT_ENDCDR))
		ast_cdr_end(cdr);

	if (ast_test_flag(&optflags, OPT_ANSLOCK))
		ast_set_flag(cdr, AST_CDR_FLAG_ANSLOCKED);
	
	if (ast_test_flag(&optflags, OPT_DONTOUCH))
		ast_set_flag(cdr, AST_CDR_FLAG_DONT_TOUCH);
		
	ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED);
}
Esempio n. 3
0
static void change_spy_mode(const char digit, struct ast_flags *flags)
{
	if (digit == '4') {
		ast_clear_flag(flags, OPTION_WHISPER);
		ast_clear_flag(flags, OPTION_BARGE);
	} else if (digit == '5') {
		ast_clear_flag(flags, OPTION_BARGE);
		ast_set_flag(flags, OPTION_WHISPER);
	} else if (digit == '6') {
		ast_clear_flag(flags, OPTION_WHISPER);
		ast_set_flag(flags, OPTION_BARGE);
	}
}
Esempio n. 4
0
static int dahdiscan_exec(struct ast_channel *chan, const char *data)
{
	const char *spec = "DAHDI";
	struct ast_flags flags;
	struct spy_dtmf_options user_options = {
		.cycle = '#',
		.volume = '\0',
		.exit = '*',
	};
	struct ast_format *oldwf;
	int res;
	char *mygroup = NULL;

	/* Coverity - This uninit_use should be ignored since this macro initializes the flags */
	ast_clear_flag(&flags, AST_FLAGS_ALL);

	if (!ast_strlen_zero(data)) {
		mygroup = ast_strdupa(data);
	}
	ast_set_flag(&flags, OPTION_DTMF_EXIT);
	ast_set_flag(&flags, OPTION_DTMF_CYCLE);
	ast_set_flag(&flags, OPTION_DAHDI_SCAN);

	oldwf = ao2_bump(ast_channel_writeformat(chan));
	if (ast_set_write_format(chan, ast_format_slin) < 0) {
		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
		ao2_cleanup(oldwf);
		return -1;
	}

	res = common_exec(chan, &flags, 0, 0, &user_options, mygroup, NULL, spec, NULL, NULL, NULL, NULL);

	if (oldwf && ast_set_write_format(chan, oldwf) < 0)
		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
	ao2_cleanup(oldwf);

	return res;
}

static int unload_module(void)
{
	int res = 0;

	res |= ast_unregister_application(app_chan);
	res |= ast_unregister_application(app_ext);
	res |= ast_unregister_application(app_dahdiscan);

	return res;
}
Esempio n. 5
0
static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook, struct ast_flags *flags)
{
	ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, ast_channel_name(autochan->chan));
	if(ast_test_flag(flags, OPTION_READONLY)) {
		ast_set_flag(audiohook, AST_AUDIOHOOK_MUTE_WRITE);
	} else {
		ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
	}
	if(ast_test_flag(flags, OPTION_LONG_QUEUE)) {
		ast_debug(9, "Using a long queue to store audio frames in spy audiohook\n");
	} else {
		ast_set_flag(audiohook, AST_AUDIOHOOK_SMALL_QUEUE);
	}
	return ast_audiohook_attach(autochan->chan, audiohook);
}
Esempio n. 6
0
static int nocdr_exec(struct ast_channel *chan, const char *data)
{
	if (ast_channel_cdr(chan))
		ast_set_flag(ast_channel_cdr(chan), AST_CDR_FLAG_POST_DISABLED);

	return 0;
}
Esempio n. 7
0
static void *playtones_alloc(struct ast_channel *chan, void *params)
{
	struct playtones_def *pd = params;
	struct playtones_state *ps = NULL;

	if (!(ps = ast_calloc(1, sizeof(*ps)))) {
		return NULL;
	}

	ast_format_copy(&ps->origwfmt, ast_channel_writeformat(chan));

	if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR)) {
		ast_log(LOG_WARNING, "Unable to set '%s' to signed linear format (write)\n", ast_channel_name(chan));
		playtones_release(NULL, ps);
		ps = NULL;
	} else {
		ps->vol = pd->vol;
		ps->reppos = pd->reppos;
		ps->nitems = pd->nitems;
		ps->items = pd->items;
		ps->oldnpos = -1;
	}

	/* Let interrupts interrupt :) */
	if (pd->interruptible) {
		ast_set_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
	} else {
		ast_clear_flag(ast_channel_flags(chan), AST_FLAG_WRITE_INT);
	}

	return ps;
}
static struct ast_channel *announce_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
{
	struct ast_channel *chan;
	const char *conf_name = data;

	/* Allocate a new private structure and then Asterisk channels */
	struct announce_pvt *pvt = (struct announce_pvt *) ast_unreal_alloc(sizeof(*pvt), announce_pvt_destructor, cap);
	if (!pvt) {
		return NULL;
	}
	ast_set_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION);
	ast_copy_string(pvt->base.name, conf_name, sizeof(pvt->base.name));

#if !defined(CS_AST_CHANNEL_CALLID_TYPEDEF)
	chan = ast_unreal_new_channels(&pvt->base, sccpconf_announce_get_tech(), AST_STATE_UP, AST_STATE_UP, NULL, NULL, assignedids, requestor, NULL);
#else
	chan = ast_unreal_new_channels(&pvt->base, sccpconf_announce_get_tech(), AST_STATE_UP, AST_STATE_UP, NULL, NULL, assignedids, requestor, 0);
#endif
	if (chan) {
		ast_answer(pvt->base.owner);
		ast_answer(pvt->base.chan);
		if (ast_channel_add_bridge_role(pvt->base.chan, "announcer")) {
			ast_hangup(chan);
			chan = NULL;
		}
	}
	ao2_cleanup(pvt);

	return chan;
}
Esempio n. 9
0
static struct ast_channel *media_request_helper(struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids,
	const struct ast_channel *requestor, const char *data, struct ast_channel_tech *tech, const char *role)
{
	struct ast_channel *chan;
	ast_callid callid;

	RAII_VAR(struct ast_unreal_pvt *, pvt, NULL, ao2_cleanup);

	if (!(pvt = ast_unreal_alloc(sizeof(*pvt), ast_unreal_destructor, cap))) {
		return NULL;
	}

	ast_copy_string(pvt->name, data, sizeof(pvt->name));

	ast_set_flag(pvt, AST_UNREAL_NO_OPTIMIZATION);

	callid = ast_read_threadstorage_callid();

	chan = ast_unreal_new_channels(pvt, tech,
		AST_STATE_UP, AST_STATE_UP, NULL, NULL, assignedids, requestor, callid);
	if (!chan) {
		return NULL;
	}

	ast_answer(pvt->owner);
	ast_answer(pvt->chan);

	if (ast_channel_add_bridge_role(pvt->chan, role)) {
		ast_hangup(chan);
		return NULL;
	}

	return chan;
}
Esempio n. 10
0
/** \brief Received MRCP message */
static apt_bool_t on_message_receive(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message)
{
	uni_speech_t *uni_speech = mrcp_application_channel_object_get(channel);

	ast_log(LOG_DEBUG, "On message receive\n");
	if(message->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) {
		return uni_recog_mrcp_response_signal(uni_speech,message);
	}
	
	if(message->start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
		if(message->start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) {
			uni_speech->is_inprogress = FALSE;			
			if (uni_speech->speech_base->state != AST_SPEECH_STATE_NOT_READY) {
				uni_speech->mrcp_event = message;
				ast_speech_change_state(uni_speech->speech_base,AST_SPEECH_STATE_DONE);
			}
			else {
				uni_speech->mrcp_event = NULL;
				ast_speech_change_state(uni_speech->speech_base,AST_SPEECH_STATE_NOT_READY);
			}
		}
		else if(message->start_line.method_id == RECOGNIZER_START_OF_INPUT) {
			ast_set_flag(uni_speech->speech_base,AST_SPEECH_QUIET);
		}
	}

	return TRUE;
}
Esempio n. 11
0
static void init_outgoing(struct outgoing *o)
{
	memset(o, 0, sizeof(struct outgoing));
	o->priority = 1;
	o->retrytime = 300;
	o->waittime = 45;
	ast_set_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE);
}
Esempio n. 12
0
static int dahdiscan_exec(struct ast_channel *chan, const char *data)
{
	const char *spec = "DAHDI";
	struct ast_flags flags;
	struct spy_dtmf_options user_options = {
		.cycle = '#',
		.volume = '\0',
		.exit = '*',
	};
	int oldwf = 0;
	int res;
	char *mygroup = NULL;

	ast_clear_flag(&flags, AST_FLAGS_ALL);

	if (!ast_strlen_zero(data)) {
		mygroup = ast_strdupa(data);
	}
	ast_set_flag(&flags, OPTION_DTMF_EXIT);
	ast_set_flag(&flags, OPTION_DTMF_CYCLE);
	ast_set_flag(&flags, OPTION_DAHDI_SCAN);

	oldwf = chan->writeformat;
	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
		return -1;
	}

	res = common_exec(chan, &flags, 0, 0, &user_options, mygroup, NULL, spec, NULL, NULL, NULL, NULL);

	if (oldwf && ast_set_write_format(chan, oldwf) < 0)
		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");

	return res;
}

static int unload_module(void)
{
	int res = 0;

	res |= ast_unregister_application(app_chan);
	res |= ast_unregister_application(app_ext);
	res |= ast_unregister_application(app_dahdiscan);

	return res;
}
Esempio n. 13
0
int sccpconf_announce_channel_push(struct ast_channel *ast, struct ast_bridge *bridge)
{
	struct ast_bridge_features *features;
	struct ast_channel *chan;
	struct announce_pvt *p = NULL;

	{
		ast_channel_lock(ast);
		p = ast_channel_tech_pvt(ast);
		if (!p) {
			ast_channel_unlock(ast);
			return -1;
		}
		ao2_ref(p, +1);
		chan = p->base.chan;
		if (!chan) {
			ast_channel_unlock(ast);
			ao2_cleanup(p);
			return -1;
		}
		ast_channel_ref(chan);
		ast_channel_unlock(ast);
	}

	features = ast_bridge_features_new();
	if (!features) {
		ast_channel_unref(chan);
		ao2_cleanup(p);
		return -1;
	}
	ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);

	// Impart the output channel into the bridge
	if (ast_bridge_impart(bridge, chan, NULL, features, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)) {
		ast_bridge_features_destroy(features);
		ast_channel_unref(chan);
		ao2_cleanup(p);
		return -1;
	}
	ao2_lock(p);
	ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
	ao2_unlock(p);
	ao2_cleanup(p);
	return 0;
}
Esempio n. 14
0
static int parse_dtls_attrib(struct ast_sip_session_media *session_media,
	const struct pjmedia_sdp_media *stream)
{
	int i;
	struct ast_rtp_engine_dtls *dtls = ast_rtp_instance_get_dtls(session_media->rtp);

	for (i = 0; i < stream->attr_count; i++) {
		pjmedia_sdp_attr *attr = stream->attr[i];
		pj_str_t *value;

		if (!attr->value.ptr) {
			continue;
		}

		value = pj_strtrim(&attr->value);

		if (!pj_strcmp2(&attr->name, "setup")) {
			if (!pj_stricmp2(value, "active")) {
				dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTIVE);
			} else if (!pj_stricmp2(value, "passive")) {
				dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_PASSIVE);
			} else if (!pj_stricmp2(value, "actpass")) {
				dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_ACTPASS);
			} else if (!pj_stricmp2(value, "holdconn")) {
				dtls->set_setup(session_media->rtp, AST_RTP_DTLS_SETUP_HOLDCONN);
			} else {
				ast_log(LOG_WARNING, "Unsupported setup attribute value '%*s'\n", (int)value->slen, value->ptr);
			}
		} else if (!pj_strcmp2(&attr->name, "connection")) {
			if (!pj_stricmp2(value, "new")) {
				dtls->reset(session_media->rtp);
			} else if (!pj_stricmp2(value, "existing")) {
				/* Do nothing */
			} else {
				ast_log(LOG_WARNING, "Unsupported connection attribute value '%*s'\n", (int)value->slen, value->ptr);
			}
		} else if (!pj_strcmp2(&attr->name, "fingerprint")) {
			char hash_value[256], hash[32];
			char fingerprint_text[value->slen + 1];
			ast_copy_pj_str(fingerprint_text, value, sizeof(fingerprint_text));

			if (sscanf(fingerprint_text, "%31s %255s", hash, hash_value) == 2) {
				if (!strcasecmp(hash, "sha-1")) {
					dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA1, hash_value);
				} else if (!strcasecmp(hash, "sha-256")) {
					dtls->set_fingerprint(session_media->rtp, AST_RTP_DTLS_HASH_SHA256, hash_value);
				} else {
					ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s'\n",
					hash);
				}
			}
		}
	}
	ast_set_flag(session_media->srtp, AST_SRTP_CRYPTO_OFFER_OK);

	return 0;
}
Esempio n. 15
0
static void set_bridge_features_on_config(struct ast_bridge_config *config, const char *features)
{
	const char *feature;

	if (ast_strlen_zero(features)) {
		return;
	}

	for (feature = features; *feature; feature++) {
		struct ast_flags *party;

		if (isupper(*feature)) {
			party = &config->features_caller;
		} else {
			party = &config->features_callee;
		}

		switch (tolower(*feature)) {
		case 't' :
			ast_set_flag(party, AST_FEATURE_REDIRECT);
			break;
		case 'k' :
			ast_set_flag(party, AST_FEATURE_PARKCALL);
			break;
		case 'h' :
			ast_set_flag(party, AST_FEATURE_DISCONNECT);
			break;
		case 'w' :
			ast_set_flag(party, AST_FEATURE_AUTOMON);
			break;
		case 'x' :
			ast_set_flag(party, AST_FEATURE_AUTOMIXMON);
			break;
		default :
			ast_log(LOG_WARNING, "Skipping unknown feature code '%c'\n", *feature);
			break;
		}
	}
}
static void *transport_websocket_init(const struct ast_socket_io_session *session)
{
	struct ast_websocket *ws;
	struct ast_str *uri = ast_str_create(128);
	enum ast_websocket_result result;
	struct ast_uri *session_uri = ast_socket_io_uri(session);
	struct ast_tls_config *tls_cfg = NULL;

	if (!uri) {
		ast_log(LOG_ERROR, "Unable to allocate websocket uri\n");
		return NULL;
	}

	ast_str_set(&uri, 0, "%s://%s:%s/socket.io/%s/websocket/%s",
		    ast_uri_is_secure(session_uri) ? "wss" : "ws",
		    ast_uri_host(session_uri), ast_uri_port(session_uri),
		    SOCKET_IO_VERSION, ast_socket_io_id(session));

	if (!ast_strlen_zero(ast_uri_query(session_uri))) {
		ast_str_append(&uri, 0, "?%s", ast_uri_query(session_uri));
	}

	if (ast_uri_is_secure(session_uri)) {
		/* The websocket client expects a copy of the TLS configuration so provide it */
		tls_cfg = ast_calloc(1, sizeof(*tls_cfg));
		ast_set_flag(&tls_cfg->flags, AST_SSL_DONT_VERIFY_SERVER);
	}

	ws = ast_websocket_client_create(
		ast_str_buffer(uri), "socket.io",
			tls_cfg, &result);
	ast_free(uri);

	if (ws) {
		struct protoent *p;

		p = getprotobyname("tcp");
		if (p) {
			int arg = 1;

			if (setsockopt(ast_websocket_fd(ws), p->p_proto, TCP_NODELAY, (char *) &arg, sizeof(arg) ) < 0) {
				ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on HTTP connection: %s\n", strerror(errno));
				ast_log(LOG_WARNING, "Some HTTP requests may be slow to respond.\n");
			}
		}

		ast_websocket_set_nonblock(ws);
	}

	return ws;
}
Esempio n. 17
0
static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook)
{
	int res = 0;
	struct ast_channel *peer = NULL;

	ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, autochan->chan->name);

	ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC | AST_AUDIOHOOK_SMALL_QUEUE);
	res = ast_audiohook_attach(autochan->chan, audiohook);

	if (!res && ast_test_flag(autochan->chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(autochan->chan))) {
		ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
	}
	return res;
}
Esempio n. 18
0
int conf_announce_channel_push(struct ast_channel *ast)
{
	struct ast_bridge_features *features;
	struct ast_channel *chan;
	RAII_VAR(struct announce_pvt *, p, NULL, ao2_cleanup);

	{
		SCOPED_CHANNELLOCK(lock, ast);

		p = ast_channel_tech_pvt(ast);
		if (!p) {
			return -1;
		}
		ao2_ref(p, +1);
		chan = p->base.chan;
		if (!chan) {
			return -1;
		}
	}

	features = ast_bridge_features_new();
	if (!features) {
		return -1;
	}
	ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);

	/* Impart the output channel into the bridge */
	if (ast_bridge_impart(p->bridge, chan, NULL, features,
		AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
		return -1;
	}
	ao2_lock(p);
	ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
	ao2_unlock(p);
	return 0;
}
Esempio n. 19
0
static int load_config(int startup)
{
	struct ast_flags config_flags = { 0, };
	struct ast_config *cfg;
	struct ast_variable *v;

	if (!startup) {
		ast_set_flag(&config_flags, CONFIG_FLAG_FILEUNCHANGED);
	}

	cfg = ast_config_load2(stun_conf_file, "res_stun_monitor", config_flags);
	if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
		ast_log(LOG_WARNING, "Unable to load config %s\n", stun_conf_file);
		return -1;
	}
	if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
		return 0;
	}

	/* clean up any previous open socket */
	stun_close_sock();
	args.stun_poll_failed_gripe = 0;

	/* set defaults */
	args.monitor_enabled = 0;
	args.refresh = DEFAULT_MONITOR_REFRESH;

	for (v = ast_variable_browse(cfg, "general"); v; v = v->next) {
		if (!strcasecmp(v->name, "stunaddr")) {
			if (setup_stunaddr(v->value)) {
				ast_log(LOG_WARNING, "Invalid STUN server address: %s at line %d\n",
					v->value, v->lineno);
			}
		} else if (!strcasecmp(v->name, "stunrefresh")) {
			if ((sscanf(v->value, "%30u", &args.refresh) != 1) || !args.refresh) {
				ast_log(LOG_WARNING, "Invalid stunrefresh value '%s', must be an integer > 0 at line %d\n", v->value, v->lineno);
				args.refresh = DEFAULT_MONITOR_REFRESH;
			}
		} else {
			ast_log(LOG_WARNING, "Invalid config option %s at line %d\n",
				v->value, v->lineno);
		}
	}

	ast_config_destroy(cfg);

	return 0;
}
Esempio n. 20
0
/*! \internal \brief Enable talk detection on the channel */
static int set_talk_detect(struct ast_channel *chan, int dsp_silence_threshold, int dsp_talking_threshold)
{
	struct ast_datastore *datastore = NULL;
	struct talk_detect_params *td_params;
	SCOPED_CHANNELLOCK(chan_lock, chan);

	datastore = ast_channel_datastore_find(chan, &talk_detect_datastore, NULL);
	if (!datastore) {
		datastore = ast_datastore_alloc(&talk_detect_datastore, NULL);
		if (!datastore) {
			return -1;
		}

		td_params = ast_calloc(1, sizeof(*td_params));
		if (!td_params) {
			ast_datastore_free(datastore);
			return -1;
		}

		ast_audiohook_init(&td_params->audiohook,
		                   AST_AUDIOHOOK_TYPE_MANIPULATE,
		                   "TALK_DETECT",
		                   AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
		td_params->audiohook.manipulate_callback = talk_detect_audiohook_cb;
		ast_set_flag(&td_params->audiohook, AST_AUDIOHOOK_TRIGGER_READ);

		td_params->dsp = ast_dsp_new_with_rate(ast_format_get_sample_rate(ast_channel_rawreadformat(chan)));
		if (!td_params->dsp) {
			ast_datastore_free(datastore);
			ast_free(td_params);
			return -1;
		}
		datastore->data = td_params;

		ast_channel_datastore_add(chan, datastore);
		ast_audiohook_attach(chan, &td_params->audiohook);
	} else {
		/* Talk detection already enabled; update existing settings */
		td_params = datastore->data;
	}

	td_params->dsp_talking_threshold = dsp_talking_threshold;
	td_params->dsp_silence_threshold = dsp_silence_threshold;

	ast_dsp_set_threshold(td_params->dsp, td_params->dsp_talking_threshold);

	return 0;
}
/** \brief Try to get result */
struct ast_speech_result* uni_recog_get(struct ast_speech *speech)
{
	struct ast_speech_result *result;
	mrcp_recog_header_t *recog_header;

	uni_speech_t *uni_speech = speech->data;

	if(uni_speech->is_inprogress) {
		uni_recog_stop(speech);
	}

	if(!uni_speech->mrcp_event) {
		ast_log(LOG_WARNING, "(%s) No RECOGNITION-COMPLETE message received\n",uni_speech->name);
		return NULL;
	}

	/* Get recognizer header */
	recog_header = mrcp_resource_header_get(uni_speech->mrcp_event);
	if(!recog_header || mrcp_resource_header_property_check(uni_speech->mrcp_event,RECOGNIZER_HEADER_COMPLETION_CAUSE) != TRUE) {
		ast_log(LOG_WARNING, "(%s) Missing completion cause in RECOGNITION-COMPLETE message\n",uni_speech->name);
		return NULL;
	}

	ast_log(LOG_NOTICE, "(%s) Get result completion cause: %03d reason: %s\n",
			uni_speech->name,
			recog_header->completion_cause,
			recog_header->completion_reason.buf ? recog_header->completion_reason.buf : "none");

	if(recog_header->completion_cause != RECOGNIZER_COMPLETION_CAUSE_SUCCESS) {
		ast_log(LOG_WARNING, "(%s) Recognition completed abnormally cause: %03d reason: %s\n",
				uni_speech->name,
				recog_header->completion_cause,
				recog_header->completion_reason.buf ? recog_header->completion_reason.buf : "none");
		return NULL;
	}

	result = uni_recog_speech_result_build(
					uni_speech,
					&uni_speech->mrcp_event->body,
					uni_speech->mrcp_event->start_line.version);
	if(result)
		ast_set_flag(speech,AST_SPEECH_HAVE_RESULTS);

	return result;
}
Esempio n. 22
0
static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook)
{
	int res = 0;

	ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, ast_channel_name(autochan->chan));

	ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC | AST_AUDIOHOOK_SMALL_QUEUE);
	res = ast_audiohook_attach(autochan->chan, audiohook);

	if (!res) {
		ast_channel_lock(autochan->chan);
		if (ast_channel_is_bridged(autochan->chan)) {
			ast_softhangup_nolock(autochan->chan, AST_SOFTHANGUP_UNBRIDGE);
		}
		ast_channel_unlock(autochan->chan);
	}
	return res;
}
Esempio n. 23
0
static int parse_dtls_attrib(struct ast_sip_session_media *session_media,
	const struct pjmedia_sdp_session *sdp,
	const struct pjmedia_sdp_media *stream)
{
	int i;

	for (i = 0; i < sdp->attr_count; i++) {
		apply_dtls_attrib(session_media, sdp->attr[i]);
	}

	for (i = 0; i < stream->attr_count; i++) {
		apply_dtls_attrib(session_media, stream->attr[i]);
	}

	ast_set_flag(session_media->srtp, AST_SRTP_CRYPTO_OFFER_OK);

	return 0;
}
Esempio n. 24
0
/** \brief Try to get result */
struct ast_speech_result* uni_recog_get(struct ast_speech *speech)
{
	mrcp_recog_header_t *recog_header;

	uni_speech_t *uni_speech = speech->data;

	if(uni_speech->is_inprogress) {
		uni_recog_stop(speech);
	}

	ast_log(LOG_NOTICE, "Get result '%s'\n",uni_speech_id_get(uni_speech));
	if(!uni_speech->mrcp_event) {
		ast_log(LOG_WARNING, "No RECOGNITION-COMPLETE message received\n");
		return NULL;
	}

	/* Get recognizer header */
	recog_header = mrcp_resource_header_get(uni_speech->mrcp_event);
	if(!recog_header || mrcp_resource_header_property_check(uni_speech->mrcp_event,RECOGNIZER_HEADER_COMPLETION_CAUSE) != TRUE) {
		ast_log(LOG_WARNING, "Missing Completion-Cause in RECOGNITION-COMPLETE message\n");
		return NULL;
	}

	if(recog_header->completion_cause != RECOGNIZER_COMPLETION_CAUSE_SUCCESS) {
		ast_log(LOG_WARNING, "Unsuccessful completion cause:%d reason:%s\n",
			recog_header->completion_cause,
			recog_header->completion_reason.buf ? recog_header->completion_reason.buf : "none");
		return NULL;
	}

	if(speech->results) {
		ast_speech_results_free(speech->results);
	}

	speech->results = uni_recog_speech_result_build(
		&uni_speech->mrcp_event->body,
		uni_speech->mrcp_event->start_line.version,
		mrcp_application_session_pool_get(uni_speech->session));
	
	if(speech->results) {
		ast_set_flag(speech,AST_SPEECH_HAVE_RESULTS);
	}
	return speech->results;
}
/** \brief Received MRCP message */
static apt_bool_t on_message_receive(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message)
{
	uni_speech_t *uni_speech = mrcp_application_channel_object_get(channel);

	if(message->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) {
		ast_log(LOG_DEBUG, "(%s) Received MRCP response method-id: %d status-code: %d req-state: %d\n",
				uni_speech->name,
				(int)message->start_line.method_id,
				message->start_line.status_code,
				(int)message->start_line.request_state);
		return uni_recog_mrcp_response_signal(uni_speech,message);
	}

	if(message->start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
		if(message->start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) {
			ast_log(LOG_DEBUG, "(%s) Recognition complete req-state: %d\n",
					uni_speech->name,
					(int)message->start_line.request_state);
			uni_speech->is_inprogress = FALSE;
			if (uni_speech->speech_base->state != AST_SPEECH_STATE_NOT_READY) {
				uni_speech->mrcp_event = message;
				ast_speech_change_state(uni_speech->speech_base,AST_SPEECH_STATE_DONE);
			}
			else {
				ast_log(LOG_DEBUG, "(%s) Unexpected RECOGNITION-COMPLETE event\n",uni_speech->name);
			}
		}
		else if(message->start_line.method_id == RECOGNIZER_START_OF_INPUT) {
			ast_log(LOG_DEBUG, "(%s) Start of input\n",uni_speech->name);
			ast_set_flag(uni_speech->speech_base, AST_SPEECH_QUIET | AST_SPEECH_SPOKE);
		}
		else {
			ast_log(LOG_DEBUG, "(%s) Received unhandled MRCP event id: %d req-state: %d\n",
					uni_speech->name,
					(int)message->start_line.method_id,
					(int)message->start_line.request_state);
		}
	}

	return TRUE;
}
Esempio n. 26
0
static struct ast_channel *announce_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
{
	struct ast_channel *chan;
	const char *conf_name = data;
	RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
	RAII_VAR(struct announce_pvt *, pvt, NULL, ao2_cleanup);

	conference = ao2_find(conference_bridges, conf_name, OBJ_KEY);
	if (!conference) {
		return NULL;
	}
	ast_assert(conference->bridge != NULL);

	/* Allocate a new private structure and then Asterisk channels */
	pvt = (struct announce_pvt *) ast_unreal_alloc(sizeof(*pvt), announce_pvt_destructor,
		cap);
	if (!pvt) {
		return NULL;
	}
	ast_set_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION);
	ast_copy_string(pvt->base.name, conf_name, sizeof(pvt->base.name));
	pvt->bridge = conference->bridge;
	ao2_ref(pvt->bridge, +1);

	chan = ast_unreal_new_channels(&pvt->base, conf_announce_get_tech(),
		AST_STATE_UP, AST_STATE_UP, NULL, NULL, assignedids, requestor, 0);
	if (chan) {
		ast_answer(pvt->base.owner);
		ast_answer(pvt->base.chan);
		if (ast_channel_add_bridge_role(pvt->base.chan, "announcer")) {
			ast_hangup(chan);
			chan = NULL;
		}
	}

	return chan;
}
Esempio n. 27
0
static int volume_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
{
	struct ast_datastore *datastore = NULL;
	struct volume_information *vi = NULL;
	int is_new = 0;

	if (!(datastore = ast_channel_datastore_find(chan, &volume_datastore, NULL))) {
		/* Allocate a new datastore to hold the reference to this volume and audiohook information */
		if (!(datastore = ast_datastore_alloc(&volume_datastore, NULL)))
			return 0;
		if (!(vi = ast_calloc(1, sizeof(*vi)))) {
			ast_datastore_free(datastore);
			return 0;
		}
		ast_audiohook_init(&vi->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume");
		vi->audiohook.manipulate_callback = volume_callback;
		ast_set_flag(&vi->audiohook, AST_AUDIOHOOK_WANTS_DTMF);
		is_new = 1;
	} else {
		vi = datastore->data;
	}

	/* Adjust gain on volume information structure */
	if (!strcasecmp(data, "tx"))
		vi->tx_gain = atoi(value);
	else if (!strcasecmp(data, "rx"))
		vi->rx_gain = atoi(value);

	if (is_new) {
		datastore->data = vi;
		ast_channel_datastore_add(chan, datastore);
		ast_audiohook_attach(chan, &vi->audiohook);
	}

	return 0;
}
Esempio n. 28
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 peer_name[AST_NAME_STRLEN + 5];
	char exitcontext[AST_MAX_CONTEXT] = "";
	signed char zero_volume = 0;
	int waitms;
	int res;
	char *ptr;
	int num;
	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(chan->macrocontext)) {
			ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext));
		} else {
			ast_copy_string(exitcontext, chan->context, sizeof(exitcontext));
		}
		ast_channel_unlock(chan);
	}

	if (chan->_state != AST_STATE_UP)
		ast_answer(chan);

	ast_set_flag(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", chan->language);
			if (!res)
				res = ast_waitstream(chan, "");
			else if (res < 0) {
				ast_clear_flag(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) {
			return -1;
		}

		res = ast_waitfordigit(chan, waitms);
		if (res < 0) {
			ast_clear_flag(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);
		}

		/* 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;
			char *s;

			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(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, autochan->chan->name, sizeof(ext) - 1);
				if ((end = strchr(ext, '-'))) {
					*end++ = ':';
					*end = '\0';
				}

				ext[0] = ':';

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

			if (!ienf) {
				continue;
			}

			strcpy(peer_name, "spy-");
			strncat(peer_name, autochan->chan->name, AST_NAME_STRLEN - 4 - 1);
			ptr = strchr(peer_name, '/');
			*ptr++ = '\0';
			ptr = strsep(&ptr, "-");

			for (s = peer_name; s < ptr; s++)
				*s = tolower(*s);

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

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

			if (res == -1) {
				ast_autochan_destroy(autochan);
				goto exit;
			} else if (res == -2) {
				res = 0;
				ast_autochan_destroy(autochan);
				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)) {
				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(chan, AST_FLAG_SPYING);

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

	return res;
}
Esempio n. 29
0
static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_autochan,
	int *volfactor, int fd, struct spy_dtmf_options *user_options, struct ast_flags *flags,
	char *exitcontext)
{
	struct chanspy_translation_helper csth;
	int running = 0, res, x = 0;
	char inp[24] = {0};
	char *name;
	struct ast_frame *f;
	struct ast_silence_generator *silgen = NULL;
	struct ast_autochan *spyee_bridge_autochan = NULL;
	const char *spyer_name;
	struct ast_channel *chans[] = { chan, spyee_autochan->chan };

	ast_channel_lock(chan);
	spyer_name = ast_strdupa(chan->name);
	ast_channel_unlock(chan);

	/* We now hold the channel lock on spyee */

	if (ast_check_hangup(chan) || ast_check_hangup(spyee_autochan->chan)) {
		return 0;
	}

	ast_channel_lock(spyee_autochan->chan);
	name = ast_strdupa(spyee_autochan->chan->name);
	ast_channel_unlock(spyee_autochan->chan);

	ast_verb(2, "Spying on channel %s\n", name);
	ast_manager_event_multichan(EVENT_FLAG_CALL, "ChanSpyStart", 2, chans,
			"SpyerChannel: %s\r\n"
			"SpyeeChannel: %s\r\n",
			spyer_name, name);

	memset(&csth, 0, sizeof(csth));
	ast_copy_flags(&csth.flags, flags, AST_FLAGS_ALL);

	ast_audiohook_init(&csth.spy_audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy");

	if (start_spying(spyee_autochan, spyer_name, &csth.spy_audiohook)) {
		ast_audiohook_destroy(&csth.spy_audiohook);
		return 0;
	}

	ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
	ast_audiohook_init(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy");
	if (start_spying(spyee_autochan, spyer_name, &csth.whisper_audiohook)) {
		ast_log(LOG_WARNING, "Unable to attach whisper audiohook to spyee %s. Whisper mode disabled!\n", name);
	}
	if ((spyee_bridge_autochan = ast_autochan_setup(ast_bridged_channel(spyee_autochan->chan)))) {
		ast_channel_lock(spyee_bridge_autochan->chan);
		if (start_spying(spyee_bridge_autochan, spyer_name, &csth.bridge_whisper_audiohook)) {
			ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee %s. Barge mode disabled!\n", name);
		}
		ast_channel_unlock(spyee_bridge_autochan->chan);
	}

	ast_channel_lock(chan);
	ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
	ast_channel_unlock(chan);

	csth.volfactor = *volfactor;

	if (csth.volfactor) {
		csth.spy_audiohook.options.read_volume = csth.volfactor;
		csth.spy_audiohook.options.write_volume = csth.volfactor;
	}

	csth.fd = fd;

	if (ast_test_flag(flags, OPTION_PRIVATE))
		silgen = ast_channel_start_silence_generator(chan);
	else
		ast_activate_generator(chan, &spygen, &csth);

	/* We can no longer rely on 'spyee' being an actual channel;
	   it can be hung up and freed out from under us. However, the
	   channel destructor will put NULL into our csth.spy.chan
	   field when that happens, so that is our signal that the spyee
	   channel has gone away.
	*/

	/* Note: it is very important that the ast_waitfor() be the first
	   condition in this expression, so that if we wait for some period
	   of time before receiving a frame from our spying channel, we check
	   for hangup on the spied-on channel _after_ knowing that a frame
	   has arrived, since the spied-on channel could have gone away while
	   we were waiting
	*/
	while ((res = ast_waitfor(chan, -1) > -1) && csth.spy_audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
		if (!(f = ast_read(chan)) || ast_check_hangup(chan)) {
			running = -1;
			break;
		}

		if (ast_test_flag(flags, OPTION_BARGE) && f->frametype == AST_FRAME_VOICE) {
			ast_audiohook_lock(&csth.whisper_audiohook);
			ast_audiohook_lock(&csth.bridge_whisper_audiohook);
			ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
			ast_audiohook_write_frame(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
			ast_audiohook_unlock(&csth.whisper_audiohook);
			ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
			ast_frfree(f);
			continue;
		} else if (ast_test_flag(flags, OPTION_WHISPER) && f->frametype == AST_FRAME_VOICE) {
			ast_audiohook_lock(&csth.whisper_audiohook);
			ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
			ast_audiohook_unlock(&csth.whisper_audiohook);
			ast_frfree(f);
			continue;
		}
		
		res = (f->frametype == AST_FRAME_DTMF) ? f->subclass.integer : 0;
		ast_frfree(f);
		if (!res)
			continue;

		if (x == sizeof(inp))
			x = 0;

		if (res < 0) {
			running = -1;
			break;
		}

		if (ast_test_flag(flags, OPTION_EXIT)) {
			char tmp[2];
			tmp[0] = res;
			tmp[1] = '\0';
			if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) {
				ast_debug(1, "Got DTMF %c, goto context %s\n", tmp[0], exitcontext);
				pbx_builtin_setvar_helper(chan, "SPY_CHANNEL", name);
				running = -2;
				break;
			} else {
				ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
			}
		} else if (res >= '0' && res <= '9') {
			if (ast_test_flag(flags, OPTION_DTMF_SWITCH_MODES)) {
				change_spy_mode(res, flags);
			} else {
				inp[x++] = res;
			}
		}

		if (res == user_options->cycle) {
			running = 0;
			break;
		} else if (res == user_options->exit) {
			running = -2;
			break;
		} else if (res == user_options->volume) {
			if (!ast_strlen_zero(inp)) {
				running = atoi(inp);
				break;
			}

			(*volfactor)++;
			if (*volfactor > 4)
				*volfactor = -4;
			ast_verb(3, "Setting spy volume on %s to %d\n", chan->name, *volfactor);

			csth.volfactor = *volfactor;
			csth.spy_audiohook.options.read_volume = csth.volfactor;
			csth.spy_audiohook.options.write_volume = csth.volfactor;
		}
	}

	if (ast_test_flag(flags, OPTION_PRIVATE))
		ast_channel_stop_silence_generator(chan, silgen);
	else
		ast_deactivate_generator(chan);

	ast_channel_lock(chan);
	ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
	ast_channel_unlock(chan);

	ast_audiohook_lock(&csth.whisper_audiohook);
	ast_audiohook_detach(&csth.whisper_audiohook);
	ast_audiohook_unlock(&csth.whisper_audiohook);
	ast_audiohook_destroy(&csth.whisper_audiohook);
	
	ast_audiohook_lock(&csth.bridge_whisper_audiohook);
	ast_audiohook_detach(&csth.bridge_whisper_audiohook);
	ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
	ast_audiohook_destroy(&csth.bridge_whisper_audiohook);

	ast_audiohook_lock(&csth.spy_audiohook);
	ast_audiohook_detach(&csth.spy_audiohook);
	ast_audiohook_unlock(&csth.spy_audiohook);
	ast_audiohook_destroy(&csth.spy_audiohook);

	if (spyee_bridge_autochan) {
		ast_autochan_destroy(spyee_bridge_autochan);
	}

	ast_verb(2, "Done Spying on channel %s\n", name);
	ast_manager_event(chan, EVENT_FLAG_CALL, "ChanSpyStop", "SpyeeChannel: %s\r\n", name);

	return running;
}
Esempio n. 30
0
static int extenspy_exec(struct ast_channel *chan, const char *data)
{
	char *ptr, *exten = NULL;
	char *mygroup = NULL;
	char *recbase = NULL;
	int fd = 0;
	struct ast_flags flags;
	struct spy_dtmf_options user_options = {
		.cycle = '*',
		.volume = '#',
		.exit = '\0',
	};
	int oldwf = 0;
	int volfactor = 0;
	int res;
	char *mailbox = NULL;
	char *name_context = NULL;
	AST_DECLARE_APP_ARGS(args,
		AST_APP_ARG(context);
		AST_APP_ARG(options);
	);
	char *parse = ast_strdupa(data);

	AST_STANDARD_APP_ARGS(args, parse);
	if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context, '@'))) {
		exten = args.context;
		*ptr++ = '\0';
		args.context = ptr;
	}

	if (ast_strlen_zero(args.context))
		args.context = ast_strdupa(chan->context);

	if (args.options) {
		char *opts[OPT_ARG_ARRAY_SIZE];
		char tmp;

		ast_app_parse_options(spy_opts, &flags, opts, args.options);
		if (ast_test_flag(&flags, OPTION_GROUP))
			mygroup = opts[OPT_ARG_GROUP];

		if (ast_test_flag(&flags, OPTION_RECORD) &&
			!(recbase = opts[OPT_ARG_RECORD]))
			recbase = "chanspy";

		if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
			tmp = opts[OPT_ARG_EXIT][0];
			if (strchr("0123456789*#", tmp) && tmp != '\0') {
				user_options.exit = tmp;
			} else {
				ast_log(LOG_NOTICE, "Argument for option 'x' must be a valid DTMF digit.");
			}
		}

		if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
			tmp = opts[OPT_ARG_CYCLE][0];
			if (strchr("0123456789*#", tmp) && tmp != '\0') {
				user_options.cycle = tmp;
			} else {
				ast_log(LOG_NOTICE, "Argument for option 'c' must be a valid DTMF digit.");
			}
		}

		if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
			int vol;

			if ((sscanf(opts[OPT_ARG_VOLUME], "%30d", &vol) != 1) || (vol > 4) || (vol < -4))
				ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
			else
				volfactor = vol;
		}

		if (ast_test_flag(&flags, OPTION_PRIVATE))
			ast_set_flag(&flags, OPTION_WHISPER);

		if (ast_test_flag(&flags, OPTION_NAME)) {
			if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
				char *delimiter;
				if ((delimiter = strchr(opts[OPT_ARG_NAME], '@'))) {
					mailbox = opts[OPT_ARG_NAME];
					*delimiter++ = '\0';
					name_context = delimiter;
				} else {
					mailbox = opts[OPT_ARG_NAME];
				}
			}
		}

	} else {
		ast_clear_flag(&flags, AST_FLAGS_ALL);
	}

	oldwf = chan->writeformat;
	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
		return -1;
	}

	if (recbase) {
		char filename[PATH_MAX];

		snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
		if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
			ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
			fd = 0;
		}
	}


	res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, NULL, NULL, exten, args.context, mailbox, name_context);

	if (fd)
		close(fd);

	if (oldwf && ast_set_write_format(chan, oldwf) < 0)
		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");

	return res;
}