Пример #1
0
/*! \brief Helper function that creates an outgoing channel and returns it immediately */
static struct ast_channel *dial_transfer(const struct ast_channel *caller, const char *exten, const char *context)
{
	char destination[AST_MAX_EXTENSION+AST_MAX_CONTEXT+1] = "";
	struct ast_channel *chan = NULL;
	int cause;

	/* Fill the variable with the extension and context we want to call */
	snprintf(destination, sizeof(destination), "%s@%s", exten, context);

	/* Now we request that chan_local prepare to call the destination */
	if (!(chan = ast_request("Local", caller->nativeformats, caller, destination, &cause))) {
		return NULL;
	}

	/* Before we actually dial out let's inherit the appropriate dialplan variables */
	ast_channel_inherit_variables(caller, chan);

	/* Since the above worked fine now we actually call it and return the channel */
	if (ast_call(chan, destination, 0)) {
		ast_hangup(chan);
		return NULL;
	}

	return chan;
}
Пример #2
0
/*!
 * \internal
 * \brief Helper function that creates an outgoing channel and returns it immediately. This function is nearly
 *        identical to the dial_transfer function in bridge_basic.c, however it doesn't swap the
 *        local channel and the channel that instigated the park.
 */
static struct ast_channel *park_local_transfer(struct ast_channel *parker, const char *context, const char *exten, struct transfer_channel_data *parked_channel_data)
{
	char destination[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 1];
	struct ast_channel *parkee;
	struct ast_channel *parkee_side_2;
	int cause;

	/* Fill the variable with the extension and context we want to call */
	snprintf(destination, sizeof(destination), "%s@%s", exten, context);

	/* Now we request that chan_local prepare to call the destination */
	parkee = ast_request("Local", ast_channel_nativeformats(parker), NULL, parker, destination,
		&cause);
	if (!parkee) {
		return NULL;
	}

	/* Before we actually dial out let's inherit appropriate information. */
	ast_channel_lock_both(parker, parkee);
	ast_channel_req_accountcodes(parkee, parker, AST_CHANNEL_REQUESTOR_REPLACEMENT);
	ast_connected_line_copy_from_caller(ast_channel_connected(parkee), ast_channel_caller(parker));
	ast_channel_inherit_variables(parker, parkee);
	ast_channel_datastore_inherit(parker, parkee);
	ast_channel_unlock(parker);

	parkee_side_2 = ast_local_get_peer(parkee);
	ast_assert(parkee_side_2 != NULL);
	ast_channel_unlock(parkee);

	/* We need to have the parker subscribe to the new local channel before hand. */
	if (create_parked_subscription_full(parker, ast_channel_uniqueid(parkee_side_2), 1, parked_channel_data)) {
		ast_channel_unref(parkee_side_2);
		ast_hangup(parkee);
		return NULL;
	}

	ast_bridge_set_transfer_variables(parkee_side_2, ast_channel_name(parker), 0);

	ast_channel_unref(parkee_side_2);

	/* Since the above worked fine now we actually call it and return the channel */
	if (ast_call(parkee, destination, 0)) {
		ast_hangup(parkee);
		return NULL;
	}

	return parkee;
}
Пример #3
0
static struct ast_channel *prepare_bridge_media_channel(const char *type)
{
	RAII_VAR(struct ast_format_cap *, cap, NULL, ao2_cleanup);
	struct ast_channel *chan;

	cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
	if (!cap) {
		return NULL;
	}

	ast_format_cap_append(cap, ast_format_slin, 0);

	chan = ast_request(type, cap, NULL, NULL, "ARI", NULL);
	if (!chan) {
		return NULL;
	}

