chan_h323.c
来自「一个非常美妙的proxy。功能强大。基于sip的协议。如果还要的话」· C语言 代码 · 共 2,305 行 · 第 1/5 页
C
2,305 行
/* * Copyright (C) 2004-2005 by Objective Systems, Inc. * * This software is furnished under an open source license and may be * used and copied only in accordance with the terms of this license. * The text of the license may generally be found in the root * directory of this installation in the COPYING file. It * can also be viewed online at the following URL: * * http://www.obj-sys.com/open/license.html * * Any redistributions of this file including modified versions must * maintain this copyright notice. * *****************************************************************************/#include "chan_h323.h"/* Defaults */#define DEFAULT_CONTEXT "default"#define DEFAULT_H323ID "Asterisk PBX"#define DEFAULT_LOGFILE "/var/log/asterisk/h323_log"#define DEFAULT_H323ACCNT "ast_h323"/* Flags */#define H323_SILENCESUPPRESSION (1<<0)#define H323_GKROUTED (1<<1)#define H323_TUNNELING (1<<2)#define H323_FASTSTART (1<<3)#define H323_OUTGOING (1<<4)#define H323_ALREADYGONE (1<<5)#define H323_NEEDDESTROY (1<<6)#define H323_DISABLEGK (1<<7)/* Channel description */static const char desc[] = "Objective Systems H323 Channel";static const char type[] = "OOH323";static const char tdesc[] = "Objective Systems H323 Channel Driver";static const char config[] = "ooh323.conf";/* Channel Definition */static struct ast_channel *ooh323_request(const char *type, int format, void *data, int *cause);static int ooh323_digit(struct ast_channel *ast, char digit);static int ooh323_call(struct ast_channel *ast, char *dest, int timeout);static int ooh323_hangup(struct ast_channel *ast);static int ooh323_answer(struct ast_channel *ast);static struct ast_frame *ooh323_read(struct ast_channel *ast);static int ooh323_write(struct ast_channel *ast, struct ast_frame *f);static int ooh323_indicate(struct ast_channel *ast, int condition);static int ooh323_fixup (struct ast_channel *oldchan, struct ast_channel *newchan);static struct ast_rtp *ooh323_get_rtp_peer(struct ast_channel *chan);static struct ast_rtp *ooh323_get_vrtp_peer(struct ast_channel *chan);static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active);static const struct ast_channel_tech ooh323_tech = { .type = type, .description = tdesc, .capabilities = -1, .requester = ooh323_request, .send_digit = ooh323_digit, .call = ooh323_call, .hangup = ooh323_hangup, .answer = ooh323_answer, .read = ooh323_read, .write = ooh323_write, .exception = ooh323_read, .indicate = ooh323_indicate, .fixup = ooh323_fixup, .send_html = 0, .bridge = ast_rtp_bridge,};static struct ast_rtp_protocol ooh323_rtp = { .type = type, .get_rtp_info = ooh323_get_rtp_peer, .get_vrtp_info = ooh323_get_vrtp_peer, .set_rtp_peer= ooh323_set_rtp_peer};/* H.323 channel specific data */static struct ooh323_pvt { ast_mutex_t lock; /* Channel private lock */ struct ast_rtp *rtp; struct ast_rtp *vrtp; /* Placeholder for now */ struct ast_channel *owner; /* Master Channel */ time_t lastrtptx; time_t lastrtprx; unsigned int flags; unsigned int call_reference; char *callToken; char *username; char *host; char *callerid_name; char *callerid_num; char caller_h323id[AST_MAX_EXTENSION]; char caller_dialedDigits[AST_MAX_EXTENSION]; char caller_email[AST_MAX_EXTENSION]; char caller_url[256]; char callee_h323id[AST_MAX_EXTENSION]; char callee_dialedDigits[AST_MAX_EXTENSION]; char callee_email[AST_MAX_EXTENSION]; char callee_url[AST_MAX_EXTENSION]; int port; int readformat; /* negotiated read format */ int writeformat; /* negotiated write format */ int capability; struct ast_codec_pref prefs; int dtmfmode; char exten[AST_MAX_EXTENSION]; /* Requested extension */ char context[AST_MAX_EXTENSION]; /* Context where to start */ char accountcode[256]; /* Account code */ int nat; int amaflags; struct ast_dsp *vad; struct ooh323_pvt *next; /* Next entity */} *iflist = NULL;/* Protect the channel list (of h323_pvt's) */AST_MUTEX_DEFINE_STATIC(iflock);/* Profile of H.323 user registered with PBX*/struct ooh323_user{ ast_mutex_t lock; char name[256]; char context[AST_MAX_EXTENSION]; int incominglimit; unsigned inUse; char accountcode[20]; int amaflags; int capability; struct ast_codec_pref prefs; int dtmfmode; int rtptimeout; struct ooh323_user *next;};struct ooh323_peer{ ast_mutex_t lock; char name[256]; unsigned outgoinglimit; unsigned outUse; int capability; struct ast_codec_pref prefs; char accountcode[20]; int amaflags; int dtmfmode; char ip[20]; int port; char *h323id; /* H323-ID alias, which asterisk will register with gk to reach this peer*/ char *email; /* Email alias, which asterisk will register with gk to reach this peer*/ char *url; /* url alias, which asterisk will register with gk to reach this peer*/ char *e164; /* e164 alias, which asterisk will register with gk to reach this peer*/ int rtptimeout; struct ooh323_peer *next;};/* List of H.323 users known to PBX */static struct ast_user_list { struct ooh323_user *users; ast_mutex_t lock;} userl;static struct ast_peer_list { struct ooh323_peer *peers; ast_mutex_t lock;}peerl;static int h323_reloading = 0;AST_MUTEX_DEFINE_STATIC(h323_reload_lock);static int usecnt =0;AST_MUTEX_DEFINE_STATIC(usecnt_lock);AST_MUTEX_DEFINE_STATIC(ooh323c_cmd_lock);/* stack callbacks */int onAlerting(ooCallData *call);int onNewCallCreated(ooCallData *call);int onCallEstablished(ooCallData *call);int onCallCleared(ooCallData *call);static char gLogFile[256] = DEFAULT_LOGFILE;static int gPort = 1720;static char gIP[20];static char gCallerID[AST_MAX_EXTENSION] = DEFAULT_H323ID;static struct ooAliases *gAliasList;static int gCapability = AST_FORMAT_ULAW;static struct ast_codec_pref gPrefs;static int gDTMFMode = H323_DTMF_RFC2833;static char gGatekeeper[100];static enum RasGatekeeperMode gRasGkMode = RasNoGatekeeper;static int gIsGateway = 0;static int gFastStart = 1;static int gTunneling = 1;static int gTOS = 0;static int gRTPTimeout = 60;static char gAccountcode[80] = DEFAULT_H323ACCNT;static int gAMAFLAGS;static char gContext[AST_MAX_EXTENSION] = DEFAULT_CONTEXT;static int gIncomingLimit = 4;static int gOutgoingLimit = 4;OOBOOL gH323Debug = FALSE;/** Asterisk RTP stuff*/static struct sched_context *sched;static struct io_context *io;/* 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);/* 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 struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state, const char *host) { struct ast_channel *ch = NULL; int fmt; if(gH323Debug) ast_log(LOG_DEBUG, "--- ooh323_new - %s\n", host); /* Don't hold a h323 pvt lock while we allocate a channel */ ast_mutex_unlock(&i->lock); ch = ast_channel_alloc(1); ast_mutex_lock(&i->lock); if(ch) { ast_mutex_lock(&ch->lock); ch->tech = &ooh323_tech; snprintf(ch->name, sizeof(ch->name), "OOH323/%s-%04x", host, rand() & 0xffff); ch->nativeformats = i->capability; fmt = ast_best_codec(ch->nativeformats); ch->type = type; ch->fds[0] = ast_rtp_fd(i->rtp); ch->fds[1] = ast_rtcp_fd(i->rtp); if (state == AST_STATE_RING) ch->rings = 1; ch->adsicpe = AST_ADSI_UNAVAILABLE; ch->writeformat = fmt; ch->rawwriteformat = fmt; ch->readformat = fmt; ch->rawreadformat = fmt; ch->tech_pvt = i; i->owner = ch; /* Allocate dsp for in-band DTMF support */ if(i->dtmfmode & H323_DTMF_INBAND) { i->vad = ast_dsp_new(); ast_dsp_set_features(i->vad, DSP_FEATURE_DTMF_DETECT); } ast_mutex_lock(&usecnt_lock); usecnt++; ast_mutex_unlock(&usecnt_lock); /* Notify the module monitors that use count for resource has changed*/ ast_update_use_count(); strncpy(ch->context, i->context, sizeof(ch->context)-1); ch->context[sizeof(ch->context)-1] = '\0'; strncpy(ch->exten, i->exten, sizeof(ch->exten)-1); ch->exten[sizeof(ch->exten)-1] = '\0'; ch->priority = 1; if (i->callerid_name) { ch->cid.cid_name = strdup(i->callerid_name); } if(i->callerid_num){ ch->cid.cid_num = strdup(i->callerid_num); } if(!ast_test_flag(i, H323_OUTGOING)) { if (!ast_strlen_zero(i->caller_h323id)) { pbx_builtin_setvar_helper(ch, "_CALLER_H323ID", i->caller_h323id); } if (!ast_strlen_zero(i->caller_dialedDigits)) { pbx_builtin_setvar_helper(ch, "_CALLER_H323DIALEDDIGITS", i->caller_dialedDigits); } if (!ast_strlen_zero(i->caller_email)) { pbx_builtin_setvar_helper(ch, "_CALLER_H323EMAIL", i->caller_email); } if (!ast_strlen_zero(i->caller_url)) { pbx_builtin_setvar_helper(ch, "_CALLER_H323URL", i->caller_url); } } if (!ast_strlen_zero(i->accountcode)){ strncpy(ch->accountcode, i->accountcode, sizeof(ch->accountcode)-1); ch->accountcode[sizeof(ch->accountcode)-1] = '\0'; } if (i->amaflags) ch->amaflags = i->amaflags; ast_setstate(ch, state); if (state != AST_STATE_DOWN) { if (ast_pbx_start(ch)) { ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name); ast_mutex_unlock(&ch->lock); ast_hangup(ch); ch = NULL; } } } else ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); if(ch) ast_mutex_unlock(&ch->lock); if(gH323Debug) ast_log(LOG_DEBUG, "+++ h323_new\n"); return ch;}static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken) { struct ooh323_pvt *pvt = NULL; struct in_addr ipAddr; if(gH323Debug) ast_log(LOG_DEBUG, "--- ooh323_alloc\n"); pvt = (struct ooh323_pvt*) malloc(sizeof(struct ooh323_pvt)); if(!pvt) { ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n"); return NULL; } memset(pvt, 0, sizeof(struct ooh323_pvt)); ast_mutex_init(&pvt->lock); ast_mutex_lock(&pvt->lock); pvt->caller_h323id[0]='\0'; pvt->caller_dialedDigits[0]='\0'; pvt->caller_email[0]='\0'; pvt->caller_url[0]='\0'; pvt->vrtp = NULL; pvt->callee_h323id[0]='\0'; pvt->callee_dialedDigits[0]='\0'; pvt->callee_email[0] = '\0'; pvt->callee_url[0] = '\0'; pvt->host = NULL; pvt->callToken = NULL; pvt->port = 0; pvt->vad = NULL; pvt->next = NULL; pvt->owner = NULL; pvt->callerid_name = NULL; pvt->callerid_num = NULL; pvt->flags = 0; if(!inet_aton(gIP, &ipAddr)) { ast_log(LOG_ERROR, "Invalid OOH323 driver ip address\n"); ast_mutex_unlock(&pvt->lock); ast_mutex_destroy(&pvt->lock); free(pvt); return NULL; } pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, ipAddr); if (!pvt->rtp) { ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno)); ast_mutex_unlock(&pvt->lock); ast_mutex_destroy(&pvt->lock); free(pvt); return NULL; } ast_rtp_settos(pvt->rtp, gTOS); pvt->call_reference = callref; if(callToken) pvt->callToken = strdup(callToken); /* whether to use gk for this call */ if(gRasGkMode == RasNoGatekeeper) OO_SETFLAG(pvt->flags, H323_DISABLEGK); pvt->dtmfmode = gDTMFMode; strncpy(pvt->context, gContext, sizeof(pvt->context)-1); pvt->exten[0]='\0'; strncpy(pvt->accountcode, gAccountcode, sizeof(pvt->accountcode)-1); pvt->amaflags = gAMAFLAGS; pvt->capability = gCapability; memcpy(&pvt->prefs, &gPrefs, sizeof(struct ast_codec_pref)); ast_mutex_unlock(&pvt->lock); /* Add to interface list */ ast_mutex_lock(&iflock); pvt->next = iflist; iflist = pvt; ast_mutex_unlock(&iflock); if(gH323Debug) ast_log(LOG_DEBUG, "+++ ooh323_alloc\n"); return pvt;}/* Possible data values - peername, exten/peername, exten@ip */static struct ast_channel *ooh323_request(const char *type, int format, void *data, int *cause){ struct ast_channel *chan=NULL; struct ooh323_pvt *p = NULL; struct ooh323_peer *peer = NULL; char *dest = NULL; char *ext = NULL; char tmp[256]; char formats[512];
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?