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

📄 chan_h323.c

📁 Asterisk中信道部分的源码 。。。。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2005 * * OpenH323 Channel Driver for ASTERISK PBX. *			By Jeremy McNamara *                      For The NuFone Network * * chan_h323 has been derived from code created by *               Michael Manousos and Mark Spencer * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. *//*! \file * * \brief This file is part of the chan_h323 driver for Asterisk * * \author Jeremy McNamara * * \par See also * \arg Config_h323 * * \ingroup channel_drivers *//*** MODULEINFO	<depend>openh323</depend>	<defaultenabled>yes</defaultenabled> ***/#ifdef __cplusplusextern "C" {#endif#include "asterisk.h"ASTERISK_FILE_VERSION(__FILE__, "$Revision: 123113 $")#ifdef __cplusplus}#endif#include <sys/types.h>#include <sys/socket.h>#include <sys/signal.h>#include <sys/param.h>#if defined(BSD) || defined(SOLARIS)#ifndef IPTOS_MINCOST#define IPTOS_MINCOST 0x02#endif#endif#include <arpa/inet.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <unistd.h>#include <stdlib.h>#include <netdb.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <fcntl.h>#ifdef __cplusplusextern "C" {#endif#include "asterisk/lock.h"#include "asterisk/logger.h"#include "asterisk/channel.h"#include "asterisk/config.h"#include "asterisk/module.h"#include "asterisk/musiconhold.h"#include "asterisk/pbx.h"#include "asterisk/options.h"#include "asterisk/utils.h"#include "asterisk/lock.h"#include "asterisk/sched.h"#include "asterisk/io.h"#include "asterisk/rtp.h"#include "asterisk/acl.h"#include "asterisk/callerid.h"#include "asterisk/cli.h"#include "asterisk/dsp.h"#include "asterisk/causes.h"#include "asterisk/stringfields.h"#include "asterisk/abstract_jb.h"#include "asterisk/astobj.h"#ifdef __cplusplus}#endif#include "h323/chan_h323.h"receive_digit_cb on_receive_digit;on_rtp_cb on_external_rtp_create;start_rtp_cb on_start_rtp_channel;setup_incoming_cb on_incoming_call;setup_outbound_cb on_outgoing_call;chan_ringing_cb	on_chan_ringing;con_established_cb on_connection_established;clear_con_cb on_connection_cleared;answer_call_cb on_answer_call;progress_cb on_progress;rfc2833_cb on_set_rfc2833_payload;hangup_cb on_hangup;setcapabilities_cb on_setcapabilities;setpeercapabilities_cb on_setpeercapabilities;/* global debug flag */int h323debug;/*! Global jitterbuffer configuration - by default, jb is disabled */static struct ast_jb_conf default_jbconf ={	.flags = 0,	.max_size = -1,	.resync_threshold = -1,	.impl = ""};static struct ast_jb_conf global_jbconf;/** Variables required by Asterisk */static const char tdesc[] = "The NuFone Network's Open H.323 Channel Driver";static const char config[] = "h323.conf";static char default_context[AST_MAX_CONTEXT] = "default";static struct sockaddr_in bindaddr;#define GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_H261)/** H.323 configuration values */static int h323_signalling_port = 1720;static char gatekeeper[100];static int gatekeeper_disable = 1;static int gatekeeper_discover = 0;static int gkroute = 0;/* Find user by alias (h.323 id) is default, alternative is the incomming call's source IP address*/static int userbyalias = 1;static int acceptAnonymous = 1;static int tos = 0;static char secret[50];static unsigned int unique = 0;static call_options_t global_options;/** Private structure of a OpenH323 channel */struct oh323_pvt {	ast_mutex_t lock;					/* Channel private lock */	call_options_t options;				/* Options to be used during call setup */	int alreadygone;					/* Whether or not we've already been destroyed by our peer */	int needdestroy;					/* if we need to be destroyed */	call_details_t cd;					/* Call details */	struct ast_channel *owner;			/* Who owns us */	struct sockaddr_in sa;				/* Our peer */	struct sockaddr_in redirip;			/* Where our RTP should be going if not to us */	int nonCodecCapability;				/* non-audio capability */	int outgoing;						/* Outgoing or incoming call? */	char exten[AST_MAX_EXTENSION];		/* Requested extension */	char context[AST_MAX_CONTEXT];		/* Context where to start */	char accountcode[256];				/* Account code */	char rdnis[80];						/* Referring DNIS, if available */	int amaflags;						/* AMA Flags */	struct ast_rtp *rtp;				/* RTP Session */	struct ast_dsp *vad;				/* Used for in-band DTMF detection */	int nativeformats;					/* Codec formats supported by a channel */	int needhangup;						/* Send hangup when Asterisk is ready */	int hangupcause;					/* Hangup cause from OpenH323 layer */	int newstate;						/* Pending state change */	int newcontrol;						/* Pending control to send */	int newdigit;						/* Pending DTMF digit to send */	int newduration;					/* Pending DTMF digit duration to send */	int pref_codec;						/* Preferred codec */	int peercapability;					/* Capabilities learned from peer */	int jointcapability;				/* Common capabilities for local and remote side */	struct ast_codec_pref peer_prefs;	/* Preferenced list of codecs which remote side supports */	int dtmf_pt;						/* Payload code used for RFC2833 messages */	int curDTMF;						/* DTMF tone being generated to Asterisk side */	int DTMFsched;						/* Scheduler descriptor for DTMF */	int update_rtp_info;				/* Configuration of fd's array is pending */	int recvonly;						/* Peer isn't wish to receive our voice stream */	int txDtmfDigit;					/* DTMF digit being to send to H.323 side */	int noInbandDtmf;					/* Inband DTMF processing by DSP isn't available */	int connection_established;			/* Call got CONNECT message */	int got_progress;					/* Call got PROGRESS message, pass inband audio */	struct oh323_pvt *next;				/* Next channel in list */} *iflist = NULL;static struct ast_user_list {	ASTOBJ_CONTAINER_COMPONENTS(struct oh323_user);} userl;static struct ast_peer_list {	ASTOBJ_CONTAINER_COMPONENTS(struct oh323_peer);} peerl;static struct ast_alias_list {	ASTOBJ_CONTAINER_COMPONENTS(struct oh323_alias);} aliasl;/** Asterisk RTP stuff */static struct sched_context *sched;static struct io_context *io;/** Protect the interface list (oh323_pvt) */AST_MUTEX_DEFINE_STATIC(iflock);/* Protect the monitoring thread, so only one process can kill or start it, and not   when it's doing something critical. */AST_MUTEX_DEFINE_STATIC(monlock);/* Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. */AST_MUTEX_DEFINE_STATIC(caplock);/* Protect the reload process */AST_MUTEX_DEFINE_STATIC(h323_reload_lock);static int h323_reloading = 0;/* This is the thread for the monitor which checks for input on the channels   which are not currently in use. */static pthread_t monitor_thread = AST_PTHREADT_NULL;static int restart_monitor(void);static int h323_do_reload(void);static struct ast_channel *oh323_request(const char *type, int format, void *data, int *cause);static int oh323_digit_begin(struct ast_channel *c, char digit);static int oh323_digit_end(struct ast_channel *c, char digit, unsigned int duration);static int oh323_call(struct ast_channel *c, char *dest, int timeout);static int oh323_hangup(struct ast_channel *c);static int oh323_answer(struct ast_channel *c);static struct ast_frame *oh323_read(struct ast_channel *c);static int oh323_write(struct ast_channel *c, struct ast_frame *frame);static int oh323_indicate(struct ast_channel *c, int condition, const void *data, size_t datalen);static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);static const struct ast_channel_tech oh323_tech = {	.type = "H323",	.description = tdesc,	.capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),	.properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,	.requester = oh323_request,	.send_digit_begin = oh323_digit_begin,	.send_digit_end = oh323_digit_end,	.call = oh323_call,	.hangup = oh323_hangup,	.answer = oh323_answer,	.read = oh323_read,	.write = oh323_write,	.indicate = oh323_indicate,	.fixup = oh323_fixup,	/* disable, for now */#if 0	.bridge = ast_rtp_bridge,#endif};static const char* redirectingreason2str(int redirectingreason){	switch (redirectingreason) {	case 0:		return "UNKNOWN";	case 1:		return "BUSY";	case 2:		return "NO_REPLY";	case 0xF:		return "UNCONDITIONAL";	default:		return "NOREDIRECT";	}}static void oh323_destroy_alias(struct oh323_alias *alias){	if (h323debug)		ast_log(LOG_DEBUG, "Destroying alias '%s'\n", alias->name);	free(alias);}static void oh323_destroy_user(struct oh323_user *user){	if (h323debug)		ast_log(LOG_DEBUG, "Destroying user '%s'\n", user->name);	ast_free_ha(user->ha);	free(user);}static void oh323_destroy_peer(struct oh323_peer *peer){	if (h323debug)		ast_log(LOG_DEBUG, "Destroying peer '%s'\n", peer->name);	ast_free_ha(peer->ha);	free(peer);}static int oh323_simulate_dtmf_end(const void *data){	struct oh323_pvt *pvt = (struct oh323_pvt *)data;	if (pvt) {		ast_mutex_lock(&pvt->lock);		/* Don't hold pvt lock while trying to lock the channel */		while(pvt->owner && ast_channel_trylock(pvt->owner)) {			ast_mutex_unlock(&pvt->lock);			usleep(1);			ast_mutex_lock(&pvt->lock);		}		if (pvt->owner) {			struct ast_frame f = {				.frametype = AST_FRAME_DTMF_END,				.subclass = pvt->curDTMF,				.samples = 0,				.src = "SIMULATE_DTMF_END",			};			ast_queue_frame(pvt->owner, &f);			ast_channel_unlock(pvt->owner);		}		pvt->DTMFsched = -1;		ast_mutex_unlock(&pvt->lock);	}	return 0;}/* Channel and private structures should be already locked */static void __oh323_update_info(struct ast_channel *c, struct oh323_pvt *pvt){	if (c->nativeformats != pvt->nativeformats) {		if (h323debug)			ast_log(LOG_DEBUG, "Preparing %s for new native format\n", c->name);		c->nativeformats = pvt->nativeformats;		ast_set_read_format(c, c->readformat);		ast_set_write_format(c, c->writeformat);	}	if (pvt->needhangup) {		if (h323debug)			ast_log(LOG_DEBUG, "Process pending hangup for %s\n", c->name);		c->_softhangup |= AST_SOFTHANGUP_DEV;		c->hangupcause = pvt->hangupcause;		ast_queue_hangup(c);		pvt->needhangup = 0;		pvt->newstate = pvt->newcontrol = pvt->newdigit = pvt->DTMFsched = -1;	}	if (pvt->newstate >= 0) {		ast_setstate(c, pvt->newstate);		pvt->newstate = -1;	}	if (pvt->newcontrol >= 0) {		ast_queue_control(c, pvt->newcontrol);		pvt->newcontrol = -1;	}	if (pvt->newdigit >= 0) {		struct ast_frame f = {			.frametype = AST_FRAME_DTMF_END,			.subclass = pvt->newdigit,			.samples = pvt->newduration * 8,			.len = pvt->newduration,			.src = "UPDATE_INFO",		};		if (pvt->newdigit == ' ') {		/* signalUpdate message */			f.subclass = pvt->curDTMF;			if (pvt->DTMFsched >= 0) {				AST_SCHED_DEL(sched, pvt->DTMFsched);			}		} else {						/* Regular input or signal message */			if (pvt->newduration) {		/* This is a signal, signalUpdate follows */				f.frametype = AST_FRAME_DTMF_BEGIN;				AST_SCHED_DEL(sched, pvt->DTMFsched);				pvt->DTMFsched = ast_sched_add(sched, pvt->newduration, oh323_simulate_dtmf_end, pvt);				if (h323debug)					ast_log(LOG_DTMF, "Scheduled DTMF END simulation for %d ms, id=%d\n", pvt->newduration, pvt->DTMFsched);			}			pvt->curDTMF = pvt->newdigit;		}		ast_queue_frame(c, &f);		pvt->newdigit = -1;	}	if (pvt->update_rtp_info > 0) {		if (pvt->rtp) {			ast_jb_configure(c, &global_jbconf);			c->fds[0] = ast_rtp_fd(pvt->rtp);			c->fds[1] = ast_rtcp_fd(pvt->rtp);			ast_queue_frame(pvt->owner, &ast_null_frame);	/* Tell Asterisk to apply changes */		}		pvt->update_rtp_info = -1;	}}/* Only channel structure should be locked */static void oh323_update_info(struct ast_channel *c){	struct oh323_pvt *pvt = c->tech_pvt;	if (pvt) {		ast_mutex_lock(&pvt->lock);		__oh323_update_info(c, pvt);		ast_mutex_unlock(&pvt->lock);	}}static void cleanup_call_details(call_details_t *cd){	if (cd->call_token) {		free(cd->call_token);		cd->call_token = NULL;	}	if (cd->call_source_aliases) {		free(cd->call_source_aliases);		cd->call_source_aliases = NULL;	}	if (cd->call_dest_alias) {		free(cd->call_dest_alias);		cd->call_dest_alias = NULL;	}	if (cd->call_source_name) {		free(cd->call_source_name);		cd->call_source_name = NULL;	}	if (cd->call_source_e164) {		free(cd->call_source_e164);		cd->call_source_e164 = NULL;	}	if (cd->call_dest_e164) {		free(cd->call_dest_e164);		cd->call_dest_e164 = NULL;	}	if (cd->sourceIp) {		free(cd->sourceIp);		cd->sourceIp = NULL;	}	if (cd->redirect_number) {		free(cd->redirect_number);

⌨️ 快捷键说明

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