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 + -
显示快捷键?