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

📄 chan_mgcp.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 5 页
字号:
	sub->callid[0] = '\0';	sub->cxmode = MGCP_CX_INACTIVE;	sub->outgoing = 0;	sub->alreadygone = 0;	memset(&sub->tmpdest, 0, sizeof(sub->tmpdest));	if (sub->rtp) {		ast_rtp_destroy(sub->rtp);		sub->rtp = NULL;	}	dump_cmd_queues(NULL, sub); /* SC */	return 0;}/* modified for new transport mechanism */static int __mgcp_xmit(struct mgcp_gateway *gw, char *data, int len){	int res;	if (gw->addr.sin_addr.s_addr)		res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->addr, sizeof(struct sockaddr_in));	else 		res=sendto(mgcpsock, data, len, 0, (struct sockaddr *)&gw->defaddr, sizeof(struct sockaddr_in));	if (res != len) {		ast_log(LOG_WARNING, "mgcp_xmit returned %d: %s\n", res, strerror(errno));	}	return res;}static int resend_response(struct mgcp_subchannel *sub, struct mgcp_response *resp){	struct mgcp_endpoint *p = sub->parent;	int res;	if (mgcpdebug) {		ast_verbose("Retransmitting:\n%s\n to %s:%d\n", resp->buf, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));	}	res = __mgcp_xmit(p->parent, resp->buf, resp->len);	if (res > 0)		res = 0;	return res;}static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req){	struct mgcp_endpoint *p = sub->parent;	int res;	if (mgcpdebug) {		ast_verbose("Transmitting:\n%s\n to %s:%d\n", req->data, ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));	}	res = __mgcp_xmit(p->parent, req->data, req->len);	if (res > 0)		res = 0;	return res;}/* modified for new transport framework */static void dump_queue(struct mgcp_gateway *gw, struct mgcp_endpoint *p){	struct mgcp_message *cur, *q = NULL, *w, *prev;	ast_mutex_lock(&gw->msgs_lock);	prev = NULL, cur = gw->msgs;	while (cur) {		if (!p || cur->owner_ep == p) {			if (prev)				prev->next = cur->next;			else				gw->msgs = cur->next;			ast_log(LOG_NOTICE, "Removing message from %s transaction %u\n", 				gw->name, cur->seqno);			w = cur;			cur = cur->next;			if (q) {				w->next = q;			} else {				w->next = NULL;			}			q = w;		} else {			prev = cur, cur=cur->next;		}	}	ast_mutex_unlock(&gw->msgs_lock);	while (q) {		cur = q;		q = q->next;		free(cur);	}}static void mgcp_queue_frame(struct mgcp_subchannel *sub, struct ast_frame *f){	for(;;) {		if (sub->owner) {			if (!ast_mutex_trylock(&sub->owner->lock)) {				ast_queue_frame(sub->owner, f);				ast_mutex_unlock(&sub->owner->lock);				break;			} else {				DEADLOCK_AVOIDANCE(&sub->lock);			}		} else			break;	}}static void mgcp_queue_hangup(struct mgcp_subchannel *sub){	for(;;) {		if (sub->owner) {			if (!ast_mutex_trylock(&sub->owner->lock)) {				ast_queue_hangup(sub->owner);				ast_mutex_unlock(&sub->owner->lock);				break;			} else {				DEADLOCK_AVOIDANCE(&sub->lock);			}		} else			break;	}}static void mgcp_queue_control(struct mgcp_subchannel *sub, int control){	struct ast_frame f = { AST_FRAME_CONTROL, };	f.subclass = control;	return mgcp_queue_frame(sub, &f);}static int retrans_pkt(const void *data){	struct mgcp_gateway *gw = (struct mgcp_gateway *)data;	struct mgcp_message *cur, *exq = NULL, *w, *prev;	int res = 0;	/* find out expired msgs */	ast_mutex_lock(&gw->msgs_lock);	prev = NULL, cur = gw->msgs;	while (cur) {		if (cur->retrans < MAX_RETRANS) {			cur->retrans++;			if (mgcpdebug) {				ast_verbose("Retransmitting #%d transaction %u on [%s]\n",					cur->retrans, cur->seqno, gw->name);			}			__mgcp_xmit(gw, cur->buf, cur->len);			prev = cur;			cur = cur->next;		} else {			if (prev)				prev->next = cur->next;			else				gw->msgs = cur->next;			ast_log(LOG_WARNING, "Maximum retries exceeded for transaction %u on [%s]\n",				cur->seqno, gw->name);			w = cur;			cur = cur->next;			if (exq) {				w->next = exq;			} else {				w->next = NULL;			}			exq = w;		}	}	if (!gw->msgs) {		gw->retransid = -1;		res = 0;	} else {		res = 1;	}	ast_mutex_unlock(&gw->msgs_lock);	while (exq) {		cur = exq;		/* time-out transaction */		handle_response(cur->owner_ep, cur->owner_sub, 406, cur->seqno, NULL); 		exq = exq->next;		free(cur);	}	return res;}/* modified for the new transaction mechanism */static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,                             char *data, int len, unsigned int seqno){	struct mgcp_message *msg = malloc(sizeof(struct mgcp_message) + len);	struct mgcp_message *cur;	struct mgcp_gateway *gw = ((p && p->parent) ? p->parent : NULL); 	struct timeval tv;	if (!msg) {		return -1;	}	if (!gw) {		return -1;	}/* SC	time(&t);	if (gw->messagepending && (gw->lastouttime + 20 < t)) {		ast_log(LOG_NOTICE, "Timeout waiting for response to message:%d,  lastouttime: %ld, now: %ld.  Dumping pending queue\n",			gw->msgs ? gw->msgs->seqno : -1, (long) gw->lastouttime, (long) t);		dump_queue(sub->parent);	}*/	msg->owner_sub = sub;	msg->owner_ep = p;	msg->seqno = seqno;	msg->next = NULL;	msg->len = len;	msg->retrans = 0;	memcpy(msg->buf, data, msg->len);	ast_mutex_lock(&gw->msgs_lock);	cur = gw->msgs;	if (cur) {		while(cur->next)			cur = cur->next;		cur->next = msg;	} else {		gw->msgs = msg;	}	if (gettimeofday(&tv, NULL) < 0) {		/* This shouldn't ever happen, but let's be sure */		ast_log(LOG_NOTICE, "gettimeofday() failed!\n");	} else {		msg->expire = tv.tv_sec * 1000 + tv.tv_usec / 1000 + DEFAULT_RETRANS;		if (gw->retransid == -1)			gw->retransid = ast_sched_add(sched, DEFAULT_RETRANS, retrans_pkt, (void *)gw);	}	ast_mutex_unlock(&gw->msgs_lock);/* SC	if (!gw->messagepending) {		gw->messagepending = 1;		gw->lastout = seqno;		gw->lastouttime = t;*/	__mgcp_xmit(gw, msg->buf, msg->len);		/* XXX Should schedule retransmission XXX *//* SC	} else		ast_log(LOG_DEBUG, "Deferring transmission of transaction %d\n", seqno);*/	return 0;}/* modified for new transport */static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,                         struct mgcp_request *req, unsigned int seqno){	int res = 0;	struct mgcp_request **queue, *q, *r, *t;	ast_mutex_t *l;	ast_log(LOG_DEBUG, "Slow sequence is %d\n", p->slowsequence);	if (p->slowsequence) {		queue = &p->cmd_queue;		l = &p->cmd_queue_lock;		ast_mutex_lock(l);	} else {		switch (req->cmd) {		case MGCP_CMD_DLCX:			queue = &sub->cx_queue;			l = &sub->cx_queue_lock;			ast_mutex_lock(l);			q = sub->cx_queue;			/* delete pending cx cmds */			while (q) {				r = q->next;				free(q);				q = r;			}			*queue = NULL;			break;		case MGCP_CMD_CRCX:		case MGCP_CMD_MDCX:			queue = &sub->cx_queue;			l = &sub->cx_queue_lock;			ast_mutex_lock(l);			break;		case MGCP_CMD_RQNT:			queue = &p->rqnt_queue;			l = &p->rqnt_queue_lock;			ast_mutex_lock(l);			break;		default:			queue = &p->cmd_queue;			l = &p->cmd_queue_lock;			ast_mutex_lock(l);			break;		}	}	r = (struct mgcp_request *) malloc (sizeof(struct mgcp_request));	if (!r) {		ast_log(LOG_WARNING, "Cannot post MGCP request: insufficient memory\n");		ast_mutex_unlock(l);		return -1;	}	memcpy(r, req, sizeof(struct mgcp_request));	if (!(*queue)) {		if (mgcpdebug) {			ast_verbose("Posting Request:\n%s to %s:%d\n", req->data, 				ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));		}		res = mgcp_postrequest(p, sub, req->data, req->len, seqno);	} else {		if (mgcpdebug) {			ast_verbose("Queueing Request:\n%s to %s:%d\n", req->data, 				ast_inet_ntoa(p->parent->addr.sin_addr), ntohs(p->parent->addr.sin_port));		}	}	/* XXX find tail. We could also keep tail in the data struct for faster access */	for (t = *queue; t && t->next; t = t->next);	r->next = NULL;	if (t)		t->next = r;	else		*queue = r;	ast_mutex_unlock(l);	return res;}static int mgcp_call(struct ast_channel *ast, char *dest, int timeout){	int res;	struct mgcp_endpoint *p;	struct mgcp_subchannel *sub;	char tone[50] = "";	const char *distinctive_ring = NULL;	struct varshead *headp;	struct ast_var_t *current;	if (mgcpdebug) {		ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_call(%s)\n", ast->name);	}	sub = ast->tech_pvt;	p = sub->parent;	headp = &ast->varshead;	AST_LIST_TRAVERSE(headp,current,entries) {		/* Check whether there is an ALERT_INFO variable */		if (strcasecmp(ast_var_name(current),"ALERT_INFO") == 0) {			distinctive_ring = ast_var_value(current);		}	}	ast_mutex_lock(&sub->lock);	switch (p->hookstate) {	case MGCP_OFFHOOK:		if (!ast_strlen_zero(distinctive_ring)) {			snprintf(tone, sizeof(tone), "L/wt%s", distinctive_ring);			if (mgcpdebug) {				ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive callwait %s\n", tone);			}		} else {			snprintf(tone, sizeof(tone), "L/wt");			if (mgcpdebug) {				ast_verbose(VERBOSE_PREFIX_3 "MGCP normal callwait %s\n", tone);			}		}		break;	case MGCP_ONHOOK:	default:		if (!ast_strlen_zero(distinctive_ring)) {			snprintf(tone, sizeof(tone), "L/r%s", distinctive_ring);			if (mgcpdebug) {				ast_verbose(VERBOSE_PREFIX_3 "MGCP distinctive ring %s\n", tone);			}		} else {			snprintf(tone, sizeof(tone), "L/rg");			if (mgcpdebug) {				ast_verbose(VERBOSE_PREFIX_3 "MGCP default ring\n");			}		}		break;	}	if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {		ast_log(LOG_WARNING, "mgcp_call called on %s, neither down nor reserved\n", ast->name);		ast_mutex_unlock(&sub->lock);		return -1;	}	res = 0;	sub->outgoing = 1;	sub->cxmode = MGCP_CX_RECVONLY;	if (p->type == TYPE_LINE) {		if (!sub->rtp) {			start_rtp(sub);		} else {			transmit_modify_request(sub);		}		if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {			/* try to prevent a callwait from disturbing the other connection */			sub->next->cxmode = MGCP_CX_RECVONLY;			transmit_modify_request(sub->next);		}		transmit_notify_request_with_callerid(sub, tone, ast->cid.cid_num, ast->cid.cid_name);		ast_setstate(ast, AST_STATE_RINGING);		if (sub->next->owner && !ast_strlen_zero(sub->next->cxident) && !ast_strlen_zero(sub->next->callid)) {			/* Put the connection back in sendrecv */			sub->next->cxmode = MGCP_CX_SENDRECV;			transmit_modify_request(sub->next);		}	} else {		ast_log(LOG_NOTICE, "Don't know how to dial on trunks yet\n");		res = -1;	}	ast_mutex_unlock(&sub->lock);	ast_queue_control(ast, AST_CONTROL_RINGING);	return res;}static int mgcp_hangup(struct ast_channel *ast){	struct mgcp_subchannel *sub = ast->tech_pvt;	struct mgcp_endpoint *p = sub->parent;	if (option_debug) {		ast_log(LOG_DEBUG, "mgcp_hangup(%s)\n", ast->name);	}	if (!ast->tech_pvt) {		ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");		return 0;	}	if (strcmp(sub->magic, MGCP_SUBCHANNEL_MAGIC)) {		ast_log(LOG_DEBUG, "Invalid magic. MGCP subchannel freed up already.\n");		return 0;	}	ast_mutex_lock(&sub->lock);	if (mgcpdebug) {		ast_verbose(VERBOSE_PREFIX_3 "MGCP mgcp_hangup(%s) on %s@%s\n", ast->name, p->name, p->parent->name);	}	if ((p->dtmfmode & MGCP_DTMF_INBAND) && p->dsp) {		/* check whether other channel is active. */		if (!sub->next->owner) {			if (p->dtmfmode & MGCP_DTMF_HYBRID)				p->dtmfmode &= ~MGCP_DTMF_INBAND;			if (mgcpdebug) {				ast_verbose(VERBOSE_PREFIX_2 "MGCP free dsp on %s@%s\n", p->name, p->parent->name);			}			ast_dsp_free(p->dsp);			p->dsp = NULL;		}	}	sub->owner = NULL;	if (!ast_strlen_zero(sub->cxident)) {		transmit_connection_del(sub);	}	sub->cxident[0] = '\0';	if ((sub == p->sub) && sub->next->owner) {

⌨️ 快捷键说明

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