aboutsummaryrefslogtreecommitdiffstats
path: root/addons/ooh323cDriver.c
diff options
context:
space:
mode:
Diffstat (limited to 'addons/ooh323cDriver.c')
-rw-r--r--addons/ooh323cDriver.c400
1 files changed, 375 insertions, 25 deletions
diff --git a/addons/ooh323cDriver.c b/addons/ooh323cDriver.c
index 5d7396abf..170132690 100644
--- a/addons/ooh323cDriver.c
+++ b/addons/ooh323cDriver.c
@@ -16,22 +16,53 @@
#include "ooh323cDriver.h"
+#include <asterisk.h>
+#include <asterisk/lock.h>
+
#include <asterisk/pbx.h>
#include <asterisk/logger.h>
-#include <asterisk/options.h>
+#undef AST_BACKGROUND_STACKSIZE
+#define AST_BACKGROUND_STACKSIZE 768 * 1024
+
+#define SEC_TO_HOLD_THREAD 24
+
+extern struct ast_module *myself;
extern OOBOOL gH323Debug;
+extern OOH323EndPoint gH323ep;
/* ooh323c stack thread. */
static pthread_t ooh323c_thread = AST_PTHREADT_NULL;
+static pthread_t ooh323cmd_thread = AST_PTHREADT_NULL;
static int grxframes = 240;
static int gtxframes = 20;
+static struct callthread {
+ ast_mutex_t lock;
+ int thePipe[2];
+ OOBOOL inUse;
+ ooCallData* call;
+ struct callthread *next, *prev;
+} *callThreads = NULL;
+
+AST_MUTEX_DEFINE_STATIC(callThreadsLock);
+
+
int ooh323c_start_receive_channel(ooCallData *call, ooLogicalChannel *pChannel);
int ooh323c_start_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel);
int ooh323c_stop_receive_channel(ooCallData *call, ooLogicalChannel *pChannel);
int ooh323c_stop_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel);
+int ooh323c_start_receive_datachannel(ooCallData *call, ooLogicalChannel *pChannel);
+int ooh323c_start_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChannel);
+int ooh323c_stop_receive_datachannel(ooCallData *call, ooLogicalChannel *pChannel);
+int ooh323c_stop_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChannel);
+
+void* ooh323c_stack_thread(void* dummy);
+void* ooh323c_cmd_thread(void* dummy);
+void* ooh323c_call_thread(void* dummy);
+int ooh323c_set_aliases(ooAliases * aliases);
+
void* ooh323c_stack_thread(void* dummy)
{
@@ -39,13 +70,145 @@ void* ooh323c_stack_thread(void* dummy)
return dummy;
}
+void* ooh323c_cmd_thread(void* dummy)
+{
+
+ ooMonitorCmdChannels();
+ return dummy;
+}
+
+void* ooh323c_call_thread(void* dummy)
+{
+ struct callthread* mycthread = (struct callthread *)dummy;
+ struct pollfd pfds[1];
+ char c;
+ int res;
+
+ do {
+
+ ooMonitorCallChannels((ooCallData*)mycthread->call);
+ mycthread->call = NULL;
+ mycthread->prev = NULL;
+ mycthread->inUse = FALSE;
+
+ ast_mutex_lock(&callThreadsLock);
+ mycthread->next = callThreads;
+ callThreads = mycthread;
+ if (mycthread->next) mycthread->next->prev = mycthread;
+ ast_mutex_unlock(&callThreadsLock);
+
+ pfds[0].fd = mycthread->thePipe[0];
+ pfds[0].events = POLLIN;
+ ooSocketPoll(pfds, 1, SEC_TO_HOLD_THREAD * 1000);
+ if (ooPDRead(pfds, 1, mycthread->thePipe[0]))
+ res = read(mycthread->thePipe[0], &c, 1);
+
+ ast_mutex_lock(&callThreadsLock);
+ ast_mutex_lock(&mycthread->lock);
+ if (mycthread->prev)
+ mycthread->prev->next = mycthread->next;
+ else
+ callThreads = mycthread->next;
+ if (mycthread->next)
+ mycthread->next->prev = mycthread->prev;
+ ast_mutex_unlock(&mycthread->lock);
+ ast_mutex_unlock(&callThreadsLock);
+
+ } while (mycthread->call != NULL);
+
+
+ ast_mutex_destroy(&mycthread->lock);
+
+ close(mycthread->thePipe[0]);
+ close(mycthread->thePipe[1]);
+ free(mycthread);
+ ast_module_unref(myself);
+ ast_update_use_count();
+ return dummy;
+}
+
+int ooh323c_start_call_thread(ooCallData *call) {
+ char c = 'c';
+ int res;
+ struct callthread *cur = callThreads;
+
+ ast_mutex_lock(&callThreadsLock);
+ while (cur != NULL && (cur->inUse || ast_mutex_trylock(&cur->lock))) {
+ cur = cur->next;
+ }
+ ast_mutex_unlock(&callThreadsLock);
+
+ if (cur != NULL && cur->inUse) {
+ ast_mutex_unlock(&cur->lock);
+ cur = NULL;
+ }
+
+/* make new thread */
+ if (cur == NULL) {
+ if (!(cur = ast_malloc(sizeof(struct callthread)))) {
+ ast_log(LOG_ERROR, "Unable to allocate thread structure for call %s\n",
+ call->callToken);
+ return -1;
+ }
+
+ ast_module_ref(myself);
+ memset(cur, 0, sizeof(cur));
+ if ((socketpair(PF_LOCAL, SOCK_STREAM, 0, cur->thePipe)) == -1) {
+ ast_log(LOG_ERROR, "Can't create thread pipe for call %s\n", call->callToken);
+ free(cur);
+ return -1;
+ }
+ cur->inUse = TRUE;
+ cur->call = call;
+
+ ast_mutex_init(&cur->lock);
+
+ if (gH323Debug)
+ ast_debug(1,"new call thread created for call %s\n", call->callToken);
+
+ if(ast_pthread_create_detached_background(&call->callThread, NULL, ooh323c_call_thread, cur) < 0)
+ {
+ ast_log(LOG_ERROR, "Unable to start ooh323c call thread for call %s\n",
+ call->callToken);
+ ast_mutex_destroy(&cur->lock);
+ close(cur->thePipe[0]);
+ close(cur->thePipe[1]);
+ free(cur);
+ return -1;
+ }
+
+ } else {
+ if (gH323Debug)
+ ast_debug(1,"using existing call thread for call %s\n", call->callToken);
+ cur->inUse = TRUE;
+ cur->call = call;
+ res = write(cur->thePipe[1], &c, 1);
+ ast_mutex_unlock(&cur->lock);
+
+ }
+ return 0;
+}
+
+
+int ooh323c_stop_call_thread(ooCallData *call) {
+ if (call->callThread != AST_PTHREADT_NULL) {
+ ooStopMonitorCallChannels(call);
+ }
+ return 0;
+}
+
int ooh323c_start_stack_thread()
{
- if(ast_pthread_create(&ooh323c_thread, NULL, ooh323c_stack_thread, NULL) < 0)
+ if(ast_pthread_create_background(&ooh323c_thread, NULL, ooh323c_stack_thread, NULL) < 0)
{
ast_log(LOG_ERROR, "Unable to start ooh323c thread.\n");
return -1;
}
+ if(ast_pthread_create_background(&ooh323cmd_thread, NULL, ooh323c_cmd_thread, NULL) < 0)
+ {
+ ast_log(LOG_ERROR, "Unable to start ooh323cmd thread.\n");
+ return -1;
+ }
return 0;
}
@@ -56,14 +219,16 @@ int ooh323c_stop_stack_thread(void)
ooStopMonitor();
pthread_join(ooh323c_thread, NULL);
ooh323c_thread = AST_PTHREADT_NULL;
+ pthread_join(ooh323cmd_thread, NULL);
+ ooh323cmd_thread = AST_PTHREADT_NULL;
}
return 0;
}
int ooh323c_set_capability
- (struct ast_codec_pref *prefs, int capability, int dtmf)
+ (struct ast_codec_pref *prefs, int capability, int dtmf, int dtmfcodec)
{
- int ret, x, format=0;
+ int ret = 0, x, format=0;
if(gH323Debug)
ast_verbose("\tAdding capabilities to H323 endpoint\n");
@@ -107,13 +272,44 @@ int ooh323c_set_capability
&ooh323c_start_transmit_channel,
&ooh323c_stop_receive_channel,
&ooh323c_stop_transmit_channel);
+ if(gH323Debug)
+ ast_verbose("\tAdding g729b capability to H323 endpoint\n");
+ ret |= ooH323EpAddG729Capability(OO_G729B, 2, 24,
+ OORXANDTX, &ooh323c_start_receive_channel,
+ &ooh323c_start_transmit_channel,
+ &ooh323c_stop_receive_channel,
+ &ooh323c_stop_transmit_channel);
}
if(format & AST_FORMAT_G723_1)
{
if(gH323Debug)
ast_verbose("\tAdding g7231 capability to H323 endpoint\n");
- ret = ooH323EpAddG7231Capability(OO_G7231, 4, 7, FALSE,
+ ret = ooH323EpAddG7231Capability(OO_G7231, 1, 1, FALSE,
+ OORXANDTX, &ooh323c_start_receive_channel,
+ &ooh323c_start_transmit_channel,
+ &ooh323c_stop_receive_channel,
+ &ooh323c_stop_transmit_channel);
+
+ }
+
+ if(format & AST_FORMAT_G726)
+ {
+ if(gH323Debug)
+ ast_verbose("\tAdding g726 capability to H323 endpoint\n");
+ ret = ooH323EpAddG726Capability(OO_G726, gtxframes, grxframes, FALSE,
+ OORXANDTX, &ooh323c_start_receive_channel,
+ &ooh323c_start_transmit_channel,
+ &ooh323c_stop_receive_channel,
+ &ooh323c_stop_transmit_channel);
+
+ }
+
+ if(format & AST_FORMAT_G726_AAL2)
+ {
+ if(gH323Debug)
+ ast_verbose("\tAdding g726aal2 capability to H323 endpoint\n");
+ ret = ooH323EpAddG726Capability(OO_G726AAL2, gtxframes, grxframes, FALSE,
OORXANDTX, &ooh323c_start_receive_channel,
&ooh323c_start_transmit_channel,
&ooh323c_stop_receive_channel,
@@ -145,8 +341,38 @@ int ooh323c_set_capability
}
+#ifdef AST_FORMAT_AMRNB
+ if(format & AST_FORMAT_AMRNB)
+ {
+ if(gH323Debug)
+ ast_verbose("\tAdding amr nb capability to H323 endpoint\n");
+ ret = ooH323EpAddAMRNBCapability(OO_AMRNB, 4, 4, FALSE,
+ OORXANDTX, &ooh323c_start_receive_channel,
+ &ooh323c_start_transmit_channel,
+ &ooh323c_stop_receive_channel,
+ &ooh323c_stop_transmit_channel);
+
+ }
+#endif
+
+#ifdef AST_FORMAT_SPEEX
+ if(format & AST_FORMAT_SPEEX)
+ {
+ if(gH323Debug)
+ ast_verbose("\tAdding speex capability to H323 endpoint\n");
+ ret = ooH323EpAddSpeexCapability(OO_SPEEX, 4, 4, FALSE,
+ OORXANDTX, &ooh323c_start_receive_channel,
+ &ooh323c_start_transmit_channel,
+ &ooh323c_stop_receive_channel,
+ &ooh323c_stop_transmit_channel);
+
+ }
+#endif
+
}
+ if(dtmf & H323_DTMF_CISCO)
+ ret |= ooH323EpEnableDTMFCISCO(0);
if(dtmf & H323_DTMF_RFC2833)
ret |= ooH323EpEnableDTMFRFC2833(0);
else if(dtmf & H323_DTMF_H245ALPHANUMERIC)
@@ -158,20 +384,30 @@ int ooh323c_set_capability
}
int ooh323c_set_capability_for_call
- (ooCallData *call, struct ast_codec_pref *prefs, int capability, int dtmf)
+ (ooCallData *call, struct ast_codec_pref *prefs, int capability, int dtmf, int dtmfcodec,
+ int t38support)
{
- int ret, x, txframes;
+ int ret = 0, x, txframes;
int format=0;
if(gH323Debug)
ast_verbose("\tAdding capabilities to call(%s, %s)\n", call->callType,
call->callToken);
- if(dtmf & H323_DTMF_RFC2833)
- ret |= ooCallEnableDTMFRFC2833(call,0);
- else if(dtmf & H323_DTMF_H245ALPHANUMERIC)
+ if(dtmf & H323_DTMF_CISCO || 1)
+ ret |= ooCallEnableDTMFCISCO(call,dtmfcodec);
+ if(dtmf & H323_DTMF_RFC2833 || 1)
+ ret |= ooCallEnableDTMFRFC2833(call,dtmfcodec);
+ if(dtmf & H323_DTMF_H245ALPHANUMERIC || 1)
ret |= ooCallEnableDTMFH245Alphanumeric(call);
- else if(dtmf & H323_DTMF_H245SIGNAL)
+ if(dtmf & H323_DTMF_H245SIGNAL || 1)
ret |= ooCallEnableDTMFH245Signal(call);
+ if (t38support)
+ ooCapabilityAddT38Capability(call, OO_T38, OORXANDTX,
+ &ooh323c_start_receive_datachannel,
+ &ooh323c_start_transmit_datachannel,
+ &ooh323c_stop_receive_datachannel,
+ &ooh323c_stop_transmit_datachannel,
+ 0);
for(x=0; 0 !=(format=ast_codec_pref_index(prefs, x)); x++)
{
@@ -182,7 +418,7 @@ int ooh323c_set_capability_for_call
call->callType, call->callToken);
txframes = prefs->framing[x];
ret= ooCallAddG711Capability(call, OO_G711ULAW64K, txframes,
- grxframes, OORXANDTX,
+ txframes, OORXANDTX,
&ooh323c_start_receive_channel,
&ooh323c_start_transmit_channel,
&ooh323c_stop_receive_channel,
@@ -195,33 +431,70 @@ int ooh323c_set_capability_for_call
call->callType, call->callToken);
txframes = prefs->framing[x];
ret= ooCallAddG711Capability(call, OO_G711ALAW64K, txframes,
- grxframes, OORXANDTX,
+ txframes, OORXANDTX,
&ooh323c_start_receive_channel,
&ooh323c_start_transmit_channel,
&ooh323c_stop_receive_channel,
&ooh323c_stop_transmit_channel);
}
+ if(format & AST_FORMAT_G726)
+ {
+ if(gH323Debug)
+ ast_verbose("\tAdding g726 capability to call (%s, %s)\n",
+ call->callType, call->callToken);
+ txframes = prefs->framing[x];
+ ret = ooCallAddG726Capability(call, OO_G726, txframes, grxframes, FALSE,
+ OORXANDTX, &ooh323c_start_receive_channel,
+ &ooh323c_start_transmit_channel,
+ &ooh323c_stop_receive_channel,
+ &ooh323c_stop_transmit_channel);
+
+ }
+
+ if(format & AST_FORMAT_G726_AAL2)
+ {
+ if(gH323Debug)
+ ast_verbose("\tAdding g726aal2 capability to call (%s, %s)\n",
+ call->callType, call->callToken);
+ txframes = prefs->framing[x];
+ ret = ooCallAddG726Capability(call, OO_G726AAL2, txframes, grxframes, FALSE,
+ OORXANDTX, &ooh323c_start_receive_channel,
+ &ooh323c_start_transmit_channel,
+ &ooh323c_stop_receive_channel,
+ &ooh323c_stop_transmit_channel);
+
+ }
+
if(format & AST_FORMAT_G729A)
{
+
+ txframes = (prefs->framing[x])/10;
+ if(gH323Debug)
+ ast_verbose("\tAdding g729 capability to call(%s, %s)\n",
+ call->callType, call->callToken);
+ ret|= ooCallAddG729Capability(call, OO_G729, txframes, txframes,
+ OORXANDTX, &ooh323c_start_receive_channel,
+ &ooh323c_start_transmit_channel,
+ &ooh323c_stop_receive_channel,
+ &ooh323c_stop_transmit_channel);
if(gH323Debug)
ast_verbose("\tAdding g729A capability to call(%s, %s)\n",
call->callType, call->callToken);
- txframes = (prefs->framing[x])/10;
- ret= ooCallAddG729Capability(call, OO_G729A, txframes, 24,
+ ret= ooCallAddG729Capability(call, OO_G729A, txframes, txframes,
OORXANDTX, &ooh323c_start_receive_channel,
&ooh323c_start_transmit_channel,
&ooh323c_stop_receive_channel,
&ooh323c_stop_transmit_channel);
-
if(gH323Debug)
- ast_verbose("\tAdding g729 capability to call(%s, %s)\n",
+ ast_verbose("\tAdding g729B capability to call(%s, %s)\n",
call->callType, call->callToken);
- ret|= ooCallAddG729Capability(call, OO_G729, txframes, 24,
+ ret|= ooCallAddG729Capability(call, OO_G729B, txframes, txframes,
OORXANDTX, &ooh323c_start_receive_channel,
&ooh323c_start_transmit_channel,
&ooh323c_stop_receive_channel,
&ooh323c_stop_transmit_channel);
+
}
if(format & AST_FORMAT_G723_1)
@@ -229,7 +502,7 @@ int ooh323c_set_capability_for_call
if(gH323Debug)
ast_verbose("\tAdding g7231 capability to call (%s, %s)\n",
call->callType, call->callToken);
- ret = ooCallAddG7231Capability(call, OO_G7231, 4, 7, FALSE,
+ ret = ooCallAddG7231Capability(call, OO_G7231, 1, 1, FALSE,
OORXANDTX, &ooh323c_start_receive_channel,
&ooh323c_start_transmit_channel,
&ooh323c_stop_receive_channel,
@@ -261,7 +534,35 @@ int ooh323c_set_capability_for_call
&ooh323c_stop_receive_channel,
&ooh323c_stop_transmit_channel);
}
+
+#ifdef AST_FORMAT_AMRNB
+ if(format & AST_FORMAT_AMRNB)
+ {
+ if(gH323Debug)
+ ast_verbose("\tAdding AMR capability to call(%s, %s)\n",
+ call->callType, call->callToken);
+ ret = ooCallAddAMRNBCapability(call, OO_AMRNB, 4, 4, FALSE,
+ OORXANDTX, &ooh323c_start_receive_channel,
+ &ooh323c_start_transmit_channel,
+ &ooh323c_stop_receive_channel,
+ &ooh323c_stop_transmit_channel);
+ }
+#endif
+#ifdef AST_FORMAT_SPEEX
+ if(format & AST_FORMAT_SPEEX)
+ {
+ if(gH323Debug)
+ ast_verbose("\tAdding Speex capability to call(%s, %s)\n",
+ call->callType, call->callToken);
+ ret = ooCallAddSpeexCapability(call, OO_SPEEX, 4, 4, FALSE,
+ OORXANDTX, &ooh323c_start_receive_channel,
+ &ooh323c_start_transmit_channel,
+ &ooh323c_stop_receive_channel,
+ &ooh323c_stop_transmit_channel);
+ }
+#endif
}
+ return ret;
}
int ooh323c_set_aliases(ooAliases * aliases)
@@ -295,9 +596,9 @@ int ooh323c_start_receive_channel(ooCallData *call, ooLogicalChannel *pChannel)
{
int fmt=-1;
fmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap);
- if(fmt>0)
- ooh323_set_read_format(call, fmt);
- else{
+ if(fmt>0) {
+ /* ooh323_set_read_format(call, fmt); */
+ }else{
ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n",
call->callToken);
return -1;
@@ -309,9 +610,19 @@ int ooh323c_start_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel)
{
int fmt=-1;
fmt = convertH323CapToAsteriskCap(pChannel->chanCap->cap);
- if(fmt>0)
- ooh323_set_write_format(call, fmt);
- else{
+ if(fmt>0) {
+ switch (fmt) {
+ case AST_FORMAT_ALAW:
+ case AST_FORMAT_ULAW:
+ ooh323_set_write_format(call, fmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes);
+ break;
+ case AST_FORMAT_G729A:
+ ooh323_set_write_format(call, fmt, ((OOCapParams *)(pChannel->chanCap->params))->txframes*10);
+ break;
+ default:
+ ooh323_set_write_format(call, fmt, 0);
+ }
+ }else{
ast_log(LOG_ERROR, "Invalid capability type for receive channel %s\n",
call->callToken);
return -1;
@@ -331,6 +642,29 @@ int ooh323c_stop_transmit_channel(ooCallData *call, ooLogicalChannel *pChannel)
return 1;
}
+
+int ooh323c_start_receive_datachannel(ooCallData *call, ooLogicalChannel *pChannel)
+{
+ return 1;
+}
+
+int ooh323c_start_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChannel)
+{
+ setup_udptl_connection(call, pChannel->remoteIP, pChannel->remoteMediaPort);
+ return 1;
+}
+
+int ooh323c_stop_receive_datachannel(ooCallData *call, ooLogicalChannel *pChannel)
+{
+ return 1;
+}
+
+int ooh323c_stop_transmit_datachannel(ooCallData *call, ooLogicalChannel *pChannel)
+{
+ close_udptl_connection(call);
+ return 1;
+}
+
int convertH323CapToAsteriskCap(int cap)
{
@@ -342,12 +676,28 @@ int convertH323CapToAsteriskCap(int cap)
return AST_FORMAT_ALAW;
case OO_GSMFULLRATE:
return AST_FORMAT_GSM;
+
+#ifdef AST_FORMAT_AMRNB
+ case OO_AMRNB:
+ return AST_FORMAT_AMRNB;
+#endif
+#ifdef AST_FORMAT_SPEEX
+ case OO_SPEEX:
+ return AST_FORMAT_SPEEX;
+#endif
+
case OO_G729:
return AST_FORMAT_G729A;
case OO_G729A:
return AST_FORMAT_G729A;
+ case OO_G729B:
+ return AST_FORMAT_G729A;
case OO_G7231:
return AST_FORMAT_G723_1;
+ case OO_G726:
+ return AST_FORMAT_G726;
+ case OO_G726AAL2:
+ return AST_FORMAT_G726_AAL2;
case OO_H263VIDEO:
return AST_FORMAT_H263;
default: