Newer
Older
/*
* Copyright (C) 2004-2005 by Objective Systems, Inc.
*
* This software is furnished under an open source license and may be
* used and copied only in accordance with the terms of this license.
* The text of the license may generally be found in the root
* directory of this installation in the COPYING file. It
* can also be viewed online at the following URL:
*
* http://www.obj-sys.com/open/license.html
*
* Any redistributions of this file including modified versions must
* maintain this copyright notice.
*
*****************************************************************************/
/* Reworked version I, Nov-2009, by Alexandr Anikin, may@telecom-service.ru */
/*** MODULEINFO
<defaultenabled>no</defaultenabled>
<support_level>extended</support_level>
#include "chan_ooh323.h"
/* Defaults */
#define DEFAULT_CONTEXT "default"
#define DEFAULT_H323ID "Asterisk PBX"
#define DEFAULT_LOGFILE "/var/log/asterisk/h323_log"
#define DEFAULT_H323ACCNT "ast_h323"
/* Flags */
#define H323_SILENCESUPPRESSION (1<<0)
#define H323_GKROUTED (1<<1)
#define H323_TUNNELING (1<<2)
#define H323_FASTSTART (1<<3)
#define H323_OUTGOING (1<<4)
#define H323_ALREADYGONE (1<<5)
#define H323_NEEDDESTROY (1<<6)
#define H323_DISABLEGK (1<<7)
#define H323_NEEDSTART (1<<8)
#define MAXT30 240
#define T38TOAUDIOTIMEOUT 30
#define T38_DISABLED 0
#define T38_ENABLED 1
#define T38_FAXGW 1
#define FAXDETECT_CNG 1
#define FAXDETECT_T38 2
/* Channel description */
static const char type[] = "OOH323";
static const char tdesc[] = "Objective Systems H323 Channel Driver";
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, struct ast_format_cap *cap,
const struct ast_channel *requestor, const char *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, const char *dest, int timeout);
static int ooh323_hangup(struct ast_channel *ast);
static int ooh323_answer(struct ast_channel *ast);
static struct ast_frame *ooh323_read(struct ast_channel *ast);
static int ooh323_write(struct ast_channel *ast, struct ast_frame *f);
static int ooh323_indicate(struct ast_channel *ast, int condition, 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 int function_ooh323_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
static int function_ooh323_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);
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, const struct ast_format_cap *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);
struct ooh323_peer *find_friend(const char *name, int port);
static struct ast_channel_tech ooh323_tech = {
.type = type,
.description = tdesc,
.properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
.requester = ooh323_request,
.send_digit_begin = ooh323_digit_begin,
.send_digit_end = ooh323_digit_end,
.call = ooh323_call,
.hangup = ooh323_hangup,
.answer = ooh323_answer,
.read = ooh323_read,
.write = ooh323_write,
.exception = ooh323_read,
.indicate = ooh323_indicate,
.fixup = ooh323_fixup,
.send_html = 0,
.queryoption = ooh323_queryoption,
.bridge = ast_rtp_instance_bridge, /* XXX chan unlocked ? */
.early_bridge = ast_rtp_instance_early_bridge,
.func_channel_read = function_ooh323_read,
.func_channel_write = function_ooh323_write,
};
static struct ast_rtp_glue ooh323_rtp = {
.type = type,
.get_rtp_info = ooh323_get_rtp_peer,
.get_vrtp_info = ooh323_get_vrtp_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,
};
/* H.323 channel private structure */
static struct ooh323_pvt {
ast_mutex_t lock; /* Channel private lock */
struct ast_rtp_instance *rtp;
struct ast_rtp_instance *vrtp; /* Placeholder for now */
int t38support; /* T.38 mode - disable, transparent, faxgw */
int faxdetect;
int faxdetected;
int rtptimeout;
struct ast_udptl *udptl;
int faxmode;
int t38_tx_enable;
int t38_init;
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;
unsigned int call_reference;
char *callToken;
char *username;
char *host;
char *callerid_name;
char *callerid_num;
char caller_h323id[AST_MAX_EXTENSION];
char caller_dialedDigits[AST_MAX_EXTENSION];
char caller_email[AST_MAX_EXTENSION];
char caller_url[256];
char callee_h323id[AST_MAX_EXTENSION];
char callee_dialedDigits[AST_MAX_EXTENSION];
char callee_email[AST_MAX_EXTENSION];
char callee_url[AST_MAX_EXTENSION];
int port;
struct ast_format readformat; /* negotiated read format */
struct ast_format writeformat; /* negotiated write format */
struct ast_format_cap *cap;
struct ast_codec_pref prefs;
int dtmfmode;
char exten[AST_MAX_EXTENSION]; /* Requested extension */
char context[AST_MAX_EXTENSION]; /* Context where to start */
char accountcode[256]; /* Account code */
int nat;
int amaflags;
int progsent; /* progress is sent */
int alertsent; /* alerting is sent */
int g729onlyA; /* G.729 only A */
struct ast_dsp *vad;
struct OOH323Regex *rtpmask; /* rtp ip regexp */
char rtpmaskstr[120];
int rtdrcount, rtdrinterval; /* roundtripdelayreq */
int faststart, h245tunneling; /* faststart & h245 tunneling */
struct ooh323_pvt *next; /* Next entity */
} *iflist = NULL;
/* Protect the channel/interface list (ooh323_pvt) */
AST_MUTEX_DEFINE_STATIC(iflock);
/* Profile of H.323 user registered with PBX*/
struct ooh323_user{
ast_mutex_t lock;
char name[256];
char context[AST_MAX_EXTENSION];
int incominglimit;
unsigned inUse;
char accountcode[20];
int amaflags;
struct ast_format_cap *cap;
struct ast_codec_pref prefs;
int dtmfmode;
int dtmfcodec;
int faxdetect;
int t38support;
int rtptimeout;
int mUseIP; /* Use IP address or H323-ID to search user */
char mIP[4*8+7+2]; /* Max for IPv6 - 2 brackets, 8 4hex, 7 - : */
struct OOH323Regex *rtpmask;
char rtpmaskstr[120];
int rtdrcount, rtdrinterval;
int faststart, h245tunneling;
int g729onlyA;
struct ooh323_user *next;
};
/* Profile of valid asterisk peers */
struct ooh323_peer{
ast_mutex_t lock;
char name[256];
unsigned outgoinglimit;
unsigned outUse;
struct ast_format_cap *cap;
struct ast_codec_pref prefs;
char accountcode[20];
int amaflags;
int dtmfmode;
int mFriend; /* indicates defined as friend */
char ip[4*8+7+2]; /* Max for IPv6 - 2 brackets, 8 4hex, 7 - : */
int port;
char *h323id; /* H323-ID alias, which asterisk will register with gk to reach this peer*/
char *email; /* Email alias, which asterisk will register with gk to reach this peer*/
char *url; /* url alias, which asterisk will register with gk to reach this peer*/
char *e164; /* e164 alias, which asterisk will register with gk to reach this peer*/
int rtptimeout;
struct OOH323Regex *rtpmask;
char rtpmaskstr[120];
int rtdrcount,rtdrinterval;
int faststart, h245tunneling;
struct ooh323_peer *next;
};
/* List of H.323 users known to PBX */
static struct ast_user_list {
struct ooh323_user *users;
ast_mutex_t lock;
} userl;
static struct ast_peer_list {
struct ooh323_peer *peers;
ast_mutex_t lock;
} peerl;
/* Mutex to protect H.323 reload process */
static int h323_reloading = 0;
AST_MUTEX_DEFINE_STATIC(h323_reload_lock);
/* Mutex to protect usage counter */
static int usecnt = 0;
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[2+8*4+7]; /* Max for IPv6 addr */
struct ast_sockaddr bindaddr;
int v6mode = 0;
static char gCallerID[AST_MAX_EXTENSION] = "";
static struct ooAliases *gAliasList;
static struct ast_format_cap *gCap;
static struct ast_codec_pref gPrefs;
static int gDTMFMode = H323_DTMF_RFC2833;
static int gFAXdetect = FAXDETECT_CNG;
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 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 = 1024;
static int gOutgoingLimit = 1024;
OOBOOL gH323Debug = FALSE;
static int gTRCLVL = OOTRCLVLERR;
static int gRTDRCount = 0, gRTDRInterval = 0;
static int gNat = FALSE;
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
{
int mTCPPortStart;
int mTCPPortEnd;
} ooconfig;
/** Asterisk RTP stuff*/
static struct ast_sched_context *sched;
static struct io_context *io;
/* Protect the monitoring thread, so only one process can kill or start it,
and not when it's doing something critical. */
AST_MUTEX_DEFINE_STATIC(monlock);
/* This is the thread for the monitor which checks for input on the channels
which are not currently in use. */
static pthread_t monitor_thread = AST_PTHREADT_NULL;
static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
const char *host, struct ast_format_cap *cap, const char *linkedid)
{
struct ast_channel *ch = NULL;
struct ast_format tmpfmt;
Tilghman Lesher
committed
if (gH323Debug) {
ast_verb(0, "--- ooh323_new - %s\n", host);
}
ast_format_clear(&tmpfmt);
/* Don't hold a h323 pvt lock while we allocate a channel */
ast_mutex_unlock(&i->lock);
ast_mutex_lock(&ooh323c_cn_lock);
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);
callnumber++;
ast_mutex_unlock(&ooh323c_cn_lock);
ast_mutex_lock(&i->lock);
if (ch) {
ast_channel_lock(ch);
ch->tech = &ooh323_tech;
if (cap)
ast_best_codec(cap, &tmpfmt);
if (!tmpfmt.id)
ast_codec_pref_index(&i->prefs, 0, &tmpfmt);
ast_format_cap_add(ch->nativeformats, &tmpfmt);
ast_format_copy(&ch->rawwriteformat, &tmpfmt);
ast_format_copy(&ch->rawreadformat, &tmpfmt);
ast_jb_configure(ch, &global_jbconf);
if (state == AST_STATE_RING)
ch->rings = 1;
ch->adsicpe = AST_ADSI_UNAVAILABLE;
ast_set_write_format(ch, &tmpfmt);
ast_set_read_format(ch, &tmpfmt);
ch->tech_pvt = i;
i->owner = ch;
/* Allocate dsp for in-band DTMF support */
if ((i->dtmfmode & H323_DTMF_INBAND) || (i->faxdetect & FAXDETECT_CNG)) {
i->vad = ast_dsp_new();
/* inband DTMF*/
if (i->dtmfmode & H323_DTMF_INBAND) {
features |= DSP_FEATURE_DIGIT_DETECT;
if (i->dtmfmode & H323_DTMF_INBANDRELAX) {
ast_dsp_set_digitmode(i->vad, DSP_DIGITMODE_DTMF | DSP_DIGITMODE_RELAXDTMF);
}
}
/* fax detection*/
if (i->faxdetect & FAXDETECT_CNG) {
features |= DSP_FEATURE_FAX_DETECT;
ast_dsp_set_faxmode(i->vad,
DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED);
}
if (features) {
ast_dsp_set_features(i->vad, features);
}
ast_mutex_lock(&usecnt_lock);
usecnt++;
ast_mutex_unlock(&usecnt_lock);
/* Notify the module monitors that use count for resource has changed*/
ast_update_use_count();
ast_copy_string(ch->context, i->context, sizeof(ch->context));
ast_copy_string(ch->exten, i->exten, sizeof(ch->exten));
ch->priority = 1;
if(!ast_test_flag(i, H323_OUTGOING)) {
if (!ast_strlen_zero(i->caller_h323id)) {
pbx_builtin_setvar_helper(ch, "_CALLER_H323ID", i->caller_h323id);
}
if (!ast_strlen_zero(i->caller_dialedDigits)) {
pbx_builtin_setvar_helper(ch, "_CALLER_H323DIALEDDIGITS",
i->caller_dialedDigits);
}
if (!ast_strlen_zero(i->caller_email)) {
pbx_builtin_setvar_helper(ch, "_CALLER_H323EMAIL",
i->caller_email);
}
if (!ast_strlen_zero(i->caller_url)) {
pbx_builtin_setvar_helper(ch, "_CALLER_H323URL", i->caller_url);
}
}
if (!ast_strlen_zero(i->accountcode))
ast_channel_accountcode_set(ch, i->accountcode);
if (i->amaflags)
ch->amaflags = i->amaflags;
ast_setstate(ch, state);
if (state != AST_STATE_DOWN) {
ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(ch));
ast_hangup(ch);
ch = NULL;
}
}
manager_event(EVENT_FLAG_SYSTEM, "ChannelUpdate", "Channel: %s\r\nChanneltype: %s\r\n"
"CallRef: %d\r\n", ast_channel_name(ch), "OOH323", i->call_reference);
} else
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
Tilghman Lesher
committed
if (gH323Debug) {
ast_verb(0, "+++ h323_new\n");
}
return ch;
}
static struct ooh323_pvt *ooh323_alloc(int callref, char *callToken)
{
struct ooh323_pvt *pvt = NULL;
Tilghman Lesher
committed
if (gH323Debug) {
ast_verb(0, "--- ooh323_alloc\n");
}
if (!(pvt = ast_calloc(1, sizeof(*pvt)))) {
ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n");
return NULL;
}
if (!(pvt->cap = ast_format_cap_alloc_nolock())) {
ast_free(pvt);
ast_log(LOG_ERROR, "Couldn't allocate private ooh323 structure\n");
return NULL;
}
ast_mutex_init(&pvt->lock);
ast_mutex_lock(&pvt->lock);
pvt->chmodepend = 0;
pvt->faxdetected = 0;
pvt->faxdetect = gFAXdetect;
pvt->t38support = gT38Support;
pvt->rtptimeout = gRTPTimeout;
pvt->rtdrinterval = gRTDRInterval;
pvt->rtdrcount = gRTDRCount;
pvt->call_reference = callref;
if (callToken)
pvt->callToken = strdup(callToken);
/* whether to use gk for this call */
if (gRasGkMode == RasNoGatekeeper)
OO_SETFLAG(pvt->flags, H323_DISABLEGK);
pvt->dtmfmode = gDTMFMode;
ast_copy_string(pvt->context, gContext, sizeof(pvt->context));
ast_copy_string(pvt->accountcode, gAccountcode, sizeof(pvt->accountcode));
pvt->amaflags = gAMAFLAGS;
ast_format_cap_copy(pvt->cap, gCap);
memcpy(&pvt->prefs, &gPrefs, sizeof(pvt->prefs));
ast_mutex_unlock(&pvt->lock);
/* Add to interface list */
ast_mutex_lock(&iflock);
pvt->next = iflist;
iflist = pvt;
ast_mutex_unlock(&iflock);
Tilghman Lesher
committed
if (gH323Debug) {
ast_verb(0, "+++ ooh323_alloc\n");
}
return pvt;
}
/*
Possible data values - peername, exten/peername, exten@ip
*/
static struct ast_channel *ooh323_request(const char *type, struct ast_format_cap *cap,
const struct ast_channel *requestor, const char *data, int *cause)
{
struct ast_channel *chan = NULL;
struct ooh323_pvt *p = NULL;
struct ooh323_peer *peer = NULL;
char *dest = NULL;
char *ext = NULL;
char tmp[256];
char formats[FORMAT_STRING_SIZE];
int port = 0;
if (gH323Debug)
ast_verb(0, "--- ooh323_request - data %s format %s\n", data,
ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap));
if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO))) {
ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap));
return NULL;
}
p = ooh323_alloc(0,0); /* Initial callRef is zero */
if (!p) {
ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", data);
return NULL;
}
ast_mutex_lock(&p->lock);
/* This is an outgoing call, since ooh323_request is called */
ast_set_flag(p, H323_OUTGOING);
ast_copy_string(tmp, data, sizeof(tmp));
dest = strchr(tmp, '/');
if (dest) {
*dest = '\0';
dest++;
} else if ((dest = strchr(tmp, '@'))) {
*dest = '\0';
dest++;
ext = tmp;
} else {
dest = tmp;
ext = NULL;
}
#if 0
if ((sport = strchr(dest, ':'))) {
*sport = '\0';
sport++;
port = atoi(sport);
}
#endif
if (dest) {
peer = find_peer(dest, port);
} else{
ast_mutex_lock(&iflock);
ast_mutex_unlock(&p->lock);
ooh323_destroy(p);
ast_mutex_unlock(&iflock);
ast_log(LOG_ERROR, "Destination format is not supported\n");
return NULL;
}
if (peer) {
p->username = strdup(peer->name);
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); */
if (ext)
ast_copy_string(p->exten, ext, sizeof(p->exten));
ast_format_cap_copy(p->cap, peer->cap);
memcpy(&p->prefs, &peer->prefs, sizeof(struct ast_codec_pref));
p->g729onlyA = peer->g729onlyA;
p->dtmfmode |= peer->dtmfmode;
p->dtmfcodec = peer->dtmfcodec;
p->faxdetect = peer->faxdetect;
p->t38support = peer->t38support;
p->rtptimeout = peer->rtptimeout;
p->faststart = peer->faststart;
p->h245tunneling = peer->h245tunneling;
if (peer->rtpmask && peer->rtpmaskstr[0]) {
p->rtpmask = peer->rtpmask;
ast_copy_string(p->rtpmaskstr, peer->rtpmaskstr, sizeof(p->rtpmaskstr));
}
if (peer->rtdrinterval) {
p->rtdrinterval = peer->rtdrinterval;
p->rtdrcount = peer->rtdrcount;
}
ast_copy_string(p->accountcode, peer->accountcode, sizeof(p->accountcode));
p->amaflags = peer->amaflags;
} else {
if (gRasGkMode == RasNoGatekeeper) {
/* no gk and no peer */
ast_log(LOG_ERROR, "Call to undefined peer %s", dest);
ast_mutex_lock(&iflock);
ast_mutex_unlock(&p->lock);
ooh323_destroy(p);
ast_mutex_unlock(&iflock);
return NULL;
}
p->dtmfmode = gDTMFMode;
p->t38support = gT38Support;
p->rtptimeout = gRTPTimeout;
ast_format_cap_copy(p->cap, gCap);
p->rtdrinterval = gRTDRInterval;
p->rtdrcount = gRTDRCount;
p->faststart = gFastStart;
p->h245tunneling = gTunneling;
memcpy(&p->prefs, &gPrefs, sizeof(struct ast_codec_pref));
p->username = strdup(dest);
p->host = strdup(dest);
if (port > 0) {
p->port = port;
}
if (ext) {
ast_copy_string(p->exten, ext, sizeof(p->exten));
}
}
chan = ooh323_new(p, AST_STATE_DOWN, p->username, cap,
requestor ? ast_channel_linkedid(requestor) : NULL);
ast_mutex_unlock(&p->lock);
if (!chan) {
ast_mutex_lock(&iflock);
ooh323_destroy(p);
ast_mutex_unlock(&iflock);
} else {
ast_mutex_lock(&p->lock);
p->callToken = (char*)ast_calloc(1, 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();
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "+++ ooh323_request\n");
return chan;
}
static struct ooh323_pvt* find_call(ooCallData *call)
{
struct ooh323_pvt *p;
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- find_call\n");
ast_mutex_lock(&iflock);
for (p = iflist; p; p = p->next) {
if (p->callToken && !strcmp(p->callToken, call->callToken)) {
break;
}
}
ast_mutex_unlock(&iflock);
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "+++ find_call\n");
return p;
}
struct ooh323_user *find_user(const char * name, const char* ip)
{
struct ooh323_user *user;
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- 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;
}
if (name && !strcmp(user->name, name)) {
break;
}
}
ast_mutex_unlock(&userl.lock);
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "+++ find_user\n");
return user;
}
struct ooh323_peer *find_friend(const char *name, int port)
{
struct ooh323_peer *peer;
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- find_friend \"%s\"\n", name);
ast_mutex_lock(&peerl.lock);
for (peer = peerl.peers; peer; peer = peer->next) {
if (gH323Debug) {
Tilghman Lesher
committed
ast_verb(0, " comparing with \"%s\"\n", peer->ip);
}
if (!strcmp(peer->ip, name)) {
if (port <= 0 || (port > 0 && peer->port == port)) {
break;
}
}
}
ast_mutex_unlock(&peerl.lock);
if (gH323Debug) {
if (peer) {
Tilghman Lesher
committed
ast_verb(0, " found matching friend\n");
Tilghman Lesher
committed
ast_verb(0, "+++ find_friend \"%s\"\n", name);
}
return peer;
}
struct ooh323_peer *find_peer(const char * name, int port)
{
struct ooh323_peer *peer;
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- find_peer \"%s\"\n", name);
ast_mutex_lock(&peerl.lock);
for (peer = peerl.peers; peer; peer = peer->next) {
if (gH323Debug) {
Tilghman Lesher
committed
ast_verb(0, " comparing with \"%s\"\n", peer->ip);
}
if (!strcasecmp(peer->name, name))
break;
if (peer->h323id && !strcasecmp(peer->h323id, name))
break;
if (peer->e164 && !strcasecmp(peer->e164, name))
break;
/*
if (!strcmp(peer->ip, name)) {
if (port > 0 && peer->port == port) { break; }
else if (port <= 0) { break; }
}
*/
}
ast_mutex_unlock(&peerl.lock);
if (gH323Debug) {
if (peer) {
Tilghman Lesher
committed
ast_verb(0, " found matching peer\n");
Tilghman Lesher
committed
ast_verb(0, "+++ find_peer \"%s\"\n", name);
}
return peer;
}
static int ooh323_digit_begin(struct ast_channel *chan, char digit)
{
char dtmf[2];
struct ooh323_pvt *p = (struct ooh323_pvt *) chan->tech_pvt;
int res = 0;
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- ooh323_digit_begin\n");
if (!p) {
ast_log(LOG_ERROR, "No private structure for call\n");
return -1;
}
ast_mutex_lock(&p->lock);
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';
ooSendDTMFDigit(p->callToken, dtmf);
} else if (p->dtmfmode & H323_DTMF_INBAND) {
res = -1; // tell Asterisk to generate inband indications
}
ast_mutex_unlock(&p->lock);
if (gH323Debug) {
ast_verb(0, "+++ ooh323_digit_begin %d\n", res);
}
return res;
}
static int ooh323_digit_end(struct ast_channel *chan, char digit, unsigned int duration)
{
struct ooh323_pvt *p = (struct ooh323_pvt *) chan->tech_pvt;
int res = 0;
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- ooh323_digit_end\n");
if (!p) {
ast_log(LOG_ERROR, "No private structure for call\n");
return -1;
}
ast_mutex_lock(&p->lock);
if (p->rtp && ((p->dtmfmode & H323_DTMF_RFC2833) || (p->dtmfmode & H323_DTMF_CISCO)) ) {
ast_rtp_instance_dtmf_end(p->rtp, digit);
} else if(p->dtmfmode & H323_DTMF_INBAND) {
res = -1; // tell Asterisk to stop inband indications
}
ast_mutex_unlock(&p->lock);
if (gH323Debug) {
ast_verb(0, "+++ ooh323_digit_end, res = %d\n", res);
}
return res;
}
static int ooh323_call(struct ast_channel *ast, const char *dest, int timeout)
{
struct ooh323_pvt *p = ast->tech_pvt;
char destination[256];
const char *val = NULL;
ooCallOptions opts = {
.fastStart = TRUE,
.tunneling = TRUE,
.disableGk = TRUE,
.callMode = OO_CALLMODE_AUDIOCALL,
.transfercap = 0
if (gH323Debug)
Tilghman Lesher
committed
ast_verb(0, "--- ooh323_call- %s\n", dest);
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_channel_name(ast));
return -1;
}
ast_mutex_lock(&p->lock);
ast_set_flag(p, H323_OUTGOING);
if (ast->connected.id.number.valid && ast->connected.id.number.str) {
free(p->callerid_num);
p->callerid_num = strdup(ast->connected.id.number.str);
if (ast->connected.id.name.valid && ast->connected.id.name.str) {
free(p->callerid_name);
p->callerid_name = strdup(ast->connected.id.name.str);
} else if (ast->connected.id.number.valid && ast->connected.id.number.str) {
free(p->callerid_name);
p->callerid_name = strdup(ast->connected.id.number.str);
ast->connected.id.name.valid = 1;
free(ast->connected.id.name.str);
ast->connected.id.name.str = strdup(gCallerID);
free(p->callerid_name);
p->callerid_name = strdup(ast->connected.id.name.str);
}
/* Retrieve vars */
if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323ID"))) {
ast_copy_string(p->caller_h323id, val, sizeof(p->caller_h323id));
}
if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323DIALEDDIGITS"))) {
ast_copy_string(p->caller_dialedDigits, val, sizeof(p->caller_dialedDigits));
p->callerid_num = strdup(val);
}
if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323EMAIL"))) {
ast_copy_string(p->caller_email, val, sizeof(p->caller_email));
}
if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323URL"))) {
ast_copy_string(p->caller_url, val, sizeof(p->caller_url));
}
if (p->host && p->port != 0)
snprintf(destination, sizeof(destination), "%s:%d", p->host, p->port);
else if (p->host)
snprintf(destination, sizeof(destination), "%s", p->host);
else
ast_copy_string(destination, dest, sizeof(destination));
destination[sizeof(destination)-1]='\0';
opts.transfercap = ast->transfercapability;
opts.fastStart = p->faststart;
opts.tunneling = p->h245tunneling;
for (i=0;i<480 && !isRunning(p->callToken);i++) usleep(12000);
if(OO_TESTFLAG(p->flags, H323_DISABLEGK)) {