massive changes, very broken, do not use (from airport)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3861 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Jeremy McNamara 2004-09-30 19:36:46 +00:00
parent d42c7aeede
commit 83f342776e
1 changed files with 149 additions and 111 deletions

View File

@ -5,8 +5,8 @@
* By Jeremy McNamara * By Jeremy McNamara
* For The NuFone Network * For The NuFone Network
* *
* This code has been derived from code created by * chan_h323 has been derived from code created by
* Michael Manousos and Mark Spencer * Michael Manousos and Mark Spencer
* *
* This file is part of the chan_h323 driver for Asterisk * This file is part of the chan_h323 driver for Asterisk
* *
@ -26,7 +26,6 @@
* Version Info: $Id$ * Version Info: $Id$
*/ */
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/signal.h> #include <sys/signal.h>
#include <sys/param.h> #include <sys/param.h>
@ -72,50 +71,44 @@ extern "C" {
#endif #endif
#include "h323/chan_h323.h" #include "h323/chan_h323.h"
send_digit_cb on_send_digit; send_digit_cb on_send_digit;
on_connection_cb on_create_connection; on_connection_cb on_create_connection;
setup_incoming_cb on_incoming_call; setup_incoming_cb on_incoming_call;
setup_outbound_cb on_outgoing_call; setup_outbound_cb on_outgoing_call;
start_logchan_cb on_start_logical_channel; start_logchan_cb on_start_logical_channel;
chan_ringing_cb on_chan_ringing; chan_ringing_cb on_chan_ringing;
con_established_cb on_connection_established; con_established_cb on_connection_established;
clear_con_cb on_connection_cleared; clear_con_cb on_connection_cleared;
answer_call_cb on_answer_call; answer_call_cb on_answer_call;
/* global debug flag */
int h323debug; int h323debug;
/** String variables required by ASTERISK */ /** Variables required by Asterisk */
static char *type = "H323"; static char *type = "H323";
static char *desc = "The NuFone Network's Open H.323 Channel Driver"; static char *desc = "The NuFone Network's Open H.323 Channel Driver";
static char *tdesc = "The NuFone Network's Open H.323 Channel Driver"; static char *tdesc = "The NuFone Network's Open H.323 Channel Driver";
static char *config = "h323.conf"; static char *config = "h323.conf";
static char default_context[AST_MAX_EXTENSION] = "default";
static char default_context[AST_MAX_EXTENSION];
/** H.323 configuration values */ /** H.323 configuration values */
static int DEFAULT_H323_PORT = 1720;
static char gatekeeper[100]; static char gatekeeper[100];
static int gatekeeper_disable = 1; static int gatekeeper_disable = 1;
static int gatekeeper_discover = 0; static int gatekeeper_discover = 0;
static int usingGk; static int usingGk;
static int port = 1720; static int gkroute = 0;
static int gkroute = 0; static int noFastStart = 0;
static int noFastStart = 1;
static int noH245Tunneling = 0; static int noH245Tunneling = 0;
/* Assume we can native bridge by default */
/* to find user by alias is default, alternative is the incomming call's source IP address*/ static int bridging = 1;
/* Find user by alias (h.323 id) is default, alternative is the incomming call's source IP address*/
static int userbyalias = 1; static int userbyalias = 1;
static int bridge_default = 1;
/* Just about everybody seems to support ulaw, so make it a nice default */ /* Just about everybody seems to support ulaw, so make it a nice default */
static int capability = AST_FORMAT_ULAW; static int capability = AST_FORMAT_ULAW;
/* TOS flag */ /* TOS flag */
static int tos = 0; static int tos = 0;
static int dtmfmode = H323_DTMF_RFC2833; static int dtmfmode = H323_DTMF_RFC2833;
static char secret[50]; static char secret[50];
/** Private structure of a OpenH323 channel */ /** Private structure of a OpenH323 channel */
@ -139,6 +132,9 @@ struct oh323_pvt {
char callerid[80]; /* Caller*ID if available */ char callerid[80]; /* Caller*ID if available */
struct ast_rtp *rtp; /* RTP Session */ struct ast_rtp *rtp; /* RTP Session */
int dtmfmode; /* What DTMF Mode is being used */ int dtmfmode; /* What DTMF Mode is being used */
int noFastStart; /* Determines if this call will utilize FastStart or not */
int noH245Tunneling; /* Determines if H.245 Tunneling is used or not */
int noSilenceSuppression; /* Determines if Silence Suppression will be used or not */
struct ast_dsp *vad; /* Used for in-band DTMF detection */ struct ast_dsp *vad; /* Used for in-band DTMF detection */
struct oh323_pvt *next; /* Next channel in list */ struct oh323_pvt *next; /* Next channel in list */
} *iflist = NULL; } *iflist = NULL;
@ -158,11 +154,11 @@ static struct ast_alias_list {
ast_mutex_t lock; ast_mutex_t lock;
} aliasl; } aliasl;
/** Asterisk RTP stuff*/ /** Asterisk RTP stuff */
static struct sched_context *sched; static struct sched_context *sched;
static struct io_context *io; static struct io_context *io;
/** Protect the interface list (of oh323_pvt's) */ /** Protect the interface list (oh323_pvt) */
AST_MUTEX_DEFINE_STATIC(iflock); AST_MUTEX_DEFINE_STATIC(iflock);
/** Usage counter and associated lock */ /** Usage counter and associated lock */
@ -173,7 +169,7 @@ AST_MUTEX_DEFINE_STATIC(usecnt_lock);
when it's doing something critical. */ when it's doing something critical. */
AST_MUTEX_DEFINE_STATIC(monlock); AST_MUTEX_DEFINE_STATIC(monlock);
/* Avoid two chan to pass capabilities simultaneaously to the h323 stack. */ /* Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. */
AST_MUTEX_DEFINE_STATIC(caplock); AST_MUTEX_DEFINE_STATIC(caplock);
/* This is the thread for the monitor which checks for input on the channels /* This is the thread for the monitor which checks for input on the channels
@ -266,8 +262,9 @@ static struct oh323_user *build_user(char *name, struct ast_variable *v)
/* set the usage flag to a sane starting value*/ /* set the usage flag to a sane starting value*/
user->inUse = 0; user->inUse = 0;
/* Assume we can native bridge */ /* set the native brigding default */
user->bridge = bridge_default; user->bridge = bridging;
user->context = default_context;
while(v) { while(v) {
if (!strcasecmp(v->name, "context")) { if (!strcasecmp(v->name, "context")) {
@ -294,7 +291,7 @@ static struct oh323_user *build_user(char *name, struct ast_variable *v)
user->incominglimit = 0; user->incominglimit = 0;
} else if (!strcasecmp(v->name, "host")) { } else if (!strcasecmp(v->name, "host")) {
if (!strcasecmp(v->value, "dynamic")) { if (!strcasecmp(v->value, "dynamic")) {
ast_log(LOG_ERROR, "Dynamic host configuration not implemented, yet!\n"); ast_log(LOG_ERROR, "A dynamic host on a type=user does not make any sense\n");
free(user); free(user);
return NULL; return NULL;
} else if (ast_get_ip(&user->addr, v->value)) { } else if (ast_get_ip(&user->addr, v->value)) {
@ -317,11 +314,12 @@ static struct oh323_user *build_user(char *name, struct ast_variable *v)
return user; return user;
} }
static struct oh323_peer *build_peer(char *name, struct ast_variable *v) static struct oh323_peer *build_peer(char *name, struct ast_variable *v)
{ {
struct oh323_peer *peer; struct oh323_peer *peer;
struct oh323_peer *prev; struct oh323_peer *prev;
struct ast_ha *oldha = NULL:
int format;
int found=0; int found=0;
prev = NULL; prev = NULL;
@ -353,29 +351,41 @@ static struct oh323_peer *build_peer(char *name, struct ast_variable *v)
if (peer) { if (peer) {
if (!found) { if (!found) {
strncpy(peer->name, name, sizeof(peer->name)-1); strncpy(peer->name, name, sizeof(peer->name)-1);
peer->addr.sin_port = htons(DEFAULT_H323_PORT);
peer->addr.sin_family = AF_INET;
} }
oldha = peer->ha;
/* set the usage flag to a sane starting value*/ peer->ha = NULL:
peer->inUse = 0; peer->addr.sin_family = AF_INET;
peer->capability = capability;
while(v) { while(v) {
if (!strcasecmp(v->name, "context")) { if (!strcasecmp(v->name, "bridge")) {
strncpy(peer->context, v->value, sizeof(peer->context)-1);
} else if (!strcasecmp(v->name, "bridge")) {
peer->bridge = ast_true(v->value); peer->bridge = ast_true(v->value);
} else if (!strcasecmp(v->name, "noFastStart")) { } else if (!strcasecmp(v->name, "noFastStart")) {
peer->noFastStart = ast_true(v->value); peer->noFastStart = ast_true(v->value);
} else if (!strcasecmp(v->name, "nat")) {
peer->nat = ast_true(v->value);
} else if (!strcasecmp(v->name, "noH245Tunneling")) { } else if (!strcasecmp(v->name, "noH245Tunneling")) {
peer->noH245Tunneling = ast_true(v->value); peer->noH245Tunneling = ast_true(v->value);
} else if (!strcasecmp(v->name, "noSilenceSuppression")) { } else if (!strcasecmp(v->name, "noSilenceSuppression")) {
peer->noSilenceSuppression = ast_true(v->value); peer->noSilenceSuppression = ast_true(v->value);
} else if (!strcasecmp(v->name, "dtmfmode")) {
if (!strcasecmp(v->value, "inband") {
peer->dtmfmode = H323_DTMF_INBAND;
} elsif (!strcasecmp(v->value, "rfc2833") {
peer->dtmfmode = H323_DTMF_RFC2833;
} else {
ast_log(LOG_WARNING, "Unknown DTMF Mode %s, using RFC2833\n", v->value);
peer->dtmfmode = H323_DTMF_RFC2833;
}
} else if (!strcasecmp(v->name, "outgoinglimit")) { } else if (!strcasecmp(v->name, "outgoinglimit")) {
peer->outgoinglimit = atoi(v->value); peer->outgoinglimit = atoi(v->value);
if (peer->outgoinglimit > 0) if (peer->outgoinglimit > 0)
peer->outgoinglimit = 0; peer->outgoinglimit = 0;
} else if (!strcasecmp(v->name, "host")) { } else if (!strcasecmp(v->name, "host")) {
if (!strcasecmp(v->value, "dynamic")) { if (!strcasecmp(v->value, "dynamic")) {
ast_log(LOG_ERROR, "Dynamic host configuration not implemented, yet!\n"); ast_log(LOG_ERROR, "Dynamic host configuration not implemented.\n");
free(peer); free(peer);
return NULL; return NULL;
} }
@ -390,8 +400,6 @@ static struct oh323_peer *build_peer(char *name, struct ast_variable *v)
return peer; return peer;
} }
/** /**
* Send (play) the specified digit to the channel. * Send (play) the specified digit to the channel.
* *
@ -408,7 +416,6 @@ static int oh323_digit(struct ast_channel *c, char digit)
return 0; return 0;
} }
/** /**
* Make a call over the specified channel to the specified * Make a call over the specified channel to the specified
* destination. This function will parse the destination string * destination. This function will parse the destination string
@ -423,7 +430,6 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
char *tmp, *cid, *cidname, oldcid[256]; char *tmp, *cid, *cidname, oldcid[256];
strtok_r(dest, "/", &(tmp)); strtok_r(dest, "/", &(tmp));
ast_log(LOG_DEBUG, "dest=%s, timeout=%d.\n", dest, timeout); ast_log(LOG_DEBUG, "dest=%s, timeout=%d.\n", dest, timeout);
if (strlen(dest) > sizeof(called_addr) - 1) { if (strlen(dest) > sizeof(called_addr) - 1) {
@ -436,67 +442,66 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
return -1; return -1;
} }
/* outgoing call */ /* this is an outgoing call */
p->outgoing = 1; p->outgoing = 1;
/* Clear the call token */ /* Ensure the call token is allocated */
if ((p->cd).call_token == NULL) if ((p->cd).call_token == NULL) {
(p->cd).call_token = (char *)malloc(128); (p->cd).call_token = (char *)malloc(128);
}
memset((char *)(p->cd).call_token, 0, 128); memset((char *)(p->cd).call_token, 0, 128);
if (p->cd.call_token == NULL) { if (!p->cd.call_token) {
ast_log(LOG_ERROR, "Not enough memory.\n"); ast_log(LOG_ERROR, "Not enough memory to alocate call token\n");
return -1; return -1;
} }
/* Build the address to call */ /* Clear and then set the address to call */
memset(called_addr, 0, sizeof(called_addr)); memset(called_addr, 0, sizeof(called_addr));
memcpy(called_addr, dest, strlen(dest)); memcpy(called_addr, dest, strlen(dest));
/* Copy callerid, if there is any */ /* Copy callerid, if there is any */
if (c->callerid) { if (!ast_strlen_zero(c->callerid)) {
memset(oldcid, 0, sizeof(oldcid)); memset(oldcid, 0, sizeof(oldcid));
memcpy(oldcid, c->callerid, strlen(c->callerid)); memcpy(oldcid, c->callerid, strlen(c->callerid));
oldcid[sizeof(oldcid)-1] = '\0'; oldcid[sizeof(oldcid)-1] = '\0';
ast_callerid_parse(oldcid, &cidname, &cid); ast_callerid_parse(oldcid, &cidname, &cid);
if (p->calloptions.callerid) { if (!ast_strlen_zero(p->calloptions.callerid)) {
free(p->calloptions.callerid); free(p->calloptions.callerid);
p->calloptions.callerid = NULL; p->calloptions.callerid = NULL;
} }
if (p->calloptions.callername) { if (!ast_strlen_zero(p->calloptions.callername)) {
free(p->calloptions.callername); free(p->calloptions.callername);
p->calloptions.callername = NULL; p->calloptions.callername = NULL;
} }
p->calloptions.callerid = (char*)malloc(256); p->calloptions.callerid = (char*)malloc(256);
if (p->calloptions.callerid == NULL) { if (!p->calloptions.callerid) {
ast_log(LOG_ERROR, "Not enough memory.\n"); ast_log(LOG_ERROR, "Not enough memory to allocate callerid\n");
return(-1); return(-1);
} }
memset(p->calloptions.callerid, 0, 256); memset(p->calloptions.callerid, 0, 256);
if ((cid != NULL)&&(strlen(cid) > 0)) if ((!ast_strlen_zero(cid))&&(!ast_strlen_zero(cid)) {
strncpy(p->calloptions.callerid, cid, 255); strncpy(p->calloptions.callerid, cid, sizeof(p->calloptions.callerid)-1);
}
p->calloptions.callername = (char*)malloc(256); p->calloptions.callername = (char*)malloc(256);
if (p->calloptions.callername == NULL) { if (!p->calloptions.callername) {
ast_log(LOG_ERROR, "Not enough memory.\n"); ast_log(LOG_ERROR, "Not enough memory.\n");
return(-1); return(-1);
} }
memset(p->calloptions.callername, 0, 256); memset(p->calloptions.callername, 0, 256);
if ((cidname != NULL)&&(strlen(cidname) > 0)) if (!ast_strlen_zero(cidname) && (!ast_strlen_zero(cidname)) {
strncpy(p->calloptions.callername, cidname, 255); strncpy(p->calloptions.callername, cidname, sizeof(p->calloptions.callername)-1);
}
} else { } else {
if (p->calloptions.callerid) { if (!ast_strlen_zero(p->calloptions.callerid)) {
free(p->calloptions.callerid); free(p->calloptions.callerid);
p->calloptions.callerid = NULL; p->calloptions.callerid = NULL;
} }
if (p->calloptions.callername) { if (!ast_strlen_zero(p->calloptions.callername)) {
free(p->calloptions.callername); free(p->calloptions.callername);
p->calloptions.callername = NULL; p->calloptions.callername = NULL;
} }
} }
p->calloptions.noFastStart = noFastStart; p->calloptions.noFastStart = noFastStart;
p->calloptions.noH245Tunneling = noH245Tunneling; p->calloptions.noH245Tunneling = noH245Tunneling;
@ -512,7 +517,6 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
static int oh323_answer(struct ast_channel *c) static int oh323_answer(struct ast_channel *c)
{ {
int res; int res;
struct oh323_pvt *p = (struct oh323_pvt *) c->pvt->pvt; struct oh323_pvt *p = (struct oh323_pvt *) c->pvt->pvt;
res = h323_answering_call(p->cd.call_token, 0); res = h323_answering_call(p->cd.call_token, 0);
@ -807,7 +811,7 @@ static struct oh323_pvt *oh323_alloc(int callid)
ast_mutex_init(&p->lock); ast_mutex_init(&p->lock);
p->cd.call_reference = callid; p->cd.call_reference = callid;
p->bridge = bridge_default; p->bridge = bridgeing;
p->dtmfmode = dtmfmode; p->dtmfmode = dtmfmode;
if (p->dtmfmode & H323_DTMF_RFC2833) if (p->dtmfmode & H323_DTMF_RFC2833)
@ -850,29 +854,82 @@ static struct oh323_pvt *find_call(int call_reference, const char *token)
} }
static int create_addr(struct oh323_pvt *r, char *opeer)
{
struct hostent *hp;
struct ast_hostent ahp;
struct oh323_peer *p;
int found = 0;
char *port;
char *callhost;
int portno;
char host[256], *hostn;
char peer[256] = "";
strncpy(peer, opeer, sizeof(peer) - 1);
port = strchr(peer, ':');
if (port) {
*port = '\0';
port++;
}
r->sa.sin_family = AF_INET;
ast_mutex_lock(&peerl.lock);
p = find_peer(peer, NULL);
if (p) {
found++;
r->capability = p->capability;
r->nat = p->nat;
if (r->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n," r->nat);
ast_rtp_setnat(r->rtp, r->nat);
}
r->noFastStart = p->noFastStart;
r->noH245Tunneling = p->noH245Tunneling;
r->noSilenceSuppression = p->noSilenceSuppression;
if (p->dtmfmode) {
r->dtmfmode = p->dtmfmode;
if (r->dtmfmode & H323_DTMF_RFC2833) {
p->nonCodecCapability |= AST_RTP_DTMF;
} else {
p->nonCodecCapability &= ~AST_RTP_DTMF;
}
}
}
static struct ast_channel *oh323_request(char *type, int format, void *data) static struct ast_channel *oh323_request(char *type, int format, void *data)
{ {
int oldformat; int oldformat;
struct oh323_pvt *p; struct oh323_pvt *p;
struct ast_channel *tmpc = NULL; struct ast_channel *tmpc = NULL;
char *dest = (char *) data; char *dest = (char *)data;
char *ext, *host; char *ext, *host;
char *h323id = NULL; char *h323id = NULL;
char tmp[256]; char tmp[256];
ast_log(LOG_DEBUG, "type=%s, format=%d, data=%s.\n", type, format, (char *)data); ast_log(LOG_DEBUG, "type=%s, format=%d, data=%s.\n", type, format, (char *)data);
p = oh323_alloc(0);
if (!p) {
ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
return NULL;
}
oldformat = format; oldformat = format;
format &= capability; format &= capability;
if (!format) { if (!format) {
ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format); ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
return NULL; return NULL;
} }
/* Assign a default capability */
p->capability = capability;
/* pass on our preferred codec to the H.323 stack */
ast_mutex_lock(&caplock);
h323_set_capability(format, dtmfmode);
ast_mutex_unlock(&caplock);
strncpy(tmp, dest, sizeof(tmp) - 1); strncpy(tmp, dest, sizeof(tmp) - 1);
host = strchr(tmp, '@'); host = strchr(tmp, '@');
if (host) { if (host) {
*host = '\0'; *host = '\0';
@ -882,46 +939,27 @@ static struct ast_channel *oh323_request(char *type, int format, void *data)
host = tmp; host = tmp;
ext = NULL; ext = NULL;
} }
strtok_r(host, "/", &(h323id));
strtok_r(host, "/", &(h323id));
if (h323id && !ast_strlen_zero(h323id)) { if (h323id && !ast_strlen_zero(h323id)) {
h323_set_id(h323id); h323_set_id(h323id);
} }
p = oh323_alloc(0);
if (!p) {
ast_log(LOG_WARNING, "Unable to build pvt data for '%s'\n", (char *)data);
return NULL;
}
/* Assign a default capability */
p->capability = capability;
if (p->dtmfmode) {
if (p->dtmfmode & H323_DTMF_RFC2833) {
p->nonCodecCapability |= AST_RTP_DTMF;
} else {
p->nonCodecCapability &= ~AST_RTP_DTMF;
}
}
/* pass on our preferred codec to the H.323 stack */
ast_mutex_lock(&caplock);
h323_set_capability(format, dtmfmode);
ast_mutex_unlock(&caplock);
if (ext) { if (ext) {
strncpy(p->username, ext, sizeof(p->username) - 1); strncpy(p->username, ext, sizeof(p->username) - 1);
} }
ast_log(LOG_DEBUG, "Host: %s\tUsername: %s\n", host, p->username); ast_log(LOG_DEBUG, "Host: %s\tUsername: %s\n", host, p->username);
tmpc = oh323_new(p, AST_STATE_DOWN, host); if (create_addr(p, host) {
if (!tmpc)
oh323_destroy(p); oh323_destroy(p);
return NULL;
}
ast_mutex_lock(&p->lock);
tmpc = oh323_new(p, AST_STATE_DOWN, host);
ast_mutex_unlock(&p->lock);
if (!tmpc) {
oh323_destroy(p);
}
ast_update_use_count();
restart_monitor(); restart_monitor();
return tmpc; return tmpc;
} }
@ -1700,7 +1738,7 @@ int reload_config(void)
} else if (!strcasecmp(v->name, "UserByAlias")) { } else if (!strcasecmp(v->name, "UserByAlias")) {
userbyalias = ast_true(v->value); userbyalias = ast_true(v->value);
} else if (!strcasecmp(v->name, "bridge")) { } else if (!strcasecmp(v->name, "bridge")) {
bridge_default = ast_true(v->value); bridging = ast_true(v->value);
} else if (!strcasecmp(v->name, "noFastStart")) { } else if (!strcasecmp(v->name, "noFastStart")) {
noFastStart = ast_true(v->value); noFastStart = ast_true(v->value);
} else if (!strcasecmp(v->name, "noH245Tunneling")) { } else if (!strcasecmp(v->name, "noH245Tunneling")) {