[svn-commits] pcadach: branch pcadach/chan_h323_exts r39499 - in
/team/pcadach/chan_h323_ex...
svn-commits at lists.digium.com
svn-commits at lists.digium.com
Wed Aug 9 19:30:54 MST 2006
Author: pcadach
Date: Wed Aug 9 21:30:53 2006
New Revision: 39499
URL: http://svn.digium.com/view/asterisk?rev=39499&view=rev
Log:
Changes to revision 10761 with all modifications.
Added:
team/pcadach/chan_h323_exts/channels/h323/ast_t38.cpp (with props)
team/pcadach/chan_h323_exts/channels/h323/ast_t38.h (with props)
team/pcadach/chan_h323_exts/channels/h323/ast_video.cpp (with props)
team/pcadach/chan_h323_exts/channels/h323/ast_video.h (with props)
Modified:
team/pcadach/chan_h323_exts/Makefile
team/pcadach/chan_h323_exts/apps/Makefile
team/pcadach/chan_h323_exts/apps/app_voicemail.c
team/pcadach/chan_h323_exts/channel.c
team/pcadach/chan_h323_exts/channels/chan_h323.c
team/pcadach/chan_h323_exts/channels/chan_iax2.c
team/pcadach/chan_h323_exts/channels/chan_sip.c
team/pcadach/chan_h323_exts/channels/h323/Makefile
team/pcadach/chan_h323_exts/channels/h323/ast_h323.cpp
team/pcadach/chan_h323_exts/channels/h323/ast_h323.h
team/pcadach/chan_h323_exts/channels/h323/chan_h323.h
team/pcadach/chan_h323_exts/codecs/Makefile
team/pcadach/chan_h323_exts/configs/sip.conf.sample
team/pcadach/chan_h323_exts/frame.c
team/pcadach/chan_h323_exts/include/asterisk/channel.h
team/pcadach/chan_h323_exts/rtp.c
team/pcadach/chan_h323_exts/udptl.c
Modified: team/pcadach/chan_h323_exts/Makefile
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323_exts/Makefile?rev=39499&r1=39498&r2=39499&view=diff
==============================================================================
--- team/pcadach/chan_h323_exts/Makefile (original)
+++ team/pcadach/chan_h323_exts/Makefile Wed Aug 9 21:30:53 2006
@@ -53,7 +53,7 @@
endif
#Overwite config files on "make samples"
-OVERWRITE=y
+OVERWRITE=n
#Include debug and macro symbols in the executables (-g) and profiling info (-pg)
DEBUG=-g3 #-pg
@@ -79,7 +79,7 @@
WITH_SMDI = 1
# Optional debugging parameters
-DEBUG_THREADS = #-DDUMP_SCHEDULER #-DDEBUG_SCHEDULER #-DDEBUG_THREADS #-DDO_CRASH #-DDETECT_DEADLOCKS
+DEBUG_THREADS = -DDEBUG_THREADS -DDO_CRASH -DDETECT_DEADLOCKS
# Uncomment next one to enable ast_frame tracing (for debugging)
TRACE_FRAMES = #-DTRACE_FRAMES
Modified: team/pcadach/chan_h323_exts/apps/Makefile
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323_exts/apps/Makefile?rev=39499&r1=39498&r2=39499&view=diff
==============================================================================
--- team/pcadach/chan_h323_exts/apps/Makefile (original)
+++ team/pcadach/chan_h323_exts/apps/Makefile Wed Aug 9 21:30:53 2006
@@ -30,6 +30,10 @@
ifeq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/osp/osp.h $(CROSS_COMPILE_TARGET)/usr/include/osp/osp.h),)
MODS:=$(filter-out app_osplookup.so,$(MODS))
+endif
+
+ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/spandsp.h $(CROSS_COMPILE_TARGET)/usr/include/spandsp.h),)
+APPS+=app_rxfax.so app_txfax.so
endif
ifneq ($(shell if [[ 0x`$(CROSS_COMPILE_BIN)curl-config --vernum` -ge 0x70907 ]]; then echo "OK" ; fi),)
@@ -86,6 +90,12 @@
app_curl.so: app_curl.o
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} $(CURLLIBS)
+app_rxfax.so : app_rxfax.o
+ $(CC) $(SOLINK) -o $@ $< -lspandsp -ltiff
+
+app_txfax.so : app_txfax.o
+ $(CC) $(SOLINK) -o $@ $< -lspandsp -ltiff
+
look: look.c
$(CC) -pipe -O6 -g look.c -o look -lncurses
Modified: team/pcadach/chan_h323_exts/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323_exts/apps/app_voicemail.c?rev=39499&r1=39498&r2=39499&view=diff
==============================================================================
--- team/pcadach/chan_h323_exts/apps/app_voicemail.c (original)
+++ team/pcadach/chan_h323_exts/apps/app_voicemail.c Wed Aug 9 21:30:53 2006
@@ -4499,6 +4499,79 @@
return res;
}
+static int get_lastdigits(int num)
+{
+ num %= 100;
+ return (num < 20) ? num : num % 10;
+}
+
+static int vm_intro_ru(struct ast_channel *chan,struct vm_state *vms)
+{
+ int res;
+ int lastnum;
+ int dcnum;
+
+ res = ast_play_and_wait(chan, "vm-youhave");
+ if (!res && vms->newmessages) {
+ lastnum = get_lastdigits(vms->newmessages);
+ dcnum = vms->newmessages - lastnum;
+ if (dcnum)
+ res = say_and_wait(chan, dcnum, chan->language);
+ if (!res && lastnum) {
+ if (lastnum == 1)
+ res = ast_play_and_wait(chan, "digits/ru/odno");
+ else
+ res = say_and_wait(chan, lastnum, chan->language);
+ }
+
+ if (!res)
+ res = ast_play_and_wait(chan, (lastnum == 1) ? "vm-novoe" : "vm-novyh");
+
+ if (!res && vms->oldmessages)
+ res = ast_play_and_wait(chan, "vm-and");
+ }
+
+ if (!res && vms->oldmessages) {
+ lastnum = get_lastdigits(vms->oldmessages);
+ dcnum = vms->newmessages - lastnum;
+ if (dcnum)
+ res = say_and_wait(chan, dcnum, chan->language);
+ if (!res && lastnum) {
+ if (lastnum == 1)
+ res = ast_play_and_wait(chan, "digits/ru/odno");
+ else
+ res = say_and_wait(chan, lastnum, chan->language);
+ }
+
+ if (!res)
+ res = ast_play_and_wait(chan, (lastnum == 1) ? "vm-staroe" : "vm-staryh");
+ }
+
+ if (!res && !vms->newmessages && !vms->oldmessages) {
+ lastnum = 0;
+ res = ast_play_and_wait(chan, "vm-no");
+ }
+
+ if (!res) {
+ switch(lastnum) {
+ case 1:
+ res = ast_play_and_wait(chan, "vm-soobshenie");
+ break;
+ case 2:
+ case 3:
+ case 4:
+ res = ast_play_and_wait(chan, "vm-soobsheniya");
+ break;
+ default:
+ res = ast_play_and_wait(chan, "vm-soobsheniy");
+ break;
+ }
+ }
+
+ return res;
+}
+
+
static int vm_intro(struct ast_channel *chan,struct vm_state *vms)
{
/* Play voicemail intro - syntax is different for different languages */
@@ -4522,6 +4595,8 @@
return vm_intro_se(chan, vms);
} else if (!strcasecmp(chan->language, "no")) { /* NORWEGIAN syntax */
return vm_intro_no(chan, vms);
+ } else if (!strcasecmp(chan->language, "ru")) { /* RUSSIAN syntax */
+ return vm_intro_ru(chan, vms);
} else { /* Default to ENGLISH */
return vm_intro_en(chan, vms);
}
Modified: team/pcadach/chan_h323_exts/channel.c
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323_exts/channel.c?rev=39499&r1=39498&r2=39499&view=diff
==============================================================================
--- team/pcadach/chan_h323_exts/channel.c (original)
+++ team/pcadach/chan_h323_exts/channel.c Wed Aug 9 21:30:53 2006
@@ -333,7 +333,7 @@
shutting_down = 1;
if (hangup) {
AST_LIST_LOCK(&channels);
- AST_LIST_TRAVERSE(&channels, c, list)
+ AST_LIST_TRAVERSE(&channels, c, chan_list)
ast_softhangup(c, AST_SOFTHANGUP_SHUTDOWN);
AST_LIST_UNLOCK(&channels);
}
@@ -345,7 +345,7 @@
struct ast_channel *c;
int cnt = 0;
AST_LIST_LOCK(&channels);
- AST_LIST_TRAVERSE(&channels, c, list)
+ AST_LIST_TRAVERSE(&channels, c, chan_list)
cnt++;
AST_LIST_UNLOCK(&channels);
return cnt;
@@ -682,7 +682,7 @@
tmp->tech = &null_tech;
AST_LIST_LOCK(&channels);
- AST_LIST_INSERT_HEAD(&channels, tmp, list);
+ AST_LIST_INSERT_HEAD(&channels, tmp, chan_list);
AST_LIST_UNLOCK(&channels);
return tmp;
}
@@ -816,7 +816,7 @@
for (retries = 0; retries < 10; retries++) {
AST_LIST_LOCK(&channels);
- AST_LIST_TRAVERSE(&channels, c, list) {
+ AST_LIST_TRAVERSE(&channels, c, chan_list) {
if (!prev) {
/* want head of list */
if (!name && !exten)
@@ -845,7 +845,7 @@
break;
}
} else if (c == prev) { /* found, return c->next */
- c = AST_LIST_NEXT(c, list);
+ c = AST_LIST_NEXT(c, chan_list);
break;
}
}
@@ -952,7 +952,7 @@
headp=&chan->varshead;
AST_LIST_LOCK(&channels);
- AST_LIST_REMOVE(&channels, chan, list);
+ AST_LIST_REMOVE(&channels, chan, chan_list);
/* Lock and unlock the channel just to be sure nobody
has it locked still */
ast_mutex_lock(&chan->lock);
@@ -2144,7 +2144,7 @@
if (chan->tech->send_digit)
res = chan->tech->send_digit(chan, digit);
- if (!(chan->tech->send_digit && chan->tech->send_digit_begin) ||
+ if (/*!(chan->tech->send_digit && chan->tech->send_digit_begin) ||*/
res) {
/*
* Device does not support DTMF tones, lets fake
@@ -2293,6 +2293,14 @@
else
res = 0;
break;
+#ifdef T38_SUPPORT
+ case AST_FRAME_MODEM:
+ if (chan->tech->write)
+ res = chan->tech->write(chan, fr);
+ else
+ res = 0;
+ break;
+#endif
case AST_FRAME_VOICE:
if (chan->tech->write) {
/* Bypass translator if we're writing format in the raw write format. This
@@ -3305,12 +3313,14 @@
}
continue;
}
+ if (option_verbose > 3)
+ ast_verbose(VERBOSE_PREFIX_4 "Reading frame from channel %s fdno %d\n", who->name, who->fdno);
f = ast_read(who);
if (!f) {
*fo = NULL;
*rc = who;
res = AST_BRIDGE_COMPLETE;
- ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s\n",who->name);
+ ast_log(LOG_DEBUG, "Didn't get a frame from channel: %s, fdno=%d\n",who->name, who->fdno);
break;
}
Modified: team/pcadach/chan_h323_exts/channels/chan_h323.c
URL: http://svn.digium.com/view/asterisk/team/pcadach/chan_h323_exts/channels/chan_h323.c?rev=39499&r1=39498&r2=39499&view=diff
==============================================================================
--- team/pcadach/chan_h323_exts/channels/chan_h323.c (original)
+++ team/pcadach/chan_h323_exts/channels/chan_h323.c Wed Aug 9 21:30:53 2006
@@ -73,11 +73,15 @@
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
+#ifdef T38_SUPPORT
+#include "asterisk/udptl.h"
+#endif
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/dsp.h"
#include "asterisk/causes.h"
+#include "asterisk/stringfields.h"
#ifdef __cplusplus
}
#endif
@@ -96,17 +100,22 @@
rfc2833_cb on_set_rfc2833_payload;
hangup_cb on_hangup;
setcapabilities_cb on_setcapabilities;
+setpeercapabilities_cb on_setpeercapabilities;
+stop_rtp_cb on_stop_rtp_channel;
+on_udptl_cb on_external_udptl_create;
+start_udptl_cb on_start_udptl_channel;
/* global debug flag */
int h323debug;
/** Variables required by Asterisk */
-static const char type[] = "H323";
static const char desc[] = "The NuFone Network's Open H.323 Channel Driver";
static const char tdesc[] = "The NuFone Network's Open H.323 Channel Driver";
static const char config[] = "h323.conf";
static char default_context[AST_MAX_CONTEXT] = "default";
static struct sockaddr_in bindaddr;
+
+#define GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_H261)
/** H.323 configuration values */
static int h323_signalling_port = 1720;
@@ -134,6 +143,11 @@
struct sockaddr_in sa; /* Our peer */
struct sockaddr_in redirip; /* Where our RTP should be going if not to us */
int nonCodecCapability; /* non-audio capability */
+#ifdef T38_SUPPORT
+// struct t38properties t38;
+ struct sockaddr_in udptlredirip;
+ struct ast_udptl *udptl;
+#endif
int outgoing; /* Outgoing or incoming call? */
char exten[AST_MAX_EXTENSION]; /* Requested extension */
char context[AST_MAX_CONTEXT]; /* Context where to start */
@@ -143,12 +157,22 @@
char rdnis[80]; /* Referring DNIS, if available */
int amaflags; /* AMA Flags */
struct ast_rtp *rtp; /* RTP Session */
+#ifdef VIDEO_SUPPORT
+ struct ast_rtp *vrtp;
+#endif
struct ast_dsp *vad; /* Used for in-band DTMF detection */
int nativeformats; /* Codec formats supported by a channel */
int needhangup; /* Send hangup when Asterisk is ready */
int hangupcause; /* Hangup cause from OpenH323 layer */
int newstate; /* Pending state change */
int newcontrol; /* Pending control to send */
+ int pref_codec; /* Preferred codec */
+ int peercapability; /* Capabilities learned from peer */
+ int jointcapability; /* Common capabilities for local and remote side */
+ int rtp_tx_enabled; /* While RTP tx is enabled */
+ int vrtp_tx_enabled;
+ struct sockaddr_in rtp_tx_addr;
+ struct sockaddr_in vrtp_tx_addr;
struct oh323_pvt *next; /* Next channel in list */
} *iflist = NULL;
@@ -206,9 +230,9 @@
static int oh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
static const struct ast_channel_tech oh323_tech = {
- .type = type,
+ .type = "H323",
.description = tdesc,
- .capabilities = AST_FORMAT_ULAW,
+ .capabilities = ((AST_FORMAT_MAX_AUDIO << 1) - 1),
.properties = AST_CHAN_TP_WANTSJITTER,
.requester = oh323_request,
.send_digit = oh323_digit,
@@ -217,10 +241,11 @@
.answer = oh323_answer,
.read = oh323_read,
.write = oh323_write,
+ .write_video = oh323_write,
.indicate = oh323_indicate,
.fixup = oh323_fixup,
/* disable, for now */
-#if 0
+#if 1
.bridge = ast_rtp_bridge,
#endif
};
@@ -306,6 +331,18 @@
ast_rtp_destroy(pvt->rtp);
}
+#ifdef VIDEO_SUPPORT
+ if (pvt->vrtp) {
+ ast_rtp_destroy(pvt->vrtp);
+ }
+#endif
+
+#ifdef T38_SUPPORT
+ if (pvt->udptl) {
+ ast_udptl_destroy(pvt->udptl);
+ }
+#endif
+
/* Free dsp used for in-band DTMF detection */
if (pvt->vad) {
ast_dsp_free(pvt->vad);
@@ -360,7 +397,7 @@
return -1;
}
ast_mutex_lock(&pvt->lock);
- if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833)) {
+ if (pvt->rtp && (pvt->options.dtmfmode & H323_DTMF_RFC2833) && pvt->rtp_tx_enabled) {
/* out-of-band DTMF */
if (h323debug) {
ast_log(LOG_DEBUG, "Sending out-of-band digit %c on %s\n", digit, c->name);
@@ -496,7 +533,7 @@
if (c->hangupcause) {
q931cause = c->hangupcause;
} else {
- char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS");
+ const char *cause = pbx_builtin_getvar_helper(c, "DIALSTATUS");
if (cause) {
if (!strcmp(cause, "CONGESTION")) {
q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
@@ -539,18 +576,48 @@
return 0;
}
-static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt)
+#ifdef T38_SUPPORT
+static struct ast_frame *oh323_rtp_read(struct ast_channel *chan, struct oh323_pvt *pvt, int *faxdetect)
+#else
+static struct ast_frame *oh323_rtp_read(struct ast_channel *chan, struct oh323_pvt *pvt)
+#endif
{
/* Retrieve audio/etc from channel. Assumes pvt->lock is already held. */
struct ast_frame *f;
+#if 0
/* Only apply it for the first packet, we just need the correct ip/port */
if (pvt->options.nat) {
ast_rtp_setnat(pvt->rtp, pvt->options.nat);
pvt->options.nat = 0;
}
-
- f = ast_rtp_read(pvt->rtp);
+#endif
+
+ switch(chan->fdno) {
+ case 0:
+ f = ast_rtp_read(pvt->rtp);
+ break;
+ case 1:
+ f = ast_rtcp_read(pvt->rtp);
+ break;
+#ifdef VIDEO_SUPPORT
+ case 2:
+ f = ast_rtp_read(pvt->vrtp);
+ break;
+ case 3:
+ f = ast_rtcp_read(pvt->vrtp);
+ break;
+#endif
+#ifdef T38_SUPPORT
+ case 4:
+ f = ast_udptl_read(pvt->udptl);
+ break;
+#endif
+ default:
+ f = &ast_null_frame;
+ break;
+ }
+
/* Don't send RFC2833 if we're not supposed to */
if (f && (f->frametype == AST_FRAME_DTMF) && !(pvt->options.dtmfmode & H323_DTMF_RFC2833)) {
return &ast_null_frame;
@@ -580,7 +647,15 @@
else
ast_log(LOG_NOTICE, "Unable to process inband DTMF while channel is locked\n");
if (f &&(f->frametype == AST_FRAME_DTMF)) {
- ast_log(LOG_DEBUG, "Received in-band digit %c.\n", f->subclass);
+#ifdef T38_SUPPORT
+ if (f->subclass == 'f') {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Fax CNG detected on %s\n", chan->name);
+ *faxdetect = 1;
+ }
+#endif
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Received in-band digit %c.\n", f->subclass);
}
}
}
@@ -592,10 +667,24 @@
{
struct ast_frame *fr;
struct oh323_pvt *pvt = (struct oh323_pvt *)c->tech_pvt;
+#ifdef T38_SUPPORT
+ int faxdetected = 0;
+#endif
ast_mutex_lock(&pvt->lock);
__oh323_update_info(c, pvt);
- fr = oh323_rtp_read(pvt);
+#ifdef T38_SUPPORT
+ fr = oh323_rtp_read(c, pvt, &faxdetected);
+#else
+ fr = oh323_rtp_read(c, pvt);
+#endif
ast_mutex_unlock(&pvt->lock);
+#ifdef T38_SUPPORT
+#if 0
+ if (faxdetected) {
+ oh323_mode_change();
+ }
+#endif
+#endif
return fr;
}
@@ -603,28 +692,58 @@
{
struct oh323_pvt *pvt = (struct oh323_pvt *) c->tech_pvt;
int res = 0;
- if (frame->frametype != AST_FRAME_VOICE) {
- if (frame->frametype == AST_FRAME_IMAGE) {
- return 0;
- } else {
- ast_log(LOG_WARNING, "Can't send %d type frames with H323 write\n", frame->frametype);
- return 0;
- }
- } else {
+
+ switch (frame->frametype) {
+ case AST_FRAME_IMAGE:
+ return 0;
+#ifdef T38_SUPPORT
+ case AST_FRAME_MODEM:
+ if (pvt) {
+ ast_mutex_lock(&pvt->lock);
+ if (pvt->udptl) {
+ res = ast_udptl_write(pvt->udptl, frame);
+ }
+ __oh323_update_info(c, pvt);
+ ast_mutex_unlock(&pvt->lock);
+ }
+ break;
+#endif
+ case AST_FRAME_VOICE:
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",
frame->subclass, c->nativeformats, c->readformat, c->writeformat);
return 0;
}
- }
- if (pvt) {
- ast_mutex_lock(&pvt->lock);
- if (pvt->rtp) {
- res = ast_rtp_write(pvt->rtp, frame);
- }
- __oh323_update_info(c, pvt);
- ast_mutex_unlock(&pvt->lock);
- }
+ if (pvt) {
+ ast_mutex_lock(&pvt->lock);
+ if (pvt->rtp && pvt->rtp_tx_enabled) {
+ res = ast_rtp_write(pvt->rtp, frame);
+ }
+// else if (h323debug)
+// ast_log(LOG_DEBUG, "RTP TX is disabled for %s\n", c->name);
+ __oh323_update_info(c, pvt);
+ ast_mutex_unlock(&pvt->lock);
+ }
+ break;
+#ifdef VIDEO_SUPPORT
+ case AST_FRAME_VIDEO:
+ if (pvt) {
+ ast_mutex_lock(&pvt->lock);
+ if (pvt->vrtp && pvt->rtp_tx_enabled) {
+ res = ast_rtp_write(pvt->vrtp, frame);
+ }
+ else if (h323debug)
+ ast_log(LOG_DEBUG, "VRTP TX is disabled for %s\n", c->name);
+ __oh323_update_info(c, pvt);
+ ast_mutex_unlock(&pvt->lock);
+ }
+ break;
+#endif
+ default:
+ ast_log(LOG_WARNING, "Can't send %d type frames with H.323 write\n", frame->frametype);
+ break;
+ }
+
return res;
}
@@ -639,7 +758,7 @@
ast_mutex_unlock(&pvt->lock);
if (h323debug)
- ast_log(LOG_DEBUG, "OH323: Indicating %d on %s\n", condition, token);
+ ast_log(LOG_DEBUG, "OH323: Indicating %d on %s, native format=%d, read format=%d, write format=%d\n", condition, token, c->nativeformats, c->readformat, c->writeformat);
switch(condition) {
case AST_CONTROL_RINGING:
@@ -735,15 +854,28 @@
ast_mutex_lock(&pvt->lock);
if (ch) {
ch->tech = &oh323_tech;
- snprintf(ch->name, sizeof(ch->name), "H323/%s", host);
- ch->nativeformats = pvt->options.capability;
- if (!ch->nativeformats) {
- ch->nativeformats = global_options.capability;
- }
+ ast_string_field_build(ch, name, "H323/%s", host);
+ if (!(fmt = pvt->jointcapability) && !(fmt = pvt->options.capability))
+ fmt = global_options.capability;
+ ch->nativeformats = ast_codec_choose(&pvt->options.prefs, fmt, 1)/* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/;
pvt->nativeformats = ch->nativeformats;
fmt = ast_best_codec(ch->nativeformats);
+#if 0
ch->type = type;
+#endif
ch->fds[0] = ast_rtp_fd(pvt->rtp);
+ ch->fds[1] = ast_rtcp_fd(pvt->rtp);
+#ifdef VIDEO_SUPPORT
+ if (pvt->vrtp) {
+ ch->fds[2] = ast_rtp_fd(pvt->vrtp);
+ ch->fds[3] = ast_rtcp_fd(pvt->vrtp);
+ }
+#endif
+#ifdef T38_SUPPORT
+ if (pvt->udptl) {
+ ch->fds[4] = ast_udptl_fd(pvt->udptl);
+ }
+#endif
if (state == AST_STATE_RING) {
ch->rings = 1;
}
@@ -765,7 +897,7 @@
strncpy(ch->exten, pvt->exten, sizeof(ch->exten) - 1);
ch->priority = 1;
if (!ast_strlen_zero(pvt->accountcode)) {
- strncpy(ch->accountcode, pvt->accountcode, sizeof(ch->accountcode) - 1);
+ ast_string_field_set(ch, accountcode, pvt->accountcode);
}
if (pvt->amaflags) {
ch->amaflags = pvt->amaflags;
@@ -810,13 +942,29 @@
return NULL;
}
memset(pvt, 0, sizeof(struct oh323_pvt));
+ memset(&pvt->rtp_tx_addr, 0xff, sizeof(pvt->rtp_tx_addr));
pvt->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0,bindaddr.sin_addr);
+#ifdef VIDEO_SUPPORT
+ memset(&pvt->vrtp_tx_addr, 0xff, sizeof(pvt->vrtp_tx_addr));
+ pvt->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
+#endif
+#ifdef T38_SUPPORT
+ pvt->udptl = ast_udptl_new_with_bindaddr(sched, io, 9, bindaddr.sin_addr);
+#endif
if (!pvt->rtp) {
ast_log(LOG_WARNING, "Unable to create RTP session: %s\n", strerror(errno));
free(pvt);
return NULL;
}
ast_rtp_settos(pvt->rtp, tos);
+#ifdef VIDEO_SUPPORT
+ if (pvt->vrtp)
+ ast_rtp_settos(pvt->vrtp, tos);
+#endif
+#ifdef T38_SUPPORT
+ if (pvt->udptl)
+ ast_udptl_settos(pvt->udptl, tos);
+#endif
ast_mutex_init(&pvt->lock);
/* Ensure the call token is allocated */
if ((pvt->cd).call_token == NULL) {
@@ -829,6 +977,7 @@
memset((char *)(pvt->cd).call_token, 0, 128);
pvt->cd.call_reference = callid;
memcpy(&pvt->options, &global_options, sizeof(pvt->options));
+ pvt->jointcapability = pvt->options.capability;
if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
pvt->nonCodecCapability |= AST_RTP_DTMF;
} else {
@@ -969,10 +1118,23 @@
if (p) {
found++;
memcpy(&pvt->options, &p->options, sizeof(pvt->options));
+ pvt->jointcapability = pvt->options.capability;
if (pvt->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
ast_rtp_setnat(pvt->rtp, pvt->options.nat);
}
+#ifdef VIDEO_SUPPORT
+ if (pvt->vrtp) {
+ ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", pvt->options.nat);
+ ast_rtp_setnat(pvt->vrtp, pvt->options.nat);
+ }
+#endif
+#ifdef T38_SUPPORT
+ if (pvt->udptl) {
+ ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %d\n", pvt->options.nat);
+ ast_udptl_setnat(pvt->udptl, pvt->options.nat);
+ }
+#endif
if (pvt->options.dtmfmode) {
if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
pvt->nonCodecCapability |= AST_RTP_DTMF;
@@ -996,6 +1158,7 @@
hp = ast_gethostbyname(hostn, &ahp);
if (hp) {
memcpy(&pvt->options, &global_options, sizeof(pvt->options));
+ pvt->jointcapability = pvt->options.capability;
memcpy(&pvt->sa.sin_addr, hp->h_addr, sizeof(pvt->sa.sin_addr));
pvt->sa.sin_port = htons(portno);
return 0;
@@ -1057,10 +1220,23 @@
}
else {
memcpy(&pvt->options, &global_options, sizeof(pvt->options));
+ pvt->jointcapability = pvt->options.capability;
if (pvt->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", pvt->options.nat);
ast_rtp_setnat(pvt->rtp, pvt->options.nat);
}
+#ifdef VIDEO_SUPPORT
+ if (pvt->vrtp) {
+ ast_log(LOG_DEBUG, "Setting NAT on VRTP to %d\n", pvt->options.nat);
+ ast_rtp_setnat(pvt->vrtp, pvt->options.nat);
+ }
+#endif
+#ifdef T38_SUPPORT
+ if (pvt->udptl) {
+ ast_log(LOG_DEBUG, "Setting NAT on UDPTL to %d\n", pvt->options.nat);
+ ast_udptl_setnat(pvt->udptl, pvt->options.nat);
+ }
+#endif
if (pvt->options.dtmfmode) {
if (pvt->options.dtmfmode & H323_DTMF_RFC2833) {
pvt->nonCodecCapability |= AST_RTP_DTMF;
@@ -1077,6 +1253,7 @@
ast_mutex_unlock(&caplock);
ast_mutex_lock(&pvt->lock);
+ pvt->pref_codec = format;
tmpc = __oh323_new(pvt, AST_STATE_DOWN, tmp1);
ast_mutex_unlock(&pvt->lock);
if (!tmpc) {
@@ -1137,11 +1314,12 @@
*
* Returns the local RTP information
*/
-struct rtp_info *external_rtp_create(unsigned call_reference, const char * token)
+struct rtp_info *external_rtp_create(unsigned call_reference, const char * token, int datatype)
{
struct oh323_pvt *pvt;
struct sockaddr_in us;
struct rtp_info *info;
+ struct ast_rtp *rtp;
info = (struct rtp_info *)malloc(sizeof(struct rtp_info));
if (!info) {
@@ -1155,7 +1333,21 @@
return NULL;
}
/* figure out our local RTP port and tell the H.323 stack about it */
- ast_rtp_get_us(pvt->rtp, &us);
+ rtp = (struct ast_rtp *)NULL;
+ switch(datatype) {
+ case 1:
+ rtp = pvt->rtp;
+ break;
+ case 2:
+ rtp = pvt->vrtp;
+ break;
+ }
+ if (!rtp) {
+ free(info);
+ ast_log(LOG_ERROR, "RTP information for call %s(%d) isn't available for datatype %d\n", token, call_reference, datatype);
+ return NULL;
+ }
+ ast_rtp_get_us(rtp, &us);
ast_mutex_unlock(&pvt->lock);
ast_inet_ntoa(info->addr, sizeof(info->addr), us.sin_addr);
@@ -1178,11 +1370,12 @@
*
* Returns nothing
*/
-void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt)
+void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int pt, int direction, int bridging_enabled, int datatype)
{
struct oh323_pvt *pvt;
struct sockaddr_in them;
struct rtpPayloadType rtptype;
+ struct ast_rtp *rtp;
if (h323debug)
ast_log(LOG_DEBUG, "Setting up RTP connection for %s\n", token);
@@ -1190,42 +1383,145 @@
/* Find the call or allocate a private structure if call not found */
pvt = find_call_locked(call_reference, token);
if (!pvt) {
- ast_log(LOG_ERROR, "Something is wrong: rtp\n");
+ ast_log(LOG_ERROR, "Something is wrong: cannot find call %s(%d) for RTP information\n", token, call_reference);
return;
}
if (pvt->alreadygone) {
ast_mutex_unlock(&pvt->lock);
return;
}
- rtptype = ast_rtp_lookup_pt(pvt->rtp, pt);
- pvt->nativeformats = rtptype.code;
- if (pvt->owner && !ast_mutex_trylock(&pvt->owner->lock)) {
- pvt->owner->nativeformats = pvt->nativeformats;
- ast_set_read_format(pvt->owner, pvt->owner->readformat);
- ast_set_write_format(pvt->owner, pvt->owner->writeformat);
- if (pvt->options.progress_audio)
- ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
- ast_mutex_unlock(&pvt->owner->lock);
- }
- else {
- if (pvt->options.progress_audio)
- pvt->newcontrol = AST_CONTROL_PROGRESS;
+ switch(datatype) {
+ case 1:
+ rtp = pvt->rtp;
+ break;
+ case 2:
+ rtp = pvt->vrtp;
+ break;
+ }
+ if (!rtp) {
+ ast_log(LOG_ERROR, "No RTP info for call %s(%d) available for datatype %d\n", token, call_reference, datatype);
+ return;
+ }
+ ast_rtp_set_m_type(rtp, pt);
+ rtptype = ast_rtp_lookup_pt(rtp, pt);
+ if (rtp == pvt->rtp) {
+ pvt->nativeformats = rtptype.code;
if (h323debug)
- ast_log(LOG_DEBUG, "RTP connection preparation for %s is pending...\n", token);
- }
-
+ ast_log(LOG_DEBUG, "RTP payload is %d, codec is %d\n", pt, pvt->nativeformats);
+ if (pvt->owner && !ast_mutex_trylock(&pvt->owner->lock)) {
+ pvt->owner->nativeformats = pvt->nativeformats;
+ ast_set_read_format(pvt->owner, pvt->owner->readformat);
+ ast_set_write_format(pvt->owner, pvt->owner->writeformat);
+ if (pvt->options.progress_audio)
+ ast_queue_control(pvt->owner, AST_CONTROL_PROGRESS);
+ else {
+ /* Kick Asterisk core to process bridging */
+ ast_queue_frame(pvt->owner, &ast_null_frame);
+ }
+ ast_mutex_unlock(&pvt->owner->lock);
+ }
+ else {
+ if (pvt->options.progress_audio)
+ pvt->newcontrol = AST_CONTROL_PROGRESS;
+ if (h323debug)
+ ast_log(LOG_DEBUG, "RTP connection preparation for %s is pending...\n", token);
+ }
+ }
+
+ if (direction) {
+ if (!bridging_enabled) {
+ if (h323debug)
+ ast_log(LOG_DEBUG, "Enabling RTP TX for %s\n", token);
+ switch(datatype) {
+ case 1:
+ pvt->rtp_tx_enabled = 1;
+ break;
+ case 2:
+ pvt->vrtp_tx_enabled = 1;
+ break;
+ }
+ } else {
+ if (h323debug)
+ ast_log(LOG_DEBUG, "RTP TX for %s is disabled while in native bridge mode\n", token);
+ switch(datatype) {
+ case 1:
+ pvt->rtp_tx_enabled = 0;
+ break;
+ case 2:
+ pvt->vrtp_tx_enabled = 0;
+ break;
+ }
+ }
+ }
+
them.sin_family = AF_INET;
/* only works for IPv4 */
- them.sin_addr.s_addr = inet_addr(remoteIp);
+ them.sin_addr.s_addr = inet_addr(remoteIp);
them.sin_port = htons(remotePort);
- ast_rtp_set_peer(pvt->rtp, &them);
-
+
+ /* Update peer address with information from TX direction only */
+ if (direction) {
+ if (!them.sin_addr.s_addr && !them.sin_port) {
+ switch(datatype) {
+ case 1:
+ memcpy(&them, &pvt->rtp_tx_addr, sizeof(them));
+ break;
+ case 2:
+ memcpy(&them, &pvt->vrtp_tx_addr, sizeof(them));
+ break;
+ }
+ }
+ ast_rtp_set_peer(rtp, &them);
+ }
+ switch(datatype) {
+ case 1:
+ memcpy(&pvt->rtp_tx_addr, &them, sizeof(them));
+ break;
+ case 2:
+ memcpy(&pvt->vrtp_tx_addr, &them, sizeof(them));
+ break;
+ }
ast_mutex_unlock(&pvt->lock);
if (h323debug)
ast_log(LOG_DEBUG, "RTP connection prepared for %s\n", token);
return;
+}
+
+void shutdown_rtp_connection(unsigned call_reference, const char *token, int direction, int datatype)
+{
+ struct oh323_pvt *pvt;
+
+ if (h323debug)
+ ast_log(LOG_DEBUG, "Shutting down RTP connection for %s\n", token);
+
+ /* Find the call or allocate a private structure if call not found */
+ pvt = find_call_locked(call_reference, token);
+ if (!pvt) {
+ ast_log(LOG_ERROR, "Something is wrong: Cannot find connection %s(%d) for RTP shutdown of datatype %d\n", token, call_reference, datatype);
+ return;
+ }
+ if (pvt->alreadygone) {
+ ast_mutex_unlock(&pvt->lock);
+ return;
+ }
+ if (direction) {
+ if (h323debug)
+ ast_log(LOG_DEBUG, "Stopping RTP TX for %s\n", token);
+ switch(datatype) {
+ case 1:
+ pvt->rtp_tx_enabled = 0;
+ memset(&pvt->rtp_tx_addr, 0xff, sizeof(pvt->rtp_tx_addr));
+ break;
+ case 2:
+ pvt->vrtp_tx_enabled = 0;
+ memset(&pvt->vrtp_tx_addr, 0xff, sizeof(pvt->vrtp_tx_addr));
+ break;
+ }
+ }
+
+ ast_mutex_unlock(&pvt->lock);
}
/**
@@ -1234,7 +1530,6 @@
*/
void connection_made(unsigned call_reference, const char *token)
{
- struct ast_channel *c = NULL;
struct oh323_pvt *pvt;
if (h323debug)
@@ -1306,6 +1601,7 @@
/* Populate the call details in the private structure */
memcpy(&pvt->cd, cd, sizeof(pvt->cd));
memcpy(&pvt->options, &global_options, sizeof(pvt->options));
+ pvt->jointcapability = pvt->options.capability;
if (h323debug) {
ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n");
@@ -1314,6 +1610,7 @@
ast_verbose(VERBOSE_PREFIX_3 "\tCalling party number: [%s]\n", pvt->cd.call_source_e164);
ast_verbose(VERBOSE_PREFIX_3 "\tCalled party name: [%s]\n", pvt->cd.call_dest_alias);
ast_verbose(VERBOSE_PREFIX_3 "\tCalled party number: [%s]\n", pvt->cd.call_dest_e164);
+ ast_verbose(VERBOSE_PREFIX_3 "\tCalling party IP: [%s]\n", pvt->cd.sourceIp);
}
/* Decide if we are allowing Gatekeeper routed calls*/
@@ -1341,7 +1638,7 @@
strncpy(pvt->exten, cd->call_dest_alias, sizeof(pvt->exten) - 1);
}
if (ast_strlen_zero(default_context)) {
- ast_log(LOG_ERROR, "Call from '%s' rejected due to no default context\n", pvt->cd.call_source_aliases);
+ ast_log(LOG_ERROR, "Call from '%s'@%s rejected due to no default context\n", pvt->cd.call_source_aliases, pvt->cd.sourceIp);
return NULL;
}
strncpy(pvt->context, default_context, sizeof(pvt->context) - 1);
@@ -1370,6 +1667,7 @@
}
strncpy(pvt->context, user->context, sizeof(pvt->context) - 1);
memcpy(&pvt->options, &user->options, sizeof(pvt->options));
+ pvt->jointcapability = pvt->options.capability;
if (!ast_strlen_zero(pvt->cd.call_dest_e164)) {
strncpy(pvt->exten, cd->call_dest_e164, sizeof(pvt->exten) - 1);
} else {
@@ -1436,7 +1734,6 @@
*/
void chan_ringing(unsigned call_reference, const char *token)
{
- struct ast_channel *c = NULL;
struct oh323_pvt *pvt;
if (h323debug)
@@ -1479,7 +1776,7 @@
break;
#if 1
#ifdef DEBUG_THREADS
- ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s, locked at %ld/%d by %s (%s:%d)\n", call_token, pvt->owner->lock.thread, pvt->owner->lock.reentrancy, pvt->owner->lock.func, pvt->owner->lock.file, pvt->owner->lock.lineno);
+ ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s, locked at %ld/%d by %s (%s:%d)\n", call_token, pvt->owner->lock.thread[0], pvt->owner->lock.reentrancy, pvt->owner->lock.func[0], pvt->owner->lock.file[0], pvt->owner->lock.lineno[0]);
#else
ast_log(LOG_NOTICE, "Avoiding H.323 destory deadlock on %s\n", call_token);
#endif
@@ -1554,21 +1851,39 @@
ast_log(LOG_DEBUG, "DTMF payload on %s set to %d\n", token, payload);
}
-static void set_local_capabilities(unsigned call_reference, const char *token)
+static void set_peer_capabilities(unsigned call_reference, const char *token, int capabilities)
{
struct oh323_pvt *pvt;
- int capability, dtmfmode;
if (h323debug)
- ast_log(LOG_DEBUG, "Setting capabilities for connection %s\n", token);
+ ast_log(LOG_DEBUG, "Got remote capabilities for connection %s\n", token);
pvt = find_call_locked(call_reference, token);
if (!pvt)
return;
- capability = pvt->options.capability;
+ pvt->peercapability = capabilities;
+ pvt->jointcapability = pvt->options.capability & capabilities;
+ ast_mutex_unlock(&pvt->lock);
+}
+
+static void set_local_capabilities(unsigned call_reference, const char *token)
+{
+ struct oh323_pvt *pvt;
+ int capability, dtmfmode, pref_codec;
+ struct ast_codec_pref prefs;
+
+ if (h323debug)
+ ast_log(LOG_DEBUG, "Setting capabilities for connection %s\n", token);
+
+ pvt = find_call_locked(call_reference, token);
+ if (!pvt)
+ return;
+ capability = (pvt->jointcapability) ? pvt->jointcapability : pvt->options.capability;
dtmfmode = pvt->options.dtmfmode;
+ prefs = pvt->options.prefs;
+ pref_codec = pvt->pref_codec;
ast_mutex_unlock(&pvt->lock);
- h323_set_capabilities(token, capability, dtmfmode);
+ h323_set_capabilities(token, capability, dtmfmode, &prefs, pref_codec);
if (h323debug)
ast_log(LOG_DEBUG, "Capabilities for connection %s is set\n", token);
@@ -1791,21 +2106,12 @@
static int update_common_options(struct ast_variable *v, struct call_options *options)
{
- unsigned int format;
int tmp;
if (!strcasecmp(v->name, "allow")) {
- format = ast_getformatbyname(v->value);
- if (format < 1)
- ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
- else
- options->capability |= format;
+ ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 1);
} else if (!strcasecmp(v->name, "disallow")) {
- format = ast_getformatbyname(v->value);
- if (format < 1)
- ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
- else
- options->capability &= ~format;
+ ast_parse_allow_disallow(&options->prefs, &options->capability, v->value, 0);
} else if (!strcasecmp(v->name, "dtmfmode")) {
if (!strcasecmp(v->value, "inband")) {
options->dtmfmode = H323_DTMF_INBAND;
@@ -2026,7 +2332,7 @@
memset(&global_options, 0, sizeof(global_options));
global_options.dtmfcodec = 101;
global_options.dtmfmode = H323_DTMF_RFC2833;
- global_options.capability = ~0; /* All capabilities */
+ global_options.capability = GLOBAL_CAPABILITY; /* All capabilities */
global_options.bridge = 1; /* Do native bridging by default */
v = ast_variable_browse(cfg, "general");
while(v) {
@@ -2246,7 +2552,7 @@
{
struct oh323_pvt *pvt;
pvt = (struct oh323_pvt *) chan->tech_pvt;
- if (pvt && pvt->rtp && pvt->options.bridge) {
+ if (pvt && pvt->rtp && pvt->options.bridge && h323_bridge_capable(pvt->cd.call_token)) {
return pvt->rtp;
}
return NULL;
@@ -2257,6 +2563,7 @@
return NULL;
}
+#if 0
static char *convertcap(int cap)
{
switch (cap) {
@@ -2281,38 +2588,202 @@
return NULL;
}
}
-
-static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs)
+#endif
+
+static int oh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
{
/* XXX Deal with Video */
struct oh323_pvt *pvt;
struct sockaddr_in them;
- struct sockaddr_in us;
- char *mode;
- char iabuf[INET_ADDRSTRLEN];
+// char iabuf[INET_ADDRSTRLEN];
if (!rtp) {
return 0;
}
- mode = convertcap(chan->writeformat);
pvt = (struct oh323_pvt *) chan->tech_pvt;
if (!pvt) {
ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
return -1;
}
- ast_rtp_get_peer(rtp, &them);
- ast_rtp_get_us(rtp, &us);
- h323_native_bridge(pvt->cd.call_token, ast_inet_ntoa(iabuf, sizeof(iabuf), them.sin_addr), mode);
- return 0;
+ if (rtp)
+ ast_rtp_get_peer(rtp, &them);
+ else
+ memset(&them, 0, sizeof(them));
+ if (h323debug) {
+ char s1[1024];
+ char s2[1024];
+ char s3[1024];
+ ast_log(LOG_DEBUG, "H.323 bridge capabilities is %s, peer is %s, joint is %s\n",
+ ast_getformatname_multiple(s1, sizeof(s1), codecs),
+ ast_getformatname_multiple(s2, sizeof(s3), pvt->peercapability),
+ ast_getformatname_multiple(s3, sizeof(s3), pvt->jointcapability));
+ }
+ return h323_native_bridge(pvt->cd.call_token, them, codecs & pvt->jointcapability);
+}
+
+static int oh323_get_codec(struct ast_channel *chan)
+{
+ struct oh323_pvt *pvt = chan->tech_pvt;
+ int capability;
+ if (!pvt)
+ return 0;
+ capability = pvt->peercapability ? pvt->peercapability : pvt->jointcapability;
+ if (h323debug) {
+ char s1[1024];
+ char s2[1024];
+ ast_log(LOG_DEBUG, "H.323 peer capabilities is %s, joint capabilities is %s\n",
+ ast_getformatname_multiple(s1, sizeof(s1), pvt->peercapability),
+ ast_getformatname_multiple(s2, sizeof(s2), pvt->jointcapability));
+ }
+ return capability;
}
static struct ast_rtp_protocol oh323_rtp = {
- .type = type,
+ .type = "H323",
.get_rtp_info = oh323_get_rtp_peer,
.get_vrtp_info = oh323_get_vrtp_peer,
- .set_rtp_peer= oh323_set_rtp_peer,
+ .set_rtp_peer = oh323_set_rtp_peer,
+ .get_codec = oh323_get_codec,
};
+
+#ifdef T38_SUPPORT
+static struct ast_udptl *oh323_get_udptl_peer(struct ast_channel *chan)
+{
+ struct oh323_pvt *pvt;
+ struct ast_udptl *udptl = NULL;
+
+ pvt = chan->tech_pvt;
+ if (!pvt)
+ return NULL;
+
+ ast_mutex_lock(&pvt->lock);
+ if (pvt->udptl)
+ udptl = pvt->udptl;
+ ast_mutex_unlock(&pvt->lock);
+ return udptl;
+}
+
+static int oh323_set_udptl_peer(struct ast_channel *chan, struct ast_udptl *udptl)
+{
+ struct oh323_pvt *pvt;
+
+ pvt = chan->tech_pvt;
+ if (!pvt)
+ return -1;
+
+ ast_mutex_lock(&pvt->lock);
+ if (udptl)
+ ast_udptl_get_peer(udptl, &pvt->udptlredirip);
+ else
+ memset(&pvt->udptlredirip, 0, sizeof(pvt->udptlredirip));
+
+ /* Switch UDPTL to different source here */
+
+ return -1;
+}
+
+static struct ast_udptl_protocol oh323_udptl = {
+ type: "H.323",
+ get_udptl_info: oh323_get_udptl_peer,
+ set_udptl_peer: oh323_set_udptl_peer,
+};
+#endif
+
+struct rtp_info *external_udptl_create(unsigned call_reference, const char * token)
+{
+ struct oh323_pvt *pvt;
+ struct sockaddr_in us;
+ struct rtp_info *info;
+
+ info = (struct rtp_info *)malloc(sizeof(struct rtp_info));
+ if (!info) {
+ ast_log(LOG_ERROR, "Unable to allocated info structure, this is very bad\n");
+ return NULL;
+ }
+ pvt = find_call_locked(call_reference, token);
+ if (!pvt) {
+ free(info);
+ ast_log(LOG_ERROR, "Unable to find call %s(%d)\n", token, call_reference);
+ return NULL;
+ }
+ /* figure out our local RTP port and tell the H.323 stack about it */
+ ast_udptl_get_us(pvt->udptl, &us);
+ ast_mutex_unlock(&pvt->lock);
+
+ ast_inet_ntoa(info->addr, sizeof(info->addr), us.sin_addr);
+ info->port = ntohs(us.sin_port);
+ if (h323debug)
+ ast_log(LOG_DEBUG, "Sending UDPTL 'US' %s:%d\n", info->addr, info->port);
+ return info;
+}
+
+void setup_udptl_connection(unsigned call_reference, const char *remoteIp, int remotePort, const char *token, int direction)
+{
+ struct oh323_pvt *pvt;
+ struct sockaddr_in them;
+
+ if (h323debug)
+ ast_log(LOG_DEBUG, "Setting up UDPTL connection for %s\n", token);
+
+ /* Find the call or allocate a private structure if call not found */
+ pvt = find_call_locked(call_reference, token);
+ if (!pvt) {
+ ast_log(LOG_ERROR, "Something is wrong: udptl\n");
+ return;
+ }
+ if (pvt->alreadygone) {
+ ast_mutex_unlock(&pvt->lock);
+ return;
+ }
+
+ them.sin_family = AF_INET;
+ /* only works for IPv4 */
+ them.sin_addr.s_addr = inet_addr(remoteIp);
+ them.sin_port = htons(remotePort);
+
+ /* Update peer address with information from TX direction only */
+ if (direction) {
+// if (!them.sin_addr.s_addr && !them.sin_port)
[... 4619 lines stripped ...]
More information about the svn-commits
mailing list