Esempio n. 1
0
/*!
 * \internal
 * \brief Check if Monitor needs to be started on a channel.
 * \since 12.0.0
 *
 * \param chan The bridge considers this channel the caller.
 * \param peer The bridge considers this channel the callee.
 *
 * \return Nothing
 */
static void bridge_check_monitor(struct ast_channel *chan, struct ast_channel *peer)
{
	const char *value;
	const char *monitor_args = NULL;
	struct ast_channel *monitor_chan = NULL;

	ast_channel_lock(chan);
	value = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR");
	if (!ast_strlen_zero(value)) {
		monitor_args = ast_strdupa(value);
		monitor_chan = chan;
	}
	ast_channel_unlock(chan);
	if (!monitor_chan) {
		ast_channel_lock(peer);
		value = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR");
		if (!ast_strlen_zero(value)) {
			monitor_args = ast_strdupa(value);
			monitor_chan = peer;
		}
		ast_channel_unlock(peer);
	}
	if (monitor_chan) {
		struct ast_app *monitor_app;

		monitor_app = pbx_findapp("Monitor");
		if (monitor_app) {
			pbx_exec(monitor_chan, monitor_app, monitor_args);
		}
	}
}
Esempio n. 2
0
static int fax_set_common(struct cw_channel *chan, t30_state_t *t30, const char *file, int calling_party, int verbose)
{
    char *x;

    x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
    if (x  &&  x[0])
        t30_set_tx_ident(t30, x);
    x = pbx_builtin_getvar_helper(chan, "LOCALSUBADDRESS");
    if (x  &&  x[0])
        t30_set_tx_sub_address(t30, x);
    x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
    if (x  &&  x[0])
        t30_set_tx_page_header_info(t30, x);
    t30_set_rx_file(t30, file, -1);

    x = pbx_builtin_getvar_helper(chan, "FAX_DISABLE_V17");
    if (x  &&  x[0])
        t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER);

    x = pbx_builtin_getvar_helper(chan, "FAX_DISABLE_ECM");
    if (x  &&  x[0])
    {
        t30_set_supported_compressions(t30,
                                       T30_SUPPORT_T4_1D_COMPRESSION
                                     | T30_SUPPORT_T4_2D_COMPRESSION);
        cw_log(LOG_DEBUG, "Disabling ECM mode\n");
    }
    else 
    {
        t30_set_ecm_capability(t30, TRUE);
        t30_set_supported_compressions(t30,
                                       T30_SUPPORT_T4_1D_COMPRESSION
                                     | T30_SUPPORT_T4_2D_COMPRESSION
                                     | T30_SUPPORT_T6_COMPRESSION);
    }

    t30_set_supported_image_sizes(t30,
                                  T30_SUPPORT_US_LETTER_LENGTH
                                | T30_SUPPORT_US_LEGAL_LENGTH
                                | T30_SUPPORT_UNLIMITED_LENGTH
                                | T30_SUPPORT_215MM_WIDTH
                                | T30_SUPPORT_255MM_WIDTH
                                | T30_SUPPORT_303MM_WIDTH);
    t30_set_supported_resolutions(t30,
                                  T30_SUPPORT_STANDARD_RESOLUTION
                                | T30_SUPPORT_FINE_RESOLUTION
                                | T30_SUPPORT_SUPERFINE_RESOLUTION
                                | T30_SUPPORT_R8_RESOLUTION
                                | T30_SUPPORT_R16_RESOLUTION);

    //t30_set_phase_b_handler(t30, phase_b_handler, chan);
    t30_set_phase_d_handler(t30, phase_d_handler, chan);
    t30_set_phase_e_handler(t30, phase_e_handler, chan);

    return 0;
}
Esempio n. 3
0
static void set_local_info(t30_state_t *state, fax_session *s)
{
	const char *x;

	x = pbx_builtin_getvar_helper(s->chan, "LOCALSTATIONID");
	if (!ast_strlen_zero(x))
		t30_set_tx_ident(state, x);

	x = pbx_builtin_getvar_helper(s->chan, "LOCALHEADERINFO");
	if (!ast_strlen_zero(x))
		t30_set_tx_page_header_info(state, x);
}
Esempio n. 4
0
static int morsecode_exec(struct ast_channel *chan, void *data)
{
	int res=0, ditlen, tone;
	char *digit;
	const char *ditlenc, *tonec;
	struct ast_module_user *u;

	u = ast_module_user_add(chan);

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
		ast_module_user_remove(u);
		return 0;
	}

	/* Use variable MORESEDITLEN, if set (else 80) */
	ditlenc = pbx_builtin_getvar_helper(chan, "MORSEDITLEN");
	if (ast_strlen_zero(ditlenc) || (sscanf(ditlenc, "%30d", &ditlen) != 1)) {
		ditlen = 80;
	}

	/* Use variable MORSETONE, if set (else 800) */
	tonec = pbx_builtin_getvar_helper(chan, "MORSETONE");
	if (ast_strlen_zero(tonec) || (sscanf(tonec, "%30d", &tone) != 1)) {
		tone = 800;
	}

	for (digit = data; *digit; digit++) {
		int digit2 = *digit;
		char *dahdit;
		if (digit2 < 0) {
			continue;
		}
		for (dahdit = morsecode[digit2]; *dahdit; dahdit++) {
			if (*dahdit == '-') {
				playtone(chan, tone, 3 * ditlen);
			} else if (*dahdit == '.') {
				playtone(chan, tone, 1 * ditlen);
			} else {
				/* Account for ditlen of silence immediately following */
				playtone(chan, 0, 2 * ditlen);
			}

			/* Pause slightly between each dit and dah */
			playtone(chan, 0, 1 * ditlen);
		}
		/* Pause between characters */
		playtone(chan, 0, 2 * ditlen);
	}

	ast_module_user_remove(u);
	return res;
}
Esempio n. 5
0
static void ast_eivr_getvariable(struct ast_channel *chan, char *data, char *outbuf, int outbuflen)
{
	/* original input data: "G,var1,var2," */
	/* data passed as "data":  "var1,var2" */

	char *inbuf, *variable;
	const char *value;
	int j;
	struct ast_str *newstring = ast_str_alloca(outbuflen); 

	outbuf[0] = '\0';

	for (j = 1, inbuf = data; ; j++) {
		variable = strsep(&inbuf, ",");
		if (variable == NULL) {
			int outstrlen = strlen(outbuf);
			if (outstrlen && outbuf[outstrlen - 1] == ',') {
				outbuf[outstrlen - 1] = 0;
			}
			break;
		}
		
		ast_channel_lock(chan);
		if (!(value = pbx_builtin_getvar_helper(chan, variable))) {
			value = "";
		}

		ast_str_append(&newstring, 0, "%s=%s,", variable, value);
		ast_channel_unlock(chan);
		ast_copy_string(outbuf, ast_str_buffer(newstring), outbuflen);
	}
}
Esempio n. 6
0
int cw_app_group_match_get_count(char *groupmatch, char *category)
{
	regex_t regexbuf;
	struct cw_channel *chan;
	int count = 0;
	char *test;
	char cat[80];
	char *s;

	if (cw_strlen_zero(groupmatch))
		return 0;

	/* if regex compilation fails, return zero matches */
	if (regcomp(&regexbuf, groupmatch, REG_EXTENDED | REG_NOSUB))
		return 0;

	s = (!cw_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX;
	cw_copy_string(cat, s, sizeof(cat));

	chan = NULL;
	while ((chan = cw_channel_walk_locked(chan)) != NULL) {
		test = pbx_builtin_getvar_helper(chan, cat);
		if (test && !regexec(&regexbuf, test, 0, NULL, 0))
			count++;
		cw_mutex_unlock(&chan->lock);
	}

	regfree(&regexbuf);

	return count;
}
Esempio n. 7
0
char *replace_cw_vars(struct cw_channel *chan, const char *_string)
{
	char *var_start, *var_end, *key, *value, *string;
	int begin, end;
	if (!_string) return "";
	string = (char *)malloc((strlen(_string)+1)*sizeof(char));
	memcpy(string, _string, strlen(_string)+1);

	while((var_start = strstr(string, "${")) && (var_end = strchr(var_start,'}'))) {
		begin = strlen(string)-strlen(var_start); 
		end = strlen(string)-strlen(var_end);
		key = (char *)alloca((end-begin-1)*sizeof(char));
		memcpy(key, var_start+2, end-begin-2);
		key[end-begin-2] = '\0';
		value = pbx_builtin_getvar_helper(chan, key);
		if (value) { 
			string = (char *)realloc(string, (strlen(string)-(end-begin+1)+strlen(value)+1)*sizeof(char));
			memmove(var_start+strlen(value), var_end+1, strlen(var_end+1)+1);
			memcpy(var_start, value, strlen(value));
		} else {
			memmove(var_start, var_end+1, strlen(var_end+1)+1);
		}
	}
	return string;
}
Esempio n. 8
0
static int checkMax(struct ast_channel *chan, struct roomdetails *dtmfmatch)
{
	int res=0;
    	struct ast_app *app;
	char getvar[30]="AstVar";
	char roomno[30]="";
	char maxusers[30]="";
	char currentusers[30]="";
	char prompt[50]="";
	char arg[255]="";

    	strcpy(maxusers,dtmfmatch->maxusers);
	strcpy(roomno,dtmfmatch->roomno);
    	strcat(arg,roomno);
    	strcat(arg,",");
	strcat(arg,getvar);

	if(!(app = pbx_findapp(ConfAppCount))) {
		ast_log(LOG_WARNING, "Invalid participant count application: %s\n", ConfAppCount);
		return -1;
	}
 	res = pbx_exec(chan, app, arg);
   	strcpy(currentusers, pbx_builtin_getvar_helper(chan, getvar));
	if(atoi(currentusers) < atoi(maxusers)){
	ast_log(LOG_NOTICE, "Currentusers: %i\n", atoi(currentusers));
		if(atoi(currentusers)>0){
			strcpy(prompt,"conf-thereare");
			if (!ast_streamfile(chan, "conf-thereare", chan->language)){
				res = ast_waitstream(chan,"");
				ast_stopstream(chan);
				
				if (!ast_say_number(chan, (atoi(currentusers)), AST_DIGIT_ANY, chan->language, (char *) NULL)){
					res = ast_waitstream(chan,"");
					ast_stopstream(chan);
				}
				if (!ast_streamfile(chan, "conf-otherinparty", chan->language)){
					res = ast_waitstream(chan,"");
					ast_stopstream(chan);
				}
			}
		}
		res=1;
	}
	else{
        	ast_log(LOG_NOTICE, "Maximum users exeeded, Current users in room: %s\n",currentusers);
        	strcpy(prompt, "conf-locked");
        	if (!ast_streamfile(chan, prompt, chan->language)){
        		res = ast_waitstream(chan,"");
			ast_stopstream(chan);
		}
		res=-1;
	}
	return res;
}
Esempio n. 9
0
static int global_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
	const char *var = pbx_builtin_getvar_helper(NULL, data);

	*buf = '\0';

	if (var)
		ast_copy_string(buf, var, len);

	return 0;
}
static int mcd_write(
	struct ast_channel *chan, const char *cmd, char *parse, const char *value
) {

	memcached_return_t rc;
	memcached_st *mcd = memcached_pool_fetch(mcdpool, &to, &rc);
	if (rc) {
        ast_log(LOG_WARNING, "mcd_write: memcached pool error: %d\n", rc);
		return 0;
    }

	char *key = (char *)ast_malloc(MEMCACHED_MAX_KEY);
	unsigned int timeout = mcdttl; 

	mcd_set_operation_result(chan, MEMCACHED_SUCCESS);

	// the app argument is the key to set
	if (ast_strlen_zero(parse)) {
		ast_log(LOG_WARNING, "MCD() requires argument (key)\n");
		mcd_set_operation_result(chan, MEMCACHED_ARGUMENT_NEEDED);
		free(key);
		return 0;
	}
	strcpy(key, parse);
	ast_log(LOG_DEBUG, "setting value for key: %s=%s\n", key, value);

	const char *ttlval = pbx_builtin_getvar_helper(chan, "MCDTTL");
	if (ttlval) {
		timeout = atoi(ttlval);
		if ((timeout == 0) && (strcmp(ttlval, "0") != 0)) {
			ast_log(LOG_WARNING, "dialplan variable MCDTTL=%s (not numeric), will use time-to-live value in the config file\n", ttlval);
			timeout = mcdttl;
		}
	}
	ast_log(LOG_DEBUG, "timeout: %d\n", timeout);

	memcached_return_t mcdret = MEMCACHED_FAILURE;
	mcdret = memcached_set(mcd, 
		key, strlen(key), value, strlen(value), (time_t)timeout, (uint32_t)0
	);
	if (mcdret)
		ast_log(LOG_WARNING, 
			"memcached_%s() error %d: %s\n", cmd, mcdret, memcached_strerror(mcd, mcdret)
		);

	mcd_set_operation_result(chan, mcdret);
	free(key);
	memcached_pool_release(mcdpool, mcd);
	return 0;

}
Esempio n. 11
0
static int return_exec(struct ast_channel *chan, void *data)
{
	char *label = pbx_builtin_getvar_helper(chan, STACKVAR);

	if (ast_strlen_zero(label)) {
		ast_log(LOG_ERROR, "Return without Gosub: stack is empty\n");
		return -1;
	} else if (ast_parseable_goto(chan, label)) {
		ast_log(LOG_WARNING, "No next statement after Gosub?\n");
		return -1;
	}

	pbx_builtin_setvar_helper(chan, STACKVAR, NULL);
	return 0;
}
Esempio n. 12
0
static int find_by_mark(void *obj, void *arg, void *data, int flags)
{
	struct ast_channel *target = obj;/*!< Potential pickup target */
	const char *mark = data;
	const char *tmp;

	ast_channel_lock(target);
	tmp = pbx_builtin_getvar_helper(target, PICKUPMARK);
	if (tmp && !strcasecmp(tmp, mark) && ast_can_pickup(target)) {
		/* Return with the channel still locked on purpose */
		return CMP_MATCH | CMP_STOP;
	}
	ast_channel_unlock(target);

	return 0;
}
Esempio n. 13
0
static void macro_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
{
	int i;
	char varname[10];
	pbx_builtin_setvar_helper(new_chan, "MACRO_DEPTH", "0");
	pbx_builtin_setvar_helper(new_chan, "MACRO_CONTEXT", NULL);
	pbx_builtin_setvar_helper(new_chan, "MACRO_EXTEN", NULL);
	pbx_builtin_setvar_helper(new_chan, "MACRO_PRIORITY", NULL);
	pbx_builtin_setvar_helper(new_chan, "MACRO_OFFSET", NULL);
	for (i = 1; i < 100; i++) {
		snprintf(varname, sizeof(varname), "ARG%d", i);
		while (pbx_builtin_getvar_helper(new_chan, varname)) {
			/* Kill all levels of arguments */
			pbx_builtin_setvar_helper(new_chan, varname, NULL);
		}
	}
}
static void set_touch_variable(enum set_touch_variables_res *res, struct ast_channel *chan, const char *var_name, char **touch)
{
	const char *c_touch;

	if (*res == SET_TOUCH_ALLOC_FAILURE) {
		return;
	}
	c_touch = pbx_builtin_getvar_helper(chan, var_name);
	if (!ast_strlen_zero(c_touch)) {
		*touch = ast_strdup(c_touch);
		if (!*touch) {
			*res = SET_TOUCH_ALLOC_FAILURE;
		} else {
			*res = SET_TOUCH_SUCCESS;
		}
	}
}
Esempio n. 15
0
/* Attempt to pick up specified mark */
static int pickup_by_mark(struct ast_channel *chan, char *mark)
{
	int res = -1;
	const char *tmp = NULL;
	struct ast_channel *target = NULL;

	while ((target = ast_channel_walk_locked(target))) {
		if ((tmp = pbx_builtin_getvar_helper(target, PICKUPMARK)) &&
		    !strcasecmp(tmp, mark) &&
		    can_pickup(target)) {
			res = pickup_do(chan, target);
			ast_channel_unlock(target);
			break;
		}
		ast_channel_unlock(target);
	}

	return res;
}
Esempio n. 16
0
int cw_app_group_get_count(char *group, char *category)
{
	struct cw_channel *chan;
	int count = 0;
	char *test;
	char cat[80];
	char *s;

	if (cw_strlen_zero(group))
		return 0;

 	s = (!cw_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX;
	cw_copy_string(cat, s, sizeof(cat));

	chan = NULL;
	while ((chan = cw_channel_walk_locked(chan)) != NULL) {
 		test = pbx_builtin_getvar_helper(chan, cat);
		if (test && !strcasecmp(test, group))
 			count++;
		cw_mutex_unlock(&chan->lock);
	}

	return count;
}
Esempio n. 17
0
/*!
 * \brief Receive Ademco ContactID or other format Data String
 *
 * \param chan Asterisk Channel
 * \param ehead Pointer to events list
 * \param signalling_type Expected signalling type for the message
 * \param no_checksum Should we calculate checksum for the message
 *
 * \retval 0 success
 * \retval -1 failure
 */
static int receive_ademco_event(struct ast_channel *chan, event_node_t **ehead, char *signalling_type, int *no_checksum)
{
	int res = 0;
	const char *limit;
	char event[17];
	event_node_t *enew, *elp;
	int got_some_digits = 0;
	int events_received = 0;
	int ack_retries = 0;
	int limit_retries = 0;
	int expected_length = sizeof(event) - 1;

	database_increment("calls-received");

	/* Wait for first event */
	ast_verb(4, "AlarmReceiver: Waiting for first event from panel...\n");

	while (res >= 0) {
		int digits_received = 0;

		res = 0;

		if (log_individual_events) {
			sprintf(signalling_type, "%s", UNKNOWN_FORMAT);
			expected_length = 16;
			*no_checksum = 0;
		}

		if (got_some_digits == 0) {
			/* Send ACK tone sequence */
			ast_verb(4, "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
			res = send_tone_burst(chan, "1400", 100, 0);
			if (!res) {
				ast_verb(4, "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
				res = send_tone_burst(chan, "2300", 100, 100);
			}
		}
		if (res) {
			return -1;
		}

		res = receive_dtmf_digits(chan, event, sizeof(event), expected_length, &digits_received);
		if (res < 0) {
			if (events_received == 0) {
				/* Hangup with no events received should be logged in the DB */
				database_increment("no-events-received");
				ast_verb(4, "AlarmReceiver: No events received!\n");
			} else {
				if (ack_retries) {
					database_increment("ack-retries");
					ast_verb(4, "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
				}
			}
			ast_verb(4, "AlarmReceiver: App exiting...\n");
			break;
		}

		if (!strcmp(signalling_type, UNKNOWN_FORMAT) && digits_received > 5) {
			expected_length = ademco_detect_format(signalling_type, event, no_checksum);

			if (res > 0) {
				if (digits_received == expected_length) {
					res = limit_retries = 0;
				} else if (digits_received == expected_length - 1
					&& (!strcmp(signalling_type, ADEMCO_EXPRESS_4_2)
					|| !strcmp(signalling_type, ADEMCO_EXPRESS_4_1))) {
					/* ADEMCO EXPRESS without checksum */
					res = limit_retries = 0;
					expected_length--;
					*no_checksum = 1;
					ast_verb(4, "AlarmMonitoring: Skipping checksum for format %s.\n", signalling_type);
					ast_debug(1, "AlarmMonitoring: Skipping checksum for format %s.\n", signalling_type);
				}
			}
		}

		ast_channel_lock(chan);
		limit = pbx_builtin_getvar_helper(chan, "ALARMRECEIVER_CALL_LIMIT");
		if (!ast_strlen_zero(limit)) {
			if (ast_tvdiff_ms(ast_tvnow(), call_start_time) > atoi(limit)) {
				ast_channel_unlock(chan);
				return -1;
			}
		}
		limit = pbx_builtin_getvar_helper(chan, "ALARMRECEIVER_RETRIES_LIMIT");
		ast_channel_unlock(chan);
		if (!ast_strlen_zero(limit)) {
			if (limit_retries + 1 >= atoi(limit)) {
				return -1;
			}
		}

		if (res) {
			/* Didn't get all of the digits */
			ast_verb(2, "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
			limit_retries++;

			if (!events_received && strcmp(signalling_type, UNKNOWN_FORMAT))
			{
				sprintf(signalling_type, "%s", UNKNOWN_FORMAT);
				expected_length = sizeof(event) - 1;
			}

			if (!got_some_digits) {
				got_some_digits = (!ast_strlen_zero(event)) ? 1 : 0;
				ack_retries++;
			}
			continue;
		}

		got_some_digits = 1;

		ast_verb(2, "AlarmReceiver: Received Event %s\n", event);
		ast_debug(1, "AlarmReceiver: Received event: %s\n", event);

		/* Calculate checksum */
		if (!(*no_checksum) && ademco_verify_checksum(event, expected_length)) {
			database_increment("checksum-errors");
			ast_verb(2, "AlarmReceiver: Nonzero checksum\n");
			ast_debug(1, "AlarmReceiver: Nonzero checksum\n");
			continue;
		}

		/* Check the message type for correctness */
		if (ademco_check_valid(signalling_type, event)) {
			database_increment("format-errors");
			ast_verb(2, "AlarmReceiver: Wrong message type\n");
			ast_debug(1, "AlarmReceiver: Wrong message type\n");
			continue;
		}

		events_received++;

		/* Queue the Event */
		if (!(enew = ast_calloc(1, sizeof(*enew)))) {
			return -1;
		}

		enew->next = NULL;
		ast_copy_string(enew->data, event, sizeof(enew->data));

		/* Insert event onto end of list */
		if (*ehead == NULL) {
			*ehead = enew;
		} else {
			for (elp = *ehead; elp->next != NULL; elp = elp->next) {
				;
			}
			elp->next = enew;
		}

		/* Let the user have the option of logging the single event before sending the kissoff tone */
		if (log_individual_events && log_events(chan, signalling_type, enew, *no_checksum)) {
			return -1;
		}

		/* Send the kissoff tone (1400 Hz, 900 ms, after 200ms delay) */
		if (send_tone_burst(chan, "1400", 900, 200)) {
			return -1;
		}

		/* If audio call follows, exit alarm receiver app */
		if (!strcmp(signalling_type, ADEMCO_CONTACT_ID)
			&& !strncmp(event + 7, ADEMCO_AUDIO_CALL_NEXT, 3)) {
			ast_verb(4, "AlarmReceiver: App exiting... Audio call next!\n");
			return 0;
		}
	}

	return res;
}
Esempio n. 18
0
static int conf_do_originate(struct cw_conf_member *member, char *ext) {
    int res;

    pthread_t th;
    pthread_attr_t attr;
    struct fast_originate_helper *fast = malloc(sizeof(struct fast_originate_helper));

    char dst[80]="";
    char appdata[80]="";
    char *var;
    
    if (!fast) {
	res = -1;
    } else {
	memset(fast, 0, sizeof(struct fast_originate_helper));

	if (  (var = pbx_builtin_getvar_helper(member->chan, "NCONF_OUTBOUND_TIMEOUT")) ) {
	    fast->timeout = atoi(var) * 1000;
	} else
	    fast->timeout = 30000;

	strcat(dst,ext);
	strcat(dst,"@");
	if ( (var = pbx_builtin_getvar_helper(member->chan, "NCONF_OUTBOUND_CONTEXT")) )
	    strcat(dst,var);
	else
	    strcat(dst,member->chan->context);


	strcat(appdata,member->id);
	strcat(appdata,"/");
	if ( (var = pbx_builtin_getvar_helper(member->chan, "NCONF_OUTBOUND_PARAMS")) )
	    strcat(appdata,var);
	else {
	    strcat(appdata,"Sdq");
#if ENABLE_VAD
	    strcat(appdata,"V");
#endif
	}

	cw_copy_string( fast->tech, 	 "Local", sizeof(fast->tech) );
	cw_copy_string( fast->data, 	 dst, sizeof(fast->data) );
	cw_copy_string( fast->app, 	 APP_CONFERENCE_NAME, sizeof(fast->app) );
	cw_copy_string( fast->appdata, appdata, sizeof(fast->appdata) );

	if ( (var = pbx_builtin_getvar_helper(member->chan, "NCONF_OUTBOUND_CID_NAME")) )
	    cw_copy_string( fast->cid_name, var, sizeof(fast->cid_name) );
	else
	    cw_copy_string( fast->cid_name,"NavyConference",sizeof(fast->cid_name) );

	if ( (var = pbx_builtin_getvar_helper(member->chan, "NCONF_OUTBOUND_CID_NUM")) )
	    cw_copy_string( fast->cid_num, var,sizeof(fast->cid_num) );
	else
	    cw_copy_string( fast->cid_num, member->id,sizeof(fast->cid_num) );

	cw_copy_string( fast->context, "internal", sizeof(fast->context) );
	cw_copy_string( fast->exten, ext, sizeof(fast->exten) );
	fast->priority = 1;
	fast->vars=NULL;
/**/

	fast->frommember=member;

        pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	if (cw_pthread_create(&th, &attr, fast_originate, fast)) {
    	    free(fast);
	    res = -1;
	} else {
	    res = 0;
	}

    }

    cw_mutex_unlock(&member->chan->lock);
    cw_conf_member_genactivate( member ) ;

    return res;
}
Esempio n. 19
0
/* Stop monitoring a channel */
int ast_monitor_stop(struct ast_channel *chan, int need_lock)
{
	int delfiles = 0;

	LOCK_IF_NEEDED(chan, need_lock);

	if (chan->monitor) {
		char filename[ FILENAME_MAX ];

		if (chan->monitor->read_stream) {
			ast_closestream(chan->monitor->read_stream);
		}
		if (chan->monitor->write_stream) {
			ast_closestream(chan->monitor->write_stream);
		}

		if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) {
			if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
				snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
				if (ast_fileexists(filename, NULL, NULL) > 0) {
					ast_filedelete(filename, NULL);
				}
				ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
			} else {
				ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
			}

			if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
				snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
				if (ast_fileexists(filename, NULL, NULL) > 0) {
					ast_filedelete(filename, NULL);
				}
				ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
			} else {
				ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
			}
		}

		if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
			char tmp[1024];
			char tmp2[1024];
			char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
			char *name = chan->monitor->filename_base;
			int directory = strchr(name, '/') ? 1 : 0;
			char *dir = directory ? "" : ast_config_AST_MONITOR_DIR;
			const char *execute, *execute_args;

			/* Set the execute application */
			execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");
			if (ast_strlen_zero(execute)) { 
				execute = "nice -n 19 soxmix";
				delfiles = 1;
			} 
			execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
			if (ast_strlen_zero(execute_args)) {
				execute_args = "";
			}
			
			snprintf(tmp, sizeof(tmp), "%s \"%s/%s-in.%s\" \"%s/%s-out.%s\" \"%s/%s.%s\" %s &", execute, dir, name, format, dir, name, format, dir, name, format,execute_args);
			if (delfiles) {
				snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name); /* remove legs when done mixing */
				ast_copy_string(tmp, tmp2, sizeof(tmp));
			}
			ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
			if (ast_safe_system(tmp) == -1)
				ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
		}
		
		free(chan->monitor->format);
		free(chan->monitor);
		chan->monitor = NULL;
	}

	UNLOCK_IF_NEEDED(chan, need_lock);

	return 0;
}
Esempio n. 20
0
static int _while_exec(struct cw_channel *chan, int argc, char **argv, int end)
{
	int res=0;
	struct localuser *u;
	char *while_pri = NULL;
	char *goto_str = NULL, *my_name = NULL;
	char *label = NULL;
	char varname[VAR_SIZE], end_varname[VAR_SIZE];
	const char *prefix = "WHILE";
	size_t size=0;
	int used_index_i = -1, x=0;
	char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";

	if (!end && argc != 1) {
		cw_log(LOG_ERROR, "Syntax: %s\n", while_syntax);
		return -1;
	}

	if (!chan) {
		/* huh ? */
		return -1;
	}

	LOCAL_USER_ADD(u);

	/* dont want run away loops if the chan isn't even up
	   this is up for debate since it slows things down a tad ......
	*/
	if (cw_waitfordigit(chan,1) < 0)
		ALL_DONE(u,-1);


	for (x=0;;x++) {
		if (get_index(chan, prefix, x)) {
			used_index_i = x;
		} else 
			break;
	}
	
	snprintf(used_index, VAR_SIZE, "%d", used_index_i);
	snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
	
	size = strlen(chan->context) + strlen(chan->exten) + 32;
	my_name = alloca(size);
	snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority);
	
	if (cw_strlen_zero(label)) {
		if (end) 
			label = used_index;
		else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
			label = new_index;
			pbx_builtin_setvar_helper(chan, my_name, label);
		}
		
	}
	
	snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
	while_pri = pbx_builtin_getvar_helper(chan, varname);
	
	if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
		snprintf(end_varname, VAR_SIZE, "END_%s", varname);
	}
	

	if (!end && !cw_true(argv[0])) {
		/* Condition Met (clean up helper vars) */
		pbx_builtin_setvar_helper(chan, varname, NULL);
		pbx_builtin_setvar_helper(chan, my_name, NULL);
		snprintf(end_varname, VAR_SIZE, "END_%s", varname);
		if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) {
			pbx_builtin_setvar_helper(chan, end_varname, NULL);
			cw_parseable_goto(chan, goto_str);
		} else {
			int pri = find_matching_endwhile(chan);
			if (pri > 0) {
				if (option_verbose > 2)
					cw_verbose(VERBOSE_PREFIX_3 "Jumping to priority %d\n", pri);
				chan->priority = pri;
			} else {
				cw_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
			}
		}
		ALL_DONE(u,res);
	}

	if (!end && !while_pri) {
		size = strlen(chan->context) + strlen(chan->exten) + 32;
		goto_str = alloca(size);
		snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority);
		pbx_builtin_setvar_helper(chan, varname, goto_str);
	} 

	else if (end && while_pri) {
		/* END of loop */
		snprintf(end_varname, VAR_SIZE, "END_%s", varname);
		if (! pbx_builtin_getvar_helper(chan, end_varname)) {
			size = strlen(chan->context) + strlen(chan->exten) + 32;
			goto_str = alloca(size);
			snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority+1);
			pbx_builtin_setvar_helper(chan, end_varname, goto_str);
		}
		cw_parseable_goto(chan, while_pri);
	}
	



	ALL_DONE(u, res);
}
Esempio n. 21
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. 22
0
/*! \brief SpeechBackground(Sound File|Timeout) Dialplan Application */
static int speech_background(struct ast_channel *chan, void *data)
{
        unsigned int timeout = 0;
        int res = 0, done = 0, argc = 0, started = 0, quieted = 0, max_dtmf_len = 0;
        struct ast_module_user *u = NULL;
        struct ast_speech *speech = find_speech(chan);
        struct ast_frame *f = NULL;
        int oldreadformat = AST_FORMAT_SLINEAR;
        char dtmf[AST_MAX_EXTENSION] = "";
        time_t start, current;
        struct ast_datastore *datastore = NULL;
        char *argv[2], *args = NULL, *filename_tmp = NULL, *filename = NULL, tmp[2] = "", dtmf_terminator = '#';
	const char *tmp2 = NULL;

        args = ast_strdupa(data);

        u = ast_module_user_add(chan);

        if (speech == NULL) {
                ast_module_user_remove(u);
                return -1;
        }

	/* If channel is not already answered, then answer it */
	if (chan->_state != AST_STATE_UP && ast_answer(chan)) {
		ast_module_user_remove(u);
		return -1;
	}

        /* Record old read format */
        oldreadformat = chan->readformat;

        /* Change read format to be signed linear */
        if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
                ast_module_user_remove(u);
                return -1;
        }

        /* Parse out options */
        argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0]));
        if (argc > 0) {
                /* Yay sound file */
                filename_tmp = ast_strdupa(argv[0]);
		if (!ast_strlen_zero(argv[1])) {
			if ((timeout = atoi(argv[1])) == 0)
				timeout = -1;
		} else
			timeout = 0;
        }

	/* See if the maximum DTMF length variable is set... we use a variable in case they want to carry it through their entire dialplan */
	if ((tmp2 = pbx_builtin_getvar_helper(chan, "SPEECH_DTMF_MAXLEN")) && !ast_strlen_zero(tmp2))
		max_dtmf_len = atoi(tmp2);

	/* See if a terminator is specified */
	if ((tmp2 = pbx_builtin_getvar_helper(chan, "SPEECH_DTMF_TERMINATOR"))) {
		if (ast_strlen_zero(tmp2))
			dtmf_terminator = '\0';
		else
			dtmf_terminator = tmp2[0];
	}

        /* Before we go into waiting for stuff... make sure the structure is ready, if not - start it again */
        if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
		ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
                ast_speech_start(speech);
        }

	/* Ensure no streams are currently running */
	ast_stopstream(chan);

        /* Okay it's streaming so go into a loop grabbing frames! */
        while (done == 0) {
		/* If the filename is null and stream is not running, start up a new sound file */
		if (!quieted && (chan->streamid == -1 && chan->timingfunc == NULL) && (filename = strsep(&filename_tmp, "&"))) {
			/* Discard old stream information */
			ast_stopstream(chan);
			/* Start new stream */
			speech_streamfile(chan, filename, chan->language);
		}

                /* Run scheduled stuff */
                ast_sched_runq(chan->sched);

                /* Yay scheduling */
                res = ast_sched_wait(chan->sched);
                if (res < 0) {
                        res = 1000;
                }

                /* If there is a frame waiting, get it - if not - oh well */
                if (ast_waitfor(chan, res) > 0) {
                        f = ast_read(chan);
                        if (f == NULL) {
                                /* The channel has hung up most likely */
                                done = 3;
                                break;
                        }
                }

		/* Do timeout check (shared between audio/dtmf) */
		if ((!quieted || strlen(dtmf)) && started == 1) {
			time(&current);
			if ((current-start) >= timeout) {
				done = 1;
				if (f)
					ast_frfree(f);
				break;
			}
		}

                /* Do checks on speech structure to see if it's changed */
                ast_mutex_lock(&speech->lock);
                if (ast_test_flag(speech, AST_SPEECH_QUIET)) {
			if (chan->stream)
				ast_stopstream(chan);
			ast_clear_flag(speech, AST_SPEECH_QUIET);
			quieted = 1;
                }
                /* Check state so we can see what to do */
                switch (speech->state) {
                case AST_SPEECH_STATE_READY:
                        /* If audio playback has stopped do a check for timeout purposes */
                        if (chan->streamid == -1 && chan->timingfunc == NULL)
                                ast_stopstream(chan);
                        if (!quieted && chan->stream == NULL && timeout && started == 0 && !filename_tmp) {
				if (timeout == -1) {
					done = 1;
					if (f)
						ast_frfree(f);
					break;
				}
				time(&start);
				started = 1;
                        }
                        /* Write audio frame out to speech engine if no DTMF has been received */
                        if (!strlen(dtmf) && f != NULL && f->frametype == AST_FRAME_VOICE) {
                                ast_speech_write(speech, f->data, f->datalen);
                        }
                        break;
                case AST_SPEECH_STATE_WAIT:
                        /* Cue up waiting sound if not already playing */
			if (!strlen(dtmf)) {
				if (chan->stream == NULL) {
					if (speech->processing_sound != NULL) {
						if (strlen(speech->processing_sound) > 0 && strcasecmp(speech->processing_sound,"none")) {
							speech_streamfile(chan, speech->processing_sound, chan->language);
						}
					}
				} else if (chan->streamid == -1 && chan->timingfunc == NULL) {
					ast_stopstream(chan);
					if (speech->processing_sound != NULL) {
						if (strlen(speech->processing_sound) > 0 && strcasecmp(speech->processing_sound,"none")) {
							speech_streamfile(chan, speech->processing_sound, chan->language);
						}
					}
				}
			}
                        break;
                case AST_SPEECH_STATE_DONE:
			/* Now that we are done... let's switch back to not ready state */
			ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
			if (!strlen(dtmf)) {
				/* Copy to speech structure the results, if available */
				speech->results = ast_speech_results_get(speech);
				/* Break out of our background too */
				done = 1;
				/* Stop audio playback */
				if (chan->stream != NULL) {
					ast_stopstream(chan);
				}
			}
                        break;
                default:
                        break;
                }
                ast_mutex_unlock(&speech->lock);

                /* Deal with other frame types */
                if (f != NULL) {
                        /* Free the frame we received */
                        switch (f->frametype) {
                        case AST_FRAME_DTMF:
				if (dtmf_terminator != '\0' && f->subclass == dtmf_terminator) {
					done = 1;
				} else {
					if (chan->stream != NULL) {
						ast_stopstream(chan);
					}
					if (!started) {
						/* Change timeout to be 5 seconds for DTMF input */
						timeout = (chan->pbx && chan->pbx->dtimeout) ? chan->pbx->dtimeout : 5;
						started = 1;
					}
					time(&start);
					snprintf(tmp, sizeof(tmp), "%c", f->subclass);
					strncat(dtmf, tmp, sizeof(dtmf) - strlen(dtmf) - 1);
					/* If the maximum length of the DTMF has been reached, stop now */
					if (max_dtmf_len && strlen(dtmf) == max_dtmf_len)
						done = 1;
				}
                                break;
                        case AST_FRAME_CONTROL:
                                switch (f->subclass) {
                                case AST_CONTROL_HANGUP:
                                        /* Since they hung up we should destroy the speech structure */
                                        done = 3;
                                default:
                                        break;
                                }
                        default:
                                break;
                        }
                        ast_frfree(f);
                        f = NULL;
                }
        }

	if (strlen(dtmf)) {
		/* We sort of make a results entry */
		speech->results = ast_calloc(1, sizeof(*speech->results));
		if (speech->results != NULL) {
			ast_speech_dtmf(speech, dtmf);
			speech->results->score = 1000;
			speech->results->text = strdup(dtmf);
			speech->results->grammar = strdup("dtmf");
		}
		ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
	}

        /* See if it was because they hung up */
        if (done == 3) {
                /* Destroy speech structure */
                ast_speech_destroy(speech);
                datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL);
                if (datastore != NULL) {
                        ast_channel_datastore_remove(chan, datastore);
                }
        } else {
                /* Channel is okay so restore read format */
                ast_set_read_format(chan, oldreadformat);
        }

        ast_module_user_remove(u);

        return 0;
}
Esempio n. 23
0
static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive)
{
	const char *s;
	char *tmp;
	char *cur, *rest;
	char *macro;
	char fullmacro[80];
	char varname[80];
	char runningapp[80], runningdata[1024];
	char *oldargs[MAX_ARGS + 1] = { NULL, };
	int argc, x;
	int res=0;
	char oldexten[256]="";
	int oldpriority, gosub_level = 0;
	char pc[80], depthc[12];
	char oldcontext[AST_MAX_CONTEXT] = "";
	const char *inhangupc;
	int offset, depth = 0, maxdepth = 7;
	int setmacrocontext=0;
	int autoloopflag, inhangup = 0;
	struct ast_str *tmp_subst = NULL;
  
	char *save_macro_exten;
	char *save_macro_context;
	char *save_macro_priority;
	char *save_macro_offset;
	struct ast_datastore *macro_store = ast_channel_datastore_find(chan, &macro_ds_info, NULL);

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "Macro() requires arguments. See \"core show application macro\" for help.\n");
		return -1;
	}

	do {
		if (macro_store) {
			break;
		}
		if (!(macro_store = ast_datastore_alloc(&macro_ds_info, NULL))) {
			ast_log(LOG_WARNING, "Unable to allocate new datastore.\n");
			break;
		}
		/* Just the existence of this datastore is enough. */
		macro_store->inheritance = DATASTORE_INHERIT_FOREVER;
		ast_channel_datastore_add(chan, macro_store);
	} while (0);

	/* does the user want a deeper rabbit hole? */
	ast_channel_lock(chan);
	if ((s = pbx_builtin_getvar_helper(chan, "MACRO_RECURSION"))) {
		sscanf(s, "%30d", &maxdepth);
	}
	
	/* Count how many levels deep the rabbit hole goes */
	if ((s = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH"))) {
		sscanf(s, "%30d", &depth);
	}
	
	/* Used for detecting whether to return when a Macro is called from another Macro after hangup */
	if (strcmp(ast_channel_exten(chan), "h") == 0)
		pbx_builtin_setvar_helper(chan, "MACRO_IN_HANGUP", "1");
	
	if ((inhangupc = pbx_builtin_getvar_helper(chan, "MACRO_IN_HANGUP"))) {
		sscanf(inhangupc, "%30d", &inhangup);
	}
	ast_channel_unlock(chan);

	if (depth >= maxdepth) {
		ast_log(LOG_ERROR, "Macro():  possible infinite loop detected.  Returning early.\n");
		return 0;
	}
	snprintf(depthc, sizeof(depthc), "%d", depth + 1);

	tmp = ast_strdupa(data);
	rest = tmp;
	macro = strsep(&rest, ",");
	if (ast_strlen_zero(macro)) {
		ast_log(LOG_WARNING, "Invalid macro name specified\n");
		return 0;
	}

	snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
	if (!ast_exists_extension(chan, fullmacro, "s", 1,
		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
		if (!ast_context_find(fullmacro)) 
			ast_log(LOG_WARNING, "No such context '%s' for macro '%s'. Was called by %s@%s\n", fullmacro, macro, ast_channel_exten(chan), ast_channel_context(chan));
		else
			ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
		return 0;
	}

	/* If we are to run the macro exclusively, take the mutex */
	if (exclusive) {
		ast_debug(1, "Locking macrolock for '%s'\n", fullmacro);
		ast_autoservice_start(chan);
		if (ast_context_lockmacro(fullmacro)) {
			ast_log(LOG_WARNING, "Failed to lock macro '%s' as in-use\n", fullmacro);
			ast_autoservice_stop(chan);
			return 0;
		}
		ast_autoservice_stop(chan);
	}

	if (!(tmp_subst = ast_str_create(16))) {
		return -1;
	}

	/* Save old info */
	oldpriority = ast_channel_priority(chan);
	ast_copy_string(oldexten, ast_channel_exten(chan), sizeof(oldexten));
	ast_copy_string(oldcontext, ast_channel_context(chan), sizeof(oldcontext));
	if (ast_strlen_zero(ast_channel_macrocontext(chan))) {
		ast_channel_macrocontext_set(chan, ast_channel_context(chan));
		ast_channel_macroexten_set(chan, ast_channel_exten(chan));
		ast_channel_macropriority_set(chan, ast_channel_priority(chan));
		setmacrocontext=1;
	}
	argc = 1;
	/* Save old macro variables */
	save_macro_exten = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_EXTEN"));
	pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten);

	save_macro_context = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"));
	pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext);

	save_macro_priority = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY"));
	snprintf(pc, sizeof(pc), "%d", oldpriority);
	pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc);
  
	save_macro_offset = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"));
	pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);

	pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);

	/* Setup environment for new run */
	ast_channel_exten_set(chan, "s");
	ast_channel_context_set(chan, fullmacro);
	ast_channel_priority_set(chan, 1);

	ast_channel_lock(chan);
	while((cur = strsep(&rest, ",")) && (argc < MAX_ARGS)) {
		const char *argp;
  		/* Save copy of old arguments if we're overwriting some, otherwise
	   	let them pass through to the other macro */
  		snprintf(varname, sizeof(varname), "ARG%d", argc);
		if ((argp = pbx_builtin_getvar_helper(chan, varname))) {
			oldargs[argc] = ast_strdup(argp);
		}
		pbx_builtin_setvar_helper(chan, varname, cur);
		argc++;
	}
	ast_channel_unlock(chan);
	autoloopflag = ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
	ast_set_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
	while (ast_exists_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan),
		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
		struct ast_context *c;
		struct ast_exten *e;
		int foundx;
		runningapp[0] = '\0';
		runningdata[0] = '\0';

		/* What application will execute? */
		if (ast_rdlock_contexts()) {
			ast_log(LOG_WARNING, "Failed to lock contexts list\n");
		} else {
			for (c = ast_walk_contexts(NULL), e = NULL; c; c = ast_walk_contexts(c)) {
				if (!strcmp(ast_get_context_name(c), ast_channel_context(chan))) {
					if (ast_rdlock_context(c)) {
						ast_log(LOG_WARNING, "Unable to lock context?\n");
					} else {
						e = find_matching_priority(c, ast_channel_exten(chan), ast_channel_priority(chan),
							S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
						if (e) { /* This will only be undefined for pbx_realtime, which is majorly broken. */
							ast_copy_string(runningapp, ast_get_extension_app(e), sizeof(runningapp));
							ast_copy_string(runningdata, ast_get_extension_app_data(e), sizeof(runningdata));
						}
						ast_unlock_context(c);
					}
					break;
				}
			}
		}
		ast_unlock_contexts();

		/* Reset the macro depth, if it was changed in the last iteration */
		pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);

		res = ast_spawn_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan),
			S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL),
			&foundx, 1);
		if (res) {
			/* Something bad happened, or a hangup has been requested. */
			if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
		    	(res == '*') || (res == '#')) {
				/* Just return result as to the previous application as if it had been dialed */
				ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
				break;
			}
			switch(res) {
			case MACRO_EXIT_RESULT:
				res = 0;
				goto out;
			default:
				ast_debug(2, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), ast_channel_name(chan), macro);
				ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), ast_channel_name(chan), macro);
				goto out;
			}
		}

		ast_debug(1, "Executed application: %s\n", runningapp);

		if (!strcasecmp(runningapp, "GOSUB")) {
			gosub_level++;
			ast_debug(1, "Incrementing gosub_level\n");
		} else if (!strcasecmp(runningapp, "GOSUBIF")) {
			char *cond, *app_arg;
			char *app2;
			ast_str_substitute_variables(&tmp_subst, 0, chan, runningdata);
			app2 = ast_str_buffer(tmp_subst);
			cond = strsep(&app2, "?");
			app_arg = strsep(&app2, ":");
			if (pbx_checkcondition(cond)) {
				if (!ast_strlen_zero(app_arg)) {
					gosub_level++;
					ast_debug(1, "Incrementing gosub_level\n");
				}
			} else {
				if (!ast_strlen_zero(app2)) {
					gosub_level++;
					ast_debug(1, "Incrementing gosub_level\n");
				}
			}
		} else if (!strcasecmp(runningapp, "RETURN")) {
			gosub_level--;
			ast_debug(1, "Decrementing gosub_level\n");
		} else if (!strcasecmp(runningapp, "STACKPOP")) {
			gosub_level--;
			ast_debug(1, "Decrementing gosub_level\n");
		} else if (!strncasecmp(runningapp, "EXEC", 4)) {
			/* Must evaluate args to find actual app */
			char *tmp2, *tmp3 = NULL;
			ast_str_substitute_variables(&tmp_subst, 0, chan, runningdata);
			tmp2 = ast_str_buffer(tmp_subst);
			if (!strcasecmp(runningapp, "EXECIF")) {
				if ((tmp3 = strchr(tmp2, '|'))) {
					*tmp3++ = '\0';
				}
				if (!pbx_checkcondition(tmp2)) {
					tmp3 = NULL;
				}
			} else {
				tmp3 = tmp2;
			}

			if (tmp3) {
				ast_debug(1, "Last app: %s\n", tmp3);
			}

			if (tmp3 && !strncasecmp(tmp3, "GOSUB", 5)) {
				gosub_level++;
				ast_debug(1, "Incrementing gosub_level\n");
			} else if (tmp3 && !strncasecmp(tmp3, "RETURN", 6)) {
				gosub_level--;
				ast_debug(1, "Decrementing gosub_level\n");
			} else if (tmp3 && !strncasecmp(tmp3, "STACKPOP", 8)) {
				gosub_level--;
				ast_debug(1, "Decrementing gosub_level\n");
			}
		}

		if (gosub_level == 0 && strcasecmp(ast_channel_context(chan), fullmacro)) {
			ast_verb(2, "Channel '%s' jumping out of macro '%s'\n", ast_channel_name(chan), macro);
			break;
		}

		/* don't stop executing extensions when we're in "h" */
		if (ast_check_hangup(chan) && !inhangup) {
			ast_debug(1, "Extension %s, macroexten %s, priority %d returned normally even though call was hung up\n", ast_channel_exten(chan), ast_channel_macroexten(chan), ast_channel_priority(chan));
			goto out;
		}
		ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
  	}
	out:

	/* Don't let the channel change now. */
	ast_channel_lock(chan);

	/* Reset the depth back to what it was when the routine was entered (like if we called Macro recursively) */
	snprintf(depthc, sizeof(depthc), "%d", depth);
	pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
	ast_set2_flag(ast_channel_flags(chan), autoloopflag, AST_FLAG_IN_AUTOLOOP);

  	for (x = 1; x < argc; x++) {
  		/* Restore old arguments and delete ours */
		snprintf(varname, sizeof(varname), "ARG%d", x);
  		if (oldargs[x]) {
			pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
			ast_free(oldargs[x]);
		} else {
			pbx_builtin_setvar_helper(chan, varname, NULL);
		}
  	}

	/* Restore macro variables */
	pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
	pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
	pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
	if (save_macro_exten)
		ast_free(save_macro_exten);
	if (save_macro_context)
		ast_free(save_macro_context);
	if (save_macro_priority)
		ast_free(save_macro_priority);

	if (setmacrocontext) {
		ast_channel_macrocontext_set(chan, "");
		ast_channel_macroexten_set(chan, "");
		ast_channel_macropriority_set(chan, 0);
	}

	if (!strcasecmp(ast_channel_context(chan), fullmacro)) {
		const char *offsets;

  		/* If we're leaving the macro normally, restore original information */
		ast_channel_priority_set(chan, oldpriority);
		ast_channel_context_set(chan, oldcontext);
		ast_channel_exten_set(chan, oldexten);
		if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {
			/* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
			normally if there is any problem */
			if (sscanf(offsets, "%30d", &offset) == 1) {
				if (ast_exists_extension(chan, ast_channel_context(chan), ast_channel_exten(chan),
					ast_channel_priority(chan) + offset + 1,
					S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
					ast_channel_priority_set(chan, ast_channel_priority(chan) + offset);
				}
			}
		}
	}

	pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
	if (save_macro_offset)
		ast_free(save_macro_offset);

	/* Unlock the macro */
	if (exclusive) {
		ast_debug(1, "Unlocking macrolock for '%s'\n", fullmacro);
		if (ast_context_unlockmacro(fullmacro)) {
			ast_log(LOG_ERROR, "Failed to unlock macro '%s' - that isn't good\n", fullmacro);
			res = 0;
		}
	}
	ast_channel_unlock(chan);
	ast_free(tmp_subst);

	return res;
}
Esempio n. 24
0
static int conf_exec(struct ast_channel *chan, void *data)
{
	int res=-1;
	int confflags = 0;
	int confno = 0;
	char confnostr[80] = "", *tmp = NULL;
	struct ast_channel *tempchan = NULL, *lastchan = NULL, *ichan = NULL;
	struct ast_frame *f;
	char *desired_group;
	int input = 0, search_group = 0;

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

	desired_group = ast_strdupa(data);
	if (!ast_strlen_zero(desired_group)) {
		ast_verb(3, "Scanning for group %s\n", desired_group);
		search_group = 1;
	}

	for (;;) {
		if (ast_waitfor(chan, 100) < 0)
			break;

		f = ast_read(chan);
		if (!f)
			break;
		if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
			ast_frfree(f);
			break;
		}
		ast_frfree(f);
		ichan = NULL;
		if(input) {
			ichan = get_dahdi_channel_locked(input);
			input = 0;
		}

		tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan);

		if (!tempchan && !lastchan) {
			break;
		}

		if (tempchan && search_group) {
			const char *mygroup;
			if ((mygroup = pbx_builtin_getvar_helper(tempchan, "GROUP")) && (!strcmp(mygroup, desired_group))) {
				ast_verb(3, "Found Matching Channel %s in group %s\n", tempchan->name, desired_group);
			} else {
				ast_channel_unlock(tempchan);
				lastchan = tempchan;
				continue;
			}
		}
		if (tempchan && (!strcmp(tempchan->tech->type, "DAHDI")) && (tempchan != chan)) {
			ast_verb(3, "DAHDI channel %s is in-use, monitoring...\n", tempchan->name);
			ast_copy_string(confnostr, tempchan->name, sizeof(confnostr));
			ast_channel_unlock(tempchan);
			if ((tmp = strchr(confnostr, '-'))) {
				*tmp = '\0';
			}
			confno = atoi(strchr(confnostr, '/') + 1);
			ast_stopstream(chan);
			ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL);
			res = conf_run(chan, confno, confflags);
			if (res < 0) {
				break;
			}
			input = res;
		} else if (tempchan) {
			ast_channel_unlock(tempchan);
		}
		lastchan = tempchan;
	}
	return res;
}
Esempio n. 25
0
static int txfax_exec(struct ast_channel *chan, void *data)
{
    int res = 0;
    char source_file[256];
    char *x;
    char *s;
    char *t;
    char *v;
    int option;
    int len;
    t30_state_t fax;
    int calling_party;
    int verbose;
    int samples;
    
    struct localuser *u;
    struct ast_frame *inf = NULL;
    struct ast_frame outf;

    int original_read_fmt;
    int original_write_fmt;
    
    uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
    uint8_t *buf = __buf + AST_FRIENDLY_OFFSET;

    if (chan == NULL)
    {
        ast_log(LOG_WARNING, "Fax transmit channel is NULL. Giving up.\n");
        return -1;
    }

    span_set_message_handler(span_message);

    /* The next few lines of code parse out the filename and header from the input string */
    if (data == NULL)
    {
        /* No data implies no filename or anything is present */
        ast_log(LOG_WARNING, "Txfax requires an argument (filename)\n");
        return -1;
    }
    
    calling_party = FALSE;
    verbose = FALSE;
    source_file[0] = '\0'; 

    for (option = 0, v = s = data;  v;  option++, s++)
    {
        t = s;
        v = strchr(s, '|');
        s = (v)  ?  v  :  s + strlen(s);
        strncpy((char *) buf, t, s - t);
        buf[s - t] = '\0';
        if (option == 0)
        {
            /* The first option is always the file name */
            len = s - t;
            if (len > 255)
                len = 255;
            strncpy(source_file, t, len);
            source_file[len] = '\0';
        }
        else if (strncmp("caller", t, s - t) == 0)
        {
            calling_party = TRUE;
        }
        else if (strncmp("debug", t, s - t) == 0)
        {
            verbose = TRUE;
        }
    }

    /* Done parsing */

    LOCAL_USER_ADD(u);

    if (chan->_state != 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(chan);
    }
    
    if (!res)
    {
        original_read_fmt = chan->readformat;
        if (original_read_fmt != AST_FORMAT_SLINEAR)
        {
            res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
            if (res < 0)
            {
                ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
                return -1;
            }
        }
        original_write_fmt = chan->writeformat;
        if (original_write_fmt != AST_FORMAT_SLINEAR)
        {
            res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
            if (res < 0)
            {
                ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
                res = ast_set_read_format(chan, original_read_fmt);
                if (res)
                    ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
                return -1;
            }
        }
        fax_init(&fax, calling_party, NULL);
        if (verbose)
	    fax.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;

        x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
        if (x  &&  x[0])
            t30_set_local_ident(&fax, x);
        x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
        if (x  &&  x[0])
            t30_set_header_info(&fax, x);
        t30_set_tx_file(&fax, source_file, -1, -1);
        //t30_set_phase_b_handler(&fax, phase_b_handler, chan);
        //t30_set_phase_d_handler(&fax, phase_d_handler, chan);
        t30_set_phase_e_handler(&fax, phase_e_handler, chan);
        while (ast_waitfor(chan, -1) > -1)
        {
            inf = ast_read(chan);
            if (inf == NULL)
            {
                res = -1;
                break;
            }
            if (inf->frametype == AST_FRAME_VOICE)
            {
                if (fax_rx(&fax, inf->data, inf->samples))
                    break;
                samples = (inf->samples <= MAX_BLOCK_SIZE)  ?  inf->samples  :  MAX_BLOCK_SIZE;
                len = fax_tx(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
                if (len)
                {
                    memset(&outf, 0, sizeof(outf));
                    outf.frametype = AST_FRAME_VOICE;
                    outf.subclass = AST_FORMAT_SLINEAR;
                    outf.datalen = len*sizeof(int16_t);
                    outf.samples = len;
                    outf.data = &buf[AST_FRIENDLY_OFFSET];
                    outf.offset = AST_FRIENDLY_OFFSET;
                    if (ast_write(chan, &outf) < 0)
                    {
                        ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
                        break;
                    }
                }
            }
            ast_frfree(inf);
        }
        if (inf == NULL)
        {
            ast_log(LOG_DEBUG, "Got hangup\n");
            res = -1;
        }
        if (original_read_fmt && original_read_fmt != AST_FORMAT_SLINEAR)
        {
            res = ast_set_read_format(chan, original_read_fmt);
            if (res)
                ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
        }
        if (original_write_fmt && original_write_fmt != AST_FORMAT_SLINEAR)
        {
            res = ast_set_write_format(chan, original_write_fmt);
            if (res)
                ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
        }
        fax_release(&fax);
    }
    else
    {
        ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
    }
    LOCAL_USER_REMOVE(u);
    return res;
}
static int pickup_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct localuser *u = NULL;
	struct ast_channel *origin = NULL, *target = NULL;
	char *tmp = NULL, *exten = NULL, *context = NULL, *rest=data;
	char workspace[256] = "";
	const char *tmp2 = NULL;

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

	LOCAL_USER_ADD(u);
	
	while (!target && (exten = rest) ) {
		res = 0;
		rest = strchr(exten, '&');
		if (rest)
			*rest++ = 0;

		/* Get the extension and context if present */
		context = strchr(exten, '@');
		if (context)
			*context++ = '\0';

		/* If the context is the pickup mark, iterate through all channels finding the right origin one */
		if (!strcmp(context, PICKUPMARK)) {
			while ((origin = ast_channel_walk_locked(origin))) {
				if (origin) {
					tmp2 = pbx_builtin_getvar_helper(origin, PICKUPMARK);
					if (tmp2 && !strcmp(tmp2, exten))
						break;
					ast_mutex_unlock(&origin->lock);
				}
			}
		} else {
			/* Use the classic mode of searching */
			origin = ast_get_channel_by_exten_locked(exten, context);
		}

		if (origin) {
			ast_cdr_getvar(origin->cdr, "dstchannel", &tmp, workspace,
					sizeof(workspace), 0, 0);
			if (tmp) {
				/* We have a possible channel... now we need to find it! */
				target = ast_get_channel_by_name_locked(tmp);
			} else {
				ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
				res = -1;
			}
			ast_mutex_unlock(&origin->lock);

		} else {
			ast_log(LOG_DEBUG, "No originating channel found.\n");
		}

		if (res)
			continue;

		if (target && (!target->pbx) && ((target->_state == AST_STATE_RINGING) || (target->_state == AST_STATE_RING) ) ) {
			ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n", target->name,
					chan->name);
			res = ast_answer(chan);
			if (res) {
				ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
				res = -1;
				break;
			}
			res = ast_queue_control(chan, AST_CONTROL_ANSWER);
			if (res) {
				ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n",
						chan->name);
				res = -1;
				break;
			}
			res = ast_channel_masquerade(target, chan);
			if (res) {
				ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
				res = -1;
				break;
			}
		} else {
			ast_log(LOG_NOTICE, "No call pickup possible for %s...\n", exten);
			res = -1;
		}
	}
	if (target) 
		ast_mutex_unlock(&target->lock);
	
	LOCAL_USER_REMOVE(u);

	return res;
}
static int macro_exec(struct ast_channel *chan, void *data)
{
	char *tmp;
	char *cur, *rest;
	char *macro;
	char fullmacro[80];
	char varname[80];
	char *oldargs[MAX_ARGS + 1] = { NULL, };
	int argc, x;
	int res=0;
	char oldexten[256]="";
	int oldpriority;
	char pc[80], depthc[12];
	char oldcontext[AST_MAX_CONTEXT] = "";
	char *offsets;
	int offset, depth;
	int setmacrocontext=0;
	int autoloopflag;
  
	char *save_macro_exten;
	char *save_macro_context;
	char *save_macro_priority;
	char *save_macro_offset;
	struct localuser *u;
 
	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "Macro() requires arguments. See \"show application macro\" for help.\n");
		return -1;
	}

	LOCAL_USER_ADD(u);

	/* Count how many levels deep the rabbit hole goes */
	tmp = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH");
	if (tmp) {
		sscanf(tmp, "%d", &depth);
	} else {
		depth = 0;
	}

	if (depth >= 7) {
		ast_log(LOG_ERROR, "Macro():  possible infinite loop detected.  Returning early.\n");
		LOCAL_USER_REMOVE(u);
		return 0;
	}
	snprintf(depthc, sizeof(depthc), "%d", depth + 1);
	pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);

	tmp = ast_strdupa(data);
	rest = tmp;
	macro = strsep(&rest, "|");
	if (ast_strlen_zero(macro)) {
		ast_log(LOG_WARNING, "Invalid macro name specified\n");
		LOCAL_USER_REMOVE(u);
		return 0;
	}
	snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
	if (!ast_exists_extension(chan, fullmacro, "s", 1, chan->cid.cid_num)) {
  		if (!ast_context_find(fullmacro)) 
			ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro);
		else
	  		ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
		LOCAL_USER_REMOVE(u);
		return 0;
	}
	
	/* Save old info */
	oldpriority = chan->priority;
	ast_copy_string(oldexten, chan->exten, sizeof(oldexten));
	ast_copy_string(oldcontext, chan->context, sizeof(oldcontext));
	if (ast_strlen_zero(chan->macrocontext)) {
		ast_copy_string(chan->macrocontext, chan->context, sizeof(chan->macrocontext));
		ast_copy_string(chan->macroexten, chan->exten, sizeof(chan->macroexten));
		chan->macropriority = chan->priority;
		setmacrocontext=1;
	}
	argc = 1;
	/* Save old macro variables */
	save_macro_exten = pbx_builtin_getvar_helper(chan, "MACRO_EXTEN");
	if (save_macro_exten) 
		save_macro_exten = strdup(save_macro_exten);
	pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten);

	save_macro_context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT");
	if (save_macro_context)
		save_macro_context = strdup(save_macro_context);
	pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext);

	save_macro_priority = pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY");
	if (save_macro_priority) 
		save_macro_priority = strdup(save_macro_priority);
	snprintf(pc, sizeof(pc), "%d", oldpriority);
	pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc);
  
	save_macro_offset = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET");
	if (save_macro_offset) 
		save_macro_offset = strdup(save_macro_offset);
	pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);

	/* Setup environment for new run */
	chan->exten[0] = 's';
	chan->exten[1] = '\0';
	ast_copy_string(chan->context, fullmacro, sizeof(chan->context));
	chan->priority = 1;

	while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
  		/* Save copy of old arguments if we're overwriting some, otherwise
	   	let them pass through to the other macro */
  		snprintf(varname, sizeof(varname), "ARG%d", argc);
		oldargs[argc] = pbx_builtin_getvar_helper(chan, varname);
		if (oldargs[argc])
			oldargs[argc] = strdup(oldargs[argc]);
		pbx_builtin_setvar_helper(chan, varname, cur);
		argc++;
	}
	autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP);
	ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP);
	while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
		/* Reset the macro depth, if it was changed in the last iteration */
		pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
		if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) {
			/* Something bad happened, or a hangup has been requested. */
			if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
		    	(res == '*') || (res == '#')) {
				/* Just return result as to the previous application as if it had been dialed */
				ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
				break;
			}
			switch(res) {
	        	case MACRO_EXIT_RESULT:
                        	res = 0;
				goto out;
			case AST_PBX_KEEPALIVE:
				if (option_debug)
					ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE in macro %s on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
				else if (option_verbose > 1)
					ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE in macro '%s' on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
				goto out;
				break;
			default:
				if (option_debug)
					ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
				else if (option_verbose > 1)
					ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
				goto out;
			}
		}
		if (strcasecmp(chan->context, fullmacro)) {
			if (option_verbose > 1)
				ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro);
			break;
		}
		/* don't stop executing extensions when we're in "h" */
		if (chan->_softhangup && strcasecmp(oldexten,"h")) {
			ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
				chan->exten, chan->priority);
			goto out;
		}
		chan->priority++;
  	}
	out:
	/* Reset the depth back to what it was when the routine was entered (like if we called Macro recursively) */
	snprintf(depthc, sizeof(depthc), "%d", depth);
	pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);

	ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
  	for (x=1; x<argc; x++) {
  		/* Restore old arguments and delete ours */
		snprintf(varname, sizeof(varname), "ARG%d", x);
  		if (oldargs[x]) {
			pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
			free(oldargs[x]);
		} else {
			pbx_builtin_setvar_helper(chan, varname, NULL);
		}
  	}

	/* Restore macro variables */
	pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
	if (save_macro_exten)
		free(save_macro_exten);
	pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
	if (save_macro_context)
		free(save_macro_context);
	pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
	if (save_macro_priority)
		free(save_macro_priority);
	if (setmacrocontext) {
		chan->macrocontext[0] = '\0';
		chan->macroexten[0] = '\0';
		chan->macropriority = 0;
	}

	if (!strcasecmp(chan->context, fullmacro)) {
  		/* If we're leaving the macro normally, restore original information */
		chan->priority = oldpriority;
		ast_copy_string(chan->context, oldcontext, sizeof(chan->context));
		if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) {
			/* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */
			ast_copy_string(chan->exten, oldexten, sizeof(chan->exten));
			if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {
				/* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
			   	normally if there is any problem */
				if (sscanf(offsets, "%d", &offset) == 1) {
					if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + offset + 1, chan->cid.cid_num)) {
						chan->priority += offset;
					}
				}
			}
		}
	}

	pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
	if (save_macro_offset)
		free(save_macro_offset);
	LOCAL_USER_REMOVE(u);
	return res;
}
Esempio n. 28
0
static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int confflags)
{
	struct ast_conference *prev=NULL, *cur;
	struct ast_conf_user *user = malloc(sizeof(struct ast_conf_user));
	int fd;
	struct zt_confinfo ztc;
	struct ast_frame *f;
	struct ast_channel *c;
	struct ast_frame fr;
	int outfd;
	int ms;
	int nfds;
	int res;
	int flags;
	int retryzap;
	int origfd;
	int musiconhold = 0;
	int firstpass = 0;
	int origquiet;
	int ret = -1;
	int x;
	int menu_active = 0;
	int using_pseudo = 0;

	struct ast_app *app;
	char *agifile;
	char *agifiledefault = "conf-background.agi";
	char meetmesecs[30] = "";
	char exitcontext[AST_MAX_EXTENSION] = "";
	int dtmf;

	ZT_BUFFERINFO bi;
	char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
	char *buf = __buf + AST_FRIENDLY_OFFSET;
	
	if (!user) {
		ast_log(LOG_ERROR, "Out of memory\n");
		return(ret);
	}
	memset(user, 0, sizeof(struct ast_conf_user));

	user->user_no = 0; /* User number 0 means starting up user! (dead - not in the list!) */

	time(&user->jointime);

	if (conf->locked) {
		/* Sorry, but this confernce is locked! */	
		if (!ast_streamfile(chan, "conf-locked", chan->language))
			ast_waitstream(chan, "");
		goto outrun;
	}
	conf->users++;
	if (confflags & CONFFLAG_MARKEDUSER)
		conf->markedusers++;
      
   	ast_mutex_lock(&conflock);
	if (conf->firstuser == NULL) {
		/* Fill the first new User struct */
		user->user_no = 1;
		user->nextuser = NULL;
		user->prevuser = NULL;
		conf->firstuser = user;
		conf->lastuser = user;
	} else {
		/* Fill the new user struct */	
		user->user_no = conf->lastuser->user_no + 1; 
		user->prevuser = conf->lastuser;
		user->nextuser = NULL;
		if (conf->lastuser->nextuser != NULL) {
			ast_log(LOG_WARNING, "Error in User Management!\n");
			ast_mutex_unlock(&conflock);
			goto outrun;
		} else {
			conf->lastuser->nextuser = user;
			conf->lastuser = user;
		}
	}
	user->chan = chan;
	user->userflags = confflags;
	user->adminflags = 0;
	ast_mutex_unlock(&conflock);
	origquiet = confflags & CONFFLAG_QUIET;
	if (confflags & CONFFLAG_EXIT_CONTEXT) {
		if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) 
			strncpy(exitcontext, agifile, sizeof(exitcontext) - 1);
		else if (!ast_strlen_zero(chan->macrocontext)) 
			strncpy(exitcontext, chan->macrocontext, sizeof(exitcontext) - 1);
		else
			strncpy(exitcontext, chan->context, sizeof(exitcontext) - 1);
	}
	while((confflags & CONFFLAG_WAITMARKED) && (conf->markedusers == 0)) {
		confflags &= ~CONFFLAG_QUIET;
		confflags |= origquiet;
		/* XXX Announce that we're waiting on the conference lead to join */
		if (!(confflags & CONFFLAG_QUIET)) {
			res = ast_streamfile(chan, "vm-dialout", chan->language);
			if (!res)
				res = ast_waitstream(chan, "");
		} else
			res = 0;
		/* If we're waiting with hold music, set to silent mode */
		if (!res) {
			confflags |= CONFFLAG_QUIET;
			ast_moh_start(chan, NULL);
			res = ast_safe_sleep_conditional(chan, 60000, confnonzero, conf);
			ast_moh_stop(chan);
		}
		if (res < 0) {
			ast_log(LOG_DEBUG, "Got hangup on '%s' already\n", chan->name);
			goto outrun;
		}
	}
	
	if (!(confflags & CONFFLAG_QUIET) && conf->users == 1) {
		if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) {
			if (ast_waitstream(chan, "") < 0)
				goto outrun;
		} else
			goto outrun;
	}

	/* Set it into linear mode (write) */
	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
		ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name);
		goto outrun;
	}

	/* Set it into linear mode (read) */
	if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
		ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name);
		goto outrun;
	}
	ast_indicate(chan, -1);
	retryzap = strcasecmp(chan->type, "Zap");
zapretry:
	origfd = chan->fds[0];
	if (retryzap) {
		fd = open("/dev/zap/pseudo", O_RDWR);
		if (fd < 0) {
			ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
			goto outrun;
		}
		using_pseudo = 1;
		/* Make non-blocking */
		flags = fcntl(fd, F_GETFL);
		if (flags < 0) {
			ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno));
			close(fd);
			goto outrun;
		}
		if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
			ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno));
			close(fd);
			goto outrun;
		}
		/* Setup buffering information */
		memset(&bi, 0, sizeof(bi));
		bi.bufsize = CONF_SIZE/2;
		bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
		bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
		bi.numbufs = 4;
		if (ioctl(fd, ZT_SET_BUFINFO, &bi)) {
			ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno));
			close(fd);
			goto outrun;
		}
		x = 1;
		if (ioctl(fd, ZT_SETLINEAR, &x)) {
			ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno));
			close(fd);
			goto outrun;
		}
		nfds = 1;
	} else {
		/* XXX Make sure we're not running on a pseudo channel XXX */
		fd = chan->fds[0];
		nfds = 0;
	}
	memset(&ztc, 0, sizeof(ztc));
	/* Check to see if we're in a conference... */
	ztc.chan = 0;	
	if (ioctl(fd, ZT_GETCONF, &ztc)) {
		ast_log(LOG_WARNING, "Error getting conference\n");
		close(fd);
		goto outrun;
	}
	if (ztc.confmode) {
		/* Whoa, already in a conference...  Retry... */
		if (!retryzap) {
			ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n");
			retryzap = 1;
			goto zapretry;
		}
	}
	memset(&ztc, 0, sizeof(ztc));
	/* Add us to the conference */
	ztc.chan = 0;	
	ztc.confno = conf->zapconf;
	if (confflags & CONFFLAG_MONITOR)
		ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER;
	else if (confflags & CONFFLAG_TALKER)
		ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
	else 
		ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;

	if (ioctl(fd, ZT_SETCONF, &ztc)) {
		ast_log(LOG_WARNING, "Error setting conference\n");
		close(fd);
		goto outrun;
	}
	ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf);

	manager_event(EVENT_FLAG_CALL, "MeetmeJoin", 
			"Channel: %s\r\n"
			"Uniqueid: %s\r\n"
			"Meetme: %s\r\n"
			"Usernum: %i\r\n",
			chan->name, chan->uniqueid, conf->confno, user->user_no);

	if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) {
		firstpass = 1;
		if (!(confflags & CONFFLAG_QUIET))
			conf_play(conf, ENTER);
	}

	if (confflags & CONFFLAG_AGI) {

		/* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND)
		  or use default filename of conf-background.agi */

		agifile = pbx_builtin_getvar_helper(chan,"MEETME_AGI_BACKGROUND");
		if (!agifile)
			agifile = agifiledefault;

		if (!strcasecmp(chan->type,"Zap")) {
			/*  Set CONFMUTE mode on Zap channel to mute DTMF tones */
			x = 1;
			ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
		}
		/* Find a pointer to the agi app and execute the script */
		app = pbx_findapp("agi");
		if (app) {
			ret = pbx_exec(chan, app, agifile, 1);
		} else {
			ast_log(LOG_WARNING, "Could not find application (agi)\n");
			ret = -2;
		}
		if (!strcasecmp(chan->type,"Zap")) {
			/*  Remove CONFMUTE mode on Zap channel */
			x = 0;
			ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
		}
	} else {
		if (!strcasecmp(chan->type,"Zap") && (confflags & CONFFLAG_STARMENU)) {
			/*  Set CONFMUTE mode on Zap channel to mute DTMF tones when the menu is enabled */
			x = 1;
			ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0);
		}	
		for(;;) {
			outfd = -1;
			ms = -1;
			c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms);
			
			/* Update the struct with the actual confflags */
			user->userflags = confflags;
			
			/* trying to add moh for single person conf */
			if (confflags & CONFFLAG_MOH) {
				if (conf->users == 1) {
					if (musiconhold == 0) {
						ast_moh_start(chan, NULL);
						musiconhold = 1;
					} 
				} else {
					if (musiconhold) {
						ast_moh_stop(chan);
						musiconhold = 0;
					}
				}
			}
			
			/* Leave if the last marked user left */
			if (conf->markedusers == 0 && confflags & CONFFLAG_MARKEDEXIT) {
				ret = -1;
				break;
			}
	
			/* Check if the admin changed my modes */
			if (user->adminflags) {			
				/* Set the new modes */
				if ((user->adminflags & ADMINFLAG_MUTED) && (ztc.confmode & ZT_CONF_TALKER)) {
					ztc.confmode ^= ZT_CONF_TALKER;
					if (ioctl(fd, ZT_SETCONF, &ztc)) {
						ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
						ret = -1;
						break;
					}
				}
				if (!(user->adminflags & ADMINFLAG_MUTED) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) {
					ztc.confmode |= ZT_CONF_TALKER;
					if (ioctl(fd, ZT_SETCONF, &ztc)) {
						ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
						ret = -1;
						break;
					}
				}
				if (user->adminflags & ADMINFLAG_KICKME) {
					//You have been kicked.
					if (!ast_streamfile(chan, "conf-kicked", chan->language))
						ast_waitstream(chan, "");
					ret = 0;
					break;
				}
			} else if (!(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) {
				ztc.confmode |= ZT_CONF_TALKER;
				if (ioctl(fd, ZT_SETCONF, &ztc)) {
					ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
					ret = -1;
					break;
				}
			}

			if (c) {
				if (c->fds[0] != origfd) {
					if (using_pseudo) {
						/* Kill old pseudo */
						close(fd);
					}
					ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n");
					retryzap = 0;
					using_pseudo = 0;
					goto zapretry;
				}
				f = ast_read(c);
				if (!f) 
					break;
				if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) {
					char tmp[2];
					tmp[0] = f->subclass;
					tmp[1] = '\0';
					if (ast_exists_extension(chan, exitcontext, tmp, 1, chan->callerid)) {
						strncpy(chan->context, exitcontext, sizeof(chan->context) - 1);
						strncpy(chan->exten, tmp, sizeof(chan->exten) - 1);
						chan->priority = 0;
						ret = 0;
						break;
					}
				} else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) {
					ret = 0;
					break;
				} else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) {
					if (musiconhold) {
			   			ast_moh_stop(chan);
					}
					if ((confflags & CONFFLAG_ADMIN)) {
						/* Admin menu */
						if (!menu_active) {
							menu_active = 1;
							/* Record this sound! */
							if (!ast_streamfile(chan, "conf-adminmenu", chan->language))
								dtmf = ast_waitstream(chan, AST_DIGIT_ANY);
							else
								dtmf = 0;
						} else 
							dtmf = f->subclass;
						if (dtmf) {
							switch(dtmf) {
								case '1': /* Un/Mute */
									menu_active = 0;
		 							if (ztc.confmode & ZT_CONF_TALKER) {
	 						       		ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
	 						       		confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER;
									} else {
										ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
										confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER;
									}
									if (ioctl(fd, ZT_SETCONF, &ztc)) {
										ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
										ret = -1;
										break;
									}
									if (ztc.confmode & ZT_CONF_TALKER) {
										if (!ast_streamfile(chan, "conf-unmuted", chan->language))
											ast_waitstream(chan, "");
									} else {
										if (!ast_streamfile(chan, "conf-muted", chan->language))
											ast_waitstream(chan, "");
									}
									break;
								case '2': /* Un/Lock the Conference */
									menu_active = 0;
									if (conf->locked) {
										conf->locked = 0;
										if (!ast_streamfile(chan, "conf-unlockednow", chan->language))
											ast_waitstream(chan, "");
									} else {
										conf->locked = 1;
										if (!ast_streamfile(chan, "conf-lockednow", chan->language))
											ast_waitstream(chan, "");
									}
									break;
								default:
									menu_active = 0;
									/* Play an error message! */
									if (!ast_streamfile(chan, "conf-errormenu", chan->language))
										ast_waitstream(chan, "");
									break;
							}
						}
					} else {
						/* User menu */
						if (!menu_active) {
							menu_active = 1;
							/* Record this sound! */
							if (!ast_streamfile(chan, "conf-usermenu", chan->language))
								dtmf = ast_waitstream(chan, AST_DIGIT_ANY);
							else
								dtmf = 0;
						} else 
							dtmf = f->subclass;
						if (dtmf) {
							switch(dtmf) {
								case '1': /* Un/Mute */
									menu_active = 0;
		 							if (ztc.confmode & ZT_CONF_TALKER) {
	 						       		ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER;
	 						       		confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER;
									} else if (!(user->adminflags & ADMINFLAG_MUTED)) {
										ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER;
										confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER;
									}
									if (ioctl(fd, ZT_SETCONF, &ztc)) {
										ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n");
										ret = -1;
										break;
									}
									if (ztc.confmode & ZT_CONF_TALKER) {
										if (!ast_streamfile(chan, "conf-unmuted", chan->language))
											ast_waitstream(chan, "");
									} else {
										if (!ast_streamfile(chan, "conf-muted", chan->language))
											ast_waitstream(chan, "");
									}
									break;
								default:
									menu_active = 0;
									/* Play an error message! */
									if (!ast_streamfile(chan, "conf-errormenu", chan->language))
										ast_waitstream(chan, "");
									break;
							}
						}
					}
					if (musiconhold) {
			   			ast_moh_start(chan, NULL);
					}
				} else if (using_pseudo) {
					if (f->frametype == AST_FRAME_VOICE) {
						if (f->subclass == AST_FORMAT_SLINEAR) {
							/* Carefully write */
							careful_write(fd, f->data, f->datalen);
						} else
							ast_log(LOG_WARNING, "Huh?  Got a non-linear (%d) frame in the conference\n", f->subclass);
					}
				}
				ast_frfree(f);
			} else if (outfd > -1) {
				res = read(outfd, buf, CONF_SIZE);
				if (res > 0) {
					memset(&fr, 0, sizeof(fr));
					fr.frametype = AST_FRAME_VOICE;
					fr.subclass = AST_FORMAT_SLINEAR;
					fr.datalen = res;
					fr.samples = res/2;
					fr.data = buf;
					fr.offset = AST_FRIENDLY_OFFSET;
					if (ast_write(chan, &fr) < 0) {
						ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno));
						/* break; */
					}
				} else 
					ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno));
			}
		}
	}
	if (using_pseudo)
		close(fd);
	else {
		/* Take out of conference */
		/* Add us to the conference */
		ztc.chan = 0;	
		ztc.confno = 0;
		ztc.confmode = 0;
		if (ioctl(fd, ZT_SETCONF, &ztc)) {
			ast_log(LOG_WARNING, "Error setting conference\n");
		}
	}
	if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN))
		conf_play(conf, LEAVE);

outrun:
	ast_mutex_lock(&conflock);
	if (user->user_no) { /* Only cleanup users who really joined! */
		manager_event(EVENT_FLAG_CALL, "MeetmeLeave", 
			"Channel: %s\r\n"
			"Uniqueid: %s\r\n"
			"Meetme: %s\r\n"
			"Usernum: %i\r\n",
			chan->name, chan->uniqueid, conf->confno, user->user_no);
		prev = NULL;
		conf->users--;
		if (confflags & CONFFLAG_MARKEDUSER) 
			conf->markedusers--;
		cur = confs;
		if (!conf->users) {
			/* No more users -- close this one out */
			while(cur) {
				if (cur == conf) {
					if (prev)
						prev->next = conf->next;
					else
						confs = conf->next;
					break;
				}
				prev = cur;
				cur = cur->next;
			}
			if (!cur) 
				ast_log(LOG_WARNING, "Conference not found\n");
			if (conf->chan)
				ast_hangup(conf->chan);
			else
				close(conf->fd);
			free(conf);
		} else {
			/* Remove the user struct */ 
			if (user == conf->firstuser) {
				if (user->nextuser) {
					/* There is another entry */
					user->nextuser->prevuser = NULL;
				} else {
					/* We are the only entry */
					conf->lastuser = NULL;
				}
				/* In either case */
				conf->firstuser = user->nextuser;
			} else if (user == conf->lastuser){
				if (user->prevuser)
					user->prevuser->nextuser = NULL;
				else
					ast_log(LOG_ERROR, "Bad bad bad!  We're the last, not the first, but nobody before us??\n");
				conf->lastuser = user->prevuser;
			} else {
				if (user->nextuser)
					user->nextuser->prevuser = user->prevuser;
				else
					ast_log(LOG_ERROR, "Bad! Bad! Bad! user->nextuser is NULL but we're not the end!\n");
				if (user->prevuser)
					user->prevuser->nextuser = user->nextuser;
				else
					ast_log(LOG_ERROR, "Bad! Bad! Bad! user->prevuser is NULL but we're not the beginning!\n");
			}
		}
		/* Return the number of seconds the user was in the conf */
		snprintf(meetmesecs, sizeof(meetmesecs), "%i", (int) (time(NULL) - user->jointime));
		pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs);
	}
	free(user);
	ast_mutex_unlock(&conflock);
	return ret;
}
/*! 
 * \brief Stop monitoring channel 
 * \param chan 
 * \param need_lock
 * Stop the recording, close any open streams, mix in/out channels if required
 * \return Always 0
*/
int AST_OPTIONAL_API_NAME(ast_monitor_stop)(struct ast_channel *chan, int need_lock)
{
	int delfiles = 0;

	LOCK_IF_NEEDED(chan, need_lock);

	if (ast_channel_monitor(chan)) {
		char filename[ FILENAME_MAX ];

		if (ast_channel_monitor(chan)->read_stream) {
			ast_closestream(ast_channel_monitor(chan)->read_stream);
		}
		if (ast_channel_monitor(chan)->write_stream) {
			ast_closestream(ast_channel_monitor(chan)->write_stream);
		}

		if (ast_channel_monitor(chan)->filename_changed && !ast_strlen_zero(ast_channel_monitor(chan)->filename_base)) {
			if (ast_channel_monitor(chan)->read_stream) {
				if (ast_fileexists(ast_channel_monitor(chan)->read_filename,NULL,NULL) > 0) {
					snprintf(filename, FILENAME_MAX, "%s-in", ast_channel_monitor(chan)->filename_base);
					if (ast_fileexists(filename, NULL, NULL) > 0) {
						ast_filedelete(filename, NULL);
					}
					ast_filerename(ast_channel_monitor(chan)->read_filename, filename, ast_channel_monitor(chan)->format);
				} else {
					ast_log(LOG_WARNING, "File %s not found\n", ast_channel_monitor(chan)->read_filename);
				}
			}

			if (ast_channel_monitor(chan)->write_stream) {
				if (ast_fileexists(ast_channel_monitor(chan)->write_filename,NULL,NULL) > 0) {
					snprintf(filename, FILENAME_MAX, "%s-out", ast_channel_monitor(chan)->filename_base);
					if (ast_fileexists(filename, NULL, NULL) > 0) {
						ast_filedelete(filename, NULL);
					}
					ast_filerename(ast_channel_monitor(chan)->write_filename, filename, ast_channel_monitor(chan)->format);
				} else {
					ast_log(LOG_WARNING, "File %s not found\n", ast_channel_monitor(chan)->write_filename);
				}
			}
		}

		if (ast_channel_monitor(chan)->joinfiles && !ast_strlen_zero(ast_channel_monitor(chan)->filename_base)) {
			char tmp[1024];
			char tmp2[1024];
			const char *format = !strcasecmp(ast_channel_monitor(chan)->format,"wav49") ? "WAV" : ast_channel_monitor(chan)->format;
			char *fname_base = ast_channel_monitor(chan)->filename_base;
			const char *execute, *execute_args;
			/* at this point, fname_base really is the full path */

			/* Set the execute application */
			execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");
			if (ast_strlen_zero(execute)) {
#ifdef HAVE_SOXMIX
				execute = "nice -n 19 soxmix";
#else
				execute = "nice -n 19 sox -m";
#endif
				format = get_soxmix_format(format);
				delfiles = 1;
			} 
			execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
			if (ast_strlen_zero(execute_args)) {
				execute_args = "";
			}
			
			snprintf(tmp, sizeof(tmp), "%s \"%s-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &",
				execute, fname_base, format, fname_base, format, fname_base, format,execute_args);
			if (delfiles) {
				snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s-\"* ) &",tmp, fname_base); /* remove legs when done mixing */
				ast_copy_string(tmp, tmp2, sizeof(tmp));
			}
			ast_debug(1,"monitor executing %s\n",tmp);
			if (ast_safe_system(tmp) == -1)
				ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
		}
		
		ast_free(ast_channel_monitor(chan)->format);
		ast_free(ast_channel_monitor(chan));
		ast_channel_monitor_set(chan, NULL);

		ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStop",
			                "Channel: %s\r\n"
	                        "Uniqueid: %s\r\n",
	                        ast_channel_name(chan),
	                        ast_channel_uniqueid(chan)
	                        );
		pbx_builtin_setvar_helper(chan, "MONITORED", NULL);
	}
	pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL);

	UNLOCK_IF_NEEDED(chan, need_lock);

	return 0;
}
Esempio n. 30
0
static char *get_index(struct cw_channel *chan, const char *prefix, int index) {
	char varname[VAR_SIZE];

	snprintf(varname, VAR_SIZE, "%s_%d", prefix, index);
	return pbx_builtin_getvar_helper(chan, varname);
}