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

📄 chan_h323.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 5 页
字号:
	pvt = find_call_locked(call_reference, token);	if (!pvt) {		ast_log(LOG_ERROR, "Received digit '%c' (%u ms) for call %s without private structure\n", digit, duration, token);		return -1;	}	if (h323debug)		ast_log(LOG_DTMF, "Received %s digit '%c' (%u ms) for call %s\n", (digit == ' ' ? "update for" : "new"), (digit == ' ' ? pvt->curDTMF : digit), duration, token);	if (pvt->owner && !ast_channel_trylock(pvt->owner)) {		if (digit == '!')			res = ast_queue_control(pvt->owner, AST_CONTROL_FLASH);		else {			struct ast_frame f = {				.frametype = AST_FRAME_DTMF_END,				.subclass = digit,				.samples = duration * 8,				.len = duration,				.src = "SEND_DIGIT",			};			if (digit == ' ') {		/* signalUpdate message */				f.subclass = pvt->curDTMF;				AST_SCHED_DEL(sched, pvt->DTMFsched);			} else {				/* Regular input or signal message */				if (pvt->DTMFsched >= 0) {					/* We still don't send DTMF END from previous event, send it now */					AST_SCHED_DEL(sched, pvt->DTMFsched);					f.subclass = pvt->curDTMF;					f.samples = f.len = 0;					ast_queue_frame(pvt->owner, &f);					/* Restore values */					f.subclass = digit;					f.samples = duration * 8;					f.len = duration;				}				if (duration) {		/* This is a signal, signalUpdate follows */					f.frametype = AST_FRAME_DTMF_BEGIN;					pvt->DTMFsched = ast_sched_add(sched, duration, oh323_simulate_dtmf_end, pvt);					if (h323debug)						ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", duration, pvt->DTMFsched);				}				pvt->curDTMF = digit;			}			res = ast_queue_frame(pvt->owner, &f);		}		ast_channel_unlock(pvt->owner);	} else {		if (digit == '!')			pvt->newcontrol = AST_CONTROL_FLASH;		else {			pvt->newduration = duration;			pvt->newdigit = digit;		}		res = 0;	}	ast_mutex_unlock(&pvt->lock);	return res;}/**  * Callback function used to inform the H.323 stack of the local rtp ip/port details  *  * Returns the local RTP information  */static struct rtp_info *external_rtp_create(unsigned call_reference, const char * token){	struct oh323_pvt *pvt;	struct sockaddr_in us;	struct rtp_info *info;	info = (struct rtp_info *)malloc(sizeof(struct rtp_info));	if (!info) {		ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");		return NULL;	}	pvt = find_call_locked(call_reference, token);	if (!pvt) {		free(info);		ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);		return NULL;	}	if (!pvt->rtp)		__oh323_rtp_create(pvt);	if (!pvt->rtp) {		ast_mutex_unlock(&pvt->lock);		free(info);		ast_log(LOG_ERROR, "No RTP stream is available for call %s (%d)", token, call_reference);		return NULL;	}	/* figure out our local RTP port and tell the H.323 stack about it */	ast_rtp_get_us(pvt->rtp, &us);	ast_mutex_unlock(&pvt->lock);	ast_copy_string(info->addr, ast_inet_ntoa(us.sin_addr), sizeof(info->addr));	info->port = ntohs(us.sin_port);	if (h323debug)		ast_log(LOG_DEBUG, "Sending RTP 'US' %s:%d\n", info->addr, info->port);	return info;}/** * Definition taken from rtp.c for rtpPayloadType because we need it here. */struct rtpPayloadType {	int isAstFormat;	/* whether the following code is an AST_FORMAT */	int code;};/**  * Call-back function passing remote ip/port information from H.323 to asterisk  *  * Returns nothing  */static void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt){	struct oh323_pvt *pvt;	struct sockaddr_in them;	struct rtpPayloadType rtptype;	int nativeformats_changed;	enum { NEED_NONE, NEED_HOLD, NEED_UNHOLD } rtp_change = NEED_NONE;	if (h323debug)		ast_log(LOG_DEBUG, "Setting up RTP connection for %s\n", token);	/* Find the call or allocate a private structure if call not found */	pvt = find_call_locked(call_reference, token);	if (!pvt) {		ast_log(LOG_ERROR, "Something is wrong: rtp\n");		return;	}	if (pvt->alreadygone) {		ast_mutex_unlock(&pvt->lock);		return;	}	if (!pvt->rtp)		__oh323_rtp_create(pvt);	them.sin_family = AF_INET;	/* only works for IPv4 */	them.sin_addr.s_addr = inet_addr(remoteIp);	them.sin_port = htons(remotePort);	if (them.sin_addr.s_addr) {		ast_rtp_set_peer(pvt->rtp, &them);		if (pvt->recvonly) {			pvt->recvonly = 0;			rtp_change = NEED_UNHOLD;		}	} else {		ast_rtp_stop(pvt->rtp);		if (!pvt->recvonly) {			pvt->recvonly = 1;			rtp_change = NEED_HOLD;		}	}	/* Change native format to reflect information taken from OLC/OLCAck */	nativeformats_changed = 0;	if (pt != 128 && pvt->rtp) {	/* Payload type is invalid, so try to use previously decided */		rtptype = ast_rtp_lookup_pt(pvt->rtp, pt);		if (h323debug)			ast_log(LOG_DEBUG, "Native format is set to %d from %d by RTP payload type %d\n", rtptype.code, pvt->nativeformats, pt);		if (pvt->nativeformats != rtptype.code) {			pvt->nativeformats = rtptype.code;			nativeformats_changed = 1;		}	} else if (h323debug)		ast_log(LOG_NOTICE, "Payload type is unknown, formats isn't changed\n");	/* Don't try to lock the channel if nothing changed */	if (nativeformats_changed || pvt->options.progress_audio || (rtp_change != NEED_NONE)) {		if (pvt->owner && !ast_channel_trylock(pvt->owner)) {			/* Re-build translation path only if native format(s) has been changed */			if (pvt->owner->nativeformats != pvt->nativeformats) {				if (h323debug)					ast_log(LOG_DEBUG, "Native format changed to %d from %d, read format is %d, write format is %d\n", pvt->nativeformats, pvt->owner->nativeformats, pvt->owner->readformat, pvt->owner->writeformat);				pvt->owner->nativeformats = pvt->nativeformats;				ast_set_read_format(pvt->owner, pvt->owner->readformat);				ast_set_write_format(pvt->owner, pvt->owner->writeformat);			}			if (pvt->options.progress_audio)				ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);			switch (rtp_change) {			case NEED_HOLD:				ast_queue_control(pvt->owner, AST_CONTROL_HOLD);				break;			case NEED_UNHOLD:				ast_queue_control(pvt->owner, AST_CONTROL_UNHOLD);				break;			default:				break;			}			ast_channel_unlock(pvt->owner);		}		else {			if (pvt->options.progress_audio)				pvt->newcontrol = AST_CONTROL_PROGRESS;			else if (rtp_change == NEED_HOLD)				pvt->newcontrol = AST_CONTROL_HOLD;			else if (rtp_change == NEED_UNHOLD)				pvt->newcontrol = AST_CONTROL_UNHOLD;			if (h323debug)				ast_log(LOG_DEBUG, "RTP connection preparation for %s is pending...\n", token);		}	}	ast_mutex_unlock(&pvt->lock);	if (h323debug)		ast_log(LOG_DEBUG, "RTP connection prepared for %s\n", token);	return;}/**  *	Call-back function to signal asterisk that the channel has been answered  * Returns nothing  */static void connection_made(unsigned call_reference, const char *token){	struct oh323_pvt *pvt;	if (h323debug)		ast_log(LOG_DEBUG, "Call %s answered\n", token);	pvt = find_call_locked(call_reference, token);	if (!pvt) {		ast_log(LOG_ERROR, "Something is wrong: connection\n");		return;	}	/* Inform asterisk about remote party connected only on outgoing calls */	if (!pvt->outgoing) {		ast_mutex_unlock(&pvt->lock);		return;	}	/* Do not send ANSWER message more than once */	if (!pvt->connection_established) {		pvt->connection_established = 1;		update_state(pvt, -1, AST_CONTROL_ANSWER);	}	ast_mutex_unlock(&pvt->lock);	return;}static int progress(unsigned call_reference, const char *token, int inband){	struct oh323_pvt *pvt;	if (h323debug)		ast_log(LOG_DEBUG, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));	pvt = find_call_locked(call_reference, token);	if (!pvt) {		ast_log(LOG_ERROR, "Private structure not found in progress.\n");		return -1;	}	if (!pvt->owner) {		ast_mutex_unlock(&pvt->lock);		ast_log(LOG_ERROR, "No Asterisk channel associated with private structure.\n");		return -1;	}	update_state(pvt, -1, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING));	ast_mutex_unlock(&pvt->lock);	return 0;}/** *  Call-back function for incoming calls * *  Returns 1 on success */static call_options_t *setup_incoming_call(call_details_t *cd){	struct oh323_pvt *pvt;	struct oh323_user *user = NULL;	struct oh323_alias *alias = NULL;	if (h323debug)		ast_log(LOG_DEBUG, "Setting up incoming call for %s\n", cd->call_token);	/* allocate the call*/	pvt = oh323_alloc(cd->call_reference);	if (!pvt) {		ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");		cleanup_call_details(cd);		return NULL;	}	/* Populate the call details in the private structure */	memcpy(&pvt->cd, cd, sizeof(pvt->cd));	memcpy(&pvt->options, &global_options, sizeof(pvt->options));	pvt->jointcapability = pvt->options.capability;	if (h323debug) {		ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n");		ast_verbose(VERBOSE_PREFIX_3 " \tCall token:  [%s]\n", pvt->cd.call_token);		ast_verbose(VERBOSE_PREFIX_3 " \tCalling party name:  [%s]\n", pvt->cd.call_source_name);		ast_verbose(VERBOSE_PREFIX_3 " \tCalling party number:  [%s]\n", pvt->cd.call_source_e164);		ast_verbose(VERBOSE_PREFIX_3 " \tCalled party name:  [%s]\n", pvt->cd.call_dest_alias);		ast_verbose(VERBOSE_PREFIX_3 " \tCalled party number:  [%s]\n", pvt->cd.call_dest_e164);		if (pvt->cd.redirect_reason >= 0)			ast_verbose(VERBOSE_PREFIX_3 " \tRedirecting party number:  [%s] (reason %d)\n", pvt->cd.redirect_number, pvt->cd.redirect_reason);		ast_verbose(VERBOSE_PREFIX_3 " \tCalling party IP:  [%s]\n", pvt->cd.sourceIp);	}	/* Decide if we are allowing Gatekeeper routed calls*/	if ((!strcasecmp(cd->sourceIp, gatekeeper)) && (gkroute == -1) && !gatekeeper_disable) {		if (!ast_strlen_zero(cd->call_dest_e164)) {			ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));			ast_copy_string(pvt->context, default_context, sizeof(pvt->context));		} else {			alias = find_alias(cd->call_dest_alias, 1);			if (!alias) {				ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd->call_dest_alias);				oh323_destroy(pvt);				return NULL;			}			ast_copy_string(pvt->exten, alias->name, sizeof(pvt->exten));			ast_copy_string(pvt->context, alias->context, sizeof(pvt->context));		}	} else {		/* Either this call is not from the Gatekeeper		   or we are not allowing gk routed calls */		user = find_user(cd, 1);		if (!user) {			if (!acceptAnonymous) {				ast_log(LOG_NOTICE, "Anonymous call from '%s@%s' rejected\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);				oh323_destroy(pvt);				return NULL;			}			if (ast_strlen_zero(default_context)) {				ast_log(LOG_ERROR, "Call from '%s@%s' rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);				oh323_destroy(pvt);				return NULL;			}			ast_copy_string(pvt->context, default_context, sizeof(pvt->context));			if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {				ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));			} else {				ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));			}			if (h323debug)				ast_log(LOG_DEBUG, "Sending %s@%s to context [%s] extension %s\n", cd->call_source_aliases, cd->sourceIp, pvt->context, pvt->exten);		} else {			if (user->host) {				if (strcasecmp(cd->sourceIp, ast_inet_ntoa(user->addr.sin_addr))) {					if (ast_strlen_zero(user->context)) {						if (ast_strlen_zero(default_context)) {							ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s) and no default context\n", user->name, cd->sourceIp);							oh323_destroy(pvt);							ASTOBJ_UNREF(user, oh323_destroy_user);							return NULL;						}						ast_copy_string(pvt->context, default_context, sizeof(pvt->context));					} else {						ast_copy_string(pvt->context, user->context, sizeof(pvt->context));					}					pvt->exten[0] = 'i';					pvt->exten[1] = '\0';					ast_log(LOG_ERROR, "Call from '%s' rejected due to non-matching IP address (%s)s\n", user->name, cd->sourceIp);					oh323_destroy(pvt);					ASTOBJ_UNREF(user, oh323_destroy_user);					return NULL;	/* XXX: Hmmm... Why to setup context if we drop connection immediately??? */				}			}			ast_copy_string(pvt->context, user->context, sizeof(pvt->context));			memcpy(&pvt->options, &user->options, sizeof(pvt->options));			pvt->jointcapability = pvt->options.capability;			if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {				ast_copy_string(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten));			} else {				ast_copy_string(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten));			}			if (!ast_strlen_zero(user->accountcode)) {				ast_copy_string(pvt->accountcode, user->accountcode, sizeof(pvt->accountcode));			}			if (user->amaflags) {				pvt->amaflags = user->amaflags;			}			ASTOBJ_UNREF(user, oh323_destroy_user);		}	}	return &pvt->options;}/** * Call-back function to start PBX when OpenH323 ready to serve incoming call * * Returns 1 on success */static int answer_call(unsigned call_reference, const char *token){	struct oh323_pvt *pvt;	struct ast_channel *c = NULL;	enum {ext_original, ext_s, ext_i, ext_notexists} try_exten;	char tmp_exten[sizeof(pvt->exten)];	if (h323debug)		ast_log(LOG_DEBUG, "Preparing Asterisk to answer for %s\n", token);	/* Find the call or allocate a private structure if call not found */	pvt = find_call_locked(call_reference, token);	if (!pvt) {		ast_log(LOG_ERROR, "Something is wrong: answer_call\n");		return 0;	}	/* Check if requested extension@context pair exists in the dialplan */	ast_copy_string(tmp_exten, pvt->exten, sizeof(tmp_exten));	/* Try to find best extension in specified context */	if ((tmp_exten[0] != '\0') && (tmp_exten[1] == '\0')) {		if (tmp_exten[0] == 's')			try_exten = ext_s;		else if (tmp_exten[0] == 'i')			try_exten = ext_i;		else			try_exten = ext_original;	} else		try_exten = ext_original;	do {		if (ast_exists_extension(NULL, pvt->context, tmp_exten, 1, NULL))			break;		switch (try_exten) {		case ext_original:			tmp_exten[0] = 's';			tmp_exten[1] = '\0';			try_exten = ext_s;			break;		case ext_s:			tmp_exten[0] = 'i';			try_exten = ext_i;			break;		case ext_i:			try_exten = ext_notexists;			break;		default:			break;		}	} while (try

⌨️ 快捷键说明

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