⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chan_agent.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 5 页
字号:
}static int agent_hangup(struct ast_channel *ast){	struct agent_pvt *p = ast->tech_pvt;	int howlong = 0;	const char *status;	ast_mutex_lock(&p->lock);	p->owner = NULL;	ast->tech_pvt = NULL;	p->app_sleep_cond = 1;	p->acknowledged = 0;	/* if they really are hung up then set start to 0 so the test	 * later if we're called on an already downed channel	 * doesn't cause an agent to be logged out like when	 * agent_request() is followed immediately by agent_hangup()	 * as in apps/app_chanisavail.c:chanavail_exec()	 */	if (option_debug)		ast_log(LOG_DEBUG, "Hangup called for state %s\n", ast_state2str(ast->_state));	if (p->start && (ast->_state != AST_STATE_UP)) {		howlong = time(NULL) - p->start;		p->start = 0;	} else if (ast->_state == AST_STATE_RESERVED) 		howlong = 0;	else		p->start = 0; 	if (p->chan) {		p->chan->_bridge = NULL;		/* If they're dead, go ahead and hang up on the agent now */		if (!ast_strlen_zero(p->loginchan)) {			/* Store last disconnect time */			if (p->wrapuptime)				p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));			else				p->lastdisc = ast_tv(0,0);			if (p->chan) {				status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS");				if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) {					long logintime = time(NULL) - p->loginstart;					p->loginstart = 0;					ast_log(LOG_NOTICE, "Agent hangup: '%s' is not available now, auto logoff\n", p->name);					agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Chanunavail");				}				/* Recognize the hangup and pass it along immediately */				ast_hangup(p->chan);				p->chan = NULL;				p->inherited_devicestate = -1;				ast_device_state_changed("Agent/%s", p->agent);			}			ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff);			if ((p->deferlogoff) || (howlong && p->autologoff && (howlong > p->autologoff))) {				long logintime = time(NULL) - p->loginstart;				p->loginstart = 0;				if (!p->deferlogoff)					ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);				p->deferlogoff = 0;				agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Autologoff");				if (persistent_agents)					dump_agents();			}		} else if (p->dead) {			ast_channel_lock(p->chan);			ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);			ast_channel_unlock(p->chan);		} else if (p->loginstart) {			ast_channel_lock(p->chan);			ast_indicate_data(p->chan, AST_CONTROL_HOLD, 				S_OR(p->moh, NULL),				!ast_strlen_zero(p->moh) ? strlen(p->moh) + 1 : 0);			ast_channel_unlock(p->chan);		}	}	ast_mutex_unlock(&p->lock);	/* Only register a device state change if the agent is still logged in */	if (!p->loginstart) {		p->loginchan[0] = '\0';		p->logincallerid[0] = '\0';		if (persistent_agents)			dump_agents();	} else {		ast_device_state_changed("Agent/%s", p->agent);	}	if (p->pending) {		AST_LIST_LOCK(&agents);		AST_LIST_REMOVE(&agents, p, list);		AST_LIST_UNLOCK(&agents);	}	if (p->abouttograb) {		/* Let the "about to grab" thread know this isn't valid anymore, and let it		   kill it later */		p->abouttograb = 0;	} else if (p->dead) {		ast_mutex_destroy(&p->lock);		ast_mutex_destroy(&p->app_lock);		free(p);	} else {		if (p->chan) {			/* Not dead -- check availability now */			ast_mutex_lock(&p->lock);			/* Store last disconnect time */			p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));			ast_mutex_unlock(&p->lock);		}		/* Release ownership of the agent to other threads (presumably running the login app). */		if (ast_strlen_zero(p->loginchan))			ast_mutex_unlock(&p->app_lock);	}	return 0;}static int agent_cont_sleep( void *data ){	struct agent_pvt *p;	int res;	p = (struct agent_pvt *)data;	ast_mutex_lock(&p->lock);	res = p->app_sleep_cond;	if (p->lastdisc.tv_sec) {		if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) 			res = 1;	}	ast_mutex_unlock(&p->lock);	if(option_debug > 4 && !res )		ast_log(LOG_DEBUG, "agent_cont_sleep() returning %d\n", res );	return res;}static int agent_ack_sleep(void *data){	struct agent_pvt *p;	int res=0;	int to = 1000;	struct ast_frame *f;	/* Wait a second and look for something */	p = (struct agent_pvt *) data;	if (!p->chan) 		return -1;	for(;;) {		to = ast_waitfor(p->chan, to);		if (to < 0) 			return -1;		if (!to) 			return 0;		f = ast_read(p->chan);		if (!f) 			return -1;		if (f->frametype == AST_FRAME_DTMF)			res = f->subclass;		else			res = 0;		ast_frfree(f);		ast_mutex_lock(&p->lock);		if (!p->app_sleep_cond) {			ast_mutex_unlock(&p->lock);			return 0;		} else if (res == '#') {			ast_mutex_unlock(&p->lock);			return 1;		}		ast_mutex_unlock(&p->lock);		res = 0;	}	return res;}static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge){	struct agent_pvt *p = bridge->tech_pvt;	struct ast_channel *ret = NULL;	if (p) {		if (chan == p->chan)			ret = bridge->_bridge;		else if (chan == bridge->_bridge)			ret = p->chan;	}	if (option_debug)		ast_log(LOG_DEBUG, "Asked for bridged channel on '%s'/'%s', returning '%s'\n", chan->name, bridge->name, ret ? ret->name : "<none>");	return ret;}/*! \brief Create new agent channel */static struct ast_channel *agent_new(struct agent_pvt *p, int state){	struct ast_channel *tmp;#if 0	if (!p->chan) {		ast_log(LOG_WARNING, "No channel? :(\n");		return NULL;	}#endif		if (p->pending)		tmp = ast_channel_alloc(0, state, 0, 0, "", p->chan ? p->chan->exten:"", p->chan ? p->chan->context:"", 0, "Agent/P%s-%d", p->agent, ast_random() & 0xffff);	else		tmp = ast_channel_alloc(0, state, 0, 0, "", p->chan ? p->chan->exten:"", p->chan ? p->chan->context:"", 0, "Agent/%s", p->agent);	if (!tmp) {		ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n");		return NULL;	}	tmp->tech = &agent_tech;	if (p->chan) {		tmp->nativeformats = p->chan->nativeformats;		tmp->writeformat = p->chan->writeformat;		tmp->rawwriteformat = p->chan->writeformat;		tmp->readformat = p->chan->readformat;		tmp->rawreadformat = p->chan->readformat;		ast_string_field_set(tmp, language, p->chan->language);		ast_copy_string(tmp->context, p->chan->context, sizeof(tmp->context));		ast_copy_string(tmp->exten, p->chan->exten, sizeof(tmp->exten));		/* XXX Is this really all we copy form the originating channel?? */	} else {		tmp->nativeformats = AST_FORMAT_SLINEAR;		tmp->writeformat = AST_FORMAT_SLINEAR;		tmp->rawwriteformat = AST_FORMAT_SLINEAR;		tmp->readformat = AST_FORMAT_SLINEAR;		tmp->rawreadformat = AST_FORMAT_SLINEAR;	}	/* Safe, agentlock already held */	tmp->tech_pvt = p;	p->owner = tmp;	/* XXX: this needs fixing */#if 0	ast_atomic_fetchadd_int(&__mod_desc->usecnt, +1);#endif	ast_update_use_count();	tmp->priority = 1;	/* Wake up and wait for other applications (by definition the login app)	 * to release this channel). Takes ownership of the agent channel	 * to this thread only.	 * For signalling the other thread, ast_queue_frame is used until we	 * can safely use signals for this purpose. The pselect() needs to be	 * implemented in the kernel for this.	 */	p->app_sleep_cond = 0;	if(ast_strlen_zero(p->loginchan) && ast_mutex_trylock(&p->app_lock)) {		if (p->chan) {			ast_queue_frame(p->chan, &ast_null_frame);			ast_mutex_unlock(&p->lock);	/* For other thread to read the condition. */			ast_mutex_lock(&p->app_lock);			ast_mutex_lock(&p->lock);		} else {			ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n");			p->owner = NULL;			tmp->tech_pvt = NULL;			p->app_sleep_cond = 1;			ast_channel_free( tmp );			ast_mutex_unlock(&p->lock);	/* For other thread to read the condition. */			ast_mutex_unlock(&p->app_lock);			return NULL;		}	} else if (!ast_strlen_zero(p->loginchan)) {		if (p->chan)			ast_queue_frame(p->chan, &ast_null_frame);		if (!p->chan) {			ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n");			p->owner = NULL;			tmp->tech_pvt = NULL;			p->app_sleep_cond = 1;			ast_channel_free( tmp );			ast_mutex_unlock(&p->lock);     /* For other thread to read the condition. */			return NULL;		}		} 	if (p->chan)		ast_indicate(p->chan, AST_CONTROL_UNHOLD);	p->owning_app = pthread_self();	/* After the above step, there should not be any blockers. */	if (p->chan) {		if (ast_test_flag(p->chan, AST_FLAG_BLOCKING)) {			ast_log( LOG_ERROR, "A blocker exists after agent channel ownership acquired\n" );			ast_assert(ast_test_flag(p->chan, AST_FLAG_BLOCKING) == 0);		}	}	return tmp;}/*! * Read configuration data. The file named agents.conf. * * \returns Always 0, or so it seems. */static int read_agent_config(void){	struct ast_config *cfg;	struct ast_config *ucfg;	struct ast_variable *v;	struct agent_pvt *p;	const char *general_val;	const char *catname;	const char *hasagent;	int genhasagent;	group = 0;	autologoff = 0;	wrapuptime = 0;	ackcall = 0;	endcall = 1;	cfg = ast_config_load(config);	if (!cfg) {		ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n");		return 0;	}	AST_LIST_LOCK(&agents);	AST_LIST_TRAVERSE(&agents, p, list) {		p->dead = 1;	}	strcpy(moh, "default");	/* set the default recording values */	recordagentcalls = 0;	strcpy(recordformat, "wav");	strcpy(recordformatext, "wav");	urlprefix[0] = '\0';	savecallsin[0] = '\0';	/* Read in [general] section for persistence */	if ((general_val = ast_variable_retrieve(cfg, "general", "persistentagents")))		persistent_agents = ast_true(general_val);	multiplelogin = ast_true(ast_variable_retrieve(cfg, "general", "multiplelogin"));	/* Read in the [agents] section */	v = ast_variable_browse(cfg, "agents");	while(v) {		/* Create the interface list */		if (!strcasecmp(v->name, "agent")) {			add_agent(v->value, 0);		} else if (!strcasecmp(v->name, "group")) {			group = ast_get_group(v->value);		} else if (!strcasecmp(v->name, "autologoff")) {			autologoff = atoi(v->value);			if (autologoff < 0)				autologoff = 0;		} else if (!strcasecmp(v->name, "ackcall")) {			if (!strcasecmp(v->value, "always"))				ackcall = 2;			else if (ast_true(v->value))				ackcall = 1;			else				ackcall = 0;		} else if (!strcasecmp(v->name, "endcall")) {			endcall = ast_true(v->value);		} else if (!strcasecmp(v->name, "wrapuptime")) {			wrapuptime = atoi(v->value);			if (wrapuptime < 0)				wrapuptime = 0;		} else if (!strcasecmp(v->name, "maxlogintries") && !ast_strlen_zero(v->value)) {			maxlogintries = atoi(v->value);			if (maxlogintries < 0)				maxlogintries = 0;		} else if (!strcasecmp(v->name, "goodbye") && !ast_strlen_zero(v->value)) {			strcpy(agentgoodbye,v->value);		} else if (!strcasecmp(v->name, "musiconhold")) {			ast_copy_string(moh, v->value, sizeof(moh));		} else if (!strcasecmp(v->name, "updatecdr")) {			if (ast_true(v->value))				updatecdr = 1;			else				updatecdr = 0;		} else if (!strcasecmp(v->name, "autologoffunavail")) {			if (ast_true(v->value))				autologoffunavail = 1;			else				autologoffunavail = 0;		} else if (!strcasecmp(v->name, "recordagentcalls")) {			recordagentcalls = ast_true(v->value);		} else if (!strcasecmp(v->name, "recordformat")) {			ast_copy_string(recordformat, v->value, sizeof(recordformat));			if (!strcasecmp(v->value, "wav49"))				strcpy(recordformatext, "WAV");			else				ast_copy_string(recordformatext, v->value, sizeof(recordformatext));		} else if (!strcasecmp(v->name, "urlprefix")) {			ast_copy_string(urlprefix, v->value, sizeof(urlprefix));			if (urlprefix[strlen(urlprefix) - 1] != '/')				strncat(urlprefix, "/", sizeof(urlprefix) - strlen(urlprefix) - 1);		} else if (!strcasecmp(v->name, "savecallsin")) {			if (v->value[0] == '/')				ast_copy_string(savecallsin, v->value, sizeof(savecallsin));			else				snprintf(savecallsin, sizeof(savecallsin) - 2, "/%s", v->value);			if (savecallsin[strlen(savecallsin) - 1] != '/')				strncat(savecallsin, "/", sizeof(savecallsin) - strlen(savecallsin) - 1);		} else if (!strcasecmp(v->name, "custom_beep")) {			ast_copy_string(beep, v->value, sizeof(beep));		}		v = v->next;	}	if ((ucfg = ast_config_load("users.conf"))) {		genhasagent = ast_true(ast_variable_retrieve(ucfg, "general", "hasagent"));		catname = ast_category_browse(ucfg, NULL);		while(catname) {			if (strcasecmp(catname, "general")) {				hasagent = ast_variable_retrieve(ucfg, catname, "hasagent");				if (ast_true(hasagent) || (!hasagent && genhasagent)) {					char tmp[256];					const char *fullname = ast_variable_retrieve(ucfg, catname, "fullname");					const char *secret = ast_variable_retrieve(ucfg, catname, "secret");					if (!fullname)						fullname = "";

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -