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

📄 chan_gtalk.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 5 页
字号:
	struct gtalk_candidate *tmp;	struct hostent *hp;	struct ast_hostent ahp;	struct sockaddr_in sin;	struct sockaddr_in aux;	if (time(NULL) == p->laststun)		return 0;	tmp = p->theircandidates;	p->laststun = time(NULL);	while (tmp) {		char username[256];		/* Find the IP address of the host */		hp = ast_gethostbyname(tmp->ip, &ahp);		sin.sin_family = AF_INET;		memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));		sin.sin_port = htons(tmp->port);		snprintf(username, sizeof(username), "%s%s", tmp->username,			 p->ourcandidates->username);				/* Find out the result of the STUN */		ast_rtp_get_peer(p->rtp, &aux);		/* If the STUN result is different from the IP of the hostname,			lock on the stun IP of the hostname advertised by the			remote client */		if (aux.sin_addr.s_addr && 		    aux.sin_addr.s_addr != sin.sin_addr.s_addr)			ast_rtp_stun_request(p->rtp, &aux, username);		else 			ast_rtp_stun_request(p->rtp, &sin, username);				if (aux.sin_addr.s_addr && option_debug > 3) {			ast_log(LOG_DEBUG, "Receiving RTP traffic from IP %s, matches with remote candidate's IP %s\n", ast_inet_ntoa(aux.sin_addr), tmp->ip);			ast_log(LOG_DEBUG, "Sending STUN request to %s\n", tmp->ip);		}		tmp = tmp->next;	}	return 1;}static int gtalk_add_candidate(struct gtalk *client, ikspak *pak){	struct gtalk_pvt *p = NULL, *tmp = NULL;	struct aji_client *c = client->connection;	struct gtalk_candidate *newcandidate = NULL;	iks *traversenodes = NULL, *receipt = NULL;	char *from;	from = iks_find_attrib(pak->x,"to");	if(!from)		from = c->jid->full;	for (tmp = client->p; tmp; tmp = tmp->next) {		if (iks_find_with_attrib(pak->x, "session", "id", tmp->sid)) {			p = tmp;			break;		}	}	if (!p)		return -1;	traversenodes = pak->query;	while(traversenodes) {		if(!strcasecmp(iks_name(traversenodes), "session")) {			traversenodes = iks_child(traversenodes);			continue;		}		if(!strcasecmp(iks_name(traversenodes), "transport")) {			traversenodes = iks_child(traversenodes);			continue;		}		if(!strcasecmp(iks_name(traversenodes), "candidate")) {			newcandidate = ast_calloc(1, sizeof(*newcandidate));			if (!newcandidate)				return 0;			ast_copy_string(newcandidate->name, iks_find_attrib(traversenodes, "name"),							sizeof(newcandidate->name));			ast_copy_string(newcandidate->ip, iks_find_attrib(traversenodes, "address"),							sizeof(newcandidate->ip));			newcandidate->port = atoi(iks_find_attrib(traversenodes, "port"));			ast_copy_string(newcandidate->username, iks_find_attrib(traversenodes, "username"),							sizeof(newcandidate->username));			ast_copy_string(newcandidate->password, iks_find_attrib(traversenodes, "password"),							sizeof(newcandidate->password));			newcandidate->preference = atof(iks_find_attrib(traversenodes, "preference"));			if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "udp"))				newcandidate->protocol = AJI_PROTOCOL_UDP;			if (!strcasecmp(iks_find_attrib(traversenodes, "protocol"), "ssltcp"))				newcandidate->protocol = AJI_PROTOCOL_SSLTCP;					if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "stun"))				newcandidate->type = AJI_CONNECT_STUN;			if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "local"))				newcandidate->type = AJI_CONNECT_LOCAL;			if (!strcasecmp(iks_find_attrib(traversenodes, "type"), "relay"))				newcandidate->type = AJI_CONNECT_RELAY;			ast_copy_string(newcandidate->network, iks_find_attrib(traversenodes, "network"),							sizeof(newcandidate->network));			newcandidate->generation = atoi(iks_find_attrib(traversenodes, "generation"));			newcandidate->next = NULL;					newcandidate->next = p->theircandidates;			p->theircandidates = newcandidate;			p->laststun = 0;			gtalk_update_stun(p->parent, p);			newcandidate = NULL;		}		traversenodes = iks_next(traversenodes);	}		receipt = iks_new("iq");	iks_insert_attrib(receipt, "type", "result");	iks_insert_attrib(receipt, "from", from);	iks_insert_attrib(receipt, "to", iks_find_attrib(pak->x, "from"));	iks_insert_attrib(receipt, "id", iks_find_attrib(pak->x, "id"));	iks_send(c->p, receipt);	iks_delete(receipt);	return 1;}static struct ast_frame *gtalk_rtp_read(struct ast_channel *ast, struct gtalk_pvt *p){	struct ast_frame *f;	if (!p->rtp)		return &ast_null_frame;	f = ast_rtp_read(p->rtp);	gtalk_update_stun(p->parent, p);	if (p->owner) {		/* We already hold the channel lock */		if (f->frametype == AST_FRAME_VOICE) {			if (f->subclass != (p->owner->nativeformats & AST_FORMAT_AUDIO_MASK)) {				if (option_debug)					ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);				p->owner->nativeformats =					(p->owner->nativeformats & AST_FORMAT_VIDEO_MASK) | f->subclass;				ast_set_read_format(p->owner, p->owner->readformat);				ast_set_write_format(p->owner, p->owner->writeformat);			}/*			if ((ast_test_flag(p, SIP_DTMF) == SIP_DTMF_INBAND) && p->vad) {				f = ast_dsp_process(p->owner, p->vad, f);				if (option_debug && f && (f->frametype == AST_FRAME_DTMF))					ast_log(LOG_DEBUG, "* Detected inband DTMF '%c'\n", f->subclass);		        } */		}	}	return f;}static struct ast_frame *gtalk_read(struct ast_channel *ast){	struct ast_frame *fr;	struct gtalk_pvt *p = ast->tech_pvt;	ast_mutex_lock(&p->lock);	fr = gtalk_rtp_read(ast, p);	ast_mutex_unlock(&p->lock);	return fr;}/*! \brief Send frame to media channel (rtp) */static int gtalk_write(struct ast_channel *ast, struct ast_frame *frame){	struct gtalk_pvt *p = ast->tech_pvt;	int res = 0;	switch (frame->frametype) {	case AST_FRAME_VOICE:		if (!(frame->subclass & ast->nativeformats)) {			ast_log(LOG_WARNING,					"Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",					frame->subclass, ast->nativeformats, ast->readformat,					ast->writeformat);			return 0;		}		if (p) {			ast_mutex_lock(&p->lock);			if (p->rtp) {				res = ast_rtp_write(p->rtp, frame);			}			ast_mutex_unlock(&p->lock);		}		break;	case AST_FRAME_VIDEO:		if (p) {			ast_mutex_lock(&p->lock);			if (p->vrtp) {				res = ast_rtp_write(p->vrtp, frame);			}			ast_mutex_unlock(&p->lock);		}		break;	case AST_FRAME_IMAGE:		return 0;		break;	default:		ast_log(LOG_WARNING, "Can't send %d type frames with Gtalk write\n",				frame->frametype);		return 0;	}	return res;}static int gtalk_fixup(struct ast_channel *oldchan, struct ast_channel *newchan){	struct gtalk_pvt *p = newchan->tech_pvt;	ast_mutex_lock(&p->lock);	if ((p->owner != oldchan)) {		ast_mutex_unlock(&p->lock);		return -1;	}	if (p->owner == oldchan)		p->owner = newchan;	ast_mutex_unlock(&p->lock);	return 0;}static int gtalk_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen){	int res = 0;	switch (condition) {	case AST_CONTROL_HOLD:		ast_moh_start(ast, data, NULL);		break;	case AST_CONTROL_UNHOLD:		ast_moh_stop(ast);		break;	default:		ast_log(LOG_NOTICE, "Don't know how to indicate condition '%d'\n", condition);		res = -1;	}	return res;}static int gtalk_digit_begin(struct ast_channel *chan, char digit){	return gtalk_digit(chan, digit, 0);}static int gtalk_digit_end(struct ast_channel *chan, char digit, unsigned int duration){	return gtalk_digit(chan, digit, duration);}static int gtalk_digit(struct ast_channel *ast, char digit, unsigned int duration){	struct gtalk_pvt *p = ast->tech_pvt;	struct gtalk *client = p->parent;	iks *iq, *gtalk, *dtmf;	char buffer[2] = {digit, '\0'};	iq = iks_new("iq");	gtalk = iks_new("gtalk");	dtmf = iks_new("dtmf");	if(!iq || !gtalk || !dtmf) {		if(iq)			iks_delete(iq);		if(gtalk)			iks_delete(gtalk);		if(dtmf)			iks_delete(dtmf);		ast_log(LOG_ERROR, "Did not send dtmf do to memory issue\n");		return -1;	}	iks_insert_attrib(iq, "type", "set");	iks_insert_attrib(iq, "to", p->them);	iks_insert_attrib(iq, "from", p->us);	iks_insert_attrib(iq, "id", client->connection->mid);	ast_aji_increment_mid(client->connection->mid);	iks_insert_attrib(gtalk, "xmlns", "http://jabber.org/protocol/gtalk");	iks_insert_attrib(gtalk, "action", "session-info");	iks_insert_attrib(gtalk, "initiator", p->initiator ? p->us: p->them);	iks_insert_attrib(gtalk, "sid", p->sid);	iks_insert_attrib(dtmf, "xmlns", "http://jabber.org/protocol/gtalk/info/dtmf");	iks_insert_attrib(dtmf, "code", buffer);	iks_insert_node(iq, gtalk);	iks_insert_node(gtalk, dtmf);	ast_mutex_lock(&p->lock);	if (ast->dtmff.frametype == AST_FRAME_DTMF_BEGIN || duration == 0) {		iks_insert_attrib(dtmf, "action", "button-down");	} else if (ast->dtmff.frametype == AST_FRAME_DTMF_END || duration != 0) {		iks_insert_attrib(dtmf, "action", "button-up");	}	iks_send(client->connection->p, iq);	iks_delete(iq);	iks_delete(gtalk);	iks_delete(dtmf);	ast_mutex_unlock(&p->lock);	return 0;}static int gtalk_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen){	ast_log(LOG_NOTICE, "XXX Implement gtalk sendhtml XXX\n");	return -1;}/* Not in use right now.static int gtalk_auto_congest(void *nothing){	struct gtalk_pvt *p = nothing;	ast_mutex_lock(&p->lock);	if (p->owner) {		if (!ast_channel_trylock(p->owner)) {			ast_log(LOG_NOTICE, "Auto-congesting %s\n", p->owner->name);			ast_queue_control(p->owner, AST_CONTROL_CONGESTION);			ast_channel_unlock(p->owner);		}	}	ast_mutex_unlock(&p->lock);	return 0;}*//*! \brief Initiate new call, part of PBX interface  * 	dest is the dial string */static int gtalk_call(struct ast_channel *ast, char *dest, int timeout){	struct gtalk_pvt *p = ast->tech_pvt;	if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {		ast_log(LOG_WARNING, "gtalk_call called on %s, neither down nor reserved\n", ast->name);		return -1;	}	ast_setstate(ast, AST_STATE_RING);	if (!p->ringrule) {		ast_copy_string(p->ring, p->parent->connection->mid, sizeof(p->ring));		p->ringrule = iks_filter_add_rule(p->parent->connection->f, gtalk_ringing_ack, p,							IKS_RULE_ID, p->ring, IKS_RULE_DONE);	} else		ast_log(LOG_WARNING, "Whoa, already have a ring rule!\n");	gtalk_invite(p, p->them, p->us, p->sid, 1);	gtalk_create_candidates(p->parent, p, p->sid, p->them, p->us);	return 0;}/*! \brief Hangup a call through the gtalk proxy channel */static int gtalk_hangup(struct ast_channel *ast){	struct gtalk_pvt *p = ast->tech_pvt;	struct gtalk *client;	ast_mutex_lock(&p->lock);	client = p->parent;	p->owner = NULL;	ast->tech_pvt = NULL;	if (!p->alreadygone)		gtalk_action(client, p, "terminate");	ast_mutex_unlock(&p->lock);	gtalk_free_pvt(client, p);	ast_module_unref(ast_module_info->self);	return 0;}/*! \brief Part of PBX interface */static struct ast_channel *gtalk_request(const char *type, int format, void *data, int *cause){	struct gtalk_pvt *p = NULL;	struct gtalk *client = NULL;	char *sender = NULL, *to = NULL, *s = NULL;	struct ast_channel *chan = NULL;	if (data) {		s = ast_strdupa(data);		if (s) {			sender = strsep(&s, "/");			if (sender && (sender[0] != '\0'))				to = strsep(&s, "/");			if (!to) {				ast_log(LOG_ERROR, "Bad arguments in Gtalk Dialstring: %s\n", (char*) data);				return NULL;			}		}	}	client = find_gtalk(to, sender);	if (!client) {		ast_log(LOG_WARNING, "Could not find recipient.\n");		return NULL;	}	if (!strcasecmp(client->name, "guest")){		/* the guest account is not tied to any configured XMPP client,		   let's set it now */		client->connection = ast_aji_get_client(sender);		if (!client->connection) {			ast_log(LOG_ERROR, "No XMPP client to talk to, us (partial JID) : %s\n", sender);			ASTOBJ_UNREF(client, gtalk_member_destroy);			return NULL;		}	}	ASTOBJ_WRLOCK(client);	p = gtalk_alloc(client, strchr(sender, '@') ? sender : client->connection->jid->full, strchr(to, '@') ? to : client->user, NULL);	if (p)		chan = gtalk_new(client, p, AST_STATE_DOWN, to);

⌨️ 快捷键说明

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