summaryrefslogtreecommitdiff
path: root/addons/ooh323cDriver.c
diff options
context:
space:
mode:
authorAlexandr Anikin <may@telecom-service.ru>2009-11-04 22:10:44 +0000
committerAlexandr Anikin <may@telecom-service.ru>2009-11-04 22:10:44 +0000
commit953031095415efa4558ca7eff29d7c85ff8efe89 (patch)
treec8a21eb3b2896c7f5b558913cb7ea914b40a06ce /addons/ooh323cDriver.c
parent317435a93200520218c4e9f4bbb8c0258f363876 (diff)
Reworked chan_ooh323 channel module.
Many architectural and functional changes. Main changes are threading model chanes (many thread in ooh323 stack instead of one), modifications and improvements in signalling part, additional codecs support (726, speex), t38 mode support. This module tested and used in production environment. (closes issue #15285) Reported by: may213 Tested by: sles, c0w, OrNix Review: https://reviewboard.asterisk.org/r/324/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@227898 65c4cc65-6c06-0410-ace0-fbb531ad65f3
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: