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

📄 chan_h323.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 5 页
字号:
		cd->redirect_number = NULL;	}}static void __oh323_destroy(struct oh323_pvt *pvt){	struct oh323_pvt *cur, *prev = NULL;	AST_SCHED_DEL(sched, pvt->DTMFsched);	if (pvt->rtp) {		ast_rtp_destroy(pvt->rtp);	}	/* Free dsp used for in-band DTMF detection */	if (pvt->vad) {		ast_dsp_free(pvt->vad);	}	cleanup_call_details(&pvt->cd);	/* Unlink us from the owner if we have one */	if (pvt->owner) {		ast_channel_lock(pvt->owner);		if (h323debug)			ast_log(LOG_DEBUG, "Detaching from %s\n", pvt->owner->name);		pvt->owner->tech_pvt = NULL;		ast_channel_unlock(pvt->owner);	}	cur = iflist;	while(cur) {		if (cur == pvt) {			if (prev)				prev->next = cur->next;			else				iflist = cur->next;			break;		}		prev = cur;		cur = cur->next;	}	if (!cur) {		ast_log(LOG_WARNING, "%p is not in list?!?! \n", cur);	} else {		ast_mutex_unlock(&pvt->lock);		ast_mutex_destroy(&pvt->lock);		free(pvt);	}}static void oh323_destroy(struct oh323_pvt *pvt){	if (h323debug) {		ast_log(LOG_DEBUG, "Destroying channel %s\n", (pvt->owner ? pvt->owner->name : "<unknown>"));	}	ast_mutex_lock(&iflock);	ast_mutex_lock(&pvt->lock);	__oh323_destroy(pvt);	ast_mutex_unlock(&iflock);}static int oh323_digit_begin(struct ast_channel *c, char digit){	struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;	char *token;	if (!pvt) {		ast_log(LOG_ERROR, "No private structure?! This is bad\n");		return -1;	}	ast_mutex_lock(&pvt->lock);	if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && (pvt->dtmf_pt > 0)) {		/* out-of-band DTMF */		if (h323debug) {			ast_log(LOG_DTMF, "Begin sending out-of-band digit %c on %s\n", digit, c->name);		}		ast_rtp_senddigit_begin(pvt->rtp, digit);		ast_mutex_unlock(&pvt->lock);	} else if (pvt->txDtmfDigit != digit) {		/* in-band DTMF */		if (h323debug) {			ast_log(LOG_DTMF, "Begin sending inband digit %c on %s\n", digit, c->name);		}		pvt->txDtmfDigit = digit;		token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;		ast_mutex_unlock(&pvt->lock);		h323_send_tone(token, digit);		if (token) {			free(token);		}	} else		ast_mutex_unlock(&pvt->lock);	oh323_update_info(c);	return 0;}/** * Send (play) the specified digit to the channel. * */static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration){	struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;	char *token;	if (!pvt) {		ast_log(LOG_ERROR, "No private structure?! This is bad\n");		return -1;	}	ast_mutex_lock(&pvt->lock);	if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && (pvt->dtmf_pt > 0)) {		/* out-of-band DTMF */		if (h323debug) {			ast_log(LOG_DTMF, "End sending out-of-band digit %c on %s, duration %d\n", digit, c->name, duration);		}		ast_rtp_senddigit_end(pvt->rtp, digit);		ast_mutex_unlock(&pvt->lock);	} else {		/* in-band DTMF */		if (h323debug) {			ast_log(LOG_DTMF, "End sending inband digit %c on %s, duration %d\n", digit, c->name, duration);		}		pvt->txDtmfDigit = ' ';		token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;		ast_mutex_unlock(&pvt->lock);		h323_send_tone(token, ' ');		if (token) {			free(token);		}	}	oh323_update_info(c);	return 0;}/** * Make a call over the specified channel to the specified * destination. * Returns -1 on error, 0 on success. */static int oh323_call(struct ast_channel *c, char *dest, int timeout){	int res = 0;	struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;	const char *addr;	char called_addr[1024];	if (h323debug) {		ast_log(LOG_DEBUG, "Calling to %s on %s\n", dest, c->name);	}	if ((c->_state != AST_STATE_DOWN) && (c->_state != AST_STATE_RESERVED)) {		ast_log(LOG_WARNING, "Line is already in use (%s)\n", c->name);		return -1;	}	ast_mutex_lock(&pvt->lock);	if (!gatekeeper_disable) {		if (ast_strlen_zero(pvt->exten)) {			ast_copy_string(called_addr, dest, sizeof(called_addr));		} else {			snprintf(called_addr, sizeof(called_addr), "%s@%s", pvt->exten, dest);		}	} else {		res = htons(pvt->sa.sin_port);		addr = ast_inet_ntoa(pvt->sa.sin_addr);		if (ast_strlen_zero(pvt->exten)) {			snprintf(called_addr, sizeof(called_addr), "%s:%d", addr, res);		} else {			snprintf(called_addr, sizeof(called_addr), "%s@%s:%d", pvt->exten, addr, res);		}	}	/* make sure null terminated */	called_addr[sizeof(called_addr) - 1] = '\0';	if (c->cid.cid_num)		ast_copy_string(pvt->options.cid_num, c->cid.cid_num, sizeof(pvt->options.cid_num));	if (c->cid.cid_name)		ast_copy_string(pvt->options.cid_name, c->cid.cid_name, sizeof(pvt->options.cid_name));	if (c->cid.cid_rdnis) {		ast_copy_string(pvt->options.cid_rdnis, c->cid.cid_rdnis, sizeof(pvt->options.cid_rdnis));	}	pvt->options.presentation = c->cid.cid_pres;	pvt->options.type_of_number = c->cid.cid_ton;	if ((addr = pbx_builtin_getvar_helper(c, "PRIREDIRECTREASON"))) {		if (!strcasecmp(addr, "UNKNOWN"))			pvt->options.redirect_reason = 0;		else if (!strcasecmp(addr, "BUSY"))			pvt->options.redirect_reason = 1;		else if (!strcasecmp(addr, "NO_REPLY"))			pvt->options.redirect_reason = 2;		else if (!strcasecmp(addr, "UNCONDITIONAL"))			pvt->options.redirect_reason = 15;		else			pvt->options.redirect_reason = -1;	} else		pvt->options.redirect_reason = -1;	pvt->options.transfer_capability = c->transfercapability;	/* indicate that this is an outgoing call */	pvt->outgoing = 1;	if (option_verbose > 2)		ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", c->transfercapability, ast_transfercapability2str(c->transfercapability));	if (h323debug)		ast_log(LOG_DEBUG, "Placing outgoing call to %s, %d\n", called_addr, pvt->options.dtmfcodec);	ast_mutex_unlock(&pvt->lock);	res = h323_make_call(called_addr, &(pvt->cd), &pvt->options);	if (res) {		ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name);		return -1;	}	oh323_update_info(c);	return 0;}static int oh323_answer(struct ast_channel *c){	int res;	struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;	char *token;	if (h323debug)		ast_log(LOG_DEBUG, "Answering on %s\n", c->name);	ast_mutex_lock(&pvt->lock);	token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;	ast_mutex_unlock(&pvt->lock);	res = h323_answering_call(token, 0);	if (token)		free(token);	oh323_update_info(c);	if (c->_state != AST_STATE_UP) {		ast_setstate(c, AST_STATE_UP);	}	return res;}static int oh323_hangup(struct ast_channel *c){	struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;	int q931cause = AST_CAUSE_NORMAL_CLEARING;	char *call_token;	if (h323debug)		ast_log(LOG_DEBUG, "Hanging up and scheduling destroy of call %s\n", c->name);	if (!c->tech_pvt) {		ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");		return 0;	}	ast_mutex_lock(&pvt->lock);	/* Determine how to disconnect */	if (pvt->owner != c) {		ast_log(LOG_WARNING, "Huh?  We aren't the owner?\n");		ast_mutex_unlock(&pvt->lock);		return 0;	}	pvt->owner = NULL;	c->tech_pvt = NULL;	if (c->hangupcause) {		q931cause = c->hangupcause;	} else {		const char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS");		if (cause) {			if (!strcmp(cause, "CONGESTION")) {				q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;			} else if (!strcmp(cause, "BUSY")) {				q931cause = AST_CAUSE_USER_BUSY;			} else if (!strcmp(cause, "CHANISUNVAIL")) {				q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;			} else if (!strcmp(cause, "NOANSWER")) {				q931cause = AST_CAUSE_NO_ANSWER;			} else if (!strcmp(cause, "CANCEL")) {				q931cause = AST_CAUSE_CALL_REJECTED;			}		}	}	/* Start the process if it's not already started */	if (!pvt->alreadygone && !pvt->hangupcause) {		call_token = pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL;		if (call_token) {			/* Release lock to eliminate deadlock */			ast_mutex_unlock(&pvt->lock);			if (h323_clear_call(call_token, q931cause)) {				ast_log(LOG_WARNING, "ClearCall failed.\n");			}			free(call_token);			ast_mutex_lock(&pvt->lock);		}	}	pvt->needdestroy = 1;	ast_mutex_unlock(&pvt->lock);	/* Update usage counter */	ast_module_unref(ast_module_info->self);	return 0;}static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt){	/* Retrieve audio/etc from channel. Assumes pvt->lock is already held. */	struct ast_frame *f;	/* Only apply it for the first packet, we just need the correct ip/port */	if (pvt->options.nat) {		ast_rtp_setnat(pvt->rtp, pvt->options.nat);		pvt->options.nat = 0;	}	f = ast_rtp_read(pvt->rtp);	/* Don't send RFC2833 if we're not supposed to */	if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & H323_DTMF_RFC2833)) {		return &ast_null_frame;	}	if (pvt->owner) {		/* We already hold the channel lock */		if (f->frametype == AST_FRAME_VOICE) {			if (f->subclass != pvt->owner->nativeformats) {				/* Try to avoid deadlock */				if (ast_channel_trylock(pvt->owner)) {					ast_log(LOG_NOTICE, "Format changed but channel is locked. Ignoring frame...\n");					return &ast_null_frame;				}				if (h323debug)					ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);				pvt->owner->nativeformats = f->subclass;				pvt->nativeformats = f->subclass;				ast_set_read_format(pvt->owner, pvt->owner->readformat);				ast_set_write_format(pvt->owner, pvt->owner->writeformat);				ast_channel_unlock(pvt->owner);			}			/* Do in-band DTMF detection */			if ((pvt->options.dtmfmode & H323_DTMF_INBAND) && pvt->vad) {				if ((pvt->nativeformats & (AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW))) {					if (!ast_channel_trylock(pvt->owner)) {						f = ast_dsp_process(pvt->owner, pvt->vad, f);						ast_channel_unlock(pvt->owner);					}					else						ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n");				} else if (pvt->nativeformats && !pvt->noInbandDtmf) {					ast_log(LOG_NOTICE, "Inband DTMF is not supported on codec %s. Use RFC2833\n", ast_getformatname(f->subclass));					pvt->noInbandDtmf = 1;				}				if (f &&(f->frametype == AST_FRAME_DTMF)) {					if (h323debug)						ast_log(LOG_DTMF, "Received in-band digit %c.\n", f->subclass);				}			}		}	}	return f;}static struct ast_frame *oh323_read(struct ast_channel *c){	struct ast_frame *fr;	struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;	ast_mutex_lock(&pvt->lock);	__oh323_update_info(c, pvt);	switch(c->fdno) {	case 0:		fr = oh323_rtp_read(pvt);		break;	case 1:		if (pvt->rtp)			fr = ast_rtcp_read(pvt->rtp);		else			fr = &ast_null_frame;		break;	default:		ast_log(LOG_ERROR, "Unable to handle fd %d on channel %s\n", c->fdno, c->name);		fr = &ast_null_frame;		break;	}	ast_mutex_unlock(&pvt->lock);	return fr;}static int oh323_write(struct ast_channel *c, struct ast_frame *frame){	struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;	int res = 0;	if (frame->frametype != AST_FRAME_VOICE) {		if (frame->frametype == AST_FRAME_IMAGE) {			return 0;		} else {			ast_log(LOG_WARNING, "Can't send %d type frames with H323 write\n", frame->frametype);			return 0;		}	} else {		if (!(frame->subclass & c->nativeformats)) {			ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",				frame->subclass, c->nativeformats, c->readformat, c->writeformat);			return 0;		}	}	if (pvt) {		ast_mutex_lock(&pvt->lock);		if (pvt->rtp && !pvt->recvonly)			res = ast_rtp_write(pvt->rtp, frame);		__oh323_update_info(c, pvt);		ast_mutex_unlock(&pvt->lock);	}	return res;}static int oh323_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen){	struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;	char *token = (char *)NULL;	int res = -1;	int got_progress;	ast_mutex_lock(&pvt->lock);	token = (pvt->cd.call_token ? strdup(pvt->cd.call_token) : NULL);	got_progress = pvt->got_progress;	if (condition == AST_CONTROL_PROGRESS)		pvt->got_progress = 1;	else if ((condition == AST_CONTROL_BUSY) || (condition == AST_CONTROL_CONGESTION))		pvt->alreadygone = 1;	ast_mutex_unlock(&pvt->lock);	if (h323debug)		ast_log(LOG_DEBUG, "OH323: Indicating %d on %s\n", condition, token);	switch(condition) {	case AST_CONTROL_RINGING:		if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) {			h323_send_alerting(token);			res = (got_progress ? 0 : -1);	/* Do not simulate any audio tones if we got PROGRESS message */		}		break;	case AST_CONTROL_PROGRESS:		if (c->_state != AST_STATE_UP) {			/* Do not send PROGRESS message more than once */

⌨️ 快捷键说明

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