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

📄 chan_agent.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 5 页
字号:
					if (!secret)						secret = "";					snprintf(tmp, sizeof(tmp), "%s,%s,%s", catname, secret,fullname);					add_agent(tmp, 0);				}			}			catname = ast_category_browse(ucfg, catname);		}		ast_config_destroy(ucfg);	}	AST_LIST_TRAVERSE_SAFE_BEGIN(&agents, p, list) {		if (p->dead) {			AST_LIST_REMOVE_CURRENT(&agents, list);			/* Destroy if  appropriate */			if (!p->owner) {				if (!p->chan) {					ast_mutex_destroy(&p->lock);					ast_mutex_destroy(&p->app_lock);					free(p);				} else {					/* Cause them to hang up */					ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);				}			}		}	}	AST_LIST_TRAVERSE_SAFE_END	AST_LIST_UNLOCK(&agents);	ast_config_destroy(cfg);	return 1;}static int check_availability(struct agent_pvt *newlyavailable, int needlock){	struct ast_channel *chan=NULL, *parent=NULL;	struct agent_pvt *p;	int res;	if (option_debug)		ast_log(LOG_DEBUG, "Checking availability of '%s'\n", newlyavailable->agent);	if (needlock)		AST_LIST_LOCK(&agents);	AST_LIST_TRAVERSE(&agents, p, list) {		if (p == newlyavailable) {			continue;		}		ast_mutex_lock(&p->lock);		if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {			if (option_debug)				ast_log(LOG_DEBUG, "Call '%s' looks like a winner for agent '%s'\n", p->owner->name, newlyavailable->agent);			/* We found a pending call, time to merge */			chan = agent_new(newlyavailable, AST_STATE_DOWN);			parent = p->owner;			p->abouttograb = 1;			ast_mutex_unlock(&p->lock);			break;		}		ast_mutex_unlock(&p->lock);	}	if (needlock)		AST_LIST_UNLOCK(&agents);	if (parent && chan)  {		if (newlyavailable->ackcall > 1) {			/* Don't do beep here */			res = 0;		} else {			if (option_debug > 2)				ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language);			res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language);			if (option_debug > 2)				ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res);			if (!res) {				res = ast_waitstream(newlyavailable->chan, "");				ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res);			}		}		if (!res) {			/* Note -- parent may have disappeared */			if (p->abouttograb) {				newlyavailable->acknowledged = 1;				/* Safe -- agent lock already held */				ast_setstate(parent, AST_STATE_UP);				ast_setstate(chan, AST_STATE_UP);				ast_copy_string(parent->context, chan->context, sizeof(parent->context));				/* Go ahead and mark the channel as a zombie so that masquerade will				   destroy it for us, and we need not call ast_hangup */				ast_mutex_lock(&parent->lock);				ast_set_flag(chan, AST_FLAG_ZOMBIE);				ast_channel_masquerade(parent, chan);				ast_mutex_unlock(&parent->lock);				p->abouttograb = 0;			} else {				if (option_debug)					ast_log(LOG_DEBUG, "Sneaky, parent disappeared in the mean time...\n");				agent_cleanup(newlyavailable);			}		} else {			if (option_debug)				ast_log(LOG_DEBUG, "Ugh...  Agent hung up at exactly the wrong time\n");			agent_cleanup(newlyavailable);		}	}	return 0;}static int check_beep(struct agent_pvt *newlyavailable, int needlock){	struct agent_pvt *p;	int res=0;	ast_log(LOG_DEBUG, "Checking beep availability of '%s'\n", newlyavailable->agent);	if (needlock)		AST_LIST_LOCK(&agents);	AST_LIST_TRAVERSE(&agents, p, list) {		if (p == newlyavailable) {			continue;		}		ast_mutex_lock(&p->lock);		if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {			if (option_debug)				ast_log(LOG_DEBUG, "Call '%s' looks like a would-be winner for agent '%s'\n", p->owner->name, newlyavailable->agent);			ast_mutex_unlock(&p->lock);			break;		}		ast_mutex_unlock(&p->lock);	}	if (needlock)		AST_LIST_UNLOCK(&agents);	if (p) {		ast_mutex_unlock(&newlyavailable->lock);		if (option_debug > 2)			ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language);		res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language);		if (option_debug > 2)			ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res);		if (!res) {			res = ast_waitstream(newlyavailable->chan, "");			if (option_debug)				ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res);		}		ast_mutex_lock(&newlyavailable->lock);	}	return res;}/* return 1 if multiple login is fine, 0 if it is not and we find a match, -1 if multiplelogin is not allowed and we don't find a match. */static int allow_multiple_login(char *chan, char *context){	struct agent_pvt *p;	char loginchan[80];	if(multiplelogin)		return 1;	if(!chan) 		return 0;	snprintf(loginchan, sizeof(loginchan), "%s@%s", chan, S_OR(context, "default"));		AST_LIST_TRAVERSE(&agents, p, list) {		if(!strcasecmp(chan, p->loginchan))			return 0;	}	return -1;}/*! \brief Part of the Asterisk PBX interface */static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause){	struct agent_pvt *p;	struct ast_channel *chan = NULL;	char *s;	ast_group_t groupmatch;	int groupoff;	int waitforagent=0;	int hasagent = 0;	struct timeval tv;	s = data;	if ((s[0] == '@') && (sscanf(s + 1, "%d", &groupoff) == 1)) {		groupmatch = (1 << groupoff);	} else if ((s[0] == ':') && (sscanf(s + 1, "%d", &groupoff) == 1)) {		groupmatch = (1 << groupoff);		waitforagent = 1;	} else 		groupmatch = 0;	/* Check actual logged in agents first */	AST_LIST_LOCK(&agents);	AST_LIST_TRAVERSE(&agents, p, list) {		ast_mutex_lock(&p->lock);		if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) &&		    ast_strlen_zero(p->loginchan)) {			if (p->chan)				hasagent++;			tv = ast_tvnow();			if (!p->lastdisc.tv_sec || (tv.tv_sec >= p->lastdisc.tv_sec)) {				p->lastdisc = ast_tv(0, 0);				/* Agent must be registered, but not have any active call, and not be in a waiting state */				if (!p->owner && p->chan) {					/* Fixed agent */					chan = agent_new(p, AST_STATE_DOWN);				}				if (chan) {					ast_mutex_unlock(&p->lock);					break;				}			}		}		ast_mutex_unlock(&p->lock);	}	if (!p) {		AST_LIST_TRAVERSE(&agents, p, list) {			ast_mutex_lock(&p->lock);			if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {				if (p->chan || !ast_strlen_zero(p->loginchan))					hasagent++;				tv = ast_tvnow();#if 0				ast_log(LOG_NOTICE, "Time now: %ld, Time of lastdisc: %ld\n", tv.tv_sec, p->lastdisc.tv_sec);#endif				if (!p->lastdisc.tv_sec || (tv.tv_sec >= p->lastdisc.tv_sec)) {					p->lastdisc = ast_tv(0, 0);					/* Agent must be registered, but not have any active call, and not be in a waiting state */					if (!p->owner && p->chan) {						/* Could still get a fixed agent */						chan = agent_new(p, AST_STATE_DOWN);					} else if (!p->owner && !ast_strlen_zero(p->loginchan)) {						/* Adjustable agent */						p->chan = ast_request("Local", format, p->loginchan, cause);						if (p->chan)							chan = agent_new(p, AST_STATE_DOWN);					}					if (chan) {						ast_mutex_unlock(&p->lock);						break;					}				}			}			ast_mutex_unlock(&p->lock);		}	}	if (!chan && waitforagent) {		/* No agent available -- but we're requesting to wait for one.		   Allocate a place holder */		if (hasagent) {			if (option_debug)				ast_log(LOG_DEBUG, "Creating place holder for '%s'\n", s);			p = add_agent(data, 1);			p->group = groupmatch;			chan = agent_new(p, AST_STATE_DOWN);			if (!chan) 				ast_log(LOG_WARNING, "Weird...  Fix this to drop the unused pending agent\n");		} else			ast_log(LOG_DEBUG, "Not creating place holder for '%s' since nobody logged in\n", s);	}	*cause = hasagent ? AST_CAUSE_BUSY : AST_CAUSE_UNREGISTERED;	AST_LIST_UNLOCK(&agents);	return chan;}static force_inline int powerof(unsigned int d){	int x = ffs(d);	if (x)		return x - 1;	return 0;}/*! * Lists agents and their status to the Manager API. * It is registered on load_module() and it gets called by the manager backend. * \param s * \param m * \returns  * \sa action_agent_logoff(), action_agent_callback_login(), load_module(). */static int action_agents(struct mansession *s, const struct message *m){	const char *id = astman_get_header(m,"ActionID");	char idText[256] = "";	char chanbuf[256];	struct agent_pvt *p;	char *username = NULL;	char *loginChan = NULL;	char *talkingtoChan = NULL;	char *status = NULL;	if (!ast_strlen_zero(id))		snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);	astman_send_ack(s, m, "Agents will follow");	AST_LIST_LOCK(&agents);	AST_LIST_TRAVERSE(&agents, p, list) {        	ast_mutex_lock(&p->lock);		/* Status Values:		   AGENT_LOGGEDOFF - Agent isn't logged in		   AGENT_IDLE      - Agent is logged in, and waiting for call		   AGENT_ONCALL    - Agent is logged in, and on a call		   AGENT_UNKNOWN   - Don't know anything about agent. Shouldn't ever get this. */		username = S_OR(p->name, "None");		/* Set a default status. It 'should' get changed. */		status = "AGENT_UNKNOWN";		if (!ast_strlen_zero(p->loginchan) && !p->chan) {			loginChan = p->loginchan;			talkingtoChan = "n/a";			status = "AGENT_IDLE";			if (p->acknowledged) {				snprintf(chanbuf, sizeof(chanbuf), " %s (Confirmed)", p->loginchan);				loginChan = chanbuf;			}		} else if (p->chan) {			loginChan = ast_strdupa(p->chan->name);			if (p->owner && p->owner->_bridge) {				if (ast_bridged_channel(p->owner)) {					talkingtoChan = ast_strdupa(S_OR(ast_bridged_channel(p->owner)->cid.cid_num, ""));				} else {					talkingtoChan = "n/a";				}        			status = "AGENT_ONCALL";			} else {        			talkingtoChan = "n/a";        			status = "AGENT_IDLE";			}		} else {			loginChan = "n/a";			talkingtoChan = "n/a";			status = "AGENT_LOGGEDOFF";		}		astman_append(s, "Event: Agents\r\n"			"Agent: %s\r\n"			"Name: %s\r\n"			"Status: %s\r\n"			"LoggedInChan: %s\r\n"			"LoggedInTime: %d\r\n"			"TalkingTo: %s\r\n"			"%s"			"\r\n",			p->agent, username, status, loginChan, (int)p->loginstart, talkingtoChan, idText);		ast_mutex_unlock(&p->lock);	}	AST_LIST_UNLOCK(&agents);	astman_append(s, "Event: AgentsComplete\r\n"		"%s"		"\r\n",idText);	return 0;}static void agent_logoff_maintenance(struct agent_pvt *p, char *loginchan, long logintime, const char *uniqueid, char *logcommand){	char *tmp = NULL;	char agent[AST_MAX_AGENT];	if (!ast_strlen_zero(logcommand))		tmp = logcommand;	else		tmp = ast_strdupa("");	snprintf(agent, sizeof(agent), "Agent/%s", p->agent);	if (!ast_strlen_zero(uniqueid)) {		manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff",				"Agent: %s\r\n"				"Reason: %s\r\n"				"Loginchan: %s\r\n"				"Logintime: %ld\r\n"				"Uniqueid: %s\r\n", 				p->agent, tmp, loginchan, logintime, uniqueid);	} else {		manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff",				"Agent: %s\r\n"				"Reason: %s\r\n"				"Loginchan: %s\r\n"				"Logintime: %ld\r\n",				p->agent, tmp, loginchan, logintime);	}	ast_queue_log("NONE", ast_strlen_zero(uniqueid) ? "NONE" : uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", loginchan, logintime, tmp);	set_agentbycallerid(p->logincallerid, NULL);	p->loginchan[0] ='\0';	p->logincallerid[0] = '\0';	p->inherited_devicestate = -1;	ast_device_state_changed("Agent/%s", p->agent);	if (persistent_agents)		dump_agents();	}static int agent_logoff(const char *agent, int soft){	struct agent_pvt *p;	long logintime;	int ret = -1; /* Return -1 if no agent if found */	AST_LIST_LOCK(&agents);	AST_LIST_TRAVERSE(&agents, p, list) {		if (!strcasecmp(p->agent, agent)) {			ret = 0;			if (p->owner || p->chan) {				if (!soft) {					ast_mutex_lock(&p->lock);					while (p->owner && ast_channel_trylock(p->owner)) {						DEADLOCK_AVOIDANCE(&p->lock);					}					if (p->owner) {						ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);

⌨️ 快捷键说明

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