summaryrefslogtreecommitdiff
path: root/addons/chan_ooh323.c
diff options
context:
space:
mode:
authorAlexandr Anikin <may@telecom-service.ru>2009-11-04 22:10:44 +0000
committerAlexandr Anikin <may@telecom-service.ru>2009-11-04 22:10:44 +0000
commit953031095415efa4558ca7eff29d7c85ff8efe89 (patch)
treec8a21eb3b2896c7f5b558913cb7ea914b40a06ce /addons/chan_ooh323.c
parent317435a93200520218c4e9f4bbb8c0258f363876 (diff)
Reworked chan_ooh323 channel module.
Many architectural and functional changes. Main changes are threading model chanes (many thread in ooh323 stack instead of one), modifications and improvements in signalling part, additional codecs support (726, speex), t38 mode support. This module tested and used in production environment. (closes issue #15285) Reported by: may213 Tested by: sles, c0w, OrNix Review: https://reviewboard.asterisk.org/r/324/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@227898 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'addons/chan_ooh323.c')
-rw-r--r--addons/chan_ooh323.c2112
1 files changed, 1585 insertions, 527 deletions
diff --git a/addons/chan_ooh323.c b/addons/chan_ooh323.c
index 4aa26c92e..697758beb 100644
--- a/addons/chan_ooh323.c
+++ b/addons/chan_ooh323.c
@@ -16,10 +16,9 @@
#include "chan_ooh323.h"
+#include <math.h>
-/*** MODULEINFO
- <defaultenabled>no</defaultenabled>
- ***/
+#define FORMAT_STRING_SIZE 512
/* Defaults */
#define DEFAULT_CONTEXT "default"
@@ -36,17 +35,33 @@
#define H323_ALREADYGONE (1<<5)
#define H323_NEEDDESTROY (1<<6)
#define H323_DISABLEGK (1<<7)
+#define H323_NEEDSTART (1<<8)
+
+#define MAXT30 240
+#define T38TOAUDIOTIMEOUT 30
+#define T38_DISABLED 0
+#define T38_ENABLED 1
+#define T38_FAXGW 1
/* Channel description */
static const char type[] = "OOH323";
static const char tdesc[] = "Objective Systems H323 Channel Driver";
-static const char config[] = "chan_ooh323.conf";
-static const char config_old[] = "ooh323.conf";
+static const char config[] = "ooh323.conf";
+
+struct ast_module *myself;
+static struct ast_jb_conf default_jbconf =
+{
+ .flags = 0,
+ .max_size = -1,
+ .resync_threshold = -1,
+ .impl = ""
+};
+static struct ast_jb_conf global_jbconf;
/* Channel Definition */
static struct ast_channel *ooh323_request(const char *type, int format,
- void *data, int *cause);
+ const struct ast_channel *requestor, void *data, int *cause);
static int ooh323_digit_begin(struct ast_channel *ast, char digit);
static int ooh323_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
static int ooh323_call(struct ast_channel *ast, char *dest, int timeout);
@@ -55,18 +70,21 @@ 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, const void *data, size_t datalen);
+static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, int *datalen);
static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
-static enum ast_rtp_get_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
-static enum ast_rtp_get_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp);
-static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
- struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active);
+static enum ast_rtp_glue_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp);
+static enum ast_rtp_glue_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp);
+static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp,
+ struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active);
+
+static struct ast_udptl *ooh323_get_udptl_peer(struct ast_channel *chan);
+static int ooh323_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl);
static void print_codec_to_cli(int fd, struct ast_codec_pref *pref);
-#if 0
-static void ast_ooh323c_exit();
-#endif
+struct ooh323_peer *find_friend(const char *name, int port);
+
static const struct ast_channel_tech ooh323_tech = {
.type = type,
@@ -84,22 +102,50 @@ static const struct ast_channel_tech ooh323_tech = {
.indicate = ooh323_indicate,
.fixup = ooh323_fixup,
.send_html = 0,
- .bridge = ast_rtp_bridge,
+ .queryoption = ooh323_queryoption,
+ .bridge = ast_rtp_instance_bridge, /* XXX chan unlocked ? */
+ .early_bridge = ast_rtp_instance_early_bridge,
+
};
-static struct ast_rtp_protocol ooh323_rtp = {
+static struct ast_rtp_glue 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
+ .update_peer = ooh323_set_rtp_peer,
+};
+
+static struct ast_udptl_protocol ooh323_udptl = {
+ type: "H323",
+ get_udptl_info: ooh323_get_udptl_peer,
+ set_udptl_peer: ooh323_set_udptl_peer,
};
+
+
+struct ooh323_user;
+
/* H.323 channel private structure */
static struct ooh323_pvt {
ast_mutex_t lock; /* Channel private lock */
- struct ast_rtp *rtp;
- struct ast_rtp *vrtp; /* Placeholder for now */
+ struct ast_rtp_instance *rtp;
+ struct ast_rtp_instance *vrtp; /* Placeholder for now */
+
+ int t38support; /* T.38 mode - disable, transparent, faxgw */
+ int rtptimeout;
+ struct ast_udptl *udptl;
+ int faxmode;
+ int t38_tx_enable;
+ int t38_init;
+ struct sockaddr_in udptlredirip;
+ time_t lastTxT38;
+ int chmodepend;
+
struct ast_channel *owner; /* Master Channel */
+ union {
+ char *user; /* cooperating user/peer */
+ char *peer;
+ } neighbor;
time_t lastrtptx;
time_t lastrtprx;
unsigned int flags;
@@ -124,12 +170,16 @@ static struct ooh323_pvt {
int capability;
struct ast_codec_pref prefs;
int dtmfmode;
+ int dtmfcodec;
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;
+ int progsent; /* progress is sent */
struct ast_dsp *vad;
+ struct OOH323Regex *rtpmask; /* rtp ip regexp */
+ char rtpmaskstr[120];
struct ooh323_pvt *next; /* Next entity */
} *iflist = NULL;
@@ -148,9 +198,13 @@ struct ooh323_user{
int capability;
struct ast_codec_pref prefs;
int dtmfmode;
+ int dtmfcodec;
+ int t38support;
int rtptimeout;
int mUseIP; /* Use IP address or H323-ID to search user */
char mIP[20];
+ struct OOH323Regex *rtpmask;
+ char rtpmaskstr[120];
struct ooh323_user *next;
};
@@ -165,6 +219,8 @@ struct ooh323_peer{
char accountcode[20];
int amaflags;
int dtmfmode;
+ int dtmfcodec;
+ int t38support;
int mFriend; /* indicates defined as friend */
char ip[20];
int port;
@@ -173,6 +229,8 @@ struct ooh323_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 OOH323Regex *rtpmask;
+ char rtpmaskstr[120];
struct ooh323_peer *next;
};
@@ -198,35 +256,51 @@ AST_MUTEX_DEFINE_STATIC(usecnt_lock);
AST_MUTEX_DEFINE_STATIC(ooh323c_cmd_lock);
+static long callnumber = 0;
+AST_MUTEX_DEFINE_STATIC(ooh323c_cn_lock);
+
/* stack callbacks */
int onAlerting(ooCallData *call);
+int onProgress(ooCallData *call);
int onNewCallCreated(ooCallData *call);
+int onOutgoingCall(ooCallData *call);
int onCallEstablished(ooCallData *call);
int onCallCleared(ooCallData *call);
+void onModeChanged(ooCallData *call, int t38mode);
static char gLogFile[256] = DEFAULT_LOGFILE;
static int gPort = 1720;
static char gIP[20];
-static char gCallerID[AST_MAX_EXTENSION] = DEFAULT_H323ID;
+static char gCallerID[AST_MAX_EXTENSION] = "";
static struct ooAliases *gAliasList;
static int gCapability = AST_FORMAT_ULAW;
static struct ast_codec_pref gPrefs;
static int gDTMFMode = H323_DTMF_RFC2833;
+static int gDTMFCodec = 101;
+static int gT38Support = T38_FAXGW;
static char gGatekeeper[100];
static enum RasGatekeeperMode gRasGkMode = RasNoGatekeeper;
static int gIsGateway = 0;
static int gFastStart = 1;
static int gTunneling = 1;
+static int gBeMaster = 0;
static int gMediaWaitForConnect = 0;
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;
+static int gIncomingLimit = 1024;
+static int gOutgoingLimit = 1024;
OOBOOL gH323Debug = FALSE;
+static int gTRCLVL = OOTRCLVLERR;
+
+static int t35countrycode = 0;
+static int t35extensions = 0;
+static int manufacturer = 0;
+static char vendor[AST_MAX_EXTENSION] = "";
+static char version[AST_MAX_EXTENSION] = "";
static struct ooh323_config
{
@@ -249,45 +323,63 @@ static pthread_t monitor_thread = AST_PTHREADT_NULL;
static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
- const char *host)
+ const char *host, int capability, const char *linkedid)
{
struct ast_channel *ch = NULL;
- int fmt;
+ int fmt = 0;
if (gH323Debug)
- ast_verbose("--- ooh323_new - %s\n", host);
+ ast_verbose("--- ooh323_new - %s, %d\n", host, capability);
/* Don't hold a h323 pvt lock while we allocate a channel */
ast_mutex_unlock(&i->lock);
- ch = ast_channel_alloc(1, state, i->callerid_num, i->callerid_name, i->accountcode, i->exten, i->context, i->amaflags, "OOH323/%s-%08x", host, (unsigned int)(unsigned long) i);
+ ch = ast_channel_alloc(1, state, i->callerid_num, i->callerid_name,
+ i->accountcode, i->exten, i->context, linkedid, i->amaflags,
+ "OOH323/%s-%ld", host, callnumber);
+ ast_mutex_lock(&ooh323c_cn_lock);
+ callnumber++;
+ ast_mutex_unlock(&ooh323c_cn_lock);
+
ast_mutex_lock(&i->lock);
if (ch) {
ast_channel_lock(ch);
ch->tech = &ooh323_tech;
- ch->nativeformats = i->capability;
+ if (capability)
+ fmt = ast_best_codec(capability);
+ if (!fmt)
+ fmt = ast_codec_pref_index(&i->prefs, 0);
+
+ ch->nativeformats = ch->rawwriteformat = ch->rawreadformat = fmt;
- fmt = ast_best_codec(ch->nativeformats);
+ ast_channel_set_fd(ch, 0, ast_rtp_instance_fd(i->rtp, 0));
+ ast_channel_set_fd(ch, 1, ast_rtp_instance_fd(i->rtp, 1));
+ ast_channel_set_fd(ch, 5, ast_udptl_fd(i->udptl));
- ch->fds[0] = ast_rtp_fd(i->rtp);
- ch->fds[1] = ast_rtcp_fd(i->rtp);
+ ast_jb_configure(ch, &global_jbconf);
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;
+ ast_set_write_format(ch, fmt);
+ ast_set_read_format(ch, fmt);
ch->tech_pvt = i;
i->owner = ch;
+ ast_module_ref(myself);
/* 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_DIGIT_DETECT);
+ ast_dsp_set_features(i->vad,
+ DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
+ ast_dsp_set_faxmode(i->vad,
+ DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED);
+
+ if (i->dtmfmode & H323_DTMF_INBANDRELAX)
+ ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
}
ast_mutex_lock(&usecnt_lock);
@@ -301,15 +393,8 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
ast_copy_string(ch->exten, i->exten, sizeof(ch->exten));
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_test_flag(i, H323_OUTGOING)) {
if (!ast_strlen_zero(i->caller_h323id)) {
pbx_builtin_setvar_helper(ch, "_CALLER_H323ID", i->caller_h323id);
@@ -336,19 +421,21 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
ast_setstate(ch, state);
if (state != AST_STATE_DOWN) {
- if (ast_pbx_start(ch)) {
+ if (ast_pbx_start(ch)) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ch->name);
- ast_channel_unlock(ch);
+ ast_channel_unlock(ch);
ast_hangup(ch);
ch = NULL;
- }
- }
+ }
+ }
+
+ manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", "Channel: %s\r\nChanneltype: %s\r\n"
+ "CallRef: %d\r\n", ch->name, "OOH323", i->call_reference);
} else
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
- if (ch)
- ast_channel_unlock(ch);
+ if(ch) ast_channel_unlock(ch);
if (gH323Debug)
ast_verbose("+++ h323_new\n");
@@ -361,6 +448,7 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
{
struct ooh323_pvt *pvt = NULL;
+ struct sockaddr_in ouraddr;
struct in_addr ipAddr;
if (gH323Debug)
ast_verbose("--- ooh323_alloc\n");
@@ -373,24 +461,40 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
ast_mutex_init(&pvt->lock);
ast_mutex_lock(&pvt->lock);
+
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);
+ ast_free(pvt);
return NULL;
}
- if (!(pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, ipAddr))) {
+ ouraddr.sin_addr = ipAddr;
+ if (!(pvt->rtp = ast_rtp_instance_new("asterisk", sched, &ouraddr, NULL))) {
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);
+ ast_free(pvt);
return NULL;
}
- ast_rtp_setqos(pvt->rtp, gTOS, 0, "ooh323");
+ ast_rtp_instance_set_qos(pvt->rtp, gTOS, 0, "ooh323-rtp");
+
+ if (!(pvt->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, ipAddr))) {
+ ast_log(LOG_WARNING, "Unable to create UDPTL session: %s\n",
+ strerror(errno));
+ ast_mutex_unlock(&pvt->lock);
+ ast_mutex_destroy(&pvt->lock);
+ ast_free(pvt);
+ return NULL;
+ }
+
+ ast_udptl_set_error_correction_scheme(pvt->udptl, UDPTL_ERROR_CORRECTION_NONE);
+ pvt->faxmode = 0;
+ pvt->t38support = gT38Support;
+ pvt->rtptimeout = gRTPTimeout;
pvt->call_reference = callref;
if (callToken)
@@ -401,8 +505,10 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
OO_SETFLAG(pvt->flags, H323_DISABLEGK);
pvt->dtmfmode = gDTMFMode;
+ pvt->dtmfcodec = gDTMFCodec;
ast_copy_string(pvt->context, gContext, sizeof(pvt->context));
ast_copy_string(pvt->accountcode, gAccountcode, sizeof(pvt->accountcode));
+
pvt->amaflags = gAMAFLAGS;
pvt->capability = gCapability;
memcpy(&pvt->prefs, &gPrefs, sizeof(pvt->prefs));
@@ -424,8 +530,9 @@ static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
/*
Possible data values - peername, exten/peername, exten@ip
*/
-static struct ast_channel *ooh323_request(const char *type, int format, const struct ast_channel *requestor,
- void *data, int *cause)
+static struct ast_channel *ooh323_request(const char *type, int format,
+ const struct ast_channel *requestor, void *data, int *cause)
+
{
struct ast_channel *chan = NULL;
struct ooh323_pvt *p = NULL;
@@ -433,13 +540,13 @@ static struct ast_channel *ooh323_request(const char *type, int format, const st
char *dest = NULL;
char *ext = NULL;
char tmp[256];
- char formats[512];
+ char formats[FORMAT_STRING_SIZE];
int oldformat;
int port = 0;
if (gH323Debug)
ast_verbose("--- ooh323_request - data %s format %s\n", (char*)data,
- ast_getformatname_multiple(formats,512,format));
+ ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,format));
oldformat = format;
format &= AST_FORMAT_AUDIO_MASK;
@@ -460,14 +567,16 @@ static struct ast_channel *ooh323_request(const char *type, int format, const st
/* This is an outgoing call, since ooh323_request is called */
ast_set_flag(p, H323_OUTGOING);
- ast_copy_string(tmp, data, sizeof(data));
+
+ ast_copy_string(tmp, data, sizeof(tmp));
dest = strchr(tmp, '/');
if (dest) {
*dest = '\0';
dest++;
- ext = tmp;
+ ext = dest;
+ dest = tmp;
} else if ((dest = strchr(tmp, '@'))) {
*dest = '\0';
dest++;
@@ -497,22 +606,28 @@ static struct ast_channel *ooh323_request(const char *type, int format, const st
p->host = strdup(peer->ip);
p->port = peer->port;
/* Disable gk as we are going to call a known peer*/
- OO_SETFLAG(p->flags, H323_DISABLEGK);
+ /* OO_SETFLAG(p->flags, H323_DISABLEGK); */
if (ext)
ast_copy_string(p->exten, ext, sizeof(p->exten));
- if (peer->capability & format) {
- p->capability = peer->capability & format;
- } else {
- p->capability = peer->capability;
- }
+ p->capability = peer->capability;
memcpy(&p->prefs, &peer->prefs, sizeof(struct ast_codec_pref));
- p->dtmfmode = peer->dtmfmode;
+ p->dtmfmode |= peer->dtmfmode;
+ p->dtmfcodec = peer->dtmfcodec;
+ p->t38support = peer->t38support;
+ p->rtptimeout = peer->rtptimeout;
+ if (peer->rtpmask && peer->rtpmaskstr[0]) {
+ p->rtpmask = peer->rtpmask;
+ ast_copy_string(p->rtpmaskstr, peer->rtpmaskstr, sizeof(p->rtpmaskstr));
+ }
ast_copy_string(p->accountcode, peer->accountcode, sizeof(p->accountcode));
p->amaflags = peer->amaflags;
} else {
p->dtmfmode = gDTMFMode;
+ p->dtmfcodec = gDTMFCodec;
+ p->t38support = gT38Support;
+ p->rtptimeout = gRTPTimeout;
p->capability = gCapability;
memcpy(&p->prefs, &gPrefs, sizeof(struct ast_codec_pref));
@@ -528,7 +643,8 @@ static struct ast_channel *ooh323_request(const char *type, int format, const st
}
- chan = ooh323_new(p, AST_STATE_DOWN, p->username);
+ chan = ooh323_new(p, AST_STATE_DOWN, p->username, format,
+ requestor ? requestor->linkedid : NULL);
ast_mutex_unlock(&p->lock);
@@ -536,6 +652,23 @@ static struct ast_channel *ooh323_request(const char *type, int format, const st
ast_mutex_lock(&iflock);
ooh323_destroy(p);
ast_mutex_unlock(&iflock);
+ } else {
+ ast_mutex_lock(&p->lock);
+ p->callToken = (char*)ast_malloc(AST_MAX_EXTENSION);
+ if(!p->callToken)
+ {
+ ast_mutex_unlock(&p->lock);
+ ast_mutex_lock(&iflock);
+ ooh323_destroy(p);
+ ast_mutex_unlock(&iflock);
+ ast_log(LOG_ERROR, "Failed to allocate memory for callToken\n");
+ return NULL;
+ }
+
+ ast_mutex_unlock(&p->lock);
+ ast_mutex_lock(&ooh323c_cmd_lock);
+ ooMakeCall(data, p->callToken, AST_MAX_EXTENSION, NULL);
+ ast_mutex_unlock(&ooh323c_cmd_lock);
}
restart_monitor();
@@ -574,9 +707,10 @@ struct ooh323_user *find_user(const char * name, const char* ip)
struct ooh323_user *user;
if (gH323Debug)
- ast_verbose("--- find_user\n");
+ ast_verbose("--- find_user: %s, %s\n",name,ip);
ast_mutex_lock(&userl.lock);
+
for (user = userl.users; user; user = user->next) {
if (ip && user->mUseIP && !strcmp(user->mIP, ip)) {
break;
@@ -585,6 +719,7 @@ struct ooh323_user *find_user(const char * name, const char* ip)
break;
}
}
+
ast_mutex_unlock(&userl.lock);
if (gH323Debug)
@@ -632,6 +767,7 @@ struct ooh323_peer *find_peer(const char * name, int port)
if (gH323Debug)
ast_verbose("--- find_peer \"%s\"\n", name);
+
ast_mutex_lock(&peerl.lock);
for (peer = peerl.peers; peer; peer = peer->next) {
if (gH323Debug) {
@@ -675,16 +811,25 @@ static int ooh323_digit_begin(struct ast_channel *chan, char digit)
return -1;
}
ast_mutex_lock(&p->lock);
- if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833)) {
- ast_rtp_senddigit_begin(p->rtp, digit);
+
+
+ if (digit == 'e' && !p->faxmode && p->t38support != T38_DISABLED) {
+ if (!p->chmodepend) {
+ if (gH323Debug)
+ ast_verbose("request to change %s to t.38 because fax cng\n",
+ p->callToken);
+ p->chmodepend = 1;
+ ooRequestChangeMode(p->callToken, 1);
+ }
+
+ } else if (p->rtp && ((p->dtmfmode & H323_DTMF_RFC2833) || (p->dtmfmode & H323_DTMF_CISCO))) {
+ ast_rtp_instance_dtmf_begin(p->rtp, digit);
} else if (((p->dtmfmode & H323_DTMF_Q931) ||
(p->dtmfmode & H323_DTMF_H245ALPHANUMERIC) ||
(p->dtmfmode & H323_DTMF_H245SIGNAL))) {
dtmf[0] = digit;
dtmf[1] = '\0';
- ast_mutex_lock(&ooh323c_cmd_lock);
ooSendDTMFDigit(p->callToken, dtmf);
- ast_mutex_unlock(&ooh323c_cmd_lock);
}
ast_mutex_unlock(&p->lock);
if (gH323Debug)
@@ -705,8 +850,8 @@ static int ooh323_digit_end(struct ast_channel *chan, char digit, unsigned int d
return -1;
}
ast_mutex_lock(&p->lock);
- if (p->rtp && (p->dtmfmode & H323_DTMF_RFC2833))
- ast_rtp_senddigit_end(p->rtp, digit);
+ if (p->rtp && ((p->dtmfmode & H323_DTMF_RFC2833) || (p->dtmfmode & H323_DTMF_CISCO)) )
+ ast_rtp_instance_dtmf_end(p->rtp, digit);
ast_mutex_unlock(&p->lock);
if (gH323Debug)
@@ -720,43 +865,42 @@ static int ooh323_call(struct ast_channel *ast, char *dest, int timeout)
{
struct ooh323_pvt *p = ast->tech_pvt;
char destination[256];
- int res = 0;
+ int res=0, i;
const char *val = NULL;
ooCallOptions opts = {
.fastStart = TRUE,
.tunneling = TRUE,
.disableGk = TRUE,
- .callMode = OO_CALLMODE_AUDIOCALL
+ .callMode = OO_CALLMODE_AUDIOCALL,
+ .transfercap = 0
};
+
if (gH323Debug)
ast_verbose("--- ooh323_call- %s\n", dest);
- if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
+
+ if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED))
+ {
ast_log(LOG_WARNING, "ooh323_call called on %s, neither down nor "
"reserved\n", ast->name);
return -1;
}
ast_mutex_lock(&p->lock);
ast_set_flag(p, H323_OUTGOING);
- if (ast->cid.cid_num) {
- if (p->callerid_num) {
- free(p->callerid_num);
- }
- p->callerid_num = strdup(ast->cid.cid_num);
+ if (ast->connected.id.number) {
+ if(p->callerid_num) free(p->callerid_num);
+ p->callerid_num = strdup(ast->connected.id.number);
}
- if (ast->cid.cid_name) {
- if (p->callerid_name) {
+ if (ast->connected.id.name) {
+ if(p->callerid_name)
free(p->callerid_name);
- }
- p->callerid_name = strdup(ast->cid.cid_name);
- }
- else{
- ast->cid.cid_name = strdup(gCallerID);
- if (p->callerid_name) {
+ p->callerid_name = strdup(ast->connected.id.name);
+ } else {
+ ast->connected.id.name = strdup(gCallerID);
+ if(p->callerid_name)
free(p->callerid_name);
- }
- p->callerid_name = strdup(ast->cid.cid_name);
+ p->callerid_name = strdup(ast->connected.id.name);
}
/* Retrieve vars */
@@ -768,9 +912,8 @@ static int ooh323_call(struct ast_channel *ast, char *dest, int timeout)
if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323DIALEDDIGITS"))) {
ast_copy_string(p->caller_dialedDigits, val, sizeof(p->caller_dialedDigits));
- if (!p->callerid_num) {
+ if(!p->callerid_num)
p->callerid_num = strdup(val);
- }
}
if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323EMAIL"))) {
@@ -781,13 +924,6 @@ static int ooh323_call(struct ast_channel *ast, char *dest, int timeout)
ast_copy_string(p->caller_url, val, sizeof(p->caller_url));
}
-
- if (!(p->callToken = (char*)malloc(AST_MAX_EXTENSION))) {
- ast_mutex_unlock(&p->lock);
- ast_log(LOG_ERROR, "Failed to allocate memory for callToken\n");
- return -1; /* TODO: need to clean/hangup?? */
- }
-
if (p->host && p->port != 0)
snprintf(destination, sizeof(destination), "%s:%d", p->host, p->port);
else if (p->host)
@@ -795,17 +931,22 @@ static int ooh323_call(struct ast_channel *ast, char *dest, int timeout)
else
ast_copy_string(destination, dest, sizeof(destination));
- ast_mutex_lock(&ooh323c_cmd_lock);
- if (OO_TESTFLAG(p->flags, H323_DISABLEGK))
- res = ooMakeCall(destination, p->callToken, AST_MAX_EXTENSION, &opts);
- else
- res = ooMakeCall(destination, p->callToken, AST_MAX_EXTENSION, NULL);
- ast_mutex_unlock(&ooh323c_cmd_lock);
+ destination[sizeof(destination)-1]='\0';
+
+ opts.transfercap = ast->transfercapability;
+
+ for (i=0;i<480 && !isRunning(p->callToken);i++) usleep(12000);
+
+ if(OO_TESTFLAG(p->flags, H323_DISABLEGK)) {
+ res = ooRunCall(destination, p->callToken, AST_MAX_EXTENSION, &opts);
+ } else {
+ res = ooRunCall(destination, p->callToken, AST_MAX_EXTENSION, NULL);
+ }
ast_mutex_unlock(&p->lock);
if (res != OO_OK) {
ast_log(LOG_ERROR, "Failed to make call\n");
- return -1; /* TODO: cleanup */
+ return -1; /* ToDO: cleanup */
}
if (gH323Debug)
ast_verbose("+++ ooh323_call\n");
@@ -816,6 +957,7 @@ static int ooh323_call(struct ast_channel *ast, char *dest, int timeout)
static int ooh323_hangup(struct ast_channel *ast)
{
struct ooh323_pvt *p = ast->tech_pvt;
+ int q931cause = AST_CAUSE_NORMAL_CLEARING;
if (gH323Debug)
ast_verbose("--- ooh323_hangup\n");
@@ -823,23 +965,42 @@ static int ooh323_hangup(struct ast_channel *ast)
if (p) {
ast_mutex_lock(&p->lock);
+ if (ast->hangupcause) {
+ q931cause = ast->hangupcause;
+ } else {
+ const char *cause = pbx_builtin_getvar_helper(ast, "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;
+ }
+ }
+ }
+
+
+
if (gH323Debug)
- ast_verbose(" hanging %s\n", p->username);
+ ast_verbose(" hanging %s with cause: %d\n", p->username, q931cause);
ast->tech_pvt = NULL;
if (!ast_test_flag(p, H323_ALREADYGONE)) {
- ast_mutex_lock(&ooh323c_cmd_lock);
- ooHangCall(p->callToken,
- ooh323_convert_hangupcause_asteriskToH323(p->owner->hangupcause));
- ast_mutex_unlock(&ooh323c_cmd_lock);
+ ooHangCall(p->callToken,
+ ooh323_convert_hangupcause_asteriskToH323(q931cause), q931cause);
ast_set_flag(p, H323_ALREADYGONE);
/* ast_mutex_unlock(&p->lock); */
- } else {
+ } else
ast_set_flag(p, H323_NEEDDESTROY);
- }
/* detach channel here */
if (p->owner) {
p->owner->tech_pvt = NULL;
p->owner = NULL;
+ ast_module_unref(myself);
}
ast_mutex_unlock(&p->lock);
@@ -851,8 +1012,7 @@ static int ooh323_hangup(struct ast_channel *ast)
ast_update_use_count();
} else {
- ast_log(LOG_ERROR, "No call to hangup\n" );
- return -1;
+ ast_log(LOG_DEBUG, "No call to hangup\n" );
}
if (gH323Debug)
@@ -868,17 +1028,19 @@ static int ooh323_answer(struct ast_channel *ast)
if (gH323Debug)
ast_verbose("--- ooh323_answer\n");
- ast_mutex_lock(&p->lock);
- if (ast->_state != AST_STATE_UP) {
- ast_channel_lock(ast);
- ast_setstate(ast, AST_STATE_UP);
- ast_debug(1, "ooh323_answer(%s)\n", ast->name);
- ast_channel_unlock(ast);
- ast_mutex_lock(&ooh323c_cmd_lock);
- ooAnswerCall(p->callToken);
- ast_mutex_unlock(&ooh323c_cmd_lock);
+ if (p) {
+
+ ast_mutex_lock(&p->lock);
+ if (ast->_state != AST_STATE_UP) {
+ ast_channel_lock(ast);
+ ast_setstate(ast, AST_STATE_UP);
+ if (option_debug)
+ ast_debug(1, "ooh323_answer(%s)\n", ast->name);
+ ast_channel_unlock(ast);
+ ooAnswerCall(p->callToken);
+ }
+ ast_mutex_unlock(&p->lock);
}
- ast_mutex_unlock(&p->lock);
if (gH323Debug)
ast_verbose("+++ ooh323_answer\n");
@@ -892,6 +1054,8 @@ static struct ast_frame *ooh323_read(struct ast_channel *ast)
static struct ast_frame null_frame = { AST_FRAME_NULL, };
struct ooh323_pvt *p = ast->tech_pvt;
+ if (!p) return &null_frame;
+
ast_mutex_lock(&p->lock);
if (p->rtp)
fr = ooh323_rtp_read(ast, p);
@@ -907,26 +1071,59 @@ static int ooh323_write(struct ast_channel *ast, struct ast_frame *f)
struct ooh323_pvt *p = ast->tech_pvt;
int res = 0;
- if (f->frametype == AST_FRAME_VOICE) {
- if (!(f->subclass & ast->nativeformats)) {
- ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native "
- "formats is %d (read/write = %d/%d)\n",
- f->subclass, ast->nativeformats, ast->readformat,
+ if (p) {
+ ast_mutex_lock(&p->lock);
+
+ if (f->frametype == AST_FRAME_MODEM) {
+ ast_debug(1, "Send UDPTL %d/%d len %d for %s\n",
+ f->frametype, f->subclass, f->datalen, ast->name);
+ if (p->udptl)
+ res = ast_udptl_write(p->udptl, f);
+ ast_mutex_unlock(&p->lock);
+ return res;
+ }
+
+
+ if (f->frametype == AST_FRAME_VOICE) {
+/* sending progress for first */
+ if (!ast_test_flag(p, H323_OUTGOING) && !p->progsent &&
+ p->callToken) {
+ ooManualProgress(p->callToken);
+ p->progsent = 1;
+ }
+
+
+ if (!(f->subclass & ast->nativeformats)) {
+ if (ast->nativeformats != 0) {
+ ast_log(LOG_WARNING, "Asked to transmit frame type %d,"
+ " while native "
+ "formats is %d (read/write = %d/%d)\n",
+ f->subclass, ast->nativeformats, ast->readformat,
ast->writeformat);
+ ast_set_write_format(ast, f->subclass);
+ } else {
+ /* ast_set_write_format(ast, f->subclass);
+ ast->nativeformats = f->subclass; */
+ }
+ ast_mutex_unlock(&p->lock);
return 0;
- }
- if (p) {
- ast_mutex_lock(&p->lock);
- if (p->rtp)
- res = ast_rtp_write(p->rtp, f);
+ }
+
+ if (p->rtp)
+ res = ast_rtp_instance_write(p->rtp, f);
+
+ ast_mutex_unlock(&p->lock);
+
+ } else if (f->frametype == AST_FRAME_IMAGE) {
ast_mutex_unlock(&p->lock);
- }
- } else if (f->frametype == AST_FRAME_IMAGE) {
- return 0;
- } else {
- ast_log(LOG_WARNING, "Can't send %d type frames with SIP write\n",
+ return 0;
+ } else {
+ ast_log(LOG_WARNING, "Can't send %d type frames with OOH323 write\n",
f->frametype);
- return 0;
+ ast_mutex_unlock(&p->lock);
+ return 0;
+ }
+
}
return res;
@@ -938,6 +1135,8 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
struct ooh323_pvt *p = (struct ooh323_pvt *) ast->tech_pvt;
char *callToken = (char *)NULL;
+ if (!p) return -1;
+
ast_mutex_lock(&p->lock);
callToken = (p->callToken ? strdup(p->callToken) : NULL);
ast_mutex_unlock(&p->lock);
@@ -951,21 +1150,18 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
if (gH323Debug)
ast_verbose("----- ooh323_indicate %d on call %s\n", condition, callToken);
-
+ ast_mutex_lock(&p->lock);
switch (condition) {
case AST_CONTROL_CONGESTION:
if (!ast_test_flag(p, H323_ALREADYGONE)) {
- ast_mutex_lock(&ooh323c_cmd_lock);
- ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED);
- ast_mutex_unlock(&ooh323c_cmd_lock);
+ ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED,
+ AST_CAUSE_SWITCH_CONGESTION);
ast_set_flag(p, H323_ALREADYGONE);
}
break;
case AST_CONTROL_BUSY:
if (!ast_test_flag(p, H323_ALREADYGONE)) {
- ast_mutex_lock(&ooh323c_cmd_lock);
- ooHangCall(callToken, OO_REASON_LOCAL_BUSY);
- ast_mutex_unlock(&ooh323c_cmd_lock);
+ ooHangCall(callToken, OO_REASON_LOCAL_BUSY, AST_CAUSE_USER_BUSY);
ast_set_flag(p, H323_ALREADYGONE);
}
break;
@@ -975,9 +1171,74 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
case AST_CONTROL_UNHOLD:
ast_moh_stop(ast);
break;
- case AST_CONTROL_PROCEEDING:
- case AST_CONTROL_RINGING:
case AST_CONTROL_PROGRESS:
+ if (ast->_state != AST_STATE_UP) {
+ if (!p->progsent) {
+ if (gH323Debug)
+ ast_log(LOG_DEBUG,"Sending manual progress for %s, res = %d\n", callToken,
+ ooManualProgress(callToken));
+ else
+ ooManualProgress(callToken);
+ p->progsent = 1;
+ }
+ }
+ break;
+ case AST_CONTROL_RINGING:
+ if (ast->_state == AST_STATE_RING || ast->_state == AST_STATE_RINGING) {
+ if (gH323Debug)
+ ast_log(LOG_DEBUG,"Sending manual ringback for %s, res = %d\n",
+ callToken,
+ ooManualRingback(callToken));
+ else
+ ooManualRingback(callToken);
+ }
+ break;
+ case AST_CONTROL_SRCUPDATE:
+ ast_rtp_instance_new_source(p->rtp);
+ break;
+
+ case AST_CONTROL_T38_PARAMETERS:
+ if (p->t38support != T38_ENABLED) {
+ struct ast_control_t38_parameters parameters = { .request_response = 0 };
+ parameters.request_response = AST_T38_REFUSED;
+ ast_queue_control_data(ast, AST_CONTROL_T38_PARAMETERS,
+ &parameters, sizeof(parameters));
+ break;
+ }
+ if (datalen != sizeof(struct ast_control_t38_parameters)) {
+ ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38. "
+ "Expected %d, got %d\n",
+ (int)sizeof(enum ast_control_t38), (int)datalen);
+ } else {
+ const struct ast_control_t38_parameters *parameters = data;
+ enum ast_control_t38 message = parameters->request_response;
+ switch (message) {
+
+ case AST_T38_REQUEST_NEGOTIATE:
+
+ if (!p->chmodepend && !p->faxmode) {
+ ooRequestChangeMode(p->callToken, 1);
+ p->chmodepend = 1;
+ }
+ break;
+
+ case AST_T38_REQUEST_TERMINATE:
+
+ if (!p->chmodepend && p->faxmode) {
+ ooRequestChangeMode(p->callToken, 0);
+ p->chmodepend = 1;
+ }
+ break;
+
+
+ default:
+ ;
+
+ }
+
+ }
+ break;
+ case AST_CONTROL_PROCEEDING:
case -1:
break;
default:
@@ -985,13 +1246,76 @@ static int ooh323_indicate(struct ast_channel *ast, int condition, const void *d
condition, callToken);
}
+ ast_mutex_unlock(&p->lock);
+
if (gH323Debug)
ast_verbose("++++ ooh323_indicate %d on %s\n", condition, callToken);
-
+ free(callToken);
return -1;
}
+static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
+{
+
+ struct ooh323_pvt *p = (struct ooh323_pvt *) ast->tech_pvt;
+ int res = -1;
+ enum ast_t38_state state = T38_STATE_UNAVAILABLE;
+ char* cp;
+
+ if (!p) return -1;
+
+ ast_mutex_lock(&p->lock);
+
+ if (gH323Debug)
+ ast_verbose("----- ooh323_queryoption %d on channel %s\n", option, ast->name);
+
+ switch (option) {
+
+ case AST_OPTION_T38_STATE:
+
+ if (*datalen != sizeof(enum ast_t38_state)) {
+ ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option."
+ " Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen);
+ break;
+ }
+ if (p->t38support != T38_DISABLED)
+ state = T38_STATE_UNKNOWN;
+ if (p->faxmode)
+ state = (p->chmodepend) ? T38_STATE_UNKNOWN : T38_STATE_NEGOTIATED;
+ else if (p->chmodepend)
+ state = T38_STATE_NEGOTIATING;
+
+
+ *((enum ast_t38_state *) data) = state;
+ res = 0;
+ break;
+
+
+ case AST_OPTION_DIGIT_DETECT:
+
+ cp = (char *) data;
+ *cp = p->vad ? 1 : 0;
+ ast_debug(1, "Reporting digit detection %sabled on %s\n",
+ *cp ? "en" : "dis", ast->name);
+
+ res = 0;
+ break;
+
+ default: ;
+
+ }
+
+ if (gH323Debug)
+ ast_verbose("+++++ ooh323_queryoption %d on channel %s\n", option, ast->name);
+
+ ast_mutex_unlock(&p->lock);
+
+ return res;
+}
+
+
+
static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
{
struct ooh323_pvt *p = newchan->tech_pvt;
@@ -1021,15 +1345,14 @@ static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan
}
-void ooh323_set_write_format(ooCallData *call, int fmt)
+void ooh323_set_write_format(ooCallData *call, int fmt, int txframes)
{
-#if 0
struct ooh323_pvt *p = NULL;
- char formats[512];
-#ifdef print_debug
- printf("--- ooh323_update_writeformat %s\n",
- ast_getformatname_multiple(formats,512, fmt));
-#endif
+ char formats[FORMAT_STRING_SIZE];
+
+ if (gH323Debug)
+ ast_verbose("--- ooh323_update_writeformat %s/%d\n",
+ ast_getformatname_multiple(formats,FORMAT_STRING_SIZE, fmt), txframes);
p = find_call(call);
if (!p) {
@@ -1040,34 +1363,56 @@ void ooh323_set_write_format(ooCallData *call, int fmt)
ast_mutex_lock(&p->lock);
p->writeformat = fmt;
- ast_mutex_unlock(&p->lock);
if (p->owner) {
- printf("Writeformat before update %s\n",
- ast_getformatname_multiple(formats,512, p->owner->writeformat));
- ast_set_write_format(p->owner, fmt);
- }
- else
- ast_log(LOG_ERROR, "No owner found\n");
+ while (p->owner && ast_channel_trylock(p->owner)) {
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ DEADLOCK_AVOIDANCE(&p->lock);
+ }
+ if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return;
+ }
+ if (gH323Debug)
+ ast_verbose("Writeformat before update %s/%s\n",
+ ast_getformatname_multiple(formats,FORMAT_STRING_SIZE, p->owner->writeformat),
+ ast_getformatname_multiple(formats,FORMAT_STRING_SIZE, p->owner->nativeformats));
+ if (txframes)
+ ast_codec_pref_setsize(&p->prefs, fmt, txframes);
+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs);
+ if (p->dtmfmode & H323_DTMF_RFC2833 && p->dtmfcodec) {
+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
+ p->rtp, p->dtmfcodec, "audio", "telephone-event", 0);
+ }
+ if (p->dtmfmode & H323_DTMF_CISCO && p->dtmfcodec) {
+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
+ p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0);
+ }
+ p->owner->nativeformats = fmt;
+ ast_set_write_format(p->owner, p->owner->writeformat);
+ ast_set_read_format(p->owner, p->owner->readformat);
+ ast_channel_unlock(p->owner);
+ } else
+ ast_log(LOG_ERROR, "No owner found\n");
-#ifdef print_debug
- printf("+++ ooh323_update_writeformat\n");
-#endif
-#endif
-}
+ ast_mutex_unlock(&p->lock);
+
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_update_writeformat\n");
+}
void ooh323_set_read_format(ooCallData *call, int fmt)
{
-#if 0
struct ooh323_pvt *p = NULL;
- char formats[512];
-#ifdef print_debug
- printf("--- ooh323_update_readformat %s\n",
- ast_getformatname_multiple(formats,512, fmt));
-#endif
+ char formats[FORMAT_STRING_SIZE];
+ if (gH323Debug)
+ ast_verbose("--- ooh323_update_readformat %s\n",
+ ast_getformatname_multiple(formats,FORMAT_STRING_SIZE, fmt));
+
p = find_call(call);
if (!p) {
ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
@@ -1075,16 +1420,37 @@ void ooh323_set_read_format(ooCallData *call, int fmt)
}
ast_mutex_lock(&p->lock);
+
p->readformat = fmt;
+
+
+ if (p->owner) {
+ while (p->owner && ast_channel_trylock(p->owner)) {
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ DEADLOCK_AVOIDANCE(&p->lock);
+ }
+ if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return;
+ }
+
+ if (gH323Debug)
+ ast_verbose("Readformat before update %s\n",
+ ast_getformatname_multiple(formats,FORMAT_STRING_SIZE, p->owner->readformat));
+ p->owner->nativeformats = fmt;
+ ast_set_read_format(p->owner, p->owner->readformat);
+ ast_channel_unlock(p->owner);
+ } else
+ ast_log(LOG_ERROR, "No owner found\n");
+
ast_mutex_unlock(&p->lock);
- ast_set_read_format(p->owner, fmt);
-
-#ifdef print_debug
- printf("+++ ooh323_update_readformat\n");
-#endif
-#endif
+
+ if (gH323Debug)
+ ast_verbose("+++ ooh323_update_readformat\n");
}
+
int onAlerting(ooCallData *call)
{
struct ooh323_pvt *p = NULL;
@@ -1093,31 +1459,34 @@ int onAlerting(ooCallData *call)
if (gH323Debug)
ast_verbose("--- onAlerting %s\n", call->callToken);
- if (!(p = find_call(call))) {
+ p = find_call(call);
+
+ if(!p) {
ast_log(LOG_ERROR, "No matching call found\n");
return -1;
}
ast_mutex_lock(&p->lock);
- if (!ast_test_flag(p, H323_OUTGOING)) {
- if (!(c = ooh323_new(p, AST_STATE_RING, p->username))) {
- ast_mutex_unlock(&p->lock);
- ast_log(LOG_ERROR, "Could not create ast_channel\n");
- return -1;
- }
+ if (!p->owner) {
ast_mutex_unlock(&p->lock);
- } else {
- if (!p->owner) {
- ast_mutex_unlock(&p->lock);
- ast_log(LOG_ERROR, "Channel has no owner\n");
- return 0;
- }
- c = p->owner;
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return 0;
+ }
+ while (p->owner && ast_channel_trylock(p->owner)) {
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ DEADLOCK_AVOIDANCE(&p->lock);
+ }
+ if (!p->owner) {
ast_mutex_unlock(&p->lock);
- ast_channel_lock(c);
- ast_setstate(c, AST_STATE_RINGING);
- ast_channel_unlock(c);
- ast_queue_control(c, AST_CONTROL_RINGING);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return 0;
}
+ c = p->owner;
+ if (c->_state != AST_STATE_UP)
+ ast_setstate(c, AST_STATE_RINGING);
+
+ ast_queue_control(c, AST_CONTROL_RINGING);
+ ast_channel_unlock(c);
+ ast_mutex_unlock(&p->lock);
if (gH323Debug)
ast_verbose("+++ onAlerting %s\n", call->callToken);
@@ -1125,6 +1494,49 @@ int onAlerting(ooCallData *call)
return OO_OK;
}
+int onProgress(ooCallData *call)
+{
+ struct ooh323_pvt *p = NULL;
+ struct ast_channel *c = NULL;
+
+ if (gH323Debug)
+ ast_verbose("--- onProgress %s\n", call->callToken);
+
+ p = find_call(call);
+
+ if(!p) {
+ ast_log(LOG_ERROR, "No matching call found\n");
+ return -1;
+ }
+ ast_mutex_lock(&p->lock);
+ if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return 0;
+ }
+ while (p->owner && ast_channel_trylock(p->owner)) {
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ DEADLOCK_AVOIDANCE(&p->lock);
+ }
+ if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return 0;
+ }
+ c = p->owner;
+ if (c->_state != AST_STATE_UP)
+ ast_setstate(c, AST_STATE_RINGING);
+
+ ast_queue_control(c, AST_CONTROL_PROGRESS);
+ ast_channel_unlock(c);
+ ast_mutex_unlock(&p->lock);
+
+ if (gH323Debug)
+ ast_verbose("+++ onProgress %s\n", call->callToken);
+
+ return OO_OK;
+}
+
/**
* Callback for sending digits from H.323 up to asterisk
*
@@ -1155,8 +1567,19 @@ int ooh323_onReceivedDigit(OOH323CallData *call, const char *digit)
f.data.ptr = NULL;
f.mallocd = 0;
f.src = "SEND_DIGIT";
- ast_mutex_unlock(&p->lock);
+
+ while (p->owner && ast_channel_trylock(p->owner)) {
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ DEADLOCK_AVOIDANCE(&p->lock);
+ }
+ if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return 0;
+ }
res = ast_queue_frame(p->owner, &f);
+ ast_channel_unlock(p->owner);
+ ast_mutex_unlock(&p->lock);
return res;
}
@@ -1164,6 +1587,7 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
{
struct ooh323_pvt *p = NULL;
struct ooh323_user *user = NULL;
+ struct ast_channel *c = NULL;
ooAliases *alias = NULL;
char *at = NULL;
char number [OO_MAX_NUMBER_LENGTH];
@@ -1195,30 +1619,35 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
p->callerid_name = strdup(alias->value);
}
ast_copy_string(p->caller_h323id, alias->value, sizeof(p->caller_h323id));
- } else if (alias->type == T_H225AliasAddress_dialedDigits) {
- if (!p->callerid_num) {
- p->callerid_num = strdup(alias->value);
}
+ else if(alias->type == T_H225AliasAddress_dialedDigits)
+ {
+ if(!p->callerid_num)
+ p->callerid_num = strdup(alias->value);
ast_copy_string(p->caller_dialedDigits, alias->value,
sizeof(p->caller_dialedDigits));
- } else if (alias->type == T_H225AliasAddress_email_ID) {
+ }
+ else if(alias->type == T_H225AliasAddress_email_ID)
+ {
ast_copy_string(p->caller_email, alias->value, sizeof(p->caller_email));
- } else if (alias->type == T_H225AliasAddress_url_ID) {
+ }
+ else if(alias->type == T_H225AliasAddress_url_ID)
+ {
ast_copy_string(p->caller_url, alias->value, sizeof(p->caller_url));
}
}
}
number[0] = '\0';
- if (ooCallGetCalledPartyNumber(call, number, OO_MAX_NUMBER_LENGTH) == OO_OK) {
- ast_copy_string(p->exten, number, sizeof(p->exten));
- } else {
+ if(ooCallGetCalledPartyNumber(call, number, OO_MAX_NUMBER_LENGTH)== OO_OK) {
+ strncpy(p->exten, number, sizeof(p->exten)-1);
+ } else {
update_our_aliases(call, p);
if (!ast_strlen_zero(p->callee_dialedDigits)) {
- ast_copy_string(p->exten, p->callee_dialedDigits, sizeof(p->exten));
- } else if (!ast_strlen_zero(p->callee_h323id)) {
+ ast_copy_string(p->exten, p->callee_dialedDigits, sizeof(p->exten));
+ } else if(!ast_strlen_zero(p->callee_h323id)) {
ast_copy_string(p->exten, p->callee_h323id, sizeof(p->exten));
- } else if (!ast_strlen_zero(p->callee_email)) {
+ } else if(!ast_strlen_zero(p->callee_email)) {
ast_copy_string(p->exten, p->callee_email, sizeof(p->exten));
if ((at = strchr(p->exten, '@'))) {
*at = '\0';
@@ -1228,34 +1657,58 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
/* if no extension found, set to default 's' */
if (ast_strlen_zero(p->exten)) {
- ast_copy_string(p->exten, "s", sizeof(p->exten));
+ p->exten[0]='s';
+ p->exten[1]='\0';
}
- if (!p->callerid_name) {
- p->callerid_name = strdup(call->remoteIP);
- }
-
- if (p->callerid_name) {
- if ((user = find_user(p->callerid_name, call->remoteIP))) {
- ast_mutex_lock(&user->lock);
- p->username = strdup(user->name);
- ast_copy_string(p->context, user->context, sizeof(p->context));
- ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode));
- p->amaflags = user->amaflags;
- p->capability = user->capability;
- memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref));
- p->dtmfmode = user->dtmfmode;
- /* Since, call is coming from a pbx user, no need to use gk */
- OO_SETFLAG(p->flags, H323_DISABLEGK);
- OO_SETFLAG(call->flags, OO_M_DISABLEGK);
- ast_mutex_unlock(&user->lock);
+ user = find_user(p->callerid_name, call->remoteIP);
+ if(user && (user->incominglimit == 0 || user->inUse < user->incominglimit)) {
+ ast_mutex_lock(&user->lock);
+ p->username = strdup(user->name);
+ p->neighbor.user = user->mUseIP ? ast_strdup(user->mIP) :
+ ast_strdup(user->name);
+ ast_copy_string(p->context, user->context, sizeof(p->context));
+ ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode));
+ p->amaflags = user->amaflags;
+ p->capability = user->capability;
+ memcpy(&p->prefs, &user->prefs, sizeof(struct ast_codec_pref));
+ p->dtmfmode |= user->dtmfmode;
+ p->dtmfcodec = user->dtmfcodec;
+ p->t38support = user->t38support;
+ p->rtptimeout = user->rtptimeout;
+ if (user->rtpmask && user->rtpmaskstr[0]) {
+ p->rtpmask = user->rtpmask;
+ ast_copy_string(p->rtpmaskstr, user->rtpmaskstr,
+ sizeof(p->rtpmaskstr));
}
+ if (user->incominglimit) user->inUse++;
+ ast_mutex_unlock(&user->lock);
+ } else {
+ if (!OO_TESTFLAG(p->flags,H323_DISABLEGK)) {
+ p->username = strdup(call->remoteIP);
+ } else {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Unacceptable ip %s\n", call->remoteIP);
+ if (!user)
+ ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_CALL_REJECTED), AST_CAUSE_CALL_REJECTED);
+ else
+ ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_NORMAL_CIRCUIT_CONGESTION), AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
+ ast_set_flag(p, H323_NEEDDESTROY);
+ return -1;
+ }
}
-
- ooh323c_set_capability_for_call(call, &p->prefs, p->capability, p->dtmfmode);
+ ooh323c_set_capability_for_call(call, &p->prefs, p->capability, p->dtmfmode, p->dtmfcodec,
+ p->t38support);
configure_local_rtp(p, call);
+/* Incoming call */
+ c = ooh323_new(p, AST_STATE_RING, p->username, 0, NULL);
+ if(!c) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Could not create ast_channel\n");
+ return -1;
+ }
ast_mutex_unlock(&p->lock);
if (gH323Debug)
@@ -1267,38 +1720,112 @@ int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
+int onOutgoingCall(ooCallData *call)
+{
+ struct ooh323_pvt *p = NULL;
+ int i = 0;
+
+ if (gH323Debug)
+ ast_verbose("--- onOutgoingCall %lx: %s\n", (long unsigned int) call, call->callToken);
+
+ if (!strcmp(call->callType, "outgoing")) {
+ p = find_call(call);
+ if (!p) {
+ ast_log(LOG_ERROR, "Failed to find a matching call.\n");
+ return -1;
+ }
+ ast_mutex_lock(&p->lock);
+
+ if (!ast_strlen_zero(p->callerid_name)) {
+ ooCallSetCallerId(call, p->callerid_name);
+ }
+ if (!ast_strlen_zero(p->callerid_num)) {
+ i = 0;
+ while (*(p->callerid_num + i) != '\0') {
+ if(!isdigit(*(p->callerid_num+i))) { break; }
+ i++;
+ }
+ if(*(p->callerid_num+i) == '\0')
+ ooCallSetCallingPartyNumber(call, p->callerid_num);
+ else {
+ if(!p->callerid_name)
+ ooCallSetCallerId(call, p->callerid_num);
+ }
+ }
+
+ if (!ast_strlen_zero(p->caller_h323id))
+ ooCallAddAliasH323ID(call, p->caller_h323id);
+
+ if (!ast_strlen_zero(p->caller_dialedDigits)) {
+ if (gH323Debug) {
+ ast_verbose("Setting dialed digits %s\n", p->caller_dialedDigits);
+ }
+ ooCallAddAliasDialedDigits(call, p->caller_dialedDigits);
+ } else if (!ast_strlen_zero(p->callerid_num)) {
+ if (ooIsDailedDigit(p->callerid_num)) {
+ if (gH323Debug) {
+ ast_verbose("setting callid number %s\n", p->callerid_num);
+ }
+ ooCallAddAliasDialedDigits(call, p->callerid_num);
+ } else if (ast_strlen_zero(p->caller_h323id)) {
+ ooCallAddAliasH323ID(call, p->callerid_num);
+ }
+ }
+ if (p->rtpmask && p->rtpmaskstr[0]) {
+ call->rtpMask = p->rtpmask;
+ ast_mutex_lock(&call->rtpMask->lock);
+ call->rtpMask->inuse++;
+ ast_mutex_unlock(&call->rtpMask->lock);
+ ast_copy_string(call->rtpMaskStr, p->rtpmaskstr, sizeof(call->rtpMaskStr));
+ }
+
+ ast_mutex_unlock(&p->lock);
+ }
+
+ if (gH323Debug)
+ ast_verbose("+++ onOutgoingCall %s\n", call->callToken);
+ return OO_OK;
+}
+
+
int onNewCallCreated(ooCallData *call)
{
struct ooh323_pvt *p = NULL;
int i = 0;
if (gH323Debug)
- ast_verbose("--- onNewCallCreated %s\n", call->callToken);
+ ast_verbose("--- onNewCallCreated %lx: %s\n", (long unsigned int) call, call->callToken);
+
+ ast_mutex_lock(&call->Lock);
+ if (ooh323c_start_call_thread(call)) {
+ ast_log(LOG_ERROR,"Failed to create call thread.\n");
+ ast_mutex_unlock(&call->Lock);
+ return -1;
+ }
if (!strcmp(call->callType, "outgoing")) {
p = find_call(call);
if (!p) {
- ast_log(LOG_ERROR, "No matching call found for outgoing call\n");
+ ast_log(LOG_ERROR, "Failed to find a matching call.\n");
+ ast_mutex_unlock(&call->Lock);
return -1;
}
ast_mutex_lock(&p->lock);
+
if (p->callerid_name) {
ooCallSetCallerId(call, p->callerid_name);
}
if (p->callerid_num) {
i = 0;
while (*(p->callerid_num + i) != '\0') {
- if (!isdigit(*(p->callerid_num + i))) {
- break;
- }
+ if(!isdigit(*(p->callerid_num+i))) { break; }
i++;
}
- if (*(p->callerid_num + i) == '\0') {
+ if(*(p->callerid_num+i) == '\0')
ooCallSetCallingPartyNumber(call, p->callerid_num);
- } else {
- if (!p->callerid_name) {
+ else {
+ if(!p->callerid_name)
ooCallSetCallerId(call, p->callerid_num);
- }
}
}
@@ -1335,17 +1862,19 @@ int onNewCallCreated(ooCallData *call)
char prefsBuf[256];
ast_codec_pref_string(&p->prefs, prefsBuf, sizeof(prefsBuf));
ast_verbose(" Outgoing call %s(%s) - Codec prefs - %s\n",
- p->username?p->username:"NULL", call->callToken, prefsBuf);
+ p->username?p->username:"NULL", call->callToken, prefsBuf);
}
- ooh323c_set_capability_for_call(call, &p->prefs, p->capability, p->dtmfmode);
+ ooh323c_set_capability_for_call(call, &p->prefs, p->capability,
+ p->dtmfmode, p->dtmfcodec, p->t38support);
configure_local_rtp(p, call);
ast_mutex_unlock(&p->lock);
}
+
+ ast_mutex_unlock(&call->Lock);
if (gH323Debug)
ast_verbose("+++ onNewCallCreated %s\n", call->callToken);
-
return OO_OK;
}
@@ -1356,33 +1885,33 @@ int onCallEstablished(ooCallData *call)
if (gH323Debug)
ast_verbose("--- onCallEstablished %s\n", call->callToken);
+
if (!(p = find_call(call))) {
ast_log(LOG_ERROR, "Failed to find a matching call.\n");
return -1;
}
- ast_mutex_lock(&p->lock);
- if (!p->owner) {
- ast_mutex_unlock(&p->lock);
- ast_log(LOG_ERROR, "Channel has no owner\n");
- return -1;
- }
-
- while (ast_channel_trylock(p->owner)) {
- ast_debug(1,"Failed to grab lock, trying again\n");
- ast_mutex_unlock(&p->lock);
- usleep(1);
+
+ if(ast_test_flag(p, H323_OUTGOING)) {
ast_mutex_lock(&p->lock);
- }
- if (p->owner->_state != AST_STATE_UP) {
- ast_setstate(p->owner, AST_STATE_UP);
- }
- ast_channel_unlock(p->owner);
- if (ast_test_flag(p, H323_OUTGOING)) {
- struct ast_channel* c = p->owner;
- ast_mutex_unlock(&p->lock);
- ast_queue_control(c, AST_CONTROL_ANSWER);
- } else {
+ if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return -1;
+ }
+
+ while (p->owner && ast_channel_trylock(p->owner)) {
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ DEADLOCK_AVOIDANCE(&p->lock);
+ }
+ if (p->owner) {
+ struct ast_channel* c = p->owner;
+ ast_queue_control(c, AST_CONTROL_ANSWER);
+ ast_channel_unlock(p->owner);
+ manager_event(EVENT_FLAG_SYSTEM,"ChannelUpdate","Channel: %s\r\nChanneltype: %s\r\n"
+ "CallRef: %d\r\n", c->name, "OOH323", p->call_reference);
+ }
ast_mutex_unlock(&p->lock);
+
}
if (gH323Debug)
@@ -1399,42 +1928,47 @@ int onCallCleared(ooCallData *call)
if (gH323Debug)
ast_verbose("--- onCallCleared %s \n", call->callToken);
- p = find_call(call);
- if (!p) {
- return 0;
- }
+
+ if ((p = find_call(call))) {
ast_mutex_lock(&p->lock);
while (p->owner) {
if (ast_channel_trylock(p->owner)) {
ooTrace(OOTRCLVLINFO, "Failed to grab lock, trying again\n");
- ast_debug(1,"Failed to grab lock, trying again\n");
- ast_mutex_unlock(&p->lock);
- usleep(1);
- ast_mutex_lock(&p->lock);
+ ast_log(LOG_DEBUG,"Failed to grab lock, trying again\n");
+ DEADLOCK_AVOIDANCE(&p->lock);
} else {
- ownerLock = 1;
- break;
+ ownerLock = 1; break;
}
}
if (ownerLock) {
if (!ast_test_flag(p, H323_ALREADYGONE)) {
- /* NOTE: Channel is not detached yet */
ast_set_flag(p, H323_ALREADYGONE);
- p->owner->hangupcause =
- ooh323_convert_hangupcause_h323ToAsterisk(call->callEndReason);
+ p->owner->hangupcause = call->q931cause;
p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
- ast_channel_unlock(p->owner);
- ast_queue_hangup(p->owner);
- ast_mutex_unlock(&p->lock);
- return OO_OK;
+ ast_queue_hangup_with_cause(p->owner,call->q931cause);
}
+ }
+
+ if(p->owner) {
+ p->owner->tech_pvt = NULL;
ast_channel_unlock(p->owner);
+ p->owner = NULL;
+ ast_module_unref(myself);
}
+
ast_set_flag(p, H323_NEEDDESTROY);
+
+ ooh323c_stop_call_thread(call);
+
ast_mutex_unlock(&p->lock);
+ ast_mutex_lock(&usecnt_lock);
+ usecnt--;
+ ast_mutex_unlock(&usecnt_lock);
+
+ }
if (gH323Debug)
ast_verbose("+++ onCallCleared\n");
@@ -1442,8 +1976,7 @@ int onCallCleared(ooCallData *call)
return OO_OK;
}
-#if 0
-static void ooh323_delete_user(struct ooh323_user *user)
+/* static void ooh323_delete_user(struct ooh323_user *user)
{
struct ooh323_user *prev = NULL, *cur = NULL;
@@ -1473,8 +2006,7 @@ static void ooh323_delete_user(struct ooh323_user *user)
if (gH323Debug)
ast_verbose("+++ ooh323_delete_user\n");
-}
-#endif
+} */
void ooh323_delete_peer(struct ooh323_peer *peer)
{
@@ -1484,36 +2016,33 @@ void ooh323_delete_peer(struct ooh323_peer *peer)
ast_verbose("--- ooh323_delete_peer\n");
if (peer) {
+ cur = peerl.peers;
ast_mutex_lock(&peerl.lock);
- for (cur = peerl.peers; cur; prev = cur, cur = cur->next) {
- if (cur == peer) {
- break;
- }
+ while(cur) {
+ if(cur==peer) break;
+ prev = cur;
+ cur = cur->next;
}
if (cur) {
- if (prev) {
+ if(prev)
prev->next = cur->next;
- } else {
+ else
peerl.peers = cur->next;
}
- }
ast_mutex_unlock(&peerl.lock);
- if (peer->h323id)
- free(peer->h323id);
- if (peer->email)
- free(peer->email);
- if (peer->url)
- free(peer->url);
- if (peer->e164)
- free(peer->e164);
+ if(peer->h323id) free(peer->h323id);
+ if(peer->email) free(peer->email);
+ if(peer->url) free(peer->url);
+ if(peer->e164) free(peer->e164);
free(peer);
}
if (gH323Debug)
ast_verbose("+++ ooh323_delete_peer\n");
+
}
@@ -1525,14 +2054,17 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v)
if (gH323Debug)
ast_verbose("--- build_user\n");
- user = ast_calloc(1, sizeof(*user));
+ user = ast_calloc(1,sizeof(struct ooh323_user));
if (user) {
+ memset(user, 0, sizeof(struct ooh323_user));
ast_mutex_init(&user->lock);
ast_copy_string(user->name, name, sizeof(user->name));
user->capability = gCapability;
memcpy(&user->prefs, &gPrefs, sizeof(user->prefs));
user->rtptimeout = gRTPTimeout;
user->dtmfmode = gDTMFMode;
+ user->dtmfcodec = gDTMFCodec;
+ user->t38support = gT38Support;
/* set default context */
ast_copy_string(user->context, gContext, sizeof(user->context));
ast_copy_string(user->accountcode, gAccountcode, sizeof(user->accountcode));
@@ -1546,35 +2078,65 @@ static struct ooh323_user *build_user(const char *name, struct ast_variable *v)
if (user->incominglimit < 0)
user->incominglimit = 0;
} else if (!strcasecmp(v->name, "accountcode")) {
- ast_copy_string(user->accountcode, v->value, sizeof(user->accountcode));
+ strncpy(user->accountcode, v->value,
+ sizeof(user->accountcode)-1);
} else if (!strcasecmp(v->name, "rtptimeout")) {
user->rtptimeout = atoi(v->value);
if (user->rtptimeout < 0)
user->rtptimeout = gRTPTimeout;
+ } else if (!strcasecmp(v->name, "rtpmask")) {
+ if ((user->rtpmask = malloc(sizeof(struct OOH323Regex))) &&
+ (regcomp(&user->rtpmask->regex, v->value, REG_EXTENDED)
+ == 0)) {
+ ast_mutex_init(&user->rtpmask->lock);
+ user->rtpmask->inuse = 1;
+ ast_copy_string(user->rtpmaskstr, v->value,
+ sizeof(user->rtpmaskstr));
+ } else user->rtpmask = NULL;
} else if (!strcasecmp(v->name, "disallow")) {
- ast_parse_allow_disallow(&user->prefs, &user->capability,
- v->value, 0);
+ ast_parse_allow_disallow(&user->prefs,
+ &user->capability, v->value, 0);
} else if (!strcasecmp(v->name, "allow")) {
const char* tcodecs = v->value;
if (!strcasecmp(v->value, "all")) {
tcodecs = "ulaw,alaw,g729,g723,gsm";
}
- ast_parse_allow_disallow(&user->prefs, &user->capability,
- tcodecs, 1);
+ ast_parse_allow_disallow(&user->prefs,
+ &user->capability, tcodecs, 1);
} else if (!strcasecmp(v->name, "amaflags")) {
user->amaflags = ast_cdr_amaflags2int(v->value);
} else if (!strcasecmp(v->name, "ip")) {
- ast_copy_string(user->mIP, v->value, sizeof(user->mIP));
+ strncpy(user->mIP, v->value, sizeof(user->mIP)-1);
+ user->mUseIP = 1;
+ } else if (!strcasecmp(v->name, "host")) {
+ strncpy(user->mIP, v->value, sizeof(user->mIP)-1);
user->mUseIP = 1;
- } else if (!strcasecmp(v->name, "dtmfmode")) {
+ } else if (!strcasecmp(v->name, "dtmfmode")) {
if (!strcasecmp(v->value, "rfc2833"))
user->dtmfmode = H323_DTMF_RFC2833;
+ if (!strcasecmp(v->value, "cisco"))
+ user->dtmfmode = H323_DTMF_CISCO;
else if (!strcasecmp(v->value, "q931keypad"))
user->dtmfmode = H323_DTMF_Q931;
else if (!strcasecmp(v->value, "h245alphanumeric"))
user->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
else if (!strcasecmp(v->value, "h245signal"))
user->dtmfmode = H323_DTMF_H245SIGNAL;
+ else if (!strcasecmp(v->value, "inband"))
+ user->dtmfmode = H323_DTMF_INBAND;
+ } else if (!strcasecmp(v->name, "relaxdtmf")) {
+ user->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0;
+ } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) {
+ user->dtmfcodec = atoi(v->value);
+ } else if (!strcasecmp(v->name, "t38support")) {
+ if (!strcasecmp(v->value, "disabled"))
+ user->t38support = T38_DISABLED;
+ if (!strcasecmp(v->value, "no"))
+ user->t38support = T38_DISABLED;
+ else if (!strcasecmp(v->value, "faxgw"))
+ user->t38support = T38_FAXGW;
+ else if (!strcasecmp(v->value, "yes"))
+ user->t38support = T38_ENABLED;
}
v = v->next;
}
@@ -1599,18 +2161,21 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v,
ast_mutex_init(&peer->lock);
ast_copy_string(peer->name, name, sizeof(peer->name));
peer->capability = gCapability;
- memcpy(&peer->prefs, &gPrefs, sizeof(struct ast_codec_pref));
+ memcpy(&peer->prefs, &gPrefs, sizeof(peer->prefs));
peer->rtptimeout = gRTPTimeout;
ast_copy_string(peer->accountcode, gAccountcode, sizeof(peer->accountcode));
peer->amaflags = gAMAFLAGS;
peer->dtmfmode = gDTMFMode;
+ peer->dtmfcodec = gDTMFCodec;
+ peer->t38support = gT38Support;
+ peer->port = 1720;
if (0 == friend_type) {
peer->mFriend = 1;
}
while (v) {
if (!strcasecmp(v->name, "h323id")) {
- if (!(peer->h323id = ast_strdup(v->value))) {
+ if (!(peer->h323id = ast_strdup(v->value))) {
ast_log(LOG_ERROR, "Could not allocate memory for h323id of "
"peer %s\n", name);
ooh323_delete_peer(peer);
@@ -1641,16 +2206,27 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v,
peer->port = atoi(v->value);
} else if (!strcasecmp(v->name, "ip")) {
ast_copy_string(peer->ip, v->value, sizeof(peer->ip));
+ } else if (!strcasecmp(v->name, "host")) {
+ ast_copy_string(peer->ip, v->value, sizeof(peer->ip));
} else if (!strcasecmp(v->name, "outgoinglimit")) {
- if ((peer->outgoinglimit = atoi(v->value)) < 0) {
+ peer->outgoinglimit = atoi(v->value);
+ if (peer->outgoinglimit < 0)
peer->outgoinglimit = 0;
- }
} else if (!strcasecmp(v->name, "accountcode")) {
ast_copy_string(peer->accountcode, v->value, sizeof(peer->accountcode));
} else if (!strcasecmp(v->name, "rtptimeout")) {
- if ((peer->rtptimeout = atoi(v->value)) < 0) {
+ peer->rtptimeout = atoi(v->value);
+ if(peer->rtptimeout < 0)
peer->rtptimeout = gRTPTimeout;
- }
+ } else if (!strcasecmp(v->name, "rtpmask")) {
+ if ((peer->rtpmask = malloc(sizeof(struct OOH323Regex))) &&
+ (regcomp(&peer->rtpmask->regex, v->value, REG_EXTENDED)
+ == 0)) {
+ ast_mutex_init(&peer->rtpmask->lock);
+ peer->rtpmask->inuse = 1;
+ ast_copy_string(peer->rtpmaskstr, v->value,
+ sizeof(peer->rtpmaskstr));
+ } else peer->rtpmask = NULL;
} else if (!strcasecmp(v->name, "disallow")) {
ast_parse_allow_disallow(&peer->prefs, &peer->capability,
v->value, 0);
@@ -1666,12 +2242,29 @@ static struct ooh323_peer *build_peer(const char *name, struct ast_variable *v,
} else if (!strcasecmp(v->name, "dtmfmode")) {
if (!strcasecmp(v->value, "rfc2833"))
peer->dtmfmode = H323_DTMF_RFC2833;
+ if (!strcasecmp(v->value, "cisco"))
+ peer->dtmfmode = H323_DTMF_CISCO;
else if (!strcasecmp(v->value, "q931keypad"))
peer->dtmfmode = H323_DTMF_Q931;
else if (!strcasecmp(v->value, "h245alphanumeric"))
peer->dtmfmode = H323_DTMF_H245ALPHANUMERIC;
else if (!strcasecmp(v->value, "h245signal"))
peer->dtmfmode = H323_DTMF_H245SIGNAL;
+ else if (!strcasecmp(v->value, "inband"))
+ peer->dtmfmode = H323_DTMF_INBAND;
+ } else if (!strcasecmp(v->name, "relaxdtmf")) {
+ peer->dtmfmode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0;
+ } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) {
+ peer->dtmfcodec = atoi(v->value);
+ } else if (!strcasecmp(v->name, "t38support")) {
+ if (!strcasecmp(v->value, "disabled"))
+ peer->t38support = T38_DISABLED;
+ if (!strcasecmp(v->value, "no"))
+ peer->t38support = T38_DISABLED;
+ else if (!strcasecmp(v->value, "faxgw"))
+ peer->t38support = T38_FAXGW;
+ else if (!strcasecmp(v->value, "yes"))
+ peer->t38support = T38_ENABLED;
}
v = v->next;
}
@@ -1689,7 +2282,7 @@ static int ooh323_do_reload(void)
ast_verbose("--- ooh323_do_reload\n");
}
- reload_config(1);
+ reload_config(1);
if (gH323Debug) {
ast_verbose("+++ ooh323_do_reload\n");
@@ -1698,19 +2291,32 @@ static int ooh323_do_reload(void)
return 0;
}
-#if 0
/*--- h323_reload: Force reload of module from cli ---*/
-static int ooh323_reload(int fd, int argc, char *argv[])
+
+char *handle_cli_ooh323_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "ooh323 reload";
+ e->usage =
+ "Usage: ooh323 reload\n"
+ " Reload OOH323 config.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc != 2)
+ return CLI_SHOWUSAGE;
+
if (gH323Debug)
ast_verbose("--- ooh323_reload\n");
ast_mutex_lock(&h323_reload_lock);
if (h323_reloading) {
ast_verbose("Previous OOH323 reload not yet done\n");
- }
- else {
+ } else {
h323_reloading = 1;
}
ast_mutex_unlock(&h323_reload_lock);
@@ -1721,19 +2327,11 @@ static int ooh323_reload(int fd, int argc, char *argv[])
return 0;
}
-#endif
-
-#if 0
-static int reload(void *mod)
-{
- return ooh323_reload(0, 0, NULL);
-}
-#endif
int reload_config(int reload)
{
int format;
- struct ooAliases *pNewAlias = NULL;
+ struct ooAliases *pNewAlias = NULL, *cur, *prev;
struct ast_config *cfg;
struct ast_variable *v;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
@@ -1745,10 +2343,7 @@ int reload_config(int reload)
if (gH323Debug)
ast_verbose("--- reload_config\n");
- cfg = ast_config_load(config, config_flags);
- if (!cfg) {
- cfg = ast_config_load(config_old, config_flags);
- }
+ cfg = ast_config_load((char*)config, config_flags);
/* We *must* have a config file otherwise stop immediately */
if (!cfg) {
@@ -1760,6 +2355,17 @@ int reload_config(int reload)
if (reload) {
delete_users();
delete_peers();
+ if (gH323Debug) {
+ ast_verbose(" reload_config - Freeing up alias list\n");
+ }
+ cur = gAliasList;
+ while (cur) {
+ prev = cur;
+ cur = cur->next;
+ free(prev->value);
+ free(prev);
+ }
+ gAliasList = NULL;
}
/* Inintialize everything to default */
@@ -1767,9 +2373,12 @@ int reload_config(int reload)
gPort = 1720;
gIP[0] = '\0';
strcpy(gCallerID, DEFAULT_H323ID);
- gCapability = AST_FORMAT_ULAW;
+ gCapability = AST_FORMAT_ALAW;
memset(&gPrefs, 0, sizeof(struct ast_codec_pref));
gDTMFMode = H323_DTMF_RFC2833;
+ gDTMFCodec = 101;
+ gT38Support = T38_FAXGW;
+ gTRCLVL = OOTRCLVLERR;
gRasGkMode = RasNoGatekeeper;
gGatekeeper[0] = '\0';
gRTPTimeout = 60;
@@ -1782,9 +2391,15 @@ int reload_config(int reload)
gMediaWaitForConnect = 0;
ooconfig.mTCPPortStart = 12030;
ooconfig.mTCPPortEnd = 12230;
+ memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
v = ast_variable_browse(cfg, "general");
while (v) {
+
+ if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
+ v = v->next;
+ continue;
+ }
if (!strcasecmp(v->name, "port")) {
gPort = (int)strtol(v->value, NULL, 10);
@@ -1792,7 +2407,7 @@ int reload_config(int reload)
ast_copy_string(gIP, v->value, sizeof(gIP));
} else if (!strcasecmp(v->name, "h225portrange")) {
char* endlimit = 0;
- char temp[256];
+ char temp[512];
ast_copy_string(temp, v->value, sizeof(temp));
endlimit = strchr(temp, ',');
if (endlimit) {
@@ -1801,16 +2416,12 @@ int reload_config(int reload)
ooconfig.mTCPPortStart = atoi(temp);
ooconfig.mTCPPortEnd = atoi(endlimit);
- if (ooH323EpSetTCPPortRange(ooconfig.mTCPPortStart,
- ooconfig.mTCPPortEnd) == OO_FAILED) {
- ast_log(LOG_ERROR, "h225portrange: Failed to set range\n");
- }
} else {
ast_log(LOG_ERROR, "h225portrange: Invalid format, separate port range with \",\"\n");
}
} else if (!strcasecmp(v->name, "gateway")) {
gIsGateway = ast_true(v->value);
- } else if (!strcasecmp(v->name, "faststart")) {
+ } else if (!strcasecmp(v->name, "faststart")) {
gFastStart = ast_true(v->value);
if (gFastStart)
ooH323EpEnableFastStart();
@@ -1828,19 +2439,28 @@ int reload_config(int reload)
ooH323EpEnableH245Tunneling();
else
ooH323EpDisableH245Tunneling();
+ } else if (!strcasecmp(v->name, "trybemaster")) {
+ gBeMaster = ast_true(v->value);
+ if (gBeMaster)
+ ooH323EpTryBeMaster(1);
+ else
+ ooH323EpTryBeMaster(0);
} else if (!strcasecmp(v->name, "h323id")) {
- pNewAlias = malloc(sizeof(*pNewAlias));
+ pNewAlias = malloc(sizeof(struct ooAliases));
if (!pNewAlias) {
ast_log(LOG_ERROR, "Failed to allocate memory for h323id alias\n");
return 1;
}
+ if (gAliasList == NULL) { /* first h323id - set as callerid if callerid is not set */
+ ast_copy_string(gCallerID, v->value, sizeof(gCallerID));
+ }
pNewAlias->type = T_H225AliasAddress_h323_ID;
pNewAlias->value = strdup(v->value);
pNewAlias->next = gAliasList;
gAliasList = pNewAlias;
pNewAlias = NULL;
} else if (!strcasecmp(v->name, "e164")) {
- pNewAlias = malloc(sizeof(*pNewAlias));
+ pNewAlias = malloc(sizeof(struct ooAliases));
if (!pNewAlias) {
ast_log(LOG_ERROR, "Failed to allocate memory for e164 alias\n");
return 1;
@@ -1851,7 +2471,7 @@ int reload_config(int reload)
gAliasList = pNewAlias;
pNewAlias = NULL;
} else if (!strcasecmp(v->name, "email")) {
- pNewAlias = malloc(sizeof(*pNewAlias));
+ pNewAlias = malloc(sizeof(struct ooAliases));
if (!pNewAlias) {
ast_log(LOG_ERROR, "Failed to allocate memory for email alias\n");
return 1;
@@ -1861,6 +2481,16 @@ int reload_config(int reload)
pNewAlias->next = gAliasList;
gAliasList = pNewAlias;
pNewAlias = NULL;
+ } else if (!strcasecmp(v->name, "t35country")) {
+ t35countrycode = atoi(v->value);
+ } else if (!strcasecmp(v->name, "t35extensions")) {
+ t35extensions = atoi(v->value);
+ } else if (!strcasecmp(v->name, "manufacturer")) {
+ manufacturer = atoi(v->value);
+ } else if (!strcasecmp(v->name, "vendorid")) {
+ ast_copy_string(vendor, v->value, sizeof(vendor));
+ } else if (!strcasecmp(v->name, "versionid")) {
+ ast_copy_string(version, v->value, sizeof(version));
} else if (!strcasecmp(v->name, "callerid")) {
ast_copy_string(gCallerID, v->value, sizeof(gCallerID));
} else if (!strcasecmp(v->name, "incominglimit")) {
@@ -1874,13 +2504,14 @@ int reload_config(int reload)
gRasGkMode = RasDiscoverGatekeeper;
} else {
gRasGkMode = RasUseSpecificGatekeeper;
- ast_copy_string(gGatekeeper, v->value, sizeof(gGatekeeper));
+ strncpy(gGatekeeper, v->value, sizeof(gGatekeeper)-1);
}
} else if (!strcasecmp(v->name, "logfile")) {
- ast_copy_string(gLogFile, v->value, sizeof(gLogFile));
+ strncpy(gLogFile, v->value, sizeof(gLogFile)-1);
} else if (!strcasecmp(v->name, "context")) {
- ast_copy_string(gContext, v->value, sizeof(gContext));
- ast_verb(3, " == Setting default context to %s\n", gContext);
+ strncpy(gContext, v->value, sizeof(gContext)-1);
+ ast_verbose(VERBOSE_PREFIX_3 " == Setting default context to %s\n",
+ gContext);
} else if (!strcasecmp(v->name, "rtptimeout")) {
gRTPTimeout = atoi(v->value);
if (gRTPTimeout <= 0)
@@ -1905,7 +2536,7 @@ int reload_config(int reload)
} else if (!strcasecmp(v->name, "amaflags")) {
gAMAFLAGS = ast_cdr_amaflags2int(v->value);
} else if (!strcasecmp(v->name, "accountcode")) {
- ast_copy_string(gAccountcode, v->value, sizeof(gAccountcode)-1);
+ ast_copy_string(gAccountcode, v->value, sizeof(gAccountcode));
} else if (!strcasecmp(v->name, "disallow")) {
ast_parse_allow_disallow(&gPrefs, &gCapability, v->value, 0);
} else if (!strcasecmp(v->name, "allow")) {
@@ -1919,6 +2550,8 @@ int reload_config(int reload)
gDTMFMode = H323_DTMF_INBAND;
else if (!strcasecmp(v->value, "rfc2833"))
gDTMFMode = H323_DTMF_RFC2833;
+ else if (!strcasecmp(v->value, "cisco"))
+ gDTMFMode = H323_DTMF_CISCO;
else if (!strcasecmp(v->value, "q931keypad"))
gDTMFMode = H323_DTMF_Q931;
else if (!strcasecmp(v->value, "h245alphanumeric"))
@@ -1926,10 +2559,27 @@ int reload_config(int reload)
else if (!strcasecmp(v->value, "h245signal"))
gDTMFMode = H323_DTMF_H245SIGNAL;
else {
- ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n", v->value);
+ ast_log(LOG_WARNING, "Unknown dtmf mode '%s', using rfc2833\n",
+ v->value);
gDTMFMode = H323_DTMF_RFC2833;
}
- }
+ } else if (!strcasecmp(v->name, "relaxdtmf")) {
+ gDTMFMode |= ast_true(v->value) ? H323_DTMF_INBANDRELAX : 0;
+ } else if (!strcasecmp(v->name, "dtmfcodec") && atoi(v->value)) {
+ gDTMFCodec = atoi(v->value);
+ } else if (!strcasecmp(v->name, "t38support")) {
+ if (!strcasecmp(v->value, "disabled"))
+ gT38Support = T38_DISABLED;
+ if (!strcasecmp(v->value, "no"))
+ gT38Support = T38_DISABLED;
+ else if (!strcasecmp(v->value, "faxgw"))
+ gT38Support = T38_FAXGW;
+ else if (!strcasecmp(v->value, "yes"))
+ gT38Support = T38_ENABLED;
+ } else if (!strcasecmp(v->name, "tracelevel")) {
+ gTRCLVL = atoi(v->value);
+ ooH323EpSetTraceLevel(gTRCLVL);
+ }
v = v->next;
}
@@ -1967,7 +2617,7 @@ int reload_config(int reload)
ast_config_destroy(cfg);
- /* Determine ip address if necessary */
+ /* Determine ip address if neccessary */
if (ast_strlen_zero(gIP)) {
ooGetLocalIPAddress(gIP);
if (!strcmp(gIP, "127.0.0.1")) {
@@ -1981,8 +2631,10 @@ int reload_config(int reload)
ast_verbose("+++ reload_config\n");
return 0;
+
}
+
static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
char ip_port[30];
@@ -2002,11 +2654,12 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc
if (a->argc != 4)
return CLI_SHOWUSAGE;
+
ast_mutex_lock(&peerl.lock);
peer = peerl.peers;
while (peer) {
ast_mutex_lock(&peer->lock);
- if (!strcmp(peer->name, a->argv[3]))
+ if(!strcmp(peer->name, a->argv[3]))
break;
else {
prev = peer;
@@ -2016,32 +2669,49 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc
}
if (peer) {
- snprintf(ip_port, sizeof(ip_port), "%s:%d", peer->ip, peer->port);
- ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name);
- ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
- print_codec_to_cli(a->fd, &peer->prefs);
- ast_cli(a->fd, ")\n");
- ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
- if (peer->dtmfmode & H323_DTMF_RFC2833)
- ast_cli(a->fd, "%s\n", "rfc2833");
- else if (peer->dtmfmode & H323_DTMF_Q931)
- ast_cli(a->fd, "%s\n", "q931keypad");
+ sprintf(ip_port, "%s:%d", peer->ip, peer->port);
+ ast_cli(a->fd, "%-15.15s%s\n", "Name: ", peer->name);
+ ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
+ print_codec_to_cli(a->fd, &peer->prefs);
+ ast_cli(a->fd, ")\n");
+ ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
+ if (peer->dtmfmode & H323_DTMF_CISCO) {
+ ast_cli(a->fd, "%s\n", "cisco");
+ ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec);
+ } else if (peer->dtmfmode & H323_DTMF_RFC2833) {
+ ast_cli(a->fd, "%s\n", "rfc2833");
+ ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", peer->dtmfcodec);
+ } else if (peer->dtmfmode & H323_DTMF_Q931)
+ ast_cli(a->fd, "%s\n", "q931keypad");
else if (peer->dtmfmode & H323_DTMF_H245ALPHANUMERIC)
- ast_cli(a->fd, "%s\n", "h245alphanumeric");
+ ast_cli(a->fd, "%s\n", "h245alphanumeric");
else if (peer->dtmfmode & H323_DTMF_H245SIGNAL)
- ast_cli(a->fd, "%s\n", "h245signal");
+ ast_cli(a->fd, "%s\n", "h245signal");
+ else if (peer->dtmfmode & H323_DTMF_INBAND && peer->dtmfmode & H323_DTMF_INBANDRELAX)
+ ast_cli(a->fd, "%s\n", "inband-relaxed");
+ else if (peer->dtmfmode & H323_DTMF_INBAND)
+ ast_cli(a->fd, "%s\n", "inband");
else
- ast_cli(a->fd, "%s\n", "unknown");
- ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", peer->accountcode);
- ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ",
+ ast_cli(a->fd, "%s\n", "unknown");
+
+ ast_cli(a->fd,"%-15s", "T.38 Mode: ");
+ if (peer->t38support == T38_DISABLED)
+ ast_cli(a->fd, "%s\n", "disabled");
+ else if (peer->t38support == T38_FAXGW)
+ ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible");
+
+ ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", peer->accountcode);
+ ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ",
ast_cdr_flags2str(peer->amaflags));
- ast_cli(a->fd, "%-15.15s%s\n", "Ip:Port: ", ip_port);
- ast_cli(a->fd, "%-15.15s%d\n", "OutgoingLimit: ", peer->outgoinglimit);
- ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", peer->rtptimeout);
- ast_mutex_unlock(&peer->lock);
+ ast_cli(a->fd, "%-15.15s%s\n", "IP:Port: ", ip_port);
+ ast_cli(a->fd, "%-15.15s%d\n", "OutgoingLimit: ", peer->outgoinglimit);
+ ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", peer->rtptimeout);
+ if (peer->rtpmaskstr[0])
+ ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", peer->rtpmaskstr);
+ ast_mutex_unlock(&peer->lock);
} else {
- ast_cli(a->fd, "Peer %s not found\n", a->argv[3]);
- ast_cli(a->fd, "\n");
+ ast_cli(a->fd, "Peer %s not found\n", a->argv[3]);
+ ast_cli(a->fd, "\n");
}
ast_mutex_unlock(&peerl.lock);
@@ -2050,10 +2720,9 @@ static char *handle_cli_ooh323_show_peer(struct ast_cli_entry *e, int cmd, struc
static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- char ip_port[30];
- char formats[512];
struct ooh323_peer *prev = NULL, *peer = NULL;
-
+ char formats[FORMAT_STRING_SIZE];
+ char ip_port[30];
#define FORMAT "%-15.15s %-15.15s %-23.23s %-s\n"
switch (cmd) {
@@ -2070,25 +2739,24 @@ static char *handle_cli_ooh323_show_peers(struct ast_cli_entry *e, int cmd, stru
if (a->argc != 3)
return CLI_SHOWUSAGE;
- ast_cli(a->fd, FORMAT, "Name", "Accountcode", "ip:port", "Formats");
+ ast_cli(a->fd, FORMAT, "Name", "Accountcode", "ip:port", "Formats");
ast_mutex_lock(&peerl.lock);
peer = peerl.peers;
while (peer) {
ast_mutex_lock(&peer->lock);
snprintf(ip_port, sizeof(ip_port), "%s:%d", peer->ip, peer->port);
- ast_cli(a->fd, FORMAT, peer->name,
+ ast_cli(a->fd, FORMAT, peer->name,
peer->accountcode,
ip_port,
- ast_getformatname_multiple(formats, sizeof(formats), peer->capability));
+ ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,peer->capability));
prev = peer;
peer = peer->next;
ast_mutex_unlock(&prev->lock);
+
}
ast_mutex_unlock(&peerl.lock);
-
#undef FORMAT
-
return CLI_SUCCESS;
}
@@ -2128,13 +2796,14 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc
if (a->argc != 4)
return CLI_SHOWUSAGE;
+
ast_mutex_lock(&userl.lock);
user = userl.users;
while (user) {
ast_mutex_lock(&user->lock);
- if (!strcmp(user->name, a->argv[3]))
+ if(!strcmp(user->name, a->argv[3])) {
break;
- else {
+ } else {
prev = user;
user = user->next;
ast_mutex_unlock(&prev->lock);
@@ -2142,30 +2811,49 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc
}
if (user) {
- ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name);
- ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
- print_codec_to_cli(a->fd, &user->prefs);
- ast_cli(a->fd, ")\n");
- ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
- if (user->dtmfmode & H323_DTMF_RFC2833)
- ast_cli(a->fd, "%s\n", "rfc2833");
- else if (user->dtmfmode & H323_DTMF_Q931)
- ast_cli(a->fd, "%s\n", "q931keypad");
+ ast_cli(a->fd, "%-15.15s%s\n", "Name: ", user->name);
+ ast_cli(a->fd, "%-15.15s%s", "Format Prefs: ", "(");
+ print_codec_to_cli(a->fd, &user->prefs);
+ ast_cli(a->fd, ")\n");
+ ast_cli(a->fd, "%-15.15s", "DTMF Mode: ");
+ if (user->dtmfmode & H323_DTMF_CISCO) {
+ ast_cli(a->fd, "%s\n", "cisco");
+ ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec);
+ } else if (user->dtmfmode & H323_DTMF_RFC2833) {
+ ast_cli(a->fd, "%s\n", "rfc2833");
+ ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", user->dtmfcodec);
+ } else if (user->dtmfmode & H323_DTMF_Q931)
+ ast_cli(a->fd, "%s\n", "q931keypad");
else if (user->dtmfmode & H323_DTMF_H245ALPHANUMERIC)
- ast_cli(a->fd, "%s\n", "h245alphanumeric");
+ ast_cli(a->fd, "%s\n", "h245alphanumeric");
else if (user->dtmfmode & H323_DTMF_H245SIGNAL)
- ast_cli(a->fd, "%s\n", "h245signal");
+ ast_cli(a->fd, "%s\n", "h245signal");
+ else if (user->dtmfmode & H323_DTMF_INBAND && user->dtmfmode & H323_DTMF_INBANDRELAX)
+ ast_cli(a->fd, "%s\n", "inband-relaxed");
+ else if (user->dtmfmode & H323_DTMF_INBAND)
+ ast_cli(a->fd, "%s\n", "inband");
else
- ast_cli(a->fd, "%s\n", "unknown");
- ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", user->accountcode);
- ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ", ast_cdr_flags2str(user->amaflags));
- ast_cli(a->fd, "%-15.15s%s\n", "Context: ", user->context);
- ast_cli(a->fd, "%-15.15s%d\n", "IncomingLimit: ", user->incominglimit);
- ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", user->rtptimeout);
+ ast_cli(a->fd, "%s\n", "unknown");
+
+ ast_cli(a->fd,"%-15s", "T.38 Mode: ");
+ if (user->t38support == T38_DISABLED)
+ ast_cli(a->fd, "%s\n", "disabled");
+ else if (user->t38support == T38_FAXGW)
+ ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible");
+
+ ast_cli(a->fd, "%-15.15s%s\n", "AccountCode: ", user->accountcode);
+ ast_cli(a->fd, "%-15.15s%s\n", "AMA flags: ",
+ ast_cdr_flags2str(user->amaflags));
+ ast_cli(a->fd, "%-15.15s%s\n", "Context: ", user->context);
+ ast_cli(a->fd, "%-15.15s%d\n", "IncomingLimit: ", user->incominglimit);
+ ast_cli(a->fd, "%-15.15s%d\n", "InUse: ", user->inUse);
+ ast_cli(a->fd, "%-15.15s%d\n", "rtptimeout: ", user->rtptimeout);
+ if (user->rtpmaskstr[0])
+ ast_cli(a->fd, "%-15.15s%s\n", "rtpmask: ", user->rtpmaskstr);
ast_mutex_unlock(&user->lock);
} else {
- ast_cli(a->fd, "User %s not found\n", a->argv[3]);
- ast_cli(a->fd, "\n");
+ ast_cli(a->fd, "User %s not found\n", a->argv[3]);
+ ast_cli(a->fd, "\n");
}
ast_mutex_unlock(&userl.lock);
@@ -2174,9 +2862,8 @@ static char *handle_cli_ooh323_show_user(struct ast_cli_entry *e, int cmd, struc
static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- char formats[512];
struct ooh323_user *prev = NULL, *user = NULL;
-
+ char formats[FORMAT_STRING_SIZE];
#define FORMAT1 "%-15.15s %-15.15s %-15.15s %-s\n"
switch (cmd) {
@@ -2193,24 +2880,26 @@ static char *handle_cli_ooh323_show_users(struct ast_cli_entry *e, int cmd, stru
if (a->argc != 3)
return CLI_SHOWUSAGE;
- ast_cli(a->fd, FORMAT1, "Username", "Accountcode", "Context", "Formats");
+
+ ast_cli(a->fd, FORMAT1, "Username", "Accountcode", "Context", "Formats");
ast_mutex_lock(&userl.lock);
user = userl.users;
- while (user) {
+ while(user)
+ {
ast_mutex_lock(&user->lock);
- ast_cli(a->fd, FORMAT1, user->name,
+ ast_cli(a->fd, FORMAT1, user->name,
user->accountcode, user->context,
- ast_getformatname_multiple(formats, 512, user->capability));
+ ast_getformatname_multiple(formats, FORMAT_STRING_SIZE, user->capability));
prev = user;
user = user->next;
ast_mutex_unlock(&prev->lock);
+
}
ast_mutex_unlock(&userl.lock);
-
#undef FORMAT1
+ return RESULT_SUCCESS;
- return CLI_SUCCESS;
}
static char *handle_cli_ooh323_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -2246,7 +2935,7 @@ static int ooh323_show_channels(int fd, int argc, char *argv[])
static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- char value[512];
+ char value[FORMAT_STRING_SIZE];
ooAliases *pAlias = NULL, *pAliasNext = NULL;;
switch (cmd) {
@@ -2263,25 +2952,27 @@ static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, str
if (a->argc != 3)
return CLI_SHOWUSAGE;
- snprintf(value, sizeof(value), "%s:%d", gIP, gPort);
- ast_cli(a->fd, "\nObjective Open H.323 Channel Driver's Config:\n");
- ast_cli(a->fd, "%-20s%s\n", "IP:Port: ", value);
- ast_cli(a->fd, "%-20s%s\n", "FastStart", gFastStart?"yes":"no");
- ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no");
- ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID);
- ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect", gMediaWaitForConnect ? "yes" : "no");
-#if 0
- {
- extern OOH323EndPoint gH323ep;
- ast_cli(a->fd, "%-20s%s\n", "FASTSTART",
+ ast_cli(a->fd, "\nObjective Open H.323 Channel Driver's Config:\n");
+ snprintf(value, sizeof(value), "%s:%d", gIP, gPort);
+ ast_cli(a->fd, "%-20s%s\n", "IP:Port: ", value);
+ ast_cli(a->fd, "%-20s%d-%d\n", "H.225 port range: ",
+ ooconfig.mTCPPortStart, ooconfig.mTCPPortEnd);
+ ast_cli(a->fd, "%-20s%s\n", "FastStart", gFastStart?"yes":"no");
+ ast_cli(a->fd, "%-20s%s\n", "Tunneling", gTunneling?"yes":"no");
+ ast_cli(a->fd, "%-20s%s\n", "CallerId", gCallerID);
+ ast_cli(a->fd, "%-20s%s\n", "MediaWaitForConnect",
+ gMediaWaitForConnect?"yes":"no");
+
+#if (0)
+ extern OOH323EndPoint gH323ep;
+ ast_cli(a->fd, "%-20s%s\n", "FASTSTART",
(OO_TESTFLAG(gH323ep.flags, OO_M_FASTSTART) != 0) ? "yes" : "no");
- ast_cli(a->fd, "%-20s%s\n", "TUNNELING",
+ ast_cli(a->fd, "%-20s%s\n", "TUNNELING",
(OO_TESTFLAG(gH323ep.flags, OO_M_TUNNELING) != 0) ? "yes" : "no");
- ast_cli(a->fd, "%-20s%s\n", "MEDIAWAITFORCONN",
+ ast_cli(a->fd, "%-20s%s\n", "MEDIAWAITFORCONN",
(OO_TESTFLAG(gH323ep.flags, OO_M_MEDIAWAITFORCONN) != 0) ? "yes" : "no");
- }
#endif
if (gRasGkMode == RasNoGatekeeper)
@@ -2291,38 +2982,61 @@ static char *handle_cli_ooh323_show_config(struct ast_cli_entry *e, int cmd, str
else
snprintf(value, sizeof(value), "%s", gGatekeeper);
- ast_cli(a->fd, "%-20s%s\n", "Gatekeeper:", value);
- ast_cli(a->fd, "%-20s%s\n", "H.323 LogFile:", gLogFile);
- ast_cli(a->fd, "%-20s%s\n", "Context:", gContext);
- ast_cli(a->fd, "%-20s%s\n", "Capability:", ast_getformatname_multiple(value, sizeof(value), gCapability));
- ast_cli(a->fd, "%-20s", "DTMF Mode: ");
- if (gDTMFMode & H323_DTMF_RFC2833)
- ast_cli(a->fd, "%s\n", "rfc2833");
- else if (gDTMFMode & H323_DTMF_Q931)
- ast_cli(a->fd, "%s\n", "q931keypad");
+ ast_cli(a->fd, "%-20s%s\n", "Gatekeeper:", value);
+
+ ast_cli(a->fd, "%-20s%s\n", "H.323 LogFile:", gLogFile);
+
+ ast_cli(a->fd, "%-20s%s\n", "Context:", gContext);
+
+ ast_cli(a->fd, "%-20s%s\n", "Capability:",
+ ast_getformatname_multiple(value,FORMAT_STRING_SIZE,gCapability));
+
+ ast_cli(a->fd, "%-20s", "DTMF Mode: ");
+ if (gDTMFMode & H323_DTMF_CISCO) {
+ ast_cli(a->fd, "%s\n", "cisco");
+ ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", gDTMFCodec);
+ } else if (gDTMFMode & H323_DTMF_RFC2833) {
+ ast_cli(a->fd, "%s\n", "rfc2833");
+ ast_cli(a->fd, "%-15.15s%d\n", "DTMF Codec: ", gDTMFCodec);
+ } else if (gDTMFMode & H323_DTMF_Q931)
+ ast_cli(a->fd, "%s\n", "q931keypad");
else if (gDTMFMode & H323_DTMF_H245ALPHANUMERIC)
- ast_cli(a->fd, "%s\n", "h245alphanumeric");
+ ast_cli(a->fd, "%s\n", "h245alphanumeric");
else if (gDTMFMode & H323_DTMF_H245SIGNAL)
- ast_cli(a->fd, "%s\n", "h245signal");
+ ast_cli(a->fd, "%s\n", "h245signal");
+ else if (gDTMFMode & H323_DTMF_INBAND && gDTMFMode & H323_DTMF_INBANDRELAX)
+ ast_cli(a->fd, "%s\n", "inband-relaxed");
+ else if (gDTMFMode & H323_DTMF_INBAND)
+ ast_cli(a->fd, "%s\n", "inband");
else
ast_cli(a->fd, "%s\n", "unknown");
- ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode);
- ast_cli(a->fd, "%-20s%s\n", "AMA flags: ", ast_cdr_flags2str(gAMAFLAGS));
+
+ ast_cli(a->fd,"%-20s", "T.38 Mode: ");
+ if (gT38Support == T38_DISABLED)
+ ast_cli(a->fd, "%s\n", "disabled");
+ else if (gT38Support == T38_FAXGW)
+ ast_cli(a->fd, "%s\n", "faxgw/chan_sip compatible");
+
+ ast_cli(a->fd, "%-20s%ld\n", "Call counter: ", callnumber);
+ ast_cli(a->fd, "%-20s%s\n", "AccountCode: ", gAccountcode);
+
+ ast_cli(a->fd, "%-20s%s\n", "AMA flags: ", ast_cdr_flags2str(gAMAFLAGS));
pAlias = gAliasList;
- if (pAlias)
- ast_cli(a->fd, "%-20s\n", "Aliases: ");
+ if(pAlias) {
+ ast_cli(a->fd, "%-20s\n", "Aliases: ");
+ }
while (pAlias) {
pAliasNext = pAlias->next;
if (pAliasNext) {
- ast_cli(a->fd, "\t%-30s\t%-30s\n", pAlias->value, pAliasNext->value);
+ ast_cli(a->fd,"\t%-30s\t%-30s\n",pAlias->value, pAliasNext->value);
pAlias = pAliasNext->next;
- } else {
- ast_cli(a->fd, "\t%-30s\n", pAlias->value);
+ }
+ else{
+ ast_cli(a->fd,"\t%-30s\n",pAlias->value);
pAlias = pAlias->next;
}
}
-
return CLI_SUCCESS;
}
@@ -2333,8 +3047,10 @@ static struct ast_cli_entry cli_ooh323[] = {
AST_CLI_DEFINE(handle_cli_ooh323_show_peers, "Show defined OOH323 peers"),
AST_CLI_DEFINE(handle_cli_ooh323_show_user, "Show details on specific OOH323 user"),
AST_CLI_DEFINE(handle_cli_ooh323_show_users, "Show defined OOH323 users"),
+ AST_CLI_DEFINE(handle_cli_ooh323_reload, "reload ooh323 config")
};
+
static int load_module(void)
{
int res;
@@ -2345,12 +3061,14 @@ static int load_module(void)
OOH323CALLBACKS h323Callbacks = {
.onNewCallCreated = onNewCallCreated,
.onAlerting = onAlerting,
+ .onProgress = onProgress,
.onIncomingCall = NULL,
- .onOutgoingCall = NULL,
+ .onOutgoingCall = onOutgoingCall,
.onCallEstablished = onCallEstablished,
.onCallCleared = onCallCleared,
.openLogicalChannels = NULL,
- .onReceivedDTMF = &ooh323_onReceivedDigit
+ .onReceivedDTMF = ooh323_onReceivedDigit,
+ .onModeChanged = onModeChanged
};
ast_log(LOG_NOTICE,
@@ -2361,6 +3079,8 @@ static int load_module(void)
"---\n"
"---------------------------------------------------------------------------------\n");
+ myself = ast_module_info->self;
+
h225Callbacks.onReceivedSetup = &ooh323_onReceivedSetup;
userl.users = NULL;
@@ -2386,24 +3106,33 @@ static int load_module(void)
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
return 0;
}
- ast_rtp_proto_register(&ooh323_rtp);
+ ast_rtp_glue_register(&ooh323_rtp);
+ ast_udptl_proto_register(&ooh323_udptl);
ast_cli_register_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
/* fire up the H.323 Endpoint */
if (OO_OK != ooH323EpInitialize(OO_CALLMODE_AUDIOCALL, gLogFile)) {
- ast_log(LOG_ERROR, "Failed to initialize OOH323 endpoint-OOH323 Disabled\n");
+ ast_log(LOG_ERROR, "Failed to initialize OOH323 endpoint-"
+ "OOH323 Disabled\n");
return 1;
}
if (gIsGateway)
ooH323EpSetAsGateway();
+ ooH323EpSetVersionInfo(t35countrycode, t35extensions, manufacturer,
+ vendor, version);
ooH323EpDisableAutoAnswer();
ooH323EpSetH225MsgCallbacks(h225Callbacks);
- ooH323EpSetTraceLevel(OOTRCLVLDBGC);
+ ooH323EpSetTraceLevel(gTRCLVL);
ooH323EpSetLocalAddress(gIP, gPort);
ooH323EpSetCallerID(gCallerID);
+ if(ooH323EpSetTCPPortRange(ooconfig.mTCPPortStart,
+ ooconfig.mTCPPortEnd) == OO_FAILED) {
+ ast_log(LOG_ERROR, "h225portrange: Failed to set range\n");
+ }
+
/* Set aliases if any */
for (pNewAlias = gAliasList; pNewAlias; pNewAlias = pNewAlias->next) {
switch (pNewAlias->type) {
@@ -2416,20 +3145,18 @@ static int load_module(void)
case T_H225AliasAddress_email_ID:
ooH323EpAddAliasEmailID(pNewAlias->value);
break;
+ default:
+ ;
}
}
ast_mutex_lock(&peerl.lock);
peer = peerl.peers;
while (peer) {
- if (peer->h323id)
- ooH323EpAddAliasH323ID(peer->h323id);
- if (peer->email)
- ooH323EpAddAliasEmailID(peer->email);
- if (peer->e164)
- ooH323EpAddAliasDialedDigits(peer->e164);
- if (peer->url)
- ooH323EpAddAliasURLID(peer->url);
+ if(peer->h323id) ooH323EpAddAliasH323ID(peer->h323id);
+ if(peer->email) ooH323EpAddAliasEmailID(peer->email);
+ if(peer->e164) ooH323EpAddAliasDialedDigits(peer->e164);
+ if(peer->url) ooH323EpAddAliasURLID(peer->url);
peer = peer->next;
}
ast_mutex_unlock(&peerl.lock);
@@ -2449,6 +3176,11 @@ static int load_module(void)
if (!gTunneling)
ooH323EpDisableH245Tunneling();
+ if (gBeMaster)
+ ooH323EpTryBeMaster(1);
+
+ ooH323EpEnableManualRingback();
+
/* Gatekeeper */
if (gRasGkMode == RasUseSpecificGatekeeper)
ooGkClientInit(gRasGkMode, gGatekeeper, 0);
@@ -2459,22 +3191,23 @@ static int load_module(void)
ooH323EpSetH323Callbacks(h323Callbacks);
/* Add endpoint capabilities */
- if (ooh323c_set_capability(&gPrefs, gCapability, gDTMFMode) < 0) {
+ if (ooh323c_set_capability(&gPrefs, gCapability, gDTMFMode, gDTMFCodec) < 0) {
ast_log(LOG_ERROR, "Capabilities failure for OOH323. OOH323 Disabled.\n");
return 1;
}
-
/* Create H.323 listener */
if (ooCreateH323Listener() != OO_OK) {
- ast_log(LOG_ERROR, "OOH323 Listener Creation failure. OOH323 DISABLED\n");
+ ast_log(LOG_ERROR, "OOH323 Listener Creation failure. "
+ "OOH323 DISABLED\n");
ooH323EpDestroy();
return 1;
}
if (ooh323c_start_stack_thread() < 0) {
- ast_log(LOG_ERROR, "Failed to start OOH323 stack thread. OOH323 DISABLED\n");
+ ast_log(LOG_ERROR, "Failed to start OOH323 stack thread. "
+ "OOH323 DISABLED\n");
ooH323EpDestroy();
return 1;
}
@@ -2504,6 +3237,7 @@ static void *do_monitor(void *data)
ast_verb(1, "Reloading H.323\n");
ooh323_do_reload();
}
+
/* Check for interfaces needing to be killed */
ast_mutex_lock(&iflock);
time(&t);
@@ -2514,11 +3248,21 @@ static void *do_monitor(void *data)
/* TODO: Need to add rtptimeout keepalive support */
if (ast_test_flag(h323, H323_NEEDDESTROY)) {
ooh323_destroy (h323);
- }
+ } /* else if (ast_test_flag(h323, H323_NEEDSTART) && h323->owner) {
+ ast_channel_lock(h323->owner);
+ if (ast_pbx_start(h323->owner)) {
+ ast_log(LOG_WARNING, "Unable to start PBX on %s\n", h323->owner->name);
+ ast_channel_unlock(h323->owner);
+ ast_hangup(h323->owner);
+ }
+ ast_channel_unlock(h323->owner);
+ ast_clear_flag(h323, H323_NEEDSTART);
+ } */
h323 = h323_next;
}
ast_mutex_unlock(&iflock);
pthread_testcancel();
+
/* Wait for sched or io */
res = ast_sched_wait(sched);
if ((res < 0) || (res > 1000)) {
@@ -2575,7 +3319,7 @@ int ooh323_destroy(struct ooh323_pvt *p)
{
/* NOTE: Assumes iflock already acquired */
struct ooh323_pvt *prev = NULL, *cur = NULL;
-
+ struct ooh323_user *user = NULL;
if (gH323Debug) {
ast_verbose("--- ooh323_destroy \n");
@@ -2599,7 +3343,9 @@ int ooh323_destroy(struct ooh323_pvt *p)
iflist = cur->next;
if (cur->callToken) {
- free(cur->callToken);
+ if (gH323Debug)
+ ast_verbose(" Destroying %s\n", cur->callToken);
+ ast_free(cur->callToken);
cur->callToken = 0;
}
@@ -2623,29 +3369,54 @@ int ooh323_destroy(struct ooh323_pvt *p)
cur->callerid_num = 0;
}
-
if (cur->rtp) {
- ast_rtp_destroy(cur->rtp);
- cur->rtp = 0;
+ ast_rtp_instance_destroy(cur->rtp);
+ cur->rtp = NULL;
+ }
+
+ if (cur->udptl) {
+ ast_udptl_destroy(cur->udptl);
+ cur->udptl = NULL;
}
/* Unlink us from the owner if we have one */
if (cur->owner) {
- ast_channel_lock(cur->owner);
+ while(ast_channel_trylock(cur->owner)) {
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ DEADLOCK_AVOIDANCE(&cur->lock);
+ }
ast_debug(1, "Detaching from %s\n", cur->owner->name);
cur->owner->tech_pvt = NULL;
ast_channel_unlock(cur->owner);
cur->owner = NULL;
+ ast_module_unref(myself);
}
if (cur->vad) {
ast_dsp_free(cur->vad);
cur->vad = NULL;
}
+
+/* decrement user/peer count */
+
+ if(!ast_test_flag(cur, H323_OUTGOING)) {
+ if (cur->neighbor.user) {
+ user = find_user(p->callerid_name, cur->neighbor.user);
+ if(user && user->inUse > 0) {
+ ast_mutex_lock(&user->lock);
+ user->inUse--;
+ ast_mutex_unlock(&user->lock);
+ }
+ free(cur->neighbor.user);
+ }
+ } else {
+/* outgoing limit decrement here !!! */
+ }
+
ast_mutex_unlock(&cur->lock);
ast_mutex_destroy(&cur->lock);
- free(cur);
+ ast_free(cur);
}
if (gH323Debug)
@@ -2664,14 +3435,20 @@ int delete_peers()
cur = cur->next;
ast_mutex_destroy(&prev->lock);
- if (prev->h323id)
- free(prev->h323id);
- if (prev->email)
- free(prev->email);
- if (prev->url)
- free(prev->url);
- if (prev->e164)
- free(prev->e164);
+ if(prev->h323id) free(prev->h323id);
+ if(prev->email) free(prev->email);
+ if(prev->url) free(prev->url);
+ if(prev->e164) free(prev->e164);
+ if(prev->rtpmask) {
+ ast_mutex_lock(&prev->rtpmask->lock);
+ prev->rtpmask->inuse--;
+ ast_mutex_unlock(&prev->rtpmask->lock);
+ if (prev->rtpmask->inuse == 0) {
+ regfree(&prev->rtpmask->regex);
+ ast_mutex_destroy(&prev->rtpmask->lock);
+ free(prev->rtpmask);
+ }
+ }
free(prev);
if (cur == peerl.peers) {
@@ -2692,6 +3469,17 @@ int delete_users()
prev = cur;
cur = cur->next;
ast_mutex_destroy(&prev->lock);
+
+ if(prev->rtpmask) {
+ ast_mutex_lock(&prev->rtpmask->lock);
+ prev->rtpmask->inuse--;
+ ast_mutex_unlock(&prev->rtpmask->lock);
+ if (prev->rtpmask->inuse == 0) {
+ regfree(&prev->rtpmask->regex);
+ ast_mutex_destroy(&prev->rtpmask->lock);
+ free(prev->rtpmask);
+ }
+ }
free(prev);
if (cur == userl.users) {
break;
@@ -2712,9 +3500,9 @@ static int unload_module(void)
}
/* First, take us out of the channel loop */
ast_cli_unregister_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
- ast_rtp_proto_unregister(&ooh323_rtp);
+ ast_rtp_glue_unregister(&ooh323_rtp);
+ ast_udptl_proto_unregister(&ooh323_udptl);
ast_channel_unregister(&ooh323_tech);
-
#if 0
ast_unregister_atexit(&ast_ooh323c_exit);
#endif
@@ -2825,38 +3613,39 @@ static int unload_module(void)
-static enum ast_rtp_get_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
+static enum ast_rtp_glue_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp)
{
struct ooh323_pvt *p = NULL;
- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
+ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
if (!(p = (struct ooh323_pvt *) chan->tech_pvt))
- return AST_RTP_GET_FAILED;
-
- *rtp = p->rtp;
+ return AST_RTP_GLUE_RESULT_FORBID;
if (!(p->rtp)) {
- return AST_RTP_GET_FAILED;
+ return AST_RTP_GLUE_RESULT_FORBID;
}
- res = AST_RTP_TRY_NATIVE;
+
+ *rtp = p->rtp ? ao2_ref(p->rtp, +1), p->rtp : NULL;
+
+ res = AST_RTP_GLUE_RESULT_LOCAL;
return res;
}
-static enum ast_rtp_get_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp **rtp)
+static enum ast_rtp_glue_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp)
{
struct ooh323_pvt *p = NULL;
- enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL;
+ enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
if (!(p = (struct ooh323_pvt *) chan->tech_pvt))
- return AST_RTP_GET_FAILED;
-
- *rtp = p->vrtp;
+ return AST_RTP_GLUE_RESULT_FORBID;
if (!(p->rtp)) {
- return AST_RTP_GET_FAILED;
+ return AST_RTP_GLUE_RESULT_FORBID;
}
- res = AST_RTP_TRY_NATIVE;
+
+ *rtp = p->vrtp ? ao2_ref(p->vrtp, +1), p->vrtp : NULL;
+ res = AST_RTP_GLUE_RESULT_LOCAL;
return res;
}
@@ -2880,7 +3669,7 @@ int ooh323_update_capPrefsOrderForCall
int ooh323_convertAsteriskCapToH323Cap(int cap)
{
- char formats[512];
+ char formats[FORMAT_STRING_SIZE];
switch (cap) {
case AST_FORMAT_ULAW:
return OO_G711ULAW64K;
@@ -2888,21 +3677,35 @@ int ooh323_convertAsteriskCapToH323Cap(int cap)
return OO_G711ALAW64K;
case AST_FORMAT_GSM:
return OO_GSMFULLRATE;
+
+#ifdef AST_FORMAT_AMRNB
+ case AST_FORMAT_AMRNB:
+ return OO_AMRNB;
+#endif
+#ifdef AST_FORMAT_SPEEX
+ case AST_FORMAT_SPEEX:
+ return OO_SPEEX;
+#endif
+
case AST_FORMAT_G729A:
return OO_G729A;
+ case AST_FORMAT_G726:
+ return OO_G726;
+ case AST_FORMAT_G726_AAL2:
+ return OO_G726AAL2;
case AST_FORMAT_G723_1:
return OO_G7231;
case AST_FORMAT_H263:
return OO_H263VIDEO;
default:
ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n",
- ast_getformatname_multiple(formats, sizeof(formats), cap));
+ ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap));
return -1;
}
}
-static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
- struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
+static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp,
+ struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, int codecs, int nat_active)
{
/* XXX Deal with Video */
struct ooh323_pvt *p;
@@ -2923,8 +3726,8 @@ static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
return -1;
}
- ast_rtp_get_peer(rtp, &them);
- ast_rtp_get_us(rtp, &us);
+ ast_rtp_instance_get_remote_address(rtp, &them);
+ ast_rtp_instance_get_local_address(rtp, &us);
return 0;
}
@@ -2941,11 +3744,27 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
ast_verbose("--- configure_local_rtp\n");
if (p->rtp) {
- ast_rtp_codec_setpref(p->rtp, &p->prefs);
+ ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(p->rtp), p->rtp, &p->prefs);
+ if (p->dtmfmode & H323_DTMF_RFC2833 && p->dtmfcodec) {
+ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, 1);
+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
+ p->rtp, p->dtmfcodec, "audio", "telephone-event", 0);
+ }
+ if (p->dtmfmode & H323_DTMF_CISCO && p->dtmfcodec) {
+ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, 1);
+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
+ p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0);
+ }
+ /* figure out our local RTP port and tell the H.323 stack about it*/
+ ast_rtp_instance_get_local_address(p->rtp, &us);
+
+ if (p->rtptimeout) {
+ ast_rtp_instance_set_timeout(p->rtp, p->rtptimeout);
+ }
+ ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 1);
+
}
- /* figure out our local RTP port and tell the H.323 stack about it*/
- ast_rtp_get_us(p->rtp, &us);
ast_copy_string(mediaInfo.lMediaIP, ast_inet_ntoa(us.sin_addr), sizeof(mediaInfo.lMediaIP));
mediaInfo.lMediaPort = ntohs(us.sin_port);
@@ -2962,9 +3781,27 @@ int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
ooAddMediaInfo(call, mediaInfo);
strcpy(mediaInfo.dir, "receive");
ooAddMediaInfo(call, mediaInfo);
+
+ strcpy(mediaInfo.dir, "transmit");
+ mediaInfo.cap = OO_G729B;
+ ooAddMediaInfo(call, mediaInfo);
+ strcpy(mediaInfo.dir, "receive");
+ ooAddMediaInfo(call, mediaInfo);
}
}
+ if (p->udptl) {
+ ast_udptl_get_us(p->udptl, &us);
+ }
+ ast_copy_string(mediaInfo.lMediaIP, ast_inet_ntoa(us.sin_addr), sizeof(mediaInfo.lMediaIP));
+ mediaInfo.lMediaPort = ntohs(us.sin_port);
+ mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort +1;
+ mediaInfo.cap = OO_T38;
+ strcpy(mediaInfo.dir, "transmit");
+ ooAddMediaInfo(call, mediaInfo);
+ strcpy(mediaInfo.dir, "receive");
+ ooAddMediaInfo(call, mediaInfo);
+
if (gH323Debug)
ast_verbose("+++ configure_local_rtp\n");
@@ -2978,7 +3815,7 @@ void setup_rtp_connection(ooCallData *call, const char *remoteIp,
struct sockaddr_in them;
if (gH323Debug)
- ast_verbose("--- setup_rtp_connection\n");
+ ast_verbose("--- setup_rtp_connection %s:%d\n", remoteIp, remotePort);
/* Find the call or allocate a private structure if call not found */
p = find_call(call);
@@ -2991,11 +3828,14 @@ void setup_rtp_connection(ooCallData *call, const char *remoteIp,
them.sin_family = AF_INET;
them.sin_addr.s_addr = inet_addr(remoteIp); /* only works for IPv4 */
them.sin_port = htons(remotePort);
- ast_rtp_set_peer(p->rtp, &them);
+ ast_rtp_instance_set_remote_address(p->rtp, &them);
- if (gH323Debug) {
+ if (p->writeformat & AST_FORMAT_G726_AAL2)
+ ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, 2,
+ "audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
+
+ if(gH323Debug)
ast_verbose("+++ setup_rtp_connection\n");
- }
return;
}
@@ -3004,28 +3844,169 @@ void close_rtp_connection(ooCallData *call)
{
struct ooh323_pvt *p = NULL;
- if (gH323Debug) {
+ if(gH323Debug)
ast_verbose("--- close_rtp_connection\n");
- }
p = find_call(call);
if (!p) {
- ast_log(LOG_ERROR, "Couldn't find matching call to close rtp connection\n");
+ ast_log(LOG_ERROR, "Couldn't find matching call to close rtp "
+ "connection\n");
return;
}
ast_mutex_lock(&p->lock);
if (p->rtp) {
- ast_rtp_stop(p->rtp);
+ ast_rtp_instance_stop(p->rtp);
}
ast_mutex_unlock(&p->lock);
- if (gH323Debug) {
+ if(gH323Debug)
ast_verbose("+++ close_rtp_connection\n");
+
+ return;
+}
+
+/*
+ udptl handling functions
+ */
+
+static struct ast_udptl *ooh323_get_udptl_peer(struct ast_channel *chan)
+{
+ struct ooh323_pvt *p;
+ struct ast_udptl *udptl = NULL;
+
+ p = chan->tech_pvt;
+ if (!p)
+ return NULL;
+
+ ast_mutex_lock(&p->lock);
+ if (p->udptl)
+ udptl = p->udptl;
+ ast_mutex_unlock(&p->lock);
+ return udptl;
+}
+
+static int ooh323_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl)
+{
+ struct ooh323_pvt *p;
+
+ p = chan->tech_pvt;
+ if (!p)
+ return -1;
+ ast_mutex_lock(&p->lock);
+ if (udptl)
+ ast_udptl_get_peer(udptl, &p->udptlredirip);
+ else
+ memset(&p->udptlredirip, 0, sizeof(p->udptlredirip));
+
+ ast_mutex_unlock(&p->lock);
+ return 0;
+}
+
+void setup_udptl_connection(ooCallData *call, const char *remoteIp,
+ int remotePort)
+{
+ struct ooh323_pvt *p = NULL;
+ struct sockaddr_in them;
+
+ if (gH323Debug)
+ ast_verbose("--- setup_udptl_connection\n");
+
+ /* Find the call or allocate a private structure if call not found */
+ p = find_call(call);
+
+ if (!p) {
+ ast_log(LOG_ERROR, "Something is wrong: rtp\n");
+ return;
+ }
+
+ ast_mutex_lock(&p->lock);
+ if (p->owner) {
+ while (p->owner && ast_channel_trylock(p->owner)) {
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ DEADLOCK_AVOIDANCE(&p->lock);
+ }
+ if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return;
+ }
+ } else {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return;
+ }
+
+ them.sin_family = AF_INET;
+ them.sin_addr.s_addr = inet_addr(remoteIp); /* only works for IPv4 */
+ them.sin_port = htons(remotePort);
+ ast_udptl_set_peer(p->udptl, &them);
+ p->t38_tx_enable = 1;
+ p->lastTxT38 = time(NULL);
+ if (p->t38support == T38_ENABLED) {
+ struct ast_control_t38_parameters parameters = { .request_response = 0 };
+ parameters.request_response = AST_T38_NEGOTIATED;
+ ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
+ }
+ if (gH323Debug)
+ ast_debug(1, "Receiving UDPTL %s:%d\n", ast_inet_ntoa(them.sin_addr),
+ ntohs(them.sin_port));
+
+ ast_channel_unlock(p->owner);
+ ast_mutex_unlock(&p->lock);
+
+ if(gH323Debug)
+ ast_verbose("+++ setup_udptl_connection\n");
+
+ return;
+}
+
+void close_udptl_connection(ooCallData *call)
+{
+ struct ooh323_pvt *p = NULL;
+
+ if(gH323Debug)
+ ast_verbose("--- close_udptl_connection\n");
+
+ p = find_call(call);
+ if (!p) {
+ ast_log(LOG_ERROR, "Couldn't find matching call to close udptl "
+ "connection\n");
+ return;
}
+ ast_mutex_lock(&p->lock);
+ if (p->owner) {
+ while (p->owner && ast_channel_trylock(p->owner)) {
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ DEADLOCK_AVOIDANCE(&p->lock);
+ }
+ if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return;
+ }
+ } else {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return;
+ }
+
+ p->t38_tx_enable = 0;
+ if (p->t38support == T38_ENABLED) {
+ struct ast_control_t38_parameters parameters = { .request_response = 0 };
+ parameters.request_response = AST_T38_TERMINATED;
+ ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
+ }
+
+ ast_channel_unlock(p->owner);
+ ast_mutex_unlock(&p->lock);
+
+ if(gH323Debug)
+ ast_verbose("+++ close_udptl_connection\n");
return;
}
+/* end of udptl handling */
int update_our_aliases(ooCallData *call, struct ooh323_pvt *p)
{
@@ -3040,7 +4021,8 @@ int update_our_aliases(ooCallData *call, struct ooh323_pvt *p)
updated = 1;
}
if (psAlias->type == T_H225AliasAddress_dialedDigits) {
- ast_copy_string(p->callee_dialedDigits, psAlias->value, sizeof(p->callee_dialedDigits));
+ ast_copy_string(p->callee_dialedDigits, psAlias->value,
+ sizeof(p->callee_dialedDigits));
updated = 1;
}
if (psAlias->type == T_H225AliasAddress_url_ID) {
@@ -3062,44 +4044,118 @@ struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p)
static struct ast_frame null_frame = { AST_FRAME_NULL, };
switch (ast->fdno) {
case 0:
- f = ast_rtp_read(p->rtp); /* RTP Audio */
+ f = ast_rtp_instance_read(p->rtp, 0); /* RTP Audio */
break;
case 1:
- f = ast_rtcp_read(p->rtp); /* RTCP Control Channel */
+ f = ast_rtp_instance_read(p->rtp, 1); /* RTCP Control Channel */
break;
case 2:
- f = ast_rtp_read(p->vrtp); /* RTP Video */
+ f = ast_rtp_instance_read(p->vrtp, 0); /* RTP Video */
break;
case 3:
- f = ast_rtcp_read(p->vrtp); /* RTCP Control Channel for video */
+ f = ast_rtp_instance_read(p->vrtp, 1); /* RTCP Control Channel for video */
+ break;
+ case 5:
+ f = ast_udptl_read(p->udptl); /* UDPTL t.38 data */
+ if (gH323Debug) ast_debug(1, "Got UDPTL %d/%d len %d for %s\n",
+ f->frametype, f->subclass, f->datalen, ast->name);
break;
+
default:
f = &null_frame;
}
- /* Don't send RFC2833 if we're not supposed to */
- if (f && (f->frametype == AST_FRAME_DTMF) && !(p->dtmfmode & H323_DTMF_RFC2833)) {
- return &null_frame;
- }
+
if (p->owner) {
/* We already hold the channel lock */
- if (f->frametype == AST_FRAME_VOICE) {
+ if (f->frametype == AST_FRAME_VOICE && !p->faxmode) {
if (f->subclass != p->owner->nativeformats) {
- ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
+ ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
p->owner->nativeformats = f->subclass;
ast_set_read_format(p->owner, p->owner->readformat);
ast_set_write_format(p->owner, p->owner->writeformat);
}
- if ((p->dtmfmode & H323_DTMF_INBAND) && p->vad) {
+
+ if ((p->dtmfmode & H323_DTMF_INBAND) && p->vad &&
+ (f->subclass == AST_FORMAT_SLINEAR || f->subclass == AST_FORMAT_ALAW ||
+ f->subclass == AST_FORMAT_ULAW)) {
f = ast_dsp_process(p->owner, p->vad, f);
- if (f && (f->frametype == AST_FRAME_DTMF)) {
- ast_debug(1, "* Detected inband DTMF '%c'\n", f->subclass);
- }
+ if (f && (f->frametype == AST_FRAME_DTMF))
+ ast_debug(1, "* Detected inband DTMF '%c'\n",f->subclass);
}
}
}
return f;
}
+void onModeChanged(ooCallData *call, int t38mode) {
+ struct ooh323_pvt *p;
+
+ p = find_call(call);
+ if (!p) {
+ ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
+ return;
+ }
+
+ ast_mutex_lock(&p->lock);
+
+ if (gH323Debug)
+ ast_debug(1, "change mode to %d for %s\n", t38mode, call->callToken);
+
+ if (t38mode == p->faxmode) {
+ if (gH323Debug)
+ ast_debug(1, "mode for %s is already %d\n", call->callToken,
+ t38mode);
+ ast_mutex_unlock(&p->lock);
+ return;
+ }
+
+ if (p->owner) {
+ while (p->owner && ast_channel_trylock(p->owner)) {
+ ast_debug(1,"Failed to grab lock, trying again\n");
+ DEADLOCK_AVOIDANCE(&p->lock);
+ }
+ if (!p->owner) {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return;
+ }
+ } else {
+ ast_mutex_unlock(&p->lock);
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return;
+ }
+
+ if (t38mode) {
+
+
+ if (p->t38support == T38_ENABLED) {
+
+/* AST_T38_CONTROL mode */
+
+ struct ast_control_t38_parameters parameters = { .request_response = 0 };
+ parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
+ ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS,
+ &parameters, sizeof(parameters));
+ p->faxmode = 1;
+
+ }
+ } else {
+ if (p->t38support == T38_ENABLED) {
+ struct ast_control_t38_parameters parameters = { .request_response = 0 };
+ parameters.request_response = AST_T38_REQUEST_TERMINATE;
+ ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS,
+ &parameters, sizeof(parameters));
+ }
+ p->faxmode = 0;
+ p->t38_init = 0;
+ }
+
+ p->chmodepend = 0;
+ ast_channel_unlock(p->owner);
+ ast_mutex_unlock(&p->lock);
+}
+
+
int ooh323_convert_hangupcause_asteriskToH323(int cause)
{
@@ -3124,6 +4180,8 @@ int ooh323_convert_hangupcause_asteriskToH323(int cause)
}
return 0;
+
+
}
int ooh323_convert_hangupcause_h323ToAsterisk(int cause)