	if (stasis_app_channel_unreal_set_internal(chan)) {
		ast_channel_cleanup(chan);
		return NULL;
	}
	return chan;
}
static int chanavail_exec(struct ast_channel *chan, void *data)
{
	int res=-1, inuse=-1, option_state=0, priority_jump=0;
	int status;
	struct localuser *u;
	char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur, *options, *stringp;
	struct ast_channel *tempchan;

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "ChanIsAvail requires an argument (Zap/1&Zap/2)\n");
		return -1;
	}

	LOCAL_USER_ADD(u);

	info = ast_strdupa(data); 
	stringp = info;
	strsep(&stringp, "|");
	options = strsep(&stringp, "|");
	if (options) {
		if (strchr(options, 's'))
			option_state = 1;
		if (strchr(options, 'j'))
			priority_jump = 1;
	}
	peers = info;
	if (peers) {
		cur = peers;
		do {
			/* remember where to start next time */
			rest = strchr(cur, '&');
			if (rest) {
				*rest = 0;
				rest++;
			}
			tech = cur;
			number = strchr(tech, '/');
			if (!number) {
				ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
				LOCAL_USER_REMOVE(u);
				return -1;
			}
			*number = '\0';
			number++;
			
			if (option_state) {
				/* If the pbx says in use then don't bother trying further.
				   This is to permit testing if someone's on a call, even if the 
	 			   channel can permit more calls (ie callwaiting, sip calls, etc).  */
                               
				snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
				status = inuse = ast_device_state(trychan);
			}
			if ((inuse <= 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
					pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
					/* Store the originally used channel too */
					snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
					pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp);
					snprintf(tmp, sizeof(tmp), "%d", status);
					pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp);
					ast_hangup(tempchan);
					tempchan = NULL;
					res = 1;
					break;
			} else {
				snprintf(tmp, sizeof(tmp), "%d", status);
				pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp);
			}
			cur = rest;
		} while (cur);
	}
	if (res < 1) {
		pbx_builtin_setvar_helper(chan, "AVAILCHAN", "");
		pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", "");
		if (priority_jump || option_priority_jumping) {
			if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
				LOCAL_USER_REMOVE(u);
				return -1;
			}
		}
	}

	LOCAL_USER_REMOVE(u);
	return 0;
}
Пример #5
0
static struct ast_conference *build_conf(char *confno, char *pin, int make, int dynamic)
{
	struct ast_conference *cnf;
	struct zt_confinfo ztc;
	ast_mutex_lock(&conflock);
	cnf = confs;
	while(cnf) {
		if (!strcmp(confno, cnf->confno)) 
			break;
		cnf = cnf->next;
	}
	if (!cnf && (make || dynamic)) {
		cnf = malloc(sizeof(struct ast_conference));
		if (cnf) {
			/* Make a new one */
			memset(cnf, 0, sizeof(struct ast_conference));
			strncpy(cnf->confno, confno, sizeof(cnf->confno) - 1);
			strncpy(cnf->pin, pin, sizeof(cnf->pin) - 1);
			cnf->markedusers = 0;
			cnf->chan = ast_request("zap", AST_FORMAT_ULAW, "pseudo");
			if (cnf->chan) {
				cnf->fd = cnf->chan->fds[0];	/* for use by conf_play() */
			} else {
				ast_log(LOG_WARNING, "Unable to open pseudo channel - trying device\n");
				cnf->fd = open("/dev/zap/pseudo", O_RDWR);
				if (cnf->fd < 0) {
					ast_log(LOG_WARNING, "Unable to open pseudo device\n");
					free(cnf);
					cnf = NULL;
					goto cnfout;
				}
			}
			memset(&ztc, 0, sizeof(ztc));
			/* Setup a new zap conference */
			ztc.chan = 0;
			ztc.confno = -1;
			ztc.confmode = ZT_CONF_CONFANN;
			if (ioctl(cnf->fd, ZT_SETCONF, &ztc)) {
				ast_log(LOG_WARNING, "Error setting conference\n");
				if (cnf->chan)
					ast_hangup(cnf->chan);
				else
					close(cnf->fd);
				free(cnf);
				cnf = NULL;
				goto cnfout;
			}
			/* Fill the conference struct */
			cnf->start = time(NULL);
			cnf->zapconf = ztc.confno;
			cnf->isdynamic = dynamic;
			cnf->firstuser = NULL;
			cnf->lastuser = NULL;
			cnf->locked = 0;
			if (option_verbose > 2)
				ast_verbose(VERBOSE_PREFIX_3 "Created MeetMe conference %d for conference '%s'\n", cnf->zapconf, cnf->confno);
			cnf->next = confs;
			confs = cnf;
		} else	
			ast_log(LOG_WARNING, "Out of memory\n");
	}
cnfout:
	ast_mutex_unlock(&conflock);
	return cnf;
}
Пример #6
0
static void *dialstring(void *string)
{
	struct ast_channel *channel;
	char *bufptr,*destptr;
	int  ms=10000;		/* ms affects number of rings */
	int  cnt=0,first;
	char tech[256];
	char tele[256];
	char filename[256];
	int  answered=0;

	for(first=0, bufptr=(char *)string, destptr=tech; *bufptr&&cnt<256; cnt++){
		if(*bufptr=='/' && !first) {
			*destptr=0;
			destptr=tele;
			first=1;
		}
		else if(*bufptr==',') {
			*destptr=0;
			destptr=filename;
		} else {
			*destptr=*bufptr;
			destptr++;
		}
		bufptr++;
	} 
	*destptr=0;
	ast_log(LOG_DEBUG, "Printing string arg: %s Eos\n", (char *)string);
	if(strlen(tech)+strlen(tele)+strlen(filename) > 256) {
		ast_log(LOG_ERROR, "Autodial:Error string too long\n");
		free(string);
		pthread_exit(NULL);
	}
	ast_log(LOG_DEBUG, "Autodial Tech %s(%d) Tele %s(%d) Filename %s(%d)\n",tech, (int)strlen(tech), tele, (int)strlen(tele), filename, (int)strlen(filename));

	channel=ast_request(tech,AST_FORMAT_SLINEAR,tele);
	if(channel!=NULL){
		ast_call(channel,tele,10000);
	} else {
		ast_log(LOG_ERROR, "Autodial:Sorry unable to obtain channel\n");
		free(string);
		pthread_exit(NULL);
	}
	if(channel->_state==AST_STATE_UP)
		ast_log(LOG_DEBUG, "Autodial:Line is Up\n");
	while(ms>0){
		struct ast_frame *f;

		ms=ast_waitfor(channel,ms);
		f=ast_read(channel);
		if(!f){
			ast_log(LOG_DEBUG, "Autodial:Hung Up\n");
			break;
		}
		if (f->frametype==AST_FRAME_CONTROL) {
			if (f->subclass==AST_CONTROL_ANSWER) {
				ast_log(LOG_DEBUG, "Autodial:Phone Answered\n");
				if (channel->_state==AST_STATE_UP) {
					char res;

					ast_streamfile(channel,filename,0);
					/* Press Five for snooze */
					res=ast_waitstream(channel, "37");
					if(res=='3'){
						answered=1;
						set_snooze_alarm((char *)string,60);
						ast_streamfile(channel,"demo-thanks",0);
						ast_waitstream(channel, "");
					}
					else if(res=='7'){
						answered=1;
						ast_streamfile(channel,"demo-thanks",0);
						ast_waitstream(channel, "");
					}
					ast_stopstream(channel);
					ms=0;
				}
			}
			else if (f->subclass==AST_CONTROL_RINGING)
				ast_log(LOG_DEBUG, "Autodial:Phone Ringing end\n");
		}
		ast_frfree(f);
	}
	if(!answered)
		set_snooze_alarm((char *) string, 5);
	free(string);
	ast_hangup(channel);
	ast_log(LOG_DEBUG, "Autodial:Hung up channel\n");
	pthread_exit(NULL);
	return NULL;
}