Apply massive patch from PCadach. If things are broken blame him. Bug#469

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1877 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Jeremy McNamara 2003-12-23 23:01:24 +00:00
parent 3827fbc302
commit ecc015889c
5 changed files with 849 additions and 208 deletions

View File

@ -46,6 +46,7 @@
#include <asterisk/callerid.h> #include <asterisk/callerid.h>
#include <asterisk/cli.h> #include <asterisk/cli.h>
#include <asterisk/dsp.h> #include <asterisk/dsp.h>
#include <asterisk/translate.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <net/if.h> #include <net/if.h>
#include <errno.h> #include <errno.h>
@ -59,6 +60,19 @@
#include "h323/chan_h323.h" #include "h323/chan_h323.h"
#define TRUE 1
#define FALSE 0
/* from rtp.c to translate RTP's payload type to Asterisk's frame subcode */
struct rtpPayloadType {
int isAstFormat; // whether the following code is an AST_FORMAT
int code;
};
call_options_t global_options;
static struct sockaddr_in bindaddr;
/** String variables required by ASTERISK */ /** String 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";
@ -106,6 +120,8 @@ struct oh323_pvt {
int bridge; /* Determine of we should native bridge or not*/ int bridge; /* Determine of we should native bridge or not*/
char exten[AST_MAX_EXTENSION]; /* Requested extension */ char exten[AST_MAX_EXTENSION]; /* Requested extension */
char context[AST_MAX_EXTENSION]; /* Context where to start */ char context[AST_MAX_EXTENSION]; /* Context where to start */
char dnid[AST_MAX_EXTENSION]; /* Called number */
char rdnis[AST_MAX_EXTENSION]; /* Redirecting number */
char username[81]; /* H.323 alias using this channel */ char username[81]; /* H.323 alias using this channel */
char accountcode[256]; /* Account code */ char accountcode[256]; /* Account code */
int amaflags; /* AMA Flags */ int amaflags; /* AMA Flags */
@ -245,17 +261,37 @@ static struct oh323_user *build_user(char *name, struct ast_variable *v)
} else if (!strcasecmp(v->name, "nat")) { } else if (!strcasecmp(v->name, "nat")) {
user->nat = ast_true(v->value); user->nat = ast_true(v->value);
} else if (!strcasecmp(v->name, "noFastStart")) { } else if (!strcasecmp(v->name, "noFastStart")) {
user->noFastStart = ast_true(v->value); user->call_options.noFastStart = ast_true(v->value);
} else if (!strcasecmp(v->name, "noH245Tunneling")) { } else if (!strcasecmp(v->name, "noH245Tunneling")) {
user->noH245Tunneling = ast_true(v->value); user->call_options.noH245Tunnelling = ast_true(v->value);
} else if (!strcasecmp(v->name, "noSilenceSuppression")) { } else if (!strcasecmp(v->name, "noSilenceSuppression")) {
user->noSilenceSuppression = ast_true(v->value); user->call_options.noSilenceSuppression = ast_true(v->value);
} else if (!strcasecmp(v->name, "secret")) { } else if (!strcasecmp(v->name, "secret")) {
strncpy(user->secret, v->value, sizeof(user->secret)-1); strncpy(user->secret, v->value, sizeof(user->secret)-1);
} else if (!strcasecmp(v->name, "callerid")) { } else if (!strcasecmp(v->name, "callerid")) {
strncpy(user->callerid, v->value, sizeof(user->callerid)-1); strncpy(user->callerid, v->value, sizeof(user->callerid)-1);
} else if (!strcasecmp(v->name, "accountcode")) { } else if (!strcasecmp(v->name, "accountcode")) {
strncpy(user->accountcode, v->value, sizeof(user->accountcode)-1); strncpy(user->accountcode, v->value, sizeof(user->accountcode)-1);
} else if (!strcasecmp(v->name, "progress_setup")) {
int progress_setup = atoi(v->value);
if((progress_setup != 0) &&
(progress_setup != 1) &&
(progress_setup != 3) &&
(progress_setup != 8)) {
ast_log(LOG_WARNING, "Invalid value %d for progress_setup at line %d, assuming 0\n", progress_setup, v->lineno);
progress_setup = 0;
}
user->call_options.progress_setup = progress_setup;
} else if (!strcasecmp(v->name, "progress_alert")) {
int progress_alert = atoi(v->value);
if((progress_alert != 0) &&
(progress_alert != 8)) {
ast_log(LOG_WARNING, "Invalid value %d for progress_alert at line %d, assuming 0\n", progress_alert, v->lineno);
progress_alert = 0;
}
user->call_options.progress_alert = progress_alert;
} else if (!strcasecmp(v->name, "progress_audio")) {
user->call_options.progress_audio = ast_true(v->value);
} else if (!strcasecmp(v->name, "incominglimit")) { } else if (!strcasecmp(v->name, "incominglimit")) {
user->incominglimit = atoi(v->value); user->incominglimit = atoi(v->value);
if (user->incominglimit < 0) if (user->incominglimit < 0)
@ -332,11 +368,31 @@ static struct oh323_peer *build_peer(char *name, struct ast_variable *v)
} else if (!strcasecmp(v->name, "bridge")) { } 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->call_options.noFastStart = ast_true(v->value);
} else if (!strcasecmp(v->name, "noH245Tunneling")) { } else if (!strcasecmp(v->name, "noH245Tunneling")) {
peer->noH245Tunneling = ast_true(v->value); peer->call_options.noH245Tunnelling = ast_true(v->value);
} else if (!strcasecmp(v->name, "noSilenceSuppression")) { } else if (!strcasecmp(v->name, "noSilenceSuppression")) {
peer->noSilenceSuppression = ast_true(v->value); peer->call_options.noSilenceSuppression = ast_true(v->value);
} else if (!strcasecmp(v->name, "progress_setup")) {
int progress_setup = atoi(v->value);
if((progress_setup != 0) &&
(progress_setup != 1) &&
(progress_setup != 3) &&
(progress_setup != 8)) {
ast_log(LOG_WARNING, "Invalid value %d for progress_setup at line %d, assuming 0\n", progress_setup, v->lineno);
progress_setup = 0;
}
peer->call_options.progress_setup = progress_setup;
} else if (!strcasecmp(v->name, "progress_alert")) {
int progress_alert = atoi(v->value);
if((progress_alert != 0) &&
(progress_alert != 8)) {
ast_log(LOG_WARNING, "Invalid value %d for progress_alert at line %d, assuming 0\n", progress_alert, v->lineno);
progress_alert = 0;
}
peer->call_options.progress_alert = progress_alert;
} else if (!strcasecmp(v->name, "progress_audio")) {
peer->call_options.progress_audio = ast_true(v->value);
} 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)
@ -427,16 +483,16 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
} else { } else {
p->calloptions.callerid = strdup(c->callerid); p->calloptions.callerid = strdup(c->callerid);
} }
} }
res = h323_make_call(called_addr, &(p->cd), p->calloptions); res = h323_make_call(called_addr, &(p->cd), &p->calloptions);
if (res) { if (res) {
ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name); ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name);
return -1; return -1;
} }
ast_setstate(c, AST_STATE_RINGING); ast_setstate(c, AST_STATE_RING);
return 0; return 0;
} }
@ -504,20 +560,31 @@ static int oh323_hangup(struct ast_channel *c)
return 0; return 0;
} }
static struct ast_frame *oh323_rtp_read(struct oh323_pvt *p) /* Pass channel struct too to allow RTCP handling */
static struct ast_frame *oh323_rtp_read(struct ast_channel *c, struct oh323_pvt *p)
{ {
/* Retrieve audio/etc from channel. Assumes p->lock is already held. */ /* Retrieve audio/etc from channel. Assumes p->lock is already held. */
struct ast_frame *f; struct ast_frame *f;
static struct ast_frame null_frame = { AST_FRAME_NULL, }; static struct ast_frame null_frame = { AST_FRAME_NULL, };
/* Only apply it for the first packet, we just need the correct ip/port */ /* Only apply it for the first packet, we just need the correct ip/port */
if(p->nat) if(p->nat)
{ {
ast_rtp_setnat(p->rtp,p->nat); ast_rtp_setnat(p->rtp,p->nat);
p->nat = 0; p->nat = 0;
} }
switch(c->fdno) {
case 0: /* RTP stream */
f = ast_rtp_read(p->rtp);
break;
case 1: /* RTCP stream */
f = ast_rtcp_read(p->rtp);
break;
default:
f = &null_frame;
}
f = ast_rtp_read(p->rtp);
/* Don't send RFC2833 if we're not supposed to */ /* Don't send RFC2833 if we're not supposed to */
if (f && (f->frametype == AST_FRAME_DTMF) && !(p->dtmfmode & H323_DTMF_RFC2833)) if (f && (f->frametype == AST_FRAME_DTMF) && !(p->dtmfmode & H323_DTMF_RFC2833))
return &null_frame; return &null_frame;
@ -525,10 +592,12 @@ static struct ast_frame *oh323_rtp_read(struct oh323_pvt *p)
/* We already hold the channel lock */ /* We already hold the channel lock */
if (f->frametype == AST_FRAME_VOICE) { if (f->frametype == AST_FRAME_VOICE) {
if (f->subclass != p->owner->nativeformats) { if (f->subclass != p->owner->nativeformats) {
/* Must be handled on opening logical channel */
ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass); ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
p->owner->nativeformats = f->subclass; p->owner->nativeformats = f->subclass;
ast_set_read_format(p->owner, p->owner->readformat); ast_set_read_format(p->owner, p->owner->readformat);
ast_set_write_format(p->owner, p->owner->writeformat); /* Don't set write format because it will be set up when channel started */
// ast_set_write_format(p->owner, p->owner->writeformat);
} }
/* Do in-band DTMF detection */ /* Do in-band DTMF detection */
@ -550,7 +619,8 @@ static struct ast_frame *oh323_read(struct ast_channel *c)
struct ast_frame *fr; struct ast_frame *fr;
struct oh323_pvt *p = c->pvt->pvt; struct oh323_pvt *p = c->pvt->pvt;
ast_mutex_lock(&p->lock); ast_mutex_lock(&p->lock);
fr = oh323_rtp_read(p); /* Pass channel structure to handle other streams than just RTP */
fr = oh323_rtp_read(c, p);
ast_mutex_unlock(&p->lock); ast_mutex_unlock(&p->lock);
return fr; return fr;
} }
@ -559,6 +629,7 @@ static int oh323_write(struct ast_channel *c, struct ast_frame *frame)
{ {
struct oh323_pvt *p = c->pvt->pvt; struct oh323_pvt *p = c->pvt->pvt;
int res = 0; int res = 0;
int need_frfree = 0; /* Does ast_frfree() call required? */
if (frame->frametype != AST_FRAME_VOICE) { if (frame->frametype != AST_FRAME_VOICE) {
if (frame->frametype == AST_FRAME_IMAGE) if (frame->frametype == AST_FRAME_IMAGE)
return 0; return 0;
@ -568,9 +639,47 @@ static int oh323_write(struct ast_channel *c, struct ast_frame *frame)
} }
} else { } else {
if (!(frame->subclass & c->nativeformats)) { if (!(frame->subclass & c->nativeformats)) {
ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n", if(!(frame->subclass & c->writeformat)) { /* Someone sent frame with old format */
frame->subclass, c->nativeformats, c->readformat, c->writeformat); ast_log(LOG_WARNING, "Asked to transmit frame type %s from %s by '%s', while native formats is %s (read/write = %s/%s)\n",
return -1; ast_getformatname(frame->subclass), frame->src, c->name, ast_getformatname(c->nativeformats), ast_getformatname(c->readformat), ast_getformatname(c->writeformat));
return (c->nativeformats ? 0 : -1);
} else {
/* Frame goes from RTP is not in our native
* format - try to translate it... Or we must
* just drop it?
*/
/* Sometimes translation table isn't set
* correctly but writeformat is invalid,
* so force required translation allocation
*/
ast_set_write_format(c, c->nativeformats);
ast_set_write_format(c, frame->subclass);
/* Translate it on-the-fly */
if (c->pvt->writetrans) {
struct ast_frame *frame1;
ast_log(LOG_WARNING, "Asked to transmit frame type %s from %s by '%s', while native formats is %s (read/write = %s/%s) - 2 TRANSLATE\n",
ast_getformatname(frame->subclass), frame->src, c->name, ast_getformatname(c->nativeformats), ast_getformatname(c->readformat), ast_getformatname(c->writeformat));
/* Allocate new frame with translated context.
* Don't free frame because it will be freed on
* upper layer (RTP).
*/
frame1 = ast_translate(c->pvt->writetrans, frame, 0);
if(frame1) {
/* Substitute passed frame with translated and
mark it for freeing before return */
frame = frame1;
need_frfree = 1;
}
else
ast_log(LOG_WARNING, "Unable to translate frame type %s to %s\n", ast_getformatname(frame->subclass), ast_getformatname(c->nativeformats));
} else {
ast_log(LOG_WARNING, "Asked to transmit frame type %s from %s by '%s', while native formats is %s (read/write = %s/%s)\n",
ast_getformatname(frame->subclass), frame->src, c->name, ast_getformatname(c->nativeformats), ast_getformatname(c->readformat), ast_getformatname(c->writeformat));
return -1;
}
}
} }
} }
if (p) { if (p) {
@ -580,6 +689,9 @@ static int oh323_write(struct ast_channel *c, struct ast_frame *frame)
} }
ast_mutex_unlock(&p->lock); ast_mutex_unlock(&p->lock);
} }
/* Free translated frame */
if(need_frfree)
ast_frfree(frame);
return res; return res;
} }
@ -613,7 +725,7 @@ static int oh323_indicate(struct ast_channel *c, int condition)
} }
return 0; return 0;
case -1: case -1:
return -1; return 0;
default: default:
ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", condition); ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", condition);
return -1; return -1;
@ -644,13 +756,20 @@ static struct ast_channel *oh323_new(struct oh323_pvt *i, int state, const char
if (ch) { if (ch) {
// snprintf(ch->name, sizeof(ch->name)-1, "H323/%s-%04x", host, rand() & 0xffff);
snprintf(ch->name, sizeof(ch->name)-1, "H323/%s", host); snprintf(ch->name, sizeof(ch->name)-1, "H323/%s", host);
ch->nativeformats = i->capability; ch->nativeformats = i->capability;
if (!ch->nativeformats) if (!ch->nativeformats)
ch->nativeformats = capability; ch->nativeformats = capability;
fmt = ast_best_codec(ch->nativeformats); fmt = ast_best_codec(ch->nativeformats);
ch->type = type; ch->type = type;
/* RTP stream */
ch->fds[0] = ast_rtp_fd(i->rtp); ch->fds[0] = ast_rtp_fd(i->rtp);
/* RTCP stream */
ch->fds[1] = ast_rtcp_fd(i->rtp);
ast_setstate(ch, state); ast_setstate(ch, state);
if (state == AST_STATE_RING) if (state == AST_STATE_RING)
@ -691,6 +810,10 @@ static struct ast_channel *oh323_new(struct oh323_pvt *i, int state, const char
ch->priority = 1; ch->priority = 1;
if (strlen(i->callerid)) if (strlen(i->callerid))
ch->callerid = strdup(i->callerid); ch->callerid = strdup(i->callerid);
if (strlen(i->dnid))
ch->dnid = strdup(i->dnid);
if (strlen(i->rdnis))
ch->rdnis = strdup(i->rdnis);
if (strlen(i->accountcode)) if (strlen(i->accountcode))
strncpy(ch->accountcode, i->accountcode, sizeof(ch->accountcode)-1); strncpy(ch->accountcode, i->accountcode, sizeof(ch->accountcode)-1);
if (i->amaflags) if (i->amaflags)
@ -731,6 +854,7 @@ static struct oh323_pvt *oh323_alloc(int callid)
p->cd.call_reference = callid; p->cd.call_reference = callid;
p->bridge = bridge_default; p->bridge = bridge_default;
memcpy(&p->calloptions, &global_options, sizeof(global_options));
p->dtmfmode = dtmfmode; p->dtmfmode = dtmfmode;
if (p->dtmfmode & H323_DTMF_RFC2833) if (p->dtmfmode & H323_DTMF_RFC2833)
@ -748,25 +872,24 @@ static struct oh323_pvt *find_call(int call_reference)
{ {
struct oh323_pvt *p; struct oh323_pvt *p;
ast_mutex_lock(&iflock); ast_mutex_lock(&iflock);
p = iflist; p = iflist;
while(p) { while(p) {
if (p->cd.call_reference == call_reference) { if (p->cd.call_reference == call_reference) {
/* Found the call */ /* Found the call */
ast_mutex_unlock(&iflock); ast_mutex_unlock(&iflock);
return p; return p;
} }
p = p->next; p = p->next;
} }
ast_mutex_unlock(&iflock); ast_mutex_unlock(&iflock);
return NULL;
return NULL;
} }
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;
@ -835,20 +958,45 @@ static struct ast_channel *oh323_request(char *type, int format, void *data)
return tmpc; return tmpc;
} }
struct oh323_alias *find_alias(const char *source_aliases) struct oh323_alias *find_alias(call_details_t cd)
{ {
struct oh323_alias *a; struct oh323_alias *a, *a_e164 = NULL, *a_pfx = NULL;
char *s, *p;
int a_pfxlen, numlen;
a = aliasl.aliases; a = aliasl.aliases;
a_pfxlen = 0;
numlen = strlen(cd.call_dest_e164);
while(a) { while(a) {
if (!strcasecmp(a->name, source_aliases)) { if (!strcasecmp(a->name, cd.call_dest_alias)) {
break; break;
} }
/* Check for match of E164 number */
if (!strcasecmp(a->e164, cd.call_dest_e164))
a_e164 = a;
else { /* Check for match called number with prefixes */
for(s = a->prefix; *s; ) {
for(; *s == ' '; ++s);
if(!(p = strchr(s, ',')))
p = s + strlen(s);
if((p - s > a_pfxlen) && (numlen >= p - s) && (strncasecmp(s, cd.call_dest_e164, p - s) == 0)) {
a_pfxlen = p - s;
a_pfx = a;
}
s = p;
if(*s == ',')
++s;
}
}
a = a->next; a = a->next;
} }
return a; if(a)
return a;
if(a_e164)
return a_e164;
return a_pfx;
} }
struct oh323_user *find_user(const call_details_t cd) struct oh323_user *find_user(const call_details_t cd)
@ -894,6 +1042,27 @@ struct oh323_peer *find_peer(char *dest_peer)
} }
static int progress(unsigned call_reference, int inband)
{
struct oh323_pvt *p;
ast_log(LOG_DEBUG, "Received ALERT/PROGRESS message for %s tones\n", (inband ? "inband" : "self-generated"));
p = find_call(call_reference);
if (!p) {
ast_log(LOG_ERROR, "Private structure not found in send_digit.\n");
return -1;
}
if (!p->owner) {
ast_log(LOG_ERROR, "No asterisk's channel associated with private structure.\n");
return -1;
}
ast_queue_control(p->owner, (inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING), 0);
return 0;
}
/** /**
* Callback for sending digits from H.323 up to asterisk * Callback for sending digits from H.323 up to asterisk
* *
@ -912,13 +1081,13 @@ int send_digit(unsigned call_reference, char digit)
} }
memset(&f, 0, sizeof(f)); memset(&f, 0, sizeof(f));
f.frametype = AST_FRAME_DTMF; f.frametype = AST_FRAME_DTMF;
f.subclass = digit; f.subclass = digit;
f.datalen = 0; f.datalen = 0;
f.samples = 300; f.samples = 300;
f.offset = 0; f.offset = 0;
f.data = NULL; f.data = NULL;
f.mallocd = 0; f.mallocd = 0;
f.src = "SEND_DIGIT"; f.src = "SEND_DIGIT";
return ast_queue_frame(p->owner, &f, 1); return ast_queue_frame(p->owner, &f, 1);
} }
@ -962,20 +1131,21 @@ struct rtp_info *create_connection(unsigned call_reference)
* Returns 1 on success * Returns 1 on success
*/ */
int setup_incoming_call(call_details_t cd) call_options_t *setup_incoming_call(call_details_t cd)
{ {
struct oh323_pvt *p = NULL; struct oh323_pvt *p = NULL;
struct ast_channel *c = NULL; struct ast_channel *c = NULL;
struct oh323_user *user = NULL; struct oh323_user *user = NULL;
struct oh323_alias *alias = NULL; struct oh323_alias *alias = NULL;
call_options_t *call_options = NULL;
/* allocate the call*/ /* allocate the call*/
p = oh323_alloc(cd.call_reference); p = oh323_alloc(cd.call_reference);
if (!p) { if (!p) {
ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n"); ast_log(LOG_ERROR, "Unable to allocate private structure, this is bad.\n");
return 0; return NULL;
} }
/* Populate the call details in the private structure */ /* Populate the call details in the private structure */
@ -986,21 +1156,28 @@ int setup_incoming_call(call_details_t cd)
p->cd.call_dest_e164 = cd.call_dest_e164; p->cd.call_dest_e164 = cd.call_dest_e164;
if (h323debug) { if (h323debug) {
ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n"); ast_verbose(VERBOSE_PREFIX_2 "Setting up Call\n");
ast_verbose(VERBOSE_PREFIX_3 " Calling party name: [%s]\n", p->cd.call_source_aliases); ast_verbose(VERBOSE_PREFIX_3 "Calling party name: [%s]\n", p->cd.call_source_aliases);
ast_verbose(VERBOSE_PREFIX_3 " Calling party number: [%s]\n", p->cd.call_source_e164); ast_verbose(VERBOSE_PREFIX_3 "Calling party number: [%s]\n", p->cd.call_source_e164);
ast_verbose(VERBOSE_PREFIX_3 " Called party name: [%s]\n", p->cd.call_dest_alias); ast_verbose(VERBOSE_PREFIX_3 "Called party name: [%s]\n", p->cd.call_dest_alias);
ast_verbose(VERBOSE_PREFIX_3 " Called party number: [%s]\n", p->cd.call_dest_e164); ast_verbose(VERBOSE_PREFIX_3 "Called party number: [%s]\n", p->cd.call_dest_e164);
ast_verbose(VERBOSE_PREFIX_3 "Redirecting party number: [%s]\n", p->cd.call_redir_e164);
} }
/* Decide if we are allowing Gatekeeper routed calls*/ /* Decide if we are allowing Gatekeeper routed calls*/
if ((!strcasecmp(cd.sourceIp, gatekeeper)) && (gkroute == -1) && (usingGk == 1)) { if ((!strcasecmp(cd.sourceIp, gatekeeper)) && (gkroute == -1) && (usingGk == 1)) {
if (strlen(cd.call_dest_e164)) { if (strlen(cd.call_dest_e164)) {
strncpy(p->exten, cd.call_dest_e164, sizeof(p->exten)-1); char *ctx;
strncpy(p->context, default_context, sizeof(p->context)-1);
alias = find_alias(cd);
ctx = alias ? alias->context : default_context;
strncpy(p->dnid, cd.call_dest_e164, sizeof(p->dnid)-1);
strncpy(p->exten, cd.call_dest_e164, sizeof(p->exten)-1);
strncpy(p->context, ctx, sizeof(p->context)-1);
} else { } else {
alias = find_alias(cd.call_dest_alias); alias = find_alias(cd);
if (!alias) { if (!alias) {
ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd.call_dest_alias); ast_log(LOG_ERROR, "Call for %s rejected, alias not found\n", cd.call_dest_alias);
@ -1010,8 +1187,8 @@ int setup_incoming_call(call_details_t cd)
strncpy(p->context, alias->context, sizeof(p->context)-1); strncpy(p->context, alias->context, sizeof(p->context)-1);
} }
/* Asterisk prefers user name to be quoted */
sprintf(p->callerid, "%s <%s>", p->cd.call_source_aliases, p->cd.call_source_e164); sprintf(p->callerid, "\"%s\" <%s>", p->cd.call_source_aliases, p->cd.call_source_e164);
} else { } else {
/* Either this call is not from the Gatekeeper /* Either this call is not from the Gatekeeper
@ -1022,11 +1199,13 @@ int setup_incoming_call(call_details_t cd)
if (!user) { if (!user) {
sprintf(p->callerid, "%s <%s>", p->cd.call_source_aliases, p->cd.call_source_e164); /* Asterisk prefers user name to be quoted */
sprintf(p->callerid, "\"%s\" <%s>", p->cd.call_source_aliases, p->cd.call_source_e164);
if (strlen(p->cd.call_dest_e164)) { if (strlen(p->cd.call_dest_e164)) {
strncpy(p->dnid, cd.call_dest_e164, sizeof(p->dnid)-1);
strncpy(p->exten, cd.call_dest_e164, sizeof(p->exten)-1); strncpy(p->exten, cd.call_dest_e164, sizeof(p->exten)-1);
} else { } else {
strncpy(p->exten, cd.call_dest_alias, sizeof(p->exten)-1); strncpy(p->exten, cd.call_dest_alias, sizeof(p->exten)-1);
} }
if (!strlen(default_context)) { if (!strlen(default_context)) {
ast_log(LOG_ERROR, "Call from user '%s' rejected due to no default context\n", p->cd.call_source_aliases); ast_log(LOG_ERROR, "Call from user '%s' rejected due to no default context\n", p->cd.call_source_aliases);
@ -1034,13 +1213,14 @@ int setup_incoming_call(call_details_t cd)
} }
strncpy(p->context, default_context, sizeof(p->context)-1); strncpy(p->context, default_context, sizeof(p->context)-1);
ast_log(LOG_DEBUG, "Sending %s to context [%s]\n", cd.call_source_aliases, p->context); ast_log(LOG_DEBUG, "Sending %s to context [%s]\n", cd.call_source_aliases, p->context);
} else { } else {
call_options = &user->call_options;
if (user->host) { if (user->host) {
if (strcasecmp(cd.sourceIp, inet_ntoa(user->addr.sin_addr))){ if (strcasecmp(cd.sourceIp, inet_ntoa(user->addr.sin_addr))){
if(!strlen(default_context)) { if(!strlen(default_context)) {
ast_log(LOG_ERROR, "Call from user '%s' rejected due to non-matching IP address of '%s'\n", user->name, cd.sourceIp); ast_log(LOG_ERROR, "Call from user '%s' rejected due to non-matching IP address of '%s'\n", user->name, cd.sourceIp);
return 0; return NULL;
} }
strncpy(p->context, default_context, sizeof(p->context)-1); strncpy(p->context, default_context, sizeof(p->context)-1);
@ -1052,12 +1232,12 @@ int setup_incoming_call(call_details_t cd)
if (user->incominglimit > 0) { if (user->incominglimit > 0) {
if (user->inUse >= user->incominglimit) { if (user->inUse >= user->incominglimit) {
ast_log(LOG_ERROR, "Call from user '%s' rejected due to usage limit of %d\n", user->name, user->incominglimit); ast_log(LOG_ERROR, "Call from user '%s' rejected due to usage limit of %d\n", user->name, user->incominglimit);
return 0; return NULL;
} }
} }
strncpy(p->context, user->context, sizeof(p->context)-1); strncpy(p->context, user->context, sizeof(p->context)-1);
p->bridge = user->bridge; p->bridge = user->bridge;
p->nat = user->nat; p->nat = user->nat;
if (strlen(user->callerid)) if (strlen(user->callerid))
strncpy(p->callerid, user->callerid, sizeof(p->callerid) - 1); strncpy(p->callerid, user->callerid, sizeof(p->callerid) - 1);
@ -1080,14 +1260,21 @@ int setup_incoming_call(call_details_t cd)
/* I know this is horrid, don't kill me saddam */ /* I know this is horrid, don't kill me saddam */
exit: exit:
if(strlen(p->cd.call_redir_e164))
strncpy(p->rdnis, cd.call_redir_e164, sizeof(p->rdnis)-1);
/* allocate a channel and tell asterisk about it */ /* allocate a channel and tell asterisk about it */
c = oh323_new(p, AST_STATE_RINGING, cd.call_token); c = oh323_new(p, AST_STATE_RINGING, cd.call_token);
if (!c) { if (!c) {
ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n"); ast_log(LOG_ERROR, "Couldn't create channel. This is bad\n");
return 0; return NULL;
} }
return 1; ast_queue_control(c, AST_CONTROL_RINGING, 0);
if(!call_options)
return &global_options;
return call_options;
} }
/** /**
@ -1117,7 +1304,56 @@ if (!p) {
* *
* Returns nothing * Returns nothing
*/ */
void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort) void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, int direction, int payloadType)
{
struct oh323_pvt *p = NULL;
struct sockaddr_in them;
struct rtpPayloadType payload;
struct ast_channel *chan;
/* Find the call or allocate a private structure if call not found */
p = find_call(call_reference);
if (!p) {
ast_log(LOG_ERROR, "Something is wrong: rtp\n");
return;
}
them.sin_family = AF_INET;
them.sin_addr.s_addr = inet_addr(remoteIp); // only works for IPv4
them.sin_port = htons(remotePort);
/* Find RTP payload <=> asterisk's subcode association */
payload = ast_rtp_lookup_pt(p->rtp, payloadType);
ast_log(LOG_DEBUG, "Setting up %sbound RTP connection for %s:%d with payload %s (RTP code %d)\n", (direction ? "out" : "in"), inet_ntoa(them.sin_addr), remotePort, ast_getformatname(payload.code), payloadType);
/* Set channel's native codec and prepare translation table
* for given direction and currently used format
*/
if ((chan = p->owner)) {
if (payload.isAstFormat) {
/* Don't allow any transmission until codec is changed */
// ast_mutex_lock(&chan->lock);
chan->nativeformats = payload.code;
if(direction)
ast_set_write_format(chan, chan->writeformat);
else
ast_set_read_format(chan, chan->readformat);
// ast_mutex_unlock(&chan->lock);
}
}
ast_rtp_set_peer(p->rtp, &them);
if(p->calloptions.progress_audio)
progress(call_reference, TRUE);
return;
}
/* Not used for now - set RTP peer's address */
void setup_rtp_peer(unsigned call_reference, const char *remoteIp, int remotePort)
{ {
struct oh323_pvt *p = NULL; struct oh323_pvt *p = NULL;
struct sockaddr_in them; struct sockaddr_in them;
@ -1134,8 +1370,6 @@ void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int rem
them.sin_addr.s_addr = inet_addr(remoteIp); // only works for IPv4 them.sin_addr.s_addr = inet_addr(remoteIp); // only works for IPv4
them.sin_port = htons(remotePort); them.sin_port = htons(remotePort);
ast_rtp_set_peer(p->rtp, &them); ast_rtp_set_peer(p->rtp, &them);
return;
} }
/** /**
@ -1236,13 +1470,15 @@ restartsearch:
} }
ast_mutex_unlock(&iflock); ast_mutex_unlock(&iflock);
pthread_testcancel();
/* Wait for sched or io */ /* Wait for sched or io */
res = ast_sched_wait(sched); res = ast_sched_wait(sched);
if ((res < 0) || (res > 1000)) if ((res < 0) || (res > 1000))
res = 1000; res = 1000;
res = ast_io_wait(io, res); res = ast_io_wait(io, res);
/* Check for thread cancellation */
pthread_testcancel();
ast_mutex_lock(&monlock); ast_mutex_lock(&monlock);
if (res >= 0) if (res >= 0)
ast_sched_runq(sched); ast_sched_runq(sched);
@ -1392,7 +1628,7 @@ int reload_config(void)
struct oh323_alias *alias = NULL; struct oh323_alias *alias = NULL;
struct hostent *hp; struct hostent *hp;
char *cat; char *cat;
char *utype; char *utype;
cfg = ast_load(config); cfg = ast_load(config);
@ -1408,6 +1644,8 @@ int reload_config(void)
} }
h323debug=0; h323debug=0;
dtmfmode = H323_DTMF_RFC2833; dtmfmode = H323_DTMF_RFC2833;
/* Fill global variables with pre-determined values */
memset(&global_options, 0, sizeof(global_options));
memset(&bindaddr, 0, sizeof(bindaddr)); memset(&bindaddr, 0, sizeof(bindaddr));
@ -1478,6 +1716,33 @@ int reload_config(void)
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);
dtmfmode = H323_DTMF_RFC2833; dtmfmode = H323_DTMF_RFC2833;
} }
/* Setup global parameters */
} else if (!strcasecmp(v->name, "noFastStart")) {
global_options.noFastStart = ast_true(v->value);
} else if (!strcasecmp(v->name, "noH245Tunneling")) {
global_options.noH245Tunnelling = ast_true(v->value);
} else if (!strcasecmp(v->name, "noSilenceSuppression")) {
global_options.noSilenceSuppression = ast_true(v->value);
} else if (!strcasecmp(v->name, "progress_setup")) {
int progress_setup = atoi(v->value);
if((progress_setup != 0) &&
(progress_setup != 1) &&
(progress_setup != 3) &&
(progress_setup != 8)) {
ast_log(LOG_WARNING, "Invalid value %d for progress_setup at line %d, assuming 0\n", progress_setup, v->lineno);
progress_setup = 0;
}
global_options.progress_setup = progress_setup;
} else if (!strcasecmp(v->name, "progress_alert")) {
int progress_alert = atoi(v->value);
if((progress_alert != 0) &&
(progress_alert != 8)) {
ast_log(LOG_WARNING, "Invalid value %d for progress_alert at line %d, assuming 0\n", progress_alert, v->lineno);
progress_alert = 0;
}
global_options.progress_alert = progress_alert;
} else if (!strcasecmp(v->name, "progress_audio")) {
global_options.progress_audio = ast_true(v->value);
} 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")) {
@ -1608,15 +1873,20 @@ int reload(void)
delete_aliases(); delete_aliases();
prune_peers(); prune_peers();
reload_config();
#if 0
This code causes seg on -r
if (strlen(gatekeeper)) { if (strlen(gatekeeper)) {
h323_gk_urq(); h323_gk_urq();
} }
reload_config();
#if 0
/* Possibly register with a GK */ /* Possibly register with a GK */
if (gatekeeper_disable == 0) { if (!gatekeeper_disable) {
if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) { if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) {
ast_log(LOG_ERROR, "Gatekeeper registration failed.\n"); ast_log(LOG_ERROR, "Gatekeeper registration failed.\n");
h323_end_process(); h323_end_process();
@ -1624,6 +1894,7 @@ int reload(void)
} }
} }
#endif #endif
restart_monitor(); restart_monitor();
return 0; return 0;
} }
@ -1747,7 +2018,9 @@ int load_module()
create_connection, create_connection,
setup_rtp_connection, setup_rtp_connection,
cleanup_connection, cleanup_connection,
connection_made, send_digit); connection_made,
send_digit,
progress);
/* start the h.323 listener */ /* start the h.323 listener */
@ -1805,6 +2078,7 @@ int unload_module()
return -1; return -1;
} }
h323_gk_urq(); h323_gk_urq();
h323_debug(0,0);
h323_end_process(); h323_end_process();
/* unregister rtp */ /* unregister rtp */
@ -1843,7 +2117,3 @@ char *key()
{ {
return ASTERISK_GPL_KEY; return ASTERISK_GPL_KEY;
} }

