aboutsummaryrefslogtreecommitdiffstats
path: root/addons/chan_ooh323.c
diff options
context:
space:
mode:
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)