View File

@ -41,10 +41,11 @@ int channelsOpen;
/* DTMF Mode */ /* DTMF Mode */
int mode = H323_DTMF_RFC2833; int mode = H323_DTMF_RFC2833;
/* Make those variables accessible from chan_h323.c */
extern "C" {
/** Options for connections creation */ /** Options for connections creation */
BOOL noFastStart; call_options_t global_options;
BOOL noH245Tunnelling; }
BOOL noSilenceSuppression;
/** /**
* We assume that only one endPoint should exist. * We assume that only one endPoint should exist.
@ -59,6 +60,27 @@ MyProcess *localProcess = NULL;
/** H.323 listener */ /** H.323 listener */
H323ListenerTCP *tcpListener; H323ListenerTCP *tcpListener;
/* Provide common methods to split out non-user parts of OpenH323 aliases */
static void FormatAliases(PString & aliases)
{
/* Convert complex strings */
// FIXME: deal more than one source alias
char *s;
const char *p = (const char *)aliases;
if ((s = strchr(p, '(')) != NULL)
*s = '\0';
else if ((s = strchr(p, ',')) != NULL)
*s = '\0';
else if ((s = strchr(p, '[')) != NULL)
*s = '\0';
else if ((s = strchr(p, ' ')) != NULL)
*s = '\0';
else if ((s = strchr(p, '\t')) != NULL)
*s = '\0';
/* Strip trailing spaces */
for(s = (char *)(p + strlen(p)); (s > p) && (*--s == ' '); *s = '\0');
}
MyProcess::MyProcess(): PProcess("The NuFone Network's", "H.323 Channel Driver for Asterisk", MyProcess::MyProcess(): PProcess("The NuFone Network's", "H.323 Channel Driver for Asterisk",
MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER) MAJOR_VERSION, MINOR_VERSION, BUILD_TYPE, BUILD_NUMBER)
{ {
@ -76,6 +98,7 @@ void MyProcess::Main()
{ {
cout << " == Creating H.323 Endpoint" << endl; cout << " == Creating H.323 Endpoint" << endl;
endPoint = new MyH323EndPoint(); endPoint = new MyH323EndPoint();
endPoint->DisableDetectInBandDTMF(TRUE);
PTrace::Initialise(0, NULL, PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine); PTrace::Initialise(0, NULL, PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine);
} }
@ -111,6 +134,7 @@ H323_G7231Capability::H323_G7231Capability(BOOL annexA_)
: H323AudioCapability(7, 4) : H323AudioCapability(7, 4)
{ {
annexA = annexA_; annexA = annexA_;
rtpPayloadType = RTP_DataFrame::G7231;
} }
PObject::Comparison H323_G7231Capability::Compare(const PObject & obj) const PObject::Comparison H323_G7231Capability::Compare(const PObject & obj) const
@ -248,7 +272,8 @@ H323Codec * AST_G729ACapability::CreateCodec(H323Codec::Direction direction) con
* port = 1720. * port = 1720.
*/ */
int MyH323EndPoint::MakeCall(const PString & dest, PString & token, int MyH323EndPoint::MakeCall(const PString & dest, PString & token,
unsigned int *callReference, unsigned int port, char *callerid) unsigned int *callReference,
call_options_t *call_options)
{ {
PString fullAddress; PString fullAddress;
MyH323Connection * connection; MyH323Connection * connection;
@ -264,7 +289,7 @@ int MyH323EndPoint::MakeCall(const PString & dest, PString & token,
cout << " -- Making call to " << fullAddress << "." << endl; cout << " -- Making call to " << fullAddress << "." << endl;
} }
if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token))) { if (!(connection = (MyH323Connection *)H323EndPoint::MakeCallLocked(fullAddress, token, call_options))) {
if (h323debug) if (h323debug)
cout << "Error making call to \"" << fullAddress << '"' << endl; cout << "Error making call to \"" << fullAddress << '"' << endl;
return 1; return 1;
@ -272,8 +297,8 @@ int MyH323EndPoint::MakeCall(const PString & dest, PString & token,
*callReference = connection->GetCallReference(); *callReference = connection->GetCallReference();
if (callerid) if (call_options->callerid)
connection->SetLocalPartyName(PString(callerid)); connection->SetCID(call_options->callerid); // Use our local function to setup H.323 caller ID correctly
connection->Unlock(); connection->Unlock();
@ -287,7 +312,16 @@ int MyH323EndPoint::MakeCall(const PString & dest, PString & token,
void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const void MyH323EndPoint::SetEndpointTypeInfo( H225_EndpointType & info ) const
{ {
// cout << " **** Terminal type: " << terminalType << endl;
H323EndPoint::SetEndpointTypeInfo(info); H323EndPoint::SetEndpointTypeInfo(info);
// cout << " **** INFO: " << info << endl;
/* Because H323EndPoint::SetEndpointTypeInfo() don't set correctly
endpoint type, force manual setting it */
if(terminalType == e_GatewayOnly)
{
info.RemoveOptionalField(H225_EndpointType::e_terminal);
info.IncludeOptionalField(H225_EndpointType::e_gateway);
}
info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol); info.m_gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
info.m_gateway.m_protocol.SetSize(1); info.m_gateway.m_protocol.SetSize(1);
H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0]; H225_SupportedProtocols &protocol=info.m_gateway.m_protocol[0];
@ -336,17 +370,17 @@ void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H
} }
BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection, BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection,
const PString & forwardParty, const PString & forwardParty,
const H323SignalPDU & pdu) const H323SignalPDU & pdu)
{ {
if (h323debug) if (h323debug)
cout << " -- Call Forwarded to " << forwardParty << endl; cout << " -- Call Forwarded to " << forwardParty << endl;
return FALSE; return FALSE;
} }
BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection, BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection,
const PString & forwardParty, const PString & forwardParty,
const H323SignalPDU & pdu) const H323SignalPDU & pdu)
{ {
if (h323debug) if (h323debug)
cout << " -- Forwarding call to " << forwardParty << endl; cout << " -- Forwarding call to " << forwardParty << endl;
@ -369,14 +403,12 @@ void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PStr
call_details_t cd; call_details_t cd;
/* Use common alias formatting routine */
FormatAliases(remoteName);
cd.call_reference = connection.GetCallReference(); cd.call_reference = connection.GetCallReference();
cd.call_token = (const char *)connection.GetCallToken(); cd.call_token = (const char *)connection.GetCallToken();
cd.call_source_aliases = (const char *)connection.GetRemotePartyName(); cd.call_source_aliases = (const char *)remoteName;
/* Convert complex strings */
char *s;
if ((s = strchr(cd.call_source_aliases, ' ')) != NULL)
*s = '\0';
/* Invoke the PBX application registered callback */ /* Invoke the PBX application registered callback */
on_connection_cleared(cd); on_connection_cleared(cd);
@ -452,7 +484,7 @@ void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PStr
break; break;
default : default :
if (h323debug) if (h323debug)
cout << " -- Call with " << remoteName << " completed" << endl; cout << " -- Call with " << remoteName << " completed (" << connection.GetCallEndReason() << ")" << endl;
} }
if(connection.IsEstablished()) if(connection.IsEstablished())
if (h323debug) if (h323debug)
@ -463,26 +495,146 @@ void MyH323EndPoint::OnConnectionCleared(H323Connection & connection, const PStr
H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *outbound) H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void *outbound)
{ {
unsigned options = 0; unsigned options = 0;
call_options_t *call_options = (call_options_t *)outbound;
if (noFastStart) if (!call_options)
call_options = &global_options;
if (call_options->noFastStart)
options |= H323Connection::FastStartOptionDisable; options |= H323Connection::FastStartOptionDisable;
if (noH245Tunnelling) if (call_options->noH245Tunnelling)
options |= H323Connection::H245TunnelingOptionDisable; options |= H323Connection::H245TunnelingOptionDisable;
return new MyH323Connection(*this, callReference, options); /* Set silence detection mode - won't work for Asterisk's RTP but can be used in the negotiation process */
SetSilenceDetectionMode(call_options->noSilenceSuppression ? H323AudioCodec::NoSilenceDetection : H323AudioCodec::AdaptiveSilenceDetection);
return new MyH323Connection(*this, callReference, options, call_options);
}
/* MyH323_ExternalRTPChannel */
MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(
H323Connection & connection, /// Connection to endpoint for channel
const H323Capability & capability, /// Capability channel is using
Directions direction, /// Direction of channel
unsigned sessionID /// Session ID for channel
): H323_ExternalRTPChannel(connection,capability,direction,sessionID)
{
}
MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(
H323Connection & connection, /// Connection to endpoint for channel
const H323Capability & capability, /// Capability channel is using
Directions direction, /// Direction of channel
unsigned sessionID, /// Session ID for channel
const H323TransportAddress & data, /// Data address
const H323TransportAddress & control/// Control address
): H323_ExternalRTPChannel(connection, capability, direction, sessionID, data, control)
{
}
MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(
H323Connection & connection, /// Connection to endpoint for channel
const H323Capability & capability, /// Capability channel is using
Directions direction, /// Direction of channel
unsigned sessionID, /// Session ID for channel
const PIPSocket::Address & ip, /// IP address of media server
WORD dataPort /// Data port (control is dataPort+1)
): H323_ExternalRTPChannel(connection, capability, direction, sessionID, ip, dataPort)
{
}
BOOL MyH323_ExternalRTPChannel::Start()
{
BOOL res;
PIPSocket::Address remoteIpAddress; // IP Address of remote endpoint
WORD remotePort; // remote endpoint Data port (control is dataPort+1)
PIPSocket::Address externalIpAddress; // IP address of media server
WORD externalPort; // local media server Data port (control is dataPort+1)
res = H323_ExternalRTPChannel::Start();
if (!res)
return res;
if (h323debug) {
/* Show H.323 channel number to make debugging more comfortable */
cout << " -- Started RTP media for channel " << GetNumber() << ": ";
cout << ((GetDirection()==H323Channel::IsTransmitter)?"sending ":((GetDirection()==H323Channel::IsReceiver)?"receiving ":" "));
cout << (const char *)(GetCapability()).GetFormatName() << endl;
}
if(!GetRemoteAddress(remoteIpAddress, remotePort) && h323debug)
cout << " ** Unable to get remote IP address" << endl;
externalMediaAddress.GetIpAndPort(externalIpAddress, externalPort);
if (h323debug) {
cout << " -- remoteIpAddress: " << remoteIpAddress << endl;
cout << " -- remotePort: " << remotePort << endl;
cout << " -- ExternalIpAddress: " << externalIpAddress << endl;
cout << " -- ExternalPort: " << externalPort << endl;
}
const OpalMediaFormat & mediaFormat = codec->GetMediaFormat();
if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType) {
rtpPayloadType = capability->GetPayloadType();
if (rtpPayloadType == RTP_DataFrame::IllegalPayloadType)
rtpPayloadType = mediaFormat.GetPayloadType();
}
/* Deduce direction of starting channel */
int direction;
if (GetDirection()==H323Channel::IsTransmitter)
direction = 1;
else if (GetDirection()==H323Channel::IsReceiver)
direction = 0;
else
direction = -1;
/* Notify Asterisk of remote RTP information */
/* direction and payload arguments needs to
* correctly setup RTP transport
*/
on_start_logical_channel(connection.GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort, direction, (int)rtpPayloadType);
return TRUE;
} }
/* MyH323Connection */ /* MyH323Connection */
MyH323Connection::MyH323Connection(MyH323EndPoint & ep, MyH323Connection::MyH323Connection(MyH323EndPoint & ep,
unsigned callReference, unsigned callReference,
unsigned options) unsigned options)
: H323Connection(ep, : H323Connection(ep,
callReference, callReference,
options) options)
{ {
remoteIpAddress = 0; // IP Address of remote endpoint remoteIpAddress = 0; // IP Address of remote endpoint
remotePort = 0; // remote endpoint Data port (control is dataPort+1) remotePort = 0; // remote endpoint Data port (control is dataPort+1)
progressSetup = global_options.progress_setup;
progressAlert = global_options.progress_alert;
if (h323debug)
cout << " == New H.323 Connection created." << endl;
return;
}
/* MyH323Connection */
MyH323Connection::MyH323Connection(MyH323EndPoint & ep,
unsigned callReference,
unsigned options,
call_options_t *call_options)
: H323Connection(ep,
callReference,
options)
{
remoteIpAddress = 0; // IP Address of remote endpoint
remotePort = 0; // remote endpoint Data port (control is dataPort+1)
if (!call_options)
call_options = &global_options;
progressSetup = call_options->progress_setup;
progressAlert = call_options->progress_alert;
if (h323debug) if (h323debug)
cout << " == New H.323 Connection created." << endl; cout << " == New H.323 Connection created." << endl;
@ -496,20 +648,118 @@ MyH323Connection::~MyH323Connection()
return; return;
} }
/* Declare reference to standard Asterisk's callerid parser */
extern "C" {
void ast_callerid_parse(const char *, char **, char **);
}
/*
* Setup H.323 caller ID to allow OpenH323 to set up Q.931's
* IE:DisplayName and IE:DisplayNumber fields correctly
*/
void MyH323Connection::SetCID(const char *callerid)
{
char *name;
char *num;
ast_callerid_parse(callerid, &name, &num);
if (h323debug)
cout << "name=" << name << ", num=" << num << endl;
if ((name && *name) || (num && *num))
{
localAliasNames.RemoveAll();
if(name && *name) {
SetLocalPartyName(PString(name));
// localAliasNames.AppendString(name);
}
if(num && *num)
localAliasNames.AppendString(PString(num));
}
}
BOOL MyH323Connection::OnReceivedProgress(const H323SignalPDU & pdu)
{
BOOL res;
res = H323Connection::OnReceivedProgress(pdu);
if(res && on_progress) {
BOOL inband;
unsigned ProgressPI;
if(!pdu.GetQ931().GetProgressIndicator(ProgressPI))
ProgressPI = 0;
if(h323debug)
cout << "Progress Indicator is " << ProgressPI << endl;
/* XXX Is this correct? XXX */
switch(ProgressPI) {
case Q931::ProgressNotEndToEndISDN:
case Q931::ProgressInbandInformationAvailable:
inband = TRUE;
break;
default:
inband = FALSE;
}
on_progress(GetCallReference(), inband);
}
return res;
}
H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller, H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString & caller,
const H323SignalPDU & /*setupPDU*/, const H323SignalPDU & setupPDU,
H323SignalPDU & /*connectPDU*/) H323SignalPDU & /*connectPDU*/)
{ {
unsigned ProgressInd;
/* The call will be answered later with "AnsweringCall()" function. /* The call will be answered later with "AnsweringCall()" function.
*/ */
if(!setupPDU.GetQ931().GetProgressIndicator(ProgressInd))
ProgressInd = 0;
if(h323debug)
cout << "PI in SETUP was " << ProgressInd << endl;
/* Progress indicator must be always set to 8 if Setup Have Progress indicator equal to 3 */
if(progressAlert)
ProgressInd = progressAlert;
else if(ProgressInd == Q931::ProgressOriginNotISDN)
ProgressInd = Q931::ProgressInbandInformationAvailable;
if(ProgressInd)
alertingPDU->GetQ931().SetProgressIndicator(ProgressInd);
if(h323debug)
cout << "Adding PI=" << ProgressInd << " to ALERT message" << endl;
return H323Connection::AnswerCallAlertWithMedia; return H323Connection::AnswerCallAlertWithMedia;
} }
BOOL MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username) BOOL MyH323Connection::OnAlerting(const H323SignalPDU & alertingPDU, const PString & username)
{ {
if (h323debug) if (h323debug)
cout << " -- Ringing phone for \"" << username << "\"" << endl; cout << " -- Ringing phone for \"" << username << "\"" << endl;
if (on_progress) {
BOOL inband;
unsigned alertingPI;
if(!alertingPDU.GetQ931().GetProgressIndicator(alertingPI))
alertingPI = 0;
if(h323debug)
cout << "Progress Indicator is " << alertingPI << endl;
/* XXX Is this correct? XXX */
switch(alertingPI) {
case Q931::ProgressNotEndToEndISDN:
case Q931::ProgressInbandInformationAvailable:
inband = TRUE;
break;
default:
inband = FALSE;
}
on_progress(GetCallReference(), inband);
}
return TRUE; return TRUE;
} }
@ -523,6 +773,7 @@ BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
PString sourceE164; PString sourceE164;
PString destE164; PString destE164;
PString redirE164;
PString sourceAliases; PString sourceAliases;
PString destAliases; PString destAliases;
PString sourceIp; PString sourceIp;
@ -537,19 +788,12 @@ BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
setupPDU.GetSourceE164(sourceE164); setupPDU.GetSourceE164(sourceE164);
destE164 = ""; destE164 = "";
setupPDU.GetDestinationE164(destE164); setupPDU.GetDestinationE164(destE164);
if(!setupPDU.GetQ931().GetRedirectingNumber(redirE164))
redirE164 = "";
/* Convert complex strings */ /* Use common alias formatting routine */
// FIXME: deal more than one source alias FormatAliases(sourceAliases);
char *s; FormatAliases(destAliases);
if ((s = strchr(sourceAliases, ' ')) != NULL)
*s = '\0';
if ((s = strchr(sourceAliases, '\t')) != NULL)
*s = '\0';
char *s1;
if ((s1 = strchr(destAliases, ' ')) != NULL)
*s1 = '\0';
if ((s1 = strchr(destAliases, '\t')) != NULL)
*s1 = '\0';
GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort); GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort);
@ -557,20 +801,24 @@ BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU)
cd.call_reference = GetCallReference(); cd.call_reference = GetCallReference();
cd.call_token = (const char *)GetCallToken(); cd.call_token = (const char *)GetCallToken();
cd.call_source_aliases = (const char *)sourceAliases; cd.call_source_aliases = (const char *)sourceAliases;
cd.call_dest_alias = (const char *)destAliases; cd.call_dest_alias = (const char *)destAliases;
cd.call_source_e164 = (const char *)sourceE164; cd.call_source_e164 = (const char *)sourceE164;
cd.call_dest_e164 = (const char *)destE164; cd.call_dest_e164 = (const char *)destE164;
cd.sourceIp = (const char *)sourceIp; cd.call_redir_e164 = (const char *)redirE164;
cd.sourceIp = (const char *)sourceIp;
/* Notify Asterisk of the request */ /* Notify Asterisk of the request */
int res = on_incoming_call(cd); call_options_t *res = on_incoming_call(cd);
if (!res) { if (!res) {
if (h323debug) if (h323debug)
cout << " -- Call Failed" << endl; cout << " -- Call Failed" << endl;
return FALSE; return FALSE;
} }
progressSetup = res->progress_setup;
progressAlert = res->progress_alert;
return H323Connection::OnReceivedSignalSetup(setupPDU); return H323Connection::OnReceivedSignalSetup(setupPDU);
} }
@ -590,22 +838,13 @@ BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
destE164 = ""; destE164 = "";
setupPDU.GetDestinationE164(destE164); setupPDU.GetDestinationE164(destE164);
/* Convert complex strings */ /* Use common alias formatting routine */
// FIXME: deal more than one source alias FormatAliases(sourceAliases);
char *s; FormatAliases(destAliases);
if ((s = strchr(sourceAliases, ' ')) != NULL)
*s = '\0';
if ((s = strchr(sourceAliases, '\t')) != NULL)
*s = '\0';
char *s1;
if ((s1 = strchr(destAliases, ' ')) != NULL)
*s1 = '\0';
if ((s1 = strchr(destAliases, '\t')) != NULL)
*s1 = '\0';
cd.call_reference = GetCallReference(); cd.call_reference = GetCallReference();
cd.call_token = (const char *)GetCallToken(); cd.call_token = (const char *)GetCallToken();
cd.call_source_aliases = (const char *)sourceAliases; cd.call_source_aliases = (const char *)sourceAliases;
cd.call_dest_alias = (const char *)destAliases; cd.call_dest_alias = (const char *)destAliases;
cd.call_source_e164 = (const char *)sourceE164; cd.call_source_e164 = (const char *)sourceE164;
cd.call_dest_e164 = (const char *)destE164; cd.call_dest_e164 = (const char *)destE164;
@ -618,6 +857,10 @@ BOOL MyH323Connection::OnSendSignalSetup(H323SignalPDU & setupPDU)
return FALSE; return FALSE;
} }
if(progressSetup)
setupPDU.GetQ931().SetProgressIndicator(progressSetup);
// setupPDU.GetQ931().SetProgressIndicator(Q931::ProgressInbandInformationAvailable);
// setupPDU.GetQ931().SetProgressIndicator(Q931::ProgressOriginNotISDN);
return H323Connection::OnSendSignalSetup(setupPDU); return H323Connection::OnSendSignalSetup(setupPDU);
} }
@ -708,7 +951,7 @@ H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capabilit
cout << " -- SessionID: " << sessionID << endl; cout << " -- SessionID: " << sessionID << endl;
cout << " -- Direction: " << dir << endl; cout << " -- Direction: " << dir << endl;
} }
return new H323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort); return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
} }
/** This callback function is invoked once upon creation of each /** This callback function is invoked once upon creation of each
@ -717,7 +960,8 @@ H323Channel * MyH323Connection::CreateRealTimeLogicalChannel(const H323Capabilit
BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel) BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
{ {
if (h323debug) { if (h323debug) {
cout << " -- Started logical channel: "; /* Show H.323 channel number to make debugging more comfortable */
cout << " -- Started logical channel " << channel.GetNumber() << ": ";
cout << ((channel.GetDirection()==H323Channel::IsTransmitter)?"sending ":((channel.GetDirection()==H323Channel::IsReceiver)?"receiving ":" ")); cout << ((channel.GetDirection()==H323Channel::IsTransmitter)?"sending ":((channel.GetDirection()==H323Channel::IsReceiver)?"receiving ":" "));
cout << (const char *)(channel.GetCapability()).GetFormatName() << endl; cout << (const char *)(channel.GetCapability()).GetFormatName() << endl;
} }
@ -726,8 +970,10 @@ BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
if (h323debug) if (h323debug)
cout << " -- channelsOpen = " << channelsOpen << endl; cout << " -- channelsOpen = " << channelsOpen << endl;
#if 0
H323_ExternalRTPChannel & external = (H323_ExternalRTPChannel &)channel; H323_ExternalRTPChannel & external = (H323_ExternalRTPChannel &)channel;
external.GetRemoteAddress(remoteIpAddress, remotePort); if(!external.GetRemoteAddress(remoteIpAddress, remotePort) && h323debug)
cout << " ** Unable to get remote IP address" << endl;
if (h323debug) { if (h323debug) {
cout << " -- remoteIpAddress: " << remoteIpAddress << endl; cout << " -- remoteIpAddress: " << remoteIpAddress << endl;
@ -735,8 +981,49 @@ BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel)
cout << " -- ExternalIpAddress: " << externalIpAddress << endl; cout << " -- ExternalIpAddress: " << externalIpAddress << endl;
cout << " -- ExternalPort: " << externalPort << endl; cout << " -- ExternalPort: " << externalPort << endl;
} }
/* Try to determine negotiated RTP payload format to configure
* RTP stack more quickly (not to wait at least one packet with
* filled RTP payload
*/
RTP_DataFrame::PayloadTypes payloadType = channel.GetCapability().GetPayloadType();
cout << " *** channel's payload is " << payloadType << endl;
if (payloadType == RTP_DataFrame::IllegalPayloadType) {
payloadType = channel.GetCodec()->GetMediaFormat().GetPayloadType();
cout << " *** channel's codec payload is " << payloadType << endl;
}
if ((payloadType == RTP_DataFrame::IllegalPayloadType) || (payloadType >= RTP_DataFrame::DynamicBase)) {
OpalMediaFormat mediaFormat = channel.GetCodec()->GetMediaFormat();
// if (mediaFormat.GetPayloadType() < RTP_DataFrame::DynamicBase)
{
payloadType = mediaFormat.GetPayloadType();
cout << " *** channel's Opal media payload is " << payloadType << endl;
}
}
// if ((payloadType == RTP_DataFrame::IllegalPayloadType)) {
// OpalMediaFormat OMF((const char *)(channel.GetCapability()).GetFormatName(), 1);
// if (OMF.IsValid())
// {
// payloadType = OMF.GetPayloadType();
// cout << " *** channel's OMF payload is " << payloadType << endl;
// }
// }
/* Deduce direction of starting channel */
int direction;
if (channel.GetDirection()==H323Channel::IsTransmitter)
direction = 1;
else if (channel.GetDirection()==H323Channel::IsReceiver)
direction = 0;
else
direction = -1;
/* Notify Asterisk of remote RTP information */ /* Notify Asterisk of remote RTP information */
on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort); /* direction and payload arguments needs to
* correctly setup RTP transport
*/
on_start_logical_channel(GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort, direction, (int)payloadType);
#endif
return TRUE; return TRUE;
} }
@ -799,7 +1086,6 @@ void h323_gk_urq(void)
cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl; cout << " ERROR: [h323_gk_urq] No Endpoint, this is bad" << endl;
return; return;
} }
endPoint->RemoveGatekeeper(); endPoint->RemoveGatekeeper();
} }
@ -823,7 +1109,8 @@ void h323_callback_register(setup_incoming_cb ifunc,
start_logchan_cb lfunc, start_logchan_cb lfunc,
clear_con_cb clfunc, clear_con_cb clfunc,
con_established_cb efunc, con_established_cb efunc,
send_digit_cb dfunc) send_digit_cb dfunc,
progress_cb pgfunc)
{ {
on_incoming_call = ifunc; on_incoming_call = ifunc;
on_outgoing_call = sfunc; on_outgoing_call = sfunc;
@ -832,6 +1119,7 @@ void h323_callback_register(setup_incoming_cb ifunc,
on_connection_cleared = clfunc; on_connection_cleared = clfunc;
on_connection_established = efunc; on_connection_established = efunc;
on_send_digit = dfunc; on_send_digit = dfunc;
on_progress = pgfunc;
} }
/** /**
@ -840,7 +1128,8 @@ void h323_callback_register(setup_incoming_cb ifunc,
int h323_set_capability(int cap, int dtmfMode) int h323_set_capability(int cap, int dtmfMode)
{ {
int g711Frames = 30; int g711Frames = 30;
int gsmFrames = 4; int gsmFrames = 4;
PINDEX last_cap = -1; /* last common capability block index */
if (!h323_end_point_exist()) { if (!h323_end_point_exist()) {
@ -848,61 +1137,74 @@ int h323_set_capability(int cap, int dtmfMode)
return 1; return 1;
} }
mode = dtmfMode; /* User input mode moved to the end of procedure */
if (dtmfMode == H323_DTMF_INBAND)
endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
else
endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
/* Hardcode this for now (Someone tell me if T.38 works now /* Hardcode this for now (Someone tell me if T.38 works now
or provide me with some debug so we can make this work */ or provide me with some debug so we can make this work */
// endPoint->SetCapability(0, 0, new H323_T38Capability(H323_T38Capability::e_UDP)); // last_cap = endPoint->SetCapability(0, 0, new H323_T38Capability(H323_T38Capability::e_UDP));
if (cap & AST_FORMAT_SPEEX) { if (cap & AST_FORMAT_SPEEX) {
/* Not real sure if Asterisk acutally supports all /* Not real sure if Asterisk acutally supports all
of the various different bit rates so add them of the various different bit rates so add them
all and figure it out later*/ all and figure it out later*/
endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability()); last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow2AudioCapability());
endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability()); last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow3AudioCapability());
endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability()); last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow4AudioCapability());
endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability()); last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow5AudioCapability());
endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability()); last_cap = endPoint->SetCapability(0, 0, new SpeexNarrow6AudioCapability());
} }
if (cap & AST_FORMAT_G729A) { if (cap & AST_FORMAT_G729A) {
AST_G729ACapability *g729aCap; AST_G729ACapability *g729aCap;
AST_G729Capability *g729Cap; AST_G729Capability *g729Cap;
endPoint->SetCapability(0, 0, g729aCap = new AST_G729ACapability); last_cap = endPoint->SetCapability(0, 0, g729aCap = new AST_G729ACapability);
endPoint->SetCapability(0, 0, g729Cap = new AST_G729Capability); last_cap = endPoint->SetCapability(0, 0, g729Cap = new AST_G729Capability);
} }
if (cap & AST_FORMAT_G723_1) { if (cap & AST_FORMAT_G723_1) {
H323_G7231Capability *g7231Cap; H323_G7231Capability *g7231Cap, *g7231Cap1;
endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability); last_cap = endPoint->SetCapability(0, 0, g7231Cap = new H323_G7231Capability);
last_cap = endPoint->SetCapability(0, 0, g7231Cap1 = new H323_G7231Capability(FALSE));
} }
if (cap & AST_FORMAT_GSM) { if (cap & AST_FORMAT_GSM) {
H323_GSM0610Capability *gsmCap; H323_GSM0610Capability *gsmCap;
endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability); last_cap = endPoint->SetCapability(0, 0, gsmCap = new H323_GSM0610Capability);
gsmCap->SetTxFramesInPacket(gsmFrames); gsmCap->SetTxFramesInPacket(gsmFrames);
} }
if (cap & AST_FORMAT_ULAW) { if (cap & AST_FORMAT_ULAW) {
H323_G711Capability *g711uCap; H323_G711Capability *g711uCap;
endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw)); last_cap = endPoint->SetCapability(0, 0, g711uCap = new H323_G711Capability(H323_G711Capability::muLaw));
g711uCap->SetTxFramesInPacket(g711Frames); g711uCap->SetTxFramesInPacket(g711Frames);
} }
if (cap & AST_FORMAT_ALAW) { if (cap & AST_FORMAT_ALAW) {
H323_G711Capability *g711aCap; H323_G711Capability *g711aCap;
endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw)); last_cap = endPoint->SetCapability(0, 0, g711aCap = new H323_G711Capability(H323_G711Capability::ALaw));
g711aCap->SetTxFramesInPacket(g711Frames); g711aCap->SetTxFramesInPacket(g711Frames);
} }
/* Add HookFlash capability - not used yet now */
last_cap++;
last_cap = endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::HookFlashH245));
/* Add correct UserInputMode capability
* This allows remote party to send UserIput
* correctly embedded into protocol
*/
last_cap++;
mode = dtmfMode;
if (dtmfMode == H323_DTMF_INBAND) {
endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneH245));
endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsTone);
} else {
endPoint->SetCapability(0, last_cap, new H323_UserInputCapability(H323_UserInputCapability::SignalToneRFC2833));
endPoint->SetSendUserInputMode(H323Connection::SendUserInputAsInlineRFC2833);
}
return 0; return 0;
} }
@ -1054,7 +1356,7 @@ void h323_send_tone(const char *call_token, char tone)
/** Make a call to the remote endpoint. /** Make a call to the remote endpoint.
*/ */
int h323_make_call(char *host, call_details_t *cd, call_options_t call_options) int h323_make_call(char *host, call_details_t *cd, call_options_t *call_options)
{ {
int res; int res;
PString token; PString token;
@ -1065,7 +1367,7 @@ int h323_make_call(char *host, call_details_t *cd, call_options_t call_options)
PString dest(host); PString dest(host);
res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options.port, call_options.callerid); res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options);
memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength()); memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
return res; return res;
@ -1142,6 +1444,3 @@ void h323_native_bridge(const char *token, char *them, char *capability)
} }
} /* extern "C" */ } /* extern "C" */

View File

@ -88,7 +88,7 @@ class H323_G7231Capability : public H323AudioCapability
H245_AudioCapability & pdu, /// PDU to set information on H245_AudioCapability & pdu, /// PDU to set information on
unsigned packetSize /// Packet size to use in capability unsigned packetSize /// Packet size to use in capability
) const; ) const;
BOOL OnReceivedPDU( BOOL OnReceivedPDU(
const H245_AudioCapability & pdu, /// PDU to get information from const H245_AudioCapability & pdu, /// PDU to get information from
unsigned & packetSize /// Packet size to use in capability unsigned & packetSize /// Packet size to use in capability
@ -198,7 +198,7 @@ class MyH323EndPoint : public H323EndPoint {
public: public:
int MakeCall(const PString &, PString &, unsigned int *, unsigned int, char *); int MakeCall(const PString &, PString &, unsigned int *, call_options_t *);
BOOL ClearCall(const PString &); BOOL ClearCall(const PString &);
void OnClosedLogicalChannel(H323Connection &, const H323Channel &); void OnClosedLogicalChannel(H323Connection &, const H323Channel &);
@ -213,9 +213,8 @@ class MyH323EndPoint : public H323EndPoint {
PStringArray SupportedPrefixes; PStringArray SupportedPrefixes;
void SetEndpointTypeInfo( H225_EndpointType & info ) const; void SetEndpointTypeInfo( H225_EndpointType & info ) const;
void SetGateway(void); void SetGateway(void);
}; };
@ -225,6 +224,7 @@ class MyH323Connection : public H323Connection {
public: public:
MyH323Connection(MyH323EndPoint &, unsigned, unsigned); MyH323Connection(MyH323EndPoint &, unsigned, unsigned);
MyH323Connection(MyH323EndPoint &, unsigned, unsigned, call_options_t *);
~MyH323Connection(); ~MyH323Connection();
H323Channel * CreateRealTimeLogicalChannel(const H323Capability &, H323Channel::Directions, unsigned, H323Channel * CreateRealTimeLogicalChannel(const H323Capability &, H323Channel::Directions, unsigned,
@ -241,6 +241,9 @@ class MyH323Connection : public H323Connection {
void SendUserInputTone(char, unsigned); void SendUserInputTone(char, unsigned);
void OnUserInputTone(char, unsigned, unsigned, unsigned); void OnUserInputTone(char, unsigned, unsigned, unsigned);
void OnUserInputString(const PString &value); void OnUserInputString(const PString &value);
BOOL OnReceivedProgress(const H323SignalPDU &);
/* Set up H.323 caller id */
void SetCID(const char *callerid);
PString sourceAliases; PString sourceAliases;
PString destAliases; PString destAliases;
@ -248,11 +251,53 @@ class MyH323Connection : public H323Connection {
PString destE164; PString destE164;
PIPSocket::Address externalIpAddress; // IP address of media server PIPSocket::Address externalIpAddress; // IP address of media server
PIPSocket::Address remoteIpAddress; // IP Address of remote endpoint PIPSocket::Address remoteIpAddress; // IP Address of remote endpoint
WORD externalPort; // local media server Data port (control is dataPort+1) WORD externalPort; // local media server Data port (control is dataPort+1)
WORD remotePort; // remote endpoint Data port (control is dataPort+1) WORD remotePort; // remote endpoint Data port (control is dataPort+1)
WORD sessionId; WORD sessionId;
BOOL bridging; // Used to help determine which IP to use BOOL bridging; // Used to help determine which IP to use
unsigned progressSetup; // ProgressIndicator IE value for SETUP message
unsigned progressAlert; // ProgressIndicator IE value for ALERT message
};
class MyH323_ExternalRTPChannel : public H323_ExternalRTPChannel
{
PCLASSINFO(MyH323_ExternalRTPChannel, H323_ExternalRTPChannel);
public:
/**@name Construction */
//@{
/**Create a new channel.
*/
MyH323_ExternalRTPChannel(
H323Connection & connection, /// Connection to endpoint for channel
const H323Capability & capability, /// Capability channel is using
Directions direction, /// Direction of channel
unsigned sessionID /// Session ID for channel
);
/**Create a new channel.
*/
MyH323_ExternalRTPChannel(
H323Connection & connection, /// Connection to endpoint for channel
const H323Capability & capability, /// Capability channel is using
Directions direction, /// Direction of channel
unsigned sessionID, /// Session ID for channel
const H323TransportAddress & data, /// Data address
const H323TransportAddress & control/// Control address
);
/**Create a new channel.
*/
MyH323_ExternalRTPChannel(
H323Connection & connection, /// Connection to endpoint for channel
const H323Capability & capability, /// Capability channel is using
Directions direction, /// Direction of channel
unsigned sessionID, /// Session ID for channel
const PIPSocket::Address & ip, /// IP address of media server
WORD dataPort /// Data port (control is dataPort+1)
);
//@}
// BOOL OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param);
BOOL Start(void);
}; };
@ -348,5 +393,3 @@ class ClearCallThread : public PThread {
protected: protected:
PString token; PString token;
}; };

View File

@ -28,7 +28,23 @@
#include <arpa/inet.h> #include <arpa/inet.h>
static struct sockaddr_in bindaddr; //static struct sockaddr_in bindaddr;
/** call_option struct is filled from the
PBX application and passed through make_call
function*/
typedef struct call_options {
char *callerid;
int noFastStart;
int noH245Tunnelling;
int noSilenceSuppression;
int progress_setup;
int progress_alert;
int progress_audio;
unsigned int port;
} call_options_t;
extern call_options_t global_options;
/* structure to hold the valid asterisk users */ /* structure to hold the valid asterisk users */
struct oh323_user { struct oh323_user {
@ -38,15 +54,13 @@ struct oh323_user {
char callerid[80]; char callerid[80];
char accountcode[20]; char accountcode[20];
int amaflags; int amaflags;
int noFastStart;
int noH245Tunneling;
int noSilenceSuppression;
int inUse; int inUse;
int incominglimit; int incominglimit;
int bridge; int bridge;
int nat; int nat;
int dtmfmode; int dtmfmode;
int host; int host;
call_options_t call_options;
struct ast_ha *ha; struct ast_ha *ha;
struct sockaddr_in addr; struct sockaddr_in addr;
struct oh323_user *next; struct oh323_user *next;
@ -57,9 +71,6 @@ struct oh323_user {
struct oh323_peer { struct oh323_peer {
char name[80]; char name[80];
char context[80]; char context[80];
int noFastStart;
int noH245Tunneling;
int noSilenceSuppression;
int inUse; int inUse;
int outgoinglimit; int outgoinglimit;
int bridge; int bridge;
@ -67,6 +78,7 @@ struct oh323_peer {
int dtmfmode; int dtmfmode;
struct sockaddr_in addr; struct sockaddr_in addr;
int delme; int delme;
call_options_t call_options;
struct oh323_peer *next; struct oh323_peer *next;
}; };
@ -81,17 +93,6 @@ struct oh323_alias {
struct oh323_alias *next; struct oh323_alias *next;
}; };
/** call_option struct is filled from the
PBX application and passed through make_call
function*/
typedef struct call_options {
char *callerid;
int noFastStart;
int noH245Tunnelling;
int noSilenceSuppression;
unsigned int port;
} call_options_t;
/** call_details struct call detail records /** call_details struct call detail records
to asterisk for processing and used for matching up to asterisk for processing and used for matching up
asterisk channels to acutal h.323 connections */ asterisk channels to acutal h.323 connections */
@ -103,6 +104,7 @@ typedef struct call_details {
const char *call_dest_alias; const char *call_dest_alias;
const char *call_source_e164; const char *call_source_e164;
const char *call_dest_e164; const char *call_dest_e164;
const char *call_redir_e164;
const char *sourceIp; const char *sourceIp;
} call_details_t; } call_details_t;
@ -123,7 +125,7 @@ on_connection_cb on_create_connection;
/* This is a callback prototype function, called upon /* This is a callback prototype function, called upon
an incoming call happens. */ an incoming call happens. */
typedef int (*setup_incoming_cb)(call_details_t); typedef call_options_t *(*setup_incoming_cb)(call_details_t);
setup_incoming_cb on_incoming_call; setup_incoming_cb on_incoming_call;
/* This is a callback prototype function, called upon /* This is a callback prototype function, called upon
@ -132,8 +134,10 @@ typedef int (*setup_outbound_cb)(call_details_t);
setup_outbound_cb on_outgoing_call; setup_outbound_cb on_outgoing_call;
/* This is a callback prototype function, called when the openh323 /* This is a callback prototype function, called when the openh323
OnStartLogicalChannel is invoked. */ OnStartLogicalChannel is invoked.
typedef void (*start_logchan_cb)(unsigned int, const char *, int); 2 more arguments - direction and payload type.
*/
typedef void (*start_logchan_cb)(unsigned int, const char *, int, int, int);
start_logchan_cb on_start_logical_channel; start_logchan_cb on_start_logical_channel;
/* This is a callback protoype function, called when the openh323 /* This is a callback protoype function, called when the openh323
@ -146,15 +150,33 @@ con_established_cb on_connection_established;
typedef void (*clear_con_cb)(call_details_t); typedef void (*clear_con_cb)(call_details_t);
clear_con_cb on_connection_cleared; clear_con_cb on_connection_cleared;
/* This is a callback prototype function, called when the openh323
OnReceivedAckPDU is invoked. */
typedef void (*setup_rtp_cb)(unsigned int, const char *, int);
setup_rtp_cb on_setup_rtp_peer;
typedef int (*progress_cb)(unsigned, int);
progress_cb on_progress;
/* debug flag */ /* debug flag */
int h323debug; int h323debug;
#define H323_DTMF_RFC2833 (1 << 0) #define H323_DTMF_RFC2833 (1 << 0)
#define H323_DTMF_INBAND (1 << 1) #define H323_DTMF_INBAND (1 << 1)
/* Required to declare global variables from chan_h323.c */
#ifndef BOOL
#define BOOL int
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* chan_h323 global parameters */
extern BOOL noFastStart;
extern BOOL noH245Tunnelling;
extern BOOL noSilenceSuppression;
void h323_gk_urq(void); void h323_gk_urq(void);
void h323_end_point_create(void); void h323_end_point_create(void);
@ -165,13 +187,13 @@ extern "C" {
/* callback function handler*/ /* callback function handler*/
void h323_callback_register(setup_incoming_cb, void h323_callback_register(setup_incoming_cb,
setup_outbound_cb, setup_outbound_cb,
on_connection_cb, on_connection_cb,
start_logchan_cb, start_logchan_cb,
clear_con_cb, clear_con_cb,
con_established_cb, con_established_cb,
send_digit_cb); send_digit_cb,
progress_cb);
int h323_set_capability(int, int); int h323_set_capability(int, int);
int h323_set_alias(struct oh323_alias *); int h323_set_alias(struct oh323_alias *);
@ -188,7 +210,7 @@ extern "C" {
void h323_send_tone(const char *call_token, char tone); void h323_send_tone(const char *call_token, char tone);
/* H323 create and destroy sessions */ /* H323 create and destroy sessions */
int h323_make_call(char *host, call_details_t *cd, call_options_t); int h323_make_call(char *host, call_details_t *cd, call_options_t *call_options);
int h323_clear_call(const char *); int h323_clear_call(const char *);
int h323_answering_call(const char *token, int); int h323_answering_call(const char *token, int);

View File

@ -52,6 +52,13 @@ allow=gsm ; Always allow GSM, it's cool :)
; use user authentication at all. ; use user authentication at all.
; ;
;context=default ;context=default
;noFastStart = no
;noH245Tunneling = no
;noSilenceSuppression = yes
;progress_setup = 3
;progress_alert = 8
;progress_audio = yes
; ;
; H.323 Alias definitions ; H.323 Alias definitions
; ;